diff --git a/.clang-tidy b/.clang-tidy index d7b77cd..a77e383 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -97,7 +97,7 @@ modernize-use-bool-literals, modernize-use-emplace, modernize-use-equals-default, modernize-use-equals-delete, -# modernize-use-nodiscard, +modernize-use-nodiscard, modernize-use-noexcept, modernize-use-nullptr, modernize-use-override, diff --git a/.github/workflows/cmake-ubuntu.yml b/.github/workflows/cmake-ubuntu.yml index b2337ef..9c2122d 100644 --- a/.github/workflows/cmake-ubuntu.yml +++ b/.github/workflows/cmake-ubuntu.yml @@ -20,8 +20,8 @@ jobs: steps: - uses: actions/checkout@v3 - - name: Install dependencies - run: | + - name: Install Dependencies + run: | sudo apt-get update sudo apt-get install -y openssl libssl-dev libx11-dev xorg-dev diff --git a/.gitignore b/.gitignore index 9adfa9e..db088bc 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ _deps cmake-build-*/ build-*/ +builds/ *_include.cmake bin/ diff --git a/CMakeLists.txt b/CMakeLists.txt index f186668..91971e1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ project(ComputerAlgebraSystem LANGUAGES CXX) set(CMAKE_CXX_STANDARD 20) -set(CMAKE_CXX_EXTENSIONS OFF) +set(CMAKE_CXX_EXTENSIONS OFF) # Don't use compiler extensions so we have a portable codebase. set(CMAKE_CXX_STANDARD_REQUIRED ON) set_property(GLOBAL PROPERTY USE_FOLDERS ON) @@ -19,6 +19,7 @@ if (CMAKE_BUILD_TYPE MATCHES Debug) endif() # Enable ASAN and UBSAN + # TODO: Fix sanitizers for Windows and Linux if (MSVC) add_compile_options(/fsanitize=address,undefined) add_link_options(/fsanitize=address,undefined) diff --git a/build.bat b/build.bat index 9b6b95f..db09cc7 100644 --- a/build.bat +++ b/build.bat @@ -17,10 +17,10 @@ IF "%#%" "-eq" "0" ( ) IF "%build_debug%" "-eq" "1" ( - cmake "-DCMAKE_BUILD_TYPE=Debug" "-S" "." "-B" "build-debug" - cmake "--build" "build-debug" + cmake "-DCMAKE_BUILD_TYPE=Debug" "-S" "." "-B" "builds/debug" + cmake "--build" "builds/debug" ) IF "%build_release%" "-eq" "1" ( - cmake "-DCMAKE_BUILD_TYPE=Release" "-S" "." "-B" "build-release" - cmake "--build" "build-release" + cmake "-DCMAKE_BUILD_TYPE=Release" "-S" "." "-B" "builds/release" + cmake "--build" "builds/release" ) \ No newline at end of file diff --git a/build.sh b/build.sh index 47da317..50779aa 100755 --- a/build.sh +++ b/build.sh @@ -28,12 +28,12 @@ fi # Build the debug version if specified if [ $build_debug -eq 1 ]; then - cmake -DCMAKE_BUILD_TYPE=Debug -S . -B build-debug - cmake --build build-debug + cmake -DCMAKE_BUILD_TYPE=Debug -S . -B builds/debug + cmake --build builds/debug fi # Build the release version if specified if [ $build_release -eq 1 ]; then - cmake -DCMAKE_BUILD_TYPE=Release -S . -B build-release - cmake --build build-release + cmake -DCMAKE_BUILD_TYPE=Release -S . -B builds/release + cmake --build builds/release fi \ No newline at end of file diff --git a/cas/include/cas/data/ExpressionParser.h b/cas/include/cas/data/ExpressionParser.h index cea4f64..26e4ceb 100644 --- a/cas/include/cas/data/ExpressionParser.h +++ b/cas/include/cas/data/ExpressionParser.h @@ -13,7 +13,7 @@ CAS_NAMESPACE class ExpressionParser { public: static ExpressionParser& getInstance(); - Expression* parse(const std::string& expression, VarSet& variables); + ExprPtr parse(const std::string& expression, VarSet& variables); void setup(std::string& expr); bool isValidExpression(const std::string& expr); diff --git a/cas/include/cas/data/ExpressionProperties.h b/cas/include/cas/data/ExpressionProperties.h deleted file mode 100644 index 2cef42b..0000000 --- a/cas/include/cas/data/ExpressionProperties.h +++ /dev/null @@ -1,33 +0,0 @@ -// -// Created by Abd-El-Aziz Zayed on 2022-08-31. -// - -#ifndef CAS_EXPRESSIONPROPERTIES_H -#define CAS_EXPRESSIONPROPERTIES_H - -#include "ExpressionType.h" -#include - -CAS_NAMESPACE - -class ExpressionProperties { -public: - ExpressionProperties(ExpressionType type, std::string name, std::string shortName); - - bool operator==(const ExpressionProperties& other) const; - - uint16_t getOrder() const; - ExpressionType getType() const; - std::string getName() const; - std::string getShortName() const; - -private: - const uint16_t order; - const ExpressionType type; - const std::string name; - const std::string shortName; -}; - -CAS_NAMESPACE_END - -#endif//CAS_EXPRESSIONPROPERTIES_H diff --git a/cas/include/cas/data/VariableMap.h b/cas/include/cas/data/VariableMap.h index 0f51f8f..f06ac6b 100644 --- a/cas/include/cas/data/VariableMap.h +++ b/cas/include/cas/data/VariableMap.h @@ -12,6 +12,8 @@ CAS_NAMESPACE +// TODO redesign to store std::pairs so iterators can be references + struct LetterMap { static const char LETTER_COUNT = 26; char letters = 0; diff --git a/cas/include/cas/latex/LatexRenderer.h b/cas/include/cas/latex/LatexRenderer.h index a3c74cf..1089909 100644 --- a/cas/include/cas/latex/LatexRenderer.h +++ b/cas/include/cas/latex/LatexRenderer.h @@ -26,7 +26,7 @@ class LatexRenderer { private: const std::string prefix = "lr_"; - const std::string resFolder = "../res/latex"; + const std::string resFolder = "../../res/latex"; }; CAS_NAMESPACE_END diff --git a/cas/include/cas/node/Abs.h b/cas/include/cas/node/Abs.h index ddae4d7..45ad325 100644 --- a/cas/include/cas/node/Abs.h +++ b/cas/include/cas/node/Abs.h @@ -11,7 +11,7 @@ CAS_NAMESPACE class Abs : public BracketExpression { public: - explicit Abs(Expression* argument); + explicit Abs(const ExprPtr& argument); Abs() = delete; @@ -19,11 +19,15 @@ class Abs : public BracketExpression { double evaluate(const VariableMap& variables) override; - Abs* clone() override; + ExprPtr clone() override; - Expression* simplified() override; + ExprPtr simplified() override; std::string text() override; + + static ExprPtr from(const ExprPtr& argument) { + return std::make_shared(argument); + } }; CAS_NAMESPACE_END diff --git a/cas/include/cas/node/BracketExpression.h b/cas/include/cas/node/BracketExpression.h index 9f0296a..31bf23d 100644 --- a/cas/include/cas/node/BracketExpression.h +++ b/cas/include/cas/node/BracketExpression.h @@ -15,9 +15,9 @@ class BracketExpression : public UnaryExpression { ~BracketExpression() override = default; - bool _equals(Expression* other) override; + bool _equals(const ExprPtr& other) override; - Expression* derivative(char var) override; + ExprPtr derivative(char var) override; std::string latex() override; @@ -28,7 +28,7 @@ class BracketExpression : public UnaryExpression { std::string explicitText() override; protected: - explicit BracketExpression(const ExpressionProperties& properties, Expression* argument, + explicit BracketExpression(const ExpressionProperties& properties, const ExprPtr& argument, const wchar_t* openBracket, const wchar_t* closeBracket, const char* openBracketLatex, const char* closeBracketLatex); diff --git a/cas/include/cas/node/Cbrt.h b/cas/include/cas/node/Cbrt.h index 4d7c578..428edb1 100644 --- a/cas/include/cas/node/Cbrt.h +++ b/cas/include/cas/node/Cbrt.h @@ -11,19 +11,21 @@ CAS_NAMESPACE class Cbrt : public Root { public: - explicit Cbrt(Expression* base); + explicit Cbrt(const ExprPtr& base); Cbrt() = delete; ~Cbrt() override = default; double evaluate(const VariableMap& variables) override; - Cbrt* clone() override; - Expression* _derivative(char variable) override; - Expression* simplified() override; + ExprPtr clone() override; + ExprPtr _derivative(char variable) override; + ExprPtr simplified() override; std::string latex() override; std::wstring stringify() override; std::string text() override; std::string explicitText() override; + + static CbrtPtr from(const ExprPtr& base) { return std::make_shared(base); } }; CAS_NAMESPACE_END diff --git a/cas/include/cas/node/Ceil.h b/cas/include/cas/node/Ceil.h index df77d48..373b1bc 100644 --- a/cas/include/cas/node/Ceil.h +++ b/cas/include/cas/node/Ceil.h @@ -11,7 +11,7 @@ CAS_NAMESPACE class Ceil : public BracketExpression { public: - explicit Ceil(Expression* argument); + explicit Ceil(const ExprPtr& argument); Ceil() = delete; @@ -19,9 +19,13 @@ class Ceil : public BracketExpression { double evaluate(const VariableMap& variables) override; - Ceil* clone() override; + ExprPtr clone() override; - Expression* simplified() override; + ExprPtr simplified() override; + + static ExprPtr from(const ExprPtr& argument) { + return std::make_shared(argument); + } }; CAS_NAMESPACE_END diff --git a/cas/include/cas/node/Const.h b/cas/include/cas/node/Const.h index a401663..dba04af 100644 --- a/cas/include/cas/node/Const.h +++ b/cas/include/cas/node/Const.h @@ -1,6 +1,7 @@ // // Created by Abd-El-Aziz Zayed on 2022-08-26. // + #ifndef CAS_CONSTANT_H #define CAS_CONSTANT_H @@ -9,23 +10,21 @@ CAS_NAMESPACE -class Const : public Expression { +class Const : public Expr { public: explicit Const(double value); - - explicit Const() : Const(0.0){}; - + Const() = delete; ~Const() override = default; double evaluate(const VariableMap& variables) override; - bool _equals(Expression* expression) override; + bool _equals(const ExprPtr& expression) override; - Const* clone() override; + ExprPtr clone() override; - Const* _derivative(char var) override; + ExprPtr _derivative(char var) override; - Const* simplified() override; + ExprPtr simplified() override; std::string latex() override; @@ -35,17 +34,18 @@ class Const : public Expression { double getValue() const { return value; } - static Const* PI() { return new Const{math::PI}; } + static ConstPtr PI() { return n(math::PI); } - static Const* E() { return new Const{math::E}; } + static ConstPtr E() { return n(math::E); } - static Const* PHI() { return new Const{math::PHI}; } + static ConstPtr PHI() { return n(math::PHI); } - static Const* zero() { return new Const; } + static ConstPtr zero() { return n(0.0); } - static Const* one() { return new Const{1.0}; } + static ConstPtr one() { return n(1.0); } - static Const* n(double value) { return new Const{value}; } + static ConstPtr n(double value) { return std::make_shared(value); } + static ConstPtr from(double value) { return n(value); } static bool floatingsEqual(double a, double b) { double max = std::max(1.0, std::max(std::fabs(a), std::fabs(b))); diff --git a/cas/include/cas/node/Divide.h b/cas/include/cas/node/Divide.h index 1b5231f..8f19102 100644 --- a/cas/include/cas/node/Divide.h +++ b/cas/include/cas/node/Divide.h @@ -10,23 +10,22 @@ CAS_NAMESPACE -class Divide : public Expression { +class Divide : public Expr { public: - explicit Divide(Expression* dividend, Expression* divisor); - Divide() = delete; + explicit Divide(const ExprPtr& dividend, const ExprPtr& divisor); - ~Divide() override; + ~Divide() override = default; double evaluate(const VariableMap& variables) override; - bool _equals(Expression* expression) override; + bool _equals(const ExprPtr& expression) override; - Divide* clone() override; + ExprPtr clone() override; - Divide* _derivative(char var) override; + ExprPtr _derivative(char var) override; - Expression* simplified() override; + ExprPtr simplified() override; std::string latex() override; @@ -36,12 +35,14 @@ class Divide : public Expression { std::string explicitText() override; - Expression* getDividend() const { return dividend; } - Expression* getDivisor() const { return divisor; } + static DividePtr from(const ExprPtr& dividend, const ExprPtr& divisor) { return std::make_shared(dividend, divisor); } + + ExprPtr getDividend() const { return dividend; } + ExprPtr getDivisor() const { return divisor; } private: - Expression* dividend; - Expression* divisor; + ExprPtr dividend; + ExprPtr divisor; }; CAS_NAMESPACE_END diff --git a/cas/include/cas/node/Exp.h b/cas/include/cas/node/Exp.h index 96e9e9a..20eef79 100644 --- a/cas/include/cas/node/Exp.h +++ b/cas/include/cas/node/Exp.h @@ -11,7 +11,7 @@ CAS_NAMESPACE class Exp : public Power { public: - explicit Exp(Expression* exponent); + explicit Exp(const ExprPtr& exponent); Exp() = delete; @@ -19,13 +19,15 @@ class Exp : public Power { double evaluate(const VariableMap& variables) override; - Exp* clone() override; + ExprPtr clone() override; - Expression* _derivative(char var) override; + ExprPtr _derivative(char var) override; - Expression* simplified() override; + ExprPtr simplified() override; std::string explicitText() override; + + static ExpPtr from(const ExprPtr& exponent) { return std::make_shared(exponent); } }; CAS_NAMESPACE_END diff --git a/cas/include/cas/node/Expression.h b/cas/include/cas/node/Expression.h index 448c2fd..19db750 100644 --- a/cas/include/cas/node/Expression.h +++ b/cas/include/cas/node/Expression.h @@ -7,12 +7,31 @@ #include "IMath.h" #include "IRepresentableMath.h" -#include "cas/data/ExpressionProperties.h" #include "cas/data/ExpressionType.h" +#include CAS_NAMESPACE -class Product; +struct ExpressionProperties { +public: + ExpressionProperties(ExpressionType type, std::string name, std::string shortName) + : order(static_cast(type)), type(type), name(std::move(name)), shortName(std::move(shortName)) {} + + uint16_t order; + ExpressionType type; + std::string name; + std::string shortName; + + uint16_t getOrder() const { return order; } + ExpressionType getType() const { return type; } + std::string getName() const { return name; } + std::string getShortName() const { return shortName; } +}; + +class Const; +class Var; + +class Prod; class Sum; class Divide; class Negate; @@ -46,89 +65,129 @@ class Round; class Sign; class Mod; -class Expression : public IMath, public IRepresentableMath { +class Min; +class Max; + +class Expr; + +using ExprPtr = std::shared_ptr; +using ConstPtr = std::shared_ptr; +using VarPtr = std::shared_ptr; +using ProdPtr = std::shared_ptr; +using SumPtr = std::shared_ptr; +using DividePtr = std::shared_ptr; +using NegatePtr = std::shared_ptr; +using PowerPtr = std::shared_ptr; +using ExpPtr = std::shared_ptr; +using LogPtr = std::shared_ptr; +using LnPtr = std::shared_ptr; +using RootPtr = std::shared_ptr; +using SqrtPtr = std::shared_ptr; +using CbrtPtr = std::shared_ptr; +using SinPtr = std::shared_ptr; +using CosPtr = std::shared_ptr; +using TanPtr = std::shared_ptr; +using CotPtr = std::shared_ptr; +using CscPtr = std::shared_ptr; +using SecPtr = std::shared_ptr; +using ArcSinPtr = std::shared_ptr; +using ArcCosPtr = std::shared_ptr; +using ArcTanPtr = std::shared_ptr; +using ArcCotPtr = std::shared_ptr; +using ArcCscPtr = std::shared_ptr; +using ArcSecPtr = std::shared_ptr; +using AbsPtr = std::shared_ptr; +using FloorPtr = std::shared_ptr; +using CeilPtr = std::shared_ptr; +using RoundPtr = std::shared_ptr; +using SignPtr = std::shared_ptr; +using ModPtr = std::shared_ptr; +using MinPtr = std::shared_ptr; +using MaxPtr = std::shared_ptr; + +class Expr : public IMath, public IRepresentableMath, public std::enable_shared_from_this { public: - explicit Expression(const ExpressionProperties& properties); + explicit Expr(const ExpressionProperties& properties); - virtual ~Expression() = default; + virtual ~Expr() = default; - Expression(const Expression& expression) = delete; + Expr(const Expr& expression) = delete; double evaluate(const VariableMap& variables) override; virtual double evaluate(); - virtual bool equals(Expression* expression); - virtual bool _equals(Expression* expression); - - virtual Expression* clone(); - - Expression* derivative(char var) override; - virtual Expression* _derivative(char var); - - Expression* simplified() override; - bool isEquivalent(IMath* expression) override; - - Product* multiply(Expression* expression); - Product* multiply(double value); - Sum* add(Expression* expression); - Sum* subtract(Expression* expression); - Sum* add(double value); - Sum* subtract(double value); - Divide* divide(Expression* expression); - Divide* divide(double divisor); - Negate* negate(); - - Power* power(Expression* expression); - Power* power(double exponent); - Exp* exp(); - Log* log(Expression* base); - Log* log(double base); - Ln* ln(); - - Root* root(Expression* root); - Root* root(double root); - Sqrt* sqrt(); - Cbrt* cbrt(); - - Cos* cos(); - Sin* sin(); - Tan* tan(); - ArcTan* atan(); - ArcCos* acos(); - ArcSin* asin(); - Csc* csc(); - Sec* sec(); - Cot* cot(); - ArcCsc* acsc(); - ArcSec* asec(); - ArcCot* acot(); - - Abs* abs(); - Floor* floor(); - Ceil* ceil(); - Round* round(); - Sign* sign(); - Mod* mod(Expression* expression); - - Expression* reciprocal(); - - bool operator<(const Expression& expression) const; - - bool lessThan(Expression* expression) const; - - static bool compare(Expression* left, Expression* right); + virtual bool equals(const ExprPtr& expression); + virtual bool _equals(const ExprPtr& expression); + + virtual ExprPtr clone(); + + ExprPtr derivative(char var) override; + virtual ExprPtr _derivative(char var); + + ExprPtr simplified() override; + bool isEquivalent(const ExprPtr& expression) override; + + ProdPtr multiply(const ExprPtr& expression); + ProdPtr multiply(double value); + SumPtr add(const ExprPtr& expression); + SumPtr subtract(const ExprPtr& expression); + SumPtr add(double value); + SumPtr subtract(double value); + DividePtr divide(const ExprPtr& expression); + DividePtr divide(double divisor); + NegatePtr negate(); + + PowerPtr power(const ExprPtr& expression); + PowerPtr power(double exponent); + ExpPtr exp(); + LogPtr log(const ExprPtr& base); + LogPtr log(double base); + LnPtr ln(); + + RootPtr root(const ExprPtr& root); + RootPtr root(double root); + SqrtPtr sqrt(); + CbrtPtr cbrt(); + + CosPtr cos(); + SinPtr sin(); + TanPtr tan(); + ArcTanPtr atan(); + ArcCosPtr acos(); + ArcSinPtr asin(); + CscPtr csc(); + SecPtr sec(); + CotPtr cot(); + ArcCscPtr acsc(); + ArcSecPtr asec(); + ArcCotPtr acot(); + + AbsPtr abs(); + FloorPtr floor(); + CeilPtr ceil(); + RoundPtr round(); + SignPtr sign(); + ModPtr mod(const ExprPtr& expression); + + ExprPtr reciprocal(); + + bool operator<(const Expr& expression) const; + + bool lessThan(const ExprPtr& expression) const; + + static bool compare(const ExprPtr& left, const ExprPtr& right); ExpressionProperties getProperties() const; - Expression* getParent() const; + Expr* getParent() const; - void setParent(Expression* newParent); + void setParent(Expr* newParent); bool isNegated() const; bool isOfType(ExpressionType type) const; - bool isOfSameType(Expression* expression) const; + bool isOfSameType(const ExprPtr& expression) const; // TODO overload math operators + - * / ^ @@ -136,12 +195,9 @@ class Expression : public IMath, public IRepresentableMath { protected: const ExpressionProperties properties; - Expression* parent = nullptr; + Expr* parent = nullptr; }; -using ExpressionPtr = Expression*; -using ExprPtr = Expression*; - CAS_NAMESPACE_END #endif//CAS_EXPRESSION_H diff --git a/cas/include/cas/node/Floor.h b/cas/include/cas/node/Floor.h index 4eb6601..5368c0c 100644 --- a/cas/include/cas/node/Floor.h +++ b/cas/include/cas/node/Floor.h @@ -11,7 +11,7 @@ CAS_NAMESPACE class Floor : public BracketExpression { public: - explicit Floor(Expression* argument); + explicit Floor(const ExprPtr& argument); Floor() = delete; @@ -19,9 +19,11 @@ class Floor : public BracketExpression { double evaluate(const VariableMap& variables) override; - Floor* clone() override; + ExprPtr clone() override; - Expression* simplified() override; + ExprPtr simplified() override; + + static FloorPtr from(const ExprPtr& argument) { return std::make_shared(argument); } }; CAS_NAMESPACE_END diff --git a/cas/include/cas/node/IMath.h b/cas/include/cas/node/IMath.h index 7ef936a..19c8a97 100644 --- a/cas/include/cas/node/IMath.h +++ b/cas/include/cas/node/IMath.h @@ -5,18 +5,19 @@ #ifndef CAS_IMATH_H #define CAS_IMATH_H -#include #include "cas/CAS.h" #include "cas/data/VariableMap.h" +#include CAS_NAMESPACE +template class IMath { public: virtual double evaluate(const VariableMap& variables) = 0; - virtual IMath* derivative(char var) = 0; - virtual IMath* simplified() = 0; - virtual bool isEquivalent(IMath* expr) = 0; + virtual E derivative(char var) = 0; + virtual E simplified() = 0; + virtual bool isEquivalent(const E& expr) = 0; }; namespace math { diff --git a/cas/include/cas/node/IRepresentableMath.h b/cas/include/cas/node/IRepresentableMath.h index 0530f00..94dd313 100644 --- a/cas/include/cas/node/IRepresentableMath.h +++ b/cas/include/cas/node/IRepresentableMath.h @@ -2,8 +2,8 @@ // Created by Abd-El-Aziz Zayed on 2022-08-27. // -#ifndef CAS_I_REPRESENTABLE_MATH__H -#define CAS_I_REPRESENTABLE_MATH__H +#ifndef CAS_INTERFACE_REPRESENTABLE_MATH_H +#define CAS_INTERFACE_REPRESENTABLE_MATH_H #include "cas/CAS.h" #include @@ -20,4 +20,4 @@ class IRepresentableMath { CAS_NAMESPACE_END -#endif//CAS_I_REPRESENTABLE_MATH__H +#endif//CAS_INTERFACE_REPRESENTABLE_MATH_H diff --git a/cas/include/cas/node/Ln.h b/cas/include/cas/node/Ln.h index 2fa32e1..8914573 100644 --- a/cas/include/cas/node/Ln.h +++ b/cas/include/cas/node/Ln.h @@ -11,7 +11,7 @@ CAS_NAMESPACE class Ln : public Log { public: - explicit Ln(Expression* argument); + explicit Ln(const ExprPtr& argument); Ln() = delete; @@ -19,13 +19,13 @@ class Ln : public Log { double evaluate(const VariableMap& variables) override; - bool _equals(Expression* expression) override; + bool _equals(const ExprPtr& expression) override; - Ln* clone() override; + ExprPtr clone() override; - Expression* _derivative(char var) override; + ExprPtr _derivative(char var) override; - Expression* simplified() override; + ExprPtr simplified() override; std::string latex() override; @@ -34,6 +34,8 @@ class Ln : public Log { std::string text() override; std::string explicitText() override; + + static LnPtr from(const ExprPtr& argument) { return std::make_shared(argument); } }; CAS_NAMESPACE_END diff --git a/cas/include/cas/node/Log.h b/cas/include/cas/node/Log.h index baa3197..b6635aa 100644 --- a/cas/include/cas/node/Log.h +++ b/cas/include/cas/node/Log.h @@ -9,27 +9,27 @@ CAS_NAMESPACE -class Log : public Expression { +class Log : public Expr { public: - explicit Log(Expression* base, Expression* argument); + explicit Log(const ExprPtr& base, const ExprPtr& argument); - explicit Log(double base, Expression* argument); + explicit Log(double base, const ExprPtr& argument); - explicit Log(Expression* argument); + explicit Log(const ExprPtr& argument); Log() = delete; - ~Log() override; + ~Log() override = default; double evaluate(const VariableMap& variables) override; - bool _equals(Expression* expression) override; + bool _equals(const ExprPtr& expression) override; - Log* clone() override; + ExprPtr clone() override; - Expression* _derivative(char var) override; + ExprPtr _derivative(char var) override; - Expression* simplified() override; + ExprPtr simplified() override; std::string latex() override; @@ -39,18 +39,22 @@ class Log : public Expression { std::string explicitText() override; - Expression* getBase() const { return base; } + ExprPtr getBase() const { return base; } - Expression* getArgument() const { return argument; } + ExprPtr getArgument() const { return argument; } + + static LogPtr from(const ExprPtr& base, const ExprPtr& argument) { return std::make_shared(base, argument); } + static LogPtr from(double base, const ExprPtr& argument) { return std::make_shared(base, argument); } + static LogPtr from(const ExprPtr& argument) { return std::make_shared(argument); } protected: - explicit Log(const ExpressionProperties& props, Expression* base, Expression* argument); + explicit Log(const ExpressionProperties& props, const ExprPtr& base, const ExprPtr& argument); bool argumentNeedsParentheses(); protected: - Expression* base; - Expression* argument; + ExprPtr base; + ExprPtr argument; }; CAS_NAMESPACE_END diff --git a/cas/include/cas/node/Max.h b/cas/include/cas/node/Max.h index 16822e4..9fb0efb 100644 --- a/cas/include/cas/node/Max.h +++ b/cas/include/cas/node/Max.h @@ -11,7 +11,7 @@ CAS_NAMESPACE class Max : public NaryExpression { public: - explicit Max(std::vector expressions); + explicit Max(std::vector expressions); Max() = delete; @@ -19,9 +19,11 @@ class Max : public NaryExpression { double evaluate(const VariableMap& variables) override; - Max* clone() override; + ExprPtr clone() override; - Expression* simplified() override; + ExprPtr simplified() override; + + static MaxPtr from(const std::vector& expressions) { return std::make_shared(expressions); } }; CAS_NAMESPACE_END diff --git a/cas/include/cas/node/Min.h b/cas/include/cas/node/Min.h index 8c038e0..2830a2d 100644 --- a/cas/include/cas/node/Min.h +++ b/cas/include/cas/node/Min.h @@ -11,7 +11,7 @@ CAS_NAMESPACE class Min : public NaryExpression { public: - explicit Min(std::vector expressions); + explicit Min(std::vector expressions); Min() = delete; @@ -19,9 +19,11 @@ class Min : public NaryExpression { double evaluate(const VariableMap& variables) override; - Min* clone() override; + ExprPtr clone() override; - Expression* simplified() override; + ExprPtr simplified() override; + + static MinPtr from(const std::vector& expressions) { return std::make_shared(expressions); } }; CAS_NAMESPACE_END diff --git a/cas/include/cas/node/Mod.h b/cas/include/cas/node/Mod.h index 2ecc070..6ff63cc 100644 --- a/cas/include/cas/node/Mod.h +++ b/cas/include/cas/node/Mod.h @@ -9,28 +9,30 @@ CAS_NAMESPACE -class Mod : public Expression { +class Mod : public Expr { public: - explicit Mod(Expression* dividend, Expression* divisor); + explicit Mod(const ExprPtr& dividend, const ExprPtr& divisor); Mod() = delete; - ~Mod() override; + ~Mod() override = default; double evaluate(const VariableMap& variables) override; - bool _equals(Expression* expression) override; - Mod* clone() override; - Expression* simplified() override; + bool _equals(const ExprPtr& expression) override; + ExprPtr clone() override; + ExprPtr simplified() override; std::string latex() override; std::wstring stringify() override; std::string text() override; std::string explicitText() override; - Expression* getDividend() const { return dividend; } - Expression* getDivisor() const { return divisor; } + ExprPtr getDividend() const { return dividend; } + ExprPtr getDivisor() const { return divisor; } + + static ModPtr from(const ExprPtr& dividend, const ExprPtr& divisor) { return std::make_shared(dividend, divisor); } private: - Expression* dividend; - Expression* divisor; + ExprPtr dividend; + ExprPtr divisor; }; CAS_NAMESPACE_END diff --git a/cas/include/cas/node/NaryExpression.h b/cas/include/cas/node/NaryExpression.h index fa0f301..13213ad 100644 --- a/cas/include/cas/node/NaryExpression.h +++ b/cas/include/cas/node/NaryExpression.h @@ -10,13 +10,13 @@ CAS_NAMESPACE -class NaryExpression : public Expression { +class NaryExpression : public Expr { public: NaryExpression() = delete; - ~NaryExpression() override; + ~NaryExpression() override = default; - bool _equals(Expression* expression) override; + bool _equals(const ExprPtr& expression) override; std::string latex() override; @@ -26,7 +26,7 @@ class NaryExpression : public Expression { std::string explicitText() override; - std::vector getExpressions() const { return {expressions}; } + std::vector getExpressions() const { return {expressions}; } template bool all(F&& f) const; @@ -38,10 +38,10 @@ class NaryExpression : public Expression { void forEach(F&& f) const; protected: - explicit NaryExpression(const ExpressionProperties& props, std::vector expressions); + explicit NaryExpression(const ExpressionProperties& props, std::vector expressions); protected: - std::vector expressions; + std::vector expressions; }; CAS_NAMESPACE_END diff --git a/cas/include/cas/node/Negate.h b/cas/include/cas/node/Negate.h index f39b2b8..b198f8f 100644 --- a/cas/include/cas/node/Negate.h +++ b/cas/include/cas/node/Negate.h @@ -11,7 +11,7 @@ CAS_NAMESPACE class Negate : public UnaryExpression { public: - explicit Negate(Expression* expression); + explicit Negate(const ExprPtr& expression); Negate() = delete; @@ -19,13 +19,13 @@ class Negate : public UnaryExpression { double evaluate(const VariableMap& variables) override; - bool _equals(Expression* expression) override; + bool _equals(const ExprPtr& expression) override; - Negate* clone() override; + ExprPtr clone() override; - Negate* _derivative(char var) override; + ExprPtr _derivative(char var) override; - Expression* simplified() override; + ExprPtr simplified() override; std::string latex() override; @@ -35,6 +35,8 @@ class Negate : public UnaryExpression { std::string explicitText() override; + static NegatePtr from(const ExprPtr& expression) { return std::make_shared(expression); } + protected: bool needsParentheses(); }; diff --git a/cas/include/cas/node/Operator.h b/cas/include/cas/node/Operator.h index 85e85ef..d75a366 100644 --- a/cas/include/cas/node/Operator.h +++ b/cas/include/cas/node/Operator.h @@ -10,17 +10,17 @@ CAS_NAMESPACE -class Operator : public Expression { +class Operator : public Expr { public: - explicit Operator(const ExpressionProperties& props, double neutral, char symbol, std::vector expressions); + explicit Operator(const ExpressionProperties& props, double neutral, char symbol, std::vector expressions); Operator() = delete; - ~Operator() override; + ~Operator() override = default; double evaluate(const VariableMap& variables) override; - bool _equals(Expression* expression) override; + bool _equals(const ExprPtr& expression) override; std::string text() override; @@ -28,18 +28,18 @@ class Operator : public Expression { char getSymbol() const { return symbol; } - std::vector getExpressions() const { return {expressions}; } + std::vector getExpressions() const { return {expressions}; } size_t getExpressionsSize() const { return expressions.size(); } protected: virtual double operate(double a, double b) = 0; - virtual bool needsParentheses(Expression* expression) = 0; + virtual bool needsParentheses(const ExprPtr& expression) = 0; protected: const double neutral; const char symbol; - std::vector expressions; + std::vector expressions; }; CAS_NAMESPACE_END diff --git a/cas/include/cas/node/Power.h b/cas/include/cas/node/Power.h index 3a766ee..f92ff18 100644 --- a/cas/include/cas/node/Power.h +++ b/cas/include/cas/node/Power.h @@ -9,25 +9,25 @@ CAS_NAMESPACE -class Power : public Expression { +class Power : public Expr { public: - explicit Power(Expression* base, Expression* exponent); + explicit Power(const ExprPtr& base, const ExprPtr& exponent); - explicit Power(Expression* base, double exponent); + explicit Power(const ExprPtr& base, double exponent); Power() = delete; - ~Power() override; + ~Power() override = default; double evaluate(const VariableMap& variables) override; - bool _equals(Expression* expression) override; + bool _equals(const ExprPtr& expression) override; - Power* clone() override; + ExprPtr clone() override; - Expression* _derivative(char var) override; + ExprPtr _derivative(char var) override; - Expression* simplified() override; + ExprPtr simplified() override; std::string latex() override; @@ -37,20 +37,22 @@ class Power : public Expression { std::string explicitText() override; - Expression* getBase() const { return base; } + ExprPtr getBase() const { return base; } - Expression* getExponent() const { return exponent; } + ExprPtr getExponent() const { return exponent; } + + static PowerPtr from(const ExprPtr& base, const ExprPtr& exponent) { return std::make_shared(base, exponent); } protected: - explicit Power(const ExpressionProperties& props, Expression* base, Expression* exponent); + explicit Power(const ExpressionProperties& props, const ExprPtr& base, const ExprPtr& exponent); bool baseNeedsParentheses(); bool exponentNeedsParentheses(); protected: - Expression* base; - Expression* exponent; + ExprPtr base; + ExprPtr exponent; }; CAS_NAMESPACE_END diff --git a/cas/include/cas/node/Prod.h b/cas/include/cas/node/Prod.h new file mode 100644 index 0000000..8e8633a --- /dev/null +++ b/cas/include/cas/node/Prod.h @@ -0,0 +1,40 @@ +// +// Created by Abd-El-Aziz Zayed on 2022-09-01. +// + +#ifndef CAS_PRODUCT_H +#define CAS_PRODUCT_H + +#include "Operator.h" + +CAS_NAMESPACE + +class Prod : public Operator { +public: + explicit Prod(const std::vector& expressions); + + Prod() = delete; + + ~Prod() override = default; + + ExprPtr clone() override; + + ExprPtr _derivative(char var) override; + + ExprPtr simplified() override; + + std::string latex() override; + + std::wstring stringify() override; + + static ProdPtr from(const std::vector& expressions) { return std::make_shared(expressions); } + +protected: + double operate(double a, double b) override { return a * b; }; + + bool needsParentheses(const ExprPtr& expression) override; +}; + +CAS_NAMESPACE_END + +#endif//CAS_PRODUCT_H diff --git a/cas/include/cas/node/Product.h b/cas/include/cas/node/Product.h deleted file mode 100644 index 0ac46f9..0000000 --- a/cas/include/cas/node/Product.h +++ /dev/null @@ -1,38 +0,0 @@ -// -// Created by Abd-El-Aziz Zayed on 2022-09-01. -// - -#ifndef CAS_PRODUCT_H -#define CAS_PRODUCT_H - -#include "Operator.h" - -CAS_NAMESPACE - -class Product : public Operator { -public: - explicit Product(const std::vector& expressions); - - Product() = delete; - - ~Product() override = default; - - Product* clone() override; - - Expression* _derivative(char var) override; - - Expression* simplified() override; - - std::string latex() override; - - std::wstring stringify() override; - -protected: - double operate(double a, double b) override { return a * b; }; - - bool needsParentheses(Expression* expression) override; -}; - -CAS_NAMESPACE_END - -#endif//CAS_PRODUCT_H diff --git a/cas/include/cas/node/Root.h b/cas/include/cas/node/Root.h index 46153b3..9503a3a 100644 --- a/cas/include/cas/node/Root.h +++ b/cas/include/cas/node/Root.h @@ -11,22 +11,25 @@ CAS_NAMESPACE class Root : public Power { public: - explicit Root(const ExpressionProperties& props, Expression* base, Expression* root); - explicit Root(Expression* base, Expression* root); - explicit Root(Expression* base, double root); + explicit Root(const ExpressionProperties& props, const ExprPtr& base, const ExprPtr& root); + explicit Root(const ExprPtr& base, const ExprPtr& root); + explicit Root(const ExprPtr& base, double root); Root() = delete; ~Root() override = default; double evaluate(const VariableMap& variables) override; - Root* clone() override; - Expression* simplified() override; + ExprPtr clone() override; + ExprPtr simplified() override; std::string latex() override; std::wstring stringify() override; std::string text() override; - Expression* getRoot() const { return getExponent(); } + ExprPtr getRoot() const { return getExponent(); } + + static RootPtr from(const ExprPtr& base, const ExprPtr& root) { return std::make_shared(base, root); } + static RootPtr from(const ExprPtr& base, double root) { return std::make_shared(base, root); } }; CAS_NAMESPACE_END diff --git a/cas/include/cas/node/Round.h b/cas/include/cas/node/Round.h index f624b94..87d911e 100644 --- a/cas/include/cas/node/Round.h +++ b/cas/include/cas/node/Round.h @@ -11,7 +11,7 @@ CAS_NAMESPACE class Round : public BracketExpression { public: - explicit Round(Expression* argument); + explicit Round(const ExprPtr& argument); Round() = delete; @@ -19,9 +19,11 @@ class Round : public BracketExpression { double evaluate(const VariableMap& variables) override; - Round* clone() override; + ExprPtr clone() override; - Expression* simplified() override; + ExprPtr simplified() override; + + static RoundPtr from(const ExprPtr& argument) { return std::make_shared(argument); } }; CAS_NAMESPACE_END diff --git a/cas/include/cas/node/Sign.h b/cas/include/cas/node/Sign.h index 36ddc9a..b5729b1 100644 --- a/cas/include/cas/node/Sign.h +++ b/cas/include/cas/node/Sign.h @@ -11,20 +11,22 @@ CAS_NAMESPACE class Sign : public UnaryExpression { public: - explicit Sign(Expression* argument); + explicit Sign(const ExprPtr& argument); Sign() = delete; ~Sign() override = default; double evaluate(const VariableMap& variables) override; - bool _equals(Expression* expression) override; + bool _equals(const ExprPtr& expression) override; - Sign* clone() override; + ExprPtr clone() override; - Expression* simplified() override; + ExprPtr simplified() override; std::string latex() override; + static SignPtr from(const ExprPtr& argument) { return std::make_shared(argument); } + private: bool needsParentheses(); }; diff --git a/cas/include/cas/node/Sqrt.h b/cas/include/cas/node/Sqrt.h index b7a60a0..e99189c 100644 --- a/cas/include/cas/node/Sqrt.h +++ b/cas/include/cas/node/Sqrt.h @@ -11,19 +11,21 @@ CAS_NAMESPACE class Sqrt : public Root { public: - explicit Sqrt(Expression* base); + explicit Sqrt(const ExprPtr& base); Sqrt() = delete; ~Sqrt() override = default; double evaluate(const VariableMap& variables) override; - Sqrt* clone() override; - Expression* _derivative(char variable) override; - Expression* simplified() override; + ExprPtr clone() override; + ExprPtr _derivative(char variable) override; + ExprPtr simplified() override; std::string latex() override; std::wstring stringify() override; std::string text() override; std::string explicitText() override; + + static SqrtPtr from(const ExprPtr& base) { return std::make_shared(base); } }; CAS_NAMESPACE_END diff --git a/cas/include/cas/node/Sum.h b/cas/include/cas/node/Sum.h index d9937c5..8ca3e52 100644 --- a/cas/include/cas/node/Sum.h +++ b/cas/include/cas/node/Sum.h @@ -11,26 +11,28 @@ CAS_NAMESPACE class Sum : public Operator { public: - explicit Sum(const std::vector& expressions); + explicit Sum(const std::vector& expressions); Sum() = delete; ~Sum() override = default; - Sum* clone() override; + ExprPtr clone() override; - Sum* _derivative(char var) override; + ExprPtr _derivative(char var) override; - Expression* simplified() override; + ExprPtr simplified() override; std::string latex() override; std::wstring stringify() override; + static SumPtr from(const std::vector& expressions) { return std::make_shared(expressions); } + protected: double operate(double a, double b) override { return a + b; }; - bool needsParentheses(Expression*) override { return false; }; + bool needsParentheses(const ExprPtr&) override { return false; }; }; CAS_NAMESPACE_END diff --git a/cas/include/cas/node/UnaryExpression.h b/cas/include/cas/node/UnaryExpression.h index e45dc35..b6e1a86 100644 --- a/cas/include/cas/node/UnaryExpression.h +++ b/cas/include/cas/node/UnaryExpression.h @@ -9,15 +9,15 @@ CAS_NAMESPACE -class UnaryExpression : public Expression { +class UnaryExpression : public Expr { public: UnaryExpression() = delete; - ~UnaryExpression() override; + ~UnaryExpression() override = default; - Expression* derivative(char var) override; + ExprPtr derivative(char var) override; - Expression* getArgument() const { return argument; } + ExprPtr getArgument() const { return argument; } std::string latex() override; @@ -28,10 +28,10 @@ class UnaryExpression : public Expression { std::string explicitText() override; protected: - explicit UnaryExpression(const ExpressionProperties& properties, Expression* argument); + explicit UnaryExpression(const ExpressionProperties& properties, const ExprPtr& argument); protected: - Expression* argument; + ExprPtr argument; }; CAS_NAMESPACE_END diff --git a/cas/include/cas/node/Var.h b/cas/include/cas/node/Var.h index 5e068d1..51523a8 100644 --- a/cas/include/cas/node/Var.h +++ b/cas/include/cas/node/Var.h @@ -9,22 +9,21 @@ CAS_NAMESPACE -class Var : public Expression { +class Var : public Expr { public: explicit Var(char variable); - explicit Var() : Var('x') {} ~Var() override = default; double evaluate(const VariableMap& variables) override; - bool _equals(Expression* expression) override; + bool _equals(const ExprPtr& expression) override; - Var* clone() override; + ExprPtr clone() override; - Expression* _derivative(char var) override; + ExprPtr _derivative(char var) override; - Var* simplified() override; + ExprPtr simplified() override; std::string latex() override; @@ -34,24 +33,26 @@ class Var : public Expression { char getSymbol() const { return symbol; } - static Var* var(char variable) { return new Var(variable); } + static VarPtr var(char variable) { return Var::from(variable); } - static Var* a() { return var('a'); } - static Var* b() { return var('b'); } - static Var* c() { return var('c'); } + static VarPtr a() { return var('a'); } + static VarPtr b() { return var('b'); } + static VarPtr c() { return var('c'); } - static Var* i() { return var('i'); } - static Var* j() { return var('j'); } - static Var* k() { return var('k'); } + static VarPtr i() { return var('i'); } + static VarPtr j() { return var('j'); } + static VarPtr k() { return var('k'); } - static Var* x() { return var('x'); } - static Var* y() { return var('y'); } - static Var* z() { return var('z'); } - static Var* w() { return var('w'); } + static VarPtr x() { return var('x'); } + static VarPtr y() { return var('y'); } + static VarPtr z() { return var('z'); } + static VarPtr w() { return var('w'); } - static Var* s() { return var('s'); } - static Var* t() { return var('t'); } - static Var* u() { return var('u'); } + static VarPtr s() { return var('s'); } + static VarPtr t() { return var('t'); } + static VarPtr u() { return var('u'); } + + static VarPtr from(char variable) { return std::make_shared(variable); } private: const char symbol; diff --git a/cas/include/cas/node/trig/ArcCos.h b/cas/include/cas/node/trig/ArcCos.h index b4ccfeb..a1b7d0a 100644 --- a/cas/include/cas/node/trig/ArcCos.h +++ b/cas/include/cas/node/trig/ArcCos.h @@ -11,14 +11,16 @@ CAS_NAMESPACE class ArcCos : public InverseTrigExpression { public: - explicit ArcCos(Expression* argument); + explicit ArcCos(const ExprPtr& argument); ArcCos() = delete; ~ArcCos() override = default; double evaluate(const VariableMap& variables) override; - ArcCos* clone() override; - Expression* _derivative(char variable) override; - Expression* simplified() override; + ExprPtr clone() override; + ExprPtr _derivative(char variable) override; + ExprPtr simplified() override; + + static ArcCosPtr from(const ExprPtr& argument) { return std::make_shared(argument); } }; CAS_NAMESPACE_END diff --git a/cas/include/cas/node/trig/ArcCot.h b/cas/include/cas/node/trig/ArcCot.h index 46f6663..4ac098d 100644 --- a/cas/include/cas/node/trig/ArcCot.h +++ b/cas/include/cas/node/trig/ArcCot.h @@ -11,14 +11,16 @@ CAS_NAMESPACE class ArcCot : public InverseTrigExpression { public: - explicit ArcCot(Expression* argument); + explicit ArcCot(const ExprPtr& argument); ArcCot() = delete; ~ArcCot() override = default; double evaluate(const VariableMap& variables) override; - ArcCot* clone() override; - Expression* _derivative(char variable) override; - Expression* simplified() override; + ExprPtr clone() override; + ExprPtr _derivative(char variable) override; + ExprPtr simplified() override; + + static ArcCotPtr from(const ExprPtr& argument) { return std::make_shared(argument); } }; CAS_NAMESPACE_END diff --git a/cas/include/cas/node/trig/ArcCsc.h b/cas/include/cas/node/trig/ArcCsc.h index ee9ee67..e33f2d1 100644 --- a/cas/include/cas/node/trig/ArcCsc.h +++ b/cas/include/cas/node/trig/ArcCsc.h @@ -11,14 +11,16 @@ CAS_NAMESPACE class ArcCsc : public InverseTrigExpression { public: - explicit ArcCsc(Expression* argument); + explicit ArcCsc(const ExprPtr& argument); ArcCsc() = delete; ~ArcCsc() override = default; double evaluate(const VariableMap& variables) override; - ArcCsc* clone() override; - Expression* _derivative(char variable) override; - Expression* simplified() override; + ExprPtr clone() override; + ExprPtr _derivative(char variable) override; + ExprPtr simplified() override; + + static ArcCscPtr from(const ExprPtr& argument) { return std::make_shared(argument); } }; CAS_NAMESPACE_END diff --git a/cas/include/cas/node/trig/ArcSec.h b/cas/include/cas/node/trig/ArcSec.h index 0087f5a..5ff00d1 100644 --- a/cas/include/cas/node/trig/ArcSec.h +++ b/cas/include/cas/node/trig/ArcSec.h @@ -11,14 +11,16 @@ CAS_NAMESPACE class ArcSec : public InverseTrigExpression { public: - explicit ArcSec(Expression* argument); + explicit ArcSec(const ExprPtr& argument); ArcSec() = delete; ~ArcSec() override = default; double evaluate(const VariableMap& variables) override; - ArcSec* clone() override; - Expression* _derivative(char variable) override; - Expression* simplified() override; + ExprPtr clone() override; + ExprPtr _derivative(char variable) override; + ExprPtr simplified() override; + + static ArcSecPtr from(const ExprPtr& argument) { return std::make_shared(argument); } }; CAS_NAMESPACE_END diff --git a/cas/include/cas/node/trig/ArcSin.h b/cas/include/cas/node/trig/ArcSin.h index d4188b6..0b5b9bb 100644 --- a/cas/include/cas/node/trig/ArcSin.h +++ b/cas/include/cas/node/trig/ArcSin.h @@ -11,14 +11,16 @@ CAS_NAMESPACE class ArcSin : public InverseTrigExpression { public: - explicit ArcSin(Expression* argument); + explicit ArcSin(const ExprPtr& argument); ArcSin() = delete; ~ArcSin() override = default; double evaluate(const VariableMap& variables) override; - ArcSin* clone() override; - Expression* _derivative(char variable) override; - Expression* simplified() override; + ExprPtr clone() override; + ExprPtr _derivative(char variable) override; + ExprPtr simplified() override; + + static ArcSinPtr from(const ExprPtr& argument) { return std::make_shared(argument); } }; CAS_NAMESPACE_END diff --git a/cas/include/cas/node/trig/ArcTan.h b/cas/include/cas/node/trig/ArcTan.h index 82c3852..bc0e105 100644 --- a/cas/include/cas/node/trig/ArcTan.h +++ b/cas/include/cas/node/trig/ArcTan.h @@ -11,14 +11,16 @@ CAS_NAMESPACE class ArcTan : public InverseTrigExpression { public: - explicit ArcTan(Expression* argument); + explicit ArcTan(const ExprPtr& argument); ArcTan() = delete; ~ArcTan() override = default; double evaluate(const VariableMap& variables) override; - ArcTan* clone() override; - Expression* _derivative(char variable) override; - Expression* simplified() override; + ExprPtr clone() override; + ExprPtr _derivative(char variable) override; + ExprPtr simplified() override; + + static ArcTanPtr from(const ExprPtr& argument) { return std::make_shared(argument); } }; CAS_NAMESPACE_END diff --git a/cas/include/cas/node/trig/Cos.h b/cas/include/cas/node/trig/Cos.h index eb92750..a7f7004 100644 --- a/cas/include/cas/node/trig/Cos.h +++ b/cas/include/cas/node/trig/Cos.h @@ -12,14 +12,16 @@ CAS_NAMESPACE class Cos : public TrigExpression { public: - explicit Cos(Expression* argument); + explicit Cos(const ExprPtr& argument); Cos() = delete; ~Cos() override = default; double evaluate(const VariableMap& variables) override; - Cos* clone() override; - Expression* _derivative(char variable) override; - Expression* simplified() override; + ExprPtr clone() override; + ExprPtr _derivative(char variable) override; + ExprPtr simplified() override; + + static CosPtr from(const ExprPtr& argument) { return std::make_shared(argument); } }; CAS_NAMESPACE_END diff --git a/cas/include/cas/node/trig/Cot.h b/cas/include/cas/node/trig/Cot.h index 735311a..489c651 100644 --- a/cas/include/cas/node/trig/Cot.h +++ b/cas/include/cas/node/trig/Cot.h @@ -11,14 +11,16 @@ CAS_NAMESPACE class Cot : public TrigExpression { public: - explicit Cot(Expression* argument); + explicit Cot(const ExprPtr& argument); Cot() = delete; ~Cot() override = default; double evaluate(const VariableMap& variables) override; - Cot* clone() override; - Expression* _derivative(char variable) override; - Expression* simplified() override; + ExprPtr clone() override; + ExprPtr _derivative(char variable) override; + ExprPtr simplified() override; + + static CotPtr from(const ExprPtr& argument) { return std::make_shared(argument); } }; CAS_NAMESPACE_END diff --git a/cas/include/cas/node/trig/Csc.h b/cas/include/cas/node/trig/Csc.h index 098ba61..93063b4 100644 --- a/cas/include/cas/node/trig/Csc.h +++ b/cas/include/cas/node/trig/Csc.h @@ -11,14 +11,16 @@ CAS_NAMESPACE class Csc : public TrigExpression { public: - explicit Csc(Expression* argument); + explicit Csc(const ExprPtr& argument); Csc() = delete; ~Csc() override = default; double evaluate(const VariableMap& variables) override; - Csc* clone() override; - Expression* _derivative(char variable) override; - Expression* simplified() override; + ExprPtr clone() override; + ExprPtr _derivative(char variable) override; + ExprPtr simplified() override; + + static CscPtr from(const ExprPtr& argument) { return std::make_shared(argument); } }; CAS_NAMESPACE_END diff --git a/cas/include/cas/node/trig/InverseTrigExpression.h b/cas/include/cas/node/trig/InverseTrigExpression.h index 7e0d623..ee57a16 100644 --- a/cas/include/cas/node/trig/InverseTrigExpression.h +++ b/cas/include/cas/node/trig/InverseTrigExpression.h @@ -17,7 +17,7 @@ class InverseTrigExpression : public TrigExpression { std::string latex() override; protected: - explicit InverseTrigExpression(const ExpressionProperties& props, Expression* argument); + explicit InverseTrigExpression(const ExpressionProperties& props, const ExprPtr& argument); }; CAS_NAMESPACE_END diff --git a/cas/include/cas/node/trig/Sec.h b/cas/include/cas/node/trig/Sec.h index 95055dc..eb723d6 100644 --- a/cas/include/cas/node/trig/Sec.h +++ b/cas/include/cas/node/trig/Sec.h @@ -12,14 +12,16 @@ CAS_NAMESPACE class Sec : public TrigExpression { public: - explicit Sec(Expression* argument); + explicit Sec(const ExprPtr& argument); Sec() = delete; ~Sec() override = default; double evaluate(const VariableMap& variables) override; - Sec* clone() override; - Expression* _derivative(char variable) override; - Expression* simplified() override; + ExprPtr clone() override; + ExprPtr _derivative(char variable) override; + ExprPtr simplified() override; + + static SecPtr from(const ExprPtr& argument) { return std::make_shared(argument); } }; CAS_NAMESPACE_END diff --git a/cas/include/cas/node/trig/Sin.h b/cas/include/cas/node/trig/Sin.h index ca01000..21a8505 100644 --- a/cas/include/cas/node/trig/Sin.h +++ b/cas/include/cas/node/trig/Sin.h @@ -12,14 +12,16 @@ CAS_NAMESPACE class Sin : public TrigExpression { public: - explicit Sin(Expression* argument); + explicit Sin(const ExprPtr& argument); Sin() = delete; ~Sin() override = default; double evaluate(const VariableMap& variables) override; - Sin* clone() override; - Expression* _derivative(char variable) override; - Expression* simplified() override; + ExprPtr clone() override; + ExprPtr _derivative(char variable) override; + ExprPtr simplified() override; + + static SinPtr from(const ExprPtr& argument) { return std::make_shared(argument); } }; CAS_NAMESPACE_END diff --git a/cas/include/cas/node/trig/Tan.h b/cas/include/cas/node/trig/Tan.h index ce6403d..1a4ea60 100644 --- a/cas/include/cas/node/trig/Tan.h +++ b/cas/include/cas/node/trig/Tan.h @@ -12,14 +12,16 @@ CAS_NAMESPACE class Tan : public TrigExpression { public: - explicit Tan(Expression* argument); + explicit Tan(const ExprPtr& argument); Tan() = delete; ~Tan() override = default; double evaluate(const VariableMap& variables) override; - Tan* clone() override; - Expression* _derivative(char variable) override; - Expression* simplified() override; + ExprPtr clone() override; + ExprPtr _derivative(char variable) override; + ExprPtr simplified() override; + + static TanPtr from(const ExprPtr& argument) { return std::make_shared(argument); } }; CAS_NAMESPACE_END diff --git a/cas/include/cas/node/trig/TrigExpression.h b/cas/include/cas/node/trig/TrigExpression.h index 60310fe..059126a 100644 --- a/cas/include/cas/node/trig/TrigExpression.h +++ b/cas/include/cas/node/trig/TrigExpression.h @@ -13,9 +13,9 @@ CAS_NAMESPACE struct UnitCircleCoordinate { double angle; - Expression* cos; - Expression* sin; - Expression* tan; + ExprPtr cos; + ExprPtr sin; + ExprPtr tan; }; class TrigExpression : public UnaryExpression { @@ -23,7 +23,7 @@ class TrigExpression : public UnaryExpression { TrigExpression() = delete; ~TrigExpression() override = default; - bool _equals(Expression* expression) override; + bool _equals(const ExprPtr& expression) override; std::string latex() override; std::wstring stringify() override; @@ -32,7 +32,7 @@ class TrigExpression : public UnaryExpression { static const std::unordered_map unitCircle; protected: - explicit TrigExpression(const ExpressionProperties& props, Expression* argument); + explicit TrigExpression(const ExpressionProperties& props, const ExprPtr& argument); bool needsParentheses(); }; diff --git a/cas/include/cas/plot/Function.h b/cas/include/cas/plot/Function.h index 83d4f7e..405005b 100644 --- a/cas/include/cas/plot/Function.h +++ b/cas/include/cas/plot/Function.h @@ -9,16 +9,16 @@ CAS_NAMESPACE -class Function : public IMath, public IRepresentableMath { +class Function : public IMath, public IRepresentableMath { public: explicit Function(std::string strFunction, const std::string& name = "z", bool simplify = true); - virtual ~Function(); + virtual ~Function() = default; double evaluate(const VariableMap& vars) override; Function* derivative(char var) override; Function* simplifiedDerivative(char var); Function* simplified() override; - bool isEquivalent(IMath* expression) override; + bool isEquivalent(Function* const & expression) override; std::string latex() override; std::wstring stringify() override; @@ -29,18 +29,18 @@ class Function : public IMath, public IRepresentableMath { size_t getUid() const; const std::string& getStrExpr() const; - Expression* getExpr() const; + ExprPtr getExpr() const; const std::string& getName() const; const std::string& getFilename() const; const VarSet& getVariables() const; protected: - explicit Function(const std::string& strFunction, Expression* expr, const VarSet& variables, const std::string& name = "z"); + explicit Function(const std::string& strFunction, const ExprPtr& expr, const VarSet& variables, const std::string& name = "z"); private: const size_t uid; const std::string strExpr; - Expression* expr; + ExprPtr expr; const std::string name; const std::string filename; VarSet variables; diff --git a/cas/include/cas/plot/Surface.h b/cas/include/cas/plot/Surface.h deleted file mode 100644 index b2a55aa..0000000 --- a/cas/include/cas/plot/Surface.h +++ /dev/null @@ -1,75 +0,0 @@ -// -// Created by Abd-El-Aziz Zayed on 2022-10-25. -// - -#ifndef CAS_SURFACE_H -#define CAS_SURFACE_H - -#include "Function.h" - -template// V for vertex -struct Plot { - bool visible = true; - - static const uint32_t RESOLUTION = 100; - static const uint32_t SIZE = RESOLUTION + 1; - - static const uint32_t indexCount = RESOLUTION * RESOLUTION * 6; - static const uint32_t indicesSize = indexCount * sizeof(uint32_t); - static uint32_t* indices; - - static const uint32_t vertexCount = SIZE * SIZE; - static const uint32_t verticesSize = vertexCount * sizeof(V); - V* vertices = new V[vertexCount]; - - static void generateIndices() { - if (indices != nullptr) { - return; - } - - indices = new uint32_t[indexCount]; - uint32_t offset = 0; - for (uint32_t y = 0; y < RESOLUTION; y++) { - for (uint32_t x = 0; x < RESOLUTION; x++) { - uint32_t a = y * SIZE + x; - uint32_t b = a + 1; - uint32_t c = (y + 1) * SIZE + x; - uint32_t d = c + 1; - - indices[offset++] = a; - indices[offset++] = b; - indices[offset++] = c; - - indices[offset++] = b; - indices[offset++] = c; - indices[offset++] = d; - } - } - } - - static void cleanup() { - if (indices != nullptr) { - delete[] indices; - indices = nullptr; - } - } -}; - -CAS_NAMESPACE - -template// F: F(xyz, rgba) -> T -class Surface : public Function { - explicit Surface(std::string strFunction); - virtual ~Surface() override; - - void update(); - -private: - Plot fPlot; - Plot xDerivativePlot; - Plot yDerivativePlot; -}; - -CAS_NAMESPACE_END - -#endif//CAS_SURFACE_H diff --git a/cas/include/cas/util/StringUtils.h b/cas/include/cas/util/StringUtils.h index 71b8e59..7dc0955 100644 --- a/cas/include/cas/util/StringUtils.h +++ b/cas/include/cas/util/StringUtils.h @@ -10,16 +10,6 @@ #include #include -inline std::wstring toWstring(const std::string& string) { - std::wstring_convert> converter; - return converter.from_bytes(string); -} - -inline std::string toString(const std::wstring& wString) { - std::wstring_convert> converter; - return converter.to_bytes(wString); -} - inline void replaceAll(std::string& str, const std::string& from, const std::string& to) { size_t start_pos = 0; while ((start_pos = str.find(from, start_pos)) != std::string::npos) { diff --git a/cas/src/CMakeLists.txt b/cas/src/CMakeLists.txt index d21f848..de06036 100644 --- a/cas/src/CMakeLists.txt +++ b/cas/src/CMakeLists.txt @@ -5,7 +5,7 @@ include(FetchContent) FetchContent_Declare(cpr GIT_REPOSITORY https://github.com/libcpr/cpr.git - GIT_TAG f88fd7737de3e640c61703eb57a0fa0ce00c60cd) + GIT_TAG 2553fc41450301cd09a9271c8d2c3e0cf3546b73) FetchContent_MakeAvailable(cpr) set(CPR_BUILD_TESTS OFF CACHE BOOL "Build the tests" FORCE) @@ -29,7 +29,7 @@ set(CAS_SRC_HEADERS ../include/cas/node/Var.h ../include/cas/node/Operator.h ../include/cas/node/Sum.h - ../include/cas/node/Product.h + ../include/cas/node/Prod.h ../include/cas/node/Divide.h ../include/cas/node/Power.h ../include/cas/node/Negate.h @@ -69,8 +69,7 @@ set(CAS_SRC_HEADERS ../include/cas/node/IMath.h ../include/cas/latex/LatexRenderer.h ../include/cas/data/ExpressionParser.h - ../include/cas/data/VariableMap.h - ../include/cas/plot/Surface.h) + ../include/cas/data/VariableMap.h) set(CAS_SRC_SOURCES core/node/Const.cpp @@ -113,7 +112,6 @@ set(CAS_SRC_SOURCES core/node/trig/ArcCot.cpp core/node/trig/ArcCsc.cpp core/node/trig/InverseTrigExpression.cpp - core/data/ExpressionProperties.cpp core/data/VariableMap.cpp core/latex/LatexRenderer.cpp core/plot/Function.cpp diff --git a/cas/src/core/data/ExpressionParser.cpp b/cas/src/core/data/ExpressionParser.cpp index a8ae2fd..c36353e 100644 --- a/cas/src/core/data/ExpressionParser.cpp +++ b/cas/src/core/data/ExpressionParser.cpp @@ -15,7 +15,7 @@ #include "cas/node/Min.h" #include "cas/node/Mod.h" #include "cas/node/Negate.h" -#include "cas/node/Product.h" +#include "cas/node/Prod.h" #include "cas/node/Round.h" #include "cas/node/Sign.h" #include "cas/node/Sqrt.h" @@ -114,7 +114,7 @@ std::string ExpressionParser::pop(std::list& list) { return top; } -Expression* ExpressionParser::parse(const std::string& expression, VarSet& variables) { +ExprPtr ExpressionParser::parse(const std::string& expression, VarSet& variables) { std::string expr = expression; removeUnnecessarySurroundingBrackets(expr); @@ -139,13 +139,13 @@ Expression* ExpressionParser::parse(const std::string& expression, VarSet& varia } } - std::vector expressions; + std::vector expressions; for (const std::string& part: parts) { if (!part.empty()) expressions.push_back(parse(part, variables)); } - return new Sum(expressions); + return Sum::from(expressions); } else if (contains(cut, "-")) { std::vector parts = split(cut, "-"); for (std::string& part: parts) { @@ -155,20 +155,20 @@ Expression* ExpressionParser::parse(const std::string& expression, VarSet& varia } if (parts.size() == 2 && parts[0].empty()) { - return new Negate(parse(parts[1], variables)); + return Negate::from(parse(parts[1], variables)); } bool first = true; - std::vector expressions; + std::vector expressions; for (const std::string& part: parts) { if (!part.empty()) { - Expression* neg = parse(part, variables); - expressions.push_back(first ? neg : new Negate(neg)); + ExprPtr neg = parse(part, variables); + expressions.push_back(first ? neg : neg->negate()); } first = false; } - return new Sum(expressions); + return Sum::from(expressions); } else if (contains(cut, "*")) { std::vector parts = split(cut, "*"); for (std::string& part: parts) { @@ -177,13 +177,13 @@ Expression* ExpressionParser::parse(const std::string& expression, VarSet& varia } } - std::vector expressions; + std::vector expressions; for (const std::string& part: parts) { if (!part.empty()) expressions.push_back(parse(part, variables)); } - return new Product(expressions); + return Prod::from(expressions); } else if (contains(cut, "/")) { std::vector parts = splitFirst(cut, "/"); @@ -194,7 +194,7 @@ Expression* ExpressionParser::parse(const std::string& expression, VarSet& varia replaceOnce(parts[1], "()", "(" + pop(remove) + ")"); } - return new Divide(parse(parts[0], variables), parse(parts[1], variables)); + return Divide::from(parse(parts[0], variables), parse(parts[1], variables)); } else if (contains(cut, "^")) { std::vector parts = splitFirst(cut, "^"); @@ -206,42 +206,42 @@ Expression* ExpressionParser::parse(const std::string& expression, VarSet& varia } std::string& base = parts[0]; - Expression* power = parse(parts[1], variables); + ExprPtr power = parse(parts[1], variables); if (base == "e") { - return new Exp(power); + return Exp::from(power); } - return new Power(parse(base, variables), power); + return Power::from(parse(base, variables), power); } else if (cut == "-()") { - return new Negate(parse(pop(remove), variables)); + return Negate::from(parse(pop(remove), variables)); } else if (cut == "sin()") { - return new Sin(parse(pop(remove), variables)); + return Sin::from(parse(pop(remove), variables)); } else if (cut == "cos()") { - return new Cos(parse(pop(remove), variables)); + return Cos::from(parse(pop(remove), variables)); } else if (cut == "tan()") { - return new Tan(parse(pop(remove), variables)); + return Tan::from(parse(pop(remove), variables)); } else if (cut == "cot()") { - return new Cot(parse(pop(remove), variables)); + return Cot::from(parse(pop(remove), variables)); } else if (cut == "sec()") { - return new Sec(parse(pop(remove), variables)); + return Sec::from(parse(pop(remove), variables)); } else if (cut == "csc()") { - return new Csc(parse(pop(remove), variables)); + return Csc::from(parse(pop(remove), variables)); } else if (cut == "asin()" || cut == "arcsin()") { - return new ArcSin(parse(pop(remove), variables)); + return ArcSin::from(parse(pop(remove), variables)); } else if (cut == "acos()" || cut == "arccos()") { - return new ArcCos(parse(pop(remove), variables)); + return ArcCos::from(parse(pop(remove), variables)); } else if (cut == "atan()" || cut == "arctan()") { - return new ArcTan(parse(pop(remove), variables)); + return ArcTan::from(parse(pop(remove), variables)); } else if (cut == "acot()" || cut == "arccot()") { - return new ArcCot(parse(pop(remove), variables)); + return ArcCot::from(parse(pop(remove), variables)); } else if (cut == "asec()" || cut == "arcsec()") { - return new ArcSec(parse(pop(remove), variables)); + return ArcSec::from(parse(pop(remove), variables)); } else if (cut == "acsc()" || cut == "arccsc()") { - return new ArcCsc(parse(pop(remove), variables)); + return ArcCsc::from(parse(pop(remove), variables)); } else if (cut == "ln()") { - return new Ln(parse(pop(remove), variables)); + return Ln::from(parse(pop(remove), variables)); } else if (cut == "log()") { - return new Log(parse(pop(remove), variables)); + return Log::from(parse(pop(remove), variables)); } else if (cut.starts_with("log_")) { std::string log = cut.substr(4); std::vector parts = split(log, "_"); @@ -253,23 +253,23 @@ Expression* ExpressionParser::parse(const std::string& expression, VarSet& varia replaceOnce(parts[1], "()", "(" + pop(remove) + ")"); } - return new Log(parse(parts[0], variables), parse(parts[1], variables)); + return Log::from(parse(parts[0], variables), parse(parts[1], variables)); } else if (cut == "sqrt()") { - return new Sqrt(parse(pop(remove), variables)); + return Sqrt::from(parse(pop(remove), variables)); } else if (cut == "cbrt()") { - return new Cbrt(parse(pop(remove), variables)); + return Cbrt::from(parse(pop(remove), variables)); } else if (cut == "abs()") { - return new Abs(parse(pop(remove), variables)); + return Abs::from(parse(pop(remove), variables)); } else if (cut == "exp()") { - return new Exp(parse(pop(remove), variables)); + return Exp::from(parse(pop(remove), variables)); } else if (cut == "floor()") { - return new Floor(parse(pop(remove), variables)); + return Floor::from(parse(pop(remove), variables)); } else if (cut == "ceil()") { - return new Ceil(parse(pop(remove), variables)); + return Ceil::from(parse(pop(remove), variables)); } else if (cut == "round()") { - return new Round(parse(pop(remove), variables)); + return Round::from(parse(pop(remove), variables)); } else if (cut == "sign()" || cut == "sgn()") { - return new Sign(parse(pop(remove), variables)); + return Sign::from(parse(pop(remove), variables)); } else if (cut == "mod()") { std::string mod = pop(remove); std::vector parts = split(mod, ","); @@ -278,29 +278,29 @@ Expression* ExpressionParser::parse(const std::string& expression, VarSet& varia throw std::invalid_argument("Invalid number of arguments for mod in " + expression); } - return new Mod(parse(parts[0], variables), parse(parts[1], variables)); + return Mod::from(parse(parts[0], variables), parse(parts[1], variables)); } else if (cut == "max()") { std::string max = pop(remove); std::vector parts = split(max, ","); - std::vector expressions; + std::vector expressions; for (const std::string& part: parts) { if (!part.empty()) expressions.push_back(parse(part, variables)); } - return new Max(expressions); + return Max::from(expressions); } else if (cut == "min()") { std::string max = pop(remove); std::vector parts = split(max, ","); - std::vector expressions; + std::vector expressions; for (const std::string& part: parts) { if (!part.empty()) expressions.push_back(parse(part, variables)); } - return new Min(expressions); + return Min::from(expressions); } } else if (expr == "e") { return cas::Const::E(); @@ -311,117 +311,117 @@ Expression* ExpressionParser::parse(const std::string& expression, VarSet& varia } else if (expr.length() == 1 && isalpha(expr[0])) { char c = expr[0]; variables.insert(c); - return new Var(c); + return Var::from(c); } else if (isNumber(expr)) { - return new Const(std::stod(expr)); + return Const::from(std::stod(expr)); } else if (contains(expr, "+")) { std::vector parts = split(expr, "+"); - std::vector expressions; + std::vector expressions; for (const std::string& part: parts) { if (!part.empty()) expressions.push_back(parse(part, variables)); } - return new Sum(expressions); + return Sum::from(expressions); } else if (contains(expr, "-")) { std::vector parts = split(expr, "-"); if (parts.size() == 2 && parts[0].empty()) { - return new Negate(parse(parts[1], variables)); + return Negate::from(parse(parts[1], variables)); } bool first = true; - std::vector expressions; + std::vector expressions; for (const std::string& part: parts) { if (!part.empty()) { - Expression* neg = parse(part, variables); - expressions.push_back(first ? neg : new Negate(neg)); + ExprPtr neg = parse(part, variables); + expressions.push_back(first ? neg : Negate::from(neg)); } first = false; } - return new Sum(expressions); + return Sum::from(expressions); } else if (contains(expr, "*")) { std::vector parts = split(expr, "*"); - std::vector expressions; + std::vector expressions; for (const std::string& part: parts) { if (!part.empty()) expressions.push_back(parse(part, variables)); } - return new Product(expressions); + return Prod::from(expressions); } else if (contains(expr, "/")) { std::vector parts = splitFirst(expr, "/"); - return new Divide(parse(parts[0], variables), parse(parts[1], variables)); + return Divide::from(parse(parts[0], variables), parse(parts[1], variables)); } else if (contains(expr, "^")) { std::vector parts = splitFirst(expr, "^"); std::string& base = parts[0]; - Expression* power = parse(parts[1], variables); + ExprPtr power = parse(parts[1], variables); if (base == "e") { - return new Exp(power); + return Exp::from(power); } - return new Power(parse(base, variables), power); + return Power::from(parse(base, variables), power); } else if (expr.starts_with("-")) { - return new Negate(parse(expr.substr(1), variables)); + return Negate::from(parse(expr.substr(1), variables)); } else if (expr.starts_with("ln")) { - return new Ln(parse(expr.substr(2), variables)); + return Ln::from(parse(expr.substr(2), variables)); } else if (expr.starts_with("sin")) { - return new Sin(parse(expr.substr(3), variables)); + return Sin::from(parse(expr.substr(3), variables)); } else if (expr.starts_with("cos")) { - return new Cos(parse(expr.substr(3), variables)); + return Cos::from(parse(expr.substr(3), variables)); } else if (expr.starts_with("tan")) { - return new Tan(parse(expr.substr(3), variables)); + return Tan::from(parse(expr.substr(3), variables)); } else if (expr.starts_with("cot")) { - return new Cot(parse(expr.substr(3), variables)); + return Cot::from(parse(expr.substr(3), variables)); } else if (expr.starts_with("csc")) { - return new Csc(parse(expr.substr(3), variables)); + return Csc::from(parse(expr.substr(3), variables)); } else if (expr.starts_with("sec")) { - return new Sec(parse(expr.substr(3), variables)); + return Sec::from(parse(expr.substr(3), variables)); } else if (expr.starts_with("asin")) { - return new ArcSin(parse(expr.substr(4), variables)); + return ArcSin::from(parse(expr.substr(4), variables)); } else if (expr.starts_with("acos")) { - return new ArcCos(parse(expr.substr(4), variables)); + return ArcCos::from(parse(expr.substr(4), variables)); } else if (expr.starts_with("atan")) { - return new ArcTan(parse(expr.substr(4), variables)); + return ArcTan::from(parse(expr.substr(4), variables)); } else if (expr.starts_with("acot")) { - return new ArcCot(parse(expr.substr(4), variables)); + return ArcCot::from(parse(expr.substr(4), variables)); } else if (expr.starts_with("acsc")) { - return new ArcCsc(parse(expr.substr(4), variables)); + return ArcCsc::from(parse(expr.substr(4), variables)); } else if (expr.starts_with("asec")) { - return new ArcSec(parse(expr.substr(4), variables)); + return ArcSec::from(parse(expr.substr(4), variables)); } else if (expr.starts_with("arcsin")) { - return new ArcSin(parse(expr.substr(6), variables)); + return ArcSin::from(parse(expr.substr(6), variables)); } else if (expr.starts_with("arccos")) { - return new ArcCos(parse(expr.substr(6), variables)); + return ArcCos::from(parse(expr.substr(6), variables)); } else if (expr.starts_with("arctan")) { - return new ArcTan(parse(expr.substr(6), variables)); + return ArcTan::from(parse(expr.substr(6), variables)); } else if (expr.starts_with("arccot")) { - return new ArcCot(parse(expr.substr(6), variables)); + return ArcCot::from(parse(expr.substr(6), variables)); } else if (expr.starts_with("arccsc")) { - return new ArcCsc(parse(expr.substr(6), variables)); + return ArcCsc::from(parse(expr.substr(6), variables)); } else if (expr.starts_with("arcsec")) { - return new ArcSec(parse(expr.substr(6), variables)); + return ArcSec::from(parse(expr.substr(6), variables)); } else if (expr.starts_with("abs")) { - return new Abs(parse(expr.substr(3), variables)); + return Abs::from(parse(expr.substr(3), variables)); } else if (expr.starts_with("exp")) { - return new Exp(parse(expr.substr(3), variables)); + return Exp::from(parse(expr.substr(3), variables)); } else if (expr.starts_with("sqrt")) { - return new Sqrt(parse(expr.substr(4), variables)); + return Sqrt::from(parse(expr.substr(4), variables)); } else if (expr.starts_with("cbrt")) { - return new Cbrt(parse(expr.substr(4), variables)); + return Cbrt::from(parse(expr.substr(4), variables)); } else if (expr.starts_with("ceil")) { - return new Ceil(parse(expr.substr(4), variables)); + return Ceil::from(parse(expr.substr(4), variables)); } else if (expr.starts_with("floor")) { - return new Floor(parse(expr.substr(5), variables)); + return Floor::from(parse(expr.substr(5), variables)); } else if (expr.starts_with("round")) { - return new Round(parse(expr.substr(5), variables)); + return Round::from(parse(expr.substr(5), variables)); } else if (expr.starts_with("sign")) { - return new Sign(parse(expr.substr(4), variables)); + return Sign::from(parse(expr.substr(4), variables)); } else if (expr.starts_with("sgn")) { - return new Sign(parse(expr.substr(3), variables)); + return Sign::from(parse(expr.substr(3), variables)); } else if (expr.starts_with("log_")) { std::string log = expr.substr(4); std::vector parts = split(log, "_"); @@ -429,12 +429,12 @@ Expression* ExpressionParser::parse(const std::string& expression, VarSet& varia if (parts.size() != 2) throw std::invalid_argument("Invalid expression " + expression); - return new Log(parse(parts[0], variables), parse(parts[1], variables)); + return Log::from(parse(parts[0], variables), parse(parts[1], variables)); } else if (expr.starts_with("log")) { if (expr.length() == 4) - return new Log(parse(expr.substr(3), variables)); + return Log::from(parse(expr.substr(3), variables)); if (expr.length() == 5) - return new Log(parse(std::string(1, expr[3]), variables), parse(std::string(1, expr[4]), variables)); + return Log::from(parse(std::string(1, expr[3]), variables), parse(std::string(1, expr[4]), variables)); throw std::invalid_argument("Invalid expression " + expression); } diff --git a/cas/src/core/data/ExpressionProperties.cpp b/cas/src/core/data/ExpressionProperties.cpp deleted file mode 100644 index 4c8df1b..0000000 --- a/cas/src/core/data/ExpressionProperties.cpp +++ /dev/null @@ -1,24 +0,0 @@ -// -// Created by Abd-El-Aziz Zayed on 2022-09-22. -// - -#include "cas/data/ExpressionProperties.h" - -CAS_NAMESPACE - -ExpressionProperties::ExpressionProperties(ExpressionType type, std::string name, std::string shortName) - : order(uint16_t(type)), type(type), name(std::move(name)), shortName(std::move(shortName)) {} - -bool ExpressionProperties::operator==(const ExpressionProperties& other) const { - return type == other.type && order == other.order && name == other.name && shortName == other.shortName; -} - -uint16_t ExpressionProperties::getOrder() const { return order; } - -ExpressionType ExpressionProperties::getType() const { return type; } - -std::string ExpressionProperties::getName() const { return name; } - -std::string ExpressionProperties::getShortName() const { return shortName; } - -CAS_NAMESPACE_END \ No newline at end of file diff --git a/cas/src/core/data/VariableMap.cpp b/cas/src/core/data/VariableMap.cpp index b97623c..cf80452 100644 --- a/cas/src/core/data/VariableMap.cpp +++ b/cas/src/core/data/VariableMap.cpp @@ -248,7 +248,7 @@ VariableMapIterator& VariableMapIterator::operator++() { if (letter == 'z' + 1) { letter = 'A'; } - } while ((letter >= 'a' && letter <= 'z' || letter >= 'A' && letter <= 'Z') && + } while (((letter >= 'a' && letter <= 'z') || (letter >= 'A' && letter <= 'Z')) && !variableMap.contains(letter)); return *this; diff --git a/cas/src/core/node/Abs.cpp b/cas/src/core/node/Abs.cpp index 8d40c13..ac720fb 100644 --- a/cas/src/core/node/Abs.cpp +++ b/cas/src/core/node/Abs.cpp @@ -9,23 +9,23 @@ CAS_NAMESPACE -Abs::Abs(Expression* argument) +Abs::Abs(const ExprPtr& argument) : BracketExpression({ExpressionType::ABSOLUTE_VALUE, "absolute_value", "abs"}, argument, L"|", L"|", "\\left|", "\\right|") {} double Abs::evaluate(const VariableMap& variables) { return std::abs(argument->evaluate(variables)); } -Abs* Abs::clone() { - return new Abs(argument->clone()); +ExprPtr Abs::clone() { + return std::make_shared(argument->clone()); } -Expression* Abs::simplified() { +ExprPtr Abs::simplified() { if (argument->isOfType(ExpressionType::CONSTANT)) { - return Const::n(Expression::evaluate()); + return Const::n(Expr::evaluate()); } if (argument->isOfType(ExpressionType::NEGATE)) { - auto* negate = dynamic_cast(argument); + auto* negate = dynamic_cast(argument.get()); return negate->getArgument()->abs(); } if (argument->isOfType(ExpressionType::ABSOLUTE_VALUE)) { diff --git a/cas/src/core/node/BracketExpression.cpp b/cas/src/core/node/BracketExpression.cpp index 2b011d2..6e18c0b 100644 --- a/cas/src/core/node/BracketExpression.cpp +++ b/cas/src/core/node/BracketExpression.cpp @@ -8,19 +8,19 @@ CAS_NAMESPACE -BracketExpression::BracketExpression(const ExpressionProperties& properties, Expression* argument, +BracketExpression::BracketExpression(const ExpressionProperties& properties, const ExprPtr& argument, const wchar_t* openBracket, const wchar_t* closeBracket, const char* openBracketLatex, const char* closeBracketLatex) : UnaryExpression(properties, argument), openBracket(openBracket), closeBracket(closeBracket), openBracketLatex(openBracketLatex), closeBracketLatex(closeBracketLatex) {} -bool BracketExpression::_equals(Expression* other) { - auto* otherBracketFunction = dynamic_cast(other); +bool BracketExpression::_equals(const ExprPtr& other) { + auto* otherBracketFunction = dynamic_cast(other.get()); return argument->equals(otherBracketFunction->argument); } -Expression* BracketExpression::derivative(char) { +ExprPtr BracketExpression::derivative(char) { throw std::runtime_error("The " + properties.getName() + "::derivative() operation is not supported"); } diff --git a/cas/src/core/node/Cbrt.cpp b/cas/src/core/node/Cbrt.cpp index fe49bd6..76e5eab 100644 --- a/cas/src/core/node/Cbrt.cpp +++ b/cas/src/core/node/Cbrt.cpp @@ -5,27 +5,27 @@ #include "cas/node/Cbrt.h" #include "cas/node/Const.h" #include "cas/node/Divide.h" -#include "cas/node/Product.h" +#include "cas/node/Prod.h" #include "cas/util/StringUtils.h" #include #include CAS_NAMESPACE -Cbrt::Cbrt(Expression* base) - : Root({ExpressionType::CUBE_ROOT, "cube_root", "cbrt"}, base, new Const(3)) {} +Cbrt::Cbrt(const ExprPtr& base) + : Root({ExpressionType::CUBE_ROOT, "cube_root", "cbrt"}, base, Const::n(3)) {} double Cbrt::evaluate(const VariableMap& variables) { return std::cbrt(base->evaluate(variables)); } -Cbrt* Cbrt::clone() { - return new Cbrt(base->clone()); +ExprPtr Cbrt::clone() { + return std::make_shared(base->clone()); } -Expression* Cbrt::_derivative(char var) { +ExprPtr Cbrt::_derivative(char var) { if (base->isOfType(ExpressionType::CONSTANT)) { - return new Const(0); + return Const::zero(); } return base->derivative(var) @@ -35,15 +35,15 @@ Expression* Cbrt::_derivative(char var) { ->cbrt())); } -Expression* Cbrt::simplified() { +ExprPtr Cbrt::simplified() { if (base->isOfType(ExpressionType::CONSTANT)) { - double cbrt = Expression::evaluate(); + double cbrt = Expr::evaluate(); if (isWholeNumber(cbrt)) - return new Const(cbrt); + return Const::n(cbrt); return clone(); } if (base->isOfType(ExpressionType::POWER)) { - auto* power = dynamic_cast(base); + auto* power = dynamic_cast(base.get()); if (power->getExponent()->isOfType(ExpressionType::CONSTANT)) { double exponent = power->getExponent()->evaluate(); if (exponent == 3) diff --git a/cas/src/core/node/Ceil.cpp b/cas/src/core/node/Ceil.cpp index ebce60c..4602695 100644 --- a/cas/src/core/node/Ceil.cpp +++ b/cas/src/core/node/Ceil.cpp @@ -9,7 +9,7 @@ CAS_NAMESPACE -Ceil::Ceil(Expression* argument) +Ceil::Ceil(const ExprPtr& argument) : BracketExpression({ExpressionType::CEIL, "ceiling", "ceil"}, argument, L"\u2308", L"\u2309", "\\lceil", "\\rceil") {} @@ -18,19 +18,19 @@ double Ceil::evaluate(const VariableMap& variables) { return std::ceil(argument->evaluate(variables)); } -Ceil* Ceil::clone() { - return new Ceil(argument->clone()); +ExprPtr Ceil::clone() { + return std::make_shared(argument->clone()); } -Expression* Ceil::simplified() { +ExprPtr Ceil::simplified() { if (argument->isOfType(ExpressionType::CONSTANT)) { - return Const::n(Expression::evaluate()); + return Const::n(Expr::evaluate()); } if (argument->isOfType(ExpressionType::CEIL)) { return argument->simplified(); } if (argument->isOfType(ExpressionType::NEGATE)) { - auto* negate = dynamic_cast(argument); + auto* negate = dynamic_cast(argument.get()); return negate->getArgument()->simplified()->floor()->negate(); } diff --git a/cas/src/core/node/Const.cpp b/cas/src/core/node/Const.cpp index 88d36a0..85a51c5 100644 --- a/cas/src/core/node/Const.cpp +++ b/cas/src/core/node/Const.cpp @@ -16,9 +16,9 @@ const char* Const::E_LATEX = "e"; const char* Const::PHI_LATEX = "\\varphi"; Const::Const(double value) - : Expression{{ExpressionType::CONSTANT, "constant", "const"}}, value{value} {} + : Expr{{ExpressionType::CONSTANT, "constant", "const"}}, value{value} {} -Const* Const::clone() { +ExprPtr Const::clone() { return Const::n(value); } @@ -26,15 +26,15 @@ double Const::evaluate(const VariableMap&) { return value; } -bool Const::_equals(Expression* expression) { +bool Const::_equals(const ExprPtr& expression) { return floatingsEqual(value, expression->evaluate()); } -Const* Const::_derivative(char) { +ExprPtr Const::_derivative(char) { return Const::zero(); } -Const* Const::simplified() { +ExprPtr Const::simplified() { return clone(); } diff --git a/cas/src/core/node/Divide.cpp b/cas/src/core/node/Divide.cpp index 6a0804c..59057bf 100644 --- a/cas/src/core/node/Divide.cpp +++ b/cas/src/core/node/Divide.cpp @@ -6,41 +6,33 @@ #include "cas/node/Const.h" #include "cas/node/Negate.h" #include "cas/node/Power.h" -#include "cas/node/Product.h" +#include "cas/node/Prod.h" #include "cas/node/Sum.h" #include "fmt/printf.h" #include "fmt/xchar.h" CAS_NAMESPACE -Divide::Divide(Expression* dividend, Expression* divisor) - : Expression({ExpressionType::DIVIDE, "divide", "div"}), dividend(dividend), divisor(divisor) { - this->dividend->setParent(this); - this->divisor->setParent(this); -} - -Divide::~Divide() { - delete dividend; - delete divisor; - - dividend = nullptr; - divisor = nullptr; +Divide::Divide(const ExprPtr& dividend, const ExprPtr& divisor) + : Expr({ExpressionType::DIVIDE, "divide", "div"}), dividend(dividend), divisor(divisor) { + dividend->setParent(this); + divisor->setParent(this); } double Divide::evaluate(const VariableMap& variables) { return dividend->evaluate(variables) / divisor->evaluate(variables); } -bool Divide::_equals(Expression* expression) { - auto* divide = dynamic_cast(expression); +bool Divide::_equals(const ExprPtr& expression) { + auto* divide = dynamic_cast(expression.get()); return dividend->equals(divide->dividend) && divisor->equals(divide->divisor); } -Divide* Divide::clone() { - return new Divide(dividend->clone(), divisor->clone()); +ExprPtr Divide::clone() { + return Divide::from(dividend->clone(), divisor->clone()); } -Divide* Divide::_derivative(char var) { +ExprPtr Divide::_derivative(char var) { return dividend->derivative(var) ->multiply(divisor->clone())// f' * g ->subtract(dividend->clone() @@ -49,7 +41,7 @@ Divide* Divide::_derivative(char var) { ->power(2));// (f' * g - f * g') / g^2 } -Expression* Divide::simplified() { +ExprPtr Divide::simplified() { if (dividend->equals(divisor)) { return Const::one(); } @@ -58,20 +50,20 @@ Expression* Divide::simplified() { bool divisorIsDivide = divisor->isOfType(ExpressionType::DIVIDE); if (dividendIsDivide && !divisorIsDivide) {// (g/h)/f = g/(h*f) - auto* dDividend = dynamic_cast(dividend); + auto* dDividend = dynamic_cast(dividend.get()); return dDividend->dividend->simplified() ->divide(dDividend->divisor->simplified() ->multiply(divisor)); } if (!dividendIsDivide && divisorIsDivide) {// f/(g/h) = (f*h)/g - auto* divisorDivide = dynamic_cast(divisor); + auto* divisorDivide = dynamic_cast(divisor.get()); return dividend ->multiply(divisorDivide->divisor->simplified()) ->divide(divisorDivide->dividend->simplified()); } if (dividendIsDivide) {// (g/h)/(f/k) = (g*k)/(h*f) - auto* dividendDivide = dynamic_cast(dividend); - auto* divisorDivide = dynamic_cast(divisor); + auto* dividendDivide = dynamic_cast(dividend.get()); + auto* divisorDivide = dynamic_cast(divisor.get()); return dividendDivide->dividend->simplified() ->multiply(divisorDivide->divisor->simplified()) ->divide(dividendDivide->divisor->simplified() @@ -87,7 +79,7 @@ Expression* Divide::simplified() { double result = dividendValue / divisorValue; if (isWholeNumber(result)) { - return new Const(result); + return Const::n(result); } return Const::n(dividendValue)->divide(Const::n(divisorValue)); } diff --git a/cas/src/core/node/Exp.cpp b/cas/src/core/node/Exp.cpp index b34b800..a3aaf77 100644 --- a/cas/src/core/node/Exp.cpp +++ b/cas/src/core/node/Exp.cpp @@ -5,31 +5,31 @@ #include "cas/node/Exp.h" #include "cas/node/Const.h" #include "cas/node/Log.h" -#include "cas/node/Product.h" +#include "cas/node/Prod.h" #include "fmt/format.h" CAS_NAMESPACE -Exp::Exp(Expression* exponent) +Exp::Exp(const ExprPtr& exponent) : Power({ExpressionType::EXPONENTIAL, "exponential", "exp"}, Const::E(), exponent) {} double Exp::evaluate(const VariableMap& variables) { return std::exp(exponent->evaluate(variables)); } -Exp* Exp::clone() { - return new Exp(exponent->clone()); +ExprPtr Exp::clone() { + return Exp::from(exponent->clone()); } -Expression* Exp::_derivative(char var) { +ExprPtr Exp::_derivative(char var) { if (exponent->isOfType(ExpressionType::CONSTANT)) { - return new Const; + return Const::zero(); } return clone()->multiply(exponent->derivative(var)); } -Expression* Exp::simplified() { +ExprPtr Exp::simplified() { if (exponent->isOfType(ExpressionType::CONSTANT)) { double exponentValue = exponent->evaluate(); if (exponentValue == 0) @@ -38,7 +38,7 @@ Expression* Exp::simplified() { return Const::E(); } if (exponent->isOfType(ExpressionType::LOGARITHM)) { - auto* log = dynamic_cast(exponent); + auto* log = dynamic_cast(exponent.get()); if (log->getBase()->equals(this->base)) return log->getArgument()->simplified(); } diff --git a/cas/src/core/node/Expression.cpp b/cas/src/core/node/Expression.cpp index ad53064..a65b308 100644 --- a/cas/src/core/node/Expression.cpp +++ b/cas/src/core/node/Expression.cpp @@ -13,7 +13,7 @@ #include "cas/node/Ln.h" #include "cas/node/Mod.h" #include "cas/node/Negate.h" -#include "cas/node/Product.h" +#include "cas/node/Prod.h" #include "cas/node/Round.h" #include "cas/node/Sign.h" #include "cas/node/Sqrt.h" @@ -33,22 +33,23 @@ #include "cas/node/trig/Tan.h" #include #include +#include CAS_NAMESPACE -Expression::Expression(const ExpressionProperties& properties) +Expr::Expr(const ExpressionProperties& properties) : properties{properties} {} -double Expression::evaluate(const VariableMap&) { +double Expr::evaluate(const VariableMap&) { throw std::runtime_error("Expression::evaluate() is not implemented for " + properties.getName()); } -double Expression::evaluate() { +double Expr::evaluate() { return evaluate({}); } -bool Expression::equals(Expression* expression) { - if (this == expression) +bool Expr::equals(const ExprPtr& expression) { + if (this == expression.get()) return true; if (!isOfType(expression->getProperties().getType())) @@ -57,180 +58,177 @@ bool Expression::equals(Expression* expression) { return _equals(expression); } -bool Expression::_equals(Expression*) { +bool Expr::_equals(const ExprPtr&) { throw std::runtime_error("Expression::equals() is not implemented for " + properties.getName()); } -Expression* Expression::clone() { +ExprPtr Expr::clone() { throw std::runtime_error("Expression::clone() is not implemented for " + properties.getName()); } -Expression* Expression::derivative(char var) { +ExprPtr Expr::derivative(char var) { return _derivative(var); } -Expression* Expression::_derivative(char) { +ExprPtr Expr::_derivative(char) { throw std::runtime_error("Expression::derivative() is not implemented for " + properties.getName()); } -Expression* Expression::simplified() { +ExprPtr Expr::simplified() { throw std::runtime_error("Expression::simplified() is not implemented for " + properties.getName()); } -bool Expression::isEquivalent(cas::IMath*) { +bool Expr::isEquivalent(const ExprPtr&) { throw std::runtime_error("Expression::isEquivalent() is not implemented for " + properties.getName()); } -Product* Expression::multiply(Expression* expression) { - return new Product({this, expression}); +ProdPtr Expr::multiply(const ExprPtr& expression) { + return std::make_shared(std::vector{shared_from_this(), expression}); } -Product* Expression::multiply(double value) { - return new Product({this, Const::n(value)}); +ProdPtr Expr::multiply(double value) { + return std::make_shared(std::vector{shared_from_this(), Const::n(value)}); } -Sum* Expression::add(Expression* expression) { - return new Sum({this, expression}); +SumPtr Expr::add(const ExprPtr& expression) { + return std::make_shared(std::vector{shared_from_this(), expression}); } -Sum* Expression::add(double value) { - return this->add(new Const(value)); +SumPtr Expr::add(double value) { + return add(Const::n(value)); } -Sum* Expression::subtract(Expression* expression) { - return new Sum({this, new Negate(expression)}); +SumPtr Expr::subtract(const ExprPtr& expression) { + const NegatePtr& negate = Negate::from(expression); + return std::make_shared(std::vector{shared_from_this(), negate}); } -Sum* Expression::subtract(double value) { - return this->subtract(new Const(value)); +SumPtr Expr::subtract(double value) { + return subtract(Const::n(value)); } -Divide* Expression::divide(Expression* expression) { - return new Divide(this, expression); +DividePtr Expr::divide(const ExprPtr& expression) { + return std::make_shared(shared_from_this(), expression); } -Divide* Expression::divide(double divisor) { +DividePtr Expr::divide(double divisor) { return this->divide(Const::n(divisor)); } -Negate* Expression::negate() { - return new Negate(this); +NegatePtr Expr::negate() { + return std::make_shared(shared_from_this()); } -Power* Expression::power(Expression* expression) { - return new Power(this, expression); +PowerPtr Expr::power(const ExprPtr& expression) { + return std::make_shared(shared_from_this(), expression); } -Power* Expression::power(double exponent) { - return new Power(this, exponent); +PowerPtr Expr::power(double exponent) { + return std::make_shared(shared_from_this(), exponent); } -Exp* Expression::exp() { - return new Exp(this); +ExpPtr Expr::exp() { + return std::make_shared(shared_from_this()); } -Log* Expression::log(Expression* base) { - return new Log(base, this); +LogPtr Expr::log(const ExprPtr& base) { + return std::make_shared(base, shared_from_this()); } -Log* Expression::log(double base) { - return new Log(base, this); +LogPtr Expr::log(double base) { + return std::make_shared(base, shared_from_this()); } -Ln* Expression::ln() { - return new Ln(this); +LnPtr Expr::ln() { + return std::make_shared(shared_from_this()); } - -Root* Expression::root(Expression* root) { - return new Root(this, root); +RootPtr Expr::root(const ExprPtr& root) { + return std::make_shared(shared_from_this(), root); } -Root* Expression::root(double root) { - return new Root(this, root); +RootPtr Expr::root(double root) { + return std::make_shared(shared_from_this(), root); } -Sqrt* Expression::sqrt() { - return new Sqrt(this); +SqrtPtr Expr::sqrt() { + return std::make_shared(shared_from_this()); } -Cbrt* Expression::cbrt() { - return new Cbrt(this); +CbrtPtr Expr::cbrt() { + return std::make_shared(shared_from_this()); } -Abs* Expression::abs() { - return new Abs(this); +AbsPtr Expr::abs() { + return std::make_shared(shared_from_this()); } -Cos* Expression::cos() { - return new Cos(this); +CosPtr Expr::cos() { + return std::make_shared(shared_from_this()); } -Sin* Expression::sin() { - return new Sin(this); +SinPtr Expr::sin() { + return std::make_shared(shared_from_this()); } -Tan* Expression::tan() { - return new Tan(this); +TanPtr Expr::tan() { + return std::make_shared(shared_from_this()); } -ArcTan* Expression::atan() { - return new ArcTan(this); +ArcTanPtr Expr::atan() { + return std::make_shared(shared_from_this()); } -ArcCos* Expression::acos() { - return new ArcCos(this); +ArcCosPtr Expr::acos() { + return std::make_shared(shared_from_this()); } -ArcSin* Expression::asin() { - return new ArcSin(this); +ArcSinPtr Expr::asin() { + return std::make_shared(shared_from_this()); } -Csc* Expression::csc() { - return new Csc(this); +CscPtr Expr::csc() { + return std::make_shared(shared_from_this()); } -Sec* Expression::sec() { - return new Sec(this); +SecPtr Expr::sec() { + return std::make_shared(shared_from_this()); } -Cot* Expression::cot() { - return new Cot(this); +CotPtr Expr::cot() { + return std::make_shared(shared_from_this()); } -ArcCsc* Expression::acsc() { - return new ArcCsc(this); +ArcCscPtr Expr::acsc() { + return std::make_shared(shared_from_this()); } -ArcSec* Expression::asec() { - return new ArcSec(this); +ArcSecPtr Expr::asec() { + return std::make_shared(shared_from_this()); } -ArcCot* Expression::acot() { - return new ArcCot(this); +ArcCotPtr Expr::acot() { + return std::make_shared(shared_from_this()); } -Floor* Expression::floor() { - return new Floor(this); +FloorPtr Expr::floor() { + return std::make_shared(shared_from_this()); } -Ceil* Expression::ceil() { - return new Ceil(this); +CeilPtr Expr::ceil() { + return std::make_shared(shared_from_this()); } -Round* Expression::round() { - return new Round(this); +RoundPtr Expr::round() { + return std::make_shared(shared_from_this()); } -Sign* Expression::sign() { - return new Sign(this); +SignPtr Expr::sign() { + return std::make_shared(shared_from_this()); } -Mod* Expression::mod(Expression* expression) { - return new Mod(this, expression); +ModPtr Expr::mod(const ExprPtr& expression) { + return std::make_shared(shared_from_this(), expression); } -Expression* Expression::reciprocal() { +ExprPtr Expr::reciprocal() { if (isOfType(ExpressionType::DIVIDE)) { auto* div = dynamic_cast(this); return div->getDivisor()->divide(div->getDividend()); } - return Const::n(1)->divide(this); + return Const::n(1)->divide(shared_from_this()); } -bool Expression::operator<(const cas::Expression& expression) const { - ExpressionType type = properties.getType(); - ExpressionType expressionType = expression.properties.getType(); - - int diff = static_cast(type) - static_cast(expressionType); +bool Expr::operator<(const cas::Expr& expression) const { + int diff = this->properties.getOrder() - expression.properties.getOrder(); if (diff == 0) { if (isOfType(ExpressionType::VARIABLE)) { @@ -258,39 +256,39 @@ bool Expression::operator<(const cas::Expression& expression) const { return diff < 0; } -bool Expression::lessThan(cas::Expression* expression) const { +bool Expr::lessThan(const ExprPtr& expression) const { return *this < *expression; } -bool Expression::compare(cas::Expression* left, cas::Expression* right) { +bool Expr::compare(const ExprPtr& left, const ExprPtr& right) { return left->lessThan(right); } -ExpressionProperties Expression::getProperties() const { +ExpressionProperties Expr::getProperties() const { return properties; } -Expression* Expression::getParent() const { +Expr* Expr::getParent() const { return parent; } -void Expression::setParent(Expression* newParent) { +void Expr::setParent(Expr* newParent) { this->parent = newParent; } -bool Expression::isNegated() const { +bool Expr::isNegated() const { return properties.getType() == ExpressionType::NEGATE; } -bool Expression::isOfType(ExpressionType type) const { +bool Expr::isOfType(ExpressionType type) const { return properties.getType() == type; } -bool Expression::isOfSameType(Expression* expression) const { +bool Expr::isOfSameType(const ExprPtr& expression) const { return isOfType(expression->getProperties().getType()); } -std::string Expression::explicitText() { +std::string Expr::explicitText() { return properties.getShortName() + "(" + text() + ")"; } diff --git a/cas/src/core/node/Floor.cpp b/cas/src/core/node/Floor.cpp index afd8a46..1aba474 100644 --- a/cas/src/core/node/Floor.cpp +++ b/cas/src/core/node/Floor.cpp @@ -9,26 +9,26 @@ CAS_NAMESPACE -Floor::Floor(Expression* argument) +Floor::Floor(const ExprPtr& argument) : BracketExpression({ExpressionType::FLOOR, "floor_value", "floor"}, argument, L"\u230A", L"\u230B", "\\lfloor", "\\rfloor") {} double Floor::evaluate(const VariableMap& variables) { return std::floor(argument->evaluate(variables)); } -Floor* Floor::clone() { - return new Floor(argument->clone()); +ExprPtr Floor::clone() { + return Floor::from(argument->clone()); } -Expression* Floor::simplified() { +ExprPtr Floor::simplified() { if (argument->isOfType(ExpressionType::CONSTANT)) { - return Const::n(Expression::evaluate()); + return Const::n(Expr::evaluate()); } if (argument->isOfType(ExpressionType::FLOOR)) { return argument->simplified(); } if (argument->isOfType(ExpressionType::NEGATE)) { - auto* negate = dynamic_cast(argument); + auto* negate = dynamic_cast(argument.get()); return negate->getArgument()->simplified()->ceil()->negate(); } diff --git a/cas/src/core/node/Ln.cpp b/cas/src/core/node/Ln.cpp index 8308c9d..8b9d776 100644 --- a/cas/src/core/node/Ln.cpp +++ b/cas/src/core/node/Ln.cpp @@ -11,30 +11,30 @@ CAS_NAMESPACE -Ln::Ln(Expression* argument) +Ln::Ln(const ExprPtr& argument) : Log({ExpressionType::NATURAL_LOGARITHM, "natural_logarithm", "ln"}, Const::E(), argument) {} double Ln::evaluate(const VariableMap& variables) { return std::log(argument->evaluate(variables)); } -bool Ln::_equals(Expression* expression) { +bool Ln::_equals(const ExprPtr& expression) { if (expression->isOfType(ExpressionType::NATURAL_LOGARITHM)) { - auto* ln = dynamic_cast(expression); + auto* ln = dynamic_cast(expression.get()); return argument->equals(ln->argument); } return false; } -Ln* Ln::clone() { - return new Ln(argument->clone()); +ExprPtr Ln::clone() { + return Ln::from(argument->clone()); } -Expression* Ln::_derivative(char var) { +ExprPtr Ln::_derivative(char var) { return argument->derivative(var)->divide(argument->clone()); } -Expression* Ln::simplified() { +ExprPtr Ln::simplified() { if (argument->equals(base)) return Const::one(); if (argument->isOfType(ExpressionType::CONSTANT)) { @@ -43,11 +43,11 @@ Expression* Ln::simplified() { return Const::zero(); } if (argument->isOfType(ExpressionType::EXPONENTIAL)) { - auto* exp = dynamic_cast(argument); + auto* exp = dynamic_cast(argument.get()); return exp->getExponent()->simplified(); } if (argument->isOfType(ExpressionType::POWER)) { - auto* power = dynamic_cast(argument); + auto* power = dynamic_cast(argument.get()); if (power->getBase()->equals(base)) return power->getExponent()->simplified(); } diff --git a/cas/src/core/node/Log.cpp b/cas/src/core/node/Log.cpp index 8b50294..e89adfb 100644 --- a/cas/src/core/node/Log.cpp +++ b/cas/src/core/node/Log.cpp @@ -7,57 +7,49 @@ #include "cas/node/Divide.h" #include "cas/node/Ln.h" #include "cas/node/Power.h" -#include "cas/node/Product.h" +#include "cas/node/Prod.h" #include "fmt/printf.h" #include "fmt/xchar.h" CAS_NAMESPACE -Log::Log(const ExpressionProperties& props, Expression* base, Expression* argument) - : Expression(props), base(base), argument(argument) { +Log::Log(const ExpressionProperties& props, const ExprPtr& base, const ExprPtr& argument) + : Expr(props), base(base), argument(argument) { base->setParent(this); argument->setParent(this); } -Log::Log(Expression* base, Expression* argument) +Log::Log(const ExprPtr& base, const ExprPtr& argument) : Log({ExpressionType::LOGARITHM, "logarithm", "log"}, base, argument) {} -Log::Log(double base, Expression* argument) - : Log({ExpressionType::LOGARITHM, "logarithm", "log"}, new Const(base), argument) {} +Log::Log(double base, const ExprPtr& argument) + : Log({ExpressionType::LOGARITHM, "logarithm", "log"}, Const::n(base), argument) {} -Log::Log(Expression* argument) +Log::Log(const ExprPtr& argument) : Log({ExpressionType::LOGARITHM, "logarithm", "log"}, Const::n(10), argument) {} -Log::~Log() { - delete base; - delete argument; - - base = nullptr; - argument = nullptr; -} - double Log::evaluate(const VariableMap& variables) { return std::log(argument->evaluate(variables)) / std::log(base->evaluate(variables)); } -bool Log::_equals(Expression* expression) { +bool Log::_equals(const ExprPtr& expression) { if (expression->isOfType(ExpressionType::LOGARITHM)) { - auto* log = dynamic_cast(expression); + auto* log = dynamic_cast(expression.get()); return base->equals(log->base) && argument->equals(log->argument); } return false; } -Log* Log::clone() { - return new Log(base->clone(), argument->clone()); +ExprPtr Log::clone() { + return Log::from(base->clone(), argument->clone()); } -Expression* Log::_derivative(char var) { +ExprPtr Log::_derivative(char var) { bool baseIsConstant = base->isOfType(ExpressionType::CONSTANT); bool argumentIsConstant = argument->isOfType(ExpressionType::CONSTANT); if (baseIsConstant && argumentIsConstant) { - return new Const(0); + return Const::zero(); } if (baseIsConstant) { @@ -66,18 +58,16 @@ Expression* Log::_derivative(char var) { ->multiply(base->clone()->ln())); } - Expression* exp = base->clone() - ->ln() - ->divide(argument->clone() - ->ln()); - Expression* derivative = exp->derivative(var); - - delete exp; + ExprPtr exp = base->clone() + ->ln() + ->divide(argument->clone() + ->ln()); + ExprPtr derivative = exp->derivative(var); return derivative; } -Expression* Log::simplified() { +ExprPtr Log::simplified() { if (argument->equals(base)) return Const::one(); @@ -88,12 +78,12 @@ Expression* Log::simplified() { } if (argument->isOfType(ExpressionType::POWER)) { - auto* power = dynamic_cast(argument); + auto* power = dynamic_cast(argument.get()); if (power->getBase()->equals(base)) return power->getExponent()->simplified(); } - return new Log(base->simplified(), argument->simplified()); + return Log::from(base->simplified(), argument->simplified()); } bool Log::argumentNeedsParentheses() { diff --git a/cas/src/core/node/Max.cpp b/cas/src/core/node/Max.cpp index f26b0f4..c2cedb7 100644 --- a/cas/src/core/node/Max.cpp +++ b/cas/src/core/node/Max.cpp @@ -8,39 +8,39 @@ CAS_NAMESPACE -Max::Max(std::vector expressions) +Max::Max(std::vector expressions) : NaryExpression({ExpressionType::MAX, "maximum", "max"}, std::move(expressions)) {} double Max::evaluate(const VariableMap& variables) { - auto functor = [&](Expression* a, Expression* b) { + auto functor = [&](const ExprPtr& a, const ExprPtr& b) { return a->evaluate(variables) > b->evaluate(variables); }; return (*std::max_element(expressions.begin(), expressions.end(), functor))->evaluate(variables); } -Max* Max::clone() { - std::vector clonedExpressions; +ExprPtr Max::clone() { + std::vector clonedExpressions; clonedExpressions.reserve(expressions.size()); for (auto& expression: expressions) clonedExpressions.push_back(expression->clone()); - return new Max(clonedExpressions); + return Max::from(clonedExpressions); } -Expression* Max::simplified() { +ExprPtr Max::simplified() { if (expressions.size() == 1) return expressions[0]->simplified(); - std::vector simplifiedExpressions; + std::vector simplifiedExpressions; simplifiedExpressions.reserve(expressions.size()); - std::transform(expressions.begin(), expressions.end(), simplifiedExpressions.begin(), [](Expression* expr) { + std::transform(expressions.begin(), expressions.end(), simplifiedExpressions.begin(), [](const ExprPtr& expr) { return expr->simplified(); }); - bool (*isConstant)(Expression*) = [](Expression* expression) { + bool (*isConstant)(const ExprPtr&) = [](const ExprPtr& expression) { return expression->isOfType(ExpressionType::CONSTANT); }; @@ -49,14 +49,14 @@ Expression* Max::simplified() { if (constantCount > 1) { bool allConstant = std::all_of(simplifiedExpressions.begin(), simplifiedExpressions.end(), isConstant); if (allConstant) { - double maxElement = (*std::max_element(simplifiedExpressions.begin(), simplifiedExpressions.end(), [](Expression* a, Expression* b) { + double maxElement = (*std::max_element(simplifiedExpressions.begin(), simplifiedExpressions.end(), [](const ExprPtr& a, const ExprPtr& b) { return a->evaluate() > b->evaluate(); }))->evaluate(); return Const::n(maxElement); } - std::vector reducedExpressions; + std::vector reducedExpressions; reducedExpressions.reserve(expressions.size()); double max = -1.0 / 0.0; @@ -73,10 +73,10 @@ Expression* Max::simplified() { return reducedExpressions[0]; } - return new Max(reducedExpressions); + return Max::from(reducedExpressions); } - return new Max(simplifiedExpressions); + return Max::from(simplifiedExpressions); } CAS_NAMESPACE_END \ No newline at end of file diff --git a/cas/src/core/node/Min.cpp b/cas/src/core/node/Min.cpp index 60187ee..cd6f084 100644 --- a/cas/src/core/node/Min.cpp +++ b/cas/src/core/node/Min.cpp @@ -8,39 +8,39 @@ CAS_NAMESPACE -Min::Min(std::vector expressions) +Min::Min(std::vector expressions) : NaryExpression({ExpressionType::MIN, "minimum", "min"}, std::move(expressions)) {} double Min::evaluate(const VariableMap& variables) { - auto functor = [&](Expression* a, Expression* b) { + auto functor = [&](const ExprPtr& a, const ExprPtr& b) { return a->evaluate(variables) < b->evaluate(variables); }; return (*std::min_element(expressions.begin(), expressions.end(), functor))->evaluate(variables); } -Min* Min::clone() { - std::vector clonedExpressions; +ExprPtr Min::clone() { + std::vector clonedExpressions; clonedExpressions.reserve(expressions.size()); for (auto& expression: expressions) clonedExpressions.push_back(expression->clone()); - return new Min(clonedExpressions); + return Min::from(clonedExpressions); } -Expression* Min::simplified() { +ExprPtr Min::simplified() { if (expressions.size() == 1) return expressions[0]->simplified(); - std::vector simplifiedExpressions; + std::vector simplifiedExpressions; simplifiedExpressions.reserve(expressions.size()); - std::transform(expressions.begin(), expressions.end(), simplifiedExpressions.begin(), [](Expression* expr) { + std::transform(expressions.begin(), expressions.end(), simplifiedExpressions.begin(), [](const ExprPtr& expr) { return expr->simplified(); }); - bool (*isConstant)(Expression*) = [](Expression* expression) { + bool (*isConstant)(const ExprPtr&) = [](const ExprPtr& expression) { return expression->isOfType(ExpressionType::CONSTANT); }; @@ -49,14 +49,14 @@ Expression* Min::simplified() { if (constantCount > 1) { bool allConstant = std::all_of(simplifiedExpressions.begin(), simplifiedExpressions.end(), isConstant); if (allConstant) { - double minElement = (*std::min_element(simplifiedExpressions.begin(), simplifiedExpressions.end(), [](Expression* a, Expression* b) { + double minElement = (*std::min_element(simplifiedExpressions.begin(), simplifiedExpressions.end(), [](const ExprPtr& a, const ExprPtr& b) { return a->evaluate() < b->evaluate(); }))->evaluate(); return Const::n(minElement); } - std::vector reducedExpressions; + std::vector reducedExpressions; reducedExpressions.reserve(expressions.size()); double min = math::POSITIVE_INFINITY; @@ -73,10 +73,10 @@ Expression* Min::simplified() { return reducedExpressions[0]; } - return new Min(reducedExpressions); + return Min::from(reducedExpressions); } - return new Min(simplifiedExpressions); + return Min::from(simplifiedExpressions); } CAS_NAMESPACE_END diff --git a/cas/src/core/node/Mod.cpp b/cas/src/core/node/Mod.cpp index 95259dc..e46653e 100644 --- a/cas/src/core/node/Mod.cpp +++ b/cas/src/core/node/Mod.cpp @@ -9,8 +9,8 @@ CAS_NAMESPACE -Mod::Mod(Expression* dividend, Expression* divisor) - : Expression({ExpressionType::MODULO, "modulo", "mod"}), dividend(dividend), divisor(divisor) { +Mod::Mod(const ExprPtr& dividend, const ExprPtr& divisor) + : Expr({ExpressionType::MODULO, "modulo", "mod"}), dividend(dividend), divisor(divisor) { if (divisor->isOfType(ExpressionType::CONSTANT) && divisor->evaluate() == 0) { throw std::invalid_argument("Divisor cannot be zero"); @@ -20,49 +20,41 @@ Mod::Mod(Expression* dividend, Expression* divisor) this->divisor->setParent(this); } -Mod::~Mod() { - delete dividend; - delete divisor; - - dividend = nullptr; - divisor = nullptr; -} - double Mod::evaluate(const VariableMap& variables) { return std::fmod(dividend->evaluate(variables), divisor->evaluate(variables)); } -bool Mod::_equals(Expression* expression) { - if (this == expression) +bool Mod::_equals(const ExprPtr& expression) { + if (this == expression.get()) return true; if (expression->isOfType(ExpressionType::MODULO)) { - auto* mod = dynamic_cast(expression); + auto* mod = dynamic_cast(expression.get()); return dividend->equals(mod->dividend) && divisor->equals(mod->divisor); } return false; } -Mod* Mod::clone() { - return new Mod(dividend->clone(), divisor->clone()); +ExprPtr Mod::clone() { + return Mod::from(dividend->clone(), divisor->clone()); } -Expression* Mod::simplified() { +ExprPtr Mod::simplified() { if (dividend->isOfType(ExpressionType::CONSTANT) && divisor->isOfType(ExpressionType::CONSTANT)) { if (isWholeNumber(dividend->evaluate()) && isWholeNumber(divisor->evaluate())) { - return new Const(Expression::evaluate()); + return Const::n(Expr::evaluate()); } } if (dividend->isOfType(ExpressionType::CONSTANT) && dividend->evaluate() == 0) { return Const::zero(); } - return new Mod(dividend->simplified(), divisor->simplified()); + return Mod::from(dividend->simplified(), divisor->simplified()); } std::string Mod::latex() { - return fmt::sprintf("\\mod{\\left(%s,%s\\right)}", dividend->latex(), divisor->latex()); + return fmt::sprintf(R"(\mod{\left(%s,%s\right)})", dividend->latex(), divisor->latex()); } std::wstring Mod::stringify() { diff --git a/cas/src/core/node/NaryExpression.cpp b/cas/src/core/node/NaryExpression.cpp index 265b612..139aab5 100644 --- a/cas/src/core/node/NaryExpression.cpp +++ b/cas/src/core/node/NaryExpression.cpp @@ -10,26 +10,19 @@ CAS_NAMESPACE NaryExpression::NaryExpression(const ExpressionProperties& props, - std::vector expressions) - : Expression(props), expressions(std::move(expressions)) { + std::vector expressions) + : Expr(props), expressions(std::move(expressions)) { for (auto& expression: this->expressions) { expression->setParent(this); } } -NaryExpression::~NaryExpression() { - for (auto& expression: expressions) { - delete expression; - expression = nullptr; - } -} - -bool NaryExpression::_equals(Expression* expression) { - if (this == expression) +bool NaryExpression::_equals(const ExprPtr& expression) { + if (this == expression.get()) return true; if (expression->isOfType(properties.getType())) { - auto* function = dynamic_cast(expression); + auto* function = dynamic_cast(expression.get()); if (expressions.size() != function->expressions.size()) return false; diff --git a/cas/src/core/node/Negate.cpp b/cas/src/core/node/Negate.cpp index 79a891b..6e5288e 100644 --- a/cas/src/core/node/Negate.cpp +++ b/cas/src/core/node/Negate.cpp @@ -10,32 +10,32 @@ CAS_NAMESPACE -Negate::Negate(Expression* expression) +Negate::Negate(const ExprPtr& expression) : UnaryExpression({ExpressionType::NEGATE, "negate", "neg"}, expression) {} double Negate::evaluate(const VariableMap& variables) { return -argument->evaluate(variables); } -bool Negate::_equals(Expression* expr) { - auto* negate = dynamic_cast(expr); +bool Negate::_equals(const ExprPtr& expr) { + auto* negate = dynamic_cast(expr.get()); return argument->equals(negate->argument); } -Negate* Negate::clone() { - return new Negate(argument->clone()); +ExprPtr Negate::clone() { + return Negate::from(argument->clone()); } -Negate* Negate::_derivative(char var) { - return new Negate(argument->derivative(var)); +ExprPtr Negate::_derivative(char var) { + return Negate::from(argument->derivative(var)); } -Expression* Negate::simplified() { +ExprPtr Negate::simplified() { if (argument->isOfType(ExpressionType::CONSTANT)) { - return Const::n(Expression::evaluate()); + return Const::n(Expr::evaluate()); } if (argument->isOfType(ExpressionType::NEGATE)) { - auto* negate = dynamic_cast(argument); + auto* negate = dynamic_cast(argument.get()); return negate->argument->simplified(); } diff --git a/cas/src/core/node/Operator.cpp b/cas/src/core/node/Operator.cpp index d1a9ab1..8db557d 100644 --- a/cas/src/core/node/Operator.cpp +++ b/cas/src/core/node/Operator.cpp @@ -7,34 +7,28 @@ CAS_NAMESPACE -Operator::Operator(const ExpressionProperties& props, double neutral, char symbol, std::vector expressions) - : Expression(props), neutral(neutral), symbol(symbol), expressions(std::move(expressions)) { +Operator::Operator(const ExpressionProperties& props, double neutral, char symbol, std::vector expressions) + : Expr(props), neutral(neutral), symbol(symbol), expressions(std::move(expressions)) { for (auto& expression: this->expressions) expression->setParent(this); } -Operator::~Operator() { - for (auto* expression: expressions) { - delete expression; - } -} - double Operator::evaluate(const VariableMap& variables) { double result = neutral; - for (auto* expression: expressions) + for (auto& expression: expressions) result = operate(result, expression->evaluate(variables)); return result; } -bool Operator::_equals(Expression* expression) { - if (this == expression) +bool Operator::_equals(const ExprPtr& expression) { + if (this == expression.get()) return true; if (!isOfSameType(expression)) return false; - auto* op = dynamic_cast(expression); + auto* op = dynamic_cast(expression.get()); if (expressions.size() != op->expressions.size() || symbol != op->getSymbol()) return false; diff --git a/cas/src/core/node/Power.cpp b/cas/src/core/node/Power.cpp index 28ce1fd..9b8badb 100644 --- a/cas/src/core/node/Power.cpp +++ b/cas/src/core/node/Power.cpp @@ -6,102 +6,79 @@ #include "cas/node/Const.h" #include "cas/node/Divide.h" #include "cas/node/Ln.h" -#include "cas/node/Product.h" +#include "cas/node/Prod.h" #include "cas/node/Sum.h" #include "fmt/printf.h" #include "fmt/xchar.h" CAS_NAMESPACE -Power::Power(const ExpressionProperties& props, Expression* base, Expression* exponent) - : Expression(props), base(base), exponent(exponent) { - this->base->setParent(this); - this->exponent->setParent(this); +Power::Power(const ExpressionProperties& props, const ExprPtr& base, const ExprPtr& exponent) + : Expr(props), base(base), exponent(exponent) { + this->base->setParent(this); + this->exponent->setParent(this); } -Power::Power(Expression* base, Expression* exponent) +Power::Power(const ExprPtr& base, const ExprPtr& exponent) : Power({ExpressionType::POWER, "power", "pow"}, base, exponent) {} -Power::Power(Expression* base, double exponent) - : Power({ExpressionType::POWER, "power", "pow"}, base, new Const(exponent)) {} - -Power::~Power() { - delete base; - delete exponent; - - base = nullptr; - exponent = nullptr; -} +Power::Power(const ExprPtr& base, double exponent) + : Power({ExpressionType::POWER, "power", "pow"}, base, Const::n(exponent)) {} double Power::evaluate(const VariableMap& variables) { return pow(base->evaluate(variables), exponent->evaluate(variables)); } -bool Power::_equals(Expression* expression) { - auto* power = dynamic_cast(expression); +bool Power::_equals(const ExprPtr& expression) { + auto* power = dynamic_cast(expression.get()); return base->equals(power->base) && exponent->equals(power->exponent); } -Power* Power::clone() { - return new Power(base->clone(), exponent->clone()); +ExprPtr Power::clone() { + return Power::from(base->clone(), exponent->clone()); } -Expression* Power::_derivative(char var) { +ExprPtr Power::_derivative(char var) { bool baseIsNumber = base->isOfType(ExpressionType::CONSTANT); bool exponentIsNumber = exponent->isOfType(ExpressionType::CONSTANT); if (baseIsNumber && exponentIsNumber)// case b^k, where b and k are both numbers (constants) - return new Const(0); + return Const::zero(); if (!baseIsNumber && exponentIsNumber)// case [ f(x) ]^k, where k is a constant { - auto* k = dynamic_cast(exponent); - - return new Product({ - // k*f^(k-1)*f' - exponent->clone(), // k - base->derivative(var), // f' - new Power( // f^(k - 1) - base->clone(), // f - new Const(k->getValue() - 1)// k - 1 - ) // end f^(k - 1) - }); // end k*f^(k-1)*f' + auto* k = dynamic_cast(exponent.get()); + + // k*f^(k-1)*f' + return Prod::from({ + exponent->clone(), // k + base->derivative(var), // f' + base->clone()->power(Const::n(k->getValue() - 1))// f^(k - 1) + }); } if (baseIsNumber)// case k^[ f(x) ], where k is a constant { - return new Product({ - // k^f * lnk * f' + // k^f * lnk * f' + return Prod::from({ this->clone(), // a^f exponent->derivative(var),// f' - new Ln(base) // lnk - }); // end k^f * lnk * f' + Ln::from(base) // lnk + }); } // otherwise: case [ f(x) ]^[ g(x) ], here we use the generalized power rule - return new Product({ - // [f(x)]^[g(x)] * ( g'*lnf + g*f'/f ) - this->clone(),// [f(x)] ^ [g(x)] - new Sum({ - // g'*lnf + g*f'/f - new Product({ - // g' * lnf - exponent->derivative(var),// g' - new Ln(base) // lnf - }), // end g' * lnf - new Product({ - // g * f' * 1/f - exponent->clone(), // g - new Divide( // f'/f - base->derivative(var),// f' - base->clone() // f - ) // end f'/f - }) // end g*f'/f - }) // end g'*lnf + g*f'/f - }); // end [f(x)]^[g(x)] * ( g'*lnf + g*f'/f) + // [f(x)]^[g(x)] * ( g'*lnf + g*f'/f ) + return Prod::from({this->clone(),// [f(x)] ^ [g(x)] + Sum::from({ // g'*lnf + g*f'/f + exponent->derivative(var) + ->multiply(Ln::from(base)),// g'*lnf // end g' * lnf + exponent->clone() + ->multiply(base->derivative(var) + ->divide(base->clone()))})});// g*f'/f } -Expression* Power::simplified() { +ExprPtr Power::simplified() { if (exponent->isOfType(ExpressionType::CONSTANT)) { double exponentValue = exponent->evaluate(); if (exponentValue == 0) { @@ -113,34 +90,34 @@ Expression* Power::simplified() { if (base->isOfType(ExpressionType::CONSTANT)) { if (isWholeNumber(base->evaluate()) && isWholeNumber(exponent->evaluate())) { - double value = Expression::evaluate(); + double value = Expr::evaluate(); if (value < 10000.) return Const::n(value); } } } if (base->isOfType(ExpressionType::DIVIDE)) { - auto* frac = dynamic_cast(base); + auto* frac = dynamic_cast(base.get()); return frac->getDividend()->simplified()->power(exponent->simplified())->divide(frac->getDivisor()->simplified()->power(exponent->simplified())); } if (base->isOfType(ExpressionType::POWER)) { - auto* pow = dynamic_cast(base); + auto* pow = dynamic_cast(base.get()); return pow->getBase()->simplified()->power(pow->getExponent()->simplified()->multiply(exponent->simplified())); } if (base->isOfType(ExpressionType::PRODUCT)) { - auto* prod = dynamic_cast(base); + auto* prod = dynamic_cast(base.get()); - std::vector newFactors; + std::vector newFactors; newFactors.reserve(prod->getExpressionsSize()); - for (auto* factor: prod->getExpressions()) { + for (auto& factor: prod->getExpressions()) { newFactors.push_back(factor->simplified() ->power(exponent->simplified())); } - return new Product(newFactors); + return Prod::from(newFactors); } - if (instanceof (base)) { - auto* log = dynamic_cast(base); + if (instanceof (base.get())) { + auto* log = dynamic_cast(base.get()); if (log->getBase()->equals(base)) { return log->getArgument()->simplified(); } @@ -154,7 +131,7 @@ bool Power::baseNeedsParentheses() { } bool Power::exponentNeedsParentheses() { - return exponent->isOfType(ExpressionType::DIVIDE) || exponent->isOfType(ExpressionType::POWER) || instanceof (exponent); + return exponent->isOfType(ExpressionType::DIVIDE) || exponent->isOfType(ExpressionType::POWER) || instanceof (exponent.get()); } std::string Power::latex() { diff --git a/cas/src/core/node/Product.cpp b/cas/src/core/node/Product.cpp index 23c34ff..e9188bf 100644 --- a/cas/src/core/node/Product.cpp +++ b/cas/src/core/node/Product.cpp @@ -2,68 +2,67 @@ // Created by Abd-El-Aziz Zayed on 2022-09-01. // -#include "cas/node/Product.h" #include "cas/node/Const.h" +#include "cas/node/Prod.h" #include "cas/node/Sum.h" #include CAS_NAMESPACE -Product::Product(const std::vector& expressions) +Prod::Prod(const std::vector& expressions) : Operator({ExpressionType::PRODUCT, "product", "prod"}, 1.0, '*', expressions) {} -Product* Product::clone() { - std::vector clonedExpressions; +ExprPtr Prod::clone() { + std::vector clonedExpressions; clonedExpressions.reserve(expressions.size()); for (auto& expression: expressions) clonedExpressions.push_back(expression->clone()); - return new Product{clonedExpressions}; + return Prod::from({clonedExpressions}); } -Expression* Product::_derivative(char var) { - std::vector differentiatedExpressions; +ExprPtr Prod::_derivative(char var) { + std::vector differentiatedExpressions; differentiatedExpressions.reserve(expressions.size()); for (size_t i = 0; i < expressions.size(); i++) { - std::vector products; + std::vector products; products.reserve(expressions.size()); for (size_t j = 0; j < expressions.size(); j++) { - Expression* exp = expressions[j]; - Expression* prod = i == j ? exp->derivative(var) : exp->clone(); + ExprPtr exp = expressions[j]; + ExprPtr prod = i == j ? exp->derivative(var) : exp->clone(); products.push_back(prod); } - differentiatedExpressions.push_back(new Product{products}); + differentiatedExpressions.push_back(Prod::from({products})); } - return new Sum{differentiatedExpressions}; + return Sum::from({differentiatedExpressions}); } -Expression* Product::simplified() { +ExprPtr Prod::simplified() { // TODO: simplify // If there is only one expression, return it if (expressions.size() == 1) return expressions[0]->simplified(); - std::vector simplifiedExpressions; + std::vector simplifiedExpressions; simplifiedExpressions.reserve(expressions.size()); double constant = 1.0; for (auto& expression: expressions) { - Expression* x = expression->simplified(); + ExprPtr x = expression->simplified(); if (x->isOfType(ExpressionType::CONSTANT)) { double value = x->evaluate(); if (value == 0) { - delete x; return Const::zero(); } constant *= value; continue; } else if (x->isOfType(ExpressionType::PRODUCT)) { - auto* product = dynamic_cast(x); + auto* product = dynamic_cast(x.get()); for (auto& exp: product->expressions) simplifiedExpressions.push_back(exp); continue; @@ -77,24 +76,24 @@ Expression* Product::simplified() { if (simplifiedExpressions.size() == 1) return simplifiedExpressions[0]; - std::sort(simplifiedExpressions.begin(), simplifiedExpressions.end(), [](Expression* a, Expression* b) { + std::sort(simplifiedExpressions.begin(), simplifiedExpressions.end(), [](const ExprPtr& a, const ExprPtr& b) { return a->lessThan(b); }); - return new Product{simplifiedExpressions}; + return Prod::from({simplifiedExpressions}); } -bool Product::needsParentheses(Expression* expression) { +bool Prod::needsParentheses(const ExprPtr& expression) { return expression->getProperties().getType() == ExpressionType::SUM; } -std::string Product::latex() { +std::string Prod::latex() { if (expressions.empty()) return ""; std::stringstream ss; for (size_t i = 0; i < expressions.size(); i++) { - Expression* exp = expressions[i]; + ExprPtr exp = expressions[i]; bool needsParens = needsParentheses(exp); if (needsParens) @@ -113,14 +112,14 @@ std::string Product::latex() { return ss.str(); } -std::wstring Product::stringify() { +std::wstring Prod::stringify() { if (expressions.empty()) return L""; std::wstringstream ss; for (size_t i = 0; i < expressions.size(); i++) { - Expression* exp = expressions[i]; + ExprPtr exp = expressions[i]; bool needsParens = needsParentheses(exp); if (needsParens) diff --git a/cas/src/core/node/Root.cpp b/cas/src/core/node/Root.cpp index 46f2c96..7f6070e 100644 --- a/cas/src/core/node/Root.cpp +++ b/cas/src/core/node/Root.cpp @@ -12,24 +12,24 @@ CAS_NAMESPACE -Root::Root(const ExpressionProperties& props, Expression* base, Expression* root) +Root::Root(const ExpressionProperties& props, const ExprPtr& base, const ExprPtr& root) : Power(props, base, root) {} -Root::Root(Expression* base, Expression* root) +Root::Root(const ExprPtr& base, const ExprPtr& root) : Root({ExpressionType::ROOT, "root", "root"}, base, root) {} -Root::Root(Expression* base, double root) - : Root(base, new Const(root)) {} +Root::Root(const ExprPtr& base, double root) + : Root(base, Const::n(root)) {} double Root::evaluate(const VariableMap& variables) { return pow(base->evaluate(variables), 1.0 / exponent->evaluate(variables)); } -Root* Root::clone() { - return new Root(base->clone(), exponent->clone()); +ExprPtr Root::clone() { + return Root::from(base->clone(), exponent->clone()); } -Expression* Root::simplified() { +ExprPtr Root::simplified() { if (exponent->isOfType(ExpressionType::CONSTANT)) { double root = exponent->evaluate(); if (root == 1) @@ -40,7 +40,7 @@ Expression* Root::simplified() { return base->simplified()->cbrt(); } - return new Root(base->simplified(), exponent->simplified()); + return Root::from(base->simplified(), exponent->simplified()); } std::string Root::latex() { diff --git a/cas/src/core/node/Round.cpp b/cas/src/core/node/Round.cpp index 5ceeaa8..74b5861 100644 --- a/cas/src/core/node/Round.cpp +++ b/cas/src/core/node/Round.cpp @@ -7,20 +7,20 @@ CAS_NAMESPACE -Round::Round(Expression* argument) +Round::Round(const ExprPtr& argument) : BracketExpression({ExpressionType::ROUND, "round", "round"}, argument, L"\u230A", L"\u2309", "\\lfloor", "\\rceil") {} double Round::evaluate(const VariableMap& variables) { return std::round(argument->evaluate(variables)); } -Round* Round::clone() { - return new Round(argument->clone()); +ExprPtr Round::clone() { + return Round::from(argument->clone()); } -Expression* Round::simplified() { +ExprPtr Round::simplified() { if (argument->isOfType(ExpressionType::CONSTANT)) { - return Const::n(Expression::evaluate()); + return Const::n(Expr::evaluate()); } if (argument->isOfType(ExpressionType::ROUND)) { return argument->simplified(); diff --git a/cas/src/core/node/Sign.cpp b/cas/src/core/node/Sign.cpp index 2190703..4bfbcd4 100644 --- a/cas/src/core/node/Sign.cpp +++ b/cas/src/core/node/Sign.cpp @@ -10,7 +10,7 @@ CAS_NAMESPACE -Sign::Sign(Expression* argument) +Sign::Sign(const ExprPtr& argument) : UnaryExpression({ExpressionType::SIGN, "sign", "sign"}, argument) {} double Sign::evaluate(const VariableMap& variables) { @@ -19,30 +19,30 @@ double Sign::evaluate(const VariableMap& variables) { : 0; } -bool Sign::_equals(Expression* expression) { - if (this == expression) +bool Sign::_equals(const ExprPtr& expression) { + if (this == expression.get()) return true; if (expression->isOfType(ExpressionType::SIGN)) { - auto* sign = dynamic_cast(expression); + auto* sign = dynamic_cast(expression.get()); return argument->equals(sign->argument); } return false; } -Sign* Sign::clone() { - return new Sign(argument->clone()); +ExprPtr Sign::clone() { + return Sign::from(argument->clone()); } -Expression* Sign::simplified() { +ExprPtr Sign::simplified() { if (argument->isOfType(ExpressionType::CONSTANT)) { - return new Const(Expression::evaluate()); + return Const::n(Expr::evaluate()); } if (argument->isOfType(ExpressionType::SIGN)) { return argument->simplified(); } if (argument->isOfType(ExpressionType::NEGATE)) { - auto* negate = dynamic_cast(argument); + auto* negate = dynamic_cast(argument.get()); return negate->getArgument()->simplified()->sign()->negate(); } return argument->simplified()->sign(); diff --git a/cas/src/core/node/Sqrt.cpp b/cas/src/core/node/Sqrt.cpp index b85e8c1..a62345b 100644 --- a/cas/src/core/node/Sqrt.cpp +++ b/cas/src/core/node/Sqrt.cpp @@ -5,40 +5,42 @@ #include "cas/node/Sqrt.h" #include "cas/node/Const.h" #include "cas/node/Divide.h" -#include "cas/node/Product.h" +#include "cas/node/Prod.h" #include "cas/util/StringUtils.h" #include "fmt/printf.h" #include "fmt/xchar.h" CAS_NAMESPACE -Sqrt::Sqrt(Expression* base) - : Root({ExpressionType::SQUARE_ROOT, "square_root", "sqrt"}, base, new Const(2)) {} +Sqrt::Sqrt(const ExprPtr& base) + : Root({ExpressionType::SQUARE_ROOT, "square_root", "sqrt"}, base, Const::n(2)) {} double Sqrt::evaluate(const VariableMap& variables) { return std::sqrt(base->evaluate(variables)); } -Sqrt* Sqrt::clone() { - return new Sqrt(base->clone()); +ExprPtr Sqrt::clone() { + return Sqrt::from(base->clone()); } -Expression* Sqrt::_derivative(char var) { - return new Divide( - base->derivative(var), - new Product({new Const(2), clone()})); +ExprPtr Sqrt::_derivative(char var) { + + // sqrt( f )' = f' / (2 * sqrt( f )) + return Divide::from( + base->derivative(var), // f' + Const::n(2)->multiply(clone()));// 2 * sqrt( f ) } -Expression* Sqrt::simplified() { +ExprPtr Sqrt::simplified() { if (base->isOfType(ExpressionType::CONSTANT)) { - double sqrt = Expression::evaluate(); + double sqrt = Expr::evaluate(); if (isWholeNumber(sqrt)) - return new Const(sqrt); + return Const::from(sqrt); else return clone(); } if (base->isOfType(ExpressionType::POWER)) { - auto* power = dynamic_cast(base); + auto* power = dynamic_cast(base.get()); if (power->getExponent()->isOfType(ExpressionType::CONSTANT)) { double exponent = power->getExponent()->evaluate(); if (exponent == 2) diff --git a/cas/src/core/node/Sum.cpp b/cas/src/core/node/Sum.cpp index 32489d6..e64686e 100644 --- a/cas/src/core/node/Sum.cpp +++ b/cas/src/core/node/Sum.cpp @@ -4,58 +4,57 @@ #include "cas/node/Sum.h" #include "cas/node/Const.h" -#include #include +#include CAS_NAMESPACE -Sum::Sum(const std::vector& expressions) +Sum::Sum(const std::vector& expressions) : Operator({ExpressionType::SUM, "summation", "sum"}, 0.0, '+', expressions) {} -Sum* Sum::clone() { - std::vector clonedExpressions; +ExprPtr Sum::clone() { + std::vector clonedExpressions; clonedExpressions.reserve(expressions.size()); for (auto& expression: expressions) clonedExpressions.push_back(expression->clone()); - return new Sum{clonedExpressions}; + return Sum::from(clonedExpressions); } -Sum* Sum::_derivative(char var) { - std::vector differentiatedExpressions; +ExprPtr Sum::_derivative(char var) { + std::vector differentiatedExpressions; differentiatedExpressions.reserve(expressions.size()); for (auto& expression: expressions) differentiatedExpressions.push_back(expression->derivative(var)); - return new Sum{differentiatedExpressions}; + return Sum::from(differentiatedExpressions); } -Expression* Sum::simplified() { +ExprPtr Sum::simplified() { // TODO: simplify // If there is only one expression, return it if (expressions.size() == 1) return expressions[0]->simplified(); - std::vector simplifiedExpressions; + std::vector simplifiedExpressions; simplifiedExpressions.reserve(expressions.size()); double constant = 0.0; for (auto& expression: expressions) { - Expression* x = expression->simplified(); + ExprPtr x = expression->simplified(); if (x->isOfType(ExpressionType::CONSTANT)) { double value = x->evaluate(); if (value == 0.0) { - delete x; continue; } constant += value; continue; } else if (x->isOfType(ExpressionType::SUM)) { - auto* sum = dynamic_cast(x); + auto* sum = dynamic_cast(x.get()); for (auto& exp: sum->expressions) simplifiedExpressions.push_back(exp); continue; @@ -70,7 +69,7 @@ Expression* Sum::simplified() { return simplifiedExpressions[0]; std::sort(simplifiedExpressions.begin(), simplifiedExpressions.end()); - return new Sum{simplifiedExpressions}; + return Sum::from(simplifiedExpressions); } std::string Sum::latex() { @@ -80,7 +79,7 @@ std::string Sum::latex() { std::stringstream ss; for (size_t i = 0; i < expressions.size(); i++) { - Expression* exp = expressions[i]; + ExprPtr exp = expressions[i]; bool needsParens = needsParentheses(exp); if (needsParens) @@ -104,7 +103,7 @@ std::wstring Sum::stringify() { std::wstringstream ss; for (size_t i = 0; i < expressions.size(); i++) { - Expression* exp = expressions[i]; + ExprPtr exp = expressions[i]; bool needsParens = needsParentheses(exp); if (needsParens) diff --git a/cas/src/core/node/UnaryExpression.cpp b/cas/src/core/node/UnaryExpression.cpp index 5713aa8..d2fdbc6 100644 --- a/cas/src/core/node/UnaryExpression.cpp +++ b/cas/src/core/node/UnaryExpression.cpp @@ -11,24 +11,19 @@ CAS_NAMESPACE -UnaryExpression::UnaryExpression(const ExpressionProperties& properties, Expression* argument) - : Expression(properties), argument(argument) { +UnaryExpression::UnaryExpression(const ExpressionProperties& properties, const ExprPtr& argument) + : Expr(properties), argument(argument) { this->argument->setParent(this); } -UnaryExpression::~UnaryExpression() { - delete argument; - argument = nullptr; -} - -Expression* UnaryExpression::derivative(char var) { +ExprPtr UnaryExpression::derivative(char var) { if (argument->isOfType(ExpressionType::CONSTANT)) - return new Const(0); + return Const::zero(); if (argument->isOfType(ExpressionType::VARIABLE)) { - auto* variable = dynamic_cast(argument); + auto* variable = dynamic_cast(argument.get()); if (variable->getSymbol() != var) - return new Const(0); + return Const::zero(); } return _derivative(var); diff --git a/cas/src/core/node/Var.cpp b/cas/src/core/node/Var.cpp index b54b515..f97c6c4 100644 --- a/cas/src/core/node/Var.cpp +++ b/cas/src/core/node/Var.cpp @@ -10,10 +10,10 @@ CAS_NAMESPACE Var::Var(char variable) - : Expression({ExpressionType::VARIABLE, "variable", "var"}), symbol(variable) {} + : Expr({ExpressionType::VARIABLE, "variable", "var"}), symbol(variable) {} -Var* Var::clone() { - return new Var(symbol); +ExprPtr Var::clone() { + return Var::from(symbol); } double Var::evaluate(const VariableMap& variables) { @@ -22,17 +22,17 @@ double Var::evaluate(const VariableMap& variables) { return variables.at(symbol); } -bool Var::_equals(Expression* expression) { - auto* var = dynamic_cast(expression); +bool Var::_equals(const ExprPtr& expression) { + auto* var = dynamic_cast(expression.get()); return var->getSymbol() == symbol; } -Expression* Var::_derivative(char var) { +ExprPtr Var::_derivative(char var) { double derivative = symbol == var ? 1.0 : 0.0; - return new Const{derivative}; + return Const::n(derivative); } -Var* Var::simplified() { +ExprPtr Var::simplified() { return clone(); } diff --git a/cas/src/core/node/trig/ArcCos.cpp b/cas/src/core/node/trig/ArcCos.cpp index ba0d80f..d3a59ce 100644 --- a/cas/src/core/node/trig/ArcCos.cpp +++ b/cas/src/core/node/trig/ArcCos.cpp @@ -11,18 +11,18 @@ CAS_NAMESPACE -ArcCos::ArcCos(Expression* argument) +ArcCos::ArcCos(const ExprPtr& argument) : InverseTrigExpression({ExpressionType::ARC_COS, "arccos", "acos"}, argument) {} double ArcCos::evaluate(const VariableMap& variables) { return std::acos(argument->evaluate(variables)); } -ArcCos* ArcCos::clone() { - return new ArcCos(argument->clone()); +ExprPtr ArcCos::clone() { + return ArcCos::from(argument->clone()); } -Expression* ArcCos::_derivative(char var) { +ExprPtr ArcCos::_derivative(char var) { return argument->derivative(var) ->negate() ->divide(Const::one() @@ -30,7 +30,7 @@ Expression* ArcCos::_derivative(char var) { ->sqrt()); } -Expression* ArcCos::simplified() { +ExprPtr ArcCos::simplified() { if (argument->isOfType(ExpressionType::CONSTANT)) { if (argument->evaluate() == 1) return Const::zero(); diff --git a/cas/src/core/node/trig/ArcCot.cpp b/cas/src/core/node/trig/ArcCot.cpp index 1baf0da..9bf7c4c 100644 --- a/cas/src/core/node/trig/ArcCot.cpp +++ b/cas/src/core/node/trig/ArcCot.cpp @@ -7,29 +7,29 @@ #include "cas/node/Divide.h" #include "cas/node/Negate.h" #include "cas/node/Power.h" -#include "cas/node/Product.h" +#include "cas/node/Prod.h" #include "cas/node/Sum.h" CAS_NAMESPACE -ArcCot::ArcCot(Expression* argument) +ArcCot::ArcCot(const ExprPtr& argument) : InverseTrigExpression({ExpressionType::ARC_COT, "arccot", "acot"}, argument) {} double ArcCot::evaluate(const VariableMap& variables) { return std::atan(1 / argument->evaluate(variables)); } -ArcCot* ArcCot::clone() { - return new ArcCot(argument->clone()); +ExprPtr ArcCot::clone() { + return ArcCot::from(argument->clone()); } -Expression* ArcCot::_derivative(char var) { - return new Divide( +ExprPtr ArcCot::_derivative(char var) { + return Divide::from( argument->derivative(var)->negate(), - new Sum({argument->clone()->power(2), new Const(1)})); + Sum::from({argument->clone()->power(2), Const::one()})); } -Expression* ArcCot::simplified() { +ExprPtr ArcCot::simplified() { if (argument->isOfType(ExpressionType::CONSTANT)) { if (argument->evaluate() == 1) return Const::PI()->divide(4); diff --git a/cas/src/core/node/trig/ArcCsc.cpp b/cas/src/core/node/trig/ArcCsc.cpp index 6f9524d..f8a8fa8 100644 --- a/cas/src/core/node/trig/ArcCsc.cpp +++ b/cas/src/core/node/trig/ArcCsc.cpp @@ -7,24 +7,24 @@ #include "cas/node/Const.h" #include "cas/node/Divide.h" #include "cas/node/Negate.h" -#include "cas/node/Product.h" +#include "cas/node/Prod.h" #include "cas/node/Sqrt.h" #include "cas/node/Sum.h" CAS_NAMESPACE -ArcCsc::ArcCsc(Expression* argument) +ArcCsc::ArcCsc(const ExprPtr& argument) : InverseTrigExpression({ExpressionType::ARC_CSC, "arccsc", "acsc"}, argument) {} double ArcCsc::evaluate(const VariableMap& variables) { return std::asin(1 / argument->evaluate(variables)); } -ArcCsc* ArcCsc::clone() { - return new ArcCsc(argument->clone()); +ExprPtr ArcCsc::clone() { + return ArcCsc::from(argument->clone()); } -Expression* ArcCsc::_derivative(char var) { +ExprPtr ArcCsc::_derivative(char var) { return argument->derivative(var) ->negate() ->divide(argument->clone() @@ -35,7 +35,7 @@ Expression* ArcCsc::_derivative(char var) { ->sqrt())); } -Expression* ArcCsc::simplified() { +ExprPtr ArcCsc::simplified() { if (argument->isOfType(ExpressionType::CONSTANT)) { if (argument->evaluate() == 1) return Const::PI()->divide(2); diff --git a/cas/src/core/node/trig/ArcSec.cpp b/cas/src/core/node/trig/ArcSec.cpp index c5c02f9..208b49c 100644 --- a/cas/src/core/node/trig/ArcSec.cpp +++ b/cas/src/core/node/trig/ArcSec.cpp @@ -8,24 +8,24 @@ #include "cas/node/Divide.h" #include "cas/node/Negate.h" #include "cas/node/Power.h" -#include "cas/node/Product.h" +#include "cas/node/Prod.h" #include "cas/node/Sqrt.h" #include "cas/node/Sum.h" CAS_NAMESPACE -ArcSec::ArcSec(Expression* argument) +ArcSec::ArcSec(const ExprPtr& argument) : InverseTrigExpression({ExpressionType::ARC_SEC, "arcsec", "asec"}, argument) {} double ArcSec::evaluate(const VariableMap& variables) { return std::acos(1.0 / argument->evaluate(variables)); } -ArcSec* ArcSec::clone() { - return new ArcSec(argument->clone()); +ExprPtr ArcSec::clone() { + return ArcSec::from(argument->clone()); } -Expression* ArcSec::_derivative(char var) { +ExprPtr ArcSec::_derivative(char var) { return argument->derivative(var) ->divide(argument->clone() ->abs() @@ -35,7 +35,7 @@ Expression* ArcSec::_derivative(char var) { ->sqrt())); } -Expression* ArcSec::simplified() { +ExprPtr ArcSec::simplified() { if (argument->isOfType(ExpressionType::CONSTANT)) { if (argument->evaluate() == 1) return Const::zero(); diff --git a/cas/src/core/node/trig/ArcSin.cpp b/cas/src/core/node/trig/ArcSin.cpp index 2d488b1..9a3123e 100644 --- a/cas/src/core/node/trig/ArcSin.cpp +++ b/cas/src/core/node/trig/ArcSin.cpp @@ -11,23 +11,24 @@ CAS_NAMESPACE -ArcSin::ArcSin(Expression* argument) +ArcSin::ArcSin(const ExprPtr& argument) : InverseTrigExpression({ExpressionType::ARC_SIN, "arcsin", "asin"}, argument) {} double ArcSin::evaluate(const VariableMap& variables) { return std::asin(argument->evaluate(variables)); } -ArcSin* ArcSin::clone() { - return new ArcSin(argument->clone()); +ExprPtr ArcSin::clone() { + return ArcSin::from(argument->clone()); } -Expression* ArcSin::_derivative(char var) { - std::vector terms = {new Const(1), argument->clone()->power(2)->negate()}; - return new Divide(argument->derivative(var), new Sqrt(new Sum(terms))); +ExprPtr ArcSin::_derivative(char var) { + // arcsin( f )' = f' / sqrt(1 - f^2) + std::vector terms = {Const::one(), argument->clone()->power(2)->negate()}; + return argument->derivative(var)->divide(Sum::from(terms)->sqrt()); } -Expression* ArcSin::simplified() { +ExprPtr ArcSin::simplified() { if (argument->isOfType(ExpressionType::CONSTANT)) { if (argument->evaluate() == 0) return Const::zero(); diff --git a/cas/src/core/node/trig/ArcTan.cpp b/cas/src/core/node/trig/ArcTan.cpp index 2f4d044..327e2e1 100644 --- a/cas/src/core/node/trig/ArcTan.cpp +++ b/cas/src/core/node/trig/ArcTan.cpp @@ -11,24 +11,24 @@ CAS_NAMESPACE -ArcTan::ArcTan(Expression* argument) +ArcTan::ArcTan(const ExprPtr& argument) : InverseTrigExpression({ExpressionType::ARC_TAN, "arctan", "atan"}, argument) {} double ArcTan::evaluate(const VariableMap& variables) { return std::atan(argument->evaluate(variables)); } -ArcTan* ArcTan::clone() { - return new ArcTan(argument->clone()); +ExprPtr ArcTan::clone() { + return ArcTan::from(argument->clone()); } -Expression* ArcTan::_derivative(char var) { - return new Divide( +ExprPtr ArcTan::_derivative(char var) { + return Divide::from( argument->derivative(var), - new Sum({new Const(1), argument->clone()->power(2)})); + Sum::from({Const::one(), argument->clone()->power(2)})); } -Expression* ArcTan::simplified() { +ExprPtr ArcTan::simplified() { if (argument->isOfType(ExpressionType::CONSTANT)) { if (argument->evaluate() == 0) return Const::zero(); diff --git a/cas/src/core/node/trig/Cos.cpp b/cas/src/core/node/trig/Cos.cpp index a381417..8bdc5d5 100644 --- a/cas/src/core/node/trig/Cos.cpp +++ b/cas/src/core/node/trig/Cos.cpp @@ -6,39 +6,42 @@ #include "cas/node/Const.h" #include "cas/node/Divide.h" #include "cas/node/Negate.h" -#include "cas/node/Product.h" +#include "cas/node/Prod.h" #include "cas/node/Sqrt.h" #include "cas/node/trig/ArcCos.h" #include "cas/node/trig/Sin.h" CAS_NAMESPACE -Cos::Cos(Expression* argument) : TrigExpression({ExpressionType::COS, "cosine", "cos"}, argument) {} +Cos::Cos(const ExprPtr& argument) : TrigExpression({ExpressionType::COS, "cosine", "cos"}, argument) {} double Cos::evaluate(const VariableMap& variables) { return std::cos(argument->evaluate(variables)); } -Cos* Cos::clone() { - return new Cos(argument->clone()); +ExprPtr Cos::clone() { + return Cos::from(argument->clone()); } -Expression* Cos::_derivative(char variable) { - return new Negate(argument->clone()->sin()->multiply(argument->derivative(variable))); +ExprPtr Cos::_derivative(char variable) { + return argument->clone() + ->sin() + ->multiply(argument->derivative(variable)) + ->negate(); } -Expression* Cos::simplified() { +ExprPtr Cos::simplified() { if (argument->isOfType(ExpressionType::CONSTANT)) { double value = argument->evaluate(); if (unitCircle.contains(value)) return unitCircle.at(value).cos->clone(); } if (argument->isOfType(ExpressionType::NEGATE)) { - auto* negate = dynamic_cast(argument); + auto* negate = dynamic_cast(argument.get()); return negate->getArgument()->simplified()->cos(); } if (argument->isOfType(ExpressionType::ARC_COS)) { - auto* arcCos = dynamic_cast(argument); + auto* arcCos = dynamic_cast(argument.get()); return arcCos->getArgument()->simplified(); } diff --git a/cas/src/core/node/trig/Cot.cpp b/cas/src/core/node/trig/Cot.cpp index 59318c4..91a95fc 100644 --- a/cas/src/core/node/trig/Cot.cpp +++ b/cas/src/core/node/trig/Cot.cpp @@ -6,44 +6,46 @@ #include "cas/node/Const.h" #include "cas/node/Negate.h" #include "cas/node/Power.h" -#include "cas/node/Product.h" +#include "cas/node/Prod.h" #include "cas/node/trig/ArcCot.h" #include "cas/node/trig/Csc.h" #include "cas/node/trig/Sec.h" CAS_NAMESPACE -Cot::Cot(Expression* argument) : TrigExpression({ExpressionType::COT, "cotangent", "cot"}, argument) {} +Cot::Cot(const ExprPtr& argument) : TrigExpression({ExpressionType::COT, "cotangent", "cot"}, argument) {} double Cot::evaluate(const VariableMap& variables) { return 1.0 / std::tan(argument->evaluate(variables)); } -Cot* Cot::clone() { - return new Cot(argument->clone()); +ExprPtr Cot::clone() { + return Cot::from(argument->clone()); } -Expression* Cot::_derivative(char variable) { - return new Negate(argument->clone() - ->csc() - ->power(2) - ->multiply(argument->derivative(variable))); +ExprPtr Cot::_derivative(char variable) { + // cot( f )' = -csc( f )^2 * f' + return argument->clone() + ->csc() + ->power(2) + ->multiply(argument->derivative(variable)) + ->negate(); } -Expression* Cot::simplified() { +ExprPtr Cot::simplified() { if (argument->isOfType(ExpressionType::CONSTANT)) { double value = argument->evaluate(); if (unitCircle.contains(value)) { - Expression* tan = unitCircle.at(value).tan; + ExprPtr tan = unitCircle.at(value).tan; return tan->clone()->reciprocal(); } } if (argument->isOfType(ExpressionType::NEGATE)) { - auto* negate = dynamic_cast(argument); + auto* negate = dynamic_cast(argument.get()); return negate->getArgument()->simplified()->cot()->negate(); } if (argument->isOfType(ExpressionType::ARC_COT)) { - auto* arcCot = dynamic_cast(argument); + auto* arcCot = dynamic_cast(argument.get()); return arcCot->getArgument()->simplified(); } diff --git a/cas/src/core/node/trig/Csc.cpp b/cas/src/core/node/trig/Csc.cpp index 3a84037..2395ce4 100644 --- a/cas/src/core/node/trig/Csc.cpp +++ b/cas/src/core/node/trig/Csc.cpp @@ -5,43 +5,43 @@ #include "cas/node/trig/Csc.h" #include "cas/node/Const.h" #include "cas/node/Negate.h" -#include "cas/node/Product.h" +#include "cas/node/Prod.h" #include "cas/node/trig/ArcCsc.h" #include "cas/node/trig/Cot.h" CAS_NAMESPACE -Csc::Csc(Expression* argument) : TrigExpression({ExpressionType::CSC, "cosecant", "csc"}, argument) {} +Csc::Csc(const ExprPtr& argument) : TrigExpression({ExpressionType::CSC, "cosecant", "csc"}, argument) {} double Csc::evaluate(const VariableMap& variables) { return 1.0 / std::sin(argument->evaluate(variables)); } -Csc* Csc::clone() { - return new Csc(argument->clone()); +ExprPtr Csc::clone() { + return Csc::from(argument->clone()); } -Expression* Csc::_derivative(char variable) { - return new Negate( - new Product({argument->clone()->csc(), - argument->clone()->cot(), - argument->derivative(variable)})); +ExprPtr Csc::_derivative(char variable) { + return Prod::from({argument->clone()->csc(), + argument->clone()->cot(), + argument->derivative(variable)}) + ->negate(); } -Expression* Csc::simplified() { +ExprPtr Csc::simplified() { if (argument->isOfType(ExpressionType::CONSTANT)) { double value = argument->evaluate(); if (unitCircle.contains(value)) { - Expression* sin = unitCircle.at(value).sin; + ExprPtr sin = unitCircle.at(value).sin; return sin->clone()->reciprocal(); } } if (argument->isOfType(ExpressionType::NEGATE)) { - auto* negate = dynamic_cast(argument); + auto* negate = dynamic_cast(argument.get()); return negate->getArgument()->simplified()->csc()->negate(); } if (argument->isOfType(ExpressionType::ARC_CSC)) { - auto* arcCsc = dynamic_cast(argument); + auto* arcCsc = dynamic_cast(argument.get()); return arcCsc->getArgument()->simplified(); } diff --git a/cas/src/core/node/trig/InverseTrigExpression.cpp b/cas/src/core/node/trig/InverseTrigExpression.cpp index cb28888..f20468b 100644 --- a/cas/src/core/node/trig/InverseTrigExpression.cpp +++ b/cas/src/core/node/trig/InverseTrigExpression.cpp @@ -7,7 +7,7 @@ CAS_NAMESPACE -InverseTrigExpression::InverseTrigExpression(const ExpressionProperties& props, Expression* argument) +InverseTrigExpression::InverseTrigExpression(const ExpressionProperties& props, const ExprPtr& argument) : TrigExpression(props, argument) {} std::string InverseTrigExpression::latex() { diff --git a/cas/src/core/node/trig/Sec.cpp b/cas/src/core/node/trig/Sec.cpp index bdeb13a..87810b8 100644 --- a/cas/src/core/node/trig/Sec.cpp +++ b/cas/src/core/node/trig/Sec.cpp @@ -5,41 +5,41 @@ #include "cas/node/trig/Sec.h" #include "cas/node/Const.h" #include "cas/node/Negate.h" -#include "cas/node/Product.h" +#include "cas/node/Prod.h" #include "cas/node/trig/Tan.h" CAS_NAMESPACE -Sec::Sec(Expression* argument) : TrigExpression({ExpressionType::SEC, "secant", "sec"}, argument) {} +Sec::Sec(const ExprPtr& argument) : TrigExpression({ExpressionType::SEC, "secant", "sec"}, argument) {} double Sec::evaluate(const VariableMap& variables) { return 1.0 / std::cos(argument->evaluate(variables)); } -Sec* Sec::clone() { - return new Sec(argument->clone()); +ExprPtr Sec::clone() { + return Sec::from(argument->clone()); } -Expression* Sec::_derivative(char variable) { - return new Product({argument->clone()->sec(), - argument->clone()->tan(), - argument->derivative(variable)}); +ExprPtr Sec::_derivative(char variable) { + return Prod::from({argument->clone()->sec(), + argument->clone()->tan(), + argument->derivative(variable)}); } -Expression* Sec::simplified() { +ExprPtr Sec::simplified() { if (argument->isOfType(ExpressionType::CONSTANT)) { double value = argument->evaluate(); if (unitCircle.contains(value)) { - Expression* cos = unitCircle.at(value).cos; + ExprPtr cos = unitCircle.at(value).cos; return cos->clone()->reciprocal(); } } if (argument->isOfType(ExpressionType::NEGATE)) { - auto* negate = dynamic_cast(argument); + auto* negate = dynamic_cast(argument.get()); return negate->getArgument()->simplified()->sec()->negate(); } if (argument->isOfType(ExpressionType::TAN)) { - auto* tan = dynamic_cast(argument); + auto* tan = dynamic_cast(argument.get()); return tan->getArgument()->simplified()->sec(); } diff --git a/cas/src/core/node/trig/Sin.cpp b/cas/src/core/node/trig/Sin.cpp index 4e24cc1..44f0b64 100644 --- a/cas/src/core/node/trig/Sin.cpp +++ b/cas/src/core/node/trig/Sin.cpp @@ -5,41 +5,41 @@ #include "cas/node/trig/Sin.h" #include "cas/node/Const.h" #include "cas/node/Negate.h" -#include "cas/node/Product.h" +#include "cas/node/Prod.h" #include "cas/node/trig/ArcSin.h" #include "cas/node/trig/Cos.h" CAS_NAMESPACE -Sin::Sin(Expression* argument) : TrigExpression({ExpressionType::SIN, "sinus", "sin"}, argument) {} +Sin::Sin(const ExprPtr& argument) : TrigExpression({ExpressionType::SIN, "sinus", "sin"}, argument) {} double Sin::evaluate(const VariableMap& variables) { return std::sin(argument->evaluate(variables)); } -Sin* Sin::clone() { - return new Sin(argument->clone()); +ExprPtr Sin::clone() { + return Sin::from(argument->clone()); } -Expression* Sin::_derivative(char variable) { +ExprPtr Sin::_derivative(char variable) { return argument ->clone() ->cos() ->multiply(argument->derivative(variable)); } -Expression* Sin::simplified() { +ExprPtr Sin::simplified() { if (argument->isOfType(ExpressionType::CONSTANT)) { double value = argument->evaluate(); if (unitCircle.contains(value)) return unitCircle.at(value).sin->clone(); } if (argument->isOfType(ExpressionType::NEGATE)) { - auto* negate = dynamic_cast(argument); + auto* negate = dynamic_cast(argument.get()); return negate->getArgument()->simplified()->sin()->negate(); } if (argument->isOfType(ExpressionType::ARC_SIN)) { - auto* arcSin = dynamic_cast(argument); + auto* arcSin = dynamic_cast(argument.get()); return arcSin->getArgument()->simplified(); } diff --git a/cas/src/core/node/trig/Tan.cpp b/cas/src/core/node/trig/Tan.cpp index 8f8adf5..ad78b8f 100644 --- a/cas/src/core/node/trig/Tan.cpp +++ b/cas/src/core/node/trig/Tan.cpp @@ -6,41 +6,41 @@ #include "cas/node/Const.h" #include "cas/node/Negate.h" #include "cas/node/Power.h" -#include "cas/node/Product.h" +#include "cas/node/Prod.h" #include "cas/node/trig/ArcTan.h" #include "cas/node/trig/Sec.h" CAS_NAMESPACE -Tan::Tan(Expression* argument) : TrigExpression({ExpressionType::TAN, "tangent", "tan"}, argument) {} +Tan::Tan(const ExprPtr& argument) : TrigExpression({ExpressionType::TAN, "tangent", "tan"}, argument) {} double Tan::evaluate(const VariableMap& variables) { return std::tan(argument->evaluate(variables)); } -Tan* Tan::clone() { - return new Tan(argument->clone()); +ExprPtr Tan::clone() { + return Tan::from(argument->clone()); } -Expression* Tan::_derivative(char variable) { +ExprPtr Tan::_derivative(char variable) { return argument->clone() ->sec() ->power(2) ->multiply(argument->derivative(variable)); } -Expression* Tan::simplified() { +ExprPtr Tan::simplified() { if (argument->isOfType(ExpressionType::CONSTANT)) { double value = argument->evaluate(); if (unitCircle.contains(value)) return unitCircle.at(value).tan->clone(); } if (argument->isOfType(ExpressionType::NEGATE)) { - auto* negate = dynamic_cast(argument); + auto* negate = dynamic_cast(argument.get()); return negate->getArgument()->simplified()->tan()->negate(); } if (argument->isOfType(ExpressionType::ARC_TAN)) { - auto* arcTan = dynamic_cast(argument); + auto* arcTan = dynamic_cast(argument.get()); return arcTan->getArgument()->simplified(); } diff --git a/cas/src/core/node/trig/TrigExpression.cpp b/cas/src/core/node/trig/TrigExpression.cpp index 4d153fa..44d2b34 100644 --- a/cas/src/core/node/trig/TrigExpression.cpp +++ b/cas/src/core/node/trig/TrigExpression.cpp @@ -34,16 +34,16 @@ const std::unordered_map TrigExpression::unitCircl {math::PI_11_6, {math::PI_11_6, Const::n(3)->sqrt()->divide(2), Const::n(-1)->divide(2), Const::n(-1)->divide(Const::n(3)->sqrt())}}, }; -TrigExpression::TrigExpression(const ExpressionProperties& properties, Expression* argument) +TrigExpression::TrigExpression(const ExpressionProperties& properties, const ExprPtr& argument) : UnaryExpression(properties, argument) {} -bool TrigExpression::_equals(Expression* other) { - auto* otherTrigFunction = dynamic_cast(other); +bool TrigExpression::_equals(const ExprPtr& other) { + auto* otherTrigFunction = dynamic_cast(other.get()); return argument->equals(otherTrigFunction->argument); } bool TrigExpression::needsParentheses() { - return instanceof (argument) || instanceof (argument) || argument->isOfType(ExpressionType::POWER) || argument->isOfType(ExpressionType::DIVIDE); + return instanceof (argument.get()) || instanceof (argument.get()) || argument->isOfType(ExpressionType::POWER) || argument->isOfType(ExpressionType::DIVIDE); } std::string TrigExpression::latex() { diff --git a/cas/src/core/plot/Function.cpp b/cas/src/core/plot/Function.cpp index 3322ab1..4e4e288 100644 --- a/cas/src/core/plot/Function.cpp +++ b/cas/src/core/plot/Function.cpp @@ -19,30 +19,25 @@ Function::Function(std::string strFunction, const std::string& name, bool simpli this->expr = parser.parse(strFunction, variables); if (simplify) { - Expression* simplifiedExpr = this->expr->simplified(); - delete this->expr; + ExprPtr simplifiedExpr = this->expr->simplified(); this->expr = simplifiedExpr; } } -Function::Function(const std::string& strFunction, cas::Expression* expr, const cas::VarSet& variables, const std::string& name) +Function::Function(const std::string& strFunction, const ExprPtr& expr, const cas::VarSet& variables, const std::string& name) : uid(nextId()), strExpr(strFunction), expr(expr), name(name), filename(generateFilename()), variables(variables) {} -Function::~Function() { - delete expr; -} - double Function::evaluate(const VariableMap& vars) { return expr->evaluate(vars); } Function* Function::derivative(char var) { - Expression* pExpression = expr->derivative(var); + ExprPtr pExpression = expr->derivative(var); return new Function(pExpression->text(), pExpression, this->variables, this->name + "_" + var); } Function* Function::simplifiedDerivative(char var) { - Expression* pExpression; + ExprPtr pExpression; try { pExpression = expr->derivative(var); } catch (std::runtime_error& e) { @@ -51,9 +46,8 @@ Function* Function::simplifiedDerivative(char var) { } // Simplify the derivative until it can't be simplified anymore - Expression* simplifiedExpr = pExpression->simplified(); + ExprPtr simplifiedExpr = pExpression->simplified(); while (simplifiedExpr->text() != pExpression->text()) { - delete pExpression; pExpression = simplifiedExpr; simplifiedExpr = pExpression->simplified(); } @@ -62,12 +56,12 @@ Function* Function::simplifiedDerivative(char var) { } Function* Function::simplified() { - Expression* pExpression = expr->simplified(); + ExprPtr pExpression = expr->simplified(); return new Function(pExpression->text(), pExpression, this->variables, this->name + "_s"); } -bool Function::isEquivalent(cas::IMath* expression) { - return expr->isEquivalent(expression); +bool Function::isEquivalent(Function* const & expression) { + return expr->isEquivalent(expression->expr); } std::string Function::latex() { @@ -98,7 +92,7 @@ const std::string& Function::getStrExpr() const { return strExpr; } -Expression* Function::getExpr() const { +ExprPtr Function::getExpr() const { return expr; } diff --git a/cas/tests/core/data/ExpressionParserTest.cpp b/cas/tests/core/data/ExpressionParserTest.cpp index eb7a3da..49eb368 100644 --- a/cas/tests/core/data/ExpressionParserTest.cpp +++ b/cas/tests/core/data/ExpressionParserTest.cpp @@ -15,7 +15,7 @@ #include "cas/node/Mod.h" #include "cas/node/Negate.h" #include "cas/node/Power.h" -#include "cas/node/Product.h" +#include "cas/node/Prod.h" #include "cas/node/Round.h" #include "cas/node/Sign.h" #include "cas/node/Sqrt.h" diff --git a/cas/tests/core/node/ArcCscNodeTest.cpp b/cas/tests/core/node/ArcCscNodeTest.cpp index 8d65292..1de4038 100644 --- a/cas/tests/core/node/ArcCscNodeTest.cpp +++ b/cas/tests/core/node/ArcCscNodeTest.cpp @@ -3,7 +3,7 @@ #include "cas/node/Divide.h" #include "cas/node/Negate.h" #include "cas/node/Power.h" -#include "cas/node/Product.h" +#include "cas/node/Prod.h" #include "cas/node/Sqrt.h" #include "cas/node/Sum.h" #include "cas/node/Var.h" diff --git a/cas/tests/core/node/ArcSecNodeTest.cpp b/cas/tests/core/node/ArcSecNodeTest.cpp index 0b91d5f..29cfe0b 100644 --- a/cas/tests/core/node/ArcSecNodeTest.cpp +++ b/cas/tests/core/node/ArcSecNodeTest.cpp @@ -3,7 +3,7 @@ #include "cas/node/Divide.h" #include "cas/node/Negate.h" #include "cas/node/Power.h" -#include "cas/node/Product.h" +#include "cas/node/Prod.h" #include "cas/node/Sqrt.h" #include "cas/node/Sum.h" #include "cas/node/Var.h" diff --git a/cas/tests/core/node/CbrtNodeTest.cpp b/cas/tests/core/node/CbrtNodeTest.cpp index d29d0f2..9bb9d41 100644 --- a/cas/tests/core/node/CbrtNodeTest.cpp +++ b/cas/tests/core/node/CbrtNodeTest.cpp @@ -5,7 +5,7 @@ #include "cas/node/Cbrt.h" #include "cas/node/Const.h" #include "cas/node/Divide.h" -#include "cas/node/Product.h" +#include "cas/node/Prod.h" #include "cas/node/Var.h" #include "gtest/gtest.h" #include diff --git a/cas/tests/core/node/DivideNodeTest.cpp b/cas/tests/core/node/DivideNodeTest.cpp index 3f9fcba..e63ac45 100644 --- a/cas/tests/core/node/DivideNodeTest.cpp +++ b/cas/tests/core/node/DivideNodeTest.cpp @@ -6,7 +6,7 @@ #include "cas/node/Divide.h" #include "cas/node/Negate.h" #include "cas/node/Power.h" -#include "cas/node/Product.h" +#include "cas/node/Prod.h" #include "cas/node/Sum.h" #include "cas/node/Var.h" #include "gtest/gtest.h" diff --git a/cas/tests/core/node/ExpNodeTest.cpp b/cas/tests/core/node/ExpNodeTest.cpp index f813166..16d9804 100644 --- a/cas/tests/core/node/ExpNodeTest.cpp +++ b/cas/tests/core/node/ExpNodeTest.cpp @@ -4,7 +4,7 @@ #include "cas/node/Const.h" #include "cas/node/Exp.h" -#include "cas/node/Product.h" +#include "cas/node/Prod.h" #include "cas/node/Var.h" #include "gtest/gtest.h" diff --git a/cas/tests/core/node/ProductNodeTest.cpp b/cas/tests/core/node/ProductNodeTest.cpp index 9e78006..30fb123 100644 --- a/cas/tests/core/node/ProductNodeTest.cpp +++ b/cas/tests/core/node/ProductNodeTest.cpp @@ -3,7 +3,7 @@ // #include "cas/node/Const.h" -#include "cas/node/Product.h" +#include "cas/node/Prod.h" #include "cas/node/Sum.h" #include "cas/node/Var.h" #include "gtest/gtest.h" diff --git a/cas/tests/core/plot/FunctionTest.cpp b/cas/tests/core/plot/FunctionTest.cpp index 6070c07..f6720c2 100644 --- a/cas/tests/core/plot/FunctionTest.cpp +++ b/cas/tests/core/plot/FunctionTest.cpp @@ -5,7 +5,7 @@ #include "cas/plot/Function.h" #include "cas/node/Const.h" #include "cas/node/Power.h" -#include "cas/node/Product.h" +#include "cas/node/Prod.h" #include "cas/node/Sum.h" #include "cas/node/Var.h" #include "gtest/gtest.h" diff --git a/src/render/metal/main.mm b/src/render/metal/main.mm index 1da4ed6..72dbdb0 100644 --- a/src/render/metal/main.mm +++ b/src/render/metal/main.mm @@ -1,11 +1,11 @@ #include +#include "cas/data/VariableMap.h" + #include "Grid.h" #include "Surface.h" #include "Window.h" -#include "cas/data/VariableMap.h" - #import #import #import @@ -28,10 +28,10 @@ MTLVertexDescriptor* getVertexDescriptor() { MTLVertexDescriptor* vertexDescriptor = [MTLVertexDescriptor new]; - vertexDescriptor.attributes[0].format = MTLVertexFormatFloat3;// position + vertexDescriptor.attributes[0].format = MTLVertexFormatFloat3; // position vertexDescriptor.attributes[0].offset = 0; vertexDescriptor.attributes[0].bufferIndex = 0; - vertexDescriptor.attributes[1].format = MTLVertexFormatFloat4;// color + vertexDescriptor.attributes[1].format = MTLVertexFormatFloat4; // color vertexDescriptor.attributes[1].offset = sizeof(simd::float3); vertexDescriptor.attributes[1].bufferIndex = 0; vertexDescriptor.layouts[0].stride = sizeof(Vertex); @@ -106,7 +106,7 @@ int main() { id device = MTLCreateSystemDefaultDevice(); id commandQueue = [device newCommandQueue]; - id library = getLibrary(device, "../src/render/metal/shader.metal"); + id library = getLibrary(device, "../../src/render/metal/shader.metal"); id vertexFunction = [library newFunctionWithName:@"vertexMain"]; // struct with both functions id fragmentFunction = [library newFunctionWithName:@"fragmentMain"]; @@ -117,15 +117,15 @@ int main() { MTLDepthStencilDescriptor* depthStencilDescriptor = getDepthStencilDescriptor(); id depthStencilState = [device newDepthStencilStateWithDescriptor:depthStencilDescriptor]; - NSArray* axis = loadMesh(device, vertexDescriptor, "../res/models/axis.obj"); + NSArray* axis = loadMesh(device, vertexDescriptor, "../../res/models/axis.obj"); // ==================== WORLD/GRID Setup ==================== Grid grid; Window window("Computer Algebra System", device, grid); - cas::VariableMap variables = {{'x', 0}, {'y', 0}}; + cas::VariableMap variables = {{'x', 0}, {'y', 0}, {'a', 0}}; std::vector> surfaces { std::make_shared(device, "x^2 + y^2", grid, variables), - std::make_shared(device, "x^2 * y^2", grid, variables), + std::make_shared(device, "x^2 * y^2 + a", grid, variables), std::make_shared(device, "sin(x*y)", grid, variables), std::make_shared(device, "abs(x * y)", grid, variables), std::make_shared(device, "floor(round(ceil(x + y)))", grid, variables)};