1 /* $NetBSD: casin.c,v 1.1 2007/08/20 16:01:31 drochner Exp $ */
2 
3 /*-
4  * Copyright (c) 2007 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software written by Stephen L. Moshier.
8  * It is redistributed by the NetBSD Foundation by permission of the author.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  *
31  * imported and modified include for newlib 2010/10/03
32  * Marco Atzeri <marco_atzeri@yahoo.it>
33  */
34 
35 /*
36 FUNCTION
37         <<casin>>, <<casinf>>---complex arc sine
38 
39 INDEX
40         casin
41 INDEX
42         casinf
43 
44 SYNOPSIS
45        #include <complex.h>
46        double complex casin(double complex <[z]>);
47        float complex casinf(float complex <[z]>);
48 
49 
50 DESCRIPTION
51         These functions compute the complex arc sine of <[z]>,
52         with branch cuts outside the interval [-1, +1] along the real axis.
53 
54         <<casinf>> is identical to <<casin>>, except that it performs
55         its calculations on <<floats complex>>.
56 
57 RETURNS
58         @ifnottex
59         These functions return the complex arc sine value, in the range
60         of a strip mathematically  unbounded  along the imaginary axis
61         and in the interval [-pi/2, +pi/2] along the real axis.
62         @end ifnottex
63         @tex
64         These functions return the complex arc sine value, in the range
65         of a strip mathematically  unbounded  along the imaginary axis
66         and in the interval [$-\pi/2$, $+\pi/2$] along the real axis.
67         @end tex
68 
69 PORTABILITY
70         <<casin>> and <<casinf>> are ISO C99
71 
72 QUICKREF
73         <<casin>> and <<casinf>> are ISO C99
74 
75 */
76 
77 
78 #include <complex.h>
79 #include <math.h>
80 
81 #ifdef __weak_alias
__weak_alias(casin,_casin)82 __weak_alias(casin, _casin)
83 #endif
84 
85 double complex
86 casin(double complex z)
87 {
88 	double complex w;
89 	double complex ca, ct, zz, z2;
90 	double x, y;
91 
92 	x = creal(z);
93 	y = cimag(z);
94 
95 #if 0 /* MD: test is incorrect, casin(>1) is defined */
96 	if (y == 0.0) {
97 		if (fabs(x) > 1.0) {
98 			w = M_PI_2 + 0.0 * (double complex) I;
99 #if 0
100 			mtherr ("casin", DOMAIN);
101 #endif
102 		} else {
103 			w = asin(x) + 0.0 * (double complex) I;
104 		}
105 		return w;
106 	}
107 #endif
108 
109 /* Power series expansion */
110 /*
111 b = cabs(z);
112 if( b < 0.125 )
113 {
114 z2.r = (x - y) * (x + y);
115 z2.i = 2.0 * x * y;
116 
117 cn = 1.0;
118 n = 1.0;
119 ca.r = x;
120 ca.i = y;
121 sum.r = x;
122 sum.i = y;
123 do
124 	{
125 	ct.r = z2.r * ca.r  -  z2.i * ca.i;
126 	ct.i = z2.r * ca.i  +  z2.i * ca.r;
127 	ca.r = ct.r;
128 	ca.i = ct.i;
129 
130 	cn *= n;
131 	n += 1.0;
132 	cn /= n;
133 	n += 1.0;
134 	b = cn/n;
135 
136 	ct.r *= b;
137 	ct.i *= b;
138 	sum.r += ct.r;
139 	sum.i += ct.i;
140 	b = fabs(ct.r) + fabs(ct.i);
141 	}
142 while( b > MACHEP );
143 w->r = sum.r;
144 w->i = sum.i;
145 return;
146 }
147 */
148 
149 
150 	ca = x + y * (double complex) I;
151 	ct = ca * (double complex) I;
152 	/* sqrt( 1 - z*z) */
153 	/* cmul( &ca, &ca, &zz ) */
154 	/*x * x  -  y * y */
155 	zz = (x - y) * (x + y) + (2.0 * x * y) * (double complex) I;
156 
157 	zz = 1.0 - creal(zz) - cimag(zz) * (double complex) I;
158 	z2 = csqrt(zz);
159 
160 	zz = ct + z2;
161 	zz = clog(zz);
162 	/* multiply by 1/i = -i */
163 	w = zz * (-1.0 * (double complex) I);
164 	return w;
165 }
166