11#include "quest/include/matrices.h"
12#include "quest/include/environment.h"
13#include "quest/include/types.h"
15#include "quest/src/core/validation.hpp"
16#include "quest/src/core/autodeployer.hpp"
17#include "quest/src/core/utilities.hpp"
18#include "quest/src/core/localiser.hpp"
19#include "quest/src/core/printer.hpp"
20#include "quest/src/core/bitwise.hpp"
21#include "quest/src/core/fastmath.hpp"
22#include "quest/src/core/memory.hpp"
23#include "quest/src/comm/comm_config.hpp"
24#include "quest/src/comm/comm_routines.hpp"
25#include "quest/src/cpu/cpu_config.hpp"
26#include "quest/src/gpu/gpu_config.hpp"
27#include "quest/src/cpu/cpu_subroutines.hpp"
49 validate_matrixNumNewElems(1, in, __func__);
51 qcomp* rowPtrs[] = {in[0].data(), in[1].data()};
56 validate_matrixNumNewElems(2, in, __func__);
58 qcomp* rowPtrs[] = {in[0].data(), in[1].data(), in[2].data(), in[3].data()};
64 validate_matrixNumNewElems(1, in, __func__);
70 validate_matrixNumNewElems(2, in, __func__);
84void freeHeapMatrix(T matr) {
93 if constexpr (util_isDenseMatrixType<T>()) {
94 cpu_deallocMatrixWrapper(matr.cpuElems);
95 cpu_deallocArray(matr.cpuElemsFlat);
97 cpu_deallocArray(matr.cpuElems);
100 auto gpuPtr = util_getGpuMemPtr(matr);
101 if (mem_isAllocated(gpuPtr))
102 gpu_deallocArray(gpuPtr);
105 util_deallocEpsilonSensitiveHeapFlag(matr.isApproxUnitary);
106 util_deallocEpsilonSensitiveHeapFlag(matr.isApproxHermitian);
107 cpu_deallocHeapFlag(matr.wasGpuSynced);
111 if constexpr (!util_isDenseMatrixType<T>()) {
112 util_deallocEpsilonSensitiveHeapFlag(matr.isApproxNonZero);
113 cpu_deallocHeapFlag(matr.isStrictlyNonNegative);
120bool didAnyLocalAllocsFail(T matr) {
123 if (!mem_isAllocated(matr.isApproxUnitary))
return true;
124 if (!mem_isAllocated(matr.isApproxHermitian))
return true;
125 if (!mem_isAllocated(matr.wasGpuSynced))
return true;
129 if constexpr (!util_isDenseMatrixType<T>()) {
130 if (!mem_isAllocated(matr.isApproxNonZero))
return true;
131 if (!mem_isAllocated(matr.isStrictlyNonNegative))
return true;
135 if constexpr (util_isDenseMatrixType<T>()) {
136 if (!mem_isAllocated(matr.cpuElemsFlat))
return true;
137 if (!mem_isOuterAllocated(matr.cpuElems))
return true;
139 if (!mem_isAllocated(matr.cpuElems))
return true;
142 bool isGpuAlloc = mem_isAllocated(util_getGpuMemPtr(matr));
143 if (
getQuESTEnv().isGpuAccelerated && !isGpuAlloc) {
146 if constexpr (util_isFullStateDiagMatr<T>()) {
147 if (matr.isGpuAccelerated)
162void freeAllMemoryIfAnyAllocsFailed(T matr) {
165 bool anyFail = didAnyLocalAllocsFail(matr);
167 anyFail = comm_isTrueOnAllNodes(anyFail);
171 freeHeapMatrix(matr);
177void validateMatrixAllocs(T matr,
const char* caller) {
180 freeAllMemoryIfAnyAllocsFailed(matr);
181 validate_newMatrixAllocs(matr, caller);
187void setInitialHeapFlags(T matr) {
190 util_setFlagToUnknown(matr.isApproxUnitary);
191 util_setFlagToUnknown(matr.isApproxHermitian);
195 if constexpr (!util_isDenseMatrixType<T>()) {
196 util_setFlagToUnknown(matr.isApproxNonZero);
197 util_setFlagToUnknown(matr.isStrictlyNonNegative);
201 *(matr.wasGpuSynced) = 0;
212 validate_envIsInit(__func__);
213 validate_newCompMatrParams(numQubits, __func__);
216 qindex numRows = powerOf2(numQubits);
217 qindex numElems = numRows * numRows;
220 qcomp* cpuMem = cpu_allocArray(numElems);
221 qcomp* gpuMem =
nullptr;
223 gpuMem = gpu_allocArray(numElems);
227 out.numQubits = numQubits;
228 out.numRows = numRows;
231 out.isApproxUnitary = util_allocEpsilonSensitiveHeapFlag();
232 out.isApproxHermitian = util_allocEpsilonSensitiveHeapFlag();
236 out.cpuElems = cpu_allocAndInitMatrixWrapper(cpuMem, numRows);
237 out.cpuElemsFlat = cpuMem;
238 out.gpuElemsFlat = gpuMem;
240 validateMatrixAllocs(out, __func__);
241 setInitialHeapFlags(out);
247 validate_envIsInit(__func__);
248 validate_newDiagMatrParams(numQubits, __func__);
251 qindex numElems = powerOf2(numQubits);
255 out.numQubits = numQubits,
256 out.numElems = numElems,
259 out.isApproxUnitary = util_allocEpsilonSensitiveHeapFlag();
260 out.isApproxHermitian = util_allocEpsilonSensitiveHeapFlag();
266 out.cpuElems = cpu_allocArray(numElems);
267 out.gpuElems = (
getQuESTEnv().isGpuAccelerated)? gpu_allocArray(numElems) :
nullptr;
269 validateMatrixAllocs(out, __func__);
270 setInitialHeapFlags(out);
275FullStateDiagMatr validateAndCreateCustomFullStateDiagMatr(
int numQubits,
int useDistrib,
int useGpuAccel,
int useMultithread,
const char* caller) {
276 validate_envIsInit(caller);
280 validate_newFullStateDiagMatrParams(numQubits, useDistrib, useGpuAccel, useMultithread, caller);
283 autodep_chooseFullStateDiagMatrDeployment(numQubits, useDistrib, useGpuAccel, useMultithread, env);
286 qindex numElems = powerOf2(numQubits);
287 qindex numElemsPerNode = numElems / (useDistrib? env.numNodes : 1);
291 out.numQubits = numQubits;
292 out.numElems = numElems;
295 out.isGpuAccelerated = useGpuAccel;
296 out.isMultithreaded = useMultithread;
297 out.isDistributed = useDistrib && (env.numNodes > 1);
298 out.numElemsPerNode = numElemsPerNode;
301 out.isApproxUnitary = util_allocEpsilonSensitiveHeapFlag();
302 out.isApproxHermitian = util_allocEpsilonSensitiveHeapFlag();
303 out.isApproxNonZero = util_allocEpsilonSensitiveHeapFlag();
304 out.isStrictlyNonNegative = cpu_allocHeapFlag();
305 out.wasGpuSynced = cpu_allocHeapFlag();
308 out.cpuElems = cpu_allocArray(numElemsPerNode);
309 out.gpuElems = (useGpuAccel)? gpu_allocArray(numElemsPerNode) :
nullptr;
311 validateMatrixAllocs(out, __func__);
312 setInitialHeapFlags(out);
318 return validateAndCreateCustomFullStateDiagMatr(numQubits, useDistrib, useGpuAccel, useMultithread, __func__);
323 return validateAndCreateCustomFullStateDiagMatr(numQubits, modeflag::USE_AUTO, modeflag::USE_AUTO, modeflag::USE_AUTO, __func__);
335void markMatrixAsSynced(T matr) {
339 *(matr.wasGpuSynced) = 1;
343 util_setFlagToUnknown(matr.isApproxUnitary);
344 util_setFlagToUnknown(matr.isApproxHermitian);
348 if constexpr (!util_isDenseMatrixType<T>()) {
349 util_setFlagToUnknown(matr.isApproxNonZero);
350 util_setFlagToUnknown(matr.isStrictlyNonNegative);
357void validateAndSyncMatrix(T matr,
const char* caller) {
358 validate_matrixFields(matr, caller);
361 if (mem_isAllocated(util_getGpuMemPtr(matr)))
362 gpu_copyCpuToGpu(matr);
364 markMatrixAsSynced(matr);
386void validateAndDestroyMatrix(T matrix,
const char* caller) {
387 validate_matrixFields(matrix, caller);
389 freeHeapMatrix(matrix);
411void setAndSyncDenseMatrElems(
CompMatr out, T elems) {
414 cpu_copyMatrix(out.cpuElems, elems, out.numRows);
422 validate_matrixFields(out, __func__);
423 validate_matrixNewElemsPtrNotNull(in, out.numRows, __func__);
425 setAndSyncDenseMatrElems(out, in);
430 validate_matrixFields(out, __func__);
431 validate_matrixNewElemsPtrNotNull(in, __func__);
434 cpu_copyArray(out.cpuElems, in, out.numElems);
442 validate_matrixFields(out, __func__);
443 validate_fullStateDiagMatrNewElems(out, startInd, numElems, __func__);
444 validate_matrixNewElemsPtrNotNull(in, __func__);
449 localiser_fullstatediagmatr_setElems(out, startInd, in, numElems);
453 markMatrixAsSynced(out);
464 validate_matrixFields(out, __func__);
465 validate_matrixNumNewElems(out.numQubits, in, __func__);
467 setAndSyncDenseMatrElems(out, in);
472 validate_matrixFields(out, __func__);
473 validate_matrixNumNewElems(out.numQubits, in, __func__);
502 validate_matrixFields(matr, __func__);
503 validate_matrixNumQubitsMatchesParam(matr.numQubits, numQb, __func__);
504 validate_matrixNumNewElems(matr.numQubits, in, __func__);
506 setAndSyncDenseMatrElems(matr, in);
510 validate_matrixFields(matr, __func__);
511 validate_matrixNumQubitsMatchesParam(matr.numQubits, numQb, __func__);
512 validate_matrixNumNewElems(matr.numQubits, in, __func__);
518 validate_matrixFields(matr, __func__);
519 validate_declaredNumElemsMatchesVectorLength(numElems, in.size(), __func__);
520 validate_fullStateDiagMatrNewElems(matr, startInd, numElems, __func__);
535 validate_envIsInit(__func__);
536 validate_newCompMatrParams(numQb, __func__);
537 validate_matrixNumNewElems(numQb, elems, __func__);
542 setAndSyncDenseMatrElems(matr, elems);
548 validate_envIsInit(__func__);
549 validate_newDiagMatrParams(numQb, __func__);
550 validate_matrixNumNewElems(numQb, elems, __func__);
574 void _validateNewNestedElemsPtrNotNull(qcomp** ptrs,
int numQubits,
const char* caller) {
576 validate_matrixNewElemsPtrNotNull(ptrs, powerOf2(numQubits), caller);
578 void _validateNewElemsPtrNotNull(qcomp* ptr,
const char* caller) {
580 validate_matrixNewElemsPtrNotNull(ptr, caller);
583 void _validateParamsToSetCompMatrFromArr(
CompMatr matr) {
585 validate_matrixFields(matr,
"setCompMatr");
588 void _validateParamsToSetInlineCompMatr(
CompMatr matr,
int numQb) {
590 const char* caller =
"setInlineCompMatr";
591 validate_matrixFields(matr, caller);
592 validate_matrixNumQubitsMatchesParam(matr.numQubits, numQb, caller);
595 void _validateParamsToSetInlineDiagMatr(
DiagMatr matr,
int numQb) {
597 const char* caller =
"setInlineDiagMatr";
598 validate_matrixFields(matr, caller);
599 validate_matrixNumQubitsMatchesParam(matr.numQubits, numQb, caller);
602 void _validateParamsToSetInlineFullStateDiagMatr(
FullStateDiagMatr matr, qindex startInd, qindex numElems) {
604 const char* caller =
"setInlineFullStateDiagMatr";
605 validate_matrixFields(matr, caller);
606 validate_fullStateDiagMatrNewElems(matr, startInd, numElems, caller);
609 void _validateParamsToCreateInlineCompMatr(
int numQb) {
611 const char* caller =
"createInlineCompMatr";
612 validate_envIsInit(caller);
613 validate_newCompMatrParams(numQb, caller);
616 void _validateParamsToCreateInlineDiagMatr(
int numQb) {
618 const char* caller =
"createInlineDiagMatr";
619 validate_envIsInit(caller);
620 validate_newDiagMatrParams(numQb, caller);
632extern int paulis_getIndOfLefmostNonIdentityPauli(
PauliStrSum sum);
636 validate_matrixFields(out, __func__);
637 validate_pauliStrSumFields(in, __func__);
638 validate_pauliStrSumCanInitMatrix(out, in, __func__);
646 localiser_fullstatediagmatr_setElemsToPauliStrSum(out, in);
648 markMatrixAsSynced(out);
653 validate_pauliStrSumFields(in, __func__);
656 int numQubits = 1 + paulis_getIndOfLefmostNonIdentityPauli(in);
657 validate_newFullStateDiagMatrParams(numQubits, modeflag::USE_AUTO, modeflag::USE_AUTO, modeflag::USE_AUTO, __func__);
662 localiser_fullstatediagmatr_setElemsToPauliStrSum(out, in);
663 markMatrixAsSynced(out);
669 validate_matrixFields(out, __func__);
670 validate_multiVarFuncQubits(out.numQubits, numQubitsPerVar, numVars, __func__);
671 validate_funcVarSignedFlag(areSigned, __func__);
673 vector<qindex> varValues(numVars);
676 for (qindex elemInd=0; elemInd<out.numElems; elemInd++) {
677 fast_getSubQuregValues(elemInd, numQubitsPerVar, numVars, areSigned, varValues.data());
680 out.cpuElems[elemInd] = callbackFunc(varValues.data());
689 validate_matrixFields(out, __func__);
690 validate_multiVarFuncQubits(out.numQubits, numQubitsPerVar, numVars, __func__);
691 validate_funcVarSignedFlag(areSigned, __func__);
695 cpu_fullstatediagmatr_setElemsFromMultiVarFunc(out, callbackFunc, numQubitsPerVar, numVars, areSigned);
703 validate_matrixFields(out, __func__);
704 validate_multiVarFuncQubits(out.numQubits, numQubitsPerDim, numDims, __func__);
706 vector<qindex> listInds(numDims);
710 for (qindex elemInd=0; elemInd<out.numElems; elemInd++) {
713 fast_getSubQuregValues(elemInd, numQubitsPerDim, numDims,
false, listInds.data());
716 out.cpuElems[elemInd] = util_getElemFromNestedPtrs(lists, listInds.data(), numDims);
725 validate_matrixFields(out, __func__);
726 validate_multiVarFuncQubits(out.numQubits, numQubitsPerDim, numDims, __func__);
730 cpu_fullstatediagmatr_setElemsFromMultiDimLists(out, lists, numQubitsPerDim, numDims);
745void validateAndPrintMatrix(T matr,
const char* caller) {
746 validate_matrixFields(matr, caller);
747 validate_numReportedNewlinesAboveZero(__func__);
750 if constexpr (util_isHeapMatrixType<T>())
751 validate_matrixIsSynced(matr, caller);
758 int numNodes = (util_isDistributedMatrix(matr))? comm_getNumNodes() : 1;
759 size_t elemMem = mem_getLocalMatrixMemoryRequired(matr.numQubits, util_isDenseMatrixType<T>(), numNodes);
760 size_t structMem =
sizeof(matr);
763 if (util_isFixedSizeMatrixType<T>())
764 structMem -= elemMem;
766 size_t numBytesPerNode = elemMem + structMem;
767 print_header(matr, numBytesPerNode);
771 print_oneFewerNewlines();
FullStateDiagMatr createCustomFullStateDiagMatr(int numQubits, int useDistrib, int useGpuAccel, int useMultithread)
DiagMatr createInlineDiagMatr(int numQb, std::vector< qcomp > elems)
FullStateDiagMatr createFullStateDiagMatr(int numQubits)
CompMatr createInlineCompMatr(int numQb, std::vector< std::vector< qcomp > > elems)
CompMatr createCompMatr(int numQubits)
DiagMatr createDiagMatr(int numQubits)
FullStateDiagMatr createFullStateDiagMatrFromPauliStrSum(PauliStrSum in)
void destroyDiagMatr(DiagMatr matr)
void destroyFullStateDiagMatr(FullStateDiagMatr matr)
void destroyCompMatr(CompMatr matr)
DiagMatr1 getDiagMatr1(std::vector< qcomp > in)
CompMatr1 getCompMatr1(std::vector< std::vector< qcomp > > in)
CompMatr2 getCompMatr2(std::vector< std::vector< qcomp > > in)
DiagMatr2 getDiagMatr2(std::vector< qcomp > in)
void reportCompMatr2(CompMatr2 matr)
void reportDiagMatr1(DiagMatr1 matr)
void reportCompMatr(CompMatr matr)
void reportDiagMatr2(DiagMatr2 matr)
void reportCompMatr1(CompMatr1 matr)
void reportDiagMatr(DiagMatr matr)
void reportFullStateDiagMatr(FullStateDiagMatr matr)
void setInlineDiagMatr(DiagMatr matr, int numQb, std::vector< qcomp > in)
void setFullStateDiagMatrFromMultiDimLists(FullStateDiagMatr out, void *lists, int *numQubitsPerDim, int numDims)
void setDiagMatrFromMultiDimLists(DiagMatr out, void *lists, int *numQubitsPerDim, int numDims)
void setFullStateDiagMatrFromMultiVarFunc(FullStateDiagMatr out, qcomp(*callbackFunc)(qindex *), int *numQubitsPerVar, int numVars, int areSigned)
void setInlineCompMatr(CompMatr matr, int numQb, std::vector< std::vector< qcomp > > in)
void setDiagMatr(DiagMatr out, qcomp *in)
void setCompMatr(CompMatr out, qcomp **in)
void setFullStateDiagMatr(FullStateDiagMatr out, qindex startInd, qcomp *in, qindex numElems)
void setDiagMatrFromMultiVarFunc(DiagMatr out, qcomp(*callbackFunc)(qindex *), int *numQubitsPerVar, int numVars, int areSigned)
void setFullStateDiagMatrFromPauliStrSum(FullStateDiagMatr out, PauliStrSum in)
void setInlineFullStateDiagMatr(FullStateDiagMatr matr, qindex startInd, qindex numElems, std::vector< qcomp > in)
void syncFullStateDiagMatr(FullStateDiagMatr matr)
void syncDiagMatr(DiagMatr matr)
void syncCompMatr(CompMatr matr)
int * isStrictlyNonNegative