[poincare] InvNorm

This commit is contained in:
Léa Saviot
2019-08-23 15:08:33 +02:00
parent ec4e76defb
commit 04ccc285c8
10 changed files with 116 additions and 5 deletions

View File

@@ -82,6 +82,7 @@ poincare_src += $(addprefix poincare/src/,\
infinity.cpp \ infinity.cpp \
integer.cpp \ integer.cpp \
integral.cpp \ integral.cpp \
inv_norm.cpp \
layout_helper.cpp \ layout_helper.cpp \
least_common_multiple.cpp \ least_common_multiple.cpp \
logarithm.cpp \ logarithm.cpp \

View File

@@ -54,6 +54,7 @@ class Expression : public TreeHandle {
friend class HyperbolicTrigonometricFunction; friend class HyperbolicTrigonometricFunction;
friend class ImaginaryPart; friend class ImaginaryPart;
friend class Integral; friend class Integral;
friend class InvNorm;
friend class LeastCommonMultiple; friend class LeastCommonMultiple;
friend class Logarithm; friend class Logarithm;
friend class Matrix; friend class Matrix;

View File

@@ -68,6 +68,7 @@ public:
HyperbolicTangent, HyperbolicTangent,
ImaginaryPart, ImaginaryPart,
Integral, Integral,
InvNorm,
LeastCommonMultiple, LeastCommonMultiple,
Logarithm, Logarithm,
MatrixTrace, MatrixTrace,

View File

@@ -0,0 +1,50 @@
#ifndef POINCARE_INV_NORM_H
#define POINCARE_INV_NORM_H
#include <poincare/approximation_helper.h>
#include <poincare/expression.h>
namespace Poincare {
class InvNormNode final : public ExpressionNode {
public:
// TreeNode
size_t size() const override { return sizeof(InvNormNode); }
int numberOfChildren() const override;
#if POINCARE_TREE_LOG
virtual void logNodeName(std::ostream & stream) const override {
stream << "InvNorm";
}
#endif
// Properties
Type type() const override { return Type::InvNorm; }
private:
// Layout
Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
// Simplication
Expression shallowReduce(ReductionContext reductionContext) override;
LayoutShape leftLayoutShape() const override { return LayoutShape::MoreLetters; };
LayoutShape rightLayoutShape() const override { return LayoutShape::BoundaryPunctuation; }
// Evaluation
Evaluation<float> approximate(SinglePrecision p, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<float>(context, complexFormat, angleUnit); }
Evaluation<double> approximate(DoublePrecision p, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<double>(context, complexFormat, angleUnit); }
template<typename T> Evaluation<T> templatedApproximate(Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const;
};
class InvNorm final : public Expression {
public:
InvNorm(const InvNormNode * n) : Expression(n) {}
static InvNorm Builder(Expression child0, Expression child1, Expression child2) { return TreeHandle::FixedArityBuilder<InvNorm, InvNormNode>(ArrayBuilder<TreeHandle>(child0, child1, child2).array(), 3); }
static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("invnorm", 3, &UntypedBuilderThreeChildren<InvNorm>);
Expression shallowReduce(ExpressionNode::ReductionContext reductionContext);
};
}
#endif

View File

@@ -40,6 +40,7 @@
#include <poincare/infinity.h> #include <poincare/infinity.h>
#include <poincare/integer.h> #include <poincare/integer.h>
#include <poincare/integral.h> #include <poincare/integral.h>
#include <poincare/inv_norm.h>
#include <poincare/least_common_multiple.h> #include <poincare/least_common_multiple.h>
#include <poincare/logarithm.h> #include <poincare/logarithm.h>
#include <poincare/matrix.h> #include <poincare/matrix.h>

52
poincare/src/inv_norm.cpp Normal file
View File

@@ -0,0 +1,52 @@
#include <poincare/inv_norm.h>
#include <poincare/layout_helper.h>
#include <poincare/normal_distribution.h>
#include <poincare/serialization_helper.h>
#include <assert.h>
namespace Poincare {
constexpr Expression::FunctionHelper InvNorm::s_functionHelper;
int InvNormNode::numberOfChildren() const { return InvNorm::s_functionHelper.numberOfChildren(); }
Layout InvNormNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const {
return LayoutHelper::Prefix(InvNorm(this), floatDisplayMode, numberOfSignificantDigits, InvNorm::s_functionHelper.name());
}
int InvNormNode::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const {
return SerializationHelper::Prefix(this, buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, InvNorm::s_functionHelper.name());
}
Expression InvNormNode::shallowReduce(ReductionContext reductionContext) {
return InvNorm(this).shallowReduce(reductionContext);
}
template<typename T>
Evaluation<T> InvNormNode::templatedApproximate(Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const {
Evaluation<T> aEvaluation = childAtIndex(0)->approximate(T(), context, complexFormat, angleUnit);
Evaluation<T> muEvaluation = childAtIndex(1)->approximate(T(), context, complexFormat, angleUnit);
Evaluation<T> sigmaEvaluation = childAtIndex(2)->approximate(T(), context, complexFormat, angleUnit);
T a = aEvaluation.toScalar();
T mu = muEvaluation.toScalar();
T sigma = sigmaEvaluation.toScalar();
if (std::isnan(a) || std::isnan(mu) || std::isnan(sigma)) {
return Complex<T>::Undefined();
}
return Complex<T>::Builder(NormalDistribution::CumulativeDistributiveInverseForProbability<T>(a, mu, sigma));
}
Expression InvNorm::shallowReduce(ExpressionNode::ReductionContext reductionContext) {
{
Expression e = Expression::defaultShallowReduce();
if (e.isUndefined()) {
return e;
}
}
//TODO LEA
return *this;
}
}

View File

@@ -47,16 +47,16 @@ T NormalDistribution::StandardNormalCumulativeDistributiveFunctionAtAbscissa(T a
template<typename T> template<typename T>
T NormalDistribution::StandardNormalCumulativeDistributiveInverseForProbability(T probability) { T NormalDistribution::StandardNormalCumulativeDistributiveInverseForProbability(T probability) {
if (probability >= 1.0) { if (probability >= (T)1.0) {
return INFINITY; return INFINITY;
} }
if (probability <= 0.0) { if (probability <= (T)0.0) {
return -INFINITY; return -INFINITY;
} }
if (probability < 0.5) { if (probability < (T)0.5) {
return -StandardNormalCumulativeDistributiveInverseForProbability(1.0-probability); return -StandardNormalCumulativeDistributiveInverseForProbability(((T)1.0)-probability);
} }
return std::sqrt(2.0) * erfInv(2.0 * probability - 1.0); return std::sqrt((T)2.0) * erfInv(((T)2.0) * probability - (T)1.0);
} }
template float NormalDistribution::EvaluateAtAbscissa<float>(float, float, float); template float NormalDistribution::EvaluateAtAbscissa<float>(float, float, float);

View File

@@ -116,6 +116,7 @@ private:
&ImaginaryPart::s_functionHelper, &ImaginaryPart::s_functionHelper,
&Integral::s_functionHelper, &Integral::s_functionHelper,
&MatrixInverse::s_functionHelper, &MatrixInverse::s_functionHelper,
&InvNorm::s_functionHelper,
&LeastCommonMultiple::s_functionHelper, &LeastCommonMultiple::s_functionHelper,
&NaperianLogarithm::s_functionHelper, &NaperianLogarithm::s_functionHelper,
&CommonLogarithm::s_functionHelper, &CommonLogarithm::s_functionHelper,

View File

@@ -302,6 +302,7 @@ template HyperbolicTangent TreeHandle::FixedArityBuilder<HyperbolicTangent, Hype
template ImaginaryPart TreeHandle::FixedArityBuilder<ImaginaryPart, ImaginaryPartNode>(TreeHandle*, size_t); template ImaginaryPart TreeHandle::FixedArityBuilder<ImaginaryPart, ImaginaryPartNode>(TreeHandle*, size_t);
template Integral TreeHandle::FixedArityBuilder<Integral, IntegralNode>(TreeHandle*, size_t); template Integral TreeHandle::FixedArityBuilder<Integral, IntegralNode>(TreeHandle*, size_t);
template IntegralLayout TreeHandle::FixedArityBuilder<IntegralLayout, IntegralLayoutNode>(TreeHandle*, size_t); template IntegralLayout TreeHandle::FixedArityBuilder<IntegralLayout, IntegralLayoutNode>(TreeHandle*, size_t);
template InvNorm TreeHandle::FixedArityBuilder<InvNorm, InvNormNode>(TreeHandle*, size_t);
template LeastCommonMultiple TreeHandle::FixedArityBuilder<LeastCommonMultiple, LeastCommonMultipleNode>(TreeHandle*, size_t); template LeastCommonMultiple TreeHandle::FixedArityBuilder<LeastCommonMultiple, LeastCommonMultipleNode>(TreeHandle*, size_t);
template LeftParenthesisLayout TreeHandle::FixedArityBuilder<LeftParenthesisLayout, LeftParenthesisLayoutNode>(TreeHandle*, size_t); template LeftParenthesisLayout TreeHandle::FixedArityBuilder<LeftParenthesisLayout, LeftParenthesisLayoutNode>(TreeHandle*, size_t);
template LeftSquareBracketLayout TreeHandle::FixedArityBuilder<LeftSquareBracketLayout, LeftSquareBracketLayoutNode>(TreeHandle*, size_t); template LeftSquareBracketLayout TreeHandle::FixedArityBuilder<LeftSquareBracketLayout, LeftSquareBracketLayoutNode>(TreeHandle*, size_t);

View File

@@ -270,6 +270,9 @@ QUIZ_CASE(poincare_approximation_function) {
assert_expression_approximates_to<float>("int(x,x, 1, 2)", "1.5"); assert_expression_approximates_to<float>("int(x,x, 1, 2)", "1.5");
assert_expression_approximates_to<double>("int(x,x, 1, 2)", "1.5"); assert_expression_approximates_to<double>("int(x,x, 1, 2)", "1.5");
assert_expression_approximates_to<float>("invnorm(0.56, 1.3, 2.4)", "1.662326");
//assert_expression_approximates_to<double>("invnorm(0.56, 1.3, 2.4)", "1.6623258450088"); FIXME precision error
assert_expression_approximates_to<float>("ln(2)", "0.6931472"); assert_expression_approximates_to<float>("ln(2)", "0.6931472");
assert_expression_approximates_to<double>("ln(2)", "6.9314718055995ᴇ-1"); assert_expression_approximates_to<double>("ln(2)", "6.9314718055995ᴇ-1");