diff --git a/.travis.yml b/.travis.yml index 6ee872f..3a4c388 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,9 +3,14 @@ language: php php: - 5.3 - 5.4 + - 5.5 + - hhvm before_script: - - curl -s http://getcomposer.org/installer | php -- --quiet - - php composer.phar install --dev + - composer install --dev --prefer-source script: phpunit + +matrix: + allow_failures: + - php: hhvm diff --git a/src/Moontoast/Math/BigNumber.php b/src/Moontoast/Math/BigNumber.php index ae0dc4c..a934335 100644 --- a/src/Moontoast/Math/BigNumber.php +++ b/src/Moontoast/Math/BigNumber.php @@ -43,18 +43,27 @@ class BigNumber */ protected $numberScale; + /** + * @var bool + */ + protected $mutable; + /** * Constructs a BigNumber object from a string, integer, float, or any * object that may be cast to a string, resulting in a numeric string value * - * @param mixed $number May be of any type that can be cast to a string - * representation of a base 10 number - * @param int $scale (optional) Specifies the default number of digits after the decimal - * place to be used in operations for this BigNumber - * @return void + * @param mixed $number May be of any type that can be cast to a string + * representation of a base 10 number + * @param int $scale (optional) Specifies the default number of digits after the decimal + * place to be used in operations for this BigNumber + * @param bool $mutable (optional) If set to false, a new instance of BigNumber is returned + * when an operation is done on the instance. + * */ - public function __construct($number, $scale = null) + public function __construct($number, $scale = null, $mutable = true) { + $this->mutable = $mutable; + if ($scale) { $this->setScale($scale); } @@ -72,6 +81,14 @@ public function __toString() return (string) $this->getValue(); } + /** + * @return boolean + */ + public function getMutable() + { + return $this->mutable; + } + /** * Sets the current number to the absolute value of itself * @@ -82,10 +99,26 @@ public function abs() // Use substr() to find the negative sign at the beginning of the // number, rather than using signum() to determine the sign. if (substr($this->numberValue, 0, 1) === '-') { - $this->numberValue = substr($this->numberValue, 1); + return $this->assignValue(substr($this->numberValue, 1)); } - return $this; + return $this->assignValue($this->numberValue); + } + + /** + * @param $value + * + * @return $this|BigNumber + */ + protected function assignValue($value) + { + if ($this->mutable) { + $this->numberValue = $value; + + return $this; + } + + return self::create($value, $this->getScale(), false); } /** @@ -93,18 +126,18 @@ public function abs() * * @param mixed $number May be of any type that can be cast to a string * representation of a base 10 number + * * @return BigNumber for fluent interface + * * @link http://www.php.net/bcadd */ public function add($number) { - $this->numberValue = bcadd( + return $this->assignValue(bcadd( $this->numberValue, $this->filterNumber($number), $this->getScale() - ); - - return $this; + )); } /** @@ -112,6 +145,7 @@ public function add($number) * if necessary * * @return BigNumber for fluent interface + * * @link http://www.php.net/ceil */ public function ceil() @@ -126,9 +160,7 @@ public function ceil() } } - $this->numberValue = bcadd($number, '0', 0); - - return $this; + return $this->assignValue(bcadd($number, '0', 0)); } /** @@ -140,6 +172,7 @@ public function ceil() * @param mixed $number May be of any type that can be cast to a string * representation of a base 10 number * @return int + * * @link http://www.php.net/bccomp */ public function compareTo($number) @@ -155,6 +188,7 @@ public function compareTo($number) * Returns the current value converted to an arbitrary base * * @param int $base The base to convert the current number to + * * @return string String representation of the number in the given base */ public function convertToBase($base) @@ -177,8 +211,11 @@ public function decrement() * * @param mixed $number May be of any type that can be cast to a string * representation of a base 10 number + * * @return BigNumber for fluent interface + * * @throws Exception\ArithmeticException if $number is zero + * * @link http://www.php.net/bcdiv */ public function divide($number) @@ -189,13 +226,11 @@ public function divide($number) throw new Exception\ArithmeticException('Division by zero'); } - $this->numberValue = bcdiv( + return $this->assignValue(bcdiv( $this->numberValue, $number, $this->getScale() - ); - - return $this; + )); } /** @@ -203,6 +238,7 @@ public function divide($number) * if necessary * * @return BigNumber for fluent interface + * * @link http://www.php.net/floor */ public function floor() @@ -217,9 +253,7 @@ public function floor() } } - $this->numberValue = bcadd($number, '0', 0); - - return $this; + return $this->assignValue(bcadd($number, '0', 0)); } /** @@ -264,6 +298,7 @@ public function increment() * * @param mixed $number May be of any type that can be cast to a string * representation of a base 10 number + * * @return bool */ public function isEqualTo($number) @@ -276,6 +311,7 @@ public function isEqualTo($number) * * @param mixed $number May be of any type that can be cast to a string * representation of a base 10 number + * * @return bool */ public function isGreaterThan($number) @@ -288,6 +324,7 @@ public function isGreaterThan($number) * * @param mixed $number May be of any type that can be cast to a string * representation of a base 10 number + * * @return bool */ public function isGreaterThanOrEqualTo($number) @@ -300,6 +337,7 @@ public function isGreaterThanOrEqualTo($number) * * @param mixed $number May be of any type that can be cast to a string * representation of a base 10 number + * * @return bool */ public function isLessThan($number) @@ -312,6 +350,7 @@ public function isLessThan($number) * * @param mixed $number May be of any type that can be cast to a string * representation of a base 10 number + * * @return bool */ public function isLessThanOrEqualTo($number) @@ -344,8 +383,11 @@ public function isPositive() * * @param mixed $number May be of any type that can be cast to a string * representation of a base 10 number + * * @return BigNumber for fluent interface + * * @throws Exception\ArithmeticException if $number is zero + * * @link http://www.php.net/bcmod */ public function mod($number) @@ -356,12 +398,10 @@ public function mod($number) throw new Exception\ArithmeticException('Division by zero'); } - $this->numberValue = bcmod( + return $this->assignValue(bcmod( $this->numberValue, $number - ); - - return $this; + )); } /** @@ -369,18 +409,18 @@ public function mod($number) * * @param mixed $number May be of any type that can be cast to a string * representation of a base 10 number + * * @return BigNumber for fluent interface + * * @link http://www.php.net/bcmul */ public function multiply($number) { - $this->numberValue = bcmul( + return $this->assignValue(bcmul( $this->numberValue, $this->filterNumber($number), $this->getScale() - ); - - return $this; + )); } /** @@ -398,18 +438,18 @@ public function negate() * * @param mixed $number May be of any type that can be cast to a string * representation of a base 10 number + * * @return BigNumber for fluent interface + * * @link http://www.php.net/bcpow */ public function pow($number) { - $this->numberValue = bcpow( + return $this->assignValue(bcpow( $this->numberValue, $this->filterNumber($number), $this->getScale() - ); - - return $this; + )); } /** @@ -430,8 +470,11 @@ public function pow($number) * representation of a base 10 number * @param mixed $mod May be of any type that can be cast to a string * representation of a base 10 number + * * @return BigNumber for fluent interface + * * @throws Exception\ArithmeticException if $number is zero + * * @link http://www.php.net/bcpowmod */ public function powMod($pow, $mod) @@ -442,20 +485,19 @@ public function powMod($pow, $mod) throw new Exception\ArithmeticException('Division by zero'); } - $this->numberValue = bcpowmod( + return $this->assignValue(bcpowmod( $this->numberValue, $this->filterNumber($pow), $mod, $this->getScale() - ); - - return $this; + )); } /** * Rounds the current number to the nearest integer * * @return BigNumber for fluent interface + * * @todo Implement precision digits */ public function round() @@ -470,13 +512,11 @@ public function round() $roundedDiff = round($diff); } - $this->numberValue = bcadd( + return $this->assignValue(bcadd( $floored, $roundedDiff, 0 - ); - - return $this; + )); } /** @@ -484,6 +524,7 @@ public function round() * * @param int $scale Specifies the default number of digits after the decimal * place to be used in operations for this BigNumber + * * @return BigNumber for fluent interface */ public function setScale($scale) @@ -498,6 +539,7 @@ public function setScale($scale) * * @param mixed $number May be of any type that can be cast to a string * representation of a base 10 number + * * @return BigNumber for fluent interface */ public function setValue($number) @@ -518,32 +560,30 @@ public function setValue($number) * Shifts the current number $bits to the left * * @param int $bits + * * @return BigNumber for fluent interface */ public function shiftLeft($bits) { - $this->numberValue = bcmul( + return $this->assignValue(bcmul( $this->numberValue, bcpow('2', $bits) - ); - - return $this; + )); } /** * Shifts the current number $bits to the right * * @param int $bits + * * @return BigNumber for fluent interface */ public function shiftRight($bits) { - $this->numberValue = bcdiv( + return $this->assignValue(bcdiv( $this->numberValue, bcpow('2', $bits) - ); - - return $this; + )); } /** @@ -566,16 +606,15 @@ public function signum() * Finds the square root of the current number * * @return BigNumber for fluent interface + * * @link http://www.php.net/bcsqrt */ public function sqrt() { - $this->numberValue = bcsqrt( + return $this->assignValue(bcsqrt( $this->numberValue, $this->getScale() - ); - - return $this; + )); } /** @@ -583,24 +622,25 @@ public function sqrt() * * @param mixed $number May be of any type that can be cast to a string * representation of a base 10 number + * * @return BigNumber for fluent interface + * * @link http://www.php.net/bcsub */ public function subtract($number) { - $this->numberValue = bcsub( + return $this->assignValue(bcsub( $this->numberValue, $this->filterNumber($number), $this->getScale() - ); - - return $this; + )); } /** * Filters a number, converting it to a string value * * @param mixed $number + * * @return string */ protected function filterNumber($number) @@ -618,6 +658,7 @@ protected function filterNumber($number) * @param string|int $number The number to convert * @param int $fromBase (optional) The base $number is in; defaults to 10 * @param int $toBase (optional) The base to convert $number to; defaults to 16 + * * @return string */ public static function baseConvert($number, $fromBase = 10, $toBase = 16) @@ -632,7 +673,9 @@ public static function baseConvert($number, $fromBase = 10, $toBase = 16) * * @param string|int $number The number to convert * @param int $toBase The base to convert $number to + * * @return string + * * @throws \InvalidArgumentException if $toBase is outside the range 2 to 36 */ public static function convertFromBase10($number, $toBase) @@ -666,7 +709,9 @@ public static function convertFromBase10($number, $toBase) * * @param string|int $number The number to convert * @param int $fromBase The base $number is in + * * @return string + * * @throws \InvalidArgumentException if $fromBase is outside the range 2 to 36 */ public static function convertToBase10($number, $fromBase) @@ -704,6 +749,22 @@ public static function convertToBase10($number, $fromBase) return $base10Num; } + /** + * @param mixed $value + * @param null $scale + * @param bool $muttable + * + * @return BigNumber + */ + public static function create($value, $scale = null, $muttable = true) + { + if ($value instanceof self) { + return new self($value->getValue(), $value->getScale(), $value->getMutable()); + } + + return new self($value, $scale, $muttable); + } + /** * Changes the default scale used by all Binary Calculator functions * diff --git a/src/Moontoast/Math/ImmutableBigNumber.php b/src/Moontoast/Math/ImmutableBigNumber.php new file mode 100644 index 0000000..db0079c --- /dev/null +++ b/src/Moontoast/Math/ImmutableBigNumber.php @@ -0,0 +1,38 @@ +