|
231 | 231 | #ifndef HAVE_CTAN@C@ |
232 | 232 | @ctype@ npy_ctan@c@(@ctype@ z) |
233 | 233 | { |
234 | | - /* ctan(z) = -I * ctanh(I * z) */ |
235 | | - z = npy_ctanh@c@(npy_cpack@c@(-npy_cimag@c@(z), npy_creal@c@(z))); |
236 | | - return (npy_cpack@c@(npy_cimag@c@(z), -npy_creal@c@(z))); |
| 234 | + /* ctan(z) = -I * ctanh(I * z) */ |
| 235 | + z = npy_ctanh@c@(npy_cpack@c@(-npy_cimag@c@(z), npy_creal@c@(z))); |
| 236 | + return (npy_cpack@c@(npy_cimag@c@(z), -npy_creal@c@(z))); |
237 | 237 | } |
238 | 238 | #endif |
239 | 239 |
|
|
285 | 285 |
|
286 | 286 | @ctype@ npy_ctanh@c@(@ctype@ z) |
287 | 287 | { |
288 | | - @type@ x, y; |
289 | | - @type@ t, beta, s, rho, denom; |
290 | | - |
291 | | - x = npy_creal@c@(z); |
292 | | - y = npy_cimag@c@(z); |
293 | | - |
294 | | - /* |
295 | | - * ctanh(NaN + i 0) = NaN + i 0 |
296 | | - * |
297 | | - * ctanh(NaN + i y) = NaN + i NaN for y != 0 |
298 | | - * |
299 | | - * The imaginary part has the sign of x*sin(2*y), but there's no |
300 | | - * special effort to get this right. |
301 | | - * |
302 | | - * ctanh(+-Inf +- i Inf) = +-1 +- 0 |
303 | | - * |
304 | | - * ctanh(+-Inf + i y) = +-1 + 0 sin(2y) for y finite |
305 | | - * |
306 | | - * The imaginary part of the sign is unspecified. This special |
307 | | - * case is only needed to avoid a spurious invalid exception when |
308 | | - * y is infinite. |
309 | | - */ |
| 288 | + @type@ x, y; |
| 289 | + @type@ t, beta, s, rho, denom; |
| 290 | + |
| 291 | + x = npy_creal@c@(z); |
| 292 | + y = npy_cimag@c@(z); |
| 293 | + |
| 294 | + /* |
| 295 | + * ctanh(NaN + i 0) = NaN + i 0 |
| 296 | + * |
| 297 | + * ctanh(NaN + i y) = NaN + i NaN for y != 0 |
| 298 | + * |
| 299 | + * The imaginary part has the sign of x*sin(2*y), but there's no |
| 300 | + * special effort to get this right. |
| 301 | + * |
| 302 | + * ctanh(+-Inf +- i Inf) = +-1 +- 0 |
| 303 | + * |
| 304 | + * ctanh(+-Inf + i y) = +-1 + 0 sin(2y) for y finite |
| 305 | + * |
| 306 | + * The imaginary part of the sign is unspecified. This special |
| 307 | + * case is only needed to avoid a spurious invalid exception when |
| 308 | + * y is infinite. |
| 309 | + */ |
310 | 310 | if (!npy_isfinite(x)) { |
311 | 311 | if (npy_isnan(x)) |
312 | 312 | return npy_cpack@c@(x, (y == 0 ? y : x * y)); |
313 | 313 | return npy_cpack@c@(npy_copysign@c@(1,x), |
314 | | - npy_copysign@c@(0, npy_isinf(y) ? y : npy_sin@c@(y) * npy_cos@c@(y))); |
| 314 | + npy_copysign@c@(0, |
| 315 | + npy_isinf(y) ? y : npy_sin@c@(y) * npy_cos@c@(y))); |
315 | 316 | } |
316 | 317 |
|
317 | | - /* |
318 | | - * ctanh(x + i NAN) = NaN + i NaN |
319 | | - * ctanh(x +- i Inf) = NaN + i NaN |
320 | | - */ |
321 | | - if (!npy_isfinite(y)) |
322 | | - return (npy_cpack@c@(y - y, y - y)); |
323 | | - |
324 | | - /* |
325 | | - * ctanh(+-huge + i +-y) ~= +-1 +- i 2sin(2y)/exp(2x), using the |
326 | | - * approximation sinh^2(huge) ~= exp(2*huge) / 4. |
327 | | - * We use a modified formula to avoid spurious overflow. |
328 | | - */ |
329 | | - if (x >= TANH@C@_HUGE) { |
330 | | - @type@ exp_mx = npy_exp@c@(-npy_fabs@c@(x)); |
331 | | - return (npy_cpack@c@(npy_copysign@c@(1, x), |
332 | | - 4 * npy_sin@c@(y) * npy_cos@c@(y) * exp_mx * exp_mx)); |
333 | | - } |
334 | | - |
335 | | - /* Kahan's algorithm */ |
336 | | - t = npy_tan@c@(y); |
337 | | - beta = 1.0 + t * t; /* = 1 / cos^2(y) */ |
338 | | - s = npy_sinh@c@(x); |
339 | | - rho = npy_sqrt@c@(1 + s * s); /* = cosh(x) */ |
340 | | - denom = 1 + beta * s * s; |
341 | | - return (npy_cpack@c@((beta * rho * s) / denom, t / denom)); |
| 318 | + /* |
| 319 | + * ctanh(x + i NAN) = NaN + i NaN |
| 320 | + * ctanh(x +- i Inf) = NaN + i NaN |
| 321 | + */ |
| 322 | + if (!npy_isfinite(y)) |
| 323 | + return (npy_cpack@c@(y - y, y - y)); |
| 324 | + |
| 325 | + /* |
| 326 | + * ctanh(+-huge + i +-y) ~= +-1 +- i 2sin(2y)/exp(2x), using the |
| 327 | + * approximation sinh^2(huge) ~= exp(2*huge) / 4. |
| 328 | + * We use a modified formula to avoid spurious overflow. |
| 329 | + */ |
| 330 | + if (x >= TANH@C@_HUGE) { |
| 331 | + @type@ exp_mx = npy_exp@c@(-npy_fabs@c@(x)); |
| 332 | + return (npy_cpack@c@(npy_copysign@c@(1, x), |
| 333 | + 4 * npy_sin@c@(y) * npy_cos@c@(y) * exp_mx * exp_mx)); |
| 334 | + } |
| 335 | + |
| 336 | + /* Kahan's algorithm */ |
| 337 | + t = npy_tan@c@(y); |
| 338 | + beta = 1.0 + t * t; /* = 1 / cos^2(y) */ |
| 339 | + s = npy_sinh@c@(x); |
| 340 | + rho = npy_sqrt@c@(1 + s * s); /* = cosh(x) */ |
| 341 | + denom = 1 + beta * s * s; |
| 342 | + return (npy_cpack@c@((beta * rho * s) / denom, t / denom)); |
342 | 343 | } |
343 | 344 | #undef TANH_HUGE |
344 | 345 | #undef TANHF_HUGE |
|
0 commit comments