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 __rintl = rintl 31 32 /* 33 * rintl(long double x) return x rounded to integral according to 34 * the prevailing rounding direction 35 * 36 * NOTE: aintl(x), anintl(x), ceill(x), floorl(x), and rintl(x) return result 37 * with the same sign as x's, including 0.0L. 38 */ 39 40 #include "libm.h" 41 #include "longdouble.h" 42 43 extern enum fp_precision_type __swapRP(enum fp_precision_type); 44 45 static const double one = 1.0; 46 static const long double qzero = 0.0L; 47 48 long double 49 rintl(long double x) { 50 enum fp_precision_type rp; 51 long double t, w, two112; 52 int *pt = (int *) &two112; 53 54 if (!finitel(x)) 55 return (x + x); 56 57 if (*(int *) &one != 0) { /* set two112 = 2^112 */ 58 pt[0] = 0x406f0000; 59 pt[1] = pt[2] = pt[3] = 0; 60 } else { 61 pt[3] = 0x406f0000; 62 pt[0] = pt[1] = pt[2] = 0; 63 } 64 65 if (fabsl(x) >= two112) 66 return (x); /* already an integer */ 67 t = copysignl(two112, x); 68 rp = __swapRP(fp_extended); /* make sure precision is long double */ 69 w = x + t; /* x+sign(x)*2^112 rounded to integer */ 70 (void) __swapRP(rp); /* restore precision mode */ 71 if (w == t) 72 return (copysignl(qzero, x)); /* x rounded to zero */ 73 else 74 return (w - t); 75 }