]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - lib/msun/src/s_nextafterl.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.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 #include <sys/cdefs.h>
14 __FBSDID("$FreeBSD$");
15
16 /* IEEE functions
17  *      nextafter(x,y)
18  *      return the next machine floating-point number of x in the
19  *      direction toward y.
20  *   Special cases:
21  */
22
23 #include <float.h>
24
25 #include "fpmath.h"
26 #include "math.h"
27 #include "math_private.h"
28
29 #if LDBL_MAX_EXP != 0x4000
30 #error "Unsupported long double format"
31 #endif
32
33 long double
34 nextafterl(long double x, long double y)
35 {
36         volatile long double t;
37         union IEEEl2bits ux, uy;
38
39         ux.e = x;
40         uy.e = y;
41
42         if ((ux.bits.exp == 0x7fff &&
43              ((ux.bits.manh&~LDBL_NBIT)|ux.bits.manl) != 0) ||
44             (uy.bits.exp == 0x7fff &&
45              ((uy.bits.manh&~LDBL_NBIT)|uy.bits.manl) != 0))
46            return x+y;  /* x or y is nan */
47         if(x==y) return y;              /* x=y, return y */
48         if(x==0.0) {
49             ux.bits.manh = 0;                   /* return +-minsubnormal */
50             ux.bits.manl = 1;
51             ux.bits.sign = uy.bits.sign;
52             t = ux.e*ux.e;
53             if(t==ux.e) return t; else return ux.e; /* raise underflow flag */
54         }
55         if(x>0.0 ^ x<y) {                       /* x -= ulp */
56             if(ux.bits.manl==0) {
57                 if ((ux.bits.manh&~LDBL_NBIT)==0)
58                     ux.bits.exp -= 1;
59                 ux.bits.manh = (ux.bits.manh - 1) | (ux.bits.manh & LDBL_NBIT);
60             }
61             ux.bits.manl -= 1;
62         } else {                                /* x += ulp */
63             ux.bits.manl += 1;
64             if(ux.bits.manl==0) {
65                 ux.bits.manh = (ux.bits.manh + 1) | (ux.bits.manh & LDBL_NBIT);
66                 if ((ux.bits.manh&~LDBL_NBIT)==0)
67                     ux.bits.exp += 1;
68             }
69         }
70         if(ux.bits.exp==0x7fff) return x+x;     /* overflow  */
71         if(ux.bits.exp==0) {                    /* underflow */
72             mask_nbit_l(ux);
73             t = ux.e * ux.e;
74             if(t!=ux.e)                 /* raise underflow flag */
75                 return ux.e;
76         }
77         return ux.e;
78 }
79
80 __strong_reference(nextafterl, nexttowardl);