mirror of
https://github.com/XRPLF/rippled.git
synced 2026-07-25 16:10:57 +00:00
Fix float point binary format (#5688)
This commit is contained in:
@@ -1941,7 +1941,7 @@ struct HostFuncImpl_test : public beast::unit_test::suite
|
||||
int const normalExp = 15;
|
||||
|
||||
Bytes const floatIntMin = {0x99, 0x20, 0xc4, 0x9b, 0xa5, 0xe3, 0x53, 0xf8}; // -2^63
|
||||
Bytes const floatIntZero = {0xd8, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; // 0
|
||||
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 floatMaxExp = {0xEC, 0x43, 0x8D, 0x7E, 0xA4, 0xC6, 0x80, 0x00}; // 1e(80+15)
|
||||
@@ -1954,8 +1954,7 @@ struct HostFuncImpl_test : public beast::unit_test::suite
|
||||
Bytes const float1More = {0xD4, 0x83, 0x8D, 0x7E, 0xA4, 0xC6, 0x80, 0x01}; // 1.000 000 000 000 001
|
||||
Bytes const float2 = {0xD4, 0x87, 0x1A, 0xFD, 0x49, 0x8D, 0x00, 0x00}; // 2
|
||||
Bytes const float10 = {0xD4, 0xC3, 0x8D, 0x7E, 0xA4, 0xC6, 0x80, 0x00}; // 10
|
||||
Bytes const floatMaxXRP = {0x5F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; // 2^62-1
|
||||
Bytes const floatMaxMPT = {0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; // 2^62-1
|
||||
Bytes const floatInvalidZero = {0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; // INVALID
|
||||
|
||||
std::string const invalid = "invalid_data";
|
||||
|
||||
@@ -2187,6 +2186,14 @@ struct HostFuncImpl_test : public beast::unit_test::suite
|
||||
result.error() == HostFunctionError::FLOAT_INPUT_MALFORMED);
|
||||
}
|
||||
|
||||
{
|
||||
auto const result =
|
||||
hfs.floatCompare(makeSlice(floatInvalidZero), Slice());
|
||||
BEAST_EXPECT(!result) &&
|
||||
BEAST_EXPECT(
|
||||
result.error() == HostFunctionError::FLOAT_INPUT_MALFORMED);
|
||||
}
|
||||
|
||||
{
|
||||
auto const result =
|
||||
hfs.floatCompare(makeSlice(float1), makeSlice(invalid));
|
||||
@@ -2723,48 +2730,17 @@ struct HostFuncImpl_test : public beast::unit_test::suite
|
||||
{
|
||||
auto const result =
|
||||
hfs.floatCompare(makeSlice(x), makeSlice(float10));
|
||||
BEAST_EXPECT(result && *result == 0);
|
||||
}
|
||||
|
||||
{
|
||||
auto const result =
|
||||
hfs.floatAdd(makeSlice(x), makeSlice(float10), 0);
|
||||
if (BEAST_EXPECT(result))
|
||||
{
|
||||
auto const result2 =
|
||||
hfs.floatCompare(makeSlice(*result), makeSlice(*y));
|
||||
BEAST_EXPECT(result2 && *result2 == 0);
|
||||
}
|
||||
}
|
||||
|
||||
// underflow
|
||||
x[7] = 1;
|
||||
{
|
||||
auto const result =
|
||||
hfs.floatDivide(makeSlice(x), makeSlice(float1More), 0);
|
||||
BEAST_EXPECT(
|
||||
!result &&
|
||||
result.error() == HostFunctionError::FLOAT_COMPUTATION_ERROR);
|
||||
result.error() == HostFunctionError::FLOAT_INPUT_MALFORMED);
|
||||
}
|
||||
|
||||
{
|
||||
auto const result = hfs.floatMultiply(
|
||||
makeSlice(floatMaxXRP), makeSlice(floatIntZero), 0);
|
||||
if (BEAST_EXPECT(result))
|
||||
{
|
||||
auto const result2 = hfs.floatCompare(
|
||||
makeSlice(*result), makeSlice(floatIntZero));
|
||||
BEAST_EXPECT(result2 && *result2 == 0);
|
||||
}
|
||||
}
|
||||
|
||||
// overflow
|
||||
{
|
||||
auto const result =
|
||||
hfs.floatAdd(makeSlice(floatMaxXRP), makeSlice(float1), 0);
|
||||
hfs.floatAdd(makeSlice(float10), makeSlice(x), 0);
|
||||
BEAST_EXPECT(
|
||||
!result &&
|
||||
result.error() == HostFunctionError::FLOAT_COMPUTATION_ERROR);
|
||||
result.error() == HostFunctionError::FLOAT_INPUT_MALFORMED);
|
||||
}
|
||||
|
||||
// MPT
|
||||
@@ -2775,26 +2751,17 @@ struct HostFuncImpl_test : public beast::unit_test::suite
|
||||
{
|
||||
auto const result =
|
||||
hfs.floatCompare(makeSlice(x), makeSlice(float10));
|
||||
BEAST_EXPECT(result && *result == 0);
|
||||
}
|
||||
|
||||
{
|
||||
auto const result =
|
||||
hfs.floatAdd(makeSlice(x), makeSlice(float10), 0);
|
||||
if (BEAST_EXPECT(result))
|
||||
{
|
||||
auto const result2 =
|
||||
hfs.floatCompare(makeSlice(*result), makeSlice(*y));
|
||||
BEAST_EXPECT(result2 && *result2 == 0);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
auto const result =
|
||||
hfs.floatAdd(makeSlice(floatMaxMPT), makeSlice(float1), 0);
|
||||
BEAST_EXPECT(
|
||||
!result &&
|
||||
result.error() == HostFunctionError::FLOAT_COMPUTATION_ERROR);
|
||||
result.error() == HostFunctionError::FLOAT_INPUT_MALFORMED);
|
||||
}
|
||||
|
||||
{
|
||||
auto const result =
|
||||
hfs.floatAdd(makeSlice(float10), makeSlice(x), 0);
|
||||
BEAST_EXPECT(
|
||||
!result &&
|
||||
result.error() == HostFunctionError::FLOAT_INPUT_MALFORMED);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -546,10 +546,18 @@ struct Wasm_test : public beast::unit_test::suite
|
||||
|
||||
TestHostFunctions hf(env, 0);
|
||||
auto re = runEscrowWasm(wasm, funcName, {}, &hf, 100'000);
|
||||
if (BEAST_EXPECT(re.has_value()))
|
||||
{
|
||||
BEAST_EXPECT(re->result && (re->cost == 91'412));
|
||||
}
|
||||
BEAST_EXPECT(re && re->result && (re->cost == 91'412));
|
||||
env.close();
|
||||
}
|
||||
|
||||
{
|
||||
std::string const wasmHex = float0Hex;
|
||||
std::string const wasmStr = boost::algorithm::unhex(wasmHex);
|
||||
std::vector<uint8_t> const wasm(wasmStr.begin(), wasmStr.end());
|
||||
|
||||
TestHostFunctions hf(env, 0);
|
||||
auto re = runEscrowWasm(wasm, funcName, {}, &hf, 100'000);
|
||||
BEAST_EXPECT(re && re->result && (re->cost == 6'533));
|
||||
env.close();
|
||||
}
|
||||
}
|
||||
@@ -732,7 +740,6 @@ struct Wasm_test : public beast::unit_test::suite
|
||||
testFloat();
|
||||
|
||||
testCodecovWasm();
|
||||
|
||||
testDisabledFloat();
|
||||
|
||||
// perfTest();
|
||||
|
||||
@@ -12411,6 +12411,49 @@ extern std::string const floatHex =
|
||||
"6f62616c732b136e6f6e7472617070696e672d6670746f696e742b0f7265666572656e6365"
|
||||
"2d74797065732b087369676e2d657874";
|
||||
|
||||
extern std::string const float0Hex =
|
||||
"0061736d0100000001290560057f7f7f7f7f017f60047e7f7f7f017f6007"
|
||||
"7f7f7f7f7f7f7f017f60047f7f7f7f017f6000017f025f0408686f73745f"
|
||||
"6c6962057472616365000008686f73745f6c69620e666c6f61745f66726f"
|
||||
"6d5f696e74000108686f73745f6c69620e666c6f61745f73756274726163"
|
||||
"74000208686f73745f6c69620d666c6f61745f636f6d7061726500030302"
|
||||
"010405030100110619037f01418080c0000b7f00419281c0000b7f0041a0"
|
||||
"81c0000b072e04066d656d6f727902000666696e69736800040a5f5f6461"
|
||||
"74615f656e6403010b5f5f686561705f6261736503020abe0201bb020101"
|
||||
"7f23808080800041206b2200248080808000418080c08000411541004100"
|
||||
"41001080808080001a200042003703084200200041086a41084100108180"
|
||||
"8080001a20004200370310420a200041106a410841001081808080001a20"
|
||||
"0042003703180240200041106a4108200041106a4108200041186a410841"
|
||||
"001082808080004108460d00419580c08000411541004100410010808080"
|
||||
"80001a0b02400240200041086a4108200041186a41081083808080000d00"
|
||||
"41aa80c0800041174100410041001080808080001a0c010b41c180c08000"
|
||||
"41164100410041001080808080001a0b02400240200041086a410841d780"
|
||||
"c0800041081083808080000d0041df80c08000411a410041004100108080"
|
||||
"8080001a0c010b41f980c0800041194100410041001080808080001a0b20"
|
||||
"0041206a24808080800041010b0b9c010100418080c0000b92010a242424"
|
||||
"20746573745f666c6f61745f30202424242020666c6f61742031302d3130"
|
||||
"3a206661696c65642020666c6f6174203020636f6d706172653a20676f6f"
|
||||
"642020666c6f6174203020636f6d706172653a2062616480000000000000"
|
||||
"002020464c4f41545f5a45524f20636f6d706172653a20676f6f64202046"
|
||||
"4c4f41545f5a45524f20636f6d706172653a20626164009502046e616d65"
|
||||
"001110666c6f61745f74657374732e7761736d01da0105002b5f5a4e3878"
|
||||
"72706c5f73746434686f7374357472616365313768616338383262323664"
|
||||
"656162656436364501355f5a4e387872706c5f73746434686f7374313466"
|
||||
"6c6f61745f66726f6d5f696e743137683032343066386533613839643139"
|
||||
"39654502355f5a4e387872706c5f73746434686f73743134666c6f61745f"
|
||||
"737562747261637431376864363430633135323334353432393563450334"
|
||||
"5f5a4e387872706c5f73746434686f73743133666c6f61745f636f6d7061"
|
||||
"72653137683663386465656231323864393638386645040666696e697368"
|
||||
"071201000f5f5f737461636b5f706f696e746572090a0100072e726f6461"
|
||||
"7461004d0970726f64756365727302086c616e6775616765010452757374"
|
||||
"000c70726f6365737365642d6279010572757374631d312e38392e302028"
|
||||
"32393438333838336520323032352d30382d3034290094010f7461726765"
|
||||
"745f6665617475726573082b0b62756c6b2d6d656d6f72792b0f62756c6b"
|
||||
"2d6d656d6f72792d6f70742b1663616c6c2d696e6469726563742d6f7665"
|
||||
"726c6f6e672b0a6d756c746976616c75652b0f6d757461626c652d676c6f"
|
||||
"62616c732b136e6f6e7472617070696e672d6670746f696e742b0f726566"
|
||||
"6572656e63652d74797065732b087369676e2d657874";
|
||||
|
||||
extern std::string const disabledFloatHex =
|
||||
"0061736d010000000108026000006000017f03030200010503010002063e"
|
||||
"0a7f004180080b7f004180080b7f004180100b7f004180100b7f00418090"
|
||||
|
||||
@@ -63,4 +63,6 @@ extern std::string const codecovWasm;
|
||||
|
||||
extern std::string const floatHex;
|
||||
|
||||
extern std::string const float0Hex;
|
||||
|
||||
extern std::string const disabledFloatHex;
|
||||
|
||||
@@ -825,84 +825,66 @@ WasmHostFunctionsImpl::floatLog(Slice const& x, int32_t mode)
|
||||
|
||||
class Number2 : public Number
|
||||
{
|
||||
public:
|
||||
enum Issue { XRP, MPT, IOU };
|
||||
|
||||
protected:
|
||||
static Bytes const FLOAT_NULL;
|
||||
|
||||
bool good_;
|
||||
Issue issue_;
|
||||
|
||||
public:
|
||||
Number2(Slice const& data) : Number(0), good_(false), issue_(IOU)
|
||||
Number2(Slice const& data) : Number(), good_(false)
|
||||
{
|
||||
if (data.size() != 8)
|
||||
return;
|
||||
|
||||
if (std::ranges::equal(FLOAT_NULL, data))
|
||||
{
|
||||
good_ = true;
|
||||
return;
|
||||
}
|
||||
|
||||
uint64_t const v = SerialIter(data).get64();
|
||||
int const neg = (v & STAmount::cPositive) ? 1 : -1;
|
||||
if (!(v & STAmount::cIssuedCurrency))
|
||||
return;
|
||||
|
||||
Number x;
|
||||
int64_t const neg = (v & STAmount::cPositive) ? 1 : -1;
|
||||
int32_t const e = static_cast<uint8_t>((v >> (64 - 10)) & 0xFFull);
|
||||
if (e < 1 || e > 177)
|
||||
return;
|
||||
|
||||
if (v & STAmount::cIssuedCurrency)
|
||||
{
|
||||
// IOU
|
||||
int32_t const e =
|
||||
static_cast<uint8_t>((v >> (64 - 10)) & ((1ull << 8) - 1));
|
||||
int64_t const m = neg * (v & ((1ull << 54) - 1));
|
||||
x = !m || (e < 1) ? Number()
|
||||
: Number(m, e + IOUAmount::minExponent - 1);
|
||||
if (m && (x.exponent() > IOUAmount::maxExponent))
|
||||
return; // invalid number
|
||||
issue_ = IOU;
|
||||
}
|
||||
else if (v & STAmount::cMPToken)
|
||||
{
|
||||
// MPT
|
||||
int64_t const m = neg * (v & ((1ull << 61) - 1));
|
||||
x = !m ? Number() : Number(m);
|
||||
issue_ = MPT;
|
||||
}
|
||||
else
|
||||
{
|
||||
// XRP
|
||||
int64_t const m = neg * (v & ((1ull << 61) - 1));
|
||||
x = !m ? Number() : Number(m);
|
||||
issue_ = XRP;
|
||||
}
|
||||
int64_t const m = neg * static_cast<int64_t>(v & ((1ull << 54) - 1));
|
||||
if (!m)
|
||||
return;
|
||||
|
||||
Number x(m, e + IOUAmount::minExponent - 1);
|
||||
*static_cast<Number*>(this) = x;
|
||||
good_ = true;
|
||||
}
|
||||
|
||||
Number2() : Number(), good_(true), issue_(IOU)
|
||||
Number2() : Number(), good_(true)
|
||||
{
|
||||
}
|
||||
|
||||
Number2(int64_t x) : Number(x), good_(true), issue_(IOU)
|
||||
Number2(int64_t x) : Number(x), good_(true)
|
||||
{
|
||||
}
|
||||
|
||||
Number2(uint64_t x) : Number(0), good_(false), issue_(IOU)
|
||||
Number2(uint64_t x) : Number(0), good_(false)
|
||||
{
|
||||
if (x <=
|
||||
std::numeric_limits<
|
||||
std::invoke_result_t<decltype(&Number::mantissa), Number>>::
|
||||
max())
|
||||
*static_cast<Number*>(this) = Number(x);
|
||||
using mtype = std::invoke_result_t<decltype(&Number::mantissa), Number>;
|
||||
if (x <= std::numeric_limits<mtype>::max())
|
||||
*this = Number(x);
|
||||
else
|
||||
{
|
||||
*static_cast<Number*>(this) = Number(x / 10, 1) + Number(x % 10);
|
||||
}
|
||||
*this = Number(x / 10, 1) + Number(x % 10);
|
||||
|
||||
good_ = true;
|
||||
}
|
||||
|
||||
Number2(int64_t mantissa, int32_t exponent)
|
||||
: Number(mantissa, exponent), good_(true), issue_(IOU)
|
||||
: Number(mantissa, exponent), good_(true)
|
||||
{
|
||||
}
|
||||
|
||||
Number2(Number const& n) : Number(n), good_(true), issue_(IOU)
|
||||
Number2(Number const& n) : Number(n), good_(true)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -911,66 +893,38 @@ public:
|
||||
return good_;
|
||||
}
|
||||
|
||||
Issue
|
||||
getIssue() const
|
||||
{
|
||||
return issue_;
|
||||
}
|
||||
|
||||
void
|
||||
setIssue(Issue i)
|
||||
{
|
||||
issue_ = i;
|
||||
}
|
||||
|
||||
Expected<Bytes, HostFunctionError>
|
||||
toBytes() const
|
||||
{
|
||||
uint64_t v = mantissa() >= 0 ? STAmount::cPositive : 0;
|
||||
v |= STAmount::cIssuedCurrency;
|
||||
|
||||
if (issue_ == IOU)
|
||||
uint64_t const absM = mantissa() >= 0 ? mantissa() : -mantissa();
|
||||
if (!absM)
|
||||
{
|
||||
v |= STAmount::cIssuedCurrency;
|
||||
|
||||
if (!mantissa())
|
||||
using etype =
|
||||
std::invoke_result_t<decltype(&Number::exponent), Number>;
|
||||
if (exponent() != std::numeric_limits<etype>::lowest())
|
||||
{
|
||||
if (exponent() != std::numeric_limits<int>::lowest())
|
||||
return Unexpected(
|
||||
HostFunctionError::
|
||||
FLOAT_COMPUTATION_ERROR); // LCOV_EXCL_LINE
|
||||
}
|
||||
else if (exponent() > IOUAmount::maxExponent)
|
||||
return Unexpected(HostFunctionError::FLOAT_COMPUTATION_ERROR);
|
||||
else if (exponent() < IOUAmount::minExponent)
|
||||
return Number2().toBytes();
|
||||
|
||||
uint64_t absM = mantissa() >= 0 ? mantissa() : -mantissa();
|
||||
if (absM > ((1ull << 54) - 1))
|
||||
return Unexpected(
|
||||
HostFunctionError::
|
||||
FLOAT_COMPUTATION_ERROR); // LCOV_EXCL_LINE
|
||||
|
||||
v |= absM;
|
||||
|
||||
int const e =
|
||||
(!mantissa() ? 0 : exponent()) - IOUAmount::minExponent + 1;
|
||||
v |= ((uint64_t)e) << 54;
|
||||
}
|
||||
return FLOAT_NULL;
|
||||
}
|
||||
else if (issue_ == MPT)
|
||||
else if (absM > ((1ull << 54) - 1))
|
||||
{
|
||||
v |= STAmount::cMPToken;
|
||||
uint64_t x = toUInt(61);
|
||||
if (x == std::numeric_limits<uint64_t>::max())
|
||||
return Unexpected(HostFunctionError::FLOAT_COMPUTATION_ERROR);
|
||||
v |= x;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint64_t x = toUInt(61);
|
||||
if (x == std::numeric_limits<uint64_t>::max())
|
||||
return Unexpected(HostFunctionError::FLOAT_COMPUTATION_ERROR);
|
||||
v |= x;
|
||||
return Unexpected(
|
||||
HostFunctionError::FLOAT_COMPUTATION_ERROR); // LCOV_EXCL_LINE
|
||||
}
|
||||
else if (exponent() > IOUAmount::maxExponent)
|
||||
return Unexpected(HostFunctionError::FLOAT_COMPUTATION_ERROR);
|
||||
else if (exponent() < IOUAmount::minExponent)
|
||||
return FLOAT_NULL;
|
||||
|
||||
int const e = exponent() - IOUAmount::minExponent + 1; //+97
|
||||
v |= absM;
|
||||
v |= ((uint64_t)e) << 54;
|
||||
|
||||
Serializer msg;
|
||||
msg.add64(v);
|
||||
@@ -987,44 +941,11 @@ public:
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
protected:
|
||||
uint64_t
|
||||
toUInt(unsigned bits) const
|
||||
{
|
||||
if (bits >= sizeof(uint64_t) * 8)
|
||||
return std::numeric_limits<uint64_t>::max(); // LCOV_EXCL_LINE
|
||||
|
||||
uint64_t maxV = (1ull << bits) - 1;
|
||||
uint64_t absM = mantissa() >= 0 ? mantissa() : -mantissa();
|
||||
|
||||
if (!absM)
|
||||
return 0;
|
||||
else if (exponent() < 0)
|
||||
{
|
||||
for (int i = 0; i > exponent(); --i)
|
||||
{
|
||||
// underflow
|
||||
if (absM < 10)
|
||||
return std::numeric_limits<uint64_t>::max();
|
||||
absM /= 10;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < exponent(); ++i)
|
||||
{
|
||||
// overflow
|
||||
if (absM > maxV / 10)
|
||||
return std::numeric_limits<uint64_t>::max();
|
||||
absM *= 10;
|
||||
}
|
||||
}
|
||||
|
||||
return absM > maxV ? std::numeric_limits<uint64_t>::max() : absM;
|
||||
}
|
||||
};
|
||||
|
||||
Bytes const Number2::FLOAT_NULL =
|
||||
{0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
struct SetRound
|
||||
{
|
||||
Number::rounding_mode oldMode_;
|
||||
@@ -1162,7 +1083,7 @@ floatAddImpl(Slice const& x, Slice const& y, int32_t mode)
|
||||
if (!yy)
|
||||
return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED);
|
||||
Number2 res = xx + yy;
|
||||
res.setIssue(xx.getIssue());
|
||||
|
||||
return res.toBytes();
|
||||
}
|
||||
// LCOV_EXCL_START
|
||||
@@ -1188,7 +1109,7 @@ floatSubtractImpl(Slice const& x, Slice const& y, int32_t mode)
|
||||
if (!yy)
|
||||
return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED);
|
||||
Number2 res = xx - yy;
|
||||
res.setIssue(xx.getIssue());
|
||||
|
||||
return res.toBytes();
|
||||
}
|
||||
// LCOV_EXCL_START
|
||||
@@ -1214,7 +1135,7 @@ floatMultiplyImpl(Slice const& x, Slice const& y, int32_t mode)
|
||||
if (!yy)
|
||||
return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED);
|
||||
Number2 res = xx * yy;
|
||||
res.setIssue(xx.getIssue());
|
||||
|
||||
return res.toBytes();
|
||||
}
|
||||
// LCOV_EXCL_START
|
||||
@@ -1240,7 +1161,7 @@ floatDivideImpl(Slice const& x, Slice const& y, int32_t mode)
|
||||
if (!yy)
|
||||
return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED);
|
||||
Number2 res = xx / yy;
|
||||
res.setIssue(xx.getIssue());
|
||||
|
||||
return res.toBytes();
|
||||
}
|
||||
catch (...)
|
||||
@@ -1266,7 +1187,7 @@ floatRootImpl(Slice const& x, int32_t n, int32_t mode)
|
||||
return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED);
|
||||
|
||||
Number2 res(root(xx, n));
|
||||
res.setIssue(xx.getIssue());
|
||||
|
||||
return res.toBytes();
|
||||
}
|
||||
// LCOV_EXCL_START
|
||||
@@ -1296,7 +1217,7 @@ floatPowerImpl(Slice const& x, int32_t n, int32_t mode)
|
||||
return Unexpected(HostFunctionError::INVALID_PARAMS);
|
||||
|
||||
Number2 res(power(xx, n, 1));
|
||||
res.setIssue(xx.getIssue());
|
||||
|
||||
return res.toBytes();
|
||||
}
|
||||
catch (...)
|
||||
@@ -1319,7 +1240,7 @@ floatLogImpl(Slice const& x, int32_t mode)
|
||||
return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED);
|
||||
|
||||
Number2 res(lg(xx));
|
||||
res.setIssue(xx.getIssue());
|
||||
|
||||
return res.toBytes();
|
||||
}
|
||||
// LCOV_EXCL_START
|
||||
|
||||
Reference in New Issue
Block a user