Ginkgo  Generated from pipelines/1554403166 branch based on develop. Ginkgo version 1.9.0
A numerical linear algebra library targeting many-core architectures
math.hpp
1 // SPDX-FileCopyrightText: 2017 - 2024 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 <type_traits>
14 #include <utility>
15 
16 #include <ginkgo/config.hpp>
17 #include <ginkgo/core/base/types.hpp>
18 #include <ginkgo/core/base/utils.hpp>
19 
20 
21 namespace gko {
22 
23 
24 // HIP should not see std::abs or std::sqrt, we want the custom implementation.
25 // Hence, provide the using declaration only for some cases
26 namespace kernels {
27 namespace reference {
28 
29 
30 using std::abs;
31 
32 
33 using std::sqrt;
34 
35 
36 } // namespace reference
37 } // namespace kernels
38 
39 
40 namespace kernels {
41 namespace omp {
42 
43 
44 using std::abs;
45 
46 
47 using std::sqrt;
48 
49 
50 } // namespace omp
51 } // namespace kernels
52 
53 
54 namespace kernels {
55 namespace cuda {
56 
57 
58 using std::abs;
59 
60 
61 using std::sqrt;
62 
63 
64 } // namespace cuda
65 } // namespace kernels
66 
67 
68 namespace kernels {
69 namespace dpcpp {
70 
71 
72 using std::abs;
73 
74 
75 using std::sqrt;
76 
77 
78 } // namespace dpcpp
79 } // namespace kernels
80 
81 
82 namespace test {
83 
84 
85 using std::abs;
86 
87 
88 using std::sqrt;
89 
90 
91 } // namespace test
92 
93 
94 // type manipulations
95 
96 
102 namespace detail {
103 
104 
108 template <typename T>
109 struct remove_complex_impl {
110  using type = T;
111 };
112 
116 template <typename T>
117 struct remove_complex_impl<std::complex<T>> {
118  using type = T;
119 };
120 
121 
127 template <typename T>
128 struct to_complex_impl {
129  using type = std::complex<T>;
130 };
131 
137 template <typename T>
138 struct to_complex_impl<std::complex<T>> {
139  using type = std::complex<T>;
140 };
141 
142 
143 template <typename T>
144 struct is_complex_impl : public std::integral_constant<bool, false> {};
145 
146 template <typename T>
147 struct is_complex_impl<std::complex<T>>
148  : public std::integral_constant<bool, true> {};
149 
150 
151 template <typename T>
152 struct is_complex_or_scalar_impl : std::is_scalar<T> {};
153 
154 template <typename T>
155 struct is_complex_or_scalar_impl<std::complex<T>> : std::is_scalar<T> {};
156 
157 
165 template <template <typename> class converter, typename T>
166 struct template_converter {};
167 
177 template <template <typename> class converter, template <typename...> class T,
178  typename... Rest>
179 struct template_converter<converter, T<Rest...>> {
180  using type = T<typename converter<Rest>::type...>;
181 };
182 
183 
184 template <typename T, typename = void>
185 struct remove_complex_s {};
186 
193 template <typename T>
194 struct remove_complex_s<T,
195  std::enable_if_t<is_complex_or_scalar_impl<T>::value>> {
196  using type = typename detail::remove_complex_impl<T>::type;
197 };
198 
205 template <typename T>
206 struct remove_complex_s<
207  T, std::enable_if_t<!is_complex_or_scalar_impl<T>::value>> {
208  using type =
209  typename detail::template_converter<detail::remove_complex_impl,
210  T>::type;
211 };
212 
213 
214 template <typename T, typename = void>
215 struct to_complex_s {};
216 
223 template <typename T>
224 struct to_complex_s<T, std::enable_if_t<is_complex_or_scalar_impl<T>::value>> {
225  using type = typename detail::to_complex_impl<T>::type;
226 };
227 
234 template <typename T>
235 struct to_complex_s<T, std::enable_if_t<!is_complex_or_scalar_impl<T>::value>> {
236  using type =
237  typename detail::template_converter<detail::to_complex_impl, T>::type;
238 };
239 
240 
241 } // namespace detail
242 
243 
249 template <typename T>
252  using type = T;
253 };
254 
260 template <typename T>
261 struct cpx_real_type<std::complex<T>> {
263  using type = typename std::complex<T>::value_type;
264 };
265 
266 
275 template <typename T>
276 using is_complex_s = detail::is_complex_impl<T>;
277 
285 template <typename T>
286 GKO_INLINE constexpr bool is_complex()
287 {
288  return detail::is_complex_impl<T>::value;
289 }
290 
291 
299 template <typename T>
300 using is_complex_or_scalar_s = detail::is_complex_or_scalar_impl<T>;
301 
309 template <typename T>
310 GKO_INLINE constexpr bool is_complex_or_scalar()
311 {
312  return detail::is_complex_or_scalar_impl<T>::value;
313 }
314 
315 
324 template <typename T>
325 using remove_complex = typename detail::remove_complex_s<T>::type;
326 
327 
343 template <typename T>
344 using to_complex = typename detail::to_complex_s<T>::type;
345 
346 
352 template <typename T>
354 
355 
356 namespace detail {
357 
358 
359 // singly linked list of all our supported precisions
360 template <typename T>
361 struct next_precision_impl {};
362 
363 template <>
364 struct next_precision_impl<float> {
365  using type = double;
366 };
367 
368 template <>
369 struct next_precision_impl<double> {
370  using type = float;
371 };
372 
373 template <typename T>
374 struct next_precision_impl<std::complex<T>> {
375  using type = std::complex<typename next_precision_impl<T>::type>;
376 };
377 
378 
379 template <typename T>
380 struct reduce_precision_impl {
381  using type = T;
382 };
383 
384 template <typename T>
385 struct reduce_precision_impl<std::complex<T>> {
386  using type = std::complex<typename reduce_precision_impl<T>::type>;
387 };
388 
389 template <>
390 struct reduce_precision_impl<double> {
391  using type = float;
392 };
393 
394 template <>
395 struct reduce_precision_impl<float> {
396  using type = half;
397 };
398 
399 
400 template <typename T>
401 struct increase_precision_impl {
402  using type = T;
403 };
404 
405 template <typename T>
406 struct increase_precision_impl<std::complex<T>> {
407  using type = std::complex<typename increase_precision_impl<T>::type>;
408 };
409 
410 template <>
411 struct increase_precision_impl<float> {
412  using type = double;
413 };
414 
415 template <>
416 struct increase_precision_impl<half> {
417  using type = float;
418 };
419 
420 
421 template <typename T>
422 struct infinity_impl {
423  // CUDA doesn't allow us to call std::numeric_limits functions
424  // so we need to store the value instead.
425  static constexpr auto value = std::numeric_limits<T>::infinity();
426 };
427 
428 
432 template <typename T1, typename T2>
433 struct highest_precision_impl {
434  using type = decltype(T1{} + T2{});
435 };
436 
437 template <typename T1, typename T2>
438 struct highest_precision_impl<std::complex<T1>, std::complex<T2>> {
439  using type = std::complex<typename highest_precision_impl<T1, T2>::type>;
440 };
441 
442 template <typename Head, typename... Tail>
443 struct highest_precision_variadic {
444  using type = typename highest_precision_impl<
445  Head, typename highest_precision_variadic<Tail...>::type>::type;
446 };
447 
448 template <typename Head>
449 struct highest_precision_variadic<Head> {
450  using type = Head;
451 };
452 
453 
454 } // namespace detail
455 
456 
460 template <typename T>
461 using next_precision = typename detail::next_precision_impl<T>::type;
462 
463 
470 template <typename T>
472 
473 
477 template <typename T>
478 using reduce_precision = typename detail::reduce_precision_impl<T>::type;
479 
480 
484 template <typename T>
485 using increase_precision = typename detail::increase_precision_impl<T>::type;
486 
487 
499 template <typename... Ts>
500 using highest_precision =
501  typename detail::highest_precision_variadic<Ts...>::type;
502 
503 
513 template <typename T>
514 GKO_INLINE constexpr reduce_precision<T> round_down(T val)
515 {
516  return static_cast<reduce_precision<T>>(val);
517 }
518 
519 
529 template <typename T>
530 GKO_INLINE constexpr increase_precision<T> round_up(T val)
531 {
532  return static_cast<increase_precision<T>>(val);
533 }
534 
535 
536 template <typename FloatType, size_type NumComponents, size_type ComponentId>
537 class truncated;
538 
539 
540 namespace detail {
541 
542 
543 template <typename T>
544 struct truncate_type_impl {
545  using type = truncated<T, 2, 0>;
546 };
547 
548 template <typename T, size_type Components>
549 struct truncate_type_impl<truncated<T, Components, 0>> {
550  using type = truncated<T, 2 * Components, 0>;
551 };
552 
553 template <typename T>
554 struct truncate_type_impl<std::complex<T>> {
555  using type = std::complex<typename truncate_type_impl<T>::type>;
556 };
557 
558 
559 template <typename T>
560 struct type_size_impl {
561  static constexpr auto value = sizeof(T) * byte_size;
562 };
563 
564 template <typename T>
565 struct type_size_impl<std::complex<T>> {
566  static constexpr auto value = sizeof(T) * byte_size;
567 };
568 
569 
570 } // namespace detail
571 
572 
577 template <typename T, size_type Limit = sizeof(uint16) * byte_size>
578 using truncate_type =
579  std::conditional_t<detail::type_size_impl<T>::value >= 2 * Limit,
581 
582 
589 template <typename S, typename R>
597  GKO_ATTRIBUTES R operator()(S val) { return static_cast<R>(val); }
598 };
599 
600 
601 // mathematical functions
602 
603 
612 GKO_INLINE constexpr int64 ceildiv(int64 num, int64 den)
613 {
614  return (num + den - 1) / den;
615 }
616 
617 
623 template <typename T>
624 GKO_INLINE constexpr T zero()
625 {
626  return T{};
627 }
628 
629 
639 template <typename T>
640 GKO_INLINE constexpr T zero(const T&)
641 {
642  return zero<T>();
643 }
644 
645 
651 template <typename T>
652 GKO_INLINE constexpr T one()
653 {
654  return T(1);
655 }
656 
657 
667 template <typename T>
668 GKO_INLINE constexpr T one(const T&)
669 {
670  return one<T>();
671 }
672 
673 
682 template <typename T>
683 GKO_INLINE constexpr bool is_zero(T value)
684 {
685  return value == zero<T>();
686 }
687 
688 
697 template <typename T>
698 GKO_INLINE constexpr bool is_nonzero(T value)
699 {
700  return value != zero<T>();
701 }
702 
703 
715 template <typename T>
716 GKO_INLINE constexpr T max(const T& x, const T& y)
717 {
718  return x >= y ? x : y;
719 }
720 
721 
733 template <typename T>
734 GKO_INLINE constexpr T min(const T& x, const T& y)
735 {
736  return x <= y ? x : y;
737 }
738 
739 
740 namespace detail {
741 
742 
752 template <typename Ref, typename Dummy = std::void_t<>>
753 struct has_to_arithmetic_type : std::false_type {
754  static_assert(std::is_same<Dummy, void>::value,
755  "Do not modify the Dummy value!");
756  using type = Ref;
757 };
758 
759 template <typename Ref>
760 struct has_to_arithmetic_type<
761  Ref, std::void_t<decltype(std::declval<Ref>().to_arithmetic_type())>>
762  : std::true_type {
763  using type = decltype(std::declval<Ref>().to_arithmetic_type());
764 };
765 
766 
771 template <typename Ref, typename Dummy = std::void_t<>>
772 struct has_arithmetic_type : std::false_type {
773  static_assert(std::is_same<Dummy, void>::value,
774  "Do not modify the Dummy value!");
775 };
776 
777 template <typename Ref>
778 struct has_arithmetic_type<Ref, std::void_t<typename Ref::arithmetic_type>>
779  : std::true_type {};
780 
781 
793 template <typename Ref>
794 constexpr GKO_ATTRIBUTES
795  std::enable_if_t<has_to_arithmetic_type<Ref>::value,
796  typename has_to_arithmetic_type<Ref>::type>
797  to_arithmetic_type(const Ref& ref)
798 {
799  return ref.to_arithmetic_type();
800 }
801 
802 template <typename Ref>
803 constexpr GKO_ATTRIBUTES std::enable_if_t<!has_to_arithmetic_type<Ref>::value &&
804  has_arithmetic_type<Ref>::value,
805  typename Ref::arithmetic_type>
806 to_arithmetic_type(const Ref& ref)
807 {
808  return ref;
809 }
810 
811 template <typename Ref>
812 constexpr GKO_ATTRIBUTES std::enable_if_t<!has_to_arithmetic_type<Ref>::value &&
813  !has_arithmetic_type<Ref>::value,
814  Ref>
815 to_arithmetic_type(const Ref& ref)
816 {
817  return ref;
818 }
819 
820 
821 // Note: All functions have postfix `impl` so they are not considered for
822 // overload resolution (in case a class / function also is in the namespace
823 // `detail`)
824 template <typename T>
825 GKO_ATTRIBUTES GKO_INLINE constexpr std::enable_if_t<!is_complex_s<T>::value, T>
826 real_impl(const T& x)
827 {
828  return x;
829 }
830 
831 template <typename T>
832 GKO_ATTRIBUTES GKO_INLINE constexpr std::enable_if_t<is_complex_s<T>::value,
833  remove_complex<T>>
834 real_impl(const T& x)
835 {
836  return x.real();
837 }
838 
839 
840 template <typename T>
841 GKO_ATTRIBUTES GKO_INLINE constexpr std::enable_if_t<!is_complex_s<T>::value, T>
842 imag_impl(const T&)
843 {
844  return T{};
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 imag_impl(const T& x)
851 {
852  return x.imag();
853 }
854 
855 
856 template <typename T>
857 GKO_ATTRIBUTES GKO_INLINE constexpr std::enable_if_t<!is_complex_s<T>::value, T>
858 conj_impl(const T& x)
859 {
860  return x;
861 }
862 
863 template <typename T>
864 GKO_ATTRIBUTES GKO_INLINE constexpr std::enable_if_t<is_complex_s<T>::value, T>
865 conj_impl(const T& x)
866 {
867  return T{real_impl(x), -imag_impl(x)};
868 }
869 
870 
871 } // namespace detail
872 
873 
883 template <typename T>
884 GKO_ATTRIBUTES GKO_INLINE constexpr auto real(const T& x)
885 {
886  return detail::real_impl(detail::to_arithmetic_type(x));
887 }
888 
889 
899 template <typename T>
900 GKO_ATTRIBUTES GKO_INLINE constexpr auto imag(const T& x)
901 {
902  return detail::imag_impl(detail::to_arithmetic_type(x));
903 }
904 
905 
913 template <typename T>
914 GKO_ATTRIBUTES GKO_INLINE constexpr auto conj(const T& x)
915 {
916  return detail::conj_impl(detail::to_arithmetic_type(x));
917 }
918 
919 
927 template <typename T>
928 GKO_INLINE constexpr auto squared_norm(const T& x)
929  -> decltype(real(conj(x) * x))
930 {
931  return real(conj(x) * x);
932 }
933 
934 
944 template <typename T>
945 GKO_INLINE constexpr std::enable_if_t<!is_complex_s<T>::value, T> abs(
946  const T& x)
947 {
948  return x >= zero<T>() ? x : -x;
949 }
950 
951 
952 template <typename T>
953 GKO_INLINE constexpr std::enable_if_t<is_complex_s<T>::value, remove_complex<T>>
954 abs(const T& x)
955 {
956  return sqrt(squared_norm(x));
957 }
958 
959 
965 template <typename T>
966 GKO_INLINE constexpr T pi()
967 {
968  return static_cast<T>(3.1415926535897932384626433);
969 }
970 
971 
980 template <typename T>
981 GKO_INLINE constexpr std::complex<remove_complex<T>> unit_root(int64 n,
982  int64 k = 1)
983 {
984  return std::polar(one<remove_complex<T>>(),
985  remove_complex<T>{2} * pi<remove_complex<T>>() * k / n);
986 }
987 
988 
1001 template <typename T>
1002 constexpr uint32 get_significant_bit(const T& n, uint32 hint = 0u) noexcept
1003 {
1004  return (T{1} << (hint + 1)) > n ? hint : get_significant_bit(n, hint + 1u);
1005 }
1006 
1007 
1019 template <typename T>
1020 constexpr T get_superior_power(const T& base, const T& limit,
1021  const T& hint = T{1}) noexcept
1022 {
1023  return hint >= limit ? hint : get_superior_power(base, limit, hint * base);
1024 }
1025 
1026 
1038 template <typename T>
1039 GKO_INLINE GKO_ATTRIBUTES std::enable_if_t<!is_complex_s<T>::value, bool>
1040 is_finite(const T& value)
1041 {
1042  constexpr T infinity{detail::infinity_impl<T>::value};
1043  return abs(value) < infinity;
1044 }
1045 
1046 
1058 template <typename T>
1059 GKO_INLINE GKO_ATTRIBUTES std::enable_if_t<is_complex_s<T>::value, bool>
1060 is_finite(const T& value)
1061 {
1062  return is_finite(value.real()) && is_finite(value.imag());
1063 }
1064 
1065 
1077 template <typename T>
1078 GKO_INLINE GKO_ATTRIBUTES T safe_divide(T a, T b)
1079 {
1080  return b == zero<T>() ? zero<T>() : a / b;
1081 }
1082 
1083 
1093 template <typename T>
1094 GKO_DEPRECATED(
1095  "is_nan can't be used safely on the device (MSVC+CUDA), and will thus be "
1096  "removed in a future release, without replacement")
1097 GKO_INLINE GKO_ATTRIBUTES
1098  std::enable_if_t<!is_complex_s<T>::value, bool> is_nan(const T& value)
1099 {
1100  using std::isnan;
1101  return isnan(value);
1102 }
1103 
1104 
1114 template <typename T>
1115 GKO_DEPRECATED(
1116  "is_nan can't be used safely on the device (MSVC+CUDA), and will thus be "
1117  "removed in a future release, without replacement")
1118 GKO_INLINE GKO_ATTRIBUTES std::enable_if_t<is_complex_s<T>::value, bool> is_nan(
1119  const T& value)
1120 {
1121  return is_nan(value.real()) || is_nan(value.imag());
1122 }
1123 
1124 
1132 template <typename T>
1133 GKO_INLINE constexpr std::enable_if_t<!is_complex_s<T>::value, T> nan()
1134 {
1135  return std::numeric_limits<T>::quiet_NaN();
1136 }
1137 
1138 
1146 template <typename T>
1147 GKO_INLINE constexpr std::enable_if_t<is_complex_s<T>::value, T> nan()
1148 {
1149  return T{nan<remove_complex<T>>(), nan<remove_complex<T>>()};
1150 }
1151 
1152 
1153 } // namespace gko
1154 
1155 
1156 #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:683
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:981
gko::default_converter::operator()
R operator()(S val)
Converts the object to result type.
Definition: math.hpp:597
gko::max
constexpr T max(const T &x, const T &y)
Returns the larger of the arguments.
Definition: math.hpp:716
gko::previous_precision
next_precision< T > previous_precision
Obtains the previous type in the singly-linked precision list.
Definition: math.hpp:471
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:945
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:1002
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:1098
gko::is_nonzero
constexpr bool is_nonzero(T value)
Returns true if and only if the given value is not zero.
Definition: math.hpp:698
gko::to_real
remove_complex< T > to_real
to_real is alias of remove_complex
Definition: math.hpp:353
gko::truncated
Definition: math.hpp:537
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:928
gko::byte_size
constexpr size_type byte_size
Number of bits in a byte.
Definition: types.hpp:177
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:514
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:1020
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:478
gko::uint32
std::uint32_t uint32
32-bit unsigned integral type.
Definition: types.hpp:126
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:276
gko::is_complex
constexpr bool is_complex()
Checks if T is a complex type.
Definition: math.hpp:286
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:580
gko::default_converter
Used to convert objects of type S to objects of type R using static_cast.
Definition: math.hpp:590
gko::next_precision
typename detail::next_precision_impl< T >::type next_precision
Obtains the next type in the singly-linked precision list.
Definition: math.hpp:461
gko::pi
constexpr T pi()
Returns the value of pi.
Definition: math.hpp:966
gko::conj
constexpr auto conj(const T &x)
Returns the conjugate of an object.
Definition: math.hpp:914
gko::cpx_real_type
Access the underlying real type of a complex number.
Definition: math.hpp:250
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:501
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:1040
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:1078
gko::cpx_real_type::type
T type
The type.
Definition: math.hpp:252
gko::is_complex_or_scalar
constexpr bool is_complex_or_scalar()
Checks if T is a complex/scalar type.
Definition: math.hpp:310
gko::int64
std::int64_t int64
64-bit signed integral type.
Definition: types.hpp:109
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:300
gko::min
constexpr T min(const T &x, const T &y)
Returns the smaller of the arguments.
Definition: math.hpp:734
gko::ceildiv
constexpr int64 ceildiv(int64 num, int64 den)
Performs integer division with rounding up.
Definition: math.hpp:612
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:485
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:325
gko::round_up
constexpr increase_precision< T > round_up(T val)
Increases the precision of the input parameter.
Definition: math.hpp:530
gko::real
constexpr auto real(const T &x)
Returns the real part of the object.
Definition: math.hpp:884
gko::zero
constexpr T zero()
Returns the additive identity for T.
Definition: math.hpp:624
gko::one
constexpr T one()
Returns the multiplicative identity for T.
Definition: math.hpp:652
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:344
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:1133
gko::imag
constexpr auto imag(const T &x)
Returns the imaginary part of the object.
Definition: math.hpp:900