2 * Single-precision log function.
4 * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 * See https://llvm.org/LICENSE.txt for license information.
6 * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
11 #include "math_config.h"
17 ULP error: 0.818 (nearest rounding.)
18 Relative error: 1.957 * 2^-26 (before rounding.)
21 #define T __logf_data.tab
22 #define A __logf_data.poly
23 #define Ln2 __logf_data.ln2
24 #define N (1 << LOGF_TABLE_BITS)
25 #define OFF 0x3f330000
30 /* double_t for better performance on targets with FLT_EVAL_METHOD==2. */
31 double_t z
, r
, r2
, y
, y0
, invc
, logc
;
37 /* Fix sign of zero with downward rounding when x==1. */
38 if (unlikely (ix
== 0x3f800000))
41 if (unlikely (ix
- 0x00800000 >= 0x7f800000 - 0x00800000))
43 /* x < 0x1p-126 or inf or nan. */
45 return __math_divzerof (1);
46 if (ix
== 0x7f800000) /* log(inf) == inf. */
48 if ((ix
& 0x80000000) || ix
* 2 >= 0xff000000)
49 return __math_invalidf (x
);
50 /* x is subnormal, normalize it. */
51 ix
= asuint (x
* 0x1p
23f
);
55 /* x = 2^k z; where z is in range [OFF,2*OFF] and exact.
56 The range is split into N subintervals.
57 The ith subinterval contains z and c is near its center. */
59 i
= (tmp
>> (23 - LOGF_TABLE_BITS
)) % N
;
60 k
= (int32_t) tmp
>> 23; /* arithmetic shift */
61 iz
= ix
- (tmp
& 0x1ff << 23);
64 z
= (double_t
) asfloat (iz
);
66 /* log(x) = log1p(z/c-1) + log(c) + k*Ln2 */
68 y0
= logc
+ (double_t
) k
* Ln2
;
70 /* Pipelined polynomial evaluation to approximate log1p(r). */
74 y
= y
* r2
+ (y0
+ r
);
75 return eval_as_float (y
);
78 strong_alias (logf
, __logf_finite
)
79 hidden_alias (logf
, __ieee754_logf
)