1#[doc = " A logger of QASM instructions\n\n @ingroup type\n @author Tyson Jones"]
4#[repr(C)]
5#[derive(Debug, Copy, Clone)]
6pub struct QASMLogger {
7 pub buffer: *mut ::std::os::raw::c_char,
8 pub bufferSize: ::std::os::raw::c_int,
9 pub bufferFill: ::std::os::raw::c_int,
10 pub isLogging: ::std::os::raw::c_int,
11}
12#[test]
13fn bindgen_test_layout_QASMLogger() {
14 const UNINIT: ::std::mem::MaybeUninit<QASMLogger> = ::std::mem::MaybeUninit::uninit();
15 let ptr = UNINIT.as_ptr();
16 assert_eq!(::std::mem::size_of::<QASMLogger>(), 24usize,);
17 assert_eq!(::std::mem::align_of::<QASMLogger>(), 8usize,);
18 assert_eq!(
19 unsafe { ::std::ptr::addr_of!((*ptr).buffer) as usize - ptr as usize },
20 0usize,
21 );
22 assert_eq!(
23 unsafe { ::std::ptr::addr_of!((*ptr).bufferSize) as usize - ptr as usize },
24 8usize,
25 );
26 assert_eq!(
27 unsafe { ::std::ptr::addr_of!((*ptr).bufferFill) as usize - ptr as usize },
28 12usize,
29 );
30 assert_eq!(
31 unsafe { ::std::ptr::addr_of!((*ptr).isLogging) as usize - ptr as usize },
32 16usize,
33 );
34}
35#[doc = " Represents an array of complex numbers grouped into an array of\n real components and an array of coressponding complex components.\n\n @ingroup type\n @author Ania Brown"]
36#[repr(C)]
37#[derive(Debug, Copy, Clone)]
38pub struct ComplexArray {
39 pub real: *mut f64,
40 pub imag: *mut f64,
41}
42#[test]
43fn bindgen_test_layout_ComplexArray() {
44 const UNINIT: ::std::mem::MaybeUninit<ComplexArray> = ::std::mem::MaybeUninit::uninit();
45 let ptr = UNINIT.as_ptr();
46 assert_eq!(::std::mem::size_of::<ComplexArray>(), 16usize,);
47 assert_eq!(::std::mem::align_of::<ComplexArray>(), 8usize,);
48 assert_eq!(
49 unsafe { ::std::ptr::addr_of!((*ptr).real) as usize - ptr as usize },
50 0usize,
51 );
52 assert_eq!(
53 unsafe { ::std::ptr::addr_of!((*ptr).imag) as usize - ptr as usize },
54 8usize,
55 );
56}
57pub const pauliOpType_PAULI_I: pauliOpType = 0;
58pub const pauliOpType_PAULI_X: pauliOpType = 1;
59pub const pauliOpType_PAULI_Y: pauliOpType = 2;
60pub const pauliOpType_PAULI_Z: pauliOpType = 3;
61#[doc = " Codes for specifying Pauli operators\n\n @ingroup type\n @author Tyson Jones"]
62pub type pauliOpType = ::std::os::raw::c_uint;
63#[doc = " Represents one complex number.\n\n @ingroup type\n @author Ania Brown"]
64#[repr(C)]
65#[derive(Debug, Copy, Clone)]
66pub struct Complex {
67 pub real: f64,
68 pub imag: f64,
69}
70#[test]
71fn bindgen_test_layout_Complex() {
72 const UNINIT: ::std::mem::MaybeUninit<Complex> = ::std::mem::MaybeUninit::uninit();
73 let ptr = UNINIT.as_ptr();
74 assert_eq!(::std::mem::size_of::<Complex>(), 16usize,);
75 assert_eq!(::std::mem::align_of::<Complex>(), 8usize,);
76 assert_eq!(
77 unsafe { ::std::ptr::addr_of!((*ptr).real) as usize - ptr as usize },
78 0usize,
79 );
80 assert_eq!(
81 unsafe { ::std::ptr::addr_of!((*ptr).imag) as usize - ptr as usize },
82 8usize,
83 );
84}
85#[doc = " Represents a 2x2 matrix of complex numbers.\n\n In C, a ::ComplexMatrix2 can be initialised by separately specifying\n the real and imaginary components as nested arrays. \\n\n For example,\n ```\n ComplexMatrix2 m = {\n .real = {{1,2},\n {3,4}},\n .imag = {{5,6},\n {7, 8}}};\n ```\n specifies matrix\n \\f[\n m = \\begin{pmatrix}\n 1 + 5\\,i & 2+6\\,i \\\\\n 3 + 7\\,i & 4+ 8\\,i\n \\end{pmatrix}\n \\f]\n\n @see\n - ::ComplexMatrix4\n - createComplexMatrixN()\n\n @ingroup type\n @author Balint Koczor\n @author Tyson Jones (doc)"]
86#[repr(C)]
87#[derive(Debug, Copy, Clone)]
88pub struct ComplexMatrix2 {
89 pub real: [[f64; 2usize]; 2usize],
90 pub imag: [[f64; 2usize]; 2usize],
91}
92#[test]
93fn bindgen_test_layout_ComplexMatrix2() {
94 const UNINIT: ::std::mem::MaybeUninit<ComplexMatrix2> = ::std::mem::MaybeUninit::uninit();
95 let ptr = UNINIT.as_ptr();
96 assert_eq!(::std::mem::size_of::<ComplexMatrix2>(), 64usize,);
97 assert_eq!(::std::mem::align_of::<ComplexMatrix2>(), 8usize,);
98 assert_eq!(
99 unsafe { ::std::ptr::addr_of!((*ptr).real) as usize - ptr as usize },
100 0usize,
101 );
102 assert_eq!(
103 unsafe { ::std::ptr::addr_of!((*ptr).imag) as usize - ptr as usize },
104 32usize,
105 );
106}
107#[doc = " Represents a 4x4 matrix of complex numbers\n\n In C, a ::ComplexMatrix4 can be initialised by separately specifying\n the real and imaginary components as nested arrays. Note that in C99, a short row\n that ends with a 0 with be padded with 0. \\n\n For example,\n ```\n ComplexMatrix4 m = {\n .real = {{1,2, 3, 4},\n {0},\n {5,6,7,8},\n {0}},\n .imag = {{0},{0},{0},{1,1,1,1}}};\n ```\n specifies matrix\n \\f[\n m = \\begin{pmatrix}\n 1 & 2 & 3 & 4 \\\\\n 0 & 0 & 0 & 0 \\\\\n 5 & 6 & 7 & 8 \\\\\n i & i & i & i\n \\end{pmatrix}\n \\f]\n\n @see\n - ::ComplexMatrix2\n - createComplexMatrixN()\n\n @ingroup type\n @author Balint Koczor\n @author Tyson Jones (doc)"]
108#[repr(C)]
109#[derive(Debug, Copy, Clone)]
110pub struct ComplexMatrix4 {
111 pub real: [[f64; 4usize]; 4usize],
112 pub imag: [[f64; 4usize]; 4usize],
113}
114#[test]
115fn bindgen_test_layout_ComplexMatrix4() {
116 const UNINIT: ::std::mem::MaybeUninit<ComplexMatrix4> = ::std::mem::MaybeUninit::uninit();
117 let ptr = UNINIT.as_ptr();
118 assert_eq!(::std::mem::size_of::<ComplexMatrix4>(), 256usize,);
119 assert_eq!(::std::mem::align_of::<ComplexMatrix4>(), 8usize,);
120 assert_eq!(
121 unsafe { ::std::ptr::addr_of!((*ptr).real) as usize - ptr as usize },
122 0usize,
123 );
124 assert_eq!(
125 unsafe { ::std::ptr::addr_of!((*ptr).imag) as usize - ptr as usize },
126 128usize,
127 );
128}
129#[doc = " Represents a general 2^N by 2^N matrix of complex numbers.\n\n @ingroup type\n @author Tyson Jones"]
130#[repr(C)]
131#[derive(Debug, Copy, Clone)]
132pub struct ComplexMatrixN {
133 pub numQubits: ::std::os::raw::c_int,
134 pub real: *mut *mut f64,
135 pub imag: *mut *mut f64,
136}
137#[test]
138fn bindgen_test_layout_ComplexMatrixN() {
139 const UNINIT: ::std::mem::MaybeUninit<ComplexMatrixN> = ::std::mem::MaybeUninit::uninit();
140 let ptr = UNINIT.as_ptr();
141 assert_eq!(::std::mem::size_of::<ComplexMatrixN>(), 24usize,);
142 assert_eq!(::std::mem::align_of::<ComplexMatrixN>(), 8usize,);
143 assert_eq!(
144 unsafe { ::std::ptr::addr_of!((*ptr).numQubits) as usize - ptr as usize },
145 0usize,
146 );
147 assert_eq!(
148 unsafe { ::std::ptr::addr_of!((*ptr).real) as usize - ptr as usize },
149 8usize,
150 );
151 assert_eq!(
152 unsafe { ::std::ptr::addr_of!((*ptr).imag) as usize - ptr as usize },
153 16usize,
154 );
155}
156#[doc = " Represents a 3-vector of real numbers\n\n @ingroup type\n @author Ania Brown"]
157#[repr(C)]
158#[derive(Debug, Copy, Clone)]
159pub struct Vector {
160 pub x: f64,
161 pub y: f64,
162 pub z: f64,
163}
164#[test]
165fn bindgen_test_layout_Vector() {
166 const UNINIT: ::std::mem::MaybeUninit<Vector> = ::std::mem::MaybeUninit::uninit();
167 let ptr = UNINIT.as_ptr();
168 assert_eq!(::std::mem::size_of::<Vector>(), 24usize,);
169 assert_eq!(::std::mem::align_of::<Vector>(), 8usize,);
170 assert_eq!(
171 unsafe { ::std::ptr::addr_of!((*ptr).x) as usize - ptr as usize },
172 0usize,
173 );
174 assert_eq!(
175 unsafe { ::std::ptr::addr_of!((*ptr).y) as usize - ptr as usize },
176 8usize,
177 );
178 assert_eq!(
179 unsafe { ::std::ptr::addr_of!((*ptr).z) as usize - ptr as usize },
180 16usize,
181 );
182}
183pub const phaseFunc_NORM: phaseFunc = 0;
184pub const phaseFunc_SCALED_NORM: phaseFunc = 1;
185pub const phaseFunc_INVERSE_NORM: phaseFunc = 2;
186pub const phaseFunc_SCALED_INVERSE_NORM: phaseFunc = 3;
187pub const phaseFunc_SCALED_INVERSE_SHIFTED_NORM: phaseFunc = 4;
188pub const phaseFunc_PRODUCT: phaseFunc = 5;
189pub const phaseFunc_SCALED_PRODUCT: phaseFunc = 6;
190pub const phaseFunc_INVERSE_PRODUCT: phaseFunc = 7;
191pub const phaseFunc_SCALED_INVERSE_PRODUCT: phaseFunc = 8;
192pub const phaseFunc_DISTANCE: phaseFunc = 9;
193pub const phaseFunc_SCALED_DISTANCE: phaseFunc = 10;
194pub const phaseFunc_INVERSE_DISTANCE: phaseFunc = 11;
195pub const phaseFunc_SCALED_INVERSE_DISTANCE: phaseFunc = 12;
196pub const phaseFunc_SCALED_INVERSE_SHIFTED_DISTANCE: phaseFunc = 13;
197pub const phaseFunc_SCALED_INVERSE_SHIFTED_WEIGHTED_DISTANCE: phaseFunc = 14;
198#[doc = " Flags for specifying named phase functions.\n These can be passed to functions applyNamedPhaseFunc(), applyNamedPhaseFuncOverrides(),\n applyParamNamedPhaseFunc(), and applyParamNamedPhaseFuncOverrides().\n\n Norm based phase functions:\n - \\p NORM maps state \\f$|x\\rangle|y\\rangle\\dots\\f$ to \\f$\\sqrt{x^2 + y^2 + \\dots}\\f$\n - \\p SCALED_NORM maps state \\f$|x\\rangle|y\\rangle\\dots\\f$ to \\f$\\text{coeff} \\sqrt{x^2 + y^2 + \\dots}\\f$\n - \\p INVERSE_NORM maps state \\f$|x\\rangle|y\\rangle\\dots\\f$ to \\f$1/\\sqrt{x^2 + y^2 + \\dots}\\f$\n - \\p SCALED_INVERSE_NORM maps state \\f$|x\\rangle|y\\rangle\\dots\\f$ to \\f$\\text{coeff}/\\sqrt{x^2 + y^2 + \\dots}\\f$\n - \\p SCALED_INVERSE_SHIFTED_NORM maps state \\f$|x\\rangle|y\\rangle\\dots\\f$ to \\f$\\text{coeff}/\\sqrt{(x-\\Delta_x)^2 + (y-\\Delta_y)^2 + \\dots}\\f$\n\n Product based phase functions:\n - \\p PRODUCT maps state \\f$|x\\rangle|y\\rangle|z\\rangle\\dots\\f$ to \\f$x \\; y \\; z \\dots\\f$\n - \\p SCALED_PRODUCT maps state \\f$|x\\rangle|y\\rangle|z\\rangle\\dots\\f$ to \\f$\\text{coeff} \\; x \\; y \\; z \\dots\\f$\n - \\p INVERSE_PRODUCT maps state \\f$|x\\rangle|y\\rangle|z\\rangle\\dots\\f$ to \\f$1/(x \\; y \\; z \\dots)\\f$\n - \\p SCALED_INVERSE_PRODUCT maps state \\f$|x\\rangle|y\\rangle|z\\rangle\\dots\\f$ to \\f$\\text{coeff}/(x \\; y \\; z \\dots)\\f$\n\n Euclidean distance based phase functions:\n - \\p DISTANCE maps state \\f$|x_1\\rangle|x_2\\rangle|y_1\\rangle|y_2\\rangle\\dots\\f$ to \\f$\\sqrt{(x_1-x_2)^2 + (y_1-y_2)^2 + \\dots}\\f$\n - \\p SCALED_DISTANCE maps state \\f$|x_1\\rangle|x_2\\rangle|y_1\\rangle|y_2\\rangle\\dots\\f$ to \\f$\\text{coeff}\\sqrt{(x_1-x_2)^2 + (y_1-y_2)^2 + \\dots}\\f$\n - \\p INVERSE_DISTANCE maps state \\f$|x_1\\rangle|x_2\\rangle|y_1\\rangle|y_2\\rangle\\dots\\f$ to \\f$1/\\sqrt{(x_1-x_2)^2 + (y_1-y_2)^2 + \\dots}\\f$\n - \\p SCALED_INVERSE_DISTANCE maps state \\f$|x_1\\rangle|x_2\\rangle|y_1\\rangle|y_2\\rangle\\dots\\f$ to \\f$\\text{coeff}/\\sqrt{(x_1-x_2)^2 + (y_1-y_2)^2 + \\dots}\\f$\n - \\p SCALED_INVERSE_SHIFTED_DISTANCE maps state \\f$|x_1\\rangle|x_2\\rangle|y_1\\rangle|y_2\\rangle\\dots\\f$ to \\f$\\text{coeff}/\\sqrt{(x_1-x_2-\\Delta_x)^2 + (y_1-y_2-\\Delta_y)^2 + \\dots}\\f$\n - \\p SCALED_INVERSE_SHIFTED_WEIGHTED_DISTANCE maps state \\f$|x_1\\rangle|x_2\\rangle|y_1\\rangle|y_2\\rangle\\dots\\f$ to \\f$\\text{coeff}/\\sqrt{f_x \\, (x_1-x_2-\\Delta_x)^2 + f_y \\; (y_1-y_2-\\Delta_y)^2 + \\dots}\\f$\n\n @ingroup type\n @author Tyson Jones\n @author Richard Meister (shifted functions)"]
199pub type phaseFunc = ::std::os::raw::c_uint;
200pub const bitEncoding_UNSIGNED: bitEncoding = 0;
201pub const bitEncoding_TWOS_COMPLEMENT: bitEncoding = 1;
202#[doc = " Flags for specifying how the bits in sub-register computational basis states\n are mapped to indices in functions like applyPhaseFunc().\n\n - \\p UNSIGNED means the bits encode an unsigned integer, hence\n \\f[\n \\begin{aligned}\n |00\\rangle & \\rightarrow \\, 0 \\\\\n |01\\rangle & \\rightarrow \\, 1 \\\\\n |10\\rangle & \\rightarrow \\, 2 \\\\\n |11\\rangle & \\rightarrow \\, 3\n \\end{aligned}\n \\f]\n - \\p TWOS_COMPLEMENT means the bits encode a signed integer through\n [two's complement](https://en.wikipedia.org/wiki/Two%27s_complement), such that\n \\f[\n \\begin{aligned}\n |000\\rangle & \\rightarrow \\, 0 \\\\\n |001\\rangle & \\rightarrow \\, 1 \\\\\n |010\\rangle & \\rightarrow \\, 2 \\\\\n |011\\rangle & \\rightarrow \\, 3 \\\\\n |100\\rangle & \\rightarrow \\,-4 \\\\\n |101\\rangle & \\rightarrow \\,-3 \\\\\n |110\\rangle & \\rightarrow \\,-2 \\\\\n |111\\rangle & \\rightarrow \\,-1\n \\end{aligned}\n \\f]\n > Remember that the qubits specified within a sub-register, and their ordering (least to most\n > significant) determine the bits of a computational basis state, before intrepretation\n > as an encoding of an integer.\n\n @ingroup type\n @author Tyson Jones"]
203pub type bitEncoding = ::std::os::raw::c_uint;
204#[doc = " A Pauli Hamiltonian, expressed as a real-weighted sum of pauli products,\n and which can hence represent any Hermitian operator.\n\n @ingroup type\n @author Tyson Jones"]
205#[repr(C)]
206#[derive(Debug, Copy, Clone)]
207pub struct PauliHamil {
208 #[doc = "The Pauli operators acting on each qubit, flattened over every operator.\n! This is a flat array of length PauliHamil.numSumTerms * PauliHamil.numQubits."]
209 pub pauliCodes: *mut pauliOpType,
210 #[doc = "The real coefficient of each Pauli product. This is an array of length PauliHamil.numSumTerms;"]
211 pub termCoeffs: *mut f64,
212 #[doc = "The number of terms in the weighted sum, or the number of Pauli products."]
213 pub numSumTerms: ::std::os::raw::c_int,
214 #[doc = "The number of qubits informing the Hilbert dimension of the Hamiltonian."]
215 pub numQubits: ::std::os::raw::c_int,
216}
217#[test]
218fn bindgen_test_layout_PauliHamil() {
219 const UNINIT: ::std::mem::MaybeUninit<PauliHamil> = ::std::mem::MaybeUninit::uninit();
220 let ptr = UNINIT.as_ptr();
221 assert_eq!(::std::mem::size_of::<PauliHamil>(), 24usize,);
222 assert_eq!(::std::mem::align_of::<PauliHamil>(), 8usize,);
223 assert_eq!(
224 unsafe { ::std::ptr::addr_of!((*ptr).pauliCodes) as usize - ptr as usize },
225 0usize,
226 );
227 assert_eq!(
228 unsafe { ::std::ptr::addr_of!((*ptr).termCoeffs) as usize - ptr as usize },
229 8usize,
230 );
231 assert_eq!(
232 unsafe { ::std::ptr::addr_of!((*ptr).numSumTerms) as usize - ptr as usize },
233 16usize,
234 );
235 assert_eq!(
236 unsafe { ::std::ptr::addr_of!((*ptr).numQubits) as usize - ptr as usize },
237 20usize,
238 );
239}
240#[doc = " Represents a diagonal complex operator on the full Hilbert state of a \\p Qureg.\n The operator need not be unitary nor Hermitian (which would constrain it to\n real values)\n\n @ingroup type\n @author Tyson Jones"]
241#[repr(C)]
242#[derive(Debug, Copy, Clone)]
243pub struct DiagonalOp {
244 #[doc = "The number of qubits this operator can act on (informing its size)"]
245 pub numQubits: ::std::os::raw::c_int,
246 #[doc = "The number of the 2^numQubits amplitudes stored on each distributed node"]
247 pub numElemsPerChunk: ::std::os::raw::c_longlong,
248 #[doc = "The number of nodes between which the elements of this operator are split"]
249 pub numChunks: ::std::os::raw::c_int,
250 #[doc = "The position of the chunk of the operator held by this process in the full operator"]
251 pub chunkId: ::std::os::raw::c_int,
252 #[doc = "The real values of the 2^numQubits complex elements"]
253 pub real: *mut f64,
254 #[doc = "The imaginary values of the 2^numQubits complex elements"]
255 pub imag: *mut f64,
256 #[doc = "A copy of the elements stored persistently on the GPU"]
257 pub deviceOperator: ComplexArray,
258}
259#[test]
260fn bindgen_test_layout_DiagonalOp() {
261 const UNINIT: ::std::mem::MaybeUninit<DiagonalOp> = ::std::mem::MaybeUninit::uninit();
262 let ptr = UNINIT.as_ptr();
263 assert_eq!(::std::mem::size_of::<DiagonalOp>(), 56usize,);
264 assert_eq!(::std::mem::align_of::<DiagonalOp>(), 8usize,);
265 assert_eq!(
266 unsafe { ::std::ptr::addr_of!((*ptr).numQubits) as usize - ptr as usize },
267 0usize,
268 );
269 assert_eq!(
270 unsafe { ::std::ptr::addr_of!((*ptr).numElemsPerChunk) as usize - ptr as usize },
271 8usize,
272 );
273 assert_eq!(
274 unsafe { ::std::ptr::addr_of!((*ptr).numChunks) as usize - ptr as usize },
275 16usize,
276 );
277 assert_eq!(
278 unsafe { ::std::ptr::addr_of!((*ptr).chunkId) as usize - ptr as usize },
279 20usize,
280 );
281 assert_eq!(
282 unsafe { ::std::ptr::addr_of!((*ptr).real) as usize - ptr as usize },
283 24usize,
284 );
285 assert_eq!(
286 unsafe { ::std::ptr::addr_of!((*ptr).imag) as usize - ptr as usize },
287 32usize,
288 );
289 assert_eq!(
290 unsafe { ::std::ptr::addr_of!((*ptr).deviceOperator) as usize - ptr as usize },
291 40usize,
292 );
293}
294#[doc = " Represents a diagonal complex operator of a smaller dimension than the full\n Hilbert state of a \\p Qureg.\n\n @ingroup type\n @author Tyson Jones"]
295#[repr(C)]
296#[derive(Debug, Copy, Clone)]
297pub struct SubDiagonalOp {
298 #[doc = "The number of target qubits which this SubDiagonalOp can operate upon"]
299 pub numQubits: ::std::os::raw::c_int,
300 #[doc = "The number of diagonal elements, i.e. 2^numQubits"]
301 pub numElems: ::std::os::raw::c_longlong,
302 #[doc = "The real values of the 2^numQubits complex elements"]
303 pub real: *mut f64,
304 #[doc = "The imaginary values of the 2^numQubits complex elements"]
305 pub imag: *mut f64,
306}
307#[test]
308fn bindgen_test_layout_SubDiagonalOp() {
309 const UNINIT: ::std::mem::MaybeUninit<SubDiagonalOp> = ::std::mem::MaybeUninit::uninit();
310 let ptr = UNINIT.as_ptr();
311 assert_eq!(::std::mem::size_of::<SubDiagonalOp>(), 32usize,);
312 assert_eq!(::std::mem::align_of::<SubDiagonalOp>(), 8usize,);
313 assert_eq!(
314 unsafe { ::std::ptr::addr_of!((*ptr).numQubits) as usize - ptr as usize },
315 0usize,
316 );
317 assert_eq!(
318 unsafe { ::std::ptr::addr_of!((*ptr).numElems) as usize - ptr as usize },
319 8usize,
320 );
321 assert_eq!(
322 unsafe { ::std::ptr::addr_of!((*ptr).real) as usize - ptr as usize },
323 16usize,
324 );
325 assert_eq!(
326 unsafe { ::std::ptr::addr_of!((*ptr).imag) as usize - ptr as usize },
327 24usize,
328 );
329}
330#[doc = " Represents a system of qubits.\n Qubits are zero-based\n\n @ingroup type\n @author Ania Brown\n @author Tyson Jones (density matrix)"]
331#[repr(C)]
332#[derive(Debug, Copy, Clone)]
333pub struct Qureg {
334 #[doc = "Whether this instance is a density-state representation"]
335 pub isDensityMatrix: ::std::os::raw::c_int,
336 #[doc = "The number of qubits represented in either the state-vector or density matrix"]
337 pub numQubitsRepresented: ::std::os::raw::c_int,
338 #[doc = "Number of qubits in the state-vector - this is double the number represented for mixed states"]
339 pub numQubitsInStateVec: ::std::os::raw::c_int,
340 #[doc = "Number of probability amplitudes held in stateVec by this process\n! In the non-MPI version, this is the total number of amplitudes"]
341 pub numAmpsPerChunk: ::std::os::raw::c_longlong,
342 #[doc = "Total number of amplitudes, which are possibly distributed among machines"]
343 pub numAmpsTotal: ::std::os::raw::c_longlong,
344 #[doc = "The position of the chunk of the state vector held by this process in the full state vector"]
345 pub chunkId: ::std::os::raw::c_int,
346 #[doc = "Number of chunks the state vector is broken up into -- the number of MPI processes used"]
347 pub numChunks: ::std::os::raw::c_int,
348 #[doc = "Computational state amplitudes - a subset thereof in the MPI version"]
349 pub stateVec: ComplexArray,
350 #[doc = "Temporary storage for a chunk of the state vector received from another process in the MPI version"]
351 pub pairStateVec: ComplexArray,
352 #[doc = "Storage for wavefunction amplitudes in the GPU version"]
353 pub deviceStateVec: ComplexArray,
354 #[doc = "Storage for reduction of probabilities on GPU"]
355 pub firstLevelReduction: *mut f64,
356 #[doc = "Storage for reduction of probabilities on GPU"]
357 pub secondLevelReduction: *mut f64,
358 #[doc = "Storage for wavefunction amplitues and config (copy of QuESTEnv's handle) in cuQuantum deployment"]
359 pub cuStateVec: *mut ::std::os::raw::c_void,
360 pub deviceCuStateVec: *mut ::std::os::raw::c_void,
361 pub cuConfig: *mut *mut ::std::os::raw::c_void,
362 #[doc = "Storage for generated QASM output"]
363 pub qasmLog: *mut QASMLogger,
364}
365#[test]
366fn bindgen_test_layout_Qureg() {
367 const UNINIT: ::std::mem::MaybeUninit<Qureg> = ::std::mem::MaybeUninit::uninit();
368 let ptr = UNINIT.as_ptr();
369 assert_eq!(::std::mem::size_of::<Qureg>(), 136usize,);
370 assert_eq!(::std::mem::align_of::<Qureg>(), 8usize,);
371 assert_eq!(
372 unsafe { ::std::ptr::addr_of!((*ptr).isDensityMatrix) as usize - ptr as usize },
373 0usize,
374 );
375 assert_eq!(
376 unsafe { ::std::ptr::addr_of!((*ptr).numQubitsRepresented) as usize - ptr as usize },
377 4usize,
378 );
379 assert_eq!(
380 unsafe { ::std::ptr::addr_of!((*ptr).numQubitsInStateVec) as usize - ptr as usize },
381 8usize,
382 );
383 assert_eq!(
384 unsafe { ::std::ptr::addr_of!((*ptr).numAmpsPerChunk) as usize - ptr as usize },
385 16usize,
386 );
387 assert_eq!(
388 unsafe { ::std::ptr::addr_of!((*ptr).numAmpsTotal) as usize - ptr as usize },
389 24usize,
390 );
391 assert_eq!(
392 unsafe { ::std::ptr::addr_of!((*ptr).chunkId) as usize - ptr as usize },
393 32usize,
394 );
395 assert_eq!(
396 unsafe { ::std::ptr::addr_of!((*ptr).numChunks) as usize - ptr as usize },
397 36usize,
398 );
399 assert_eq!(
400 unsafe { ::std::ptr::addr_of!((*ptr).stateVec) as usize - ptr as usize },
401 40usize,
402 );
403 assert_eq!(
404 unsafe { ::std::ptr::addr_of!((*ptr).pairStateVec) as usize - ptr as usize },
405 56usize,
406 );
407 assert_eq!(
408 unsafe { ::std::ptr::addr_of!((*ptr).deviceStateVec) as usize - ptr as usize },
409 72usize,
410 );
411 assert_eq!(
412 unsafe { ::std::ptr::addr_of!((*ptr).firstLevelReduction) as usize - ptr as usize },
413 88usize,
414 );
415 assert_eq!(
416 unsafe { ::std::ptr::addr_of!((*ptr).secondLevelReduction) as usize - ptr as usize },
417 96usize,
418 );
419 assert_eq!(
420 unsafe { ::std::ptr::addr_of!((*ptr).cuStateVec) as usize - ptr as usize },
421 104usize,
422 );
423 assert_eq!(
424 unsafe { ::std::ptr::addr_of!((*ptr).deviceCuStateVec) as usize - ptr as usize },
425 112usize,
426 );
427 assert_eq!(
428 unsafe { ::std::ptr::addr_of!((*ptr).cuConfig) as usize - ptr as usize },
429 120usize,
430 );
431 assert_eq!(
432 unsafe { ::std::ptr::addr_of!((*ptr).qasmLog) as usize - ptr as usize },
433 128usize,
434 );
435}
436#[doc = " Information about the environment the program is running in.\n In practice, this holds info about MPI ranks and helps to hide MPI initialization code\n\n @ingroup type\n @author Ania Brown\n @author Tyson Jones (seeding)"]
437#[repr(C)]
438#[derive(Debug, Copy, Clone)]
439pub struct QuESTEnv {
440 pub rank: ::std::os::raw::c_int,
441 pub numRanks: ::std::os::raw::c_int,
442 pub seeds: *mut ::std::os::raw::c_ulong,
443 pub numSeeds: ::std::os::raw::c_int,
444 pub cuConfig: *mut *mut ::std::os::raw::c_void,
445}
446#[test]
447fn bindgen_test_layout_QuESTEnv() {
448 const UNINIT: ::std::mem::MaybeUninit<QuESTEnv> = ::std::mem::MaybeUninit::uninit();
449 let ptr = UNINIT.as_ptr();
450 assert_eq!(::std::mem::size_of::<QuESTEnv>(), 32usize,);
451 assert_eq!(::std::mem::align_of::<QuESTEnv>(), 8usize,);
452 assert_eq!(
453 unsafe { ::std::ptr::addr_of!((*ptr).rank) as usize - ptr as usize },
454 0usize,
455 );
456 assert_eq!(
457 unsafe { ::std::ptr::addr_of!((*ptr).numRanks) as usize - ptr as usize },
458 4usize,
459 );
460 assert_eq!(
461 unsafe { ::std::ptr::addr_of!((*ptr).seeds) as usize - ptr as usize },
462 8usize,
463 );
464 assert_eq!(
465 unsafe { ::std::ptr::addr_of!((*ptr).numSeeds) as usize - ptr as usize },
466 16usize,
467 );
468 assert_eq!(
469 unsafe { ::std::ptr::addr_of!((*ptr).cuConfig) as usize - ptr as usize },
470 24usize,
471 );
472}
473extern "C" {
474 #[doc = " Creates a state-vector Qureg object representing a set of qubits which will remain in a pure state.\n\n Allocates space for a state-vector of complex amplitudes, which assuming a single\n ::qreal floating-point number requires <b>qrealBytes</b>, requires memory\n \\f[\n \\text{qrealBytes} \\times 2 \\times 2^\\text{numQubits}\\;\\;\\text{(bytes)},\n \\f]\n though there are additional memory costs in GPU and distributed modes.\n\n The returned ::Qureg begins in the zero state, as produced by initZeroState().\n\n Once created, the following ::Qureg fields are relevant in all backends:\n - Qureg.numQubitsRepresented\n - Qureg.isDensityMatrix\n\n > ::QuESTEnv \\p env must be prior created with createQuESTEnv().\n\n ### Serial\n In serial and local (non-distributed) multithreaded modes, a state-vector \\p Qureg\n costs only the memory above. For example, at double precision\n (#QuEST_PREC <b>= 2</b>, <b>qrealBytes = 8</b>), the memory costs are:\n \\p numQubits | memory\n ------------- | -------------\n 10 | 16 KiB\n 16 | 1 MiB\n 20 | 16 MiB\n 26 | 1 GiB\n 30 | 16 GiB\n\n Individual amplitudes should be fetched and modified with functions like getAmp() and setAmps().\n However, it is sometimes useful to access the state-vector directly, for example to\n create your own low-level (high performance) multithreaded functions.\n In those instants, Qureg.stateVec can be accessed directly, storing the real\n and imaginary components of the state-vector amplitudes in:\n - `Qureg.stateVec.real`\n - `Qureg.stateVec.imag`\n\n The total number of amplitudes in the state-vector is\n - Qureg.numAmpsTotal\n\n For example,\n ```\n Qureg qureg = createQureg(10, env);\n\n // ruin a perfectly good state-vector\n for (long long int i=0; i<qureg.numAmpsTotal; i++) {\n qureg.stateVec.real[i] = rand();\n qureg.stateVec.imag[i] = rand();\n }\n ```\n \\n\n\n\n ### GPU\n\n In GPU-accelerated mode, an <em>additional</em> state-vector is created in GPU memory.\n Therefore both RAM and VRAM must be of sufficient memory to store the state-vector,\n each of the size indicated in the Serial table above.\n\n > Note that many GPUs do not support quad precision ::qreal.\n\n Individual amplitudes of the created ::Qureg should be fetched and modified with functions like getAmp() and setAmps().\n This is especially important since the GPU state-vector can be accessed directly,\n and changes to Qureg.stateVec will be ignored and overwritten.\n To modify the state-vector \"directly\", one must use copyStateFromGPU() and\n copyStateToGPU() before and after.\n\n For example,\n ```\n Qureg qureg = createQureg(10, env);\n\n // ruin a perfectly good state-vector\n for (long long int i=0; i<qureg.numAmpsTotal; i++) {\n qureg.stateVec.real[i] = rand();\n qureg.stateVec.imag[i] = rand();\n }\n copyStateToGPU();\n ```\n \\n\n\n\n ### Distributed\n\n In distributed mode, the state-vector is uniformly partitioned between the <b>N</b>\n distributed nodes.\n\n > Only a power-of-2 number of nodes <b>N</b> may be used (e.g. <b>N = 1, 2, 4, 8, </b>...).\n > There must additionally be at least 1 amplitude of a state-vector stored on each node.\n > This means one cannot create a state-vector ::Qureg with fewer than \\f$\\log_2(\\text{N})\\f$ qubits.\n\n In addition to Qureg.stateVec, additional memory is allocated on each node for\n communication buffers, of size equal to the state-vector partition.\n Hence the total memory <em>per-node</em> required is:\n \\f[\n 2 \\times \\text{qrealBytes} \\times 2 \\times 2^\\text{numQubits}/N \\;\\;\\text{(bytes)},\n \\f]\n\n For example, at double precision\n (#QuEST_PREC <b>= 2</b>, <b>qrealBytes = 8</b>), the memory costs are:\n\n | \\p numQubits | memory per node |||||\n |-------------|-------|-------|-------|--------| ------ |\n | | <b>N = 2</b> | <b>N = 4</b> | <b>N = 8</b> | <b>N = 16</b> | <b>N = 32</b> |\n | 10 | 16 KiB | 8 KiB | 4 KiB | 2 KiB | 1 KiB |\n | 20 | 16 MiB | 8 MiB | 4 MiB | 2 MiB | 1 MiB |\n | 30 | 16 GiB | 8 GiB | 4 GiB | 2 GiB | 1 GiB |\n | 40 | 16 TiB | 8 TiB | 4 TiB | 2 TiB | 1 TiB |\n\n State-vector amplitudes should be set and modified using getAmp() and setAmps().\n Direct modification is possible, but should be done extremely carefully, since\n each node only stores a <em>partition</em> of the full state-vector, which itself\n mightn't fit on any single node. Furthermore, an asynchronous MPI process may\n may unexpectedly modify local amplitudes; avoid this with syncQuESTEnv().\n\n The fields relevant to distribution are:\n\n - Qureg.numAmpsPerChunk: the length of Qureg.stateVec (`.real` and `.imag`) on each node.\n - Qureg.chunkId: the id of the node, from <b>0</b> to <b>N-1</b>.\n\n Therefore, this code is valid\n ```\nsyncQuESTEnv(env);\n // set state |i> to have amplitude i\n for (long long int i=0; i<qureg.numAmpsPerChunk; i++)\n qureg.stateVec.real[i] = i + qureg.chunkId * qureg.numAmpsPerChunk;\n ```\n while the following erroneous code would cause a segmentation fault:\n ```\n // incorrectly attempt to set state |i> to have amplitude i\n for (long long int i=0; i<qureg.numAmpsTotal; i++)\n qureg.stateVec.real[i] = i;\n ```\n \\n\n\n\n @see\n - createDensityQureg() to create a density matrix of the equivalent number of qubits, which can enter noisy states.\n - createCloneQureg() to create a new qureg of the size and state of an existing qureg.\n - destroyQureg() to free the allocated ::Qureg memory.\n - reportQuregParams() to print information about a ::Qureg.\n - copyStateFromGPU() and copyStateToGPU() for directly modifying state-vectors in GPU mode.\n - syncQuESTEnv() for directly modifying state-vectors in distributed mode.\n\n @ingroup type\n @returns an object representing the set of qubits\n @param[in] numQubits number of qubits in the system\n @param[in] env object representing the execution environment (local, multinode etc)\n @throws invalidQuESTInputError()\n - if \\p numQubits <= 0\n - if \\p numQubits is so large that the number of amplitudes cannot fit in a long long int type,\n - if in distributed mode, there are more nodes than elements in the would-be state-vector\n @throws exit\n - if in GPU mode, but GPU memory cannot be allocated.\n @author Ania Brown\n @author Tyson Jones (validation, doc)"]
475 pub fn createQureg(numQubits: ::std::os::raw::c_int, env: QuESTEnv) -> Qureg;
476}
477extern "C" {
478 #[doc = " Creates a density matrix Qureg object representing a set of qubits which\n can enter noisy and mixed states.\n\n Allocates space for a matrix of complex amplitudes, which assuming a single\n ::qreal floating-point number requires <b>qrealBytes</b>, requires memory\n \\f[\n \\text{qrealBytes} \\times 2 \\times 2^{2 \\times\\text{numQubits}}\\;\\;\\text{(bytes)},\n \\f]\n though there are additional memory costs in GPU and distributed modes.\n Notice this is the memory cost of a state-vector created with createQureg()\n of twice as many qubits.\n\n The returned ::Qureg begins in the zero state, as produced by initZeroState().\n\n Once created, the following ::Qureg fields are relevant in all backends:\n - Qureg.numQubitsRepresented\n - Qureg.isDensityMatrix\n\n Behind the scenes, density matrice are stored as state-vectors, flattened column-wise.\n As such, individual amplitudes should be fetched with getDensityAmp(), in lieu\n of direct access.\n \\n\n\n > ::QuESTEnv \\p env must be prior created with createQuESTEnv().\n\n ### Serial\n In serial and local (non-distributed) multithreaded modes, a density matrix \\p Qureg\n costs only the memory above. For example, at double precision\n (#QuEST_PREC <b>= 2</b>, <b>qrealBytes = 8</b>), the memory costs are:\n \\p numQubits | memory\n ------------- | -------------\n 10 | 16 MiB\n 12 | 256 MiB\n 14 | 4 GiB\n 16 | 64 GiB\n 18 | 1 TiB\n 20 | 16 TiB\n\n\n ### GPU\n\n In GPU-accelerated mode, an <em>additional</em> density matrix is created in GPU memory.\n Therefore both RAM and VRAM must be of sufficient memory to store the state-vector,\n each of the size indicated in the Serial table above.\n\n > Note that many GPUs do not support quad precision ::qreal.\n\n ### Distributed\n\n In distributed mode, the density matrix is uniformly partitioned between the <b>N</b>\n distributed nodes (column-wise).\n\n > Only a power-of-2 number of nodes <b>N</b> may be used (e.g. <b>N = 1, 2, 4, 8, </b>...).\n > There must additionally be at least 1 amplitude of a density matrix stored on each node.\n > This means one cannot create a density matrix ::Qureg with fewer than \\f$\\log_2(\\text{N})/2\\f$ qubits.\n\n Additional memory is allocated on each node for communication buffers, of size\n equal to the density matrix partition.\n Hence the total memory <em>per-node</em> required is:\n \\f[\n 2 \\times \\text{qrealBytes} \\times 2 \\times 2^{2\\times\\text{numQubits}}/N \\;\\;\\text{(bytes)},\n \\f]\n\n For example, at double precision\n (#QuEST_PREC <b>= 2</b>, <b>qrealBytes = 8</b>), the memory costs are:\n\n | \\p numQubits | memory per node |||||\n |-------------|-------|-------|-------|--------| ------ |\n | | <b>N = 2</b> | <b>N = 4</b> | <b>N = 8</b> | <b>N = 16</b> | <b>N = 32</b> |\n | 10 | 16 MiB | 8 MiB | 4 MiB | 2 MiB | 1 MiB |\n | 15 | 16 GiB | 8 GiB | 4 GiB | 2 GiB | 1 GiB |\n | 20 | 16 TiB | 8 TiB | 4 TiB | 2 TiB | 1 TiB |\n\n\n @see\n - createQureg() to create a state-vector of the equivalent number of qubits, with a square-root memory cost\n - createCloneQureg() to create a new qureg of the size and state of an existing qureg.\n - destroyQureg() to free the allocated \\p Qureg memory.\n - reportQuregParams() to print information about a ::Qureg.\n\n @ingroup type\n @returns an object representing the set of qubits\n @param[in] numQubits number of qubits in the system\n @param[in] env object representing the execution environment (local, multinode etc)\n @throws invalidQuESTInputError()\n - if \\p numQubits <= 0\n - if \\p numQubits is so large that the number of amplitudes cannot fit in a long long int type,\n - if in distributed mode, there are more nodes than elements in the would-be state-vector\n @throws exit\n - if in GPU mode, but GPU memory cannot be allocated.\n @author Tyson Jones"]
479 pub fn createDensityQureg(numQubits: ::std::os::raw::c_int, env: QuESTEnv) -> Qureg;
480}
481extern "C" {
482 #[doc = " Create a new ::Qureg which is an exact clone of the passed qureg, which can be\n either a state-vector or a density matrix.\n\n The returned \\ref Qureg will have the same\n dimensions as the passed \\p qureg and begin in an identical quantum state.\n This must be destroyed by the user later with destroyQureg().\n\n @see\n - destroyQureg()\n - cloneQureg()\n - createQureg()\n - createDensityQureg()\n\n @ingroup type\n @returns an object representing the set of qubits\n @param[in] qureg an existing \\ref Qureg to be cloned\n @param[in] env the ::QuESTEnv\n @author Tyson Jones"]
483 pub fn createCloneQureg(qureg: Qureg, env: QuESTEnv) -> Qureg;
484}
485extern "C" {
486 #[doc = " Deallocate a ::Qureg, freeing its memory.\n\n This frees all memory bound to \\p qureg, including its state-vector or\n density matrix in RAM, in VRAM (in GPU mode), and communication buffers\n (in distributed mode).\n\n The \\p qureg must have been previously created with createQureg(),\n createDensityQureg() or createCloneQureg().\n\n @see\n - createQureg()\n - createDensityQureg()\n - createCloneQureg()\n\n @ingroup type\n @param[in,out] qureg the ::Qureg to be destroyed\n @param[in] env the ::QuESTEnv\n @author Ania Brown\n @author Tyson Jones (improved doc)"]
487 pub fn destroyQureg(qureg: Qureg, env: QuESTEnv);
488}
489extern "C" {
490 #[doc = " Allocate dynamic memory for a square complex matrix of any size,\n which can be passed to functions like multiQubitUnitary() and applyMatrixN().\n\n The returned matrix will have dimensions\n \\f[\n 2^{\\text{numQubits}} \\times 2^{\\text{numQubits}},\n \\f]\n stored as nested arrays ComplexMatrixN.real and ComplexMatrixN.imag,\n initialised to zero.\n\n > If your matrix will ultimately be diagonal, use createSubDiagonalOp()\n > instead to save quadratic memory and runtime.\n\n Unlike a ::Qureg, the memory of a ::ComplexMatrixN is always stored in RAM,\n and non-distributed. Hence, elements can be directly accessed and modified:\n ```\n int numQubits = 5;\n int dim = (1 << numQubits);\n ComplexMatrixN m = createComplexMatrixN(numQubits);\n\n for (int r=0; r<dim; r++) {\n for (int c=0; c<dim; c++) {\n m.real[r][c] = rand();\n m.imag[r][c] = rand();\n }\n }\n ```\n \\n\n A ::ComplexMatrixN can be initialised in bulk using initComplexMatrixN(),\n though this is not C++ compatible.\n\n Like ::ComplexMatrix2 and ::ComplexMatrix4 (which are incidentally stored in the stack),\n the returned ::ComplexMatrixN is safe to return from functions.\n\n > The ::ComplexMatrixN must eventually be freed using destroyComplexMatrixN(),\n > since it is created in the dynamic heap. One can instead use getStaticComplexMatrixN()\n > to create a ComplexMatrixN struct in the stack (which doesn't need to be later destroyed),\n > though this may cause a stack overflow if the matrix is too large (approx 10+ qubits).\n\n @see\n - destroyComplexMatrixN()\n - getStaticComplexMatrixN()\n - initComplexMatrixN()\n - applyMatrixN()\n - multiQubitUnitary()\n - mixMultiQubitKrausMap()\n - createSubDiagonalOp()\n\n @ingroup type\n @param[in] numQubits the number of qubits of which the returned ComplexMatrixN will correspond\n @returns a dynamic ComplexMatrixN struct, that is one where the .real and .imag\n fields are arrays kept in the heap and must be later destroyed.\n @throws invalidQuESTInputError()\n - if \\p numQubits <= 0\n - if the memory was not allocated successfully\n @author Tyson Jones"]
491 pub fn createComplexMatrixN(numQubits: ::std::os::raw::c_int) -> ComplexMatrixN;
492}
493extern "C" {
494 #[doc = " Destroy a ComplexMatrixN instance created with createComplexMatrixN()\n\n It is invalid to attempt to destroy a matrix created with getStaticComplexMatrixN().\n\n @see\n - getStaticComplexMatrixN()\n - createComplexMatrixN()\n\n @ingroup type\n @param[in] matr the dynamic matrix (created with createComplexMatrixN()) to deallocate\n @throws invalidQuESTInputError()\n - if \\p matr was not yet allocated.\n @throws malloc_error\n - if \\p matr was static (created with getStaticComplexMatrixN())\n @author Tyson Jones"]
495 pub fn destroyComplexMatrixN(matr: ComplexMatrixN);
496}
497extern "C" {
498 #[doc = " Initialises a ComplexMatrixN instance to have the passed\n \\p real and \\p imag values. This allows succint population of any-sized\n ComplexMatrixN, e.g. through 2D arrays:\n\n ComplexMatrixN m = createComplexMatrixN(3);\n initComplexMatrixN(m,\n (qreal[8][8]) {{1,2,3,4,5,6,7,8}, {0}},\n (qreal[8][8]) {{0}});\n\n \\p m can be created by either createComplexMatrixN() or getStaticComplexMatrixN().\n\n This function is only callable in C, since C++ signatures cannot\n contain variable-length 2D arrays\n\n @ingroup type\n @param[in] m the matrix to initialise\n @param[in] real matrix of real values; can be 2D array of array of pointers\n @param[in] imag matrix of imaginary values; can be 2D array of array of pointers\n @throws invalidQuESTInputError()\n - if \\p m has not been allocated (e.g. with createComplexMatrixN())\n @author Tyson Jones"]
499 pub fn initComplexMatrixN(m: ComplexMatrixN, real: *mut *mut f64, imag: *mut *mut f64);
500}
501extern "C" {
502 #[doc = " Dynamically allocates a Hamiltonian expressed as a real-weighted sum of products of Pauli operators.\n\n A ::PauliHamil is merely an encapsulation of the multiple parameters of functions\n like applyPauliSum().\n\n The Pauli operators (PauliHamil.pauliCodes) are all initialised to identity\n (::PAULI_I), but the coefficients (PauliHamil.termCoeffs) are not initialised.\n\n The Hamiltonian can be used in functions like applyPauliHamil() and applyTrotterCircuit(),\n with \\p Qureg instances of the same number of qubits.\n\n A ::PauliHamil can be modified directly (see ::PauliHamil), or through initPauliHamil().\n It can furthermore be created and initialised from a file description directly with\n createPauliHamilFromFile().\n\n > The returned dynamic \\p PauliHamil instance must later be freed via destroyPauliHamil().\n\n @see\n - createPauliHamilFromFile()\n - createDiagonalOpFromPauliHamilFile()\n - initPauliHamil()\n - destroyPauliHamil()\n - applyPauliSum()\n - applyTrotterCircuit()\n - calcExpecPauliHamil()\n\n @ingroup type\n @param[in] numQubits the number of qubits on which this Hamiltonian acts\n @param[in] numSumTerms the number of weighted terms in the sum, or the number of Pauli products\n @returns a dynamic \\p PauliHamil struct, with fields \\p pauliCodes and \\p termCoeffs stored in the heap\n @throws invalidQuESTInputError()\n - if \\p numQubits <= 0\n - if \\p numSumTerms <= 0\n @author Tyson Jones"]
503 pub fn createPauliHamil(
504 numQubits: ::std::os::raw::c_int,
505 numSumTerms: ::std::os::raw::c_int,
506 ) -> PauliHamil;
507}
508extern "C" {
509 #[doc = " Destroy a ::PauliHamil instance, created with either createPauliHamil() or createPauliHamilFromFile().\n\n @ingroup type\n @param[in] hamil a dynamic \\p PauliHamil instantiation\n @author Tyson Jones"]
510 pub fn destroyPauliHamil(hamil: PauliHamil);
511}
512extern "C" {
513 #[doc = " Creates a \\p PauliHamil instance, a real-weighted sum of products of Pauli operators,\n populated with the data in filename \\p fn.\n\n Each line in the plaintext file is interpreted as a separate product of Pauli operators\n in the total sum.\n Each line must be a space-separated list with format\n\n c p1 p2 p3 ... pN\n\n where \\p c is the real coefficient of the term, and \\p p1 ... \\p pN are\n numbers in <b>{0,1,2,3}</b> to indicate ::PAULI_I, ::PAULI_X, ::PAULI_Y, ::PAULI_Z\n operators respectively, which act on qubits \\p 0 through \\p N-1 (all qubits).\n\n For example, the file containing\n\n 0.31 1 0 1 2\n -0.2 3 2 0 0\n\n encodes a two-term four-qubit Hamiltonian\n \\f[\n 0.31 \\, X_0 \\, X_2 \\, Y_3 -0.2 \\, Z_0 \\, Y_1 \\,.\n \\f]\n\n The initialised ::PauliHamil can be previewed with reportPauliHamil().\n\n The number of qubits and terms are inferred from the file.\n The created Hamiltonian can be used just like one created via createPauliHamil().\n It can be modified directly (see ::PauliHamil), or through initPauliHamil().\n\n > The returned dynamic \\p PauliHamil instance must later be freed via destroyPauliHamil().\n\n @see\n - reportPauliHamil()\n - destroyPauliHamil()\n - createPauliHamil()\n - initPauliHamil()\n - createDiagonalOpFromPauliHamilFile()\n\n @ingroup type\n @param[in] fn filename of the plaintext file specifying the pauli operators and coefficients\n @returns a dynamic ::PauliHamil struct\n @throws invalidQuESTInputError()\n - if the file with name \\p fn cannot be read\n - if the file is not correctly formatted as described above\n @author Tyson Jones"]
514 pub fn createPauliHamilFromFile(fn_: *mut ::std::os::raw::c_char) -> PauliHamil;
515}
516extern "C" {
517 #[doc = " Initialise ::PauliHamil instance \\p hamil with the given term coefficients and\n Pauli codes (one for every qubit in every term).\n\n Arguments \\p coeffs and \\p codes encode a weighted sum of Pauli operators, with the same\n format as other QuEST functions (like calcExpecPauliSum()).\n\n This is useful to set the elements of the ::PauliHamil in batch. \\n\n For example\n ```\n int numQubits = 3;\n int numTerms = 2;\n PauliHamil hamil = createPauliHamil(numQubits, numTerms);\n\n // hamil = 0.5 X0 Y1 - 0.5 Z1 X3\n initPauliHamil(hamil,\n (qreal[]) {0.5, -0.5},\n (enum pauliOpType[]) {PAULI_X,PAULI_Y,PAULI_I, PAULI_I, PAULI_Z, PAULI_X});\n ```\n\n The initialised ::PauliHamil can be previewed with reportPauliHamil().\n\n > \\p hamil must be already created with createPauliHamil(), or createPauliHamilFromFile().\n\n @see\n - reportPauliHamil()\n - createPauliHamil()\n - createPauliHamilFromFile()\n\n @ingroup type\n @param[in, out] hamil an existing ::PauliHamil instance to be modified\n @param[in] coeffs an array of sum term coefficients, which must have length `hamil.numSumTerms`\n @param[in] codes a flat array of Pauli codes, of length `hamil.numSumTerms`*`hamil.numQubits`\n @throws invalidQuESTInputError()\n - if \\p hamil has invalid parameters (\\p numQubits <= 0, \\p numSumTerms <= 0)\n - if any code in \\p codes is not a valid Pauli code (::pauliOpType)\n @author Tyson Jones"]
518 pub fn initPauliHamil(hamil: PauliHamil, coeffs: *mut f64, codes: *mut pauliOpType);
519}
520extern "C" {
521 #[doc = " Creates a ::DiagonalOp representing a diagonal operator on the\n full Hilbert space of a ::Qureg.\n\n The resulting operator need not be unitary nor Hermitian, and can be\n applied to any ::Qureg of a compatible number of qubits.\n\n This function allocates space for \\f$2^{\\text{numQubits}}\\f$ complex amplitudes,\n which are initially zero. This is the same cost as a local state-vector of equal\n number of qubits; see the Serial section of createQureg().\n Note that this is a <em>paralell</em> data-type, so its\n ultimate memory costs depend on the hardware backends, as elaborated below.\n\n The operator elements should be modified with initDiagonalOp() and setDiagonalOpElems(),\n and must be later freed with destroyDiagonalOp().\n\n ### GPU\n\n In GPU-accelerated mode, this function also creates additional equally-sized\n persistent memory on the GPU.\n If you wish to modify the operator elements directly (in lieu of setDiagonalOpElems()),\n you must thereafter call syncDiagonalOp() to update the operator stored in VRAM.\n\n For example,\n ```\n DiagonalOp op = createDiagonalOp(4, env);\n for (long long int i=0; i<op.numElemsPerChunk; i++) {\n op.real[i] = rand();\n op.imag[i] = rand();\n }\n syncDiagonalOp(op);\n ```\n\n ### Distribution\n\n In distributed mode, the memory for the diagonal operator is divided evenly\n between the \\f$N\\f$ available nodes, such that each node contains only\n \\f$2^{\\text{numQubits}}/N\\f$ complex values. This is assigned to\n DiagonalOp.numElemsPerChunk.\n\n Users must therefore exercise care in modifying DiagonalOp.real and DiagonalOp.imag\n directly.\n\n For example, the following is valid code when when distributed between <b>N = 2</b> nodes:\n ```\n // create diag({1,2,3,4,5,6,7,8, 9,10,11,12,13,14,15,16})\n int numQubits = 4;\n DiagonalOp op = createDiagonalOp(numQubits, env);\n for (int i=0; i<8; i++) {\n if (env.rank == 0)\n op.real[i] = (i+1);\n if (env.rank == 1)\n op.real[i] = (i+1+8);\n }\n ```\n \\n\n\n\n @see\n - createDiagonalOpFromPauliHamilFile()\n - setDiagonalOpElems()\n - initDiagonalOp()\n - syncDiagonalOp()\n - applyDiagonalOp()\n - calcExpecDiagonalOp()\n - destroyDiagonalOp()\n\n @ingroup type\n @returns a dynamic DiagonalOp instance initialised to diag(0,0,...).\n @param[in] numQubits number of qubits which inform the Hilbert dimension of the operator.\n @param[in] env the ::QuESTEnv\n @throws invalidQuESTInputError()\n - if \\p numQubits <= 0\n - if \\p numQubits is so large that the number of elements cannot fit in a long long int type,\n - if in distributed mode, there are more nodes than elements in the operator\n @throws exit\n - if the memory could not be allocated\n @author Tyson Jones"]
522 pub fn createDiagonalOp(numQubits: ::std::os::raw::c_int, env: QuESTEnv) -> DiagonalOp;
523}
524extern "C" {
525 #[doc = " Destroys a ::DiagonalOp created with createDiagonalOp(), freeing its memory.\n\n @see\n - createDiagonalOp()\n\n @ingroup type\n @param[in] op the ::DiagonalOp to destroy\n @param[in] env the ::QuESTEnv\n @throws invalidQuESTInputError()\n - if \\p op was not previously created\n @author Tyson Jones"]
526 pub fn destroyDiagonalOp(op: DiagonalOp, env: QuESTEnv);
527}
528extern "C" {
529 #[doc = " Overwrites the entire ::DiagonalOp \\p op with the given \\p real and \\p imag\n complex elements.\n\n Both \\p real and \\p imag must have length equal to <b>pow(2, </b>`op.numQubits`<b>)</b>.\n\n In GPU mode, this updates both the RAM (\\p op.real and \\p op.imag) <em>and</em>\n persistent GPU memory; there is no need to call syncDiagonalOp() afterward.\n\n In distributed mode, this function assumes \\p real and \\p imag exist fully on every\n node. For ::DiagonalOp which are too large to fit into a single node, use\n setDiagonalOpElems() or syncDiagonalOp().\n\n @see\n - setDiagonalOpElems()\n - initDiagonalOpFromPauliHamil()\n\n @ingroup type\n @param[in,out] op the diagonal operator to modify\n @param[in] real the real components of the full set of new elements\n @param[in] imag the imaginary components of the full set of new elements\n @throws invalidQuESTInputError()\n - if \\p op was not created\n @throws segmentation-fault\n - if either \\p real or \\p imag have length smaller than <b>pow(2, </b>`op.numQubits`<b>)</b>\n @author Tyson Jones"]
530 pub fn initDiagonalOp(op: DiagonalOp, real: *mut f64, imag: *mut f64);
531}
532extern "C" {
533 #[doc = " Populates the diagonal operator \\p op to be equivalent to the given Pauli\n Hamiltonian \\p hamil, assuming \\p hamil contains only `PAULI_Z` operators.\n\n Given a ::PauliHamil \\p hamil featuring only `PAULI_Z` and `PAULI_I`, with\n term coefficients \\f$\\{\\lambda_j\\}\\f$, which\n hence has form\n \\f[\n \\begin{aligned}\n \\text{hamil} &= \\sum\\limits_j^{\\text{numSumTerms}} \\lambda_j\n \\bigotimes\\limits_{k_j} \\hat{Z}_k \\\\\n &\\equiv \\begin{pmatrix}\n r_1 \\\\ & r_2 \\\\ & & r_3 \\\\ & & & \\ddots \\\\ & & & & r_{2^{\\,\\text{numQubits}}}\n \\end{pmatrix},\n \\end{aligned}\n \\f]\n this function modifies \\p op to\n \\f[\n \\text{op} \\; \\rightarrow \\; \\text{diag}\n \\big( \\; r_1, \\; r_2, \\; r_3, \\; \\dots, \\; r_{2^{\\,\\text{numQubits}}} \\, \\big),\n \\f]\n where the real amplitudes have form\n \\f[\n r_i = \\sum\\limits_j \\, s_{ij} \\, \\lambda_j, \\;\\;\\;\\; s_{ij} = \\pm 1 \\,.\n \\f]\n This is useful since calculations with ::DiagonalOp are significantly faster than\n the equivalent calculations with a general ::PauliHamil. For example,\n applyDiagonalOp() requires a factor `numSumTerms * numQubits` fewer operations\n than applyPauliHamil().\n\n > In distributed mode, each node will contain only a sub-partition of the full diagonal matrix.\n > In GPU mode, both the CPU and GPU memory copies of \\p op will be updated, so there\n > is no need to call syncDiagonalOp() afterward.\n\n @see\n - createDiagonalOp()\n - createPauliHamil()\n - createDiagonalOpFromPauliHamilFile()\n - initDiagonalOp()\n - setDiagonalOpElems()\n\n @ingroup type\n @param[in,out] op an existing ::DiagonalOp (e.g. created with createDiagonalOp()) to modify\n @param[in] hamil a ::PauliHamil of equal dimension to \\p op, containing only `PAULI_Z` and `PAULI_I` operators\n @throws invalidQuESTInputError()\n - if \\p hamil has invalid parameters (\\p numQubits <= 0, \\p numSumTerms <= 0)\n - if \\p op and \\p hamil have unequal dimensions\n - if \\p hamil contains any operator other than `PAULI_Z` and `PAULI_I`\n @throws segmentation-fault\n - if either \\p op or \\p hamil have not been already created\n @author Tyson Jones\n @author Milos Prokop (serial prototype)"]
534 pub fn initDiagonalOpFromPauliHamil(op: DiagonalOp, hamil: PauliHamil);
535}
536extern "C" {
537 #[doc = " Creates and initialiases a diagonal operator from the Z Pauli Hamiltonian encoded in\n file with filename \\p fn.\n\n This is a convenience function to prepare a diagonal operator from a plaintext\n description of an all-Z Pauli Hamiltonian. The returned ::DiagonalOp is a\n distributed data structure, and significantly faster to use (through functions\n like calcExpecDiagonalOp()) than ::PauliHamil functions (like calcExpecPauliHamil()).\n\n - See createDiagonalOp() for info about the returned operator.\n - See initDiagonalOpFromPauliHamil() for info about the initialised state.\n - See createPauliHamilFromFile() for info about the required file format.\n\n > The returned ::DiagonalOp must be later freed with destroyDiagonalOp().\n > Note a ::PauliHamil from \\p fn is temporarily internally created.\n\n This function is equivalent to\n ```\n // produce diagonal matrix d\n PauliHamil h = createPauliHamilFromFile(fn);\n DiagonalOp d = createDiagonalOp(h.numQubits, env);\n initDiagonalOpFromPauliHamil(d, h);\n destroyPauliHamil(h);\n ```\n <br>\n\n @see\n - initDiagonalOpFromPauliHamil()\n - createPauliHamilFromFile()\n - createDiagonalOp()\n - destroyDiagonalOp()\n\n @ingroup type\n @param[in] fn filename of a plaintext file encoding an all-Z Pauli Hamiltonian\n @param[in] env the session ::QuESTEnv\n @returns a created ::DiagonalOp equivalent to the Hamiltonian in \\p fn\n @throws invalidQuESTInputError()\n - if file \\p fn cannot be read\n - if file \\p fn does not encode a valid ::PauliHamil\n - if the encoded ::PauliHamil consists of operators other than `PAULI_Z` and `PAULI_I`\n @author Tyson Jones\n @author Milos Prokop (serial prototype)"]
538 pub fn createDiagonalOpFromPauliHamilFile(
539 fn_: *mut ::std::os::raw::c_char,
540 env: QuESTEnv,
541 ) -> DiagonalOp;
542}
543extern "C" {
544 #[doc = " Modifies a subset (starting at index \\p startInd, and ending at index\n \\p startInd <b>+</b> \\p numElems) of the elements in ::DiagonalOp \\p op\n with the given complex numbers (passed as \\p real and \\p imag components).\n\n In GPU mode, this updates both the RAM (\\p op.real and \\p op.imag), and the\n persistent GPU memory.\n\n In distributed mode, this function assumes the subset \\p real and \\p imag exist\n (at least) on the node containing the ultimately updated elements.\\n\n For example, below is the correct way to modify the full 8 elements of \\p op\n when split between 2 nodes.\n ```\n DiagonalOp op = createDiagonalOp(3, env);\n\n int numElems = 4;\n qreal re[] = {1,2,3,4};\n qreal im[] = {1,2,3,4};\n setDiagonalOpElems(op, 0, re, im, numElems);\n\n // modify re and im to the next set of elements\n for (int i=0; i<4; i++) {\n re[i] += 4;\n im[i] += 4;\n }\n setDiagonalOpElems(op, 4, re, im, numElems);\n ```\n\n In this way, one can avoid a single node containing all new elements which might\n not fit. If more elements are passed than exist on an individual node, each\n node merely ignores the additional elements.\n\n @ingroup type\n @param[in,out] op the ::DiagonalOp to modify\n @param[in] startInd the starting index (globally) of the subset of elements to modify\n @param[in] real the real components of the new elements\n @param[in] imag the imaginary components of the new elements\n @param[in] numElems the number of new elements (the length of \\p real and \\p imag)\n @throws invalidQuESTInputError()\n - if \\p op was not created\n - if \\p startInd is an invalid index (<0 or >=<b>pow(2,</b>`op.numQubits`<b>)</b>)\n - if \\p numElems is an invalid number of elements (<=0 or ><b>pow(2,</b>`op.numQubits`<b>)</b>)\n - if there are fewer than \\p numElems elements in \\p op after \\p startInd\n @throws segmentation-fault\n - if either \\p real or \\p imag have fewer elements than \\p numElems\n @author Tyson Jones"]
545 pub fn setDiagonalOpElems(
546 op: DiagonalOp,
547 startInd: ::std::os::raw::c_longlong,
548 real: *mut f64,
549 imag: *mut f64,
550 numElems: ::std::os::raw::c_longlong,
551 );
552}
553extern "C" {
554 #[doc = " Apply a diagonal operator, which is possibly non-unitary and non-Hermitian,\n to the entire \\p qureg.\n\n Let \\f$d_j = \\text{op.real}[j] + (\\text{op.imag}[j])\\,\\text{i} \\f$, and\n \\f[\n \\hat{D} = \\begin{pmatrix}\n d_0 \\\\\n & d_1 \\\\\n & & \\ddots \\\\\n & & & d_{2^{\\text{op.numQubits}}-1}\n \\end{pmatrix}.\n \\f]\n If \\p qureg is a state-vector \\f$|\\psi\\rangle\\f$, this function performs\n \\f$|\\psi\\rangle \\rightarrow \\hat{D} \\, |\\psi\\rangle\\f$. \\n\n If \\p qureg is a density-matrix \\f$\\rho\\f$, this function performs\n \\f$\\rho \\rightarrow \\hat{D}\\, \\rho\\f$. Notice this has not applied \\f$\\hat{D}\\f$\n in the fashion of a unitary.\n\n > If your operator is unitary with unit amplitudes, the phases of which can be\n > described by an analytic expression, you should instead use applyPhaseFunc()\n > or applyNamedPhaseFunc() for significant memory and runtime savings.\n\n > To apply a diagonal operator upon a specific subset of qubits, use applySubDiagonalOp()\n\n @see\n - createDiagonalOp()\n - calcExpecDiagonalOp()\n - applyPhaseFunc()\n - applyNamedPhaseFunc()\n - applySubDiagonalOp()\n\n @ingroup operator\n @param[in,out] qureg the state to operate the diagonal operator upon\n @param[in] op the diagonal operator to apply\n @throws invalidQuESTInputError()\n - if \\p op was not created\n - if \\p op acts on a different number of qubits than \\p qureg represents\n @author Tyson Jones"]
555 pub fn applyDiagonalOp(qureg: Qureg, op: DiagonalOp);
556}
557extern "C" {
558 #[doc = " Computes the expected value of the diagonal operator \\p op for state \\p qureg.\n Since \\p op is not necessarily Hermitian, the expected value may be a complex\n number.\n\n Let \\f$ D \\f$ be the diagonal operator \\p op, with diagonal elements \\f$ d_i \\f$.\n Then if \\p qureg is a state-vector \\f$|\\psi\\rangle \\f$, this function computes\n \\f[\n\\langle \\psi | D | \\psi \\rangle = \\sum_i |\\psi_i|^2 \\, d_i\n \\f]\n If \\p qureg is a density matrix \\f$ \\rho \\f$, this function computes\n \\f[\n\\text{Trace}( D \\rho ) = \\sum_i \\rho_{ii} \\, d_i\n \\f]\n\n @see\n - createDiagonalOp()\n - applyDiagonalOp()\n - calcExpecPauliSum()\n - calcExpecPauliProd()\n - calcExpecPauliHamil()\n\n @ingroup calc\n @param[in] qureg a state-vector or density matrix\n @param[in] op the diagonal operator to compute the expected value of\n @return the expected vaulue of the operator\n @throws invalidQuESTInputError()\n - if \\p op was not created\n - if \\p op acts on a different number of qubits than \\p qureg represents\n @author Tyson Jones"]
559 pub fn calcExpecDiagonalOp(qureg: Qureg, op: DiagonalOp) -> Complex;
560}
561extern "C" {
562 #[doc = " Creates a ::SubDiagonalOp representing a diagonal operator which can act upon\n a subset of the qubits in a ::Qureg. This is similar to a ::DiagonalOp acting\n upon specific qubits.\n\n The resulting operator (initially all zero) need not be unitary nor Hermitian,\n and can be applied to any ::Qureg of a compatible number of qubits.\n\n > This function allocates space for \\f$2^{\\text{numQubits}}\\f$ complex amplitudes,\n > which are initially zero. This is the same cost as a local state-vector of equal\n > number of qubits; see the Serial section of createQureg().\n > Unlike ::DiagonalOp, this object is <em>not</em> distributed; instead, all\n > nodes (during distributed simulation) store the full set of diagonal elements,\n > similar to a ::ComplexMatrixN.\n\n\n The returned ::SubDiagonalOp must be later freed with destroySubDiagonalOp().\n\n For example, the below code creates an 8x8 identity operator.\n ```\n SubDiagonalOp op = createSubDiagonalOp(3);\n for (int i=0; i<op.numElems; i++)\n op.real[i] = 1;\n ```\n \\n\n\n\n @see\n - diagonalUnitary() to apply the created ::SubDiagonalOp upon a subset of qubits of a ::Qureg\n - applyGateSubDiagonalOp() to relax the numerical unitarity requirement of diagonalUnitary()\n - applySubDiagonalOp() to apply the SubDiagonalOp through left-multiplication only\n (as a non-unitary) upon a density matrix\n - destroySubDiagonalOp()\n - createDiagonalOp()\n\n @ingroup type\n @returns a SubDiagonalOp instance initialised to diag(0,0,...).\n @param[in] numQubits number of qubits which inform the Hilbert dimension of the returned ::SubDiagonalOp.\n @throws invalidQuESTInputError()\n - if \\p numQubits <= 0\n - if \\p numQubits is so large that the number of elements cannot fit in a long long int type,\n @throws exit\n - if the memory could not be allocated\n @author Tyson Jones"]
563 pub fn createSubDiagonalOp(numQubits: ::std::os::raw::c_int) -> SubDiagonalOp;
564}
565extern "C" {
566 #[doc = " Destroy a ::SubDiagonalOp instance created with createSubDiagonalOp().\n\n @see\n - createSubDiagonalOp()\n\n @ingroup type\n @param[in] op ::SubDiagonalOp to destroy\n @throws malloc_error\n - if \\p op was not prior created\n @author Tyson Jones"]
567 pub fn destroySubDiagonalOp(op: SubDiagonalOp);
568}
569extern "C" {
570 #[doc = " Apply a many-qubit unitary specified as a diagonal matrix upon a specific\n set of qubits of a quantum register.\n\n This is identical to function diagonalUnitary(), except here unitarity is not\n numerically checked nor enforced. That is, \\p op is mathematically treated as if\n it were unitary despite its true unitarity. This is useful for numerically relaxing\n the precision of unitarity.\n\n > To apply the operator as if it were e.g. Hermitian, use applySubDiagonalOp().\n\n @see\n - createSubDiagonalOp()\n - diagonalUnitary()\n - applySubDiagonalOp()\n - applyDiagonalOp()\n\n @ingroup operator\n @param[in,out] qureg the ::Qureg instance to operate upon\n @param[in] targets the list of target qubit indices\n @param[in] numTargets the length of list \\p targets, which must match the dimension of \\p op\n @param[in] op a ::SubDiagonalOp initialised to any complex values\n @throws invalidQuESTInputError()\n - if \\p numTargets does not match the size of \\p op\n - if \\p numTargets is invalid (<0 or larger than \\p qureg)\n - if \\p numTargets contains an invalid qubit index, or a repetition\n @author Tyson Jones"]
571 pub fn applyGateSubDiagonalOp(
572 qureg: Qureg,
573 targets: *mut ::std::os::raw::c_int,
574 numTargets: ::std::os::raw::c_int,
575 op: SubDiagonalOp,
576 );
577}
578extern "C" {
579 #[doc = " Left-apply a many-qubit a diagonal matrix upon a specific set of qubits of a quantum register.\n\n This is similar to applyGateSubDiagonalOp(), except that here, the operator \\p op\n is only <em>left</em> multiplied onto density matrices.\n\n Let \\f$\\hat{D}\\f$ denote the operator \\p op. Precisely, this function effects\n \\f[\n |\\psi\\rangle \\rightarrow \\hat{D}_{\\text{targets}} |\\psi\\rangle\n \\f]\n upon state-vectors \\f$|\\psi\\rangle\\f$, and\n \\f[\n \\rho \\rightarrow \\hat{D}_{\\text{targets}} \\; \\rho\n \\f]\n upon density matrices \\f$\\rho\\f$, imposing no numerical conditions (like unitarity) upon \\p op.\n\n > To apply \\p op as if it were unitary, use applyGateSubDiagonalOp() (or use\n > diagonalUnitary() to explicitly check/enforce unitarity).\n\n > To apply a full-Hilbert diagonal operator which must ergo itself be distributed,\n > use applyDiagonalOp()\n\n @see\n - createSubDiagonalOp()\n - applyGateSubDiagonalOp()\n - diagonalUnitary()\n - applyDiagonalOp()\n\n @ingroup operator\n @param[in,out] qureg the ::Qureg instance to operate upon\n @param[in] targets the list of target qubit indices\n @param[in] numTargets the length of list \\p targets, which must match the dimension of \\p op\n @param[in] op a ::SubDiagonalOp with any complex elements\n @throws invalidQuESTInputError()\n - if \\p numTargets does not match the size of \\p op\n - if \\p numTargets is invalid (<0 or larger than \\p qureg)\n - if \\p numTargets contains an invalid qubit index, or a repetition\n @author Tyson Jones"]
580 pub fn applySubDiagonalOp(
581 qureg: Qureg,
582 targets: *mut ::std::os::raw::c_int,
583 numTargets: ::std::os::raw::c_int,
584 op: SubDiagonalOp,
585 );
586}
587extern "C" {
588 #[doc = " Print the current state vector of probability amplitudes for a set of qubits to file.\n File format:\n @verbatim\nreal, imag\nrealComponent1, imagComponent1\nrealComponent2, imagComponent2\n...\nrealComponentN, imagComponentN\n@endverbatim\n\n File naming convention:\n\n For each node that the program runs on, a file 'state_rank_[node_rank].csv' is generated. If there is\n more than one node, ranks after the first do not include the header\n @verbatim\nreal, imag\n@endverbatim\n so that files are easier to combine.\n\n @ingroup debug\n @param[in,out] qureg object representing the set of qubits\n @author Ania Brown"]
589 pub fn reportState(qureg: Qureg);
590}
591extern "C" {
592 #[doc = " Print the current state vector of probability amplitudes for a set of qubits to standard out.\n For debugging purposes. Each rank should print output serially.\n Only print output for systems <= 5 qubits\n\n @ingroup debug\n @author Ania Brown"]
593 pub fn reportStateToScreen(qureg: Qureg, env: QuESTEnv, reportRank: ::std::os::raw::c_int);
594}
595extern "C" {
596 #[doc = " Report metainformation about a set of qubits: number of qubits, number of probability amplitudes.\n\n @ingroup debug\n @param[in] qureg object representing the set of qubits\n @author Ania Brown"]
597 pub fn reportQuregParams(qureg: Qureg);
598}
599extern "C" {
600 #[doc = " Print the \\p PauliHamil to screen.\n The output features a new line for each term, each with format\n\n c p1 p2 p3 ... pN\n\n where \\p c is the real coefficient of the term, and \\p p1 ... \\p pN are\n numbers \\p 0, \\p 1, \\p 2, \\p 3 to indicate identity, pauliX, pauliY and pauliZ\n operators respectively, acting on qubits \\p 0 through \\p N-1 (all qubits).\n A tab character separates c and p1, but single spaces separate the Pauli operators.\n\n @see\n - createPauliHamil()\n - initPauliHamil()\n - createPauliHamilFromFile()\n\n @ingroup debug\n @param[in] hamil an instantiated PauliHamil\n @throws invalidQuESTInputError if the parameters of \\p hamil are invalid, i.e.\n if \\p numQubits <= 0, or if \\p numSumTerms <= 0, or if \\p pauliCodes\n contains an invalid Pauli code.\n @author Tyson Jones"]
601 pub fn reportPauliHamil(hamil: PauliHamil);
602}
603extern "C" {
604 #[doc = " Returns the number of qubits represented by \\p qureg.\n\n @see\n - getNumAmps()\n\n @ingroup calc\n @param[in] qureg a state-vecor or density matrix\n @return `qureg.numQubitsRepresented`\n @author Tyson Jones"]
605 pub fn getNumQubits(qureg: Qureg) -> ::std::os::raw::c_int;
606}
607extern "C" {
608 #[doc = " Returns the number of complex amplitudes in a state-vector \\p qureg.\n\n In distributed mode, this returns the total number of amplitudes in the full\n representation of \\p qureg, and so may be larger than the number stored on\n each node. For the latter, refer to Qureg.numAmpsPerChunk.\n\n @see\n - getNumQubits()\n\n @ingroup calc\n @param[in] qureg a state-vecotor\n @return the total number of complex amplitudes representing \\p qureg.\n @throws invalidQuESTInputError()\n - if \\p qureg is a density matrix\n @author Tyson Jones"]
609 pub fn getNumAmps(qureg: Qureg) -> ::std::os::raw::c_longlong;
610}
611extern "C" {
612 #[doc = " Initialises a qureg to have all-zero-amplitudes. This is an unphysical state\n useful for iteratively building a state with functions like setWeightedQureg(),\n and should not be confused with initZeroState().\n\n @ingroup init\n @param[in,out] qureg a ::Qureg of which to clear all amplitudes\n @author Tyson Jones"]
613 pub fn initBlankState(qureg: Qureg);
614}
615extern "C" {
616 #[doc = " Initialise \\p qureg into the zero state.\n\n If \\p qureg is a state-vector of \\f$N\\f$ qubits, it is modified to state\n \\f$ {| 0 \\rangle}^{\\otimes N} \\f$. \\n\n If \\p qureg is a density matrix of \\f$ N \\f$ qubits, it is modified to state\n \\f$ {| 0 \\rangle\\langle 0 |}^{\\otimes N} \\f$\n\n @ingroup init\n @param[in,out] qureg the object representing the set of all qubits to initialise\n @author Ania Brown (state-vector)\n @author Tyson Jones (density matrix, doc)"]
617 pub fn initZeroState(qureg: Qureg);
618}
619extern "C" {
620 #[doc = " Initialise \\p qureg into the plus state.\n\n If \\p qureg is a state-vector of \\f$N\\f$ qubits, it is modified to state\n \\f[\n {| + \\rangle}^{\\otimes N} = \\frac{1}{\\sqrt{2^N}} (| 0 \\rangle + | 1 \\rangle)^{\\otimes N}\\,.\n \\f]\n If \\p qureg is a density matrix of \\f$N\\f$ qubits, it is modified to state\n \\f[\n {| + \\rangle\\langle+|}^{\\otimes N} = \\frac{1}{{2^N}} \\sum_i\\sum_j |i\\rangle\\langle j|\\,.\n \\f]\n\n\n @ingroup init\n @param[in,out] qureg the object representing the set of qubits to be initialised\n @author Ania Brown (state-vector)\n @author Tyson Jones (density matrix, doc)"]
621 pub fn initPlusState(qureg: Qureg);
622}
623extern "C" {
624 #[doc = " Initialise \\p qureg into the classical state (also known as a\n \"computational basis state\") with index \\p stateInd.\n\n If \\p qureg is a state-vector, it will become\n \\f$ | \\text{stateInd} \\rangle \\f$. \\n\n If \\p qureg is a density matrix, it will become\n \\f$ | \\text{stateInd} \\rangle \\langle \\text{stateInd} | \\f$.\n\n Classical states are indexed from zero, so that \\p stateInd <b>= 0</b> produces\n \\f$ | 00 \\dots 00 \\rangle \\f$,\n and \\p stateInd <b>= 1</b> produces \\f$ | 00 \\dots 01 \\rangle \\f$, and\n \\p stateInd <b>=</b> \\f$ 2^N - 1 \\f$ produces\n \\f$ | 11 \\dots 11 \\rangle \\f$.\n\n Subsequent calls to getProbAmp() will yield 0 for all indices except \\p stateInd,\n and the phase of \\p stateInd's amplitude will be 1 (real).\n\n This function can be used to initialise \\p qureg into a specific binary state\n (e.g. \\p 11001) using a binary literal (supported by only some compilers):\n ```\n initClassicalState(qureg, 0b11001);\n ```\n \\n\n\n\n @see\n - initPureState()\n\n @ingroup init\n @param[in,out] qureg the ::Qureg to modify\n @param[in] stateInd the index of the basis state to modify \\p qureg into\n @throws invalidQuESTInputError()\n - if \\p stateInd is outside <b>[0, </b>`qureg.numQubitsRepresented`<b>)</b>\n @author Tyson Jones"]
625 pub fn initClassicalState(qureg: Qureg, stateInd: ::std::os::raw::c_longlong);
626}
627extern "C" {
628 #[doc = " Initialise \\p qureg into to a given pure state of an equivalent Hilbert dimension.\n\n If \\p qureg is a state-vector, this merely clones \\p pure into \\p qureg. \\n\n If \\p qureg is a density matrix, this makes \\p qureg 100% likely to be in the \\p pure state.\n\n ::Qureg \\p pure is not modified.\n\n @see\n - initClassicalState()\n\n @ingroup init\n @param[in,out] qureg the ::Qureg to modify\n @param[in] pure a state-vector containing the pure state into which to initialise \\p qureg\n @throws invalidQuESTInputError()\n - if \\p qureg and \\p pure have mismatching dimensions\n - if \\p pure is a density matrix\n @author Tyson Jones"]
629 pub fn initPureState(qureg: Qureg, pure_: Qureg);
630}
631extern "C" {
632 #[doc = " Initialises \\p qureg to be in the un-normalised, non-physical state with\n with \\f$n\\f$-th complex amplitude given by \\f$2n/10 + i(2n+1)/10\\f$.\n\n This is used internally for debugging and testing.\n\n @ingroup debug\n @param[in,out] qureg the register to have its amplitudes overwritten\n @author Ania Brown\n @author Tyson Jones (doc)"]
633 pub fn initDebugState(qureg: Qureg);
634}
635extern "C" {
636 #[doc = " Initialise \\p qureg by specifying all amplitudes.\n For density matrices, it is assumed the amplitudes have been flattened\n column-wise into the given arrays.\n\n The real and imaginary components of the amplitudes are passed in separate arrays,\n \\p reals and \\p imags,\n each of which must have length `qureg.numAmpsTotal`.\n There is no automatic checking that the passed arrays are L2 normalised, so this\n can be used to prepare \\p qureg in a non-physical state.\n\n In distributed mode, this would require the complete state to fit in\n every node. To manually prepare a state for which all amplitudes cannot fit into a single node,\n use setAmps()\n\n @see\n - setAmps()\n\n @ingroup init\n @param[in,out] qureg the ::Qureg to overwrite\n @param[in] reals array of the real components of the new amplitudes\n @param[in] imags array of the imaginary components of the new amplitudes\n @throws segmentation-fault\n - if either \\p reals or \\p imags have fewer than `qureg.numAmpsTotal` elements\n @author Tyson Jones"]
637 pub fn initStateFromAmps(qureg: Qureg, reals: *mut f64, imags: *mut f64);
638}
639extern "C" {
640 #[doc = " Overwrites a contiguous subset of the amplitudes in state-vector \\p qureg,\n with those passed in \\p reals and \\p imags.\n\n Only amplitudes with indices in <b>[</b>\\p startInd<b>,</b> \\p startInd <b>+</b> \\p numAmps<b>]</b>\n will be changed. The resulting \\p qureg may not necessarily be in an L2 normalised state.\n\n In distributed mode, this function assumes the subset \\p reals and \\p imags exist\n (at least) on the node containing the ultimately updated elements.\\n\n For example, below is the correct way to modify the full 8 elements of \\p qureg\n when split between 2 nodes.\n ```\n Qureg qureg = createQureg(3, env);\n\n long long int numAmps = 4;\n qreal re[] = {1,2,3,4};\n qreal im[] = {1,2,3,4};\n setAmps(qureg, 0, re, im, numAmps);\n\n // modify re and im to the next set of elements\n for (int i=0; i<4; i++) {\n re[i] += 4;\n im[i] += 4;\n }\n setAmps(qureg, 4, re, im, numAmps);\n ```\n \\n\n\n\n @see\n - setDensityAmps()\n - setWeightedQureg()\n - initStateFromAmps()\n - initBlankState()\n\n @ingroup init\n @param[in,out] qureg the state-vector to modify\n @param[in] startInd the index of the first amplitude in \\p qureg to modify\n @param[in] reals array of the real components of the new amplitudes\n @param[in] imags array of the imaginary components of the new amplitudes\n @param[in] numAmps the length of each of the reals and imags arrays.\n @throws invalidQuESTInputError()\n - if \\p qureg is not a state-vector (i.e. is a density matrix)\n - if \\p startInd is outside [0, `qureg.numAmpsTotal`]\n - if \\p numAmps is outside [0, `qureg.numAmpsTotal`]\n - if \\p numAmps + \\p startInd >= `qureg.numAmpsTotal`\n @author Tyson Jones"]
641 pub fn setAmps(
642 qureg: Qureg,
643 startInd: ::std::os::raw::c_longlong,
644 reals: *mut f64,
645 imags: *mut f64,
646 numAmps: ::std::os::raw::c_longlong,
647 );
648}
649extern "C" {
650 #[doc = " Overwrites a contiguous subset of the amplitudes in density-matrix \\p qureg,\n with those passed in \\p reals and \\p imags, intrepreted column-wise.\n\n Only the first \\p numAmp amplitudes starting from row-column index (\\p startRow, \\p startCol), and\n proceeding down the column (wrapping around between rows) will be modified.\n The resulting \\p qureg may not necessarily be a valid density matrix normalisation.\n\n In distributed mode, this function assumes the subset \\p reals and \\p imags exist\n (at least) on the node(s) containing the ultimately updated elements.\\n\n\n\n @see\n - setAmps()\n - initStateFromAmps()\n\n @ingroup init\n @param[in,out] qureg the density-matrix to modify\n @param[in] startRow the row-index of the first amplitude in \\p qureg to modify\n @param[in] startCol the column-index of the first amplitude in \\p qureg to modify\n @param[in] reals array of the real components of the new amplitudes\n @param[in] imags array of the imaginary components of the new amplitudes\n @param[in] numAmps the length of each of the reals and imags arrays\n @throws invalidQuESTInputError()\n - if \\p qureg is not a density matrix (i.e. is a state-vector)\n - if \\p startRow is outside [0, `1 << qureg.numQubitsRepresented`]\n - if \\p startCol is outside [0, `1 << qureg.numQubitsRepresented`]\n - if \\p numAmps is outside [0, `qureg.numAmpsTotal`]\n - if \\p numAmps is larger than the remaining number of amplitudes from (`startRow`, `startCol`), column-wise\n @author Tyson Jones"]
651 pub fn setDensityAmps(
652 qureg: Qureg,
653 startRow: ::std::os::raw::c_longlong,
654 startCol: ::std::os::raw::c_longlong,
655 reals: *mut f64,
656 imags: *mut f64,
657 numAmps: ::std::os::raw::c_longlong,
658 );
659}
660extern "C" {
661 #[doc = " Overwrites the density-matrix \\p qureg with the Z-basis matrix representation\n of the given real-weighted sum of Pauli tensors \\p hamil.\n\n This leaves \\p qureg in a non-physical state - as a matrix form of \\p hamil -\n and is useful for establishing a persistent-backend dense representation of\n the Hamiltonian. For example, \\p qureg can be subsequently passed to functions\n like calcDensityInnerProduct() which would effectively in-place compute\n calcExpecPauliHamil().\n\n @see\n - createPauliHamil()\n - createDensityQureg()\n - calcDensityInnerProduct()\n\n @ingroup init\n @param[in,out] qureg the density-matrix to overwrite\n @param[in] hamil the ::PauliHamil to expand into a matrix representation\n @throws invalidQuESTInputError()\n - if \\p qureg is not a density matrix (i.e. is a state-vector)\n - if the dimensions of \\p qureg and \\p hamil do not match\n - if \\p hamil is an invalid ::PauliHamil\n @author Tyson Jones"]
662 pub fn setQuregToPauliHamil(qureg: Qureg, hamil: PauliHamil);
663}
664extern "C" {
665 #[doc = " Overwrite the amplitudes of \\p targetQureg with those from \\p copyQureg.\n\n Registers must either both be state-vectors, or both be density matrices, and\n of equal dimensions.\n Only the quantum state is cloned, while auxilary info (like recorded QASM) is unchanged.\n copyQureg is unaffected.\n\n @see\n - createCloneQureg()\n - initPureState()\n - setWeightedQureg()\n\n @ingroup init\n @param[in, out] targetQureg the qureg to have its quantum state overwritten\n @param[in] copyQureg the qureg to have its quantum state cloned into targetQureg.\n @throws invalidQuESTInputError()\n - if \\p targetQureg is a state-vector while \\p copyQureg is a density matrix (and vice versa)\n - if \\p targetQureg and \\p copyQureg have different dimensions\n @author Tyson Jones"]
666 pub fn cloneQureg(targetQureg: Qureg, copyQureg: Qureg);
667}
668extern "C" {
669 #[doc = " Shift the phase between \\f$ |0\\rangle \\f$ and \\f$ |1\\rangle \\f$ of a single qubit by a given angle.\n\n > This is equivalent to a Z-axis rotation of the Bloch-sphere up to a global phase factor.\n For angle \\f$\\theta\\f$, this effects single-qubit unitary\n \\f[\n \\begin{pmatrix}\n 1 & 0 \\\\\n 0 & \\exp(i \\theta)\n \\end{pmatrix}\n \\f]\n with circuit diagram\n@htmlonly\n<center>\n<script type=\"text/tikz\">\n\\begin{tikzpicture}[scale=.5]\n\\node[draw=none] at (-4, 0) {targetQubit};\n\n\\draw (-2,0) -- (-1, 0);\n\\draw (1, 0) -- (2, 0);\n\\draw (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle;\n\\node[draw=none] at (0, 0) {$R_\\theta$};\n\\end{tikzpicture}\n</script>\n</center>\n@endhtmlonly\n\n @see\n - controlledPhaseShift()\n - multiControlledPhaseShift()\n\n @ingroup unitary\n @param[in,out] qureg object representing the set of all qubits\n @param[in] targetQubit qubit to undergo a phase shift\n @param[in] angle amount by which to shift the phase in radians\n @throws invalidQuESTInputError()\n - \\p targetQubit is outside [0, \\p qureg.numQubitsRepresented).\n @author Tyson Jones"]
670 pub fn phaseShift(qureg: Qureg, targetQubit: ::std::os::raw::c_int, angle: f64);
671}
672extern "C" {
673 #[doc = " Introduce a phase factor \\f$ \\exp(i \\theta) \\f$ on state \\f$ |11\\rangle \\f$ of qubits\n \\p idQubit1 and \\p idQubit2.\n For angle \\f$\\theta\\f$, this effects the unitary\n \\f[\n \\begin{pmatrix}\n 1 & & & \\\\\n & 1 & & \\\\\n & & 1 & \\\\\n & & & \\exp(i \\theta)\n \\end{pmatrix}\n \\f]\n on \\p idQubit1 and \\p idQubit2.\n\n@htmlonly\n<center>\n<script type=\"text/tikz\">\n\\begin{tikzpicture}[scale=.5]\n\\node[draw=none] at (-3.5, 2) {qubit1};\n\\node[draw=none] at (-3.5, 0) {qubit2};\n\n\\draw (-2, 2) -- (2, 2);\n\\draw[fill=black] (0, 2) circle (.2);\n\\draw (0, 2) -- (0, 1);\n\n\\draw (-2,0) -- (-1, 0);\n\\draw (1, 0) -- (2, 0);\n\\draw (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle;\n\\node[draw=none] at (0, 0) {$R_\\theta$};\n\\end{tikzpicture}\n</script>\n</center>\n@endhtmlonly\n\n @see\n - phaseShift()\n - multiControlledPhaseShift()\n\n @ingroup unitary\n @param[in,out] qureg object representing the set of all qubits\n @param[in] idQubit1 first qubit in the state to phase shift\n @param[in] idQubit2 second qubit in the state to phase shift\n @param[in] angle amount by which to shift the phase in radians\n @throws invalidQuESTInputError()\n - if \\p idQubit1 or \\p idQubit2 are outside [0, \\p qureg.numQubitsRepresented)\n - if \\p idQubit1 and \\p idQubit2 are equal\n @author Tyson Jones"]
674 pub fn controlledPhaseShift(
675 qureg: Qureg,
676 idQubit1: ::std::os::raw::c_int,
677 idQubit2: ::std::os::raw::c_int,
678 angle: f64,
679 );
680}
681extern "C" {
682 #[doc = " Introduce a phase factor \\f$ \\exp(i \\theta) \\f$ on state \\f$ |1 \\dots 1 \\rangle \\f$\n of the passed qubits.\n\n@htmlonly\n<center>\n<script type=\"text/tikz\">\n\\begin{tikzpicture}[scale=.5]\n\\node[draw=none] at (-3.5, 2) {controls};\n\\node[draw=none] at (1, .7) {$\\theta$};\n\n\\node[draw=none] at (0, 6) {$\\vdots$};\n\\draw (0, 5) -- (0, 4);\n\n\\draw (-2, 4) -- (2, 4);\n\\draw[fill=black] (0, 4) circle (.2);\n\\draw (0, 4) -- (0, 2);\n\n\\draw (-2, 2) -- (2, 2);\n\\draw[fill=black] (0, 2) circle (.2);\n\\draw (0, 2) -- (0, 0);\n\n\\draw (-2,0) -- (2, 0);\n\\draw[fill=black] (0, 0) circle (.2);\n\\end{tikzpicture}\n</script>\n</center>\n@endhtmlonly\n\n @see\n - phaseShift()\n - controlledPhaseShift()\n - controlledPhaseFlip()\n - multiControlledPhaseFlip()\n\n @ingroup unitary\n @param[in,out] qureg object representing the set of all qubits\n @param[in] controlQubits array of qubits to phase shift\n @param[in] numControlQubits the length of array \\p controlQubits\n @param[in] angle amount by which to shift the phase in radians\n @throws invalidQuESTInputError()\n - if \\p numControlQubits is outside [1, \\p qureg.numQubitsRepresented])\n - if any qubit index in \\p controlQubits is outside [0, \\p qureg.numQubitsRepresented])\n - if the qubits in \\p controlQubits are not unique\n @author Tyson Jones"]
683 pub fn multiControlledPhaseShift(
684 qureg: Qureg,
685 controlQubits: *mut ::std::os::raw::c_int,
686 numControlQubits: ::std::os::raw::c_int,
687 angle: f64,
688 );
689}
690extern "C" {
691 #[doc = " Apply the (two-qubit) controlled phase flip gate, also known as the controlled pauliZ gate.\n For each state, if both input qubits have value one, multiply the amplitude of that state by -1. This applies the two-qubit unitary:\n \\f[\n \\begin{pmatrix}\n 1 \\\\\n & 1 \\\\\\\n & & 1 \\\\\n & & & -1\n \\end{pmatrix}\n \\f]\n with circuit diagram:\n@htmlonly\n<center>\n<script type=\"text/tikz\">\n\\begin{tikzpicture}[scale=.5]\n\\node[draw=none] at (-3.5, 2) {idQubit1};\n\\node[draw=none] at (-3.5, 0) {idQubit2};\n\n\\draw (-2, 2) -- (2, 2);\n\\draw[fill=black] (0, 2) circle (.2);\n\\draw (0, 2) -- (0, 0);\n\n\\draw (-2,0) -- (2, 0);\n\\draw[fill=black] (0, 0) circle (.2);\n\\end{tikzpicture}\n</script>\n</center>\n@endhtmlonly\n\n @see\n - pauliZ()\n - phaseShift()\n - multiControlledPhaseFlip()\n\n @ingroup unitary\n @param[in,out] qureg object representing the set of all qubits\n @param[in] idQubit1, idQubit2 qubits to operate upon\n @throws invalidQuESTInputError()\n - if \\p idQubit1 or \\p idQubit2 are outside [0, \\p qureg.numQubitsRepresented)\n - if \\p idQubit1 and \\p idQubit2 are equal\n @author Tyson Jones"]
692 pub fn controlledPhaseFlip(
693 qureg: Qureg,
694 idQubit1: ::std::os::raw::c_int,
695 idQubit2: ::std::os::raw::c_int,
696 );
697}
698extern "C" {
699 #[doc = " Apply the multiple-qubit controlled phase flip gate, also known as the multiple-qubit controlled pauliZ gate.\n For each state, if all control qubits have value one, multiply the amplitude of that state by -1. This applies the many-qubit unitary:\n \\f[\n \\begin{pmatrix}\n 1 \\\\\n & 1 \\\\\\\n & & \\ddots \\\\\n & & & 1 \\\\\n & & & & -1\n \\end{pmatrix}\n \\f]\n on the control qubits.\n\n@htmlonly\n<center>\n<script type=\"text/tikz\">\n\\begin{tikzpicture}[scale=.5]\n\\node[draw=none] at (-3.5, 2) {controls};\n\n\\node[draw=none] at (0, 6) {$\\vdots$};\n\\draw (0, 5) -- (0, 4);\n\n\\draw (-2, 4) -- (2, 4);\n\\draw[fill=black] (0, 4) circle (.2);\n\\draw (0, 4) -- (0, 2);\n\n\\draw (-2, 2) -- (2, 2);\n\\draw[fill=black] (0, 2) circle (.2);\n\\draw (0, 2) -- (0, 0);\n\n\\draw (-2,0) -- (2, 0);\n\\draw[fill=black] (0, 0) circle (.2);\n\\end{tikzpicture}\n</script>\n</center>\n@endhtmlonly\n\n @ingroup unitary\n @param[in,out] qureg object representing the set of all qubits\n @param[in] controlQubits array of input qubits\n @param[in] numControlQubits number of input qubits\n @throws invalidQuESTInputError()\n - if \\p numControlQubits is outside [1, \\p qureg.numQubitsRepresented)\n - if any qubit in \\p controlQubits is outside [0, \\p qureg.numQubitsRepresented)\n - if any qubit in \\p qubits is repeated\n @author Tyson Jones"]
700 pub fn multiControlledPhaseFlip(
701 qureg: Qureg,
702 controlQubits: *mut ::std::os::raw::c_int,
703 numControlQubits: ::std::os::raw::c_int,
704 );
705}
706extern "C" {
707 #[doc = " Apply the single-qubit S gate.\n This is a rotation of \\f$\\pi/2\\f$ around the Z-axis on the Bloch sphere, or the unitary:\n \\f[\n \\begin{pmatrix}\n 1 & 0 \\\\\n 0 & i\n \\end{pmatrix}\n \\f]\n with circuit diagram:\n@htmlonly\n<center>\n<script type=\"text/tikz\">\n\\begin{tikzpicture}[scale=.5]\n\\node[draw=none] at (-3.5, 0) {target};\n\n\\draw (-2,0) -- (-1, 0);\n\\draw (1, 0) -- (2, 0);\n\\draw (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle;\n\\node[draw=none] at (0, 0) {S};\n\\end{tikzpicture}\n</script>\n</center>\n@endhtmlonly\n\n @see\n - tGate()\n\n @ingroup unitary\n @param[in,out] qureg object representing the set of all qubits\n @param[in] targetQubit qubit to operate upon\n @throws invalidQuESTInputError()\n - if \\p targetQubit is outside [0, \\p qureg.numQubitsRepresented)\n @author Ania Brown (state-vector)\n @author Tyson Jones (density matrix, doc)"]
708 pub fn sGate(qureg: Qureg, targetQubit: ::std::os::raw::c_int);
709}
710extern "C" {
711 #[doc = " Apply the single-qubit T gate.\n This is a rotation of \\f$\\pi/4\\f$ around the Z-axis on the Bloch sphere, or the unitary:\n \\f[\n \\begin{pmatrix}\n 1 & 0 \\\\\n 0 & \\exp\\left(i \\frac{\\pi}{4}\\right)\n \\end{pmatrix}\n \\f]\n with circuit diagram:\n@htmlonly\n<center>\n<script type=\"text/tikz\">\n\\begin{tikzpicture}[scale=.5]\n\\node[draw=none] at (-3.5, 0) {target};\n\n\\draw (-2,0) -- (-1, 0);\n\\draw (1, 0) -- (2, 0);\n\\draw (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle;\n\\node[draw=none] at (0, 0) {T};\n\\end{tikzpicture}\n</script>\n</center>\n@endhtmlonly\n\n @see\n - sGate()\n\n @ingroup unitary\n @param[in,out] qureg object representing the set of all qubits\n @param[in] targetQubit qubit to operate upon\n @throws invalidQuESTInputError()\n - if \\p targetQubit is outside [0, \\p qureg.numQubitsRepresented)\n @author Ania Brown (state-vector)\n @author Tyson Jones (density matrix, doc)"]
712 pub fn tGate(qureg: Qureg, targetQubit: ::std::os::raw::c_int);
713}
714extern "C" {
715 #[doc = " Create the QuEST execution environment.\n This should be called only once, and the environment should be freed with destroyQuESTEnv at the end\n of the user's code.\n If something needs to be done to set up the execution environment, such as\n initializing MPI when running in distributed mode, it is handled here.\n\n @see\n - reportQuESTEnv()\n - destroyQuESTEnv()\n - syncQuESTEnv()\n\n @ingroup type\n @return object representing the execution environment. A single instance is used for each program\n @author Ania Brown"]
716 pub fn createQuESTEnv() -> QuESTEnv;
717}
718extern "C" {
719 #[doc = " Destroy the QuEST environment.\n If something needs to be done to clean up the execution environment, such as\n finalizing MPI when running in distributed mode, it is handled here\n\n @see\n - createQuESTEnv()\n\n @ingroup type\n @param[in] env object representing the execution environment. A single instance is used for each program\n @author Ania Brown"]
720 pub fn destroyQuESTEnv(env: QuESTEnv);
721}
722extern "C" {
723 #[doc = " Report information about the QuEST environment\n\n @ingroup debug\n @param[in] env object representing the execution environment. A single instance is used for each program\n @author Ania Brown"]
724 pub fn reportQuESTEnv(env: QuESTEnv);
725}
726extern "C" {
727 #[doc = " Sets \\p str to a string containing information about the runtime environment,\n including whether simulation is using CUDA (for GPU), OpenMP (for multithreading)\n and/or MPI (for distribution). The number of CPU threads and distributed ranks is\n also reported. Note there is currently no reporting of the number of GPU cores used.\n\n The string format is:\n ```\n \"CUDA=b OpenMP=b MPI=b threads=n ranks=n\"\n ```\n where <b>b</b> is 0 or 1, and <b>n</b> are integers.\n\n @ingroup debug\n @param[in] env object representing the execution environment. A single instance is used for each program\n @param[out] str to be populated with the output string\n @author Ania Brown\n @author Tyson Jones"]
728 pub fn getEnvironmentString(env: QuESTEnv, str_: *mut ::std::os::raw::c_char);
729}
730extern "C" {
731 #[doc = " In GPU mode, this copies the state-vector (or density matrix) from GPU memory\n (qureg.deviceStateVec) to RAM (qureg.stateVec), where it can be accessed/modified\n by the user.\n In CPU mode, this function has no effect.\n In conjunction with copyStateToGPU(), this allows a user to directly modify the\n state-vector in a harware agnostic way.\n Note though that users should instead use setAmps() if possible.\n\n For example, to set the first real element to 1, one could do:\n ```\n copyStateFromGPU(qureg);\n qureg.stateVec.real[0] = 1;\n copyStateToGPU(qureg);\n ```\n\n Note users should never access qureg.deviceStateVec directly.\n\n @see\n - copyStateToGPU()\n - copySubstateFromGPU()\n - copySubstateToGPU()\n\n @ingroup debug\n @param[in, out] qureg the qureg of which to copy `.deviceStateVec` to `.stateVec` in GPU mode\n @author Ania Brown\n @author Tyson Jones (doc)"]
732 pub fn copyStateFromGPU(qureg: Qureg);
733}
734extern "C" {
735 #[doc = " Get the complex amplitude at a given index in the state vector.\n\n @see\n - getDensityAmp()\n - getRealAmp()\n - getImagAmp()\n - getProbAmp()\n - getNumAmps()\n - getNumQubits()\n\n @ingroup calc\n @param[in] qureg object representing a set of qubits\n @param[in] index index in state vector of probability amplitudes\n @return amplitude at index, returned as a Complex struct (with .real and .imag attributes)\n @throws invalidQuESTInputError()\n - if \\p qureg is a density matrix\n - if \\p index is outside [0, \\f$2^{N}\\f$) where \\f$N = \\f$ \\p qureg.numQubitsRepresented\n @author Tyson Jones"]
736 pub fn getAmp(qureg: Qureg, index: ::std::os::raw::c_longlong) -> Complex;
737}
738extern "C" {
739 #[doc = " Get the real component of the complex probability amplitude at an index in the state vector.\n\n @see\n - getAmp()\n - getDensityAmp()\n - getImagAmp()\n - getProbAmp()\n - getNumAmps()\n - getNumQubits()\n\n @ingroup calc\n @param[in] qureg object representing a set of qubits\n @param[in] index index in state vector of probability amplitudes\n @return real component at that index\n @throws invalidQuESTInputError()\n - if \\p qureg is a density matrix\n - if \\p index is outside [0, \\f$2^{N}\\f$) where \\f$N = \\f$ \\p qureg.numQubitsRepresented\n @author Ania Brown"]
740 pub fn getRealAmp(qureg: Qureg, index: ::std::os::raw::c_longlong) -> f64;
741}
742extern "C" {
743 #[doc = " Get the imaginary component of the complex probability amplitude at an index in the state vector.\n\n @see\n - getAmp()\n - getDensityAmp()\n - getRealAmp()\n - getProbAmp()\n - getNumAmps()\n - getNumQubits()\n\n @ingroup calc\n @param[in] qureg object representing a set of qubits\n @param[in] index index in state vector of probability amplitudes\n @return imaginary component at that index\n @throws invalidQuESTInputError()\n - if \\p qureg is a density matrix\n - if \\p index is outside [0, \\f$2^{N}\\f$) where \\f$N = \\f$ \\p qureg.numQubitsRepresented\n @author Ania Brown"]
744 pub fn getImagAmp(qureg: Qureg, index: ::std::os::raw::c_longlong) -> f64;
745}
746extern "C" {
747 #[doc = " Get the probability of a state-vector at an index in the full state vector.\n\n @see\n - getAmp()\n - getDensityAmp()\n - getRealAmp()\n - getImagAmp()\n - getNumAmps()\n - getNumQubits()\n\n @ingroup calc\n @param[in] qureg object representing a set of qubits\n @param[in] index index in state vector of probability amplitudes\n @return realEl*realEl + imagEl*imagEl\n @throws invalidQuESTInputError()\n - if \\p qureg is a density matrix\n - if \\p index is outside [0, \\f$2^{N}\\f$) where \\f$N = \\f$ \\p qureg.numQubitsRepresented\n @author Ania Brown"]
748 pub fn getProbAmp(qureg: Qureg, index: ::std::os::raw::c_longlong) -> f64;
749}
750extern "C" {
751 #[doc = " Get an amplitude from a density matrix at a given row and column.\n\n @see\n - getAmp()\n - getRealAmp()\n - getImagAmp()\n - getProbAmp()\n - getNumAmps()\n - getNumQubits()\n\n @ingroup calc\n @param[in] qureg object representing a density matrix\n @param[in] row row of the desired amplitude in the density matrix\n @param[in] col column of the desired amplitude in the density matrix\n @return a Complex scalar representing the desired amplitude\n @throws invalidQuESTInputError()\n - if \\p qureg is a state-vector,\n - if \\p row or \\p col are outside [0, \\f$2^{N}\\f$) where \\f$N = \\f$ \\p qureg.numQubitsRepresented\n @author Tyson Jones"]
752 pub fn getDensityAmp(
753 qureg: Qureg,
754 row: ::std::os::raw::c_longlong,
755 col: ::std::os::raw::c_longlong,
756 ) -> Complex;
757}
758extern "C" {
759 #[doc = " A debugging function which calculates the probability of the qubits in \\p qureg\n being in any state, which should always be 1 for correctly normalised states\n (hence returning a real number).\n For state-vectors \\f$ \\psi \\f$, this is the norm of the entire state-vector\n (the sum of the absolute-value-squared of every amplitude):\n \\f[\n \\sum\\limits_i |\\psi_i|^2\n \\f]\n and for density matrices \\f$ \\rho \\f$, it is the trace:\n \\f[\n \\text{Trace}(\\rho) = \\sum\\limits_i \\rho_{i,i} \\;\n \\f]\n\n For un-normalised density matrices (those directly modified or initialised by the user),\n this function returns the real component of the trace.\n\n Note this calculation utilises Kahan summation for greater accuracy, and hence is\n not parallelised and so will be slower than other functions.\n\n @ingroup calc\n @param[in] qureg object representing a set of qubits\n @return the total probability of the qubits in \\p qureg being in any state\n @author Ania Brown (state-vector)\n @author Tyson Jones (density matrix, doc)"]
760 pub fn calcTotalProb(qureg: Qureg) -> f64;
761}
762extern "C" {
763 #[doc = " Apply a single-qubit unitary parameterised by two given complex scalars.\n Given valid complex numbers \\f$\\alpha\\f$ and \\f$\\beta\\f$, applies the unitary\n \\f[\n U =\n \\begin{pmatrix}\n \\alpha & -\\beta^* \\\\\n \\beta & \\alpha^*\n \\end{pmatrix}\n \\f]\n which is general up to a global phase factor.\n Valid \\f$\\alpha\\f$, \\f$\\beta\\f$ satisfy \\f$|\\alpha|^2 + |\\beta|^2 = 1\\f$.\n\n@htmlonly\n<center>\n<script type=\"text/tikz\">\n\\begin{tikzpicture}[scale=.5]\n\\node[draw=none] at (-3.5, 0) {target};\n\n\\draw (-2,0) -- (-1, 0);\n\\draw (1, 0) -- (2, 0);\n\\draw (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle;\n\\node[draw=none] at (0, 0) {U};\n\\end{tikzpicture}\n</script>\n</center>\n@endhtmlonly\n\n @see\n - controlledCompactUnitary()\n - unitary()\n - twoQubitUnitary()\n - multiQubitUnitary()\n\n @ingroup unitary\n @param[in,out] qureg object representing the set of all qubits\n @param[in] targetQubit qubit to operate on\n @param[in] alpha complex unitary parameter (row 1, column 1)\n @param[in] beta complex unitary parameter (row 2, column 1)\n @throws invalidQuESTInputError()\n - if \\p targetQubit is outside [0, \\p qureg.numQubitsRepresented)\n - if \\p alpha, \\p beta don't satisfy |`alpha`|^2 + |`beta`|^2 = 1\n @author Ania Brown (state-vector)\n @author Tyson Jones (density matrix, doc)"]
764 pub fn compactUnitary(
765 qureg: Qureg,
766 targetQubit: ::std::os::raw::c_int,
767 alpha: Complex,
768 beta: Complex,
769 );
770}
771extern "C" {
772 #[doc = " Apply a general single-qubit unitary (including a global phase factor).\n The passed 2x2 ComplexMatrix must be unitary, otherwise an error is thrown.\n\n@htmlonly\n<center>\n<script type=\"text/tikz\">\n\\begin{tikzpicture}[scale=.5]\n\\node[draw=none] at (-3.5, 0) {target};\n\n\\draw (-2,0) -- (-1, 0);\n\\draw (1, 0) -- (2, 0);\n\\draw (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle;\n\\node[draw=none] at (0, 0) {U};\n\\end{tikzpicture}\n</script>\n</center>\n@endhtmlonly\n\n If \\p qureg is a state-vector, then the resulting state is \\f$ u \\, |\\text{qureg}\\rangle \\f$.\\n\n If \\p qureg is a density-matrix \\f$ \\rho \\f$, then the resulting state is \\f$ u \\, \\rho \\, u^\\dagger \\f$.\n\n > Use applyMatrix2() to left-multiply a non-unitary ::ComplexMatrix2\n\n @see\n - ::ComplexMatrix2\n - controlledUnitary()\n - multiControlledUnitary()\n - multiStateControlledUnitary()\n - twoQubitUnitary()\n - multiQubitUnitary()\n - applyMatrix2()\n - compactUnitary()\n\n @ingroup unitary\n @param[in,out] qureg object representing the set of all qubits\n @param[in] targetQubit qubit to operate on\n @param[in] u unitary matrix to apply\n @throws invalidQuESTInputError()\n - if \\p targetQubit is outside [0, \\p qureg.numQubitsRepresented)\n - if matrix \\p u is not unitary\n @author Ania Brown (state-vector)\n @author Tyson Jones (density matrix, doc)"]
773 pub fn unitary(qureg: Qureg, targetQubit: ::std::os::raw::c_int, u: ComplexMatrix2);
774}
775extern "C" {
776 #[doc = " Rotate a single qubit by a given angle around the X-axis of the Bloch-sphere. For angle \\f$\\theta\\f$, applies\n \\f[\n \\begin{pmatrix}\n \\cos\\theta/2 & -i \\sin \\theta/2\\\\\n -i \\sin \\theta/2 & \\cos \\theta/2\n \\end{pmatrix}\n \\f]\n with circuit diagram:\n@htmlonly\n<center>\n<script type=\"text/tikz\">\n\\begin{tikzpicture}[scale=.5]\n\\node[draw=none] at (-3.5, 0) {rot};\n\n\\draw (-2,0) -- (-1, 0);\n\\draw (1, 0) -- (2, 0);\n\\draw (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle;\n\\node[draw=none] at (0, 0) {$R_x(\\theta)$};\n\\end{tikzpicture}\n</script>\n</center>\n@endhtmlonly\n\n @see\n - controlledRotateX()\n - rotateY()\n - rotateZ()\n - rotateAroundAxis()\n - multiRotateZ()\n - multiRotatePauli()\n\n @ingroup unitary\n @param[in,out] qureg object representing the set of all qubits\n @param[in] rotQubit qubit to rotate\n @param[in] angle angle by which to rotate in radians\n @throws invalidQuESTInputError()\n - if \\p rotQubit is outside [0, \\p qureg.numQubitsRepresented)\n @author Ania Brown (state-vector)\n @author Tyson Jones (density matrix, doc)"]
777 pub fn rotateX(qureg: Qureg, rotQubit: ::std::os::raw::c_int, angle: f64);
778}
779extern "C" {
780 #[doc = " Rotate a single qubit by a given angle around the Y-axis of the Bloch-sphere.\n For angle \\f$\\theta\\f$, applies\n \\f[\n \\begin{pmatrix}\n \\cos\\theta/2 & - \\sin \\theta/2\\\\\n \\sin \\theta/2 & \\cos \\theta/2\n \\end{pmatrix}\n \\f]\n with circuit diagram:\n@htmlonly\n<center>\n<script type=\"text/tikz\">\n\\begin{tikzpicture}[scale=.5]\n\\node[draw=none] at (-3.5, 0) {rot};\n\n\\draw (-2,0) -- (-1, 0);\n\\draw (1, 0) -- (2, 0);\n\\draw (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle;\n\\node[draw=none] at (0, 0) {$R_y(\\theta)$};\n\\end{tikzpicture}\n</script>\n</center>\n@endhtmlonly\n\n @see\n - controlledRotateY()\n - rotateX()\n - rotateZ()\n - rotateAroundAxis()\n - multiRotateZ()\n - multiRotatePauli()\n\n @ingroup unitary\n @param[in,out] qureg object representing the set of all qubits\n @param[in] rotQubit qubit to rotate\n @param[in] angle angle by which to rotate in radians\n @throws invalidQuESTInputError\n if \\p rotQubit is outside [0, \\p qureg.numQubitsRepresented).\n @author Ania Brown (state-vector)\n @author Tyson Jones (density matrix, doc, debug)"]
781 pub fn rotateY(qureg: Qureg, rotQubit: ::std::os::raw::c_int, angle: f64);
782}
783extern "C" {
784 #[doc = " Rotate a single qubit by a given angle around the Z-axis of the Bloch-sphere (also known as a phase shift gate).\n For angle \\f$\\theta\\f$, applies\n \\f[\n \\begin{pmatrix}\n \\exp(-i \\theta/2) & 0 \\\\\n 0 & \\exp(i \\theta/2)\n \\end{pmatrix}\n \\f]\n with circuit diagram:\n@htmlonly\n<center>\n<script type=\"text/tikz\">\n\\begin{tikzpicture}[scale=.5]\n\\node[draw=none] at (-3.5, 0) {rot};\n\n\\draw (-2,0) -- (-1, 0);\n\\draw (1, 0) -- (2, 0);\n\\draw (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle;\n\\node[draw=none] at (0, 0) {$R_z(\\theta)$};\n\\end{tikzpicture}\n</script>\n</center>\n@endhtmlonly\n\n @see\n - multiRotateZ()\n - controlledRotateZ()\n - rotateY()\n - rotateX()\n - rotateAroundAxis()\n - multiRotatePauli()\n - phaseShift()\n\n @ingroup unitary\n @param[in,out] qureg object representing the set of all qubits\n @param[in] rotQubit qubit to rotate\n @param[in] angle angle by which to rotate in radians\n @throws invalidQuESTInputError()\n - if \\p rotQubit is outside [0, \\p qureg.numQubitsRepresented)\n @author Ania Brown (state-vector)\n @author Tyson Jones (density matrix, doc)"]
785 pub fn rotateZ(qureg: Qureg, rotQubit: ::std::os::raw::c_int, angle: f64);
786}
787extern "C" {
788 #[doc = " Rotate a single qubit by a given angle around a given \\ref Vector on the Bloch-sphere.\n The vector must not be zero (else an error is thrown), but needn't be unit magnitude, since\n it will be normalised by QuEST.\n\n For angle \\f$\\theta\\f$ and axis vector \\f$\\vec{n}\\f$, applies \\f$R_{\\hat{n}} = \\exp \\left(- i \\frac{\\theta}{2} \\hat{n} \\cdot \\vec{\\sigma} \\right) \\f$\n where \\f$\\vec{\\sigma}\\f$ is the vector of Pauli matrices.\n\n @see\n - controlledRotateAroundAxis()\n - rotateX()\n - rotateY()\n - rotateZ()\n - multiRotateZ()\n - multiRotatePauli()\n\n @ingroup unitary\n @param[in,out] qureg object representing the set of all qubits\n @param[in] rotQubit qubit to rotate\n @param[in] angle angle by which to rotate in radians\n @param[in] axis vector around which to rotate (can be non-unit; will be normalised)\n @throws invalidQuESTInputError()\n - if \\p rotQubit is outside [0, \\p qureg.numQubitsRepresented)\n - if \\p axis is the zero vector\n @author Ania Brown (state-vector)\n @author Tyson Jones (density matrix, doc)"]
789 pub fn rotateAroundAxis(
790 qureg: Qureg,
791 rotQubit: ::std::os::raw::c_int,
792 angle: f64,
793 axis: Vector,
794 );
795}
796extern "C" {
797 #[doc = " Applies a controlled rotation by a given angle around the X-axis of the Bloch-sphere.\n The target qubit is rotated in states where the control qubit has value 1.\n\n@htmlonly\n<center>\n<script type=\"text/tikz\">\n\\begin{tikzpicture}[scale=.5]\n\\node[draw=none] at (-3.5, 2) {control};\n\\node[draw=none] at (-3.5, 0) {target};\n\n\\draw (-2, 2) -- (2, 2);\n\\draw[fill=black] (0, 2) circle (.2);\n\\draw (0, 2) -- (0, 1);\n\n\\draw (-2,0) -- (-1, 0);\n\\draw (1, 0) -- (2, 0);\n\\draw (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle;\n\\node[draw=none] at (0, 0) {$R_x(\\theta)$};\n\\end{tikzpicture}\n</script>\n</center>\n@endhtmlonly\n\n @see\n - rotateX()\n - controlledRotateY()\n - controlledRotateZ()\n - controlledRotateAroundAxis()\n - controlledPhaseShift()\n - multiRotateZ()\n - multiRotatePauli()\n\n @ingroup unitary\n @param[in,out] qureg object representing the set of all qubits\n @param[in] controlQubit qubit which has value 1 in the rotated states\n @param[in] targetQubit qubit to rotate\n @param[in] angle angle by which to rotate the target qubit in radians\n @throws invalidQuESTInputError()\n - if either \\p controlQubit or \\p targetQubit are outside [0, \\p qureg.numQubitsRepresented)\n - if \\p controlQubit and \\p targetQubit are equal\n @author Tyson Jones"]
798 pub fn controlledRotateX(
799 qureg: Qureg,
800 controlQubit: ::std::os::raw::c_int,
801 targetQubit: ::std::os::raw::c_int,
802 angle: f64,
803 );
804}
805extern "C" {
806 #[doc = " Applies a controlled rotation by a given angle around the Y-axis of the Bloch-sphere.\n The target qubit is rotated in states where the control qubit has value 1.\n\n@htmlonly\n<center>\n<script type=\"text/tikz\">\n\\begin{tikzpicture}[scale=.5]\n\\node[draw=none] at (-3.5, 2) {control};\n\\node[draw=none] at (-3.5, 0) {target};\n\n\\draw (-2, 2) -- (2, 2);\n\\draw[fill=black] (0, 2) circle (.2);\n\\draw (0, 2) -- (0, 1);\n\n\\draw (-2,0) -- (-1, 0);\n\\draw (1, 0) -- (2, 0);\n\\draw (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle;\n\\node[draw=none] at (0, 0) {$R_y(\\theta)$};\n\\end{tikzpicture}\n</script>\n</center>\n@endhtmlonly\n\n - rotateY()\n - controlledRotateX()\n - controlledRotateZ()\n - controlledRotateAroundAxis()\n - controlledPhaseShift()\n - multiRotateZ()\n - multiRotatePauli()\n\n @ingroup unitary\n @param[in,out] qureg object representing the set of all qubits\n @param[in] controlQubit qubit which has value 1 in the rotated states\n @param[in] targetQubit qubit to rotate\n @param[in] angle angle by which to rotate the target qubit in radians\n @throws invalidQuESTInputError()\n - if either \\p controlQubit or \\p targetQubit are outside [0, \\p qureg.numQubitsRepresented)\n - if \\p controlQubit and \\p targetQubit are equal\n @author Tyson Jones"]
807 pub fn controlledRotateY(
808 qureg: Qureg,
809 controlQubit: ::std::os::raw::c_int,
810 targetQubit: ::std::os::raw::c_int,
811 angle: f64,
812 );
813}
814extern "C" {
815 #[doc = " Applies a controlled rotation by a given angle around the Z-axis of the Bloch-sphere.\n The target qubit is rotated in states where the control qubit has value 1.\n\n@htmlonly\n<center>\n<script type=\"text/tikz\">\n\\begin{tikzpicture}[scale=.5]\n\\node[draw=none] at (-3.5, 2) {control};\n\\node[draw=none] at (-3.5, 0) {target};\n\n\\draw (-2, 2) -- (2, 2);\n\\draw[fill=black] (0, 2) circle (.2);\n\\draw (0, 2) -- (0, 1);\n\n\\draw (-2,0) -- (-1, 0);\n\\draw (1, 0) -- (2, 0);\n\\draw (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle;\n\\node[draw=none] at (0, 0) {$R_z(\\theta)$};\n\\end{tikzpicture}\n</script>\n</center>\n@endhtmlonly\n\n @see\n - rotateZ()\n - controlledRotateX()\n - controlledRotateY()\n - controlledRotateAroundAxis()\n - controlledPhaseShift()\n - multiRotateZ()\n - multiRotatePauli()\n\n @ingroup unitary\n @param[in,out] qureg object representing the set of all qubits\n @param[in] controlQubit qubit which has value 1 in the rotated states\n @param[in] targetQubit qubit to rotate\n @param[in] angle angle by which to rotate the target qubit in radians\n @throws invalidQuESTInputError()\n - if either \\p controlQubit or \\p targetQubit are outside [0, \\p qureg.numQubitsRepresented)\n - if \\p controlQubit and \\p targetQubit are equal\n @author Tyson Jones"]
816 pub fn controlledRotateZ(
817 qureg: Qureg,
818 controlQubit: ::std::os::raw::c_int,
819 targetQubit: ::std::os::raw::c_int,
820 angle: f64,
821 );
822}
823extern "C" {
824 #[doc = " Applies a controlled rotation by a given angle around a given vector on the Bloch-sphere.\n The vector must not be zero (else an error is thrown), but needn't be unit magnitude.\n\n For angle \\f$\\theta\\f$ and axis vector \\f$\\vec{n}\\f$, applies \\f$R_{\\hat{n}} = \\exp \\left(- i \\frac{\\theta}{2} \\hat{n} \\cdot \\vec{\\sigma} \\right) \\f$ to states where the target qubit is 1\n (\\f$\\vec{\\sigma}\\f$ is the vector of Pauli matrices).\n\n@htmlonly\n<center>\n<script type=\"text/tikz\">\n\\begin{tikzpicture}[scale=.5]\n\\node[draw=none] at (-3.5, 2) {control};\n\\node[draw=none] at (-3.5, 0) {target};\n\n\\draw (-2, 2) -- (2, 2);\n\\draw[fill=black] (0, 2) circle (.2);\n\\draw (0, 2) -- (0, 1);\n\n\\draw (-2,0) -- (-1, 0);\n\\draw (1, 0) -- (2, 0);\n\\draw (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle;\n\\node[draw=none] at (0, 0) {$R_{\\hat{n}}(\\theta)$};\n\\end{tikzpicture}\n</script>\n</center>\n@endhtmlonly\n\n @see\n - rotateAroundAxis()\n - multiRotatePauli()\n\n @ingroup unitary\n @param[in,out] qureg object representing the set of all qubits\n @param[in] controlQubit qubit with value 1 in the rotated states\n @param[in] targetQubit qubit to rotate\n @param[in] angle angle by which to rotate in radians\n @param[in] axis vector around which to rotate (can be non-unit; will be normalised)\n @throws invalidQuESTInputError()\n - if either \\p controlQubit or \\p targetQubit are outside [0, \\p qureg.numQubitsRepresented)\n - if \\p controlQubit and \\p targetQubit are equal\n - if \\p axis is the zero vector\n @author Tyson Jones"]
825 pub fn controlledRotateAroundAxis(
826 qureg: Qureg,
827 controlQubit: ::std::os::raw::c_int,
828 targetQubit: ::std::os::raw::c_int,
829 angle: f64,
830 axis: Vector,
831 );
832}
833extern "C" {
834 #[doc = " Apply a controlled unitary (single control, single target) parameterised by two given complex scalars.\n Given valid complex numbers \\f$\\alpha\\f$ and \\f$\\beta\\f$, applies the two-qubit unitary\n \\f[\n \\begin{pmatrix}\n 1 \\\\\n & 1 \\\\\n & & \\alpha & -\\beta^* \\\\\n & & \\beta & \\alpha^*\n \\end{pmatrix}\n \\f]\n to the control and target qubits.\n Valid \\f$\\alpha\\f$, \\f$\\beta\\f$ satisfy \\f$|\\alpha|^2 + |\\beta|^2 = 1\\f$.\n The target unitary is general up to a global phase factor.\n\n@htmlonly\n<center>\n<script type=\"text/tikz\">\n\\begin{tikzpicture}[scale=.5]\n\\node[draw=none] at (-3.5, 2) {control};\n\\node[draw=none] at (-3.5, 0) {target};\n\n\\draw (-2, 2) -- (2, 2);\n\\draw[fill=black] (0, 2) circle (.2);\n\\draw (0, 2) -- (0, 1);\n\n\\draw (-2,0) -- (-1, 0);\n\\draw (1, 0) -- (2, 0);\n\\draw (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle;\n\\node[draw=none] at (0, 0) {$U_{\\alpha, \\beta}$};\n\\end{tikzpicture}\n</script>\n</center>\n@endhtmlonly\n\n @see\n - compactUnitary()\n - controlledUnitary()\n - multiControlledUnitary()\n - multiStateControlledUnitary()\n\n @ingroup unitary\n @param[in,out] qureg object representing the set of all qubits\n @param[in] controlQubit apply the target unitary if this qubit has value 1\n @param[in] targetQubit qubit on which to apply the target unitary\n @param[in] alpha complex unitary parameter (row 1, column 1)\n @param[in] beta complex unitary parameter (row 2, column 1)\n @throws invalidQuESTInputError()\n - if either \\p controlQubit or \\p targetQubit are outside [0, \\p qureg.numQubitsRepresented)\n - if \\p controlQubit and \\p targetQubit are equal\n - if \\p alpha, \\p beta don't satisfy |`alpha`|^2 + |`beta`|^2 = 1\n @author Ania Brown (state-vector)\n @author Tyson Jones (density matrix, doc)"]
835 pub fn controlledCompactUnitary(
836 qureg: Qureg,
837 controlQubit: ::std::os::raw::c_int,
838 targetQubit: ::std::os::raw::c_int,
839 alpha: Complex,
840 beta: Complex,
841 );
842}
843extern "C" {
844 #[doc = " Apply a general controlled unitary (single control, single target), which can include a global phase factor.\n The given unitary is applied to the target qubit if the control qubit has value 1,\n effecting the two-qubit unitary\n \\f[\n \\begin{pmatrix}\n 1 \\\\\n & 1 \\\\\n & & u_{00} & u_{01}\\\\\n & & u_{10} & u_{11}\n \\end{pmatrix}\n \\f]\n on the control and target qubits.\n\n@htmlonly\n<center>\n<script type=\"text/tikz\">\n\\begin{tikzpicture}[scale=.5]\n\\node[draw=none] at (-3.5, 2) {control};\n\\node[draw=none] at (-3.5, 0) {target};\n\n\\draw (-2, 2) -- (2, 2);\n\\draw[fill=black] (0, 2) circle (.2);\n\\draw (0, 2) -- (0, 1);\n\n\\draw (-2,0) -- (-1, 0);\n\\draw (1, 0) -- (2, 0);\n\\draw (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle;\n\\node[draw=none] at (0, 0) {U};\n\\end{tikzpicture}\n</script>\n</center>\n@endhtmlonly\n\n @see\n - ::ComplexMatrix2\n - unitary()\n - multiControlledUnitary()\n - multiStateControlledUnitary()\n - twoQubitUnitary()\n - multiQubitUnitary()\n\n @ingroup unitary\n @param[in,out] qureg object representing the set of all qubits\n @param[in] controlQubit apply unitary if this qubit is 1\n @param[in] targetQubit qubit to operate on\n @param[in] u single-qubit unitary matrix to apply\n @throws invalidQuESTInputError()\n - if either \\p controlQubit or \\p targetQubit are outside [0, \\p qureg.numQubitsRepresented)\n - if \\p controlQubit and \\p targetQubit are equal\n - if \\p u is not unitary\n @author Ania Brown (state-vector)\n @author Tyson Jones (density matrix, doc)"]
845 pub fn controlledUnitary(
846 qureg: Qureg,
847 controlQubit: ::std::os::raw::c_int,
848 targetQubit: ::std::os::raw::c_int,
849 u: ComplexMatrix2,
850 );
851}
852extern "C" {
853 #[doc = " Apply a general multiple-control single-target unitary, which can include\n a global phase factor. Any number of control qubits can be specified,\n and if all have value 1, the given unitary is applied to the target qubit.\n This effects the many-qubit unitary\n \\f[\n \\begin{pmatrix}\n 1 \\\\\n & 1 \\\\\\\n & & \\ddots \\\\\n & & & u_{00} & u_{01}\\\\\n & & & u_{10} & u_{11}\n \\end{pmatrix}\n \\f]\n on the control and target qubits.\n The given 2x2 ComplexMatrix must be unitary, otherwise an error is thrown.\n\n@htmlonly\n<center>\n<script type=\"text/tikz\">\n\\begin{tikzpicture}[scale=.5]\n\\node[draw=none] at (-3.5, 3) {controls};\n\\node[draw=none] at (-3.5, 0) {target};\n\n\\node[draw=none] at (0, 6) {$\\vdots$};\n\\draw (0, 5) -- (0, 4);\n\n\\draw (-2, 4) -- (2, 4);\n\\draw[fill=black] (0, 4) circle (.2);\n\\draw (0, 4) -- (0, 2);\n\n\\draw (-2, 2) -- (2, 2);\n\\draw[fill=black] (0, 2) circle (.2);\n\\draw (0, 2) -- (0, 1);\n\n\\draw (-2,0) -- (-1, 0);\n\\draw (1, 0) -- (2, 0);\n\\draw (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle;\n\\node[draw=none] at (0, 0) {U};\n\\end{tikzpicture}\n</script>\n</center>\n@endhtmlonly\n\n @see\n - ::ComplexMatrix2\n - unitary()\n - controlledUnitary()\n - multiStateControlledUnitary()\n - twoQubitUnitary()\n - multiQubitUnitary()\n\n @ingroup unitary\n @param[in,out] qureg object representing the set of all qubits\n @param[in] controlQubits applies unitary if all qubits in this array equal 1\n @param[in] numControlQubits number of control qubits\n @param[in] targetQubit qubit to operate on\n @param[in] u single-qubit unitary matrix to apply\n @throws invalidQuESTInputError()\n - if \\p numControlQubits is outside [1, \\p qureg.numQubitsRepresented])\n - if any qubit index (\\p targetQubit or one in \\p controlQubits) is outside [0, \\p qureg.numQubitsRepresented])\n - if any qubit in \\p controlQubits is repeated\n - if \\p controlQubits contains \\p targetQubit\n - if \\p u is not unitary\n @author Ania Brown (state-vector)\n @author Tyson Jones (density matrix, doc)"]
854 pub fn multiControlledUnitary(
855 qureg: Qureg,
856 controlQubits: *mut ::std::os::raw::c_int,
857 numControlQubits: ::std::os::raw::c_int,
858 targetQubit: ::std::os::raw::c_int,
859 u: ComplexMatrix2,
860 );
861}
862extern "C" {
863 #[doc = " Apply the single-qubit Pauli-X (also known as the X, sigma-X, NOT or bit-flip) gate.\n This is a rotation of \\f$\\pi\\f$ around the x-axis on the Bloch sphere. I.e.\n \\f[\n \\begin{pmatrix}\n 0 & 1 \\\\\n 1 & 0\n \\end{pmatrix}\n \\f]\n with circuit diagram:\n@htmlonly\n<center>\n<script type=\"text/tikz\">\n\\begin{tikzpicture}[scale=.5]\n\\node[draw=none] at (-3.5, 0) {target};\n\n\\draw (-2,0) -- (2, 0);\n\\draw (0, 0) circle (.5);\n\\draw (0, .5) -- (0, -.5);\n\\end{tikzpicture}\n</script>\n</center>\n@endhtmlonly\n\n @see\n - rotateX()\n - pauliY()\n - pauliZ()\n - controlledNot()\n - multiQubitNot()\n - multiControlledMultiQubitNot()\n\n @ingroup unitary\n @param[in,out] qureg object representing the set of all qubits\n @param[in] targetQubit qubit to operate on\n @throws invalidQuESTInputError()\n - if \\p targetQubit is outside [0, \\p qureg.numQubitsRepresented)\n @author Ania Brown (state-vector)\n @author Tyson Jones (density matrix, doc)"]
864 pub fn pauliX(qureg: Qureg, targetQubit: ::std::os::raw::c_int);
865}
866extern "C" {
867 #[doc = " Apply the single-qubit Pauli-Y (also known as the Y or sigma-Y) gate.\n This is a rotation of \\f$\\pi\\f$ around the Y-axis on the Bloch sphere. I.e.\n \\f[\n \\begin{pmatrix}\n 0 & -i \\\\\n i & 0\n \\end{pmatrix}\n \\f]\n with circuit diagram:\n@htmlonly\n<center>\n<script type=\"text/tikz\">\n\\begin{tikzpicture}[scale=.5]\n\\node[draw=none] at (-3.5, 0) {target};\n\n\\draw (-2,0) -- (-1, 0);\n\\draw (1, 0) -- (2, 0);\n\\draw (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle;\n\\node[draw=none] at (0, 0) {$\\sigma_y$};\n\\end{tikzpicture}\n</script>\n</center>\n@endhtmlonly\n\n @see\n - rotateY()\n - pauliX()\n - pauliZ()\n\n @ingroup unitary\n @param[in,out] qureg object representing the set of all qubits\n @param[in] targetQubit qubit to operate on\n @throws invalidQuESTInputError()\n - if \\p targetQubit is outside [0, \\p qureg.numQubitsRepresented)\n @author Ania Brown (state-vector)\n @author Tyson Jones (density matrix, doc)"]
868 pub fn pauliY(qureg: Qureg, targetQubit: ::std::os::raw::c_int);
869}
870extern "C" {
871 #[doc = " Apply the single-qubit Pauli-Z (also known as the Z, sigma-Z or phase-flip) gate.\n This is a rotation of \\f$\\pi\\f$ around the Z-axis (a phase shift) on the Bloch sphere. I.e.\n \\f[\n \\begin{pmatrix}\n 1 & 0 \\\\\n 0 & -1\n \\end{pmatrix}\n \\f]\n with circuit diagram:\n@htmlonly\n<center>\n<script type=\"text/tikz\">\n\\begin{tikzpicture}[scale=.5]\n\\node[draw=none] at (-3.5, 0) {target};\n\n\\draw (-2,0) -- (-1, 0);\n\\draw (1, 0) -- (2, 0);\n\\draw (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle;\n\\node[draw=none] at (0, 0) {$\\sigma_z$};\n\\end{tikzpicture}\n</script>\n</center>\n@endhtmlonly\n\n @see\n - phaseShift()\n - rotateZ()\n - pauliX()\n - pauliY()\n - controlledPhaseFlip()\n - multiControlledPhaseFlip()\n\n @ingroup unitary\n @param[in,out] qureg object representing the set of all qubits\n @param[in] targetQubit qubit to operate on\n @throws invalidQuESTInputError()\n - if \\p targetQubit is outside [0, \\p qureg.numQubitsRepresented)\n @author Ania Brown (state-vector)\n @author Tyson Jones (density matrix, doc)"]
872 pub fn pauliZ(qureg: Qureg, targetQubit: ::std::os::raw::c_int);
873}
874extern "C" {
875 #[doc = " Apply the single-qubit Hadamard gate.\n This takes \\f$|0\\rangle\\f$ to \\f$|+\\rangle\\f$ and \\f$|1\\rangle\\f$ to \\f$|-\\rangle\\f$, and is equivalent to a rotation of\n \\f$\\pi\\f$ around the x-axis then \\f$\\pi/2\\f$ about the y-axis on the Bloch-sphere. I.e.\n \\f[\n \\frac{1}{\\sqrt{2}}\n \\begin{pmatrix}\n 1 & 1 \\\\\n 1 & -1\n \\end{pmatrix}\n \\f]\n\n@htmlonly\n<center>\n<script type=\"text/tikz\">\n\\begin{tikzpicture}[scale=.5]\n\\node[draw=none] at (-3.5, 0) {target};\n\n\\draw (-2,0) -- (-1, 0);\n\\draw (1, 0) -- (2, 0);\n\\draw (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle;\n\\node[draw=none] at (0, 0) {H};\n\\end{tikzpicture}\n</script>\n</center>\n@endhtmlonly\n\n @ingroup unitary\n @param[in,out] qureg object representing the set of all qubits\n @param[in] targetQubit qubit to operate on\n @throws invalidQuESTInputError()\n - if \\p targetQubit is outside [0, \\p qureg.numQubitsRepresented)\n @author Ania Brown (state-vector)\n @author Tyson Jones (density matrix, doc)"]
876 pub fn hadamard(qureg: Qureg, targetQubit: ::std::os::raw::c_int);
877}
878extern "C" {
879 #[doc = " Apply the controlled not (single control, single target) gate, also\n known as the c-X, c-sigma-X, c-Pauli-X and c-bit-flip gate.\n This applies pauliX to the target qubit if the control qubit has value 1.\n This effects the two-qubit unitary\n \\f[\n \\begin{pmatrix}\n 1 \\\\\n & 1 \\\\\\\n & & & 1 \\\\\n & & 1\n \\end{pmatrix}\n \\f]\n on the control and target qubits.\n\n@htmlonly\n<center>\n<script type=\"text/tikz\">\n\\begin{tikzpicture}[scale=.5]\n\\node[draw=none] at (-3.5, 2) {control};\n\\node[draw=none] at (-3.5, 0) {target};\n\n\\draw (-2, 2) -- (2, 2);\n\\draw[fill=black] (0, 2) circle (.2);\n\\draw (0, 2) -- (0, -.5);\n\n\\draw (-2,0) -- (2, 0);\n\\draw (0, 0) circle (.5);\n\\end{tikzpicture}\n</script>\n</center>\n@endhtmlonly\n\n @see\n - multiControlledMultiQubitNot()\n - pauliX()\n\n @ingroup unitary\n @param[in,out] qureg the state-vector or density matrix to modify\n @param[in] controlQubit nots the target if this qubit is 1\n @param[in] targetQubit qubit to not\n @throws invalidQuESTInputError()\n - if either \\p controlQubit or \\p targetQubit are outside <b>[0, </b>`qureg.numQubitsRepresented`<b>)</b>\n - if \\p controlQubit and \\p targetQubit are equal\n @author Ania Brown (state-vector)\n @author Tyson Jones (density matrix, doc)"]
880 pub fn controlledNot(
881 qureg: Qureg,
882 controlQubit: ::std::os::raw::c_int,
883 targetQubit: ::std::os::raw::c_int,
884 );
885}
886extern "C" {
887 #[doc = " Apply a NOT (or Pauli X) gate with multiple control and target qubits.\n This applies pauliX to qubits \\p targs on every basis state for which the\n control qubits \\p ctrls are all in the \\f$|1\\rangle\\f$ state. The ordering within\n each of \\p ctrls and \\p targs has no effect on the operation.\n > This function is equivalent, but significantly faster (approximately \\p numTargs times)\n > than applying controlled NOTs on each qubit in \\p targs in turn, since:\n > \\f[\n > C_{a, \\,b, \\,\\dots}( X_c \\otimes X_d \\otimes \\dots ) \\equiv\n > C_{a, \\,b, \\,\\dots}( X_c) \\; \\otimes \\; C_{a, \\,b, \\,\\dots}(X_d) \\; \\otimes \\; \\dots\n > \\f]\n\n The effected unitary, if \\p targs and \\p ctrls happened to be contiguous, has matrix:\n \\f[\n \\begin{pmatrix}\n 1 \\\\\n & 1 \\\\\\\n & & \\ddots \\\\\n & & & & & & {{\\scriptstyle\\cdot}^{{\\scriptstyle\\cdot}^{{\\scriptstyle\\cdot}}}} \\\\\n & & & & & 1 & \\\\\n & & & & 1 & & \\\\\n & & & {{\\scriptstyle\\cdot}^{{\\scriptstyle\\cdot}^{{\\scriptstyle\\cdot}}}} & & &\n \\end{pmatrix}\n \\f]\n and circuit diagram:\n@htmlonly\n<center>\n<script type=\"text/tikz\">\n\\begin{tikzpicture}[scale=.5]\n\\node[draw=none] at (-3.5, 1) {targets};\n\\node[draw=none] at (-3.5, 5) {controls};\n\n\\node[draw=none] at (0, 8) {$\\vdots$};\n\\draw (0, 7) -- (0, 6);\n\n\\draw (-2, 6) -- (2, 6);\n\\draw[fill=black] (0, 6) circle (.2);\n\\draw (0, 6) -- (0, 4);\n\n\\draw (-2, 4) -- (2, 4);\n\\draw[fill=black] (0, 4) circle (.2);\n\\draw(0, 4) -- (0, -1);\n\n\\draw (-2,2) -- (2, 2);\n\\draw (0, 2) circle (.4);\n\n\\draw (-2,0) -- (2, 0);\n\\draw (0, 0) circle (.4);\n\n\\node[draw=none] at (0, -1.5) {$\\vdots$};\n\\end{tikzpicture}\n</script>\n</center>\n@endhtmlonly\n > In distributed mode, this operation requires at most a single round of pair-wise\n > communication between nodes, and hence is as efficient as pauliX().\n\n @see\n - multiQubitNot()\n - controlledNot()\n - pauliX()\n\n @ingroup unitary\n @param[in,out] qureg a state-vector or density matrix to modify\n @param[in] ctrls a list of the control qubit indices\n @param[in] numCtrls the length of list \\p ctrls\n @param[in] targs a list of the qubits to be targeted by the X gates\n @param[in] numTargs the length of list \\p targs\n @throws invalidQuESTInputError()\n - if any qubit in \\p ctrls and \\p targs is invalid, i.e. outside <b>[0, </b>`qureg.numQubitsRepresented`<b>)</b>\n - if \\p ctrls or \\p targs contain any repetitions\n - if any qubit in \\p ctrls is also in \\p targs (and vice versa)\n - if \\p numTargs <b>< 1</b>\n - if \\p numCtrls <b>< 1</b> (use multiQubitNot() for no controls)\n @throws segmentation-fault\n - if \\p ctrls contains fewer elements than \\p numCtrls\n - if \\p targs contains fewer elements than \\p numTargs\n @author Tyson Jones"]
888 pub fn multiControlledMultiQubitNot(
889 qureg: Qureg,
890 ctrls: *mut ::std::os::raw::c_int,
891 numCtrls: ::std::os::raw::c_int,
892 targs: *mut ::std::os::raw::c_int,
893 numTargs: ::std::os::raw::c_int,
894 );
895}
896extern "C" {
897 #[doc = " Apply the controlled pauliY (single control, single target) gate, also\n known as the c-Y and c-sigma-Y gate.\n This applies pauliY to the target qubit if the control qubit has value 1.\n This effects the two-qubit unitary\n \\f[\n \\begin{pmatrix}\n 1 \\\\\n & 1 \\\\\\\n & & & -i \\\\\n & & i\n \\end{pmatrix}\n \\f]\n on the control and target qubits.\n\n@htmlonly\n<center>\n<script type=\"text/tikz\">\n\\begin{tikzpicture}[scale=.5]\n\\node[draw=none] at (-3.5, 2) {control};\n\\node[draw=none] at (-3.5, 0) {target};\n\n\\draw (-2, 2) -- (2, 2);\n\\draw[fill=black] (0, 2) circle (.2);\n\\draw (0, 2) -- (0, 1);\n\n\\draw (-2,0) -- (-1, 0);\n\\draw (1, 0) -- (2, 0);\n\\draw (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle;\n\\node[draw=none] at (0, 0) {Y};\n\\end{tikzpicture}\n</script>\n</center>\n@endhtmlonly\n\n @ingroup unitary\n @param[in,out] qureg object representing the set of all qubits\n @param[in] controlQubit applies pauliY to the target if this qubit is 1\n @param[in] targetQubit qubit to not\n @throws invalidQuESTInputError()\n - if either \\p controlQubit or \\p targetQubit are outside [0, \\p qureg.numQubitsRepresented)\n - if \\p controlQubit and \\p targetQubit are equal\n @author Tyson Jones\n @author Ania Brown (debug)"]
898 pub fn controlledPauliY(
899 qureg: Qureg,
900 controlQubit: ::std::os::raw::c_int,
901 targetQubit: ::std::os::raw::c_int,
902 );
903}
904extern "C" {
905 #[doc = " Gives the probability of a specified qubit being measured in the given outcome (0 or 1).\n This performs no actual measurement and does not change the state of the qubits.\n\n For state-vectors, this function works by summing the absolute-value-squared of every\n amplitude in the state-vector for which \\p measureQubit \\p = \\p 0.\n If \\p outcome \\p = \\p 1, it returns \\p 1 minus this value. Hence for unnormalised\n state-vectors, this result will differ from the absolute-value-squared of every\n amplitude where \\p measureQubit \\p = \\p outcome.\n\n For density matrices, this function sums the diagonal values (should be real)\n corresponding to \\p measureQubit \\p = \\p 0 (returning 1 minus this if \\p outcome \\p = \\p 1).\n\n @see\n - calcProbOfAllOutcomes()\n\n @see\n - measure()\n - measureWithStats()\n - collapseToOutcome()\n - calcTotalProb()\n\n @ingroup calc\n @param[in] qureg object representing the set of all qubits\n @param[in] measureQubit qubit to study\n @param[in] outcome for which to find the probability of the qubit being measured in\n @return probability of qubit measureQubit being measured in the given outcome\n @throws invalidQuESTInputError()\n - if \\p measureQubit is outside [0, \\p qureg.numQubitsRepresented)\n - if \\p outcome is not in {0, 1}\n @author Ania Brown (state-vector)\n @author Tyson Jones (density matrix)"]
906 pub fn calcProbOfOutcome(
907 qureg: Qureg,
908 measureQubit: ::std::os::raw::c_int,
909 outcome: ::std::os::raw::c_int,
910 ) -> f64;
911}
912extern "C" {
913 #[doc = " Populates \\p outcomeProbs with the probabilities of every outcome of the sub-register\n contained in \\p qubits.\n\n > This performs no actual measurement and does not modify \\p qureg.\n\n - For \\p qubits <b>= {a, b, c, ...}</b>, \\p outcomeProbs\n is populated to\n \\f[\n \\text{outcomeProbs} = \\{ \\; |\\alpha_0|^2, \\; |\\alpha_1|^2, \\; |\\alpha_2|^2, \\; |\\alpha_3|^2, \\; ... \\; \\},\n \\f]\n where \\f$|\\alpha_j|^2\\f$ are the probabilities of the respective outcome states (interpreting\n \\p qubits as ordered least to most significant)\n \\f[\n |\\dots\\textbf{c}\\,\\textbf{b}\\,\\textbf{a}\\rangle_i \\; \\; = \\;\\; |000\\rangle, \\;\\; |001\\rangle \\;\\; |010\\rangle \\;\\; |011\\rangle, \\;\\; \\dots\n \\f]\n understood in a state-vector \\p qureg \\f$|\\psi\\rangle\\f$ as\n \\f[\n |\\psi\\rangle = \\sum\\limits_i^{\\text{numQubits}} \\alpha_i \\; |\\dots\\textbf{c}\\,\\textbf{b}\\,\\textbf{a}\\rangle_i\n \\; \\otimes \\; |\\phi\\rangle_i,\n \\f]\n or in a density matrix \\p qureg \\f$\\rho\\f$ as\n \\f[\n \\begin{aligned}\n \\rho &= \\sum\\limits_{i,j}^{\\text{numQubits}} \\; \\beta_{ij} \\; |\\dots\\textbf{c}\\,\\textbf{b}\\,\\textbf{a}\\rangle_i\\,\\langle\\dots\\textbf{c}\\,\\textbf{b}\\,\\textbf{a}|_j\n \\; \\otimes \\; \\mu_{ij} \\\\\n &= \\sum\\limits_i^{\\text{numQubits}} \\; |\\alpha_i|^2 \\; |\\dots\\textbf{c}\\,\\textbf{b}\\,\\textbf{a}\\rangle\\langle\\dots\\textbf{c}\\,\\textbf{b}\\,\\textbf{a}|_i \\;\\; + \\,\n \\sum\\limits_{i \\ne j}^{\\text{numQubits}} \\; \\beta_{ij} \\; |\\dots\\textbf{c}\\,\\textbf{b}\\,\\textbf{a}\\rangle_i\\,\\langle\\dots\\textbf{c}\\,\\textbf{b}\\,\\textbf{a}|_j\n \\; \\otimes \\; \\mu_{ij},\n \\end{aligned}\n \\f]\n where \\f$|\\phi\\rangle_i\\f$ and \\f$\\mu_{ij}\\f$ are understood to be the separated states of the remaining qubits.\n\n > \\p outcomeProbs must be a pre-allocated array of length \\f$2^{\\text{numQubits}}\\f$,\n > which is equivalent to <b>1<<</b>\\p numQubits. In distributed mode, every node receives\n > the full list of outcome probabilities.\n\n - Note that the indices in \\p qubits need not be adjacent nor ordered. The order of\n \\p qubits determines the order of \\p outcomeProbs, whereby \\p qubits are treated\n as <em>increasing</em> significance.\n \\n\\n\n\n - For example, given a \\p qureg initialised into state-vector\n \\f[\n |\\psi\\rangle =\n \\alpha_0 |000\\rangle \\;+\\; \\alpha_1 |001\\rangle \\;+\\;\n \\alpha_2 |010\\rangle \\;+\\; \\alpha_3 |011\\rangle \\;+\\;\n \\alpha_4 |100\\rangle \\;+\\; \\alpha_5 |101\\rangle \\;+\\;\n \\alpha_6 |110\\rangle \\;+\\; \\alpha_7 |111\\rangle,\n \\f]\n then executing\n ```\n int qubits[] = {2, 0};\n int numQubits = 2;\n\n qreal outcomeProbs[1<<numQubits];\n calcProbOfAllOutcomes(outcomeProbs, qureg, qubits, numQubits);\n ```\n would populate \\p outcomeProbs with\n \\f[\n \\text{outcomeProbs} = \\{ \\;\\; |\\alpha_0|^2+|\\alpha_2|^2, \\;\\; |\\alpha_4|^2+|\\alpha_6|^2, \\;\\;\n |\\alpha_1|^2+|\\alpha_3|^2, \\;\\; |\\alpha_5|^2+|\\alpha_7|^2 \\;\\; \\}.\n \\f]\n\n > Since all probability amplitudes of a state-vector are ultimately involved in\n > the output probabilities, calcProbOfAllOutcomes() works as expected for\n > un-normalised states. This is similarly true for density matrices, where all\n > diagonal elements are involved, although only the real values of the diagonal elements\n > will be consulted.\n\n @see\n - calcProbOfOutcome()\n\n @ingroup calc\n @param[out] outcomeProbs a pre-allocated array of length <b>1<<</b>\\p numQubits,\n which will be modified to contain all outcome probabilities\n @param[in] qureg a state-vector or density matrix to study\n @param[in] qubits a list of qubits to study\n @param[in] numQubits the length of list \\p qubits\n @throws invalidQuESTInputError()\n - if \\p numQubits <= 0\n - if any index in \\p qubits is invalid, i.e. outside <b>[0,</b> \\p qureg.numQubitsRepresented <b>)</b>\n - if \\p qubits contains any repetitions\n @throws segmentation-fault\n - if \\p outcomeProbs is not pre-allocated\n - if \\p outcomeProbs contains space for fewer than <b>1<<</b>\\p numQubits elements\n @author Tyson Jones"]
914 pub fn calcProbOfAllOutcomes(
915 outcomeProbs: *mut f64,
916 qureg: Qureg,
917 qubits: *mut ::std::os::raw::c_int,
918 numQubits: ::std::os::raw::c_int,
919 );
920}
921extern "C" {
922 #[doc = " Measures a single qubit, collapsing it randomly to 0 or 1.\n\n Outcome probabilities are weighted by the state vector, which is irreversibly\n changed after collapse to be consistent with the outcome.\n\n > The random outcome generator is seeded by seedQuESTDefault() within\n > createQuESTEnv(), unless later overridden by seedQuEST().\n\n @see\n - measureWithStats()\n - collapseToOutcome()\n - seedQuEST()\n - seedQuESTDefault()\n\n @ingroup normgate\n @param[in, out] qureg object representing the set of all qubits\n @param[in] measureQubit qubit to measure\n @return the measurement outcome, 0 or 1\n @throws invalidQuESTInputError()\n - if \\p measureQubit is outside [0, \\p qureg.numQubitsRepresented)\n @author Ania Brown (state-vector)\n @author Tyson Jones (density matrix)"]
923 pub fn measure(qureg: Qureg, measureQubit: ::std::os::raw::c_int) -> ::std::os::raw::c_int;
924}
925extern "C" {
926 #[doc = " Computes the inner product \\f$ \\langle \\text{bra} | \\text{ket} \\rangle \\f$ of two\n equal-size state vectors, given by\n \\f[\n\\langle \\text{bra} | \\text{ket} \\rangle = \\sum_i {\\text{bra}_i}^* \\; \\times \\; \\text{ket}_i\n \\f]\n The same \\p qureg may be passed as both \\p bra and \\p ket,\n though we recommend users check state-vector normalisation with \\p calcTotalProb which\n employs Kahan summation for greater accuracy.\n Neither state-vector is modified.\n\n This function returns the correct inner product even if \\p bra and \\p ket are\n not correctly normalised states.\n\n @see\n - calcDensityInnerProduct()\n\n @ingroup calc\n @param[in] bra qureg to be the 'bra' (i.e. have its values conjugate transposed) in the inner product\n @param[in] ket qureg to be the 'ket' in the inner product\n @return the complex inner product of \\p bra and \\p ket\n @throws invalidQuESTInputError()\n - if either \\p bra and \\p ket are not both state-vectors\n - if \\p bra and \\p ket do not have equal dimensions\n @author Tyson Jones"]
927 pub fn calcInnerProduct(bra: Qureg, ket: Qureg) -> Complex;
928}
929extern "C" {
930 #[doc = " Computes the Hilbert-Schmidt scalar product\n (which is equivalent to the Frobenius inner product of matrices)\n of two density matrices \\p rho1 and \\p rho2 of equivalent size.\n That is, we define the Hilbert-Schmidt scalar product\n \\f[\n((\\rho_1, \\rho_2))_{HS} := \\text{Tr}[ \\rho_1^\\dagger \\rho_2 ],\n \\f]\n which is equivalent to the sum of products of matrix elemets, i.e.,\n \\f[\n((\\rho_1, \\rho_2))_{HS} = \\sum\\limits_i \\sum\\limits_j (\\rho_1)_{ij}^* (\\rho_2)_{ij}\n \\f]\n Assuming that both density matrices are Hermitian,\n the resulting scalar product is real and invariant under\n reordering its arguments as\n \\f[\n((\\rho_1, \\rho_2))_{HS} = ((\\rho_2, \\rho_1))_{HS} = \\text{Tr}[\\rho_1 \\rho_2]\n \\f]\n If both \\p rho1 and \\p rho2 are density matrices of pure states\n \\p bra and \\p ket, then the equality holds\n \\f[\n((\\rho_1, \\rho_2))_{HS} = |\\langle \\text{bra} | \\text{ket} \\rangle|^2.\n \\f]\n If either or both of \\p rho1 and \\p rho2 are non Hermitian (i.e. invalid density\n matrices), then this function returns the real component of the scalar product,\n and discards the imaginary component. That is, it returns\n \\f[\n\\text{Re}\\{ \\text{Tr}[ \\rho_1^\\dagger \\rho_2 ] \\} = \\text{Re}\\{ \\text{Tr}[ \\rho_2^\\dagger \\rho_1 ] \\}.\n \\f]\n This is still sometimes useful, e.g. in calculating the inner product with an\n anti-commutator, e.g. (for Hermitian \\f$ \\sigma \\f$, \\f$ \\rho \\f$, \\f$ H \\f$)\n \\f[\n ((\\sigma, H \\rho + \\rho H))_{HS} = 2 \\; \\text{Re} \\{ ((\\sigma, H \\rho))_{HS} \\}\n \\f]\n where \\f$ H \\rho \\f$ could be a weighted sum of Pauli products applied to \\f$ \\rho \\f$\n through applyPauliSum().\n\n @see\n - calcInnerProduct()\n - calcHilbertSchmidtDistance()\n\n @ingroup calc\n @param[in] rho1 qureg as a density matrix (to have its values conjugate transposed)\n @param[in] rho2 qureg as a density matrix\n @returns the real Hilbert-Schmidt scalar product of density matrices\n\\p rho1 and \\p rho2 (assuming Hermiticity)\n @throws invalidQuESTInputError()\n - if \\p rho1 and \\p rho2 are not both density matrices\n - if \\p rho1 and \\p rho2 have mismatching dimensions\n @author Balint Koczor (CPU)\n @author Tyson Jones (GPU)"]
931 pub fn calcDensityInnerProduct(rho1: Qureg, rho2: Qureg) -> f64;
932}
933extern "C" {
934 #[doc = " Seeds the random number generator with a custom array of key(s), overriding the\n default keys.\n\n This determines the sequence of outcomes in functions like measure() and measureWithStats().\n\n In distributed mode, the key(s) passed to the master node will be broadcast to all\n other nodes, such that every node generates the same sequence of pseudorandom numbers.\n\n This function will copy the contents of \\p seedArray into a permanent array\n `env.seeds`, so \\p seedArray is afterward safe to free.\n\n > QuEST uses the\n > <a href=\"http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/emt19937ar.html\">Mersenne Twister</a>\n > for random number generation.\n\n @see\n - Use seedQuESTDefault() to seed via the current timestamp and process id.\n - Use getQuESTSeeds() to obtain the seeds currently being used for RNG.\n\n @ingroup debug\n @param[in] env a pointer to the ::QuESTEnv runtime environment\n @param[in] seedArray Array of integers to use as seed.\n This allows the MT to be initialised with more than a 32-bit integer if required\n @param[in] numSeeds Length of seedArray\n @author Ania Brown\n @author Tyson Jones (doc)"]
935 pub fn seedQuEST(
936 env: *mut QuESTEnv,
937 seedArray: *mut ::std::os::raw::c_ulong,
938 numSeeds: ::std::os::raw::c_int,
939 );
940}
941extern "C" {
942 #[doc = " Obtain the seeds presently used in random number generation.\n\n This function sets argument \\p seeds to the address of the array of keys\n which have seeded QuEST's\n <a href=\"http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/emt19937ar.html\">Mersenne Twister</a>\n random number generator. \\p numSeeds is set to the length of \\p seeds.\n These are the seeds which inform the outcomes of random functions like\n measure(), and are set using seedQuEST() and seedQuESTDefault().\n\n > The output \\p seeds array <b>must not</b> be freed, and should not be modified.\n\n Obtaining QuEST's seeds is useful for seeding your own random number generators,\n so that a simulation (with random QuEST measurements, and your own random decisions)\n can be precisely repeated later, just by calling seedQuEST().\n\n Note this function merely sets the arguments to the attributes for \\p env.\n I.e.\n ```\n unsigned long int* seeds;\n int numSeeds;\n getQuESTSeeds(env, &seeds, &numSeeds);\n\n func(seeds, numSeeds);\n ```\n is equivalent to\n ```\n func(env.seeds, env.numSeeds);\n ```\n However, one should not rely upon their local pointer from getQuESTSeeds() to be\n automatically updated after a subsequent call to seedQuEST() or seedQuESTDefault().\n Instead, getQuESTSeeds() should be recalled.\n\n @see\n - seedQuEST()\n - seedQuESTDefault()\n\n @ingroup debug\n @param[in] env the ::QuESTEnv runtime environment\n @param[in] seeds a pointer to an unitialised array to be modified\n @param[in] numSeeds a pointer to an integer to be modified\n @author Tyson Jones"]
943 pub fn getQuESTSeeds(
944 env: QuESTEnv,
945 seeds: *mut *mut ::std::os::raw::c_ulong,
946 numSeeds: *mut ::std::os::raw::c_int,
947 );
948}
949extern "C" {
950 #[doc = " Mixes a density matrix \\p qureg to induce single-qubit dephasing noise.\n With probability \\p prob, applies Pauli Z to \\p targetQubit.\n\n This transforms \\p qureg = \\f$\\rho\\f$ into the mixed state\n \\f[\n (1 - \\text{prob}) \\, \\rho + \\text{prob} \\; Z_q \\, \\rho \\, Z_q\n \\f]\n where q = \\p targetQubit.\n \\p prob cannot exceed 1/2, which maximally mixes \\p targetQubit.\n\n @see\n - mixTwoQubitDephasing()\n - mixDamping()\n - mixDepolarising()\n - mixKrausMap()\n - mixPauli()\n - mixDensityMatrix()\n\n @ingroup decoherence\n @param[in,out] qureg a density matrix\n @param[in] targetQubit qubit upon which to induce dephasing noise\n @param[in] prob the probability of the phase error occuring\n @throws invalidQuESTInputError()\n - if \\p qureg is not a density matrix\n - if \\p targetQubit is outside [0, \\p qureg.numQubitsRepresented)\n - if \\p prob is not in [0, 1/2]\n @author Tyson Jones (GPU, doc)\n @author Ania Brown (CPU, distributed)"]
951 pub fn mixDephasing(qureg: Qureg, targetQubit: ::std::os::raw::c_int, prob: f64);
952}
953extern "C" {
954 #[doc = " Mixes a density matrix \\p qureg to induce two-qubit dephasing noise.\n With probability \\p prob, applies Pauli Z to either or both qubits.\n\n This transforms \\p qureg = \\f$\\rho\\f$ into the mixed state\n \\f[\n (1 - \\text{prob}) \\, \\rho + \\frac{\\text{prob}}{3} \\; \\left(\n Z_a \\, \\rho \\, Z_a +\n Z_b \\, \\rho \\, Z_b +\n Z_a Z_b \\, \\rho \\, Z_a Z_b\n \\right)\n \\f]\n where a = \\p qubit1, b = \\p qubit2.\n \\p prob cannot exceed 3/4, at which maximal mixing occurs.\n\n @see\n - mixDephasing()\n\n @ingroup decoherence\n @param[in,out] qureg a density matrix\n @param[in] qubit1 qubit upon which to induce dephasing noise\n @param[in] qubit2 qubit upon which to induce dephasing noise\n @param[in] prob the probability of the phase error occuring\n @throws invalidQuESTInputError()\n - if \\p qureg is not a density matrix\n - if either \\p qubit1 or \\p qubit2 is outside [0, \\p qureg.numQubitsRepresented)\n - if \\p qubit1 = \\p qubit2\n - if \\p prob is not in [0, 3/4]\n @author Tyson Jones (GPU, doc)\n @author Ania Brown (CPU, distributed)"]
955 pub fn mixTwoQubitDephasing(
956 qureg: Qureg,
957 qubit1: ::std::os::raw::c_int,
958 qubit2: ::std::os::raw::c_int,
959 prob: f64,
960 );
961}
962extern "C" {
963 #[doc = " Mixes a density matrix \\p qureg to induce single-qubit homogeneous depolarising noise.\n This is equivalent to, with probability \\p prob, uniformly randomly applying\n either Pauli X, Y, or Z to \\p targetQubit.\n\n This transforms \\p qureg = \\f$\\rho\\f$ into the mixed state\n \\f[\n (1 - \\text{prob}) \\, \\rho + \\frac{\\text{prob}}{3} \\; \\left(\n X_q \\, \\rho \\, X_q +\n Y_q \\, \\rho \\, Y_q +\n Z_q \\, \\rho \\, Z_q\n \\right)\n \\f]\n where q = \\p targetQubit.\n \\p prob cannot exceed 3/4, at which maximal mixing occurs.\n The produced state is equivalently expressed as\n \\f[\n \\left( 1 - \\frac{4}{3} \\text{prob} \\right) \\rho +\n \\left( \\frac{4}{3} \\text{prob} \\right) \\frac{\\vec{\\bf{1}}}{2}\n \\f]\n where \\f$ \\frac{\\vec{\\bf{1}}}{2} \\f$ is the maximally mixed state of the target\n qubit.\n\n @see\n - mixTwoQubitDepolarising()\n - mixDephasing()\n - mixDamping()\n - mixKrausMap()\n - mixPauli()\n - mixDensityMatrix()\n\n @ingroup decoherence\n @param[in,out] qureg a density matrix\n @param[in] targetQubit qubit upon which to induce depolarising noise\n @param[in] prob the probability of the depolarising error occuring\n @throws invalidQuESTInputError()\n - if \\p qureg is not a density matrix\n - if \\p targetQubit is outside [0, \\p qureg.numQubitsRepresented)\n - if \\p prob is not in [0, 3/4]\n @author Tyson Jones (GPU, doc)\n @author Ania Brown (CPU, distributed)"]
964 pub fn mixDepolarising(qureg: Qureg, targetQubit: ::std::os::raw::c_int, prob: f64);
965}
966extern "C" {
967 #[doc = " Mixes a density matrix \\p qureg to induce single-qubit amplitude damping (decay to 0 state).\n With probability \\p prob, applies damping (transition from 1 to 0 state).\n\n This transforms \\p qureg = \\f$\\rho\\f$ into the mixed state\n \\f[\nK_0 \\rho K_0^\\dagger + K_1 \\rho K_1^\\dagger\n \\f]\n where q = \\p targetQubit and \\f$K_0\\f$ and \\f$K_1\\f$ are Kraus operators\n \\f[\nK_0 = \\begin{pmatrix} 1 & 0 \\\\ 0 & \\sqrt{1-\\text{prob}} \\end{pmatrix}, \\;\\;\nK_1 = \\begin{pmatrix} 0 & \\sqrt{\\text{prob}} \\\\ 0 & 0 \\end{pmatrix}.\n \\f]\n \\p prob cannot exceed 1, at which total damping/decay occurs. Note that unlike\n mixDephasing() and mixDepolarising(), this function can increase the purity of a\n mixed state (by, as \\p prob becomes 1, gaining certainty that the qubit is in\n the 0 state).\n\n @see\n - mixDephasing()\n - mixDepolarising()\n - mixKrausMap()\n - mixPauli()\n - mixDensityMatrix()\n\n @ingroup decoherence\n @param[in,out] qureg a density matrix\n @param[in] targetQubit qubit upon which to induce amplitude damping\n @param[in] prob the probability of the damping\n @throws invalidQuESTInputError()\n - if \\p qureg is not a density matrix\n - if \\p targetQubit is outside [0, \\p qureg.numQubitsRepresented)\n - if \\p prob is not in [0, 1]\n @author Nicolas Vogt of HQS (local CPU)\n @author Ania Brown (GPU, patched local CPU)\n @author Tyson Jones (distributed, doc)"]
968 pub fn mixDamping(qureg: Qureg, targetQubit: ::std::os::raw::c_int, prob: f64);
969}
970extern "C" {
971 #[doc = " Mixes a density matrix \\p qureg to induce two-qubit homogeneous depolarising noise.\n With probability \\p prob, applies to \\p qubit1 and \\p qubit2 any operator of the set\n \\f$\\{ IX, IY, IZ, XI, YI, ZI, XX, XY, XZ, YX, YY, YZ, ZX, ZY, ZZ \\}\\f$.\n Note this is the set of all two-qubit Pauli gates excluding \\f$II\\f$.\n\n This transforms \\p qureg = \\f$\\rho\\f$ into the mixed state\n \\f[\n (1 - \\text{prob}) \\, \\rho \\; + \\; \\frac{\\text{prob}}{15} \\; \\left(\n \\sum \\limits_{\\sigma_a \\in \\{X_a,Y_a,Z_a,I_a\\}}\n \\sum \\limits_{\\sigma_b \\in \\{X_b,Y_b,Z_b,I_b\\}}\n \\sigma_a \\sigma_b \\; \\rho \\; \\sigma_a \\sigma_b\n \\right)\n - \\frac{\\text{prob}}{15} I_a I_b \\; \\rho \\; I_a I_b\n \\f]\n or verbosely\n \\f[\n (1 - \\text{prob}) \\, \\rho + \\frac{\\text{prob}}{15} \\; \\left(\n \\begin{aligned}\n &X_a \\, \\rho \\, X_a +\n X_b \\, \\rho \\, X_b +\n Y_a \\, \\rho \\, Y_a +\n Y_b \\, \\rho \\, Y_b +\n Z_a \\, \\rho \\, Z_a +\n Z_b \\, \\rho \\, Z_b\n \\\\\n + &X_a X_b \\, \\rho \\, X_a X_b +\n X_a Y_b \\, \\rho \\, X_a Y_b +\n X_a Z_b \\, \\rho \\, X_a Z_b +\n Y_a X_b \\, \\rho \\, Y_a X_b\n \\\\\n + &Y_a Y_b \\, \\rho \\, Y_a Y_b +\n Y_a Z_b \\, \\rho \\, Y_a Z_b +\n Z_a X_b \\, \\rho \\, Z_a X_b +\n Z_a Y_b \\, \\rho \\, Z_a Y_b +\n Z_a Z_b \\, \\rho \\, Z_a Z_b\n \\end{aligned}\n \\right)\n \\f]\n where a = \\p qubit1, b = \\p qubit2.\n\n \\p prob cannot exceed 15/16, at which maximal mixing occurs.\n\n The produced state is equivalently expressed as\n \\f[\n \\left( 1 - \\frac{16}{15} \\text{prob} \\right) \\rho + \\left( \\frac{16}{15} \\text{prob} \\right) \\frac{\\vec{\\bf{1}}}{2}\n \\f]\n where \\f$ \\frac{\\vec{\\bf{1}}}{2} \\f$ is the maximally mixed state of the two\n target qubits.\n\n @see\n - mixDepolarising()\n\n @ingroup decoherence\n @param[in,out] qureg a density matrix\n @param[in] qubit1 qubit upon which to induce depolarising noise\n @param[in] qubit2 qubit upon which to induce depolarising noise\n @param[in] prob the probability of the depolarising error occuring\n @throws invalidQuESTInputError()\n - if \\p qureg is not a density matrix\n - if either \\p qubit1 or \\p qubit2 is outside [0, \\p qureg.numQubitsRepresented)\n - if \\p qubit1 = \\p qubit2\n - if \\p prob is not in [0, 15/16]\n @author Tyson Jones (GPU, doc)\n @author Ania Brown (CPU, distributed)"]
972 pub fn mixTwoQubitDepolarising(
973 qureg: Qureg,
974 qubit1: ::std::os::raw::c_int,
975 qubit2: ::std::os::raw::c_int,
976 prob: f64,
977 );
978}
979extern "C" {
980 #[doc = " Mixes a density matrix \\p qureg to induce general single-qubit Pauli noise.\n With probabilities \\p probX, \\p probY and \\p probZ, applies Pauli X, Y, and Z\n respectively to \\p targetQubit.\n\n This transforms \\p qureg = \\f$\\rho\\f$ into the mixed state\n \\f[\n (1 - \\text{probX} - \\text{probY} - \\text{probZ}) \\, \\rho + \\;\\;\\;\n (\\text{probX})\\; X_q \\, \\rho \\, X_q + \\;\\;\\;\n (\\text{probY})\\; Y_q \\, \\rho \\, Y_q + \\;\\;\\;\n (\\text{probZ})\\; Z_q \\, \\rho \\, Z_q\n \\f]\n where q = \\p targetQubit.\n Each of \\p probX, \\p probY and \\p probZ cannot exceed the chance of no error:\n 1 - \\p probX - \\p probY - \\p probZ\n\n This function operates by first converting the given Pauli probabilities into\n a single-qubit Kraus map (four 2x2 operators).\n\n @see\n - mixDephasing()\n - mixDepolarising()\n - mixDamping()\n - mixKrausMap()\n - mixDensityMatrix()\n\n @ingroup decoherence\n @param[in,out] qureg a density matrix\n @param[in] targetQubit qubit to decohere\n @param[in] probX the probability of inducing an X error\n @param[in] probY the probability of inducing an Y error\n @param[in] probZ the probability of inducing an Z error\n @throws invalidQuESTInputError()\n - if \\p qureg is not a density matrix\n - if \\p targetQubit is outside [0, \\p qureg.numQubitsRepresented)\n - if any of \\p probX, \\p probY or \\p probZ are not in [0, 1]\n - if any of p in {\\p probX, \\p probY or \\p probZ} don't satisfy p <= (1 - \\p probX - \\p probY - \\p probZ)\n @author Balint Koczor\n @author Tyson Jones (refactored, doc)"]
981 pub fn mixPauli(
982 qureg: Qureg,
983 targetQubit: ::std::os::raw::c_int,
984 probX: f64,
985 probY: f64,
986 probZ: f64,
987 );
988}
989extern "C" {
990 #[doc = " Modifies combineQureg to become (1-\\p prob)\\p combineProb + \\p prob \\p otherQureg.\n Both registers must be equal-dimension density matrices, and prob must be in [0, 1].\n\n @see\n - mixDephasing()\n - mixDepolarising()\n - mixDamping()\n - mixKrausMap()\n - mixPauli()\n\n @ingroup decoherence\n @param[in,out] combineQureg a density matrix to be modified\n @param[in] prob the probability of \\p otherQureg in the modified \\p combineQureg\n @param[in] otherQureg a density matrix to be mixed into \\p combineQureg\n @throws invalidQuESTInputError()\n - if either \\p combineQureg or \\p otherQureg are not density matrices\n - if the dimensions of \\p combineQureg and \\p otherQureg do not match\n - if \\p prob is not in [0, 1]\n @author Tyson Jones"]
991 pub fn mixDensityMatrix(combineQureg: Qureg, prob: f64, otherQureg: Qureg);
992}
993extern "C" {
994 #[doc = " Calculates the purity of a density matrix, by the trace of the density matrix squared.\n Returns \\f$\\text{Tr}(\\rho^2)\\f$.\n For a pure state, this =1.\n For a mixed state, the purity is less than 1 and is lower bounded by 1/2^n, where\n n is the number of qubits. The minimum purity is achieved for the maximally mixed state identity/2^n.\n\n This function does not accept state-vectors, which clearly have purity 1.\n\n Note this function will give incorrect results for non-Hermitian Quregs (i.e.\n invalid density matrices), which will disagree with \\f$\\text{Tr}(\\rho^2)\\f$.\n Instead, this function returns \\f$\\sum_{ij} |\\rho_{ij}|^2 \\f$.\n\n @see\n - calcFidelity()\n - calcHilbertSchmidtDistance()\n - calcTotalProb()\n\n @ingroup calc\n @param[in] qureg a density matrix of which to measure the purity\n @return the purity\n @throws invalidQuESTInputError()\n - if either \\p combineQureg or \\p otherQureg are not density matrices\n - if the dimensions of \\p combineQureg and \\p otherQureg do not match\n - if \\p prob is not in [0, 1]\n @author Tyson Jones"]
995 pub fn calcPurity(qureg: Qureg) -> f64;
996}
997extern "C" {
998 #[doc = " Calculates the fidelity of \\p qureg (a state-vector or density matrix) against\n a reference pure state (necessarily a state-vector).\n If \\p qureg is a state-vector, this function computes\n \\f[\n|\\langle \\text{qureg} | \\text{pureState} \\rangle|^2\n \\f]\n If \\p qureg is a density matrix, this function computes\n \\f[\n\\langle \\text{pureState} | \\text{qureg} | \\text{pureState} \\rangle\n \\f]\n In either case, the returned fidelity lies in [0, 1] (assuming both input\n states have valid normalisation). If any of the input \\p Quregs are not\n normalised, this function will return the real component of the correct\n linear algebra calculation.\n\n The number of qubits represented in \\p qureg and \\p pureState must match.\n\n > In the GPU-accelerated cuQuantum backend, this function further assumes that\n > the density matrix \\p qureg is correctly normalised, and otherwise returns the\n > fidelity of the conjugate-transpose of \\p qureg.\n\n @see\n - calcHilbertSchmidtDistance()\n - calcPurity()\n\n @ingroup calc\n @param[in] qureg a density matrix or state vector\n @param[in] pureState a state vector\n @return the fidelity between the input registers\n @throws invalidQuESTInputError()\n - if the second argument (\\p pureState) is not a state-vector\n - if the number of qubits in \\p qureg and \\p pureState do not match\n @author Tyson Jones"]
999 pub fn calcFidelity(qureg: Qureg, pureState: Qureg) -> f64;
1000}
1001extern "C" {
1002 #[doc = " Performs a SWAP gate between \\p qubit1 and \\p qubit2.\n This effects\n \\f[\n \\begin{pmatrix}\n 1 \\\\\n & & 1 \\\\\\\n & 1 \\\\\n & & & 1\n \\end{pmatrix}\n \\f]\n on the designated qubits, though is performed internally by three CNOT gates.\n\n@htmlonly\n<center>\n<script type=\"text/tikz\">\n\\begin{tikzpicture}[scale=.5]\n\\node[draw=none] at (-3.5, 2) {qubit1};\n\\node[draw=none] at (-3.5, 0) {qubit2};\n\n\\draw (-2, 2) -- (2, 2);\n\\draw (0, 2) -- (0, 0);\n\\draw (-2,0) -- (2, 0);\n\n\\draw (-.35,-.35) -- (.35,.35);\n\\draw (-.35,.35) -- (.35,-.35);\n\n\\draw (-.35,-.35 + 2) -- (.35,.35 + 2);\n\\draw (-.35,.35 + 2) -- (.35,-.35 + 2);\n\n\\end{tikzpicture}\n</script>\n</center>\n@endhtmlonly\n\n @see\n - sqrtSwapGate()\n\n @ingroup unitary\n @param[in,out] qureg object representing the set of all qubits\n @param[in] qubit1 qubit to swap\n @param[in] qubit2 other qubit to swap\n @throws invalidQuESTInputError()\n - if either \\p qubit1 or \\p qubit2 are outside [0, \\p qureg.numQubitsRepresented)\n - if \\p qubit1 and \\p qubit2 are equal\n @author Tyson Jones"]
1003 pub fn swapGate(qureg: Qureg, qubit1: ::std::os::raw::c_int, qubit2: ::std::os::raw::c_int);
1004}
1005extern "C" {
1006 #[doc = " Apply a multi-controlled multi-target Z rotation, also known as a controlled phase gadget.\n This is the unitary\n \\f[\n |1\\rangle\\langle 1|^{\\otimes\\, \\text{numControls}} \\; \\otimes \\,\n \\exp \\left( - i \\, \\frac{\\theta}{2} \\; \\bigotimes_{j}^{\\text{numTargets}} Z_j\\right)\n \\;\\;+\\;\\; \\sum\\limits_{k=0}^{2^{\\,\\text{numControls}} - 2} |k\\rangle\\langle k| \\otimes \\text{I}\n \\f]\n where the Pauli Z gates operate upon the qubits in `targetQubits`, and cause\n rotations of \\f$\\theta =\\f$ \\p angle.\n\n@htmlonly\n<center>\n<script type=\"text/tikz\">\n\\begin{tikzpicture}[scale=.5]\n\\node[draw=none] at (-4, 1) {targets};\n\\node[draw=none] at (-4, 5) {controls};\n\n\\node[draw=none] at (0, 8) {$\\vdots$};\n\\draw (0, 7) -- (0, 6);\n\n\\draw (-2.5, 6) -- (2.5, 6);\n\\draw[fill=black] (0, 6) circle (.2);\n\\draw (0, 6) -- (0, 4);\n\n\\draw (-2.5, 4) -- (2.5, 4);\n\\draw[fill=black] (0, 4) circle (.2);\n\\draw(0, 4) -- (0, 3);\n\n\\draw (-2.5,0) -- (-1.5, 0);\n\\draw (1.5, 0) -- (2.5, 0);\n\\draw (-2.5,2) -- (-1.5, 2);\n\\draw (1.5, 2) -- (2.5, 2);\n\\draw (-1.5,-1)--(-1.5,3)--(1.5,3)--(1.5,-1);\n\\node[draw=none] at (0, -1) {$\\vdots$};\n\n% below is broken in Tikzjax rendering...\n% \\node[draw=none] at (0, 1) {$e^{-i\\frac{\\theta}{2}Z^{\\otimes}}$};\n% so we sadly replace it with:\n\\node[draw=none] at (0, 1) {$\\exp(\\dots)$};\n\n\\end{tikzpicture}\n</script>\n</center>\n@endhtmlonly\n\n > All qubits not appearing in \\p targetQubits and \\p controlQubits are assumed to receive the identity operator.\n\n This has the effect of premultiplying all amplitudes (for which the control qubits are `1`)\n with \\f$\\exp(\\pm i \\theta/2)\\f$, where the sign is determined by the parity of\n the target qubits for that amplitude.\n\n @see\n - multiControlledMultiRotatePauli()\n - multiRotatePauli()\n - multiRotateZ()\n - controlledRotateZ()\n - rotateZ()\n\n @ingroup unitary\n @param[in,out] qureg object representing the set of all qubits\n @param[in] controlQubits list of the indices of qubits to control upon\n @param[in] numControls length of length `controlQubits`\n @param[in] targetQubits a list of the indices of the target qubits\n @param[in] numTargets length of list `targetQubits`\n @param[in] angle the angle by which the multi-qubit state is rotated around the Z axis\n @throws invalidQuESTInputError()\n - if any qubit in \\p controlQubits and \\p targetQubits is invalid, i.e. outside <b>[0, </b>`qureg.numQubitsRepresented`<b>)</b>\n - if \\p controlQubits or \\p targetQubits contain any repetitions\n - if any qubit in \\p controlQubits is also in \\p targetQubits (and vice versa)\n - if \\p numTargets <b>< 1</b>\n - if \\p numControls <b>< 1</b> (use multiRotateZ() for no controls)\n @throws segmentation-fault\n - if \\p controlQubits contains fewer elements than \\p numControls\n - if \\p targetQubits contains fewer elements than \\p numTargets\n @author Tyson Jones"]
1007 pub fn multiControlledMultiRotateZ(
1008 qureg: Qureg,
1009 controlQubits: *mut ::std::os::raw::c_int,
1010 numControls: ::std::os::raw::c_int,
1011 targetQubits: *mut ::std::os::raw::c_int,
1012 numTargets: ::std::os::raw::c_int,
1013 angle: f64,
1014 );
1015}
1016extern "C" {
1017 #[doc = " Apply a multi-controlled multi-target multi-Pauli rotation, also known as a\n controlled Pauli gadget.\n This is the unitary\n \\f[\n |1\\rangle\\langle 1|^{\\otimes\\, \\text{numControls}} \\; \\otimes \\,\n \\exp \\left( - i \\, \\frac{\\theta}{2} \\; \\bigotimes_{j}^{\\text{numTargets}} \\hat{\\sigma}_j\\right)\n \\;\\;+\\;\\; \\sum\\limits_{k=0}^{2^{\\,\\text{numControls}} - 2} |k\\rangle\\langle k| \\otimes \\text{I}\n \\f]\n where \\f$\\hat{\\sigma}_j\\f$ are the Pauli operators (::pauliOpType) in `targetPaulis`, which operate\n upon the corresponding qubits in `targetQubits`.\n\n@htmlonly\n<center>\n<script type=\"text/tikz\">\n\\begin{tikzpicture}[scale=.5]\n\\node[draw=none] at (-4, 1) {targets};\n\\node[draw=none] at (-4, 5) {controls};\n\n\\node[draw=none] at (0, 8) {$\\vdots$};\n\\draw (0, 7) -- (0, 6);\n\n\\draw (-2.5, 6) -- (2.5, 6);\n\\draw[fill=black] (0, 6) circle (.2);\n\\draw (0, 6) -- (0, 4);\n\n\\draw (-2.5, 4) -- (2.5, 4);\n\\draw[fill=black] (0, 4) circle (.2);\n\\draw(0, 4) -- (0, 3);\n\n\\draw (-2.5,0) -- (-1.5, 0);\n\\draw (1.5, 0) -- (2.5, 0);\n\\draw (-2.5,2) -- (-1.5, 2);\n\\draw (1.5, 2) -- (2.5, 2);\n\\draw (-1.5,-1)--(-1.5,3)--(1.5,3)--(1.5,-1);\n\n\\node[draw=none] at (0, -1) {$\\vdots$};\n\n% below is broken in Tikzjax rendering\n% \\node[draw=none] at (0, 1) {$e^{-i\\frac{\\theta}{2} \\bigotimes\\limits_j \\hat{\\sigma}_j}$};\n% so we sadly replace it with:\n\\node[draw=none] at (0, 1) {$\\exp(\\dots)$};\n\n\\end{tikzpicture}\n</script>\n</center>\n@endhtmlonly\n\n > All qubits not appearing in \\p targetQubits and \\p controlQubits are assumed to receive the identity operator.\n\n For example:\n ```\n int numCtrls = 1;\n int numTargs = 4;\n int ctrls[] = {4};\n int targs[] = {0,1,2,3};\n\n pauliOpType paulis[] = {PAULI_X, PAULI_Y, PAULI_Z, PAULI_I};\n\n multiControlledMultiRotatePauli(\n qureg, ctrls, numCtrls, targs, paulis, numTargs, 0.1);\n ```\n effects\n \\f[\n |1\\rangle\\langle 1 | \\otimes \\exp\\left( -i \\, (0.1/2) \\, X_0 \\, Y_1 \\, Z_2 \\right) \\, \\text{I}_3\n \\;\\; + \\;\\; |0\\rangle\\langle 0| \\otimes \\text{I}^{\\otimes 4}\n \\f]\n on \\p qureg, where unspecified qubits (along with those targeted by `PAULI_I`) are\n assumed to receive the identity operator (excluded from exponentiation).\n\n > This means specifying `PAULI_I` does *not* induce a global phase factor \\f$\\exp(-i \\theta/2)\\f$.\n > Hence, if all \\p targetPaulis are identity, then this function does nothing to \\p qureg.\n > Specifying `PAULI_I` on a qubit is superfluous but allowed for convenience.\n\n This function effects the controlled Pauli gadget by first (controlled)\n rotating the qubits which are targeted with either `X` or `Y` into alternate basis,\n performing multiControlledMultiRotateZ() on all target qubits, then restoring\n the original basis.\n\n @see\n - multiControlledMultiRotateZ()\n - multiRotatePauli()\n - multiRotateZ()\n - rotateX()\n - rotateY()\n - rotateZ()\n - rotateAroundAxis()\n\n @ingroup unitary\n @param[in,out] qureg object representing the set of all qubits\n @param[in] controlQubits list of the indices of qubits to control upon\n @param[in] numControls length of length `controlQubits`\n @param[in] targetQubits a list of the indices of the target qubits\n @param[in] targetPaulis a list of the Pauli operators around which to rotate the target qubits\n @param[in] numTargets length of list `targetQubits`\n @param[in] angle the angle by which the multi-qubit state is rotated around the Z axis\n @throws invalidQuESTInputError()\n - if any qubit in \\p controlQubits and \\p targetQubits is invalid, i.e. outside <b>[0, </b>`qureg.numQubitsRepresented`<b>)</b>\n - if \\p controlQubits or \\p targetQubits contain any repetitions\n - if any qubit in \\p controlQubits is also in \\p targetQubits (and vice versa)\n - if \\p numTargets <b>< 1</b>\n - if \\p numControls <b>< 1</b> (use multiRotateZ() for no controls)\n - if any element of \\p targetPaulis is not one of `PAULI_I`, `PAULI_X`, `PAULI_Y`, `PAULI_Z`\n @throws segmentation-fault\n - if \\p controlQubits contains fewer elements than \\p numControls\n - if \\p targetQubits contains fewer elements than \\p numTargets\n - if \\p targetPaulis contains fewer elements than \\p numTargets\n @author Tyson Jones"]
1018 pub fn multiControlledMultiRotatePauli(
1019 qureg: Qureg,
1020 controlQubits: *mut ::std::os::raw::c_int,
1021 numControls: ::std::os::raw::c_int,
1022 targetQubits: *mut ::std::os::raw::c_int,
1023 targetPaulis: *mut pauliOpType,
1024 numTargets: ::std::os::raw::c_int,
1025 angle: f64,
1026 );
1027}
1028extern "C" {
1029 #[doc = " Computes the expected value of a product of Pauli operators.\n Letting \\f$ \\sigma = \\otimes_j \\hat{\\sigma}_j \\f$ be the operators indicated by \\p pauliCodes\n and acting on qubits \\p targetQubits, this function computes \\f$ \\langle \\psi | \\sigma | \\psi \\rangle \\f$\n if \\p qureg = \\f$ \\psi \\f$ is a state-vector, and computes \\f$ \\text{Trace}(\\sigma \\rho) \\f$\n if \\p qureg = \\f$ \\rho \\f$ is a density matrix.\n\n \\p pauliCodes is an array of length \\p numTargets which specifies which Pauli operators to\n enact on the corresponding qubits in \\p targetQubits, where 0 = \\p PAULI_I, 1 = \\p PAULI_X,\n 2 = \\p PAULI_Y, 3 = \\p PAULI_Z. The target qubits must be unique, and at most \\p qureg.numQubitsRepresented\n may be specified. For example, on a 7-qubit state-vector,\n ```\n calcExpecPauliProd(qureg, {4,5,6}, {PAULI_X, PAULI_I, PAULI_Z}, 3, workspace);\n ```\n will compute \\f$ \\langle \\psi | I I I I X I Z | \\psi \\rangle \\f$ (where in this notation, the left-most operator\n applies to the least-significant qubit, i.e. that with index 0).\n\n \\p workspace must be a register with the same type (state-vector vs density matrix) and dimensions\n (number of represented qubits) as \\p qureg, and is used as working space. When this function returns, \\p qureg\n will be unchanged and \\p workspace will be set to \\f$ \\sigma | \\psi \\rangle \\f$ (if \\p qureg is a state-vector)\n or \\f$ \\sigma \\rho \\f$ (if \\p qureg is a density matrix). NOTE that this last quantity is NOT the result of applying\n the paulis as unitaries, \\f$ \\sigma^\\dagger \\rho \\sigma \\f$, but is instead the result of their direct\n multiplication with the density matrix. It is therefore itself not a valid density matrix.\n\n This function works by cloning the \\p qureg state into \\p workspace, applying the specified\n Pauli operators to \\p workspace then computing its inner product with \\p qureg (for state-vectors)\n or its trace (for density matrices). It therefore should scale linearly in time with the number of\n specified non-identity Pauli operators, which is bounded by the number of represented qubits.\n\n @see\n - calcExpecDiagonalOp()\n - calcExpecPauliSum()\n - calcExpecPauliHamil()\n\n @ingroup calc\n @param[in] qureg the register of which to find the expected value, which is unchanged by this function\n @param[in] targetQubits a list of the indices of the target qubits\n @param[in] pauliCodes a list of the Pauli codes (0=PAULI_I, 1=PAULI_X, 2=PAULI_Y, 3=PAULI_Z)\n to apply to the corresponding qubits in \\p targetQubits\n @param[in] numTargets number of target qubits, i.e. the length of \\p targetQubits and \\p pauliCodes\n @param[in,out] workspace a working-space qureg with the same dimensions as \\p qureg, which is modified\n to be the result of multiplying the state with the pauli operators\n @throws invalidQuESTInputError()\n - if \\p numTargets is outside [1, \\p qureg.numQubitsRepresented])\n - if any qubit in \\p targetQubits is outside [0, \\p qureg.numQubitsRepresented))\n - if any qubit in \\p targetQubits is repeated\n - if any code in \\p pauliCodes is not in {0,1,2,3}\n - if \\p workspace is not of the same type and dimensions as \\p qureg\n @author Tyson Jones"]
1030 pub fn calcExpecPauliProd(
1031 qureg: Qureg,
1032 targetQubits: *mut ::std::os::raw::c_int,
1033 pauliCodes: *mut pauliOpType,
1034 numTargets: ::std::os::raw::c_int,
1035 workspace: Qureg,
1036 ) -> f64;
1037}
1038extern "C" {
1039 #[doc = " Computes the expected value of a sum of products of Pauli operators.\n Let \\f$ H = \\sum_i c_i \\otimes_j^{N} \\hat{\\sigma}_{i,j} \\f$ be\n the operators indicated by \\p allPauliCodes (where \\f$ c_i \\in \\f$ \\p termCoeffs\n and \\f$ N = \\f$ \\p qureg.numQubitsRepresented).\n This function computes \\f$ \\langle \\psi | H | \\psi \\rangle \\f$\n if \\p qureg = \\f$ \\psi \\f$ is a state-vector, and computes \\f$ \\text{Trace}(H \\rho) =\\text{Trace}(\\rho H) \\f$\n if \\p qureg = \\f$ \\rho \\f$ is a density matrix.\n\n \\p allPauliCodes is an array of length \\p numSumTerms*\\p qureg.numQubitsRepresented\n which specifies which Pauli operators to apply, where 0 = \\p PAULI_I, 1 = \\p PAULI_X,\n 2 = \\p PAULI_Y, 3 = \\p PAULI_Z. For each sum term, a Pauli operator must be specified for\n EVERY qubit in \\p qureg; each set of \\p numSumTerms operators will be grouped into a product.\n \\p termCoeffs is an arrray of length \\p numSumTerms containing the term coefficients.\n For example, on a 3-qubit state-vector,\n ```\n int paulis[6] = {PAULI_X, PAULI_I, PAULI_I, PAULI_X, PAULI_Y, PAULI_Z};\n qreal coeffs[2] = {1.5, -3.6};\n calcExpecPauliSum(qureg, paulis, coeffs, 2, workspace);\n ```\n will compute \\f$ \\langle \\psi | (1.5 X I I - 3.6 X Y Z) | \\psi \\rangle \\f$ (where in this notation, the left-most operator\n applies to the least-significant qubit, i.e. that with index 0).\n\n \\p workspace must be a register with the same type (state-vector vs density matrix) and dimensions\n (number of represented qubits) as \\p qureg, and is used as working space. When this function returns, \\p qureg\n will be unchanged and \\p workspace will be set to \\p qureg pre-multiplied with the final Pauli product.\n NOTE that if \\p qureg is a density matrix, \\p workspace will become \\f$ \\hat{\\sigma} \\rho \\f$\n which is itself not a density matrix (it is distinct from \\f$ \\hat{\\sigma} \\rho \\hat{\\sigma}^\\dagger \\f$).\n\n This function works by cloning the \\p qureg state into \\p workspace, applying each of the specified\n Pauli products to \\p workspace (one Pauli operation at a time), then computing its inner product with \\p qureg (for state-vectors)\n or its trace (for density matrices) multiplied with the corresponding coefficient, and summing these contributions.\n It therefore should scale linearly in time with the total number of non-identity specified Pauli operators.\n\n @see\n - calcExpecDiagonalOp()\n - calcExpecPauliProd()\n - calcExpecPauliHamil()\n\n @ingroup calc\n @param[in] qureg the register of which to find the expected value, which is unchanged by this function\n @param[in] allPauliCodes a list of the Pauli codes (0=PAULI_I, 1=PAULI_X, 2=PAULI_Y, 3=PAULI_Z)\n of all Paulis involved in the products of terms. A Pauli must be specified for each qubit\n in the register, in every term of the sum.\n @param[in] termCoeffs The coefficients of each term in the sum of Pauli products\n @param[in] numSumTerms The total number of Pauli products specified\n @param[in,out] workspace a working-space qureg with the same dimensions as \\p qureg, which is modified\n to be the result of multiplying the state with the final specified Pauli product\n @throws invalidQuESTInputError()\n - if any code in \\p allPauliCodes is not in {0,1,2,3}\n - if \\p numSumTerms <= 0,\n - if \\p workspace is not of the same type and dimensions as \\p qureg\n @author Tyson Jones"]
1040 pub fn calcExpecPauliSum(
1041 qureg: Qureg,
1042 allPauliCodes: *mut pauliOpType,
1043 termCoeffs: *mut f64,
1044 numSumTerms: ::std::os::raw::c_int,
1045 workspace: Qureg,
1046 ) -> f64;
1047}
1048extern "C" {
1049 #[doc = " Computes the expected value of \\p qureg under Hermitian operator \\p hamil.\n Represent \\p hamil as \\f$ H = \\sum_i c_i \\otimes_j^{N} \\hat{\\sigma}_{i,j} \\f$\n (where \\f$ c_i \\in \\f$ \\p hamil.termCoeffs and \\f$ N = \\f$ \\p hamil.numQubits).\n This function computes \\f$ \\langle \\psi | H | \\psi \\rangle \\f$\n if \\p qureg = \\f$ \\psi \\f$ is a state-vector, and computes \\f$ \\text{Trace}(H \\rho) =\\text{Trace}(\\rho H) \\f$\n if \\p qureg = \\f$ \\rho \\f$ is a density matrix.\n\n This function is merely an encapsulation of calcExpecPauliSum() - refer to the doc\n there for an elaboration.\n\n \\p workspace must be a register with the same type (state-vector vs density matrix) and dimensions\n (number of represented qubits) as \\p qureg and \\p hamil, and is used as working space.\n When this function returns, \\p qureg will be unchanged and \\p workspace will be set to\n \\p qureg pre-multiplied with the final Pauli product in \\p hamil.\n NOTE that if \\p qureg is a density matrix, \\p workspace will become \\f$ \\hat{\\sigma} \\rho \\f$\n which is itself not a density matrix (it is distinct from \\f$ \\hat{\\sigma} \\rho \\hat{\\sigma}^\\dagger \\f$).\n\n This function works by cloning the \\p qureg state into \\p workspace, applying each of the specified\n Pauli products in \\p hamil to \\p workspace (one Pauli operation at a time), then computing its inner product with \\p qureg (for state-vectors)\n or its trace (for density matrices) multiplied with the corresponding coefficient, and summing these contributions.\n It therefore should scale linearly in time with the total number of non-identity specified Pauli operators.\n\n @see\n - createPauliHamil()\n - calcExpecDiagonalOp()\n - calcExpecPauliSum()\n - calcExpecPauliProd()\n\n @ingroup calc\n @param[in] qureg the register of which to find the expected value, which is unchanged by this function\n @param[in] hamil a \\p PauliHamil created with createPauliHamil() or createPauliHamilFromFile()\n @param[in,out] workspace a working-space qureg with the same dimensions as \\p qureg, which is modified\n to be the result of multiplying the state with the final specified Pauli product\n @throws invalidQuESTInputError()\n - if any code in \\p hamil.pauliCodes is not a valid Pauli code\n - if \\p hamil.numSumTerms <= 0\n - if \\p workspace is not of the same type and dimensions as \\p qureg and \\p hamil\n @author Tyson Jones"]
1050 pub fn calcExpecPauliHamil(qureg: Qureg, hamil: PauliHamil, workspace: Qureg) -> f64;
1051}
1052extern "C" {
1053 #[doc = " Apply a general two-qubit unitary (including a global phase factor).\n\n@htmlonly\n<center>\n<script type=\"text/tikz\">\n\\begin{tikzpicture}[scale=.5]\n\\node[draw=none] at (-3.5, 0) {target2};\n\\node[draw=none] at (-3.5, 2) {target1};\n\n\\draw (-2,0) -- (-1, 0);\n\\draw (1, 0) -- (2, 0);\n\\draw (-2,2) -- (-1, 2);\n\\draw (1, 2) -- (2, 2);\n\\draw (-1,-1)--(-1,3)--(1,3)--(1,-1)--cycle;\n\\node[draw=none] at (0, 1) {U};\n\\end{tikzpicture}\n</script>\n</center>\n@endhtmlonly\n\n \\p targetQubit1 is treated as the \\p least significant qubit in \\p u, such that\n a row in \\p u is dotted with the vector\n \\f$ |\\text{targetQubit2} \\;\\; \\text{targetQubit1}\\rangle : \\{ |00\\rangle, |01\\rangle, |10\\rangle, |11\\rangle \\} \\f$\n\n For example,\n ```\n twoQubitUnitary(qureg, a, b, u);\n ```\n will invoke multiplication\n \\f[\n \\begin{pmatrix}\n u_{00} & u_{01} & u_{02} & u_{03} \\\\\n u_{10} & u_{11} & u_{12} & u_{13} \\\\\n u_{20} & u_{21} & u_{22} & u_{23} \\\\\n u_{30} & u_{31} & u_{32} & u_{33}\n \\end{pmatrix}\n \\begin{pmatrix}\n |ba\\rangle = |00\\rangle \\\\\n |ba\\rangle = |01\\rangle \\\\\n |ba\\rangle = |10\\rangle \\\\\n |ba\\rangle = |11\\rangle\n \\end{pmatrix}\n \\f]\n\n The passed ::ComplexMatrix4 must be unitary, otherwise an error is thrown.\n > Use applyMatrix4() to left-multiply a non-unitary ::ComplexMatrix4.\n\n Note that in distributed mode, this routine requires that each node contains at least 4 amplitudes.\n This means an q-qubit register (state vector or density matrix) can be distributed\n by at most 2^q/4 nodes.\n\n @see\n - ::ComplexMatrix4\n - controlledTwoQubitUnitary()\n - multiControlledTwoQubitUnitary()\n - multiQubitUnitary()\n - applyMatrix4()\n\n @ingroup unitary\n @param[in,out] qureg object representing the set of all qubits\n @param[in] targetQubit1 first qubit to operate on, treated as least significant in \\p u\n @param[in] targetQubit2 second qubit to operate on, treated as most significant in \\p u\n @param[in] u unitary matrix to apply\n @throws invalidQuESTInputError()\n - if \\p targetQubit1 or \\p targetQubit2 are outside [0, \\p qureg.numQubitsRepresented)\n - if \\p targetQubit1 equals \\p targetQubit2\n - if matrix \\p u is not unitary\n - if each node cannot fit 4 amplitudes in distributed mode\n @author Tyson Jones"]
1054 pub fn twoQubitUnitary(
1055 qureg: Qureg,
1056 targetQubit1: ::std::os::raw::c_int,
1057 targetQubit2: ::std::os::raw::c_int,
1058 u: ComplexMatrix4,
1059 );
1060}
1061extern "C" {
1062 #[doc = " Apply a general controlled two-qubit unitary (including a global phase factor).\n The given unitary is applied to the target amplitudes where the control qubit has value 1.\n This effects the many-qubit unitary\n \\f[\n \\begin{pmatrix}\n 1 \\\\\n & 1 \\\\\n & & 1 \\\\\n & & & 1 \\\\\n & & & & u_{00} & u_{01} & u_{02} & u_{03} \\\\\n & & & & u_{10} & u_{11} & u_{12} & u_{13} \\\\\n & & & & u_{20} & u_{21} & u_{22} & u_{23} \\\\\n & & & & u_{30} & u_{31} & u_{32} & u_{33}\n \\end{pmatrix}\n \\f]\n on the control and target qubits.\n\n \\p targetQubit1 is treated as the \\p least significant qubit in \\p u, such that\n a row in \\p u is dotted with the vector\n \\f$ |\\text{targetQubit2} \\;\\; \\text{targetQubit1}\\rangle : \\{ |00\\rangle, |01\\rangle, |10\\rangle, |11\\rangle \\} \\f$\n\n The passed 4x4 ComplexMatrix must be unitary, otherwise an error is thrown.\n\n@htmlonly\n<center>\n<script type=\"text/tikz\">\n\\begin{tikzpicture}[scale=.5]\n\\node[draw=none] at (-3.5, 0) {target1};\n\\node[draw=none] at (-3.5, 2) {target2};\n\\node[draw=none] at (-3.5, 4) {control};\n\n\\draw (-2, 4) -- (2, 4);\n\\draw[fill=black] (0, 4) circle (.2);\n\\draw(0, 4) -- (0, 3);\n\n\\draw (-2,0) -- (-1, 0);\n\\draw (1, 0) -- (2, 0);\n\\draw (-2,2) -- (-1, 2);\n\\draw (1, 2) -- (2, 2);\n\\draw (-1,-1)--(-1,3)--(1,3)--(1,-1)--cycle;\n\\node[draw=none] at (0, 1) {U};\n\\end{tikzpicture}\n</script>\n</center>\n@endhtmlonly\n\n Note that in distributed mode, this routine requires that each node contains at least 4 amplitudes.\n This means an q-qubit register (state vector or density matrix) can be distributed\n by at most 2^q/4 nodes.\n\n @see\n - ::ComplexMatrix4\n - multiControlledTwoQubitUnitary()\n - multiQubitUnitary()\n - unitary()\n\n @ingroup unitary\n @param[in,out] qureg object representing the set of all qubits\n @param[in] controlQubit the control qubit which must be in state 1 to effect the given unitary\n @param[in] targetQubit1 first qubit to operate on, treated as least significant in \\p u\n @param[in] targetQubit2 second qubit to operate on, treated as most significant in \\p u\n @param[in] u unitary matrix to apply\n @throws invalidQuESTInputError()\n - if \\p controlQubit, \\p targetQubit1 or \\p targetQubit2 are outside [0, \\p qureg.numQubitsRepresented)\n - if any of \\p controlQubit, \\p targetQubit1 and \\p targetQubit2 are equal\n - if matrix \\p u is not unitary\n - if each node cannot fit 4 amplitudes in distributed mode.\n @author Tyson Jones"]
1063 pub fn controlledTwoQubitUnitary(
1064 qureg: Qureg,
1065 controlQubit: ::std::os::raw::c_int,
1066 targetQubit1: ::std::os::raw::c_int,
1067 targetQubit2: ::std::os::raw::c_int,
1068 u: ComplexMatrix4,
1069 );
1070}
1071extern "C" {
1072 #[doc = " Apply a general multi-controlled two-qubit unitary (including a global phase factor).\n Any number of control qubits can be specified, and if all have value 1,\n the given unitary is applied to the target qubit.\n This effects the many-qubit unitary\n \\f[\n \\begin{pmatrix}\n 1 \\\\\n & 1 \\\\\\\n & & \\ddots \\\\\n & & & u_{00} & u_{01} & u_{02} & u_{03} \\\\\n & & & u_{10} & u_{11} & u_{12} & u_{13} \\\\\n & & & u_{20} & u_{21} & u_{22} & u_{23} \\\\\n & & & u_{30} & u_{31} & u_{32} & u_{33}\n \\end{pmatrix}\n \\f]\n on the control and target qubits.\n\n \\p targetQubit1 is treated as the \\p least significant qubit in \\p u, such that\n a row in \\p u is dotted with the vector\n \\f$ |\\text{targetQubit2} \\;\\; \\text{targetQubit1}\\rangle : \\{ |00\\rangle, |01\\rangle, |10\\rangle, |11\\rangle \\} \\f$\n\n The passed 4x4 ComplexMatrix must be unitary, otherwise an error is thrown.\n\n@htmlonly\n<center>\n<script type=\"text/tikz\">\n\\begin{tikzpicture}[scale=.5]\n\\node[draw=none] at (-3.5, 0) {target1};\n\\node[draw=none] at (-3.5, 2) {target2};\n\\node[draw=none] at (-3.5, 5) {controls};\n\n\\node[draw=none] at (0, 8) {$\\vdots$};\n\\draw (0, 7) -- (0, 6);\n\n\\draw (-2, 6) -- (2, 6);\n\\draw[fill=black] (0, 6) circle (.2);\n\\draw (0, 6) -- (0, 4);\n\n\\draw (-2, 4) -- (2, 4);\n\\draw[fill=black] (0, 4) circle (.2);\n\\draw(0, 4) -- (0, 3);\n\n\\draw (-2,0) -- (-1, 0);\n\\draw (1, 0) -- (2, 0);\n\\draw (-2,2) -- (-1, 2);\n\\draw (1, 2) -- (2, 2);\n\\draw (-1,-1)--(-1,3)--(1,3)--(1,-1)--cycle;\n\\node[draw=none] at (0, 1) {U};\n\\end{tikzpicture}\n</script>\n</center>\n@endhtmlonly\n\n Note that in distributed mode, this routine requires that each node contains at least 4 amplitudes.\n This means an q-qubit register (state vector or density matrix) can be distributed\n by at most 2^q/4 nodes.\n\n @see\n - ::ComplexMatrix4\n - twoQubitUnitary()\n - controlledTwoQubitUnitary()\n - multiQubitUnitary()\n - unitary()\n\n @ingroup unitary\n @param[in,out] qureg object representing the set of all qubits\n @param[in] controlQubits the control qubits which all must be in state 1 to effect the given unitary\n @param[in] numControlQubits the number of control qubits\n @param[in] targetQubit1 first target qubit, treated as least significant in \\p u\n @param[in] targetQubit2 second target qubit, treated as most significant in \\p u\n @param[in] u unitary matrix to apply\n @throws invalidQuESTInputError()\n - if \\p targetQubit1 or \\p targetQubit2 are outside [0, \\p qureg.numQubitsRepresented)\n - if \\p targetQubit1 equals \\p targetQubit2\n - if any qubit in \\p controlQubits is outside [0, \\p qureg.numQubitsRepresented)\n - if \\p controlQubits are not unique\n - if either \\p targetQubit1 and \\p targetQubit2 are in \\p controlQubits\n - if matrix \\p u is not unitary\n - if each node cannot fit 4 amplitudes in distributed mode\n @author Tyson Jones"]
1073 pub fn multiControlledTwoQubitUnitary(
1074 qureg: Qureg,
1075 controlQubits: *mut ::std::os::raw::c_int,
1076 numControlQubits: ::std::os::raw::c_int,
1077 targetQubit1: ::std::os::raw::c_int,
1078 targetQubit2: ::std::os::raw::c_int,
1079 u: ComplexMatrix4,
1080 );
1081}
1082extern "C" {
1083 #[doc = " Apply a general multi-qubit unitary (including a global phase factor) with any number of target qubits.\n\n The first target qubit in \\p targs is treated as \\b least significant in \\p u.\n For example,\n ```\n multiQubitUnitary(qureg, (int []) {a, b, c}, 3, u);\n ```\n will invoke multiplication\n \\f[\n \\begin{pmatrix}\n u_{00} & u_{01} & u_{02} & u_{03} & u_{04} & u_{05} & u_{06} & u_{07} \\\\\n u_{10} & u_{11} & u_{12} & u_{13} & u_{14} & u_{15} & u_{16} & u_{17} \\\\\n u_{20} & u_{21} & u_{22} & u_{23} & u_{24} & u_{25} & u_{26} & u_{27} \\\\\n u_{30} & u_{31} & u_{32} & u_{33} & u_{34} & u_{35} & u_{36} & u_{37} \\\\\n u_{40} & u_{41} & u_{42} & u_{43} & u_{44} & u_{45} & u_{46} & u_{47} \\\\\n u_{50} & u_{51} & u_{52} & u_{53} & u_{54} & u_{55} & u_{56} & u_{57} \\\\\n u_{60} & u_{61} & u_{62} & u_{63} & u_{64} & u_{65} & u_{66} & u_{67} \\\\\n u_{70} & u_{71} & u_{72} & u_{73} & u_{74} & u_{75} & u_{76} & u_{77} \\\\\n \\end{pmatrix}\n \\begin{pmatrix}\n |cba\\rangle = |000\\rangle \\\\\n |cba\\rangle = |001\\rangle \\\\\n |cba\\rangle = |010\\rangle \\\\\n |cba\\rangle = |011\\rangle \\\\\n |cba\\rangle = |100\\rangle \\\\\n |cba\\rangle = |101\\rangle \\\\\n |cba\\rangle = |110\\rangle \\\\\n |cba\\rangle = |111\\rangle\n \\end{pmatrix}\n \\f]\n\n The passed ComplexMatrix must be unitary and be a compatible size with the specified number of\n target qubits, otherwise an error is thrown.\n > To effect a non-unitary ::ComplexMatrixN, use applyGateMatrixN().\n\n > To left-multiply a non-unitary ::ComplexMatrixN, use applyMatrixN().\n\n > To specify only the diagonal elements of the matrix, use diagonalUnitary().\n\n@htmlonly\n<center>\n<script type=\"text/tikz\">\n\\begin{tikzpicture}[scale=.5]\n\\node[draw=none] at (-3.5, 1) {targets};\n\n\\draw (-2,0) -- (-1, 0);\n\\draw (1, 0) -- (2, 0);\n\\draw (-2,2) -- (-1, 2);\n\\draw (1, 2) -- (2, 2);\n\\draw (-1,-1)--(-1,3)--(1,3)--(1,-1);\n\\node[draw=none] at (0, 1) {U};\n\\node[draw=none] at (0, -1) {$\\vdots$};\n\n\\end{tikzpicture}\n</script>\n</center>\n@endhtmlonly\n\n Note that in multithreaded mode, each thread will clone 2^\\p numTargs amplitudes,\n and store these in the runtime stack.\n Using t threads, the total memory overhead of this function is t*2^\\p numTargs.\n For many targets (e.g. 16 qubits), this may cause a stack-overflow / seg-fault\n (e.g. on a 1 MiB stack).\n\n Note too that in distributed mode, this routine requires that each node contains\n at least 2^\\p numTargs amplitudes in the register. This means an q-qubit register (state vector or density matrix)\n can be distributed by at most 2^q / 2^\\p numTargs nodes.\n\n @see\n - createComplexMatrixN()\n - controlledMultiQubitUnitary()\n - multiControlledMultiQubitUnitary()\n - applyGateMatrixN()\n - applyMatrixN()\n - twoQubitUnitary()\n - unitary()\n - compactUnitary()\n - diagonalUnitary()\n\n @ingroup unitary\n @param[in,out] qureg object representing the set of all qubits\n @param[in] targs a list of the target qubits, ordered least significant to most in \\p u\n @param[in] numTargs the number of target qubits\n @param[in] u unitary matrix to apply\n @throws invalidQuESTInputError()\n - if any index in \\p targs is outside of [0, \\p qureg.numQubitsRepresented)\n - if \\p targs are not unique\n - if matrix \\p u is not unitary\n - if \\p u is not of a compatible size with \\p numTargs\n - if a node cannot fit the required number of target amplitudes in distributed mode\n @author Tyson Jones"]
1084 pub fn multiQubitUnitary(
1085 qureg: Qureg,
1086 targs: *mut ::std::os::raw::c_int,
1087 numTargs: ::std::os::raw::c_int,
1088 u: ComplexMatrixN,
1089 );
1090}
1091extern "C" {
1092 #[doc = " Apply a general controlled multi-qubit unitary (including a global phase factor).\n One control and any number of target qubits can be specified.\n This effects the many-qubit unitary\n \\f[\n \\begin{pmatrix}\n 1 \\\\\n & 1 \\\\\\\n & & 1 \\\\\n & & & 1 \\\\\n & & & & u_{00} & u_{01} & \\dots \\\\\n & & & & u_{10} & u_{11} & \\dots \\\\\n & & & & \\vdots & \\vdots & \\ddots\n \\end{pmatrix}\n \\f]\n on the control and target qubits.\n\n The target qubits in \\p targs are treated as ordered least significant\n to most significant in \\p u.\n\n The passed ComplexMatrix must be unitary and be a compatible size with the specified number of\n target qubits, otherwise an error is thrown.\n\n@htmlonly\n<center>\n<script type=\"text/tikz\">\n\\begin{tikzpicture}[scale=.5]\n\\node[draw=none] at (-3.5, 1) {targets};\n\\node[draw=none] at (-3.5, 4) {control};\n\n\\draw (-2, 4) -- (2, 4);\n\\draw[fill=black] (0, 4) circle (.2);\n\\draw(0, 4) -- (0, 3);\n\n\\draw (-2,0) -- (-1, 0);\n\\draw (1, 0) -- (2, 0);\n\\draw (-2,2) -- (-1, 2);\n\\draw (1, 2) -- (2, 2);\n\\draw (-1,-1)--(-1,3)--(1,3)--(1,-1);\n\\node[draw=none] at (0, 1) {U};\n\\node[draw=none] at (0, -1) {$\\vdots$};\n\n\\end{tikzpicture}\n</script>\n</center>\n@endhtmlonly\n\n Note that in multithreaded mode, each thread will clone 2^\\p numTargs amplitudes,\n and store these in the runtime stack.\n Using t threads, the total memory overhead of this function is t*2^\\p numTargs.\n For many targets (e.g. 16 qubits), this may cause a stack-overflow / seg-fault\n (e.g. on a 1 MiB stack).\n\n Note too that in distributed mode, this routine requires that each node contains at least 2^\\p numTargs amplitudes.\n This means an q-qubit register (state vector or density matrix) can be distributed\n by at most 2^q / 2^\\p numTargs nodes.\n\n @see\n - createComplexMatrixN()\n - multiQubitUnitary()\n - multiControlledMultiQubitUnitary()\n\n @ingroup unitary\n @param[in,out] qureg object representing the set of all qubits\n @param[in] ctrl the control qubit\n @param[in] targs a list of the target qubits, ordered least to most significant\n @param[in] numTargs the number of target qubits\n @param[in] u unitary matrix to apply\n @throws invalidQuESTInputError()\n - if \\p ctrl or any index in \\p targs is outside of [0, \\p qureg.numQubitsRepresented)\n - if \\p targs are not unique\n - if \\p targs contains \\p ctrl\n - if matrix \\p u is not unitary\n - if matrix \\p u is not of a compatible size with \\p numTargs\n - if a node cannot fit the required number of target amplitudes in distributed mode\n @author Tyson Jones"]
1093 pub fn controlledMultiQubitUnitary(
1094 qureg: Qureg,
1095 ctrl: ::std::os::raw::c_int,
1096 targs: *mut ::std::os::raw::c_int,
1097 numTargs: ::std::os::raw::c_int,
1098 u: ComplexMatrixN,
1099 );
1100}
1101extern "C" {
1102 #[doc = " Apply a general multi-controlled multi-qubit unitary (including a global phase factor).\n Any number of control and target qubits can be specified.\n This effects the many-qubit unitary\n \\f[\n \\begin{pmatrix}\n 1 \\\\\n & 1 \\\\\\\n & & \\ddots \\\\\n & & & u_{00} & u_{01} & \\dots \\\\\n & & & u_{10} & u_{11} & \\dots \\\\\n & & & \\vdots & \\vdots & \\ddots\n \\end{pmatrix}\n \\f]\n on the control and target qubits.\n\n The target qubits in \\p targs are treated as ordered least significant\n to most significant in \\p u.\n\n The passed ::ComplexMatrixN must be unitary and be a compatible size with the specified number of\n target qubits, otherwise an error is thrown.\n > To left-multiply a non-unitary ::ComplexMatrixN, including control qubits,\n > use applyMultiControlledMatrixN()\n\n@htmlonly\n<center>\n<script type=\"text/tikz\">\n\\begin{tikzpicture}[scale=.5]\n\\node[draw=none] at (-3.5, 1) {targets};\n\\node[draw=none] at (-3.5, 5) {controls};\n\n\\node[draw=none] at (0, 8) {$\\vdots$};\n\\draw (0, 7) -- (0, 6);\n\n\\draw (-2, 6) -- (2, 6);\n\\draw[fill=black] (0, 6) circle (.2);\n\\draw (0, 6) -- (0, 4);\n\n\\draw (-2, 4) -- (2, 4);\n\\draw[fill=black] (0, 4) circle (.2);\n\\draw(0, 4) -- (0, 3);\n\n\\draw (-2,0) -- (-1, 0);\n\\draw (1, 0) -- (2, 0);\n\\draw (-2,2) -- (-1, 2);\n\\draw (1, 2) -- (2, 2);\n\\draw (-1,-1)--(-1,3)--(1,3)--(1,-1);\n\\node[draw=none] at (0, 1) {U};\n\\node[draw=none] at (0, -1) {$\\vdots$};\n\n\\end{tikzpicture}\n</script>\n</center>\n@endhtmlonly\n\n Note that in multithreaded mode, each thread will clone 2^\\p numTargs amplitudes,\n and store these in the runtime stack.\n Using t threads, the total memory overhead of this function is t*2^\\p numTargs.\n For many targets (e.g. 16 qubits), this may cause a stack-overflow / seg-fault\n (e.g. on a 1 MiB stack).\n\n Note that in distributed mode, this routine requires that each node contains at least 2^\\p numTargs amplitudes.\n This means an q-qubit register (state vector or density matrix) can be distributed\n by at most 2^q / 2^\\p numTargs nodes.\n\n @see\n - createComplexMatrixN()\n - applyMultiControlledGateMatrixN()\n - applyMultiControlledMatrixN()\n - multiControlledMultiQubitNot()\n - controlledMultiQubitUnitary()\n - multiQubitUnitary()\n\n @ingroup unitary\n @param[in,out] qureg object representing the set of all qubits\n @param[in] ctrls a list of the control qubits\n @param[in] numCtrls the number of control qubits\n @param[in] targs a list of the target qubits, ordered least to most significant\n @param[in] numTargs the number of target qubits\n @param[in] u unitary matrix to apply\n @throws invalidQuESTInputError()\n - if any qubit in \\p ctrls and \\p targs is invalid, i.e. outside <b>[0, </b>`qureg.numQubitsRepresented`<b>)</b>\n - if \\p ctrls or \\p targs contain any repetitions\n - if any qubit in \\p ctrls is also in \\p targs (and vice versa)\n - if \\p numTargs <b>< 1</b>\n - if \\p numCtrls <b>< 1</b> (use multiQubitUnitary() for no controls)\n - if matrix \\p u is not unitary\n - if matrix \\p u is not of a compatible size with \\p numTargs\n - if a node cannot fit the required number of target amplitudes in distributed mode\n @throws segmentation-fault\n - if \\p ctrls contains fewer elements than \\p numCtrls\n - if \\p targs contains fewer elements than \\p numTargs\n @author Tyson Jones"]
1103 pub fn multiControlledMultiQubitUnitary(
1104 qureg: Qureg,
1105 ctrls: *mut ::std::os::raw::c_int,
1106 numCtrls: ::std::os::raw::c_int,
1107 targs: *mut ::std::os::raw::c_int,
1108 numTargs: ::std::os::raw::c_int,
1109 u: ComplexMatrixN,
1110 );
1111}
1112extern "C" {
1113 #[doc = " Apply a general single-qubit Kraus map to a density matrix, as specified by at most\n four Kraus operators, \\f$K_i\\f$ (\\p ops). A Kraus map is also referred to as\n a \"operator-sum representation\" of a quantum channel, and enables the simulation of\n general single-qubit noise process,\n by effecting\n \\f[\n\\rho \\to \\sum\\limits_i^{\\text{numOps}} K_i \\rho K_i^\\dagger\n \\f]\n\n The Kraus map must be completely positive and trace preserving, which constrains each\n \\f$ K_i \\f$ in \\p ops by\n \\f[\n\\sum \\limits_i^{\\text{numOps}} K_i^\\dagger K_i = I\n \\f]\n where \\f$ I \\f$ is the identity matrix. Use mixNonTPKrausMap() to relax this condition.\n\n Note that in distributed mode, this routine requires that each node contains at least 4 amplitudes.\n This means an q-qubit register can be distributed by at most 2^(q-2) numTargs nodes.\n\n @see\n - ::ComplexMatrix2\n - mixNonTPKrausMap()\n - mixTwoQubitKrausMap()\n - mixMultiQubitKrausMap()\n - mixDephasing()\n - mixDepolarising()\n - mixDamping()\n - mixPauli()\n - mixDensityMatrix()\n\n @ingroup decoherence\n @param[in,out] qureg the density matrix to which to apply the map\n @param[in] target the target qubit of the map\n @param[in] ops an array of at most 4 Kraus operators\n @param[in] numOps the number of operators in \\p ops which must be >0 and <= 4.\n @throws invalidQuESTInputError()\n - if \\p qureg is not a density matrix\n - if \\p target is outside of [0, \\p qureg.numQubitsRepresented)\n - if \\p numOps is outside [1, 4]\n - if \\p ops do not create a completely positive, trace preserving map\n - if a node cannot fit 4 amplitudes in distributed mode\n @author Balint Koczor\n @author Tyson Jones (refactored, doc)"]
1114 pub fn mixKrausMap(
1115 qureg: Qureg,
1116 target: ::std::os::raw::c_int,
1117 ops: *mut ComplexMatrix2,
1118 numOps: ::std::os::raw::c_int,
1119 );
1120}
1121extern "C" {
1122 #[doc = " Apply a general two-qubit Kraus map to a density matrix, as specified by at most\n sixteen Kraus operators. A Kraus map is also referred to as a \"operator-sum representation\"\n of a quantum channel. This allows one to simulate a general two-qubit noise process.\n\n The Kraus map must be completely positive and trace preserving, which constrains each\n \\f$ K_i \\f$ in \\p ops by\n \\f[\n\\sum \\limits_i^{\\text{numOps}} K_i^\\dagger K_i = I\n \\f]\n where \\f$ I \\f$ is the identity matrix. Use mixNonTPTwoQubitKrausMap() to relax this\n this condition.\n\n \\p targetQubit1 is treated as the \\p least significant qubit in each op in \\p ops.\n\n Note that in distributed mode, this routine requires that each node contains at least 16 amplitudes.\n This means an q-qubit register can be distributed by at most 2^(q-4) numTargs nodes.\n\n @see\n - ::ComplexMatrix4\n - mixNonTPTwoQubitKrausMap()\n - mixMultiQubitKrausMap()\n - mixKrausMap()\n\n @ingroup decoherence\n @param[in,out] qureg the density matrix to which to apply the map\n @param[in] target1 the least significant target qubit in \\p ops\n @param[in] target2 the most significant target qubit in \\p ops\n @param[in] ops an array of at most 16 Kraus operators\n @param[in] numOps the number of operators in \\p ops which must be >0 and <= 16.\n @throws invalidQuESTInputError()\n - if \\p qureg is not a density matrix\n - if either \\p target1 or \\p target2 is outside of [0, \\p qureg.numQubitsRepresented)\n - if \\p target1 = \\p target2\n - if \\p numOps is outside [1, 16]\n - if \\p ops do not create a completely positive, trace preserving map\n - if a node cannot fit 16 amplitudes in distributed mode\n @author Balint Koczor\n @author Tyson Jones (refactored, doc)"]
1123 pub fn mixTwoQubitKrausMap(
1124 qureg: Qureg,
1125 target1: ::std::os::raw::c_int,
1126 target2: ::std::os::raw::c_int,
1127 ops: *mut ComplexMatrix4,
1128 numOps: ::std::os::raw::c_int,
1129 );
1130}
1131extern "C" {
1132 #[doc = " Apply a general N-qubit Kraus map to a density matrix, as specified by at most (2N)^2\n Kraus operators. This allows one to simulate a general noise process.\n\n The Kraus map must be completely positive and trace preserving, which constrains each\n \\f$ K_i \\f$ in \\p ops by\n \\f[\n\\sum \\limits_i^{\\text{numOps}} K_i^\\dagger K_i = I\n \\f]\n where \\f$ I \\f$ is the identity matrix. Use mixNonTPMultiQubitKrausMap() to relax\n this condition.\n\n The first qubit in \\p targets is treated as the \\p least significant qubit in each op in \\p ops.\n\n Note that in distributed mode, this routine requires that each node contains at least (2N)^2 amplitudes.\n This means an q-qubit register can be distributed by at most 2^(q-2)/N^2 nodes.\n\n Note too that this routine internally creates a 'superoperator'; a complex matrix of dimensions\n 2^(2*numTargets) by 2^(2*numTargets). Therefore, invoking this function incurs,\n for numTargs={1,2,3,4,5, ...}, an additional memory overhead of (at double-precision)\n {0.25 KiB, 4 KiB, 64 KiB, 1 MiB, 16 MiB, ...} (respectively).\n At quad precision (usually 10 B per number, but possibly 16 B due to alignment),\n this costs at most double the amount of memory.\n For numTargets < 4, this superoperator will be created in the runtime\n stack. For numTargs >= 4, the superoperator will be allocated in the heap and\n therefore this routine may suffer an anomalous slowdown.\n\n @see\n - createComplexMatrixN()\n - initComplexMatrixN()\n - mixNonTPMultiQubitKrausMap()\n - mixKrausMap()\n - mixTwoQubitKrausMap()\n\n @ingroup decoherence\n @param[in,out] qureg the density matrix to which to apply the map\n @param[in] targets a list of target qubit indices, the first of which is treated as least significant in each op in \\p ops\n @param[in] numTargets the length of \\p targets\n @param[in] ops an array of at most (2N)^2 Kraus operators\n @param[in] numOps the number of operators in \\p ops which must be >0 and <= (2N)^2.\n @throws invalidQuESTInputError()\n - if \\p qureg is not a density matrix\n - if any target in \\p targets is outside of [0, \\p qureg.numQubitsRepresented)\n - if any qubit in \\p targets is repeated\n - if \\p numOps is outside [1, (2 \\p numTargets)^2]\n - if any ComplexMatrixN in \\p ops does not have op.numQubits == \\p numTargets\n - if \\p ops do not create a completely positive, trace preserving map\n - if a node cannot fit (2N)^2 amplitudes in distributed mode\n @author Tyson Jones\n @author Balint Koczor"]
1133 pub fn mixMultiQubitKrausMap(
1134 qureg: Qureg,
1135 targets: *mut ::std::os::raw::c_int,
1136 numTargets: ::std::os::raw::c_int,
1137 ops: *mut ComplexMatrixN,
1138 numOps: ::std::os::raw::c_int,
1139 );
1140}
1141extern "C" {
1142 #[doc = " Apply a general non-trace-preserving single-qubit Kraus map to a density matrix,\n as specified by at most four operators, \\f$K_i\\f$ (\\p ops).\n This effects\n \\f[\n\\rho \\to \\sum\\limits_i^{\\text{numOps}} K_i \\rho K_i^\\dagger\n \\f]\n where \\f$K_i\\f$ are permitted to be any matrix. This means the density matrix\n can enter a non-physical state.\n\n Use mixKrausMap() to enforce that the channel is trace preserving and completely positive.\n\n Note that in distributed mode, this routine requires that each node contains at least 4 amplitudes.\n This means an q-qubit register can be distributed by at most 2^(q-2) numTargs nodes.\n\n @see\n - ::ComplexMatrix2\n - mixKrausMap()\n - mixNonTPTwoQubitKrausMap()\n - mixNonTPMultiQubitKrausMap()\n\n @ingroup decoherence\n @param[in,out] qureg the density matrix to which to apply the map\n @param[in] target the target qubit of the map\n @param[in] ops an array of at most 4 Kraus operators\n @param[in] numOps the number of operators in \\p ops which must be >0 and <= 4.\n @throws invalidQuESTInputError()\n - if \\p qureg is not a density matrix\n - if \\p target is outside of [0, \\p qureg.numQubitsRepresented)\n - if \\p numOps is outside [1, 4]\n - if a node cannot fit 4 amplitudes in distributed mode\n @author Tyson Jones\n @author Balint Koczor (backend code)"]
1143 pub fn mixNonTPKrausMap(
1144 qureg: Qureg,
1145 target: ::std::os::raw::c_int,
1146 ops: *mut ComplexMatrix2,
1147 numOps: ::std::os::raw::c_int,
1148 );
1149}
1150extern "C" {
1151 #[doc = " Apply a general non-trace-preserving two-qubit Kraus map to a density matrix,\n as specified by at most sixteen operators, \\f$K_i\\f$ (\\p ops).\n\n This effects\n \\f[\n\\rho \\to \\sum\\limits_i^{\\text{numOps}} K_i \\rho K_i^\\dagger\n \\f]\n where the matrices \\f$K_i\\f$ are unconstrained, and hence the effective map is permitted\n to be non-completely-positive and non-trace-preserving.\n Use mixTwoQubitKrausMap() to enforce that the map be completely positive.\n\n \\p targetQubit1 is treated as the \\p least significant qubit in each op in \\p ops.\n\n Note that in distributed mode, this routine requires that each node contains at least 16 amplitudes.\n This means an q-qubit register can be distributed by at most 2^(q-4) numTargs nodes.\n\n @see\n - ::ComplexMatrix4\n - mixTwoQubitKrausMap()\n - mixNonTPKrausMap()\n - mixNonTPMultiQubitKrausMap()\n\n @ingroup decoherence\n @param[in,out] qureg the density matrix to which to apply the map\n @param[in] target1 the least significant target qubit in \\p ops\n @param[in] target2 the most significant target qubit in \\p ops\n @param[in] ops an array of at most 16 Kraus operators\n @param[in] numOps the number of operators in \\p ops which must be >0 and <= 16.\n @throws invalidQuESTInputError()\n - if \\p qureg is not a density matrix\n - if either \\p target1 or \\p target2 is outside of [0, \\p qureg.numQubitsRepresented)\n - if \\p target1 = \\p target2\n - if \\p numOps is outside [1, 16]\n - if a node cannot fit 16 amplitudes in distributed mode\n @author Tyson Jones\n @author Balint Koczor (backend code)"]
1152 pub fn mixNonTPTwoQubitKrausMap(
1153 qureg: Qureg,
1154 target1: ::std::os::raw::c_int,
1155 target2: ::std::os::raw::c_int,
1156 ops: *mut ComplexMatrix4,
1157 numOps: ::std::os::raw::c_int,
1158 );
1159}
1160extern "C" {
1161 #[doc = " Apply a general N-qubit non-trace-preserving Kraus map to a density matrix,\n as specified by at most (2N)^2 operators.\n\n This effects\n \\f[\n\\rho \\to \\sum\\limits_i^{\\text{numOps}} K_i \\rho K_i^\\dagger\n \\f]\n where the matrices \\f$ K_i \\f$ are unconstrained, and hence the effective map is permitted\n to be non-completely-positive and non-trace-preserving.\n Use mixMultiQubitKrausMap() to enforce that the map be completely positive.\n\n The first qubit in \\p targets is treated as the \\p least significant qubit in each op in \\p ops.\n\n Note that in distributed mode, this routine requires that each node contains at least (2N)^2 amplitudes.\n This means an q-qubit register can be distributed by at most 2^(q-2)/N^2 nodes.\n\n Note too that this routine internally creates a 'superoperator'; a complex matrix of dimensions\n 2^(2*numTargets) by 2^(2*numTargets). Therefore, invoking this function incurs,\n for numTargs={1,2,3,4,5, ...}, an additional memory overhead of (at double-precision)\n {0.25 KiB, 4 KiB, 64 KiB, 1 MiB, 16 MiB, ...} (respectively).\n At quad precision (usually 10 B per number, but possibly 16 B due to alignment),\n this costs at most double the amount of memory.\n For numTargets < 4, this superoperator will be created in the runtime\n stack. For numTargs >= 4, the superoperator will be allocated in the heap and\n therefore this routine may suffer an anomalous slowdown.\n\n @see\n - createComplexMatrixN()\n - initComplexMatrixN()\n - mixMultiQubitKrausMap()\n - mixNonTPKrausMap()\n - mixNonTPTwoQubitKrausMap()\n\n @ingroup decoherence\n @param[in,out] qureg the density matrix to which to apply the map\n @param[in] targets a list of target qubit indices, the first of which is treated as least significant in each op in \\p ops\n @param[in] numTargets the length of \\p targets\n @param[in] ops an array of at most (2N)^2 Kraus operators\n @param[in] numOps the number of operators in \\p ops which must be >0 and <= (2N)^2.\n @throws invalidQuESTInputError()\n - if \\p qureg is not a density matrix\n - if any target in \\p targets is outside of [0, \\p qureg.numQubitsRepresented)\n - if any qubit in \\p targets is repeated\n - if \\p numOps is outside [1, (2 \\p numTargets)^2]\n - if any ComplexMatrixN in \\p ops does not have op.numQubits == \\p numTargets\n - if a node cannot fit (2N)^2 amplitudes in distributed mode\n @author Tyson Jones\n @author Balint Koczor (backend code)"]
1162 pub fn mixNonTPMultiQubitKrausMap(
1163 qureg: Qureg,
1164 targets: *mut ::std::os::raw::c_int,
1165 numTargets: ::std::os::raw::c_int,
1166 ops: *mut ComplexMatrixN,
1167 numOps: ::std::os::raw::c_int,
1168 );
1169}
1170extern "C" {
1171 #[doc = " Computes the Hilbert Schmidt distance between two density matrices \\p a and \\p b,\n defined as the Frobenius norm of the difference between them.\n That is, we define the Hilbert Schmidt distance\n \\f[\nD(a, b) = \\| a - b \\|_F = \\sqrt{ \\text{Tr}[ (a-b)(a-b)^\\dagger ] }\n \\f]\n This is equivalent to the square-root of the sum of the absolute value squared of the\n element-differences of the matrices, i.e.\n \\f[\nD(a, b) = \\sqrt{ \\sum\\limits_i \\sum\\limits_j | a_{ij} - b_{ij} |^2 }\n \\f]\n We caution this may differ by some definitions of the Hilbert Schmidt distance\n by a square-root.\n\n This function correctly returns the result of the above formulations even when\n \\p a and \\p b are incorrectly normalised (i.e. are general matrices).\n\n @see\n - calcDensityInnerProduct()\n - calcFidelity()\n - calcPurity()\n\n @ingroup calc\n @param[in] a a density matrix\n @param[in] b an equally-sized density matrix\n @throws invalidQuESTInputError()\n - if either \\p a or \\p b are not density matrices\n - if \\p a and \\p have mismatching dimensions\n @author Balint Koczor\n @author Tyson Jones (refactored, doc)"]
1172 pub fn calcHilbertSchmidtDistance(a: Qureg, b: Qureg) -> f64;
1173}
1174extern "C" {
1175 #[doc = " Modifies qureg \\p out to the result of (\\p facOut \\p out + \\p fac1 \\p qureg1 + \\p fac2 \\p qureg2),\n imposing no constraints on normalisation. Works for both state-vectors and density matrices.\n Note that afterward, \\p out may not longer be normalised and ergo no longer a valid\n state-vector or density matrix. Users must therefore be careful passing \\p out to\n other QuEST functions which assume normalisation in order to function correctly.\n\n \\p qureg1, \\p qureg2 and \\p out must be all state-vectors, or all density matrices,\n of equal dimensions. \\p out can be one (or both) of \\p qureg1 and \\p qureg2.\n\n @ingroup init\n @param[in] fac1 the complex number by which to scale \\p qureg1 in the output state\n @param[in] qureg1 the first qureg to add to \\p out, which is itself unmodified\n @param[in] fac2 the complex number by which to scale \\p qureg2 in the output state\n @param[in] qureg2 the second qureg to add to \\p out, which is itself unmodified\n @param[in] facOut the complex factor by which to multiply the current elements of \\p out.\n \\p out is completely overwritten if \\p facOut is set to (Complex) {.real=0,.imag=0}\n @param[in,out] out the qureg to be modified, to be scaled by \\p facOut then have \\p fac1 \\p qureg1 and\n \\p fac2 \\p qureg2 added to it.\n @throws invalidQuESTInputError()\n - if \\p qureg1, \\p qureg2 and \\p aren't all state-vectors or all density matrices\n - if the dimensions of \\p qureg1, \\p qureg2 and \\p aren't equal\n @author Tyson Jones"]
1176 pub fn setWeightedQureg(
1177 fac1: Complex,
1178 qureg1: Qureg,
1179 fac2: Complex,
1180 qureg2: Qureg,
1181 facOut: Complex,
1182 out: Qureg,
1183 );
1184}
1185extern "C" {
1186 #[doc = " Modifies \\p outQureg to be the result of applying the weighted sum of Pauli products (a Hermitian but not\n necessarily unitary operator) to \\p inQureg. Note that afterward, \\p outQureg may no longer be normalised and ergo not a\n state-vector or density matrix. Users must therefore be careful passing \\p outQureg to\n other QuEST functions which assume normalisation in order to function correctly.\n\n Letting \\f$ \\alpha = \\sum_i c_i \\otimes_j^{N} \\hat{\\sigma}_{i,j} \\f$ be\n the operators indicated by \\p allPauliCodes (where \\f$ c_i \\in \\f$ \\p termCoeffs and \\f$ N = \\f$ \\p qureg.numQubitsRepresented),\n this function effects \\f$ \\alpha | \\psi \\rangle \\f$ on state-vector \\f$ |\\psi\\rangle \\f$\n and \\f$\\alpha \\rho\\f$ (left matrix multiplication) on density matrix \\f$ \\rho \\f$.\n\n \\p allPauliCodes is an array of length \\p numSumTerms*\\p qureg.numQubitsRepresented\n which specifies which Pauli operators to apply, where 0 = \\p PAULI_I, 1 = \\p PAULI_X,\n 2 = \\p PAULI_Y, 3 = \\p PAULI_Z. For each sum term, a Pauli operator must be specified for\n EVERY qubit in \\p qureg; each set of \\p numSumTerms operators will be grouped into a product.\n \\p termCoeffs is an arrray of length \\p numSumTerms containing the term coefficients.\n For example, on a 3-qubit state-vector,\n ```\n int paulis[6] = {PAULI_X, PAULI_I, PAULI_I, PAULI_X, PAULI_Y, PAULI_Z};\n qreal coeffs[2] = {1.5, -3.6};\n applyPauliSum(inQureg, paulis, coeffs, 2, outQureg);\n ```\n will apply Hermitian operation \\f$ (1.5 X I I - 3.6 X Y Z) \\f$\n (where in this notation, the left-most operator applies to the least-significant qubit, i.e. that with index 0).\n\n In theory, \\p inQureg is unchanged though its state is temporarily\n modified and is reverted by re-applying Paulis (XX=YY=ZZ=I), so may see a change by small numerical errors.\n The initial state in \\p outQureg is not used.\n\n \\p inQureg and \\p outQureg must both be state-vectors, or both density matrices,\n of equal dimensions. \\p inQureg cannot be \\p outQureg.\n\n This function works by applying each Pauli product to \\p inQureg in turn,\n and adding the resulting state (weighted by a coefficient in \\p termCoeffs)\n to the initially-blanked \\p outQureg. Ergo it should scale with the total number\n of Pauli operators specified (excluding identities), and the qureg dimension.\n\n @see\n - calcExpecPauliSum()\n - applyPauliHamil()\n\n @ingroup operator\n @param[in] inQureg the register containing the state which \\p outQureg will be set to, under\n the action of the Hermitiain operator specified by the Pauli codes. \\p inQureg should be\n unchanged, though may vary slightly due to numerical error.\n @param[in] allPauliCodes a list of the Pauli codes (0=PAULI_I, 1=PAULI_X, 2=PAULI_Y, 3=PAULI_Z)\n of all Paulis involved in the products of terms. A Pauli must be specified for each qubit\n in the register, in every term of the sum.\n @param[in] termCoeffs The coefficients of each term in the sum of Pauli products\n @param[in] numSumTerms The total number of Pauli products specified\n @param[out] outQureg the qureg to modify to be the result of applyling the weighted Pauli sum operator\n to the state in \\p inQureg\n @throws invalidQuESTInputError()\n - if any code in \\p allPauliCodes is not in {0,1,2,3}\n - if numSumTerms <= 0\n - if \\p inQureg is not of the same type and dimensions as \\p outQureg\n @author Tyson Jones"]
1187 pub fn applyPauliSum(
1188 inQureg: Qureg,
1189 allPauliCodes: *mut pauliOpType,
1190 termCoeffs: *mut f64,
1191 numSumTerms: ::std::os::raw::c_int,
1192 outQureg: Qureg,
1193 );
1194}
1195extern "C" {
1196 #[doc = " Modifies \\p outQureg to be the result of applying \\p PauliHamil (a Hermitian but not\n necessarily unitary operator) to \\p inQureg. Note that afterward, \\p outQureg may no longer be normalised and ergo not a\n state-vector or density matrix. Users must therefore be careful passing \\p outQureg to\n other QuEST functions which assume normalisation in order to function correctly.\n\n This is merely an encapsulation of applyPauliSum(), which can refer to for elaborated doc.\n\n Letting \\p hamil be expressed as \\f$ \\alpha = \\sum_i c_i \\otimes_j^{N} \\hat{\\sigma}_{i,j} \\f$\n (where \\f$ c_i \\in \\f$ \\p hamil.termCoeffs and \\f$ N = \\f$ \\p hamil.numQubits),\n this function effects \\f$ \\alpha | \\psi \\rangle \\f$ on state-vector \\f$ |\\psi\\rangle \\f$\n and \\f$\\alpha \\rho\\f$ (left matrix multiplication) on density matrix \\f$ \\rho \\f$.\n\n In theory, \\p inQureg is unchanged though its state is temporarily\n modified and is reverted by re-applying Paulis (XX=YY=ZZ=I), so may see a change by small numerical errors.\n The initial state in \\p outQureg is not used.\n\n \\p inQureg and \\p outQureg must both be state-vectors, or both density matrices,\n of equal dimensions to \\p hamil.\n \\p inQureg cannot be \\p outQureg.\n\n This function works by applying each Pauli product in \\p hamil to \\p inQureg in turn,\n and adding the resulting state (weighted by a coefficient in \\p termCoeffs)\n to the initially-blanked \\p outQureg. Ergo it should scale with the total number\n of Pauli operators specified (excluding identities), and the qureg dimension.\n\n @see\n - createPauliHamil()\n - createPauliHamilFromFile()\n - calcExpecPauliHamil()\n - applyTrotterCircuit()\n\n @ingroup operator\n @param[in] inQureg the register containing the state which \\p outQureg will be set to, under\n the action of \\p hamil. \\p inQureg should be unchanged, though may vary slightly due to numerical error.\n @param[in] hamil a weighted sum of products of pauli operators\n @param[out] outQureg the qureg to modify to be the result of applyling \\p hamil to the state in \\p inQureg\n @throws invalidQuESTInputError()\n - if any code in \\p hamil.pauliCodes is not a valid Pauli code\n - if \\p numSumTerms <= 0\n - if \\p inQureg is not of the same type and dimensions as \\p outQureg and \\p hamil\n @author Tyson Jones"]
1197 pub fn applyPauliHamil(inQureg: Qureg, hamil: PauliHamil, outQureg: Qureg);
1198}
1199extern "C" {
1200 #[doc = " Applies a trotterisation of unitary evolution \\f$ \\exp(-i \\, \\text{hamil} \\, \\text{time}) \\f$\n to \\p qureg. This is a sequence of unitary operators, effected by multiRotatePauli(),\n which together approximate the action of full unitary-time evolution under the given Hamiltonian.\n\n Notate \\f$ \\text{hamil} = \\sum_j^N c_j \\, \\hat \\sigma_j \\f$ where \\f$c_j\\f$ is a real\n coefficient in \\p hamil, \\f$\\hat \\sigma_j\\f$ is the corresponding product of Pauli operators,\n of which there are a total \\f$N\\f$.\n Then, \\p order=1 performs first-order Trotterisation, whereby\n \\f[\n \\exp(-i \\, \\text{hamil} \\, \\text{time})\n \\approx\n \\prod\\limits^{\\text{reps}} \\prod\\limits_{j=1}^{N} \\exp(-i \\, c_j \\, \\text{time} \\, \\hat\\sigma_j / \\text{reps})\n \\f]\n \\p order=2 performs the lowest order \"symmetrized\" Suzuki decomposition, whereby\n \\f[\n \\exp(-i \\, \\text{hamil} \\, \\text{time})\n \\approx\n \\prod\\limits^{\\text{reps}} \\left[\n \\prod\\limits_{j=1}^{N} \\exp(-i \\, c_j \\, \\text{time} \\, \\hat\\sigma_j / (2 \\, \\text{reps}))\n \\prod\\limits_{j=N}^{1} \\exp(-i \\, c_j \\, \\text{time} \\, \\hat\\sigma_j / (2 \\, \\text{reps}))\n \\right]\n \\f]\n Greater even values of \\p order specify higher-order symmetrized decompositions\n \\f$ S[\\text{time}, \\text{order}, \\text{reps}] \\f$ which satisfy\n \\f[\n S[\\text{time}, \\text{order}, 1] =\n \\left( \\prod\\limits^2 S[p \\, \\text{time}, \\text{order}-2, 1] \\right)\n S[ (1-4p)\\,\\text{time}, \\text{order}-2, 1]\n \\left( \\prod\\limits^2 S[p \\, \\text{time}, \\text{order}-2, 1] \\right)\n \\f]\n and\n \\f[\n S[\\text{time}, \\text{order}, \\text{reps}] =\n \\prod\\limits^{\\text{reps}} S[\\text{time}/\\text{reps}, \\text{order}, 1]\n \\f]\n where \\f$ p = \\left( 4 - 4^{1/(\\text{order}-1)} \\right)^{-1} \\f$.\n\n These formulations are taken from 'Finding Exponential Product Formulas\n of Higher Orders', Naomichi Hatano and Masuo Suzuki (2005) (<a href=\"https://arxiv.org/abs/math-ph/0506007\">arXiv</a>).\n\n Note that the applied Trotter circuit is captured by QASM, if QASM logging is enabled\n on \\p qureg. \\n\n For example:\n ```\n startRecordingQASM(qureg);\n applyTrotterCircuit(qureg, hamil, 1, 2, 1);\n printRecordedQASM(qureg);\n ```\n may show\n ```\n // Beginning of Trotter circuit (time 1, order 2, 1 repetitions).\n // Here, a multiRotatePauli with angle 0.5 and paulis X Y I was applied.\n // Here, a multiRotatePauli with angle -0.5 and paulis I Z X was applied.\n // Here, a multiRotatePauli with angle -0.5 and paulis I Z X was applied.\n // Here, a multiRotatePauli with angle 0.5 and paulis X Y I was applied.\n // End of Trotter circuit\n ```\n \\n\n\n\n @see\n - createPauliHamil()\n\n @ingroup operator\n @param[in,out] qureg the register to modify under the approximate unitary-time evolution\n @param[in] hamil the hamiltonian under which to approxiamte unitary-time evolution\n @param[in] time the target evolution time, which is permitted to be both positive and negative.\n @param[in] order the order of Trotter-Suzuki decomposition to use. Higher orders (necessarily even)\n are more accurate but prescribe an exponentially increasing number of gates.\n @param[in] reps the number of repetitions of the decomposition of the given order. This\n improves the accuracy but prescribes a linearly increasing number of gates.\n @throws invalidQuESTInputError()\n - if \\p qureg.numQubitsRepresented != \\p hamil.numQubits\n - if \\p hamil contains invalid parameters or Pauli codes,\n - if \\p order is not in {1, 2, 4, 6, ...}\n - or if \\p reps <= 0\n @author Tyson Jones"]
1201 pub fn applyTrotterCircuit(
1202 qureg: Qureg,
1203 hamil: PauliHamil,
1204 time: f64,
1205 order: ::std::os::raw::c_int,
1206 reps: ::std::os::raw::c_int,
1207 );
1208}
1209extern "C" {
1210 #[doc = " Apply a general 2-by-2 matrix, which may be non-unitary. The matrix is\n left-multiplied onto the state, for both state-vectors and density matrices.\n\n Note this differs from the action of unitary() on a density matrix.\n\n This function may leave \\p qureg is an unnormalised state.\n\n @see\n - ::ComplexMatrix2\n - unitary()\n\n @ingroup operator\n @param[in,out] qureg object representing the set of all qubits\n @param[in] targetQubit qubit to operate \\p u upon\n @param[in] u matrix to apply\n @throws invalidQuESTInputError()\n - if \\p targetQubit is outside [0, \\p qureg.numQubitsRepresented)\n @author Tyson Jones"]
1211 pub fn applyMatrix2(qureg: Qureg, targetQubit: ::std::os::raw::c_int, u: ComplexMatrix2);
1212}
1213extern "C" {
1214 #[doc = " Apply a general 4-by-4 matrix, which may be non-unitary. The matrix is\n left-multiplied onto the state, for both state-vectors and density matrices.\n\n Note this differs from the action of twoQubitUnitary() on a density matrix.\n\n \\p targetQubit1 is treated as the \\p least significant qubit in \\p u, such that\n a row in \\p u is dotted with the vector\n \\f$ |\\text{targetQubit2} \\;\\; \\text{targetQubit1}\\rangle : \\{ |00\\rangle, |01\\rangle, |10\\rangle, |11\\rangle \\} \\f$\n\n For example,\n ```\n applyMatrix4(qureg, a, b, u);\n ```\n will invoke multiplication\n \\f[\n \\begin{pmatrix}\n u_{00} & u_{01} & u_{02} & u_{03} \\\\\n u_{10} & u_{11} & u_{12} & u_{13} \\\\\n u_{20} & u_{21} & u_{22} & u_{23} \\\\\n u_{30} & u_{31} & u_{32} & u_{33}\n \\end{pmatrix}\n \\begin{pmatrix}\n |ba\\rangle = |00\\rangle \\\\\n |ba\\rangle = |01\\rangle \\\\\n |ba\\rangle = |10\\rangle \\\\\n |ba\\rangle = |11\\rangle\n \\end{pmatrix}\n \\f]\n\n This function may leave \\p qureg is an unnormalised state.\n\n Note that in distributed mode, this routine requires that each node contains at least 4 amplitudes.\n This means an q-qubit register (state vector or density matrix) can be distributed\n by at most 2^q/4 nodes.\n\n @see\n - ::ComplexMatrix4\n - twoQubitUnitary()\n\n @ingroup operator\n @param[in,out] qureg object representing the set of all qubits\n @param[in] targetQubit1 first qubit to operate on, treated as least significant in \\p u\n @param[in] targetQubit2 second qubit to operate on, treated as most significant in \\p u\n @param[in] u matrix to apply\n @throws invalidQuESTInputError()\n - if \\p targetQubit1 or \\p targetQubit2 are outside [0, \\p qureg.numQubitsRepresented)\n - if \\p targetQubit1 equals \\p targetQubit2\n - if each node cannot fit 4 amplitudes in distributed mode\n @author Tyson Jones"]
1215 pub fn applyMatrix4(
1216 qureg: Qureg,
1217 targetQubit1: ::std::os::raw::c_int,
1218 targetQubit2: ::std::os::raw::c_int,
1219 u: ComplexMatrix4,
1220 );
1221}
1222extern "C" {
1223 #[doc = " Apply a general N-by-N matrix, which may be non-unitary, on any number of target qubits.\n The matrix is left-multiplied onto the state, for both state-vectors and density matrices.\n Note this differs from the action of multiQubitUnitary() on a density matrix.\n\n The first target qubit in \\p targs is treated as \\b least significant in \\p u.\n For example,\n ```\n applyMatrixN(qureg, (int []) {a, b, c}, 3, u);\n ```\n will invoke multiplication\n \\f[\n \\begin{pmatrix}\n u_{00} & u_{01} & u_{02} & u_{03} & u_{04} & u_{05} & u_{06} & u_{07} \\\\\n u_{10} & u_{11} & u_{12} & u_{13} & u_{14} & u_{15} & u_{16} & u_{17} \\\\\n u_{20} & u_{21} & u_{22} & u_{23} & u_{24} & u_{25} & u_{26} & u_{27} \\\\\n u_{30} & u_{31} & u_{32} & u_{33} & u_{34} & u_{35} & u_{36} & u_{37} \\\\\n u_{40} & u_{41} & u_{42} & u_{43} & u_{44} & u_{45} & u_{46} & u_{47} \\\\\n u_{50} & u_{51} & u_{52} & u_{53} & u_{54} & u_{55} & u_{56} & u_{57} \\\\\n u_{60} & u_{61} & u_{62} & u_{63} & u_{64} & u_{65} & u_{66} & u_{67} \\\\\n u_{70} & u_{71} & u_{72} & u_{73} & u_{74} & u_{75} & u_{76} & u_{77} \\\\\n \\end{pmatrix}\n \\begin{pmatrix}\n |cba\\rangle = |000\\rangle \\\\\n |cba\\rangle = |001\\rangle \\\\\n |cba\\rangle = |010\\rangle \\\\\n |cba\\rangle = |011\\rangle \\\\\n |cba\\rangle = |100\\rangle \\\\\n |cba\\rangle = |101\\rangle \\\\\n |cba\\rangle = |110\\rangle \\\\\n |cba\\rangle = |111\\rangle\n \\end{pmatrix}\n \\f]\n\n This function may leave \\p qureg is an unnormalised state.\n\n The passed ComplexMatrix must be a compatible size with the specified number of\n target qubits, otherwise an error is thrown.\n\n Note that in multithreaded mode, each thread will clone 2^\\p numTargs amplitudes,\n and store these in the runtime stack.\n Using t threads, the total memory overhead of this function is t*2^\\p numTargs.\n For many targets (e.g. 16 qubits), this may cause a stack-overflow / seg-fault\n (e.g. on a 1 MiB stack).\n\n Note too that in distributed mode, this routine requires that each node contains\n at least 2^\\p numTargs amplitudes in the register. This means an q-qubit register (state vector or density matrix)\n can be distributed by at most 2^q / 2^\\p numTargs nodes.\n\n @see\n - applyGateMatrixN()\n - createComplexMatrixN()\n - getStaticComplexMatrixN()\n - applyMultiControlledMatrixN()\n - multiQubitUnitary()\n\n @ingroup operator\n @param[in,out] qureg object representing the set of all qubits\n @param[in] targs a list of the target qubits, ordered least significant to most in \\p u\n @param[in] numTargs the number of target qubits\n @param[in] u matrix to apply\n @throws invalidQuESTInputError()\n - if any index in \\p targs is outside of [0, \\p qureg.numQubitsRepresented)\n - if \\p targs are not unique\n - if \\p u is not of a compatible size with \\p numTargs\n - if a node cannot fit the required number of target amplitudes in distributed mode\n @author Tyson Jones"]
1224 pub fn applyMatrixN(
1225 qureg: Qureg,
1226 targs: *mut ::std::os::raw::c_int,
1227 numTargs: ::std::os::raw::c_int,
1228 u: ComplexMatrixN,
1229 );
1230}
1231extern "C" {
1232 #[doc = " Apply a gate specified by a general N-by-N matrix, which may be non-unitary, on any number of target qubits.\n This function applies the given matrix to both statevector and density matrices\n as if it were a valid unitary gate.\n Hence this function is equivalent to multiQubitUnitary(), albeit the unitarity\n of \\p u is not checked nor enforced.\n This function differs from applyMatrixN() on density matrices.\n\n This function may leave \\p qureg is an unnormalised state.\n\n @see\n - applyMultiControlledGateMatrixN()\n - applyMatrixN()\n - createComplexMatrixN()\n - getStaticComplexMatrixN()\n - multiQubitUnitary()\n\n @ingroup operator\n @param[in,out] qureg object representing the set of all qubits\n @param[in] targs a list of the target qubits, ordered least significant to most in \\p u\n @param[in] numTargs the number of target qubits\n @param[in] u matrix to apply, which need not be unitary\n @throws invalidQuESTInputError()\n - if any index in \\p targs is outside of [0, \\p qureg.numQubitsRepresented)\n - if \\p targs are not unique\n - if \\p u is not of a compatible size with \\p numTargs\n - if a node cannot fit the required number of target amplitudes in distributed mode\n @author Tyson Jones"]
1233 pub fn applyGateMatrixN(
1234 qureg: Qureg,
1235 targs: *mut ::std::os::raw::c_int,
1236 numTargs: ::std::os::raw::c_int,
1237 u: ComplexMatrixN,
1238 );
1239}
1240extern "C" {
1241 #[doc = " Apply a general multi-controlled multi-qubit gate specified as an (possibly non-unitary)\n arbitrary complex matrix.\n This is equivalent to multiControlledMultiQubitUnitary() but does not check nor enforce\n unitary of the given matrix \\p m.\n This differs from applyMultiControlledMatrixN(), because the latter only left-applies\n the matrix upon density matrices.\n\n Any number of control and target qubits can be specified.\n This effects the many-qubit unitary\n \\f[\n \\begin{pmatrix}\n 1 \\\\\n & 1 \\\\\\\n & & \\ddots \\\\\n & & & m_{00} & m_{01} & \\dots \\\\\n & & & m_{10} & m_{11} & \\dots \\\\\n & & & \\vdots & \\vdots & \\ddots\n \\end{pmatrix}\n \\f]\n on the control and target qubits.\n\n Besides unitarity, the inputs and their preconditions are the same as for\n multiControlledMultiQubitUnitary().\n\n @see\n - createComplexMatrixN()\n - applyMultiControlledMatrixN()\n - multiControlledMultiQubitUnitary()\n\n @ingroup unitary\n @param[in,out] qureg object representing the set of all qubits\n @param[in] ctrls a list of the control qubits\n @param[in] numCtrls the number of control qubits\n @param[in] targs a list of the target qubits, ordered least to most significant\n @param[in] numTargs the number of target qubits\n @param[in] m arbitrary matrix to apply as if it were a unitary gate\n @throws invalidQuESTInputError()\n - if any qubit in \\p ctrls and \\p targs is invalid, i.e. outside <b>[0, </b>`qureg.numQubitsRepresented`<b>)</b>\n - if \\p ctrls or \\p targs contain any repetitions\n - if any qubit in \\p ctrls is also in \\p targs (and vice versa)\n - if \\p numTargs <b>< 1</b>\n - if \\p numCtrls <b>< 1</b> (use multiQubitUnitary() for no controls)\n - if matrix \\p m is not of a compatible size with \\p numTargs\n - if a node cannot fit the required number of target amplitudes in distributed mode\n @throws segmentation-fault\n - if \\p ctrls contains fewer elements than \\p numCtrls\n - if \\p targs contains fewer elements than \\p numTargs\n @author Tyson Jones"]
1242 pub fn applyMultiControlledGateMatrixN(
1243 qureg: Qureg,
1244 ctrls: *mut ::std::os::raw::c_int,
1245 numCtrls: ::std::os::raw::c_int,
1246 targs: *mut ::std::os::raw::c_int,
1247 numTargs: ::std::os::raw::c_int,
1248 m: ComplexMatrixN,
1249 );
1250}
1251extern "C" {
1252 #[doc = " Apply a general N-by-N matrix, which may be non-unitary, with additional controlled qubits.\n The matrix is left-multiplied onto the state, for both state-vectors and density matrices.\n Hence, this function differs from multiControlledMultiQubitUnitary() by more than just permitting a non-unitary\n matrix.\n\n This function may leave \\p qureg is an unnormalised state.\n\n Any number of control and target qubits can be specified.\n This effects the many-qubit matrix\n \\f[\n \\begin{pmatrix}\n 1 \\\\\n & 1 \\\\\\\n & & \\ddots \\\\\n & & & u_{00} & u_{01} & \\dots \\\\\n & & & u_{10} & u_{11} & \\dots \\\\\n & & & \\vdots & \\vdots & \\ddots\n \\end{pmatrix}\n \\f]\n on the control and target qubits.\n\n The target qubits in \\p targs are treated as ordered least significant\n to most significant in \\p u.\n\n The passed ComplexMatrix must be a compatible size with the specified number of\n target qubits, otherwise an error is thrown.\n\n Note that in multithreaded mode, each thread will clone 2^\\p numTargs amplitudes,\n and store these in the runtime stack.\n Using t threads, the total memory overhead of this function is t*2^\\p numTargs.\n For many targets (e.g. 16 qubits), this may cause a stack-overflow / seg-fault\n (e.g. on a 1 MiB stack).\n\n Note that in distributed mode, this routine requires that each node contains at least 2^\\p numTargs amplitudes.\n This means an q-qubit register (state vector or density matrix) can be distributed\n by at most 2^q / 2^\\p numTargs nodes.\n\n @ingroup operator\n @param[in,out] qureg object representing the set of all qubits\n @param[in] ctrls a list of the control qubits\n @param[in] numCtrls the number of control qubits\n @param[in] targs a list of the target qubits, ordered least to most significant\n @param[in] numTargs the number of target qubits\n @param[in] u matrix to apply\n @throws invalidQuESTInputError()\n - if any index in \\p ctrls and \\p targs is outside of [0, \\p qureg.numQubitsRepresented)\n - if \\p ctrls and \\p targs are not unique\n - if matrix \\p u is not a compatible size with \\p numTargs\n - if a node cannot fit the required number of target amplitudes in distributed mode\n @author Tyson Jones"]
1253 pub fn applyMultiControlledMatrixN(
1254 qureg: Qureg,
1255 ctrls: *mut ::std::os::raw::c_int,
1256 numCtrls: ::std::os::raw::c_int,
1257 targs: *mut ::std::os::raw::c_int,
1258 numTargs: ::std::os::raw::c_int,
1259 u: ComplexMatrixN,
1260 );
1261}
1262extern "C" {
1263 #[doc = " Induces a phase change upon each amplitude of \\p qureg, determined by the passed\n exponential polynomial \"phase function\". This effects a diagonal unitary of unit complex scalars,\n targeting the nominated \\p qubits.\n\n - Arguments \\p coeffs and \\p exponents together specify a real exponential polynomial \\f$f(r)\\f$\n with \\p numTerms terms, of the form\n \\f[\n f(r) = \\sum\\limits_{i}^{\\text{numTerms}} \\text{coeffs}[i] \\; r^{\\, \\text{exponents}[i]}\\,,\n \\f]\n where both \\p coeffs and \\p exponents can be negative, positive and fractional.\n For example,\n ```\n qreal coeffs[] = {1, -3.14};\n qreal exponents[] = {2, -5.5};\n int numTerms = 2;\n ```\n constitutes the function\n \\f[\n f(r) = 1 \\, r^2 - 3.14 \\, r^{-5.5}.\n \\f]\n Note you cannot use fractional exponents with \\p encoding <b>=</b> ::TWOS_COMPLEMENT,\n since the negative indices would generate (illegal) complex phases, and must\n be overriden with applyPhaseFuncOverrides(). \\n\n > If your function \\f$f(r)\\f$ diverges at one or more \\f$r\\f$ values, you must instead\n > use applyPhaseFuncOverrides() and specify explicit phase changes for these values.\n > Otherwise, the corresponding amplitudes of the state-vector will become indeterminate (like `NaN`).\n > Note that use of any negative exponent will result in divergences at \\f$r=0\\f$.\n\n - The function \\f$f(r)\\f$ specifies the phase change to induce upon amplitude \\f$\\alpha\\f$\n of computational basis state with index \\f$r\\f$, such that\n \\f[\n \\alpha \\, |r\\rangle \\rightarrow \\, \\exp(i f(r)) \\; \\alpha \\, |r\\rangle.\n \\f]\n The index \\f$r\\f$ associated with each computational basis state is determined by\n the binary value of the specified \\p qubits (ordered least to most significant),\n interpreted under the given ::bitEncoding \\p encoding. \\n\\n\n For example, under \\p encoding <b>=</b> \\p UNSIGNED and \\p qubits <b>= {0,1}</b>,\n \\f[\n \\begin{aligned}\n |0\\mathbf{00}\\rangle & \\rightarrow \\, e^{i f(0)}\\,|0\\mathbf{00}\\rangle \\\\\n |0\\mathbf{01}\\rangle & \\rightarrow \\, e^{i f(1)}\\,|0\\mathbf{01}\\rangle \\\\\n |0\\mathbf{10}\\rangle & \\rightarrow \\, e^{i f(2)}\\,|0\\mathbf{10}\\rangle \\\\\n |0\\mathbf{11}\\rangle & \\rightarrow \\, e^{i f(3)}\\,|0\\mathbf{11}\\rangle \\\\\n |1\\mathbf{00}\\rangle & \\rightarrow \\, e^{i f(0)}\\,|1\\mathbf{00}\\rangle \\\\\n |1\\mathbf{01}\\rangle & \\rightarrow \\, e^{i f(1)}\\,|1\\mathbf{01}\\rangle \\\\\n |1\\mathbf{10}\\rangle & \\rightarrow \\, e^{i f(2)}\\,|1\\mathbf{10}\\rangle \\\\\n |1\\mathbf{11}\\rangle & \\rightarrow \\, e^{i f(3)}\\,|1\\mathbf{11}\\rangle\n \\end{aligned}\n \\f]\n\n - If \\p qureg is a density matrix \\f$\\rho\\f$, this function modifies \\p qureg to\n \\f[\n \\rho \\rightarrow \\hat{D} \\, \\rho \\, \\hat{D}^\\dagger\n \\f]\n where \\f$\\hat{D}\\f$ is the diagonal unitary operator\n \\f[\n \\hat{D} = \\text{diag} \\, \\{ \\; e^{i f(r_0)}, \\; e^{i f(r_1)}, \\; \\dots \\; \\}.\n \\f]\n This means element \\f$\\rho_{jk}\\f$ is modified to\n \\f[\n \\alpha \\, |j\\rangle\\langle k| \\; \\rightarrow \\; e^{i (f(r_j) - f(r_k))} \\; \\alpha \\, |j\\rangle\\langle k|\n \\f]\\n\n\n - The interpreted phase function can be previewed in the QASM log, as a comment. \\n\n For example:\n ```\n startRecordingQASM(qureg);\n applyPhaseFunc(qureg, ...);\n printRecordedQASM(qureg);\n ```\n may show\n ```\n // Here, applyPhaseFunc() multiplied a complex scalar of the form\n // exp(i (1 x^3))\n // upon every substate |x>, informed by qubits (under an unsigned binary encoding)\n // {4, 1, 2, 0}\n ```\n\n > This function may become numerically imprecise for quickly growing phase functions\n > which admit very large phases, for example of 10^10.\n\n @see\n - applyPhaseFuncOverrides() to override the phase function for specific states.\n - applyMultiVarPhaseFunc() for multi-variable exponential polynomial phase functions.\n - applyNamedPhaseFunc() for a set of specific phase functions.\n - applyDiagonalOp() to apply a non-unitary diagonal operator.\n\n @ingroup operator\n @param[in,out] qureg the state-vector or density matrix to be modified\n @param[in] qubits a list of the indices of the qubits which will inform \\f$r\\f$ for each amplitude in \\p qureg\n @param[in] numQubits the length of list \\p qubits\n @param[in] encoding the ::bitEncoding under which to infer the binary value \\f$r\\f$ from the bits of \\p qubits in each basis state of \\p qureg\n @param[in] coeffs the coefficients of the exponential polynomial phase function \\f$f(r)\\f$\n @param[in] exponents the exponents of the exponential polynomial phase function \\f$f(r)\\f$\n @param[in] numTerms the length of list \\p coeffs, which must be the same as that of \\p exponents\n @exception invalidQuESTInputError()\n - if any qubit in \\p qubits has an invalid index (i.e. does not satisfy 0 <= qubit < `qureg.numQubitsRepresented`)\n - if the elements of \\p qubits are not unique\n - if \\p numQubits < 0 or \\p numQubits >= `qureg.numQubitsRepresented`\n - if \\p encoding is not a valid ::bitEncoding\n - if \\p encoding is not compatible with \\p numQubits (e.g. \\p TWOS_COMPLEMENT with only 1 qubit)\n - if \\p exponents contains a fractional number despite \\p encoding <b>=</b> ::TWOS_COMPLEMENT (you must instead use applyPhaseFuncOverrides() and override all negative indices)\n - if \\p exponents contains a negative power (you must instead use applyPhaseFuncOverrides() and override the zero index)\n - if \\p numTerms <= 0\n @author Tyson Jones"]
1264 pub fn applyPhaseFunc(
1265 qureg: Qureg,
1266 qubits: *mut ::std::os::raw::c_int,
1267 numQubits: ::std::os::raw::c_int,
1268 encoding: bitEncoding,
1269 coeffs: *mut f64,
1270 exponents: *mut f64,
1271 numTerms: ::std::os::raw::c_int,
1272 );
1273}
1274extern "C" {
1275 #[doc = " Induces a phase change upon each amplitude of \\p qureg, determined by the passed\n exponential polynomial \"phase function\", and an explicit set of 'overriding' values at specific\n state indices.\n\n See applyPhaseFunc() first for a full description.\n\n - As in applyPhaseFunc(), the arguments \\p coeffs and \\p exponents specify a phase\n function \\f$f(r)\\f$, where \\f$r\\f$ is determined by \\p qubits and \\p encoding for\n each basis state of \\p qureg.\\n\\n\n - Additionally, \\p overrideInds is a list of length \\p numOverrides which specifies\n the values of \\f$r\\f$ for which to explicitly set the induced phase change.\\n\n The overriding phase changes are specified in the corresponding elements of \\p overridePhases.\\n\\n\n For example,\n ```\n int qubits[] = {0,1};\n enum bitEncoding encoding = UNSIGNED;\n\n long long int overrideInds[] = {2};\n qreal overridePhases[] = {M_PI};\n\n applyPhaseFuncOverrides(...);\n ```\n would effect the same diagonal unitary of applyPhaseFunc(), <em>except</em> that all\n instance of \\f$f(r=2)\\f$ are overriden with phase \\f$\\pi\\f$. \\n I.e.\n \\f[\n \\begin{aligned}\n |0\\mathbf{00}\\rangle & \\rightarrow \\, e^{i f(0)}\\,|0\\mathbf{00}\\rangle \\\\\n |0\\mathbf{01}\\rangle & \\rightarrow \\, e^{i f(1)}\\,|0\\mathbf{01}\\rangle \\\\\n |0\\mathbf{10}\\rangle & \\rightarrow \\, e^{i \\pi} \\hspace{12pt} |0\\mathbf{10}\\rangle \\\\\n |0\\mathbf{11}\\rangle & \\rightarrow \\, e^{i f(3)}\\,|0\\mathbf{11}\\rangle \\\\\n |1\\mathbf{00}\\rangle & \\rightarrow \\, e^{i f(0)}\\,|1\\mathbf{00}\\rangle \\\\\n |1\\mathbf{01}\\rangle & \\rightarrow \\, e^{i f(1)}\\,|1\\mathbf{01}\\rangle \\\\\n |1\\mathbf{10}\\rangle & \\rightarrow \\, e^{i \\pi} \\hspace{12pt} |1\\mathbf{10}\\rangle \\\\\n |1\\mathbf{11}\\rangle & \\rightarrow \\, e^{i f(3)}\\,|1\\mathbf{11}\\rangle\n \\end{aligned}\n \\f]\n Note that if \\p encoding <b>=</b> ::TWOS_COMPLEMENT, \\a and \\f$f(r)\\f$ features a\n fractional exponent, then every negative phase index must be overriden. This\n is checked and enforced by QuEST's validation, \\a unless there are more than\n 16 targeted qubits, in which case valid input is assumed (due to an otherwise\n prohibitive performance overhead).\n \\n\n > Overriding phases are checked at each computational basis state of \\p qureg <em>before</em>\n > evaluating the phase function \\f$f(r)\\f$, and hence are useful for avoiding\n > singularities or errors at diverging values of \\f$r\\f$.\n\n - If \\p qureg is a density matrix \\f$\\rho\\f$, the overrides determine the diagonal unitary matrix\n \\f$\\hat{D}\\f$, which is then applied to \\p qureg as\n \\f[\n \\rho \\; \\rightarrow \\; \\hat{D} \\, \\rho \\hat{D}^\\dagger.\n \\f]\n This means that with overrides \\f$f(r_j) \\rightarrow \\theta\\f$ and \\f$f(r_k) \\rightarrow \\phi\\f$,\n element \\f$\\rho_{jk}\\f$ is modified to\n \\f[\n \\alpha \\, |j\\rangle\\langle k| \\; \\rightarrow \\;\n \\exp(\\, i \\, (\\theta - \\phi) \\, ) \\; \\alpha \\, |j\\rangle\\langle k|.\n \\f]\\n\n\n - The interpreted phase function and list of overrides can be previewed in the QASM log, as a comment. \\n\n For example:\n ```\n startRecordingQASM(qureg);\n applyPhaseFunc(qureg, ...);\n printRecordedQASM(qureg);\n ```\n may show\n ```\n // Here, applyPhaseFunc() multiplied a complex scalar of the form\n // exp(i (0.3 x^(-5) + 4 x^1 + 1 x^3))\n // upon every substate |x>, informed by qubits (under a two's complement binary encoding)\n // {4, 1, 2, 0}\n // though with overrides\n // |0> -> exp(i 3.14159)\n // |1> -> exp(i (-3.14159))\n // |2> -> exp(i 0)\n ```\n \\n\n\n\n @see\n - applyPhaseFunc() for full doc on how \\f$f(r)\\f$ is evaluated.\n - applyMultiVarPhaseFunc() for multi-variable exponential polynomial phase functions.\n - applyNamedPhaseFunc() for a set of specific phase functions.\n - applyDiagonalOp() to apply a non-unitary diagonal operator.\n\n @ingroup operator\n @param[in,out] qureg the state-vector or density matrix to be modified\n @param[in] qubits a list of the indices of the qubits which will inform \\f$r\\f$ for each amplitude in \\p qureg\n @param[in] numQubits the length of list \\p qubits\n @param[in] encoding the ::bitEncoding under which to infer the binary value \\f$r\\f$ from the bits of \\p qubits in each basis state of \\p qureg\n @param[in] coeffs the coefficients of the exponential polynomial phase function \\f$f(r)\\f$\n @param[in] exponents the exponents of the exponential polynomial phase function \\f$f(r)\\f$\n @param[in] numTerms the length of list \\p coeffs, which must be the same as that of \\p exponents\n @param[in] overrideInds a list of sub-state indices (values of \\f$r\\f$) of which to explicit set the phase change\n @param[in] overridePhases a list of replacement phase changes, for the corresponding \\f$r\\f$ values in \\p overrideInds (one to one)\n @param[in] numOverrides the lengths of lists \\p overrideInds and \\p overridePhases\n @exception invalidQuESTInputError()\n - if any qubit in \\p qubits has an invalid index (i.e. does not satisfy 0 <= qubit < `qureg.numQubitsRepresented`)\n - if the elements of \\p qubits are not unique\n - if \\p numQubits < 0 or \\p numQubits >= `qureg.numQubitsRepresented`\n - if \\p encoding is not a valid ::bitEncoding\n - if \\p encoding is not compatible with \\p numQubits (i.e. \\p TWOS_COMPLEMENT with 1 qubit)\n - if \\p numTerms <= 0\n - if any value in \\p overrideInds is not producible by \\p qubits under the given \\p encoding (e.g. 2 unsigned qubits cannot represent index 9)\n - if \\p numOverrides < 0\n - if \\p exponents contains a negative power and the (consequently diverging) zero index is not contained in \\p overrideInds\n - if \\p encoding is ::TWOS_COMPLEMENT, and \\p exponents contains a fractional number, but \\p overrideInds does not contain every possible negative index (checked only up to 16 targeted qubits)\n @author Tyson Jones"]
1276 pub fn applyPhaseFuncOverrides(
1277 qureg: Qureg,
1278 qubits: *mut ::std::os::raw::c_int,
1279 numQubits: ::std::os::raw::c_int,
1280 encoding: bitEncoding,
1281 coeffs: *mut f64,
1282 exponents: *mut f64,
1283 numTerms: ::std::os::raw::c_int,
1284 overrideInds: *mut ::std::os::raw::c_longlong,
1285 overridePhases: *mut f64,
1286 numOverrides: ::std::os::raw::c_int,
1287 );
1288}
1289extern "C" {
1290 #[doc = " Induces a phase change upon each amplitude of \\p qureg, determined by a\n multi-variable exponential polynomial \"phase function\".\n\n This is a multi-variable extension of applyPhaseFunc(), whereby multiple sub-registers inform\n separate variables in the exponential polynomial function, and effects a diagonal unitary\n operator.\n\n - Arguments \\p coeffs, \\p exponents and \\p numTermsPerReg together specify a real\n exponential polynomial \\f$f(\\vec{r})\\f$ of the form\n \\f[\n f(r_1, \\; \\dots, \\; r_{\\text{numRegs}}) = \\sum\\limits_j^{\\text{numRegs}} \\; \\sum\\limits_{i}^{\\text{numTermsPerReg}[j]} \\; c_{i,j} \\; {r_j}^{\\; p_{i,j}}\\,,\n \\f]\n where both coefficients \\f$c_{i,j}\\f$ and exponents \\f$p_{i,j}\\f$ can be any real number, subject to constraints described below.\n \\n\\n\n While \\p coeffs and \\p exponents are flat lists, they should be considered grouped into\n #`numRegs` sublists with lengths given by \\p numTermsPerReg (which itself has length \\p numRegs). \\n\\n\n For example,\n ```\n int numRegs = 3;\n qreal coeffs[] = {1, 2, 4, -3.14};\n qreal exponents[] = {2, 1, 5, 0.5 };\n int numTermsPerReg[] = {1, 2, 1 };\n ```\n constitutes the function\n \\f[\n f(\\vec{r}) = 1 \\, {r_1}^2 + 2 \\, {r_2} + 4 \\, {r_2}^{5} - 3.14 \\, {r_3}^{0.5}.\n \\f] \\n\n > This means lists \\p coeffs and \\p exponents should both be of length equal to the sum of \\p numTermsPerReg.\n Unlike applyPhaseFunc(), applyMultiVarPhaseFunc() places additional constraints on the\n exponents in \\f$f(\\vec{r})\\f$, due to the exponentially growing costs of overriding\n diverging indices. Namely:\\n\n -# \\p exponents must not contain a negative number, since this would result in a divergence\n when that register is zero, which would need to be overriden for every other register\n basis state. If \\f$f(\\vec{r})\\f$ must contain a negative exponent, you should instead\n call applyPhaseFuncOverrides() once for each register/variable, and override the\n zero index for the relevant variable. This works, because\n \\f[ \\exp( i \\sum_j f_j(r_j) ) = \\prod_j \\exp(i f_j(r_j) ). \\f]\n -# \\p exponents must not contain a fractional number if \\p endoding <b>=</b> ::TWOS_COMPLEMENT,\n because such a term would produce illegal complex values at negative register indices.\n Similar to the problem above, each negative register index would require overriding at\n every index of the other registers, and hence require an exponential number of overrides.\n Therefore, if \\f$f(\\vec{r})\\f$ must contain a negative exponent, you should instead\n call applyPhaseFuncOverrides() once for each register/variable, and override every\n negative index of each register in turn.\n \\n\\n\n - Lists \\p qubits and \\p numQubitsPerReg together describe #`numRegs` sub-registers of \\p qureg,\n which can each contain a different number of qubits. \\n\n Although \\p qubits is a flat list of unique qubit indices, it should be imagined grouped into #`numRegs` sub-lists,\n of lengths given by \\p numQubitsPerReg. \\n\\n\n For example,\n ```\n int qubits[] = {0,1, 3,4,5, 7}\n int numQubitsPerReg[] = {2, 3, 1};\n int numRegs = 3;\n ```\n describes three sub-registers, which are bolded below in an eight-qubit zero-state.\n \\f[\n |r_3\\rangle \\; |0\\rangle \\; |r_2\\rangle \\; |0\\rangle \\; |r_1\\rangle =\n |\\mathbf{0}\\rangle \\; |0\\rangle \\; |\\mathbf{000}\\rangle \\; |0\\rangle \\; |\\mathbf{00}\\rangle\n \\f]\n Note that the qubits need not be ordered increasing, and qubits within each sub-register\n are assumed ordered least to most significant in that sub-register.\\n\\n\n > List \\p qubits should have length equal to the sum of elements in \\p numQubitsPerReg.\n\n - Each sub-register is associated with a variable \\f$r_j\\f$ in phase function \\f$f(\\vec{r})\\f$. \\n\n For a given computational basis state of \\p qureg, the value of each variable is determined\n by the binary value in the corresponding sub-register, when intepreted with ::bitEncoding \\p encoding. \\n\n See ::bitEncoding for more information.\\n\\n\n\n - The function \\f$f(\\vec{r})\\f$ specifies the phase change to induce upon amplitude \\f$\\alpha\\f$\n of computational basis state with the nominated sub-registers encoding values \\f$r_1, \\; \\dots\\f$.\n \\f[\n \\alpha \\, |r_{\\text{numRegs}}, \\; \\dots, \\; r_2, \\; r_1 \\rangle \\rightarrow \\, \\exp(i f(\\vec{r}\\,)) \\; \\alpha \\, |r_{\\text{numRegs}}, \\; \\dots, \\; r_2, \\; r_1 \\rangle.\n \\f]\n For example, using the sub-registers in the previous example and \\p encoding <b>=</b> \\p UNSIGNED, the\n following states receive amplitude factors:\n \\f[\n \\begin{aligned}\n |\\mathbf{0}\\rangle \\; |0\\rangle \\; |\\mathbf{000}\\rangle \\; |0\\rangle \\; |\\mathbf{00}\\rangle &\n \\rightarrow \\,\n e^{i f(r_3=0,r_2=0,r_1=0)} \\\\\n |\\mathbf{0}\\rangle \\; |0\\rangle \\; |\\mathbf{000}\\rangle \\; |0\\rangle \\; |\\mathbf{01}\\rangle &\n \\rightarrow \\,\n e^{i f(r_3=0,r_2=0,r_1=1)} \\\\\n |\\mathbf{0}\\rangle \\; |0\\rangle \\; |\\mathbf{000}\\rangle \\; |0\\rangle \\; |\\mathbf{10}\\rangle &\n \\rightarrow \\,\n e^{i f(r_3=0,r_2=0,r_1=2)} \\\\\n |\\mathbf{0}\\rangle \\; |0\\rangle \\; |\\mathbf{000}\\rangle \\; |0\\rangle \\; |\\mathbf{11}\\rangle &\n \\rightarrow \\,\n e^{i f(r_3=0,r_2=0,r_1=3)} \\\\\n |\\mathbf{0}\\rangle \\; |0\\rangle \\; |\\mathbf{000}\\rangle \\; |1\\rangle \\; |\\mathbf{00}\\rangle &\n \\rightarrow \\,\n e^{i f(r_3=0,r_2=0,r_1=0)} \\\\\n & \\;\\;\\;\\vdots \\\\\n |\\mathbf{0}\\rangle \\; |0\\rangle \\; |\\mathbf{111}\\rangle \\; |0\\rangle \\; |\\mathbf{01}\\rangle &\n \\rightarrow \\,\n e^{i f(r_3=0,r_2=7,r_1=1)} \\\\\n & \\;\\;\\;\\vdots \\\\\n |\\mathbf{1}\\rangle \\; |0\\rangle \\; |\\mathbf{111}\\rangle \\; |0\\rangle \\; |\\mathbf{11}\\rangle &\n \\rightarrow \\,\n e^{i f(r_3=1,r_2=7,r_1=3)}\n \\end{aligned}\n \\f]\n\n - If \\p qureg is a density matrix \\f$\\rho\\f$, then its elements are modified as\n \\f[\n \\alpha \\, |j\\rangle\\langle k| \\; \\rightarrow \\;\n \\exp(i \\, (f(\\vec{r}_j) - f(\\vec{r}_k)) \\, ) \\; \\alpha \\, |j\\rangle\\langle k|,\n \\f]\n where \\f$f(\\vec{r}_j)\\f$ and \\f$f(\\vec{r}_k)\\f$ are determined as above.\\n\\n\n\n - The interpreted phase function can be previewed in the QASM log, as a comment. \\n\n For example:\n ```\n startRecordingQASM(qureg);\n applyMultiVarPhaseFunc(qureg, ...);\n printRecordedQASM(qureg);\n ```\n would show, for the above example,\n ```\n // Here, applyMultiVarPhaseFunc() multiplied a complex scalar of the form\n // exp(i (\n // + 1 x^2\n // + 2 y + 4 y^(-1)\n // - 3.14 z^0.5 ))\n // upon substates informed by qubits (under an unsigned binary encoding)\n // |x> = {0, 1}\n // |y> = {3, 4, 5}\n // |z> = {7}\n ```\n \\n\n\n\n @see\n - applyMultiVarPhaseFuncOverrides() to additionally specify explicit phases for specific sub-register values.\n - applyNamedPhaseFunc() for a set of specific and potentially multi-variable phase functions.\n - applyPhaseFunc() for a single-variable polynomial exponential phase function, which is approximately twice as fast.\n - applyDiagonalOp() to apply a non-unitary diagonal operator.\n\n @ingroup operator\n @param[in,out] qureg the state-vector or density matrix to be modified\n @param[in] qubits a list of all the qubit indices contained in each sub-register\n @param[in] numQubitsPerReg a list of the lengths of each sub-list in \\p qubits\n @param[in] numRegs the number of sub-registers, which is the length of both \\p numQubitsPerReg and \\p numTermsPerReg\n @param[in] encoding the ::bitEncoding under which to infer the binary value \\f$r_j\\f$ from the bits of a sub-register\n @param[in] coeffs the coefficients of all terms of the exponential polynomial phase function \\f$f(\\vec{r})\\f$\n @param[in] exponents the exponents of all terms of the exponential polynomial phase function \\f$f(\\vec{r})\\f$\n @param[in] numTermsPerReg a list of the number of \\p coeff and \\p exponent terms supplied for each variable/sub-register\n @exception invalidQuESTInputError()\n - if any qubit in \\p qubits has an invalid index (i.e. does not satisfy 0 <= qubit < `qureg.numQubitsRepresented`)\n - if the elements of \\p qubits are not unique (including if sub-registers overlap)\n - if \\p numRegs <= 0 or \\p numRegs > 100 (constrained by `MAX_NUM_REGS_APPLY_ARBITRARY_PHASE` in QuEST_precision.h)\n - if \\p encoding is not a valid ::bitEncoding\n - if the size of any sub-register is incompatible with \\p encoding (e.g. contains fewer than two qubits in \\p encoding <b>=</b> \\p TWOS_COMPLEMENT)\n - if any element of \\p numTermsPerReg is < 1\n - if \\p exponents contains a negative number\n - if \\p exponents contains a fractional number despite \\p encoding <b>=</b> ::TWOS_COMPLEMENT\n @author Tyson Jones"]
1291 pub fn applyMultiVarPhaseFunc(
1292 qureg: Qureg,
1293 qubits: *mut ::std::os::raw::c_int,
1294 numQubitsPerReg: *mut ::std::os::raw::c_int,
1295 numRegs: ::std::os::raw::c_int,
1296 encoding: bitEncoding,
1297 coeffs: *mut f64,
1298 exponents: *mut f64,
1299 numTermsPerReg: *mut ::std::os::raw::c_int,
1300 );
1301}
1302extern "C" {
1303 #[doc = " Induces a phase change upon each amplitude of \\p qureg, determined by a\n multi-variable exponential polynomial \"phase function\", and an explicit set of 'overriding'\n values at specific state indices.\n\n See applyMultiVarPhaseFunc() first for a full description.\n\n - As in applyMultiVarPhaseFunc(), the arguments \\p coeffs and \\p exponents specify a\n multi-variable phase function \\f$f(\\vec{r})\\f$, where \\f$\\vec{r}\\f$ is determined by\n the sub-registers in \\p qubits, and ::bitEncoding \\p encoding for each basis state of \\p qureg.\\n\\n\n\n - Additionally, \\p overrideInds is a list of length \\p numOverrides which specifies\n the values of \\f$\\vec{r}\\f$ for which to explicitly set the induced phase change.\\n\n While flat, \\p overrideInds should be imagined grouped into sub-lists of length\n \\p numRegs, which specify the full \\f$\\{r_1,\\; \\dots \\;r_{\\text{numRegs}} \\} \\f$ coordinate to override. \\n\n Each sublist corresponds to a single element of \\p overridePhases. \\n\n For example,\n ```\n int numRegs = 3;\n int numOverrides = 2;\n long long int overrideInds[] = { 0,0,0, 1,2,3 };\n qreal overridePhases[] = { M_PI, - M_PI };\n ```\n denotes that any basis state of \\p qureg with sub-register values \\f$\\{r_3,r_2,r_1\\} = \\{0, 0, 0\\}\\f$\n (or \\f$\\{r_3,r_2,r_1\\} = \\{1,2,3\\}\\f$) should receive phase change \\f$\\pi\\f$ (or \\f$-\\pi\\f$)\n in lieu of \\f$\\exp(i f(r_3=0,r_2=0,r_1=0))\\f$.\\n\\n\n > Note that you cannot use applyMultiVarPhaseFuncOverrides() to override divergences\n > in \\f$f(\\vec{r})\\f$, since each diverging value \\f$r_j\\f$ would need to be overriden\n > as an \\f$\\vec{r}\\f$ coordinate for every basis state of the other registers; the number\n > of overrides grows exponentially. Ergo, if \\p exponents contains a negative number\n > (diverging at \\f$r_j=0\\f$), or \\p exponents contains a fractional number despite\n > \\p encoding <b>=</b> ::TWOS_COMPLEMENT (producing complex phases at negative indices),\n > you must instead call applyPhaseFuncOverrides() for each variable in turn and\n > override the diverging \\f$r_j\\f$ (each independently of the other registers).\n\n - The interpreted overrides can be previewed in the QASM log, as a comment. \\n\n For example:\n ```\n startRecordingQASM(qureg);\n applyMultiVarPhaseFuncOverrides(qureg, ...);\n printRecordedQASM(qureg);\n ```\n may show\n ```\n // Here, applyMultiVarPhaseFunc() multiplied ...\n // though with overrides\n // |x=0, y=0, z=0> -> exp(i 3.14159)\n // |x=1, y=2, z=3> -> exp(i (-3.14159))\n ```\n \\n\n\n\n @see\n - applyNamedPhaseFunc() for a set of specific and potentially multi-variable phase functions.\n - applyDiagonalOp() to apply a non-unitary diagonal operator.\n\n @ingroup operator\n @param[in,out] qureg the state-vector or density-matrix to be modified\n @param[in] qubits a list of all the qubit indices contained in each sub-register\n @param[in] numQubitsPerReg a list of the lengths of each sub-list in \\p qubits\n @param[in] numRegs the number of sub-registers, which is the length of both \\p numQubitsPerReg and \\p numTermsPerReg\n @param[in] encoding the ::bitEncoding under which to infer the binary value \\f$r_j\\f$ from the bits of a sub-register\n @param[in] coeffs the coefficients of all terms of the exponential polynomial phase function \\f$f(\\vec{r})\\f$\n @param[in] exponents the exponents of all terms of the exponential polynomial phase function \\f$f(\\vec{r})\\f$\n @param[in] numTermsPerReg a list of the number of \\p coeff and \\p exponent terms supplied for each variable/sub-register\n @param[in] overrideInds a flattened list of sub-register coordinates (values of \\f$\\vec{r}\\f$) of which to explicit set the phase change\n @param[in] overridePhases a list of replacement phase changes, for the corresponding \\f$\\vec{r}\\f$ values in \\p overrideInds\n @param[in] numOverrides the lengths of list \\p overridePhases (but not necessarily of \\p overrideInds)\n @exception invalidQuESTInputError()\n - if any qubit in \\p qubits has an invalid index (i.e. does not satisfy 0 <= qubit < `qureg.numQubitsRepresented`)\n - if the elements of \\p qubits are not unique (including if sub-registers overlap)\n - if \\p numRegs <= 0 or \\p numRegs > 100 (constrained by `MAX_NUM_REGS_APPLY_ARBITRARY_PHASE` in QuEST_precision.h)\n - if \\p encoding is not a valid ::bitEncoding\n - if the size of any sub-register is incompatible with \\p encoding (e.g. contains fewer than two qubits in \\p encoding <b>=</b> \\p TWOS_COMPLEMENT)\n - if any element of \\p numTermsPerReg is < 1\n - if \\p exponents contains a negative number\n - if \\p exponents contains a fractional number despite \\p encoding <b>=</b> ::TWOS_COMPLEMENT\n - if any value in \\p overrideInds is not producible by its corresponding sub-register under the given \\p encoding (e.g. 2 unsigned qubits cannot represent index 9)\n - if \\p numOverrides < 0\n @author Tyson Jones"]
1304 pub fn applyMultiVarPhaseFuncOverrides(
1305 qureg: Qureg,
1306 qubits: *mut ::std::os::raw::c_int,
1307 numQubitsPerReg: *mut ::std::os::raw::c_int,
1308 numRegs: ::std::os::raw::c_int,
1309 encoding: bitEncoding,
1310 coeffs: *mut f64,
1311 exponents: *mut f64,
1312 numTermsPerReg: *mut ::std::os::raw::c_int,
1313 overrideInds: *mut ::std::os::raw::c_longlong,
1314 overridePhases: *mut f64,
1315 numOverrides: ::std::os::raw::c_int,
1316 );
1317}
1318extern "C" {
1319 #[doc = " Induces a phase change upon each amplitude of \\p qureg, determined by a\n named (and potentially multi-variable) phase function.\n\n This effects a diagonal unitary operator, with a phase function \\f$f(\\vec{r})\\f$ which may not be\n simply expressible as an exponential polynomial in functions applyPhaseFunc() and applyMultiVarPhaseFunc().\n\n Arguments \\p qubits and \\p numQubitsPerReg encode sub-registers of \\p qureg in the same\n manner as in applyMultiVarPhaseFunc():\n - Lists \\p qubits and \\p numQubitsPerReg together describe #`numRegs` sub-registers of \\p qureg,\n which can each contain a different number of qubits. \\n\n Although \\p qubits is a flat list of unique qubit indices, it should be imagined grouped into #`numRegs` sub-lists,\n of lengths given by \\p numQubitsPerReg. \\n\\n\n For example,\n ```\n int qubits[] = {0,1, 3,4,5, 7}\n int numQubitsPerReg[] = {2, 3, 1};\n int numRegs = 3;\n ```\n describes three sub-registers, which are bolded below in an eight-qubit zero-state.\n \\f[\n |r_3\\rangle \\; |0\\rangle \\; |r_2\\rangle \\; |0\\rangle \\; |r_1\\rangle =\n |\\mathbf{0}\\rangle \\; |0\\rangle \\; |\\mathbf{000}\\rangle \\; |0\\rangle \\; |\\mathbf{00}\\rangle\n \\f]\n Note that the qubits need not be ordered increasing, and qubits within each sub-register\n are assumed ordered least to most significant in that sub-register.\\n\\n\n > List \\p qubits should have length equal to the sum of elements in \\p numQubitsPerReg.\n\n - Each sub-register is associated with a variable \\f$r_j\\f$ in phase function \\f$f(\\vec{r})\\f$. \\n\n For a given computational basis state of \\p qureg, the value of each variable is determined\n by the binary value in the corresponding sub-register, when intepreted with ::bitEncoding \\p encoding. \\n\n See ::bitEncoding for more information.\\n\\n\n\n - Argument \\p functionNameCode determines the phase function \\f$f(\\vec{r})\\f$.\\n\n For example,\n ```\n int numRegs = 3;\n enum phaseFunc functionNameCode = NORM;\n ```\n describes phase function\n \\f[\n f(\\vec{r}) = \\sqrt{ {r_1}^2 + {r_2}^2 + {r_3} ^2 }.\n \\f]\n See ::phaseFunc for a list and description of all named phase functions. \\n\n Some phase functions, like \\p SCALED_NORM, require passing additional parameters, through\n the function applyParamNamedPhaseFunc().\\n\\n\n > If the phase function \\f$f(\\vec{r})\\f$ diverges at one or more \\f$\\vec{r}\\f$ values, you should instead\n > use applyNamedPhaseFuncOverrides() and specify explicit phase changes for these coordinates.\n > Otherwise, the corresponding amplitudes of \\p qureg will become indeterminate (like `NaN`). \\n\n\n - The function \\f$f(\\vec{r})\\f$ specifies the phase change to induce upon amplitude \\f$\\alpha\\f$\n of computational basis state with the nominated sub-registers encoding values \\f$r_1, \\; \\dots\\f$.\n \\f[\n \\alpha \\, |r_{\\text{numRegs}}, \\; \\dots, \\; r_2, \\; r_1 \\rangle \\rightarrow \\, \\exp(i f(\\vec{r}\\,)) \\; \\alpha \\, |r_{\\text{numRegs}}, \\; \\dots, \\; r_2, \\; r_1 \\rangle.\n \\f]\n For example, using the sub-registers in the above example and \\p encoding <b>=</b> \\p UNSIGNED, the\n following states receive amplitude factors:\n \\f[\n \\begin{aligned}\n |\\mathbf{0}\\rangle \\; |0\\rangle \\; |\\mathbf{000}\\rangle \\; |0\\rangle \\; |\\mathbf{00}\\rangle &\n \\rightarrow \\,\n e^{i f(r_3=0,r_2=0,r_1=0)} \\\\\n |\\mathbf{0}\\rangle \\; |0\\rangle \\; |\\mathbf{000}\\rangle \\; |0\\rangle \\; |\\mathbf{01}\\rangle &\n \\rightarrow \\,\n e^{i f(r_3=0,r_2=0,r_1=1)} \\\\\n |\\mathbf{0}\\rangle \\; |0\\rangle \\; |\\mathbf{000}\\rangle \\; |0\\rangle \\; |\\mathbf{10}\\rangle &\n \\rightarrow \\,\n e^{i f(r_3=0,r_2=0,r_1=2)} \\\\\n |\\mathbf{0}\\rangle \\; |0\\rangle \\; |\\mathbf{000}\\rangle \\; |0\\rangle \\; |\\mathbf{11}\\rangle &\n \\rightarrow \\,\n e^{i f(r_3=0,r_2=0,r_1=3)} \\\\\n |\\mathbf{0}\\rangle \\; |0\\rangle \\; |\\mathbf{000}\\rangle \\; |1\\rangle \\; |\\mathbf{00}\\rangle &\n \\rightarrow \\,\n e^{i f(r_3=0,r_2=0,r_1=0)} \\\\\n & \\;\\;\\;\\vdots \\\\\n |\\mathbf{0}\\rangle \\; |0\\rangle \\; |\\mathbf{111}\\rangle \\; |0\\rangle \\; |\\mathbf{01}\\rangle &\n \\rightarrow \\,\n e^{i f(r_3=0,r_2=7,r_1=1)} \\\\\n & \\;\\;\\;\\vdots \\\\\n |\\mathbf{1}\\rangle \\; |0\\rangle \\; |\\mathbf{111}\\rangle \\; |0\\rangle \\; |\\mathbf{11}\\rangle &\n \\rightarrow \\,\n e^{i f(r_3=1,r_2=7,r_1=3)}\n \\end{aligned}\n \\f]\\n\n\n - If \\p qureg is a density matrix, its elements are modified to\n \\f[\n\\alpha \\, |j\\rangle\\langle k| \\; \\rightarrow \\;\n\\exp(i (f(\\vec{r}_j) \\, - \\, f(\\vec{r}_k))) \\; \\alpha \\, |j\\rangle\\langle k|\n \\f]\n where \\f$f(\\vec{r}_j)\\f$ and \\f$f(\\vec{r}_k)\\f$ are determined as above. This is equivalent\n to modification\n \\f[\n \\rho \\; \\rightarrow \\; \\hat{D} \\, \\rho \\, \\hat{D}^\\dagger\n \\f]\n where \\f$\\hat{D}\\f$ is the diagonal unitary\n \\f[\n \\hat{D} = \\text{diag}\\, \\{ \\; e^{i f(\\vec{r_0})}, \\; e^{i f(\\vec{r_1})}, \\; \\dots \\; \\}.\n \\f]\\n\n\n - The interpreted phase function can be previewed in the QASM log, as a comment. \\n\n For example:\n ```\n startRecordingQASM(qureg);\n applyNamedPhaseFunc(qureg, ..., INVERSE_DISTANCE, ... );\n printRecordedQASM(qureg);\n ```\n may show\n ```\n // Here, applyNamedPhaseFunc() multiplied a complex scalar of form\n // exp(i 1 / sqrt((x-y)^2 + (z-t)^2))\n ```\n \\n\n\n\n @see\n - applyNamedPhaseFuncOverrides() to additionally specify phase values for specific sub-register indices.\n - applyParamNamedPhaseFunc() to specify named phase functions which require additional parameters.\n - applyPhaseFunc() to specify a general single-variable exponential polynomial phase function.\n - applyMultiVarPhaseFunc() to specify a general multi-variable exponential polynomial phase function.\n - applyDiagonalOp() to apply a non-unitary diagonal operator.\n\n @ingroup operator\n @param[in,out] qureg the state-vector or density-matrix to be modified\n @param[in] qubits a list of all the qubit indices contained in each sub-register\n @param[in] numQubitsPerReg a list of the lengths of each sub-list in \\p qubits\n @param[in] numRegs the number of sub-registers, which is the length of both \\p numQubitsPerReg and \\p numTermsPerReg\n @param[in] encoding the ::bitEncoding under which to infer the binary value \\f$r_j\\f$ from the bits of a sub-register\n @param[in] functionNameCode the ::phaseFunc \\f$f(\\vec{r})\\f$\n @exception invalidQuESTInputError()\n - if any qubit in \\p qubits has an invalid index (i.e. does not satisfy 0 <= qubit < `qureg.numQubitsRepresented`)\n - if the elements of \\p qubits are not unique (including if sub-registers overlap)\n - if \\p numRegs <= 0 or \\p numRegs > 100 (constrained by `MAX_NUM_REGS_APPLY_ARBITRARY_PHASE` in QuEST_precision.h)\n - if \\p encoding is not a valid ::bitEncoding\n - if the size of any sub-register is incompatible with \\p encoding (e.g. contains fewer than two qubits in \\p encoding <b>=</b> \\p TWOS_COMPLEMENT)\n - if \\p functionNameCode is not a valid ::phaseFunc\n - if \\p functionNameCode requires additional parameters, which must instead be passed with applyParamNamedPhaseFunc()\n @author Tyson Jones"]
1320 pub fn applyNamedPhaseFunc(
1321 qureg: Qureg,
1322 qubits: *mut ::std::os::raw::c_int,
1323 numQubitsPerReg: *mut ::std::os::raw::c_int,
1324 numRegs: ::std::os::raw::c_int,
1325 encoding: bitEncoding,
1326 functionNameCode: phaseFunc,
1327 );
1328}
1329extern "C" {
1330 #[doc = " Induces a phase change upon each amplitude of \\p qureg, determined by a\n named (and potentially multi-variable) phase function, and an explicit set of 'overriding'\n values at specific state indices.\n\n See applyNamedPhaseFunc() first for a full description.\n\n - As in applyNamedPhaseFunc(), \\p functionNameCode specifies a\n multi-variable phase function \\f$f(\\vec{r})\\f$, where \\f$\\vec{r}\\f$ is determined by\n the sub-registers in \\p qubits, and ::bitEncoding \\p encoding for each basis state of \\p qureg.\\n\\n\n\n - Additionally, \\p overrideInds is a list of length \\p numOverrides which specifies\n the values of \\f$\\vec{r}\\f$ for which to explicitly set the induced phase change.\\n\n While flat, \\p overrideInds should be imagined grouped into sub-lists of length\n \\p numRegs, which specify the full \\f$\\{r_1,\\; \\dots \\;r_{\\text{numRegs}} \\} \\f$ coordinate to override. \\n\n Each sublist corresponds to a single element of \\p overridePhases. \\n\n For example,\n ```\n int numRegs = 3;\n int numOverrides = 2;\n long long int overrideInds[] = { 0,0,0, 1,2,3 };\n qreal overridePhases[] = { M_PI, - M_PI };\n ```\n denotes that any basis state of \\p qureg with sub-register values \\f$\\{r_3,r_2,r_1\\} = \\{0, 0, 0\\}\\f$\n (or \\f$\\{r_3,r_2,r_1\\} = \\{1,2,3\\}\\f$) should receive phase change \\f$\\pi\\f$ (or \\f$-\\pi\\f$)\n in lieu of \\f$\\exp(i f(r_3=0,r_2=0,r_1=0))\\f$.\\n\\n\n\n - The interpreted overrides can be previewed in the QASM log, as a comment. \\n\n For example:\n ```\n startRecordingQASM(qureg);\n applyNamedPhaseFuncOverrides(qureg, ...);\n printRecordedQASM(qureg);\n ```\n may show\n ```\n // Here, applyNamedPhaseFunc() multiplied ...\n // though with overrides\n // |x=0, y=0, z=0> -> exp(i 3.14159)\n // |x=1, y=2, z=3> -> exp(i (-3.14159))\n ```\n \\n\n\n\n @see\n - applyParamNamedPhaseFuncOverrides() to specify <em>parameterised</em> named phase functions, with phase overrides.\n - applyPhaseFunc() to specify a general single-variable exponential polynomial phase function.\n - applyMultiVarPhaseFunc() to specify a general multi-variable exponential polynomial phase function.\n - applyDiagonalOp() to apply a non-unitary diagonal operator.\n\n @ingroup operator\n @param[in,out] qureg the state-vector pr density-matrix to be modified\n @param[in] qubits a list of all the qubit indices contained in each sub-register\n @param[in] numQubitsPerReg a list of the lengths of each sub-list in \\p qubits\n @param[in] numRegs the number of sub-registers, which is the length of both \\p numQubitsPerReg and \\p numTermsPerReg\n @param[in] encoding the ::bitEncoding under which to infer the binary value \\f$r_j\\f$ from the bits of a sub-register\n @param[in] functionNameCode the ::phaseFunc \\f$f(\\vec{r})\\f$\n @param[in] overrideInds a flattened list of sub-register coordinates (values of \\f$\\vec{r}\\f$) of which to explicit set the phase change\n @param[in] overridePhases a list of replacement phase changes, for the corresponding \\f$\\vec{r}\\f$ values in \\p overrideInds\n @param[in] numOverrides the lengths of list \\p overridePhases (but not necessarily of \\p overrideInds)\n @exception invalidQuESTInputError()\n - if any qubit in \\p qubits has an invalid index (i.e. does not satisfy 0 <= qubit < `qureg.numQubitsRepresented`)\n - if the elements of \\p qubits are not unique (including if sub-registers overlap)\n - if \\p numRegs <= 0 or \\p numRegs > 100 (constrained by `MAX_NUM_REGS_APPLY_ARBITRARY_PHASE` in QuEST_precision.h)\n - if \\p encoding is not a valid ::bitEncoding\n - if the size of any sub-register is incompatible with \\p encoding (e.g. contains fewer than two qubits in \\p encoding <b>=</b> \\p TWOS_COMPLEMENT)\n - if \\p functionNameCode is not a valid ::phaseFunc\n - if \\p functionNameCode requires additional parameters, which must instead be passed with applyParamNamedPhaseFunc()\n - if any value in \\p overrideInds is not producible by its corresponding sub-register under the given \\p encoding (e.g. 2 unsigned qubits cannot represent index 9)\n - if \\p numOverrides < 0\n @author Tyson Jones"]
1331 pub fn applyNamedPhaseFuncOverrides(
1332 qureg: Qureg,
1333 qubits: *mut ::std::os::raw::c_int,
1334 numQubitsPerReg: *mut ::std::os::raw::c_int,
1335 numRegs: ::std::os::raw::c_int,
1336 encoding: bitEncoding,
1337 functionNameCode: phaseFunc,
1338 overrideInds: *mut ::std::os::raw::c_longlong,
1339 overridePhases: *mut f64,
1340 numOverrides: ::std::os::raw::c_int,
1341 );
1342}
1343extern "C" {
1344 #[doc = " Induces a phase change upon each amplitude of \\p qureg, determined by a\n named, paramaterized (and potentially multi-variable) phase function.\n\n See applyNamedPhaseFunc() for full documentation. \\n\n This function merely accepts additional ::phaseFunc names which accept one (or more) parameters.\n\n - Argument \\p functionNameCode, which determines the phase function \\f$f(\\vec{r}, \\vec{\\theta})\\f$,\n can include parameterised ::phaseFunc names like \\p SCALED_NORM, which require additional\n parameters \\f$\\vec{\\theta}\\f$ passed via list \\p params.\\n\n For example,\n ```\n enum phaseFunc functionNameCode = SCALED_PRODUCT;\n qreal params[] = {0.5};\n int numParams = 1;\n applyParamNamedPhaseFunc(..., functionNameCode, params, numParams);\n ```\n invokes phase function\n \\f[\n f(\\vec{r}, \\theta)|_{\\theta=0.5} \\; = \\; 0.5 \\prod_j^{\\text{numRegs}} \\; r_j\\,.\n \\f]\n See ::phaseFunc for all named phased functions.\n\n - Functions with divergences, like \\p INVERSE_NORM and \\p SCALED_INVERSE_DISTANCE, must accompany\n an extra parameter to specify an overriding phase at the divergence. For example,\n ```\n enum phaseFunc functionNameCode = SCALED_INVERSE_NORM;\n qreal params[] = {0.5, M_PI};\n int numParams = 2;\n applyParamNamedPhaseFunc(..., functionNameCode, params, numParams);\n ```\n invokes phase function\n \\f[\n f(\\vec{r}, \\theta)|_{\\theta=0.5} \\; = \\; \\begin{cases} \\pi & \\;\\;\\; \\vec{r}=\\vec{0} \\\\ \\displaystyle 0.5 \\left[ \\sum_j^{\\text{numRegs}} {r_j}^2 \\right]^{-1/2} & \\;\\;\\;\\text{otherwise} \\end{cases}.\n \\f]\n Notice the order of the parameters matches the order of the words in the \\p phaseFunc.\n > Functions \\p SCALED_INVERSE_SHIFTED_NORM and \\p SCALED_INVERSE_SHIFTED_DISTANCE,\n > which can have denominators arbitrarily close to zero, will invoke the\n > divergence parameter whenever the denominator is smaller than (or equal to)\n > machine precision `REAL_EPS`.\n\n - Functions allowing the shifting of unweighted sub-register values, which are \\p SCALED_INVERSE_SHIFTED_NORM,\n and \\p SCALED_INVERSE_SHIFTED_DISTANCE, need these shift values to be passed in the \\p params\n argument _after_ the scaling and divergence override parameters listed above. The function\n \\p SCALED_INVERSE_SHIFTED_NORM needs as many extra parameters, as there are sub-registers;\n \\p SCALED_INVERSE_SHIFTED_DISTANCE needs one extra parameter for each pair of sub-registers.\n For example,\n ```\n enum phaseFunc functionNameCode = SCALED_INVERSE_SHIFTED_NORM;\n int qubits[] = {0,1,2,3, 4,5,6,7};\n int qubitsPerReg[] = {4, 4};\n qreal params[] = {0.5, M_PI, 0.8, -0.3};\n int numParams = 4;\n applyParamNamedPhaseFunc(..., qubits, qubitsPerReg, 2, ..., functionNameCode, params, numParams);\n ```\n invokes phase function\n \\f[\n f(\\vec{r}) \\; = \\; \\begin{cases} \\pi & \\;\\;\\; \\vec{r}=\\vec{0} \\\\ \\displaystyle 0.5 \\left[(r_1-0.8)^2 + (r_2+0.3)^2\\right]^{-1/2} & \\;\\;\\;\\text{otherwise} \\end{cases}.\n \\f]\n and\n ```\n enum phaseFunc functionNameCode = SCALED_INVERSE_SHIFTED_DISTANCE;\n int qubits[] = {0,1, 2,3, 4,5, 6,7};\n int qubitsPerReg[] = {2, 2, 2, 2};\n qreal params[] = {0.5, M_PI, 0.8, -0.3};\n int numParams = 4;\n applyParamNamedPhaseFunc(..., qubits, qubitsPerReg, 4, ..., functionNameCode, params, numParams);\n ```\n invokes phase function\n \\f[\n f(\\vec{r}) \\; = \\; \\begin{cases} \\pi & \\;\\;\\; \\vec{r}=\\vec{0} \\\\ \\displaystyle 0.5 \\left[(r_1-r_2-0.8)^2 + (r_3-r_4+0.3)^2\\right]^{-1/2} & \\;\\;\\;\\text{otherwise} \\end{cases}.\n \\f]\n\n - Function \\p SCALED_INVERSE_SHIFTED_WEIGHTED_DISTANCE, which effects phase\n \\f[\n \\text{coeff}/\\sqrt{f_x \\, (x_1-x_2-\\Delta_x)^2 + f_y \\; (y_1-y_2-\\Delta_y)^2 + \\dots}\n \\f]\n (and phase \\f$\\phi\\f$ at divergences)\n accepts parameters in the following order:\n \\f[\n \\{ \\; \\text{coeff}, \\; \\phi, \\; f_x, \\; \\Delta x, \\; f_y, \\; \\Delta y, \\; \\dots \\; \\}\n \\f]\n > Note that where the denominator's \\f$\\text{sqrt}\\f$ argument would be negative (and the resulting\n > phase function _complex_), the phase is instead set to the divergence parameter \\f$\\phi\\f$.\n\n > You can further override \\f$f(\\vec{r}, \\vec{\\theta})\\f$ at one or more \\f$\\vec{r}\\f$ values\n > via applyParamNamedPhaseFuncOverrides().\n\n - The interpreted parameterised phase function can be previewed in the QASM log, as a comment. \\n\n For example:\n ```\n startRecordingQASM(qureg);\n applyParamNamedPhaseFunc(...);\n printRecordedQASM(qureg);\n ```\n may show\n ```\n // Here, applyNamedPhaseFunc() multiplied a complex scalar of form\n // exp(i (-0.5) / (x y z))\n ```\n \\n\n\n\n @see\n - applyParamNamedPhaseFuncOverrides() to additionally specify phase values for specific sub-register indices.\n - applyPhaseFunc() to specify a general single-variable exponential polynomial phase function.\n - applyMultiVarPhaseFunc() to specify a general multi-variable exponential polynomial phase function.\n - applyDiagonalOp() to apply a non-unitary diagonal operator.\n\n @ingroup operator\n @param[in,out] qureg the state-vector or density-matrix to be modified\n @param[in] qubits a list of all the qubit indices contained in each sub-register\n @param[in] numQubitsPerReg a list of the lengths of each sub-list in \\p qubits\n @param[in] numRegs the number of sub-registers, which is the length of both \\p numQubitsPerReg and \\p numTermsPerReg\n @param[in] encoding the ::bitEncoding under which to infer the binary value \\f$r_j\\f$ from the bits of a sub-register\n @param[in] functionNameCode the ::phaseFunc \\f$f(\\vec{r}, \\vec{\\theta})\\f$\n @param[in] params a list of any additional parameters needed by the ::phaseFunc \\p functionNameCode\n @param[in] numParams the length of list \\p params\n @exception invalidQuESTInputError()\n - if any qubit in \\p qubits has an invalid index (i.e. does not satisfy 0 <= qubit < `qureg.numQubitsRepresented`)\n - if the elements of \\p qubits are not unique (including if sub-registers overlap)\n - if \\p numRegs <= 0 or \\p numRegs > 100 (constrained by `MAX_NUM_REGS_APPLY_ARBITRARY_PHASE` in QuEST_precision.h)\n - if \\p encoding is not a valid ::bitEncoding\n - if the size of any sub-register is incompatible with \\p encoding (e.g. contains fewer than two qubits in \\p encoding <b>=</b> \\p TWOS_COMPLEMENT)\n - if \\p functionNameCode is not a valid ::phaseFunc\n - if \\p numParams is incompatible with \\p functionNameCode (for example, no parameters were passed to \\p SCALED_PRODUCT)\n @author Tyson Jones\n @author Richard Meister (shifted functions)"]
1345 pub fn applyParamNamedPhaseFunc(
1346 qureg: Qureg,
1347 qubits: *mut ::std::os::raw::c_int,
1348 numQubitsPerReg: *mut ::std::os::raw::c_int,
1349 numRegs: ::std::os::raw::c_int,
1350 encoding: bitEncoding,
1351 functionNameCode: phaseFunc,
1352 params: *mut f64,
1353 numParams: ::std::os::raw::c_int,
1354 );
1355}
1356extern "C" {
1357 #[doc = " Induces a phase change upon each amplitude of \\p qureg, determined by a\n named, parameterised (and potentially multi-variable) phase function, and an explicit set of 'overriding'\n values at specific state indices.\n\n See applyParamNamedPhaseFunc() and applyNamedPhaseFunc() first for a full description.\n\n - As in applyParamNamedPhaseFunc(), \\p functionNameCode specifies a parameterised\n multi-variable phase function \\f$f(\\vec{r}, \\vec{\\theta})\\f$, where \\f$\\vec{\\theta}\\f$ is\n passed in list \\p params, and \\f$\\vec{r}\\f$ is determined both by\n the sub-registers in \\p qubits, and ::bitEncoding \\p encoding for each basis state of \\p qureg.\\n\\n\n\n - Additionally, \\p overrideInds is a list of length \\p numOverrides which specifies\n the values of \\f$\\vec{r}\\f$ for which to explicitly set the induced phase change.\\n\n While flat, \\p overrideInds should be imagined grouped into sub-lists of length\n \\p numRegs, which specify the full \\f$\\{r_1,\\; \\dots \\;r_{\\text{numRegs}} \\} \\f$ coordinate to override. \\n\n Each sublist corresponds to a single element of \\p overridePhases. \\n\n For example,\n ```\n int numRegs = 3;\n int numOverrides = 2;\n long long int overrideInds[] = { 0,0,0, 1,2,3 };\n qreal overridePhases[] = { M_PI, - M_PI };\n ```\n denotes that any basis state of \\p qureg with sub-register values \\f$\\{r_3,r_2,r_1\\} = \\{0, 0, 0\\}\\f$\n (or \\f$\\{r_3,r_2,r_1\\} = \\{1,2,3\\}\\f$) should receive phase change \\f$\\pi\\f$ (or \\f$-\\pi\\f$)\n in lieu of \\f$\\exp(i f(r_3=0,r_2=0,r_1=0, \\vec{\\theta}))\\f$.\\n\\n\n\n - The interpreted overrides can be previewed in the QASM log, as a comment. \\n\n For example:\n ```\n startRecordingQASM(qureg);\n applyParamNamedPhaseFuncOverrides(qureg, ...);\n printRecordedQASM(qureg);\n ```\n may show\n ```\n // Here, applyParamNamedPhaseFunc() multiplied ...\n // though with overrides\n // |x=0, y=0, z=0> -> exp(i 3.14159)\n // |x=1, y=2, z=3> -> exp(i (-3.14159))\n ```\n \\n\n\n\n @see\n - applyPhaseFunc() to specify a general single-variable exponential polynomial phase function.\n - applyMultiVarPhaseFunc() to specify a general multi-variable exponential polynomial phase function.\n - applyDiagonalOp() to apply a non-unitary diagonal operator.\n\n @ingroup operator\n @param[in,out] qureg the state-vector or density-matrix to be modified\n @param[in] qubits a list of all the qubit indices contained in each sub-register\n @param[in] numQubitsPerReg a list of the lengths of each sub-list in \\p qubits\n @param[in] numRegs the number of sub-registers, which is the length of both \\p numQubitsPerReg and \\p numTermsPerReg\n @param[in] encoding the ::bitEncoding under which to infer the binary value \\f$r_j\\f$ from the bits of a sub-register\n @param[in] functionNameCode the ::phaseFunc \\f$f(\\vec{r}, \\vec{\\theta})\\f$\n @param[in] params a list of any additional parameters \\f$\\vec{\\theta}\\f$ needed by the ::phaseFunc \\p functionNameCode\n @param[in] numParams the length of list \\p params\n @param[in] overrideInds a flattened list of sub-register coordinates (values of \\f$\\vec{r}\\f$) of which to explicit set the phase change\n @param[in] overridePhases a list of replacement phase changes, for the corresponding \\f$\\vec{r}\\f$ values in \\p overrideInds\n @param[in] numOverrides the lengths of list \\p overridePhases (but not necessarily of \\p overrideInds)\n @exception invalidQuESTInputError()\n - if any qubit in \\p qubits has an invalid index (i.e. does not satisfy 0 <= qubit < `qureg.numQubitsRepresented`)\n - if the elements of \\p qubits are not unique (including if sub-registers overlap)\n - if \\p numRegs <= 0 or \\p numRegs > 100 (constrained by `MAX_NUM_REGS_APPLY_ARBITRARY_PHASE` in QuEST_precision.h)\n - if \\p encoding is not a valid ::bitEncoding\n - if the size of any sub-register is incompatible with \\p encoding (e.g. contains fewer than two qubits in \\p encoding <b>=</b> \\p TWOS_COMPLEMENT)\n - if \\p functionNameCode is not a valid ::phaseFunc\n - if \\p numParams is incompatible with \\p functionNameCode (for example, no parameters were passed to \\p SCALED_PRODUCT)\n - if any value in \\p overrideInds is not producible by its corresponding sub-register under the given \\p encoding (e.g. 2 unsigned qubits cannot represent index 9)\n - if \\p numOverrides < 0\n @author Tyson Jones"]
1358 pub fn applyParamNamedPhaseFuncOverrides(
1359 qureg: Qureg,
1360 qubits: *mut ::std::os::raw::c_int,
1361 numQubitsPerReg: *mut ::std::os::raw::c_int,
1362 numRegs: ::std::os::raw::c_int,
1363 encoding: bitEncoding,
1364 functionNameCode: phaseFunc,
1365 params: *mut f64,
1366 numParams: ::std::os::raw::c_int,
1367 overrideInds: *mut ::std::os::raw::c_longlong,
1368 overridePhases: *mut f64,
1369 numOverrides: ::std::os::raw::c_int,
1370 );
1371}
1372extern "C" {
1373 #[doc = " Applies the quantum Fourier transform (QFT) to the entirety of \\p qureg.\n The effected unitary circuit (shown here for 4 qubits, bottom qubit is <b>0</b>) resembles\n@htmlonly\n<center>\n<script type=\"text/tikz\">\n\\begin{tikzpicture}[scale=.5]\n\\draw (-2, 5) -- (23, 5);\n\\draw (-2, 3) -- (23, 3);\n\\draw (-2, 1) -- (23, 1);\n\\draw (-2, -1) -- (23, -1);\n\n\\draw[fill=white] (-1, 4) -- (-1, 6) -- (1, 6) -- (1,4) -- cycle;\n\\node[draw=none] at (0, 5) {H};\n\n\\draw(2, 5) -- (2, 3);\n\\draw[fill=black] (2, 5) circle (.2);\n\\draw[fill=black] (2, 3) circle (.2);\n\\draw(4, 5) -- (4, 1);\n\\draw[fill=black] (4, 5) circle (.2);\n\\draw[fill=black] (4, 1) circle (.2);\n\\draw(6, 5) -- (6, -1);\n\\draw[fill=black] (6, 5) circle (.2);\n\\draw[fill=black] (6, -1) circle (.2);\n\n\\draw[fill=white] (-1+8, 4-2) -- (-1+8, 6-2) -- (1+8, 6-2) -- (1+8,4-2) -- cycle;\n\\node[draw=none] at (8, 5-2) {H};\n\n\\draw(10, 5-2) -- (10, 3-2);\n\\draw[fill=black] (10, 5-2) circle (.2);\n\\draw[fill=black] (10, 3-2) circle (.2);\n\\draw(12, 5-2) -- (12, 3-4);\n\\draw[fill=black] (12, 5-2) circle (.2);\n\\draw[fill=black] (12, 3-4) circle (.2);\n\n\\draw[fill=white] (-1+8+6, 4-4) -- (-1+8+6, 6-4) -- (1+8+6, 6-4) -- (1+8+6,4-4) -- cycle;\n\\node[draw=none] at (8+6, 5-4) {H};\n\n\\draw(16, 5-2-2) -- (16, 3-4);\n\\draw[fill=black] (16, 5-2-2) circle (.2);\n\\draw[fill=black] (16, 3-4) circle (.2);\n\n\\draw[fill=white] (-1+8+6+4, 4-4-2) -- (-1+8+6+4, 6-4-2) -- (1+8+6+4, 6-4-2) -- (1+8+6+4,4-4-2) -- cycle;\n\\node[draw=none] at (8+6+4, 5-4-2) {H};\n\n\\draw (20, 5) -- (20, -1);\n\\draw (20 - .35, 5 + .35) -- (20 + .35, 5 - .35);\n\\draw (20 - .35, 5 - .35) -- (20 + .35, 5 + .35);\n\\draw (20 - .35, -1 + .35) -- (20 + .35, -1 - .35);\n\\draw (20 - .35, -1 - .35) -- (20 + .35, -1 + .35);\n\\draw (22, 3) -- (22, 1);\n\\draw (22 - .35, 3 + .35) -- (22 + .35, 3 - .35);\n\\draw (22 - .35, 3 - .35) -- (22 + .35, 3 + .35);\n\\draw (22 - .35, 1 + .35) -- (22 + .35, 1 - .35);\n\\draw (22 - .35, 1 - .35) -- (22 + .35, 1 + .35);\n\\end{tikzpicture}\n</script>\n</center>\n@endhtmlonly\n though is performed more efficiently.\n\n - If \\p qureg is a state-vector, the output amplitudes are the discrete Fourier\n transform (DFT) of the input amplitudes, in the exact ordering. This is true\n even if \\p qureg is unnormalised. \\n\n Precisely,\n \\f[\n \\text{QFT} \\, \\left( \\sum\\limits_{x=0}^{2^N-1} \\alpha_x |x\\rangle \\right)\n =\n \\frac{1}{\\sqrt{2^N}}\n \\sum\\limits_{x=0}^{2^N-1} \\left(\n \\sum\\limits_{y=0}^{2^N-1} e^{2 \\pi \\, i \\, x \\, y / 2^N} \\; \\alpha_y\n \\right) |x\\rangle\n \\f]\n\n - If \\p qureg is a density matrix \\f$\\rho\\f$, it will be changed under the unitary action\n of the QFT. This can be imagined as each mixed state-vector undergoing the DFT\n on its amplitudes. This is true even if \\p qureg is unnormalised.\n \\f[\n \\rho \\; \\rightarrow \\; \\text{QFT} \\; \\rho \\; \\text{QFT}^{\\dagger}\n \\f]\n\n > This function merges contiguous controlled-phase gates into single invocations\n > of applyNamedPhaseFunc(), and hence is significantly faster than performing\n > the QFT circuit directly.\n\n > Furthermore, in distributed mode, this function requires only \\f$\\log_2(\\text{\\#nodes})\\f$\n > rounds of pair-wise\n > communication, and hence is exponentially faster than directly performing the\n > DFT on the amplitudes of \\p qureg.\n\n @see\n - applyQFT() to apply the QFT to a sub-register of \\p qureg.\n\n @ingroup operator\n @param[in,out] qureg a state-vector or density matrix to modify\n @author Tyson Jones"]
1374 pub fn applyFullQFT(qureg: Qureg);
1375}
1376extern "C" {
1377 #[doc = " Applies the quantum Fourier transform (QFT) to a specific subset of qubits\n of the register \\p qureg.\n\n The order of \\p qubits affects the ultimate unitary.\n The canonical full-state QFT (applyFullQFT()) is achieved by targeting every\n qubit in increasing order.\n\n The effected unitary circuit (shown here for \\p numQubits <b>= 4</b>) resembles\n@htmlonly\n<center>\n<script type=\"text/tikz\">\n\\begin{tikzpicture}[scale=.5]\n\\draw (-2, 5) -- (23, 5); \\node[draw=none] at (-4,5) {qubits[3]};\n\\draw (-2, 3) -- (23, 3); \\node[draw=none] at (-4,3) {qubits[2]};\n\\draw (-2, 1) -- (23, 1); \\node[draw=none] at (-4,1) {qubits[1]};\n\\draw (-2, -1) -- (23, -1); \\node[draw=none] at (-4,-1) {qubits[0]};\n\n\\draw[fill=white] (-1, 4) -- (-1, 6) -- (1, 6) -- (1,4) -- cycle;\n\\node[draw=none] at (0, 5) {H};\n\n\\draw(2, 5) -- (2, 3);\n\\draw[fill=black] (2, 5) circle (.2);\n\\draw[fill=black] (2, 3) circle (.2);\n\\draw(4, 5) -- (4, 1);\n\\draw[fill=black] (4, 5) circle (.2);\n\\draw[fill=black] (4, 1) circle (.2);\n\\draw(6, 5) -- (6, -1);\n\\draw[fill=black] (6, 5) circle (.2);\n\\draw[fill=black] (6, -1) circle (.2);\n\n\\draw[fill=white] (-1+8, 4-2) -- (-1+8, 6-2) -- (1+8, 6-2) -- (1+8,4-2) -- cycle;\n\\node[draw=none] at (8, 5-2) {H};\n\n\\draw(10, 5-2) -- (10, 3-2);\n\\draw[fill=black] (10, 5-2) circle (.2);\n\\draw[fill=black] (10, 3-2) circle (.2);\n\\draw(12, 5-2) -- (12, 3-4);\n\\draw[fill=black] (12, 5-2) circle (.2);\n\\draw[fill=black] (12, 3-4) circle (.2);\n\n\\draw[fill=white] (-1+8+6, 4-4) -- (-1+8+6, 6-4) -- (1+8+6, 6-4) -- (1+8+6,4-4) -- cycle;\n\\node[draw=none] at (8+6, 5-4) {H};\n\n\\draw(16, 5-2-2) -- (16, 3-4);\n\\draw[fill=black] (16, 5-2-2) circle (.2);\n\\draw[fill=black] (16, 3-4) circle (.2);\n\n\\draw[fill=white] (-1+8+6+4, 4-4-2) -- (-1+8+6+4, 6-4-2) -- (1+8+6+4, 6-4-2) -- (1+8+6+4,4-4-2) -- cycle;\n\\node[draw=none] at (8+6+4, 5-4-2) {H};\n\n\\draw (20, 5) -- (20, -1);\n\\draw (20 - .35, 5 + .35) -- (20 + .35, 5 - .35);\n\\draw (20 - .35, 5 - .35) -- (20 + .35, 5 + .35);\n\\draw (20 - .35, -1 + .35) -- (20 + .35, -1 - .35);\n\\draw (20 - .35, -1 - .35) -- (20 + .35, -1 + .35);\n\\draw (22, 3) -- (22, 1);\n\\draw (22 - .35, 3 + .35) -- (22 + .35, 3 - .35);\n\\draw (22 - .35, 3 - .35) -- (22 + .35, 3 + .35);\n\\draw (22 - .35, 1 + .35) -- (22 + .35, 1 - .35);\n\\draw (22 - .35, 1 - .35) -- (22 + .35, 1 + .35);\n\\end{tikzpicture}\n</script>\n</center>\n@endhtmlonly\n though is performed more efficiently.\n\n - If \\p qureg is a state-vector, the output amplitudes are a kronecker product of\n the discrete Fourier transform (DFT) acting upon the targeted amplitudes, and the\n remaining. \\n\n Precisely,\n - let \\f$|x,r\\rangle\\f$ represent a computational basis state where\n \\f$x\\f$ is the binary value of the targeted qubits, and \\f$r\\f$ is the binary value\n of the remaining qubits.\n - let \\f$|x_j,r_j\\rangle\\f$ be the \\f$j\\text{th}\\f$ such state.\n - let \\f$n =\\f$ \\p numQubits, and \\f$N =\\f$ `qureg.numQubitsRepresented`.\\n\n Then, this function effects\n \\f[\n (\\text{QFT}\\otimes 1) \\, \\left( \\sum\\limits_{j=0}^{2^N-1} \\alpha_j \\, |x_j,r_j\\rangle \\right)\n =\n \\frac{1}{\\sqrt{2^n}}\n \\sum\\limits_{j=0}^{2^N-1} \\alpha_j \\left(\n \\sum\\limits_{y=0}^{2^n-1} e^{2 \\pi \\, i \\, x_j \\, y / 2^n} \\;\n |y,r_j \\rangle\n \\right)\n \\f]\n\n - If \\p qureg is a density matrix \\f$\\rho\\f$, it will be changed under the unitary action\n of the QFT. This can be imagined as each mixed state-vector undergoing the DFT\n on its amplitudes. This is true even if \\p qureg is unnormalised.\n \\f[\n \\rho \\; \\rightarrow \\; \\text{QFT} \\; \\rho \\; \\text{QFT}^{\\dagger}\n \\f]\n\n > This function merges contiguous controlled-phase gates into single invocations\n > of applyNamedPhaseFunc(), and hence is significantly faster than performing\n > the QFT circuit directly.\n\n > Furthermore, in distributed mode, this function requires only \\f$\\log_2(\\text{\\#nodes})\\f$\n > rounds of pair-wise\n > communication, and hence is exponentially faster than directly performing the\n > DFT on the amplitudes of \\p qureg.\n\n @see\n - applyFullQFT() to apply the QFT to the entirety of \\p qureg.\n\n @ingroup operator\n @param[in,out] qureg a state-vector or density matrix to modify\n @param[in] qubits a list of the qubits to operate the QFT upon\n @param[in] numQubits the length of list \\p qubits\n @throws invalidQuESTInputError()\n - if any qubit in \\p qubits is invalid, i.e. outside <b>[0, </b>`qureg.numQubitsRepresented`<b>)</b>\n - if \\p qubits contain any repetitions\n - if \\p numQubits <b>< 1</b>\n - if \\p numQubits <b>></b>`qureg.numQubitsRepresented`\n @throws segmentation-fault\n - if \\p qubits contains fewer elements than \\p numQubits\n @author Tyson Jones"]
1378 pub fn applyQFT(
1379 qureg: Qureg,
1380 qubits: *mut ::std::os::raw::c_int,
1381 numQubits: ::std::os::raw::c_int,
1382 );
1383}
1384extern "C" {
1385 #[doc = " Force the target \\p qubit of \\p qureg into the given classical \\p outcome, via a\n non-renormalising projection.\n\n This function zeroes all amplitudes in the state-vector or density-matrix which\n correspond to the opposite \\p outcome given. Unlike collapseToOutcome(), it does\n not thereafter normalise \\p qureg, and hence may leave it in a non-physical state.\n\n Note there is no requirement that the \\p outcome state has a non-zero proability, and hence\n this function may leave \\p qureg in a blank state, like that produced by initBlankState().\n\n @see\n - collapseToOutcome() for a norm-preserving equivalent, like a forced measurement\n\n @ingroup operator\n @param[in,out] qureg a state-vector or density matrix to modify\n @param[in] qubit the qubit to which to apply the projector\n @param[in] outcome the single-qubit outcome (`0` or `1`) to project \\p qubit into\n @throws invalidQuESTInputError()\n - if \\p qubit is outside [0, `qureg.numQubitsRepresented`)\n - if \\p outcome is not in {0,1}\n @author Tyson Jones"]
1386 pub fn applyProjector(
1387 qureg: Qureg,
1388 qubit: ::std::os::raw::c_int,
1389 outcome: ::std::os::raw::c_int,
1390 );
1391}
1392extern "C" {
1393 pub fn statevec_twoQubitUnitary(
1394 qureg: Qureg,
1395 targetQubit1: ::std::os::raw::c_int,
1396 targetQubit2: ::std::os::raw::c_int,
1397 u: ComplexMatrix4,
1398 );
1399}