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 /* 27 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 28 * Use is subject to license terms. 29 */ 30 31 #pragma weak __roundl = roundl 32 33 #include "libm.h" 34 35 #if defined(__sparc) 36 long double 37 roundl(long double x) 38 { 39 union { 40 unsigned i[4]; 41 long double q; 42 } xx; 43 44 unsigned hx, sx, v; 45 int j; 46 47 xx.q = x; 48 sx = xx.i[0] & 0x80000000; 49 hx = xx.i[0] & ~0x80000000; 50 51 /* handle trivial cases */ 52 if (hx >= 0x406f0000) /* |x| >= 2^112 + ... or x is nan */ 53 return (hx >= 0x7fff0000 ? x + x : x); 54 55 /* handle |x| < 1 */ 56 if (hx < 0x3fff0000) { 57 if (hx >= 0x3ffe0000) 58 return (sx ? -1.0L : 1.0L); 59 60 return (sx ? -0.0L : 0.0L); 61 } 62 63 xx.i[0] = hx; 64 j = 0x406f - (hx >> 16); /* 1 <= j <= 112 */ 65 66 if (j >= 96) { /* 96 <= j <= 112 */ 67 v = (1U << (j - 96)) >> 1; 68 69 if (v) { 70 if (xx.i[0] & v) 71 xx.i[0] += v; 72 73 xx.i[0] &= ~(v - 1); 74 } else if (xx.i[1] & 0x80000000) { 75 ++xx.i[0]; 76 } 77 78 xx.i[1] = xx.i[2] = xx.i[3] = 0; 79 } else if (j >= 64) { /* 64 <= j <= 95 */ 80 v = (1U << (j - 64)) >> 1; 81 82 if (v) { 83 if (xx.i[1] & v) { 84 xx.i[1] += v; 85 86 if (xx.i[1] < v) 87 ++xx.i[0]; 88 } 89 90 xx.i[1] &= ~(v - 1); 91 } else if (xx.i[2] & 0x80000000) { 92 if (++xx.i[1] == 0) 93 ++xx.i[0]; 94 } 95 96 xx.i[2] = xx.i[3] = 0; 97 } else if (j >= 32) { /* 32 <= j <= 63 */ 98 v = (1U << (j - 32)) >> 1; 99 100 if (v) { 101 if (xx.i[2] & v) { 102 xx.i[2] += v; 103 104 if (xx.i[2] < v) { 105 if (++xx.i[1] == 0) 106 ++xx.i[0]; 107 } 108 } 109 110 xx.i[2] &= ~(v - 1); 111 } else if (xx.i[3] & 0x80000000) { 112 if (++xx.i[2] == 0) { 113 if (++xx.i[1] == 0) 114 ++xx.i[0]; 115 } 116 } 117 118 xx.i[3] = 0; 119 } else { /* 1 <= j <= 31 */ 120 v = 1U << (j - 1); 121 122 if (xx.i[3] & v) { 123 xx.i[3] += v; 124 125 if (xx.i[3] < v) { 126 if (++xx.i[2] == 0) { 127 if (++xx.i[1] == 0) 128 ++xx.i[0]; 129 } 130 } 131 } 132 133 xx.i[3] &= ~(v - 1); 134 } 135 136 /* negate result if need be */ 137 if (sx) 138 xx.i[0] |= 0x80000000; 139 140 return (xx.q); 141 } 142 #elif defined(__x86) 143 long double 144 roundl(long double x) 145 { 146 union { 147 unsigned i[3]; 148 long double e; 149 } xx; 150 151 int ex, sx, i; 152 153 xx.e = x; 154 ex = xx.i[2] & 0x7fff; 155 sx = xx.i[2] & 0x8000; 156 157 if (ex < 0x403e) { /* |x| < 2^63 */ 158 if (ex < 0x3fff) { /* |x| < 1 */ 159 if (ex >= 0x3ffe) 160 return (sx ? -1.0L : 1.0L); 161 162 return (sx ? -0.0L : 0.0L); 163 } 164 165 /* round x at the integer bit */ 166 if (ex < 0x401e) { 167 i = 1 << (0x401d - ex); 168 xx.i[1] = (xx.i[1] + i) & ~(i | (i - 1)); 169 xx.i[0] = 0; 170 } else { 171 i = 1 << (0x403d - ex); 172 xx.i[0] += i; 173 174 if (xx.i[0] < i) 175 xx.i[1]++; 176 177 xx.i[0] &= ~(i | (i - 1)); 178 } 179 180 if (xx.i[1] == 0) { 181 xx.i[2] = sx | ++ex; 182 xx.i[1] = 0x80000000U; 183 } 184 185 return (xx.e); 186 } else if (ex < 0x7fff) { /* x is integral */ 187 return (x); 188 } else { /* inf or nan */ 189 return (x + x); 190 } 191 } 192 #else 193 #error Unknown architecture 194 #endif /* defined(__sparc) || defined(__x86) */