34284579dd404478f708dcd3dd25976b9ae0a244
[libm] / src / cmath / casin.c
1 /* origin: OpenBSD /usr/src/lib/libm/src/s_casin.c */
2 /*
3  * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 /*
18  *      Complex circular arc sine
19  *
20  *
21  * SYNOPSIS:
22  *
23  * double complex casin();
24  * double complex z, w;
25  *
26  * w = casin (z);
27  *
28  *
29  * DESCRIPTION:
30  *
31  * Inverse complex sine:
32  *
33  *                               2
34  * w = -i clog( iz + csqrt( 1 - z ) ).
35  *
36  * casin(z) = -i casinh(iz)
37  *
38  * ACCURACY:
39  *
40  *                      Relative error:
41  * arithmetic   domain     # trials      peak         rms
42  *    DEC       -10,+10     10100       2.1e-15     3.4e-16
43  *    IEEE      -10,+10     30000       2.2e-14     2.7e-15
44  * Larger relative error can be observed for z near zero.
45  * Also tested by csin(casin(z)) = z.
46  */
47
48 #include "libm.h"
49
50 double complex casin(double complex z)
51 {
52         double complex w;
53         static double complex ca, ct, zz, z2;
54         double x, y;
55
56         x = creal(z);
57         y = cimag(z);
58
59         if (y == 0.0) {
60                 if (fabs(x) > 1.0)
61                         w = M_PI_2 + 0.0 * I;
62                 else
63                         w = asin(x) + 0.0 * I;
64                 return w;
65         }
66
67         /* Power series expansion */
68         /*
69         b = cabs(z);
70         if( b < 0.125 ) {
71                 z2.r = (x - y) * (x + y);
72                 z2.i = 2.0 * x * y;
73
74                 cn = 1.0;
75                 n = 1.0;
76                 ca.r = x;
77                 ca.i = y;
78                 sum.r = x;
79                 sum.i = y;
80                 do {
81                         ct.r = z2.r * ca.r  -  z2.i * ca.i;
82                         ct.i = z2.r * ca.i  +  z2.i * ca.r;
83                         ca.r = ct.r;
84                         ca.i = ct.i;
85
86                         cn *= n;
87                         n += 1.0;
88                         cn /= n;
89                         n += 1.0;
90                         b = cn/n;
91
92                         ct.r *= b;
93                         ct.i *= b;
94                         sum.r += ct.r;
95                         sum.i += ct.i;
96                         b = fabs(ct.r) + fabs(ct.i);
97                 }
98                 while( b > MACHEP );
99                 w->r = sum.r;
100                 w->i = sum.i;
101                 return;
102         }
103         */
104
105         ca = x + y * I;
106         ct = ca * I;
107         /* sqrt(1 - z*z) */
108         /* cmul(&ca, &ca, &zz) */
109         /* x * x  -  y * y */
110         // FIXME: 1 - ()() - () I
111         zz = (x - y) * (x + y) + (2.0 * x * y) * I;
112         zz = 1.0 - creal(zz) - cimag(zz) * I;
113         z2 = csqrt(zz);
114         zz = ct + z2;
115         zz = clog(zz);
116         /* multiply by 1/i = -i */
117         // FIXME: -I
118         w = zz * (-1.0 * I);
119         return w;
120 }