1use crate::{
11 f256, BigUInt, EXP_BIAS, EXP_BITS, FRACTION_BITS, HI_FRACTION_BITS,
12 SIGNIFICAND_BITS, U256,
13};
14
15impl f256 {
16 #[must_use]
18 #[inline]
19 #[allow(clippy::cast_possible_wrap)]
20 pub(crate) const fn from_i64(i: i64) -> Self {
21 if i == 0 {
22 return Self::ZERO;
23 }
24 let j = (i as i128).unsigned_abs();
26 let msb = 127 - j.leading_zeros();
27 Self::new(
28 i.is_negative() as u32,
29 msb as i32,
30 U256::new(j << (HI_FRACTION_BITS - msb), 0),
31 )
32 }
33
34 #[allow(clippy::cast_sign_loss)]
36 #[must_use]
37 #[inline]
38 #[allow(clippy::cast_possible_wrap)]
39 pub(crate) const fn from_i128(i: i128) -> Self {
40 if i == 0 {
41 return Self::ZERO;
42 }
43 let j = match i.checked_abs() {
44 Some(k) => k as u128,
45 None => i as u128,
46 };
47 let msb = 127 - j.leading_zeros();
48 Self::new(
49 i.is_negative() as u32,
50 msb as i32,
51 U256::new(0, j).shift_left(FRACTION_BITS - msb),
52 )
53 }
54
55 #[must_use]
57 #[inline]
58 #[allow(clippy::cast_possible_wrap)]
59 pub(crate) const fn from_u64(i: u64) -> Self {
60 if i == 0 {
61 return Self::ZERO;
62 }
63 let msb = 127 - (i as u128).leading_zeros();
64 Self::new(
65 0_u32,
66 msb as i32,
67 U256::new((i as u128) << (HI_FRACTION_BITS - msb), 0),
68 )
69 }
70
71 #[must_use]
73 #[inline]
74 #[allow(clippy::cast_possible_wrap)]
75 pub(crate) const fn from_u128(i: u128) -> Self {
76 if i == 0 {
77 return Self::ZERO;
78 }
79 let msb = 127 - i.leading_zeros();
80 Self::new(
81 0_u32,
82 msb as i32,
83 U256::new(0, i).shift_left(FRACTION_BITS - msb),
84 )
85 }
86
87 #[must_use]
89 #[inline]
90 #[allow(clippy::cast_possible_wrap)]
91 pub(crate) fn from_u256(i: &U256) -> Self {
92 debug_assert!(i.hi.0.leading_zeros() >= EXP_BITS);
93 if i.is_zero() {
94 return Self::ZERO;
95 }
96 let msb = i.msb();
97 Self::new(0_u32, msb as i32, i.shift_left(FRACTION_BITS - msb))
98 }
99}
100
101macro_rules! impl_from_signed_int {
102 () => {
103 impl_from_signed_int!(i8, i16, i32, i64);
104 };
105 ($($t:ty),*) => {
106 $(
107 impl From<$t> for f256 {
108 #[allow(trivial_numeric_casts)]
109 fn from(i: $t) -> Self {
110 Self::from_i64(i as i64)
111 }
112 }
113 )*
114 }
115}
116
117impl_from_signed_int!();
118
119impl From<i128> for f256 {
120 fn from(i: i128) -> Self {
121 Self::from_i128(i)
122 }
123}
124
125#[cfg(test)]
126mod from_signed_int_tests {
127 use super::*;
128
129 #[allow(clippy::cast_sign_loss)]
130 fn check_from_signed_int<T>(numbers: &[T])
131 where
132 T: Into<i128> + Copy,
133 f256: From<T>,
134 {
135 for n in numbers {
136 let f = f256::from(*n);
137 let i = (*n).into();
138 let j = match i.checked_abs() {
139 Some(k) => k as u128,
140 None => i as u128,
141 };
142 assert_eq!(f.is_sign_negative(), i.is_negative());
143 let (s, t, c) = f.decode();
144 assert_eq!(c.hi.0, 0);
145 assert_eq!(c.lo.0, j >> t as usize);
146 }
147 }
148
149 #[test]
150 fn test_from_i8() {
151 let numbers: [i8; 7] = [-128, -38, -1, 0, 1, 28, 127];
152 check_from_signed_int::<i8>(&numbers);
153 }
154
155 #[test]
156 fn test_from_i16() {
157 let numbers: [i16; 5] = [i16::MIN, -1, 0, 28200, i16::MAX];
158 check_from_signed_int::<i16>(&numbers);
159 }
160
161 #[test]
162 fn test_from_i32() {
163 let numbers: [i32; 5] = [i32::MIN, -1, 0, 2000000, i32::MAX];
164 check_from_signed_int::<i32>(&numbers);
165 }
166
167 #[test]
168 fn test_from_i64() {
169 let numbers: [i64; 5] = [i64::MIN, -1, 0, 2128255, i64::MAX];
170 check_from_signed_int::<i64>(&numbers);
171 }
172
173 #[test]
174 fn test_from_i128() {
175 let numbers: [i128; 5] =
176 [i128::MIN, -1, 0, 5_i128.pow(28), i128::MAX];
177 check_from_signed_int::<i128>(&numbers);
178 }
179}
180
181macro_rules! impl_from_unsigned_int {
182 () => {
183 impl_from_unsigned_int!(u8, u16, u32, u64);
184 };
185 ($($t:ty),*) => {
186 $(
187 impl From<$t> for f256 {
188 #[allow(trivial_numeric_casts)]
189 fn from(i: $t) -> Self {
190 Self::from_u64(i as u64)
191 }
192 }
193 )*
194 }
195}
196
197impl_from_unsigned_int!();
198
199impl From<u128> for f256 {
200 fn from(i: u128) -> Self {
201 Self::from_u128(i)
202 }
203}
204
205#[cfg(test)]
206mod from_unsigned_int_tests {
207 use super::*;
208
209 #[allow(clippy::cast_sign_loss)]
210 fn check_from_unsigned_int<T>(numbers: &[T])
211 where
212 T: Into<u128> + Copy,
213 f256: From<T>,
214 {
215 for n in numbers {
216 let f = f256::from(*n);
217 let i = (*n).into();
218 assert!(f.is_sign_positive());
219 let (s, t, c) = f.decode();
220 assert_eq!(c.hi.0, 0);
221 assert_eq!(c.lo.0, i >> t as usize);
222 }
223 }
224
225 #[test]
226 fn test_from_u8() {
227 let numbers: [u8; 4] = [0, 1, 98, u8::MAX];
228 check_from_unsigned_int::<u8>(&numbers);
229 }
230
231 #[test]
232 fn test_from_u16() {
233 let numbers: [u16; 3] = [0, 28200, u16::MAX];
234 check_from_unsigned_int::<u16>(&numbers);
235 }
236
237 #[test]
238 fn test_from_u32() {
239 let numbers: [u32; 3] = [0, 2000000, u32::MAX];
240 check_from_unsigned_int::<u32>(&numbers);
241 }
242
243 #[test]
244 fn test_from_u64() {
245 let numbers: [u64; 3] = [0, 2128255, u64::MAX];
246 check_from_unsigned_int::<u64>(&numbers);
247 }
248
249 #[test]
250 fn test_from_u128() {
251 let numbers: [u128; 3] = [0, 7_u128.pow(27), u128::MAX];
252 check_from_unsigned_int::<u128>(&numbers);
253 }
254}