public function packI64($v)
{
if (!is_numeric($v)) {
throw new \InvalidArgumentException('Input must be numeric.');
}
// x64
if (PHP_INT_SIZE >= 8) {
$v = (int) $v;
return pack('NN', $v >> 32, $v & 0xffffffff);
}
// x32, int
if (is_int($v)) {
return pack('NN', $v < 0 ? -1 : 0, $v);
}
// x32, bcmath
if (function_exists('bcmul')) {
if (bccomp($v, 0) == -1) {
$v = bcadd('18446744073709551616', $v);
}
$h = bcdiv($v, '4294967296', 0);
$l = bcmod($v, '4294967296');
// conversion to float is intentional; int would lose 31st bit
return pack('NN', (double) $h, (double) $l);
}
// x32, no-bcmath
$p = max(0, strlen($v) - 13);
$lo = abs((double) substr($v, $p));
$hi = abs((double) substr($v, 0, $p));
// (10 ^ 13) % (1 << 32) = 1316134912
$m = $lo + $hi * 1316134912.0;
$q = floor($m / 4294967296.0);
$l = $m - $q * 4294967296.0;
// (10 ^ 13) / (1 << 32) = 2328
$h = $hi * 2328.0 + $q;
if ($v < 0) {
if ($l == 0) {
$h = 4294967296.0 - $h;
} else {
$h = 4294967295.0 - $h;
$l = 4294967296.0 - $l;
}
}
return pack('NN', $h, $l);
}