Qrack  1.7
General classical-emulating-quantum development framework
complex16x2simd.hpp
Go to the documentation of this file.
1 //
3 // (C) Daniel Strano and the Qrack contributors 2017, 2018. All rights reserved.
4 //
5 // This is a SIMD implementation of the double precision complex type.
6 // The API is designed to (almost entirely) mirror that of the C++ standard library
7 // double precision complex type.
8 //
9 // Licensed under the GNU Lesser General Public License V3.
10 // See LICENSE.md in the project root or https://www.gnu.org/licenses/lgpl-3.0.en.html
11 // for details.
12 
13 #pragma once
14 
15 #include <emmintrin.h>
16 #include <immintrin.h>
17 #include <smmintrin.h>
18 
19 namespace Qrack {
20 
23  __m256d _val2;
24 
25  inline Complex16x2Simd(){};
26  inline Complex16x2Simd(const __m256d& v2) { _val2 = v2; }
27  inline Complex16x2Simd(const double& r1, const double& i1, const double& r2, const double& i2)
28  {
29  _val2 = _mm256_set_pd(i1, r1, i2, r2);
30  }
31  inline Complex16x2Simd operator+(const Complex16x2Simd& other) const { return _mm256_add_pd(_val2, other._val2); }
33  {
34  _val2 = _mm256_add_pd(_val2, other._val2);
35  return _val2;
36  }
37  inline Complex16x2Simd operator-(const Complex16x2Simd& other) const { return _mm256_sub_pd(_val2, other._val2); }
39  {
40  _val2 = _mm256_sub_pd(_val2, other._val2);
41  return _val2;
42  }
43  inline Complex16x2Simd operator*(const Complex16x2Simd& other) const
44  {
45  return _mm256_add_pd(
46  _mm256_mul_pd(_mm256_shuffle_pd(_val2, _val2, 5), _mm256_shuffle_pd((-other._val2), other._val2, 15)),
47  _mm256_mul_pd(_val2, _mm256_shuffle_pd(other._val2, other._val2, 0)));
48  }
50  {
51  _val2 = _mm256_add_pd(
52  _mm256_mul_pd(_mm256_shuffle_pd(_val2, _val2, 5), _mm256_shuffle_pd((-other._val2), other._val2, 15)),
53  _mm256_mul_pd(_val2, _mm256_shuffle_pd(other._val2, other._val2, 0)));
54  return _val2;
55  }
56  inline Complex16x2Simd operator*(const double rhs) const { return _mm256_mul_pd(_val2, _mm256_set1_pd(rhs)); }
57  inline Complex16x2Simd operator-() const { return -_val2; }
58  inline Complex16x2Simd operator*=(const double& other)
59  {
60  _val2 = _mm256_mul_pd(_val2, _mm256_set1_pd(other));
61  return _val2;
62  }
63 };
64 
65 inline Complex16x2Simd dupeLo(const Complex16x2Simd& cmplx2)
66 {
67  return _mm256_permute2f128_pd(cmplx2._val2, cmplx2._val2, 0);
68 }
69 inline Complex16x2Simd dupeHi(const Complex16x2Simd& cmplx2)
70 {
71  return _mm256_permute2f128_pd(cmplx2._val2, cmplx2._val2, 17);
72 }
74  const Complex16x2Simd& mtrxCol1, const Complex16x2Simd& mtrxCol2, const Complex16x2Simd& qubit)
75 {
76  __m256d dupeLo = _mm256_permute2f128_pd(qubit._val2, qubit._val2, 0);
77  __m256d dupeHi = _mm256_permute2f128_pd(qubit._val2, qubit._val2, 17);
78  return _mm256_add_pd(_mm256_add_pd(_mm256_mul_pd(_mm256_shuffle_pd(mtrxCol1._val2, mtrxCol1._val2, 5),
79  _mm256_shuffle_pd(-dupeLo, dupeLo, 15)),
80  _mm256_mul_pd(mtrxCol1._val2, _mm256_shuffle_pd(dupeLo, dupeLo, 0))),
81  _mm256_add_pd(
82  _mm256_mul_pd(_mm256_shuffle_pd(mtrxCol2._val2, mtrxCol2._val2, 5), _mm256_shuffle_pd(-dupeHi, dupeHi, 15)),
83  _mm256_mul_pd(mtrxCol2._val2, _mm256_shuffle_pd(dupeHi, dupeHi, 0))));
84 }
86  const double& nrm, const Complex16x2Simd& mtrxCol1, const Complex16x2Simd& mtrxCol2, const Complex16x2Simd& qubit)
87 {
88  __m256d dupeLo = _mm256_permute2f128_pd(qubit._val2, qubit._val2, 0);
89  __m256d dupeHi = _mm256_permute2f128_pd(qubit._val2, qubit._val2, 17);
90  return _mm256_mul_pd(_mm256_set1_pd(nrm),
91  _mm256_add_pd(_mm256_add_pd(_mm256_mul_pd(_mm256_shuffle_pd(mtrxCol1._val2, mtrxCol1._val2, 5),
92  _mm256_shuffle_pd(-dupeLo, dupeLo, 15)),
93  _mm256_mul_pd(mtrxCol1._val2, _mm256_shuffle_pd(dupeLo, dupeLo, 0))),
94  _mm256_add_pd(_mm256_mul_pd(_mm256_shuffle_pd(mtrxCol2._val2, mtrxCol2._val2, 5),
95  _mm256_shuffle_pd(-dupeHi, dupeHi, 15)),
96  _mm256_mul_pd(mtrxCol2._val2, _mm256_shuffle_pd(dupeHi, dupeHi, 0)))));
97 }
98 inline Complex16x2Simd operator*(const double lhs, const Complex16x2Simd& rhs)
99 {
100  return _mm256_mul_pd(_mm256_set1_pd(lhs), rhs._val2);
101 }
102 
103 } // namespace Qrack
Complex16x2Simd operator+(const Complex16x2Simd &other) const
Definition: complex16x2simd.hpp:31
Complex16x2Simd operator*=(const Complex16x2Simd &other)
Definition: complex16x2simd.hpp:49
Complex16x2Simd dupeHi(const Complex16x2Simd &cmplx2)
Definition: complex16x2simd.hpp:69
Complex16x2Simd dupeLo(const Complex16x2Simd &cmplx2)
Definition: complex16x2simd.hpp:65
__m256d _val2
Definition: complex16x2simd.hpp:23
Complex16x2Simd operator*(const Complex16x2Simd &other) const
Definition: complex16x2simd.hpp:43
Complex16x2Simd(const double &r1, const double &i1, const double &r2, const double &i2)
Definition: complex16x2simd.hpp:27
Complex16x2Simd()
Definition: complex16x2simd.hpp:25
Complex16x2Simd operator-=(const Complex16x2Simd &other)
Definition: complex16x2simd.hpp:38
Complex16x2Simd operator*(const double rhs) const
Definition: complex16x2simd.hpp:56
Complex16x2Simd operator-(const Complex16x2Simd &other) const
Definition: complex16x2simd.hpp:37
SIMD implementation of the double precision complex vector type of 2 complex numbers, only for AVX Apply2x2.
Definition: complex16x2simd.hpp:22
Complex16x2Simd(const __m256d &v2)
Definition: complex16x2simd.hpp:26
Complex16x2Simd matrixMul(const Complex16x2Simd &mtrxCol1, const Complex16x2Simd &mtrxCol2, const Complex16x2Simd &qubit)
Definition: complex16x2simd.hpp:73
Complex16x2Simd operator*=(const double &other)
Definition: complex16x2simd.hpp:58
Complex16x2Simd operator+=(const Complex16x2Simd &other)
Definition: complex16x2simd.hpp:32
Definition: complex16simd.hpp:21
Complex16x2Simd operator-() const
Definition: complex16x2simd.hpp:57