Author: Andreu Correa Casablanca (castarco@litipk.com)
 public function testInfiniteRound()
 {
     $pInf = Decimal::getPositiveInfinite();
     $nInf = Decimal::getNegativeInfinite();
     $this->assertTrue($pInf->round()->equals($pInf));
     $this->assertTrue($nInf->round()->equals($nInf));
 }
 public function testPositiveNegativeDecimalAdd()
 {
     $n1 = Decimal::fromString('3.45');
     $n2 = Decimal::fromString('-7.67');
     $this->assertTrue($n1->add($n2)->equals(Decimal::fromString('-4.22')));
     $this->assertTrue($n2->add($n1)->equals(Decimal::fromString('-4.22')));
 }
 /**
  * @dataProvider modProvider
  */
 public function testFiniteFiniteMod($number, $mod, $answer, $scale = null)
 {
     $numberDec = Decimal::fromString($number);
     $modDec = Decimal::fromString($mod);
     $decimalAnswer = $numberDec->mod($modDec, $scale);
     $this->assertTrue(Decimal::fromString($answer)->equals($decimalAnswer), $decimalAnswer . ' % ' . $mod . ' must be equal to ' . $answer . ', but was ' . $decimalAnswer);
 }
 public function testNegativeNumbers()
 {
     $this->assertFalse(Decimal::fromInteger(-1)->isZero());
     $this->assertFalse(Decimal::fromFloat(-1.0)->isZero());
     $this->assertFalse(Decimal::fromFloat(-0.1)->isZero());
     $this->assertFalse(Decimal::fromString('-1')->isZero());
 }
 public function testBasicCase()
 {
     $n1 = Decimal::fromString('3.45');
     $this->assertTrue(Decimal::fromDecimal($n1)->equals($n1));
     $this->assertTrue(Decimal::fromDecimal($n1, 2)->equals($n1));
     $this->assertTrue(Decimal::fromDecimal($n1, 1)->equals(Decimal::fromString('3.5')));
     $this->assertTrue(Decimal::fromDecimal($n1, 0)->equals(Decimal::fromString('3')));
 }
 public function toFileMakerValue($value)
 {
     if (null === $value) {
         return null;
     }
     Assertion::integer($value);
     return Decimal::fromInteger($value);
 }
Example #7
0
 public function toFileMakerValue($value)
 {
     if (null === $value) {
         return null;
     }
     Assertion::float($value);
     return Decimal::fromFloat($value);
 }
 public function testNegativeInfiniteNegativePower()
 {
     $nInf = InfiniteDecimal::getNegativeInfinite();
     $zero = DecimalConstants::Zero();
     $this->assertTrue($nInf->pow(Decimal::fromInteger(-1))->equals($zero));
     $this->assertTrue($nInf->pow(Decimal::fromInteger(-2))->equals($zero));
     $this->assertTrue($nInf->pow(Decimal::fromInteger(-3))->equals($zero));
     $this->assertTrue($nInf->pow($nInf)->equals($zero));
 }
 public function __invoke($value) : ValidationResult
 {
     Assertion::numeric($value);
     $decimalValue = Decimal::fromString((string) $value);
     if ($decimalValue->comp($this->limit) === 1) {
         return new ValidationResult(new ValidationError('error.max-number', ['limit' => (string) $this->limit]));
     }
     return new ValidationResult();
 }
Example #10
0
 function handleValueFromDb($value, array $fieldInfo, $row)
 {
     if ($value === null && $this->zeroIfNull) {
         $value = "0";
     }
     if ($value !== null) {
         return BigNumbers\Decimal::fromString($value);
     }
 }
 public function testInfiniteInfiniteComp()
 {
     $pInf = Decimal::getPositiveInfinite();
     $nInf = Decimal::getNegativeInfinite();
     $this->assertTrue($pInf->comp($pInf) === 0);
     $this->assertTrue($nInf->comp($nInf) === 0);
     $this->assertTrue($pInf->comp($nInf) === 1);
     $this->assertTrue($nInf->comp($pInf) === -1);
 }
 public function testAsFloat()
 {
     $this->assertEquals(1.0, Decimal::fromString('1.0')->asFloat());
     $this->assertTrue(is_float(Decimal::fromString('1.0')->asFloat()));
     $this->assertEquals(1.0, Decimal::fromInteger(1)->asFloat());
     $this->assertTrue(is_float(Decimal::fromInteger(1)->asFloat()));
     $this->assertEquals(1.0, Decimal::fromFloat(1.0)->asFloat());
     $this->assertEquals(1.123123123, Decimal::fromString('1.123123123')->asFloat());
     $this->assertTrue(is_float(Decimal::fromFloat(1.0)->asFloat()));
     $this->assertTrue(is_float(Decimal::fromString('1.123123123')->asFloat()));
 }
Example #13
0
 /**
  * {@inheritDoc}
  */
 public function convertToPHPValue($value, AbstractPlatform $platform)
 {
     if ($value === null) {
         return null;
     }
     try {
         return Decimal::create($value);
     } catch (\Exception $e) {
         throw ConversionException::conversionFailedFormat($value, $this->getName(), '0.0');
     }
 }
 public function testFiniteInfiniteDiv()
 {
     $pTen = Decimal::fromInteger(10);
     $nTen = Decimal::fromInteger(-10);
     $pInf = InfiniteDecimal::getPositiveInfinite();
     $nInf = InfiniteDecimal::getNegativeInfinite();
     $this->assertTrue($pInf->div($pTen)->equals($pInf));
     $this->assertTrue($pInf->div($nTen)->equals($nInf));
     $this->assertTrue($nInf->div($pTen)->equals($nInf));
     $this->assertTrue($nInf->div($nTen)->equals($pInf));
     $this->assertTrue($pTen->div($pInf)->isZero());
     $this->assertTrue($nTen->div($pInf)->isZero());
     $this->assertTrue($pTen->div($nInf)->isZero());
     $this->assertTrue($nTen->div($nInf)->isZero());
 }
 public function testBasicDiv()
 {
     $one = Decimal::fromInteger(1);
     $two = Decimal::fromInteger(2);
     $four = Decimal::fromInteger(4);
     $eight = Decimal::fromInteger(8);
     // Integer exact division
     $this->assertTrue($eight->div($two)->equals($four));
     $this->assertTrue($eight->div($four)->equals($two));
     // Arbitrary precision division
     $this->assertTrue($one->div($eight, 0)->equals(Decimal::fromString('0')));
     $this->assertTrue($one->div($eight, 1)->equals(Decimal::fromString('0.1')));
     $this->assertTrue($one->div($eight, 2)->equals(Decimal::fromString('0.13')));
     $this->assertTrue($one->div($eight, 3)->equals(Decimal::fromString('0.125')));
 }
 public function __invoke(string $value)
 {
     $cleanedValue = preg_replace_callback('(^[^\\d-.]*(-?)([^.]*)(.?)(.*)$)', function (array $match) : string {
         return $match[1] . preg_replace('([^\\d]+)', '', $match[2]) . $match[3] . preg_replace('([^\\d]+)', '', $match[4]);
     }, $value);
     if ('' === $cleanedValue) {
         return null;
     }
     if ('-' === $cleanedValue) {
         $cleanedValue = '0';
     }
     if (0 === strpos($cleanedValue, '.')) {
         $cleanedValue = '0' . $cleanedValue;
     }
     return Decimal::fromString($cleanedValue);
 }
 public function testNotIntegers()
 {
     $this->assertFalse(Decimal::fromString("-200.001")->isInteger());
     $this->assertFalse(Decimal::fromString("-2.001")->isInteger());
     $this->assertFalse(Decimal::fromString("-1.001")->isInteger());
     $this->assertFalse(Decimal::fromString("0.001")->isInteger());
     $this->assertFalse(Decimal::fromString("1.001")->isInteger());
     $this->assertFalse(Decimal::fromString("2.001")->isInteger());
     $this->assertFalse(Decimal::fromString("200.001")->isInteger());
     $this->assertFalse(Decimal::fromFloat(-200.001)->isInteger());
     $this->assertFalse(Decimal::fromFloat(-2.001)->isInteger());
     $this->assertFalse(Decimal::fromFloat(-1.001)->isInteger());
     $this->assertFalse(Decimal::fromFloat(0.001)->isInteger());
     $this->assertFalse(Decimal::fromFloat(1.001)->isInteger());
     $this->assertFalse(Decimal::fromFloat(2.001)->isInteger());
     $this->assertFalse(Decimal::fromFloat(200.001)->isInteger());
 }
Example #18
0
 /**
  * Parse condition divided to field, operator and value
  *
  * @param string field
  * @return array
  */
 protected function _parseCondition($field, $operator, $value)
 {
     // sum function
     $sum = function ($item) use($field) {
         $sum = Decimal::fromInteger(0);
         foreach ($item[$field] as $s) {
             $sum = $sum->add($s);
         }
         return $sum;
     };
     // convert value to decimal
     $value = Decimal::fromFloat($this->_parseDecimal($value));
     switch ($operator) {
         case '=':
             return function ($item) use($sum, $value) {
                 $total = $sum($item);
                 return $total->equals($value);
             };
         case 'NOT':
             return function ($item) use($sum, $value) {
                 $total = $sum($item);
                 return $total->equals($value);
             };
         case '>=':
             return function ($item) use($sum, $value) {
                 $total = $sum($item);
                 return $total->comp($value) > -1;
             };
         case '<=':
             return function ($item) use($sum, $value) {
                 $total = $sum($item);
                 return $total->comp($value) < 1;
             };
         case '>':
             return function ($item) use($sum, $value) {
                 $total = $sum($item);
                 return $total->comp($value) > 0;
             };
         case '<':
             return function ($item) use($sum, $value) {
                 $total = $sum($item);
                 return $total->comp($value) < 0;
             };
     }
     return [$field . $operator => $value];
 }
 public function testInfiniteMul()
 {
     $pInf = Decimal::getPositiveInfinite();
     $nInf = Decimal::getNegativeInfinite();
     $pOne = Decimal::fromInteger(1);
     $nOne = Decimal::fromInteger(-1);
     $oipp = $pOne->mul($pInf);
     $oipn = $pOne->mul($nInf);
     $oinp = $nOne->mul($pInf);
     $oinn = $nOne->mul($nInf);
     $this->assertTrue($oipp->isPositive());
     $this->assertTrue($oinn->isPositive());
     $this->assertTrue($oinp->isNegative());
     $this->assertTrue($oipn->isNegative());
     $this->assertTrue($oipp->isInfinite());
     $this->assertTrue($oipn->isInfinite());
     $this->assertTrue($oinp->isInfinite());
     $this->assertTrue($oinn->isInfinite());
 }
Example #20
0
    function testDecimalToDb()
    {
        $d = Test\Factory::managerNoteModelCustom('
            /** :amiss = true; */
            class Pants {
                /** :amiss = {"field": {"primary": true, "type": "autoinc"}}; */
                public $id;

                /** :amiss = {"field": {"type": "decimal"}}; */
                public $num;
            }
        ');
        $c = $d->ns . '\\Pants';
        $obj = new $c();
        $obj->num = Decimal::fromString("1.23456");
        $d->manager->insert($obj);
        $out = $d->connector->query("SELECT num FROM pants")->fetchColumn(0);
        $this->assertEquals("1.23456", $out);
    }
 public function testScaledComp()
 {
     // Transitivity
     $this->assertEquals(0, Decimal::fromFloat(1.001)->comp(Decimal::fromFloat(1.01), 1));
     $this->assertEquals(0, Decimal::fromFloat(1.01)->comp(Decimal::fromFloat(1.004), 1));
     $this->assertEquals(0, Decimal::fromFloat(1.001)->comp(Decimal::fromFloat(1.004), 1));
     // Reflexivity
     $this->assertEquals(0, Decimal::fromFloat(1.00525)->comp(Decimal::fromFloat(1.00525), 2));
     // Symmetry
     $this->assertEquals(0, Decimal::fromFloat(1.01)->comp(Decimal::fromFloat(1.001), 1));
     $this->assertEquals(0, Decimal::fromFloat(1.004)->comp(Decimal::fromFloat(1.01), 1));
     $this->assertEquals(0, Decimal::fromFloat(1.004)->comp(Decimal::fromFloat(1.001), 1));
     // Proper rounding
     $this->assertEquals(0, Decimal::fromFloat(1.004)->comp(Decimal::fromFloat(1.0), 2));
     // Warning, float to Decimal conversion can have unexpected behaviors, like converting
     // 1.005 to Decimal("1.0049999999999999")
     $this->assertEquals(0, Decimal::fromFloat(1.0050000000001)->comp(Decimal::fromFloat(1.01), 2));
     $this->assertEquals(0, Decimal::fromString("1.005")->comp(Decimal::fromString("1.010"), 2));
     # Proper rounding
     $this->assertEquals(-1, Decimal::fromFloat(1.004)->comp(Decimal::fromFloat(1.0050000000001), 2));
 }
 public function testInfiniteInfiniteSub()
 {
     $pInf = Decimal::getPositiveInfinite();
     $nInf = Decimal::getNegativeInfinite();
     $catched = false;
     try {
         $pInf->sub($pInf);
     } catch (\DomainException $e) {
         $catched = true;
     }
     $this->assertTrue($catched);
     $catched = false;
     try {
         $nInf->sub($nInf);
     } catch (\DomainException $e) {
         $catched = true;
     }
     $this->assertTrue($catched);
     $this->assertTrue($pInf->sub($nInf)->equals($pInf));
     $this->assertTrue($nInf->sub($pInf)->equals($nInf));
 }
Example #23
0
 private function isDecimal($v)
 {
     try {
         BigNumbers\Decimal::create($v);
         return true;
     } catch (\Exception $e) {
         return false;
     }
 }
 public function testCreateFromDecimal()
 {
     $this->assertTrue(Decimal::create(Decimal::fromString('345.76'), 1)->equals(Decimal::fromString('345.8')));
     $this->assertTrue(Decimal::create(Decimal::fromString('345.76'), 2)->equals(Decimal::fromString('345.76')));
 }
 public function testPositiveAdditiveInverse()
 {
     $this->assertTrue(Decimal::fromInteger(1)->additiveInverse()->equals(Decimal::fromInteger(-1)));
     $this->assertTrue(Decimal::fromString('1.768')->additiveInverse()->equals(Decimal::fromString('-1.768')));
 }
 /**
  * @dataProvider floatProvider
  */
 public function testFromFloat($in, $str, $scale = null, $removeZeroes = false)
 {
     $v = Decimal::fromFloat($in, $scale, $removeZeroes);
     $this->assertSame($str, $v->innerValue());
 }
 public function testGetInfinite()
 {
     $this->assertTrue(Decimal::getPositiveInfinite()->equals(InfiniteDecimal::getPositiveInfinite()));
     $this->assertTrue(Decimal::getNegativeInfinite()->equals(InfiniteDecimal::getNegativeInfinite()));
 }
 public function testSuccessfulConversionToFileMaker()
 {
     $type = new DecimalType();
     $value = Decimal::fromInteger(1);
     $this->assertSame($value, $type->toFileMakerValue($value));
 }
Example #29
0
 protected function applyValue($input, Context $ctx)
 {
     $output = $input;
     cast:
     $allowString = $this->allowString === null ? true : $this->allowString;
     try {
         $cast = $input;
         if ($allowString && is_string($input)) {
             if ($input === '') {
                 $cast = null;
             } else {
                 $cast = BigNumbers\Decimal::fromString($input);
             }
         } elseif ($this->allowInt && is_int($input)) {
             $cast = BigNumbers\Decimal::fromInteger($input);
         } elseif ($this->allowDouble && is_float($input)) {
             $cast = BigNumbers\Decimal::fromFloat($input);
         }
         if ($cast !== $input) {
             $ctx->setChange(Change::Internal);
         }
         $output = $cast;
     } catch (\Exception $ex) {
         $ctx->addReason($this, ['id' => 'decimal.invalid']);
         goto done;
     }
     // must cast before this so we can cast to null
     if ($output === null) {
         goto done;
     }
     type:
     if (!$output instanceof BigNumbers\Decimal) {
         $ctx->addReason($this, ['id' => 'decimal.invalid']);
         goto done;
     }
     scale:
     if ($this->scale !== null) {
         if (preg_match('/\\.([0-9]+)$/', $output . '', $match)) {
             $inScale = strlen($match[1]);
             if ($inScale > $this->scale) {
                 $ctx->addReason($this, ['id' => 'decimal.scale', 'params' => ['scale' => $inScale, 'expected' => $this->scale]]);
             }
         }
     }
     precision:
     if ($this->precision !== null) {
         $digits = preg_replace("/[^0-9]/", '', $output . '');
         $inPrecision = strlen($digits);
         if ($inPrecision > $this->precision) {
             $ctx->addReason($this, ['id' => 'decimal.precision', 'params' => ['precision' => $inPrecision, 'expected' => $this->precision]]);
         }
     }
     minmax:
     $min = $this->min !== null ? BigNumbers\Decimal::create($this->min) : null;
     $max = $this->max !== null ? BigNumbers\Decimal::create($this->max) : null;
     if ($min !== null && $max !== null) {
         if ($output->comp($min) < 0 || $output->comp($max) > 0) {
             $ctx->addReason($this, ['id' => 'decimal.between', 'params' => ['atLeast' => $min . '', 'atMost' => $max . '']]);
         }
     } elseif ($min !== null) {
         if ($output->comp($min) < 0) {
             $ctx->addReason($this, ['id' => 'decimal.atLeast', 'params' => ['atLeast' => $min . '']]);
         }
     } elseif ($max !== null) {
         if ($output->comp($max) > 0) {
             $ctx->addReason($this, ['id' => 'decimal.atMost', 'params' => ['atMost' => $max . '']]);
         }
     }
     divisibleBy:
     if ($this->divisibleBy !== null) {
         $divisibleBy = !$this->divisibleBy instanceof BigNumbers\Decimal ? BigNumbers\Decimal::create($this->divisibleBy) : $this->divisibleBy;
         if (!$output->mod($divisibleBy)->isZero()) {
             $dvFmt = $this->removeTrailingZeroes($divisibleBy);
             $ctx->addReason($this, ['id' => 'decimal.divisibleBy', 'params' => ['divisibleBy' => $dvFmt]]);
         }
     }
     done:
     if ($this->emitString && $output instanceof BigNumbers\Decimal) {
         $output = $output->innerValue();
         if (!is_string($input)) {
             $ctx->setChange(Change::Internal);
         }
     }
     return $output;
 }
Example #30
0
 /**
  * Calculate totals
  *
  * @param callable filter
  * @return array
  */
 protected function _calculateTotals($filter)
 {
     if (!is_callable($filter)) {
         throw new \InvalidArgumentException('Filter for _calculateTotals method has to be callable.');
     }
     $taxTotals = [];
     $weight = Decimal::fromInteger(0);
     foreach ($this->getItems($filter) as $item) {
         $price = $this->getItemPrice($item);
         if (!isset($taxTotals[$item->getTaxRate()])) {
             $taxTotals[$item->getTaxRate()] = Decimal::fromInteger(0);
         }
         $taxTotals[$item->getTaxRate()] = $taxTotals[$item->getTaxRate()]->add($price);
         // weight
         if ($item instanceof WeightedCartItemInterface) {
             $itemWeight = Decimal::fromFloat((double) $item->getWeight());
             $itemWeight = $itemWeight->mul(Decimal::fromInteger((int) $item->getCartQuantity()));
             $weight = $weight->add($itemWeight);
         }
     }
     $totals = ['subtotals' => [], 'taxes' => [], 'totals' => [], 'weight' => $weight->round(6)];
     foreach ($taxTotals as $taxRate => $amount) {
         if ($this->_pricesWithVat) {
             $totals['totals'][$taxRate] = $amount;
             $totals['taxes'][$taxRate] = $amount->mul(Decimal::fromFloat(1 - 1 / (1 + (double) $taxRate / 100)))->round($this->_roundingDecimals);
             $totals['subtotals'][$taxRate] = $amount->sub($totals['taxes'][$taxRate]);
         } else {
             $totals['subtotals'][$taxRate] = $amount;
             $totals['taxes'][$taxRate] = $amount->mul(Decimal::fromFloat((double) $taxRate / 100))->round($this->_roundingDecimals);
             $totals['totals'][$taxRate] = $amount->add($totals['taxes'][$taxRate]);
         }
     }
     return $totals;
 }