/** * Performs long multiplication up to $stop digits * * If you're going to be doing array_slice($product->value, 0, $stop), some cycles can be saved. * * @see _barrett() * @param Math_BigInteger $x * @return Math_BigInteger * @access private */ function _multiplyLower($x, $stop) { $this_length = count($this->value); $x_length = count($x->value); if (!$this_length || !$x_length) { // a 0 is being multiplied return new Math_BigInteger(); } if ($this_length < $x_length) { return $x->_multiplyLower($this, $stop); } $product = new Math_BigInteger(); $product->value = $this->_array_repeat(0, $this_length + $x_length); // the following for loop could be removed if the for loop following it // (the one with nested for loops) initially set $i to 0, but // doing so would also make the result in one set of unnecessary adds, // since on the outermost loops first pass, $product->value[$k] is going // to always be 0 $carry = 0; for ($j = 0; $j < $this_length; $j++) { // ie. $i = 0, $k = $i $temp = $this->value[$j] * $x->value[0] + $carry; // $product->value[$k] == 0 $carry = floor($temp / 0x4000000); $product->value[$j] = $temp - 0x4000000 * $carry; } if ($j < $stop) { $product->value[$j] = $carry; } // the above for loop is what the previous comment was talking about. the // following for loop is the "one with nested for loops" for ($i = 1; $i < $x_length; $i++) { $carry = 0; for ($j = 0, $k = $i; $j < $this_length && $k < $stop; $j++, $k++) { $temp = $product->value[$k] + $this->value[$j] * $x->value[$i] + $carry; $carry = floor($temp / 0x4000000); $product->value[$k] = $temp - 0x4000000 * $carry; } if ($k < $stop) { $product->value[$k] = $carry; } } $product->is_negative = $this->is_negative != $x->is_negative; return $product; }