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

ExpressionComparator & fixes #167

Merged
merged 11 commits into from
Nov 29, 2023
2 changes: 1 addition & 1 deletion include/fintamath/expressions/Expression.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ class Expression : public IExpressionCRTP<Expression> {

void setVariable(const Variable &var, const Expression &val);

static void registerTermsMaker(Parser::Function<std::unique_ptr<Term>, const Token &> &&maker) {
static void registerTermMaker(Parser::Function<std::unique_ptr<Term>, const Token &> &&maker) {
Parser::add<Token>(getTermMakers(), std::move(maker));
}

Expand Down
14 changes: 14 additions & 0 deletions include/fintamath/expressions/ExpressionComparator.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#pragma once

#include "fintamath/functions/FunctionArguments.hpp"

namespace fintamath {

struct ComparatorOptions {
bool constantOrderInversed = false;
bool comparableOrderInversed = false;
};

std::strong_ordering compare(ArgumentPtr lhs, ArgumentPtr rhs, ComparatorOptions options = {});

}
2 changes: 2 additions & 0 deletions include/fintamath/expressions/ExpressionUtils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ std::pair<ArgumentPtr, ArgumentPtr> splitPowExpr(const ArgumentPtr &rhs);

std::pair<ArgumentPtr, ArgumentPtr> splitRational(const ArgumentPtr &arg);

ArgumentPtr makePolynom(const IFunction &func, ArgumentPtrVector &&args);

ArgumentPtr makePolynom(const IFunction &func, const ArgumentPtrVector &args);

ArgumentPtrVector getPolynomChildren(const IFunction &func, const ArgumentPtr &arg);
Expand Down
106 changes: 2 additions & 104 deletions include/fintamath/expressions/interfaces/IPolynomExpression.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,39 +28,19 @@ class IPolynomExpression : public IExpression {

using SimplifyFunctionVector = std::vector<SimplifyFunction>;

using ExpressionTreePathStack = std::stack<std::pair<const std::shared_ptr<const IExpression>, size_t>>;

struct ChildrenComparatorResult {
int postfix = 0;
int postfixUnary = 0;
int prefixFirst = 0;
int prefixLast = 0;
int prefixVariables = 0;
int size = 0;
};

virtual SimplifyFunctionVector getFunctionsForPreSimplify() const;

virtual SimplifyFunctionVector getFunctionsForPostSimplify() const;

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

/**
* @brief
*
* @param lhs
* @param rhs
* @return -1 if we should swap the arguments
* @return 1 if we should not swap the arguments
* @return 0 if this comparator fails
*/
virtual int comparator(const ArgumentPtr &lhs, const ArgumentPtr &rhs) const;
virtual std::strong_ordering compare(const ArgumentPtr &lhs, const ArgumentPtr &rhs) const;

ArgumentPtr preSimplify() const override;

ArgumentPtr postSimplify() const override;

virtual bool isTermsOrderInversed() const;
virtual bool isConstantOrderInversed() const;

virtual bool isComparableOrderInversed() const;

Expand All @@ -73,88 +53,6 @@ class IPolynomExpression : public IExpression {

void sort();

/**
* @brief
*
* @param lhs
* @param rhs
* @return -1 if we should swap the arguments
* @return 1 if we should not swap the arguments
* @return 0 if this comparator fails
*/
int comparatorNonExpressions(const ArgumentPtr &lhs, const ArgumentPtr &rhs) const;

/**
* @brief
*
* @param lhs
* @param rhs
* @return -1 if we should swap the arguments
* @return 1 if we should not swap the arguments
* @return 0 if this comparator fails
*/
int comparatorPolynoms(const std::shared_ptr<const IPolynomExpression> &lhs,
const std::shared_ptr<const IPolynomExpression> &rhs) const;

/**
* @brief
*
* @param lhs
* @param rhs
* @return -1 if we should swap the arguments
* @return 1 if we should not swap the arguments
* @return 0 if this comparator fails
*/
int comparatorPolynomAndNonPolynom(const std::shared_ptr<const IPolynomExpression> &lhs,
const ArgumentPtr &rhs) const;

/**
* @brief
*
* @param lhs
* @param rhs
* @return -1 if we should swap the arguments
* @return 1 if we should not swap the arguments
* @return 0 if this comparator fails
*/
int comparatorExpressionAndNonExpression(const std::shared_ptr<const IExpression> &lhs,
const ArgumentPtr &rhs) const;

/**
* @brief
*
* @param lhs
* @param rhs
* @return -1 if we should swap the arguments
* @return 1 if we should not swap the arguments
* @return 0 if this comparator fails
*/
int comparatorExpressions(const std::shared_ptr<const IExpression> &lhs,
const std::shared_ptr<const IExpression> &rhs) const;

ChildrenComparatorResult comparatorChildren(const ArgumentPtrVector &lhsChildren,
const ArgumentPtrVector &rhsChildren) const;

/**
* @brief
*
* @param lhsExpr
* @param rhsExpr
* @return -1 if we should swap the arguments
* @return 1 if we should not swap the arguments
* @return 0 if this comparator fails
*/
static int comparatorFunctions(const std::shared_ptr<const IFunction> &lhs,
const std::shared_ptr<const IFunction> &rhs);

int comparatorVariables(const ArgumentPtr &lhs, const ArgumentPtr &rhs, bool isTermsOrderInversed) const;

static std::shared_ptr<const Variable> getNextVariable(ExpressionTreePathStack &stack);

static size_t getPositionOfFirstChildWithVariable(const ArgumentPtrVector &children);

static bool unwrapUnary(ArgumentPtr &lhs);

protected:
std::shared_ptr<IFunction> func;

Expand Down
13 changes: 13 additions & 0 deletions include/fintamath/functions/IFunction.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ class IFunction : public IMathObject {

virtual ArgumentTypeVector getArgTypes() const = 0;

virtual size_t getFunctionOrder() const = 0;

virtual bool doArgsMatch(const ArgumentRefVector &argsVect) const = 0;

virtual bool isEvaluatable() const = 0;
Expand All @@ -51,6 +53,9 @@ class IFunction : public IMathObject {
template <std::derived_from<IFunction> T>
static void registerType() {
Parser::registerType<T>(getParser());

getFunctionOrderMutableMap()[T().toString()] = maxFunctionOrder;
maxFunctionOrder++;
}

static std::unique_ptr<IFunction> parse(const std::string &parsedStr, IFunction::Type type = IFunction::Type::Any) {
Expand All @@ -67,8 +72,16 @@ class IFunction : public IMathObject {
protected:
virtual std::unique_ptr<IMathObject> callAbstract(const ArgumentRefVector &argsVect) const = 0;

static const std::unordered_map<std::string, size_t> &getFunctionOrderMap() {
return getFunctionOrderMutableMap();
}

private:
static std::unordered_map<std::string, size_t> &getFunctionOrderMutableMap();

static Parser::Map<std::unique_ptr<IFunction>> &getParser();

static inline size_t maxFunctionOrder = 0;
};

template <typename Return, typename Derived, typename... Args>
Expand Down
5 changes: 5 additions & 0 deletions include/fintamath/functions/IFunctionCRTP.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ class IFunctionCRTP_ : public IFunction {
return argTypes;
}

size_t getFunctionOrder() const final {
static const std::string funcStr = Derived().toString();
return getFunctionOrderMap().at(funcStr);
}

bool doArgsMatch(const ArgumentRefVector &argsVect) const override {
if (argsVect.empty()) { // TODO: support None type functions
return false;
Expand Down
6 changes: 3 additions & 3 deletions src/fintamath/config/ExpressionConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ struct ExpressionConfig {
}

static void registerTermsMakers() {
Expression::registerTermsMaker([](const Token &token) {
Expression::registerTermMaker([](const Token &token) {
if (auto arg = IFunction::parse(token, IFunction::Type::Binary)) {
return std::make_unique<Term>(token, std::move(arg));
}
Expand All @@ -125,15 +125,15 @@ struct ExpressionConfig {
return std::unique_ptr<Term>();
});

Expression::registerTermsMaker([](const Token &token) {
Expression::registerTermMaker([](const Token &token) {
if (auto arg = ILiteral::parse(token)) {
return std::make_unique<Term>(token, std::move(arg));
}

return std::unique_ptr<Term>();
});

Expression::registerTermsMaker([](const Token &token) {
Expression::registerTermMaker([](const Token &token) {
if (auto arg = INumber::parse(token)) {
return std::make_unique<Term>(token, std::move(arg));
}
Expand Down
5 changes: 5 additions & 0 deletions src/fintamath/config/ParserConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,11 @@ Parser::Map<std::unique_ptr<IConstant>> &IConstant::getParser() {
return parser;
}

std::unordered_map<std::string, size_t> &IFunction::getFunctionOrderMutableMap() {
static std::unordered_map<std::string, size_t> orderMap;
return orderMap;
}

Parser::Map<std::unique_ptr<IFunction>> &IFunction::getParser() {
static Parser::Map<std::unique_ptr<IFunction>> parser;
return parser;
Expand Down
Loading