add f16 feature

This commit is contained in:
Trevor Spiteri 2018-08-23 13:12:32 +02:00
parent f7b4242102
commit 932caf3f92
6 changed files with 325 additions and 13 deletions

View File

@ -17,5 +17,15 @@ keywords = ["mathematics", "numerics"]
categories = ["algorithms", "data-structures", "no-std", "science"] categories = ["algorithms", "data-structures", "no-std", "science"]
license = "MIT/Apache-2.0" license = "MIT/Apache-2.0"
[features]
f16 = ["half"]
[dependencies] [dependencies]
typenum = "1.8" typenum = "1.8"
[dependencies.half]
version = "1"
optional = true
[package.metadata.docs.rs]
features = ["f16"]

View File

@ -35,6 +35,14 @@ fixed-point numbers.
## Whats new ## Whats new
### Version 0.1.3 news (unreleased)
* The `f16` feature was added with its methods [`from_f16`] and
[`to_f16`].
[`from_f16`]: https://docs.rs/fixed/0.1.3/fixed/struct.FixedI32.html#method.from_f16
[`to_f16`]: https://docs.rs/fixed/0.1.3/fixed/struct.FixedI32.html#method.to_f16
### Version 0.1.2 news (2018-08-15) ### Version 0.1.2 news (2018-08-15)
* The crate can now be used without the standard library `std`. * The crate can now be used without the standard library `std`.
@ -108,6 +116,22 @@ extern crate fixed;
The *fixed* crate requires rustc version 1.28.0 or later. The *fixed* crate requires rustc version 1.28.0 or later.
## Optional features
The *fixed* crate has one optional feature:
1. `f16`, disabled by default. This provides conversion to/from
[`f16`]. This features requires the [*half* crate].
To enable the feature, you can add the dependency like this to
[*Cargo.toml*]:
```toml
[dependencies.fixed]
version = "0.1.2"
features = ["f16"]
```
## License ## License
This crate is free software: you can redistribute it and/or modify it This crate is free software: you can redistribute it and/or modify it
@ -127,6 +151,7 @@ additional terms or conditions.
[*Cargo.toml*]: https://doc.rust-lang.org/cargo/guide/dependencies.html [*Cargo.toml*]: https://doc.rust-lang.org/cargo/guide/dependencies.html
[*fixed* crate]: https://crates.io/crates/fixed [*fixed* crate]: https://crates.io/crates/fixed
[*half* crate]: https://crates.io/crates/half
[*typenum* crate]: https://crates.io/crates/typenum [*typenum* crate]: https://crates.io/crates/typenum
[LICENSE-APACHE]: https://www.apache.org/licenses/LICENSE-2.0 [LICENSE-APACHE]: https://www.apache.org/licenses/LICENSE-2.0
[LICENSE-MIT]: https://opensource.org/licenses/MIT [LICENSE-MIT]: https://opensource.org/licenses/MIT
@ -140,5 +165,6 @@ additional terms or conditions.
[`FixedU32`]: https://docs.rs/fixed/0.1.2/fixed/struct.FixedU32.html [`FixedU32`]: https://docs.rs/fixed/0.1.2/fixed/struct.FixedU32.html
[`FixedU64`]: https://docs.rs/fixed/0.1.2/fixed/struct.FixedU64.html [`FixedU64`]: https://docs.rs/fixed/0.1.2/fixed/struct.FixedU64.html
[`FixedU8`]: https://docs.rs/fixed/0.1.2/fixed/struct.FixedU8.html [`FixedU8`]: https://docs.rs/fixed/0.1.2/fixed/struct.FixedU8.html
[`f16`]: https://docs.rs/half/^1/half/struct.f16.html
[channels]: https://doc.rust-lang.org/book/second-edition/appendix-07-nightly-rust.html [channels]: https://doc.rust-lang.org/book/second-edition/appendix-07-nightly-rust.html
[const generics]: https://github.com/rust-lang/rust/issues/44580 [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 copyright notice and this notice are preserved. This file is offered
as-is, without any warranty. --> as-is, without any warranty. -->
Version 0.1.3 news (unreleased)
==========================
* The `f16` feature was added with its methods `from_f16` and
`to_f16`.
Version 0.1.2 (2018-08-15) Version 0.1.2 (2018-08-15)
========================== ==========================

View File

@ -15,6 +15,8 @@
use core::mem; use core::mem;
use frac::{IsLessOrEqual, True, Unsigned, U16, U32, U8}; use frac::{IsLessOrEqual, True, Unsigned, U16, U32, U8};
#[cfg(feature = "f16")]
use half::f16;
use helper::FloatHelper; use helper::FloatHelper;
use {FixedI16, FixedI32, FixedI8, FixedU16, FixedU32, FixedU8}; use {FixedI16, FixedI32, FixedI8, FixedU16, FixedU32, FixedU8};
@ -149,8 +151,12 @@ macro_rules! to_float {
} }
pub(crate) trait FloatConv: Sized { pub(crate) trait FloatConv: Sized {
#[cfg(feature = "f16")]
fn from_f16(val: f16, frac_bits: u32) -> Option<(Self, bool)>;
fn from_f32(val: f32, frac_bits: u32) -> Option<(Self, bool)>; fn from_f32(val: f32, frac_bits: u32) -> Option<(Self, bool)>;
fn from_f64(val: f64, frac_bits: u32) -> Option<(Self, bool)>; fn from_f64(val: f64, frac_bits: u32) -> Option<(Self, bool)>;
#[cfg(feature = "f16")]
fn to_f16(self, neg: bool, frac_bits: u32) -> f16;
fn to_f32(self, neg: bool, frac_bits: u32) -> f32; fn to_f32(self, neg: bool, frac_bits: u32) -> f32;
fn to_f64(self, neg: bool, frac_bits: u32) -> f64; fn to_f64(self, neg: bool, frac_bits: u32) -> f64;
} }
@ -158,8 +164,12 @@ pub(crate) trait FloatConv: Sized {
macro_rules! float_conv { macro_rules! float_conv {
($($Uns:ty)*) => { $( ($($Uns:ty)*) => { $(
impl FloatConv for $Uns { impl FloatConv for $Uns {
#[cfg(feature = "f16")]
from_float! { fn from_f16(f16) -> $Uns }
from_float! { fn from_f32(f32) -> $Uns } from_float! { fn from_f32(f32) -> $Uns }
from_float! { fn from_f64(f64) -> $Uns } from_float! { fn from_f64(f64) -> $Uns }
#[cfg(feature = "f16")]
to_float! { fn to_f16($Uns) -> f16 }
to_float! { fn to_f32($Uns) -> f32 } to_float! { fn to_f32($Uns) -> f32 }
to_float! { fn to_f64($Uns) -> f64 } to_float! { fn to_f64($Uns) -> f64 }
} }
@ -181,6 +191,10 @@ macro_rules! lossless_from_fixed {
}; };
} }
#[cfg(feature = "f16")]
lossless_from_fixed! { FixedI8(U8)::to_f16 -> f16 }
#[cfg(feature = "f16")]
lossless_from_fixed! { FixedU8(U8)::to_f16 -> f16 }
lossless_from_fixed! { FixedI8(U8)::to_f32 -> f32 } lossless_from_fixed! { FixedI8(U8)::to_f32 -> f32 }
lossless_from_fixed! { FixedI16(U16)::to_f32 -> f32 } lossless_from_fixed! { FixedI16(U16)::to_f32 -> f32 }
lossless_from_fixed! { FixedU8(U8)::to_f32 -> f32 } lossless_from_fixed! { FixedU8(U8)::to_f32 -> f32 }
@ -278,6 +292,53 @@ mod tests {
assert!(Fix::from_f32(511.0 / 32.0).is_none()); assert!(Fix::from_f32(511.0 / 32.0).is_none());
} }
#[cfg(feature = "f16")]
#[test]
fn to_f16() {
use half::f16;
for u in 0x00..=0xff {
let fu = FixedU8::<frac::U7>::from_bits(u);
assert_eq!(fu.to_f16(), f16::from_f32(u as f32 / 128.0));
let i = u as i8;
let fi = FixedI8::<frac::U7>::from_bits(i);
assert_eq!(fi.to_f16(), f16::from_f32(i as f32 / 128.0));
for hi in &[
0u32,
0x0000_0100,
0x7fff_ff00,
0x8000_0000,
0x8100_0000,
0xffff_fe00,
0xffff_ff00,
] {
let uu = *hi | u as u32;
let fuu = FixedU32::<frac::U7>::from_bits(uu);
assert_eq!(fuu.to_f16(), f16::from_f32(uu as f32 / 128.0));
let ii = uu as i32;
let fii = FixedI32::<frac::U7>::from_bits(ii);
assert_eq!(fii.to_f16(), f16::from_f32(ii as f32 / 128.0));
}
for hi in &[
0u128,
0x0000_0000_0000_0000_0000_0000_0000_0100,
0x7fff_ffff_ffff_ffff_ffff_ffff_ffff_ff00,
0x8000_0000_0000_0000_0000_0000_0000_0000,
0x8100_0000_0000_0000_0000_0000_0000_0000,
0xffff_ffff_ffff_ffff_ffff_ffff_ffff_fe00,
0xffff_ffff_ffff_ffff_ffff_ffff_ffff_ff00,
] {
let uu = *hi | u as u128;
let fuu = FixedU128::<frac::U7>::from_bits(uu);
assert_eq!(fuu.to_f16(), f16::from_f64(uu as f64 / 128.0));
let ii = uu as i128;
let fii = FixedI128::<frac::U7>::from_bits(ii);
assert_eq!(fii.to_f16(), f16::from_f64(ii as f64 / 128.0));
}
}
}
#[test] #[test]
fn to_f32() { fn to_f32() {
for u in 0x00..=0xff { for u in 0x00..=0xff {

View File

@ -15,6 +15,8 @@
use core::mem; use core::mem;
use frac::{IsLessOrEqual, True, Unsigned, U128, U16, U32, U64, U8}; use frac::{IsLessOrEqual, True, Unsigned, U128, U16, U32, U64, U8};
#[cfg(feature = "f16")]
use half::f16;
use { use {
FixedI128, FixedI16, FixedI32, FixedI64, FixedI8, FixedU128, FixedU16, FixedU32, FixedU64, FixedI128, FixedI16, FixedI32, FixedI64, FixedI8, FixedU128, FixedU16, FixedU32, FixedU64,
FixedU8, FixedU8,
@ -35,7 +37,7 @@ pub(crate) trait FloatHelper {
} }
macro_rules! float_helper { macro_rules! float_helper {
($Float:ident($Bits:ty, $prec:expr)) => { ($Float:ident($Bits:ty, $prec:expr, $to_bits:ident)) => {
impl FloatHelper for $Float { impl FloatHelper for $Float {
type Bits = $Bits; type Bits = $Bits;
@ -98,7 +100,7 @@ macro_rules! float_helper {
let mant_mask = !(!0 << ($prec - 1)); let mant_mask = !(!0 << ($prec - 1));
let exp_mask = !(neg_mask | mant_mask); let exp_mask = !(neg_mask | mant_mask);
let bits = self.to_bits(); let bits = self.$to_bits();
let neg = bits & neg_mask != 0; let neg = bits & neg_mask != 0;
let biased_exp = (bits & exp_mask) >> ($prec - 1); let biased_exp = (bits & exp_mask) >> ($prec - 1);
let exp = (biased_exp as i32) - <$Float as FloatHelper>::exp_bias(); let exp = (biased_exp as i32) - <$Float as FloatHelper>::exp_bias();
@ -110,8 +112,10 @@ macro_rules! float_helper {
}; };
} }
float_helper! { f32(u32, 24) } #[cfg(feature = "f16")]
float_helper! { f64(u64, 53) } float_helper! { f16(u16, 11, as_bits) }
float_helper! { f32(u32, 24, to_bits) }
float_helper! { f64(u64, 53, to_bits) }
pub(crate) trait FixedHelper<Frac>: Sized pub(crate) trait FixedHelper<Frac>: Sized
where where

View File

@ -77,6 +77,22 @@ extern crate fixed;
The *fixed* crate requires rustc version 1.28.0 or later. The *fixed* crate requires rustc version 1.28.0 or later.
## Optional features
The *fixed* crate has one optional feature:
1. `f16`, disabled by default. This provides conversion to/from
[`f16`]. This features requires the [*half* crate].
To enable the feature, you can add the dependency like this to
[*Cargo.toml*]:
```toml
[dependencies.fixed]
version = "0.1.2"
features = ["f16"]
```
## License ## License
This crate is free software: you can redistribute it and/or modify it This crate is free software: you can redistribute it and/or modify it
@ -96,6 +112,7 @@ additional terms or conditions.
[*Cargo.toml*]: https://doc.rust-lang.org/cargo/guide/dependencies.html [*Cargo.toml*]: https://doc.rust-lang.org/cargo/guide/dependencies.html
[*fixed* crate]: https://crates.io/crates/fixed [*fixed* crate]: https://crates.io/crates/fixed
[*half* crate]: https://crates.io/crates/half
[*typenum* crate]: https://crates.io/crates/typenum [*typenum* crate]: https://crates.io/crates/typenum
[LICENSE-APACHE]: https://www.apache.org/licenses/LICENSE-2.0 [LICENSE-APACHE]: https://www.apache.org/licenses/LICENSE-2.0
[LICENSE-MIT]: https://opensource.org/licenses/MIT [LICENSE-MIT]: https://opensource.org/licenses/MIT
@ -109,6 +126,7 @@ additional terms or conditions.
[`FixedU32`]: struct.FixedU32.html [`FixedU32`]: struct.FixedU32.html
[`FixedU64`]: struct.FixedU64.html [`FixedU64`]: struct.FixedU64.html
[`FixedU8`]: struct.FixedU8.html [`FixedU8`]: struct.FixedU8.html
[`f16`]: https://docs.rs/half/^1/half/struct.f16.html
[channels]: https://doc.rust-lang.org/book/second-edition/appendix-07-nightly-rust.html [channels]: https://doc.rust-lang.org/book/second-edition/appendix-07-nightly-rust.html
[const generics]: https://github.com/rust-lang/rust/issues/44580 [const generics]: https://github.com/rust-lang/rust/issues/44580
*/ */
@ -118,6 +136,8 @@ additional terms or conditions.
#![doc(test(attr(deny(warnings))))] #![doc(test(attr(deny(warnings))))]
#![cfg_attr(nightly_repr_transparent, feature(repr_transparent))] #![cfg_attr(nightly_repr_transparent, feature(repr_transparent))]
#[cfg(feature = "f16")]
extern crate half;
extern crate typenum; extern crate typenum;
macro_rules! if_signed { macro_rules! if_signed {
@ -144,12 +164,12 @@ mod helper;
use arith::MulDivDir; use arith::MulDivDir;
use core::cmp::Ordering; use core::cmp::Ordering;
use core::f32;
use core::f64;
use core::hash::{Hash, Hasher}; use core::hash::{Hash, Hasher};
use core::marker::PhantomData; use core::marker::PhantomData;
use float::FloatConv; use float::FloatConv;
use frac::{IsLessOrEqual, True, Unsigned, U128, U16, U32, U64, U8}; use frac::{IsLessOrEqual, True, Unsigned, U128, U16, U32, U64, U8};
#[cfg(feature = "f16")]
use half::f16;
use helper::FixedHelper; use helper::FixedHelper;
macro_rules! pass_method { macro_rules! pass_method {
@ -208,13 +228,13 @@ macro_rules! doc_comment_signed_unsigned {
} }
macro_rules! from_float { macro_rules! from_float {
($Signedness:tt, fn $method:ident($Float:ident) -> $Fixed:ident < $Frac:ident >) => { ($Signedness:tt,fn $method:ident($Float:ident) -> $Fixed:ident < $Frac:ident >) => {
doc_comment_signed_unsigned! { doc_comment_signed_unsigned! {
$Signedness, $Signedness,
concat!( concat!(
"Creates a fixed-point number from `", stringify!($Float), "`.\n", "Creates a fixed-point number from `", stringify!($Float), "`.\n",
"\n", "\n",
"This method rounds to the nearest, with ties rounding to even.", "This method rounds to the nearest, with ties rounding to even.\n",
"\n", "\n",
"# Examples\n", "# Examples\n",
"\n", "\n",
@ -242,7 +262,7 @@ macro_rules! from_float {
concat!( concat!(
"Creates a fixed-point number from `", stringify!($Float), "`.\n", "Creates a fixed-point number from `", stringify!($Float), "`.\n",
"\n", "\n",
"This method rounds to the nearest, with ties rounding to even.", "This method rounds to the nearest, with ties rounding to even.\n",
"\n", "\n",
"# Examples\n", "# Examples\n",
"\n", "\n",
@ -299,13 +319,13 @@ macro_rules! from_float {
} }
macro_rules! to_float { macro_rules! to_float {
($Signedness:tt, fn $method:ident($Fixed:ident < $Frac:ident >) -> $Float:ident) => { ($Signedness:tt,fn $method:ident($Fixed:ident < $Frac:ident >) -> $Float:ident) => {
doc_comment_signed_unsigned! { doc_comment_signed_unsigned! {
$Signedness, $Signedness,
concat!( concat!(
"Converts the fixed-point number to `", stringify!($Float), "`.\n", "Converts the fixed-point number to `", stringify!($Float), "`.\n",
"\n", "\n",
"This method rounds to the nearest, with ties rounding to even.", "This method rounds to the nearest, with ties rounding to even.\n",
"\n", "\n",
"# Examples\n", "# Examples\n",
"\n", "\n",
@ -323,7 +343,7 @@ macro_rules! to_float {
concat!( concat!(
"Converts the fixed-point number to `", stringify!($Float), "`.\n", "Converts the fixed-point number to `", stringify!($Float), "`.\n",
"\n", "\n",
"This method rounds to the nearest, with ties rounding to even.", "This method rounds to the nearest, with ties rounding to even.\n",
"\n", "\n",
"# Examples\n", "# Examples\n",
"\n", "\n",
@ -354,8 +374,21 @@ macro_rules! to_float {
}; };
} }
#[cfg(feature = "f16")]
macro_rules! string_up_to_16 {
(U8, $s:expr) => {
$s
};
(U16, $s:expr) => {
$s
};
($other:tt, $s:expr) => {
""
};
}
macro_rules! fixed { macro_rules! fixed {
($description:expr, $Fixed:ident($Inner:ty, $Len:ty, $bits_count:expr), $Signedness:tt) => { ($description:expr, $Fixed:ident($Inner:ty, $Len:tt, $bits_count:expr), $Signedness:tt) => {
doc_comment! { doc_comment! {
concat!( concat!(
$description, $description,
@ -809,8 +842,180 @@ macro_rules! fixed {
} }
} }
#[cfg(feature = "f16")]
doc_comment_signed_unsigned! {
$Signedness,
concat!(
"Creates a fixed-point number from `f16`.\n",
"\n",
"This method rounds to the nearest, with ties rounding to even.\n",
"\n",
"This method is only available when the `f16` feature is enabled.\n",
"\n",
"# Examples\n",
"\n",
"```rust\n",
"extern crate fixed;\n",
"extern crate half;\n",
"use fixed::frac;\n",
"use fixed::", stringify!($Fixed), ";\n",
"use half::f16;\n",
"type Fix = ", stringify!($Fixed), "<frac::U4>;\n",
"// 1.75 is 0001.1100, that is from_bits(28)\n",
"let val = f16::from_f32(1.75);\n",
"let neg_val = f16::from_f32(-1.75);\n",
"assert_eq!(Fix::from_f16(val), Some(Fix::from_bits(28)));\n",
"assert_eq!(Fix::from_f16(neg_val), Some(Fix::from_bits(-28)));\n",
"// 1e-2 is too small for four fractional bits\n",
"let small = f16::from_f32(1e-2);\n",
"let neg_small = f16::from_f32(-1e-2);\n",
"assert_eq!(Fix::from_f16(small), Some(Fix::from_bits(0)));\n",
"assert_eq!(Fix::from_f16(neg_small), Some(Fix::from_bits(0)));\n",
string_up_to_16!(
$Len,
concat!(
"// 50000 is too large for ", stringify!($Fixed), "<frac::U4>\n",
"let large = f16::from_f32(50000.0);\n",
"let neg_large = f16::from_f32(-50000.0);\n",
"assert!(Fix::from_f16(large).is_none());\n",
"assert!(Fix::from_f16(neg_large).is_none());\n"
)
),
"```\n"
),
concat!(
"Creates a fixed-point number from `", stringify!($Float), "`.\n",
"\n",
"This method rounds to the nearest, with ties rounding to even.\n",
"\n",
"This method is only available when the `f16` feature is enabled.\n",
"\n",
"# Examples\n",
"\n",
"```rust\n",
"extern crate fixed;\n",
"extern crate half;\n",
"use fixed::frac;\n",
"use fixed::", stringify!($Fixed), ";\n",
"use half::f16;\n",
"type Fix = ", stringify!($Fixed), "<frac::U4>;\n",
"// 1.75 is 0001.1100, that is from_bits(28)\n",
"let val = f16::from_f32(1.75);\n",
"assert_eq!(Fix::from_f16(val), Some(Fix::from_bits(28)));\n",
"// 1e-2 is too small for four fractional bits\n",
"let small = f16::from_f32(1e-2);\n",
"assert_eq!(Fix::from_f16(small), Some(Fix::from_bits(0)));\n",
string_up_to_16!(
$Len,
concat!(
"// 50000 is too large for ", stringify!($Fixed), "<frac::U4>\n",
"let large = f16::from_f32(50000.0);\n",
"assert!(Fix::from_f16(large).is_none());\n",
)
),
"```\n"
),
#[inline]
pub fn from_f16(val: f16) -> Option<$Fixed<Frac>> {
let int_bits = Self::int_bits();
let frac_bits = Self::frac_bits();
let (int_frac, neg) = FloatConv::from_f16(val, frac_bits)?;
if <$Fixed<Frac> as FixedHelper<Frac>>::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 = 1 << (int_bits + frac_bits - 1);
if int_frac & msb != 0 {
if !neg || (int_frac & !msb) != 0 {
return None;
}
}
} else if neg {
if int_frac != 0 {
return None;
}
return Some($Fixed::from_bits(0));
}
let (int, frac) = if frac_bits == 0 {
(int_frac, 0)
} else if int_bits == 0 {
(0, int_frac)
} else {
((int_frac >> frac_bits), (int_frac << int_bits))
};
Some(FixedHelper::from_parts(neg, int, frac))
}
}
from_float! { $Signedness, fn from_f32(f32) -> $Fixed<Frac> } from_float! { $Signedness, fn from_f32(f32) -> $Fixed<Frac> }
from_float! { $Signedness, fn from_f64(f64) -> $Fixed<Frac> } from_float! { $Signedness, fn from_f64(f64) -> $Fixed<Frac> }
#[cfg(feature = "f16")]
doc_comment_signed_unsigned! {
$Signedness,
concat!(
"Converts the fixed-point number to `f16`.\n",
"\n",
"This method rounds to the nearest, with ties rounding to even.\n",
"\n",
"This method is only available when the `f16` feature is enabled.\n",
"\n",
"# Examples\n",
"\n",
"```rust\n",
"extern crate fixed;\n",
"extern crate half;\n",
"use fixed::frac;\n",
"use fixed::", stringify!($Fixed), ";\n",
"use half::f16;\n",
"type Fix = ", stringify!($Fixed), "<frac::U4>;\n",
"// 1.75 is 0001.1100, that is from_bits(28)\n",
"let val = f16::from_f32(1.75);\n",
"let neg_val = f16::from_f32(-1.75);\n",
"assert_eq!(Fix::from_bits(28).to_f16(), val);\n",
"assert_eq!(Fix::from_bits(-28).to_f16(), neg_val);\n",
"```\n"
),
concat!(
"Converts the fixed-point number to `f16`.\n",
"\n",
"This method rounds to the nearest, with ties rounding to even.\n",
"\n",
"This method is only available when the `f16` feature is enabled.\n",
"\n",
"# Examples\n",
"\n",
"```rust\n",
"extern crate fixed;\n",
"extern crate half;\n",
"use fixed::frac;\n",
"use fixed::", stringify!($Fixed), ";\n",
"use half::f16;\n",
"type Fix = ", stringify!($Fixed), "<frac::U4>;\n",
"// 1.75 is 0001.1100, that is from_bits(28)\n",
"let val = f16::from_f32(1.75);\n",
"assert_eq!(Fix::from_bits(28).to_f16(), val);\n",
"```\n"
),
#[inline]
pub fn to_f16(self) -> f16 {
let int_bits = Self::int_bits();
let frac_bits = Self::frac_bits();
let (neg, int, frac) = self.parts();
let int_frac = if frac_bits == 0 {
int
} else if int_bits == 0 {
frac
} else {
(int << frac_bits) | (frac >> int_bits)
};
FloatConv::to_f16(int_frac, neg, frac_bits)
}
}
to_float! { $Signedness, fn to_f32($Fixed<Frac>) -> f32 } to_float! { $Signedness, fn to_f32($Fixed<Frac>) -> f32 }
to_float! { $Signedness, fn to_f64($Fixed<Frac>) -> f64 } to_float! { $Signedness, fn to_f64($Fixed<Frac>) -> f64 }