Skip to content

Commit

Permalink
microsoftGH-1336 <cmath>: Use intrinsics where possible
Browse files Browse the repository at this point in the history
  • Loading branch information
StephanTLavavej committed Nov 5, 2020
1 parent d9170d1 commit 8e2f512
Showing 1 changed file with 102 additions and 15 deletions.
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_PURE) && !defined(__clang__)
#include <intrin0.h>
#endif // !defined(_M_CEE_PURE) && !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_PURE
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_PURE
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_PURE
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_PURE
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_PURE
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_PURE
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_PURE
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_PURE
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_PURE
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_PURE
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) \
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_PURE
#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_PURE
#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

0 comments on commit 8e2f512

Please sign in to comment.