Skip to content

Commit

Permalink
[libc] Move implementations of expf and exp2f from the AOR to src/math.
Browse files Browse the repository at this point in the history
Reviewers: phosek

Differential Revision: https://reviews.llvm.org/D79149
  • Loading branch information
Siva Chandra Reddy committed May 15, 2020
1 parent 0d5d5a7 commit 96d8572
Show file tree
Hide file tree
Showing 20 changed files with 812 additions and 22 deletions.
2 changes: 2 additions & 0 deletions libc/config/linux/api.td
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,8 @@ def MathAPI : PublicAPI<"math.h"> {
"cosf",
"fabs",
"fabsf",
"expf",
"exp2f",
"round",
"sincosf",
"sinf",
Expand Down
2 changes: 2 additions & 0 deletions libc/lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ add_entrypoint_library(
libc.src.math.cosf
libc.src.math.fabs
libc.src.math.fabsf
libc.src.math.expf
libc.src.math.exp2f
libc.src.math.round
libc.src.math.sincosf
libc.src.math.sinf
Expand Down
3 changes: 3 additions & 0 deletions libc/spec/stdc.td
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,9 @@ def StdC : StandardSpec<"stdc"> {
FunctionSpec<"cosf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
FunctionSpec<"sinf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,

FunctionSpec<"expf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
FunctionSpec<"exp2f", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,

FunctionSpec<"round", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
]
>;
Expand Down
38 changes: 37 additions & 1 deletion libc/src/math/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
add_header_library(
add_object_library(
math_utils
SRCS
math_utils.cpp
HDRS
math_utils.h
DEPENDS
Expand Down Expand Up @@ -88,3 +90,37 @@ add_entrypoint_object(
DEPENDS
libc.utils.FPUtil.fputil
)

add_object_library(
exp_utils
HDRS
exp_utils.h
SRCS
exp_utils.cpp
DEPENDS
.math_utils
)

add_entrypoint_object(
expf
SRCS
expf.cpp
HDRS
expf.h
DEPENDS
.exp_utils
.math_utils
libc.include.math
)

add_entrypoint_object(
exp2f
SRCS
exp2f.cpp
HDRS
exp2f.h
DEPENDS
.exp_utils
.math_utils
libc.include.math
)
2 changes: 1 addition & 1 deletion libc/src/math/cosf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ float LLVM_LIBC_ENTRYPOINT(cosf)(float y) {
return sinf_poly(x * s, x * x, p, n ^ 1);
}

return invalidf(y);
return invalid(y);
}

} // namespace __llvm_libc
63 changes: 63 additions & 0 deletions libc/src/math/exp2f.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
//===-- Single-precision 2^x function -------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "exp_utils.h"
#include "math_utils.h"

#include "include/math.h"
#include "src/__support/common.h"

#include <stdint.h>

#define T exp2f_data.tab
#define C exp2f_data.poly
#define SHIFT exp2f_data.shift_scaled

namespace __llvm_libc {

float LLVM_LIBC_ENTRYPOINT(exp2f)(float x) {
uint32_t abstop;
uint64_t ki, t;
// double_t for better performance on targets with FLT_EVAL_METHOD==2.
double_t kd, xd, z, r, r2, y, s;

xd = static_cast<double_t>(x);
abstop = top12_bits(x) & 0x7ff;
if (unlikely(abstop >= top12_bits(128.0f))) {
// |x| >= 128 or x is nan.
if (as_uint32_bits(x) == as_uint32_bits(-INFINITY))
return 0.0f;
if (abstop >= top12_bits(INFINITY))
return x + x;
if (x > 0.0f)
return overflow<float>(0);
if (x <= -150.0f)
return underflow<float>(0);
if (x < -149.0f)
return may_underflow<float>(0);
}

// x = k/N + r with r in [-1/(2N), 1/(2N)] and int k.
kd = static_cast<double>(xd + SHIFT);
ki = as_uint64_bits(kd);
kd -= SHIFT; // k/N for int k.
r = xd - kd;

// exp2(x) = 2^(k/N) * 2^r ~= s * (C0*r^3 + C1*r^2 + C2*r + 1)
t = T[ki % N];
t += ki << (52 - EXP2F_TABLE_BITS);
s = as_double(t);
z = C[0] * r + C[1];
r2 = r * r;
y = C[2] * r + 1;
y = z * r2 + y;
y = y * s;
return static_cast<float>(y);
}

} // namespace __llvm_libc
18 changes: 18 additions & 0 deletions libc/src/math/exp2f.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//===-- Implementation header for exp2f -------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIBC_SRC_MATH_EXP2F_H
#define LLVM_LIBC_SRC_MATH_EXP2F_H

namespace __llvm_libc {

float exp2f(float x);

} // namespace __llvm_libc

#endif // LLVM_LIBC_SRC_MATH_EXP2F_H
129 changes: 129 additions & 0 deletions libc/src/math/exp_utils.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
//===-- Implemention of exp and friends' utils ----------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "exp_utils.h"

#include "math_utils.h"

namespace __llvm_libc {

const Exp2fDataTable exp2f_data = {
// :tab[i] = uint(2^(i/N)) - (i << 52-BITS)
// used for computing 2^(k/N) for an int |k| < 150 N as
// double(tab[k%N] + (k << 52-BITS))
{
// tab
#if N == 8
0x3ff0000000000000,
0x3fef72b83c7d517b,
0x3fef06fe0a31b715,
0x3feebfdad5362a27,
0x3feea09e667f3bcd,
0x3feeace5422aa0db,
0x3feee89f995ad3ad,
0x3fef5818dcfba487,
#elif N == 16
0x3ff0000000000000,
0x3fefb5586cf9890f,
0x3fef72b83c7d517b,
0x3fef387a6e756238,
0x3fef06fe0a31b715,
0x3feedea64c123422,
0x3feebfdad5362a27,
0x3feeab07dd485429,
0x3feea09e667f3bcd,
0x3feea11473eb0187,
0x3feeace5422aa0db,
0x3feec49182a3f090,
0x3feee89f995ad3ad,
0x3fef199bdd85529c,
0x3fef5818dcfba487,
0x3fefa4afa2a490da,
#elif N == 32
0x3ff0000000000000, 0x3fefd9b0d3158574, 0x3fefb5586cf9890f,
0x3fef9301d0125b51, 0x3fef72b83c7d517b, 0x3fef54873168b9aa,
0x3fef387a6e756238, 0x3fef1e9df51fdee1, 0x3fef06fe0a31b715,
0x3feef1a7373aa9cb, 0x3feedea64c123422, 0x3feece086061892d,
0x3feebfdad5362a27, 0x3feeb42b569d4f82, 0x3feeab07dd485429,
0x3feea47eb03a5585, 0x3feea09e667f3bcd, 0x3fee9f75e8ec5f74,
0x3feea11473eb0187, 0x3feea589994cce13, 0x3feeace5422aa0db,
0x3feeb737b0cdc5e5, 0x3feec49182a3f090, 0x3feed503b23e255d,
0x3feee89f995ad3ad, 0x3feeff76f2fb5e47, 0x3fef199bdd85529c,
0x3fef3720dcef9069, 0x3fef5818dcfba487, 0x3fef7c97337b9b5f,
0x3fefa4afa2a490da, 0x3fefd0765b6e4540,
#elif N == 64
0x3ff0000000000000, 0x3fefec9a3e778061, 0x3fefd9b0d3158574,
0x3fefc74518759bc8, 0x3fefb5586cf9890f, 0x3fefa3ec32d3d1a2,
0x3fef9301d0125b51, 0x3fef829aaea92de0, 0x3fef72b83c7d517b,
0x3fef635beb6fcb75, 0x3fef54873168b9aa, 0x3fef463b88628cd6,
0x3fef387a6e756238, 0x3fef2b4565e27cdd, 0x3fef1e9df51fdee1,
0x3fef1285a6e4030b, 0x3fef06fe0a31b715, 0x3feefc08b26416ff,
0x3feef1a7373aa9cb, 0x3feee7db34e59ff7, 0x3feedea64c123422,
0x3feed60a21f72e2a, 0x3feece086061892d, 0x3feec6a2b5c13cd0,
0x3feebfdad5362a27, 0x3feeb9b2769d2ca7, 0x3feeb42b569d4f82,
0x3feeaf4736b527da, 0x3feeab07dd485429, 0x3feea76f15ad2148,
0x3feea47eb03a5585, 0x3feea23882552225, 0x3feea09e667f3bcd,
0x3fee9fb23c651a2f, 0x3fee9f75e8ec5f74, 0x3fee9feb564267c9,
0x3feea11473eb0187, 0x3feea2f336cf4e62, 0x3feea589994cce13,
0x3feea8d99b4492ed, 0x3feeace5422aa0db, 0x3feeb1ae99157736,
0x3feeb737b0cdc5e5, 0x3feebd829fde4e50, 0x3feec49182a3f090,
0x3feecc667b5de565, 0x3feed503b23e255d, 0x3feede6b5579fdbf,
0x3feee89f995ad3ad, 0x3feef3a2b84f15fb, 0x3feeff76f2fb5e47,
0x3fef0c1e904bc1d2, 0x3fef199bdd85529c, 0x3fef27f12e57d14b,
0x3fef3720dcef9069, 0x3fef472d4a07897c, 0x3fef5818dcfba487,
0x3fef69e603db3285, 0x3fef7c97337b9b5f, 0x3fef902ee78b3ff6,
0x3fefa4afa2a490da, 0x3fefba1bee615a27, 0x3fefd0765b6e4540,
0x3fefe7c1819e90d8,
#endif
},
as_double(0x4338000000000000) / N, // shift_scaled
{
// poly
#if N == 8
as_double(0x3fac6a00335106e2),
as_double(0x3fcec0c313449f55),
as_double(0x3fe62e431111f69f),
#elif N == 16
as_double(0x3fac6ac6aa313963),
as_double(0x3fcebfff4532d9ba),
as_double(0x3fe62e43001bc49f),
#elif N == 32
as_double(0x3fac6af84b912394),
as_double(0x3fcebfce50fac4f3),
as_double(0x3fe62e42ff0c52d6),
#elif N == 64
as_double(0x3fac6b04b4221b2a),
as_double(0x3fcebfc213e184d7),
as_double(0x3fe62e42fefb5b7f),
#endif
},
as_double(0x4338000000000000), // shift
as_double(0x3ff71547652b82fe) * N, // invln2_scaled
{
// poly_scaled
#if N == 8
as_double(0x3fac6a00335106e2) / N / N / N,
as_double(0x3fcec0c313449f55) / N / N,
as_double(0x3fe62e431111f69f) / N,
#elif N == 16
as_double(0x3fac6ac6aa313963) / N / N / N,
as_double(0x3fcebfff4532d9ba) / N / N,
as_double(0x3fe62e43001bc49f) / N,
#elif N == 32
as_double(0x3fac6af84b912394) / N / N / N,
as_double(0x3fcebfce50fac4f3) / N / N,
as_double(0x3fe62e42ff0c52d6) / N,
#elif N == 64
as_double(0x3fac6b04b4221b2a) / N / N / N,
as_double(0x3fcebfc213e184d7) / N / N,
as_double(0x3fe62e42fefb5b7f) / N,
#endif
},
};

} // namespace __llvm_libc
33 changes: 33 additions & 0 deletions libc/src/math/exp_utils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//===-- Collection of utils for exp and friends -----------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIBC_SRC_MATH_EXP_UTILS_H
#define LLVM_LIBC_SRC_MATH_EXP_UTILS_H

#include <stdint.h>

#define EXP2F_TABLE_BITS 5
#define EXP2F_POLY_ORDER 3
#define N (1 << EXP2F_TABLE_BITS)

namespace __llvm_libc {

struct Exp2fDataTable {
uint64_t tab[1 << EXP2F_TABLE_BITS];
double shift_scaled;
double poly[EXP2F_POLY_ORDER];
double shift;
double invln2_scaled;
double poly_scaled[EXP2F_POLY_ORDER];
};

extern const Exp2fDataTable exp2f_data;

} // namespace __llvm_libc

#endif // LLVM_LIBC_SRC_MATH_EXP_UTILS_H
Loading

0 comments on commit 96d8572

Please sign in to comment.