1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
/* Copyright 2017 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "common.h"
#ifdef CONFIG_FPU
union ieee_float_shape_type {
float value;
uint32_t word;
};
/* Get a 32 bit int from a float. */
#define GET_FLOAT_WORD(i, d) \
do { \
union ieee_float_shape_type gf_u; \
gf_u.value = (d); \
(i) = gf_u.word; \
} while (0)
/* Set a float from a 32 bit int. */
#define SET_FLOAT_WORD(d, i) \
do { \
union ieee_float_shape_type sf_u; \
sf_u.word = (i); \
(d) = sf_u.value; \
} while (0)
float fabsf(float x)
{
uint32_t ix;
GET_FLOAT_WORD(ix, x);
SET_FLOAT_WORD(x, (ix & 0x7fffffff));
return x;
}
#define FLT_UWORD_IS_ZERO(x) ((x) == 0)
#define FLT_UWORD_IS_SUBNORMAL(x) ((x) < 0x00800000L)
#define FLT_UWORD_IS_FINITE(x) ((x) < 0x7f800000L)
static const float one = 1.0f, tiny = 1.0e-30f;
static float __ieee754_sqrtf(float x)
{
float z;
uint32_t r, hx;
int32_t ix, s, q, m, t, i;
GET_FLOAT_WORD(ix, x);
hx = ix & 0x7fffffff;
/*
* take care of Inf and NaN
* sqrt(NaN)=NaN, sqrt(+inf)=+inf, sqrt(-inf)=sNaN
*/
if (!FLT_UWORD_IS_FINITE(hx))
return x * x + x;
/* take care of zero and -ves */
if (FLT_UWORD_IS_ZERO(hx))
return x;
if (ix < 0)
return (x - x) / (x - x);
m = (ix >> 23);
if (FLT_UWORD_IS_SUBNORMAL(hx)) {
for (i = 0; (ix & 0x00800000L) == 0; i++)
ix <<= 1;
m -= i - 1;
}
m -= 127;
ix = (ix & 0x007fffffL) | 0x00800000L;
if (m & 1)
ix += ix;
m >>= 1;
ix += ix;
q = s = 0;
r = 0x01000000L;
while (r != 0) {
t = s + r;
if (t <= ix) {
s = t + r;
ix -= t;
q += r;
}
ix += ix;
r >>= 1;
}
if (ix != 0) {
z = one - tiny;
if (z >= one) {
z = one + tiny;
if (z > one)
q += 2;
else
q += (q & 1);
}
}
ix = (q >> 1) + 0x3f000000L;
ix += (m << 23);
SET_FLOAT_WORD(z, ix);
return z;
}
float sqrtf(float x)
{
return __ieee754_sqrtf(x);
}
#endif
|