You are here

class ParagonIE_Sodium_Core32_Int64 in Automatic Updates 8

Same name and namespace in other branches
  1. 7 vendor/paragonie/sodium_compat/src/Core32/Int64.php \ParagonIE_Sodium_Core32_Int64

Class ParagonIE_Sodium_Core32_Int64

Encapsulates a 64-bit integer.

These are immutable. It always returns a new instance.

Hierarchy

Expanded class hierarchy of ParagonIE_Sodium_Core32_Int64

File

vendor/paragonie/sodium_compat/src/Core32/Int64.php, line 10

View source
class ParagonIE_Sodium_Core32_Int64 {

  /**
   * @var array<int, int> - four 16-bit integers
   */
  public $limbs = array(
    0,
    0,
    0,
    0,
  );

  /**
   * @var int
   */
  public $overflow = 0;

  /**
   * @var bool
   */
  public $unsignedInt = false;

  /**
   * ParagonIE_Sodium_Core32_Int64 constructor.
   * @param array $array
   * @param bool $unsignedInt
   */
  public function __construct($array = array(
    0,
    0,
    0,
    0,
  ), $unsignedInt = false) {
    $this->limbs = array(
      (int) $array[0],
      (int) $array[1],
      (int) $array[2],
      (int) $array[3],
    );
    $this->overflow = 0;
    $this->unsignedInt = $unsignedInt;
  }

  /**
   * Adds two int64 objects
   *
   * @param ParagonIE_Sodium_Core32_Int64 $addend
   * @return ParagonIE_Sodium_Core32_Int64
   */
  public function addInt64(ParagonIE_Sodium_Core32_Int64 $addend) {
    $i0 = $this->limbs[0];
    $i1 = $this->limbs[1];
    $i2 = $this->limbs[2];
    $i3 = $this->limbs[3];
    $j0 = $addend->limbs[0];
    $j1 = $addend->limbs[1];
    $j2 = $addend->limbs[2];
    $j3 = $addend->limbs[3];
    $r3 = $i3 + ($j3 & 0xffff);
    $carry = $r3 >> 16;
    $r2 = $i2 + ($j2 & 0xffff) + $carry;
    $carry = $r2 >> 16;
    $r1 = $i1 + ($j1 & 0xffff) + $carry;
    $carry = $r1 >> 16;
    $r0 = $i0 + ($j0 & 0xffff) + $carry;
    $carry = $r0 >> 16;
    $r0 &= 0xffff;
    $r1 &= 0xffff;
    $r2 &= 0xffff;
    $r3 &= 0xffff;
    $return = new ParagonIE_Sodium_Core32_Int64(array(
      $r0,
      $r1,
      $r2,
      $r3,
    ));
    $return->overflow = $carry;
    $return->unsignedInt = $this->unsignedInt;
    return $return;
  }

  /**
   * Adds a normal integer to an int64 object
   *
   * @param int $int
   * @return ParagonIE_Sodium_Core32_Int64
   * @throws SodiumException
   * @throws TypeError
   */
  public function addInt($int) {
    ParagonIE_Sodium_Core32_Util::declareScalarType($int, 'int', 1);

    /** @var int $int */
    $int = (int) $int;
    $i0 = $this->limbs[0];
    $i1 = $this->limbs[1];
    $i2 = $this->limbs[2];
    $i3 = $this->limbs[3];
    $r3 = $i3 + ($int & 0xffff);
    $carry = $r3 >> 16;
    $r2 = $i2 + ($int >> 16 & 0xffff) + $carry;
    $carry = $r2 >> 16;
    $r1 = $i1 + $carry;
    $carry = $r1 >> 16;
    $r0 = $i0 + $carry;
    $carry = $r0 >> 16;
    $r0 &= 0xffff;
    $r1 &= 0xffff;
    $r2 &= 0xffff;
    $r3 &= 0xffff;
    $return = new ParagonIE_Sodium_Core32_Int64(array(
      $r0,
      $r1,
      $r2,
      $r3,
    ));
    $return->overflow = $carry;
    $return->unsignedInt = $this->unsignedInt;
    return $return;
  }

  /**
   * @param int $b
   * @return int
   */
  public function compareInt($b = 0) {
    $gt = 0;
    $eq = 1;
    $i = 4;
    $j = 0;
    while ($i > 0) {
      --$i;

      /** @var int $x1 */
      $x1 = $this->limbs[$i];

      /** @var int $x2 */
      $x2 = $b >> ($j << 4) & 0xffff;

      /** int */
      $gt |= $x2 - $x1 >> 8 & $eq;

      /** int */
      $eq &= ($x2 ^ $x1) - 1 >> 8;
    }
    return $gt + $gt - $eq + 1;
  }

  /**
   * @param int $b
   * @return bool
   */
  public function isGreaterThan($b = 0) {
    return $this
      ->compareInt($b) > 0;
  }

  /**
   * @param int $b
   * @return bool
   */
  public function isLessThanInt($b = 0) {
    return $this
      ->compareInt($b) < 0;
  }

  /**
   * @param int $hi
   * @param int $lo
   * @return ParagonIE_Sodium_Core32_Int64
   */
  public function mask64($hi = 0, $lo = 0) {

    /** @var int $a */
    $a = $hi >> 16 & 0xffff;

    /** @var int $b */
    $b = $hi & 0xffff;

    /** @var int $c */
    $c = $lo >> 16 & 0xffff;

    /** @var int $d */
    $d = $lo & 0xffff;
    return new ParagonIE_Sodium_Core32_Int64(array(
      $this->limbs[0] & $a,
      $this->limbs[1] & $b,
      $this->limbs[2] & $c,
      $this->limbs[3] & $d,
    ), $this->unsignedInt);
  }

  /**
   * @param int $int
   * @param int $size
   * @return ParagonIE_Sodium_Core32_Int64
   * @throws SodiumException
   * @throws TypeError
   * @psalm-suppress MixedAssignment
   */
  public function mulInt($int = 0, $size = 0) {
    if (ParagonIE_Sodium_Compat::$fastMult) {
      return $this
        ->mulIntFast($int);
    }
    ParagonIE_Sodium_Core32_Util::declareScalarType($int, 'int', 1);
    ParagonIE_Sodium_Core32_Util::declareScalarType($size, 'int', 2);

    /** @var int $int */
    $int = (int) $int;

    /** @var int $size */
    $size = (int) $size;
    if (!$size) {
      $size = 63;
    }
    $a = clone $this;
    $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) {
      $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;
      $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;
    return $return;
  }

  /**
   * @param ParagonIE_Sodium_Core32_Int64 $A
   * @param ParagonIE_Sodium_Core32_Int64 $B
   * @return array<int, ParagonIE_Sodium_Core32_Int64>
   * @throws SodiumException
   * @throws TypeError
   * @psalm-suppress MixedInferredReturnType
   */
  public static function ctSelect(ParagonIE_Sodium_Core32_Int64 $A, ParagonIE_Sodium_Core32_Int64 $B) {
    $a = clone $A;
    $b = clone $B;

    /** @var int $aNeg */
    $aNeg = $a->limbs[0] >> 15 & 1;

    /** @var int $bNeg */
    $bNeg = $b->limbs[0] >> 15 & 1;

    /** @var int $m */
    $m = -($aNeg & $bNeg) | 1;

    /** @var int $swap */
    $swap = $bNeg & ~$aNeg;

    /** @var int $d */
    $d = -$swap;

    /*
            if ($bNeg && !$aNeg) {
       $a = clone $int;
       $b = clone $this;
            } elseif($bNeg && $aNeg) {
       $a = $this->mulInt(-1);
       $b = $int->mulInt(-1);
            }
    */
    $x = $a
      ->xorInt64($b)
      ->mask64($d, $d);
    return array(
      $a
        ->xorInt64($x)
        ->mulInt($m),
      $b
        ->xorInt64($x)
        ->mulInt($m),
    );
  }

  /**
   * @param array<int, int> $a
   * @param array<int, int> $b
   * @param int $baseLog2
   * @return array<int, int>
   */
  public function multiplyLong(array $a, array $b, $baseLog2 = 16) {
    $a_l = count($a);
    $b_l = count($b);

    /** @var array<int, int> $r */
    $r = array_fill(0, $a_l + $b_l + 1, 0);
    $base = 1 << $baseLog2;
    for ($i = 0; $i < $a_l; ++$i) {
      $a_i = $a[$i];
      for ($j = 0; $j < $a_l; ++$j) {
        $b_j = $b[$j];
        $product = $a_i * $b_j + $r[$i + $j];
        $carry = $product >> $baseLog2 & 0xffff;
        $r[$i + $j] = $product - (int) ($carry * $base) & 0xffff;
        $r[$i + $j + 1] += $carry;
      }
    }
    return array_slice($r, 0, 5);
  }

  /**
   * @param int $int
   * @return ParagonIE_Sodium_Core32_Int64
   */
  public function mulIntFast($int) {

    // Handle negative numbers
    $aNeg = $this->limbs[0] >> 15 & 1;
    $bNeg = $int >> 31 & 1;
    $a = array_reverse($this->limbs);
    $b = array(
      $int & 0xffff,
      $int >> 16 & 0xffff,
      -$bNeg & 0xffff,
      -$bNeg & 0xffff,
    );
    if ($aNeg) {
      for ($i = 0; $i < 4; ++$i) {
        $a[$i] = ($a[$i] ^ 0xffff) & 0xffff;
      }
      ++$a[0];
    }
    if ($bNeg) {
      for ($i = 0; $i < 4; ++$i) {
        $b[$i] = ($b[$i] ^ 0xffff) & 0xffff;
      }
      ++$b[0];
    }

    // Multiply
    $res = $this
      ->multiplyLong($a, $b);

    // Re-apply negation to results
    if ($aNeg !== $bNeg) {
      for ($i = 0; $i < 4; ++$i) {
        $res[$i] = (0xffff ^ $res[$i]) & 0xffff;
      }

      // Handle integer overflow
      $c = 1;
      for ($i = 0; $i < 4; ++$i) {
        $res[$i] += $c;
        $c = $res[$i] >> 16;
        $res[$i] &= 0xffff;
      }
    }

    // Return our values
    $return = new ParagonIE_Sodium_Core32_Int64();
    $return->limbs = array(
      $res[3] & 0xffff,
      $res[2] & 0xffff,
      $res[1] & 0xffff,
      $res[0] & 0xffff,
    );
    if (count($res) > 4) {
      $return->overflow = $res[4] & 0xffff;
    }
    $return->unsignedInt = $this->unsignedInt;
    return $return;
  }

  /**
   * @param ParagonIE_Sodium_Core32_Int64 $right
   * @return ParagonIE_Sodium_Core32_Int64
   */
  public function mulInt64Fast(ParagonIE_Sodium_Core32_Int64 $right) {
    $aNeg = $this->limbs[0] >> 15 & 1;
    $bNeg = $right->limbs[0] >> 15 & 1;
    $a = array_reverse($this->limbs);
    $b = array_reverse($right->limbs);
    if ($aNeg) {
      for ($i = 0; $i < 4; ++$i) {
        $a[$i] = ($a[$i] ^ 0xffff) & 0xffff;
      }
      ++$a[0];
    }
    if ($bNeg) {
      for ($i = 0; $i < 4; ++$i) {
        $b[$i] = ($b[$i] ^ 0xffff) & 0xffff;
      }
      ++$b[0];
    }
    $res = $this
      ->multiplyLong($a, $b);
    if ($aNeg !== $bNeg) {
      if ($aNeg !== $bNeg) {
        for ($i = 0; $i < 4; ++$i) {
          $res[$i] = ($res[$i] ^ 0xffff) & 0xffff;
        }
        $c = 1;
        for ($i = 0; $i < 4; ++$i) {
          $res[$i] += $c;
          $c = $res[$i] >> 16;
          $res[$i] &= 0xffff;
        }
      }
    }
    $return = new ParagonIE_Sodium_Core32_Int64();
    $return->limbs = array(
      $res[3] & 0xffff,
      $res[2] & 0xffff,
      $res[1] & 0xffff,
      $res[0] & 0xffff,
    );
    if (count($res) > 4) {
      $return->overflow = $res[4];
    }
    return $return;
  }

  /**
   * @param ParagonIE_Sodium_Core32_Int64 $int
   * @param int $size
   * @return ParagonIE_Sodium_Core32_Int64
   * @throws SodiumException
   * @throws TypeError
   * @psalm-suppress MixedAssignment
   */
  public function mulInt64(ParagonIE_Sodium_Core32_Int64 $int, $size = 0) {
    if (ParagonIE_Sodium_Compat::$fastMult) {
      return $this
        ->mulInt64Fast($int);
    }
    ParagonIE_Sodium_Core32_Util::declareScalarType($size, 'int', 2);
    if (!$size) {
      $size = 63;
    }
    list($a, $b) = self::ctSelect($this, $int);
    $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) {
      $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;
      $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;
      $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;
  }

  /**
   * OR this 64-bit integer with another.
   *
   * @param ParagonIE_Sodium_Core32_Int64 $b
   * @return ParagonIE_Sodium_Core32_Int64
   */
  public function orInt64(ParagonIE_Sodium_Core32_Int64 $b) {
    $return = new ParagonIE_Sodium_Core32_Int64();
    $return->unsignedInt = $this->unsignedInt;
    $return->limbs = array(
      (int) ($this->limbs[0] | $b->limbs[0]),
      (int) ($this->limbs[1] | $b->limbs[1]),
      (int) ($this->limbs[2] | $b->limbs[2]),
      (int) ($this->limbs[3] | $b->limbs[3]),
    );
    return $return;
  }

  /**
   * @param int $c
   * @return ParagonIE_Sodium_Core32_Int64
   * @throws SodiumException
   * @throws TypeError
   * @psalm-suppress MixedArrayAccess
   */
  public function rotateLeft($c = 0) {
    ParagonIE_Sodium_Core32_Util::declareScalarType($c, 'int', 1);

    /** @var int $c */
    $c = (int) $c;
    $return = new ParagonIE_Sodium_Core32_Int64();
    $return->unsignedInt = $this->unsignedInt;
    $c &= 63;
    if ($c === 0) {

      // NOP, but we want a copy.
      $return->limbs = $this->limbs;
    }
    else {

      /** @var array<int, int> $limbs */
      $limbs =& $return->limbs;

      /** @var array<int, int> $myLimbs */
      $myLimbs =& $this->limbs;

      /** @var int $idx_shift */
      $idx_shift = $c >> 4 & 3;

      /** @var int $sub_shift */
      $sub_shift = $c & 15;
      for ($i = 3; $i >= 0; --$i) {

        /** @var int $j */
        $j = $i + $idx_shift & 3;

        /** @var int $k */
        $k = $i + $idx_shift + 1 & 3;
        $limbs[$i] = (int) (((int) $myLimbs[$j] << $sub_shift | (int) $myLimbs[$k] >> 16 - $sub_shift) & 0xffff);
      }
    }
    return $return;
  }

  /**
   * Rotate to the right
   *
   * @param int $c
   * @return ParagonIE_Sodium_Core32_Int64
   * @throws SodiumException
   * @throws TypeError
   * @psalm-suppress MixedArrayAccess
   */
  public function rotateRight($c = 0) {
    ParagonIE_Sodium_Core32_Util::declareScalarType($c, 'int', 1);

    /** @var int $c */
    $c = (int) $c;

    /** @var ParagonIE_Sodium_Core32_Int64 $return */
    $return = new ParagonIE_Sodium_Core32_Int64();
    $return->unsignedInt = $this->unsignedInt;
    $c &= 63;

    /** @var int $c */
    if ($c === 0) {

      // NOP, but we want a copy.
      $return->limbs = $this->limbs;
    }
    else {

      /** @var array<int, int> $limbs */
      $limbs =& $return->limbs;

      /** @var array<int, int> $myLimbs */
      $myLimbs =& $this->limbs;

      /** @var int $idx_shift */
      $idx_shift = $c >> 4 & 3;

      /** @var int $sub_shift */
      $sub_shift = $c & 15;
      for ($i = 3; $i >= 0; --$i) {

        /** @var int $j */
        $j = $i - $idx_shift & 3;

        /** @var int $k */
        $k = $i - $idx_shift - 1 & 3;
        $limbs[$i] = (int) (((int) $myLimbs[$j] >> (int) $sub_shift | (int) $myLimbs[$k] << 16 - (int) $sub_shift) & 0xffff);
      }
    }
    return $return;
  }

  /**
   * @param int $c
   * @return ParagonIE_Sodium_Core32_Int64
   * @throws SodiumException
   * @throws TypeError
   */
  public function shiftLeft($c = 0) {
    ParagonIE_Sodium_Core32_Util::declareScalarType($c, 'int', 1);

    /** @var int $c */
    $c = (int) $c;
    $return = new ParagonIE_Sodium_Core32_Int64();
    $return->unsignedInt = $this->unsignedInt;
    $c &= 63;
    if ($c >= 16) {
      if ($c >= 48) {
        $return->limbs = array(
          $this->limbs[3],
          0,
          0,
          0,
        );
      }
      elseif ($c >= 32) {
        $return->limbs = array(
          $this->limbs[2],
          $this->limbs[3],
          0,
          0,
        );
      }
      else {
        $return->limbs = array(
          $this->limbs[1],
          $this->limbs[2],
          $this->limbs[3],
          0,
        );
      }
      return $return
        ->shiftLeft($c & 15);
    }
    if ($c === 0) {
      $return->limbs = $this->limbs;
    }
    elseif ($c < 0) {

      /** @var int $c */
      return $this
        ->shiftRight(-$c);
    }
    else {
      if (!is_int($c)) {
        throw new TypeError();
      }

      /** @var int $carry */
      $carry = 0;
      for ($i = 3; $i >= 0; --$i) {

        /** @var int $tmp */
        $tmp = $this->limbs[$i] << $c | $carry & 0xffff;
        $return->limbs[$i] = (int) ($tmp & 0xffff);

        /** @var int $carry */
        $carry = $tmp >> 16;
      }
    }
    return $return;
  }

  /**
   * @param int $c
   * @return ParagonIE_Sodium_Core32_Int64
   * @throws SodiumException
   * @throws TypeError
   */
  public function shiftRight($c = 0) {
    ParagonIE_Sodium_Core32_Util::declareScalarType($c, 'int', 1);
    $c = (int) $c;

    /** @var int $c */
    $return = new ParagonIE_Sodium_Core32_Int64();
    $return->unsignedInt = $this->unsignedInt;
    $c &= 63;
    $negative = -($this->limbs[0] >> 15 & 1);
    if ($c >= 16) {
      if ($c >= 48) {
        $return->limbs = array(
          (int) ($negative & 0xffff),
          (int) ($negative & 0xffff),
          (int) ($negative & 0xffff),
          (int) $this->limbs[0],
        );
      }
      elseif ($c >= 32) {
        $return->limbs = array(
          (int) ($negative & 0xffff),
          (int) ($negative & 0xffff),
          (int) $this->limbs[0],
          (int) $this->limbs[1],
        );
      }
      else {
        $return->limbs = array(
          (int) ($negative & 0xffff),
          (int) $this->limbs[0],
          (int) $this->limbs[1],
          (int) $this->limbs[2],
        );
      }
      return $return
        ->shiftRight($c & 15);
    }
    if ($c === 0) {
      $return->limbs = $this->limbs;
    }
    elseif ($c < 0) {
      return $this
        ->shiftLeft(-$c);
    }
    else {
      if (!is_int($c)) {
        throw new TypeError();
      }

      /** @var int $carryRight */
      $carryRight = $negative & 0xffff;
      $mask = (int) ((1 << $c + 1) - 1 & 0xffff);
      for ($i = 0; $i < 4; ++$i) {
        $return->limbs[$i] = (int) (($this->limbs[$i] >> $c | $carryRight << 16 - $c) & 0xffff);
        $carryRight = (int) ($this->limbs[$i] & $mask);
      }
    }
    return $return;
  }

  /**
   * Subtract a normal integer from an int64 object.
   *
   * @param int $int
   * @return ParagonIE_Sodium_Core32_Int64
   * @throws SodiumException
   * @throws TypeError
   */
  public function subInt($int) {
    ParagonIE_Sodium_Core32_Util::declareScalarType($int, 'int', 1);
    $int = (int) $int;
    $return = new ParagonIE_Sodium_Core32_Int64();
    $return->unsignedInt = $this->unsignedInt;

    /** @var int $carry */
    $carry = 0;
    for ($i = 3; $i >= 0; --$i) {

      /** @var int $tmp */
      $tmp = $this->limbs[$i] - ($int >> 16 & 0xffff) + $carry;

      /** @var int $carry */
      $carry = $tmp >> 16;
      $return->limbs[$i] = (int) ($tmp & 0xffff);
    }
    return $return;
  }

  /**
   * The difference between two Int64 objects.
   *
   * @param ParagonIE_Sodium_Core32_Int64 $b
   * @return ParagonIE_Sodium_Core32_Int64
   */
  public function subInt64(ParagonIE_Sodium_Core32_Int64 $b) {
    $return = new ParagonIE_Sodium_Core32_Int64();
    $return->unsignedInt = $this->unsignedInt;

    /** @var int $carry */
    $carry = 0;
    for ($i = 3; $i >= 0; --$i) {

      /** @var int $tmp */
      $tmp = $this->limbs[$i] - $b->limbs[$i] + $carry;

      /** @var int $carry */
      $carry = $tmp >> 16;
      $return->limbs[$i] = (int) ($tmp & 0xffff);
    }
    return $return;
  }

  /**
   * XOR this 64-bit integer with another.
   *
   * @param ParagonIE_Sodium_Core32_Int64 $b
   * @return ParagonIE_Sodium_Core32_Int64
   */
  public function xorInt64(ParagonIE_Sodium_Core32_Int64 $b) {
    $return = new ParagonIE_Sodium_Core32_Int64();
    $return->unsignedInt = $this->unsignedInt;
    $return->limbs = array(
      (int) ($this->limbs[0] ^ $b->limbs[0]),
      (int) ($this->limbs[1] ^ $b->limbs[1]),
      (int) ($this->limbs[2] ^ $b->limbs[2]),
      (int) ($this->limbs[3] ^ $b->limbs[3]),
    );
    return $return;
  }

  /**
   * @param int $low
   * @param int $high
   * @return self
   * @throws SodiumException
   * @throws TypeError
   */
  public static function fromInts($low, $high) {
    ParagonIE_Sodium_Core32_Util::declareScalarType($low, 'int', 1);
    ParagonIE_Sodium_Core32_Util::declareScalarType($high, 'int', 2);
    $high = (int) $high;
    $low = (int) $low;
    return new ParagonIE_Sodium_Core32_Int64(array(
      (int) ($high >> 16 & 0xffff),
      (int) ($high & 0xffff),
      (int) ($low >> 16 & 0xffff),
      (int) ($low & 0xffff),
    ));
  }

  /**
   * @param int $low
   * @return self
   * @throws SodiumException
   * @throws TypeError
   */
  public static function fromInt($low) {
    ParagonIE_Sodium_Core32_Util::declareScalarType($low, 'int', 1);
    $low = (int) $low;
    return new ParagonIE_Sodium_Core32_Int64(array(
      0,
      0,
      (int) ($low >> 16 & 0xffff),
      (int) ($low & 0xffff),
    ));
  }

  /**
   * @return int
   */
  public function toInt() {
    return (int) (($this->limbs[2] & 0xffff) << 16 | $this->limbs[3] & 0xffff);
  }

  /**
   * @param string $string
   * @return self
   * @throws SodiumException
   * @throws TypeError
   */
  public static function fromString($string) {
    ParagonIE_Sodium_Core32_Util::declareScalarType($string, 'string', 1);
    $string = (string) $string;
    if (ParagonIE_Sodium_Core32_Util::strlen($string) !== 8) {
      throw new RangeException('String must be 8 bytes; ' . ParagonIE_Sodium_Core32_Util::strlen($string) . ' given.');
    }
    $return = new ParagonIE_Sodium_Core32_Int64();
    $return->limbs[0] = (int) ((ParagonIE_Sodium_Core32_Util::chrToInt($string[0]) & 0xff) << 8);
    $return->limbs[0] |= ParagonIE_Sodium_Core32_Util::chrToInt($string[1]) & 0xff;
    $return->limbs[1] = (int) ((ParagonIE_Sodium_Core32_Util::chrToInt($string[2]) & 0xff) << 8);
    $return->limbs[1] |= ParagonIE_Sodium_Core32_Util::chrToInt($string[3]) & 0xff;
    $return->limbs[2] = (int) ((ParagonIE_Sodium_Core32_Util::chrToInt($string[4]) & 0xff) << 8);
    $return->limbs[2] |= ParagonIE_Sodium_Core32_Util::chrToInt($string[5]) & 0xff;
    $return->limbs[3] = (int) ((ParagonIE_Sodium_Core32_Util::chrToInt($string[6]) & 0xff) << 8);
    $return->limbs[3] |= ParagonIE_Sodium_Core32_Util::chrToInt($string[7]) & 0xff;
    return $return;
  }

  /**
   * @param string $string
   * @return self
   * @throws SodiumException
   * @throws TypeError
   */
  public static function fromReverseString($string) {
    ParagonIE_Sodium_Core32_Util::declareScalarType($string, 'string', 1);
    $string = (string) $string;
    if (ParagonIE_Sodium_Core32_Util::strlen($string) !== 8) {
      throw new RangeException('String must be 8 bytes; ' . ParagonIE_Sodium_Core32_Util::strlen($string) . ' given.');
    }
    $return = new ParagonIE_Sodium_Core32_Int64();
    $return->limbs[0] = (int) ((ParagonIE_Sodium_Core32_Util::chrToInt($string[7]) & 0xff) << 8);
    $return->limbs[0] |= ParagonIE_Sodium_Core32_Util::chrToInt($string[6]) & 0xff;
    $return->limbs[1] = (int) ((ParagonIE_Sodium_Core32_Util::chrToInt($string[5]) & 0xff) << 8);
    $return->limbs[1] |= ParagonIE_Sodium_Core32_Util::chrToInt($string[4]) & 0xff;
    $return->limbs[2] = (int) ((ParagonIE_Sodium_Core32_Util::chrToInt($string[3]) & 0xff) << 8);
    $return->limbs[2] |= ParagonIE_Sodium_Core32_Util::chrToInt($string[2]) & 0xff;
    $return->limbs[3] = (int) ((ParagonIE_Sodium_Core32_Util::chrToInt($string[1]) & 0xff) << 8);
    $return->limbs[3] |= ParagonIE_Sodium_Core32_Util::chrToInt($string[0]) & 0xff;
    return $return;
  }

  /**
   * @return array<int, int>
   */
  public function toArray() {
    return array(
      (int) (($this->limbs[0] & 0xffff) << 16 | $this->limbs[1] & 0xffff),
      (int) (($this->limbs[2] & 0xffff) << 16 | $this->limbs[3] & 0xffff),
    );
  }

  /**
   * @return ParagonIE_Sodium_Core32_Int32
   */
  public function toInt32() {
    $return = new ParagonIE_Sodium_Core32_Int32();
    $return->limbs[0] = (int) $this->limbs[2];
    $return->limbs[1] = (int) $this->limbs[3];
    $return->unsignedInt = $this->unsignedInt;
    $return->overflow = (int) (ParagonIE_Sodium_Core32_Util::abs($this->limbs[1], 16) & 0xffff);
    return $return;
  }

  /**
   * @return ParagonIE_Sodium_Core32_Int64
   */
  public function toInt64() {
    $return = new ParagonIE_Sodium_Core32_Int64();
    $return->limbs[0] = (int) $this->limbs[0];
    $return->limbs[1] = (int) $this->limbs[1];
    $return->limbs[2] = (int) $this->limbs[2];
    $return->limbs[3] = (int) $this->limbs[3];
    $return->unsignedInt = $this->unsignedInt;
    $return->overflow = ParagonIE_Sodium_Core32_Util::abs($this->overflow);
    return $return;
  }

  /**
   * @param bool $bool
   * @return self
   */
  public function setUnsignedInt($bool = false) {
    $this->unsignedInt = !empty($bool);
    return $this;
  }

  /**
   * @return string
   * @throws TypeError
   */
  public function toString() {
    return ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[0] >> 8 & 0xff) . ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[0] & 0xff) . ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[1] >> 8 & 0xff) . ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[1] & 0xff) . ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[2] >> 8 & 0xff) . ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[2] & 0xff) . ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[3] >> 8 & 0xff) . ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[3] & 0xff);
  }

  /**
   * @return string
   * @throws TypeError
   */
  public function toReverseString() {
    return ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[3] & 0xff) . ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[3] >> 8 & 0xff) . ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[2] & 0xff) . ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[2] >> 8 & 0xff) . ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[1] & 0xff) . ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[1] >> 8 & 0xff) . ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[0] & 0xff) . ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[0] >> 8 & 0xff);
  }

  /**
   * @return string
   */
  public function __toString() {
    try {
      return $this
        ->toString();
    } catch (TypeError $ex) {

      // PHP engine can't handle exceptions from __toString()
      return '';
    }
  }

}

Members

Namesort descending Modifiers Type Description Overrides
ParagonIE_Sodium_Core32_Int64::$limbs public property
ParagonIE_Sodium_Core32_Int64::$overflow public property
ParagonIE_Sodium_Core32_Int64::$unsignedInt public property
ParagonIE_Sodium_Core32_Int64::addInt public function Adds a normal integer to an int64 object
ParagonIE_Sodium_Core32_Int64::addInt64 public function Adds two int64 objects
ParagonIE_Sodium_Core32_Int64::compareInt public function
ParagonIE_Sodium_Core32_Int64::ctSelect public static function @psalm-suppress MixedInferredReturnType
ParagonIE_Sodium_Core32_Int64::fromInt public static function
ParagonIE_Sodium_Core32_Int64::fromInts public static function
ParagonIE_Sodium_Core32_Int64::fromReverseString public static function
ParagonIE_Sodium_Core32_Int64::fromString public static function
ParagonIE_Sodium_Core32_Int64::isGreaterThan public function
ParagonIE_Sodium_Core32_Int64::isLessThanInt public function
ParagonIE_Sodium_Core32_Int64::mask64 public function
ParagonIE_Sodium_Core32_Int64::mulInt public function @psalm-suppress MixedAssignment
ParagonIE_Sodium_Core32_Int64::mulInt64 public function @psalm-suppress MixedAssignment
ParagonIE_Sodium_Core32_Int64::mulInt64Fast public function
ParagonIE_Sodium_Core32_Int64::mulIntFast public function
ParagonIE_Sodium_Core32_Int64::multiplyLong public function
ParagonIE_Sodium_Core32_Int64::orInt64 public function OR this 64-bit integer with another.
ParagonIE_Sodium_Core32_Int64::rotateLeft public function @psalm-suppress MixedArrayAccess
ParagonIE_Sodium_Core32_Int64::rotateRight public function Rotate to the right
ParagonIE_Sodium_Core32_Int64::setUnsignedInt public function
ParagonIE_Sodium_Core32_Int64::shiftLeft public function
ParagonIE_Sodium_Core32_Int64::shiftRight public function
ParagonIE_Sodium_Core32_Int64::subInt public function Subtract a normal integer from an int64 object.
ParagonIE_Sodium_Core32_Int64::subInt64 public function The difference between two Int64 objects.
ParagonIE_Sodium_Core32_Int64::toArray public function
ParagonIE_Sodium_Core32_Int64::toInt public function
ParagonIE_Sodium_Core32_Int64::toInt32 public function
ParagonIE_Sodium_Core32_Int64::toInt64 public function
ParagonIE_Sodium_Core32_Int64::toReverseString public function
ParagonIE_Sodium_Core32_Int64::toString public function
ParagonIE_Sodium_Core32_Int64::xorInt64 public function XOR this 64-bit integer with another.
ParagonIE_Sodium_Core32_Int64::__construct public function ParagonIE_Sodium_Core32_Int64 constructor.
ParagonIE_Sodium_Core32_Int64::__toString public function