Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make expressions immutable and improve performance #236

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions include/fintamath/core/IMathObject.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ class IMathObject {
virtual MathObjectClass getClass() const noexcept = 0;

friend bool operator==(const IMathObject &lhs, const IMathObject &rhs) {
if (&lhs == &rhs) {
return true;
}

return lhs.equalsAbstract(rhs);
}

Expand Down
4 changes: 4 additions & 0 deletions include/fintamath/core/IMathObjectCRTP.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ class IMathObjectCRTP_ : public IMathObject {
}

bool operator==(const I_MATH_OBJECT_CRTP &rhs) const {
if (this == &rhs) {
return true;
}

return equals(cast<Derived>(rhs));
}

Expand Down
28 changes: 9 additions & 19 deletions include/fintamath/expressions/Expression.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "fintamath/functions/IFunction.hpp"
#include "fintamath/functions/IOperator.hpp"
#include "fintamath/literals/Variable.hpp"
#include "fintamath/numbers/Real.hpp"

namespace fintamath {

Expand Down Expand Up @@ -78,29 +79,20 @@ class Expression : public IExpressionCRTP<Expression> {

Expression(int64_t val);

std::string toString() const override;

const std::shared_ptr<IFunction> &getFunction() const override;

const ArgumentPtrVector &getChildren() const override;

void setChildren(const ArgumentPtrVector &childVect) override;
std::string toString() const override;

void setVariables(const std::vector<std::pair<Variable, ArgumentPtr>> &varsToVals) override;
std::unique_ptr<IMathObject> toMinimalObject() const override;

void setVariable(const Variable &var, const Expression &val);
friend Expression approximate(const Expression &rhs, unsigned precision);

template <typename Function>
static void registerExpressionConstructor(ExpressionConstructor constructor);

protected:
ArgumentPtr simplify() const override;

private:
void simplifyMutable() const;

void updateStringMutable() const;

static detail::TermVector tokensToTerms(detail::TokenVector &tokens);

static detail::ObjectStack termsToObjects(detail::TermVector &terms);
Expand Down Expand Up @@ -147,19 +139,17 @@ class Expression : public IExpressionCRTP<Expression> {

friend std::unique_ptr<IMathObject> parseRawExpr(const std::string &str);

friend Expression approximate(const Expression &rhs, unsigned precision);

static ExpressionMaker &getExpressionMaker();

private:
mutable ArgumentPtr child;
ArgumentPtr child;

mutable ArgumentPtrVector childrenCached = {{}};
mutable ArgumentPtrVector childrenCached;
};

mutable std::string stringCached;
Expression solve(const Expression &rhs);

mutable bool isSimplified = false;
};
Expression approximate(const Expression &rhs, unsigned precision = Real::getPrecisionStatic());

std::unique_ptr<IMathObject> parseRawExpr(const std::string &str);

Expand Down
4 changes: 0 additions & 4 deletions include/fintamath/expressions/ExpressionFunctions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,4 @@ Expression negInf();

Expression complexInf();

Expression solve(const Expression &rhs);

extern Expression approximate(const Expression &rhs, unsigned precision = Real::getPrecision());

}
17 changes: 0 additions & 17 deletions include/fintamath/expressions/ExpressionUtils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,23 +29,6 @@ ArgumentPtr useSimplifyFunctions(const std::vector<SimplifyFunction> &simplFuncs
return {};
}

ArgumentPtr simplifyUndefined(const IFunction &func, const std::same_as<ArgumentPtr> auto &...args) {
ArgumentPtr res;

if ((is<Undefined>(args) || ...)) {
static const MathObjectClass undefinedReturnType = Undefined{}.getReturnClass();
const MathObjectClass funcReturnType = func.getReturnClass();

if (is(undefinedReturnType, funcReturnType) ||
is(funcReturnType, undefinedReturnType)) {

res = Undefined{}.clone();
}
}

return res;
}

bool isInfinity(const ArgumentPtr &arg);

bool isMulInfinity(const ArgumentPtr &arg);
Expand Down
57 changes: 38 additions & 19 deletions include/fintamath/expressions/IExpression.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,22 @@ namespace fintamath {
class IExpression : public IMathObject {
FINTAMATH_PARENT_CLASS_BODY(IExpression, IMathObject)

protected:
enum class State : uint8_t {
Unknown,
PreSimplify,
Simplify,
Solve,
Approximate,
};

private:
struct CallFunctionCached {
ArgumentPtr value;
std::optional<unsigned> precision;
bool areArgsPrecise = true;
};

public:
using VariableSet = std::set<Variable, ToStringComparator<std::less<>>>;

Expand All @@ -30,45 +46,48 @@ class IExpression : public IMathObject {

virtual const ArgumentPtrVector &getChildren() const = 0;

virtual void setChildren(const ArgumentPtrVector &childVect) = 0;

VariableSet getVariables() const;
const VariableSet &getVariables() const;

virtual void setVariables(const std::vector<std::pair<Variable, ArgumentPtr>> &varsToVals);

std::unique_ptr<IMathObject> toMinimalObject() const final;
std::unique_ptr<IMathObject> toMinimalObject() const override;

virtual const std::shared_ptr<IFunction> &getOutputFunction() const;

std::string toString() const override;

protected:
virtual ArgumentPtr simplify() const;
virtual ArgumentPtr preSimplify(bool isTranformOverriden = true) const;

virtual ArgumentPtr preSimplify() const;
virtual ArgumentPtr simplify(bool isTranformOverriden = true) const;

virtual ArgumentPtr postSimplify() const;
virtual ArgumentPtr approximate(bool isTranformOverriden = true) const;

virtual ArgumentPtr approximate() const;
virtual ArgumentPtr tranform(State newState) const;

virtual ArgumentPtr setPrecision(unsigned precision, const Integer &maxInt) const;
State getState() const;

static void simplifyChild(ArgumentPtr &child);
ArgumentPtr callFunction() const;

static void preSimplifyChild(ArgumentPtr &child);
static void preSimplifyChild(ArgumentPtr &child, bool isTranformOverriden = true);

static void postSimplifyChild(ArgumentPtr &child);
static void simplifyChild(ArgumentPtr &child, bool isTranformOverriden = true);

static void approximateChild(ArgumentPtr &child);
static void approximateChild(ArgumentPtr &child, bool isTranformOverriden = true);

static void setPrecisionChild(ArgumentPtr &child, unsigned precision, const Integer &maxInt);
static void callFunctionChild(ArgumentPtr &child);

static ArgumentPtr callFunction(const IFunction &func, const ArgumentPtrVector &argPtrs);
static void tranformChild(ArgumentPtr &child, State newState, bool isOverriden);

private:
ArgumentPtr simplifyUndefined() const;

static std::unique_ptr<INumber> convertToApproximated(const INumber &num);

static std::unique_ptr<INumber> convertToApproximated(const INumber &num, unsigned precision, const Integer &maxInt);
private:
mutable std::optional<VariableSet> variablesCached;

mutable std::optional<CallFunctionCached> callFunctionCached;

static ArgumentPtrVector convertToApproximatedNumbers(const ArgumentPtrVector &args);
mutable State state = State::Unknown;
};

template <typename Derived>
Expand Down
13 changes: 3 additions & 10 deletions include/fintamath/expressions/interfaces/IBinaryExpression.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,11 @@ class IBinaryExpression : public IExpression {
public:
explicit IBinaryExpression(const IFunction &inFunc, ArgumentPtr lhs, ArgumentPtr rhs);

std::string toString() const override;

const std::shared_ptr<IFunction> &getFunction() const final;

const ArgumentPtrVector &getChildren() const final;

void setChildren(const ArgumentPtrVector &childVect) final;
std::string toString() const override;

protected:
using SimplifyFunction = std::function<ArgumentPtr(const IFunction &, const ArgumentPtr &, const ArgumentPtr &)>;
Expand All @@ -36,12 +34,7 @@ class IBinaryExpression : public IExpression {

virtual SimplifyFunctionVector getFunctionsForPostSimplify() const;

ArgumentPtr preSimplify() const override;

ArgumentPtr postSimplify() const override;

private:
ArgumentPtr simplifyRec(bool isPostSimplify) const;
ArgumentPtr tranform(State newState) const override;

protected:
std::shared_ptr<IFunction> func;
Expand All @@ -51,7 +44,7 @@ class IBinaryExpression : public IExpression {
ArgumentPtr rhsChild;

private:
mutable ArgumentPtrVector childrenCached = {{}, {}};
mutable ArgumentPtrVector childrenCached;
};

template <typename Derived>
Expand Down
16 changes: 5 additions & 11 deletions include/fintamath/expressions/interfaces/IPolynomExpression.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,11 @@ class IPolynomExpression : public IExpression {
public:
explicit IPolynomExpression(const IFunction &inFunc, ArgumentPtrVector args);

std::string toString() const override;

const std::shared_ptr<IFunction> &getFunction() const final;

const ArgumentPtrVector &getChildren() const final;

void setChildren(const ArgumentPtrVector &childVect) final;
std::string toString() const override;

protected:
using SimplifyFunction = std::function<ArgumentPtr(const IFunction &, const ArgumentPtr &, const ArgumentPtr &)>;
Expand All @@ -40,9 +38,7 @@ class IPolynomExpression : public IExpression {

virtual std::string childToString(const IOperator &oper, const ArgumentPtr &inChild, const ArgumentPtr &prevChild) const;

ArgumentPtr preSimplify() const override;

ArgumentPtr postSimplify() const override;
ArgumentPtr preSimplify(bool isTranformOverriden = true) const override;

virtual bool isTermOrderInversed() const noexcept;

Expand All @@ -51,13 +47,11 @@ class IPolynomExpression : public IExpression {
virtual std::strong_ordering compare(const ArgumentPtr &lhs, const ArgumentPtr &rhs) const;

private:
void simplifyRec(bool isPostSimplify);

void simplifyChildren(bool isPostSimplify);
ArgumentPtr tranform(State newState) const override;

void compress();
void compress(ArgumentPtrVector &newChildren) const;

void sort();
void sort(ArgumentPtrVector &newChildren) const;

protected:
std::shared_ptr<IFunction> func;
Expand Down
12 changes: 3 additions & 9 deletions include/fintamath/expressions/interfaces/IUnaryExpression.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,11 @@ class IUnaryExpression : public IExpression {
public:
explicit IUnaryExpression(const IFunction &inFunc, ArgumentPtr rhs);

std::string toString() const override;

const std::shared_ptr<IFunction> &getFunction() const final;

const ArgumentPtrVector &getChildren() const override;

void setChildren(const ArgumentPtrVector &childVect) override;
std::string toString() const override;

protected:
using SimplifyFunction = std::function<ArgumentPtr(const IFunction &, const ArgumentPtr &)>;
Expand All @@ -36,20 +34,16 @@ class IUnaryExpression : public IExpression {

virtual SimplifyFunctionVector getFunctionsForPostSimplify() const;

ArgumentPtr preSimplify() const override;

ArgumentPtr postSimplify() const override;

protected:
std::shared_ptr<IFunction> func;

ArgumentPtr child;

private:
ArgumentPtr simplifyRec(bool isPostSimplify) const;
ArgumentPtr tranform(State newState) const override;

private:
mutable ArgumentPtrVector childrenCached = {{}};
mutable ArgumentPtrVector childrenCached;
};

template <typename Derived>
Expand Down
3 changes: 2 additions & 1 deletion include/fintamath/numbers/Complex.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <compare>
#include <cstdint>
#include <memory>
#include <optional>
#include <string>

#include "fintamath/core/IMathObject.hpp"
Expand Down Expand Up @@ -48,7 +49,7 @@ class Complex : public INumberCRTP<Complex> {

std::unique_ptr<IMathObject> toMinimalObject() const override;

bool isPrecise() const noexcept override;
std::optional<unsigned> getPrecision() const noexcept override;

bool isComplex() const noexcept override;

Expand Down
5 changes: 3 additions & 2 deletions include/fintamath/numbers/INumber.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <concepts>
#include <memory>
#include <optional>
#include <string>
#include <utility>

Expand All @@ -17,8 +18,8 @@ class INumber : public IComparable {
FINTAMATH_PARENT_CLASS_BODY(INumber, IComparable)

public:
virtual bool isPrecise() const noexcept {
return true;
virtual std::optional<unsigned> getPrecision() const noexcept {
return {};
}

virtual bool isComplex() const noexcept {
Expand Down
Loading
Loading