constify some stuff

This commit is contained in:
Trevor Spiteri 2019-01-30 17:31:24 +01:00
parent 87b00f66a2
commit aa707df6c9
6 changed files with 108 additions and 130 deletions

View File

@ -82,7 +82,7 @@ macro_rules! fmt_radix2_helper {
#[inline]
fn take_frac_digit(&mut self, digit_bits: u32) -> u8 {
let nbits = <$UInner as SealedInt>::nbits();
let nbits = <$UInner as SealedInt>::NBITS;
let rem_bits = nbits - digit_bits;
let mask = !0 << rem_bits;
let ret = ((*self & mask) >> rem_bits) as u8;
@ -104,7 +104,7 @@ fn fmt_radix2_helper<F>(
where
F: FmtRadix2Helper,
{
let int_bits = F::nbits() - frac_bits;
let int_bits = F::NBITS - frac_bits;
let digit_bits: u32 = radix.digit_bits();
// 128 binary digits, one radix point, one leading zero
let mut buf: [u8; 130] = [0; 130];
@ -150,7 +150,7 @@ where
Bits: SealedInt,
Bits::Unsigned: FmtRadix2Helper,
{
fmt_radix2_helper(F::frac_bits(), num.parts(), radix, fmt)
fmt_radix2_helper(F::FRAC_NBITS, num.parts(), radix, fmt)
}
macro_rules! impl_fmt {
@ -252,7 +252,7 @@ macro_rules! fmt_dec_helper {
impl FmtDecHelper for $UInner {
#[inline]
fn cmp_half(&self) -> Ordering {
self.cmp(&<$UInner as SealedInt>::msb())
self.cmp(&<$UInner as SealedInt>::MSB)
}
#[inline]
@ -283,7 +283,7 @@ fn fmt_dec_helper<F>(
where
F: FmtDecHelper,
{
let int_bits = F::nbits() - frac_bits;
let int_bits = F::NBITS - frac_bits;
// 40 int digits
// + 128 frac digits
// + 1 dec point,
@ -332,7 +332,7 @@ where
*r = b'0' + frac.take_frac_digit();
}
// check for rounding up
let round_up = match frac.cmp(&F::msb()) {
let round_up = match frac.cmp(&F::MSB) {
Ordering::Less => false,
Ordering::Greater => true,
Ordering::Equal => {
@ -370,7 +370,7 @@ where
Bits: SealedInt,
Bits::Unsigned: FmtDecHelper,
{
fmt_dec_helper(F::frac_bits(), num.parts(), fmt)
fmt_dec_helper(F::FRAC_NBITS, num.parts(), fmt)
}
#[cfg(test)]

View File

@ -19,6 +19,7 @@ This module reexports items from the [*typenum* crate].
[*typenum* crate]: https://crates.io/crates/typenum
*/
pub(crate) use typenum::{Bit, False};
pub use typenum::{
IsGreaterOrEqual, IsLessOrEqual, True, Unsigned, U0, U1, U10, U100, U101, U102, U103, U104,
U105, U106, U107, U108, U109, U11, U110, U111, U112, U113, U114, U115, U116, U117, U118, U119,

View File

@ -487,7 +487,7 @@ assert_eq!(Fix::int_bits(), ",
),
#[inline]
pub fn int_bits() -> u32 {
<Self as SealedFixed>::int_bits()
<Self as SealedFixed>::INT_NBITS
}
);
@ -509,7 +509,7 @@ assert_eq!(Fix::frac_bits(), 6);
),
#[inline]
pub fn frac_bits() -> u32 {
<Self as SealedFixed>::frac_bits()
<Self as SealedFixed>::FRAC_NBITS
}
);
@ -730,15 +730,12 @@ assert_eq!(Fix::saturating_from_fixed(too_small), Fix::min_value());
where
F: Fixed,
{
let frac_bits = Self::frac_bits();
let int_bits = Self::int_bits();
let (value, overflow) =
<<F as SealedFixed>::Bits as SealedInt>::to_fixed_overflow(
val.to_bits(),
<F as SealedFixed>::frac_bits(),
frac_bits,
int_bits,
F::FRAC_NBITS,
<$Fixed<Frac>>::FRAC_NBITS,
<$Fixed<Frac>>::FRAC_NBITS,
);
if overflow {
return if val.to_bits().neg_abs().0 {
@ -870,15 +867,12 @@ assert_eq!(Fix::overflowing_from_fixed(large), (wrapped, true));
where
F: Fixed,
{
let frac_bits = Self::frac_bits();
let int_bits = Self::int_bits();
let (value, mut overflow) =
<<F as SealedFixed>::Bits as SealedInt>::to_fixed_overflow(
val.to_bits(),
<F as SealedFixed>::frac_bits(),
frac_bits,
int_bits,
F::FRAC_NBITS,
<$Fixed<Frac>>::FRAC_NBITS,
<$Fixed<Frac>>::INT_NBITS,
);
let bits = if_signed_unsigned!(
$Signedness,
@ -1145,11 +1139,12 @@ assert_eq!(Fix::saturating_from_int(too_small), Fix::min_value());
where
I: Int,
{
let frac_bits = Self::frac_bits();
let int_bits = Self::int_bits();
let (value, overflow) =
<I as SealedInt>::to_fixed_overflow(val, 0, frac_bits, int_bits);
let (value, overflow) = <I as SealedInt>::to_fixed_overflow(
val,
0,
<$Fixed<Frac>>::FRAC_NBITS,
<$Fixed<Frac>>::INT_NBITS,
);
if overflow {
return if val.neg_abs().0 {
$Fixed::min_value()
@ -1293,11 +1288,12 @@ assert_eq!(Fix::overflowing_from_int(large), (wrapped, true));
where
I: Int,
{
let frac_bits = Self::frac_bits();
let int_bits = Self::int_bits();
let (value, mut overflow) =
<I as SealedInt>::to_fixed_overflow(val, 0, frac_bits, int_bits);
let (value, mut overflow) = <I as SealedInt>::to_fixed_overflow(
val,
0,
<$Fixed<Frac>>::FRAC_NBITS,
<$Fixed<Frac>>::INT_NBITS,
);
let bits = if_signed_unsigned!(
$Signedness,
match value {
@ -1359,8 +1355,8 @@ assert_eq!((-two_half).to_int(), -3);",
#[inline]
pub fn to_int(self) -> $Inner {
let int = self.int().to_bits();
if Self::frac_bits() < $nbits {
int >> Self::frac_bits()
if <$Fixed<Frac>>::FRAC_NBITS < $nbits {
int >> <$Fixed<Frac>>::FRAC_NBITS
} else {
int
}
@ -1548,8 +1544,6 @@ assert_eq!(Fix::saturating_from_float(f64::NEG_INFINITY), Fix::min_value());
where
F: Float,
{
let frac_bits = Self::frac_bits();
let int_bits = Self::int_bits();
let saturated = if val.is_sign_positive() {
$Fixed::max_value()
} else {
@ -1558,19 +1552,22 @@ assert_eq!(Fix::saturating_from_float(f64::NEG_INFINITY), Fix::min_value());
if !val.is_finite() {
return saturated;
}
let (neg, abs_128, overflow) =
<F as SealedFloat>::to_fixed_neg_abs_overflow(val, frac_bits, int_bits);
let (neg, abs_128, overflow) = <F as SealedFloat>::to_fixed_neg_abs_overflow(
val,
<$Fixed<Frac>>::FRAC_NBITS,
<$Fixed<Frac>>::INT_NBITS,
);
if overflow {
return saturated;
}
let abs_bits =
abs_128 as <<$Fixed<Frac> as SealedFixed>::Bits as SealedInt>::Unsigned;
if <<$Fixed<Frac> as SealedFixed>::Bits as SealedInt>::is_signed() {
if <<$Fixed<Frac> as SealedFixed>::Bits as SealedInt>::IS_SIGNED {
// most significant bit (msb) can be one only for min value,
// that is for a negative value with only the msb true.
let msb =
<<$Fixed<Frac> as SealedFixed>::Bits as SealedInt>::Unsigned::msb();
<<$Fixed<Frac> as SealedFixed>::Bits as SealedInt>::Unsigned::MSB;
if abs_bits & msb != 0 {
if !neg || abs_bits != msb {
return saturated;
@ -1710,22 +1707,23 @@ assert_eq!(Fix::overflowing_from_float(large), (wrapped, true));
where
F: Float,
{
let frac_bits = Self::frac_bits();
let int_bits = Self::int_bits();
if !val.is_finite() {
panic!("{} is not finite", val);
}
let (neg, abs_128, mut overflow) =
<F as SealedFloat>::to_fixed_neg_abs_overflow(val, frac_bits, int_bits);
<F as SealedFloat>::to_fixed_neg_abs_overflow(
val,
<$Fixed<Frac>>::FRAC_NBITS,
<$Fixed<Frac>>::INT_NBITS,
);
let abs_bits =
abs_128 as <<$Fixed<Frac> as SealedFixed>::Bits as SealedInt>::Unsigned;
if <<$Fixed<Frac> as SealedFixed>::Bits as SealedInt>::is_signed() {
if <<$Fixed<Frac> as SealedFixed>::Bits as SealedInt>::IS_SIGNED {
// most significant bit (msb) can be one only for min value,
// that is for a negative value with only the msb true.
let msb =
<<$Fixed<Frac> as SealedFixed>::Bits as SealedInt>::Unsigned::msb();
<<$Fixed<Frac> as SealedFixed>::Bits as SealedInt>::Unsigned::MSB;
if abs_bits & msb != 0 {
if !neg || abs_bits != msb {
overflow = true;
@ -1782,10 +1780,13 @@ assert_eq!(Fix::from_bits(",
where
F: Float,
{
let frac_bits = Self::frac_bits();
let int_bits = Self::int_bits();
let (neg, abs) = self.to_bits().neg_abs();
SealedFloat::from_neg_abs(neg, u128::from(abs), frac_bits, int_bits)
SealedFloat::from_neg_abs(
neg,
u128::from(abs),
<$Fixed<Frac>>::FRAC_NBITS,
<$Fixed<Frac>>::INT_NBITS,
)
}
);

View File

@ -29,13 +29,18 @@ pub enum Widest {
}
pub trait SealedFixed: Copy + Debug + Display {
type FracNBits: Unsigned;
type Bits: SealedInt;
type Frac: Unsigned;
fn frac_bits() -> u32;
fn int_bits() -> u32 {
Self::Bits::nbits() - Self::frac_bits()
}
const FRAC_NBITS: u32 = Self::FracNBits::U32;
const INT_NBITS: u32 = Self::Bits::NBITS - Self::FRAC_NBITS;
const FRAC_MASK: u128 = !Self::INT_MASK;
// split shift in two parts in case that FRAC_NBITS == 128
const INT_MASK: u128 =
!0 << (Self::FRAC_NBITS / 2) << (Self::FRAC_NBITS - Self::FRAC_NBITS / 2);
const FRAC_HI: u128 = Self::FRAC_MASK ^ (Self::FRAC_MASK >> 1);
const INT_LO: u128 = Self::INT_MASK ^ (Self::INT_MASK << 1);
fn from_fixed<F>(fixed: F) -> Self
where
@ -43,20 +48,20 @@ pub trait SealedFixed: Copy + Debug + Display {
#[inline]
fn one() -> Option<Self> {
let min_int_bits = if Self::Bits::is_signed() { 2 } else { 1 };
if Self::int_bits() < min_int_bits {
let min_int_bits = if Self::Bits::IS_SIGNED { 2 } else { 1 };
if Self::INT_NBITS < min_int_bits {
None
} else {
Some(Self::from_bits(Self::Bits::one_shl(Self::frac_bits())))
Some(Self::from_bits(Self::Bits::one_shl(Self::FRAC_NBITS)))
}
}
#[inline]
fn minus_one() -> Option<Self> {
if !Self::Bits::is_signed() || Self::int_bits() < 1 {
if !Self::Bits::IS_SIGNED || Self::INT_NBITS < 1 {
None
} else {
Some(Self::from_bits(Self::Bits::all_ones_shl(Self::frac_bits())))
Some(Self::from_bits(Self::Bits::all_ones_shl(Self::FRAC_NBITS)))
}
}
@ -84,13 +89,8 @@ macro_rules! sealed_fixed {
where
Frac: Unsigned + IsLessOrEqual<$Len, Output = True>,
{
type FracNBits = Frac;
type Bits = $Bits;
type Frac = Frac;
#[inline]
fn frac_bits() -> u32 {
Frac::to_u32()
}
#[inline]
fn from_fixed<F>(fixed: F) -> Self
@ -102,34 +102,22 @@ macro_rules! sealed_fixed {
#[inline]
fn frac_mask() -> Self::Bits {
!Self::int_mask()
Self::FRAC_MASK as _
}
#[inline]
fn int_mask() -> Self::Bits {
if Self::int_bits() == 0 {
0
} else {
!0 << Self::frac_bits()
}
Self::INT_MASK as _
}
#[inline]
fn highest_frac_bit() -> Self::Bits {
if Self::frac_bits() == 0 {
0
} else {
1 << (Self::frac_bits() - 1)
}
Self::FRAC_HI as _
}
#[inline]
fn lowest_int_bit() -> Self::Bits {
if Self::int_bits() == 0 {
0
} else {
1 << Self::frac_bits()
}
Self::INT_LO as _
}
#[inline]
@ -150,8 +138,8 @@ macro_rules! sealed_fixed {
<Self::Bits as SealedInt>::Unsigned,
<Self::Bits as SealedInt>::Unsigned,
) {
let frac_bits = <Self as SealedFixed>::frac_bits();
let int_bits = <Self as SealedFixed>::int_bits();
let frac_bits = <Self as SealedFixed>::FRAC_NBITS;
let int_bits = <Self as SealedFixed>::INT_NBITS;
let (neg, abs) = SealedInt::neg_abs(self.to_bits());
let (int_abs, frac_abs) = if int_bits == 0 {

View File

@ -25,7 +25,7 @@ pub trait SealedFloat: Copy + Debug + Display {
#[inline]
fn exp_bias() -> i32 {
let nbits = Self::Bits::nbits();
let nbits = Self::Bits::NBITS;
let exp_bits = nbits - Self::prec();
(1 << (exp_bits - 1)) - 1
}
@ -64,7 +64,7 @@ macro_rules! sealed_float {
#[inline]
fn zero(neg: bool) -> $Float {
let nbits = <Self::Bits as SealedInt>::nbits();
let nbits = <Self::Bits as SealedInt>::NBITS;
let neg_mask = !0 << (nbits - 1);
let neg_bits = if neg { neg_mask } else { 0 };
<$Float>::from_bits(neg_bits)
@ -72,7 +72,7 @@ macro_rules! sealed_float {
#[inline]
fn infinity(neg: bool) -> $Float {
let nbits = <Self::Bits as SealedInt>::nbits();
let nbits = <Self::Bits as SealedInt>::NBITS;
let neg_mask = !0 << (nbits - 1);
let mant_mask = !(!0 << ($prec - 1));
let exp_mask = !(neg_mask | mant_mask);
@ -93,7 +93,7 @@ macro_rules! sealed_float {
#[inline]
fn parts(self) -> (bool, i32, $Bits) {
let nbits = <Self::Bits as SealedInt>::nbits();
let nbits = <Self::Bits as SealedInt>::NBITS;
let neg_mask = !0 << (nbits - 1);
let mant_mask = !(!0 << ($prec - 1));
let exp_mask = !(neg_mask | mant_mask);
@ -175,7 +175,7 @@ macro_rules! sealed_float {
frac_bits: u32,
int_bits: u32,
) -> (bool, u128, bool) {
let float_bits = Self::Bits::nbits() as i32;
let float_bits = Self::Bits::NBITS as i32;
let prec = Self::prec() as i32;
let fix_bits = (frac_bits + int_bits) as i32;

View File

@ -14,13 +14,18 @@
// <https://opensource.org/licenses/MIT>.
use core::fmt::{Debug, Display};
use frac::{Bit, False, True, Unsigned, U1, U128, U16, U32, U64, U8};
use sealed_fixed::Widest;
pub trait SealedInt: Copy + Ord + Debug + Display {
type NBits: Unsigned;
type IsSigned: Bit;
type Unsigned: SealedInt;
fn is_signed() -> bool;
fn nbits() -> u32;
const NBITS: u32 = Self::NBits::U32;
const IS_SIGNED: bool = Self::IsSigned::BOOL;
const MSB: Self;
fn one_shl(shift: u32) -> Self;
fn all_ones_shl(shift: u32) -> Self;
fn is_zero(self) -> bool;
@ -34,27 +39,16 @@ pub trait SealedInt: Copy + Ord + Debug + Display {
fn neg_abs(self) -> (bool, Self::Unsigned);
fn from_neg_abs(neg: bool, abs: Self::Unsigned) -> Self;
#[inline]
fn msb() -> Self {
Self::one_shl(Self::nbits() - 1)
}
}
macro_rules! sealed_int {
($Int:ident($Unsigned:ty, $is_signed:ident, $nbits:expr); $($rest:tt)*) => {
($Int:ident($NBits:ident, $IsSigned:ident, $Unsigned:ty); $($rest:tt)*) => {
impl SealedInt for $Int {
type NBits = $NBits;
type IsSigned = $IsSigned;
type Unsigned = $Unsigned;
#[inline]
fn is_signed() -> bool {
$is_signed
}
#[inline]
fn nbits() -> u32 {
$nbits
}
const MSB: $Int = 1 << (Self::NBITS - 1);
#[inline]
fn one_shl(shift: u32) -> $Int {
@ -74,9 +68,9 @@ macro_rules! sealed_int {
$($rest)*
}
};
($Int:ident($Unsigned:ty, false, $nbits:expr)) => {
($Unsigned:ident($NBits:ident)) => {
sealed_int! {
$Int($Unsigned, false, $nbits);
$Unsigned($NBits, False, $Unsigned);
#[inline]
fn neg_abs(self) -> (bool, Self::Unsigned) {
@ -97,7 +91,7 @@ macro_rules! sealed_int {
dst_frac_bits: u32,
dst_int_bits: u32,
) -> (Widest, bool) {
let src_bits = <Self as SealedInt>::nbits() as i32;
let src_bits = <Self as SealedInt>::NBITS as i32;
let dst_bits = (dst_frac_bits + dst_int_bits) as i32;
if self == 0 {
@ -122,9 +116,9 @@ macro_rules! sealed_int {
}
}
};
($Int:ident($Unsigned:ty, true, $nbits:expr)) => {
($Signed:ident($NBits:ident, $Unsigned:ty)) => {
sealed_int! {
$Int($Unsigned, true, $nbits);
$Signed($NBits, True, $Unsigned);
#[inline]
fn neg_abs(self) -> (bool, Self::Unsigned) {
@ -137,7 +131,7 @@ macro_rules! sealed_int {
#[inline]
fn from_neg_abs(neg: bool, abs: Self::Unsigned) -> Self {
debug_assert!(abs <= Self::Unsigned::msb());
debug_assert!(abs <= Self::Unsigned::MSB);
if neg {
abs.wrapping_neg() as Self
} else {
@ -152,7 +146,7 @@ macro_rules! sealed_int {
dst_frac_bits: u32,
dst_int_bits: u32,
) -> (Widest, bool) {
let src_bits = <Self as SealedInt>::nbits() as i32;
let src_bits = <Self as SealedInt>::NBITS as i32;
let dst_bits = (dst_frac_bits + dst_int_bits) as i32;
if self >= 0 {
@ -185,17 +179,11 @@ macro_rules! sealed_int {
}
impl SealedInt for bool {
type NBits = U1;
type IsSigned = False;
type Unsigned = bool;
#[inline]
fn is_signed() -> bool {
false
}
#[inline]
fn nbits() -> u32 {
1
}
const MSB: bool = true;
#[inline]
fn one_shl(shift: u32) -> bool {
@ -252,13 +240,13 @@ impl SealedInt for bool {
}
}
sealed_int! { i8(u8, true, 8) }
sealed_int! { i16(u16, true, 16) }
sealed_int! { i32(u32, true, 32) }
sealed_int! { i64(u64, true, 64) }
sealed_int! { i128(u128, true, 128) }
sealed_int! { u8(u8, false, 8) }
sealed_int! { u16(u16, false, 16) }
sealed_int! { u32(u32, false, 32) }
sealed_int! { u64(u64, false, 64) }
sealed_int! { u128(u128, false, 128) }
sealed_int! { i8(U8, u8) }
sealed_int! { i16(U16, u16) }
sealed_int! { i32(U32, u32) }
sealed_int! { i64(U64, u64) }
sealed_int! { i128(U128, u128) }
sealed_int! { u8(U8) }
sealed_int! { u16(U16) }
sealed_int! { u32(U32) }
sealed_int! { u64(U64) }
sealed_int! { u128(U128) }