ethnum/int.rs
1//! Root module for 256-bit signed integer type.
2
3mod api;
4mod cmp;
5mod convert;
6mod fmt;
7mod iter;
8mod ops;
9mod parse;
10
11pub use self::convert::AsI256;
12use crate::uint::U256;
13use core::{mem::MaybeUninit, num::ParseIntError};
14
15/// A 256-bit signed integer type.
16#[derive(Clone, Copy, Default, Eq, Hash, PartialEq)]
17#[repr(transparent)]
18pub struct I256(pub [i128; 2]);
19
20impl I256 {
21 /// The additive identity for this integer type, i.e. `0`.
22 pub const ZERO: Self = I256([0; 2]);
23
24 /// The multiplicative identity for this integer type, i.e. `1`.
25 pub const ONE: Self = I256::new(1);
26
27 /// The multiplicative inverse for this integer type, i.e. `-1`.
28 pub const MINUS_ONE: Self = I256::new(-1);
29
30 /// Creates a new 256-bit integer value from a primitive `i128` integer.
31 #[inline]
32 pub const fn new(value: i128) -> Self {
33 I256::from_words(value >> 127, value)
34 }
35
36 /// Creates a new 256-bit integer value from high and low words.
37 #[inline]
38 pub const fn from_words(hi: i128, lo: i128) -> Self {
39 #[cfg(target_endian = "little")]
40 {
41 I256([lo, hi])
42 }
43 #[cfg(target_endian = "big")]
44 {
45 I256([hi, lo])
46 }
47 }
48
49 /// Splits a 256-bit integer into high and low words.
50 #[inline]
51 pub const fn into_words(self) -> (i128, i128) {
52 #[cfg(target_endian = "little")]
53 {
54 let I256([lo, hi]) = self;
55 (hi, lo)
56 }
57 #[cfg(target_endian = "big")]
58 {
59 let I256([hi, lo]) = self;
60 (hi, lo)
61 }
62 }
63
64 /// Get the low 128-bit word for this signed integer.
65 #[inline]
66 pub fn low(&self) -> &i128 {
67 #[cfg(target_endian = "little")]
68 {
69 &self.0[0]
70 }
71 #[cfg(target_endian = "big")]
72 {
73 &self.0[1]
74 }
75 }
76
77 /// Get the low 128-bit word for this signed integer as a mutable reference.
78 #[inline]
79 pub fn low_mut(&mut self) -> &mut i128 {
80 #[cfg(target_endian = "little")]
81 {
82 &mut self.0[0]
83 }
84 #[cfg(target_endian = "big")]
85 {
86 &mut self.0[1]
87 }
88 }
89
90 /// Get the high 128-bit word for this signed integer.
91 #[inline]
92 pub fn high(&self) -> &i128 {
93 #[cfg(target_endian = "little")]
94 {
95 &self.0[1]
96 }
97 #[cfg(target_endian = "big")]
98 {
99 &self.0[0]
100 }
101 }
102
103 /// Get the high 128-bit word for this signed integer as a mutable
104 /// reference.
105 #[inline]
106 pub fn high_mut(&mut self) -> &mut i128 {
107 #[cfg(target_endian = "little")]
108 {
109 &mut self.0[1]
110 }
111 #[cfg(target_endian = "big")]
112 {
113 &mut self.0[0]
114 }
115 }
116
117 /// Converts a prefixed string slice in base 16 to an integer.
118 ///
119 /// The string is expected to be an optional `+` or `-` sign followed by
120 /// the `0x` prefix and finally the digits. Leading and trailing whitespace
121 /// represent an error.
122 ///
123 /// # Examples
124 ///
125 /// Basic usage:
126 ///
127 /// ```
128 /// # use ethnum::I256;
129 /// assert_eq!(I256::from_str_hex("0x2A"), Ok(I256::new(42)));
130 /// assert_eq!(I256::from_str_hex("-0xa"), Ok(I256::new(-10)));
131 /// ```
132 pub fn from_str_hex(src: &str) -> Result<Self, ParseIntError> {
133 crate::parse::from_str_radix(src, 16, Some("0x"))
134 }
135
136 /// Converts a prefixed string slice in a base determined by the prefix to
137 /// an integer.
138 ///
139 /// The string is expected to be an optional `+` or `-` sign followed by
140 /// the one of the supported prefixes and finally the digits. Leading and
141 /// trailing whitespace represent an error. The base is determined based
142 /// on the prefix:
143 ///
144 /// * `0b`: base `2`
145 /// * `0o`: base `8`
146 /// * `0x`: base `16`
147 /// * no prefix: base `10`
148 ///
149 /// # Examples
150 ///
151 /// Basic usage:
152 ///
153 /// ```
154 /// # use ethnum::I256;
155 /// assert_eq!(I256::from_str_prefixed("-0b101"), Ok(I256::new(-0b101)));
156 /// assert_eq!(I256::from_str_prefixed("0o17"), Ok(I256::new(0o17)));
157 /// assert_eq!(I256::from_str_prefixed("-0xa"), Ok(I256::new(-0xa)));
158 /// assert_eq!(I256::from_str_prefixed("42"), Ok(I256::new(42)));
159 /// ```
160 pub fn from_str_prefixed(src: &str) -> Result<Self, ParseIntError> {
161 crate::parse::from_str_prefixed(src)
162 }
163
164 /// Same as [`I256::from_str_prefixed`] but as a `const fn`. This method is
165 /// not intended to be used directly but rather through the [`crate::int`]
166 /// macro.
167 #[doc(hidden)]
168 pub const fn const_from_str_prefixed(src: &str) -> Self {
169 parse::const_from_str_prefixed(src)
170 }
171
172 /// Cast to a primitive `i8`.
173 #[inline]
174 pub const fn as_i8(self) -> i8 {
175 let (_, lo) = self.into_words();
176 lo as _
177 }
178
179 /// Cast to a primitive `i16`.
180 #[inline]
181 pub const fn as_i16(self) -> i16 {
182 let (_, lo) = self.into_words();
183 lo as _
184 }
185
186 /// Cast to a primitive `i32`.
187 #[inline]
188 pub const fn as_i32(self) -> i32 {
189 let (_, lo) = self.into_words();
190 lo as _
191 }
192
193 /// Cast to a primitive `i64`.
194 #[inline]
195 pub const fn as_i64(self) -> i64 {
196 let (_, lo) = self.into_words();
197 lo as _
198 }
199
200 /// Cast to a primitive `i128`.
201 #[inline]
202 pub const fn as_i128(self) -> i128 {
203 let (_, lo) = self.into_words();
204 lo as _
205 }
206
207 /// Cast to a primitive `u8`.
208 #[inline]
209 pub const fn as_u8(self) -> u8 {
210 let (_, lo) = self.into_words();
211 lo as _
212 }
213
214 /// Cast to a primitive `u16`.
215 #[inline]
216 pub const fn as_u16(self) -> u16 {
217 let (_, lo) = self.into_words();
218 lo as _
219 }
220
221 /// Cast to a primitive `u32`.
222 #[inline]
223 pub const fn as_u32(self) -> u32 {
224 let (_, lo) = self.into_words();
225 lo as _
226 }
227
228 /// Cast to a primitive `u64`.
229 #[inline]
230 pub const fn as_u64(self) -> u64 {
231 let (_, lo) = self.into_words();
232 lo as _
233 }
234
235 /// Cast to a primitive `u128`.
236 #[inline]
237 pub const fn as_u128(self) -> u128 {
238 let (_, lo) = self.into_words();
239 lo as _
240 }
241
242 /// Cast to a `U256`.
243 #[inline]
244 pub const fn as_u256(self) -> U256 {
245 let Self([a, b]) = self;
246 U256([a as _, b as _])
247 }
248
249 /// Cast to a primitive `isize`.
250 #[inline]
251 pub const fn as_isize(self) -> isize {
252 let (_, lo) = self.into_words();
253 lo as _
254 }
255
256 /// Cast to a primitive `usize`.
257 #[inline]
258 pub const fn as_usize(self) -> usize {
259 let (_, lo) = self.into_words();
260 lo as _
261 }
262
263 /// Cast to a primitive `f32`.
264 #[inline]
265 pub fn as_f32(self) -> f32 {
266 self.as_f64() as _
267 }
268
269 /// Cast to a primitive `f64`.
270 #[inline]
271 pub fn as_f64(self) -> f64 {
272 let sign = self.signum128() as f64;
273 self.unsigned_abs().as_f64() * sign
274 }
275
276 /// Performs integer and division and returns the quotient and the remainder as a tuple. This is equivelent to `(self / rhs, self % rhs)`, but more effecient.
277 ///
278 /// # Panics
279 ///
280 /// This function will panic if `rhs` is 0, and will panic on overflow iff debug assertions are enabled.
281 ///
282 /// # Examples
283 ///
284 /// Basic usage:
285 ///
286 /// ```
287 /// # use ethnum::I256;
288 /// assert_eq!(I256::new(22).div_rem(I256::new(5)), (I256::new(4), I256::new(2)));
289 /// assert_eq!(I256::new(-22).div_rem(I256::new(5)), (I256::new(-4), I256::new(-2)));
290 /// assert_eq!(I256::new(22).div_rem(I256::new(-5)), (I256::new(-4), I256::new(2)));
291 /// assert_eq!(I256::new(-22).div_rem(I256::new(-5)), (I256::new(4), I256::new(-2)));
292 /// ```
293 #[inline]
294 #[must_use = "this returns the result of the operation, \
295 without modifying the original"]
296 #[track_caller]
297 pub fn div_rem(self, rhs: Self) -> (Self, Self) {
298 if self == Self::MIN && rhs == -1 {
299 panic!("attempt to divide with overflow")
300 }
301 self.wrapping_div_rem(rhs)
302 }
303
304 /// Performs euclidean division and returns the quotient and the remainder as a tuple.
305 ///
306 /// This computes the integers `q` and `r` such that self = q * rhs + r, with `q = self.div_euclid` and `r = self.rem_euclid(rhs)`.
307 ///
308 /// # Panics
309 ///
310 /// This function will panic if `rhs` is 0, and will panic on overflow iff debug assertions are enabled.
311 ///
312 /// # Examples
313 ///
314 /// Basic usage:
315 ///
316 /// ```
317 /// # use ethnum::I256;
318 /// assert_eq!(I256::new(22).div_rem_euclid(I256::new(5)), (I256::new(4), I256::new(2)));
319 /// assert_eq!(I256::new(-22).div_rem_euclid(I256::new(5)), (I256::new(-5), I256::new(3)));
320 /// assert_eq!(I256::new(22).div_rem_euclid(I256::new(-5)), (I256::new(-4), I256::new(2)));
321 /// assert_eq!(I256::new(-22).div_rem_euclid(I256::new(-5)), (I256::new(5), I256::new(3)));
322 ///
323 /// # assert_eq!(I256::new(20).div_rem_euclid(I256::new(5)), (I256::new(4), I256::new(0)));
324 /// # assert_eq!(I256::new(-20).div_rem_euclid(I256::new(5)), (I256::new(-4), I256::new(0)));
325 /// # assert_eq!(I256::new(20).div_rem_euclid(I256::new(-5)), (I256::new(-4), I256::new(0)));
326 /// # assert_eq!(I256::new(-20).div_rem_euclid(I256::new(-5)), (I256::new(4), I256::new(0)));
327 /// ```
328 #[inline]
329 #[must_use = "this returns the result of the operation, \
330 without modifying the original"]
331 #[track_caller]
332 pub fn div_rem_euclid(self, rhs: Self) -> (Self, Self) {
333 if self == Self::MIN && rhs == -1 {
334 panic!("attempt to divide with overflow")
335 }
336 self.wrapping_div_rem_euclid(rhs)
337 }
338
339 /// Checked division. Computes `self.div_rem(rhs)`,
340 /// returning `None` if `rhs == 0` or the division results in overflow.
341 ///
342 /// # Examples
343 ///
344 /// Basic usage:
345 ///
346 /// ```
347 /// # use ethnum::I256;
348 /// assert_eq!((I256::MIN + 1).checked_div_rem(I256::new(-1)), Some((I256::MAX, I256::new(0))));
349 /// assert_eq!(I256::MIN.checked_div_rem(I256::new(-1)), None);
350 /// assert_eq!(I256::new(1).checked_div_rem(I256::new(0)), None);
351 /// ```
352 #[inline]
353 #[must_use = "this returns the result of the operation, \
354 without modifying the original"]
355 #[track_caller]
356 pub fn checked_div_rem(self, rhs: Self) -> Option<(Self, Self)> {
357 if rhs == 0 || (self == Self::MIN && rhs == -1) {
358 None
359 } else {
360 if rhs.cmp(&I256::ZERO) == core::cmp::Ordering::Equal {
361 // The optimizer understands inequalities better
362 unsafe { core::hint::unreachable_unchecked() }
363 }
364
365 let mut res: MaybeUninit<Self> = MaybeUninit::uninit();
366 let mut rem: MaybeUninit<Self> = MaybeUninit::uninit();
367 crate::intrinsics::idivmod4(&mut res, &self, &rhs, Some(&mut rem));
368 unsafe { Some(((res.assume_init()), (rem.assume_init()))) }
369 }
370 }
371
372 /// Checked Euclidean division. Computes `self.div_rem_euclid(rhs)`,
373 /// returning `None` if `rhs == 0` or the division results in overflow.
374 ///
375 /// # Examples
376 ///
377 /// Basic usage:
378 ///
379 /// ```
380 /// # use ethnum::I256;
381 /// assert_eq!((I256::MIN + 1).checked_div_rem_euclid(I256::new(-1)), Some((I256::MAX, I256::new(0))));
382 /// assert_eq!(I256::MIN.checked_div_rem_euclid(I256::new(-1)), None);
383 /// assert_eq!(I256::new(1).checked_div_rem_euclid(I256::new(0)), None);
384 /// ```
385 #[inline]
386 #[must_use = "this returns the result of the operation, \
387 without modifying the original"]
388 #[track_caller]
389 pub fn checked_div_rem_euclid(self, rhs: Self) -> Option<(Self, Self)> {
390 if rhs == 0 || (self == Self::MIN && rhs == -1) {
391 None
392 } else {
393 if rhs.cmp(&I256::ZERO) == core::cmp::Ordering::Equal {
394 // The optimizer understands inequalities better
395 unsafe { core::hint::unreachable_unchecked() }
396 }
397
398 Some(self.wrapping_div_rem_euclid(rhs))
399 }
400 }
401
402 /// Saturating integer division. Computes `self.div_rem(rhs)`, saturating at the
403 /// numeric bounds instead of overflowing.
404 ///
405 /// # Examples
406 ///
407 /// Basic usage:
408 ///
409 /// ```
410 /// # use ethnum::I256;
411 /// assert_eq!(I256::new(5).saturating_div_rem(I256::new(2)), (I256::new(2), I256::new(1)));
412 /// assert_eq!(I256::MAX.saturating_div_rem(I256::new(-1)), (I256::MIN + 1, I256::new(0)));
413 /// assert_eq!(I256::MIN.saturating_div_rem(I256::new(-1)), (I256::MAX, I256::new(0)));
414 /// ```
415 /// ```should_panic (expected = "attempt to divide by zero")
416 /// # use ethnum::I256;
417 /// let _ = I256::new(1).saturating_div_rem(I256::ZERO);
418 /// ```
419 #[inline]
420 #[must_use = "this returns the result of the operation, \
421 without modifying the original"]
422 #[track_caller]
423 pub fn saturating_div_rem(self, rhs: Self) -> (Self, Self) {
424 match self.overflowing_div_rem(rhs) {
425 (q, r, false) => (q, r),
426 (_q, r, true) => (Self::MAX, r), // MIN / -1 is the only possible saturating overflow
427 }
428 }
429
430 /// Saturating integer division. Computes `self.div_rem_euclid(rhs)`, saturating at the
431 /// numeric bounds instead of overflowing.
432 ///
433 /// # Examples
434 ///
435 /// Basic usage:
436 ///
437 /// ```
438 /// # use ethnum::I256;
439 /// assert_eq!(I256::new(5).saturating_div_rem_euclid(I256::new(2)), (I256::new(2), I256::new(1)));
440 /// assert_eq!(I256::MAX.saturating_div_rem_euclid(I256::new(-1)), (I256::MIN + 1, I256::new(0)));
441 /// assert_eq!(I256::MIN.saturating_div_rem_euclid(I256::new(-1)), (I256::MAX, I256::new(0)));
442 /// ```
443 /// ```should_panic (expected = "attempt to divide by zero")
444 /// # use ethnum::I256;
445 /// let _ = I256::new(1).saturating_div_rem_euclid(I256::ZERO);
446 /// ```
447 #[inline]
448 #[must_use = "this returns the result of the operation, \
449 without modifying the original"]
450 #[track_caller]
451 pub fn saturating_div_rem_euclid(self, rhs: Self) -> (Self, Self) {
452 match self.overflowing_div_rem_euclid(rhs) {
453 (q, r, false) => (q, r),
454 (_q, r, true) => (Self::MAX, r),
455 }
456 }
457
458 /// Performs integer and division and returns the quotient and the remainder as a tuple. This is equivelent to `(self.wrapping_div(rhs), self.wrapping_rem(rhs))`, but more effecient.
459 ///
460 /// # Panics
461 ///
462 /// This function will panic if `rhs` is 0.
463 ///
464 /// # Examples
465 ///
466 /// Basic usage:
467 ///
468 /// ```
469 /// # use ethnum::I256;
470 /// assert_eq!(I256::new(22).wrapping_div_rem(I256::new(5)), (I256::new(4), I256::new(2)));
471 /// assert_eq!(I256::new(-22).wrapping_div_rem(I256::new(5)), (I256::new(-4), I256::new(-2)));
472 /// assert_eq!(I256::new(22).wrapping_div_rem(I256::new(-5)), (I256::new(-4), I256::new(2)));
473 /// assert_eq!(I256::new(-22).wrapping_div_rem(I256::new(-5)), (I256::new(4), I256::new(-2)));
474 ///
475 /// assert_eq!(I256::MIN.wrapping_div_rem(I256::MINUS_ONE), (I256::MIN, I256::ZERO));
476 /// ```
477 #[inline]
478 #[must_use = "this returns the result of the operation, \
479 without modifying the original"]
480 #[track_caller]
481 pub fn wrapping_div_rem(self, rhs: Self) -> (Self, Self) {
482 if rhs == 0 {
483 if rhs.cmp(&I256::ZERO) != core::cmp::Ordering::Equal {
484 // The optimizer understands inequalities better
485 unsafe { core::hint::unreachable_unchecked() }
486 }
487 panic!("attempt to divide by zero");
488 }
489 if rhs.cmp(&I256::ZERO) == core::cmp::Ordering::Equal {
490 // The optimizer understands inequalities better
491 unsafe { core::hint::unreachable_unchecked() }
492 }
493
494 let mut res: MaybeUninit<Self> = MaybeUninit::uninit();
495 let mut rem: MaybeUninit<Self> = MaybeUninit::uninit();
496 crate::intrinsics::idivmod4(&mut res, &self, &rhs, Some(&mut rem));
497 unsafe { ((res.assume_init()), (rem.assume_init())) }
498 }
499
500 /// Performs euclidean division and returns the quotient and the remainder as a tuple.
501 ///
502 /// This computes the integers `q` and `r` such that self = q * rhs + r, with `q = self.wrapping_div_euclid` and `r = self.wrapping_rem_euclid(rhs)`.
503 ///
504 /// # Panics
505 ///
506 /// This function will panic if `rhs` is 0.
507 ///
508 /// # Examples
509 ///
510 /// Basic usage:
511 ///
512 /// ```
513 /// # use ethnum::I256;
514 /// assert_eq!(I256::new(22).wrapping_div_rem_euclid(I256::new(5)), (I256::new(4), I256::new(2)));
515 /// assert_eq!(I256::new(-22).wrapping_div_rem_euclid(I256::new(5)), (I256::new(-5), I256::new(3)));
516 /// assert_eq!(I256::new(22).wrapping_div_rem_euclid(I256::new(-5)), (I256::new(-4), I256::new(2)));
517 /// assert_eq!(I256::new(-22).wrapping_div_rem_euclid(I256::new(-5)), (I256::new(5), I256::new(3)));
518 ///
519 /// assert_eq!(I256::MIN.wrapping_div_rem(I256::MINUS_ONE), (I256::MIN, I256::ZERO));
520 /// # assert_eq!(I256::new(20).wrapping_div_rem_euclid(I256::new(5)), (I256::new(4), I256::new(0)));
521 /// # assert_eq!(I256::new(-20).wrapping_div_rem_euclid(I256::new(5)), (I256::new(-4), I256::new(0)));
522 /// # assert_eq!(I256::new(20).wrapping_div_rem_euclid(I256::new(-5)), (I256::new(-4), I256::new(0)));
523 /// # assert_eq!(I256::new(-20).wrapping_div_rem_euclid(I256::new(-5)), (I256::new(4), I256::new(0)));
524 /// ```
525 #[inline]
526 #[must_use = "this returns the result of the operation, \
527 without modifying the original"]
528 #[track_caller]
529 pub fn wrapping_div_rem_euclid(self, rhs: Self) -> (Self, Self) {
530 let dividend_sign = self.is_negative();
531 let quotient_sign = dividend_sign ^ rhs.is_negative();
532 let abs_dividend = self.unsigned_abs();
533 let abs_divisor = rhs.unsigned_abs();
534
535 let (q, r) = abs_dividend.div_rem(abs_divisor);
536 let mut quotient = q.as_i256();
537 let mut remainder = r.as_i256();
538
539 let adjust_remainder = dividend_sign && remainder != 0;
540 if adjust_remainder {
541 remainder = abs_divisor.as_i256() - remainder;
542 // cannot overflow
543 }
544 if remainder.is_negative() || remainder.as_u256() >= abs_divisor {
545 debug_assert!(false);
546 unsafe { core::hint::unreachable_unchecked() }
547 }
548
549 if adjust_remainder {
550 if quotient_sign {
551 quotient = !quotient;
552 // quotient = -quotient - 1
553 } else {
554 quotient += 1;
555 // cannot overflow
556 }
557 } else if quotient_sign {
558 quotient = quotient.wrapping_neg();
559 }
560
561 (quotient, remainder)
562 }
563
564 /// Calculates the quotient and the remainder when `self` is divided by `rhs`.
565 ///
566 /// Returns a tuple of the quotient and the remainder along with a boolean indicating whether
567 /// an arithmetic overflow would occur. If an overflow would occur then
568 /// `self` is returned.
569 ///
570 /// # Panics
571 ///
572 /// This function will panic if `rhs` is 0.
573 ///
574 /// # Examples
575 ///
576 /// Basic usage:
577 ///
578 /// ```
579 /// # use ethnum::I256;
580 /// assert_eq!(I256::new(5).overflowing_div_rem(I256::new(2)), (I256::new(2), I256::new(1), false));
581 /// assert_eq!(I256::MIN.overflowing_div_rem(I256::new(-1)), (I256::MIN, I256::new(0), true));
582 /// ```
583 #[inline]
584 #[must_use = "this returns the result of the operation, \
585 without modifying the original"]
586 #[track_caller]
587 pub fn overflowing_div_rem(self, rhs: Self) -> (Self, Self, bool) {
588 if self == Self::MIN && rhs == -1 {
589 (self, Self::ZERO, true)
590 } else {
591 let (q, r) = self.wrapping_div_rem(rhs);
592 (q, r, false)
593 }
594 }
595
596 /// Calculates the quotient and remainder of Euclidean division `self.div_rem_euclid(rhs)`.
597 ///
598 /// Returns a tuple of the quotient and the remainder along with a boolean indicating whether
599 /// an arithmetic overflow would occur. If an overflow would occur then
600 /// `self` is returned.
601 ///
602 /// # Panics
603 ///
604 /// This function will panic if `rhs` is 0.
605 ///
606 /// # Examples
607 ///
608 /// Basic usage:
609 ///
610 /// ```
611 /// # use ethnum::I256;
612 /// assert_eq!(I256::new(5).overflowing_div_rem_euclid(I256::new(2)), (I256::new(2), I256::new(1), false));
613 /// assert_eq!(I256::MIN.overflowing_div_rem_euclid(I256::new(-1)), (I256::MIN, I256::new(0), true));
614 /// ```
615 #[inline]
616 #[must_use = "this returns the result of the operation, \
617 without modifying the original"]
618 #[track_caller]
619 pub fn overflowing_div_rem_euclid(self, rhs: Self) -> (Self, Self, bool) {
620 if self == Self::MIN && rhs == -1 {
621 (self, Self::ZERO, true)
622 } else {
623 let (q, r) = self.wrapping_div_rem_euclid(rhs);
624 (q, r, false)
625 }
626 }
627}
628
629#[cfg(test)]
630mod tests {
631 use crate::I256;
632
633 #[test]
634 #[allow(clippy::float_cmp)]
635 fn converts_to_f64() {
636 assert_eq!((-I256::from_words(1, 0)).as_f64(), -(2.0f64.powi(128)))
637 }
638}