Sun Mar 23 15:26:47 2014 UTC ()
Avoid strict aliasing problems


(martin)
diff -r1.2 -r1.3 src/lib/libm/noieee_src/n_exp2.c
diff -r1.1 -r1.2 src/lib/libm/noieee_src/n_exp2f.c

cvs diff -r1.2 -r1.3 src/lib/libm/noieee_src/n_exp2.c (expand / switch to unified diff)

--- src/lib/libm/noieee_src/n_exp2.c 2014/03/12 19:42:18 1.2
+++ src/lib/libm/noieee_src/n_exp2.c 2014/03/23 15:26:47 1.3
@@ -15,33 +15,34 @@ @@ -15,33 +15,34 @@
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE. 24 * SUCH DAMAGE.
25 */ 25 */
26 26
27#include <sys/cdefs.h> 27#include <sys/cdefs.h>
28__RCSID("$NetBSD: n_exp2.c,v 1.2 2014/03/12 19:42:18 martin Exp $"); 28__RCSID("$NetBSD: n_exp2.c,v 1.3 2014/03/23 15:26:47 martin Exp $");
29#ifdef __FBSDID 29#ifdef __FBSDID
30__FBSDID("$FreeBSD: src/lib/msun/src/s_exp2.c,v 1.7 2008/02/22 02:27:34 das Exp $"); 30__FBSDID("$FreeBSD: src/lib/msun/src/s_exp2.c,v 1.7 2008/02/22 02:27:34 das Exp $");
31#endif 31#endif
32 32
33#include <stdint.h> 33#include <stdint.h>
34#include <float.h> 34#include <float.h>
 35#include <string.h>
35 36
36#include "math.h" 37#include "math.h"
37 38
38#define TBLBITS 8 39#define TBLBITS 8
39#define TBLSIZE (1 << TBLBITS) 40#define TBLSIZE (1 << TBLBITS)
40 41
41static const double 42static const double
42 huge = 0x1p126, 43 huge = 0x1p126,
43 redux = 0x1.8p52 / TBLSIZE, 44 redux = 0x1.8p52 / TBLSIZE,
44 P1 = 0x1.62e42fefa39efp-1, 45 P1 = 0x1.62e42fefa39efp-1,
45 P2 = 0x1.ebfbdff82c575p-3, 46 P2 = 0x1.ebfbdff82c575p-3,
46 P3 = 0x1.c6b08d704a0a6p-5, 47 P3 = 0x1.c6b08d704a0a6p-5,
47 P4 = 0x1.3b2ab88f70400p-7, 48 P4 = 0x1.3b2ab88f70400p-7,
@@ -334,59 +335,61 @@ static const double tbl[TBLSIZE * 2] = { @@ -334,59 +335,61 @@ static const double tbl[TBLSIZE * 2] = {
334 * Note that the range of i is +-TBLSIZE/2, so we actually index the tables 335 * Note that the range of i is +-TBLSIZE/2, so we actually index the tables
335 * by i0 = i + TBLSIZE/2. For cache efficiency, exp2t[] and eps[] are 336 * by i0 = i + TBLSIZE/2. For cache efficiency, exp2t[] and eps[] are
336 * virtual tables, interleaved in the real table tbl[]. 337 * virtual tables, interleaved in the real table tbl[].
337 * 338 *
338 * This method is due to Gal, with many details due to Gal and Bachelis: 339 * This method is due to Gal, with many details due to Gal and Bachelis:
339 * 340 *
340 * Gal, S. and Bachelis, B. An Accurate Elementary Mathematical Library 341 * Gal, S. and Bachelis, B. An Accurate Elementary Mathematical Library
341 * for the IEEE Floating Point Standard. TOMS 17(1), 26-46 (1991). 342 * for the IEEE Floating Point Standard. TOMS 17(1), 26-46 (1991).
342 */ 343 */
343double 344double
344exp2(double x) 345exp2(double x)
345{ 346{
346 double r, t, twopk, z; 347 double r, t, twopk, z;
347 uint32_t hx, ix, i0; 348 uint32_t hx, ix, i0, temp;
348 int k, big; 349 int k, big;
349 350
350 /* Filter out exceptional cases. */ 351 /* Filter out exceptional cases. */
351 hx = ((uint32_t*)&x)[0]; 352 memcpy(&hx, &x, sizeof(hx));
352 ix = hx & 0x7fffffff; /* high word of |x| */ 353 ix = hx & 0x7fffffff; /* high word of |x| */
353 if(ix >= 0x40900000) { /* |x| >= 1024 */ 354 if(ix >= 0x40900000) { /* |x| >= 1024 */
354 if(x >= 0x1.0p10) 355 if(x >= 0x1.0p10)
355 return (huge * huge); /* overflow */ 356 return (huge * huge); /* overflow */
356 if(x <= -0x1.0ccp10) 357 if(x <= -0x1.0ccp10)
357 return (twom1000 * twom1000); /* underflow */ 358 return (twom1000 * twom1000); /* underflow */
358 } else if (ix < 0x3c900000) { /* |x| < 0x1p-54 */ 359 } else if (ix < 0x3c900000) { /* |x| < 0x1p-54 */
359 return (1.0 + x); 360 return (1.0 + x);
360 } 361 }
361 362
362 /* Reduce x, computing z, i0, and k. */ 363 /* Reduce x, computing z, i0, and k. */
363 (*(volatile double*)&t) = x + redux; 364 (*(volatile double*)&t) = x + redux;
364 i0 = ((uint32_t*)&t)[1]; 365 i0 = ((uint32_t*)&t)[1];
365 i0 += TBLSIZE / 2; 366 i0 += TBLSIZE / 2;
366 k = (i0 >> TBLBITS) << 20; 367 k = (i0 >> TBLBITS) << 20;
367 i0 = (i0 & (TBLSIZE - 1)) << 1; 368 i0 = (i0 & (TBLSIZE - 1)) << 1;
368 t -= redux; 369 t -= redux;
369 z = x - t; 370 z = x - t;
370 371
371 /* Compute r = exp2(y) = exp2t[i0] * p(z - eps[i]). */ 372 /* Compute r = exp2(y) = exp2t[i0] * p(z - eps[i]). */
372 t = tbl[i0]; /* exp2t[i0] */ 373 t = tbl[i0]; /* exp2t[i0] */
373 z -= tbl[i0 + 1]; /* eps[i0] */ 374 z -= tbl[i0 + 1]; /* eps[i0] */
374 big = k >= -1021 << 20; 375 big = k >= -1021 << 20;
375 if (big) { 376 if (big) {
376 ((uint32_t*)&twopk)[0] = 0x3ff00000+k; 377 temp = 0x3ff00000+k;
377 ((uint32_t*)&twopk)[1] = 0; 378 twopk = 0.0;
 379 memcpy(&twopk, &temp, sizeof(temp));
378 } else { 380 } else {
379 ((uint32_t*)&twopk)[0] = 0x3ff00000+k + (1000 << 20); 381 temp = 0x3ff00000+k + (1000 << 20);
380 ((uint32_t*)&twopk)[1] = 0; 382 twopk = 0.0;
 383 memcpy(&twopk, &temp, sizeof(temp));
381 } 384 }
382 r = t + t * z * (P1 + z * (P2 + z * (P3 + z * (P4 + z * P5)))); 385 r = t + t * z * (P1 + z * (P2 + z * (P3 + z * (P4 + z * P5))));
383 386
384 /* Scale by 2**(k>>20). */ 387 /* Scale by 2**(k>>20). */
385 if (big) { 388 if (big) {
386 /*if (k == 1024 << 20) 389 /*if (k == 1024 << 20)
387 return (r * 2.0 * 0x1p1023); */ 390 return (r * 2.0 * 0x1p1023); */
388 return (r * twopk); 391 return (r * twopk);
389 } else { 392 } else {
390 return (r * twopk * twom1000); 393 return (r * twopk * twom1000);
391 } 394 }
392} 395}

cvs diff -r1.1 -r1.2 src/lib/libm/noieee_src/n_exp2f.c (expand / switch to unified diff)

--- src/lib/libm/noieee_src/n_exp2f.c 2014/03/06 10:55:57 1.1
+++ src/lib/libm/noieee_src/n_exp2f.c 2014/03/23 15:26:47 1.2
@@ -15,33 +15,34 @@ @@ -15,33 +15,34 @@
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE. 24 * SUCH DAMAGE.
25 */ 25 */
26 26
27#include <sys/cdefs.h> 27#include <sys/cdefs.h>
28__RCSID("$NetBSD: n_exp2f.c,v 1.1 2014/03/06 10:55:57 martin Exp $"); 28__RCSID("$NetBSD: n_exp2f.c,v 1.2 2014/03/23 15:26:47 martin Exp $");
29#ifdef __FBSDID 29#ifdef __FBSDID
30__FBSDID("$FreeBSD: src/lib/msun/src/s_exp2f.c,v 1.9 2008/02/22 02:27:34 das Exp $"); 30__FBSDID("$FreeBSD: src/lib/msun/src/s_exp2f.c,v 1.9 2008/02/22 02:27:34 das Exp $");
31#endif 31#endif
32 32
33#include <stdint.h> 33#include <stdint.h>
34#include <float.h> 34#include <float.h>
 35#include <string.h>
35 36
36#include "math.h" 37#include "math.h"
37 38
38#define TBLBITS 4 39#define TBLBITS 4
39#define TBLSIZE (1 << TBLBITS) 40#define TBLSIZE (1 << TBLBITS)
40 41
41static const float 42static const float
42 huge = 0x1p100f, 43 huge = 0x1p100f,
43 redux = 0x1.8p23f / TBLSIZE, 44 redux = 0x1.8p23f / TBLSIZE,
44 P1 = 0x1.62e430p-1f, 45 P1 = 0x1.62e430p-1f,
45 P2 = 0x1.ebfbe0p-3f, 46 P2 = 0x1.ebfbe0p-3f,
46 P3 = 0x1.c6b348p-5f, 47 P3 = 0x1.c6b348p-5f,
47 P4 = 0x1.3b2c9cp-7f; 48 P4 = 0x1.3b2c9cp-7f;
@@ -89,46 +90,47 @@ static const double exp2ft[TBLSIZE] = { @@ -89,46 +90,47 @@ static const double exp2ft[TBLSIZE] = {
89 * roundoff error insignificant and simplifies the scaling step. 90 * roundoff error insignificant and simplifies the scaling step.
90 * 91 *
91 * This method is due to Tang, but I do not use his suggested parameters: 92 * This method is due to Tang, but I do not use his suggested parameters:
92 * 93 *
93 * Tang, P. Table-driven Implementation of the Exponential Function 94 * Tang, P. Table-driven Implementation of the Exponential Function
94 * in IEEE Floating-Point Arithmetic. TOMS 15(2), 144-157 (1989). 95 * in IEEE Floating-Point Arithmetic. TOMS 15(2), 144-157 (1989).
95 */ 96 */
96float 97float
97exp2f(float x) 98exp2f(float x)
98{ 99{
99 double tv, twopk, u, z; 100 double tv, twopk, u, z;
100 float t; 101 float t;
101 uint32_t hx, ix, i0; 102 uint32_t hx, ix, i0;
102 int32_t k; 103 int32_t k, temp;
103 104
104 /* Filter out exceptional cases. */ 105 /* Filter out exceptional cases. */
105 hx = *((uint32_t*)&x); 106 memcpy(&hx, &x, sizeof(hx));
106 ix = hx & 0x7fffffff; /* high word of |x| */ 107 ix = hx & 0x7fffffff; /* high word of |x| */
107 if(ix >= 0x43000000) { /* |x| >= 128 */ 108 if(ix >= 0x43000000) { /* |x| >= 128 */
108 if(x >= 0x1.0p7f) 109 if(x >= 0x1.0p7f)
109 return (huge * huge); /* overflow */ 110 return (huge * huge); /* overflow */
110 if(x <= -0x1.2cp7f) 111 if(x <= -0x1.2cp7f)
111 return (twom100 * twom100); /* underflow */ 112 return (twom100 * twom100); /* underflow */
112 } else if (ix <= 0x33000000) { /* |x| <= 0x1p-25 */ 113 } else if (ix <= 0x33000000) { /* |x| <= 0x1p-25 */
113 return (1.0f + x); 114 return (1.0f + x);
114 } 115 }
115 116
116 /* Reduce x, computing z, i0, and k. */ 117 /* Reduce x, computing z, i0, and k. */
117 *((volatile float*)&t) = x + redux; 118 i0 = x + redux;
118 i0 = *((uint32_t*)&t); 119 memcpy(&t, &i0, sizeof(t));
119 i0 += TBLSIZE / 2; 120 i0 += TBLSIZE / 2;
120 k = (i0 >> TBLBITS) << 20; 121 k = (i0 >> TBLBITS) << 20;
121 i0 &= TBLSIZE - 1; 122 i0 &= TBLSIZE - 1;
122 t -= redux; 123 t -= redux;
123 z = x - t; 124 z = x - t;
124 ((uint32_t*)&twopk)[0] = 0x3ff00000+k; 125 temp = 0x3ff00000+k;
125 ((uint32_t*)&twopk)[1] = 0; 126 twopk = 0.0;
 127 memcpy(&twopk, &temp, sizeof(temp));
126 128
127 /* Compute r = exp2(y) = exp2ft[i0] * p(z). */ 129 /* Compute r = exp2(y) = exp2ft[i0] * p(z). */
128 tv = exp2ft[i0]; 130 tv = exp2ft[i0];
129 u = tv * z; 131 u = tv * z;
130 tv = tv + u * (P1 + z * P2) + u * (z * z) * (P3 + z * P4); 132 tv = tv + u * (P1 + z * P2) + u * (z * z) * (P3 + z * P4);
131 133
132 /* Scale by 2**(k>>20). */ 134 /* Scale by 2**(k>>20). */
133 return (tv * twopk); 135 return (tv * twopk);
134} 136}