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