Float point HF (#5611)

- added support for 8-byte  float point
This commit is contained in:
Olek
2025-07-30 10:38:03 -04:00
committed by GitHub
parent 3b849ff497
commit 3108ca0549
12 changed files with 1442 additions and 12 deletions

View File

@@ -342,6 +342,10 @@ abs(Number x) noexcept
Number
power(Number const& f, unsigned n);
// logarithm with base 10
Number
lg(Number const& value);
// Returns f^(1/d)
// Uses NewtonRaphson iterations until the result stops changing
// to find the root of the polynomial g(x) = x^d - f

View File

@@ -623,6 +623,48 @@ power(Number const& f, unsigned n)
return r;
}
// Continued fraction approximation of ln(x)
static Number
ln(Number const& x, unsigned iterations = 50)
{
if (x <= 0)
throw std::runtime_error("Not positive value");
Number const z = (x - 1) / (x + 1);
Number const zz = z * z;
Number denom = Number(1, -10);
// Construct the fraction from the bottom up
for (int i = iterations; i > 0; --i)
{
Number k(2 * i - 1);
denom = k - (i * i * zz / denom);
}
auto const r = 2 * z / denom;
return r;
}
Number
lg(Number const& x)
{
static Number const ln10 = ln(Number(10));
if (x <= Number(10))
{
auto const r = ln(x) / ln10;
return r;
}
// ln(x) = ln(normX * 10^norm) = ln(normX) + norm * ln(10)
int diffExp = 15 + x.exponent();
Number const normalX = x / Number(1, diffExp); // (1 <= normalX < 10)
auto const lnX = ln(normalX) + diffExp * ln10;
auto const r = lnX / ln10;
return r;
}
// Returns f^(1/d)
// Uses NewtonRaphson iterations until the result stops changing
// to find the non-negative root of the polynomial g(x) = x^d - f

View File

@@ -26,6 +26,7 @@
#include <xrpld/ledger/detail/ApplyViewBase.h>
namespace ripple {
namespace test {
struct TestLedgerDataProvider : public HostFunctions
@@ -378,6 +379,89 @@ public:
#endif
return msg.size() + sizeof(data);
}
Expected<int32_t, HostFunctionError>
traceFloat(std::string_view const& msg, Slice const& data) override
{
#ifdef DEBUG_OUTPUT
auto& j = std::cerr;
#else
auto j = getJournal().trace();
#endif
auto const s = floatToString(data);
j << "WAMR TRACE FLOAT: " << msg << " " << s;
#ifdef DEBUG_OUTPUT
j << std::endl;
#endif
return msg.size() + s.size();
}
Expected<Bytes, HostFunctionError>
floatFromInt(int64_t x, int32_t mode) override
{
return floatFromIntImpl(x, mode);
}
Expected<Bytes, HostFunctionError>
floatFromUint(uint64_t x, int32_t mode) override
{
return floatFromUintImpl(x, mode);
}
Expected<Bytes, HostFunctionError>
floatSet(int64_t mantissa, int32_t exponent, int32_t mode) override
{
return floatSetImpl(mantissa, exponent, mode);
}
Expected<int32_t, HostFunctionError>
floatCompare(Slice const& x, Slice const& y) override
{
return floatCompareImpl(x, y);
}
Expected<Bytes, HostFunctionError>
floatAdd(Slice const& x, Slice const& y, int32_t mode) override
{
return floatAddImpl(x, y, mode);
}
Expected<Bytes, HostFunctionError>
floatSubtract(Slice const& x, Slice const& y, int32_t mode) override
{
return floatSubtractImpl(x, y, mode);
}
Expected<Bytes, HostFunctionError>
floatMultiply(Slice const& x, Slice const& y, int32_t mode) override
{
return floatMultiplyImpl(x, y, mode);
}
Expected<Bytes, HostFunctionError>
floatDivide(Slice const& x, Slice const& y, int32_t mode) override
{
return floatDivideImpl(x, y, mode);
}
Expected<Bytes, HostFunctionError>
floatRoot(Slice const& x, int32_t n, int32_t mode) override
{
return floatRootImpl(x, n, mode);
}
Expected<Bytes, HostFunctionError>
floatPower(Slice const& x, int32_t n, int32_t mode) override
{
return floatPowerImpl(x, n, mode);
}
Expected<Bytes, HostFunctionError>
floatLog(Slice const& x, int32_t mode) override
{
return floatLogImpl(x, mode);
}
};
struct TestHostFunctionsSink : public TestHostFunctions

View File

@@ -509,6 +509,31 @@ struct Wasm_test : public beast::unit_test::suite
}
}
void
testFloat()
{
testcase("float point");
std::string const funcName("finish");
using namespace test::jtx;
Env env(*this);
{
std::string const wasmHex = floatHex;
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);
if (BEAST_EXPECT(re.has_value()))
{
BEAST_EXPECT(re->result && (re->cost == 91'412));
}
env.close();
}
}
void
perfTest()
{
@@ -656,6 +681,7 @@ struct Wasm_test : public beast::unit_test::suite
testHFCost();
testEscrowWasmDN();
testFloat();
testCodecovWasm();

View File

@@ -12222,3 +12222,151 @@ extern std::string const codecovWasm =
"31352900490f7461726765745f6665617475726573042b0f6d757461626c652d676c6f6261"
"6c732b087369676e2d6578742b0f7265666572656e63652d74797065732b0a6d756c746976"
"616c7565";
extern std::string const floatHex =
"0061736d0100000001430860057f7f7f7f7f017f60047e7f7f7f017f60047f7f7f7f017f60"
"057f7e7f7f7f017f60077f7f7f7f7f7f7f017f60067f7f7f7f7f7f017f60037f7f7e017f60"
"00017f02c9020e08686f73745f6c6962057472616365000008686f73745f6c69620e666c6f"
"61745f66726f6d5f696e74000108686f73745f6c69620f666c6f61745f66726f6d5f75696e"
"74000008686f73745f6c69621274726163655f6f70617175655f666c6f6174000208686f73"
"745f6c696209666c6f61745f736574000308686f73745f6c69620d666c6f61745f636f6d70"
"617265000208686f73745f6c696209666c6f61745f616464000408686f73745f6c69620e66"
"6c6f61745f7375627472616374000408686f73745f6c69620e666c6f61745f6d756c746970"
"6c79000408686f73745f6c69620c666c6f61745f646976696465000408686f73745f6c6962"
"09666c6f61745f706f77000508686f73745f6c69620974726163655f6e756d000608686f73"
"745f6c69620a666c6f61745f726f6f74000508686f73745f6c696209666c6f61745f6c6f67"
"00000302010705030100110619037f01418080c0000b7f0041b48ac0000b7f0041c08ac000"
"0b072e04066d656d6f727902000666696e697368000e0a5f5f646174615f656e6403010b5f"
"5f686561705f6261736503020acf1301cc1301027f23808080800041206b22002480808080"
"00418080c08000411d4100410041001080808080001a2000420037031002400240428ce000"
"200041106a410841001081808080004108470d00419d80c080004117200041106a41084101"
"1080808080001a0c010b41b480c08000411e4100410041001080808080001a0b2000428ce0"
"0037031802400240200041186a4108200041106a410841001082808080004108470d0041d2"
"80c080004117200041106a41081083808080001a0c010b41e980c08000411e410041004100"
"1080808080001a0b02400240410242fb00200041106a410841001084808080004108470d00"
"418781c080004121200041106a41081083808080001a0c010b41a881c08000412641004100"
"41001080808080001a0b41ce81c08000411541e381c0800041081083808080001a41f381c0"
"8000411641eb81c0800041081083808080001a418982c08000411b41004100410010808080"
"80001a20004200370318024002404201200041186a410841001081808080004108470d0041"
"a482c08000410f200041186a41081083808080001a0c010b41b382c0800041164100410041"
"001080808080001a0b02400240200041186a410841e381c0800041081085808080000d0041"
"c982c08000411b4100410041001080808080001a0c010b41e482c08000411b410041004100"
"1080808080001a0b02400240200041186a410841eb81c0800041081085808080004101470d"
"0041ff82c0800041234100410041001080808080001a0c010b41a283c08000412441004100"
"41001080808080001a0b0240024041eb81c080004108200041186a41081085808080004102"
"470d0041c683c0800041234100410041001080808080001a0c010b41e983c0800041244100"
"410041001080808080001a0b418d84c0800041204100410041001080808080001a200042d4"
"87b6f4c7d4b1c000370310410921010340200041106a410841e381c080004108200041106a"
"410841001086808080001a2001417f6a22010d000b20004200370318420a200041186a4108"
"41001081808080001a02400240200041186a4108200041106a41081085808080000d0041ad"
"84c0800041144100410041001080808080001a0c010b41c184c08000411341004100410010"
"80808080001a0b410b21010340200041106a410841e381c080004108200041106a41084100"
"1087808080001a2001417f6a22010d000b02400240200041106a410841eb81c08000410810"
"85808080000d0041d484c0800041194100410041001080808080001a0c010b41ed84c08000"
"41184100410041001080808080001a0b418585c0800041234100410041001080808080001a"
"20004200370300420a2000410841001081808080001a200042d487b6f4c7d4b1c000370308"
"410621010340200041086a410820004108200041086a410841001088808080001a2001417f"
"6a22010d000b2000420037031042c0843d200041106a410841001081808080001a02400240"
"200041106a4108200041086a41081085808080000d0041a885c08000411941004100410010"
"80808080001a0c010b41c185c0800041184100410041001080808080001a0b410721010340"
"200041086a410820004108200041086a410841001089808080001a2001417f6a22010d000b"
"20004200370318417f4201200041186a410841001084808080001a02400240200041086a41"
"08200041186a41081085808080000d0041d985c0800041174100410041001080808080001a"
"0c010b41f085c0800041164100410041001080808080001a0b418686c08000411741004100"
"41001080808080001a2000420037030841e381c0800041084103200041086a41084100108a"
"808080001a419d86c080004112200041086a41081083808080001a41eb81c0800041084106"
"200041086a41084100108a808080001a41af86c080004118200041086a4108108380808000"
"1a200042003703104209200041106a410841001081808080001a200041106a410841022000"
"41086a41084100108a808080001a41c786c080004114200041086a41081083808080001a20"
"0041106a41084100200041086a41084100108a808080001a41db86c080004117200041086a"
"41081083808080001a200042003703184200200041186a410841001081808080001a200041"
"186a41084102200041086a41084100108a808080001a41f286c080004114200041086a4108"
"1083808080001a418687c080004138200041186a41084100200041086a41084100108a8080"
"8000ac108b808080001a41be87c0800041184100410041001080808080001a200042003703"
"084209200041086a410841001081808080001a20004200370310200041086a410841022000"
"41106a41084100108c808080001a41d687c080004112200041106a41081083808080001a20"
"0041086a41084103200041106a41084100108c808080001a41e887c080004112200041106a"
"41081083808080001a2000420037031842c0843d200041186a410841001081808080001a20"
"0041186a41084103200041106a41084100108c808080001a41fa87c080004118200041106a"
"41081083808080001a200041186a41084106200041106a41084100108c808080001a419288"
"c08000411c200041106a41081083808080001a41ae88c08000411741004100410010808080"
"80001a2000420037031042c0843d200041106a410841001081808080001a20004200370318"
"200041106a4108200041186a41084100108d808080001a41c588c080004114200041186a41"
"081083808080001a41d988c08000411a4100410041001080808080001a2000420037031841"
"e381c08000410841eb81c080004108200041186a410841001088808080001a0240024041eb"
"81c080004108200041186a41081085808080000d0041f388c0800041164100410041001080"
"808080001a0c010b418989c0800041154100410041001080808080001a0b41eb81c0800041"
"0841eb81c080004108200041186a410841001088808080001a0240024041e381c080004108"
"200041186a41081085808080000d00419e89c0800041174100410041001080808080001a0c"
"010b41b589c0800041164100410041001080808080001a0b41cb89c08000411a4100410041"
"001080808080001a2000420037031020004200370318420a200041186a4108410010818080"
"80001a41e381c080004108200041186a4108200041106a410841001089808080001a41e589"
"c080004119200041106a41081083808080001a41e381c080004108200041106a4108200041"
"106a410841001089808080001a41fe89c08000410f200041106a41081083808080001a0240"
"0240200041186a4108200041106a41081085808080000d00418d8ac0800041144100410041"
"001080808080001a0c010b41a18ac0800041134100410041001080808080001a0b20004120"
"6a24808080800041010b0bbe0a0100418080c0000bb40a0a24242420746573745f666c6f61"
"745f66726f6d5f7761736d202424242020666c6f61742066726f6d20693634203132333030"
"3a2020666c6f61742066726f6d206936342031323330303a206661696c65642020666c6f61"
"742066726f6d207536342031323330303a2020666c6f61742066726f6d2075363420313233"
"30303a206661696c65642020666c6f61742066726f6d2065787020322c206d616e74697373"
"61203132333a2020666c6f61742066726f6d2065787020322c206d616e746973736120333a"
"206661696c65642020666c6f61742066726f6d20636f6e737420313ad4838d7ea4c6800094"
"838d7ea4c680002020666c6f61742066726f6d20636f6e7374202d313a0a24242420746573"
"745f666c6f61745f636f6d70617265202424242020666c6f61742066726f6d20313a202066"
"6c6f61742066726f6d20313a206661696c65642020666c6f61742066726f6d2031203d3d20"
"464c4f41545f4f4e452020666c6f61742066726f6d203120213d20464c4f41545f4f4e4520"
"20666c6f61742066726f6d2031203e20464c4f41545f4e454741544956455f4f4e45202066"
"6c6f61742066726f6d203120213e20464c4f41545f4e454741544956455f4f4e452020464c"
"4f41545f4e454741544956455f4f4e45203c20666c6f61742066726f6d20312020464c4f41"
"545f4e454741544956455f4f4e4520213c20666c6f61742066726f6d20310a242424207465"
"73745f666c6f61745f6164645f737562747261637420242424202072657065617465642061"
"64643a20676f6f6420207265706561746564206164643a2062616420207265706561746564"
"2073756274726163743a20676f6f64202072657065617465642073756274726163743a2062"
"61640a24242420746573745f666c6f61745f6d756c7469706c795f64697669646520242424"
"20207265706561746564206d756c7469706c793a20676f6f6420207265706561746564206d"
"756c7469706c793a2062616420207265706561746564206469766964653a20676f6f642020"
"7265706561746564206469766964653a206261640a24242420746573745f666c6f61745f70"
"6f77202424242020666c6f61742063756265206f6620313a2020666c6f6174203674682070"
"6f776572206f66202d313a2020666c6f617420737175617265206f6620393a2020666c6f61"
"742030746820706f776572206f6620393a2020666c6f617420737175617265206f6620303a"
"2020666c6f61742030746820706f776572206f6620302028657870656374696e6720494e56"
"414c49445f504152414d53206572726f72293a0a24242420746573745f666c6f61745f726f"
"6f74202424242020666c6f61742073717274206f6620393a2020666c6f6174206362727420"
"6f6620393a2020666c6f61742063627274206f6620313030303030303a2020666c6f617420"
"36746820726f6f74206f6620313030303030303a0a24242420746573745f666c6f61745f6c"
"6f672024242420206c6f675f3130206f6620313030303030303a0a24242420746573745f66"
"6c6f61745f6e65676174652024242420206e656761746520636f6e737420313a20676f6f64"
"20206e656761746520636f6e737420313a2062616420206e656761746520636f6e7374202d"
"313a20676f6f6420206e656761746520636f6e7374202d313a206261640a24242420746573"
"745f666c6f61745f696e76657274202424242020696e76657274206120666c6f6174206672"
"6f6d2031303a2020696e7665727420616761696e3a2020696e766572742074776963653a20"
"676f6f642020696e766572742074776963653a20626164009c06046e616d65001110666c6f"
"61745f74657374732e7761736d01e1050f002b5f5a4e387872706c5f73746434686f737435"
"7472616365313768303332393563316538663365373233614501355f5a4e387872706c5f73"
"746434686f73743134666c6f61745f66726f6d5f696e743137683032306436373439326164"
"39346333304502365f5a4e387872706c5f73746434686f73743135666c6f61745f66726f6d"
"5f75696e74313768346166373638366538353062383432364503395f5a4e387872706c5f73"
"746434686f7374313874726163655f6f70617175655f666c6f617431376831396639386666"
"35663362313932336245042f5f5a4e387872706c5f73746434686f737439666c6f61745f73"
"6574313768323964346230383964626561326664624505345f5a4e387872706c5f73746434"
"686f73743133666c6f61745f636f6d70617265313768346362313239626634623330373233"
"6445062f5f5a4e387872706c5f73746434686f737439666c6f61745f616464313768383661"
"336165636435336234643937374507355f5a4e387872706c5f73746434686f73743134666c"
"6f61745f7375627472616374313768653033313036323931393464333931364508355f5a4e"
"387872706c5f73746434686f73743134666c6f61745f6d756c7469706c7931376830323839"
"3337633039656534323630644509335f5a4e387872706c5f73746434686f73743132666c6f"
"61745f64697669646531376834363036323038303562623237353632450a2f5f5a4e387872"
"706c5f73746434686f737439666c6f61745f706f7731376833326463303662646430303338"
"626331450b2f5f5a4e387872706c5f73746434686f73743974726163655f6e756d31376830"
"336535336633646539393463633033450c315f5a4e387872706c5f73746434686f73743130"
"666c6f61745f726f6f7431376863656632313139376565656136653630450d2f5f5a4e3878"
"72706c5f73746434686f737439666c6f61745f6c6f67313768323530663038303633353663"
"35653639450e0666696e697368071201000f5f5f737461636b5f706f696e746572090a0100"
"072e726f64617461004d0970726f64756365727302086c616e677561676501045275737400"
"0c70726f6365737365642d6279010572757374631d312e38382e3020283662303062633338"
"3820323032352d30362d3233290094010f7461726765745f6665617475726573082b0b6275"
"6c6b2d6d656d6f72792b0f62756c6b2d6d656d6f72792d6f70742b1663616c6c2d696e6469"
"726563742d6f7665726c6f6e672b0a6d756c746976616c75652b0f6d757461626c652d676c"
"6f62616c732b136e6f6e7472617070696e672d6670746f696e742b0f7265666572656e6365"
"2d74797065732b087369676e2d657874";

View File

@@ -60,3 +60,5 @@ extern std::string const opcCallPerfTest;
extern std::string const keyletHostFunctions;
extern std::string const codecovWasm;
extern std::string const floatHex;

View File

@@ -22,6 +22,7 @@
#include <xrpld/app/misc/WasmParamsHelper.h>
#include <xrpl/basics/Expected.h>
#include <xrpl/basics/Slice.h>
#include <xrpl/beast/utility/Journal.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Keylet.h>
@@ -49,8 +50,46 @@ enum class HostFunctionError : int32_t {
INVALID_ACCOUNT = -16,
INVALID_FIELD = -17,
INDEX_OUT_OF_BOUNDS = -18,
FLOAT_INPUT_MALFORMED = -19,
FLOAT_COMPUTATION_ERROR = -20,
};
std::string
floatToString(Slice const& data);
Expected<Bytes, HostFunctionError>
floatFromIntImpl(int64_t x, int32_t mode);
Expected<Bytes, HostFunctionError>
floatFromUintImpl(uint64_t x, int32_t mode);
Expected<Bytes, HostFunctionError>
floatSetImpl(int64_t mantissa, int32_t exponent, int32_t mode);
Expected<int32_t, HostFunctionError>
floatCompareImpl(Slice const& x, Slice const& y);
Expected<Bytes, HostFunctionError>
floatAddImpl(Slice const& x, Slice const& y, int32_t mode);
Expected<Bytes, HostFunctionError>
floatSubtractImpl(Slice const& x, Slice const& y, int32_t mode);
Expected<Bytes, HostFunctionError>
floatMultiplyImpl(Slice const& x, Slice const& y, int32_t mode);
Expected<Bytes, HostFunctionError>
floatDivideImpl(Slice const& x, Slice const& y, int32_t mode);
Expected<Bytes, HostFunctionError>
floatRootImpl(Slice const& x, int32_t n, int32_t mode);
Expected<Bytes, HostFunctionError>
floatPowerImpl(Slice const& x, int32_t n, int32_t mode);
Expected<Bytes, HostFunctionError>
floatLogImpl(Slice const& x, int32_t mode);
struct HostFunctions
{
virtual void
@@ -289,6 +328,78 @@ struct HostFunctions
return Unexpected(HostFunctionError::INTERNAL);
}
virtual Expected<int32_t, HostFunctionError>
traceFloat(std::string_view const& msg, Slice const& data)
{
return Unexpected(HostFunctionError::INTERNAL);
}
virtual Expected<Bytes, HostFunctionError>
floatFromInt(int64_t x, int32_t mode)
{
return Unexpected(HostFunctionError::INTERNAL);
}
virtual Expected<Bytes, HostFunctionError>
floatFromUint(uint64_t x, int32_t mode)
{
return Unexpected(HostFunctionError::INTERNAL);
}
virtual Expected<Bytes, HostFunctionError>
floatSet(int64_t mantissa, int32_t exponent, int32_t mode)
{
return Unexpected(HostFunctionError::INTERNAL);
}
virtual Expected<int32_t, HostFunctionError>
floatCompare(Slice const& x, Slice const& y)
{
return Unexpected(HostFunctionError::INTERNAL);
}
virtual Expected<Bytes, HostFunctionError>
floatAdd(Slice const& x, Slice const& y, int32_t mode)
{
return Unexpected(HostFunctionError::INTERNAL);
}
virtual Expected<Bytes, HostFunctionError>
floatSubtract(Slice const& x, Slice const& y, int32_t mode)
{
return Unexpected(HostFunctionError::INTERNAL);
}
virtual Expected<Bytes, HostFunctionError>
floatMultiply(Slice const& x, Slice const& y, int32_t mode)
{
return Unexpected(HostFunctionError::INTERNAL);
}
virtual Expected<Bytes, HostFunctionError>
floatDivide(Slice const& x, Slice const& y, int32_t mode)
{
return Unexpected(HostFunctionError::INTERNAL);
}
virtual Expected<Bytes, HostFunctionError>
floatRoot(Slice const& x, int32_t n, int32_t mode)
{
return Unexpected(HostFunctionError::INTERNAL);
}
virtual Expected<Bytes, HostFunctionError>
floatPower(Slice const& x, int32_t n, int32_t mode)
{
return Unexpected(HostFunctionError::INTERNAL);
}
virtual Expected<Bytes, HostFunctionError>
floatLog(Slice const& x, int32_t mode)
{
return Unexpected(HostFunctionError::INTERNAL);
}
virtual ~HostFunctions() = default;
};

View File

@@ -654,4 +654,544 @@ WasmHostFunctionsImpl::traceNum(std::string_view const& msg, int64_t data)
return msg.size() + sizeof(data);
}
Expected<int32_t, HostFunctionError>
WasmHostFunctionsImpl::traceFloat(
std::string_view const& msg,
Slice const& data)
{
#ifdef DEBUG_OUTPUT
auto j = getJournal().error();
#else
auto j = getJournal().trace();
#endif
auto const s = floatToString(data);
j << "WAMR TRACE FLOAT(" << leKey.key << "): " << msg << " " << s;
return msg.size() + s.size();
}
Expected<Bytes, HostFunctionError>
WasmHostFunctionsImpl::floatFromInt(int64_t x, int32_t mode)
{
return floatFromIntImpl(x, mode);
}
Expected<Bytes, HostFunctionError>
WasmHostFunctionsImpl::floatFromUint(uint64_t x, int32_t mode)
{
return floatFromUintImpl(x, mode);
}
Expected<Bytes, HostFunctionError>
WasmHostFunctionsImpl::floatSet(
int64_t mantissa,
int32_t exponent,
int32_t mode)
{
return floatSetImpl(mantissa, exponent, mode);
}
Expected<int32_t, HostFunctionError>
WasmHostFunctionsImpl::floatCompare(Slice const& x, Slice const& y)
{
return floatCompareImpl(x, y);
}
Expected<Bytes, HostFunctionError>
WasmHostFunctionsImpl::floatAdd(Slice const& x, Slice const& y, int32_t mode)
{
return floatAddImpl(x, y, mode);
}
Expected<Bytes, HostFunctionError>
WasmHostFunctionsImpl::floatSubtract(
Slice const& x,
Slice const& y,
int32_t mode)
{
return floatSubtractImpl(x, y, mode);
}
Expected<Bytes, HostFunctionError>
WasmHostFunctionsImpl::floatMultiply(
Slice const& x,
Slice const& y,
int32_t mode)
{
return floatMultiplyImpl(x, y, mode);
}
Expected<Bytes, HostFunctionError>
WasmHostFunctionsImpl::floatDivide(Slice const& x, Slice const& y, int32_t mode)
{
return floatDivideImpl(x, y, mode);
}
Expected<Bytes, HostFunctionError>
WasmHostFunctionsImpl::floatRoot(Slice const& x, int32_t n, int32_t mode)
{
return floatRootImpl(x, n, mode);
}
Expected<Bytes, HostFunctionError>
WasmHostFunctionsImpl::floatPower(Slice const& x, int32_t n, int32_t mode)
{
return floatPowerImpl(x, n, mode);
}
Expected<Bytes, HostFunctionError>
WasmHostFunctionsImpl::floatLog(Slice const& x, int32_t mode)
{
return floatLogImpl(x, mode);
}
class Number2 : public Number
{
bool good_;
enum Issue { XRP, MPT, IOU };
Issue issue_;
public:
Number2(Slice const& data) : Number(0), good_(false), issue_(IOU)
{
if (data.size() != 8)
return;
uint64_t const v = SerialIter(data).get64();
int const neg = (v & STAmount::cPositive) ? 1 : -1;
Number x;
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 ? Number() : Number(m, e - 97);
if (m && (x.exponent() > 80 || x.exponent() < -96))
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;
}
*static_cast<Number*>(this) = x;
good_ = true;
}
Number2(int64_t x) : Number(x), good_(true), issue_(IOU)
{
}
Number2(uint64_t x) : Number(0), good_(false), issue_(IOU)
{
if (x <=
std::numeric_limits<
std::invoke_result_t<decltype(&Number::mantissa), Number>>::
max())
*static_cast<Number*>(this) = Number(x);
else
{
*static_cast<Number*>(this) = Number(x / 10, 1) + Number(x % 10);
}
good_ = true;
}
Number2(int64_t mantissa, int32_t exponent)
: Number(mantissa, exponent), good_(true), issue_(IOU)
{
}
Number2(Number const& n) : Number(n), good_(true), issue_(IOU)
{
}
operator bool() const
{
return good_;
}
Expected<Bytes, HostFunctionError>
toBytes() const
{
uint64_t v = mantissa() >= 0 ? STAmount::cPositive : 0;
if (issue_ == IOU)
{
v |= STAmount::cIssuedCurrency;
if (!mantissa())
{
if (exponent() != std::numeric_limits<int>::lowest())
return Unexpected(
HostFunctionError::FLOAT_COMPUTATION_ERROR);
}
else if (exponent() > 80 || exponent() < -96)
return Unexpected(HostFunctionError::FLOAT_COMPUTATION_ERROR);
uint64_t absM = mantissa() >= 0 ? mantissa() : -mantissa();
if (absM > ((1ull << 54) - 1))
return Unexpected(HostFunctionError::FLOAT_COMPUTATION_ERROR);
v |= absM;
int const e = (!mantissa() ? 0 : exponent()) + 97;
v |= ((uint64_t)e) << 54;
}
else if (issue_ == MPT)
{
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;
}
Serializer msg;
msg.add64(v);
auto const data = msg.getData();
return data;
}
protected:
uint64_t
toUInt(unsigned bits) const
{
if (bits >= sizeof(uint64_t) * 8)
return std::numeric_limits<uint64_t>::max();
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)
{
if (absM < 10)
return std::numeric_limits<uint64_t>::max(); // underflow
absM /= 10;
}
}
else
{
for (int i = 0; i < exponent(); ++i)
{
if (absM > maxV / 10)
return std::numeric_limits<uint64_t>::max(); // overflow
absM *= 10;
}
}
return absM > maxV ? std::numeric_limits<uint64_t>::max() : absM;
}
};
struct SetRound
{
Number::rounding_mode oldMode_;
bool good_;
SetRound(int32_t mode) : oldMode_(Number::getround()), good_(false)
{
if (mode < Number::rounding_mode::to_nearest ||
mode > Number::rounding_mode::upward)
return;
Number::setround(static_cast<Number::rounding_mode>(mode));
good_ = true;
}
~SetRound()
{
Number::setround(oldMode_);
}
operator bool() const
{
return good_;
}
};
std::string
floatToString(Slice const& data)
{
Number2 const num(data);
if (!num)
{
std::string hex;
hex.reserve(data.size() * 2);
boost::algorithm::hex(
data.begin(), data.end(), std::back_inserter(hex));
return "Invalid data: " + hex;
}
auto const s = to_string(num);
return s;
}
Expected<Bytes, HostFunctionError>
floatFromIntImpl(int64_t x, int32_t mode)
{
try
{
SetRound rm(mode);
if (!rm)
return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED);
Number2 num(x);
if (!num)
return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED);
return num.toBytes();
}
catch (...)
{
}
return Unexpected(HostFunctionError::FLOAT_COMPUTATION_ERROR);
}
Expected<Bytes, HostFunctionError>
floatFromUintImpl(uint64_t x, int32_t mode)
{
try
{
SetRound rm(mode);
if (!rm)
return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED);
Number2 num(x);
if (!num)
return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED);
return num.toBytes();
}
catch (...)
{
}
return Unexpected(HostFunctionError::FLOAT_COMPUTATION_ERROR);
}
Expected<Bytes, HostFunctionError>
floatSetImpl(int64_t mantissa, int32_t exponent, int32_t mode)
{
try
{
SetRound rm(mode);
if (!rm)
return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED);
Number2 num(mantissa, exponent);
if (!num)
return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED);
return num.toBytes();
}
catch (...)
{
}
return Unexpected(HostFunctionError::FLOAT_COMPUTATION_ERROR);
}
Expected<int32_t, HostFunctionError>
floatCompareImpl(Slice const& x, Slice const& y)
{
try
{
Number2 xx(x);
if (!xx)
return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED);
Number2 yy(y);
if (!yy)
return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED);
return xx < yy ? 2 : (xx == yy ? 0 : 1);
}
catch (...)
{
}
return Unexpected(HostFunctionError::FLOAT_COMPUTATION_ERROR);
}
Expected<Bytes, HostFunctionError>
floatAddImpl(Slice const& x, Slice const& y, int32_t mode)
{
try
{
SetRound rm(mode);
if (!rm)
return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED);
Number2 xx(x);
if (!xx)
return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED);
Number2 yy(y);
if (!yy)
return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED);
Number2 res = xx + yy;
return res.toBytes();
}
catch (...)
{
}
return Unexpected(HostFunctionError::FLOAT_COMPUTATION_ERROR);
}
Expected<Bytes, HostFunctionError>
floatSubtractImpl(Slice const& x, Slice const& y, int32_t mode)
{
try
{
SetRound rm(mode);
if (!rm)
return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED);
Number2 xx(x);
if (!xx)
return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED);
Number2 yy(y);
if (!yy)
return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED);
Number2 res = xx - yy;
return res.toBytes();
}
catch (...)
{
}
return Unexpected(HostFunctionError::FLOAT_COMPUTATION_ERROR);
}
Expected<Bytes, HostFunctionError>
floatMultiplyImpl(Slice const& x, Slice const& y, int32_t mode)
{
try
{
SetRound rm(mode);
if (!rm)
return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED);
Number2 xx(x);
if (!xx)
return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED);
Number2 yy(y);
if (!yy)
return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED);
Number2 res = xx * yy;
return res.toBytes();
}
catch (...)
{
}
return Unexpected(HostFunctionError::FLOAT_COMPUTATION_ERROR);
}
Expected<Bytes, HostFunctionError>
floatDivideImpl(Slice const& x, Slice const& y, int32_t mode)
{
try
{
SetRound rm(mode);
if (!rm)
return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED);
Number2 xx(x);
if (!xx)
return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED);
Number2 yy(y);
if (!yy)
return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED);
Number2 res = xx / yy;
return res.toBytes();
}
catch (...)
{
}
return Unexpected(HostFunctionError::FLOAT_COMPUTATION_ERROR);
}
Expected<Bytes, HostFunctionError>
floatRootImpl(Slice const& x, int32_t n, int32_t mode)
{
try
{
SetRound rm(mode);
if (!rm)
return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED);
Number2 xx(x);
if (!xx)
return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED);
Number2 const res(root(xx, n));
return res.toBytes();
}
catch (...)
{
}
return Unexpected(HostFunctionError::FLOAT_COMPUTATION_ERROR);
}
Expected<Bytes, HostFunctionError>
floatPowerImpl(Slice const& x, int32_t n, int32_t mode)
{
try
{
SetRound rm(mode);
if (!rm)
return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED);
Number2 xx(x);
if (!xx)
return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED);
if (xx == Number() && !n)
return Unexpected(HostFunctionError::INVALID_PARAMS);
Number2 const res(power(xx, n, 1));
return res.toBytes();
}
catch (...)
{
}
return Unexpected(HostFunctionError::FLOAT_COMPUTATION_ERROR);
}
Expected<Bytes, HostFunctionError>
floatLogImpl(Slice const& x, int32_t mode)
{
try
{
SetRound rm(mode);
if (!rm)
return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED);
Number2 xx(x);
if (!xx)
return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED);
Number2 const res(lg(xx));
return res.toBytes();
}
catch (...)
{
}
return Unexpected(HostFunctionError::FLOAT_COMPUTATION_ERROR);
}
} // namespace ripple

View File

@@ -190,6 +190,42 @@ public:
Expected<int32_t, HostFunctionError>
traceNum(std::string_view const& msg, int64_t data) override;
Expected<int32_t, HostFunctionError>
traceFloat(std::string_view const& msg, Slice const& data) override;
Expected<Bytes, HostFunctionError>
floatFromInt(int64_t x, int32_t mode) override;
Expected<Bytes, HostFunctionError>
floatFromUint(uint64_t x, int32_t mode) override;
Expected<Bytes, HostFunctionError>
floatSet(int64_t mantissa, int32_t exponent, int32_t mode) override;
Expected<int32_t, HostFunctionError>
floatCompare(Slice const& x, Slice const& y) override;
Expected<Bytes, HostFunctionError>
floatAdd(Slice const& x, Slice const& y, int32_t mode) override;
Expected<Bytes, HostFunctionError>
floatSubtract(Slice const& x, Slice const& y, int32_t mode) override;
Expected<Bytes, HostFunctionError>
floatMultiply(Slice const& x, Slice const& y, int32_t mode) override;
Expected<Bytes, HostFunctionError>
floatDivide(Slice const& x, Slice const& y, int32_t mode) override;
Expected<Bytes, HostFunctionError>
floatRoot(Slice const& x, int32_t n, int32_t mode) override;
Expected<Bytes, HostFunctionError>
floatPower(Slice const& x, int32_t n, int32_t mode) override;
Expected<Bytes, HostFunctionError>
floatLog(Slice const& x, int32_t mode) override;
};
} // namespace ripple

View File

@@ -22,6 +22,7 @@
#include <xrpld/app/misc/WasmHostFuncWrapper.h>
#include <xrpld/app/tx/detail/NFTokenUtils.h>
#include <xrpl/protocol/STNumber.h>
#include <xrpl/protocol/digest.h>
namespace ripple {
@@ -64,7 +65,7 @@ setData(
template <class IW>
Expected<int32_t, HostFunctionError>
getDataInt32(IW const* _rt, wasm_val_vec_t const* params, int32_t& i)
getDataInt32(IW const* _runtime, wasm_val_vec_t const* params, int32_t& i)
{
auto const result = params->data[i].of.i32;
i++;
@@ -73,16 +74,29 @@ getDataInt32(IW const* _rt, wasm_val_vec_t const* params, int32_t& i)
template <class IW>
Expected<int64_t, HostFunctionError>
getDataInt64(IW const* _rt, wasm_val_vec_t const* params, int32_t& i)
getDataInt64(IW const* _runtime, wasm_val_vec_t const* params, int32_t& i)
{
auto const result = params->data[i].of.i64;
i++;
return result;
}
template <class IW>
Expected<uint64_t, HostFunctionError>
getDataUint64(IW const* runtime, wasm_val_vec_t const* params, int32_t& i)
{
auto const r = getDataSlice(runtime, params, i);
if (!r)
return Unexpected(r.error());
if (r->size() != sizeof(uint64_t))
return Unexpected(HostFunctionError::INVALID_PARAMS);
return *reinterpret_cast<uint64_t const*>(r->data());
}
template <class IW>
Expected<SFieldCRef, HostFunctionError>
getDataSField(IW const* _rt, wasm_val_vec_t const* params, int32_t& i)
getDataSField(IW const* _runtime, wasm_val_vec_t const* params, int32_t& i)
{
auto const& m = SField::getKnownCodeToField();
auto const it = m.find(params->data[i].of.i32);
@@ -217,7 +231,9 @@ returnResult(
{
return hfResult(results, res.error());
}
if constexpr (std::is_same_v<std::decay_t<decltype(*res)>, Bytes>)
using t = std::decay_t<decltype(*res)>;
if constexpr (std::is_same_v<t, Bytes>)
{
return hfResult(
results,
@@ -228,7 +244,7 @@ returnResult(
res->data(),
res->size()));
}
else if constexpr (std::is_same_v<std::decay_t<decltype(*res)>, Hash>)
else if constexpr (std::is_same_v<t, Hash>)
{
return hfResult(
results,
@@ -239,13 +255,11 @@ returnResult(
res->data(),
res->size()));
}
else if constexpr (std::is_same_v<std::decay_t<decltype(*res)>, int32_t>)
else if constexpr (std::is_same_v<t, int32_t>)
{
return hfResult(results, res.value());
}
else if constexpr (std::is_same_v<
std::decay_t<decltype(*res)>,
std::uint32_t>)
else if constexpr (std::is_same_v<t, std::uint32_t>)
{
auto const resultValue = res.value();
return hfResult(
@@ -1044,7 +1058,6 @@ ticketKeylet_wrap(
results,
hf->ticketKeylet(acc.value(), seq.value()),
index);
;
}
wasm_trap_t*
@@ -1131,6 +1144,310 @@ traceNum_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results)
runtime, params, results, hf->traceNum(*msg, *number), index);
}
wasm_trap_t*
traceFloat_wrap(
void* env,
wasm_val_vec_t const* params,
wasm_val_vec_t* results)
{
auto* hf = reinterpret_cast<HostFunctions*>(env);
auto const* runtime = reinterpret_cast<InstanceWrapper const*>(hf->getRT());
if (params->data[1].of.i32 > maxWasmDataLength)
return hfResult(results, HostFunctionError::DATA_FIELD_TOO_LARGE);
int i = 0;
auto const msg = getDataString(runtime, params, i);
if (!msg)
return hfResult(results, msg.error());
auto const number = getDataSlice(runtime, params, i);
if (!number)
return hfResult(results, number.error());
return returnResult(
runtime, params, results, hf->traceFloat(*msg, *number), i);
}
wasm_trap_t*
floatFromInt_wrap(
void* env,
wasm_val_vec_t const* params,
wasm_val_vec_t* results)
{
auto* hf = reinterpret_cast<HostFunctions*>(env);
auto const* runtime = reinterpret_cast<InstanceWrapper const*>(hf->getRT());
int i = 0;
auto const x = getDataInt64(runtime, params, i);
if (!x)
return hfResult(results, x.error());
i = 3;
auto const rounding = getDataInt32(runtime, params, i);
if (!rounding)
return hfResult(results, rounding.error());
i = 1;
return returnResult(
runtime, params, results, hf->floatFromInt(*x, *rounding), i);
}
wasm_trap_t*
floatFromUint_wrap(
void* env,
wasm_val_vec_t const* params,
wasm_val_vec_t* results)
{
auto* hf = reinterpret_cast<HostFunctions*>(env);
auto const* runtime = reinterpret_cast<InstanceWrapper const*>(hf->getRT());
int i = 0;
auto const x = getDataUint64(runtime, params, i);
if (!x)
return hfResult(results, x.error());
i = 4;
auto const rounding = getDataInt32(runtime, params, i);
if (!rounding)
return hfResult(results, rounding.error());
i = 2;
return returnResult(
runtime, params, results, hf->floatFromUint(*x, *rounding), i);
}
wasm_trap_t*
floatSet_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results)
{
auto* hf = reinterpret_cast<HostFunctions*>(env);
auto const* runtime = reinterpret_cast<InstanceWrapper const*>(hf->getRT());
int i = 0;
auto const exp = getDataInt32(runtime, params, i);
if (!exp)
return hfResult(results, exp.error());
auto const mant = getDataInt64(runtime, params, i);
if (!mant)
return hfResult(results, mant.error());
i = 4;
auto const rounding = getDataInt32(runtime, params, i);
if (!rounding)
return hfResult(results, rounding.error());
i = 2;
return returnResult(
runtime, params, results, hf->floatSet(*mant, *exp, *rounding), i);
}
wasm_trap_t*
floatCompare_wrap(
void* env,
wasm_val_vec_t const* params,
wasm_val_vec_t* results)
{
auto* hf = reinterpret_cast<HostFunctions*>(env);
auto const* runtime = reinterpret_cast<InstanceWrapper const*>(hf->getRT());
int i = 0;
auto const x = getDataSlice(runtime, params, i);
if (!x)
return hfResult(results, x.error());
auto const y = getDataSlice(runtime, params, i);
if (!y)
return hfResult(results, y.error());
return returnResult(runtime, params, results, hf->floatCompare(*x, *y), i);
}
wasm_trap_t*
floatAdd_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results)
{
auto* hf = reinterpret_cast<HostFunctions*>(env);
auto const* runtime = reinterpret_cast<InstanceWrapper const*>(hf->getRT());
int i = 0;
auto const x = getDataSlice(runtime, params, i);
if (!x)
return hfResult(results, x.error());
auto const y = getDataSlice(runtime, params, i);
if (!y)
return hfResult(results, y.error());
i = 6;
auto const rounding = getDataInt32(runtime, params, i);
if (!rounding)
return hfResult(results, rounding.error());
i = 4;
return returnResult(
runtime, params, results, hf->floatAdd(*x, *y, *rounding), i);
}
wasm_trap_t*
floatSubtract_wrap(
void* env,
wasm_val_vec_t const* params,
wasm_val_vec_t* results)
{
auto* hf = reinterpret_cast<HostFunctions*>(env);
auto const* runtime = reinterpret_cast<InstanceWrapper const*>(hf->getRT());
int i = 0;
auto const x = getDataSlice(runtime, params, i);
if (!x)
return hfResult(results, x.error());
auto const y = getDataSlice(runtime, params, i);
if (!y)
return hfResult(results, y.error());
i = 6;
auto const rounding = getDataInt32(runtime, params, i);
if (!rounding)
return hfResult(results, rounding.error());
i = 4;
return returnResult(
runtime, params, results, hf->floatSubtract(*x, *y, *rounding), i);
}
wasm_trap_t*
floatMultiply_wrap(
void* env,
wasm_val_vec_t const* params,
wasm_val_vec_t* results)
{
auto* hf = reinterpret_cast<HostFunctions*>(env);
auto const* runtime = reinterpret_cast<InstanceWrapper const*>(hf->getRT());
int i = 0;
auto const x = getDataSlice(runtime, params, i);
if (!x)
return hfResult(results, x.error());
auto const y = getDataSlice(runtime, params, i);
if (!y)
return hfResult(results, y.error());
i = 6;
auto const rounding = getDataInt32(runtime, params, i);
if (!rounding)
return hfResult(results, rounding.error());
i = 4;
return returnResult(
runtime, params, results, hf->floatMultiply(*x, *y, *rounding), i);
}
wasm_trap_t*
floatDivide_wrap(
void* env,
wasm_val_vec_t const* params,
wasm_val_vec_t* results)
{
auto* hf = reinterpret_cast<HostFunctions*>(env);
auto const* runtime = reinterpret_cast<InstanceWrapper const*>(hf->getRT());
int i = 0;
auto const x = getDataSlice(runtime, params, i);
if (!x)
return hfResult(results, x.error());
auto const y = getDataSlice(runtime, params, i);
if (!y)
return hfResult(results, y.error());
i = 6;
auto const rounding = getDataInt32(runtime, params, i);
if (!rounding)
return hfResult(results, rounding.error());
i = 4;
return returnResult(
runtime, params, results, hf->floatDivide(*x, *y, *rounding), i);
}
wasm_trap_t*
floatRoot_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results)
{
auto* hf = reinterpret_cast<HostFunctions*>(env);
auto const* runtime = reinterpret_cast<InstanceWrapper const*>(hf->getRT());
int i = 0;
auto const x = getDataSlice(runtime, params, i);
if (!x)
return hfResult(results, x.error());
auto const n = getDataInt32(runtime, params, i);
if (!n)
return hfResult(results, n.error());
i = 5;
auto const rounding = getDataInt32(runtime, params, i);
if (!rounding)
return hfResult(results, rounding.error());
i = 3;
return returnResult(
runtime, params, results, hf->floatRoot(*x, *n, *rounding), i);
}
wasm_trap_t*
floatPower_wrap(
void* env,
wasm_val_vec_t const* params,
wasm_val_vec_t* results)
{
auto* hf = reinterpret_cast<HostFunctions*>(env);
auto const* runtime = reinterpret_cast<InstanceWrapper const*>(hf->getRT());
int i = 0;
auto const x = getDataSlice(runtime, params, i);
if (!x)
return hfResult(results, x.error());
auto const n = getDataInt32(runtime, params, i);
if (!n)
return hfResult(results, n.error());
i = 5;
auto const rounding = getDataInt32(runtime, params, i);
if (!rounding)
return hfResult(results, rounding.error());
i = 3;
return returnResult(
runtime, params, results, hf->floatPower(*x, *n, *rounding), i);
}
wasm_trap_t*
floatLog_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results)
{
auto* hf = reinterpret_cast<HostFunctions*>(env);
auto const* runtime = reinterpret_cast<InstanceWrapper const*>(hf->getRT());
int i = 0;
auto const x = getDataSlice(runtime, params, i);
if (!x)
return hfResult(results, x.error());
i = 4;
auto const rounding = getDataInt32(runtime, params, i);
if (!rounding)
return hfResult(results, rounding.error());
i = 2;
return returnResult(
runtime, params, results, hf->floatLog(*x, *rounding), i);
}
namespace test {
class MockInstanceWrapper
{
wmem mem_;
@@ -1148,8 +1465,6 @@ public:
}
};
namespace test {
// LCOV_EXCL_START
bool
testGetDataIncrement()

View File

@@ -313,4 +313,113 @@ using traceNum_proto = int32_t(uint8_t const*, int32_t, int64_t);
wasm_trap_t*
traceNum_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
using traceFloat_proto =
int32_t(uint8_t const*, int32_t, uint8_t const*, int32_t);
wasm_trap_t*
traceFloat_wrap(
void* env,
wasm_val_vec_t const* params,
wasm_val_vec_t* results);
using floatFromInt_proto = int32_t(int64_t, uint8_t*, int32_t, int32_t);
wasm_trap_t*
floatFromInt_wrap(
void* env,
wasm_val_vec_t const* params,
wasm_val_vec_t* results);
using floatFromUint_proto =
int32_t(uint8_t const*, int32_t, uint8_t*, int32_t, int32_t);
wasm_trap_t*
floatFromUint_wrap(
void* env,
wasm_val_vec_t const* params,
wasm_val_vec_t* results);
using floatSet_proto = int32_t(int32_t, int64_t, uint8_t*, int32_t, int32_t);
wasm_trap_t*
floatSet_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
using floatCompare_proto =
int32_t(uint8_t const*, int32_t, uint8_t const*, int32_t);
wasm_trap_t*
floatCompare_wrap(
void* env,
wasm_val_vec_t const* params,
wasm_val_vec_t* results);
using floatAdd_proto = int32_t(
uint8_t const*,
int32_t,
uint8_t const*,
int32_t,
uint8_t*,
int32_t,
int32_t);
wasm_trap_t*
floatAdd_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
using floatSubtract_proto = int32_t(
uint8_t const*,
int32_t,
uint8_t const*,
int32_t,
uint8_t*,
int32_t,
int32_t);
wasm_trap_t*
floatSubtract_wrap(
void* env,
wasm_val_vec_t const* params,
wasm_val_vec_t* results);
using floatMultiply_proto = int32_t(
uint8_t const*,
int32_t,
uint8_t const*,
int32_t,
uint8_t*,
int32_t,
int32_t);
wasm_trap_t*
floatMultiply_wrap(
void* env,
wasm_val_vec_t const* params,
wasm_val_vec_t* results);
using floatDivide_proto = int32_t(
uint8_t const*,
int32_t,
uint8_t const*,
int32_t,
uint8_t*,
int32_t,
int32_t);
wasm_trap_t*
floatDivide_wrap(
void* env,
wasm_val_vec_t const* params,
wasm_val_vec_t* results);
using floatRoot_proto =
int32_t(uint8_t const*, int32_t, int32_t, uint8_t*, int32_t, int32_t);
wasm_trap_t*
floatRoot_wrap(
void* env,
wasm_val_vec_t const* params,
wasm_val_vec_t* results);
using floatPower_proto =
int32_t(uint8_t const*, int32_t, int32_t, uint8_t*, int32_t, int32_t);
wasm_trap_t*
floatPower_wrap(
void* env,
wasm_val_vec_t const* params,
wasm_val_vec_t* results);
using floatLog_proto =
int32_t(uint8_t const*, int32_t, uint8_t*, int32_t, int32_t);
wasm_trap_t*
floatLog_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
} // namespace ripple

View File

@@ -77,6 +77,19 @@ createWasmImport(HostFunctions* hfs)
WASM_IMPORT_FUNC2(i, getNFT, "get_nft", hfs, 1000);
WASM_IMPORT_FUNC (i, trace, hfs, 500);
WASM_IMPORT_FUNC2(i, traceNum, "trace_num", hfs, 500);
WASM_IMPORT_FUNC2(i, traceFloat, "trace_opaque_float", hfs, 500);
WASM_IMPORT_FUNC2(i, floatFromInt, "float_from_int", hfs, 1000);
WASM_IMPORT_FUNC2(i, floatFromUint, "float_from_uint", hfs, 1000);
WASM_IMPORT_FUNC2(i, floatSet, "float_set", hfs, 1000);
WASM_IMPORT_FUNC2(i, floatCompare, "float_compare", hfs, 1000);
WASM_IMPORT_FUNC2(i, floatAdd, "float_add", hfs, 1000);
WASM_IMPORT_FUNC2(i, floatSubtract, "float_subtract", hfs, 1000);
WASM_IMPORT_FUNC2(i, floatMultiply, "float_multiply", hfs, 1000);
WASM_IMPORT_FUNC2(i, floatDivide, "float_divide", hfs, 1000);
WASM_IMPORT_FUNC2(i, floatRoot, "float_root", hfs, 1000);
WASM_IMPORT_FUNC2(i, floatPower, "float_pow", hfs, 1000);
WASM_IMPORT_FUNC2(i, floatLog, "float_log", hfs, 1000);
// clang-format on
}