malachite_base/lib.rs
1// Copyright © 2026 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 contains many utilities that are used by the
10//! [`malachite-nz`](https://docs.rs/malachite-nz/latest/malachite_nz/) and
11//! [`malachite-q`]((https://docs.rs/malachite-q/latest/malachite_q/)) crates. These utilities
12//! include
13//! - Traits that wrap functions from the standard library, like
14//! [`CheckedAdd`](num::arithmetic::traits::CheckedAdd).
15//! - Traits that give extra functionality to primitive types, like
16//! [`Gcd`](num::arithmetic::traits::Gcd), [`FloorSqrt`](num::arithmetic::traits::FloorSqrt), and
17//! [`BitAccess`](num::logic::traits::BitAccess).
18//! - Iterator-producing functions that let you generate values for testing. Here's an example of
19//! an iterator that produces all pairs of [`u32`]s:
20//! ```
21//! use malachite_base::num::exhaustive::exhaustive_unsigneds;
22//! use malachite_base::tuples::exhaustive::exhaustive_pairs_from_single;
23//!
24//! let mut pairs = exhaustive_pairs_from_single(exhaustive_unsigneds::<u32>());
25//! assert_eq!(
26//! pairs.take(20).collect::<Vec<_>>(),
27//! &[
28//! (0, 0), (0, 1), (1, 0), (1, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 0), (2, 1),
29//! (3, 0), (3, 1), (2, 2), (2, 3), (3, 2), (3, 3), (0, 4), (0, 5), (1, 4), (1, 5)
30//! ]
31//! );
32//! ```
33//! - The [`RoundingMode`](rounding_modes::RoundingMode) enum, which allows you to specify the
34//! rounding behavior of various functions.
35//! - The [`NiceFloat`](num::float::NiceFloat) wrapper, which provides alternative implementations
36//! of [`Eq`], [`Ord`], and [`Display`](std::fmt::Display) for floating-point values which are in
37//! some ways nicer than the defaults.
38//!
39//! # Complexity conventions
40//! Most functions in Malachite come with a "Worst-case complexity" section stating time and
41//! additional-memory bounds, like $T(n) = O(n \log n \log\log n)$ and $M(n) = O(n)$, along with a
42//! line defining each variable. The model is a word RAM: time counts operations on machine words
43//! (an operation on any primitive type up to `u128` compiles to a bounded number of native
44//! instructions, so it counts as one step), and additional memory counts words allocated beyond
45//! the inputs and the output.
46//!
47//! Since primitive-integer inputs are bounded, every function on them technically runs in
48//! constant time. The complexity sections are written to be more informative than that:
49//! - "Constant time and additional memory" means the operation count is bounded independently of
50//! the type's width and of the inputs' values.
51//! - Otherwise, the bound is written in terms of variables, describing how the work would scale
52//! if the same algorithm were instantiated at an arbitrarily large width. For example,
53//! [`mod_pow`](num::arithmetic::traits::ModPow::mod_pow) for primitive types is documented as
54//! $T(n) = O(n)$, where $n$ is `exp.significant_bits()`: the work scales with the exponent's
55//! bit length. Every such variable is bounded by the type's width, so these bounds may be read
56//! as constants; the variable form tells you what the constant depends on.
57//!
58//! # Demos and benchmarks
59//! This crate comes with a `bin` target that can be used for running demos and benchmarks.
60//! - Almost all of the public functions in this crate have an associated demo. Running a demo
61//! shows you a function's behavior on a large number of inputs. For example, to demo the
62//! [`mod_pow`](num::arithmetic::traits::ModPow::mod_pow) function on [`u32`]s, you can use the
63//! following command:
64//! ```text
65//! cargo run --features bin_build --release -- -l 10000 -m exhaustive -d demo_mod_pow_u32
66//! ```
67//! This command uses the `exhaustive` mode, which generates every possible input, generally
68//! starting with the simplest input and progressing to more complex ones. Another mode is
69//! `random`. The `-l` flag specifies how many inputs should be generated.
70//! - You can use a similar command to run benchmarks. The following command benchmarks various
71//! GCD algorithms for [`u64`]s:
72//! ```text
73//! cargo run --features bin_build --release -- -l 1000000 -m random -b \
74//! benchmark_gcd_algorithms_u64 -o gcd-bench.gp
75//! ```
76//! This creates a file called gcd-bench.gp. You can use gnuplot to create an SVG from it like
77//! so:
78//! ```text
79//! gnuplot -e "set terminal svg; l \"gcd-bench.gp\"" > gcd-bench.svg
80//! ```
81//!
82//! The list of available demos and benchmarks is not documented anywhere; you must find them by
83//! browsing through
84//! [`bin_util/demo_and_bench`](https://github.com/mhogrefe/malachite/tree/master/malachite-base/src/bin_util/demo_and_bench).
85//!
86//! # Features
87//! - `test_build`: A large proportion of the code in this crate is only used for testing. For a
88//! typical user, building this code would result in an unnecessarily long compilation time and
89//! an unnecessarily large binary. Much of it is also used for testing
90//! [`malachite-nz`](https://docs.rs/malachite-nz/latest/malachite_nz/) and
91//! [`malachite-q`](https://docs.rs/malachite-q/latest/malachite_q/), so it can't just be
92//! confined to the `tests` directory. My solution is to only build this code when the
93//! `test_build` feature is enabled. If you want to run unit tests, you must enable `test_build`.
94//! However, doctests don't require it, since they only test the public interface.
95//! - `bin_build`: This feature is used to build the code for demos and benchmarks, which also
96//! takes a long time to build. Enabling this feature also enables `test_build`.
97
98#![forbid(unsafe_code)]
99#![allow(
100 unstable_name_collisions,
101 clippy::assertions_on_constants,
102 clippy::cognitive_complexity,
103 clippy::many_single_char_names,
104 clippy::range_plus_one,
105 clippy::suspicious_arithmetic_impl,
106 clippy::suspicious_op_assign_impl,
107 clippy::too_many_arguments,
108 clippy::type_complexity,
109 clippy::upper_case_acronyms,
110 clippy::multiple_bound_locations
111)]
112#![warn(
113 clippy::cast_lossless,
114 clippy::comparison_chain,
115 clippy::explicit_into_iter_loop,
116 clippy::explicit_iter_loop,
117 clippy::filter_map_next,
118 clippy::large_digit_groups,
119 clippy::manual_filter_map,
120 clippy::manual_find_map,
121 clippy::map_flatten,
122 clippy::map_unwrap_or,
123 clippy::match_same_arms,
124 clippy::missing_const_for_fn,
125 clippy::mut_mut,
126 clippy::needless_borrow,
127 clippy::needless_continue,
128 clippy::needless_pass_by_value,
129 clippy::print_stdout,
130 clippy::redundant_closure_for_method_calls,
131 clippy::single_match_else,
132 clippy::trait_duplication_in_bounds,
133 clippy::type_repetition_in_bounds,
134 clippy::uninlined_format_args,
135 clippy::unused_self,
136 clippy::if_not_else,
137 clippy::manual_assert,
138 clippy::range_plus_one,
139 clippy::redundant_else,
140 clippy::semicolon_if_nothing_returned,
141 clippy::cloned_instead_of_copied,
142 clippy::flat_map_option,
143 clippy::unnecessary_wraps,
144 clippy::unnested_or_patterns,
145 clippy::use_self,
146 clippy::trivially_copy_pass_by_ref
147)]
148#![cfg_attr(
149 not(any(feature = "test_build", feature = "random", feature = "std")),
150 no_std
151)]
152
153#[macro_use]
154extern crate alloc;
155
156#[cfg(feature = "test_build")]
157#[doc(hidden)]
158#[inline]
159pub fn fail_on_untested_path(message: &str) {
160 panic!("Untested path. {message}");
161}
162
163#[cfg(not(feature = "test_build"))]
164#[doc(hidden)]
165#[inline]
166pub const fn fail_on_untested_path(_message: &str) {}
167
168// TODO links for malachite-nz and malachite-q
169
170/// The [`Named`](named::Named) trait, for getting a type's name.
171#[macro_use]
172pub mod named;
173
174#[doc(hidden)]
175#[macro_use]
176pub mod macros;
177
178/// Functions for working with [`bool`]s.
179#[macro_use]
180pub mod bools;
181/// Functions for working with [`char`]s.
182#[macro_use]
183pub mod chars;
184/// Macros and traits related to comparing values.
185pub mod comparison;
186/// Functions and adaptors for iterators.
187pub mod iterators;
188/// [`Never`](nevers::Never), a type that cannot be instantiated.
189pub mod nevers;
190/// Functions for working with primitive integers and floats.
191#[macro_use]
192pub mod num;
193/// [`FoerSequence`](foer_sequences::FoerSequence), a type representing a sequence that is finite or
194/// eventually repeating (which is what "foer" abbreviates), just like the digits of a rational
195/// number.
196pub mod foer_sequences;
197/// Functions for working with [`Ordering`](std::cmp::Ordering)s.
198pub mod options;
199/// Functions for working with [`Option`]s.
200pub mod orderings;
201#[cfg(feature = "random")]
202/// Functions for generating random values.
203pub mod random;
204/// [`RoundingMode`](rounding_modes::RoundingMode), an enum used to specify rounding behavior.
205pub mod rounding_modes;
206/// Functions for working with [`HashSet`](std::collections::HashSet)s and
207/// [`BTreeSet`](std::collections::BTreeSet)s.
208pub mod sets;
209/// Functions for working with slices.
210#[macro_use]
211pub mod slices;
212/// Functions for working with [`String`]s.
213pub mod strings;
214/// Functions for working with tuples.
215pub mod tuples;
216/// Unions (sum types). These are essentially generic enums.
217///
218/// # unwrap
219/// ```
220/// use malachite_base::union_struct;
221/// use malachite_base::unions::UnionFromStrError;
222/// use std::fmt::{self, Display, Formatter};
223/// use std::str::FromStr;
224///
225/// union_struct!(
226/// (pub(crate)),
227/// Union3,
228/// Union3<T, T, T>,
229/// [A, A, 'A', a],
230/// [B, B, 'B', b],
231/// [C, C, 'C', c]
232/// );
233///
234/// let mut u: Union3<char, char, char>;
235///
236/// u = Union3::A('a');
237/// assert_eq!(u.unwrap(), 'a');
238///
239/// u = Union3::B('b');
240/// assert_eq!(u.unwrap(), 'b');
241///
242/// u = Union3::C('c');
243/// assert_eq!(u.unwrap(), 'c');
244/// ```
245///
246/// # fmt
247/// ```
248/// use malachite_base::union_struct;
249/// use malachite_base::unions::UnionFromStrError;
250/// use std::fmt::{self, Display, Formatter};
251/// use std::str::FromStr;
252///
253/// union_struct!(
254/// (pub(crate)),
255/// Union3,
256/// Union3<T, T, T>,
257/// [A, A, 'A', a],
258/// [B, B, 'B', b],
259/// [C, C, 'C', c]
260/// );
261///
262/// let mut u: Union3<char, u32, bool>;
263///
264/// u = Union3::A('a');
265/// assert_eq!(u.to_string(), "A(a)");
266///
267/// u = Union3::B(5);
268/// assert_eq!(u.to_string(), "B(5)");
269///
270/// u = Union3::C(false);
271/// assert_eq!(u.to_string(), "C(false)");
272/// ```
273///
274/// # from_str
275/// ```
276/// use malachite_base::union_struct;
277/// use malachite_base::unions::UnionFromStrError;
278/// use std::fmt::{self, Display, Formatter};
279/// use std::str::FromStr;
280///
281/// union_struct!(
282/// (pub(crate)),
283/// Union3,
284/// Union3<T, T, T>,
285/// [A, A, 'A', a],
286/// [B, B, 'B', b],
287/// [C, C, 'C', c]
288/// );
289///
290/// let u3: Union3<bool, u32, char> = Union3::from_str("B(5)").unwrap();
291/// assert_eq!(u3, Union3::B(5));
292///
293/// let result: Result<Union3<char, u32, bool>, _> = Union3::from_str("xyz");
294/// assert_eq!(result, Err(UnionFromStrError::Generic("xyz".to_string())));
295///
296/// let result: Result<Union3<char, u32, bool>, _> = Union3::from_str("A(ab)");
297/// if let Err(UnionFromStrError::Specific(Union3::A(_e))) = result {
298/// } else {
299/// panic!("wrong error variant")
300/// }
301/// ```
302pub mod unions;
303/// Functions for working with [`Vec`]s.
304pub mod vecs;
305
306#[cfg(feature = "test_build")]
307pub mod test_util;
308
309pub mod platform;