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 lhs * rhs.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 return *this;
477 }
478#pragma hila loop_function
479 /// assign from zero
480 inline Algebra<SU2<T>> &operator=(const std::nullptr_t &z) out_only {
481 a = 0;
482 b = 0;
483 c = 0;
484 return *this;
485 }
486#pragma hila loop_function
487 /// add assign another Algebra<SU2>
488 template <typename A,
489 std::enable_if_t<hila::is_assignable<T &, hila::type_plus<T &, A>>::value, int> = 0>
490 inline Algebra<SU2<T>> &operator+=(const Algebra<SU2<A>> &rhs) {
491 a += rhs.a;
492 b += rhs.b;
493 c += rhs.c;
494 return *this;
495 }
496#pragma hila loop_function
497 /// subtract assign another Algebra<SU2>
498 template <typename A,
499 std::enable_if_t<hila::is_assignable<T &, hila::type_minus<T &, A>>::value, int> = 0>
500 inline Algebra<SU2<T>> &operator-=(const Algebra<SU2<A>> &rhs) {
501 a -= rhs.a;
502 b -= rhs.b;
503 c -= rhs.c;
504 return *this;
505 }
506#pragma hila loop_function
507 /// multiply assign scalar
508 template <typename A,
509 std::enable_if_t<hila::is_assignable<T &, hila::type_mul<T &, A>>::value, int> = 0>
510 inline Algebra<SU2<T>> &operator*=(const A rhs) {
511 a *= rhs;
512 b *= rhs;
513 c *= rhs;
514 return *this;
515 }
516#pragma hila loop_function
517 /// divide assign scalar
518 template <typename A,
519 std::enable_if_t<hila::is_assignable<T &, hila::type_div<T &, A>>::value, int> = 0>
520 inline Algebra<SU2<T>> &operator/=(const A rhs) {
521 a /= rhs;
522 b /= rhs;
523 c /= rhs;
524 return *this;
525 }
526 /// a^2 + b^2 + c^2
527 inline T squarenorm() const {
528 return a * a + b * b + c * c;
529 }
530 /// Expand algebra to SU2
531 inline SU2<T> expand() const {
532 SU2<T> ret;
533 ret.a = a;
534 ret.b = b;
535 ret.c = c;
536 ret.d = 0;
537 return ret * 0.5; // factor of 1/2 from normalization, $\lambda_a = 1/2 \sigma_a$
538 }
539 /// SU2 Algebra $exp( E ) = exp( i 1/2 a_n\sigma_n )$ , returns SU2
540 inline SU2<T> exp() const {
541 // $U = exp(E) = (cos(r) + sin(r)/r *(a i\sigma_1 + b i\sigma_2 + c i\sigma_3))$
542 // r = sqrt(a^2+b^2+c^2)
543 Algebra<SU2<T>> tmp =
544 (*this) * 0.5; // factor of 1/2 from normalization, $\lambda_a = 1/2 \sigma_a$
545 SU2<T> ret;
546 T r = sqrt(tmp.squarenorm());
547 if (r <= 0) { // TODO: c++20 [[unlikely]] / [[likely]] ?
548 ret = 1;
549 return ret;
550 }
551 T sr = sin(r) / r;
552 ret.d = cos(r);
553 ret.a = sr * tmp.a;
554 ret.b = sr * tmp.b;
555 ret.c = sr * tmp.c;
556 return ret;
557 }
558 ///
559 inline Algebra<SU2<T>> &gaussian_random(double width = 1.0) out_only {
560 T one, two;
561 one = hila::gaussrand2(two);
562 a = width * one;
563 b = width * two;
564 c = width * hila::gaussrand();
565 return *this;
566 }
567};
568
569/// add two Algebra<SU2>'s
570template <typename A, typename B, typename R = hila::type_plus<A, B>>
571inline Algebra<SU2<R>> operator+(const Algebra<SU2<A>> &lhs, const Algebra<SU2<B>> &rhs) {
572 Algebra<SU2<R>> ret;
573 ret.a = lhs.a + rhs.a;
574 ret.b = lhs.b + rhs.b;
575 ret.c = lhs.c + rhs.c;
576 return ret;
577}
578/// subtract two Algebra<SU2>'s
579template <typename A, typename B, typename R = hila::type_minus<A, B>>
580inline Algebra<SU2<R>> operator-(const Algebra<SU2<A>> &lhs, const Algebra<SU2<B>> &rhs) {
581 Algebra<SU2<R>> ret;
582 ret.a = lhs.a - rhs.a;
583 ret.b = lhs.b - rhs.b;
584 ret.c = lhs.c - rhs.c;
585 return ret;
586}
587
588/// Algebra<SU2> * scalar
589template <typename A, typename B,
590 std::enable_if_t<hila::is_assignable<A &, hila::type_mul<A, B>>::value, int> = 0>
591inline Algebra<SU2<A>> operator*(const Algebra<SU2<A>> &x, const B y) {
592 Algebra<SU2<A>> ret;
593 ret.a = x.a * y;
594 ret.b = x.b * y;
595 ret.c = x.c * y;
596 return ret;
597}
598/// scalar * Algebra<SU2>
599template <typename A, typename B,
600 std::enable_if_t<hila::is_assignable<A &, hila::type_mul<A, B>>::value, int> = 0>
601inline Algebra<SU2<A>> operator*(const B y, const Algebra<SU2<A>> &x) {
602 Algebra<SU2<A>> ret;
603 ret.a = x.a * y;
604 ret.b = x.b * y;
605 ret.c = x.c * y;
606 return ret;
607}
608/// Algebra<SU2> / scalar
609template <typename A, typename B,
610 std::enable_if_t<hila::is_assignable<A &, hila::type_div<A, B>>::value, int> = 0>
611inline Algebra<SU2<A>> operator/(const Algebra<SU2<A>> &x, const B y) {
612 Algebra<SU2<A>> ret;
613 ret.a = x.a / y;
614 ret.b = x.b / y;
615 ret.c = x.c / y;
616 return ret;
617}
618
619/// $U^\dagger E U$ transport up
620template <typename T>
621inline Algebra<SU2<T>> right_conjugation(const SU2<T> &U, const Algebra<SU2<T>> &E) {
622 Algebra<SU2<T>> res;
623 T t1 = 2.0 * U.d;
624 T t3 = t1 * U.d - 1.0;
625 T t2 = 2.0 * (E.a * U.a + E.b * U.b + E.c * U.c);
626 res.a = E.a * t3 + U.a * t2 - t1 * (E.b * U.c - E.c * U.b);
627 res.b = E.b * t3 + U.b * t2 - t1 * (E.c * U.a - E.a * U.c);
628 res.c = E.c * t3 + U.c * t2 - t1 * (E.a * U.b - E.b * U.a);
629 return res;
630}
631
632/// $U E U^\dagger$ transport down
633template <typename T>
634inline Algebra<SU2<T>> left_conjugation(const SU2<T> &U, const Algebra<SU2<T>> &E) {
635 Algebra<SU2<T>> res;
636 T t1 = 2.0 * U.d;
637 T t3 = t1 * U.d - 1.0;
638 T t2 = 2.0 * (E.a * U.a + E.b * U.b + E.c * U.c);
639 res.a = E.a * t3 + U.a * t2 + t1 * (E.b * U.c - E.c * U.b);
640 res.b = E.b * t3 + U.b * t2 + t1 * (E.c * U.a - E.a * U.c);
641 res.c = E.c * t3 + U.c * t2 + t1 * (E.a * U.b - E.b * U.a);
642 return res;
643}
644
645/// dot product for SU2 algebra: A dot B = A^a B^a = -2 Tr( A^a T^a B^b T^b )
646template<typename T>
647inline T su2_algebra_dot(const Algebra<SU2<T>> &A, const Algebra<SU2<T>> &B) {
648 return A.a * B.a + A.b * B.b + A.c*B.c;
649}
650
651template <typename T>
652inline T squarenorm(const Algebra<SU2<T>> &E) {
653 return E.squarenorm();
654}
655
656template <typename T>
657inline SU2<T> exp(const Algebra<SU2<T>> &E) {
658 return E.exp();
659}
660
661/// std stream op <<
662template <typename T>
663inline std::ostream &operator<<(std::ostream &strm, const Algebra<SU2<T>> &E) {
664 strm << E.a << " " << E.b << " " << E.c;
665 return strm;
666}
667
668namespace hila {
669template <typename T>
670std::string prettyprint(const SU2<T> &A, int prec = 8) {
671 std::stringstream strm;
672 strm.precision(prec);
673
674 strm << "[ " << A.d << u8" 𝟙 + " << A.a << u8" iσ₁ + " << A.b << u8" iσ₂ + " << A.c << u8" iσ₃ ]";
675 return strm.str();
676}
677template <typename T>
678std::string prettyprint(const Algebra<SU2<T>> &A, int prec = 8) {
679 std::stringstream strm;
680 strm.precision(prec);
681
682 strm << "[ " << A.a << u8" ½iσ₁ + " << A.b << u8" ½iσ₂ + " << A.c << u8" ½iσ₃ ]";
683 return strm.str();
684}
685} // namespace hila
686
687
688// SU2 matrix multiplication routines ------------------------
689//#define nn_a(x, y) (x.d * y.a + x.a * y.d - x.b * y.c + x.c * y.b)
690//#define nn_b(x, y) (x.d * y.b + x.b * y.d - x.c * y.a + x.a * y.c)
691//#define nn_c(x, y) (x.d * y.c + x.c * y.d - x.a * y.b + x.b * y.a)
692//#define nn_d(x, y) (x.d * y.d - x.a * y.a - x.b * y.b - x.c * y.c)
693//
694//#define na_a(x, y) (-x.d * y.a + x.a * y.d + x.b * y.c - x.c * y.b)
695//#define na_b(x, y) (-x.d * y.b + x.b * y.d + x.c * y.a - x.a * y.c)
696//#define na_c(x, y) (-x.d * y.c + x.c * y.d + x.a * y.b - x.b * y.a)
697//#define na_d(x, y) (x.d * y.d + x.a * y.a + x.b * y.b + x.c * y.c)
698//
699//#define an_a(x, y) (x.d * y.a - x.a * y.d + x.b * y.c - x.c * y.b)
700//#define an_b(x, y) (x.d * y.b - x.b * y.d + x.c * y.a - x.a * y.c)
701//#define an_c(x, y) (x.d * y.c - x.c * y.d + x.a * y.b - x.b * y.a)
702//#define an_d(x, y) (x.d * y.d + x.a * y.a + x.b * y.b + x.c * y.c)
703//
704//#define aa_a(x, y) (-x.d * y.a - x.a * y.d - x.b * y.c + x.c * y.b)
705//#define aa_b(x, y) (-x.d * y.b - x.b * y.d - x.c * y.a + x.a * y.c)
706//#define aa_c(x, y) (-x.d * y.c - x.c * y.d - x.a * y.b + x.b * y.a)
707//#define aa_d(x, y) (x.d * y.d - x.a * y.a - x.b * y.b - x.c * y.c)
708
709#endif // SU2_H_
auto operator/(const Array< n, m, A > &a, const Array< n, m, B > &b)
Division operator.
Definition array.h:916
std::ostream & operator<<(std::ostream &strm, const Array< n, m, T > &A)
Stream operator.
Definition array.h:977
auto operator-(const Array< n, m, A > &a, const Array< n, m, B > &b)
Subtraction operator.
Definition array.h:781
Array< n, m, T > exp(Array< n, m, T > a)
Exponential.
Definition array.h:1059
hila::arithmetic_type< T > squarenorm(const Array< n, m, T > &rhs)
Return square norm of Array.
Definition array.h:1018
auto operator+(const Array< n, m, A > &a, const Array< n, m, B > &b)
Addition operator.
Definition array.h:740
Array< n, m, T > cos(Array< n, m, T > a)
Cosine.
Definition array.h:1089
Array< n, m, T > acos(Array< n, m, T > a)
Inverse Cosine.
Definition array.h:1119
Array< n, m, T > sqrt(Array< n, m, T > a)
Square root.
Definition array.h:1039
Array< n, m, T > operator*(Array< n, m, T > a, const Array< n, m, T > &b)
Multiplication operator.
Definition array.h:861
Array< n, m, T > sin(Array< n, m, T > a)
Sine.
Definition array.h:1079
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:480
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:520
Algebra< SU2< T > > & operator*=(const A rhs)
multiply assign scalar
Definition su2.h:510
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:500
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:540
T squarenorm() const
a^2 + b^2 + c^2
Definition su2.h:527
SU2< T > expand() const
Expand algebra to SU2.
Definition su2.h:531
Algebra< SU2< T > > & operator+=(const Algebra< SU2< A > > &rhs)
add assign another Algebra<SU2>
Definition su2.h:490
Definition su2.h:7
Complex definition.
Definition cmplx.h:56
The main matrix type template Matrix_t. This is a base class type for "useful" types which are deriv...
Definition matrix.h:106
T c[n *m]
The data as a one dimensional array.
Definition matrix.h:110
T e(const int i, const int j) const
Standard array indexing operation for matrices and vectors.
Definition matrix.h:286
Matrix class which defines matrix operations.
Definition matrix.h:1620
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.
Implement hila::swap for gauge fields.
Definition array.h:981
logger_class log
Now declare the logger.
double gaussrand()
Gaussian random generation routine.
Definition random.cpp:216
double gaussrand2(double &out2)
hila::gaussrand2 returns 2 Gaussian distributed random numbers with variance .
Definition random.cpp:181