Ginkgo Generated from branch based on main. Ginkgo version 1.10.0
A numerical linear algebra library targeting many-core architectures
Loading...
Searching...
No Matches
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
23namespace gko {
24
25
26// type manipulations
27
28
34namespace detail {
35
36
40template <typename T>
41struct remove_complex_impl {
42 using type = T;
43};
44
48template <typename T>
49struct remove_complex_impl<std::complex<T>> {
50 using type = T;
51};
52
53
59template <typename T>
60struct to_complex_impl {
61 using type = std::complex<T>;
62};
63
69template <typename T>
70struct to_complex_impl<std::complex<T>> {
71 using type = std::complex<T>;
72};
73
74
75template <typename T>
76struct is_complex_impl : public std::integral_constant<bool, false> {};
77
78template <typename T>
79struct is_complex_impl<std::complex<T>>
80 : public std::integral_constant<bool, true> {};
81
82
83template <typename T>
84struct is_complex_or_scalar_impl : std::is_scalar<T> {};
85
86template <>
87struct is_complex_or_scalar_impl<half> : std::true_type {};
88
89template <>
90struct is_complex_or_scalar_impl<bfloat16> : std::true_type {};
91
92template <typename T>
93struct is_complex_or_scalar_impl<std::complex<T>>
94 : is_complex_or_scalar_impl<T> {};
95
96
104template <template <typename> class converter, typename T>
105struct template_converter {};
106
116template <template <typename> class converter, template <typename...> class T,
117 typename... Rest>
118struct template_converter<converter, T<Rest...>> {
119 using type = T<typename converter<Rest>::type...>;
120};
121
122
123template <typename T, typename = void>
124struct remove_complex_s {};
125
132template <typename T>
133struct 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
144template <typename T>
145struct 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
153template <typename T, typename = void>
154struct to_complex_s {};
155
162template <typename T>
163struct 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
173template <typename T>
174struct 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
188template <typename T>
191 using type = T;
192};
193
199template <typename T>
200struct cpx_real_type<std::complex<T>> {
202 using type = typename std::complex<T>::value_type;
203};
204
205
214template <typename T>
215using is_complex_s = detail::is_complex_impl<T>;
216
224template <typename T>
225GKO_INLINE constexpr bool is_complex()
226{
227 return detail::is_complex_impl<T>::value;
228}
229
230
238template <typename T>
239using is_complex_or_scalar_s = detail::is_complex_or_scalar_impl<T>;
240
248template <typename T>
249GKO_INLINE constexpr bool is_complex_or_scalar()
250{
251 return detail::is_complex_or_scalar_impl<T>::value;
252}
253
254
263template <typename T>
264using remove_complex = typename detail::remove_complex_s<T>::type;
265
266
282template <typename T>
283using to_complex = typename detail::to_complex_s<T>::type;
284
285
291template <typename T>
293
294
295namespace detail {
296
297
298// singly linked list of all our supported precisions
299template <typename T>
300struct next_precision_base_impl {};
301
302template <>
303struct next_precision_base_impl<float> {
304 using type = double;
305};
306
307template <>
308struct next_precision_base_impl<double> {
309 using type = float;
310};
311
312template <typename T>
313struct next_precision_base_impl<std::complex<T>> {
314 using type = std::complex<typename next_precision_base_impl<T>::type>;
315};
316
317
323template <typename T, int step, typename Visited, typename... Rest>
324struct find_precision_list_impl;
325
326template <typename T, int step, typename... Visited, typename U,
327 typename... Rest>
328struct 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
334template <typename T, int step, typename... Visited, typename... Rest>
335struct 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
345template <typename T, int step = 1>
346struct 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
358template <typename T, int step>
359struct find_precision_impl<std::complex<T>, step> {
360 using type = std::complex<typename find_precision_impl<T, step>::type>;
361};
362
363
364template <typename T>
365struct reduce_precision_impl {
366 using type = T;
367};
368
369template <typename T>
370struct reduce_precision_impl<std::complex<T>> {
371 using type = std::complex<typename reduce_precision_impl<T>::type>;
372};
373
374template <>
375struct reduce_precision_impl<double> {
376 using type = float;
377};
378
379// for block jacobi
380template <>
381struct reduce_precision_impl<float> {
382 using type = half;
383};
384
385
386template <typename T>
387struct increase_precision_impl {
388 using type = T;
389};
390
391template <typename T>
392struct increase_precision_impl<std::complex<T>> {
393 using type = std::complex<typename increase_precision_impl<T>::type>;
394};
395
396template <>
397struct increase_precision_impl<float> {
398 using type = double;
399};
400
401// for block jacobi
402template <>
403struct increase_precision_impl<half> {
404 using type = float;
405};
406
407
408template <typename T>
409struct 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
419template <typename T1, typename T2>
420struct highest_precision_impl {
421 using type = decltype(T1{} + T2{});
422};
423
424template <typename T1, typename T2>
425struct highest_precision_impl<std::complex<T1>, std::complex<T2>> {
426 using type = std::complex<typename highest_precision_impl<T1, T2>::type>;
427};
428
429template <typename Head, typename... Tail>
430struct highest_precision_variadic {
431 using type = typename highest_precision_impl<
432 Head, typename highest_precision_variadic<Tail...>::type>::type;
433};
434
435template <typename Head>
436struct highest_precision_variadic<Head> {
437 using type = Head;
438};
439
440
441} // namespace detail
442
443
447template <typename T>
448using next_precision_base = typename detail::next_precision_base_impl<T>::type;
449
450
457template <typename T>
459
460
465template <typename T, int step = 1>
466using next_precision = typename detail::find_precision_impl<T, step>::type;
467
472template <typename T, int step = 1>
473using previous_precision = typename detail::find_precision_impl<T, -step>::type;
474
475
479template <typename T>
480using reduce_precision = typename detail::reduce_precision_impl<T>::type;
481
482
486template <typename T>
487using increase_precision = typename detail::increase_precision_impl<T>::type;
488
489
501template <typename... Ts>
503 typename detail::highest_precision_variadic<Ts...>::type;
504
505
515template <typename T>
516GKO_INLINE constexpr reduce_precision<T> round_down(T val)
517{
518 return static_cast<reduce_precision<T>>(val);
519}
520
521
531template <typename T>
532GKO_INLINE constexpr increase_precision<T> round_up(T val)
533{
534 return static_cast<increase_precision<T>>(val);
535}
536
537
538template <typename FloatType, size_type NumComponents, size_type ComponentId>
539class truncated;
540
541
542namespace detail {
543
544
545template <typename T>
546struct truncate_type_impl {
547 using type = truncated<T, 2, 0>;
548};
549
550template <typename T, size_type Components>
551struct truncate_type_impl<truncated<T, Components, 0>> {
552 using type = truncated<T, 2 * Components, 0>;
553};
554
555template <typename T>
556struct truncate_type_impl<std::complex<T>> {
557 using type = std::complex<typename truncate_type_impl<T>::type>;
558};
559
560
561template <typename T>
562struct type_size_impl {
563 static constexpr auto value = sizeof(T) * byte_size;
564};
565
566template <typename T>
567struct type_size_impl<std::complex<T>> {
568 static constexpr auto value = sizeof(T) * byte_size;
569};
570
571
572} // namespace detail
573
574
579template <typename T, size_type Limit = sizeof(uint16) * byte_size>
581 std::conditional_t<detail::type_size_impl<T>::value >= 2 * Limit,
582 typename detail::truncate_type_impl<T>::type, T>;
583
584
591template <typename S, typename R>
599 GKO_ATTRIBUTES R operator()(S val) { return static_cast<R>(val); }
600};
601
602
603// mathematical functions
604
605
614GKO_INLINE constexpr int64 ceildiv(int64 num, int64 den)
615{
616 return (num + den - 1) / den;
617}
618
619
625template <typename T>
626GKO_INLINE constexpr T zero()
627{
628 return T{};
629}
630
631
641template <typename T>
642GKO_INLINE constexpr T zero(const T&)
643{
644 return zero<T>();
645}
646
647
653template <typename T>
654GKO_INLINE constexpr T one()
655{
656 return T(1);
657}
658
659template <>
660GKO_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
666template <>
667GKO_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
683template <typename T>
684GKO_INLINE constexpr T one(const T&)
685{
686 return one<T>();
687}
688
689
698template <typename T>
699GKO_INLINE constexpr bool is_zero(T value)
700{
701 return value == zero<T>();
702}
703
704
713template <typename T>
714GKO_INLINE constexpr bool is_nonzero(T value)
715{
716 return value != zero<T>();
717}
718
719
731template <typename T>
732GKO_INLINE constexpr T max(const T& x, const T& y)
733{
734 return x >= y ? x : y;
735}
736
737
749template <typename T>
750GKO_INLINE constexpr T min(const T& x, const T& y)
751{
752 return x <= y ? x : y;
753}
754
755
756namespace detail {
757
758
768template <typename Ref, typename Dummy = std::void_t<>>
769struct 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
775template <typename Ref>
776struct 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
787template <typename Ref, typename Dummy = std::void_t<>>
788struct has_arithmetic_type : std::false_type {
789 static_assert(std::is_same<Dummy, void>::value,
790 "Do not modify the Dummy value!");
791};
792
793template <typename Ref>
794struct has_arithmetic_type<Ref, std::void_t<typename Ref::arithmetic_type>>
795 : std::true_type {};
796
797
809template <typename Ref>
810constexpr 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
818template <typename Ref>
819constexpr GKO_ATTRIBUTES std::enable_if_t<!has_to_arithmetic_type<Ref>::value &&
820 has_arithmetic_type<Ref>::value,
821 typename Ref::arithmetic_type>
822to_arithmetic_type(const Ref& ref)
823{
824 return ref;
825}
826
827template <typename Ref>
828constexpr GKO_ATTRIBUTES std::enable_if_t<!has_to_arithmetic_type<Ref>::value &&
829 !has_arithmetic_type<Ref>::value,
830 Ref>
831to_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`)
840template <typename T>
841GKO_ATTRIBUTES GKO_INLINE constexpr std::enable_if_t<!is_complex_s<T>::value, T>
842real_impl(const T& x)
843{
844 return x;
845}
846
847template <typename T>
848GKO_ATTRIBUTES GKO_INLINE constexpr std::enable_if_t<is_complex_s<T>::value,
850real_impl(const T& x)
851{
852 return x.real();
853}
854
855
856template <typename T>
857GKO_ATTRIBUTES GKO_INLINE constexpr std::enable_if_t<!is_complex_s<T>::value, T>
858imag_impl(const T&)
859{
860 return T{};
861}
862
863template <typename T>
864GKO_ATTRIBUTES GKO_INLINE constexpr std::enable_if_t<is_complex_s<T>::value,
866imag_impl(const T& x)
867{
868 return x.imag();
869}
870
871
872template <typename T>
873GKO_ATTRIBUTES GKO_INLINE constexpr std::enable_if_t<!is_complex_s<T>::value, T>
874conj_impl(const T& x)
875{
876 return x;
877}
878
879template <typename T>
880GKO_ATTRIBUTES GKO_INLINE constexpr std::enable_if_t<is_complex_s<T>::value, T>
881conj_impl(const T& x)
882{
883 return T{real_impl(x), -imag_impl(x)};
884}
885
886
887} // namespace detail
888
889
899template <typename T>
900GKO_ATTRIBUTES GKO_INLINE constexpr auto real(const T& x)
901{
902 return detail::real_impl(detail::to_arithmetic_type(x));
903}
904
905
915template <typename T>
916GKO_ATTRIBUTES GKO_INLINE constexpr auto imag(const T& x)
917{
918 return detail::imag_impl(detail::to_arithmetic_type(x));
919}
920
921
929template <typename T>
930GKO_ATTRIBUTES GKO_INLINE constexpr auto conj(const T& x)
931{
932 return detail::conj_impl(detail::to_arithmetic_type(x));
933}
934
935
943template <typename T>
944GKO_INLINE constexpr auto squared_norm(const T& x)
945 -> decltype(real(conj(x) * x))
946{
947 return real(conj(x) * x);
948}
949
950using std::abs;
951
961template <typename T>
962GKO_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
969template <typename T>
970GKO_INLINE constexpr std::enable_if_t<is_complex_s<T>::value, remove_complex<T>>
971abs(const T& x)
972{
973 return sqrt(squared_norm(x));
974}
975
976// increase the priority in function lookup
977GKO_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
983GKO_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
990using std::sqrt;
991
992GKO_INLINE gko::half sqrt(gko::half a)
993{
994 return gko::half(std::sqrt(float(a)));
995}
996
997GKO_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
1003GKO_INLINE gko::bfloat16 sqrt(gko::bfloat16 a)
1004{
1005 return gko::bfloat16(std::sqrt(float(a)));
1006}
1007
1008GKO_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
1020template <typename T>
1021GKO_INLINE constexpr T pi()
1022{
1023 return static_cast<T>(3.1415926535897932384626433);
1024}
1025
1026
1035template <typename T>
1036GKO_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
1056template <typename T>
1057constexpr 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
1074template <typename T>
1075constexpr 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
1093template <typename T>
1094GKO_INLINE GKO_ATTRIBUTES std::enable_if_t<!is_complex_s<T>::value, bool>
1095is_finite(const T& value)
1096{
1097 constexpr T infinity{detail::infinity_impl<T>::value};
1098 return abs(value) < infinity;
1099}
1100
1101
1113template <typename T>
1114GKO_INLINE GKO_ATTRIBUTES std::enable_if_t<is_complex_s<T>::value, bool>
1115is_finite(const T& value)
1116{
1117 return is_finite(value.real()) && is_finite(value.imag());
1118}
1119
1120
1132template <typename T>
1133GKO_INLINE GKO_ATTRIBUTES T safe_divide(T a, T b)
1134{
1135 return b == zero<T>() ? zero<T>() : a / b;
1136}
1137
1138
1148template <typename T>
1149GKO_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")
1152GKO_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
1169template <typename T>
1170GKO_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")
1173GKO_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
1187template <typename T>
1188GKO_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
1201template <typename T>
1202GKO_INLINE constexpr std::enable_if_t<is_complex_s<T>::value, T> nan()
1203{
1205}
1206
1207
1208} // namespace gko
1209
1210
1211#endif // GKO_PUBLIC_CORE_BASE_MATH_HPP_
A class providing basic support for bfloat16 precision floating point types.
Definition bfloat16.hpp:76
A class providing basic support for half precision floating point types.
Definition half.hpp:288
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
The Ginkgo namespace.
Definition abstract_factory.hpp:20
constexpr T one()
Returns the multiplicative identity for T.
Definition math.hpp:654
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
constexpr T pi()
Returns the value of pi.
Definition math.hpp:1021
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
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
constexpr increase_precision< T > round_up(T val)
Increases the precision of the input parameter.
Definition math.hpp:532
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
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
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
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
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
constexpr bool is_complex_or_scalar()
Checks if T is a complex/scalar type.
Definition math.hpp:249
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
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
constexpr std::enable_if_t<!is_complex_s< T >::value, T > nan()
Returns a quiet NaN of the given type.
Definition math.hpp:1188
constexpr T zero()
Returns the additive identity for T.
Definition math.hpp:626
constexpr bool is_zero(T value)
Returns true if and only if the given value is zero.
Definition math.hpp:699
constexpr auto imag(const T &x)
Returns the imaginary part of the object.
Definition math.hpp:916
std::uint32_t uint32
32-bit unsigned integral type.
Definition types.hpp:130
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
next_precision_base< T > previous_precision_base
Obtains the previous type in the singly-linked precision list.
Definition math.hpp:458
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
constexpr reduce_precision< T > round_down(T val)
Reduces the precision of the input parameter.
Definition math.hpp:516
std::int64_t int64
64-bit signed integral type.
Definition types.hpp:113
constexpr int64 ceildiv(int64 num, int64 den)
Performs integer division with rounding up.
Definition math.hpp:614
constexpr bool is_complex()
Checks if T is a complex type.
Definition math.hpp:225
T safe_divide(T a, T b)
Computes the quotient of the given parameters, guarding against division by zero.
Definition math.hpp:1133
constexpr T min(const T &x, const T &y)
Returns the smaller of the arguments.
Definition math.hpp:750
constexpr auto squared_norm(const T &x) -> decltype(real(conj(x) *x))
Returns the squared norm of the object.
Definition math.hpp:944
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
constexpr size_type byte_size
Number of bits in a byte.
Definition types.hpp:178
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
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
remove_complex< T > to_real
to_real is alias of remove_complex
Definition math.hpp:292
constexpr auto conj(const T &x)
Returns the conjugate of an object.
Definition math.hpp:930
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
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
constexpr bool is_nonzero(T value)
Returns true if and only if the given value is not zero.
Definition math.hpp:714
std::uint16_t uint16
16-bit unsigned integral type.
Definition types.hpp:124
constexpr T max(const T &x, const T &y)
Returns the larger of the arguments.
Definition math.hpp:732
constexpr auto real(const T &x)
Returns the real part of the object.
Definition math.hpp:900
STL namespace.
Access the underlying real type of a complex number.
Definition math.hpp:189
T type
The type.
Definition math.hpp:191
Used to convert objects of type S to objects of type R using static_cast.
Definition math.hpp:592
R operator()(S val)
Converts the object to result type.
Definition math.hpp:599