1use crate::uint::U256;
4
5type InnerUint = U256;
7
8pub const ONE: u128 = 1_000_000_000_000;
10
11#[derive(Clone, Debug, PartialEq)]
13pub struct PreciseNumber {
14 pub value: InnerUint,
16}
17
18fn one() -> InnerUint {
20 InnerUint::from(ONE)
21}
22
23fn zero() -> InnerUint {
25 InnerUint::from(0)
26}
27
28impl PreciseNumber {
29 fn rounding_correction() -> InnerUint {
33 InnerUint::from(ONE / 2)
34 }
35
36 fn precision() -> InnerUint {
41 InnerUint::from(100)
42 }
43
44 fn zero() -> Self {
45 Self { value: zero() }
46 }
47
48 fn one() -> Self {
49 Self { value: one() }
50 }
51
52 const MAX_APPROXIMATION_ITERATIONS: u128 = 100;
54
55 fn min_pow_base() -> InnerUint {
58 InnerUint::from(1)
59 }
60
61 fn max_pow_base() -> InnerUint {
67 InnerUint::from(2 * ONE)
68 }
69
70 pub fn new(value: u128) -> Option<Self> {
72 let value = InnerUint::from(value).checked_mul(one())?;
73 Some(Self { value })
74 }
75
76 pub fn to_imprecise(&self) -> Option<u128> {
78 self.value
79 .checked_add(Self::rounding_correction())?
80 .checked_div(one())
81 .map(|v| v.as_u128())
82 }
83
84 pub fn almost_eq(&self, rhs: &Self, precision: InnerUint) -> bool {
86 let (difference, _) = self.unsigned_sub(rhs);
87 difference.value < precision
88 }
89
90 pub fn less_than(&self, rhs: &Self) -> bool {
92 self.value < rhs.value
93 }
94
95 pub fn greater_than(&self, rhs: &Self) -> bool {
97 self.value > rhs.value
98 }
99
100 pub fn less_than_or_equal(&self, rhs: &Self) -> bool {
102 self.value <= rhs.value
103 }
104
105 pub fn greater_than_or_equal(&self, rhs: &Self) -> bool {
107 self.value >= rhs.value
108 }
109
110 pub fn floor(&self) -> Option<Self> {
112 let value = self.value.checked_div(one())?.checked_mul(one())?;
113 Some(Self { value })
114 }
115
116 pub fn ceiling(&self) -> Option<Self> {
118 let value = self
119 .value
120 .checked_add(one().checked_sub(InnerUint::from(1))?)?
121 .checked_div(one())?
122 .checked_mul(one())?;
123 Some(Self { value })
124 }
125
126 pub fn checked_div(&self, rhs: &Self) -> Option<Self> {
128 if *rhs == Self::zero() {
129 return None;
130 }
131 match self.value.checked_mul(one()) {
132 Some(v) => {
133 let value = v
134 .checked_add(Self::rounding_correction())?
135 .checked_div(rhs.value)?;
136 Some(Self { value })
137 }
138 None => {
139 let value = self
140 .value
141 .checked_add(Self::rounding_correction())?
142 .checked_div(rhs.value)?
143 .checked_mul(one())?;
144 Some(Self { value })
145 }
146 }
147 }
148
149 pub fn checked_mul(&self, rhs: &Self) -> Option<Self> {
151 match self.value.checked_mul(rhs.value) {
152 Some(v) => {
153 let value = v
154 .checked_add(Self::rounding_correction())?
155 .checked_div(one())?;
156 Some(Self { value })
157 }
158 None => {
159 let value = if self.value >= rhs.value {
160 self.value.checked_div(one())?.checked_mul(rhs.value)?
161 } else {
162 rhs.value.checked_div(one())?.checked_mul(self.value)?
163 };
164 Some(Self { value })
165 }
166 }
167 }
168
169 pub fn checked_add(&self, rhs: &Self) -> Option<Self> {
171 let value = self.value.checked_add(rhs.value)?;
172 Some(Self { value })
173 }
174
175 pub fn checked_sub(&self, rhs: &Self) -> Option<Self> {
177 let value = self.value.checked_sub(rhs.value)?;
178 Some(Self { value })
179 }
180
181 pub fn unsigned_sub(&self, rhs: &Self) -> (Self, bool) {
183 match self.value.checked_sub(rhs.value) {
184 None => {
185 let value = rhs.value.checked_sub(self.value).unwrap();
186 (Self { value }, true)
187 }
188 Some(value) => (Self { value }, false),
189 }
190 }
191
192 pub fn checked_pow(&self, exponent: u128) -> Option<Self> {
194 let value = if exponent.checked_rem(2)? == 0 {
197 one()
198 } else {
199 self.value
200 };
201 let mut result = Self { value };
202
203 let mut squared_base = self.clone();
207 let mut current_exponent = exponent.checked_div(2)?;
208 while current_exponent != 0 {
209 squared_base = squared_base.checked_mul(&squared_base)?;
210
211 if current_exponent.checked_rem(2)? != 0 {
213 result = result.checked_mul(&squared_base)?;
214 }
215
216 current_exponent = current_exponent.checked_div(2)?;
217 }
218 Some(result)
219 }
220
221 fn checked_pow_approximation(&self, exponent: &Self, max_iterations: u128) -> Option<Self> {
240 assert!(self.value >= Self::min_pow_base());
241 assert!(self.value <= Self::max_pow_base());
242 let one = Self::one();
243 if *exponent == Self::zero() {
244 return Some(one);
245 }
246 let mut precise_guess = one.clone();
247 let mut term = precise_guess.clone();
248 let (x_minus_a, x_minus_a_negative) = self.unsigned_sub(&precise_guess);
249 let exponent_plus_one = exponent.checked_add(&one)?;
250 let mut negative = false;
251 for k in 1..max_iterations {
252 let k = Self::new(k)?;
253 let (current_exponent, current_exponent_negative) = exponent_plus_one.unsigned_sub(&k);
254 term = term.checked_mul(¤t_exponent)?;
255 term = term.checked_mul(&x_minus_a)?;
256 term = term.checked_div(&k)?;
257 if term.value < Self::precision() {
258 break;
259 }
260 if x_minus_a_negative {
261 negative = !negative;
262 }
263 if current_exponent_negative {
264 negative = !negative;
265 }
266 if negative {
267 precise_guess = precise_guess.checked_sub(&term)?;
268 } else {
269 precise_guess = precise_guess.checked_add(&term)?;
270 }
271 }
272 Some(precise_guess)
273 }
274
275 #[allow(dead_code)]
280 fn checked_pow_fraction(&self, exponent: &Self) -> Option<Self> {
281 assert!(self.value >= Self::min_pow_base());
282 assert!(self.value <= Self::max_pow_base());
283 let whole_exponent = exponent.floor()?;
284 let precise_whole = self.checked_pow(whole_exponent.to_imprecise()?)?;
285 let (remainder_exponent, negative) = exponent.unsigned_sub(&whole_exponent);
286 assert!(!negative);
287 if remainder_exponent.value == InnerUint::from(0) {
288 return Some(precise_whole);
289 }
290 let precise_remainder = self
291 .checked_pow_approximation(&remainder_exponent, Self::MAX_APPROXIMATION_ITERATIONS)?;
292 precise_whole.checked_mul(&precise_remainder)
293 }
294
295 fn newtonian_root_approximation(
300 &self,
301 root: &Self,
302 mut guess: Self,
303 iterations: u128,
304 ) -> Option<Self> {
305 let zero = Self::zero();
306 if *self == zero {
307 return Some(zero);
308 }
309 if *root == zero {
310 return None;
311 }
312 let one = Self::new(1)?;
313 let root_minus_one = root.checked_sub(&one)?;
314 let root_minus_one_whole = root_minus_one.to_imprecise()?;
315 let mut last_guess = guess.clone();
316 let precision = Self::precision();
317 for _ in 0..iterations {
318 let first_term = root_minus_one.checked_mul(&guess)?;
320 let power = guess.checked_pow(root_minus_one_whole);
321 let second_term = match power {
322 Some(num) => self.checked_div(&num)?,
323 None => Self::new(0)?,
324 };
325 guess = first_term.checked_add(&second_term)?.checked_div(root)?;
326 if last_guess.almost_eq(&guess, precision) {
327 break;
328 } else {
329 last_guess = guess.clone();
330 }
331 }
332 Some(guess)
333 }
334
335 fn minimum_sqrt_base() -> Self {
338 Self {
339 value: InnerUint::from(0),
340 }
341 }
342
343 fn maximum_sqrt_base() -> Self {
346 Self::new(std::u128::MAX).unwrap()
347 }
348
349 pub fn sqrt(&self) -> Option<Self> {
352 if self.less_than(&Self::minimum_sqrt_base())
353 || self.greater_than(&Self::maximum_sqrt_base())
354 {
355 return None;
356 }
357 let two = PreciseNumber::new(2)?;
358 let one = PreciseNumber::new(1)?;
359 let guess = self.checked_add(&one)?.checked_div(&two)?;
362 self.newtonian_root_approximation(&two, guess, Self::MAX_APPROXIMATION_ITERATIONS)
363 }
364}
365
366#[cfg(test)]
367mod tests {
368 use super::*;
369 use proptest::prelude::*;
370
371 fn check_pow_approximation(base: InnerUint, exponent: InnerUint, expected: InnerUint) {
372 let precision = InnerUint::from(5_000_000); let base = PreciseNumber { value: base };
374 let exponent = PreciseNumber { value: exponent };
375 let root = base
376 .checked_pow_approximation(&exponent, PreciseNumber::MAX_APPROXIMATION_ITERATIONS)
377 .unwrap();
378 let expected = PreciseNumber { value: expected };
379 assert!(root.almost_eq(&expected, precision));
380 }
381
382 #[test]
383 fn test_root_approximation() {
384 let one = one();
385 check_pow_approximation(one / 4, one / 2, one / 2); check_pow_approximation(one * 11 / 10, one / 2, InnerUint::from(1_048808848161u128)); check_pow_approximation(one * 4 / 5, one * 2 / 5, InnerUint::from(914610103850u128));
391 check_pow_approximation(one / 2, one * 4 / 50, InnerUint::from(946057646730u128));
395 }
397
398 fn check_pow_fraction(
399 base: InnerUint,
400 exponent: InnerUint,
401 expected: InnerUint,
402 precision: InnerUint,
403 ) {
404 let base = PreciseNumber { value: base };
405 let exponent = PreciseNumber { value: exponent };
406 let power = base.checked_pow_fraction(&exponent).unwrap();
407 let expected = PreciseNumber { value: expected };
408 assert!(power.almost_eq(&expected, precision));
409 }
410
411 #[test]
412 fn test_pow_fraction() {
413 let one = one();
414 let precision = InnerUint::from(50_000_000); let less_precision = precision * 1_000; check_pow_fraction(one, one, one, precision);
417 check_pow_fraction(
418 one * 20 / 13,
419 one * 50 / 3,
420 InnerUint::from(1312_534484739100u128),
421 precision,
422 ); check_pow_fraction(one * 2 / 7, one * 49 / 4, InnerUint::from(2163), precision);
424 check_pow_fraction(
425 one * 5000 / 5100,
426 one / 9,
427 InnerUint::from(997802126900u128),
428 precision,
429 ); check_pow_fraction(
433 one * 2,
434 one * 27 / 5,
435 InnerUint::from(42_224253144700u128),
436 less_precision,
437 ); check_pow_fraction(
439 one * 18 / 10,
440 one * 11 / 3,
441 InnerUint::from(8_629769290500u128),
442 less_precision,
443 ); }
445
446 #[test]
447 fn test_newtonian_approximation() {
448 let test = PreciseNumber::new(9).unwrap();
450 let nth_root = PreciseNumber::new(2).unwrap();
451 let guess = test.checked_div(&nth_root).unwrap();
452 let root = test
453 .newtonian_root_approximation(
454 &nth_root,
455 guess,
456 PreciseNumber::MAX_APPROXIMATION_ITERATIONS,
457 )
458 .unwrap()
459 .to_imprecise()
460 .unwrap();
461 assert_eq!(root, 3); let test = PreciseNumber::new(101).unwrap();
464 let nth_root = PreciseNumber::new(2).unwrap();
465 let guess = test.checked_div(&nth_root).unwrap();
466 let root = test
467 .newtonian_root_approximation(
468 &nth_root,
469 guess,
470 PreciseNumber::MAX_APPROXIMATION_ITERATIONS,
471 )
472 .unwrap()
473 .to_imprecise()
474 .unwrap();
475 assert_eq!(root, 10); let test = PreciseNumber::new(1_000_000_000).unwrap();
478 let nth_root = PreciseNumber::new(2).unwrap();
479 let guess = test.checked_div(&nth_root).unwrap();
480 let root = test
481 .newtonian_root_approximation(
482 &nth_root,
483 guess,
484 PreciseNumber::MAX_APPROXIMATION_ITERATIONS,
485 )
486 .unwrap()
487 .to_imprecise()
488 .unwrap();
489 assert_eq!(root, 31_623); let test = PreciseNumber::new(500).unwrap();
493 let nth_root = PreciseNumber::new(5).unwrap();
494 let guess = test.checked_div(&nth_root).unwrap();
495 let root = test
496 .newtonian_root_approximation(
497 &nth_root,
498 guess,
499 PreciseNumber::MAX_APPROXIMATION_ITERATIONS,
500 )
501 .unwrap()
502 .to_imprecise()
503 .unwrap();
504 assert_eq!(root, 3); }
506
507 fn check_square_root(check: &PreciseNumber) {
508 let epsilon = PreciseNumber {
509 value: InnerUint::from(10),
510 }; let one = PreciseNumber::one();
512 let one_plus_epsilon = one.checked_add(&epsilon).unwrap();
513 let one_minus_epsilon = one.checked_sub(&epsilon).unwrap();
514 let approximate_root = check.sqrt().unwrap();
515 let lower_bound = approximate_root
516 .checked_mul(&one_minus_epsilon)
517 .unwrap()
518 .checked_pow(2)
519 .unwrap();
520 let upper_bound = approximate_root
521 .checked_mul(&one_plus_epsilon)
522 .unwrap()
523 .checked_pow(2)
524 .unwrap();
525 assert!(check.less_than_or_equal(&upper_bound));
526 assert!(check.greater_than_or_equal(&lower_bound));
527 }
528
529 #[test]
530 fn test_square_root_min_max() {
531 let test_roots = [
532 PreciseNumber::minimum_sqrt_base(),
533 PreciseNumber::maximum_sqrt_base(),
534 ];
535 for i in test_roots.iter() {
536 check_square_root(i);
537 }
538 }
539
540 #[test]
541 fn test_floor() {
542 let whole_number = PreciseNumber::new(2).unwrap();
543 let mut decimal_number = PreciseNumber::new(2).unwrap();
544 decimal_number.value += InnerUint::from(1);
545 let floor = decimal_number.floor().unwrap();
546 let floor_again = floor.floor().unwrap();
547 assert_eq!(whole_number.value, floor.value);
548 assert_eq!(whole_number.value, floor_again.value);
549 }
550
551 #[test]
552 fn test_ceiling() {
553 let whole_number = PreciseNumber::new(2).unwrap();
554 let mut decimal_number = PreciseNumber::new(2).unwrap();
555 decimal_number.value -= InnerUint::from(1);
556 let ceiling = decimal_number.ceiling().unwrap();
557 let ceiling_again = ceiling.ceiling().unwrap();
558 assert_eq!(whole_number.value, ceiling.value);
559 assert_eq!(whole_number.value, ceiling_again.value);
560 }
561
562 proptest! {
563 #[test]
564 fn test_square_root(a in 0..u128::MAX) {
565 let a = PreciseNumber { value: InnerUint::from(a) };
566 check_square_root(&a);
567 }
568 }
569}