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; }
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); }