axelar-cgp-sui

Module 0x0::math

use 0x1::u128;
use 0x1::vector;

Constants

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;

Function mul

Multiply two floating numbers. This function will round down the result.

public(friend) fun mul(x: u64, y: u64): u64
Implementation
public(package) fun mul(x: u64, y: u64): u64 {
    let (_, result) = mul_internal(x, y);

    result
}

Function mul_u128

public(friend) fun mul_u128(x: u128, y: u128): u128
Implementation
public(package) fun mul_u128(x: u128, y: u128): u128 {
    let (_, result) = mul_internal_u128(x, y);

    result
}

Function 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
Implementation
public(package) fun mul_round_up(x: u64, y: u64): u64 {
    let (is_round_down, result) = mul_internal(x, y);

    result + is_round_down
}

Function div

Divide two floating numbers. This function will round down the result.

public(friend) fun div(x: u64, y: u64): u64
Implementation
public(package) fun div(x: u64, y: u64): u64 {
    let (_, result) = div_internal(x, y);

    result
}

Function div_u128

public(friend) fun div_u128(x: u128, y: u128): u128
Implementation
public(package) fun div_u128(x: u128, y: u128): u128 {
    let (_, result) = div_internal_u128(x, y);

    result
}

Function 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
Implementation
public(package) fun div_round_up(x: u64, y: u64): u64 {
    let (is_round_down, result) = div_internal(x, y);

    result + is_round_down
}

Function median

given a vector of u64, return the median

public(friend) fun median(v: vector<u128>): u128
Implementation
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]
    }
}

Function 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
Implementation
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
}

Function quick_sort

fun quick_sort(data: vector<u128>): vector<u128>
Implementation
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
}

Function mul_internal

fun mul_internal(x: u64, y: u64): (u64, u64)
Implementation
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)
}

Function mul_internal_u128

fun mul_internal_u128(x: u128, y: u128): (u128, u128)
Implementation
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)
}

Function div_internal

fun div_internal(x: u64, y: u64): (u64, u64)
Implementation
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)
}

Function div_internal_u128

fun div_internal_u128(x: u128, y: u128): (u128, u128)
Implementation
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)
}