Ginkgo Generated from branch based on master. Ginkgo version 1.7.0
A numerical linear algebra library targeting many-core architectures
Loading...
Searching...
No Matches
math.hpp
1/*******************************<GINKGO LICENSE>******************************
2Copyright (c) 2017-2023, the Ginkgo authors
3All rights reserved.
4
5Redistribution and use in source and binary forms, with or without
6modification, are permitted provided that the following conditions
7are met:
8
91. Redistributions of source code must retain the above copyright
10notice, this list of conditions and the following disclaimer.
11
122. Redistributions in binary form must reproduce the above copyright
13notice, this list of conditions and the following disclaimer in the
14documentation and/or other materials provided with the distribution.
15
163. Neither the name of the copyright holder nor the names of its
17contributors may be used to endorse or promote products derived from
18this software without specific prior written permission.
19
20THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
21IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31******************************<GINKGO LICENSE>*******************************/
32
33#ifndef GKO_PUBLIC_CORE_BASE_MATH_HPP_
34#define GKO_PUBLIC_CORE_BASE_MATH_HPP_
35
36
37#include <cmath>
38#include <complex>
39#include <cstdlib>
40#include <limits>
41#include <type_traits>
42#include <utility>
43
44
45#include <ginkgo/config.hpp>
46#include <ginkgo/core/base/types.hpp>
47#include <ginkgo/core/base/utils.hpp>
48
49
50namespace gko {
51
52
53// HIP should not see std::abs or std::sqrt, we want the custom implementation.
54// Hence, provide the using declaration only for some cases
55namespace kernels {
56namespace reference {
57
58
59using std::abs;
60
61
62using std::sqrt;
63
64
65} // namespace reference
66} // namespace kernels
67
68
69namespace kernels {
70namespace omp {
71
72
73using std::abs;
74
75
76using std::sqrt;
77
78
79} // namespace omp
80} // namespace kernels
81
82
83namespace kernels {
84namespace cuda {
85
86
87using std::abs;
88
89
90using std::sqrt;
91
92
93} // namespace cuda
94} // namespace kernels
95
96
97namespace kernels {
98namespace dpcpp {
99
100
101using std::abs;
102
103
104using std::sqrt;
105
106
107} // namespace dpcpp
108} // namespace kernels
109
110
111namespace test {
112
113
114using std::abs;
115
116
117using std::sqrt;
118
119
120} // namespace test
121
122
123// type manipulations
124
125
131namespace detail {
132
133
137template <typename T>
138struct remove_complex_impl {
139 using type = T;
140};
141
145template <typename T>
146struct remove_complex_impl<std::complex<T>> {
147 using type = T;
148};
149
150
156template <typename T>
157struct to_complex_impl {
158 using type = std::complex<T>;
159};
160
166template <typename T>
167struct to_complex_impl<std::complex<T>> {
168 using type = std::complex<T>;
169};
170
171
172template <typename T>
173struct is_complex_impl : public std::integral_constant<bool, false> {};
174
175template <typename T>
176struct is_complex_impl<std::complex<T>>
177 : public std::integral_constant<bool, true> {};
178
179
180template <typename T>
181struct is_complex_or_scalar_impl : std::is_scalar<T> {};
182
183template <typename T>
184struct is_complex_or_scalar_impl<std::complex<T>> : std::is_scalar<T> {};
185
186
194template <template <typename> class converter, typename T>
195struct template_converter {};
196
206template <template <typename> class converter, template <typename...> class T,
207 typename... Rest>
208struct template_converter<converter, T<Rest...>> {
209 using type = T<typename converter<Rest>::type...>;
210};
211
212
213template <typename T, typename = void>
214struct remove_complex_s {};
215
222template <typename T>
223struct remove_complex_s<T,
224 std::enable_if_t<is_complex_or_scalar_impl<T>::value>> {
225 using type = typename detail::remove_complex_impl<T>::type;
226};
227
234template <typename T>
235struct remove_complex_s<
236 T, std::enable_if_t<!is_complex_or_scalar_impl<T>::value>> {
237 using type =
238 typename detail::template_converter<detail::remove_complex_impl,
239 T>::type;
240};
241
242
243template <typename T, typename = void>
244struct to_complex_s {};
245
252template <typename T>
253struct to_complex_s<T, std::enable_if_t<is_complex_or_scalar_impl<T>::value>> {
254 using type = typename detail::to_complex_impl<T>::type;
255};
256
263template <typename T>
264struct to_complex_s<T, std::enable_if_t<!is_complex_or_scalar_impl<T>::value>> {
265 using type =
266 typename detail::template_converter<detail::to_complex_impl, T>::type;
267};
268
269
270} // namespace detail
271
272
278template <typename T>
281 using type = T;
282};
283
289template <typename T>
290struct cpx_real_type<std::complex<T>> {
292 using type = typename std::complex<T>::value_type;
293};
294
295
304template <typename T>
305using is_complex_s = detail::is_complex_impl<T>;
306
314template <typename T>
315GKO_INLINE GKO_ATTRIBUTES constexpr bool is_complex()
316{
317 return detail::is_complex_impl<T>::value;
318}
319
320
328template <typename T>
329using is_complex_or_scalar_s = detail::is_complex_or_scalar_impl<T>;
330
338template <typename T>
339GKO_INLINE GKO_ATTRIBUTES constexpr bool is_complex_or_scalar()
340{
341 return detail::is_complex_or_scalar_impl<T>::value;
342}
343
344
353template <typename T>
354using remove_complex = typename detail::remove_complex_s<T>::type;
355
356
372template <typename T>
373using to_complex = typename detail::to_complex_s<T>::type;
374
375
381template <typename T>
383
384
385namespace detail {
386
387
388// singly linked list of all our supported precisions
389template <typename T>
390struct next_precision_impl {};
391
392template <>
393struct next_precision_impl<float> {
394 using type = double;
395};
396
397template <>
398struct next_precision_impl<double> {
399 using type = float;
400};
401
402template <typename T>
403struct next_precision_impl<std::complex<T>> {
404 using type = std::complex<typename next_precision_impl<T>::type>;
405};
406
407
408template <typename T>
409struct reduce_precision_impl {
410 using type = T;
411};
412
413template <typename T>
414struct reduce_precision_impl<std::complex<T>> {
415 using type = std::complex<typename reduce_precision_impl<T>::type>;
416};
417
418template <>
419struct reduce_precision_impl<double> {
420 using type = float;
421};
422
423template <>
424struct reduce_precision_impl<float> {
425 using type = half;
426};
427
428
429template <typename T>
430struct increase_precision_impl {
431 using type = T;
432};
433
434template <typename T>
435struct increase_precision_impl<std::complex<T>> {
436 using type = std::complex<typename increase_precision_impl<T>::type>;
437};
438
439template <>
440struct increase_precision_impl<float> {
441 using type = double;
442};
443
444template <>
445struct increase_precision_impl<half> {
446 using type = float;
447};
448
449
450template <typename T>
451struct infinity_impl {
452 // CUDA doesn't allow us to call std::numeric_limits functions
453 // so we need to store the value instead.
454 static constexpr auto value = std::numeric_limits<T>::infinity();
455};
456
457
461template <typename T1, typename T2>
462struct highest_precision_impl {
463 using type = decltype(T1{} + T2{});
464};
465
466template <typename T1, typename T2>
467struct highest_precision_impl<std::complex<T1>, std::complex<T2>> {
468 using type = std::complex<typename highest_precision_impl<T1, T2>::type>;
469};
470
471template <typename Head, typename... Tail>
472struct highest_precision_variadic {
473 using type = typename highest_precision_impl<
474 Head, typename highest_precision_variadic<Tail...>::type>::type;
475};
476
477template <typename Head>
478struct highest_precision_variadic<Head> {
479 using type = Head;
480};
481
482
483} // namespace detail
484
485
489template <typename T>
490using next_precision = typename detail::next_precision_impl<T>::type;
491
492
499template <typename T>
501
502
506template <typename T>
507using reduce_precision = typename detail::reduce_precision_impl<T>::type;
508
509
513template <typename T>
514using increase_precision = typename detail::increase_precision_impl<T>::type;
515
516
528template <typename... Ts>
530 typename detail::highest_precision_variadic<Ts...>::type;
531
532
542template <typename T>
543GKO_INLINE GKO_ATTRIBUTES constexpr reduce_precision<T> round_down(T val)
544{
545 return static_cast<reduce_precision<T>>(val);
546}
547
548
558template <typename T>
559GKO_INLINE GKO_ATTRIBUTES constexpr increase_precision<T> round_up(T val)
560{
561 return static_cast<increase_precision<T>>(val);
562}
563
564
565template <typename FloatType, size_type NumComponents, size_type ComponentId>
567
568
569namespace detail {
570
571
572template <typename T>
573struct truncate_type_impl {
574 using type = truncated<T, 2, 0>;
575};
576
577template <typename T, size_type Components>
578struct truncate_type_impl<truncated<T, Components, 0>> {
580};
581
582template <typename T>
583struct truncate_type_impl<std::complex<T>> {
584 using type = std::complex<typename truncate_type_impl<T>::type>;
585};
586
587
588template <typename T>
589struct type_size_impl {
590 static constexpr auto value = sizeof(T) * byte_size;
591};
592
593template <typename T>
594struct type_size_impl<std::complex<T>> {
595 static constexpr auto value = sizeof(T) * byte_size;
596};
597
598
599} // namespace detail
600
601
606template <typename T, size_type Limit = sizeof(uint16) * byte_size>
608 std::conditional_t<detail::type_size_impl<T>::value >= 2 * Limit,
610
611
618template <typename S, typename R>
626 GKO_ATTRIBUTES R operator()(S val) { return static_cast<R>(val); }
627};
628
629
630// mathematical functions
631
632
641GKO_INLINE GKO_ATTRIBUTES constexpr int64 ceildiv(int64 num, int64 den)
642{
643 return (num + den - 1) / den;
644}
645
646
647#if defined(__HIPCC__) && GINKGO_HIP_PLATFORM_HCC
648
649
655template <typename T>
656GKO_INLINE __host__ constexpr T zero()
657{
658 return T{};
659}
660
661
671template <typename T>
672GKO_INLINE __host__ constexpr T zero(const T&)
673{
674 return zero<T>();
675}
676
677
683template <typename T>
684GKO_INLINE __host__ constexpr T one()
685{
686 return T(1);
687}
688
689
699template <typename T>
700GKO_INLINE __host__ constexpr T one(const T&)
701{
702 return one<T>();
703}
704
705
711template <typename T>
712GKO_INLINE __device__ constexpr std::enable_if_t<
713 !std::is_same<T, std::complex<remove_complex<T>>>::value, T>
714zero()
715{
716 return T{};
717}
718
719
729template <typename T>
730GKO_INLINE __device__ constexpr T zero(const T&)
731{
732 return zero<T>();
733}
734
735
741template <typename T>
742GKO_INLINE __device__ constexpr std::enable_if_t<
743 !std::is_same<T, std::complex<remove_complex<T>>>::value, T>
744one()
745{
746 return T(1);
747}
748
749
759template <typename T>
760GKO_INLINE __device__ constexpr T one(const T&)
761{
762 return one<T>();
763}
764
765
766#else
767
768
774template <typename T>
775GKO_INLINE GKO_ATTRIBUTES constexpr T zero()
776{
777 return T{};
778}
779
780
790template <typename T>
791GKO_INLINE GKO_ATTRIBUTES constexpr T zero(const T&)
792{
793 return zero<T>();
794}
795
796
802template <typename T>
803GKO_INLINE GKO_ATTRIBUTES constexpr T one()
804{
805 return T(1);
806}
807
808
818template <typename T>
819GKO_INLINE GKO_ATTRIBUTES constexpr T one(const T&)
820{
821 return one<T>();
822}
823
824
825#endif // defined(__HIPCC__) && GINKGO_HIP_PLATFORM_HCC
826
827
828#undef GKO_BIND_ZERO_ONE
829
830
839template <typename T>
840GKO_INLINE GKO_ATTRIBUTES constexpr bool is_zero(T value)
841{
842 return value == zero<T>();
843}
844
845
854template <typename T>
855GKO_INLINE GKO_ATTRIBUTES constexpr bool is_nonzero(T value)
856{
857 return value != zero<T>();
858}
859
860
872template <typename T>
873GKO_INLINE GKO_ATTRIBUTES constexpr T max(const T& x, const T& y)
874{
875 return x >= y ? x : y;
876}
877
878
890template <typename T>
891GKO_INLINE GKO_ATTRIBUTES constexpr T min(const T& x, const T& y)
892{
893 return x <= y ? x : y;
894}
895
896
897namespace detail {
898
899
909template <typename Ref, typename Dummy = xstd::void_t<>>
910struct has_to_arithmetic_type : std::false_type {
911 static_assert(std::is_same<Dummy, void>::value,
912 "Do not modify the Dummy value!");
913 using type = Ref;
914};
915
916template <typename Ref>
917struct has_to_arithmetic_type<
918 Ref, xstd::void_t<decltype(std::declval<Ref>().to_arithmetic_type())>>
919 : std::true_type {
920 using type = decltype(std::declval<Ref>().to_arithmetic_type());
921};
922
923
928template <typename Ref, typename Dummy = xstd::void_t<>>
929struct has_arithmetic_type : std::false_type {
930 static_assert(std::is_same<Dummy, void>::value,
931 "Do not modify the Dummy value!");
932};
933
934template <typename Ref>
935struct has_arithmetic_type<Ref, xstd::void_t<typename Ref::arithmetic_type>>
936 : std::true_type {};
937
938
950template <typename Ref>
951constexpr GKO_ATTRIBUTES
952 std::enable_if_t<has_to_arithmetic_type<Ref>::value,
953 typename has_to_arithmetic_type<Ref>::type>
954 to_arithmetic_type(const Ref& ref)
955{
956 return ref.to_arithmetic_type();
957}
958
959template <typename Ref>
960constexpr GKO_ATTRIBUTES std::enable_if_t<!has_to_arithmetic_type<Ref>::value &&
961 has_arithmetic_type<Ref>::value,
962 typename Ref::arithmetic_type>
963to_arithmetic_type(const Ref& ref)
964{
965 return ref;
966}
967
968template <typename Ref>
969constexpr GKO_ATTRIBUTES std::enable_if_t<!has_to_arithmetic_type<Ref>::value &&
970 !has_arithmetic_type<Ref>::value,
971 Ref>
972to_arithmetic_type(const Ref& ref)
973{
974 return ref;
975}
976
977
978// Note: All functions have postfix `impl` so they are not considered for
979// overload resolution (in case a class / function also is in the namespace
980// `detail`)
981template <typename T>
982GKO_ATTRIBUTES GKO_INLINE constexpr std::enable_if_t<!is_complex_s<T>::value, T>
983real_impl(const T& x)
984{
985 return x;
986}
987
988template <typename T>
989GKO_ATTRIBUTES GKO_INLINE constexpr std::enable_if_t<is_complex_s<T>::value,
991real_impl(const T& x)
992{
993 return x.real();
994}
995
996
997template <typename T>
998GKO_ATTRIBUTES GKO_INLINE constexpr std::enable_if_t<!is_complex_s<T>::value, T>
999imag_impl(const T&)
1000{
1001 return T{};
1002}
1003
1004template <typename T>
1005GKO_ATTRIBUTES GKO_INLINE constexpr std::enable_if_t<is_complex_s<T>::value,
1007imag_impl(const T& x)
1008{
1009 return x.imag();
1010}
1011
1012
1013template <typename T>
1014GKO_ATTRIBUTES GKO_INLINE constexpr std::enable_if_t<!is_complex_s<T>::value, T>
1015conj_impl(const T& x)
1016{
1017 return x;
1018}
1019
1020template <typename T>
1021GKO_ATTRIBUTES GKO_INLINE constexpr std::enable_if_t<is_complex_s<T>::value, T>
1022conj_impl(const T& x)
1023{
1024 return T{real_impl(x), -imag_impl(x)};
1025}
1026
1027
1028} // namespace detail
1029
1030
1040template <typename T>
1041GKO_ATTRIBUTES GKO_INLINE constexpr auto real(const T& x)
1042{
1043 return detail::real_impl(detail::to_arithmetic_type(x));
1044}
1045
1046
1056template <typename T>
1057GKO_ATTRIBUTES GKO_INLINE constexpr auto imag(const T& x)
1058{
1059 return detail::imag_impl(detail::to_arithmetic_type(x));
1060}
1061
1062
1070template <typename T>
1071GKO_ATTRIBUTES GKO_INLINE constexpr auto conj(const T& x)
1072{
1073 return detail::conj_impl(detail::to_arithmetic_type(x));
1074}
1075
1076
1084template <typename T>
1085GKO_INLINE GKO_ATTRIBUTES constexpr auto squared_norm(const T& x)
1086 -> decltype(real(conj(x) * x))
1087{
1088 return real(conj(x) * x);
1089}
1090
1091
1101template <typename T>
1102GKO_INLINE
1103 GKO_ATTRIBUTES constexpr xstd::enable_if_t<!is_complex_s<T>::value, T>
1104 abs(const T& x)
1105{
1106 return x >= zero<T>() ? x : -x;
1107}
1108
1109
1110template <typename T>
1111GKO_INLINE GKO_ATTRIBUTES constexpr xstd::enable_if_t<is_complex_s<T>::value,
1113abs(const T& x)
1114{
1115 return sqrt(squared_norm(x));
1116}
1117
1118
1124template <typename T>
1125GKO_INLINE GKO_ATTRIBUTES constexpr T pi()
1126{
1127 return static_cast<T>(3.1415926535897932384626433);
1128}
1129
1130
1139template <typename T>
1140GKO_INLINE GKO_ATTRIBUTES constexpr std::complex<remove_complex<T>> unit_root(
1141 int64 n, int64 k = 1)
1142{
1143 return std::polar(one<remove_complex<T>>(),
1145}
1146
1147
1160template <typename T>
1161constexpr uint32 get_significant_bit(const T& n, uint32 hint = 0u) noexcept
1162{
1163 return (T{1} << (hint + 1)) > n ? hint : get_significant_bit(n, hint + 1u);
1164}
1165
1166
1178template <typename T>
1179constexpr T get_superior_power(const T& base, const T& limit,
1180 const T& hint = T{1}) noexcept
1181{
1182 return hint >= limit ? hint : get_superior_power(base, limit, hint * base);
1183}
1184
1185
1197template <typename T>
1198GKO_INLINE GKO_ATTRIBUTES std::enable_if_t<!is_complex_s<T>::value, bool>
1199is_finite(const T& value)
1200{
1201 constexpr T infinity{detail::infinity_impl<T>::value};
1202 return abs(value) < infinity;
1203}
1204
1205
1217template <typename T>
1218GKO_INLINE GKO_ATTRIBUTES std::enable_if_t<is_complex_s<T>::value, bool>
1219is_finite(const T& value)
1220{
1221 return is_finite(value.real()) && is_finite(value.imag());
1222}
1223
1224
1236template <typename T>
1237GKO_INLINE GKO_ATTRIBUTES T safe_divide(T a, T b)
1238{
1239 return b == zero<T>() ? zero<T>() : a / b;
1240}
1241
1242
1252template <typename T>
1253GKO_INLINE GKO_ATTRIBUTES std::enable_if_t<!is_complex_s<T>::value, bool>
1254is_nan(const T& value)
1255{
1256 return std::isnan(value);
1257}
1258
1259
1269template <typename T>
1270GKO_INLINE GKO_ATTRIBUTES std::enable_if_t<is_complex_s<T>::value, bool> is_nan(
1271 const T& value)
1272{
1273 return std::isnan(value.real()) || std::isnan(value.imag());
1274}
1275
1276
1284template <typename T>
1285GKO_INLINE GKO_ATTRIBUTES constexpr std::enable_if_t<!is_complex_s<T>::value, T>
1287{
1288 return std::numeric_limits<T>::quiet_NaN();
1289}
1290
1291
1299template <typename T>
1300GKO_INLINE GKO_ATTRIBUTES constexpr std::enable_if_t<is_complex_s<T>::value, T>
1302{
1304}
1305
1306
1307} // namespace gko
1308
1309
1310#endif // GKO_PUBLIC_CORE_BASE_MATH_HPP_
Definition math.hpp:566
The Ginkgo namespace.
Definition abstract_factory.hpp:48
constexpr T one()
Returns the multiplicative identity for T.
Definition math.hpp:803
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:1199
constexpr T pi()
Returns the value of pi.
Definition math.hpp:1125
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:354
constexpr increase_precision< T > round_up(T val)
Increases the precision of the input parameter.
Definition math.hpp:559
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:607
typename detail::next_precision_impl< T >::type next_precision
Obtains the next type in the singly-linked precision list.
Definition math.hpp:490
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:529
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:373
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:1161
constexpr bool is_complex_or_scalar()
Checks if T is a complex/scalar type.
Definition math.hpp:339
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:1254
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:305
constexpr std::enable_if_t<!is_complex_s< T >::value, T > nan()
Returns a quiet NaN of the given type.
Definition math.hpp:1286
constexpr T zero()
Returns the additive identity for T.
Definition math.hpp:775
constexpr bool is_zero(T value)
Returns true if and only if the given value is zero.
Definition math.hpp:840
constexpr auto imag(const T &x)
Returns the imaginary part of the object.
Definition math.hpp:1057
std::uint32_t uint32
32-bit unsigned integral type.
Definition types.hpp:160
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:1140
typename detail::reduce_precision_impl< T >::type reduce_precision
Obtains the next type in the hierarchy with lower precision than T.
Definition math.hpp:507
constexpr reduce_precision< T > round_down(T val)
Reduces the precision of the input parameter.
Definition math.hpp:543
std::int64_t int64
64-bit signed integral type.
Definition types.hpp:143
constexpr int64 ceildiv(int64 num, int64 den)
Performs integer division with rounding up.
Definition math.hpp:641
constexpr bool is_complex()
Checks if T is a complex type.
Definition math.hpp:315
T safe_divide(T a, T b)
Computes the quotient of the given parameters, guarding against division by zero.
Definition math.hpp:1237
constexpr T min(const T &x, const T &y)
Returns the smaller of the arguments.
Definition math.hpp:891
constexpr xstd::enable_if_t<!is_complex_s< T >::value, T > abs(const T &x)
Returns the absolute value of the object.
Definition math.hpp:1104
constexpr auto squared_norm(const T &x) -> decltype(real(conj(x) *x))
Returns the squared norm of the object.
Definition math.hpp:1085
next_precision< T > previous_precision
Obtains the previous type in the singly-linked precision list.
Definition math.hpp:500
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:329
constexpr size_type byte_size
Number of bits in a byte.
Definition types.hpp:211
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:1179
typename detail::increase_precision_impl< T >::type increase_precision
Obtains the next type in the hierarchy with higher precision than T.
Definition math.hpp:514
remove_complex< T > to_real
to_real is alias of remove_complex
Definition math.hpp:382
constexpr auto conj(const T &x)
Returns the conjugate of an object.
Definition math.hpp:1071
constexpr bool is_nonzero(T value)
Returns true if and only if the given value is not zero.
Definition math.hpp:855
constexpr T max(const T &x, const T &y)
Returns the larger of the arguments.
Definition math.hpp:873
constexpr auto real(const T &x)
Returns the real part of the object.
Definition math.hpp:1041
Access the underlying real type of a complex number.
Definition math.hpp:279
T type
The type.
Definition math.hpp:281
Used to convert objects of type S to objects of type R using static_cast.
Definition math.hpp:619
R operator()(S val)
Converts the object to result type.
Definition math.hpp:626