Exemplo n.º 1
0
 /**
  * Calculates the greatest common divisor and Bezout's identity.
  *
  * Say you have 693 and 609.  The GCD is 21.  Bezout's identity states that there exist integers x and y such that
  * 693*x + 609*y == 21.  In point of fact, there are actually an infinite number of x and y combinations and which
  * combination is returned is dependant upon which mode is in use.  See
  * {@link http://en.wikipedia.org/wiki/B%C3%A9zout%27s_identity Bezout's identity - Wikipedia} for more information.
  *
  * Here's an example:
  * <code>
  * <?php
  *    include 'Math/BigInteger.php';
  *
  *    $a = new Math_BigInteger(693);
  *    $b = new Math_BigInteger(609);
  *
  *    extract($a->extendedGCD($b));
  *
  *    echo $gcd->toString() . "\r\n"; // outputs 21
  *    echo $a->toString() * $x->toString() + $b->toString() * $y->toString(); // outputs 21
  * ?>
  * </code>
  *
  * @param Math_BigInteger $n
  * @return Math_BigInteger
  * @access public
  * @internal Calculates the GCD using the binary xGCD algorithim described in
  *    {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=19 HAC 14.61}.  As the text above 14.61 notes,
  *    the more traditional algorithim requires "relatively costly multiple-precision divisions".
  */
 function extendedGCD($n)
 {
     switch (MATH_BIGINTEGER_MODE) {
         case MATH_BIGINTEGER_MODE_GMP:
             extract(gmp_gcdext($this->value, $n->value));
             return array('gcd' => $this->_normalize(new Math_BigInteger($g)), 'x' => $this->_normalize(new Math_BigInteger($s)), 'y' => $this->_normalize(new Math_BigInteger($t)));
         case MATH_BIGINTEGER_MODE_BCMATH:
             // it might be faster to use the binary xGCD algorithim here, as well, but (1) that algorithim works
             // best when the base is a power of 2 and (2) i don't think it'd make much difference, anyway.  as is,
             // the basic extended euclidean algorithim is what we're using.
             $u = $this->value;
             $v = $n->value;
             $a = '1';
             $b = '0';
             $c = '0';
             $d = '1';
             while (bccomp($v, '0', 0) != 0) {
                 $q = bcdiv($u, $v, 0);
                 $temp = $u;
                 $u = $v;
                 $v = bcsub($temp, bcmul($v, $q, 0), 0);
                 $temp = $a;
                 $a = $c;
                 $c = bcsub($temp, bcmul($a, $q, 0), 0);
                 $temp = $b;
                 $b = $d;
                 $d = bcsub($temp, bcmul($b, $q, 0), 0);
             }
             return array('gcd' => $this->_normalize(new Math_BigInteger($u)), 'x' => $this->_normalize(new Math_BigInteger($a)), 'y' => $this->_normalize(new Math_BigInteger($b)));
     }
     $y = $n->copy();
     $x = $this->copy();
     $g = new Math_BigInteger();
     $g->value = array(1);
     while (!($x->value[0] & 1 || $y->value[0] & 1)) {
         $x->_rshift(1);
         $y->_rshift(1);
         $g->_lshift(1);
     }
     $u = $x->copy();
     $v = $y->copy();
     $a = new Math_BigInteger();
     $b = new Math_BigInteger();
     $c = new Math_BigInteger();
     $d = new Math_BigInteger();
     $a->value = $d->value = $g->value = array(1);
     $b->value = $c->value = array();
     while (!empty($u->value)) {
         while (!($u->value[0] & 1)) {
             $u->_rshift(1);
             if (!empty($a->value) && $a->value[0] & 1 || !empty($b->value) && $b->value[0] & 1) {
                 $a = $a->add($y);
                 $b = $b->subtract($x);
             }
             $a->_rshift(1);
             $b->_rshift(1);
         }
         while (!($v->value[0] & 1)) {
             $v->_rshift(1);
             if (!empty($d->value) && $d->value[0] & 1 || !empty($c->value) && $c->value[0] & 1) {
                 $c = $c->add($y);
                 $d = $d->subtract($x);
             }
             $c->_rshift(1);
             $d->_rshift(1);
         }
         if ($u->compare($v) >= 0) {
             $u = $u->subtract($v);
             $a = $a->subtract($c);
             $b = $b->subtract($d);
         } else {
             $v = $v->subtract($u);
             $c = $c->subtract($a);
             $d = $d->subtract($b);
         }
     }
     return array('gcd' => $this->_normalize($g->multiply($v)), 'x' => $this->_normalize($c), 'y' => $this->_normalize($d));
 }
Exemplo n.º 2
0
echo gmp_strval($div1) . "\n";
// gmp_fact
$fact1 = gmp_fact(5);
// 5 * 4 * 3 * 2 * 1
echo gmp_strval($fact1) . "\n";
$fact2 = gmp_fact(50);
// 50 * 49 * 48, ... etc
echo gmp_strval($fact2) . "\n";
// gmp_gcd
$gcd = gmp_gcd("12", "21");
echo gmp_strval($gcd) . "\n";
// gmp_gcdext
$a = gmp_init(12);
$b = gmp_init(21);
$g = gmp_gcd($a, $b);
$r = gmp_gcdext($a, $b);
$check_gcd = gmp_strval($g) == gmp_strval($r['g']);
$eq_res = gmp_add(gmp_mul($a, $r['s']), gmp_mul($b, $r['t']));
$check_res = gmp_strval($g) == gmp_strval($eq_res);
if ($check_gcd && $check_res) {
    $fmt = "Solution: %d*%d + %d*%d = %d\n";
    printf($fmt, gmp_strval($a), gmp_strval($r['s']), gmp_strval($b), gmp_strval($r['t']), gmp_strval($r['g']));
} else {
    echo "Error while solving the equation\n";
}
// gmp_hamdist
$ham1 = gmp_init("1001010011", 2);
$ham2 = gmp_init("1011111100", 2);
echo gmp_hamdist($ham1, $ham2) . "\n";
echo gmp_popcount(gmp_xor($ham1, $ham2)) . "\n";
// gmp_init (although that's probably tested well by now)
Exemplo n.º 3
0
 /**
  * Finds the greatest common denominator of two numbers using the extended
  * Euclidean algorithm.
  *
  * The returned array is ( a0, b0, gcd( a, b ) ), where
  *     a0 * a + b0 * b = gcd( a, b )
  *
  * @param resource $a The first number
  * @param resource $b The second number
  * @return array(resource)
  */
 public function gcd($a, $b)
 {
     $result = gmp_gcdext($a, $b);
     return array($result['s'], $result['t'], $result['g']);
 }
Exemplo n.º 4
0
<?php

$n = gmp_init("34293864345");
$n1 = gmp_init("23434293864345");
$a = array(array(123, 45), array(4341, 9734), array(23487, 333), array(-234234, -123123), array(-100, -2234), array(345, "34587345"), array(345, "0"), array("345556456", 345873), array("34545345556456", "323432445873"), array($n, $n1));
foreach ($a as $val) {
    $r = gmp_gcdext($val[0], $val[1]);
    var_dump(gmp_strval($r['g']));
    var_dump(gmp_strval($r['s']));
    var_dump(gmp_strval($r['t']));
}
var_dump(gmp_gcdext($val[0], array()));
var_dump(gmp_gcdext(array(), array()));
var_dump(gmp_gcdext(array(), array(), 1));
var_dump(gmp_gcdext(array()));
var_dump(gmp_gcdext());
echo "Done\n";
Exemplo n.º 5
0
 public function extendedGCD($n)
 {
     switch (MATH_BIGINTEGER_MODE) {
         case MATH_BIGINTEGER_MODE_GMP:
             $_gmp_gcdext = gmp_gcdext($this->value, $n->value);
             $g = $_gmp_gcdext['g'];
             $s = $_gmp_gcdext['s'];
             $t = $_gmp_gcdext['t'];
             return array('gcd' => $this->_normalize(new Math_BigInteger($g)), 'x' => $this->_normalize(new Math_BigInteger($s)), 'y' => $this->_normalize(new Math_BigInteger($t)));
         case MATH_BIGINTEGER_MODE_BCMATH:
             $u = $this->value;
             $v = $n->value;
             $a = '1';
             $b = '0';
             $c = '0';
             $d = '1';
             while (bccomp($v, '0', 0) != 0) {
                 $q = bcdiv($u, $v, 0);
                 $temp = $u;
                 $u = $v;
                 $v = bcsub($temp, bcmul($v, $q, 0), 0);
                 $temp = $a;
                 $a = $c;
                 $c = bcsub($temp, bcmul($a, $q, 0), 0);
                 $temp = $b;
                 $b = $d;
                 $d = bcsub($temp, bcmul($b, $q, 0), 0);
             }
             return array('gcd' => $this->_normalize(new Math_BigInteger($u)), 'x' => $this->_normalize(new Math_BigInteger($a)), 'y' => $this->_normalize(new Math_BigInteger($b)));
     }
     $y = $n->copy();
     $x = $this->copy();
     $g = new Math_BigInteger();
     $g->value = array(1);
     while (!($x->value[0] & 1 || $y->value[0] & 1)) {
         $x->_rshift(1);
         $y->_rshift(1);
         $g->_lshift(1);
     }
     $u = $x->copy();
     $v = $y->copy();
     $a = new Math_BigInteger();
     $b = new Math_BigInteger();
     $c = new Math_BigInteger();
     $d = new Math_BigInteger();
     $a->value = $d->value = $g->value = array(1);
     $b->value = $c->value = array();
     while (!empty($u->value)) {
         while (!($u->value[0] & 1)) {
             $u->_rshift(1);
             if (!empty($a->value) && $a->value[0] & 1 || !empty($b->value) && $b->value[0] & 1) {
                 $a = $a->add($y);
                 $b = $b->subtract($x);
             }
             $a->_rshift(1);
             $b->_rshift(1);
         }
         while (!($v->value[0] & 1)) {
             $v->_rshift(1);
             if (!empty($d->value) && $d->value[0] & 1 || !empty($c->value) && $c->value[0] & 1) {
                 $c = $c->add($y);
                 $d = $d->subtract($x);
             }
             $c->_rshift(1);
             $d->_rshift(1);
         }
         if (0 <= $u->compare($v)) {
             $u = $u->subtract($v);
             $a = $a->subtract($c);
             $b = $b->subtract($d);
         } else {
             $v = $v->subtract($u);
             $c = $c->subtract($a);
             $d = $d->subtract($b);
         }
     }
     return array('gcd' => $this->_normalize($g->multiply($v)), 'x' => $this->_normalize($c), 'y' => $this->_normalize($d));
 }
Exemplo n.º 6
0
 public static function add(\fpoirotte\Pssht\ECC\Curve $curve, \fpoirotte\Pssht\ECC\Point $P, \fpoirotte\Pssht\ECC\Point $Q)
 {
     $mod = $curve->getModulus();
     $xP = $P->coordinates['x'];
     $yP = $P->coordinates['y'];
     $xQ = $Q->coordinates['x'];
     $yQ = $Q->coordinates['y'];
     if (!gmp_cmp($xP, $xQ) && !gmp_cmp($yP, $yQ)) {
         $alphanum = gmp_add(gmp_mul('3', gmp_pow($xP, '2')), $curve->getA());
         $alphaden = gmp_mul('2', $yP);
     } else {
         $alphanum = gmp_sub($yQ, $yP);
         $alphaden = gmp_sub($xQ, $xP);
     }
     $bezout = gmp_gcdext($alphaden, $mod);
     $alpha = gmp_mod(gmp_mul($alphanum, $bezout['s']), $mod);
     $xR = gmp_sub(gmp_sub(gmp_pow($alpha, '2'), $xP), $xQ);
     $yR = gmp_sub(gmp_mul($alpha, gmp_sub($xP, $xR)), $yP);
     return new static(gmp_mod(gmp_add($xR, $mod), $mod), gmp_mod(gmp_add($yR, $mod), $mod));
 }