BCAdd - fixes a problem of BCMath and exponential numbers

@param  string  $op1
@param  string  $op2
@param  integer $scale
@return string
480504
public static function Add($op1, $op2, $scale = null)
    {
        $op1 = self::exponent($op1, $scale);
        $op2 = self::exponent($op2, $scale);

        return bcadd($op1, $op2, $scale);
    }
879014
private function add($s1, $s2, $scale) {
        if ($this->bcmath) return bcadd($s1, $s2, $scale);
        else return $this->scale($s1 + $s2, $scale);
    }
974402
public static function mul($n1, $n2, $round = false)
    {
        $product = bcmul($n1, $n2, self::$scale);

        return $round ? self::round($product) : (float)$product;
    }
665267
public static function floor($arg1, $scale = 0) : string {
		if ($arg1[0] != '-') {
			return bcadd($arg1, '0', $scale);
		} else {
			$value = '1';
			if ($scale != 0) {
				$value = self::divide('1', 10 ** $scale, $scale);
			}
			return bcsub($arg1, $value, $scale);
		}
	}
1172171
public static function round($arg1, $scale = 0) : string {
		if (!isset($scale)) {
			$scale = self::$scale;
		}
		if ($arg1[0] != '-') {
			return bcadd($arg1, '0.' . str_repeat('0', $scale) . '5', $scale);
		} else {
			return bcsub($arg1, '0.' . str_repeat('0', $scale) . '5', $scale);
		}
	}
518712
public static function op_IntegerDivide( $val1, $val2 )
	{
		switch ( ValueProxy::$conv_t[ $val1->GetValueCode() ][ $val2->GetValueCode() ] )
		{
			case -1:
				return $val2->Promote( $val1 )->IDiv( $val2 );

			case 0:
				return $val1->IDiv( $val2 );

			case 1:
				return $val1->IDiv( $val1->Promote( $val2 ) );

			default:
				if ( ValueProxy::$conv_t[ $val2->GetValueCode() ][ $val1->GetValueCode() ] == 1 )
					return $val2->Promote( $val1 )->IDiv( $val2 );

				throw XPath2Exception::withErrorCodeAndParams( "XPTY0004", Resources::BinaryOperatorNotDefined,
					array(
						"op:idiv",
						SequenceType::WithTypeCodeAndCardinality( SequenceType::GetXmlTypeCodeFromObject( $val1 ), XmlTypeCardinality::One ),
						SequenceType::WithTypeCodeAndCardinality( SequenceType::GetXmlTypeCodeFromObject( $val2 ), XmlTypeCardinality::One )
					)
				);
		}
	}
716013
public static function mul($int1, $int2)
    {
        if (!static::is($int1) || !static::is($int2)) {
            throw new \InvalidArgumentException(
                "The \$int1 and \$int2 parameters must be of type int (or string representing a big int)."
            );
        }

        if (is_int($int1) && is_int($int2)) {
            return ($int1 * $int2);
        } elseif (function_exists('bcmul')) {
            return bcmul($int1, $int2);
        }

        throw new \RuntimeException("The BCMath library is not available."); // @codeCoverageIgnore
    }
1027460
public static long safeMultiply(
        long op1,
        long op2
    ) {

        if (op2 == 1L) {
            return op1;
        }

        if (
            (op2 > 0)
            ? (op1 > Long.MAX_VALUE / op2) || (op1 < Long.MIN_VALUE / op2)
            : ((op2 < -1)
                ? (op1 > Long.MIN_VALUE / op2) || (op1 < Long.MAX_VALUE / op2)
                : (op2 == -1) && (op1 == Long.MIN_VALUE))
        ) {
            StringBuilder sb = new StringBuilder(32);
            sb.append("Long overflow: (");
            sb.append(op1);
            sb.append(',');
            sb.append(op2);
            sb.append(')');
            throw new ArithmeticException(sb.toString());
        }

        return op1 * op2;

    }
198402
public function combine($op, $map1/**, $transf2,... */)
    {
        $transformations = func_get_args();
        array_shift($transformations);

        return function(Expression $expr, $compiler) use ($op, $transformations)
        {
            $tree = new SpanExpression(strtoupper($op));

            foreach ($transformations as $transformation) {
                $tree->addExpression($transformation($expr, $compiler));
            }

            return $tree;
        };
    }
597926
def _addf(ins):
    ''' 
    '''
    op1, op2 = tuple(ins.quad[2:])

    if _f_ops(op1, op2) is not None:
        opa, opb = _f_ops(op1, op2)
        if opb == 0:  # A + 0 => A
            output = _float_oper(opa)
            output.extend(_fpush())
            return output

    output = _float_oper(op1, op2)
    output.append('call __ADDF')
    output.extend(_fpush())
    REQUIRES.add('addf.asm')
    return output
116548
public static function doubleReverse($arg1, $reverse1, $reverse2, $scale = null) : string {
		if ($reverse1) {
			$arg1 = self::opposite($arg1, $scale);
		}
		if ($reverse2) {
			$arg1 = self::opposite($arg1, $scale);
		}
		return $arg1;
	}
1151807
private static function simplePowerSerie (Decimal $x, Decimal $firstTerm, int $scale): Decimal
    {
        $approx = $firstTerm;
        $change = DecimalConstants::One();

        $xPowerN = DecimalConstants::One();     // Calculates x^n
        $sign = DecimalConstants::One();      // Calculates a_n

        for ($i = 1; !$change->floor($scale + 2)->isZero(); $i++) {
            $xPowerN = $xPowerN->mul($x);

            if ($i % 2 === 0) {
                $factorN = DecimalConstants::zero();
            } else {
                 if ($i % 4 === 1) {
                     $factorN = DecimalConstants::one()->div(Decimal::fromInteger($i), $scale + 2);
                 } else {
                     $factorN = DecimalConstants::negativeOne()->div(Decimal::fromInteger($i), $scale + 2);
                 }
            }

            if (!$factorN->isZero()) {
                $change = $factorN->mul($xPowerN, $scale + 2);
                $approx = $approx->add($change, $scale + 2);
            }
        }

        return $approx->round($scale);
    }
1015781
public function getAmountBasic($roundingMode = self::ROUND_HALF_UP)
    {
        return Math::bcround($this->amount, self::BASIC_PRECISION, $roundingMode);
    }
651918
public static function compare($n1, $n2)
    {
        $n1 = self::round($n1, 2);
        $n2 = self::round($n2, 2);

        return (bccomp($n1, $n2, self::$scale) === 0);
    }
995738
public static function compare_floats($v1, $v2, string $operator = '===', int $precision = 4): bool
  {
    $v1 = round((float)$v1 * pow(10, $precision));
    $v2 = round((float)$v2 * pow(10, $precision));
    switch ($operator ){
      case '===':
        return $v1 === $v2;
      case '==':
        return $v1 == $v2;
      case '>=':
        return $v1 >= $v2;
      case '<=':
        return $v1 <= $v2;
      case '>':
        return $v1 > $v2;
      case '<':
        return $v1 < $v2;
    }
    return false;
  }
953532
public static function subtract($arg1, $arg2, $scale = null) : string {
		return self::__operator('bcsub', $arg1, $arg2, $scale ?? self::$scale);
	}
557413
public static function div($n1, $n2, $round = false)
    {
        // Avoid division by Zero
        if ($n2 == 0) {
            return (float)0;
        }

        $quotient = bcdiv($n1, $n2, self::$scale);

        return $round ? self::round($quotient) : (float)$quotient;
    }