33#ifndef GKO_PUBLIC_CORE_BASE_MATH_HPP_
34#define GKO_PUBLIC_CORE_BASE_MATH_HPP_
45#include <ginkgo/config.hpp>
46#include <ginkgo/core/base/types.hpp>
47#include <ginkgo/core/base/utils.hpp>
138struct remove_complex_impl {
146struct remove_complex_impl<std::complex<T>> {
157struct to_complex_impl {
158 using type = std::complex<T>;
167struct to_complex_impl<std::complex<T>> {
168 using type = std::complex<T>;
173struct is_complex_impl :
public std::integral_constant<bool, false> {};
176struct is_complex_impl<std::complex<T>>
177 :
public std::integral_constant<bool, true> {};
181struct is_complex_or_scalar_impl : std::is_scalar<T> {};
184struct is_complex_or_scalar_impl<std::complex<T>> : std::is_scalar<T> {};
194template <
template <
typename>
class converter,
typename T>
195struct template_converter {};
206template <
template <
typename>
class converter,
template <
typename...>
class T,
213template <
typename T,
typename =
void>
214struct remove_complex_s {};
223struct remove_complex_s<
T,
224 std::enable_if_t<is_complex_or_scalar_impl<T>::value>> {
225 using type =
typename detail::remove_complex_impl<T>::type;
235struct remove_complex_s<
236 T, std::enable_if_t<!is_complex_or_scalar_impl<T>::value>> {
238 typename detail::template_converter<detail::remove_complex_impl,
243template <
typename T,
typename =
void>
244struct to_complex_s {};
253struct to_complex_s<
T, std::enable_if_t<is_complex_or_scalar_impl<T>::value>> {
254 using type =
typename detail::to_complex_impl<T>::type;
264struct to_complex_s<
T, std::enable_if_t<!is_complex_or_scalar_impl<T>::value>> {
266 typename detail::template_converter<detail::to_complex_impl, T>::type;
292 using type =
typename std::complex<T>::value_type;
317 return detail::is_complex_impl<T>::value;
341 return detail::is_complex_or_scalar_impl<T>::value;
390struct next_precision_impl {};
393struct next_precision_impl<
float> {
398struct next_precision_impl<
double> {
403struct next_precision_impl<std::complex<T>> {
404 using type = std::complex<typename next_precision_impl<T>::type>;
409struct reduce_precision_impl {
414struct reduce_precision_impl<std::complex<T>> {
415 using type = std::complex<typename reduce_precision_impl<T>::type>;
419struct reduce_precision_impl<
double> {
424struct reduce_precision_impl<
float> {
430struct increase_precision_impl {
435struct increase_precision_impl<std::complex<T>> {
436 using type = std::complex<typename increase_precision_impl<T>::type>;
440struct increase_precision_impl<
float> {
445struct increase_precision_impl<
half> {
451struct infinity_impl {
454 static constexpr auto value = std::numeric_limits<T>::infinity();
461template <
typename T1,
typename T2>
462struct highest_precision_impl {
463 using type =
decltype(
T1{} +
T2{});
466template <
typename T1,
typename T2>
467struct highest_precision_impl<std::complex<T1>, std::complex<T2>> {
468 using type = std::complex<typename highest_precision_impl<T1, T2>::type>;
471template <
typename Head,
typename...
Tail>
472struct highest_precision_variadic {
473 using type =
typename highest_precision_impl<
474 Head,
typename highest_precision_variadic<
Tail...>::type>::type;
477template <
typename Head>
478struct highest_precision_variadic<
Head> {
528template <
typename...
Ts>
530 typename detail::highest_precision_variadic<
Ts...>::type;
565template <
typename FloatType,
size_type NumComponents,
size_type ComponentId>
573struct truncate_type_impl {
577template <
typename T,
size_type Components>
583struct truncate_type_impl<std::complex<T>> {
584 using type = std::complex<typename truncate_type_impl<T>::type>;
589struct type_size_impl {
590 static constexpr auto value =
sizeof(
T) *
byte_size;
594struct type_size_impl<std::complex<T>> {
595 static constexpr auto value =
sizeof(
T) *
byte_size;
606template <
typename T,
size_type Limit = sizeof(u
int16) *
byte_size>
608 std::conditional_t<detail::type_size_impl<T>::value >= 2 *
Limit,
618template <
typename S,
typename R>
647#if defined(__HIPCC__) && GINKGO_HIP_PLATFORM_HCC
712GKO_INLINE
__device__ constexpr std::enable_if_t<
713 !std::is_same<T, std::complex<remove_complex<T>>>::value,
T>
742GKO_INLINE
__device__ constexpr std::enable_if_t<
743 !std::is_same<T, std::complex<remove_complex<T>>>::value,
T>
775GKO_INLINE GKO_ATTRIBUTES
constexpr T zero()
791GKO_INLINE GKO_ATTRIBUTES
constexpr T zero(
const T&)
803GKO_INLINE GKO_ATTRIBUTES
constexpr T one()
819GKO_INLINE GKO_ATTRIBUTES
constexpr T one(
const T&)
828#undef GKO_BIND_ZERO_ONE
840GKO_INLINE GKO_ATTRIBUTES
constexpr bool is_zero(
T value)
873GKO_INLINE GKO_ATTRIBUTES
constexpr T max(
const T& x,
const T& y)
875 return x >= y ? x : y;
891GKO_INLINE GKO_ATTRIBUTES
constexpr T min(
const T& x,
const T& y)
893 return x <= y ? x : y;
909template <
typename Ref,
typename Dummy = xstd::
void_t<>>
910struct has_to_arithmetic_type : std::false_type {
911 static_assert(std::is_same<Dummy, void>::value,
912 "Do not modify the Dummy value!");
916template <
typename Ref>
917struct has_to_arithmetic_type<
918 Ref, xstd::void_t<decltype(std::declval<Ref>().to_arithmetic_type())>>
920 using type =
decltype(std::declval<Ref>().to_arithmetic_type());
928template <
typename Ref,
typename Dummy = xstd::
void_t<>>
929struct has_arithmetic_type : std::false_type {
930 static_assert(std::is_same<Dummy, void>::value,
931 "Do not modify the Dummy value!");
934template <
typename Ref>
935struct has_arithmetic_type<
Ref, xstd::void_t<typename Ref::arithmetic_type>>
950template <
typename Ref>
951constexpr GKO_ATTRIBUTES
952 std::enable_if_t<has_to_arithmetic_type<Ref>::value,
953 typename has_to_arithmetic_type<Ref>::type>
954 to_arithmetic_type(
const Ref&
ref)
956 return ref.to_arithmetic_type();
959template <
typename Ref>
960constexpr GKO_ATTRIBUTES std::enable_if_t<!has_to_arithmetic_type<Ref>::value &&
961 has_arithmetic_type<Ref>::value,
962 typename Ref::arithmetic_type>
963to_arithmetic_type(
const Ref&
ref)
968template <
typename Ref>
969constexpr GKO_ATTRIBUTES std::enable_if_t<!has_to_arithmetic_type<Ref>::value &&
970 !has_arithmetic_type<Ref>::value,
972to_arithmetic_type(
const Ref&
ref)
982GKO_ATTRIBUTES GKO_INLINE
constexpr std::enable_if_t<!is_complex_s<T>::value,
T>
989GKO_ATTRIBUTES GKO_INLINE
constexpr std::enable_if_t<is_complex_s<T>::value,
998GKO_ATTRIBUTES GKO_INLINE
constexpr std::enable_if_t<!is_complex_s<T>::value,
T>
1004template <
typename T>
1005GKO_ATTRIBUTES GKO_INLINE
constexpr std::enable_if_t<is_complex_s<T>::value,
1007imag_impl(
const T& x)
1013template <
typename T>
1014GKO_ATTRIBUTES GKO_INLINE
constexpr std::enable_if_t<!is_complex_s<T>::value,
T>
1015conj_impl(
const T& x)
1020template <
typename T>
1021GKO_ATTRIBUTES GKO_INLINE
constexpr std::enable_if_t<is_complex_s<T>::value,
T>
1022conj_impl(
const T& x)
1024 return T{real_impl(x), -imag_impl(x)};
1040template <
typename T>
1041GKO_ATTRIBUTES GKO_INLINE
constexpr auto real(
const T& x)
1043 return detail::real_impl(detail::to_arithmetic_type(x));
1056template <
typename T>
1057GKO_ATTRIBUTES GKO_INLINE
constexpr auto imag(
const T& x)
1059 return detail::imag_impl(detail::to_arithmetic_type(x));
1070template <
typename T>
1071GKO_ATTRIBUTES GKO_INLINE
constexpr auto conj(
const T& x)
1073 return detail::conj_impl(detail::to_arithmetic_type(x));
1084template <
typename T>
1101template <
typename T>
1103 GKO_ATTRIBUTES
constexpr xstd::enable_if_t<!is_complex_s<T>::value,
T>
1106 return x >=
zero<T>() ? x : -x;
1110template <
typename T>
1111GKO_INLINE GKO_ATTRIBUTES
constexpr xstd::enable_if_t<is_complex_s<T>::value,
1124template <
typename T>
1125GKO_INLINE GKO_ATTRIBUTES
constexpr T pi()
1127 return static_cast<T>(3.1415926535897932384626433);
1139template <
typename T>
1140GKO_INLINE GKO_ATTRIBUTES
constexpr std::complex<remove_complex<T>>
unit_root(
1160template <
typename T>
1178template <
typename T>
1180 const T&
hint =
T{1})
noexcept
1197template <
typename T>
1198GKO_INLINE GKO_ATTRIBUTES std::enable_if_t<!is_complex_s<T>::value,
bool>
1201 constexpr T infinity{detail::infinity_impl<T>::value};
1217template <
typename T>
1218GKO_INLINE GKO_ATTRIBUTES std::enable_if_t<is_complex_s<T>::value,
bool>
1236template <
typename T>
1252template <
typename T>
1253GKO_INLINE GKO_ATTRIBUTES std::enable_if_t<!is_complex_s<T>::value,
bool>
1256 return std::isnan(value);
1269template <
typename T>
1270GKO_INLINE GKO_ATTRIBUTES std::enable_if_t<is_complex_s<T>::value,
bool>
is_nan(
1273 return std::isnan(value.real()) || std::isnan(value.imag());
1284template <
typename T>
1285GKO_INLINE GKO_ATTRIBUTES
constexpr std::enable_if_t<!is_complex_s<T>::value,
T>
1288 return std::numeric_limits<T>::quiet_NaN();
1299template <
typename T>
1300GKO_INLINE GKO_ATTRIBUTES
constexpr std::enable_if_t<is_complex_s<T>::value,
T>
The Ginkgo namespace.
Definition abstract_factory.hpp:48
constexpr T one()
Returns the multiplicative identity for T.
Definition math.hpp:803
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:1199
constexpr T pi()
Returns the value of pi.
Definition math.hpp:1125
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:354
constexpr increase_precision< T > round_up(T val)
Increases the precision of the input parameter.
Definition math.hpp:559
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:607
typename detail::next_precision_impl< T >::type next_precision
Obtains the next type in the singly-linked precision list.
Definition math.hpp:490
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:529
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:373
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:1161
constexpr bool is_complex_or_scalar()
Checks if T is a complex/scalar type.
Definition math.hpp:339
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:1254
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:305
constexpr std::enable_if_t<!is_complex_s< T >::value, T > nan()
Returns a quiet NaN of the given type.
Definition math.hpp:1286
constexpr T zero()
Returns the additive identity for T.
Definition math.hpp:775
constexpr bool is_zero(T value)
Returns true if and only if the given value is zero.
Definition math.hpp:840
constexpr auto imag(const T &x)
Returns the imaginary part of the object.
Definition math.hpp:1057
std::uint32_t uint32
32-bit unsigned integral type.
Definition types.hpp:160
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:1140
typename detail::reduce_precision_impl< T >::type reduce_precision
Obtains the next type in the hierarchy with lower precision than T.
Definition math.hpp:507
constexpr reduce_precision< T > round_down(T val)
Reduces the precision of the input parameter.
Definition math.hpp:543
std::int64_t int64
64-bit signed integral type.
Definition types.hpp:143
constexpr int64 ceildiv(int64 num, int64 den)
Performs integer division with rounding up.
Definition math.hpp:641
constexpr bool is_complex()
Checks if T is a complex type.
Definition math.hpp:315
T safe_divide(T a, T b)
Computes the quotient of the given parameters, guarding against division by zero.
Definition math.hpp:1237
constexpr T min(const T &x, const T &y)
Returns the smaller of the arguments.
Definition math.hpp:891
constexpr xstd::enable_if_t<!is_complex_s< T >::value, T > abs(const T &x)
Returns the absolute value of the object.
Definition math.hpp:1104
constexpr auto squared_norm(const T &x) -> decltype(real(conj(x) *x))
Returns the squared norm of the object.
Definition math.hpp:1085
next_precision< T > previous_precision
Obtains the previous type in the singly-linked precision list.
Definition math.hpp:500
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:329
constexpr size_type byte_size
Number of bits in a byte.
Definition types.hpp:211
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:1179
typename detail::increase_precision_impl< T >::type increase_precision
Obtains the next type in the hierarchy with higher precision than T.
Definition math.hpp:514
remove_complex< T > to_real
to_real is alias of remove_complex
Definition math.hpp:382
constexpr auto conj(const T &x)
Returns the conjugate of an object.
Definition math.hpp:1071
constexpr bool is_nonzero(T value)
Returns true if and only if the given value is not zero.
Definition math.hpp:855
constexpr T max(const T &x, const T &y)
Returns the larger of the arguments.
Definition math.hpp:873
constexpr auto real(const T &x)
Returns the real part of the object.
Definition math.hpp:1041
Access the underlying real type of a complex number.
Definition math.hpp:279
T type
The type.
Definition math.hpp:281
Used to convert objects of type S to objects of type R using static_cast.
Definition math.hpp:619
R operator()(S val)
Converts the object to result type.
Definition math.hpp:626