42 #ifndef QRACK_TURBO_BITS
43 #define QRACK_TURBO_BITS 4
58 std::mt19937_64 rng(
seed);
60 std::vector<real1>
R(d * d);
62 v = (
real1)normal(rng);
64 for (
size_t j = 0
U; j < d; ++j) {
66 for (
size_t i = 0
U; i < d; ++i) {
67 nrm +=
R[j * d + i] *
R[j * d + i];
70 if (nrm < (
real1)1e-8)
72 for (
size_t i = 0
U; i < d; ++i) {
75 for (
size_t k = j + 1U; k < d; ++k) {
77 for (
size_t i = 0
U; i < d; ++i) {
78 dot +=
R[j * d + i] *
R[k * d + i];
80 for (
size_t i = 0
U; i < d; ++i) {
81 R[k * d + i] -= dot *
R[j * d + i];
92 std::random_device rd;
93 *seed_out = ((uint64_t)rd() << 32U) | (uint64_t)rd();
98 static inline std::vector<real1>
_tq_transpose(
const std::vector<real1>&
R,
const size_t d)
100 std::vector<real1>
T(d * d);
101 for (
size_t i = 0
U; i < d; ++i)
102 for (
size_t j = 0
U; j < d; ++j)
103 T[i * d + j] =
R[j * d + i];
111 for (
size_t i = 0
U; i < d; ++i) {
113 for (
size_t j = 0
U; j < d; ++j) {
114 s +=
R[j * d + i] * v[j];
123 const int levels = 1 << bits;
127 if (step < (
real1)1e-8)
129 const real1 clamped = std::max(lo, std::min(hi - step, val));
130 int bucket = (int)((clamped - lo) / step);
133 if (bucket >= levels)
141 const int levels = 1 << bits;
145 return lo + ((
real1)bucket + (
real1)0.5) * step;
153 os.write(
reinterpret_cast<const char*
>(&x),
sizeof(
size_t));
157 os.write(
reinterpret_cast<const char*
>(&x),
sizeof(
int));
161 os.write(
reinterpret_cast<const char*
>(&x),
sizeof(
bool));
166 is.read(
reinterpret_cast<char*
>(&x),
sizeof(
size_t));
172 is.read(
reinterpret_cast<char*
>(&x),
sizeof(
int));
178 is.read(
reinterpret_cast<char*
>(&x),
sizeof(
bool));
221 std::vector<real1>
R;
222 std::vector<real1>
RT;
241 ,
NWORDS((2U * (1ULL << p) * b + 63U) / 64U)
242 ,
packed(new uint64_t[(2U * (1ULL << p) * b + 63U) / 64U])
285 const size_t bit_offset = idx * (size_t)
BITS;
286 const size_t word = bit_offset / 64U;
287 const size_t bit = bit_offset % 64U;
288 const uint64_t mask = (uint64_t)(
LEVELS - 1) << bit;
289 packed[word] = (
packed[word] & ~mask) | ((uint64_t)bucket << bit);
290 if (bit + (
size_t)
BITS > 64U) {
292 const uint64_t mask2 = ((uint64_t)1 <<
overflow) - 1U;
300 const size_t bit_offset = idx * (size_t)
BITS;
301 const size_t word = bit_offset / 64U;
302 const size_t bit = bit_offset % 64U;
303 int bucket = (int)((
packed[word] >> bit) & (uint64_t)(
LEVELS - 1));
304 if (bit + (
size_t)
BITS > 64U) {
306 const int high = (int)(
packed[word + 1U] & (((uint64_t)1 <<
overflow) - 1U));
318 const size_t D2 = 2U *
D;
319 std::vector<real1> v_in(D2), v_rot(D2);
320 for (
size_t i = 0
U; i <
D; ++i) {
321 v_in[2U * i] = real(amps[i]);
322 v_in[2U * i + 1U] = imag(amps[i]);
331 for (
size_t j = 0
U; j < D2; ++j) {
332 sum += v_rot[j] * v_rot[j];
339 for (
size_t j = 0
U; j < D2; ++j) {
347 const size_t D2 = 2U *
D;
348 std::vector<real1> v_rot(D2), v_out(D2);
349 for (
size_t j = 0
U; j < D2; ++j) {
353 for (
size_t i = 0
U; i <
D; ++i) {
354 amps[i] =
complex(v_out[2U * i], v_out[2U * i + 1U]);
363 const size_t D2 = 2U *
D;
364 for (
size_t j = 0
U; j < D2; ++j) {
383 void save(std::ostream& os)
const
388 os.write(
reinterpret_cast<const char*
>(&
seed),
sizeof(uint64_t));
393 os.write(
reinterpret_cast<const char*
>(
packed.get()), (std::streamsize)(
NWORDS *
sizeof(uint64_t)));
404 for (
size_t tmp = D_in; tmp > 1U; tmp >>= 1U) {
409 is.read(
reinterpret_cast<char*
>(&seed_in),
sizeof(uint64_t));
424 blk.
packed.reset(
new uint64_t[nwords]);
425 is.read(
reinterpret_cast<char*
>(blk.
packed.get()), (std::streamsize)(nwords *
sizeof(uint64_t)));
446 class StateVectorTurboQuant;
462 std::vector<complex> amps(
BLOCK);
463 blocks[b].decompress(amps.data());
464 f(amps.data(),
BLOCK);
465 blocks[b].compress(amps.data());
473 ,
num_blocks((cap + (1ULL << p) - 1U) / (1ULL << p))
490 void save(std::ostream& os)
const
507 for (
size_t tmp = block_size; tmp > 1U; tmp >>= 1U) {
512 std::vector<TurboBlock> loaded;
513 loaded.reserve(nblocks);
514 for (
size_t i = 0
U; i < nblocks; ++i) {
521 auto sv = std::make_shared<StateVectorTurboQuant>(cap, p, bits,
nullptr);
522 sv->blocks = std::move(loaded);
544 std::vector<complex> amps(
BLOCK);
549 #if ENABLE_COMPLEX_X2
574 const size_t blo = std::min(b1, b2), bhi = std::max(b1, b2);
578 blocks[b1].decompress(a1.data());
579 blocks[b2].decompress(a2.data());
582 blocks[b1].compress(a1.data());
583 blocks[b2].compress(a2.data());
591 blocks[b].compress(z.data());
601 std::copy(copyIn + b *
BLOCK, copyIn + b *
BLOCK + len, amps.data());
603 blocks[b].compress(amps.data());
612 const size_t b1 =
block_of(offset + length - 1U);
613 for (
size_t b = b0; b <= b1; ++b) {
615 const size_t base = b *
BLOCK;
616 for (
size_t j = 0
U; j <
BLOCK; ++j) {
617 const size_t g = base + j;
618 if (g >= (
size_t)offset && g < (
size_t)(offset + length))
619 amps[j] = copyIn ? copyIn[g - offset] :
ZERO_CMPLX;
630 tmp[i] = sv->read(src + i);
631 copy_in(sv ? tmp.data() :
nullptr, dst, len);
637 std::vector<complex> amps(
BLOCK);
638 blocks[b].decompress(amps.data());
640 std::copy(amps.data(), amps.data() + len, out + b *
BLOCK);
647 out[i] =
read(offset + i);
652 auto src = std::dynamic_pointer_cast<StateVectorTurboQuant>(toCopy);
656 blocks[b] = src->blocks[b];
660 toCopy->copy_out(tmp.data());
669 auto other = std::dynamic_pointer_cast<StateVectorTurboQuant>(svp);
671 const size_t hb = (size_t)(half /
BLOCK);
672 if (other && (half %
BLOCK == 0
U)) {
675 0
U, hb, [&](
const bitCapIntOcl& b,
const unsigned&) { std::swap(
blocks[b + hb], other->blocks[b]); });
680 svp->write(i,
read(i + half));
681 write(i + half, amp);
691 std::vector<complex> amps(
BLOCK);
692 blocks[b].decompress(amps.data());
694 for (
size_t j = 0
U; j < len; ++j)
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_turboquant.hpp:449
void copy_in(const complex *copyIn)
Definition: statevector_turboquant.hpp:595
std::vector< TurboBlock > blocks
Definition: statevector_turboquant.hpp:453
void shuffle(StateVectorPtr svp)
Definition: statevector_turboquant.hpp:665
void copy(StateVectorPtr toCopy)
Definition: statevector_turboquant.hpp:650
void write2(const bitCapInt &i1, const complex &c1, const bitCapInt &i2, const complex &c2)
Definition: statevector_turboquant.hpp:560
bitCapIntOcl get_size()
Definition: statevector_turboquant.hpp:480
void get_probs(real1 *outArray)
Definition: statevector_turboquant.hpp:686
complex read(const bitCapIntOcl &i)
Definition: statevector_turboquant.hpp:542
size_t block_of(const bitCapIntOcl i) const
Definition: statevector_turboquant.hpp:456
void clear()
Definition: statevector_turboquant.hpp:587
void copy_out(complex *out)
Definition: statevector_turboquant.hpp:634
bool is_sparse()
Definition: statevector_turboquant.hpp:699
complex read(const bitCapInt &i)
Definition: statevector_turboquant.hpp:541
friend std::istream & operator>>(std::istream &is, StateVectorTurboQuantPtr &sv)
Definition: statevector_turboquant.hpp:533
void with_block(const size_t b, F &&f)
Definition: statevector_turboquant.hpp:459
void write(const bitCapIntOcl &i, const complex &c)
Definition: statevector_turboquant.hpp:555
void save(std::ostream &os) const
Definition: statevector_turboquant.hpp:490
friend std::ostream & operator<<(std::ostream &os, const StateVectorTurboQuant &sv)
Definition: statevector_turboquant.hpp:527
StateVectorTurboQuant(bitCapIntOcl cap, int p, int b, const complex *copyIn)
Definition: statevector_turboquant.hpp:470
void copy_in(const complex *copyIn, const bitCapIntOcl offset, const bitCapIntOcl length)
Definition: statevector_turboquant.hpp:607
static StateVectorTurboQuantPtr load(std::istream &is)
Definition: statevector_turboquant.hpp:500
size_t BLOCK
Definition: statevector_turboquant.hpp:451
void copy_out(complex *out, const bitCapIntOcl offset, const bitCapIntOcl length)
Definition: statevector_turboquant.hpp:644
size_t num_blocks
Definition: statevector_turboquant.hpp:452
size_t offset_in(const bitCapIntOcl i) const
Definition: statevector_turboquant.hpp:457
void write(const bitCapInt &i, const complex &c)
Definition: statevector_turboquant.hpp:554
void copy_in(StateVectorPtr sv, const bitCapIntOcl src, const bitCapIntOcl dst, const bitCapIntOcl len)
Definition: statevector_turboquant.hpp:625
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_turboquant.hpp:565
std::vector< std::mutex > block_mutexes
Definition: statevector_turboquant.hpp:454
Definition: statevector.hpp:50
bitCapIntOcl capacity
Definition: statevector.hpp:52
Half-precision floating-point type.
Definition: half.hpp:2206
GLOSSARY: bitLenInt - "bit-length integer" - unsigned integer ID of qubit position in register bitCap...
Definition: complex16x2simd.hpp:25
quid init()
"Quasi-default constructor" (for an empty simulator)
Definition: wasm_api.cpp:634
void T(quid sid, bitLenInt q)
(External API) "T" Gate
Definition: wasm_api.cpp:1154
static std::vector< real1 > _tq_make_rotation(const size_t d, const uint64_t seed)
Definition: statevector_turboquant.hpp:56
std::shared_ptr< StateVectorTurboQuant > StateVectorTurboQuantPtr
Definition: statevector_turboquant.hpp:446
void seed(quid sid, unsigned s)
"Seed" random number generator (if pseudo-random Mersenne twister is in use)
Definition: wasm_api.cpp:873
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:106
std::complex< real1 > complex
Definition: qrack_types.hpp:140
static void _tq_write_int(std::ostream &os, const int x)
Definition: statevector_turboquant.hpp:155
double norm(const complex2 &c)
Definition: complex16x2simd.hpp:122
static size_t _tq_read_size(std::istream &is)
Definition: statevector_turboquant.hpp:163
void R(quid sid, real1_f phi, QubitPauliBasis q)
(External API) Rotation around Pauli axes
Definition: wasm_api.cpp:1485
QRACK_CONST real1 ONE_R1
Definition: qrack_types.hpp:188
static int _tq_read_int(std::istream &is)
Definition: statevector_turboquant.hpp:169
QRACK_CONST real1 ZERO_R1
Definition: qrack_types.hpp:186
static real1 _tq_dequant(const int bucket, const real1 scale, const int bits)
Definition: statevector_turboquant.hpp:139
static std::vector< real1 > _tq_transpose(const std::vector< real1 > &R, const size_t d)
Definition: statevector_turboquant.hpp:98
static void _tq_write_size(std::ostream &os, const size_t x)
Definition: statevector_turboquant.hpp:151
static int _tq_quant_bucket(const real1 val, const real1 scale, const int bits)
Definition: statevector_turboquant.hpp:121
std::shared_ptr< StateVector > StateVectorPtr
Definition: qrack_types.hpp:147
QRACK_CONST complex ZERO_CMPLX
Definition: qrack_types.hpp:258
static void _tq_rotate(const real1 *v, const std::vector< real1 > &R, const size_t d, real1 *out)
Definition: statevector_turboquant.hpp:109
static bool _tq_read_bool(std::istream &is)
Definition: statevector_turboquant.hpp:175
static void _tq_write_bool(std::ostream &os, const bool x)
Definition: statevector_turboquant.hpp:159
uint32 sqrt(uint32 &r, int &exp)
Fixed point square root.
Definition: half.hpp:1638
HALF_CONSTEXPR_NOERR unsigned int overflow(unsigned int sign=0)
Half-precision overflow.
Definition: half.hpp:815
#define ZERO_R1_F
Definition: qrack_types.hpp:162
#define bitCapInt
Definition: qrack_types.hpp:65
#define bitCapIntOcl
Definition: qrack_types.hpp:53
#define ONE_R1_F
Definition: qrack_types.hpp:165
#define QRACK_TURBO_BITS
Definition: statevector_turboquant.hpp:43
Definition: statevector_turboquant.hpp:210
void pack_bucket(const size_t idx, const int bucket)
Definition: statevector_turboquant.hpp:283
uint64_t seed
Definition: statevector_turboquant.hpp:217
friend std::istream & operator>>(std::istream &is, TurboBlock &b)
Definition: statevector_turboquant.hpp:436
real1 get_total_prob() const
Definition: statevector_turboquant.hpp:360
bool initialized
Definition: statevector_turboquant.hpp:231
std::vector< real1 > R
Definition: statevector_turboquant.hpp:221
std::unique_ptr< uint64_t[]> packed
Definition: statevector_turboquant.hpp:230
size_t D
Definition: statevector_turboquant.hpp:211
TurboBlock(const TurboBlock &o)
Definition: statevector_turboquant.hpp:248
real1 block_scale
Definition: statevector_turboquant.hpp:226
void compress(const complex *amps)
Definition: statevector_turboquant.hpp:314
friend std::ostream & operator<<(std::ostream &os, const TurboBlock &b)
Definition: statevector_turboquant.hpp:430
size_t NWORDS
Definition: statevector_turboquant.hpp:229
TurboBlock(int p, int b)
Definition: statevector_turboquant.hpp:233
static TurboBlock load(std::istream &is)
Definition: statevector_turboquant.hpp:396
int LEVELS
Definition: statevector_turboquant.hpp:213
TurboBlock & operator=(const TurboBlock &o)
Definition: statevector_turboquant.hpp:263
void save(std::ostream &os) const
Definition: statevector_turboquant.hpp:383
std::vector< real1 > RT
Definition: statevector_turboquant.hpp:222
int BITS
Definition: statevector_turboquant.hpp:212
int unpack_bucket(const size_t idx) const
Definition: statevector_turboquant.hpp:298
void decompress(complex *amps) const
Definition: statevector_turboquant.hpp:345
SIMD implementation of the double precision complex vector type of 2 complex numbers,...
Definition: complex16x2simd.hpp:30