Skip to content

Commit

Permalink
Simplify with complex numbers
Browse files Browse the repository at this point in the history
  • Loading branch information
fintarin committed Aug 26, 2023
1 parent 61febb3 commit 92efe87
Show file tree
Hide file tree
Showing 64 changed files with 438 additions and 123 deletions.
4 changes: 4 additions & 0 deletions include/fintamath/expressions/ExpressionUtils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ std::string putInSpaces(const std::string &str);

std::string functionToString(const IFunction &func, const ArgumentsPtrVector &args);

std::string operatorChildToString(const IOperator &oper, const ArgumentPtr &child);

std::string binaryOperatorToString(const IOperator &oper, const ArgumentPtr &lhs, const ArgumentPtr &rhs);

std::string prefixUnaryOperatorToString(const IOperator &oper, const ArgumentPtr &rhs);
Expand All @@ -27,6 +29,8 @@ bool hasVariable(const ArgumentPtr &arg, const Variable &var);

bool hasInfinity(const ArgumentPtr &arg);

bool hasComplex(const ArgumentPtr &arg);

bool isInfinity(const ArgumentPtr &arg);

bool isNegated(const ArgumentPtr &arg);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class IPolynomExpression : public IExpression {

virtual SimplifyFunctionsVector getFunctionsForPostSimplify() const;

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

/**
* @brief
Expand Down
3 changes: 3 additions & 0 deletions include/fintamath/functions/powers/Pow.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ namespace fintamath {
class Integer;
class Rational;
class Real;
class Complex;

class Pow : public IOperatorCRTP<INumber, Pow, INumber, INumber> {
public:
Expand All @@ -33,6 +34,8 @@ class Pow : public IOperatorCRTP<INumber, Pow, INumber, INumber> {
static std::unique_ptr<IMathObject> powSimplify(const Rational &lhs, const Rational &rhs);

static std::unique_ptr<IMathObject> powSimplify(const Real &lhs, const Real &rhs);

static std::unique_ptr<IMathObject> powSimplify(const Complex &lhs, const Complex &rhs);
};

FINTAMATH_FUNCTION_EXPRESSION(Pow, powExpr);
Expand Down
51 changes: 44 additions & 7 deletions src/fintamath/expressions/ExpressionUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@
#include "fintamath/functions/arithmetic/Div.hpp"
#include "fintamath/functions/arithmetic/Mul.hpp"
#include "fintamath/functions/arithmetic/Neg.hpp"
#include "fintamath/functions/arithmetic/Sub.hpp"
#include "fintamath/functions/powers/Pow.hpp"
#include "fintamath/literals/constants/ComplexInf.hpp"
#include "fintamath/literals/constants/Inf.hpp"
#include "fintamath/literals/constants/NegInf.hpp"
#include "fintamath/literals/constants/Undefined.hpp"
#include "fintamath/numbers/Complex.hpp"
#include "fintamath/numbers/Rational.hpp"
#include "fintamath/numbers/Real.hpp"

Expand Down Expand Up @@ -47,7 +49,20 @@ std::string operatorChildToString(const IOperator &oper, const ArgumentPtr &chil
if (const auto childExpr = cast<IExpression>(child)) {
childOper = cast<IOperator>(childExpr->getOutputFunction());
}
else if (operPriority <= IOperator::Priority::PrefixUnary && childStr.front() == Neg().toString().front()) {
else if (const auto childComplex = cast<Complex>(child)) {
if (childComplex->real() != Integer(0)) {
childOper = std::make_shared<Add>();
}
else if (childComplex->imag() != Integer(1)) {
if (childComplex->imag() == Integer(-1)) {
childOper = std::make_shared<Neg>();
}
else {
childOper = std::make_shared<Mul>();
}
}
}
else if (childStr.front() == Neg().toString().front()) {
childOper = std::make_shared<Neg>();
}
else if (is<Rational>(child)) {
Expand All @@ -62,12 +77,11 @@ std::string operatorChildToString(const IOperator &oper, const ArgumentPtr &chil
if (childOper) {
IOperator::Priority lhsOperPriority = childOper->getOperatorPriority();

if (operPriority == IOperator::Priority::Multiplication) {
return putInBrackets(childStr);
}

if (lhsOperPriority >= operPriority ||
(lhsOperPriority == operPriority && !oper.isAssociative())) {
if (lhsOperPriority > operPriority ||
(lhsOperPriority == operPriority &&
childOper->getFunctionType() == IFunction::Type::Unary) ||
(!oper.isAssociative() &&
childOper->getFunctionType() != IFunction::Type::Unary)) {

return putInBrackets(childStr);
}
Expand Down Expand Up @@ -169,6 +183,29 @@ bool hasInfinity(const ArgumentPtr &arg) {
});
}

bool hasComplex(const ArgumentPtr &arg) {
if (const auto num = cast<INumber>(arg); num && num->isComplex()) {
return true;
}

auto expr = cast<IExpression>(arg);
if (!expr) {
return false;
}

ArgumentsPtrVector children = expr->getChildren();

return std::any_of(children.begin(), children.end(), [](const auto &child) {
bool res = false;

if (hasComplex(child)) {
res = true;
}

return res;
});
}

bool isInfinity(const ArgumentPtr &arg) {
return is<Inf>(arg) || is<NegInf>(arg) || is<ComplexInf>(arg);
}
Expand Down
8 changes: 1 addition & 7 deletions src/fintamath/expressions/IExpression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -142,13 +142,7 @@ ArgumentPtr IExpression::callFunction(const IFunction &func, const ArgumentsPtrV
return {};
}

ArgumentPtr res;
try {
res = func(args);
}
catch (const UndefinedException &) {
return {};
}
ArgumentPtr res = func(args);

if (areArgumentsPrecise) {
if (const auto num = cast<INumber>(res); num && !num->isPrecise()) {
Expand Down
6 changes: 6 additions & 0 deletions src/fintamath/expressions/binary/CompExpression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@ ArgumentPtr CompExpression::preSimplify() const {
if (!simplExpr->isSolution &&
(!is<Integer>(rhsChild) || *rhsChild != Integer(0))) {

if (*func != Eqv() && *func != Neqv() &&
(hasComplex(lhsChild) || hasComplex(rhsChild))) {

return simpl;
}

if (!hasInfinity(lhsChild) && !hasInfinity(rhsChild)) {
ArgumentPtr resLhs = subExpr(simplExpr->lhsChild, simplExpr->rhsChild);
preSimplifyChild(resLhs);
Expand Down
26 changes: 10 additions & 16 deletions src/fintamath/expressions/interfaces/IPolynomExpression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ std::string IPolynomExpression::toString() const {

std::string result;

result += operatorChildToString(children.front(), {});
result += childToString(children.front(), {});

for (size_t i = 1; i < children.size(); i++) {
result += operatorChildToString(children[i], children[i - 1]);
result += childToString(children[i], children[i - 1]);
}

return result;
Expand Down Expand Up @@ -180,22 +180,16 @@ ArgumentPtr IPolynomExpression::preciseSimplify() const {
return preciseExpr;
}

std::string IPolynomExpression::operatorChildToString(const ArgumentPtr &inChild, const ArgumentPtr &prevChild) const {
std::string result = inChild->toString();

if (const auto exprChild = cast<IExpression>(inChild)) {
const auto oper = cast<IOperator>(func);
const auto childOper = cast<IOperator>(exprChild->getFunction());

if (oper &&
childOper &&
oper->getOperatorPriority() <= childOper->getOperatorPriority()) {

result = putInBrackets(result);
}
std::string IPolynomExpression::childToString(const ArgumentPtr &inChild, const ArgumentPtr &prevChild) const {
std::string childStr;
if (const auto oper = cast<IOperator>(func)) {
childStr = operatorChildToString(*oper, inChild);
}
else {
childStr = inChild->toString();
}

return prevChild ? (putInSpaces(func->toString()) + result) : result;
return prevChild ? (putInSpaces(func->toString()) + childStr) : childStr;
}

bool IPolynomExpression::isTermsOrderInversed() const {
Expand Down
5 changes: 2 additions & 3 deletions src/fintamath/expressions/polynomial/AddExpression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,10 @@ AddExpression::AddExpression(const ArgumentsPtrVector &inChildren)
: IPolynomExpressionCRTP(Add(), inChildren) {
}

std::string AddExpression::operatorChildToString(const ArgumentPtr &inChild, const ArgumentPtr &prevChild) const {
std::string AddExpression::childToString(const ArgumentPtr &inChild, const ArgumentPtr &prevChild) const {
std::string result = operatorChildToString(Add(), inChild);
bool isChildNegated = false;

std::string result = inChild->toString();

if (result.size() > 1 &&
result.front() == Neg().toString().front()) {

Expand Down
2 changes: 1 addition & 1 deletion src/fintamath/expressions/polynomial/AddExpression.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class AddExpression : public IPolynomExpressionCRTP<AddExpression> {

SimplifyFunctionsVector getFunctionsForPostSimplify() const override;

std::string operatorChildToString(const ArgumentPtr &inChild, const ArgumentPtr &prevChild) const override;
std::string childToString(const ArgumentPtr &inChild, const ArgumentPtr &prevChild) const override;

/**
* @brief
Expand Down
4 changes: 2 additions & 2 deletions src/fintamath/expressions/polynomial/MulExpression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ std::string MulExpression::toString() const {
return IPolynomExpression::toString();
}

std::string MulExpression::operatorChildToString(const ArgumentPtr &inChild, const ArgumentPtr &prevChild) const {
std::string MulExpression::childToString(const ArgumentPtr &inChild, const ArgumentPtr &prevChild) const {
if (!prevChild && *inChild == Integer(-1)) {
return Neg().toString();
}
Expand All @@ -65,7 +65,7 @@ std::string MulExpression::operatorChildToString(const ArgumentPtr &inChild, con
}
}

return operStr + inChild->toString();
return operStr + operatorChildToString(Mul(), inChild);
}

MulExpression::SimplifyFunctionsVector MulExpression::getFunctionsForPreSimplify() const {
Expand Down
2 changes: 1 addition & 1 deletion src/fintamath/expressions/polynomial/MulExpression.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class MulExpression : public IPolynomExpressionCRTP<MulExpression> {
}

protected:
std::string operatorChildToString(const ArgumentPtr &inChild, const ArgumentPtr &prevChild) const override;
std::string childToString(const ArgumentPtr &inChild, const ArgumentPtr &prevChild) const override;

SimplifyFunctionsVector getFunctionsForPreSimplify() const override;

Expand Down
4 changes: 2 additions & 2 deletions src/fintamath/expressions/polynomial/OrExpression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ OrExpression::OrExpression(const ArgumentsPtrVector &inChildren)
: IPolynomExpressionCRTP(Or(), inChildren) {
}

std::string OrExpression::operatorChildToString(const ArgumentPtr &inChild, const ArgumentPtr &prevChild) const {
std::string result = inChild->toString();
std::string OrExpression::childToString(const ArgumentPtr &inChild, const ArgumentPtr &prevChild) const {
std::string result = operatorChildToString(Or(), inChild);

if (const auto &childExpr = cast<IExpression>(inChild);
childExpr && is<And>(childExpr->getFunction())) {
Expand Down
2 changes: 1 addition & 1 deletion src/fintamath/expressions/polynomial/OrExpression.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class OrExpression : public IPolynomExpressionCRTP<OrExpression> {
}

protected:
std::string operatorChildToString(const ArgumentPtr &inChild, const ArgumentPtr &prevChild) const override;
std::string childToString(const ArgumentPtr &inChild, const ArgumentPtr &prevChild) const override;

ArgumentPtr postSimplify() const override;

Expand Down
9 changes: 5 additions & 4 deletions src/fintamath/functions/calculus/Max.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include "fintamath/functions/calculus/Max.hpp"

#include "fintamath/numbers/Complex.hpp"

namespace fintamath {

std::unique_ptr<IMathObject> Max::call(const ArgumentsRefVector &argsVect) const {
Expand All @@ -8,10 +10,9 @@ std::unique_ptr<IMathObject> Max::call(const ArgumentsRefVector &argsVect) const
for (size_t i = 1; i < argsVect.size(); i++) {
std::reference_wrapper<const IComparable> arg = cast<IComparable>(argsVect[i].get());

// TODO! uncomment
// if (is<Complex>(arg)) {
// return {};
// }
if (is<Complex>(arg)) {
return {};
}

if (res < arg) {
res = arg;
Expand Down
8 changes: 4 additions & 4 deletions src/fintamath/functions/calculus/Min.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "fintamath/functions/calculus/Min.hpp"
#include "fintamath/numbers/Complex.hpp"

namespace fintamath {

Expand All @@ -8,10 +9,9 @@ std::unique_ptr<IMathObject> Min::call(const ArgumentsRefVector &argsVect) const
for (size_t i = 1; i < argsVect.size(); i++) {
std::reference_wrapper<const IComparable> arg = cast<IComparable>(argsVect[i].get());

// TODO! uncomment
// if (is<Complex>(arg)) {
// return {};
// }
if (is<Complex>(arg)) {
return {};
}

if (res > arg) {
res = arg;
Expand Down
9 changes: 4 additions & 5 deletions src/fintamath/functions/comparison/Less.cpp
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
#include "fintamath/functions/comparison/Less.hpp"

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

namespace fintamath {

std::unique_ptr<IMathObject> Less::call(const ArgumentsRefVector &argsVect) const {
const auto &lhs = cast<IComparable>(argsVect.front().get());
const auto &rhs = cast<IComparable>(argsVect.back().get());

// TODO! uncomment
// if (is<Complex>(lhs) || is<Complex>(rhs)) {
// return {};
// }
if (is<Complex>(lhs) || is<Complex>(rhs)) {
return {};
}

return Boolean(lhs < rhs).clone();
}
Expand Down
9 changes: 5 additions & 4 deletions src/fintamath/functions/comparison/LessEqv.cpp
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
#include "fintamath/functions/comparison/LessEqv.hpp"

#include "fintamath/numbers/Complex.hpp"

namespace fintamath {

std::unique_ptr<IMathObject> LessEqv::call(const ArgumentsRefVector &argsVect) const {
const auto &lhs = cast<IComparable>(argsVect.front().get());
const auto &rhs = cast<IComparable>(argsVect.back().get());

// TODO! uncomment
// if (is<Complex>(lhs) || is<Complex>(rhs)) {
// return {};
// }
if (is<Complex>(lhs) || is<Complex>(rhs)) {
return {};
}

return Boolean(lhs <= rhs).clone();
}
Expand Down
9 changes: 5 additions & 4 deletions src/fintamath/functions/comparison/More.cpp
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
#include "fintamath/functions/comparison/More.hpp"

#include "fintamath/numbers/Complex.hpp"

namespace fintamath {

std::unique_ptr<IMathObject> More::call(const ArgumentsRefVector &argsVect) const {
const auto &lhs = cast<IComparable>(argsVect.front().get());
const auto &rhs = cast<IComparable>(argsVect.back().get());

// TODO! uncomment
// if (is<Complex>(lhs) || is<Complex>(rhs)) {
// return {};
// }
if (is<Complex>(lhs) || is<Complex>(rhs)) {
return {};
}

return Boolean(lhs > rhs).clone();
}
Expand Down
9 changes: 5 additions & 4 deletions src/fintamath/functions/comparison/MoreEqv.cpp
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
#include "fintamath/functions/comparison/MoreEqv.hpp"

#include "fintamath/numbers/Complex.hpp"

namespace fintamath {

std::unique_ptr<IMathObject> MoreEqv::call(const ArgumentsRefVector &argsVect) const {
const auto &lhs = cast<IComparable>(argsVect.front().get());
const auto &rhs = cast<IComparable>(argsVect.back().get());

// TODO! uncomment
// if (is<Complex>(lhs) || is<Complex>(rhs)) {
// return {};
// }
if (is<Complex>(lhs) || is<Complex>(rhs)) {
return {};
}

return Boolean(lhs >= rhs).clone();
}
Expand Down
Loading

0 comments on commit 92efe87

Please sign in to comment.