Skip to content

Commit 20b84d0

Browse files
committed
add f16
1 parent fbdc29a commit 20b84d0

14 files changed

Lines changed: 453 additions & 52 deletions

File tree

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ features = ["std"]
2020
rustdoc-args = ["--generate-link-to-definition"]
2121

2222
[dependencies]
23-
libm = { version = "0.2.0", optional = true }
23+
libm = { version = "0.2.0", optional = true, features = ["unstable-float"] }
2424

2525
[features]
2626
default = ["std"]

build.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,8 @@ fn main() {
66
ac.emit_path_cfg("core::num::Saturating", "has_num_saturating"); // 1.74
77

88
autocfg::rerun_path("build.rs");
9+
10+
// FIXME: use autocfg to emit it
11+
println!("cargo:rustc-cfg=has_f16");
12+
println!("cargo:rustc-check-cfg=cfg(has_f16)");
913
}

src/bounds.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#[cfg(has_f16)]
2+
use core::f16;
13
use core::num::Wrapping;
24
use core::num::{
35
NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize, NonZeroU128,
@@ -124,7 +126,10 @@ impl<T: Bounded> Bounded for Wrapping<T> {
124126
}
125127
}
126128

129+
#[cfg(has_f16)]
130+
bounded_impl!(f16, f16::MIN, f16::MAX);
127131
bounded_impl!(f32, f32::MIN, f32::MAX);
132+
bounded_impl!(f64, f64::MIN, f64::MAX);
128133

129134
macro_rules! for_each_tuple_ {
130135
( $m:ident !! ) => (
@@ -157,7 +162,6 @@ macro_rules! bounded_tuple {
157162
}
158163

159164
for_each_tuple!(bounded_tuple);
160-
bounded_impl!(f64, f64::MIN, f64::MAX);
161165

162166
#[test]
163167
fn wrapping_bounded() {

src/cast.rs

Lines changed: 86 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#[cfg(has_f16)]
2+
use core::f16;
13
use core::mem::size_of;
24
use core::num::Wrapping;
35
use core::num::{
@@ -105,6 +107,15 @@ pub trait ToPrimitive {
105107
self.to_u64().map(From::from)
106108
}
107109

110+
/// Converts the value of `self` to an `f16`. Overflows may map to positive
111+
/// or negative inifinity, otherwise `None` is returned if the value cannot
112+
/// be represented by an `f16`.
113+
#[cfg(has_f16)]
114+
#[inline]
115+
fn to_f16(&self) -> Option<f16> {
116+
self.to_f64().as_ref().and_then(ToPrimitive::to_f16)
117+
}
118+
108119
/// Converts the value of `self` to an `f32`. Overflows may map to positive
109120
/// or negative inifinity, otherwise `None` is returned if the value cannot
110121
/// be represented by an `f32`.
@@ -130,8 +141,9 @@ pub trait ToPrimitive {
130141
}
131142

132143
macro_rules! impl_to_primitive_int_to_int {
133-
($SrcT:ident : $( fn $method:ident -> $DstT:ident ; )*) => {$(
144+
($SrcT:ident : $( $(#[$cfg:meta])* fn $method:ident -> $DstT:ident ; )*) => {$(
134145
#[inline]
146+
$(#[$cfg])*
135147
fn $method(&self) -> Option<$DstT> {
136148
let min = $DstT::MIN as $SrcT;
137149
let max = $DstT::MAX as $SrcT;
@@ -145,8 +157,9 @@ macro_rules! impl_to_primitive_int_to_int {
145157
}
146158

147159
macro_rules! impl_to_primitive_int_to_uint {
148-
($SrcT:ident : $( fn $method:ident -> $DstT:ident ; )*) => {$(
160+
($SrcT:ident : $( $(#[$cfg:meta])* fn $method:ident -> $DstT:ident ; )*) => {$(
149161
#[inline]
162+
$(#[$cfg])*
150163
fn $method(&self) -> Option<$DstT> {
151164
let max = $DstT::MAX as $SrcT;
152165
if 0 <= *self && (size_of::<$SrcT>() <= size_of::<$DstT>() || *self <= max) {
@@ -179,6 +192,11 @@ macro_rules! impl_to_primitive_int {
179192
fn to_u128 -> u128;
180193
}
181194

195+
#[cfg(has_f16)]
196+
#[inline]
197+
fn to_f16(&self) -> Option<f16> {
198+
Some(*self as f16)
199+
}
182200
#[inline]
183201
fn to_f32(&self) -> Option<f32> {
184202
Some(*self as f32)
@@ -199,8 +217,9 @@ impl_to_primitive_int!(i64);
199217
impl_to_primitive_int!(i128);
200218

201219
macro_rules! impl_to_primitive_uint_to_int {
202-
($SrcT:ident : $( fn $method:ident -> $DstT:ident ; )*) => {$(
220+
($SrcT:ident : $( $(#[$cfg:meta])* fn $method:ident -> $DstT:ident ; )*) => {$(
203221
#[inline]
222+
$(#[$cfg])*
204223
fn $method(&self) -> Option<$DstT> {
205224
let max = $DstT::MAX as $SrcT;
206225
if size_of::<$SrcT>() < size_of::<$DstT>() || *self <= max {
@@ -213,8 +232,9 @@ macro_rules! impl_to_primitive_uint_to_int {
213232
}
214233

215234
macro_rules! impl_to_primitive_uint_to_uint {
216-
($SrcT:ident : $( fn $method:ident -> $DstT:ident ; )*) => {$(
235+
($SrcT:ident : $( $(#[$cfg:meta])* fn $method:ident -> $DstT:ident ; )*) => {$(
217236
#[inline]
237+
$(#[$cfg])*
218238
fn $method(&self) -> Option<$DstT> {
219239
let max = $DstT::MAX as $SrcT;
220240
if size_of::<$SrcT>() <= size_of::<$DstT>() || *self <= max {
@@ -247,6 +267,11 @@ macro_rules! impl_to_primitive_uint {
247267
fn to_u128 -> u128;
248268
}
249269

270+
#[cfg(has_f16)]
271+
#[inline]
272+
fn to_f16(&self) -> Option<f16> {
273+
Some(*self as f16)
274+
}
250275
#[inline]
251276
fn to_f32(&self) -> Option<f32> {
252277
Some(*self as f32)
@@ -315,8 +340,9 @@ impl_to_primitive_nonzero!(NonZeroI64);
315340
impl_to_primitive_nonzero!(NonZeroI128);
316341

317342
macro_rules! impl_to_primitive_float_to_float {
318-
($SrcT:ident : $( fn $method:ident -> $DstT:ident ; )*) => {$(
343+
($SrcT:ident : $( $(#[$cfg:meta])* fn $method:ident -> $DstT:ident ; )*) => {$(
319344
#[inline]
345+
$(#[$cfg])*
320346
fn $method(&self) -> Option<$DstT> {
321347
// We can safely cast all values, whether NaN, +-inf, or finite.
322348
// Finite values that are reducing size may saturate to +-inf.
@@ -334,8 +360,9 @@ macro_rules! float_to_int_unchecked {
334360
}
335361

336362
macro_rules! impl_to_primitive_float_to_signed_int {
337-
($f:ident : $( fn $method:ident -> $i:ident ; )*) => {$(
363+
($f:ident : $( $(#[$cfg:meta])* fn $method:ident -> $i:ident ; )*) => {$(
338364
#[inline]
365+
$(#[$cfg])*
339366
fn $method(&self) -> Option<$i> {
340367
// Float as int truncates toward zero, so we want to allow values
341368
// in the exclusive range `(MIN-1, MAX+1)`.
@@ -363,8 +390,9 @@ macro_rules! impl_to_primitive_float_to_signed_int {
363390
}
364391

365392
macro_rules! impl_to_primitive_float_to_unsigned_int {
366-
($f:ident : $( fn $method:ident -> $u:ident ; )*) => {$(
393+
($f:ident : $( $(#[$cfg:meta])* fn $method:ident -> $u:ident ; )*) => {$(
367394
#[inline]
395+
$(#[$cfg])*
368396
fn $method(&self) -> Option<$u> {
369397
// Float as int truncates toward zero, so we want to allow values
370398
// in the exclusive range `(-1, MAX+1)`.
@@ -410,13 +438,17 @@ macro_rules! impl_to_primitive_float {
410438
}
411439

412440
impl_to_primitive_float_to_float! { $T:
441+
#[cfg(has_f16)]
442+
fn to_f16 -> f16;
413443
fn to_f32 -> f32;
414444
fn to_f64 -> f64;
415445
}
416446
}
417447
};
418448
}
419449

450+
#[cfg(has_f16)]
451+
impl_to_primitive_float!(f16);
420452
impl_to_primitive_float!(f32);
421453
impl_to_primitive_float!(f64);
422454

@@ -515,6 +547,14 @@ pub trait FromPrimitive: Sized {
515547
n.to_u64().and_then(FromPrimitive::from_u64)
516548
}
517549

550+
/// Converts a `f16` to return an optional value of this type. If the
551+
/// value cannot be represented by this type, then `None` is returned.
552+
#[cfg(has_f16)]
553+
#[inline]
554+
fn from_f16(n: f16) -> Option<Self> {
555+
FromPrimitive::from_f64(n as f64)
556+
}
557+
518558
/// Converts a `f32` to return an optional value of this type. If the
519559
/// value cannot be represented by this type, then `None` is returned.
520560
#[inline]
@@ -590,6 +630,11 @@ macro_rules! impl_from_primitive {
590630
n.$to_ty()
591631
}
592632

633+
#[cfg(has_f16)]
634+
#[inline]
635+
fn from_f16(n: f16) -> Option<$T> {
636+
n.$to_ty()
637+
}
593638
#[inline]
594639
fn from_f32(n: f32) -> Option<$T> {
595640
n.$to_ty()
@@ -614,6 +659,8 @@ impl_from_primitive!(u16, to_u16);
614659
impl_from_primitive!(u32, to_u32);
615660
impl_from_primitive!(u64, to_u64);
616661
impl_from_primitive!(u128, to_u128);
662+
#[cfg(has_f16)]
663+
impl_from_primitive!(f16, to_f16);
617664
impl_from_primitive!(f32, to_f32);
618665
impl_from_primitive!(f64, to_f64);
619666

@@ -696,8 +743,9 @@ impl_from_primitive_nonzero!(NonZeroU64, to_u64);
696743
impl_from_primitive_nonzero!(NonZeroU128, to_u128);
697744

698745
macro_rules! impl_to_primitive_wrapping {
699-
($( fn $method:ident -> $i:ident ; )*) => {$(
746+
($( $(#[$cfg:meta])* fn $method:ident -> $i:ident ; )*) => {$(
700747
#[inline]
748+
$(#[$cfg])*
701749
fn $method(&self) -> Option<$i> {
702750
(self.0).$method()
703751
}
@@ -720,14 +768,17 @@ impl<T: ToPrimitive> ToPrimitive for Wrapping<T> {
720768
fn to_u64 -> u64;
721769
fn to_u128 -> u128;
722770

771+
#[cfg(has_f16)]
772+
fn to_f16 -> f16;
723773
fn to_f32 -> f32;
724774
fn to_f64 -> f64;
725775
}
726776
}
727777

728778
macro_rules! impl_from_primitive_wrapping {
729-
($( fn $method:ident ( $i:ident ); )*) => {$(
779+
($( $(#[$cfg:meta])* fn $method:ident ( $i:ident ); )*) => {$(
730780
#[inline]
781+
$(#[$cfg])*
731782
fn $method(n: $i) -> Option<Self> {
732783
T::$method(n).map(Wrapping)
733784
}
@@ -750,6 +801,8 @@ impl<T: FromPrimitive> FromPrimitive for Wrapping<T> {
750801
fn from_u64(u64);
751802
fn from_u128(u128);
752803

804+
#[cfg(has_f16)]
805+
fn from_f16(f16);
753806
fn from_f32(f32);
754807
fn from_f64(f64);
755808
}
@@ -810,6 +863,8 @@ impl_num_cast!(i32, to_i32);
810863
impl_num_cast!(i64, to_i64);
811864
impl_num_cast!(i128, to_i128);
812865
impl_num_cast!(isize, to_isize);
866+
#[cfg(has_f16)]
867+
impl_num_cast!(f16, to_f16);
813868
impl_num_cast!(f32, to_f32);
814869
impl_num_cast!(f64, to_f64);
815870

@@ -879,34 +934,37 @@ where
879934
}
880935

881936
macro_rules! impl_as_primitive {
882-
(@ $T: ty => impl $U: ty ) => {
937+
(@ $T: ty => $(#[$cfg:meta])* impl $U: ty ) => {
938+
$(#[$cfg])*
883939
impl AsPrimitive<$U> for $T {
884940
#[inline] fn as_(self) -> $U { self as $U }
885941
}
886942
};
887-
(@ $T: ty => { $( $U: ty ),* } ) => {$(
888-
impl_as_primitive!(@ $T => impl $U);
943+
(@ $T: ty => { $( $(#[$cfg:meta])* $U: ty ),* } ) => {$(
944+
impl_as_primitive!(@ $T => $(#[$cfg])* impl $U);
889945
)*};
890-
($T: ty => { $( $U: ty ),* } ) => {
891-
impl_as_primitive!(@ $T => { $( $U ),* });
946+
($T: ty => { $( $(#[$cfg:meta])* $U: ty ),* } ) => {
947+
impl_as_primitive!(@ $T => { $( $(#[$cfg])* $U ),* });
892948
impl_as_primitive!(@ $T => { u8, u16, u32, u64, u128, usize });
893949
impl_as_primitive!(@ $T => { i8, i16, i32, i64, i128, isize });
894950
};
895951
}
896952

897-
impl_as_primitive!(u8 => { char, f32, f64 });
898-
impl_as_primitive!(i8 => { f32, f64 });
899-
impl_as_primitive!(u16 => { f32, f64 });
900-
impl_as_primitive!(i16 => { f32, f64 });
901-
impl_as_primitive!(u32 => { f32, f64 });
902-
impl_as_primitive!(i32 => { f32, f64 });
903-
impl_as_primitive!(u64 => { f32, f64 });
904-
impl_as_primitive!(i64 => { f32, f64 });
905-
impl_as_primitive!(u128 => { f32, f64 });
906-
impl_as_primitive!(i128 => { f32, f64 });
907-
impl_as_primitive!(usize => { f32, f64 });
908-
impl_as_primitive!(isize => { f32, f64 });
909-
impl_as_primitive!(f32 => { f32, f64 });
910-
impl_as_primitive!(f64 => { f32, f64 });
953+
impl_as_primitive!(u8 => { char, #[cfg(has_f16)] f16, f32, f64 });
954+
impl_as_primitive!(i8 => { #[cfg(has_f16)] f16, f32, f64 });
955+
impl_as_primitive!(u16 => { #[cfg(has_f16)] f16, f32, f64 });
956+
impl_as_primitive!(i16 => { #[cfg(has_f16)] f16, f32, f64 });
957+
impl_as_primitive!(u32 => { #[cfg(has_f16)] f16, f32, f64 });
958+
impl_as_primitive!(i32 => { #[cfg(has_f16)] f16, f32, f64 });
959+
impl_as_primitive!(u64 => { #[cfg(has_f16)] f16, f32, f64 });
960+
impl_as_primitive!(i64 => { #[cfg(has_f16)] f16, f32, f64 });
961+
impl_as_primitive!(u128 => { #[cfg(has_f16)] f16, f32, f64 });
962+
impl_as_primitive!(i128 => { #[cfg(has_f16)] f16, f32, f64 });
963+
impl_as_primitive!(usize => { #[cfg(has_f16)] f16, f32, f64 });
964+
impl_as_primitive!(isize => { #[cfg(has_f16)] f16, f32, f64 });
965+
#[cfg(has_f16)]
966+
impl_as_primitive!(f16 => { f16, f32, f64 });
967+
impl_as_primitive!(f32 => { #[cfg(has_f16)] f16, f32, f64 });
968+
impl_as_primitive!(f64 => { #[cfg(has_f16)] f16, f32, f64 });
911969
impl_as_primitive!(char => { char });
912970
impl_as_primitive!(bool => {});

0 commit comments

Comments
 (0)