this repo has no description
1/*
2 * nextafterf.c
3 * cLibm
4 *
5 * Created by Ian Ollmann on 6/14/07.
6 * Copyright 2007 Apple Inc. All rights reserved.
7 *
8 */
9
10#include <math.h>
11#include <stdint.h>
12
13#ifdef ARMLIBM_SET_FLAGS
14#include <fenv.h>
15#include "required_arithmetic.h"
16#pragma STDC FENV_ACCESS ON
17
18float nextafterf( float x, float y )
19{
20 union{ float f; uint32_t u;} ux = { x };
21 uint32_t step = 1;
22
23 if( y != y || x != x)
24 return x + y;
25
26 if( y <= x ) // a subtraction here would risk Inf-Inf
27 {
28 if( y == x )
29 return y; //make sure sign of 0 is correct
30
31 step = -1;
32 }
33
34 //correct for the sign
35 int32_t signMask = (int32_t) ux.u >> 31;
36 step = (step ^ signMask) - signMask;
37
38 uint32_t absux = ux.u & 0x7fffffffU;
39
40 if( absux - 0x00800001U >= 0x7f7fffffU - 0x00800001U )
41 { //0, Inf, max finite, min normal, denorm
42 //Nan is handled above and won't occur here
43 //Inf can just fall through. We are only here if y!=x.
44
45 if( absux == 0 ) // zero
46 {
47 ux.f = y;
48 required_multiply_float( 0x1.0p-120f, 0x1.0p-120f );
49 ux.u = (ux.u & 0x80000000U) + 1U;
50 return ux.f;
51 }
52 else if( absux == 0x7f7fffffU ) // max finite
53 {
54 ux.u += step;
55
56 //if infinity is the result, set some flags
57 if( 0 == (ux.u & 2) )
58 {
59 required_add_float( x, 1.0f ); //set inexact
60 required_multiply_float( x, x ); //set overflow
61 }
62
63 return ux.f;
64 }
65
66 ux.u += step;
67 if( 0 == (ux.u & 0x7f800000))
68 required_multiply_float( 0x1.0p-120f, 0x1.0p-120f );
69
70 return ux.f;
71 }
72
73 ux.u += step;
74
75 return ux.f;
76}
77
78#else
79
80float nextafterf( float x, float y )
81{
82 union{ float f; uint32_t u;} ux = { x };
83 uint32_t step = 1;
84
85 if( y != y || x != x)
86 return x + y;
87
88 if( y <= x ) // a subtraction here would risk Inf-Inf
89 {
90 if( y == x )
91 return y; //make sure sign of 0 is correct
92
93 step = -1;
94 }
95
96 //correct for the sign
97 int32_t signMask = (int32_t) ux.u >> 31;
98 step = (step ^ signMask) - signMask;
99
100 uint32_t absux = ux.u & 0x7fffffffU;
101
102 if( absux == 0 ) // zero
103 {
104 ux.f = y;
105 ux.u = (ux.u & 0x80000000U) + 1U;
106 return ux.f;
107 }
108
109 ux.u += step;
110 return ux.f;
111}
112
113#endif // ARMLIBM_SET_FLAGS