reifydb_value/value/number/safe/convert/
f64.rs1use super::*;
5
6impl_safe_convert_float_demote!(f64 => f32);
7
8impl_safe_convert_float_to_signed!(f64 => i8, i16, i32, i64, i128);
9
10impl_safe_convert_float_to_unsigned!(f64 => u8, u16, u32, u64, u128);
11
12impl_safe_convert_to_decimal_from_float!(f64 => from_f64);
13
14#[cfg(test)]
15pub mod tests {
16
17 mod f32 {
18 use super::*;
19 use crate::value::number::safe::convert::SafeConvert;
20
21 #[test]
22 fn test_checked_convert_happy() {
23 let x: f64 = 123.0;
24 let y: Option<f32> = x.checked_convert();
25 assert_eq!(y, Some(123.0f32));
26 }
27
28 #[test]
29 fn test_checked_convert_unhappy_due_to_infinity() {
30 let x: f64 = f64::MAX;
31 let y: Option<f32> = x.checked_convert();
32 assert_eq!(y, None);
33 }
34
35 #[test]
36 fn test_checked_convert_unhappy_due_to_negative_infinity() {
37 let x: f64 = f64::MIN;
38 let y: Option<f32> = x.checked_convert();
39 assert_eq!(y, None);
40 }
41
42 #[test]
43 fn test_saturating_convert_within_range() {
44 let x: f64 = 456.789;
45 let y: f32 = x.saturating_convert();
46 assert_eq!(y, 456.789f32);
47 }
48
49 #[test]
50 fn test_saturating_convert_too_large() {
51 let x: f64 = f64::MAX;
52 let y: f32 = x.saturating_convert();
53 assert_eq!(y, f32::MAX);
54 }
55
56 #[test]
57 fn test_saturating_convert_too_small() {
58 let x: f64 = f64::MIN;
59 let y: f32 = x.saturating_convert();
60 assert_eq!(y, f32::MIN);
61 }
62
63 #[test]
64 fn test_saturating_convert_nan() {
65 let x: f64 = f64::NAN;
66 let y: f32 = x.saturating_convert();
67 assert!(y.is_nan());
68 }
69
70 #[test]
71 fn test_wrapping_convert_regular() {
72 let x: f64 = 789.123;
73 let y: f32 = x.wrapping_convert();
74 assert_eq!(y, 789.123f32);
75 }
76
77 #[test]
78 fn test_wrapping_convert_nan() {
79 let x: f64 = f64::NAN;
80 let y: f32 = x.wrapping_convert();
81 assert!(y.is_nan());
82 }
83
84 #[test]
85 fn test_wrapping_convert_infinity() {
86 let x: f64 = f64::INFINITY;
87 let y: f32 = x.wrapping_convert();
88 assert!(y.is_infinite() && y.is_sign_positive());
89 }
90 }
91
92 mod i8 {
93 use crate::value::number::safe::convert::SafeConvert;
94
95 #[test]
96 fn test_checked_convert_happy() {
97 let x: f64 = 42.0;
98 let y: Option<i8> = x.checked_convert();
99 assert_eq!(y, Some(42i8));
100 }
101
102 #[test]
103 fn test_checked_convert_unhappy() {
104 let x: f64 = 300.0;
105 let y: Option<i8> = x.checked_convert();
106 assert_eq!(y, None);
107 }
108
109 #[test]
110 fn test_checked_convert_negative() {
111 let x: f64 = -42.0;
112 let y: Option<i8> = x.checked_convert();
113 assert_eq!(y, Some(-42i8));
114 }
115
116 #[test]
117 fn test_checked_convert_nan() {
118 let x: f64 = f64::NAN;
119 let y: Option<i8> = x.checked_convert();
120 assert_eq!(y, None);
121 }
122
123 #[test]
124 fn test_checked_convert_infinity() {
125 let x: f64 = f64::INFINITY;
126 let y: Option<i8> = x.checked_convert();
127 assert_eq!(y, None);
128 }
129
130 #[test]
131 fn test_saturating_convert_overflow() {
132 let x: f64 = 300.0;
133 let y: i8 = x.saturating_convert();
134 assert_eq!(y, i8::MAX);
135 }
136
137 #[test]
138 fn test_saturating_convert_underflow() {
139 let x: f64 = -300.0;
140 let y: i8 = x.saturating_convert();
141 assert_eq!(y, i8::MIN);
142 }
143
144 #[test]
145 fn test_saturating_convert_nan() {
146 let x: f64 = f64::NAN;
147 let y: i8 = x.saturating_convert();
148 assert_eq!(y, 0);
149 }
150
151 #[test]
152 fn test_saturating_convert_infinity() {
153 let x: f64 = f64::INFINITY;
154 let y: i8 = x.saturating_convert();
155 assert_eq!(y, i8::MAX);
156 }
157
158 #[test]
159 fn test_saturating_convert_neg_infinity() {
160 let x: f64 = f64::NEG_INFINITY;
161 let y: i8 = x.saturating_convert();
162 assert_eq!(y, i8::MIN);
163 }
164
165 #[test]
166 fn test_wrapping_convert() {
167 let x: f64 = 42.0;
168 let y: i8 = x.wrapping_convert();
169 assert_eq!(y, 42i8);
170 }
171
172 #[test]
173 fn test_wrapping_convert_nan() {
174 let x: f64 = f64::NAN;
175 let y: i8 = x.wrapping_convert();
176 assert_eq!(y, 0);
177 }
178 }
179
180 mod i16 {
181 use crate::value::number::safe::convert::SafeConvert;
182
183 #[test]
184 fn test_checked_convert_happy() {
185 let x: f64 = 42.0;
186 let y: Option<i16> = x.checked_convert();
187 assert_eq!(y, Some(42i16));
188 }
189
190 #[test]
191 fn test_checked_convert_unhappy() {
192 let x: f64 = 40000.0;
193 let y: Option<i16> = x.checked_convert();
194 assert_eq!(y, None);
195 }
196
197 #[test]
198 fn test_checked_convert_negative() {
199 let x: f64 = -42.0;
200 let y: Option<i16> = x.checked_convert();
201 assert_eq!(y, Some(-42i16));
202 }
203
204 #[test]
205 fn test_checked_convert_nan() {
206 let x: f64 = f64::NAN;
207 let y: Option<i16> = x.checked_convert();
208 assert_eq!(y, None);
209 }
210
211 #[test]
212 fn test_saturating_convert_overflow() {
213 let x: f64 = 40000.0;
214 let y: i16 = x.saturating_convert();
215 assert_eq!(y, i16::MAX);
216 }
217
218 #[test]
219 fn test_saturating_convert_underflow() {
220 let x: f64 = -40000.0;
221 let y: i16 = x.saturating_convert();
222 assert_eq!(y, i16::MIN);
223 }
224
225 #[test]
226 fn test_wrapping_convert() {
227 let x: f64 = 42.0;
228 let y: i16 = x.wrapping_convert();
229 assert_eq!(y, 42i16);
230 }
231 }
232
233 mod i32 {
234 use crate::value::number::safe::convert::SafeConvert;
235
236 #[test]
237 fn test_checked_convert_happy() {
238 let x: f64 = 42.0;
239 let y: Option<i32> = x.checked_convert();
240 assert_eq!(y, Some(42i32));
241 }
242
243 #[test]
244 fn test_checked_convert_unhappy() {
245 let x: f64 = 3e38;
246 let y: Option<i32> = x.checked_convert();
247 assert_eq!(y, None);
248 }
249
250 #[test]
251 fn test_checked_convert_negative() {
252 let x: f64 = -42.0;
253 let y: Option<i32> = x.checked_convert();
254 assert_eq!(y, Some(-42i32));
255 }
256
257 #[test]
258 fn test_saturating_convert_overflow() {
259 let x: f64 = 3e38;
260 let y: i32 = x.saturating_convert();
261 assert_eq!(y, i32::MAX);
262 }
263
264 #[test]
265 fn test_saturating_convert_underflow() {
266 let x: f64 = -3e38;
267 let y: i32 = x.saturating_convert();
268 assert_eq!(y, i32::MIN);
269 }
270
271 #[test]
272 fn test_wrapping_convert() {
273 let x: f64 = 42.0;
274 let y: i32 = x.wrapping_convert();
275 assert_eq!(y, 42i32);
276 }
277 }
278
279 mod i64 {
280 use crate::value::number::safe::convert::SafeConvert;
281
282 #[test]
283 fn test_checked_convert_happy() {
284 let x: f64 = 42.0;
285 let y: Option<i64> = x.checked_convert();
286 assert_eq!(y, Some(42i64));
287 }
288
289 #[test]
290 fn test_checked_convert_unhappy() {
291 let x: f64 = 1e300;
292 let y: Option<i64> = x.checked_convert();
293 assert_eq!(y, None);
294 }
295
296 #[test]
297 fn test_checked_convert_negative() {
298 let x: f64 = -42.0;
299 let y: Option<i64> = x.checked_convert();
300 assert_eq!(y, Some(-42i64));
301 }
302
303 #[test]
304 fn test_saturating_convert_overflow() {
305 let x: f64 = 1e300;
306 let y: i64 = x.saturating_convert();
307 assert_eq!(y, i64::MAX);
308 }
309
310 #[test]
311 fn test_saturating_convert_underflow() {
312 let x: f64 = -1e300;
313 let y: i64 = x.saturating_convert();
314 assert_eq!(y, i64::MIN);
315 }
316
317 #[test]
318 fn test_wrapping_convert() {
319 let x: f64 = 42.0;
320 let y: i64 = x.wrapping_convert();
321 assert_eq!(y, 42i64);
322 }
323 }
324
325 mod i128 {
326 use crate::value::number::safe::convert::SafeConvert;
327
328 #[test]
329 fn test_checked_convert_happy() {
330 let x: f64 = 42.0;
331 let y: Option<i128> = x.checked_convert();
332 assert_eq!(y, Some(42i128));
333 }
334
335 #[test]
336 fn test_checked_convert_unhappy() {
337 let x: f64 = 1e300;
338 let y: Option<i128> = x.checked_convert();
339 assert_eq!(y, None);
340 }
341
342 #[test]
343 fn test_checked_convert_negative() {
344 let x: f64 = -42.0;
345 let y: Option<i128> = x.checked_convert();
346 assert_eq!(y, Some(-42i128));
347 }
348
349 #[test]
350 fn test_saturating_convert_overflow() {
351 let x: f64 = 1e300;
352 let y: i128 = x.saturating_convert();
353 assert_eq!(y, i128::MAX);
354 }
355
356 #[test]
357 fn test_saturating_convert_underflow() {
358 let x: f64 = -1e300;
359 let y: i128 = x.saturating_convert();
360 assert_eq!(y, i128::MIN);
361 }
362
363 #[test]
364 fn test_wrapping_convert() {
365 let x: f64 = 42.0;
366 let y: i128 = x.wrapping_convert();
367 assert_eq!(y, 42i128);
368 }
369 }
370
371 mod u8 {
372 use crate::value::number::safe::convert::SafeConvert;
373
374 #[test]
375 fn test_checked_convert_happy() {
376 let x: f64 = 42.0;
377 let y: Option<u8> = x.checked_convert();
378 assert_eq!(y, Some(42u8));
379 }
380
381 #[test]
382 fn test_checked_convert_unhappy() {
383 let x: f64 = 300.0;
384 let y: Option<u8> = x.checked_convert();
385 assert_eq!(y, None);
386 }
387
388 #[test]
389 fn test_checked_convert_negative() {
390 let x: f64 = -42.0;
391 let y: Option<u8> = x.checked_convert();
392 assert_eq!(y, None);
393 }
394
395 #[test]
396 fn test_checked_convert_nan() {
397 let x: f64 = f64::NAN;
398 let y: Option<u8> = x.checked_convert();
399 assert_eq!(y, None);
400 }
401
402 #[test]
403 fn test_checked_convert_infinity() {
404 let x: f64 = f64::INFINITY;
405 let y: Option<u8> = x.checked_convert();
406 assert_eq!(y, None);
407 }
408
409 #[test]
410 fn test_saturating_convert_overflow() {
411 let x: f64 = 300.0;
412 let y: u8 = x.saturating_convert();
413 assert_eq!(y, u8::MAX);
414 }
415
416 #[test]
417 fn test_saturating_convert_underflow() {
418 let x: f64 = -42.0;
419 let y: u8 = x.saturating_convert();
420 assert_eq!(y, 0);
421 }
422
423 #[test]
424 fn test_saturating_convert_nan() {
425 let x: f64 = f64::NAN;
426 let y: u8 = x.saturating_convert();
427 assert_eq!(y, 0);
428 }
429
430 #[test]
431 fn test_saturating_convert_infinity() {
432 let x: f64 = f64::INFINITY;
433 let y: u8 = x.saturating_convert();
434 assert_eq!(y, u8::MAX);
435 }
436
437 #[test]
438 fn test_wrapping_convert() {
439 let x: f64 = 42.0;
440 let y: u8 = x.wrapping_convert();
441 assert_eq!(y, 42u8);
442 }
443
444 #[test]
445 fn test_wrapping_convert_negative() {
446 let x: f64 = -42.0;
447 let y: u8 = x.wrapping_convert();
448 assert_eq!(y, 0);
449 }
450 }
451
452 mod u16 {
453 use crate::value::number::safe::convert::SafeConvert;
454
455 #[test]
456 fn test_checked_convert_happy() {
457 let x: f64 = 42.0;
458 let y: Option<u16> = x.checked_convert();
459 assert_eq!(y, Some(42u16));
460 }
461
462 #[test]
463 fn test_checked_convert_unhappy() {
464 let x: f64 = 70000.0;
465 let y: Option<u16> = x.checked_convert();
466 assert_eq!(y, None);
467 }
468
469 #[test]
470 fn test_checked_convert_negative() {
471 let x: f64 = -42.0;
472 let y: Option<u16> = x.checked_convert();
473 assert_eq!(y, None);
474 }
475
476 #[test]
477 fn test_saturating_convert_overflow() {
478 let x: f64 = 70000.0;
479 let y: u16 = x.saturating_convert();
480 assert_eq!(y, u16::MAX);
481 }
482
483 #[test]
484 fn test_saturating_convert_underflow() {
485 let x: f64 = -42.0;
486 let y: u16 = x.saturating_convert();
487 assert_eq!(y, 0);
488 }
489
490 #[test]
491 fn test_wrapping_convert() {
492 let x: f64 = 42.0;
493 let y: u16 = x.wrapping_convert();
494 assert_eq!(y, 42u16);
495 }
496 }
497
498 mod u32 {
499 use crate::value::number::safe::convert::SafeConvert;
500
501 #[test]
502 fn test_checked_convert_happy() {
503 let x: f64 = 42.0;
504 let y: Option<u32> = x.checked_convert();
505 assert_eq!(y, Some(42u32));
506 }
507
508 #[test]
509 fn test_checked_convert_unhappy() {
510 let x: f64 = 1e300;
511 let y: Option<u32> = x.checked_convert();
512 assert_eq!(y, None);
513 }
514
515 #[test]
516 fn test_checked_convert_negative() {
517 let x: f64 = -42.0;
518 let y: Option<u32> = x.checked_convert();
519 assert_eq!(y, None);
520 }
521
522 #[test]
523 fn test_saturating_convert_overflow() {
524 let x: f64 = 1e300;
525 let y: u32 = x.saturating_convert();
526 assert_eq!(y, u32::MAX);
527 }
528
529 #[test]
530 fn test_saturating_convert_underflow() {
531 let x: f64 = -42.0;
532 let y: u32 = x.saturating_convert();
533 assert_eq!(y, 0);
534 }
535
536 #[test]
537 fn test_wrapping_convert() {
538 let x: f64 = 42.0;
539 let y: u32 = x.wrapping_convert();
540 assert_eq!(y, 42u32);
541 }
542 }
543
544 mod u64 {
545 use crate::value::number::safe::convert::SafeConvert;
546
547 #[test]
548 fn test_checked_convert_happy() {
549 let x: f64 = 42.0;
550 let y: Option<u64> = x.checked_convert();
551 assert_eq!(y, Some(42u64));
552 }
553
554 #[test]
555 fn test_checked_convert_unhappy() {
556 let x: f64 = 1e300;
557 let y: Option<u64> = x.checked_convert();
558 assert_eq!(y, None);
559 }
560
561 #[test]
562 fn test_checked_convert_negative() {
563 let x: f64 = -42.0;
564 let y: Option<u64> = x.checked_convert();
565 assert_eq!(y, None);
566 }
567
568 #[test]
569 fn test_saturating_convert_overflow() {
570 let x: f64 = 1e300;
571 let y: u64 = x.saturating_convert();
572 assert_eq!(y, u64::MAX);
573 }
574
575 #[test]
576 fn test_saturating_convert_underflow() {
577 let x: f64 = -42.0;
578 let y: u64 = x.saturating_convert();
579 assert_eq!(y, 0);
580 }
581
582 #[test]
583 fn test_wrapping_convert() {
584 let x: f64 = 42.0;
585 let y: u64 = x.wrapping_convert();
586 assert_eq!(y, 42u64);
587 }
588 }
589
590 mod u128 {
591 use crate::value::number::safe::convert::SafeConvert;
592
593 #[test]
594 fn test_checked_convert_happy() {
595 let x: f64 = 42.0;
596 let y: Option<u128> = x.checked_convert();
597 assert_eq!(y, Some(42u128));
598 }
599
600 #[test]
601 fn test_checked_convert_unhappy() {
602 let x: f64 = 1e300;
603 let y: Option<u128> = x.checked_convert();
604 assert_eq!(y, None);
605 }
606
607 #[test]
608 fn test_checked_convert_negative() {
609 let x: f64 = -42.0;
610 let y: Option<u128> = x.checked_convert();
611 assert_eq!(y, None);
612 }
613
614 #[test]
615 fn test_saturating_convert_overflow() {
616 let x: f64 = 1e300;
617 let y: u128 = x.saturating_convert();
618 assert_eq!(y, u128::MAX);
619 }
620
621 #[test]
622 fn test_saturating_convert_underflow() {
623 let x: f64 = -42.0;
624 let y: u128 = x.saturating_convert();
625 assert_eq!(y, 0);
626 }
627
628 #[test]
629 fn test_wrapping_convert() {
630 let x: f64 = 42.0;
631 let y: u128 = x.wrapping_convert();
632 assert_eq!(y, 42u128);
633 }
634 }
635
636 mod decimal {
637 use std::f64::consts::PI;
638
639 use crate::value::{decimal::Decimal, number::safe::convert::SafeConvert};
640
641 #[test]
642 fn test_checked_convert() {
643 let x: f64 = 42.5;
644 let y: Option<Decimal> = x.checked_convert();
645 assert!(y.is_some());
646 let decimal = y.unwrap();
647 assert_eq!(decimal.to_string(), "42.5");
648 }
649
650 #[test]
651 fn test_checked_convert_high_precision() {
652 let x: f64 = 123.456789;
653 let y: Option<Decimal> = x.checked_convert();
654 assert!(y.is_some());
655 let decimal = y.unwrap();
656 assert!(decimal.to_string().starts_with("123.456789"));
659 }
660
661 #[test]
662 fn test_checked_convert_integer() {
663 let x: f64 = 1000.0;
664 let y: Option<Decimal> = x.checked_convert();
665 assert!(y.is_some());
666 let decimal = y.unwrap();
667 assert_eq!(decimal.to_string(), "1000");
668 }
669
670 #[test]
671 fn test_checked_convert_small_decimal() {
672 let x: f64 = 0.0000125;
673 let y: Option<Decimal> = x.checked_convert();
674 assert!(y.is_some());
675 let decimal = y.unwrap();
676 assert!(decimal.to_string().starts_with("0.0000125"));
677 }
678
679 #[test]
680 fn test_checked_convert_negative() {
681 let x: f64 = -9876.543210;
682 let y: Option<Decimal> = x.checked_convert();
683 assert!(y.is_some());
684 let decimal = y.unwrap();
685 assert!(decimal.to_string().starts_with("-9876.5432"));
686 }
687
688 #[test]
689 fn test_checked_convert_zero() {
690 let x: f64 = 0.0;
691 let y: Option<Decimal> = x.checked_convert();
692 assert!(y.is_some());
693 let decimal = y.unwrap();
694 assert_eq!(decimal.to_string(), "0");
695 }
696
697 #[test]
698 fn test_checked_convert_negative_zero() {
699 let x: f64 = -0.0;
700 let y: Option<Decimal> = x.checked_convert();
701 assert!(y.is_some());
702 let decimal = y.unwrap();
703 assert_eq!(decimal.to_string(), "0");
705 }
706
707 #[test]
708 fn test_checked_convert_nan() {
709 let x: f64 = f64::NAN;
710 let y: Option<Decimal> = x.checked_convert();
711 assert!(y.is_none());
712 }
713
714 #[test]
715 fn test_checked_convert_infinity() {
716 let x: f64 = f64::INFINITY;
717 let y: Option<Decimal> = x.checked_convert();
718 assert!(y.is_none());
719 }
720
721 #[test]
722 fn test_checked_convert_neg_infinity() {
723 let x: f64 = f64::NEG_INFINITY;
724 let y: Option<Decimal> = x.checked_convert();
725 assert!(y.is_none());
726 }
727
728 #[test]
729 fn test_saturating_convert() {
730 let x: f64 = 999999.999999;
731 let y: Decimal = x.saturating_convert();
732 let str_repr = y.to_string();
735 assert!(str_repr.starts_with("999999") || str_repr.starts_with("1000000"));
736 }
737
738 #[test]
739 fn test_saturating_convert_nan() {
740 let x: f64 = f64::NAN;
741 let y: Decimal = x.saturating_convert();
742 assert_eq!(y.to_string(), "0");
743 }
744
745 #[test]
746 fn test_saturating_convert_infinity() {
747 let x: f64 = f64::INFINITY;
748 let y: Decimal = x.saturating_convert();
749 assert_eq!(y.to_string(), "0");
750 }
751
752 #[test]
753 fn test_wrapping_convert() {
754 let x: f64 = 42.0;
755 let y: Decimal = x.wrapping_convert();
756 assert_eq!(y.to_string(), "42");
757 }
758
759 #[test]
760 fn test_wrapping_convert_with_decimal() {
761 let x: f64 = PI;
762 let y: Decimal = x.wrapping_convert();
763 let str_repr = y.to_string();
764 assert!(str_repr.starts_with("3.141"), "actual: {}", str_repr);
765 }
766
767 #[test]
768 fn checked_convert_refuses_floats_past_seventy_six_digits() {
769 let y: Option<Decimal> = 1e80f64.checked_convert();
772 assert_eq!(y, None);
773 let y: Decimal = 1e80f64.saturating_convert();
774 assert_eq!(y.to_string(), "9".repeat(76));
775 let y: Decimal = (-1e80f64).saturating_convert();
776 assert_eq!(y.to_string(), format!("-{}", "9".repeat(76)));
777 let y: Option<Decimal> = 1e-300f64.checked_convert();
778 assert_eq!(y, Some(Decimal::zero()));
779 }
780 }
781}