Skip to content

Commit

Permalink
Add Mod, Floor, Ceil
Browse files Browse the repository at this point in the history
  • Loading branch information
fintarin committed Oct 25, 2023
1 parent 60965d4 commit 70e5343
Show file tree
Hide file tree
Showing 17 changed files with 599 additions and 1 deletion.
3 changes: 3 additions & 0 deletions include/fintamath/core/MathObjectTypes.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@ class MathObjectType {
Integral,
Frac,
PowF,
Floor,
Ceil,

IOperator = 12000,

Expand Down Expand Up @@ -140,6 +142,7 @@ class MathObjectType {
Index,
Deg,
Comma,
Mod,

None = std::numeric_limits<size_t>::max(),
};
Expand Down
6 changes: 6 additions & 0 deletions include/fintamath/expressions/ExpressionFunctions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ Expression sub(const Expression &lhs, const Expression &rhs);

Expression div(const Expression &lhs, const Expression &rhs);

Expression mod(const Expression &lhs, const Expression &rhs);

Expression neg(const Expression &rhs);

Expression eqv(const Expression &lhs, const Expression &rhs);
Expand All @@ -30,6 +32,10 @@ Expression lessEqv(const Expression &lhs, const Expression &rhs);

Expression moreEqv(const Expression &lhs, const Expression &rhs);

Expression floor(const Expression &rhs);

Expression ceil(const Expression &rhs);

Expression abs(const Expression &rhs);

Expression factorial(const Expression &rhs);
Expand Down
1 change: 1 addition & 0 deletions include/fintamath/functions/IOperator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class IOperator : public IFunction {
PrefixUnary, // e.g. -a
Multiplication, // e.g. a * b
Addition, // e.g. a + b
Modulo, // e.g. a mod b
Comparison, // e.g. a = b
Conjunction, // e.g. a & b
Disjunction, // e.g. a | b
Expand Down
29 changes: 29 additions & 0 deletions include/fintamath/functions/ntheory/Ceil.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#pragma once

#include "fintamath/functions/IFunction.hpp"
#include "fintamath/numbers/INumber.hpp"

namespace fintamath {

class Ceil : public IFunctionCRTP<INumber, Ceil, INumber> {
public:
Ceil() = default;

std::string toString() const override {
return "ceil";
}

static MathObjectType getTypeStatic() {
return MathObjectType::Ceil;
}

protected:
std::unique_ptr<IMathObject> call(const ArgumentRefVector &argsVect) const override;

private:
static std::unique_ptr<IMathObject> multiCeilSimplify(const INumber &rhs);
};

FINTAMATH_FUNCTION_EXPRESSION(Ceil, ceilExpr);

}
29 changes: 29 additions & 0 deletions include/fintamath/functions/ntheory/Floor.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#pragma once

#include "fintamath/functions/IFunction.hpp"
#include "fintamath/numbers/INumber.hpp"

namespace fintamath {

class Floor : public IFunctionCRTP<INumber, Floor, INumber> {
public:
Floor() = default;

std::string toString() const override {
return "floor";
}

static MathObjectType getTypeStatic() {
return MathObjectType::Floor;
}

protected:
std::unique_ptr<IMathObject> call(const ArgumentRefVector &argsVect) const override;

private:
static std::unique_ptr<IMathObject> multiFloorSimplify(const INumber &rhs);
};

FINTAMATH_FUNCTION_EXPRESSION(Floor, floorExpr);

}
31 changes: 31 additions & 0 deletions include/fintamath/functions/ntheory/Mod.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#pragma once

#include "fintamath/functions/IOperator.hpp"
#include "fintamath/numbers/INumber.hpp"
#include "fintamath/numbers/Integer.hpp"

namespace fintamath {

class Mod : public IOperatorCRTP<INumber, Mod, INumber, INumber> {
public:
Mod() : IOperatorCRTP(IOperator::Priority::Modulo) {
}

std::string toString() const override {
return "mod";
}

static MathObjectType getTypeStatic() {
return MathObjectType::Mod;
}

protected:
std::unique_ptr<IMathObject> call(const ArgumentRefVector &argsVect) const override;

private:
static std::unique_ptr<IMathObject> multiModSimplify(const INumber &lhs, const INumber &rhs);
};

FINTAMATH_FUNCTION_EXPRESSION(Mod, modExpr);

}
6 changes: 6 additions & 0 deletions src/fintamath/config/ParserConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@
#include "fintamath/functions/logic/Nequiv.hpp"
#include "fintamath/functions/logic/Not.hpp"
#include "fintamath/functions/logic/Or.hpp"
#include "fintamath/functions/ntheory/Ceil.hpp"
#include "fintamath/functions/ntheory/Floor.hpp"
#include "fintamath/functions/ntheory/Mod.hpp"
#include "fintamath/functions/other/Comma.hpp"
#include "fintamath/functions/other/Deg.hpp"
#include "fintamath/functions/other/Factorial.hpp"
Expand Down Expand Up @@ -223,6 +226,8 @@ struct ParserConfig {
IFunction::registerType<Integral>();
IFunction::registerType<Frac>();
IFunction::registerType<PowF>();
IFunction::registerType<Floor>();
IFunction::registerType<Ceil>();

IOperator::registerType<Add>();
IOperator::registerType<Sub>();
Expand All @@ -248,6 +253,7 @@ struct ParserConfig {
IOperator::registerType<Index>();
IOperator::registerType<Deg>();
IOperator::registerType<Comma>();
IOperator::registerType<Mod>();

IExpression::registerType<Expression>();
}
Expand Down
15 changes: 15 additions & 0 deletions src/fintamath/expressions/ExpressionFunctions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
#include "fintamath/functions/logic/And.hpp"
#include "fintamath/functions/logic/Not.hpp"
#include "fintamath/functions/logic/Or.hpp"
#include "fintamath/functions/ntheory/Ceil.hpp"
#include "fintamath/functions/ntheory/Floor.hpp"
#include "fintamath/functions/ntheory/Mod.hpp"
#include "fintamath/functions/other/Factorial.hpp"
#include "fintamath/functions/powers/Exp.hpp"
#include "fintamath/functions/powers/Pow.hpp"
Expand Down Expand Up @@ -53,6 +56,10 @@ Expression div(const Expression &lhs, const Expression &rhs) {
return lhs / rhs;
}

Expression mod(const Expression &lhs, const Expression &rhs) {
return Expression(modExpr(lhs, rhs));
}

Expression neg(const Expression &rhs) {
return -rhs;
}
Expand Down Expand Up @@ -81,6 +88,14 @@ Expression moreEqv(const Expression &lhs, const Expression &rhs) {
return Expression(moreEqvExpr(lhs, rhs));
}

Expression floor(const Expression &rhs) {
return Expression(floorExpr(rhs));
}

Expression ceil(const Expression &rhs) {
return Expression(ceilExpr(rhs));
}

Expression abs(const Expression &rhs) {
return Expression(absExpr(rhs));
}
Expand Down
48 changes: 48 additions & 0 deletions src/fintamath/functions/ntheory/Ceil.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#include "fintamath/functions/ntheory/Ceil.hpp"

#include "fintamath/functions/powers/Sqrt.hpp"
#include "fintamath/numbers/Complex.hpp"
#include "fintamath/numbers/Integer.hpp"
#include "fintamath/numbers/IntegerFunctions.hpp"
#include "fintamath/numbers/Rational.hpp"
#include "fintamath/numbers/RationalFunctions.hpp"
#include "fintamath/numbers/Real.hpp"
#include "fintamath/numbers/RealFunctions.hpp"

namespace fintamath {

std::unique_ptr<IMathObject> Ceil::call(const ArgumentRefVector &argsVect) const {
const auto &rhs = cast<INumber>(argsVect.front().get());

return multiCeilSimplify(rhs);
}

std::unique_ptr<IMathObject> Ceil::multiCeilSimplify(const INumber &rhs) {
static const auto multiCeil = [] {
static MultiMethod<std::unique_ptr<IMathObject>(const INumber &)> outMultiCeil;

outMultiCeil.add<Integer>([](const Integer &inRhs) {
return inRhs.clone();
});

outMultiCeil.add<Rational>([](const Rational &inRhs) {
return ceil(inRhs).clone();
});

outMultiCeil.add<Real>([](const Real &inRhs) {
return ceil(inRhs).clone();
});

outMultiCeil.add<Complex>([](const Complex &inRhs) {
const auto re = cast<INumber>(multiCeilSimplify(inRhs.real()));
const auto im = cast<INumber>(multiCeilSimplify(inRhs.imag()));
return Complex(*re, *im).toMinimalObject();
});

return outMultiCeil;
}();

return multiCeil(rhs);
}

}
48 changes: 48 additions & 0 deletions src/fintamath/functions/ntheory/Floor.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#include "fintamath/functions/ntheory/Floor.hpp"

#include "fintamath/functions/powers/Sqrt.hpp"
#include "fintamath/numbers/Complex.hpp"
#include "fintamath/numbers/Integer.hpp"
#include "fintamath/numbers/IntegerFunctions.hpp"
#include "fintamath/numbers/Rational.hpp"
#include "fintamath/numbers/RationalFunctions.hpp"
#include "fintamath/numbers/Real.hpp"
#include "fintamath/numbers/RealFunctions.hpp"

namespace fintamath {

std::unique_ptr<IMathObject> Floor::call(const ArgumentRefVector &argsVect) const {
const auto &rhs = cast<INumber>(argsVect.front().get());

return multiFloorSimplify(rhs);
}

std::unique_ptr<IMathObject> Floor::multiFloorSimplify(const INumber &rhs) {
static const auto multiFloor = [] {
static MultiMethod<std::unique_ptr<IMathObject>(const INumber &)> outMultiFloor;

outMultiFloor.add<Integer>([](const Integer &inRhs) {
return inRhs.clone();
});

outMultiFloor.add<Rational>([](const Rational &inRhs) {
return floor(inRhs).clone();
});

outMultiFloor.add<Real>([](const Real &inRhs) {
return floor(inRhs).clone();
});

outMultiFloor.add<Complex>([](const Complex &inRhs) {
const auto re = cast<INumber>(multiFloorSimplify(inRhs.real()));
const auto im = cast<INumber>(multiFloorSimplify(inRhs.imag()));
return Complex(*re, *im).toMinimalObject();
});

return outMultiFloor;
}();

return multiFloor(rhs);
}

}
41 changes: 41 additions & 0 deletions src/fintamath/functions/ntheory/Mod.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#include "fintamath/functions/ntheory/Mod.hpp"

#include "fintamath/literals/constants/Undefined.hpp"
#include "fintamath/numbers/IntegerFunctions.hpp"

namespace fintamath {

std::unique_ptr<IMathObject> Mod::call(const ArgumentRefVector &argsVect) const {
const auto &lhs = cast<INumber>(argsVect.front().get());
const auto &rhs = cast<INumber>(argsVect.back().get());

if (rhs == Integer(0)) {
return Undefined().clone();
}

return multiModSimplify(lhs, rhs);
}

std::unique_ptr<IMathObject> Mod::multiModSimplify(const INumber &lhs, const INumber &rhs) {
// TODO: implement non-integer modulo

static const auto multiMod = [] {
static MultiMethod<std::unique_ptr<IMathObject>(const INumber &, const INumber &)> outMultiMod;

outMultiMod.add<Integer, Integer>([](const Integer &inLhs, const Integer &inRhs) {
Integer mod = inLhs % inRhs;

if (mod != 0 && inLhs.sign() != inRhs.sign()) {
mod += inRhs;
}

return std::move(mod).clone();
});

return outMultiMod;
}();

return multiMod(lhs, rhs);
}

}
23 changes: 23 additions & 0 deletions tests/src/expressions/ExpressionFunctionsTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,29 @@ TEST(ExpressionFunctionsTests, moreEqvTest) {
EXPECT_EQ(moreEqv(Expression("a^2"), Expression("a")).toString(), "a^2 - a >= 0");
}

TEST(ExpressionFunctionsTests, modTest) {
EXPECT_EQ(mod(Variable("a"), Expression("b^2")).toString(), "a mod (b^2)");
EXPECT_EQ(mod(10, Expression("a+2")).toString(), "10 mod (a + 2)");
EXPECT_EQ(mod(Expression("5/2"), Expression("3")).toString(), "(5/2) mod 3");
EXPECT_EQ(mod(Expression("5"), Expression("3")).toString(), "2");
}

TEST(ExpressionFunctionsTests, floorTest) {
EXPECT_EQ(floor(Expression("a+3")).toString(), "floor(a + 3)");
EXPECT_EQ(floor(Expression("a^4")).toString(), "floor(a^4)");
EXPECT_EQ(floor(Expression("-333")).toString(), "-333");
EXPECT_EQ(floor(Expression("2/3")).toString(), "0");
EXPECT_EQ(floor(Expression("-2/3")).toString(), "-1");
}

TEST(ExpressionFunctionsTests, ceilTest) {
EXPECT_EQ(ceil(Expression("a+3")).toString(), "ceil(a + 3)");
EXPECT_EQ(ceil(Expression("a^4")).toString(), "ceil(a^4)");
EXPECT_EQ(ceil(Expression("-333")).toString(), "-333");
EXPECT_EQ(ceil(Expression("2/3")).toString(), "1");
EXPECT_EQ(ceil(Expression("-2/3")).toString(), "0");
}

TEST(ExpressionFunctionsTests, absTest) {
EXPECT_EQ(abs(Expression("a+3")).toString(), "abs(a + 3)");
EXPECT_EQ(abs(Expression("a^4")).toString(), "abs(a^4)");
Expand Down
Loading

0 comments on commit 70e5343

Please sign in to comment.