@@ -213,21 +213,53 @@ def _div3n2n(a12, a3, b, b1, b2, n):
213
213
return q , r
214
214
215
215
216
+ def _int2digits (a , n ):
217
+ """decompose non-negative integer a into base 2**n"""
218
+ a_digits = [0 ] * ((a .bit_length () + n - 1 ) // n )
219
+
220
+ def inner (x , L , R ):
221
+ if L + 1 == R :
222
+ a_digits [L ] = x
223
+ return
224
+ mid = (L + R ) >> 1
225
+ shift = (mid - L ) * n
226
+ upper = x >> shift
227
+ lower = x ^ (upper << shift )
228
+ inner (lower , L , mid )
229
+ inner (upper , mid , R )
230
+
231
+ if a :
232
+ inner (a , 0 , len (a_digits ))
233
+ return a_digits
234
+
235
+
236
+ def _digits2int (digits , n ):
237
+ """combine base-2**n digits into an int"""
238
+
239
+ def inner (L , R ):
240
+ if L + 1 == R :
241
+ return digits [L ]
242
+ mid = (L + R ) >> 1
243
+ shift = (mid - L ) * n
244
+ return (inner (mid , R ) << shift ) + inner (L , mid )
245
+
246
+ return inner (0 , len (digits )) if digits else 0
247
+
248
+
216
249
def _divmod_pos (a , b ):
217
- """Divide a positive integer a by a positive integer b, giving
250
+ """Divide a non-negative integer a by a positive integer b, giving
218
251
quotient and remainder."""
219
252
# Use grade-school algorithm in base 2**n, n = nbits(b)
220
253
n = b .bit_length ()
221
- mask = (1 << n ) - 1
222
- a_digits = []
223
- while a :
224
- a_digits .append (a & mask )
225
- a >>= n
226
- r = 0 if a_digits [- 1 ] >= b else a_digits .pop ()
227
- q = 0
228
- while a_digits :
229
- q_digit , r = _div2n1n ((r << n ) + a_digits .pop (), b , n )
230
- q = (q << n ) + q_digit
254
+ a_digits = _int2digits (a , n )
255
+
256
+ r = 0
257
+ q_digits = []
258
+ for a_digit in reversed (a_digits ):
259
+ q_digit , r = _div2n1n ((r << n ) + a_digit , b , n )
260
+ q_digits .append (q_digit )
261
+ q_digits .reverse ()
262
+ q = _digits2int (q_digits , n )
231
263
return q , r
232
264
233
265
0 commit comments