1bbbf1280Sopenharmony_ci/* 2bbbf1280Sopenharmony_ci * Single-precision log function. 3bbbf1280Sopenharmony_ci * 4bbbf1280Sopenharmony_ci * Copyright (c) 2017-2019, Arm Limited. 5bbbf1280Sopenharmony_ci * SPDX-License-Identifier: MIT 6bbbf1280Sopenharmony_ci */ 7bbbf1280Sopenharmony_ci 8bbbf1280Sopenharmony_ci#include <math.h> 9bbbf1280Sopenharmony_ci#include <stdint.h> 10bbbf1280Sopenharmony_ci#include "math_config.h" 11bbbf1280Sopenharmony_ci 12bbbf1280Sopenharmony_ci/* 13bbbf1280Sopenharmony_ciLOGF_TABLE_BITS = 4 14bbbf1280Sopenharmony_ciLOGF_POLY_ORDER = 4 15bbbf1280Sopenharmony_ci 16bbbf1280Sopenharmony_ciULP error: 0.818 (nearest rounding.) 17bbbf1280Sopenharmony_ciRelative error: 1.957 * 2^-26 (before rounding.) 18bbbf1280Sopenharmony_ci*/ 19bbbf1280Sopenharmony_ci 20bbbf1280Sopenharmony_ci#define T __logf_data.tab 21bbbf1280Sopenharmony_ci#define A __logf_data.poly 22bbbf1280Sopenharmony_ci#define Ln2 __logf_data.ln2 23bbbf1280Sopenharmony_ci#define N (1 << LOGF_TABLE_BITS) 24bbbf1280Sopenharmony_ci#define OFF 0x3f330000 25bbbf1280Sopenharmony_ci 26bbbf1280Sopenharmony_cifloat 27bbbf1280Sopenharmony_cilogf (float x) 28bbbf1280Sopenharmony_ci{ 29bbbf1280Sopenharmony_ci /* double_t for better performance on targets with FLT_EVAL_METHOD==2. */ 30bbbf1280Sopenharmony_ci double_t z, r, r2, y, y0, invc, logc; 31bbbf1280Sopenharmony_ci uint32_t ix, iz, tmp; 32bbbf1280Sopenharmony_ci int k, i; 33bbbf1280Sopenharmony_ci 34bbbf1280Sopenharmony_ci ix = asuint (x); 35bbbf1280Sopenharmony_ci#if WANT_ROUNDING 36bbbf1280Sopenharmony_ci /* Fix sign of zero with downward rounding when x==1. */ 37bbbf1280Sopenharmony_ci if (unlikely (ix == 0x3f800000)) 38bbbf1280Sopenharmony_ci return 0; 39bbbf1280Sopenharmony_ci#endif 40bbbf1280Sopenharmony_ci if (unlikely (ix - 0x00800000 >= 0x7f800000 - 0x00800000)) 41bbbf1280Sopenharmony_ci { 42bbbf1280Sopenharmony_ci /* x < 0x1p-126 or inf or nan. */ 43bbbf1280Sopenharmony_ci if (ix * 2 == 0) 44bbbf1280Sopenharmony_ci return __math_divzerof (1); 45bbbf1280Sopenharmony_ci if (ix == 0x7f800000) /* log(inf) == inf. */ 46bbbf1280Sopenharmony_ci return x; 47bbbf1280Sopenharmony_ci if ((ix & 0x80000000) || ix * 2 >= 0xff000000) 48bbbf1280Sopenharmony_ci return __math_invalidf (x); 49bbbf1280Sopenharmony_ci /* x is subnormal, normalize it. */ 50bbbf1280Sopenharmony_ci ix = asuint (x * 0x1p23f); 51bbbf1280Sopenharmony_ci ix -= 23 << 23; 52bbbf1280Sopenharmony_ci } 53bbbf1280Sopenharmony_ci 54bbbf1280Sopenharmony_ci /* x = 2^k z; where z is in range [OFF,2*OFF] and exact. 55bbbf1280Sopenharmony_ci The range is split into N subintervals. 56bbbf1280Sopenharmony_ci The ith subinterval contains z and c is near its center. */ 57bbbf1280Sopenharmony_ci tmp = ix - OFF; 58bbbf1280Sopenharmony_ci i = (tmp >> (23 - LOGF_TABLE_BITS)) % N; 59bbbf1280Sopenharmony_ci k = (int32_t) tmp >> 23; /* arithmetic shift */ 60bbbf1280Sopenharmony_ci iz = ix - (tmp & 0x1ff << 23); 61bbbf1280Sopenharmony_ci invc = T[i].invc; 62bbbf1280Sopenharmony_ci logc = T[i].logc; 63bbbf1280Sopenharmony_ci z = (double_t) asfloat (iz); 64bbbf1280Sopenharmony_ci 65bbbf1280Sopenharmony_ci /* log(x) = log1p(z/c-1) + log(c) + k*Ln2 */ 66bbbf1280Sopenharmony_ci r = z * invc - 1; 67bbbf1280Sopenharmony_ci y0 = logc + (double_t) k * Ln2; 68bbbf1280Sopenharmony_ci 69bbbf1280Sopenharmony_ci /* Pipelined polynomial evaluation to approximate log1p(r). */ 70bbbf1280Sopenharmony_ci r2 = r * r; 71bbbf1280Sopenharmony_ci y = A[1] * r + A[2]; 72bbbf1280Sopenharmony_ci y = A[0] * r2 + y; 73bbbf1280Sopenharmony_ci y = y * r2 + (y0 + r); 74bbbf1280Sopenharmony_ci return eval_as_float (y); 75bbbf1280Sopenharmony_ci} 76bbbf1280Sopenharmony_ci#if USE_GLIBC_ABI 77bbbf1280Sopenharmony_cistrong_alias (logf, __logf_finite) 78bbbf1280Sopenharmony_cihidden_alias (logf, __ieee754_logf) 79bbbf1280Sopenharmony_ci#endif 80