1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
24  */
25 /*
26  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
27  * Use is subject to license terms.
28  */
29 
30 #pragma weak __csqrtf = csqrtf
31 
32 #include "libm.h"		/* sqrt/fabsf/sqrtf */
33 #include "complex_wrapper.h"
34 
35 /* INDENT OFF */
36 static const float zero = 0.0F;
37 /* INDENT ON */
38 
39 fcomplex
csqrtf(fcomplex z)40 csqrtf(fcomplex z) {
41 	fcomplex ans;
42 	double dt, dx, dy;
43 	float x, y, t, ax, ay, w;
44 	int ix, iy, hx, hy;
45 
46 	x = F_RE(z);
47 	y = F_IM(z);
48 	hx = THE_WORD(x);
49 	hy = THE_WORD(y);
50 	ix = hx & 0x7fffffff;
51 	iy = hy & 0x7fffffff;
52 	ay = fabsf(y);
53 	ax = fabsf(x);
54 	if (ix >= 0x7f800000 || iy >= 0x7f800000) {
55 		/* x or y is Inf or NaN */
56 		if (iy == 0x7f800000)
57 			F_IM(ans) = F_RE(ans) = ay;
58 		else if (ix == 0x7f800000) {
59 			if (hx > 0) {
60 				F_RE(ans) = ax;
61 				F_IM(ans) = ay * zero;
62 			} else {
63 				F_RE(ans) = ay * zero;
64 				F_IM(ans) = ax;
65 			}
66 		} else
67 			F_IM(ans) = F_RE(ans) = ax + ay;
68 	} else if (iy == 0) {
69 		if (hx >= 0) {
70 			F_RE(ans) = sqrtf(ax);
71 			F_IM(ans) = zero;
72 		} else {
73 			F_IM(ans) = sqrtf(ax);
74 			F_RE(ans) = zero;
75 		}
76 	} else {
77 		dx = (double) ax;
78 		dy = (double) ay;
79 		dt = sqrt(0.5 * (sqrt(dx * dx + dy * dy) + dx));
80 		t = (float) dt;
81 		w = (float) (dy / (dt + dt));
82 		if (hx >= 0) {
83 			F_RE(ans) = t;
84 			F_IM(ans) = w;
85 		} else {
86 			F_IM(ans) = t;
87 			F_RE(ans) = w;
88 		}
89 	}
90 	if (hy < 0)
91 		F_IM(ans) = -F_IM(ans);
92 	return (ans);
93 }
94