| 2483 | // type T can be DiagMatr, FullStateDiagMatr |
| 2484 | template <class T> |
| 2485 | void assertMatrExpIsNonDiverging(T matr, qcomp exponent, const char* caller) { |
| 2486 | |
| 2487 | validate_matrixFields(matr, caller); |
| 2488 | validate_matrixIsSynced(matr, caller); |
| 2489 | |
| 2490 | // avoid exepensive and epsilon-dependent validation below (do not overwrite matr.isApproxNonZero) |
| 2491 | if (isNumericalValidationDisabled()) |
| 2492 | return; |
| 2493 | |
| 2494 | // divergences are only validated when the imaginary component is strictly |
| 2495 | // zero, otherwise alternate complex exponentiation is sometimes performed |
| 2496 | // with a more complicated numerical stability |
| 2497 | if (std::imag(exponent) != 0) |
| 2498 | return; |
| 2499 | |
| 2500 | // when the real exponent is STRICTLY less than zero, it is required that every |
| 2501 | // matrix element's magnitude is APPROX non-zero, to avoid 1/0 divergences. |
| 2502 | // We do this independent of the size of exponent, even despite that exponents |
| 2503 | // really close to 0 (from below) can "counteract" the blowing up, because |
| 2504 | // precision is too poor near epsilon for this to be implicitly relied upon. |
| 2505 | if (std::real(exponent) < 0) |
| 2506 | assertThat(util_isApproxNonZero(matr, global_validationEpsilon), report::DIAG_MATR_APPROX_ZERO_WHILE_EXPONENT_REAL_AND_NEGATIVE, caller); |
| 2507 | } |
| 2508 | void validate_matrixExpIsNonDiverging(DiagMatr m, qcomp p, const char* caller) { assertMatrExpIsNonDiverging(m, p, caller); } |
| 2509 | void validate_matrixExpIsNonDiverging(FullStateDiagMatr m, qcomp p, const char* caller) { assertMatrExpIsNonDiverging(m, p, caller); } |
| 2510 |
no test coverage detected