From ddba1f6050b7e9e88a785b35f8d830fbe3e50f99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 26 Aug 2019 15:53:18 +0200 Subject: [PATCH] [poincare/InvBinom] --- poincare/Makefile | 1 + poincare/include/poincare/expression_node.h | 1 + poincare/include/poincare/inv_binom.h | 48 ++++++++++++ poincare/include/poincare_nodes.h | 1 + poincare/src/inv_binom.cpp | 85 +++++++++++++++++++++ poincare/src/parsing/parser.h | 1 + poincare/src/tree_handle.cpp | 1 + 7 files changed, 138 insertions(+) create mode 100644 poincare/include/poincare/inv_binom.h create mode 100644 poincare/src/inv_binom.cpp diff --git a/poincare/Makefile b/poincare/Makefile index 4e66fcbfe..b71437ebe 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -86,6 +86,7 @@ poincare_src += $(addprefix poincare/src/,\ infinity.cpp \ integer.cpp \ integral.cpp \ + inv_binom.cpp \ inv_norm.cpp \ layout_helper.cpp \ least_common_multiple.cpp \ diff --git a/poincare/include/poincare/expression_node.h b/poincare/include/poincare/expression_node.h index fc6d4f2f6..d52370d1f 100644 --- a/poincare/include/poincare/expression_node.h +++ b/poincare/include/poincare/expression_node.h @@ -70,6 +70,7 @@ public: HyperbolicTangent, ImaginaryPart, Integral, + InvBinom, InvNorm, LeastCommonMultiple, Logarithm, diff --git a/poincare/include/poincare/inv_binom.h b/poincare/include/poincare/inv_binom.h new file mode 100644 index 000000000..db0767503 --- /dev/null +++ b/poincare/include/poincare/inv_binom.h @@ -0,0 +1,48 @@ +#ifndef POINCARE_INV_BINOM_H +#define POINCARE_INV_BINOM_H + +#include +#include + +namespace Poincare { + +class InvBinomNode final : public BinomialDistributionFunctionNode { +public: + + // TreeNode + size_t size() const override { return sizeof(InvBinomNode); } + int numberOfChildren() const override; +#if POINCARE_TREE_LOG + virtual void logNodeName(std::ostream & stream) const override { + stream << "InvBinom"; + } +#endif + + // Properties + Type type() const override { return Type::InvBinom; } + +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; + + // 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 InvBinom final : public BinomialDistributionFunction { +public: + InvBinom(const InvBinomNode * n) : BinomialDistributionFunction(n) {} + static InvBinom Builder(Expression child0, Expression child1, Expression child2) { return TreeHandle::FixedArityBuilder(ArrayBuilder(child0, child1, child2).array(), 3); } + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("invbinom", 3, &UntypedBuilderThreeChildren); + Expression shallowReduce(ExpressionNode::ReductionContext reductionContext); +}; + +} + +#endif diff --git a/poincare/include/poincare_nodes.h b/poincare/include/poincare_nodes.h index c348100a1..7bf331df5 100644 --- a/poincare/include/poincare_nodes.h +++ b/poincare/include/poincare_nodes.h @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include diff --git a/poincare/src/inv_binom.cpp b/poincare/src/inv_binom.cpp new file mode 100644 index 000000000..e0237a5b2 --- /dev/null +++ b/poincare/src/inv_binom.cpp @@ -0,0 +1,85 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Poincare { + +constexpr Expression::FunctionHelper InvBinom::s_functionHelper; + +int InvBinomNode::numberOfChildren() const { return InvBinom::s_functionHelper.numberOfChildren(); } + +Layout InvBinomNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { + return LayoutHelper::Prefix(InvBinom(this), floatDisplayMode, numberOfSignificantDigits, InvBinom::s_functionHelper.name()); +} + +int InvBinomNode::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { + return SerializationHelper::Prefix(this, buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, InvBinom::s_functionHelper.name()); +} + +Expression InvBinomNode::shallowReduce(ReductionContext reductionContext) { + return InvBinom(this).shallowReduce(reductionContext); +} + +template +Evaluation InvBinomNode::templatedApproximate(Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { + Evaluation aEvaluation = childAtIndex(0)->approximate(T(), context, complexFormat, angleUnit); + Evaluation nEvaluation = childAtIndex(1)->approximate(T(), context, complexFormat, angleUnit); + Evaluation pEvaluation = childAtIndex(2)->approximate(T(), context, complexFormat, angleUnit); + + T a = aEvaluation.toScalar(); + T n = nEvaluation.toScalar(); + T p = pEvaluation.toScalar(); + + // CumulativeDistributiveInverseForProbability handles bad n and p values + return Complex::Builder(BinomialDistribution::CumulativeDistributiveInverseForProbability(a, n, p)); +} + +Expression InvBinom::shallowReduce(ExpressionNode::ReductionContext reductionContext) { + { + bool stopReduction = false; + Expression e = BinomialDistributionFunction::shallowReduce(reductionContext.context(), &stopReduction); + if (stopReduction) { + return e; + } + } + Expression a = childAtIndex(0); + Expression n = childAtIndex(1); + Context * context = reductionContext.context(); + + // Check a + if (a.deepIsMatrix(context)) { + return replaceWithUndefinedInPlace(); + } + if (a.type() != ExpressionNode::Type::Rational) { + return *this; + } + + // Special values + + // Undef if a < 0 or a > 1 + Rational rationalA = static_cast(a); + if (rationalA.isNegative()) { + return replaceWithUndefinedInPlace(); + } + Integer num = rationalA.unsignedIntegerNumerator(); + Integer den = rationalA.integerDenominator(); + if (den.isLowerThan(num)) { + return replaceWithUndefinedInPlace(); + } + + // TODO LEA if a == 0, check p ? + // n if a == 1 + if (rationalA.isOne()) { + replaceWithInPlace(n); + return n; + } + + return *this; +} + +} diff --git a/poincare/src/parsing/parser.h b/poincare/src/parsing/parser.h index ad3aaed84..25fedf107 100644 --- a/poincare/src/parsing/parser.h +++ b/poincare/src/parsing/parser.h @@ -117,6 +117,7 @@ private: &MatrixIdentity::s_functionHelper, &ImaginaryPart::s_functionHelper, &Integral::s_functionHelper, + &InvBinom::s_functionHelper, &MatrixInverse::s_functionHelper, &InvNorm::s_functionHelper, &LeastCommonMultiple::s_functionHelper, diff --git a/poincare/src/tree_handle.cpp b/poincare/src/tree_handle.cpp index b820893c0..9cab1ef6a 100644 --- a/poincare/src/tree_handle.cpp +++ b/poincare/src/tree_handle.cpp @@ -304,6 +304,7 @@ template HyperbolicTangent TreeHandle::FixedArityBuilder(TreeHandle*, size_t); template Integral TreeHandle::FixedArityBuilder(TreeHandle*, size_t); template IntegralLayout TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template InvBinom TreeHandle::FixedArityBuilder(TreeHandle*, size_t); template InvNorm TreeHandle::FixedArityBuilder(TreeHandle*, size_t); template LeastCommonMultiple TreeHandle::FixedArityBuilder(TreeHandle*, size_t); template LeftParenthesisLayout TreeHandle::FixedArityBuilder(TreeHandle*, size_t);