test_division.py 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. from mpmath.libmp import *
  2. from mpmath import mpf, mp
  3. from random import randint, choice, seed
  4. all_modes = [round_floor, round_ceiling, round_down, round_up, round_nearest]
  5. fb = from_bstr
  6. fi = from_int
  7. ff = from_float
  8. def test_div_1_3():
  9. a = fi(1)
  10. b = fi(3)
  11. c = fi(-1)
  12. # floor rounds down, ceiling rounds up
  13. assert mpf_div(a, b, 7, round_floor) == fb('0.01010101')
  14. assert mpf_div(a, b, 7, round_ceiling) == fb('0.01010110')
  15. assert mpf_div(a, b, 7, round_down) == fb('0.01010101')
  16. assert mpf_div(a, b, 7, round_up) == fb('0.01010110')
  17. assert mpf_div(a, b, 7, round_nearest) == fb('0.01010101')
  18. # floor rounds up, ceiling rounds down
  19. assert mpf_div(c, b, 7, round_floor) == fb('-0.01010110')
  20. assert mpf_div(c, b, 7, round_ceiling) == fb('-0.01010101')
  21. assert mpf_div(c, b, 7, round_down) == fb('-0.01010101')
  22. assert mpf_div(c, b, 7, round_up) == fb('-0.01010110')
  23. assert mpf_div(c, b, 7, round_nearest) == fb('-0.01010101')
  24. def test_mpf_divi_1_3():
  25. a = 1
  26. b = fi(3)
  27. c = -1
  28. assert mpf_rdiv_int(a, b, 7, round_floor) == fb('0.01010101')
  29. assert mpf_rdiv_int(a, b, 7, round_ceiling) == fb('0.01010110')
  30. assert mpf_rdiv_int(a, b, 7, round_down) == fb('0.01010101')
  31. assert mpf_rdiv_int(a, b, 7, round_up) == fb('0.01010110')
  32. assert mpf_rdiv_int(a, b, 7, round_nearest) == fb('0.01010101')
  33. assert mpf_rdiv_int(c, b, 7, round_floor) == fb('-0.01010110')
  34. assert mpf_rdiv_int(c, b, 7, round_ceiling) == fb('-0.01010101')
  35. assert mpf_rdiv_int(c, b, 7, round_down) == fb('-0.01010101')
  36. assert mpf_rdiv_int(c, b, 7, round_up) == fb('-0.01010110')
  37. assert mpf_rdiv_int(c, b, 7, round_nearest) == fb('-0.01010101')
  38. def test_div_300():
  39. q = fi(1000000)
  40. a = fi(300499999) # a/q is a little less than a half-integer
  41. b = fi(300500000) # b/q exactly a half-integer
  42. c = fi(300500001) # c/q is a little more than a half-integer
  43. # Check nearest integer rounding (prec=9 as 2**8 < 300 < 2**9)
  44. assert mpf_div(a, q, 9, round_down) == fi(300)
  45. assert mpf_div(b, q, 9, round_down) == fi(300)
  46. assert mpf_div(c, q, 9, round_down) == fi(300)
  47. assert mpf_div(a, q, 9, round_up) == fi(301)
  48. assert mpf_div(b, q, 9, round_up) == fi(301)
  49. assert mpf_div(c, q, 9, round_up) == fi(301)
  50. # Nearest even integer is down
  51. assert mpf_div(a, q, 9, round_nearest) == fi(300)
  52. assert mpf_div(b, q, 9, round_nearest) == fi(300)
  53. assert mpf_div(c, q, 9, round_nearest) == fi(301)
  54. # Nearest even integer is up
  55. a = fi(301499999)
  56. b = fi(301500000)
  57. c = fi(301500001)
  58. assert mpf_div(a, q, 9, round_nearest) == fi(301)
  59. assert mpf_div(b, q, 9, round_nearest) == fi(302)
  60. assert mpf_div(c, q, 9, round_nearest) == fi(302)
  61. def test_tight_integer_division():
  62. # Test that integer division at tightest possible precision is exact
  63. N = 100
  64. seed(1)
  65. for i in range(N):
  66. a = choice([1, -1]) * randint(1, 1<<randint(10, 100))
  67. b = choice([1, -1]) * randint(1, 1<<randint(10, 100))
  68. p = a * b
  69. width = bitcount(abs(b)) - trailing(b)
  70. a = fi(a); b = fi(b); p = fi(p)
  71. for mode in all_modes:
  72. assert mpf_div(p, a, width, mode) == b
  73. def test_epsilon_rounding():
  74. # Verify that mpf_div uses infinite precision; this result will
  75. # appear to be exactly 0.101 to a near-sighted algorithm
  76. a = fb('0.101' + ('0'*200) + '1')
  77. b = fb('1.10101')
  78. c = mpf_mul(a, b, 250, round_floor) # exact
  79. assert mpf_div(c, b, bitcount(a[1]), round_floor) == a # exact
  80. assert mpf_div(c, b, 2, round_down) == fb('0.10')
  81. assert mpf_div(c, b, 3, round_down) == fb('0.101')
  82. assert mpf_div(c, b, 2, round_up) == fb('0.11')
  83. assert mpf_div(c, b, 3, round_up) == fb('0.110')
  84. assert mpf_div(c, b, 2, round_floor) == fb('0.10')
  85. assert mpf_div(c, b, 3, round_floor) == fb('0.101')
  86. assert mpf_div(c, b, 2, round_ceiling) == fb('0.11')
  87. assert mpf_div(c, b, 3, round_ceiling) == fb('0.110')
  88. # The same for negative numbers
  89. a = fb('-0.101' + ('0'*200) + '1')
  90. b = fb('1.10101')
  91. c = mpf_mul(a, b, 250, round_floor)
  92. assert mpf_div(c, b, bitcount(a[1]), round_floor) == a
  93. assert mpf_div(c, b, 2, round_down) == fb('-0.10')
  94. assert mpf_div(c, b, 3, round_up) == fb('-0.110')
  95. # Floor goes up, ceiling goes down
  96. assert mpf_div(c, b, 2, round_floor) == fb('-0.11')
  97. assert mpf_div(c, b, 3, round_floor) == fb('-0.110')
  98. assert mpf_div(c, b, 2, round_ceiling) == fb('-0.10')
  99. assert mpf_div(c, b, 3, round_ceiling) == fb('-0.101')
  100. def test_mod():
  101. mp.dps = 15
  102. assert mpf(234) % 1 == 0
  103. assert mpf(-3) % 256 == 253
  104. assert mpf(0.25) % 23490.5 == 0.25
  105. assert mpf(0.25) % -23490.5 == -23490.25
  106. assert mpf(-0.25) % 23490.5 == 23490.25
  107. assert mpf(-0.25) % -23490.5 == -0.25
  108. # Check that these cases are handled efficiently
  109. assert mpf('1e10000000000') % 1 == 0
  110. assert mpf('1.23e-1000000000') % 1 == mpf('1.23e-1000000000')
  111. # test __rmod__
  112. assert 3 % mpf('1.75') == 1.25
  113. def test_div_negative_rnd_bug():
  114. mp.dps = 15
  115. assert (-3) / mpf('0.1531879017645047') == mpf('-19.583791966887116')
  116. assert mpf('-2.6342475750861301') / mpf('0.35126216427941814') == mpf('-7.4993775104985909')