vax_floating/
lib.rs

1#![doc = include_str!("../README.md")]
2//!
3#![doc = include_str!("doc/encoded_reserved.doc")]
4//!
5#![doc = include_str!("doc/vax_ieee_754_diffs.doc")]
6
7#![forbid(future_incompatible)]
8#![warn(missing_docs, missing_debug_implementations, bare_trait_objects)]
9
10use forward_ref::{
11    forward_ref_binop,
12    forward_ref_op_assign,
13    forward_ref_unop,
14};
15use std::{
16    cmp::Ordering,
17    fmt::{self, Debug, Display, Formatter, LowerExp, UpperExp},
18    hash::{Hash, Hasher},
19    ops::{
20        Add,
21        AddAssign,
22        Div,
23        DivAssign,
24        Mul,
25        MulAssign,
26        Sub,
27        SubAssign,
28        Neg,
29        Shl,
30        ShlAssign,
31        Shr,
32        ShrAssign,
33    },
34    str::FromStr,
35};
36
37pub mod error;
38pub mod arithmetic;
39#[cfg(any(test, feature = "proptest"))]
40pub mod proptest;
41
42pub use crate::{
43    error::{Error, Result},
44    arithmetic::{Fault, Sign, VaxFloatingPoint},
45};
46
47/// Implement the `swap_words` function for a given unsigned integer type.
48macro_rules! swap_words_impl {
49    (u32) => {
50        /// Reverses the (16-bit) word order of a 32-bit integer (`u32`).
51        const fn swap_words(value: u32) -> u32 {
52            value.rotate_right(16)
53        }
54    };
55    (u64) => {
56        /// Reverses the (16-bit) word order of a 64-bit integer (`u64`).
57        const fn swap_words(value: u64) -> u64 {
58            let low = value as u32;
59            let low = low.rotate_right(16) as u64;
60            let high = (value >> 32) as u32;
61            let high = high.rotate_right(16) as u64;
62            (low << 32) | high
63        }
64    };
65    (u128) => {
66        /// Reverses the (16-bit) word order of a 128-bit integer (`u128`).
67        const fn swap_words(value: u128) -> u128 {
68            let low_low = value as u32;
69            let low_low = low_low.rotate_right(16) as u128;
70            let low_high = (value >> 32) as u32;
71            let low_high = low_high.rotate_right(16) as u128;
72            let high_low = (value >> 64) as u32;
73            let high_low = high_low.rotate_right(16) as u128;
74            let high_high = (value >> 96) as u32;
75            let high_high = high_high.rotate_right(16) as u128;
76            (low_low << 96) | (low_high << 64) | (high_low << 32) | high_high
77        }
78    };
79}
80
81/// The format specifier for the bits of a specified VAX floating-point type.
82macro_rules! zero_ext_hex {
83    (FFloating) => {"{:#010X}"};
84    (DFloating) => {"{:#018X}"};
85    (GFloating) => {"{:#018X}"};
86    (HFloating) => {"{:#034X}"};
87}
88
89/// Example bits values for a specified VAX floating-point type. Used for examples.
90macro_rules! vax_fp_bits {
91    (FFloating, 1.5) => {"0x000040C0"};
92    (DFloating, 1.5) => {"0x00000000000040C0"};
93    (GFloating, 1.5) => {"0x0000000000004018"};
94    (HFloating, 1.5) => {"0x0000000000000000000000000080004001"};
95    (FFloating, 12.5) => {"0x00004248"};
96    (DFloating, 12.5) => {"0x0000000000004248"};
97    (GFloating, 12.5) => {"0x0000000000004049"};
98    (HFloating, 12.5) => {"0x0000000000000000000000000090004004"};
99    (FFloating, 10.0) => {"0x00004220"};
100    (DFloating, 10.0) => {"0x0000000000004220"};
101    (GFloating, 10.0) => {"0x0000000000004044"};
102    (HFloating, 10.0) => {"0x00000000000000000000000040004004"};
103    (FFloating, -10.0) => {"0x0000C220"};
104    (DFloating, -10.0) => {"0x000000000000C220"};
105    (GFloating, -10.0) => {"0x000000000000C044"};
106    (HFloating, -10.0) => {"0x0000000000000000000000004000C004"};
107}
108
109/// Implement the functions that support converting to and from Rust floating point types (`f32` and
110/// `f64`).
111///
112/// This creates the constant functions 'to_f32()` and `from_f32()` for all VAX floating-point
113/// types, and `to_f64()` and 'from_f64()` for VAX floating-point types with a large enough
114/// fraction. USAGE: `to_from_rust_fp_impl!(<unsigned type of fraction>, <VAX FP Struct>);`
115///
116/// This also creates the implementations for `From<f32>` for all VAX floating-point types and
117/// `From<f64>` for VAX floating-point types with a large enough fraction. It also creates the
118/// inverse `From<(F|D|G|H)Floating>` for `f32` and `f64`. USAGE:
119/// `to_from_rust_fp_impl!(From, <unsigned type of fraction>, <VAX FP Type>);`
120macro_rules! to_from_rust_fp_impl {
121    (u32, $SelfT: ident) => {
122        to_from_rust_fp_impl!(u32, $SelfT, f32, to_f32, from_f32);
123    };
124    ($ux: ident, $SelfT: ident) => {
125        to_from_rust_fp_impl!($ux, $SelfT, f32, to_f32, from_f32);
126        to_from_rust_fp_impl!($ux, $SelfT, f64, to_f64, from_f64);
127    };
128    (From, u32, $SelfT: ident) => {
129        to_from_rust_fp_impl!(From, u32, $SelfT, f32, to_f32, from_f32);
130    };
131    (From, $ux: ident, $SelfT: ident) => {
132        to_from_rust_fp_impl!(From, $ux, $SelfT, f32, to_f32, from_f32);
133        to_from_rust_fp_impl!(From, $ux, $SelfT, f64, to_f64, from_f64);
134    };
135    ($ux: ident, $SelfT: ident, $fx: ident, $to_func: ident, $from_func: ident) => {
136            #[doc = concat!("Convert from [`", stringify!($fx), "`] to a `", stringify!($SelfT), "`.")]
137            ///
138            /// Can be used to define constants.
139            ///
140            /// # Examples
141            ///
142            /// ```rust
143            #[doc = concat!("# use vax_floating::", stringify!($SelfT), ";")]
144            #[doc = concat!("const ZERO: ", stringify!($SelfT), " = ", stringify!($SelfT), "::",
145                stringify!($from_func), "(0_", stringify!($fx), ");")]
146            #[doc = concat!("const THREE_HALVES: ", stringify!($SelfT), " = ", stringify!($SelfT),
147                "::", stringify!($from_func), "(1.5);")]
148            #[doc = concat!("assert_eq!(", stringify!($SelfT), "::from_bits(0), ZERO);")]
149            #[doc = concat!("assert_eq!(", stringify!($SelfT), "::from_bits(", vax_fp_bits!($SelfT, 1.5), "), THREE_HALVES);")]
150            /// ```
151            ///
152            #[doc = concat!("`From<", stringify!($fx), ">` cannot be used to define constants.")]
153            ///
154            /// ```compile_fail
155            #[doc = concat!("# use vax_floating::", stringify!($SelfT), ";")]
156            #[doc = concat!("const ZERO: ", stringify!($SelfT), " = ", stringify!($SelfT),
157                "::from(0_", stringify!($fx), ");")]
158            /// ```
159            pub const fn $from_func(src: $fx) -> Self {
160                Self::from_fp(VaxFloatingPoint::<$ux>::$from_func(src))
161            }
162
163            #[doc = concat!("Convert from a `", stringify!($SelfT), "` to [`", stringify!($fx), "`].")]
164            ///
165            /// Can be used to define constants.
166            ///
167            /// # Examples
168            ///
169            /// ```rust
170            #[doc = concat!("# use vax_floating::", stringify!($SelfT), ";")]
171            #[doc = concat!("const ZERO: ", stringify!($fx), " = ", stringify!($SelfT),
172                "::from_bits(0).", stringify!($to_func), "();")]
173            #[doc = concat!("const THREE_HALVES: ", stringify!($fx), " = ", stringify!($SelfT),
174                "::from_bits(", vax_fp_bits!($SelfT, 1.5), ").", stringify!($to_func), "();")]
175            #[doc = concat!("assert_eq!(ZERO, 0.0_", stringify!($fx), ");")]
176            #[doc = concat!("assert_eq!(THREE_HALVES, 1.5_", stringify!($fx), ");")]
177            #[doc = concat!("assert_eq!(", stringify!($SelfT), "::from_bits(",
178                vax_fp_bits!($SelfT, 1.5), ").", stringify!($to_func), "(), 1.5_",
179                stringify!($fx), ");")]
180            /// ```
181            ///
182            #[doc = concat!("`From<", stringify!($SelfT), ">` cannot be used to define constants.")]
183            ///
184            /// ```compile_fail
185            #[doc = concat!("# use vax_floating::", stringify!($SelfT), ";")]
186            #[doc = concat!("const ZERO: ", stringify!($fx), " = ", stringify!($fx),
187                "::from(", stringify!($SelfT), "::from_bits(0));")]
188            /// ```
189            pub const fn $to_func(&self) -> $fx {
190                self.to_fp().$to_func()
191            }
192    };
193    (From, $ux: ident, $SelfT: ident, $fx: ident, $to_func: ident, $from_func: ident) => {
194        impl From<&$fx> for $SelfT {
195            fn from(src: &$fx) -> Self {
196                Self::$from_func(*src)
197            }
198        }
199
200        impl From<$fx> for $SelfT {
201            fn from(src: $fx) -> Self {
202                Self::$from_func(src)
203            }
204        }
205
206        impl From<&$SelfT> for $fx {
207            fn from(src: &$SelfT) -> Self {
208                src.$to_func()
209            }
210        }
211
212        impl From<$SelfT> for $fx {
213            fn from(src: $SelfT) -> Self {
214                src.$to_func()
215            }
216        }
217    };
218}
219
220macro_rules! vax_float_use_line {
221    (FFloating, FFloating) => {
222        "# use vax_floating::FFloating;"
223    };
224    (DFloating, DFloating) => {
225        "# use vax_floating::DFloating;"
226    };
227    (GFloating, GFloating) => {
228        "# use vax_floating::GFloating;"
229    };
230    (HFloating, HFloating) => {
231        "# use vax_floating::HFloating;"
232    };
233    ($SelfT: ident, $ToSelfT: ident) => {
234        concat!("# use vax_floating::{", stringify!($SelfT), ", ", stringify!($ToSelfT), "};")
235    };
236}
237
238/// Implement the functions that support converting to and from Rust floating point types (`f32` and
239/// `f64`).
240///
241/// This creates the constant functions 'to_f32()` and `from_f32()` for all VAX floating-point
242/// types, and `to_f64()` and 'from_f64()` for VAX floating-point types with a large enough
243/// fraction. USAGE: `to_from_vax_float_impl!(<unsigned type of fraction>, <VAX FP Struct>);`
244///
245/// This also creates the implementations for `From<f32>` for all VAX floating-point types and
246/// `From<f64>` for VAX floating-point types with a large enough fraction. It also creates the
247/// inverse `From<(F|D|G|H)Floating>` for `f32` and `f64`. USAGE:
248/// `to_from_rust_fp_impl!(From, <unsigned type of fraction>, <VAX FP Type>);`
249macro_rules! to_from_vax_float_impl {
250    (From, FFloating) => {
251        to_from_vax_float_impl!(From, FFloating, DFloating, to_f_floating, to_d_floating);
252        to_from_vax_float_impl!(From, FFloating, GFloating, to_f_floating, to_g_floating);
253        to_from_vax_float_impl!(From, FFloating, HFloating, to_f_floating, to_h_floating);
254    };
255    (From, DFloating) => {
256        to_from_vax_float_impl!(From, DFloating, GFloating, to_d_floating, to_g_floating);
257        to_from_vax_float_impl!(From, DFloating, HFloating, to_d_floating, to_h_floating);
258    };
259    (From, GFloating) => {
260        to_from_vax_float_impl!(From, GFloating, HFloating, to_g_floating, to_h_floating);
261    };
262    (From, HFloating) => {};
263    ($ux: ident, $SelfT: ident) => {
264        to_from_vax_float_impl!($ux, $SelfT, FFloating, to_f_floating, to_vfp_32, from_f_floating, from_vfp_32);
265        to_from_vax_float_impl!($ux, $SelfT, DFloating, to_d_floating, to_vfp_64, from_d_floating, from_vfp_64);
266        to_from_vax_float_impl!($ux, $SelfT, GFloating, to_g_floating, to_vfp_64, from_g_floating, from_vfp_64);
267        to_from_vax_float_impl!($ux, $SelfT, HFloating, to_h_floating, to_vfp_128, from_h_floating, from_vfp_128);
268    };
269    ($ux: ident, $SelfT: ident, $ToSelfT: ident, $to_fp_func: ident, $to_vfp: ident, $from_fp_func: ident, $from_vfp: ident) => {
270            #[doc = concat!("Convert from [`", stringify!($ToSelfT), "`] to a `", stringify!($SelfT), "`.")]
271            ///
272            /// Can be used to define constants.
273            ///
274            /// # Examples
275            ///
276            /// ```rust
277            #[doc = vax_float_use_line!($SelfT, $ToSelfT)]
278            #[doc = concat!("const FROM_ZERO: ", stringify!($ToSelfT), " = ", stringify!($ToSelfT),
279                "::from_bits(0);")]
280            #[doc = concat!("const FROM_THREE_HALVES: ", stringify!($ToSelfT), " = ",
281                stringify!($ToSelfT), "::from_f32(1.5);")]
282            #[doc = concat!("const ZERO: ", stringify!($SelfT), " = ", stringify!($SelfT), "::",
283                stringify!($from_fp_func), "(FROM_ZERO);")]
284            #[doc = concat!("const THREE_HALVES: ", stringify!($SelfT), " = ", stringify!($SelfT), "::",
285                stringify!($from_fp_func), "(FROM_THREE_HALVES);")]
286            #[doc = concat!("assert_eq!(", stringify!($SelfT), "::from_bits(0), ZERO);")]
287            #[doc = concat!("assert_eq!(", stringify!($SelfT), "::from_bits(", vax_fp_bits!($SelfT, 1.5), "), THREE_HALVES);")]
288            /// ```
289            ///
290            #[doc = concat!("`From<", stringify!($ToSelfT), ">` cannot be used to define constants.")]
291            ///
292            /// ```compile_fail
293            #[doc = vax_float_use_line!($SelfT, $ToSelfT)]
294            #[doc = concat!("const FROM_ZERO: ", stringify!($ToSelfT), " = ", stringify!($ToSelfT),
295                "::from_bits(0);")]
296            #[doc = concat!("const ZERO: ", stringify!($SelfT), " = ", stringify!($SelfT),
297                "::from(FROM_ZERO);")]
298            /// ```
299            pub const fn $from_fp_func(src: $ToSelfT) -> Self {
300                Self::from_fp(VaxFloatingPoint::<$ux>::$from_vfp(src.to_fp()))
301            }
302
303            #[doc = concat!("Convert from a `", stringify!($SelfT), "` to [`",
304                stringify!($ToSelfT), "`].")]
305            ///
306            /// Can be used to define constants.
307            ///
308            /// # Examples
309            ///
310            /// ```rust
311            #[doc = vax_float_use_line!($SelfT, $ToSelfT)]
312            #[doc = concat!("const FROM_ZERO: ", stringify!($SelfT), " = ", stringify!($SelfT),
313                "::from_bits(0);")]
314            #[doc = concat!("const FROM_THREE_HALVES: ", stringify!($SelfT), " = ",
315                stringify!($SelfT), "::from_bits(", vax_fp_bits!($SelfT, 1.5), ");")]
316            #[doc = concat!("const ZERO: ", stringify!($ToSelfT), " = FROM_ZERO.",
317                stringify!($to_fp_func), "();")]
318            #[doc = concat!("const THREE_HALVES: ", stringify!($ToSelfT), " = FROM_THREE_HALVES.",
319                stringify!($to_fp_func), "();")]
320            #[doc = concat!("assert_eq!(ZERO, ", stringify!($ToSelfT), "::from_bits(0));")]
321            #[doc = concat!("assert_eq!(THREE_HALVES, ", stringify!($ToSelfT), "::from_f32(1.5));")]
322            /// ```
323            ///
324            #[doc = concat!("`From<", stringify!($SelfT), ">` cannot be used to define constants.")]
325            ///
326            /// ```compile_fail
327            #[doc = vax_float_use_line!($SelfT, $ToSelfT)]
328            #[doc = concat!("const FROM_ZERO: ", stringify!($SelfT), " = ", stringify!($SelfT),
329                "::from_bits(0);")]
330            #[doc = concat!("const ZERO: ", stringify!($ToSelfT), " = ", stringify!($ToSelfT),
331                "::from(FROM_ZERO);")]
332            /// ```
333            pub const fn $to_fp_func(&self) -> $ToSelfT {
334                $ToSelfT::from_fp(self.to_fp().$to_vfp())
335            }
336    };
337    (From, $SelfT: ident, $OtherT: ident, $to_self: ident, $to_other: ident) => {
338        impl From<&$OtherT> for $SelfT {
339            fn from(src: &$OtherT) -> Self {
340                src.$to_self()
341            }
342        }
343
344        impl From<$OtherT> for $SelfT {
345            fn from(src: $OtherT) -> Self {
346                src.$to_self()
347            }
348        }
349
350        impl From<&$SelfT> for $OtherT {
351            fn from(src: &$SelfT) -> Self {
352                src.$to_other()
353            }
354        }
355
356        impl From<$SelfT> for $OtherT {
357            fn from(src: $SelfT) -> Self {
358                src.$to_other()
359            }
360        }
361    };
362}
363
364/// The documentation to display for lossy `from_*()` and `From<*>` conversions to
365/// VAX floating point types.
366macro_rules! from_int_lossy_doc {
367    ($SelfT: ident) => {
368        concat!("**Note**: Only the most significant set bits that fit into the number of [`",
369            stringify!($SelfT), "::MANTISSA_DIGITS`] will be preserved. This will result in a loss
370            of precision.")
371    };
372}
373
374/// Implement the functions that support converting from Rust integer types.
375///
376/// This creates the constant functions `from_<type>()` for all integer types that are smaller than
377/// the fraction size of the VAX floating-point type.
378/// USAGE: `from_rust_int_impl!(<unsigned type of fraction>, <VAX FP Struct>);`
379///
380/// This also creates the implementations for `From` for all VAX floating-point types and
381/// `From<f64>` for VAX floating-point types with a large enough fraction. It also creates the
382/// inverse `From<(F|D|G|H)Floating>` for `f32` and `f64`. USAGE:
383/// `from_rust_int_impl!(From, <unsigned type of fraction>, <VAX FP Type>);`
384macro_rules! from_rust_int_impl {
385    (u32, $SelfT: ident) => {
386        from_rust_int_impl!(to_u32, u32, $SelfT);
387        from_rust_int_impl!(lossy_u64, u32, $SelfT);
388        from_rust_int_impl!(lossy_u128, u32, $SelfT);
389    };
390    (u64, $SelfT: ident) => {
391        from_rust_int_impl!(to_u32, u64, $SelfT);
392        from_rust_int_impl!(to_u64, u64, $SelfT);
393        from_rust_int_impl!(lossy_u128, u64, $SelfT);
394    };
395    (u128, $SelfT: ident) => {
396        from_rust_int_impl!(to_u32, u128, $SelfT);
397        from_rust_int_impl!(to_u64, u128, $SelfT);
398        from_rust_int_impl!(to_u128, u128, $SelfT);
399    };
400    (From, u32, $SelfT: ident) => {
401        from_rust_int_impl!(From, to_u32, u32, $SelfT);
402        from_rust_int_impl!(From, lossy_u64, u32, $SelfT);
403        from_rust_int_impl!(From, lossy_u128, u32, $SelfT);
404    };
405    (From, u64, $SelfT: ident) => {
406        from_rust_int_impl!(From, to_u32, u64, $SelfT);
407        from_rust_int_impl!(From, to_u64, u64, $SelfT);
408        from_rust_int_impl!(From, lossy_u128, u64, $SelfT);
409    };
410    (From, u128, $SelfT: ident) => {
411        from_rust_int_impl!(From, to_u32, u128, $SelfT);
412        from_rust_int_impl!(From, to_u64, u128, $SelfT);
413        from_rust_int_impl!(From, to_u128, u128, $SelfT);
414    };
415    (to_u32, $ux: ident, $SelfT: ident) => {
416        from_rust_int_impl!($ux, $SelfT, u8, from_u8, "");
417        from_rust_int_impl!($ux, $SelfT, i8, from_i8, "");
418        from_rust_int_impl!($ux, $SelfT, u16, from_u16, "");
419        from_rust_int_impl!($ux, $SelfT, i16, from_i16, "");
420    };
421    (to_u64, $ux: ident, $SelfT: ident) => {
422        from_rust_int_impl!($ux, $SelfT, u32, from_u32, "");
423        from_rust_int_impl!($ux, $SelfT, i32, from_i32, "");
424    };
425    (to_u128, $ux: ident, $SelfT: ident) => {
426        from_rust_int_impl!($ux, $SelfT, u64, from_u64, "");
427        from_rust_int_impl!($ux, $SelfT, i64, from_i64, "");
428        from_rust_int_impl!($ux, $SelfT, usize, from_usize, "");
429        from_rust_int_impl!($ux, $SelfT, isize, from_isize, "");
430        from_rust_int_impl!($ux, $SelfT, u128, from_u128, from_int_lossy_doc!($SelfT));
431        from_rust_int_impl!($ux, $SelfT, i128, from_i128, from_int_lossy_doc!($SelfT));
432    };
433    (lossy_u64, $ux: ident, $SelfT: ident) => {
434        from_rust_int_impl!($ux, $SelfT, u32, from_u32, from_int_lossy_doc!($SelfT));
435        from_rust_int_impl!($ux, $SelfT, i32, from_i32, from_int_lossy_doc!($SelfT));
436    };
437    (lossy_u128, $ux: ident, $SelfT: ident) => {
438        from_rust_int_impl!($ux, $SelfT, u64, from_u64, from_int_lossy_doc!($SelfT));
439        from_rust_int_impl!($ux, $SelfT, i64, from_i64, from_int_lossy_doc!($SelfT));
440        from_rust_int_impl!($ux, $SelfT, usize, from_usize, from_int_lossy_doc!($SelfT));
441        from_rust_int_impl!($ux, $SelfT, isize, from_isize, from_int_lossy_doc!($SelfT));
442        from_rust_int_impl!($ux, $SelfT, u128, from_u128, from_int_lossy_doc!($SelfT));
443        from_rust_int_impl!($ux, $SelfT, i128, from_i128, from_int_lossy_doc!($SelfT));
444    };
445    (From, to_u32, $ux: ident, $SelfT: ident) => {
446        from_rust_int_impl!(From, $ux, $SelfT, u8, from_u8, "");
447        from_rust_int_impl!(From, $ux, $SelfT, i8, from_i8, "");
448        from_rust_int_impl!(From, $ux, $SelfT, u16, from_u16, "");
449        from_rust_int_impl!(From, $ux, $SelfT, i16, from_i16, "");
450    };
451    (From, to_u64, $ux: ident, $SelfT: ident) => {
452        from_rust_int_impl!(From, $ux, $SelfT, u32, from_u32, "");
453        from_rust_int_impl!(From, $ux, $SelfT, i32, from_i32, "");
454    };
455    (From, to_u128, $ux: ident, $SelfT: ident) => {
456        from_rust_int_impl!(From, $ux, $SelfT, u64, from_u64, "");
457        from_rust_int_impl!(From, $ux, $SelfT, i64, from_i64, "");
458        from_rust_int_impl!(From, $ux, $SelfT, usize, from_usize, "");
459        from_rust_int_impl!(From, $ux, $SelfT, isize, from_isize, "");
460        from_rust_int_impl!(From, $ux, $SelfT, u128, from_u128, from_int_lossy_doc!($SelfT));
461        from_rust_int_impl!(From, $ux, $SelfT, i128, from_i128, from_int_lossy_doc!($SelfT));
462    };
463    (From, lossy_u64, $ux: ident, $SelfT: ident) => {
464        from_rust_int_impl!(From, $ux, $SelfT, u32, from_u32, from_int_lossy_doc!($SelfT));
465        from_rust_int_impl!(From, $ux, $SelfT, i32, from_i32, from_int_lossy_doc!($SelfT));
466    };
467    (From, lossy_u128, $ux: ident, $SelfT: ident) => {
468        from_rust_int_impl!(From, $ux, $SelfT, u64, from_u64, from_int_lossy_doc!($SelfT));
469        from_rust_int_impl!(From, $ux, $SelfT, i64, from_i64, from_int_lossy_doc!($SelfT));
470        from_rust_int_impl!(From, $ux, $SelfT, usize, from_usize, from_int_lossy_doc!($SelfT));
471        from_rust_int_impl!(From, $ux, $SelfT, isize, from_isize, from_int_lossy_doc!($SelfT));
472        from_rust_int_impl!(From, $ux, $SelfT, u128, from_u128, from_int_lossy_doc!($SelfT));
473        from_rust_int_impl!(From, $ux, $SelfT, i128, from_i128, from_int_lossy_doc!($SelfT));
474    };
475    ($ux: ident, $SelfT: ident, $uy: ident, $from_func: ident, $lossy_doc: expr) => {
476        #[doc = concat!("Convert from [`", stringify!($uy), "`] to a `", stringify!($SelfT), "`.")]
477        ///
478        /// Can be used to define constants.
479        ///
480        #[doc = $lossy_doc]
481        ///
482        /// # Examples
483        ///
484        /// ```rust
485        #[doc = concat!("# use vax_floating::", stringify!($SelfT), ";")]
486        #[doc = concat!("const ZERO: ", stringify!($SelfT), " = ", stringify!($SelfT), "::",
487            stringify!($from_func), "(0_", stringify!($uy), ");")]
488        #[doc = concat!("const TEN: ", stringify!($SelfT), " = ", stringify!($SelfT),
489            "::", stringify!($from_func), "(10);")]
490        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::from_bits(0), ZERO);")]
491        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::from_bits(", vax_fp_bits!($SelfT, 10.0), "), TEN);")]
492        /// ```
493        ///
494        #[doc = concat!("`From<", stringify!($uy), ">` cannot be used to define constants.")]
495        ///
496        /// ```compile_fail
497        #[doc = concat!("# use vax_floating::", stringify!($SelfT), ";")]
498        #[doc = concat!("const ZERO: ", stringify!($SelfT), " = ", stringify!($SelfT),
499            "::from(0_", stringify!($uy), ");")]
500        /// ```
501        pub const fn $from_func(src: $uy) -> Self {
502            Self::from_fp(VaxFloatingPoint::<$ux>::$from_func(src))
503        }
504    };
505    (From, $ux: ident, $SelfT: ident, $fx: ident, $from_func: ident, $lossy_doc: expr) => {
506        impl From<&$fx> for $SelfT {
507            /// Converts to this type from the input type.
508            ///
509            #[doc = $lossy_doc]
510            fn from(src: &$fx) -> Self {
511                Self::$from_func(*src)
512            }
513        }
514
515        impl From<$fx> for $SelfT {
516            /// Converts to this type from the input type.
517            ///
518            #[doc = $lossy_doc]
519            fn from(src: $fx) -> Self {
520                Self::$from_func(src)
521            }
522        }
523    };
524}
525
526/// Implement the Shr, Shl, ShrAssign, and ShlAssign traits.
527macro_rules! sh_impl {
528    ($t: ident) => {
529        sh_impl! { $t, u32, i32 }
530    };
531    ($t: ident, $uf: ident, $if: ident) => {
532        impl Shl<$uf> for $t {
533            type Output = $t;
534
535            #[inline]
536            fn shl(self, other: $uf) -> $t {
537                Self::from_fp(self.to_fp().shift_left_unsigned(other))
538            }
539        }
540        forward_ref_binop! { impl Shl, shl for $t, $uf }
541
542        impl Shr<$uf> for $t {
543            type Output = $t;
544
545            #[inline]
546            fn shr(self, other: $uf) -> $t {
547                Self::from_fp(self.to_fp().shift_right_unsigned(other))
548            }
549        }
550        forward_ref_binop! { impl Shr, shr for $t, $uf }
551
552        impl ShlAssign<$uf> for $t {
553            #[inline]
554            fn shl_assign(&mut self, other: $uf) {
555                *self = *self << other;
556            }
557        }
558        forward_ref_op_assign! { impl ShlAssign, shl_assign for $t, $uf }
559
560        impl ShrAssign<$uf> for $t {
561            #[inline]
562            fn shr_assign(&mut self, other: $uf) {
563                *self = *self >> other;
564            }
565        }
566        forward_ref_op_assign! { impl ShrAssign, shr_assign for $t, $uf }
567
568        impl Shl<$if> for $t {
569            type Output = $t;
570
571            #[inline]
572            fn shl(self, other: $if) -> $t {
573                Self::from_fp(self.to_fp().shift_left(other))
574            }
575        }
576        forward_ref_binop! { impl Shl, shl for $t, $if }
577
578        impl Shr<$if> for $t {
579            type Output = $t;
580
581            #[inline]
582            fn shr(self, other: $if) -> $t {
583                Self::from_fp(self.to_fp().shift_right(other))
584            }
585        }
586        forward_ref_binop! { impl Shr, shr for $t, $if }
587    };
588}
589
590/// Define and implement a VAX floating-point type given a set of parameters.
591///
592/// # Examples
593///
594/// ```text
595/// floating_impl!{
596///     Self = FFloating,
597///     ActualT = u32,
598///     ExpBits = 8,
599///     VaxName = "F_floating",
600///     le_bytes = "[0xC8, 0x40, 0x00, 0x00]",
601///     be_bytes = "[0x00, 0x00, 0x40, 0xC8]",
602/// }
603/// ```
604macro_rules! floating_impl {
605    (
606        Self = $SelfT: ident,
607        ActualT = $ux: ident,
608        ExpBits = $exp: literal,
609        VaxName = $VaxName: literal,
610        swapped = $swapped: literal,
611        le_bytes = $le_bytes: literal,
612        be_bytes = $be_bytes: literal,
613    ) => {
614        #[doc = concat!("# The VAX ", $VaxName, " type.")]
615        ///
616        /// ## Reference Documentation
617        ///
618        /// Here are excerpts from the **VAX Architecture Reference Manual** and the **VAX MACRO
619        /// and Instruction Set Reference Manual** for the VAX
620        #[doc = concat!($VaxName, " floating-point type.")]
621        ///
622        #[doc = include_str!(concat!("doc/", stringify!($SelfT), "_vax.doc"))]
623        #[derive(Copy, Clone, Default, Eq)]
624        pub struct $SelfT($ux);
625
626        impl $SelfT {
627            #[doc = concat!("The radix or base of the internal representation of `", stringify!($SelfT), "`.")]
628            pub const RADIX: u32 = 2;
629
630            /// Number of significant digits in base 2.
631            pub const MANTISSA_DIGITS: u32 = <$ux>::BITS - $exp;
632
633            #[doc = concat!("The mask used by `from_ascii()` to determine when new digits won't ",
634                "change the `", stringify!($SelfT), "` fraction value.")]
635            const DIV_PRECISION: u32 = Self::MANTISSA_DIGITS + 2;
636
637            /// Approximate number of significant digits in base 10.
638            pub const DIGITS: u32 = {
639                let value: $ux = 1 << Self::MANTISSA_DIGITS;
640                // I chose not to make this change because similar changes would be needed in
641                // src/arithmetic.rs as well that happen during runtime. I'm leaving it here in
642                // case I change my mind later.
643                //
644                // This should use the ilog10, but the feature was unstable until Rust version
645                // 1.67.1, which prevents it from being used to define a constant. This change
646                // enables support for more versions of the rust compiler.
647                //
648                // The simple replacement is slow, but since it is run only once at compile time,
649                // I'm not going to bother finding a more efficient one.
650                //
651                // error[E0658]: use of unstable library feature 'int_log'
652                //     --> src/lib.rs:523:23
653                //      |
654                //      |                   value.ilog10()
655                //                                ^^^^^^
656                //let mut slow_ilog = 0_u32;
657                //while 10 <= value {
658                //    slow_ilog += 1;
659                //    value /= 10;
660                //}
661                //slow_ilog
662                value.ilog10()
663            };
664
665            #[doc = concat!("[Machine epsilon] value for `", stringify!($SelfT), "`.")]
666            ///
667            /// This is the difference between `1.0` and the next larger representable number.
668            ///
669            /// [Machine epsilon]: https://en.wikipedia.org/wiki/Machine_epsilon
670            pub const EPSILON: $SelfT = $SelfT::from_parts(Sign::Positive, Self::EXP_BIAS + 1 - (Self::MANTISSA_DIGITS as i32), 0);
671
672            #[doc = concat!("Smallest finite `", stringify!($SelfT), "` value.")]
673            pub const MIN: $SelfT =
674                $SelfT::from_parts(Sign::Negative, Self::MAX_EXP, (1 << Self::MANTISSA_DIGITS) - 1);
675            #[doc = concat!("Smallest positive normal `", stringify!($SelfT), "` value.")]
676            pub const MIN_POSITIVE: $SelfT =
677                $SelfT::from_parts(Sign::Positive, Self::MIN_EXP, 0);
678            #[doc = concat!("Largest finite `", stringify!($SelfT), "` value.")]
679            pub const MAX: $SelfT =
680                $SelfT::from_parts(Sign::Positive, Self::MAX_EXP, (1 << Self::MANTISSA_DIGITS) - 1);
681
682            /// One greater than the minimum possible normal power of 2 exponent.
683            pub const MIN_EXP: i32 = 1 - (Self::EXP_BIAS);
684            /// Maximum possible power of 2 exponent.
685            pub const MAX_EXP: i32 = (Self::EXP_BIAS) - 1;
686
687            /// Minimum possible normal power of 10 exponent.
688            pub const MIN_10_EXP: i32 = {
689                const TEN: VaxFloatingPoint::<$ux> = VaxFloatingPoint::<$ux>::from_f32(10.0);
690                let mut temp = Self::MIN_POSITIVE.to_fp();
691                let mut tens = 1;
692                while temp.exponent() <= 0 {
693                    temp = temp.multiply_by(TEN);
694                    tens -= 1;
695                }
696                tens
697            };
698            /// Maximum possible power of 10 exponent.
699            pub const MAX_10_EXP: i32 = {
700                const TENTH: VaxFloatingPoint::<$ux> = VaxFloatingPoint::<$ux>::from_f32(1.0)
701                    .divide_by(VaxFloatingPoint::<$ux>::from_f32(10.0), <$ux>::BITS);
702                let mut temp = Self::MAX.to_fp();
703                let mut tens = -1;
704                while temp.exponent() > 0 {
705                    temp = temp.multiply_by(TENTH);
706                    tens += 1;
707                }
708                tens
709            };
710
711            #[doc = concat!("The size of the VAX `", $VaxName, "` type in bits.")]
712            pub const BITS: u32 = <$ux>::BITS;
713
714            #[doc = concat!("[Exponent bias] of the `", stringify!($SelfT), "` type.")]
715            ///
716            /// The value subtracted from the exponent to get the actual exponent.
717            ///
718            /// [Exponent bias]: https://en.wikipedia.org/wiki/Exponent_bias
719            const EXP_BIAS: i32 = 1 << ($exp - 1);
720
721            #[doc = concat!("The size of the exponent in the VAX `", $VaxName, "` type in bits.")]
722            const EXP_BITS: u32 = $exp;
723
724            #[doc = concat!("The number of bits the exponent of the VAX `", $VaxName,
725                "` type is shifted.")]
726            ///
727            /// Because of the unique ordering of the bytes in VAX floating point types, the
728            /// exponent is always in the first (lowest addressed) 16-bits of binary representation.
729            const EXP_SHIFT: u32 = 15 - Self::EXP_BITS;
730
731            #[doc = concat!("The mask for the exponent of the VAX `", $VaxName, "` type.")]
732            ///
733            /// Because of the unique ordering of the bytes in VAX floating point types, the
734            /// exponent is always in the first (lowest addressed) 16-bits of binary representation.
735            const EXP_MASK: $ux = ((1 << Self::EXP_BITS) - 1) << Self::EXP_SHIFT;
736
737            #[doc = concat!("The sign mask for the VAX `", $VaxName, "` type.")]
738            ///
739            /// Because of the unique ordering of the bytes in VAX floating point types, the sign
740            /// bit is always bit 15.
741            const SIGN: $ux = 1 << 15;
742
743            #[doc = concat!("The fraction mask for the VAX `", $VaxName, "` type.")]
744            const FRAC_MASK: $ux = !(Self::EXP_MASK | Self::SIGN);
745
746            #[doc = concat!("Number of bits to shift when converting from the word swapped `",
747                stringify!($SelfT), "` to `VaxFloatingPoint<", stringify!($ux),
748                ">` fraction value.")]
749            const FP_FRAC_SHIFT: u32 = $exp;
750
751            #[doc = concat!("The rounding bit mask added to the fraction of `VaxFloatingPoint<",
752                stringify!($ux), "> when converting back to `", stringify!($SelfT), "`.")]
753            const FP_FRAC_ROUND: $ux = 1 << (Self::FP_FRAC_SHIFT - 1);
754
755            #[doc = concat!(
756                "The mask used by `from_ascii()` to determine when new digits won't change the `",
757                stringify!($SelfT), "` fraction value.")]
758            const ASCII_MASK: $ux = ((1 << (Self::MANTISSA_DIGITS + 1)) - 1) << Self::FP_FRAC_SHIFT;
759
760            /// Reserved shifts to the top two bits of the fraction.
761            const RESERVED_SHIFT: u32 = if 14 > Self::EXP_BITS {
762                    // This shouldn't need the wrapping_sub because the if statement should block
763                    // any Self::EXP_BITS values above 13, however Rust versions after 1.67.1 and
764                    // before 1.70.0 seem to evaluate this even though it is unused and trigger an
765                    // overflow error. This change enables support for more versions of the rust
766                    // compiler.
767                    //
768                    // 13 - Self::EXP_BITS
769                    // ^^^^^^^^^^^^^^^^^^^ attempt to compute `13_u32 - 15_u32`, which would overflow
770                    13_u32.wrapping_sub(Self::EXP_BITS)
771                }
772                else {
773                   // If there is no room in the first 16 bits (h_floating), use top of the second 16-bits.
774                   30
775                };
776            /// The overflow or underflow shift moves a 16-bit value into the 16-bit area after the
777            /// most significant two bits.
778            const RESERVED_OVER_UNDER_SHIFT: u32 = if 14 > Self::EXP_BITS { 16 } else { 32 };
779
780            // Implement the swap_words function for this VAX floating point type.
781            swap_words_impl!($ux);
782
783            #[doc = concat!("Raw transmutation from the `", stringify!($SelfT), "` type to `",
784                stringify!($ux), "`.")]
785            ///
786            /// # Examples
787            ///
788            /// ```rust
789            #[doc = concat!("# use vax_floating::", stringify!($SelfT), ";")]
790            #[doc = concat!("assert_eq!(", stringify!($SelfT), "::from_f32(0_f32).to_bits(), 0_",
791                stringify!($ux), ");")]
792            #[doc = concat!("assert_eq!(", stringify!($SelfT), "::from_f32(1.5).to_bits(), ",
793                vax_fp_bits!($SelfT, 1.5), "_", stringify!($ux), ");")]
794            #[doc = concat!("assert_eq!(", stringify!($SelfT), "::from_f32(12.5).to_bits(), ",
795                vax_fp_bits!($SelfT, 12.5), "_", stringify!($ux), ");")]
796            /// ```
797            #[inline]
798            pub const fn to_bits(self) -> $ux { self.0 }
799
800            #[doc = concat!("Raw transmutation from a `", stringify!($ux), "` the `",
801                stringify!($SelfT), "` type.")]
802            ///
803            /// # Examples
804            ///
805            /// ```rust
806            #[doc = concat!("# use vax_floating::", stringify!($SelfT), ";")]
807            #[doc = concat!("assert_eq!(", stringify!($SelfT), "::from_bits(0), ",
808                stringify!($SelfT), "::from_f32(0_f32));")]
809            #[doc = concat!("assert_eq!(", stringify!($SelfT), "::from_bits(",
810                vax_fp_bits!($SelfT, 1.5), "), ", stringify!($SelfT), "::from_f32(1.5));")]
811            #[doc = concat!("assert_eq!(", stringify!($SelfT), "::from_bits(",
812                vax_fp_bits!($SelfT, 12.5), "), ", stringify!($SelfT), "::from_f32(12.5));")]
813            /// ```
814            #[inline]
815            pub const fn from_bits(bits: $ux) -> Self { Self(bits) }
816
817            #[doc = concat!("Return the memory representation of the `", stringify!($SelfT),
818                "` type as a byte array in little-endian byte order.")]
819            ///
820            /// # Examples
821            ///
822            /// ```rust
823            #[doc = concat!("# use vax_floating::", stringify!($SelfT), ";")]
824            #[doc = concat!("let bytes = ", stringify!($SelfT), "::from_f32(12.5).to_le_bytes();")]
825            #[doc = concat!("assert_eq!(bytes, ", $le_bytes, ");")]
826            /// ```
827            #[inline]
828            pub const fn to_le_bytes(&self) -> [u8; std::mem::size_of::<$ux>()] { self.0.to_le_bytes() }
829
830            #[doc = concat!("Return the memory representation of the `", stringify!($SelfT),
831                "` type as a byte array in big-endian (network) byte order.")]
832            ///
833            /// # Examples
834            ///
835            /// ```rust
836            #[doc = concat!("# use vax_floating::", stringify!($SelfT), ";")]
837            #[doc = concat!("let bytes = ", stringify!($SelfT), "::from_f32(12.5).to_be_bytes();")]
838            #[doc = concat!("assert_eq!(bytes, ", $be_bytes, ");")]
839            /// ```
840            #[inline]
841            pub const fn to_be_bytes(&self) -> [u8; std::mem::size_of::<$ux>()] { self.0.to_be_bytes() }
842
843            #[doc = concat!("Return the memory representation of the `", stringify!($SelfT),
844                "` type as a byte array in native byte order.")]
845            ///
846            /// # Examples
847            ///
848            /// ```rust
849            #[doc = concat!("# use vax_floating::", stringify!($SelfT), ";")]
850            #[doc = concat!("let bytes = ", stringify!($SelfT), "::from_f32(12.5).to_ne_bytes();")]
851            /// assert_eq!(
852            ///     bytes,
853            ///     if cfg!(target_endian = "big") {
854            #[doc = concat!("   ", $be_bytes)]
855            ///     } else {
856            #[doc = concat!("   ", $le_bytes)]
857            ///     }
858            /// );
859            /// ```
860            #[inline]
861            pub const fn to_ne_bytes(&self) -> [u8; std::mem::size_of::<$ux>()] { self.0.to_ne_bytes() }
862
863            #[doc = concat!("Create a `", stringify!($SelfT),
864                "` type from its representation as a byte array in little endian.")]
865            ///
866            /// # Examples
867            ///
868            /// ```rust
869            #[doc = concat!("# use vax_floating::", stringify!($SelfT), ";")]
870            #[doc = concat!("let float = ", stringify!($SelfT), "::from_le_bytes(", $le_bytes, ");")]
871            #[doc = concat!("assert_eq!(float, ", stringify!($SelfT), "::from_f32(12.5));")]
872            /// ```
873            #[inline]
874            pub const fn from_le_bytes(bytes: [u8; std::mem::size_of::<$ux>()]) -> Self {
875                Self(<$ux>::from_le_bytes(bytes))
876            }
877
878            #[doc = concat!("Create a `", stringify!($SelfT),
879                "` type from its representation as a byte array in big endian.")]
880            ///
881            /// # Examples
882            ///
883            /// ```rust
884            #[doc = concat!("# use vax_floating::", stringify!($SelfT), ";")]
885            #[doc = concat!("let float = ", stringify!($SelfT), "::from_be_bytes(", $be_bytes, ");")]
886            #[doc = concat!("assert_eq!(float, ", stringify!($SelfT), "::from_f32(12.5));")]
887            /// ```
888            #[inline]
889            pub const fn from_be_bytes(bytes: [u8; std::mem::size_of::<$ux>()]) -> Self {
890                Self(<$ux>::from_be_bytes(bytes))
891            }
892
893            #[doc = concat!("Create a `", stringify!($SelfT),
894                "` type from its representation as a byte array in native endianness.")]
895            ///
896            /// # Examples
897            ///
898            /// ```rust
899            #[doc = concat!("# use vax_floating::", stringify!($SelfT), ";")]
900            #[doc = concat!("let float = ", stringify!($SelfT), "::from_ne_bytes(")]
901            ///     if cfg!(target_endian = "big") {
902            #[doc = concat!("   ", $be_bytes)]
903            ///     } else {
904            #[doc = concat!("   ", $le_bytes)]
905            ///     }
906            /// );
907            #[doc = concat!("assert_eq!(float, ", stringify!($SelfT), "::from_f32(12.5));")]
908            /// ```
909            #[inline]
910            pub const fn from_ne_bytes(bytes: [u8; std::mem::size_of::<$ux>()]) -> Self {
911                Self(<$ux>::from_ne_bytes(bytes))
912            }
913
914            #[doc = concat!("Reverses the (16-bit) word order of the raw transmutation of a `",
915                stringify!($ux), "` into the `", stringify!($SelfT), "` type.")]
916            ///
917            /// # Examples
918            ///
919            /// ```rust
920            #[doc = concat!("# use vax_floating::", stringify!($SelfT), ";")]
921            #[doc = concat!("assert_eq!(", stringify!($SelfT), "::from_bits(",
922                vax_fp_bits!($SelfT, 12.5), ").to_swapped(), ", $swapped, "_", stringify!($ux), ");")]
923            #[doc = concat!("assert_eq!(", stringify!($SelfT), "::from_f32(12.5).to_swapped(), ",
924                $swapped, "_", stringify!($ux), ");")]
925            /// ```
926            #[inline]
927            pub const fn to_swapped(self) -> $ux {
928                Self::swap_words(self.0)
929            }
930
931            #[doc = concat!("Reverses the (16-bit) word order of the raw transmutation of the `",
932                stringify!($SelfT), "` type into a `", stringify!($ux), "`.")]
933            ///
934            /// # Examples
935            ///
936            /// ```rust
937            #[doc = concat!("# use vax_floating::", stringify!($SelfT), ";")]
938            #[doc = concat!("assert_eq!(", stringify!($SelfT), "::from_swapped(", $swapped, "), ",
939                stringify!($SelfT), "::from_f32(12.5));")]
940            #[doc = concat!("assert_eq!(", stringify!($SelfT), "::from_swapped(", $swapped, "), ",
941                stringify!($SelfT), "::from_bits(", vax_fp_bits!($SelfT, 12.5), "));")]
942            /// ```
943            #[inline]
944            pub const fn from_swapped(swapped: $ux) -> Self {
945                Self(Self::swap_words(swapped))
946            }
947
948            #[doc = concat!("Create a `", stringify!($SelfT),
949                "` type from the sign, (base 2) exponent, and fraction value.")]
950            #[inline]
951            const fn from_parts(sign: Sign, exp: i32, frac: $ux) -> Self {
952                Self((Self::swap_words(frac) & Self::FRAC_MASK) |
953                    ((((exp + Self::EXP_BIAS) as $ux) << Self::EXP_SHIFT) & Self::EXP_MASK) |
954                    if sign.is_negative() { Self::SIGN } else { 0 })
955            }
956
957            /// Returns a number that represents the sign of `self`.
958            ///
959            /// - `1.0` if the number is positive, `+0.0`
960            /// - `-1.0` if the number is negative
961            /// - `Reserved` if the number is `Reserved`
962            /// # Examples
963            ///
964            /// ```rust
965            #[doc = concat!("# use vax_floating::", stringify!($SelfT), ";")]
966            #[doc = concat!("const ONE: ", stringify!($SelfT), " = ", stringify!($SelfT),
967                "::from_i8(1);")]
968            #[doc = concat!("const NEG: ", stringify!($SelfT), " = ", stringify!($SelfT),
969                "::from_i8(-1);")]
970            #[doc = concat!("assert_eq!(", stringify!($SelfT), "::from_bits(0).signum(), ONE);")]
971            #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN_POSITIVE.signum(), ONE);")]
972            #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.signum(), ONE);")]
973            #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.signum(), NEG);")]
974            #[doc = concat!("assert!(", stringify!($SelfT),
975                "::from_bits(0x8000).signum().is_reserved());")]
976            /// ```
977            #[inline]
978            pub const fn signum(self) -> Self {
979                if self.is_reserved() { self }
980                else {
981                    Self((self.0 & Self::SIGN) |
982                        (((Self::EXP_BIAS as $ux) + 1) << Self::EXP_SHIFT))
983                }
984            }
985
986            #[doc = concat!("Return `true` if the `", stringify!($SelfT), "` is zero.")]
987            ///
988            /// # Examples
989            ///
990            /// ```rust
991            #[doc = concat!("# use vax_floating::", stringify!($SelfT), ";")]
992            #[doc = concat!("assert_eq!(", stringify!($SelfT), "::from_bits(0).is_zero(), true);")]
993            #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN_POSITIVE.is_zero(), false);")]
994            #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.is_zero(), false);")]
995            #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.is_zero(), false);")]
996            /// // As long as the sign and exponent is zero, it is considered to be zero.
997            #[doc = concat!("assert_eq!(", stringify!($SelfT), "::from_bits(0xFFFF0000_",
998                stringify!($ux), ").is_zero(), true);")]
999            /// ```
1000            #[inline]
1001            pub const fn is_zero(&self) -> bool { 0 == (self.0 & (Self::SIGN | Self::EXP_MASK)) }
1002
1003            #[doc = concat!("Return `true` if the `", stringify!($SelfT), "` is negative.")]
1004            ///
1005            /// # Examples
1006            ///
1007            /// ```rust
1008            #[doc = concat!("# use vax_floating::", stringify!($SelfT), ";")]
1009            #[doc = concat!("assert_eq!(", stringify!($SelfT), "::from_bits(0).is_negative(), false);")]
1010            #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN_POSITIVE.is_negative(), false);")]
1011            #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.is_negative(), false);")]
1012            #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.is_negative(), true);")]
1013            /// // All reserved values have the sign bit set, but are not negative.
1014            #[doc = concat!("assert_eq!(", stringify!($SelfT), "::from_bits(0x8000_",
1015                stringify!($ux), ").is_negative(), false);")]
1016            /// ```
1017            #[inline]
1018            pub const fn is_negative(&self) -> bool {
1019                0 != ((self.0 & Self::SIGN)) && (0 != (self.0 & Self::EXP_MASK))
1020            }
1021
1022            #[doc = concat!("Return `true` if the `", stringify!($SelfT), "` is reserved.")]
1023            ///
1024            /// # Examples
1025            ///
1026            /// ```rust
1027            #[doc = concat!("# use vax_floating::", stringify!($SelfT), ";")]
1028            #[doc = concat!("assert_eq!(", stringify!($SelfT), "::from_bits(0).is_reserved(), false);")]
1029            #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN_POSITIVE.is_reserved(), false);")]
1030            #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.is_reserved(), false);")]
1031            #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.is_reserved(), false);")]
1032            /// // As long as the sign is negative and exponent is zero, it is considered reserved.
1033            #[doc = concat!("assert_eq!(", stringify!($SelfT), "::from_bits(0x8000_",
1034                stringify!($ux), ").is_reserved(), true);")]
1035            #[doc = concat!("assert_eq!(", stringify!($SelfT), "::from_bits(0xFFFF8000_",
1036                stringify!($ux), ").is_reserved(), true);")]
1037            /// ```
1038            #[inline]
1039            pub const fn is_reserved(&self) -> bool { Self::SIGN == (self.0 & (Self::SIGN | Self::EXP_MASK)) }
1040
1041            #[doc = concat!("Force the sign of the `", stringify!($SelfT), "` to positive.")]
1042            ///
1043            /// # Examples
1044            ///
1045            /// ```rust
1046            #[doc = concat!("# use vax_floating::", stringify!($SelfT), ";")]
1047            /// for (case, abs) in [
1048            ///     (0_f32, 0_f32), // Zero doesn't have a sign.
1049            ///     (1.5, 1.5),    // Positive isn't changed.
1050            ///     (-3.14, 3.14),  // Negative to positive.
1051            ///     (-0.04, 0.04),  // Negative to positive.
1052            /// ].iter() {
1053            #[doc = concat!("    assert_eq!(", stringify!($SelfT), "::from_f32(*case).abs(), ", stringify!($SelfT), "::from_f32(*abs));")]
1054            /// }
1055            /// ```
1056            #[inline]
1057            pub const fn abs(self) -> Self { Self(self.0 & !Self::SIGN) }
1058
1059            #[doc = concat!("Negate the sign of the `", stringify!($SelfT), "` value.")]
1060            ///
1061            /// # Examples
1062            ///
1063            /// ```rust
1064            #[doc = concat!("# use vax_floating::", stringify!($SelfT), ";")]
1065            /// for (case, neg) in [
1066            ///     (0_f32, 0_f32), // Zero doesn't have a sign.
1067            ///     (1.5, -1.5),    // Positive to negative.
1068            ///     (-3.14, 3.14),  // Negative to positive.
1069            /// ].iter() {
1070            #[doc = concat!("    assert_eq!(", stringify!($SelfT), "::from_f32(*case).negate(), ", stringify!($SelfT), "::from_f32(*neg));")]
1071            /// }
1072            /// ```
1073            pub const fn negate(self) -> Self {
1074                if 0 != (self.0 & Self::EXP_MASK) { Self(self.0 ^ Self::SIGN) }
1075                else { self }
1076            }
1077
1078            #[doc = concat!("Return the sign of the `", stringify!($SelfT), "` value.")]
1079            ///
1080            /// # Examples
1081            ///
1082            /// ```rust
1083            #[doc = concat!("# use vax_floating::{", stringify!($SelfT), ", arithmetic::Sign};")]
1084            /// for (case, sign) in [
1085            ///     (-0.0_f32, Sign::Positive),
1086            ///     (1.5, Sign::Positive),
1087            ///     (-3.14, Sign::Negative),
1088            /// ].iter() {
1089            #[doc = concat!("    assert_eq!(", stringify!($SelfT), "::from_f32(*case).sign(), *sign);")]
1090            /// }
1091            /// ```
1092            pub const fn sign(&self) -> Sign {
1093                if 0 == (self.0 & Self::SIGN) {
1094                    Sign::Positive
1095                }
1096                else {
1097                    Sign::Negative
1098                }
1099            }
1100
1101            #[doc = concat!("Add a `", stringify!($SelfT), "` to another `",
1102                stringify!($SelfT), "`.")]
1103            ///
1104            /// # Examples
1105            ///
1106            /// ```rust
1107            #[doc = concat!("# use vax_floating::", stringify!($SelfT), ";")]
1108            #[doc = concat!("const NINETEEN_POINT_FIVE: ", stringify!($SelfT), " = ",
1109                stringify!($SelfT), "::from_u8(17).add_to(", stringify!($SelfT),
1110                "::from_f32(2.5));")]
1111            #[doc = concat!("let seventeen = ", stringify!($SelfT), "::from_u8(17);")]
1112            #[doc = concat!("let two_point_five = ", stringify!($SelfT), "::from_f32(2.5);")]
1113            /// assert_eq!(seventeen + two_point_five, NINETEEN_POINT_FIVE);
1114            /// ```
1115            ///
1116            /// This is the same as the addition (`+`) operator, except it can be used to
1117            /// define constants.
1118            ///
1119            /// ```compile_fail
1120            #[doc = concat!("# use vax_floating::", stringify!($SelfT), ";")]
1121            #[doc = concat!("const NINETEEN_POINT_FIVE: ", stringify!($SelfT), " = ",
1122                stringify!($SelfT), "::from_u8(17) + ", stringify!($SelfT), "::from_f32(2.5);")]
1123            /// ```
1124            pub const fn add_to(self, other: Self) -> Self {
1125                Self::from_fp(self.to_fp().add_to(other.to_fp(), false))
1126            }
1127
1128            #[doc = concat!("Subtract a `", stringify!($SelfT), "` from another `",
1129                stringify!($SelfT), "`.")]
1130            ///
1131            /// # Examples
1132            ///
1133            /// ```rust
1134            #[doc = concat!("# use vax_floating::", stringify!($SelfT), ";")]
1135            #[doc = concat!("const FOURTEEN_POINT_FIVE: ", stringify!($SelfT), " = ",
1136                stringify!($SelfT), "::from_u8(17).subtract_by(", stringify!($SelfT),
1137                "::from_f32(2.5));")]
1138            #[doc = concat!("let seventeen = ", stringify!($SelfT), "::from_u8(17);")]
1139            #[doc = concat!("let two_point_five = ", stringify!($SelfT), "::from_f32(2.5);")]
1140            /// assert_eq!(seventeen - two_point_five, FOURTEEN_POINT_FIVE);
1141            /// ```
1142            ///
1143            /// This is the same as the subtraction (`-`) operator, except it can be used to
1144            /// define constants.
1145            ///
1146            /// ```compile_fail
1147            #[doc = concat!("# use vax_floating::", stringify!($SelfT), ";")]
1148            #[doc = concat!("const FOURTEEN_POINT_FIVE: ", stringify!($SelfT), " = ",
1149                stringify!($SelfT), "::from_u8(17) - ", stringify!($SelfT), "::from_f32(2.5);")]
1150            /// ```
1151            pub const fn subtract_by(self, other: Self) -> Self {
1152                Self::from_fp(self.to_fp().add_to(other.to_fp(), true))
1153            }
1154
1155            #[doc = concat!("Multiply a `", stringify!($SelfT), "` by another `",
1156                stringify!($SelfT), "`.")]
1157            ///
1158            /// # Examples
1159            ///
1160            /// ```rust
1161            #[doc = concat!("# use vax_floating::", stringify!($SelfT), ";")]
1162            #[doc = concat!("const SEVENTEEN_TIMES_TWENTY_THREE: ", stringify!($SelfT), " = ",
1163                stringify!($SelfT), "::from_u8(17).multiply_by(", stringify!($SelfT),
1164                "::from_u8(23));")]
1165            #[doc = concat!("let seventeen = ", stringify!($SelfT), "::from_u8(17);")]
1166            #[doc = concat!("let twenty_three = ", stringify!($SelfT), "::from_u8(23);")]
1167            /// assert_eq!(seventeen * twenty_three, SEVENTEEN_TIMES_TWENTY_THREE);
1168            /// ```
1169            ///
1170            /// This is the same as the multiplication (`*`) operator, except it can be used to
1171            /// define constants.
1172            ///
1173            /// ```compile_fail
1174            #[doc = concat!("# use vax_floating::", stringify!($SelfT), ";")]
1175            #[doc = concat!("const SEVENTEEN_TIMES_TWENTY_THREE: ", stringify!($SelfT), " = ",
1176                stringify!($SelfT), "::from_u8(17) * ", stringify!($SelfT), "::from_u8(23);")]
1177            /// ```
1178            pub const fn multiply_by(self, multiplier: Self) -> Self {
1179                Self::from_fp(self.to_fp().multiply_by(multiplier.to_fp()))
1180            }
1181
1182            #[doc = concat!("Divide a `", stringify!($SelfT), "` by another `",
1183                stringify!($SelfT), "`.")]
1184            ///
1185            /// # Examples
1186            ///
1187            /// ```rust
1188            #[doc = concat!("# use vax_floating::", stringify!($SelfT), ";")]
1189            #[doc = concat!("const TWENTY_TWO_SEVENTHS: ", stringify!($SelfT), " = ",
1190                stringify!($SelfT), "::from_u8(22).divide_by(", stringify!($SelfT),
1191                "::from_u8(7));")]
1192            #[doc = concat!("let twenty_two = ", stringify!($SelfT), "::from_u8(22);")]
1193            #[doc = concat!("let seven = ", stringify!($SelfT), "::from_u8(7);")]
1194            /// assert_eq!(twenty_two / seven, TWENTY_TWO_SEVENTHS);
1195            /// ```
1196            ///
1197            /// This is the same as the division (`/`) operator, except it can be used to define
1198            /// constants.
1199            ///
1200            /// ```compile_fail
1201            #[doc = concat!("# use vax_floating::", stringify!($SelfT), ";")]
1202            #[doc = concat!("const TWENTY_TWO_SEVENTHS: ", stringify!($SelfT), " = ", stringify!($SelfT),
1203                "::from_u8(22) / ", stringify!($SelfT), "::from_u8(7);")]
1204            /// ```
1205            pub const fn divide_by(self, divisor: Self) -> Self {
1206                Self::from_fp(self.to_fp().divide_by(divisor.to_fp(), Self::DIV_PRECISION))
1207            }
1208
1209            #[doc = concat!("Convert from a `", stringify!($SelfT), "` to a `VaxFloatingPoint<", stringify!($ux), ">`.")]
1210            ///
1211            /// VaxFloatingPoint is used internally for performing mathmatical operations. Since
1212            #[doc = concat!("the `VaxFloatingPoint<", stringify!($ux),
1213                ">` type has more precision (it uses the entire", stringify!($ux), ")")]
1214            /// and supports exponent values outside the range of the
1215            #[doc = concat!(stringify!($SelfT), "(", $VaxName, ")")]
1216            /// floating-point type, it may be useful for some calculations.
1217            ///
1218            /// # Examples
1219            ///
1220            /// ```rust
1221            #[doc = concat!("# use vax_floating::{", stringify!($SelfT), ", VaxFloatingPoint};")]
1222            #[doc = concat!("const TWO: VaxFloatingPoint<", stringify!($ux), "> = ", stringify!($SelfT),
1223                "::from_ascii(\"2\").to_fp();")]
1224            #[doc = concat!("const THREE: VaxFloatingPoint<", stringify!($ux),
1225                "> = VaxFloatingPoint::<", stringify!($ux), ">::from_u8(3);")]
1226            #[doc = concat!("const TWO_THIRDS_MAX: ", stringify!($SelfT), " = ",
1227                stringify!($SelfT), "::MAX.divide_by(", stringify!($SelfT),
1228                "::from_u8(3)).multiply_by(", stringify!($SelfT), "::from_u8(2));")]
1229            #[doc = concat!("let fp = ", stringify!($SelfT), "::MAX.to_fp();")]
1230            /// let invalid = fp * TWO;
1231            /// let two_thirds = invalid / THREE;
1232            #[doc = concat!("assert_eq!(", stringify!($SelfT),
1233                "::from_fp(two_thirds), TWO_THIRDS_MAX);")]
1234            #[doc = concat!("assert!(", stringify!($SelfT), "::from_fp(invalid).is_reserved());")]
1235            /// ```
1236            pub const fn to_fp(&self) -> VaxFloatingPoint<$ux> {
1237                match (self.0 & Self::EXP_MASK) >> Self::EXP_SHIFT {
1238                    0 => match self.to_fault() {
1239                        None => VaxFloatingPoint::<$ux>::ZERO,
1240                        Some(fault) => VaxFloatingPoint::<$ux>::from_fault(fault),
1241                    }
1242                    exp => unsafe { VaxFloatingPoint::<$ux>::new_unchecked(
1243                            self.sign(),
1244                            (exp as i32) - Self::EXP_BIAS,
1245                            Self::swap_words(self.0 & Self::FRAC_MASK) << Self::FP_FRAC_SHIFT |
1246                                (1 << (<$ux>::BITS - 1)),
1247                    ) },
1248                }
1249            }
1250
1251            #[doc = concat!("Convert from a `VaxFloatingPoint<", stringify!($ux), ">` to a `",
1252                stringify!($SelfT), "`.")]
1253            ///
1254            /// VaxFloatingPoint is used internally for performing mathmatical operations. Since
1255            #[doc = concat!("the `VaxFloatingPoint<", stringify!($ux),
1256                ">` type has more precision (it uses the entire", stringify!($ux), ")")]
1257            /// and supports exponent values outside the range of the
1258            #[doc = concat!(stringify!($SelfT), "(", $VaxName, ")")]
1259            /// floating-point type, it may be useful for some calculations.
1260            ///
1261            /// # Examples
1262            ///
1263            /// ```rust
1264            #[doc = concat!("# use vax_floating::{", stringify!($SelfT), ", VaxFloatingPoint};")]
1265            #[doc = concat!("const TWO: VaxFloatingPoint<", stringify!($ux), "> = ", stringify!($SelfT),
1266                "::from_ascii(\"2\").to_fp();")]
1267            #[doc = concat!("const THREE: VaxFloatingPoint<", stringify!($ux),
1268                "> = VaxFloatingPoint::<", stringify!($ux), ">::from_u8(3);")]
1269            #[doc = concat!("const TWO_THIRDS_MAX: ", stringify!($SelfT), " = ",
1270                stringify!($SelfT), "::MAX.divide_by(", stringify!($SelfT),
1271                "::from_u8(3)).multiply_by(", stringify!($SelfT), "::from_u8(2));")]
1272            #[doc = concat!("let fp = ", stringify!($SelfT), "::MAX.to_fp();")]
1273            /// let invalid = fp * TWO;
1274            /// let two_thirds = invalid / THREE;
1275            #[doc = concat!("assert_eq!(", stringify!($SelfT),
1276                "::from_fp(two_thirds), TWO_THIRDS_MAX);")]
1277            #[doc = concat!("assert!(", stringify!($SelfT), "::from_fp(invalid).is_reserved());")]
1278            /// ```
1279            pub const fn from_fp(fp: VaxFloatingPoint<$ux>) -> Self {
1280                if let Some(fault) = fp.fault() { Self::from_fault(fault) }
1281                else if fp.is_zero() { Self(0) }
1282                else {
1283                    let fp = fp.round_fraction(Self::FP_FRAC_ROUND);
1284                    let exp = ((fp.exponent() + Self::EXP_BIAS) << Self::EXP_SHIFT) as $ux;
1285                    if 0 == (exp & Self::EXP_MASK) || 0 != (exp & !Self::EXP_MASK) {
1286                        if 0 >= (fp.exponent() + Self::EXP_BIAS) {
1287                            Self::from_underflow(Some(fp.exponent()))
1288                        }
1289                        else {
1290                            Self::from_overflow(Some(fp.exponent()))
1291                        }
1292                    }
1293                    else {
1294                        Self((Self::swap_words(fp.fraction() >> Self::FP_FRAC_SHIFT) & Self::FRAC_MASK) |
1295                            exp | if fp.sign().is_negative() { Self::SIGN } else { 0 })
1296                    }
1297                }
1298            }
1299
1300            #[doc = concat!("Parse a string slice into a `", stringify!($SelfT), "`.")]
1301            ///
1302            /// # Panics
1303            ///
1304            /// This will panic if it fails to parse the string.
1305            ///
1306            /// # Examples
1307            ///
1308            /// ```rust
1309            #[doc = concat!("# use vax_floating::", stringify!($SelfT), ";")]
1310            #[doc = concat!("const TWELVE_DOT_FIVE: ", stringify!($SelfT), " = ", stringify!($SelfT),
1311                "::from_ascii(\"12.5\");")]
1312            #[doc = concat!("assert_eq!(", stringify!($SelfT), "::from_f32(12.5), TWELVE_DOT_FIVE);")]
1313            /// ```
1314            ///
1315            /// Invalid input strings will fail to compile.
1316            ///
1317            /// ```compile_fail
1318            #[doc = concat!("# use vax_floating::", stringify!($SelfT), ";")]
1319            #[doc = concat!("const TWO_DECIMAL_POINTS: ", stringify!($SelfT), " = ", stringify!($SelfT),
1320                "::from_ascii(\"..\");")]
1321            /// ```
1322            ///
1323            /// Unlike [`FromStr::from_str`], `from_ascii` can be used to define constants.
1324            ///
1325            /// ```compile_fail
1326            #[doc = concat!("# use vax_floating::", stringify!($SelfT), ";")]
1327            /// # use std::str::FromStr;
1328            #[doc = concat!("const TWELVE_DOT_FIVE: ", stringify!($SelfT), " = ", stringify!($SelfT),
1329                "::from_str(\"12.5\").unwrap();")]
1330            /// ```
1331            pub const fn from_ascii(text: &str) -> $SelfT {
1332                match Self::from_ascii_inner(text) {
1333                    Ok(me) => me,
1334                    Err(_) => { panic!("Failed to parse input string within from_ascii()"); }
1335                }
1336            }
1337
1338            #[doc = concat!("Internal function that Parses a string slice into a `",
1339                stringify!($SelfT), "`.")]
1340            const fn from_ascii_inner(text: &str) -> std::result::Result<$SelfT, &str> {
1341                match VaxFloatingPoint::<$ux>::from_ascii(text, Self::ASCII_MASK) {
1342                    Ok(vfp) => Ok(Self::from_fp(vfp)),
1343                    Err(s) => Err(s),
1344                }
1345            }
1346
1347            #[doc = concat!("Convert an [`Error::Underflow`] to the corresponding reserved value of a `",
1348                stringify!($SelfT), "`.")]
1349            const fn from_underflow(exp: Option<i32>) -> $SelfT {
1350                const UNDERFLOW: $ux = $SelfT::SIGN | (0b01 << $SelfT::RESERVED_SHIFT);
1351                match exp {
1352                    None => Self(UNDERFLOW),
1353                    Some(exp) => Self(UNDERFLOW | if exp < (i16::MIN as i32) {
1354                        0
1355                    }
1356                    else {
1357                        ((exp as $ux) & 0xFFFF) << Self::RESERVED_OVER_UNDER_SHIFT
1358                    }),
1359                }
1360            }
1361
1362            #[doc = concat!("Convert an [`Error::Overflow`] to the corresponding reserved value of a `",
1363                stringify!($SelfT), "`.")]
1364            const fn from_overflow(exp: Option<i32>) -> $SelfT {
1365                const OVERFLOW: $ux = $SelfT::SIGN | (0b10 << $SelfT::RESERVED_SHIFT);
1366                match exp {
1367                    None => Self(OVERFLOW),
1368                    Some(exp) => Self(OVERFLOW | if exp > (u16::MAX as i32) {
1369                        0
1370                    }
1371                    else {
1372                        ((exp as $ux) & 0xFFFF) << Self::RESERVED_OVER_UNDER_SHIFT
1373                    }),
1374                }
1375            }
1376
1377            #[doc = concat!("Convert an [`Error`] to the corresponding reserved value of a `",
1378                stringify!($SelfT), "`.")]
1379            const fn from_error(err: &Error) -> $SelfT {
1380                const DIV_BY_ZERO: $ux = $SelfT::SIGN;
1381                const RESERVED: $ux = $SelfT::SIGN | (0b11 << $SelfT::RESERVED_SHIFT);
1382                match err {
1383                    Error::DivByZero => $SelfT(DIV_BY_ZERO),
1384                    Error::Underflow(exp) => $SelfT::from_underflow(*exp),
1385                    Error::Overflow(exp) => $SelfT::from_overflow(*exp),
1386                    Error::Reserved | Error::InvalidStr(_) => $SelfT(RESERVED),
1387                }
1388            }
1389
1390            #[doc = concat!("Convert a [`Fault`] to the corresponding reserved value of a `",
1391                stringify!($SelfT), "`.")]
1392            const fn from_fault(fault: Fault) -> $SelfT {
1393                const DIV_BY_ZERO: $ux = $SelfT::SIGN;
1394                const UNDERFLOW: $ux = $SelfT::SIGN | (0b01 << $SelfT::RESERVED_SHIFT);
1395                const OVERFLOW: $ux = $SelfT::SIGN | (0b10 << $SelfT::RESERVED_SHIFT);
1396                const RESERVED: $ux = $SelfT::SIGN | (0b11 << $SelfT::RESERVED_SHIFT);
1397                match fault {
1398                    Fault::DivByZero => $SelfT(DIV_BY_ZERO),
1399                    Fault::Underflow => $SelfT(UNDERFLOW),
1400                    Fault::Overflow => $SelfT(OVERFLOW),
1401                    Fault::Reserved => $SelfT(RESERVED),
1402                }
1403            }
1404
1405            #[doc = concat!("Convert a `", stringify!($SelfT), "` to a [`Result`].")]
1406            ///
1407            /// All valid floating point values will be `Ok`, and encoded reserved values will
1408            /// return the corresponding `Err([Error])`.
1409            const fn to_result(self) -> Result<$SelfT> {
1410                if self.is_reserved() {
1411                    match (self.0 >> $SelfT::RESERVED_SHIFT) & 3 {
1412                        0b00 => Err(Error::DivByZero),
1413                        0b01 => Err(Error::Underflow(
1414                            match (self.0 >> $SelfT::RESERVED_OVER_UNDER_SHIFT) & 0xFFFF {
1415                                0 => None,
1416                                value => Some((value | 0xFFFF0000) as i32),
1417                            })),
1418                        0b10 => Err(Error::Overflow(
1419                            match (self.0 >> $SelfT::RESERVED_OVER_UNDER_SHIFT) & 0xFFFF {
1420                                0 => None,
1421                                value => Some(value as i32),
1422                            })),
1423                        0b11 => Err(Error::Reserved),
1424                        _ => unreachable!(),
1425                    }
1426                }
1427                else {
1428                    Ok(self)
1429                }
1430            }
1431
1432            #[doc = concat!("Convert a [`Fault`] to the corresponding reserved value of a `",
1433                stringify!($SelfT), "`.")]
1434            const fn to_fault(self) -> Option<Fault> {
1435                if self.is_reserved() {
1436                    match (self.0 >> $SelfT::RESERVED_SHIFT) & 3 {
1437                        0b00 => Some(Fault::DivByZero),
1438                        0b01 => Some(Fault::Underflow),
1439                        0b10 => Some(Fault::Overflow),
1440                        0b11 => Some(Fault::Reserved),
1441                        _ => unreachable!(),
1442                    }
1443                }
1444                else {
1445                    None
1446                }
1447            }
1448
1449            #[doc = concat!("Panic if the `",
1450                stringify!($SelfT), "` is not a valid value (i.e. reserved).")]
1451            ///
1452            /// This should be used when defining constants to check for errors.
1453            ///
1454            /// # Panics
1455            ///
1456            /// Panics if the value is reserved (i.e. sign bit set with exponent value of zero).
1457            ///
1458            /// # Examples
1459            ///
1460            /// ```rust
1461            #[doc = concat!("# use vax_floating::", stringify!($SelfT), ";")]
1462            #[doc = concat!("const TWELVE_DOT_FIVE: ", stringify!($SelfT), " = ", stringify!($SelfT),
1463                "::from_f32(12.5).unwrap();")]
1464            #[doc = concat!("assert_eq!(", stringify!($SelfT), "::from_f32(12.5), TWELVE_DOT_FIVE);")]
1465            /// ```
1466            ///
1467            /// ```compile_fail
1468            #[doc = concat!("# use vax_floating::", stringify!($SelfT), ";")]
1469            #[doc = concat!("const OVERFLOW: ", stringify!($SelfT), " = ", stringify!($SelfT),
1470                "::MAX.add_to(", stringify!($SelfT), "::MAX).unwrap();")]
1471            /// ```
1472            ///
1473            /// ```
1474            #[doc = concat!("# use vax_floating::", stringify!($SelfT), ";")]
1475            #[doc = concat!("const DIV_BY_ZERO: ", stringify!($SelfT), " = ", stringify!($SelfT),
1476                "::MAX.divide_by(", stringify!($SelfT), "::from_bits(0));")]
1477            /// // Without unwrap, sets constant to divide-by-zero encoded reserved value.
1478            #[doc = concat!("assert_eq!(", stringify!($SelfT), "::from_bits(0x8000), DIV_BY_ZERO);")]
1479            /// ```
1480            ///
1481            /// ```compile_fail
1482            #[doc = concat!("# use vax_floating::", stringify!($SelfT), ";")]
1483            #[doc = concat!("const DIV_BY_ZERO: ", stringify!($SelfT), " = ", stringify!($SelfT),
1484                "::MAX.divide_by(", stringify!($SelfT), "::from_bits(0)).unwrap();")]
1485            /// ```
1486            pub const fn unwrap(self) -> Self {
1487                if self.is_reserved() {
1488                    match (self.0 >> $SelfT::RESERVED_SHIFT) & 3 {
1489                        0b00 => { panic!("Divide by zero error"); }
1490                        0b01 => { panic!("Underflow error"); }
1491                        0b10 => { panic!("Overflow error"); }
1492                        0b11 => { panic!("Reserved operand fault"); }
1493                        _ => unreachable!(),
1494                    }
1495                }
1496                else {
1497                    self
1498                }
1499            }
1500
1501            #[doc = concat!("Return the defualt value if the `",
1502                stringify!($SelfT), "` is not valid (i.e. reserved).")]
1503            ///
1504            /// # Examples
1505            ///
1506            /// ```rust
1507            #[doc = concat!("# use vax_floating::", stringify!($SelfT), ";")]
1508            #[doc = concat!("const TWELVE_DOT_FIVE: ", stringify!($SelfT), " = ", stringify!($SelfT),
1509                "::from_f32(12.5).unwrap_or_default();")]
1510            #[doc = concat!("assert_eq!(", stringify!($SelfT), "::from_f32(12.5), TWELVE_DOT_FIVE);")]
1511            ///
1512            #[doc = concat!("const OVERFLOW: ", stringify!($SelfT), " = ", stringify!($SelfT),
1513                "::MAX.add_to(", stringify!($SelfT), "::MAX).unwrap_or_default();")]
1514            #[doc = concat!("assert_eq!(", stringify!($SelfT), "::default(), OVERFLOW);")]
1515            /// ```
1516            pub const fn unwrap_or_default(self) -> Self {
1517                if self.is_reserved() {
1518                    // default() is not const, but the following is. The `verify_float_defaults`
1519                    // test verifies that this is correct.
1520                    Self::from_bits(0)
1521                }
1522                else {
1523                    self
1524                }
1525            }
1526
1527            #[doc = concat!("Return an alternate value if the `",
1528                stringify!($SelfT), "` is not valid (i.e. reserved).")]
1529            ///
1530            /// # Examples
1531            ///
1532            /// ```rust
1533            #[doc = concat!("# use vax_floating::", stringify!($SelfT), ";")]
1534            #[doc = concat!("const TWELVE_DOT_FIVE: ", stringify!($SelfT), " = ", stringify!($SelfT),
1535                "::from_f32(12.5).unwrap_or(", stringify!($SelfT), "::MAX);")]
1536            #[doc = concat!("assert_eq!(", stringify!($SelfT), "::from_f32(12.5), TWELVE_DOT_FIVE);")]
1537            ///
1538            #[doc = concat!("const OVERFLOW: ", stringify!($SelfT), " = ", stringify!($SelfT),
1539                "::MAX.add_to(", stringify!($SelfT), "::MAX).unwrap_or(", stringify!($SelfT), "::MAX);")]
1540            #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX, OVERFLOW);")]
1541            /// ```
1542            pub const fn unwrap_or(self, default: Self) -> Self {
1543                if self.is_reserved() {
1544                    default
1545                }
1546                else {
1547                    self
1548                }
1549            }
1550
1551            #[doc = concat!("Returns the result from a closure if the `",
1552                stringify!($SelfT), "` is not valid (i.e. reserved).")]
1553            ///
1554            /// This is included for completeness, but it isn't const like the other `unwrap`
1555            /// functions.
1556            ///
1557            /// # Examples
1558            ///
1559            /// ```rust
1560            #[doc = concat!("# use vax_floating::", stringify!($SelfT), ";")]
1561            /// use vax_floating::Result;
1562            #[doc = concat!("fn saturate_float(float: ", stringify!($SelfT), ") -> ",
1563                stringify!($SelfT), " {")]
1564            ///     use vax_floating::Error::*;
1565            #[doc = concat!("    match <Result<", stringify!($SelfT), ">>::from(float) {")]
1566            ///         Ok(float) => float,
1567            #[doc = concat!("        Err(Overflow(_)) | Err(DivByZero) => ", stringify!($SelfT), "::MAX,")]
1568            #[doc = concat!("        Err(Underflow(_)) => ", stringify!($SelfT), "::MIN_POSITIVE,")]
1569            #[doc = concat!("        Err(_) => ", stringify!($SelfT), "::MIN,")]
1570            ///     }
1571            /// }
1572            ///
1573            #[doc = concat!("let twelve_dot_five: ", stringify!($SelfT), " = ", stringify!($SelfT),
1574                "::from_f32(12.5).unwrap_or_else(saturate_float);")]
1575            #[doc = concat!("assert_eq!(", stringify!($SelfT), "::from_f32(12.5), twelve_dot_five);")]
1576            ///
1577            #[doc = concat!("let overflow: ", stringify!($SelfT), " = ", stringify!($SelfT),
1578                "::MAX.add_to(", stringify!($SelfT), "::MAX).unwrap_or_else(saturate_float);")]
1579            #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX, overflow);")]
1580            /// ```
1581            pub fn unwrap_or_else<F: FnOnce(Self) -> Self>(self, op: F) -> Self {
1582                if self.is_reserved() {
1583                    op(self)
1584                }
1585                else {
1586                    self
1587                }
1588            }
1589
1590            from_rust_int_impl!($ux, $SelfT);
1591
1592            to_from_rust_fp_impl!($ux, $SelfT);
1593
1594            to_from_vax_float_impl!($ux, $SelfT);
1595        }
1596
1597        from_rust_int_impl!(From, $ux, $SelfT);
1598
1599        to_from_rust_fp_impl!(From, $ux, $SelfT);
1600
1601        to_from_vax_float_impl!(From, $SelfT);
1602
1603        impl From<$SelfT> for Result<$SelfT> {
1604            fn from(float: $SelfT) -> Result<$SelfT> {
1605                float.to_result()
1606            }
1607        }
1608
1609        impl From<Result<$SelfT>> for $SelfT {
1610            fn from(result: Result<$SelfT>) -> $SelfT {
1611                match result {
1612                    Ok(float) => float,
1613                    Err(err) => $SelfT::from_error(&err),
1614                }
1615            }
1616        }
1617
1618        impl Hash for $SelfT {
1619            fn hash<H: Hasher>(&self, state: &mut H) {
1620                const ZERO: $ux = 0;
1621                if self.is_zero() { ZERO.hash(state); }
1622                else { self.0.hash(state) }
1623            }
1624        }
1625
1626        impl PartialEq for $SelfT {
1627            fn eq(&self, other: &Self) -> bool {
1628                // All zeroes are equally zero.
1629                if self.is_zero() && other.is_zero() { true }
1630                else { self.0 == other.0 }
1631            }
1632        }
1633
1634        impl PartialOrd for $SelfT {
1635            fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1636                use Ordering::*;
1637                if self.is_reserved() || other.is_reserved() {
1638                    if self.0 == other.0 { return Some(Equal); }
1639                    return None;
1640                }
1641                match (self.is_zero(), other.is_zero()) {
1642                    (true, true) => Some(Equal),
1643                    (false, true) => match 0 == (self.0 & Self::SIGN) {
1644                        true => Some(Greater),
1645                        false => Some(Less),
1646                    }
1647                    (true, false) => match 0 == (other.0 & Self::SIGN) {
1648                        true => Some(Less),
1649                        false => Some(Greater),
1650                    }
1651                    (false, false) => {
1652                        if (0 != (self.0 & Self::SIGN)) ^ (0 != (other.0 & Self::SIGN)) {
1653                            match (0 != (self.0 & Self::SIGN)) {
1654                                false => Some(Greater),
1655                                true => Some(Less),
1656                            }
1657                        }
1658                        else {
1659                            match 0 != (self.0 & Self::SIGN) {
1660                                false => {
1661                                    Self::swap_words(self.0 & !Self::SIGN)
1662                                        .partial_cmp(&Self::swap_words(other.0 & !Self::SIGN))
1663                                }
1664                                true => {
1665                                    Self::swap_words(other.0 & !Self::SIGN)
1666                                        .partial_cmp(&Self::swap_words(self.0 & !Self::SIGN))
1667                                }
1668                            }
1669                        }
1670                    }
1671                }
1672            }
1673        }
1674
1675        impl Add for $SelfT {
1676            type Output = $SelfT;
1677
1678            fn add(self, rhs: Self) -> Self::Output {
1679                Self::from_fp(self.to_fp().add_to(rhs.to_fp(), false))
1680            }
1681        }
1682        forward_ref_binop!(impl Add, add for $SelfT, $SelfT);
1683
1684        impl AddAssign for $SelfT {
1685            #[inline]
1686            fn add_assign(&mut self, other: $SelfT) {
1687                *self = *self / other;
1688            }
1689        }
1690        forward_ref_op_assign! { impl AddAssign, add_assign for $SelfT, $SelfT }
1691
1692        impl Sub for $SelfT {
1693            type Output = $SelfT;
1694
1695            fn sub(self, rhs: Self) -> Self::Output {
1696                Self::from_fp(self.to_fp().add_to(rhs.to_fp(), true))
1697            }
1698        }
1699        forward_ref_binop!(impl Sub, sub for $SelfT, $SelfT);
1700
1701        impl SubAssign for $SelfT {
1702            #[inline]
1703            fn sub_assign(&mut self, other: $SelfT) {
1704                *self = *self / other;
1705            }
1706        }
1707        forward_ref_op_assign! { impl SubAssign, sub_assign for $SelfT, $SelfT }
1708
1709        impl Div for $SelfT {
1710            type Output = $SelfT;
1711
1712            fn div(self, rhs: Self) -> Self::Output {
1713                Self::from_fp(self.to_fp().divide_by(rhs.to_fp(), Self::DIV_PRECISION))
1714            }
1715        }
1716        forward_ref_binop!(impl Div, div for $SelfT, $SelfT);
1717
1718        impl DivAssign for $SelfT {
1719            #[inline]
1720            fn div_assign(&mut self, other: $SelfT) {
1721                *self = *self / other;
1722            }
1723        }
1724        forward_ref_op_assign! { impl DivAssign, div_assign for $SelfT, $SelfT }
1725
1726        impl Mul for $SelfT {
1727            type Output = $SelfT;
1728
1729            fn mul(self, rhs: Self) -> Self::Output {
1730                Self::from_fp(self.to_fp().multiply_by(rhs.to_fp()))
1731            }
1732        }
1733        forward_ref_binop!(impl Mul, mul for $SelfT, $SelfT);
1734
1735        impl MulAssign for $SelfT {
1736            #[inline]
1737            fn mul_assign(&mut self, other: $SelfT) {
1738                *self = *self * other;
1739            }
1740        }
1741        forward_ref_op_assign! { impl MulAssign, mul_assign for $SelfT, $SelfT }
1742
1743        sh_impl!($SelfT);
1744
1745        impl Neg for $SelfT {
1746            type Output = $SelfT;
1747
1748            #[inline]
1749            fn neg(self) -> Self::Output
1750            {
1751                self.negate()
1752            }
1753        }
1754        forward_ref_unop! { impl Neg, neg for $SelfT }
1755
1756        impl FromStr for $SelfT {
1757            type Err = Error;
1758
1759            fn from_str(s: &str) -> Result<$SelfT> {
1760                Ok($SelfT::from_ascii_inner(s)?)
1761            }
1762        }
1763
1764        impl Debug for $SelfT {
1765            fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
1766                let fp = self.to_fp();
1767                fmt.debug_struct(stringify!($SelfT))
1768                    .field("bits", &format_args!(zero_ext_hex!($SelfT), self.clone().to_bits()))
1769                    .field("sign", &format_args!("{:?}", fp.sign()))
1770                    .field("exponent", &format_args!("{0}", fp.exponent()))
1771                    .field("frac", &format_args!("{:#X}", fp.fraction()))
1772                    .finish()
1773            }
1774        }
1775
1776        impl Display for $SelfT {
1777            fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
1778                self.to_fp().float_to_decimal_display(fmt, Self::MANTISSA_DIGITS)
1779            }
1780        }
1781
1782        impl LowerExp for $SelfT {
1783            fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
1784                self.to_fp().float_to_exponential_common(fmt, Self::MANTISSA_DIGITS, false)
1785            }
1786        }
1787
1788        impl UpperExp for $SelfT {
1789            fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
1790                self.to_fp().float_to_exponential_common(fmt, Self::MANTISSA_DIGITS, true)
1791            }
1792        }
1793    };
1794}
1795
1796floating_impl!{
1797    Self = FFloating,
1798    ActualT = u32,
1799    ExpBits = 8,
1800    VaxName = "F_floating",
1801    swapped = "0x42480000",
1802    le_bytes = "[0x48, 0x42, 0x00, 0x00]",
1803    be_bytes = "[0x00, 0x00, 0x42, 0x48]",
1804}
1805
1806floating_impl!{
1807    Self = DFloating,
1808    ActualT = u64,
1809    ExpBits = 8,
1810    VaxName = "D_floating",
1811    swapped = "0x4248000000000000",
1812    le_bytes = "[0x48, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]",
1813    be_bytes = "[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x48]",
1814}
1815
1816floating_impl!{
1817    Self = GFloating,
1818    ActualT = u64,
1819    ExpBits = 11,
1820    VaxName = "G_floating",
1821    swapped = "0x4049000000000000",
1822    le_bytes = "[0x49, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]",
1823    be_bytes = "[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x49]",
1824}
1825
1826floating_impl!{
1827    Self = HFloating,
1828    ActualT = u128,
1829    ExpBits = 15,
1830    VaxName = "H_floating",
1831    swapped = "0x40049000000000000000000000000000",
1832    le_bytes = "[0x04, 0x40, 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, \
1833        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]",
1834    be_bytes = "[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
1835        0x00, 0x00, 0x00, 0x00, 0x90, 0x00, 0x40, 0x04]",
1836}
1837
1838#[cfg(test)]
1839mod tests {
1840    use super::{
1841        FFloating,
1842        DFloating,
1843        GFloating,
1844        HFloating,
1845        Sign,
1846        Error,
1847    };
1848    use proptest::prelude::*;
1849    use std::{
1850        cmp::{min, max},
1851        collections::hash_map::DefaultHasher,
1852        hash::{Hash, Hasher},
1853        str::FromStr,
1854    };
1855
1856    fn pi_str(size: usize) -> &'static str {
1857        static PI_STR: &'static str = "3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798609437027705392171762931767523846748184676694051320005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235420199561121290219608640344181598136297747713099605187072113499999983729780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083814206171776691473035982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989";
1858        if 0 == size { &PI_STR[..=0] }
1859        else if size < (PI_STR.len()-2) { &PI_STR[..(size+2)] }
1860        else { PI_STR }
1861    }
1862
1863    macro_rules! create_pi_test {
1864        ($name: ident, $floating: ident, $start: expr) => {
1865            #[test]
1866            fn $name() {
1867                let expected_pi = $floating::from_str(pi_str($start as usize)).unwrap();
1868                for i in (($start+1) as usize)..1000 {
1869                    let pi = $floating::from_str(pi_str(i)).unwrap();
1870                    assert_eq!(pi, expected_pi);
1871                }
1872            }
1873        };
1874    }
1875
1876    create_pi_test!(f_floating_pi_test, FFloating, FFloating::DIGITS+1);
1877    create_pi_test!(d_floating_pi_test, DFloating, DFloating::DIGITS+1);
1878    create_pi_test!(g_floating_pi_test, GFloating, GFloating::DIGITS);
1879    create_pi_test!(h_floating_pi_test, HFloating, HFloating::DIGITS);
1880
1881    const MAX_FFLOATING: f32 = unsafe { std::mem::transmute::<u32, f32>(0x7EFFFFFF) };
1882    const MIN_FFLOATING: f32 = unsafe { std::mem::transmute::<u32, f32>(0xFEFFFFFF) };
1883
1884    prop_compose! {
1885        fn ffloating_f32_range(min: f32, max: f32)(float in min..=max) -> f32 {
1886            float
1887        }
1888    }
1889
1890    prop_compose! {
1891        fn ffloating_range(min: f32, max: f32)(float in ffloating_f32_range(min, max)) -> FFloating {
1892            FFloating::from_f32(float)
1893        }
1894    }
1895
1896    prop_compose! {
1897        fn ffloating_f32()(float in ffloating_f32_range(MIN_FFLOATING, MAX_FFLOATING)) -> f32 {
1898            float
1899        }
1900    }
1901
1902    prop_compose! {
1903        fn ffloating()(float in ffloating_f32_range(MAX_FFLOATING, MIN_FFLOATING)) -> FFloating {
1904            FFloating::from_f32(float)
1905        }
1906    }
1907
1908    macro_rules! to_from_test {
1909        ($float: ident, $floating: ident) => {
1910            let floating = $floating::from_f32($float);
1911            let to_f32 = floating.to_f32();
1912            assert_eq!($float, to_f32, "{:?}, float bits = {:#X}, to_from bits = {:#X}", floating,
1913                $float.to_bits(), to_f32.to_bits());
1914        };
1915    }
1916
1917    proptest! {
1918        #[test]
1919        fn to_from_f32(float in ffloating_f32()) {
1920            to_from_test!(float, FFloating);
1921            to_from_test!(float, DFloating);
1922            to_from_test!(float, GFloating);
1923            to_from_test!(float, HFloating);
1924        }
1925    }
1926
1927    #[test]
1928    fn verify_float_defaults() {
1929        assert_eq!(FFloating::default(), FFloating::from_bits(0));
1930        assert_eq!(DFloating::default(), DFloating::from_bits(0));
1931        assert_eq!(GFloating::default(), GFloating::from_bits(0));
1932        assert_eq!(HFloating::default(), HFloating::from_bits(0));
1933    }
1934
1935    macro_rules! swap_words_test {
1936        ($ux: ident, $bytes: literal, $vax_type: ident, $start: ident, $swapped: ident) => {
1937            let mut start = [0_u8; $bytes];
1938            start.copy_from_slice(&$start[0..$bytes]);
1939            let start = $ux::from_ne_bytes(start);
1940            let mut swapped = [0_u8; $bytes];
1941            swapped.copy_from_slice(&$swapped[(16-$bytes)..16]);
1942            let swapped = $ux::from_ne_bytes(swapped);
1943            assert_eq!($vax_type::swap_words(start), swapped)//,
1944                //"start = {:X}; swapped = {:X}", start, swapped);
1945        };
1946    }
1947
1948    proptest! {
1949        #[test]
1950        fn swap_words(words in proptest::collection::vec(u16::MIN..=u16::MAX, 8..=8)) {
1951            let start_bytes: Vec<u8> = words.iter().map(|w| w.to_ne_bytes()).flatten().collect();
1952            let swapped_bytes: Vec<u8> = words.iter().rev().map(|w| w.to_ne_bytes()).flatten().collect();
1953            swap_words_test!(u128, 16, HFloating, start_bytes, swapped_bytes);
1954            swap_words_test!(u64, 8, GFloating, start_bytes, swapped_bytes);
1955            swap_words_test!(u64, 8, DFloating, start_bytes, swapped_bytes);
1956            swap_words_test!(u32, 4, FFloating, start_bytes, swapped_bytes);
1957        }
1958    }
1959
1960    fn calculate_hash<T: Hash>(t: &T) -> u64 {
1961        let mut s = DefaultHasher::new();
1962        t.hash(&mut s);
1963        s.finish()
1964    }
1965
1966    macro_rules! create_hash_eq_test {
1967        ($name: ident, $floating: ident, $ux: ident) => {
1968            proptest! {
1969                #[test]
1970                fn $name(bits1 in <$ux>::MIN..=<$ux>::MAX, bits2 in <$ux>::MIN..=<$ux>::MAX) {
1971                    let zero1 = bits1 & $floating::FRAC_MASK;
1972                    let zero2 = bits2 & $floating::FRAC_MASK;
1973                    let float1 = $floating::from_bits(bits1);
1974                    let float2 = $floating::from_bits(bits2);
1975                    let float_zero1 = $floating::from_bits(zero1);
1976                    let float_zero2 = $floating::from_bits(zero2);
1977                    if zero1 != bits1 {
1978                        assert_ne!(float1, float_zero1, "float1 should not be equal to float_zero1");
1979                    }
1980                    if zero2 != bits2 {
1981                        assert_ne!(float2, float_zero2, "float2 should not be equal to float_zero2");
1982                    }
1983                    if bits1 != bits2 {
1984                        assert_ne!(float1, float2, "float1 should not be equal to float2");
1985                    }
1986                    else {
1987                        assert_eq!(float1, float2, "float1 should be equal to float2");
1988                        assert_eq!(calculate_hash(&float1), calculate_hash(&float2),
1989                            "float1 hash should be equal to float2 hash");
1990                    }
1991                    // All zeroes are equal to each other.
1992                    assert_eq!(float_zero1, float_zero2, "float_zero1 should be equal to float_zero2");
1993                    assert_eq!(calculate_hash(&float_zero1), calculate_hash(&float_zero2),
1994                        "float_zero1 hash should be equal to float_zero2 hash");
1995                }
1996            }
1997        };
1998    }
1999
2000    create_hash_eq_test!(test_f_floating_hash_eq, FFloating, u32);
2001    create_hash_eq_test!(test_d_floating_hash_eq, DFloating, u64);
2002    create_hash_eq_test!(test_g_floating_hash_eq, GFloating, u64);
2003    create_hash_eq_test!(test_h_floating_hash_eq, HFloating, u128);
2004
2005    macro_rules! create_ordering_test {
2006        ($name: ident, $floating: ident, $ux: ident) => {
2007            #[test]
2008            fn $name() {
2009                use Sign::*;
2010                const MAX_FRAC: $ux = (1 << $floating::MANTISSA_DIGITS) - 1;
2011                static ORDERED_LIST: &'static [$floating] = &[
2012                    $floating::from_parts(Negative, $floating::MAX_EXP, MAX_FRAC),  // Minimum
2013                    $floating::from_parts(Negative, $floating::MAX_EXP, 0),
2014                    $floating::from_parts(Negative, 0, MAX_FRAC),  // -0.99999999
2015                    $floating::from_parts(Negative, 0, 0),  // -0.5
2016                    $floating::from_parts(Negative, $floating::MIN_EXP, MAX_FRAC),
2017                    $floating::from_parts(Negative, $floating::MIN_EXP, 0), // Max negative
2018                    $floating(0),   // 0
2019                    $floating::from_parts(Positive, $floating::MIN_EXP, 0), // Max positive
2020                    $floating::from_parts(Positive, $floating::MIN_EXP, MAX_FRAC),
2021                    $floating::from_parts(Positive, 0, 0),  // 0.5
2022                    $floating::from_parts(Positive, 0, MAX_FRAC),  // 0.99999999
2023                    $floating::from_parts(Positive, $floating::MAX_EXP, 0),
2024                    $floating::from_parts(Positive, $floating::MAX_EXP, MAX_FRAC),  // Maximum
2025                ];
2026                for i in 0..ORDERED_LIST.len() {
2027                    let leq = ORDERED_LIST[i];
2028                    for j in i..ORDERED_LIST.len() {
2029                        let geq = ORDERED_LIST[j];
2030                        assert!(leq <= geq,
2031                            "Comparison failed: {:X?} should be less than {:X?}, but it wasn't",
2032                            leq, geq);
2033                        assert!(geq >= leq,
2034                            "Comparison failed: {:X?} should be less than {:X?}, but it wasn't",
2035                            leq, geq);
2036                    }
2037                }
2038            }
2039        };
2040    }
2041
2042    create_ordering_test!(test_f_floating_ordering, FFloating, u32);
2043    create_ordering_test!(test_d_floating_ordering, DFloating, u64);
2044    create_ordering_test!(test_g_floating_ordering, GFloating, u64);
2045    create_ordering_test!(test_h_floating_ordering, HFloating, u128);
2046
2047    macro_rules! create_convert_test {
2048        ($name: ident, $floating: ident, $ux: ident) => {
2049            proptest! {
2050                #[test]
2051                fn $name(
2052                    frac in 0..((1 as $ux) << ($floating::MANTISSA_DIGITS)),
2053                    sign in 0..=1,
2054                ) {
2055                    let sign = if sign == 0 { '+' } else { '-' };
2056                    let int_text = format!("{}{}", sign, frac);
2057                    let float_text = format!("{}{}.0", sign, frac);
2058                    let exp_text = {
2059                        let (before, after) = int_text.split_at(2);
2060                        format!("{}.{}e{}", before, after, after.len())
2061                    };
2062                    let from_int_text = $floating::from_str(&int_text).unwrap();
2063                    let from_float_text = $floating::from_str(&float_text).unwrap();
2064                    let from_exp_text = $floating::from_str(&exp_text).unwrap();
2065                    let mut from_frac = $floating::from(frac);
2066                    if '-' == sign { from_frac = -from_frac; }
2067                    prop_assert_eq!(from_int_text, from_float_text);
2068                    prop_assert_eq!(from_int_text, from_exp_text);
2069                    prop_assert_eq!(from_int_text, from_frac);
2070                }
2071            }
2072        };
2073    }
2074
2075    create_convert_test!(convert_to_f_floating, FFloating, u32);
2076    create_convert_test!(convert_to_d_floating, DFloating, u64);
2077    create_convert_test!(convert_to_g_floating, GFloating, u64);
2078    create_convert_test!(convert_to_h_floating, HFloating, u128);
2079
2080    // This compares two display outputs to see if they are close enough to each other. This is to
2081    // compare the f32 to FFloating and f64 to GFloating. There are some rounding differences
2082    // between the VAX floating-point Display functions. This function compares the two strings and
2083    // check to see if they are within 2 of each other at the least significant digit.
2084    pub fn display_close_enough(disp1: &str, disp2: &str, ok_diff: usize, fail_msg: &str) -> u128 {
2085        if disp1 != disp2 {
2086            close_enough_inner(disp1.to_string(), disp2.to_string(), disp1, disp2, ok_diff, fail_msg)
2087        }
2088        else { 0 }
2089    }
2090
2091    // This compares two display outputs to see if they are close enough to each other. This is to
2092    // compare the f32 to FFloating and f64 to GFloating. There are some rounding differences
2093    // between the VAX floating-point Display functions. This function compares the two strings and
2094    // check to see if they are within 2 of each other at the least significant digit.
2095    //
2096    // There is probably a better way to do this, but this works for now.
2097    pub fn close_enough_inner(
2098        mut disp1: String,
2099        mut disp2: String,
2100        orig1: &str,
2101        orig2: &str,
2102        ok_diff: usize,
2103        fail_msg: &str,
2104    ) -> u128 {
2105        // Test and remove the sign.
2106        match disp1.get(0..=0) {
2107            Some("+") => if disp1.get(0..=0) == Some("+") {
2108                disp1.remove(0);
2109                disp2.remove(0);
2110            }
2111            else {
2112                panic!("Signs don't match don't match: {}\n left: {:?}\nright: {:?}", fail_msg, orig1, orig2);
2113            }
2114            Some("-") => if disp1.get(0..=0) == Some("-") {
2115                disp1.remove(0);
2116                disp2.remove(0);
2117            }
2118            else {
2119                panic!("Signs don't match don't match: {}\n left: {:?}\nright: {:?}", fail_msg, orig1, orig2);
2120            }
2121            _ => {}
2122        }
2123        // Check and remove exponent.
2124        if disp1.contains(['e', 'E']) {
2125            let (rem1, exp1) = disp1.rsplit_once(['e', 'E']).unwrap_or((&disp1, ""));
2126            let (rem2, exp2) = disp2.rsplit_once(['e', 'E']).unwrap_or((&disp2, ""));
2127            if exp1 != exp2 {
2128                panic!("Exponents don't match: {}\n left: {:?}\nright: {:?}", fail_msg, orig1, orig2);
2129            }
2130            disp1.truncate(rem1.len());
2131            disp2.truncate(rem2.len());
2132        }
2133        // Remove decimal places.
2134        match(disp1.find('.'), disp2.find('.')) {
2135            (Some(p1), Some(p2)) => {
2136                if p1 != p2 {
2137                    panic!("Decimal points don't line up: {}\n left: {:?}\nright: {:?}", fail_msg,
2138                        orig1, orig2);
2139                }
2140                disp1.remove(p1);
2141                disp2.remove(p2);
2142            }
2143            (None, Some(p2)) => {
2144                if disp1.len() != p2 {
2145                    panic!("Decimal points don't line up: {}\n left: {:?}\nright: {:?}", fail_msg,
2146                        orig1, orig2);
2147                }
2148                disp2.remove(p2);
2149            }
2150            (Some(p1), None) => {
2151                if p1 != disp2.len() {
2152                    panic!("Decimal points don't line up: {}\n left: {:?}\nright: {:?}", fail_msg,
2153                        orig1, orig2);
2154                }
2155                disp1.remove(p1);
2156            }
2157            (None, None) => {}
2158        }
2159        // Remove leading zeroes and verify that they are the same size.
2160        let no_lead1 = disp1.trim_start_matches('0');
2161        let no_lead2 = disp2.trim_start_matches('0');
2162        if 1 < (disp1.len() - no_lead1.len()).abs_diff(disp2.len() - no_lead2.len()) {
2163            panic!("Leading zeroes don't match: {}\n left: {:?}\nright: {:?}", fail_msg, orig1, orig2);
2164        }
2165        // Trim trailing zeroes and replace any size difference with zeroes.
2166        let no_tail1 = disp1.trim_end_matches('0');
2167        let no_tail2 = disp2.trim_end_matches('0');
2168        let remove_tail = min(disp1.len() - no_tail1.len(), disp2.len() - no_tail2.len());
2169        disp1.truncate(disp1.len() - remove_tail);
2170        disp2.truncate(disp2.len() - remove_tail);
2171        if disp1.len() > disp2.len() {
2172            for _ in 0..(disp1.len()-disp2.len()) {
2173                disp2.push('0');
2174            }
2175        }
2176        else if disp1.len() < disp2.len() {
2177            for _ in 0..(disp2.len()-disp1.len()) {
2178                disp1.push('0');
2179            }
2180        }
2181        let val1 = i128::from_str_radix(&disp1, 10)
2182            .expect(&format!("Failed to convert string to number ({:?}): {}\n left: {:?}\nright: {:?}",
2183                &disp1, fail_msg, orig1, orig2));
2184        let val2 = i128::from_str_radix(&disp2, 10)
2185            .expect(&format!("Failed to convert string to number ({:?}): {}\n left: {:?}\nright: {:?}",
2186                &disp2, fail_msg, orig1, orig2));
2187        let diff = val1.abs_diff(val2);
2188        if diff > (ok_diff as u128) {
2189            panic!("Values are too far apart ({}): {}\n left: {:?}\nright: {:?}", diff, fail_msg,
2190                orig1, orig2);
2191        }
2192        diff
2193    }
2194
2195    // This compares two display outputs to see if they are close enough to each other. This is to
2196    // compare the f32 to FFloating and f64 to GFloating. There are some rounding differences
2197    // between the VAX floating-point Display functions. This function compares the two strings and
2198    // and only compare the `digits` nost-significant digits.
2199    pub fn display_close_enough_2(disp1: &str, disp2: &str, digits: usize, precision: bool, fail_msg: &str) -> u128 {
2200        if disp1 != disp2 {
2201            close_enough_inner_2(disp1.to_string(), disp2.to_string(), disp1, disp2, digits, precision, fail_msg)
2202        }
2203        else { 0 }
2204    }
2205
2206    // This compares two display outputs to see if they are close enough to each other. This is to
2207    // compare the f32 to FFloating and f64 to GFloating. There are some rounding differences
2208    // between the VAX floating-point Display functions. This function compares the two strings and
2209    // and only compare the `digits` nost-significant digits.
2210    //
2211    // This is attempt number two to write this function. The original was having problems with
2212    // precision, because there seem to be issues with the Rust implementations with precision:
2213    //
2214    // Input: "+1.0e23" Format: "{:.1}"
2215    // g_floating: "100000000000000000000000.0"
2216    // f64:         "99999999999999991611392.0"
2217    // 15 digits:    ^^^^^^^^^^^^^^^
2218    //
2219    // It looks like it is not restricting the display digits to the number of valid digits (15)
2220    // and rounding appropriately. What we want to do extract the portion of the string that we
2221    // care about and just compare those.
2222    pub fn close_enough_inner_2(
2223        mut disp1: String,
2224        mut disp2: String,
2225        orig1: &str,
2226        orig2: &str,
2227        digits: usize,
2228        precision: bool,
2229        fail_msg: &str,
2230    ) -> u128 {
2231        // Test and remove the sign.
2232        match disp1.get(0..=0) {
2233            Some("+") => if disp1.get(0..=0) == Some("+") {
2234                disp1.remove(0);
2235                disp2.remove(0);
2236            }
2237            else {
2238                panic!("Signs don't match don't match: {}\n left: {:?}\nright: {:?}", fail_msg, orig1, orig2);
2239            }
2240            Some("-") => if disp1.get(0..=0) == Some("-") {
2241                disp1.remove(0);
2242                disp2.remove(0);
2243            }
2244            else {
2245                panic!("Signs don't match don't match: {}\n left: {:?}\nright: {:?}", fail_msg, orig1, orig2);
2246            }
2247            _ => {}
2248        }
2249        // Check and remove exponent.
2250        if disp1.contains(['e', 'E']) {
2251            let (rem1, exp1) = disp1.rsplit_once(['e', 'E']).unwrap_or((&disp1, ""));
2252            let (rem2, exp2) = disp2.rsplit_once(['e', 'E']).unwrap_or((&disp2, ""));
2253            if exp1 != exp2 {
2254                panic!("Exponents don't match: {}\n left: {:?}\nright: {:?}", fail_msg, orig1, orig2);
2255            }
2256            disp1.truncate(rem1.len());
2257            disp2.truncate(rem2.len());
2258        }
2259        // Find location of decimal place and first non-zero digit.
2260        let fp1 = match disp1.find('.') {
2261            None => disp1.len(),
2262            Some(fp1) => {
2263                disp1.remove(fp1);
2264                fp1
2265            }
2266        };
2267        let fp2 = match disp2.find('.') {
2268            None => disp2.len(),
2269            Some(fp2) => {
2270                disp2.remove(fp2);
2271                fp2
2272            }
2273        };
2274        if precision {
2275            if (disp1.len() - fp1) != (disp2.len() - fp2) {
2276                panic!("Precision mismatch: {}\n left: {:?}\nright: {:?}", fail_msg, orig1, orig2);
2277            }
2278        }
2279        let (val1, val2) = match (disp1.find(|c: char| ('1' <= c) && ('9' >= c)),
2280            disp2.find(|c: char| ('1' <= c) && ('9' >= c)))
2281        {
2282            (None, None) => (0, 0),
2283            (Some(digit1), None) => (
2284                u128::from_str_radix(&disp1[digit1..min(digit1+digits, disp1.len())], 10)
2285                    .expect(&format!("Failed to convert string to number ({:?}): {}\n left: {:?}\nright: {:?}",
2286                    &disp1, fail_msg, orig1, orig2)),
2287                0),
2288            (None, Some(digit2)) => (0,
2289                u128::from_str_radix(&disp2[digit2..min(digit2+digits, disp2.len())], 10)
2290                    .expect(&format!("Failed to convert string to number ({:?}): {}\n left: {:?}\nright: {:?}",
2291                    &disp2, fail_msg, orig1, orig2))),
2292            (Some(digit1), Some(digit2)) => {
2293                let offset = min((digit1 as isize)-(fp1 as isize), (digit2 as isize)-(fp2 as isize));
2294                let start1 = if 0 > ((fp1 as isize)+offset) {
2295                    for _ in 0..((fp1 as isize)+offset).unsigned_abs() {
2296                        disp1.insert(0, '0');
2297                    }
2298                    0
2299                }
2300                else {
2301                    ((fp1 as isize)+offset) as usize
2302                };
2303                let start2 = if 0 > ((fp2 as isize)+offset) {
2304                    for _ in 0..((fp2 as isize)+offset).unsigned_abs() {
2305                        disp2.insert(0, '0');
2306                    }
2307                    0
2308                }
2309                else {
2310                    ((fp2 as isize)+offset) as usize
2311                };
2312                let mut target_len = max(disp1.len()-start1, disp2.len()-start2);
2313                if target_len > digits { target_len = digits; }
2314                if disp1.len()-start1 > target_len {
2315                    disp1.truncate(start1 + target_len);
2316                }
2317                else if disp1.len()-start1 < target_len {
2318                    for _ in 0..(target_len+start1-disp1.len()) {
2319                        disp1.push('0');
2320                    }
2321                }
2322                if disp2.len()-start2 > target_len {
2323                    disp2.truncate(start2 + target_len);
2324                }
2325                else if disp2.len()-start2 < target_len {
2326                    for _ in 0..(target_len+start2-disp2.len()) {
2327                        disp2.push('0');
2328                    }
2329                }
2330                (
2331                    u128::from_str_radix(&disp1[start1..], 10)
2332                        .expect(&format!("Failed to convert string to number ({:?}): {}\n left: {:?}\nright: {:?}",
2333                        &disp1, fail_msg, orig1, orig2)),
2334                    u128::from_str_radix(&disp2[start2..], 10)
2335                        .expect(&format!("Failed to convert string to number ({:?}): {}\n left: {:?}\nright: {:?}",
2336                        &disp1, fail_msg, orig1, orig2))
2337                )
2338            }
2339        };
2340        let diff = val1.abs_diff(val2);
2341        if diff > (1 as u128) {
2342            panic!("Values are too far apart ({}): {}\n left: {:?}\nright: {:?}", diff, fail_msg,
2343                orig1, orig2);
2344        }
2345        diff
2346    }
2347
2348    macro_rules! display_case {
2349        ($fmt: literal, $floating: ident, $fx: ident, $text: ident) => {
2350            let vax_float = format!($fmt, $floating);
2351            let rust_float = format!($fmt, $fx);
2352            dbg!(&$text);
2353            display_close_enough(&vax_float, &rust_float, 2, &format!("input string = {:?}", $text));
2354        };
2355    }
2356
2357    macro_rules! create_display_test {
2358        ($name: ident, $floating: ident, $ux: ident, $fx: ident) => {
2359            create_display_test!($name, $floating, $ux, $fx, {
2360                "{}",
2361                "{:e}",
2362                "{:E}",
2363                "{:.0e}",
2364                "{:.0E}",
2365                "{:.1e}",
2366                "{:.1E}",
2367                "{:.2e}",
2368                "{:.2E}",
2369                "{:.3e}",
2370                "{:.3E}",
2371                "{:.4e}",
2372                "{:.4E}",
2373                "{:.5e}",
2374                "{:.5E}",
2375                "{:.6e}",
2376                "{:.6E}"
2377            });
2378        };
2379        ($name: ident, $floating: ident, $ux: ident, $fx: ident, $fmts: tt) => {
2380            create_display_test!($name, $floating, $ux, $fx, $fmts, $floating::MIN_10_EXP+1, $floating::MAX_10_EXP);
2381        };
2382        (
2383            $name: ident,
2384            $floating: ident,
2385            $ux: ident,
2386            $fx: ident,
2387            {$($fmt: literal),+},
2388            $min_exp: expr,
2389            $max_exp: expr
2390        ) => {
2391            proptest! {
2392                #[test]
2393                fn $name(
2394                    frac in 9..((1 as $ux) << ($floating::MANTISSA_DIGITS)),
2395                    exp in $min_exp..$max_exp,
2396                    sign in 0..=1,
2397                ) {
2398                    let sign = if sign == 0 { '+' } else { '-' };
2399                    let int_text = if 9 == frac { "0".to_string() } else { format!("{}", frac) };
2400                    let exp_text = {
2401                        let (before, mut after) = int_text.split_at(1);
2402                        if "" == after { after = "0"; }
2403                        format!("{}{}.{}e{}", sign, before, after, exp)
2404                    };
2405                    let mut rust_float = $fx::from_str(&exp_text).unwrap();
2406                    if rust_float == -0.0 { rust_float = 0.0; }
2407                    let vax_float = $floating::from_str(&exp_text).unwrap();
2408                    $(
2409                        display_case!($fmt, vax_float, rust_float, exp_text);
2410                    )+
2411                }
2412            }
2413        };
2414        ($name: ident, $floating: ident, $ux: ident) => {
2415            create_display_test!($name, $floating, $ux, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
2416            13, 14, 15, 16, 17});
2417        };
2418        ($name: ident, $floating: ident, $ux: ident, $fmts: tt) => {
2419            create_display_test!($name, $floating, $ux, $fmts, $floating::MIN_10_EXP+1, $floating::MAX_10_EXP);
2420        };
2421        (
2422            $name: ident,
2423            $floating: ident,
2424            $ux: ident,
2425            {$($prec: literal),+},
2426            $min_exp: expr,
2427            $max_exp: expr
2428        ) => {
2429            proptest! {
2430                #[test]
2431                fn $name(
2432                    frac in 9..((1 as $ux) << ($floating::MANTISSA_DIGITS)),
2433                    exp in $min_exp..$max_exp,
2434                    sign in 0..=1,
2435                ) {
2436                    let mut sign = if sign == 0 { "" } else { "-" };
2437                    let int_text = if 9 == frac {
2438                        sign = "";
2439                        "0".to_string()
2440                    } else { format!("{}", frac) };
2441                    let exp_text = {
2442                        let (before, mut after) = int_text.split_at(1);
2443                        if "" == after { after = "0"; }
2444                        format!("{}{}.{}e{}", sign, before, after, exp)
2445                    };
2446                    let vax_float = $floating::from_str(&exp_text).unwrap();
2447                    $(
2448                    {
2449                        let mut expected = if 0 > exp {
2450                            let leading_zeroes = (exp.unsigned_abs() - 1) as usize;
2451                            format!("{0}0.{3:0>1$}{2}", sign, leading_zeroes, int_text, "")
2452                        }
2453                        else {
2454                            let insert = (exp as usize) + 1;
2455                            if insert > int_text.len() {
2456                                let trailing_zeroes = if "0" == int_text { 0 } else {
2457                                    insert - int_text.len()
2458                                };
2459                                format!("{0}{1}{3:0>2$}.0", sign, int_text, trailing_zeroes, "")
2460                            }
2461                            else {
2462                                let (before, after) = int_text.split_at(insert);
2463                                format!("{0}{1}.{2}", sign, before, after)
2464                            }
2465                        };
2466                        let end = expected.find('.').unwrap_or(expected.len()) + $prec + 1;
2467                        if 0 == $prec { expected.truncate(end - 1); }
2468                        else if end < expected.len() { expected.truncate(end); }
2469                        else if end > expected.len() {
2470                            for _ in expected.len()..end {
2471                                expected.push('0');
2472                            }
2473                        }
2474                        let vax_float = format!("{0:.1$}", vax_float, $prec);
2475                        display_close_enough_2(&vax_float, &expected, $floating::DIGITS as usize, true, &format!("input string = {:?}", &exp_text));
2476                    }
2477                    )+
2478                }
2479            }
2480        };
2481    }
2482
2483    create_display_test!(display_f_floating, FFloating, u32, f32);
2484    create_display_test!(display_g_floating, GFloating, u64, f64);
2485    create_display_test!(display_g_floating_extra, GFloating, u64, f64, {
2486        "{:.7e}",
2487        "{:.7E}",
2488        "{:.8e}",
2489        "{:.8E}",
2490        "{:.9e}",
2491        "{:.9E}",
2492        "{:.10e}",
2493        "{:.10E}",
2494        "{:.11e}",
2495        "{:.11E}",
2496        "{:.12e}",
2497        "{:.12E}",
2498        "{:.13e}",
2499        "{:.13E}",
2500        "{:.14e}",
2501        "{:.14E}",
2502        "{:.15e}",
2503        "{:.15E}"
2504    });
2505    create_display_test!(display_d_floating, DFloating, u64, f64, {
2506        "{:.0e}",
2507        "{:.0E}",
2508        "{:.1e}",
2509        "{:.1E}",
2510        "{:.2e}",
2511        "{:.2E}",
2512        "{:.3e}",
2513        "{:.3E}",
2514        "{:.4e}",
2515        "{:.4E}",
2516        "{:.5e}",
2517        "{:.5E}",
2518        "{:.6e}",
2519        "{:.6E}",
2520        "{:.7e}",
2521        "{:.7E}",
2522        "{:.8e}",
2523        "{:.8E}",
2524        "{:.9e}",
2525        "{:.9E}",
2526        "{:.10e}",
2527        "{:.10E}",
2528        "{:.11e}",
2529        "{:.11E}",
2530        "{:.12e}",
2531        "{:.12E}",
2532        "{:.13e}",
2533        "{:.13E}",
2534        "{:.14e}",
2535        "{:.14E}",
2536        "{:.15e}",
2537        "{:.15E}"
2538    });
2539    create_display_test!(display_h_floating, HFloating, u128, f64, {
2540        "{:.0e}",
2541        "{:.0E}",
2542        "{:.1e}",
2543        "{:.1E}",
2544        "{:.2e}",
2545        "{:.2E}",
2546        "{:.3e}",
2547        "{:.3E}",
2548        "{:.4e}",
2549        "{:.4E}",
2550        "{:.5e}",
2551        "{:.5E}",
2552        "{:.6e}",
2553        "{:.6E}",
2554        "{:.7e}",
2555        "{:.7E}",
2556        "{:.8e}",
2557        "{:.8E}",
2558        "{:.9e}",
2559        "{:.9E}",
2560        "{:.10e}",
2561        "{:.10E}",
2562        "{:.11e}",
2563        "{:.11E}",
2564        "{:.12e}",
2565        "{:.12E}",
2566        "{:.13e}",
2567        "{:.13E}",
2568        "{:.14e}",
2569        "{:.14E}",
2570        "{:.15e}",
2571        "{:.15E}"
2572    }, f64::MIN_10_EXP+1, f64::MAX_10_EXP);
2573    //create_display_test!(display_f_floating_0, FFloating, u32, f32, {"{:.0}"}, FFloating::MIN_10_EXP+1, 7);
2574    //create_display_test!(display_f_floating_1, FFloating, u32, f32, {"{:.1}"}, FFloating::MIN_10_EXP+1, 7);
2575    //create_display_test!(display_f_floating_2, FFloating, u32, f32, {"{:.2}"}, FFloating::MIN_10_EXP+1, 7);
2576    create_display_test!(display_f_floating_precision, FFloating, u32);
2577    create_display_test!(display_d_floating_precision, DFloating, u64);
2578    create_display_test!(display_g_floating_precision, GFloating, u64);
2579    create_display_test!(display_h_floating_precision, HFloating, u128);
2580
2581    #[test]
2582    fn vax_reserved_and_results() {
2583        assert_eq!(FFloating::from_bits(0x8000).to_result(), Err(Error::DivByZero));
2584        assert_eq!(DFloating::from_bits(0x8000).to_result(), Err(Error::DivByZero));
2585        assert_eq!(GFloating::from_bits(0x8000).to_result(), Err(Error::DivByZero));
2586        assert_eq!(HFloating::from_bits(0x8000).to_result(), Err(Error::DivByZero));
2587        assert_eq!(FFloating::from_bits(0x8060).to_result(), Err(Error::Reserved));
2588        assert_eq!(DFloating::from_bits(0x8060).to_result(), Err(Error::Reserved));
2589        assert_eq!(GFloating::from_bits(0x800C).to_result(), Err(Error::Reserved));
2590        assert_eq!(HFloating::from_bits(0xC0008000).to_result(), Err(Error::Reserved));
2591        assert_eq!(FFloating::from_bits(0x8040).to_result(), Err(Error::Overflow(None)));
2592        assert_eq!(DFloating::from_bits(0x8040).to_result(), Err(Error::Overflow(None)));
2593        assert_eq!(GFloating::from_bits(0x8008).to_result(), Err(Error::Overflow(None)));
2594        assert_eq!(HFloating::from_bits(0x80008000).to_result(), Err(Error::Overflow(None)));
2595        assert_eq!(FFloating::from_bits(0x8020).to_result(), Err(Error::Underflow(None)));
2596        assert_eq!(DFloating::from_bits(0x8020).to_result(), Err(Error::Underflow(None)));
2597        assert_eq!(GFloating::from_bits(0x8004).to_result(), Err(Error::Underflow(None)));
2598        assert_eq!(HFloating::from_bits(0x40008000).to_result(), Err(Error::Underflow(None)));
2599        assert_eq!(FFloating::from_bits(0xFFFF8040).to_result(), Err(Error::Overflow(Some(65535))));
2600        assert_eq!(DFloating::from_bits(0xFFFF8040).to_result(), Err(Error::Overflow(Some(65535))));
2601        assert_eq!(GFloating::from_bits(0xFFFF8008).to_result(), Err(Error::Overflow(Some(65535))));
2602        assert_eq!(HFloating::from_bits(0xFFFF80008000).to_result(), Err(Error::Overflow(Some(65535))));
2603        assert_eq!(FFloating::from_bits(0x80008020).to_result(), Err(Error::Underflow(Some(-32768))));
2604        assert_eq!(DFloating::from_bits(0x80008020).to_result(), Err(Error::Underflow(Some(-32768))));
2605        assert_eq!(GFloating::from_bits(0x80008004).to_result(), Err(Error::Underflow(Some(-32768))));
2606        assert_eq!(HFloating::from_bits(0x800040008000).to_result(), Err(Error::Underflow(Some(-32768))));
2607    }
2608
2609    macro_rules! ilog10_test {
2610        ($ux: ty) => {
2611            let mut value: $ux = <$ux>::MAX;
2612            let ilog = value.ilog10();
2613            let display = format!("{}", value).len() - 1;
2614            let mut slow = 0_u32;
2615            while 10 <= value {
2616                slow += 1;
2617                value /= 10;
2618            }
2619            assert_eq!(ilog, slow);
2620            assert_eq!(ilog, display as u32);
2621        };
2622        ($ux: ty, $floating: ident) => {
2623            let mut value: $ux = 1 << $floating::MANTISSA_DIGITS;
2624            let ilog = value.ilog10();
2625            let display = format!("{}", value).len() - 1;
2626            let mut slow = 0_u32;
2627            while 10 <= value {
2628                slow += 1;
2629                value /= 10;
2630            }
2631            assert_eq!(ilog, slow);
2632            assert_eq!(ilog, display as u32);
2633        };
2634    }
2635
2636    #[test]
2637    fn alternate_ilog10() {
2638        ilog10_test!(u32, FFloating);
2639        ilog10_test!(u64, DFloating);
2640        ilog10_test!(u64, GFloating);
2641        ilog10_test!(u128, HFloating);
2642        ilog10_test!(u32);
2643        ilog10_test!(u64);
2644        ilog10_test!(u128);
2645    }
2646
2647    #[test]
2648    #[ignore]
2649    fn minor_display_bug_1() {
2650        const TENTH: DFloating = DFloating::from_ascii("0.1");
2651        const ONE_HUNDRED: FFloating = FFloating::from_u8(100);
2652        const MANY_ZEROES: HFloating = HFloating::from_u128(
2653            100_000_000_000_000_000_000_000_000_000_000u128);
2654        assert_eq!(&format!("{:e}", TENTH), "1e-1");
2655        assert_eq!(&format!("{:e}", ONE_HUNDRED), "1e2");   // Fails with 1.00e2
2656        assert_eq!(&format!("{:E}", MANY_ZEROES), "1E32");  // Fails with 1.00000000000000000000000000000000E32
2657    }
2658
2659    proptest! {
2660        fn from_h_floating_tests(
2661            h_floating in any::<HFloating>(),
2662        ) {
2663            let float_as_text = h_floating.to_string();
2664            let f_float = h_floating.to_f_floating();
2665            let d_float = h_floating.to_d_floating();
2666            let g_float = h_floating.to_g_floating();
2667            assert_eq!(f_float, FFloating::from_str(&float_as_text).unwrap());
2668            assert_eq!(d_float, DFloating::from_str(&float_as_text).unwrap());
2669            assert_eq!(g_float, GFloating::from_str(&float_as_text).unwrap());
2670        }
2671    }
2672
2673    proptest! {
2674        fn from_g_floating_tests(
2675            g_floating in any::<GFloating>(),
2676        ) {
2677            let float_as_text = g_floating.to_string();
2678            let f_float = g_floating.to_f_floating();
2679            let d_float = g_floating.to_d_floating();
2680            let h_float = g_floating.to_h_floating();
2681            assert_eq!(f_float, FFloating::from_str(&float_as_text).unwrap());
2682            assert_eq!(d_float, DFloating::from_str(&float_as_text).unwrap());
2683            assert_eq!(h_float, HFloating::from_str(&float_as_text).unwrap());
2684        }
2685    }
2686
2687    proptest! {
2688        fn from_d_floating_tests(
2689            d_floating in any::<DFloating>(),
2690        ) {
2691            let float_as_text = d_floating.to_string();
2692            let f_float = d_floating.to_f_floating();
2693            let g_float = d_floating.to_g_floating();
2694            let h_float = d_floating.to_h_floating();
2695            assert_eq!(f_float, FFloating::from_str(&float_as_text).unwrap());
2696            assert_eq!(g_float, GFloating::from_str(&float_as_text).unwrap());
2697            assert_eq!(h_float, HFloating::from_str(&float_as_text).unwrap());
2698        }
2699    }
2700
2701    proptest! {
2702        fn from_f_floating_tests(
2703            f_floating in any::<FFloating>(),
2704        ) {
2705            let float_as_text = f_floating.to_string();
2706            let d_float = f_floating.to_d_floating();
2707            let g_float = f_floating.to_g_floating();
2708            let h_float = f_floating.to_h_floating();
2709            assert_eq!(d_float, DFloating::from_str(&float_as_text).unwrap());
2710            assert_eq!(g_float, GFloating::from_str(&float_as_text).unwrap());
2711            assert_eq!(h_float, HFloating::from_str(&float_as_text).unwrap());
2712        }
2713    }
2714}