mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-19 00:37:25 +01:00
[poincare] Fix LCM
This commit is contained in:
@@ -80,6 +80,7 @@ objs += $(addprefix poincare/src/,\
|
||||
infinity.o\
|
||||
integer.o\
|
||||
layout_helper.o\
|
||||
least_common_multiple.o\
|
||||
logarithm.o\
|
||||
opposite.o\
|
||||
matrix.o\
|
||||
|
||||
@@ -144,6 +144,7 @@
|
||||
#include <poincare/infinity.h>
|
||||
#include <poincare/integer.h>
|
||||
#include <poincare/global_context.h>
|
||||
#include <poincare/least_common_multiple.h>
|
||||
#include <poincare/logarithm.h>
|
||||
#include <poincare/naperian_logarithm.h>
|
||||
#include <poincare/number.h>
|
||||
|
||||
@@ -1,21 +1,29 @@
|
||||
#ifndef POINCARE_LEAST_COMMON_MULTIPLE_H
|
||||
#define POINCARE_LEAST_COMMON_MULTIPLE_H
|
||||
|
||||
#include <poincare/layout_helper.h>
|
||||
#include <poincare/static_hierarchy.h>
|
||||
#include <poincare/evaluation.h>
|
||||
#include <poincare/serialization_helper.h>
|
||||
#include <poincare/expression.h>
|
||||
|
||||
namespace Poincare {
|
||||
|
||||
class LeastCommonMultiple : public StaticHierarchy<2> {
|
||||
using StaticHierarchy<2>::StaticHierarchy;
|
||||
class LeastCommonMultipleNode : public ExpressionNode {
|
||||
public:
|
||||
Type type() const override;
|
||||
static LeastCommonMultipleNode * FailedAllocationStaticNode();
|
||||
LeastCommonMultipleNode * failedAllocationStaticNode() override { return FailedAllocationStaticNode(); }
|
||||
|
||||
// TreeNode
|
||||
size_t size() const override { return sizeof(LeastCommonMultipleNode); }
|
||||
int numberOfChildren() const override { return 2; }
|
||||
#if POINCARE_TREE_LOG
|
||||
virtual void logNodeName(std::ostream & stream) const override {
|
||||
stream << "LeastCommonMultiple";
|
||||
}
|
||||
#endif
|
||||
// ExpressionNode
|
||||
Type type() const override { return Type::LeastCommonMultiple; }
|
||||
private:
|
||||
/* Layout */
|
||||
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override {
|
||||
return LayoutHelper::Prefix(this, floatDisplayMode, numberOfSignificantDigits, name());
|
||||
}
|
||||
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
|
||||
int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override {
|
||||
return SerializationHelper::Prefix(this, buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, name());
|
||||
}
|
||||
@@ -28,6 +36,19 @@ private:
|
||||
template<typename T> Evaluation<T> templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const;
|
||||
};
|
||||
|
||||
class LeastCommonMultiple : public Expression {
|
||||
public:
|
||||
LeastCommonMultiple() : Expression(TreePool::sharedPool()->createTreeNode<LeastCommonMultipleNode>()) {}
|
||||
LeastCommonMultiple(const LeastCommonMultipleNode * n) : Expression(n) {}
|
||||
LeastCommonMultiple(Expression child1, Expression child2) : LeastCommonMultiple() {
|
||||
replaceChildAtIndexInPlace(0, child1);
|
||||
replaceChildAtIndexInPlace(1, child2);
|
||||
}
|
||||
|
||||
// Expression
|
||||
Expression shallowReduce(Context& context, Preferences::AngleUnit angleUnit) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -137,8 +137,8 @@ gcd { poincare_expression_yylval.expression = GreatCommonDivisor(); return FUNCT
|
||||
im { poincare_expression_yylval.expression = ImaginaryPart(); return FUNCTION; }
|
||||
/*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; }
|
||||
*/
|
||||
lcm { poincare_expression_yylval.expression = LeastCommonMultiple(); return FUNCTION; }
|
||||
ln { poincare_expression_yylval.expression = NaperianLogarithm(); return FUNCTION; }
|
||||
log { return LOGFUNCTION; }
|
||||
/*permute { poincare_expression_yylval.expression = new PermuteCoefficient(); return FUNCTION; }
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include <poincare/rational.h>
|
||||
#include <poincare/undefined.h>
|
||||
#include <poincare/arithmetic.h>
|
||||
#include <poincare/layout_helper.h>
|
||||
|
||||
extern "C" {
|
||||
#include <assert.h>
|
||||
@@ -10,64 +11,31 @@ extern "C" {
|
||||
|
||||
namespace Poincare {
|
||||
|
||||
ExpressionNode::Type LeastCommonMultiple::type() const {
|
||||
return Type::LeastCommonMultiple;
|
||||
LeastCommonMultipleNode * LeastCommonMultipleNode::FailedAllocationStaticNode() {
|
||||
static AllocationFailureExpressionNode<LeastCommonMultipleNode> failure;
|
||||
TreePool::sharedPool()->registerStaticNodeIfRequired(&failure);
|
||||
return &failure;
|
||||
}
|
||||
|
||||
Expression * LeastCommonMultiple::clone() const {
|
||||
LeastCommonMultiple * a = new LeastCommonMultiple(m_operands, true);
|
||||
return a;
|
||||
LayoutReference LeastCommonMultipleNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const {
|
||||
return LayoutHelper::Prefix(LeastCommonMultiple(this), floatDisplayMode, numberOfSignificantDigits, name());
|
||||
}
|
||||
|
||||
Expression LeastCommonMultiple::shallowReduce(Context& context, Preferences::AngleUnit angleUnit) const {
|
||||
Expression e = Expression::defaultShallowReduce(context, angleUnit);
|
||||
if (e.isUndefinedOrAllocationFailure()) {
|
||||
return e;
|
||||
}
|
||||
Expression * op0 = childAtIndex(0);
|
||||
Expression * op1 = childAtIndex(1);
|
||||
#if MATRIX_EXACT_REDUCING
|
||||
if (op0->type() == Type::Matrix || op1->type() == Type::Matrix) {
|
||||
return replaceWith(new Undefined(), true);
|
||||
}
|
||||
#endif
|
||||
if (op0->type() == Type::Rational) {
|
||||
Rational * r0 = static_cast<Rational *>(op0);
|
||||
if (!r0->denominator().isOne()) {
|
||||
return replaceWith(new Undefined(), true);
|
||||
}
|
||||
}
|
||||
if (op1->type() == Type::Rational) {
|
||||
Rational * r1 = static_cast<Rational *>(op1);
|
||||
if (!r1->denominator().isOne()) {
|
||||
return replaceWith(new Undefined(), true);
|
||||
}
|
||||
}
|
||||
if (op0->type() != Type::Rational || op1->type() != Type::Rational) {
|
||||
return this;
|
||||
}
|
||||
Rational * r0 = static_cast<Rational *>(op0);
|
||||
Rational * r1 = static_cast<Rational *>(op1);
|
||||
|
||||
Integer a = r0->numerator();
|
||||
Integer b = r1->numerator();
|
||||
Integer lcm = Arithmetic::LCM(&a, &b);
|
||||
return replaceWith(new Rational(lcm), true);
|
||||
Expression LeastCommonMultipleNode::shallowReduce(Context& context, Preferences::AngleUnit angleUnit) const {
|
||||
return LeastCommonMultiple(this).shallowReduce(context, angleUnit);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Complex<T> * LeastCommonMultiple::templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const {
|
||||
Evaluation<T> * f1Input = childAtIndex(0)->privateApproximate(T(), context, angleUnit);
|
||||
Evaluation<T> * f2Input = childAtIndex(1)->privateApproximate(T(), context, angleUnit);
|
||||
T f1 = f1Input->toScalar();
|
||||
T f2 = f2Input->toScalar();
|
||||
delete f1Input;
|
||||
delete f2Input;
|
||||
Evaluation<T> LeastCommonMultipleNode::templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const {
|
||||
Evaluation<T> f1Input = childAtIndex(0)->approximate(T(), context, angleUnit);
|
||||
Evaluation<T> f2Input = childAtIndex(1)->approximate(T(), context, angleUnit);
|
||||
T f1 = f1Input.toScalar();
|
||||
T f2 = f2Input.toScalar();
|
||||
if (std::isnan(f1) || std::isnan(f2) || f1 != (int)f1 || f2 != (int)f2) {
|
||||
return new Complex<T>(Complex<T>::Undefined());
|
||||
return Complex<T>::Undefined();
|
||||
}
|
||||
if (f1 == 0.0f || f2 == 0.0f) {
|
||||
return new Complex<T>(0);
|
||||
return Complex<T>(0.0);
|
||||
}
|
||||
int a = (int)f2;
|
||||
int b = (int)f1;
|
||||
@@ -82,7 +50,43 @@ Complex<T> * LeastCommonMultiple::templatedApproximate(Context& context, Prefere
|
||||
a = b;
|
||||
b = r;
|
||||
}
|
||||
return new Complex<T>(product/a);
|
||||
return Complex<T>(product/a);
|
||||
}
|
||||
|
||||
Expression LeastCommonMultiple::shallowReduce(Context& context, Preferences::AngleUnit angleUnit) const {
|
||||
Expression e = Expression::defaultShallowReduce(context, angleUnit);
|
||||
if (e.isUndefinedOrAllocationFailure()) {
|
||||
return e;
|
||||
}
|
||||
Expression op0 = childAtIndex(0);
|
||||
Expression op1 = childAtIndex(1);
|
||||
#if MATRIX_EXACT_REDUCING
|
||||
if (op0.type() == Type::Matrix || op1.type() == Type::Matrix) {
|
||||
return Undefined();
|
||||
}
|
||||
#endif
|
||||
if (op0.type() == ExpressionNode::Type::Rational) {
|
||||
Rational r0 = static_cast<Rational&>(op0);
|
||||
if (!r0.integerDenominator().isOne()) {
|
||||
return Undefined();
|
||||
}
|
||||
}
|
||||
if (op1.type() == ExpressionNode::Type::Rational) {
|
||||
Rational r1 = static_cast<Rational&>(op1);
|
||||
if (!r1.integerDenominator().isOne()) {
|
||||
return Undefined();
|
||||
}
|
||||
}
|
||||
if (op0.type() != ExpressionNode::Type::Rational || op1.type() != ExpressionNode::Type::Rational) {
|
||||
return *this;
|
||||
}
|
||||
Rational r0 = static_cast<Rational&>(op0);
|
||||
Rational r1 = static_cast<Rational&>(op1);
|
||||
|
||||
Integer a = r0.signedIntegerNumerator();
|
||||
Integer b = r1.signedIntegerNumerator();
|
||||
Integer lcm = Arithmetic::LCM(a, b);
|
||||
return Rational(lcm);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -34,12 +34,12 @@ QUIZ_CASE(poincare_parse_function) {
|
||||
assert_parsed_expression_type("frac(2.3)", ExpressionNode::Type::FracPart);
|
||||
assert_parsed_expression_type("gcd(2,3)", ExpressionNode::Type::GreatCommonDivisor);
|
||||
assert_parsed_expression_type("im(2+I)", ExpressionNode::Type::ImaginaryPart);
|
||||
assert_parsed_expression_type("lcm(2,3)", ExpressionNode::Type::LeastCommonMultiple);
|
||||
#if 0
|
||||
assert_parsed_expression_type("int(x, 2, 3)", ExpressionNode::Type::Integral);
|
||||
#if MATRICES_ARE_DEFINED
|
||||
assert_parsed_expression_type("inverse([[1,2,3][4,5,6][7,8,9]])", ExpressionNode::Type::MatrixInverse);
|
||||
#endif
|
||||
assert_parsed_expression_type("lcm(2,3)", ExpressionNode::Type::LeastCommonMultiple);
|
||||
assert_parsed_expression_type("ln(2)", ExpressionNode::Type::NaperianLogarithm);
|
||||
assert_parsed_expression_type("log(2)", ExpressionNode::Type::Logarithm);
|
||||
assert_parsed_expression_type("permute(10, 4)", ExpressionNode::Type::PermuteCoefficient);
|
||||
@@ -109,14 +109,14 @@ QUIZ_CASE(poincare_function_evaluate) {
|
||||
|
||||
assert_parsed_expression_evaluates_to<float>("im(2+3I)", "3");
|
||||
assert_parsed_expression_evaluates_to<double>("im(2+3I)", "3");
|
||||
|
||||
assert_parsed_expression_evaluates_to<float>("lcm(234,394)", "46098");
|
||||
assert_parsed_expression_evaluates_to<double>("lcm(234,394)", "46098");
|
||||
#if 0
|
||||
|
||||
assert_parsed_expression_evaluates_to<float>("int(x, 1, 2)", "1.5");
|
||||
assert_parsed_expression_evaluates_to<double>("int(x, 1, 2)", "1.5");
|
||||
|
||||
assert_parsed_expression_evaluates_to<float>("lcm(234,394)", "46098");
|
||||
assert_parsed_expression_evaluates_to<double>("lcm(234,394)", "46098");
|
||||
|
||||
assert_parsed_expression_evaluates_to<float>("ln(2)", "0.6931472");
|
||||
assert_parsed_expression_evaluates_to<double>("ln(2)", "6.9314718055995E-1");
|
||||
|
||||
@@ -275,9 +275,9 @@ QUIZ_CASE(poincare_function_simplify) {
|
||||
assert_parsed_expression_simplify_to("frac(-1.3)", "7/10");
|
||||
assert_parsed_expression_simplify_to("gcd(123,278)", "1");
|
||||
assert_parsed_expression_simplify_to("gcd(11,121)", "11");
|
||||
#if 0
|
||||
assert_parsed_expression_simplify_to("lcm(123,278)", "34194");
|
||||
assert_parsed_expression_simplify_to("lcm(11,121)", "121");
|
||||
#if 0
|
||||
assert_parsed_expression_simplify_to("R(4)", "2");
|
||||
assert_parsed_expression_simplify_to("root(4,3)", "root(4,3)");
|
||||
assert_parsed_expression_simplify_to("root(4,P)", "4^(1/P)");
|
||||
|
||||
@@ -10,8 +10,12 @@ static inline int pool_size() {
|
||||
}
|
||||
#if POINCARE_TREE_LOG
|
||||
static inline void log_pool() {
|
||||
Poincare::TreePool::sharedPool()->flatLog(std::cout);
|
||||
Poincare::TreePool::sharedPool()->treeLog(std::cout);
|
||||
}
|
||||
static void log_pool_tree() {
|
||||
Poincare::TreePool::sharedPool()->treeLog(std::cout);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static void assert_pool_size(int i) {
|
||||
|
||||
Reference in New Issue
Block a user