malachite_base/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 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#![warn(
80 clippy::cast_lossless,
81 clippy::explicit_into_iter_loop,
82 clippy::explicit_iter_loop,
83 clippy::filter_map_next,
84 clippy::large_digit_groups,
85 clippy::manual_filter_map,
86 clippy::manual_find_map,
87 clippy::map_flatten,
88 clippy::map_unwrap_or,
89 clippy::match_same_arms,
90 clippy::missing_const_for_fn,
91 clippy::mut_mut,
92 clippy::needless_borrow,
93 clippy::needless_continue,
94 clippy::needless_pass_by_value,
95 clippy::print_stdout,
96 clippy::redundant_closure_for_method_calls,
97 clippy::single_match_else,
98 clippy::trait_duplication_in_bounds,
99 clippy::type_repetition_in_bounds,
100 clippy::uninlined_format_args,
101 clippy::unused_self,
102 clippy::if_not_else,
103 clippy::manual_assert,
104 clippy::range_plus_one,
105 clippy::redundant_else,
106 clippy::semicolon_if_nothing_returned,
107 clippy::cloned_instead_of_copied,
108 clippy::flat_map_option,
109 clippy::unnecessary_wraps,
110 clippy::unnested_or_patterns,
111 clippy::trivially_copy_pass_by_ref
112)]
113#![allow(
114 clippy::cognitive_complexity,
115 clippy::float_cmp,
116 clippy::many_single_char_names,
117 clippy::too_many_arguments,
118 clippy::type_complexity,
119 clippy::upper_case_acronyms,
120 unstable_name_collisions
121)]
122#![cfg_attr(
123 not(any(feature = "test_build", feature = "random", feature = "std")),
124 no_std
125)]
126
127#[macro_use]
128extern crate alloc;
129
130#[cfg(feature = "test_build")]
131#[doc(hidden)]
132#[inline]
133pub fn fail_on_untested_path(message: &str) {
134 panic!("Untested path. {message}");
135}
136
137#[cfg(not(feature = "test_build"))]
138#[doc(hidden)]
139#[inline]
140pub const fn fail_on_untested_path(_message: &str) {}
141
142// TODO links for malachite-nz and malachite-q
143
144/// The [`Named`](named::Named) trait, for getting a type's name.
145#[macro_use]
146pub mod named;
147
148#[doc(hidden)]
149#[macro_use]
150pub mod macros;
151
152/// Functions for working with [`bool`]s.
153#[macro_use]
154pub mod bools;
155/// Functions for working with [`char`]s.
156#[macro_use]
157pub mod chars;
158/// Macros and traits related to comparing values.
159pub mod comparison;
160/// Functions and adaptors for iterators.
161pub mod iterators;
162/// [`Never`](nevers::Never), a type that cannot be instantiated.
163pub mod nevers;
164/// Functions for working with primitive integers and floats.
165#[macro_use]
166pub mod num;
167/// Functions for working with [`Ordering`](std::cmp::Ordering)s.
168pub mod options;
169/// Functions for working with [`Option`]s.
170pub mod orderings;
171#[cfg(feature = "random")]
172/// Functions for generating random values.
173pub mod random;
174/// [`RationalSequence`](rational_sequences::RationalSequence), a type representing a sequence that
175/// is finite or eventually repeating, just like the digits of a rational number.
176pub mod rational_sequences;
177/// [`RoundingMode`](rounding_modes::RoundingMode), an enum used to specify rounding behavior.
178pub mod rounding_modes;
179/// Functions for working with [`HashSet`](std::collections::HashSet)s and
180/// [`BTreeSet`](std::collections::BTreeSet)s.
181pub mod sets;
182/// Functions for working with slices.
183#[macro_use]
184pub mod slices;
185/// Functions for working with [`String`]s.
186pub mod strings;
187/// Functions for working with tuples.
188pub mod tuples;
189/// Unions (sum types). These are essentially generic enums.
190///
191/// # unwrap
192/// ```
193/// use malachite_base::union_struct;
194/// use malachite_base::unions::UnionFromStrError;
195/// use std::fmt::{self, Display, Formatter};
196/// use std::str::FromStr;
197///
198/// union_struct!(
199/// (pub(crate)),
200/// Union3,
201/// Union3<T, T, T>,
202/// [A, A, 'A', a],
203/// [B, B, 'B', b],
204/// [C, C, 'C', c]
205/// );
206///
207/// let mut u: Union3<char, char, char>;
208///
209/// u = Union3::A('a');
210/// assert_eq!(u.unwrap(), 'a');
211///
212/// u = Union3::B('b');
213/// assert_eq!(u.unwrap(), 'b');
214///
215/// u = Union3::C('c');
216/// assert_eq!(u.unwrap(), 'c');
217/// ```
218///
219/// # fmt
220/// ```
221/// use malachite_base::union_struct;
222/// use malachite_base::unions::UnionFromStrError;
223/// use std::fmt::{self, Display, Formatter};
224/// use std::str::FromStr;
225///
226/// union_struct!(
227/// (pub(crate)),
228/// Union3,
229/// Union3<T, T, T>,
230/// [A, A, 'A', a],
231/// [B, B, 'B', b],
232/// [C, C, 'C', c]
233/// );
234///
235/// let mut u: Union3<char, u32, bool>;
236///
237/// u = Union3::A('a');
238/// assert_eq!(u.to_string(), "A(a)");
239///
240/// u = Union3::B(5);
241/// assert_eq!(u.to_string(), "B(5)");
242///
243/// u = Union3::C(false);
244/// assert_eq!(u.to_string(), "C(false)");
245/// ```
246///
247/// # from_str
248/// ```
249/// use malachite_base::union_struct;
250/// use malachite_base::unions::UnionFromStrError;
251/// use std::fmt::{self, Display, Formatter};
252/// use std::str::FromStr;
253///
254/// union_struct!(
255/// (pub(crate)),
256/// Union3,
257/// Union3<T, T, T>,
258/// [A, A, 'A', a],
259/// [B, B, 'B', b],
260/// [C, C, 'C', c]
261/// );
262///
263/// let u3: Union3<bool, u32, char> = Union3::from_str("B(5)").unwrap();
264/// assert_eq!(u3, Union3::B(5));
265///
266/// let result: Result<Union3<char, u32, bool>, _> = Union3::from_str("xyz");
267/// assert_eq!(result, Err(UnionFromStrError::Generic("xyz".to_string())));
268///
269/// let result: Result<Union3<char, u32, bool>, _> = Union3::from_str("A(ab)");
270/// if let Err(UnionFromStrError::Specific(Union3::A(_e))) = result {
271/// } else {
272/// panic!("wrong error variant")
273/// }
274/// ```
275pub mod unions;
276/// Functions for working with [`Vec`]s.
277pub mod vecs;
278
279#[cfg(feature = "test_build")]
280pub mod test_util;
281
282pub mod platform;