test_compatibility.py 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. from mpmath import *
  2. from random import seed, randint, random
  3. import math
  4. # Test compatibility with Python floats, which are
  5. # IEEE doubles (53-bit)
  6. N = 5000
  7. seed(1)
  8. # Choosing exponents between roughly -140, 140 ensures that
  9. # the Python floats don't overflow or underflow
  10. xs = [(random()-1) * 10**randint(-140, 140) for x in range(N)]
  11. ys = [(random()-1) * 10**randint(-140, 140) for x in range(N)]
  12. # include some equal values
  13. ys[int(N*0.8):] = xs[int(N*0.8):]
  14. # Detect whether Python is compiled to use 80-bit floating-point
  15. # instructions, in which case the double compatibility test breaks
  16. uses_x87 = -4.1974624032366689e+117 / -8.4657370748010221e-47 \
  17. == 4.9581771393902231e+163
  18. def test_double_compatibility():
  19. mp.prec = 53
  20. for x, y in zip(xs, ys):
  21. mpx = mpf(x)
  22. mpy = mpf(y)
  23. assert mpf(x) == x
  24. assert (mpx < mpy) == (x < y)
  25. assert (mpx > mpy) == (x > y)
  26. assert (mpx == mpy) == (x == y)
  27. assert (mpx != mpy) == (x != y)
  28. assert (mpx <= mpy) == (x <= y)
  29. assert (mpx >= mpy) == (x >= y)
  30. assert mpx == mpx
  31. if uses_x87:
  32. mp.prec = 64
  33. a = mpx + mpy
  34. b = mpx * mpy
  35. c = mpx / mpy
  36. d = mpx % mpy
  37. mp.prec = 53
  38. assert +a == x + y
  39. assert +b == x * y
  40. assert +c == x / y
  41. assert +d == x % y
  42. else:
  43. assert mpx + mpy == x + y
  44. assert mpx * mpy == x * y
  45. assert mpx / mpy == x / y
  46. assert mpx % mpy == x % y
  47. assert abs(mpx) == abs(x)
  48. assert mpf(repr(x)) == x
  49. assert ceil(mpx) == math.ceil(x)
  50. assert floor(mpx) == math.floor(x)
  51. def test_sqrt():
  52. # this fails quite often. it appers to be float
  53. # that rounds the wrong way, not mpf
  54. fail = 0
  55. mp.prec = 53
  56. for x in xs:
  57. x = abs(x)
  58. mp.prec = 100
  59. mp_high = mpf(x)**0.5
  60. mp.prec = 53
  61. mp_low = mpf(x)**0.5
  62. fp = x**0.5
  63. assert abs(mp_low-mp_high) <= abs(fp-mp_high)
  64. fail += mp_low != fp
  65. assert fail < N/10
  66. def test_bugs():
  67. # particular bugs
  68. assert mpf(4.4408920985006262E-16) < mpf(1.7763568394002505E-15)
  69. assert mpf(-4.4408920985006262E-16) > mpf(-1.7763568394002505E-15)