provide From<Fixed*> for {f32,f64} when lossless
This commit is contained in:
parent
26f760d5ca
commit
7eb5e65100
|
@ -21,7 +21,6 @@ use core::mem;
|
||||||
use core::str;
|
use core::str;
|
||||||
use frac::Unsigned;
|
use frac::Unsigned;
|
||||||
use FixedHelper;
|
use FixedHelper;
|
||||||
|
|
||||||
use {
|
use {
|
||||||
FixedI128, FixedI16, FixedI32, FixedI64, FixedI8, FixedU128, FixedU16, FixedU32, FixedU64,
|
FixedI128, FixedI16, FixedI32, FixedI64, FixedI8, FixedU128, FixedU16, FixedU32, FixedU64,
|
||||||
FixedU8,
|
FixedU8,
|
||||||
|
@ -74,11 +73,11 @@ trait FmtRadix2Helper {
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! fmt_radix2_helper {
|
macro_rules! fmt_radix2_helper {
|
||||||
($($Inner:ty)*) => { $(
|
($($UInner:ty)*) => { $(
|
||||||
impl FmtRadix2Helper for $Inner {
|
impl FmtRadix2Helper for $UInner {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn int_frac_bits() -> u32 {
|
fn int_frac_bits() -> u32 {
|
||||||
mem::size_of::<$Inner>() as u32 * 8
|
mem::size_of::<$UInner>() as u32 * 8
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -96,7 +95,7 @@ macro_rules! fmt_radix2_helper {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn take_frac_digit(&mut self, digit_bits: u32) -> u8 {
|
fn take_frac_digit(&mut self, digit_bits: u32) -> u8 {
|
||||||
let int_frac_bits = <$Inner as FmtRadix2Helper>::int_frac_bits();
|
let int_frac_bits = <$UInner as FmtRadix2Helper>::int_frac_bits();
|
||||||
let rem_bits = int_frac_bits - digit_bits;
|
let rem_bits = int_frac_bits - digit_bits;
|
||||||
let mask = !0 << rem_bits;
|
let mask = !0 << rem_bits;
|
||||||
let ret = ((*self & mask) >> rem_bits) as u8;
|
let ret = ((*self & mask) >> rem_bits) as u8;
|
||||||
|
@ -158,14 +157,14 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn fmt_radix2<Frac: Unsigned, F, Inner>(
|
fn fmt_radix2<Frac: Unsigned, F, UInner>(
|
||||||
num: F,
|
num: F,
|
||||||
radix: &dyn Radix2,
|
radix: &dyn Radix2,
|
||||||
fmt: &mut Formatter,
|
fmt: &mut Formatter,
|
||||||
) -> FmtResult
|
) -> FmtResult
|
||||||
where
|
where
|
||||||
F: FixedHelper<Frac, Inner = Inner>,
|
F: FixedHelper<Frac, UInner = UInner>,
|
||||||
Inner: FmtRadix2Helper,
|
UInner: FmtRadix2Helper,
|
||||||
{
|
{
|
||||||
fmt_radix2_helper(Frac::to_u32(), num.parts(), radix, fmt)
|
fmt_radix2_helper(Frac::to_u32(), num.parts(), radix, fmt)
|
||||||
}
|
}
|
||||||
|
@ -272,11 +271,11 @@ trait FmtDecHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! fmt_dec_helper {
|
macro_rules! fmt_dec_helper {
|
||||||
($($Inner:ty)*) => { $(
|
($($UInner:ty)*) => { $(
|
||||||
impl FmtDecHelper for $Inner {
|
impl FmtDecHelper for $UInner {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn int_frac_bits() -> u32 {
|
fn int_frac_bits() -> u32 {
|
||||||
mem::size_of::<$Inner>() as u32 * 8
|
mem::size_of::<$UInner>() as u32 * 8
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -398,10 +397,10 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn fmt_dec<Frac: Unsigned, F, Inner>(num: F, fmt: &mut Formatter) -> FmtResult
|
fn fmt_dec<Frac: Unsigned, F, UInner>(num: F, fmt: &mut Formatter) -> FmtResult
|
||||||
where
|
where
|
||||||
F: FixedHelper<Frac, Inner = Inner>,
|
F: FixedHelper<Frac, UInner = UInner>,
|
||||||
Inner: FmtDecHelper,
|
UInner: FmtDecHelper,
|
||||||
{
|
{
|
||||||
fmt_dec_helper(Frac::to_u32(), num.parts(), fmt)
|
fmt_dec_helper(Frac::to_u32(), num.parts(), fmt)
|
||||||
}
|
}
|
||||||
|
|
24
src/flt.rs
24
src/flt.rs
|
@ -14,7 +14,9 @@
|
||||||
// <https://opensource.org/licenses/MIT>.
|
// <https://opensource.org/licenses/MIT>.
|
||||||
|
|
||||||
use core::mem;
|
use core::mem;
|
||||||
|
use frac::Unsigned;
|
||||||
use helper::FloatHelper;
|
use helper::FloatHelper;
|
||||||
|
use {FixedI16, FixedI32, FixedI8, FixedU16, FixedU32, FixedU8};
|
||||||
|
|
||||||
macro_rules! to_f {
|
macro_rules! to_f {
|
||||||
(fn $method:ident($Uns:ty) -> $Flt:ty) => {
|
(fn $method:ident($Uns:ty) -> $Flt:ty) => {
|
||||||
|
@ -99,3 +101,25 @@ macro_rules! flt_conv {
|
||||||
)* };
|
)* };
|
||||||
}
|
}
|
||||||
flt_conv! { u8 u16 u32 u64 u128 }
|
flt_conv! { u8 u16 u32 u64 u128 }
|
||||||
|
|
||||||
|
macro_rules! lossless {
|
||||||
|
($Fixed:ident:: $method:ident -> $Flt:ident) => {
|
||||||
|
impl<Frac: Unsigned> From<$Fixed<Frac>> for $Flt {
|
||||||
|
#[inline]
|
||||||
|
fn from(src: $Fixed<Frac>) -> $Flt {
|
||||||
|
src.$method()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
lossless! { FixedI8::to_f32 -> f32 }
|
||||||
|
lossless! { FixedI16::to_f32 -> f32 }
|
||||||
|
lossless! { FixedU8::to_f32 -> f32 }
|
||||||
|
lossless! { FixedU16::to_f32 -> f32 }
|
||||||
|
lossless! { FixedI8::to_f64 -> f64 }
|
||||||
|
lossless! { FixedI16::to_f64 -> f64 }
|
||||||
|
lossless! { FixedI32::to_f64 -> f64 }
|
||||||
|
lossless! { FixedU8::to_f64 -> f64 }
|
||||||
|
lossless! { FixedU16::to_f64 -> f64 }
|
||||||
|
lossless! { FixedU32::to_f64 -> f64 }
|
||||||
|
|
|
@ -114,22 +114,23 @@ float_helper! { f32(u32, 24) }
|
||||||
float_helper! { f64(u64, 53) }
|
float_helper! { f64(u64, 53) }
|
||||||
|
|
||||||
pub(crate) trait FixedHelper<Frac: Unsigned>: Sized {
|
pub(crate) trait FixedHelper<Frac: Unsigned>: Sized {
|
||||||
type Inner;
|
type UInner;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn int_frac_bits() -> u32 {
|
fn int_frac_bits() -> u32 {
|
||||||
mem::size_of::<Self::Inner>() as u32 * 8
|
mem::size_of::<Self::UInner>() as u32 * 8
|
||||||
}
|
}
|
||||||
|
|
||||||
fn one() -> Option<Self>;
|
fn one() -> Option<Self>;
|
||||||
fn minus_one() -> Option<Self>;
|
fn minus_one() -> Option<Self>;
|
||||||
fn parts(self) -> (bool, Self::Inner, Self::Inner);
|
fn from_parts(neg: bool, int_abs: Self::UInner, frac_abs: Self::UInner) -> Self;
|
||||||
|
fn parts(self) -> (bool, Self::UInner, Self::UInner);
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! fixed_num_unsigned {
|
macro_rules! fixed_num_unsigned {
|
||||||
($Fixed:ident($Inner:ty)) => {
|
($Fixed:ident($UInner:ty)) => {
|
||||||
impl<Frac: Unsigned> FixedHelper<Frac> for $Fixed<Frac> {
|
impl<Frac: Unsigned> FixedHelper<Frac> for $Fixed<Frac> {
|
||||||
type Inner = $Inner;
|
type UInner = $UInner;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn one() -> Option<Self> {
|
fn one() -> Option<Self> {
|
||||||
|
@ -148,10 +149,33 @@ macro_rules! fixed_num_unsigned {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn parts(self) -> (bool, $Inner, $Inner) {
|
fn from_parts(
|
||||||
let bits = self.to_bits();
|
neg: bool,
|
||||||
|
int_abs: Self::UInner,
|
||||||
|
frac_abs: Self::UInner,
|
||||||
|
) -> $Fixed<Frac> {
|
||||||
let int_bits = <$Fixed<Frac>>::int_bits();
|
let int_bits = <$Fixed<Frac>>::int_bits();
|
||||||
let frac_bits = <$Fixed<Frac>>::frac_bits();
|
let frac_bits = <$Fixed<Frac>>::frac_bits();
|
||||||
|
|
||||||
|
let _ = neg;
|
||||||
|
debug_assert!(!neg);
|
||||||
|
|
||||||
|
let int_frac = if int_bits == 0 {
|
||||||
|
frac_abs
|
||||||
|
} else if frac_bits == 0 {
|
||||||
|
int_abs
|
||||||
|
} else {
|
||||||
|
(int_abs << frac_bits) | (frac_abs >> int_bits)
|
||||||
|
};
|
||||||
|
$Fixed::from_bits(int_frac)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn parts(self) -> (bool, $UInner, $UInner) {
|
||||||
|
let int_bits = <$Fixed<Frac>>::int_bits();
|
||||||
|
let frac_bits = <$Fixed<Frac>>::frac_bits();
|
||||||
|
|
||||||
|
let bits = self.to_bits();
|
||||||
let int_part = if int_bits == 0 { 0 } else { bits >> frac_bits };
|
let int_part = if int_bits == 0 { 0 } else { bits >> frac_bits };
|
||||||
let frac_part = if frac_bits == 0 { 0 } else { bits << int_bits };
|
let frac_part = if frac_bits == 0 { 0 } else { bits << int_bits };
|
||||||
(false, int_part, frac_part)
|
(false, int_part, frac_part)
|
||||||
|
@ -161,9 +185,9 @@ macro_rules! fixed_num_unsigned {
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! fixed_num_signed {
|
macro_rules! fixed_num_signed {
|
||||||
($Fixed:ident($Inner:ty)) => {
|
($Fixed:ident($UInner:ty)) => {
|
||||||
impl<Frac: Unsigned> FixedHelper<Frac> for $Fixed<Frac> {
|
impl<Frac: Unsigned> FixedHelper<Frac> for $Fixed<Frac> {
|
||||||
type Inner = $Inner;
|
type UInner = $UInner;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn one() -> Option<Self> {
|
fn one() -> Option<Self> {
|
||||||
|
@ -188,13 +212,47 @@ macro_rules! fixed_num_signed {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn parts(self) -> (bool, $Inner, $Inner) {
|
fn from_parts(
|
||||||
let bits = self.to_bits().wrapping_abs() as $Inner;
|
neg: bool,
|
||||||
|
int_abs: Self::UInner,
|
||||||
|
frac_abs: Self::UInner,
|
||||||
|
) -> $Fixed<Frac> {
|
||||||
let int_bits = <$Fixed<Frac>>::int_bits();
|
let int_bits = <$Fixed<Frac>>::int_bits();
|
||||||
let frac_bits = <$Fixed<Frac>>::frac_bits();
|
let frac_bits = <$Fixed<Frac>>::frac_bits();
|
||||||
let int_part = if int_bits == 0 { 0 } else { bits >> frac_bits };
|
|
||||||
let frac_part = if frac_bits == 0 { 0 } else { bits << int_bits };
|
let int_frac_abs = if int_bits == 0 {
|
||||||
(self.to_bits() < 0, int_part, frac_part)
|
frac_abs
|
||||||
|
} else if frac_bits == 0 {
|
||||||
|
int_abs
|
||||||
|
} else {
|
||||||
|
(int_abs << frac_bits) | (frac_abs >> int_bits)
|
||||||
|
};
|
||||||
|
let int_frac = if neg {
|
||||||
|
int_frac_abs.wrapping_neg()
|
||||||
|
} else {
|
||||||
|
int_frac_abs
|
||||||
|
};
|
||||||
|
$Fixed::from_bits(int_frac as _)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn parts(self) -> (bool, $UInner, $UInner) {
|
||||||
|
let int_bits = <$Fixed<Frac>>::int_bits();
|
||||||
|
let frac_bits = <$Fixed<Frac>>::frac_bits();
|
||||||
|
|
||||||
|
let (neg, abs) = if self.to_bits() < 0 {
|
||||||
|
(true, self.to_bits().wrapping_neg() as $UInner)
|
||||||
|
} else {
|
||||||
|
(false, self.to_bits() as $UInner)
|
||||||
|
};
|
||||||
|
let (int_abs, frac_abs) = if int_bits == 0 {
|
||||||
|
(0, abs)
|
||||||
|
} else if frac_bits == 0 {
|
||||||
|
(abs, 0)
|
||||||
|
} else {
|
||||||
|
((abs >> frac_bits), (abs << int_bits))
|
||||||
|
};
|
||||||
|
(neg, int_abs, frac_abs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue