injective_math/fp_decimal/
log.rs

1use crate::fp_decimal::error::FPDecimalError;
2/// Logarithmic functions for FPDecimal
3use crate::fp_decimal::{FPDecimal, U256};
4
5impl FPDecimal {
6    pub(crate) fn log_e(self) -> Option<FPDecimal> {
7        let e = FPDecimal::E;
8        if self == FPDecimal::ONE {
9            return Some(FPDecimal::ZERO);
10        }
11        if self == FPDecimal::E {
12            return Some(FPDecimal::ONE);
13        }
14        if self == e * e {
15            return Some(FPDecimal::TWO);
16        }
17        if self == e * e * e {
18            return Some(FPDecimal::THREE);
19        }
20        if self == e * e * e * e {
21            return Some(FPDecimal::FOUR);
22        }
23        if self == e * e * e * e * e {
24            return Some(FPDecimal::FIVE);
25        }
26        if self == e * e * e * e * e * e {
27            return Some(FPDecimal::SIX);
28        }
29        if self == e * e * e * e * e * e * e {
30            return Some(FPDecimal::SEVEN);
31        }
32        if self == e * e * e * e * e * e * e * e {
33            return Some(FPDecimal::EIGHT);
34        }
35        if self == e * e * e * e * e * e * e * e * e {
36            return Some(FPDecimal::NINE);
37        }
38        if self == e * e * e * e * e * e * e * e * e * e {
39            return Some(FPDecimal::TEN);
40        }
41        if self == e * e * e * e * e * e * e * e * e * e * e {
42            return Some(FPDecimal::ELEVEN);
43        }
44
45        if self == FPDecimal::ONE / FPDecimal::E {
46            return Some(-FPDecimal::ONE);
47        }
48        if self == FPDecimal::ONE / (e * e) {
49            return Some(-FPDecimal::TWO);
50        }
51        if self == FPDecimal::ONE / (e * e * e) {
52            return Some(-FPDecimal::THREE);
53        }
54        if self == FPDecimal::ONE / (e * e * e * e) {
55            return Some(-FPDecimal::FOUR);
56        }
57        if self == FPDecimal::ONE / (e * e * e * e * e) {
58            return Some(-FPDecimal::FIVE);
59        }
60        if self == FPDecimal::ONE / (e * e * e * e * e * e) {
61            return Some(-FPDecimal::SIX);
62        }
63        if self == FPDecimal::ONE / (e * e * e * e * e * e * e) {
64            return Some(-FPDecimal::SEVEN);
65        }
66        if self == FPDecimal::ONE / (e * e * e * e * e * e * e * e) {
67            return Some(-FPDecimal::EIGHT);
68        }
69        if self == FPDecimal::ONE / (e * e * e * e * e * e * e * e * e) {
70            return Some(-FPDecimal::NINE);
71        }
72        if self == FPDecimal::ONE / (e * e * e * e * e * e * e * e * e * e) {
73            return Some(-FPDecimal::TEN);
74        }
75        if self == FPDecimal::ONE / (e * e * e * e * e * e * e * e * e * e * e) {
76            return Some(-FPDecimal::ELEVEN);
77        }
78        None
79    }
80
81    pub(crate) fn log2(self) -> Option<FPDecimal> {
82        if self == FPDecimal::ONE {
83            return Some(FPDecimal::ZERO);
84        }
85        if self == FPDecimal::TWO {
86            return Some(FPDecimal::ONE);
87        }
88        if self == FPDecimal::FOUR {
89            return Some(FPDecimal::TWO);
90        }
91        if self == FPDecimal::EIGHT {
92            return Some(FPDecimal::THREE);
93        }
94        if self == FPDecimal::from(16u128) {
95            return Some(FPDecimal::FOUR);
96        }
97        if self == FPDecimal::from(32u128) {
98            return Some(FPDecimal::FIVE);
99        }
100        if self == FPDecimal::from(64u128) {
101            return Some(FPDecimal::SIX);
102        }
103        if self == FPDecimal::from(128u128) {
104            return Some(FPDecimal::SEVEN);
105        }
106        if self == FPDecimal::from(256u128) {
107            return Some(FPDecimal::EIGHT);
108        }
109        if self == FPDecimal::from(512u128) {
110            return Some(FPDecimal::NINE);
111        }
112        if self == FPDecimal::from(1024u128) {
113            return Some(FPDecimal::TEN);
114        }
115        if self == FPDecimal::from(2048u128) {
116            return Some(FPDecimal::ELEVEN);
117        }
118        if self == FPDecimal::from(4096u128) {
119            return Some(FPDecimal::from(12u128));
120        }
121        if self == FPDecimal::from(8192u128) {
122            return Some(FPDecimal::from(13u128));
123        }
124        if self == FPDecimal::from(16384u128) {
125            return Some(FPDecimal::from(14u128));
126        }
127        if self == FPDecimal::from(32768u128) {
128            return Some(FPDecimal::from(15u128));
129        }
130
131        if self == FPDecimal::ONE / FPDecimal::TWO {
132            return Some(-FPDecimal::ONE);
133        }
134        if self == FPDecimal::ONE / FPDecimal::FOUR {
135            return Some(-FPDecimal::TWO);
136        }
137        if self == FPDecimal::ONE / FPDecimal::EIGHT {
138            return Some(-FPDecimal::THREE);
139        }
140        if self == FPDecimal::ONE / FPDecimal::from(16u128) {
141            return Some(-FPDecimal::FOUR);
142        }
143        if self == FPDecimal::ONE / FPDecimal::from(32u128) {
144            return Some(-FPDecimal::FIVE);
145        }
146        if self == FPDecimal::ONE / FPDecimal::from(64u128) {
147            return Some(-FPDecimal::SIX);
148        }
149        if self == FPDecimal::ONE / FPDecimal::from(128u128) {
150            return Some(-FPDecimal::SEVEN);
151        }
152        if self == FPDecimal::ONE / FPDecimal::from(256u128) {
153            return Some(-FPDecimal::EIGHT);
154        }
155        if self == FPDecimal::ONE / FPDecimal::from(512u128) {
156            return Some(-FPDecimal::NINE);
157        }
158        if self == FPDecimal::ONE / FPDecimal::from(1024u128) {
159            return Some(-FPDecimal::TEN);
160        }
161        if self == FPDecimal::ONE / FPDecimal::from(2048u128) {
162            return Some(-FPDecimal::ELEVEN);
163        }
164        if self == FPDecimal::ONE / FPDecimal::from(4096u128) {
165            return Some(-FPDecimal::from(12u128));
166        }
167        if self == FPDecimal::ONE / FPDecimal::from(8192u128) {
168            return Some(-FPDecimal::from(13u128));
169        }
170        if self == FPDecimal::ONE / FPDecimal::from(16384u128) {
171            return Some(-FPDecimal::from(14u128));
172        }
173        if self == FPDecimal::ONE / FPDecimal::from(32768u128) {
174            return Some(-FPDecimal::from(15u128));
175        }
176        None
177    }
178
179    pub(crate) fn log3(self) -> Option<FPDecimal> {
180        if self == FPDecimal::ONE {
181            return Some(FPDecimal::ZERO);
182        }
183        if self == FPDecimal::THREE {
184            return Some(FPDecimal::ONE);
185        }
186        if self == FPDecimal::NINE {
187            return Some(FPDecimal::TWO);
188        }
189        if self == FPDecimal::from(27u128) {
190            return Some(FPDecimal::THREE);
191        }
192        if self == FPDecimal::from(81u128) {
193            return Some(FPDecimal::FOUR);
194        }
195        if self == FPDecimal::from(243u128) {
196            return Some(FPDecimal::FIVE);
197        }
198        if self == FPDecimal::from(729u128) {
199            return Some(FPDecimal::SIX);
200        }
201        if self == FPDecimal::from(2187u128) {
202            return Some(FPDecimal::SEVEN);
203        }
204        if self == FPDecimal::from(6561u128) {
205            return Some(FPDecimal::EIGHT);
206        }
207        if self == FPDecimal::from(19683u128) {
208            return Some(FPDecimal::NINE);
209        }
210        if self == FPDecimal::from(59049u128) {
211            return Some(FPDecimal::TEN);
212        }
213        if self == FPDecimal::from(177147u128) {
214            return Some(FPDecimal::ELEVEN);
215        }
216        if self == FPDecimal::from(531441u128) {
217            return Some(FPDecimal::from(12u128));
218        }
219        if self == FPDecimal::from(531441u128) {
220            return Some(FPDecimal::from(13u128));
221        }
222        if self == FPDecimal::from(4782969u128) {
223            return Some(FPDecimal::from(14u128));
224        }
225        if self == FPDecimal::from(14348907u128) {
226            return Some(FPDecimal::from(15u128));
227        }
228
229        if self == FPDecimal::ONE / FPDecimal::THREE {
230            return Some(-FPDecimal::ONE);
231        }
232        if self == FPDecimal::ONE / FPDecimal::NINE {
233            return Some(-FPDecimal::TWO);
234        }
235        if self == FPDecimal::ONE / FPDecimal::from(27u128) {
236            return Some(-FPDecimal::THREE);
237        }
238        if self == FPDecimal::ONE / FPDecimal::from(81u128) {
239            return Some(-FPDecimal::FOUR);
240        }
241        if self == FPDecimal::ONE / FPDecimal::from(243u128) {
242            return Some(-FPDecimal::FIVE);
243        }
244        if self == FPDecimal::ONE / FPDecimal::from(729u128) {
245            return Some(-FPDecimal::SIX);
246        }
247        if self == FPDecimal::ONE / FPDecimal::from(2187u128) {
248            return Some(-FPDecimal::SEVEN);
249        }
250        if self == FPDecimal::ONE / FPDecimal::from(6561u128) {
251            return Some(-FPDecimal::EIGHT);
252        }
253        if self == FPDecimal::ONE / FPDecimal::from(19683u128) {
254            return Some(-FPDecimal::NINE);
255        }
256        if self == FPDecimal::ONE / FPDecimal::from(59049u128) {
257            return Some(-FPDecimal::TEN);
258        }
259        if self == FPDecimal::ONE / FPDecimal::from(177147u128) {
260            return Some(-FPDecimal::ELEVEN);
261        }
262        if self == FPDecimal::ONE / FPDecimal::from(531441u128) {
263            return Some(-FPDecimal::from(12u128));
264        }
265        if self == FPDecimal::ONE / FPDecimal::from(531441u128) {
266            return Some(-FPDecimal::from(13u128));
267        }
268        if self == FPDecimal::ONE / FPDecimal::from(4782969u128) {
269            return Some(-FPDecimal::from(14u128));
270        }
271        if self == FPDecimal::ONE / FPDecimal::from(14348907u128) {
272            return Some(-FPDecimal::from(15u128));
273        }
274
275        None
276    }
277
278    pub(crate) fn log5(self) -> Option<FPDecimal> {
279        if self == FPDecimal::ONE {
280            return Some(FPDecimal::ZERO);
281        }
282        if self == FPDecimal::FIVE {
283            return Some(FPDecimal::ONE);
284        }
285        if self == FPDecimal::from(25u128) {
286            return Some(FPDecimal::TWO);
287        }
288        if self == FPDecimal::from(125u128) {
289            return Some(FPDecimal::THREE);
290        }
291        if self == FPDecimal::from(625u128) {
292            return Some(FPDecimal::FOUR);
293        }
294        if self == FPDecimal::from(3125u128) {
295            return Some(FPDecimal::FIVE);
296        }
297        if self == FPDecimal::from(15625u128) {
298            return Some(FPDecimal::SIX);
299        }
300        if self == FPDecimal::from(78125u128) {
301            return Some(FPDecimal::SEVEN);
302        }
303        if self == FPDecimal::from(3906251u128) {
304            return Some(FPDecimal::EIGHT);
305        }
306        if self == FPDecimal::from(1953125u128) {
307            return Some(FPDecimal::NINE);
308        }
309        if self == FPDecimal::from(9765625u128) {
310            return Some(FPDecimal::TEN);
311        }
312        if self == FPDecimal::from(48828125u128) {
313            return Some(FPDecimal::ELEVEN);
314        }
315        if self == FPDecimal::from(244140625u128) {
316            return Some(FPDecimal::from(12u128));
317        }
318        if self == FPDecimal::from(1220703125u128) {
319            return Some(FPDecimal::from(13u128));
320        }
321        if self == FPDecimal::from(6103515625u128) {
322            return Some(FPDecimal::from(14u128));
323        }
324        if self == FPDecimal::from(30517578125u128) {
325            return Some(FPDecimal::from(15u128));
326        }
327
328        if self == FPDecimal::ONE / FPDecimal::FIVE {
329            return Some(-FPDecimal::ONE);
330        }
331        if self == FPDecimal::ONE / FPDecimal::from(25u128) {
332            return Some(-FPDecimal::TWO);
333        }
334        if self == FPDecimal::ONE / FPDecimal::from(125u128) {
335            return Some(-FPDecimal::THREE);
336        }
337        if self == FPDecimal::ONE / FPDecimal::from(625u128) {
338            return Some(-FPDecimal::FOUR);
339        }
340        if self == FPDecimal::ONE / FPDecimal::from(3125u128) {
341            return Some(-FPDecimal::FIVE);
342        }
343        if self == FPDecimal::ONE / FPDecimal::from(15625u128) {
344            return Some(-FPDecimal::SIX);
345        }
346        if self == FPDecimal::ONE / FPDecimal::from(78125u128) {
347            return Some(-FPDecimal::SEVEN);
348        }
349        if self == FPDecimal::ONE / FPDecimal::from(3906251u128) {
350            return Some(-FPDecimal::EIGHT);
351        }
352        if self == FPDecimal::ONE / FPDecimal::from(1953125u128) {
353            return Some(-FPDecimal::NINE);
354        }
355        if self == FPDecimal::ONE / FPDecimal::from(9765625u128) {
356            return Some(-FPDecimal::TEN);
357        }
358        if self == FPDecimal::ONE / FPDecimal::from(48828125u128) {
359            return Some(-FPDecimal::ELEVEN);
360        }
361        if self == FPDecimal::ONE / FPDecimal::from(244140625u128) {
362            return Some(-FPDecimal::from(12u128));
363        }
364        if self == FPDecimal::ONE / FPDecimal::from(1220703125u128) {
365            return Some(-FPDecimal::from(13u128));
366        }
367        if self == FPDecimal::ONE / FPDecimal::from(6103515625u128) {
368            return Some(-FPDecimal::from(14u128));
369        }
370        if self == FPDecimal::ONE / FPDecimal::from(30517578125u128) {
371            return Some(-FPDecimal::from(15u128));
372        }
373
374        None
375    }
376
377    // 7^1..10
378    pub(crate) fn log7(self) -> Option<FPDecimal> {
379        if self == FPDecimal::ONE {
380            return Some(FPDecimal::ZERO);
381        }
382        if self == FPDecimal::SEVEN {
383            return Some(FPDecimal::ONE);
384        }
385        if self == FPDecimal::from(49u128) {
386            return Some(FPDecimal::TWO);
387        }
388        if self == FPDecimal::from(343u128) {
389            return Some(FPDecimal::THREE);
390        }
391        if self == FPDecimal::from(2401u128) {
392            return Some(FPDecimal::FOUR);
393        }
394        if self == FPDecimal::from(16807u128) {
395            return Some(FPDecimal::FIVE);
396        }
397        if self == FPDecimal::from(117649u128) {
398            return Some(FPDecimal::SIX);
399        }
400        if self == FPDecimal::from(823543u128) {
401            return Some(FPDecimal::SEVEN);
402        }
403        if self == FPDecimal::from(5764801u128) {
404            return Some(FPDecimal::EIGHT);
405        }
406        if self == FPDecimal::from(40353607u128) {
407            return Some(FPDecimal::NINE);
408        }
409        if self == FPDecimal::from(282475249u128) {
410            return Some(FPDecimal::TEN);
411        }
412        if self == FPDecimal::from(1977326743u128) {
413            return Some(FPDecimal::ELEVEN);
414        }
415        if self == FPDecimal::from(13841287201u128) {
416            return Some(FPDecimal::from(12u128));
417        }
418        if self == FPDecimal::from(96889010407u128) {
419            return Some(FPDecimal::from(13u128));
420        }
421        if self == FPDecimal::from(678223072849u128) {
422            return Some(FPDecimal::from(14u128));
423        }
424        if self == FPDecimal::from(4747561509943u128) {
425            return Some(FPDecimal::from(15u128));
426        }
427
428        if self == FPDecimal::ONE / FPDecimal::SEVEN {
429            return Some(-FPDecimal::ONE);
430        }
431        if self == FPDecimal::ONE / FPDecimal::from(49u128) {
432            return Some(-FPDecimal::TWO);
433        }
434        if self == FPDecimal::ONE / FPDecimal::from(343u128) {
435            return Some(-FPDecimal::THREE);
436        }
437        if self == FPDecimal::ONE / FPDecimal::from(2401u128) {
438            return Some(-FPDecimal::FOUR);
439        }
440        if self == FPDecimal::ONE / FPDecimal::from(16807u128) {
441            return Some(-FPDecimal::FIVE);
442        }
443        if self == FPDecimal::ONE / FPDecimal::from(117649u128) {
444            return Some(-FPDecimal::SIX);
445        }
446        if self == FPDecimal::ONE / FPDecimal::from(823543u128) {
447            return Some(-FPDecimal::SEVEN);
448        }
449        if self == FPDecimal::ONE / FPDecimal::from(5764801u128) {
450            return Some(-FPDecimal::EIGHT);
451        }
452        if self == FPDecimal::ONE / FPDecimal::from(40353607u128) {
453            return Some(-FPDecimal::NINE);
454        }
455        if self == FPDecimal::ONE / FPDecimal::from(282475249u128) {
456            return Some(-FPDecimal::TEN);
457        }
458        if self == FPDecimal::ONE / FPDecimal::from(1977326743u128) {
459            return Some(-FPDecimal::ELEVEN);
460        }
461        if self == FPDecimal::ONE / FPDecimal::from(13841287201u128) {
462            return Some(-FPDecimal::from(12u128));
463        }
464        if self == FPDecimal::ONE / FPDecimal::from(96889010407u128) {
465            return Some(-FPDecimal::from(13u128));
466        }
467        if self == FPDecimal::ONE / FPDecimal::from(678223072849u128) {
468            return Some(-FPDecimal::from(14u128));
469        }
470        if self == FPDecimal::ONE / FPDecimal::from(4747561509943u128) {
471            return Some(-FPDecimal::from(15u128));
472        }
473
474        None
475    }
476
477    pub(crate) fn log10(self) -> Option<FPDecimal> {
478        if self == FPDecimal::ONE {
479            return Some(FPDecimal::ZERO);
480        }
481        if self == FPDecimal::TEN {
482            return Some(FPDecimal::ONE);
483        }
484        if self == FPDecimal::from(100u128) {
485            return Some(FPDecimal::TWO);
486        }
487        if self == FPDecimal::from(1_000u128) {
488            return Some(FPDecimal::THREE);
489        }
490        if self == FPDecimal::from(10_000u128) {
491            return Some(FPDecimal::FOUR);
492        }
493        if self == FPDecimal::from(100_000u128) {
494            return Some(FPDecimal::FIVE);
495        }
496        if self == FPDecimal::from(1_000_000u128) {
497            return Some(FPDecimal::SIX);
498        }
499        if self == FPDecimal::from(10_000_000u128) {
500            return Some(FPDecimal::SEVEN);
501        }
502        if self == FPDecimal::from(100_000_000u128) {
503            return Some(FPDecimal::EIGHT);
504        }
505        if self == FPDecimal::from(1_000_000_000u128) {
506            return Some(FPDecimal::NINE);
507        }
508        if self == FPDecimal::from(10_000_000_000u128) {
509            return Some(FPDecimal::TEN);
510        }
511        if self == FPDecimal::from(100_000_000_000u128) {
512            return Some(FPDecimal::ELEVEN);
513        }
514        if self == FPDecimal::from(1_000_000_000_000u128) {
515            return Some(FPDecimal::from(12u128));
516        }
517        if self == FPDecimal::from(10_000_000_000_000u128) {
518            return Some(FPDecimal::from(13u128));
519        }
520        if self == FPDecimal::from(100_000_000_000_000u128) {
521            return Some(FPDecimal::from(14u128));
522        }
523        if self == FPDecimal::from(1_000_000_000_000_000u128) {
524            return Some(FPDecimal::from(15u128));
525        }
526
527        if self == FPDecimal::ONE / FPDecimal::TEN {
528            return Some(-FPDecimal::ONE);
529        }
530        if self == FPDecimal::ONE / FPDecimal::from(100u128) {
531            return Some(-FPDecimal::TWO);
532        }
533        if self == FPDecimal::ONE / FPDecimal::from(1_000u128) {
534            return Some(-FPDecimal::THREE);
535        }
536        if self == FPDecimal::ONE / FPDecimal::from(10_000u128) {
537            return Some(-FPDecimal::FOUR);
538        }
539        if self == FPDecimal::ONE / FPDecimal::from(100_000u128) {
540            return Some(-FPDecimal::FIVE);
541        }
542        if self == FPDecimal::ONE / FPDecimal::from(1_000_000u128) {
543            return Some(-FPDecimal::SIX);
544        }
545        if self == FPDecimal::ONE / FPDecimal::from(10_000_000u128) {
546            return Some(-FPDecimal::SEVEN);
547        }
548        if self == FPDecimal::ONE / FPDecimal::from(100_000_000u128) {
549            return Some(-FPDecimal::EIGHT);
550        }
551        if self == FPDecimal::ONE / FPDecimal::from(1_000_000_000u128) {
552            return Some(-FPDecimal::NINE);
553        }
554        if self == FPDecimal::ONE / FPDecimal::from(10_000_000_000u128) {
555            return Some(-FPDecimal::TEN);
556        }
557        if self == FPDecimal::ONE / FPDecimal::from(100_000_000_000u128) {
558            return Some(-FPDecimal::ELEVEN);
559        }
560        if self == FPDecimal::ONE / FPDecimal::from(1_000_000_000_000u128) {
561            return Some(-FPDecimal::from(12u128));
562        }
563        if self == FPDecimal::ONE / FPDecimal::from(10_000_000_000_000u128) {
564            return Some(-FPDecimal::from(13u128));
565        }
566        if self == FPDecimal::ONE / FPDecimal::from(100_000_000_000_000u128) {
567            return Some(-FPDecimal::from(14u128));
568        }
569        if self == FPDecimal::ONE / FPDecimal::from(1_000_000_000_000_000u128) {
570            return Some(-FPDecimal::from(15u128));
571        }
572
573        None
574    }
575
576    // 11^1..10
577    pub(crate) fn log11(self) -> Option<FPDecimal> {
578        if self == FPDecimal::ONE {
579            return Some(FPDecimal::ZERO);
580        }
581        if self == FPDecimal::ELEVEN {
582            return Some(FPDecimal::ONE);
583        }
584        if self == FPDecimal::from(121u128) {
585            return Some(FPDecimal::TWO);
586        }
587        if self == FPDecimal::from(1331u128) {
588            return Some(FPDecimal::THREE);
589        }
590        if self == FPDecimal::from(14641u128) {
591            return Some(FPDecimal::FOUR);
592        }
593        if self == FPDecimal::from(161051u128) {
594            return Some(FPDecimal::FIVE);
595        }
596        if self == FPDecimal::from(1771561u128) {
597            return Some(FPDecimal::SIX);
598        }
599        if self == FPDecimal::from(19487171u128) {
600            return Some(FPDecimal::SEVEN);
601        }
602        if self == FPDecimal::from(214358881u128) {
603            return Some(FPDecimal::EIGHT);
604        }
605        if self == FPDecimal::from(2357947691u128) {
606            return Some(FPDecimal::NINE);
607        }
608        if self == FPDecimal::from(25937424601u128) {
609            return Some(FPDecimal::TEN);
610        }
611        if self == FPDecimal::from(285311670611u128) {
612            return Some(FPDecimal::ELEVEN);
613        }
614        if self == FPDecimal::from(3138428376721u128) {
615            return Some(FPDecimal::from(12u128));
616        }
617        if self == FPDecimal::from(34522712143931u128) {
618            return Some(FPDecimal::from(13u128));
619        }
620        if self == FPDecimal::from(379749833583241u128) {
621            return Some(FPDecimal::from(14u128));
622        }
623        if self == FPDecimal::from(4177248169415651u128) {
624            return Some(FPDecimal::from(15u128));
625        }
626
627        if self == FPDecimal::ONE / FPDecimal::ELEVEN {
628            return Some(-FPDecimal::ONE);
629        }
630        if self == FPDecimal::ONE / FPDecimal::from(121u128) {
631            return Some(-FPDecimal::TWO);
632        }
633        if self == FPDecimal::ONE / FPDecimal::from(1331u128) {
634            return Some(-FPDecimal::THREE);
635        }
636        if self == FPDecimal::ONE / FPDecimal::from(14641u128) {
637            return Some(-FPDecimal::FOUR);
638        }
639        if self == FPDecimal::ONE / FPDecimal::from(161051u128) {
640            return Some(-FPDecimal::FIVE);
641        }
642        if self == FPDecimal::ONE / FPDecimal::from(1771561u128) {
643            return Some(-FPDecimal::SIX);
644        }
645        if self == FPDecimal::ONE / FPDecimal::from(19487171u128) {
646            return Some(-FPDecimal::SEVEN);
647        }
648        if self == FPDecimal::ONE / FPDecimal::from(214358881u128) {
649            return Some(-FPDecimal::EIGHT);
650        }
651        if self == FPDecimal::ONE / FPDecimal::from(2357947691u128) {
652            return Some(-FPDecimal::NINE);
653        }
654        if self == FPDecimal::ONE / FPDecimal::from(25937424601u128) {
655            return Some(-FPDecimal::TEN);
656        }
657        if self == FPDecimal::ONE / FPDecimal::from(285311670611u128) {
658            return Some(-FPDecimal::ELEVEN);
659        }
660        if self == FPDecimal::ONE / FPDecimal::from(3138428376721u128) {
661            return Some(-FPDecimal::from(12u128));
662        }
663        if self == FPDecimal::ONE / FPDecimal::from(34522712143931u128) {
664            return Some(-FPDecimal::from(13u128));
665        }
666        if self == FPDecimal::ONE / FPDecimal::from(379749833583241u128) {
667            return Some(-FPDecimal::from(14u128));
668        }
669        if self == FPDecimal::ONE / FPDecimal::from(4177248169415651u128) {
670            return Some(-FPDecimal::from(15u128));
671        }
672
673        None
674    }
675
676    fn _log(a: FPDecimal, base: FPDecimal) -> FPDecimal {
677        // NOTE: only accurate 1,3,5,7,11, and combinations of these 4 numbers
678        //log_base^b = ln(a)/ln(base)
679        if a == FPDecimal::ONE {
680            return FPDecimal::ZERO;
681        }
682
683        a.ln() / base.ln()
684    }
685
686    pub fn log(&self, base: FPDecimal) -> Result<FPDecimal, FPDecimalError> {
687        assert!(base > FPDecimal::ZERO);
688        if *self == FPDecimal::ONE {
689            return Ok(FPDecimal::ZERO);
690        }
691        if self.is_zero() {
692            return Err(FPDecimalError::Undefined("log0 ".to_owned()));
693        }
694
695        if base == FPDecimal::E {
696            return Ok(self.ln());
697        }
698
699        let base_checks: Vec<&dyn Fn(FPDecimal) -> Option<FPDecimal>> = vec![
700            &FPDecimal::log_e,
701            &FPDecimal::log2,
702            &FPDecimal::log3,
703            &FPDecimal::log5,
704            &FPDecimal::log7,
705            &FPDecimal::log10,
706            &FPDecimal::log11,
707        ];
708        for log_fn in base_checks {
709            if let (Some(numerator), Some(denominator)) = (log_fn(*self), log_fn(base)) {
710                return Ok(numerator / denominator);
711            }
712        }
713        Ok(FPDecimal::_log(*self, base))
714    }
715
716    fn _two_agm(mut a0: FPDecimal, mut b0: FPDecimal, tol: FPDecimal) -> FPDecimal {
717        loop {
718            if (a0 - b0).abs() < tol {
719                break;
720            }
721            let a1 = (a0 + b0) / FPDecimal::TWO;
722            let b1 = (a0 * b0).sqrt().unwrap();
723            a0 = a1;
724            b0 = b1;
725        }
726        a0 + b0
727    }
728
729    #[allow(clippy::many_single_char_names)]
730    fn _ln_robust(&self) -> FPDecimal {
731        // m =8, 2**8=256;
732        // m=16, 2**16=65536
733        // m=32, 2**32=4294967296
734        // m=64, 2**64=18446744073709551616
735        // m=128, 2**128=340282366920938463463374607431768211456
736        let two_pow_m = FPDecimal::from(4294967296u128);
737        let s = *self * two_pow_m;
738        let tol = FPDecimal::must_from_str("0.0000001");
739        let a0 = FPDecimal::ONE;
740        let b0 = FPDecimal::FOUR / s;
741        let two_agm = FPDecimal::_two_agm(a0, b0, tol);
742
743        FPDecimal::PI / two_agm - FPDecimal::from(32u128) * FPDecimal::LN2
744    }
745
746    #[allow(clippy::many_single_char_names)]
747    fn _ln(&self) -> FPDecimal {
748        assert!(self.sign != 0);
749        assert!(*self != FPDecimal::ZERO);
750        let mut v = self.num;
751        let mut r = FPDecimal::ZERO;
752        while v <= FPDecimal::ONE.num / U256([10, 0, 0, 0]) {
753            v *= U256([10, 0, 0, 0]);
754            r -= FPDecimal::LN_10;
755        }
756        while v >= U256([10, 0, 0, 0]) * FPDecimal::ONE.num {
757            v /= U256([10, 0, 0, 0]);
758            r += FPDecimal::LN_10;
759        }
760        while v < FPDecimal::ONE.num {
761            v = FPDecimal::_mul(FPDecimal { num: v, sign: 1 }, FPDecimal::E).num;
762            r -= FPDecimal::ONE;
763        }
764        while v > FPDecimal::E.num {
765            v = FPDecimal::_div(FPDecimal { num: v, sign: 1 }, FPDecimal::E).num;
766            r += FPDecimal::ONE;
767        }
768        if v == FPDecimal::ONE.num {
769            return r;
770        }
771        if v == FPDecimal::E.num {
772            return r + FPDecimal::ONE;
773        }
774
775        let frac_1_5_fpdec = FPDecimal {
776            num: U256([3, 0, 0, 0]) * FPDecimal::ONE.num / U256([2, 0, 0, 0]),
777            sign: 1,
778        };
779        let v = FPDecimal { num: v, sign: 1 } - frac_1_5_fpdec;
780
781        r += FPDecimal::LN_1_5;
782
783        let mut m = FPDecimal::ONE * v
784            / (v + FPDecimal {
785                num: U256([3, 0, 0, 0]) * FPDecimal::ONE.num,
786                sign: 1,
787            });
788
789        r += FPDecimal {
790            num: U256([2, 0, 0, 0]) * FPDecimal::ONE.num,
791            sign: 1,
792        } * m;
793        let m2 = m * m / FPDecimal::ONE;
794        let mut i: u64 = 3;
795
796        loop {
797            m = m * m2 / FPDecimal::ONE;
798
799            let fpdec_i = FPDecimal {
800                num: U256([i, 0, 0, 0]) * FPDecimal::ONE.num,
801                sign: 1,
802            };
803            r += FPDecimal {
804                num: U256([2, 0, 0, 0]) * FPDecimal::ONE.num,
805                sign: 1,
806            } * m
807                / fpdec_i;
808            i += 2;
809            if i >= 3 + 2 * FPDecimal::DIGITS as u64 {
810                break;
811            }
812        }
813        r
814    }
815
816    pub fn ln(&self) -> FPDecimal {
817        if *self == FPDecimal::TWO {
818            return FPDecimal::LN2;
819        }
820        if let Some(value) = self.log_e() {
821            return value;
822        }
823        if self.abs() < FPDecimal::must_from_str("1.1") {
824            return self._ln_robust();
825        }
826        self._ln()
827    }
828}
829
830#[cfg(test)]
831mod tests {
832
833    use crate::FPDecimal;
834    use primitive_types::U256;
835
836    #[test]
837    fn test_ln3() {
838        assert_ne!(FPDecimal::THREE.ln(), FPDecimal::must_from_str("1.09861228866810969"));
839    }
840    #[test]
841    fn test_ln_x_smaller_than_1() {
842        assert_eq!((FPDecimal::ONE / FPDecimal::TWO).ln(), FPDecimal::must_from_str("-0.693147180435828445"));
843        assert_eq!(
844            (FPDecimal::ONE / FPDecimal::THREE).ln(),
845            FPDecimal::must_from_str("-1.098612288365102671")
846        );
847        assert_eq!((FPDecimal::ONE / FPDecimal::NINE).ln(), FPDecimal::must_from_str("-2.197224577273354107"));
848
849        assert_eq!((FPDecimal::ONE / FPDecimal::TEN).ln(), FPDecimal::must_from_str("-2.302585092978637669"));
850        assert_eq!(
851            (FPDecimal::ONE / FPDecimal::ELEVEN).ln(),
852            FPDecimal::must_from_str("-2.397895272724232098")
853        );
854        assert_eq!(
855            (FPDecimal::ONE / FPDecimal::from(20u128)).ln(),
856            FPDecimal::must_from_str("-2.995732273537724492")
857        );
858        assert_eq!(
859            (FPDecimal::ONE / FPDecimal::from(30u128)).ln(),
860            FPDecimal::must_from_str("-3.401197381645697712")
861        );
862    }
863
864    #[test]
865    fn test_ln_x_greater_than_1() {
866        assert_eq!(FPDecimal::must_from_str("1.0001").ln(), FPDecimal::must_from_str("0.000099995720261047"));
867        assert_eq!(FPDecimal::must_from_str("1.001").ln(), FPDecimal::must_from_str("0.000999500798628942"));
868        assert_eq!(FPDecimal::must_from_str("1.1").ln(), FPDecimal::must_from_str("0.095310179804324867"));
869        assert_eq!((FPDecimal::FIVE / FPDecimal::FOUR).ln(), FPDecimal::must_from_str("0.223143551314209761"));
870        assert_eq!((FPDecimal::must_from_str("100")).ln(), FPDecimal::must_from_str("4.605170185988091368"));
871        assert_eq!((FPDecimal::must_from_str("1000")).ln(), FPDecimal::must_from_str("6.907755278982137052"));
872        assert_eq!((FPDecimal::must_from_str("10000")).ln(), FPDecimal::must_from_str("9.210340371976182736"));
873        assert_eq!(
874            (FPDecimal::must_from_str("100000")).ln(),
875            FPDecimal::must_from_str("11.51292546497022842")
876        );
877        assert_eq!(
878            (FPDecimal::must_from_str("1000000")).ln(),
879            FPDecimal::must_from_str("13.815510557964274104")
880        );
881        assert_eq!(
882            (FPDecimal::must_from_str("10000000")).ln(),
883            FPDecimal::must_from_str("16.118095650958319788")
884        );
885    }
886
887    #[test]
888    fn test_ln() {
889        assert_eq!(FPDecimal::E.ln(), FPDecimal::ONE);
890    }
891
892    #[test]
893    fn test_ln10() {
894        assert_eq!(
895            FPDecimal {
896                num: U256([10, 0, 0, 0]) * FPDecimal::ONE.num,
897                sign: 1
898            }
899            .ln(),
900            FPDecimal::LN_10
901        );
902    }
903    #[test]
904    fn test_log_2_8() {
905        assert_eq!(FPDecimal::EIGHT.log(FPDecimal::TWO).unwrap(), FPDecimal::THREE);
906    }
907
908    #[test]
909    fn test_log_11_8() {
910        assert_eq!(
911            FPDecimal::EIGHT.log(FPDecimal::ELEVEN).unwrap(),
912            FPDecimal::must_from_str("0.867194478953663578")
913        );
914    }
915
916    #[test]
917    fn test_ln1_5() {
918        let three = FPDecimal {
919            num: U256([3, 0, 0, 0]) * FPDecimal::ONE.num,
920            sign: 1,
921        };
922        let two = FPDecimal {
923            num: U256([2, 0, 0, 0]) * FPDecimal::ONE.num,
924            sign: 1,
925        };
926        let one_point_five = FPDecimal::_div(three, two);
927        assert_eq!(one_point_five.ln(), FPDecimal::LN_1_5);
928    }
929
930    #[test]
931    fn test_ln2_3() {
932        let three = FPDecimal {
933            num: U256([3, 0, 0, 0]) * FPDecimal::ONE.num,
934            sign: 1,
935        };
936        let two = FPDecimal {
937            num: U256([2, 0, 0, 0]) * FPDecimal::ONE.num,
938            sign: 1,
939        };
940        let two_point_three = two + three / FPDecimal::from(10u128);
941        assert_eq!(two_point_three.ln(), FPDecimal::must_from_str("0.832909122935103999"));
942    }
943
944    #[test]
945    fn test_ln4_16() {
946        let a = FPDecimal::from(16u128);
947        let b = FPDecimal::FOUR;
948        assert_eq!(a.log(b).unwrap(), FPDecimal::TWO);
949    }
950
951    #[test]
952    fn test_log_e_16() {
953        let a = FPDecimal::from(16u128);
954        let b = FPDecimal::FOUR;
955        assert_eq!(a.log(b).unwrap(), FPDecimal::TWO);
956    }
957}