From 075521e8a036f6738f12156f317112e129f6d616 Mon Sep 17 00:00:00 2001 From: Alden Date: Sun, 12 Feb 2023 23:02:53 -0500 Subject: [PATCH 01/13] a new failing test case --- test/modules/acos.js | 1 + 1 file changed, 1 insertion(+) diff --git a/test/modules/acos.js b/test/modules/acos.js index 66a9dbb..49bdc6d 100644 --- a/test/modules/acos.js +++ b/test/modules/acos.js @@ -68,6 +68,7 @@ T('acos', function () { t('0.41923186648524998285699814886092351368793359300547574', 42, 3, '1.13819724675000902666504291062053681280681'); t('-0.19508761025300975791021816036', 27, 1, '1.76714310275532020878366926'); t('0.0623252416', 19, 0, '1.508430664767542249'); + t('0.9999999297625', 14, 4, '0.00037479994883195'); /* t('0.95', 6, 5, '0.31756'); From 05c3fd3fae7b6045674f328b36f4d64d3d5f5394 Mon Sep 17 00:00:00 2001 From: Alden Date: Sun, 12 Feb 2023 23:08:43 -0500 Subject: [PATCH 02/13] test case finder --- test/hypothesis/.gitignore | 3 + test/hypothesis/error_hunt.py | 125 +++++++++++++++++++++++++++++++ test/hypothesis/evaluate.mjs | 26 +++++++ test/hypothesis/requirements.txt | 3 + 4 files changed, 157 insertions(+) create mode 100644 test/hypothesis/.gitignore create mode 100644 test/hypothesis/error_hunt.py create mode 100644 test/hypothesis/evaluate.mjs create mode 100644 test/hypothesis/requirements.txt diff --git a/test/hypothesis/.gitignore b/test/hypothesis/.gitignore new file mode 100644 index 0000000..6694234 --- /dev/null +++ b/test/hypothesis/.gitignore @@ -0,0 +1,3 @@ +__pycache__ +.hypothesis +.ipynb_checkpoints diff --git a/test/hypothesis/error_hunt.py b/test/hypothesis/error_hunt.py new file mode 100644 index 0000000..7d5e952 --- /dev/null +++ b/test/hypothesis/error_hunt.py @@ -0,0 +1,125 @@ +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 + +mp.prec = 500 + +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()) + + +def to_precision(x, precision=14): + getcontext().prec = precision + return Decimal(str(x)) * Decimal("1.0") + + +decimal_fixed_precision = 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]) + +decimal_positive = 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]) + + +@given(decimal_fixed_precision) +@settings(max_examples=100) +def test_tangent(x): + y = to_precision(mp.tan(x)) + z = get_decimal("tan", [str(x)], {"precision": 14}) + assert y == z + + +@given(decimal_fixed_precision) +@settings(max_examples=100) +def test_cosine(x): + y = to_precision(mp.cos(x)) + z = get_decimal("cos", [str(x)], {"precision": 14}) + assert y == z + + +@given(decimal_fixed_precision) +@settings(max_examples=100) +def test_sine(x): + y = to_precision(mp.sin(x)) + z = get_decimal("sin", [str(x)], {"precision": 14}) + assert y == z + + +@given(decimal_positive) +@settings(max_examples=100) +def test_log(x): + y = to_precision(mp.log10(x)) + z = get_decimal("log", [str(x)], {"precision": 14}) + assert y == z + + +inverse_trig_strat = decimals( + allow_nan=False, allow_infinity=False, min_value=-1, max_value=1, places=14 +) + + +@given(inverse_trig_strat) +@settings(max_examples=100) +def test_acos(x): + y = to_precision(mp.acos(x)) + z = get_decimal("acos", [str(x)], {"precision": 14}) + assert y == z + + +@given(inverse_trig_strat) +@settings(max_examples=100) +def test_asin(x): + y = to_precision(mp.asin(x)) + z = get_decimal("asin", [str(x)], {"precision": 14}) + assert y == z + + +@given(decimal_fixed_precision) +@settings(max_examples=100) +def test_atan(x): + y = to_precision(mp.atan(x)) + z = get_decimal("atan", [str(x)], {"precision": 14}) + assert y == z + + +@given(decimal_fixed_precision) +@settings(max_examples=10) +def test_cosh(x): + y = to_precision(mp.cosh(x)) + z = get_decimal("cosh", [str(x)], {"precision": 14}) + assert y == z + + +@given(decimal_fixed_precision) +@settings(max_examples=4) +def test_sinh(x): + y = to_precision(mp.sinh(x)) + z = get_decimal("sinh", [str(x)], {"precision": 14}) + assert y == z + + +@given(decimal_fixed_precision) +@settings(max_examples=4) +def test_tanh(x): + y = to_precision(mp.tanh(x)) + z = get_decimal("tanh", [str(x)], {"precision": 14}) + assert y == z diff --git a/test/hypothesis/evaluate.mjs b/test/hypothesis/evaluate.mjs new file mode 100644 index 0000000..bf31f47 --- /dev/null +++ b/test/hypothesis/evaluate.mjs @@ -0,0 +1,26 @@ +// listen for test cases, and provide the results. +// give JSON of the test case, receive the result +// Example: +// > {"func":"tan", "args":["12.5"], "config":{"precision":8}} +// -0.066468242 + + +import {Decimal} from '../../decimal.mjs'; +import {createInterface} from 'readline'; + +const readline = createInterface({ + input: process.stdin, + output: process.stdout +}); + +readline.on("close", () => {console.log('\n'); process.exit(0);}); + +readline.on("line", (line) => { + if (line) { + const {func, args, config} = JSON.parse(line); + config.defaults = true; + Decimal.set(config); + const result = Decimal[func](...args); + console.log(result); + } +}); \ No newline at end of file diff --git a/test/hypothesis/requirements.txt b/test/hypothesis/requirements.txt new file mode 100644 index 0000000..ab25b9f --- /dev/null +++ b/test/hypothesis/requirements.txt @@ -0,0 +1,3 @@ +hypothesis +mpmath +node \ No newline at end of file From 4c52aec1cd4e4cbdb400fc1edb8804f7ce82b3ed Mon Sep 17 00:00:00 2001 From: Alden Date: Mon, 13 Feb 2023 01:43:52 -0500 Subject: [PATCH 03/13] additional falsifyer --- test/modules/acos.js | 1 + 1 file changed, 1 insertion(+) diff --git a/test/modules/acos.js b/test/modules/acos.js index 49bdc6d..5fffc01 100644 --- a/test/modules/acos.js +++ b/test/modules/acos.js @@ -69,6 +69,7 @@ T('acos', function () { t('-0.19508761025300975791021816036', 27, 1, '1.76714310275532020878366926'); t('0.0623252416', 19, 0, '1.508430664767542249'); t('0.9999999297625', 14, 4, '0.00037479994883195'); + t('0.99999999467518', 14, 4, '0.00010319709302810'); /* t('0.95', 6, 5, '0.31756'); From 0f36747c05c15f734e86f920a099ffbc0fa8b5a9 Mon Sep 17 00:00:00 2001 From: Alden Date: Mon, 13 Feb 2023 01:44:14 -0500 Subject: [PATCH 04/13] parametrize tests --- test/hypothesis/error_hunt.py | 152 ++++++++++++---------------------- 1 file changed, 55 insertions(+), 97 deletions(-) diff --git a/test/hypothesis/error_hunt.py b/test/hypothesis/error_hunt.py index 7d5e952..7523551 100644 --- a/test/hypothesis/error_hunt.py +++ b/test/hypothesis/error_hunt.py @@ -5,8 +5,10 @@ import hypothesis from hypothesis import given, settings from hypothesis.strategies import decimals, integers, tuples from mpmath import mp +import pytest mp.prec = 500 +getcontext().prec = 14 node = subprocess.Popen( ["node", "evaluate.mjs"], stdout=subprocess.PIPE, stdin=subprocess.PIPE @@ -20,106 +22,62 @@ def get_decimal(func: str, args: list, config: dict): return Decimal(node.stdout.readline().strip().decode()) -def to_precision(x, precision=14): - getcontext().prec = precision - return Decimal(str(x)) * Decimal("1.0") - - -decimal_fixed_precision = 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]) - -decimal_positive = 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]) - - -@given(decimal_fixed_precision) -@settings(max_examples=100) -def test_tangent(x): - y = to_precision(mp.tan(x)) - z = get_decimal("tan", [str(x)], {"precision": 14}) - assert y == z - - -@given(decimal_fixed_precision) -@settings(max_examples=100) -def test_cosine(x): - y = to_precision(mp.cos(x)) - z = get_decimal("cos", [str(x)], {"precision": 14}) +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}) assert y == z -@given(decimal_fixed_precision) -@settings(max_examples=100) -def test_sine(x): - y = to_precision(mp.sin(x)) - z = get_decimal("sin", [str(x)], {"precision": 14}) - assert y == z - - -@given(decimal_positive) -@settings(max_examples=100) -def test_log(x): - y = to_precision(mp.log10(x)) - z = get_decimal("log", [str(x)], {"precision": 14}) - assert y == z - - -inverse_trig_strat = decimals( - allow_nan=False, allow_infinity=False, min_value=-1, max_value=1, places=14 +@pytest.mark.parametrize("fn", "sin cos tan atan".split()) +@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]) ) +def test_matches(x, fn): + assert_matches(x, fn) + + +@pytest.mark.parametrize("fn", "ln log10".split()) +@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]) +) +def test_positive_domain(x, fn): + assert_matches(x, fn) -@given(inverse_trig_strat) -@settings(max_examples=100) -def test_acos(x): - y = to_precision(mp.acos(x)) - z = get_decimal("acos", [str(x)], {"precision": 14}) - assert y == z - - -@given(inverse_trig_strat) -@settings(max_examples=100) -def test_asin(x): - y = to_precision(mp.asin(x)) - z = get_decimal("asin", [str(x)], {"precision": 14}) - assert y == z - - -@given(decimal_fixed_precision) -@settings(max_examples=100) -def test_atan(x): - y = to_precision(mp.atan(x)) - z = get_decimal("atan", [str(x)], {"precision": 14}) - assert y == z - - -@given(decimal_fixed_precision) -@settings(max_examples=10) -def test_cosh(x): - y = to_precision(mp.cosh(x)) - z = get_decimal("cosh", [str(x)], {"precision": 14}) - assert y == z - - -@given(decimal_fixed_precision) -@settings(max_examples=4) -def test_sinh(x): - y = to_precision(mp.sinh(x)) - z = get_decimal("sinh", [str(x)], {"precision": 14}) - assert y == z - - -@given(decimal_fixed_precision) -@settings(max_examples=4) -def test_tanh(x): - y = to_precision(mp.tanh(x)) - z = get_decimal("tanh", [str(x)], {"precision": 14}) - assert y == z +@pytest.mark.parametrize("fn", "asin acos".split()) +@given( + x=decimals( + allow_nan=False, allow_infinity=False, min_value=-1, max_value=1, places=14 + ) +) +def test_inverse_trig(x, fn): + assert_matches(x, fn) + + +@pytest.mark.parametrize("fn", "sinh cosh tanh".split()) +@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]) +) +def test_small_domain(x, fn): + assert_matches(x, fn) From 727eae8053b0e76d629281836fa98ee9f3bdd0f9 Mon Sep 17 00:00:00 2001 From: Alden Date: Mon, 13 Feb 2023 01:56:56 -0500 Subject: [PATCH 05/13] check more cases --- test/hypothesis/error_hunt.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/test/hypothesis/error_hunt.py b/test/hypothesis/error_hunt.py index 7523551..d8be7ee 100644 --- a/test/hypothesis/error_hunt.py +++ b/test/hypothesis/error_hunt.py @@ -39,11 +39,12 @@ def assert_matches(x, mpfunc, jsfunc=None): integers(min_value=-99, max_value=99), ).map(lambda tup: tup[0] * Decimal(10) ** tup[1]) ) +@settings(max_examples=1000) def test_matches(x, fn): assert_matches(x, fn) -@pytest.mark.parametrize("fn", "ln log10".split()) +@pytest.mark.parametrize("fn", "ln log10 sqrt".split()) @given( x=tuples( decimals( @@ -56,6 +57,7 @@ def test_matches(x, fn): integers(min_value=-99, max_value=99), ).map(lambda tup: tup[0] * Decimal(10) ** tup[1]) ) +@settings(max_examples=1000) def test_positive_domain(x, fn): assert_matches(x, fn) @@ -66,11 +68,12 @@ def test_positive_domain(x, fn): allow_nan=False, allow_infinity=False, min_value=-1, max_value=1, places=14 ) ) +@settings(max_examples=1000) def test_inverse_trig(x, fn): assert_matches(x, fn) -@pytest.mark.parametrize("fn", "sinh cosh tanh".split()) +@pytest.mark.parametrize("fn", "sinh cosh tanh exp".split()) @given( x=tuples( decimals( @@ -79,5 +82,6 @@ def test_inverse_trig(x, fn): integers(min_value=-99, max_value=3), ).map(lambda tup: tup[0] * Decimal(10) ** tup[1]) ) +@settings(max_examples=1000) def test_small_domain(x, fn): assert_matches(x, fn) From 24981236086cefc713e0ad4edf6f130ded5abdb4 Mon Sep 17 00:00:00 2001 From: Alden Date: Mon, 13 Feb 2023 02:18:42 -0500 Subject: [PATCH 06/13] test acosh --- test/hypothesis/error_hunt.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/test/hypothesis/error_hunt.py b/test/hypothesis/error_hunt.py index d8be7ee..08d9806 100644 --- a/test/hypothesis/error_hunt.py +++ b/test/hypothesis/error_hunt.py @@ -30,7 +30,7 @@ def assert_matches(x, mpfunc, jsfunc=None): assert y == z -@pytest.mark.parametrize("fn", "sin cos tan atan".split()) +@pytest.mark.parametrize("fn", "sin cos tan atan asinh".split()) @given( x=tuples( decimals( @@ -62,7 +62,7 @@ def test_positive_domain(x, fn): assert_matches(x, fn) -@pytest.mark.parametrize("fn", "asin acos".split()) +@pytest.mark.parametrize("fn", "asin acos atanh".split()) @given( x=decimals( allow_nan=False, allow_infinity=False, min_value=-1, max_value=1, places=14 @@ -85,3 +85,15 @@ def test_inverse_trig(x, fn): @settings(max_examples=1000) def test_small_domain(x, fn): assert_matches(x, fn) + +@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) +def test_acosh(x, fn): + assert_matches(x, 'acosh') \ No newline at end of file From 0316809a806d54f18990c001645397e55595b24e Mon Sep 17 00:00:00 2001 From: Alden Date: Mon, 13 Feb 2023 02:19:00 -0500 Subject: [PATCH 07/13] remove extranous zero --- test/modules/acos.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/modules/acos.js b/test/modules/acos.js index 5fffc01..0b5036c 100644 --- a/test/modules/acos.js +++ b/test/modules/acos.js @@ -69,7 +69,7 @@ T('acos', function () { t('-0.19508761025300975791021816036', 27, 1, '1.76714310275532020878366926'); t('0.0623252416', 19, 0, '1.508430664767542249'); t('0.9999999297625', 14, 4, '0.00037479994883195'); - t('0.99999999467518', 14, 4, '0.00010319709302810'); + t('0.99999999467518', 14, 4, '0.0001031970930281'); /* t('0.95', 6, 5, '0.31756'); From e634266aadd86fde3161068f71467c6de87baaf7 Mon Sep 17 00:00:00 2001 From: Alden Date: Mon, 13 Feb 2023 03:19:39 -0500 Subject: [PATCH 08/13] remove extraneous parameter --- test/hypothesis/error_hunt.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/hypothesis/error_hunt.py b/test/hypothesis/error_hunt.py index 08d9806..e5fc6fc 100644 --- a/test/hypothesis/error_hunt.py +++ b/test/hypothesis/error_hunt.py @@ -95,5 +95,5 @@ def test_small_domain(x, fn): ).map(lambda tup: tup[0] * Decimal(10) ** tup[1]) ) @settings(max_examples=1000) -def test_acosh(x, fn): +def test_acosh(x): assert_matches(x, 'acosh') \ No newline at end of file From 2b1298cd69fe014dc61b73db47daefacf0328cce Mon Sep 17 00:00:00 2001 From: Alden Date: Mon, 13 Feb 2023 03:50:30 -0500 Subject: [PATCH 09/13] use a method less prone to cancellation near x=1 --- decimal.js | 7 +++---- decimal.mjs | 5 ++--- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/decimal.js b/decimal.js index aa6526a..8eabf43 100644 --- a/decimal.js +++ b/decimal.js @@ -744,14 +744,13 @@ Ctor.precision = pr + 6; Ctor.rounding = 1; - - x = x.asin(); - halfPi = getPi(Ctor, pr + 4, rm).times(0.5); + + x = (new Ctor(1)).minus(x).div(x.plus(1)).sqrt().atan(); Ctor.precision = pr; Ctor.rounding = rm; - return halfPi.minus(x); + return x.times(2); }; diff --git a/decimal.mjs b/decimal.mjs index 909300c..293ee8e 100644 --- a/decimal.mjs +++ b/decimal.mjs @@ -741,13 +741,12 @@ P.inverseCosine = P.acos = function () { Ctor.precision = pr + 6; Ctor.rounding = 1; - x = x.asin(); - halfPi = getPi(Ctor, pr + 4, rm).times(0.5); + x = (new Ctor(1)).minus(x).div(x.plus(1)).sqrt().atan(); Ctor.precision = pr; Ctor.rounding = rm; - return halfPi.minus(x); + return x.times(2); }; From b3142b4c60ccd760c0c62f87d1fda51533560a6e Mon Sep 17 00:00:00 2001 From: Alden Date: Mon, 13 Feb 2023 14:34:55 -0500 Subject: [PATCH 10/13] new falisifying test for sine --- test/modules/sin.js | 1 + 1 file changed, 1 insertion(+) diff --git a/test/modules/sin.js b/test/modules/sin.js index d90ea99..05036fe 100644 --- a/test/modules/sin.js +++ b/test/modules/sin.js @@ -119,4 +119,5 @@ T('sin', function () { t('22011131111011111.111111611113111111111151111111', 143, 2, '0.82582504036277799386306063085803210583251158969990606609364360685569588545519071481543672724620118406694191888115120286393881609546697317692404'); t('996270725099515169352424536636186062915113219400094989.8763797268889422850038402633796294758036260533902551191769915343780424028900449342752548782035', 46, 2, '0.6613706114081017074779805460666900787572253475'); t('0.780360750628373', 37, 5, '0.7035358359376557390803090830882458906'); + t('5900', 14, 4, '0.088879123681079'); }); From 64906296b6ee4c04fdda2d57665feb451a09a508 Mon Sep 17 00:00:00 2001 From: Alden Date: Mon, 13 Feb 2023 14:35:27 -0500 Subject: [PATCH 11/13] search for more exampoles --- test/hypothesis/error_hunt.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/hypothesis/error_hunt.py b/test/hypothesis/error_hunt.py index e5fc6fc..af9df0b 100644 --- a/test/hypothesis/error_hunt.py +++ b/test/hypothesis/error_hunt.py @@ -39,7 +39,7 @@ def assert_matches(x, mpfunc, jsfunc=None): integers(min_value=-99, max_value=99), ).map(lambda tup: tup[0] * Decimal(10) ** tup[1]) ) -@settings(max_examples=1000) +@settings(max_examples=100_000) def test_matches(x, fn): assert_matches(x, fn) @@ -57,7 +57,7 @@ def test_matches(x, fn): integers(min_value=-99, max_value=99), ).map(lambda tup: tup[0] * Decimal(10) ** tup[1]) ) -@settings(max_examples=1000) +@settings(max_examples=100_000) def test_positive_domain(x, fn): assert_matches(x, fn) @@ -68,7 +68,7 @@ def test_positive_domain(x, fn): allow_nan=False, allow_infinity=False, min_value=-1, max_value=1, places=14 ) ) -@settings(max_examples=1000) +@settings(max_examples=100_000) def test_inverse_trig(x, fn): assert_matches(x, fn) @@ -82,7 +82,7 @@ def test_inverse_trig(x, fn): integers(min_value=-99, max_value=3), ).map(lambda tup: tup[0] * Decimal(10) ** tup[1]) ) -@settings(max_examples=1000) +@settings(max_examples=100_000) def test_small_domain(x, fn): assert_matches(x, fn) @@ -94,6 +94,6 @@ def test_small_domain(x, fn): integers(min_value=0, max_value=99), ).map(lambda tup: tup[0] * Decimal(10) ** tup[1]) ) -@settings(max_examples=1000) +@settings(max_examples=100_000) def test_acosh(x): assert_matches(x, 'acosh') \ No newline at end of file From 780480cc2ac7f4a95f4de5501c0c360b53da90f0 Mon Sep 17 00:00:00 2001 From: Alden Date: Mon, 13 Feb 2023 16:32:13 -0500 Subject: [PATCH 12/13] additional cosine test showing cancellation --- test/modules/acos.js | 1 + 1 file changed, 1 insertion(+) diff --git a/test/modules/acos.js b/test/modules/acos.js index 0b5036c..4537c33 100644 --- a/test/modules/acos.js +++ b/test/modules/acos.js @@ -70,6 +70,7 @@ T('acos', function () { t('0.0623252416', 19, 0, '1.508430664767542249'); t('0.9999999297625', 14, 4, '0.00037479994883195'); t('0.99999999467518', 14, 4, '0.0001031970930281'); + t('0.9999999999999999995', 25, 4, '0.000000001000000000000000000041667'); /* t('0.95', 6, 5, '0.31756'); From d130921f982b5b59e9875f00ec2982724ed1f2f2 Mon Sep 17 00:00:00 2001 From: Alden Date: Mon, 13 Feb 2023 17:11:19 -0500 Subject: [PATCH 13/13] additional case showing loss of significance near x=1 --- test/modules/acos.js | 1 + 1 file changed, 1 insertion(+) diff --git a/test/modules/acos.js b/test/modules/acos.js index 4537c33..b2ef48c 100644 --- a/test/modules/acos.js +++ b/test/modules/acos.js @@ -71,6 +71,7 @@ T('acos', function () { t('0.9999999297625', 14, 4, '0.00037479994883195'); t('0.99999999467518', 14, 4, '0.0001031970930281'); t('0.9999999999999999995', 25, 4, '0.000000001000000000000000000041667'); + t('0.99999999999999999999995', 30, 4, '0.0000000000100000000000000000000000416667'); /* t('0.95', 6, 5, '0.31756');