Line 0
Link Here
|
|
|
1 |
/*- |
2 |
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD |
3 |
* |
4 |
* Copyright (c) 2011 David Schultz <das@FreeBSD.ORG> |
5 |
* All rights reserved. |
6 |
* |
7 |
* Redistribution and use in source and binary forms, with or without |
8 |
* modification, are permitted provided that the following conditions |
9 |
* are met: |
10 |
* 1. Redistributions of source code must retain the above copyright |
11 |
* notice, this list of conditions and the following disclaimer. |
12 |
* 2. Redistributions in binary form must reproduce the above copyright |
13 |
* notice, this list of conditions and the following disclaimer in the |
14 |
* documentation and/or other materials provided with the distribution. |
15 |
* |
16 |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
17 |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
18 |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
19 |
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
20 |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
21 |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
22 |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
23 |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
24 |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
25 |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
26 |
* SUCH DAMAGE. |
27 |
*/ |
28 |
|
29 |
#include <sys/cdefs.h> |
30 |
__FBSDID("$FreeBSD$"); |
31 |
|
32 |
#include <complex.h> |
33 |
|
34 |
#include "math.h" |
35 |
#include "math_private.h" |
36 |
|
37 |
#warning These functions are broken on ld128 architectures. |
38 |
#warning Functions defined here are currently unused. |
39 |
#warning Someone who cares needs to convert src/k_exp.c. |
40 |
|
41 |
#if 0 |
42 |
static const uint32_t k = 1799; /* constant for reduction */ |
43 |
static const double kln2 = 1246.97177782734161156; /* k * ln2 */ |
44 |
#endif |
45 |
|
46 |
/* |
47 |
* Compute exp(x), scaled to avoid spurious overflow. An exponent is |
48 |
* returned separately in 'expt'. |
49 |
* |
50 |
* Input: ln(DBL_MAX) <= x < ln(2 * DBL_MAX / DBL_MIN_DENORM) ~= 1454.91 |
51 |
* Output: 2**1023 <= y < 2**1024 |
52 |
*/ |
53 |
static long double |
54 |
__frexp_expl(long double x, int *expt) |
55 |
{ |
56 |
#if 0 |
57 |
double exp_x; |
58 |
uint32_t hx; |
59 |
|
60 |
/* |
61 |
* We use exp(x) = exp(x - kln2) * 2**k, carefully chosen to |
62 |
* minimize |exp(kln2) - 2**k|. We also scale the exponent of |
63 |
* exp_x to MAX_EXP so that the result can be multiplied by |
64 |
* a tiny number without losing accuracy due to denormalization. |
65 |
*/ |
66 |
exp_x = exp(x - kln2); |
67 |
GET_HIGH_WORD(hx, exp_x); |
68 |
*expt = (hx >> 20) - (0x3ff + 1023) + k; |
69 |
SET_HIGH_WORD(exp_x, (hx & 0xfffff) | ((0x3ff + 1023) << 20)); |
70 |
return (exp_x); |
71 |
#endif |
72 |
return (x - x) / (x - x); |
73 |
} |
74 |
|
75 |
/* |
76 |
* __ldexp_exp(x, expt) and __ldexp_cexp(x, expt) compute exp(x) * 2**expt. |
77 |
* They are intended for large arguments (real part >= ln(DBL_MAX)) |
78 |
* where care is needed to avoid overflow. |
79 |
* |
80 |
* The present implementation is narrowly tailored for our hyperbolic and |
81 |
* exponential functions. We assume expt is small (0 or -1), and the caller |
82 |
* has filtered out very large x, for which overflow would be inevitable. |
83 |
*/ |
84 |
|
85 |
long double |
86 |
__ldexp_expl(long double x, int expt) |
87 |
{ |
88 |
#if 0 |
89 |
double exp_x, scale; |
90 |
int ex_expt; |
91 |
|
92 |
exp_x = __frexp_exp(x, &ex_expt); |
93 |
expt += ex_expt; |
94 |
INSERT_WORDS(scale, (0x3ff + expt) << 20, 0); |
95 |
return (exp_x * scale); |
96 |
#endif |
97 |
return (x - x) / (x - x); |
98 |
} |
99 |
|
100 |
long double complex |
101 |
__ldexp_cexpl(long double complex z, int expt) |
102 |
{ |
103 |
#if 0 |
104 |
double x, y, exp_x, scale1, scale2; |
105 |
int ex_expt, half_expt; |
106 |
|
107 |
x = creal(z); |
108 |
y = cimag(z); |
109 |
exp_x = __frexp_exp(x, &ex_expt); |
110 |
expt += ex_expt; |
111 |
|
112 |
/* |
113 |
* Arrange so that scale1 * scale2 == 2**expt. We use this to |
114 |
* compensate for scalbn being horrendously slow. |
115 |
*/ |
116 |
half_expt = expt / 2; |
117 |
INSERT_WORDS(scale1, (0x3ff + half_expt) << 20, 0); |
118 |
half_expt = expt - half_expt; |
119 |
INSERT_WORDS(scale2, (0x3ff + half_expt) << 20, 0); |
120 |
|
121 |
sincos(y, &s, &c); |
122 |
return (CMPLX(c) * exp_x * scale1 * scale2, |
123 |
s * exp_x * scale1 * scale2)); |
124 |
#endif |
125 |
return (x - x) / (x - x); |
126 |
} |