Here's the corrected 32-bit mumurhash3 implementation in PL/I.

This does a check for the endianness of the machine and properly
reads values.  I've included a demonstration test.

This also corrects a typo I had in the previous version when
using pointer-add to calculate the base of the TAIL array.

I've verified this matches the result of the C version on an x86 host
with the same data.

   - Dave R. -

 test: proc options(main);

  mumur3_32: proc(data, nbytes) returns(fixed unsigned bin(32));

    /* return '1'b if the platform is big-endian */
    determine_endian: proc returns(bit(1));
       dcl int FIXED BIN(31);
       dcl charptr POINTER;
       dcl chararray(4) CHAR(1) based(charptr);

       int = '12345678'xu;
       charptr = addr(int);

       if (chararray(1) = '12'x) then
          return ('1'B); /* big-endian */
       else
          return ('0'B); /* little-endian */
    end;

    dcl is_big_endian bit(1);

    dcl data pointer;
    dcl nbytes fixed bin(31);

    if (data = NULL() | nbytes = 0) then
       return (0);

    is_big_endian = determine_endian();

    dcl c1 unsigned fixed bin(32) init('cc9e2d51'XU);
    dcl c2 unsigned fixed bin(32) init('1b873593'XU);

    dcl nblocks fixed bin(31) init(ISRL(nbytes,2)); /* nbytes/4 */
    dcl blocks(0:(nblocks-1)) unsigned fixed bin(32) based(data);
    dcl blocks_le(0:(nblocks-1)) unsigned fixed bin(32) based(data)
               LITTLEENDIAN;
    dcl tail(0:3) unsigned fixed bin(8) based(tailp);

    dcl tailp pointer;
    tailp = pointeradd(data, nblocks * 4);
   
    dcl h unsigned fixed bin(32) init(0);
    dcl i fixed bin(31);
    dcl k unsigned fixed bin(32);
    
    do i=0 to nblocks-1;
       if(is_big_endian) then k = blocks_le(i);
       else k = blocks(i);
       
       k = k * c1;
       k = ior(isll(k,15), isrl(k, 32-15));
       k = k * c2;
       
       h = ieor(h,k);
       h = ior(isll(h,13), isrl(h, 32-13));
       h = (h * 5) + 'e6546b64'xu;
     end;
     
     k = 0;
     select( iand(nbytes, 3) );
       when(3) do;
         k = ieor(k, isll(tail(2), 16));
         goto case_2;
       end;
       when(2) do;
    case_2: ;
         k = ieor(k, isll(tail(1), 8));
         goto case_1;
       end;
       when(1) do;
    case_1: ;
         k = ieor(k, tail(0));
         k = k * c1;
         k = ieor( isll(k,15), isrl(k,32-15));
         k = k * c2;
         h = ieor(h, k);
       end;
     otherwise; /* do nothing */
    end;
    
    h = ieor(h, nbytes);
    
    h = ieor(h, isrl(h,16));
    h = h * '85ebca6b'xu;
    h = ieor(h, isrl(h,13));
    h = h * 'c2b2ae35'xu;
    h = ieor(h, isrl(h,16));
    
    return(h);
 end;
   
   /* 29 element array of bytes */
  dcl data(29) unsigned fixed bin(8)
    init( 'E2'xu, '96'xu, '94'xu, '85'xu, '40'xu, 'A2'xu,
          'A3'xu, '99'xu, '89'xu, '95'xu, '87'xu, '40'xu,
          '84'xu, '81'xu, 'A3'xu, '81'xu, '40'xu, 'A3'xu,
          '96'xu, '40'xu, 'A3'xu, '85'xu, 'A2'xu, 'A3'xu,
          '40'xu, '96'xu, 'A4'xu, 'A3'xu, '15'xu );
  
  dcl val fixed bin(32) unsigned;
  
  val = mumur3_32(addr(data), 29);
  
  put skip list('val is ', val);
 end;

----------------------------------------------------------------------
For IBM-MAIN subscribe / signoff / archive access instructions,
send email to [email protected] with the message: INFO IBM-MAIN

Reply via email to