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}