use std::ops::{Add, Sub, Mul, Div, AddAssign, SubAssign}; use std::cmp::Ordering; #[derive(Debug, Copy, Clone)] pub struct FiNum(u64); impl FiNum { pub fn new_str(s: &str) -> Self { match s.parse::() { Ok(n) => Self::new((n*4294967296.0) as u64), Err(_e) => Self::zero(), } } pub fn new(value: u64) -> Self { FiNum(value) } pub fn new_i32(value: i32) -> Self { FiNum((value as u64)<<32) } pub fn zero() -> Self { FiNum(0u64) } pub fn one() -> Self { FiNum(1u64<<32) } pub fn infinity() -> Self { FiNum(u64::MAX) } pub fn is_tiny(self) -> bool { self.0>0u64 && self.0<=1u64 } pub fn is_zero(self) -> bool { self.0==0 } pub fn value(&self) -> u64 { self.0 } pub fn recip(&self) -> Self { FiNum((0x8000000000000000u64/self.0)<<1) } pub fn fmt_pct2(&self) -> String { format!("{:>5.2}%", (100.0*(self.0 as f64))/((1u64<<32) as f64)) } pub fn fmt_recip(&self) -> String { if *self String { format!("{:X}",self.0) } pub fn new_deserialize(s: &str) -> Self { FiNum(u64::from_str_radix(s, 16).unwrap()) } } impl From for FiNum { fn from(value:i32) -> Self { FiNum::new((value as u64)<<32) } } impl PartialEq for FiNum { fn eq(&self, other:&Self) -> bool { self.0==other.0 } } impl Eq for FiNum { } impl PartialOrd for FiNum { fn partial_cmp(&self, other:&Self) -> Option { self.0.partial_cmp(&other.0) } } impl Ord for FiNum { fn cmp(&self, other:&Self) -> Ordering { self.0.cmp(&other.0) } } impl Add for FiNum { type Output=Self; fn add(self, other: Self) -> Self { FiNum(self.0+other.0) } } impl AddAssign for FiNum { fn add_assign(&mut self, other: Self) { self.0+=other.0; } } impl Sub for FiNum { type Output=Self; fn sub(self, other: Self) -> Self { FiNum(self.0-other.0) } } impl SubAssign for FiNum { fn sub_assign(&mut self, other: Self) { self.0-=other.0; } } impl Mul for FiNum { type Output=Self; fn mul(self, other: Self) -> Self { FiNum(((self.value() as u128)*(other.value() as u128)>>32) as u64) } } impl Div for FiNum { type Output=Self; fn div(self,other:Self) -> Self { let ip=(self.value() as u128)/(other.value() as u128); let rp=(self.value() as u128)%(other.value() as u128); let fp=(rp<<32)/(other.value() as u128); FiNum(((ip<<32)|fp) as u64) } } impl std::fmt::Display for FiNum { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { // write!(f, "{:08X}.{:08X}", self.0>>32,self.0&0xFFFFFFFF) write!(f, "{:.8}", (self.0 as f64)/((1u64<<32) as f64)) } }