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#[cfg(feature = "serde")]
156#[macro_use]
157extern crate serde;
158
159#[cfg(feature = "test_build")]
160#[doc(hidden)]
161#[inline]
162pub fn fail_on_untested_path(message: &str) {
163 panic!("Untested path. {message}");
164}
165
166#[cfg(not(feature = "test_build"))]
167#[doc(hidden)]
168#[inline]
169pub const fn fail_on_untested_path(_message: &str) {}
170
171// TODO links for malachite-nz and malachite-q
172
173/// Functions for working with [`HashMap`](std::collections::HashMap)s and
174/// [`BTreeMap`](std::collections::BTreeMap)s.
175pub mod maps;
176/// The [`Named`](named::Named) trait, for getting a type's name.
177#[macro_use]
178pub mod named;
179
180#[doc(hidden)]
181#[macro_use]
182pub mod macros;
183
184/// Functions for working with [`bool`]s.
185#[macro_use]
186pub mod bools;
187/// Functions for working with [`char`]s.
188#[macro_use]
189pub mod chars;
190/// Macros and traits related to comparing values.
191pub mod comparison;
192/// Functions and adaptors for iterators.
193pub mod iterators;
194/// [`Never`](nevers::Never), a type that cannot be instantiated.
195pub mod nevers;
196/// Functions for working with primitive integers and floats.
197#[macro_use]
198pub mod num;
199/// [`FoerSequence`](foer_sequences::FoerSequence), a type representing a sequence that is finite or
200/// eventually repeating (which is what "foer" abbreviates), just like the digits of a rational
201/// number.
202pub mod foer_sequences;
203/// Functions for working with [`Option`]s.
204pub mod options;
205/// Functions for working with [`Ordering`](std::cmp::Ordering)s.
206pub mod orderings;
207/// The [`Polynomial`](polynomial::Polynomial) trait, for what every polynomial type has in common.
208pub mod polynomial;
209#[cfg(feature = "random")]
210/// Functions for generating random values.
211pub mod random;
212/// [`RoundingMode`](rounding_modes::RoundingMode), an enum used to specify rounding behavior.
213pub mod rounding_modes;
214/// Functions for working with [`HashSet`](std::collections::HashSet)s and
215/// [`BTreeSet`](std::collections::BTreeSet)s.
216pub mod sets;
217/// Functions for working with slices.
218#[macro_use]
219pub mod slices;
220/// Functions for working with [`String`]s.
221pub mod strings;
222/// Functions for working with tuples.
223pub mod tuples;
224/// Unions (sum types). These are essentially generic enums.
225///
226/// # unwrap
227/// ```
228/// use malachite_base::union_struct;
229/// use malachite_base::unions::UnionFromStrError;
230/// use std::fmt::{self, Display, Formatter};
231/// use std::str::FromStr;
232///
233/// union_struct!(
234/// (pub(crate)),
235/// Union3,
236/// Union3<T, T, T>,
237/// [A, A, 'A', a],
238/// [B, B, 'B', b],
239/// [C, C, 'C', c]
240/// );
241///
242/// let mut u: Union3<char, char, char>;
243///
244/// u = Union3::A('a');
245/// assert_eq!(u.unwrap(), 'a');
246///
247/// u = Union3::B('b');
248/// assert_eq!(u.unwrap(), 'b');
249///
250/// u = Union3::C('c');
251/// assert_eq!(u.unwrap(), 'c');
252/// ```
253///
254/// # fmt
255/// ```
256/// use malachite_base::union_struct;
257/// use malachite_base::unions::UnionFromStrError;
258/// use std::fmt::{self, Display, Formatter};
259/// use std::str::FromStr;
260///
261/// union_struct!(
262/// (pub(crate)),
263/// Union3,
264/// Union3<T, T, T>,
265/// [A, A, 'A', a],
266/// [B, B, 'B', b],
267/// [C, C, 'C', c]
268/// );
269///
270/// let mut u: Union3<char, u32, bool>;
271///
272/// u = Union3::A('a');
273/// assert_eq!(u.to_string(), "A(a)");
274///
275/// u = Union3::B(5);
276/// assert_eq!(u.to_string(), "B(5)");
277///
278/// u = Union3::C(false);
279/// assert_eq!(u.to_string(), "C(false)");
280/// ```
281///
282/// # from_str
283/// ```
284/// use malachite_base::union_struct;
285/// use malachite_base::unions::UnionFromStrError;
286/// use std::fmt::{self, Display, Formatter};
287/// use std::str::FromStr;
288///
289/// union_struct!(
290/// (pub(crate)),
291/// Union3,
292/// Union3<T, T, T>,
293/// [A, A, 'A', a],
294/// [B, B, 'B', b],
295/// [C, C, 'C', c]
296/// );
297///
298/// let u3: Union3<bool, u32, char> = Union3::from_str("B(5)").unwrap();
299/// assert_eq!(u3, Union3::B(5));
300///
301/// let result: Result<Union3<char, u32, bool>, _> = Union3::from_str("xyz");
302/// assert_eq!(result, Err(UnionFromStrError::Generic("xyz".to_string())));
303///
304/// let result: Result<Union3<char, u32, bool>, _> = Union3::from_str("A(ab)");
305/// if let Err(UnionFromStrError::Specific(Union3::A(_e))) = result {
306/// } else {
307/// panic!("wrong error variant")
308/// }
309/// ```
310/// # fmt_latex
311/// ```
312/// use malachite_base::strings::latex::ToLatex;
313/// use malachite_base::union_struct;
314/// use malachite_base::unions::UnionFromStrError;
315/// use std::fmt::{self, Display, Formatter};
316/// use std::str::FromStr;
317///
318/// union_struct!(
319/// (pub(crate)),
320/// Union3,
321/// Union3<T, T, T>,
322/// [A, A, 'A', a],
323/// [B, B, 'B', b],
324/// [C, C, 'C', c]
325/// );
326///
327/// let mut u: Union3<char, u32, bool>;
328///
329/// u = Union3::A('a');
330/// assert_eq!(u.to_latex_string(), r"\text{A}\left(\text{a}\right)");
331///
332/// u = Union3::B(5);
333/// assert_eq!(u.to_latex_string(), r"\text{B}\left(5\right)");
334///
335/// u = Union3::C(false);
336/// assert_eq!(u.to_latex_string(), r"\text{C}\left(\text{F}\right)");
337/// ```
338///
339/// | value | fragment | renders as |
340/// |--------------------|---------------------------------|---------------------------------|
341/// | `Union3::A('a')` | `\text{A}\left(\text{a}\right)` | $\text{A}\left(\text{a}\right)$ |
342/// | `Union3::B(5)` | `\text{B}\left(5\right)` | $\text{B}\left(5\right)$ |
343/// | `Union3::C(false)` | `\text{C}\left(\text{F}\right)` | $\text{C}\left(\text{F}\right)$ |
344///
345/// # fmt_typst
346/// ```
347/// use malachite_base::strings::typst::ToTypst;
348/// use malachite_base::union_struct;
349/// use malachite_base::unions::UnionFromStrError;
350/// use std::fmt::{self, Display, Formatter};
351/// use std::str::FromStr;
352///
353/// union_struct!(
354/// (pub(crate)),
355/// Union3,
356/// Union3<T, T, T>,
357/// [A, A, 'A', a],
358/// [B, B, 'B', b],
359/// [C, C, 'C', c]
360/// );
361///
362/// let mut u: Union3<char, u32, bool>;
363///
364/// u = Union3::A('a');
365/// assert_eq!(u.to_typst_string(), r#""A"("a")"#);
366///
367/// u = Union3::B(5);
368/// assert_eq!(u.to_typst_string(), r#""B"(5)"#);
369///
370/// u = Union3::C(false);
371/// assert_eq!(u.to_typst_string(), r#""C"("F")"#);
372/// ```
373///
374/// | value | fragment |
375/// |--------------------|------------|
376/// | `Union3::A('a')` | `"A"("a")` |
377/// | `Union3::B(5)` | `"B"(5)` |
378/// | `Union3::C(false)` | `"C"("F")` |
379pub mod unions;
380/// [`UnsignedPolynomial`](unsigned_polynomial::UnsignedPolynomial), a type representing polynomials
381/// in one variable whose coefficients are primitive unsigned integers.
382pub mod unsigned_polynomial;
383/// Schemes for naming variables, for instance the variables of a polynomial.
384pub mod vars;
385/// Functions for working with [`Vec`]s.
386pub mod vecs;
387
388#[cfg(feature = "test_build")]
389pub mod test_util;
390
391pub mod platform;