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 subtraction of two decimal numbers
*/
class Subtraction
{
/**
* Maximum safe string size in order to be confident
* that it won't overflow the max int size when operating with it
*
* @var int
*/
private $maxSafeIntStringSize;
/**
* Constructor
*/
public function __construct()
{
$this->maxSafeIntStringSize = strlen((string) PHP_INT_MAX) - 1;
}
/**
* Performs the subtraction
*
* @param DecimalNumber $a Minuend
* @param DecimalNumber $b Subtrahend
*
* @return DecimalNumber Result of the subtraction
*/
public function compute(DecimalNumber $a, DecimalNumber $b)
{
if (function_exists('bcsub')) {
return $this->computeUsingBcMath($a, $b);
}
return $this->computeWithoutBcMath($a, $b);
}
/**
* Performs the subtraction using BC Math
*
* @param DecimalNumber $a Minuend
* @param DecimalNumber $b Subtrahend
*
* @return DecimalNumber Result of the subtraction
*/
public function computeUsingBcMath(DecimalNumber $a, DecimalNumber $b)
{
$precision1 = $a->getPrecision();
$precision2 = $b->getPrecision();
return new DecimalNumber((string) bcsub($a, $b, max($precision1, $precision2)));
}
/**
* Performs the subtraction without using BC Math
*
* @param DecimalNumber $a Minuend
* @param DecimalNumber $b Subtrahend
*
* @return DecimalNumber Result of the subtraction
*/
public function computeWithoutBcMath(DecimalNumber $a, DecimalNumber $b)
{
if ($a->isNegative()) {
if ($b->isNegative()) {
// if both minuend and subtrahend are negative
// perform the subtraction with inverted coefficients position and sign
// f(x, y) = |y| - |x|
// eg. f(-1, -2) = |-2| - |-1| = 2 - 1 = 1
// e.g. f(-2, -1) = |-1| - |-2| = 1 - 2 = -1
return $this->computeWithoutBcMath($b->toPositive(), $a->toPositive());
} else {
// if the minuend is negative and the subtrahend is positive,
// we can just add them as positive numbers and then invert the sign
// f(x, y) = -(|x| + y)
// eg. f(1, 2) = -(|-1| + 2) = -3
// eg. f(-2, 1) = -(|-2| + 1) = -3
return $a
->toPositive()
->plus($b)
->toNegative();
}
} elseif ($b->isNegative()) {
// if the minuend is positive subtrahend is negative, perform an addition
// f(x, y) = x + |y|
// eg. f(2, -1) = 2 + |-1| = 2 + 1 = 3
return $a->plus($b->toPositive());
}
// optimization: 0 - x = -x
if ('0' === (string) $a) {
return (!$b->isNegative()) ? $b->toNegative() : $b;
}
// optimization: x - 0 = x
if ('0' === (string) $b) {
return $a;
}
// pad coefficients with leading/trailing zeroes
list($coeff1, $coeff2) = $this->normalizeCoefficients($a, $b);
// compute the coefficient subtraction
if ($a->isGreaterThan($b)) {
$sub = $this->subtractStrings($coeff1, $coeff2);
$sign = '';
} else {
$sub = $this->subtractStrings($coeff2, $coeff1);
$sign = '-';
}
// keep the bigger exponent
$exponent = max($a->getExponent(), $b->getExponent());
return new DecimalNumber($sign . $sub, $exponent);
}
/**
* Normalizes coefficients by adding leading or trailing zeroes as needed so that both are the same length
*
* @param DecimalNumber $a
* @param DecimalNumber $b
*
* @return array An array containing the normalized coefficients
*/
private function normalizeCoefficients(DecimalNumber $a, DecimalNumber $b)
{
$exp1 = $a->getExponent();
$exp2 = $b->getExponent();
$coeff1 = $a->getCoefficient();
$coeff2 = $b->getCoefficient();
// add trailing zeroes if needed
if ($exp1 > $exp2) {
$coeff2 = str_pad($coeff2, strlen($coeff2) + $exp1 - $exp2, '0', STR_PAD_RIGHT);
} elseif ($exp1 < $exp2) {
$coeff1 = str_pad($coeff1, strlen($coeff1) + $exp2 - $exp1, '0', STR_PAD_RIGHT);
}
$len1 = strlen($coeff1);
$len2 = strlen($coeff2);
// add leading zeroes if needed
if ($len1 > $len2) {
$coeff2 = str_pad($coeff2, $len1, '0', STR_PAD_LEFT);
} elseif ($len1 < $len2) {
$coeff1 = str_pad($coeff1, $len2, '0', STR_PAD_LEFT);
}
return [$coeff1, $coeff2];
}
/**
* Subtracts $number2 to $number1.
* For this algorithm to work, $number1 has to be >= $number 2.
*
* @param string $number1
* @param string $number2
* @param bool $fractional [default=false]
* If true, the numbers will be treated as the fractional part of a number (padded with trailing zeroes).
* Otherwise, they will be treated as the integer part (padded with leading zeroes).
*
* @return string
*/
private function subtractStrings($number1, $number2, $fractional = false)
{
// find out which of the strings is longest
$maxLength = max(strlen($number1), strlen($number2));
// add leading or trailing zeroes as needed
$number1 = str_pad($number1, $maxLength, '0', $fractional ? STR_PAD_RIGHT : STR_PAD_LEFT);
$number2 = str_pad($number2, $maxLength, '0', $fractional ? STR_PAD_RIGHT : STR_PAD_LEFT);
$result = '';
$carryOver = 0;
for ($i = $maxLength - 1; 0 <= $i; --$i) {
$operand1 = $number1[$i] - $carryOver;
$operand2 = $number2[$i];
if ($operand1 >= $operand2) {
$result .= $operand1 - $operand2;
$carryOver = 0;
} else {
$result .= 10 + $operand1 - $operand2;
$carryOver = 1;
}
}
return strrev($result);
}
}
xxxxx1.0, XXX xxxx