[poincare] Randint::shallowReduce: replace by undef if the argument was

defined but not the randint approximation.

This fixes tests: randint(1,inf) --> NAN, randint([[1,2]],2) --> NAN
This commit is contained in:
Émilie Feral
2019-09-20 15:13:22 +02:00
committed by LeaNumworks
parent 6916b6e06f
commit ab420b871c
2 changed files with 10 additions and 5 deletions

View File

@@ -6,6 +6,7 @@
namespace Poincare {
class RandintNode /*final*/ : public ExpressionNode {
friend class Randint;
public:
// TreeNode
@@ -33,7 +34,7 @@ private:
Evaluation<double> approximate(DoublePrecision p, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override {
return templateApproximate<double>(context, complexFormat, angleUnit);
}
template <typename T> Evaluation<T> templateApproximate(Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const;
template <typename T> Evaluation<T> templateApproximate(Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, bool * inputIsUndefined = nullptr) const;
// Simplification
Expression shallowReduce(ReductionContext reductionContext) override;
LayoutShape leftLayoutShape() const override { return LayoutShape::MoreLetters; };

View File

@@ -28,9 +28,12 @@ int RandintNode::serialize(char * buffer, int bufferSize, Preferences::PrintFloa
return SerializationHelper::Prefix(this, buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, Randint::s_functionHelper.name());
}
template <typename T> Evaluation<T> RandintNode::templateApproximate(Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const {
template <typename T> Evaluation<T> RandintNode::templateApproximate(Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, bool * inputIsUndefined) const {
Evaluation<T> aInput = childAtIndex(0)->approximate(T(), context, complexFormat, angleUnit);
Evaluation<T> bInput = childAtIndex(1)->approximate(T(), context, complexFormat, angleUnit);
if (inputIsUndefined) {
*inputIsUndefined = aInput.isUndefined() || bInput.isUndefined();
}
T a = aInput.toScalar();
T b = bInput.toScalar();
if (std::isnan(a) || std::isnan(b) || a != std::round(a) || b != std::round(b) || a > b || std::isinf(a) || std::isinf(b)) {
@@ -49,9 +52,10 @@ Expression Randint::shallowReduce(ExpressionNode::ReductionContext reductionCont
if (e.isUndefined()) {
return e;
}
double eval = approximateToScalar<double>(reductionContext.context() , reductionContext.complexFormat() , reductionContext.angleUnit() );
if (std::isnan(eval)) {
/* The result might be NAN because we are reducing a function's expression
bool inputIsUndefined = false;
double eval = static_cast<RandintNode *>(node())->templateApproximate<double>(reductionContext.context(), reductionContext.complexFormat(), reductionContext.angleUnit(), &inputIsUndefined).toScalar();
if (inputIsUndefined) {
/* The input might be NAN because we are reducing a function's expression
* which depends on x. We thus do not want to replace too early with
* undefined. */
return *this;