1use alloc::string::{String, ToString};
2use core::fmt;
3use core::ops::{
4 Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Not, Rem, RemAssign, Shl, ShlAssign, Shr,
5 ShrAssign, Sub, SubAssign,
6};
7use core::str::FromStr;
8
9use crate::errors::{DivideByZeroError, DivisionError, OverflowError, OverflowOperation, StdError};
10use crate::forward_ref::{forward_ref_binop, forward_ref_op_assign};
11use crate::{
12 Int128, Int256, Int64, Uint128, Uint256, Uint512, Uint64, __internal::forward_ref_partial_eq,
13};
14
15use bnum::types::{I512, U512};
18
19use super::conversion::{grow_be_int, primitive_to_wrapped_int, try_from_uint_to_int};
20use super::impl_int_serde;
21use super::num_consts::NumConsts;
22
23#[derive(Copy, Clone, Default, Debug, PartialEq, Eq, PartialOrd, Ord, schemars::JsonSchema)]
48pub struct Int512(#[schemars(with = "String")] pub(crate) I512);
49
50impl_int_serde!(Int512);
51forward_ref_partial_eq!(Int512, Int512);
52
53impl Int512 {
54 pub const MAX: Int512 = Int512(I512::MAX);
55 pub const MIN: Int512 = Int512(I512::MIN);
56
57 #[inline]
60 pub const fn new(value: [u8; 64]) -> Self {
61 Self::from_be_bytes(value)
62 }
63
64 #[inline]
66 pub const fn zero() -> Self {
67 Int512(I512::ZERO)
68 }
69
70 #[inline]
72 pub const fn one() -> Self {
73 Self(I512::ONE)
74 }
75
76 #[must_use]
77 pub const fn from_be_bytes(data: [u8; 64]) -> Self {
78 let words: [u64; 8] = [
79 u64::from_le_bytes([
80 data[63], data[62], data[61], data[60], data[59], data[58], data[57], data[56],
81 ]),
82 u64::from_le_bytes([
83 data[55], data[54], data[53], data[52], data[51], data[50], data[49], data[48],
84 ]),
85 u64::from_le_bytes([
86 data[47], data[46], data[45], data[44], data[43], data[42], data[41], data[40],
87 ]),
88 u64::from_le_bytes([
89 data[39], data[38], data[37], data[36], data[35], data[34], data[33], data[32],
90 ]),
91 u64::from_le_bytes([
92 data[31], data[30], data[29], data[28], data[27], data[26], data[25], data[24],
93 ]),
94 u64::from_le_bytes([
95 data[23], data[22], data[21], data[20], data[19], data[18], data[17], data[16],
96 ]),
97 u64::from_le_bytes([
98 data[15], data[14], data[13], data[12], data[11], data[10], data[9], data[8],
99 ]),
100 u64::from_le_bytes([
101 data[7], data[6], data[5], data[4], data[3], data[2], data[1], data[0],
102 ]),
103 ];
104 Self(I512::from_bits(U512::from_digits(words)))
105 }
106
107 #[must_use]
108 pub const fn from_le_bytes(data: [u8; 64]) -> Self {
109 let words: [u64; 8] = [
110 u64::from_le_bytes([
111 data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7],
112 ]),
113 u64::from_le_bytes([
114 data[8], data[9], data[10], data[11], data[12], data[13], data[14], data[15],
115 ]),
116 u64::from_le_bytes([
117 data[16], data[17], data[18], data[19], data[20], data[21], data[22], data[23],
118 ]),
119 u64::from_le_bytes([
120 data[24], data[25], data[26], data[27], data[28], data[29], data[30], data[31],
121 ]),
122 u64::from_le_bytes([
123 data[32], data[33], data[34], data[35], data[36], data[37], data[38], data[39],
124 ]),
125 u64::from_le_bytes([
126 data[40], data[41], data[42], data[43], data[44], data[45], data[46], data[47],
127 ]),
128 u64::from_le_bytes([
129 data[48], data[49], data[50], data[51], data[52], data[53], data[54], data[55],
130 ]),
131 u64::from_le_bytes([
132 data[56], data[57], data[58], data[59], data[60], data[61], data[62], data[63],
133 ]),
134 ];
135 Self(I512::from_bits(U512::from_digits(words)))
136 }
137
138 #[must_use = "this returns the result of the operation, without modifying the original"]
140 pub const fn to_be_bytes(self) -> [u8; 64] {
141 let bits = self.0.to_bits();
142 let words = bits.digits();
143 let words = [
144 words[7].to_be_bytes(),
145 words[6].to_be_bytes(),
146 words[5].to_be_bytes(),
147 words[4].to_be_bytes(),
148 words[3].to_be_bytes(),
149 words[2].to_be_bytes(),
150 words[1].to_be_bytes(),
151 words[0].to_be_bytes(),
152 ];
153 unsafe { core::mem::transmute::<[[u8; 8]; 8], [u8; 64]>(words) }
154 }
155
156 #[must_use = "this returns the result of the operation, without modifying the original"]
158 pub const fn to_le_bytes(self) -> [u8; 64] {
159 let bits = self.0.to_bits();
160 let words = bits.digits();
161 let words = [
162 words[0].to_le_bytes(),
163 words[1].to_le_bytes(),
164 words[2].to_le_bytes(),
165 words[3].to_le_bytes(),
166 words[4].to_le_bytes(),
167 words[5].to_le_bytes(),
168 words[6].to_le_bytes(),
169 words[7].to_le_bytes(),
170 ];
171 unsafe { core::mem::transmute::<[[u8; 8]; 8], [u8; 64]>(words) }
172 }
173
174 #[must_use]
175 pub const fn is_zero(&self) -> bool {
176 self.0.is_zero()
177 }
178
179 #[must_use]
180 pub const fn is_negative(&self) -> bool {
181 self.0.is_negative()
182 }
183
184 #[must_use = "this returns the result of the operation, without modifying the original"]
185 pub const fn pow(self, exp: u32) -> Self {
186 match self.0.checked_pow(exp) {
187 Some(val) => Self(val),
188 None => panic!("attempt to exponentiate with overflow"),
189 }
190 }
191
192 pub fn checked_add(self, other: Self) -> Result<Self, OverflowError> {
193 self.0
194 .checked_add(other.0)
195 .map(Self)
196 .ok_or_else(|| OverflowError::new(OverflowOperation::Add))
197 }
198
199 pub fn checked_sub(self, other: Self) -> Result<Self, OverflowError> {
200 self.0
201 .checked_sub(other.0)
202 .map(Self)
203 .ok_or_else(|| OverflowError::new(OverflowOperation::Sub))
204 }
205
206 pub fn checked_mul(self, other: Self) -> Result<Self, OverflowError> {
207 self.0
208 .checked_mul(other.0)
209 .map(Self)
210 .ok_or_else(|| OverflowError::new(OverflowOperation::Mul))
211 }
212
213 pub fn checked_pow(self, exp: u32) -> Result<Self, OverflowError> {
214 self.0
215 .checked_pow(exp)
216 .map(Self)
217 .ok_or_else(|| OverflowError::new(OverflowOperation::Pow))
218 }
219
220 pub fn checked_div(self, other: Self) -> Result<Self, DivisionError> {
221 if other.is_zero() {
222 return Err(DivisionError::DivideByZero);
223 }
224 self.0
225 .checked_div(other.0)
226 .map(Self)
227 .ok_or(DivisionError::Overflow)
228 }
229
230 pub fn checked_div_euclid(self, other: Self) -> Result<Self, DivisionError> {
231 if other.is_zero() {
232 return Err(DivisionError::DivideByZero);
233 }
234 self.0
235 .checked_div_euclid(other.0)
236 .map(Self)
237 .ok_or(DivisionError::Overflow)
238 }
239
240 pub fn checked_rem(self, other: Self) -> Result<Self, DivideByZeroError> {
241 self.0
242 .checked_rem(other.0)
243 .map(Self)
244 .ok_or(DivideByZeroError)
245 }
246
247 pub fn checked_shr(self, other: u32) -> Result<Self, OverflowError> {
248 if other >= 512 {
249 return Err(OverflowError::new(OverflowOperation::Shr));
250 }
251
252 Ok(Self(self.0.shr(other)))
253 }
254
255 pub fn checked_shl(self, other: u32) -> Result<Self, OverflowError> {
256 if other >= 512 {
257 return Err(OverflowError::new(OverflowOperation::Shl));
258 }
259
260 Ok(Self(self.0.shl(other)))
261 }
262
263 #[must_use = "this returns the result of the operation, without modifying the original"]
264 #[inline]
265 pub fn wrapping_add(self, other: Self) -> Self {
266 Self(self.0.wrapping_add(other.0))
267 }
268
269 #[must_use = "this returns the result of the operation, without modifying the original"]
270 #[inline]
271 pub fn wrapping_sub(self, other: Self) -> Self {
272 Self(self.0.wrapping_sub(other.0))
273 }
274
275 #[must_use = "this returns the result of the operation, without modifying the original"]
276 #[inline]
277 pub fn wrapping_mul(self, other: Self) -> Self {
278 Self(self.0.wrapping_mul(other.0))
279 }
280
281 #[must_use = "this returns the result of the operation, without modifying the original"]
282 #[inline]
283 pub fn wrapping_pow(self, other: u32) -> Self {
284 Self(self.0.wrapping_pow(other))
285 }
286
287 #[must_use = "this returns the result of the operation, without modifying the original"]
288 pub fn saturating_add(self, other: Self) -> Self {
289 Self(self.0.saturating_add(other.0))
290 }
291
292 #[must_use = "this returns the result of the operation, without modifying the original"]
293 pub fn saturating_sub(self, other: Self) -> Self {
294 Self(self.0.saturating_sub(other.0))
295 }
296
297 #[must_use = "this returns the result of the operation, without modifying the original"]
298 pub fn saturating_mul(self, other: Self) -> Self {
299 Self(self.0.saturating_mul(other.0))
300 }
301
302 #[must_use = "this returns the result of the operation, without modifying the original"]
303 pub fn saturating_pow(self, exp: u32) -> Self {
304 Self(self.0.saturating_pow(exp))
305 }
306
307 #[must_use = "this returns the result of the operation, without modifying the original"]
308 pub const fn abs_diff(self, other: Self) -> Uint512 {
309 Uint512(self.0.abs_diff(other.0))
310 }
311
312 #[must_use = "this returns the result of the operation, without modifying the original"]
313 pub const fn abs(self) -> Self {
314 match self.0.checked_abs() {
315 Some(val) => Self(val),
316 None => panic!("attempt to calculate absolute value with overflow"),
317 }
318 }
319
320 #[must_use = "this returns the result of the operation, without modifying the original"]
321 pub const fn unsigned_abs(self) -> Uint512 {
322 Uint512(self.0.unsigned_abs())
323 }
324
325 pub const fn strict_neg(self) -> Self {
329 match self.0.checked_neg() {
330 Some(val) => Self(val),
331 None => panic!("attempt to negate with overflow"),
332 }
333 }
334}
335
336impl NumConsts for Int512 {
337 const ZERO: Self = Self::zero();
338 const ONE: Self = Self::one();
339 const MAX: Self = Self::MAX;
340 const MIN: Self = Self::MIN;
341}
342
343try_from_uint_to_int!(Uint512, Int512);
345
346impl From<Uint256> for Int512 {
347 fn from(val: Uint256) -> Self {
348 let mut bytes = [0u8; 64];
349 bytes[32..].copy_from_slice(&val.to_be_bytes());
350
351 Self::from_be_bytes(bytes)
352 }
353}
354
355impl From<Uint128> for Int512 {
356 fn from(val: Uint128) -> Self {
357 val.u128().into()
358 }
359}
360
361impl From<Uint64> for Int512 {
362 fn from(val: Uint64) -> Self {
363 val.u64().into()
364 }
365}
366
367primitive_to_wrapped_int!(u8, Int512);
369primitive_to_wrapped_int!(u16, Int512);
370primitive_to_wrapped_int!(u32, Int512);
371primitive_to_wrapped_int!(u64, Int512);
372primitive_to_wrapped_int!(u128, Int512);
373
374primitive_to_wrapped_int!(i8, Int512);
376primitive_to_wrapped_int!(i16, Int512);
377primitive_to_wrapped_int!(i32, Int512);
378primitive_to_wrapped_int!(i64, Int512);
379primitive_to_wrapped_int!(i128, Int512);
380
381impl From<Int64> for Int512 {
383 fn from(val: Int64) -> Self {
384 Int512(val.i64().into())
385 }
386}
387
388impl From<Int128> for Int512 {
389 fn from(val: Int128) -> Self {
390 Int512(val.i128().into())
391 }
392}
393
394impl From<Int256> for Int512 {
395 fn from(val: Int256) -> Self {
396 Self::from_be_bytes(grow_be_int(val.to_be_bytes()))
397 }
398}
399
400impl TryFrom<&str> for Int512 {
401 type Error = StdError;
402
403 fn try_from(val: &str) -> Result<Self, Self::Error> {
404 Self::from_str(val)
405 }
406}
407
408impl FromStr for Int512 {
409 type Err = StdError;
410
411 fn from_str(s: &str) -> Result<Self, Self::Err> {
412 match I512::from_str_radix(s, 10) {
413 Ok(u) => Ok(Self(u)),
414 Err(e) => Err(StdError::generic_err(format!("Parsing Int512: {e}"))),
415 }
416 }
417}
418
419impl From<Int512> for String {
420 fn from(original: Int512) -> Self {
421 original.to_string()
422 }
423}
424
425impl fmt::Display for Int512 {
426 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
427 self.0.fmt(f)
428 }
429}
430
431impl Add<Int512> for Int512 {
432 type Output = Self;
433
434 fn add(self, rhs: Self) -> Self {
435 Int512(self.0.checked_add(rhs.0).unwrap())
436 }
437}
438forward_ref_binop!(impl Add, add for Int512, Int512);
439
440impl Sub<Int512> for Int512 {
441 type Output = Self;
442
443 fn sub(self, rhs: Self) -> Self {
444 Int512(self.0.checked_sub(rhs.0).unwrap())
445 }
446}
447forward_ref_binop!(impl Sub, sub for Int512, Int512);
448
449impl SubAssign<Int512> for Int512 {
450 fn sub_assign(&mut self, rhs: Int512) {
451 self.0 = self.0.checked_sub(rhs.0).unwrap();
452 }
453}
454forward_ref_op_assign!(impl SubAssign, sub_assign for Int512, Int512);
455
456impl Div<Int512> for Int512 {
457 type Output = Self;
458
459 fn div(self, rhs: Self) -> Self::Output {
460 Self(self.0.checked_div(rhs.0).unwrap())
461 }
462}
463forward_ref_binop!(impl Div, div for Int512, Int512);
464
465impl Rem for Int512 {
466 type Output = Self;
467
468 #[inline]
472 fn rem(self, rhs: Self) -> Self {
473 Self(self.0.rem(rhs.0))
474 }
475}
476forward_ref_binop!(impl Rem, rem for Int512, Int512);
477
478impl Not for Int512 {
479 type Output = Self;
480
481 fn not(self) -> Self::Output {
482 Self(!self.0)
483 }
484}
485
486impl Neg for Int512 {
487 type Output = Self;
488
489 fn neg(self) -> Self::Output {
490 self.strict_neg()
491 }
492}
493
494impl RemAssign<Int512> for Int512 {
495 fn rem_assign(&mut self, rhs: Int512) {
496 *self = *self % rhs;
497 }
498}
499forward_ref_op_assign!(impl RemAssign, rem_assign for Int512, Int512);
500
501impl Mul<Int512> for Int512 {
502 type Output = Self;
503
504 fn mul(self, rhs: Self) -> Self::Output {
505 Self(self.0.checked_mul(rhs.0).unwrap())
506 }
507}
508forward_ref_binop!(impl Mul, mul for Int512, Int512);
509
510impl MulAssign<Int512> for Int512 {
511 fn mul_assign(&mut self, rhs: Self) {
512 self.0 = self.0.checked_mul(rhs.0).unwrap();
513 }
514}
515forward_ref_op_assign!(impl MulAssign, mul_assign for Int512, Int512);
516
517impl Shr<u32> for Int512 {
518 type Output = Self;
519
520 fn shr(self, rhs: u32) -> Self::Output {
521 self.checked_shr(rhs).unwrap_or_else(|_| {
522 panic!("right shift error: {rhs} is larger or equal than the number of bits in Int512",)
523 })
524 }
525}
526forward_ref_binop!(impl Shr, shr for Int512, u32);
527
528impl Shl<u32> for Int512 {
529 type Output = Self;
530
531 fn shl(self, rhs: u32) -> Self::Output {
532 self.checked_shl(rhs).unwrap_or_else(|_| {
533 panic!("left shift error: {rhs} is larger or equal than the number of bits in Int512",)
534 })
535 }
536}
537forward_ref_binop!(impl Shl, shl for Int512, u32);
538
539impl AddAssign<Int512> for Int512 {
540 fn add_assign(&mut self, rhs: Int512) {
541 self.0 = self.0.checked_add(rhs.0).unwrap();
542 }
543}
544forward_ref_op_assign!(impl AddAssign, add_assign for Int512, Int512);
545
546impl DivAssign<Int512> for Int512 {
547 fn div_assign(&mut self, rhs: Self) {
548 self.0 = self.0.checked_div(rhs.0).unwrap();
549 }
550}
551forward_ref_op_assign!(impl DivAssign, div_assign for Int512, Int512);
552
553impl ShrAssign<u32> for Int512 {
554 fn shr_assign(&mut self, rhs: u32) {
555 *self = Shr::<u32>::shr(*self, rhs);
556 }
557}
558forward_ref_op_assign!(impl ShrAssign, shr_assign for Int512, u32);
559
560impl ShlAssign<u32> for Int512 {
561 fn shl_assign(&mut self, rhs: u32) {
562 *self = Shl::<u32>::shl(*self, rhs);
563 }
564}
565forward_ref_op_assign!(impl ShlAssign, shl_assign for Int512, u32);
566
567impl<A> core::iter::Sum<A> for Int512
568where
569 Self: Add<A, Output = Self>,
570{
571 fn sum<I: Iterator<Item = A>>(iter: I) -> Self {
572 iter.fold(Self::zero(), Add::add)
573 }
574}
575
576#[cfg(test)]
577mod tests {
578 use super::*;
579 use crate::math::conversion::test_try_from_uint_to_int;
580
581 #[test]
582 fn size_of_works() {
583 assert_eq!(core::mem::size_of::<Int512>(), 64);
584 }
585
586 #[test]
587 fn int512_new_works() {
588 let num = Int512::new([1; 64]);
589 let a: [u8; 64] = num.to_be_bytes();
590 assert_eq!(a, [1; 64]);
591
592 let be_bytes = [
593 0u8, 222u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
594 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
595 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
596 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 2u8, 3u8,
597 ];
598 let num = Int512::new(be_bytes);
599 let resulting_bytes: [u8; 64] = num.to_be_bytes();
600 assert_eq!(be_bytes, resulting_bytes);
601 }
602
603 #[test]
604 fn int512_not_works() {
605 let num = Int512::new([1; 64]);
606 let a = (!num).to_be_bytes();
607 assert_eq!(a, [254; 64]);
608
609 assert_eq!(!Int512::from(-1234806i128), Int512::from(!-1234806i128));
610
611 assert_eq!(!Int512::MAX, Int512::MIN);
612 assert_eq!(!Int512::MIN, Int512::MAX);
613 }
614
615 #[test]
616 fn int512_zero_works() {
617 let zero = Int512::zero();
618 assert_eq!(zero.to_be_bytes(), [0; 64]);
619 }
620
621 #[test]
622 fn uint512_one_works() {
623 let one = Int512::one();
624 let mut one_be = [0; 64];
625 one_be[63] = 1;
626
627 assert_eq!(one.to_be_bytes(), one_be);
628 }
629
630 #[test]
631 fn int512_endianness() {
632 let be_bytes = [
633 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
634 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
635 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
636 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 2u8, 3u8,
637 ];
638 let le_bytes = [
639 3u8, 2u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
640 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
641 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
642 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
643 ];
644
645 let num1 = Int512::new(be_bytes);
647 let num2 = Int512::from_be_bytes(be_bytes);
648 let num3 = Int512::from_le_bytes(le_bytes);
649 assert_eq!(num1, Int512::from(65536u32 + 512 + 3));
650 assert_eq!(num1, num2);
651 assert_eq!(num1, num3);
652 }
653
654 #[test]
655 fn int512_convert_from() {
656 let a = Int512::from(5u128);
657 assert_eq!(a.0, I512::from(5u32));
658
659 let a = Int512::from(5u64);
660 assert_eq!(a.0, I512::from(5u32));
661
662 let a = Int512::from(5u32);
663 assert_eq!(a.0, I512::from(5u32));
664
665 let a = Int512::from(5u16);
666 assert_eq!(a.0, I512::from(5u32));
667
668 let a = Int512::from(5u8);
669 assert_eq!(a.0, I512::from(5u32));
670
671 let a = Int512::from(-5i128);
672 assert_eq!(a.0, I512::from(-5i32));
673
674 let a = Int512::from(-5i64);
675 assert_eq!(a.0, I512::from(-5i32));
676
677 let a = Int512::from(-5i32);
678 assert_eq!(a.0, I512::from(-5i32));
679
680 let a = Int512::from(-5i16);
681 assert_eq!(a.0, I512::from(-5i32));
682
683 let a = Int512::from(-5i8);
684 assert_eq!(a.0, I512::from(-5i32));
685
686 let values = [
688 Int64::MAX,
689 Int64::MIN,
690 Int64::one(),
691 -Int64::one(),
692 Int64::zero(),
693 ];
694 for v in values {
695 assert_eq!(Int512::from(v).to_string(), v.to_string());
696 }
697
698 let values = [
699 Int128::MAX,
700 Int128::MIN,
701 Int128::one(),
702 -Int128::one(),
703 Int128::zero(),
704 ];
705 for v in values {
706 assert_eq!(Int512::from(v).to_string(), v.to_string());
707 }
708
709 let values = [
710 Int256::MAX,
711 Int256::MIN,
712 Int256::one(),
713 -Int256::one(),
714 Int256::zero(),
715 ];
716 for v in values {
717 assert_eq!(Int512::from(v).to_string(), v.to_string());
718 }
719
720 let result = Int512::try_from("34567");
721 assert_eq!(
722 result.unwrap().0,
723 I512::from_str_radix("34567", 10).unwrap()
724 );
725
726 let result = Int512::try_from("1.23");
727 assert!(result.is_err());
728 }
729
730 #[test]
731 fn int512_try_from_unsigned_works() {
732 test_try_from_uint_to_int::<Uint256, Int256>("Uint256", "Int256");
733 test_try_from_uint_to_int::<Uint512, Int256>("Uint512", "Int256");
734 }
735
736 #[test]
737 fn int512_implements_display() {
738 let a = Int512::from(12345u32);
739 assert_eq!(format!("Embedded: {a}"), "Embedded: 12345");
740 assert_eq!(a.to_string(), "12345");
741
742 let a = Int512::from(-12345i32);
743 assert_eq!(format!("Embedded: {a}"), "Embedded: -12345");
744 assert_eq!(a.to_string(), "-12345");
745
746 let a = Int512::zero();
747 assert_eq!(format!("Embedded: {a}"), "Embedded: 0");
748 assert_eq!(a.to_string(), "0");
749 }
750
751 #[test]
752 fn int512_display_padding_works() {
753 let a = Int512::from(123u64);
755 assert_eq!(format!("Embedded: {a:05}"), "Embedded: 00123");
756 let a = Int512::from(-123i64);
757 assert_eq!(format!("Embedded: {a:05}"), "Embedded: -0123");
758
759 let a = Int512::from(123u64);
761 assert_eq!(format!("Embedded: {a:02}"), "Embedded: 123");
762 let a = Int512::from(-123i64);
763 assert_eq!(format!("Embedded: {a:02}"), "Embedded: -123");
764 }
765
766 #[test]
767 fn int512_to_be_bytes_works() {
768 assert_eq!(Int512::zero().to_be_bytes(), [0; 64]);
769
770 let mut max = [0xff; 64];
771 max[0] = 0x7f;
772 assert_eq!(Int512::MAX.to_be_bytes(), max);
773
774 let mut one = [0; 64];
775 one[63] = 1;
776 assert_eq!(Int512::from(1u128).to_be_bytes(), one);
777 assert_eq!(
779 Int512::from(240282366920938463463374607431768124608u128).to_be_bytes(),
780 [
781 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
782 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180, 196, 179, 87, 165,
783 121, 59, 133, 246, 117, 221, 191, 255, 254, 172, 192
784 ]
785 );
786 assert_eq!(
787 Int512::from_be_bytes([
788 17, 4, 23, 32, 87, 67, 123, 200, 58, 91, 0, 38, 33, 21, 67, 78, 87, 76, 65, 54,
789 211, 201, 192, 7, 42, 233, 2, 240, 200, 115, 150, 240, 218, 88, 106, 45, 208, 134,
790 238, 119, 85, 22, 14, 88, 166, 195, 154, 73, 64, 10, 44, 59, 13, 22, 47, 12, 99, 8,
791 252, 96, 230, 187, 38, 29
792 ])
793 .to_be_bytes(),
794 [
795 17, 4, 23, 32, 87, 67, 123, 200, 58, 91, 0, 38, 33, 21, 67, 78, 87, 76, 65, 54,
796 211, 201, 192, 7, 42, 233, 2, 240, 200, 115, 150, 240, 218, 88, 106, 45, 208, 134,
797 238, 119, 85, 22, 14, 88, 166, 195, 154, 73, 64, 10, 44, 59, 13, 22, 47, 12, 99, 8,
798 252, 96, 230, 187, 38, 29
799 ]
800 );
801 }
802
803 #[test]
804 fn int512_to_le_bytes_works() {
805 assert_eq!(Int512::zero().to_le_bytes(), [0; 64]);
806
807 let mut max = [0xff; 64];
808 max[63] = 0x7f;
809 assert_eq!(Int512::MAX.to_le_bytes(), max);
810
811 let mut one = [0; 64];
812 one[0] = 1;
813 assert_eq!(Int512::from(1u128).to_le_bytes(), one);
814 assert_eq!(
816 Int512::from(240282366920938463463374607431768124608u128).to_le_bytes(),
817 [
818 192, 172, 254, 255, 191, 221, 117, 246, 133, 59, 121, 165, 87, 179, 196, 180, 0, 0,
819 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
820 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
821 ]
822 );
823 assert_eq!(
824 Int512::from_be_bytes([
825 17, 4, 23, 32, 87, 67, 123, 200, 58, 91, 0, 38, 33, 21, 67, 78, 87, 76, 65, 54,
826 211, 201, 192, 7, 42, 233, 2, 240, 200, 115, 150, 240, 218, 88, 106, 45, 208, 134,
827 238, 119, 85, 22, 14, 88, 166, 195, 154, 73, 64, 10, 44, 59, 13, 22, 47, 12, 99, 8,
828 252, 96, 230, 187, 38, 29
829 ])
830 .to_le_bytes(),
831 [
832 29, 38, 187, 230, 96, 252, 8, 99, 12, 47, 22, 13, 59, 44, 10, 64, 73, 154, 195,
833 166, 88, 14, 22, 85, 119, 238, 134, 208, 45, 106, 88, 218, 240, 150, 115, 200, 240,
834 2, 233, 42, 7, 192, 201, 211, 54, 65, 76, 87, 78, 67, 21, 33, 38, 0, 91, 58, 200,
835 123, 67, 87, 32, 23, 4, 17
836 ]
837 );
838 }
839
840 #[test]
841 fn int512_is_zero_works() {
842 assert!(Int512::zero().is_zero());
843 assert!(Int512(I512::from(0u32)).is_zero());
844
845 assert!(!Int512::from(1u32).is_zero());
846 assert!(!Int512::from(123u32).is_zero());
847 assert!(!Int512::from(-123i32).is_zero());
848 }
849
850 #[test]
851 fn int512_is_negative_works() {
852 assert!(Int512::MIN.is_negative());
853 assert!(Int512::from(-123i32).is_negative());
854
855 assert!(!Int512::MAX.is_negative());
856 assert!(!Int512::zero().is_negative());
857 assert!(!Int512::from(123u32).is_negative());
858 }
859
860 #[test]
861 fn int512_wrapping_methods() {
862 assert_eq!(
864 Int512::from(2u32).wrapping_add(Int512::from(2u32)),
865 Int512::from(4u32)
866 ); assert_eq!(Int512::MAX.wrapping_add(Int512::from(1u32)), Int512::MIN); assert_eq!(
871 Int512::from(7u32).wrapping_sub(Int512::from(5u32)),
872 Int512::from(2u32)
873 ); assert_eq!(Int512::MIN.wrapping_sub(Int512::from(1u32)), Int512::MAX); assert_eq!(
878 Int512::from(3u32).wrapping_mul(Int512::from(2u32)),
879 Int512::from(6u32)
880 ); assert_eq!(
882 Int512::MAX.wrapping_mul(Int512::from(2u32)),
883 Int512::from(-2i32)
884 ); assert_eq!(Int512::from(2u32).wrapping_pow(3), Int512::from(8u32)); assert_eq!(Int512::MAX.wrapping_pow(2), Int512::from(1u32)); }
890
891 #[test]
892 fn int512_json() {
893 let orig = Int512::from(1234567890987654321u128);
894 let serialized = serde_json::to_vec(&orig).unwrap();
895 assert_eq!(serialized.as_slice(), b"\"1234567890987654321\"");
896 let parsed: Int512 = serde_json::from_slice(&serialized).unwrap();
897 assert_eq!(parsed, orig);
898 }
899
900 #[test]
901 fn int512_compare() {
902 let a = Int512::from(12345u32);
903 let b = Int512::from(23456u32);
904
905 assert!(a < b);
906 assert!(b > a);
907 assert_eq!(a, Int512::from(12345u32));
908 }
909
910 #[test]
911 #[allow(clippy::op_ref)]
912 fn int512_math() {
913 let a = Int512::from(-12345i32);
914 let b = Int512::from(23456u32);
915
916 assert_eq!(a + b, Int512::from(11111u32));
918 assert_eq!(a + &b, Int512::from(11111u32));
919
920 assert_eq!(b - a, Int512::from(35801u32));
922 assert_eq!(b - &a, Int512::from(35801u32));
923
924 let mut c = Int512::from(300000u32);
926 c += b;
927 assert_eq!(c, Int512::from(323456u32));
928 let mut d = Int512::from(300000u32);
929 d += &b;
930 assert_eq!(d, Int512::from(323456u32));
931
932 let mut c = Int512::from(300000u32);
934 c -= b;
935 assert_eq!(c, Int512::from(276544u32));
936 let mut d = Int512::from(300000u32);
937 d -= &b;
938 assert_eq!(d, Int512::from(276544u32));
939
940 assert_eq!(a - b, Int512::from(-35801i32));
942 }
943
944 #[test]
945 #[should_panic]
946 fn int512_add_overflow_panics() {
947 let _ = Int512::MAX + Int512::from(12u32);
948 }
949
950 #[test]
951 #[allow(clippy::op_ref)]
952 fn int512_sub_works() {
953 assert_eq!(Int512::from(2u32) - Int512::from(1u32), Int512::from(1u32));
954 assert_eq!(Int512::from(2u32) - Int512::from(0u32), Int512::from(2u32));
955 assert_eq!(Int512::from(2u32) - Int512::from(2u32), Int512::from(0u32));
956 assert_eq!(Int512::from(2u32) - Int512::from(3u32), Int512::from(-1i32));
957
958 let a = Int512::from(10u32);
960 let b = Int512::from(3u32);
961 let expected = Int512::from(7u32);
962 assert_eq!(a - b, expected);
963 assert_eq!(a - &b, expected);
964 assert_eq!(&a - b, expected);
965 assert_eq!(&a - &b, expected);
966 }
967
968 #[test]
969 #[should_panic]
970 fn int512_sub_overflow_panics() {
971 let _ = Int512::MIN + Int512::one() - Int512::from(2u32);
972 }
973
974 #[test]
975 fn int512_sub_assign_works() {
976 let mut a = Int512::from(14u32);
977 a -= Int512::from(2u32);
978 assert_eq!(a, Int512::from(12u32));
979
980 let mut a = Int512::from(10u32);
982 let b = Int512::from(3u32);
983 let expected = Int512::from(7u32);
984 a -= &b;
985 assert_eq!(a, expected);
986 }
987
988 #[test]
989 #[allow(clippy::op_ref)]
990 fn int512_mul_works() {
991 assert_eq!(Int512::from(2u32) * Int512::from(3u32), Int512::from(6u32));
992 assert_eq!(Int512::from(2u32) * Int512::zero(), Int512::zero());
993
994 let a = Int512::from(11u32);
996 let b = Int512::from(3u32);
997 let expected = Int512::from(33u32);
998 assert_eq!(a * b, expected);
999 assert_eq!(a * &b, expected);
1000 assert_eq!(&a * b, expected);
1001 assert_eq!(&a * &b, expected);
1002 }
1003
1004 #[test]
1005 fn int512_mul_assign_works() {
1006 let mut a = Int512::from(14u32);
1007 a *= Int512::from(2u32);
1008 assert_eq!(a, Int512::from(28u32));
1009
1010 let mut a = Int512::from(10u32);
1012 let b = Int512::from(3u32);
1013 a *= &b;
1014 assert_eq!(a, Int512::from(30u32));
1015 }
1016
1017 #[test]
1018 fn int512_pow_works() {
1019 assert_eq!(Int512::from(2u32).pow(2), Int512::from(4u32));
1020 assert_eq!(Int512::from(2u32).pow(10), Int512::from(1024u32));
1021 }
1022
1023 #[test]
1024 #[should_panic]
1025 fn int512_pow_overflow_panics() {
1026 _ = Int512::MAX.pow(2u32);
1027 }
1028
1029 #[test]
1030 fn int512_shr_works() {
1031 let original = Int512::new([
1032 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
1033 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
1034 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
1035 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 4u8, 2u8,
1036 ]);
1037
1038 let shifted = Int512::new([
1039 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
1040 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
1041 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
1042 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 128u8, 1u8, 0u8,
1043 ]);
1044
1045 assert_eq!(original >> 2u32, shifted);
1046 }
1047
1048 #[test]
1049 #[should_panic]
1050 fn int512_shr_overflow_panics() {
1051 let _ = Int512::from(1u32) >> 512u32;
1052 }
1053
1054 #[test]
1055 fn sum_works() {
1056 let nums = vec![
1057 Int512::from(17u32),
1058 Int512::from(123u32),
1059 Int512::from(540u32),
1060 Int512::from(82u32),
1061 ];
1062 let expected = Int512::from(762u32);
1063
1064 let sum_as_ref: Int512 = nums.iter().sum();
1065 assert_eq!(expected, sum_as_ref);
1066
1067 let sum_as_owned: Int512 = nums.into_iter().sum();
1068 assert_eq!(expected, sum_as_owned);
1069 }
1070
1071 #[test]
1072 fn int512_methods() {
1073 assert!(matches!(
1075 Int512::MAX.checked_add(Int512::from(1u32)),
1076 Err(OverflowError { .. })
1077 ));
1078 assert_eq!(
1079 Int512::from(1u32).checked_add(Int512::from(1u32)),
1080 Ok(Int512::from(2u32)),
1081 );
1082 assert!(matches!(
1083 Int512::MIN.checked_sub(Int512::from(1u32)),
1084 Err(OverflowError { .. })
1085 ));
1086 assert_eq!(
1087 Int512::from(2u32).checked_sub(Int512::from(1u32)),
1088 Ok(Int512::from(1u32)),
1089 );
1090 assert!(matches!(
1091 Int512::MAX.checked_mul(Int512::from(2u32)),
1092 Err(OverflowError { .. })
1093 ));
1094 assert_eq!(
1095 Int512::from(2u32).checked_mul(Int512::from(2u32)),
1096 Ok(Int512::from(4u32)),
1097 );
1098 assert!(matches!(
1099 Int512::MAX.checked_pow(2u32),
1100 Err(OverflowError { .. })
1101 ));
1102 assert_eq!(Int512::from(2u32).checked_pow(3u32), Ok(Int512::from(8u32)),);
1103 assert_eq!(
1104 Int512::MAX.checked_div(Int512::from(0u32)),
1105 Err(DivisionError::DivideByZero)
1106 );
1107 assert_eq!(
1108 Int512::from(6u32).checked_div(Int512::from(2u32)),
1109 Ok(Int512::from(3u32)),
1110 );
1111 assert_eq!(
1112 Int512::MAX.checked_div_euclid(Int512::from(0u32)),
1113 Err(DivisionError::DivideByZero)
1114 );
1115 assert_eq!(
1116 Int512::from(6u32).checked_div_euclid(Int512::from(2u32)),
1117 Ok(Int512::from(3u32)),
1118 );
1119 assert_eq!(
1120 Int512::from(7u32).checked_div_euclid(Int512::from(2u32)),
1121 Ok(Int512::from(3u32)),
1122 );
1123 assert!(matches!(
1124 Int512::MAX.checked_rem(Int512::from(0u32)),
1125 Err(DivideByZeroError { .. })
1126 ));
1127 assert_eq!(
1129 Int512::from(-12i32).checked_div(Int512::from(10i32)),
1130 Ok(Int512::from(-1i32)),
1131 );
1132 assert_eq!(
1133 Int512::from(-2i32).checked_pow(3u32),
1134 Ok(Int512::from(-8i32)),
1135 );
1136 assert_eq!(
1137 Int512::from(-6i32).checked_mul(Int512::from(-7i32)),
1138 Ok(Int512::from(42i32)),
1139 );
1140 assert_eq!(
1141 Int512::from(-2i32).checked_add(Int512::from(3i32)),
1142 Ok(Int512::from(1i32)),
1143 );
1144 assert_eq!(
1145 Int512::from(-1i32).checked_div_euclid(Int512::from(-2i32)),
1146 Ok(Int512::from(1u32)),
1147 );
1148
1149 assert_eq!(Int512::MAX.saturating_add(Int512::from(1u32)), Int512::MAX);
1151 assert_eq!(Int512::MIN.saturating_sub(Int512::from(1u32)), Int512::MIN);
1152 assert_eq!(Int512::MAX.saturating_mul(Int512::from(2u32)), Int512::MAX);
1153 assert_eq!(Int512::from(4u32).saturating_pow(2u32), Int512::from(16u32));
1154 assert_eq!(Int512::MAX.saturating_pow(2u32), Int512::MAX);
1155 }
1156
1157 #[test]
1158 #[allow(clippy::op_ref)]
1159 fn int512_implements_rem() {
1160 let a = Int512::from(10u32);
1161 assert_eq!(a % Int512::from(10u32), Int512::zero());
1162 assert_eq!(a % Int512::from(2u32), Int512::zero());
1163 assert_eq!(a % Int512::from(1u32), Int512::zero());
1164 assert_eq!(a % Int512::from(3u32), Int512::from(1u32));
1165 assert_eq!(a % Int512::from(4u32), Int512::from(2u32));
1166
1167 assert_eq!(
1168 Int512::from(-12i32) % Int512::from(10i32),
1169 Int512::from(-2i32)
1170 );
1171 assert_eq!(
1172 Int512::from(12i32) % Int512::from(-10i32),
1173 Int512::from(2i32)
1174 );
1175 assert_eq!(
1176 Int512::from(-12i32) % Int512::from(-10i32),
1177 Int512::from(-2i32)
1178 );
1179
1180 let a = Int512::from(10u32);
1182 let b = Int512::from(3u32);
1183 let expected = Int512::from(1u32);
1184 assert_eq!(a % b, expected);
1185 assert_eq!(a % &b, expected);
1186 assert_eq!(&a % b, expected);
1187 assert_eq!(&a % &b, expected);
1188 }
1189
1190 #[test]
1191 #[should_panic(expected = "divisor of zero")]
1192 fn int512_rem_panics_for_zero() {
1193 let _ = Int512::from(10u32) % Int512::zero();
1194 }
1195
1196 #[test]
1197 fn int512_rem_assign_works() {
1198 let mut a = Int512::from(30u32);
1199 a %= Int512::from(4u32);
1200 assert_eq!(a, Int512::from(2u32));
1201
1202 let mut a = Int512::from(25u32);
1204 let b = Int512::from(6u32);
1205 a %= &b;
1206 assert_eq!(a, Int512::from(1u32));
1207 }
1208
1209 #[test]
1210 fn int512_shr() {
1211 let x: Int512 = 0x8000_0000_0000_0000_0000_0000_0000_0000u128.into();
1212 assert_eq!(x >> 0, x); assert_eq!(
1214 x >> 1,
1215 Int512::from(0x4000_0000_0000_0000_0000_0000_0000_0000u128)
1216 );
1217 assert_eq!(
1218 x >> 4,
1219 Int512::from(0x0800_0000_0000_0000_0000_0000_0000_0000u128)
1220 );
1221 assert_eq!(
1223 Int512::MIN >> (core::mem::size_of::<Int512>() as u32 * 8 - 1),
1224 -Int512::one()
1225 );
1226 }
1227
1228 #[test]
1229 fn int512_shl() {
1230 let x: Int512 = 0x0800_0000_0000_0000_0000_0000_0000_0000u128.into();
1231 assert_eq!(x << 0, x); assert_eq!(
1233 x << 1,
1234 Int512::from(0x1000_0000_0000_0000_0000_0000_0000_0000u128)
1235 );
1236 assert_eq!(
1237 x << 4,
1238 Int512::from(0x8000_0000_0000_0000_0000_0000_0000_0000u128)
1239 );
1240 assert_eq!(
1242 Int512::one() << (core::mem::size_of::<Int512>() as u32 * 8 - 1),
1243 Int512::MIN
1244 );
1245 }
1246
1247 #[test]
1248 fn int512_abs_diff_works() {
1249 let a = Int512::from(42u32);
1250 let b = Int512::from(5u32);
1251 let expected = Uint512::from(37u32);
1252 assert_eq!(a.abs_diff(b), expected);
1253 assert_eq!(b.abs_diff(a), expected);
1254
1255 let c = Int512::from(-5i32);
1256 assert_eq!(b.abs_diff(c), Uint512::from(10u32));
1257 assert_eq!(c.abs_diff(b), Uint512::from(10u32));
1258 }
1259
1260 #[test]
1261 fn int512_abs_works() {
1262 let a = Int512::from(42i32);
1263 assert_eq!(a.abs(), a);
1264
1265 let b = Int512::from(-42i32);
1266 assert_eq!(b.abs(), a);
1267
1268 assert_eq!(Int512::zero().abs(), Int512::zero());
1269 assert_eq!((Int512::MIN + Int512::one()).abs(), Int512::MAX);
1270 }
1271
1272 #[test]
1273 fn int512_unsigned_abs_works() {
1274 assert_eq!(Int512::zero().unsigned_abs(), Uint512::zero());
1275 assert_eq!(Int512::one().unsigned_abs(), Uint512::one());
1276 assert_eq!(
1277 Int512::MIN.unsigned_abs(),
1278 Uint512::from_be_bytes(Int512::MAX.to_be_bytes()) + Uint512::one()
1279 );
1280
1281 let v = Int512::from(-42i32);
1282 assert_eq!(v.unsigned_abs(), v.abs_diff(Int512::zero()));
1283 }
1284
1285 #[test]
1286 #[should_panic = "attempt to calculate absolute value with overflow"]
1287 fn int512_abs_min_panics() {
1288 _ = Int512::MIN.abs();
1289 }
1290
1291 #[test]
1292 #[should_panic = "attempt to negate with overflow"]
1293 fn int512_neg_min_panics() {
1294 _ = -Int512::MIN;
1295 }
1296
1297 #[test]
1298 fn int512_partial_eq() {
1299 let test_cases = [(1, 1, true), (42, 42, true), (42, 24, false), (0, 0, true)]
1300 .into_iter()
1301 .map(|(lhs, rhs, expected): (u64, u64, bool)| {
1302 (Int512::from(lhs), Int512::from(rhs), expected)
1303 });
1304
1305 #[allow(clippy::op_ref)]
1306 for (lhs, rhs, expected) in test_cases {
1307 assert_eq!(lhs == rhs, expected);
1308 assert_eq!(&lhs == rhs, expected);
1309 assert_eq!(lhs == &rhs, expected);
1310 assert_eq!(&lhs == &rhs, expected);
1311 }
1312 }
1313}