[poincare] Fix Randint

This commit is contained in:
Émilie Feral
2018-08-28 16:14:21 +02:00
parent 340ee6695c
commit 2273951fcc
6 changed files with 49 additions and 31 deletions

View File

@@ -100,6 +100,7 @@ objs += $(addprefix poincare/src/,\
print_float.o\
preferences.o\
product.o\
randint.o\
random.o\
rational.o\
real_part.o\

View File

@@ -145,6 +145,7 @@
#include <poincare/matrix_complex.h>
#include <poincare/multiplication.h>
#include <poincare/power.h>
#include <poincare/randint.h>
#include <poincare/random.h>
#include <poincare/subtraction.h>
#include <poincare/undefined.h>

View File

@@ -1,32 +1,54 @@
#ifndef POINCARE_RANDINT_H
#define POINCARE_RANDINT_H
#include <poincare/static_hierarchy.h>
#include <poincare/layout_helper.h>
#include <poincare/expression.h>
#include <poincare/serialization_helper.h>
namespace Poincare {
class Randint : public StaticHierarchy<2> {
using StaticHierarchy<2>::StaticHierarchy;
class RandintNode : public ExpressionNode {
public:
Type type() const override;
private:
/* Layout */
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override {
return LayoutHelper::Prefix(this, floatDisplayMode, numberOfSignificantDigits, name());
// Allocation Failure
static RandintNode * FailedAllocationStaticNode();
RandintNode * failedAllocationStaticNode() override { return FailedAllocationStaticNode(); }
// TreeNode
size_t size() const override { return sizeof(RandintNode); }
int numberOfChildren() const override { return 2; }
#if POINCARE_TREE_LOG
virtual void logNodeName(std::ostream & stream) const override {
stream << "Randint";
}
#endif
// Properties
Type type() const override { return Type::Randint; }
private:
// Layout
LayoutReference createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override {
return SerializationHelper::Prefix(this, buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, name());
}
const char * name() const { return "randint"; }
/* Evaluation */
// Evaluation
Evaluation<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return templateApproximate<float>(context, angleUnit);
}
Evaluation<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return templateApproximate<double>(context, angleUnit);
}
template <typename T> Evaluation<T> templateApproximate()Context& context, Preferences::AngleUnit angleUnit) const;
template <typename T> Evaluation<T> templateApproximate(Context& context, Preferences::AngleUnit angleUnit) const;
};
class Randint : public Expression {
friend class RandintNode;
public:
Randint() : Expression(TreePool::sharedPool()->createTreeNode<RandintNode>()) {}
Randint(const RandintNode * n) : Expression(n) {}
template<typename T> static T random();
private:
};
}

View File

@@ -146,8 +146,7 @@ prediction { poincare_expression_yylval.expression = SimplePredictionInterval();
product { poincare_expression_yylval.expression = Product(); return FUNCTION; }
quo { poincare_expression_yylval.expression = DivisionQuotient(); return FUNCTION; }
random { poincare_expression_yylval.expression = Random(); return FUNCTION; }
/*randint { poincare_expression_yylval.expression = new Randint(); return FUNCTION; }
*/
randint { poincare_expression_yylval.expression = Randint(); return FUNCTION; }
re { poincare_expression_yylval.expression = RealPart(); return FUNCTION; }
rem { poincare_expression_yylval.expression = DivisionRemainder(); return FUNCTION; }
root { poincare_expression_yylval.expression = NthRoot(); return FUNCTION; }

View File

@@ -1,5 +1,6 @@
#include <poincare/randint.h>
#include <poincare/random.h>
#include <poincare/allocation_failure_expression_node.h>
#include <ion.h>
extern "C" {
@@ -9,28 +10,27 @@ extern "C" {
namespace Poincare {
ExpressionNode::Type Randint::type() const {
return Type::Randint;
RandintNode * RandintNode::FailedAllocationStaticNode() {
static AllocationFailureExpressionNode<RandintNode> failure;
TreePool::sharedPool()->registerStaticNodeIfRequired(&failure);
return &failure;
}
Expression * Randint::clone() const {
Randint * a = new Randint(m_operands, true);
return a;
LayoutReference RandintNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const {
return LayoutHelper::Prefix(Randint(this), floatDisplayMode, numberOfSignificantDigits, name());
}
template <typename T> Evaluation<T> * Randint::templateApproximate(Context & context, Preferences::AngleUnit angleUnit) const {
Evaluation<T> * aInput = childAtIndex(0)->approximate(T(), context, angleUnit);
Evaluation<T> * bInput = childAtIndex(1)->approximate(T(), context, angleUnit);
T a = aInput->toScalar();
T b = bInput->toScalar();
delete aInput;
delete bInput;
template <typename T> Evaluation<T> RandintNode::templateApproximate(Context & context, Preferences::AngleUnit angleUnit) const {
Evaluation<T> aInput = childAtIndex(0)->approximate(T(), context, angleUnit);
Evaluation<T> bInput = childAtIndex(1)->approximate(T(), context, angleUnit);
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) {
return new Complex<T>(Complex<T>::Undefined());
return Complex<T>::Undefined();
}
T result = std::floor(Random::random<T>()*(b+1.0-a)+a);
return new Complex<T>(result);
return Complex<T>(result);
}
}

View File

@@ -50,9 +50,7 @@ QUIZ_CASE(poincare_parse_function) {
assert_parsed_expression_type("quo(29, 10)", ExpressionNode::Type::DivisionQuotient);
assert_parsed_expression_type("random()", ExpressionNode::Type::Random);
#if 0
assert_parsed_expression_type("randint(1, 2)", ExpressionNode::Type::Randint);
#endif
assert_parsed_expression_type("re(2+I)", ExpressionNode::Type::RealPart);
assert_parsed_expression_type("rem(29, 10)", ExpressionNode::Type::DivisionRemainder);
@@ -230,12 +228,9 @@ QUIZ_CASE(poincare_function_evaluate) {
assert_exp_is_bounded(exp, 0.0f, 1.0f);
assert_exp_is_bounded(exp, 0.0, 1.0);
#if 0
exp = parse_expression("randint(4,45)");
assert_exp_is_bounded(exp, 4.0f, 45.0f, true);
assert_exp_is_bounded(exp, 4.0, 45.0, true);
delete exp;
#endif
}
QUIZ_CASE(poincare_function_simplify) {