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