| | from mpmath import * |
| | from mpmath.libmp import * |
| |
|
| | import random |
| |
|
| | def test_fractional_pow(): |
| | mp.dps = 15 |
| | assert mpf(16) ** 2.5 == 1024 |
| | assert mpf(64) ** 0.5 == 8 |
| | assert mpf(64) ** -0.5 == 0.125 |
| | assert mpf(16) ** -2.5 == 0.0009765625 |
| | assert (mpf(10) ** 0.5).ae(3.1622776601683791) |
| | assert (mpf(10) ** 2.5).ae(316.2277660168379) |
| | assert (mpf(10) ** -0.5).ae(0.31622776601683794) |
| | assert (mpf(10) ** -2.5).ae(0.0031622776601683794) |
| | assert (mpf(10) ** 0.3).ae(1.9952623149688795) |
| | assert (mpf(10) ** -0.3).ae(0.50118723362727224) |
| |
|
| | def test_pow_integer_direction(): |
| | """ |
| | Test that inexact integer powers are rounded in the right |
| | direction. |
| | """ |
| | random.seed(1234) |
| | for prec in [10, 53, 200]: |
| | for i in range(50): |
| | a = random.randint(1<<(prec-1), 1<<prec) |
| | b = random.randint(2, 100) |
| | ab = a**b |
| | |
| | assert to_int(mpf_pow(from_int(a), from_int(b), prec, round_down)) < ab |
| | assert to_int(mpf_pow(from_int(a), from_int(b), prec, round_up)) > ab |
| |
|
| |
|
| | def test_pow_epsilon_rounding(): |
| | """ |
| | Stress test directed rounding for powers with integer exponents. |
| | Basically, we look at the following cases: |
| | |
| | >>> 1.0001 ** -5 # doctest: +SKIP |
| | 0.99950014996500702 |
| | >>> 0.9999 ** -5 # doctest: +SKIP |
| | 1.000500150035007 |
| | >>> (-1.0001) ** -5 # doctest: +SKIP |
| | -0.99950014996500702 |
| | >>> (-0.9999) ** -5 # doctest: +SKIP |
| | -1.000500150035007 |
| | |
| | >>> 1.0001 ** -6 # doctest: +SKIP |
| | 0.99940020994401269 |
| | >>> 0.9999 ** -6 # doctest: +SKIP |
| | 1.0006002100560125 |
| | >>> (-1.0001) ** -6 # doctest: +SKIP |
| | 0.99940020994401269 |
| | >>> (-0.9999) ** -6 # doctest: +SKIP |
| | 1.0006002100560125 |
| | |
| | etc. |
| | |
| | We run the tests with values a very small epsilon away from 1: |
| | small enough that the result is indistinguishable from 1 when |
| | rounded to nearest at the output precision. We check that the |
| | result is not erroneously rounded to 1 in cases where the |
| | rounding should be done strictly away from 1. |
| | """ |
| |
|
| | def powr(x, n, r): |
| | return make_mpf(mpf_pow_int(x._mpf_, n, mp.prec, r)) |
| |
|
| | for (inprec, outprec) in [(100, 20), (5000, 3000)]: |
| |
|
| | mp.prec = inprec |
| |
|
| | pos10001 = mpf(1) + mpf(2)**(-inprec+5) |
| | pos09999 = mpf(1) - mpf(2)**(-inprec+5) |
| | neg10001 = -pos10001 |
| | neg09999 = -pos09999 |
| |
|
| | mp.prec = outprec |
| | r = round_up |
| | assert powr(pos10001, 5, r) > 1 |
| | assert powr(pos09999, 5, r) == 1 |
| | assert powr(neg10001, 5, r) < -1 |
| | assert powr(neg09999, 5, r) == -1 |
| | assert powr(pos10001, 6, r) > 1 |
| | assert powr(pos09999, 6, r) == 1 |
| | assert powr(neg10001, 6, r) > 1 |
| | assert powr(neg09999, 6, r) == 1 |
| |
|
| | assert powr(pos10001, -5, r) == 1 |
| | assert powr(pos09999, -5, r) > 1 |
| | assert powr(neg10001, -5, r) == -1 |
| | assert powr(neg09999, -5, r) < -1 |
| | assert powr(pos10001, -6, r) == 1 |
| | assert powr(pos09999, -6, r) > 1 |
| | assert powr(neg10001, -6, r) == 1 |
| | assert powr(neg09999, -6, r) > 1 |
| |
|
| | r = round_down |
| | assert powr(pos10001, 5, r) == 1 |
| | assert powr(pos09999, 5, r) < 1 |
| | assert powr(neg10001, 5, r) == -1 |
| | assert powr(neg09999, 5, r) > -1 |
| | assert powr(pos10001, 6, r) == 1 |
| | assert powr(pos09999, 6, r) < 1 |
| | assert powr(neg10001, 6, r) == 1 |
| | assert powr(neg09999, 6, r) < 1 |
| |
|
| | assert powr(pos10001, -5, r) < 1 |
| | assert powr(pos09999, -5, r) == 1 |
| | assert powr(neg10001, -5, r) > -1 |
| | assert powr(neg09999, -5, r) == -1 |
| | assert powr(pos10001, -6, r) < 1 |
| | assert powr(pos09999, -6, r) == 1 |
| | assert powr(neg10001, -6, r) < 1 |
| | assert powr(neg09999, -6, r) == 1 |
| |
|
| | r = round_ceiling |
| | assert powr(pos10001, 5, r) > 1 |
| | assert powr(pos09999, 5, r) == 1 |
| | assert powr(neg10001, 5, r) == -1 |
| | assert powr(neg09999, 5, r) > -1 |
| | assert powr(pos10001, 6, r) > 1 |
| | assert powr(pos09999, 6, r) == 1 |
| | assert powr(neg10001, 6, r) > 1 |
| | assert powr(neg09999, 6, r) == 1 |
| |
|
| | assert powr(pos10001, -5, r) == 1 |
| | assert powr(pos09999, -5, r) > 1 |
| | assert powr(neg10001, -5, r) > -1 |
| | assert powr(neg09999, -5, r) == -1 |
| | assert powr(pos10001, -6, r) == 1 |
| | assert powr(pos09999, -6, r) > 1 |
| | assert powr(neg10001, -6, r) == 1 |
| | assert powr(neg09999, -6, r) > 1 |
| |
|
| | r = round_floor |
| | assert powr(pos10001, 5, r) == 1 |
| | assert powr(pos09999, 5, r) < 1 |
| | assert powr(neg10001, 5, r) < -1 |
| | assert powr(neg09999, 5, r) == -1 |
| | assert powr(pos10001, 6, r) == 1 |
| | assert powr(pos09999, 6, r) < 1 |
| | assert powr(neg10001, 6, r) == 1 |
| | assert powr(neg09999, 6, r) < 1 |
| |
|
| | assert powr(pos10001, -5, r) < 1 |
| | assert powr(pos09999, -5, r) == 1 |
| | assert powr(neg10001, -5, r) == -1 |
| | assert powr(neg09999, -5, r) < -1 |
| | assert powr(pos10001, -6, r) < 1 |
| | assert powr(pos09999, -6, r) == 1 |
| | assert powr(neg10001, -6, r) < 1 |
| | assert powr(neg09999, -6, r) == 1 |
| |
|
| | mp.dps = 15 |
| |
|