Ginkgo  Generated from pipelines/2837190956 branch based on develop. Ginkgo version 2.0.0
A numerical linear algebra library targeting many-core architectures
math.hpp
1 // SPDX-FileCopyrightText: 2017 - 2026 The Ginkgo authors
2 //
3 // SPDX-License-Identifier: BSD-3-Clause
4 
5 #ifndef GKO_PUBLIC_CORE_BASE_MATH_HPP_
6 #define GKO_PUBLIC_CORE_BASE_MATH_HPP_
7 
8 
9 #include <cmath>
10 #include <complex>
11 #include <cstdlib>
12 #include <limits>
13 #include <tuple>
14 #include <type_traits>
15 #include <utility>
16 
17 #include <ginkgo/config.hpp>
18 #include <ginkgo/core/base/half.hpp>
19 #include <ginkgo/core/base/types.hpp>
20 #include <ginkgo/core/base/utils.hpp>
21 
22 
23 namespace gko {
24 
25 
26 // type manipulations
27 
28 
33 namespace detail {
34 
35 
39 template <typename T>
40 struct remove_complex_impl {
41  using type = T;
42 };
43 
47 template <typename T>
48 struct remove_complex_impl<std::complex<T>> {
49  using type = T;
50 };
51 
52 
58 template <typename T>
59 struct to_complex_impl {
60  using type = std::complex<T>;
61 };
62 
68 template <typename T>
69 struct to_complex_impl<std::complex<T>> {
70  using type = std::complex<T>;
71 };
72 
73 
74 template <typename T>
75 struct is_complex_impl : public std::integral_constant<bool, false> {};
76 
77 template <typename T>
78 struct is_complex_impl<std::complex<T>>
79  : public std::integral_constant<bool, true> {};
80 
81 
82 template <typename T>
83 struct is_complex_or_scalar_impl : std::is_scalar<T> {};
84 
85 template <>
86 struct is_complex_or_scalar_impl<half> : std::true_type {};
87 
88 template <>
89 struct is_complex_or_scalar_impl<bfloat16> : std::true_type {};
90 
91 template <typename T>
92 struct is_complex_or_scalar_impl<std::complex<T>>
93  : is_complex_or_scalar_impl<T> {};
94 
95 
103 template <template <typename> class converter, typename T>
104 struct template_converter {};
105 
115 template <template <typename> class converter, template <typename...> class T,
116  typename... Rest>
117 struct template_converter<converter, T<Rest...>> {
118  using type = T<typename converter<Rest>::type...>;
119 };
120 
121 
122 template <typename T, typename = void>
123 struct remove_complex_s {};
124 
131 template <typename T>
132 struct remove_complex_s<T,
133  std::enable_if_t<is_complex_or_scalar_impl<T>::value>> {
134  using type = typename detail::remove_complex_impl<T>::type;
135 };
136 
143 template <typename T>
144 struct remove_complex_s<
145  T, std::enable_if_t<!is_complex_or_scalar_impl<T>::value>> {
146  using type =
147  typename detail::template_converter<detail::remove_complex_impl,
148  T>::type;
149 };
150 
151 
152 template <typename T, typename = void>
153 struct to_complex_s {};
154 
161 template <typename T>
162 struct to_complex_s<T, std::enable_if_t<is_complex_or_scalar_impl<T>::value>> {
163  using type = typename detail::to_complex_impl<T>::type;
164 };
165 
172 template <typename T>
173 struct to_complex_s<T, std::enable_if_t<!is_complex_or_scalar_impl<T>::value>> {
174  using type =
175  typename detail::template_converter<detail::to_complex_impl, T>::type;
176 };
177 
178 
179 } // namespace detail
180 
181 
187 template <typename T>
190  using type = T;
191 };
192 
198 template <typename T>
199 struct cpx_real_type<std::complex<T>> {
201  using type = typename std::complex<T>::value_type;
202 };
203 
204 
213 template <typename T>
214 using is_complex_s = detail::is_complex_impl<T>;
215 
223 template <typename T>
224 GKO_INLINE constexpr bool is_complex()
225 {
226  return detail::is_complex_impl<T>::value;
227 }
228 
229 
237 template <typename T>
238 using is_complex_or_scalar_s = detail::is_complex_or_scalar_impl<T>;
239 
247 template <typename T>
248 GKO_INLINE constexpr bool is_complex_or_scalar()
249 {
250  return detail::is_complex_or_scalar_impl<T>::value;
251 }
252 
253 
262 template <typename T>
263 using remove_complex = typename detail::remove_complex_s<T>::type;
264 
265 
281 template <typename T>
282 using to_complex = typename detail::to_complex_s<T>::type;
283 
284 
290 template <typename T>
292 
293 
294 namespace detail {
295 
296 
297 // singly linked list of all our supported precisions
298 template <typename T>
299 struct next_precision_base_impl {};
300 
301 template <>
302 struct next_precision_base_impl<float> {
303  using type = double;
304 };
305 
306 template <>
307 struct next_precision_base_impl<double> {
308  using type = float;
309 };
310 
311 template <typename T>
312 struct next_precision_base_impl<std::complex<T>> {
313  using type = std::complex<typename next_precision_base_impl<T>::type>;
314 };
315 
316 
322 template <typename T, int step, typename Visited, typename... Rest>
323 struct find_precision_list_impl;
324 
325 template <typename T, int step, typename... Visited, typename U,
326  typename... Rest>
327 struct find_precision_list_impl<T, step, std::tuple<Visited...>, U, Rest...> {
328  using type =
329  typename find_precision_list_impl<T, step, std::tuple<Visited..., U>,
330  Rest...>::type;
331 };
332 
333 template <typename T, int step, typename... Visited, typename... Rest>
334 struct find_precision_list_impl<T, step, std::tuple<Visited...>, T, Rest...> {
335  using tuple = std::tuple<T, Rest..., Visited...>;
336  constexpr static auto tuple_size =
337  static_cast<int>(std::tuple_size_v<tuple>);
338  // It turns the first part into positive when step is negative
339  constexpr static int index = (tuple_size + step % tuple_size) % tuple_size;
340  using type = std::tuple_element_t<index, tuple>;
341 };
342 
343 
344 template <typename T, int step = 1>
345 struct find_precision_impl {
346  using type = typename find_precision_list_impl<T, step, std::tuple<>,
347 #if GINKGO_ENABLE_HALF
348  half,
349 #endif
350 #if GINKGO_ENABLE_BFLOAT16
351  bfloat16,
352 #endif
353  float, double>::type;
354 };
355 
356 
357 template <typename T, int step>
358 struct find_precision_impl<std::complex<T>, step> {
359  using type = std::complex<typename find_precision_impl<T, step>::type>;
360 };
361 
362 
363 template <typename T>
364 struct reduce_precision_impl {
365  using type = T;
366 };
367 
368 template <typename T>
369 struct reduce_precision_impl<std::complex<T>> {
370  using type = std::complex<typename reduce_precision_impl<T>::type>;
371 };
372 
373 template <>
374 struct reduce_precision_impl<double> {
375  using type = float;
376 };
377 
378 // for block jacobi
379 template <>
380 struct reduce_precision_impl<float> {
381  using type = half;
382 };
383 
384 
385 template <typename T>
386 struct increase_precision_impl {
387  using type = T;
388 };
389 
390 template <typename T>
391 struct increase_precision_impl<std::complex<T>> {
392  using type = std::complex<typename increase_precision_impl<T>::type>;
393 };
394 
395 template <>
396 struct increase_precision_impl<float> {
397  using type = double;
398 };
399 
400 // for block jacobi
401 template <>
402 struct increase_precision_impl<half> {
403  using type = float;
404 };
405 
406 
407 template <typename T>
408 struct infinity_impl {
409  // CUDA doesn't allow us to call std::numeric_limits functions
410  // so we need to store the value instead.
411  static constexpr auto value = std::numeric_limits<T>::infinity();
412 };
413 
414 
418 template <typename T1, typename T2>
419 struct highest_precision_impl {
420  using type = decltype(T1{} + T2{});
421 };
422 
423 template <typename T1, typename T2>
424 struct highest_precision_impl<std::complex<T1>, std::complex<T2>> {
425  using type = std::complex<typename highest_precision_impl<T1, T2>::type>;
426 };
427 
428 template <typename Head, typename... Tail>
429 struct highest_precision_variadic {
430  using type = typename highest_precision_impl<
431  Head, typename highest_precision_variadic<Tail...>::type>::type;
432 };
433 
434 template <typename Head>
435 struct highest_precision_variadic<Head> {
436  using type = Head;
437 };
438 
439 
440 } // namespace detail
441 
442 
446 template <typename T>
447 using next_precision_base = typename detail::next_precision_base_impl<T>::type;
448 
449 
456 template <typename T>
458 
459 
464 template <typename T, int step = 1>
465 using next_precision = typename detail::find_precision_impl<T, step>::type;
466 
471 template <typename T, int step = 1>
472 using previous_precision = typename detail::find_precision_impl<T, -step>::type;
473 
474 
478 template <typename T>
479 using reduce_precision = typename detail::reduce_precision_impl<T>::type;
480 
481 
485 template <typename T>
486 using increase_precision = typename detail::increase_precision_impl<T>::type;
487 
488 
500 template <typename... Ts>
501 using highest_precision =
502  typename detail::highest_precision_variadic<Ts...>::type;
503 
504 
514 template <typename T>
515 GKO_INLINE constexpr reduce_precision<T> round_down(T val)
516 {
517  return static_cast<reduce_precision<T>>(val);
518 }
519 
520 
530 template <typename T>
531 GKO_INLINE constexpr increase_precision<T> round_up(T val)
532 {
533  return static_cast<increase_precision<T>>(val);
534 }
535 
536 
537 template <typename FloatType, size_type NumComponents, size_type ComponentId>
538 class truncated;
539 
540 
541 namespace detail {
542 
543 
544 template <typename T>
545 struct truncate_type_impl {
546  using type = truncated<T, 2, 0>;
547 };
548 
549 template <typename T, size_type Components>
550 struct truncate_type_impl<truncated<T, Components, 0>> {
551  using type = truncated<T, 2 * Components, 0>;
552 };
553 
554 template <typename T>
555 struct truncate_type_impl<std::complex<T>> {
556  using type = std::complex<typename truncate_type_impl<T>::type>;
557 };
558 
559 
560 template <typename T>
561 struct type_size_impl {
562  static constexpr auto value = sizeof(T) * byte_size;
563 };
564 
565 template <typename T>
566 struct type_size_impl<std::complex<T>> {
567  static constexpr auto value = sizeof(T) * byte_size;
568 };
569 
570 
571 } // namespace detail
572 
573 
578 template <typename T, size_type Limit = sizeof(uint16) * byte_size>
579 using truncate_type =
580  std::conditional_t<detail::type_size_impl<T>::value >= 2 * Limit,
582 
583 
590 template <typename S, typename R>
598  GKO_ATTRIBUTES R operator()(S val) { return static_cast<R>(val); }
599 };
600 
601 
602 // mathematical functions
603 
604 
613 GKO_INLINE constexpr int64 ceildiv(int64 num, int64 den)
614 {
615  return (num + den - 1) / den;
616 }
617 
618 
624 template <typename T>
625 GKO_INLINE constexpr T zero()
626 {
627  return T{};
628 }
629 
630 
640 template <typename T>
641 GKO_INLINE constexpr T zero(const T&)
642 {
643  return zero<T>();
644 }
645 
646 
652 template <typename T>
653 GKO_INLINE constexpr T one()
654 {
655  return T(1);
656 }
657 
658 template <>
659 GKO_INLINE constexpr half one<half>()
660 {
661  constexpr auto bits = static_cast<uint16>(0b0'01111'0000000000u);
662  return half::create_from_bits(bits);
663 }
664 
665 template <>
666 GKO_INLINE constexpr bfloat16 one<bfloat16>()
667 {
668  constexpr auto bits = static_cast<uint16>(0b0'01111111'0000000u);
669  return bfloat16::create_from_bits(bits);
670 }
671 
672 
682 template <typename T>
683 GKO_INLINE constexpr T one(const T&)
684 {
685  return one<T>();
686 }
687 
688 
697 template <typename T>
698 GKO_INLINE constexpr bool is_zero(T value)
699 {
700  return value == zero<T>();
701 }
702 
703 
712 template <typename T>
713 GKO_INLINE constexpr bool is_nonzero(T value)
714 {
715  return value != zero<T>();
716 }
717 
718 
730 template <typename T>
731 GKO_INLINE constexpr T max(const T& x, const T& y)
732 {
733  return x >= y ? x : y;
734 }
735 
736 
748 template <typename T>
749 GKO_INLINE constexpr T min(const T& x, const T& y)
750 {
751  return x <= y ? x : y;
752 }
753 
754 
755 namespace detail {
756 
757 
767 template <typename Ref, typename Dummy = std::void_t<>>
768 struct has_to_arithmetic_type : std::false_type {
769  static_assert(std::is_same<Dummy, void>::value,
770  "Do not modify the Dummy value!");
771  using type = Ref;
772 };
773 
774 template <typename Ref>
775 struct has_to_arithmetic_type<
776  Ref, std::void_t<decltype(std::declval<Ref>().to_arithmetic_type())>>
777  : std::true_type {
778  using type = decltype(std::declval<Ref>().to_arithmetic_type());
779 };
780 
781 
786 template <typename Ref, typename Dummy = std::void_t<>>
787 struct has_arithmetic_type : std::false_type {
788  static_assert(std::is_same<Dummy, void>::value,
789  "Do not modify the Dummy value!");
790 };
791 
792 template <typename Ref>
793 struct has_arithmetic_type<Ref, std::void_t<typename Ref::arithmetic_type>>
794  : std::true_type {};
795 
796 
808 template <typename Ref>
809 constexpr GKO_ATTRIBUTES
810  std::enable_if_t<has_to_arithmetic_type<Ref>::value,
811  typename has_to_arithmetic_type<Ref>::type>
812  to_arithmetic_type(const Ref& ref)
813 {
814  return ref.to_arithmetic_type();
815 }
816 
817 template <typename Ref>
818 constexpr GKO_ATTRIBUTES std::enable_if_t<!has_to_arithmetic_type<Ref>::value &&
819  has_arithmetic_type<Ref>::value,
820  typename Ref::arithmetic_type>
821 to_arithmetic_type(const Ref& ref)
822 {
823  return ref;
824 }
825 
826 template <typename Ref>
827 constexpr GKO_ATTRIBUTES std::enable_if_t<!has_to_arithmetic_type<Ref>::value &&
828  !has_arithmetic_type<Ref>::value,
829  Ref>
830 to_arithmetic_type(const Ref& ref)
831 {
832  return ref;
833 }
834 
835 
836 // Note: All functions have postfix `impl` so they are not considered for
837 // overload resolution (in case a class / function also is in the namespace
838 // `detail`)
839 template <typename T>
840 GKO_ATTRIBUTES GKO_INLINE constexpr std::enable_if_t<!is_complex_s<T>::value, T>
841 real_impl(const T& x)
842 {
843  return x;
844 }
845 
846 template <typename T>
847 GKO_ATTRIBUTES GKO_INLINE constexpr std::enable_if_t<is_complex_s<T>::value,
848  remove_complex<T>>
849 real_impl(const T& x)
850 {
851  return x.real();
852 }
853 
854 
855 template <typename T>
856 GKO_ATTRIBUTES GKO_INLINE constexpr std::enable_if_t<!is_complex_s<T>::value, T>
857 imag_impl(const T&)
858 {
859  return T{};
860 }
861 
862 template <typename T>
863 GKO_ATTRIBUTES GKO_INLINE constexpr std::enable_if_t<is_complex_s<T>::value,
864  remove_complex<T>>
865 imag_impl(const T& x)
866 {
867  return x.imag();
868 }
869 
870 
871 template <typename T>
872 GKO_ATTRIBUTES GKO_INLINE constexpr std::enable_if_t<!is_complex_s<T>::value, T>
873 conj_impl(const T& x)
874 {
875  return x;
876 }
877 
878 template <typename T>
879 GKO_ATTRIBUTES GKO_INLINE constexpr std::enable_if_t<is_complex_s<T>::value, T>
880 conj_impl(const T& x)
881 {
882  return T{real_impl(x), -imag_impl(x)};
883 }
884 
885 
886 } // namespace detail
887 
888 
898 template <typename T>
899 GKO_ATTRIBUTES GKO_INLINE constexpr auto real(const T& x)
900 {
901  return detail::real_impl(detail::to_arithmetic_type(x));
902 }
903 
904 
914 template <typename T>
915 GKO_ATTRIBUTES GKO_INLINE constexpr auto imag(const T& x)
916 {
917  return detail::imag_impl(detail::to_arithmetic_type(x));
918 }
919 
920 
928 template <typename T>
929 GKO_ATTRIBUTES GKO_INLINE constexpr auto conj(const T& x)
930 {
931  return detail::conj_impl(detail::to_arithmetic_type(x));
932 }
933 
934 
942 template <typename T>
943 GKO_INLINE constexpr auto squared_norm(const T& x)
944  -> decltype(real(conj(x) * x))
945 {
946  return real(conj(x) * x);
947 }
948 
949 using std::abs;
950 
960 template <typename T>
961 GKO_INLINE constexpr std::enable_if_t<!is_complex_s<T>::value, T> abs(
962  const T& x)
963 {
964  return x >= zero<T>() ? x : -x;
965 }
966 
967 
968 template <typename T>
969 GKO_INLINE constexpr std::enable_if_t<is_complex_s<T>::value, remove_complex<T>>
970 abs(const T& x)
971 {
972  return sqrt(squared_norm(x));
973 }
974 
975 // increase the priority in function lookup
976 GKO_INLINE gko::half abs(const std::complex<gko::half>& x)
977 {
978  // Using float abs not sqrt on norm to avoid overflow
979  return static_cast<gko::half>(abs(std::complex<float>(x)));
980 }
981 
982 GKO_INLINE gko::bfloat16 abs(const std::complex<gko::bfloat16>& x)
983 {
984  // Using float abs not sqrt on norm to avoid overflow
985  return static_cast<gko::bfloat16>(abs(std::complex<float>(x)));
986 }
987 
988 
989 using std::sqrt;
990 
991 GKO_INLINE gko::half sqrt(gko::half a)
992 {
993  return gko::half(std::sqrt(float(a)));
994 }
995 
996 GKO_INLINE std::complex<gko::half> sqrt(std::complex<gko::half> a)
997 {
998  return std::complex<gko::half>(sqrt(std::complex<float>(
999  static_cast<float>(a.real()), static_cast<float>(a.imag()))));
1000 }
1001 
1002 GKO_INLINE gko::bfloat16 sqrt(gko::bfloat16 a)
1003 {
1004  return gko::bfloat16(std::sqrt(float(a)));
1005 }
1006 
1007 GKO_INLINE std::complex<gko::bfloat16> sqrt(std::complex<gko::bfloat16> a)
1008 {
1009  return std::complex<gko::bfloat16>(sqrt(std::complex<float>(
1010  static_cast<float>(a.real()), static_cast<float>(a.imag()))));
1011 }
1012 
1013 
1019 template <typename T>
1020 GKO_INLINE constexpr T pi()
1021 {
1022  return static_cast<T>(3.1415926535897932384626433);
1023 }
1024 
1025 
1034 template <typename T>
1035 GKO_INLINE constexpr std::complex<remove_complex<T>> unit_root(int64 n,
1036  int64 k = 1)
1037 {
1038  return std::polar(one<remove_complex<T>>(),
1039  remove_complex<T>{2} * pi<remove_complex<T>>() * k / n);
1040 }
1041 
1042 
1055 template <typename T>
1056 constexpr uint32 get_significant_bit(const T& n, uint32 hint = 0u) noexcept
1057 {
1058  return (T{1} << (hint + 1)) > n ? hint : get_significant_bit(n, hint + 1u);
1059 }
1060 
1061 
1073 template <typename T>
1074 constexpr T get_superior_power(const T& base, const T& limit,
1075  const T& hint = T{1}) noexcept
1076 {
1077  return hint >= limit ? hint : get_superior_power(base, limit, hint * base);
1078 }
1079 
1080 
1092 template <typename T>
1093 GKO_INLINE GKO_ATTRIBUTES std::enable_if_t<!is_complex_s<T>::value, bool>
1094 is_finite(const T& value)
1095 {
1096  constexpr T infinity{detail::infinity_impl<T>::value};
1097  return abs(value) < infinity;
1098 }
1099 
1100 
1112 template <typename T>
1113 GKO_INLINE GKO_ATTRIBUTES std::enable_if_t<is_complex_s<T>::value, bool>
1114 is_finite(const T& value)
1115 {
1116  return is_finite(value.real()) && is_finite(value.imag());
1117 }
1118 
1119 
1131 template <typename T>
1132 GKO_INLINE GKO_ATTRIBUTES T safe_divide(T a, T b)
1133 {
1134  return b == zero<T>() ? zero<T>() : a / b;
1135 }
1136 
1137 
1147 template <typename T>
1148 GKO_DEPRECATED(
1149  "is_nan can't be used safely on the device (MSVC+CUDA), and will thus be "
1150  "removed in a future release, without replacement")
1151 GKO_INLINE GKO_ATTRIBUTES
1152  std::enable_if_t<!is_complex_s<T>::value, bool> is_nan(const T& value)
1153 {
1154  using std::isnan;
1155  return isnan(value);
1156 }
1157 
1158 
1168 template <typename T>
1169 GKO_DEPRECATED(
1170  "is_nan can't be used safely on the device (MSVC+CUDA), and will thus be "
1171  "removed in a future release, without replacement")
1172 GKO_INLINE GKO_ATTRIBUTES std::enable_if_t<is_complex_s<T>::value, bool> is_nan(
1173  const T& value)
1174 {
1175  return is_nan(value.real()) || is_nan(value.imag());
1176 }
1177 
1178 
1186 template <typename T>
1187 GKO_INLINE constexpr std::enable_if_t<!is_complex_s<T>::value, T> nan()
1188 {
1189  return std::numeric_limits<T>::quiet_NaN();
1190 }
1191 
1192 
1200 template <typename T>
1201 GKO_INLINE constexpr std::enable_if_t<is_complex_s<T>::value, T> nan()
1202 {
1203  return T{nan<remove_complex<T>>(), nan<remove_complex<T>>()};
1204 }
1205 
1206 
1207 } // namespace gko
1208 
1209 
1210 #endif // GKO_PUBLIC_CORE_BASE_MATH_HPP_
gko::is_zero
constexpr bool is_zero(T value)
Returns true if and only if the given value is zero.
Definition: math.hpp:698
gko::unit_root
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:1035
gko::default_converter::operator()
R operator()(S val)
Converts the object to result type.
Definition: math.hpp:598
gko::max
constexpr T max(const T &x, const T &y)
Returns the larger of the arguments.
Definition: math.hpp:731
gko::abs
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:961
gko::bfloat16
A class providing basic support for bfloat16 precision floating point types.
Definition: bfloat16.hpp:76
gko::get_significant_bit
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:1056
gko::is_nan
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:1152
gko::is_nonzero
constexpr bool is_nonzero(T value)
Returns true if and only if the given value is not zero.
Definition: math.hpp:713
gko::to_real
remove_complex< T > to_real
to_real is alias of remove_complex
Definition: math.hpp:291
gko::truncated
Definition: half.hpp:23
gko::squared_norm
constexpr auto squared_norm(const T &x) -> decltype(real(conj(x) *x))
Returns the squared norm of the object.
Definition: math.hpp:943
gko::byte_size
constexpr size_type byte_size
Number of bits in a byte.
Definition: types.hpp:189
gko
The Ginkgo namespace.
Definition: abstract_factory.hpp:19
gko::round_down
constexpr reduce_precision< T > round_down(T val)
Reduces the precision of the input parameter.
Definition: math.hpp:515
gko::get_superior_power
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:1074
gko::reduce_precision
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
gko::uint32
std::uint32_t uint32
32-bit unsigned integral type.
Definition: types.hpp:141
gko::is_complex_s
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:214
gko::is_complex
constexpr bool is_complex()
Checks if T is a complex type.
Definition: math.hpp:224
gko::truncate_type
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:581
gko::default_converter
Used to convert objects of type S to objects of type R using static_cast.
Definition: math.hpp:591
gko::previous_precision_base
next_precision_base< T > previous_precision_base
Obtains the previous type in the singly-linked precision list.
Definition: math.hpp:457
gko::pi
constexpr T pi()
Returns the value of pi.
Definition: math.hpp:1020
gko::conj
constexpr auto conj(const T &x)
Returns the conjugate of an object.
Definition: math.hpp:929
gko::cpx_real_type
Access the underlying real type of a complex number.
Definition: math.hpp:188
gko::highest_precision
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:502
gko::is_finite
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:1094
gko::safe_divide
T safe_divide(T a, T b)
Computes the quotient of the given parameters, guarding against division by zero.
Definition: math.hpp:1132
gko::cpx_real_type::type
T type
The type.
Definition: math.hpp:190
gko::next_precision_base
typename detail::next_precision_base_impl< T >::type next_precision_base
Obtains the next type in the singly-linked precision list.
Definition: math.hpp:447
gko::next_precision
typename detail::find_precision_impl< T, step >::type next_precision
Obtains the next move type of T in the singly-linked precision corresponding bfloat16/half.
Definition: math.hpp:465
gko::half
A class providing basic support for half precision floating point types.
Definition: half.hpp:288
gko::previous_precision
typename detail::find_precision_impl< T, -step >::type previous_precision
Obtains the previous move type of T in the singly-linked precision corresponding bfloat16/half.
Definition: math.hpp:472
gko::is_complex_or_scalar
constexpr bool is_complex_or_scalar()
Checks if T is a complex/scalar type.
Definition: math.hpp:248
gko::int64
std::int64_t int64
64-bit signed integral type.
Definition: types.hpp:124
gko::is_complex_or_scalar_s
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:238
gko::min
constexpr T min(const T &x, const T &y)
Returns the smaller of the arguments.
Definition: math.hpp:749
gko::ceildiv
constexpr int64 ceildiv(int64 num, int64 den)
Performs integer division with rounding up.
Definition: math.hpp:613
gko::increase_precision
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
gko::xstd::void_t
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:46
gko::remove_complex
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:263
gko::round_up
constexpr increase_precision< T > round_up(T val)
Increases the precision of the input parameter.
Definition: math.hpp:531
gko::real
constexpr auto real(const T &x)
Returns the real part of the object.
Definition: math.hpp:899
gko::zero
constexpr T zero()
Returns the additive identity for T.
Definition: math.hpp:625
gko::one
constexpr T one()
Returns the multiplicative identity for T.
Definition: math.hpp:653
gko::to_complex
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:282
gko::nan
constexpr std::enable_if_t<!is_complex_s< T >::value, T > nan()
Returns a quiet NaN of the given type.
Definition: math.hpp:1187
gko::imag
constexpr auto imag(const T &x)
Returns the imaginary part of the object.
Definition: math.hpp:915