to_fixed_overflow -> to_fixed_dir_overflow
This commit is contained in:
parent
7e9e3ef04d
commit
9ebfa67cac
12
src/lib.rs
12
src/lib.rs
|
@ -1131,7 +1131,7 @@ assert_eq!(Dst::saturating_from_fixed(too_small), Dst::min_value());
|
||||||
where
|
where
|
||||||
F: Fixed,
|
F: Fixed,
|
||||||
{
|
{
|
||||||
let (value, overflow) = F::Bits::to_fixed_overflow(
|
let (value, _, overflow) = F::Bits::to_fixed_dir_overflow(
|
||||||
val.to_bits(),
|
val.to_bits(),
|
||||||
F::FRAC_NBITS,
|
F::FRAC_NBITS,
|
||||||
Self::FRAC_NBITS,
|
Self::FRAC_NBITS,
|
||||||
|
@ -1254,7 +1254,7 @@ assert_eq!(Fix::saturating_from_int(too_small), Fix::min_value());
|
||||||
where
|
where
|
||||||
I: Int,
|
I: Int,
|
||||||
{
|
{
|
||||||
let (value, overflow) = I::to_fixed_overflow(
|
let (value, _, overflow) = I::to_fixed_dir_overflow(
|
||||||
val,
|
val,
|
||||||
0,
|
0,
|
||||||
Self::FRAC_NBITS,
|
Self::FRAC_NBITS,
|
||||||
|
@ -1736,7 +1736,7 @@ assert_eq!(Dst::overflowing_from_fixed(too_large), (wrapped, true));
|
||||||
where
|
where
|
||||||
F: Fixed,
|
F: Fixed,
|
||||||
{
|
{
|
||||||
let (value, mut overflow) = F::Bits::to_fixed_overflow(
|
let (value, _, mut overflow) = F::Bits::to_fixed_dir_overflow(
|
||||||
val.to_bits(),
|
val.to_bits(),
|
||||||
F::FRAC_NBITS,
|
F::FRAC_NBITS,
|
||||||
Self::FRAC_NBITS,
|
Self::FRAC_NBITS,
|
||||||
|
@ -1854,7 +1854,7 @@ assert_eq!(Fix::overflowing_from_int(large), (wrapped, true));
|
||||||
where
|
where
|
||||||
I: Int,
|
I: Int,
|
||||||
{
|
{
|
||||||
let (value, mut overflow) = I::to_fixed_overflow(
|
let (value, _, mut overflow) = I::to_fixed_dir_overflow(
|
||||||
val,
|
val,
|
||||||
0,
|
0,
|
||||||
Self::FRAC_NBITS,
|
Self::FRAC_NBITS,
|
||||||
|
@ -3033,14 +3033,14 @@ assert_eq!(Fix::from_bits(bits).rotate_right(3), Fix::from_bits(rot));
|
||||||
/// Wrapping fixed-point multiplication.
|
/// Wrapping fixed-point multiplication.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn wrapping_mul(self, rhs: $Fixed<Frac>) -> $Fixed<Frac> {
|
pub fn wrapping_mul(self, rhs: $Fixed<Frac>) -> $Fixed<Frac> {
|
||||||
let (ans, _dir) = self.to_bits().mul_dir(rhs.to_bits(), Frac::U32);
|
let (ans, _) = self.to_bits().mul_dir(rhs.to_bits(), Frac::U32);
|
||||||
Self::from_bits(ans)
|
Self::from_bits(ans)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Wrapping fixed-point division.
|
/// Wrapping fixed-point division.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn wrapping_div(self, rhs: $Fixed<Frac>) -> $Fixed<Frac> {
|
pub fn wrapping_div(self, rhs: $Fixed<Frac>) -> $Fixed<Frac> {
|
||||||
let (ans, _dir) = self.to_bits().div_dir(rhs.to_bits(), Frac::U32);
|
let (ans, _) = self.to_bits().div_dir(rhs.to_bits(), Frac::U32);
|
||||||
Self::from_bits(ans)
|
Self::from_bits(ans)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
// <https://www.apache.org/licenses/LICENSE-2.0> and
|
// <https://www.apache.org/licenses/LICENSE-2.0> and
|
||||||
// <https://opensource.org/licenses/MIT>.
|
// <https://opensource.org/licenses/MIT>.
|
||||||
|
|
||||||
|
use core::cmp::Ordering;
|
||||||
use core::fmt::{Debug, Display};
|
use core::fmt::{Debug, Display};
|
||||||
use frac::{Bit, False, True, Unsigned, U0, U1, U128, U16, U32, U64, U7, U8};
|
use frac::{Bit, False, True, Unsigned, U0, U1, U128, U16, U32, U64, U7, U8};
|
||||||
use sealed::{Fixed, Widest};
|
use sealed::{Fixed, Widest};
|
||||||
|
@ -45,12 +46,12 @@ pub trait SealedInt: Copy + Ord + Debug + Display {
|
||||||
fn is_zero(self) -> bool;
|
fn is_zero(self) -> bool;
|
||||||
fn is_negative(self) -> bool;
|
fn is_negative(self) -> bool;
|
||||||
|
|
||||||
fn to_fixed_overflow(
|
fn to_fixed_dir_overflow(
|
||||||
self,
|
self,
|
||||||
src_frac_bits: u32,
|
src_frac_bits: u32,
|
||||||
dst_frac_bits: u32,
|
dst_frac_bits: u32,
|
||||||
dst_int_bits: u32,
|
dst_int_bits: u32,
|
||||||
) -> (Widest, bool);
|
) -> (Widest, Ordering, bool);
|
||||||
|
|
||||||
fn neg_abs(self) -> (bool, Self::Unsigned);
|
fn neg_abs(self) -> (bool, Self::Unsigned);
|
||||||
fn from_neg_abs(neg: bool, abs: Self::Unsigned) -> Self;
|
fn from_neg_abs(neg: bool, abs: Self::Unsigned) -> Self;
|
||||||
|
@ -132,34 +133,36 @@ macro_rules! sealed_int {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_fixed_overflow(
|
fn to_fixed_dir_overflow(
|
||||||
self,
|
self,
|
||||||
src_frac_bits: u32,
|
src_frac_bits: u32,
|
||||||
dst_frac_bits: u32,
|
dst_frac_bits: u32,
|
||||||
dst_int_bits: u32,
|
dst_int_bits: u32,
|
||||||
) -> (Widest, bool) {
|
) -> (Widest, Ordering, bool) {
|
||||||
let src_bits = Self::NBITS as i32;
|
let src_bits = Self::NBITS as i32;
|
||||||
let dst_bits = (dst_frac_bits + dst_int_bits) as i32;
|
let dst_bits = (dst_frac_bits + dst_int_bits) as i32;
|
||||||
|
|
||||||
if self == 0 {
|
if self == 0 {
|
||||||
return (Widest::Unsigned(0), false);
|
return (Widest::Unsigned(0), Ordering::Equal, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
let leading_zeros = self.leading_zeros();
|
let leading_zeros = self.leading_zeros();
|
||||||
let bits = self << leading_zeros;
|
let need_to_shr = src_frac_bits as i32 - dst_frac_bits as i32;
|
||||||
let need_to_shr =
|
let overflow = src_bits - dst_bits > need_to_shr + leading_zeros as i32;
|
||||||
leading_zeros as i32 + src_frac_bits as i32 - dst_frac_bits as i32;
|
let bits_128 = u128::from(self);
|
||||||
let overflow = src_bits - need_to_shr > dst_bits;
|
let (bits, lost_bits) = match need_to_shr {
|
||||||
let bits = if need_to_shr == 0 {
|
-128 => (0, false),
|
||||||
u128::from(bits)
|
-127..=-1 => (bits_128 << -need_to_shr, false),
|
||||||
} else if need_to_shr < 0 && -need_to_shr < 128 {
|
0 => (bits_128, false),
|
||||||
u128::from(bits) << -need_to_shr
|
1..=127 => {
|
||||||
} else if need_to_shr > 0 && need_to_shr < 128 {
|
let shifted = bits_128 >> need_to_shr;
|
||||||
u128::from(bits) >> need_to_shr
|
(shifted, shifted << need_to_shr != bits_128)
|
||||||
} else {
|
}
|
||||||
0
|
128 => (0, true),
|
||||||
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
(Widest::Unsigned(bits), overflow)
|
let dir = if lost_bits { Ordering::Less } else { Ordering::Equal };
|
||||||
|
(Widest::Unsigned(bits), dir, overflow)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -192,17 +195,17 @@ macro_rules! sealed_int {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_fixed_overflow(
|
fn to_fixed_dir_overflow(
|
||||||
self,
|
self,
|
||||||
src_frac_bits: u32,
|
src_frac_bits: u32,
|
||||||
dst_frac_bits: u32,
|
dst_frac_bits: u32,
|
||||||
dst_int_bits: u32,
|
dst_int_bits: u32,
|
||||||
) -> (Widest, bool) {
|
) -> (Widest, Ordering, bool) {
|
||||||
let src_bits = Self::NBITS as i32;
|
let src_bits = Self::NBITS as i32;
|
||||||
let dst_bits = (dst_frac_bits + dst_int_bits) as i32;
|
let dst_bits = (dst_frac_bits + dst_int_bits) as i32;
|
||||||
|
|
||||||
if self >= 0 {
|
if self >= 0 {
|
||||||
return SealedInt::to_fixed_overflow(
|
return SealedInt::to_fixed_dir_overflow(
|
||||||
self as $Unsigned,
|
self as $Unsigned,
|
||||||
src_frac_bits,
|
src_frac_bits,
|
||||||
dst_frac_bits,
|
dst_frac_bits,
|
||||||
|
@ -211,20 +214,22 @@ macro_rules! sealed_int {
|
||||||
}
|
}
|
||||||
|
|
||||||
let leading_ones = (!self).leading_zeros();
|
let leading_ones = (!self).leading_zeros();
|
||||||
let bits = self << (leading_ones - 1);
|
let need_to_shr = src_frac_bits as i32 - dst_frac_bits as i32;
|
||||||
let need_to_shr =
|
let overflow = src_bits - dst_bits > need_to_shr + leading_ones as i32 - 1;
|
||||||
leading_ones as i32 - 1 + src_frac_bits as i32 - dst_frac_bits as i32;
|
let bits_128 = i128::from(self);
|
||||||
let overflow = src_bits - need_to_shr > dst_bits;
|
let (bits, lost_bits) = match need_to_shr {
|
||||||
let bits = if need_to_shr == 0 {
|
-128 => (0, false),
|
||||||
i128::from(bits)
|
-127..=-1 => (bits_128 << -need_to_shr, false),
|
||||||
} else if need_to_shr < 0 && -need_to_shr < 128 {
|
0 => (bits_128, false),
|
||||||
i128::from(bits) << -need_to_shr
|
1..=127 => {
|
||||||
} else if need_to_shr > 0 && need_to_shr < 128 {
|
let shifted = bits_128 >> need_to_shr;
|
||||||
i128::from(bits) >> need_to_shr
|
(shifted, shifted << need_to_shr != bits_128)
|
||||||
} else {
|
}
|
||||||
0
|
128 => (-1, true),
|
||||||
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
(Widest::Negative(bits), overflow)
|
let dir = if lost_bits { Ordering::Less } else { Ordering::Equal };
|
||||||
|
(Widest::Negative(bits), dir, overflow)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -289,26 +294,26 @@ impl SealedInt for bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_fixed_overflow(
|
fn to_fixed_dir_overflow(
|
||||||
self,
|
self,
|
||||||
src_frac_bits: u32,
|
src_frac_bits: u32,
|
||||||
dst_frac_bits: u32,
|
dst_frac_bits: u32,
|
||||||
dst_int_bits: u32,
|
dst_int_bits: u32,
|
||||||
) -> (Widest, bool) {
|
) -> (Widest, Ordering, bool) {
|
||||||
debug_assert_eq!(src_frac_bits, 0);
|
debug_assert_eq!(src_frac_bits, 0);
|
||||||
let _ = src_frac_bits;
|
let _ = src_frac_bits;
|
||||||
if !self {
|
if !self {
|
||||||
return (Widest::Unsigned(0), false);
|
return (Widest::Unsigned(0), Ordering::Equal, false);
|
||||||
}
|
}
|
||||||
let overflow = dst_int_bits == 0;
|
let overflow = dst_int_bits == 0;
|
||||||
let bits = if dst_frac_bits == 0 {
|
let (bits, dir) = if dst_frac_bits == 0 {
|
||||||
1u128
|
(1, Ordering::Equal)
|
||||||
} else if dst_frac_bits < 128 {
|
} else if dst_frac_bits < 128 {
|
||||||
1u128 << dst_frac_bits
|
(1 << dst_frac_bits, Ordering::Equal)
|
||||||
} else {
|
} else {
|
||||||
0
|
(0, Ordering::Less)
|
||||||
};
|
};
|
||||||
(Widest::Unsigned(bits), overflow)
|
(Widest::Unsigned(bits), dir, overflow)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
Loading…
Reference in New Issue