Description
Operator Strength Reduction optimizer directly substitutes a sub-expression x - x with 0, not accounting for INF or NAN values being supplied to x (inf - inf and nan - nan must produce nan). Other affected cases include 0 * inf returning 0 instead of NAN, and sqrt(-1) / sqrt(-1) getting substituted for 1 despite sqrt(-1) === NAN (NAN / NAN === NAN).
As variable resolution occurs during evaluation, x - x cannot be resolved during parsing although 1 - 1 and inf - inf can. One way to address this would be to resolve operations between numeric literal operands during parsing and implement a mechanism to toggle optimizations that disregard INF and NAN (like GCC's FloatingPointMath flags).
Workarounds
- Filter out operator strength reduction optimization from
ExpressionOptimizerRegistry
$parser = Parser::createDefault();
$optimizations = new ExpressionOptimizerRegistry();
foreach($parser->getExpressionOptimizerRegistry()->getRegistered() as $identifier => $value){
if(!($value instanceof OperatorStrengthReductionExpressionOptimizer)){
$optimizations->register($identifier, $value);
}
}
$parser = new Parser(
$parser->getBinaryOperatorRegistry(),
$parser->getUnaryOperatorRegistry(),
$parser->getConstantRegistry(),
$parser->getFunctionRegistry(),
$optimizations,
$parser->getScanner()
);
- Disable optimizations altogether —
$parser = Parser::createUnoptimized();
Description
Operator Strength Reduction optimizer directly substitutes a sub-expression
x - xwith0, not accounting forINForNANvalues being supplied tox(inf - infandnan - nanmust producenan). Other affected cases include0 * infreturning0instead ofNAN, andsqrt(-1) / sqrt(-1)getting substituted for1despitesqrt(-1) === NAN(NAN / NAN === NAN).As variable resolution occurs during evaluation,
x - xcannot be resolved during parsing although1 - 1andinf - infcan. One way to address this would be to resolve operations between numeric literal operands during parsing and implement a mechanism to toggle optimizations that disregardINFandNAN(like GCC's FloatingPointMath flags).Workarounds
ExpressionOptimizerRegistry$parser = Parser::createUnoptimized();