1*25c28e83SPiotr Jasiukajtis /* 2*25c28e83SPiotr Jasiukajtis * CDDL HEADER START 3*25c28e83SPiotr Jasiukajtis * 4*25c28e83SPiotr Jasiukajtis * The contents of this file are subject to the terms of the 5*25c28e83SPiotr Jasiukajtis * Common Development and Distribution License (the "License"). 6*25c28e83SPiotr Jasiukajtis * You may not use this file except in compliance with the License. 7*25c28e83SPiotr Jasiukajtis * 8*25c28e83SPiotr Jasiukajtis * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*25c28e83SPiotr Jasiukajtis * or http://www.opensolaris.org/os/licensing. 10*25c28e83SPiotr Jasiukajtis * See the License for the specific language governing permissions 11*25c28e83SPiotr Jasiukajtis * and limitations under the License. 12*25c28e83SPiotr Jasiukajtis * 13*25c28e83SPiotr Jasiukajtis * When distributing Covered Code, include this CDDL HEADER in each 14*25c28e83SPiotr Jasiukajtis * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*25c28e83SPiotr Jasiukajtis * If applicable, add the following below this CDDL HEADER, with the 16*25c28e83SPiotr Jasiukajtis * fields enclosed by brackets "[]" replaced with your own identifying 17*25c28e83SPiotr Jasiukajtis * information: Portions Copyright [yyyy] [name of copyright owner] 18*25c28e83SPiotr Jasiukajtis * 19*25c28e83SPiotr Jasiukajtis * CDDL HEADER END 20*25c28e83SPiotr Jasiukajtis */ 21*25c28e83SPiotr Jasiukajtis 22*25c28e83SPiotr Jasiukajtis /* 23*25c28e83SPiotr Jasiukajtis * Copyright 2011 Nexenta Systems, Inc. All rights reserved. 24*25c28e83SPiotr Jasiukajtis */ 25*25c28e83SPiotr Jasiukajtis /* 26*25c28e83SPiotr Jasiukajtis * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 27*25c28e83SPiotr Jasiukajtis * Use is subject to license terms. 28*25c28e83SPiotr Jasiukajtis */ 29*25c28e83SPiotr Jasiukajtis 30*25c28e83SPiotr Jasiukajtis #pragma weak nearbyintl = __nearbyintl 31*25c28e83SPiotr Jasiukajtis 32*25c28e83SPiotr Jasiukajtis #include "libm.h" 33*25c28e83SPiotr Jasiukajtis #include "fma.h" 34*25c28e83SPiotr Jasiukajtis #include "fenv_inlines.h" 35*25c28e83SPiotr Jasiukajtis 36*25c28e83SPiotr Jasiukajtis #if defined(__sparc) 37*25c28e83SPiotr Jasiukajtis 38*25c28e83SPiotr Jasiukajtis static union { 39*25c28e83SPiotr Jasiukajtis unsigned i; 40*25c28e83SPiotr Jasiukajtis float f; 41*25c28e83SPiotr Jasiukajtis } snan = { 0x7f800001 }; 42*25c28e83SPiotr Jasiukajtis 43*25c28e83SPiotr Jasiukajtis long double 44*25c28e83SPiotr Jasiukajtis __nearbyintl(long double x) { 45*25c28e83SPiotr Jasiukajtis union { 46*25c28e83SPiotr Jasiukajtis unsigned i[4]; 47*25c28e83SPiotr Jasiukajtis long double q; 48*25c28e83SPiotr Jasiukajtis } xx; 49*25c28e83SPiotr Jasiukajtis unsigned hx, sx, i, frac; 50*25c28e83SPiotr Jasiukajtis unsigned int fsr; 51*25c28e83SPiotr Jasiukajtis int rm, j; 52*25c28e83SPiotr Jasiukajtis volatile float dummy; 53*25c28e83SPiotr Jasiukajtis 54*25c28e83SPiotr Jasiukajtis xx.q = x; 55*25c28e83SPiotr Jasiukajtis sx = xx.i[0] & 0x80000000; 56*25c28e83SPiotr Jasiukajtis hx = xx.i[0] & ~0x80000000; 57*25c28e83SPiotr Jasiukajtis 58*25c28e83SPiotr Jasiukajtis /* handle trivial cases */ 59*25c28e83SPiotr Jasiukajtis if (hx >= 0x406f0000) { /* x is nan, inf, or already integral */ 60*25c28e83SPiotr Jasiukajtis /* check for signaling nan */ 61*25c28e83SPiotr Jasiukajtis if ((hx > 0x7fff0000 || (hx == 0x7fff0000 && 62*25c28e83SPiotr Jasiukajtis (xx.i[1] | xx.i[2] | xx.i[3]))) && !(hx & 0x8000)) { 63*25c28e83SPiotr Jasiukajtis dummy = snan.f; 64*25c28e83SPiotr Jasiukajtis dummy += snan.f; 65*25c28e83SPiotr Jasiukajtis xx.i[0] = sx | hx | 0x8000; 66*25c28e83SPiotr Jasiukajtis } 67*25c28e83SPiotr Jasiukajtis return (xx.q); 68*25c28e83SPiotr Jasiukajtis } else if ((hx | xx.i[1] | xx.i[2] | xx.i[3]) == 0) /* x is zero */ 69*25c28e83SPiotr Jasiukajtis return (x); 70*25c28e83SPiotr Jasiukajtis 71*25c28e83SPiotr Jasiukajtis /* get the rounding mode */ 72*25c28e83SPiotr Jasiukajtis __fenv_getfsr32(&fsr); 73*25c28e83SPiotr Jasiukajtis rm = fsr >> 30; 74*25c28e83SPiotr Jasiukajtis 75*25c28e83SPiotr Jasiukajtis /* flip the sense of directed roundings if x is negative */ 76*25c28e83SPiotr Jasiukajtis if (sx) 77*25c28e83SPiotr Jasiukajtis rm ^= rm >> 1; 78*25c28e83SPiotr Jasiukajtis 79*25c28e83SPiotr Jasiukajtis /* handle |x| < 1 */ 80*25c28e83SPiotr Jasiukajtis if (hx < 0x3fff0000) { 81*25c28e83SPiotr Jasiukajtis if (rm == FSR_RP || (rm == FSR_RN && (hx >= 0x3ffe0000 && 82*25c28e83SPiotr Jasiukajtis ((hx & 0xffff) | xx.i[1] | xx.i[2] | xx.i[3])))) 83*25c28e83SPiotr Jasiukajtis xx.i[0] = sx | 0x3fff0000; 84*25c28e83SPiotr Jasiukajtis else 85*25c28e83SPiotr Jasiukajtis xx.i[0] = sx; 86*25c28e83SPiotr Jasiukajtis xx.i[1] = xx.i[2] = xx.i[3] = 0; 87*25c28e83SPiotr Jasiukajtis return (xx.q); 88*25c28e83SPiotr Jasiukajtis } 89*25c28e83SPiotr Jasiukajtis 90*25c28e83SPiotr Jasiukajtis /* round x at the integer bit */ 91*25c28e83SPiotr Jasiukajtis j = 0x406f - (hx >> 16); 92*25c28e83SPiotr Jasiukajtis if (j >= 96) { 93*25c28e83SPiotr Jasiukajtis i = 1 << (j - 96); 94*25c28e83SPiotr Jasiukajtis frac = ((xx.i[0] << 1) << (127 - j)) | (xx.i[1] >> (j - 96)); 95*25c28e83SPiotr Jasiukajtis if ((xx.i[1] & (i - 1)) | xx.i[2] | xx.i[3]) 96*25c28e83SPiotr Jasiukajtis frac |= 1; 97*25c28e83SPiotr Jasiukajtis if (!frac) 98*25c28e83SPiotr Jasiukajtis return (x); 99*25c28e83SPiotr Jasiukajtis xx.i[1] = xx.i[2] = xx.i[3] = 0; 100*25c28e83SPiotr Jasiukajtis xx.i[0] &= ~(i - 1); 101*25c28e83SPiotr Jasiukajtis if (rm == FSR_RP || (rm == FSR_RN && (frac > 0x80000000u || 102*25c28e83SPiotr Jasiukajtis (frac == 0x80000000 && (xx.i[0] & i))))) 103*25c28e83SPiotr Jasiukajtis xx.i[0] += i; 104*25c28e83SPiotr Jasiukajtis } else if (j >= 64) { 105*25c28e83SPiotr Jasiukajtis i = 1 << (j - 64); 106*25c28e83SPiotr Jasiukajtis frac = ((xx.i[1] << 1) << (95 - j)) | (xx.i[2] >> (j - 64)); 107*25c28e83SPiotr Jasiukajtis if ((xx.i[2] & (i - 1)) | xx.i[3]) 108*25c28e83SPiotr Jasiukajtis frac |= 1; 109*25c28e83SPiotr Jasiukajtis if (!frac) 110*25c28e83SPiotr Jasiukajtis return (x); 111*25c28e83SPiotr Jasiukajtis xx.i[2] = xx.i[3] = 0; 112*25c28e83SPiotr Jasiukajtis xx.i[1] &= ~(i - 1); 113*25c28e83SPiotr Jasiukajtis if (rm == FSR_RP || (rm == FSR_RN && (frac > 0x80000000u || 114*25c28e83SPiotr Jasiukajtis (frac == 0x80000000 && (xx.i[1] & i))))) { 115*25c28e83SPiotr Jasiukajtis xx.i[1] += i; 116*25c28e83SPiotr Jasiukajtis if (xx.i[1] == 0) 117*25c28e83SPiotr Jasiukajtis xx.i[0]++; 118*25c28e83SPiotr Jasiukajtis } 119*25c28e83SPiotr Jasiukajtis } else if (j >= 32) { 120*25c28e83SPiotr Jasiukajtis i = 1 << (j - 32); 121*25c28e83SPiotr Jasiukajtis frac = ((xx.i[2] << 1) << (63 - j)) | (xx.i[3] >> (j - 32)); 122*25c28e83SPiotr Jasiukajtis if (xx.i[3] & (i - 1)) 123*25c28e83SPiotr Jasiukajtis frac |= 1; 124*25c28e83SPiotr Jasiukajtis if (!frac) 125*25c28e83SPiotr Jasiukajtis return (x); 126*25c28e83SPiotr Jasiukajtis xx.i[3] = 0; 127*25c28e83SPiotr Jasiukajtis xx.i[2] &= ~(i - 1); 128*25c28e83SPiotr Jasiukajtis if (rm == FSR_RP || (rm == FSR_RN && (frac > 0x80000000u || 129*25c28e83SPiotr Jasiukajtis (frac == 0x80000000 && (xx.i[2] & i))))) { 130*25c28e83SPiotr Jasiukajtis xx.i[2] += i; 131*25c28e83SPiotr Jasiukajtis if (xx.i[2] == 0) 132*25c28e83SPiotr Jasiukajtis if (++xx.i[1] == 0) 133*25c28e83SPiotr Jasiukajtis xx.i[0]++; 134*25c28e83SPiotr Jasiukajtis } 135*25c28e83SPiotr Jasiukajtis } else { 136*25c28e83SPiotr Jasiukajtis i = 1 << j; 137*25c28e83SPiotr Jasiukajtis frac = (xx.i[3] << 1) << (31 - j); 138*25c28e83SPiotr Jasiukajtis if (!frac) 139*25c28e83SPiotr Jasiukajtis return (x); 140*25c28e83SPiotr Jasiukajtis xx.i[3] &= ~(i - 1); 141*25c28e83SPiotr Jasiukajtis if (rm == FSR_RP || (rm == FSR_RN && (frac > 0x80000000u || 142*25c28e83SPiotr Jasiukajtis (frac == 0x80000000 && (xx.i[3] & i))))) { 143*25c28e83SPiotr Jasiukajtis xx.i[3] += i; 144*25c28e83SPiotr Jasiukajtis if (xx.i[3] == 0) 145*25c28e83SPiotr Jasiukajtis if (++xx.i[2] == 0) 146*25c28e83SPiotr Jasiukajtis if (++xx.i[1] == 0) 147*25c28e83SPiotr Jasiukajtis xx.i[0]++; 148*25c28e83SPiotr Jasiukajtis } 149*25c28e83SPiotr Jasiukajtis } 150*25c28e83SPiotr Jasiukajtis 151*25c28e83SPiotr Jasiukajtis return (xx.q); 152*25c28e83SPiotr Jasiukajtis } 153*25c28e83SPiotr Jasiukajtis 154*25c28e83SPiotr Jasiukajtis #elif defined(__x86) 155*25c28e83SPiotr Jasiukajtis 156*25c28e83SPiotr Jasiukajtis /* inline template */ 157*25c28e83SPiotr Jasiukajtis extern long double frndint(long double); 158*25c28e83SPiotr Jasiukajtis 159*25c28e83SPiotr Jasiukajtis long double 160*25c28e83SPiotr Jasiukajtis __nearbyintl(long double x) { 161*25c28e83SPiotr Jasiukajtis long double z; 162*25c28e83SPiotr Jasiukajtis unsigned oldcwsw, cwsw; 163*25c28e83SPiotr Jasiukajtis 164*25c28e83SPiotr Jasiukajtis /* save the control and status words, mask the inexact exception */ 165*25c28e83SPiotr Jasiukajtis __fenv_getcwsw(&oldcwsw); 166*25c28e83SPiotr Jasiukajtis cwsw = oldcwsw | 0x00200000; 167*25c28e83SPiotr Jasiukajtis __fenv_setcwsw(&cwsw); 168*25c28e83SPiotr Jasiukajtis 169*25c28e83SPiotr Jasiukajtis z = frndint(x); 170*25c28e83SPiotr Jasiukajtis 171*25c28e83SPiotr Jasiukajtis /* 172*25c28e83SPiotr Jasiukajtis * restore the control and status words, preserving all but the 173*25c28e83SPiotr Jasiukajtis * inexact flag 174*25c28e83SPiotr Jasiukajtis */ 175*25c28e83SPiotr Jasiukajtis __fenv_getcwsw(&cwsw); 176*25c28e83SPiotr Jasiukajtis oldcwsw |= (cwsw & 0x1f); 177*25c28e83SPiotr Jasiukajtis __fenv_setcwsw(&oldcwsw); 178*25c28e83SPiotr Jasiukajtis 179*25c28e83SPiotr Jasiukajtis return (z); 180*25c28e83SPiotr Jasiukajtis } 181*25c28e83SPiotr Jasiukajtis 182*25c28e83SPiotr Jasiukajtis #else 183*25c28e83SPiotr Jasiukajtis #error Unknown architecture 184*25c28e83SPiotr Jasiukajtis #endif 185