Skip to main content

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//! # Demos and benchmarks
40//! This crate comes with a `bin` target that can be used for running demos and benchmarks.
41//! - Almost all of the public functions in this crate have an associated demo. Running a demo
42//!   shows you a function's behavior on a large number of inputs. For example, to demo the
43//!   [`mod_pow`](num::arithmetic::traits::ModPow::mod_pow) function on [`u32`]s, you can use the
44//!   following command:
45//!   ```text
46//!   cargo run --features bin_build --release -- -l 10000 -m exhaustive -d demo_mod_pow_u32
47//!   ```
48//!   This command uses the `exhaustive` mode, which generates every possible input, generally
49//!   starting with the simplest input and progressing to more complex ones. Another mode is
50//!   `random`. The `-l` flag specifies how many inputs should be generated.
51//! - You can use a similar command to run benchmarks. The following command benchmarks various
52//!   GCD algorithms for [`u64`]s:
53//!   ```text
54//!   cargo run --features bin_build --release -- -l 1000000 -m random -b \
55//!       benchmark_gcd_algorithms_u64 -o gcd-bench.gp
56//!   ```
57//!   This creates a file called gcd-bench.gp. You can use gnuplot to create an SVG from it like
58//!   so:
59//!   ```text
60//!   gnuplot -e "set terminal svg; l \"gcd-bench.gp\"" > gcd-bench.svg
61//!   ```
62//!
63//! The list of available demos and benchmarks is not documented anywhere; you must find them by
64//! browsing through
65//! [`bin_util/demo_and_bench`](https://github.com/mhogrefe/malachite/tree/master/malachite-base/src/bin_util/demo_and_bench).
66//!
67//! # Features
68//! - `test_build`: A large proportion of the code in this crate is only used for testing. For a
69//!   typical user, building this code would result in an unnecessarily long compilation time and
70//!   an unnecessarily large binary. Much of it is also used for testing
71//!   [`malachite-nz`](https://docs.rs/malachite-nz/latest/malachite_nz/) and
72//!   [`malachite-q`](https://docs.rs/malachite-q/latest/malachite_q/), so it can't just be
73//!   confined to the `tests` directory. My solution is to only build this code when the
74//!   `test_build` feature is enabled. If you want to run unit tests, you must enable `test_build`.
75//!   However, doctests don't require it, since they only test the public interface.
76//! - `bin_build`: This feature is used to build the code for demos and benchmarks, which also
77//!   takes a long time to build. Enabling this feature also enables `test_build`.
78
79#![forbid(unsafe_code)]
80#![allow(
81    unstable_name_collisions,
82    clippy::assertions_on_constants,
83    clippy::cognitive_complexity,
84    clippy::many_single_char_names,
85    clippy::range_plus_one,
86    clippy::suspicious_arithmetic_impl,
87    clippy::suspicious_op_assign_impl,
88    clippy::too_many_arguments,
89    clippy::type_complexity,
90    clippy::upper_case_acronyms,
91    clippy::multiple_bound_locations
92)]
93#![warn(
94    clippy::cast_lossless,
95    clippy::comparison_chain,
96    clippy::explicit_into_iter_loop,
97    clippy::explicit_iter_loop,
98    clippy::filter_map_next,
99    clippy::large_digit_groups,
100    clippy::manual_filter_map,
101    clippy::manual_find_map,
102    clippy::map_flatten,
103    clippy::map_unwrap_or,
104    clippy::match_same_arms,
105    clippy::missing_const_for_fn,
106    clippy::mut_mut,
107    clippy::needless_borrow,
108    clippy::needless_continue,
109    clippy::needless_pass_by_value,
110    clippy::print_stdout,
111    clippy::redundant_closure_for_method_calls,
112    clippy::single_match_else,
113    clippy::trait_duplication_in_bounds,
114    clippy::type_repetition_in_bounds,
115    clippy::uninlined_format_args,
116    clippy::unused_self,
117    clippy::if_not_else,
118    clippy::manual_assert,
119    clippy::range_plus_one,
120    clippy::redundant_else,
121    clippy::semicolon_if_nothing_returned,
122    clippy::cloned_instead_of_copied,
123    clippy::flat_map_option,
124    clippy::unnecessary_wraps,
125    clippy::unnested_or_patterns,
126    clippy::use_self,
127    clippy::trivially_copy_pass_by_ref
128)]
129#![cfg_attr(
130    not(any(feature = "test_build", feature = "random", feature = "std")),
131    no_std
132)]
133
134#[macro_use]
135extern crate alloc;
136
137#[cfg(feature = "test_build")]
138#[doc(hidden)]
139#[inline]
140pub fn fail_on_untested_path(message: &str) {
141    panic!("Untested path. {message}");
142}
143
144#[cfg(not(feature = "test_build"))]
145#[doc(hidden)]
146#[inline]
147pub const fn fail_on_untested_path(_message: &str) {}
148
149// TODO links for malachite-nz and malachite-q
150
151/// The [`Named`](named::Named) trait, for getting a type's name.
152#[macro_use]
153pub mod named;
154
155#[doc(hidden)]
156#[macro_use]
157pub mod macros;
158
159/// Functions for working with [`bool`]s.
160#[macro_use]
161pub mod bools;
162/// Functions for working with [`char`]s.
163#[macro_use]
164pub mod chars;
165/// Macros and traits related to comparing values.
166pub mod comparison;
167/// Functions and adaptors for iterators.
168pub mod iterators;
169/// [`Never`](nevers::Never), a type that cannot be instantiated.
170pub mod nevers;
171/// Functions for working with primitive integers and floats.
172#[macro_use]
173pub mod num;
174/// [`FoerSequence`](foer_sequences::FoerSequence), a type representing a sequence that is finite or
175/// eventually repeating (which is what "foer" abbreviates), just like the digits of a rational
176/// number.
177pub mod foer_sequences;
178/// Functions for working with [`Ordering`](std::cmp::Ordering)s.
179pub mod options;
180/// Functions for working with [`Option`]s.
181pub mod orderings;
182#[cfg(feature = "random")]
183/// Functions for generating random values.
184pub mod random;
185/// [`RoundingMode`](rounding_modes::RoundingMode), an enum used to specify rounding behavior.
186pub mod rounding_modes;
187/// Functions for working with [`HashSet`](std::collections::HashSet)s and
188/// [`BTreeSet`](std::collections::BTreeSet)s.
189pub mod sets;
190/// Functions for working with slices.
191#[macro_use]
192pub mod slices;
193/// Functions for working with [`String`]s.
194pub mod strings;
195/// Functions for working with tuples.
196pub mod tuples;
197/// Unions (sum types). These are essentially generic enums.
198///
199/// # unwrap
200/// ```
201/// use malachite_base::union_struct;
202/// use malachite_base::unions::UnionFromStrError;
203/// use std::fmt::{self, Display, Formatter};
204/// use std::str::FromStr;
205///
206/// union_struct!(
207///     (pub(crate)),
208///     Union3,
209///     Union3<T, T, T>,
210///     [A, A, 'A', a],
211///     [B, B, 'B', b],
212///     [C, C, 'C', c]
213/// );
214///
215/// let mut u: Union3<char, char, char>;
216///
217/// u = Union3::A('a');
218/// assert_eq!(u.unwrap(), 'a');
219///
220/// u = Union3::B('b');
221/// assert_eq!(u.unwrap(), 'b');
222///
223/// u = Union3::C('c');
224/// assert_eq!(u.unwrap(), 'c');
225/// ```
226///
227/// # fmt
228/// ```
229/// use malachite_base::union_struct;
230/// use malachite_base::unions::UnionFromStrError;
231/// use std::fmt::{self, Display, Formatter};
232/// use std::str::FromStr;
233///
234/// union_struct!(
235///     (pub(crate)),
236///     Union3,
237///     Union3<T, T, T>,
238///     [A, A, 'A', a],
239///     [B, B, 'B', b],
240///     [C, C, 'C', c]
241/// );
242///
243/// let mut u: Union3<char, u32, bool>;
244///
245/// u = Union3::A('a');
246/// assert_eq!(u.to_string(), "A(a)");
247///
248/// u = Union3::B(5);
249/// assert_eq!(u.to_string(), "B(5)");
250///
251/// u = Union3::C(false);
252/// assert_eq!(u.to_string(), "C(false)");
253/// ```
254///
255/// # from_str
256/// ```
257/// use malachite_base::union_struct;
258/// use malachite_base::unions::UnionFromStrError;
259/// use std::fmt::{self, Display, Formatter};
260/// use std::str::FromStr;
261///
262/// union_struct!(
263///     (pub(crate)),
264///     Union3,
265///     Union3<T, T, T>,
266///     [A, A, 'A', a],
267///     [B, B, 'B', b],
268///     [C, C, 'C', c]
269/// );
270///
271/// let u3: Union3<bool, u32, char> = Union3::from_str("B(5)").unwrap();
272/// assert_eq!(u3, Union3::B(5));
273///
274/// let result: Result<Union3<char, u32, bool>, _> = Union3::from_str("xyz");
275/// assert_eq!(result, Err(UnionFromStrError::Generic("xyz".to_string())));
276///
277/// let result: Result<Union3<char, u32, bool>, _> = Union3::from_str("A(ab)");
278/// if let Err(UnionFromStrError::Specific(Union3::A(_e))) = result {
279/// } else {
280///     panic!("wrong error variant")
281/// }
282/// ```
283pub mod unions;
284/// Functions for working with [`Vec`]s.
285pub mod vecs;
286
287#[cfg(feature = "test_build")]
288pub mod test_util;
289
290pub mod platform;