From 5b1c000a2ecb980393b45d10143d4f918b43f9e9 Mon Sep 17 00:00:00 2001 From: Fabian Homborg Date: Tue, 25 Aug 2020 16:45:31 +0200 Subject: [PATCH] math: Add bitwise and/or functions Just as `math "bitand(5,3)"` and `math "bitor(6,2)"`. These cast to long long before doing their thing, so they truncate to an integer, producing weird results with floats. That's to be expected because float representation is *very* different, and performing bitwise operations on floats feels quite useless. Fixes #7281. --- doc_src/cmds/math.rst | 5 +++++ src/tinyexpr.cpp | 16 ++++++++++++++++ tests/checks/math.fish | 14 ++++++++++++++ 3 files changed, 35 insertions(+) diff --git a/doc_src/cmds/math.rst b/doc_src/cmds/math.rst index e99fba8b8..ca644c825 100644 --- a/doc_src/cmds/math.rst +++ b/doc_src/cmds/math.rst @@ -75,6 +75,7 @@ Functions - ``asin`` - ``atan`` - ``atan2`` +- ``bitand``, ``bitor`` and ``bitxor`` to perform bitwise operations. These will throw away any non-integer parts and interpret the rest as an int. - ``ceil`` - ``cos`` - ``cosh`` @@ -114,6 +115,10 @@ Examples ``math 0xFF`` outputs 255, ``math 0 x 3`` outputs 0 (because it computes 0 multiplied by 3). +``math "bitand(0xFE, 0x2e)"`` outputs 46. + +``math "bitor(9,2)"`` outputs 11. + Compatibility notes ------------------- diff --git a/src/tinyexpr.cpp b/src/tinyexpr.cpp index 09ffcd5ba..a44503b2e 100644 --- a/src/tinyexpr.cpp +++ b/src/tinyexpr.cpp @@ -167,6 +167,19 @@ static double ncr(double n, double r) { static double npr(double n, double r) { return ncr(n, r) * fac(r); } + +static constexpr double bit_and(double a, double b) { + return static_cast(static_cast(a) & static_cast(b)); +} + +static constexpr double bit_or(double a, double b) { + return static_cast(static_cast(a) | static_cast(b)); +} + +static constexpr double bit_xor(double a, double b) { + return static_cast(static_cast(a) ^ static_cast(b)); +} + static const te_builtin functions[] = { /* must be in alphabetical order */ {"abs", reinterpret_cast(static_cast(fabs)), TE_FUNCTION1}, @@ -174,6 +187,9 @@ static const te_builtin functions[] = { {"asin", reinterpret_cast(static_cast(asin)), TE_FUNCTION1}, {"atan", reinterpret_cast(static_cast(atan)), TE_FUNCTION1}, {"atan2", reinterpret_cast(static_cast(atan2)), TE_FUNCTION2}, + {"bitand", reinterpret_cast(static_cast(bit_and)), TE_FUNCTION2}, + {"bitor", reinterpret_cast(static_cast(bit_or)), TE_FUNCTION2}, + {"bitxor", reinterpret_cast(static_cast(bit_xor)), TE_FUNCTION2}, {"ceil", reinterpret_cast(static_cast(ceil)), TE_FUNCTION1}, {"cos", reinterpret_cast(static_cast(cos)), TE_FUNCTION1}, {"cosh", reinterpret_cast(static_cast(cosh)), TE_FUNCTION1}, diff --git a/tests/checks/math.fish b/tests/checks/math.fish index b3cab0c4a..4e7636186 100644 --- a/tests/checks/math.fish +++ b/tests/checks/math.fish @@ -140,3 +140,17 @@ math "42 >= 1337" # CHECKERR: math: Error: Logical operations are not supported, use `test` instead # CHECKERR: '42 >= 1337' # CHECKERR: ^ + +math "bitand(0xFE, 1)" +# CHECK: 0 +math "bitor(0xFE, 1)" +# CHECK: 255 +math "bitxor(5, 1)" +# CHECK: 4 +math "bitand(5.5, 2)" +# CHECK: 0 +math "bitand(5.5, 1)" +# CHECK: 1 + +math "bitor(37 ^ 5, 255)" +# CHECK: 69343999