malachite_float/conversion/
primitive_float_from_float.rs1use crate::InnerFloat::{Finite, Infinity, NaN, Zero};
10use crate::{Float, significand_bits};
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 { (x, o) } else { (-x, o.reverse()) }
95 }
96 }
97}
98
99fn primitive_float_rounding_from_float_ref<T: PrimitiveFloat>(
100 f: &Float,
101 rm: RoundingMode,
102) -> (T, Ordering) {
103 match f {
104 float_nan!() => (T::NAN, Equal),
105 float_infinity!() => (T::INFINITY, Equal),
106 float_negative_infinity!() => (T::NEGATIVE_INFINITY, Equal),
107 float_zero!() => (T::ZERO, Equal),
108 float_negative_zero!() => (T::NEGATIVE_ZERO, Equal),
109 Float(Finite {
110 sign,
111 exponent,
112 significand,
113 ..
114 }) => {
115 let abs_rm = if *sign { rm } else { -rm };
116 let (x, o) = {
117 let exponent = i64::from(*exponent) - 1;
118 if exponent < T::MIN_EXPONENT {
119 match abs_rm {
120 Floor | Down => (T::ZERO, Less),
121 Ceiling | Up => (T::MIN_POSITIVE_SUBNORMAL, Greater),
122 Nearest => {
123 if exponent == T::MIN_EXPONENT - 1 && !significand.is_power_of_2() {
124 (T::MIN_POSITIVE_SUBNORMAL, Greater)
125 } else {
126 (T::ZERO, Less)
127 }
128 }
129 Exact => panic!("Float too small for exact conversion"),
130 }
131 } else if exponent > T::MAX_EXPONENT {
132 match abs_rm {
133 Floor | Down | Nearest => (T::MAX_FINITE, Less),
134 Ceiling | Up => (T::INFINITY, Greater),
135 Exact => panic!("Float too large for exact conversion"),
136 }
137 } else {
138 let target_prec = T::max_precision_for_sci_exponent(exponent);
139 let bits = significand_bits(significand);
140 let (mantissa, o) =
141 significand.shr_round(i128::from(bits) - i128::from(target_prec), abs_rm);
142 let mantissa = u64::wrapping_from(&mantissa);
143 if mantissa.significant_bits() > target_prec {
144 if exponent == T::MAX_EXPONENT {
145 match abs_rm {
146 Floor | Down | Nearest => (T::MAX_FINITE, Less),
147 Ceiling | Up => (T::INFINITY, Greater),
148
149 Exact => {
150 panic!("Float too large for exact conversion")
151 }
152 }
153 } else {
154 (
155 T::from_integer_mantissa_and_exponent(
156 mantissa >> 1,
157 exponent - i64::wrapping_from(target_prec) + 2,
158 )
159 .unwrap(),
160 o,
161 )
162 }
163 } else {
164 (
165 T::from_integer_mantissa_and_exponent(
166 mantissa,
167 exponent - i64::wrapping_from(target_prec) + 1,
168 )
169 .unwrap(),
170 o,
171 )
172 }
173 }
174 };
175 if *sign { (x, o) } else { (-x, o.reverse()) }
176 }
177 }
178}
179
180#[derive(Clone, Copy, Debug, Eq, PartialEq)]
181pub enum FloatFromFloatError {
182 Overflow,
183 Underflow,
184 Inexact,
185}
186
187fn primitive_float_try_from_float<T: PrimitiveFloat>(f: Float) -> Result<T, FloatFromFloatError> {
188 match f {
189 float_nan!() => Ok(T::NAN),
190 float_infinity!() => Ok(T::INFINITY),
191 float_negative_infinity!() => Ok(T::NEGATIVE_INFINITY),
192 float_zero!() => Ok(T::ZERO),
193 float_negative_zero!() => Ok(T::NEGATIVE_ZERO),
194 Float(Finite {
195 sign,
196 exponent,
197 significand,
198 ..
199 }) => {
200 let x = {
201 let exponent = i64::from(exponent) - 1;
202 if exponent < T::MIN_EXPONENT {
203 return Err(FloatFromFloatError::Underflow);
204 } else if exponent > T::MAX_EXPONENT {
205 return Err(FloatFromFloatError::Overflow);
206 }
207 let target_prec = T::max_precision_for_sci_exponent(exponent);
208 let bits = significand_bits(&significand);
209 if bits > target_prec && !significand.divisible_by_power_of_2(bits - target_prec) {
210 return Err(FloatFromFloatError::Inexact);
211 }
212 let mantissa = u64::wrapping_from(
213 &(significand >> (i128::from(bits) - i128::from(target_prec))),
214 );
215 T::from_integer_mantissa_and_exponent(
216 mantissa,
217 exponent - i64::wrapping_from(target_prec) + 1,
218 )
219 .unwrap()
220 };
221 Ok(if sign { x } else { -x })
222 }
223 }
224}
225
226fn primitive_float_try_from_float_ref<T: PrimitiveFloat>(
227 f: &Float,
228) -> Result<T, FloatFromFloatError> {
229 match f {
230 float_nan!() => Ok(T::NAN),
231 float_infinity!() => Ok(T::INFINITY),
232 float_negative_infinity!() => Ok(T::NEGATIVE_INFINITY),
233 float_zero!() => Ok(T::ZERO),
234 float_negative_zero!() => Ok(T::NEGATIVE_ZERO),
235 Float(Finite {
236 sign,
237 exponent,
238 significand,
239 ..
240 }) => {
241 let x = if *significand == 0u32 {
242 T::ZERO
243 } else {
244 let exponent = i64::from(*exponent) - 1;
245 if exponent < T::MIN_EXPONENT {
246 return Err(FloatFromFloatError::Underflow);
247 } else if exponent > T::MAX_EXPONENT {
248 return Err(FloatFromFloatError::Overflow);
249 }
250 let target_prec = T::max_precision_for_sci_exponent(exponent);
251 let bits = significand_bits(significand);
252 if bits > target_prec && !significand.divisible_by_power_of_2(bits - target_prec) {
253 return Err(FloatFromFloatError::Inexact);
254 }
255 let mantissa = u64::wrapping_from(
256 &(significand >> (i128::from(bits) - i128::from(target_prec))),
257 );
258 T::from_integer_mantissa_and_exponent(
259 mantissa,
260 exponent - i64::wrapping_from(target_prec) + 1,
261 )
262 .unwrap()
263 };
264 Ok(if *sign { x } else { -x })
265 }
266 }
267}
268
269fn primitive_float_convertible_from_float<T: PrimitiveFloat>(f: &Float) -> bool {
270 match f {
271 Float(Finite {
272 exponent,
273 significand,
274 ..
275 }) => {
276 let exponent = i64::from(*exponent) - 1;
277 exponent >= T::MIN_EXPONENT && exponent <= T::MAX_EXPONENT && {
278 let target_prec = T::max_precision_for_sci_exponent(exponent);
279 let bits = significand_bits(significand);
280 bits <= target_prec || significand.divisible_by_power_of_2(bits - target_prec)
281 }
282 }
283 _ => true,
284 }
285}
286
287macro_rules! impl_primitive_float_from {
288 ($t: ident) => {
289 impl RoundingFrom<Float> for $t {
290 #[inline]
306 fn rounding_from(f: Float, rm: RoundingMode) -> ($t, Ordering) {
307 primitive_float_rounding_from_float(f, rm)
308 }
309 }
310
311 impl RoundingFrom<&Float> for $t {
312 #[inline]
328 fn rounding_from(f: &Float, rm: RoundingMode) -> ($t, Ordering) {
329 primitive_float_rounding_from_float_ref(f, rm)
330 }
331 }
332
333 impl TryFrom<Float> for $t {
334 type Error = FloatFromFloatError;
335
336 #[inline]
345 fn try_from(f: Float) -> Result<$t, Self::Error> {
346 primitive_float_try_from_float(f)
347 }
348 }
349
350 impl TryFrom<&Float> for $t {
351 type Error = FloatFromFloatError;
352
353 #[inline]
362 fn try_from(f: &Float) -> Result<$t, Self::Error> {
363 primitive_float_try_from_float_ref(f)
364 }
365 }
366
367 impl ConvertibleFrom<&Float> for $t {
368 #[inline]
377 fn convertible_from(f: &Float) -> bool {
378 primitive_float_convertible_from_float::<$t>(f)
379 }
380 }
381 };
382}
383apply_to_primitive_floats!(impl_primitive_float_from);