diff --git a/src/test/app/HostFuncImpl_test.cpp b/src/test/app/HostFuncImpl_test.cpp index 520342629a..de1468ca85 100644 --- a/src/test/app/HostFuncImpl_test.cpp +++ b/src/test/app/HostFuncImpl_test.cpp @@ -2176,7 +2176,7 @@ struct HostFuncImpl_test : public beast::unit_test::suite Bytes const floatIntMin = {0x99, 0x20, 0xc4, 0x9b, 0xa5, 0xe3, 0x53, 0xf8}; // -2^63 Bytes const floatIntZero = {0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; // 0 Bytes const floatIntMax = {0xd9, 0x20, 0xc4, 0x9b, 0xa5, 0xe3, 0x53, 0xf8}; // 2^63-1 - Bytes const floatUIntMax = {0xd9, 0x46, 0x8d, 0xb8, 0xba, 0xc7, 0x10, 0xcb}; // 2^64 + Bytes const floatUIntMax = {0xd9, 0x46, 0x8d, 0xb8, 0xba, 0xc7, 0x10, 0xcb}; // 2^64-1 Bytes const floatMaxExp = {0xEC, 0x43, 0x8D, 0x7E, 0xA4, 0xC6, 0x80, 0x00}; // 1e(80+15) Bytes const floatPreMaxExp = {0xEC, 0x03, 0x8D, 0x7E, 0xA4, 0xC6, 0x80, 0x00}; // 1e(79+15) Bytes const floatMinusMaxExp = {0xAC, 0x43, 0x8D, 0x7E, 0xA4, 0xC6, 0x80, 0x00}; // -1e(80+15) @@ -2365,7 +2365,7 @@ struct HostFuncImpl_test : public beast::unit_test::suite { auto const result = - hfs.floatSet(1, Number::maxExponent + normalExp + 1, 0); + hfs.floatSet(1, wasm_float::maxExponent + normalExp + 1, 0); BEAST_EXPECT(!result) && BEAST_EXPECT( result.error() == @@ -2406,8 +2406,8 @@ struct HostFuncImpl_test : public beast::unit_test::suite } { - auto const result = hfs.floatSet( - wasm_float::maxMantissa, wasm_float::maxExponent, 0); + auto const result = + hfs.floatSet(STAmount::cMaxValue, wasm_float::maxExponent, 0); BEAST_EXPECT(result) && BEAST_EXPECT(*result == floatMaxIOU); } @@ -2713,7 +2713,7 @@ struct HostFuncImpl_test : public beast::unit_test::suite { auto const y = hfs.floatSet( - wasm_float::maxMantissa, -normalExp - 1, 0); // 0.9999999... + STAmount::cMaxValue, -normalExp - 1, 0); // 0.9999999... if (BEAST_EXPECT(y)) { auto const result = diff --git a/src/xrpld/app/wasm/HostFuncImpl.h b/src/xrpld/app/wasm/HostFuncImpl.h index 7688eaf724..0183a74a12 100644 --- a/src/xrpld/app/wasm/HostFuncImpl.h +++ b/src/xrpld/app/wasm/HostFuncImpl.h @@ -274,10 +274,10 @@ public: namespace wasm_float { // The range for the mantissa and exponent when normalized -static std::int64_t constexpr minMantissa = STAmount::cMinValue; -static std::int64_t constexpr maxMantissa = STAmount::cMaxValue; -static int constexpr minExponent = STAmount::cMinOffset; -static int constexpr maxExponent = STAmount::cMaxOffset; +static std::int64_t constexpr minMantissa = 1'000'000'000'000'000ll; +static std::int64_t constexpr maxMantissa = (1ull << 54) - 1; +static int constexpr minExponent = -96; +static int constexpr maxExponent = 80; } // namespace wasm_float diff --git a/src/xrpld/app/wasm/detail/HostFuncImplFloat.cpp b/src/xrpld/app/wasm/detail/HostFuncImplFloat.cpp index 4e6c45ccf0..e424e3cedf 100644 --- a/src/xrpld/app/wasm/detail/HostFuncImplFloat.cpp +++ b/src/xrpld/app/wasm/detail/HostFuncImplFloat.cpp @@ -45,7 +45,7 @@ public: if (!m) return; - Number x(m, e + minExponent - 1); + Number x(makeNumber(m, e + wasm_float::minExponent - 1)); *static_cast(this) = x; good_ = true; } @@ -54,7 +54,7 @@ public: { } - Number2(int64_t x) : Number(x), good_(true) + Number2(int64_t x) : Number(makeNumber(x, 0)), good_(true) { } @@ -62,22 +62,36 @@ public: { using mtype = std::invoke_result_t; if (x <= std::numeric_limits::max()) - *this = Number(x); + *this = makeNumber(x, 0); else - *this = Number(x / 10, 1) + Number(x % 10); - + *this = makeNumber(x / 10, 1); good_ = true; } Number2(int64_t mantissa, int32_t exponent) - : Number(mantissa, exponent), good_(true) + : Number(makeNumber(mantissa, exponent)), good_(true) { } - Number2(Number const& n) : Number(n), good_(true) + Number2(Number const& n) + : Number(makeNumber(n.mantissa(), n.exponent())), good_(true) { } + static Number + makeNumber(int64_t mantissa, int32_t exponent) + { + if (mantissa < 0) + return Number(true, -mantissa, exponent, Number::normalized()); + return Number(false, mantissa, exponent, Number::normalized()); + } + + static Number + makeNumber(uint64_t mantissa, int32_t exponent) + { + return Number(false, mantissa, exponent, Number::normalized()); + } + operator bool() const { return good_; @@ -102,17 +116,17 @@ public: } return FLOAT_NULL; } - else if (absM > ((1ull << 54) - 1)) + else if (absM > wasm_float::maxMantissa) { return Unexpected( HostFunctionError::FLOAT_COMPUTATION_ERROR); // LCOV_EXCL_LINE } - else if (exponent() > maxExponent) + else if (exponent() > wasm_float::maxExponent) return Unexpected(HostFunctionError::FLOAT_COMPUTATION_ERROR); - else if (exponent() < minExponent) + else if (exponent() < wasm_float::minExponent) return FLOAT_NULL; - int const e = exponent() - minExponent + 1; //+97 + int const e = exponent() - wasm_float::minExponent + 1; //+97 v |= absM; v |= ((uint64_t)e) << 54; @@ -136,24 +150,30 @@ public: Bytes const Number2::FLOAT_NULL = {0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; -struct SetRound +struct FloatState { Number::rounding_mode oldMode_; + MantissaRange::mantissa_scale oldScale_; bool good_; - SetRound(int32_t mode) : oldMode_(Number::getround()), good_(false) + FloatState(int32_t mode) + : oldMode_(Number::getround()) + , oldScale_(Number::getMantissaScale()) + , good_(false) { if (mode < Number::rounding_mode::to_nearest || mode > Number::rounding_mode::upward) return; Number::setround(static_cast(mode)); + Number::setMantissaScale(MantissaRange::mantissa_scale::small); good_ = true; } - ~SetRound() + ~FloatState() { Number::setround(oldMode_); + Number::setMantissaScale(oldScale_); } operator bool() const @@ -186,7 +206,7 @@ floatFromIntImpl(int64_t x, int32_t mode) { try { - detail::SetRound rm(mode); + detail::FloatState rm(mode); if (!rm) return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED); @@ -206,12 +226,13 @@ floatFromUintImpl(uint64_t x, int32_t mode) { try { - detail::SetRound rm(mode); + detail::FloatState rm(mode); if (!rm) return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED); detail::Number2 num(x); - return num.toBytes(); + auto r = num.toBytes(); + return r; } // LCOV_EXCL_START catch (...) @@ -226,7 +247,7 @@ floatSetImpl(int64_t mantissa, int32_t exponent, int32_t mode) { try { - detail::SetRound rm(mode); + detail::FloatState rm(mode); if (!rm) return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED); detail::Number2 num(mantissa, exponent); @@ -264,7 +285,7 @@ floatAddImpl(Slice const& x, Slice const& y, int32_t mode) { try { - detail::SetRound rm(mode); + detail::FloatState rm(mode); if (!rm) return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED); @@ -291,7 +312,7 @@ floatSubtractImpl(Slice const& x, Slice const& y, int32_t mode) { try { - detail::SetRound rm(mode); + detail::FloatState rm(mode); if (!rm) return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED); detail::Number2 xx(x); @@ -317,7 +338,7 @@ floatMultiplyImpl(Slice const& x, Slice const& y, int32_t mode) { try { - detail::SetRound rm(mode); + detail::FloatState rm(mode); if (!rm) return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED); detail::Number2 xx(x); @@ -343,7 +364,7 @@ floatDivideImpl(Slice const& x, Slice const& y, int32_t mode) { try { - detail::SetRound rm(mode); + detail::FloatState rm(mode); if (!rm) return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED); detail::Number2 xx(x); @@ -370,7 +391,7 @@ floatRootImpl(Slice const& x, int32_t n, int32_t mode) if (n < 1) return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED); - detail::SetRound rm(mode); + detail::FloatState rm(mode); if (!rm) return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED); @@ -395,10 +416,10 @@ floatPowerImpl(Slice const& x, int32_t n, int32_t mode) { try { - if ((n < 0) || (n > maxExponent)) + if ((n < 0) || (n > wasm_float::maxExponent)) return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED); - detail::SetRound rm(mode); + detail::FloatState rm(mode); if (!rm) return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED); @@ -425,7 +446,7 @@ floatLogImpl(Slice const& x, int32_t mode) { try { - detail::SetRound rm(mode); + detail::FloatState rm(mode); if (!rm) return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED);