/** * Powers this value to $b * * @param Decimal $b exponent * @param integer $scale * @return Decimal */ public function pow(Decimal $b, $scale = null) { if ($this->isZero()) { if ($b->isPositive()) { return Decimal::fromDecimal($this, $scale); } else { throw new \DomainException("zero can't be powered to zero or negative numbers."); } } elseif ($b->isZero()) { return DecimalConstants::One(); } else { if ($b->isNegative()) { return DecimalConstants::One()->div($this->pow($b->additiveInverse()), $scale); } elseif ($b->scale == 0) { $pow_scale = $scale === null ? max($this->scale, $b->scale) : max($this->scale, $b->scale, $scale); return self::fromString(bcpow($this->value, $b->value, $pow_scale + 1), $pow_scale); } else { if ($this->isPositive()) { $pow_scale = $scale === null ? max($this->scale, $b->scale) : max($this->scale, $b->scale, $scale); $truncated_b = bcadd($b->value, '0', 0); $remaining_b = bcsub($b->value, $truncated_b, $b->scale); $first_pow_approx = bcpow($this->value, $truncated_b, $pow_scale + 1); $intermediate_root = self::innerPowWithLittleExponent($this->value, $remaining_b, $b->scale, $pow_scale + 1); return Decimal::fromString(bcmul($first_pow_approx, $intermediate_root, $pow_scale + 1), $pow_scale); } else { // elseif ($this->isNegative()) if ($b->isInteger()) { if (preg_match('/^[+\\-]?[0-9]*[02468](\\.0+)?$/', $b->value, $captures) === 1) { // $b is an even number return $this->additiveInverse()->pow($b, $scale); } else { // $b is an odd number return $this->additiveInverse()->pow($b, $scale)->additiveInverse(); } } throw new NotImplementedException("Usually negative numbers can't be powered to non integer numbers. " . "The cases where is possible are not implemented."); } } } }