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