예제 #1
0
 function biBarrettMu($m)
 {
     $this->modulus = biCopy($m);
     $this->k = biHighIndex($this->modulus) + 1;
     $b2k = new BigInt();
     $b2k->digits[2 * $this->k] = 1;
     // b2k = b^(2k)
     $this->mu = biDivide($b2k, $this->modulus);
     $this->bkplus1 = new BigInt();
     $this->bkplus1->digits[$this->k + 1] = 1;
     // bkplus1 = b^(k+1)
     //$this->modulo = BarrettMu_modulo;
     //$this->multiplyMod = BarrettMu_multiplyMod;
     //this.powMod = BarrettMu_powMod;
 }
예제 #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);
}