add struct ToFixedHelper
This commit is contained in:
parent
aac10de995
commit
91a1f1554b
57
src/cmp.rs
57
src/cmp.rs
|
@ -29,16 +29,16 @@ macro_rules! fixed_cmp_fixed {
|
|||
impl<FracLhs: $LhsLeEqU, FracRhs: $RhsLeEqU> PartialEq<$Rhs<FracRhs>> for $Lhs<FracLhs> {
|
||||
#[inline]
|
||||
fn eq(&self, rhs: &$Rhs<FracRhs>) -> bool {
|
||||
let (rhs_128, dir, overflow) = rhs.to_bits().to_fixed_dir_overflow(
|
||||
let conv = rhs.to_bits().to_fixed_helper(
|
||||
<$Rhs<FracRhs>>::FRAC_NBITS as i32,
|
||||
Self::FRAC_NBITS,
|
||||
Self::INT_NBITS,
|
||||
);
|
||||
let rhs_bits = match rhs_128 {
|
||||
let rhs_bits = match conv.bits {
|
||||
Widest::Unsigned(bits) => bits as <Self as Fixed>::Bits,
|
||||
Widest::Negative(bits) => bits as <Self as Fixed>::Bits,
|
||||
};
|
||||
dir == Ordering::Equal && !overflow && rhs_bits == self.to_bits()
|
||||
conv.dir == Ordering::Equal && !conv.overflow && rhs_bits == self.to_bits()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -50,23 +50,23 @@ macro_rules! fixed_cmp_fixed {
|
|||
(true, false) => return Some(Ordering::Less),
|
||||
_ => {}
|
||||
}
|
||||
let (rhs_128, dir, overflow) = rhs.to_bits().to_fixed_dir_overflow(
|
||||
let conv = rhs.to_bits().to_fixed_helper(
|
||||
<$Rhs<FracRhs>>::FRAC_NBITS as i32,
|
||||
Self::FRAC_NBITS,
|
||||
Self::INT_NBITS,
|
||||
);
|
||||
if overflow {
|
||||
if conv.overflow {
|
||||
return if rhs.to_bits().is_negative() {
|
||||
Some(Ordering::Greater)
|
||||
} else {
|
||||
Some(Ordering::Less)
|
||||
};
|
||||
}
|
||||
let rhs_bits = match rhs_128 {
|
||||
let rhs_bits = match conv.bits {
|
||||
Widest::Unsigned(bits) => bits as <Self as Fixed>::Bits,
|
||||
Widest::Negative(bits) => bits as <Self as Fixed>::Bits,
|
||||
};
|
||||
Some(self.to_bits().cmp(&rhs_bits).then(dir))
|
||||
Some(self.to_bits().cmp(&rhs_bits).then(conv.dir))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -76,19 +76,20 @@ macro_rules! fixed_cmp_fixed {
|
|||
(true, false) => return true,
|
||||
_ => {}
|
||||
}
|
||||
let (rhs_128, dir, overflow) = rhs.to_bits().to_fixed_dir_overflow(
|
||||
let conv = rhs.to_bits().to_fixed_helper(
|
||||
<$Rhs<FracRhs>>::FRAC_NBITS as i32,
|
||||
Self::FRAC_NBITS,
|
||||
Self::INT_NBITS,
|
||||
);
|
||||
if overflow {
|
||||
if conv.overflow {
|
||||
return !rhs.to_bits().is_negative();
|
||||
}
|
||||
let rhs_bits = match rhs_128 {
|
||||
let rhs_bits = match conv.bits {
|
||||
Widest::Unsigned(bits) => bits as <Self as Fixed>::Bits,
|
||||
Widest::Negative(bits) => bits as <Self as Fixed>::Bits,
|
||||
};
|
||||
self.to_bits() < rhs_bits || (self.to_bits() == rhs_bits && dir == Ordering::Less)
|
||||
self.to_bits() < rhs_bits
|
||||
|| (self.to_bits() == rhs_bits && conv.dir == Ordering::Less)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -189,13 +190,12 @@ macro_rules! fixed_cmp_float {
|
|||
if !SealedFloat::is_finite(*rhs) {
|
||||
return false;
|
||||
}
|
||||
let (rhs_128, dir, overflow) =
|
||||
rhs.to_fixed_dir_overflow(Self::FRAC_NBITS, Self::INT_NBITS);
|
||||
let rhs_bits = match rhs_128 {
|
||||
let conv = rhs.to_fixed_helper(Self::FRAC_NBITS, Self::INT_NBITS);
|
||||
let rhs_bits = match conv.bits {
|
||||
Widest::Unsigned(bits) => bits as <Self as Fixed>::Bits,
|
||||
Widest::Negative(bits) => bits as <Self as Fixed>::Bits,
|
||||
};
|
||||
dir == Ordering::Equal && !overflow && rhs_bits == self.to_bits()
|
||||
conv.dir == Ordering::Equal && !conv.overflow && rhs_bits == self.to_bits()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -225,20 +225,19 @@ macro_rules! fixed_cmp_float {
|
|||
(true, false) => return Some(Ordering::Less),
|
||||
_ => {}
|
||||
}
|
||||
let (rhs_128, dir, overflow) =
|
||||
rhs.to_fixed_dir_overflow(Self::FRAC_NBITS, Self::INT_NBITS);
|
||||
if overflow {
|
||||
let conv = rhs.to_fixed_helper(Self::FRAC_NBITS, Self::INT_NBITS);
|
||||
if conv.overflow {
|
||||
return if rhs_is_neg {
|
||||
Some(Ordering::Greater)
|
||||
} else {
|
||||
Some(Ordering::Less)
|
||||
};
|
||||
}
|
||||
let rhs_bits = match rhs_128 {
|
||||
let rhs_bits = match conv.bits {
|
||||
Widest::Unsigned(bits) => bits as <Self as Fixed>::Bits,
|
||||
Widest::Negative(bits) => bits as <Self as Fixed>::Bits,
|
||||
};
|
||||
Some(self.to_bits().cmp(&rhs_bits).then(dir))
|
||||
Some(self.to_bits().cmp(&rhs_bits).then(conv.dir))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -255,17 +254,16 @@ macro_rules! fixed_cmp_float {
|
|||
(true, false) => return true,
|
||||
_ => {}
|
||||
}
|
||||
let (rhs_128, dir, overflow) =
|
||||
rhs.to_fixed_dir_overflow(Self::FRAC_NBITS, Self::INT_NBITS);
|
||||
if overflow {
|
||||
let conv = rhs.to_fixed_helper(Self::FRAC_NBITS, Self::INT_NBITS);
|
||||
if conv.overflow {
|
||||
return !rhs_is_neg;
|
||||
}
|
||||
let rhs_bits = match rhs_128 {
|
||||
let rhs_bits = match conv.bits {
|
||||
Widest::Unsigned(bits) => bits as <Self as Fixed>::Bits,
|
||||
Widest::Negative(bits) => bits as <Self as Fixed>::Bits,
|
||||
};
|
||||
let lhs_bits = self.to_bits();
|
||||
lhs_bits < rhs_bits || (lhs_bits == rhs_bits && dir == Ordering::Less)
|
||||
lhs_bits < rhs_bits || (lhs_bits == rhs_bits && conv.dir == Ordering::Less)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -304,17 +302,16 @@ macro_rules! fixed_cmp_float {
|
|||
(true, false) => return true,
|
||||
_ => {}
|
||||
}
|
||||
let (lhs_128, dir, overflow) =
|
||||
self.to_fixed_dir_overflow(<$Fix<Frac>>::FRAC_NBITS, <$Fix<Frac>>::INT_NBITS);
|
||||
if overflow {
|
||||
let conv = self.to_fixed_helper(<$Fix<Frac>>::FRAC_NBITS, <$Fix<Frac>>::INT_NBITS);
|
||||
if conv.overflow {
|
||||
return lhs_is_neg;
|
||||
}
|
||||
let lhs_bits = match lhs_128 {
|
||||
let lhs_bits = match conv.bits {
|
||||
Widest::Unsigned(bits) => bits as <$Fix<Frac> as Fixed>::Bits,
|
||||
Widest::Negative(bits) => bits as <$Fix<Frac> as Fixed>::Bits,
|
||||
};
|
||||
let rhs_bits = rhs.to_bits();
|
||||
lhs_bits < rhs_bits || (lhs_bits == rhs_bits && dir == Ordering::Greater)
|
||||
lhs_bits < rhs_bits || (lhs_bits == rhs_bits && conv.dir == Ordering::Greater)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
|
@ -18,7 +18,7 @@ This module contains sealed traits.
|
|||
*/
|
||||
|
||||
pub(crate) use crate::{
|
||||
sealed_fixed::{SealedFixed, Widest},
|
||||
sealed_fixed::{SealedFixed, ToFixedHelper, Widest},
|
||||
sealed_float::SealedFloat,
|
||||
sealed_int::SealedInt,
|
||||
};
|
||||
|
|
|
@ -21,6 +21,7 @@ use crate::{
|
|||
FixedU8,
|
||||
};
|
||||
use core::{
|
||||
cmp::Ordering,
|
||||
fmt::{Debug, Display},
|
||||
hash::Hash,
|
||||
};
|
||||
|
@ -32,6 +33,12 @@ pub enum Widest {
|
|||
Negative(i128),
|
||||
}
|
||||
|
||||
pub struct ToFixedHelper {
|
||||
pub(crate) bits: Widest,
|
||||
pub(crate) dir: Ordering,
|
||||
pub(crate) overflow: bool,
|
||||
}
|
||||
|
||||
pub trait SealedFixed: Copy {
|
||||
type FracNBits: Unsigned;
|
||||
type SBits: SealedInt;
|
||||
|
@ -102,12 +109,12 @@ macro_rules! sealed_fixed {
|
|||
|
||||
#[inline]
|
||||
fn saturating_from_fixed<F: Fixed>(val: F) -> Self {
|
||||
let (value, _, overflow) = val.to_sbits().to_fixed_dir_overflow(
|
||||
let conv = val.to_sbits().to_fixed_helper(
|
||||
F::FRAC_NBITS as i32,
|
||||
Self::FRAC_NBITS,
|
||||
Self::INT_NBITS,
|
||||
);
|
||||
if overflow {
|
||||
if conv.overflow {
|
||||
return if val.to_sbits().is_negative() {
|
||||
SealedFixed::from_sbits(Self::SBits::min_value())
|
||||
} else {
|
||||
|
@ -116,7 +123,7 @@ macro_rules! sealed_fixed {
|
|||
}
|
||||
let bits = if_signed_unsigned!(
|
||||
$Signedness,
|
||||
match value {
|
||||
match conv.bits {
|
||||
Widest::Unsigned(bits) => {
|
||||
if (bits as Self::SBits) < 0 {
|
||||
return $Fixed::from_bits(Self::SBits::max_value());
|
||||
|
@ -125,7 +132,7 @@ macro_rules! sealed_fixed {
|
|||
}
|
||||
Widest::Negative(bits) => bits as Self::SBits,
|
||||
},
|
||||
match value {
|
||||
match conv.bits {
|
||||
Widest::Unsigned(bits) => bits as Self::SBits,
|
||||
Widest::Negative(_) => {
|
||||
return $Fixed::from_bits(Self::SBits::min_value());
|
||||
|
@ -137,31 +144,32 @@ macro_rules! sealed_fixed {
|
|||
|
||||
#[inline]
|
||||
fn overflowing_from_fixed<F: Fixed>(val: F) -> (Self, bool) {
|
||||
let (value, _, mut overflow) = val.to_sbits().to_fixed_dir_overflow(
|
||||
let conv = val.to_sbits().to_fixed_helper(
|
||||
F::FRAC_NBITS as i32,
|
||||
Self::FRAC_NBITS,
|
||||
Self::INT_NBITS,
|
||||
);
|
||||
let mut new_overflow = false;
|
||||
let bits = if_signed_unsigned!(
|
||||
$Signedness,
|
||||
match value {
|
||||
match conv.bits {
|
||||
Widest::Unsigned(bits) => {
|
||||
if (bits as Self::SBits) < 0 {
|
||||
overflow = true;
|
||||
new_overflow = true;
|
||||
}
|
||||
bits as Self::SBits
|
||||
}
|
||||
Widest::Negative(bits) => bits as Self::SBits,
|
||||
},
|
||||
match value {
|
||||
match conv.bits {
|
||||
Widest::Unsigned(bits) => bits as Self::SBits,
|
||||
Widest::Negative(bits) => {
|
||||
overflow = true;
|
||||
new_overflow = true;
|
||||
bits as Self::SBits
|
||||
}
|
||||
},
|
||||
);
|
||||
($Fixed::from_bits(bits), overflow)
|
||||
($Fixed::from_bits(bits), conv.overflow || new_overflow)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -177,14 +185,13 @@ macro_rules! sealed_fixed {
|
|||
if !val.is_finite() {
|
||||
return saturated;
|
||||
}
|
||||
let (value, _, overflow) =
|
||||
val.to_fixed_dir_overflow(Self::FRAC_NBITS, Self::INT_NBITS);
|
||||
if overflow {
|
||||
let conv = val.to_fixed_helper(Self::FRAC_NBITS, Self::INT_NBITS);
|
||||
if conv.overflow {
|
||||
return saturated;
|
||||
}
|
||||
let bits = if_signed_unsigned!(
|
||||
$Signedness,
|
||||
match value {
|
||||
match conv.bits {
|
||||
Widest::Unsigned(bits) => {
|
||||
if (bits as Self::SBits) < 0 {
|
||||
return Self::max_value();
|
||||
|
@ -193,7 +200,7 @@ macro_rules! sealed_fixed {
|
|||
}
|
||||
Widest::Negative(bits) => bits as Self::SBits,
|
||||
},
|
||||
match value {
|
||||
match conv.bits {
|
||||
Widest::Unsigned(bits) => bits as Self::SBits,
|
||||
Widest::Negative(_) => return Self::min_value(),
|
||||
},
|
||||
|
@ -205,28 +212,28 @@ macro_rules! sealed_fixed {
|
|||
if !val.is_finite() {
|
||||
panic!("{} is not finite", val.traits());
|
||||
}
|
||||
let (value, _, mut overflow) =
|
||||
val.to_fixed_dir_overflow(Self::FRAC_NBITS, Self::INT_NBITS);
|
||||
let conv = val.to_fixed_helper(Self::FRAC_NBITS, Self::INT_NBITS);
|
||||
let mut new_overflow = false;
|
||||
let bits = if_signed_unsigned!(
|
||||
$Signedness,
|
||||
match value {
|
||||
match conv.bits {
|
||||
Widest::Unsigned(bits) => {
|
||||
if (bits as Self::SBits) < 0 {
|
||||
overflow = true;
|
||||
new_overflow = true;
|
||||
}
|
||||
bits as Self::SBits
|
||||
}
|
||||
Widest::Negative(bits) => bits as Self::SBits,
|
||||
},
|
||||
match value {
|
||||
match conv.bits {
|
||||
Widest::Unsigned(bits) => bits as Self::SBits,
|
||||
Widest::Negative(bits) => {
|
||||
overflow = true;
|
||||
new_overflow = true;
|
||||
bits as Self::SBits
|
||||
}
|
||||
},
|
||||
);
|
||||
($Fixed::from_bits(bits), overflow)
|
||||
($Fixed::from_bits(bits), conv.overflow || new_overflow)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
// <https://www.apache.org/licenses/LICENSE-2.0> and
|
||||
// <https://opensource.org/licenses/MIT>.
|
||||
|
||||
use crate::sealed::{Fixed, SealedFixed, SealedInt, Widest};
|
||||
use crate::sealed::{Fixed, SealedFixed, SealedInt, ToFixedHelper, Widest};
|
||||
use core::{
|
||||
cmp::Ordering,
|
||||
fmt::{Debug, Display},
|
||||
|
@ -79,7 +79,7 @@ pub trait SealedFloat: Copy {
|
|||
|
||||
fn from_neg_abs(neg: bool, abs: u128, frac_bits: u32, int_bits: u32) -> Self;
|
||||
// self must be finite, otherwise meaningless results are returned
|
||||
fn to_fixed_dir_overflow(self, frac_bits: u32, int_bits: u32) -> (Widest, Ordering, bool);
|
||||
fn to_fixed_helper(self, frac_bits: u32, int_bits: u32) -> ToFixedHelper;
|
||||
}
|
||||
|
||||
macro_rules! sealed_float {
|
||||
|
@ -212,11 +212,7 @@ macro_rules! sealed_float {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn to_fixed_dir_overflow(
|
||||
self,
|
||||
dst_frac_bits: u32,
|
||||
dst_int_bits: u32,
|
||||
) -> (Widest, Ordering, bool) {
|
||||
fn to_fixed_helper(self, dst_frac_bits: u32, dst_int_bits: u32) -> ToFixedHelper {
|
||||
let prec = Self::PREC as i32;
|
||||
|
||||
let (neg, exp, mut mantissa) = self.parts();
|
||||
|
@ -226,7 +222,11 @@ macro_rules! sealed_float {
|
|||
mantissa |= 1 << (prec - 1);
|
||||
}
|
||||
if mantissa == 0 {
|
||||
return (Widest::Unsigned(0), Ordering::Equal, false);
|
||||
return ToFixedHelper {
|
||||
bits: Widest::Unsigned(0),
|
||||
dir: Ordering::Equal,
|
||||
overflow: false,
|
||||
};
|
||||
}
|
||||
|
||||
let mut src_frac_bits = prec - 1 - exp;
|
||||
|
@ -237,7 +237,11 @@ macro_rules! sealed_float {
|
|||
} else {
|
||||
Ordering::Less
|
||||
};
|
||||
return (Widest::Unsigned(0), dir, false);
|
||||
return ToFixedHelper {
|
||||
bits: Widest::Unsigned(0),
|
||||
dir,
|
||||
overflow: false,
|
||||
};
|
||||
}
|
||||
let mut dir = Ordering::Equal;
|
||||
if need_to_shr > 0 {
|
||||
|
@ -262,9 +266,8 @@ macro_rules! sealed_float {
|
|||
mantissa = -mantissa;
|
||||
dir = dir.reverse();
|
||||
}
|
||||
let (fixed, _, overflow) =
|
||||
mantissa.to_fixed_dir_overflow(src_frac_bits, dst_frac_bits, dst_int_bits);
|
||||
(fixed, dir, overflow)
|
||||
let conv = mantissa.to_fixed_helper(src_frac_bits, dst_frac_bits, dst_int_bits);
|
||||
ToFixedHelper { dir, ..conv }
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
use crate::{
|
||||
frac::{Bit, False, True, Unsigned, U0, U128, U16, U32, U64, U8},
|
||||
sealed::{Fixed, SealedFixed, Widest},
|
||||
sealed::{Fixed, SealedFixed, ToFixedHelper, Widest},
|
||||
FixedI128, FixedI16, FixedI32, FixedI64, FixedI8, FixedU128, FixedU16, FixedU32, FixedU64,
|
||||
FixedU8,
|
||||
};
|
||||
|
@ -94,12 +94,12 @@ pub trait SealedInt: Copy {
|
|||
fn overflowing_add(self, val: Self) -> (Self, bool);
|
||||
fn leading_zeros(self) -> u32;
|
||||
|
||||
fn to_fixed_dir_overflow(
|
||||
fn to_fixed_helper(
|
||||
self,
|
||||
src_frac_bits: i32,
|
||||
dst_frac_bits: u32,
|
||||
dst_int_bits: u32,
|
||||
) -> (Widest, Ordering, bool);
|
||||
) -> ToFixedHelper;
|
||||
|
||||
fn to_repr_fixed(self) -> Self::ReprFixed;
|
||||
|
||||
|
@ -219,17 +219,21 @@ macro_rules! sealed_int {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn to_fixed_dir_overflow(
|
||||
fn to_fixed_helper(
|
||||
self,
|
||||
src_frac_bits: i32,
|
||||
dst_frac_bits: u32,
|
||||
dst_int_bits: u32,
|
||||
) -> (Widest, Ordering, bool) {
|
||||
) -> ToFixedHelper {
|
||||
let src_bits = Self::NBITS as i32;
|
||||
let dst_bits = (dst_frac_bits + dst_int_bits) as i32;
|
||||
|
||||
if self == 0 {
|
||||
return (Widest::Unsigned(0), Ordering::Equal, false);
|
||||
return ToFixedHelper {
|
||||
bits:Widest::Unsigned(0),
|
||||
dir:Ordering::Equal,
|
||||
overflow:false,
|
||||
};
|
||||
}
|
||||
|
||||
let leading_zeros = self.leading_zeros();
|
||||
|
@ -248,7 +252,11 @@ macro_rules! sealed_int {
|
|||
_ => unreachable!(),
|
||||
};
|
||||
let dir = if lost_bits { Ordering::Less } else { Ordering::Equal };
|
||||
(Widest::Unsigned(bits), dir, overflow)
|
||||
ToFixedHelper {
|
||||
bits: Widest::Unsigned(bits),
|
||||
dir,
|
||||
overflow,
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -281,17 +289,21 @@ macro_rules! sealed_int {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn to_fixed_dir_overflow(
|
||||
fn to_fixed_helper(
|
||||
self,
|
||||
src_frac_bits: i32,
|
||||
dst_frac_bits: u32,
|
||||
dst_int_bits: u32,
|
||||
) -> (Widest, Ordering, bool) {
|
||||
) -> ToFixedHelper {
|
||||
let src_bits = Self::NBITS as i32;
|
||||
let dst_bits = (dst_frac_bits + dst_int_bits) as i32;
|
||||
|
||||
if self == 0 {
|
||||
return (Widest::Unsigned(0), Ordering::Equal, false);
|
||||
return ToFixedHelper {
|
||||
bits: Widest::Unsigned(0),
|
||||
dir: Ordering::Equal,
|
||||
overflow: false,
|
||||
};
|
||||
}
|
||||
|
||||
let need_to_shr = src_frac_bits - dst_frac_bits as i32;
|
||||
|
@ -314,11 +326,12 @@ macro_rules! sealed_int {
|
|||
_ => unreachable!(),
|
||||
};
|
||||
let dir = if lost_bits { Ordering::Less } else { Ordering::Equal };
|
||||
if self >= 0 {
|
||||
(Widest::Unsigned(bits as u128), dir, overflow)
|
||||
let bits = if self >= 0 {
|
||||
Widest::Unsigned(bits as u128)
|
||||
} else {
|
||||
(Widest::Negative(bits), dir, overflow)
|
||||
}
|
||||
Widest::Negative(bits)
|
||||
};
|
||||
ToFixedHelper { bits, dir, overflow }
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue