5#ifndef GKO_PUBLIC_CORE_BASE_MATH_HPP_
6#define GKO_PUBLIC_CORE_BASE_MATH_HPP_
16#include <ginkgo/config.hpp>
17#include <ginkgo/core/base/half.hpp>
18#include <ginkgo/core/base/types.hpp>
19#include <ginkgo/core/base/utils.hpp>
40struct remove_complex_impl {
48struct remove_complex_impl<
std::complex<T>> {
59struct to_complex_impl {
60 using type = std::complex<T>;
69struct to_complex_impl<
std::complex<T>> {
70 using type = std::complex<T>;
75struct is_complex_impl :
public std::integral_constant<bool, false> {};
78struct is_complex_impl<
std::complex<T>>
79 :
public std::integral_constant<bool, true> {};
83struct is_complex_or_scalar_impl : std::is_scalar<T> {};
86struct is_complex_or_scalar_impl<half> : std::true_type {};
89struct is_complex_or_scalar_impl<
std::complex<T>>
90 : is_complex_or_scalar_impl<T> {};
100template <
template <
typename>
class converter,
typename T>
101struct template_converter {};
112template <
template <
typename>
class converter,
template <
typename...>
class T,
114struct template_converter<converter, T<Rest...>> {
115 using type = T<typename converter<Rest>::type...>;
119template <
typename T,
typename =
void>
120struct remove_complex_s {};
129struct remove_complex_s<T,
130 std::enable_if_t<is_complex_or_scalar_impl<T>::value>> {
131 using type =
typename detail::remove_complex_impl<T>::type;
141struct remove_complex_s<
142 T,
std::enable_if_t<!is_complex_or_scalar_impl<T>::value>> {
144 typename detail::template_converter<detail::remove_complex_impl,
149template <
typename T,
typename =
void>
150struct to_complex_s {};
159struct to_complex_s<T,
std::enable_if_t<is_complex_or_scalar_impl<T>::value>> {
160 using type =
typename detail::to_complex_impl<T>::type;
170struct to_complex_s<T,
std::enable_if_t<!is_complex_or_scalar_impl<T>::value>> {
172 typename detail::template_converter<detail::to_complex_impl, T>::type;
198 using type =
typename std::complex<T>::value_type;
223 return detail::is_complex_impl<T>::value;
247 return detail::is_complex_or_scalar_impl<T>::value;
296struct next_precision_base_impl {};
299struct next_precision_base_impl<float> {
304struct next_precision_base_impl<double> {
309struct next_precision_base_impl<
std::complex<T>> {
310 using type = std::complex<typename next_precision_base_impl<T>::type>;
315struct next_precision_impl {};
319struct next_precision_impl<
gko::
half> {
324struct next_precision_impl<float> {
329struct next_precision_impl<double> {
334struct next_precision_impl<
std::complex<T>> {
335 using type = std::complex<typename next_precision_impl<T>::type>;
340struct reduce_precision_impl {
345struct reduce_precision_impl<
std::complex<T>> {
346 using type = std::complex<typename reduce_precision_impl<T>::type>;
350struct reduce_precision_impl<double> {
355struct reduce_precision_impl<float> {
361struct increase_precision_impl {
366struct increase_precision_impl<
std::complex<T>> {
367 using type = std::complex<typename increase_precision_impl<T>::type>;
371struct increase_precision_impl<float> {
376struct increase_precision_impl<
half> {
382struct infinity_impl {
385 static constexpr auto value = std::numeric_limits<T>::infinity();
392template <
typename T1,
typename T2>
393struct highest_precision_impl {
394 using type =
decltype(T1{} + T2{});
397template <
typename T1,
typename T2>
398struct highest_precision_impl<
std::complex<T1>, std::complex<T2>> {
399 using type = std::complex<typename highest_precision_impl<T1, T2>::type>;
402template <
typename Head,
typename... Tail>
403struct highest_precision_variadic {
404 using type =
typename highest_precision_impl<
405 Head,
typename highest_precision_variadic<Tail...>::type>::type;
408template <
typename Head>
409struct highest_precision_variadic<Head> {
436#if GINKGO_ENABLE_HALF
477template <
typename... Ts>
479 typename detail::highest_precision_variadic<Ts...>::type;
514template <
typename FloatType,
size_type NumComponents,
size_type ComponentId>
522struct truncate_type_impl {
526template <
typename T,
size_type Components>
527struct truncate_type_impl<
truncated<T, Components, 0>> {
532struct truncate_type_impl<
std::complex<T>> {
533 using type = std::complex<typename truncate_type_impl<T>::type>;
538struct type_size_impl {
539 static constexpr auto value =
sizeof(T) * byte_size;
543struct type_size_impl<
std::complex<T>> {
544 static constexpr auto value =
sizeof(T) * byte_size;
555template <
typename T,
size_type Limit = sizeof(u
int16) *
byte_size>
557 std::conditional_t<detail::type_size_impl<T>::value >= 2 * Limit,
567template <
typename S,
typename R>
575 GKO_ATTRIBUTES R
operator()(S val) {
return static_cast<R
>(val); }
592 return (num + den - 1) / den;
618GKO_INLINE
constexpr T
zero(
const T&)
630GKO_INLINE
constexpr T
one()
636GKO_INLINE
constexpr half one<half>()
638 constexpr auto bits =
static_cast<uint16>(0b0'01111'0000000000u);
639 return half::create_from_bits(bits);
653GKO_INLINE
constexpr T
one(
const T&)
701GKO_INLINE
constexpr T
max(
const T& x,
const T& y)
703 return x >= y ? x : y;
719GKO_INLINE
constexpr T
min(
const T& x,
const T& y)
721 return x <= y ? x : y;
737template <
typename Ref,
typename Dummy = std::
void_t<>>
738struct has_to_arithmetic_type : std::false_type {
739 static_assert(std::is_same<Dummy, void>::value,
740 "Do not modify the Dummy value!");
744template <
typename Ref>
745struct has_to_arithmetic_type<
746 Ref,
std::
void_t<decltype(std::declval<Ref>().to_arithmetic_type())>>
748 using type =
decltype(std::declval<Ref>().to_arithmetic_type());
756template <
typename Ref,
typename Dummy = std::
void_t<>>
757struct has_arithmetic_type : std::false_type {
758 static_assert(std::is_same<Dummy, void>::value,
759 "Do not modify the Dummy value!");
762template <
typename Ref>
763struct has_arithmetic_type<Ref,
std::
void_t<typename Ref::arithmetic_type>>
778template <
typename Ref>
779constexpr GKO_ATTRIBUTES
780 std::enable_if_t<has_to_arithmetic_type<Ref>::value,
781 typename has_to_arithmetic_type<Ref>::type>
782 to_arithmetic_type(
const Ref& ref)
784 return ref.to_arithmetic_type();
787template <
typename Ref>
788constexpr GKO_ATTRIBUTES std::enable_if_t<!has_to_arithmetic_type<Ref>::value &&
789 has_arithmetic_type<Ref>::value,
790 typename Ref::arithmetic_type>
791to_arithmetic_type(
const Ref& ref)
796template <
typename Ref>
797constexpr GKO_ATTRIBUTES std::enable_if_t<!has_to_arithmetic_type<Ref>::value &&
798 !has_arithmetic_type<Ref>::value,
800to_arithmetic_type(
const Ref& ref)
810GKO_ATTRIBUTES GKO_INLINE
constexpr std::enable_if_t<!is_complex_s<T>::value, T>
817GKO_ATTRIBUTES GKO_INLINE
constexpr std::enable_if_t<is_complex_s<T>::value,
826GKO_ATTRIBUTES GKO_INLINE
constexpr std::enable_if_t<!is_complex_s<T>::value, T>
833GKO_ATTRIBUTES GKO_INLINE
constexpr std::enable_if_t<is_complex_s<T>::value,
842GKO_ATTRIBUTES GKO_INLINE
constexpr std::enable_if_t<!is_complex_s<T>::value, T>
849GKO_ATTRIBUTES GKO_INLINE
constexpr std::enable_if_t<is_complex_s<T>::value, T>
852 return T{real_impl(x), -imag_impl(x)};
869GKO_ATTRIBUTES GKO_INLINE
constexpr auto real(
const T& x)
871 return detail::real_impl(detail::to_arithmetic_type(x));
885GKO_ATTRIBUTES GKO_INLINE
constexpr auto imag(
const T& x)
887 return detail::imag_impl(detail::to_arithmetic_type(x));
899GKO_ATTRIBUTES GKO_INLINE
constexpr auto conj(
const T& x)
901 return detail::conj_impl(detail::to_arithmetic_type(x));
931GKO_INLINE
constexpr std::enable_if_t<!is_complex_s<T>::value, T>
abs(
934 return x >=
zero<T>() ? x : -x;
946GKO_INLINE
gko::half abs(
const std::complex<gko::half>& x)
949 return static_cast<gko::half>(
abs(std::complex<float>(x)));
960GKO_INLINE std::complex<gko::half> sqrt(std::complex<gko::half> a)
962 return std::complex<gko::half>(sqrt(std::complex<float>(
963 static_cast<float>(a.real()),
static_cast<float>(a.imag()))));
973GKO_INLINE
constexpr T
pi()
975 return static_cast<T
>(3.1415926535897932384626433);
1008template <
typename T>
1026template <
typename T>
1028 const T& hint = T{1})
noexcept
1045template <
typename T>
1046GKO_INLINE GKO_ATTRIBUTES std::enable_if_t<!is_complex_s<T>::value,
bool>
1049 constexpr T infinity{detail::infinity_impl<T>::value};
1050 return abs(value) < infinity;
1065template <
typename T>
1066GKO_INLINE GKO_ATTRIBUTES std::enable_if_t<is_complex_s<T>::value,
bool>
1084template <
typename T>
1100template <
typename T>
1102 "is_nan can't be used safely on the device (MSVC+CUDA), and will thus be "
1103 "removed in a future release, without replacement")
1104GKO_INLINE GKO_ATTRIBUTES
1108 return isnan(value);
1121template <
typename T>
1123 "is_nan can't be used safely on the device (MSVC+CUDA), and will thus be "
1124 "removed in a future release, without replacement")
1139template <
typename T>
1140GKO_INLINE
constexpr std::enable_if_t<!is_complex_s<T>::value, T>
nan()
1142 return std::numeric_limits<T>::quiet_NaN();
1153template <
typename T>
1154GKO_INLINE
constexpr std::enable_if_t<is_complex_s<T>::value, T>
nan()
A class providing basic support for half precision floating point types.
Definition half.hpp:286
typename detail::make_void< Ts... >::type void_t
Use the custom implementation, since the std::void_t used in is_matrix_type_builder seems to trigger ...
Definition std_extensions.hpp:47
The Ginkgo namespace.
Definition abstract_factory.hpp:20
constexpr T one()
Returns the multiplicative identity for T.
Definition math.hpp:630
std::enable_if_t<!is_complex_s< T >::value, bool > is_finite(const T &value)
Checks if a floating point number is finite, meaning it is neither +/- infinity nor NaN.
Definition math.hpp:1047
constexpr T pi()
Returns the value of pi.
Definition math.hpp:973
constexpr std::enable_if_t<!is_complex_s< T >::value, T > abs(const T &x)
Returns the absolute value of the object.
Definition math.hpp:931
typename detail::remove_complex_s< T >::type remove_complex
Obtain the type which removed the complex of complex/scalar type or the template parameter of class b...
Definition math.hpp:260
constexpr increase_precision< T > round_up(T val)
Increases the precision of the input parameter.
Definition math.hpp:508
typename detail::next_precision_base_impl< T >::type next_precision_base
Obtains the next type in the singly-linked precision list.
Definition math.hpp:421
std::conditional_t< detail::type_size_impl< T >::value >=2 *Limit, typename detail::truncate_type_impl< T >::type, T > truncate_type
Truncates the type by half (by dropping bits), but ensures that it is at least Limit bits wide.
Definition math.hpp:556
typename detail::next_precision_impl< T >::type next_precision
Obtains the next type in the singly-linked precision list with half.
Definition math.hpp:438
typename detail::highest_precision_variadic< Ts... >::type highest_precision
Obtains the smallest arithmetic type that is able to store elements of all template parameter types e...
Definition math.hpp:478
typename detail::to_complex_s< T >::type to_complex
Obtain the type which adds the complex of complex/scalar type or the template parameter of class by a...
Definition math.hpp:279
constexpr uint32 get_significant_bit(const T &n, uint32 hint=0u) noexcept
Returns the position of the most significant bit of the number.
Definition math.hpp:1009
constexpr bool is_complex_or_scalar()
Checks if T is a complex/scalar type.
Definition math.hpp:245
std::enable_if_t<!is_complex_s< T >::value, bool > is_nan(const T &value)
Checks if a floating point number is NaN.
Definition math.hpp:1105
detail::is_complex_impl< T > is_complex_s
Allows to check if T is a complex value during compile time by accessing the value attribute of this ...
Definition math.hpp:211
constexpr std::enable_if_t<!is_complex_s< T >::value, T > nan()
Returns a quiet NaN of the given type.
Definition math.hpp:1140
constexpr T zero()
Returns the additive identity for T.
Definition math.hpp:602
constexpr bool is_zero(T value)
Returns true if and only if the given value is zero.
Definition math.hpp:668
constexpr auto imag(const T &x)
Returns the imaginary part of the object.
Definition math.hpp:885
std::uint32_t uint32
32-bit unsigned integral type.
Definition types.hpp:129
constexpr std::complex< remove_complex< T > > unit_root(int64 n, int64 k=1)
Returns the value of exp(2 * pi * i * k / n), i.e.
Definition math.hpp:988
next_precision_base< T > previous_precision_base
Obtains the previous type in the singly-linked precision list.
Definition math.hpp:431
typename detail::reduce_precision_impl< T >::type reduce_precision
Obtains the next type in the hierarchy with lower precision than T.
Definition math.hpp:456
constexpr reduce_precision< T > round_down(T val)
Reduces the precision of the input parameter.
Definition math.hpp:492
std::int64_t int64
64-bit signed integral type.
Definition types.hpp:112
constexpr int64 ceildiv(int64 num, int64 den)
Performs integer division with rounding up.
Definition math.hpp:590
constexpr bool is_complex()
Checks if T is a complex type.
Definition math.hpp:221
T safe_divide(T a, T b)
Computes the quotient of the given parameters, guarding against division by zero.
Definition math.hpp:1085
constexpr T min(const T &x, const T &y)
Returns the smaller of the arguments.
Definition math.hpp:719
constexpr auto squared_norm(const T &x) -> decltype(real(conj(x) *x))
Returns the squared norm of the object.
Definition math.hpp:913
detail::is_complex_or_scalar_impl< T > is_complex_or_scalar_s
Allows to check if T is a complex or scalar value during compile time by accessing the value attribut...
Definition math.hpp:235
constexpr T get_superior_power(const T &base, const T &limit, const T &hint=T{1}) noexcept
Returns the smallest power of base not smaller than limit.
Definition math.hpp:1027
typename detail::increase_precision_impl< T >::type increase_precision
Obtains the next type in the hierarchy with higher precision than T.
Definition math.hpp:463
remove_complex< T > to_real
to_real is alias of remove_complex
Definition math.hpp:288
constexpr auto conj(const T &x)
Returns the conjugate of an object.
Definition math.hpp:899
constexpr bool is_nonzero(T value)
Returns true if and only if the given value is not zero.
Definition math.hpp:683
std::uint16_t uint16
16-bit unsigned integral type.
Definition types.hpp:123
constexpr T max(const T &x, const T &y)
Returns the larger of the arguments.
Definition math.hpp:701
constexpr auto real(const T &x)
Returns the real part of the object.
Definition math.hpp:869
Access the underlying real type of a complex number.
Definition math.hpp:185
T type
The type.
Definition math.hpp:187
Used to convert objects of type S to objects of type R using static_cast.
Definition math.hpp:568
R operator()(S val)
Converts the object to result type.
Definition math.hpp:575