function NativeCalculator::doSub
Performs the subtraction of two non-signed large integers.
1 call to NativeCalculator::doSub()
- NativeCalculator::add in vendor/
brick/ math/ src/ Internal/ Calculator/ NativeCalculator.php - Adds two numbers.
File
-
vendor/
brick/ math/ src/ Internal/ Calculator/ NativeCalculator.php, line 324
Class
- NativeCalculator
- Calculator implementation using only native PHP code.
Namespace
Brick\Math\Internal\CalculatorCode
private function doSub(string $a, string $b) : string {
if ($a === $b) {
return '0';
}
// Ensure that we always subtract to a positive result: biggest minus smallest.
$cmp = $this->doCmp($a, $b);
$invert = $cmp === -1;
if ($invert) {
$c = $a;
$a = $b;
$b = $c;
}
[
$a,
$b,
$length,
] = $this->pad($a, $b);
$carry = 0;
$result = '';
$complement = 10 ** $this->maxDigits;
for ($i = $length - $this->maxDigits;; $i -= $this->maxDigits) {
$blockLength = $this->maxDigits;
if ($i < 0) {
$blockLength += $i;
/** @psalm-suppress LoopInvalidation */
$i = 0;
}
/** @psalm-var numeric-string $blockA */
$blockA = \substr($a, $i, $blockLength);
/** @psalm-var numeric-string $blockB */
$blockB = \substr($b, $i, $blockLength);
$sum = $blockA - $blockB - $carry;
if ($sum < 0) {
$sum += $complement;
$carry = 1;
}
else {
$carry = 0;
}
$sum = (string) $sum;
$sumLength = \strlen($sum);
if ($sumLength < $blockLength) {
$sum = \str_repeat('0', $blockLength - $sumLength) . $sum;
}
$result = $sum . $result;
if ($i === 0) {
break;
}
}
// Carry cannot be 1 when the loop ends, as a > b
assert($carry === 0);
$result = \ltrim($result, '0');
if ($invert) {
$result = $this->neg($result);
}
return $result;
}