1use std::fmt;
2
3use rustc_macros::{Decodable, Encodable};
4
5#[derive(Clone, Debug, Copy, PartialEq, Eq, Hash, Encodable, Decodable, PartialOrd, Ord)]
14pub struct BigInt {
15 sign: Sign,
16 val: u128,
17}
18
19#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Encodable, Decodable, PartialOrd, Ord)]
21enum Sign {
22 Negative,
23 NonNegative,
24}
25
26impl BigInt {
27 pub const ZERO: BigInt = BigInt { sign: Sign::NonNegative, val: 0 };
28 pub const ONE: BigInt = BigInt { sign: Sign::NonNegative, val: 1 };
29
30 pub fn is_negative(&self) -> bool {
31 matches!(self.sign, Sign::Negative)
32 }
33
34 pub fn abs(&self) -> u128 {
35 self.val
36 }
37
38 pub fn int_min(bit_width: u32) -> BigInt {
41 BigInt { sign: Sign::Negative, val: 1u128 << (bit_width - 1) }
42 }
43
44 pub fn int_max(bit_width: u32) -> BigInt {
47 (i128::MAX >> (128 - bit_width)).into()
48 }
49
50 pub fn uint_max(bit_width: u32) -> BigInt {
53 (u128::MAX >> (128 - bit_width)).into()
54 }
55}
56
57impl From<usize> for BigInt {
58 fn from(val: usize) -> Self {
59 BigInt { sign: Sign::NonNegative, val: val as u128 }
60 }
61}
62
63impl From<u128> for BigInt {
64 fn from(val: u128) -> Self {
65 BigInt { sign: Sign::NonNegative, val }
66 }
67}
68
69impl From<i128> for BigInt {
70 fn from(val: i128) -> Self {
71 let sign = if val < 0 { Sign::Negative } else { Sign::NonNegative };
72 BigInt { sign, val: val.unsigned_abs() }
73 }
74}
75
76impl From<i32> for BigInt {
77 fn from(val: i32) -> Self {
78 if val < 0 {
80 BigInt { sign: Sign::Negative, val: -(val as i64) as u128 }
81 } else {
82 BigInt { sign: Sign::NonNegative, val: val as u128 }
83 }
84 }
85}
86
87impl From<u32> for BigInt {
88 fn from(val: u32) -> Self {
89 BigInt { sign: Sign::NonNegative, val: val as u128 }
90 }
91}
92
93impl fmt::Display for BigInt {
94 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
95 match self.sign {
96 Sign::NonNegative => write!(f, "{}", self.val),
97 Sign::Negative => write!(f, "-{}", self.val),
98 }
99 }
100}