From de0b13ab02160368b418528dfa2390173cfd2114 Mon Sep 17 00:00:00 2001 From: Paragon Initiative Enterprises Date: Thu, 20 Sep 2018 20:16:15 -0400 Subject: [PATCH] Optimize 32-bit by reducing memory overhead (arrays, object creation, etc.). --- src/Core32/Int32.php | 75 ++++++++++++++++++++++++- src/Core32/Int64.php | 131 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 205 insertions(+), 1 deletion(-) diff --git a/src/Core32/Int32.php b/src/Core32/Int32.php index 8dc7d49d..88caaeb1 100644 --- a/src/Core32/Int32.php +++ b/src/Core32/Int32.php @@ -168,12 +168,42 @@ public function mulInt($int = 0, $size = 0) $return = new ParagonIE_Sodium_Core32_Int32(); $return->unsignedInt = $this->unsignedInt; + // Initialize: + $ret0 = 0; + $ret1 = 0; + $a0 = $a->limbs[0]; + $a1 = $a->limbs[1]; + + /** @var int $size */ + /** @var int $i */ for ($i = $size; $i >= 0; --$i) { $m = (int) (-($int & 1)); + /* $return = $return->addInt32($a->mask($m)); + */ + $x0 = $a0 & $m; + $x1 = $a1 & $m; + + $ret1 += $x1; + $c = $ret1 >> 16; + + $ret0 += $x0 + $c; + + $ret0 &= 0xffff; + $ret1 &= 0xffff; + + /* $a = $a->shiftLeft(1); + */ + $a1 = ($a1 << 1); + $x1 = $a1 >> 16; + $a0 = ($a0 << 1) | $x1; + $a0 &= 0xffff; + $a1 &= 0xffff; $int >>= 1; } + $return->limbs[0] = $ret0; + $return->limbs[1] = $ret1; return $return; } @@ -197,13 +227,56 @@ public function mulInt32(ParagonIE_Sodium_Core32_Int32 $int, $size = 0) $return = new ParagonIE_Sodium_Core32_Int32(); $return->unsignedInt = $this->unsignedInt; + // Initialize: + $ret0 = 0; + $ret1 = 0; + $a0 = $a->limbs[0]; + $a1 = $a->limbs[1]; + $b0 = $b->limbs[0]; + $b1 = $b->limbs[1]; + + /** @var int $size */ /** @var int $i */ for ($i = $size; $i >= 0; --$i) { - $m = (int) (-($b->limbs[1] & 1)); + $m = (int) (-($b1 & 1)); + /* $return = $return->addInt32($a->mask($m)); + */ + $x0 = $a0 & $m; + $x1 = $a1 & $m; + + $ret1 += $x1; + $c = $ret1 >> 16; + + $ret0 += $x0 + $c; + + $ret0 &= 0xffff; + $ret1 &= 0xffff; + + /* $a = $a->shiftLeft(1); + */ + $a1 = ($a1 << 1); + $x1 = $a1 >> 16; + $a0 = ($a0 << 1) | $x1; + $a0 &= 0xffff; + $a1 &= 0xffff; + + /* $b = $b->shiftRight(1); + */ + $x0 = ($b0 & 1) << 16; + + $b0 = ($b0 >> 1); + $b1 = (($b1 | $x0) >> 1); + + $b0 &= 0xffff; + $b1 &= 0xffff; + } + $return->limbs[0] = $ret0; + $return->limbs[1] = $ret1; + return $return; } diff --git a/src/Core32/Int64.php b/src/Core32/Int64.php index 6f791ea0..f9d906de 100644 --- a/src/Core32/Int64.php +++ b/src/Core32/Int64.php @@ -197,15 +197,73 @@ public function mulInt($int = 0, $size = 0) $return = new ParagonIE_Sodium_Core32_Int64(); $return->unsignedInt = $this->unsignedInt; + // Initialize: + $ret0 = 0; + $ret1 = 0; + $ret2 = 0; + $ret3 = 0; + $a0 = $a->limbs[0]; + $a1 = $a->limbs[1]; + $a2 = $a->limbs[2]; + $a3 = $a->limbs[3]; + + /** @var int $size */ + /** @var int $i */ for ($i = $size; $i >= 0; --$i) { + /* $return = $return->addInt64( $a->mask64( (int) (-($int & 1)), (int) (-($int & 1)) ) ); + */ + $mask = -($int & 1); + $x0 = $a0 & $mask; + $x1 = $a1 & $mask; + $x2 = $a2 & $mask; + $x3 = $a3 & $mask; + + $ret3 += $x3; + $c = $ret3 >> 16; + + $ret2 += $x2 + $c; + $c = $ret2 >> 16; + + $ret1 += $x1 + $c; + $c = $ret1 >> 16; + + $ret0 += $x0 + $c; + + $ret0 &= 0xffff; + $ret1 &= 0xffff; + $ret2 &= 0xffff; + $ret3 &= 0xffff; + + /* + $a = $a->shiftLeft(1); + */ + $a3 = $a3 << 1; + $x3 = $a3 >> 16; + $a2 = ($a2 << 1) | $x3; + $x2 = $a2 >> 16; + $a1 = ($a1 << 1) | $x2; + $x1 = $a1 >> 16; + $a0 = ($a0 << 1) | $x1; + $a0 &= 0xffff; + $a1 &= 0xffff; + $a2 &= 0xffff; + $a3 &= 0xffff; + + $int >>= 1; + $return->limbs[0] = $ret0; + $return->limbs[1] = $ret1; + $return->limbs[2] = $ret2; + $return->limbs[3] = $ret3; + /* $a = $a->shiftLeft(1); $int >>= 1; + */ } return $return; } @@ -270,18 +328,91 @@ public function mulInt64(ParagonIE_Sodium_Core32_Int64 $int, $size = 0) $return = new ParagonIE_Sodium_Core32_Int64(); $return->unsignedInt = $this->unsignedInt; + // Initialize: + $ret0 = 0; + $ret1 = 0; + $ret2 = 0; + $ret3 = 0; + $a0 = $a->limbs[0]; + $a1 = $a->limbs[1]; + $a2 = $a->limbs[2]; + $a3 = $a->limbs[3]; + $b0 = $b->limbs[0]; + $b1 = $b->limbs[1]; + $b2 = $b->limbs[2]; + $b3 = $b->limbs[3]; + /** @var int $size */ /** @var int $i */ for ($i = (int) $size; $i >= 0; --$i) { + /* $return = $return->addInt64( $a->mask64( (int) (-($b->limbs[3] & 1)), (int) (-($b->limbs[3] & 1)) ) ); + */ + $mask = -($b3 & 1); + $x0 = $a0 & $mask; + $x1 = $a1 & $mask; + $x2 = $a2 & $mask; + $x3 = $a3 & $mask; + + $ret3 += $x3; + $c = $ret3 >> 16; + + $ret2 += $x2 + $c; + $c = $ret2 >> 16; + + $ret1 += $x1 + $c; + $c = $ret1 >> 16; + + $ret0 += $x0 + $c; + + $ret0 &= 0xffff; + $ret1 &= 0xffff; + $ret2 &= 0xffff; + $ret3 &= 0xffff; + + /* $a = $a->shiftLeft(1); + */ + $a3 = $a3 << 1; + $x3 = $a3 >> 16; + $a2 = ($a2 << 1) | $x3; + $x2 = $a2 >> 16; + $a1 = ($a1 << 1) | $x2; + $x1 = $a1 >> 16; + $a0 = ($a0 << 1) | $x1; + $a0 &= 0xffff; + $a1 &= 0xffff; + $a2 &= 0xffff; + $a3 &= 0xffff; + + /* $b = $b->shiftRight(1); + */ + $x0 = ($b0 & 1) << 16; + $x1 = ($b1 & 1) << 16; + $x2 = ($b2 & 1) << 16; + + $b0 = ($b0 >> 1); + $b1 = (($b1 | $x0) >> 1); + $b2 = (($b2 | $x1) >> 1); + $b3 = (($b3 | $x2) >> 1); + + $b0 &= 0xffff; + $b1 &= 0xffff; + $b2 &= 0xffff; + $b3 &= 0xffff; + } + $return->limbs[0] = $ret0; + $return->limbs[1] = $ret1; + $return->limbs[2] = $ret2; + $return->limbs[3] = $ret3; + return $return; }