Skip to content

Commit

Permalink
Add Inf and Indeterminate
Browse files Browse the repository at this point in the history
  • Loading branch information
fintarin committed Jul 27, 2023
1 parent 4ca54d9 commit 19f4f41
Show file tree
Hide file tree
Showing 30 changed files with 373 additions and 66 deletions.
30 changes: 17 additions & 13 deletions include/fintamath/core/MathObjectTypes.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ enum class MathObjectType : MathObjectTypeId {
Pi,
True,
False,
Inf,
NegInf,
Indeterminate,

IFunction = 11000,

Expand Down Expand Up @@ -144,19 +147,19 @@ class MathObjectBoundTypeIds {
using Type = MathObjectType;

static std::unordered_map<Id, Id> ids{
{Id(Type::IMathObject), Id(Type::None)}, //
{Id(Type::IArithmetic), Id(Type::ILiteral)}, //
{Id(Type::IExpression), Id(Type::IComparable)}, //
{Id(Type::IUnaryExpression), Id(Type::IBinaryExpression)}, //
{Id(Type::IBinaryExpression), Id(Type::IPolynomExpression)}, //
{Id(Type::IPolynomExpression), Id(Type::IComparable)}, //
{Id(Type::IComparable), Id(Type::ILiteral)}, //
{Id(Type::INumber), Id(Type::ILiteral)}, //
{Id(Type::IInteger), Id(Type::ILiteral)}, //
{Id(Type::ILiteral), Id(Type::IFunction)}, //
{Id(Type::IConstant), Id(Type::IFunction)}, //
{Id(Type::IFunction), Id(Type::None)}, //
{Id(Type::IOperator), Id(Type::None)}, //
{Id(Type::IMathObject), Id(Type::None)},
{Id(Type::IArithmetic), Id(Type::ILiteral)},
{Id(Type::IExpression), Id(Type::IComparable)},
{Id(Type::IUnaryExpression), Id(Type::IBinaryExpression)},
{Id(Type::IBinaryExpression), Id(Type::IPolynomExpression)},
{Id(Type::IPolynomExpression), Id(Type::IComparable)},
{Id(Type::IComparable), Id(Type::ILiteral)},
{Id(Type::INumber), Id(Type::ILiteral)},
{Id(Type::IInteger), Id(Type::ILiteral)},
{Id(Type::ILiteral), Id(Type::IFunction)},
{Id(Type::IConstant), Id(Type::IFunction)},
{Id(Type::IFunction), Id(Type::None)},
{Id(Type::IOperator), Id(Type::None)},
};

return ids;
Expand All @@ -166,6 +169,7 @@ class MathObjectBoundTypeIds {
inline bool isBaseOf(size_t toTypeId, size_t fromTypeId) {
if (auto toTypeBoundaries = MathObjectBoundTypeIds::get().find(toTypeId);
toTypeBoundaries != MathObjectBoundTypeIds::get().end()) {

return fromTypeId >= toTypeBoundaries->first && fromTypeId < toTypeBoundaries->second;
}

Expand Down
22 changes: 22 additions & 0 deletions include/fintamath/literals/constants/Indeterminate.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#pragma once

#include "fintamath/literals/constants/IConstant.hpp"
#include "fintamath/numbers/INumber.hpp"

namespace fintamath {

class Indeterminate : public IConstantCRTP<INumber, Indeterminate> {
public:
std::string toString() const override {
return "Indeterminate";
}

static MathObjectTypeId getTypeIdStatic() {
return MathObjectTypeId(MathObjectType::Indeterminate);
}

protected:
std::unique_ptr<IMathObject> call() const override;
};

}
22 changes: 22 additions & 0 deletions include/fintamath/literals/constants/Inf.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#pragma once

#include "fintamath/literals/constants/IConstant.hpp"
#include "fintamath/numbers/INumber.hpp"

namespace fintamath {

class Inf : public IConstantCRTP<INumber, Inf> {
public:
std::string toString() const override {
return "Inf";
}

static MathObjectTypeId getTypeIdStatic() {
return MathObjectTypeId(MathObjectType::Inf);
}

protected:
std::unique_ptr<IMathObject> call() const override;
};

}
22 changes: 22 additions & 0 deletions include/fintamath/literals/constants/NegInf.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#pragma once

#include "fintamath/literals/constants/IConstant.hpp"
#include "fintamath/numbers/INumber.hpp"

namespace fintamath {

class NegInf : public IConstantCRTP<INumber, NegInf> {
public:
std::string toString() const override {
return "-Inf";
}

static MathObjectTypeId getTypeIdStatic() {
return MathObjectTypeId(MathObjectType::NegInf);
}

protected:
std::unique_ptr<IMathObject> call() const override;
};

}
6 changes: 6 additions & 0 deletions src/fintamath/config/ParserConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,11 @@
#include "fintamath/literals/constants/E.hpp"
#include "fintamath/literals/constants/False.hpp"
#include "fintamath/literals/constants/IConstant.hpp"
#include "fintamath/literals/constants/Inf.hpp"
#include "fintamath/literals/constants/NegInf.hpp"
#include "fintamath/literals/constants/Pi.hpp"
#include "fintamath/literals/constants/True.hpp"
#include "fintamath/literals/constants/Indeterminate.hpp"
#include "fintamath/numbers/IInteger.hpp"
#include "fintamath/numbers/INumber.hpp"
#include "fintamath/numbers/Integer.hpp"
Expand Down Expand Up @@ -165,6 +168,9 @@ struct ParserConfig {
IConstant::registerType<Pi>();
IConstant::registerType<True>();
IConstant::registerType<False>();
IConstant::registerType<Inf>();
IConstant::registerType<NegInf>();
IConstant::registerType<Indeterminate>();

IFunction::registerType<Abs>();
IFunction::registerType<Log>();
Expand Down
2 changes: 1 addition & 1 deletion src/fintamath/expressions/Expression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -459,7 +459,7 @@ void Expression::validateFunctionArgs(const std::shared_ptr<IFunction> &func, co
else if (const auto childConst = cast<IConstant>(arg)) {
const MathObjectTypeId childTypeId = childConst->getReturnTypeId();

if (!isBaseOf(typeId, childTypeId)) {
if (!isBaseOf(typeId, childTypeId) && !isBaseOf(childTypeId, typeId)) {
throw InvalidInputFunctionException(func->toString(), argumentVectorToStringVector(args));
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/fintamath/expressions/ExpressionUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
#include "fintamath/expressions/IExpression.hpp"
#include "fintamath/functions/arithmetic/Div.hpp"
#include "fintamath/functions/arithmetic/Mul.hpp"
#include "fintamath/functions/arithmetic/Neg.hpp"
#include "fintamath/functions/powers/Pow.hpp"
#include "fintamath/literals/constants/NegInf.hpp"
#include "fintamath/numbers/Rational.hpp"
#include "fintamath/numbers/Real.hpp"

Expand Down
1 change: 1 addition & 0 deletions src/fintamath/expressions/IExpression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "fintamath/functions/other/Index.hpp"
#include "fintamath/literals/Variable.hpp"
#include "fintamath/literals/constants/IConstant.hpp"
#include "fintamath/literals/constants/Indeterminate.hpp"
#include "fintamath/numbers/INumber.hpp"
#include "fintamath/numbers/Real.hpp"

Expand Down
33 changes: 23 additions & 10 deletions src/fintamath/expressions/binary/DivExpression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
#include "fintamath/functions/arithmetic/Neg.hpp"
#include "fintamath/functions/arithmetic/Sub.hpp"
#include "fintamath/functions/powers/Pow.hpp"
#include "fintamath/literals/constants/Indeterminate.hpp"
#include "fintamath/literals/constants/Inf.hpp"
#include "fintamath/literals/constants/NegInf.hpp"
#include "fintamath/numbers/IntegerFunctions.hpp"
#include "fintamath/numbers/Rational.hpp"

Expand All @@ -28,16 +31,16 @@ std::string DivExpression::toString() const {

DivExpression::SimplifyFunctionsVector DivExpression::getFunctionsForPreSimplify() const {
static const DivExpression::SimplifyFunctionsVector simplifyFunctions = {
&DivExpression::zeroSimplify, //
&DivExpression::divSimplify, //
&DivExpression::mulSimplify, //
&DivExpression::constSimplify, //
&DivExpression::divSimplify, //
&DivExpression::mulSimplify, //
};
return simplifyFunctions;
}

DivExpression::SimplifyFunctionsVector DivExpression::getFunctionsForPostSimplify() const {
static const DivExpression::SimplifyFunctionsVector simplifyFunctions = {
&DivExpression::zeroSimplify, //
&DivExpression::constSimplify, //
&DivExpression::negSimplify, //
&DivExpression::numSimplify, //
&DivExpression::divSimplify, //
Expand All @@ -49,19 +52,29 @@ DivExpression::SimplifyFunctionsVector DivExpression::getFunctionsForPostSimplif
return simplifyFunctions;
}

ArgumentPtr DivExpression::zeroSimplify(const IFunction & /*func*/, const ArgumentPtr &lhs, const ArgumentPtr &rhs) {
ArgumentPtr DivExpression::constSimplify(const IFunction & /*func*/, const ArgumentPtr &lhs, const ArgumentPtr &rhs) {
if ((*lhs == Integer(0) || is<Inf>(lhs) || is<NegInf>(lhs)) &&
(*rhs == Integer(0) || is<Inf>(rhs) || is<NegInf>(rhs))) {

return Indeterminate().clone();
}

if (*lhs == Integer(0)) {
return lhs;
}

if (*rhs == Integer(0)) {
throw UndefinedBinaryOperatorException(Div().toString(), lhs->toString(), rhs->toString());
return Inf().clone();
}

if (is<Inf>(rhs) || is<NegInf>(rhs)) {
return Integer(0).clone();
}

return {};
}

ArgumentPtr DivExpression::numSimplify(const IFunction & /*func*/, const ArgumentPtr &lhs, const ArgumentPtr &rhs) {
if (*lhs == Integer(0)) {
return lhs;
}

static const Integer one = 1;

if (Div().doArgsMatch({one, *rhs})) {
Expand Down
2 changes: 1 addition & 1 deletion src/fintamath/expressions/binary/DivExpression.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class DivExpression : public IBinaryExpressionCRTP<DivExpression> {
SimplifyFunctionsVector getFunctionsForPostSimplify() const override;

private:
static ArgumentPtr zeroSimplify(const IFunction &func, const ArgumentPtr &lhs, const ArgumentPtr &rhs);
static ArgumentPtr constSimplify(const IFunction &func, const ArgumentPtr &lhs, const ArgumentPtr &rhs);

static ArgumentPtr numSimplify(const IFunction &func, const ArgumentPtr &lhs, const ArgumentPtr &rhs);

Expand Down
64 changes: 45 additions & 19 deletions src/fintamath/expressions/binary/PowExpression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
#include "fintamath/functions/powers/Pow.hpp"
#include "fintamath/functions/powers/Root.hpp"
#include "fintamath/functions/powers/Sqrt.hpp"
#include "fintamath/literals/constants/Inf.hpp"
#include "fintamath/literals/constants/NegInf.hpp"
#include "fintamath/literals/constants/Indeterminate.hpp"
#include "fintamath/numbers/Integer.hpp"
#include "fintamath/numbers/IntegerFunctions.hpp"
#include "fintamath/numbers/Rational.hpp"
Expand Down Expand Up @@ -79,15 +82,15 @@ ArgumentPtr PowExpression::preciseSimplify() const {

PowExpression::SimplifyFunctionsVector PowExpression::getFunctionsForPreSimplify() const {
static const PowExpression::SimplifyFunctionsVector simplifyFunctions = {
&PowExpression::negSimplify, //
&PowExpression::powSimplify, //
&PowExpression::negSimplify, //
&PowExpression::powSimplify, //
};
return simplifyFunctions;
}

PowExpression::SimplifyFunctionsVector PowExpression::getFunctionsForPostSimplify() const {
static const PowExpression::SimplifyFunctionsVector simplifyFunctions = {
&PowExpression::numSimplify, //
&PowExpression::constSimplify, //
&PowExpression::polynomSimplify, //
&PowExpression::negSimplify, //
&PowExpression::powSimplify, //
Expand Down Expand Up @@ -200,32 +203,55 @@ ArgumentPtr PowExpression::powSimplify(const IFunction & /*func*/, const Argumen
return res;
}

ArgumentPtr PowExpression::numSimplify(const IFunction & /*func*/, const ArgumentPtr &lhs, const ArgumentPtr &rhs) {
auto lhsInt = cast<Integer>(lhs);
auto rhsInt = cast<Integer>(rhs);
ArgumentPtr PowExpression::constSimplify(const IFunction & /*func*/, const ArgumentPtr &lhs, const ArgumentPtr &rhs) {
if (*rhs == Integer(1)) {
return lhs;
}

if (rhsInt) {
if (*rhsInt == 0) {
return std::make_shared<Integer>(1);
}
if (*rhs == Integer(-1)) {
ArgumentPtr divLhs = Integer(1).clone();
ArgumentPtr divRhs = lhs;
return makeExpr(Div(), divLhs, divRhs);
}

if (const auto rhsComp = cast<IComparable>(rhs); is<NegInf>(rhs) || (rhsComp && *rhsComp < Integer(0))) {
ArgumentPtr divLhs = Integer(1).clone();
ArgumentPtr divRhs = makeExpr(Pow(), lhs, makeExpr(Neg(), rhs));
return makeExpr(Div(), divLhs, divRhs);
}

if (is<NegInf>(lhs)) {
ArgumentPtr mulLhs = makeExpr(Pow(), Integer(-1).clone(), rhs);
ArgumentPtr mulRhs = makeExpr(Pow(), Inf().clone(), rhs);
return makeExpr(Mul(), mulLhs, mulRhs);
}

if (*rhsInt == 1 || (lhsInt && *lhsInt == 1)) {
return lhs;
if (*lhs == Integer(0)) {
if (*rhs == Integer(0)) {
return Indeterminate().clone();
}

if (*rhsInt == -1) {
ArgumentPtr res = makeExpr(Div(), std::make_shared<Integer>(1), lhs);
return res;
return lhs;
}

if (*lhs == Integer(1)) {
if (is<Inf>(rhs)) {
return Indeterminate().clone();
}

return lhs;
}

if (lhsInt && *lhsInt == 0) {
if (is<Inf>(lhs)) {
if (*rhs == Integer(0)) {
return Indeterminate().clone();
}

return lhs;
}

if (const auto rhsComp = cast<IComparable>(rhs); rhsComp && *rhsComp < Integer(0)) {
ArgumentPtr res = makeExpr(Div(), std::make_shared<Integer>(1), makeExpr(Pow(), lhs, makeExpr(Neg(), rhs)));
return res;
if (*rhs == Integer(0)) {
return Integer(1).clone();
}

return {};
Expand Down
2 changes: 1 addition & 1 deletion src/fintamath/expressions/binary/PowExpression.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class PowExpression : public IBinaryExpressionCRTP<PowExpression> {

static ArgumentPtr powSimplify(const IFunction &func, const ArgumentPtr &lhs, const ArgumentPtr &rhs);

static ArgumentPtr numSimplify(const IFunction &func, const ArgumentPtr &lhs, const ArgumentPtr &rhs);
static ArgumentPtr constSimplify(const IFunction &func, const ArgumentPtr &lhs, const ArgumentPtr &rhs);

static ArgumentPtr polynomSimplify(const IFunction &func, const ArgumentPtr &lhs, const ArgumentPtr &rhs);

Expand Down
9 changes: 9 additions & 0 deletions src/fintamath/expressions/interfaces/IBinaryExpression.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "fintamath/expressions/interfaces/IBinaryExpression.hpp"

#include "fintamath/expressions/ExpressionUtils.hpp"
#include "fintamath/literals/constants/Indeterminate.hpp"

namespace fintamath {

Expand All @@ -25,6 +26,10 @@ ArgumentPtr IBinaryExpression::preSimplify() const {
preSimplifyChild(simpl->lhsChild);
preSimplifyChild(simpl->rhsChild);

if (is<Indeterminate>(simpl->lhsChild) || is<Indeterminate>(simpl->rhsChild)) {
return Indeterminate().clone();
}

ArgumentPtr res = simpl->useSimplifyFunctions(getFunctionsForPreSimplify());

if (res && *res != *simpl) {
Expand All @@ -40,6 +45,10 @@ ArgumentPtr IBinaryExpression::postSimplify() const {
postSimplifyChild(simpl->lhsChild);
postSimplifyChild(simpl->rhsChild);

if (is<Indeterminate>(simpl->lhsChild) || is<Indeterminate>(simpl->rhsChild)) {
return Indeterminate().clone();
}

if (ArgumentPtr res = callFunction(*simpl->func, {simpl->lhsChild, simpl->rhsChild})) {
return res;
}
Expand Down
Loading

0 comments on commit 19f4f41

Please sign in to comment.