diff --git a/include/fintamath/core/MathObjectTypes.hpp b/include/fintamath/core/MathObjectTypes.hpp index 927abea23..27d0116af 100644 --- a/include/fintamath/core/MathObjectTypes.hpp +++ b/include/fintamath/core/MathObjectTypes.hpp @@ -49,6 +49,7 @@ enum class MathObjectType : MathObjectTypeId { Rational, Real, + Complex, IInteger = 8000, @@ -69,6 +70,7 @@ enum class MathObjectType : MathObjectTypeId { NegInf, ComplexInf, Undefined, + ImaginaryUnit, IFunction = 11000, diff --git a/include/fintamath/literals/constants/ImaginaryUnit.hpp b/include/fintamath/literals/constants/ImaginaryUnit.hpp new file mode 100644 index 000000000..3f694f9b9 --- /dev/null +++ b/include/fintamath/literals/constants/ImaginaryUnit.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include "fintamath/literals/constants/IConstant.hpp" +#include "fintamath/numbers/Complex.hpp" + +namespace fintamath { + +class ImaginaryUnit : public IConstantCRTP { +public: + std::string toString() const override { + return "I"; + } + + static MathObjectTypeId getTypeIdStatic() { + return MathObjectTypeId(MathObjectType::ImaginaryUnit); + } + +protected: + std::unique_ptr call() const override; +}; + +} diff --git a/include/fintamath/numbers/Complex.hpp b/include/fintamath/numbers/Complex.hpp new file mode 100644 index 000000000..ca05533c0 --- /dev/null +++ b/include/fintamath/numbers/Complex.hpp @@ -0,0 +1,71 @@ +#pragma once + +#include "fintamath/numbers/Integer.hpp" +#include "fintamath/numbers/Rational.hpp" +#include "fintamath/numbers/Real.hpp" + +namespace fintamath { + +class Complex : public INumberCRTP { +public: + Complex() = default; + + Complex(const Complex &rhs); + + Complex(Complex &&rhs) noexcept = default; + + Complex &operator=(const Complex &rhs); + + Complex &operator=(Complex &&rhs) noexcept = default; + + explicit Complex(const std::string &str); + + explicit Complex(const INumber &inReal, const INumber &inImag); + + explicit Complex(Integer inReal, Integer inImag); + + Complex(const Integer &rhs); + + Complex(const Rational &rhs); + + Complex(const Real &rhs); + + Complex(int64_t rhs); + + std::string toString() const override; + + std::unique_ptr toMinimalObject() const override; + + Complex precise(uint8_t precision) const; + + const INumber &real() const; + + const INumber &imag() const; + + static MathObjectTypeId getTypeIdStatic() { + return MathObjectTypeId(MathObjectType::Complex); + } + +protected: + bool equals(const Complex &rhs) const override; + + bool less(const Complex &rhs) const override; + + bool more(const Complex &rhs) const override; + + Complex &add(const Complex &rhs) override; + + Complex &substract(const Complex &rhs) override; + + Complex &multiply(const Complex &rhs) override; + + Complex ÷(const Complex &rhs) override; + + Complex &negate() override; + +private: + std::unique_ptr re = std::make_unique(0); + std::unique_ptr im = std::make_unique(0); +}; + +} diff --git a/src/fintamath/config/ConverterConfig.cpp b/src/fintamath/config/ConverterConfig.cpp index 3b31aac17..a84119c2a 100644 --- a/src/fintamath/config/ConverterConfig.cpp +++ b/src/fintamath/config/ConverterConfig.cpp @@ -1,5 +1,6 @@ #include "fintamath/core/Converter.hpp" +#include "fintamath/numbers/Complex.hpp" #include "fintamath/numbers/Integer.hpp" #include "fintamath/numbers/Rational.hpp" #include "fintamath/numbers/Real.hpp" @@ -39,6 +40,19 @@ struct ConverterConfig { Converter::add([](const Real & /*type*/, const Rational &value) { return std::make_unique(value); }); + + Converter::add([](const Complex & /*type*/, const Complex &value) { + return std::make_unique(value); + }); + Converter::add([](const Complex & /*type*/, const Integer &value) { + return std::make_unique(value); + }); + Converter::add([](const Complex & /*type*/, const Rational &value) { + return std::make_unique(value); + }); + Converter::add([](const Complex & /*type*/, const Real &value) { + return std::make_unique(value); + }); } }; diff --git a/src/fintamath/config/ParserConfig.cpp b/src/fintamath/config/ParserConfig.cpp index 927b76a12..0c4fe6190 100644 --- a/src/fintamath/config/ParserConfig.cpp +++ b/src/fintamath/config/ParserConfig.cpp @@ -66,6 +66,7 @@ #include "fintamath/literals/constants/E.hpp" #include "fintamath/literals/constants/False.hpp" #include "fintamath/literals/constants/IConstant.hpp" +#include "fintamath/literals/constants/ImaginaryUnit.hpp" #include "fintamath/literals/constants/Inf.hpp" #include "fintamath/literals/constants/NegInf.hpp" #include "fintamath/literals/constants/Pi.hpp" @@ -157,7 +158,6 @@ struct ParserConfig { INumber::registerType(&IInteger::parse); INumber::registerType(); - INumber::registerType(); IInteger::registerType(); @@ -169,6 +169,7 @@ struct ParserConfig { IConstant::registerType(); IConstant::registerType(); IConstant::registerType(); + IConstant::registerType(); IConstant::registerType(); IConstant::registerType(); IConstant::registerType(); diff --git a/src/fintamath/literals/constants/ImaginaryUnit.cpp b/src/fintamath/literals/constants/ImaginaryUnit.cpp new file mode 100644 index 000000000..49ac76cf8 --- /dev/null +++ b/src/fintamath/literals/constants/ImaginaryUnit.cpp @@ -0,0 +1,9 @@ +#include "fintamath/literals/constants/ImaginaryUnit.hpp" + +namespace fintamath { + +std::unique_ptr ImaginaryUnit::call() const { + return std::make_unique(Integer(0), Integer(1)); +} + +} diff --git a/src/fintamath/numbers/Complex.cpp b/src/fintamath/numbers/Complex.cpp new file mode 100644 index 000000000..79652e68b --- /dev/null +++ b/src/fintamath/numbers/Complex.cpp @@ -0,0 +1,175 @@ +#include "fintamath/numbers/Complex.hpp" + +#include +#include + +#include "fintamath/exceptions/InvalidInputException.hpp" +#include "fintamath/exceptions/UndefinedException.hpp" + +namespace fintamath { + +Complex::Complex(const Complex &rhs) : re(cast(rhs.re->clone())), im(cast(rhs.im->clone())) { +} + +Complex &Complex::operator=(const Complex &rhs) { + if (this != &rhs) { + re = cast(rhs.re->clone()); + im = cast(rhs.im->clone()); + } + + return *this; +} + +Complex::Complex(const std::string &str) { + if (!str.empty() && str.back() == 'I') { + im = INumber::parse(str.substr(0, str.length() - 1)); + } + else { + re = INumber::parse(str); + } + + if (!re || !im) { + throw InvalidInputException(str); + } +} + +Complex::Complex(const INumber &inReal, const INumber &inImag) { + if (is(inReal) || is(inImag)) { + throw InvalidInputException("Nested complex numbers are not allowed"); + } + + re = cast(inReal.clone()); + im = cast(inImag.clone()); +} + +Complex::Complex(Integer inReal, Integer inImag) { + re = cast(std::move(inReal).clone()); + im = cast(std::move(inImag).clone()); +} + +Complex::Complex(const Integer &rhs) : re(cast(rhs.toMinimalObject())) { +} + +Complex::Complex(const Rational &rhs) : re(cast(rhs.toMinimalObject())) { +} + +Complex::Complex(const Real &rhs) : re(cast(rhs.toMinimalObject())) { +} + +Complex::Complex(int64_t rhs) : re(std::make_unique(rhs)) { +} + +std::string Complex::toString() const { + std::string res; + + if (*re != Integer(0)) { + res += re->toString(); + } + + if (*im != Integer(0)) { + std::string imStr = im->toString(); + bool isImNeg = false; + + if (imStr.front() == '-') { + imStr = imStr.substr(1); + isImNeg = true; + } + + if (imStr == "1") { + imStr.clear(); + } + + if (!res.empty()) { + res += isImNeg ? " - " : " + "; + } + + res += imStr + "I"; + } + + if (res.empty()) { + res = "0"; + } + + return res; +} + +std::unique_ptr Complex::toMinimalObject() const { + if (*im == Integer(0)) { + return re->clone(); + } + return clone(); +} + +Complex Complex::precise(uint8_t precision) const { + Complex res = *this; + res.re = std::make_unique(convert(*re)->precise(precision)); + res.im = std::make_unique(convert(*im)->precise(precision)); + return res; +} + +const INumber &Complex::real() const { + return *re; +} + +const INumber &Complex::imag() const { + return *re; +} + +bool Complex::equals(const Complex &rhs) const { + return *re == *rhs.re && *im == *rhs.im; +} + +bool Complex::less(const Complex &rhs) const { + if (*re == *rhs.re) { + return *im < *rhs.im; + } + + return *re < *rhs.re; +} + +bool Complex::more(const Complex &rhs) const { + if (*re == *rhs.re) { + return *im > *rhs.im; + } + + return *re > *rhs.re; +} + +Complex &Complex::add(const Complex &rhs) { + re = *re + *rhs.re; + im = *im + *rhs.im; + return *this; +} + +Complex &Complex::substract(const Complex &rhs) { + re = *re - *rhs.re; + im = *im - *rhs.im; + return *this; +} + +// https://en.wikipedia.org/wiki/Complex_number#Multiplication_and_square +Complex &Complex::multiply(const Complex &rhs) { + auto lhsRe = cast(re->clone()); + auto lhsIm = cast(im->clone()); + re = *(*lhsRe * *rhs.re) + *(*lhsIm * *rhs.im); + im = *(*lhsRe * *rhs.im) + *(*lhsIm * *rhs.re); + return *this; +} + +// https://en.wikipedia.org/wiki/Complex_number#Reciprocal_and_division +Complex &Complex::divide(const Complex &rhs) { + auto lhsRe = cast(re->clone()); + auto lhsIm = cast(im->clone()); + auto divisor = *(*rhs.re * *rhs.re) + *(*rhs.im * *rhs.im); + re = *(*(*lhsRe * *rhs.re) + *(*lhsIm * *rhs.im)) / *divisor; + im = *(*(*lhsIm * *rhs.re) - *(*lhsRe * *rhs.im)) / *divisor; + return *this; +} + +Complex &Complex::negate() { + re = -(*re); + im = -(*im); + return *this; +} + +} diff --git a/tests/src/literals/constants/ImaginaryUnitTests.cpp b/tests/src/literals/constants/ImaginaryUnitTests.cpp new file mode 100644 index 000000000..040702bb6 --- /dev/null +++ b/tests/src/literals/constants/ImaginaryUnitTests.cpp @@ -0,0 +1,31 @@ +#include + +#include "fintamath/literals/constants/ImaginaryUnit.hpp" +#include "fintamath/literals/constants/Pi.hpp" + +using namespace fintamath; + +const ImaginaryUnit c; + +TEST(ImaginaryUnitTests, toStringTest) { + EXPECT_EQ(c.toString(), "I"); +} + +TEST(ImaginaryUnitTests, callTest) { + EXPECT_EQ(c()->toString(), "I"); +} + +TEST(ImaginaryUnitTests, equalsTest) { + EXPECT_EQ(c, c); + EXPECT_EQ(c, ImaginaryUnit()); + EXPECT_EQ(ImaginaryUnit(), c); + EXPECT_EQ(c, cast(ImaginaryUnit())); + EXPECT_EQ(cast(ImaginaryUnit()), c); + EXPECT_NE(c, Pi()); + EXPECT_NE(Pi(), c); +} + +TEST(ImaginaryUnitTests, getTypeIdTest) { + EXPECT_EQ(ImaginaryUnit::getTypeIdStatic(), MathObjectTypeId(MathObjectType::ImaginaryUnit)); + EXPECT_EQ(ImaginaryUnit().getTypeId(), MathObjectTypeId(MathObjectType::ImaginaryUnit)); +} diff --git a/tests/src/numbers/ComplexTests.cpp b/tests/src/numbers/ComplexTests.cpp new file mode 100644 index 000000000..2a6b5ce86 --- /dev/null +++ b/tests/src/numbers/ComplexTests.cpp @@ -0,0 +1,507 @@ +#include + +#include "fintamath/exceptions/InvalidInputException.hpp" +#include "fintamath/exceptions/UndefinedException.hpp" +#include "fintamath/numbers/Complex.hpp" + +using namespace fintamath; + +TEST(ComplexTests, constructorTest) { + EXPECT_EQ(Complex(), 0); +} + +TEST(ComplexTests, stringConstructorTest) { + EXPECT_EQ(Complex("0"), 0); + EXPECT_EQ(Complex("2"), 2); + EXPECT_EQ(Complex("-93"), -93); + EXPECT_EQ(Complex("-9.3").toString(), "-93/10"); + EXPECT_EQ(Complex("0989929039237832000.9302930929333").toString(), "9899290392378320009302930929333/10000000000000"); + EXPECT_EQ(Complex(".1").toString(), "1/10"); + EXPECT_EQ(Complex("1.").toString(), "1"); + + EXPECT_THROW(Complex("--10"), InvalidInputException); + EXPECT_THROW(Complex("test"), InvalidInputException); + EXPECT_THROW(Complex(""), InvalidInputException); + EXPECT_THROW(Complex("+"), InvalidInputException); + EXPECT_THROW(Complex("939849.0-0023"), InvalidInputException); + EXPECT_THROW(Complex("a"), InvalidInputException); + EXPECT_THROW(Complex("a.1"), InvalidInputException); + EXPECT_THROW(Complex("1.a"), InvalidInputException); + EXPECT_THROW(Complex("1a.1"), InvalidInputException); + EXPECT_THROW(Complex("1.1a"), InvalidInputException); + EXPECT_THROW(Complex(".1."), InvalidInputException); + EXPECT_THROW(Complex("."), InvalidInputException); + EXPECT_THROW(Complex("--10.-1"), InvalidInputException); + EXPECT_THROW(Complex("10.-1"), InvalidInputException); + EXPECT_THROW(Complex("1-0.1"), InvalidInputException); + EXPECT_THROW(Complex("10-.1"), InvalidInputException); + EXPECT_THROW(Complex("10.--1"), InvalidInputException); + EXPECT_THROW(Complex("1.10.1"), InvalidInputException); +} + +TEST(ComplexTests, integerIntegerConstructorTest) { + EXPECT_EQ(Complex(-380, -608).toString(), "5/8"); + EXPECT_EQ(Complex(2849300, 18493).toString(), "2849300/18493"); + EXPECT_EQ(Complex(2849300, -1893).toString(), "-2849300/1893"); + + EXPECT_THROW(Complex(23070, 0), UndefinedBinaryOperatorException); +} + +TEST(ComplexTests, integerConstructorTest) { + EXPECT_EQ(Complex(Integer("122432964238764283746823")), Integer("122432964238764283746823")); +} + +TEST(ComplexTests, integerAssignmentOperatorTest) { + Complex b; + EXPECT_EQ(b = Integer("39743491820370928039"), Complex("39743491820370928039")); +} + +TEST(ComplexTests, intConstructorTest) { + EXPECT_EQ(Complex(2), 2); +} + +TEST(ComplexTests, intAssignmentOperatorTest) { + Complex a; + EXPECT_EQ(a = 2, 2); +} + +TEST(ComplexTests, plusAssignmentOperatorTest) { + EXPECT_EQ(Complex(2, 3) += Complex(5, 2), Complex(19, 6)); + EXPECT_EQ(Complex(-738, 10) += Complex(5, 2), Complex(-713, 10)); + EXPECT_EQ(Complex(738, 10) += Complex(5, 2), Complex(763, 10)); + EXPECT_EQ(Complex(-738, 10) += Complex(-5, 2), Complex(-763, 10)); +} + +TEST(ComplexTests, integerPlusAssignmentOperatorTest) { + EXPECT_EQ(Complex(-10) += Integer(5), -5); + EXPECT_EQ(Complex(2, 3) += Integer(-5), Complex(-13, 3)); +} + +TEST(ComplexTests, intPlusAssignmentOperatorTest) { + EXPECT_EQ(Complex(-10) += 5, -5); + EXPECT_EQ(Complex(2, 3) += -5, Complex(-13, 3)); +} + +TEST(ComplexTests, plusOperatorTest) { + EXPECT_EQ(Complex(170, 15) + Complex(-5, 2), Complex(53, 6)); + EXPECT_EQ(Complex(17, 19) + Complex(53, 5), Complex(1092, 95)); + EXPECT_EQ(Complex(170, 12) + Complex(2, 5), Complex(437, 30)); +} + +TEST(ComplexTests, integerPlusOperatorTest) { + EXPECT_EQ(Complex(170) + Integer(-5), 165); + EXPECT_EQ(Complex(17) + Integer(53), 70); + EXPECT_EQ(Complex(170, 12) + Integer(2), Complex(194, 12)); +} + +TEST(ComplexTests, intPlusOperatorTest) { + EXPECT_EQ(Complex(170) + -5, 165); + EXPECT_EQ(Complex(17) + 53, 70); + EXPECT_EQ(Complex(170, 12) + 2, Complex(194, 12)); +} + +TEST(ComplexTests, integerFriendPlusOperatorTest) { + EXPECT_EQ(Integer(2) + Complex(-18), -16); + EXPECT_EQ(Integer(4938493849) + Complex(1009), 4938494858); +} + +TEST(ComplexTests, intFriendPlusOperatorTest) { + EXPECT_EQ(2 + Complex(-18), -16); + EXPECT_EQ(4938493849 + Complex(1009), 4938494858); +} + +TEST(ComplexTests, minusAssignmentOperatorTest) { + EXPECT_EQ(Complex(2, 3) -= Complex(5, 2), Complex(-11, 6)); + EXPECT_EQ(Complex(-738, 10) -= Complex(5, 2), Complex(-763, 10)); + EXPECT_EQ(Complex(738, 10) -= Complex(5, 2), Complex(713, 10)); + EXPECT_EQ(Complex(-738, 10) -= Complex(-5, 2), Complex(-713, 10)); +} + +TEST(ComplexTests, integerMinusAssignmentOperatorTest) { + EXPECT_EQ(Complex(-738, -10) -= Integer(-5), Complex(394, 5)); + EXPECT_EQ(Complex(-738, 10) -= Integer(5), Complex(-394, 5)); +} + +TEST(ComplexTests, intMinusAssignmentOperatorTest) { + EXPECT_EQ(Complex(-738, -10) -= -5, Complex(394, 5)); + EXPECT_EQ(Complex(-738, 10) -= 5, Complex(-394, 5)); +} + +TEST(ComplexTests, minusOperatorTest) { + EXPECT_EQ(Complex(170, 15) - Complex(-5, 2), Complex(83, 6)); + EXPECT_EQ(Complex(17, 19) - Complex(53, 5), Complex(-922, 95)); + EXPECT_EQ(Complex(170, 12) - Complex(2, 5), Complex(413, 30)); +} + +TEST(ComplexTests, integerMinusOperatorTest) { + EXPECT_EQ(Complex(170) - Integer(5), 165); + EXPECT_EQ(Complex(17) - Integer(53), -36); + EXPECT_EQ(Complex(170, 12) - Integer(-2), Complex(194, 12)); +} + +TEST(ComplexTests, intMinusOperatorTest) { + EXPECT_EQ(Complex(170) - 5, 165); + EXPECT_EQ(Complex(17) - 53, -36); + EXPECT_EQ(Complex(170, 12) - -2, Complex(194, 12)); +} + +TEST(ComplexTests, integerFriendMinusOperatorTest) { + EXPECT_EQ(Integer(2) - Complex(-18), 20); + EXPECT_EQ(Integer(4938493849) - Complex(1009), 4938492840); +} + +TEST(ComplexTests, intFriendMinusOperatorTest) { + EXPECT_EQ(2 - Complex(-18), 20); + EXPECT_EQ(4938493849 - Complex(1009), 4938492840); +} + +TEST(ComplexTests, multiplyAssignmentOperatorTest) { + EXPECT_EQ(Complex(2, 3) *= Complex(5, 2), Complex(5, 3)); + EXPECT_EQ(Complex(-738, 10) *= Complex(5, 2), Complex(-369, 2)); + EXPECT_EQ(Complex(738, 10) *= Complex(5, 2), Complex(369, 2)); + EXPECT_EQ(Complex(-738, 10) *= Complex(-5, 2), Complex(369, 2)); +} + +TEST(ComplexTests, integerMultiplyAssignmentOperatorTest) { + EXPECT_EQ(Complex(2, 3) *= Integer(-5), Complex(-10, 3)); + EXPECT_EQ(Complex(738, -10) *= Integer(5894), Complex(-4349772, 10)); + EXPECT_EQ(Complex(-738, -10) *= Integer(10), 738); +} + +TEST(ComplexTests, intMultiplyAssignmentOperatorTest) { + EXPECT_EQ(Complex(2, 3) *= -5, Complex(-10, 3)); + EXPECT_EQ(Complex(738, -10) *= 5894, Complex(-4349772, 10)); + EXPECT_EQ(Complex(-738, -10) *= 10, 738); +} + +TEST(ComplexTests, multiplyOperatorTest) { + EXPECT_EQ(Complex(170, 15) * Complex(-5, 2), Complex(-85, 3)); + EXPECT_EQ(Complex(17, 19) * Complex(53, 5), Complex(901, 95)); + EXPECT_EQ(Complex(170, 12) * Complex(2, 5), Complex(17, 3)); +} + +TEST(ComplexTests, integerMultiplyOperatorTest) { + EXPECT_EQ(Complex(2, 3) * Integer(-5), Complex(-10, 3)); + EXPECT_EQ(Complex(738, -10) * Integer(5894), Complex(-4349772, 10)); + EXPECT_EQ(Complex(-738, -10) * Integer(10), 738); +} + +TEST(ComplexTests, intMultiplyOperatorTest) { + EXPECT_EQ(Complex(2, 3) * -5, Complex(-10, 3)); + EXPECT_EQ(Complex(738, -10) * 5894, Complex(-4349772, 10)); + EXPECT_EQ(Complex(-738, -10) * 10, 738); +} + +TEST(ComplexTests, integerFriendMultiplyOperatorTest) { + EXPECT_EQ(Integer(-5) * Complex(2, 3), Complex(-10, 3)); + EXPECT_EQ(Integer(589398724) * Complex(1, 8372738), Complex(589398724, 8372738)); + EXPECT_EQ(Integer(10) * Complex(-738, -10), 738); +} + +TEST(ComplexTests, intFriendMultiplyOperatorTest) { + EXPECT_EQ(-5 * Complex(2, 3), Complex(-10, 3)); + EXPECT_EQ(589398724 * Complex(1, 8372738), Complex(589398724, 8372738)); + EXPECT_EQ(10 * Complex(-738, -10), 738); +} + +TEST(ComplexTests, divideAssignmentOperatorTest) { + EXPECT_EQ(Complex(2, 3) /= Complex(5, 2), Complex(4, 15)); + EXPECT_EQ(Complex(-738, 10) /= Complex(5, 2), Complex(-738, 25)); + EXPECT_EQ(Complex(738, 10) /= Complex(5, 2), Complex(738, 25)); + EXPECT_EQ(Complex(-738, 10) /= Complex(-5, 2), Complex(738, 25)); + + EXPECT_THROW(Complex(-738, -10) /= Complex("0"), UndefinedBinaryOperatorException); +} + +TEST(ComplexTests, integerDivideAssignmentOperatorTest) { + EXPECT_EQ(Complex(2, 3) /= Integer(-2), Complex(1, -3)); + EXPECT_EQ(Complex(738, -10) /= Integer(5894), Complex(-738, 58940)); + EXPECT_EQ(Complex(-738, -10) /= Integer(10), Complex(369, 50)); +} + +TEST(ComplexTests, intDivideAssignmentOperatorTest) { + EXPECT_EQ(Complex(2, 3) /= -2, Complex(1, -3)); + EXPECT_EQ(Complex(738, -10) /= 5894, Complex(-738, 58940)); + EXPECT_EQ(Complex(-738, -10) /= 10, Complex(369, 50)); +} + +TEST(ComplexTests, divideOperatorTest) { + EXPECT_EQ(Complex(170, 15) / Complex(-5, 2), Complex(-68, 15)); + EXPECT_EQ(Complex(17, 19) / Complex(53, 5), Complex(85, 1007)); + EXPECT_EQ(Complex(170, 12) / Complex(2, 5), Complex(425, 12)); +} + +TEST(ComplexTests, integerDivideOperatorTest) { + EXPECT_EQ(Complex(2, 3) / Integer(-5), Complex(-2, 15)); + EXPECT_EQ(Complex(738, -10) / Integer(5894), Complex(738, -58940)); +} + +TEST(ComplexTests, intDivideOperatorTest) { + EXPECT_EQ(Complex(2, 3) / -5, Complex(-2, 15)); + EXPECT_EQ(Complex(738, -10) / 5894, Complex(738, -58940)); +} + +TEST(ComplexTests, integerFriendDivideOperatorTest) { + EXPECT_EQ(Integer(-5) / Complex(2, 3), Complex(-15, 2)); + EXPECT_EQ(Integer(589398724) / Complex(8372738), Complex(589398724, 8372738)); + EXPECT_EQ(Integer(10) / Complex(-10, -738), 738); +} + +TEST(ComplexTests, intFriendDivideOperatorTest) { + EXPECT_EQ(-5 / Complex(2, 3), Complex(-15, 2)); + EXPECT_EQ(589398724 / Complex(8372738), Complex(589398724, 8372738)); + EXPECT_EQ(10 / Complex(-10, -738), 738); +} + +TEST(ComplexTests, unaryPlusOperatorTest) { + EXPECT_EQ(+Complex(-5), -5); +} + +TEST(ComplexTests, unaryMinusOperatorTest) { + EXPECT_EQ(-Complex(5), -5); +} + +TEST(ComplexTests, equalOperatorTest) { + EXPECT_TRUE(Complex(1, 2) == Complex(1, 2)); + EXPECT_TRUE(Complex(5, 10) == Complex(1, 2)); + EXPECT_TRUE(Complex(5, -10) == Complex(-5, 10)); + + EXPECT_FALSE(Complex(1, 2) == Complex(1, 3)); + EXPECT_FALSE(Complex(3, 2) == Complex(1, 3)); + EXPECT_FALSE(Complex(55, 10) == Complex(-1, 10)); +} + +TEST(ComplexTests, integerEqualOperatorTest) { + EXPECT_TRUE(Complex(500) == Integer(500)); + EXPECT_TRUE(Complex(50, -10) == Integer(-5)); +} + +TEST(ComplexTests, intEqualOperatorTest) { + EXPECT_TRUE(Complex(500) == 500); + EXPECT_TRUE(Complex(50, -10) == -5); +} + +TEST(ComplexTests, integerFriendEqualOperatorTest) { + EXPECT_TRUE(Integer(500) == Complex(500)); + EXPECT_TRUE(Integer(-5) == Complex(50, -10)); +} + +TEST(ComplexTests, intFriendEqualOperatorTest) { + EXPECT_TRUE(500 == Complex(500)); + EXPECT_TRUE(-5 == Complex(50, -10)); +} + +TEST(ComplexTests, notEqualOperatorTest) { + EXPECT_TRUE(Complex(55, 10) != Complex(-1, 10)); + + EXPECT_FALSE(Complex(5, 10) != Complex(1, 2)); + EXPECT_FALSE(Complex(5, -10) != Complex(-5, 10)); +} + +TEST(ComplexTests, integerNotEqualOperatorTest) { + EXPECT_TRUE(Complex(50, 10) != Integer(-5)); + + EXPECT_FALSE(Complex(500) != Integer(500)); +} + +TEST(ComplexTests, intNotEqualOperatorTest) { + EXPECT_TRUE(Complex(50, 10) != -5); + + EXPECT_FALSE(Complex(500) != 500); +} + +TEST(ComplexTests, integerFriendNotEqualOperatorTest) { + EXPECT_TRUE(Integer(50) != Complex(3920)); + + EXPECT_FALSE(Integer(500) != Complex(500)); + EXPECT_FALSE(Integer(-5) != Complex(50, -10)); +} + +TEST(ComplexTests, intFriendNotEqualOperatorTest) { + EXPECT_TRUE(50 != Complex(3920)); + + EXPECT_FALSE(500 != Complex(500)); + EXPECT_FALSE(-5 != Complex(50, -10)); +} + +TEST(ComplexTests, lessOperatorTest) { + EXPECT_TRUE(Complex(5, -10) < Complex(50, 10)); + + EXPECT_FALSE(Complex(5, 10) < Complex(1, 2)); + EXPECT_FALSE(Complex(5, -10) < Complex(-50, 10)); + EXPECT_FALSE(Complex(55, 10) < Complex(1, 10)); +} + +TEST(ComplexTests, integerLessOperatorTest) { + EXPECT_TRUE(Complex(500) < Integer(3283)); + + EXPECT_FALSE(Complex(50, -10) < Integer(-5)); +} + +TEST(ComplexTests, intLessOperatorTest) { + EXPECT_TRUE(Complex(500) < 3283); + + EXPECT_FALSE(Complex(50, -10) < -5); +} + +TEST(ComplexTests, integerFriendLessOperatorTest) { + EXPECT_TRUE(Integer(-5) < Complex(50, 10)); + EXPECT_TRUE(Integer(7387) < Complex(3983920)); + + EXPECT_FALSE(Integer(500) < Complex(500)); +} + +TEST(ComplexTests, intFriendLessOperatorTest) { + EXPECT_TRUE(-5 < Complex(50, 10)); + EXPECT_TRUE(7387 < Complex(3983920)); + + EXPECT_FALSE(500 < Complex(500)); +} + +TEST(ComplexTests, moreOperatorTest) { + EXPECT_TRUE(Complex(5, -10) > Complex(-50, 10)); + EXPECT_TRUE(Complex(55, 10) > Complex(1, 10)); + + EXPECT_FALSE(Complex(5, 10) > Complex(1, 2)); + EXPECT_FALSE(Complex(5, -10) > Complex(50, 10)); +} + +TEST(ComplexTests, integerMoreOperatorTest) { + EXPECT_FALSE(Complex(500) > Integer(3283)); + EXPECT_FALSE(Complex(50, -10) > Integer(-5)); +} + +TEST(ComplexTests, intMoreOperatorTest) { + EXPECT_FALSE(Complex(500) > 3283); + EXPECT_FALSE(Complex(50, -10) > -5); +} + +TEST(ComplexTests, integerFriendMoreOperatorTest) { + EXPECT_TRUE(Integer(738657) > Complex(320)); + + EXPECT_FALSE(Integer(500) > Complex(500)); + EXPECT_FALSE(Integer(-5) > Complex(50, 10)); +} + +TEST(ComplexTests, intFriendMoreOperatorTest) { + EXPECT_TRUE(738657 > Complex(320)); + + EXPECT_FALSE(500 > Complex(500)); + EXPECT_FALSE(-5 > Complex(50, 10)); +} + +TEST(ComplexTests, lessEqualOperatorTest) { + EXPECT_TRUE(Complex(5, 10) <= Complex(1, 2)); + EXPECT_TRUE(Complex(5, -10) <= Complex(50, 10)); + + EXPECT_FALSE(Complex(5, -10) <= Complex(-50, 10)); + EXPECT_FALSE(Complex(55, 10) <= Complex(1, 10)); +} + +TEST(ComplexTests, integerLessEqualOperatorTest) { + EXPECT_TRUE(Complex(500) <= Integer(3283)); + EXPECT_TRUE(Complex(50, -10) <= Integer(-5)); +} + +TEST(ComplexTests, intLessEqualOperatorTest) { + EXPECT_TRUE(Complex(500) <= 3283); + EXPECT_TRUE(Complex(50, -10) <= -5); +} + +TEST(ComplexTests, integerFriendLessEqualOperatorTest) { + EXPECT_TRUE(Integer(500) <= Complex(500)); + EXPECT_TRUE(Integer(-5) <= Complex(50, 10)); + + EXPECT_FALSE(Integer(73687) <= Complex(30)); +} + +TEST(ComplexTests, intFriendLessEqualOperatorTest) { + EXPECT_TRUE(500 <= Complex(500)); + EXPECT_TRUE(-5 <= Complex(50, 10)); + + EXPECT_FALSE(73687 <= Complex(30)); +} + +TEST(ComplexTests, moreEqualOperatorTest) { + EXPECT_TRUE(Complex(5, 10) >= Complex(1, 2)); + EXPECT_TRUE(Complex(5, -10) >= Complex(-50, 10)); + EXPECT_TRUE(Complex(55, 10) >= Complex(1, 10)); + + EXPECT_FALSE(Complex(5, -10) >= Complex(50, 10)); +} + +TEST(ComplexTests, integerMoreEqualOperatorTest) { + EXPECT_TRUE(Complex(50, -10) >= Integer(-5)); + + EXPECT_FALSE(Complex(500) >= Integer(3283)); +} + +TEST(ComplexTests, intMoreEqualOperatorTest) { + EXPECT_TRUE(Complex(50, -10) >= -5); + + EXPECT_FALSE(Complex(500) >= 3283); +} + +TEST(ComplexTests, integerFriendMoreEqualOperatorTest) { + EXPECT_TRUE(Integer(500) >= Complex(500)); + EXPECT_TRUE(Integer(738657) >= Complex(320)); + + EXPECT_FALSE(Integer(-5) >= Complex(50, 10)); +} + +TEST(ComplexTests, intFriendMoreEqualOperatorTest) { + EXPECT_TRUE(500 >= Complex(500)); + EXPECT_TRUE(738657 >= Complex(320)); + + EXPECT_FALSE(-5 >= Complex(50, 10)); +} + +TEST(ComplexTests, realTest) { + EXPECT_EQ(Complex(5, 2).real(), Integer(5)); + EXPECT_EQ(Complex(55).real(), Integer(55)); + EXPECT_EQ(Complex(-10, 100).real(), Integer(-1)); +} + +TEST(ComplexTests, imagTest) { + EXPECT_EQ(Complex(5, 2).imag(), Integer(2)); + EXPECT_EQ(Complex(55).imag(), Integer(1)); + EXPECT_EQ(Complex(-10, 100).imag(), Integer(10)); +} + +TEST(ComplexTests, toStringTest) { + EXPECT_EQ(Complex(5, 2).toString(), "5/2"); + EXPECT_EQ(Complex(55, -10).toString(), "-11/2"); +} + +TEST(ComplexTests, simplifyTest) { + EXPECT_TRUE(is(Complex(5, 2).toMinimalObject())); + EXPECT_TRUE(is(Complex(55, 5).toMinimalObject())); + EXPECT_TRUE(is(Complex(-5, 2).toMinimalObject())); + EXPECT_TRUE(is(Complex(-55, 5).toMinimalObject())); + + EXPECT_EQ(Complex(5, 2).toMinimalObject()->toString(), "5/2"); + EXPECT_EQ(Complex(55, 5).toMinimalObject()->toString(), "11"); + EXPECT_EQ(Complex(-5, 2).toMinimalObject()->toString(), "-5/2"); + EXPECT_EQ(Complex(-55, 5).toMinimalObject()->toString(), "-11"); +} + +TEST(ComplexTests, equalsTest) { + Complex a; + Integer b; + Integer c(1); + + EXPECT_EQ(a, a); + EXPECT_EQ(a, Complex()); + EXPECT_EQ(Complex(), a); + EXPECT_EQ(a, cast(Complex())); + EXPECT_EQ(cast(Complex()), a); + EXPECT_EQ(a, b); + EXPECT_EQ(b, a); + EXPECT_NE(a, c); + EXPECT_NE(c, a); +} + +TEST(ComplexTests, getTypeIdTest) { + EXPECT_EQ(Complex::getTypeIdStatic(), MathObjectTypeId(MathObjectType::Complex)); + EXPECT_EQ(Complex().getTypeId(), MathObjectTypeId(MathObjectType::Complex)); +} diff --git a/tests/src/parser/ParserTests.cpp b/tests/src/parser/ParserTests.cpp index 2c342b121..d474d983f 100644 --- a/tests/src/parser/ParserTests.cpp +++ b/tests/src/parser/ParserTests.cpp @@ -63,6 +63,7 @@ #include "fintamath/literals/constants/E.hpp" #include "fintamath/literals/constants/False.hpp" #include "fintamath/literals/constants/IConstant.hpp" +#include "fintamath/literals/constants/ImaginaryUnit.hpp" #include "fintamath/literals/constants/Undefined.hpp" #include "fintamath/literals/constants/Inf.hpp" #include "fintamath/literals/constants/NegInf.hpp" @@ -182,6 +183,7 @@ TEST(ParseTests, parseConstantTest) { EXPECT_TRUE(is(IConstant::parse("Pi"))); EXPECT_TRUE(is(IConstant::parse("True"))); EXPECT_TRUE(is(IConstant::parse("False"))); + EXPECT_TRUE(is(IConstant::parse("I"))); EXPECT_TRUE(is(IConstant::parse("Inf"))); EXPECT_TRUE(is(IConstant::parse("-Inf"))); EXPECT_TRUE(is(IConstant::parse("ComplexInf")));