The Quantum Exact Simulation Toolkit v4.2.0
Loading...
Searching...
No Matches
precision.h
1/** @file
2 * The precision of QuEST's numerical types, some of which
3 * are overridable and others of which are intendedly fixed.
4 *
5 * @author Tyson Jones
6 * @author Milos Prokop (patched trig overloads in v3)
7 *
8 * @defgroup precision Precision
9 * @ingroup api
10 * @brief Macros for controlling QuEST's numerical precision.
11 * @{
12 */
13
14#ifndef PRECISION_H
15#define PRECISION_H
16
17#include "quest/include/config.h"
18
19
20
21/*
22 * STATE-INDEXING TYPE
23 */
24
25// can be (for example) int, long, long long, unsigned, long unsigned, long long unsigned.
26// We make sure that the backend never relies upon being able to represent negative
27// indices (e.g. as flags) since that would require a strictly signed type. Note this precision
28// determines qindex which is user-facing so using unsigned types opens the users to the
29// risks of underflowing. Since we never store large collections of this type, there is little
30// benefit in shrinking the type size and facing the associated precision risks. Similarly,
31// there is little benefit in making it larger since a 'long long int' can represent 62 qubits,
32// which is already well beyond simulability, requiring 64 EiB total at double precision.
33// Still, we use a #define, rather than a typedef, so that the value can be compile-time overridden.
34
35/// @neverdoced
36#define INDEX_TYPE long long int
37
38// spoofing above macro as const to doc
39#if 0
40
41 /// @notyetdoced
42 /// @macrodoc
43 typedef long long int INDEX_TYPE;
44
45#endif
46
47
48
49/*
50 * PAULI STRING INDEXING TYPE
51 */
52
53// should never be changed; it is unsigned due to its use in extensive bitwise processing
54// (no overflow risks since the API does not use this type), and its precision constrains
55// the number of Paulis which can be specified in a PauliStr. Specifically, PauliStr stores
56// two PAULI_MASK_TYPE instances, each of which are interpreted as half the digits of a
57// base-4 numeral encoding the Pauli string. A single 64-bit 'long long unsigned' can ergo
58// specify only 32 qubits, whereas two can specify more qubits (64) than we can simulate.
59// This type is defined purely to avoid littering the source with explicit typing.
60
61/// @neverdoced
62#define PAULI_MASK_TYPE long long unsigned int
63
64// spoofing above macro as typedef to doc
65#if 0
66
67 /// @notyetdoced
68 /// @macrodoc
69 typedef long long unsigned int PAULI_MASK_TYPE;
70
71#endif
72
73
74
75/*
76 * RE-CONFIGURABLE FLOATING-POINT PRECISION
77 */
78
79// validate precision is 1 (float), 2 (double) or 4 (long double)
80#if ! (FLOAT_PRECISION == 1 || FLOAT_PRECISION == 2 || FLOAT_PRECISION == 4)
81 #error "FLOAT_PRECISION must be 1 (float), 2 (double) or 4 (long double)"
82#endif
83
84// infer floating-point type from precision
85#if FLOAT_PRECISION == 1
86 #define FLOAT_TYPE float
87#elif FLOAT_PRECISION == 2
88 #define FLOAT_TYPE double
89#elif FLOAT_PRECISION == 4
90 #define FLOAT_TYPE long double
91#endif
92
93// spoofing above macros as typedefs and consts to doc
94#if 0
95
96 /// @notyetdoced
97 /// @macrodoc
98 ///
99 /// (note this macro is informed by the FLOAT_PRECISION CMake variable)
100 const int FLOAT_PRECISION = 2;
101
102 /// @notyetdoced
103 /// @macrodoc
104 ///
105 /// (note this macro is informed by the FLOAT_PRECISION CMake variable)
106 typedef double int FLOAT_TYPE;
107
108#endif
109
110
111
112/*
113 * CHECK PRECISION TYPES ARE COMPATIBLE WITH DEPLOYMENT
114 */
115
116#if COMPILE_CUDA && (FLOAT_PRECISION == 4)
117 #error "A quad floating-point precision (FLOAT_PRECISION=4, i.e. long double) is not supported by GPU deployment"
118#endif
119
120
121
122/*
123 * DEFAULT VALIDATION PRECISION
124 *
125 * which is pre-run-time overridable by specifying the corresponding environment variable.
126 */
127
128#if FLOAT_PRECISION == 1
129 #define UNSPECIFIED_DEFAULT_VALIDATION_EPSILON 1E-5
130
131#elif FLOAT_PRECISION == 2
132 #define UNSPECIFIED_DEFAULT_VALIDATION_EPSILON 1E-12
133
134#elif FLOAT_PRECISION == 4
135 #define UNSPECIFIED_DEFAULT_VALIDATION_EPSILON 1E-13
136
137#endif
138
139
140
141/*
142 * PRECISION-AGNOSTIC CONVENIENCE MACROS
143 */
144
145#if FLOAT_PRECISION == 1
146 #define QREAL_FORMAT_SPECIFIER "%.8g"
147
148#elif FLOAT_PRECISION == 2
149 #define QREAL_FORMAT_SPECIFIER "%.14g"
150
151#elif FLOAT_PRECISION == 4
152 #define QREAL_FORMAT_SPECIFIER "%.17Lg"
153
154#endif
155
156// spoofing above macros as typedefs and consts to doc
157#if 0
158
159 /// @notyetdoced
160 /// @macrodoc
161 const char* QREAL_FORMAT_SPECIFIER = "%.14g";
162
163#endif
164
165
166
167#endif // PRECISION_H
168
169/** @} */ // (end file-wide doxygen defgroup)
long long int INDEX_TYPE
Definition precision.h:43
const char * QREAL_FORMAT_SPECIFIER
Definition precision.h:161
const int FLOAT_PRECISION
Definition precision.h:100
double int FLOAT_TYPE
Definition precision.h:106
long long unsigned int PAULI_MASK_TYPE
Definition precision.h:69