Skip to main content

fast_posit/posit/convert/
int.rs

1use super::*;
2
3use crate::underlying::const_as;
4
5/// The kernel for converting a _signed_ int to a posit.
6///
7/// # Safety
8///
9/// `int` cannot be `FromInt::ZERO` or `FromInt::MIN`, or calling this function is *undefined
10/// behaviour*.
11#[inline]
12unsafe fn round_from_kernel<
13  FromInt: crate::Int,
14  const N: u32,
15  const ES: u32,
16  Int: crate::Int,
17  const RS: u32,
18>(int: FromInt) -> (Decoded<N, ES, RS, Int>, Int) {
19  // If converting into a narrower type (`FromInt` → `Int`), we need to shift right, *before* we
20  // convert to the narrower type. Some bits will be lost in this conversion; we will accumulate
21  // them into `sticky`.
22  let shift_right = if const { Int::BITS >= FromInt::BITS } {0} else {FromInt::BITS - Int::BITS};
23
24  // If converting into a wider type (`FromInt` → `Int`), we need to shift left, *after* we convert
25  // to the wider type.
26  let shift_left = if const { Int::BITS <= FromInt::BITS } {0} else {Int::BITS - FromInt::BITS};
27
28  // To turn the `int` into a `frac` that starts with `0b01` or `0b10`, find the number of leading
29  // 0s or 1s, and shift left by that number of places minus one. To compensate, the `exp` has to
30  // be `FRAC_WIDTH` subtracted by the number of places we shifted. The `sticky` bits are the bits
31  // lost when shifting right.
32  //
33  // Examples:
34  //
35  //   value: 0b00010011 (= 19)
36  //    frac: 0b01001100
37  //     exp: +4 (= (8 - 2) frac width - 2 underflow)
38  //
39  //   value: 0b11111111 (= -1)
40  //    frac: 0b10000000
41  //     exp: -1 (= (8 - 2) frac width - 7 underflow)
42  //
43  // SAFETY: `int` is not 0 nor MIN (function precondition)
44  let underflow = unsafe { int.leading_run_minus_one() };
45  let frac = const_as::<FromInt, Int>(int << underflow >> shift_right) << shift_left;
46  let exp = {
47    let exp = Decoded::<N, ES, N, FromInt>::FRAC_WIDTH.wrapping_sub(underflow);
48    const_as::<i32, Int>(exp as i32)
49  };
50  let sticky = {
51    let true_shift = shift_right.saturating_sub(underflow);
52    Int::from(int.mask_lsb(true_shift) != FromInt::ZERO)
53  };
54
55  (Decoded{frac, exp}, sticky)
56}
57
58/// The kernel for converting a posit to a _signed_ int.
59#[inline]
60fn round_into_kernel<
61  ToInt: crate::Int,
62  const N: u32,
63  const ES: u32,
64  Int: crate::Int,
65  const RS: u32,
66>(decoded: Decoded<N, ES, RS, Int>) -> ToInt {
67  // If converting into a narrower type (`Int` → `ToInt`), we need to shift right, *before* we
68  // convert to the narrower type. Some bits will be lost in this conversion; we will accumulate
69  // them into `sticky`.
70  let diff_right = if const { ToInt::BITS >= Int::BITS } {0} else {Int::BITS - ToInt::BITS};
71
72  // If converting into a wider type (`Int` → `ToInt`), we may shift left, *after* we convert to
73  // the wider type.
74  let diff_left = if const { ToInt::BITS <= Int::BITS } {0} else {ToInt::BITS - Int::BITS};
75
76  // To convert `decoded` into an int, note that the value it represents is
77  //
78  //   frac × 2^-FRAC_WIDTH × 2^exp
79  //
80  // The integer part of this is the result, the fractional part determines the direction of the
81  // rounding (as always, the rounding is "round to nearest, ties to even"; to understand in more
82  // detail how this is implemented using `round` and `sticky` bits, see the comments in
83  // [`encode_regular_round`]).
84  //
85  // Examples:
86  //
87  //   19.0:
88  //      frac: 0b01_001100
89  //       exp: +4
90  //     shift: 6 frac width - 4 exp = 2
91  //     value: 0b00010011 = 19
92  //
93  //   -1.0:
94  //      frac: 0b10_000000
95  //       exp: -1 (= (8 - 2) frac width - 7 underflow)
96  //     shift: 6 frac width + 1 exp = 7
97  //     value: 0b11111111 = -1
98  //
99  //   19.5:
100  //      frac: 0b01_001110
101  //       exp: +4
102  //     shift: 6 frac width - 4 exp = 2
103  //     value: 0b00010100 = 20 (rounded up)
104  //
105  // Two points to keep in mind
106  //
107  //   - `ToInt` may be wider or narrower than the source posit's `Int`, so we must be careful in
108  //     doing the shift and casts in the right order
109  //   - The shift may be too big in either direction: if too big to the left it leads to overflow
110  //     (in which case `ToInt::MIN` is returned), and if too big to the right it leads to loss of
111  //     all bits (in which case `ToInt::ZERO` is returned).
112
113  // This is the amount that `frac` needs to be shifted right (or left, if negative).
114  let shift = Int::of_u32(Decoded::<N, ES, RS, Int>::FRAC_WIDTH).wrapping_sub(decoded.exp);
115
116  // If `shift` is negative: the `ToInt` type needs to be wide enough to hold the value.
117  if shift < Int::ZERO {
118    let shift_left = (-shift).as_u32();
119    if shift_left > diff_left {
120      // Too narrow, return `0b10000…`.
121      return ToInt::MIN;
122    }
123    const_as::<Int, ToInt>(decoded.frac) << shift_left
124  }
125  // If `shift` is exactly zero: the `ToInt` type cannot be any narrower.
126  else if shift == Int::ZERO {
127    if diff_right != 0 {
128      // Too narrow, return `0b10000…`.
129      return ToInt::MIN;
130    }
131    const_as::<Int, ToInt>(decoded.frac)
132  }
133  // If `shift` is greater than zero: the `ToInt` type needs to be wide enough to hold the value;
134  // also since we shift left we need to take care of rounding depending on what bits were lost.
135  else {
136    let shift_right = shift.as_u32();
137    if shift_right > Int::BITS {
138      // The whole thing is shifted out, return `0`.
139      return ToInt::ZERO;
140    }
141    if shift_right < diff_right {
142      // Too narrow, return `0b10000…`.
143      return ToInt::MIN;
144    }
145    // Rounding formula with round bit and sticky bit, for details see [`encode_regular_round`].
146    let sticky = decoded.frac.mask_lsb(shift_right - 1);
147    let int = decoded.frac >> (shift_right - 1);
148    let round = int.get_lsb();
149    let int = int >> 1;
150    let odd = int.get_lsb();
151    // Assemble the number, with the rounding rules.
152    //
153    // One detail: we use wrapping_add on round_up because, if the rounded value exceeds
154    // `ToInt::MAX`, when adding 1 we wrap around to `ToInt::MIN` = `0b1000…`, which is exactly
155    // what we want (example: if `i8::MAX` == 127, but the posit is 127.5, rounding up to 128
156    // exceeds the representable irange of `i8`, so we return `i8::MIN`).
157    let round_up: bool = round & (odd | (sticky != Int::ZERO));
158    const_as::<Int, ToInt>(int).wrapping_add(ToInt::from(round_up))
159  }
160}
161
162macro_rules! make_impl {
163  ($t:ty) => {
164    impl<
165      const N: u32,
166      const ES: u32,
167      Int: crate::Int,
168      const RS: u32,
169    > RoundFrom<$t> for Posit<N, ES, Int, RS> {
170      #[doc = concat!("Convert an `", stringify!($t), "` into a `Posit`, [rounding according to the standard]:")]
171      ///
172      #[doc = concat!("  - If the value is [`", stringify!($t), "::MIN`] (i.e. the value where the most significant bit is 1 and the rest are 0), it converts to [NaR](Posit::NAR).")]
173      ///   - Otherwise, the integer value is rounded (if necessary).
174      ///
175      /// [rounding according to the standard]: https://posithub.org/docs/posit_standard-2.pdf#subsection.6.4
176      fn round_from(value: $t) -> Self {
177        // Handle 0 and MIN. Remember that according to the standard, MIN (i.e. bit pattern
178        // 0b1000…), is converted to NaR, and NaR is converted to MIN.
179        if value == 0 { return Posit::ZERO }
180        if value == <$t>::MIN { return Posit::NAR }
181
182        // This piece of code is only necessary in really extreme cases, like converting i128::MAX
183        // to an 8-bit posit. But in those cases, we do need to guard against overflow on `exp`.
184        if const { <$t>::BITS as i128 > 1 << Decoded::<N, ES, RS, Int>::FRAC_WIDTH } {
185          let limit = 1 << (1 << Decoded::<N, ES, RS, Int>::FRAC_WIDTH);
186          if value >=  limit { return Posit::MAX }
187          if value <= -limit { return Posit::MIN }
188        }
189
190        // SAFETY: `value` is not 0 or MIN
191        let (result, sticky) = unsafe { round_from_kernel(value) };
192        // SAFETY: `frac` is not underflowing and `exp` cannot be greater than `FromInt::BITS`
193        unsafe { result.encode_regular_round(sticky) }
194      }
195    }
196
197    impl<
198      const N: u32,
199      const ES: u32,
200      Int: crate::Int,
201      const RS: u32,
202    > RoundFrom<Posit<N, ES, Int, RS>> for $t {
203      #[doc = concat!("Convert a `Posit` into an `", stringify!($t), "`, [rounding according to the standard]:")]
204      ///
205      #[doc = concat!("  - If the value is [NaR](Posit::NAR), or if overflows the target type, then it converts to [`", stringify!($t), "::MIN`] (i.e. the value where the most significant bit is 1 and the rest are 0).")]
206      ///   - Otherwise, it returns the nearest integer to `value`, rounding ties to even.
207      ///
208      /// [rounding according to the standard]: https://posithub.org/docs/posit_standard-2.pdf#subsection.6.4
209      // TODO examples? here and in the other conversions
210      fn round_from(value: Posit<N, ES, Int, RS>) -> Self {
211        if value == Posit::ZERO { return 0 }
212        if value == Posit::NAR { return <$t>::MIN }
213
214        // SAFETY: `value` is not 0 or NaR
215        let decoded = unsafe { value.decode_regular() };
216        round_into_kernel(decoded)
217      }
218    }
219  }
220}
221
222make_impl!{i8}
223make_impl!{i16}
224make_impl!{i32}
225make_impl!{i64}
226make_impl!{i128}
227
228#[cfg(test)]
229mod tests {
230  use super::*;
231  use malachite::rational::Rational;
232  use proptest::prelude::*;
233
234  mod int_to_posit {
235    use super::*;
236
237    /// Aux function: check that `int` is converted to a posit with the correct rounding.
238    fn is_correct_rounded<FromInt: crate::Int, const N: u32, const ES: u32, Int: crate::Int, const RS: u32>(
239      int: FromInt,
240    ) -> bool
241    where
242      FromInt: Into<Rational> + RoundInto<Posit<N, ES, Int, RS>>,
243      Rational: TryFrom<Posit<N, ES, Int, RS>, Error = super::rational::IsNaR>,
244    {
245      let posit: Posit<N, ES, Int, RS> = int.round_into();
246      if int == FromInt::MIN {
247        posit == Posit::NAR
248      } else {
249        let exact: Rational = int.into();
250        super::rational::is_correct_rounded(exact, posit)
251      }
252    }
253
254    macro_rules! make_exhaustive {
255      ($t:ident) => {
256        mod $t {
257          use super::*;
258
259          #[test]
260          fn posit_10_0_exhaustive() {
261            for int in $t::MIN ..= $t::MAX {
262              assert!(is_correct_rounded::<$t, 10, 0, i16, 10>(int), "{:?}", int)
263            }
264          }
265
266          #[test]
267          fn posit_10_1_exhaustive() {
268            for int in $t::MIN ..= $t::MAX {
269              assert!(is_correct_rounded::<$t, 10, 1, i16, 10>(int), "{:?}", int)
270            }
271          }
272
273          #[test]
274          fn posit_10_2_exhaustive() {
275            for int in $t::MIN ..= $t::MAX {
276              assert!(is_correct_rounded::<$t, 10, 2, i16, 10>(int), "{:?}", int)
277            }
278          }
279
280          #[test]
281          fn posit_10_3_exhaustive() {
282            for int in $t::MIN ..= $t::MAX {
283              assert!(is_correct_rounded::<$t, 10, 3, i16, 10>(int), "{:?}", int)
284            }
285          }
286
287          #[test]
288          fn posit_8_0_exhaustive() {
289            for int in $t::MIN ..= $t::MAX {
290              assert!(is_correct_rounded::<$t, 8, 0, i8, 8>(int), "{:?}", int)
291            }
292          }
293
294          #[test]
295          fn p8_exhaustive() {
296            for int in $t::MIN ..= $t::MAX {
297              assert!(is_correct_rounded::<$t, 8, 2, i8, 8>(int), "{:?}", int)
298            }
299          }
300
301          #[test]
302          fn p16_exhaustive() {
303            for int in $t::MIN ..= $t::MAX {
304              assert!(is_correct_rounded::<$t, 16, 2, i16, 16>(int), "{:?}", int)
305            }
306          }
307
308          #[test]
309          fn p32_exhaustive() {
310            for int in $t::MIN ..= $t::MAX {
311              assert!(is_correct_rounded::<$t, 32, 2, i32, 32>(int), "{:?}", int)
312            }
313          }
314
315          #[test]
316          fn p64_exhaustive() {
317            for int in $t::MIN ..= $t::MAX {
318              assert!(is_correct_rounded::<$t, 64, 2, i64, 64>(int), "{:?}", int)
319            }
320          }
321
322          #[test]
323          fn posit_3_0_exhaustive() {
324            for int in $t::MIN ..= $t::MAX {
325              assert!(is_correct_rounded::<$t, 3, 0, i8, 3>(int), "{:?}", int)
326            }
327          }
328
329          #[test]
330          fn posit_4_0_exhaustive() {
331            for int in $t::MIN ..= $t::MAX {
332              assert!(is_correct_rounded::<$t, 4, 0, i8, 4>(int), "{:?}", int)
333            }
334          }
335
336          #[test]
337          fn posit_4_1_exhaustive() {
338            for int in $t::MIN ..= $t::MAX {
339              assert!(is_correct_rounded::<$t, 4, 1, i8, 4>(int), "{:?}", int)
340            }
341          }
342
343          #[test]
344          fn bposit_8_3_6_proptest() {
345            for int in $t::MIN ..= $t::MAX {
346              assert!(is_correct_rounded::<$t, 8, 3, i8, 6>(int), "{:?}", int)
347            }
348          }
349
350          #[test]
351          fn bposit_16_5_6_proptest() {
352            for int in $t::MIN ..= $t::MAX {
353              assert!(is_correct_rounded::<$t, 16, 5, i16, 6>(int), "{:?}", int)
354            }
355          }
356
357          #[test]
358          fn bposit_32_5_6_proptest() {
359            for int in $t::MIN ..= $t::MAX {
360              assert!(is_correct_rounded::<$t, 32, 5, i32, 6>(int), "{:?}", int)
361            }
362          }
363
364          #[test]
365          fn bposit_64_5_6_proptest() {
366            for int in $t::MIN ..= $t::MAX {
367              assert!(is_correct_rounded::<$t, 64, 5, i64, 6>(int), "{:?}", int)
368            }
369          }
370
371          #[test]
372          fn bposit_10_2_6_proptest() {
373            for int in $t::MIN ..= $t::MAX {
374              assert!(is_correct_rounded::<$t, 10, 2, i16, 6>(int), "{:?}", int)
375            }
376          }
377
378          #[test]
379          fn bposit_10_2_7_proptest() {
380            for int in $t::MIN ..= $t::MAX {
381              assert!(is_correct_rounded::<$t, 10, 2, i16, 7>(int), "{:?}", int)
382            }
383          }
384
385          #[test]
386          fn bposit_10_2_8_proptest() {
387            for int in $t::MIN ..= $t::MAX {
388              assert!(is_correct_rounded::<$t, 10, 2, i16, 8>(int), "{:?}", int)
389            }
390          }
391
392          #[test]
393          fn bposit_10_2_9_proptest() {
394            for int in $t::MIN ..= $t::MAX {
395              assert!(is_correct_rounded::<$t, 10, 2, i16, 9>(int), "{:?}", int)
396            }
397          }
398        }
399      }
400    }
401
402    macro_rules! make_proptest {
403      ($t:ident) => {
404        mod $t {
405          use super::*;
406
407          proptest!{
408            #![proptest_config(ProptestConfig::with_cases(crate::PROPTEST_CASES))]
409
410            #[test]
411            fn posit_10_0_proptest(int in any::<$t>()) {
412              assert!(is_correct_rounded::<$t, 10, 0, i16, 10>(int), "{:?}", int)
413            }
414
415            #[test]
416            fn posit_10_1_proptest(int in any::<$t>()) {
417              assert!(is_correct_rounded::<$t, 10, 1, i16, 10>(int), "{:?}", int)
418            }
419
420            #[test]
421            fn posit_10_2_proptest(int in any::<$t>()) {
422              assert!(is_correct_rounded::<$t, 10, 2, i16, 10>(int), "{:?}", int)
423            }
424
425            #[test]
426            fn posit_10_3_proptest(int in any::<$t>()) {
427              assert!(is_correct_rounded::<$t, 10, 3, i16, 10>(int), "{:?}", int)
428            }
429
430            #[test]
431            fn posit_8_0_proptest(int in any::<$t>()) {
432              assert!(is_correct_rounded::<$t, 8, 0, i8, 8>(int), "{:?}", int)
433            }
434
435            #[test]
436            fn p8_proptest(int in any::<$t>()) {
437              assert!(is_correct_rounded::<$t, 8, 2, i8, 8>(int), "{:?}", int)
438            }
439
440            #[test]
441            fn p16_proptest(int in any::<$t>()) {
442              assert!(is_correct_rounded::<$t, 16, 2, i16, 16>(int), "{:?}", int)
443            }
444
445            #[test]
446            fn p32_proptest(int in any::<$t>()) {
447              assert!(is_correct_rounded::<$t, 32, 2, i32, 32>(int), "{:?}", int)
448            }
449
450            #[test]
451            fn p64_proptest(int in any::<$t>()) {
452              assert!(is_correct_rounded::<$t, 64, 2, i64, 64>(int), "{:?}", int)
453            }
454
455            #[test]
456            fn posit_3_0_proptest(int in any::<$t>()) {
457              assert!(is_correct_rounded::<$t, 3, 0, i8, 3>(int), "{:?}", int)
458            }
459
460            #[test]
461            fn posit_4_0_proptest(int in any::<$t>()) {
462              assert!(is_correct_rounded::<$t, 4, 0, i8, 4>(int), "{:?}", int)
463            }
464
465            #[test]
466            fn posit_4_1_proptest(int in any::<$t>()) {
467              assert!(is_correct_rounded::<$t, 4, 1, i8, 4>(int), "{:?}", int)
468            }
469
470            #[test]
471            fn bposit_8_3_6_proptest(int in any::<$t>()) {
472              assert!(is_correct_rounded::<$t, 8, 3, i8, 6>(int), "{:?}", int)
473            }
474
475            #[test]
476            fn bposit_16_5_6_proptest(int in any::<$t>()) {
477              assert!(is_correct_rounded::<$t, 16, 5, i16, 6>(int), "{:?}", int)
478            }
479
480            #[test]
481            fn bposit_32_5_6_proptest(int in any::<$t>()) {
482              assert!(is_correct_rounded::<$t, 32, 5, i32, 6>(int), "{:?}", int)
483            }
484
485            #[test]
486            fn bposit_64_5_6_proptest(int in any::<$t>()) {
487              assert!(is_correct_rounded::<$t, 64, 5, i64, 6>(int), "{:?}", int)
488            }
489
490            #[test]
491            fn bposit_10_2_6_proptest(int in any::<$t>()) {
492              assert!(is_correct_rounded::<$t, 10, 2, i16, 6>(int), "{:?}", int)
493            }
494
495            #[test]
496            fn bposit_10_2_7_proptest(int in any::<$t>()) {
497              assert!(is_correct_rounded::<$t, 10, 2, i16, 7>(int), "{:?}", int)
498            }
499
500            #[test]
501            fn bposit_10_2_8_proptest(int in any::<$t>()) {
502              assert!(is_correct_rounded::<$t, 10, 2, i16, 8>(int), "{:?}", int)
503            }
504
505            #[test]
506            fn bposit_10_2_9_proptest(int in any::<$t>()) {
507              assert!(is_correct_rounded::<$t, 10, 2, i16, 9>(int), "{:?}", int)
508            }
509          }
510        }
511      }
512    }
513
514    make_exhaustive!{i8}
515    make_exhaustive!{i16}
516    make_proptest!{i32}
517    make_proptest!{i64}
518    make_proptest!{i128}
519  }
520
521  mod posit_to_int {
522    use super::*;
523
524    /// Aux function: check that `posit` rounds to `int`.
525    fn is_correct_rounded<ToInt: crate::Int, const N: u32, const ES: u32, Int: crate::Int, const RS: u32>(
526      posit: Posit<N, ES, Int, RS>,
527      int: ToInt,
528    ) -> bool
529    where
530      ToInt: RoundFrom<Posit<N, ES, Int, RS>>,
531      Rational: From<i32> + From<ToInt> + TryFrom<Posit<N, ES, Int, RS>, Error = super::rational::IsNaR>,
532      // TODO Why do I need the `From<i32>` bound hereeeeeee, rust pls fix
533    {
534      match Rational::try_from(posit) {
535        Ok(exact) => {
536          use malachite::base::num::arithmetic::traits::RoundToMultiple;
537          use malachite::base::rounding_modes::RoundingMode;
538          let rounded = exact.round_to_multiple(Rational::from(1), RoundingMode::Nearest).0;
539          if rounded > Rational::from(ToInt::MAX) {
540            int == ToInt::MIN
541          } else if rounded < Rational::from(ToInt::MIN) {
542            int == ToInt::MIN
543          } else {
544            Rational::from(int) == rounded
545          }
546        },
547        Err(super::rational::IsNaR) => {
548          int == ToInt::MIN
549        }
550      }
551    }
552
553    macro_rules! make_exhaustive {
554      ($name:ident, $t:ty) => {
555        mod $name {
556          use super::*;
557
558          #[test]
559          fn i8_exhaustive() {
560            for p in <$t>::cases_exhaustive_all() {
561              let int: i8 = p.round_into();
562              assert!(is_correct_rounded(p, int), "{p:?} {int}");
563            }
564          }
565
566          #[test]
567          fn i16_exhaustive() {
568            for p in <$t>::cases_exhaustive_all() {
569              let int: i16 = p.round_into();
570              assert!(is_correct_rounded(p, int), "{p:?} {int}");
571            }
572          }
573
574          #[test]
575          fn i32_exhaustive() {
576            for p in <$t>::cases_exhaustive_all() {
577              let int: i32 = p.round_into();
578              assert!(is_correct_rounded(p, int), "{p:?} {int}");
579            }
580          }
581
582          #[test]
583          fn i64_exhaustive() {
584            for p in <$t>::cases_exhaustive_all() {
585              let int: i64 = p.round_into();
586              assert!(is_correct_rounded(p, int), "{p:?} {int}");
587            }
588          }
589
590          #[test]
591          fn i128_exhaustive() {
592            for p in <$t>::cases_exhaustive_all() {
593              let int: i128 = p.round_into();
594              assert!(is_correct_rounded(p, int), "{p:?} {int}");
595            }
596          }
597        }
598      }
599    }
600
601    macro_rules! make_proptest {
602      ($name:ident, $t:ty) => {
603        mod $name {
604          use super::*;
605
606          proptest!{
607            #![proptest_config(ProptestConfig::with_cases(crate::PROPTEST_CASES))]
608
609            #[test]
610            fn i8_proptest(p in <$t>::cases_proptest_all()) {
611              let int: i8 = p.round_into();
612              assert!(is_correct_rounded(p, int), "{p:?} {int}");
613            }
614
615            #[test]
616            fn i16_proptest(p in <$t>::cases_proptest_all()) {
617              let int: i16 = p.round_into();
618              assert!(is_correct_rounded(p, int), "{p:?} {int}");
619            }
620
621            #[test]
622            fn i32_proptest(p in <$t>::cases_proptest_all()) {
623              let int: i32 = p.round_into();
624              assert!(is_correct_rounded(p, int), "{p:?} {int}");
625            }
626
627            #[test]
628            fn i64_proptest(p in <$t>::cases_proptest_all()) {
629              let int: i64 = p.round_into();
630              assert!(is_correct_rounded(p, int), "{p:?} {int}");
631            }
632
633            #[test]
634            fn i128_proptest(p in <$t>::cases_proptest_all()) {
635              let int: i128 = p.round_into();
636              assert!(is_correct_rounded(p, int), "{p:?} {int}");
637            }
638          }
639        }
640      }
641    }
642
643    make_exhaustive!{posit_10_0, Posit<10, 0, i16>}
644    make_exhaustive!{posit_10_1, Posit<10, 1, i16>}
645    make_exhaustive!{posit_10_2, Posit<10, 2, i16>}
646    make_exhaustive!{posit_10_3, Posit<10, 3, i16>}
647    make_exhaustive!{posit_8_0,  Posit<8,  0, i8 >}
648    make_exhaustive!{p8, crate::p8}
649    make_exhaustive!{p16, crate::p16}
650    make_proptest!{p32, crate::p32}
651    make_proptest!{p64, crate::p64}
652    make_exhaustive!{posit_3_0, Posit::<3, 0, i8>}
653    make_exhaustive!{posit_4_0, Posit::<4, 0, i8>}
654    make_exhaustive!{posit_4_1, Posit::<4, 1, i8>}
655    make_exhaustive!{bposit_8_3_6,  Posit::<8, 3, i8, 6>}
656    make_exhaustive!{bposit_16_5_6, Posit::<16, 5, i16, 6>}
657    make_proptest!{bposit_32_5_6, Posit::<32, 5, i32, 6>}
658    make_proptest!{bposit_64_5_6, Posit::<64, 5, i64, 6>}
659    make_exhaustive!{bposit_10_2_6, Posit::<10, 2, i16, 6>}
660    make_exhaustive!{bposit_10_2_7, Posit::<10, 2, i16, 7>}
661    make_exhaustive!{bposit_10_2_8, Posit::<10, 2, i16, 8>}
662    make_exhaustive!{bposit_10_2_9, Posit::<10, 2, i16, 9>}
663  }
664}