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
nexttowardl(long double x,long double y)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