malachite_float/conversion/
primitive_float_from_float.rs1use crate::InnerFloat::{Finite, Infinity, NaN, Zero};
10use crate::{significand_bits, Float};
11use core::cmp::Ordering::{self, *};
12use malachite_base::num::arithmetic::traits::{DivisibleByPowerOf2, IsPowerOf2, ShrRound};
13use malachite_base::num::basic::floats::PrimitiveFloat;
14use malachite_base::num::conversion::traits::{ConvertibleFrom, RoundingFrom, WrappingFrom};
15use malachite_base::num::logic::traits::SignificantBits;
16use malachite_base::rounding_modes::RoundingMode::{self, *};
17
18fn primitive_float_rounding_from_float<T: PrimitiveFloat>(
19 f: Float,
20 rm: RoundingMode,
21) -> (T, Ordering) {
22 match f {
23 float_nan!() => (T::NAN, Equal),
24 float_infinity!() => (T::INFINITY, Equal),
25 float_negative_infinity!() => (T::NEGATIVE_INFINITY, Equal),
26 float_zero!() => (T::ZERO, Equal),
27 float_negative_zero!() => (T::NEGATIVE_ZERO, Equal),
28 Float(Finite {
29 sign,
30 exponent,
31 significand,
32 ..
33 }) => {
34 let abs_rm = if sign { rm } else { -rm };
35 let (x, o) = {
36 let exponent = i64::from(exponent) - 1;
37 if exponent < T::MIN_EXPONENT {
38 match abs_rm {
39 Floor | Down => (T::ZERO, Less),
40 Ceiling | Up => (T::MIN_POSITIVE_SUBNORMAL, Greater),
41 Nearest => {
42 if exponent == T::MIN_EXPONENT - 1 && !significand.is_power_of_2() {
43 (T::MIN_POSITIVE_SUBNORMAL, Greater)
44 } else {
45 (T::ZERO, Less)
46 }
47 }
48 Exact => panic!("Float too small for exact conversion"),
49 }
50 } else if exponent > T::MAX_EXPONENT {
51 match abs_rm {
52 Floor | Down | Nearest => (T::MAX_FINITE, Less),
53 Ceiling | Up => (T::INFINITY, Greater),
54 Exact => panic!("Float too large for exact conversion"),
55 }
56 } else {
57 let target_prec = T::max_precision_for_sci_exponent(exponent);
58 let bits = significand_bits(&significand);
59 let (mantissa, o) =
60 significand.shr_round(i128::from(bits) - i128::from(target_prec), abs_rm);
61 let mantissa = u64::wrapping_from(&mantissa);
62 if mantissa.significant_bits() > target_prec {
63 if exponent == T::MAX_EXPONENT {
64 match abs_rm {
65 Floor | Down | Nearest => (T::MAX_FINITE, Less),
66 Ceiling | Up => (T::INFINITY, Greater),
67
68 Exact => {
69 panic!("Float too large for exact conversion")
70 }
71 }
72 } else {
73 (
74 T::from_integer_mantissa_and_exponent(
75 mantissa >> 1,
76 exponent - i64::wrapping_from(target_prec) + 2,
77 )
78 .unwrap(),
79 o,
80 )
81 }
82 } else {
83 (
84 T::from_integer_mantissa_and_exponent(
85 mantissa,
86 exponent - i64::wrapping_from(target_prec) + 1,
87 )
88 .unwrap(),
89 o,
90 )
91 }
92 }
93 };
94 if sign {
95 (x, o)
96 } else {
97 (-x, o.reverse())
98 }
99 }
100 }
101}
102
103fn primitive_float_rounding_from_float_ref<T: PrimitiveFloat>(
104 f: &Float,
105 rm: RoundingMode,
106) -> (T, Ordering) {
107 match f {
108 float_nan!() => (T::NAN, Equal),
109 float_infinity!() => (T::INFINITY, Equal),
110 float_negative_infinity!() => (T::NEGATIVE_INFINITY, Equal),
111 float_zero!() => (T::ZERO, Equal),
112 float_negative_zero!() => (T::NEGATIVE_ZERO, Equal),
113 Float(Finite {
114 sign,
115 exponent,
116 significand,
117 ..
118 }) => {
119 let abs_rm = if *sign { rm } else { -rm };
120 let (x, o) = {
121 let exponent = i64::from(*exponent) - 1;
122 if exponent < T::MIN_EXPONENT {
123 match abs_rm {
124 Floor | Down => (T::ZERO, Less),
125 Ceiling | Up => (T::MIN_POSITIVE_SUBNORMAL, Greater),
126 Nearest => {
127 if exponent == T::MIN_EXPONENT - 1 && !significand.is_power_of_2() {
128 (T::MIN_POSITIVE_SUBNORMAL, Greater)
129 } else {
130 (T::ZERO, Less)
131 }
132 }
133 Exact => panic!("Float too small for exact conversion"),
134 }
135 } else if exponent > T::MAX_EXPONENT {
136 match abs_rm {
137 Floor | Down | Nearest => (T::MAX_FINITE, Less),
138 Ceiling | Up => (T::INFINITY, Greater),
139 Exact => panic!("Float too large for exact conversion"),
140 }
141 } else {
142 let target_prec = T::max_precision_for_sci_exponent(exponent);
143 let bits = significand_bits(significand);
144 let (mantissa, o) =
145 significand.shr_round(i128::from(bits) - i128::from(target_prec), abs_rm);
146 let mantissa = u64::wrapping_from(&mantissa);
147 if mantissa.significant_bits() > target_prec {
148 if exponent == T::MAX_EXPONENT {
149 match abs_rm {
150 Floor | Down | Nearest => (T::MAX_FINITE, Less),
151 Ceiling | Up => (T::INFINITY, Greater),
152
153 Exact => {
154 panic!("Float too large for exact conversion")
155 }
156 }
157 } else {
158 (
159 T::from_integer_mantissa_and_exponent(
160 mantissa >> 1,
161 exponent - i64::wrapping_from(target_prec) + 2,
162 )
163 .unwrap(),
164 o,
165 )
166 }
167 } else {
168 (
169 T::from_integer_mantissa_and_exponent(
170 mantissa,
171 exponent - i64::wrapping_from(target_prec) + 1,
172 )
173 .unwrap(),
174 o,
175 )
176 }
177 }
178 };
179 if *sign {
180 (x, o)
181 } else {
182 (-x, o.reverse())
183 }
184 }
185 }
186}
187
188#[derive(Clone, Copy, Debug, Eq, PartialEq)]
189pub enum FloatFromFloatError {
190 Overflow,
191 Underflow,
192 Inexact,
193}
194
195fn primitive_float_try_from_float<T: PrimitiveFloat>(f: Float) -> Result<T, FloatFromFloatError> {
196 match f {
197 float_nan!() => Ok(T::NAN),
198 float_infinity!() => Ok(T::INFINITY),
199 float_negative_infinity!() => Ok(T::NEGATIVE_INFINITY),
200 float_zero!() => Ok(T::ZERO),
201 float_negative_zero!() => Ok(T::NEGATIVE_ZERO),
202 Float(Finite {
203 sign,
204 exponent,
205 significand,
206 ..
207 }) => {
208 let x = {
209 let exponent = i64::from(exponent) - 1;
210 if exponent < T::MIN_EXPONENT {
211 return Err(FloatFromFloatError::Underflow);
212 } else if exponent > T::MAX_EXPONENT {
213 return Err(FloatFromFloatError::Overflow);
214 }
215 let target_prec = T::max_precision_for_sci_exponent(exponent);
216 let bits = significand_bits(&significand);
217 if bits > target_prec && !significand.divisible_by_power_of_2(bits - target_prec) {
218 return Err(FloatFromFloatError::Inexact);
219 }
220 let mantissa = u64::wrapping_from(
221 &(significand >> (i128::from(bits) - i128::from(target_prec))),
222 );
223 T::from_integer_mantissa_and_exponent(
224 mantissa,
225 exponent - i64::wrapping_from(target_prec) + 1,
226 )
227 .unwrap()
228 };
229 Ok(if sign { x } else { -x })
230 }
231 }
232}
233
234fn primitive_float_try_from_float_ref<T: PrimitiveFloat>(
235 f: &Float,
236) -> Result<T, FloatFromFloatError> {
237 match f {
238 float_nan!() => Ok(T::NAN),
239 float_infinity!() => Ok(T::INFINITY),
240 float_negative_infinity!() => Ok(T::NEGATIVE_INFINITY),
241 float_zero!() => Ok(T::ZERO),
242 float_negative_zero!() => Ok(T::NEGATIVE_ZERO),
243 Float(Finite {
244 sign,
245 exponent,
246 significand,
247 ..
248 }) => {
249 let x = if *significand == 0u32 {
250 T::ZERO
251 } else {
252 let exponent = i64::from(*exponent) - 1;
253 if exponent < T::MIN_EXPONENT {
254 return Err(FloatFromFloatError::Underflow);
255 } else if exponent > T::MAX_EXPONENT {
256 return Err(FloatFromFloatError::Overflow);
257 }
258 let target_prec = T::max_precision_for_sci_exponent(exponent);
259 let bits = significand_bits(significand);
260 if bits > target_prec && !significand.divisible_by_power_of_2(bits - target_prec) {
261 return Err(FloatFromFloatError::Inexact);
262 }
263 let mantissa = u64::wrapping_from(
264 &(significand >> (i128::from(bits) - i128::from(target_prec))),
265 );
266 T::from_integer_mantissa_and_exponent(
267 mantissa,
268 exponent - i64::wrapping_from(target_prec) + 1,
269 )
270 .unwrap()
271 };
272 Ok(if *sign { x } else { -x })
273 }
274 }
275}
276
277fn primitive_float_convertible_from_float<T: PrimitiveFloat>(f: &Float) -> bool {
278 match f {
279 Float(Finite {
280 exponent,
281 significand,
282 ..
283 }) => {
284 let exponent = i64::from(*exponent) - 1;
285 exponent >= T::MIN_EXPONENT && exponent <= T::MAX_EXPONENT && {
286 let target_prec = T::max_precision_for_sci_exponent(exponent);
287 let bits = significand_bits(significand);
288 bits <= target_prec || significand.divisible_by_power_of_2(bits - target_prec)
289 }
290 }
291 _ => true,
292 }
293}
294
295macro_rules! impl_primitive_float_from {
296 ($t: ident) => {
297 impl RoundingFrom<Float> for $t {
298 #[inline]
314 fn rounding_from(f: Float, rm: RoundingMode) -> ($t, Ordering) {
315 primitive_float_rounding_from_float(f, rm)
316 }
317 }
318
319 impl RoundingFrom<&Float> for $t {
320 #[inline]
336 fn rounding_from(f: &Float, rm: RoundingMode) -> ($t, Ordering) {
337 primitive_float_rounding_from_float_ref(f, rm)
338 }
339 }
340
341 impl TryFrom<Float> for $t {
342 type Error = FloatFromFloatError;
343
344 #[inline]
353 fn try_from(f: Float) -> Result<$t, Self::Error> {
354 primitive_float_try_from_float(f)
355 }
356 }
357
358 impl TryFrom<&Float> for $t {
359 type Error = FloatFromFloatError;
360
361 #[inline]
370 fn try_from(f: &Float) -> Result<$t, Self::Error> {
371 primitive_float_try_from_float_ref(f)
372 }
373 }
374
375 impl ConvertibleFrom<&Float> for $t {
376 #[inline]
385 fn convertible_from(f: &Float) -> bool {
386 primitive_float_convertible_from_float::<$t>(f)
387 }
388 }
389 };
390}
391apply_to_primitive_floats!(impl_primitive_float_from);