malachite_nz/integer/conversion/
primitive_int_from_integer.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::integer::Integer;
10use crate::natural::Natural;
11use core::ops::Neg;
12use malachite_base::comparison::traits::Min;
13use malachite_base::num::arithmetic::traits::{DivisibleByPowerOf2, WrappingNeg};
14use malachite_base::num::basic::integers::PrimitiveInt;
15use malachite_base::num::basic::traits::Zero;
16use malachite_base::num::conversion::traits::{
17    ConvertibleFrom, OverflowingFrom, SaturatingFrom, WrappingFrom,
18};
19use malachite_base::num::logic::traits::SignificantBits;
20
21#[derive(Clone, Copy, Debug, Eq, PartialEq)]
22pub struct UnsignedFromIntegerError;
23
24fn try_from_unsigned<'a, T: TryFrom<&'a Natural>>(
25    value: &'a Integer,
26) -> Result<T, UnsignedFromIntegerError> {
27    match *value {
28        Integer { sign: false, .. } => Err(UnsignedFromIntegerError),
29        Integer {
30            sign: true,
31            ref abs,
32        } => T::try_from(abs).map_err(|_| UnsignedFromIntegerError),
33    }
34}
35
36fn wrapping_from_unsigned<'a, T: WrappingFrom<&'a Natural> + WrappingNeg<Output = T>>(
37    value: &'a Integer,
38) -> T {
39    match *value {
40        Integer {
41            sign: true,
42            ref abs,
43        } => T::wrapping_from(abs),
44        Integer {
45            sign: false,
46            ref abs,
47        } => T::wrapping_from(abs).wrapping_neg(),
48    }
49}
50
51fn saturating_from_unsigned<'a, T: Copy + SaturatingFrom<&'a Natural> + Zero>(
52    value: &'a Integer,
53) -> T {
54    match *value {
55        Integer {
56            sign: true,
57            ref abs,
58        } => T::saturating_from(abs),
59        _ => T::ZERO,
60    }
61}
62
63fn overflowing_from_unsigned<
64    'a,
65    T: OverflowingFrom<&'a Natural> + WrappingFrom<&'a Natural> + WrappingNeg<Output = T>,
66>(
67    value: &'a Integer,
68) -> (T, bool) {
69    match *value {
70        Integer {
71            sign: true,
72            ref abs,
73        } => T::overflowing_from(abs),
74        Integer {
75            sign: false,
76            ref abs,
77        } => (T::wrapping_from(abs).wrapping_neg(), true),
78    }
79}
80
81#[derive(Clone, Copy, Debug, Eq, PartialEq)]
82pub struct SignedFromIntegerError;
83
84fn try_from_signed<'a, T: ConvertibleFrom<&'a Integer> + WrappingFrom<&'a Integer>>(
85    value: &'a Integer,
86) -> Result<T, SignedFromIntegerError> {
87    if T::convertible_from(value) {
88        Ok(T::wrapping_from(value))
89    } else {
90        Err(SignedFromIntegerError)
91    }
92}
93
94fn saturating_from_signed<
95    'a,
96    U: PrimitiveInt + SaturatingFrom<&'a Natural>,
97    S: Min + Neg<Output = S> + SaturatingFrom<U> + WrappingFrom<U>,
98>(
99    value: &'a Integer,
100) -> S {
101    match *value {
102        Integer {
103            sign: true,
104            ref abs,
105        } => S::saturating_from(U::saturating_from(abs)),
106        Integer {
107            sign: false,
108            ref abs,
109        } => {
110            let abs = U::saturating_from(abs);
111            if abs.get_highest_bit() {
112                S::MIN
113            } else {
114                -S::wrapping_from(abs)
115            }
116        }
117    }
118}
119
120fn convertible_from_signed<T: PrimitiveInt>(value: &Integer) -> bool {
121    match *value {
122        Integer {
123            sign: true,
124            ref abs,
125        } => abs.significant_bits() < T::WIDTH,
126        Integer {
127            sign: false,
128            ref abs,
129        } => {
130            let significant_bits = abs.significant_bits();
131            significant_bits < T::WIDTH
132                || significant_bits == T::WIDTH && abs.divisible_by_power_of_2(T::WIDTH - 1)
133        }
134    }
135}
136
137macro_rules! impl_from {
138    ($u: ident, $s: ident) => {
139        impl<'a> TryFrom<&'a Integer> for $u {
140            type Error = UnsignedFromIntegerError;
141
142            /// Converts an [`Integer`] to an unsigned primitive integer, returning an error if the
143            /// [`Integer`] cannot be represented.
144            ///
145            /// # Worst-case complexity
146            /// Constant time and additional memory.
147            ///
148            /// # Examples
149            /// See [here](super::primitive_int_from_integer#try_from).
150            #[inline]
151            fn try_from(value: &Integer) -> Result<$u, Self::Error> {
152                try_from_unsigned(value)
153            }
154        }
155
156        impl<'a> WrappingFrom<&'a Integer> for $u {
157            /// Converts an [`Integer`] to an unsigned primitive integer, wrapping modulo $2^W$,
158            /// where $W$ is the width of the primitive integer.
159            ///
160            /// # Worst-case complexity
161            /// Constant time and additional memory.
162            ///
163            /// # Examples
164            /// See [here](super::primitive_int_from_integer#wrapping_from).
165            #[inline]
166            fn wrapping_from(value: &Integer) -> $u {
167                wrapping_from_unsigned(value)
168            }
169        }
170
171        impl<'a> SaturatingFrom<&'a Integer> for $u {
172            /// Converts an [`Integer`] to an unsigned primitive integer.
173            ///
174            /// If the [`Integer`] cannot be represented by the output type, then either zero or the
175            /// maximum representable value is returned, whichever is closer.
176            ///
177            /// # Worst-case complexity
178            /// Constant time and additional memory.
179            ///
180            /// # Examples
181            /// See [here](super::primitive_int_from_integer#saturating_from).
182            #[inline]
183            fn saturating_from(value: &Integer) -> $u {
184                saturating_from_unsigned(value)
185            }
186        }
187
188        impl<'a> OverflowingFrom<&'a Integer> for $u {
189            /// Converts an [`Integer`] to an unsigned primitive integer, wrapping modulo $2^W$,
190            /// where $W$ is the width of the primitive integer.
191            ///
192            /// The returned boolean value indicates whether wrapping occurred.
193            ///
194            /// # Worst-case complexity
195            /// Constant time and additional memory.
196            ///
197            /// # Examples
198            /// See [here](super::primitive_int_from_integer#overflowing_from).
199            #[inline]
200            fn overflowing_from(value: &Integer) -> ($u, bool) {
201                overflowing_from_unsigned(value)
202            }
203        }
204
205        impl<'a> ConvertibleFrom<&'a Integer> for $u {
206            /// Determines whether an [`Integer`] can be converted to an unsigned primitive integer.
207            ///
208            /// # Worst-case complexity
209            /// Constant time and additional memory.
210            ///
211            /// # Examples
212            /// See [here](super::primitive_int_from_integer#convertible_from).
213            #[inline]
214            fn convertible_from(value: &Integer) -> bool {
215                value.sign && $u::convertible_from(&value.abs)
216            }
217        }
218
219        impl<'a> TryFrom<&'a Integer> for $s {
220            type Error = SignedFromIntegerError;
221
222            /// Converts an [`Integer`] to a signed primitive integer, returning an error if the
223            /// [`Integer`] cannot be represented.
224            ///
225            /// # Worst-case complexity
226            /// Constant time and additional memory.
227            ///
228            /// # Examples
229            /// See [here](super::primitive_int_from_integer#try_from).
230            #[inline]
231            fn try_from(value: &Integer) -> Result<$s, Self::Error> {
232                try_from_signed(value)
233            }
234        }
235
236        impl<'a> WrappingFrom<&'a Integer> for $s {
237            /// Converts an [`Integer`] to a signed primitive integer, wrapping modulo $2^W$, where
238            /// $W$ is the width of the primitive integer.
239            ///
240            /// # Worst-case complexity
241            /// Constant time and additional memory.
242            ///
243            /// # Examples
244            /// See [here](super::primitive_int_from_integer#wrapping_from).
245            #[inline]
246            fn wrapping_from(value: &Integer) -> $s {
247                $s::wrapping_from($u::wrapping_from(value))
248            }
249        }
250
251        impl<'a> SaturatingFrom<&'a Integer> for $s {
252            /// Converts an [`Integer`] to a signed primitive integer.
253            ///
254            /// If the [`Integer`] cannot be represented by the output type, then either the maximum
255            /// or the minimum representable value is returned, whichever is closer.
256            ///
257            /// # Worst-case complexity
258            /// Constant time and additional memory.
259            ///
260            /// # Examples
261            /// See [here](super::primitive_int_from_integer#saturating_from).
262            #[inline]
263            fn saturating_from(value: &Integer) -> $s {
264                saturating_from_signed::<$u, $s>(value)
265            }
266        }
267
268        impl<'a> OverflowingFrom<&'a Integer> for $s {
269            /// Converts an [`Integer`] to a signed primitive integer, wrapping modulo $2^W$, where
270            /// $W$ is the width of the primitive integer.
271            ///
272            /// The returned boolean value indicates whether wrapping occurred.
273            ///
274            /// # Worst-case complexity
275            /// Constant time and additional memory.
276            ///
277            /// # Examples
278            /// See [here](super::primitive_int_from_integer#overflowing_from).
279            #[inline]
280            fn overflowing_from(value: &Integer) -> ($s, bool) {
281                ($s::wrapping_from(value), !$s::convertible_from(value))
282            }
283        }
284
285        impl<'a> ConvertibleFrom<&'a Integer> for $s {
286            /// Determines whether an [`Integer`] can be converted to a signed primitive integer.
287            ///
288            /// # Worst-case complexity
289            /// Constant time and additional memory.
290            ///
291            /// # Examples
292            /// See [here](super::primitive_int_from_integer#convertible_from).
293            #[inline]
294            fn convertible_from(value: &Integer) -> bool {
295                convertible_from_signed::<$u>(value)
296            }
297        }
298    };
299}
300apply_to_unsigned_signed_pairs!(impl_from);