nanvm_lib/vm/bigint/
from.rs1use super::BigInt;
2use crate::{
3 common::default::default,
4 sign::Sign,
5 vm::{IVm, Number},
6};
7
8impl<A: IVm> From<u64> for BigInt<A> {
9 fn from(value: u64) -> Self {
10 if value == 0 {
11 return default();
12 }
13 Self::new_one(Sign::Positive, value)
14 }
15}
16
17fn neg(i: i64) -> u64 {
18 i.overflowing_neg().0 as u64
19}
20
21impl<A: IVm> From<i64> for BigInt<A> {
22 fn from(value: i64) -> Self {
23 if value >= 0 {
24 return (value as u64).into();
25 }
26 Self::new_one(Sign::Negative, neg(value))
27 }
28}
29
30impl<A: IVm> BigInt<A> {
31 pub(crate) fn from_integral(n: Number) -> Option<Self> {
38 if f64::from(n).fract() != 0.0 {
39 return None;
40 }
41 let (sign, significand, exponent) = n.decompose()?;
42 let magnitude = if exponent >= 0 {
43 (Self::from(significand) << Self::from(exponent as u64))
44 .expect("a binary64's exponent is far under BigInt's size limit")
45 } else {
46 Self::from(
49 significand
50 .checked_shr(exponent.unsigned_abs())
51 .unwrap_or(0),
52 )
53 };
54 Some(if sign == Sign::Negative {
55 -magnitude
56 } else {
57 magnitude
58 })
59 }
60
61 pub(crate) fn pow2(e: u32) -> Self {
64 (Self::from(1u64) << Self::from(u64::from(e)))
65 .expect("a binary64's exponent is far under BigInt's size limit")
66 }
67}
68
69#[cfg(test)]
70mod test {
71 use crate::{
72 naive::Naive,
73 sign::Sign,
74 vm::{BigInt, Number, bigint::from::neg},
75 };
76
77 fn integral(v: f64) -> BigInt<Naive> {
78 BigInt::from_integral(Number::from(v)).expect("an integral, finite Number")
79 }
80
81 #[test]
82 fn from_integral() {
83 assert_eq!(integral(0.0), BigInt::default());
84 assert_eq!(integral(-0.0), BigInt::default());
85 assert_eq!(integral(1.0), BigInt::from(1u64));
86 assert_eq!(integral(-3.0), BigInt::from(-3i64));
87 assert_eq!(integral(9_007_199_254_740_992.0), BigInt::from(1u64 << 53));
89 assert_eq!(
90 integral(9_007_199_254_740_994.0),
91 BigInt::from((1u64 << 53) + 2)
92 );
93 assert_eq!(
94 integral(-18_446_744_073_709_551_616.0),
95 BigInt::normalize_new(Sign::Negative, [0, 1])
96 );
97 assert_eq!(
99 integral(f64::MAX),
100 BigInt::from((1u64 << 53) - 1).mul_bounded(BigInt::pow2(971))
101 );
102 }
103
104 #[test]
105 fn from_integral_refuses() {
106 for v in [0.5, -1.5, f64::NAN, f64::INFINITY, f64::NEG_INFINITY] {
107 assert_eq!(BigInt::<Naive>::from_integral(Number::from(v)), None);
108 }
109 }
110
111 #[test]
112 fn pow2() {
113 assert_eq!(BigInt::<Naive>::pow2(0), BigInt::from(1u64));
114 assert_eq!(BigInt::<Naive>::pow2(63), BigInt::from(1u64 << 63));
115 assert_eq!(
116 BigInt::<Naive>::pow2(64),
117 BigInt::normalize_new(Sign::Positive, [0, 1])
118 );
119 }
120
121 #[test]
122 fn overflow_min1() {
123 let x = neg(i64::MIN + 1);
124 assert_eq!(x, (1 << 63) - 1);
125 }
126 #[test]
127 fn overflow_min() {
128 let x = neg(i64::MIN);
129 assert_eq!(x, 1 << 63);
130 }
131}