Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 3710481

Browse files
committed
ENH: Import the csinh/csin implementation from FreeBSD
The code from FreeBSD was lightly adapted to fit with the numpy style. With this commit, npy_csinh(f) and npy_csin(f) pass all of the tests in test_c99complex.c.
1 parent e574e29 commit 3710481

1 file changed

Lines changed: 124 additions & 6 deletions

File tree

numpy/core/src/npymath/npy_math_complex.c.src

Lines changed: 124 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -482,10 +482,9 @@ static @ctype@ _npy_scaled_cexp@c@(@type@ x, @type@ y, npy_int expt)
482482
#ifndef HAVE_CSIN@C@
483483
@ctype@ npy_csin@c@(@ctype@ z)
484484
{
485-
@type@ x, y;
486-
x = npy_creal@c@(z);
487-
y = npy_cimag@c@(z);
488-
return npy_cpack@c@(npy_sin@c@(x) * npy_cosh@c@(y), npy_cos@c@(x) * npy_sinh@c@(y));
485+
/* csin(z) = -I * csinh(I * z) */
486+
z = npy_csinh@c@(npy_cpack@c@(-npy_cimag@c@(z), npy_creal@c@(z)));
487+
return npy_cpack@c@(npy_cimag@c@(z), -npy_creal@c@(z));
489488
}
490489
#endif
491490

@@ -627,13 +626,132 @@ static @ctype@ _npy_scaled_cexp@c@(@type@ x, @type@ y, npy_int expt)
627626
#endif
628627

629628
#ifndef HAVE_CSINH@C@
629+
/*
630+
* Taken from the msun library in FreeBSD, rev 226599.
631+
*
632+
* Hyperbolic sine of a complex argument z = x + i y.
633+
*
634+
* sinh(z) = sinh(x+iy)
635+
* = sinh(x) cos(y) + i cosh(x) sin(y).
636+
*
637+
* Exceptional values are noted in the comments within the source code.
638+
* These values and the return value were taken from n1124.pdf.
639+
*/
640+
641+
#if @precision@ == 1
642+
#define CSINH_BIG 9.0f
643+
#define CSINH_HUGE 1.70141183e+38f
644+
#endif
645+
#if @precision@ == 2
646+
#define CSINH_BIG 22.0
647+
#define CSINH_HUGE 8.9884656743115795e+307
648+
#endif
649+
#if @precision@ >= 3
650+
#define CSINH_BIG 24.0L
651+
#define CSINH_HUGE 5.94865747678615882543e+4931L
652+
#endif
653+
630654
@ctype@ npy_csinh@c@(@ctype@ z)
631655
{
632-
@type@ x, y;
656+
@type@ x, y, h, absx;
657+
npy_int xfinite, yfinite;
658+
633659
x = npy_creal@c@(z);
634660
y = npy_cimag@c@(z);
635-
return npy_cpack@c@(npy_cos@c@(y)*npy_sinh@c@(x), npy_sin@c@(y)*npy_cosh@c@(x));
661+
662+
xfinite = npy_isfinite(x);
663+
yfinite = npy_isfinite(y);
664+
665+
/* Handle the nearly-non-exceptional cases where x and y are finite. */
666+
if (xfinite && yfinite) {
667+
if (y == 0)
668+
return npy_cpack@c@(npy_sinh@c@(x), y);
669+
absx = npy_fabs@c@(x);
670+
if (absx < CSINH_BIG) /* small x: normal case */
671+
return npy_cpack@c@(npy_sinh@c@(x) * npy_cos@c@(y), npy_cosh@c@(x) * npy_sin@c@(y));
672+
673+
/* |x| >= 22, so cosh(x) ~= exp(|x|) */
674+
if (absx < SCALED_CEXP_LOWER@C@) {
675+
/* x < 710: exp(|x|) won't overflow */
676+
h = npy_exp@c@(npy_fabs@c@(x)) * 0.5;
677+
return npy_cpack@c@(npy_copysign@c@(h, x) * npy_cos@c@(y), h * npy_sin@c@(y));
678+
} else if (x < SCALED_CEXP_UPPER@C@) {
679+
/* x < 1455: scale to avoid overflow */
680+
z = _npy_scaled_cexp@c@(absx, y, -1);
681+
return npy_cpack@c@(npy_creal@c@(z) * npy_copysign@c@(1, x), npy_cimag@c@(z));
682+
} else {
683+
/* x >= 1455: the result always overflows */
684+
h = CSINH_HUGE * x;
685+
return npy_cpack@c@(h * npy_cos@c@(y), h * h * npy_sin@c@(y));
686+
}
687+
}
688+
689+
/*
690+
* sinh(+-0 +- I Inf) = sign(d(+-0, dNaN))0 + I dNaN.
691+
* The sign of 0 in the result is unspecified. Choice = normally
692+
* the same as dNaN. Raise the invalid floating-point exception.
693+
*
694+
* sinh(+-0 +- I NaN) = sign(d(+-0, NaN))0 + I d(NaN).
695+
* The sign of 0 in the result is unspecified. Choice = normally
696+
* the same as d(NaN).
697+
*/
698+
if (x == 0 && !yfinite)
699+
return npy_cpack@c@(npy_copysign@c@(0, x * (y - y)), y - y);
700+
701+
/*
702+
* sinh(+-Inf +- I 0) = +-Inf + I +-0.
703+
*
704+
* sinh(NaN +- I 0) = d(NaN) + I +-0.
705+
*/
706+
if (y == 0 && !xfinite) {
707+
if (npy_isnan(x))
708+
return z;
709+
return npy_cpack@c@(x, npy_copysign@c@(0, y));
710+
}
711+
712+
/*
713+
* sinh(x +- I Inf) = dNaN + I dNaN.
714+
* Raise the invalid floating-point exception for finite nonzero x.
715+
*
716+
* sinh(x + I NaN) = d(NaN) + I d(NaN).
717+
* Optionally raises the invalid floating-point exception for finite
718+
* nonzero x. Choice = don't raise (except for signaling NaNs).
719+
*/
720+
if (xfinite && !yfinite)
721+
return npy_cpack@c@(y - y, x * (y - y));
722+
723+
/*
724+
* sinh(+-Inf + I NaN) = +-Inf + I d(NaN).
725+
* The sign of Inf in the result is unspecified. Choice = normally
726+
* the same as d(NaN).
727+
*
728+
* sinh(+-Inf +- I Inf) = +Inf + I dNaN.
729+
* The sign of Inf in the result is unspecified. Choice = always +.
730+
* Raise the invalid floating-point exception.
731+
*
732+
* sinh(+-Inf + I y) = +-Inf cos(y) + I Inf sin(y)
733+
*/
734+
if (!xfinite && !npy_isnan(x)) {
735+
if (!yfinite)
736+
return npy_cpack@c@(x * x, x * (y - y));
737+
return npy_cpack@c@(x * npy_cos@c@(y), NPY_INFINITY@C@ * npy_sin@c@(y));
738+
}
739+
740+
/*
741+
* sinh(NaN + I NaN) = d(NaN) + I d(NaN).
742+
*
743+
* sinh(NaN +- I Inf) = d(NaN) + I d(NaN).
744+
* Optionally raises the invalid floating-point exception.
745+
* Choice = raise.
746+
*
747+
* sinh(NaN + I y) = d(NaN) + I d(NaN).
748+
* Optionally raises the invalid floating-point exception for finite
749+
* nonzero y. Choice = don't raise (except for signaling NaNs).
750+
*/
751+
return npy_cpack@c@((x * x) * (y - y), (x + x) * (y - y));
636752
}
753+
#undef CSINH_BIG
754+
#undef CSINH_HUGE
637755
#endif
638756

639757
#ifndef HAVE_CTANH@C@

0 commit comments

Comments
 (0)