5#ifndef GKO_PUBLIC_CORE_BASE_MATH_HPP_
6#define GKO_PUBLIC_CORE_BASE_MATH_HPP_
17#include <ginkgo/config.hpp>
18#include <ginkgo/core/base/types.hpp>
19#include <ginkgo/core/base/utils.hpp>
110struct remove_complex_impl {
118struct remove_complex_impl<std::complex<T>> {
129struct to_complex_impl {
130 using type = std::complex<T>;
139struct to_complex_impl<std::complex<T>> {
140 using type = std::complex<T>;
145struct is_complex_impl :
public std::integral_constant<bool, false> {};
148struct is_complex_impl<std::complex<T>>
149 :
public std::integral_constant<bool, true> {};
153struct is_complex_or_scalar_impl : std::is_scalar<T> {};
156struct is_complex_or_scalar_impl<std::complex<T>> : std::is_scalar<T> {};
166template <
template <
typename>
class converter,
typename T>
167struct template_converter {};
178template <
template <
typename>
class converter,
template <
typename...>
class T,
180struct template_converter<converter, T<Rest...>> {
181 using type = T<typename converter<Rest>::type...>;
185template <
typename T,
typename =
void>
186struct remove_complex_s {};
195struct remove_complex_s<T,
196 std::enable_if_t<is_complex_or_scalar_impl<T>::value>> {
197 using type =
typename detail::remove_complex_impl<T>::type;
207struct remove_complex_s<
208 T, std::enable_if_t<!is_complex_or_scalar_impl<T>::value>> {
210 typename detail::template_converter<detail::remove_complex_impl,
215template <
typename T,
typename =
void>
216struct to_complex_s {};
225struct to_complex_s<T, std::enable_if_t<is_complex_or_scalar_impl<T>::value>> {
226 using type =
typename detail::to_complex_impl<T>::type;
236struct to_complex_s<T, std::enable_if_t<!is_complex_or_scalar_impl<T>::value>> {
238 typename detail::template_converter<detail::to_complex_impl, T>::type;
264 using type =
typename std::complex<T>::value_type;
289 return detail::is_complex_impl<T>::value;
313 return detail::is_complex_or_scalar_impl<T>::value;
362struct next_precision_impl {};
365struct next_precision_impl<float> {
370struct next_precision_impl<double> {
375struct next_precision_impl<std::complex<T>> {
376 using type = std::complex<typename next_precision_impl<T>::type>;
381struct reduce_precision_impl {
386struct reduce_precision_impl<std::complex<T>> {
387 using type = std::complex<typename reduce_precision_impl<T>::type>;
391struct reduce_precision_impl<double> {
396struct reduce_precision_impl<float> {
402struct increase_precision_impl {
407struct increase_precision_impl<std::complex<T>> {
408 using type = std::complex<typename increase_precision_impl<T>::type>;
412struct increase_precision_impl<float> {
417struct increase_precision_impl<half> {
423struct infinity_impl {
426 static constexpr auto value = std::numeric_limits<T>::infinity();
433template <
typename T1,
typename T2>
434struct highest_precision_impl {
435 using type =
decltype(T1{} + T2{});
438template <
typename T1,
typename T2>
439struct highest_precision_impl<std::complex<T1>, std::complex<T2>> {
440 using type = std::complex<typename highest_precision_impl<T1, T2>::type>;
443template <
typename Head,
typename... Tail>
444struct highest_precision_variadic {
445 using type =
typename highest_precision_impl<
446 Head,
typename highest_precision_variadic<Tail...>::type>::type;
449template <
typename Head>
450struct highest_precision_variadic<Head> {
500template <
typename... Ts>
502 typename detail::highest_precision_variadic<Ts...>::type;
537template <
typename FloatType,
size_type NumComponents,
size_type ComponentId>
545struct truncate_type_impl {
549template <
typename T,
size_type Components>
550struct truncate_type_impl<
truncated<T, Components, 0>> {
555struct truncate_type_impl<std::complex<T>> {
556 using type = std::complex<typename truncate_type_impl<T>::type>;
561struct type_size_impl {
562 static constexpr auto value =
sizeof(T) *
byte_size;
566struct type_size_impl<std::complex<T>> {
567 static constexpr auto value =
sizeof(T) *
byte_size;
578template <
typename T,
size_type Limit = sizeof(u
int16) *
byte_size>
580 std::conditional_t<detail::type_size_impl<T>::value >= 2 * Limit,
590template <
typename S,
typename R>
598 GKO_ATTRIBUTES R
operator()(S val) {
return static_cast<R
>(val); }
615 return (num + den - 1) / den;
619#if defined(__HIPCC__) && GINKGO_HIP_PLATFORM_HCC
628GKO_INLINE __host__
constexpr T
zero()
644GKO_INLINE __host__
constexpr T
zero(
const T&)
656GKO_INLINE __host__
constexpr T
one()
672GKO_INLINE __host__
constexpr T
one(
const T&)
684GKO_INLINE __device__
constexpr std::enable_if_t<
685 !std::is_same<T, std::complex<remove_complex<T>>>::value, T>
702GKO_INLINE __device__
constexpr T
zero(
const T&)
714GKO_INLINE __device__
constexpr std::enable_if_t<
715 !std::is_same<T, std::complex<remove_complex<T>>>::value, T>
732GKO_INLINE __device__
constexpr T
one(
const T&)
747GKO_INLINE GKO_ATTRIBUTES
constexpr T
zero()
763GKO_INLINE GKO_ATTRIBUTES
constexpr T
zero(
const T&)
775GKO_INLINE GKO_ATTRIBUTES
constexpr T
one()
791GKO_INLINE GKO_ATTRIBUTES
constexpr T
one(
const T&)
800#undef GKO_BIND_ZERO_ONE
812GKO_INLINE GKO_ATTRIBUTES
constexpr bool is_zero(T value)
845GKO_INLINE GKO_ATTRIBUTES
constexpr T
max(
const T& x,
const T& y)
847 return x >= y ? x : y;
863GKO_INLINE GKO_ATTRIBUTES
constexpr T
min(
const T& x,
const T& y)
865 return x <= y ? x : y;
881template <
typename Ref,
typename Dummy = xstd::
void_t<>>
882struct has_to_arithmetic_type : std::false_type {
883 static_assert(std::is_same<Dummy, void>::value,
884 "Do not modify the Dummy value!");
888template <
typename Ref>
889struct has_to_arithmetic_type<
890 Ref, xstd::void_t<decltype(std::declval<Ref>().to_arithmetic_type())>>
892 using type =
decltype(std::declval<Ref>().to_arithmetic_type());
900template <
typename Ref,
typename Dummy = xstd::
void_t<>>
901struct has_arithmetic_type : std::false_type {
902 static_assert(std::is_same<Dummy, void>::value,
903 "Do not modify the Dummy value!");
906template <
typename Ref>
907struct has_arithmetic_type<Ref, xstd::void_t<typename Ref::arithmetic_type>>
922template <
typename Ref>
923constexpr GKO_ATTRIBUTES
924 std::enable_if_t<has_to_arithmetic_type<Ref>::value,
925 typename has_to_arithmetic_type<Ref>::type>
926 to_arithmetic_type(
const Ref& ref)
928 return ref.to_arithmetic_type();
931template <
typename Ref>
932constexpr GKO_ATTRIBUTES std::enable_if_t<!has_to_arithmetic_type<Ref>::value &&
933 has_arithmetic_type<Ref>::value,
934 typename Ref::arithmetic_type>
935to_arithmetic_type(
const Ref& ref)
940template <
typename Ref>
941constexpr GKO_ATTRIBUTES std::enable_if_t<!has_to_arithmetic_type<Ref>::value &&
942 !has_arithmetic_type<Ref>::value,
944to_arithmetic_type(
const Ref& ref)
954GKO_ATTRIBUTES GKO_INLINE
constexpr std::enable_if_t<!is_complex_s<T>::value, T>
961GKO_ATTRIBUTES GKO_INLINE
constexpr std::enable_if_t<is_complex_s<T>::value,
970GKO_ATTRIBUTES GKO_INLINE
constexpr std::enable_if_t<!is_complex_s<T>::value, T>
977GKO_ATTRIBUTES GKO_INLINE
constexpr std::enable_if_t<is_complex_s<T>::value,
986GKO_ATTRIBUTES GKO_INLINE
constexpr std::enable_if_t<!is_complex_s<T>::value, T>
993GKO_ATTRIBUTES GKO_INLINE
constexpr std::enable_if_t<is_complex_s<T>::value, T>
996 return T{real_impl(x), -imag_impl(x)};
1012template <
typename T>
1013GKO_ATTRIBUTES GKO_INLINE
constexpr auto real(
const T& x)
1015 return detail::real_impl(detail::to_arithmetic_type(x));
1028template <
typename T>
1029GKO_ATTRIBUTES GKO_INLINE
constexpr auto imag(
const T& x)
1031 return detail::imag_impl(detail::to_arithmetic_type(x));
1042template <
typename T>
1043GKO_ATTRIBUTES GKO_INLINE
constexpr auto conj(
const T& x)
1045 return detail::conj_impl(detail::to_arithmetic_type(x));
1056template <
typename T>
1073template <
typename T>
1075 GKO_ATTRIBUTES
constexpr xstd::enable_if_t<!is_complex_s<T>::value, T>
1078 return x >=
zero<T>() ? x : -x;
1082template <
typename T>
1083GKO_INLINE GKO_ATTRIBUTES
constexpr xstd::enable_if_t<is_complex_s<T>::value,
1096template <
typename T>
1097GKO_INLINE GKO_ATTRIBUTES
constexpr T
pi()
1099 return static_cast<T
>(3.1415926535897932384626433);
1111template <
typename T>
1112GKO_INLINE GKO_ATTRIBUTES
constexpr std::complex<remove_complex<T>>
unit_root(
1132template <
typename T>
1150template <
typename T>
1152 const T& hint = T{1})
noexcept
1169template <
typename T>
1170GKO_INLINE GKO_ATTRIBUTES std::enable_if_t<!is_complex_s<T>::value,
bool>
1173 constexpr T infinity{detail::infinity_impl<T>::value};
1174 return abs(value) < infinity;
1189template <
typename T>
1190GKO_INLINE GKO_ATTRIBUTES std::enable_if_t<is_complex_s<T>::value,
bool>
1208template <
typename T>
1224template <
typename T>
1225GKO_INLINE GKO_ATTRIBUTES std::enable_if_t<!is_complex_s<T>::value,
bool>
1228 return std::isnan(value);
1241template <
typename T>
1242GKO_INLINE GKO_ATTRIBUTES std::enable_if_t<is_complex_s<T>::value,
bool>
is_nan(
1245 return std::isnan(value.real()) || std::isnan(value.imag());
1256template <
typename T>
1257GKO_INLINE GKO_ATTRIBUTES
constexpr std::enable_if_t<!is_complex_s<T>::value, T>
1260 return std::numeric_limits<T>::quiet_NaN();
1271template <
typename T>
1272GKO_INLINE GKO_ATTRIBUTES
constexpr std::enable_if_t<is_complex_s<T>::value, T>
The Ginkgo namespace.
Definition abstract_factory.hpp:20
constexpr T one()
Returns the multiplicative identity for T.
Definition math.hpp:775
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:1171
constexpr T pi()
Returns the value of pi.
Definition math.hpp:1097
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:326
constexpr increase_precision< T > round_up(T val)
Increases the precision of the input parameter.
Definition math.hpp:531
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:579
typename detail::next_precision_impl< T >::type next_precision
Obtains the next type in the singly-linked precision list.
Definition math.hpp:462
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:501
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:345
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:1133
constexpr bool is_complex_or_scalar()
Checks if T is a complex/scalar type.
Definition math.hpp:311
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:1226
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:277
constexpr std::enable_if_t<!is_complex_s< T >::value, T > nan()
Returns a quiet NaN of the given type.
Definition math.hpp:1258
constexpr T zero()
Returns the additive identity for T.
Definition math.hpp:747
constexpr bool is_zero(T value)
Returns true if and only if the given value is zero.
Definition math.hpp:812
constexpr auto imag(const T &x)
Returns the imaginary part of the object.
Definition math.hpp:1029
std::uint32_t uint32
32-bit unsigned integral type.
Definition types.hpp:126
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:1112
typename detail::reduce_precision_impl< T >::type reduce_precision
Obtains the next type in the hierarchy with lower precision than T.
Definition math.hpp:479
constexpr reduce_precision< T > round_down(T val)
Reduces the precision of the input parameter.
Definition math.hpp:515
std::int64_t int64
64-bit signed integral type.
Definition types.hpp:109
constexpr int64 ceildiv(int64 num, int64 den)
Performs integer division with rounding up.
Definition math.hpp:613
constexpr bool is_complex()
Checks if T is a complex type.
Definition math.hpp:287
T safe_divide(T a, T b)
Computes the quotient of the given parameters, guarding against division by zero.
Definition math.hpp:1209
constexpr T min(const T &x, const T &y)
Returns the smaller of the arguments.
Definition math.hpp:863
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:1076
constexpr auto squared_norm(const T &x) -> decltype(real(conj(x) *x))
Returns the squared norm of the object.
Definition math.hpp:1057
next_precision< T > previous_precision
Obtains the previous type in the singly-linked precision list.
Definition math.hpp:472
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:301
constexpr size_type byte_size
Number of bits in a byte.
Definition types.hpp:177
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:1151
typename detail::increase_precision_impl< T >::type increase_precision
Obtains the next type in the hierarchy with higher precision than T.
Definition math.hpp:486
remove_complex< T > to_real
to_real is alias of remove_complex
Definition math.hpp:354
constexpr auto conj(const T &x)
Returns the conjugate of an object.
Definition math.hpp:1043
constexpr bool is_nonzero(T value)
Returns true if and only if the given value is not zero.
Definition math.hpp:827
constexpr T max(const T &x, const T &y)
Returns the larger of the arguments.
Definition math.hpp:845
constexpr auto real(const T &x)
Returns the real part of the object.
Definition math.hpp:1013
Access the underlying real type of a complex number.
Definition math.hpp:251
T type
The type.
Definition math.hpp:253
Used to convert objects of type S to objects of type R using static_cast.
Definition math.hpp:591
R operator()(S val)
Converts the object to result type.
Definition math.hpp:598