Coverage for /usr/lib/python3/dist-packages/mpmath/libmp/libintmath.py: 31%

345 statements  

« prev     ^ index     » next       coverage.py v7.9.1, created at 2025-06-14 15:55 +0200

1""" 

2Utility functions for integer math. 

3 

4TODO: rename, cleanup, perhaps move the gmpy wrapper code 

5here from settings.py 

6 

7""" 

8 

9import math 

10from bisect import bisect 

11 

12from .backend import xrange 

13from .backend import BACKEND, gmpy, sage, sage_utils, MPZ, MPZ_ONE, MPZ_ZERO 

14 

15small_trailing = [0] * 256 

16for j in range(1,8): 

17 small_trailing[1<<j::1<<(j+1)] = [j] * (1<<(7-j)) 

18 

19def giant_steps(start, target, n=2): 

20 """ 

21 Return a list of integers ~= 

22 

23 [start, n*start, ..., target/n^2, target/n, target] 

24 

25 but conservatively rounded so that the quotient between two 

26 successive elements is actually slightly less than n. 

27 

28 With n = 2, this describes suitable precision steps for a 

29 quadratically convergent algorithm such as Newton's method; 

30 with n = 3 steps for cubic convergence (Halley's method), etc. 

31 

32 >>> giant_steps(50,1000) 

33 [66, 128, 253, 502, 1000] 

34 >>> giant_steps(50,1000,4) 

35 [65, 252, 1000] 

36 

37 """ 

38 L = [target] 

39 while L[-1] > start*n: 

40 L = L + [L[-1]//n + 2] 

41 return L[::-1] 

42 

43def rshift(x, n): 

44 """For an integer x, calculate x >> n with the fastest (floor) 

45 rounding. Unlike the plain Python expression (x >> n), n is 

46 allowed to be negative, in which case a left shift is performed.""" 

47 if n >= 0: return x >> n 

48 else: return x << (-n) 

49 

50def lshift(x, n): 

51 """For an integer x, calculate x << n. Unlike the plain Python 

52 expression (x << n), n is allowed to be negative, in which case a 

53 right shift with default (floor) rounding is performed.""" 

54 if n >= 0: return x << n 

55 else: return x >> (-n) 

56 

57if BACKEND == 'sage': 

58 import operator 

59 rshift = operator.rshift 

60 lshift = operator.lshift 

61 

62def python_trailing(n): 

63 """Count the number of trailing zero bits in abs(n).""" 

64 if not n: 

65 return 0 

66 low_byte = n & 0xff 

67 if low_byte: 

68 return small_trailing[low_byte] 

69 t = 8 

70 n >>= 8 

71 while not n & 0xff: 

72 n >>= 8 

73 t += 8 

74 return t + small_trailing[n & 0xff] 

75 

76if BACKEND == 'gmpy': 

77 if gmpy.version() >= '2': 

78 def gmpy_trailing(n): 

79 """Count the number of trailing zero bits in abs(n) using gmpy.""" 

80 if n: return MPZ(n).bit_scan1() 

81 else: return 0 

82 else: 

83 def gmpy_trailing(n): 

84 """Count the number of trailing zero bits in abs(n) using gmpy.""" 

85 if n: return MPZ(n).scan1() 

86 else: return 0 

87 

88# Small powers of 2 

89powers = [1<<_ for _ in range(300)] 

90 

91def python_bitcount(n): 

92 """Calculate bit size of the nonnegative integer n.""" 

93 bc = bisect(powers, n) 

94 if bc != 300: 

95 return bc 

96 bc = int(math.log(n, 2)) - 4 

97 return bc + bctable[n>>bc] 

98 

99def gmpy_bitcount(n): 

100 """Calculate bit size of the nonnegative integer n.""" 

101 if n: return MPZ(n).numdigits(2) 

102 else: return 0 

103 

104#def sage_bitcount(n): 

105# if n: return MPZ(n).nbits() 

106# else: return 0 

107 

108def sage_trailing(n): 

109 return MPZ(n).trailing_zero_bits() 

110 

111if BACKEND == 'gmpy': 

112 bitcount = gmpy_bitcount 

113 trailing = gmpy_trailing 

114elif BACKEND == 'sage': 

115 sage_bitcount = sage_utils.bitcount 

116 bitcount = sage_bitcount 

117 trailing = sage_trailing 

118else: 

119 bitcount = python_bitcount 

120 trailing = python_trailing 

121 

122if BACKEND == 'gmpy' and 'bit_length' in dir(gmpy): 

123 bitcount = gmpy.bit_length 

124 

125# Used to avoid slow function calls as far as possible 

126trailtable = [trailing(n) for n in range(256)] 

127bctable = [bitcount(n) for n in range(1024)] 

128 

129# TODO: speed up for bases 2, 4, 8, 16, ... 

130 

131def bin_to_radix(x, xbits, base, bdigits): 

132 """Changes radix of a fixed-point number; i.e., converts 

133 x * 2**xbits to floor(x * 10**bdigits).""" 

134 return x * (MPZ(base)**bdigits) >> xbits 

135 

136stddigits = '0123456789abcdefghijklmnopqrstuvwxyz' 

137 

138def small_numeral(n, base=10, digits=stddigits): 

139 """Return the string numeral of a positive integer in an arbitrary 

140 base. Most efficient for small input.""" 

141 if base == 10: 

142 return str(n) 

143 digs = [] 

144 while n: 

145 n, digit = divmod(n, base) 

146 digs.append(digits[digit]) 

147 return "".join(digs[::-1]) 

148 

149def numeral_python(n, base=10, size=0, digits=stddigits): 

150 """Represent the integer n as a string of digits in the given base. 

151 Recursive division is used to make this function about 3x faster 

152 than Python's str() for converting integers to decimal strings. 

153 

154 The 'size' parameters specifies the number of digits in n; this 

155 number is only used to determine splitting points and need not be 

156 exact.""" 

157 if n <= 0: 

158 if not n: 

159 return "0" 

160 return "-" + numeral(-n, base, size, digits) 

161 # Fast enough to do directly 

162 if size < 250: 

163 return small_numeral(n, base, digits) 

164 # Divide in half 

165 half = (size // 2) + (size & 1) 

166 A, B = divmod(n, base**half) 

167 ad = numeral(A, base, half, digits) 

168 bd = numeral(B, base, half, digits).rjust(half, "0") 

169 return ad + bd 

170 

171def numeral_gmpy(n, base=10, size=0, digits=stddigits): 

172 """Represent the integer n as a string of digits in the given base. 

173 Recursive division is used to make this function about 3x faster 

174 than Python's str() for converting integers to decimal strings. 

175 

176 The 'size' parameters specifies the number of digits in n; this 

177 number is only used to determine splitting points and need not be 

178 exact.""" 

179 if n < 0: 

180 return "-" + numeral(-n, base, size, digits) 

181 # gmpy.digits() may cause a segmentation fault when trying to convert 

182 # extremely large values to a string. The size limit may need to be 

183 # adjusted on some platforms, but 1500000 works on Windows and Linux. 

184 if size < 1500000: 

185 return gmpy.digits(n, base) 

186 # Divide in half 

187 half = (size // 2) + (size & 1) 

188 A, B = divmod(n, MPZ(base)**half) 

189 ad = numeral(A, base, half, digits) 

190 bd = numeral(B, base, half, digits).rjust(half, "0") 

191 return ad + bd 

192 

193if BACKEND == "gmpy": 

194 numeral = numeral_gmpy 

195else: 

196 numeral = numeral_python 

197 

198_1_800 = 1<<800 

199_1_600 = 1<<600 

200_1_400 = 1<<400 

201_1_200 = 1<<200 

202_1_100 = 1<<100 

203_1_50 = 1<<50 

204 

205def isqrt_small_python(x): 

206 """ 

207 Correctly (floor) rounded integer square root, using 

208 division. Fast up to ~200 digits. 

209 """ 

210 if not x: 

211 return x 

212 if x < _1_800: 

213 # Exact with IEEE double precision arithmetic 

214 if x < _1_50: 

215 return int(x**0.5) 

216 # Initial estimate can be any integer >= the true root; round up 

217 r = int(x**0.5 * 1.00000000000001) + 1 

218 else: 

219 bc = bitcount(x) 

220 n = bc//2 

221 r = int((x>>(2*n-100))**0.5+2)<<(n-50) # +2 is to round up 

222 # The following iteration now precisely computes floor(sqrt(x)) 

223 # See e.g. Crandall & Pomerance, "Prime Numbers: A Computational 

224 # Perspective" 

225 while 1: 

226 y = (r+x//r)>>1 

227 if y >= r: 

228 return r 

229 r = y 

230 

231def isqrt_fast_python(x): 

232 """ 

233 Fast approximate integer square root, computed using division-free 

234 Newton iteration for large x. For random integers the result is almost 

235 always correct (floor(sqrt(x))), but is 1 ulp too small with a roughly 

236 0.1% probability. If x is very close to an exact square, the answer is 

237 1 ulp wrong with high probability. 

238 

239 With 0 guard bits, the largest error over a set of 10^5 random 

240 inputs of size 1-10^5 bits was 3 ulp. The use of 10 guard bits 

241 almost certainly guarantees a max 1 ulp error. 

242 """ 

243 # Use direct division-based iteration if sqrt(x) < 2^400 

244 # Assume floating-point square root accurate to within 1 ulp, then: 

245 # 0 Newton iterations good to 52 bits 

246 # 1 Newton iterations good to 104 bits 

247 # 2 Newton iterations good to 208 bits 

248 # 3 Newton iterations good to 416 bits 

249 if x < _1_800: 

250 y = int(x**0.5) 

251 if x >= _1_100: 

252 y = (y + x//y) >> 1 

253 if x >= _1_200: 

254 y = (y + x//y) >> 1 

255 if x >= _1_400: 

256 y = (y + x//y) >> 1 

257 return y 

258 bc = bitcount(x) 

259 guard_bits = 10 

260 x <<= 2*guard_bits 

261 bc += 2*guard_bits 

262 bc += (bc&1) 

263 hbc = bc//2 

264 startprec = min(50, hbc) 

265 # Newton iteration for 1/sqrt(x), with floating-point starting value 

266 r = int(2.0**(2*startprec) * (x >> (bc-2*startprec)) ** -0.5) 

267 pp = startprec 

268 for p in giant_steps(startprec, hbc): 

269 # r**2, scaled from real size 2**(-bc) to 2**p 

270 r2 = (r*r) >> (2*pp - p) 

271 # x*r**2, scaled from real size ~1.0 to 2**p 

272 xr2 = ((x >> (bc-p)) * r2) >> p 

273 # New value of r, scaled from real size 2**(-bc/2) to 2**p 

274 r = (r * ((3<<p) - xr2)) >> (pp+1) 

275 pp = p 

276 # (1/sqrt(x))*x = sqrt(x) 

277 return (r*(x>>hbc)) >> (p+guard_bits) 

278 

279def sqrtrem_python(x): 

280 """Correctly rounded integer (floor) square root with remainder.""" 

281 # to check cutoff: 

282 # plot(lambda x: timing(isqrt, 2**int(x)), [0,2000]) 

283 if x < _1_600: 

284 y = isqrt_small_python(x) 

285 return y, x - y*y 

286 y = isqrt_fast_python(x) + 1 

287 rem = x - y*y 

288 # Correct remainder 

289 while rem < 0: 

290 y -= 1 

291 rem += (1+2*y) 

292 else: 

293 if rem: 

294 while rem > 2*(1+y): 

295 y += 1 

296 rem -= (1+2*y) 

297 return y, rem 

298 

299def isqrt_python(x): 

300 """Integer square root with correct (floor) rounding.""" 

301 return sqrtrem_python(x)[0] 

302 

303def sqrt_fixed(x, prec): 

304 return isqrt_fast(x<<prec) 

305 

306sqrt_fixed2 = sqrt_fixed 

307 

308if BACKEND == 'gmpy': 

309 if gmpy.version() >= '2': 

310 isqrt_small = isqrt_fast = isqrt = gmpy.isqrt 

311 sqrtrem = gmpy.isqrt_rem 

312 else: 

313 isqrt_small = isqrt_fast = isqrt = gmpy.sqrt 

314 sqrtrem = gmpy.sqrtrem 

315elif BACKEND == 'sage': 

316 isqrt_small = isqrt_fast = isqrt = \ 

317 getattr(sage_utils, "isqrt", lambda n: MPZ(n).isqrt()) 

318 sqrtrem = lambda n: MPZ(n).sqrtrem() 

319else: 

320 isqrt_small = isqrt_small_python 

321 isqrt_fast = isqrt_fast_python 

322 isqrt = isqrt_python 

323 sqrtrem = sqrtrem_python 

324 

325 

326def ifib(n, _cache={}): 

327 """Computes the nth Fibonacci number as an integer, for 

328 integer n.""" 

329 if n < 0: 

330 return (-1)**(-n+1) * ifib(-n) 

331 if n in _cache: 

332 return _cache[n] 

333 m = n 

334 # Use Dijkstra's logarithmic algorithm 

335 # The following implementation is basically equivalent to 

336 # http://en.literateprograms.org/Fibonacci_numbers_(Scheme) 

337 a, b, p, q = MPZ_ONE, MPZ_ZERO, MPZ_ZERO, MPZ_ONE 

338 while n: 

339 if n & 1: 

340 aq = a*q 

341 a, b = b*q+aq+a*p, b*p+aq 

342 n -= 1 

343 else: 

344 qq = q*q 

345 p, q = p*p+qq, qq+2*p*q 

346 n >>= 1 

347 if m < 250: 

348 _cache[m] = b 

349 return b 

350 

351MAX_FACTORIAL_CACHE = 1000 

352 

353def ifac(n, memo={0:1, 1:1}): 

354 """Return n factorial (for integers n >= 0 only).""" 

355 f = memo.get(n) 

356 if f: 

357 return f 

358 k = len(memo) 

359 p = memo[k-1] 

360 MAX = MAX_FACTORIAL_CACHE 

361 while k <= n: 

362 p *= k 

363 if k <= MAX: 

364 memo[k] = p 

365 k += 1 

366 return p 

367 

368def ifac2(n, memo_pair=[{0:1}, {1:1}]): 

369 """Return n!! (double factorial), integers n >= 0 only.""" 

370 memo = memo_pair[n&1] 

371 f = memo.get(n) 

372 if f: 

373 return f 

374 k = max(memo) 

375 p = memo[k] 

376 MAX = MAX_FACTORIAL_CACHE 

377 while k < n: 

378 k += 2 

379 p *= k 

380 if k <= MAX: 

381 memo[k] = p 

382 return p 

383 

384if BACKEND == 'gmpy': 

385 ifac = gmpy.fac 

386elif BACKEND == 'sage': 

387 ifac = lambda n: int(sage.factorial(n)) 

388 ifib = sage.fibonacci 

389 

390def list_primes(n): 

391 n = n + 1 

392 sieve = list(xrange(n)) 

393 sieve[:2] = [0, 0] 

394 for i in xrange(2, int(n**0.5)+1): 

395 if sieve[i]: 

396 for j in xrange(i**2, n, i): 

397 sieve[j] = 0 

398 return [p for p in sieve if p] 

399 

400if BACKEND == 'sage': 

401 # Note: it is *VERY* important for performance that we convert 

402 # the list to Python ints. 

403 def list_primes(n): 

404 return [int(_) for _ in sage.primes(n+1)] 

405 

406small_odd_primes = (3,5,7,11,13,17,19,23,29,31,37,41,43,47) 

407small_odd_primes_set = set(small_odd_primes) 

408 

409def isprime(n): 

410 """ 

411 Determines whether n is a prime number. A probabilistic test is 

412 performed if n is very large. No special trick is used for detecting 

413 perfect powers. 

414 

415 >>> sum(list_primes(100000)) 

416 454396537 

417 >>> sum(n*isprime(n) for n in range(100000)) 

418 454396537 

419 

420 """ 

421 n = int(n) 

422 if not n & 1: 

423 return n == 2 

424 if n < 50: 

425 return n in small_odd_primes_set 

426 for p in small_odd_primes: 

427 if not n % p: 

428 return False 

429 m = n-1 

430 s = trailing(m) 

431 d = m >> s 

432 def test(a): 

433 x = pow(a,d,n) 

434 if x == 1 or x == m: 

435 return True 

436 for r in xrange(1,s): 

437 x = x**2 % n 

438 if x == m: 

439 return True 

440 return False 

441 # See http://primes.utm.edu/prove/prove2_3.html 

442 if n < 1373653: 

443 witnesses = [2,3] 

444 elif n < 341550071728321: 

445 witnesses = [2,3,5,7,11,13,17] 

446 else: 

447 witnesses = small_odd_primes 

448 for a in witnesses: 

449 if not test(a): 

450 return False 

451 return True 

452 

453def moebius(n): 

454 """ 

455 Evaluates the Moebius function which is `mu(n) = (-1)^k` if `n` 

456 is a product of `k` distinct primes and `mu(n) = 0` otherwise. 

457 

458 TODO: speed up using factorization 

459 """ 

460 n = abs(int(n)) 

461 if n < 2: 

462 return n 

463 factors = [] 

464 for p in xrange(2, n+1): 

465 if not (n % p): 

466 if not (n % p**2): 

467 return 0 

468 if not sum(p % f for f in factors): 

469 factors.append(p) 

470 return (-1)**len(factors) 

471 

472def gcd(*args): 

473 a = 0 

474 for b in args: 

475 if a: 

476 while b: 

477 a, b = b, a % b 

478 else: 

479 a = b 

480 return a 

481 

482 

483# Comment by Juan Arias de Reyna: 

484# 

485# I learn this method to compute EulerE[2n] from van de Lune. 

486# 

487# We apply the formula EulerE[2n] = (-1)^n 2**(-2n) sum_{j=0}^n a(2n,2j+1) 

488# 

489# where the numbers a(n,j) vanish for j > n+1 or j <= -1 and satisfies 

490# 

491# a(0,-1) = a(0,0) = 0; a(0,1)= 1; a(0,2) = a(0,3) = 0 

492# 

493# a(n,j) = a(n-1,j) when n+j is even 

494# a(n,j) = (j-1) a(n-1,j-1) + (j+1) a(n-1,j+1) when n+j is odd 

495# 

496# 

497# But we can use only one array unidimensional a(j) since to compute 

498# a(n,j) we only need to know a(n-1,k) where k and j are of different parity 

499# and we have not to conserve the used values. 

500# 

501# We cached up the values of Euler numbers to sufficiently high order. 

502# 

503# Important Observation: If we pretend to use the numbers 

504# EulerE[1], EulerE[2], ... , EulerE[n] 

505# it is convenient to compute first EulerE[n], since the algorithm 

506# computes first all 

507# the previous ones, and keeps them in the CACHE 

508 

509MAX_EULER_CACHE = 500 

510 

511def eulernum(m, _cache={0:MPZ_ONE}): 

512 r""" 

513 Computes the Euler numbers `E(n)`, which can be defined as 

514 coefficients of the Taylor expansion of `1/cosh x`: 

515 

516 .. math :: 

517 

518 \frac{1}{\cosh x} = \sum_{n=0}^\infty \frac{E_n}{n!} x^n 

519 

520 Example:: 

521 

522 >>> [int(eulernum(n)) for n in range(11)] 

523 [1, 0, -1, 0, 5, 0, -61, 0, 1385, 0, -50521] 

524 >>> [int(eulernum(n)) for n in range(11)] # test cache 

525 [1, 0, -1, 0, 5, 0, -61, 0, 1385, 0, -50521] 

526 

527 """ 

528 # for odd m > 1, the Euler numbers are zero 

529 if m & 1: 

530 return MPZ_ZERO 

531 f = _cache.get(m) 

532 if f: 

533 return f 

534 MAX = MAX_EULER_CACHE 

535 n = m 

536 a = [MPZ(_) for _ in [0,0,1,0,0,0]] 

537 for n in range(1, m+1): 

538 for j in range(n+1, -1, -2): 

539 a[j+1] = (j-1)*a[j] + (j+1)*a[j+2] 

540 a.append(0) 

541 suma = 0 

542 for k in range(n+1, -1, -2): 

543 suma += a[k+1] 

544 if n <= MAX: 

545 _cache[n] = ((-1)**(n//2))*(suma // 2**n) 

546 if n == m: 

547 return ((-1)**(n//2))*suma // 2**n 

548 

549def stirling1(n, k): 

550 """ 

551 Stirling number of the first kind. 

552 """ 

553 if n < 0 or k < 0: 

554 raise ValueError 

555 if k >= n: 

556 return MPZ(n == k) 

557 if k < 1: 

558 return MPZ_ZERO 

559 L = [MPZ_ZERO] * (k+1) 

560 L[1] = MPZ_ONE 

561 for m in xrange(2, n+1): 

562 for j in xrange(min(k, m), 0, -1): 

563 L[j] = (m-1) * L[j] + L[j-1] 

564 return (-1)**(n+k) * L[k] 

565 

566def stirling2(n, k): 

567 """ 

568 Stirling number of the second kind. 

569 """ 

570 if n < 0 or k < 0: 

571 raise ValueError 

572 if k >= n: 

573 return MPZ(n == k) 

574 if k <= 1: 

575 return MPZ(k == 1) 

576 s = MPZ_ZERO 

577 t = MPZ_ONE 

578 for j in xrange(k+1): 

579 if (k + j) & 1: 

580 s -= t * MPZ(j)**n 

581 else: 

582 s += t * MPZ(j)**n 

583 t = t * (k - j) // (j + 1) 

584 return s // ifac(k)