2023-02-13 04:08:43 +00:00
|
|
|
from decimal import Decimal, getcontext
|
|
|
|
import json
|
|
|
|
import subprocess
|
|
|
|
import hypothesis
|
|
|
|
from hypothesis import given, settings
|
|
|
|
from hypothesis.strategies import decimals, integers, tuples
|
|
|
|
from mpmath import mp
|
2023-02-13 06:44:14 +00:00
|
|
|
import pytest
|
2023-02-13 04:08:43 +00:00
|
|
|
|
|
|
|
mp.prec = 500
|
2023-02-13 06:44:14 +00:00
|
|
|
getcontext().prec = 14
|
2023-02-13 04:08:43 +00:00
|
|
|
|
|
|
|
node = subprocess.Popen(
|
|
|
|
["node", "evaluate.mjs"], stdout=subprocess.PIPE, stdin=subprocess.PIPE
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
def get_decimal(func: str, args: list, config: dict):
|
|
|
|
arg = json.dumps({"func": func, "args": args, "config": config}).encode() + b"\r"
|
|
|
|
node.stdin.write(arg)
|
|
|
|
node.stdin.flush()
|
|
|
|
return Decimal(node.stdout.readline().strip().decode())
|
|
|
|
|
|
|
|
|
2023-02-13 06:44:14 +00:00
|
|
|
def assert_matches(x, mpfunc, jsfunc=None):
|
|
|
|
if jsfunc is None:
|
|
|
|
jsfunc = mpfunc
|
|
|
|
y = Decimal(str(getattr(mp, mpfunc)(x))) * Decimal("1.0")
|
|
|
|
z = get_decimal(jsfunc, [str(x)], {"precision": 14})
|
2023-02-13 04:08:43 +00:00
|
|
|
assert y == z
|
|
|
|
|
|
|
|
|
2023-02-13 07:18:42 +00:00
|
|
|
@pytest.mark.parametrize("fn", "sin cos tan atan asinh".split())
|
2023-02-13 06:44:14 +00:00
|
|
|
@given(
|
|
|
|
x=tuples(
|
|
|
|
decimals(
|
|
|
|
allow_nan=False, allow_infinity=False, min_value=-1, max_value=1, places=14
|
|
|
|
),
|
|
|
|
integers(min_value=-99, max_value=99),
|
|
|
|
).map(lambda tup: tup[0] * Decimal(10) ** tup[1])
|
2023-02-13 04:08:43 +00:00
|
|
|
)
|
2023-02-13 06:56:56 +00:00
|
|
|
@settings(max_examples=1000)
|
2023-02-13 06:44:14 +00:00
|
|
|
def test_matches(x, fn):
|
|
|
|
assert_matches(x, fn)
|
|
|
|
|
|
|
|
|
2023-02-13 06:56:56 +00:00
|
|
|
@pytest.mark.parametrize("fn", "ln log10 sqrt".split())
|
2023-02-13 06:44:14 +00:00
|
|
|
@given(
|
|
|
|
x=tuples(
|
|
|
|
decimals(
|
|
|
|
allow_nan=False,
|
|
|
|
allow_infinity=False,
|
|
|
|
min_value=1e-13,
|
|
|
|
max_value=1,
|
|
|
|
places=14,
|
|
|
|
),
|
|
|
|
integers(min_value=-99, max_value=99),
|
|
|
|
).map(lambda tup: tup[0] * Decimal(10) ** tup[1])
|
|
|
|
)
|
2023-02-13 06:56:56 +00:00
|
|
|
@settings(max_examples=1000)
|
2023-02-13 06:44:14 +00:00
|
|
|
def test_positive_domain(x, fn):
|
|
|
|
assert_matches(x, fn)
|
2023-02-13 04:08:43 +00:00
|
|
|
|
|
|
|
|
2023-02-13 07:18:42 +00:00
|
|
|
@pytest.mark.parametrize("fn", "asin acos atanh".split())
|
2023-02-13 06:44:14 +00:00
|
|
|
@given(
|
|
|
|
x=decimals(
|
|
|
|
allow_nan=False, allow_infinity=False, min_value=-1, max_value=1, places=14
|
|
|
|
)
|
|
|
|
)
|
2023-02-13 06:56:56 +00:00
|
|
|
@settings(max_examples=1000)
|
2023-02-13 06:44:14 +00:00
|
|
|
def test_inverse_trig(x, fn):
|
|
|
|
assert_matches(x, fn)
|
|
|
|
|
|
|
|
|
2023-02-13 06:56:56 +00:00
|
|
|
@pytest.mark.parametrize("fn", "sinh cosh tanh exp".split())
|
2023-02-13 06:44:14 +00:00
|
|
|
@given(
|
|
|
|
x=tuples(
|
|
|
|
decimals(
|
|
|
|
allow_nan=False, allow_infinity=False, min_value=-1, max_value=1, places=14
|
|
|
|
),
|
|
|
|
integers(min_value=-99, max_value=3),
|
|
|
|
).map(lambda tup: tup[0] * Decimal(10) ** tup[1])
|
|
|
|
)
|
2023-02-13 06:56:56 +00:00
|
|
|
@settings(max_examples=1000)
|
2023-02-13 06:44:14 +00:00
|
|
|
def test_small_domain(x, fn):
|
|
|
|
assert_matches(x, fn)
|
2023-02-13 07:18:42 +00:00
|
|
|
|
|
|
|
@given(
|
|
|
|
x=tuples(
|
|
|
|
decimals(
|
|
|
|
allow_nan=False, allow_infinity=False, min_value=1, max_value=10, places=14
|
|
|
|
),
|
|
|
|
integers(min_value=0, max_value=99),
|
|
|
|
).map(lambda tup: tup[0] * Decimal(10) ** tup[1])
|
|
|
|
)
|
|
|
|
@settings(max_examples=1000)
|
2023-02-13 08:19:39 +00:00
|
|
|
def test_acosh(x):
|
2023-02-13 07:18:42 +00:00
|
|
|
assert_matches(x, 'acosh')
|