malachite_float/lib.rs
1// Copyright © 2025 Mikhail Hogrefe
2//
3// This file is part of Malachite.
4//
5// Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU
6// Lesser General Public License (LGPL) as published by the Free Software Foundation; either version
7// 3 of the License, or (at your option) any later version. See <https://www.gnu.org/licenses/>.
8
9//! This crate defines [`Float`]s, which are arbitrary-precision floating-point numbers.
10//!
11//! [`Float`]s are currently experimental. They are missing many important functions. However, the
12//! functions that are currently implemented are thoroughly tested and documented, with the
13//! exception of string conversion functions. The current string conversions are incomplete and
14//! will be changed in the future to match MPFR's behavior.
15//!
16//! # Demos and benchmarks
17//! This crate comes with a `bin` target that can be used for running demos and benchmarks.
18//! - Almost all of the public functions in this crate have an associated demo. Running a demo
19//! shows you a function's behavior on a large number of inputs. TODO
20//! - You can use a similar command to run benchmarks. TODO
21//!
22//! The list of available demos and benchmarks is not documented anywhere; you must find them by
23//! browsing through
24//! [`bin_util/demo_and_bench`](https://github.com/mhogrefe/malachite/tree/master/malachite-float/src/bin_util/demo_and_bench).
25//!
26//! # Features
27//! - `32_bit_limbs`: Sets the type of [`Limb`](malachite_nz#limbs) to [`u32`] instead of the
28//! default, [`u64`].
29//! - `test_build`: A large proportion of the code in this crate is only used for testing. For a
30//! typical user, building this code would result in an unnecessarily long compilation time and
31//! an unnecessarily large binary. My solution is to only build this code when the `test_build`
32//! feature is enabled. If you want to run unit tests, you must enable `test_build`. However,
33//! doctests don't require it, since they only test the public interface.
34//! - `bin_build`: This feature is used to build the code for demos and benchmarks, which also
35//! takes a long time to build. Enabling this feature also enables `test_build`.
36
37#![allow(
38 unstable_name_collisions,
39 clippy::assertions_on_constants,
40 clippy::cognitive_complexity,
41 clippy::many_single_char_names,
42 clippy::range_plus_one,
43 clippy::suspicious_arithmetic_impl,
44 clippy::suspicious_op_assign_impl,
45 clippy::too_many_arguments,
46 clippy::type_complexity,
47 clippy::upper_case_acronyms,
48 clippy::multiple_bound_locations
49)]
50#![warn(
51 clippy::cast_lossless,
52 clippy::explicit_into_iter_loop,
53 clippy::explicit_iter_loop,
54 clippy::filter_map_next,
55 clippy::large_digit_groups,
56 clippy::manual_filter_map,
57 clippy::manual_find_map,
58 clippy::map_flatten,
59 clippy::map_unwrap_or,
60 clippy::match_same_arms,
61 clippy::missing_const_for_fn,
62 clippy::mut_mut,
63 clippy::needless_borrow,
64 clippy::needless_continue,
65 clippy::needless_pass_by_value,
66 clippy::print_stdout,
67 clippy::redundant_closure_for_method_calls,
68 clippy::single_match_else,
69 clippy::trait_duplication_in_bounds,
70 clippy::type_repetition_in_bounds,
71 clippy::uninlined_format_args,
72 clippy::unused_self,
73 clippy::if_not_else,
74 clippy::manual_assert,
75 clippy::range_plus_one,
76 clippy::redundant_else,
77 clippy::semicolon_if_nothing_returned,
78 clippy::cloned_instead_of_copied,
79 clippy::flat_map_option,
80 clippy::unnecessary_wraps,
81 clippy::unnested_or_patterns,
82 clippy::use_self,
83 clippy::trivially_copy_pass_by_ref
84)]
85#![cfg_attr(
86 not(any(feature = "test_build", feature = "random", feature = "std")),
87 no_std
88)]
89
90extern crate alloc;
91
92#[macro_use]
93extern crate malachite_base;
94
95#[cfg(feature = "test_build")]
96extern crate itertools;
97
98#[cfg(feature = "test_build")]
99use crate::InnerFloat::Finite;
100use core::ops::Deref;
101#[cfg(feature = "test_build")]
102use malachite_base::num::arithmetic::traits::DivisibleByPowerOf2;
103use malachite_base::num::basic::integers::PrimitiveInt;
104#[cfg(feature = "test_build")]
105use malachite_base::num::logic::traits::SignificantBits;
106use malachite_nz::natural::Natural;
107use malachite_nz::platform::Limb;
108
109/// A floating-point number.
110///
111/// `Float`s are currently experimental. They are missing many important functions. However, the
112/// functions that are currently implemented are thoroughly tested and documented, with the
113/// exception of string conversion functions. The current string conversions are incomplete and will
114/// be changed in the future to match MPFR's behavior.
115///
116/// `Float`s are similar to the primitive floats defined by the IEEE 754 standard. They include NaN,
117/// positive and $-\infty$, and positive and negative zero. There is only one NaN; there is no
118/// concept of a NaN payload.
119///
120/// All the finite `Float`s are dyadic rationals (rational numbers whose denominator is a power of
121/// 2). A finite `Float` consists of several fields:
122/// - a sign, which denotes whether the `Float` is positive or negative;
123/// - a significand, which is a [`Natural`] number whose value is equal to the `Float`'s absolute
124/// value multiplied by a power of 2;
125/// - an exponent, which is one more than the floor of the base-2 logarithm of the `Float`'s
126/// absolute value;
127/// - and finally, a precision, which is greater than zero and indicates the number of significant
128/// bits. It is common to think of a `Float` as an approximation to some real number, and the
129/// precision indicates how good the approximation is intended to be.
130///
131/// `Float`s inherit some odd behavior from the IEEE 754 standard regarding comparison. A `NaN` is
132/// not equal to any `Float`, including itself. Positive and negative zero compare as equal, despite
133/// being two distinct values. Additionally, (and this is not IEEE 754's fault), `Float`s with
134/// different precisions compare as equal if they represent the same numeric value.
135///
136/// In many cases, the above behavior is unsatisfactory, so the [`ComparableFloat`] and
137/// [`ComparableFloat`] wrappers are provided. See their documentation for a description of their
138/// comparison behavior.
139///
140/// In documentation, we will use the '$=$' sign to mean that two `Float`s are identical, writing
141/// things like $-\text{NaN}=\text{NaN}$ and $-(0.0) = -0.0$.
142///
143/// The `Float` type is designed to be very similar to the `mpfr_t` type in
144/// [MPFR](https://www.mpfr.org/mpfr-current/mpfr.html#Nomenclature-and-Types), and all Malachite
145/// functions produce exactly the same result as their counterparts in MPFR, unless otherwise noted.
146///
147/// Here are the structural difference between `Float` and `mpfr_t`:
148/// - `Float` can only represent a single `NaN` value, with no sign or payload.
149/// - Only finite, nonzero `Float`s have a significand, precision, and exponent. For other `Float`s,
150/// these concepts are undefined. In particular, unlike `mpfr_t` zeros, `Float` zeros do not have
151/// a precision.
152/// - The types of `mpfr_t` components are configuration- and platform-dependent. The types of
153/// `Float` components are platform-independent, although the `Limb` type is
154/// configuration-dependent: it is `u64` by default, but may be changed to `u32` using the
155/// `--32_bit_limbs` compiler flag. The type of the exponent is always `i32` and the type of the
156/// precision is always `u64`. The `Limb` type only has a visible effect on the functions that
157/// extract the raw significand. All other functions have the same interface when compiled with
158/// either `Limb` type.
159///
160/// `Float`s whose precision is 64 bits or less can be represented without any memory allocation.
161/// (Unless Malachite is compiled with `32_bit_limbs`, in which case the limit is 32).
162#[derive(Clone)]
163pub struct Float(pub(crate) InnerFloat);
164
165// We want to limit the visibility of the `NaN`, `Zero`, `Infinity`, and `Finite` constructors to
166// within this crate. To do this, we wrap the `InnerFloat` enum in a struct that gets compiled away.
167#[derive(Clone)]
168pub(crate) enum InnerFloat {
169 NaN,
170 Infinity {
171 sign: bool,
172 },
173 Zero {
174 sign: bool,
175 },
176 Finite {
177 sign: bool,
178 exponent: i32,
179 precision: u64,
180 significand: Natural,
181 },
182}
183
184#[inline]
185pub(crate) fn significand_bits(significand: &Natural) -> u64 {
186 significand.limb_count() << Limb::LOG_WIDTH
187}
188
189impl Float {
190 /// The maximum raw exponent of any [`Float`], equal to $2^{30}-1$, or $1,073,741,823$. This is
191 /// one more than the maximum scientific exponent. If we write a [`Float`] as $\pm m2^e$, with
192 /// $1\leq m<2$ and $e$ an integer, we must have $e\leq 2^{30}-2$. If the result of a
193 /// calculation would produce a [`Float`] with an exponent larger than this, $\pm\infty$ is
194 /// returned instead.
195 pub const MAX_EXPONENT: i32 = 0x3fff_ffff;
196 /// The minimum raw exponent of any [`Float`], equal to $-(2^{30}-1)$, or $-1,073,741,823$. This
197 /// is one more than the minimum scientific exponent. If we write a [`Float`] as $\pm m2^e$,
198 /// with $1\leq m<2$ and $e$ an integer, we must have $e\geq -2^{30}$. If the result of a
199 /// calculation would produce a [`Float`] with an exponent smaller than this, $\pm0.0$ is
200 /// returned instead.
201 pub const MIN_EXPONENT: i32 = -Self::MAX_EXPONENT;
202
203 #[cfg(feature = "test_build")]
204 pub fn is_valid(&self) -> bool {
205 match self {
206 Self(Finite {
207 precision,
208 significand,
209 exponent,
210 ..
211 }) => {
212 if *precision == 0
213 || !significand.is_valid()
214 || *exponent > Self::MAX_EXPONENT
215 || *exponent < Self::MIN_EXPONENT
216 {
217 return false;
218 }
219 let bits = significand.significant_bits();
220 bits != 0
221 && bits.divisible_by_power_of_2(Limb::LOG_WIDTH)
222 && *precision <= bits
223 && bits - precision < Limb::WIDTH
224 && significand.divisible_by_power_of_2(bits - precision)
225 }
226 _ => true,
227 }
228 }
229}
230
231/// `ComparableFloat` is a wrapper around a [`Float`], taking the [`Float`] by value.
232///
233/// `CompatableFloat` has different comparison behavior than [`Float`]. See the [`Float`]
234/// documentation for its comparison behavior, which is largely derived from the IEEE 754
235/// specification; the `ComparableFloat` behavior, on the other hand, is more mathematically
236/// well-behaved, and respects the principle that equality should be the finest equivalence
237/// relation: that is, that two equal objects should not be different in any way.
238///
239/// To be more specific: when a [`Float`] is wrapped in a `ComparableFloat`,
240/// - `NaN` is not equal to any other [`Float`], but equal to itself;
241/// - Positive and negative zero are not equal to each other;
242/// - Ordering is total. Negative zero is ordered to be smaller than positive zero, and `NaN` is
243/// arbitrarily ordered to be between the two zeros;
244/// - Two [`Float`]s with different precisions but representing the same value are unequal, and the
245/// one with the greater precision is ordered to be larger;
246/// - The hashing function is compatible with equality.
247///
248/// The analogous wrapper for primitive floats is
249/// [`NiceFloat`](malachite_base::num::float::NiceFloat). However,
250/// [`NiceFloat`](malachite_base::num::float::NiceFloat) also facilitates better string conversion,
251/// something that isn't necessary for [`Float`]s
252///
253/// `ComparableFloat` owns its float. This is useful in many cases, for example if you want to use
254/// [`Float`]s as keys in a hash map. In other situations, it is better to use
255/// [`ComparableFloatRef`], which only has a reference to its float.
256#[derive(Clone)]
257pub struct ComparableFloat(pub Float);
258
259/// `ComparableFloatRef` is a wrapper around a [`Float`], taking the [`Float`] be reference.
260///
261/// See the [`ComparableFloat`] documentation for details.
262#[derive(Clone)]
263pub struct ComparableFloatRef<'a>(pub &'a Float);
264
265impl ComparableFloat {
266 pub const fn as_ref(&self) -> ComparableFloatRef<'_> {
267 ComparableFloatRef(&self.0)
268 }
269}
270
271impl Deref for ComparableFloat {
272 type Target = Float;
273
274 /// Allows a [`ComparableFloat`] to dereference to a [`Float`].
275 ///
276 /// ```
277 /// use malachite_base::num::basic::traits::One;
278 /// use malachite_float::{ComparableFloat, Float};
279 ///
280 /// let x = ComparableFloat(Float::ONE);
281 /// assert_eq!(*x, Float::ONE);
282 /// ```
283 fn deref(&self) -> &Float {
284 &self.0
285 }
286}
287
288impl Deref for ComparableFloatRef<'_> {
289 type Target = Float;
290
291 /// Allows a [`ComparableFloatRef`] to dereference to a [`Float`].
292 ///
293 /// ```
294 /// use malachite_base::num::basic::traits::One;
295 /// use malachite_float::{ComparableFloatRef, Float};
296 ///
297 /// let x = Float::ONE;
298 /// let y = ComparableFloatRef(&x);
299 /// assert_eq!(*y, Float::ONE);
300 /// ```
301 fn deref(&self) -> &Float {
302 self.0
303 }
304}
305
306/// Traits for arithmetic.
307pub mod arithmetic;
308#[macro_use]
309/// Basic traits for working with [`Float`]s.
310pub mod basic;
311/// Traits for comparing [`Float`]s for equality or order.
312pub mod comparison;
313/// Functions that produce [`Float`] approximations of mathematical constants, using a given
314/// precision and rounding mode.
315pub mod constants;
316/// Traits for converting to and from [`Float`]s, including converting [`Float`]s to and from
317/// strings.
318pub mod conversion;
319/// Iterators that generate [`Float`]s without repetition.
320pub mod exhaustive;
321#[cfg(feature = "random")]
322/// Iterators that generate [`Float`]s randomly.
323pub mod random;
324
325#[cfg(feature = "test_build")]
326pub mod test_util;