1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
//! This crate provides a correct, clean, flexible, and 🚀 *fast* software implementation of
//! [Posit arithmetic](https://posithub.org/docs/posit_standard-2.pdf).
//!
//! # Introduction
//!
//! Posits are an alternative floating point format proposed by John Gustafson in 2017, with the
//! first standard published in 2022. They have several interesting features that make them an
//! excellent replacement for traditional IEEE754 floats, in domains such as neural networks or
//! HPC.
//!
//! The following references are useful if you are not yet familiar with posits:
//!
//! - [Posit standard](https://posithub.org/docs/posit_standard-2.pdf) (2022)
//! - [Original extended paper](https://posithub.org/docs/Posits4.pdf) (2017)
//! - [Book](https://doi.org/10.1201/9781003466024 ) (2024)
//!
//! This crate aims to implement the entire posit standard and beyond, including features such as
//! arbitrary posit and quire sizes, bounded posits, etc. Versions prior to 1.0.0, however,
//! may be incomplete. Correctness is ensured via extensive testing against an oracle.
//!
//! # Usage
//!
//! The following is an extended tour over the main functionality of the crate, sort of in the
//! style of "learn X in Y minutes". For more information, refer to the documentation of specific
//! types and functions.
//!
//! Use standard posit types, or define your own.
//! ```
//! # use fast_posit::*;
//! use fast_posit::{p8, p16, p32, p64}; // Standard: n bits, 2 exponent bits
//! type MyPosit = Posit<24, 3, i32>; // Non-standard: 24 bits, 3 exponent bits
//! type MyBoundedPosit = Posit<32, 3, i32, 6>; // b-posit: 32 bits, 3 exponent bits, 6 max regime
//! ```
//!
//! Create posits from ints, IEEE floats, strings, constants, or a raw bit representation.
//! ```
//! # use fast_posit::*;
//! use fast_posit::{RoundFrom, RoundInto};
//! let a = p32::round_from(2.71_f64);
//! let b = p32::round_from(42_i32);
//! let c = p32::from_bits(0x7f001337);
//! let d = p32::MIN_POSITIVE;
//! ```
//!
//! Perform basic arithmetic and comparisons using the usual operators.
//! ```
//! # use fast_posit::*;
//! assert!(p16::round_from(2.14) + p16::ONE == p16::round_from(3.14));
//! assert!(p16::MIN_POSITIVE < 1e-15.round_into());
//! assert!(p16::round_from(-1.1).floor() == p16::round_from(-2));
//! ```
//!
//! Convert posits back to ints, IEEE floats, strings, or a raw bit representation.
//! ```
//! # use fast_posit::*;
//! assert_eq!(p8::ONE.to_bits(), 0b01000000);
//! assert_eq!(4_i32, p16::round_from(3.5).round_into());
//! assert_eq!(-f32::exp2(56.), p16::MIN.round_into());
//! ```
//!
//! Use a quire to calculate sums and dot products _without loss of precision_!
//! ```
//! # use fast_posit::*;
//! use fast_posit::{q8, q16, q32, q64};
//! let mut quire = q16::ZERO;
//! quire += p16::MAX;
//! quire += p16::round_from(0.1);
//! quire -= p16::MAX;
//! let result: p16 = quire.round_into();
//! // Correct result with the quire, no issues with rounding errors.
//! assert_eq!(result, p16::round_from(0.1));
//! // The same sum without the quire would give a wrong result, due to double rounding.
//! let posit = p16::MAX + p16::round_from(0.1) - p16::MAX;
//! assert_eq!(posit, p16::ZERO);
//! ```
//!
//! Dot products in the quire can give correct results with 32 bits even where IEEE floats fail
//! with 64 bits.
//! ```
//! # use fast_posit::*;
//! let a = [3.2e7, 1., -1., 8.0e7];
//! let b = [4.0e8, 1., -1., -1.6e8];
//! // Calculating the dot product with 64-bit IEEE floats yields an incorrect result.
//! let float: f64 = a.iter().zip(b.iter())
//! .map(|(x, y)| x * y)
//! .sum();
//! assert_eq!(float, 0.);
//! // Calculating the dot product with 32-bit posits and a quire yields the correct result.
//! let posit: p32 = a.iter().zip(b.iter())
//! .map(|(x, y)| (p32::round_from(*x), p32::round_from(*y)))
//! .fold(q32::ZERO, |mut q, (x, y)| { q.add_prod(x, y); q })
//! .round_into();
//! assert_eq!(posit, 2.round_into());
//! ```
//!
//! Use a quire per thread to ensure the result is the same _regardless of parallelisation_!
//! ```
//! # use fast_posit::*;
//! let mut quires = [q16::ZERO; 8];
//! for thread in 0..8 {
//! let local_quire = &mut quires[thread];
//! *local_quire += p16::round_from(123);
//! *local_quire += p16::round_from(456);
//! // ...
//! }
//! // Assemble the final result by summing the thread-local quires first, then converting to posit.
//! let [mut first, rest @ ..] = quires;
//! for i in rest {
//! first += &i
//! }
//! let result: p16 = first.round_into();
//! assert_eq!(result, p16::round_from(8 * (123 + 456)));
//! ```
//!
//! Use mixed-precision with no hassle; it's especially cheap when the ES is the same, such as
//! among the standard types.
//! ```
//! # use fast_posit::*;
//! let terms = [3, 7, 15, 1].map(p8::round_from); // https://oeis.org/A001203
//! let pi = {
//! let mut partial = p64::ZERO;
//! for i in terms[1..].iter().rev() {
//! partial = p64::ONE / (i.convert() + partial) // `i` upcasted p8→p64 essentially for free
//! }
//! terms[0].convert() + partial
//! };
//! assert!((3.141592.round_into() .. 3.141593.round_into()).contains(&pi));
//! ```
//!
//! Please refer to the documentation for each specific item for more details. Wherever a function
//! corresponds to a function in [the standard](https://posithub.org/docs/posit_standard-2.pdf),
//! this will be noted.
//!
//! # Performance
//!
//! In terms of performance, you can expect as a *very rough estimate* 70 to 350 Mops/s
//! (corresponding to about a 4–20× slowdown relative to native hw FPU operations) on an 11th gen
//! Intel x86 core at 3.80GHz. This is, as far as we're aware, faster (or at least as fast) than
//! any freely available software implementation of posit arithmetic.
//!
//! 
//!
//! Needless to say, both absolute performance and relative performance vs the FPU will vary
//! depending on your system.
//!
//! This crate includes benchmarks; run them with `cargo bench -F bench`.
pub use Posit;
pub use Quire;
pub use Int;
pub use ;
/// Standard-defined 8-bit posit (with 2-bit exponent and unbounded regime).
///
/// This type is defined in the [2022 standard](https://posithub.org/docs/posit_standard-2.pdf); it
/// is a special case of the generic [`Posit`] type. If you want a posit with arbitrary size `N`,
/// exponent size `ES`, and optionally maximum regime size `RS`, see [`Posit<N, ES, RS>`].
pub type p8 = ;
/// Standard-defined 16-bit posit (with 2-bit exponent and unbounded regime).
///
/// This type is defined in the [2022 standard](https://posithub.org/docs/posit_standard-2.pdf); it
/// is a special case of the generic [`Posit`] type. If you want a posit with arbitrary size `N`,
/// exponent size `ES`, and optionally maximum regime size `RS`, see [`Posit<N, ES, RS>`].
pub type p16 = ;
/// Standard-defined 32-bit posit (with 2-bit exponent and unbounded regime).
///
/// This type is defined in the [2022 standard](https://posithub.org/docs/posit_standard-2.pdf); it
/// is a special case of the generic [`Posit`] type. If you want a posit with arbitrary size `N`,
/// exponent size `ES`, and optionally maximum regime size `RS`, see [`Posit<N, ES, RS>`].
pub type p32 = ;
/// Standard-defined 64-bit posit (with 2-bit exponent and unbounded regime).
///
/// This type is defined in the [2022 standard](https://posithub.org/docs/posit_standard-2.pdf); it
/// is a special case of the generic [`Posit`] type. If you want a posit with arbitrary size `N`,
/// exponent size `ES`, and optionally maximum regime size `RS`, see [`Posit<N, ES, RS>`].
pub type p64 = ;
/// Standard-defined 128-bit quire for a [p8].
pub type q8 = ;
/// Standard-defined 256-bit quire for a [p16].
pub type q16 = ;
/// Standard-defined 512-bit quire for a [p32].
pub type q32 = ;
/// Standard-defined 1024-bit quire for a [p64].
pub type q64 = ;
/// Re-export some internals for benchmarking purposes, only on `feature = "bench"`.
/// Set the number of proptest cases globally.
///
/// This number strikes a balance between coverage and practicality.
const PROPTEST_CASES: u32 = if cfg! else ;