HILA
Loading...
Searching...
No Matches
su2.h
1#ifndef SU2_H_
2#define SU2_H_
3
4#include "matrix.h"
5
6template <typename T>
7class Algebra;
8
9/// This implementation represents the matrices as
10/// $U = d + a i\sigma_1 + b i\sigma_2 + c i\sigma_3$
11/// This is in SU(2) if $a^2 + b^2 + c^2 + d^2 = 1$
12
13template <typename T>
14class SU2 {
15 static_assert(hila::is_floating_point<T>::value, "SU2 requires a floating point type");
16
17 public: // public on purpose
18 T a, b, c, d;
19
20 public:
21 using base_type = T;
22 using argument_type = T;
23
24 SU2() = default;
25 ~SU2() = default;
26 SU2(const SU2 &) = default;
27
28 /// construct from 'scalar'
29 template <typename B, std::enable_if_t<hila::is_assignable<T &, B>::value, int> = 0>
30 SU2(const B z) {
31 a = 0;
32 b = 0;
33 c = 0;
34 d = z;
35 }
36 /// initializer list constructor
37 template <typename S, std::enable_if_t<hila::is_assignable<T &, S>::value, int> = 0>
38 SU2(std::initializer_list<S> rhs) {
39 assert(rhs.size() == 4 && "SU2 initializer list size must be 4");
40 auto it = rhs.begin();
41 a = *(it++);
42 b = *(it++);
43 c = *(it++);
44 d = *(it);
45 }
46 /// Normalize det = 1 to make sure it's an element of SU2
47 inline SU2<T> &normalize() {
48 T len = sqrt(this->det());
49 // assert(len != 0);
50 // if (len <= 0)
51 // return *this;
52 a /= len;
53 b /= len;
54 c /= len;
55 d /= len;
56 return *this;
57 }
58
59 /// Normalize det = 1 to make sure it's an element of SU2
60 inline SU2<T> &reunitarize() {
61 return this->normalize();
62 }
63 /// complex conjugate transpose
64 inline SU2<T> dagger() const {
65 SU2<T> ret;
66 ret.a = -a;
67 ret.b = -b;
68 ret.c = -c;
69 ret.d = d;
70 return ret;
71 }
72 /// for SU2 same as .dagger()
73 // if matrix is not normalized?
74 // SU2<T> inverse() const {
75 // return this->dagger();
76 // };
77
78 inline T trace() const {
79 return 2.0 * d;
80 }
81
82 inline T det() const {
83 return a * a + b * b + c * c + d * d;
84 }
85 inline T squarenorm() const {
86 return det();
87 }
88 static constexpr int size() {
89 return 2;
90 }
91 /// unary -
92 inline SU2<T> operator-() const {
93 SU2<T> res;
94 res.a = -a;
95 res.b = -b;
96 res.c = -c;
97 res.d = -d;
98 return res;
99 }
100 /// unary +
101 inline SU2<T> operator+() const {
102 return *this;
103 }
104#pragma hila loop_function
105 /// assign from another SU2
106 template <typename A, std::enable_if_t<hila::is_assignable<T &, A>::value, int> = 0>
107 inline SU2<T> &operator=(const SU2<A> &rhs) out_only {
108 a = rhs.a;
109 b = rhs.b;
110 c = rhs.c;
111 d = rhs.d;
112 return *this;
113 }
114#pragma hila loop_function
115 /// assign from initializer list
116 template <typename S, std::enable_if_t<hila::is_assignable<T &, S>::value, int> = 0>
117 inline SU2<T> &operator=(std::initializer_list<S> rhs) out_only {
118 assert(rhs.size() == 4 && "SU2 initializer list size must be 4");
119 auto it = rhs.begin();
120 a = *(it++);
121 b = *(it++);
122 c = *(it++);
123 d = *(it);
124 }
125#pragma hila loop_function
126 /// assign from 'scalar'
127 template <typename A, std::enable_if_t<hila::is_assignable<T &, A>::value, int> = 0>
128 inline SU2<T> &operator=(A rhs) out_only {
129 a = 0;
130 b = 0;
131 c = 0;
132 d = rhs;
133 return *this;
134 }
135#pragma hila loop_function
136 /// add assign another SU2
137 template <typename A,
138 std::enable_if_t<hila::is_assignable<T &, hila::type_plus<T &, A>>::value, int> = 0>
139 inline SU2<T> &operator+=(const SU2<A> &rhs) {
140 a += rhs.a;
141 b += rhs.b;
142 c += rhs.c;
143 d += rhs.d;
144 return *this;
145 }
146#pragma hila loop_function
147 /// subtract assign another SU2
148 template <typename A,
149 std::enable_if_t<hila::is_assignable<T &, hila::type_minus<T &, A>>::value, int> = 0>
150 inline SU2<T> &operator-=(const SU2<A> &rhs) {
151 a -= rhs.a;
152 b -= rhs.b;
153 c -= rhs.c;
154 d -= rhs.d;
155 return *this;
156 }
157#pragma hila loop_function
158 /// add assign ('scalar' * identity matrix)
159 template <typename A,
160 std::enable_if_t<hila::is_assignable<T &, hila::type_plus<T &, A>>::value, int> = 0>
161 inline SU2<T> &operator+=(const A rhs) {
162 d += rhs;
163 return *this;
164 }
165#pragma hila loop_function
166 /// subtract assign ('scalar' * identity matrix)
167 template <typename A,
168 std::enable_if_t<hila::is_assignable<T &, hila::type_minus<T &, A>>::value, int> = 0>
169 inline SU2<T> &operator-=(const A rhs) {
170 d -= rhs;
171 return *this;
172 }
173#pragma hila loop_function
174 /// multiply assign scalar
175 template <typename A,
176 std::enable_if_t<hila::is_assignable<T &, hila::type_mul<T &, A>>::value, int> = 0>
177 inline SU2<T> &operator*=(const A rhs) {
178 a *= rhs;
179 b *= rhs;
180 c *= rhs;
181 d *= rhs;
182 return *this;
183 }
184#pragma hila loop_function
185 /// divide assign scalar
186 template <typename A,
187 std::enable_if_t<hila::is_assignable<T &, hila::type_div<T &, A>>::value, int> = 0>
188 inline SU2<T> &operator/=(const A rhs) {
189 a /= rhs;
190 b /= rhs;
191 c /= rhs;
192 d /= rhs;
193 return *this;
194 }
195
196 /// make random SU2
197 inline SU2<T> &random(double width = 1.0) out_only {
198 double one, two;
199 one = hila::gaussrand2(two);
200 a = width*one;
201 b = width*two;
202 one = hila::gaussrand2(two);
203 c = width*one;
204 d = width*two;
205 return this->normalize();
206 }
207
208 /// make gaussian random matrix, does not normalize
209 inline SU2<T> &gaussian_random(double width = 1.0) out_only {
210 double one, two;
211 one = hila::gaussrand2(two);
212 a = width*one;
213 b = width*two;
214 one = hila::gaussrand2(two);
215 c = width*one;
216 d = width*two;
217 return *this;
218 }
219 /// project SU2 to generators $\lambda_a = 1/2 \sigma_a$
221 Algebra<SU2<T>> ret;
222 ret.a = a;
223 ret.b = b;
224 ret.c = c;
225 return 2.0 * ret; // factor of 2 from normalization, $\lambda_a = 1/2 \sigma_a$
226 }
227 /// SU2 matrix exp
228 #pragma hila novector
229 inline SU2<T> exp() const {
230 // $exp(U) = e^d*(cos(r) + sin(r)/r *(a i\sigma_1 + b i\sigma_2 + c i\sigma_3))$
231 // r = sqrt(a^2+b^2+c^2)
232 SU2<T> ret;
233 T r = ::sqrt(a * a + b * b + c * c);
234 if (r <= 0) { // TODO: c++20 [[unlikely]] / [[likely]] ?
235 ret = ::exp(d);
236 return ret;
237 }
238 T ed = ::exp(d);
239 T sr = ed * ::sin(r) / r;
240 ret.d = ed * ::cos(r);
241 ret.a *= sr;
242 ret.b *= sr;
243 ret.c *= sr;
244 return ret;
245 }
246
247 #pragma hila novector
248 /// SU2 matrix log, returns SU2 algebra
249 inline Algebra<SU2<T>> log() const {
250 //$ exp(U) = A => U = log(A)$
251 // (a,b,c) -> (a,b,c)*arcCos(r)/r
252 Algebra<SU2<T>> ret;
253 T r = ::sqrt(a * a + b * b + c * c);
254 if (r <= 0) { // TODO: c++20 [[unlikely]] / [[likely]] ?
255 ret = 0;
256 return ret;
257 }
258 r = ::acos(d) / r;
259 // factor 2 for the algebra
260 ret.a = 2.0 * r * this->a;
261 ret.b = 2.0 * r * this->b;
262 ret.c = 2.0 * r * this->c;
263 return ret;
264 }
265
266 SquareMatrix<2, Complex<T>> convert_to_2x2_matrix() const {
268 res.e(0, 0) = Complex<T>(this->d, this->c);
269 res.e(0, 1) = Complex<T>(this->b, this->a);
270 res.e(1, 0) = Complex<T>(-this->b, this->a);
271 res.e(1, 1) = Complex<T>(this->d, -this->c);
272 return res;
273 }
274};
275
276/// add two SU2's
277template <typename A, typename B, typename R = hila::type_plus<A, B>>
278inline SU2<R> operator+(const SU2<A> &lhs, const SU2<B> &rhs) {
279 SU2<R> ret;
280 ret.a = lhs.a + rhs.a;
281 ret.b = lhs.b + rhs.b;
282 ret.c = lhs.c + rhs.c;
283 ret.d = lhs.d + rhs.d;
284 return ret;
285}
286/// SU2 + ('scalar' * identity matrix)
287template <typename A, typename B,
288 std::enable_if_t<hila::is_assignable<A &, hila::type_plus<A, B>>::value, int> = 0>
289inline SU2<A> operator+(const SU2<A> &lhs, const B rhs) {
290 SU2<A> ret = lhs;
291 ret.d += rhs;
292 return ret;
293}
294/// ('scalar' * identity matrix) + SU2
295template <typename A, typename B,
296 std::enable_if_t<hila::is_assignable<B &, hila::type_plus<A, B>>::value, int> = 0>
297inline SU2<B> operator+(const A lhs, const SU2<B> &rhs) {
298 SU2<B> ret = rhs;
299 ret.d += lhs;
300 return ret;
301}
302/// subtract two SU2's
303template <typename A, typename B, typename R = hila::type_minus<A, B>>
304inline SU2<R> operator-(const SU2<A> &lhs, const SU2<B> &rhs) {
305 SU2<R> ret;
306 ret.a = lhs.a - rhs.a;
307 ret.b = lhs.b - rhs.b;
308 ret.c = lhs.c - rhs.c;
309 ret.d = lhs.d - rhs.d;
310 return ret;
311}
312/// SU2 - ('scalar' * identity matrix)
313template <typename A, typename B,
314 std::enable_if_t<hila::is_assignable<A &, hila::type_minus<A, B>>::value, int> = 0>
315inline SU2<A> operator-(const SU2<A> &lhs, const B rhs) {
316 SU2<A> ret = lhs;
317 ret.d -= rhs;
318 return ret;
319}
320/// ('scalar' * identity matrix) - SU2
321template <typename A, typename B,
322 std::enable_if_t<hila::is_assignable<B &, hila::type_minus<A, B>>::value, int> = 0>
323inline SU2<B> operator-(const A lhs, const SU2<B> &rhs) {
324 SU2<B> ret = -rhs;
325 ret.d += lhs;
326 return ret;
327}
328/// multiply two SU2's
329template <typename A, typename B, typename R = hila::type_mul<A, B>>
330inline SU2<R> operator*(const SU2<A> &x, const SU2<B> &y) {
331 SU2<R> ret;
332 ret.a = (x.d * y.a + x.a * y.d - x.b * y.c + x.c * y.b);
333 ret.b = (x.d * y.b + x.b * y.d - x.c * y.a + x.a * y.c);
334 ret.c = (x.d * y.c + x.c * y.d - x.a * y.b + x.b * y.a);
335 ret.d = (x.d * y.d - x.a * y.a - x.b * y.b - x.c * y.c);
336 return ret;
337}
338/// SU2 * scalar
339template <typename A, typename B,
340 std::enable_if_t<hila::is_assignable<A &, hila::type_mul<A, B>>::value, int> = 0>
341inline SU2<A> operator*(const SU2<A> &x, const B y) {
342 SU2<A> ret;
343 ret.a = x.a * y;
344 ret.b = x.b * y;
345 ret.c = x.c * y;
346 ret.d = x.d * y;
347 return ret;
348}
349/// scalar * SU2
350template <typename A, typename B,
351 std::enable_if_t<hila::is_assignable<A &, hila::type_mul<A, B>>::value, int> = 0>
352inline SU2<A> operator*(const B y, const SU2<A> &x) {
353 SU2<A> ret;
354 ret.a = x.a * y;
355 ret.b = x.b * y;
356 ret.c = x.c * y;
357 ret.d = x.d * y;
358 return ret;
359}
360/// SU2 / scalar
361template <typename A, typename B,
362 std::enable_if_t<hila::is_assignable<A &, hila::type_div<A, B>>::value, int> = 0>
363inline SU2<A> operator/(const SU2<A> &x, const B y) {
364 SU2<A> ret;
365 ret.a = x.a / y;
366 ret.b = x.b / y;
367 ret.c = x.c / y;
368 ret.d = x.d / y;
369 return ret;
370}
371
372template <typename T>
373inline T trace(const SU2<T> &U) {
374 return U.trace();
375}
376template <typename T>
377inline T det(const SU2<T> &U) {
378 return U.det();
379}
380template <typename T>
381inline T squarenorm(const SU2<T> &U) {
382 return U.squarenorm();
383}
384template <typename T>
385inline SU2<T> exp(const SU2<T> &U) {
386 return U.exp();
387}
388/// SU2 matrix log, returns SU2 Algebra
389template <typename T>
390inline Algebra<SU2<T>> log(const SU2<T> &U) {
391 return U.log();
392}
393/// std stream op <<
394template <typename T>
395inline std::ostream &operator<<(std::ostream &strm, const SU2<T> &U) {
396 strm << U.a << " " << U.b << " " << U.c << " " << U.d;
397 return strm;
398}
399
400/// extract SU2 from NxN complex matrix from elements (i,i), (i,j), (j,i), (j,j)
401/// i < j should be valid here! Return matrix is unnormalized
402template <typename T, int N, typename Mtype>
403inline SU2<T> project_from_matrix(const Matrix_t<N, N, Complex<T>, Mtype> &m, int i, int j) {
404 SU2<T> u;
405 u.d = (m.e(i, i).re + m.e(j, j).re) * 0.5;
406 u.c = (m.e(i, i).im - m.e(j, j).im) * 0.5;
407 u.a = (m.e(i, j).im + m.e(j, i).im) * 0.5;
408 u.b = (m.e(i, j).re - m.e(j, i).re) * 0.5;
409 return u;
410}
411
412
413// SU2 * vector (vec can be complex or real)
414template <typename A, typename B>
415inline auto operator*(const SU2<A> &lhs, const Vector<2,B> &rhs) {
416 return lhs.convert_to_2x2_matrix() * rhs;
417}
418
419// horizontalvector * SU2 (vec can be complex or real)
420template <typename A, typename B>
421inline auto operator*(const RowVector<2,B> &lhs, const SU2<A> &rhs) {
422 return rhs * lhs.convert_to_2x2_matrix();
423}
424
425
426/// This implementation represents algebra as
427/// $ a i/2\sigma_1 + b i/2\sigma_2 + c i/2\sigma_3$
428template <typename T>
429class Algebra<SU2<T>> {
430 public: // public on purpose
431 T a, b, c;
432
433 public:
434 using base_type = T;
435 using argument_type = T;
436
437 Algebra() = default;
438 ~Algebra() = default;
439 Algebra(const Algebra &) = default;
440 /// construct from 0
441 Algebra(const std::nullptr_t &z) {
442 a = 0;
443 b = 0;
444 c = 0;
445 }
446 /// unary -
447 inline Algebra<SU2<T>> operator-() const {
448 Algebra<SU2<T>> res;
449 res.a = -a;
450 res.b = -b;
451 res.c = -c;
452 return res;
453 }
454 /// unary +
455 inline Algebra<SU2<T>> operator+() const {
456 return *this;
457 }
458#pragma hila loop_function
459 /// assign from another Algebra<SU2>
460 template <typename A, std::enable_if_t<hila::is_assignable<T &, A>::value, int> = 0>
461 inline Algebra<SU2<T>> &operator=(const Algebra<SU2<A>> &rhs) out_only {
462 a = rhs.a;
463 b = rhs.b;
464 c = rhs.c;
465 return *this;
466 }
467#pragma hila loop_function
468 /// assign from initializer list
469 template <typename S, std::enable_if_t<hila::is_assignable<T &, S>::value, int> = 0>
470 inline Algebra<SU2<T>> &operator=(std::initializer_list<S> rhs) out_only {
471 assert(rhs.size() == 3 && "Algebra<SU2> initializer list size must be 3");
472 auto it = rhs.begin();
473 a = *(it++);
474 b = *(it++);
475 c = *(it);
476 }
477#pragma hila loop_function
478 /// assign from zero
479 inline Algebra<SU2<T>> &operator=(const std::nullptr_t &z) out_only {
480 a = 0;
481 b = 0;
482 c = 0;
483 return *this;
484 }
485#pragma hila loop_function
486 /// add assign another Algebra<SU2>
487 template <typename A,
488 std::enable_if_t<hila::is_assignable<T &, hila::type_plus<T &, A>>::value, int> = 0>
489 inline Algebra<SU2<T>> &operator+=(const Algebra<SU2<A>> &rhs) {
490 a += rhs.a;
491 b += rhs.b;
492 c += rhs.c;
493 return *this;
494 }
495#pragma hila loop_function
496 /// subtract assign another Algebra<SU2>
497 template <typename A,
498 std::enable_if_t<hila::is_assignable<T &, hila::type_minus<T &, A>>::value, int> = 0>
499 inline Algebra<SU2<T>> &operator-=(const Algebra<SU2<A>> &rhs) {
500 a -= rhs.a;
501 b -= rhs.b;
502 c -= rhs.c;
503 return *this;
504 }
505#pragma hila loop_function
506 /// multiply assign scalar
507 template <typename A,
508 std::enable_if_t<hila::is_assignable<T &, hila::type_mul<T &, A>>::value, int> = 0>
509 inline Algebra<SU2<T>> &operator*=(const A rhs) {
510 a *= rhs;
511 b *= rhs;
512 c *= rhs;
513 return *this;
514 }
515#pragma hila loop_function
516 /// divide assign scalar
517 template <typename A,
518 std::enable_if_t<hila::is_assignable<T &, hila::type_div<T &, A>>::value, int> = 0>
519 inline Algebra<SU2<T>> &operator/=(const A rhs) {
520 a /= rhs;
521 b /= rhs;
522 c /= rhs;
523 return *this;
524 }
525 /// a^2 + b^2 + c^2
526 inline T squarenorm() const {
527 return a * a + b * b + c * c;
528 }
529 /// Expand algebra to SU2
530 inline SU2<T> expand() const {
531 SU2<T> ret;
532 ret.a = a;
533 ret.b = b;
534 ret.c = c;
535 ret.d = 0;
536 return ret * 0.5; // factor of 1/2 from normalization, $\lambda_a = 1/2 \sigma_a$
537 }
538 /// SU2 Algebra $exp( E ) = exp( i 1/2 a_n\sigma_n )$ , returns SU2
539 inline SU2<T> exp() const {
540 // $U = exp(E) = (cos(r) + sin(r)/r *(a i\sigma_1 + b i\sigma_2 + c i\sigma_3))$
541 // r = sqrt(a^2+b^2+c^2)
542 Algebra<SU2<T>> tmp =
543 (*this) * 0.5; // factor of 1/2 from normalization, $\lambda_a = 1/2 \sigma_a$
544 SU2<T> ret;
545 T r = sqrt(tmp.squarenorm());
546 if (r <= 0) { // TODO: c++20 [[unlikely]] / [[likely]] ?
547 ret = 1;
548 return ret;
549 }
550 T sr = sin(r) / r;
551 ret.d = cos(r);
552 ret.a = sr * tmp.a;
553 ret.b = sr * tmp.b;
554 ret.c = sr * tmp.c;
555 return ret;
556 }
557 ///
558 inline Algebra<SU2<T>> &gaussian_random(double width = 1.0) out_only {
559 T one, two;
560 one = hila::gaussrand2(two);
561 a = width * one;
562 b = width * two;
563 c = width * hila::gaussrand();
564 return *this;
565 }
566};
567
568/// add two Algebra<SU2>'s
569template <typename A, typename B, typename R = hila::type_plus<A, B>>
570inline Algebra<SU2<R>> operator+(const Algebra<SU2<A>> &lhs, const Algebra<SU2<B>> &rhs) {
571 Algebra<SU2<R>> ret;
572 ret.a = lhs.a + rhs.a;
573 ret.b = lhs.b + rhs.b;
574 ret.c = lhs.c + rhs.c;
575 return ret;
576}
577/// subtract two Algebra<SU2>'s
578template <typename A, typename B, typename R = hila::type_minus<A, B>>
579inline Algebra<SU2<R>> operator-(const Algebra<SU2<A>> &lhs, const Algebra<SU2<B>> &rhs) {
580 Algebra<SU2<R>> ret;
581 ret.a = lhs.a - rhs.a;
582 ret.b = lhs.b - rhs.b;
583 ret.c = lhs.c - rhs.c;
584 return ret;
585}
586
587/// Algebra<SU2> * scalar
588template <typename A, typename B,
589 std::enable_if_t<hila::is_assignable<A &, hila::type_mul<A, B>>::value, int> = 0>
590inline Algebra<SU2<A>> operator*(const Algebra<SU2<A>> &x, const B y) {
591 Algebra<SU2<A>> ret;
592 ret.a = x.a * y;
593 ret.b = x.b * y;
594 ret.c = x.c * y;
595 return ret;
596}
597/// scalar * Algebra<SU2>
598template <typename A, typename B,
599 std::enable_if_t<hila::is_assignable<A &, hila::type_mul<A, B>>::value, int> = 0>
600inline Algebra<SU2<A>> operator*(const B y, const Algebra<SU2<A>> &x) {
601 Algebra<SU2<A>> ret;
602 ret.a = x.a * y;
603 ret.b = x.b * y;
604 ret.c = x.c * y;
605 return ret;
606}
607/// Algebra<SU2> / scalar
608template <typename A, typename B,
609 std::enable_if_t<hila::is_assignable<A &, hila::type_div<A, B>>::value, int> = 0>
610inline Algebra<SU2<A>> operator/(const Algebra<SU2<A>> &x, const B y) {
611 Algebra<SU2<A>> ret;
612 ret.a = x.a / y;
613 ret.b = x.b / y;
614 ret.c = x.c / y;
615 return ret;
616}
617
618/// $U^\dagger E U$ transport up
619template <typename T>
620inline Algebra<SU2<T>> right_conjugation(const SU2<T> &U, const Algebra<SU2<T>> &E) {
621 Algebra<SU2<T>> res;
622 T t1 = 2.0 * U.d;
623 T t3 = t1 * U.d - 1.0;
624 T t2 = 2.0 * (E.a * U.a + E.b * U.b + E.c * U.c);
625 res.a = E.a * t3 + U.a * t2 - t1 * (E.b * U.c - E.c * U.b);
626 res.b = E.b * t3 + U.b * t2 - t1 * (E.c * U.a - E.a * U.c);
627 res.c = E.c * t3 + U.c * t2 - t1 * (E.a * U.b - E.b * U.a);
628 return res;
629}
630
631/// $U E U^\dagger$ transport down
632template <typename T>
633inline Algebra<SU2<T>> left_conjugation(const SU2<T> &U, const Algebra<SU2<T>> &E) {
634 Algebra<SU2<T>> res;
635 T t1 = 2.0 * U.d;
636 T t3 = t1 * U.d - 1.0;
637 T t2 = 2.0 * (E.a * U.a + E.b * U.b + E.c * U.c);
638 res.a = E.a * t3 + U.a * t2 + t1 * (E.b * U.c - E.c * U.b);
639 res.b = E.b * t3 + U.b * t2 + t1 * (E.c * U.a - E.a * U.c);
640 res.c = E.c * t3 + U.c * t2 + t1 * (E.a * U.b - E.b * U.a);
641 return res;
642}
643
644template <typename T>
645inline T squarenorm(const Algebra<SU2<T>> &E) {
646 return E.squarenorm();
647}
648
649template <typename T>
650inline SU2<T> exp(const Algebra<SU2<T>> &E) {
651 return E.exp();
652}
653
654/// std stream op <<
655template <typename T>
656inline std::ostream &operator<<(std::ostream &strm, const Algebra<SU2<T>> &E) {
657 strm << E.a << " " << E.b << " " << E.c;
658 return strm;
659}
660
661namespace hila {
662template <typename T>
663std::string prettyprint(const SU2<T> &A, int prec = 8) {
664 std::stringstream strm;
665 strm.precision(prec);
666
667 strm << "[ " << A.d << u8" 𝟙 + " << A.a << u8" iσ₁ + " << A.b << u8" iσ₂ + " << A.c << u8" iσ₃ ]";
668 return strm.str();
669}
670template <typename T>
671std::string prettyprint(const Algebra<SU2<T>> &A, int prec = 8) {
672 std::stringstream strm;
673 strm.precision(prec);
674
675 strm << "[ " << A.a << u8" ½iσ₁ + " << A.b << u8" ½iσ₂ + " << A.c << u8" ½iσ₃ ]";
676 return strm.str();
677}
678} // namespace hila
679
680
681// SU2 matrix multiplication routines ------------------------
682//#define nn_a(x, y) (x.d * y.a + x.a * y.d - x.b * y.c + x.c * y.b)
683//#define nn_b(x, y) (x.d * y.b + x.b * y.d - x.c * y.a + x.a * y.c)
684//#define nn_c(x, y) (x.d * y.c + x.c * y.d - x.a * y.b + x.b * y.a)
685//#define nn_d(x, y) (x.d * y.d - x.a * y.a - x.b * y.b - x.c * y.c)
686//
687//#define na_a(x, y) (-x.d * y.a + x.a * y.d + x.b * y.c - x.c * y.b)
688//#define na_b(x, y) (-x.d * y.b + x.b * y.d + x.c * y.a - x.a * y.c)
689//#define na_c(x, y) (-x.d * y.c + x.c * y.d + x.a * y.b - x.b * y.a)
690//#define na_d(x, y) (x.d * y.d + x.a * y.a + x.b * y.b + x.c * y.c)
691//
692//#define an_a(x, y) (x.d * y.a - x.a * y.d + x.b * y.c - x.c * y.b)
693//#define an_b(x, y) (x.d * y.b - x.b * y.d + x.c * y.a - x.a * y.c)
694//#define an_c(x, y) (x.d * y.c - x.c * y.d + x.a * y.b - x.b * y.a)
695//#define an_d(x, y) (x.d * y.d + x.a * y.a + x.b * y.b + x.c * y.c)
696//
697//#define aa_a(x, y) (-x.d * y.a - x.a * y.d - x.b * y.c + x.c * y.b)
698//#define aa_b(x, y) (-x.d * y.b - x.b * y.d - x.c * y.a + x.a * y.c)
699//#define aa_c(x, y) (-x.d * y.c - x.c * y.d - x.a * y.b + x.b * y.a)
700//#define aa_d(x, y) (x.d * y.d - x.a * y.a - x.b * y.b - x.c * y.c)
701
702#endif // SU2_H_
std::ostream & operator<<(std::ostream &strm, const Array< n, m, T > &A)
Stream operator.
Definition array.h:916
hila::arithmetic_type< T > squarenorm(const Array< n, m, T > &rhs)
Return square norm of Array.
Definition array.h:957
Algebra< SU2< T > > & operator=(std::initializer_list< S > rhs)
assign from initializer list
Definition su2.h:470
Algebra< SU2< T > > & operator=(const std::nullptr_t &z)
assign from zero
Definition su2.h:479
Algebra< SU2< T > > & operator=(const Algebra< SU2< A > > &rhs)
assign from another Algebra<SU2>
Definition su2.h:461
Algebra< SU2< T > > & operator/=(const A rhs)
divide assign scalar
Definition su2.h:519
Algebra< SU2< T > > & operator*=(const A rhs)
multiply assign scalar
Definition su2.h:509
Algebra< SU2< T > > operator+() const
unary +
Definition su2.h:455
Algebra< SU2< T > > & operator-=(const Algebra< SU2< A > > &rhs)
subtract assign another Algebra<SU2>
Definition su2.h:499
Algebra< SU2< T > > operator-() const
unary -
Definition su2.h:447
Algebra(const std::nullptr_t &z)
construct from 0
Definition su2.h:441
SU2< T > exp() const
SU2 Algebra $exp( E ) = exp( i 1/2 a_n\sigma_n )$ , returns SU2.
Definition su2.h:539
T squarenorm() const
a^2 + b^2 + c^2
Definition su2.h:526
SU2< T > expand() const
Expand algebra to SU2.
Definition su2.h:530
Algebra< SU2< T > > & operator+=(const Algebra< SU2< A > > &rhs)
add assign another Algebra<SU2>
Definition su2.h:489
Definition su2.h:7
Complex definition.
Definition cmplx.h:50
The main matrix type template Matrix_t. This is a base class type for "useful" types which are deriv...
Definition matrix.h:102
T c[n *m]
The data as a one dimensional array.
Definition matrix.h:106
T e(const int i, const int j) const
Standard array indexing operation for matrices.
Definition matrix.h:272
Matrix class which defines matrix operations.
Definition matrix.h:1679
Definition su2.h:14
Algebra< SU2< T > > project_to_algebra() const
project SU2 to generators $\lambda_a = 1/2 \sigma_a$
Definition su2.h:220
SU2< T > & random(double width=1.0)
make random SU2
Definition su2.h:197
SU2< T > & operator=(const SU2< A > &rhs)
assign from another SU2
Definition su2.h:107
SU2< T > & operator+=(const SU2< A > &rhs)
add assign another SU2
Definition su2.h:139
SU2(const B z)
construct from 'scalar'
Definition su2.h:30
SU2< T > & operator*=(const A rhs)
multiply assign scalar
Definition su2.h:177
T trace() const
for SU2 same as .dagger()
Definition su2.h:78
SU2< T > & operator-=(const SU2< A > &rhs)
subtract assign another SU2
Definition su2.h:150
SU2< T > & operator-=(const A rhs)
subtract assign ('scalar' * identity matrix)
Definition su2.h:169
SU2< T > & operator=(A rhs)
assign from 'scalar'
Definition su2.h:128
SU2< T > operator+() const
unary +
Definition su2.h:101
SU2< T > operator-() const
unary -
Definition su2.h:92
SU2< T > & normalize()
Normalize det = 1 to make sure it's an element of SU2.
Definition su2.h:47
SU2< T > & reunitarize()
Normalize det = 1 to make sure it's an element of SU2.
Definition su2.h:60
SU2< T > & operator/=(const A rhs)
divide assign scalar
Definition su2.h:188
SU2< T > dagger() const
complex conjugate transpose
Definition su2.h:64
SU2(std::initializer_list< S > rhs)
initializer list constructor
Definition su2.h:38
SU2< T > & gaussian_random(double width=1.0)
make gaussian random matrix, does not normalize
Definition su2.h:209
Algebra< SU2< T > > log() const
SU2 matrix log, returns SU2 algebra.
Definition su2.h:249
SU2< T > exp() const
SU2 matrix exp.
Definition su2.h:229
SU2< T > & operator=(std::initializer_list< S > rhs)
assign from initializer list
Definition su2.h:117
SU2< T > & operator+=(const A rhs)
add assign ('scalar' * identity matrix)
Definition su2.h:161
Definition of Matrix types.
Invert diagonal + const. matrix using Sherman-Morrison formula.
Definition array.h:920
logger_class log
Now declare the logger.
double gaussrand()
Gaussian random generation routine.
Definition random.cpp:212
double gaussrand2(double &out2)
hila::gaussrand2 returns 2 Gaussian distributed random numbers with variance .
Definition random.cpp:177