[poincare] InvNorm simplification + better approx

This commit is contained in:
Léa Saviot
2019-08-23 16:39:20 +02:00
parent 976c3ce245
commit cd227ef3bd
3 changed files with 56 additions and 3 deletions

View File

@@ -1,6 +1,9 @@
#include <poincare/inv_norm.h>
#include <poincare/infinity.h>
#include <poincare/integer.h>
#include <poincare/layout_helper.h>
#include <poincare/normal_distribution.h>
#include <poincare/rational.h>
#include <poincare/serialization_helper.h>
#include <assert.h>
@@ -45,7 +48,44 @@ Expression InvNorm::shallowReduce(ExpressionNode::ReductionContext reductionCont
return e;
}
}
//TODO LEA
Expression c0 = childAtIndex(0);
Expression c1 = childAtIndex(1);
{
Context * context = reductionContext.context();
Expression c2 = childAtIndex(2);
if (c0.deepIsMatrix(context) || c1.deepIsMatrix(context) || c2.deepIsMatrix(context)) {
return replaceWithUndefinedInPlace();
}
if (c0.type() != ExpressionNode::Type::Rational) {
return *this;
}
}
// Undef if x < 0 or x > 1
Rational r0 = static_cast<Rational &>(c0);
if (r0.isNegative()) {
return replaceWithUndefinedInPlace();
}
Integer a = r0.unsignedIntegerNumerator();
Integer b = r0.integerDenominator();
if (b.isLowerThan(a)) {
return replaceWithUndefinedInPlace();
}
// -INF if x == 0 and +INF if x == 1
bool is0 = r0.isZero();
bool is1 = !is0 && r0.isOne();
if (is0 || is1) {
Expression result = Infinity::Builder(is0);
replaceWithInPlace(result);
return result;
}
// mu if x == 0.5
if (r0.isHalf()) {
replaceWithInPlace(c1);
return c1;
}
return *this;
}

View File

@@ -1,6 +1,7 @@
#include <poincare/normal_distribution.h>
#include <poincare/erf_inv.h>
#include <cmath>
#include <float.h>
#include <assert.h>
namespace Poincare {
@@ -47,10 +48,14 @@ T NormalDistribution::StandardNormalCumulativeDistributiveFunctionAtAbscissa(T a
template<typename T>
T NormalDistribution::StandardNormalCumulativeDistributiveInverseForProbability(T probability) {
if (probability >= (T)1.0) {
if (probability > (T)1.0 || probability < (T)0.0) {
return NAN;
}
T precision = sizeof(T) == sizeof(double) ? DBL_EPSILON : FLT_EPSILON;
if (((T)1.0) - probability < precision) {
return INFINITY;
}
if (probability <= (T)0.0) {
if (probability < precision) {
return -INFINITY;
}
if (probability < (T)0.5) {

View File

@@ -1059,3 +1059,11 @@ QUIZ_CASE(poincare_hyperbolic_trigonometry) {
assert_parsed_expression_simplify_to("atanh(tanh(0.5))", "1/2", User, Radian, Real);
assert_parsed_expression_simplify_to("atanh(tanh(-3))", "-3", User, Radian, Real);
}
QUIZ_CASE(poincare_probabolity) {
assert_parsed_expression_simplify_to("invnorm(-1.3,2,3)", Undefined::Name());
assert_parsed_expression_simplify_to("invnorm(0,2,3)", "-inf");
assert_parsed_expression_simplify_to("invnorm(0.5,2,3)", "2");
assert_parsed_expression_simplify_to("invnorm(1,2,3)", "inf");
assert_parsed_expression_simplify_to("invnorm(1.3,2,3)", "undef");
}