diff --git a/docs/manual/functions.qmd b/docs/manual/functions.qmd index 1fb40ba..35bb905 100644 --- a/docs/manual/functions.qmd +++ b/docs/manual/functions.qmd @@ -52,6 +52,8 @@ The following built-in functions are available: | SIN(Number) | Sine of the angle *Number* in radians. | | SINH(Number) | Hyperbolic sine of *Number*. | | SQRT(Number) | Square root of *Number*. | +| SUPPORTS32BIT() | Returns true if 32-bit integers are supported. This will affect the supported range of values for bitwise operations. | +| SUPPORTS64BIT() | Returns true if 64-bit integers are supported. This will affect the supported range of values for bitwise operations. | | TAN(Number) | Tangent of *Number*. | | TGAMMA(Number) | Returns the gamma function of *Number*. | | TRUNC(Number) | Discards the fractional part of *Number*.
\linebreak `TRUNC(-3.2)` = -3
\linebreak `TRUNC(3.2)` = 3 | diff --git a/tests/tetests.cpp b/tests/tetests.cpp index bd5b646..1416faa 100644 --- a/tests/tetests.cpp +++ b/tests/tetests.cpp @@ -758,6 +758,38 @@ TEST_CASE("Zeros", "[zeros]") CHECK(std::isnan(tep.evaluate("(1%0)%1"))); } +TEST_CASE("UINT support", "[uint]") + { + te_parser tep; + + if constexpr(te_parser::supports_32bit()) + { + INFO("Checking for handling of large value: " + + std::to_string(std::numeric_limits::max())); + CHECK(tep.evaluate(std::to_string(std::numeric_limits::max())) == + std::numeric_limits::max()); + CHECK(tep.evaluate( + "(" + std::to_string(std::numeric_limits::max()) + " - 100) + 100") == + std::numeric_limits::max()); + CHECK(tep.evaluate( + std::to_string(std::numeric_limits::max()) + " - 700") == + std::numeric_limits::max() - 700); + } + + if constexpr(te_parser::supports_64bit()) + { + INFO("Checking for handling of large value: " + + std::to_string(std::numeric_limits::max())); + CHECK(tep.evaluate(std::to_string(std::numeric_limits::max())) == + std::numeric_limits::max()); + CHECK(tep.evaluate( + "(" + std::to_string(std::numeric_limits::max()) + " - 100) + 100") == + std::numeric_limits::max()); + CHECK(tep.evaluate( + std::to_string(std::numeric_limits::max()) + " - 700") == + std::numeric_limits::max() - 700); + } + } TEST_CASE("Braces", "[braces]") { diff --git a/tinyexpr.cpp b/tinyexpr.cpp index b859571..7b370a8 100644 --- a/tinyexpr.cpp +++ b/tinyexpr.cpp @@ -848,6 +848,18 @@ namespace te_builtins return te_parser::te_max_value; } + [[nodiscard]] + constexpr static te_type te_supports_32bit() noexcept + { + return te_parser::supports_32bit() ? 1.0 : 0.0; + } + + [[nodiscard]] + constexpr static te_type te_supports_64bit() noexcept + { + return te_parser::supports_64bit() ? 1.0 : 0.0; + } + // cotangent [[nodiscard]] static te_type te_cot(te_type val) noexcept @@ -986,6 +998,8 @@ const std::set te_parser::m_functions = { // NOLINT { "sqrt", static_cast(te_builtins::te_sqrt), TE_PURE }, { "sum", static_cast(te_builtins::te_sum), static_cast(TE_PURE | TE_VARIADIC) }, + { "supports32bit", static_cast(te_builtins::te_supports_32bit), TE_PURE }, + { "supports64bit", static_cast(te_builtins::te_supports_64bit), TE_PURE }, { "tan", static_cast(te_builtins::te_tan), TE_PURE }, { "tanh", static_cast(te_builtins::te_tanh), TE_PURE }, { "tgamma", static_cast(te_builtins::te_tgamma), TE_PURE }, diff --git a/tinyexpr.h b/tinyexpr.h index 9380b4d..941f8b0 100644 --- a/tinyexpr.h +++ b/tinyexpr.h @@ -254,6 +254,16 @@ class te_parser /// @brief No position, which is what get_last_error_position() returns /// when there was no parsing error. constexpr static int64_t npos = -1; + /// @returns @c true if the parser's internal type can hold `uint32_t` without truncation. + constexpr static bool supports_32bit() noexcept + { + return std::numeric_limits::digits >= std::numeric_limits::digits; + } + /// @returns @c true if the parser's internal type can hold `uint64_t` without truncation. + constexpr static bool supports_64bit() noexcept + { + return std::numeric_limits::digits >= std::numeric_limits::digits; + } /** @brief Parses the input @c expression. @param expression The formula to compile. @returns Whether the expression compiled or not. (This can be checked