rust/fpnum/src/lib.rs
branchtransitional_engine
changeset 16079 624b74443b53
parent 15860 c910381d1ea9
child 16081 6633961698ad
equal deleted inserted replaced
16078:db18f1a30b0c 16079:624b74443b53
     1 use std::{cmp, ops, ops::Shl};
     1 use std::{cmp, ops};
       
     2 use saturate::SaturatingInto;
     2 
     3 
     3 const POSITIVE_MASK: u64 = 0x0000_0000_0000_0000;
     4 const POSITIVE_MASK: u64 = 0x0000_0000_0000_0000;
     4 const NEGATIVE_MASK: u64 = 0xFFFF_FFFF_FFFF_FFFF;
     5 const NEGATIVE_MASK: u64 = 0xFFFF_FFFF_FFFF_FFFF;
     5 
     6 
     6 #[inline]
     7 #[inline]
    64 
    65 
    65     #[inline]
    66     #[inline]
    66     pub fn sqr(&self) -> Self {
    67     pub fn sqr(&self) -> Self {
    67         Self {
    68         Self {
    68             sign_mask: 0,
    69             sign_mask: 0,
    69             value: ((self.value as u128).pow(2) >> 32) as u64,
    70             value: ((self.value as u128).pow(2) >> 32).saturating_into(),
    70         }
    71         }
    71     }
    72     }
    72 
    73 
    73     #[inline]
    74     #[inline]
    74     pub fn sqrt(&self) -> Self {
    75     pub fn sqrt(&self) -> Self {
   147 
   148 
   148 impl Eq for FPNum {}
   149 impl Eq for FPNum {}
   149 
   150 
   150 impl PartialOrd for FPNum {
   151 impl PartialOrd for FPNum {
   151     #[inline]
   152     #[inline]
   152     fn partial_cmp(&self, rhs: &Self) -> std::option::Option<std::cmp::Ordering> {
   153     fn partial_cmp(&self, rhs: &Self) -> Option<cmp::Ordering> {
   153         Some(self.cmp(rhs))
   154         Some(self.cmp(rhs))
   154     }
   155     }
   155 }
   156 }
   156 
   157 
   157 impl Ord for FPNum {
   158 impl Ord for FPNum {
   202 
   203 
   203     #[inline]
   204     #[inline]
   204     fn mul(self, rhs: Self) -> Self {
   205     fn mul(self, rhs: Self) -> Self {
   205         Self {
   206         Self {
   206             sign_mask: self.sign_mask ^ rhs.sign_mask,
   207             sign_mask: self.sign_mask ^ rhs.sign_mask,
   207             value: ((self.value as u128 * rhs.value as u128) >> 32) as u64,
   208             value: ((self.value as u128 * rhs.value as u128) >> 32).saturating_into(),
   208         }
   209         }
   209     }
   210     }
   210 }
   211 }
   211 
   212 
   212 impl ops::Mul<i32> for FPNum {
   213 impl ops::Mul<i32> for FPNum {
   214 
   215 
   215     #[inline]
   216     #[inline]
   216     fn mul(self, rhs: i32) -> Self {
   217     fn mul(self, rhs: i32) -> Self {
   217         Self {
   218         Self {
   218             sign_mask: self.sign_mask ^ bool_mask(rhs < 0),
   219             sign_mask: self.sign_mask ^ bool_mask(rhs < 0),
   219             value: self.value * rhs.abs() as u64,
   220             value: (self.value as u128 * rhs.abs() as u128).saturating_into(),
   220         }
   221         }
   221     }
   222     }
   222 }
   223 }
   223 
   224 
   224 impl ops::Div for FPNum {
   225 impl ops::Div for FPNum {
   226 
   227 
   227     #[inline]
   228     #[inline]
   228     fn div(self, rhs: Self) -> Self {
   229     fn div(self, rhs: Self) -> Self {
   229         Self {
   230         Self {
   230             sign_mask: self.sign_mask ^ rhs.sign_mask,
   231             sign_mask: self.sign_mask ^ rhs.sign_mask,
   231             value: (((self.value as u128) << 32) / rhs.value as u128) as u64,
   232             value: (((self.value as u128) << 32) / rhs.value as u128).saturating_into(),
   232         }
   233         }
   233     }
   234     }
   234 }
   235 }
   235 
   236 
   236 impl ops::Div<i32> for FPNum {
   237 impl ops::Div<i32> for FPNum {
   324         self.x().is_zero() && self.y().is_zero()
   325         self.x().is_zero() && self.y().is_zero()
   325     }
   326     }
   326 
   327 
   327     #[inline]
   328     #[inline]
   328     pub fn max_norm(&self) -> FPNum {
   329     pub fn max_norm(&self) -> FPNum {
   329         std::cmp::max(self.x().abs(), self.y().abs())
   330         cmp::max(self.x().abs(), self.y().abs())
   330     }
   331     }
   331 
   332 
   332     #[inline]
   333     #[inline]
   333     pub fn sqr_distance(&self) -> FPNum {
   334     pub fn sqr_distance(&self) -> FPNum {
   334         self.x().sqr() + self.y().sqr()
   335         self.x().sqr() + self.y().sqr()
   503 }
   504 }
   504 
   505 
   505 #[inline]
   506 #[inline]
   506 pub fn distance<T>(x: T, y: T) -> FPNum
   507 pub fn distance<T>(x: T, y: T) -> FPNum
   507 where
   508 where
   508     T: Into<i64> + std::fmt::Debug,
   509     T: Into<i128> + std::fmt::Debug,
   509 {
   510 {
   510     let sqr: u128 = (x.into().pow(2) as u128).shl(64) + (y.into().pow(2) as u128).shl(64);
   511     let [x_squared, y_squared] = [x, y].map(|i| (i.into().pow(2) as u128).saturating_mul(2^64));
       
   512     let sqr: u128 = x_squared.saturating_add(y_squared);
   511 
   513 
   512     FPNum {
   514     FPNum {
   513         sign_mask: POSITIVE_MASK,
   515         sign_mask: POSITIVE_MASK,
   514         value: integral_sqrt_ext(sqr),
   516         value: integral_sqrt_ext(sqr),
   515     }
   517     }