78 lines
2.3 KiB
Python
78 lines
2.3 KiB
Python
|
from mpmath import *
|
||
|
from random import seed, randint, random
|
||
|
import math
|
||
|
|
||
|
# Test compatibility with Python floats, which are
|
||
|
# IEEE doubles (53-bit)
|
||
|
|
||
|
N = 5000
|
||
|
seed(1)
|
||
|
|
||
|
# Choosing exponents between roughly -140, 140 ensures that
|
||
|
# the Python floats don't overflow or underflow
|
||
|
xs = [(random()-1) * 10**randint(-140, 140) for x in range(N)]
|
||
|
ys = [(random()-1) * 10**randint(-140, 140) for x in range(N)]
|
||
|
|
||
|
# include some equal values
|
||
|
ys[int(N*0.8):] = xs[int(N*0.8):]
|
||
|
|
||
|
# Detect whether Python is compiled to use 80-bit floating-point
|
||
|
# instructions, in which case the double compatibility test breaks
|
||
|
uses_x87 = -4.1974624032366689e+117 / -8.4657370748010221e-47 \
|
||
|
== 4.9581771393902231e+163
|
||
|
|
||
|
def test_double_compatibility():
|
||
|
mp.prec = 53
|
||
|
for x, y in zip(xs, ys):
|
||
|
mpx = mpf(x)
|
||
|
mpy = mpf(y)
|
||
|
assert mpf(x) == x
|
||
|
assert (mpx < mpy) == (x < y)
|
||
|
assert (mpx > mpy) == (x > y)
|
||
|
assert (mpx == mpy) == (x == y)
|
||
|
assert (mpx != mpy) == (x != y)
|
||
|
assert (mpx <= mpy) == (x <= y)
|
||
|
assert (mpx >= mpy) == (x >= y)
|
||
|
assert mpx == mpx
|
||
|
if uses_x87:
|
||
|
mp.prec = 64
|
||
|
a = mpx + mpy
|
||
|
b = mpx * mpy
|
||
|
c = mpx / mpy
|
||
|
d = mpx % mpy
|
||
|
mp.prec = 53
|
||
|
assert +a == x + y
|
||
|
assert +b == x * y
|
||
|
assert +c == x / y
|
||
|
assert +d == x % y
|
||
|
else:
|
||
|
assert mpx + mpy == x + y
|
||
|
assert mpx * mpy == x * y
|
||
|
assert mpx / mpy == x / y
|
||
|
assert mpx % mpy == x % y
|
||
|
assert abs(mpx) == abs(x)
|
||
|
assert mpf(repr(x)) == x
|
||
|
assert ceil(mpx) == math.ceil(x)
|
||
|
assert floor(mpx) == math.floor(x)
|
||
|
|
||
|
def test_sqrt():
|
||
|
# this fails quite often. it appers to be float
|
||
|
# that rounds the wrong way, not mpf
|
||
|
fail = 0
|
||
|
mp.prec = 53
|
||
|
for x in xs:
|
||
|
x = abs(x)
|
||
|
mp.prec = 100
|
||
|
mp_high = mpf(x)**0.5
|
||
|
mp.prec = 53
|
||
|
mp_low = mpf(x)**0.5
|
||
|
fp = x**0.5
|
||
|
assert abs(mp_low-mp_high) <= abs(fp-mp_high)
|
||
|
fail += mp_low != fp
|
||
|
assert fail < N/10
|
||
|
|
||
|
def test_bugs():
|
||
|
# particular bugs
|
||
|
assert mpf(4.4408920985006262E-16) < mpf(1.7763568394002505E-15)
|
||
|
assert mpf(-4.4408920985006262E-16) > mpf(-1.7763568394002505E-15)
|