implement infallible fixed to primitive conversions

This commit is contained in:
Trevor Spiteri 2019-01-26 21:16:20 +01:00
parent 266f2910ce
commit b71b41cd70
4 changed files with 103 additions and 16 deletions

View File

@ -33,8 +33,17 @@ fixed-point number lies in the range 0.5 ≤ *x* < 0.5 for signed
fixed-point numbers, and in the range 0 ≤ *x* < 1 for unsigned
fixed-point numbers.
All lossless infallible conversions between fixed-point numbers and
integer primitives are implemented. That is, you can use [`From`] or
[`Into`] for the conversions that always work without losing any bits.
## Whats new
### Version 0.1.5 (unreleased)
* Lossless infallible conversions between fixed-point numbers and
integer primitives are now supported using [`From`] and [`Into`].
### Version 0.1.4 news (2018-11-29)
* Division is now implemented for [`FixedI128`] and [`FixedU128`].
@ -129,5 +138,7 @@ additional terms or conditions.
[`FixedU32`]: https://docs.rs/fixed/0.1.4/fixed/struct.FixedU32.html
[`FixedU64`]: https://docs.rs/fixed/0.1.4/fixed/struct.FixedU64.html
[`FixedU8`]: https://docs.rs/fixed/0.1.4/fixed/struct.FixedU8.html
[`From`]: https://doc.rust-lang.org/nightly/std/convert/trait.From.html
[`Into`]: https://doc.rust-lang.org/nightly/std/convert/trait.Into.html
[`f16`]: https://docs.rs/half/^1/half/struct.f16.html
[const generics]: https://github.com/rust-lang/rust/issues/44580

View File

@ -5,6 +5,12 @@ modification, are permitted in any medium without royalty provided the
copyright notice and this notice are preserved. This file is offered
as-is, without any warranty. -->
Version 0.1.5 (unreleased)
==========================
* Lossless infallible conversions between fixed-point numbers and
integer primitives are now supported using `From` and `Into`.
Version 0.1.4 (2018-11-29)
==========================

View File

@ -101,7 +101,7 @@ convert! { (FixedU32, FixedI32, U32) -> (FixedU128, FixedI128, U128) }
convert! { (FixedU64, FixedI64, U64) -> (FixedU128, FixedI128, U128) }
macro_rules! prim_convert {
macro_rules! prim_to_fixed {
(($SrcU:ident, $SrcI:ident, $SrcBits:ident) -> ($DstU:ident, $DstI:ident, $DstBits:ident)) => {
// Condition: FracDst <= $DstBits - $SrcBits
impl<FracDst> From<$SrcU> for $DstU<FracDst>
@ -169,25 +169,85 @@ macro_rules! prim_convert {
};
}
prim_convert! { (u8, i8) -> (FixedU8, FixedI8) }
prim_convert! { (u8, i8, U8) -> (FixedU16, FixedI16, U16) }
prim_convert! { (u8, i8, U8) -> (FixedU32, FixedI32, U32) }
prim_convert! { (u8, i8, U8) -> (FixedU64, FixedI64, U64) }
prim_convert! { (u8, i8, U8) -> (FixedU128, FixedI128, U128) }
prim_to_fixed! { (u8, i8) -> (FixedU8, FixedI8) }
prim_to_fixed! { (u8, i8, U8) -> (FixedU16, FixedI16, U16) }
prim_to_fixed! { (u8, i8, U8) -> (FixedU32, FixedI32, U32) }
prim_to_fixed! { (u8, i8, U8) -> (FixedU64, FixedI64, U64) }
prim_to_fixed! { (u8, i8, U8) -> (FixedU128, FixedI128, U128) }
prim_convert! { (u16, i16) -> (FixedU16, FixedI16) }
prim_convert! { (u16, i16, U16) -> (FixedU32, FixedI32, U32) }
prim_convert! { (u16, i16, U16) -> (FixedU64, FixedI64, U64) }
prim_convert! { (u16, i16, U16) -> (FixedU128, FixedI128, U128) }
prim_to_fixed! { (u16, i16) -> (FixedU16, FixedI16) }
prim_to_fixed! { (u16, i16, U16) -> (FixedU32, FixedI32, U32) }
prim_to_fixed! { (u16, i16, U16) -> (FixedU64, FixedI64, U64) }
prim_to_fixed! { (u16, i16, U16) -> (FixedU128, FixedI128, U128) }
prim_convert! { (u32, i32) -> (FixedU32, FixedI32) }
prim_convert! { (u32, i32, U32) -> (FixedU64, FixedI64, U64) }
prim_convert! { (u32, i32, U32) -> (FixedU128, FixedI128, U128) }
prim_to_fixed! { (u32, i32) -> (FixedU32, FixedI32) }
prim_to_fixed! { (u32, i32, U32) -> (FixedU64, FixedI64, U64) }
prim_to_fixed! { (u32, i32, U32) -> (FixedU128, FixedI128, U128) }
prim_convert! { (u64, i64) -> (FixedU64, FixedI64) }
prim_convert! { (u64, i64, U64) -> (FixedU128, FixedI128, U128) }
prim_to_fixed! { (u64, i64) -> (FixedU64, FixedI64) }
prim_to_fixed! { (u64, i64, U64) -> (FixedU128, FixedI128, U128) }
prim_convert! { (u128, i128) -> (FixedU128, FixedI128) }
prim_to_fixed! { (u128, i128) -> (FixedU128, FixedI128) }
macro_rules! fixed_to_prim {
(($SrcU:ident, $SrcI:ident) -> ($DstU:ident, $DstI:ident)) => {
impl From<$SrcU<U0>> for $DstU {
#[inline]
fn from(src: $SrcU<U0>) -> $DstU {
src.to_bits()
}
}
impl From<$SrcI<U0>> for $DstI {
#[inline]
fn from(src: $SrcI<U0>) -> $DstI {
src.to_bits()
}
}
};
(($SrcU:ident, $SrcI:ident) -> wider ($DstU:ident, $DstI:ident)) => {
impl From<$SrcU<U0>> for $DstU {
#[inline]
fn from(src: $SrcU<U0>) -> $DstU {
src.to_bits().into()
}
}
impl From<$SrcI<U0>> for $DstI {
#[inline]
fn from(src: $SrcI<U0>) -> $DstI {
src.to_bits().into()
}
}
impl From<$SrcU<U0>> for $DstI {
#[inline]
fn from(src: $SrcU<U0>) -> $DstI {
src.to_bits().into()
}
}
};
}
fixed_to_prim! { (FixedU8, FixedI8) -> (u8, i8) }
fixed_to_prim! { (FixedU8, FixedI8) -> wider (u16, i16) }
fixed_to_prim! { (FixedU8, FixedI8) -> wider (u32, i32) }
fixed_to_prim! { (FixedU8, FixedI8) -> wider (u64, i64) }
fixed_to_prim! { (FixedU8, FixedI8) -> wider (u128, i128) }
fixed_to_prim! { (FixedU16, FixedI16) -> (u16, i16) }
fixed_to_prim! { (FixedU16, FixedI16) -> wider (u32, i32) }
fixed_to_prim! { (FixedU16, FixedI16) -> wider (u64, i64) }
fixed_to_prim! { (FixedU16, FixedI16) -> wider (u128, i128) }
fixed_to_prim! { (FixedU32, FixedI32) -> (u32, i32) }
fixed_to_prim! { (FixedU32, FixedI32) -> wider (u64, i64) }
fixed_to_prim! { (FixedU32, FixedI32) -> wider (u128, i128) }
fixed_to_prim! { (FixedU64, FixedI64) -> (u64, i64) }
fixed_to_prim! { (FixedU64, FixedI64) -> wider (u128, i128) }
fixed_to_prim! { (FixedU128, FixedI128) -> (u128, i128) }
#[cfg(test)]
mod tests {
@ -214,6 +274,7 @@ mod tests {
let l = L8::from_bits(val);
assert_eq!(l, L8::from(val));
assert_eq!(val, u8::from(l));
assert_eq!(LL16::from(l), LL16::from_bits(val16));
assert_eq!(LH16::from(l), LH16::from_bits(val16 << 8));
assert_eq!(LL128::from(l), LL128::from_bits(val128));
@ -248,6 +309,7 @@ mod tests {
let l = L8::from_bits(val);
assert_eq!(l, L8::from(val));
assert_eq!(val, i8::from(l));
assert_eq!(LL16::from(l), LL16::from_bits(val16));
assert_eq!(LH16::from(l), LH16::from_bits(val16 << 8));
assert_eq!(LL128::from(l), LL128::from_bits(val128));
@ -282,6 +344,7 @@ mod tests {
let l = L8::from_bits(val);
assert_eq!(l, L8::from(val));
assert_eq!(val, u8::from(l));
assert_eq!(LL16::from(l), LL16::from_bits(val16));
assert_eq!(LH16::from(l), LH16::from_bits(val16 << 7));
assert_eq!(LL128::from(l), LL128::from_bits(val128));

View File

@ -42,6 +42,10 @@ fixed-point number lies in the range 0.5 ≤ *x* < 0.5 for signed
fixed-point numbers, and in the range 0 *x* < 1 for unsigned
fixed-point numbers.
All lossless infallible conversions between fixed-point numbers and
integer primitives are implemented. That is, you can use [`From`] or
[`Into`] for the conversions that always work without losing any bits.
## Quick example
```rust
@ -117,6 +121,7 @@ additional terms or conditions.
[LICENSE-APACHE]: https://www.apache.org/licenses/LICENSE-2.0
[LICENSE-MIT]: https://opensource.org/licenses/MIT
[`FixedI128`]: struct.FixedI128.html
[`FixedI128`]: struct.FixedI128.html
[`FixedI16`]: struct.FixedI16.html
[`FixedI32`]: struct.FixedI32.html
[`FixedI64`]: struct.FixedI64.html
@ -126,6 +131,8 @@ additional terms or conditions.
[`FixedU32`]: struct.FixedU32.html
[`FixedU64`]: struct.FixedU64.html
[`FixedU8`]: struct.FixedU8.html
[`From`]: https://doc.rust-lang.org/nightly/std/convert/trait.From.html
[`Into`]: https://doc.rust-lang.org/nightly/std/convert/trait.Into.html
[`f16`]: https://docs.rs/half/^1/half/struct.f16.html
[const generics]: https://github.com/rust-lang/rust/issues/44580
*/