1#ifndef DIAGONAL_MATRIX_H_
2#define DIAGONAL_MATRIX_H_
17template <
int n,
typename T>
22 "DiagonalMatrix requires Complex or arithmetic type");
25 using base_type = hila::arithmetic_type<T>;
26 using argument_type = T;
36 template <
typename S, std::enable_if_t<(hila::is_assignable<T &, S>::value),
int> = 0>
38 for (
int i = 0; i < n; i++)
45 template <typename S, std::enable_if_t<hila::is_assignable<T &, S>::value,
int> = 0>
47 assert(rhs.size() == n &&
"Matrix/Vector initializer list size must match variable size");
49 for (
auto it = rhs.begin(); it != rhs.end(); it++, i++) {
57 static constexpr int rows() {
60 static constexpr int columns() {
63 static constexpr int size() {
72 #pragma hila loop_function
73 inline T
e(
const int i)
const {
78 inline T &
e(
const int i) const_function {
83 T
e(
const int i,
const int j)
const {
118 for (
int i = 0; i < n; i++) {
135 template <
typename S>
137 return !(*
this == rhs);
145 template <typename S, std::enable_if_t<hila::is_assignable<T &, S>::value,
int> = 0>
148 for (
int i = 0; i < n; i++) {
156 template <typename S, std::enable_if_t<hila::is_assignable<T &, S>::value,
int> = 0>
159 for (
int i = 0; i < n; i++) {
167 template <typename S, std::enable_if_t<hila::is_assignable<T &, S>::value,
int> = 0>
169 assert(rhs.size() == n &&
"Initializer list has a wrong size in assignment");
171 for (
auto it = rhs.begin(); it != rhs.end(); it++, i++) {
180 template <typename S, std::enable_if_t<hila::is_assignable<T &, S>::value,
int> = 0>
182 for (
int i = 0; i < n; i++) {
189 template <typename S, std::enable_if_t<hila::is_assignable<T &, S>::value,
int> = 0>
191 for (
int i = 0; i < n; i++) {
199 template <typename S, std::enable_if_t<hila::is_assignable<T &, S>::value,
int> = 0>
201 for (
int i = 0; i < n; i++) {
208 template <typename S, std::enable_if_t<hila::is_assignable<T &, S>::value,
int> = 0>
210 for (
int i = 0; i < n; i++) {
218 template <
typename S,
219 std::enable_if_t<hila::is_assignable<T &, hila::type_mul<T, S>>::value,
int> = 0>
221 for (
int i = 0; i < n; i++) {
228 template <
typename S,
229 std::enable_if_t<hila::is_assignable<T &, hila::type_mul<T, S>>::value,
int> = 0>
231 for (
int i = 0; i < n; i++) {
239 template <
typename S,
240 std::enable_if_t<hila::is_assignable<T &, hila::type_div<T, S>>::value,
int> = 0>
242 for (
int i = 0; i < n; i++) {
249 template <
typename S,
250 std::enable_if_t<hila::is_assignable<T &, hila::type_div<T, S>>::value,
int> = 0>
252 for (
int i = 0; i < n; i++) {
262 template <typename S, std::enable_if_t<hila::is_assignable<T &, S>::value,
int> = 0>
264 for (
int i = 0; i < n; i++)
281 for (
int i = 0; i < n; i++)
305 for (
int i = 0; i < n; i++) {
306 res.c[i] =
::abs(c[i]);
318 for (
int i = 0; i < n; i++) {
326 for (
int i = 0; i < n; i++) {
327 res.c[i] = ::imag(c[i]);
336 template <typename S = T, std::enable_if_t<hila::is_arithmetic<S>::value,
int> = 0>
339 for (
int i = 1; i < n; i++) {
346 template <typename S = T, std::enable_if_t<hila::is_arithmetic<S>::value,
int> = 0>
349 for (
int i = 1; i < n; i++) {
358 for (
int i = 1; i < n; i++)
365 for (
int i = 1; i < n; i++)
370 auto squarenorm()
const {
371 hila::arithmetic_type<T> res(0);
372 for (
int i = 0; i < n; i++)
373 res += ::squarenorm(c[i]);
377 hila::arithmetic_type<T> norm()
const {
378 return sqrt(squarenorm());
387 static_assert(hila::is_floating_point<hila::arithmetic_type<T>>::value,
388 "DiagonalMatrix random() requires non-integral type elements");
389 for (
int i = 0; i < n; i++) {
397 static_assert(hila::is_floating_point<hila::arithmetic_type<T>>::value,
398 "DiagonaMatrix gaussian_random() requires non-integral type elements");
399 for (
int i = 0; i < n; i++) {
409 std::string
str(
int prec = 8,
char separator =
' ')
const {
410 return this->asArray().str(prec, separator);
418 for (
int i = 0; i < n; i++) {
419 for (
int j = 0; j < n; j++) {
452 hila::sort order = hila::sort::ascending)
const {
453 return this->asArray().sort(permutation, order).asDiagonalMatrix();
458 return this->asArray().sort(order).asDiagonalMatrix();
467template <
typename A,
typename B,
int n,
int m>
469 if constexpr (m != n)
472 for (
int i = 0; i < n; i++) {
473 if (lhs.
e(i) != rhs.
e(i))
483template <
typename A,
typename S,
typename Mtype,
int n,
int m1,
int m2>
485 if constexpr (m1 != n || m2 != n)
488 for (
int i = 0; i < n; i++) {
489 for (
int j = 0; j < n; j++) {
491 if (lhs.
e(i) != rhs.
e(i, i))
494 if (rhs.
e(i, j) != 0)
502template <
typename A,
typename S,
typename Mtype,
int n,
int m1,
int m2>
509template <
int n,
typename T>
514template <
int n,
typename T>
519template <
int n,
typename T>
524template <
int n,
typename T>
526 return arg.adjoint();
529template <
int n,
typename T>
534template <
int n,
typename T>
539template <
int n,
typename T>
544template <
int n,
typename T>
549template <
int n,
typename T>
551 return arg.squarenorm();
554template <
int n,
typename T>
559template <
int n,
typename T>
575template <
typename Mt,
typename S,
typename Enable =
void>
576struct diagonalmatrix_scalar_op_s {
581template <
typename Mt,
typename S>
582struct diagonalmatrix_scalar_op_s<
584 typename std::enable_if_t<std::is_convertible<hila::type_plus<hila::number_type<Mt>, S>,
585 hila::number_type<Mt>>::value>> {
587 using type =
typename std::conditional<
588 hila::is_floating_point<hila::arithmetic_type<Mt>>::value, Mt,
593template <
typename Mt,
typename S>
594using diagonalmatrix_scalar_type =
typename diagonalmatrix_scalar_op_s<Mt, S>::type;
604template <
int n,
typename T,
typename S,
605 std::enable_if_t<hila::is_complex_or_arithmetic<S>::value,
int> = 0,
606 typename Rtype = hila::diagonalmatrix_scalar_type<DiagonalMatrix<n, T>, S>>
609 for (
int i = 0; i < n; i++)
610 res.e(i) = a.
e(i) + b;
615template <
int n,
typename T,
typename S,
616 std::enable_if_t<hila::is_complex_or_arithmetic<S>::value,
int> = 0,
617 typename Rtype = hila::diagonalmatrix_scalar_type<DiagonalMatrix<n, T>, S>>
623template <
int n,
typename T,
typename S,
624 std::enable_if_t<hila::is_complex_or_arithmetic<S>::value,
int> = 0,
625 typename Rtype = hila::diagonalmatrix_scalar_type<DiagonalMatrix<n, T>, S>>
628 for (
int i = 0; i < n; i++)
629 res.e(i) = a.
e(i) - b;
634template <
int n,
typename T,
typename S,
635 std::enable_if_t<hila::is_complex_or_arithmetic<S>::value,
int> = 0,
636 typename Rtype = hila::diagonalmatrix_scalar_type<DiagonalMatrix<n, T>, S>>
639 for (
int i = 0; i < n; i++)
640 res.e(i) = b - a.
e(i);
645template <
int n,
typename T,
typename S,
646 std::enable_if_t<hila::is_complex_or_arithmetic<S>::value,
int> = 0,
647 typename Rtype = hila::diagonalmatrix_scalar_type<DiagonalMatrix<n, T>, S>>
650 for (
int i = 0; i < n; i++)
651 res.e(i) = a.
e(i) * b;
656template <
int n,
typename T,
typename S,
657 std::enable_if_t<hila::is_complex_or_arithmetic<S>::value,
int> = 0,
658 typename Rtype = hila::diagonalmatrix_scalar_type<DiagonalMatrix<n, T>, S>>
664template <
int n,
typename T,
typename S,
665 std::enable_if_t<hila::is_complex_or_arithmetic<S>::value,
int> = 0,
666 typename Rtype = hila::diagonalmatrix_scalar_type<DiagonalMatrix<n, T>, S>>
669 for (
int i = 0; i < n; i++)
670 res.e(i) = a.
e(i) / b;
675template <
int n,
typename T,
typename S,
676 std::enable_if_t<hila::is_complex_or_arithmetic<S>::value,
int> = 0,
677 typename Rtype = hila::diagonalmatrix_scalar_type<DiagonalMatrix<n, T>, S>>
680 for (
int i = 0; i < n; i++)
681 res.e(i) = b / a.
e(i);
687template <
int n,
typename A,
typename B,
typename R = hila::type_plus<A, B>>
690 for (
int i = 0; i < n; i++)
691 res.
e(i) = a.
e(i) + b.
e(i);
695template <
int n,
typename A,
typename B,
typename R = hila::type_minus<A, B>>
698 for (
int i = 0; i < n; i++)
699 res.
e(i) = a.
e(i) - b.
e(i);
703template <
int n,
typename A,
typename B,
typename R = hila::type_mul<A, B>>
706 for (
int i = 0; i < n; i++)
707 res.
e(i) = a.
e(i) * b.
e(i);
711template <
int n,
typename A,
typename B,
typename R = hila::type_div<A, B>>
714 for (
int i = 0; i < n; i++)
715 res.
e(i) = a.
e(i) / b.
e(i);
721template <
int n,
typename T,
typename Mtype, std::enable_if_t<Mtype::is_matrix(),
int> = 0,
722 typename Rtype = hila::mat_x_mat_type<Matrix<n, n, T>, Mtype>>
728 static_assert(mc == n && mr == n,
"Matrix sizes do not match");
732 for (
int i = 0; i < n; i++)
737template <
int n,
typename T,
typename Mtype, std::enable_if_t<Mtype::is_matrix(),
int> = 0,
738 typename Rtype = hila::mat_x_mat_type<Matrix<n, n, T>, Mtype>>
743template <
int n,
typename T,
typename Mtype, std::enable_if_t<Mtype::is_matrix(),
int> = 0,
744 typename Rtype = hila::mat_x_mat_type<Matrix<n, n, T>, Mtype>>
750 static_assert(mc == n && mr == n,
"Matrix sizes do not match");
753 for (
int i = 0; i < n; i++)
758template <
int n,
typename T,
typename Mtype, std::enable_if_t<Mtype::is_matrix(),
int> = 0,
759 typename Rtype = hila::mat_x_mat_type<Matrix<n, n, T>, Mtype>>
764 static_assert(mc == n && mr == n,
"Matrix sizes do not match");
767 for (
int i = 0; i < n; i++)
775template <
int n,
typename T,
typename Mtype, std::enable_if_t<Mtype::is_matrix(),
int> = 0,
776 typename Rtype = hila::mat_x_mat_type<Matrix<n, n, T>, Mtype>>
782 static_assert(mr == n,
"Matrix sizes do not match");
785 for (
int i = 0; i < n; i++)
786 for (
int j = 0; j < mc; j++)
787 r.e(i, j) = a.
e(i) * b.
e(i, j);
791template <
int n,
typename T,
typename Mtype, std::enable_if_t<Mtype::is_matrix(),
int> = 0,
792 typename Rtype = hila::mat_x_mat_type<Matrix<n, n, T>, Mtype>>
798 static_assert(mc == n,
"Matrix sizes do not match");
801 for (
int i = 0; i < mr; i++)
802 for (
int j = 0; j < n; j++)
803 r.e(i, j) = b.
e(i, j) * a.
e(j);
808template <
int n,
typename T,
typename Mtype, std::enable_if_t<Mtype::is_matrix(),
int> = 0,
809 typename Rtype = hila::mat_x_mat_type<Matrix<n, n, T>, Mtype>>
815 static_assert(mc == n,
"Matrix sizes do not match");
818 for (
int i = 0; i < mr; i++)
819 for (
int j = 0; j < n; j++)
820 r.e(i, j) = b.
e(i, j) / a.
e(j);
828template <
int n,
typename T>
830 for (
int i = 0; i < n; i++)
831 a.c[i] =
sqrt(a.c[i]);
835template <
int n,
typename T>
837 for (
int i = 0; i < n; i++)
838 a.c[i] =
cbrt(a.c[i]);
842template <
int n,
typename T>
844 for (
int i = 0; i < n; i++)
845 a.c[i] =
exp(a.c[i]);
849template <
int n,
typename T>
851 for (
int i = 0; i < n; i++)
852 a.c[i] =
log(a.c[i]);
856template <
int n,
typename T>
858 for (
int i = 0; i < n; i++)
859 a.c[i] =
sin(a.c[i]);
863template <
int n,
typename T>
865 for (
int i = 0; i < n; i++)
866 a.c[i] =
cos(a.c[i]);
870template <
int n,
typename T>
872 for (
int i = 0; i < n; i++)
873 a.c[i] =
tan(a.c[i]);
877template <
int n,
typename T>
879 for (
int i = 0; i < n; i++)
880 a.c[i] =
asin(a.c[i]);
884template <
int n,
typename T>
886 for (
int i = 0; i < n; i++)
887 a.c[i] =
acos(a.c[i]);
891template <
int n,
typename T>
893 for (
int i = 0; i < n; i++)
894 a.c[i] =
atan(a.c[i]);
898template <
int n,
typename T>
900 for (
int i = 0; i < n; i++)
901 a.c[i] =
sinh(a.c[i]);
905template <
int n,
typename T>
907 for (
int i = 0; i < n; i++)
908 a.c[i] =
cosh(a.c[i]);
912template <
int n,
typename T>
914 for (
int i = 0; i < n; i++)
915 a.c[i] =
tanh(a.c[i]);
919template <
int n,
typename T>
921 for (
int i = 0; i < n; i++)
922 a.c[i] =
asinh(a.c[i]);
926template <
int n,
typename T>
928 for (
int i = 0; i < n; i++)
929 a.c[i] =
acosh(a.c[i]);
933template <
int n,
typename T>
935 for (
int i = 0; i < n; i++)
936 a.c[i] =
atanh(a.c[i]);
943 int n,
typename T,
typename S,
944 std::enable_if_t<hila::is_arithmetic<S>::value || hila::contains_complex<T>::value,
int> = 0>
946 for (
int i = 0; i < n; i++)
947 a.c[i] =
pow(a.c[i], p);
952template <
int n,
typename T,
typename S,
953 std::enable_if_t<!hila::contains_complex<T>::value,
int> = 0>
956 for (
int i = 0; i < n; i++)
957 res.
e(i) =
pow(a.
e(i), p);
966template <
typename Ntype,
typename T,
int n,
967 std::enable_if_t<hila::is_arithmetic<T>::value,
int> = 0>
970 for (
int i = 0; i < n; i++)
975template <typename Ntype, typename T, int n, std::enable_if_t<hila::is_complex<T>::value,
int> = 0>
978 for (
int i = 0; i < n; i++)
979 res.c[i] = cast_to<Ntype>(mat.c[i]);
984template <
int n,
typename T>
991template <
int n,
typename T>
993 return to_string(A.asArray(), prec, separator);
996template <
int n,
typename T>
998 return prettyprint(A.
toMatrix(), prec);
Array< n, m, T > conj(const Array< n, m, T > &arg)
Return conjugate Array.
auto operator/(const Array< n, m, A > &a, const Array< n, m, B > &b)
Division operator.
std::ostream & operator<<(std::ostream &strm, const Array< n, m, T > &A)
Stream operator.
Array< n, m, T > asin(Array< n, m, T > a)
Inverse Sine.
auto operator-(const Array< n, m, A > &a, const Array< n, m, B > &b)
Subtraction operator.
Array< n, m, T > exp(Array< n, m, T > a)
Exponential.
Array< n, m, T > tanh(Array< n, m, T > a)
Hyperbolic tangent.
Array< n, m, hila::arithmetic_type< T > > imag(const Array< n, m, T > &arg)
Return imaginary part of Array.
hila::arithmetic_type< T > squarenorm(const Array< n, m, T > &rhs)
Return square norm of Array.
Array< n, m, T > cosh(Array< n, m, T > a)
Hyperbolic Cosine.
Array< n, m, T > tan(Array< n, m, T > a)
Tangent.
auto operator+(const Array< n, m, A > &a, const Array< n, m, B > &b)
Addition operator.
Array< n, m, T > cos(Array< n, m, T > a)
Cosine.
Array< n, m, T > cbrt(Array< n, m, T > a)
Cuberoot.
Array< n, m, T > acos(Array< n, m, T > a)
Inverse Cosine.
Array< n, m, T > acosh(Array< n, m, T > a)
Inverse Hyperbolic Cosine.
Array< n, m, T > sqrt(Array< n, m, T > a)
Square root.
Array< n, m, T > asinh(Array< n, m, T > a)
Inverse Hyperbolic Sine.
Array< n, m, T > atan(Array< n, m, T > a)
Inverse Tangent.
Array< n, m, T > pow(Array< n, m, T > a, int b)
Power.
Array< n, m, T > operator*(Array< n, m, T > a, const Array< n, m, T > &b)
Multiplication operator.
Array< n, m, Ntype > cast_to(const Array< n, m, T > &mat)
Array casting operation.
Array< n, m, T > sin(Array< n, m, T > a)
Sine.
Array< n, m, T > sinh(Array< n, m, T > a)
Hyperbolic Sine.
Array< n, m, hila::arithmetic_type< T > > real(const Array< n, m, T > &arg)
Return real part of Array.
Array< n, m, T > atanh(Array< n, m, T > a)
Inverse Hyperbolic Tangent.
Define type DiagonalMatrix<n,T>
Matrix< n, n, T > toMatrix() const
convert to generic matrix
bool operator!=(const S &rhs) const
Boolean operator != to check if matrices are exactly different.
Vector< n, T > column(int i) const
Returns column vector i.
DiagonalMatrix & operator=(const DiagonalMatrix< n, S > &rhs) &
T e(const int i) const
Element access - e(i) gives diagonal element i.
DiagonalMatrix & transpose() const
transpose - leaves diagonal matrix as is
DiagonalMatrix conj() const
conj - conjugate elements
DiagonalMatrix & random()
Fills Matrix with random elements.
std::string str(int prec=8, char separator=' ') const
convert to string for printing
RowVector< n, T > row(int i) const
Return row from Diagonal matrix.
DiagonalMatrix dagger() const
dagger - conjugate elements
DiagonalMatrix()=default
Define default constructors to ensure std::is_trivial.
DiagonalMatrix< n, T > operator-() const
Unary - operator.
DiagonalMatrix & fill(const S rhs)
fill with constant value - same as assignment
T max() const
Find max or min value - only for arithmetic types.
static constexpr int rows()
Returns matrix size - all give same result.
const auto & operator+() const
Unary + operator.
DiagonalMatrix< n, T > sort(Vector< N, int > &permutation, hila::sort order=hila::sort::ascending) const
implement sort as casting to matrix
auto real() const
real and imaginary parts of diagonal matrix
auto abs() const
absolute value of all elements
The main matrix type template Matrix_t. This is a base class type for "useful" types which are deriv...
static constexpr int rows()
Define constant methods rows(), columns() - may be useful in template code.
static constexpr int columns()
Returns column length.
T e(const int i, const int j) const
Standard array indexing operation for matrices and vectors.
Matrix class which defines matrix operations.
bool operator==(const Complex< A > &a, const Complex< B > &b)
Compare equality of two complex numbers.
Complex< T > dagger(const Complex< T > &val)
Return dagger of Complex number.
T abs(const Complex< T > &a)
Return absolute value of Complex number.
T arg(const Complex< T > &a)
Return argument of Complex number.
Definition of Matrix types.
Implement hila::swap for gauge fields.
T gaussian_random()
Template function T hila::gaussian_random<T>(),generates gaussian random value of type T,...
logger_class log
Now declare the logger.
double random()
Real valued uniform random number generator.
decltype(std::declval< A >()+std::declval< B >()) type_plus
std::string to_string(const Array< n, m, T > &A, int prec=8, char separator=' ')
Converts Array object to string.
hila::is_complex_or_arithmetic<T>::value