left-curve / grug

Grug
https://leftcurve.software/grug
44 stars 5 forks source link

Math implementation #21

Closed larry0x closed 2 weeks ago

larry0x commented 1 month ago

Add math types: {Uint,Int,Decimal,SignedDecimal}{64,128,256,512}.

Compared to CosmWasm, which creates Uint64, Uint128, Uint256... separately, our approach is to create a single generic Uint<T> type, while the concrete types are just it with different generics:

type Uint64 = Uint<u64>;
type Uint128 = Uint<u128>;
type Uint256 = Uint<bnum::U256>;
type Uint512 = Uint<bnum::U512>;

Decimal would be a wrapper over Uint:

struct Decimal<U>(Uint<U>);

A Signed type will allow integers and decimals to take on negative numbers:

struct Signed<T> {
    abs: T,
    is_negative: bool,
}

type Int128 = Signed<Uint<u128>>;
type SignedDecimal128 = Signed<Decimal<u128>>;
Rhaki commented 4 weeks ago

Ready for a review

Rhaki commented 2 weeks ago

Traits Integer and MultiplyRatio are missing for Signed

Rhaki commented 2 weeks ago

Some functions on Udec like new_percent, are not exposed via trait. This doesn't allow to implements these functions also for Signed<T> where T implements. Is it worth to handle these functions in traits? (e.g: MultiplyFraction trait has been created for Uint. Anyway it's also implemented for Signed<T>)

larry0x commented 2 weeks ago

Some functions on Udec like new_percent, are not exposed via trait. This doesn't allow to implements these functions also for Signed<T> where T implements. Is it worth to handle these functions in traits? (e.g: MultiplyFraction trait has been created for Uint. Anyway it's also implemented for Signed<T>)

I think for now we just make them special cases like:

impl<U> Signed<Udec<U>>
where
    // trait bounds...
{
    pub fn new_percent(percent: impl Into<Uint<U>>) -> Self {
        // ...
    }
}