fast_posit/posit/convert/
mod.rs

1use super::*;
2
3// TODO add examples to docs after the impls (for ints, etc) are done
4
5/// Used to do value-to-value conversions using the rules prescribed for that conversion in the
6/// [posit standard], which may *round* the input (see below). It is the reciprocal of
7/// [`RoundInto`].
8///
9/// The interface is identical to the standard [`From`], but for the [conversions described in the
10/// posit standard]; therefore — unlike that which is the
11/// [convention for the `From` trait](core::convert::From#when-to-implement-from) —
12/// these conversions are _not necessarily lossless_, and may round if necessary, according the
13/// [definition in the posit standard].
14///
15/// The exact meaning of these conversions depends on the types involved; for the exact description
16/// of what each particular conversion does, **consult the documentation for specific
17/// implementations of `round_from`**.
18///
19/// Many of the usage guidelines for [`From`] also apply to [`RoundFrom`]: if you do implement it
20/// for your types, prefer implementing [`RoundFrom`] over [`RoundInto`] because implementing
21/// [`RoundFrom`] automatically provides one with an implementation of [`RoundInto`], and prefer
22/// using [`RoundInto`] over [`RoundFrom`] when specifying trait bounds on a generic function.
23/// There's also a blanket implementation of `RoundFrom<T> for T`, and `RoundFrom<T> for U`
24/// implies `RoundInto<U> for T`.
25///
26/// # Rounding
27///
28/// "Rounding" in this crate stands for the [definition in the posit standard]. In short:
29///
30///   - If the value is greater in absolute value than the biggest posit, round to it (i.e., never
31///     overflow).
32///   - If the value is smaller in absolute value than the smallest positive posit, round to it
33///     (i.e., never underflow).
34///   - Otherwise, round to the nearest bit pattern, or in case of a tie, to the even bit pattern.
35///
36/// # Examples
37///
38/// Rounding from ints, floats:
39/// ```
40/// # use fast_posit::*;
41/// assert!(p16::round_from(1) == p16::round_from(1.00000001));
42/// assert!(p32::round_from(1) <  p32::round_from(1.00000001));
43///
44/// assert_eq!(p32::round_from(f64::NAN), p32::NAR);
45/// ```
46///
47/// Rounding to ints, floats:
48/// ```
49/// # use fast_posit::*;
50/// assert_eq!(f32::round_from(p16::MIN_POSITIVE), 1.3877788e-17);
51/// assert_eq!(i64::round_from(p8::MAX), 1 << 24);
52///
53/// assert!(f64::round_from(p32::NAR).is_nan());
54/// ```
55///
56/// [posit standard]: https://posithub.org/docs/posit_standard-2.pdf#section.6
57/// [conversions described in the posit standard]: https://posithub.org/docs/posit_standard-2.pdf#section.6
58/// [definition in the posit standard]: https://posithub.org/docs/posit_standard-2.pdf#section.4
59pub trait RoundFrom<T> {
60  /// Converts to this type from the input type, [according to the rules prescribed in the posit
61  /// standard] for this particular conversion.
62  ///
63  /// This is the _rounding_ conversion that is specified in the posit standard (see
64  /// [Rounding](RoundFrom#rounding)); if you're looking for the usual Rust-y conversions
65  /// ([`From`] if exact, [`TryFrom`] if fallible), use those traits instead.
66  ///
67  /// [according to the rules prescribed in the posit standard]: https://posithub.org/docs/posit_standard-2.pdf#section.4
68  #[must_use]
69  fn round_from(value: T) -> Self;
70}
71
72/// Used to do value-to-value conversions using the rules prescribed for that conversion in the
73/// [posit standard], which may *round* the input (see below). It is the reciprocal of
74/// [`RoundFrom`].
75///
76/// The interface is identical to the standard [`Into`], but for the [conversions described in the
77/// posit standard]; therefore — unlike that which is the
78/// [convention for the `From` and `Into` traits](core::convert::From#when-to-implement-from) —
79/// these conversions are _not necessarily lossless_, and may round if necessary, according the
80/// [definition in the posit standard].
81///
82/// The exact meaning of these conversions depends on the types involved; for the exact description
83/// of what each particular conversion does, **consult the documentation for specific
84/// implementations of `round_from`**.
85///
86/// Many of the usage guidelines for [`Into`] also apply to [`RoundInto`]: if you do implement it
87/// for your types, prefer implementing [`RoundFrom`] over [`RoundInto`] because implementing
88/// [`RoundFrom`] automatically provides one with an implementation of [`RoundInto`], and prefer
89/// using [`RoundInto`] over [`RoundFrom`] when specifying trait bounds on a generic function.
90/// There's also a blanket implementation of `RoundInto<T> for T`, and `RoundFrom<T> for U`
91/// implies `RoundInto<U> for T`.
92///
93/// # Rounding
94///
95/// "Rounding" in this crate stands for the [definition in the posit standard]. In short:
96///
97///   - If the value is greater in absolute value than the biggest posit, round to it (i.e., never
98///     overflow).
99///   - If the value is smaller in absolute value than the smallest positive posit, round to it
100///     (i.e., never underflow).
101///   - Otherwise, round to the nearest bit pattern, or in case of a tie, to the even bit pattern.
102///
103/// # Examples
104///
105/// Rounding from ints, floats:
106/// ```
107/// # use fast_posit::*;
108/// assert_eq!(p16::ONE.next(), 1.0004883_f64.round_into());
109/// assert_eq!(p32::ONE.next(), 1.0000000075_f64.round_into());
110///
111/// assert_eq!(p32::NAR, f64::NAN.round_into());
112/// ```
113///
114/// Rounding to ints, floats:
115/// ```
116/// # use fast_posit::*;
117/// assert_eq!(5.960464477539063e-8, p8::MIN_POSITIVE.round_into());
118/// assert_eq!(1_i64 << 56, p16::MAX.round_into());
119///
120/// assert!(f64::is_nan(p32::NAR.round_into()));
121/// ```
122///
123/// [posit standard]: https://posithub.org/docs/posit_standard-2.pdf#section.6
124/// [conversions described in the posit standard]: https://posithub.org/docs/posit_standard-2.pdf#section.6
125/// [definition in the posit standard]: https://posithub.org/docs/posit_standard-2.pdf#section.4
126pub trait RoundInto<T> {
127  /// Converts this type into the (usually inferred) input type, [according to the rules prescribed
128  /// in the posit standard] for this particular conversion.
129  ///
130  /// This is the _rounding_ conversion that is specified in the posit standard (see
131  /// [Rounding](RoundInto#rounding)); if you're looking for the usual Rust-y conversions
132  /// ([`Into`] if exact, [`TryInto`] if fallible), use those traits instead.
133  ///
134  /// [according to the rules prescribed in the posit standard]: https://posithub.org/docs/posit_standard-2.pdf#section.4
135  #[must_use]
136  fn round_into(self) -> T;
137}
138
139impl<T> RoundFrom<T> for T {
140  fn round_from(value: T) -> Self {
141    value
142  }
143}
144
145impl<T, U> RoundInto<U> for T where U: RoundFrom<T> {
146  fn round_into(self) -> U {
147    U::round_from(self)
148  }
149}
150
151mod float;
152mod int;
153mod posit;