fix(decimal): optimize integer to decimal conversion without string intermediate

- Changed integer to decimal conversion from php::toDecimal(php::toString(expr))
  to direct php::toDecimal(expr)
- Added test case to verify decimal integer operand does not convert through string
- Created new test file decimal-int-operand.php to test decimal multiplication
  with integer operands
- Added phpt test for decimal multiplication accepting Int and dynamically typed
  Int operands
- Fixed type conversion trait to handle INT type directly without string conversion
pull/44/head
韩天峰 3 weeks ago
parent 21d0224769
commit e345b0d82a
  1. 22
      phpunit/code/big-numeric/decimal-int-operand.php
  2. 25
      phpunit/src/BigNumericValidationTest.php
  3. 2
      src/Parser/TypeConversionTrait.php
  4. 22
      tests/compiler/decimal/int-operand-without-string-conversion.phpt

@ -0,0 +1,22 @@
<?php
function multiplyDecimalByInt(int $factor): string
{
$value = std::decimal('123.456');
$value = $value * 1000;
$value = $value * $factor;
return $value->toString();
}
function multiplyDecimalByVar($factor): string
{
$value = std::decimal('123.456');
$value = $value * $factor;
return $value->toString();
}
function main(): void
{
echo multiplyDecimalByInt(1000), "\n";
echo multiplyDecimalByVar(1000), "\n";
}

@ -2,6 +2,31 @@
class BigNumericValidationTest extends \BaseTest
{
public function testDecimalIntegerOperandDoesNotConvertThroughString(): void
{
global $translator;
$compiler = \TypePhp\CompilerTest::create(ROOT_PATH);
$translator = $compiler;
$testFile = __DIR__ . '/../code/big-numeric/decimal-int-operand.php';
$compiler->addFiles([$testFile]);
$compiler->prepareFile($testFile);
$cppFile = $compiler->convertFile($testFile);
$cpp = file_get_contents($cppFile);
$this->assertStringContainsString(
'php::Decimal::mul(value, php::toDecimal(1000L))',
$cpp,
);
$this->assertStringNotContainsString(
'php::toDecimal(php::toString(1000L))',
$cpp,
);
$this->assertStringContainsString(
'php::Decimal::mul(value, factor)',
$cpp,
);
}
public function testDecimalPowerOperatorIsRejected(): void
{
$this->exec("Operator '**' is not supported for Decimal or BigFloat", 'big-numeric/decimal-pow-operator.php');

@ -85,7 +85,7 @@ trait TypeConversionTrait
return 'php::toDecimal(php::toString(' . $expr . '))';
}
if ($fromType === Type::INT) {
return 'php::toDecimal(php::toString(' . $expr . '))';
return 'php::toDecimal(' . $expr . ')';
}
if ($fromType === Type::BIGINT) {
return 'php::toDecimal(php::BigInt::toString(' . $expr . '))';

@ -0,0 +1,22 @@
--TEST--
Decimal multiplication accepts Int and dynamically typed Int operands
--FILE--
<?php
function multiplyDecimal($factor): string
{
$value = std::decimal('123.456');
$value = $value * $factor;
return $value->toString();
}
function main(): void
{
$value = std::decimal('123.456');
echo ($value * 1000)->toString(), "\n";
echo multiplyDecimal(1000), "\n";
}
?>
--EXPECT--
123456.000
123456.000
Loading…
Cancel
Save