diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 65863a1..5d273c9 100644 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -52,7 +52,7 @@ jobs: - name: Build # Build your program with the given configuration. Note that --config is needed because the default Windows generator is a multi-config generator (Visual Studio generator). - run: | + run: | cmake -DDEFINE_DEBUG=1 ${{ steps.strings.outputs.build-output-dir }} cmake --build ${{ steps.strings.outputs.build-output-dir }} --config ${{ matrix.build_type }} diff --git a/CustomMath_lib/BisectMethod/BisectMethod.cpp b/CustomMath_lib/BisectMethod/BisectMethod.cpp index 7b26dbe..470a3c9 100644 --- a/CustomMath_lib/BisectMethod/BisectMethod.cpp +++ b/CustomMath_lib/BisectMethod/BisectMethod.cpp @@ -29,6 +29,9 @@ ull CalculateSignChange(const Vector &x, const Vector &y, lld mu) { return s; } +#pragma clang diagnostic push +#pragma ide diagnostic ignored "misc-no-recursion" + std::vector BisectMethodCall(const Vector &x, const Vector &y, lld start, lld end, lld precision) { #ifdef DEBUG if (start > end) { @@ -72,6 +75,8 @@ std::vector BisectMethodCall(const Vector &x, const Vector &y, lld start, l return result; } +#pragma clang diagnostic pop + Vector BisectMethod(const Vector &x, const Vector &y, lld precision) { #ifdef DEBUG if (x.size != y.size + 1) { diff --git a/CustomMath_lib/CholeskyMethod/Cholesky_Decomposition.cpp b/CustomMath_lib/CholeskyMethod/Cholesky_Decomposition.cpp index 29d7b3b..6a4a4d6 100644 --- a/CustomMath_lib/CholeskyMethod/Cholesky_Decomposition.cpp +++ b/CustomMath_lib/CholeskyMethod/Cholesky_Decomposition.cpp @@ -7,7 +7,7 @@ void Cholesky_Decomposition_InPlace(Matrix &A) { CHECK_SQUARE_MATRIX(A) - ull n = A.rows; + auto n = A.rows; for (ull k = 0; k < n; k++) { // if (A.matrix[k][k] <= 0) { @@ -30,7 +30,7 @@ void Cholesky_Decomposition_InPlace(Matrix &A) { Matrix Cholesky_Decomposition(const Matrix &A) { CHECK_SQUARE_MATRIX(A) - ull n = A.rows; + auto n = A.rows; auto L = Matrix(A); Cholesky_Decomposition_InPlace(L); @@ -44,9 +44,9 @@ Matrix Cholesky_Decomposition(const Matrix &A) { } Vector Cholesky_Solve(const Matrix &A, const Vector &b) { - Matrix L = Cholesky_Decomposition(A); - Vector y = LowerTriangleMatrix_Solve(L, b); - Vector x = UpperTriangleMatrix_Solve(L.transpose(), y); + auto L = Cholesky_Decomposition(A); + auto y = LowerTriangleMatrix_Solve(L, b); + auto x = UpperTriangleMatrix_Solve(L.transpose(), y); return x; } diff --git a/CustomMath_lib/CholeskyMethod/Cholesky_LDLT.cpp b/CustomMath_lib/CholeskyMethod/Cholesky_LDLT.cpp index 63b1508..d3a76c2 100644 --- a/CustomMath_lib/CholeskyMethod/Cholesky_LDLT.cpp +++ b/CustomMath_lib/CholeskyMethod/Cholesky_LDLT.cpp @@ -7,7 +7,7 @@ void Cholesky_LDLT_Decomposition_InPlace(Matrix &A) { CHECK_SQUARE_MATRIX(A) - ull n = A.rows; + auto n = A.rows; Vector tmp = Vector(n); for (ull j = 0; j < n; j++) { @@ -30,7 +30,7 @@ void Cholesky_LDLT_Decomposition_InPlace(Matrix &A) { Cholesky_LDLT_Result Cholesky_LDLT_Decomposition(const Matrix &A) { CHECK_SQUARE_MATRIX(A) - ull n = A.rows; + auto n = A.rows; auto L = Matrix(A); Cholesky_LDLT_Decomposition_InPlace(L); @@ -56,11 +56,11 @@ Vector Cholesky_LDLT_Solve(const Matrix &A, const Vector &b) { auto L = tmp.L; auto D = tmp.D; - Vector y = LowerTriangleMatrix_Solve(L, b); + auto y = LowerTriangleMatrix_Solve(L, b); for (ull i = 0; i < A.rows; i++) { y.array[i] /= D.matrix[i][i]; } - Vector x = UpperTriangleMatrix_Solve(L.transpose(), y); + auto x = UpperTriangleMatrix_Solve(L.transpose(), y); return x; } diff --git a/CustomMath_lib/GaussMethod/LU_Decomposition.cpp b/CustomMath_lib/GaussMethod/LU_Decomposition.cpp index 5e210e0..cc9dfd0 100644 --- a/CustomMath_lib/GaussMethod/LU_Decomposition.cpp +++ b/CustomMath_lib/GaussMethod/LU_Decomposition.cpp @@ -7,7 +7,7 @@ void LU_Decomposition_InPlace(Matrix &A) { CHECK_SQUARE_MATRIX(A) - ull n = A.rows; + auto n = A.rows; for (ull i = 0; i < n - 1; i++) { for (ull j = i + 1; j < n; j++) { @@ -20,12 +20,12 @@ void LU_Decomposition_InPlace(Matrix &A) { } } -void LU_Decomposition(const Matrix &A, Matrix &L, Matrix &U) { +LU_Decomposition_Result LU_Decomposition(const Matrix &A) { CHECK_SQUARE_MATRIX(A) - ull n = A.rows; - L = Matrix(n, n); - U = Matrix(A); + auto n = A.rows; + auto L = Matrix(n, n); + auto U = Matrix(A); LU_Decomposition_InPlace(U); for (ull i = 0; i < n; i++) { @@ -38,13 +38,7 @@ void LU_Decomposition(const Matrix &A, Matrix &L, Matrix &U) { U.matrix[i][j] = 0; } } -} - -LU_Decomposition_Result LU_Decomposition(const Matrix &A) { - CHECK_SQUARE_MATRIX(A) - Matrix L, U; - LU_Decomposition(A, L, U); return {L, U}; } @@ -61,8 +55,8 @@ Vector LU_Solve(const Matrix &A, const Vector &b) { CHECK_SQUARE_MATRIX(A) CHECK_EQUAL_SIZE(A, b) - Matrix A_copy = Matrix(A); - Vector b_copy = Vector(b); + auto A_copy = Matrix(A); + auto b_copy = Vector(b); LU_Solve_InPlace(A_copy, b_copy); return b_copy; } \ No newline at end of file diff --git a/CustomMath_lib/GaussMethod/LU_Decomposition.h b/CustomMath_lib/GaussMethod/LU_Decomposition.h index eefcc5b..ffadcbd 100644 --- a/CustomMath_lib/GaussMethod/LU_Decomposition.h +++ b/CustomMath_lib/GaussMethod/LU_Decomposition.h @@ -12,9 +12,6 @@ typedef struct { Matrix U; } LU_Decomposition_Result; -/// Decomposition A = LU, det(L) == 1 -void LU_Decomposition(const Matrix &A, Matrix &L, Matrix &U); - /// Decomposition A = LU, det(L) == 1 LU_Decomposition_Result LU_Decomposition(const Matrix &A); diff --git a/CustomMath_lib/GaussMethod/LU_FP_Decomposition.cpp b/CustomMath_lib/GaussMethod/LU_FP_Decomposition.cpp index a860a49..17a1ca5 100644 --- a/CustomMath_lib/GaussMethod/LU_FP_Decomposition.cpp +++ b/CustomMath_lib/GaussMethod/LU_FP_Decomposition.cpp @@ -4,12 +4,12 @@ #include "LU_FP_Decomposition.h" -void LU_FP_Decomposition_InPlace(Matrix &A, Matrix &P, Matrix &Q) { +LU_FP_Decomposition_Inplace_Result LU_FP_Decomposition_InPlace(Matrix &A) { CHECK_SQUARE_MATRIX(A) - ull n = A.rows; - P = Matrix::identity(n); - Q = Matrix::identity(n); + auto n = A.rows; + auto P = Matrix::identity(n); + auto Q = Matrix::identity(n); for (ull i = 0; i < n; i++) { // find the pivot @@ -53,15 +53,17 @@ void LU_FP_Decomposition_InPlace(Matrix &A, Matrix &P, Matrix &Q) { } } } + + return {P, Q}; } -void LU_FP_Decomposition(const Matrix &A, Matrix &L, Matrix &U, Matrix &P, Matrix &Q) { +LU_FP_Decomposition_Result LU_FP_Decomposition(const Matrix &A) { CHECK_SQUARE_MATRIX(A) - ull n = A.rows; - L = Matrix(n, n); - U = Matrix(A); - LU_FP_Decomposition_InPlace(U, P, Q); + auto n = A.rows; + auto L = Matrix(n, n); + auto U = Matrix(A); + auto [P, Q] = LU_FP_Decomposition_InPlace(U); for (ull i = 0; i < n; i++) { L.matrix[i][i] = 1; @@ -72,13 +74,7 @@ void LU_FP_Decomposition(const Matrix &A, Matrix &L, Matrix &U, Matrix &P, Matri U.matrix[i][j] = 0; } } -} - -LU_FP_Decomposition_Result LU_FP_Decomposition(const Matrix &A) { - CHECK_SQUARE_MATRIX(A) - Matrix L, U, P, Q; - LU_FP_Decomposition(A, L, U, P, Q); return {L, U, P, Q}; } @@ -86,11 +82,10 @@ void LU_FP_Solve_InPlace(Matrix &A, Vector &b) { CHECK_SQUARE_MATRIX(A) CHECK_EQUAL_SIZE(A, b) - Matrix P, Q; - LU_FP_Decomposition_InPlace(A, P, Q); - Vector Pb = P * b; - Vector UQix = LowerTriangleMatrix_Solve(A, Pb, true); - Vector Qix = UpperTriangleMatrix_Solve(A, UQix); + auto [P, Q] = LU_FP_Decomposition_InPlace(A); + auto Pb = P * b; + auto UQix = LowerTriangleMatrix_Solve(A, Pb, true); + auto Qix = UpperTriangleMatrix_Solve(A, UQix); b = Q * Qix; } @@ -98,8 +93,8 @@ Vector LU_FP_Solve(const Matrix &A, const Vector &b) { CHECK_SQUARE_MATRIX(A) CHECK_EQUAL_SIZE(A, b) - Matrix A_copy = Matrix(A); - Vector b_copy = Vector(b); + auto A_copy = Matrix(A); + auto b_copy = Vector(b); LU_FP_Solve_InPlace(A_copy, b_copy); return b_copy; } \ No newline at end of file diff --git a/CustomMath_lib/GaussMethod/LU_FP_Decomposition.h b/CustomMath_lib/GaussMethod/LU_FP_Decomposition.h index 1dc331f..ea3cc76 100644 --- a/CustomMath_lib/GaussMethod/LU_FP_Decomposition.h +++ b/CustomMath_lib/GaussMethod/LU_FP_Decomposition.h @@ -7,6 +7,11 @@ #include "CustomMath_lib.h" +typedef struct { + Matrix P; + Matrix Q; +} LU_FP_Decomposition_Inplace_Result; + typedef struct { Matrix L; Matrix U; @@ -14,9 +19,6 @@ typedef struct { Matrix Q; } LU_FP_Decomposition_Result; -// LU Decomposition with Full Pivoting -void LU_FP_Decomposition(const Matrix &A, Matrix &L, Matrix &U, Matrix &P, Matrix &Q); - // LU Decomposition with Full Pivoting LU_FP_Decomposition_Result LU_FP_Decomposition(const Matrix &A); @@ -24,7 +26,7 @@ LU_FP_Decomposition_Result LU_FP_Decomposition(const Matrix &A); Vector LU_FP_Solve(const Matrix &A, const Vector &b); // LU Decomposition with Full Pivoting, and A is stored as L + U (ignoring L's all-one diagonal) -void LU_FP_Decomposition_InPlace(Matrix &A, Matrix &P, Matrix &Q); +LU_FP_Decomposition_Inplace_Result LU_FP_Decomposition_InPlace(Matrix &A); // Solve Ax = b using LU decomposition with Full Pivoting, b is then replaced by x void LU_FP_Solve_InPlace(Matrix &A, Vector &b); diff --git a/CustomMath_lib/GaussMethod/LU_PP_Decomposition.cpp b/CustomMath_lib/GaussMethod/LU_PP_Decomposition.cpp index 93eb41a..83b1e57 100644 --- a/CustomMath_lib/GaussMethod/LU_PP_Decomposition.cpp +++ b/CustomMath_lib/GaussMethod/LU_PP_Decomposition.cpp @@ -4,16 +4,16 @@ #include "LU_PP_Decomposition.h" -void LU_PP_Decomposition_InPlace(Matrix &A, Matrix &P) { +Matrix LU_PP_Decomposition_InPlace(Matrix &A) { CHECK_SQUARE_MATRIX(A) - ull n = A.rows; - P = Matrix::identity(n); + auto n = A.rows; + auto P = Matrix::identity(n); for (ull i = 0; i < n; i++) { // find the pivot - ull pivot_i = i; - lld pivot = std::abs(A.matrix[i][i]); + auto pivot_i = i; + auto pivot = std::abs(A.matrix[i][i]); for (ull j = i; j < n; j++) { if (std::abs(A.matrix[j][i]) > std::abs(pivot)) { pivot = A.matrix[j][i]; @@ -42,15 +42,17 @@ void LU_PP_Decomposition_InPlace(Matrix &A, Matrix &P) { } } } + + return P; } -void LU_PP_Decomposition(const Matrix &A, Matrix &L, Matrix &U, Matrix &P) { +LU_PP_Decomposition_Result LU_PP_Decomposition(const Matrix &A) { CHECK_SQUARE_MATRIX(A) - ull n = A.rows; - L = Matrix(n, n); - U = Matrix(A); - LU_PP_Decomposition_InPlace(U, P); + auto n = A.rows; + auto L = Matrix(n, n); + auto U = Matrix(A); + auto P = LU_PP_Decomposition_InPlace(U); for (ull i = 0; i < n; i++) { L.matrix[i][i] = 1; @@ -61,13 +63,7 @@ void LU_PP_Decomposition(const Matrix &A, Matrix &L, Matrix &U, Matrix &P) { U.matrix[i][j] = 0; } } -} - -LU_PP_Decomposition_Result LU_PP_Decomposition(const Matrix &A) { - CHECK_SQUARE_MATRIX(A) - Matrix L, U, P; - LU_PP_Decomposition(A, L, U, P); return {L, U, P}; } @@ -75,10 +71,9 @@ void LU_PP_Solve_InPlace(Matrix &A, Vector &b) { CHECK_SQUARE_MATRIX(A) CHECK_EQUAL_SIZE(A, b) - Matrix P; - LU_PP_Decomposition_InPlace(A, P); - Vector Pb = P * b; // fixme: this can be optimized since P only contains pivots - Vector y = LowerTriangleMatrix_Solve(A, Pb, true); + auto P = LU_PP_Decomposition_InPlace(A); + auto Pb = P * b; // fixme: this can be optimized since P only contains pivots + auto y = LowerTriangleMatrix_Solve(A, Pb, true); b = UpperTriangleMatrix_Solve(A, y); } @@ -86,8 +81,8 @@ Vector LU_PP_Solve(const Matrix &A, const Vector &b) { CHECK_SQUARE_MATRIX(A) CHECK_EQUAL_SIZE(A, b) - Matrix A_copy = Matrix(A); - Vector b_copy = Vector(b); + auto A_copy = Matrix(A); + auto b_copy = Vector(b); LU_PP_Solve_InPlace(A_copy, b_copy); return b_copy; } \ No newline at end of file diff --git a/CustomMath_lib/GaussMethod/LU_PP_Decomposition.h b/CustomMath_lib/GaussMethod/LU_PP_Decomposition.h index e7fa40e..b9bea0d 100644 --- a/CustomMath_lib/GaussMethod/LU_PP_Decomposition.h +++ b/CustomMath_lib/GaussMethod/LU_PP_Decomposition.h @@ -13,9 +13,6 @@ typedef struct { Matrix P; } LU_PP_Decomposition_Result; -// LU Decomposition with Partial Pivoting -void LU_PP_Decomposition(const Matrix &A, Matrix &L, Matrix &U, Matrix &P); - // LU Decomposition with Partial Pivoting LU_PP_Decomposition_Result LU_PP_Decomposition(const Matrix &A); @@ -23,7 +20,7 @@ LU_PP_Decomposition_Result LU_PP_Decomposition(const Matrix &A); Vector LU_PP_Solve(const Matrix &A, const Vector &b); // LU Decomposition with Partial Pivoting, and A is stored as L + U (ignoring L's all-one diagonal) -void LU_PP_Decomposition_InPlace(Matrix &A, Matrix &P); +Matrix LU_PP_Decomposition_InPlace(Matrix &A); // Solve Ax = b using LU decomposition with Partial Pivoting, b is then replaced by x void LU_PP_Solve_InPlace(Matrix &A, Vector &b); diff --git a/CustomMath_lib/HessenbergMethod/HessenbergMethod.cpp b/CustomMath_lib/HessenbergMethod/HessenbergMethod.cpp index 7a6ba30..92cd104 100644 --- a/CustomMath_lib/HessenbergMethod/HessenbergMethod.cpp +++ b/CustomMath_lib/HessenbergMethod/HessenbergMethod.cpp @@ -4,44 +4,16 @@ #include "HessenbergMethod.h" -void HessenbergMethod_Inplace(Matrix &A) { - auto n = A.rows; - Vector v; - lld beta; - - for (ull k = 0; k < n - 1; k++) { - auto x = Vector(n - k - 1); - for (ull i = 0; i < n - k - 1; i++) { - x.array[i] = A.matrix[k + i + 1][k]; - } - HouseHolderMethod(x, v, beta); - - auto w = product(v, v) * beta; - - auto A_sub = A.sub_matrix(k + 1, n, k, n); - A_sub = A_sub - w * A_sub; - A.set(k + 1, n, k, n, A_sub); - - A_sub = A.sub_matrix(0, n, k + 1, n); - A_sub = A_sub - A_sub * w; - A.set(0, n, k + 1, n, A_sub); - } -} - void HessenbergMethod_Inplace(Matrix &A, Matrix &P) { - // init P here: P = Matrix::identity(A.rows); - auto n = A.rows; - Vector v; - lld beta; for (ull k = 0; k < n - 1; k++) { auto x = Vector(n - k - 1); for (ull i = 0; i < n - k - 1; i++) { x.array[i] = A.matrix[k + i + 1][k]; } - HouseHolderMethod(x, v, beta); + auto [v, beta] = HouseHolderMethod(x); auto w = product(v, v) * beta; @@ -64,10 +36,4 @@ HessenbergMethod_Result HessenbergMethod(const Matrix &A) { Matrix P; HessenbergMethod_Inplace(result, P); return {result.clean(), P.clean()}; // clean the matrix -} - -Matrix HessenbergMethod(const Matrix &A, Matrix &P) { - auto result = A; - HessenbergMethod_Inplace(result, P); - return result.clean(); // clean the matrix } \ No newline at end of file diff --git a/CustomMath_lib/HessenbergMethod/HessenbergMethod.h b/CustomMath_lib/HessenbergMethod/HessenbergMethod.h index 145fd54..8a9d345 100644 --- a/CustomMath_lib/HessenbergMethod/HessenbergMethod.h +++ b/CustomMath_lib/HessenbergMethod/HessenbergMethod.h @@ -15,14 +15,7 @@ typedef struct { /// P^T A P = H, returns H, P HessenbergMethod_Result HessenbergMethod(const Matrix &A); -/// P^T A P = H, returns H, P -Matrix HessenbergMethod(const Matrix &A, Matrix &P); - -/// P^T A P = H, inplace returns H only -void HessenbergMethod_Inplace(Matrix &A); - /// P^T A P = H, inplace returns H only, P passed in void HessenbergMethod_Inplace(Matrix &A, Matrix &P); - #endif //NUMERICAL_ALGEBRA_HESSENBERGMETHOD_H diff --git a/CustomMath_lib/HouseholderMethod/HouseholderMethod.cpp b/CustomMath_lib/HouseholderMethod/HouseholderMethod.cpp index f23d3e4..8c63a0e 100644 --- a/CustomMath_lib/HouseholderMethod/HouseholderMethod.cpp +++ b/CustomMath_lib/HouseholderMethod/HouseholderMethod.cpp @@ -4,16 +4,18 @@ #include "HouseholderMethod.h" -void HouseHolderMethod(const Vector &x, Vector &v, lld &beta) { +HouseHolder_Result HouseHolderMethod(const Vector &x) { ull n = x.size; + lld beta; lld eng = VectorNorm_Infinity(x); - Vector y = x / eng; + auto y = x / eng; lld sigma = y * y - y.array[0] * y.array[0]; - v = Vector(n); + auto v = Vector(n); for (ull i = 1; i < n; i++) { v.array[i] = y.array[i]; } v.array[0] = 1; + if (sigma != 0) { lld alpha = std::sqrt(y.array[0] * y.array[0] + sigma); if (y.array[0] <= 0) { @@ -26,12 +28,7 @@ void HouseHolderMethod(const Vector &x, Vector &v, lld &beta) { } else { beta = 0; } -} -HouseHolder_Result HouseHolderMethod(const Vector &x) { - Vector v; - lld beta; - HouseHolderMethod(x, v, beta); return {v, beta}; } @@ -42,16 +39,13 @@ void QR_Decomposition_InPlace(Matrix &A, Vector &d) { d = Vector(k); for (ull j = 0; j < k; j++) { - Vector v; - lld beta; auto A_j = Vector(m - j); for (ull i = j; i < m; i++) { A_j.array[i - j] = A.matrix[i][j]; } - HouseHolderMethod(A_j, v, beta); + auto [v, beta] = HouseHolderMethod(A_j); auto A_sub = A.sub_matrix(j, m, j, n); -// A_sub = (Matrix::identity(m - j) - product(v, v) * beta) * A_sub; auto w = (A_sub.transpose() * v) * beta; A_sub = A_sub - product(v, w); A.set(j, m, j, n, A_sub); @@ -63,11 +57,10 @@ void QR_Decomposition_InPlace(Matrix &A, Vector &d) { } } -void QR_Decomposition(const Matrix &A, Matrix &Q, Matrix &R) { +QR_Decomposition_Result QR_Decomposition(const Matrix &A) { ull m = A.rows; ull n = A.cols; -// Q = Matrix(n, m); - R = Matrix(n, n); + auto R = Matrix(n, n); auto B = Matrix(A); Vector d; @@ -97,12 +90,8 @@ void QR_Decomposition(const Matrix &A, Matrix &Q, Matrix &R) { tmp_Q.print(); // stripping tmp_Q to n x m -> Q: - Q = tmp_Q.sub_matrix(0, n, 0, m); -} + auto Q = tmp_Q.sub_matrix(0, n, 0, m); -QR_Decomposition_Result QR_Decomposition(const Matrix &A) { - Matrix Q, R; - QR_Decomposition(A, Q, R); return {Q, R}; } diff --git a/CustomMath_lib/HouseholderMethod/HouseholderMethod.h b/CustomMath_lib/HouseholderMethod/HouseholderMethod.h index 08c82de..80bf15d 100644 --- a/CustomMath_lib/HouseholderMethod/HouseholderMethod.h +++ b/CustomMath_lib/HouseholderMethod/HouseholderMethod.h @@ -23,12 +23,6 @@ HouseHolder_Result HouseHolderMethod(const Vector &x); /// Calculate the QR factorization of A = Q * [R; 0]^T QR_Decomposition_Result QR_Decomposition(const Matrix &A); -/// Calculate the Householder vector v and the Householder constant beta -void HouseHolderMethod(const Vector &x, Vector &v, lld &beta); - -/// Calculate the QR factorization of A = Q * [R; 0]^T -void QR_Decomposition(const Matrix &A, Matrix &Q, Matrix &R); - /// Solve Ax = b using QR factorization Vector QR_Solve(const Matrix &A, const Vector &b); diff --git a/CustomMath_lib/IterationMethod/IterationMethod.cpp b/CustomMath_lib/IterationMethod/IterationMethod.cpp index 12b0997..55435b1 100644 --- a/CustomMath_lib/IterationMethod/IterationMethod.cpp +++ b/CustomMath_lib/IterationMethod/IterationMethod.cpp @@ -5,7 +5,6 @@ #include "IterationMethod.h" - VIterationMethodOutput JacobiIteration(const IterationMethodInput &input) { auto A = input.A; auto x = input.x_default; diff --git a/CustomMath_lib/JacobiMethod/JacobiMethod.cpp b/CustomMath_lib/JacobiMethod/JacobiMethod.cpp index fe748b8..9c6d9cd 100644 --- a/CustomMath_lib/JacobiMethod/JacobiMethod.cpp +++ b/CustomMath_lib/JacobiMethod/JacobiMethod.cpp @@ -150,4 +150,6 @@ JIterationMethodOutput JacobiMethod(const Matrix &matrix, JacobiMethodType type) return {A, P, iteration_count, ITERATION_METHOD_RETURN_DURATION}; } + + throw std::invalid_argument("Invalid JacobiMethodType."); } \ No newline at end of file diff --git a/CustomMath_lib/PowerIteration/PowerIteration.cpp b/CustomMath_lib/PowerIteration/PowerIteration.cpp index f736352..ceee4af 100644 --- a/CustomMath_lib/PowerIteration/PowerIteration.cpp +++ b/CustomMath_lib/PowerIteration/PowerIteration.cpp @@ -28,8 +28,7 @@ RevPowerIterationOutput RevPowerIteration(const PowerIterationInput &input) { auto A = input.A; auto x = input.x_default; - Matrix P; - LU_PP_Decomposition_InPlace(A, P); + auto P = LU_PP_Decomposition_InPlace(A); ITERATION_METHOD_TIMING_START diff --git a/CustomMath_lib/QRMethod/DoubleShiftQRMethod.cpp b/CustomMath_lib/QRMethod/DoubleShiftQRMethod.cpp index 9cc152b..cfc9c02 100644 --- a/CustomMath_lib/QRMethod/DoubleShiftQRMethod.cpp +++ b/CustomMath_lib/QRMethod/DoubleShiftQRMethod.cpp @@ -4,10 +4,11 @@ #include "DoubleShiftQRMethod.h" -Matrix DoubleShiftQRMethod(const Matrix &matrix) { - auto H = HessenbergMethod(matrix).H; +DoubleShiftQRMethod_Result DoubleShiftQRMethod(const Matrix &A) { + auto P = Matrix::identity(A.rows); + auto H = HessenbergMethod(A).H; - auto n = matrix.rows; + auto n = A.rows; auto m = n - 1; auto s = H.matrix[m - 1][m - 1] + H.matrix[n - 1][n - 1]; auto t = H.matrix[m - 1][m - 1] * H.matrix[n - 1][n - 1] - H.matrix[m - 1][n - 1] * H.matrix[n - 1][m - 1]; @@ -15,65 +16,9 @@ Matrix DoubleShiftQRMethod(const Matrix &matrix) { auto y = H.matrix[1][0] * (H.matrix[0][0] + H.matrix[1][1] - s); auto z = H.matrix[1][0] * H.matrix[2][1]; - Vector b; - lld beta; - - for (ull k = 0; k < n - 2; k++) { - auto tmpVector = Vector(std::vector{x, y, z}); - HouseHolderMethod(tmpVector, b, beta); - auto w = product(b, b) * beta; - - auto q = MAX(1, k); - auto H_sub = H.sub_matrix(k, k + 3, q - 1, n); - H_sub = H_sub - w * H_sub; - H.set(k, k + 3, q - 1, n, H_sub); - - auto r = MIN(k + 3, n); - H_sub = H.sub_matrix(0, r, k, k + 3); - H_sub = H_sub - H_sub * w; - H.set(0, r, k, k + 3, H_sub); - - x = H.matrix[k + 1][k]; - y = H.matrix[k + 2][k]; - if (k < n - 3) { - z = H.matrix[k + 3][k]; - } - } - auto tmpVector = Vector(std::vector{x, y}); - HouseHolderMethod(tmpVector, b, beta); - auto w = product(b, b) * beta; - - auto H_sub = H.sub_matrix(n - 2, n, n - 3, n); - H_sub = H_sub - w * H_sub; - H.set(n - 2, n, n - 3, n, H_sub); - - H_sub = H.sub_matrix(0, n, n - 2, n); - H_sub = H_sub - H_sub * w; - H.set(0, n, n - 2, n, H_sub); - - return H.clean(); -} - -Matrix DoubleStepQRIteration(Matrix &matrix, Matrix &P) { - // init P: - P = Matrix::identity(matrix.rows); - - auto H = HessenbergMethod(matrix).H; - - auto n = matrix.rows; - auto m = n - 1; - auto s = H.matrix[m - 1][m - 1] + H.matrix[n - 1][n - 1]; - auto t = H.matrix[m - 1][m - 1] * H.matrix[n - 1][n - 1] - H.matrix[m - 1][n - 1] * H.matrix[n - 1][m - 1]; - auto x = H.matrix[0][0] * H.matrix[0][0] + H.matrix[0][1] * H.matrix[1][0] - s * H.matrix[0][0] + t; - auto y = H.matrix[1][0] * (H.matrix[0][0] + H.matrix[1][1] - s); - auto z = H.matrix[1][0] * H.matrix[2][1]; - - Vector b; - lld beta; - for (ull k = 0; k < n - 2; k++) { auto tmpVector = Vector(std::vector{x, y, z}); - HouseHolderMethod(tmpVector, b, beta); + auto [b, beta] = HouseHolderMethod(tmpVector); auto w = product(b, b) * beta; auto q = MAX(1, k); @@ -96,8 +41,9 @@ Matrix DoubleStepQRIteration(Matrix &matrix, Matrix &P) { z = H.matrix[k + 3][k]; } } + auto tmpVector = Vector(std::vector{x, y}); - HouseHolderMethod(tmpVector, b, beta); + auto [b, beta] = HouseHolderMethod(tmpVector); auto w = product(b, b) * beta; auto H_sub = H.sub_matrix(n - 2, n, n - 3, n); @@ -108,5 +54,5 @@ Matrix DoubleStepQRIteration(Matrix &matrix, Matrix &P) { H_sub = H_sub - H_sub * w; H.set(0, n, n - 2, n, H_sub); - return H.clean(); + return {H.clean(), P}; } \ No newline at end of file diff --git a/CustomMath_lib/QRMethod/DoubleShiftQRMethod.h b/CustomMath_lib/QRMethod/DoubleShiftQRMethod.h index be82ade..43aa255 100644 --- a/CustomMath_lib/QRMethod/DoubleShiftQRMethod.h +++ b/CustomMath_lib/QRMethod/DoubleShiftQRMethod.h @@ -7,10 +7,12 @@ #include "CustomMath_lib.h" -/// P^T A P = H, returns H, P -Matrix DoubleShiftQRMethod(const Matrix &matrix); +typedef struct { + Matrix H; + Matrix P; +} DoubleShiftQRMethod_Result; /// P^T A P = H, returns H, P -Matrix DoubleStepQRIteration(Matrix &matrix, Matrix &P); +DoubleShiftQRMethod_Result DoubleShiftQRMethod(const Matrix &matrix); #endif //NUMERICAL_ALGEBRA_DOUBLESHIFTQRMETHOD_H diff --git a/CustomMath_lib/QRMethod/QRMethod.cpp b/CustomMath_lib/QRMethod/QRMethod.cpp index b7c9576..d6ab8e2 100644 --- a/CustomMath_lib/QRMethod/QRMethod.cpp +++ b/CustomMath_lib/QRMethod/QRMethod.cpp @@ -7,7 +7,6 @@ MIterationMethodOutput QRMethod(const Matrix &matrix) { Matrix H = matrix; Matrix Q; - auto P = Matrix::identity(H.rows); auto n = H.rows; ITERATION_METHOD_TIMING_START @@ -21,7 +20,6 @@ MIterationMethodOutput QRMethod(const Matrix &matrix) { H.matrix[i + 1][i] = 0; } } -// H.print(); ull m = 0; ull k = 0; @@ -64,8 +62,7 @@ MIterationMethodOutput QRMethod(const Matrix &matrix) { }; } - auto H22 = H.sub_matrix(l, n - m, l, n - m); - H22 = DoubleStepQRIteration(H22, P); + auto [H22, P] = DoubleShiftQRMethod(H.sub_matrix(l, n - m, l, n - m)); H.set(l, n - m, l, n - m, H22); auto Q_tmp = Matrix::identity(n); @@ -145,7 +142,7 @@ std::vector AllEigenValues(const Matrix &R) { return result; } -void print_llc(const std::vector& vec) { +void print_llc(const std::vector &vec) { for (auto i: vec) { std::cout << i.real << " + " << i.complex << "i" << std::endl; } diff --git a/CustomMath_lib/QRMethod/QRMethod.h b/CustomMath_lib/QRMethod/QRMethod.h index f7e6c0e..6fe9f07 100644 --- a/CustomMath_lib/QRMethod/QRMethod.h +++ b/CustomMath_lib/QRMethod/QRMethod.h @@ -22,6 +22,6 @@ VIterationMethodOutput AllRootsForPolynomial(const Vector &coefficients); std::vector AllEigenValues(const Matrix &R); -void print_llc(const std::vector& vec); +void print_llc(const std::vector &vec); #endif //NUMERICAL_ALGEBRA_QRMETHOD_H diff --git a/Doctests/BaseTests/MatrixTest.cpp b/Doctests/BaseTests/MatrixTest.cpp index b308f82..df29728 100644 --- a/Doctests/BaseTests/MatrixTest.cpp +++ b/Doctests/BaseTests/MatrixTest.cpp @@ -169,7 +169,7 @@ TEST_CASE("Matrix/MatrixProperties") { CHECK_THROWS(m = m2.diagonal_inverse()); m = Matrix("[1 0 0; 4 0 0; 9 0 0]"); - CHECK_EQ(cmp(m.norm(),std::sqrt(98)), true); + CHECK_EQ(cmp(m.norm(), std::sqrt(98)), true); m = Matrix("[1 2 3; 4 5 6; 7 8 9]"); CHECK_EQ(m.max(), 9); diff --git a/Doctests/GeneralTests/GaussMethodTest.cpp b/Doctests/GeneralTests/GaussMethodTest.cpp index e56043b..ed2762f 100644 --- a/Doctests/GeneralTests/GaussMethodTest.cpp +++ b/Doctests/GeneralTests/GaussMethodTest.cpp @@ -6,59 +6,46 @@ #include "../doctest.h" TEST_CASE("GaussMethod::LowerTriangleMatrix_Solve()") { - Matrix A; - Vector b, x, expected_x; + auto A = Matrix("[1 0 0; 5 -8 0; -2 -6 -1]"); + auto b = Vector("[8 8 8]"); + auto expected_x = Vector("[8 4 -48]"); - A = Matrix("[1 0 0; 5 -8 0; -2 -6 -1]"); - b = Vector("[8 8 8]"); - expected_x = Vector("[8 4 -48]"); - - x = LowerTriangleMatrix_Solve(A, b); + auto x = LowerTriangleMatrix_Solve(A, b); CHECK_EQ(x, expected_x); } TEST_CASE("GaussMethod::UpperTriangleMatrix_Solve()") { - Matrix A; - Vector b, x, expected_x; - - A = Matrix("[9 -8 2; 0 -4 10; 0 0 3]"); - b = Vector("[2 -8 6]"); - expected_x = Vector("[6 7 2]"); + auto A = Matrix("[9 -8 2; 0 -4 10; 0 0 3]"); + auto b = Vector("[2 -8 6]"); + auto expected_x = Vector("[6 7 2]"); + auto x = UpperTriangleMatrix_Solve(A, b); - x = UpperTriangleMatrix_Solve(A, b); CHECK_EQ(x, expected_x); } TEST_CASE("GaussMethod::LU_Decomposition()") { - Matrix A, L, U, expected_L, expected_U; - A = Matrix("[-2 10 2; 6 0 4; 4 10 8]"); - expected_L = Matrix("[1 0 0; -3 1 0; -2 1 1]"); - expected_U = Matrix("[-2 10 2; 0 30 10; 0 0 2]"); - - LU_Decomposition(A, L, U); + auto A = Matrix("[-2 10 2; 6 0 4; 4 10 8]"); + auto expected_L = Matrix("[1 0 0; -3 1 0; -2 1 1]"); + auto expected_U = Matrix("[-2 10 2; 0 30 10; 0 0 2]"); + auto [L, U] = LU_Decomposition(A); CHECK_EQ(L, expected_L); CHECK_EQ(U, expected_U); } TEST_CASE("GaussMethod::LU_FP_Decomposition()") { - Matrix A, L, U, P, Q; - A = Matrix("[-2 10 2; 6 0 4; 4 10 8]"); - - LU_FP_Decomposition(A, L, U, P, Q); - - Matrix PAQ = P * A * Q; - Matrix LU = L * U; + auto A = Matrix("[-2 10 2; 6 0 4; 4 10 8]"); + auto [L, U, P, Q] = LU_FP_Decomposition(A); + auto PAQ = P * A * Q; + auto LU = L * U; CHECK_EQ(PAQ, LU); } TEST_CASE("GaussMethod::LU_PP_Decomposition()") { - Matrix A, L, U, P; - - A = Matrix("[-2 10 2; 6 0 4; 4 10 8]"); - LU_PP_Decomposition(A, L, U, P); + auto A = Matrix("[-2 10 2; 6 0 4; 4 10 8]"); + auto [L, U, P] = LU_PP_Decomposition(A); Matrix PA = P * A; Matrix LU = L * U; diff --git a/Doctests/doctest.h b/Doctests/doctest.h index 5c754cd..0c5ff92 100644 --- a/Doctests/doctest.h +++ b/Doctests/doctest.h @@ -87,7 +87,7 @@ #endif // MSVC #if defined(__clang__) && defined(__clang_minor__) && defined(__clang_patchlevel__) #define DOCTEST_CLANG DOCTEST_COMPILER(__clang_major__, __clang_minor__, __clang_patchlevel__) -#elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) && \ +#elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) && \ !defined(__INTEL_COMPILER) #define DOCTEST_GCC DOCTEST_COMPILER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) #endif // GCC @@ -278,7 +278,7 @@ DOCTEST_MSVC_SUPPRESS_WARNING(4623) // default constructor was implicitly define #undef DOCTEST_CONFIG_WINDOWS_SEH #endif // DOCTEST_CONFIG_NO_WINDOWS_SEH -#if !defined(_WIN32) && !defined(__QNX__) && !defined(DOCTEST_CONFIG_POSIX_SIGNALS) && \ +#if !defined(_WIN32) && !defined(__QNX__) && !defined(DOCTEST_CONFIG_POSIX_SIGNALS) && \ !defined(__EMSCRIPTEN__) && !defined(__wasi__) #define DOCTEST_CONFIG_POSIX_SIGNALS #endif // _WIN32 @@ -288,7 +288,7 @@ DOCTEST_MSVC_SUPPRESS_WARNING(4623) // default constructor was implicitly define #ifndef DOCTEST_CONFIG_NO_EXCEPTIONS #if !defined(__cpp_exceptions) && !defined(__EXCEPTIONS) && !defined(_CPPUNWIND) \ - || defined(__wasi__) + || defined(__wasi__) #define DOCTEST_CONFIG_NO_EXCEPTIONS #endif // no exceptions #endif // DOCTEST_CONFIG_NO_EXCEPTIONS @@ -443,9 +443,11 @@ DOCTEST_MSVC_SUPPRESS_WARNING(4623) // default constructor was implicitly define #define DOCTEST_PLATFORM_LINUX #endif // DOCTEST_PLATFORM -namespace doctest { namespace detail { - static DOCTEST_CONSTEXPR int consume(const int*, int) noexcept { return 0; } -}} +namespace doctest { + namespace detail { + static DOCTEST_CONSTEXPR int consume(const int *, int) noexcept { return 0; } + } +} #define DOCTEST_GLOBAL_NO_WARNINGS(var, ...) \ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wglobal-constructors") \ @@ -496,7 +498,9 @@ DOCTEST_GCC_SUPPRESS_WARNING_POP // https://github.com/doctest/doctest/issues/126 // https://github.com/doctest/doctest/issues/356 #if DOCTEST_CLANG + #include + #endif // clang #ifdef _LIBCPP_VERSION @@ -513,6 +517,7 @@ DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN #include #include #include + DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END #else // DOCTEST_CONFIG_USE_STD_HEADERS @@ -552,14 +557,16 @@ DOCTEST_MSVC_SUPPRESS_WARNING_POP #endif // DOCTEST_CONFIG_USE_STD_HEADERS #ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS + #include + #endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS namespace doctest { -using std::size_t; + using std::size_t; -DOCTEST_INTERFACE extern bool is_running_in_test; + DOCTEST_INTERFACE extern bool is_running_in_test; #ifndef DOCTEST_CONFIG_STRING_SIZE_TYPE #define DOCTEST_CONFIG_STRING_SIZE_TYPE unsigned @@ -584,502 +591,525 @@ DOCTEST_INTERFACE extern bool is_running_in_test; // - push_back/pop_back // - assign/insert/erase // - relational operators as free functions - taking const char* as one of the params -class DOCTEST_INTERFACE String -{ -public: - using size_type = DOCTEST_CONFIG_STRING_SIZE_TYPE; + class DOCTEST_INTERFACE String { + public: + using size_type = DOCTEST_CONFIG_STRING_SIZE_TYPE; -private: - static DOCTEST_CONSTEXPR size_type len = 24; //!OCLINT avoid private static members - static DOCTEST_CONSTEXPR size_type last = len - 1; //!OCLINT avoid private static members + private: + static DOCTEST_CONSTEXPR size_type len = 24; //!OCLINT avoid private static members + static DOCTEST_CONSTEXPR size_type last = len - 1; //!OCLINT avoid private static members - struct view // len should be more than sizeof(view) - because of the final byte for flags - { - char* ptr; - size_type size; - size_type capacity; - }; + struct view // len should be more than sizeof(view) - because of the final byte for flags + { + char *ptr; + size_type size; + size_type capacity; + }; - union - { - char buf[len]; // NOLINT(*-avoid-c-arrays) - view data; - }; + union { + char buf[len]; // NOLINT(*-avoid-c-arrays) + view data; + }; - char* allocate(size_type sz); + char *allocate(size_type sz); - bool isOnStack() const noexcept { return (buf[last] & 128) == 0; } - void setOnHeap() noexcept; - void setLast(size_type in = last) noexcept; - void setSize(size_type sz) noexcept; + bool isOnStack() const noexcept { return (buf[last] & 128) == 0; } - void copy(const String& other); + void setOnHeap() noexcept; -public: - static DOCTEST_CONSTEXPR size_type npos = static_cast(-1); + void setLast(size_type in = last) noexcept; + + void setSize(size_type sz) noexcept; + + void copy(const String &other); + + public: + static DOCTEST_CONSTEXPR size_type npos = static_cast(-1); + + String() noexcept; + + ~String(); + + // cppcheck-suppress noExplicitConstructor + String(const char *in); - String() noexcept; - ~String(); + String(const char *in, size_type in_size); - // cppcheck-suppress noExplicitConstructor - String(const char* in); - String(const char* in, size_type in_size); + String(std::istream &in, size_type in_size); - String(std::istream& in, size_type in_size); + String(const String &other); - String(const String& other); - String& operator=(const String& other); + String &operator=(const String &other); - String& operator+=(const String& other); + String &operator+=(const String &other); - String(String&& other) noexcept; - String& operator=(String&& other) noexcept; + String(String &&other) noexcept; - char operator[](size_type i) const; - char& operator[](size_type i); + String &operator=(String &&other) noexcept; - // the only functions I'm willing to leave in the interface - available for inlining - const char* c_str() const { return const_cast(this)->c_str(); } // NOLINT - char* c_str() { - if (isOnStack()) { - return reinterpret_cast(buf); + char operator[](size_type i) const; + + char &operator[](size_type i); + + // the only functions I'm willing to leave in the interface - available for inlining + const char *c_str() const { return const_cast(this)->c_str(); } // NOLINT + char *c_str() { + if (isOnStack()) { + return reinterpret_cast(buf); + } + return data.ptr; } - return data.ptr; - } - size_type size() const; - size_type capacity() const; + size_type size() const; - String substr(size_type pos, size_type cnt = npos) &&; - String substr(size_type pos, size_type cnt = npos) const &; + size_type capacity() const; - size_type find(char ch, size_type pos = 0) const; - size_type rfind(char ch, size_type pos = npos) const; + String substr(size_type pos, size_type cnt = npos) &&; - int compare(const char* other, bool no_case = false) const; - int compare(const String& other, bool no_case = false) const; + String substr(size_type pos, size_type cnt = npos) const &; -friend DOCTEST_INTERFACE std::ostream& operator<<(std::ostream& s, const String& in); -}; + size_type find(char ch, size_type pos = 0) const; -DOCTEST_INTERFACE String operator+(const String& lhs, const String& rhs); + size_type rfind(char ch, size_type pos = npos) const; -DOCTEST_INTERFACE bool operator==(const String& lhs, const String& rhs); -DOCTEST_INTERFACE bool operator!=(const String& lhs, const String& rhs); -DOCTEST_INTERFACE bool operator<(const String& lhs, const String& rhs); -DOCTEST_INTERFACE bool operator>(const String& lhs, const String& rhs); -DOCTEST_INTERFACE bool operator<=(const String& lhs, const String& rhs); -DOCTEST_INTERFACE bool operator>=(const String& lhs, const String& rhs); + int compare(const char *other, bool no_case = false) const; -class DOCTEST_INTERFACE Contains { -public: - explicit Contains(const String& string); + int compare(const String &other, bool no_case = false) const; - bool checkWith(const String& other) const; + friend DOCTEST_INTERFACE std::ostream &operator<<(std::ostream &s, const String &in); + }; - String string; -}; + DOCTEST_INTERFACE String operator+(const String &lhs, const String &rhs); -DOCTEST_INTERFACE String toString(const Contains& in); + DOCTEST_INTERFACE bool operator==(const String &lhs, const String &rhs); -DOCTEST_INTERFACE bool operator==(const String& lhs, const Contains& rhs); -DOCTEST_INTERFACE bool operator==(const Contains& lhs, const String& rhs); -DOCTEST_INTERFACE bool operator!=(const String& lhs, const Contains& rhs); -DOCTEST_INTERFACE bool operator!=(const Contains& lhs, const String& rhs); + DOCTEST_INTERFACE bool operator!=(const String &lhs, const String &rhs); -namespace Color { - enum Enum - { - None = 0, - White, - Red, - Green, - Blue, - Cyan, - Yellow, - Grey, - - Bright = 0x10, - - BrightRed = Bright | Red, - BrightGreen = Bright | Green, - LightGrey = Bright | Grey, - BrightWhite = Bright | White + DOCTEST_INTERFACE bool operator<(const String &lhs, const String &rhs); + + DOCTEST_INTERFACE bool operator>(const String &lhs, const String &rhs); + + DOCTEST_INTERFACE bool operator<=(const String &lhs, const String &rhs); + + DOCTEST_INTERFACE bool operator>=(const String &lhs, const String &rhs); + + class DOCTEST_INTERFACE Contains { + public: + explicit Contains(const String &string); + + bool checkWith(const String &other) const; + + String string; }; - DOCTEST_INTERFACE std::ostream& operator<<(std::ostream& s, Color::Enum code); -} // namespace Color + DOCTEST_INTERFACE String toString(const Contains &in); -namespace assertType { - enum Enum - { - // macro traits + DOCTEST_INTERFACE bool operator==(const String &lhs, const Contains &rhs); + + DOCTEST_INTERFACE bool operator==(const Contains &lhs, const String &rhs); + + DOCTEST_INTERFACE bool operator!=(const String &lhs, const Contains &rhs); - is_warn = 1, - is_check = 2 * is_warn, - is_require = 2 * is_check, + DOCTEST_INTERFACE bool operator!=(const Contains &lhs, const String &rhs); - is_normal = 2 * is_require, - is_throws = 2 * is_normal, - is_throws_as = 2 * is_throws, - is_throws_with = 2 * is_throws_as, - is_nothrow = 2 * is_throws_with, + namespace Color { + enum Enum { + None = 0, + White, + Red, + Green, + Blue, + Cyan, + Yellow, + Grey, - is_false = 2 * is_nothrow, - is_unary = 2 * is_false, // not checked anywhere - used just to distinguish the types + Bright = 0x10, - is_eq = 2 * is_unary, - is_ne = 2 * is_eq, + BrightRed = Bright | Red, + BrightGreen = Bright | Green, + LightGrey = Bright | Grey, + BrightWhite = Bright | White + }; + + DOCTEST_INTERFACE std::ostream &operator<<(std::ostream &s, Color::Enum code); + } // namespace Color + + namespace assertType { + enum Enum { + // macro traits + + is_warn = 1, + is_check = 2 * is_warn, + is_require = 2 * is_check, - is_lt = 2 * is_ne, - is_gt = 2 * is_lt, + is_normal = 2 * is_require, + is_throws = 2 * is_normal, + is_throws_as = 2 * is_throws, + is_throws_with = 2 * is_throws_as, + is_nothrow = 2 * is_throws_with, - is_ge = 2 * is_gt, - is_le = 2 * is_ge, + is_false = 2 * is_nothrow, + is_unary = 2 * is_false, // not checked anywhere - used just to distinguish the types - // macro types + is_eq = 2 * is_unary, + is_ne = 2 * is_eq, - DT_WARN = is_normal | is_warn, - DT_CHECK = is_normal | is_check, - DT_REQUIRE = is_normal | is_require, + is_lt = 2 * is_ne, + is_gt = 2 * is_lt, - DT_WARN_FALSE = is_normal | is_false | is_warn, - DT_CHECK_FALSE = is_normal | is_false | is_check, - DT_REQUIRE_FALSE = is_normal | is_false | is_require, + is_ge = 2 * is_gt, + is_le = 2 * is_ge, - DT_WARN_THROWS = is_throws | is_warn, - DT_CHECK_THROWS = is_throws | is_check, - DT_REQUIRE_THROWS = is_throws | is_require, + // macro types - DT_WARN_THROWS_AS = is_throws_as | is_warn, - DT_CHECK_THROWS_AS = is_throws_as | is_check, - DT_REQUIRE_THROWS_AS = is_throws_as | is_require, + DT_WARN = is_normal | is_warn, + DT_CHECK = is_normal | is_check, + DT_REQUIRE = is_normal | is_require, - DT_WARN_THROWS_WITH = is_throws_with | is_warn, - DT_CHECK_THROWS_WITH = is_throws_with | is_check, - DT_REQUIRE_THROWS_WITH = is_throws_with | is_require, + DT_WARN_FALSE = is_normal | is_false | is_warn, + DT_CHECK_FALSE = is_normal | is_false | is_check, + DT_REQUIRE_FALSE = is_normal | is_false | is_require, - DT_WARN_THROWS_WITH_AS = is_throws_with | is_throws_as | is_warn, - DT_CHECK_THROWS_WITH_AS = is_throws_with | is_throws_as | is_check, - DT_REQUIRE_THROWS_WITH_AS = is_throws_with | is_throws_as | is_require, + DT_WARN_THROWS = is_throws | is_warn, + DT_CHECK_THROWS = is_throws | is_check, + DT_REQUIRE_THROWS = is_throws | is_require, - DT_WARN_NOTHROW = is_nothrow | is_warn, - DT_CHECK_NOTHROW = is_nothrow | is_check, - DT_REQUIRE_NOTHROW = is_nothrow | is_require, + DT_WARN_THROWS_AS = is_throws_as | is_warn, + DT_CHECK_THROWS_AS = is_throws_as | is_check, + DT_REQUIRE_THROWS_AS = is_throws_as | is_require, - DT_WARN_EQ = is_normal | is_eq | is_warn, - DT_CHECK_EQ = is_normal | is_eq | is_check, - DT_REQUIRE_EQ = is_normal | is_eq | is_require, + DT_WARN_THROWS_WITH = is_throws_with | is_warn, + DT_CHECK_THROWS_WITH = is_throws_with | is_check, + DT_REQUIRE_THROWS_WITH = is_throws_with | is_require, - DT_WARN_NE = is_normal | is_ne | is_warn, - DT_CHECK_NE = is_normal | is_ne | is_check, - DT_REQUIRE_NE = is_normal | is_ne | is_require, + DT_WARN_THROWS_WITH_AS = is_throws_with | is_throws_as | is_warn, + DT_CHECK_THROWS_WITH_AS = is_throws_with | is_throws_as | is_check, + DT_REQUIRE_THROWS_WITH_AS = is_throws_with | is_throws_as | is_require, - DT_WARN_GT = is_normal | is_gt | is_warn, - DT_CHECK_GT = is_normal | is_gt | is_check, - DT_REQUIRE_GT = is_normal | is_gt | is_require, + DT_WARN_NOTHROW = is_nothrow | is_warn, + DT_CHECK_NOTHROW = is_nothrow | is_check, + DT_REQUIRE_NOTHROW = is_nothrow | is_require, - DT_WARN_LT = is_normal | is_lt | is_warn, - DT_CHECK_LT = is_normal | is_lt | is_check, - DT_REQUIRE_LT = is_normal | is_lt | is_require, + DT_WARN_EQ = is_normal | is_eq | is_warn, + DT_CHECK_EQ = is_normal | is_eq | is_check, + DT_REQUIRE_EQ = is_normal | is_eq | is_require, - DT_WARN_GE = is_normal | is_ge | is_warn, - DT_CHECK_GE = is_normal | is_ge | is_check, - DT_REQUIRE_GE = is_normal | is_ge | is_require, + DT_WARN_NE = is_normal | is_ne | is_warn, + DT_CHECK_NE = is_normal | is_ne | is_check, + DT_REQUIRE_NE = is_normal | is_ne | is_require, - DT_WARN_LE = is_normal | is_le | is_warn, - DT_CHECK_LE = is_normal | is_le | is_check, - DT_REQUIRE_LE = is_normal | is_le | is_require, + DT_WARN_GT = is_normal | is_gt | is_warn, + DT_CHECK_GT = is_normal | is_gt | is_check, + DT_REQUIRE_GT = is_normal | is_gt | is_require, - DT_WARN_UNARY = is_normal | is_unary | is_warn, - DT_CHECK_UNARY = is_normal | is_unary | is_check, - DT_REQUIRE_UNARY = is_normal | is_unary | is_require, + DT_WARN_LT = is_normal | is_lt | is_warn, + DT_CHECK_LT = is_normal | is_lt | is_check, + DT_REQUIRE_LT = is_normal | is_lt | is_require, - DT_WARN_UNARY_FALSE = is_normal | is_false | is_unary | is_warn, - DT_CHECK_UNARY_FALSE = is_normal | is_false | is_unary | is_check, - DT_REQUIRE_UNARY_FALSE = is_normal | is_false | is_unary | is_require, + DT_WARN_GE = is_normal | is_ge | is_warn, + DT_CHECK_GE = is_normal | is_ge | is_check, + DT_REQUIRE_GE = is_normal | is_ge | is_require, + + DT_WARN_LE = is_normal | is_le | is_warn, + DT_CHECK_LE = is_normal | is_le | is_check, + DT_REQUIRE_LE = is_normal | is_le | is_require, + + DT_WARN_UNARY = is_normal | is_unary | is_warn, + DT_CHECK_UNARY = is_normal | is_unary | is_check, + DT_REQUIRE_UNARY = is_normal | is_unary | is_require, + + DT_WARN_UNARY_FALSE = is_normal | is_false | is_unary | is_warn, + DT_CHECK_UNARY_FALSE = is_normal | is_false | is_unary | is_check, + DT_REQUIRE_UNARY_FALSE = is_normal | is_false | is_unary | is_require, + }; + } // namespace assertType + + DOCTEST_INTERFACE const char *assertString(assertType::Enum at); + + DOCTEST_INTERFACE const char *failureString(assertType::Enum at); + + DOCTEST_INTERFACE const char *skipPathFromFilename(const char *file); + + struct DOCTEST_INTERFACE TestCaseData { + String m_file; // the file in which the test was registered (using String - see #350) + unsigned m_line; // the line where the test was registered + const char *m_name; // name of the test case + const char *m_test_suite; // the test suite in which the test was added + const char *m_description; + bool m_skip; + bool m_no_breaks; + bool m_no_output; + bool m_may_fail; + bool m_should_fail; + int m_expected_failures; + double m_timeout; }; -} // namespace assertType -DOCTEST_INTERFACE const char* assertString(assertType::Enum at); -DOCTEST_INTERFACE const char* failureString(assertType::Enum at); -DOCTEST_INTERFACE const char* skipPathFromFilename(const char* file); + struct DOCTEST_INTERFACE AssertData { + // common - for all asserts + const TestCaseData *m_test_case; + assertType::Enum m_at; + const char *m_file; + int m_line; + const char *m_expr; + bool m_failed; -struct DOCTEST_INTERFACE TestCaseData -{ - String m_file; // the file in which the test was registered (using String - see #350) - unsigned m_line; // the line where the test was registered - const char* m_name; // name of the test case - const char* m_test_suite; // the test suite in which the test was added - const char* m_description; - bool m_skip; - bool m_no_breaks; - bool m_no_output; - bool m_may_fail; - bool m_should_fail; - int m_expected_failures; - double m_timeout; -}; - -struct DOCTEST_INTERFACE AssertData -{ - // common - for all asserts - const TestCaseData* m_test_case; - assertType::Enum m_at; - const char* m_file; - int m_line; - const char* m_expr; - bool m_failed; - - // exception-related - for all asserts - bool m_threw; - String m_exception; - - // for normal asserts - String m_decomp; - - // for specific exception-related asserts - bool m_threw_as; - const char* m_exception_type; - - class DOCTEST_INTERFACE StringContains { + // exception-related - for all asserts + bool m_threw; + String m_exception; + + // for normal asserts + String m_decomp; + + // for specific exception-related asserts + bool m_threw_as; + const char *m_exception_type; + + class DOCTEST_INTERFACE StringContains { private: Contains content; bool isContains; public: - StringContains(const String& str) : content(str), isContains(false) { } - StringContains(Contains cntn) : content(static_cast(cntn)), isContains(true) { } + StringContains(const String &str) : content(str), isContains(false) {} - bool check(const String& str) { return isContains ? (content == str) : (content.string == str); } + StringContains(Contains cntn) : content(static_cast(cntn)), isContains(true) {} - operator const String&() const { return content.string; } + bool check(const String &str) { return isContains ? (content == str) : (content.string == str); } - const char* c_str() const { return content.string.c_str(); } - } m_exception_string; + operator const String &() const { return content.string; } - AssertData(assertType::Enum at, const char* file, int line, const char* expr, - const char* exception_type, const StringContains& exception_string); -}; + const char *c_str() const { return content.string.c_str(); } + } m_exception_string; -struct DOCTEST_INTERFACE MessageData -{ - String m_string; - const char* m_file; - int m_line; - assertType::Enum m_severity; -}; + AssertData(assertType::Enum at, const char *file, int line, const char *expr, + const char *exception_type, const StringContains &exception_string); + }; -struct DOCTEST_INTERFACE SubcaseSignature -{ - String m_name; - const char* m_file; - int m_line; + struct DOCTEST_INTERFACE MessageData { + String m_string; + const char *m_file; + int m_line; + assertType::Enum m_severity; + }; - bool operator==(const SubcaseSignature& other) const; - bool operator<(const SubcaseSignature& other) const; -}; + struct DOCTEST_INTERFACE SubcaseSignature { + String m_name; + const char *m_file; + int m_line; -struct DOCTEST_INTERFACE IContextScope -{ - DOCTEST_DECLARE_INTERFACE(IContextScope) - virtual void stringify(std::ostream*) const = 0; -}; + bool operator==(const SubcaseSignature &other) const; -namespace detail { - struct DOCTEST_INTERFACE TestCase; -} // namespace detail + bool operator<(const SubcaseSignature &other) const; + }; -struct ContextOptions //!OCLINT too many fields -{ - std::ostream* cout = nullptr; // stdout stream - String binary_name; // the test binary name - - const detail::TestCase* currentTest = nullptr; - - // == parameters from the command line - String out; // output filename - String order_by; // how tests should be ordered - unsigned rand_seed; // the seed for rand ordering - - unsigned first; // the first (matching) test to be executed - unsigned last; // the last (matching) test to be executed - - int abort_after; // stop tests after this many failed assertions - int subcase_filter_levels; // apply the subcase filters for the first N levels - - bool success; // include successful assertions in output - bool case_sensitive; // if filtering should be case sensitive - bool exit; // if the program should be exited after the tests are ran/whatever - bool duration; // print the time duration of each test case - bool minimal; // minimal console output (only test failures) - bool quiet; // no console output - bool no_throw; // to skip exceptions-related assertion macros - bool no_exitcode; // if the framework should return 0 as the exitcode - bool no_run; // to not run the tests at all (can be done with an "*" exclude) - bool no_intro; // to not print the intro of the framework - bool no_version; // to not print the version of the framework - bool no_colors; // if output to the console should be colorized - bool force_colors; // forces the use of colors even when a tty cannot be detected - bool no_breaks; // to not break into the debugger - bool no_skip; // don't skip test cases which are marked to be skipped - bool gnu_file_line; // if line numbers should be surrounded with :x: and not (x): - bool no_path_in_filenames; // if the path to files should be removed from the output - bool no_line_numbers; // if source code line numbers should be omitted from the output - bool no_debug_output; // no output in the debug console when a debugger is attached - bool no_skipped_summary; // don't print "skipped" in the summary !!! UNDOCUMENTED !!! - bool no_time_in_output; // omit any time/timestamps from output !!! UNDOCUMENTED !!! - - bool help; // to print the help - bool version; // to print the version - bool count; // if only the count of matching tests is to be retrieved - bool list_test_cases; // to list all tests matching the filters - bool list_test_suites; // to list all suites matching the filters - bool list_reporters; // lists all registered reporters -}; + struct DOCTEST_INTERFACE IContextScope { + DOCTEST_DECLARE_INTERFACE(IContextScope) -namespace detail { - namespace types { + virtual void stringify(std::ostream *) const = 0; + }; + + namespace detail { + struct DOCTEST_INTERFACE TestCase; + } // namespace detail + + struct ContextOptions //!OCLINT too many fields + { + std::ostream *cout = nullptr; // stdout stream + String binary_name; // the test binary name + + const detail::TestCase *currentTest = nullptr; + + // == parameters from the command line + String out; // output filename + String order_by; // how tests should be ordered + unsigned rand_seed; // the seed for rand ordering + + unsigned first; // the first (matching) test to be executed + unsigned last; // the last (matching) test to be executed + + int abort_after; // stop tests after this many failed assertions + int subcase_filter_levels; // apply the subcase filters for the first N levels + + bool success; // include successful assertions in output + bool case_sensitive; // if filtering should be case sensitive + bool exit; // if the program should be exited after the tests are ran/whatever + bool duration; // print the time duration of each test case + bool minimal; // minimal console output (only test failures) + bool quiet; // no console output + bool no_throw; // to skip exceptions-related assertion macros + bool no_exitcode; // if the framework should return 0 as the exitcode + bool no_run; // to not run the tests at all (can be done with an "*" exclude) + bool no_intro; // to not print the intro of the framework + bool no_version; // to not print the version of the framework + bool no_colors; // if output to the console should be colorized + bool force_colors; // forces the use of colors even when a tty cannot be detected + bool no_breaks; // to not break into the debugger + bool no_skip; // don't skip test cases which are marked to be skipped + bool gnu_file_line; // if line numbers should be surrounded with :x: and not (x): + bool no_path_in_filenames; // if the path to files should be removed from the output + bool no_line_numbers; // if source code line numbers should be omitted from the output + bool no_debug_output; // no output in the debug console when a debugger is attached + bool no_skipped_summary; // don't print "skipped" in the summary !!! UNDOCUMENTED !!! + bool no_time_in_output; // omit any time/timestamps from output !!! UNDOCUMENTED !!! + + bool help; // to print the help + bool version; // to print the version + bool count; // if only the count of matching tests is to be retrieved + bool list_test_cases; // to list all tests matching the filters + bool list_test_suites; // to list all suites matching the filters + bool list_reporters; // lists all registered reporters + }; + + namespace detail { + namespace types { #ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS - using namespace std; + using namespace std; #else - template - struct enable_if { }; + template + struct enable_if { }; - template - struct enable_if { using type = T; }; + template + struct enable_if { using type = T; }; - struct true_type { static DOCTEST_CONSTEXPR bool value = true; }; - struct false_type { static DOCTEST_CONSTEXPR bool value = false; }; + struct true_type { static DOCTEST_CONSTEXPR bool value = true; }; + struct false_type { static DOCTEST_CONSTEXPR bool value = false; }; - template struct remove_reference { using type = T; }; - template struct remove_reference { using type = T; }; - template struct remove_reference { using type = T; }; + template struct remove_reference { using type = T; }; + template struct remove_reference { using type = T; }; + template struct remove_reference { using type = T; }; - template struct is_rvalue_reference : false_type { }; - template struct is_rvalue_reference : true_type { }; + template struct is_rvalue_reference : false_type { }; + template struct is_rvalue_reference : true_type { }; - template struct remove_const { using type = T; }; - template struct remove_const { using type = T; }; + template struct remove_const { using type = T; }; + template struct remove_const { using type = T; }; - // Compiler intrinsics - template struct is_enum { static DOCTEST_CONSTEXPR bool value = __is_enum(T); }; - template struct underlying_type { using type = __underlying_type(T); }; + // Compiler intrinsics + template struct is_enum { static DOCTEST_CONSTEXPR bool value = __is_enum(T); }; + template struct underlying_type { using type = __underlying_type(T); }; - template struct is_pointer : false_type { }; - template struct is_pointer : true_type { }; + template struct is_pointer : false_type { }; + template struct is_pointer : true_type { }; - template struct is_array : false_type { }; - // NOLINTNEXTLINE(*-avoid-c-arrays) - template struct is_array : true_type { }; + template struct is_array : false_type { }; + // NOLINTNEXTLINE(*-avoid-c-arrays) + template struct is_array : true_type { }; #endif - } + } - // - template - T&& declval(); + // + template + T &&declval(); - template - DOCTEST_CONSTEXPR_FUNC T&& forward(typename types::remove_reference::type& t) DOCTEST_NOEXCEPT { - return static_cast(t); - } + template + DOCTEST_CONSTEXPR_FUNC T &&forward(typename types::remove_reference::type &t) DOCTEST_NOEXCEPT { + return static_cast(t); + } - template - DOCTEST_CONSTEXPR_FUNC T&& forward(typename types::remove_reference::type&& t) DOCTEST_NOEXCEPT { - return static_cast(t); - } + template + DOCTEST_CONSTEXPR_FUNC T &&forward(typename types::remove_reference::type &&t) DOCTEST_NOEXCEPT { + return static_cast(t); + } - template - struct deferred_false : types::false_type { }; + template + struct deferred_false : types::false_type { + }; // MSVS 2015 :( #if !DOCTEST_CLANG && defined(_MSC_VER) && _MSC_VER <= 1900 - template - struct has_global_insertion_operator : types::false_type { }; + template + struct has_global_insertion_operator : types::false_type { }; - template - struct has_global_insertion_operator(), declval()), void())> : types::true_type { }; + template + struct has_global_insertion_operator(), declval()), void())> : types::true_type { }; - template - struct has_insertion_operator { static DOCTEST_CONSTEXPR bool value = has_global_insertion_operator::value; }; + template + struct has_insertion_operator { static DOCTEST_CONSTEXPR bool value = has_global_insertion_operator::value; }; - template - struct insert_hack; + template + struct insert_hack; - template - struct insert_hack { - static void insert(std::ostream& os, const T& t) { ::operator<<(os, t); } - }; + template + struct insert_hack { + static void insert(std::ostream& os, const T& t) { ::operator<<(os, t); } + }; - template - struct insert_hack { - static void insert(std::ostream& os, const T& t) { operator<<(os, t); } - }; + template + struct insert_hack { + static void insert(std::ostream& os, const T& t) { operator<<(os, t); } + }; - template - using insert_hack_t = insert_hack::value>; + template + using insert_hack_t = insert_hack::value>; #else - template - struct has_insertion_operator : types::false_type { }; + template + struct has_insertion_operator : types::false_type { + }; #endif - template - struct has_insertion_operator(), declval()), void())> : types::true_type { }; + template + struct has_insertion_operator(), declval()), void())> + : types::true_type { + }; - template - struct should_stringify_as_underlying_type { - static DOCTEST_CONSTEXPR bool value = detail::types::is_enum::value && !doctest::detail::has_insertion_operator::value; - }; + template + struct should_stringify_as_underlying_type { + static DOCTEST_CONSTEXPR bool value = + detail::types::is_enum::value && !doctest::detail::has_insertion_operator::value; + }; - DOCTEST_INTERFACE std::ostream* tlssPush(); - DOCTEST_INTERFACE String tlssPop(); + DOCTEST_INTERFACE std::ostream *tlssPush(); - template - struct StringMakerBase { - template - static String convert(const DOCTEST_REF_WRAP(T)) { + DOCTEST_INTERFACE String tlssPop(); + + template + struct StringMakerBase { + template + static String convert(const DOCTEST_REF_WRAP(T)) { #ifdef DOCTEST_CONFIG_REQUIRE_STRINGIFICATION_FOR_ALL_USED_TYPES - static_assert(deferred_false::value, "No stringification detected for type T. See string conversion manual"); + static_assert(deferred_false::value, "No stringification detected for type T. See string conversion manual"); #endif - return "{?}"; - } - }; - - template - struct filldata; + return "{?}"; + } + }; - template - void filloss(std::ostream* stream, const T& in) { - filldata::fill(stream, in); - } + template + struct filldata; - template - void filloss(std::ostream* stream, const T (&in)[N]) { // NOLINT(*-avoid-c-arrays) - // T[N], T(&)[N], T(&&)[N] have same behaviour. - // Hence remove reference. - filloss::type>(stream, in); - } + template + void filloss(std::ostream *stream, const T &in) { + filldata::fill(stream, in); + } - template - String toStream(const T& in) { - std::ostream* stream = tlssPush(); - filloss(stream, in); - return tlssPop(); - } + template + void filloss(std::ostream *stream, const T (&in)[N]) { // NOLINT(*-avoid-c-arrays) + // T[N], T(&)[N], T(&&)[N] have same behaviour. + // Hence remove reference. + filloss < typename types::remove_reference::type > (stream, in); + } - template <> - struct StringMakerBase { - template - static String convert(const DOCTEST_REF_WRAP(T) in) { - return toStream(in); + template + String toStream(const T &in) { + std::ostream *stream = tlssPush(); + filloss(stream, in); + return tlssPop(); } - }; -} // namespace detail -template -struct StringMaker : public detail::StringMakerBase< - detail::has_insertion_operator::value || detail::types::is_pointer::value || detail::types::is_array::value> -{}; + template<> + struct StringMakerBase { + template + static String convert(const DOCTEST_REF_WRAP(T)in) { + return toStream(in); + } + }; + } // namespace detail + + template + struct StringMaker : public detail::StringMakerBase< + detail::has_insertion_operator::value || detail::types::is_pointer::value || + detail::types::is_array::value> { + }; #ifndef DOCTEST_STRINGIFY #ifdef DOCTEST_CONFIG_DOUBLE_STRINGIFY @@ -1089,286 +1119,358 @@ struct StringMaker : public detail::StringMakerBase< #endif #endif -template -String toString() { + template + String toString() { #if DOCTEST_CLANG == 0 && DOCTEST_GCC == 0 && DOCTEST_ICC == 0 - String ret = __FUNCSIG__; // class doctest::String __cdecl doctest::toString(void) - String::size_type beginPos = ret.find('<'); - return ret.substr(beginPos + 1, ret.size() - beginPos - static_cast(sizeof(">(void)"))); + String ret = __FUNCSIG__; // class doctest::String __cdecl doctest::toString(void) + String::size_type beginPos = ret.find('<'); + return ret.substr(beginPos + 1, ret.size() - beginPos - static_cast(sizeof(">(void)"))); #else - String ret = __PRETTY_FUNCTION__; // doctest::String toString() [with T = TYPE] - String::size_type begin = ret.find('=') + 2; - return ret.substr(begin, ret.size() - begin - 1); + String ret = __PRETTY_FUNCTION__; // doctest::String toString() [with T = TYPE] + String::size_type begin = ret.find('=') + 2; + return ret.substr(begin, ret.size() - begin - 1); #endif -} + } -template ::value, bool>::type = true> -String toString(const DOCTEST_REF_WRAP(T) value) { - return StringMaker::convert(value); -} + template::value, bool>::type = true> + String toString(const DOCTEST_REF_WRAP(T)value) { + return StringMaker::convert(value); + } #ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING -DOCTEST_INTERFACE String toString(const char* in); + DOCTEST_INTERFACE String toString(const char* in); #endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING #if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0) -// see this issue on why this is needed: https://github.com/doctest/doctest/issues/183 -DOCTEST_INTERFACE String toString(const std::string& in); + // see this issue on why this is needed: https://github.com/doctest/doctest/issues/183 + DOCTEST_INTERFACE String toString(const std::string& in); #endif // VS 2019 -DOCTEST_INTERFACE String toString(String in); + DOCTEST_INTERFACE String toString(String in); -DOCTEST_INTERFACE String toString(std::nullptr_t); + DOCTEST_INTERFACE String toString(std::nullptr_t); -DOCTEST_INTERFACE String toString(bool in); + DOCTEST_INTERFACE String toString(bool in); -DOCTEST_INTERFACE String toString(float in); -DOCTEST_INTERFACE String toString(double in); -DOCTEST_INTERFACE String toString(double long in); + DOCTEST_INTERFACE String toString(float in); -DOCTEST_INTERFACE String toString(char in); -DOCTEST_INTERFACE String toString(char signed in); -DOCTEST_INTERFACE String toString(char unsigned in); -DOCTEST_INTERFACE String toString(short in); -DOCTEST_INTERFACE String toString(short unsigned in); -DOCTEST_INTERFACE String toString(signed in); -DOCTEST_INTERFACE String toString(unsigned in); -DOCTEST_INTERFACE String toString(long in); -DOCTEST_INTERFACE String toString(long unsigned in); -DOCTEST_INTERFACE String toString(long long in); -DOCTEST_INTERFACE String toString(long long unsigned in); + DOCTEST_INTERFACE String toString(double in); -template ::value, bool>::type = true> -String toString(const DOCTEST_REF_WRAP(T) value) { - using UT = typename detail::types::underlying_type::type; - return (DOCTEST_STRINGIFY(static_cast(value))); -} + DOCTEST_INTERFACE String toString(double long in); -namespace detail { - template - struct filldata - { - static void fill(std::ostream* stream, const T& in) { + DOCTEST_INTERFACE String toString(char in); + + DOCTEST_INTERFACE String toString(char signed in); + + DOCTEST_INTERFACE String toString(char unsigned in); + + DOCTEST_INTERFACE String toString(short in); + + DOCTEST_INTERFACE String toString(short unsigned in); + + DOCTEST_INTERFACE String toString(signed in); + + DOCTEST_INTERFACE String toString(unsigned in); + + DOCTEST_INTERFACE String toString(long in); + + DOCTEST_INTERFACE String toString(long unsigned in); + + DOCTEST_INTERFACE String toString(long long in); + + DOCTEST_INTERFACE String toString(long long unsigned in); + + template::value, bool>::type = true> + String toString(const DOCTEST_REF_WRAP(T)value) { + using UT = typename detail::types::underlying_type::type; + return (DOCTEST_STRINGIFY(static_cast(value))); + } + + namespace detail { + template + struct filldata { + static void fill(std::ostream *stream, const T &in) { #if defined(_MSC_VER) && _MSC_VER <= 1900 - insert_hack_t::insert(*stream, in); + insert_hack_t::insert(*stream, in); #else - operator<<(*stream, in); + operator<<(*stream, in); #endif - } - }; + } + }; + + DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4866) -DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4866) // NOLINTBEGIN(*-avoid-c-arrays) - template - struct filldata { - static void fill(std::ostream* stream, const T(&in)[N]) { - *stream << "["; - for (size_t i = 0; i < N; i++) { - if (i != 0) { *stream << ", "; } - *stream << (DOCTEST_STRINGIFY(in[i])); + template + struct filldata { + static void fill(std::ostream *stream, const T(&in)[N]) { + *stream << "["; + for (size_t i = 0; i < N; i++) { + if (i != 0) { *stream << ", "; } + *stream << (DOCTEST_STRINGIFY(in[i])); + } + *stream << "]"; } - *stream << "]"; - } - }; + }; // NOLINTEND(*-avoid-c-arrays) -DOCTEST_MSVC_SUPPRESS_WARNING_POP + DOCTEST_MSVC_SUPPRESS_WARNING_POP - // Specialized since we don't want the terminating null byte! + // Specialized since we don't want the terminating null byte! // NOLINTBEGIN(*-avoid-c-arrays) - template - struct filldata { - static void fill(std::ostream* stream, const char (&in)[N]) { - *stream << String(in, in[N - 1] ? N : N - 1); - } // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks) - }; + template + struct filldata { + static void fill(std::ostream *stream, const char (&in)[N]) { + *stream << String(in, in[N - 1] ? N : N - 1); + } // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks) + }; // NOLINTEND(*-avoid-c-arrays) - template <> - struct filldata { - static void fill(std::ostream* stream, const void* in); - }; + template<> + struct filldata { + static void fill(std::ostream *stream, const void *in); + }; - template - struct filldata { -DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4180) - static void fill(std::ostream* stream, const T* in) { -DOCTEST_MSVC_SUPPRESS_WARNING_POP -DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wmicrosoft-cast") - filldata::fill(stream, + template + struct filldata { + DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4180) + + static void fill(std::ostream *stream, const T *in) { + DOCTEST_MSVC_SUPPRESS_WARNING_POP + DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wmicrosoft-cast") + filldata::fill(stream, #if DOCTEST_GCC == 0 || DOCTEST_GCC >= DOCTEST_COMPILER(4, 9, 0) - reinterpret_cast(in) + reinterpret_cast(in) #else - *reinterpret_cast(&in) + *reinterpret_cast(&in) #endif - ); -DOCTEST_CLANG_SUPPRESS_WARNING_POP - } - }; -} + ); + DOCTEST_CLANG_SUPPRESS_WARNING_POP + } + }; + } -struct DOCTEST_INTERFACE Approx -{ - Approx(double value); + struct DOCTEST_INTERFACE Approx { + Approx(double value); - Approx operator()(double value) const; + Approx operator()(double value) const; #ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS - template - explicit Approx(const T& value, - typename detail::types::enable_if::value>::type* = - static_cast(nullptr)) { - *this = static_cast(value); - } + + template + explicit Approx(const T &value, + typename detail::types::enable_if::value>::type * = + static_cast(nullptr)) { + *this = static_cast(value); + } + #endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS - Approx& epsilon(double newEpsilon); + Approx &epsilon(double newEpsilon); #ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS - template - typename std::enable_if::value, Approx&>::type epsilon( - const T& newEpsilon) { - m_epsilon = static_cast(newEpsilon); - return *this; - } -#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS - Approx& scale(double newScale); + template + typename std::enable_if::value, Approx &>::type epsilon( + const T &newEpsilon) { + m_epsilon = static_cast(newEpsilon); + return *this; + } -#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS - template - typename std::enable_if::value, Approx&>::type scale( - const T& newScale) { - m_scale = static_cast(newScale); - return *this; - } -#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS +#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS - // clang-format off - DOCTEST_INTERFACE friend bool operator==(double lhs, const Approx & rhs); - DOCTEST_INTERFACE friend bool operator==(const Approx & lhs, double rhs); - DOCTEST_INTERFACE friend bool operator!=(double lhs, const Approx & rhs); - DOCTEST_INTERFACE friend bool operator!=(const Approx & lhs, double rhs); - DOCTEST_INTERFACE friend bool operator<=(double lhs, const Approx & rhs); - DOCTEST_INTERFACE friend bool operator<=(const Approx & lhs, double rhs); - DOCTEST_INTERFACE friend bool operator>=(double lhs, const Approx & rhs); - DOCTEST_INTERFACE friend bool operator>=(const Approx & lhs, double rhs); - DOCTEST_INTERFACE friend bool operator< (double lhs, const Approx & rhs); - DOCTEST_INTERFACE friend bool operator< (const Approx & lhs, double rhs); - DOCTEST_INTERFACE friend bool operator> (double lhs, const Approx & rhs); - DOCTEST_INTERFACE friend bool operator> (const Approx & lhs, double rhs); + Approx &scale(double newScale); #ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS -#define DOCTEST_APPROX_PREFIX \ - template friend typename std::enable_if::value, bool>::type - DOCTEST_APPROX_PREFIX operator==(const T& lhs, const Approx& rhs) { return operator==(static_cast(lhs), rhs); } - DOCTEST_APPROX_PREFIX operator==(const Approx& lhs, const T& rhs) { return operator==(rhs, lhs); } - DOCTEST_APPROX_PREFIX operator!=(const T& lhs, const Approx& rhs) { return !operator==(lhs, rhs); } - DOCTEST_APPROX_PREFIX operator!=(const Approx& lhs, const T& rhs) { return !operator==(rhs, lhs); } - DOCTEST_APPROX_PREFIX operator<=(const T& lhs, const Approx& rhs) { return static_cast(lhs) < rhs.m_value || lhs == rhs; } - DOCTEST_APPROX_PREFIX operator<=(const Approx& lhs, const T& rhs) { return lhs.m_value < static_cast(rhs) || lhs == rhs; } - DOCTEST_APPROX_PREFIX operator>=(const T& lhs, const Approx& rhs) { return static_cast(lhs) > rhs.m_value || lhs == rhs; } - DOCTEST_APPROX_PREFIX operator>=(const Approx& lhs, const T& rhs) { return lhs.m_value > static_cast(rhs) || lhs == rhs; } - DOCTEST_APPROX_PREFIX operator< (const T& lhs, const Approx& rhs) { return static_cast(lhs) < rhs.m_value && lhs != rhs; } - DOCTEST_APPROX_PREFIX operator< (const Approx& lhs, const T& rhs) { return lhs.m_value < static_cast(rhs) && lhs != rhs; } - DOCTEST_APPROX_PREFIX operator> (const T& lhs, const Approx& rhs) { return static_cast(lhs) > rhs.m_value && lhs != rhs; } - DOCTEST_APPROX_PREFIX operator> (const Approx& lhs, const T& rhs) { return lhs.m_value > static_cast(rhs) && lhs != rhs; } -#undef DOCTEST_APPROX_PREFIX + template + typename std::enable_if::value, Approx &>::type scale( + const T &newScale) { + m_scale = static_cast(newScale); + return *this; + } + #endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS - // clang-format on + // clang-format off + DOCTEST_INTERFACE friend bool operator==(double lhs, const Approx &rhs); - double m_epsilon; - double m_scale; - double m_value; -}; + DOCTEST_INTERFACE friend bool operator==(const Approx &lhs, double rhs); -DOCTEST_INTERFACE String toString(const Approx& in); + DOCTEST_INTERFACE friend bool operator!=(double lhs, const Approx &rhs); -DOCTEST_INTERFACE const ContextOptions* getContextOptions(); + DOCTEST_INTERFACE friend bool operator!=(const Approx &lhs, double rhs); -template -struct DOCTEST_INTERFACE_DECL IsNaN -{ - F value; bool flipped; - IsNaN(F f, bool flip = false) : value(f), flipped(flip) { } - IsNaN operator!() const { return { value, !flipped }; } - operator bool() const; -}; -#ifndef __MINGW32__ -extern template struct DOCTEST_INTERFACE_DECL IsNaN; -extern template struct DOCTEST_INTERFACE_DECL IsNaN; -extern template struct DOCTEST_INTERFACE_DECL IsNaN; -#endif -DOCTEST_INTERFACE String toString(IsNaN in); -DOCTEST_INTERFACE String toString(IsNaN in); -DOCTEST_INTERFACE String toString(IsNaN in); + DOCTEST_INTERFACE friend bool operator<=(double lhs, const Approx &rhs); -#ifndef DOCTEST_CONFIG_DISABLE + DOCTEST_INTERFACE friend bool operator<=(const Approx &lhs, double rhs); -namespace detail { - // clang-format off -#ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING - template struct decay_array { using type = T; }; - template struct decay_array { using type = T*; }; - template struct decay_array { using type = T*; }; + DOCTEST_INTERFACE friend bool operator>=(double lhs, const Approx &rhs); - template struct not_char_pointer { static DOCTEST_CONSTEXPR int value = 1; }; - template<> struct not_char_pointer { static DOCTEST_CONSTEXPR int value = 0; }; - template<> struct not_char_pointer { static DOCTEST_CONSTEXPR int value = 0; }; + DOCTEST_INTERFACE friend bool operator>=(const Approx &lhs, double rhs); - template struct can_use_op : public not_char_pointer::type> {}; -#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING - // clang-format on + DOCTEST_INTERFACE friend bool operator<(double lhs, const Approx &rhs); - struct DOCTEST_INTERFACE TestFailureException - { - }; + DOCTEST_INTERFACE friend bool operator<(const Approx &lhs, double rhs); - DOCTEST_INTERFACE bool checkIfShouldThrow(assertType::Enum at); + DOCTEST_INTERFACE friend bool operator>(double lhs, const Approx &rhs); -#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS - DOCTEST_NORETURN -#endif // DOCTEST_CONFIG_NO_EXCEPTIONS - DOCTEST_INTERFACE void throwException(); + DOCTEST_INTERFACE friend bool operator>(const Approx &lhs, double rhs); - struct DOCTEST_INTERFACE Subcase - { - SubcaseSignature m_signature; - bool m_entered = false; +#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS +#define DOCTEST_APPROX_PREFIX \ + template friend typename std::enable_if::value, bool>::type - Subcase(const String& name, const char* file, int line); - Subcase(const Subcase&) = delete; - Subcase(Subcase&&) = delete; - Subcase& operator=(const Subcase&) = delete; - Subcase& operator=(Subcase&&) = delete; - ~Subcase(); + DOCTEST_APPROX_PREFIX operator==(const T &lhs, const Approx &rhs) { + return operator==(static_cast(lhs), rhs); + } - operator bool() const; + DOCTEST_APPROX_PREFIX operator==(const Approx &lhs, const T &rhs) { return operator==(rhs, lhs); } - private: - bool checkFilters(); - }; + DOCTEST_APPROX_PREFIX operator!=(const T &lhs, const Approx &rhs) { return !operator==(lhs, rhs); } - template - String stringifyBinaryExpr(const DOCTEST_REF_WRAP(L) lhs, const char* op, - const DOCTEST_REF_WRAP(R) rhs) { - return (DOCTEST_STRINGIFY(lhs)) + op + (DOCTEST_STRINGIFY(rhs)); - } + DOCTEST_APPROX_PREFIX operator!=(const Approx &lhs, const T &rhs) { return !operator==(rhs, lhs); } -#if DOCTEST_CLANG && DOCTEST_CLANG < DOCTEST_COMPILER(3, 6, 0) -DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wunused-comparison") -#endif + DOCTEST_APPROX_PREFIX operator<=(const T &lhs, const Approx &rhs) { + return static_cast(lhs) < rhs.m_value || lhs == rhs; + } -// This will check if there is any way it could find a operator like member or friend and uses it. -// If not it doesn't find the operator or if the operator at global scope is defined after -// this template, the template won't be instantiated due to SFINAE. Once the template is not -// instantiated it can look for global operator using normal conversions. -#ifdef __NVCC__ -#define SFINAE_OP(ret,op) ret -#else -#define SFINAE_OP(ret,op) decltype((void)(doctest::detail::declval() op doctest::detail::declval()),ret{}) -#endif + DOCTEST_APPROX_PREFIX operator<=(const Approx &lhs, const T &rhs) { + return lhs.m_value < static_cast(rhs) || lhs == rhs; + } + + DOCTEST_APPROX_PREFIX operator>=(const T &lhs, const Approx &rhs) { + return static_cast(lhs) > rhs.m_value || lhs == rhs; + } + + DOCTEST_APPROX_PREFIX operator>=(const Approx &lhs, const T &rhs) { + return lhs.m_value > static_cast(rhs) || lhs == rhs; + } + + DOCTEST_APPROX_PREFIX operator<(const T &lhs, const Approx &rhs) { + return static_cast(lhs) < rhs.m_value && lhs != rhs; + } + + DOCTEST_APPROX_PREFIX operator<(const Approx &lhs, const T &rhs) { + return lhs.m_value < static_cast(rhs) && lhs != rhs; + } + + DOCTEST_APPROX_PREFIX operator>(const T &lhs, const Approx &rhs) { + return static_cast(lhs) > rhs.m_value && lhs != rhs; + } + + DOCTEST_APPROX_PREFIX operator>(const Approx &lhs, const T &rhs) { + return lhs.m_value > static_cast(rhs) && lhs != rhs; + } + +#undef DOCTEST_APPROX_PREFIX +#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS + + // clang-format on + + double m_epsilon; + double m_scale; + double m_value; + }; + + DOCTEST_INTERFACE String toString(const Approx &in); + + DOCTEST_INTERFACE const ContextOptions *getContextOptions(); + + template + struct DOCTEST_INTERFACE_DECL IsNaN { + F value; + bool flipped; + + IsNaN(F f, bool flip = false) : value(f), flipped(flip) {} + + IsNaN operator!() const { return {value, !flipped}; } + + operator bool() const; + }; + +#ifndef __MINGW32__ + extern template + struct DOCTEST_INTERFACE_DECL IsNaN; + extern template + struct DOCTEST_INTERFACE_DECL IsNaN; + extern template + struct DOCTEST_INTERFACE_DECL IsNaN; +#endif + DOCTEST_INTERFACE String toString(IsNaN in); + + DOCTEST_INTERFACE String toString(IsNaN in); + + DOCTEST_INTERFACE String toString(IsNaN in); + +#ifndef DOCTEST_CONFIG_DISABLE + + namespace detail { + // clang-format off +#ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING + template struct decay_array { using type = T; }; + template struct decay_array { using type = T*; }; + template struct decay_array { using type = T*; }; + + template struct not_char_pointer { static DOCTEST_CONSTEXPR int value = 1; }; + template<> struct not_char_pointer { static DOCTEST_CONSTEXPR int value = 0; }; + template<> struct not_char_pointer { static DOCTEST_CONSTEXPR int value = 0; }; + + template struct can_use_op : public not_char_pointer::type> {}; +#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING + // clang-format on + + struct DOCTEST_INTERFACE TestFailureException { + }; + + DOCTEST_INTERFACE bool checkIfShouldThrow(assertType::Enum at); + +#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS + + DOCTEST_NORETURN +#endif // DOCTEST_CONFIG_NO_EXCEPTIONS + DOCTEST_INTERFACE void throwException(); + + struct DOCTEST_INTERFACE Subcase { + SubcaseSignature m_signature; + bool m_entered = false; + + Subcase(const String &name, const char *file, int line); + + Subcase(const Subcase &) = delete; + + Subcase(Subcase &&) = delete; + + Subcase &operator=(const Subcase &) = delete; + + Subcase &operator=(Subcase &&) = delete; + + ~Subcase(); + + operator bool() const; + + private: + bool checkFilters(); + }; + + template + String stringifyBinaryExpr(const DOCTEST_REF_WRAP(L)lhs, const char *op, + const DOCTEST_REF_WRAP(R)rhs) { + return (DOCTEST_STRINGIFY(lhs)) + op + (DOCTEST_STRINGIFY(rhs)); + } + +#if DOCTEST_CLANG && DOCTEST_CLANG < DOCTEST_COMPILER(3, 6, 0) + DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wunused-comparison") +#endif + +// This will check if there is any way it could find a operator like member or friend and uses it. +// If not it doesn't find the operator or if the operator at global scope is defined after +// this template, the template won't be instantiated due to SFINAE. Once the template is not +// instantiated it can look for global operator using normal conversions. +#ifdef __NVCC__ +#define SFINAE_OP(ret,op) ret +#else +#define SFINAE_OP(ret, op) decltype((void)(doctest::detail::declval() op doctest::detail::declval()),ret{}) +#endif #define DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(op, op_str, op_macro) \ template \ @@ -1381,9 +1483,9 @@ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wunused-comparison") return Result(res); \ } - // more checks could be added - like in Catch: - // https://github.com/catchorg/Catch2/pull/1480/files - // https://github.com/catchorg/Catch2/pull/1481/files + // more checks could be added - like in Catch: + // https://github.com/catchorg/Catch2/pull/1480/files + // https://github.com/catchorg/Catch2/pull/1481/files #define DOCTEST_FORBIT_EXPRESSION(rt, op) \ template \ rt& operator op(const R&) { \ @@ -1392,77 +1494,98 @@ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wunused-comparison") return *this; \ } - struct DOCTEST_INTERFACE Result // NOLINT(*-member-init) - { - bool m_passed; - String m_decomp; + struct DOCTEST_INTERFACE Result // NOLINT(*-member-init) + { + bool m_passed; + String m_decomp; - Result() = default; // TODO: Why do we need this? (To remove NOLINT) - Result(bool passed, const String& decomposition = String()); - - // forbidding some expressions based on this table: https://en.cppreference.com/w/cpp/language/operator_precedence - DOCTEST_FORBIT_EXPRESSION(Result, &) - DOCTEST_FORBIT_EXPRESSION(Result, ^) - DOCTEST_FORBIT_EXPRESSION(Result, |) - DOCTEST_FORBIT_EXPRESSION(Result, &&) - DOCTEST_FORBIT_EXPRESSION(Result, ||) - DOCTEST_FORBIT_EXPRESSION(Result, ==) - DOCTEST_FORBIT_EXPRESSION(Result, !=) - DOCTEST_FORBIT_EXPRESSION(Result, <) - DOCTEST_FORBIT_EXPRESSION(Result, >) - DOCTEST_FORBIT_EXPRESSION(Result, <=) - DOCTEST_FORBIT_EXPRESSION(Result, >=) - DOCTEST_FORBIT_EXPRESSION(Result, =) - DOCTEST_FORBIT_EXPRESSION(Result, +=) - DOCTEST_FORBIT_EXPRESSION(Result, -=) - DOCTEST_FORBIT_EXPRESSION(Result, *=) - DOCTEST_FORBIT_EXPRESSION(Result, /=) - DOCTEST_FORBIT_EXPRESSION(Result, %=) - DOCTEST_FORBIT_EXPRESSION(Result, <<=) - DOCTEST_FORBIT_EXPRESSION(Result, >>=) - DOCTEST_FORBIT_EXPRESSION(Result, &=) - DOCTEST_FORBIT_EXPRESSION(Result, ^=) - DOCTEST_FORBIT_EXPRESSION(Result, |=) - }; + Result() = default; // TODO: Why do we need this? (To remove NOLINT) + Result(bool passed, const String &decomposition = String()); + + // forbidding some expressions based on this table: https://en.cppreference.com/w/cpp/language/operator_precedence + DOCTEST_FORBIT_EXPRESSION(Result, &) + + DOCTEST_FORBIT_EXPRESSION(Result, ^) + + DOCTEST_FORBIT_EXPRESSION(Result, |) + + DOCTEST_FORBIT_EXPRESSION(Result, &&) + + DOCTEST_FORBIT_EXPRESSION(Result, ||) + + DOCTEST_FORBIT_EXPRESSION(Result, ==) + + DOCTEST_FORBIT_EXPRESSION(Result, !=) + + DOCTEST_FORBIT_EXPRESSION(Result, <) + + DOCTEST_FORBIT_EXPRESSION(Result, >) + + DOCTEST_FORBIT_EXPRESSION(Result, <=) + + DOCTEST_FORBIT_EXPRESSION(Result, >=) + + DOCTEST_FORBIT_EXPRESSION(Result, =) + + DOCTEST_FORBIT_EXPRESSION(Result, +=) + + DOCTEST_FORBIT_EXPRESSION(Result, -=) + + DOCTEST_FORBIT_EXPRESSION(Result, *=) + + DOCTEST_FORBIT_EXPRESSION(Result, /=) + + DOCTEST_FORBIT_EXPRESSION(Result, %=) + + DOCTEST_FORBIT_EXPRESSION(Result, <<=) + + DOCTEST_FORBIT_EXPRESSION(Result, >>=) + + DOCTEST_FORBIT_EXPRESSION(Result, &=) + + DOCTEST_FORBIT_EXPRESSION(Result, ^=) + + DOCTEST_FORBIT_EXPRESSION(Result, |=) + }; #ifndef DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION - DOCTEST_CLANG_SUPPRESS_WARNING_PUSH - DOCTEST_CLANG_SUPPRESS_WARNING("-Wsign-conversion") - DOCTEST_CLANG_SUPPRESS_WARNING("-Wsign-compare") - //DOCTEST_CLANG_SUPPRESS_WARNING("-Wdouble-promotion") - //DOCTEST_CLANG_SUPPRESS_WARNING("-Wconversion") - //DOCTEST_CLANG_SUPPRESS_WARNING("-Wfloat-equal") - - DOCTEST_GCC_SUPPRESS_WARNING_PUSH - DOCTEST_GCC_SUPPRESS_WARNING("-Wsign-conversion") - DOCTEST_GCC_SUPPRESS_WARNING("-Wsign-compare") - //DOCTEST_GCC_SUPPRESS_WARNING("-Wdouble-promotion") - //DOCTEST_GCC_SUPPRESS_WARNING("-Wconversion") - //DOCTEST_GCC_SUPPRESS_WARNING("-Wfloat-equal") - - DOCTEST_MSVC_SUPPRESS_WARNING_PUSH - // https://stackoverflow.com/questions/39479163 what's the difference between 4018 and 4389 - DOCTEST_MSVC_SUPPRESS_WARNING(4388) // signed/unsigned mismatch - DOCTEST_MSVC_SUPPRESS_WARNING(4389) // 'operator' : signed/unsigned mismatch - DOCTEST_MSVC_SUPPRESS_WARNING(4018) // 'expression' : signed/unsigned mismatch - //DOCTEST_MSVC_SUPPRESS_WARNING(4805) // 'operation' : unsafe mix of type 'type' and type 'type' in operation + DOCTEST_CLANG_SUPPRESS_WARNING_PUSH + DOCTEST_CLANG_SUPPRESS_WARNING("-Wsign-conversion") + DOCTEST_CLANG_SUPPRESS_WARNING("-Wsign-compare") + //DOCTEST_CLANG_SUPPRESS_WARNING("-Wdouble-promotion") + //DOCTEST_CLANG_SUPPRESS_WARNING("-Wconversion") + //DOCTEST_CLANG_SUPPRESS_WARNING("-Wfloat-equal") + + DOCTEST_GCC_SUPPRESS_WARNING_PUSH + DOCTEST_GCC_SUPPRESS_WARNING("-Wsign-conversion") + DOCTEST_GCC_SUPPRESS_WARNING("-Wsign-compare") + //DOCTEST_GCC_SUPPRESS_WARNING("-Wdouble-promotion") + //DOCTEST_GCC_SUPPRESS_WARNING("-Wconversion") + //DOCTEST_GCC_SUPPRESS_WARNING("-Wfloat-equal") + + DOCTEST_MSVC_SUPPRESS_WARNING_PUSH + // https://stackoverflow.com/questions/39479163 what's the difference between 4018 and 4389 + DOCTEST_MSVC_SUPPRESS_WARNING(4388) // signed/unsigned mismatch + DOCTEST_MSVC_SUPPRESS_WARNING(4389) // 'operator' : signed/unsigned mismatch + DOCTEST_MSVC_SUPPRESS_WARNING(4018) // 'expression' : signed/unsigned mismatch + //DOCTEST_MSVC_SUPPRESS_WARNING(4805) // 'operation' : unsafe mix of type 'type' and type 'type' in operation #endif // DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION - // clang-format off + // clang-format off #ifndef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING #define DOCTEST_COMPARISON_RETURN_TYPE bool #else // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING #define DOCTEST_COMPARISON_RETURN_TYPE typename types::enable_if::value || can_use_op::value, bool>::type - inline bool eq(const char* lhs, const char* rhs) { return String(lhs) == String(rhs); } - inline bool ne(const char* lhs, const char* rhs) { return String(lhs) != String(rhs); } - inline bool lt(const char* lhs, const char* rhs) { return String(lhs) < String(rhs); } - inline bool gt(const char* lhs, const char* rhs) { return String(lhs) > String(rhs); } - inline bool le(const char* lhs, const char* rhs) { return String(lhs) <= String(rhs); } - inline bool ge(const char* lhs, const char* rhs) { return String(lhs) >= String(rhs); } + inline bool eq(const char* lhs, const char* rhs) { return String(lhs) == String(rhs); } + inline bool ne(const char* lhs, const char* rhs) { return String(lhs) != String(rhs); } + inline bool lt(const char* lhs, const char* rhs) { return String(lhs) < String(rhs); } + inline bool gt(const char* lhs, const char* rhs) { return String(lhs) > String(rhs); } + inline bool le(const char* lhs, const char* rhs) { return String(lhs) <= String(rhs); } + inline bool ge(const char* lhs, const char* rhs) { return String(lhs) >= String(rhs); } #endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING - // clang-format on + // clang-format on #define DOCTEST_RELATIONAL_OP(name, op) \ template \ @@ -1471,12 +1594,17 @@ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wunused-comparison") return lhs op rhs; \ } - DOCTEST_RELATIONAL_OP(eq, ==) - DOCTEST_RELATIONAL_OP(ne, !=) - DOCTEST_RELATIONAL_OP(lt, <) - DOCTEST_RELATIONAL_OP(gt, >) - DOCTEST_RELATIONAL_OP(le, <=) - DOCTEST_RELATIONAL_OP(ge, >=) + DOCTEST_RELATIONAL_OP(eq, ==) + + DOCTEST_RELATIONAL_OP(ne, !=) + + DOCTEST_RELATIONAL_OP(lt, <) + + DOCTEST_RELATIONAL_OP(gt, >) + + DOCTEST_RELATIONAL_OP(le, <=) + + DOCTEST_RELATIONAL_OP(ge, >=) #ifndef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING #define DOCTEST_CMP_EQ(l, r) l == r @@ -1494,244 +1622,269 @@ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wunused-comparison") #define DOCTEST_CMP_LE(l, r) le(l, r) #endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING - template - // cppcheck-suppress copyCtorAndEqOperator - struct Expression_lhs - { - L lhs; - assertType::Enum m_at; + template + // cppcheck-suppress copyCtorAndEqOperator + struct Expression_lhs { + L lhs; + assertType::Enum m_at; - explicit Expression_lhs(L&& in, assertType::Enum at) - : lhs(static_cast(in)) - , m_at(at) {} + explicit Expression_lhs(L &&in, assertType::Enum at) + : lhs(static_cast(in)), m_at(at) {} - DOCTEST_NOINLINE operator Result() { + DOCTEST_NOINLINE operator Result() { // this is needed only for MSVC 2015 -DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4800) // 'int': forcing value to bool - bool res = static_cast(lhs); -DOCTEST_MSVC_SUPPRESS_WARNING_POP - if(m_at & assertType::is_false) { //!OCLINT bitwise operator in conditional - res = !res; - } + DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4800) // 'int': forcing value to bool + bool res = static_cast(lhs); + DOCTEST_MSVC_SUPPRESS_WARNING_POP + if (m_at & assertType::is_false) { //!OCLINT bitwise operator in conditional + res = !res; + } - if(!res || getContextOptions()->success) { - return { res, (DOCTEST_STRINGIFY(lhs)) }; + if (!res || getContextOptions()->success) { + return {res, (DOCTEST_STRINGIFY(lhs))}; + } + return {res}; } - return { res }; - } - /* This is required for user-defined conversions from Expression_lhs to L */ - operator L() const { return lhs; } + /* This is required for user-defined conversions from Expression_lhs to L */ + operator L() const { return lhs; } - // clang-format off - DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(==, " == ", DOCTEST_CMP_EQ) //!OCLINT bitwise operator in conditional - DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(!=, " != ", DOCTEST_CMP_NE) //!OCLINT bitwise operator in conditional - DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>, " > ", DOCTEST_CMP_GT) //!OCLINT bitwise operator in conditional - DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<, " < ", DOCTEST_CMP_LT) //!OCLINT bitwise operator in conditional - DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>=, " >= ", DOCTEST_CMP_GE) //!OCLINT bitwise operator in conditional - DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<=, " <= ", DOCTEST_CMP_LE) //!OCLINT bitwise operator in conditional - // clang-format on + // clang-format off + DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(==, " == ", + DOCTEST_CMP_EQ) //!OCLINT bitwise operator in conditional + DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(!=, " != ", + DOCTEST_CMP_NE) //!OCLINT bitwise operator in conditional + DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>, " > ", DOCTEST_CMP_GT) //!OCLINT bitwise operator in conditional + DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<, " < ", DOCTEST_CMP_LT) //!OCLINT bitwise operator in conditional + DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>=, " >= ", + DOCTEST_CMP_GE) //!OCLINT bitwise operator in conditional + DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<=, " <= ", + DOCTEST_CMP_LE) //!OCLINT bitwise operator in conditional + // clang-format on - // forbidding some expressions based on this table: https://en.cppreference.com/w/cpp/language/operator_precedence - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, &) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, ^) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, |) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, &&) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, ||) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, =) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, +=) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, -=) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, *=) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, /=) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, %=) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, <<=) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, >>=) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, &=) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, ^=) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, |=) - // these 2 are unfortunate because they should be allowed - they have higher precedence over the comparisons, but the - // ExpressionDecomposer class uses the left shift operator to capture the left operand of the binary expression... - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, <<) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, >>) - }; + // forbidding some expressions based on this table: https://en.cppreference.com/w/cpp/language/operator_precedence + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, &) + + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, ^) + + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, |) + + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, &&) + + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, ||) + + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, =) + + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, +=) + + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, -=) + + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, *=) + + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, /=) + + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, %=) + + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, <<=) + + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, >>=) + + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, &=) + + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, ^=) + + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, |=) + // these 2 are unfortunate because they should be allowed - they have higher precedence over the comparisons, but the + // ExpressionDecomposer class uses the left shift operator to capture the left operand of the binary expression... + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, <<) + + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, >>) + }; #ifndef DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION - DOCTEST_CLANG_SUPPRESS_WARNING_POP - DOCTEST_MSVC_SUPPRESS_WARNING_POP - DOCTEST_GCC_SUPPRESS_WARNING_POP + DOCTEST_CLANG_SUPPRESS_WARNING_POP + DOCTEST_MSVC_SUPPRESS_WARNING_POP + DOCTEST_GCC_SUPPRESS_WARNING_POP #endif // DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION #if DOCTEST_CLANG && DOCTEST_CLANG < DOCTEST_COMPILER(3, 6, 0) -DOCTEST_CLANG_SUPPRESS_WARNING_POP + DOCTEST_CLANG_SUPPRESS_WARNING_POP #endif - struct DOCTEST_INTERFACE ExpressionDecomposer - { - assertType::Enum m_at; + struct DOCTEST_INTERFACE ExpressionDecomposer { + assertType::Enum m_at; - ExpressionDecomposer(assertType::Enum at); + ExpressionDecomposer(assertType::Enum at); - // The right operator for capturing expressions is "<=" instead of "<<" (based on the operator precedence table) - // but then there will be warnings from GCC about "-Wparentheses" and since "_Pragma()" is problematic this will stay for now... - // https://github.com/catchorg/Catch2/issues/870 - // https://github.com/catchorg/Catch2/issues/565 - template - Expression_lhs operator<<(L&& operand) { - return Expression_lhs(static_cast(operand), m_at); - } + // The right operator for capturing expressions is "<=" instead of "<<" (based on the operator precedence table) + // but then there will be warnings from GCC about "-Wparentheses" and since "_Pragma()" is problematic this will stay for now... + // https://github.com/catchorg/Catch2/issues/870 + // https://github.com/catchorg/Catch2/issues/565 + template + Expression_lhs operator<<(L &&operand) { + return Expression_lhs(static_cast(operand), m_at); + } - template ::value,void >::type* = nullptr> - Expression_lhs operator<<(const L &operand) { - return Expression_lhs(operand, m_at); - } - }; + template::value, void>::type * = nullptr> + Expression_lhs operator<<(const L &operand) { + return Expression_lhs(operand, m_at); + } + }; - struct DOCTEST_INTERFACE TestSuite - { - const char* m_test_suite = nullptr; - const char* m_description = nullptr; - bool m_skip = false; - bool m_no_breaks = false; - bool m_no_output = false; - bool m_may_fail = false; - bool m_should_fail = false; - int m_expected_failures = 0; - double m_timeout = 0; - - TestSuite& operator*(const char* in); + struct DOCTEST_INTERFACE TestSuite { + const char *m_test_suite = nullptr; + const char *m_description = nullptr; + bool m_skip = false; + bool m_no_breaks = false; + bool m_no_output = false; + bool m_may_fail = false; + bool m_should_fail = false; + int m_expected_failures = 0; + double m_timeout = 0; - template - TestSuite& operator*(const T& in) { - in.fill(*this); - return *this; - } - }; + TestSuite &operator*(const char *in); - using funcType = void (*)(); + template + TestSuite &operator*(const T &in) { + in.fill(*this); + return *this; + } + }; - struct DOCTEST_INTERFACE TestCase : public TestCaseData - { - funcType m_test; // a function pointer to the test case + using funcType = void (*)(); - String m_type; // for templated test cases - gets appended to the real name - int m_template_id; // an ID used to distinguish between the different versions of a templated test case - String m_full_name; // contains the name (only for templated test cases!) + the template type + struct DOCTEST_INTERFACE TestCase : public TestCaseData { + funcType m_test; // a function pointer to the test case - TestCase(funcType test, const char* file, unsigned line, const TestSuite& test_suite, - const String& type = String(), int template_id = -1); + String m_type; // for templated test cases - gets appended to the real name + int m_template_id; // an ID used to distinguish between the different versions of a templated test case + String m_full_name; // contains the name (only for templated test cases!) + the template type - TestCase(const TestCase& other); - TestCase(TestCase&&) = delete; + TestCase(funcType test, const char *file, unsigned line, const TestSuite &test_suite, + const String &type = String(), int template_id = -1); - DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(26434) // hides a non-virtual function - TestCase& operator=(const TestCase& other); - DOCTEST_MSVC_SUPPRESS_WARNING_POP + TestCase(const TestCase &other); - TestCase& operator=(TestCase&&) = delete; + TestCase(TestCase &&) = delete; - TestCase& operator*(const char* in); + DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(26434) // hides a non-virtual function + TestCase &operator=(const TestCase &other); - template - TestCase& operator*(const T& in) { - in.fill(*this); - return *this; - } + DOCTEST_MSVC_SUPPRESS_WARNING_POP - bool operator<(const TestCase& other) const; + TestCase &operator=(TestCase &&) = delete; - ~TestCase() = default; - }; + TestCase &operator*(const char *in); - // forward declarations of functions used by the macros - DOCTEST_INTERFACE int regTest(const TestCase& tc); - DOCTEST_INTERFACE int setTestSuite(const TestSuite& ts); - DOCTEST_INTERFACE bool isDebuggerActive(); + template + TestCase &operator*(const T &in) { + in.fill(*this); + return *this; + } - template - int instantiationHelper(const T&) { return 0; } + bool operator<(const TestCase &other) const; - namespace binaryAssertComparison { - enum Enum - { - eq = 0, - ne, - gt, - lt, - ge, - le + ~TestCase() = default; }; - } // namespace binaryAssertComparison - // clang-format off - template struct RelationalComparator { bool operator()(const DOCTEST_REF_WRAP(L), const DOCTEST_REF_WRAP(R) ) const { return false; } }; + // forward declarations of functions used by the macros + DOCTEST_INTERFACE int regTest(const TestCase &tc); + + DOCTEST_INTERFACE int setTestSuite(const TestSuite &ts); + + DOCTEST_INTERFACE bool isDebuggerActive(); + + template + int instantiationHelper(const T &) { return 0; } + + namespace binaryAssertComparison { + enum Enum { + eq = 0, + ne, + gt, + lt, + ge, + le + }; + } // namespace binaryAssertComparison + + // clang-format off + template + struct RelationalComparator { + bool operator()(const DOCTEST_REF_WRAP(L), const DOCTEST_REF_WRAP(R)) const { return false; } + }; #define DOCTEST_BINARY_RELATIONAL_OP(n, op) \ template struct RelationalComparator { bool operator()(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) const { return op(lhs, rhs); } }; - // clang-format on + // clang-format on - DOCTEST_BINARY_RELATIONAL_OP(0, doctest::detail::eq) - DOCTEST_BINARY_RELATIONAL_OP(1, doctest::detail::ne) - DOCTEST_BINARY_RELATIONAL_OP(2, doctest::detail::gt) - DOCTEST_BINARY_RELATIONAL_OP(3, doctest::detail::lt) - DOCTEST_BINARY_RELATIONAL_OP(4, doctest::detail::ge) - DOCTEST_BINARY_RELATIONAL_OP(5, doctest::detail::le) + DOCTEST_BINARY_RELATIONAL_OP(0, doctest::detail::eq) - struct DOCTEST_INTERFACE ResultBuilder : public AssertData - { - ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr, - const char* exception_type = "", const String& exception_string = ""); + DOCTEST_BINARY_RELATIONAL_OP(1, doctest::detail::ne) - ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr, - const char* exception_type, const Contains& exception_string); + DOCTEST_BINARY_RELATIONAL_OP(2, doctest::detail::gt) - void setResult(const Result& res); + DOCTEST_BINARY_RELATIONAL_OP(3, doctest::detail::lt) - template - DOCTEST_NOINLINE bool binary_assert(const DOCTEST_REF_WRAP(L) lhs, - const DOCTEST_REF_WRAP(R) rhs) { - m_failed = !RelationalComparator()(lhs, rhs); - if (m_failed || getContextOptions()->success) { - m_decomp = stringifyBinaryExpr(lhs, ", ", rhs); - } - return !m_failed; - } + DOCTEST_BINARY_RELATIONAL_OP(4, doctest::detail::ge) - template - DOCTEST_NOINLINE bool unary_assert(const DOCTEST_REF_WRAP(L) val) { - m_failed = !val; + DOCTEST_BINARY_RELATIONAL_OP(5, doctest::detail::le) - if (m_at & assertType::is_false) { //!OCLINT bitwise operator in conditional - m_failed = !m_failed; - } + struct DOCTEST_INTERFACE ResultBuilder : public AssertData { + ResultBuilder(assertType::Enum at, const char *file, int line, const char *expr, + const char *exception_type = "", const String &exception_string = ""); + + ResultBuilder(assertType::Enum at, const char *file, int line, const char *expr, + const char *exception_type, const Contains &exception_string); - if (m_failed || getContextOptions()->success) { - m_decomp = (DOCTEST_STRINGIFY(val)); + void setResult(const Result &res); + + template + DOCTEST_NOINLINE bool binary_assert(const DOCTEST_REF_WRAP(L)lhs, + const DOCTEST_REF_WRAP(R)rhs) { + m_failed = !RelationalComparator()(lhs, rhs); + if (m_failed || getContextOptions()->success) { + m_decomp = stringifyBinaryExpr(lhs, ", ", rhs); + } + return !m_failed; } - return !m_failed; - } + template + DOCTEST_NOINLINE bool unary_assert(const DOCTEST_REF_WRAP(L)val) { + m_failed = !val; - void translateException(); + if (m_at & assertType::is_false) { //!OCLINT bitwise operator in conditional + m_failed = !m_failed; + } - bool log(); - void react() const; - }; + if (m_failed || getContextOptions()->success) { + m_decomp = (DOCTEST_STRINGIFY(val)); + } - namespace assertAction { - enum Enum - { - nothing = 0, - dbgbreak = 1, - shouldthrow = 2 + return !m_failed; + } + + void translateException(); + + bool log(); + + void react() const; }; - } // namespace assertAction - DOCTEST_INTERFACE void failed_out_of_a_testing_context(const AssertData& ad); + namespace assertAction { + enum Enum { + nothing = 0, + dbgbreak = 1, + shouldthrow = 2 + }; + } // namespace assertAction + + DOCTEST_INTERFACE void failed_out_of_a_testing_context(const AssertData &ad); - DOCTEST_INTERFACE bool decomp_assert(assertType::Enum at, const char* file, int line, - const char* expr, const Result& result); + DOCTEST_INTERFACE bool decomp_assert(assertType::Enum at, const char *file, int line, + const char *expr, const Result &result); #define DOCTEST_ASSERT_OUT_OF_TESTS(decomp) \ do { \ @@ -1760,156 +1913,166 @@ DOCTEST_CLANG_SUPPRESS_WARNING_POP if(rb.m_failed && checkIfShouldThrow(at)) \ throwException() - template - DOCTEST_NOINLINE bool binary_assert(assertType::Enum at, const char* file, int line, - const char* expr, const DOCTEST_REF_WRAP(L) lhs, - const DOCTEST_REF_WRAP(R) rhs) { - bool failed = !RelationalComparator()(lhs, rhs); + template + DOCTEST_NOINLINE bool binary_assert(assertType::Enum at, const char *file, int line, + const char *expr, const DOCTEST_REF_WRAP(L)lhs, + const DOCTEST_REF_WRAP(R)rhs) { + bool failed = !RelationalComparator()(lhs, rhs); - // ################################################################################### - // IF THE DEBUGGER BREAKS HERE - GO 1 LEVEL UP IN THE CALLSTACK FOR THE FAILING ASSERT - // THIS IS THE EFFECT OF HAVING 'DOCTEST_CONFIG_SUPER_FAST_ASSERTS' DEFINED - // ################################################################################### - DOCTEST_ASSERT_OUT_OF_TESTS(stringifyBinaryExpr(lhs, ", ", rhs)); - DOCTEST_ASSERT_IN_TESTS(stringifyBinaryExpr(lhs, ", ", rhs)); - return !failed; - } + // ################################################################################### + // IF THE DEBUGGER BREAKS HERE - GO 1 LEVEL UP IN THE CALLSTACK FOR THE FAILING ASSERT + // THIS IS THE EFFECT OF HAVING 'DOCTEST_CONFIG_SUPER_FAST_ASSERTS' DEFINED + // ################################################################################### + DOCTEST_ASSERT_OUT_OF_TESTS(stringifyBinaryExpr(lhs, ", ", rhs)); + DOCTEST_ASSERT_IN_TESTS(stringifyBinaryExpr(lhs, ", ", rhs)); + return !failed; + } - template - DOCTEST_NOINLINE bool unary_assert(assertType::Enum at, const char* file, int line, - const char* expr, const DOCTEST_REF_WRAP(L) val) { - bool failed = !val; + template + DOCTEST_NOINLINE bool unary_assert(assertType::Enum at, const char *file, int line, + const char *expr, const DOCTEST_REF_WRAP(L)val) { + bool failed = !val; - if(at & assertType::is_false) //!OCLINT bitwise operator in conditional - failed = !failed; + if (at & assertType::is_false) //!OCLINT bitwise operator in conditional + failed = !failed; - // ################################################################################### - // IF THE DEBUGGER BREAKS HERE - GO 1 LEVEL UP IN THE CALLSTACK FOR THE FAILING ASSERT - // THIS IS THE EFFECT OF HAVING 'DOCTEST_CONFIG_SUPER_FAST_ASSERTS' DEFINED - // ################################################################################### - DOCTEST_ASSERT_OUT_OF_TESTS((DOCTEST_STRINGIFY(val))); - DOCTEST_ASSERT_IN_TESTS((DOCTEST_STRINGIFY(val))); - return !failed; - } + // ################################################################################### + // IF THE DEBUGGER BREAKS HERE - GO 1 LEVEL UP IN THE CALLSTACK FOR THE FAILING ASSERT + // THIS IS THE EFFECT OF HAVING 'DOCTEST_CONFIG_SUPER_FAST_ASSERTS' DEFINED + // ################################################################################### + DOCTEST_ASSERT_OUT_OF_TESTS((DOCTEST_STRINGIFY(val))); + DOCTEST_ASSERT_IN_TESTS((DOCTEST_STRINGIFY(val))); + return !failed; + } - struct DOCTEST_INTERFACE IExceptionTranslator - { - DOCTEST_DECLARE_INTERFACE(IExceptionTranslator) - virtual bool translate(String&) const = 0; - }; + struct DOCTEST_INTERFACE IExceptionTranslator { + DOCTEST_DECLARE_INTERFACE(IExceptionTranslator) - template - class ExceptionTranslator : public IExceptionTranslator //!OCLINT destructor of virtual class - { - public: - explicit ExceptionTranslator(String (*translateFunction)(T)) - : m_translateFunction(translateFunction) {} + virtual bool translate(String &) const = 0; + }; + + template + class ExceptionTranslator : public IExceptionTranslator //!OCLINT destructor of virtual class + { + public: + explicit ExceptionTranslator(String (*translateFunction)(T)) + : m_translateFunction(translateFunction) {} - bool translate(String& res) const override { + bool translate(String &res) const override { #ifndef DOCTEST_CONFIG_NO_EXCEPTIONS - try { - throw; // lgtm [cpp/rethrow-no-exception] - // cppcheck-suppress catchExceptionByValue - } catch(const T& ex) { - res = m_translateFunction(ex); //!OCLINT parameter reassignment - return true; - } catch(...) {} //!OCLINT - empty catch statement + try { + throw; // lgtm [cpp/rethrow-no-exception] + // cppcheck-suppress catchExceptionByValue + } catch (const T &ex) { + res = m_translateFunction(ex); //!OCLINT parameter reassignment + return true; + } catch (...) {} //!OCLINT - empty catch statement #endif // DOCTEST_CONFIG_NO_EXCEPTIONS - static_cast(res); // to silence -Wunused-parameter - return false; - } + static_cast(res); // to silence -Wunused-parameter + return false; + } - private: - String (*m_translateFunction)(T); - }; + private: + String (*m_translateFunction)(T); + }; - DOCTEST_INTERFACE void registerExceptionTranslatorImpl(const IExceptionTranslator* et); + DOCTEST_INTERFACE void registerExceptionTranslatorImpl(const IExceptionTranslator *et); - // ContextScope base class used to allow implementing methods of ContextScope - // that don't depend on the template parameter in doctest.cpp. - struct DOCTEST_INTERFACE ContextScopeBase : public IContextScope { - ContextScopeBase(const ContextScopeBase&) = delete; + // ContextScope base class used to allow implementing methods of ContextScope + // that don't depend on the template parameter in doctest.cpp. + struct DOCTEST_INTERFACE ContextScopeBase : public IContextScope { + ContextScopeBase(const ContextScopeBase &) = delete; - ContextScopeBase& operator=(const ContextScopeBase&) = delete; - ContextScopeBase& operator=(ContextScopeBase&&) = delete; + ContextScopeBase &operator=(const ContextScopeBase &) = delete; - ~ContextScopeBase() override = default; + ContextScopeBase &operator=(ContextScopeBase &&) = delete; - protected: - ContextScopeBase(); - ContextScopeBase(ContextScopeBase&& other) noexcept; + ~ContextScopeBase() override = default; - void destroy(); - bool need_to_destroy{true}; - }; + protected: + ContextScopeBase(); - template class ContextScope : public ContextScopeBase - { - L lambda_; + ContextScopeBase(ContextScopeBase &&other) noexcept; - public: - explicit ContextScope(const L &lambda) : lambda_(lambda) {} - explicit ContextScope(L&& lambda) : lambda_(static_cast(lambda)) { } + void destroy(); + + bool need_to_destroy{true}; + }; + + template + class ContextScope : public ContextScopeBase { + L lambda_; + + public: + explicit ContextScope(const L &lambda) : lambda_(lambda) {} + + explicit ContextScope(L &&lambda) : lambda_(static_cast(lambda)) {} - ContextScope(const ContextScope&) = delete; - ContextScope(ContextScope&&) noexcept = default; + ContextScope(const ContextScope &) = delete; - ContextScope& operator=(const ContextScope&) = delete; - ContextScope& operator=(ContextScope&&) = delete; + ContextScope(ContextScope &&) noexcept = default; - void stringify(std::ostream* s) const override { lambda_(s); } + ContextScope &operator=(const ContextScope &) = delete; - ~ContextScope() override { - if (need_to_destroy) { - destroy(); + ContextScope &operator=(ContextScope &&) = delete; + + void stringify(std::ostream *s) const override { lambda_(s); } + + ~ContextScope() override { + if (need_to_destroy) { + destroy(); + } } - } - }; + }; - struct DOCTEST_INTERFACE MessageBuilder : public MessageData - { - std::ostream* m_stream; - bool logged = false; + struct DOCTEST_INTERFACE MessageBuilder : public MessageData { + std::ostream *m_stream; + bool logged = false; - MessageBuilder(const char* file, int line, assertType::Enum severity); + MessageBuilder(const char *file, int line, assertType::Enum severity); - MessageBuilder(const MessageBuilder&) = delete; - MessageBuilder(MessageBuilder&&) = delete; + MessageBuilder(const MessageBuilder &) = delete; - MessageBuilder& operator=(const MessageBuilder&) = delete; - MessageBuilder& operator=(MessageBuilder&&) = delete; + MessageBuilder(MessageBuilder &&) = delete; - ~MessageBuilder(); + MessageBuilder &operator=(const MessageBuilder &) = delete; - // the preferred way of chaining parameters for stringification -DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4866) - template - MessageBuilder& operator,(const T& in) { - *m_stream << (DOCTEST_STRINGIFY(in)); - return *this; - } -DOCTEST_MSVC_SUPPRESS_WARNING_POP + MessageBuilder &operator=(MessageBuilder &&) = delete; - // kept here just for backwards-compatibility - the comma operator should be preferred now - template - MessageBuilder& operator<<(const T& in) { return this->operator,(in); } + ~MessageBuilder(); - // the `,` operator has the lowest operator precedence - if `<<` is used by the user then - // the `,` operator will be called last which is not what we want and thus the `*` operator - // is used first (has higher operator precedence compared to `<<`) so that we guarantee that - // an operator of the MessageBuilder class is called first before the rest of the parameters - template - MessageBuilder& operator*(const T& in) { return this->operator,(in); } + // the preferred way of chaining parameters for stringification + DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4866) - bool log(); - void react(); - }; + template + MessageBuilder &operator,(const T &in) { + *m_stream << (DOCTEST_STRINGIFY(in)); + return *this; + } - template - ContextScope MakeContextScope(const L &lambda) { - return ContextScope(lambda); - } -} // namespace detail + DOCTEST_MSVC_SUPPRESS_WARNING_POP + + // kept here just for backwards-compatibility - the comma operator should be preferred now + template + MessageBuilder &operator<<(const T &in) { return this->operator,(in); } + + // the `,` operator has the lowest operator precedence - if `<<` is used by the user then + // the `,` operator will be called last which is not what we want and thus the `*` operator + // is used first (has higher operator precedence compared to `<<`) so that we guarantee that + // an operator of the MessageBuilder class is called first before the rest of the parameters + template + MessageBuilder &operator*(const T &in) { return this->operator,(in); } + + bool log(); + + void react(); + }; + + template + ContextScope MakeContextScope(const L &lambda) { + return ContextScope(lambda); + } + } // namespace detail #define DOCTEST_DEFINE_DECORATOR(name, type, def) \ struct name \ @@ -1921,196 +2084,210 @@ DOCTEST_MSVC_SUPPRESS_WARNING_POP void fill(detail::TestSuite& state) const { state.DOCTEST_CAT(m_, name) = data; } \ } -DOCTEST_DEFINE_DECORATOR(test_suite, const char*, ""); -DOCTEST_DEFINE_DECORATOR(description, const char*, ""); -DOCTEST_DEFINE_DECORATOR(skip, bool, true); -DOCTEST_DEFINE_DECORATOR(no_breaks, bool, true); -DOCTEST_DEFINE_DECORATOR(no_output, bool, true); -DOCTEST_DEFINE_DECORATOR(timeout, double, 0); -DOCTEST_DEFINE_DECORATOR(may_fail, bool, true); -DOCTEST_DEFINE_DECORATOR(should_fail, bool, true); -DOCTEST_DEFINE_DECORATOR(expected_failures, int, 0); - -template -int registerExceptionTranslator(String (*translateFunction)(T)) { - DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wexit-time-destructors") - static detail::ExceptionTranslator exceptionTranslator(translateFunction); - DOCTEST_CLANG_SUPPRESS_WARNING_POP - detail::registerExceptionTranslatorImpl(&exceptionTranslator); - return 0; -} + DOCTEST_DEFINE_DECORATOR(test_suite, const char*, ""); + + DOCTEST_DEFINE_DECORATOR(description, const char*, ""); + + DOCTEST_DEFINE_DECORATOR(skip, bool, true); + + DOCTEST_DEFINE_DECORATOR(no_breaks, bool, true); + + DOCTEST_DEFINE_DECORATOR(no_output, bool, true); + + DOCTEST_DEFINE_DECORATOR(timeout, double, 0); + + DOCTEST_DEFINE_DECORATOR(may_fail, bool, true); + + DOCTEST_DEFINE_DECORATOR(should_fail, bool, true); + + DOCTEST_DEFINE_DECORATOR(expected_failures, int, 0); + + template + int registerExceptionTranslator(String (*translateFunction)(T)) { + DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wexit-time-destructors") + static detail::ExceptionTranslator exceptionTranslator(translateFunction); + DOCTEST_CLANG_SUPPRESS_WARNING_POP + detail::registerExceptionTranslatorImpl(&exceptionTranslator); + return 0; + } } // namespace doctest // in a separate namespace outside of doctest because the DOCTEST_TEST_SUITE macro // introduces an anonymous namespace in which getCurrentTestSuite gets overridden namespace doctest_detail_test_suite_ns { -DOCTEST_INTERFACE doctest::detail::TestSuite& getCurrentTestSuite(); + DOCTEST_INTERFACE doctest::detail::TestSuite &getCurrentTestSuite(); } // namespace doctest_detail_test_suite_ns namespace doctest { #else // DOCTEST_CONFIG_DISABLE -template -int registerExceptionTranslator(String (*)(T)) { - return 0; -} + template + int registerExceptionTranslator(String (*)(T)) { + return 0; + } #endif // DOCTEST_CONFIG_DISABLE -namespace detail { - using assert_handler = void (*)(const AssertData&); - struct ContextState; -} // namespace detail + namespace detail { + using assert_handler = void (*)(const AssertData &); + struct ContextState; + } // namespace detail -class DOCTEST_INTERFACE Context -{ - detail::ContextState* p; + class DOCTEST_INTERFACE Context { + detail::ContextState *p; - void parseArgs(int argc, const char* const* argv, bool withDefaults = false); + void parseArgs(int argc, const char *const *argv, bool withDefaults = false); -public: - explicit Context(int argc = 0, const char* const* argv = nullptr); + public: + explicit Context(int argc = 0, const char *const *argv = nullptr); - Context(const Context&) = delete; - Context(Context&&) = delete; + Context(const Context &) = delete; - Context& operator=(const Context&) = delete; - Context& operator=(Context&&) = delete; + Context(Context &&) = delete; - ~Context(); // NOLINT(performance-trivially-destructible) + Context &operator=(const Context &) = delete; - void applyCommandLine(int argc, const char* const* argv); + Context &operator=(Context &&) = delete; - void addFilter(const char* filter, const char* value); - void clearFilters(); - void setOption(const char* option, bool value); - void setOption(const char* option, int value); - void setOption(const char* option, const char* value); + ~Context(); // NOLINT(performance-trivially-destructible) - bool shouldExit(); + void applyCommandLine(int argc, const char *const *argv); - void setAsDefaultForAssertsOutOfTestCases(); + void addFilter(const char *filter, const char *value); - void setAssertHandler(detail::assert_handler ah); + void clearFilters(); - void setCout(std::ostream* out); + void setOption(const char *option, bool value); - int run(); -}; + void setOption(const char *option, int value); -namespace TestCaseFailureReason { - enum Enum - { - None = 0, - AssertFailure = 1, // an assertion has failed in the test case - Exception = 2, // test case threw an exception - Crash = 4, // a crash... - TooManyFailedAsserts = 8, // the abort-after option - Timeout = 16, // see the timeout decorator - ShouldHaveFailedButDidnt = 32, // see the should_fail decorator - ShouldHaveFailedAndDid = 64, // see the should_fail decorator - DidntFailExactlyNumTimes = 128, // see the expected_failures decorator - FailedExactlyNumTimes = 256, // see the expected_failures decorator - CouldHaveFailedAndDid = 512 // see the may_fail decorator + void setOption(const char *option, const char *value); + + bool shouldExit(); + + void setAsDefaultForAssertsOutOfTestCases(); + + void setAssertHandler(detail::assert_handler ah); + + void setCout(std::ostream *out); + + int run(); }; -} // namespace TestCaseFailureReason -struct DOCTEST_INTERFACE CurrentTestCaseStats -{ - int numAssertsCurrentTest; - int numAssertsFailedCurrentTest; - double seconds; - int failure_flags; // use TestCaseFailureReason::Enum - bool testCaseSuccess; -}; - -struct DOCTEST_INTERFACE TestCaseException -{ - String error_string; - bool is_crash; -}; + namespace TestCaseFailureReason { + enum Enum { + None = 0, + AssertFailure = 1, // an assertion has failed in the test case + Exception = 2, // test case threw an exception + Crash = 4, // a crash... + TooManyFailedAsserts = 8, // the abort-after option + Timeout = 16, // see the timeout decorator + ShouldHaveFailedButDidnt = 32, // see the should_fail decorator + ShouldHaveFailedAndDid = 64, // see the should_fail decorator + DidntFailExactlyNumTimes = 128, // see the expected_failures decorator + FailedExactlyNumTimes = 256, // see the expected_failures decorator + CouldHaveFailedAndDid = 512 // see the may_fail decorator + }; + } // namespace TestCaseFailureReason + + struct DOCTEST_INTERFACE CurrentTestCaseStats { + int numAssertsCurrentTest; + int numAssertsFailedCurrentTest; + double seconds; + int failure_flags; // use TestCaseFailureReason::Enum + bool testCaseSuccess; + }; -struct DOCTEST_INTERFACE TestRunStats -{ - unsigned numTestCases; - unsigned numTestCasesPassingFilters; - unsigned numTestSuitesPassingFilters; - unsigned numTestCasesFailed; - int numAsserts; - int numAssertsFailed; -}; - -struct QueryData -{ - const TestRunStats* run_stats = nullptr; - const TestCaseData** data = nullptr; - unsigned num_data = 0; -}; + struct DOCTEST_INTERFACE TestCaseException { + String error_string; + bool is_crash; + }; -struct DOCTEST_INTERFACE IReporter -{ - // The constructor has to accept "const ContextOptions&" as a single argument - // which has most of the options for the run + a pointer to the stdout stream - // Reporter(const ContextOptions& in) + struct DOCTEST_INTERFACE TestRunStats { + unsigned numTestCases; + unsigned numTestCasesPassingFilters; + unsigned numTestSuitesPassingFilters; + unsigned numTestCasesFailed; + int numAsserts; + int numAssertsFailed; + }; - // called when a query should be reported (listing test cases, printing the version, etc.) - virtual void report_query(const QueryData&) = 0; + struct QueryData { + const TestRunStats *run_stats = nullptr; + const TestCaseData **data = nullptr; + unsigned num_data = 0; + }; - // called when the whole test run starts - virtual void test_run_start() = 0; - // called when the whole test run ends (caching a pointer to the input doesn't make sense here) - virtual void test_run_end(const TestRunStats&) = 0; + struct DOCTEST_INTERFACE IReporter { + // The constructor has to accept "const ContextOptions&" as a single argument + // which has most of the options for the run + a pointer to the stdout stream + // Reporter(const ContextOptions& in) - // called when a test case is started (safe to cache a pointer to the input) - virtual void test_case_start(const TestCaseData&) = 0; - // called when a test case is reentered because of unfinished subcases (safe to cache a pointer to the input) - virtual void test_case_reenter(const TestCaseData&) = 0; - // called when a test case has ended - virtual void test_case_end(const CurrentTestCaseStats&) = 0; + // called when a query should be reported (listing test cases, printing the version, etc.) + virtual void report_query(const QueryData &) = 0; - // called when an exception is thrown from the test case (or it crashes) - virtual void test_case_exception(const TestCaseException&) = 0; + // called when the whole test run starts + virtual void test_run_start() = 0; - // called whenever a subcase is entered (don't cache pointers to the input) - virtual void subcase_start(const SubcaseSignature&) = 0; - // called whenever a subcase is exited (don't cache pointers to the input) - virtual void subcase_end() = 0; + // called when the whole test run ends (caching a pointer to the input doesn't make sense here) + virtual void test_run_end(const TestRunStats &) = 0; - // called for each assert (don't cache pointers to the input) - virtual void log_assert(const AssertData&) = 0; - // called for each message (don't cache pointers to the input) - virtual void log_message(const MessageData&) = 0; + // called when a test case is started (safe to cache a pointer to the input) + virtual void test_case_start(const TestCaseData &) = 0; - // called when a test case is skipped either because it doesn't pass the filters, has a skip decorator - // or isn't in the execution range (between first and last) (safe to cache a pointer to the input) - virtual void test_case_skipped(const TestCaseData&) = 0; + // called when a test case is reentered because of unfinished subcases (safe to cache a pointer to the input) + virtual void test_case_reenter(const TestCaseData &) = 0; - DOCTEST_DECLARE_INTERFACE(IReporter) + // called when a test case has ended + virtual void test_case_end(const CurrentTestCaseStats &) = 0; - // can obtain all currently active contexts and stringify them if one wishes to do so - static int get_num_active_contexts(); - static const IContextScope* const* get_active_contexts(); + // called when an exception is thrown from the test case (or it crashes) + virtual void test_case_exception(const TestCaseException &) = 0; - // can iterate through contexts which have been stringified automatically in their destructors when an exception has been thrown - static int get_num_stringified_contexts(); - static const String* get_stringified_contexts(); -}; + // called whenever a subcase is entered (don't cache pointers to the input) + virtual void subcase_start(const SubcaseSignature &) = 0; -namespace detail { - using reporterCreatorFunc = IReporter* (*)(const ContextOptions&); + // called whenever a subcase is exited (don't cache pointers to the input) + virtual void subcase_end() = 0; - DOCTEST_INTERFACE void registerReporterImpl(const char* name, int prio, reporterCreatorFunc c, bool isReporter); + // called for each assert (don't cache pointers to the input) + virtual void log_assert(const AssertData &) = 0; - template - IReporter* reporterCreator(const ContextOptions& o) { - return new Reporter(o); - } -} // namespace detail + // called for each message (don't cache pointers to the input) + virtual void log_message(const MessageData &) = 0; -template -int registerReporter(const char* name, int priority, bool isReporter) { - detail::registerReporterImpl(name, priority, detail::reporterCreator, isReporter); - return 0; -} + // called when a test case is skipped either because it doesn't pass the filters, has a skip decorator + // or isn't in the execution range (between first and last) (safe to cache a pointer to the input) + virtual void test_case_skipped(const TestCaseData &) = 0; + + DOCTEST_DECLARE_INTERFACE(IReporter) + + // can obtain all currently active contexts and stringify them if one wishes to do so + static int get_num_active_contexts(); + + static const IContextScope *const *get_active_contexts(); + + // can iterate through contexts which have been stringified automatically in their destructors when an exception has been thrown + static int get_num_stringified_contexts(); + + static const String *get_stringified_contexts(); + }; + + namespace detail { + using reporterCreatorFunc = IReporter *(*)(const ContextOptions &); + + DOCTEST_INTERFACE void registerReporterImpl(const char *name, int prio, reporterCreatorFunc c, bool isReporter); + + template + IReporter *reporterCreator(const ContextOptions &o) { + return new Reporter(o); + } + } // namespace detail + + template + int registerReporter(const char *name, int priority, bool isReporter) { + detail::registerReporterImpl(name, priority, detail::reporterCreator, isReporter); + return 0; + } } // namespace doctest #ifdef DOCTEST_CONFIG_ASSERTS_RETURN_VALUES @@ -2432,7 +2609,7 @@ int registerReporter(const char* name, int priority, bool isReporter) { #define DOCTEST_UNARY_ASSERT(assert_type, ...) \ doctest::detail::unary_assert(doctest::assertType::assert_type, __FILE__, __LINE__, \ - #__VA_ARGS__, __VA_ARGS__) +#__VA_ARGS__, __VA_ARGS__) #endif // DOCTEST_CONFIG_SUPER_FAST_ASSERTS @@ -3830,8 +4007,8 @@ namespace Color { // clang-format off const char* assertString(assertType::Enum at) { DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4061) // enum 'x' in switch of enum 'y' is not explicitly handled - #define DOCTEST_GENERATE_ASSERT_TYPE_CASE(assert_type) case assertType::DT_ ## assert_type: return #assert_type - #define DOCTEST_GENERATE_ASSERT_TYPE_CASES(assert_type) \ +#define DOCTEST_GENERATE_ASSERT_TYPE_CASE(assert_type) case assertType::DT_ ## assert_type: return #assert_type +#define DOCTEST_GENERATE_ASSERT_TYPE_CASES(assert_type) \ DOCTEST_GENERATE_ASSERT_TYPE_CASE(WARN_ ## assert_type); \ DOCTEST_GENERATE_ASSERT_TYPE_CASE(CHECK_ ## assert_type); \ DOCTEST_GENERATE_ASSERT_TYPE_CASE(REQUIRE_ ## assert_type) diff --git a/main.cpp b/main.cpp index 89e5d3b..4a87121 100644 --- a/main.cpp +++ b/main.cpp @@ -6,11 +6,11 @@ int main() { auto y = Vector(n - 1, -1); auto A = Matrix(n, n); - for(ull i = 0; i < n; i++) { - for(ull j = 0; j < n; j++) { - if(i == j) { + for (ull i = 0; i < n; i++) { + for (ull j = 0; j < n; j++) { + if (i == j) { A.matrix[i][j] = 2; - } else if(i == j + 1 || i == j - 1) { + } else if (i == j + 1 || i == j - 1) { A.matrix[i][j] = -1; } }