Your skill will accomplishwhat the force of many cannot PerlMonks

### reproducing javascripts >> operator

by mje (Curate)
 on Mar 20, 2015 at 11:06 UTC Need Help??
mje has asked for the wisdom of the Perl Monks concerning the following question:

I've got some javascript I need to rewrite in Perl and I'm stuck on the javascript >> operator which I believe is sign-propagating right bitwise shift. I found this node and it looked promising but none of the suggestions work for me.

I was thinking it may be because my ivsize is 8. Anyway, here are some examples from javascript of numbers shifted right 8 bits:

```  -1 >> 8 = -1
2140837940 >> 8 = 8362648
-1934825877 >> 8 = -7557914
-2004116368 >> 8 = -7828580
1978483312 >> 8 = 7728450
-293893010 >> 8 = -1148020

I cannot seem to reproduce this in Perl. Any ideas?

javascript >> operator

Replies are listed 'Best First'.
Re: reproducing javascripts >> operator
by shmem (Chancellor) on Mar 20, 2015 at 11:46 UTC

Looking at the results, the JavaScript bitwise shift isn't. It's a division with rounding.

This is ugly, but does what you want:

```sub rshift {int(\$_[0]/(1<<\$_[1])+(\$_[0]<0?-0.5:0.5))}

for (2140837940,-1934825877,-2004116368,1978483312,-293893010) {
print "\$_ >> 8 = ",rshift(\$_,8),"\n"
}
__END__
2140837940 >> 8 = 8362648
-1934825877 >> 8 = -7557914
-2004116368 >> 8 = -7828580
1978483312 >> 8 = 7728450
-293893010 >> 8 = -1148020

perl -le'print map{pack c,(\$-++?1:13)+ord}split//,ESEL'

Yeah, if the numbers are large enough, JavaScript silently converts them to float before doing some operations like this--it can be surprising.

...roboticus

When your only tool is a hammer, all problems look like your thumb.

Thanks. That does seem to work for everything except -1.

It appears on a 32 bit perl use integer and the >> operator work.

I'm using a 64 bit perl with 8 bytes integers. The actual problem I'm having is the script below works on a 32 bit perl and does not on a 64 bit perl. It is a hack of some javascript hence the way it is written right now.

```use 5.016;
use strict;
use warnings;
use integer;

challenge('932209653','YRM1k2jP', 'a', 'e', 'xxx:');

sub challenge {
my (\$c, \$slt, \$s1, \$s2, \$value) = @_;

my \$table = "00000000 77073096 EE0E612C 990951BA 076DC419 706AF48F
+ E963A535 9E6495A3 0EDB8832 79DCB8A4 E0D5E91E 97D2D988 09B64C2B 7EB17
+CBD E7B82D07 90BF1D91 1DB71064 6AB020F2 F3B97148 84BE41DE 1ADAD47D 6D
+DDE4EB F4D4B551 83D385C7 136C9856 646BA8C0 FD62F97A 8A65C9EC 14015C4F
+ 63066CD9 FA0F3D63 8D080DF5 3B6E20C8 4C69105E D56041E4 A2677172 3C03E
+4D1 4B04D447 D20D85FD A50AB56B 35B5A8FA 42B2986C DBBBC9D6 ACBCF940 32
+D86CE3 45DF5C75 DCD60DCF ABD13D59 26D930AC 51DE003A C8D75180 BFD06116
+ 21B4F4B5 56B3C423 CFBA9599 B8BDA50F 2802B89E 5F058808 C60CD9B2 B10BE
+924 2F6F7C87 58684C11 C1611DAB B6662D3D 76DC4190 01DB7106 98D220BC EF
+D5102A 71B18589 06B6B51F 9FBFE4A5 E8B8D433 7807C9A2 0F00F934 9609A88E
+ E10E9818 7F6A0DBB 086D3D2D 91646C97 E6635C01 6B6B51F4 1C6C6162 85653
+0D8 F262004E 6C0695ED 1B01A57B 8208F4C1 F50FC457 65B0D9C6 12B7E950 8B
+BEB8EA FCB9887C 62DD1DDF 15DA2D49 8CD37CF3 FBD44C65 4DB26158 3AB551CE
+ A3BC0074 D4BB30E2 4ADFA541 3DD895D7 A4D1C46D D3D6F4FB 4369E96A 346ED
+9FC AD678846 DA60B8D0 44042D73 33031DE5 AA0A4C5F DD0D7CC9 5005713C 27
+0241AA BE0B1010 C90C2086 5768B525 206F85B3 B966D409 CE61E49F 5EDEF90E
+ 29D9C998 B0D09822 C7D7A8B4 59B33D17 2EB40D81 B7BD5C3B C0BA6CAD EDB88
+320 9ABFB3B6 03B6E20C 74B1D29A EAD54739 9DD277AF 04DB2615 73DC1683 E3
+630B12 94643B84 0D6D6A3E 7A6A5AA8 E40ECF0B 9309FF9D 0A00AE27 7D079EB1
+ F00F9344 8708A3D2 1E01F268 6906C2FE F762575D 806567CB 196C3671 6E6B0
+6E7 FED41B76 89D32BE0 10DA7A5A 67DD4ACC F9B9DF6F 8EBEEFF9 17B7BE43 60
+B08ED5 D6D6A3E8 A1D1937E 38D8C2C4 4FDFF252 D1BB67F1 A6BC5767 3FB506DD
+ 48B2364B D80D2BDA AF0A1B4C 36034AF6 41047A60 DF60EFC3 A867DF55 316E8
+EEF 4669BE79 CB61B38C BC66831A 256FD2A0 5268E236 CC0C7795 BB0B4703 22
+0216B9 5505262F C5BA3BBE B2BD0B28 2BB45A92 5CB36A04 C2D7FFA7 B5D0CF31
+ 2CD99E8B 5BDEAE1D 9B64C2B0 EC63F226 756AA39C 026D930A 9C0906A9 EB0E3
+63F 72076785 05005713 95BF4A82 E2B87A14 7BB12BAE 0CB61B38 92D28E9B E5
+D5BE0D 7CDCEFB7 0BDBDF21 86D3D2D4 F1D4E242 68DDB3F8 1FDA836E 81BE16CD
+ F6B9265B 6FB077E1 18B74777 88085AE6 FF0F6A70 66063BCA 11010B5C 8F659
+EFF F862AE69 616BFFD3 166CCF45 A00AE278 D70DD2EE 4E048354 3903B3C2 A7
+672661 D06016F7 4969474D 3E6E77DB AED16A4A D9D65ADC 40DF0B66 37D83BF0
+ A9BCAE53 DEBB9EC5 47B2CF7F 30B5FFE9 BDBDF21C CABAC28A 53B39330 24B4A
+3A6 BAD03605 CDD70693 54DE5729 23D967BF B3667A2E C4614AB8 5D681B02 2A
+6F2B94 B40BBE37 C30C8EA1 5A05DF1B 2D02EF8D";

my \$n = 4;

my \$start = ord(\$s1);
my \$end   = ord(\$s2);
my @arr;
my \$chlg;
my \$crc;

my \$m = ((\$end - \$start) + 1) ** \$n;
for (my \$i=0; \$i < \$n; \$i++) {
\$arr[\$i] = \$s1;
}
XXX:
for (my \$i=0; \$i < (\$m-1); \$i++) {
YYY:
for (my \$j = \$n-1; \$j >= 0;--\$j) {
my \$t = ord(\$arr[\$j]);
\$t++;
say \$t if \$i == 0;
\$arr[\$j] = chr(\$t);
if (ord(\$arr[\$j]) <= \$end) {
last YYY;
} else {
\$arr[\$j] = \$s1;
}
}
\$chlg = join("", @arr);
my \$str = \$chlg . \$slt;
\$crc = -1;
for (my \$k = 0, my \$iTop = length(\$str); \$k < \$iTop; \$k++ ) {
my \$code = ord(substr(\$str, \$k, 1));
\$crc = (\$crc >> 8) ^
(hex(substr(\$table, (((\$crc ^ \$code) & 0x000000FF) * 9
+), 8)));
}
\$crc =  \$crc ^ (-1);
\$crc = abs(\$crc);
if (\$crc == \$c) {
last XXX;
}
}
my \$result = \$value . \$chlg . ":" . \$slt . ":" . \$crc;
say \$result;
return \$result;
}
# outputs xxx:dede:YRM1k2jP:932209653 on 32 bit perl
# and           xxx:eeee:YRM1k2jP:2651920522 on 64 bit perl
The actual problem I'm having is the script below works on a 32 bit perl and does not on a 64 bit perl

At least rshift() fixes the different-output issue; it works

```# 32bit:
perl -e 'printf"%vd\n",\$^V; do pop' 1120752.pl
5.8.8
98
xxx:eeee:YRM1k2jP:1749307403
# 64bit:
perl -e 'printf"%vd\n",\$^V; do pop' 1120752.pl
5.14.2
98
xxx:eeee:YRM1k2jP:1749307403

...for some value of "works". The 98 ostensibly comes from the line

```say \$t if \$i == 0;

...and something else besides that may need to be fixed. Your turn.

perl -le'print map{pack c,(\$-++?1:13)+ord}split//,ESEL'
Re: reproducing javascripts >> operator
by ww (Archbishop) on Mar 20, 2015 at 11:35 UTC
Re: reproducing javascripts >> operator
by oiskuu (Hermit) on Mar 20, 2015 at 19:26 UTC

The (canonical) way to perform sign extension is via xor and subtract: sub sxtb { (shift ^ 0x80) - 0x80 }

For CRC digest, I'd consider using a specific module, but in a pinch, the following should work:

```sub sxt { ((0xffffffff & shift) ^ 0x80000000) - 0x80000000 }
...

\$crc = (\$crc >> 8) ^ ...
\$crc = sxt \$crc;
...

Create A New User
Node Status?
node history
Node Type: perlquestion [id://1120729]
Approved by GrandFather
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others rifling through the Monastery: (2)
As of 2019-04-20 07:20 GMT
Sections?
Information?
Find Nodes?
Leftovers?
Voting Booth?
I am most likely to install a new module from CPAN if:

Results (108 votes). Check out past polls.

Notices?