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 int *px = (int *) &x; 80 int *py = (int *) &y; 81 82 if (x == y) 83 return (y); /* C99 requirement */ 84 if (x != x || y != y) 85 return (x * y); 86 87 if (ISZEROL(x)) { /* x == 0.0 */ 88 px[n0] = py[n0] & XSGNMSK; 89 px[n1] = px[n2] = 0; 90 px[n3] = 1; 91 } else { 92 X86PDNRM1(x); 93 if ((px[n0] & XSGNMSK) == 0) { /* x > 0.0 */ 94 if (x > y) /* x > y */ 95 DEC(px) 96 else 97 INC(px) 98 } else { 99 if (x < y) /* x < y */ 100 DEC(px) 101 else 102 INC(px) 103 } 104 } 105 #ifndef lint 106 { 107 volatile long double dummy; 108 int k = XBIASED_EXP(x); 109 110 if (k == 0) 111 dummy = LDBL_MIN * copysignl(LDBL_MIN, x); 112 else if (k == 0x7fff) 113 dummy = LDBL_MAX * copysignl(LDBL_MAX, x); 114 } 115 #endif 116 return (x); 117 } 118