JEMBOT MAWOT Bypass Shell
<?php
/**
* This file is part of the PrestaShop\Decimal package
*
* @author PrestaShop SA <contact@prestashop.com>
* @license https://opensource.org/licenses/MIT MIT License
*/
namespace PrestaShop\Decimal\Operation;
use PrestaShop\Decimal\DecimalNumber;
/**
* Computes the multiplication between two decimal numbers
*/
class Multiplication
{
/**
* Performs the multiplication
*
* @param DecimalNumber $a Left operand
* @param DecimalNumber $b Right operand
*
* @return DecimalNumber Result of the multiplication
*/
public function compute(DecimalNumber $a, DecimalNumber $b)
{
if (function_exists('bcmul')) {
return $this->computeUsingBcMath($a, $b);
}
return $this->computeWithoutBcMath($a, $b);
}
/**
* Performs the multiplication using BC Math
*
* @param DecimalNumber $a Left operand
* @param DecimalNumber $b Right operand
*
* @return DecimalNumber Result of the multiplication
*/
public function computeUsingBcMath(DecimalNumber $a, DecimalNumber $b)
{
$precision1 = $a->getPrecision();
$precision2 = $b->getPrecision();
return new DecimalNumber((string) bcmul($a, $b, $precision1 + $precision2));
}
/**
* Performs the multiplication without BC Math
*
* @param DecimalNumber $a Left operand
* @param DecimalNumber $b Right operand
*
* @return DecimalNumber Result of the multiplication
*/
public function computeWithoutBcMath(DecimalNumber $a, DecimalNumber $b)
{
$aAsString = (string) $a;
$bAsString = (string) $b;
// optimization: if either one is zero, the result is zero
if ('0' === $aAsString || '0' === $bAsString) {
return new DecimalNumber('0');
}
// optimization: if either one is one, the result is the other one
if ('1' === $aAsString) {
return $b;
}
if ('1' === $bAsString) {
return $a;
}
$result = $this->multiplyStrings(
ltrim($a->getCoefficient(), '0'),
ltrim($b->getCoefficient(), '0')
);
$sign = ($a->isNegative() xor $b->isNegative()) ? '-' : '';
// a multiplication has at most as many decimal figures as the sum
// of the number of decimal figures the factors have
$exponent = $a->getExponent() + $b->getExponent();
return new DecimalNumber($sign . $result, $exponent);
}
/**
* Multiplies two integer numbers as strings.
*
* This method implements a naive "long multiplication" algorithm.
*
* @param string $topNumber
* @param string $bottomNumber
*
* @return string
*/
private function multiplyStrings($topNumber, $bottomNumber)
{
$topNumberLength = strlen($topNumber);
$bottomNumberLength = strlen($bottomNumber);
if ($topNumberLength < $bottomNumberLength) {
// multiplication is commutative, and this algorithm
// performs better if the bottom number is shorter.
return $this->multiplyStrings($bottomNumber, $topNumber);
}
$stepNumber = 0;
$result = new DecimalNumber('0');
for ($i = $bottomNumberLength - 1; $i >= 0; --$i) {
$carryOver = 0;
$partialResult = '';
// optimization: we don't need to bother multiplying by zero
if ($bottomNumber[$i] === '0') {
++$stepNumber;
continue;
}
if ($bottomNumber[$i] === '1') {
// multiplying by one is the same as copying the top number
$partialResult = strrev($topNumber);
} else {
// digit-by-digit multiplication using carry-over
for ($j = $topNumberLength - 1; $j >= 0; --$j) {
$multiplicationResult = ($bottomNumber[$i] * $topNumber[$j]) + $carryOver;
$carryOver = floor($multiplicationResult / 10);
$partialResult .= $multiplicationResult % 10;
}
if ($carryOver > 0) {
$partialResult .= $carryOver;
}
}
// pad the partial result with as many zeros as performed steps
$padding = str_pad('', $stepNumber, '0');
$partialResult = $padding . $partialResult;
// add to the result
$result = $result->plus(
new DecimalNumber(strrev($partialResult))
);
++$stepNumber;
}
return (string) $result;
}
}
xxxxx1.0, XXX xxxx