Blame view

emulateur/epsilon-nofrendo/poincare/test/properties.cpp 6.36 KB
6663b6c9   adorian   projet complet av...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
  #include <quiz.h>
  #include <poincare.h>
  #include <ion.h>
  #include <assert.h>
  #include "helper.h"
  
  using namespace Poincare;
  
  constexpr Poincare::Expression::Sign Positive = Poincare::Expression::Sign::Positive;
  constexpr Poincare::Expression::Sign Negative = Poincare::Expression::Sign::Negative;
  constexpr Poincare::Expression::Sign Unknown = Poincare::Expression::Sign::Unknown;
  
  void assert_parsed_expression_sign(const char * expression, Poincare::Expression::Sign sign) {
    GlobalContext globalContext;
    Expression * e = parse_expression(expression);
    Expression::Simplify(&e, globalContext, Degree);
    assert(e->sign() == sign);
    delete e;
  }
  
  QUIZ_CASE(poincare_sign) {
    assert_parsed_expression_sign("abs(-cos(2))", Positive);
    assert_parsed_expression_sign("2.345E-23", Positive);
    assert_parsed_expression_sign("-2.345E-23", Negative);
    assert_parsed_expression_sign("2*(-3)*abs(-32)", Negative);
    assert_parsed_expression_sign("2*(-3)*abs(-32)*cos(3)", Unknown);
    assert_parsed_expression_sign("2^(-abs(3))", Positive);
    assert_parsed_expression_sign("(-2)^4", Positive);
    assert_parsed_expression_sign("(-2)^3", Negative);
    assert_parsed_expression_sign("random()", Positive);
    assert_parsed_expression_sign("42/3", Positive);
    assert_parsed_expression_sign("-23/32", Negative);
    assert_parsed_expression_sign("P", Positive);
    assert_parsed_expression_sign("X", Positive);
  }
  
  QUIZ_CASE(poincare_polynomial_degree) {
    assert_parsed_expression_polynomial_degree("x+1", 1);
    assert_parsed_expression_polynomial_degree("cos(2)+1", 0);
    assert_parsed_expression_polynomial_degree("confidence(0.2,10)+1", -1);
    assert_parsed_expression_polynomial_degree("diff(3*x+x,2)", 0);
    assert_parsed_expression_polynomial_degree("diff(3*x+x,x)", -1);
    assert_parsed_expression_polynomial_degree("(3*x+2)/3", 1);
    assert_parsed_expression_polynomial_degree("(3*x+2)/x", -1);
    assert_parsed_expression_polynomial_degree("int(2*x, 0, 1)", 0);
    assert_parsed_expression_polynomial_degree("[[1,2][3,4]]", -1);
    assert_parsed_expression_polynomial_degree("(x^2+2)*(x+1)", 3);
    assert_parsed_expression_polynomial_degree("-(x+1)", 1);
    assert_parsed_expression_polynomial_degree("(x^2+2)^(3)", 6);
    assert_parsed_expression_polynomial_degree("prediction(0.2,10)+1", -1);
    assert_parsed_expression_polynomial_degree("2-x-x^3", 3);
    assert_parsed_expression_polynomial_degree("P*x", 1);
  }
  
  void assert_parsed_expression_has_characteristic_range(const char * expression, float range, Expression::AngleUnit angleUnit = Expression::AngleUnit::Degree) {
    GlobalContext globalContext;
    Expression * e = parse_expression(expression);
    Expression::Simplify(&e, globalContext, angleUnit);
    if (std::isnan(range)) {
      assert(std::isnan(e->characteristicXRange(globalContext, angleUnit)));
    } else {
      assert(std::fabs(e->characteristicXRange(globalContext, angleUnit) - range) < 0.0000001f);
    }
    delete e;
  }
  
  QUIZ_CASE(poincare_characteristic_range) {
    assert_parsed_expression_has_characteristic_range("cos(x)", 360.0f);
    assert_parsed_expression_has_characteristic_range("cos(-x)", 360.0f);
    assert_parsed_expression_has_characteristic_range("cos(x)", 2.0f*M_PI, Expression::AngleUnit::Radian);
    assert_parsed_expression_has_characteristic_range("cos(-x)", 2.0f*M_PI, Expression::AngleUnit::Radian);
    assert_parsed_expression_has_characteristic_range("sin(9*x+10)", 40.0f);
    assert_parsed_expression_has_characteristic_range("sin(9*x+10)+cos(x/2)", 720.0f);
    assert_parsed_expression_has_characteristic_range("sin(9*x+10)+cos(x/2)", 4.0f*M_PI, Expression::AngleUnit::Radian);
    assert_parsed_expression_has_characteristic_range("x", NAN);
    assert_parsed_expression_has_characteristic_range("cos(3)+2", 0.0f);
    assert_parsed_expression_has_characteristic_range("log(cos(40*x))", 9.0f);
    assert_parsed_expression_has_characteristic_range("cos(cos(x))", 360.0f);
  }
  
  void assert_parsed_expression_has_variables(const char * expression, const char * variables) {
    Expression * e = parse_expression(expression);
    char variableBuffer[Expression::k_maxNumberOfVariables+1] = {0};
    int numberOfVariables = e->getVariables(Poincare::Symbol::isVariableSymbol, variableBuffer);
    if (variables == nullptr) {
      assert(numberOfVariables == -1);
    } else {
      assert(numberOfVariables == strlen(variables));
      char * currentChar = variableBuffer;
      while (*variables != 0) {
        assert(*currentChar++ == *variables++);
      }
    }
    delete e;
  }
  
  QUIZ_CASE(poincare_get_variables) {
    assert_parsed_expression_has_variables("x+y", "xy");
    assert_parsed_expression_has_variables("x+y+z+2*t", "xyzt");
    assert_parsed_expression_has_variables("abcdef", "abcdef");
    assert_parsed_expression_has_variables("abcdefg", nullptr);
    assert_parsed_expression_has_variables("abcde", "abcde");
    assert_parsed_expression_has_variables("x^2+2*y+k!*A+w", "xykw");
  }
  
  void assert_parsed_expression_has_polynomial_coefficient(const char * expression, char symbolName, const char ** coefficients, Expression::AngleUnit angleUnit = Expression::AngleUnit::Degree) {
    GlobalContext globalContext;
    Expression * e = parse_expression(expression);
    Expression::Reduce(&e, globalContext, angleUnit);
    Expression * coefficientBuffer[Poincare::Expression::k_maxNumberOfPolynomialCoefficients];
    int d = e->getPolynomialCoefficients(symbolName, coefficientBuffer, globalContext, Radian);
    for (int i = 0; i <= d; i++) {
      Expression * f = parse_expression(coefficients[i]);
      Expression::Reduce(&coefficientBuffer[i], globalContext, angleUnit);
      Expression::Reduce(&f, globalContext, angleUnit);
      assert(coefficientBuffer[i]->isIdenticalTo(f));
      delete f;
      delete coefficientBuffer[i];
    }
    assert(coefficients[d+1] == 0);
    delete e;
  }
  
  QUIZ_CASE(poincare_get_polynomial_coefficients) {
    const char * coefficient0[] = {"2", "1", "1", 0};
    assert_parsed_expression_has_polynomial_coefficient("x^2+x+2", 'x', coefficient0);
    const char * coefficient1[] = {"12+(-6)*P", "12", "3", 0}; //3*x^2+12*x-6*π+12
    assert_parsed_expression_has_polynomial_coefficient("3*(x+2)^2-6*P", 'x', coefficient1);
    // TODO: decomment when enable 3-degree polynomes
    //const char * coefficient2[] = {"2+32*x", "2", "6", "2", 0}; //2*n^3+6*n^2+2*n+2+32*x
    //assert_parsed_expression_has_polynomial_coefficient("2*(n+1)^3-4n+32*x", 'n', coefficient2);
    const char * coefficient3[] = {"1", "-P", "1", 0}; //x^2-Pi*x+1
    assert_parsed_expression_has_polynomial_coefficient("x^2-P*x+1", 'x', coefficient3);
  }