function bdiv($x, $y) { global $bs; global $bx2; global $bm; global $bx; global $bd; global $bdm; $n = count($x) - 1; $t = count($y) - 1; $nmt = $n - $t; if ($n < $t || $n == $t && ($x[$n] < $y[$n] || $n > 0 && $x[$n] == $y[$n] && $x[$n - 1] < $y[$n - 1])) { $this->q = array(0); $this->mod = array($x); return; } if ($n == $t && toppart($x, $t, 2) / toppart($y, $t, 2) < 4) { $qq = 0; $xx = 0; for (;;) { $xx = bsub($x, $y); if (count($xx) == 0) { break; } $x = $xx; $qq++; } $this->q = array($qq); $this->mod = $x; return; } $shift2 = floor(log($y[$t]) / M_LN2) + 1; $shift = $bs - $shift2; if ($shift) { $x = array_merge((array) $x); $y = array_merge((array) $y); for ($i = $t; $i > 0; $i--) { $y[$i] = $y[$i] << $shift & $bm | $y[$i - 1] >> $shift2; } $y[0] = $y[0] << $shift & $bm; if ($x[$n] & ($bm << $shift2 & $bm)) { $x[++$n] = 0; $nmt++; } for ($i = $n; $i > 0; $i--) { $x[$i] = $x[$i] << $shift & $bm | $x[$i - 1] >> $shift2; } $x[0] = $x[0] << $shift & $bm; } $i = 0; $j = 0; $x2 = 0; $q = zeros($nmt + 1); $y2 = array_merge(zeros($nmt), (array) $y); for (;;) { $x2 = bsub($x, $y2); if (count($x2) == 0) { break; } $q[$nmt]++; $x = $x2; } $yt = $y[$t]; $top = toppart($y, $t, 2); for ($i = $n; $i > $t; $i--) { $m = $i - $t - 1; if ($i >= count($x)) { $q[$m] = 1; } else { if ($x[$i] == $yt) { $q[$m] = $bm; } else { $q[$m] = floor(toppart($x, $i, 2) / $yt); } } $topx = toppart($x, $i, 3); while ($q[$m] * $top > $topx) { $q[$m]--; } $y2 = array_slice($y2, 1); $x2 = bsub($x, bmul(array($q[$m]), $y2)); if (count($x2) == 0) { $q[$m]--; $x2 = bsub($x, bmul(array($q[m]), $y2)); } $x = $x2; } if ($shift) { for ($i = 0; $i < count($x) - 1; $i++) { $x[$i] = $x[$i] >> $shift | $x[$i + 1] << $shift2 & $bm; } $x[count($x) - 1] >>= $shift; } $n = count($q); while ($n > 1 && $q[$n - 1] == 0) { $n--; } $this->q = array_slice($q, 0, $n); $n = count($x); while ($n > 1 && $x[$n - 1] == 0) { $n--; } $this->mod = array_slice($x, 0, $n); }
/** * @param $x * @param $m * @param $mu * @return array */ function bmod2($x, $m, $mu) { $xl = count($x) - (count($m) << 1); if ($xl > 0) { return bmod2(array_concat(array_slice($x, 0, $xl), bmod2(array_slice($x, $xl), $m, $mu)), $m, $mu); } $ml1 = count($m) + 1; $ml2 = count($m) - 1; $q3 = array_slice(bmul(array_slice($x, $ml2), $mu), $ml1); $r1 = array_slice($x, 0, $ml1); $r2 = array_slice(bmul($q3, $m), 0, $ml1); $r = bsub($r1, $r2); if (count($r) == 0) { $r1[$ml1] = 1; $r = bsub($r1, $r2); } for ($n = 0;; $n++) { $rr = bsub($r, $m); if (count($rr) == 0) { break; } $r = $rr; if ($n >= 3) { return bmod2($r, $m, $mu); } } return $r; }