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}