mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-24 08:10:50 +01:00
[poincare] NaperianLogarithm
This commit is contained in:
@@ -57,6 +57,7 @@ objs += $(addprefix poincare/src/,\
|
||||
matrix_complex.o\
|
||||
multiplication.o\
|
||||
n_ary_expression_node.o\
|
||||
naperian_logarithm.o\
|
||||
nth_root.o\
|
||||
number.o\
|
||||
parenthesis.o\
|
||||
|
||||
@@ -115,6 +115,7 @@
|
||||
#include <poincare/infinity.h>
|
||||
#include <poincare/integer.h>
|
||||
#include <poincare/logarithm.h>
|
||||
#include <poincare/naperian_logarithm.h>
|
||||
#include <poincare/number.h>
|
||||
#include <poincare/opposite.h>
|
||||
#include <poincare/decimal.h>
|
||||
|
||||
@@ -28,6 +28,7 @@ class Expression : public TreeByValue {
|
||||
friend class Matrix;
|
||||
template<int T>
|
||||
friend class LogarithmNode;
|
||||
friend class NaperianLogarithmNode;
|
||||
template<typename T>
|
||||
friend class ExceptionExpressionNode;
|
||||
public:
|
||||
|
||||
@@ -1,29 +1,49 @@
|
||||
#ifndef POINCARE_NAPERIAN_LOGARITHM_H
|
||||
#define POINCARE_NAPERIAN_LOGARITHM_H
|
||||
|
||||
#include <poincare/layout_helper.h>
|
||||
#include <poincare/static_hierarchy.h>
|
||||
#include <poincare/approximation_helper.h>
|
||||
#include <poincare/expression.h>
|
||||
#include <poincare/layout_helper.h>
|
||||
#include <poincare/serialization_helper.h>
|
||||
|
||||
namespace Poincare {
|
||||
|
||||
class NaperianLogarithm : public StaticHierarchy<1> {
|
||||
using StaticHierarchy<1>::StaticHierarchy;
|
||||
class NaperianLogarithmNode : public ExpressionNode {
|
||||
public:
|
||||
Type type() const override;
|
||||
// Allocation Failure
|
||||
static NaperianLogarithmNode * FailedAllocationStaticNode();
|
||||
NaperianLogarithmNode * failedAllocationStaticNode() override { return FailedAllocationStaticNode(); }
|
||||
|
||||
// TreeNode
|
||||
size_t size() const override { return sizeof(NaperianLogarithmNode); }
|
||||
int numberOfChildren() const override { return 1; }
|
||||
#if POINCARE_TREE_LOG
|
||||
virtual void logNodeName(std::ostream & stream) const override {
|
||||
stream << "NaperianLogarithm";
|
||||
}
|
||||
#endif
|
||||
|
||||
// Properties
|
||||
Type type() const override { return Type::NaperianLogarithm; }
|
||||
|
||||
private:
|
||||
/* Layout */
|
||||
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override {
|
||||
// Layout
|
||||
LayoutReference createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override {
|
||||
return LayoutHelper::Prefix(this, floatDisplayMode, numberOfSignificantDigits, name());
|
||||
}
|
||||
int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override {
|
||||
return SerializationHelper::Prefix(this, buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, name());
|
||||
}
|
||||
const char * name() const { return "ln"; }
|
||||
/* Simplification */
|
||||
Expression shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
|
||||
static const char * name() { return "ln"; }
|
||||
// Simplification
|
||||
Expression shallowReduce(Context& context, Preferences::AngleUnit angleUnit) const override;
|
||||
/* Evaluation */
|
||||
template<typename T> static std::complex<T> computeOnComplex(const std::complex<T> c, Preferences::AngleUnit angleUnit);
|
||||
template<typename T> static Complex<T> computeOnComplex(const std::complex<T> c, Preferences::AngleUnit angleUnit) {
|
||||
/* ln has a branch cut on ]-inf, 0]: it is then multivalued on this cut. We
|
||||
* followed the convention chosen by the lib c++ of llvm on ]-inf+0i, 0+0i]
|
||||
* (warning: ln takes the other side of the cut values on ]-inf-0i, 0-0i]). */
|
||||
return std::log(c);
|
||||
}
|
||||
Evaluation<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
|
||||
return ApproximationHelper::Map<float>(this, context, angleUnit,computeOnComplex<float>);
|
||||
}
|
||||
@@ -32,6 +52,16 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
class NaperianLogarithm : public Expression {
|
||||
public:
|
||||
NaperianLogarithm() : Expression(TreePool::sharedPool()->createTreeNode<NaperianLogarithmNode>()) {}
|
||||
NaperianLogarithm(const NaperianLogarithmNode * n) : Expression(n) {}
|
||||
NaperianLogarithm(Expression operand) : NaperianLogarithm() {
|
||||
replaceChildAtIndexInPlace(0, operand);
|
||||
}
|
||||
Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -140,8 +140,8 @@ im { poincare_expression_yylval.expression = new ImaginaryPart(); return FUNCTIO
|
||||
int { poincare_expression_yylval.expression = new Integral(); return FUNCTION; }
|
||||
inverse { poincare_expression_yylval.expression = new MatrixInverse(); return FUNCTION; }
|
||||
lcm { poincare_expression_yylval.expression = new LeastCommonMultiple(); return FUNCTION; }
|
||||
ln { poincare_expression_yylval.expression = new NaperianLogarithm(); return FUNCTION; }
|
||||
*/
|
||||
ln { poincare_expression_yylval.expression = NaperianLogarithm(); return FUNCTION; }
|
||||
log { return LOGFUNCTION; }
|
||||
/*permute { poincare_expression_yylval.expression = new PermuteCoefficient(); return FUNCTION; }
|
||||
prediction95 { poincare_expression_yylval.expression = new PredictionInterval(); return FUNCTION; }
|
||||
|
||||
@@ -2,46 +2,31 @@
|
||||
#include <poincare/symbol.h>
|
||||
#include <poincare/logarithm.h>
|
||||
#include <poincare/simplification_helper.h>
|
||||
extern "C" {
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
}
|
||||
#include <ion.h>
|
||||
#include <cmath>
|
||||
|
||||
namespace Poincare {
|
||||
|
||||
Expression::Type NaperianLogarithm::type() const {
|
||||
return Type::NaperianLogarithm;
|
||||
NaperianLogarithmNode * NaperianLogarithmNode::FailedAllocationStaticNode() {
|
||||
static AllocationFailureExpressionNode<NaperianLogarithmNode> failure;
|
||||
TreePool::sharedPool()->registerStaticNodeIfRequired(&failure);
|
||||
return &failure;
|
||||
}
|
||||
|
||||
Expression * NaperianLogarithm::clone() const {
|
||||
NaperianLogarithm * a = new NaperianLogarithm(m_operands, true);
|
||||
return a;
|
||||
Expression NaperianLogarithmNode::shallowReduce(Context& context, Preferences::AngleUnit angleUnit) const {
|
||||
return NaperianLogarithm(this).shallowReduce(context, angleUnit);
|
||||
}
|
||||
|
||||
Expression NaperianLogarithm::shallowReduce(Context& context, Preferences::AngleUnit angleUnit) {
|
||||
Expression * e = Expression::defaultShallowReduce(context, angleUnit);
|
||||
if (e != this) {
|
||||
Expression NaperianLogarithm::shallowReduce(Context& context, Preferences::AngleUnit angleUnit) const {
|
||||
Expression e = Expression::defaultShallowReduce(context, angleUnit);
|
||||
if (e.isUndefinedOrAllocationFailure()) {
|
||||
return e;
|
||||
}
|
||||
#if MATRIX_EXACT_REDUCING
|
||||
if (operand(0)->type() == Type::Matrix) {
|
||||
return SimplificationHelper::Map(this, context, angleUnit);
|
||||
if (childAtIndex(0).type() == ExpressionNode::Type::Matrix) {
|
||||
return SimplificationHelper::Map(*this, context, angleUnit);
|
||||
}
|
||||
#endif
|
||||
const Expression * logOperands[2] = {operand(0)->clone(), new Symbol(Ion::Charset::Exponential)};
|
||||
Logarithm * l = new Logarithm(logOperands, 2, false);
|
||||
replaceWith(l, true);
|
||||
return l->shallowReduce(context, angleUnit);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::complex<T> NaperianLogarithm::computeOnComplex(const std::complex<T> c, Preferences::AngleUnit angleUnit) {
|
||||
/* ln has a branch cut on ]-inf, 0]: it is then multivalued on this cut. We
|
||||
* followed the convention chosen by the lib c++ of llvm on ]-inf+0i, 0+0i]
|
||||
* (warning: ln takes the other side of the cut values on ]-inf-0i, 0-0i]). */
|
||||
return std::log(c);
|
||||
Logarithm l = Logarithm(childAtIndex(0), Symbol(Ion::Charset::Exponential));
|
||||
return l.shallowReduce(context, angleUnit);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -10,14 +10,14 @@ QUIZ_CASE(poincare_logarithm_evaluate) {
|
||||
assert_parsed_expression_evaluates_to<float>("log(2,64)", "0.1666667");
|
||||
assert_parsed_expression_evaluates_to<double>("log(6,7)", "0.9207822211616");
|
||||
assert_parsed_expression_evaluates_to<float>("log(5)", "0.69897");
|
||||
// assert_parsed_expression_evaluates_to<double>("ln(5)", "1.6094379124341");
|
||||
assert_parsed_expression_evaluates_to<double>("ln(5)", "1.6094379124341");
|
||||
assert_parsed_expression_evaluates_to<float>("log(2+5*I,64)", "0.4048317+0.2862042*I");
|
||||
assert_parsed_expression_evaluates_to<double>("log(6,7+4*I)", "8.0843880717528E-1-2.0108238082167E-1*I");
|
||||
assert_parsed_expression_evaluates_to<float>("log(5+2*I)", "0.731199+0.1652518*I");
|
||||
// assert_parsed_expression_evaluates_to<double>("ln(5+2*I)", "1.6836479149932+3.8050637711236E-1*I");
|
||||
assert_parsed_expression_evaluates_to<double>("ln(5+2*I)", "1.6836479149932+3.8050637711236E-1*I");
|
||||
|
||||
// WARNING: evaluate on branch cut can be multivalued
|
||||
// assert_parsed_expression_evaluates_to<double>("ln(-4)", "1.3862943611199+3.1415926535898*I");
|
||||
assert_parsed_expression_evaluates_to<double>("ln(-4)", "1.3862943611199+3.1415926535898*I");
|
||||
}
|
||||
|
||||
QUIZ_CASE(poincare_logarithm_simplify) {
|
||||
|
||||
Reference in New Issue
Block a user