117 lines
1.9 KiB
C
117 lines
1.9 KiB
C
|
/* 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
|