зеркало из https://github.com/microsoft/STL.git
203 строки
7.7 KiB
C++
203 строки
7.7 KiB
C++
// xtgmath.h internal header
|
|
|
|
// Copyright (c) Microsoft Corporation.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
|
#pragma once
|
|
#ifndef _XTGMATH
|
|
#define _XTGMATH
|
|
#include <yvals.h>
|
|
#if _STL_COMPILER_PREPROCESSOR
|
|
|
|
#include <cstdlib>
|
|
#include <xtr1common>
|
|
|
|
#pragma pack(push, _CRT_PACKING)
|
|
#pragma warning(push, _STL_WARNING_LEVEL)
|
|
#pragma warning(disable : _STL_DISABLED_WARNINGS)
|
|
_STL_DISABLE_CLANG_WARNINGS
|
|
#pragma push_macro("new")
|
|
#undef new
|
|
|
|
_STD_BEGIN
|
|
template <class _Ty1, class _Ty2>
|
|
using _Common_float_type_t = conditional_t<is_same_v<_Ty1, long double> || is_same_v<_Ty2, long double>, long double,
|
|
conditional_t<is_same_v<_Ty1, float> && is_same_v<_Ty2, float>, float,
|
|
double>>; // find type for two-argument math function
|
|
_STD_END
|
|
|
|
// FUNCTION TEMPLATE frexp
|
|
template <class _Ty, _STD enable_if_t<_STD is_integral_v<_Ty>, int> = 0>
|
|
double frexp(_Ty _Value, _Out_ int* const _Exp) noexcept /* strengthened */ {
|
|
return _CSTD frexp(static_cast<double>(_Value), _Exp);
|
|
}
|
|
|
|
// FUNCTION TEMPLATE pow
|
|
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> pow(const _Ty1 _Left, const _Ty2 _Right) noexcept /* strengthened */ {
|
|
using _Common = _STD _Common_float_type_t<_Ty1, _Ty2>;
|
|
return _CSTD pow(static_cast<_Common>(_Left), static_cast<_Common>(_Right));
|
|
}
|
|
|
|
// FUNCTION TEMPLATE fma
|
|
#if !_HAS_IF_CONSTEXPR
|
|
inline float _Fma(float _Left, float _Middle, float _Right) noexcept {
|
|
return _CSTD fmaf(_Left, _Middle, _Right);
|
|
}
|
|
|
|
inline double _Fma(double _Left, double _Middle, double _Right) noexcept {
|
|
return _CSTD fma(_Left, _Middle, _Right);
|
|
}
|
|
|
|
inline long double _Fma(long double _Left, long double _Middle, long double _Right) noexcept {
|
|
return _CSTD fmal(_Left, _Middle, _Right);
|
|
}
|
|
#endif // !_HAS_IF_CONSTEXPR
|
|
|
|
template <class _Ty1, class _Ty2, class _Ty3,
|
|
_STD enable_if_t<_STD is_arithmetic_v<_Ty1> && _STD is_arithmetic_v<_Ty2> && _STD is_arithmetic_v<_Ty3>, int> = 0>
|
|
_NODISCARD _STD _Common_float_type_t<_Ty1, _STD _Common_float_type_t<_Ty2, _Ty3>> fma(
|
|
_Ty1 _Left, _Ty2 _Middle, _Ty3 _Right) noexcept /* strengthened */ {
|
|
using _Common = _STD _Common_float_type_t<_Ty1, _STD _Common_float_type_t<_Ty2, _Ty3>>;
|
|
#if _HAS_IF_CONSTEXPR
|
|
if constexpr (_STD is_same_v<_Common, float>) {
|
|
return _CSTD fmaf(static_cast<_Common>(_Left), static_cast<_Common>(_Middle), static_cast<_Common>(_Right));
|
|
} else if constexpr (_STD is_same_v<_Common, double>) {
|
|
return _CSTD fma(static_cast<_Common>(_Left), static_cast<_Common>(_Middle), static_cast<_Common>(_Right));
|
|
} else {
|
|
return _CSTD fmal(static_cast<_Common>(_Left), static_cast<_Common>(_Middle), static_cast<_Common>(_Right));
|
|
}
|
|
#else // ^^^ use "if constexpr" dispatch / use overload resolution vvv
|
|
return _Fma(static_cast<_Common>(_Left), static_cast<_Common>(_Middle), static_cast<_Common>(_Right));
|
|
#endif // _HAS_IF_CONSTEXPR
|
|
}
|
|
|
|
// FUNCTION TEMPLATE remquo
|
|
#if !_HAS_IF_CONSTEXPR
|
|
inline float _Remquo(float _Left, float _Right, int* _Pquo) noexcept {
|
|
return _CSTD remquof(_Left, _Right, _Pquo);
|
|
}
|
|
|
|
inline double _Remquo(double _Left, double _Right, int* _Pquo) noexcept {
|
|
return _CSTD remquo(_Left, _Right, _Pquo);
|
|
}
|
|
|
|
inline long double _Remquo(long double _Left, long double _Right, int* _Pquo) noexcept {
|
|
return _CSTD remquol(_Left, _Right, _Pquo);
|
|
}
|
|
#endif // !_HAS_IF_CONSTEXPR
|
|
|
|
template <class _Ty1, class _Ty2, _STD enable_if_t<_STD is_arithmetic_v<_Ty1> && _STD is_arithmetic_v<_Ty2>, int> = 0>
|
|
_STD _Common_float_type_t<_Ty1, _Ty2> remquo(_Ty1 _Left, _Ty2 _Right, int* _Pquo) noexcept /* strengthened */ {
|
|
using _Common = _STD _Common_float_type_t<_Ty1, _Ty2>;
|
|
#if _HAS_IF_CONSTEXPR
|
|
if constexpr (_STD is_same_v<_Common, float>) {
|
|
return _CSTD remquof(static_cast<_Common>(_Left), static_cast<_Common>(_Right), _Pquo);
|
|
} else if constexpr (_STD is_same_v<_Common, double>) {
|
|
return _CSTD remquo(static_cast<_Common>(_Left), static_cast<_Common>(_Right), _Pquo);
|
|
} else {
|
|
return _CSTD remquol(static_cast<_Common>(_Left), static_cast<_Common>(_Right), _Pquo);
|
|
}
|
|
#else // ^^^ use "if constexpr" dispatch / use overload resolution vvv
|
|
return _Remquo(static_cast<_Common>(_Left), static_cast<_Common>(_Right), _Pquo);
|
|
#endif // _HAS_IF_CONSTEXPR
|
|
}
|
|
|
|
#define _GENERIC_MATH1R(FUN, RET) \
|
|
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)); \
|
|
}
|
|
|
|
#define _GENERIC_MATH1(FUN) _GENERIC_MATH1R(FUN, double)
|
|
|
|
#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)); \
|
|
}
|
|
|
|
// The following order matches N4820 26.8.1 [cmath.syn].
|
|
_GENERIC_MATH1(acos)
|
|
_GENERIC_MATH1(asin)
|
|
_GENERIC_MATH1(atan)
|
|
_GENERIC_MATH2(atan2)
|
|
_GENERIC_MATH1(cos)
|
|
_GENERIC_MATH1(sin)
|
|
_GENERIC_MATH1(tan)
|
|
_GENERIC_MATH1(acosh)
|
|
_GENERIC_MATH1(asinh)
|
|
_GENERIC_MATH1(atanh)
|
|
_GENERIC_MATH1(cosh)
|
|
_GENERIC_MATH1(sinh)
|
|
_GENERIC_MATH1(tanh)
|
|
_GENERIC_MATH1(exp)
|
|
_GENERIC_MATH1(exp2)
|
|
_GENERIC_MATH1(expm1)
|
|
// frexp() is hand-crafted
|
|
_GENERIC_MATH1R(ilogb, int)
|
|
_GENERIC_MATH1X(ldexp, int)
|
|
_GENERIC_MATH1(log)
|
|
_GENERIC_MATH1(log10)
|
|
_GENERIC_MATH1(log1p)
|
|
_GENERIC_MATH1(log2)
|
|
_GENERIC_MATH1(logb)
|
|
// No modf(), types must match
|
|
_GENERIC_MATH1X(scalbn, int)
|
|
_GENERIC_MATH1X(scalbln, long)
|
|
_GENERIC_MATH1(cbrt)
|
|
// abs() has integer overloads
|
|
_GENERIC_MATH1(fabs)
|
|
_GENERIC_MATH2(hypot)
|
|
// 3-arg hypot() is hand-crafted
|
|
// pow() is hand-crafted
|
|
_GENERIC_MATH1(sqrt)
|
|
_GENERIC_MATH1(erf)
|
|
_GENERIC_MATH1(erfc)
|
|
_GENERIC_MATH1(lgamma)
|
|
_GENERIC_MATH1(tgamma)
|
|
_GENERIC_MATH1(ceil)
|
|
_GENERIC_MATH1(floor)
|
|
_GENERIC_MATH1(nearbyint)
|
|
_GENERIC_MATH1(rint)
|
|
_GENERIC_MATH1R(lrint, long)
|
|
_GENERIC_MATH1R(llrint, long long)
|
|
_GENERIC_MATH1(round)
|
|
_GENERIC_MATH1R(lround, long)
|
|
_GENERIC_MATH1R(llround, long long)
|
|
_GENERIC_MATH1(trunc)
|
|
_GENERIC_MATH2(fmod)
|
|
_GENERIC_MATH2(remainder)
|
|
// remquo() is hand-crafted
|
|
_GENERIC_MATH2(copysign)
|
|
// nan(const char*) is exempt
|
|
_GENERIC_MATH2(nextafter)
|
|
_GENERIC_MATH1X(nexttoward, long double)
|
|
_GENERIC_MATH2(fdim)
|
|
_GENERIC_MATH2(fmax)
|
|
_GENERIC_MATH2(fmin)
|
|
// fma() is hand-crafted
|
|
// lerp() should be exempt, LWG-3223
|
|
// The "classification/comparison functions" (fpclassify(), etc.) are exempt, LWG-1327
|
|
// TRANSITION, VSO-945789, Special Math shouldn't be exempt
|
|
|
|
#undef _GENERIC_MATH1R
|
|
#undef _GENERIC_MATH1
|
|
#undef _GENERIC_MATH1X
|
|
#undef _GENERIC_MATH2
|
|
|
|
#pragma pop_macro("new")
|
|
_STL_RESTORE_CLANG_WARNINGS
|
|
#pragma warning(pop)
|
|
#pragma pack(pop)
|
|
#endif // _STL_COMPILER_PREPROCESSOR
|
|
#endif // _XTGMATH
|