Check loss of precision in complex arc* functions
(self, dtype)
| 4207 | @pytest.mark.xfail(IS_WASM, reason="doesn't work") |
| 4208 | @pytest.mark.parametrize('dtype', [np.complex64, np.complex_, np.longcomplex]) |
| 4209 | def test_loss_of_precision(self, dtype): |
| 4210 | """Check loss of precision in complex arc* functions""" |
| 4211 | |
| 4212 | # Check against known-good functions |
| 4213 | |
| 4214 | info = np.finfo(dtype) |
| 4215 | real_dtype = dtype(0.).real.dtype |
| 4216 | eps = info.eps |
| 4217 | |
| 4218 | def check(x, rtol): |
| 4219 | x = x.astype(real_dtype) |
| 4220 | |
| 4221 | z = x.astype(dtype) |
| 4222 | d = np.absolute(np.arcsinh(x)/np.arcsinh(z).real - 1) |
| 4223 | assert_(np.all(d < rtol), (np.argmax(d), x[np.argmax(d)], d.max(), |
| 4224 | 'arcsinh')) |
| 4225 | |
| 4226 | z = (1j*x).astype(dtype) |
| 4227 | d = np.absolute(np.arcsinh(x)/np.arcsin(z).imag - 1) |
| 4228 | assert_(np.all(d < rtol), (np.argmax(d), x[np.argmax(d)], d.max(), |
| 4229 | 'arcsin')) |
| 4230 | |
| 4231 | z = x.astype(dtype) |
| 4232 | d = np.absolute(np.arctanh(x)/np.arctanh(z).real - 1) |
| 4233 | assert_(np.all(d < rtol), (np.argmax(d), x[np.argmax(d)], d.max(), |
| 4234 | 'arctanh')) |
| 4235 | |
| 4236 | z = (1j*x).astype(dtype) |
| 4237 | d = np.absolute(np.arctanh(x)/np.arctan(z).imag - 1) |
| 4238 | assert_(np.all(d < rtol), (np.argmax(d), x[np.argmax(d)], d.max(), |
| 4239 | 'arctan')) |
| 4240 | |
| 4241 | # The switchover was chosen as 1e-3; hence there can be up to |
| 4242 | # ~eps/1e-3 of relative cancellation error before it |
| 4243 | |
| 4244 | x_series = np.logspace(-20, -3.001, 200) |
| 4245 | x_basic = np.logspace(-2.999, 0, 10, endpoint=False) |
| 4246 | |
| 4247 | if dtype is np.longcomplex: |
| 4248 | if bad_arcsinh(): |
| 4249 | pytest.skip("Trig functions of np.longcomplex values known " |
| 4250 | "to be inaccurate on aarch64 and PPC for some " |
| 4251 | "compilation configurations.") |
| 4252 | # It's not guaranteed that the system-provided arc functions |
| 4253 | # are accurate down to a few epsilons. (Eg. on Linux 64-bit) |
| 4254 | # So, give more leeway for long complex tests here: |
| 4255 | check(x_series, 50.0*eps) |
| 4256 | else: |
| 4257 | check(x_series, 2.1*eps) |
| 4258 | check(x_basic, 2.0*eps/1e-3) |
| 4259 | |
| 4260 | # Check a few points |
| 4261 | |
| 4262 | z = np.array([1e-5*(1+1j)], dtype=dtype) |
| 4263 | p = 9.999999999333333333e-6 + 1.000000000066666666e-5j |
| 4264 | d = np.absolute(1-np.arctanh(z)/p) |
| 4265 | assert_(np.all(d < 1e-15)) |
| 4266 |
nothing calls this directly
no test coverage detected