1 /* $NetBSD: s_nextafterl.c,v 1.5 2014/01/31 19:38:47 matt Exp $ */
3 /* @(#)s_nextafter.c 5.1 93/09/24 */
5 * ====================================================
6 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
8 * Developed at SunPro, a Sun Microsystems, Inc. business.
9 * Permission to use, copy, modify, and distribute this
10 * software is freely granted, provided that this notice
12 * ====================================================
15 #include <sys/cdefs.h>
16 __RCSID("$NetBSD: s_nextafterl.c,v 1.5 2014/01/31 19:38:47 matt Exp $");
20 #include <machine/ieee.h>
22 #ifdef __HAVE_LONG_DOUBLE
25 #if LDBL_MAX_EXP != 0x4000
26 #error "Unsupported long double format"
29 #ifdef LDBL_IMPLICIT_NBIT
36 * return the next machine floating-point number of x in the
39 * If x == y, y shall be returned
40 * If x or y is NaN, a NaN shall be returned
43 nextafterl(long double x
, long double y
)
45 volatile long double t
;
46 union ieee_ext_u ux
, uy
;
51 if ((ux
.extu_exp
== EXT_EXP_INFNAN
&&
52 ((ux
.extu_frach
&~ LDBL_NBIT
)|ux
.extu_fracl
) != 0) ||
53 (uy
.extu_exp
== EXT_EXP_INFNAN
&&
54 ((uy
.extu_frach
&~ LDBL_NBIT
)|uy
.extu_fracl
) != 0))
55 return x
+y
; /* x or y is nan */
57 if (x
== y
) return y
; /* x=y, return y */
60 ux
.extu_frach
= 0; /* return +-minsubnormal */
62 ux
.extu_sign
= uy
.extu_sign
;
63 t
= ux
.extu_ld
* ux
.extu_ld
;
67 return ux
.extu_ld
; /* raise underflow flag */
70 if ((x
>0.0) ^ (x
<y
)) { /* x -= ulp */
71 if (ux
.extu_fracl
== 0) {
72 if ((ux
.extu_frach
& ~LDBL_NBIT
) == 0)
74 ux
.extu_frach
= (ux
.extu_frach
- 1) |
75 (ux
.extu_frach
& LDBL_NBIT
);
78 } else { /* x += ulp */
80 if (ux
.extu_fracl
== 0) {
81 ux
.extu_frach
= (ux
.extu_frach
+ 1) |
82 (ux
.extu_frach
& LDBL_NBIT
);
83 if ((ux
.extu_frach
& ~LDBL_NBIT
) == 0)
88 if (ux
.extu_exp
== EXT_EXP_INFNAN
)
89 return x
+x
; /* overflow */
91 if (ux
.extu_exp
== 0) { /* underflow */
92 #ifndef LDBL_IMPLICIT_NBIT
95 t
= ux
.extu_ld
* ux
.extu_ld
;
96 if (t
!= ux
.extu_ld
) /* raise underflow flag */
104 #endif /* __HAVE_LONG_DOUBLE */