Skip to content

Commit b1af77c

Browse files
committed
avoid some object churn in division
1 parent 097c6d7 commit b1af77c

1 file changed

Lines changed: 25 additions & 9 deletions

File tree

quadint/quad/rings.py

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -332,10 +332,22 @@ def divmod(self, x: "QuadInt", y: "QuadInt"):
332332
raise ZeroDivisionError
333333

334334
# Candidate center from x/y ≈ (x * conj(y)) / N(y)
335-
num = x * y.conjugate()
336-
337-
A0 = _round_div_ties_away_from_zero(num.a, Ny)
338-
B0 = _round_div_ties_away_from_zero(num.b, Ny)
335+
a1, b1 = x.a, x.b
336+
a2, b2 = y.a, y.b
337+
338+
# num = x * conj(y), but computed in numerators directly
339+
# (a1+b1√D)(a2-b2√D) = (a1*a2 - b1*b2*D) + (a2*b1 - a1*b2)√D
340+
num_a = a1 * a2 - b1 * b2 * self.D
341+
num_b = a2 * b1 - a1 * b2
342+
343+
if self.den != 1:
344+
if (num_a % self.den) != 0 or (num_b % self.den) != 0:
345+
raise ArithmeticError("Non-integral product; check ring parameters / parity")
346+
num_a //= self.den
347+
num_b //= self.den
348+
349+
A0 = _round_div_ties_away_from_zero(num_a, Ny)
350+
B0 = _round_div_ties_away_from_zero(num_b, Ny)
339351
dd = self.den ** 2
340352
threshold = absNy * absNy * dd
341353

@@ -344,8 +356,8 @@ def B0_for_A(A: int) -> int: # noqa: ARG001
344356

345357
# Prefer any norm-reducing remainder; among those, minimize |N(r)| then distance to (A0,B0).
346358
def score_for_AB(A: int, B: int) -> tuple[int, ...]:
347-
da = A * Ny - num.a
348-
db = B * Ny - num.b
359+
da = A * Ny - num_a
360+
db = B * Ny - num_b
349361

350362
# numerator of N(w) where w=(da + db*sqrt(D))/den
351363
nw_num = da * da - self.D * (db * db)
@@ -363,9 +375,13 @@ def score_for_AB(A: int, B: int) -> tuple[int, ...]:
363375
A0=A0, B0_for_A=B0_for_A, score_for_AB=score_for_AB, den=self.den, radius=rad,
364376
)
365377

366-
q = x._make(bestA, bestB)
367-
r = x - q * y
368-
if abs(abs(r)) < absNy:
378+
da = bestA * Ny - num_a
379+
db = bestB * Ny - num_b
380+
nw_num = da * da - self.D * (db * db)
381+
382+
if abs(nw_num) < threshold:
383+
q = x._make(bestA, bestB)
384+
r = x - q * y
369385
return q, r
370386

371387
raise NotImplementedError(

0 commit comments

Comments
 (0)