1#[cfg(feature = "serde")]
4use serde::{Deserialize, Serialize};
5
6pub const DECIMAL_PARTS: usize = 10;
8
9pub const I64_MAX: BigFloatNum = BigFloatNum {
11 m: [0, 0, 0, 0, 0, 8070, 4775, 3685, 3720, 9223],
12 n: DECIMAL_POSITIONS as i16,
13 sign: DECIMAL_SIGN_POS,
14 e: -(DECIMAL_POSITIONS as i8 - 19),
15};
16
17pub const I64_MIN: BigFloatNum = BigFloatNum {
19 m: [0, 0, 0, 0, 0, 8080, 4775, 3685, 3720, 9223],
20 n: DECIMAL_POSITIONS as i16,
21 sign: DECIMAL_SIGN_NEG,
22 e: -(DECIMAL_POSITIONS as i8 - 19),
23};
24
25pub const U64_MAX: BigFloatNum = BigFloatNum {
27 m: [0, 0, 0, 0, 0, 1615, 955, 737, 6744, 1844],
28 n: DECIMAL_POSITIONS as i16,
29 sign: DECIMAL_SIGN_POS,
30 e: -(DECIMAL_POSITIONS as i8 - 20),
31};
32
33pub const I128_MAX: BigFloatNum = BigFloatNum {
35 m: [7270, 4105, 1588, 3037, 1687, 3173, 4692, 3460, 4118, 1701],
36 n: DECIMAL_POSITIONS as i16,
37 sign: DECIMAL_SIGN_POS,
38 e: -1,
39};
40
41pub const I128_MIN: BigFloatNum = BigFloatNum {
43 m: [7280, 4105, 1588, 3037, 1687, 3173, 4692, 3460, 4118, 1701],
44 n: DECIMAL_POSITIONS as i16,
45 sign: DECIMAL_SIGN_NEG,
46 e: -1,
47};
48
49pub const U128_MAX: BigFloatNum = BigFloatNum {
51 m: [4550, 8211, 3176, 6074, 3374, 6346, 9384, 6920, 8236, 3402],
52 n: DECIMAL_POSITIONS as i16,
53 sign: DECIMAL_SIGN_POS,
54 e: -1,
55};
56
57#[derive(Copy, Clone, Debug)]
59#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
60pub struct BigFloatNum {
61 pub(crate) sign: i8, pub(crate) e: i8, pub(crate) n: i16, pub(crate) m: [i16; DECIMAL_PARTS], }
66
67#[derive(Eq, PartialEq, Debug, Copy, Clone)]
69pub enum Error {
70 ExponentOverflow(i8),
73
74 DivisionByZero,
76
77 ArgumentIsNegative,
79
80 InvalidArgument,
82}
83
84#[derive(Eq, PartialEq, Debug, Copy, Clone)]
86pub enum RoundingMode {
87 Up,
89
90 Down,
92
93 ToZero,
95
96 FromZero,
98
99 ToEven,
101
102 ToOdd,
104}
105
106pub const DECIMAL_BASE_LOG10: usize = 4; pub const DECIMAL_POSITIONS: usize = DECIMAL_PARTS * DECIMAL_BASE_LOG10;
108pub const DECIMAL_BASE: usize = 10000; pub const DECIMAL_SIGN_POS: i8 = 1; pub const DECIMAL_SIGN_NEG: i8 = -1; pub const DECIMAL_MIN_EXPONENT: i8 = -128; pub const DECIMAL_MAX_EXPONENT: i8 = 127; pub const ZEROED_MANTISSA: [i16; DECIMAL_PARTS] = [0; DECIMAL_PARTS];
114
115pub const ZERO: BigFloatNum = BigFloatNum {
117 m: ZEROED_MANTISSA,
118 n: 0,
119 sign: DECIMAL_SIGN_POS,
120 e: 0,
121};
122
123pub const ONE: BigFloatNum = BigFloatNum {
125 m: [0, 0, 0, 0, 0, 0, 0, 0, 0, 1000],
126 n: DECIMAL_POSITIONS as i16,
127 sign: DECIMAL_SIGN_POS,
128 e: 1 - (DECIMAL_POSITIONS as i8),
129};
130
131pub const TWO: BigFloatNum = BigFloatNum {
133 m: [0, 0, 0, 0, 0, 0, 0, 0, 0, 2000],
134 n: DECIMAL_POSITIONS as i16,
135 sign: DECIMAL_SIGN_POS,
136 e: 1 - (DECIMAL_POSITIONS as i8),
137};
138
139pub const E: BigFloatNum = BigFloatNum {
141 m: [7757, 6249, 3526, 7471, 6028, 2353, 9045, 2845, 2818, 2718],
142 n: DECIMAL_POSITIONS as i16,
143 sign: DECIMAL_SIGN_POS,
144 e: 1 - (DECIMAL_POSITIONS as i8),
145};
146
147pub const PI: BigFloatNum = BigFloatNum {
149 m: [4197, 288, 2795, 3383, 6264, 2384, 9793, 5358, 5926, 3141],
150 n: DECIMAL_POSITIONS as i16,
151 sign: DECIMAL_SIGN_POS,
152 e: 1 - (DECIMAL_POSITIONS as i8),
153};
154
155pub const MAX: BigFloatNum = BigFloatNum {
157 m: [9999, 9999, 9999, 9999, 9999, 9999, 9999, 9999, 9999, 9999],
158 n: DECIMAL_POSITIONS as i16,
159 sign: DECIMAL_SIGN_POS,
160 e: DECIMAL_MAX_EXPONENT,
161};
162
163pub const MIN: BigFloatNum = BigFloatNum {
165 m: [9999, 9999, 9999, 9999, 9999, 9999, 9999, 9999, 9999, 9999],
166 n: DECIMAL_POSITIONS as i16,
167 sign: DECIMAL_SIGN_NEG,
168 e: DECIMAL_MAX_EXPONENT,
169};
170
171pub const MIN_POSITIVE: BigFloatNum = BigFloatNum {
173 m: [1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
174 n: 1,
175 sign: DECIMAL_SIGN_POS,
176 e: DECIMAL_MIN_EXPONENT,
177};
178
179pub const MIN_POSITIVE_NORMAL: BigFloatNum = BigFloatNum {
181 m: [0, 0, 0, 0, 0, 0, 0, 0, 0, 1000],
182 n: 1,
183 sign: DECIMAL_SIGN_POS,
184 e: DECIMAL_MIN_EXPONENT,
185};
186
187impl BigFloatNum {
189 pub fn new() -> Self {
191 BigFloatNum {
192 sign: DECIMAL_SIGN_POS,
193 e: 0,
194 n: 0,
195 m: ZEROED_MANTISSA,
196 }
197 }
198
199 pub fn one() -> Self {
201 let mut val = Self::new();
202 val.m[DECIMAL_PARTS - 1] = DECIMAL_BASE as i16 / 10;
203 val.n = DECIMAL_POSITIONS as i16;
204 val.e = 1 - DECIMAL_POSITIONS as i8;
205 val
206 }
207
208 pub fn from_bytes(bytes: &[u8], sign: i8, exponent: i8) -> BigFloatNum {
214 let mut mantissa = ZEROED_MANTISSA;
215 let mut n: usize = 0;
216 let mut p: i16 = 1;
217 let d = if bytes.len() > DECIMAL_POSITIONS { DECIMAL_POSITIONS } else { bytes.len() };
218 for i in 1..d + 1 {
219 mantissa[n] += (bytes[d - i] % 10) as i16 * p;
220 p *= 10;
221 if p == DECIMAL_BASE as i16 {
222 n += 1;
223 p = 1;
224 }
225 }
226
227 BigFloatNum {
228 sign: if sign >= 0 { DECIMAL_SIGN_POS } else { DECIMAL_SIGN_NEG },
229 e: exponent,
230 n: Self::num_digits(&mantissa),
231 m: mantissa,
232 }
233 }
234
235 pub fn get_mantissa_bytes(&self, bytes: &mut [u8]) {
241 let mut n: usize = 0;
242 let mut p: i16 = 1;
243 let d = if bytes.len() < self.n as usize { bytes.len() } else { self.n as usize };
244 for i in 1..d + 1 {
245 bytes[d - i] = ((self.m[n] / p) % 10) as u8;
246 p *= 10;
247 if p == DECIMAL_BASE as i16 {
248 n += 1;
249 p = 1;
250 }
251 }
252 }
253
254 pub fn get_mantissa_len(&self) -> usize {
256 self.n as usize
257 }
258
259 pub fn is_zero(&self) -> bool {
261 self.n == 0
262 }
263
264 pub fn is_int_even(&self) -> bool {
266 let int = self.int();
267 if int.e < 0 {
268 let p = int.n + int.e as i16;
269 let mut d = int.m[p as usize / DECIMAL_BASE_LOG10];
270 let mut i = p % DECIMAL_BASE_LOG10 as i16;
271 while i > 0 {
272 d /= 10;
273 i -= 1;
274 }
275 d & 1 == 0
276 } else if int.e == 0 {
277 int.m[0] & 1 == 0
278 } else {
279 true
280 }
281 }
282
283 pub fn is_subnormal(&self) -> bool {
285 self.n < DECIMAL_POSITIONS as i16 && self.e == DECIMAL_MIN_EXPONENT
286 }
287}