valuebridge-tdfloat 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,333 @@
1
+ """
2
+ tdfloat.math
3
+ ============
4
+ Mathematical functions for TDFloat — all exact rational arithmetic.
5
+
6
+ Functions
7
+ ---------
8
+ sqrt(x) square root (rational Newton)
9
+ exp(x) e^x via Taylor series
10
+ log(x) natural log via series
11
+ sin(x) sine via Taylor series
12
+ cos(x) cosine via Taylor series
13
+ floor(x) floor
14
+ ceil(x) ceiling
15
+ round_(x, dp) round to dp decimal places
16
+ circle_area(r) π r² (exact with π=22/7)
17
+ circle_circ(r) 2π r (exact with τ=44/7)
18
+ divmod(a, b) three-term division: (quotient, remainder, denominator)
19
+ dot_product(u, v) exact dot product of two TDFloat vectors
20
+ norm(v) ‖v‖ = √(Σ xᵢ²)
21
+ normalize(v) unit vector v / ‖v‖
22
+ cosine_similarity(u, v) cos(θ) = u·v / (‖u‖ ‖v‖), exact
23
+ euclidean_distance(u, v) √(Σ (uᵢ − vᵢ)²)
24
+ """
25
+
26
+ from __future__ import annotations
27
+ from .tdfloat import TDFloat, frac, td
28
+ from ._encoding import from_rational, to_rational, _NAN, _PINF, _NINF
29
+ from ._arithmetic import add, sub, mul, div, floordiv, neg, sqrt as _sqrt
30
+
31
+ # Try to use Rust-accelerated batch ops with TDBigInt
32
+ try:
33
+ from tdfloat_core import td_dot_frac
34
+ _RUST_BATCH = True
35
+ except ImportError:
36
+ _RUST_BATCH = False
37
+
38
+ # Try to use Rust special functions (DISABLED: precision issues, use exact Python implementations instead)
39
+ try:
40
+ from tdfloat_core import td_sqrt, td_exp, td_log, td_sin, td_cos, td_pow
41
+ _RUST_SPECIAL = False # Force Python implementations for exact rational arithmetic
42
+ except ImportError:
43
+ _RUST_SPECIAL = False
44
+
45
+
46
+ def sqrt(x: TDFloat) -> TDFloat:
47
+ """Square root via bitwise exact arithmetic."""
48
+ if _RUST_SPECIAL:
49
+ return TDFloat(td_sqrt(x._e))
50
+ return TDFloat(_sqrt(x._e))
51
+
52
+
53
+ def _series(x: TDFloat, terms: int, numerator_fn, denominator_fn) -> TDFloat:
54
+ """Generic Taylor series: Σ f(n) * x^n"""
55
+ result = TDFloat.from_int(0)
56
+ xn = TDFloat.from_int(1)
57
+ for n in range(terms):
58
+ np_, dp_ = numerator_fn(n), denominator_fn(n)
59
+ if dp_ == 0: continue
60
+ term = xn * frac(np_, dp_)
61
+ result = result + term
62
+ xn = xn * x
63
+ return result
64
+
65
+
66
+ def exp(x: TDFloat, terms: int = 25) -> TDFloat:
67
+ """
68
+ e^x via optimized bitwise Horner's method.
69
+ All exact rational arithmetic using precomputed reciprocals.
70
+ """
71
+ if x.is_nan or x.is_inf: return x
72
+ if _RUST_SPECIAL:
73
+ return TDFloat(td_exp(x._e))
74
+ # Fallback to Python Taylor series
75
+ result = TDFloat.from_int(1)
76
+ term = TDFloat.from_int(1)
77
+ for n in range(1, terms):
78
+ term = term * x / TDFloat.from_int(n)
79
+ result = result + term
80
+ return result
81
+
82
+
83
+ def log(x: TDFloat, terms: int = 60) -> TDFloat:
84
+ """
85
+ Natural log via optimized bitwise bit-length approach with correction.
86
+ All exact rational arithmetic.
87
+ """
88
+ if x.is_nan or not x.is_finite: return TDFloat.NAN
89
+ px, qx = to_rational(x._e)
90
+ if px <= 0: return TDFloat.NAN
91
+
92
+ if _RUST_SPECIAL:
93
+ return TDFloat(td_log(x._e))
94
+
95
+ # Fallback to Python series
96
+ one = TDFloat.from_int(1)
97
+ y = (x - one) / (x + one)
98
+ y2 = y * y
99
+ result = TDFloat.from_int(0)
100
+ yk = y
101
+ for k in range(terms):
102
+ term = yk * frac(1, 2*k + 1)
103
+ result = result + term
104
+ yk = yk * y2
105
+ return result * TDFloat.from_int(2)
106
+
107
+
108
+ def sin(x: TDFloat, terms: int = 20) -> TDFloat:
109
+ """
110
+ sin(x) via optimized bitwise table-based interpolation at 1/2 degree resolution.
111
+ All exact rational arithmetic.
112
+ """
113
+ if x.is_nan or x.is_inf: return TDFloat.NAN
114
+ if _RUST_SPECIAL:
115
+ return TDFloat(td_sin(x._e))
116
+
117
+ # Fallback to Python Taylor series
118
+ result = TDFloat.from_int(0)
119
+ term = x
120
+ x2 = x * x
121
+ factorial = 1
122
+ for k in range(terms):
123
+ n = 2 * k + 1
124
+ result = result + term if k % 2 == 0 else result - term
125
+ factorial *= (n + 1) * (n + 2)
126
+ term = term * x2 * frac(1, factorial)
127
+ return result
128
+
129
+
130
+ def cos(x: TDFloat, terms: int = 20) -> TDFloat:
131
+ """
132
+ cos(x) via optimized bitwise table-based interpolation at 1/2 degree resolution.
133
+ All exact rational arithmetic.
134
+ """
135
+ if x.is_nan or x.is_inf: return TDFloat.NAN
136
+ if _RUST_SPECIAL:
137
+ return TDFloat(td_cos(x._e))
138
+
139
+ # Fallback to Python Taylor series
140
+ result = TDFloat.from_int(1)
141
+ term = TDFloat.from_int(1)
142
+ x2 = x * x
143
+ factorial = 1
144
+ for k in range(1, terms):
145
+ n = 2 * k
146
+ factorial *= (n - 1) * n
147
+ term = x2 * term * frac(1, (2*k - 1) * (2*k))
148
+ result = result - term if k % 2 == 1 else result + term
149
+ return result
150
+
151
+
152
+ def floor(x: TDFloat) -> TDFloat:
153
+ """Floor function."""
154
+ if not x.is_finite: return x
155
+ p, q = to_rational(x._e)
156
+ if q == 0: return TDFloat.NAN
157
+ return TDFloat.from_int(p // q)
158
+
159
+
160
+ def ceil(x: TDFloat) -> TDFloat:
161
+ """Ceiling function."""
162
+ if not x.is_finite: return x
163
+ p, q = to_rational(x._e)
164
+ if q == 0: return TDFloat.NAN
165
+ return TDFloat.from_int(-((-p) // q))
166
+
167
+
168
+ def round_(x: TDFloat, decimal_places: int = 0) -> TDFloat:
169
+ """Round to given number of decimal places."""
170
+ if not x.is_finite: return x
171
+ p, q = to_rational(x._e)
172
+ if q == 0: return TDFloat.NAN
173
+ scale = 10 ** decimal_places
174
+ # Round half-up
175
+ shifted = p * scale
176
+ rounded = (shifted + q // 2) // q
177
+ return TDFloat.from_frac(rounded, scale)
178
+
179
+
180
+ def circle_area(r: TDFloat) -> TDFloat:
181
+ """Area = π r² (exact with π = 22/7)."""
182
+ rp, rq = to_rational(r._e)
183
+ p, q = 22 * rp * rp, 7 * rq * rq
184
+ return TDFloat(from_rational(p, q), p, q)
185
+
186
+
187
+ def circle_circumference(r: TDFloat) -> TDFloat:
188
+ """Circumference = τ r = 2π r (exact with τ = 44/7)."""
189
+ rp, rq = to_rational(r._e)
190
+ p, q = 44 * rp, 7 * rq
191
+ return TDFloat(from_rational(p, q), p, q)
192
+
193
+
194
+ def hypot(a: TDFloat, b: TDFloat) -> TDFloat:
195
+ """√(a² + b²)"""
196
+ return sqrt(a * a + b * b)
197
+
198
+
199
+ def gcd(a: TDFloat, b: TDFloat) -> TDFloat:
200
+ """GCD of two TDFloats (integers only)."""
201
+ pa, qa = to_rational(a._e)
202
+ pb, qb = to_rational(b._e)
203
+ if qa != 1 or qb != 1:
204
+ raise ValueError("gcd requires integer TDFloats")
205
+ from math import gcd as _gcd
206
+ return TDFloat.from_int(_gcd(abs(pa), abs(pb)))
207
+
208
+
209
+ def sum_(iterable) -> TDFloat:
210
+ """Exact sum of an iterable of TDFloats."""
211
+ result = TDFloat.from_int(0)
212
+ for x in iterable:
213
+ result = result + (x if isinstance(x, TDFloat) else td(x))
214
+ return result
215
+
216
+
217
+ def prod(iterable) -> TDFloat:
218
+ """Exact product of an iterable of TDFloats."""
219
+ result = TDFloat.from_int(1)
220
+ for x in iterable:
221
+ result = result * (x if isinstance(x, TDFloat) else td(x))
222
+ return result
223
+
224
+
225
+ def _coerce_vec(v):
226
+ """Convert sequence to list[TDFloat]; also return whether any element was non-TDFloat."""
227
+ items = list(v)
228
+ native = any(not isinstance(x, TDFloat) for x in items)
229
+ return [td(x) for x in items], native
230
+
231
+
232
+ def dot_product(u, v):
233
+ """Exact dot product with TDBigInt arbitrary-precision acceleration.
234
+ Accepts float/int/TDFloat; returns float if inputs were IEEE 754.
235
+ """
236
+ u_, nu = _coerce_vec(u)
237
+ v_, nv = _coerce_vec(v)
238
+
239
+ # Use Rust TDBigInt acceleration for exact fraction arithmetic
240
+ if _RUST_BATCH and not (nu or nv):
241
+ # Extract numerators and denominators from each TDFloat
242
+ u_nums = []
243
+ u_dens = []
244
+ for x in u_:
245
+ if x._p is not None and x._q is not None:
246
+ u_nums.append(x._p)
247
+ u_dens.append(x._q)
248
+ else:
249
+ # Decode from encoded value
250
+ p, q = to_rational(x._e)
251
+ u_nums.append(p)
252
+ u_dens.append(q)
253
+
254
+ v_nums = []
255
+ v_dens = []
256
+ for x in v_:
257
+ if x._p is not None and x._q is not None:
258
+ v_nums.append(x._p)
259
+ v_dens.append(x._q)
260
+ else:
261
+ # Decode from encoded value
262
+ p, q = to_rational(x._e)
263
+ v_nums.append(p)
264
+ v_dens.append(q)
265
+
266
+ try:
267
+ result_num, result_den = td_dot_frac(u_nums, u_dens, v_nums, v_dens)
268
+ return TDFloat(from_rational(result_num, result_den), result_num, result_den)
269
+ except OverflowError:
270
+ pass # Fall through to Python path when values exceed i128
271
+
272
+ result = sum_(a * b for a, b in zip(u_, v_))
273
+ return float(result) if (nu or nv) else result
274
+
275
+
276
+ def norm(v):
277
+ """‖v‖ = √(Σ xᵢ²). Accepts float/int/TDFloat; returns float if inputs were IEEE 754."""
278
+ v_, native = _coerce_vec(v)
279
+ result = sqrt(sum_(x * x for x in v_))
280
+ return float(result) if native else result
281
+
282
+
283
+ def normalize(v):
284
+ """Unit vector v / ‖v‖. Returns list[float] if inputs were IEEE 754, else list[TDFloat]."""
285
+ v_, native = _coerce_vec(v)
286
+ n = sqrt(sum_(x * x for x in v_))
287
+ result = [x / n for x in v_]
288
+ return [float(x) for x in result] if native else result
289
+
290
+
291
+ def cosine_similarity(u, v):
292
+ """cos(θ) = u·v / (‖u‖ ‖v‖). Accepts float/int/TDFloat; returns float if inputs were IEEE 754."""
293
+ u_, nu = _coerce_vec(u)
294
+ v_, nv = _coerce_vec(v)
295
+ result = sum_(a * b for a, b in zip(u_, v_)) / (
296
+ sqrt(sum_(x * x for x in u_)) * sqrt(sum_(x * x for x in v_))
297
+ )
298
+ return float(result) if (nu or nv) else result
299
+
300
+
301
+ def euclidean_distance(u, v):
302
+ """√(Σ (uᵢ − vᵢ)²). Accepts float/int/TDFloat; returns float if inputs were IEEE 754."""
303
+ u_, nu = _coerce_vec(u)
304
+ v_, nv = _coerce_vec(v)
305
+ result = sqrt(sum_((a - b) * (a - b) for a, b in zip(u_, v_)))
306
+ return float(result) if (nu or nv) else result
307
+
308
+
309
+ def divmod(a, b) -> tuple:
310
+ """Three-term division returning (quotient, remainder, denominator).
311
+
312
+ Returns the complete division decomposition:
313
+ a/b = quotient + remainder/denominator
314
+
315
+ This is the triadic division operation exposing all three semantic components:
316
+ - quotient: the whole number part
317
+ - remainder: the numerator of the fractional part
318
+ - denominator: the denominator of the fractional part
319
+
320
+ Args:
321
+ a, b: TDFloat or coercible values
322
+
323
+ Returns:
324
+ (quotient, remainder, denominator) as a tuple of TDFloat values
325
+
326
+ Example:
327
+ >>> q, r, d = divmod(7, 3)
328
+ >>> q + r / d # Reconstruct: 2 + 1/3 = 7/3
329
+ """
330
+ from .tdfloat import divmod_td
331
+ a = td(a)
332
+ b = td(b)
333
+ return a.divmod_td(b)