0

I have a hashing function in PHP which is a port of a Java hash function. On my 32-bit, the functions match. However, when running the PHP code on 64-bit OS the results change.

Is there anyway in which I can execute the arithmetic operations independent of the architecture, as if they are always executed on 32-bit system?

Here is my hashing function:

function numericHash( $text, $lessThan = 50 )
{
    $hash = 0;

    for ( $i = 0; $i < strlen( $text ); $i++ ) {
        $b = ord( $text[ $i ] );
        $hash += $b;
        $hash = intval( $hash );
        $hash += ( $hash << 10 );
        $hash = intval( $hash );
        $hash ^= ( $hash >> 6 );
        $hash = intval( $hash );
    }

    $hash += ( $hash << 3 );
    $hash = intval( $hash );
    $hash ^= ( $hash >> 11 );
    $hash = intval( $hash );

    $hash += intval( $hash << 15 );
    $hash = intval( $hash );
    return bcmod( (string) abs( $hash ), (string) $lessThan );
}
Interfector
  • 1,868
  • 1
  • 23
  • 43

2 Answers2

1

The shift operators behave different on php compiled for 64, because you have a PHP_MAX_INT value of 0xFFFFFFFFFFFF instead of 0xFFFFFFFF on 32 bit.

function lshift32($num, $steps) {
        // 64 bit
        if (PHP_INT_MAX >= 0x7FFFFFF) {
                if ($num < 0) {
                        // set 32bit signed bit
                        $num = $num | 0x80000000;
                }
                $num = ($num << $steps) & 0xFFFFFFFF;
                if (($num & 0x80000000) == 0x80000000) {
                        $num = $num | 0xFFFFFFFF00000000;
                }


                return $num;
        }
        else
        {
                return $num << $steps;
        }
}
Philipp
  • 15,377
  • 4
  • 35
  • 52
  • I tried a simple test with the following results 32bit: int(87860732) << 10 => int(-224923648) 64bit: lshift32(int(87860732), 10) => int(4070043668) Can you confirm this, Philipp? – Interfector Mar 02 '14 at 13:36
  • there are some problems with sign(and i implemented an lsh..) code updated – Philipp Mar 03 '14 at 10:46
0

The solution in my case is to use the following function in place of intval

function intval32bits($value)
{
    $value = ($value & 0xFFFFFFFF);

    if ($value & 0x80000000)
        $value = -((~$value & 0xFFFFFFFF) + 1);

    return $value;
}

Reference: https://stackoverflow.com/a/2123458

Community
  • 1
  • 1
Interfector
  • 1,868
  • 1
  • 23
  • 43