Skip to content

Commit c97b0be

Browse files
committed
UPDATE:
1. using `C++20` feature `requires` to enforce that `n_qubits` is always greater than 0 at compile-time.
1 parent 2c64942 commit c97b0be

File tree

1 file changed

+26
-0
lines changed

1 file changed

+26
-0
lines changed

qubitverse/simulator/gates/gates.hh

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
namespace simulator
1515
{
1616
template <std::size_t n_qubits = 1>
17+
requires(n_qubits > 0)
1718
class qubit
1819
{
1920
public:
@@ -91,6 +92,7 @@ namespace simulator
9192
};
9293

9394
template <std::size_t n_qubits>
95+
requires(n_qubits > 0)
9496
void qubit<n_qubits>::apply_predefined_gate(complex (&__s)[1 << n_qubits], const gate_type &__g_type, const std::size_t &qubit_target)
9597
{
9698
const std::size_t stride = 1 << qubit_target; // Distance between paired indices
@@ -113,6 +115,7 @@ namespace simulator
113115
}
114116

115117
template <std::size_t n_qubits>
118+
requires(n_qubits > 0)
116119
qubit<n_qubits>::qgate_2x2 &qubit<n_qubits>::get_theta_gate(qgate_2x2 &__g, const gate_type &__g_type, const double &__theta)
117120
{
118121
__g.type = __g_type;
@@ -154,6 +157,7 @@ namespace simulator
154157
}
155158

156159
template <std::size_t n_qubits>
160+
requires(n_qubits > 0)
157161
void qubit<n_qubits>::apply_theta_gate(complex (&__s)[1 << n_qubits], const gate_type &__g_type, const double &__theta, const std::size_t &qubit_target)
158162
{
159163
const std::size_t stride = 1 << qubit_target; // Distance between paired indices
@@ -178,6 +182,7 @@ namespace simulator
178182
}
179183

180184
template <std::size_t n_qubits>
185+
requires(n_qubits > 0)
181186
void qubit<n_qubits>::apply_2qubit_gate(complex (&__s)[1 << n_qubits], const gate_type &__g_type, const std::size_t &q_control, const std::size_t &q_target)
182187
{
183188
if (n_qubits < 2)
@@ -235,134 +240,154 @@ namespace simulator
235240
}
236241

237242
template <std::size_t n_qubits>
243+
requires(n_qubits > 0)
238244
qubit<n_qubits>::qubit()
239245
{
240246
this->M_qubits[0] = {1, 0};
241247
}
242248

243249
template <std::size_t n_qubits>
250+
requires(n_qubits > 0)
244251
qubit<n_qubits> &qubit<n_qubits>::apply_identity(const std::size_t &q_target)
245252
{
246253
qubit::apply_predefined_gate(this->M_qubits, gate_type::IDENTITY, q_target);
247254
return *this;
248255
}
249256

250257
template <std::size_t n_qubits>
258+
requires(n_qubits > 0)
251259
qubit<n_qubits> &qubit<n_qubits>::apply_pauli_x(const std::size_t &q_target)
252260
{
253261
qubit::apply_predefined_gate(this->M_qubits, gate_type::PAULI_X, q_target);
254262
return *this;
255263
}
256264

257265
template <std::size_t n_qubits>
266+
requires(n_qubits > 0)
258267
qubit<n_qubits> &qubit<n_qubits>::apply_pauli_y(const std::size_t &q_target)
259268
{
260269
qubit::apply_predefined_gate(this->M_qubits, gate_type::PAULI_Y, q_target);
261270
return *this;
262271
}
263272

264273
template <std::size_t n_qubits>
274+
requires(n_qubits > 0)
265275
qubit<n_qubits> &qubit<n_qubits>::apply_pauli_z(const std::size_t &q_target)
266276
{
267277
qubit::apply_predefined_gate(this->M_qubits, gate_type::PAULI_Z, q_target);
268278
return *this;
269279
}
270280

271281
template <std::size_t n_qubits>
282+
requires(n_qubits > 0)
272283
qubit<n_qubits> &qubit<n_qubits>::apply_hadamard(const std::size_t &q_target)
273284
{
274285
qubit::apply_predefined_gate(this->M_qubits, gate_type::HADAMARD, q_target);
275286
return *this;
276287
}
277288

278289
template <std::size_t n_qubits>
290+
requires(n_qubits > 0)
279291
qubit<n_qubits> &qubit<n_qubits>::apply_phase_pi_2_shift(const std::size_t &q_target)
280292
{
281293
qubit::apply_predefined_gate(this->M_qubits, gate_type::PHASE_PI_2_SHIFT, q_target);
282294
return *this;
283295
}
284296

285297
template <std::size_t n_qubits>
298+
requires(n_qubits > 0)
286299
qubit<n_qubits> &qubit<n_qubits>::apply_phase_pi_4_shift(const std::size_t &q_target)
287300
{
288301
qubit::apply_predefined_gate(this->M_qubits, gate_type::PHASE_PI_4_SHIFT, q_target);
289302
return *this;
290303
}
291304

292305
template <std::size_t n_qubits>
306+
requires(n_qubits > 0)
293307
qubit<n_qubits> &qubit<n_qubits>::apply_phase_general_shift(const double &_theta, const std::size_t &q_target)
294308
{
295309
qubit::apply_theta_gate(this->M_qubits, gate_type::PHASE_GENERAL_SHIFT, _theta, q_target);
296310
return *this;
297311
}
298312

299313
template <std::size_t n_qubits>
314+
requires(n_qubits > 0)
300315
qubit<n_qubits> &qubit<n_qubits>::apply_rotation_x(const double &_theta, const std::size_t &q_target)
301316
{
302317
qubit::apply_theta_gate(this->M_qubits, gate_type::ROTATION_X, _theta, q_target);
303318
return *this;
304319
}
305320

306321
template <std::size_t n_qubits>
322+
requires(n_qubits > 0)
307323
qubit<n_qubits> &qubit<n_qubits>::apply_rotation_y(const double &_theta, const std::size_t &q_target)
308324
{
309325
qubit::apply_theta_gate(this->M_qubits, gate_type::ROTATION_Y, _theta, q_target);
310326
return *this;
311327
}
312328

313329
template <std::size_t n_qubits>
330+
requires(n_qubits > 0)
314331
qubit<n_qubits> &qubit<n_qubits>::apply_rotation_z(const double &_theta, const std::size_t &q_target)
315332
{
316333
qubit::apply_theta_gate(this->M_qubits, gate_type::ROTATION_Z, _theta, q_target);
317334
return *this;
318335
}
319336

320337
template <std::size_t n_qubits>
338+
requires(n_qubits > 0)
321339
qubit<n_qubits> &qubit<n_qubits>::apply_cnot(const std::size_t &q_control, const std::size_t &q_target)
322340
{
323341
qubit::apply_2qubit_gate(this->M_qubits, gate_type::CONTROLLED_NOT, q_control, q_target);
324342
return *this;
325343
}
326344

327345
template <std::size_t n_qubits>
346+
requires(n_qubits > 0)
328347
qubit<n_qubits> &qubit<n_qubits>::apply_cz(const std::size_t &q_control, const std::size_t &q_target)
329348
{
330349
qubit::apply_2qubit_gate(this->M_qubits, gate_type::CONTROLLED_Z, q_control, q_target);
331350
return *this;
332351
}
333352

334353
template <std::size_t n_qubits>
354+
requires(n_qubits > 0)
335355
qubit<n_qubits> &qubit<n_qubits>::apply_swap(const std::size_t &q_control, const std::size_t &q_target)
336356
{
337357
qubit::apply_2qubit_gate(this->M_qubits, gate_type::SWAP_GATE, q_control, q_target);
338358
return *this;
339359
}
340360

341361
template <std::size_t n_qubits>
362+
requires(n_qubits > 0)
342363
const qubit<n_qubits>::complex (&qubit<n_qubits>::get_qubits() const)[1 << n_qubits]
343364
{
344365
return this->M_qubits;
345366
}
346367

347368
template <std::size_t n_qubits>
369+
requires(n_qubits > 0)
348370
const constexpr std::size_t qubit<n_qubits>::get_size() const
349371
{
350372
return 1 << n_qubits;
351373
}
352374

353375
template <std::size_t n_qubits>
376+
requires(n_qubits > 0)
354377
const constexpr std::size_t qubit<n_qubits>::memory_consumption() const
355378
{
356379
return sizeof(complex) * (1 << n_qubits);
357380
}
358381

359382
template <std::size_t n_qubits>
383+
requires(n_qubits > 0)
360384
const constexpr std::size_t qubit<n_qubits>::no_of_qubits() const
361385
{
362386
return n_qubits;
363387
}
364388

365389
template <std::size_t n_qubits>
390+
requires(n_qubits > 0)
366391
void qubit<n_qubits>::get_nth_qubit(complex (&__s)[2], const std::size_t &nth) const
367392
{
368393
std::size_t mask = 1 << (n_qubits - nth - 1);
@@ -383,6 +408,7 @@ namespace simulator
383408
}
384409

385410
template <std::size_t n_qubits>
411+
requires(n_qubits > 0)
386412
std::size_t qubit<n_qubits>::measure()
387413
{
388414
double tot_prob = 0.0;

0 commit comments

Comments
 (0)