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