mod ops;
mod fmt;
mod convert;
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub struct FixedPoint<T, const DECIMALS: u32> {
raw: T,
}
impl<T, const DECIMALS: u32> FixedPoint<T, DECIMALS> {
pub const fn from_raw(raw: T) -> Self {
Self { raw }
}
pub const fn raw(&self) -> &T {
&self.raw
}
pub fn into_raw(self) -> T {
self.raw
}
}
impl<const DECIMALS: u32> FixedPoint<u64, DECIMALS> {
pub const ZERO: Self = Self { raw: 0 };
pub const ONE: Self = Self { raw: Self::scale_u64() };
pub const MAX: Self = Self { raw: u64::MAX };
const fn scale_u64() -> u64 {
let mut result = 1u64;
let mut i = 0;
while i < DECIMALS {
result = result * 10;
i += 1;
}
result
}
pub const fn scale() -> u64 {
Self::scale_u64()
}
}
impl<const DECIMALS: u32> FixedPoint<u128, DECIMALS> {
pub const ZERO: Self = Self { raw: 0 };
pub const ONE: Self = Self { raw: Self::scale_u128() };
pub const MAX: Self = Self { raw: u128::MAX };
const fn scale_u128() -> u128 {
let mut result = 1u128;
let mut i = 0;
while i < DECIMALS {
result = result * 10;
i += 1;
}
result
}
pub const fn scale() -> u128 {
Self::scale_u128()
}
}
impl<T: PartialOrd, const DECIMALS: u32> PartialOrd for FixedPoint<T, DECIMALS> {
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
self.raw.partial_cmp(&other.raw)
}
}
impl<T: Ord, const DECIMALS: u32> Ord for FixedPoint<T, DECIMALS> {
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
self.raw.cmp(&other.raw)
}
}
#[cfg(test)]
mod tests {
use super::*;
type Fp6 = FixedPoint<u64, 6>;
type Fp18 = FixedPoint<u128, 18>;
#[test]
fn scale_values() {
assert_eq!(Fp6::scale(), 1_000_000);
assert_eq!(Fp18::scale(), 1_000_000_000_000_000_000);
}
#[test]
fn zero_and_one() {
assert_eq!(Fp6::ZERO.raw(), &0);
assert_eq!(Fp6::ONE.raw(), &1_000_000);
}
#[test]
fn ordering() {
let a = Fp6::from_raw(100);
let b = Fp6::from_raw(200);
assert!(a < b);
}
}