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 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
117 changes: 102 additions & 15 deletions stl/inc/cmath
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
#include <cstdlib>
#include <xtr1common>

#if !defined(_M_CEE) && !defined(__clang__)
#include <intrin0.h>
#endif // !defined(_M_CEE) && !defined(__clang__)

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

_NODISCARD _Check_return_ inline float ceil(_In_ float _Xx) noexcept /* strengthened */ {
#ifdef _M_CEE
return _CSTD ceilf(_Xx);
#elif defined(__clang__)
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 */ {
#ifdef _M_CEE
return _CSTD copysignf(_Number, _Sign);
#elif defined(__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 +116,13 @@ _NODISCARD _Check_return_ inline float fdim(_In_ float _Xx, _In_ float _Yx) noex
}

_NODISCARD _Check_return_ inline float floor(_In_ float _Xx) noexcept /* strengthened */ {
#ifdef _M_CEE
return _CSTD floorf(_Xx);
#elif defined(__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 +230,13 @@ _NODISCARD _Check_return_ inline float rint(_In_ float _Xx) noexcept /* strength
}

_NODISCARD _Check_return_ inline float round(_In_ float _Xx) noexcept /* strengthened */ {
#ifdef _M_CEE
return _CSTD roundf(_Xx);
#elif defined(__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 +272,13 @@ _NODISCARD _Check_return_ inline float tgamma(_In_ float _Xx) noexcept /* streng
}

_NODISCARD _Check_return_ inline float trunc(_In_ float _Xx) noexcept /* strengthened */ {
#ifdef _M_CEE
return _CSTD truncf(_Xx);
#elif defined(__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 +315,24 @@ _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 */ {
#ifdef _M_CEE
return _CSTD ceill(_Xx);
#elif defined(__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 */ {
#ifdef _M_CEE
return _CSTD copysignl(_Number, _Sign);
#elif defined(__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 +373,13 @@ _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 */ {
#ifdef _M_CEE
return _CSTD floorl(_Xx);
#elif defined(__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 +496,13 @@ _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 */ {
#ifdef _M_CEE
return _CSTD roundl(_Xx);
#elif defined(__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 +538,13 @@ _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 */ {
#ifdef _M_CEE
return _CSTD truncl(_Xx);
#elif defined(__clang__)
return __builtin_truncl(_Xx);
#else // ^^^ __clang__ / !__clang__ vvv
return __trunc(static_cast<double>(_Xx));
#endif // __clang__
}


Expand Down Expand Up @@ -561,28 +625,47 @@ _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 _M_CEE
#define _GENERIC_MATH1I(FUN, CLANG_INTRIN, MSVC_INTRIN) _GENERIC_MATH1_BASE(FUN, double, _CSTD FUN)
#elif defined(__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 _M_CEE
#define _GENERIC_MATH2I(FUN, CLANG_INTRIN, MSVC_INTRIN) _GENERIC_MATH2_BASE(FUN, _CSTD FUN)
#elif defined(__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 +705,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 +730,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