add methods to SealedInt and SealedFixed for from_int and from_fixed
This commit is contained in:
parent
073ffb0f29
commit
d6775959c2
13
src/lib.rs
13
src/lib.rs
|
@ -947,7 +947,7 @@ macro_rules! fixed {
|
|||
return saturated;
|
||||
}
|
||||
let (neg, abs_128, overflow) =
|
||||
<F as SealedFloat>::to_neg_abs_overflow(val, frac_bits, int_bits);
|
||||
<F as SealedFloat>::to_fixed_neg_abs_overflow(val, frac_bits, int_bits);
|
||||
if overflow {
|
||||
return saturated;
|
||||
}
|
||||
|
@ -1085,7 +1085,7 @@ macro_rules! fixed {
|
|||
panic!("{} is not finite", val);
|
||||
}
|
||||
let (neg, abs_128, mut overflow) =
|
||||
<F as SealedFloat>::to_neg_abs_overflow(val, frac_bits, int_bits);
|
||||
<F as SealedFloat>::to_fixed_neg_abs_overflow(val, frac_bits, int_bits);
|
||||
let abs_bits =
|
||||
abs_128 as <<$Fixed<Frac> as SealedFixed>::Bits as SealedInt>::Unsigned;
|
||||
|
||||
|
@ -1173,14 +1173,7 @@ macro_rules! fixed {
|
|||
{
|
||||
let frac_bits = Self::frac_bits();
|
||||
let int_bits = Self::int_bits();
|
||||
let (neg, int, frac) = self.parts();
|
||||
let abs = if frac_bits == 0 {
|
||||
int
|
||||
} else if int_bits == 0 {
|
||||
frac
|
||||
} else {
|
||||
(int << frac_bits) | (frac >> int_bits)
|
||||
};
|
||||
let (neg, abs) = self.to_bits().neg_abs();
|
||||
SealedFloat::from_neg_abs(neg, u128::from(abs), frac_bits, int_bits)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,6 +56,8 @@ pub trait SealedFixed: Copy {
|
|||
<Self::Bits as SealedInt>::Unsigned,
|
||||
<Self::Bits as SealedInt>::Unsigned,
|
||||
);
|
||||
|
||||
fn to_neg_abs_overflow(self, frac_bits: u32, int_bits: u32) -> (bool, u128, bool);
|
||||
}
|
||||
|
||||
macro_rules! sealed_fixed {
|
||||
|
@ -98,6 +100,38 @@ macro_rules! sealed_fixed {
|
|||
};
|
||||
(neg, int_abs, frac_abs)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn to_neg_abs_overflow(
|
||||
self,
|
||||
dst_frac_bits: u32,
|
||||
dst_int_bits: u32,
|
||||
) -> (bool, u128, bool) {
|
||||
let src_frac_bits = <Self as SealedFixed>::frac_bits();
|
||||
let src_bits = Self::Bits::nbits() as i32;
|
||||
let dst_bits = (dst_frac_bits + dst_int_bits) as i32;
|
||||
|
||||
if SealedInt::is_zero(self.to_bits()) {
|
||||
return (false, 0, false);
|
||||
}
|
||||
|
||||
let (neg, mut abs) = SealedInt::neg_abs(self.to_bits());
|
||||
let leading_zeros = abs.leading_zeros();
|
||||
abs <<= leading_zeros;
|
||||
let need_to_shr =
|
||||
leading_zeros as i32 + src_frac_bits as i32 - dst_frac_bits as i32;
|
||||
let overflow = src_bits - need_to_shr > dst_bits;
|
||||
let abs = if need_to_shr == 0 {
|
||||
u128::from(abs)
|
||||
} else if need_to_shr < 0 && -need_to_shr < 128 {
|
||||
u128::from(abs) << -need_to_shr
|
||||
} else if need_to_shr > 0 && need_to_shr < 128 {
|
||||
u128::from(abs) >> need_to_shr
|
||||
} else {
|
||||
0
|
||||
};
|
||||
(neg, abs, overflow)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ pub trait SealedFloat: Copy + Display + Debug {
|
|||
|
||||
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_neg_abs_overflow(self, frac_bits: u32, int_bits: u32) -> (bool, u128, bool);
|
||||
fn to_fixed_neg_abs_overflow(self, frac_bits: u32, int_bits: u32) -> (bool, u128, bool);
|
||||
}
|
||||
|
||||
macro_rules! sealed_float {
|
||||
|
@ -170,7 +170,11 @@ macro_rules! sealed_float {
|
|||
Self::from_bits(bits_sign | bits_exp_mantissa)
|
||||
}
|
||||
|
||||
fn to_neg_abs_overflow(self, frac_bits: u32, int_bits: u32) -> (bool, u128, bool) {
|
||||
fn to_fixed_neg_abs_overflow(
|
||||
self,
|
||||
frac_bits: u32,
|
||||
int_bits: u32,
|
||||
) -> (bool, u128, bool) {
|
||||
let float_bits = Self::Bits::nbits() as i32;
|
||||
let prec = Self::prec() as i32;
|
||||
let fix_bits = (frac_bits + int_bits) as i32;
|
||||
|
|
|
@ -21,6 +21,9 @@ pub trait SealedInt: Copy + Ord {
|
|||
fn one_shl(shift: u32) -> Self;
|
||||
fn all_ones_shl(shift: u32) -> Self;
|
||||
fn is_zero(self) -> bool;
|
||||
|
||||
fn to_fixed_neg_abs_overflow(self, frac_bits: u32, int_bits: u32) -> (bool, u128, bool);
|
||||
|
||||
fn neg_abs(self) -> (bool, Self::Unsigned);
|
||||
fn from_neg_abs(neg: bool, abs: Self::Unsigned) -> Self;
|
||||
|
||||
|
@ -60,6 +63,33 @@ macro_rules! sealed_int {
|
|||
self == 0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn to_fixed_neg_abs_overflow(
|
||||
self,
|
||||
frac_bits: u32,
|
||||
int_bits: u32,
|
||||
) -> (bool, u128, bool) {
|
||||
let src_bits = <Self as SealedInt>::nbits() as i32;
|
||||
let dst_bits = (frac_bits + int_bits) as i32;
|
||||
|
||||
let (neg, mut abs) = SealedInt::neg_abs(self);
|
||||
let leading_zeros = abs.leading_zeros();
|
||||
abs <<= leading_zeros;
|
||||
let need_to_shr =
|
||||
leading_zeros as i32 - frac_bits as i32;
|
||||
let overflow = src_bits - need_to_shr > dst_bits;
|
||||
let abs = if need_to_shr == 0 {
|
||||
u128::from(abs)
|
||||
} else if need_to_shr < 0 && -need_to_shr < 128 {
|
||||
u128::from(abs) << -need_to_shr
|
||||
} else if need_to_shr > 0 && need_to_shr < 128 {
|
||||
u128::from(abs) >> need_to_shr
|
||||
} else {
|
||||
0
|
||||
};
|
||||
(neg, abs, overflow)
|
||||
}
|
||||
|
||||
$($rest)*
|
||||
}
|
||||
};
|
||||
|
@ -138,6 +168,22 @@ impl SealedInt for bool {
|
|||
!self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn to_fixed_neg_abs_overflow(self, frac_bits: u32, int_bits: u32) -> (bool, u128, bool) {
|
||||
if !self {
|
||||
return (false, 0, false);
|
||||
}
|
||||
let overflow = int_bits == 0;
|
||||
let abs = if frac_bits == 0 {
|
||||
1u128
|
||||
} else if frac_bits < 128 {
|
||||
1u128 << frac_bits
|
||||
} else {
|
||||
0
|
||||
};
|
||||
(false, abs, overflow)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn neg_abs(self) -> (bool, bool) {
|
||||
(false, self)
|
||||
|
|
Loading…
Reference in New Issue