Skip to content

Commit

Permalink
Refactor Real numbers
Browse files Browse the repository at this point in the history
  • Loading branch information
fintarin committed Aug 1, 2023
1 parent 5eae5f8 commit f3169cd
Show file tree
Hide file tree
Showing 28 changed files with 180 additions and 202 deletions.
6 changes: 0 additions & 6 deletions include/fintamath/numbers/Real.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,12 @@ class Real : public INumberCRTP<Real> {

std::string toString() const override;

std::unique_ptr<IMathObject> toMinimalObject() const override;

bool isPrecise() const override;

Real precise(uint8_t precision) const;

int sign() const;

bool isNearZero() const;

const boost::multiprecision::cpp_dec_float_100 &getBackend() const;

static MathObjectTypeId getTypeIdStatic() {
Expand Down Expand Up @@ -75,8 +71,6 @@ class Real : public INumberCRTP<Real> {
boost::multiprecision::cpp_dec_float_100 backend;

uint8_t ouputPrecision = FINTAMATH_PRECISION;

static const boost::multiprecision::cpp_dec_float_100 DELTA;
};

}
40 changes: 14 additions & 26 deletions src/fintamath/numbers/Real.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,6 @@ using namespace boost::multiprecision;

namespace fintamath {

static cpp_dec_float_100 initDelta() {
static const cpp_dec_float_100 delta = pow(cpp_dec_float_100(10), -FINTAMATH_PRECISION);
return delta;
}

const cpp_dec_float_100 Real::DELTA = initDelta();

Real::Real() = default;

Real::Real(const Real &rhs) = default;
Expand Down Expand Up @@ -85,8 +78,10 @@ std::string Real::toString() const {
ss << backend;
std::string res = ss.str();

if (size_t ePos = res.find('e'); ePos != std::string::npos) {
res.replace(ePos, 1, "*10^");
size_t expPos = res.find('e');

if (expPos != std::string::npos) {
res.replace(expPos, 1, "*10^");

if (size_t plusPos = res.find('+'); plusPos != std::string::npos) {
res.replace(plusPos, 1, "");
Expand All @@ -96,18 +91,15 @@ std::string Real::toString() const {
res.replace(negZeroPos + 1, 1, "");
}
}
else {
expPos = res.length();
}

return res;
}

std::unique_ptr<IMathObject> Real::toMinimalObject() const {
if (backend.backend().isfinite()) {
if (std::string str = toString(); str.find('.') == std::string::npos && str.find('*') == std::string::npos) {
return std::make_unique<Integer>(str);
}
if (res.find('.') == std::string::npos) {
res.insert(expPos, ".0");
}

return clone();
return res;
}

bool Real::isPrecise() const {
Expand All @@ -125,16 +117,12 @@ int Real::sign() const {
return backend.sign();
}

bool Real::isNearZero() const {
return abs(backend) < DELTA;
}

const cpp_dec_float_100 &Real::getBackend() const {
return backend;
}

bool Real::equals(const Real &rhs) const {
return (*this - rhs).isNearZero();
return backend == rhs.backend;
}

bool Real::less(const Real &rhs) const {
Expand Down Expand Up @@ -167,17 +155,17 @@ Real &Real::multiply(const Real &rhs) {
}

Real &Real::divide(const Real &rhs) {
if (rhs.isNearZero()) {
backend /= rhs.backend;

if (!backend.backend().isfinite()) {
throw UndefinedBinaryOperatorException("/", toString(), rhs.toString());
}

backend /= rhs.backend;
return *this;
}

Real &Real::negate() {
backend = -backend;
return *this;
}

}
27 changes: 6 additions & 21 deletions src/fintamath/numbers/RealFunctions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,13 @@ Real sqrt(const Real &rhs) {
}

Real pow(const Real &lhs, const Real &rhs) {
if (lhs.isNearZero() && rhs.isNearZero()) {
throw UndefinedBinaryOperatorException("^", lhs.toString(), rhs.toString());
}
if (lhs < 0 && !is<Integer>(rhs.toMinimalObject())) { // TODO: do not use toMinimalObject
if (lhs == 0 && rhs == 0) {
throw UndefinedBinaryOperatorException("^", lhs.toString(), rhs.toString());
}

cpp_dec_float_100 res = pow(lhs.getBackend(), rhs.getBackend());

if (res.backend().isinf() || res.backend().isnan()) {
if (!res.backend().isfinite()) {
throw UndefinedBinaryOperatorException("^", lhs.toString(), rhs.toString());
}

Expand Down Expand Up @@ -73,23 +70,11 @@ Real lg(const Real &rhs) {
}

Real sin(const Real &rhs) {
Real res(sin(rhs.getBackend()));

if (res.isNearZero()) {
return 0;
}

return res;
return {sin(rhs.getBackend())};
}

Real cos(const Real &rhs) {
Real res(cos(rhs.getBackend()));

if (res.isNearZero()) {
return 0;
}

return res;
return {cos(rhs.getBackend())};
}

Real tan(const Real &rhs) {
Expand All @@ -113,7 +98,7 @@ Real cot(const Real &rhs) {
Real asin(const Real &rhs) {
cpp_dec_float_100 res = asin(rhs.getBackend());

if (res.backend().isnan()) {
if (!res.backend().isfinite()) {
throw UndefinedFunctionException("asin", {rhs.toString()});
}

Expand All @@ -123,7 +108,7 @@ Real asin(const Real &rhs) {
Real acos(const Real &rhs) {
cpp_dec_float_100 res = acos(rhs.getBackend());

if (res.backend().isnan()) {
if (!res.backend().isfinite()) {
throw UndefinedFunctionException("acos", {rhs.toString()});
}

Expand Down
6 changes: 3 additions & 3 deletions tests/src/FintamathTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ TEST(FintamathTests, fintamathTests) {
EXPECT_EQ(solve(expr).toString(), "x = 7/2");

expr = Expression("-3x^2 + 28x - 49 = 0");
EXPECT_EQ(solve(expr).precise(2).toString(), "x = 2.3 | x = 7");
EXPECT_EQ(solve(expr).precise(2).toString(), "x = 2.3 | x = 7.0");

//-------------------------------------------------------------------------------------//

Expand All @@ -78,7 +78,7 @@ TEST(FintamathTests, fintamathTests) {
EXPECT_EQ(expr.toString(), "x^6 + 6 x^5 + 15 x^4 + 20 x^3 + 15 x^2 + 6 x + 1");

expr = expr.precise(10);
EXPECT_EQ(expr.toString(), "x^6 + 6 x^5 + 15 x^4 + 20 x^3 + 15 x^2 + 6 x + 1");
EXPECT_EQ(expr.toString(), "x^6.0 + 6.0 x^5.0 + 15.0 x^4.0 + 20.0 x^3.0 + 15.0 x^2.0 + 6.0 x + 1.0");

expr = pow(x + 1, 7);
EXPECT_EQ(expr.toString(), "x^7 + 7 x^6 + 21 x^5 + 35 x^4 + 35 x^3 + 21 x^2 + 7 x + 1");
Expand All @@ -87,5 +87,5 @@ TEST(FintamathTests, fintamathTests) {
EXPECT_EQ(expr.toString(), "x^7 + 7 x^6 + 21 x^5 + 35 x^4 + 35 x^3 + 21 x^2 + 7 x + 1");

expr = expr.precise(10);
EXPECT_EQ(expr.toString(), "x^7 + 7 x^6 + 21 x^5 + 35 x^4 + 35 x^3 + 21 x^2 + 7 x + 1");
EXPECT_EQ(expr.toString(), "x^7.0 + 7.0 x^6.0 + 21.0 x^5.0 + 35.0 x^4.0 + 35.0 x^3.0 + 21.0 x^2.0 + 7.0 x + 1.0");
}
40 changes: 24 additions & 16 deletions tests/src/expressions/ExpressionFunctionsTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,50 +144,58 @@ TEST(ExpressionFunctionsTests, lgTest) {
}

TEST(ExpressionFunctionsTests, sinTest) {
EXPECT_EQ(sin(Expression("5*Pi")).toString(), "sin(5 Pi)"); // TODO trigonometry
EXPECT_EQ(sin(Expression("Pi/2")).toString(), "sin(Pi/2)"); // TODO trigonometry
// TODO trigonometry
EXPECT_EQ(sin(Expression("5*Pi")).toString(), "sin(5 Pi)");
EXPECT_EQ(sin(Expression("Pi/2")).toString(), "sin(Pi/2)");
EXPECT_EQ(sin(Expression("a+b")).toString(), "sin(a + b)");
}

TEST(ExpressionFunctionsTests, cosTest) {
EXPECT_EQ(cos(Expression("5*Pi")).toString(), "cos(5 Pi)"); // TODO trigonometry
EXPECT_EQ(cos(Expression("3*Pi/2")).toString(), "cos((3 Pi)/2)"); // TODO trigonometry
// TODO trigonometry
EXPECT_EQ(cos(Expression("5*Pi")).toString(), "cos(5 Pi)");
EXPECT_EQ(cos(Expression("3*Pi/2")).toString(), "cos((3 Pi)/2)");
EXPECT_EQ(cos(Expression("8*a")).toString(), "cos(8 a)");
}

TEST(ExpressionFunctionsTests, tanTest) {
EXPECT_EQ(tan(Expression("0")).toString(), "0");
EXPECT_EQ(tan(Expression("3*Pi/4")).toString(), "tan((3 Pi)/4)"); // TODO trigonometry
// TODO trigonometry
EXPECT_EQ(tan(Expression("0")).toString(), "tan(0)");
EXPECT_EQ(tan(Expression("3*Pi/4")).toString(), "tan((3 Pi)/4)");
EXPECT_EQ(tan(Expression("a^3")).toString(), "tan(a^3)");
}

TEST(ExpressionFunctionsTests, cotTest) {
EXPECT_EQ(cot(Expression("Pi/4")).toString(), "cot(Pi/4)"); // TODO trigonometry
EXPECT_EQ(cot(Expression("Pi/2")).toString(), "cot(Pi/2)"); // TODO trigonometry
// TODO trigonometry
EXPECT_EQ(cot(Expression("Pi/4")).toString(), "cot(Pi/4)");
EXPECT_EQ(cot(Expression("Pi/2")).toString(), "cot(Pi/2)");
EXPECT_EQ(cot(Expression("a/5")).toString(), "cot(a/5)");
}

TEST(ExpressionFunctionsTests, asinTest) {
EXPECT_EQ(asin(Expression("0")).toString(), "0");
EXPECT_EQ(asin(Expression("1")).toString(), "asin(1)"); // TODO trigonometry
// TODO trigonometry
EXPECT_EQ(asin(Expression("0")).toString(), "asin(0)");
EXPECT_EQ(asin(Expression("1")).toString(), "asin(1)");
EXPECT_EQ(asin(Expression("a+b")).toString(), "asin(a + b)");
}

TEST(ExpressionFunctionsTests, acosTest) {
EXPECT_EQ(acos(Expression("0")).toString(), "acos(0)"); // TODO trigonometry
EXPECT_EQ(acos(Expression("1")).toString(), "0");
// TODO trigonometry
EXPECT_EQ(acos(Expression("0")).toString(), "acos(0)");
EXPECT_EQ(acos(Expression("1")).toString(), "acos(1)");
EXPECT_EQ(acos(Expression("8*a")).toString(), "acos(8 a)");
}

TEST(ExpressionFunctionsTests, atanTest) {
EXPECT_EQ(atan(Expression("0")).toString(), "0");
EXPECT_EQ(atan(Expression("-1")).toString(), "atan(-1)"); // TODO trigonometry
// TODO trigonometry
EXPECT_EQ(atan(Expression("0")).toString(), "atan(0)");
EXPECT_EQ(atan(Expression("-1")).toString(), "atan(-1)");
EXPECT_EQ(atan(Expression("a^3")).toString(), "atan(a^3)");
}

TEST(ExpressionFunctionsTests, acotTest) {
EXPECT_EQ(acot(Expression("1")).toString(), "acot(1)"); // TODO trigonometry
// EXPECT_EQ(acot(Expression("0")).toString(), "acot(0)"); // TODO trigonometry
// TODO trigonometry
EXPECT_EQ(acot(Expression("1")).toString(), "acot(1)");
EXPECT_EQ(acot(Expression("0")).toString(), "acot(0)");
EXPECT_EQ(acot(Expression("a/5")).toString(), "acot(a/5)");
}

Expand Down
35 changes: 18 additions & 17 deletions tests/src/expressions/ExpressionTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1110,10 +1110,10 @@ TEST(ExpressionTests, preciseTest) {
"4.605170185988091368035982909368728415202202977257545952066655801935145219354705");
EXPECT_EQ(Expression("lg99").precise().toString(),
"1.9956351945975499153402557777532548601069599188478448242562702992902113378005716");
EXPECT_EQ(Expression("lg100").precise().toString(), "2");
EXPECT_EQ(Expression("lg100").precise().toString(), "2.0");
EXPECT_EQ(Expression("lb100").precise().toString(),
"6.6438561897747246957406388589787803517296627860491612241095127916318695532172504");
EXPECT_EQ(Expression("lb4").precise().toString(), "2");
EXPECT_EQ(Expression("lb4").precise().toString(), "2.0");
EXPECT_EQ(Expression("sin10").precise().toString(),
"-0.54402111088936981340474766185137728168364301291622389157418401261675720964049343");
EXPECT_EQ(Expression("cos10").precise().toString(),
Expand Down Expand Up @@ -1158,7 +1158,7 @@ TEST(ExpressionTests, preciseTest) {
"0.70807341827357119349878411475038109488300038553777244537757498689098246806203958");
EXPECT_EQ(Expression("sin(10^30)").precise().toString(),
"-0.090116901912138058030386428952987330274396332993043449885460666579773983476795775");
EXPECT_EQ(Expression("sin(1)^2+cos(1)^2").precise().toString(), "1");
EXPECT_EQ(Expression("sin(1)^2+cos(1)^2").precise().toString(), "1.0");
EXPECT_EQ(Expression("sin(Pi/3)").precise().toString(),
"0.86602540378443864676372317075293618347140262690519031402790348972596650845440002");
EXPECT_EQ(Expression("cos(Pi/3)").precise().toString(), "0.5");
Expand All @@ -1175,15 +1175,16 @@ TEST(ExpressionTests, preciseTest) {
EXPECT_EQ(Expression("sin(60deg)").precise().toString(),
"0.86602540378443864676372317075293618347140262690519031402790348972596650845440002");

EXPECT_EQ(Expression("tan(Pi/2)").precise().toString(),
"tan(1.5707963267948966192313216916397514420985846996875529104874722961539082031431045)");
EXPECT_EQ(Expression("cot(0)").precise().toString(), "cot(0)");
EXPECT_EQ(Expression("asin(2)").precise().toString(), "asin(2)");
EXPECT_EQ(Expression("acos(2)").precise().toString(), "acos(2)");
EXPECT_EQ(Expression("tan(3/2*Pi)").precise().toString(),
"tan(4.7123889803846898576939650749192543262957540990626587314624168884617246094293135)");
EXPECT_EQ(Expression("cot(2*Pi)").precise().toString(),
"cot(6.283185307179586476925286766559005768394338798750211641949889184615632812572418)");
// TODO! trigonometry
// EXPECT_EQ(Expression("tan(Pi/2)").precise().toString(),
// "tan(1.5707963267948966192313216916397514420985846996875529104874722961539082031431045)");
// EXPECT_EQ(Expression("cot(0)").precise().toString(), "cot(0)");
// EXPECT_EQ(Expression("asin(2)").precise().toString(), "asin(2)");
// EXPECT_EQ(Expression("acos(2)").precise().toString(), "acos(2)");
// EXPECT_EQ(Expression("tan(3/2*Pi)").precise().toString(),
// "tan(4.7123889803846898576939650749192543262957540990626587314624168884617246094293135)");
// EXPECT_EQ(Expression("cot(2*Pi)").precise().toString(),
// "cot(6.283185307179586476925286766559005768394338798750211641949889184615632812572418)");

EXPECT_EQ(Expression("E^(E^(E^(E^(E^E))))").precise().toString(),
"2.7182818284590452353602874713526624977572470936999595749669676277240766303535476^(2."
Expand All @@ -1196,21 +1197,21 @@ TEST(ExpressionTests, preciseTest) {
"4.2608204763570033817001212246457024649334243739593219749116048935993443487275001");
EXPECT_EQ(Expression("(2/3)!!").precise().toString(),
"0.66666666666666666666666666666666666666666666666666666666666666666666666666666667!!");
EXPECT_EQ(Expression("(1/1000000000000000000000000000000000000000)!!").precise().toString(), "(1*10^-39)!!");
EXPECT_EQ(Expression("(-1)!!").precise().toString(), "(-1)!!");
EXPECT_EQ(Expression("(1/1000000000000000000000000000000000000000)!!").precise().toString(), "(1.0*10^-39)!!");
EXPECT_EQ(Expression("(-1)!!").precise().toString(), "(-1.0)!!");

EXPECT_EQ(Expression("10^10000").precise(8).toString(), "1*10^10000");
EXPECT_EQ(Expression("10^10000").precise(8).toString(), "1.0*10^10000");
EXPECT_EQ(Expression("x+E").precise(8).toString(), "x + 2.7182818");
EXPECT_EQ(Expression("x^(100!)").precise(8).toString(), "x^(9.3326215*10^157)");
EXPECT_EQ(Expression("9^10000").precise(8).toString(), "2.6613034*10^9542");
EXPECT_EQ(Expression("sin(E)").precise(16).toString(), "0.4107812905029087");
EXPECT_EQ(Expression("sin(sin(E))").precise(30).toString(), "0.39932574404189139297067052142");
EXPECT_EQ(Expression("(sqrt(2) + 1)^2").precise(5).toString(), "5.8284");
EXPECT_EQ(Expression("(sqrt(2) - a - 1)^2").precise(5).toString(), "a^2 - 0.82843 a + 0.17157");
EXPECT_EQ(Expression("(sqrt(2) - a - 1)^2").precise(5).toString(), "a^2.0 - 0.82843 a + 0.17157");
EXPECT_EQ(Expression("2^200/x").precise(10).toString(), "(1.606938044*10^60)/x");
EXPECT_EQ(Expression("x/2^200").precise(10).toString(), "6.223015278*10^-61 x");
EXPECT_EQ(Expression("((x - z)^2 / 8) * (x / y)").precise().toString(),
"(0.125 x^3)/y + (-0.25 x^2 z)/y + (0.125 x z^2)/y");
"(0.125 x^3.0)/y + (-0.25 x^2.0 z)/y + (0.125 x z^2.0)/y");

EXPECT_EQ(Expression("ln(x)").precise().toString(), "ln(x)");
EXPECT_EQ(Expression("sqrt(x)").precise().toString(), "sqrt(x)");
Expand Down
2 changes: 1 addition & 1 deletion tests/src/functions/hyperbolic/AcoshTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ TEST(AcoshTests, getFunctionTypeTest) {
}

TEST(AcoshTests, callTest) {
EXPECT_EQ(f(Integer(1))->toString(), "0");
EXPECT_EQ(f(Integer(1))->toString(), "0.0");
EXPECT_EQ(f(Integer(2))->toString(),
"1.316957896924816708625046347307968444026981971467516479768472256920460185416444");
EXPECT_EQ(f(Rational(11, 10))->toString(),
Expand Down
2 changes: 1 addition & 1 deletion tests/src/functions/hyperbolic/AsinhTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ TEST(AsinhTests, getFunctionTypeTest) {
}

TEST(AsinhTests, callTest) {
EXPECT_EQ(f(Integer(0))->toString(), "0");
EXPECT_EQ(f(Integer(0))->toString(), "0.0");
EXPECT_EQ(f(Integer(1))->toString(),
"0.88137358701954302523260932497979230902816032826163541075329560865337718422202609");
EXPECT_EQ(f(Rational(1, 10))->toString(),
Expand Down
2 changes: 1 addition & 1 deletion tests/src/functions/hyperbolic/AtanhTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ TEST(AtanhTests, getFunctionTypeTest) {
}

TEST(AtanhTests, callTest) {
EXPECT_EQ(f(Integer(0))->toString(), "0");
EXPECT_EQ(f(Integer(0))->toString(), "0.0");
EXPECT_EQ(f(Rational(10, 11))->toString(),
"1.5222612188617114982502989901828527171422876437023053200970422417875370779853391");
EXPECT_EQ(f(Rational(-10, 11))->toString(),
Expand Down
2 changes: 1 addition & 1 deletion tests/src/functions/hyperbolic/CoshTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ TEST(CoshTests, getFunctionTypeTest) {
}

TEST(CoshTests, callTest) {
EXPECT_EQ(f(Integer(0))->toString(), "1");
EXPECT_EQ(f(Integer(0))->toString(), "1.0");
EXPECT_EQ(f(Integer(5))->toString(),
"74.20994852478784444410610804448771402386825858945317206609157532124237417173709");
EXPECT_EQ(f(Integer(-5))->toString(),
Expand Down
2 changes: 1 addition & 1 deletion tests/src/functions/hyperbolic/SinhTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ TEST(SinhTests, getFunctionTypeTest) {
}

TEST(SinhTests, callTest) {
EXPECT_EQ(f(Integer(0))->toString(), "0");
EXPECT_EQ(f(Integer(0))->toString(), "0.0");
EXPECT_EQ(f(Integer(5))->toString(),
"74.203210577788758977009471996064565599619409004425816980661269789669690649221486");
EXPECT_EQ(f(Integer(-5))->toString(),
Expand Down
Loading

0 comments on commit f3169cd

Please sign in to comment.