injective_math/fp_decimal/
exp.rs

1use std::cmp::Ordering;
2use std::str::FromStr;
3
4use crate::fp_decimal::error::FPDecimalError;
5/// Exponential functions for FPDecimal
6use crate::fp_decimal::{FPDecimal, U256};
7
8impl FPDecimal {
9    #[allow(clippy::many_single_char_names)]
10    pub fn exp_taylor_expansion(a: FPDecimal, b: FPDecimal) -> FPDecimal {
11        //a^b n+1 terms taylor expansion
12        let base = a.ln() * b;
13        let mut numerator = base;
14        let mut denominator = FPDecimal::ONE;
15
16        let denominator_parts = vec![
17            FPDecimal::TWO,
18            FPDecimal::THREE,
19            FPDecimal::FOUR,
20            FPDecimal::FIVE,
21            FPDecimal::SIX,
22            FPDecimal::SEVEN,
23            FPDecimal::EIGHT,
24            FPDecimal::NINE,
25            FPDecimal::TEN,
26            FPDecimal::ELEVEN,
27            FPDecimal::must_from_str("12"),
28            FPDecimal::must_from_str("13"),
29            FPDecimal::must_from_str("14"),
30            FPDecimal::must_from_str("15"),
31            FPDecimal::must_from_str("16"),
32            FPDecimal::must_from_str("17"),
33            FPDecimal::must_from_str("18"),
34            FPDecimal::must_from_str("19"),
35            FPDecimal::must_from_str("20"),
36            FPDecimal::must_from_str("21"),
37            FPDecimal::must_from_str("22"),
38            FPDecimal::must_from_str("23"),
39            FPDecimal::must_from_str("24"),
40            FPDecimal::must_from_str("25"),
41        ];
42
43        denominator_parts
44            .iter()
45            .map(|part| {
46                numerator *= base;
47                denominator *= *part;
48                numerator / denominator
49            })
50            .collect::<Vec<FPDecimal>>()
51            .iter()
52            .sum::<FPDecimal>()
53            + FPDecimal::ONE
54            + a.ln() * b
55    }
56    // e^(a)
57
58    fn two_pow(exponent: FPDecimal) -> Option<FPDecimal> {
59        if exponent == FPDecimal::ONE {
60            return Some(FPDecimal::TWO);
61        }
62        if exponent == FPDecimal::TWO {
63            return Some(FPDecimal::FOUR);
64        }
65        if exponent == FPDecimal::THREE {
66            return Some(FPDecimal::EIGHT);
67        }
68        if exponent == FPDecimal::FOUR {
69            return Some(FPDecimal::from(16u128));
70        }
71        if exponent == FPDecimal::FIVE {
72            return Some(FPDecimal::from(32u128));
73        }
74        if exponent == FPDecimal::SIX {
75            return Some(FPDecimal::from(64u128));
76        }
77        if exponent == FPDecimal::SEVEN {
78            return Some(FPDecimal::from(128u128));
79        }
80        if exponent == FPDecimal::EIGHT {
81            return Some(FPDecimal::from(256u128));
82        }
83        if exponent == FPDecimal::NINE {
84            return Some(FPDecimal::from(512u128));
85        }
86        if exponent == FPDecimal::TEN {
87            return Some(FPDecimal::from(1024u128));
88        }
89        if exponent == FPDecimal::ELEVEN {
90            return Some(FPDecimal::from(2048u128));
91        }
92        if exponent == FPDecimal::from(12u128) {
93            return Some(FPDecimal::from(4096u128));
94        }
95        if exponent == FPDecimal::from(13u128) {
96            return Some(FPDecimal::from(8192u128));
97        }
98        if exponent == FPDecimal::from(14u128) {
99            return Some(FPDecimal::from(16384u128));
100        }
101        if exponent == FPDecimal::from(15u128) {
102            return Some(FPDecimal::from(32768u128));
103        }
104
105        fn check_log_2(x: &FPDecimal, exponent: &FPDecimal) -> bool {
106            match x.log2() {
107                Some(v) => v == *exponent,
108                None => false,
109            }
110        }
111        let special_checks = [
112            FPDecimal::ONE,
113            FPDecimal::TWO,
114            FPDecimal::THREE,
115            FPDecimal::FOUR,
116            FPDecimal::FIVE,
117            FPDecimal::SIX,
118            FPDecimal::SEVEN,
119            FPDecimal::EIGHT,
120            FPDecimal::NINE,
121            FPDecimal::TEN,
122            FPDecimal::ELEVEN,
123            FPDecimal::from(12u128),
124            FPDecimal::from(13u128),
125            FPDecimal::from(14u128),
126            FPDecimal::from(15u128),
127            FPDecimal::ONE / FPDecimal::TWO,
128            FPDecimal::ONE / FPDecimal::THREE,
129            FPDecimal::ONE / FPDecimal::FOUR,
130            FPDecimal::ONE / FPDecimal::FIVE,
131            FPDecimal::ONE / FPDecimal::SIX,
132            FPDecimal::ONE / FPDecimal::SEVEN,
133            FPDecimal::ONE / FPDecimal::EIGHT,
134            FPDecimal::ONE / FPDecimal::NINE,
135            FPDecimal::ONE / FPDecimal::TEN,
136            FPDecimal::ONE / FPDecimal::ELEVEN,
137            FPDecimal::ONE / FPDecimal::from(12u128),
138            FPDecimal::ONE / FPDecimal::from(13u128),
139            FPDecimal::ONE / FPDecimal::from(14u128),
140            FPDecimal::ONE / FPDecimal::from(15u128),
141        ];
142        for x in special_checks.iter() {
143            if check_log_2(x, &exponent) {
144                return Some(*x);
145            }
146            if check_log_2(x, &(-exponent)) {
147                return Some(FPDecimal::ONE / *x);
148            }
149        }
150
151        if exponent == -FPDecimal::TWO {
152            return Some(FPDecimal::ONE / FPDecimal::FOUR);
153        }
154        if exponent == -FPDecimal::THREE {
155            return Some(FPDecimal::ONE / FPDecimal::EIGHT);
156        }
157        if exponent == -FPDecimal::FOUR {
158            return Some(FPDecimal::ONE / FPDecimal::from(16u128));
159        }
160        if exponent == -FPDecimal::FIVE {
161            return Some(FPDecimal::ONE / FPDecimal::from(32u128));
162        }
163        if exponent == -FPDecimal::SIX {
164            return Some(FPDecimal::ONE / FPDecimal::from(64u128));
165        }
166        if exponent == -FPDecimal::SEVEN {
167            return Some(FPDecimal::ONE / FPDecimal::from(128u128));
168        }
169        if exponent == -FPDecimal::EIGHT {
170            return Some(FPDecimal::ONE / FPDecimal::from(256u128));
171        }
172        if exponent == -FPDecimal::NINE {
173            return Some(FPDecimal::ONE / FPDecimal::from(512u128));
174        }
175        if exponent == -FPDecimal::TEN {
176            return Some(FPDecimal::ONE / FPDecimal::from(1024u128));
177        }
178        if exponent == -FPDecimal::ELEVEN {
179            return Some(FPDecimal::ONE / FPDecimal::from(2048u128));
180        }
181        if exponent == -FPDecimal::from(12u128) {
182            return Some(FPDecimal::ONE / FPDecimal::from(4096u128));
183        }
184        if exponent == -FPDecimal::from(13u128) {
185            return Some(FPDecimal::ONE / FPDecimal::from(8192u128));
186        }
187        if exponent == -FPDecimal::from(14u128) {
188            return Some(FPDecimal::ONE / FPDecimal::from(16384u128));
189        }
190        if exponent == -FPDecimal::from(15u128) {
191            return Some(FPDecimal::ONE / FPDecimal::from(32768u128));
192        }
193        None
194    }
195
196    fn e_pow(exponent: FPDecimal) -> Option<FPDecimal> {
197        if exponent == FPDecimal::ONE {
198            return Some(FPDecimal::E);
199        }
200        if exponent == FPDecimal::ONE.ln() {
201            return Some(FPDecimal::ONE);
202        }
203        if exponent == FPDecimal::TWO.ln() {
204            return Some(FPDecimal::TWO);
205        }
206        if exponent == FPDecimal::THREE.ln() {
207            return Some(FPDecimal::THREE);
208        }
209        if exponent == FPDecimal::FOUR.ln() {
210            return Some(FPDecimal::FOUR);
211        }
212        if exponent == FPDecimal::FIVE.ln() {
213            return Some(FPDecimal::FIVE);
214        }
215        if exponent == FPDecimal::SIX.ln() {
216            return Some(FPDecimal::SIX);
217        }
218        if exponent == FPDecimal::SEVEN.ln() {
219            return Some(FPDecimal::SEVEN);
220        }
221        if exponent == FPDecimal::EIGHT.ln() {
222            return Some(FPDecimal::EIGHT);
223        }
224        if exponent == FPDecimal::NINE.ln() {
225            return Some(FPDecimal::NINE);
226        }
227        if exponent == FPDecimal::TEN.ln() {
228            return Some(FPDecimal::TEN);
229        }
230        if exponent == FPDecimal::ELEVEN.ln() {
231            return Some(FPDecimal::ELEVEN);
232        }
233        if exponent == FPDecimal::from(12u128).ln() {
234            return Some(FPDecimal::from(12u128));
235        }
236        if exponent == FPDecimal::from(13u128).ln() {
237            return Some(FPDecimal::from(13u128));
238        }
239        if exponent == FPDecimal::from(14u128).ln() {
240            return Some(FPDecimal::from(14u128));
241        }
242        if exponent == FPDecimal::from(15u128).ln() {
243            return Some(FPDecimal::from(15u128));
244        }
245
246        if exponent == (FPDecimal::ONE / FPDecimal::TWO).ln() {
247            return Some(FPDecimal::ONE / FPDecimal::TWO);
248        }
249        if exponent == (FPDecimal::ONE / FPDecimal::THREE).ln() {
250            return Some(FPDecimal::ONE / FPDecimal::THREE);
251        }
252        if exponent == (FPDecimal::ONE / FPDecimal::FOUR).ln() {
253            return Some(FPDecimal::ONE / FPDecimal::FOUR);
254        }
255        if exponent == (FPDecimal::ONE / FPDecimal::FIVE).ln() {
256            return Some(FPDecimal::ONE / FPDecimal::FIVE);
257        }
258        if exponent == (FPDecimal::ONE / FPDecimal::SIX).ln() {
259            return Some(FPDecimal::ONE / FPDecimal::SIX);
260        }
261        if exponent == (FPDecimal::ONE / FPDecimal::SEVEN).ln() {
262            return Some(FPDecimal::ONE / FPDecimal::SEVEN);
263        }
264        if exponent == (FPDecimal::ONE / FPDecimal::EIGHT).ln() {
265            return Some(FPDecimal::ONE / FPDecimal::EIGHT);
266        }
267        if exponent == (FPDecimal::ONE / FPDecimal::NINE).ln() {
268            return Some(FPDecimal::ONE / FPDecimal::NINE);
269        }
270        if exponent == (FPDecimal::ONE / FPDecimal::TEN).ln() {
271            return Some(FPDecimal::ONE / FPDecimal::TEN);
272        }
273        if exponent == (FPDecimal::ONE / FPDecimal::ELEVEN).ln() {
274            return Some(FPDecimal::ONE / FPDecimal::ELEVEN);
275        }
276        if exponent == (FPDecimal::ONE / FPDecimal::from(12u128)).ln() {
277            return Some(FPDecimal::ONE / FPDecimal::from(12u128));
278        }
279        if exponent == (FPDecimal::ONE / FPDecimal::from(13u128)).ln() {
280            return Some(FPDecimal::ONE / FPDecimal::from(13u128));
281        }
282        if exponent == (FPDecimal::ONE / FPDecimal::from(14u128)).ln() {
283            return Some(FPDecimal::ONE / FPDecimal::from(14u128));
284        }
285        if exponent == (FPDecimal::ONE / FPDecimal::from(15u128)).ln() {
286            return Some(FPDecimal::ONE / FPDecimal::from(15u128));
287        }
288
289        if exponent == -FPDecimal::ONE {
290            return Some(FPDecimal::ONE / FPDecimal::E);
291        }
292        if exponent == -FPDecimal::ONE.ln() {
293            return Some(FPDecimal::ONE);
294        }
295        if exponent == FPDecimal::TWO.ln() {
296            return Some(FPDecimal::ONE / FPDecimal::TWO);
297        }
298        if exponent == -FPDecimal::THREE.ln() {
299            return Some(FPDecimal::ONE / FPDecimal::THREE);
300        }
301        if exponent == -FPDecimal::FOUR.ln() {
302            return Some(FPDecimal::ONE / FPDecimal::FOUR);
303        }
304        if exponent == -FPDecimal::FIVE.ln() {
305            return Some(FPDecimal::ONE / FPDecimal::FIVE);
306        }
307        if exponent == -FPDecimal::SIX.ln() {
308            return Some(FPDecimal::ONE / FPDecimal::SIX);
309        }
310        if exponent == -FPDecimal::SEVEN.ln() {
311            return Some(FPDecimal::ONE / FPDecimal::SEVEN);
312        }
313        if exponent == -FPDecimal::EIGHT.ln() {
314            return Some(FPDecimal::ONE / FPDecimal::EIGHT);
315        }
316        if exponent == -FPDecimal::NINE.ln() {
317            return Some(FPDecimal::ONE / FPDecimal::NINE);
318        }
319        if exponent == -FPDecimal::TEN.ln() {
320            return Some(FPDecimal::ONE / FPDecimal::TEN);
321        }
322        if exponent == -FPDecimal::ELEVEN.ln() {
323            return Some(FPDecimal::ONE / FPDecimal::ELEVEN);
324        }
325        if exponent == -FPDecimal::from(12u128).ln() {
326            return Some(FPDecimal::ONE / FPDecimal::from(12u128));
327        }
328        if exponent == -FPDecimal::from(13u128).ln() {
329            return Some(FPDecimal::ONE / FPDecimal::from(13u128));
330        }
331        if exponent == -FPDecimal::from(14u128).ln() {
332            return Some(FPDecimal::ONE / FPDecimal::from(14u128));
333        }
334        if exponent == -FPDecimal::from(15u128).ln() {
335            return Some(FPDecimal::ONE / FPDecimal::from(15u128));
336        }
337
338        if exponent == -(FPDecimal::ONE / FPDecimal::TWO).ln() {
339            return Some(FPDecimal::TWO);
340        }
341        if exponent == -(FPDecimal::ONE / FPDecimal::THREE).ln() {
342            return Some(FPDecimal::THREE);
343        }
344        if exponent == -(FPDecimal::ONE / FPDecimal::FOUR).ln() {
345            return Some(FPDecimal::FOUR);
346        }
347        if exponent == -(FPDecimal::ONE / FPDecimal::FIVE).ln() {
348            return Some(FPDecimal::FIVE);
349        }
350        if exponent == -(FPDecimal::ONE / FPDecimal::SIX).ln() {
351            return Some(FPDecimal::SIX);
352        }
353        if exponent == -(FPDecimal::ONE / FPDecimal::SEVEN).ln() {
354            return Some(FPDecimal::SEVEN);
355        }
356        if exponent == -(FPDecimal::ONE / FPDecimal::EIGHT).ln() {
357            return Some(FPDecimal::EIGHT);
358        }
359        if exponent == -(FPDecimal::ONE / FPDecimal::NINE).ln() {
360            return Some(FPDecimal::NINE);
361        }
362        if exponent == -(FPDecimal::ONE / FPDecimal::TEN).ln() {
363            return Some(FPDecimal::TEN);
364        }
365        if exponent == -(FPDecimal::ONE / FPDecimal::ELEVEN).ln() {
366            return Some(FPDecimal::ELEVEN);
367        }
368        if exponent == -(FPDecimal::ONE / FPDecimal::from(12u128)).ln() {
369            return Some(FPDecimal::from(12u128));
370        }
371        if exponent == -(FPDecimal::ONE / FPDecimal::from(13u128)).ln() {
372            return Some(FPDecimal::from(13u128));
373        }
374        if exponent == -(FPDecimal::ONE / FPDecimal::from(14u128)).ln() {
375            return Some(FPDecimal::from(14u128));
376        }
377        if exponent == -(FPDecimal::ONE / FPDecimal::from(15u128)).ln() {
378            return Some(FPDecimal::from(15u128));
379        }
380        None
381    }
382
383    fn three_pow(exponent: FPDecimal) -> Option<FPDecimal> {
384        if exponent == FPDecimal::ONE {
385            return Some(FPDecimal::THREE);
386        }
387        if exponent == FPDecimal::TWO {
388            return Some(FPDecimal::NINE);
389        }
390        if exponent == FPDecimal::THREE {
391            return Some(FPDecimal::from(27u128));
392        }
393        if exponent == FPDecimal::FOUR {
394            return Some(FPDecimal::from(81u128));
395        }
396        if exponent == FPDecimal::FIVE {
397            return Some(FPDecimal::from(243u128));
398        }
399        if exponent == FPDecimal::SIX {
400            return Some(FPDecimal::from(729u128));
401        }
402        if exponent == FPDecimal::SEVEN {
403            return Some(FPDecimal::from(2187u128));
404        }
405        if exponent == FPDecimal::EIGHT {
406            return Some(FPDecimal::from(6561u128));
407        }
408        if exponent == FPDecimal::NINE {
409            return Some(FPDecimal::from(19683u128));
410        }
411        if exponent == FPDecimal::TEN {
412            return Some(FPDecimal::from(59049u128));
413        }
414        if exponent == FPDecimal::ELEVEN {
415            return Some(FPDecimal::from(177147u128));
416        }
417        if exponent == FPDecimal::from(12u128) {
418            return Some(FPDecimal::from(531441u128));
419        }
420        if exponent == FPDecimal::from(13u128) {
421            return Some(FPDecimal::from(1594323u128));
422        }
423        if exponent == FPDecimal::from(14u128) {
424            return Some(FPDecimal::from(4782969u128));
425        }
426        if exponent == FPDecimal::from(15u128) {
427            return Some(FPDecimal::from(14348907u128));
428        }
429
430        if exponent == -FPDecimal::ONE {
431            return Some(FPDecimal::ONE / FPDecimal::THREE);
432        }
433        if exponent == -FPDecimal::TWO {
434            return Some(FPDecimal::ONE / FPDecimal::NINE);
435        }
436        if exponent == -FPDecimal::THREE {
437            return Some(FPDecimal::ONE / FPDecimal::from(27u128));
438        }
439        if exponent == -FPDecimal::FOUR {
440            return Some(FPDecimal::ONE / FPDecimal::from(81u128));
441        }
442        if exponent == -FPDecimal::FIVE {
443            return Some(FPDecimal::ONE / FPDecimal::from(243u128));
444        }
445        if exponent == -FPDecimal::SIX {
446            return Some(FPDecimal::ONE / FPDecimal::from(729u128));
447        }
448        if exponent == -FPDecimal::SEVEN {
449            return Some(FPDecimal::ONE / FPDecimal::from(2187u128));
450        }
451        if exponent == -FPDecimal::EIGHT {
452            return Some(FPDecimal::ONE / FPDecimal::from(6561u128));
453        }
454        if exponent == -FPDecimal::NINE {
455            return Some(FPDecimal::ONE / FPDecimal::from(19683u128));
456        }
457        if exponent == -FPDecimal::TEN {
458            return Some(FPDecimal::ONE / FPDecimal::from(59049u128));
459        }
460        if exponent == -FPDecimal::ELEVEN {
461            return Some(FPDecimal::ONE / FPDecimal::from(177147u128));
462        }
463        if exponent == -FPDecimal::from(12u128) {
464            return Some(FPDecimal::ONE / FPDecimal::from(531441u128));
465        }
466        if exponent == -FPDecimal::from(13u128) {
467            return Some(FPDecimal::ONE / FPDecimal::from(1594323u128));
468        }
469        if exponent == -FPDecimal::from(14u128) {
470            return Some(FPDecimal::ONE / FPDecimal::from(4782969u128));
471        }
472        if exponent == -FPDecimal::from(15u128) {
473            return Some(FPDecimal::ONE / FPDecimal::from(14348907u128));
474        }
475        None
476    }
477
478    fn five_pow(exponent: FPDecimal) -> Option<FPDecimal> {
479        if exponent == FPDecimal::ONE {
480            return Some(FPDecimal::FIVE);
481        }
482        if exponent == FPDecimal::TWO {
483            return Some(FPDecimal::from(25u128));
484        }
485        if exponent == FPDecimal::THREE {
486            return Some(FPDecimal::from(125u128));
487        }
488        if exponent == FPDecimal::FOUR {
489            return Some(FPDecimal::from(625u128));
490        }
491        if exponent == FPDecimal::FIVE {
492            return Some(FPDecimal::from(3125u128));
493        }
494        if exponent == FPDecimal::SIX {
495            return Some(FPDecimal::from(15625u128));
496        }
497        if exponent == FPDecimal::SEVEN {
498            return Some(FPDecimal::from(78125u128));
499        }
500        if exponent == FPDecimal::EIGHT {
501            return Some(FPDecimal::from(390625u128));
502        }
503        if exponent == FPDecimal::NINE {
504            return Some(FPDecimal::from(1953125u128));
505        }
506        if exponent == FPDecimal::TEN {
507            return Some(FPDecimal::from(9765625u128));
508        }
509        if exponent == FPDecimal::ELEVEN {
510            return Some(FPDecimal::from(48828125u128));
511        }
512        if exponent == FPDecimal::from(12u128) {
513            return Some(FPDecimal::from(244140625u128));
514        }
515        if exponent == FPDecimal::from(13u128) {
516            return Some(FPDecimal::from(1220703125u128));
517        }
518        if exponent == FPDecimal::from(14u128) {
519            return Some(FPDecimal::from(6103515625u128));
520        }
521        if exponent == FPDecimal::from(15u128) {
522            return Some(FPDecimal::from(30517578125u128));
523        }
524
525        if exponent == -FPDecimal::ONE {
526            return Some(FPDecimal::ONE / FPDecimal::FIVE);
527        }
528        if exponent == -FPDecimal::TWO {
529            return Some(FPDecimal::ONE / FPDecimal::from(25u128));
530        }
531        if exponent == -FPDecimal::THREE {
532            return Some(FPDecimal::ONE / FPDecimal::from(125u128));
533        }
534        if exponent == -FPDecimal::FOUR {
535            return Some(FPDecimal::ONE / FPDecimal::from(625u128));
536        }
537        if exponent == -FPDecimal::FIVE {
538            return Some(FPDecimal::ONE / FPDecimal::from(3125u128));
539        }
540        if exponent == -FPDecimal::SIX {
541            return Some(FPDecimal::ONE / FPDecimal::from(15625u128));
542        }
543        if exponent == -FPDecimal::SEVEN {
544            return Some(FPDecimal::ONE / FPDecimal::from(78125u128));
545        }
546        if exponent == -FPDecimal::EIGHT {
547            return Some(FPDecimal::ONE / FPDecimal::from(390625u128));
548        }
549        if exponent == -FPDecimal::NINE {
550            return Some(FPDecimal::ONE / FPDecimal::from(1953125u128));
551        }
552        if exponent == -FPDecimal::TEN {
553            return Some(FPDecimal::ONE / FPDecimal::from(9765625u128));
554        }
555        if exponent == -FPDecimal::ELEVEN {
556            return Some(FPDecimal::ONE / FPDecimal::from(48828125u128));
557        }
558        if exponent == -FPDecimal::from(12u128) {
559            return Some(FPDecimal::ONE / FPDecimal::from(244140625u128));
560        }
561        if exponent == -FPDecimal::from(13u128) {
562            return Some(FPDecimal::ONE / FPDecimal::from(1220703125u128));
563        }
564        if exponent == -FPDecimal::from(14u128) {
565            return Some(FPDecimal::ONE / FPDecimal::from(6103515625u128));
566        }
567        if exponent == -FPDecimal::from(15u128) {
568            return Some(FPDecimal::ONE / FPDecimal::from(30517578125u128));
569        }
570        None
571    }
572
573    fn seven_pow(exponent: FPDecimal) -> Option<FPDecimal> {
574        if exponent == FPDecimal::ONE {
575            return Some(FPDecimal::SEVEN);
576        }
577        if exponent == FPDecimal::TWO {
578            return Some(FPDecimal::from(49u128));
579        }
580        if exponent == FPDecimal::THREE {
581            return Some(FPDecimal::from(343u128));
582        }
583        if exponent == FPDecimal::FOUR {
584            return Some(FPDecimal::from(2401u128));
585        }
586        if exponent == FPDecimal::FIVE {
587            return Some(FPDecimal::from(16807u128));
588        }
589        if exponent == FPDecimal::SIX {
590            return Some(FPDecimal::from(117649u128));
591        }
592        if exponent == FPDecimal::SEVEN {
593            return Some(FPDecimal::from(823543u128));
594        }
595        if exponent == FPDecimal::EIGHT {
596            return Some(FPDecimal::from(5764801u128));
597        }
598        if exponent == FPDecimal::NINE {
599            return Some(FPDecimal::from(40353607u128));
600        }
601        if exponent == FPDecimal::TEN {
602            return Some(FPDecimal::from(282475249u128));
603        }
604        if exponent == FPDecimal::ELEVEN {
605            return Some(FPDecimal::from(1977326743u128));
606        }
607        if exponent == FPDecimal::from(12u128) {
608            return Some(FPDecimal::from(13841287201u128));
609        }
610        if exponent == FPDecimal::from(13u128) {
611            return Some(FPDecimal::from(96889010407u128));
612        }
613        if exponent == FPDecimal::from(14u128) {
614            return Some(FPDecimal::from(678223072849u128));
615        }
616        if exponent == FPDecimal::from(15u128) {
617            return Some(FPDecimal::from(4747561509943u128));
618        }
619        if exponent == -FPDecimal::ONE {
620            return Some(FPDecimal::ONE / FPDecimal::SEVEN);
621        }
622        if exponent == -FPDecimal::TWO {
623            return Some(FPDecimal::ONE / FPDecimal::from(49u128));
624        }
625        if exponent == -FPDecimal::THREE {
626            return Some(FPDecimal::ONE / FPDecimal::from(343u128));
627        }
628        if exponent == -FPDecimal::FOUR {
629            return Some(FPDecimal::ONE / FPDecimal::from(2401u128));
630        }
631        if exponent == -FPDecimal::FIVE {
632            return Some(FPDecimal::ONE / FPDecimal::from(16807u128));
633        }
634        if exponent == -FPDecimal::SIX {
635            return Some(FPDecimal::ONE / FPDecimal::from(117649u128));
636        }
637        if exponent == -FPDecimal::SEVEN {
638            return Some(FPDecimal::ONE / FPDecimal::from(823543u128));
639        }
640        if exponent == -FPDecimal::EIGHT {
641            return Some(FPDecimal::ONE / FPDecimal::from(5764801u128));
642        }
643        if exponent == -FPDecimal::NINE {
644            return Some(FPDecimal::ONE / FPDecimal::from(40353607u128));
645        }
646        if exponent == -FPDecimal::TEN {
647            return Some(FPDecimal::ONE / FPDecimal::from(282475249u128));
648        }
649        if exponent == -FPDecimal::ELEVEN {
650            return Some(FPDecimal::ONE / FPDecimal::from(1977326743u128));
651        }
652        if exponent == -FPDecimal::from(12u128) {
653            return Some(FPDecimal::ONE / FPDecimal::from(13841287201u128));
654        }
655        if exponent == -FPDecimal::from(13u128) {
656            return Some(FPDecimal::ONE / FPDecimal::from(96889010407u128));
657        }
658        if exponent == -FPDecimal::from(14u128) {
659            return Some(FPDecimal::ONE / FPDecimal::from(678223072849u128));
660        }
661        if exponent == -FPDecimal::from(15u128) {
662            return Some(FPDecimal::ONE / FPDecimal::from(4747561509943u128));
663        }
664
665        None
666    }
667
668    fn ten_pow(exponent: FPDecimal) -> Option<FPDecimal> {
669        if exponent == FPDecimal::ONE {
670            return Some(FPDecimal::from(10u128));
671        }
672        if exponent == FPDecimal::TWO {
673            return Some(FPDecimal::from(100u128));
674        }
675        if exponent == FPDecimal::THREE {
676            return Some(FPDecimal::from(1000u128));
677        }
678        if exponent == FPDecimal::FOUR {
679            return Some(FPDecimal::from(10000u128));
680        }
681        if exponent == FPDecimal::FIVE {
682            return Some(FPDecimal::from(100000u128));
683        }
684        if exponent == FPDecimal::SIX {
685            return Some(FPDecimal::from(1000000u128));
686        }
687        if exponent == FPDecimal::SEVEN {
688            return Some(FPDecimal::from(10000000u128));
689        }
690        if exponent == FPDecimal::EIGHT {
691            return Some(FPDecimal::from(100000000u128));
692        }
693        if exponent == FPDecimal::NINE {
694            return Some(FPDecimal::from(1000000000u128));
695        }
696        if exponent == FPDecimal::TEN {
697            return Some(FPDecimal::from(10000000000u128));
698        }
699        if exponent == FPDecimal::ELEVEN {
700            return Some(FPDecimal::from(100000000000u128));
701        }
702        if exponent == FPDecimal::from(12u128) {
703            return Some(FPDecimal::from(1000000000000u128));
704        }
705        if exponent == FPDecimal::from(13u128) {
706            return Some(FPDecimal::from(10000000000000u128));
707        }
708        if exponent == FPDecimal::from(14u128) {
709            return Some(FPDecimal::from(100000000000000u128));
710        }
711        if exponent == FPDecimal::from(15u128) {
712            return Some(FPDecimal::from(1000000000000000u128));
713        }
714        if exponent == FPDecimal::from(16u128) {
715            return Some(FPDecimal::from(10000000000000000u128));
716        }
717        if exponent == FPDecimal::from(17u128) {
718            return Some(FPDecimal::from(100000000000000000u128));
719        }
720        if exponent == FPDecimal::from(18u128) {
721            return Some(FPDecimal::from(1000000000000000000u128));
722        }
723        if exponent == FPDecimal::from(19u128) {
724            return Some(FPDecimal::from(10000000000000000000u128));
725        }
726        if exponent == FPDecimal::from(20u128) {
727            return Some(FPDecimal::from(100000000000000000000u128));
728        }
729        if exponent == FPDecimal::NEGATIVE_ONE {
730            return Some(FPDecimal::from_str("0.1").unwrap());
731        }
732        if exponent == FPDecimal::from_str("-2").unwrap() {
733            return Some(FPDecimal::from_str("0.01").unwrap());
734        }
735        if exponent == FPDecimal::from_str("-3").unwrap() {
736            return Some(FPDecimal::from_str("0.001").unwrap());
737        }
738        if exponent == FPDecimal::from_str("-4").unwrap() {
739            return Some(FPDecimal::from_str("0.0001").unwrap());
740        }
741        if exponent == FPDecimal::from_str("-5").unwrap() {
742            return Some(FPDecimal::from_str("0.00001").unwrap());
743        }
744        if exponent == FPDecimal::from_str("-6").unwrap() {
745            return Some(FPDecimal::from_str("0.000001").unwrap());
746        }
747        if exponent == FPDecimal::from_str("-7").unwrap() {
748            return Some(FPDecimal::from_str("0.0000001").unwrap());
749        }
750        if exponent == FPDecimal::from_str("-8").unwrap() {
751            return Some(FPDecimal::from_str("0.00000001").unwrap());
752        }
753        if exponent == FPDecimal::from_str("-9").unwrap() {
754            return Some(FPDecimal::from_str("0.000000001").unwrap());
755        }
756        if exponent == FPDecimal::from_str("-10").unwrap() {
757            return Some(FPDecimal::from_str("0.0000000001").unwrap());
758        }
759        if exponent == FPDecimal::from_str("-11").unwrap() {
760            return Some(FPDecimal::from_str("0.00000000001").unwrap());
761        }
762        if exponent == FPDecimal::from_str("-12").unwrap() {
763            return Some(FPDecimal::from_str("0.000000000001").unwrap());
764        }
765        if exponent == FPDecimal::from_str("-13").unwrap() {
766            return Some(FPDecimal::from_str("0.0000000000001").unwrap());
767        }
768        if exponent == FPDecimal::from_str("-14").unwrap() {
769            return Some(FPDecimal::from_str("0.00000000000001").unwrap());
770        }
771        if exponent == FPDecimal::from_str("-15").unwrap() {
772            return Some(FPDecimal::from_str("0.000000000000001").unwrap());
773        }
774        if exponent == FPDecimal::from_str("-16").unwrap() {
775            return Some(FPDecimal::from_str("0.0000000000000001").unwrap());
776        }
777        if exponent == FPDecimal::from_str("-17").unwrap() {
778            return Some(FPDecimal::from_str("0.00000000000000001").unwrap());
779        }
780        if exponent == FPDecimal::from_str("-18").unwrap() {
781            return Some(FPDecimal::from_str("0.000000000000000001").unwrap());
782        }
783        if exponent < FPDecimal::from_str("-18").unwrap() {
784            return Some(FPDecimal::ZERO);
785        }
786        if exponent == FPDecimal::from(21u128) {
787            return Some(FPDecimal::from(1000000000000000000000u128));
788        }
789        if exponent == FPDecimal::from(22u128) {
790            return Some(FPDecimal::from(10000000000000000000000u128));
791        }
792        if exponent == FPDecimal::from(23u128) {
793            return Some(FPDecimal::from(100000000000000000000000u128));
794        }
795        if exponent == FPDecimal::from(24u128) {
796            return Some(FPDecimal::from(1000000000000000000000000u128));
797        }
798        if exponent == FPDecimal::from(25u128) {
799            return Some(FPDecimal::from(10000000000000000000000000u128));
800        }
801        if exponent == FPDecimal::from(26u128) {
802            return Some(FPDecimal::from(100000000000000000000000000u128));
803        }
804        if exponent == FPDecimal::from(27u128) {
805            return Some(FPDecimal::from(1000000000000000000000000000u128));
806        }
807        if exponent == FPDecimal::from(28u128) {
808            return Some(FPDecimal::from(10000000000000000000000000000u128));
809        }
810        if exponent == FPDecimal::from(29u128) {
811            return Some(FPDecimal::from(100000000000000000000000000000u128));
812        }
813        if exponent == FPDecimal::from(30u128) {
814            return Some(FPDecimal::from(1000000000000000000000000000000u128));
815        }
816        if exponent == FPDecimal::from(31u128) {
817            return Some(FPDecimal::from(10000000000000000000000000000000u128));
818        }
819        if exponent == FPDecimal::from(32u128) {
820            return Some(FPDecimal::from(100000000000000000000000000000000u128));
821        }
822        if exponent == FPDecimal::from(33u128) {
823            return Some(FPDecimal::from(1000000000000000000000000000000000u128));
824        }
825        if exponent == FPDecimal::from(34u128) {
826            return Some(FPDecimal::from(10000000000000000000000000000000000u128));
827        }
828        if exponent == FPDecimal::from(35u128) {
829            return Some(FPDecimal::from(100000000000000000000000000000000000u128));
830        }
831        if exponent == FPDecimal::from(36u128) {
832            return Some(FPDecimal::from(1000000000000000000000000000000000000u128));
833        }
834        if exponent == FPDecimal::from(37u128) {
835            return Some(FPDecimal::from(10000000000000000000000000000000000000u128));
836        }
837        if exponent == FPDecimal::from(38u128) {
838            return Some(FPDecimal::from(100000000000000000000000000000000000000u128));
839        }
840        if exponent == FPDecimal::from(39u128) {
841            return Some(FPDecimal::from_str("1000000000000000000000000000000000000000").unwrap());
842        }
843        if exponent == FPDecimal::from(40u128) {
844            return Some(FPDecimal::from_str("10000000000000000000000000000000000000000").unwrap());
845        }
846        if exponent == FPDecimal::from(41u128) {
847            return Some(FPDecimal::from_str("100000000000000000000000000000000000000000").unwrap());
848        }
849        if exponent == FPDecimal::from(42u128) {
850            return Some(FPDecimal::from_str("1000000000000000000000000000000000000000000").unwrap());
851        }
852        if exponent == FPDecimal::from(43u128) {
853            return Some(FPDecimal::from_str("10000000000000000000000000000000000000000000").unwrap());
854        }
855        if exponent == FPDecimal::from(44u128) {
856            return Some(FPDecimal::from_str("100000000000000000000000000000000000000000000").unwrap());
857        }
858        if exponent == FPDecimal::from(45u128) {
859            return Some(FPDecimal::from_str("1000000000000000000000000000000000000000000000").unwrap());
860        }
861        if exponent == FPDecimal::from(46u128) {
862            return Some(FPDecimal::from_str("10000000000000000000000000000000000000000000000").unwrap());
863        }
864        if exponent == FPDecimal::from(47u128) {
865            return Some(FPDecimal::from_str("100000000000000000000000000000000000000000000000").unwrap());
866        }
867        if exponent == FPDecimal::from(48u128) {
868            return Some(FPDecimal::from_str("1000000000000000000000000000000000000000000000000").unwrap());
869        }
870        if exponent == FPDecimal::from(49u128) {
871            return Some(FPDecimal::from_str("10000000000000000000000000000000000000000000000000").unwrap());
872        }
873        if exponent == FPDecimal::from(50u128) {
874            return Some(FPDecimal::from_str("100000000000000000000000000000000000000000000000000").unwrap());
875        }
876        if exponent == FPDecimal::from(51u128) {
877            return Some(FPDecimal::from_str("1000000000000000000000000000000000000000000000000000").unwrap());
878        }
879        if exponent == FPDecimal::from(52u128) {
880            return Some(FPDecimal::from_str("10000000000000000000000000000000000000000000000000000").unwrap());
881        }
882        if exponent == FPDecimal::from(53u128) {
883            return Some(FPDecimal::from_str("100000000000000000000000000000000000000000000000000000").unwrap());
884        }
885        if exponent == FPDecimal::from(54u128) {
886            return Some(FPDecimal::from_str("1000000000000000000000000000000000000000000000000000000").unwrap());
887        }
888        if exponent == FPDecimal::from(55u128) {
889            return Some(FPDecimal::from_str("10000000000000000000000000000000000000000000000000000000").unwrap());
890        }
891        if exponent == FPDecimal::from(56u128) {
892            return Some(FPDecimal::from_str("100000000000000000000000000000000000000000000000000000000").unwrap());
893        }
894        if exponent == FPDecimal::from(57u128) {
895            return Some(FPDecimal::from_str("1000000000000000000000000000000000000000000000000000000000").unwrap());
896        }
897        if exponent == FPDecimal::from(58u128) {
898            return Some(FPDecimal::from_str("10000000000000000000000000000000000000000000000000000000000").unwrap());
899        }
900        if exponent == FPDecimal::from(59u128) {
901            return Some(FPDecimal::from_str("100000000000000000000000000000000000000000000000000000000000").unwrap());
902        }
903        None
904    }
905
906    fn eleven_pow(exponent: FPDecimal) -> Option<FPDecimal> {
907        if exponent == FPDecimal::ONE {
908            return Some(FPDecimal::ELEVEN);
909        }
910        if exponent == FPDecimal::TWO {
911            return Some(FPDecimal::from(121u128));
912        }
913        if exponent == FPDecimal::THREE {
914            return Some(FPDecimal::from(1331u128));
915        }
916        if exponent == FPDecimal::FOUR {
917            return Some(FPDecimal::from(14641u128));
918        }
919        if exponent == FPDecimal::FIVE {
920            return Some(FPDecimal::from(161051u128));
921        }
922        if exponent == FPDecimal::SIX {
923            return Some(FPDecimal::from(1771561u128));
924        }
925        if exponent == FPDecimal::SEVEN {
926            return Some(FPDecimal::from(19487171u128));
927        }
928        if exponent == FPDecimal::EIGHT {
929            return Some(FPDecimal::from(214358881u128));
930        }
931        if exponent == FPDecimal::NINE {
932            return Some(FPDecimal::from(2357947691u128));
933        }
934        if exponent == FPDecimal::TEN {
935            return Some(FPDecimal::from(25937424601u128));
936        }
937        if exponent == FPDecimal::ELEVEN {
938            return Some(FPDecimal::from(285311670611u128));
939        }
940        if exponent == FPDecimal::from(12u128) {
941            return Some(FPDecimal::from(3138428376721u128));
942        }
943        if exponent == FPDecimal::from(13u128) {
944            return Some(FPDecimal::from(34522712143931u128));
945        }
946        if exponent == FPDecimal::from(14u128) {
947            return Some(FPDecimal::from(379749833583241u128));
948        }
949        if exponent == FPDecimal::from(15u128) {
950            return Some(FPDecimal::from(4177248169415651u128));
951        }
952        if exponent == -FPDecimal::ONE {
953            return Some(FPDecimal::ONE / FPDecimal::ELEVEN);
954        }
955        if exponent == -FPDecimal::TWO {
956            return Some(FPDecimal::ONE / FPDecimal::from(121u128));
957        }
958        if exponent == -FPDecimal::THREE {
959            return Some(FPDecimal::ONE / FPDecimal::from(1331u128));
960        }
961        if exponent == -FPDecimal::FOUR {
962            return Some(FPDecimal::ONE / FPDecimal::from(14641u128));
963        }
964        if exponent == -FPDecimal::FIVE {
965            return Some(FPDecimal::ONE / FPDecimal::from(161051u128));
966        }
967        if exponent == -FPDecimal::SIX {
968            return Some(FPDecimal::ONE / FPDecimal::from(1771561u128));
969        }
970        if exponent == -FPDecimal::SEVEN {
971            return Some(FPDecimal::ONE / FPDecimal::from(19487171u128));
972        }
973        if exponent == -FPDecimal::EIGHT {
974            return Some(FPDecimal::ONE / FPDecimal::from(214358881u128));
975        }
976        if exponent == -FPDecimal::NINE {
977            return Some(FPDecimal::ONE / FPDecimal::from(2357947691u128));
978        }
979        if exponent == -FPDecimal::TEN {
980            return Some(FPDecimal::ONE / FPDecimal::from(25937424601u128));
981        }
982        if exponent == -FPDecimal::ELEVEN {
983            return Some(FPDecimal::ONE / FPDecimal::from(285311670611u128));
984        }
985        if exponent == -FPDecimal::from(12u128) {
986            return Some(FPDecimal::ONE / FPDecimal::from(3138428376721u128));
987        }
988        if exponent == -FPDecimal::from(13u128) {
989            return Some(FPDecimal::ONE / FPDecimal::from(34522712143931u128));
990        }
991        if exponent == -FPDecimal::from(14u128) {
992            return Some(FPDecimal::ONE / FPDecimal::from(379749833583241u128));
993        }
994        if exponent == -FPDecimal::from(15u128) {
995            return Some(FPDecimal::ONE / FPDecimal::from(4177248169415651u128));
996        }
997
998        None
999    }
1000
1001    pub fn pow(self, exponent: FPDecimal) -> Result<FPDecimal, FPDecimalError> {
1002        if self.is_zero() {
1003            match exponent.cmp(&FPDecimal::ZERO) {
1004                Ordering::Greater => return Ok(self),
1005                Ordering::Equal => return Ok(FPDecimal::ONE),
1006                Ordering::Less => return Err(FPDecimalError::NotSupported("Not supported".to_owned())),
1007            }
1008        }
1009        if self > FPDecimal::ZERO && exponent == FPDecimal::ZERO {
1010            return Ok(FPDecimal::ONE);
1011        }
1012        // NOTE: x^(1/3) won't be precise
1013        if exponent == FPDecimal::ONE / FPDecimal::TWO {
1014            return self.sqrt();
1015        }
1016        fn common_const_checks(base: FPDecimal, exponent: FPDecimal) -> Option<FPDecimal> {
1017            if base == FPDecimal::ONE {
1018                return Some(FPDecimal::ONE);
1019            }
1020            // type
1021            type BaseFunction<'a> = (&'a dyn Fn(FPDecimal) -> Option<FPDecimal>, FPDecimal);
1022
1023            let basic_check: [BaseFunction; 7] = [
1024                (&FPDecimal::two_pow, FPDecimal::TWO),
1025                (&FPDecimal::e_pow, FPDecimal::E),
1026                (&FPDecimal::three_pow, FPDecimal::THREE),
1027                (&FPDecimal::five_pow, FPDecimal::FIVE),
1028                (&FPDecimal::seven_pow, FPDecimal::SEVEN),
1029                (&FPDecimal::ten_pow, FPDecimal::TEN),
1030                (&FPDecimal::eleven_pow, FPDecimal::ELEVEN),
1031            ];
1032
1033            for (exp_fn, basic_case) in basic_check {
1034                if base == basic_case {
1035                    return exp_fn(exponent);
1036                }
1037            }
1038            None
1039        }
1040
1041        if self < FPDecimal::ZERO {
1042            if exponent.is_int() {
1043                if exponent % FPDecimal::TWO == FPDecimal::ONE {
1044                    if let Some(value) = common_const_checks(-self, exponent) {
1045                        return Ok(-value);
1046                    }
1047                } else if exponent % FPDecimal::TWO == FPDecimal::ZERO {
1048                    if let Some(value) = common_const_checks(-self, exponent) {
1049                        return Ok(value);
1050                    }
1051                }
1052                return Ok(FPDecimal::exp(exponent * (-self).ln()));
1053            } else {
1054                return Err(FPDecimalError::NotSupported("No complex number".to_owned()));
1055            }
1056        }
1057        if exponent.abs() == FPDecimal::ONE / FPDecimal::TWO {
1058            if exponent > FPDecimal::ZERO {
1059                return self.sqrt();
1060            } else {
1061                return Ok(FPDecimal::ONE / self.sqrt().unwrap());
1062            }
1063        }
1064
1065        fn common_checks(exponent: FPDecimal) -> Option<FPDecimal> {
1066            if FPDecimal::TWO.ln() == exponent {
1067                return Some(FPDecimal::TWO);
1068            }
1069            if FPDecimal::THREE.ln() == exponent {
1070                return Some(FPDecimal::THREE);
1071            }
1072            if FPDecimal::FIVE.ln() == exponent {
1073                return Some(FPDecimal::FIVE);
1074            }
1075            if FPDecimal::SEVEN.ln() == exponent {
1076                return Some(FPDecimal::SEVEN);
1077            }
1078            if FPDecimal::TEN.ln() == exponent {
1079                return Some(FPDecimal::TEN);
1080            }
1081            if FPDecimal::ELEVEN.ln() == exponent {
1082                return Some(FPDecimal::ELEVEN);
1083            }
1084            None
1085        }
1086
1087        type BaseCheckFunction<'a> = (&'a dyn Fn(FPDecimal) -> Option<FPDecimal>, FPDecimal);
1088
1089        if let Some(value) = common_const_checks(self, exponent) {
1090            return Ok(value);
1091        }
1092
1093        match common_checks(exponent) {
1094            Some(value) => Ok(value),
1095            None => {
1096                let base_checks: Vec<BaseCheckFunction> = vec![
1097                    (&FPDecimal::log_e, FPDecimal::E),
1098                    (&FPDecimal::log2, FPDecimal::TWO),
1099                    (&FPDecimal::log3, FPDecimal::THREE),
1100                    (&FPDecimal::log5, FPDecimal::FIVE),
1101                    (&FPDecimal::log7, FPDecimal::SEVEN),
1102                    (&FPDecimal::log10, FPDecimal::TEN),
1103                    (&FPDecimal::log11, FPDecimal::ELEVEN),
1104                ];
1105                for (log_fn, divisor) in base_checks {
1106                    if let Some(value) = log_fn(exponent) {
1107                        if self == divisor {
1108                            return Ok(value);
1109                        }
1110                    }
1111                    if let Some(value) = log_fn(self) {
1112                        if FPDecimal::ONE / value == exponent {
1113                            return Ok(divisor);
1114                        }
1115                    }
1116                }
1117                Ok(FPDecimal::exp(exponent * self.ln()))
1118            }
1119        }
1120    }
1121
1122    pub fn exp(a: FPDecimal) -> FPDecimal {
1123        // this throws underflow with a sufficiently large negative exponent
1124        // short circuit and just return 0 above a certain threshold
1125        // otherwise if there is a long enough delay between updates on a cluster
1126        // the penalty function will be bricked
1127        if a.sign == 0 && a.num >= FPDecimal::from(45i128).num {
1128            return FPDecimal::ZERO;
1129        }
1130        let mut x = a.num;
1131        let mut r = FPDecimal::ONE;
1132        while x >= U256([10, 0, 0, 0]) * FPDecimal::ONE.num {
1133            x -= U256([10, 0, 0, 0]) * FPDecimal::ONE.num;
1134            r = FPDecimal::_mul(r, FPDecimal::E_10);
1135        }
1136        if x == FPDecimal::ONE.num {
1137            let val = FPDecimal::_mul(r, FPDecimal::E);
1138            if a.sign == 0 {
1139                return FPDecimal::reciprocal(val);
1140            }
1141            return val;
1142        } else if x == FPDecimal::ZERO.num {
1143            let val = r;
1144            if a.sign == 0 {
1145                return FPDecimal::reciprocal(val);
1146            }
1147            return val;
1148        }
1149        let mut tr = FPDecimal::ONE.num;
1150        let mut d = tr;
1151        for i in 1..((2 * FPDecimal::DIGITS + 1) as u64) {
1152            d = (d * x) / (FPDecimal::ONE.num * U256([i, 0, 0, 0]));
1153            tr += d;
1154        }
1155        let val = FPDecimal::_mul(FPDecimal { num: tr, sign: 1 }, r);
1156        if a.sign == 0 {
1157            return FPDecimal::reciprocal(val);
1158        }
1159        val
1160    }
1161
1162    pub fn sqrt(self) -> Result<FPDecimal, FPDecimalError> {
1163        const MAX_ITERATIONS: i64 = 300;
1164
1165        if self < FPDecimal::ZERO {
1166            return Err(FPDecimalError::NotSupported("No complex number".to_owned()));
1167            // return None;
1168        }
1169
1170        if self.is_zero() {
1171            return Ok(FPDecimal::ZERO);
1172        }
1173
1174        // Start with an arbitrary number as the first guess
1175        let mut r = self / FPDecimal::TWO;
1176        let mut l = r + FPDecimal::ONE;
1177
1178        // Keep going while the difference is larger than the tolerance
1179        let mut c = 0i64;
1180        while (l != r) && (c < MAX_ITERATIONS) {
1181            l = r;
1182            r = (r + self / r) / FPDecimal::TWO;
1183            c += 1;
1184        }
1185
1186        Ok(r)
1187    }
1188    // pub fn sqrt(self) -> FPDecimal {
1189    //     match FPDecimal::_sqrt(self) {
1190    //         Some(value) => value,
1191    //         None => panic!("Undefined behavior"),
1192    //     }
1193    // }
1194}
1195
1196#[cfg(test)]
1197mod tests {
1198
1199    use crate::fp_decimal::error::FPDecimalError;
1200    use crate::fp_decimal::U256;
1201    use crate::FPDecimal;
1202    use std::str::FromStr;
1203
1204    #[test]
1205    fn test_3_pow_2_point_3() {
1206        // a^x = e^(xln(a))
1207        // 3^2.3 = e(2.3ln(3))
1208        assert_eq!(
1209            FPDecimal::exp_taylor_expansion(FPDecimal::THREE, FPDecimal::must_from_str("2.3")),
1210            // 12.513502532843181622
1211            FPDecimal::must_from_str("12.513502532843184097")
1212        );
1213    }
1214
1215    #[test]
1216    fn test_exp() {
1217        assert_eq!(FPDecimal::exp(FPDecimal::ONE), FPDecimal::E);
1218    }
1219    #[test]
1220    fn test_exp_x_greater_than_neg_one() {
1221        assert_eq!(
1222            FPDecimal::exp(FPDecimal::must_from_str("-0.0001")),
1223            FPDecimal::must_from_str("0.999900004999833338")
1224        );
1225
1226        assert_eq!(
1227            FPDecimal::exp(FPDecimal::must_from_str("-0.001")),
1228            FPDecimal::must_from_str("0.999000499833374993")
1229        );
1230
1231        assert_eq!(
1232            FPDecimal::exp(FPDecimal::must_from_str("-0.01")),
1233            FPDecimal::must_from_str("0.990049833749168057")
1234        );
1235
1236        assert_eq!(
1237            FPDecimal::exp(FPDecimal::must_from_str("-0.1")),
1238            FPDecimal::must_from_str("0.904837418035959577")
1239        );
1240
1241        assert_eq!(
1242            FPDecimal::exp(FPDecimal::must_from_str("-0.3")),
1243            FPDecimal::must_from_str("0.740818220681717868")
1244        );
1245
1246        assert_eq!(
1247            FPDecimal::exp(FPDecimal::must_from_str("-0.5")),
1248            FPDecimal::must_from_str("0.606530659712633426")
1249        );
1250
1251        assert_eq!(
1252            FPDecimal::exp(FPDecimal::must_from_str("-0.79")),
1253            FPDecimal::must_from_str("0.453844795282355824")
1254        );
1255
1256        assert_eq!(
1257            FPDecimal::exp(FPDecimal::must_from_str("-0.89")),
1258            FPDecimal::must_from_str("0.410655752752345489")
1259        );
1260        assert_eq!(
1261            FPDecimal::exp(FPDecimal::must_from_str("-0.9")),
1262            FPDecimal::must_from_str("0.406569659740599113")
1263        );
1264        assert_eq!(
1265            FPDecimal::exp(FPDecimal::must_from_str("-0.99")),
1266            FPDecimal::must_from_str("0.371576691022045691")
1267        );
1268    }
1269
1270    #[test]
1271    fn test_exp_x_smaller_than_neg_one() {
1272        assert_eq!(FPDecimal::exp(-FPDecimal::ONE), FPDecimal::ONE / FPDecimal::E);
1273        assert_eq!(FPDecimal::exp(-FPDecimal::TWO), FPDecimal::must_from_str("0.135335283236612692"));
1274        assert_eq!(
1275            FPDecimal::exp(-FPDecimal::THREE),
1276            FPDecimal::ONE / (FPDecimal::E * FPDecimal::E * FPDecimal::E)
1277        );
1278        assert_eq!(
1279            FPDecimal::exp(-FPDecimal::FOUR),
1280            FPDecimal::ONE / (FPDecimal::E * FPDecimal::E * FPDecimal::E * FPDecimal::E)
1281        );
1282    }
1283
1284    #[test]
1285    fn test_exp_x_smaller_than_one() {
1286        assert_eq!(FPDecimal::exp(FPDecimal::ONE), FPDecimal::E);
1287        assert_eq!(
1288            FPDecimal::exp(FPDecimal::must_from_str("0.79")),
1289            FPDecimal::must_from_str("2.203396426255936650")
1290        );
1291
1292        assert_eq!(
1293            FPDecimal::exp(FPDecimal::must_from_str("0.89")),
1294            FPDecimal::must_from_str("2.435129651289874518")
1295        );
1296        assert_eq!(
1297            FPDecimal::exp(FPDecimal::must_from_str("0.9")),
1298            FPDecimal::must_from_str("2.459603111156949656")
1299        );
1300        assert_eq!(
1301            FPDecimal::exp(FPDecimal::must_from_str("0.99")),
1302            FPDecimal::must_from_str("2.691234472349262282")
1303        );
1304    }
1305
1306    #[test]
1307    fn test_exp_x_greater_than_one() {
1308        assert_eq!(FPDecimal::exp(FPDecimal::ONE), FPDecimal::E);
1309        assert_eq!(
1310            FPDecimal::exp(FPDecimal::must_from_str("1.0001")),
1311            FPDecimal::must_from_str("2.718553670233753334")
1312        );
1313
1314        assert_eq!(
1315            FPDecimal::exp(FPDecimal::must_from_str("1.001")),
1316            FPDecimal::must_from_str("2.721001469881578756")
1317        );
1318        assert_eq!(
1319            FPDecimal::exp(FPDecimal::must_from_str("1.01")),
1320            FPDecimal::must_from_str("2.745601015016916484")
1321        );
1322        assert_eq!(
1323            FPDecimal::exp(FPDecimal::must_from_str("1.1")),
1324            FPDecimal::must_from_str("3.004166023946433102")
1325        );
1326        assert_eq!(
1327            FPDecimal::exp(FPDecimal::must_from_str("1.2")),
1328            FPDecimal::must_from_str("3.320116922736547481")
1329        );
1330
1331        assert_eq!(FPDecimal::exp(FPDecimal::TWO), FPDecimal::must_from_str("7.389056098930650216"));
1332        assert_eq!(FPDecimal::exp(FPDecimal::THREE), FPDecimal::must_from_str("20.085536923187667729"));
1333        assert_eq!(FPDecimal::exp(FPDecimal::FOUR), FPDecimal::must_from_str("54.598150033144239058"));
1334        assert_eq!(FPDecimal::exp(FPDecimal::FIVE), FPDecimal::must_from_str("148.413159102576603394"));
1335        assert_eq!(FPDecimal::exp(FPDecimal::SIX), FPDecimal::must_from_str("403.428793492735117251"));
1336        assert_eq!(FPDecimal::exp(FPDecimal::SEVEN), FPDecimal::must_from_str("1096.633158428456948182"));
1337        assert_eq!(FPDecimal::exp(FPDecimal::EIGHT), FPDecimal::must_from_str("2980.957987041489775723"));
1338    }
1339
1340    #[test]
1341    fn test_exp0() {
1342        assert_eq!(FPDecimal::exp(FPDecimal::ZERO), FPDecimal::ONE);
1343    }
1344
1345    #[test]
1346    fn test_exp10() {
1347        assert_eq!(FPDecimal::exp(FPDecimal::TEN), FPDecimal::E_10);
1348    }
1349    #[test]
1350    fn test_pow_neg() {
1351        assert_eq!(
1352            FPDecimal::pow(FPDecimal::ZERO, -FPDecimal::ONE.div(2i128)).unwrap_err(),
1353            FPDecimalError::NotSupported("Not supported".to_owned())
1354        );
1355    }
1356
1357    #[test]
1358    fn test_pow_zero() {
1359        assert_eq!(FPDecimal::ZERO.pow(FPDecimal::ONE).unwrap(), FPDecimal::ZERO);
1360    }
1361
1362    #[test]
1363    fn test_4_pow_0_5() {
1364        assert_eq!(FPDecimal::pow(FPDecimal::FOUR, FPDecimal::must_from_str("0.5")).unwrap(), FPDecimal::TWO);
1365    }
1366
1367    #[test]
1368    fn test_128_pow_0_5() {
1369        assert_eq!(
1370            FPDecimal::pow(FPDecimal::from(128u128), FPDecimal::must_from_str("0.5")).unwrap(),
1371            FPDecimal::must_from_str("11.313708498984760390")
1372        );
1373    }
1374
1375    #[test]
1376    fn test_128_pow_1_7() {
1377        assert_eq!(
1378            FPDecimal::pow(FPDecimal::from(128u128), FPDecimal::ONE / FPDecimal::SEVEN).unwrap(),
1379            FPDecimal::TWO
1380        );
1381    }
1382
1383    #[test]
1384    fn test_9_pow_0_5() {
1385        assert_eq!(
1386            FPDecimal::pow(FPDecimal::NINE, FPDecimal::must_from_str("0.5")).unwrap(),
1387            FPDecimal::THREE
1388        );
1389    }
1390
1391    #[test]
1392    fn test_27_pow_0_5() {
1393        assert_eq!(
1394            FPDecimal::pow(FPDecimal::from(27u128), FPDecimal::must_from_str("0.5")).unwrap(),
1395            FPDecimal::must_from_str("5.196152422706631880")
1396        );
1397    }
1398    #[test]
1399    fn test_27_pow_1_over_3() {
1400        assert_eq!(
1401            FPDecimal::pow(FPDecimal::from(27u128), FPDecimal::ONE / FPDecimal::THREE).unwrap(),
1402            FPDecimal::THREE
1403        );
1404    }
1405
1406    #[test]
1407    fn test_81_pow_0_25() {
1408        assert_eq!(
1409            FPDecimal::pow(FPDecimal::from(81u128), FPDecimal::ONE / FPDecimal::FOUR).unwrap(),
1410            FPDecimal::THREE
1411        );
1412    }
1413
1414    #[test]
1415    fn test_81_pow_0_5() {
1416        assert_eq!(
1417            FPDecimal::pow(FPDecimal::from(81u128), FPDecimal::ONE / FPDecimal::TWO).unwrap(),
1418            FPDecimal::NINE
1419        );
1420    }
1421
1422    #[test]
1423    fn test_25_pow_0_5() {
1424        assert_eq!(
1425            FPDecimal::pow(FPDecimal::from(25u128), FPDecimal::must_from_str("0.5")).unwrap(),
1426            FPDecimal::FIVE
1427        );
1428    }
1429
1430    #[test]
1431    fn test_125_pow_0_5() {
1432        assert_eq!(
1433            FPDecimal::pow(FPDecimal::from(125u128), FPDecimal::must_from_str("0.5")).unwrap(),
1434            FPDecimal::must_from_str("11.180339887498948482")
1435        );
1436    }
1437    #[test]
1438    fn test_125_pow_1_over_3() {
1439        assert_eq!(
1440            FPDecimal::pow(FPDecimal::from(125u128), FPDecimal::ONE / FPDecimal::THREE).unwrap(),
1441            FPDecimal::FIVE
1442        );
1443    }
1444
1445    #[test]
1446    fn test_625_pow_0_25() {
1447        assert_eq!(
1448            FPDecimal::pow(FPDecimal::from(625u128), FPDecimal::ONE / FPDecimal::FOUR).unwrap(),
1449            FPDecimal::FIVE
1450        );
1451    }
1452
1453    #[test]
1454    fn test_49_pow_0_5() {
1455        assert_eq!(
1456            FPDecimal::pow(FPDecimal::from(49u128), FPDecimal::must_from_str("0.5")).unwrap(),
1457            FPDecimal::SEVEN
1458        );
1459    }
1460
1461    #[test]
1462    fn test_343_pow_0_5() {
1463        assert_eq!(
1464            FPDecimal::pow(FPDecimal::from(343u128), FPDecimal::must_from_str("0.5")).unwrap(),
1465            FPDecimal::must_from_str("18.520259177452134133")
1466        );
1467    }
1468    #[test]
1469    fn test_343_pow_1_over_3() {
1470        assert_eq!(
1471            FPDecimal::pow(FPDecimal::from(343u128), FPDecimal::ONE / FPDecimal::THREE).unwrap(),
1472            FPDecimal::SEVEN
1473        );
1474    }
1475
1476    #[test]
1477    fn test_2401_pow_0_25() {
1478        assert_eq!(
1479            FPDecimal::pow(FPDecimal::from(2401u128), FPDecimal::ONE / FPDecimal::FOUR).unwrap(),
1480            FPDecimal::SEVEN
1481        );
1482    }
1483
1484    #[test]
1485    fn test_121_pow_0_5() {
1486        assert_eq!(
1487            FPDecimal::pow(FPDecimal::from(121u128), FPDecimal::must_from_str("0.5")).unwrap(),
1488            FPDecimal::ELEVEN
1489        );
1490    }
1491
1492    #[test]
1493    fn test_1331_pow_0_5() {
1494        assert_eq!(
1495            FPDecimal::pow(FPDecimal::from(1331u128), FPDecimal::must_from_str("0.5")).unwrap(),
1496            FPDecimal::must_from_str("36.48287269390939834")
1497        );
1498    }
1499    #[test]
1500    fn test_1331_pow_1_over_3() {
1501        assert_eq!(
1502            FPDecimal::pow(FPDecimal::from(1331u128), FPDecimal::ONE / FPDecimal::THREE).unwrap(),
1503            FPDecimal::ELEVEN
1504        );
1505    }
1506
1507    #[test]
1508    fn test_14641_pow_0_25() {
1509        assert_eq!(
1510            FPDecimal::pow(FPDecimal::from(14641u128), FPDecimal::ONE / FPDecimal::FOUR).unwrap(),
1511            FPDecimal::ELEVEN
1512        );
1513    }
1514
1515    #[test]
1516    fn test_2_pow_1() {
1517        assert_eq!(FPDecimal::TWO.pow(FPDecimal::ONE).unwrap(), FPDecimal::TWO);
1518    }
1519
1520    #[test]
1521    fn test_3_pow_1() {
1522        assert_eq!(FPDecimal::THREE.pow(FPDecimal::ONE).unwrap(), FPDecimal::THREE);
1523    }
1524
1525    #[test]
1526    fn test_pow_exp_1() {
1527        assert_eq!(FPDecimal::E.pow(FPDecimal::ONE).unwrap(), FPDecimal::E);
1528    }
1529
1530    #[test]
1531    fn test_pow_exp_0() {
1532        assert_eq!(FPDecimal::E.pow(FPDecimal::ZERO).unwrap(), FPDecimal::ONE);
1533    }
1534
1535    #[test]
1536    fn test_pow_exp_10() {
1537        assert_eq!(
1538            FPDecimal::E
1539                .pow(FPDecimal {
1540                    num: U256([10, 0, 0, 0]) * FPDecimal::ONE.num,
1541                    sign: 1
1542                })
1543                .unwrap(),
1544            FPDecimal::E_10
1545        );
1546    }
1547
1548    #[test]
1549    fn test_pow_zero_2() {
1550        assert_eq!(FPDecimal::ZERO.pow(FPDecimal::ONE.div(2i128)).unwrap(), FPDecimal::ZERO);
1551    }
1552
1553    #[test]
1554    fn test_square_root() {
1555        let inputs: Vec<i128> = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 16, 25, -1];
1556
1557        let expected = vec![
1558            Ok(FPDecimal::ZERO),
1559            Ok(FPDecimal::ONE),
1560            Ok(FPDecimal::from_str("1.414213562373095048").unwrap()),
1561            Ok(FPDecimal::from_str("1.732050807568877293").unwrap()),
1562            Ok(FPDecimal::TWO),
1563            Ok(FPDecimal::from_str("2.236067977499789696").unwrap()),
1564            Ok(FPDecimal::from_str("2.449489742783178098").unwrap()),
1565            Ok(FPDecimal::from_str("2.645751311064590590").unwrap()),
1566            Ok(FPDecimal::from_str("2.828427124746190097").unwrap()),
1567            Ok(FPDecimal::THREE),
1568            Ok(FPDecimal::from_str("3.162277660168379331").unwrap()),
1569            Ok(FPDecimal::FOUR),
1570            Ok(FPDecimal::FIVE),
1571            Err(FPDecimalError::NotSupported("No complex number".to_owned())),
1572        ];
1573
1574        for (ix, el) in inputs.iter().enumerate() {
1575            let result = FPDecimal::from(*el).sqrt();
1576
1577            assert_eq!(result, expected[ix]);
1578        }
1579    }
1580
1581    #[test]
1582    fn test_pow_10_positive() {
1583        let base = FPDecimal::from(10u128);
1584        assert_eq!(base.pow(FPDecimal::must_from_str("6")).unwrap(), FPDecimal::must_from_str("1000000"));
1585    }
1586
1587    #[test]
1588    fn test_pow_10_max() {
1589        let base = FPDecimal::from(10u128);
1590        assert_eq!(
1591            base.pow(FPDecimal::must_from_str("59")).unwrap(),
1592            FPDecimal::from_str("100000000000000000000000000000000000000000000000000000000000").unwrap()
1593        );
1594    }
1595
1596    #[test]
1597    #[should_panic]
1598    fn test_pow_10_overflow() {
1599        let base = FPDecimal::from(10u128);
1600        base.pow(FPDecimal::must_from_str("60")).unwrap();
1601    }
1602
1603    #[test]
1604    fn test_pow_10_neg_3() {
1605        let base = FPDecimal::from(10u128);
1606        assert_eq!(base.pow(FPDecimal::must_from_str("-3")).unwrap(), FPDecimal::must_from_str("0.001"));
1607    }
1608
1609    #[test]
1610    fn test_e_pow_neg_3() {
1611        let base = FPDecimal::E;
1612        assert_eq!(
1613            base.pow(FPDecimal::must_from_str("-3")).unwrap(),
1614            FPDecimal::must_from_str("0.049787068367863943")
1615        );
1616    }
1617
1618    #[test]
1619    fn test_e_pow_0_5() {
1620        assert_eq!(
1621            FPDecimal::E.pow(FPDecimal::must_from_str("0.5")).unwrap(),
1622            // 1.6487212707001281469
1623            FPDecimal::must_from_str("1.648721270700128146")
1624        );
1625    }
1626
1627    #[test]
1628    fn test_pow_10_min() {
1629        let base = FPDecimal::from(10u128);
1630        assert_eq!(
1631            base.pow(FPDecimal::must_from_str("-18")).unwrap(),
1632            FPDecimal::must_from_str("0.000000000000000001")
1633        );
1634    }
1635
1636    #[test]
1637    fn test_pow_10_underflow() {
1638        let base = FPDecimal::from(10u128);
1639        assert_eq!(base.pow(FPDecimal::must_from_str("-19")).unwrap(), FPDecimal::ZERO);
1640    }
1641
1642    #[test]
1643    fn test_checked_2_pow_2() {
1644        let base = FPDecimal::from(2u128);
1645
1646        let result = FPDecimal::pow(base, FPDecimal::from(2u128)).unwrap();
1647        assert_eq!(result, FPDecimal::from(4u128));
1648    }
1649
1650    #[test]
1651    fn test_2_3_pow_1_4() {
1652        let base = FPDecimal::must_from_str("2.3");
1653        let exponent = FPDecimal::must_from_str("1.4");
1654        // let result_1 = FPDecimal::checked_positive_pow(base, exponent).unwrap();
1655        let result_2 = FPDecimal::pow(base, exponent).unwrap();
1656        assert_eq!(result_2, FPDecimal::must_from_str("3.209363953267971906"));
1657    }
1658
1659    #[test]
1660    fn test_2_3_pow_3_7() {
1661        let base = FPDecimal::must_from_str("2.3");
1662        let exponent = FPDecimal::must_from_str("3.7");
1663        let result_2 = FPDecimal::pow(base, exponent).unwrap();
1664        //21.796812747431183828
1665        assert_eq!(result_2, FPDecimal::must_from_str("21.796812747431186181"));
1666    }
1667
1668    #[test]
1669    fn test_2_3_pow_neg_1_4() {
1670        let base = FPDecimal::must_from_str("2.3");
1671        let exponent = FPDecimal::must_from_str("-1.4");
1672        // let result_1 = FPDecimal::checked_positive_pow(base, exponent).unwrap();
1673        let result_2 = FPDecimal::pow(base, exponent).unwrap();
1674        // 0.31158821952298012815
1675        assert_eq!(result_2, FPDecimal::must_from_str("0.311588219522980075"));
1676        // assert_eq!(result_1, FPDecimal::must_from_str("0.311588219522980069"));
1677    }
1678
1679    #[test]
1680    fn test_2_3_pow_neg_3_7() {
1681        let base = FPDecimal::must_from_str("2.3");
1682        let exponent = FPDecimal::must_from_str("-3.7");
1683        // let result_1 = FPDecimal::checked_positive_pow(base, exponent).unwrap();
1684        let result_2 = FPDecimal::pow(base, exponent).unwrap();
1685        // 0.045878267230508407006
1686        assert_eq!(result_2, FPDecimal::must_from_str("0.045878267230508402"));
1687        // assert_eq!(result_1, FPDecimal::must_from_str("0.045878267230507924"));
1688    }
1689
1690    #[test]
1691    fn test_2_3_pow_0_4() {
1692        let base = FPDecimal::must_from_str("2.3");
1693        let exponent = FPDecimal::must_from_str("0.4");
1694        let result_2 = FPDecimal::pow(base, exponent).unwrap();
1695        assert_eq!(result_2, FPDecimal::must_from_str("1.395375631855639968"));
1696    }
1697
1698    #[test]
1699    fn test_2_3_pow_neg_0_4() {
1700        let base = FPDecimal::must_from_str("2.3");
1701        let exponent = FPDecimal::must_from_str("-0.4");
1702        let result_2 = FPDecimal::pow(base, exponent).unwrap();
1703        // 0.71665290490285417314
1704        assert_eq!(result_2, FPDecimal::must_from_str("0.716652904902854170"));
1705    }
1706
1707    #[test]
1708    fn test_1_over_16_pow_neg_0_5() {
1709        let base = FPDecimal::ONE / FPDecimal::from(16u128);
1710        let exponent = FPDecimal::must_from_str("-0.5");
1711
1712        let result = FPDecimal::pow(base, exponent).unwrap();
1713        assert_eq!(result, FPDecimal::FOUR);
1714    }
1715
1716    #[test]
1717    fn test_1_over_16_pow_0_5() {
1718        let base = FPDecimal::ONE / FPDecimal::from(16u128);
1719        let exponent = FPDecimal::must_from_str("0.5");
1720
1721        // let result = FPDecimal::checked_positive_pow(base, exponent).unwrap();
1722        let result = FPDecimal::pow(base, exponent).unwrap();
1723        assert_eq!(result, FPDecimal::ONE / FPDecimal::FOUR);
1724    }
1725
1726    #[test]
1727    fn test_100_pow_neg_1_over_2() {
1728        assert_eq!(
1729            FPDecimal::pow(FPDecimal::from(100u128), FPDecimal::must_from_str("-0.5")).unwrap(),
1730            FPDecimal::must_from_str("0.1")
1731        );
1732    }
1733
1734    #[test]
1735    fn test_1000_pow_1_over_3() {
1736        assert_eq!(
1737            FPDecimal::pow(FPDecimal::from(1000u128), FPDecimal::ONE / FPDecimal::THREE).unwrap(),
1738            FPDecimal::TEN
1739        );
1740    }
1741
1742    #[test]
1743    fn test_neg_1000_pow_1_over_3() {
1744        assert_eq!(
1745            FPDecimal::pow(FPDecimal::must_from_str("-1000.0"), FPDecimal::ONE / FPDecimal::THREE).unwrap_err(),
1746            FPDecimalError::NotSupported("No complex number".to_owned())
1747        );
1748    }
1749
1750    #[test]
1751    fn test_neg_10_pow_3() {
1752        assert_eq!(
1753            FPDecimal::pow(FPDecimal::must_from_str("-10"), FPDecimal::THREE).unwrap(),
1754            -FPDecimal::TEN.pow(FPDecimal::THREE).unwrap()
1755        );
1756    }
1757
1758    #[test]
1759    fn test_neg_10_pow_4() {
1760        assert_eq!(
1761            FPDecimal::pow(FPDecimal::must_from_str("-10"), FPDecimal::FOUR),
1762            FPDecimal::TEN.pow(FPDecimal::FOUR)
1763        );
1764    }
1765
1766    #[test]
1767    fn test_neg_10_pow_2_3() {
1768        assert_eq!(
1769            FPDecimal::pow(FPDecimal::must_from_str("-10"), FPDecimal::must_from_str("2.3")).unwrap_err(),
1770            FPDecimalError::NotSupported("No complex number".to_owned())
1771        );
1772    }
1773
1774    #[test]
1775    #[should_panic]
1776    fn test_neg_1000_pow_1_over_4() {
1777        assert_eq!(
1778            FPDecimal::pow(FPDecimal::must_from_str("-1000.0"), FPDecimal::ONE / FPDecimal::FOUR).unwrap(),
1779            -FPDecimal::TEN
1780        );
1781    }
1782
1783    #[test]
1784    fn test_exp_log_2() {
1785        // assert_eq!(FPDecimal::E.pow(FPDecimal::TWO.ln()), FPDecimal::must_from_str("2.0"));
1786        assert_eq!(FPDecimal::E.pow(FPDecimal::TWO.ln()).unwrap(), FPDecimal::must_from_str("2.0"));
1787    }
1788
1789    #[test]
1790    fn test_sqrt() {
1791        assert_eq!(FPDecimal::FOUR.sqrt().unwrap(), FPDecimal::TWO);
1792        assert_eq!(FPDecimal::from(16u128).sqrt().unwrap(), FPDecimal::FOUR);
1793        assert_eq!(FPDecimal::ONE.sqrt().unwrap(), FPDecimal::ONE);
1794        assert_eq!(FPDecimal::NINE.sqrt().unwrap(), FPDecimal::THREE);
1795        assert_eq!(FPDecimal::from(81u128).sqrt().unwrap(), FPDecimal::NINE);
1796    }
1797    #[test]
1798    fn test_1_power_n() {
1799        assert_eq!(FPDecimal::ONE, FPDecimal::ONE.pow(FPDecimal::ONE).unwrap());
1800        assert_eq!(FPDecimal::ONE, FPDecimal::ONE.pow(FPDecimal::TWO).unwrap());
1801        assert_eq!(FPDecimal::ONE, FPDecimal::ONE.pow(FPDecimal::THREE).unwrap());
1802        assert_eq!(FPDecimal::ONE, FPDecimal::ONE.pow(FPDecimal::FOUR).unwrap());
1803    }
1804
1805    // NOTE: its ok we ignore these two unit tests. they should not be the goal of this crate
1806    // TODO: add a lookup table for this in future
1807    /*
1808    #[test]
1809    fn test_ln_e_pow_1_5() {
1810        let base = FPDecimal::E * FPDecimal::E.sqrt();
1811        assert_eq!(base.ln(), FPDecimal::must_from_str("1.5"));
1812    }
1813
1814    #[test]
1815    fn test_ln_e_pow_minus_1_5() {
1816        let base = FPDecimal::ONE / (FPDecimal::E.sqrt() * FPDecimal::E);
1817        assert_eq!(base.ln(), FPDecimal::must_from_str("-1.5"));
1818    }
1819    #[test]
1820    fn test_log_1_5_2_2_5() {
1821        let base = FPDecimal::must_from_str("1.5");
1822        let exp = FPDecimal::must_from_str("2.25");
1823        assert_eq!(exp.log(base), FPDecimal::TWO);
1824    }
1825
1826    #[test]
1827    fn test_25_pow_0_11111() {
1828        let power = FPDecimal::ONE / FPDecimal::from(9_u128);
1829        let result: FPDecimal = FPDecimal::must_from_str("25.0").ln() * power;
1830        let dampen: FPDecimal = FPDecimal::E.pow(result);
1831        //                                           1.4299640339921836144
1832        assert_eq!(dampen, FPDecimal::must_from_str("1.429969148308728731"));
1833    }
1834    #[test]
1835    fn test_25_pow_0_11111_decimal_lib() {
1836        let x = FPDecimal::ONE / FPDecimal::from(9_u128);
1837        let a: FPDecimal = FPDecimal::must_from_str("25.0");
1838        let result: FPDecimal = a.pow(x);
1839        assert_eq!(result, FPDecimal::must_from_str("1.429969148308728731"));
1840    }
1841    */
1842}