mirror of
https://github.com/Xahau/xahaud.git
synced 2025-11-19 18:15:50 +00:00
add float APIs
This commit is contained in:
@@ -21,27 +21,169 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
// Emit a transaction from the running hook. On success, returns 32-byte
|
/// control APIs
|
||||||
// transaction ID bytes (same content written by the wasm host function).
|
// _g
|
||||||
|
// accept
|
||||||
|
// rollback
|
||||||
|
|
||||||
|
/// util APIs
|
||||||
|
// util_raddr
|
||||||
|
// util_accid
|
||||||
|
// util_verify
|
||||||
|
// util_sha512h
|
||||||
|
|
||||||
|
/// sto APIs
|
||||||
|
// sto_validate
|
||||||
|
// sto_subfield
|
||||||
|
// sto_subarray
|
||||||
|
// sto_emplace
|
||||||
|
// sto_erase
|
||||||
|
// util_keylet
|
||||||
|
|
||||||
|
/// etxn APIs
|
||||||
Expected<std::shared_ptr<Transaction>, HookReturnCode>
|
Expected<std::shared_ptr<Transaction>, HookReturnCode>
|
||||||
emit(Slice txBlob);
|
emit(Slice txBlob);
|
||||||
|
|
||||||
// Dependencies (public so callers can compose):
|
|
||||||
// etxn_generation == otxn_generation() + 1
|
|
||||||
uint32_t
|
|
||||||
etxn_generation() const;
|
|
||||||
Expected<uint64_t, HookReturnCode>
|
Expected<uint64_t, HookReturnCode>
|
||||||
etxn_burden() const;
|
etxn_burden() const;
|
||||||
|
|
||||||
Expected<uint64_t, HookReturnCode>
|
Expected<uint64_t, HookReturnCode>
|
||||||
etxn_fee_base(Slice txBlob) const;
|
etxn_fee_base(Slice txBlob) const;
|
||||||
|
// etxn_details
|
||||||
|
// etxn_reserve
|
||||||
uint32_t
|
uint32_t
|
||||||
otxn_generation() const;
|
etxn_generation() const;
|
||||||
|
// etxn_nonce
|
||||||
|
|
||||||
|
/// float APIs
|
||||||
|
Expected<uint64_t, HookReturnCode>
|
||||||
|
float_set(int32_t exponent, int64_t mantissa) const;
|
||||||
|
|
||||||
|
Expected<uint64_t, HookReturnCode>
|
||||||
|
float_multiply(uint64_t float1, uint64_t float2) const;
|
||||||
|
|
||||||
|
Expected<uint64_t, HookReturnCode>
|
||||||
|
float_mulratio(
|
||||||
|
uint64_t float1,
|
||||||
|
uint32_t round_up,
|
||||||
|
uint32_t numerator,
|
||||||
|
uint32_t denominator) const;
|
||||||
|
|
||||||
|
uint64_t
|
||||||
|
float_negate(uint64_t float1) const;
|
||||||
|
|
||||||
|
Expected<uint64_t, HookReturnCode>
|
||||||
|
float_compare(uint64_t float1, uint64_t float2, uint32_t mode) const;
|
||||||
|
|
||||||
|
Expected<uint64_t, HookReturnCode>
|
||||||
|
float_sum(uint64_t float1, uint64_t float2) const;
|
||||||
|
|
||||||
|
// float_sto
|
||||||
|
// float_sto_set
|
||||||
|
Expected<uint64_t, HookReturnCode>
|
||||||
|
float_invert(uint64_t float1) const;
|
||||||
|
|
||||||
|
Expected<uint64_t, HookReturnCode>
|
||||||
|
float_divide(uint64_t float1, uint64_t float2) const;
|
||||||
|
|
||||||
|
uint64_t
|
||||||
|
float_one() const;
|
||||||
|
|
||||||
|
Expected<uint64_t, HookReturnCode>
|
||||||
|
float_mantissa(uint64_t float1) const;
|
||||||
|
|
||||||
|
uint64_t
|
||||||
|
float_sign(uint64_t float1) const;
|
||||||
|
|
||||||
|
Expected<uint64_t, HookReturnCode>
|
||||||
|
float_int(uint64_t float1, uint32_t decimal_places, uint32_t absolute)
|
||||||
|
const;
|
||||||
|
|
||||||
|
Expected<uint64_t, HookReturnCode>
|
||||||
|
float_log(uint64_t float1) const;
|
||||||
|
|
||||||
|
Expected<uint64_t, HookReturnCode>
|
||||||
|
float_root(uint64_t float1, uint32_t n) const;
|
||||||
|
|
||||||
|
/// otxn APIs
|
||||||
uint64_t
|
uint64_t
|
||||||
otxn_burden() const;
|
otxn_burden() const;
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
otxn_generation() const;
|
||||||
|
// otxn_field
|
||||||
|
// otxn_id
|
||||||
|
// otxn_type
|
||||||
|
// otxn_slot
|
||||||
|
// otxn_param
|
||||||
|
|
||||||
|
/// hook APIs
|
||||||
|
// hook_account
|
||||||
|
// hook_hash
|
||||||
|
// hook_again
|
||||||
|
// hook_param
|
||||||
|
// hook_param_set
|
||||||
|
// hook_skip
|
||||||
|
// hook_pos
|
||||||
|
|
||||||
|
/// ledger APIs
|
||||||
|
// fee_base
|
||||||
|
// ledger_seq
|
||||||
|
// ledger_last_hash
|
||||||
|
// ledger_last_time
|
||||||
|
// ledger_nonce
|
||||||
|
// ledger_keylet
|
||||||
|
|
||||||
|
/// state APIs
|
||||||
|
// state
|
||||||
|
// state_foreign
|
||||||
|
// state_set
|
||||||
|
// state_foreign_set
|
||||||
|
|
||||||
|
/// slot APIs
|
||||||
|
// slot
|
||||||
|
// slot_clear
|
||||||
|
// slot_count
|
||||||
|
// slot_set
|
||||||
|
// slot_size
|
||||||
|
// slot_subarray
|
||||||
|
// slot_subfield
|
||||||
|
// slot_type
|
||||||
|
// slot_float
|
||||||
|
|
||||||
|
/// trace APIs
|
||||||
|
// trace
|
||||||
|
// trace_num
|
||||||
|
// trace_float
|
||||||
|
|
||||||
|
// meta_slot
|
||||||
|
// xpop_slot
|
||||||
|
|
||||||
private:
|
private:
|
||||||
HookContext& hookCtx;
|
HookContext& hookCtx;
|
||||||
|
|
||||||
|
inline Expected<uint64_t, HookReturnCode>
|
||||||
|
float_multiply_internal_parts(
|
||||||
|
uint64_t man1,
|
||||||
|
int32_t exp1,
|
||||||
|
bool neg1,
|
||||||
|
uint64_t man2,
|
||||||
|
int32_t exp2,
|
||||||
|
bool neg2) const;
|
||||||
|
|
||||||
|
inline Expected<uint64_t, HookReturnCode>
|
||||||
|
mulratio_internal(
|
||||||
|
int64_t& man1,
|
||||||
|
int32_t& exp1,
|
||||||
|
bool round_up,
|
||||||
|
uint32_t numerator,
|
||||||
|
uint32_t denominator) const;
|
||||||
|
|
||||||
|
inline Expected<uint64_t, HookReturnCode>
|
||||||
|
float_divide_internal(uint64_t float1, uint64_t float2) const;
|
||||||
|
|
||||||
|
inline Expected<uint64_t, HookReturnCode>
|
||||||
|
double_to_xfl(double x) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace hook
|
} // namespace hook
|
||||||
|
|||||||
@@ -846,6 +846,11 @@ public:
|
|||||||
ADD_HOOK_FUNCTION(hook_account, ctx);
|
ADD_HOOK_FUNCTION(hook_account, ctx);
|
||||||
ADD_HOOK_FUNCTION(hook_hash, ctx);
|
ADD_HOOK_FUNCTION(hook_hash, ctx);
|
||||||
ADD_HOOK_FUNCTION(hook_again, ctx);
|
ADD_HOOK_FUNCTION(hook_again, ctx);
|
||||||
|
ADD_HOOK_FUNCTION(hook_param, ctx);
|
||||||
|
ADD_HOOK_FUNCTION(hook_param_set, ctx);
|
||||||
|
ADD_HOOK_FUNCTION(hook_skip, ctx);
|
||||||
|
ADD_HOOK_FUNCTION(hook_pos, ctx);
|
||||||
|
|
||||||
ADD_HOOK_FUNCTION(fee_base, ctx);
|
ADD_HOOK_FUNCTION(fee_base, ctx);
|
||||||
ADD_HOOK_FUNCTION(ledger_seq, ctx);
|
ADD_HOOK_FUNCTION(ledger_seq, ctx);
|
||||||
ADD_HOOK_FUNCTION(ledger_last_hash, ctx);
|
ADD_HOOK_FUNCTION(ledger_last_hash, ctx);
|
||||||
@@ -853,11 +858,6 @@ public:
|
|||||||
ADD_HOOK_FUNCTION(ledger_nonce, ctx);
|
ADD_HOOK_FUNCTION(ledger_nonce, ctx);
|
||||||
ADD_HOOK_FUNCTION(ledger_keylet, ctx);
|
ADD_HOOK_FUNCTION(ledger_keylet, ctx);
|
||||||
|
|
||||||
ADD_HOOK_FUNCTION(hook_param, ctx);
|
|
||||||
ADD_HOOK_FUNCTION(hook_param_set, ctx);
|
|
||||||
ADD_HOOK_FUNCTION(hook_skip, ctx);
|
|
||||||
ADD_HOOK_FUNCTION(hook_pos, ctx);
|
|
||||||
|
|
||||||
ADD_HOOK_FUNCTION(state, ctx);
|
ADD_HOOK_FUNCTION(state, ctx);
|
||||||
ADD_HOOK_FUNCTION(state_foreign, ctx);
|
ADD_HOOK_FUNCTION(state_foreign, ctx);
|
||||||
ADD_HOOK_FUNCTION(state_set, ctx);
|
ADD_HOOK_FUNCTION(state_set, ctx);
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -4494,71 +4494,15 @@ DEFINE_HOOK_FUNCTION(int64_t, float_set, int32_t exp, int64_t mantissa)
|
|||||||
HOOK_SETUP(); // populates memory_ctx, memory, memory_length, applyCtx,
|
HOOK_SETUP(); // populates memory_ctx, memory, memory_length, applyCtx,
|
||||||
// hookCtx on current stack
|
// hookCtx on current stack
|
||||||
|
|
||||||
if (mantissa == 0)
|
hook::HookAPI api(hookCtx);
|
||||||
return 0;
|
auto const result = api.float_set(exp, mantissa);
|
||||||
|
if (!result)
|
||||||
int64_t normalized = hook_float::normalize_xfl(mantissa, exp);
|
return result.error();
|
||||||
|
return result.value();
|
||||||
// the above function will underflow into a canonical 0
|
|
||||||
// but this api must report that underflow
|
|
||||||
if (normalized == 0 || normalized == XFL_OVERFLOW)
|
|
||||||
return INVALID_FLOAT;
|
|
||||||
|
|
||||||
return normalized;
|
|
||||||
|
|
||||||
HOOK_TEARDOWN();
|
HOOK_TEARDOWN();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int64_t
|
|
||||||
mulratio_internal(
|
|
||||||
int64_t& man1,
|
|
||||||
int32_t& exp1,
|
|
||||||
bool round_up,
|
|
||||||
uint32_t numerator,
|
|
||||||
uint32_t denominator)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
ripple::IOUAmount amt{man1, exp1};
|
|
||||||
ripple::IOUAmount out = ripple::mulRatio(
|
|
||||||
amt, numerator, denominator, round_up != 0); // already normalized
|
|
||||||
man1 = out.mantissa();
|
|
||||||
exp1 = out.exponent();
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
catch (std::overflow_error& e)
|
|
||||||
{
|
|
||||||
return XFL_OVERFLOW;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int64_t
|
|
||||||
float_multiply_internal_parts(
|
|
||||||
uint64_t man1,
|
|
||||||
int32_t exp1,
|
|
||||||
bool neg1,
|
|
||||||
uint64_t man2,
|
|
||||||
int32_t exp2,
|
|
||||||
bool neg2)
|
|
||||||
{
|
|
||||||
using namespace boost::multiprecision;
|
|
||||||
cpp_int mult = cpp_int(man1) * cpp_int(man2);
|
|
||||||
mult /= power_of_ten[15];
|
|
||||||
uint64_t man_out = static_cast<uint64_t>(mult);
|
|
||||||
if (mult > man_out)
|
|
||||||
return XFL_OVERFLOW;
|
|
||||||
|
|
||||||
int32_t exp_out = exp1 + exp2 + 15;
|
|
||||||
bool neg_out = (neg1 && !neg2) || (!neg1 && neg2);
|
|
||||||
int64_t ret = normalize_xfl(man_out, exp_out, neg_out);
|
|
||||||
|
|
||||||
if (ret == EXPONENT_UNDERSIZED)
|
|
||||||
return 0;
|
|
||||||
if (ret == EXPONENT_OVERSIZED)
|
|
||||||
return XFL_OVERFLOW;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEFINE_HOOK_FUNCTION(
|
DEFINE_HOOK_FUNCTION(
|
||||||
int64_t,
|
int64_t,
|
||||||
float_int,
|
float_int,
|
||||||
@@ -4570,33 +4514,12 @@ DEFINE_HOOK_FUNCTION(
|
|||||||
// hookCtx on current stack
|
// hookCtx on current stack
|
||||||
|
|
||||||
RETURN_IF_INVALID_FLOAT(float1);
|
RETURN_IF_INVALID_FLOAT(float1);
|
||||||
if (float1 == 0)
|
|
||||||
return 0;
|
|
||||||
uint64_t man1 = get_mantissa(float1);
|
|
||||||
int32_t exp1 = get_exponent(float1);
|
|
||||||
bool neg1 = is_negative(float1);
|
|
||||||
|
|
||||||
if (decimal_places > 15)
|
hook::HookAPI api(hookCtx);
|
||||||
return INVALID_ARGUMENT;
|
auto const result = api.float_int(float1, decimal_places, absolute);
|
||||||
|
if (!result)
|
||||||
if (neg1)
|
return result.error();
|
||||||
{
|
return result.value();
|
||||||
if (!absolute)
|
|
||||||
return CANT_RETURN_NEGATIVE;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t shift = -(exp1 + decimal_places);
|
|
||||||
|
|
||||||
if (shift > 15)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (shift < 0)
|
|
||||||
return TOO_BIG;
|
|
||||||
|
|
||||||
if (shift > 0)
|
|
||||||
man1 /= power_of_ten[shift];
|
|
||||||
|
|
||||||
return man1;
|
|
||||||
|
|
||||||
HOOK_TEARDOWN();
|
HOOK_TEARDOWN();
|
||||||
}
|
}
|
||||||
@@ -4609,17 +4532,11 @@ DEFINE_HOOK_FUNCTION(int64_t, float_multiply, int64_t float1, int64_t float2)
|
|||||||
RETURN_IF_INVALID_FLOAT(float1);
|
RETURN_IF_INVALID_FLOAT(float1);
|
||||||
RETURN_IF_INVALID_FLOAT(float2);
|
RETURN_IF_INVALID_FLOAT(float2);
|
||||||
|
|
||||||
if (float1 == 0 || float2 == 0)
|
hook::HookAPI api(hookCtx);
|
||||||
return 0;
|
auto const result = api.float_multiply(float1, float2);
|
||||||
|
if (!result)
|
||||||
uint64_t man1 = get_mantissa(float1);
|
return result.error();
|
||||||
int32_t exp1 = get_exponent(float1);
|
return result.value();
|
||||||
bool neg1 = is_negative(float1);
|
|
||||||
uint64_t man2 = get_mantissa(float2);
|
|
||||||
int32_t exp2 = get_exponent(float2);
|
|
||||||
bool neg2 = is_negative(float2);
|
|
||||||
|
|
||||||
return float_multiply_internal_parts(man1, exp1, neg1, man2, exp2, neg2);
|
|
||||||
|
|
||||||
HOOK_TEARDOWN();
|
HOOK_TEARDOWN();
|
||||||
}
|
}
|
||||||
@@ -4636,22 +4553,13 @@ DEFINE_HOOK_FUNCTION(
|
|||||||
// hookCtx on current stack
|
// hookCtx on current stack
|
||||||
|
|
||||||
RETURN_IF_INVALID_FLOAT(float1);
|
RETURN_IF_INVALID_FLOAT(float1);
|
||||||
if (float1 == 0)
|
|
||||||
return 0;
|
|
||||||
if (denominator == 0)
|
|
||||||
return DIVISION_BY_ZERO;
|
|
||||||
|
|
||||||
int64_t man1 = (int64_t)get_mantissa(float1);
|
hook::HookAPI api(hookCtx);
|
||||||
int32_t exp1 = get_exponent(float1);
|
auto const result =
|
||||||
|
api.float_mulratio(float1, round_up, numerator, denominator);
|
||||||
if (mulratio_internal(man1, exp1, round_up > 0, numerator, denominator) < 0)
|
if (!result)
|
||||||
return XFL_OVERFLOW;
|
return result.error();
|
||||||
|
return result.value();
|
||||||
// defensive check
|
|
||||||
if (man1 < 0)
|
|
||||||
man1 *= -1LL;
|
|
||||||
|
|
||||||
return make_float((uint64_t)man1, exp1, is_negative(float1));
|
|
||||||
|
|
||||||
HOOK_TEARDOWN();
|
HOOK_TEARDOWN();
|
||||||
}
|
}
|
||||||
@@ -4661,10 +4569,10 @@ DEFINE_HOOK_FUNCTION(int64_t, float_negate, int64_t float1)
|
|||||||
HOOK_SETUP(); // populates memory_ctx, memory, memory_length, applyCtx,
|
HOOK_SETUP(); // populates memory_ctx, memory, memory_length, applyCtx,
|
||||||
// hookCtx on current stack
|
// hookCtx on current stack
|
||||||
|
|
||||||
if (float1 == 0)
|
|
||||||
return 0;
|
|
||||||
RETURN_IF_INVALID_FLOAT(float1);
|
RETURN_IF_INVALID_FLOAT(float1);
|
||||||
return hook_float::invert_sign(float1);
|
|
||||||
|
hook::HookAPI api(hookCtx);
|
||||||
|
return api.float_negate(float1);
|
||||||
|
|
||||||
HOOK_TEARDOWN();
|
HOOK_TEARDOWN();
|
||||||
}
|
}
|
||||||
@@ -4682,46 +4590,11 @@ DEFINE_HOOK_FUNCTION(
|
|||||||
RETURN_IF_INVALID_FLOAT(float1);
|
RETURN_IF_INVALID_FLOAT(float1);
|
||||||
RETURN_IF_INVALID_FLOAT(float2);
|
RETURN_IF_INVALID_FLOAT(float2);
|
||||||
|
|
||||||
bool equal_flag = mode & compare_mode::EQUAL;
|
hook::HookAPI api(hookCtx);
|
||||||
bool less_flag = mode & compare_mode::LESS;
|
auto const result = api.float_compare(float1, float2, mode);
|
||||||
bool greater_flag = mode & compare_mode::GREATER;
|
if (!result)
|
||||||
bool not_equal = less_flag && greater_flag;
|
return result.error();
|
||||||
|
return result.value();
|
||||||
if ((equal_flag && less_flag && greater_flag) || mode == 0)
|
|
||||||
return INVALID_ARGUMENT;
|
|
||||||
|
|
||||||
if (mode & (~0b111UL))
|
|
||||||
return INVALID_ARGUMENT;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
int64_t man1 = (int64_t)(get_mantissa(float1)) *
|
|
||||||
(is_negative(float1) ? -1LL : 1LL);
|
|
||||||
int32_t exp1 = get_exponent(float1);
|
|
||||||
ripple::IOUAmount amt1{man1, exp1};
|
|
||||||
int64_t man2 = (int64_t)(get_mantissa(float2)) *
|
|
||||||
(is_negative(float2) ? -1LL : 1LL);
|
|
||||||
int32_t exp2 = get_exponent(float2);
|
|
||||||
ripple::IOUAmount amt2{man2, exp2};
|
|
||||||
|
|
||||||
if (not_equal && amt1 != amt2)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (equal_flag && amt1 == amt2)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (greater_flag && amt1 > amt2)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (less_flag && amt1 < amt2)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
catch (std::overflow_error& e)
|
|
||||||
{
|
|
||||||
return XFL_OVERFLOW;
|
|
||||||
}
|
|
||||||
|
|
||||||
HOOK_TEARDOWN();
|
HOOK_TEARDOWN();
|
||||||
}
|
}
|
||||||
@@ -4734,36 +4607,11 @@ DEFINE_HOOK_FUNCTION(int64_t, float_sum, int64_t float1, int64_t float2)
|
|||||||
RETURN_IF_INVALID_FLOAT(float1);
|
RETURN_IF_INVALID_FLOAT(float1);
|
||||||
RETURN_IF_INVALID_FLOAT(float2);
|
RETURN_IF_INVALID_FLOAT(float2);
|
||||||
|
|
||||||
if (float1 == 0)
|
hook::HookAPI api(hookCtx);
|
||||||
return float2;
|
auto const result = api.float_sum(float1, float2);
|
||||||
if (float2 == 0)
|
if (!result)
|
||||||
return float1;
|
return result.error();
|
||||||
|
return result.value();
|
||||||
int64_t man1 =
|
|
||||||
(int64_t)(get_mantissa(float1)) * (is_negative(float1) ? -1LL : 1LL);
|
|
||||||
int32_t exp1 = get_exponent(float1);
|
|
||||||
int64_t man2 =
|
|
||||||
(int64_t)(get_mantissa(float2)) * (is_negative(float2) ? -1LL : 1LL);
|
|
||||||
int32_t exp2 = get_exponent(float2);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
ripple::IOUAmount amt1{man1, exp1};
|
|
||||||
ripple::IOUAmount amt2{man2, exp2};
|
|
||||||
amt1 += amt2;
|
|
||||||
int64_t result = make_float(amt1);
|
|
||||||
if (result == EXPONENT_UNDERSIZED)
|
|
||||||
{
|
|
||||||
// this is an underflow e.g. as a result of subtracting an xfl from
|
|
||||||
// itself and thus not an error, just return canonical 0
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
catch (std::overflow_error& e)
|
|
||||||
{
|
|
||||||
return XFL_OVERFLOW;
|
|
||||||
}
|
|
||||||
|
|
||||||
HOOK_TEARDOWN();
|
HOOK_TEARDOWN();
|
||||||
}
|
}
|
||||||
@@ -5066,100 +4914,27 @@ DEFINE_HOOK_FUNCTION(
|
|||||||
HOOK_TEARDOWN();
|
HOOK_TEARDOWN();
|
||||||
}
|
}
|
||||||
|
|
||||||
const int64_t float_one_internal = make_float(1000000000000000ull, -15, false);
|
|
||||||
|
|
||||||
inline int64_t
|
|
||||||
float_divide_internal(int64_t float1, int64_t float2, bool hasFix)
|
|
||||||
{
|
|
||||||
RETURN_IF_INVALID_FLOAT(float1);
|
|
||||||
RETURN_IF_INVALID_FLOAT(float2);
|
|
||||||
if (float2 == 0)
|
|
||||||
return DIVISION_BY_ZERO;
|
|
||||||
if (float1 == 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
// special case: division by 1
|
|
||||||
// RH TODO: add more special cases (division by power of 10)
|
|
||||||
if (float2 == float_one_internal)
|
|
||||||
return float1;
|
|
||||||
|
|
||||||
uint64_t man1 = get_mantissa(float1);
|
|
||||||
int32_t exp1 = get_exponent(float1);
|
|
||||||
bool neg1 = is_negative(float1);
|
|
||||||
uint64_t man2 = get_mantissa(float2);
|
|
||||||
int32_t exp2 = get_exponent(float2);
|
|
||||||
bool neg2 = is_negative(float2);
|
|
||||||
|
|
||||||
int64_t tmp1 = normalize_xfl(man1, exp1);
|
|
||||||
int64_t tmp2 = normalize_xfl(man2, exp2);
|
|
||||||
|
|
||||||
if (tmp1 < 0 || tmp2 < 0)
|
|
||||||
return INVALID_FLOAT;
|
|
||||||
|
|
||||||
if (tmp1 == 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
while (man2 > man1)
|
|
||||||
{
|
|
||||||
man2 /= 10;
|
|
||||||
exp2++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (man2 == 0)
|
|
||||||
return DIVISION_BY_ZERO;
|
|
||||||
|
|
||||||
while (man2 < man1)
|
|
||||||
{
|
|
||||||
if (man2 * 10 > man1)
|
|
||||||
break;
|
|
||||||
man2 *= 10;
|
|
||||||
exp2--;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t man3 = 0;
|
|
||||||
int32_t exp3 = exp1 - exp2;
|
|
||||||
|
|
||||||
while (man2 > 0)
|
|
||||||
{
|
|
||||||
int i = 0;
|
|
||||||
if (hasFix)
|
|
||||||
{
|
|
||||||
for (; man1 >= man2; man1 -= man2, ++i)
|
|
||||||
;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (; man1 > man2; man1 -= man2, ++i)
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
man3 *= 10;
|
|
||||||
man3 += i;
|
|
||||||
man2 /= 10;
|
|
||||||
if (man2 == 0)
|
|
||||||
break;
|
|
||||||
exp3--;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool neg3 = !((neg1 && neg2) || (!neg1 && !neg2));
|
|
||||||
|
|
||||||
return normalize_xfl(man3, exp3, neg3);
|
|
||||||
}
|
|
||||||
|
|
||||||
DEFINE_HOOK_FUNCTION(int64_t, float_divide, int64_t float1, int64_t float2)
|
DEFINE_HOOK_FUNCTION(int64_t, float_divide, int64_t float1, int64_t float2)
|
||||||
{
|
{
|
||||||
HOOK_SETUP(); // populates memory_ctx, memory, memory_length, applyCtx,
|
HOOK_SETUP(); // populates memory_ctx, memory, memory_length, applyCtx,
|
||||||
// hookCtx on current stack
|
// hookCtx on current stack
|
||||||
|
|
||||||
bool const hasFix = view.rules().enabled(fixFloatDivide);
|
RETURN_IF_INVALID_FLOAT(float1);
|
||||||
return float_divide_internal(float1, float2, hasFix);
|
RETURN_IF_INVALID_FLOAT(float2);
|
||||||
|
|
||||||
|
hook::HookAPI api(hookCtx);
|
||||||
|
auto const result = api.float_divide(float1, float2);
|
||||||
|
if (!result)
|
||||||
|
return result.error();
|
||||||
|
return result.value();
|
||||||
|
|
||||||
HOOK_TEARDOWN();
|
HOOK_TEARDOWN();
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_HOOK_FUNCNARG(int64_t, float_one)
|
DEFINE_HOOK_FUNCNARG(int64_t, float_one)
|
||||||
{
|
{
|
||||||
return float_one_internal;
|
hook::HookAPI api(hookCtx);
|
||||||
|
return api.float_one();
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_HOOK_FUNCTION(int64_t, float_invert, int64_t float1)
|
DEFINE_HOOK_FUNCTION(int64_t, float_invert, int64_t float1)
|
||||||
@@ -5167,13 +4942,13 @@ DEFINE_HOOK_FUNCTION(int64_t, float_invert, int64_t float1)
|
|||||||
HOOK_SETUP(); // populates memory_ctx, memory, memory_length, applyCtx,
|
HOOK_SETUP(); // populates memory_ctx, memory, memory_length, applyCtx,
|
||||||
// hookCtx on current stack
|
// hookCtx on current stack
|
||||||
|
|
||||||
if (float1 == 0)
|
RETURN_IF_INVALID_FLOAT(float1);
|
||||||
return DIVISION_BY_ZERO;
|
|
||||||
if (float1 == float_one_internal)
|
|
||||||
return float_one_internal;
|
|
||||||
|
|
||||||
bool const fixV3 = view.rules().enabled(fixFloatDivide);
|
hook::HookAPI api(hookCtx);
|
||||||
return float_divide_internal(float_one_internal, float1, fixV3);
|
auto const result = api.float_invert(float1);
|
||||||
|
if (!result)
|
||||||
|
return result.error();
|
||||||
|
return result.value();
|
||||||
|
|
||||||
HOOK_TEARDOWN();
|
HOOK_TEARDOWN();
|
||||||
}
|
}
|
||||||
@@ -5184,9 +4959,12 @@ DEFINE_HOOK_FUNCTION(int64_t, float_mantissa, int64_t float1)
|
|||||||
// hookCtx on current stack
|
// hookCtx on current stack
|
||||||
|
|
||||||
RETURN_IF_INVALID_FLOAT(float1);
|
RETURN_IF_INVALID_FLOAT(float1);
|
||||||
if (float1 == 0)
|
|
||||||
return 0;
|
hook::HookAPI api(hookCtx);
|
||||||
return get_mantissa(float1);
|
auto const result = api.float_mantissa(float1);
|
||||||
|
if (!result)
|
||||||
|
return result.error();
|
||||||
|
return result.value();
|
||||||
|
|
||||||
HOOK_TEARDOWN();
|
HOOK_TEARDOWN();
|
||||||
}
|
}
|
||||||
@@ -5197,62 +4975,13 @@ DEFINE_HOOK_FUNCTION(int64_t, float_sign, int64_t float1)
|
|||||||
// hookCtx on current stack
|
// hookCtx on current stack
|
||||||
|
|
||||||
RETURN_IF_INVALID_FLOAT(float1);
|
RETURN_IF_INVALID_FLOAT(float1);
|
||||||
if (float1 == 0)
|
|
||||||
return 0;
|
hook::HookAPI api(hookCtx);
|
||||||
return is_negative(float1);
|
return api.float_sign(float1);
|
||||||
|
|
||||||
HOOK_TEARDOWN();
|
HOOK_TEARDOWN();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int64_t
|
|
||||||
double_to_xfl(double x)
|
|
||||||
{
|
|
||||||
if ((x) == 0)
|
|
||||||
return 0;
|
|
||||||
bool neg = x < 0;
|
|
||||||
double absresult = neg ? -x : x;
|
|
||||||
|
|
||||||
// first compute the base 10 order of the float
|
|
||||||
int32_t exp_out = (int32_t)log10(absresult);
|
|
||||||
|
|
||||||
// next adjust it into the valid mantissa range (this means dividing by its
|
|
||||||
// order and multiplying by 10**15)
|
|
||||||
absresult *= pow(10, -exp_out + 15);
|
|
||||||
|
|
||||||
// after adjustment the value may still fall below the minMantissa
|
|
||||||
int64_t result = (int64_t)absresult;
|
|
||||||
if (result < minMantissa)
|
|
||||||
{
|
|
||||||
if (result == minMantissa - 1LL)
|
|
||||||
result += 1LL;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result *= 10LL;
|
|
||||||
exp_out--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// likewise the value can fall above the maxMantissa
|
|
||||||
if (result > maxMantissa)
|
|
||||||
{
|
|
||||||
if (result == maxMantissa + 1LL)
|
|
||||||
result -= 1LL;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result /= 10LL;
|
|
||||||
exp_out++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
exp_out -= 15;
|
|
||||||
int64_t ret = make_float(result, exp_out, neg);
|
|
||||||
|
|
||||||
if (ret == EXPONENT_UNDERSIZED)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEFINE_HOOK_FUNCTION(int64_t, float_log, int64_t float1)
|
DEFINE_HOOK_FUNCTION(int64_t, float_log, int64_t float1)
|
||||||
{
|
{
|
||||||
HOOK_SETUP(); // populates memory_ctx, memory, memory_length, applyCtx,
|
HOOK_SETUP(); // populates memory_ctx, memory, memory_length, applyCtx,
|
||||||
@@ -5260,18 +4989,11 @@ DEFINE_HOOK_FUNCTION(int64_t, float_log, int64_t float1)
|
|||||||
|
|
||||||
RETURN_IF_INVALID_FLOAT(float1);
|
RETURN_IF_INVALID_FLOAT(float1);
|
||||||
|
|
||||||
if (float1 == 0)
|
hook::HookAPI api(hookCtx);
|
||||||
return INVALID_ARGUMENT;
|
auto const result = api.float_log(float1);
|
||||||
|
if (!result)
|
||||||
uint64_t man1 = get_mantissa(float1);
|
return result.error();
|
||||||
int32_t exp1 = get_exponent(float1);
|
return result.value();
|
||||||
if (is_negative(float1))
|
|
||||||
return COMPLEX_NOT_SUPPORTED;
|
|
||||||
|
|
||||||
double inp = (double)(man1);
|
|
||||||
double result = log10(inp) + exp1;
|
|
||||||
|
|
||||||
return double_to_xfl(result);
|
|
||||||
|
|
||||||
HOOK_TEARDOWN();
|
HOOK_TEARDOWN();
|
||||||
}
|
}
|
||||||
@@ -5282,21 +5004,12 @@ DEFINE_HOOK_FUNCTION(int64_t, float_root, int64_t float1, uint32_t n)
|
|||||||
// hookCtx on current stack
|
// hookCtx on current stack
|
||||||
|
|
||||||
RETURN_IF_INVALID_FLOAT(float1);
|
RETURN_IF_INVALID_FLOAT(float1);
|
||||||
if (float1 == 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (n < 2)
|
hook::HookAPI api(hookCtx);
|
||||||
return INVALID_ARGUMENT;
|
auto const result = api.float_root(float1, n);
|
||||||
|
if (!result)
|
||||||
uint64_t man1 = get_mantissa(float1);
|
return result.error();
|
||||||
int32_t exp1 = get_exponent(float1);
|
return result.value();
|
||||||
if (is_negative(float1))
|
|
||||||
return COMPLEX_NOT_SUPPORTED;
|
|
||||||
|
|
||||||
double inp = (double)(man1)*pow(10, exp1);
|
|
||||||
double result = pow(inp, ((double)1.0f) / ((double)(n)));
|
|
||||||
|
|
||||||
return double_to_xfl(result);
|
|
||||||
|
|
||||||
HOOK_TEARDOWN();
|
HOOK_TEARDOWN();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user