23template <typename T, std::enable_if_t<hila::is_arithmetic<T>::value,
int> = 0>
24inline T mul_add(T a, T b, T c) {
28template <typename T, std::enable_if_t<hila::is_arithmetic<T>::value,
int> = 0>
29inline T mul_sub(T a, T b, T c) {
33template <typename T, std::enable_if_t<hila::is_arithmetic<T>::value,
int> = 0>
34inline T nmul_add(T a, T b, T c) {
59 "Complex can be used only with floating point type");
63 using base_type = hila::arithmetic_type<T>;
64 using argument_type = T;
141 template <typename S, std::enable_if_t<hila::is_arithmetic<S>::value,
int> = 0>
142 explicit constexpr Complex<T>(
const S val) : re(val), im(0) {}
145 constexpr Complex<T>(
const std::nullptr_t n) : re(0), im(0) {}
148 template <typename A, typename B, std::enable_if_t<hila::is_arithmetic<A>::value,
int> = 0,
149 std::enable_if_t<hila::is_arithmetic<B>::value,
int> = 0>
150 explicit constexpr Complex<T>(
const A &a,
const B &b) : re(a), im(b) {}
164 #pragma hila loop_function
176 #pragma hila loop_function
181 inline T &
real() const_function {
185 inline T &
imag() const_function {
190 template <
typename A>
223 template <
typename A>
230 template <typename S, std::enable_if_t<hila::is_arithmetic<S>::value,
int> = 0>
238 template <
typename S>
249 return re * re + im * im;
271 return atan2(im, re);
390 template <
typename A>
397 template <typename A, std::enable_if_t<hila::is_arithmetic<A>::value,
int> = 0>
426 template <
typename A>
433 template <typename A, std::enable_if_t<hila::is_arithmetic<A>::value,
int> = 0>
474 template <
typename A>
476 T r = mul_sub(re, lhs.re, im * lhs.im);
477 im = mul_add(im, lhs.re, re * lhs.im);
482 template <typename A, std::enable_if_t<hila::is_arithmetic<A>::value,
int> = 0>
526 template <
typename A>
528 T n = lhs.squarenorm();
529 T r = mul_add(re, lhs.re, im * lhs.im) / n;
530 im = mul_sub(im, lhs.re, re * lhs.im) / n;
535 template <typename A, std::enable_if_t<hila::is_arithmetic<A>::value,
int> = 0>
591 std::string str(
int prec = 8,
char separator =
' ')
const {
592 std::stringstream ss;
594 ss << re << separator << im;
610 template <
typename A>
612 return Complex<T>(re * b.re + im * b.im, re * b.im - im * b.re);
626 template <
typename A>
628 return Complex<T>(re * b.re + im * b.im, im * b.re - re * b.im);
632 template <
typename Ntype>
654struct is_complex : std::integral_constant<bool, false> {};
657struct is_complex<
Complex<T>> : std::integral_constant<bool, true> {};
660struct is_complex<
Imaginary_t<T>> : std::integral_constant<bool, true> {};
665 : std::integral_constant<bool, hila::is_arithmetic<T>::value || hila::is_complex<T>::value> {};
671template <
typename T,
typename Enable =
void>
672struct contains_complex : std::integral_constant<bool, false> {};
675struct contains_complex<T, typename std::enable_if_t<hila::is_field_class_type<T>::value>>
676 : std::integral_constant<bool,
677 hila::contains_type<T, Complex<hila::arithmetic_type<T>>>::value> {};
683template <
typename T,
typename Enable =
void,
typename N = hila::arithmetic_type<T>>
684struct complex_or_arithmetic_type_struct {
689struct complex_or_arithmetic_type_struct<
690 T, typename std::enable_if_t<hila::contains_complex<T>::value>> {
695using number_type =
typename complex_or_arithmetic_type_struct<T>::type;
702template <
typename T1,
typename T2,
typename Enable =
void>
708template <
typename T1,
typename T2>
709struct ntype_op_s<T1, T2,
710 typename std::enable_if_t<(hila::contains_complex<T1>::value ||
711 hila::contains_complex<T2>::value)>> {
715template <
typename T1,
typename T2>
716using ntype_op =
typename ntype_op_s<T1, T2>::type;
724template <
typename A,
typename B,
typename Enable =
void>
725struct complex_x_scalar_s {
729template <
typename A,
typename B>
730struct complex_x_scalar_s<
731 A, B, typename std::enable_if_t<std::is_assignable<A &, hila::type_plus<A, B>>::value>> {
735template <
typename A,
typename B>
736using complex_x_scalar_type =
typename complex_x_scalar_s<A, B>::type;
764template <typename T, std::enable_if_t<hila::contains_complex<T>::value,
int> = 0>
769template <typename T, std::enable_if_t<hila::contains_complex<T>::value,
int> = 0>
770inline void set_complex_in_var(T &var,
int i,
const Complex<hila::arithmetic_type<T>> &val) {
777template <typename T, std::enable_if_t<hila::is_floating_point<T>::value,
int> = 0>
838template <
typename T1,
typename T2,
typename Tr = hila::type_plus<T1, T2>>
855template <typename T, typename A, std::enable_if_t<hila::is_arithmetic<A>::value,
int> = 0>
857 return hila::complex_x_scalar_type<T, A>(c.re + a, c.im);
869template <typename T, typename A, std::enable_if_t<hila::is_arithmetic<A>::value,
int> = 0>
871 return hila::complex_x_scalar_type<T, A>(c.re + a, c.im);
884template <
typename T1,
typename T2,
typename Tr = hila::type_plus<T1, T2>>
899template <typename T, typename A, std::enable_if_t<hila::is_arithmetic<A>::value,
int> = 0>
901 return hila::complex_x_scalar_type<T, A>(c.re - a, c.im);
913template <typename T, typename A, std::enable_if_t<hila::is_arithmetic<A>::value,
int> = 0>
915 return hila::complex_x_scalar_type<T, A>(a - c.re, -c.im);
932template <
typename T1,
typename T2,
typename Tr = hila::type_mul<T1, T2>>
934 return Complex<Tr>(a.re * b.re - a.im * b.im, a.re * b.im + a.im * b.re);
949template <typename T, typename A, std::enable_if_t<hila::is_arithmetic<A>::value,
int> = 0>
951 return hila::complex_x_scalar_type<T, A>(c.re * a, c.im * a);
966template <typename T, typename A, std::enable_if_t<hila::is_arithmetic<A>::value,
int> = 0>
968 return hila::complex_x_scalar_type<T, A>(a * c.re, a * c.im);
991template <
typename T1,
typename T2,
typename Tr = hila::type_mul<T1, T2>>
994 return Complex<Tr>((a.re * b.re + a.im * b.im) * n, (a.im * b.re - a.re * b.im) * n);
1010template <typename T, typename A, std::enable_if_t<hila::is_arithmetic<A>::value,
int> = 0>
1012 return hila::complex_x_scalar_type<T, A>(c.re / a, c.im / a);
1029template <typename T, typename A, std::enable_if_t<hila::is_arithmetic<A>::value,
int> = 0>
1032 return hila::complex_x_scalar_type<T, A>((a * c.re) / n, -(a * c.im) / n);
1048template <
typename T>
1052 T t1 = mul_add(a.re, b.re, c.re);
1053 T t2 = mul_add(a.re, b.im, c.im);
1054 r.re = mul_add(a.im, b.im, t1);
1055 r.im = mul_add(a.im, b.re, t2);
1071template <
typename A,
typename B>
1073 return (a.re == b.re && a.im == b.im);
1090template <typename A, typename B, std::enable_if_t<hila::is_arithmetic<B>::value,
int> = 0>
1092 return (a.re == b && a.im == 0);
1109template <typename A, typename B, std::enable_if_t<hila::is_arithmetic<A>::value,
int> = 0>
1125template <
typename A,
typename B>
1127 return (a.re != b.re || a.im != b.im);
1141template <typename A, typename B, std::enable_if_t<hila::is_arithmetic<B>::value,
int> = 0>
1143 return (a.re != b || a.im != 0);
1157template <typename A, typename B, std::enable_if_t<hila::is_arithmetic<A>::value,
int> = 0>
1169template <typename Ntype, typename T, std::enable_if_t<hila::is_arithmetic<Ntype>::value,
int> = 0>
1186template <
typename T>
1198template <
typename T>
1210template <
typename T>
1222template <
typename T>
1234template <
typename T>
1252template <
typename T>
1254 return strm << A.
real() <<
' ' << A.
imag();
1270template <
typename T>
1272 return A.str(prec, separator);
1284template <
typename T>
1286 std::stringstream ss;
1288 ss <<
"( " << A.
real() <<
", " << A.
imag() <<
" )";
1306template <
typename T>
1314 template <typename A, std::enable_if_t<hila::is_arithmetic<A>::value,
int> = 0>
1332#if defined(_GPU_DEVICE_COMPILE_)
1342template <typename T, std::enable_if_t<hila::contains_complex<T>::value,
int> = 0>
1346 constexpr int n_cmplx =
sizeof(T) /
sizeof(
Complex<hila::arithmetic_type<T>>);
1347 for (
int k = 0; k < n_cmplx; k++) {
1348 ca = hila::get_complex_in_var(c, k);
1349 cb.re = -ca.im * i.
imag();
1350 cb.im = ca.re * i.
imag();
1351 hila::set_complex_in_var(res, k, cb);
1357template <typename T, std::enable_if_t<hila::contains_complex<T>::value,
int> = 0>
1364template <typename A, typename T, std::enable_if_t<std::is_arithmetic<T>::value,
int> = 0>
1371template <typename A, typename T, std::enable_if_t<std::is_arithmetic<T>::value,
int> = 0>
1378template <
typename A,
typename B>
1388template <typename T, typename A, std::enable_if_t<std::is_arithmetic<A>::value,
int> = 0>
1395template <
typename A,
typename B>
1406template <
typename T>
1412template <typename T, std::enable_if_t<hila::is_arithmetic<T>::value,
int> = 0>
1418template <
typename T>
1424template <
typename T>
1432template <
typename T>
1436 return pow(r, 0.25) *
expi(0.5 * a);
1440template <
typename T>
1444 return pow(r, (1.0 / 6.0)) *
expi((1.0 / 3.0) * a);
1448template <
typename A,
typename B>
1454template <typename T, typename S, std::enable_if_t<hila::is_arithmetic<S>::value,
int> = 0>
1460template <typename T, typename S, std::enable_if_t<hila::is_arithmetic<S>::value,
int> = 0>
1468template <
typename T>
1475template <
typename T>
1481template <
typename T>
1488template <
typename T>
1495template <
typename T>
1501template <
typename T>
1507template <
typename T>
1509 return -0.5 *
I * (
log((
I - z) / (
I + z)));
1513template <
typename T>
1515 return -
I * (
log(
I * z +
sqrt(1 - z * z)));
1519template <
typename T>
1521 return -
I * (
log(z +
I * (
sqrt(1 - z * z))));
1525template <
typename T>
1527 return 0.5 *
log((1 + z) / (1 - z));
1531template <
typename T>
1533 return log(z +
sqrt(1 + z * z));
1537template <
typename T>
1539 return log(z +
sqrt(z * z - 1));
Array< n, m, Ntype > cast_to(const Array< n, m, T > &mat)
Array casting operation.
Complex< T > dagger() const
Compute dagger of Complex number.
Complex< T > & operator*=(const Complex< A > &lhs) &
*= multiply assignment operator
Complex< T > conj() const
Compute conjugate of Complex number.
T abs() const
Compute absolute value of Complex number.
Complex< T > polar(const T r, const T theta)
Stores and returns Complex number given in polar coordinates.
T real() const
Real part of Complex number.
Complex< T > & operator++()
++ increment operator
T arg() const
Compute argument of Complex number.
Complex< T > & operator/=(const Complex< A > &lhs) &
/= divide assignment operator
T squarenorm() const
Compute square norm of Complex number.
Complex< T > & gaussian_random(double width=1.0)
Produces complex gaussian random values.
Complex< T > & operator--()
– decrement operator
Complex< T > operator+() const
Unary + operator.
T imag() const
Imaginary part of Complex number.
Complex< T > & random()
Assign random values to Complex real and imaginary part.
Complex< T > operator-() const
Unary - operator.
Complex< T > mul_conj(const Complex< A > &b) const
Multiply conjugate method.
Complex< T > & operator-=(const Complex< A > &lhs) &
-= subtraction assignment operator
Complex< T > & operator+=(const Complex< A > &lhs) &
+= addition assignment operator
Complex< T > conj_mul(const Complex< A > &b) const
Conjugate multiply method.
Complex< T > & operator=(const Complex< T > &s) &=default
Assignment operator.
Imaginary type, used to represent purely imaginary numbers.
Complex< T > asin(Complex< T > z)
Complex< T > cbrt(Complex< T > z)
Complex< Tr > operator-(const Complex< T1 > &a, const Complex< T2 > &b)
Subtraction operator Complex - Complex.
bool operator==(const Complex< A > &a, const Complex< B > &b)
Compare equality of two complex numbers.
T imag(const Complex< T > &a)
Retrun imaginary value of Complex number.
Complex< T > cosh(Complex< T > z)
Complex< T > acosh(Complex< T > z)
Complex< Tr > operator*(const Complex< T1 > &a, const Complex< T2 > &b)
Multiplication operator Complex * Complex.
Complex< T > conj(const Complex< T > &val)
Return conjugate of Complex number.
Complex< Tr > operator/(const Complex< T1 > &a, const Complex< T2 > &b)
Division operator Complex / Complex.
auto squarenorm(const Complex< T > &val)
Return Squarenorm of Complex number.
Complex< Tr > operator+(const Complex< T1 > &a, const Complex< T2 > &b)
Addition operator Complex + Complex.
bool operator!=(const Complex< A > &a, const Complex< B > &b)
Compare non-equality of two complex numbers.
Complex< T > tanh(Complex< T > z)
Complex< T > sin(Complex< T > z)
Complex< T > atan(Complex< T > z)
Complex< T > dagger(const Complex< T > &val)
Return dagger of Complex number.
Complex< T > tan(Complex< T > z)
- rely on optimizer to simplify
Complex< T > polar(T r, T arg)
Return complex number given by polar representation.
Complex< T > log(Complex< T > z)
T real(const Complex< T > &a)
Return real value of Complex number.
constexpr Imaginary_t< double > I(1.0)
Imaginary unit I - global variable.
T abs(const Complex< T > &a)
Return absolute value of Complex number.
std::ostream & operator<<(std::ostream &strm, const Complex< T > &A)
Print a complex value as (re,im)
T arg(const Complex< T > &a)
Return argument of Complex number.
Complex< T > cos(Complex< T > z)
Complex< T > sinh(Complex< T > z)
auto pow(Complex< A > z, Complex< B > p)
pow(z.p) = =
Complex< T > atanh(Complex< T > z)
Complex< T > acos(Complex< T > z)
Complex< T > sqrt(Complex< T > z)
Complex< T > asinh(Complex< T > z)
Complex< T > exp(const Complex< T > z)
This file defines all includes for HILA.
Implement hila::swap for gauge fields.
double random()
Real valued uniform random number generator.
double gaussrand2(double &out2)
hila::gaussrand2 returns 2 Gaussian distributed random numbers with variance .
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