Rational number addition

@param NI $a first operand
@param NI $b second operand

@return RationalType
506625
public function rationalAdd(NI $a, NI $b)
    {
        if (!$a instanceof RationalType) {
            $a = $a->asRational();
        }
        if (!$b instanceof RationalType) {
            $b = $b->asRational();
        }

        $d = RationalTypeFactory::create($this->lcm($a->denominator()->get(), $b->denominator()->get()));
        $nn = $this->rationalDiv($this->rationalMul($a->numerator(), $d), $a->denominator())->get();
        $nd = $this->rationalDiv($this->rationalMul($b->numerator(), $d), $b->denominator())->get();
        $n = $this->intAdd(new IntType($nn), new IntType($nd));

        return RationalTypeFactory::create($n, $d->numerator());
    }
1296550
public Rational add(Rational val) {
        BigInteger num = a.multiply(val.b).add(b.multiply(val.a));
        BigInteger deno = b.multiply(val.b);
        return (new Rational(num, deno));
    }
600180
private function unsignedRightShift($a, $b)
    {
        if ($b >= 32 || $b < -32) {
            $m = (int)($b / 32);
            $b = $b - ($m * 32);
        }

        if ($b < 0) {
            $b = 32 + $b;
        }

        if ($b == 0) {
            return (($a >> 1) & 0x7fffffff) * 2 + (($a >> $b) & 1);
        }

        if ($a < 0) {
            $a = ($a >> 1);
            $a &= 2147483647;
            $a |= 0x40000000;
            $a = ($a >> ($b - 1));
        } else { 
            $a = ($a >> $b);
        }

        return $a;
    }
840975
public function rationalPow(RationalType $a, NI $exp)
    {
        if ($exp instanceof ComplexType) {
            $r = $this->floatComplexPow($a(), $exp);
            if ($r instanceof FloatType) {
                return RationalTypeFactory::fromFloat($r());
            }
            return $r;
        }

        $exp2 = $exp->get();
        $numF = pow($a->numerator()->get(), $exp2);
        $denF = pow($a->denominator()->get(), $exp2);
        $numR = RationalTypeFactory::fromFloat($numF);
        $denR = RationalTypeFactory::fromFloat($denF);

        return $this->rationalDiv($numR, $denR);
    }
192706
public static function mod(int $a, int $b) : int
    {
        return ($a % $b) + ($a < 0 ? $b : 0);
    }
1155253
public function compare(DecimalNumber $a, DecimalNumber $b)
    {
        if (function_exists('bccomp')) {
            return $this->compareUsingBcMath($a, $b);
        }

        return $this->compareWithoutBcMath($a, $b);
    }
1227557
public function complexAdd(ComplexType $a, ComplexType $b)
    {
        $r = $this->rationalAdd($a->r(), $b->r());
        $i = $this->rationalAdd($a->i(), $b->i());
        return ComplexTypeFactory::create($r, $i);
    }
743200
protected function complexCompare(ComplexType $a, ComplexType $b)
    {
        if ($a->isReal() && $b->isReal()) {
            return $this->rationalCompare($a->r(), $b->r());
        }

        //hack to get around native php integer limitations
        //what we should be doing here is to return $this->rationalCompare($a->modulus(), $b->modulus())
        //but this blows up because of the big rationals it produces
        $am = $a->modulus()->asFloatType()->get();
        $bm = $b->modulus()->asFloatType()->get();

        if ($am == $bm) {
            return 0;
        }
        if ($am < $bm) {
            return -1;
        }
        return 1;
    }
317364
public function Add($a, $b)
    {
        $this->preOpMethodParamsCheck(array($a, $b));

        return $this->math->add($a, $b);
    }
687075
public static ComplexNumber Add(ComplexNumber z1, ComplexNumber z2) {
        return new ComplexNumber(z1.real + z2.real, z1.imaginary + z2.imaginary);
    }
397829
public function rationalDiv(NI $a, NI $b)
    {
        list($a, $b) = $this->checkRationalTypes($a, $b);
        $n = $this->intMul($a->numerator(), $b->denominator());
        $d = $this->intMul($a->denominator(), $b->numerator());

        return RationalTypeFactory::create($n, $d);
    }
815066
protected function checkRationalTypes(NumericTypeInterface $a, NumericTypeInterface $b)
    {
        $a1 = ($a instanceof RationalType ? $a : $a->asRational());
        $b1 = ($b instanceof RationalType ? $b : $b->asRational());

        return [$a1, $b1];
    }
566118
protected function gcd($a, $b)
    {
        while ($b != 0) {
            $remainder = $a % $b;
            $a = $b;
            $b = $remainder;
        }
        return abs($a);
    }
828637
public function floatAdd(NI $a, NI $b)
    {
        list($a, $b) = $this->checkFloatTypes($a, $b);
        return new FloatType($a() + $b());
    }
497414
public function naturalAdd(NI $a, NI $b)
    {
        list($a, $b) = $this->checkIntTypes($a, $b);
        return new NaturalIntType($a() + $b());
    }
587793
public function compare(NI $a, NI $b)
    {
        switch ($this->arbitrate($a, $b)) {
            case 'int':
            case 'whole':
            case 'natural':
            case 'float':
                return $this->intFloatCompare($a, $b);
            case 'rational':
                list($a, $b) = $this->checkRationalTypes($a, $b);
                return $this->rationalCompare($a, $b);
            case 'complex':
                return $this->complexCompare($a, $b);
            case 'complex:numeric':
                return $this->complexCompare($a, $b->asComplex());
            case 'numeric:complex':
                return $this->complexCompare($a->asComplex(), $b);
        }
    }
1194846
private function multiplyRational(Rational $r): Rational
    {
        $w = $this->whole;
        $n = $this->numerator;
        $d = $this->denominator;

        $w2 = $r->whole;
        $n2 = $r->numerator;
        $d2 = $r->denominator;

        $new_w = $w * $w2;
        $new_n = $w * $n2 * $d + $w2 * $n * $d2 + $n2 * $n;
        $new_d = $d * $d2;

        return new Rational($new_w, $new_n, $new_d);
    }