in reply to Pure perl Jenkins 32 bit Hash

Are you sure the 32-bit mix4 is correct? Doing low-level unsigned arithmetic can be awkward in perl.

... $a -= $b; $a -= $c; no integer; $a ^= ($c >> 13); use integer; ...

Replies are listed 'Best First'.
Re^2: Pure perl Jenkins 32 bit Hash
by huck (Prior) on Nov 18, 2017 at 02:56 UTC

    Are you sure the 32-bit mix4 is correct?

    Guess not

    $Config{api_versionstring}:5.14.0 $Config{use64bitint}: $Config{ivsize}:4 $Config{byteorder}:1234 $Config{i16size}:2 $Config{i32size}:4 $Config{i64size}:8 $Config{osname}:MSWin32 $Config{osvers}:5.2 $ENV{PROCESSOR_ARCHITECTURE}:X86 orig : 11111111000000001111111111111111 ff00ffff use integer:>>16: 11111111111111111111111100000000 ffffff00 no integer :>>16: 00000000000000001111111100000000 0000ff00 orig : 00001111000000001111111111111111 0f00ffff use integer:>>16: 00000000000000000000111100000000 00000f00 no integer :>>16: 00000000000000000000111100000000 00000f00

    Doing low-level unsigned arithmetic can be awkward in perl.

    Seems so, this needs more investigation and i dont have a C compiler for that 32bit machine

    Thanks for the heads up, I will keep looking deeper

    Added:

    Re: How to do 'unsigned shift right' in perl? Note that both "<<" and ">>" in Perl are implemented directly using "<<" and ">>" in C. If use integer (see Integer Arithmetic) is in force then signed C integers are used, else unsigned C integers are used.

    Added2:

    Wow

    Ive got the "fix", just like you said, but understanding why it works and "-hash hash3" still doesnt work on 32bit and how mixing IV,UV and possibly NV arithmetic between mix and hash3 is causing the difference hasnt quite gelled yet. I'll be back! Devel::Peek and perlguts will rescue me!

Re^2: Pure perl Jenkins 32 bit Hash
by huck (Prior) on Nov 18, 2017 at 19:06 UTC

    Doing low-level unsigned arithmetic can be awkward in perl.

    yupo

    ok so i developed an overly debugged version of mix and the revised mix4 and ran it on the 32 bit box

    # this is inside a 'use integer;' block sub mix4 ($$$) { # per http://www.perlmonks.org/?node_id=1203705 this is a revised 32bi +t under 'use integer'; $_[A] -= $_[B]; $_[A] -= $_[C]; { no integer; $_[A] ^= ($_[C]>>13) +; } $_[B] -= $_[C]; $_[B] -= $_[A]; { no integer; $_[B] ^= ($_[A]<< 8) +; } $_[C] -= $_[A]; $_[C] -= $_[B]; { no integer; $_[C] ^= ($_[B]>>13) +; } $_[A] -= $_[B]; $_[A] -= $_[C]; { no integer; $_[A] ^= ($_[C]>>12) +; } $_[B] -= $_[C]; $_[B] -= $_[A]; { no integer; $_[B] ^= ($_[A]<<16) +; } $_[C] -= $_[A]; $_[C] -= $_[B]; { no integer; $_[C] ^= ($_[B]>> 5) +; } $_[A] -= $_[B]; $_[A] -= $_[C]; { no integer; $_[A] ^= ($_[C]>> 3) +; } $_[B] -= $_[C]; $_[B] -= $_[A]; { no integer; $_[B] ^= ($_[A]<<10) +; } $_[C] -= $_[A]; $_[C] -= $_[B]; { no integer; $_[C] ^= ($_[B]>>15) +; } }

    This is mix

    # there is no 'use integer;' here; sub mix ($$$) { $_[A] -= $_[B]; $_[A] -= $_[C]; $_[A] ^= ($_[C]>>13); $_[B] -= $_[C]; $_[B] -= $_[A]; $_[B] ^= ($_[A]<< 8); $_[C] -= $_[A]; $_[C] -= $_[B]; $_[C] ^= ($_[B]>>13); $_[A] -= $_[B]; $_[A] -= $_[C]; $_[A] ^= ($_[C]>>12); $_[B] -= $_[C]; $_[B] -= $_[A]; $_[B] ^= ($_[A]<<16); $_[C] -= $_[A]; $_[C] -= $_[B]; $_[C] ^= ($_[B]>> 5); $_[A] -= $_[B]; $_[A] -= $_[C]; $_[A] ^= ($_[C]>> 3); $_[B] -= $_[C]; $_[B] -= $_[A]; $_[B] ^= ($_[A]<<10); $_[C] -= $_[A]; $_[C] -= $_[B]; $_[C] ^= ($_[B]>>15); }
    and the results are very interesting

    during the first modification of C mix4exp shows (it is best to look at the following using download version without wrap)

    a1-x c>13 : A : 59743 0000e95f b1-x a< 8 : B : - -162 +9499560 9edfcf58 c1-a : C : - + - -59741 ffff16a3 SV = IV(0xc5f738) at 0xc5f73c REFCNT = 1 FLAGS = (PADMY,IOK,pIOK) IV = -59741 c1-b : C : - + - 1629439819 611f474b SV = IV(0xc5f738) at 0xc5f73c REFCNT = 1 FLAGS = (PADMY,IOK,pIOK) IV = 1629439819 c1-x b>13 : orig 1 : 01100 +001000111110100011101001011 611f474b : orig 2 : 10011 +110110111111100111101011000 9edfcf58 : >>13 : 00000 +000000001001111011011111110 0004f6fe : res : 01100 +001000110111011000110110101 611bb1b5 c1-x b>13 : C : - + - 1629204917 611bb1b5 while mixexp shows a1-x c>13 : A : 59743 0000e95f b1-x a< 8 : B : - -162 +9499560 9edfcf58 c1-a : C : - + - -59741 ffff16a3 SV = IV(0xc5f418) at 0xc5f41c REFCNT = 1 FLAGS = (PADMY,IOK,pIOK) IV = -59741 c1-b : C : - + - -2147483648 80000000 SV = PVNV(0xc7355c) at 0xc5f41c REFCNT = 1 FLAGS = (PADMY,NOK,pNOK) IV = -59741 NV = -2665527477 PV = 0 c1-x b>13 : orig 1 : 10000 +000000000000000000000000000 80000000 : orig 2 : 10011 +110110111111100111101011000 9edfcf58 : >>13 : 00000 +000000001001111011011111110 0004f6fe : res : 10000 +000000001001111011011111110 8004f6fe c1-x b>13 : C : - + - -2147158274 8004f6fe
    The Dump calls are Dump($_[C]);

    Notice that in mix4exp the Dump shows C stays IV, and shows the proper result of mod(32) arithmetic with A and B .

    But notice how in mixexp the Dump shows that after -=A C has stayed IV, with the proper result, but that after -=B C overflowed the IV creating a NV and when it comes to the shift portion it is an overflow indicator (0x80000000) that gets shifted. Of course everything goes to L in a handbasket after that.

    Doing low-level unsigned arithmetic can be awkward in perl.

    yupo