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