|
17 | 17 | However, things like 'N[Pi, 100]' should work as expected. |
18 | 18 | """ |
19 | 19 |
|
20 | | -from functools import lru_cache |
21 | | - |
22 | 20 | import mpmath |
23 | | -import sympy |
24 | 21 |
|
25 | 22 | from mathics.core.atoms import ( |
26 | 23 | Integer, |
|
33 | 30 | from mathics.core.attributes import A_LISTABLE, A_PROTECTED, A_READ_PROTECTED |
34 | 31 | from mathics.core.builtin import Builtin, Predefined |
35 | 32 | from mathics.core.convert.python import from_python |
| 33 | +from mathics.core.evaluation import Evaluation |
36 | 34 | from mathics.core.expression import Expression |
37 | 35 | from mathics.core.list import ListExpression |
38 | 36 | from mathics.core.number import ( |
|
52 | 50 | SymbolRound, |
53 | 51 | ) |
54 | 52 | from mathics.eval.nevaluator import eval_N |
55 | | -from mathics.eval.numbers.numbers import eval_Accuracy, eval_Precision |
| 53 | +from mathics.eval.numbers.numbers import ( |
| 54 | + check_finite_decimal, |
| 55 | + convert_float_base, |
| 56 | + convert_repeating_decimal, |
| 57 | + eval_Accuracy, |
| 58 | + eval_Precision, |
| 59 | + log_n_b, |
| 60 | +) |
56 | 61 |
|
57 | 62 | SymbolIntegerDigits = Symbol("IntegerDigits") |
58 | 63 | SymbolIntegerExponent = Symbol("IntegerExponent") |
59 | 64 |
|
60 | 65 |
|
61 | | -@lru_cache() |
62 | | -def log_n_b(py_n, py_b) -> int: |
63 | | - return ( |
64 | | - int(mpmath.floor(mpmath.log(py_n, py_b))) + 1 if py_n != 0 and py_n != 1 else 1 |
65 | | - ) |
66 | | - |
67 | | - |
68 | | -def check_finite_decimal(denominator): |
69 | | - # The rational number is finite decimal if the denominator has form 2^a * 5^b |
70 | | - while denominator % 5 == 0: |
71 | | - denominator = denominator / 5 |
72 | | - |
73 | | - while denominator % 2 == 0: |
74 | | - denominator = denominator / 2 |
75 | | - |
76 | | - return True if denominator == 1 else False |
77 | | - |
78 | | - |
79 | | -def convert_repeating_decimal(numerator, denominator, base): |
80 | | - head = [x for x in str(numerator // denominator)] |
81 | | - tails = [] |
82 | | - subresults = [numerator % denominator] |
83 | | - numerator %= denominator |
84 | | - |
85 | | - while numerator != 0: # only rational input can go to this case |
86 | | - numerator *= base |
87 | | - result_digit, numerator = divmod(numerator, denominator) |
88 | | - tails.append(str(result_digit)) |
89 | | - if numerator not in subresults: |
90 | | - subresults.append(numerator) |
91 | | - else: |
92 | | - break |
93 | | - |
94 | | - for i in range(len(head) - 1, -1, -1): |
95 | | - j = len(tails) - 1 |
96 | | - if head[i] != tails[j]: |
97 | | - break |
98 | | - else: |
99 | | - del tails[j] |
100 | | - tails.insert(0, head[i]) |
101 | | - del head[i] |
102 | | - |
103 | | - # truncate all leading 0's |
104 | | - if all(elem == "0" for elem in head): |
105 | | - for i in range(0, len(tails)): |
106 | | - if tails[0] == "0": |
107 | | - tails = tails[1:] + [str(0)] |
108 | | - else: |
109 | | - break |
110 | | - return (head, tails) |
111 | | - |
112 | | - |
113 | | -def convert_float_base(x, base, precision=10): |
114 | | - length_of_int = 0 if x == 0 else int(mpmath.log(x, base)) |
115 | | - # iexps = list(range(length_of_int, -1, -1)) |
116 | | - |
117 | | - def convert_int(x, base, exponents): |
118 | | - out = [] |
119 | | - for e in range(0, exponents + 1): |
120 | | - d = x % base |
121 | | - out.append(d) |
122 | | - x = x / base |
123 | | - if x == 0: |
124 | | - break |
125 | | - out.reverse() |
126 | | - return out |
127 | | - |
128 | | - def convert_float(x, base, exponents): |
129 | | - out = [] |
130 | | - for e in range(0, exponents): |
131 | | - d = int(x * base) |
132 | | - out.append(d) |
133 | | - x = (x * base) - d |
134 | | - if x == 0: |
135 | | - break |
136 | | - return out |
137 | | - |
138 | | - int_part = convert_int(int(x), base, length_of_int) |
139 | | - if isinstance(x, (float, sympy.Float)): |
140 | | - # fexps = list(range(-1, -int(precision + 1), -1)) |
141 | | - real_part = convert_float(x - int(x), base, precision + 1) |
142 | | - return int_part + real_part |
143 | | - elif isinstance(x, int): |
144 | | - return int_part |
145 | | - else: |
146 | | - raise TypeError(x) |
147 | | - |
148 | | - |
149 | 66 | class Accuracy(Builtin): |
150 | 67 | """ |
151 | 68 | <url> |
@@ -255,7 +172,7 @@ class IntegerExponent(Builtin): |
255 | 172 |
|
256 | 173 | summary_text = "number of trailing 0s in a given base" |
257 | 174 |
|
258 | | - def eval_two_arg_integers(self, n: Integer, b: Integer, evaluation): |
| 175 | + def eval_two_arg_integers(self, n: Integer, b: Integer, evaluation: Evaluation): |
259 | 176 | """IntegerExponent[n_Integer, b_Integer]""" |
260 | 177 |
|
261 | 178 | py_n, py_b = n.value, b.value |
|
0 commit comments