Peano
Loading...
Searching...
No Matches
cbrt.h
Go to the documentation of this file.
1/*******************************************************************************
2 * This file is part of SWIFT.
3 * Copyright (c) 2016 Pedro Gonnet (pedro.gonnet@durham.ac.uk)
4 * Matthieu Schaller (schaller@strw.leidenuniv.nl)
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published
8 * by the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 *
19 ******************************************************************************/
20#ifndef SWIFT_CBRT_H
21#define SWIFT_CBRT_H
22
23/* Config parameters. */
24#include <config.h>
25
26/* Some standard headers. */
27#include <math.h>
28
29/* Local headers. */
30#include "inline.h"
31
47__attribute__((always_inline)) INLINE static float icbrtf(float x_in) {
48
49 union {
50 float as_float;
51 unsigned int as_uint;
52 int as_int;
53 } cast;
54
55 /* Extract the exponent. */
56 cast.as_float = x_in;
57 const int exponent = ((cast.as_int & 0x7f800000) >> 23) - 127;
58
59 /* Clear the exponent and sign to get the mantissa. */
60 cast.as_uint = (cast.as_uint & ~0xff800000) | 0x3f800000;
61 const float x_norm = cast.as_float;
62
63 /* Multiply by sqrt(1/2) and subtract one, should then be in the
64 range [sqrt(1/2) - 1, sqrt(2) - 1). */
65 const float x = x_norm * (float)M_SQRT1_2 - 1.0f;
66
67 /* Compute the polynomial interpolant. */
68 float res =
69 9.99976591940035e-01f +
70 x * (-3.32901212909283e-01f +
71 x * (2.24361110929912e-01f +
72 x * (-1.88913279594895e-01f + x * 1.28384036492344e-01f)));
73
74 /* Compute the new exponent and the correction factor. */
75 int exponent_new = exponent;
76 if (exponent_new < 0) exponent_new -= 2;
77 exponent_new = -exponent_new / 3;
78 const int exponent_rem = exponent + 3 * exponent_new;
79 cast.as_uint = (exponent_new + 127) << 23;
80 static const float scale[3] = {8.90898718140339e-01f, 7.07106781186548e-01f,
81 5.61231024154687e-01f};
82 const float exponent_scale = cast.as_float * scale[exponent_rem];
83
84 /* Scale the result and set the correct sign. */
85 res = copysignf(res * exponent_scale, x_in);
86
87 /* One step of Newton iteration to refine the result. */
88 res *= (1.0f / 3.0f) * (4.0f - x_in * res * res * res);
89
90 /* We're done. */
91 return res;
92}
93
94#endif /* SWIFT_CBRT_H */
__attribute__((always_inline)) INLINE static float icbrtf(float x_in)
Compute the inverse cube root of a single-precision floating-point number.
Definition cbrt.h:47
#define INLINE
Defines inline.
Definition inline.h:36