malachite_float/conversion/integer_from_float.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::InnerFloat::{Finite, Zero};
10use crate::{Float, significand_bits};
11use core::cmp::Ordering::{self, *};
12use malachite_base::num::arithmetic::traits::{DivisibleByPowerOf2, ShrRound};
13use malachite_base::num::basic::traits::{One, Zero as ZeroTrait};
14use malachite_base::num::conversion::from::SignedFromFloatError;
15use malachite_base::num::conversion::traits::{ConvertibleFrom, RoundingFrom};
16use malachite_base::rounding_modes::RoundingMode::{self, *};
17use malachite_nz::integer::Integer;
18use malachite_nz::natural::Natural;
19
20impl RoundingFrom<Float> for Integer {
21 /// Converts a [`Float`] to an [`Integer`], using a specified [`RoundingMode`] and taking the
22 /// [`Float`] by value. An [`Ordering`] is also returned, indicating whether the returned value
23 /// is less than, equal to, or greater than the original value.
24 ///
25 /// If the [`Float`] is NaN or infinite, the function will panic regardless of the rounding
26 /// mode.
27 ///
28 /// # Worst-case complexity
29 /// $T(n) = O(n)$
30 ///
31 /// $M(n) = O(n)$
32 ///
33 /// where $T$ is time, $M$ is additional memory, and $n$ is `f.complexity()`.
34 ///
35 /// # Panics
36 /// Panics if the [`Float`] is not an integer and `rm` is `Exact`, or if the [`Float`] is NaN or
37 /// infinite.
38 ///
39 /// # Examples
40 /// ```
41 /// use malachite_base::num::conversion::traits::RoundingFrom;
42 /// use malachite_base::rounding_modes::RoundingMode::*;
43 /// use malachite_base::strings::ToDebugString;
44 /// use malachite_float::Float;
45 /// use malachite_nz::integer::Integer;
46 ///
47 /// assert_eq!(
48 /// Integer::rounding_from(Float::from(1.5), Floor).to_debug_string(),
49 /// "(1, Less)"
50 /// );
51 /// assert_eq!(
52 /// Integer::rounding_from(Float::from(1.5), Ceiling).to_debug_string(),
53 /// "(2, Greater)"
54 /// );
55 /// assert_eq!(
56 /// Integer::rounding_from(Float::from(1.5), Nearest).to_debug_string(),
57 /// "(2, Greater)"
58 /// );
59 ///
60 /// assert_eq!(
61 /// Integer::rounding_from(Float::from(-1.5), Floor).to_debug_string(),
62 /// "(-2, Less)"
63 /// );
64 /// assert_eq!(
65 /// Integer::rounding_from(Float::from(-1.5), Ceiling).to_debug_string(),
66 /// "(-1, Greater)"
67 /// );
68 /// assert_eq!(
69 /// Integer::rounding_from(Float::from(-1.5), Nearest).to_debug_string(),
70 /// "(-2, Less)"
71 /// );
72 /// ```
73 fn rounding_from(f: Float, rm: RoundingMode) -> (Self, Ordering) {
74 match f {
75 float_either_zero!() => (Self::ZERO, Equal),
76 Float(Finite {
77 sign,
78 exponent,
79 significand,
80 ..
81 }) => {
82 let abs_rm = if sign { rm } else { -rm };
83 let (abs_i, abs_o) = if exponent < 0 {
84 match abs_rm {
85 Floor | Down | Nearest => (Natural::ZERO, Less),
86 Ceiling | Up => (Natural::ONE, Greater),
87 Exact => {
88 panic!("Cannot convert Float to Integer using {rm}")
89 }
90 }
91 } else {
92 let sb = significand_bits(&significand);
93 let eb = u64::from(exponent.unsigned_abs());
94 if sb >= eb {
95 significand.shr_round(sb - eb, abs_rm)
96 } else {
97 (significand << (eb - sb), Equal)
98 }
99 };
100 if sign {
101 (Self::from(abs_i), abs_o)
102 } else {
103 (-abs_i, abs_o.reverse())
104 }
105 }
106 _ => panic!("Can't convert {f} to Integer using {rm}"),
107 }
108 }
109}
110
111impl RoundingFrom<&Float> for Integer {
112 /// Converts a [`Float`] to an [`Integer`], using a specified [`RoundingMode`] and taking the
113 /// [`Float`] by reference. An [`Ordering`] is also returned, indicating whether the returned
114 /// value is less than, equal to, or greater than the original value.
115 ///
116 /// If the [`Float`] is NaN or infinite, the function will panic regardless of the rounding
117 /// mode.
118 ///
119 /// # Worst-case complexity
120 /// $T(n) = O(n)$
121 ///
122 /// $M(n) = O(n)$
123 ///
124 /// where $T$ is time, $M$ is additional memory, and $n$ is `f.complexity()`.
125 ///
126 /// # Panics
127 /// Panics if the [`Float`] is not an integer and `rm` is `Exact`, or if the [`Float`] is NaN or
128 /// infinite.
129 ///
130 /// # Examples
131 /// ```
132 /// use malachite_base::num::conversion::traits::RoundingFrom;
133 /// use malachite_base::rounding_modes::RoundingMode::*;
134 /// use malachite_base::strings::ToDebugString;
135 /// use malachite_float::Float;
136 /// use malachite_nz::integer::Integer;
137 ///
138 /// assert_eq!(
139 /// Integer::rounding_from(&Float::from(1.5), Floor).to_debug_string(),
140 /// "(1, Less)"
141 /// );
142 /// assert_eq!(
143 /// Integer::rounding_from(&Float::from(1.5), Ceiling).to_debug_string(),
144 /// "(2, Greater)"
145 /// );
146 /// assert_eq!(
147 /// Integer::rounding_from(&Float::from(1.5), Nearest).to_debug_string(),
148 /// "(2, Greater)"
149 /// );
150 ///
151 /// assert_eq!(
152 /// Integer::rounding_from(&Float::from(-1.5), Floor).to_debug_string(),
153 /// "(-2, Less)"
154 /// );
155 /// assert_eq!(
156 /// Integer::rounding_from(&Float::from(-1.5), Ceiling).to_debug_string(),
157 /// "(-1, Greater)"
158 /// );
159 /// assert_eq!(
160 /// Integer::rounding_from(&Float::from(-1.5), Nearest).to_debug_string(),
161 /// "(-2, Less)"
162 /// );
163 /// ```
164 fn rounding_from(f: &Float, rm: RoundingMode) -> (Self, Ordering) {
165 match f {
166 float_either_zero!() => (Self::ZERO, Equal),
167 Float(Finite {
168 sign,
169 exponent,
170 significand,
171 ..
172 }) => {
173 if *significand == 0u32 {
174 (Self::ZERO, Equal)
175 } else {
176 let abs_rm = if *sign { rm } else { -rm };
177 let (abs_i, abs_o) = if *exponent < 0 {
178 match abs_rm {
179 Floor | Down | Nearest => (Natural::ZERO, Less),
180 Ceiling | Up => (Natural::ONE, Greater),
181 Exact => {
182 panic!("Cannot convert Float to Integer using {rm}")
183 }
184 }
185 } else {
186 let sb = significand_bits(significand);
187 let eb = u64::from(exponent.unsigned_abs());
188 if sb >= eb {
189 significand.shr_round(sb - eb, abs_rm)
190 } else {
191 (significand << (eb - sb), Equal)
192 }
193 };
194 if *sign {
195 (Self::from(abs_i), abs_o)
196 } else {
197 (-abs_i, abs_o.reverse())
198 }
199 }
200 }
201 _ => panic!("Can't convert {f} to Integer using {rm}"),
202 }
203 }
204}
205
206impl TryFrom<Float> for Integer {
207 type Error = SignedFromFloatError;
208
209 /// Converts a [`Float`] to an [`Integer`], taking the [`Float`] by value. If the [`Float`] is
210 /// not equal to an integer, an error is returned.
211 ///
212 /// # Worst-case complexity
213 /// $T(n) = O(n)$
214 ///
215 /// $M(n) = O(n)$
216 ///
217 /// where $T$ is time, $M$ is additional memory, and $n$ is `f.complexity()`.
218 ///
219 /// # Examples
220 /// ```
221 /// use malachite_base::num::basic::traits::{Infinity, NaN, Zero};
222 /// use malachite_base::num::conversion::from::SignedFromFloatError::*;
223 /// use malachite_float::Float;
224 /// use malachite_nz::integer::Integer;
225 ///
226 /// assert_eq!(Integer::try_from(Float::ZERO).unwrap(), 0);
227 /// assert_eq!(Integer::try_from(Float::from(123.0)).unwrap(), 123);
228 /// assert_eq!(Integer::try_from(Float::from(-123.0)).unwrap(), -123);
229 ///
230 /// assert_eq!(
231 /// Integer::try_from(Float::from(1.5)),
232 /// Err(FloatNonIntegerOrOutOfRange)
233 /// );
234 /// assert_eq!(Integer::try_from(Float::INFINITY), Err(FloatInfiniteOrNan));
235 /// assert_eq!(Integer::try_from(Float::NAN), Err(FloatInfiniteOrNan));
236 /// ```
237 fn try_from(f: Float) -> Result<Self, Self::Error> {
238 match f {
239 Float(Zero { .. }) => Ok(Self::ZERO),
240 Float(Finite {
241 sign,
242 exponent,
243 significand,
244 ..
245 }) => {
246 if exponent <= 0 {
247 Err(SignedFromFloatError::FloatNonIntegerOrOutOfRange)
248 } else {
249 let sb = significand_bits(&significand);
250 let eb = u64::from(exponent.unsigned_abs());
251 if sb >= eb {
252 let bits = sb - eb;
253 if significand.divisible_by_power_of_2(bits) {
254 Ok(Self::from_sign_and_abs(sign, significand >> bits))
255 } else {
256 Err(SignedFromFloatError::FloatNonIntegerOrOutOfRange)
257 }
258 } else {
259 Ok(Self::from_sign_and_abs(sign, significand << (eb - sb)))
260 }
261 }
262 }
263 _ => Err(SignedFromFloatError::FloatInfiniteOrNan),
264 }
265 }
266}
267
268impl TryFrom<&Float> for Integer {
269 type Error = SignedFromFloatError;
270
271 /// Converts a [`Float`] to an [`Integer`], taking the [`Float`] by reference. If the [`Float`]
272 /// is not equal to an integer, an error is returned.
273 ///
274 /// # Worst-case complexity
275 /// $T(n) = O(n)$
276 ///
277 /// $M(n) = O(n)$
278 ///
279 /// where $T$ is time, $M$ is additional memory, and $n$ is `f.complexity()`.
280 ///
281 /// # Examples
282 /// ```
283 /// use malachite_base::num::basic::traits::{Infinity, NaN, Zero};
284 /// use malachite_base::num::conversion::from::SignedFromFloatError::*;
285 /// use malachite_float::Float;
286 /// use malachite_nz::integer::Integer;
287 ///
288 /// assert_eq!(Integer::try_from(&Float::ZERO).unwrap(), 0);
289 /// assert_eq!(Integer::try_from(&Float::from(123.0)).unwrap(), 123);
290 /// assert_eq!(Integer::try_from(&Float::from(-123.0)).unwrap(), -123);
291 ///
292 /// assert_eq!(
293 /// Integer::try_from(&Float::from(1.5)),
294 /// Err(FloatNonIntegerOrOutOfRange)
295 /// );
296 /// assert_eq!(Integer::try_from(&Float::INFINITY), Err(FloatInfiniteOrNan));
297 /// assert_eq!(Integer::try_from(&Float::NAN), Err(FloatInfiniteOrNan));
298 /// ```
299 fn try_from(f: &Float) -> Result<Self, Self::Error> {
300 match f {
301 Float(Zero { .. }) => Ok(Self::ZERO),
302 Float(Finite {
303 sign,
304 exponent,
305 significand,
306 ..
307 }) => {
308 if *exponent <= 0 {
309 Err(SignedFromFloatError::FloatNonIntegerOrOutOfRange)
310 } else {
311 let sb = significand_bits(significand);
312 let eb = u64::from(exponent.unsigned_abs());
313 if sb >= eb {
314 let bits = sb - eb;
315 if significand.divisible_by_power_of_2(bits) {
316 Ok(Self::from_sign_and_abs(*sign, significand >> bits))
317 } else {
318 Err(SignedFromFloatError::FloatNonIntegerOrOutOfRange)
319 }
320 } else {
321 Ok(Self::from_sign_and_abs(*sign, significand << (eb - sb)))
322 }
323 }
324 }
325 _ => Err(SignedFromFloatError::FloatInfiniteOrNan),
326 }
327 }
328}
329
330impl ConvertibleFrom<&Float> for Integer {
331 /// Determines whether a [`Float`] can be converted to an [`Integer`], taking the [`Float`] by
332 /// reference.
333 ///
334 /// # Worst-case complexity
335 /// $T(n) = O(n)$
336 ///
337 /// $M(n) = O(n)$
338 ///
339 /// where $T$ is time, $M$ is additional memory, and $n$ is `f.significant_bits()`.
340 ///
341 /// # Examples
342 /// ```
343 /// use malachite_base::num::basic::traits::{Infinity, NaN, Zero};
344 /// use malachite_base::num::conversion::traits::ConvertibleFrom;
345 /// use malachite_float::Float;
346 /// use malachite_nz::integer::Integer;
347 ///
348 /// assert_eq!(Integer::convertible_from(&Float::ZERO), true);
349 /// assert_eq!(Integer::convertible_from(&Float::from(123.0)), true);
350 /// assert_eq!(Integer::convertible_from(&Float::from(-123.0)), true);
351 ///
352 /// assert_eq!(Integer::convertible_from(&Float::from(1.5)), false);
353 /// assert_eq!(Integer::convertible_from(&Float::INFINITY), false);
354 /// assert_eq!(Integer::convertible_from(&Float::NAN), false);
355 /// ```
356 fn convertible_from(f: &Float) -> bool {
357 match f {
358 Float(Zero { .. }) => true,
359 Float(Finite {
360 exponent,
361 significand,
362 ..
363 }) => {
364 *significand == 0u32
365 || *exponent > 0 && {
366 let sb = significand_bits(significand);
367 let eb = u64::from(exponent.unsigned_abs());
368 sb < eb || significand.divisible_by_power_of_2(sb - eb)
369 }
370 }
371 _ => false,
372 }
373 }
374}