Skip to content

[libclc] Move exp, exp2 and expm1 to the CLC library #133932

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 1, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,15 @@
//
//===----------------------------------------------------------------------===//

#ifdef cl_khr_fp64
#ifndef __CLC_MATH_CLC_EXP_H__
#define __CLC_MATH_CLC_EXP_H__

#pragma OPENCL EXTENSION cl_khr_fp64 : enable
_CLC_DECL double __clc_exp_helper(double x, double x_min, double x_max, double r, int n);
#define __CLC_BODY <clc/math/unary_decl.inc>
#define __CLC_FUNCTION __clc_exp

#endif
#include <clc/math/gentype.inc>

#undef __CLC_BODY
#undef __CLC_FUNCTION

#endif // __CLC_MATH_CLC_EXP_H__
20 changes: 20 additions & 0 deletions libclc/clc/include/clc/math/clc_exp2.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//===----------------------------------------------------------------------===//
//
// 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 __CLC_MATH_CLC_EXP2_H__
#define __CLC_MATH_CLC_EXP2_H__

#define __CLC_BODY <clc/math/unary_decl.inc>
#define __CLC_FUNCTION __clc_exp2

#include <clc/math/gentype.inc>

#undef __CLC_BODY
#undef __CLC_FUNCTION

#endif // __CLC_MATH_CLC_EXP2_H__
20 changes: 20 additions & 0 deletions libclc/clc/include/clc/math/clc_exp_helper.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//===----------------------------------------------------------------------===//
//
// 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 __CLC_MATH_CLC_EXP_HELPER
#define __CLC_MATH_CLC_EXP_HELPER

#define __DOUBLE_ONLY
#define __CLC_BODY <clc/math/clc_exp_helper.inc>

#include <clc/math/gentype.inc>

#undef __CLC_BODY
#undef __DOUBLE_ONLY

#endif // __CLC_MATH_CLC_EXP_HELPER
13 changes: 13 additions & 0 deletions libclc/clc/include/clc/math/clc_exp_helper.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

_CLC_DECL _CLC_OVERLOAD __CLC_GENTYPE __clc_exp_helper(__CLC_GENTYPE x,
__CLC_GENTYPE x_min,
__CLC_GENTYPE x_max,
__CLC_GENTYPE r,
__CLC_INTN n);
20 changes: 20 additions & 0 deletions libclc/clc/include/clc/math/clc_expm1.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//===----------------------------------------------------------------------===//
//
// 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 __CLC_MATH_CLC_EXPM1_H__
#define __CLC_MATH_CLC_EXPM1_H__

#define __CLC_BODY <clc/math/unary_decl.inc>
#define __CLC_FUNCTION __clc_expm1

#include <clc/math/gentype.inc>

#undef __CLC_BODY
#undef __CLC_FUNCTION

#endif // __CLC_MATH_CLC_EXPM1_H__
4 changes: 4 additions & 0 deletions libclc/clc/lib/generic/SOURCES
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,11 @@ math/clc_ceil.cl
math/clc_copysign.cl
math/clc_cospi.cl
math/clc_ep_log.cl
math/clc_exp.cl
math/clc_exp10.cl
math/clc_exp2.cl
math/clc_expm1.cl
math/clc_exp_helper.cl
math/clc_fabs.cl
math/clc_fma.cl
math/clc_fmod.cl
Expand Down
19 changes: 19 additions & 0 deletions libclc/clc/lib/generic/math/clc_exp.cl
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//===----------------------------------------------------------------------===//
//
// 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 <clc/clc_convert.h>
#include <clc/float/definitions.h>
#include <clc/internal/clc.h>
#include <clc/math/clc_exp_helper.h>
#include <clc/math/clc_fma.h>
#include <clc/math/clc_mad.h>
#include <clc/math/math.h>
#include <clc/relational/clc_isnan.h>

#define __CLC_BODY <clc_exp.inc>
#include <clc/math/gentype.inc>
76 changes: 76 additions & 0 deletions libclc/clc/lib/generic/math/clc_exp.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

#if __CLC_FPSIZE == 32

_CLC_OVERLOAD _CLC_DEF __CLC_GENTYPE __clc_exp(__CLC_GENTYPE x) {
// Reduce x
const __CLC_GENTYPE ln2HI = 0x1.62e300p-1f;
const __CLC_GENTYPE ln2LO = 0x1.2fefa2p-17f;
const __CLC_GENTYPE invln2 = 0x1.715476p+0f;

__CLC_GENTYPE fhalF = x < 0.0f ? -0.5f : 0.5f;
__CLC_INTN p = __CLC_CONVERT_INTN(__clc_mad(x, invln2, fhalF));
__CLC_GENTYPE fp = __CLC_CONVERT_GENTYPE(p);
__CLC_GENTYPE hi = __clc_mad(fp, -ln2HI, x); // t*ln2HI is exact here
__CLC_GENTYPE lo = -fp * ln2LO;

// Evaluate poly
__CLC_GENTYPE t = hi + lo;
__CLC_GENTYPE tt = t * t;
__CLC_GENTYPE v = __clc_mad(
tt,
-__clc_mad(
tt,
__clc_mad(tt,
__clc_mad(tt,
__clc_mad(tt, 0x1.637698p-25f, -0x1.bbd41cp-20f),
0x1.1566aap-14f),
-0x1.6c16c2p-9f),
0x1.555556p-3f),
t);

__CLC_GENTYPE y = 1.0f - (((-lo) - MATH_DIVIDE(t * v, 2.0f - v)) - hi);

// Scale by 2^p
__CLC_GENTYPE r = __CLC_AS_GENTYPE(__CLC_AS_INTN(y) + (p << 23));

// ln(largest_normal) = 88.72283905206835305366
const __CLC_GENTYPE ulim = 0x1.62e430p+6f;
// ln(smallest_normal) = -87.33654475055310898657
const __CLC_GENTYPE llim = -0x1.5d589ep+6f;

r = x < llim ? 0.0f : r;
r = x < ulim ? r : __CLC_AS_GENTYPE((__CLC_UINTN)0x7f800000);
return __clc_isnan(x) ? x : r;
}

#elif __CLC_FPSIZE == 64

_CLC_OVERLOAD _CLC_DEF __CLC_GENTYPE __clc_exp(__CLC_GENTYPE x) {

const __CLC_GENTYPE X_MIN = -0x1.74910d52d3051p+9; // -1075*ln(2)
const __CLC_GENTYPE X_MAX = 0x1.62e42fefa39efp+9; // 1024*ln(2)
const __CLC_GENTYPE R_64_BY_LOG2 = 0x1.71547652b82fep+6; // 64/ln(2)
const __CLC_GENTYPE R_LOG2_BY_64_LD = 0x1.62e42fefa0000p-7; // head ln(2)/64
const __CLC_GENTYPE R_LOG2_BY_64_TL = 0x1.cf79abc9e3b39p-46; // tail ln(2)/64

__CLC_INTN n = __CLC_CONVERT_INTN(x * R_64_BY_LOG2);
__CLC_GENTYPE r =
__clc_fma(-R_LOG2_BY_64_TL, __CLC_CONVERT_GENTYPE(n),
__clc_fma(-R_LOG2_BY_64_LD, __CLC_CONVERT_GENTYPE(n), x));
return __clc_exp_helper(x, X_MIN, X_MAX, r, n);
}

#elif __CLC_FPSIZE == 16

_CLC_OVERLOAD _CLC_DEF __CLC_GENTYPE __clc_exp(__CLC_GENTYPE x) {
return __CLC_CONVERT_GENTYPE(__clc_exp(__CLC_CONVERT_FLOATN(x)));
}

#endif
20 changes: 20 additions & 0 deletions libclc/clc/lib/generic/math/clc_exp2.cl
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//===----------------------------------------------------------------------===//
//
// 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 <clc/clc_convert.h>
#include <clc/float/definitions.h>
#include <clc/internal/clc.h>
#include <clc/math/clc_exp_helper.h>
#include <clc/math/clc_fma.h>
#include <clc/math/clc_mad.h>
#include <clc/math/clc_rint.h>
#include <clc/math/math.h>
#include <clc/relational/clc_isnan.h>

#define __CLC_BODY <clc_exp2.inc>
#include <clc/math/gentype.inc>
68 changes: 68 additions & 0 deletions libclc/clc/lib/generic/math/clc_exp2.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

#if __CLC_FPSIZE == 32

_CLC_OVERLOAD _CLC_DEF __CLC_GENTYPE __clc_exp2(__CLC_GENTYPE x) {
// Reduce x
const __CLC_GENTYPE ln2HI = 0x1.62e300p-1f;
const __CLC_GENTYPE ln2LO = 0x1.2fefa2p-17f;

__CLC_GENTYPE t = __clc_rint(x);
__CLC_INTN p = __CLC_CONVERT_INTN(t);
__CLC_GENTYPE tt = x - t;
__CLC_GENTYPE hi = tt * ln2HI;
__CLC_GENTYPE lo = tt * ln2LO;

// Evaluate poly
t = hi + lo;
tt = t * t;
__CLC_GENTYPE v = __clc_mad(
tt,
-__clc_mad(
tt,
__clc_mad(tt,
__clc_mad(tt,
__clc_mad(tt, 0x1.637698p-25f, -0x1.bbd41cp-20f),
0x1.1566aap-14f),
-0x1.6c16c2p-9f),
0x1.555556p-3f),
t);

__CLC_GENTYPE y = 1.0f - (((-lo) - MATH_DIVIDE(t * v, 2.0f - v)) - hi);

// Scale by 2^p
__CLC_GENTYPE r = __CLC_AS_FLOATN(__CLC_AS_INTN(y) + (p << 23));

const __CLC_GENTYPE ulim = 128.0f;
const __CLC_GENTYPE llim = -126.0f;

r = x < llim ? 0.0f : r;
r = x < ulim ? r : __CLC_AS_FLOATN((__CLC_UINTN)0x7f800000);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should just use infinity as a later cleanup

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, there's good opportunity for infinity-related improvements.

return __clc_isnan(x) ? x : r;
}

#elif __CLC_FPSIZE == 64

_CLC_OVERLOAD _CLC_DEF __CLC_GENTYPE __clc_exp2(__CLC_GENTYPE x) {
const __CLC_GENTYPE R_LN2 = 0x1.62e42fefa39efp-1; // ln(2)
const __CLC_GENTYPE R_1_BY_64 = 1.0 / 64.0;

__CLC_INTN n = __CLC_CONVERT_INTN(x * 64.0);
__CLC_GENTYPE r = R_LN2 * __clc_fma(-R_1_BY_64, __CLC_CONVERT_GENTYPE(n), x);

return __clc_exp_helper(x, -1074.0, 1024.0, r, n);
}

#elif __CLC_FPSIZE == 16

_CLC_OVERLOAD _CLC_DEF __CLC_GENTYPE __clc_exp2(__CLC_GENTYPE x) {
return __CLC_CONVERT_GENTYPE(__clc_exp2(__CLC_CONVERT_FLOATN(x)));
}

#endif
20 changes: 20 additions & 0 deletions libclc/clc/lib/generic/math/clc_exp_helper.cl
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//===----------------------------------------------------------------------===//
//
// 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 <clc/clc_convert.h>
#include <clc/internal/clc.h>
#include <clc/math/clc_fma.h>
#include <clc/math/clc_ldexp.h>
#include <clc/math/math.h>
#include <clc/math/tables.h>
#include <clc/relational/clc_isnan.h>

#define __DOUBLE_ONLY
#define __CLC_BODY <clc_exp_helper.inc>

#include <clc/math/gentype.inc>
54 changes: 54 additions & 0 deletions libclc/clc/lib/generic/math/clc_exp_helper.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

_CLC_DEF _CLC_OVERLOAD __CLC_GENTYPE __clc_exp_helper(__CLC_GENTYPE x,
__CLC_GENTYPE x_min,
__CLC_GENTYPE x_max,
__CLC_GENTYPE r,
__CLC_INTN n) {

__CLC_INTN j = n & 0x3f;
__CLC_INTN m = n >> 6;

// 6 term tail of Taylor expansion of e^r
__CLC_GENTYPE z2 =
r * __clc_fma(
r,
__clc_fma(r,
__clc_fma(r,
__clc_fma(r,
__clc_fma(r, 0x1.6c16c16c16c17p-10,
0x1.1111111111111p-7),
0x1.5555555555555p-5),
0x1.5555555555555p-3),
0x1.0000000000000p-1),
1.0);

__CLC_GENTYPE tv0 = USE_TABLE(two_to_jby64_ep_tbl_head, j);
__CLC_GENTYPE tv1 = USE_TABLE(two_to_jby64_ep_tbl_tail, j);
z2 = __clc_fma(tv0 + tv1, z2, tv1) + tv0;

__CLC_INTN small_value =
(m < -1022) || ((m == -1022) && __CLC_CONVERT_INTN(z2 < 1.0));

__CLC_INTN n1 = m >> 2;
__CLC_INTN n2 = m - n1;
__CLC_GENTYPE z3 =
z2 * __CLC_AS_GENTYPE((__CLC_CONVERT_LONGN(n1) + 1023) << 52);
z3 *= __CLC_AS_GENTYPE((__CLC_CONVERT_LONGN(n2) + 1023) << 52);

z2 = __clc_ldexp(z2, m);
z2 = __CLC_CONVERT_LONGN(small_value) ? z3 : z2;

z2 = __clc_isnan(x) ? x : z2;

z2 = x > x_max ? __CLC_AS_GENTYPE((__CLC_ULONGN)PINFBITPATT_DP64) : z2;
z2 = x < x_min ? 0.0 : z2;

return z2;
}
20 changes: 20 additions & 0 deletions libclc/clc/lib/generic/math/clc_expm1.cl
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//===----------------------------------------------------------------------===//
//
// 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 <clc/clc_convert.h>
#include <clc/float/definitions.h>
#include <clc/internal/clc.h>
#include <clc/math/clc_exp_helper.h>
#include <clc/math/clc_fma.h>
#include <clc/math/clc_mad.h>
#include <clc/math/math.h>
#include <clc/math/tables.h>
#include <clc/relational/clc_isnan.h>

#define __CLC_BODY <clc_expm1.inc>
#include <clc/math/gentype.inc>
Loading
Loading