xref: /illumos-gate/usr/src/lib/libm/common/Q/rndintl.c (revision 1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9f)
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 aintl = __aintl
30 #pragma weak anintl = __anintl
31 #pragma weak irintl = __irintl
32 #pragma weak nintl = __nintl
33 
34 /*
35  * aintl(x)	return x chopped to integral value
36  * anintl(x)	return sign(x)*(|x|+0.5) chopped to integral value
37  * irintl(x)	return rint(x) in integer format
38  * nintl(x)	return anint(x) in integer format
39  *
40  * NOTE: aintl(x), anintl(x), ceill(x), floorl(x), and rintl(x) return result
41  * with the same sign as x's,  including 0.0.
42  */
43 
44 #include "libm.h"
45 #include "longdouble.h"
46 
47 extern enum fp_direction_type __swapRD(enum fp_direction_type);
48 
49 static const long double qone = 1.0L, qhalf = 0.5L, qmhalf = -0.5L;
50 
51 long double
52 aintl(long double x) {
53 	long double t, w;
54 
55 	if (!finitel(x))
56 		return (x + x);
57 	w = fabsl(x);
58 	t = rintl(w);
59 	if (t <= w)
60 		return (copysignl(t, x));	/* NaN or already aint(|x|) */
61 	else	/* |t|>|x| case */
62 		return (copysignl(t - qone, x));	/* |t-1|*sign(x) */
63 }
64 
65 long double
66 anintl(long double x) {
67 	long double t, w, z;
68 
69 	if (!finitel(x))
70 		return (x + x);
71 	w = fabsl(x);
72 	t = rintl(w);
73 	if (t == w)
74 		return (copysignl(t, x));
75 	z = t - w;
76 	if (z > qhalf)
77 		t = t - qone;
78 	else if (z <= qmhalf)
79 		t = t + qone;
80 	return (copysignl(t, x));
81 }
82 
83 int
84 irintl(long double x) {
85 	enum fp_direction_type rd;
86 
87 	rd = __swapRD(fp_nearest);
88 	(void) __swapRD(rd);	/* restore Rounding Direction */
89 	switch (rd) {
90 	case fp_nearest:
91 		if (x < 2147483647.5L && x >= -2147483648.5L)
92 			return ((int)rintl(x));
93 		break;
94 	case fp_tozero:
95 		if (x < 2147483648.0L && x > -2147483649.0L)
96 			return ((int)rintl(x));
97 		break;
98 	case fp_positive:
99 		if (x <= 2147483647.0L && x > -2147483649.0L)
100 			return ((int)rintl(x));
101 		break;
102 	case fp_negative:
103 		if (x < 2147483648.0L && x >= -2147483648.0L)
104 			return ((int)rintl(x));
105 		break;
106 	}
107 	return ((int)copysignl(1.0e100L, x));
108 }
109 
110 int
111 nintl(long double x) {
112 	if ((x < 2147483647.5L) && (x > -2147483648.5L))
113 		return ((int)anintl(x));
114 	else
115 		return ((int)copysignl(1.0e100L, x));
116 }
117