/** * Process the EqualRounded operator. * * @return boolean|null A boolean with a value of true if the two expressions are numerically equal after rounding and false if they are not. If either sub-expression is NULL, the operator results in NULL. * @throws \qtism\runtime\expressions\operators\OperatorProcessingException */ public function process() { $operands = $this->getOperands(); if ($operands->containsNull()) { return null; } if ($operands->exclusivelySingle() === false) { $msg = "The EqualRounded operator only accepts operands with a single cardinality."; throw new OperatorProcessingException($msg, $this, OperatorProcessingException::WRONG_CARDINALITY); } if ($operands->exclusivelyNumeric() === false) { $msg = "The EqualRounded operator only accepts operands with an integer or float baseType."; throw new OperatorProcessingException($msg, $this, OperatorProcessingException::WRONG_BASETYPE); } // delegate the rounding to the RoundTo operator. $expression = $this->getExpression(); $roundingMode = $expression->getRoundingMode(); $figures = $expression->getFigures(); if (gettype($figures) === 'string') { // Variable reference to deal with. $state = $this->getState(); $varName = Utils::sanitizeVariableRef($figures); $varValue = $state[$varName]; if (is_null($varValue) === true) { $msg = "The variable with name '{$varName}' could not be resolved."; throw new OperatorProcessingException($msg, $this, OperatorProcessingException::NONEXISTENT_VARIABLE); } elseif (!$varValue instanceof Integer) { $msg = "The variable with name '{$varName}' is not an integer."; throw new OperatorProcessingException($msg, $this, OperatorProcessingException::WRONG_VARIABLE_BASETYPE); } $figures = $varValue->getValue(); } $rounded = new OperandsCollection(); // will contain the rounded operands. foreach ($operands as $operand) { $baseType = RuntimeUtils::inferBaseType($operand); $subExpression = new BaseValue($baseType, $operand); $roundToExpression = new RoundTo(new ExpressionCollection(array($subExpression)), $figures, $roundingMode); $roundToProcessor = new RoundToProcessor($roundToExpression, new OperandsCollection(array($operand))); try { $rounded[] = $roundToProcessor->process(); } catch (OperatorProcessingException $e) { $msg = "An error occured while rounding '{$operand}'."; throw new OperatorProcessingException($msg, $this, OperatorProcessingException::LOGIC_ERROR, $e); } } return new Boolean($rounded[0]->getValue() == $rounded[1]->getValue()); }
public function testInfinity() { $expr = $this->createComponentFromXml(' <roundTo figures="0" roundingMode="decimalPlaces"> <baseValue baseType="float">3.4</baseValue> </roundTo> '); $operands = new OperandsCollection(array(new Float(INF))); $processor = new RoundToProcessor($expr, $operands); $result = $processor->process(); $this->assertTrue(is_infinite($result->getValue())); $this->assertTrue(INF === $result->getValue()); $processor->setOperands(new OperandsCollection(array(new Float(-INF)))); $result = $processor->process(); $this->assertTrue(is_infinite($result->getValue())); $this->assertTrue(-INF === $result->getValue()); }