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 __nexttowardl = nexttowardl 31 32 #include "libm.h" 33 #include <float.h> /* LDBL_MAX, LDBL_MIN */ 34 35 #if defined(__sparc) 36 #define n0 0 37 #define n1 1 38 #define n2 2 39 #define n3 3 40 #define X86PDNRM1(x) 41 #define INC(px) { \ 42 if (++px[n3] == 0) \ 43 if (++px[n2] == 0) \ 44 if (++px[n1] == 0) \ 45 ++px[n0]; \ 46 } 47 #define DEC(px) { \ 48 if (--px[n3] == 0xffffffff) \ 49 if (--px[n2] == 0xffffffff) \ 50 if (--px[n1] == 0xffffffff) \ 51 --px[n0]; \ 52 } 53 #elif defined(__x86) 54 #define n0 2 55 #define n1 1 56 #define n2 0 57 #define n3 0 58 /* 59 * if pseudo-denormal, replace by the equivalent normal 60 */ 61 #define X86PDNRM1(x) if (XBIASED_EXP(x) == 0 && (((int *)&x)[1] & \ 62 0x80000000) != 0) \ 63 ((int *)&x)[2] |= 1 64 #define INC(px) { \ 65 if (++px[n2] == 0) \ 66 if ((++px[n1] & ~0x80000000) == 0) \ 67 px[n1] = 0x80000000, ++px[n0]; \ 68 } 69 #define DEC(px) { \ 70 if (--px[n2] == 0xffffffff) \ 71 if (--px[n1] == 0x7fffffff) \ 72 if ((--px[n0] & 0x7fff) != 0) \ 73 px[n1] |= 0x80000000; \ 74 } 75 #endif 76 77 long double 78 nexttowardl(long double x, long double y) 79 { 80 int *px = (int *)&x; 81 int *py = (int *)&y; 82 83 if (x == y) 84 return (y); /* C99 requirement */ 85 if (x != x || y != y) 86 return (x * y); 87 88 if (ISZEROL(x)) { /* x == 0.0 */ 89 px[n0] = py[n0] & XSGNMSK; 90 px[n1] = px[n2] = 0; 91 px[n3] = 1; 92 } else { 93 X86PDNRM1(x); 94 if ((px[n0] & XSGNMSK) == 0) { /* x > 0.0 */ 95 if (x > y) /* x > y */ 96 DEC(px) 97 else 98 INC(px) 99 } else { 100 if (x < y) /* x < y */ 101 DEC(px) 102 else 103 INC(px) 104 } 105 } 106 #ifndef lint 107 { 108 volatile long double dummy __unused; 109 int k = XBIASED_EXP(x); 110 111 if (k == 0) 112 dummy = LDBL_MIN * copysignl(LDBL_MIN, x); 113 else if (k == 0x7fff) 114 dummy = LDBL_MAX * copysignl(LDBL_MAX, x); 115 } 116 #endif 117 return (x); 118 }