From d75a1bcf8af4185fa1f46c6b11d873e3f846050a Mon Sep 17 00:00:00 2001 From: Brent Huisman <brenthuisman@users.noreply.github.com> Date: Thu, 19 Nov 2020 12:49:47 +0100 Subject: [PATCH] Fix portability issues with long double in modcc. (#1246) Change from long double to double for storing floating point values in modcc. WSL, and Windows generally, treats long double differently than Linux, which leads to inconsistencies in literal numeric values in code generated by modcc on the two platforms. Fixes #1245 --- modcc/expression.hpp | 8 ++++---- modcc/symdiff.cpp | 6 +++--- modcc/symdiff.hpp | 6 +++--- test/unit-modcc/test_parser.cpp | 10 ++-------- 4 files changed, 12 insertions(+), 18 deletions(-) diff --git a/modcc/expression.hpp b/modcc/expression.hpp index 4d131b44..50c5c1b1 100644 --- a/modcc/expression.hpp +++ b/modcc/expression.hpp @@ -330,11 +330,11 @@ public: : Expression(loc), value_(std::stold(value)) {} - NumberExpression(Location loc, long double value) + NumberExpression(Location loc, double value) : Expression(loc), value_(value) {} - virtual long double value() const {return value_;}; + virtual double value() const {return value_;}; std::string to_string() const override { return purple(pprintf("%", value_)); @@ -350,7 +350,7 @@ public: void accept(Visitor *v) override; private: - long double value_; + double value_; }; // an integral number @@ -361,7 +361,7 @@ public: {} IntegerExpression(Location loc, long long integer) - : NumberExpression(loc, static_cast<long double>(integer)), integer_(integer) + : NumberExpression(loc, static_cast<double>(integer)), integer_(integer) {} long long integer_value() const {return integer_;} diff --git a/modcc/symdiff.cpp b/modcc/symdiff.cpp index 03b3d4f2..ef5e3222 100644 --- a/modcc/symdiff.cpp +++ b/modcc/symdiff.cpp @@ -262,7 +262,7 @@ private: std::string id_; }; -long double expr_value(Expression* e) { +double expr_value(Expression* e) { return e && e->is_number()? e->is_number()->value(): NAN; } @@ -273,7 +273,7 @@ private: static bool is_number(Expression* e) { return e && e->is_number(); } static bool is_number(const expression_ptr& e) { return is_number(e.get()); } - void as_number(Location loc, long double v) { + void as_number(Location loc, double v) { result_ = make_expression<NumberExpression>(loc, v); } @@ -293,7 +293,7 @@ public: result_ = nullptr; } - long double value() const { return expr_value(result_); } + double value() const { return expr_value(result_); } bool is_number() const { return is_number(result_); } diff --git a/modcc/symdiff.hpp b/modcc/symdiff.hpp index 31c71501..9e819215 100644 --- a/modcc/symdiff.hpp +++ b/modcc/symdiff.hpp @@ -25,7 +25,7 @@ bool involves_identifier(Expression* e, const identifier_set& ids); expression_ptr constant_simplify(Expression* e); // Extract value of expression that is a NumberExpression, or else return NAN. -long double expr_value(Expression* e); +double expr_value(Expression* e); // Test if expression is a NumberExpression with value zero. inline bool is_zero(Expression* e) { @@ -57,11 +57,11 @@ inline expression_ptr constant_simplify(const expression_ptr& e) { return constant_simplify(e.get()); } -inline long double expr_value(const expression_ptr& e) { +inline double expr_value(const expression_ptr& e) { return expr_value(e.get()); } -inline long double is_zero(const expression_ptr& e) { +inline double is_zero(const expression_ptr& e) { return is_zero(e.get()); } diff --git a/test/unit-modcc/test_parser.cpp b/test/unit-modcc/test_parser.cpp index 10952756..2bead45e 100644 --- a/test/unit-modcc/test_parser.cpp +++ b/test/unit-modcc/test_parser.cpp @@ -580,7 +580,7 @@ TEST(Parser, parse_conserve) { } } -long double eval(Expression *e) { +double eval(Expression *e) { if (auto n = e->is_number()) { return n->value(); } @@ -606,7 +606,7 @@ long double eval(Expression *e) { default:; } } - return std::numeric_limits<long double>::quiet_NaN(); + return std::numeric_limits<double>::quiet_NaN(); } // test parsing of expressions for correctness @@ -654,12 +654,6 @@ TEST(Parser, parse_binop) { for (const auto& test_case: tests) { std::unique_ptr<Expression> e; EXPECT_TRUE(check_parse(e, &Parser::parse_expression, test_case.first)); - - // A loose tolerance of 1e-10 is required here because the eval() - // function uses long double for intermediate results (like constant - // folding in modparser). For expressions with transcendental - // operations this can see relatively large divergence between the - // double and long double results. EXPECT_NEAR(eval(e.get()), test_case.second, 1e-10); } } -- GitLab