17#include <catch2/catch_test_macros.hpp>
18#include <catch2/matchers/catch_matchers_floating_point.hpp>
26using namespace Catch::Matchers;
36#if QUEST_FLOAT_PRECISION == 1
37 qreal absoluteEpsilon = 1E-2;
38 qreal relativeEpsilon = 1E-2;
39#elif QUEST_FLOAT_PRECISION == 2
40 qreal absoluteEpsilon = 1E-8;
41 qreal relativeEpsilon = 1E-8;
42#elif QUEST_FLOAT_PRECISION == 4
43 qreal absoluteEpsilon = 1E-10;
44 qreal relativeEpsilon = 1E-10;
48qreal getTestAbsoluteEpsilon() {
50 return absoluteEpsilon;
53qreal getTestRelativeEpsilon() {
55 return relativeEpsilon;
59void setTestAbsoluteEpsilon(qreal eps) {
60 absoluteEpsilon = eps;
63void setTestRelativeEpsilon(qreal eps) {
64 relativeEpsilon = eps;
67void setTestEpsilon(qreal eps) {
68 setTestAbsoluteEpsilon(eps);
69 setTestRelativeEpsilon(eps);
73qreal getAbsDif(qcomp a, qcomp b) {
75 return std::abs(a - b);
78qreal getRelDif(qcomp a, qcomp b) {
80 qreal denom = std::min({std::abs(a), std::abs(b)});
81 return getAbsDif(a,b) / denom;
85bool doScalarsAgree(qcomp a, qcomp b) {
89 if (getAbsDif(a, b) <= absoluteEpsilon)
92 return (getRelDif(a, b) <= relativeEpsilon);
95bool doMatricesAgree(qmatrix a, qmatrix b) {
96 DEMAND( a.size() == b.size() );
99 size_t dim = a.size();
101 for (
size_t i=0; i<dim; i++)
102 for (
size_t j=0; j<dim; j++)
103 if (!doScalarsAgree(a[i][j], b[i][j]))
119void REPORT_AMP_AND_FAIL(
size_t index, qcomp amplitude, qcomp reference ) {
120 qreal absolute_difference = getAbsDif(amplitude, reference);
121 qreal relative_difference = getRelDif(amplitude, reference);
123 index, amplitude, reference,
124 absolute_difference, absoluteEpsilon,
125 relative_difference, relativeEpsilon
131void REQUIRE_AGREE(
Qureg q, qvector v1 ) {
132 DEMAND( !q.isDensityMatrix );
133 DEMAND( q.numAmps == (qindex) v1.size() );
135 qvector v2 = getVector(q);
137 for (
size_t i=0; i<v1.size(); i++)
138 if (!doScalarsAgree(v1[i], v2[i]))
139 REPORT_AMP_AND_FAIL(i, v2[i], v1[i]);
145void REQUIRE_AGREE(
Qureg q, qmatrix m1 ) {
146 DEMAND( q.isDensityMatrix );
147 DEMAND( getPow2(q.numQubits) == (qindex) m1.size() );
149 qmatrix m2 = getMatrix(q);
151 for (
size_t i=0; i<m1.size(); i++)
152 for (
size_t j=0; j<m1.size(); j++)
153 if (!doScalarsAgree(m1[i][j], m2[i][j]))
154 REPORT_AMP_AND_FAIL(j*m1.size()+i, m2[i][j], m1[i][j]);
166void REPORT_SCALAR_AND_FAIL( qcomp scalar, qcomp reference ) {
167 qreal absolute_difference = getAbsDif(scalar, reference);
168 qreal relative_difference = getRelDif(scalar, reference);
171 absolute_difference, absoluteEpsilon,
172 relative_difference, relativeEpsilon
177void REPORT_SCALAR_AND_FAIL( qreal scalar, qreal reference ) {
180 qreal absolute_difference = getAbsDif(qcomp(scalar,0), qcomp(reference,0));
181 qreal relative_difference = getRelDif(qcomp(scalar,0), qcomp(reference,0));
184 absolute_difference, absoluteEpsilon,
185 relative_difference, relativeEpsilon
191void REQUIRE_AGREE( qcomp scalar, qcomp reference ) {
193 if (!doScalarsAgree(scalar, reference))
194 REPORT_SCALAR_AND_FAIL(scalar, reference);
199void REQUIRE_AGREE( qreal scalar, qreal reference ) {
201 if (!doScalarsAgree(qcomp(scalar,0), qcomp(reference,0)))
202 REPORT_SCALAR_AND_FAIL(scalar, reference);
214void REQUIRE_AGREE( vector<qreal> apiList, vector<qreal> refList ) {
215 DEMAND( apiList.size() == refList.size() );
217 for (
size_t i=0; i<apiList.size(); i++)
218 if (!doScalarsAgree(apiList[i], refList[i]))
219 REPORT_SCALAR_AND_FAIL(apiList[i], refList[i]);
225void REQUIRE_AGREE( vector<qcomp> apiList, vector<qcomp> refList ) {
226 DEMAND( apiList.size() == refList.size() );
228 for (
size_t i=0; i<apiList.size(); i++)
229 if (!doScalarsAgree(apiList[i], refList[i]))
230 REPORT_SCALAR_AND_FAIL(apiList[i], refList[i]);
242void REPORT_ELEM_AND_FAIL(
size_t row,
size_t col, qcomp elem, qcomp reference ) {
243 qreal absolute_difference = getAbsDif(elem, reference);
244 qreal relative_difference = getRelDif(elem, reference);
246 row, col, elem, reference,
247 absolute_difference, absoluteEpsilon,
248 relative_difference, relativeEpsilon
254void REQUIRE_AGREE( qmatrix matrix, qmatrix reference ) {
255 DEMAND( matrix.size() == reference.size() );
257 size_t dim = matrix.size();
259 for (
size_t r=0; r<dim; r++)
260 for (
size_t c=0; c<dim; c++)
261 if (!doScalarsAgree(matrix[r][c], reference[r][c]))
262 REPORT_ELEM_AND_FAIL(r, c, matrix[r][c], reference[r][c]);
268void REQUIRE_AGREE(
CompMatr1 matrix, qmatrix reference ) { REQUIRE_AGREE( getMatrix(matrix), reference ); }
269void REQUIRE_AGREE(
CompMatr2 matrix, qmatrix reference ) { REQUIRE_AGREE( getMatrix(matrix), reference ); }
270void REQUIRE_AGREE(
CompMatr matrix, qmatrix reference ) { REQUIRE_AGREE( getMatrix(matrix), reference ); }
271void REQUIRE_AGREE(
DiagMatr1 matrix, qmatrix reference ) { REQUIRE_AGREE( getMatrix(matrix), reference ); }
272void REQUIRE_AGREE(
DiagMatr2 matrix, qmatrix reference ) { REQUIRE_AGREE( getMatrix(matrix), reference ); }
273void REQUIRE_AGREE(
DiagMatr matrix, qmatrix reference ) { REQUIRE_AGREE( getMatrix(matrix), reference ); }
274void REQUIRE_AGREE(
SuperOp matrix, qmatrix reference ) { REQUIRE_AGREE( getMatrix(matrix), reference ); }
285void REQUIRE_AGREE(
Qureg qureg,
Qureg other ) {
286 DEMAND( qureg.numQubits == other.numQubits );
287 DEMAND( qureg.isDensityMatrix == other.isDensityMatrix );
289 return (qureg.isDensityMatrix)?
290 REQUIRE_AGREE( qureg, getMatrix(other) ):
291 REQUIRE_AGREE( qureg, getVector(other) );