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);