diff --git a/src/Decimal.php b/src/Decimal.php index 2a374ae..f12995c 100644 --- a/src/Decimal.php +++ b/src/Decimal.php @@ -20,6 +20,8 @@ class Decimal const CLASSIC_DECIMAL_NUMBER_REGEXP = '/^([+\-]?)0*(([1-9][0-9]*|[0-9])(\.[0-9]+)?)$/'; const EXP_NOTATION_NUMBER_REGEXP = '/^ (?P [+\-]?) 0*(?P [0-9](?P \.[0-9]+)?) [eE] (?P [+\-]?)(?P \d+)$/x'; const EXP_NUM_GROUPS_NUMBER_REGEXP = '/^ (?P \d*) (?: \. (?P \d+) ) E (?P[\+\-]) (?P\d+) $/x'; + + const DECIMAL_CONSTANTS = DecimalConstants::class; /** * Internal numeric value @@ -48,9 +50,9 @@ private function __clone() * * @param mixed $value * @param int $scale - * @return Decimal + * @return self */ - public static function create($value, int $scale = null): Decimal + public static function create($value, int $scale = null): self { if (\is_int($value)) { return self::fromInteger($value); @@ -58,7 +60,7 @@ public static function create($value, int $scale = null): Decimal return self::fromFloat($value, $scale); } elseif (\is_string($value)) { return self::fromString($value, $scale); - } elseif ($value instanceof Decimal) { + } elseif ($value instanceof self) { return self::fromDecimal($value, $scale); } else { throw new \TypeError( @@ -68,7 +70,7 @@ public static function create($value, int $scale = null): Decimal } } - public static function fromInteger(int $intValue): Decimal + public static function fromInteger(int $intValue): self { self::paramsValidation($intValue, null); @@ -78,9 +80,9 @@ public static function fromInteger(int $intValue): Decimal /** * @param float $fltValue * @param int $scale - * @return Decimal + * @return self */ - public static function fromFloat(float $fltValue, int $scale = null): Decimal + public static function fromFloat(float $fltValue, int $scale = null): self { self::paramsValidation($fltValue, $scale); @@ -118,9 +120,9 @@ public static function fromFloat(float $fltValue, int $scale = null): Decimal /** * @param string $strValue * @param integer $scale - * @return Decimal + * @return self */ - public static function fromString(string $strValue, int $scale = null): Decimal + public static function fromString(string $strValue, int $scale = null): self { self::paramsValidation($strValue, $scale); @@ -158,11 +160,11 @@ public static function fromString(string $strValue, int $scale = null): Decimal * Constructs a new Decimal object based on a previous one, * but changing it's $scale property. * - * @param Decimal $decValue + * @param self $decValue * @param null|int $scale - * @return Decimal + * @return self */ - public static function fromDecimal(Decimal $decValue, int $scale = null): Decimal + public static function fromDecimal(self $decValue, int $scale = null): self { self::paramsValidation($decValue, $scale); @@ -179,11 +181,11 @@ public static function fromDecimal(Decimal $decValue, int $scale = null): Decima /** * Adds two Decimal objects - * @param Decimal $b + * @param self $b * @param null|int $scale - * @return Decimal + * @return self */ - public function add(Decimal $b, int $scale = null): Decimal + public function add(self $b, int $scale = null): self { self::paramsValidation($b, $scale); @@ -195,11 +197,11 @@ public function add(Decimal $b, int $scale = null): Decimal /** * Subtracts two BigNumber objects - * @param Decimal $b + * @param self $b * @param integer $scale - * @return Decimal + * @return self */ - public function sub(Decimal $b, int $scale = null): Decimal + public function sub(self $b, int $scale = null): self { self::paramsValidation($b, $scale); @@ -211,16 +213,16 @@ public function sub(Decimal $b, int $scale = null): Decimal /** * Multiplies two BigNumber objects - * @param Decimal $b + * @param self $b * @param integer $scale - * @return Decimal + * @return self */ - public function mul(Decimal $b, int $scale = null): Decimal + public function mul(self $b, int $scale = null): self { self::paramsValidation($b, $scale); if ($b->isZero()) { - return DecimalConstants::Zero(); + return (static::DECIMAL_CONSTANTS)::Zero(); } return self::fromString( @@ -235,18 +237,18 @@ public function mul(Decimal $b, int $scale = null): Decimal * integer division because it rounds the * last digit in order to minimize the error. * - * @param Decimal $b + * @param self $b * @param integer $scale - * @return Decimal + * @return self */ - public function div(Decimal $b, int $scale = null): Decimal + public function div(self $b, int $scale = null): self { self::paramsValidation($b, $scale); if ($b->isZero()) { throw new \DomainException("Division by zero is not allowed."); } elseif ($this->isZero()) { - return DecimalConstants::Zero(); + return (static::DECIMAL_CONSTANTS)::Zero(); } else { if (null !== $scale) { $divscale = $scale; @@ -278,16 +280,16 @@ public function div(Decimal $b, int $scale = null): Decimal /** * Returns the square root of this object * @param integer $scale - * @return Decimal + * @return self */ - public function sqrt(int $scale = null): Decimal + public function sqrt(int $scale = null): self { if ($this->isNegative()) { throw new \DomainException( "Decimal can't handle square roots of negative numbers (it's only for real numbers)." ); } elseif ($this->isZero()) { - return DecimalConstants::Zero(); + return (static::DECIMAL_CONSTANTS)::Zero(); } $sqrt_scale = ($scale !== null ? $scale : $this->scale); @@ -301,22 +303,22 @@ public function sqrt(int $scale = null): Decimal /** * Powers this value to $b * - * @param Decimal $b exponent + * @param self $b exponent * @param integer $scale - * @return Decimal + * @return self */ - public function pow(Decimal $b, int $scale = null): Decimal + public function pow(self $b, int $scale = null): self { if ($this->isZero()) { if ($b->isPositive()) { - return Decimal::fromDecimal($this, $scale); + return self::fromDecimal($this, $scale); } else { throw new \DomainException("zero can't be powered to zero or negative numbers."); } } elseif ($b->isZero()) { - return DecimalConstants::One(); + return (static::DECIMAL_CONSTANTS)::One(); } else if ($b->isNegative()) { - return DecimalConstants::One()->div( + return (static::DECIMAL_CONSTANTS)::One()->div( $this->pow($b->additiveInverse(), max($scale, self::DEFAULT_SCALE)), max($scale, self::DEFAULT_SCALE) ); @@ -342,7 +344,7 @@ public function pow(Decimal $b, int $scale = null): Decimal $pow_scale+1 ); - return Decimal::fromString( + return self::fromString( \bcmul($first_pow_approx, $intermediate_root, $pow_scale+1), $pow_scale ); @@ -364,9 +366,9 @@ public function pow(Decimal $b, int $scale = null): Decimal /** * Returns the object's logarithm in base 10 * @param integer $scale - * @return Decimal + * @return self */ - public function log10(int $scale = null): Decimal + public function log10(int $scale = null): self { if ($this->isNegative()) { throw new \DomainException( @@ -408,11 +410,11 @@ public function isInteger(): bool /** * Equality comparison between this object and $b - * @param Decimal $b - * @param integer $scale + * @param self $b + * @param integer $scale * @return boolean */ - public function equals(Decimal $b, int $scale = null): bool + public function equals(self $b, int $scale = null): bool { self::paramsValidation($b, $scale); @@ -434,11 +436,11 @@ public function equals(Decimal $b, int $scale = null): bool /** * $this > $b : returns 1 , $this < $b : returns -1 , $this == $b : returns 0 * - * @param Decimal $b + * @param self $b * @param integer $scale * @return integer */ - public function comp(Decimal $b, int $scale = null): int + public function comp(self $b, int $scale = null): int { self::paramsValidation($b, $scale); @@ -459,11 +461,11 @@ public function comp(Decimal $b, int $scale = null): int /** * Returns true if $this > $b, otherwise false * - * @param Decimal $b + * @param self $b * @param integer $scale * @return bool */ - public function isGreaterThan(Decimal $b, int $scale = null): bool + public function isGreaterThan(self $b, int $scale = null): bool { return $this->comp($b, $scale) === 1; } @@ -471,11 +473,11 @@ public function isGreaterThan(Decimal $b, int $scale = null): bool /** * Returns true if $this >= $b * - * @param Decimal $b + * @param self $b * @param integer $scale * @return bool */ - public function isGreaterOrEqualTo(Decimal $b, int $scale = null): bool + public function isGreaterOrEqualTo(self $b, int $scale = null): bool { $comparisonResult = $this->comp($b, $scale); @@ -485,11 +487,11 @@ public function isGreaterOrEqualTo(Decimal $b, int $scale = null): bool /** * Returns true if $this < $b, otherwise false * - * @param Decimal $b + * @param self $b * @param integer $scale * @return bool */ - public function isLessThan(Decimal $b, int $scale = null): bool + public function isLessThan(self $b, int $scale = null): bool { return $this->comp($b, $scale) === -1; } @@ -497,11 +499,11 @@ public function isLessThan(Decimal $b, int $scale = null): bool /** * Returns true if $this <= $b, otherwise false * - * @param Decimal $b + * @param self $b * @param integer $scale * @return bool */ - public function isLessOrEqualTo(Decimal $b, int $scale = null): bool + public function isLessOrEqualTo(self $b, int $scale = null): bool { $comparisonResult = $this->comp($b, $scale); @@ -510,9 +512,9 @@ public function isLessOrEqualTo(Decimal $b, int $scale = null): bool /** * Returns the element's additive inverse. - * @return Decimal + * @return self */ - public function additiveInverse(): Decimal + public function additiveInverse(): self { if ($this->isZero()) { return $this; @@ -529,9 +531,9 @@ public function additiveInverse(): Decimal /** * "Rounds" the Decimal to have at most $scale digits after the point * @param integer $scale - * @return Decimal + * @return self */ - public function round(int $scale = 0): Decimal + public function round(int $scale = 0): self { if ($scale >= $this->scale) { return $this; @@ -543,9 +545,9 @@ public function round(int $scale = 0): Decimal /** * "Ceils" the Decimal to have at most $scale digits after the point * @param integer $scale - * @return Decimal + * @return self */ - public function ceil($scale = 0): Decimal + public function ceil($scale = 0): self { if ($scale >= $this->scale) { return $this; @@ -558,7 +560,7 @@ public function ceil($scale = 0): Decimal return $this->innerTruncate($scale); } - private function innerTruncate(int $scale = 0, bool $ceil = true): Decimal + private function innerTruncate(int $scale = 0, bool $ceil = true): self { $rounded = \bcadd($this->value, '0', $scale); @@ -585,9 +587,9 @@ private function innerTruncate(int $scale = 0, bool $ceil = true): Decimal /** * "Floors" the Decimal to have at most $scale digits after the point * @param integer $scale - * @return Decimal + * @return self */ - public function floor(int $scale = 0): Decimal + public function floor(int $scale = 0): self { if ($scale >= $this->scale) { return $this; @@ -602,9 +604,9 @@ public function floor(int $scale = 0): Decimal /** * Returns the absolute value (always a positive number) - * @return Decimal + * @return self */ - public function abs(): Decimal + public function abs(): self { return ($this->isZero() || $this->isPositive()) ? $this @@ -613,11 +615,11 @@ public function abs(): Decimal /** * Calculate modulo with a decimal - * @param Decimal $d + * @param self $d * @param integer $scale * @return $this % $d */ - public function mod(Decimal $d, int $scale = null): Decimal + public function mod(self $d, int $scale = null): self { $div = $this->div($d, 1)->floor(); return $this->sub($div->mul($d), $scale); @@ -628,23 +630,23 @@ public function mod(Decimal $d, int $scale = null): Decimal * Note that accuracy is limited by the accuracy of predefined PI; * * @param integer $scale - * @return Decimal sin($this) + * @return self sin($this) */ - public function sin(int $scale = null): Decimal + public function sin(int $scale = null): self { // First normalise the number in the [0, 2PI] domain - $x = $this->mod(DecimalConstants::PI()->mul(Decimal::fromString("2"))); + $x = $this->mod((static::DECIMAL_CONSTANTS)::pi()->mul(self::fromString("2"))); - // PI has only 32 significant numbers - $scale = (null === $scale) ? 32 : $scale; + // PI has only limited significant numbers + $scale = $scale ?? (static::DECIMAL_CONSTANTS)::pi()->scale; return self::factorialSerie( $x, - DecimalConstants::zero(), + (static::DECIMAL_CONSTANTS)::zero(), function ($i) { return ($i % 2 === 1) ? ( - ($i % 4 === 1) ? DecimalConstants::one() : DecimalConstants::negativeOne() - ) : DecimalConstants::zero(); + ($i % 4 === 1) ? (static::DECIMAL_CONSTANTS)::one() : (static::DECIMAL_CONSTANTS)::negativeOne() + ) : (static::DECIMAL_CONSTANTS)::zero(); }, $scale ); @@ -655,10 +657,11 @@ function ($i) { * Note that accuracy is limited by the accuracy of predefined PI; * * @param integer $scale - * @return Decimal + * @return self */ - public function cosec(int $scale = null): Decimal + public function cosec(int $scale = null): self { + $scale = $scale ?? (static::DECIMAL_CONSTANTS)::pi()->scale; $sin = $this->sin($scale + 2); if ($sin->isZero()) { throw new \DomainException( @@ -666,7 +669,7 @@ public function cosec(int $scale = null): Decimal ); } - return DecimalConstants::one()->div($sin)->round($scale); + return (static::DECIMAL_CONSTANTS)::one()->div($sin)->round($scale); } /** @@ -674,23 +677,23 @@ public function cosec(int $scale = null): Decimal * Note that accuracy is limited by the accuracy of predefined PI; * * @param integer $scale - * @return Decimal cos($this) + * @return self cos($this) */ - public function cos(int $scale = null): Decimal + public function cos(int $scale = null): self { // First normalise the number in the [0, 2PI] domain - $x = $this->mod(DecimalConstants::PI()->mul(Decimal::fromString("2"))); + $x = $this->mod((static::DECIMAL_CONSTANTS)::pi()->mul(self::fromString("2"))); - // PI has only 32 significant numbers - $scale = ($scale === null) ? 32 : $scale; + // PI has only limited significant numbers + $scale = $scale ?? (static::DECIMAL_CONSTANTS)::pi()->scale; return self::factorialSerie( $x, - DecimalConstants::one(), + (static::DECIMAL_CONSTANTS)::one(), function ($i) { return ($i % 2 === 0) ? ( - ($i % 4 === 0) ? DecimalConstants::one() : DecimalConstants::negativeOne() - ) : DecimalConstants::zero(); + ($i % 4 === 0) ? (static::DECIMAL_CONSTANTS)::one() : (static::DECIMAL_CONSTANTS)::negativeOne() + ) : (static::DECIMAL_CONSTANTS)::zero(); }, $scale ); @@ -701,10 +704,11 @@ function ($i) { * Note that accuracy is limited by the accuracy of predefined PI; * * @param integer $scale - * @return Decimal + * @return self */ - public function sec(int $scale = null): Decimal + public function sec(int $scale = null): self { + $scale = $scale ?? (static::DECIMAL_CONSTANTS)::pi()->scale; $cos = $this->cos($scale + 2); if ($cos->isZero()) { throw new \DomainException( @@ -712,104 +716,103 @@ public function sec(int $scale = null): Decimal ); } - return DecimalConstants::one()->div($cos)->round($scale); + return (static::DECIMAL_CONSTANTS)::one()->div($cos)->round($scale); } /** - * Calculates the arcsine of this with the highest possible accuracy + * Calculates the arcsine of this with the highest possible accuracy * * @param integer $scale - * @return Decimal + * @return self */ - public function arcsin(int $scale = null): Decimal + public function arcsin(int $scale = null): self { - if($this->comp(DecimalConstants::one(), $scale + 2) === 1 || $this->comp(DecimalConstants::negativeOne(), $scale + 2) === -1) { + $scale = $scale ?? (static::DECIMAL_CONSTANTS)::pi()->scale; + + if($this->comp((static::DECIMAL_CONSTANTS)::one(), $scale + 2) === 1 || $this->comp((static::DECIMAL_CONSTANTS)::negativeOne(), $scale + 2) === -1) { throw new \DomainException( "The arcsin of this number is undefined." ); } if ($this->round($scale)->isZero()) { - return DecimalConstants::zero(); + return (static::DECIMAL_CONSTANTS)::zero(); } - if ($this->round($scale)->equals(DecimalConstants::one())) { - return DecimalConstants::pi()->div(Decimal::fromInteger(2))->round($scale); + if ($this->round($scale)->equals((static::DECIMAL_CONSTANTS)::one())) { + return (static::DECIMAL_CONSTANTS)::pi()->div(self::fromInteger(2))->round($scale); } - if ($this->round($scale)->equals(DecimalConstants::negativeOne())) { - return DecimalConstants::pi()->div(Decimal::fromInteger(-2))->round($scale); + if ($this->round($scale)->equals((static::DECIMAL_CONSTANTS)::negativeOne())) { + return (static::DECIMAL_CONSTANTS)::pi()->div(self::fromInteger(-2))->round($scale); } - $scale = ($scale === null) ? 32 : $scale; - return self::powerSerie( $this, - DecimalConstants::zero(), + (static::DECIMAL_CONSTANTS)::zero(), $scale ); } /** - * Calculates the arccosine of this with the highest possible accuracy + * Calculates the arccosine of this with the highest possible accuracy * * @param integer $scale - * @return Decimal + * @return self */ - public function arccos(int $scale = null): Decimal + public function arccos(int $scale = null): self { - if($this->comp(DecimalConstants::one(), $scale + 2) === 1 || $this->comp(DecimalConstants::negativeOne(), $scale + 2) === -1) { + $scale = $scale ?? (static::DECIMAL_CONSTANTS)::pi()->scale; + + if ($this->comp((static::DECIMAL_CONSTANTS)::one(), $scale + 2) === 1 || $this->comp((static::DECIMAL_CONSTANTS)::negativeOne(), $scale + 2) === -1) { throw new \DomainException( "The arccos of this number is undefined." ); } - $piOverTwo = DecimalConstants::pi()->div(Decimal::fromInteger(2), $scale + 2)->round($scale); + $piOverTwo = (static::DECIMAL_CONSTANTS)::pi()->div(self::fromInteger(2), $scale + 2)->round($scale); if ($this->round($scale)->isZero()) { return $piOverTwo; } - if ($this->round($scale)->equals(DecimalConstants::one())) { - return DecimalConstants::zero(); + if ($this->round($scale)->equals((static::DECIMAL_CONSTANTS)::one())) { + return (static::DECIMAL_CONSTANTS)::zero(); } - if ($this->round($scale)->equals(DecimalConstants::negativeOne())) { - return DecimalConstants::pi()->round($scale); + if ($this->round($scale)->equals((static::DECIMAL_CONSTANTS)::negativeOne())) { + return (static::DECIMAL_CONSTANTS)::pi()->round($scale); } - - $scale = ($scale === null) ? 32 : $scale; - + return $piOverTwo->sub( self::powerSerie( $this, - DecimalConstants::zero(), + (static::DECIMAL_CONSTANTS)::zero(), $scale ) )->round($scale); } /** - * Calculates the arctangente of this with the highest possible accuracy + * Calculates the arctangente of this with the highest possible accuracy * * @param integer $scale - * @return Decimal + * @return self */ - public function arctan(int $scale = null): Decimal + public function arctan(int $scale = null): self { - $piOverFour = DecimalConstants::pi()->div(Decimal::fromInteger(4), $scale + 2)->round($scale); + $scale = $scale ?? (static::DECIMAL_CONSTANTS)::pi()->scale; + $piOverFour = (static::DECIMAL_CONSTANTS)::pi()->div(self::fromInteger(4), $scale + 2)->round($scale); if ($this->round($scale)->isZero()) { - return DecimalConstants::zero(); + return (static::DECIMAL_CONSTANTS)::zero(); } - if ($this->round($scale)->equals(DecimalConstants::one())) { + if ($this->round($scale)->equals((static::DECIMAL_CONSTANTS)::one())) { return $piOverFour; } - if ($this->round($scale)->equals(DecimalConstants::negativeOne())) { - return DecimalConstants::negativeOne()->mul($piOverFour); + if ($this->round($scale)->equals((static::DECIMAL_CONSTANTS)::negativeOne())) { + return (static::DECIMAL_CONSTANTS)::negativeOne()->mul($piOverFour); } - $scale = ($scale === null) ? 32 : $scale; - return self::simplePowerSerie( $this, - DecimalConstants::zero(), + (static::DECIMAL_CONSTANTS)::zero(), $scale + 2 )->round($scale); } @@ -818,29 +821,29 @@ public function arctan(int $scale = null): Decimal * Calculates the arccotangente of this with the highest possible accuracy * * @param integer $scale - * @return Decimal + * @return self */ - public function arccot(int $scale = null): Decimal + public function arccot(int $scale = null): self { - $scale = ($scale === null) ? 32 : $scale; + $scale = $scale ?? (static::DECIMAL_CONSTANTS)::pi()->scale; - $piOverTwo = DecimalConstants::pi()->div(Decimal::fromInteger(2), $scale + 2); + $piOverTwo = (static::DECIMAL_CONSTANTS)::pi()->div(self::fromInteger(2), $scale + 2); if ($this->round($scale)->isZero()) { return $piOverTwo->round($scale); } - $piOverFour = DecimalConstants::pi()->div(Decimal::fromInteger(4), $scale + 2); - if ($this->round($scale)->equals(DecimalConstants::one())) { + $piOverFour = (static::DECIMAL_CONSTANTS)::pi()->div(self::fromInteger(4), $scale + 2); + if ($this->round($scale)->equals((static::DECIMAL_CONSTANTS)::one())) { return $piOverFour->round($scale); } - if ($this->round($scale)->equals(DecimalConstants::negativeOne())) { - return DecimalConstants::negativeOne()->mul($piOverFour, $scale + 2)->round($scale); + if ($this->round($scale)->equals((static::DECIMAL_CONSTANTS)::negativeOne())) { + return (static::DECIMAL_CONSTANTS)::negativeOne()->mul($piOverFour, $scale + 2)->round($scale); } return $piOverTwo->sub( self::simplePowerSerie( $this, - DecimalConstants::zero(), + (static::DECIMAL_CONSTANTS)::zero(), $scale + 2 ) )->round($scale); @@ -850,31 +853,31 @@ public function arccot(int $scale = null): Decimal * Calculates the arcsecant of this with the highest possible accuracy * * @param integer $scale - * @return Decimal + * @return self */ - public function arcsec(int $scale = null): Decimal + public function arcsec(int $scale = null): self { - if($this->comp(DecimalConstants::one(), $scale + 2) === -1 && $this->comp(DecimalConstants::negativeOne(), $scale + 2) === 1) { + $scale = $scale ?? (static::DECIMAL_CONSTANTS)::pi()->scale; + + if ($this->comp((static::DECIMAL_CONSTANTS)::one(), $scale + 2) === -1 && $this->comp((static::DECIMAL_CONSTANTS)::negativeOne(), $scale + 2) === 1) { throw new \DomainException( "The arcsecant of this number is undefined." ); } - $piOverTwo = DecimalConstants::pi()->div(Decimal::fromInteger(2), $scale + 2)->round($scale); + $piOverTwo = (static::DECIMAL_CONSTANTS)::pi()->div(self::fromInteger(2), $scale + 2)->round($scale); - if ($this->round($scale)->equals(DecimalConstants::one())) { - return DecimalConstants::zero(); + if ($this->round($scale)->equals((static::DECIMAL_CONSTANTS)::one())) { + return (static::DECIMAL_CONSTANTS)::zero(); } - if ($this->round($scale)->equals(DecimalConstants::negativeOne())) { - return DecimalConstants::pi()->round($scale); + if ($this->round($scale)->equals((static::DECIMAL_CONSTANTS)::negativeOne())) { + return (static::DECIMAL_CONSTANTS)::pi()->round($scale); } - - $scale = ($scale === null) ? 32 : $scale; - + return $piOverTwo->sub( self::powerSerie( - DecimalConstants::one()->div($this, $scale + 2), - DecimalConstants::zero(), + (static::DECIMAL_CONSTANTS)::one()->div($this, $scale + 2), + (static::DECIMAL_CONSTANTS)::zero(), $scale + 2 ) )->round($scale); @@ -884,28 +887,28 @@ public function arcsec(int $scale = null): Decimal * Calculates the arccosecant of this with the highest possible accuracy * * @param integer $scale - * @return Decimal + * @return self */ - public function arccsc(int $scale = null): Decimal + public function arccsc(int $scale = null): self { - if($this->comp(DecimalConstants::one(), $scale + 2) === -1 && $this->comp(DecimalConstants::negativeOne(), $scale + 2) === 1) { + $scale = $scale ?? (static::DECIMAL_CONSTANTS)::pi()->scale; + + if ($this->comp((static::DECIMAL_CONSTANTS)::one(), $scale + 2) === -1 && $this->comp((static::DECIMAL_CONSTANTS)::negativeOne(), $scale + 2) === 1) { throw new \DomainException( "The arccosecant of this number is undefined." ); } - - $scale = ($scale === null) ? 32 : $scale; - - if ($this->round($scale)->equals(DecimalConstants::one())) { - return DecimalConstants::pi()->div(Decimal::fromInteger(2), $scale + 2)->round($scale); + + if ($this->round($scale)->equals((static::DECIMAL_CONSTANTS)::one())) { + return (static::DECIMAL_CONSTANTS)::pi()->div(self::fromInteger(2), $scale + 2)->round($scale); } - if ($this->round($scale)->equals(DecimalConstants::negativeOne())) { - return DecimalConstants::pi()->div(Decimal::fromInteger(-2), $scale + 2)->round($scale); + if ($this->round($scale)->equals((static::DECIMAL_CONSTANTS)::negativeOne())) { + return (static::DECIMAL_CONSTANTS)::pi()->div(self::fromInteger(-2), $scale + 2)->round($scale); } return self::powerSerie( - DecimalConstants::one()->div($this, $scale + 2), - DecimalConstants::zero(), + (static::DECIMAL_CONSTANTS)::one()->div($this, $scale + 2), + (static::DECIMAL_CONSTANTS)::zero(), $scale + 2 )->round($scale); } @@ -914,12 +917,12 @@ public function arccsc(int $scale = null): Decimal * Returns exp($this), said in other words: e^$this . * * @param integer $scale - * @return Decimal + * @return self */ - public function exp(int $scale = null): Decimal + public function exp(int $scale = null): self { if ($this->isZero()) { - return DecimalConstants::one(); + return (static::DECIMAL_CONSTANTS)::one(); } $scale = $scale ?? \max( @@ -928,33 +931,33 @@ public function exp(int $scale = null): Decimal ); return self::factorialSerie( - $this, DecimalConstants::one(), function ($i) { return DecimalConstants::one(); }, $scale + $this, (static::DECIMAL_CONSTANTS)::one(), function ($i) { return (static::DECIMAL_CONSTANTS)::one(); }, $scale ); } /** * Internal method used to compute sin, cos and exp * - * @param Decimal $x - * @param Decimal $firstTerm + * @param self $x + * @param self $firstTerm * @param callable $generalTerm * @param $scale - * @return Decimal + * @return self */ - private static function factorialSerie (Decimal $x, Decimal $firstTerm, callable $generalTerm, int $scale): Decimal + private static function factorialSerie (self $x, self $firstTerm, callable $generalTerm, int $scale): self { $approx = $firstTerm; - $change = DecimalConstants::One(); + $change = (static::DECIMAL_CONSTANTS)::One(); - $faculty = DecimalConstants::One(); // Calculates the faculty under the sign - $xPowerN = DecimalConstants::One(); // Calculates x^n + $faculty = (static::DECIMAL_CONSTANTS)::One(); // Calculates the faculty under the sign + $xPowerN = (static::DECIMAL_CONSTANTS)::One(); // Calculates x^n for ($i = 1; !$change->floor($scale+1)->isZero(); $i++) { // update x^n and n! for this walkthrough $xPowerN = $xPowerN->mul($x); - $faculty = $faculty->mul(Decimal::fromInteger($i)); + $faculty = $faculty->mul(self::fromInteger($i)); - /** @var Decimal $multiplier */ + /** @var self $multiplier */ $multiplier = $generalTerm($i); if (!$multiplier->isZero()) { @@ -970,35 +973,35 @@ private static function factorialSerie (Decimal $x, Decimal $firstTerm, callable /** * Internal method used to compute arcsine and arcosine * - * @param Decimal $x - * @param Decimal $firstTerm + * @param self $x + * @param self $firstTerm * @param $scale - * @return Decimal + * @return self */ - private static function powerSerie (Decimal $x, Decimal $firstTerm, int $scale): Decimal + private static function powerSerie (self $x, self $firstTerm, int $scale): self { $approx = $firstTerm; - $change = DecimalConstants::One(); + $change = (static::DECIMAL_CONSTANTS)::One(); - $xPowerN = DecimalConstants::One(); // Calculates x^n - $factorN = DecimalConstants::One(); // Calculates a_n + $xPowerN = (static::DECIMAL_CONSTANTS)::One(); // Calculates x^n + $factorN = (static::DECIMAL_CONSTANTS)::One(); // Calculates a_n - $numerator = DecimalConstants::one(); - $denominator = DecimalConstants::one(); + $numerator = (static::DECIMAL_CONSTANTS)::one(); + $denominator = (static::DECIMAL_CONSTANTS)::one(); for ($i = 1; !$change->floor($scale + 2)->isZero(); $i++) { $xPowerN = $xPowerN->mul($x); if ($i % 2 === 0) { - $factorN = DecimalConstants::zero(); + $factorN = (static::DECIMAL_CONSTANTS)::zero(); } elseif ($i === 1) { - $factorN = DecimalConstants::one(); + $factorN = (static::DECIMAL_CONSTANTS)::one(); } else { - $incrementNum = Decimal::fromInteger($i - 2); + $incrementNum = self::fromInteger($i - 2); $numerator = $numerator->mul($incrementNum, $scale +2); - $incrementDen = Decimal::fromInteger($i - 1); - $increment = Decimal::fromInteger($i); + $incrementDen = self::fromInteger($i - 1); + $increment = self::fromInteger($i); $denominator = $denominator ->div($incrementNum, $scale +2) ->mul($incrementDen, $scale +2) @@ -1019,29 +1022,29 @@ private static function powerSerie (Decimal $x, Decimal $firstTerm, int $scale): /** * Internal method used to compute arctan and arccotan * - * @param Decimal $x - * @param Decimal $firstTerm + * @param self $x + * @param self $firstTerm * @param $scale - * @return Decimal + * @return self */ - private static function simplePowerSerie (Decimal $x, Decimal $firstTerm, int $scale): Decimal + private static function simplePowerSerie (self $x, self $firstTerm, int $scale): self { $approx = $firstTerm; - $change = DecimalConstants::One(); + $change = (static::DECIMAL_CONSTANTS)::One(); - $xPowerN = DecimalConstants::One(); // Calculates x^n - $sign = DecimalConstants::One(); // Calculates a_n + $xPowerN = (static::DECIMAL_CONSTANTS)::One(); // Calculates x^n + $sign = (static::DECIMAL_CONSTANTS)::One(); // Calculates a_n for ($i = 1; !$change->floor($scale + 2)->isZero(); $i++) { $xPowerN = $xPowerN->mul($x); if ($i % 2 === 0) { - $factorN = DecimalConstants::zero(); + $factorN = (static::DECIMAL_CONSTANTS)::zero(); } else { if ($i % 4 === 1) { - $factorN = DecimalConstants::one()->div(Decimal::fromInteger($i), $scale + 2); + $factorN = (static::DECIMAL_CONSTANTS)::one()->div(self::fromInteger($i), $scale + 2); } else { - $factorN = DecimalConstants::negativeOne()->div(Decimal::fromInteger($i), $scale + 2); + $factorN = (static::DECIMAL_CONSTANTS)::negativeOne()->div(self::fromInteger($i), $scale + 2); } } @@ -1059,18 +1062,19 @@ private static function simplePowerSerie (Decimal $x, Decimal $firstTerm, int $s * Note that accuracy is limited by the accuracy of predefined PI; * * @param integer $scale - * @return Decimal tan($this) + * @return self tan($this) */ - public function tan(int $scale = null): Decimal + public function tan(int $scale = null): self { - $cos = $this->cos($scale + 2); - if ($cos->isZero()) { - throw new \DomainException( - "The tangent of this 'angle' is undefined." - ); - } - - return $this->sin($scale + 2)->div($cos)->round($scale); + $scale = $scale ?? (static::DECIMAL_CONSTANTS)::pi()->scale; + $cos = $this->cos($scale + 2); + if ($cos->isZero()) { + throw new \DomainException( + "The tangent of this 'angle' is undefined." + ); + } + + return $this->sin($scale + 2)->div($cos)->round($scale); } /** @@ -1078,27 +1082,28 @@ public function tan(int $scale = null): Decimal * Note that accuracy is limited by the accuracy of predefined PI; * * @param integer $scale - * @return Decimal cotan($this) + * @return self cotan($this) */ - public function cotan(int $scale = null): Decimal + public function cotan(int $scale = null): self { - $sin = $this->sin($scale + 2); - if ($sin->isZero()) { - throw new \DomainException( - "The cotangent of this 'angle' is undefined." - ); - } - - return $this->cos($scale + 2)->div($sin)->round($scale); + $scale = $scale ?? (static::DECIMAL_CONSTANTS)::pi()->scale; + $sin = $this->sin($scale + 2); + if ($sin->isZero()) { + throw new \DomainException( + "The cotangent of this 'angle' is undefined." + ); + } + + return $this->cos($scale + 2)->div($sin)->round($scale); } /** * Indicates if the passed parameter has the same sign as the method's bound object. * - * @param Decimal $b + * @param self $b * @return bool */ - public function hasSameSign(Decimal $b): bool + public function hasSameSign(self $b): bool { return $this->isPositive() && $b->isPositive() || $this->isNegative() && $b->isNegative(); } @@ -1349,14 +1354,14 @@ private static function normalizeSign(string $sign): string * Counts the number of significant digits of $val. * Assumes a consistent internal state (without zeros at the end or the start). * - * @param Decimal $val - * @param Decimal $abs $val->abs() + * @param self $val + * @param self $abs $val->abs() * @return int */ - private static function countSignificativeDigits(Decimal $val, Decimal $abs): int + private static function countSignificativeDigits(self $val, self $abs): int { return \strlen($val->value) - ( - ($abs->comp(DecimalConstants::One()) === -1) ? 2 : \max($val->scale, 1) + ($abs->comp((static::DECIMAL_CONSTANTS)::One()) === -1) ? 2 : \max($val->scale, 1) ) - ($val->isNegative() ? 1 : 0); } } diff --git a/src/DecimalConstants.php b/src/DecimalConstants.php index c35d16f..771eb3a 100644 --- a/src/DecimalConstants.php +++ b/src/DecimalConstants.php @@ -11,7 +11,7 @@ * * @author Andreu Correa Casablanca */ -final class DecimalConstants +class DecimalConstants { /** @var Decimal */ private static $ZERO = null; diff --git a/tests/Decimal/DecimalArccosTest.php b/tests/Decimal/DecimalArccosTest.php index 157a670..5c3872a 100644 --- a/tests/Decimal/DecimalArccosTest.php +++ b/tests/Decimal/DecimalArccosTest.php @@ -12,6 +12,7 @@ public function arccosProvider() { // Some values provided by wolframalpha return [ ['0.154', '1.41618102663394', 14], + ['0.154', '1.41618102663393517247013425592456', null], ['1', '0', 17], ['-1', '3.14159265358979324', 17], ]; diff --git a/tests/Decimal/DecimalArccotTest.php b/tests/Decimal/DecimalArccotTest.php index aeb2880..d178bfa 100644 --- a/tests/Decimal/DecimalArccotTest.php +++ b/tests/Decimal/DecimalArccotTest.php @@ -12,6 +12,7 @@ public function arccotProvider() { // Some values provided by wolframalpha return [ ['0.154', '1.41799671285823', 14], + ['0.154', '1.41799671285823208779719313430598', null], ['0', '1.57079632679489662', 17], ['-1', '-0.78540', 5], ]; diff --git a/tests/Decimal/DecimalArccscTest.php b/tests/Decimal/DecimalArccscTest.php index 526614a..2ff0857 100644 --- a/tests/Decimal/DecimalArccscTest.php +++ b/tests/Decimal/DecimalArccscTest.php @@ -12,6 +12,7 @@ public function arccscProvider() { // Some values provided by wolframalpha return [ ['25.546', '0.03915507577327', 14], + ['25.546', '0.03915507577326592075276730624736', null], ['1.5', '0.729728', 6], ['1', '1.57079632679489662', 17], ['-1', '-1.57079632679489662', 17], diff --git a/tests/Decimal/DecimalArcsecTest.php b/tests/Decimal/DecimalArcsecTest.php index 28a2b1a..7f059f0 100644 --- a/tests/Decimal/DecimalArcsecTest.php +++ b/tests/Decimal/DecimalArcsecTest.php @@ -12,6 +12,7 @@ public function arcsecProvider() { // Some values provided by wolframalpha return [ ['25.546', '1.53164125102163', 14], + ['25.546', '1.53164125102163069847855438539239', null], ['1.5', '0.841068', 6], ['1', '0', 17], ['-1', '3.14159265358979324', 17], diff --git a/tests/Decimal/DecimalArcsinTest.php b/tests/Decimal/DecimalArcsinTest.php index 162d792..3dcea56 100644 --- a/tests/Decimal/DecimalArcsinTest.php +++ b/tests/Decimal/DecimalArcsinTest.php @@ -12,6 +12,7 @@ public function arcsinProvider() { // Some values provided by wolframalpha return [ ['0.154', '0.15461530016096', 14], + ['0.154', '0.15461530016096144676118743571519', null], ['1', '1.57079632679489662', 17], ['-1', '-1.57079632679489662', 17], ]; diff --git a/tests/Decimal/DecimalArctanTest.php b/tests/Decimal/DecimalArctanTest.php index dc5494b..5d3afb7 100644 --- a/tests/Decimal/DecimalArctanTest.php +++ b/tests/Decimal/DecimalArctanTest.php @@ -12,6 +12,7 @@ public function arctanProvider() { // Some values provided by wolframalpha return [ ['0.154', '0.15279961393666', 14], + ['0.154', '0.15279961393666453143412855733377', null], ['0', '0', 17], ['-1', '-0.78539816339744831', 17], ]; diff --git a/tests/Decimal/DecimalCosTest.php b/tests/Decimal/DecimalCosTest.php index 79f2dcd..e499067 100644 --- a/tests/Decimal/DecimalCosTest.php +++ b/tests/Decimal/DecimalCosTest.php @@ -12,6 +12,7 @@ public function cosProvider() { // Some values provided by Mathematica return [ ['1', '0.54030230586814', 14], + ['1', '0.54030230586813971740093660744298', null], ['123.123', '-0.82483472946164834', 17], ['15000000000', '-0.72218064388924347683', 20] ]; @@ -23,7 +24,7 @@ public function cosProvider() { public function testSimple($nr, $answer, $digits) { $x = Decimal::fromString($nr); - $cosX = $x->cos((int)$digits); + $cosX = $x->cos($digits); $this->assertTrue( Decimal::fromString($answer)->equals($cosX), diff --git a/tests/Decimal/DecimalCosecTest.php b/tests/Decimal/DecimalCosecTest.php index 17e3a6f..e3fa144 100644 --- a/tests/Decimal/DecimalCosecTest.php +++ b/tests/Decimal/DecimalCosecTest.php @@ -12,6 +12,7 @@ public function cosecProvider() { // Some values provided by Mathematica return [ ['1', '1.18839510577812', 14], + ['1', '1.18839510577812121626159945237455', null], ['123.123', '-1.76874094322450309', 17], ['15000000000', '1.44570405082842149818', 20] ]; @@ -23,7 +24,7 @@ public function cosecProvider() { public function testSimple($nr, $answer, $digits) { $x = Decimal::fromString($nr); - $cosecX = $x->cosec((int)$digits); + $cosecX = $x->cosec($digits); $this->assertTrue( Decimal::fromString($answer)->equals($cosecX), diff --git a/tests/Decimal/DecimalCotanTest.php b/tests/Decimal/DecimalCotanTest.php index d6248c5..22ab522 100644 --- a/tests/Decimal/DecimalCotanTest.php +++ b/tests/Decimal/DecimalCotanTest.php @@ -13,6 +13,7 @@ public function cotanProvider() { // Some values providede by mathematica return [ ['1', '0.64209261593433', 14], + ['1', '0.64209261593433070300641998659427', null], ['123.123', '1.45891895739232371', 17], ['15000000000', '-1.04405948230055701685', 20] ]; @@ -37,8 +38,8 @@ public function testSimple($nr, $answer, $digits) */ public function testCotanPiDiv() { - $PI = DecimalConstants::PI(); - $PI->cotan(); + $pi = DecimalConstants::pi(); + $pi->cotan(30); } } \ No newline at end of file diff --git a/tests/Decimal/DecimalSecTest.php b/tests/Decimal/DecimalSecTest.php index 473843a..1019f8f 100644 --- a/tests/Decimal/DecimalSecTest.php +++ b/tests/Decimal/DecimalSecTest.php @@ -12,6 +12,7 @@ public function SecProvider() { // Some values provided by Mathematica return [ ['5', '3.52532008581609', 14], + ['5', '3.52532008581608840670180105996324', null], ['456.456', '-1.66172995090378344', 17], ['28000000000', '-1.11551381955633891873', 20], ]; @@ -23,7 +24,7 @@ public function SecProvider() { public function testSimple($nr, $answer, $digits) { $x = Decimal::fromString($nr); - $secX = $x->sec((int)$digits); + $secX = $x->sec($digits); $this->assertTrue( Decimal::fromString($answer)->equals($secX), diff --git a/tests/Decimal/DecimalSinTest.php b/tests/Decimal/DecimalSinTest.php index 9b1feff..44766a2 100644 --- a/tests/Decimal/DecimalSinTest.php +++ b/tests/Decimal/DecimalSinTest.php @@ -12,6 +12,7 @@ public function sinProvider() { // Some values providede by mathematica return [ ['1', '0.84147098480790', 14], + ['1', '0.84147098480789650665250232163030', null], ['123.123', '-0.56537391969733569', 17], ['15000000000', '0.69170450164193502844', 20] ]; diff --git a/tests/Decimal/DecimalTanTest.php b/tests/Decimal/DecimalTanTest.php index 43e01d2..289865a 100644 --- a/tests/Decimal/DecimalTanTest.php +++ b/tests/Decimal/DecimalTanTest.php @@ -13,6 +13,7 @@ public function tanProvider() { // Some values providede by mathematica return [ ['1', '1.55740772465490', 14], + ['1', '1.55740772465490223050697480745836', null], ['123.123', '0.68543903342472368', 17], ['15000000000', '-0.95779983511717825557', 20] ]; @@ -37,8 +38,8 @@ public function testSimple($nr, $answer, $digits) */ public function testTanPiTwoDiv() { - $PiDividedByTwo = DecimalConstants::PI()->div(Decimal::fromInteger(2)); - $PiDividedByTwo->tan(); + $piDividedByTwo = DecimalConstants::pi()->div(Decimal::fromInteger(2)); + $piDividedByTwo->tan(30); } }