protected function sphUnpackI64($v)
    {
        list($hi, $lo) = array_values(unpack('N*N*', $v));

        // x64
        if (PHP_INT_SIZE >= 8) {
            if ($hi < 0) {
                $hi += (1 << 32);
            } // because php 5.2.2 to 5.2.5 is totally fucked up again
            if ($lo < 0) {
                $lo += (1 << 32);
            }

            return ($hi << 32) + $lo;
        }

        // x32, int
        if ($hi == 0) {
            if ($lo > 0) {
                return $lo;
            }

            return sprintf('%u', $lo);
        } // x32, int
        elseif ($hi == -1) {
            if ($lo < 0) {
                return $lo;
            }

            return sprintf('%.0f', $lo - 4294967296.0);
        }

        $neg = '';
        $c = 0;
        if ($hi < 0) {
            $hi = ~$hi;
            $lo = ~$lo;
            $c = 1;
            $neg = '-';
        }

        $hi = sprintf('%u', $hi);
        $lo = sprintf('%u', $lo);

        // x32, bcmath
        if (function_exists('bcmul')) {
            return $neg.bcadd(bcadd($lo, bcmul($hi, '4294967296')), $c);
        }

        // x32, no-bcmath
        $hi = (float) $hi;
        $lo = (float) $lo;

        $q = floor($hi / 10000000.0);
        $r = $hi - $q * 10000000.0;
        $m = $lo + $r * 4967296.0;
        $mq = floor($m / 10000000.0);
        $l = $m - $mq * 10000000.0 + $c;
        $h = $q * 4294967296.0 + $r * 429.0 + $mq;
        if ($l == 10000000) {
            $l = 0;
            $h += 1;
        }

        $h = sprintf('%.0f', $h);
        $l = sprintf('%07.0f', $l);
        if ($h == '0') {
            return $neg.sprintf('%.0f', (float) $l);
        }

        return $neg.$h.$l;
    }