Qrack  10.0
General classical-emulating-quantum development framework
statevector.hpp
Go to the documentation of this file.
1 //
3 // (C) Daniel Strano and the Qrack contributors 2017-2023. All rights reserved.
4 //
5 // This header defines buffers for Qrack::QFusion.
6 // QFusion adds an optional "gate fusion" layer on top of a QEngine or QUnit.
7 // Single bit gates are buffered in per-bit 2x2 complex matrices, to reduce the cost
8 // of successive application of single bit gates to the same bit.
9 //
10 // Licensed under the GNU Lesser General Public License V3.
11 // See LICENSE.md in the project root or https://www.gnu.org/licenses/lgpl-3.0.en.html
12 // for details.
13 
14 #pragma once
15 
16 #include "common/parallel_for.hpp"
17 
18 #include <algorithm>
19 #include <mutex>
20 #include <numeric>
21 #include <random>
22 #include <set>
23 
24 #ifdef ENABLE_PTHREAD
25 #include <future>
26 #endif
27 
28 #include <unordered_map>
29 #define SparseStateVecMap std::unordered_map<bitCapIntOcl, complex>
30 
31 #if ENABLE_COMPLEX_X2
32 #if FPPOW == 5
34 #elif FPPOW == 6
36 #endif
37 #endif
38 
39 namespace Qrack {
40 
41 class StateVectorArray;
42 class StateVectorSparse;
43 
44 // This is a buffer struct that's capable of representing controlled single bit gates and arithmetic, when subclassed.
45 class StateVector : public ParallelFor {
46 protected:
48 
49 public:
51 
53  : capacity(cap)
54  , isReadLocked(true)
55  {
56  }
57  virtual ~StateVector()
58  {
59  // Intentionally left blank.
60  }
61 
62  virtual complex read(const bitCapIntOcl& i) = 0;
63 #if ENABLE_COMPLEX_X2
64  virtual complex2 read2(const bitCapIntOcl& i1, const bitCapIntOcl& i2) = 0;
65 #endif
66  virtual void write(const bitCapIntOcl& i, const complex& c) = 0;
69  virtual void write2(const bitCapIntOcl& i1, const complex& c1, const bitCapIntOcl& i2, const complex& c2) = 0;
70  virtual void clear() = 0;
71  virtual void copy_in(const complex* inArray) = 0;
72  virtual void copy_in(const complex* copyIn, const bitCapIntOcl offset, const bitCapIntOcl length) = 0;
73  virtual void copy_in(StateVectorPtr copyInSv, const bitCapIntOcl srcOffset, const bitCapIntOcl dstOffset,
74  const bitCapIntOcl length) = 0;
75  virtual void copy_out(complex* outArray) = 0;
76  virtual void copy_out(complex* copyIn, const bitCapIntOcl offset, const bitCapIntOcl length) = 0;
77  virtual void copy(StateVectorPtr toCopy) = 0;
78  virtual void shuffle(StateVectorPtr svp) = 0;
79  virtual void get_probs(real1* outArray) = 0;
80  virtual bool is_sparse() = 0;
81 };
82 
83 class StateVectorArray : public StateVector {
84 public:
85  std::unique_ptr<complex[], void (*)(complex*)> amplitudes;
86 
87 protected:
88 #if defined(__APPLE__)
89  complex* _aligned_state_vec_alloc(bitCapIntOcl allocSize)
90  {
91  void* toRet;
92  posix_memalign(&toRet, QRACK_ALIGN_SIZE, allocSize);
93  return (complex*)toRet;
94  }
95 #endif
96 
97  std::unique_ptr<complex[], void (*)(complex*)> Alloc(bitCapIntOcl elemCount)
98  {
99 #if defined(__ANDROID__)
100  return std::unique_ptr<complex[], void (*)(complex*)>(new complex[elemCount], [](complex* c) { delete c; });
101 #else
102  // elemCount is always a power of two, but might be smaller than QRACK_ALIGN_SIZE
103  size_t allocSize = sizeof(complex) * elemCount;
104  if (allocSize < QRACK_ALIGN_SIZE) {
105  allocSize = QRACK_ALIGN_SIZE;
106  }
107 #if defined(__APPLE__)
108  return std::unique_ptr<complex[], void (*)(complex*)>(
109  _aligned_state_vec_alloc(allocSize), [](complex* c) { free(c); });
110 #elif defined(_WIN32) && !defined(__CYGWIN__)
111  return std::unique_ptr<complex[], void (*)(complex*)>(
112  (complex*)_aligned_malloc(allocSize, QRACK_ALIGN_SIZE), [](complex* c) { _aligned_free(c); });
113 #else
114  return std::unique_ptr<complex[], void (*)(complex*)>(
115  (complex*)aligned_alloc(QRACK_ALIGN_SIZE, allocSize), [](complex* c) { free(c); });
116 #endif
117 #endif
118  }
119 
120  virtual void Free() { amplitudes = nullptr; }
121 
122 public:
124  : StateVector(cap)
126  {
127  // Intentionally left blank.
128  }
129 
130  virtual ~StateVectorArray() { Free(); }
131 
132  complex read(const bitCapIntOcl& i) { return amplitudes.get()[i]; };
133 
134 #if ENABLE_COMPLEX_X2
135  complex2 read2(const bitCapIntOcl& i1, const bitCapIntOcl& i2)
136  {
137  return complex2(amplitudes.get()[i1], amplitudes.get()[i2]);
138  }
139 #endif
140 
141  void write(const bitCapIntOcl& i, const complex& c) { amplitudes.get()[i] = c; };
142 
143  void write2(const bitCapIntOcl& i1, const complex& c1, const bitCapIntOcl& i2, const complex& c2)
144  {
145  amplitudes.get()[i1] = c1;
146  amplitudes.get()[i2] = c2;
147  };
148 
149  void clear()
150  {
151  par_for(0, capacity, [&](const bitCapIntOcl& lcv, const unsigned& cpu) { amplitudes[lcv] = ZERO_CMPLX; });
152  }
153 
154  void copy_in(const complex* copyIn)
155  {
156  if (copyIn) {
157  par_for(0, capacity, [&](const bitCapIntOcl& lcv, const unsigned& cpu) { amplitudes[lcv] = copyIn[lcv]; });
158  } else {
159  par_for(0, capacity, [&](const bitCapIntOcl& lcv, const unsigned& cpu) { amplitudes[lcv] = ZERO_CMPLX; });
160  }
161  }
162 
163  void copy_in(const complex* copyIn, const bitCapIntOcl offset, const bitCapIntOcl length)
164  {
165  if (copyIn) {
166  par_for(0, length,
167  [&](const bitCapIntOcl& lcv, const unsigned& cpu) { amplitudes[lcv + offset] = copyIn[lcv]; });
168  } else {
169  par_for(0, length,
170  [&](const bitCapIntOcl& lcv, const unsigned& cpu) { amplitudes[lcv + offset] = ZERO_CMPLX; });
171  }
172  }
173 
174  void copy_in(
175  StateVectorPtr copyInSv, const bitCapIntOcl srcOffset, const bitCapIntOcl dstOffset, const bitCapIntOcl length)
176  {
177  if (copyInSv) {
178  const complex* copyIn = std::dynamic_pointer_cast<StateVectorArray>(copyInSv)->amplitudes.get() + srcOffset;
179  par_for(0, length,
180  [&](const bitCapIntOcl& lcv, const unsigned& cpu) { amplitudes[lcv + dstOffset] = copyIn[lcv]; });
181  } else {
182  par_for(0, length,
183  [&](const bitCapIntOcl& lcv, const unsigned& cpu) { amplitudes[lcv + dstOffset] = ZERO_CMPLX; });
184  }
185  }
186 
187  void copy_out(complex* copyOut)
188  {
189  par_for(0, capacity, [&](const bitCapIntOcl& lcv, const unsigned& cpu) { copyOut[lcv] = amplitudes[lcv]; });
190  }
191 
192  void copy_out(complex* copyOut, const bitCapIntOcl offset, const bitCapIntOcl length)
193  {
194  par_for(
195  0, length, [&](const bitCapIntOcl& lcv, const unsigned& cpu) { copyOut[lcv] = amplitudes[lcv + offset]; });
196  }
197 
198  void copy(StateVectorPtr toCopy) { copy(std::dynamic_pointer_cast<StateVectorArray>(toCopy)); }
199 
201  {
202  par_for(0, capacity,
203  [&](const bitCapIntOcl& lcv, const unsigned& cpu) { amplitudes[lcv] = toCopy->amplitudes[lcv]; });
204  }
205 
206  void shuffle(StateVectorPtr svp) { shuffle(std::dynamic_pointer_cast<StateVectorArray>(svp)); }
207 
209  {
210  const bitCapIntOcl offset = capacity >> 1U;
211  par_for(0, offset, [&](const bitCapIntOcl& lcv, const unsigned& cpu) {
212  const complex tmp = amplitudes[lcv + offset];
213  amplitudes[lcv + offset] = svp->amplitudes[lcv];
214  svp->amplitudes[lcv] = tmp;
215  });
216  }
217 
218  void get_probs(real1* outArray)
219  {
220  par_for(
221  0, capacity, [&](const bitCapIntOcl& lcv, const unsigned& cpu) { outArray[lcv] = norm(amplitudes[lcv]); });
222  }
223 
224  bool is_sparse() { return false; }
225 };
226 
228 protected:
230  std::mutex mtx;
231 
233  {
234  auto it = amplitudes.find(i);
235  return (it == amplitudes.end()) ? ZERO_CMPLX : it->second;
236  }
237 
239  {
240  std::lock_guard<std::mutex> lock(mtx);
241  return readUnlocked(i);
242  }
243 
244 public:
246  : StateVector(cap)
247  , amplitudes()
248  {
249  }
250 
251  size_t size() { return amplitudes.size(); }
252 
253  void mult(real1_f nrm)
254  {
255  const real1 _nrm = (real1)nrm;
256  for (auto& pair : amplitudes) {
257  pair.second *= _nrm;
258  }
259  }
260 
261  real1_f truncate_to_size(size_t maxAmps)
262  {
263  if (amplitudes.size() <= maxAmps) {
264  return ONE_R1_F;
265  }
266 
267  std::multiset<real1> nrms;
268  for (const auto& pair : amplitudes) {
269  real1 nrm = norm(pair.second);
270  if (nrms.size() < maxAmps) {
271  nrms.insert(nrm);
272  } else if (*(nrms.begin()) < nrm) {
273  nrms.erase(nrms.begin());
274  nrms.insert(nrm);
275  }
276  }
277 
278  const real1 limit = *(nrms.begin());
279  const real1 fidelity = std::accumulate(nrms.begin(), nrms.end(), ZERO_R1);
280  const real1 nrm = ONE_R1 / (real1)std::sqrt((real1_s)fidelity);
281  nrms.clear();
282 
283  SparseStateVecMap nAmplitudes;
284  for (auto it = amplitudes.begin(); it != amplitudes.end(); ++it) {
285  if (norm(it->second) >= limit) {
286  nAmplitudes[it->first] = it->second;
287  }
288  }
289  amplitudes.clear();
290  amplitudes = nAmplitudes;
291  nAmplitudes.clear();
292 
293  if (amplitudes.size() > maxAmps) {
294  std::vector<bitCapIntOcl> indices;
295  for (auto it = amplitudes.begin(); it != amplitudes.end(); ++it) {
296  if (norm(it->second) == limit) {
297  indices.push_back(it->first);
298  }
299  }
300  std::random_device rd;
301  std::mt19937 g(rd());
302  std::shuffle(indices.begin(), indices.end(), g);
303  indices.resize(amplitudes.size() - maxAmps);
304  for (const bitCapIntOcl& idx : indices) {
305  amplitudes.erase(idx);
306  }
307  }
308 
309  // Normalize
310  mult(nrm);
311 
312  return fidelity;
313  }
314 
316 
317 #if ENABLE_COMPLEX_X2
318  complex2 read2(const bitCapIntOcl& i1, const bitCapIntOcl& i2)
319  {
320  if (isReadLocked) {
321  return complex2(readLocked(i1), readLocked(i2));
322  }
323  return complex2(readUnlocked(i1), readUnlocked(i2));
324  }
325 #endif
326 
327  void write(const bitCapIntOcl& i, const complex& c)
328  {
329  const bool isCSet = abs(c) > REAL1_EPSILON;
330  if (isCSet) {
331  std::lock_guard<std::mutex> lock(mtx);
332  amplitudes[i] = c;
333  } else {
334  std::lock_guard<std::mutex> lock(mtx);
335  amplitudes.erase(i);
336  }
337  }
338 
339  void write2(const bitCapIntOcl& i1, const complex& c1, const bitCapIntOcl& i2, const complex& c2)
340  {
341  const bool isC1Set = abs(c1) > REAL1_EPSILON;
342  const bool isC2Set = abs(c2) > REAL1_EPSILON;
343  if (!isC1Set && !isC2Set) {
344  std::lock_guard<std::mutex> lock(mtx);
345  amplitudes.erase(i1);
346  amplitudes.erase(i2);
347  } else if (isC1Set && isC2Set) {
348  std::lock_guard<std::mutex> lock(mtx);
349  amplitudes[i1] = c1;
350  amplitudes[i2] = c2;
351  } else if (isC1Set) {
352  std::lock_guard<std::mutex> lock(mtx);
353  amplitudes.erase(i2);
354  amplitudes[i1] = c1;
355  } else {
356  std::lock_guard<std::mutex> lock(mtx);
357  amplitudes.erase(i1);
358  amplitudes[i2] = c2;
359  }
360  }
361 
362  void clear()
363  {
364  std::lock_guard<std::mutex> lock(mtx);
365  amplitudes.clear();
366  }
367 
368  void copy_in(const complex* copyIn)
369  {
370  if (!copyIn) {
371  clear();
372  return;
373  }
374 
375  std::lock_guard<std::mutex> lock(mtx);
376  for (bitCapIntOcl i = 0U; i < capacity; ++i) {
377  if (abs(copyIn[i]) <= REAL1_EPSILON) {
378  amplitudes.erase(i);
379  } else {
380  amplitudes[i] = copyIn[i];
381  }
382  }
383  }
384 
385  void copy_in(const complex* copyIn, const bitCapIntOcl offset, const bitCapIntOcl length)
386  {
387  if (!copyIn) {
388  std::lock_guard<std::mutex> lock(mtx);
389  for (bitCapIntOcl i = 0U; i < length; ++i) {
390  amplitudes.erase(i);
391  }
392 
393  return;
394  }
395 
396  std::lock_guard<std::mutex> lock(mtx);
397  for (bitCapIntOcl i = 0U; i < length; ++i) {
398  if (abs(copyIn[i]) <= REAL1_EPSILON) {
399  amplitudes.erase(i);
400  } else {
401  amplitudes[i + offset] = copyIn[i];
402  }
403  }
404  }
405 
406  void copy_in(
407  StateVectorPtr copyInSv, const bitCapIntOcl srcOffset, const bitCapIntOcl dstOffset, const bitCapIntOcl length)
408  {
409  StateVectorSparsePtr copyIn = std::dynamic_pointer_cast<StateVectorSparse>(copyInSv);
410 
411  if (!copyIn) {
412  std::lock_guard<std::mutex> lock(mtx);
413  for (bitCapIntOcl i = 0U; i < length; ++i) {
414  amplitudes.erase(i + srcOffset);
415  }
416 
417  return;
418  }
419 
420  std::lock_guard<std::mutex> lock(mtx);
421  for (bitCapIntOcl i = 0U; i < length; ++i) {
422  complex amp = copyIn->read(i + srcOffset);
423  if (abs(amp) <= REAL1_EPSILON) {
424  amplitudes.erase(i + srcOffset);
425  } else {
426  amplitudes[i + dstOffset] = amp;
427  }
428  }
429  }
430 
431  void copy_out(complex* copyOut)
432  {
433  for (bitCapIntOcl i = 0U; i < capacity; ++i) {
434  copyOut[i] = read(i);
435  }
436  }
437 
438  void copy_out(complex* copyOut, const bitCapIntOcl offset, const bitCapIntOcl length)
439  {
440  for (bitCapIntOcl i = 0U; i < length; ++i) {
441  copyOut[i] = read(i + offset);
442  }
443  }
444 
445  void copy(const StateVectorPtr toCopy) { copy(std::dynamic_pointer_cast<StateVectorSparse>(toCopy)); }
446 
448  {
449  std::lock_guard<std::mutex> lock(mtx);
450  amplitudes = toCopy->amplitudes;
451  }
452 
453  void shuffle(StateVectorPtr svp) { shuffle(std::dynamic_pointer_cast<StateVectorSparse>(svp)); }
454 
456  {
457  const size_t halfCap = (size_t)(capacity >> 1U);
458  std::lock_guard<std::mutex> lock(mtx);
459  for (bitCapIntOcl i = 0U; i < halfCap; ++i) {
460  complex amp = svp->read(i);
461  svp->write(i, read(i + halfCap));
462  write(i + halfCap, amp);
463  }
464  }
465 
466  void get_probs(real1* outArray)
467  {
468  for (bitCapIntOcl i = 0U; i < capacity; ++i) {
469  outArray[i] = norm(read(i));
470  }
471  }
472 
473  bool is_sparse() { return (amplitudes.size() < (size_t)(capacity >> 1U)); }
474 
475  std::vector<bitCapIntOcl> iterable()
476  {
477  std::vector<std::vector<bitCapIntOcl>> toRet(GetConcurrencyLevel());
478  std::vector<std::vector<bitCapIntOcl>>::iterator toRetIt;
479 
480  // For lock_guard scope
481  if (true) {
482  std::lock_guard<std::mutex> lock(mtx);
483 
484  par_for(0U, amplitudes.size(), [&](const bitCapIntOcl& lcv, const unsigned& cpu) {
485  auto it = amplitudes.begin();
486  std::advance(it, lcv);
487  toRet[cpu].push_back(it->first);
488  });
489  }
490 
491  for (int64_t i = (int64_t)(toRet.size() - 1U); i >= 0; i--) {
492  if (toRet[i].empty()) {
493  toRetIt = toRet.begin();
494  std::advance(toRetIt, i);
495  toRet.erase(toRetIt);
496  }
497  }
498 
499  if (toRet.empty()) {
500  return {};
501  }
502 
503  while (toRet.size() > 1U) {
504  // Work odd unit into collapse sequence:
505  if (toRet.size() & 1U) {
506  toRet[toRet.size() - 2U].insert(
507  toRet[toRet.size() - 2U].end(), toRet[toRet.size() - 1U].begin(), toRet[toRet.size() - 1U].end());
508  toRet.pop_back();
509  }
510 
511  const int64_t combineCount = (int64_t)(toRet.size() >> 1U);
512 #if ENABLE_PTHREAD
513  std::vector<std::future<void>> futures(combineCount);
514  for (int64_t i = (combineCount - 1); i >= 0; i--) {
515  futures[i] = std::async(std::launch::async, [i, combineCount, &toRet]() {
516  toRet[i].insert(toRet[i].end(), toRet[i + combineCount].begin(), toRet[i + combineCount].end());
517  toRet[i + combineCount].clear();
518  });
519  }
520  for (int64_t i = (combineCount - 1); i >= 0; i--) {
521  futures[i].get();
522  toRet.pop_back();
523  }
524 #else
525  for (int64_t i = (combineCount - 1); i >= 0; i--) {
526  toRet[i].insert(toRet[i].end(), toRet[i + combineCount].begin(), toRet[i + combineCount].end());
527  toRet.pop_back();
528  }
529 #endif
530  }
531 
532  return toRet[0U];
533  }
534 
536  std::set<bitCapIntOcl> iterable(
537  const bitCapIntOcl& setMask, const bitCapIntOcl& filterMask = 0, const bitCapIntOcl& filterValues = 0)
538  {
539  if (!filterMask && filterValues) {
540  return {};
541  }
542 
543  const bitCapIntOcl unsetMask = ~setMask;
544 
545  std::vector<std::set<bitCapIntOcl>> toRet(GetConcurrencyLevel());
546  std::vector<std::set<bitCapIntOcl>>::iterator toRetIt;
547 
548  // For lock_guard scope
549  if (true) {
550  std::lock_guard<std::mutex> lock(mtx);
551 
552  if (!filterMask && !filterValues) {
553  par_for(0U, amplitudes.size(), [&](const bitCapIntOcl& lcv, const unsigned& cpu) {
554  auto it = amplitudes.begin();
555  std::advance(it, lcv);
556  toRet[cpu].insert(it->first & unsetMask);
557  });
558  } else {
559  const bitCapIntOcl unfilterMask = ~filterMask;
560  par_for(0U, amplitudes.size(), [&](const bitCapIntOcl lcv, const unsigned& cpu) {
561  auto it = amplitudes.begin();
562  std::advance(it, lcv);
563  if ((it->first & filterMask) == filterValues) {
564  toRet[cpu].insert(it->first & unsetMask & unfilterMask);
565  }
566  });
567  }
568  }
569 
570  for (int64_t i = (int64_t)(toRet.size() - 1U); i >= 0; i--) {
571  if (toRet[i].empty()) {
572  toRetIt = toRet.begin();
573  std::advance(toRetIt, i);
574  toRet.erase(toRetIt);
575  }
576  }
577 
578  if (toRet.empty()) {
579  return {};
580  }
581 
582  while (toRet.size() > 1U) {
583  // Work odd unit into collapse sequence:
584  if (toRet.size() & 1U) {
585  toRet[toRet.size() - 2U].insert(toRet[toRet.size() - 1U].begin(), toRet[toRet.size() - 1U].end());
586  toRet.pop_back();
587  }
588 
589  const int64_t combineCount = (int64_t)(toRet.size() >> 1U);
590 #if ENABLE_PTHREAD
591  std::vector<std::future<void>> futures(combineCount);
592  for (int64_t i = (combineCount - 1); i >= 0; i--) {
593  futures[i] = std::async(std::launch::async, [i, combineCount, &toRet]() {
594  toRet[i].insert(toRet[i + combineCount].begin(), toRet[i + combineCount].end());
595  toRet[i + combineCount].clear();
596  });
597  }
598 
599  for (int64_t i = (combineCount - 1); i >= 0; i--) {
600  futures[i].get();
601  toRet.pop_back();
602  }
603 #else
604  for (int64_t i = (combineCount - 1); i >= 0; i--) {
605  toRet[i].insert(toRet[i + combineCount].begin(), toRet[i + combineCount].end());
606  toRet.pop_back();
607  }
608 #endif
609  }
610 
611  return toRet[0U];
612  }
613 };
614 
615 } // namespace Qrack
Definition: parallel_for.hpp:19
unsigned GetConcurrencyLevel()
Definition: parallel_for.hpp:41
void par_for(const bitCapIntOcl begin, const bitCapIntOcl end, ParallelFunc fn)
Call fn once for every numerical value between begin and end.
Definition: parallel_for.cpp:50
Definition: statevector.hpp:83
std::unique_ptr< complex[], void(*)(complex *)> Alloc(bitCapIntOcl elemCount)
Definition: statevector.hpp:97
void copy(StateVectorArrayPtr toCopy)
Definition: statevector.hpp:200
virtual ~StateVectorArray()
Definition: statevector.hpp:130
std::unique_ptr< complex[], void(*)(complex *)> amplitudes
Definition: statevector.hpp:85
complex read(const bitCapIntOcl &i)
Definition: statevector.hpp:132
void write(const bitCapIntOcl &i, const complex &c)
Definition: statevector.hpp:141
void copy_out(complex *copyOut, const bitCapIntOcl offset, const bitCapIntOcl length)
Definition: statevector.hpp:192
void clear()
Definition: statevector.hpp:149
virtual void Free()
Definition: statevector.hpp:120
void copy_in(StateVectorPtr copyInSv, const bitCapIntOcl srcOffset, const bitCapIntOcl dstOffset, const bitCapIntOcl length)
Definition: statevector.hpp:174
void get_probs(real1 *outArray)
Definition: statevector.hpp:218
void write2(const bitCapIntOcl &i1, const complex &c1, const bitCapIntOcl &i2, const complex &c2)
Optimized "write" that is only guaranteed to write if either amplitude is nonzero.
Definition: statevector.hpp:143
void copy_out(complex *copyOut)
Definition: statevector.hpp:187
void shuffle(StateVectorArrayPtr svp)
Definition: statevector.hpp:208
void shuffle(StateVectorPtr svp)
Definition: statevector.hpp:206
bool is_sparse()
Definition: statevector.hpp:224
void copy(StateVectorPtr toCopy)
Definition: statevector.hpp:198
void copy_in(const complex *copyIn, const bitCapIntOcl offset, const bitCapIntOcl length)
Definition: statevector.hpp:163
void copy_in(const complex *copyIn)
Definition: statevector.hpp:154
StateVectorArray(bitCapIntOcl cap)
Definition: statevector.hpp:123
Definition: statevector.hpp:227
void get_probs(real1 *outArray)
Definition: statevector.hpp:466
void shuffle(StateVectorPtr svp)
Definition: statevector.hpp:453
complex readLocked(const bitCapIntOcl &i)
Definition: statevector.hpp:238
size_t size()
Definition: statevector.hpp:251
std::set< bitCapIntOcl > iterable(const bitCapIntOcl &setMask, const bitCapIntOcl &filterMask=0, const bitCapIntOcl &filterValues=0)
Returns empty if iteration should be over full set, otherwise just the iterable elements:
Definition: statevector.hpp:536
std::vector< bitCapIntOcl > iterable()
Definition: statevector.hpp:475
real1_f truncate_to_size(size_t maxAmps)
Definition: statevector.hpp:261
void copy_out(complex *copyOut)
Definition: statevector.hpp:431
void write2(const bitCapIntOcl &i1, const complex &c1, const bitCapIntOcl &i2, const complex &c2)
Optimized "write" that is only guaranteed to write if either amplitude is nonzero.
Definition: statevector.hpp:339
void copy_out(complex *copyOut, const bitCapIntOcl offset, const bitCapIntOcl length)
Definition: statevector.hpp:438
void copy_in(const complex *copyIn, const bitCapIntOcl offset, const bitCapIntOcl length)
Definition: statevector.hpp:385
void copy_in(const complex *copyIn)
Definition: statevector.hpp:368
void write(const bitCapIntOcl &i, const complex &c)
Definition: statevector.hpp:327
std::mutex mtx
Definition: statevector.hpp:230
SparseStateVecMap amplitudes
Definition: statevector.hpp:229
StateVectorSparse(bitCapIntOcl cap)
Definition: statevector.hpp:245
complex read(const bitCapIntOcl &i)
Definition: statevector.hpp:315
complex readUnlocked(const bitCapIntOcl &i)
Definition: statevector.hpp:232
void copy_in(StateVectorPtr copyInSv, const bitCapIntOcl srcOffset, const bitCapIntOcl dstOffset, const bitCapIntOcl length)
Definition: statevector.hpp:406
void copy(StateVectorSparsePtr toCopy)
Definition: statevector.hpp:447
void clear()
Definition: statevector.hpp:362
void mult(real1_f nrm)
Definition: statevector.hpp:253
bool is_sparse()
Definition: statevector.hpp:473
void shuffle(StateVectorSparsePtr svp)
Definition: statevector.hpp:455
void copy(const StateVectorPtr toCopy)
Definition: statevector.hpp:445
Definition: statevector.hpp:45
bitCapIntOcl capacity
Definition: statevector.hpp:47
virtual void get_probs(real1 *outArray)=0
virtual void shuffle(StateVectorPtr svp)=0
virtual complex read(const bitCapIntOcl &i)=0
virtual void write(const bitCapIntOcl &i, const complex &c)=0
virtual void copy_out(complex *outArray)=0
virtual void copy_in(const complex *copyIn, const bitCapIntOcl offset, const bitCapIntOcl length)=0
virtual void copy_in(const complex *inArray)=0
virtual void copy_out(complex *copyIn, const bitCapIntOcl offset, const bitCapIntOcl length)=0
virtual void write2(const bitCapIntOcl &i1, const complex &c1, const bitCapIntOcl &i2, const complex &c2)=0
Optimized "write" that is only guaranteed to write if either amplitude is nonzero.
virtual void copy(StateVectorPtr toCopy)=0
virtual void clear()=0
StateVector(bitCapIntOcl cap)
Definition: statevector.hpp:52
bool isReadLocked
Definition: statevector.hpp:50
virtual void copy_in(StateVectorPtr copyInSv, const bitCapIntOcl srcOffset, const bitCapIntOcl dstOffset, const bitCapIntOcl length)=0
virtual ~StateVector()
Definition: statevector.hpp:57
virtual bool is_sparse()=0
Half-precision floating-point type.
Definition: half.hpp:2222
GLOSSARY: bitLenInt - "bit-length integer" - unsigned integer ID of qubit position in register bitCap...
Definition: complex16x2simd.hpp:25
void U(quid sid, bitLenInt q, real1_f theta, real1_f phi, real1_f lambda)
(External API) 3-parameter unitary gate
Definition: wasm_api.cpp:1199
half_float::half real1
Definition: qrack_types.hpp:102
std::complex< real1 > complex
Definition: qrack_types.hpp:136
std::shared_ptr< StateVectorSparse > StateVectorSparsePtr
Definition: qrack_types.hpp:155
double norm(const complex2 &c)
Definition: complex16x2simd.hpp:122
QRACK_CONST real1 REAL1_EPSILON
Definition: qrack_types.hpp:208
QRACK_CONST real1 ONE_R1
Definition: qrack_types.hpp:193
QRACK_CONST real1 ZERO_R1
Definition: qrack_types.hpp:191
float real1_f
Definition: qrack_types.hpp:103
std::shared_ptr< StateVectorArray > StateVectorArrayPtr
Definition: qrack_types.hpp:154
float real1_s
Definition: qrack_types.hpp:104
std::shared_ptr< StateVector > StateVectorPtr
Definition: qrack_types.hpp:151
QRACK_CONST complex ZERO_CMPLX
Definition: qrack_types.hpp:263
uint32 sqrt(uint32 &r, int &exp)
Fixed point square root.
Definition: half.hpp:1654
HALF_CONSTEXPR half abs(half arg)
Absolute value.
Definition: half.hpp:2975
#define bitCapIntOcl
Definition: qrack_types.hpp:54
#define ONE_R1_F
Definition: qrack_types.hpp:171
#define QRACK_ALIGN_SIZE
Definition: qrack_types.hpp:165
#define SparseStateVecMap
Definition: statevector.hpp:29
SIMD implementation of the double precision complex vector type of 2 complex numbers,...
Definition: complex16x2simd.hpp:30