Skip to content
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

<cmath>: Use intrinsics where possible #1336

Merged
merged 6 commits into from
Nov 6, 2020
Merged
Changes from 4 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
113 changes: 88 additions & 25 deletions stl/inc/cmath
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
#include <cstdlib>
#include <xtr1common>

#ifndef __clang__
#include <intrin0.h>
#endif // !__clang__

#if _HAS_CXX20
#include <xutility>
#endif // _HAS_CXX20
Expand Down Expand Up @@ -56,11 +60,19 @@ _NODISCARD _Check_return_ inline float cbrt(_In_ float _Xx) noexcept /* strength
}

_NODISCARD _Check_return_ inline float ceil(_In_ float _Xx) noexcept /* strengthened */ {
return _CSTD ceilf(_Xx);
#ifdef __clang__
StephanTLavavej marked this conversation as resolved.
Show resolved Hide resolved
return __builtin_ceilf(_Xx);
#else // ^^^ __clang__ / !__clang__ vvv
return __ceilf(_Xx);
#endif // __clang__
}

_NODISCARD _Check_return_ inline float copysign(_In_ float _Number, _In_ float _Sign) noexcept /* strengthened */ {
return _CSTD copysignf(_Number, _Sign);
#ifdef __clang__
return __builtin_copysignf(_Number, _Sign);
#else // ^^^ __clang__ / !__clang__ vvv
return __copysignf(_Number, _Sign);
#endif // __clang__
}

_NODISCARD _Check_return_ inline float cos(_In_ float _Xx) noexcept /* strengthened */ {
Expand Down Expand Up @@ -100,7 +112,11 @@ _NODISCARD _Check_return_ inline float fdim(_In_ float _Xx, _In_ float _Yx) noex
}

_NODISCARD _Check_return_ inline float floor(_In_ float _Xx) noexcept /* strengthened */ {
return _CSTD floorf(_Xx);
#ifdef __clang__
return __builtin_floorf(_Xx);
#else // ^^^ __clang__ / !__clang__ vvv
return __floorf(_Xx);
#endif // __clang__
}

_NODISCARD _Check_return_ inline float fma(_In_ float _Xx, _In_ float _Yx, _In_ float _Zx) noexcept /* strengthened */ {
Expand Down Expand Up @@ -208,7 +224,11 @@ _NODISCARD _Check_return_ inline float rint(_In_ float _Xx) noexcept /* strength
}

_NODISCARD _Check_return_ inline float round(_In_ float _Xx) noexcept /* strengthened */ {
return _CSTD roundf(_Xx);
#ifdef __clang__
return __builtin_roundf(_Xx);
#else // ^^^ __clang__ / !__clang__ vvv
return __roundf(_Xx);
#endif // __clang__
}

_NODISCARD _Check_return_ inline float scalbln(_In_ float _Xx, _In_ long _Yx) noexcept /* strengthened */ {
Expand Down Expand Up @@ -244,7 +264,11 @@ _NODISCARD _Check_return_ inline float tgamma(_In_ float _Xx) noexcept /* streng
}

_NODISCARD _Check_return_ inline float trunc(_In_ float _Xx) noexcept /* strengthened */ {
return _CSTD truncf(_Xx);
#ifdef __clang__
return __builtin_truncf(_Xx);
#else // ^^^ __clang__ / !__clang__ vvv
return __truncf(_Xx);
#endif // __clang__
}

_NODISCARD _Check_return_ inline long double acos(_In_ long double _Xx) noexcept /* strengthened */ {
Expand Down Expand Up @@ -281,12 +305,20 @@ _NODISCARD _Check_return_ inline long double cbrt(_In_ long double _Xx) noexcept
}

_NODISCARD _Check_return_ inline long double ceil(_In_ long double _Xx) noexcept /* strengthened */ {
return _CSTD ceill(_Xx);
#ifdef __clang__
return __builtin_ceill(_Xx);
#else // ^^^ __clang__ / !__clang__ vvv
return __ceil(static_cast<double>(_Xx));
#endif // __clang__
}

_NODISCARD _Check_return_ inline long double copysign(_In_ long double _Number, _In_ long double _Sign) noexcept
/* strengthened */ {
return _CSTD copysignl(_Number, _Sign);
#ifdef __clang__
return __builtin_copysignl(_Number, _Sign);
#else // ^^^ __clang__ / !__clang__ vvv
return __copysign(static_cast<double>(_Number), static_cast<double>(_Sign));
#endif // __clang__
}

_NODISCARD _Check_return_ inline long double cos(_In_ long double _Xx) noexcept /* strengthened */ {
Expand Down Expand Up @@ -327,7 +359,11 @@ _NODISCARD _Check_return_ inline long double fdim(_In_ long double _Xx, _In_ lon
}

_NODISCARD _Check_return_ inline long double floor(_In_ long double _Xx) noexcept /* strengthened */ {
return _CSTD floorl(_Xx);
#ifdef __clang__
return __builtin_floorl(_Xx);
#else // ^^^ __clang__ / !__clang__ vvv
return __floor(static_cast<double>(_Xx));
#endif // __clang__
}

_NODISCARD _Check_return_ inline long double fma(
Expand Down Expand Up @@ -444,7 +480,11 @@ _NODISCARD _Check_return_ inline long double rint(_In_ long double _Xx) noexcept
}

_NODISCARD _Check_return_ inline long double round(_In_ long double _Xx) noexcept /* strengthened */ {
return _CSTD roundl(_Xx);
#ifdef __clang__
return __builtin_roundl(_Xx);
#else // ^^^ __clang__ / !__clang__ vvv
return __round(static_cast<double>(_Xx));
#endif // __clang__
}

_NODISCARD _Check_return_ inline long double scalbln(_In_ long double _Xx, _In_ long _Yx) noexcept /* strengthened */ {
Expand Down Expand Up @@ -480,7 +520,11 @@ _NODISCARD _Check_return_ inline long double tgamma(_In_ long double _Xx) noexce
}

_NODISCARD _Check_return_ inline long double trunc(_In_ long double _Xx) noexcept /* strengthened */ {
return _CSTD truncl(_Xx);
#ifdef __clang__
return __builtin_truncl(_Xx);
#else // ^^^ __clang__ / !__clang__ vvv
return __trunc(static_cast<double>(_Xx));
#endif // __clang__
}


Expand Down Expand Up @@ -561,28 +605,43 @@ _STD _Common_float_type_t<_Ty1, _Ty2> remquo(_Ty1 _Left, _Ty2 _Right, int* _Pquo
#endif // _HAS_IF_CONSTEXPR
}

#define _GENERIC_MATH1R(FUN, RET) \
#define _GENERIC_MATH1_BASE(NAME, RET, FUN) \
StephanTLavavej marked this conversation as resolved.
Show resolved Hide resolved
template <class _Ty, _STD enable_if_t<_STD is_integral_v<_Ty>, int> = 0> \
_NODISCARD RET FUN(_Ty _Left) noexcept /* strengthened */ { \
return _CSTD FUN(static_cast<double>(_Left)); \
_NODISCARD RET NAME(_Ty _Left) noexcept /* strengthened */ { \
return FUN(static_cast<double>(_Left)); \
}

#define _GENERIC_MATH1(FUN) _GENERIC_MATH1R(FUN, double)
#define _GENERIC_MATH1R(FUN, RET) _GENERIC_MATH1_BASE(FUN, RET, _CSTD FUN)
#define _GENERIC_MATH1(FUN) _GENERIC_MATH1R(FUN, double)

#ifdef __clang__
#define _GENERIC_MATH1I(FUN, CLANG_INTRIN, MSVC_INTRIN) _GENERIC_MATH1_BASE(FUN, double, CLANG_INTRIN)
#else // ^^^ __clang__ / !__clang__ vvv
#define _GENERIC_MATH1I(FUN, CLANG_INTRIN, MSVC_INTRIN) _GENERIC_MATH1_BASE(FUN, double, MSVC_INTRIN)
#endif // __clang__

#define _GENERIC_MATH1X(FUN, ARG2) \
template <class _Ty, _STD enable_if_t<_STD is_integral_v<_Ty>, int> = 0> \
_NODISCARD double FUN(_Ty _Left, ARG2 _Arg2) noexcept /* strengthened */ { \
return _CSTD FUN(static_cast<double>(_Left), _Arg2); \
}

#define _GENERIC_MATH2(FUN) \
template <class _Ty1, class _Ty2, \
_STD enable_if_t<_STD is_arithmetic_v<_Ty1> && _STD is_arithmetic_v<_Ty2>, int> = 0> \
_NODISCARD _STD _Common_float_type_t<_Ty1, _Ty2> FUN(_Ty1 _Left, _Ty2 _Right) noexcept /* strengthened */ { \
using _Common = _STD _Common_float_type_t<_Ty1, _Ty2>; \
return _CSTD FUN(static_cast<_Common>(_Left), static_cast<_Common>(_Right)); \
#define _GENERIC_MATH2_BASE(NAME, FUN) \
template <class _Ty1, class _Ty2, \
_STD enable_if_t<_STD is_arithmetic_v<_Ty1> && _STD is_arithmetic_v<_Ty2>, int> = 0> \
_NODISCARD _STD _Common_float_type_t<_Ty1, _Ty2> NAME(_Ty1 _Left, _Ty2 _Right) noexcept /* strengthened */ { \
using _Common = _STD _Common_float_type_t<_Ty1, _Ty2>; \
return FUN(static_cast<_Common>(_Left), static_cast<_Common>(_Right)); \
}

#define _GENERIC_MATH2(FUN) _GENERIC_MATH2_BASE(FUN, _CSTD FUN)

#ifdef __clang__
#define _GENERIC_MATH2I(FUN, CLANG_INTRIN, MSVC_INTRIN) _GENERIC_MATH2_BASE(FUN, CLANG_INTRIN)
#else // ^^^ __clang__ / !__clang__ vvv
#define _GENERIC_MATH2I(FUN, CLANG_INTRIN, MSVC_INTRIN) _GENERIC_MATH2_BASE(FUN, MSVC_INTRIN)
#endif // __clang__

// The following order matches N4820 26.8.1 [cmath.syn].
_GENERIC_MATH1(acos)
_GENERIC_MATH1(asin)
Expand Down Expand Up @@ -622,20 +681,20 @@ _GENERIC_MATH1(erf)
_GENERIC_MATH1(erfc)
_GENERIC_MATH1(lgamma)
_GENERIC_MATH1(tgamma)
_GENERIC_MATH1(ceil)
_GENERIC_MATH1(floor)
_GENERIC_MATH1I(ceil, __builtin_ceil, __ceil)
_GENERIC_MATH1I(floor, __builtin_floor, __floor)
_GENERIC_MATH1(nearbyint)
_GENERIC_MATH1(rint)
_GENERIC_MATH1R(lrint, long)
_GENERIC_MATH1R(llrint, long long)
_GENERIC_MATH1(round)
_GENERIC_MATH1I(round, __builtin_round, __round)
_GENERIC_MATH1R(lround, long)
_GENERIC_MATH1R(llround, long long)
_GENERIC_MATH1(trunc)
_GENERIC_MATH1I(trunc, __builtin_trunc, __trunc)
_GENERIC_MATH2(fmod)
_GENERIC_MATH2(remainder)
// remquo() is hand-crafted
_GENERIC_MATH2(copysign)
_GENERIC_MATH2I(copysign, __builtin_copysign, __copysign)
// nan(const char*) is exempt
_GENERIC_MATH2(nextafter)
_GENERIC_MATH1X(nexttoward, long double)
Expand All @@ -647,10 +706,14 @@ _GENERIC_MATH2(fmin)
// The "classification/comparison functions" (fpclassify(), etc.) are exempt, LWG-1327
// TRANSITION, VSO-945789, Special Math shouldn't be exempt

#undef _GENERIC_MATH1_BASE
#undef _GENERIC_MATH1R
#undef _GENERIC_MATH1
#undef _GENERIC_MATH1I
#undef _GENERIC_MATH1X
#undef _GENERIC_MATH2_BASE
#undef _GENERIC_MATH2
#undef _GENERIC_MATH2I


_STD_BEGIN
Expand Down