| 2059 | // T can be CompMatr, DiagMatr, FullStateDiagMatr (i.e. heap-based matrices) |
| 2060 | template <typename T> |
| 2061 | void assertNewMatrixAllocsSucceeded(T matr, size_t numBytes, const char* caller) { |
| 2062 | |
| 2063 | // this validation is called AFTER the caller has checked for failed |
| 2064 | // allocs and (in that scenario) freed every pointer, but does not |
| 2065 | // overwrite any pointers to nullptr, so the failed alloc is known. |
| 2066 | // This is only safe to do so (rather than making the caller set ptrs |
| 2067 | // to nullptr) because the structs contains only 1D pointer; even |
| 2068 | // CompMatr which "fakes" a 2D ptr via offsets of a contiguous array. |
| 2069 | |
| 2070 | // we expensively get node consensus about malloc failure, in case of heterogeneous hardware/loads, |
| 2071 | // but we avoid this potetially expensive synchronisation if validation is anyway disabled |
| 2072 | // (which also avoids us enumerating the matrix rows) |
| 2073 | if (!global_isValidationEnabled) |
| 2074 | return; |
| 2075 | |
| 2076 | /// @todo |
| 2077 | /// fix this abhorrent hackiness! Presently, tokenSubs accepts only qindex (in lieu of |
| 2078 | /// unsigned size_t) in order to be able to report negative numbers. But alas, the max |
| 2079 | /// size_t is bigger than max qindex, due to the sign-bit. So trying to report numBytes |
| 2080 | /// can cause a size_t -> qindex overflow. This is a realistic scenario, occurring when |
| 2081 | /// when the user tries to allocate the max-size memory for which malloc incidentally |
| 2082 | /// fails. This is when numBytes is +1 too big to be a qindex; we simply reduce by 2! |
| 2083 | /// We under-report the memory by 2 bytes, instead of 1, just to avoid an odd number |
| 2084 | /// which an astute user would immediately notice is not a power-of-2 and be confused by. |
| 2085 | /// This is a hacky evil, but it is better than reporting a negative memory size! |
| 2086 | tokenSubs vars; |
| 2087 | vars["${NUM_BYTES}"] = ((qindex) numBytes <= 0)? |
| 2088 | numBytes - 2 : numBytes; |
| 2089 | |
| 2090 | // assert CPU array (which may be nested arrays) all allocated successfully |
| 2091 | bool isAlloc; |
| 2092 | if constexpr (util_isDenseMatrixType<T>()) { |
| 2093 | // size of .cpuElems isn't included in numBytes report which is fine; it's |
| 2094 | // quadratically smaller than .cpuElemsFlat so quickly negligible |
| 2095 | isAlloc = mem_isAllocated(matr.cpuElemsFlat) && mem_isOuterAllocated(matr.cpuElems); |
| 2096 | } else |
| 2097 | isAlloc = mem_isAllocated(matr.cpuElems); |
| 2098 | assertAllNodesAgreeThat(isAlloc, report::NEW_MATRIX_CPU_ELEMS_ALLOC_FAILED, vars, caller); |
| 2099 | |
| 2100 | // optionally assert GPU memory was malloc'd successfully |
| 2101 | bool gpuShouldBeAlloc = getQuESTEnv().isGpuAccelerated; |
| 2102 | if constexpr (util_isFullStateDiagMatr<T>()) |
| 2103 | gpuShouldBeAlloc &= matr.isGpuAccelerated; |
| 2104 | |
| 2105 | if (gpuShouldBeAlloc) |
| 2106 | assertAllNodesAgreeThat(mem_isAllocated(util_getGpuMemPtr(matr)), report::NEW_MATRIX_GPU_ELEMS_ALLOC_FAILED, vars, caller); |
| 2107 | |
| 2108 | // assert the teeny-tiny heap flags are alloc'd |
| 2109 | vars["${NUM_BYTES}"] = sizeof(*(matr.isApproxUnitary)); // all fields are same-size |
| 2110 | assertAllNodesAgreeThat(mem_isAllocated(matr.isApproxUnitary), report::NEW_HEAP_FLAG_ALLOC_FAILED, vars, caller); |
| 2111 | assertAllNodesAgreeThat(mem_isAllocated(matr.isApproxHermitian), report::NEW_HEAP_FLAG_ALLOC_FAILED, vars, caller); |
| 2112 | assertAllNodesAgreeThat(mem_isAllocated(matr.wasGpuSynced), report::NEW_HEAP_FLAG_ALLOC_FAILED, vars, caller); |
| 2113 | |
| 2114 | // only diagonal matrices (which can be exponentiated) have these additional flags |
| 2115 | if constexpr (!util_isDenseMatrixType<T>()) { |
| 2116 | assertAllNodesAgreeThat(mem_isAllocated(matr.isApproxNonZero), report::NEW_HEAP_FLAG_ALLOC_FAILED, vars, caller); |
| 2117 | assertAllNodesAgreeThat(mem_isAllocated(matr.isStrictlyNonNegative), report::NEW_HEAP_FLAG_ALLOC_FAILED, vars, caller); |
| 2118 | } |
no test coverage detected