test_power.py 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. from mpmath import *
  2. from mpmath.libmp import *
  3. import random
  4. def test_fractional_pow():
  5. mp.dps = 15
  6. assert mpf(16) ** 2.5 == 1024
  7. assert mpf(64) ** 0.5 == 8
  8. assert mpf(64) ** -0.5 == 0.125
  9. assert mpf(16) ** -2.5 == 0.0009765625
  10. assert (mpf(10) ** 0.5).ae(3.1622776601683791)
  11. assert (mpf(10) ** 2.5).ae(316.2277660168379)
  12. assert (mpf(10) ** -0.5).ae(0.31622776601683794)
  13. assert (mpf(10) ** -2.5).ae(0.0031622776601683794)
  14. assert (mpf(10) ** 0.3).ae(1.9952623149688795)
  15. assert (mpf(10) ** -0.3).ae(0.50118723362727224)
  16. def test_pow_integer_direction():
  17. """
  18. Test that inexact integer powers are rounded in the right
  19. direction.
  20. """
  21. random.seed(1234)
  22. for prec in [10, 53, 200]:
  23. for i in range(50):
  24. a = random.randint(1<<(prec-1), 1<<prec)
  25. b = random.randint(2, 100)
  26. ab = a**b
  27. # note: could actually be exact, but that's very unlikely!
  28. assert to_int(mpf_pow(from_int(a), from_int(b), prec, round_down)) < ab
  29. assert to_int(mpf_pow(from_int(a), from_int(b), prec, round_up)) > ab
  30. def test_pow_epsilon_rounding():
  31. """
  32. Stress test directed rounding for powers with integer exponents.
  33. Basically, we look at the following cases:
  34. >>> 1.0001 ** -5 # doctest: +SKIP
  35. 0.99950014996500702
  36. >>> 0.9999 ** -5 # doctest: +SKIP
  37. 1.000500150035007
  38. >>> (-1.0001) ** -5 # doctest: +SKIP
  39. -0.99950014996500702
  40. >>> (-0.9999) ** -5 # doctest: +SKIP
  41. -1.000500150035007
  42. >>> 1.0001 ** -6 # doctest: +SKIP
  43. 0.99940020994401269
  44. >>> 0.9999 ** -6 # doctest: +SKIP
  45. 1.0006002100560125
  46. >>> (-1.0001) ** -6 # doctest: +SKIP
  47. 0.99940020994401269
  48. >>> (-0.9999) ** -6 # doctest: +SKIP
  49. 1.0006002100560125
  50. etc.
  51. We run the tests with values a very small epsilon away from 1:
  52. small enough that the result is indistinguishable from 1 when
  53. rounded to nearest at the output precision. We check that the
  54. result is not erroneously rounded to 1 in cases where the
  55. rounding should be done strictly away from 1.
  56. """
  57. def powr(x, n, r):
  58. return make_mpf(mpf_pow_int(x._mpf_, n, mp.prec, r))
  59. for (inprec, outprec) in [(100, 20), (5000, 3000)]:
  60. mp.prec = inprec
  61. pos10001 = mpf(1) + mpf(2)**(-inprec+5)
  62. pos09999 = mpf(1) - mpf(2)**(-inprec+5)
  63. neg10001 = -pos10001
  64. neg09999 = -pos09999
  65. mp.prec = outprec
  66. r = round_up
  67. assert powr(pos10001, 5, r) > 1
  68. assert powr(pos09999, 5, r) == 1
  69. assert powr(neg10001, 5, r) < -1
  70. assert powr(neg09999, 5, r) == -1
  71. assert powr(pos10001, 6, r) > 1
  72. assert powr(pos09999, 6, r) == 1
  73. assert powr(neg10001, 6, r) > 1
  74. assert powr(neg09999, 6, r) == 1
  75. assert powr(pos10001, -5, r) == 1
  76. assert powr(pos09999, -5, r) > 1
  77. assert powr(neg10001, -5, r) == -1
  78. assert powr(neg09999, -5, r) < -1
  79. assert powr(pos10001, -6, r) == 1
  80. assert powr(pos09999, -6, r) > 1
  81. assert powr(neg10001, -6, r) == 1
  82. assert powr(neg09999, -6, r) > 1
  83. r = round_down
  84. assert powr(pos10001, 5, r) == 1
  85. assert powr(pos09999, 5, r) < 1
  86. assert powr(neg10001, 5, r) == -1
  87. assert powr(neg09999, 5, r) > -1
  88. assert powr(pos10001, 6, r) == 1
  89. assert powr(pos09999, 6, r) < 1
  90. assert powr(neg10001, 6, r) == 1
  91. assert powr(neg09999, 6, r) < 1
  92. assert powr(pos10001, -5, r) < 1
  93. assert powr(pos09999, -5, r) == 1
  94. assert powr(neg10001, -5, r) > -1
  95. assert powr(neg09999, -5, r) == -1
  96. assert powr(pos10001, -6, r) < 1
  97. assert powr(pos09999, -6, r) == 1
  98. assert powr(neg10001, -6, r) < 1
  99. assert powr(neg09999, -6, r) == 1
  100. r = round_ceiling
  101. assert powr(pos10001, 5, r) > 1
  102. assert powr(pos09999, 5, r) == 1
  103. assert powr(neg10001, 5, r) == -1
  104. assert powr(neg09999, 5, r) > -1
  105. assert powr(pos10001, 6, r) > 1
  106. assert powr(pos09999, 6, r) == 1
  107. assert powr(neg10001, 6, r) > 1
  108. assert powr(neg09999, 6, r) == 1
  109. assert powr(pos10001, -5, r) == 1
  110. assert powr(pos09999, -5, r) > 1
  111. assert powr(neg10001, -5, r) > -1
  112. assert powr(neg09999, -5, r) == -1
  113. assert powr(pos10001, -6, r) == 1
  114. assert powr(pos09999, -6, r) > 1
  115. assert powr(neg10001, -6, r) == 1
  116. assert powr(neg09999, -6, r) > 1
  117. r = round_floor
  118. assert powr(pos10001, 5, r) == 1
  119. assert powr(pos09999, 5, r) < 1
  120. assert powr(neg10001, 5, r) < -1
  121. assert powr(neg09999, 5, r) == -1
  122. assert powr(pos10001, 6, r) == 1
  123. assert powr(pos09999, 6, r) < 1
  124. assert powr(neg10001, 6, r) == 1
  125. assert powr(neg09999, 6, r) < 1
  126. assert powr(pos10001, -5, r) < 1
  127. assert powr(pos09999, -5, r) == 1
  128. assert powr(neg10001, -5, r) == -1
  129. assert powr(neg09999, -5, r) < -1
  130. assert powr(pos10001, -6, r) < 1
  131. assert powr(pos09999, -6, r) == 1
  132. assert powr(neg10001, -6, r) < 1
  133. assert powr(neg09999, -6, r) == 1
  134. mp.dps = 15