cppqed-multidiagonal 0.4.0
Multidiagonal sparse operator algebra for C++QED
Loading...
Searching...
No Matches
MultiArrayComplex.h
Go to the documentation of this file.
1// Copyright András Vukics 2022–2026. Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE.txt)
2#pragma once
3
4#include "MultiArray.h"
5
6#include <Eigen/Dense>
7
8#include <boost/serialization/complex.hpp>
9
10#include <complex>
11
13typedef std::complex<double> dcomp;
14
16using std::complex_literals::operator""i;
17
19inline bool isNonZero(dcomp c) {return bool(real(c)) || bool(imag(c));}
20
22inline bool hasRealPart(dcomp c) {return bool(real(c));}
24inline bool hasImagPart(dcomp c) {return bool(imag(c));}
25
27inline bool absCompare(dcomp c1, dcomp c2) {return abs(c1)< abs(c2);}
29inline bool realCompare(dcomp c1, dcomp c2) {return real(c1)<real(c2);}
30
33auto sqr(auto&& x) // return type is non-reference or trailing
34noexcept(noexcept(x*x)) // propagate noexcept
35-> decltype(x*x) // enable SFINAE
36{ return x * x; }
37
39double relativeDeviation(const auto& a, const auto& b)
40{
41 const double den = std::abs(a)+std::abs(b);
42 return den==0. ? 0. : std::abs(a-b)/den;
43}
44
47inline double sqrAbs(dcomp v) {return std::norm(v);}
48
56inline dcomp textbookProduct(dcomp a, dcomp b) {return {a.real()*b.real()-a.imag()*b.imag(), a.real()*b.imag()+a.imag()*b.real()};}
57
58
59namespace boost::json {
61 template<class T>
62 void tag_invoke(value_from_tag, value& jv, const std::complex<T>& c) {
63 jv = {c.real(), c.imag()};
64 }
65
67 template<class T>
68 std::complex<T> tag_invoke(value_to_tag<std::complex<T>>, const value& jv) {
69 return { json::value_to<T>(jv.at(0)), json::value_to<T>(jv.at(1)) } ;
70 }
71} // boost::json
72
74using CMatrix=Eigen::MatrixX<dcomp>;
76using CVector=Eigen::VectorX<dcomp>;
77
78
79namespace cppqedutils {
80
83template <typename N> concept scalar = std::convertible_to<N,double> || std::convertible_to<N,dcomp>;
84
86template <size_t RANK>
88{
89 return Eigen::Map<CVector>{ma.dataStorage().data(), Eigen::Index(ma.dataView.size())};
90}
91
93template <size_t RANK>
95{
96 return Eigen::Map<const CVector>{ma.dataStorage().data(), Eigen::Index(ma.dataView.size())};
97}
98
99
105template <size_t TWO_TIMES_RANK> requires ( !(TWO_TIMES_RANK%2) )
107{
108 static constexpr size_t RANK=TWO_TIMES_RANK/2;
110 std::ranges::for_each(std::views::iota(0ul,RANK), [&] (size_t i) {
111 res[i]=extents[i];
112#ifndef NDEBUG
113 if (size_t b=extents[i+RANK]; res[i]!=b)
114 throw std::invalid_argument("MultiArray does not have the shape of a matrix: index no. "+std::to_string(i)+": "+std::to_string(res[i])+" vs. "+std::to_string(b));
115#endif // NDEBUG
116 });
117 return res;
118}
119
122template <size_t TWO_TIMES_RANK>
124{
125 const Eigen::Index matrixDim = Eigen::Index(multiarray::calculateExtent(halveExtents(ma.extents)));
126 return Eigen::Map<CMatrix>{ma.dataStorage().data(), matrixDim, matrixDim};
127}
128
130template <size_t TWO_TIMES_RANK>
132{
133 const Eigen::Index matrixDim = Eigen::Index(multiarray::calculateExtent(halveExtents(ma.extents)));
134 return Eigen::Map<const CMatrix>{ma.dataStorage().data(), matrixDim, matrixDim};
135}
136
137
143template <size_t RANK1, size_t RANK2>
145 std::function<dcomp(dcomp,dcomp)> func=std::multiplies<dcomp>{} )
146{
147 MultiArray<dcomp,RANK1+RANK2> res{concatenate(m1.extents,m2.extents)};
148 for (size_t stride=m1.dataView.size(), i=0; i<stride; ++i) for (size_t j=0; j<m2.dataView.size(); ++j) res.dataStorage()[i+stride*j]=func(m1.dataView[i],m2.dataView[j]);
149 return res;
150}
151
152
154template <size_t RANK>
156{
157 for (dcomp& v : ma.dataStorage()) v=conj(v);
158 return ma;
159}
160
161
163template <size_t RANK>
164double frobeniusNormSqr(const MultiArray<dcomp,RANK>& ma) { return std::ranges::fold_left_first( ma.dataView | std::views::transform(sqrAbs), std::plus{} ).value_or(0.); }
165
167template <size_t RANK>
169
175template <size_t TWO_TIMES_RANK>
177{
178 checkContiguous(mav,"hermitianConjugateSelf");
180 auto _=[&] (size_t i, size_t j) -> dcomp& {return mav.dataView[i+matrixDim*j];};
181 for (size_t i=0; i<matrixDim; ++i) {
182 _(i,i)=conj(_(i,i));
183 for (size_t j=i+1; j<matrixDim; ++j) {
184 dcomp &u=_(i,j), &l=_(j,i);
185 u=conj(u); l=conj(l);
186 std::swap(u, l);
187 }
188 }
189}
190
199template <size_t TWO_TIMES_RANK>
201{
202 checkContiguous(mav,"twoTimesRealPartOfSelf");
204 auto _=[&] (size_t i, size_t j) -> dcomp& {return mav.dataView[i+matrixDim*j];};
205 for (size_t i=0; i<matrixDim; ++i) {
206 _(i,i)=2.*real(_(i,i));
207 for (size_t j=i+1; j<matrixDim; ++j) _(j,i)=conj(_(i,j)=_(i,j)+conj(_(j,i)));
208 }
209}
210
211} // cppqedutils
Eigen::MatrixX< dcomp > CMatrix
Dense complex matrix type (Eigen dynamic-size).
Definition MultiArrayComplex.h:74
double sqrAbs(dcomp v)
Squared absolute value of a complex number: |v|^2 = re^2 + im^2, computed as such (std::norm),...
Definition MultiArrayComplex.h:47
bool isNonZero(dcomp c)
Returns true if either the real or imaginary part of c is non-zero.
Definition MultiArrayComplex.h:19
bool absCompare(dcomp c1, dcomp c2)
Comparator by absolute value, for use with sorting algorithms.
Definition MultiArrayComplex.h:27
std::complex< double > dcomp
Double-precision complex number. Named to resemble a built-in type rather than a class.
Definition MultiArrayComplex.h:13
dcomp textbookProduct(dcomp a, dcomp b)
Complex product by the textbook formula , for hot loops.
Definition MultiArrayComplex.h:56
auto sqr(auto &&x) noexcept(noexcept(x *x)) -> decltype(x *x)
Generic square: x*x. Return type is deduced; noexcept and SFINAE are propagated.
Definition MultiArrayComplex.h:33
bool hasRealPart(dcomp c)
Returns true if the real part of c is non-zero.
Definition MultiArrayComplex.h:22
double relativeDeviation(const auto &a, const auto &b)
Relative deviation between two values: |a-b| / (|a|+|b|). Returns 0 if both are zero.
Definition MultiArrayComplex.h:39
bool hasImagPart(dcomp c)
Returns true if the imaginary part of c is non-zero.
Definition MultiArrayComplex.h:24
Eigen::VectorX< dcomp > CVector
Dense complex vector type (Eigen dynamic-size).
Definition MultiArrayComplex.h:76
bool realCompare(dcomp c1, dcomp c2)
Comparator by real part, for use with sorting algorithms.
Definition MultiArrayComplex.h:29
A non-owning, strided view over a contiguous buffer. Should be passed by value.
Definition MultiArray.h:106
Extents< RANK > extents
Definition MultiArray.h:172
std::span< T > dataView
Definition MultiArray.h:176
Concept satisfied by scalar numeric types usable as operator coefficients: any type convertible to do...
Definition MultiArrayComplex.h:83
Definition MultiArrayComplex.h:59
void tag_invoke(value_from_tag, value &jv, const std::complex< T > &c)
Boost.JSON serialization for std::complex<T>: emits a two-element JSON array [re, im].
Definition MultiArrayComplex.h:62
auto calculateExtent(Extents< RANK > extents)
Returns the total number of elements: the product of all extents.
Definition MultiArray.h:240
Namespace alias for Boost.Hana, used for compile-time sequences and heterogeneous containers.
Definition MultiArray.h:17
void twoTimesRealPartOfSelf(MultiArrayView< dcomp, TWO_TIMES_RANK > mav)
In-place replacement of a rank-2R matrix view mav with M + M† (twice its Hermitian part).
Definition MultiArrayComplex.h:200
constexpr auto concatenate(const std::array< Type, sizes > &... arrays)
Concatenates multiple std::array instances of different sizes into one.
Definition MultiArray.h:33
std::array< size_t, RANK > Extents
Compile-time–fixed shape and stride descriptor for a rank-RANK array. Should be passed by value,...
Definition MultiArray.h:46
MultiArray< dcomp, RANK > & conj(MultiArray< dcomp, RANK > &ma)
In-place complex conjugation of all elements of ma.
Definition MultiArrayComplex.h:155
void hermitianConjugateSelf(MultiArrayView< dcomp, TWO_TIMES_RANK > mav)
In-place Hermitian conjugation of a rank-2R matrix view mav.
Definition MultiArrayComplex.h:176
auto matricize(MultiArray< dcomp, TWO_TIMES_RANK > &ma)
Maps a mutable rank-2R MultiArray<dcomp> to an Eigen square matrix (no data copy)....
Definition MultiArrayComplex.h:123
Extents< TWO_TIMES_RANK/2 > halveExtents(Extents< TWO_TIMES_RANK > extents)
Extracts the first half of a rank-2R extent array, verifying that both halves are equal.
Definition MultiArrayComplex.h:106
double frobeniusNormSqr(const MultiArray< dcomp, RANK > &ma)
Squared Frobenius norm: . Returns 0 for an empty array.
Definition MultiArrayComplex.h:164
void checkContiguous(MultiArrayView< T, RANK > mav, std::string message)
Debug-mode check that a view covers its storage as an owning MultiArray of the same extents would: of...
Definition MultiArray.h:277
auto directProduct(const MultiArray< dcomp, RANK1 > &m1, const MultiArray< dcomp, RANK2 > &m2, std::function< dcomp(dcomp, dcomp)> func=std::multiplies< dcomp >{})
Tensor (outer) product of two complex multi-arrays.
Definition MultiArrayComplex.h:144
auto vectorize(MultiArray< dcomp, RANK > &ma)
Maps a mutable MultiArray<dcomp,RANK> to an Eigen column vector (no data copy).
Definition MultiArrayComplex.h:87
double frobeniusNorm(const MultiArray< dcomp, RANK > &ma)
Frobenius norm: .
Definition MultiArrayComplex.h:168