]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - lib/msun/src/s_nextafterl.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / lib / msun / src / s_nextafterl.c
1 /* @(#)s_nextafter.c 5.1 93/09/24 */
2 /*
3  * ====================================================
4  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
5  *
6  * Developed at SunPro, a Sun Microsystems, Inc. business.
7  * Permission to use, copy, modify, and distribute this
8  * software is freely granted, provided that this notice
9  * is preserved.
10  * ====================================================
11  */
12
13 #ifndef lint
14 static char rcsid[] = "$FreeBSD$";
15 #endif
16
17 /* IEEE functions
18  *      nextafter(x,y)
19  *      return the next machine floating-point number of x in the
20  *      direction toward y.
21  *   Special cases:
22  */
23
24 #include <sys/cdefs.h>
25 #include <float.h>
26
27 #include "fpmath.h"
28 #include "math.h"
29 #include "math_private.h"
30
31 #if LDBL_MAX_EXP != 0x4000
32 #error "Unsupported long double format"
33 #endif
34
35 long double
36 nextafterl(long double x, long double y)
37 {
38         volatile long double t;
39         union IEEEl2bits ux, uy;
40
41         ux.e = x;
42         uy.e = y;
43
44         if ((ux.bits.exp == 0x7fff &&
45              ((ux.bits.manh&~LDBL_NBIT)|ux.bits.manl) != 0) ||
46             (uy.bits.exp == 0x7fff &&
47              ((uy.bits.manh&~LDBL_NBIT)|uy.bits.manl) != 0))
48            return x+y;  /* x or y is nan */
49         if(x==y) return y;              /* x=y, return y */
50         if(x==0.0) {
51             ux.bits.manh = 0;                   /* return +-minsubnormal */
52             ux.bits.manl = 1;
53             ux.bits.sign = uy.bits.sign;
54             t = ux.e*ux.e;
55             if(t==ux.e) return t; else return ux.e; /* raise underflow flag */
56         }
57         if(x>0.0 ^ x<y) {                       /* x -= ulp */
58             if(ux.bits.manl==0) {
59                 if ((ux.bits.manh&~LDBL_NBIT)==0)
60                     ux.bits.exp -= 1;
61                 ux.bits.manh = (ux.bits.manh - 1) | (ux.bits.manh & LDBL_NBIT);
62             }
63             ux.bits.manl -= 1;
64         } else {                                /* x += ulp */
65             ux.bits.manl += 1;
66             if(ux.bits.manl==0) {
67                 ux.bits.manh = (ux.bits.manh + 1) | (ux.bits.manh & LDBL_NBIT);
68                 if ((ux.bits.manh&~LDBL_NBIT)==0)
69                     ux.bits.exp += 1;
70             }
71         }
72         if(ux.bits.exp==0x7fff) return x+x;     /* overflow  */
73         if(ux.bits.exp==0) {                    /* underflow */
74             mask_nbit_l(ux);
75             t = ux.e * ux.e;
76             if(t!=ux.e)                 /* raise underflow flag */
77                 return ux.e;
78         }
79         return ux.e;
80 }
81
82 __strong_reference(nextafterl, nexttowardl);