malachite_base/num/conversion/
traits.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
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(&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/// Associates with `Self` a type that's half `Self`'s size.
275pub trait HasHalf {
276    /// The type that's half the size of `Self`.
277    type Half;
278}
279
280/// Provides a function to join two pieces into a number. For example, two [`u32`]s may be joined to
281/// form a [`u64`].
282pub trait JoinHalves: HasHalf {
283    /// Joins two values into a single value; the upper, or most-significant, half comes first.
284    fn join_halves(upper: Self::Half, lower: Self::Half) -> Self;
285}
286
287/// Provides functions to split a number into two pieces. For example, a [`u64`] may be split into
288/// two [`u32`]s.
289pub trait SplitInHalf: HasHalf {
290    /// Extracts the lower, or least-significant, half of a number.
291    fn lower_half(&self) -> Self::Half;
292
293    /// Extracts the upper, or most-significant half of a number.
294    fn upper_half(&self) -> Self::Half;
295
296    /// Extracts both halves of a number; the upper, or most-significant, half comes first.
297    ///
298    /// # Worst-case complexity
299    /// $T(n) = O(\max(T_U(n), T_L(n)))$
300    ///
301    /// $M(n) = O(\max(M_U(n), M_L(n)))$
302    ///
303    /// where $T$ is time, $M$ is additional memory, $T_U$ and $T_L$ are the time complexities of
304    /// the [`upper_half`](Self::upper_half) and [`lower_half`](Self::lower_half) functions,
305    /// respectively, and $M_U$ and $M_L$ are the memory complexities of the
306    /// [`upper_half`](Self::upper_half) and [`lower_half`](Self::lower_half) functions,
307    /// respectively.
308    #[inline]
309    fn split_in_half(&self) -> (Self::Half, Self::Half) {
310        (self.upper_half(), self.lower_half())
311    }
312}
313
314/// Determines whether a number is an integer.
315pub trait IsInteger {
316    #[allow(clippy::wrong_self_convention)]
317    fn is_integer(self) -> bool;
318}
319
320/// Converts a number to or from a raw mantissa and exponent.
321///
322/// See [here](crate::num::basic::floats::PrimitiveFloat) for a definition of raw mantissa and
323/// exponent.
324pub trait RawMantissaAndExponent<M, E, T = Self>: Sized {
325    /// Extracts the raw mantissa and exponent from a number.
326    fn raw_mantissa_and_exponent(self) -> (M, E);
327
328    /// Extracts the raw mantissa from a number.
329    fn raw_mantissa(self) -> M {
330        self.raw_mantissa_and_exponent().0
331    }
332
333    /// Extracts the raw exponent from a number.
334    fn raw_exponent(self) -> E {
335        self.raw_mantissa_and_exponent().1
336    }
337
338    /// Constructs a number from its raw mantissa and exponent.
339    fn from_raw_mantissa_and_exponent(raw_mantissa: M, raw_exponent: E) -> T;
340}
341
342/// Converts a number to or from an integer mantissa and exponent.
343///
344/// See [here](crate::num::basic::floats::PrimitiveFloat) for a definition of integer mantissa and
345/// exponent.
346///
347/// The mantissa is an odd integer, and the exponent is an integer, such that $x = 2^em$.
348pub trait IntegerMantissaAndExponent<M, E, T = Self>: Sized {
349    /// Extracts the integer mantissa and exponent from a number.
350    fn integer_mantissa_and_exponent(self) -> (M, E);
351
352    /// Extracts the integer mantissa from a number.
353    fn integer_mantissa(self) -> M {
354        self.integer_mantissa_and_exponent().0
355    }
356
357    /// Extracts the integer exponent from a number.
358    fn integer_exponent(self) -> E {
359        self.integer_mantissa_and_exponent().1
360    }
361
362    /// Constructs a number from its integer mantissa and exponent.
363    fn from_integer_mantissa_and_exponent(integer_mantissa: M, integer_exponent: E) -> Option<T>;
364}
365
366/// Converts a number to or from a scientific mantissa and exponent.
367///
368/// See [here](crate::num::basic::floats::PrimitiveFloat) for a definition of scientific mantissa
369/// and exponent.
370pub trait SciMantissaAndExponent<M, E, T = Self>: Sized {
371    /// Extracts the scientific mantissa and exponent from a number.
372    fn sci_mantissa_and_exponent(self) -> (M, E);
373
374    /// Extracts the scientific mantissa from a number.
375    fn sci_mantissa(self) -> M {
376        self.sci_mantissa_and_exponent().0
377    }
378
379    /// Extracts the scientific exponent from a number.
380    fn sci_exponent(self) -> E {
381        self.sci_mantissa_and_exponent().1
382    }
383
384    /// Constructs a number from its scientific mantissa and exponent.
385    fn from_sci_mantissa_and_exponent(sci_mantissa: M, sci_exponent: E) -> Option<T>;
386}
387
388/// Converts a slice of one type of value to a single value of another type.
389pub trait FromOtherTypeSlice<T: Sized> {
390    fn from_other_type_slice(slice: &[T]) -> Self;
391}
392
393/// Converts a slice of one type of value to a [`Vec`] of another type.
394pub trait VecFromOtherTypeSlice<T: Sized>: Sized {
395    fn vec_from_other_type_slice(slice: &[T]) -> Vec<Self>;
396}
397
398/// Converts a slice of one type of value to a [`Vec`] of another type.
399pub trait VecFromOtherType<T>: Sized {
400    fn vec_from_other_type(value: T) -> Vec<Self>;
401}