127 lines
2.7 KiB
Rust
127 lines
2.7 KiB
Rust
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::<f64>() {
|
|
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 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_recip(&self) -> String {
|
|
if *self<FiNum::one() { format!("1/{}",self.recip()) }
|
|
else { format!("{}",self) }
|
|
}
|
|
pub fn serialize(&self) -> String {
|
|
format!("{:X}",self.0)
|
|
}
|
|
pub fn new_deserialize(s: &str) -> Self {
|
|
FiNum(u64::from_str_radix(s, 16).unwrap())
|
|
}
|
|
}
|
|
|
|
impl From<i32> 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<Ordering> {
|
|
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, "{:.8}", (self.0 as f64)/((1u64<<32) as f64))
|
|
}
|
|
}
|
|
|