xref: /illumos-gate/usr/src/lib/libm/common/complex/cexpf.c (revision 6e6545bfaed3bab9ce836ee82d1abd8f2edba89a)
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  * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
23  */
24 /*
25  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
26  * Use is subject to license terms.
27  */
28 
29 #pragma weak __cexpf = cexpf
30 
31 #include "libm.h"
32 #include "complex_wrapper.h"
33 
34 #if defined(__i386) && !defined(__amd64)
35 extern int __swapRP(int);
36 #endif
37 
38 static const float zero = 0.0F;
39 
40 fcomplex
41 cexpf(fcomplex z) {
42 	fcomplex	ans;
43 	float		x, y, c, s;
44 	double		t;
45 	int		n, ix, iy, hx, hy;
46 
47 	x = F_RE(z);
48 	y = F_IM(z);
49 	hx = THE_WORD(x);
50 	hy = THE_WORD(y);
51 	ix = hx & 0x7fffffff;
52 	iy = hy & 0x7fffffff;
53 	if (iy == 0) {		/* y = 0 */
54 		F_RE(ans) = expf(x);
55 		F_IM(ans) = y;
56 	} else if (ix == 0x7f800000) {	/* x is +-inf */
57 		if (hx < 0) {
58 			if (iy >= 0x7f800000) {
59 				F_RE(ans) = zero;
60 				F_IM(ans) = zero;
61 			} else {
62 				sincosf(y, &s, &c);
63 				F_RE(ans) = zero * c;
64 				F_IM(ans) = zero * s;
65 			}
66 		} else {
67 			if (iy >= 0x7f800000) {
68 				F_RE(ans) = x;
69 				F_IM(ans) = y - y;
70 			} else {
71 				sincosf(y, &s, &c);
72 				F_RE(ans) = x * c;
73 				F_IM(ans) = x * s;
74 			}
75 		}
76 	} else {
77 		sincosf(y, &s, &c);
78 		if (ix >= 0x42B171AA) {	/* |x| > 88.722... ~ log(2**128) */
79 #if defined(__i386) && !defined(__amd64)
80 			int	rp = __swapRP(fp_extended);
81 #endif
82 			t = __k_cexp(x, &n);
83 			F_RE(ans) = (float)scalbn(t * (double)c, n);
84 			F_IM(ans) = (float)scalbn(t * (double)s, n);
85 #if defined(__i386) && !defined(__amd64)
86 			if (rp != fp_extended)
87 				(void) __swapRP(rp);
88 #endif
89 		} else {
90 			t = expf(x);
91 			F_RE(ans) = t * c;
92 			F_IM(ans) = t * s;
93 		}
94 	}
95 	return (ans);
96 }
97