Skip to main content

malachite_base/num/conversion/
traits.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
9use crate::num::conversion::string::options::{FromSciStringOptions, ToSciOptions};
10use crate::num::conversion::string::to_sci::SciWrapper;
11use crate::rounding_modes::RoundingMode;
12use alloc::string::String;
13use alloc::vec::Vec;
14use core::cmp::Ordering;
15use core::fmt::{Formatter, Result};
16
17/// Expresses a value as a [`Vec`] of digits, or reads a value from an iterator of digits.
18///
19/// The trait is parameterized by `T`, which is both the digit type and the base type.
20pub trait Digits<T>: Sized {
21    /// Returns a [`Vec`] containing the digits of a value in ascending order: least- to
22    /// most-significant.
23    fn to_digits_asc(&self, base: &T) -> Vec<T>;
24
25    /// Returns a [`Vec`] containing the digits of a value in descending order: most- to
26    /// least-significant.
27    fn to_digits_desc(&self, base: &T) -> Vec<T>;
28
29    /// Converts an iterator of digits into a value.
30    ///
31    /// The input digits are in ascending order: least- to most-significant.
32    fn from_digits_asc<I: Iterator<Item = T>>(base: &T, digits: I) -> Option<Self>;
33
34    /// Converts an iterator of digits into a value.
35    ///
36    /// The input digits are in descending order: most- to least-significant.
37    fn from_digits_desc<I: Iterator<Item = T>>(base: &T, digits: I) -> Option<Self>;
38}
39
40/// An iterator over a value's base-$2^k$ digits.
41pub trait PowerOf2DigitIterator<T>: Iterator<Item = T> + DoubleEndedIterator<Item = T> {
42    fn get_digit(&self, index: u64) -> T;
43}
44
45/// Creates an iterator over a value's base-$2^k$ digits.
46pub trait PowerOf2DigitIterable<T> {
47    type PowerOf2DigitIterator: PowerOf2DigitIterator<T>;
48
49    /// Returns a double-ended iterator over a value's digits in base $2^l$, where $k$ is
50    /// `log_base`.
51    ///
52    /// The iterator ends after the value's most-significant digit.
53    fn power_of_2_digits(self, log_base: u64) -> Self::PowerOf2DigitIterator;
54}
55
56/// Expresses a value as a [`Vec`] of base-$2^k$ digits, or reads a value from an iterator of
57/// base-$2^k$ digits.
58///
59/// The trait is parameterized by the digit type.
60pub trait PowerOf2Digits<T>: Sized {
61    /// Returns a [`Vec`] containing the digits of a value in ascending order: least- to
62    /// most-significant.
63    ///
64    /// The base is $2^k$, where $k$ is `log_base`.
65    fn to_power_of_2_digits_asc(&self, log_base: u64) -> Vec<T>;
66
67    /// Returns a [`Vec`] containing the digits of a value in descending order: most- to
68    /// least-significant.
69    ///
70    /// The base is $2^k$, where $k$ is `log_base`.
71    fn to_power_of_2_digits_desc(&self, log_base: u64) -> Vec<T>;
72
73    /// Converts an iterator of digits into a value.
74    ///
75    /// The input digits are in ascending order: least- to most-significant. The base is $2^k$,
76    /// where $k$ is `log_base`.
77    fn from_power_of_2_digits_asc<I: Iterator<Item = T>>(log_base: u64, digits: I) -> Option<Self>;
78
79    /// Converts an iterator of digits into a value.
80    ///
81    /// The input digits are in descending order: most- to least-significant. The base is $2^k$,
82    /// where $k$ is `log_base`.
83    fn from_power_of_2_digits_desc<I: Iterator<Item = T>>(log_base: u64, digits: I)
84    -> Option<Self>;
85}
86
87/// Converts a string slice in a given base to a value.
88pub trait FromStringBase: Sized {
89    fn from_string_base(base: u8, s: &str) -> Option<Self>;
90}
91
92/// Converts a number to a string using a specified base.
93pub trait ToStringBase {
94    /// Converts a signed number to a lowercase string using a specified base.
95    fn to_string_base(&self, base: u8) -> String;
96
97    /// Converts a signed number to an uppercase string using a specified base.
98    fn to_string_base_upper(&self, base: u8) -> String;
99}
100
101/// Converts a number to a string, possibly in scientific notation.
102pub trait ToSci: Sized {
103    /// Formats a number, possibly in scientific notation.
104    fn fmt_sci(&self, f: &mut Formatter, options: ToSciOptions) -> Result;
105
106    /// Determines whether some formatting options can be applied to a number.
107    fn fmt_sci_valid(&self, options: ToSciOptions) -> bool;
108
109    /// Converts a number to a string, possibly in scientific notation.
110    fn to_sci_with_options(&self, options: ToSciOptions) -> SciWrapper<'_, Self> {
111        SciWrapper { x: self, options }
112    }
113
114    /// Converts a number to a string, possibly in scientific notation, using the default
115    /// [`ToSciOptions`].
116    #[inline]
117    fn to_sci(&self) -> SciWrapper<'_, Self> {
118        SciWrapper {
119            x: self,
120            options: ToSciOptions::default(),
121        }
122    }
123}
124
125/// Converts a `&str`, possibly in scientific notation, to a number.
126pub trait FromSciString: Sized {
127    /// Converts a `&str`, possibly in scientific notation, to a number.
128    fn from_sci_string_with_options(s: &str, options: FromSciStringOptions) -> Option<Self>;
129
130    /// Converts a `&str`, possibly in scientific notation, to a number, using the default
131    /// [`FromSciStringOptions`].
132    #[inline]
133    fn from_sci_string(s: &str) -> Option<Self> {
134        Self::from_sci_string_with_options(s, FromSciStringOptions::default())
135    }
136}
137
138/// Converts a value from one type to another. If the conversion fails, the function panics.
139///
140/// It is recommended that this trait is not implemented directly; it is automatically implemented
141/// when [`TryFrom`] is implemented.
142pub trait ExactFrom<T>: Sized {
143    fn exact_from(value: T) -> Self;
144}
145
146/// Converts a value from one type to another. If the conversion fails, the function panics.
147///
148/// It is recommended that this trait is not implemented directly; it is automatically implemented
149/// when [`ExactFrom`] is implemented.
150pub trait ExactInto<T> {
151    fn exact_into(self) -> T;
152}
153
154impl<T, U: TryFrom<T>> ExactFrom<T> for U {
155    #[inline]
156    fn exact_from(value: T) -> U {
157        U::try_from(value).ok().unwrap()
158    }
159}
160
161impl<T, U: ExactFrom<T>> ExactInto<U> for T {
162    #[inline]
163    fn exact_into(self) -> U {
164        U::exact_from(self)
165    }
166}
167
168/// Converts a value from one type to another. where if the conversion is not exact the result will
169/// wrap around.
170///
171/// If `WrappingFrom` is implemented, it usually makes sense to implement [`OverflowingFrom`] as
172/// well.
173pub trait WrappingFrom<T>: Sized {
174    fn wrapping_from(value: T) -> Self;
175}
176
177/// Converts a value from one type to another, where if the conversion is not exact the result will
178/// wrap around.
179///
180/// It is recommended that this trait is not implemented directly; it is automatically implemented
181/// when [`WrappingFrom`] is implemented.
182pub trait WrappingInto<T>: Sized {
183    fn wrapping_into(self) -> T;
184}
185
186impl<T, U: WrappingFrom<T>> WrappingInto<U> for T {
187    #[inline]
188    fn wrapping_into(self) -> U {
189        U::wrapping_from(self)
190    }
191}
192
193/// Converts a value from one type to another, where if the conversion is not exact the result is
194/// set to the maximum or minimum value of the result type, whichever is closer.
195pub trait SaturatingFrom<T>: Sized {
196    fn saturating_from(value: T) -> Self;
197}
198
199/// Converts a value from one type to another, where if the conversion is not exact the result is
200/// set to the maximum or minimum value of the result type, whichever is closer.
201///
202/// It is recommended that this trait is not implemented directly; it is automatically implemented
203/// when [`SaturatingFrom`] is implemented.
204pub trait SaturatingInto<T>: Sized {
205    fn saturating_into(self) -> T;
206}
207
208impl<T, U: SaturatingFrom<T>> SaturatingInto<U> for T {
209    #[inline]
210    fn saturating_into(self) -> U {
211        U::saturating_from(self)
212    }
213}
214
215/// Converts a value from one type to another, where if the conversion is not exact the result will
216/// wrap around. The result is returned along with a [`bool`] that indicates whether wrapping has
217/// occurred.
218///
219/// If `OverflowingFrom` is implemented, it usually makes sense to implement [`WrappingFrom`] as
220/// well.
221pub trait OverflowingFrom<T>: Sized {
222    fn overflowing_from(value: T) -> (Self, bool);
223}
224
225/// Converts a value from one type to another, where if the conversion is not exact the result will
226/// wrap around. The result is returned along with a [`bool`] that indicates whether wrapping has
227/// occurred.
228///
229/// It is recommended that this trait is not implemented directly; it is automatically implemented
230/// when [`OverflowingFrom`] is implemented.
231pub trait OverflowingInto<T>: Sized {
232    fn overflowing_into(self) -> (T, bool);
233}
234
235impl<T, U: OverflowingFrom<T>> OverflowingInto<U> for T {
236    #[inline]
237    fn overflowing_into(self) -> (U, bool) {
238        U::overflowing_from(self)
239    }
240}
241
242/// Converts a value from one type to another, where the conversion is made according to a specified
243/// [`RoundingMode`]. An [`Ordering`] is also returned, indicating whether the returned value is
244/// less than, equal to, or greater than the original value.
245pub trait RoundingFrom<T>: Sized {
246    fn rounding_from(value: T, rm: RoundingMode) -> (Self, Ordering);
247}
248
249/// Converts a value from one type to another, where the conversion is made according to a specified
250/// [`RoundingMode`]. An [`Ordering`] is also returned, indicating whether the returned value is
251/// less than, equal to, or greater than the original value.
252///
253/// It is recommended that this trait is not implemented directly; it is automatically implemented
254/// when [`RoundingFrom`] is implemented.
255pub trait RoundingInto<T>: Sized {
256    fn rounding_into(self, rm: RoundingMode) -> (T, Ordering);
257}
258
259impl<T, U: RoundingFrom<T>> RoundingInto<U> for T {
260    #[inline]
261    fn rounding_into(self, rm: RoundingMode) -> (U, Ordering) {
262        U::rounding_from(self, rm)
263    }
264}
265
266/// Tests whether a value of one type is convertible into a value of another.
267///
268/// If `ConvertibleFrom<T>` for `Self` is implemented, it usually makes sense to implement
269/// [`TryFrom`] for `T` as well.
270pub trait ConvertibleFrom<T> {
271    fn convertible_from(value: T) -> bool;
272}
273
274/// Converts a value to a purely imaginary value of a complex type: the value becomes the imaginary
275/// part, and the real part is zero.
276///
277/// No type in this crate implements this trait; it exists for complex types downstream, like
278/// Gaussian integers.
279pub trait ImaginaryFrom<T>: Sized {
280    fn imaginary_from(value: T) -> Self;
281}
282
283/// Converts a value to a purely imaginary value of a complex type: the value becomes the imaginary
284/// part, and the real part is zero.
285///
286/// It is recommended that this trait is not implemented directly; it is automatically implemented
287/// when [`ImaginaryFrom`] is implemented.
288pub trait ImaginaryInto<T> {
289    fn imaginary_into(self) -> T;
290}
291
292impl<T, U: ImaginaryFrom<T>> ImaginaryInto<U> for T {
293    #[inline]
294    fn imaginary_into(self) -> U {
295        U::imaginary_from(self)
296    }
297}
298
299/// Associates with `Self` a type that's half `Self`'s size.
300pub trait HasHalf {
301    /// The type that's half the size of `Self`.
302    type Half;
303}
304
305/// Provides a function to join two pieces into a number. For example, two [`u32`]s may be joined to
306/// form a [`u64`].
307pub trait JoinHalves: HasHalf {
308    /// Joins two values into a single value; the upper, or most-significant, half comes first.
309    fn join_halves(upper: Self::Half, lower: Self::Half) -> Self;
310}
311
312/// Provides functions to split a number into two pieces. For example, a [`u64`] may be split into
313/// two [`u32`]s.
314pub trait SplitInHalf: HasHalf {
315    /// Extracts the lower, or least-significant, half of a number.
316    fn lower_half(&self) -> Self::Half;
317
318    /// Extracts the upper, or most-significant half of a number.
319    fn upper_half(&self) -> Self::Half;
320
321    /// Extracts both halves of a number; the upper, or most-significant, half comes first.
322    ///
323    /// # Worst-case complexity
324    /// $T(n) = O(\max(T_U(n), T_L(n)))$
325    ///
326    /// $M(n) = O(\max(M_U(n), M_L(n)))$
327    ///
328    /// where $T$ is time, $M$ is additional memory, $T_U$ and $T_L$ are the time complexities of
329    /// the [`upper_half`](Self::upper_half) and [`lower_half`](Self::lower_half) functions,
330    /// respectively, and $M_U$ and $M_L$ are the memory complexities of the
331    /// [`upper_half`](Self::upper_half) and [`lower_half`](Self::lower_half) functions,
332    /// respectively.
333    // This default implementation is the one place where taking the two halves separately is the
334    // point, rather than a missed `split_in_half` call.
335    #[cfg_attr(dylint_lib = "malachite_lints", allow(use_split_in_half))]
336    #[inline]
337    fn split_in_half(&self) -> (Self::Half, Self::Half) {
338        (self.upper_half(), self.lower_half())
339    }
340}
341
342/// Determines whether a number is an integer.
343pub trait IsInteger {
344    #[allow(clippy::wrong_self_convention)]
345    fn is_integer(self) -> bool;
346}
347
348/// Tests whether a value is equal to a Gaussian integer: a complex number whose real and imaginary
349/// parts are both integers.
350///
351/// For real-valued types, this is equivalent to [`IsInteger`]. In general, `x.is_integer() ==
352/// x.is_gaussian_integer() && x.is_real()`.
353pub trait IsGaussianInteger {
354    #[allow(clippy::wrong_self_convention)]
355    fn is_gaussian_integer(self) -> bool;
356}
357
358/// Tests whether a value is equal to a real number.
359///
360/// For complex types this means that the imaginary part is zero. For floating-point types, `NaN`
361/// and the infinities are not real numbers. In general, `x.is_integer() == x.is_gaussian_integer()
362/// && x.is_real()`.
363pub trait IsReal {
364    #[allow(clippy::wrong_self_convention)]
365    fn is_real(self) -> bool;
366}
367
368/// Converts a number to or from a raw mantissa and exponent.
369///
370/// See [here](crate::num::basic::floats::PrimitiveFloat) for a definition of raw mantissa and
371/// exponent.
372pub trait RawMantissaAndExponent<M, E, T = Self>: Sized {
373    /// Extracts the raw mantissa and exponent from a number.
374    fn raw_mantissa_and_exponent(self) -> (M, E);
375
376    /// Extracts the raw mantissa from a number.
377    fn raw_mantissa(self) -> M {
378        self.raw_mantissa_and_exponent().0
379    }
380
381    /// Extracts the raw exponent from a number.
382    fn raw_exponent(self) -> E {
383        self.raw_mantissa_and_exponent().1
384    }
385
386    /// Constructs a number from its raw mantissa and exponent.
387    fn from_raw_mantissa_and_exponent(raw_mantissa: M, raw_exponent: E) -> T;
388}
389
390/// Converts a number to or from an integer mantissa and exponent.
391///
392/// See [here](crate::num::basic::floats::PrimitiveFloat) for a definition of integer mantissa and
393/// exponent.
394///
395/// The mantissa is an odd integer, and the exponent is an integer, such that $x = 2^em$.
396pub trait IntegerMantissaAndExponent<M, E, T = Self>: Sized {
397    /// Extracts the integer mantissa and exponent from a number.
398    fn integer_mantissa_and_exponent(self) -> (M, E);
399
400    /// Extracts the integer mantissa from a number.
401    fn integer_mantissa(self) -> M {
402        self.integer_mantissa_and_exponent().0
403    }
404
405    /// Extracts the integer exponent from a number.
406    fn integer_exponent(self) -> E {
407        self.integer_mantissa_and_exponent().1
408    }
409
410    /// Constructs a number from its integer mantissa and exponent.
411    fn from_integer_mantissa_and_exponent(integer_mantissa: M, integer_exponent: E) -> Option<T>;
412}
413
414/// Converts a number to or from a scientific mantissa and exponent.
415///
416/// See [here](crate::num::basic::floats::PrimitiveFloat) for a definition of scientific mantissa
417/// and exponent.
418pub trait SciMantissaAndExponent<M, E, T = Self>: Sized {
419    /// Extracts the scientific mantissa and exponent from a number.
420    fn sci_mantissa_and_exponent(self) -> (M, E);
421
422    /// Extracts the scientific mantissa from a number.
423    fn sci_mantissa(self) -> M {
424        self.sci_mantissa_and_exponent().0
425    }
426
427    /// Extracts the scientific exponent from a number.
428    fn sci_exponent(self) -> E {
429        self.sci_mantissa_and_exponent().1
430    }
431
432    /// Constructs a number from its scientific mantissa and exponent.
433    fn from_sci_mantissa_and_exponent(sci_mantissa: M, sci_exponent: E) -> Option<T>;
434}
435
436/// Converts a slice of one type of value to a single value of another type.
437pub trait FromOtherTypeSlice<T: Sized> {
438    fn from_other_type_slice(slice: &[T]) -> Self;
439}
440
441/// Converts a slice of one type of value to a [`Vec`] of another type.
442pub trait VecFromOtherTypeSlice<T: Sized>: Sized {
443    fn vec_from_other_type_slice(slice: &[T]) -> Vec<Self>;
444}
445
446/// Converts a slice of one type of value to a [`Vec`] of another type.
447pub trait VecFromOtherType<T>: Sized {
448    fn vec_from_other_type(value: T) -> Vec<Self>;
449}