0x0::math
mul
mul_u128
mul_round_up
div
div_u128
div_round_up
median
sqrt
quick_sort
mul_internal
mul_internal_u128
div_internal
div_internal_u128
use 0x1::u128;
use 0x1::vector;
Error codes
const EInvalidPrecision: u64 = 0;
scaling setting for float
const FLOAT_SCALING: u64 = 1000000000;
const FLOAT_SCALING_U128: u128 = 1000000000;
const FLOAT_SCALING_U256: u256 = 1000000000;
mul
Multiply two floating numbers. This function will round down the result.
public(friend) fun mul(x: u64, y: u64): u64
public(package) fun mul(x: u64, y: u64): u64 {
let (_, result) = mul_internal(x, y);
result
}
mul_u128
public(friend) fun mul_u128(x: u128, y: u128): u128
public(package) fun mul_u128(x: u128, y: u128): u128 {
let (_, result) = mul_internal_u128(x, y);
result
}
mul_round_up
Multiply two floating numbers. This function will round up the result.
public(friend) fun mul_round_up(x: u64, y: u64): u64
public(package) fun mul_round_up(x: u64, y: u64): u64 {
let (is_round_down, result) = mul_internal(x, y);
result + is_round_down
}
div
Divide two floating numbers. This function will round down the result.
public(friend) fun div(x: u64, y: u64): u64
public(package) fun div(x: u64, y: u64): u64 {
let (_, result) = div_internal(x, y);
result
}
div_u128
public(friend) fun div_u128(x: u128, y: u128): u128
public(package) fun div_u128(x: u128, y: u128): u128 {
let (_, result) = div_internal_u128(x, y);
result
}
div_round_up
Divide two floating numbers. This function will round up the result.
public(friend) fun div_round_up(x: u64, y: u64): u64
public(package) fun div_round_up(x: u64, y: u64): u64 {
let (is_round_down, result) = div_internal(x, y);
result + is_round_down
}
median
given a vector of u64, return the median
public(friend) fun median(v: vector<u128>): u128
public(package) fun median(v: vector<u128>): u128 {
let n = v.length();
if (n == 0) {
return 0
};
let sorted_v = quick_sort(v);
if (n % 2 == 0) {
mul_u128(
(sorted_v[n / 2 - 1] + sorted_v[n / 2]),
FLOAT_SCALING_U128 / 2,
)
} else {
sorted_v[n / 2]
}
}
sqrt
Computes the integer square root of a scaled u64 value, assuming the original value is scaled by precision. The result will be in the same floating-point representation.
public(friend) fun sqrt(x: u64, precision: u64): u64
public(package) fun sqrt(x: u64, precision: u64): u64 {
assert!(precision <= FLOAT_SCALING, EInvalidPrecision);
let multiplier = (FLOAT_SCALING / precision) as u128;
let scaled_x: u128 = (x as u128) * multiplier * FLOAT_SCALING_U128;
let sqrt_scaled_x: u128 = std::u128::sqrt(scaled_x);
(sqrt_scaled_x / multiplier) as u64
}
quick_sort
fun quick_sort(data: vector<u128>): vector<u128>
fun quick_sort(data: vector<u128>): vector<u128> {
if (data.length() <= 1) {
return data
};
let pivot = data[0];
let mut less = vector<u128>[];
let mut equal = vector<u128>[];
let mut greater = vector<u128>[];
data.do!(|value| {
if (value < pivot) {
less.push_back(value);
} else if (value == pivot) {
equal.push_back(value);
} else {
greater.push_back(value);
};
});
let mut sortedData = vector<u128>[];
sortedData.append(quick_sort(less));
sortedData.append(equal);
sortedData.append(quick_sort(greater));
sortedData
}
mul_internal
fun mul_internal(x: u64, y: u64): (u64, u64)
fun mul_internal(x: u64, y: u64): (u64, u64) {
let x = x as u128;
let y = y as u128;
let round = if ((x * y) % FLOAT_SCALING_U128 == 0) 0 else 1;
(round, (x * y / FLOAT_SCALING_U128) as u64)
}
mul_internal_u128
fun mul_internal_u128(x: u128, y: u128): (u128, u128)
fun mul_internal_u128(x: u128, y: u128): (u128, u128) {
let x = x as u256;
let y = y as u256;
let round = if ((x * y) % FLOAT_SCALING_U256 == 0) 0 else 1;
(round, (x * y / FLOAT_SCALING_U256) as u128)
}
div_internal
fun div_internal(x: u64, y: u64): (u64, u64)
fun div_internal(x: u64, y: u64): (u64, u64) {
let x = x as u128;
let y = y as u128;
let round = if ((x * FLOAT_SCALING_U128 % y) == 0) 0 else 1;
(round, (x * FLOAT_SCALING_U128 / y) as u64)
}
div_internal_u128
fun div_internal_u128(x: u128, y: u128): (u128, u128)
fun div_internal_u128(x: u128, y: u128): (u128, u128) {
let x = x as u256;
let y = y as u256;
let round = if ((x * FLOAT_SCALING_U256 % y) == 0) 0 else 1;
(round, (x * FLOAT_SCALING_U256 / y) as u128)
}