How to do unsigned 32 bit arithmetic in Perl? - perl

I would like to implement the following C program in Perl:
#include <stdio.h>
#include <stdint.h>
uint32_t xorshift32 ()
{
static uint32_t y = 2463534242;
y ^= y << 13;
y ^= y >> 17;
y ^= y << 5;
return y;
}
int main (int argc, char *argv[])
{
int n = 10;
while (n-- > 0)
printf ("%u\n", xorshift32());
}
The output is:
723471715
2497366906
2064144800
2008045182
3532304609
374114282
1350636274
691148861
746858951
2653896249
This is my unsuccessful attempt:
{
package Xorshift;
use strict;
use warnings;
use integer;
sub new
{
my $class = shift;
bless { y => 2463534242 } => $class
}
sub rand ()
{
my $y = $_[0]->{y};
$y ^= $y << 13;
$y ^= $y >> 17;
$y ^= $y << 5;
$_[0]->{y} = $y;
return $y;
}
}
my $xor = Xorshift->new;
my $n = 10;
while ($n-- > 0) {
print $xor->rand(), "\n";
}
The output is this:
660888219700579
3396719463693796860
-1120433007023638100
2588568168682748299
1469630995924843144
-8422345229424035168
1449080611344244726
-4722527344582589597
8061824971057606814
-3113862584906767882
The problems:
Perl uses 64 bit arithmetic.
The integers are signed.
How to do 32 bit unsigned arithmetic instead?

If you want to simulate the result of 32-bit ops, you can simply apply a mask:
{
package Xorshift;
use strict;
use warnings;
use integer;
sub new
{
my $class = shift;
bless { y => 2463534242 } => $class
}
sub to32{
return ($_[0] & 0xFFFFFFFF);
}
sub rand ()
{
my $y = $_[0]->{y};
$y ^= to32($y << 13);
$y ^= to32($y >> 17);
$y ^= to32($y << 5);
$_[0]->{y} = $y;
return $y;
}
}
my $xor = Xorshift->new;
my $n = 10;
while ($n-- > 0) {
print $xor->rand(), "\n";
}

Related

Perl subroutine not working in loop

I tried writing a simple code to find whether a number can be expressed as the sum of primes or not, in Perl. The sample code is as shown:
sub funcIsPrime {
my $num = $_[0];
my $isPrime = 1;
for($i= 2; $i <= $num/2; $i++){
if($num%$i == 0){
$isPrime = 0;
last;
}
}
return $isPrime;
}
#my $num = <>;
my $num = 20;
for($i = 2; $i <= $num/2; $i++){
print "$i\t";
my $j = $num-$i;
print "$j\n";
if(funcIsPrime($i) and funcIsPrime($j)){ # Line x
print "$num = $i + $j\n";
}
}
The function call statements in Line x do not execute. The same line when put outside the loop works fine. What can be the possible solution? Please help. Thank you.
The main issue is missing my in variable declarations. Perl won't let you run the program if you include use warnings; and use strict;:
Global symbol "$i" requires explicit package name (did you forget to declare "my $i"?) at test.pl line 22.
Execution of test.pl aborted due to compilation errors.
Here's simplified working code (you can search for factors up to the square root of n, by the way, although this isn't a perfect or efficient prime test by any means):
use strict;
use warnings;
sub isPrime {
my $num = $_[0];
for (my $i = int sqrt $num; $i > 1; $i--) {
if ($num % $i == 0) {
return 0;
}
}
return 1;
}
my $num = 20;
for (my $i = 2; $i <= $num / 2; $i++) {
my $j = $num - $i;
if (isPrime($i) && isPrime($j)) {
print "$num = $i + $j\n";
}
}
Output
20 = 3 + 17
20 = 7 + 13

Perl: pack int to arbitrary length byte string

I want to encode numbers in N bit containers and send them in a UDP packet. A receiver will know N, and the receiver will grab a number from exactly N bits.(N <= 64)
Somethink like this:
sub to56BIT {
return pack("??", shift);
}
sub to24BIT {
return pack("??", shift);
}
my $n = 7;
to24BIT($n);
On the receiver's side:
int n = Get_val24(byte_stream, offset);
Is there any way to do this in Perl?
I think solution might be:
sub packIntN {
my $int = shift;
my $length = shift;
return pack("B" . $length, substr(unpack("B64", pack("Q>", $int)), 64 - $length));
}
But maybe there is more elegant way.
Input/Output example:
We have a script test.pl:
use strict;
use warnings;
sub to24BIT {
#???
}
my $n = 7;
print to24BIT($n);
I want this:
./test.pl | hexdump -C
00000000 00 00 07 |...|
00000003
Another script test2.pl:
use strict;
use warnings;
sub to40BIT {
#???
}
my $n = 7;
print to40BIT($n);
I want this:
./test.pl | hexdump -C
00000000 00 00 00 00 07 |.....|
00000005
Is N always going to be an integer factor of 8 (one of 8, 16, 24, 32, 40, 48, 56, 64)? If so, for speed, I recommend writing a packer for each size and use a dispatch table to find the right packer.
sub pack_8bit { pack('C', $_[0]) }
sub pack_16bit { pack('S>', $_[0]) }
sub pack_24bit { substr(pack('L>', $_[0]), 1) }
sub pack_32bit { pack('L>', $_[0]) }
sub pack_40bit { substr(pack('Q>', $_[0]), 3) }
sub pack_48bit { substr(pack('Q>', $_[0]), 2) }
sub pack_56bit { substr(pack('Q>', $_[0]), 1) }
sub pack_64bit { pack('Q>', $_[0]) }
{
my %packers = (
8 => \&pack_8bit, 40 => \&pack_40bit,
16 => \&pack_16bit, 48 => \&pack_48bit,
24 => \&pack_24bit, 56 => \&pack_56bit,
32 => \&pack_32bit, 64 => \&pack_64bit,
);
sub pack_num {
my $packer = $packers{$_[0]}
or die;
return $packer->($_[1]);
}
sub get_packer {
my $packer = $packers{$_[0]}
or die;
return $packer;
}
}
my $packed = pack_num(40, 7);
-or-
my $packer = get_packer(40);
my $packed = $packer->(7);
If you're planning on packing multiple numbers into one string (like pack('L>*', #nums)), I'd also use a dispatch table like this, though I'm not sure what would be the fastest implementation of pack_24bit, pack_40bit, pack_48bit and pack_56bit (other than a C solution).
Bearing in mind that you will always have a whole
number of bytes, I ended up with
substr(pack("Q>",$n<<(64-$len)),0,($len+7)/8);
and
unpack("Q>",$s.(0 x 8)) >> (64-$len);
as tried in this example:
#!/usr/bin/perl
$len = 40;
$n = 7;
$s = substr(pack("Q>",$n<<(64-$len)),0,($len+7)/8);
open(PIPE,"| hexdump -C");
print PIPE $s;
close PIPE;
$v = unpack("Q>",$s.(0 x 8)) >> (64-$len);
printf "%d\n",$v;

Perl - Determinant of Matrix Containing Variables

I have a Perl program containing the following methods:
det To find the determinant of a matrix.
identityMatrix Return an n by n identity matrix (1s on the main diagnal, rest 0s).
matrixAdd To add two matrices together.
matrixScalarMultiply To multiply an integer by a matrix.
I can easily find the determinant of, for example, a matrix A - I where
(It is 0)
But what if I want to find the determinant of A - RI?
In this case, I want my program to solve for the characteristic polynomial solution (a.k.a. the determinant containing variables) along these lines instead of an integer value:
Any suggestions on how to handle this? Code below:
#!/usr/bin/perl
#perl Solver.pl
use strict;
use warnings;
### solve the characteristic polynomial det(A - RI)
my #A = ( # 3x3, det = -3
[1, 3, -3],
[1, 0, 0],
[0, 1, 0],
);
# test_matrix = A - I
my $test_matrix = matrixAdd( \#A,
matrixScalarMultiply( identityMatrix(3), -1 ) );
print "\nTest:\n";
for( my $i = 0; $i <= $#$test_matrix; $i++ ){
print "[";
for( my $j = 0; $j <= $#$test_matrix; $j++ ){
$j == $#$test_matrix ? print $test_matrix->[$i][$j], "]\n" :
print $test_matrix->[$i][$j], ", ";
}
}
my $dd = det ($test_matrix);
print "det = $dd \n";
# recursively find determinant of a real square matrix
# only call on n by n matrices where n >= 2
#
# arg0 = matrix reference
sub det{
my ($A) = #_;
#base: 2x2 matrix
if( $#$A + 1 == 2 ){ #recall $#$A == last index of A
return $A->[0][0]*$A->[1][1] - $A->[1][0]*$A->[0][1];
}
#cofactor expansion for matrices > 2x2
my $answer = 0;
for( my $col = 0; $col <= $#$A; $col++ ){
my $m = (); #sub matrix
my $multiplier = $A->[0][$col];
if( $col % 2 == 1 ){ #+, -, +, -, ...
$multiplier *= -1;
}
for( my $i = 1; $i <= $#$A; $i++ ){
#j is indexer for A, k for m
for( my ($j, $k) = (0, 0); $j <= $#$A; $j++ ){
$m->[$i-1][$k++] = $A->[$i][$j] unless $j == $col;
}
}
$answer += $multiplier*det( $m );
}#end cofactor expansion
return $answer;
}#end det()
# return reference to an n by n identity matrix
# can do this in Perl!
#
# arg0 = dimension 'n'
sub identityMatrix{
my $n = shift;
my #ret;
for (my $i = 0; $i < $n; $i++ ){
for (my $j = 0; $j < $n; $j++ ){
$ret[$i][$j] = $i == $j ? 1 : 0;
}
}
return \#ret;
}
# return reference to an n by n matrix which is the sum
# of two different n by n matrices, "a" and "b"
#
# arg0, 1 = references to the pair of matrices to add
sub matrixAdd{
my #ret;
my ($a, $b) = ($_[0], $_[1]);
for (my $i = 0; $i <= $#$a; $i++ ){
for (my $j = 0; $j <= $#$a; $j++ ){
$ret[$i][$j] = $a->[$i][$j] + $b->[$i][$j];
}
}
return \#ret;
}
# return reference to a matrix multiplied by a given scalar
#
# arg0 = reference to matrix
# arg1 = scalar to multiply by
sub matrixScalarMultiply{
my #ret;
my ($a, $multiplier) = ($_[0], $_[1]);
for (my $i = 0; $i <= $#$a; $i++ ){
for (my $j = 0; $j <= $#$a; $j++ ){
$ret[$i][$j] = $a->[$i][$j] * $multiplier;
}
}
return \#ret;
}
This is called symbolic math and is in the wheelhouse of tools like Mathematica. For Perl, there are packages like Math::Synbolic but I couldn't tell you how easy they are to use.
On the other hand, if you are just interested in what values of R have a determinant of zero and not that interested in what the characteristic polynomial looks like, then you are looking for the eigenvalues of A. There are some Perl libraries for that, too.

Permutations using Perl

I am trying to write a simple recursive Perl routine to generate all of the permutations of an array. I don't have any of the modules that provide routines for doing this and I can't install them either. Here is the code I have so far:
sub permute
{
my #array = #_;
if (#array == 0)
{
return;
}
else
{
my $accum = "";
my $result = permute_with_accumulator($accum, #array);
return $result;
}
}
sub permute_with_accumulator
{
my ($accum, #array) = #_;
if (#array == 1)
{
my $element = $array[0];
$accum .= "$element,";
}
else
{
my $i;
for ($i = 0; $i <= $#array; $i++)
{
$accum .= "$array[$i] ";
my #new_array = ();
if ($i == 0)
{
#new_array = #array[1..$#array];
}
elsif ($i == $#array)
{
#new_array = #array[0..$#array-1];
}
else
{
my $lower = $i - 1;
my $upper = $i + 1;
#new_array = #array[1..$lower, $upper..$#array];
}
permute_with_accumulator($accum, #new_array);
}
}
return $accum;
}
But when I do #array = qw(e1 e2 e3 e4 e5) and run:
my $perms = permute(#array);
print ("$perms\n");
the output is just
e1 e2 e3 e4 e5
Any advice is appreciated.
Regards.
Actually, this could be found in the FAQ:
How do I permute N elements of a list?
Along with some nifty code for pasting:
#!/usr/bin/perl -n
# Fischer-Krause ordered permutation generator
sub permute (&#) {
my $code = shift;
my #idx = 0..$#_;
while ( $code->(#_[#idx]) ) {
my $p = $#idx;
--$p while $idx[$p-1] > $idx[$p];
my $q = $p or return;
push #idx, reverse splice #idx, $p;
++$q while $idx[$p-1] > $idx[$q];
#idx[$p-1,$q]=#idx[$q,$p-1];
}
}
permute { print "#_\n" } split;
This code is supposed to be used as a standalone script, but you can just use the sub directly with
sub permute (&#); # predeclare sub, paste sub at bottom
my #a;
permute { push #a, "#_" } #some_array;
There is a nice lecture on YouTube in the Stanford programming paradigms series about doing permutation with recursion and double mapping in Scheme. In Perl, I came up with the following implementation for the algorithm:
#!/usr/bin/perl
use strict;
use warnings;
my #array = qw(e1 e2 e3);
sub permute {
return ([]) unless (#_);
return map {
my #cdr = #_;
my $car = splice #cdr, $_, 1;
map { [$car, #$_]; } &permute(#cdr);
} 0 .. $#_;
}
print "#$_\n" foreach (&permute (#array));
Might be very inefficient, but I thought it was fun & elegant :)

How can I print N array elements with delimiters per line?

I have an array in Perl I want to print with space delimiters between each element, except every 10th element which should be newline delimited. There aren't any spaces in the elements if that matters.
I've written a function to do it with for and a counter, but I wondered if there's a better/shorter/canonical Perl way, perhaps a special join syntax or similar.
My function to illustrate:
sub PrintArrayWithNewlines
{
my $counter = 0;
my $newlineIndex = shift #_;
foreach my $item (#_)
{
++$counter;
print "$item";
if($counter == $newlineIndex)
{
$counter = 0;
print "\n";
}
else
{
print " ";
}
}
}
I like splice for a job like this:
sub PrintArrayWithNewlines {
my $n = 10;
my $delim = " ";
while (my #x = splice #_, 0, $n) {
print join($delim, #x), "\n";
}
}
You can use List::MoreUtils::natatime:
use warnings; use strict;
use List::MoreUtils qw( natatime );
my #x = (1 .. 35);
my $it = natatime 10, #x;
while ( my #v = $it->() ) {
print "#v\n"
}
Output:
C:\Temp> x
1 2 3 4 5 6 7 8 9 10
11 12 13 14 15 16 17 18 19 20
21 22 23 24 25 26 27 28 29 30
31 32 33 34 35
If you do not want to use any external modules, you can use array slices:
use warnings; use strict;
my #x = (1 .. 95);
my $n = 10;
for my $i ( 0 .. int #x/$n ) {
no warnings 'uninitialized';
print "#x[$n * $i .. $n * ($i + 1) - 1]\n";
}
The functions by and every in my module List::Gen can solve this problem:
use List::Gen;
for (every 10 => 'a' .. 'z') {
print "#$_\n"
}
# a b c d e f g h i j
# k l m n o p q r s t
# u v w x y z
it can also be written
foreach (by 10 => 'a' .. 'z') {
print "#$_\n"
}
or using the functional form:
mapn {print "#_\n"} 10 => 'a' .. 'z'; # #_ not #$_ here
or an iterator if that's your style:
my $letters = by 10 => 'a' .. 'z';
while (my $line = $letters->next) {
print "#$line\n";
}
You can also use map with a modification to PrintArrayWithNewlines:
#!/usr/bin/perl -w
use strict;
sub PrintArrayWithNewlines
{
my #array = #_;
my $newlineIndex = 10;
foreach my $item (#array) {
++$globalCounter;
print "$item";
if ($globalCounter == $newlineIndex) {
$globalCounter = 0;
print "\n";
}
else {
print " ";
}
}
}
my $globalCounter = 0;
my #myArray = 'a' .. 'z'
map { PrintArrayWithNewlines($_) } #myArray;
print "\n";
The output would be:
$ ./test.pl
a b c d e f g h i j
k l m n o p q r s t
u v x y z