diff --git a/poincare/Makefile b/poincare/Makefile index 60b627637..049e6db31 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -98,6 +98,7 @@ poincare_src += $(addprefix poincare/src/,\ naperian_logarithm.cpp \ norm_cdf.cpp \ norm_cdf2.cpp \ + norm_pdf.cpp \ nth_root.cpp \ number.cpp \ opposite.cpp \ diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 96bb84efe..b5c033ad2 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -66,6 +66,7 @@ class Expression : public TreeHandle { friend class Multiplication; friend class MultiplicationNode; friend class NaperianLogarithm; + friend class NormPDF; friend class NormCDF; friend class NormCDF2; friend class NthRoot; diff --git a/poincare/include/poincare/expression_node.h b/poincare/include/poincare/expression_node.h index 79fc3226e..75355f414 100644 --- a/poincare/include/poincare/expression_node.h +++ b/poincare/include/poincare/expression_node.h @@ -75,6 +75,7 @@ public: NaperianLogarithm, NormCDF, NormCDF2, + NormPDF, NthRoot, Opposite, Parenthesis, diff --git a/poincare/include/poincare/norm_pdf.h b/poincare/include/poincare/norm_pdf.h new file mode 100644 index 000000000..b5b375819 --- /dev/null +++ b/poincare/include/poincare/norm_pdf.h @@ -0,0 +1,52 @@ +#ifndef POINCARE_NORM_PDF_H +#define POINCARE_NORM_PDF_H + +#include +#include + +namespace Poincare { + +class NormPDFNode final : public ExpressionNode { +public: + + // TreeNode + size_t size() const override { return sizeof(NormPDFNode); } + int numberOfChildren() const override; +#if POINCARE_TREE_LOG + virtual void logNodeName(std::ostream & stream) const override { + stream << "NormPDF"; + } +#endif + + // Properties + Type type() const override { return Type::NormPDF; } + Sign sign(Context * context) const override { return Sign::Positive; } + Expression setSign(Sign s, ReductionContext reductionContext) override; + +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 approximate(SinglePrecision p, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } + Evaluation approximate(DoublePrecision p, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } + template Evaluation templatedApproximate(Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; +}; + +class NormPDF final : public Expression { +public: + NormPDF(const NormPDFNode * n) : Expression(n) {} + static NormPDF Builder(Expression child0, Expression child1, Expression child2) { return TreeHandle::FixedArityBuilder(ArrayBuilder(child0, child1, child2).array(), 3); } + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("normpdf", 3, &UntypedBuilderThreeChildren); + Expression shallowReduce(ExpressionNode::ReductionContext reductionContext); +}; + +} + +#endif diff --git a/poincare/include/poincare_nodes.h b/poincare/include/poincare_nodes.h index 6709e2028..308baf921 100644 --- a/poincare/include/poincare_nodes.h +++ b/poincare/include/poincare_nodes.h @@ -54,6 +54,7 @@ #include #include #include +#include #include #include #include diff --git a/poincare/src/norm_pdf.cpp b/poincare/src/norm_pdf.cpp new file mode 100644 index 000000000..1fb454701 --- /dev/null +++ b/poincare/src/norm_pdf.cpp @@ -0,0 +1,57 @@ +#include +#include +#include +#include +#include + +namespace Poincare { + +constexpr Expression::FunctionHelper NormPDF::s_functionHelper; + +int NormPDFNode::numberOfChildren() const { return NormPDF::s_functionHelper.numberOfChildren(); } + +Expression NormPDFNode::setSign(Sign s, ReductionContext reductionContext) { + assert(s == Sign::Positive); + return NormPDF(this); +} + +Layout NormPDFNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { + return LayoutHelper::Prefix(NormPDF(this), floatDisplayMode, numberOfSignificantDigits, NormPDF::s_functionHelper.name()); +} + +int NormPDFNode::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { + return SerializationHelper::Prefix(this, buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, NormPDF::s_functionHelper.name()); +} + +Expression NormPDFNode::shallowReduce(ReductionContext reductionContext) { + return NormPDF(this).shallowReduce(reductionContext); +} + +template +Evaluation NormPDFNode::templatedApproximate(Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { + Evaluation xEvaluation = childAtIndex(0)->approximate(T(), context, complexFormat, angleUnit); + Evaluation muEvaluation = childAtIndex(1)->approximate(T(), context, complexFormat, angleUnit); + Evaluation sigmaEvaluation = childAtIndex(2)->approximate(T(), context, complexFormat, angleUnit); + + T x = xEvaluation.toScalar(); + T mu = muEvaluation.toScalar(); + T sigma = sigmaEvaluation.toScalar(); + + if (std::isnan(x) || std::isnan(mu) || std::isnan(sigma)) { + return Complex::Undefined(); + } + return Complex::Builder(NormalDistribution::EvaluateAtAbscissa(x, mu, sigma)); +} + +Expression NormPDF::shallowReduce(ExpressionNode::ReductionContext reductionContext) { + { + Expression e = Expression::defaultShallowReduce(); + if (e.isUndefined()) { + return e; + } + } + //TODO LEA + return *this; +} + +} diff --git a/poincare/src/normal_distribution.cpp b/poincare/src/normal_distribution.cpp index 5b6d0c35e..c5005b622 100644 --- a/poincare/src/normal_distribution.cpp +++ b/poincare/src/normal_distribution.cpp @@ -60,6 +60,7 @@ T NormalDistribution::StandardNormalCumulativeDistributiveInverseForProbability( } template float NormalDistribution::EvaluateAtAbscissa(float, float, float); +template double NormalDistribution::EvaluateAtAbscissa(double, double, double); template float NormalDistribution::CumulativeDistributiveFunctionAtAbscissa(float, float, float); template double NormalDistribution::CumulativeDistributiveFunctionAtAbscissa(double, double, double); template float NormalDistribution::CumulativeDistributiveInverseForProbability(float, float, float); diff --git a/poincare/src/parsing/parser.h b/poincare/src/parsing/parser.h index 75be59de0..3a3cdba30 100644 --- a/poincare/src/parsing/parser.h +++ b/poincare/src/parsing/parser.h @@ -123,6 +123,7 @@ private: &Logarithm::s_functionHelper, &NormCDF::s_functionHelper, &NormCDF2::s_functionHelper, + &NormPDF::s_functionHelper, &PermuteCoefficient::s_functionHelper, &SimplePredictionInterval::s_functionHelper, &PredictionInterval::s_functionHelper, diff --git a/poincare/src/tree_handle.cpp b/poincare/src/tree_handle.cpp index a0fe8d645..185ddd231 100644 --- a/poincare/src/tree_handle.cpp +++ b/poincare/src/tree_handle.cpp @@ -319,6 +319,7 @@ template Multiplication TreeHandle::NAryBuilder(TreeHandle*, size_t); template NormCDF TreeHandle::FixedArityBuilder(TreeHandle*, size_t); template NormCDF2 TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template NormPDF TreeHandle::FixedArityBuilder(TreeHandle*, size_t); template NthRoot TreeHandle::FixedArityBuilder(TreeHandle*, size_t); template Opposite TreeHandle::FixedArityBuilder(TreeHandle*, size_t); template Parenthesis TreeHandle::FixedArityBuilder(TreeHandle*, size_t); diff --git a/poincare/test/approximation.cpp b/poincare/test/approximation.cpp index dae16a713..66d56da94 100644 --- a/poincare/test/approximation.cpp +++ b/poincare/test/approximation.cpp @@ -285,6 +285,8 @@ QUIZ_CASE(poincare_approximation_function) { assert_expression_approximates_to("normcdf2(0.5, 3.6, 1.3, 3.4)", "0.3436388"); assert_expression_approximates_to("normcdf2(0.5, 3.6, 1.3, 3.4)", "3.4363881299147ᴇ-1"); + assert_expression_approximates_to("normpdf(1.2, 3.4, 5.6)", "0.06594901"); + assert_expression_approximates_to("permute(10, 4)", "5040"); assert_expression_approximates_to("permute(10, 4)", "5040");