1
+ from decimal import Decimal , getcontext
2
+ import json
3
+ import subprocess
4
+ import hypothesis
5
+ from hypothesis import given , settings
6
+ from hypothesis .strategies import decimals , integers , tuples
7
+ from mpmath import mp
8
+ import pytest
9
+
10
+ mp .prec = 500
11
+ getcontext ().prec = 14
12
+
13
+ node = subprocess .Popen (
14
+ ["node" , "evaluate.mjs" ], stdout = subprocess .PIPE , stdin = subprocess .PIPE
15
+ )
16
+
17
+
18
+ def get_decimal (func : str , args : list , config : dict ):
19
+ arg = json .dumps ({"func" : func , "args" : args , "config" : config }).encode () + b"\r "
20
+ node .stdin .write (arg )
21
+ node .stdin .flush ()
22
+ return Decimal (node .stdout .readline ().strip ().decode ())
23
+
24
+
25
+ def assert_matches (x , mpfunc , jsfunc = None ):
26
+ if jsfunc is None :
27
+ jsfunc = mpfunc
28
+ y = Decimal (str (getattr (mp , mpfunc )(x ))) * Decimal ("1.0" )
29
+ z = get_decimal (jsfunc , [str (x )], {"precision" : 14 })
30
+ assert y == z
31
+
32
+
33
+ @pytest .mark .parametrize ("fn" , "sin cos tan atan asinh" .split ())
34
+ @given (
35
+ x = tuples (
36
+ decimals (
37
+ allow_nan = False , allow_infinity = False , min_value = - 1 , max_value = 1 , places = 14
38
+ ),
39
+ integers (min_value = - 99 , max_value = 99 ),
40
+ ).map (lambda tup : tup [0 ] * Decimal (10 ) ** tup [1 ])
41
+ )
42
+ @settings (max_examples = 100_000 )
43
+ def test_matches (x , fn ):
44
+ assert_matches (x , fn )
45
+
46
+
47
+ @pytest .mark .parametrize ("fn" , "ln log10 sqrt" .split ())
48
+ @given (
49
+ x = tuples (
50
+ decimals (
51
+ allow_nan = False ,
52
+ allow_infinity = False ,
53
+ min_value = 1e-13 ,
54
+ max_value = 1 ,
55
+ places = 14 ,
56
+ ),
57
+ integers (min_value = - 99 , max_value = 99 ),
58
+ ).map (lambda tup : tup [0 ] * Decimal (10 ) ** tup [1 ])
59
+ )
60
+ @settings (max_examples = 100_000 )
61
+ def test_positive_domain (x , fn ):
62
+ assert_matches (x , fn )
63
+
64
+
65
+ @pytest .mark .parametrize ("fn" , "asin acos atanh" .split ())
66
+ @given (
67
+ x = decimals (
68
+ allow_nan = False , allow_infinity = False , min_value = - 1 , max_value = 1 , places = 14
69
+ )
70
+ )
71
+ @settings (max_examples = 100_000 )
72
+ def test_inverse_trig (x , fn ):
73
+ assert_matches (x , fn )
74
+
75
+
76
+ @pytest .mark .parametrize ("fn" , "sinh cosh tanh exp" .split ())
77
+ @given (
78
+ x = tuples (
79
+ decimals (
80
+ allow_nan = False , allow_infinity = False , min_value = - 1 , max_value = 1 , places = 14
81
+ ),
82
+ integers (min_value = - 99 , max_value = 3 ),
83
+ ).map (lambda tup : tup [0 ] * Decimal (10 ) ** tup [1 ])
84
+ )
85
+ @settings (max_examples = 100_000 )
86
+ def test_small_domain (x , fn ):
87
+ assert_matches (x , fn )
88
+
89
+ @given (
90
+ x = tuples (
91
+ decimals (
92
+ allow_nan = False , allow_infinity = False , min_value = 1 , max_value = 10 , places = 14
93
+ ),
94
+ integers (min_value = 0 , max_value = 99 ),
95
+ ).map (lambda tup : tup [0 ] * Decimal (10 ) ** tup [1 ])
96
+ )
97
+ @settings (max_examples = 100_000 )
98
+ def test_acosh (x ):
99
+ assert_matches (x , 'acosh' )
0 commit comments