15 static_assert(hila::is_floating_point<T>::value,
"SU2 requires a floating point type");
22 using argument_type = T;
26 SU2(
const SU2 &) =
default;
29 template <typename B, std::enable_if_t<hila::is_assignable<T &, B>::value,
int> = 0>
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();
48 T len =
sqrt(this->det());
82 inline T det()
const {
83 return a * a + b * b + c * c + d * d;
85 inline T squarenorm()
const {
88 static constexpr int size() {
104#pragma hila loop_function
106 template <typename A, std::enable_if_t<hila::is_assignable<T &, A>::value,
int> = 0>
114#pragma hila loop_function
116 template <typename S, std::enable_if_t<hila::is_assignable<T &, S>::value,
int> = 0>
118 assert(rhs.size() == 4 &&
"SU2 initializer list size must be 4");
119 auto it = rhs.begin();
125#pragma hila loop_function
127 template <typename A, std::enable_if_t<hila::is_assignable<T &, A>::value,
int> = 0>
135#pragma hila loop_function
137 template <
typename A,
138 std::enable_if_t<hila::is_assignable<T &, hila::type_plus<T &, A>>::value,
int> = 0>
146#pragma hila loop_function
148 template <
typename A,
149 std::enable_if_t<hila::is_assignable<T &, hila::type_minus<T &, A>>::value,
int> = 0>
157#pragma hila loop_function
159 template <
typename A,
160 std::enable_if_t<hila::is_assignable<T &, hila::type_plus<T &, A>>::value,
int> = 0>
165#pragma hila loop_function
167 template <
typename A,
168 std::enable_if_t<hila::is_assignable<T &, hila::type_minus<T &, A>>::value,
int> = 0>
173#pragma hila loop_function
175 template <
typename A,
176 std::enable_if_t<hila::is_assignable<T &, hila::type_mul<T &, A>>::value,
int> = 0>
184#pragma hila loop_function
186 template <
typename A,
187 std::enable_if_t<hila::is_assignable<T &, hila::type_div<T &, A>>::value,
int> = 0>
228 #pragma hila novector
233 T r =
::sqrt(a * a + b * b + c * c);
239 T sr = ed *
::sin(r) / r;
240 ret.d = ed *
::cos(r);
247 #pragma hila novector
253 T r =
::sqrt(a * a + b * b + c * c);
260 ret.a = 2.0 * r * this->a;
261 ret.b = 2.0 * r * this->b;
262 ret.c = 2.0 * r * this->c;
277template <
typename A,
typename B,
typename R = hila::type_plus<A, B>>
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;
287template <
typename A,
typename B,
288 std::enable_if_t<hila::is_assignable<A &, hila::type_plus<A, B>>::value,
int> = 0>
295template <
typename A,
typename B,
296 std::enable_if_t<hila::is_assignable<B &, hila::type_plus<A, B>>::value,
int> = 0>
303template <
typename A,
typename B,
typename R = hila::type_minus<A, B>>
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;
313template <
typename A,
typename B,
314 std::enable_if_t<hila::is_assignable<A &, hila::type_minus<A, B>>::value,
int> = 0>
321template <
typename A,
typename B,
322 std::enable_if_t<hila::is_assignable<B &, hila::type_minus<A, B>>::value,
int> = 0>
329template <
typename A,
typename B,
typename R = hila::type_mul<A, B>>
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);
339template <
typename A,
typename B,
340 std::enable_if_t<hila::is_assignable<A &, hila::type_mul<A, B>>::value,
int> = 0>
350template <
typename A,
typename B,
351 std::enable_if_t<hila::is_assignable<A &, hila::type_mul<A, B>>::value,
int> = 0>
361template <
typename A,
typename B,
362 std::enable_if_t<hila::is_assignable<A &, hila::type_div<A, B>>::value,
int> = 0>
373inline T trace(
const SU2<T> &U) {
377inline T det(
const SU2<T> &U) {
382 return U.squarenorm();
396 strm << U.a <<
" " << U.b <<
" " << U.c <<
" " << U.d;
402template <
typename T,
int N,
typename Mtype>
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;
414template <
typename A,
typename B>
416 return lhs.convert_to_2x2_matrix() * rhs;
420template <
typename A,
typename B>
422 return lhs * rhs.convert_to_2x2_matrix();
435 using argument_type = T;
458#pragma hila loop_function
460 template <typename A, std::enable_if_t<hila::is_assignable<T &, A>::value,
int> = 0>
467#pragma hila loop_function
469 template <typename S, std::enable_if_t<hila::is_assignable<T &, S>::value,
int> = 0>
471 assert(rhs.size() == 3 &&
"Algebra<SU2> initializer list size must be 3");
472 auto it = rhs.begin();
478#pragma hila loop_function
486#pragma hila loop_function
488 template <
typename A,
489 std::enable_if_t<hila::is_assignable<T &, hila::type_plus<T &, A>>::value,
int> = 0>
496#pragma hila loop_function
498 template <
typename A,
499 std::enable_if_t<hila::is_assignable<T &, hila::type_minus<T &, A>>::value,
int> = 0>
506#pragma hila loop_function
508 template <
typename A,
509 std::enable_if_t<hila::is_assignable<T &, hila::type_mul<T &, A>>::value,
int> = 0>
516#pragma hila loop_function
518 template <
typename A,
519 std::enable_if_t<hila::is_assignable<T &, hila::type_div<T &, A>>::value,
int> = 0>
528 return a * a + b * b + c * c;
546 T r =
sqrt(tmp.squarenorm());
559 inline Algebra<SU2<T>> &gaussian_random(
double width = 1.0) out_only {
570template <
typename A,
typename B,
typename R = hila::type_plus<A, B>>
573 ret.a = lhs.a + rhs.a;
574 ret.b = lhs.b + rhs.b;
575 ret.c = lhs.
c + rhs.c;
579template <
typename A,
typename B,
typename R = hila::type_minus<A, B>>
582 ret.a = lhs.a - rhs.a;
583 ret.b = lhs.b - rhs.b;
584 ret.c = lhs.
c - rhs.c;
589template <
typename A,
typename B,
590 std::enable_if_t<hila::is_assignable<A &, hila::type_mul<A, B>>::value,
int> = 0>
599template <
typename A,
typename B,
600 std::enable_if_t<hila::is_assignable<A &, hila::type_mul<A, B>>::value,
int> = 0>
609template <
typename A,
typename B,
610 std::enable_if_t<hila::is_assignable<A &, hila::type_div<A, B>>::value,
int> = 0>
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);
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);
648 return A.a * B.a + A.b * B.b + A.c*B.c;
653 return E.squarenorm();
664 strm << E.a <<
" " << E.b <<
" " << E.c;
670std::string prettyprint(
const SU2<T> &A,
int prec = 8) {
671 std::stringstream strm;
672 strm.precision(prec);
674 strm <<
"[ " << A.d << u8
" 𝟙 + " << A.a << u8
" iσ₁ + " << A.b << u8
" iσ₂ + " << A.c << u8
" iσ₃ ]";
678std::string prettyprint(
const Algebra<
SU2<T>> &A,
int prec = 8) {
679 std::stringstream strm;
680 strm.precision(prec);
682 strm <<
"[ " << A.a << u8
" ½iσ₁ + " << A.b << u8
" ½iσ₂ + " << A.c << u8
" ½iσ₃ ]";
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.
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.
hila::arithmetic_type< T > squarenorm(const Array< n, m, T > &rhs)
Return square norm of Array.
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 > acos(Array< n, m, T > a)
Inverse Cosine.
Array< n, m, T > sqrt(Array< n, m, T > a)
Square root.
Array< n, m, T > operator*(Array< n, m, T > a, const Array< n, m, T > &b)
Multiplication operator.
Array< n, m, T > sin(Array< n, m, T > a)
Sine.
Algebra< SU2< T > > & operator=(std::initializer_list< S > rhs)
assign from initializer list
Algebra< SU2< T > > & operator=(const std::nullptr_t &z)
assign from zero
Algebra< SU2< T > > & operator=(const Algebra< SU2< A > > &rhs)
assign from another Algebra<SU2>
Algebra< SU2< T > > & operator/=(const A rhs)
divide assign scalar
Algebra< SU2< T > > & operator*=(const A rhs)
multiply assign scalar
Algebra< SU2< T > > operator+() const
unary +
Algebra< SU2< T > > & operator-=(const Algebra< SU2< A > > &rhs)
subtract assign another Algebra<SU2>
Algebra< SU2< T > > operator-() const
unary -
Algebra(const std::nullptr_t &z)
construct from 0
SU2< T > exp() const
SU2 Algebra $exp( E ) = exp( i 1/2 a_n\sigma_n )$ , returns SU2.
T squarenorm() const
a^2 + b^2 + c^2
SU2< T > expand() const
Expand algebra to SU2.
Algebra< SU2< T > > & operator+=(const Algebra< SU2< A > > &rhs)
add assign another Algebra<SU2>
The main matrix type template Matrix_t. This is a base class type for "useful" types which are deriv...
T c[n *m]
The data as a one dimensional array.
T e(const int i, const int j) const
Standard array indexing operation for matrices and vectors.
Matrix class which defines matrix operations.
Algebra< SU2< T > > project_to_algebra() const
project SU2 to generators $\lambda_a = 1/2 \sigma_a$
SU2< T > & random(double width=1.0)
make random SU2
SU2< T > & operator=(const SU2< A > &rhs)
assign from another SU2
SU2< T > & operator+=(const SU2< A > &rhs)
add assign another SU2
SU2(const B z)
construct from 'scalar'
SU2< T > & operator*=(const A rhs)
multiply assign scalar
T trace() const
for SU2 same as .dagger()
SU2< T > & operator-=(const SU2< A > &rhs)
subtract assign another SU2
SU2< T > & operator-=(const A rhs)
subtract assign ('scalar' * identity matrix)
SU2< T > & operator=(A rhs)
assign from 'scalar'
SU2< T > operator+() const
unary +
SU2< T > operator-() const
unary -
SU2< T > & normalize()
Normalize det = 1 to make sure it's an element of SU2.
SU2< T > & reunitarize()
Normalize det = 1 to make sure it's an element of SU2.
SU2< T > & operator/=(const A rhs)
divide assign scalar
SU2< T > dagger() const
complex conjugate transpose
SU2(std::initializer_list< S > rhs)
initializer list constructor
SU2< T > & gaussian_random(double width=1.0)
make gaussian random matrix, does not normalize
Algebra< SU2< T > > log() const
SU2 matrix log, returns SU2 algebra.
SU2< T > exp() const
SU2 matrix exp.
SU2< T > & operator=(std::initializer_list< S > rhs)
assign from initializer list
SU2< T > & operator+=(const A rhs)
add assign ('scalar' * identity matrix)
Definition of Matrix types.
Implement hila::swap for gauge fields.
logger_class log
Now declare the logger.
double gaussrand()
Gaussian random generation routine.
double gaussrand2(double &out2)
hila::gaussrand2 returns 2 Gaussian distributed random numbers with variance .