@@ -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