Ejemplo n.º 1
0
 function modulo($x)
 {
     $q1 = biDivideByRadixPower($x, $this->k - 1);
     $q2 = biMultiply($q1, $this->mu);
     $q3 = biDivideByRadixPower($q2, $this->k + 1);
     $r1 = biModuloByRadixPower($x, $this->k + 1);
     $r2term = biMultiply($q3, $this->modulus);
     $r2 = biModuloByRadixPower($r2term, $this->k + 1);
     $r = biSubtract($r1, $r2);
     if ($r->isNeg) {
         $r = biAdd($r, $this->bkplus1);
     }
     $rgtem = biCompare($r, $this->modulus) >= 0 ? 1 : 0;
     while ($rgtem) {
         $r = biSubtract($r, $this->modulus);
         $rgtem = biCompare($r, $this->modulus) >= 0 ? 1 : 0;
     }
     return $r;
 }
Ejemplo n.º 2
0
function biDivideModulo($x, $y)
{
    global $biRadixBase, $biRadixBits, $biBitsPerDigit, $biRadix, $biHalfRadix, $biRadixSquared, $biMaxDigitVal, $biMaxInteger, $biMaxDigits, $biZERO_ARRAY, $biBigZero, $biBigOne, $dpl10, $lr10;
    $nb = biNumBits($x);
    $nh = biHighIndex($x);
    $tb = biNumBits($y);
    $th = biHighIndex($y);
    $origXIsNeg = $x->isNeg ? 1 : 0;
    $origYIsNeg = $y->isNeg ? 1 : 0;
    $origX = $x;
    $origY = $y;
    $q;
    $r;
    if ($nb < $tb || $nb == $tb && biCompareModule($x, $y) < 0) {
        // |x| < |y|
        if ($x->isNeg && $y->isNeg xor !$x->isNeg && !$y->isNeg) {
            $q = new BigInt();
            $r = biCopy($x);
        } else {
            $q = new BigInt();
            $q->digits[0] = 1;
            $q->isNeg = 1;
            $r = biAdd($y, $x);
        }
        return array($q, $r);
    }
    $q = new BigInt();
    $x = biCopy($x);
    $x->isNeg = 0;
    $r = $x;
    $y = biCopy($y);
    $y->isNeg = 0;
    // Normalize Y.
    $t = ceil($tb / $biBitsPerDigit) - 1;
    $lambda = 0;
    while ($y->digits[$t] < $biHalfRadix) {
        $y = biShiftLeft($y, 1);
        ++$lambda;
        ++$tb;
        $t = intval(ceil($tb / $biBitsPerDigit)) - 1;
    }
    // Shift r over to keep the quotient constant. We'll shift the
    // remainder back at the end.
    $r = biShiftLeft($r, $lambda);
    $nb += $lambda;
    // Update the bit count for x.
    $n = intval(ceil($nb / $biBitsPerDigit)) - 1;
    $b = biMultiplyByRadixPower($y, $n - $t);
    while (biCompare($r, $b) != -1) {
        $q->digits[$n - $t] += 1;
        $r = biSubtract($r, $b);
    }
    for ($i = $n; $i > $t; --$i) {
        $ri = $i >= count($r->digits) ? 0 : $r->digits[$i];
        $ri1 = $i - 1 >= count($r->digits) ? 0 : $r->digits[$i - 1];
        $ri2 = $i - 2 >= count($r->digits) || $i - 2 < 0 ? 0 : $r->digits[$i - 2];
        $yt = $t >= count($y->digits) ? 0 : $y->digits[$t];
        $yt1 = $t - 1 >= count($y->digits) || $t - 1 < 0 ? 0 : $y->digits[$t - 1];
        if ($ri == $yt) {
            $q->digits[$i - $t - 1] = $biMaxDigitVal;
        } else {
            $q->digits[$i - $t - 1] = intval(floor(($ri * $biRadix + $ri1) / $yt));
        }
        $c1 = $q->digits[$i - $t - 1] * ($yt * $biRadix + $yt1);
        $c2 = $ri * $biRadixSquared + ($ri1 * $biRadix + $ri2);
        while ($c1 > $c2) {
            $q->digits[$i - $t - 1] -= 1;
            $c1 = $q->digits[$i - $t - 1] * ($yt * $biRadix | $yt1);
            $c2 = $ri * $biRadix * $biRadix + ($ri1 * $biRadix + $ri2);
        }
        $b = biMultiplyByRadixPower($y, $i - $t - 1);
        $r = biSubtract($r, biMultiplyDigit($b, $q->digits[$i - $t - 1]));
        if ($r->isNeg) {
            $r = biAdd($r, $b);
            $q->digits[$i - $t - 1] -= 1;
        }
    }
    $r = biShiftRight($r, $lambda);
    // Fiddle with the signs and stuff to make sure that 0 <= r < y.
    /*$q->isNeg = ($x->isNeg != $origYIsNeg) ? 1 : 0;
    	if ($x->isNeg) {
    		if ($origYIsNeg) {
    			$q = biAdd($q, $biBigOne);
    		} else {
    			$q = biSubtract($q, $biBigOne);
    		}
    		$y = biShiftRight($y, $lambda);
    		$r = biSubtract($y, $r);
    	}*/
    // Check for the unbelievably stupid degenerate case of r == -0.
    /*
    $origXIsNeg = $x->isNeg ? 1 : 0;
    $origYIsNeg = $y->isNeg ? 1 : 0;
    if ($nb < $tb  || ($nb == $tb && biCompareModule($x, $y) < 0)) {
    	// |x| < |y|
    	if (($x->isNeg && $y->isNeg) xor (!$x->isNeg && !$y->isNeg)){
    		$q = new BigInt();
    		$r= biCopy($x);
    	}else {
    		$q = new BigInt();
    		$q->digits[0] = 1;
    		$q->isNeg = 1;
    		$r = biAdd($y, $x);
    	}
    	return array($q, $r);
    }
    */
    if (!$origXIsNeg && !$origYIsNeg) {
        return array($q, $r);
    } elseif ($origXIsNeg && $origYIsNeg) {
        $r->isNeg = 1;
        return array($q, $r);
    } else {
        $q->isNeg = 1;
        $q = biSubtract($q, $biBigOne);
        $r->isNeg = $origXIsNeg;
        $r = biAdd($r, $origY);
    }
    if ($r->digits[0] == 0 && biHighIndex($r) == 0) {
        $r->isNeg = 0;
    }
    return array($q, $r);
}