-#include <regex.h>
-#include "core.c"
+#include "qansel.h"
+#include "bytecode.c"
+#include "openqasm.c"
-void qansel_read_script(char* script, char*** chunksReturn, int** chunkLinesReturn, int* countReturn)
+void main(int argc, char** argv)
{
- size_t scriptSize = strlen(script);
- char* line = malloc(0);
- char** chunks = malloc(0);
- int* chunksAssociatedLines = malloc(0);
- int lineCount = 1;
- int lineLen = 0;
- int chunkCount = 0;
- int inComment = 0;
- for (int i = 0; i < scriptSize; i++)
- {
- int charactersLeft = scriptSize - i;
- if (script[i] == '\n')
- {
- lineCount++;
- inComment = 0;
- }
- else if (charactersLeft >= 2 && script[i] == '/' && script[i + 1] == '/')
- {
- inComment = 1;
- }
- else if (!inComment && script[i] != ';' && script[i] != '{' && script[i] != '}')
- {
- line = realloc(line, lineLen + 1);
- line[lineLen++] = script[i] == '\t' ? ' ' : script[i];
- if (script[i] == ')' && lineLen > 2)
- {
- for (int j = 0; j < lineLen - 1; j++)
- {
- if ( (line[j] == 'i' || line[j] == 'I') && (line[j + 1] == 'f' || line[j + 1] == 'F') )
- {
- line = realloc(line, lineLen + 1);
- line[lineLen++] = 0;
- chunks = realloc(chunks, (chunkCount + 1) * sizeof(char*));
- chunksAssociatedLines = realloc(chunksAssociatedLines, (chunkCount + 1) * sizeof(int));
- chunks[chunkCount] = line;
- chunksAssociatedLines[chunkCount++] = lineCount;
- line = malloc(0);
- lineLen = 0;
- break;
- }
- }
- }
- }
- else if (!inComment && (script[i] == '{' || script[i] == '}'))
- {
- if (lineLen > 0)
- {
- line = realloc(line, lineLen + 1);
- line[lineLen++] = 0;
- chunks = realloc(chunks, (chunkCount + 1) * sizeof(char*));
- chunksAssociatedLines = realloc(chunksAssociatedLines, (chunkCount + 1) * sizeof(int));
- chunks[chunkCount] = line;
- chunksAssociatedLines[chunkCount++] = lineCount;
- line = malloc(2);
- }
- else
- {
- line = realloc(line, 2);
- }
- line[0] = script[i];
- line[1] = 0;
- chunks = realloc(chunks, (chunkCount + 1) * sizeof(char*));
- chunksAssociatedLines = realloc(chunksAssociatedLines, (chunkCount + 1) * sizeof(int));
- chunks[chunkCount] = line;
- chunksAssociatedLines[chunkCount++] = lineCount;
- line = malloc(0);
- lineLen = 0;
- }
- else if (!inComment && script[i] == ';')
- {
- if (lineLen > 0)
- {
- line = realloc(line, lineLen + 1);
- line[lineLen++] = 0;
- chunks = realloc(chunks, (chunkCount + 1) * sizeof(char*));
- chunksAssociatedLines = realloc(chunksAssociatedLines, (chunkCount + 1) * sizeof(int));
- chunks[chunkCount] = line;
- chunksAssociatedLines[chunkCount++] = lineCount;
- line = malloc(0);
- lineLen = 0;
- }
- }
- }
- if (lineLen > 0)
- {
- line = realloc(line, lineLen + 1);
- line[lineLen++] = 0;
- chunks = realloc(chunks, (chunkCount + 1) * sizeof(char*));
- chunksAssociatedLines = realloc(chunksAssociatedLines, (chunkCount + 1) * sizeof(int));
- chunks[chunkCount] = line;
- chunksAssociatedLines[chunkCount++] = lineCount;
- }
- else
- {
- free(line);
- }
- for (int i = 0; i < chunkCount; i++)
- {
- int len = strlen(chunks[i]);
- for (int j = 0; j < len; j++)
- {
- if (chunks[i][j] >= 'A' && chunks[i][j] <= 'Z')
- {
- chunks[i][j] += 'a' - 'A';
- }
- }
- }
- *chunksReturn = chunks;
- *chunkLinesReturn = chunksAssociatedLines;
- *countReturn = chunkCount;
-}
+ int opt;
+ int optimizationSettings = QANSEL_MODE_BARE;
+ int displaySettings = 0;
+ int maximumQubitSettings = QANSEL_QUBITS_MAX;
+ int hardwarerngSetting = 0;
-float qansel_parse_float_part(char* neg, char* str)
-{
- float ret;
- int len = strlen(str);
- if (len > 2)
+ while ((opt = getopt(argc, argv, "o:q:d:rv")) != -1)
{
- ret = atof(str);
- if (str[len - 2] == 'p' && str[len - 1] == 'i')
+ switch (opt)
{
- ret *= M_PI;
+ case 'o': optimizationSettings = atoi(optarg); break;
+ case 'd': displaySettings = atoi(optarg); break;
+ case 'q': maximumQubitSettings = atoi(optarg); break;
+ case 'r': hardwarerngSetting = 1; break;
+ case 'v': QANSEL_VERBOSE = 1; break;
+ default: exit(1);
}
}
- else if (strcmp(str, "pi") == 0)
- {
- ret = M_PI;
- }
- else
- {
- ret = atof(str);
- }
- if (strcmp(neg, "-") == 0)
- {
- ret *= -1;
- }
- return ret;
-}
-
-int qansel_parse_float(char* str, float* returnFloat)
-{
- *returnFloat = 0;
- const char expr[] = "^(-|)([0-9][0-9]*\\.[0-9]*|[0-9][0-9]*|[0-9][0-9]*\\.[0-9]*pi|[0-9][0-9]*pi|pi)([/](-|)([0-9][0-9]*\\.[0-9]*|[0-9][0-9]*|[0-9][0-9]*\\.[0-9]*pi|[0-9][0-9]*pi|pi)|)$";
- regex_t regex;
- regmatch_t regmatches[10];
- if (regcomp(®ex, expr, REG_EXTENDED | REG_ICASE)) return 0;
- int ret = regexec(®ex, str, 10, regmatches, 0);
- if (!ret)
- {
- int strbeg = regmatches[1].rm_so;
- int strlen = regmatches[1].rm_eo - regmatches[1].rm_so;
- char neg1[strlen + 1];
- memcpy(neg1, str + strbeg, strlen);
- neg1[strlen] = 0;
- strbeg = regmatches[2].rm_so;
- strlen = regmatches[2].rm_eo - regmatches[2].rm_so;
- char numer[strlen + 1];
- memcpy(numer, str + strbeg, strlen);
- numer[strlen] = 0;
- *returnFloat = qansel_parse_float_part(neg1, numer);
-
- if (regmatches[3].rm_eo > regmatches[3].rm_so)
- {
- strbeg = regmatches[4].rm_so;
- strlen = regmatches[4].rm_eo - regmatches[4].rm_so;
- char neg2[strlen + 1];
- memcpy(neg2, str + strbeg, strlen);
- neg2[strlen] = 0;
-
- strbeg = regmatches[5].rm_so;
- strlen = regmatches[5].rm_eo - regmatches[5].rm_so;
- char denom[strlen + 1];
- memcpy(denom, str + strbeg, strlen);
- denom[strlen] = 0;
-
- float fdenom = qansel_parse_float_part(neg2, denom);
- *returnFloat /= fdenom;
- }
- }
- else if (ret == REG_NOMATCH)
- {
- return 0;
- }
- else
+ if (displaySettings < 0 | displaySettings > 100)
{
- char errbuf[100];
- regerror(ret, ®ex, errbuf, sizeof(errbuf));
- fprintf(stderr, "QAnsel: %s.\n", errbuf);
+ fprintf(stderr, "QAnsel: Invalid display settings.\n");
exit(1);
}
- regfree(®ex);
+ QANSEL_USE_DISPLAY = displaySettings;
- return 1;
-}
-
-int qansel_process_chunk(int index, char* chunk, int line, regmatch_t* regmatches, int* qubitCount, int* bitCount, unsigned char** binary, int* binarySize)
-{
- unsigned short s0;
- float d0, d1, d2;
- unsigned char instr = 0;
- unsigned char a0 = 0;
- unsigned char a1 = 0;
- unsigned char a2 = 0;
- if (index == 0) //qreg
- {
- if (*qubitCount > 0)
- {
- fprintf(stderr, "QAnsel on line %i: Qubits can only be initialized once.\n", line);
- return 0;
- }
- int strbeg = regmatches[1].rm_so;
- int strlen = regmatches[1].rm_eo - regmatches[1].rm_so;
- char tmp[strlen + 1];
- memcpy(tmp, chunk + strbeg, strlen);
- tmp[strlen] = 0;
- int nump = atoi(tmp);
- if (nump > QUBITS_MAX)
- {
- fprintf(stderr, "QAnsel on line %i: Initialized qubits cannot exceed %i.\n", line, QUBITS_MAX);
- return 0;
- }
- *qubitCount = nump;
- }
- else if (index == 1) //creg
- {
- if (*bitCount > 0)
- {
- fprintf(stderr, "QAnsel on line %i: Classical bits can only be initialized once.\n", line);
- return 0;
- }
- int strbeg = regmatches[1].rm_so;
- int strlen = regmatches[1].rm_eo - regmatches[1].rm_so;
- char tmp[strlen + 1];
- memcpy(tmp, chunk + strbeg, strlen);
- tmp[strlen] = 0;
- int nump = atoi(tmp);
- if (nump > QUBITS_MAX)
- {
- fprintf(stderr, "QAnsel on line %i: Initialized classical bits cannot exceed %i.\n", line, QUBITS_MAX);
- return 0;
- }
- *bitCount = nump;
- }
- else if (index == 2 || index == 3 || index == 4 || index == 5) //single qubit instructions
- {
- if (*qubitCount == 0)
- {
- fprintf(stderr, "QAnsel on line %i: Quantum bit instruction used prior to initialization.\n", line);
- return 0;
- }
- int rmp = 1;
- {
- int strbeg = regmatches[rmp].rm_so;
- int strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so;
- rmp++;
- char tmp[strlen + 1];
- memcpy(tmp, chunk + strbeg, strlen);
- tmp[strlen] = 0;
- if (strcmp(tmp, "rx") == 0) instr = QANSEL_INSTRUCTION_RX;
- else if (strcmp(tmp, "ry") == 0) instr = QANSEL_INSTRUCTION_RY;
- else if (strcmp(tmp, "rz") == 0) instr = QANSEL_INSTRUCTION_RZ;
- else if (strcmp(tmp, "u1") == 0) instr = QANSEL_INSTRUCTION_U1;
- else if (strcmp(tmp, "u2") == 0) instr = QANSEL_INSTRUCTION_U2;
- else if (strcmp(tmp, "u3") == 0) instr = QANSEL_INSTRUCTION_U3;
- else if (strcmp(tmp, "u") == 0) instr = QANSEL_INSTRUCTION_U3;
- else if (strcmp(tmp, "reset") == 0) instr = QANSEL_INSTRUCTION_RESET;
- else if (strcmp(tmp, "barrier") == 0) instr = QANSEL_INSTRUCTION_BARRIER;
- else if (strcmp(tmp, "born") == 0) instr = QANSEL_INSTRUCTION_BORN;
- else if (strcmp(tmp, "density") == 0) instr = QANSEL_INSTRUCTION_DENSITY;
- else if (strcmp(tmp, "print") == 0) instr = QANSEL_INSTRUCTION_PRINT;
- else if (strcmp(tmp, "not") == 0) instr = QANSEL_INSTRUCTION_X;
- else if (strcmp(tmp, "x") == 0) instr = QANSEL_INSTRUCTION_X;
- else if (strcmp(tmp, "y") == 0) instr = QANSEL_INSTRUCTION_Y;
- else if (strcmp(tmp, "z") == 0) instr = QANSEL_INSTRUCTION_Z;
- else if (strcmp(tmp, "h") == 0) instr = QANSEL_INSTRUCTION_H;
- else if (strcmp(tmp, "s") == 0) instr = QANSEL_INSTRUCTION_S;
- else if (strcmp(tmp, "t") == 0) instr = QANSEL_INSTRUCTION_T;
- }
- for (int i = 0; i < (index == 2 ? 0 : (index == 3 ? 1 : (index == 4 ? 2 : 3))); i++)
- {
- int strbeg = regmatches[rmp].rm_so;
- int strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so;
- rmp++;
- char tmp[strlen + 1];
- memcpy(tmp, chunk + strbeg, strlen);
- tmp[strlen] = 0;
- if (!qansel_parse_float(tmp, (i == 0 ? &d0 : (i == 1 ? &d1 : &d2))))
- {
- fprintf(stderr, "QAnsel on line %i: Invalid rotation value.\n", line);
- return 0;
- }
- }
- {
- int strbeg = regmatches[rmp].rm_so;
- int strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so;
- rmp++;
- if (strlen > 0)
- {
- strbeg = regmatches[rmp].rm_so;
- strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so;
- rmp++;
- char tmp[strlen + 1];
- memcpy(tmp, chunk + strbeg, strlen);
- tmp[strlen] = 0;
- a0 = atoi(tmp);
- if (a0 >= *qubitCount)
- {
- fprintf(stderr, "QAnsel on line %i: Index `%i` exceeds allocated quantum bits.\n", line, a0);
- return 0;
- }
- }
- else
- {
- a0 = 0x0F;
- if (instr == QANSEL_INSTRUCTION_DENSITY)
- {
- fprintf(stderr, "QAnsel on line %i: Density matrices can only be produced for individual qubits.\n", line, a0);
- return 0;
- }
- }
- }
- switch (index)
- {
- case 2:
- *binarySize += 2;
- *binary = realloc(*binary, (*binarySize));
- (*binary)[(*binarySize) - 2] = instr;
- (*binary)[(*binarySize) - 1] = a0;
- break;
- case 3:
- *binarySize += 2 + sizeof(float) * 1;
- *binary = realloc(*binary, (*binarySize));
- (*binary)[(*binarySize) - 2 - sizeof(float) * 1] = instr;
- (*binary)[(*binarySize) - 1 - sizeof(float) * 1] = a0;
- memcpy((*binary) + ((*binarySize) - sizeof(float)), &d0, sizeof(float));
- break;
- case 4:
- *binarySize += 2 + sizeof(float) * 2;
- *binary = realloc(*binary, (*binarySize));
- (*binary)[(*binarySize) - 2 - sizeof(float) * 2] = instr;
- (*binary)[(*binarySize) - 1 - sizeof(float) * 2] = a0;
- memcpy((*binary) + ((*binarySize) - sizeof(float) * 2), &d0, sizeof(float));
- memcpy((*binary) + ((*binarySize) - sizeof(float) * 1), &d1, sizeof(float));
- break;
- case 5:
- *binarySize += 2 + sizeof(float) * 3;
- *binary = realloc(*binary, (*binarySize));
- (*binary)[(*binarySize) - 2 - sizeof(float) * 3] = instr;
- (*binary)[(*binarySize) - 1 - sizeof(float) * 3] = a0;
- memcpy((*binary) + ((*binarySize) - sizeof(float) * 3), &d0, sizeof(float));
- memcpy((*binary) + ((*binarySize) - sizeof(float) * 2), &d1, sizeof(float));
- memcpy((*binary) + ((*binarySize) - sizeof(float) * 1), &d2, sizeof(float));
- break;
- }
- }
- else if (index == 6) //measure instruction
- {
- if (*qubitCount == 0)
- {
- fprintf(stderr, "QAnsel on line %i: Quantum bit instruction used prior to initialization.\n", line);
- return 0;
- }
- if (*bitCount == 0)
- {
- fprintf(stderr, "QAnsel on line %i: Classical bit instruction used prior to initialization.\n", line);
- return 0;
- }
- int rmp = 1;
- {
- int strbeg = regmatches[rmp].rm_so;
- int strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so;
- rmp++;
- if (strlen > 0)
- {
- strbeg = regmatches[rmp].rm_so;
- strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so;
- rmp++;
- char tmp[strlen + 1];
- memcpy(tmp, chunk + strbeg, strlen);
- tmp[strlen] = 0;
- a0 = atoi(tmp);
- if (a0 >= *qubitCount)
- {
- fprintf(stderr, "QAnsel on line %i: Index `%i` exceeds allocated quantum bits.\n", line, a0);
- return 0;
- }
- }
- else
- {
- a0 = 0x0F;
- }
- }
- {
- int strbeg = regmatches[rmp].rm_so;
- int strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so;
- rmp++;
- if (strlen > 0)
- {
- strbeg = regmatches[rmp].rm_so;
- strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so;
- rmp++;
- char tmp[strlen + 1];
- memcpy(tmp, chunk + strbeg, strlen);
- tmp[strlen] = 0;
- a1 = atoi(tmp);
- if (a1 >= *bitCount)
- {
- fprintf(stderr, "QAnsel on line %i: Index `%i` exceeds allocated classical bits.\n", line, a1);
- return 0;
- }
- a1 += 0x10;
- }
- else
- {
- a1 = 0x1F;
- }
- }
- *binarySize += 3;
- *binary = realloc(*binary, (*binarySize));
- (*binary)[(*binarySize) - 3] = QANSEL_INSTRUCTION_MEASURE;
- (*binary)[(*binarySize) - 2] = a0;
- (*binary)[(*binarySize) - 1] = a1;
- }
- else if (index == 7) //classical bit instructions
- {
- if (*bitCount == 0)
- {
- fprintf(stderr, "QAnsel on line %i: Classical bit instruction used prior to initialization.\n", line);
- return 0;
- }
- int rmp = 1;
- {
- int strbeg = regmatches[rmp].rm_so;
- int strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so;
- rmp++;
- char tmp[strlen + 1];
- memcpy(tmp, chunk + strbeg, strlen);
- tmp[strlen] = 0;
- if (strcmp(tmp, "sample") == 0) instr = QANSEL_INSTRUCTION_SAMPLE;
- else if (strcmp(tmp, "reset") == 0) instr = QANSEL_INSTRUCTION_RESET;
- else if (strcmp(tmp, "print") == 0) instr = QANSEL_INSTRUCTION_PRINT;
- }
- {
- int strbeg = regmatches[rmp].rm_so;
- int strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so;
- rmp++;
- if (strlen > 0)
- {
- strbeg = regmatches[rmp].rm_so;
- strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so;
- rmp++;
- char tmp[strlen + 1];
- memcpy(tmp, chunk + strbeg, strlen);
- tmp[strlen] = 0;
- a0 = atoi(tmp);
- if (a0 >= *bitCount)
- {
- fprintf(stderr, "QAnsel on line %i: Index `%i` exceeds allocated classical bits.\n", line, a0);
- return 0;
- }
- a0 += 0x10;
- }
- else
- {
- a0 = 0x1F;
- }
- }
- *binarySize += 2;
- *binary = realloc(*binary, (*binarySize));
- (*binary)[(*binarySize) - 2] = instr;
- (*binary)[(*binarySize) - 1] = a0;
- }
- else if (index == 8 || index == 9) //double qubit instructions
- {
- if (*qubitCount == 0)
- {
- fprintf(stderr, "QAnsel on line %i: Quantum bit instruction used prior to initialization.\n", line);
- return 0;
- }
- int rmp = 1;
- {
- int strbeg = regmatches[rmp].rm_so;
- int strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so;
- rmp++;
- char tmp[strlen + 1];
- memcpy(tmp, chunk + strbeg, strlen);
- tmp[strlen] = 0;
- if (strcmp(tmp, "cx") == 0) instr = QANSEL_INSTRUCTION_CX;
- if (strcmp(tmp, "cnot") == 0) instr = QANSEL_INSTRUCTION_CX;
- if (strcmp(tmp, "ccnot") == 0) instr = QANSEL_INSTRUCTION_CCX;
- if (strcmp(tmp, "ccx") == 0) instr = QANSEL_INSTRUCTION_CCX;
- else if (strcmp(tmp, "toffoli") == 0) instr = QANSEL_INSTRUCTION_CCX;
- else if (strcmp(tmp, "cswap") == 0) instr = QANSEL_INSTRUCTION_CSWAP;
- else if (strcmp(tmp, "fredkin") == 0) instr = QANSEL_INSTRUCTION_CSWAP;
- }
- for (int i = 0; i < (index == 8 ? 2 : 3); i++)
- {
- int strbeg = regmatches[rmp].rm_so;
- int strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so;
- rmp++;
- char tmp[strlen + 1];
- memcpy(tmp, chunk + strbeg, strlen);
- tmp[strlen] = 0;
- int tmpi = atoi(tmp);
- if (tmpi >= *qubitCount)
- {
- fprintf(stderr, "QAnsel on line %i: Index `%i` exceeds allocated quantum bits.\n", line, tmpi);
- return 0;
- }
- switch (i)
- {
- case 0: a0 = tmpi; break;
- case 1: a1 = tmpi; break;
- case 2: a2 = tmpi; break;
- }
- }
- if (index == 8)
- {
- *binarySize += 3;
- *binary = realloc(*binary, (*binarySize));
- (*binary)[(*binarySize) - 3] = instr;
- (*binary)[(*binarySize) - 2] = a0;
- (*binary)[(*binarySize) - 1] = a1;
- }
- else
- {
- *binarySize += 4;
- *binary = realloc(*binary, (*binarySize));
- (*binary)[(*binarySize) - 4] = instr;
- (*binary)[(*binarySize) - 3] = a0;
- (*binary)[(*binarySize) - 2] = a1;
- (*binary)[(*binarySize) - 1] = a2;
- }
- }
- else if (index == 10) //if instructions
+ if (optimizationSettings < QANSEL_MODE_BARE || optimizationSettings > QANSEL_MODE_METAL_THREADED)
{
- if (*bitCount == 0)
- {
- fprintf(stderr, "QAnsel on line %i: Classical bit instruction used prior to initialization.\n", line);
- return 0;
- }
- int rmp = 1;
- {
- int strbeg = regmatches[rmp].rm_so;
- int strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so;
- rmp++;
- if (strlen > 0)
- {
- strbeg = regmatches[rmp].rm_so;
- strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so;
- rmp++;
- char tmp[strlen + 1];
- memcpy(tmp, chunk + strbeg, strlen);
- tmp[strlen] = 0;
- a0 = atoi(tmp);
- if (a0 >= *bitCount)
- {
- fprintf(stderr, "QAnsel on line %i: Index `%i` exceeds allocated classical bits.\n", line, a0);
- return 0;
- }
- a0 += 0x10;
- }
- else
- {
- a0 = 0x1F;
- }
- }
- {
- int strbeg = regmatches[rmp].rm_so;
- int strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so;
- rmp++;
- char tmp[strlen + 1];
- memcpy(tmp, chunk + strbeg, strlen);
- tmp[strlen] = 0;
- if (strlen == 0)
- {
- strbeg = regmatches[rmp].rm_so;
- strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so;
- rmp++;
- char tmp[strlen + 1];
- memcpy(tmp, chunk + strbeg, strlen);
- tmp[strlen] = 0;
- if (strcmp(tmp, "==") == 0) instr = QANSEL_INSTRUCTION_IF_E;
- else if (strcmp(tmp, "!=") == 0) instr = QANSEL_INSTRUCTION_IF_NE;
- else if (strcmp(tmp, "<>") == 0) instr = QANSEL_INSTRUCTION_IF_NE;
- else if (strcmp(tmp, ">=") == 0) instr = QANSEL_INSTRUCTION_IF_GE;
- else if (strcmp(tmp, "<=") == 0) instr = QANSEL_INSTRUCTION_IF_LE;
- else if (strcmp(tmp, ">") == 0) instr = QANSEL_INSTRUCTION_IF_G;
- else if (strcmp(tmp, "<") == 0) instr = QANSEL_INSTRUCTION_IF_L;
- }
- else
- {
- if (strcmp(tmp, "==") == 0) instr = QANSEL_INSTRUCTION_IF_E;
- else if (strcmp(tmp, "!=") == 0) instr = QANSEL_INSTRUCTION_IF_NE;
- else if (strcmp(tmp, "<>") == 0) instr = QANSEL_INSTRUCTION_IF_NE;
- else if (strcmp(tmp, ">=") == 0) instr = QANSEL_INSTRUCTION_IF_GE;
- else if (strcmp(tmp, "<=") == 0) instr = QANSEL_INSTRUCTION_IF_LE;
- else if (strcmp(tmp, ">") == 0) instr = QANSEL_INSTRUCTION_IF_G;
- else if (strcmp(tmp, "<") == 0) instr = QANSEL_INSTRUCTION_IF_L;
- }
- }
- {
- int strbeg = regmatches[rmp].rm_so;
- int strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so;
- rmp++;
- char tmp[strlen + 1];
- memcpy(tmp, chunk + strbeg, strlen);
- tmp[strlen] = 0;
- s0 = (unsigned short)atoi(tmp);
- }
- //printf("%s(%02x,%i)\n", qansel_instruction_to_string(instr), a0, s0);
- *binarySize += 2 + sizeof(unsigned short);
- *binary = realloc(*binary, (*binarySize));
- (*binary)[(*binarySize) - 2 - sizeof(unsigned short)] = instr;
- (*binary)[(*binarySize) - 1 - sizeof(unsigned short)] = a0;
- memcpy((*binary) + ((*binarySize) - sizeof(unsigned short)), &s0, sizeof(unsigned short));
+ fprintf(stderr, "QAnsel: Invalid optimization settings.\n");
+ exit(1);
}
- else if (index == 11) //floating point settings
+ QANSEL_MODE = optimizationSettings;
+
+ if (maximumQubitSettings <= 0 || maximumQubitSettings > QANSEL_QUBITS_MAX)
{
- int rmp = 1;
- {
- int strbeg = regmatches[rmp].rm_so;
- int strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so;
- rmp++;
- char tmp[strlen + 1];
- memcpy(tmp, chunk + strbeg, strlen);
- tmp[strlen] = 0;
- if (strcmp(tmp, "hvar") == 0) instr = QANSEL_INSTRUCTION_HVAR;
- }
- {
- int strbeg = regmatches[rmp].rm_so;
- int strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so;
- rmp++;
- char tmp[strlen + 1];
- memcpy(tmp, chunk + strbeg, strlen);
- tmp[strlen] = 0;
- if (!qansel_parse_float(tmp, &d0))
- {
- fprintf(stderr, "QAnsel on line %i: Syntax error.\n", line);
- return 0;
- }
- }
- *binarySize += 1 + sizeof(float);
- *binary = realloc(*binary, (*binarySize));
- (*binary)[(*binarySize) - 1 - sizeof(float)] = instr;
- memcpy((*binary) + ((*binarySize) - sizeof(float)), &d0, sizeof(float));
+ fprintf(stderr, "QAnsel: Invalid limit for quantum bits.\n");
+ exit(1);
}
- else if (index == 12) //lone instructions
+ QANSEL_QUBIT_LIMIT = maximumQubitSettings;
+
+ if (hardwarerngSetting == 1)
{
- int rmp = 1;
+ QANSEL_RANDOM_FILE = fopen("/dev/TrueRNG0", "r");
+ if (QANSEL_RANDOM_FILE == NULL)
{
- int strbeg = regmatches[rmp].rm_so;
- int strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so;
- rmp++;
- char tmp[strlen + 1];
- memcpy(tmp, chunk + strbeg, strlen);
- tmp[strlen] = 0;
- if (strcmp(tmp, "rand") == 0) instr = QANSEL_INSTRUCTION_RAND;
- else if (strcmp(tmp, "exit") == 0) instr = QANSEL_INSTRUCTION_EXIT;
+ fprintf(stderr, "QAnsel: No supported hardware random number generator found.\n");
+ exit(1);
}
- *binarySize += 1;
- *binary = realloc(*binary, (*binarySize));
- (*binary)[(*binarySize) - 1] = instr;
}
- return 1;
-}
-
-int qansel_process_chunks(char** chunks, int* associatedLines, int count)
-{
- unsigned char* binary = malloc(0);
- int binarySize = 0;
- int qubitCount = 0;
- int bitCount = 0;
- char errbuf[100];
- regex_t regex;
- regmatch_t regmatches[10];
- const char regexes[][1024] =
+
+ if (QANSEL_MODE == QANSEL_MODE_METAL || QANSEL_MODE == QANSEL_MODE_METAL_THREADED)
{
- "^\\s*qreg\\s*q\\s*\\[\\s*([0-9][0-9]*)\\s*\\]\\s*$",
- "^\\s*creg\\s*c\\s*\\[\\s*([0-9][0-9]*)\\s*\\]\\s*$",
- "^\\s*(x|y|z|h|s|t|reset|barrier|born|density|print)\\s*q\\s*(\\[\\s*([0-9][0-9]*)\\s*\\]\\s*|)$",
- "^\\s*(rx|ry|rz|u1)\\(\\s*([-/0-9PI.]*)\\s*\\)\\s*q\\s*(\\[\\s*([0-9][0-9]*)\\s*\\]\\s*|)$",
- "^\\s*(u2)\\(\\s*([-/0-9PI.]*)\\s*,\\s*([-/0-9PI.]*)\\s*\\)\\s*q\\s*(\\[\\s*([0-9][0-9]*)\\s*\\]\\s*|)$",
- "^\\s*(u|u3)\\(\\s*([-/0-9PI.]*)\\s*,\\s*([-/0-9PI.]*)\\s*,\\s*([-/0-9PI.]*)\\s*\\)\\s*q\\s*(\\[\\s*([0-9][0-9]*)\\s*\\]\\s*|)$",
- "^\\s*measure\\s*q\\s*(\\[\\s*([0-9][0-9]*)\\s*\\]\\s*)\\s*->\\s*c\\c*(\\[\\s*([0-9][0-9]*)\\s*\\]\\s*)$",
- //"^\\s*measure\\s*q\\s*(\\[\\s*([0-9][0-9]*)\\s*\\]\\s*|)\\s*->\\s*c\\c*(\\[\\s*([0-9][0-9]*)\\s*\\]\\s*|)$",
- "^\\s*(sample|reset|print)\\s*c\\s*(\\[\\s*([0-9][0-9]*)\\s*\\]\\s*|)$",
- "^\\s*(cx|cnot|swap)\\s*q\\s*\\[\\s*([0-9][0-9]*)\\s*\\]\\s*,\\s*q\\s*\\[\\s*([0-9]*)\\s*\\]\\s*$",
- "^\\s*(ccx|toffoli|cswap|fredkin)\\s*q\\s*\\[\\s*([0-9][0-9]*)\\s*\\]\\s*,\\s*q\\s*\\[\\s*([0-9][0-9]*)\\s*\\]\\s*,\\s*q\\s*\\[\\s*([0-9][0-9]*)\\s*\\]\\s*$",
- "^\\s*if\\s*\\(\\s*c\\s*(\\[\\s*([0-9][0-9]*)\\s*\\]|)\\s*(==|!=|<>|>=|<=|>|<)\\s*([0-9][0-9]*)\\s*\\).*\\s*$",
- "^\\s*(hvar)\\s*([-/0-9PI.]*)\\s*$",
- "^\\s*(rand|exit)\\s*$",
- };
- int ret, status = 0, found;
- for (int i = 0; i < count; i++)
- {
- found = 0;
- for (int j = 0; j < sizeof(regexes) / sizeof(regexes[0]); j++)
+ if (!cpx_mtx_begin())
{
- if (regcomp(®ex, regexes[j], REG_EXTENDED | REG_ICASE))
- {
- printf("QAnsel: Regex fatal error.\n");
- exit(1);
- }
- ret = regexec(®ex, chunks[i], 10, regmatches, 0);
- regfree(®ex);
- if (!ret)
- {
- found = 1;
- status = qansel_process_chunk(j, chunks[i], associatedLines[i], regmatches, &qubitCount, &bitCount, &binary, &binarySize);
- break;
- }
- else if (ret == REG_NOMATCH) {}
- else
- {
- regerror(ret, ®ex, errbuf, sizeof(errbuf));
- fprintf(stderr, "QAnsel: %s.\n", errbuf);
- exit(1);
- }
- }
- if (!status) break;
- if (!found)
- {
- fprintf(stderr, "QAnsel on line %i: Invalid syntax.\n", associatedLines[i]);
- return 0;
+ fprintf(stderr, "QAnsel: No supported hardware accelerator found.\n");
+ exit(1);
}
}
- qansel_execute(binary, binarySize);
- free(binary);
-}
-
-void main(int argc, char** argv)
-{
- MODE = MODE_METAL_THREADED;
- unsigned char err = cpx_mtx_begin();
- if (err == 0 && (MODE == MODE_METAL_THREADED || MODE == MODE_METAL))
- {
- MODE = MODE == MODE_METAL_THREADED ? MODE_THREADED : MODE_BARE;
- }
- RANDOM_FILE = fopen("/dev/TrueRNG0", "r");
- if (!RANDOM_FILE) RANDOM_FILE = fopen("/dev/random", "r");
-
char* script = malloc(0);
size_t scriptSize = 0;
int c;
script = realloc(script, scriptSize + 1);
script[scriptSize++] = 0;
- char** chunks;
- int* chunksAssociatedLines;
- int chunksCount;
- qansel_read_script(script, &chunks, &chunksAssociatedLines, &chunksCount);
- qansel_process_chunks(chunks, chunksAssociatedLines, chunksCount);
- for (int i = 0; i < chunksCount; i++) free(chunks[i]);
- free(chunks);
- free(chunksAssociatedLines);
- free(script);
-
- fclose(RANDOM_FILE);
+ unsigned char* bytecode;
+ int bytecodeSize;
+ if (qanselBuildFromSource(script, &bytecode, &bytecodeSize))
+ {
+ qanselExecuteBytecode(bytecode, bytecodeSize);
+ }
+ free(bytecode);
- if (MODE_METAL || MODE_METAL_THREADED) cpx_mtx_clean();
+ if (QANSEL_RANDOM_FILE != NULL) fclose(QANSEL_RANDOM_FILE);
+ if (QANSEL_MODE == QANSEL_MODE_METAL || QANSEL_MODE == QANSEL_MODE_METAL_THREADED) cpx_mtx_clean();
return;
}
\ No newline at end of file
--- /dev/null
+typedef struct
+{
+ char n[128];
+ unsigned char q0, q1, q2;
+ float arg0, arg1, arg2;
+} QInstr;
+
+const char* qansel_instruction_to_string(unsigned char instr)
+{
+ switch (instr)
+ {
+ case QANSEL_INSTRUCTION_X: return "QANSEL_INSTRUCTION_X";
+ case QANSEL_INSTRUCTION_Y: return "QANSEL_INSTRUCTION_Y";
+ case QANSEL_INSTRUCTION_Z: return "QANSEL_INSTRUCTION_Z";
+ case QANSEL_INSTRUCTION_H: return "QANSEL_INSTRUCTION_H";
+ case QANSEL_INSTRUCTION_S: return "QANSEL_INSTRUCTION_S";
+ case QANSEL_INSTRUCTION_T: return "QANSEL_INSTRUCTION_T";
+ case QANSEL_INSTRUCTION_RX: return "QANSEL_INSTRUCTION_RX";
+ case QANSEL_INSTRUCTION_RY: return "QANSEL_INSTRUCTION_RY";
+ case QANSEL_INSTRUCTION_RZ: return "QANSEL_INSTRUCTION_RZ";
+ case QANSEL_INSTRUCTION_U1: return "QANSEL_INSTRUCTION_U1";
+ case QANSEL_INSTRUCTION_U2: return "QANSEL_INSTRUCTION_U2";
+ case QANSEL_INSTRUCTION_U3: return "QANSEL_INSTRUCTION_U3";
+ case QANSEL_INSTRUCTION_CX: return "QANSEL_INSTRUCTION_CX";
+ case QANSEL_INSTRUCTION_SWAP: return "QANSEL_INSTRUCTION_SWAP";
+ case QANSEL_INSTRUCTION_CCX: return "QANSEL_INSTRUCTION_CCX";
+ case QANSEL_INSTRUCTION_CSWAP: return "QANSEL_INSTRUCTION_CSWAP";
+ case QANSEL_INSTRUCTION_MEASURE: return "QANSEL_INSTRUCTION_MEASURE";
+ case QANSEL_INSTRUCTION_SAMPLE: return "QANSEL_INSTRUCTION_SAMPLE";
+ case QANSEL_INSTRUCTION_DENSITY: return "QANSEL_INSTRUCTION_DENSITY";
+ case QANSEL_INSTRUCTION_BORN: return "QANSEL_INSTRUCTION_BORN";
+ case QANSEL_INSTRUCTION_IF_E: return "QANSEL_INSTRUCTION_JUMP_E";
+ case QANSEL_INSTRUCTION_IF_NE: return "QANSEL_INSTRUCTION_JUMP_NE";
+ case QANSEL_INSTRUCTION_IF_G: return "QANSEL_INSTRUCTION_JUMP_G";
+ case QANSEL_INSTRUCTION_IF_GE: return "QANSEL_INSTRUCTION_JUMP_GE";
+ case QANSEL_INSTRUCTION_IF_L: return "QANSEL_INSTRUCTION_JUMP_L";
+ case QANSEL_INSTRUCTION_IF_LE: return "QANSEL_INSTRUCTION_JUMP_LE";
+ case QANSEL_INSTRUCTION_RAND: return "QANSEL_INSTRUCTION_RAND";
+ case QANSEL_INSTRUCTION_HVAR: return "QANSEL_INSTRUCTION_HVAR";
+ case QANSEL_INSTRUCTION_RESET: return "QANSEL_INSTRUCTION_RESET";
+ case QANSEL_INSTRUCTION_PRINT: return "QANSEL_INSTRUCTION_PRINT";
+ case QANSEL_INSTRUCTION_BARRIER: return "QANSEL_INSTRUCTION_BARRIER";
+ case QANSEL_INSTRUCTION_EXIT: return "QANSEL_INSTRUCTION_EXIT";
+ }
+ return "Unknown";
+}
+
+void qansel_rand_init()
+{
+ srand(time(NULL));
+}
+
+float qansel_rand_s(float s)
+{
+ unsigned int tmp;
+ memcpy(&tmp, &s, sizeof(unsigned int));
+ srand(tmp);
+}
+float qansel_rand_h()
+{
+ return ((float)rand()) / ((float)RAND_MAX);
+}
+float qansel_rand_t()
+{
+ if (QANSEL_RANDOM_FILE)
+ {
+ unsigned int num = 0;
+ for (unsigned char i = 0; i < 4; i++)
+ {
+ num = (num << 8) | fgetc(QANSEL_RANDOM_FILE);
+ }
+ return ((float)num) / ((float)UINT32_MAX);
+ }
+ else
+ {
+ return qansel_rand_h();
+ }
+}
+
+float qansel_rand()
+{
+ return QANSEL_HIDDEN_VARIABLE ? qansel_rand_h() : qansel_rand_t();
+}
+
+void qansel_cnot(cpx_mtx_t* stateVector, unsigned char qubitCount, unsigned char bitA, unsigned char bitB)
+{
+ if (bitA >= qubitCount || bitB >= qubitCount) return;
+ unsigned int retLen = (unsigned int)pow(2, qubitCount);
+ cpx_mtx_t ret;
+ cpx_mtx_init(&ret, 1, retLen);
+ cpx_t n;
+ for (unsigned int i = 0; i < retLen; i++)
+ {
+ unsigned char bitAVal = (i >> bitA) & 1;
+ unsigned char bitBVal = (i >> bitB) & 1;
+ unsigned char bitBNew = bitAVal ? !bitBVal : bitBVal;
+ unsigned int j = (i & ~(1 << bitB)) | (bitBNew << bitB);
+ cpx_mtx_get(stateVector, 0, i, &n);
+ cpx_mtx_set(&ret, 0, j, &n);
+ }
+ cpx_mtx_free(stateVector);
+ stateVector->ptr = ret.ptr;
+ stateVector->rows = ret.rows;
+ stateVector->cols = ret.cols;
+}
+
+void qansel_swap(cpx_mtx_t* stateVector, unsigned char qubitCount, unsigned char bitA, unsigned char bitB)
+{
+ if (bitA >= qubitCount || bitB >= qubitCount) return;
+ unsigned int retLen = (unsigned int)pow(2, qubitCount);
+ cpx_mtx_t ret;
+ cpx_mtx_init(&ret, 1, retLen);
+ cpx_t n;
+ for (unsigned int i = 0; i < retLen; i++)
+ {
+ unsigned char bitAVal = (i >> bitA) & 1;
+ unsigned char bitBVal = (i >> bitB) & 1;
+ unsigned char bitANew = bitBVal;
+ unsigned char bitBNew = bitAVal;
+ unsigned int j = (i & ~((1 << bitA) | (1 << bitB))) | ((bitANew << bitA) | (bitBNew << bitB));
+ cpx_mtx_get(stateVector, 0, i, &n);
+ cpx_mtx_set(&ret, 0, j, &n);
+ }
+ cpx_mtx_free(stateVector);
+ stateVector->ptr = ret.ptr;
+ stateVector->rows = ret.rows;
+ stateVector->cols = ret.cols;
+}
+
+void qansel_fredkin(cpx_mtx_t* stateVector, unsigned char qubitCount, unsigned char bitA, unsigned char bitB, unsigned char bitC)
+{
+ if (bitA >= qubitCount || bitB >= qubitCount) return;
+ unsigned int retLen = (unsigned int)pow(2, qubitCount);
+ cpx_mtx_t ret;
+ cpx_mtx_init(&ret, 1, retLen);
+ cpx_t n;
+ for (unsigned int i = 0; i < retLen; i++)
+ {
+ unsigned char bitAVal = (i >> bitA) & 1;
+ unsigned char bitBVal = (i >> bitB) & 1;
+ unsigned char bitCVal = (i >> bitC) & 1;
+ unsigned char bitBNew = bitAVal ? bitCVal : bitBVal;
+ unsigned char bitCNew = bitAVal ? bitBVal : bitCVal;
+ unsigned int j = (i & ~((1 << bitB) | (1 << bitC))) | ((bitBNew << bitB) | (bitCNew << bitC));
+ cpx_mtx_get(stateVector, 0, i, &n);
+ cpx_mtx_set(&ret, 0, j, &n);
+ }
+ cpx_mtx_free(stateVector);
+ stateVector->ptr = ret.ptr;
+ stateVector->rows = ret.rows;
+ stateVector->cols = ret.cols;
+}
+
+
+void qansel_toffoli(cpx_mtx_t* stateVector, unsigned char qubitCount, unsigned char bitA, unsigned char bitB, unsigned char bitC)
+{
+ if (bitA >= qubitCount || bitB >= qubitCount) return;
+ unsigned int retLen = (unsigned int)pow(2, qubitCount);
+ cpx_mtx_t ret;
+ cpx_mtx_init(&ret, 1, retLen);
+ cpx_t n;
+ for (unsigned int i = 0; i < retLen; i++)
+ {
+ unsigned char bitAVal = (i >> bitA) & 1;
+ unsigned char bitBVal = (i >> bitB) & 1;
+ unsigned char bitCVal = (i >> bitC) & 1;
+ unsigned char bitCNew = (bitAVal && bitBVal) ? !bitCVal : bitCVal;
+ unsigned int j = (i & ~(1 << bitC)) | (bitCNew << bitC);
+ cpx_mtx_get(stateVector, 0, i, &n);
+ cpx_mtx_set(&ret, 0, j, &n);
+ }
+ cpx_mtx_free(stateVector);
+ stateVector->ptr = ret.ptr;
+ stateVector->rows = ret.rows;
+ stateVector->cols = ret.cols;
+}
+
+float* qansel_unitary(float theta, float phi, float lambda)
+{
+ cpx_mtx_t m;
+ cpx_t a, b, c, d;
+ a.real = cos(theta/2.0);
+ a.imaginary = 0;
+ b.real = -cos(lambda) * sin(theta/2.0);
+ b.imaginary = sin(lambda) * sin(theta/2.0);
+ c.real = cos(phi) * sin(theta/2.0);
+ c.imaginary = sin(phi) * sin(theta/2.0);
+ d.real = cos(phi + lambda) * cos(theta/2.0);
+ d.imaginary = sin(phi + lambda) * cos(theta/2.0);
+ cpx_mtx_init(&m, 2, 2);
+ cpx_mtx_set(&m, 0, 0, &a);
+ cpx_mtx_set(&m, 0, 1, &b);
+ cpx_mtx_set(&m, 1, 0, &c);
+ cpx_mtx_set(&m, 1, 1, &d);
+ return m.ptr;
+}
+
+void qansel_instruction
+(
+ cpx_mtx_t* stateVector,
+ int qubitCount,
+ unsigned char instr,
+ unsigned char index,
+ float arg0,
+ float arg1,
+ float arg2
+)
+{
+ cpx_mtx_t tmp;
+ cpx_mtx_t gate;
+ gate.rows = 2;
+ gate.cols = 2;
+ float* gate_ptr;
+ switch (instr)
+ {
+ case QANSEL_INSTRUCTION_H: gate_ptr = Hadamard; break;
+ case QANSEL_INSTRUCTION_X: gate_ptr = PauliX; break;
+ case QANSEL_INSTRUCTION_Y: gate_ptr = PauliY; break;
+ case QANSEL_INSTRUCTION_Z: gate_ptr = PauliZ; break;
+ case QANSEL_INSTRUCTION_S: gate_ptr = PhaseS; break;
+ case QANSEL_INSTRUCTION_T: gate_ptr = PhaseT; break;
+ case QANSEL_INSTRUCTION_RX:
+ case QANSEL_INSTRUCTION_RY:
+ case QANSEL_INSTRUCTION_RZ:
+ case QANSEL_INSTRUCTION_U1:
+ case QANSEL_INSTRUCTION_U2:
+ case QANSEL_INSTRUCTION_U3:
+ gate_ptr = qansel_unitary(arg0, arg1, arg2);
+ break;
+ default: gate_ptr = Identity; break;
+ }
+
+ cpx_t n;
+ cpx_mtx_t filter;
+ cpx_mtx_init(&filter, 2, 2);
+ unsigned char qubit = qubitCount - (index) - 1;
+ if (qubit == 0)
+ {
+ memcpy(filter.ptr, gate_ptr, 8 * sizeof(float));
+ }
+ else
+ {
+ memcpy(filter.ptr, Identity, 8 * sizeof(float));
+ }
+
+ for (unsigned char i = 1; i < qubitCount; i++)
+ {
+ if (index != 0x0F)
+ {
+ if (qubit == i)
+ {
+ gate.ptr = gate_ptr;
+ }
+ else
+ {
+ gate.ptr = Identity;
+ }
+ }
+ else
+ {
+ gate.ptr = gate_ptr;
+ }
+
+ tmp.rows = filter.rows * gate.rows;
+ tmp.cols = filter.cols * gate.cols;
+ tmp.ptr = malloc(tmp.rows * (tmp.cols * 2) * sizeof(float));
+
+ #ifdef SPEED_TEST
+ printf("(%ix%i);(%ix%i) (knk)\n", tmp.rows, tmp.cols, gate.rows, gate.cols);
+ unsigned long int us1, us2;
+ us1 = get_time();
+ cpx_mtx_knk_metal(tmp.ptr, filter.ptr, gate.ptr, filter.rows, filter.cols, gate.rows, gate.cols);
+ us2 = get_time();
+ printf("\tMetal: %lu\n", us2 - us1);
+ us1 = get_time();
+ cpx_mtx_knk_metal_2x2(tmp.ptr, filter.ptr, gate.ptr, filter.rows, filter.cols, gate.rows, gate.cols);
+ us2 = get_time();
+ printf("\tMetal2x2: %lu\n", us2 - us1);
+ us1 = get_time();
+ cpx_mtx_knk_threads(tmp.ptr, filter.ptr, gate.ptr, filter.rows, filter.cols, gate.rows, gate.cols);
+ us2 = get_time();
+ printf("\tThreads: %lu\n", us2 - us1);
+ us1 = get_time();
+ cpx_mtx_knk_threads_2x2(tmp.ptr, filter.ptr, gate.ptr, filter.rows, filter.cols, gate.rows, gate.cols);
+ us2 = get_time();
+ printf("\tThreads2x2: %lu\n", us2 - us1);
+ us1 = get_time();
+ cpx_mtx_knk(tmp.ptr, filter.ptr, gate.ptr, filter.rows, filter.cols, gate.rows, gate.cols);
+ us2 = get_time();
+ printf("\tBare: %lu\n", us2 - us1);
+ us1 = get_time();
+ cpx_mtx_knk_2x2(tmp.ptr, filter.ptr, gate.ptr, filter.rows, filter.cols, gate.rows, gate.cols);
+ us2 = get_time();
+ printf("\tBare2x2: %lu\n", us2 - us1);
+
+ //us1 = get_time();
+ //cpx_mtx_knk(tmp.ptr, filter.ptr, gate.ptr, filter.rows, filter.cols, gate.rows, gate.cols);
+ //us2 = get_time();
+ //printf("\tTranspose: %lu\n", us2 - us1);
+ #else
+ if (QANSEL_MODE == QANSEL_MODE_METAL && tmp.cols >= 64)
+ {
+ cpx_mtx_knk_metal_2x2(tmp.ptr, filter.ptr, gate.ptr, filter.rows, filter.cols, gate.rows, gate.cols);
+ }
+ else if ((QANSEL_MODE == QANSEL_MODE_THREADED || QANSEL_MODE == QANSEL_MODE_METAL_THREADED) && tmp.cols >= 64)
+ {
+ cpx_mtx_knk_threads_2x2(tmp.ptr, filter.ptr, gate.ptr, filter.rows, filter.cols, gate.rows, gate.cols);
+ }
+ else
+ {
+ cpx_mtx_knk_2x2(tmp.ptr, filter.ptr, gate.ptr, filter.rows, filter.cols, gate.rows, gate.cols);
+ }
+ #endif
+
+ free(filter.ptr);
+ filter.ptr = tmp.ptr;
+ filter.rows = tmp.rows;
+ filter.cols = tmp.cols;
+ }
+
+ cpx_mtx_init(&tmp, stateVector->rows, stateVector->cols);
+
+ #ifdef SPEED_TEST
+ printf("%ix%i (dot)\n", tmp.rows, tmp.cols);
+ unsigned long int us1, us2;
+ us1 = get_time();
+ cpx_mtx_dot_metal(tmp.ptr, stateVector->ptr, filter.ptr, stateVector->rows, stateVector->cols, filter.rows, filter.cols);
+ us2 = get_time();
+ printf("\tMetal: %lu\n", us2 - us1);
+ us1 = get_time();
+ cpx_mtx_dot_threads(tmp.ptr, stateVector->ptr, filter.ptr, stateVector->rows, stateVector->cols, filter.rows, filter.cols);
+ us2 = get_time();
+ printf("\tThreads: %lu\n", us2 - us1);
+ us1 = get_time();
+ cpx_mtx_dot(tmp.ptr, stateVector->ptr, filter.ptr, stateVector->rows, stateVector->cols, filter.rows, filter.cols);
+ us2 = get_time();
+ printf("\tBare: %lu\n", us2 - us1);
+ #else
+ if ((QANSEL_MODE == QANSEL_MODE_METAL || QANSEL_MODE == QANSEL_MODE_METAL_THREADED) && tmp.cols >= 64)
+ {
+ cpx_mtx_dot_metal(tmp.ptr, stateVector->ptr, filter.ptr, stateVector->rows, stateVector->cols, filter.rows, filter.cols);
+ }
+ else if (QANSEL_MODE == QANSEL_MODE_THREADED && tmp.cols >= 64)
+ {
+ cpx_mtx_dot_threads(tmp.ptr, stateVector->ptr, filter.ptr, stateVector->rows, stateVector->cols, filter.rows, filter.cols);
+ }
+ else
+ {
+ cpx_mtx_dot(tmp.ptr, stateVector->ptr, filter.ptr, stateVector->rows, stateVector->cols, filter.rows, filter.cols);
+ }
+ #endif
+ free(stateVector->ptr);
+ stateVector->ptr = tmp.ptr;
+ free(filter.ptr);
+ if (instr == QANSEL_INSTRUCTION_U1 || instr == QANSEL_INSTRUCTION_U2 || instr == QANSEL_INSTRUCTION_U3)
+ {
+ free(gate_ptr);
+ }
+}
+
+unsigned char qansel_measure(cpx_mtx_t* stateVector, unsigned char qubitCount, unsigned char qubit)
+{
+ unsigned int qubitCountPow2 = (unsigned int)pow(2, qubitCount);
+ cpx_t n;
+ float prob0 = 0;
+ for (unsigned int i = 0; i < qubitCountPow2; i++)
+ {
+ unsigned char bit = (i >> qubit) & 1;
+ cpx_mtx_get(stateVector, 0, i, &n);
+ if (bit == 0) prob0 += cpx_magsqr(&n);
+ }
+
+ float r = qansel_rand();
+ unsigned char newBit = r < prob0 ? 0 : 1;
+ float probTot = 0;
+ for (unsigned int i = 0; i < qubitCountPow2; i++)
+ {
+ unsigned char bit = (i >> qubit) & 1;
+ cpx_mtx_get(stateVector, 0, i, &n);
+ if (bit != newBit)
+ {
+ n.real = 0;
+ n.imaginary = 0;
+ }
+ else
+ {
+ probTot += cpx_magsqr(&n);
+ }
+ cpx_mtx_set(stateVector, 0, i, &n);
+ }
+
+ float multiplier = sqrt(1 / probTot);
+ for (unsigned int i = 0; i < qubitCountPow2; i++)
+ {
+ unsigned char bit = (i >> qubit) & 1;
+ cpx_mtx_get(stateVector, 0, i, &n);
+ if (bit == newBit)
+ {
+ n.real *= multiplier;
+ n.imaginary *= multiplier;
+ }
+ cpx_mtx_set(stateVector, 0, i, &n);
+ }
+
+ return newBit;
+}
+
+int qansel_get_instruction_bitmax(unsigned char* ptr, int offset, int* bitmax, int* qbitmax)
+{
+ unsigned char a0, a1, a2;
+ *bitmax = 0;
+ *qbitmax = 0;
+ switch (ptr[offset])
+ {
+ case QANSEL_INSTRUCTION_X:
+ case QANSEL_INSTRUCTION_Y:
+ case QANSEL_INSTRUCTION_Z:
+ case QANSEL_INSTRUCTION_H:
+ case QANSEL_INSTRUCTION_S:
+ case QANSEL_INSTRUCTION_T:
+ case QANSEL_INSTRUCTION_RX:
+ case QANSEL_INSTRUCTION_RY:
+ case QANSEL_INSTRUCTION_RZ:
+ case QANSEL_INSTRUCTION_U1:
+ case QANSEL_INSTRUCTION_U2:
+ case QANSEL_INSTRUCTION_U3:
+ case QANSEL_INSTRUCTION_BARRIER:
+ case QANSEL_INSTRUCTION_DENSITY:
+ case QANSEL_INSTRUCTION_BORN:
+ a0 = ptr[offset + 1];
+ if (a0 > 0x0D && a0 != 0x0F) return 0;
+ if (a0 != 0x0F) *qbitmax = a0 + 1;
+ return 1;
+ case QANSEL_INSTRUCTION_SAMPLE:
+ case QANSEL_INSTRUCTION_IF_E:
+ case QANSEL_INSTRUCTION_IF_NE:
+ case QANSEL_INSTRUCTION_IF_G:
+ case QANSEL_INSTRUCTION_IF_GE:
+ case QANSEL_INSTRUCTION_IF_L:
+ case QANSEL_INSTRUCTION_IF_LE:
+ a0 = ptr[offset + 1];
+ if ((a0 > 0x1D || a0 < 0x10) && a0 != 0x1F) return 0;
+ if (a0 != 0x1F) *bitmax = (a0 - 0x10) + 1;
+ return 1;
+ case QANSEL_INSTRUCTION_RESET:
+ case QANSEL_INSTRUCTION_PRINT:
+ a0 = ptr[offset + 1];
+ if (a0 == 0xFF) return 1;
+ if (a0 < 0x10)
+ {
+ if (a0 > 0x0D && a0 != 0x0F) return 0;
+ if (a0 != 0x0F) *qbitmax = a0 + 1;
+ return 1;
+ }
+ else
+ {
+ if ((a0 > 0x1D || a0 < 0x10) && a0 != 0x1F) return 0;
+ if (a0 != 0x1F) *bitmax = (a0 - 0x10) + 1;
+ return 1;
+ }
+ return 0;
+ case QANSEL_INSTRUCTION_CX:
+ case QANSEL_INSTRUCTION_SWAP:
+ a0 = ptr[offset + 1];
+ a1 = ptr[offset + 2];
+ if (a0 > 0x0D) return 0;
+ if (a1 > 0x0D) return 0;
+ *qbitmax = (a0 > a1 ? a0 : a1) + 1;
+ return 1;
+ case QANSEL_INSTRUCTION_CCX:
+ case QANSEL_INSTRUCTION_CSWAP:
+ a0 = ptr[offset + 1];
+ a1 = ptr[offset + 2];
+ a2 = ptr[offset + 3];
+ if (a0 > 0x0D || a1 > 0x0D || a2 > 0x0D) return 0;
+ *qbitmax = ((a0 > a1) && (a0 > a2) ? a0 : ((a1 > a0) && (a1 > a2) ? a1 : a2)) + 1;
+ return 1;
+ case QANSEL_INSTRUCTION_MEASURE:
+ a0 = ptr[offset + 1];
+ a1 = ptr[offset + 2];
+ if (a0 > 0x0D) return 0;
+ if (a1 > 0x1D || a1 < 0x10) return 0;
+ *qbitmax = a0 + 1;
+ *bitmax = (a1 - 0x10) + 1;
+ return 1;
+ case QANSEL_INSTRUCTION_RAND:
+ case QANSEL_INSTRUCTION_HVAR:
+ case QANSEL_INSTRUCTION_EXIT:
+ return 1;
+ }
+ return 0;
+}
+
+int qansel_get_instruction_size(unsigned char instr)
+{
+ switch (instr)
+ {
+ case QANSEL_INSTRUCTION_X: return 1 + 1;
+ case QANSEL_INSTRUCTION_Y: return 1 + 1;
+ case QANSEL_INSTRUCTION_Z: return 1 + 1;
+ case QANSEL_INSTRUCTION_H: return 1 + 1;
+ case QANSEL_INSTRUCTION_S: return 1 + 1;
+ case QANSEL_INSTRUCTION_T: return 1 + 1;
+ case QANSEL_INSTRUCTION_RX: return 1 + 1 + sizeof(float);
+ case QANSEL_INSTRUCTION_RY: return 1 + 1 + sizeof(float);
+ case QANSEL_INSTRUCTION_RZ: return 1 + 1 + sizeof(float);
+ case QANSEL_INSTRUCTION_U1: return 1 + 1 + sizeof(float);
+ case QANSEL_INSTRUCTION_U2: return 1 + 1 + sizeof(float) * 2;
+ case QANSEL_INSTRUCTION_U3: return 1 + 1 + sizeof(float) * 3;
+ case QANSEL_INSTRUCTION_CX: return 1 + 2;
+ case QANSEL_INSTRUCTION_SWAP: return 1 + 2;
+ case QANSEL_INSTRUCTION_CCX: return 1 + 3;
+ case QANSEL_INSTRUCTION_CSWAP: return 1 + 3;
+ case QANSEL_INSTRUCTION_MEASURE: return 1 + 2;
+ case QANSEL_INSTRUCTION_SAMPLE: return 1 + 1;
+ case QANSEL_INSTRUCTION_DENSITY: return 1 + 1;
+ case QANSEL_INSTRUCTION_BORN: return 1 + 1;
+ case QANSEL_INSTRUCTION_IF_E: return 1 + 1 + sizeof(unsigned short);
+ case QANSEL_INSTRUCTION_IF_NE: return 1 + 1 + sizeof(unsigned short);
+ case QANSEL_INSTRUCTION_IF_G: return 1 + 1 + sizeof(unsigned short);
+ case QANSEL_INSTRUCTION_IF_GE: return 1 + 1 + sizeof(unsigned short);
+ case QANSEL_INSTRUCTION_IF_L: return 1 + 1 + sizeof(unsigned short);
+ case QANSEL_INSTRUCTION_IF_LE: return 1 + 1 + sizeof(unsigned short);
+ case QANSEL_INSTRUCTION_RAND: return 1;
+ case QANSEL_INSTRUCTION_HVAR: return 1 + sizeof(float);
+ case QANSEL_INSTRUCTION_RESET: return 1 + 1;
+ case QANSEL_INSTRUCTION_PRINT: return 1 + 1;
+ case QANSEL_INSTRUCTION_BARRIER: return 1 + 1;
+ case QANSEL_INSTRUCTION_EXIT: return 1;
+ }
+ return 0;
+}
+
+void qansel_born(cpx_mtx_t* stateVector, int PC, int qubitCount, unsigned char q0)
+{
+ unsigned int qubitCountPow2 = (unsigned int)pow(2, qubitCount);
+ if (q0 == 0x0F)
+ {
+ for (unsigned int j = 0; j < qubitCountPow2; j++)
+ {
+ unsigned int tmp = j;
+ for (unsigned char k = 0; k < qubitCount; k++)
+ {
+ putchar('0' + (tmp >> (qubitCount - 1) & 1));
+ tmp <<= 1;
+ }
+ cpx_t n;
+ cpx_mtx_get(stateVector, 0, j, &n);
+ printf(": %.1f%%\n", cpx_magsqr(&n) * 100);
+ }
+ }
+ else if (q0 <= 0x0D)
+ {
+ float prob = 0;
+ for (unsigned int j = 0; j < qubitCountPow2; j++)
+ {
+ cpx_t n;
+ cpx_mtx_get(stateVector, 0, j, &n);
+ if ((j >> q0) & 1)
+ {
+ prob += cpx_magsqr(&n);
+ }
+ }
+ printf("0: %.1f%%\n", (1 - prob) * 100.0);
+ printf("1: %.1f%%\n", prob * 100.0);
+ }
+}
+
+void qansel_density_or_print(cpx_mtx_t* stateVector, unsigned char* bitVector, unsigned char density, int bitCount, int qubitCount, unsigned char a0)
+{
+ unsigned int qubitCountPow2 = (unsigned int)pow(2, qubitCount);
+ if (a0 == 0x0F || a0 == 0x1F || a0 == 0xFF)
+ {
+ if (a0 == 0x0F || a0 == 0xFF)
+ {
+ printf("[ "); cpx_mtx_print(stateVector); printf(" ]\n");
+ }
+ if (a0 == 0x1F || a0 == 0xFF)
+ {
+ for (int32_t j = bitCount - 1; j >= 0; j--)
+ {
+ putchar('0' + bitVector[j]);
+ }
+ putchar('\n');
+ }
+ }
+ else if (a0 >= 0x10 && a0 <= 0x1D)
+ {
+ putchar('0' + bitVector[a0 - 0x10]);
+ putchar('\n');
+ }
+ else
+ {
+ cpx_mtx_t tmp;
+ cpx_mtx_init(&tmp, 1, 2);
+ for (unsigned int j = 0; j < qubitCountPow2; j++)
+ {
+ if ((j >> a0) & 1)
+ {
+ cpx_t a, b;
+ cpx_mtx_get(&tmp, 0, 1, &a);
+ cpx_mtx_get(stateVector, 0, j, &b);
+ a.real += b.real;
+ a.imaginary += b.imaginary;
+ cpx_mtx_set(&tmp, 0, 1, &a);
+ }
+ else
+ {
+ cpx_t a, b;
+ cpx_mtx_get(&tmp, 0, 0, &a);
+ cpx_mtx_get(stateVector, 0, j, &b);
+ a.real += b.real;
+ a.imaginary += b.imaginary;
+ cpx_mtx_set(&tmp, 0, 0, &a);
+ }
+ }
+ float multiplier = 0;
+ cpx_t n;
+ cpx_mtx_get(&tmp, 0, 0, &n);
+ multiplier += cpx_magsqr(&n);
+ cpx_mtx_get(&tmp, 0, 1, &n);
+ multiplier += cpx_magsqr(&n);
+ multiplier = sqrt(1 / multiplier);
+ n.real *= multiplier;
+ n.imaginary *= multiplier;
+ cpx_mtx_set(&tmp, 0, 1, &n);
+ cpx_mtx_get(&tmp, 0, 0, &n);
+ n.real *= multiplier;
+ n.imaginary *= multiplier;
+ cpx_mtx_set(&tmp, 0, 0, &n);
+
+ if (density)
+ {
+ cpx_t a, b, c, d, x, y, z, w;
+ cpx_mtx_get(&tmp, 0, 0, &a);
+ cpx_mtx_get(&tmp, 0, 1, &b);
+ cpx_mtx_get(&tmp, 0, 0, &c);
+ cpx_mtx_get(&tmp, 0, 1, &d);
+ c.imaginary *= -1;
+ d.imaginary *= -1;
+ cpx_mul(&x, &a, &c);
+ cpx_mul(&y, &a, &d);
+ cpx_mul(&z, &b, &c);
+ cpx_mul(&w, &b, &d);
+ char* sx = cpx_str(&x);
+ char* sy = cpx_str(&y);
+ char* sz = cpx_str(&z);
+ char* sw = cpx_str(&w);
+ printf("[ %s, %s ]\n", sx, sy);
+ printf("[ %s, %s ]\n", sz, sw);
+ free(sx);
+ free(sy);
+ free(sz);
+ free(sw);
+ }
+ else
+ {
+ printf("[ "); cpx_mtx_print(&tmp); printf(" ]\n");
+ }
+ cpx_mtx_free(&tmp);
+ }
+}
+
+float qansel_get_float(unsigned char* program, int offset)
+{
+ float ret;
+ memcpy(&ret, program + offset, sizeof(float));
+ return ret;
+}
+
+short qansel_get_short(unsigned char* program, int offset)
+{
+ short ret;
+ memcpy(&ret, program + offset, sizeof(short));
+ return ret;
+}
+
+int qansel_get_int(unsigned char* program, int offset)
+{
+ int ret;
+ memcpy(&ret, program + offset, sizeof(int));
+ return ret;
+}
+
+void qansel_reset(cpx_mtx_t* stateVector, unsigned char* bitVector, int qubitCount, int bitCount, unsigned char q0)
+{
+ unsigned int qubitCountPow2 = (unsigned int)pow(2, qubitCount);
+ if (q0 == 0xFF)
+ {
+ cpx_mtx_set2(stateVector, 0, 0, 1, 0);
+ for (unsigned int j = 1; j < qubitCountPow2; j++)
+ {
+ cpx_mtx_set2(stateVector, 0, j, 0, 0);
+ }
+ for (unsigned char j = 0; j < bitCount; j++)
+ {
+ bitVector[j] = 0;
+ }
+ }
+ else if (q0 == 0x0F)
+ {
+ cpx_mtx_set2(stateVector, 0, 0, 1, 0);
+ for (unsigned int j = 1; j < qubitCountPow2; j++)
+ {
+ cpx_mtx_set2(stateVector, 0, j, 0, 0);
+ }
+ }
+ else if (q0 == 0x1F)
+ {
+ for (unsigned char j = 0; j < bitCount; j++)
+ {
+ bitVector[j] = 0;
+ }
+ }
+ else if (q0 <= 0x0D)
+ {
+ unsigned char bit = qansel_measure(stateVector, qubitCount, q0);
+ if (bit)
+ {
+ qansel_instruction(stateVector, qubitCount, QANSEL_INSTRUCTION_X, q0, 0, 0, 0);
+ }
+ }
+ else if (q0 >= 0x10 && q0 <= 0x1D)
+ {
+ bitVector[q0 - 0x10] = 0;
+ }
+}
+
+unsigned char qansel_compare(unsigned char* bitVector, int bitCount, int PC, unsigned char a0, short op)
+{
+ unsigned char ret = 0;
+ short val;
+ if (a0 == 0x1F)
+ {
+ val = 0;
+ for (int32_t j = bitCount - 1; j >= 0; j--)
+ {
+ val = (val << 1) | bitVector[j];
+ }
+ if (val == op) ret |= QANSEL_FLAGS_EQUAL;
+ if (val > op) ret |= QANSEL_FLAGS_GREATER;
+ if (val < op) ret |= QANSEL_FLAGS_LESSER;
+ }
+ else if (a0 >= 0x10 && a0 <= 0x1D)
+ {
+ val = bitVector[a0 - 0x10];
+ if (val == op) ret |= QANSEL_FLAGS_EQUAL;
+ if (val > op) ret |= QANSEL_FLAGS_GREATER;
+ if (val < op) ret |= QANSEL_FLAGS_LESSER;
+ }
+ return ret;
+}
+
+int qansel_crawl(unsigned char* program, int programSize, int* qubitCount, int* bitCount, int* sample)
+{
+ if (QANSEL_VERBOSE) printf("Crawling program . . .\n");
+ int PC = 0;
+ *qubitCount = 0;
+ *bitCount = 0;
+ *sample = 0xFF;
+ while (PC < programSize)
+ {
+ int next = qansel_get_instruction_size(program[PC]);
+ if (program[PC] == QANSEL_INSTRUCTION_SAMPLE)
+ {
+ if ((program[PC + 1] < 0x10 || program[PC + 1] > 0x1D) && program[PC + 1] != 0x1F)
+ {
+ if (QANSEL_VERBOSE) fprintf(stderr, "QAnsel (%04X): Invalid index.\n", PC);
+ }
+ else
+ {
+ *sample = program[PC + 1] - 0x10;
+ }
+ }
+ if (next == 0)
+ {
+ printf("QAnsel (%04X): Invalid instruction 0x%02x.\n", PC, program[PC]);
+ return 0;
+ }
+ int bitmax, qbitmax;
+ int success = qansel_get_instruction_bitmax(program, PC, &bitmax, &qbitmax);
+ if (!success)
+ {
+ fprintf(stderr, "QAnsel (%04X): Invalid index.\n", PC);
+ return 0;
+ }
+ if (bitmax > *bitCount) *bitCount = bitmax;
+ if (qbitmax > *qubitCount) *qubitCount = qbitmax;
+ PC += next;
+ }
+ if (QANSEL_VERBOSE) printf("Quantum bits allocated: %i\n", *qubitCount);
+ if (QANSEL_VERBOSE) printf("Classical bits allocated: %i\n", *bitCount);
+ return 1;
+}
+
+void qansel_run(unsigned char* program, int programSize, int qubitCount, int bitCount, unsigned char* outputBitVector)
+{
+ int PC = 0;
+ unsigned int qubitCountPow2 = (unsigned int)pow(2, qubitCount);
+ unsigned char bitVector[bitCount];
+ memset(bitVector, 0, bitCount);
+ cpx_mtx_t stateVector;
+ cpx_mtx_init(&stateVector, 1, qubitCountPow2);
+ cpx_mtx_set2(&stateVector, 0, 0, 1, 0);
+ if (QANSEL_USE_DISPLAY) { QANSEL_USE_DISPLAY = display(&stateVector, qubitCount, QANSEL_USE_DISPLAY); }
+ unsigned char skip = 0, a0 = 0, a1 = 0, a2 = 0;
+ unsigned char flags = 0;
+ unsigned short tmp = 0;
+
+ while (PC < programSize)
+ {
+ //printf("%i;%i\n", PC, programSize);
+ int next = qansel_get_instruction_size(program[PC]);
+ if (skip)
+ {
+ skip = 0;
+ }
+ else
+ {
+ unsigned char instr = program[PC];
+ //printf("-----------------------------------\n");
+ //qansel_density_or_print(&stateVector, bitVector, 0, bitCount, qubitCount, 0x0F);
+ //qansel_density_or_print(&stateVector, bitVector, 0, bitCount, qubitCount, 0x1F);
+ //printf("%s(%i, %i, %i)(%f, %f, %f)\n", qansel_instruction_to_string(instr), program[PC+1], program[PC+2], program[PC], qansel_get_float(program, PC + 2), qansel_get_float(program, PC + 2 + sizeof(float)), qansel_get_float(program, PC + 2) + sizeof(float) * 2);
+ switch (instr)
+ {
+ case QANSEL_INSTRUCTION_X:
+ case QANSEL_INSTRUCTION_Y:
+ case QANSEL_INSTRUCTION_Z:
+ case QANSEL_INSTRUCTION_H:
+ case QANSEL_INSTRUCTION_S:
+ case QANSEL_INSTRUCTION_T:
+ a0 = program[PC + 1];
+ qansel_instruction(&stateVector, qubitCount, instr, program[PC + 1], 0, 0, 0);
+ break;
+ case QANSEL_INSTRUCTION_RX:
+ a0 = program[PC + 1];
+ qansel_instruction
+ (
+ &stateVector, qubitCount, instr, a0,
+ M_PI / 2, -M_PI / 2, qansel_get_float(program, PC + 2) - (M_PI / 2)
+ );
+ break;
+ case QANSEL_INSTRUCTION_RY:
+ case QANSEL_INSTRUCTION_U1:
+ a0 = program[PC + 1];
+ qansel_instruction
+ (
+ &stateVector, qubitCount, instr, a0,
+ qansel_get_float(program, PC + 2), 0, 0
+ );
+ break;
+ case QANSEL_INSTRUCTION_RZ:
+ a0 = program[PC + 1];
+ qansel_instruction
+ (
+ &stateVector, qubitCount, instr, a0,
+ 0, 0, qansel_get_float(program, PC + 2)
+ );
+ break;
+ case QANSEL_INSTRUCTION_U2:
+ a0 = program[PC + 1];
+ qansel_instruction
+ (
+ &stateVector, qubitCount, instr, a0,
+ qansel_get_float(program, PC + 2),
+ qansel_get_float(program, PC + 2 + sizeof(float)),
+ 0
+ );
+ break;
+ case QANSEL_INSTRUCTION_U3:
+ a0 = program[PC + 1];
+ qansel_instruction
+ (
+ &stateVector, qubitCount, instr, a0,
+ qansel_get_float(program, PC + 2),
+ qansel_get_float(program, PC + 2 + sizeof(float)),
+ qansel_get_float(program, PC + 2 + sizeof(float) * 2)
+ );
+ break;
+ case QANSEL_INSTRUCTION_CX:
+ a0 = program[PC + 1];
+ a1 = program[PC + 2];
+ qansel_cnot(&stateVector, qubitCount, a0, a1);
+ break;
+ case QANSEL_INSTRUCTION_SWAP:
+ a0 = program[PC + 1];
+ a1 = program[PC + 2];
+ qansel_swap(&stateVector, qubitCount, a0, a1);
+ break;
+ case QANSEL_INSTRUCTION_CCX:
+ a0 = program[PC + 1];
+ a1 = program[PC + 2];
+ a2 = program[PC + 3];
+ qansel_toffoli(&stateVector, qubitCount, a0, a1, a2);
+ break;
+ case QANSEL_INSTRUCTION_CSWAP:
+ a0 = program[PC + 1];
+ a1 = program[PC + 2];
+ a2 = program[PC + 3];
+ qansel_fredkin(&stateVector, qubitCount, a0, a1, a2);
+ break;
+ case QANSEL_INSTRUCTION_MEASURE:
+ a0 = program[PC + 1];
+ a1 = program[PC + 2] - 0x10;
+ bitVector[a1] = qansel_measure(&stateVector, qubitCount, a0);
+ break;
+ case QANSEL_INSTRUCTION_BORN:
+ a0 = program[PC + 1];
+ qansel_born(&stateVector, PC, qubitCount, a0);
+ break;
+ case QANSEL_INSTRUCTION_DENSITY:
+ a0 = program[PC + 1];
+ qansel_density_or_print(&stateVector, bitVector, 1, bitCount, qubitCount, a0);
+ break;
+ case QANSEL_INSTRUCTION_PRINT:
+ a0 = program[PC + 1];
+ qansel_density_or_print(&stateVector, bitVector, 0, bitCount, qubitCount, a0);
+ break;
+ case QANSEL_INSTRUCTION_BARRIER:
+ a0 = program[PC + 1];
+ break;
+ case QANSEL_INSTRUCTION_RESET:
+ a0 = program[PC + 1];
+ qansel_reset(&stateVector, bitVector, qubitCount, bitCount, a0);
+ break;
+ case QANSEL_INSTRUCTION_HVAR:
+ QANSEL_HIDDEN_VARIABLE = 1;
+ float tmp1 = qansel_get_float(program, PC + 1);
+ unsigned int tmp2;
+ memcpy(&tmp2, &tmp1, sizeof(unsigned int));
+ srand(tmp2);
+ break;
+ case QANSEL_INSTRUCTION_RAND:
+ QANSEL_HIDDEN_VARIABLE = 0;
+ break;
+ case QANSEL_INSTRUCTION_IF_E:
+ a0 = program[PC + 1];
+ tmp = qansel_get_short(program, PC + 2);
+ flags = qansel_compare(bitVector, bitCount, PC, a0, tmp);
+ skip = 1; if (flags & QANSEL_FLAGS_EQUAL) skip = 0;
+ break;
+ case QANSEL_INSTRUCTION_IF_NE:
+ a0 = program[PC + 1];
+ tmp = qansel_get_short(program, PC + 2);
+ flags = qansel_compare(bitVector, bitCount, PC, a0, tmp);
+ skip = 1; if (!(flags & QANSEL_FLAGS_EQUAL)) skip = 0;
+ break;
+ case QANSEL_INSTRUCTION_IF_G:
+ a0 = program[PC + 1];
+ tmp = qansel_get_short(program, PC + 2);
+ flags = qansel_compare(bitVector, bitCount, PC, a0, tmp);
+ skip = 1; if (flags & QANSEL_FLAGS_GREATER) skip = 0;
+ break;
+ case QANSEL_INSTRUCTION_IF_GE:
+ a0 = program[PC + 1];
+ tmp = qansel_get_short(program, PC + 2);
+ flags = qansel_compare(bitVector, bitCount, PC, a0, tmp);
+ skip = 1; if ((flags & QANSEL_FLAGS_GREATER) && (flags & QANSEL_FLAGS_EQUAL)) skip = 0;
+ break;
+ case QANSEL_INSTRUCTION_IF_L:
+ a0 = program[PC + 1];
+ tmp = qansel_get_short(program, PC + 2);
+ flags = qansel_compare(bitVector, bitCount, PC, a0, tmp);
+ skip = 1; if (flags & QANSEL_FLAGS_LESSER) skip = 0;
+ break;
+ case QANSEL_INSTRUCTION_IF_LE:
+ a0 = program[PC + 1];
+ tmp = qansel_get_short(program, PC + 2);
+ flags = qansel_compare(bitVector, bitCount, PC, a0, tmp);
+ skip = 1; if ((flags & QANSEL_FLAGS_LESSER) && (flags & QANSEL_FLAGS_EQUAL)) skip = 0;
+ break;
+ case QANSEL_INSTRUCTION_SAMPLE: break;
+
+ }
+ }
+ PC += next;
+ if (QANSEL_USE_DISPLAY) { QANSEL_USE_DISPLAY = display(&stateVector, qubitCount, QANSEL_USE_DISPLAY); }
+ }
+ if (outputBitVector != NULL)
+ {
+ for (int i = 0; i < bitCount; i++)
+ {
+ outputBitVector[i] = bitVector[i];
+ }
+ }
+ cpx_mtx_free(&stateVector);
+ if (QANSEL_USE_DISPLAY) { display(NULL, 0, 0); }
+
+}
+
+int qanselExecuteBytecode(unsigned char* buff, int sizeofbuff)
+{
+ struct timespec ts;
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+ float seed = (float)((unsigned long)ts.tv_sec * 1000000000LL + ts.tv_nsec);
+ qansel_rand_s(seed);
+
+ unsigned short vals;
+ float valf;
+ int pos = 0;
+
+ int qubitCount, bitCount, sample;
+ if (!qansel_crawl(buff, sizeofbuff, &qubitCount, &bitCount, &sample))
+ {
+ return 0;
+ }
+
+ if (sample != 0xFF)
+ {
+ unsigned short stats[65536];
+ for (unsigned int i = 0; i < (1 << bitCount); i++)
+ {
+ stats[i] = 0;
+ }
+ unsigned char bitVect[bitCount];
+ memset(bitVect, 0, bitCount);
+ for (int i = 0; i < bitCount; i++) bitVect[i] = 0;
+ unsigned int shots = 1000;
+ for (unsigned int i = 0; i < shots; i++)
+ {
+ qansel_run(buff, sizeofbuff, qubitCount, bitCount, bitVect);
+ unsigned short stat = 0;
+ for (signed char j = bitCount - 1; j >= 0; j--)
+ {
+ stat = (stat << 1) | bitVect[j];
+ }
+ stats[stat]++;
+ }
+ unsigned int count = 0;
+ for (unsigned int i = 0; i < (1 << bitCount); i++)
+ {
+ unsigned int tmp = i;
+ for (unsigned char j = 0; j < bitCount; j++)
+ {
+ unsigned char bit = (tmp >> (bitCount - 1) & 1);
+ if (j == (bitCount - sample - 1) && bit)
+ {
+ count += stats[i];
+ }
+ if (sample == 0x0F)
+ {
+ putchar('0' + bit);
+ }
+ tmp <<= 1;
+ }
+ if (sample == 0x0F)
+ {
+ printf(": %.1f%%\n", ((float)stats[i] / (float)shots) * (float)100);
+ }
+ }
+ if (sample != 0x0F)
+ {
+ float prob = ((float)count / (float)shots) * (float)100;
+ printf("0: %.1f%%\n", ((float)100)-prob);
+ printf("1: %.1f%%\n", prob);
+ }
+ }
+ else
+ {
+ qansel_run(buff, sizeofbuff, qubitCount, bitCount, NULL);
+ }
+ return 1;
+}
n->imaginary = m->ptr[row * ((m->cols) * 2) + (col * 2) + 1];
}
+void cpx_mtx_copy(cpx_mtx_t* m, cpx_mtx_t* n)
+{
+ for (int i = 0; i < n->rows; i++)
+ {
+ for (int j = 0; j < n->cols; j++)
+ {
+ cpx_t tmp;
+ cpx_mtx_get(n, i, j, &tmp);
+ cpx_mtx_set(m, i, j, &tmp);
+ }
+ }
+}
+
+int cpx_mtx_cmp(cpx_mtx_t* m, cpx_mtx_t* n)
+{
+ if (m->rows != n->rows) return -1;
+ if (m->cols != n->cols) return -2;
+ for (int i = 0; i < n->rows; i++)
+ {
+ for (int j = 0; j < n->cols; j++)
+ {
+ cpx_t tmp1;
+ cpx_t tmp2;
+ cpx_mtx_get(n, i, j, &tmp1);
+ cpx_mtx_get(m, i, j, &tmp2);
+ if (tmp1.real != tmp2.real || tmp1.imaginary != tmp2.imaginary)
+ {
+ return j + i * n->cols + 1;
+ }
+ }
+ }
+ return 0;
+}
+
void cpx_mtx_init(cpx_mtx_t* m, int rows, int cols)
{
int z = rows * (cols * 2) * sizeof(float);
cl_mem memR = clCreateBuffer(cpx_mtx_context, CL_MEM_READ_ONLY, sizeR, NULL, &err); gpuerr(err);
//Populate buffers
- err = clEnqueueWriteBuffer(cpx_mtx_command_queue, memA, CL_TRUE, 0, sizeA, ptrA, 0, NULL, NULL);
- gpuerr(err);
+ err = clEnqueueWriteBuffer(cpx_mtx_command_queue, memA, CL_TRUE, 0, sizeA, ptrA, 0, NULL, NULL); gpuerr(err);
//Load and compile program
cl_program program;
+++ /dev/null
-#include <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-#include <time.h>
-#include "complex.c"
-#include "gates.c"
-#include "display.c"
-#include "chacha20.c"
-#define QUBITS_MAX 14
-unsigned char HIDDEN_VARIABLE = 0;
-FILE* RANDOM_FILE;
-#define GPU_ENABLED
-unsigned char USE_THREADS = 1;
-#define MODE_BARE 1
-#define MODE_THREADED 2
-#define MODE_METAL 3
-#define MODE_METAL_THREADED 4
-unsigned char MODE = MODE_BARE;
-//#define SPEED_TEST
-
-#define QANSEL_INSTRUCTION_X 0x10
-#define QANSEL_INSTRUCTION_Y 0x11
-#define QANSEL_INSTRUCTION_Z 0x12
-#define QANSEL_INSTRUCTION_H 0x13
-#define QANSEL_INSTRUCTION_S 0x14
-#define QANSEL_INSTRUCTION_T 0x15
-#define QANSEL_INSTRUCTION_RX 0x20
-#define QANSEL_INSTRUCTION_RY 0x21
-#define QANSEL_INSTRUCTION_RZ 0x22
-#define QANSEL_INSTRUCTION_U1 0x23
-#define QANSEL_INSTRUCTION_U2 0x24
-#define QANSEL_INSTRUCTION_U3 0x25
-#define QANSEL_INSTRUCTION_CX 0x30
-#define QANSEL_INSTRUCTION_SWAP 0x31
-#define QANSEL_INSTRUCTION_CCX 0x40
-#define QANSEL_INSTRUCTION_CSWAP 0x41
-#define QANSEL_INSTRUCTION_MEASURE 0xD0
-#define QANSEL_INSTRUCTION_SAMPLE 0xD1
-#define QANSEL_INSTRUCTION_DENSITY 0xD2
-#define QANSEL_INSTRUCTION_BORN 0xD3
-#define QANSEL_INSTRUCTION_IF_E 0xE1
-#define QANSEL_INSTRUCTION_IF_NE 0xE2
-#define QANSEL_INSTRUCTION_IF_G 0xE3
-#define QANSEL_INSTRUCTION_IF_GE 0xE4
-#define QANSEL_INSTRUCTION_IF_L 0xE5
-#define QANSEL_INSTRUCTION_IF_LE 0xE6
-#define QANSEL_INSTRUCTION_RAND 0xF0
-#define QANSEL_INSTRUCTION_HVAR 0xF1
-#define QANSEL_INSTRUCTION_RESET 0xF2
-#define QANSEL_INSTRUCTION_PRINT 0xF3
-#define QANSEL_INSTRUCTION_BARRIER 0xF4
-#define QANSEL_INSTRUCTION_EXIT 0xF5
-
-#define QANSEL_FLAGS_EQUAL 0b00001
-#define QANSEL_FLAGS_GREATER 0b00010
-#define QANSEL_FLAGS_LESSER 0b00100
-#define QANSEL_FLAGS_JUMPED 0b01000
-typedef struct
-{
- char n[128];
- unsigned char q0, q1, q2;
- float arg0, arg1, arg2;
-} QInstr;
-
-const char* qansel_instruction_to_string(unsigned char instr)
-{
- switch (instr)
- {
- case QANSEL_INSTRUCTION_X: return "QANSEL_INSTRUCTION_X";
- case QANSEL_INSTRUCTION_Y: return "QANSEL_INSTRUCTION_Y";
- case QANSEL_INSTRUCTION_Z: return "QANSEL_INSTRUCTION_Z";
- case QANSEL_INSTRUCTION_H: return "QANSEL_INSTRUCTION_H";
- case QANSEL_INSTRUCTION_S: return "QANSEL_INSTRUCTION_S";
- case QANSEL_INSTRUCTION_T: return "QANSEL_INSTRUCTION_T";
- case QANSEL_INSTRUCTION_RX: return "QANSEL_INSTRUCTION_RX";
- case QANSEL_INSTRUCTION_RY: return "QANSEL_INSTRUCTION_RY";
- case QANSEL_INSTRUCTION_RZ: return "QANSEL_INSTRUCTION_RZ";
- case QANSEL_INSTRUCTION_U1: return "QANSEL_INSTRUCTION_U1";
- case QANSEL_INSTRUCTION_U2: return "QANSEL_INSTRUCTION_U2";
- case QANSEL_INSTRUCTION_U3: return "QANSEL_INSTRUCTION_U3";
- case QANSEL_INSTRUCTION_CX: return "QANSEL_INSTRUCTION_CX";
- case QANSEL_INSTRUCTION_SWAP: return "QANSEL_INSTRUCTION_SWAP";
- case QANSEL_INSTRUCTION_CCX: return "QANSEL_INSTRUCTION_CCX";
- case QANSEL_INSTRUCTION_CSWAP: return "QANSEL_INSTRUCTION_CSWAP";
- case QANSEL_INSTRUCTION_MEASURE: return "QANSEL_INSTRUCTION_MEASURE";
- case QANSEL_INSTRUCTION_SAMPLE: return "QANSEL_INSTRUCTION_SAMPLE";
- case QANSEL_INSTRUCTION_DENSITY: return "QANSEL_INSTRUCTION_DENSITY";
- case QANSEL_INSTRUCTION_BORN: return "QANSEL_INSTRUCTION_BORN";
- case QANSEL_INSTRUCTION_IF_E: return "QANSEL_INSTRUCTION_JUMP_E";
- case QANSEL_INSTRUCTION_IF_NE: return "QANSEL_INSTRUCTION_JUMP_NE";
- case QANSEL_INSTRUCTION_IF_G: return "QANSEL_INSTRUCTION_JUMP_G";
- case QANSEL_INSTRUCTION_IF_GE: return "QANSEL_INSTRUCTION_JUMP_GE";
- case QANSEL_INSTRUCTION_IF_L: return "QANSEL_INSTRUCTION_JUMP_L";
- case QANSEL_INSTRUCTION_IF_LE: return "QANSEL_INSTRUCTION_JUMP_LE";
- case QANSEL_INSTRUCTION_RAND: return "QANSEL_INSTRUCTION_RAND";
- case QANSEL_INSTRUCTION_HVAR: return "QANSEL_INSTRUCTION_HVAR";
- case QANSEL_INSTRUCTION_RESET: return "QANSEL_INSTRUCTION_RESET";
- case QANSEL_INSTRUCTION_PRINT: return "QANSEL_INSTRUCTION_PRINT";
- case QANSEL_INSTRUCTION_BARRIER: return "QANSEL_INSTRUCTION_BARRIER";
- case QANSEL_INSTRUCTION_EXIT: return "QANSEL_INSTRUCTION_EXIT";
- }
- return "Unknown";
-}
-float qansel_rand_s(float s)
-{
- unsigned int tmp;
- memcpy(&tmp, &s, sizeof(unsigned int));
- srand(tmp);
-}
-float qansel_rand_h()
-{
- return ((float)rand()) / ((float)RAND_MAX);
-}
-float qansel_rand_t()
-{
- if (RANDOM_FILE)
- {
- unsigned int num = 0;
- for (unsigned char i = 0; i < 4; i++)
- {
- num = (num << 8) | fgetc(RANDOM_FILE);
- }
- return ((float)num) / ((float)UINT32_MAX);
- }
- else
- {
- HIDDEN_VARIABLE = 1;
- return qansel_rand_h();
- }
-}
-
-float qansel_rand()
-{
- return HIDDEN_VARIABLE ? qansel_rand_h() : qansel_rand_t();
-}
-
-void qansel_cnot(cpx_mtx_t* stateVector, unsigned char qubitCount, unsigned char bitA, unsigned char bitB)
-{
- if (bitA >= qubitCount || bitB >= qubitCount) return;
- unsigned int retLen = (unsigned int)pow(2, qubitCount);
- cpx_mtx_t ret;
- cpx_mtx_init(&ret, 1, retLen);
- cpx_t n;
- for (unsigned int i = 0; i < retLen; i++)
- {
- unsigned char bitAVal = (i >> bitA) & 1;
- unsigned char bitBVal = (i >> bitB) & 1;
- unsigned char bitBNew = bitAVal ? !bitBVal : bitBVal;
- unsigned int j = (i & ~(1 << bitB)) | (bitBNew << bitB);
- cpx_mtx_get(stateVector, 0, i, &n);
- cpx_mtx_set(&ret, 0, j, &n);
- }
- cpx_mtx_free(stateVector);
- stateVector->ptr = ret.ptr;
- stateVector->rows = ret.rows;
- stateVector->cols = ret.cols;
-}
-
-void qansel_swap(cpx_mtx_t* stateVector, unsigned char qubitCount, unsigned char bitA, unsigned char bitB)
-{
- if (bitA >= qubitCount || bitB >= qubitCount) return;
- unsigned int retLen = (unsigned int)pow(2, qubitCount);
- cpx_mtx_t ret;
- cpx_mtx_init(&ret, 1, retLen);
- cpx_t n;
- for (unsigned int i = 0; i < retLen; i++)
- {
- unsigned char bitAVal = (i >> bitA) & 1;
- unsigned char bitBVal = (i >> bitB) & 1;
- unsigned char bitANew = bitBVal;
- unsigned char bitBNew = bitAVal;
- unsigned int j = (i & ~((1 << bitA) | (1 << bitB))) | ((bitANew << bitA) | (bitBNew << bitB));
- cpx_mtx_get(stateVector, 0, i, &n);
- cpx_mtx_set(&ret, 0, j, &n);
- }
- cpx_mtx_free(stateVector);
- stateVector->ptr = ret.ptr;
- stateVector->rows = ret.rows;
- stateVector->cols = ret.cols;
-}
-
-void qansel_fredkin(cpx_mtx_t* stateVector, unsigned char qubitCount, unsigned char bitA, unsigned char bitB, unsigned char bitC)
-{
- if (bitA >= qubitCount || bitB >= qubitCount) return;
- unsigned int retLen = (unsigned int)pow(2, qubitCount);
- cpx_mtx_t ret;
- cpx_mtx_init(&ret, 1, retLen);
- cpx_t n;
- for (unsigned int i = 0; i < retLen; i++)
- {
- unsigned char bitAVal = (i >> bitA) & 1;
- unsigned char bitBVal = (i >> bitB) & 1;
- unsigned char bitCVal = (i >> bitC) & 1;
- unsigned char bitBNew = bitAVal ? bitCVal : bitBVal;
- unsigned char bitCNew = bitAVal ? bitBVal : bitCVal;
- unsigned int j = (i & ~((1 << bitB) | (1 << bitC))) | ((bitBNew << bitB) | (bitCNew << bitC));
- cpx_mtx_get(stateVector, 0, i, &n);
- cpx_mtx_set(&ret, 0, j, &n);
- }
- cpx_mtx_free(stateVector);
- stateVector->ptr = ret.ptr;
- stateVector->rows = ret.rows;
- stateVector->cols = ret.cols;
-}
-
-
-void qansel_toffoli(cpx_mtx_t* stateVector, unsigned char qubitCount, unsigned char bitA, unsigned char bitB, unsigned char bitC)
-{
- if (bitA >= qubitCount || bitB >= qubitCount) return;
- unsigned int retLen = (unsigned int)pow(2, qubitCount);
- cpx_mtx_t ret;
- cpx_mtx_init(&ret, 1, retLen);
- cpx_t n;
- for (unsigned int i = 0; i < retLen; i++)
- {
- unsigned char bitAVal = (i >> bitA) & 1;
- unsigned char bitBVal = (i >> bitB) & 1;
- unsigned char bitCVal = (i >> bitC) & 1;
- unsigned char bitCNew = (bitAVal && bitBVal) ? !bitCVal : bitCVal;
- unsigned int j = (i & ~(1 << bitC)) | (bitCNew << bitC);
- cpx_mtx_get(stateVector, 0, i, &n);
- cpx_mtx_set(&ret, 0, j, &n);
- }
- cpx_mtx_free(stateVector);
- stateVector->ptr = ret.ptr;
- stateVector->rows = ret.rows;
- stateVector->cols = ret.cols;
-}
-
-float* qansel_unitary(float theta, float phi, float lambda)
-{
- cpx_mtx_t m;
- cpx_t a, b, c, d;
- a.real = cos(theta/2.0);
- a.imaginary = 0;
- b.real = -cos(lambda) * sin(theta/2.0);
- b.imaginary = sin(lambda) * sin(theta/2.0);
- c.real = cos(phi) * sin(theta/2.0);
- c.imaginary = sin(phi) * sin(theta/2.0);
- d.real = cos(phi + lambda) * cos(theta/2.0);
- d.imaginary = sin(phi + lambda) * cos(theta/2.0);
- cpx_mtx_init(&m, 2, 2);
- cpx_mtx_set(&m, 0, 0, &a);
- cpx_mtx_set(&m, 0, 1, &b);
- cpx_mtx_set(&m, 1, 0, &c);
- cpx_mtx_set(&m, 1, 1, &d);
- return m.ptr;
-}
-
-void qansel_instruction
-(
- cpx_mtx_t* stateVector,
- int qubitCount,
- unsigned char instr,
- unsigned char index,
- float arg0,
- float arg1,
- float arg2
-)
-{
- cpx_mtx_t tmp;
- cpx_mtx_t gate;
- gate.rows = 2;
- gate.cols = 2;
- float* gate_ptr;
- switch (instr)
- {
- case QANSEL_INSTRUCTION_H: gate_ptr = Hadamard; break;
- case QANSEL_INSTRUCTION_X: gate_ptr = PauliX; break;
- case QANSEL_INSTRUCTION_Y: gate_ptr = PauliY; break;
- case QANSEL_INSTRUCTION_Z: gate_ptr = PauliZ; break;
- case QANSEL_INSTRUCTION_S: gate_ptr = PhaseS; break;
- case QANSEL_INSTRUCTION_T: gate_ptr = PhaseT; break;
- case QANSEL_INSTRUCTION_RX:
- case QANSEL_INSTRUCTION_RY:
- case QANSEL_INSTRUCTION_RZ:
- case QANSEL_INSTRUCTION_U1:
- case QANSEL_INSTRUCTION_U2:
- case QANSEL_INSTRUCTION_U3:
- gate_ptr = qansel_unitary(arg0, arg1, arg2);
- break;
- default: gate_ptr = Identity; break;
- }
-
- cpx_t n;
- cpx_mtx_t filter;
- cpx_mtx_init(&filter, 2, 2);
- unsigned char qubit = qubitCount - (index) - 1;
- if (qubit == 0)
- {
- memcpy(filter.ptr, gate_ptr, 8 * sizeof(float));
- }
- else
- {
- memcpy(filter.ptr, Identity, 8 * sizeof(float));
- }
-
- for (unsigned char i = 1; i < qubitCount; i++)
- {
- if (index != 0x0F)
- {
- if (qubit == i)
- {
- gate.ptr = gate_ptr;
- }
- else
- {
- gate.ptr = Identity;
- }
- }
- else
- {
- gate.ptr = gate_ptr;
- }
-
- tmp.rows = filter.rows * gate.rows;
- tmp.cols = filter.cols * gate.cols;
- tmp.ptr = malloc(tmp.rows * (tmp.cols * 2) * sizeof(float));
-
- #ifdef SPEED_TEST
- printf("(%ix%i);(%ix%i) (knk)\n", tmp.rows, tmp.cols, gate.rows, gate.cols);
- unsigned long int us1, us2;
- us1 = get_time();
- cpx_mtx_knk_metal(tmp.ptr, filter.ptr, gate.ptr, filter.rows, filter.cols, gate.rows, gate.cols);
- us2 = get_time();
- printf("\tMetal: %lu\n", us2 - us1);
- us1 = get_time();
- cpx_mtx_knk_metal_2x2(tmp.ptr, filter.ptr, gate.ptr, filter.rows, filter.cols, gate.rows, gate.cols);
- us2 = get_time();
- printf("\tMetal2x2: %lu\n", us2 - us1);
- us1 = get_time();
- cpx_mtx_knk_threads(tmp.ptr, filter.ptr, gate.ptr, filter.rows, filter.cols, gate.rows, gate.cols);
- us2 = get_time();
- printf("\tThreads: %lu\n", us2 - us1);
- us1 = get_time();
- cpx_mtx_knk_threads_2x2(tmp.ptr, filter.ptr, gate.ptr, filter.rows, filter.cols, gate.rows, gate.cols);
- us2 = get_time();
- printf("\tThreads2x2: %lu\n", us2 - us1);
- us1 = get_time();
- cpx_mtx_knk(tmp.ptr, filter.ptr, gate.ptr, filter.rows, filter.cols, gate.rows, gate.cols);
- us2 = get_time();
- printf("\tBare: %lu\n", us2 - us1);
- us1 = get_time();
- cpx_mtx_knk_2x2(tmp.ptr, filter.ptr, gate.ptr, filter.rows, filter.cols, gate.rows, gate.cols);
- us2 = get_time();
- printf("\tBare2x2: %lu\n", us2 - us1);
-
- //us1 = get_time();
- //cpx_mtx_knk(tmp.ptr, filter.ptr, gate.ptr, filter.rows, filter.cols, gate.rows, gate.cols);
- //us2 = get_time();
- //printf("\tTranspose: %lu\n", us2 - us1);
- #else
- if (MODE == MODE_METAL && tmp.cols >= 64)
- {
- cpx_mtx_knk_metal_2x2(tmp.ptr, filter.ptr, gate.ptr, filter.rows, filter.cols, gate.rows, gate.cols);
- }
- else if ((MODE == MODE_THREADED || MODE == MODE_METAL_THREADED) && tmp.cols >= 64)
- {
- cpx_mtx_knk_threads_2x2(tmp.ptr, filter.ptr, gate.ptr, filter.rows, filter.cols, gate.rows, gate.cols);
- }
- else
- {
- cpx_mtx_knk_2x2(tmp.ptr, filter.ptr, gate.ptr, filter.rows, filter.cols, gate.rows, gate.cols);
- }
- #endif
-
- free(filter.ptr);
- filter.ptr = tmp.ptr;
- filter.rows = tmp.rows;
- filter.cols = tmp.cols;
- }
-
- cpx_mtx_init(&tmp, stateVector->rows, stateVector->cols);
-
- #ifdef SPEED_TEST
- printf("%ix%i (dot)\n", tmp.rows, tmp.cols);
- unsigned long int us1, us2;
- us1 = get_time();
- cpx_mtx_dot_metal(tmp.ptr, stateVector->ptr, filter.ptr, stateVector->rows, stateVector->cols, filter.rows, filter.cols);
- us2 = get_time();
- printf("\tMetal: %lu\n", us2 - us1);
- us1 = get_time();
- cpx_mtx_dot_threads(tmp.ptr, stateVector->ptr, filter.ptr, stateVector->rows, stateVector->cols, filter.rows, filter.cols);
- us2 = get_time();
- printf("\tThreads: %lu\n", us2 - us1);
- us1 = get_time();
- cpx_mtx_dot(tmp.ptr, stateVector->ptr, filter.ptr, stateVector->rows, stateVector->cols, filter.rows, filter.cols);
- us2 = get_time();
- printf("\tBare: %lu\n", us2 - us1);
- #else
- if ((MODE == MODE_METAL || MODE == MODE_METAL_THREADED) && tmp.cols >= 64)
- {
- cpx_mtx_dot_metal(tmp.ptr, stateVector->ptr, filter.ptr, stateVector->rows, stateVector->cols, filter.rows, filter.cols);
- }
- else if (MODE == MODE_THREADED && tmp.cols >= 64)
- {
- cpx_mtx_dot_threads(tmp.ptr, stateVector->ptr, filter.ptr, stateVector->rows, stateVector->cols, filter.rows, filter.cols);
- }
- else
- {
- cpx_mtx_dot(tmp.ptr, stateVector->ptr, filter.ptr, stateVector->rows, stateVector->cols, filter.rows, filter.cols);
- }
- #endif
- free(stateVector->ptr);
- stateVector->ptr = tmp.ptr;
- free(filter.ptr);
- if (instr == QANSEL_INSTRUCTION_U1 || instr == QANSEL_INSTRUCTION_U2 || instr == QANSEL_INSTRUCTION_U3)
- {
- free(gate_ptr);
- }
-}
-
-unsigned char qansel_measure(cpx_mtx_t* stateVector, unsigned char qubitCount, unsigned char qubit)
-{
- unsigned int qubitCountPow2 = (unsigned int)pow(2, qubitCount);
- cpx_t n;
- float prob0 = 0;
- for (unsigned int i = 0; i < qubitCountPow2; i++)
- {
- unsigned char bit = (i >> qubit) & 1;
- cpx_mtx_get(stateVector, 0, i, &n);
- if (bit == 0) prob0 += cpx_magsqr(&n);
- }
-
- float r = qansel_rand();
- unsigned char newBit = r < prob0 ? 0 : 1;
- float probTot = 0;
- for (unsigned int i = 0; i < qubitCountPow2; i++)
- {
- unsigned char bit = (i >> qubit) & 1;
- cpx_mtx_get(stateVector, 0, i, &n);
- if (bit != newBit)
- {
- n.real = 0;
- n.imaginary = 0;
- }
- else
- {
- probTot += cpx_magsqr(&n);
- }
- cpx_mtx_set(stateVector, 0, i, &n);
- }
-
- float multiplier = sqrt(1 / probTot);
- for (unsigned int i = 0; i < qubitCountPow2; i++)
- {
- unsigned char bit = (i >> qubit) & 1;
- cpx_mtx_get(stateVector, 0, i, &n);
- if (bit == newBit)
- {
- n.real *= multiplier;
- n.imaginary *= multiplier;
- }
- cpx_mtx_set(stateVector, 0, i, &n);
- }
-
- return newBit;
-}
-
-int qansel_get_instruction_bitmax(unsigned char* ptr, int offset, int* bitmax, int* qbitmax)
-{
- unsigned char a0, a1, a2;
- *bitmax = 0;
- *qbitmax = 0;
- switch (ptr[offset])
- {
- case QANSEL_INSTRUCTION_X:
- case QANSEL_INSTRUCTION_Y:
- case QANSEL_INSTRUCTION_Z:
- case QANSEL_INSTRUCTION_H:
- case QANSEL_INSTRUCTION_S:
- case QANSEL_INSTRUCTION_T:
- case QANSEL_INSTRUCTION_RX:
- case QANSEL_INSTRUCTION_RY:
- case QANSEL_INSTRUCTION_RZ:
- case QANSEL_INSTRUCTION_U1:
- case QANSEL_INSTRUCTION_U2:
- case QANSEL_INSTRUCTION_U3:
- case QANSEL_INSTRUCTION_BARRIER:
- case QANSEL_INSTRUCTION_DENSITY:
- case QANSEL_INSTRUCTION_BORN:
- a0 = ptr[offset + 1];
- if (a0 > 0x0D && a0 != 0x0F) return 0;
- if (a0 != 0x0F) *qbitmax = a0 + 1;
- return 1;
- case QANSEL_INSTRUCTION_SAMPLE:
- case QANSEL_INSTRUCTION_IF_E:
- case QANSEL_INSTRUCTION_IF_NE:
- case QANSEL_INSTRUCTION_IF_G:
- case QANSEL_INSTRUCTION_IF_GE:
- case QANSEL_INSTRUCTION_IF_L:
- case QANSEL_INSTRUCTION_IF_LE:
- a0 = ptr[offset + 1];
- if ((a0 > 0x1D || a0 < 0x10) && a0 != 0x1F) return 0;
- if (a0 != 0x1F) *bitmax = (a0 - 0x10) + 1;
- return 1;
- case QANSEL_INSTRUCTION_RESET:
- case QANSEL_INSTRUCTION_PRINT:
- a0 = ptr[offset + 1];
- if (a0 == 0xFF) return 1;
- if (a0 < 0x10)
- {
- if (a0 > 0x0D && a0 != 0x0F) return 0;
- if (a0 != 0x0F) *qbitmax = a0 + 1;
- return 1;
- }
- else
- {
- if ((a0 > 0x1D || a0 < 0x10) && a0 != 0x1F) return 0;
- if (a0 != 0x1F) *bitmax = (a0 - 0x10) + 1;
- return 1;
- }
- return 0;
- case QANSEL_INSTRUCTION_CX:
- case QANSEL_INSTRUCTION_SWAP:
- a0 = ptr[offset + 1];
- a1 = ptr[offset + 2];
- if (a0 > 0x0D) return 0;
- if (a1 > 0x0D) return 0;
- *qbitmax = (a0 > a1 ? a0 : a1) + 1;
- return 1;
- case QANSEL_INSTRUCTION_CCX:
- case QANSEL_INSTRUCTION_CSWAP:
- a0 = ptr[offset + 1];
- a1 = ptr[offset + 2];
- a2 = ptr[offset + 3];
- if (a0 > 0x0D || a1 > 0x0D || a2 > 0x0D) return 0;
- *qbitmax = ((a0 > a1) && (a0 > a2) ? a0 : ((a1 > a0) && (a1 > a2) ? a1 : a2)) + 1;
- return 1;
- case QANSEL_INSTRUCTION_MEASURE:
- a0 = ptr[offset + 1];
- a1 = ptr[offset + 2];
- if (a0 > 0x0D) return 0;
- if (a1 > 0x1D || a1 < 0x10) return 0;
- *qbitmax = a0 + 1;
- *bitmax = (a1 - 0x10) + 1;
- return 1;
- case QANSEL_INSTRUCTION_RAND:
- case QANSEL_INSTRUCTION_HVAR:
- case QANSEL_INSTRUCTION_EXIT:
- return 1;
- }
- return 0;
-}
-
-int qansel_get_instruction_size(unsigned char instr)
-{
- switch (instr)
- {
- case QANSEL_INSTRUCTION_X: return 1 + 1;
- case QANSEL_INSTRUCTION_Y: return 1 + 1;
- case QANSEL_INSTRUCTION_Z: return 1 + 1;
- case QANSEL_INSTRUCTION_H: return 1 + 1;
- case QANSEL_INSTRUCTION_S: return 1 + 1;
- case QANSEL_INSTRUCTION_T: return 1 + 1;
- case QANSEL_INSTRUCTION_RX: return 1 + 1 + sizeof(float);
- case QANSEL_INSTRUCTION_RY: return 1 + 1 + sizeof(float);
- case QANSEL_INSTRUCTION_RZ: return 1 + 1 + sizeof(float);
- case QANSEL_INSTRUCTION_U1: return 1 + 1 + sizeof(float);
- case QANSEL_INSTRUCTION_U2: return 1 + 1 + sizeof(float) * 2;
- case QANSEL_INSTRUCTION_U3: return 1 + 1 + sizeof(float) * 3;
- case QANSEL_INSTRUCTION_CX: return 1 + 2;
- case QANSEL_INSTRUCTION_SWAP: return 1 + 2;
- case QANSEL_INSTRUCTION_CCX: return 1 + 3;
- case QANSEL_INSTRUCTION_CSWAP: return 1 + 3;
- case QANSEL_INSTRUCTION_MEASURE: return 1 + 2;
- case QANSEL_INSTRUCTION_SAMPLE: return 1 + 1;
- case QANSEL_INSTRUCTION_DENSITY: return 1 + 1;
- case QANSEL_INSTRUCTION_BORN: return 1 + 1;
- case QANSEL_INSTRUCTION_IF_E: return 1 + 1 + sizeof(unsigned short);
- case QANSEL_INSTRUCTION_IF_NE: return 1 + 1 + sizeof(unsigned short);
- case QANSEL_INSTRUCTION_IF_G: return 1 + 1 + sizeof(unsigned short);
- case QANSEL_INSTRUCTION_IF_GE: return 1 + 1 + sizeof(unsigned short);
- case QANSEL_INSTRUCTION_IF_L: return 1 + 1 + sizeof(unsigned short);
- case QANSEL_INSTRUCTION_IF_LE: return 1 + 1 + sizeof(unsigned short);
- case QANSEL_INSTRUCTION_RAND: return 1;
- case QANSEL_INSTRUCTION_HVAR: return 1 + sizeof(float);
- case QANSEL_INSTRUCTION_RESET: return 1 + 1;
- case QANSEL_INSTRUCTION_PRINT: return 1 + 1;
- case QANSEL_INSTRUCTION_BARRIER: return 1 + 1;
- case QANSEL_INSTRUCTION_EXIT: return 1;
- }
- return 0;
-}
-
-void qansel_born(cpx_mtx_t* stateVector, int PC, int qubitCount, unsigned char q0)
-{
- unsigned int qubitCountPow2 = (unsigned int)pow(2, qubitCount);
- if (q0 == 0x0F)
- {
- for (unsigned int j = 0; j < qubitCountPow2; j++)
- {
- unsigned int tmp = j;
- for (unsigned char k = 0; k < qubitCount; k++)
- {
- putchar('0' + (tmp >> (qubitCount - 1) & 1));
- tmp <<= 1;
- }
- cpx_t n;
- cpx_mtx_get(stateVector, 0, j, &n);
- printf(": %.1f%%\n", cpx_magsqr(&n) * 100);
- }
- }
- else if (q0 <= 0x0D)
- {
- float prob = 0;
- for (unsigned int j = 0; j < qubitCountPow2; j++)
- {
- cpx_t n;
- cpx_mtx_get(stateVector, 0, j, &n);
- if ((j >> q0) & 1)
- {
- prob += cpx_magsqr(&n);
- }
- }
- printf("0: %.1f%%\n", (1 - prob) * 100.0);
- printf("1: %.1f%%\n", prob * 100.0);
- }
-}
-
-void qansel_density_or_print(cpx_mtx_t* stateVector, unsigned char* bitVector, unsigned char density, int bitCount, int qubitCount, unsigned char a0)
-{
- unsigned int qubitCountPow2 = (unsigned int)pow(2, qubitCount);
- if (a0 == 0x0F || a0 == 0x1F || a0 == 0xFF)
- {
- if (a0 == 0x0F || a0 == 0xFF)
- {
- printf("[ "); cpx_mtx_print(stateVector); printf(" ]\n");
- }
- if (a0 == 0x1F || a0 == 0xFF)
- {
- for (int32_t j = bitCount - 1; j >= 0; j--)
- {
- putchar('0' + bitVector[j]);
- }
- putchar('\n');
- }
- }
- else if (a0 >= 0x10 && a0 <= 0x1D)
- {
- putchar('0' + bitVector[a0 - 0x10]);
- putchar('\n');
- }
- else
- {
- cpx_mtx_t tmp;
- cpx_mtx_init(&tmp, 1, 2);
- for (unsigned int j = 0; j < qubitCountPow2; j++)
- {
- if ((j >> a0) & 1)
- {
- cpx_t a, b;
- cpx_mtx_get(&tmp, 0, 1, &a);
- cpx_mtx_get(stateVector, 0, j, &b);
- a.real += b.real;
- a.imaginary += b.imaginary;
- cpx_mtx_set(&tmp, 0, 1, &a);
- }
- else
- {
- cpx_t a, b;
- cpx_mtx_get(&tmp, 0, 0, &a);
- cpx_mtx_get(stateVector, 0, j, &b);
- a.real += b.real;
- a.imaginary += b.imaginary;
- cpx_mtx_set(&tmp, 0, 0, &a);
- }
- }
- float multiplier = 0;
- cpx_t n;
- cpx_mtx_get(&tmp, 0, 0, &n);
- multiplier += cpx_magsqr(&n);
- cpx_mtx_get(&tmp, 0, 1, &n);
- multiplier += cpx_magsqr(&n);
- multiplier = sqrt(1 / multiplier);
- n.real *= multiplier;
- n.imaginary *= multiplier;
- cpx_mtx_set(&tmp, 0, 1, &n);
- cpx_mtx_get(&tmp, 0, 0, &n);
- n.real *= multiplier;
- n.imaginary *= multiplier;
- cpx_mtx_set(&tmp, 0, 0, &n);
-
- if (density)
- {
- cpx_t a, b, c, d, x, y, z, w;
- cpx_mtx_get(&tmp, 0, 0, &a);
- cpx_mtx_get(&tmp, 0, 1, &b);
- cpx_mtx_get(&tmp, 0, 0, &c);
- cpx_mtx_get(&tmp, 0, 1, &d);
- c.imaginary *= -1;
- d.imaginary *= -1;
- cpx_mul(&x, &a, &c);
- cpx_mul(&y, &a, &d);
- cpx_mul(&z, &b, &c);
- cpx_mul(&w, &b, &d);
- char* sx = cpx_str(&x);
- char* sy = cpx_str(&y);
- char* sz = cpx_str(&z);
- char* sw = cpx_str(&w);
- printf("[ %s, %s ]\n", sx, sy);
- printf("[ %s, %s ]\n", sz, sw);
- free(sx);
- free(sy);
- free(sz);
- free(sw);
- }
- else
- {
- printf("[ "); cpx_mtx_print(&tmp); printf(" ]\n");
- }
- cpx_mtx_free(&tmp);
- }
-}
-
-float qansel_get_float(unsigned char* program, int offset)
-{
- float ret;
- memcpy(&ret, program + offset, sizeof(float));
- return ret;
-}
-
-short qansel_get_short(unsigned char* program, int offset)
-{
- short ret;
- memcpy(&ret, program + offset, sizeof(short));
- return ret;
-}
-
-int qansel_get_int(unsigned char* program, int offset)
-{
- int ret;
- memcpy(&ret, program + offset, sizeof(int));
- return ret;
-}
-
-void qansel_reset(cpx_mtx_t* stateVector, unsigned char* bitVector, int qubitCount, int bitCount, unsigned char q0)
-{
- unsigned int qubitCountPow2 = (unsigned int)pow(2, qubitCount);
- if (q0 == 0xFF)
- {
- cpx_mtx_set2(stateVector, 0, 0, 1, 0);
- for (unsigned int j = 1; j < qubitCountPow2; j++)
- {
- cpx_mtx_set2(stateVector, 0, j, 0, 0);
- }
- for (unsigned char j = 0; j < bitCount; j++)
- {
- bitVector[j] = 0;
- }
- }
- else if (q0 == 0x0F)
- {
- cpx_mtx_set2(stateVector, 0, 0, 1, 0);
- for (unsigned int j = 1; j < qubitCountPow2; j++)
- {
- cpx_mtx_set2(stateVector, 0, j, 0, 0);
- }
- }
- else if (q0 == 0x1F)
- {
- for (unsigned char j = 0; j < bitCount; j++)
- {
- bitVector[j] = 0;
- }
- }
- else if (q0 <= 0x0D)
- {
- unsigned char bit = qansel_measure(stateVector, qubitCount, q0);
- if (bit)
- {
- qansel_instruction(stateVector, qubitCount, QANSEL_INSTRUCTION_X, q0, 0, 0, 0);
- }
- }
- else if (q0 >= 0x10 && q0 <= 0x1D)
- {
- bitVector[q0 - 0x10] = 0;
- }
-}
-
-unsigned char qansel_compare(unsigned char* bitVector, int bitCount, int PC, unsigned char a0, short op)
-{
- unsigned char ret = 0;
- short val;
- if (a0 == 0x1F)
- {
- val = 0;
- for (int32_t j = bitCount - 1; j >= 0; j--)
- {
- val = (val << 1) | bitVector[j];
- }
- if (val == op) ret |= QANSEL_FLAGS_EQUAL;
- if (val > op) ret |= QANSEL_FLAGS_GREATER;
- if (val < op) ret |= QANSEL_FLAGS_LESSER;
- }
- else if (a0 >= 0x10 && a0 <= 0x1D)
- {
- val = bitVector[a0 - 0x10];
- if (val == op) ret |= QANSEL_FLAGS_EQUAL;
- if (val > op) ret |= QANSEL_FLAGS_GREATER;
- if (val < op) ret |= QANSEL_FLAGS_LESSER;
- }
- return ret;
-}
-
-void qansel_crawl(unsigned char* program, int programSize, int* qubitCount, int* bitCount, int* sample)
-{
- printf("Crawling program . . .\n");
- int PC = 0;
- *qubitCount = 0;
- *bitCount = 0;
- *sample = 0xFF;
- while (PC < programSize)
- {
- int next = qansel_get_instruction_size(program[PC]);
- if (program[PC] == QANSEL_INSTRUCTION_SAMPLE)
- {
- if ((program[PC + 1] < 0x10 || program[PC + 1] > 0x1D) && program[PC + 1] != 0x1F)
- {
- fprintf(stderr, "QAnsel (%04X): Invalid index.\n", PC);
- }
- else
- {
- *sample = program[PC + 1] - 0x10;
- }
- }
- if (next == 0)
- {
- printf("QAnsel (%04X): Invalid instruction 0x%02x.\n", PC, program[PC]);
- exit(1);
- }
- int bitmax, qbitmax;
- int success = qansel_get_instruction_bitmax(program, PC, &bitmax, &qbitmax);
- if (!success)
- {
- fprintf(stderr, "QAnsel (%04X): Invalid index.\n", PC);
- exit(1);
- }
- if (bitmax > *bitCount) *bitCount = bitmax;
- if (qbitmax > *qubitCount) *qubitCount = qbitmax;
- PC += next;
- }
- printf("Quantum bits allocated: %i\n", *qubitCount);
- printf("Classical bits allocated: %i\n", *bitCount);
-}
-
-void qansel_run(unsigned char* program, int programSize, int qubitCount, int bitCount, unsigned char* outputBitVector)
-{
- int PC = 0;
- unsigned int qubitCountPow2 = (unsigned int)pow(2, qubitCount);
- unsigned char bitVector[bitCount];
- memset(bitVector, 0, bitCount);
- cpx_mtx_t stateVector;
- cpx_mtx_init(&stateVector, 1, qubitCountPow2);
- cpx_mtx_set2(&stateVector, 0, 0, 1, 0);
- //if (gfx) display(&stateVector, qubitCount);
- unsigned char skip = 0, a0 = 0, a1 = 0, a2 = 0;
- unsigned char flags = 0;
- unsigned short tmp = 0;
-
- while (PC < programSize)
- {
- //printf("%i;%i\n", PC, programSize);
- int next = qansel_get_instruction_size(program[PC]);
- if (skip)
- {
- skip = 0;
- }
- else
- {
- unsigned char instr = program[PC];
- //printf("-----------------------------------\n");
- //qansel_density_or_print(&stateVector, bitVector, 0, bitCount, qubitCount, 0x0F);
- //qansel_density_or_print(&stateVector, bitVector, 0, bitCount, qubitCount, 0x1F);
- //printf("%s(%i, %i, %i)(%f, %f, %f)\n", qansel_instruction_to_string(instr), program[PC+1], program[PC+2], program[PC], qansel_get_float(program, PC + 2), qansel_get_float(program, PC + 2 + sizeof(float)), qansel_get_float(program, PC + 2) + sizeof(float) * 2);
- switch (instr)
- {
- case QANSEL_INSTRUCTION_X:
- case QANSEL_INSTRUCTION_Y:
- case QANSEL_INSTRUCTION_Z:
- case QANSEL_INSTRUCTION_H:
- case QANSEL_INSTRUCTION_S:
- case QANSEL_INSTRUCTION_T:
- a0 = program[PC + 1];
- qansel_instruction(&stateVector, qubitCount, instr, program[PC + 1], 0, 0, 0);
- break;
- case QANSEL_INSTRUCTION_RX:
- a0 = program[PC + 1];
- qansel_instruction
- (
- &stateVector, qubitCount, instr, a0,
- M_PI / 2, -M_PI / 2, qansel_get_float(program, PC + 2) - (M_PI / 2)
- );
- break;
- case QANSEL_INSTRUCTION_RY:
- case QANSEL_INSTRUCTION_U1:
- a0 = program[PC + 1];
- qansel_instruction
- (
- &stateVector, qubitCount, instr, a0,
- qansel_get_float(program, PC + 2), 0, 0
- );
- break;
- case QANSEL_INSTRUCTION_RZ:
- a0 = program[PC + 1];
- qansel_instruction
- (
- &stateVector, qubitCount, instr, a0,
- 0, 0, qansel_get_float(program, PC + 2)
- );
- break;
- case QANSEL_INSTRUCTION_U2:
- a0 = program[PC + 1];
- qansel_instruction
- (
- &stateVector, qubitCount, instr, a0,
- qansel_get_float(program, PC + 2),
- qansel_get_float(program, PC + 2 + sizeof(float)),
- 0
- );
- break;
- case QANSEL_INSTRUCTION_U3:
- a0 = program[PC + 1];
- qansel_instruction
- (
- &stateVector, qubitCount, instr, a0,
- qansel_get_float(program, PC + 2),
- qansel_get_float(program, PC + 2 + sizeof(float)),
- qansel_get_float(program, PC + 2 + sizeof(float) * 2)
- );
- break;
- case QANSEL_INSTRUCTION_CX:
- a0 = program[PC + 1];
- a1 = program[PC + 2];
- qansel_cnot(&stateVector, qubitCount, a0, a1);
- break;
- case QANSEL_INSTRUCTION_SWAP:
- a0 = program[PC + 1];
- a1 = program[PC + 2];
- qansel_swap(&stateVector, qubitCount, a0, a1);
- break;
- case QANSEL_INSTRUCTION_CCX:
- a0 = program[PC + 1];
- a1 = program[PC + 2];
- a2 = program[PC + 3];
- qansel_toffoli(&stateVector, qubitCount, a0, a1, a2);
- break;
- case QANSEL_INSTRUCTION_CSWAP:
- a0 = program[PC + 1];
- a1 = program[PC + 2];
- a2 = program[PC + 3];
- qansel_fredkin(&stateVector, qubitCount, a0, a1, a2);
- break;
- case QANSEL_INSTRUCTION_MEASURE:
- a0 = program[PC + 1];
- a1 = program[PC + 2] - 0x10;
- bitVector[a1] = qansel_measure(&stateVector, qubitCount, a0);
- break;
- case QANSEL_INSTRUCTION_BORN:
- a0 = program[PC + 1];
- qansel_born(&stateVector, PC, qubitCount, a0);
- break;
- case QANSEL_INSTRUCTION_DENSITY:
- a0 = program[PC + 1];
- qansel_density_or_print(&stateVector, bitVector, 1, bitCount, qubitCount, a0);
- break;
- case QANSEL_INSTRUCTION_PRINT:
- a0 = program[PC + 1];
- qansel_density_or_print(&stateVector, bitVector, 0, bitCount, qubitCount, a0);
- break;
- case QANSEL_INSTRUCTION_BARRIER:
- a0 = program[PC + 1];
- break;
- case QANSEL_INSTRUCTION_RESET:
- a0 = program[PC + 1];
- qansel_reset(&stateVector, bitVector, qubitCount, bitCount, a0);
- break;
- case QANSEL_INSTRUCTION_HVAR:
- HIDDEN_VARIABLE = 1;
- float tmp1 = qansel_get_float(program, PC + 1);
- unsigned int tmp2;
- memcpy(&tmp2, &tmp1, sizeof(unsigned int));
- srand(tmp2);
- break;
- case QANSEL_INSTRUCTION_RAND:
- HIDDEN_VARIABLE = 0;
- break;
- case QANSEL_INSTRUCTION_IF_E:
- a0 = program[PC + 1];
- tmp = qansel_get_short(program, PC + 2);
- flags = qansel_compare(bitVector, bitCount, PC, a0, tmp);
- skip = 1; if (flags & QANSEL_FLAGS_EQUAL) skip = 0;
- break;
- case QANSEL_INSTRUCTION_IF_NE:
- a0 = program[PC + 1];
- tmp = qansel_get_short(program, PC + 2);
- flags = qansel_compare(bitVector, bitCount, PC, a0, tmp);
- skip = 1; if (!(flags & QANSEL_FLAGS_EQUAL)) skip = 0;
- break;
- case QANSEL_INSTRUCTION_IF_G:
- a0 = program[PC + 1];
- tmp = qansel_get_short(program, PC + 2);
- flags = qansel_compare(bitVector, bitCount, PC, a0, tmp);
- skip = 1; if (flags & QANSEL_FLAGS_GREATER) skip = 0;
- break;
- case QANSEL_INSTRUCTION_IF_GE:
- a0 = program[PC + 1];
- tmp = qansel_get_short(program, PC + 2);
- flags = qansel_compare(bitVector, bitCount, PC, a0, tmp);
- skip = 1; if ((flags & QANSEL_FLAGS_GREATER) && (flags & QANSEL_FLAGS_EQUAL)) skip = 0;
- break;
- case QANSEL_INSTRUCTION_IF_L:
- a0 = program[PC + 1];
- tmp = qansel_get_short(program, PC + 2);
- flags = qansel_compare(bitVector, bitCount, PC, a0, tmp);
- skip = 1; if (flags & QANSEL_FLAGS_LESSER) skip = 0;
- break;
- case QANSEL_INSTRUCTION_IF_LE:
- a0 = program[PC + 1];
- tmp = qansel_get_short(program, PC + 2);
- flags = qansel_compare(bitVector, bitCount, PC, a0, tmp);
- skip = 1; if ((flags & QANSEL_FLAGS_LESSER) && (flags & QANSEL_FLAGS_EQUAL)) skip = 0;
- break;
- case QANSEL_INSTRUCTION_SAMPLE: break;
-
- }
- }
- PC += next;
- }
- if (outputBitVector != NULL)
- {
- for (int i = 0; i < bitCount; i++)
- {
- outputBitVector[i] = bitVector[i];
- }
- }
- cpx_mtx_free(&stateVector);
-}
-
-void qansel_execute(unsigned char* buff, int sizeofbuff)
-{
- struct timespec ts;
- clock_gettime(CLOCK_MONOTONIC, &ts);
- float seed = (float)((unsigned long)ts.tv_sec * 1000000000LL + ts.tv_nsec);
- qansel_rand_s(seed);
-
- unsigned short vals;
- float valf;
- int pos = 0;
-
- int qubitCount, bitCount, sample;
- qansel_crawl(buff, sizeofbuff, &qubitCount, &bitCount, &sample);
- if (sample != 0xFF)
- {
- unsigned short stats[65536];
- for (unsigned int i = 0; i < (1 << bitCount); i++)
- {
- stats[i] = 0;
- }
- unsigned char bitVect[bitCount];
- memset(bitVect, 0, bitCount);
- for (int i = 0; i < bitCount; i++) bitVect[i] = 0;
- unsigned int shots = 1000;
- for (unsigned int i = 0; i < shots; i++)
- {
- qansel_run(buff, sizeofbuff, qubitCount, bitCount, bitVect);
- unsigned short stat = 0;
- for (signed char j = bitCount - 1; j >= 0; j--)
- {
- stat = (stat << 1) | bitVect[j];
- }
- stats[stat]++;
- }
- unsigned int count = 0;
- for (unsigned int i = 0; i < (1 << bitCount); i++)
- {
- unsigned int tmp = i;
- for (unsigned char j = 0; j < bitCount; j++)
- {
- unsigned char bit = (tmp >> (bitCount - 1) & 1);
- if (j == (bitCount - sample - 1) && bit)
- {
- count += stats[i];
- }
- if (sample == 0x0F)
- {
- putchar('0' + bit);
- }
- tmp <<= 1;
- }
- if (sample == 0x0F)
- {
- printf(": %.1f%%\n", ((float)stats[i] / (float)shots) * (float)100);
- }
- }
- if (sample != 0x0F)
- {
- float prob = ((float)count / (float)shots) * (float)100;
- printf("0: %.1f%%\n", ((float)100)-prob);
- printf("1: %.1f%%\n", prob);
- }
- }
- else
- {
- qansel_run(buff, sizeofbuff, qubitCount, bitCount, NULL);
- }
-}
}
}
-void display_wait(uint32_t i)
-{
- SDL_Delay(i);
-}
-
-void display(cpx_mtx_t* stateVector, uint8_t qubitCount)
+int display(cpx_mtx_t* stateVector, uint8_t qubitCount, int delay)
{
+ if (qubitCount > 8)
+ {
+ fprintf(stderr, "QAnsel warning: Too many quantum bits to be displayed.\n");
+ return 0;
+ }
uint32_t qubitCountPow2 = (uint32_t)pow(2, qubitCount);
static uint8_t displayInitialized = 0;
static SDL_Window* window = NULL;
- static SDL_Surface* surface = NULL;
static SDL_Renderer* renderer = NULL;
+ static cpx_mtx_t oldStateVector;
int SCREEN_WIDTH = 640 * 2;
int SCREEN_HEIGHT = 480;
int SCREEN_HALF = SCREEN_HEIGHT / 2;
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
- return;
+ cpx_mtx_free(&oldStateVector);
+ displayInitialized = 0;
+ return delay;
}
if (displayInitialized == 0)
{
if (SDL_Init(SDL_INIT_VIDEO))
{
- fprintf(stderr, "Failed to open graphical window.\n");
+ fprintf(stderr, "QAnsel: Failed to open graphical window.\n");
exit(1);
}
window = SDL_CreateWindow
);
if (window == NULL)
{
- fprintf(stderr, "Failed to open graphical window.\n");
+ fprintf(stderr, "QAnsel: Failed to open graphical window.\n");
exit(1);
}
- renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_SOFTWARE);
+ renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
if (renderer == NULL)
{
- fprintf(stderr, "Failed to open graphical window.\n");
+ fprintf(stderr, "QAnsel: Failed to open graphical window.\n");
exit(1);
}
+ cpx_mtx_init(&oldStateVector, stateVector->rows, stateVector->cols);
+ cpx_mtx_copy(&oldStateVector, stateVector);
displayInitialized = 1;
}
+ else if (cpx_mtx_cmp(&oldStateVector, stateVector) == 0)
+ {
+ return delay;
+ }
+ cpx_mtx_copy(&oldStateVector, stateVector);
+
SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0x00, 0xFF);
SDL_RenderClear(renderer);
SDL_SetRenderDrawColor(renderer, 0x00, 0xFF, 0x00, 0x00);
i0 = i1;
}
+ SDL_Event windowEvent;
+ if (SDL_PollEvent(&windowEvent))
+ {
+ if (SDL_QUIT == windowEvent.type)
+ {
+ delay = 0;
+ }
+ }
+
SDL_RenderPresent(renderer); // Update screen.
- SDL_Delay(500); // Wait for two seconds.
+ if (delay != 255)
+ {
+ SDL_Delay(100 * delay);
+ }
+ return delay;
}
\ No newline at end of file
--- /dev/null
+int qansel_read_script(char* script, char*** chunksReturn, int** chunkLinesReturn, int* countReturn)
+{
+ int scriptSize = strlen(script);
+ if (scriptSize > QANSEL_MAX_SIZE)
+ {
+ fprintf(stderr, "QAnsel: The source is too large.\n");
+ return 0;
+ }
+ char* line = malloc(0);
+ char** chunks = malloc(0);
+ int* chunksAssociatedLines = malloc(0);
+ int lineCount = 1;
+ int lineLen = 0;
+ int chunkCount = 0;
+ int inComment = 0;
+ for (int i = 0; i < scriptSize; i++)
+ {
+ int charactersLeft = scriptSize - i;
+ if (script[i] == '\n')
+ {
+ lineCount++;
+ inComment = 0;
+ }
+ else if (charactersLeft >= 2 && script[i] == '/' && script[i + 1] == '/')
+ {
+ inComment = 1;
+ }
+ else if (!inComment && script[i] != ';' && script[i] != '{' && script[i] != '}')
+ {
+ line = realloc(line, lineLen + 1);
+ line[lineLen++] = script[i] == '\t' ? ' ' : script[i];
+ if (script[i] == ')' && lineLen > 2)
+ {
+ for (int j = 0; j < lineLen - 1; j++)
+ {
+ if ( (line[j] == 'i' || line[j] == 'I') && (line[j + 1] == 'f' || line[j + 1] == 'F') )
+ {
+ line = realloc(line, lineLen + 1);
+ line[lineLen++] = 0;
+ chunks = realloc(chunks, (chunkCount + 1) * sizeof(char*));
+ chunksAssociatedLines = realloc(chunksAssociatedLines, (chunkCount + 1) * sizeof(int));
+ chunks[chunkCount] = line;
+ chunksAssociatedLines[chunkCount++] = lineCount;
+ line = malloc(0);
+ lineLen = 0;
+ break;
+ }
+ }
+ }
+ }
+ else if (!inComment && (script[i] == '{' || script[i] == '}'))
+ {
+ if (lineLen > 0)
+ {
+ line = realloc(line, lineLen + 1);
+ line[lineLen++] = 0;
+ chunks = realloc(chunks, (chunkCount + 1) * sizeof(char*));
+ chunksAssociatedLines = realloc(chunksAssociatedLines, (chunkCount + 1) * sizeof(int));
+ chunks[chunkCount] = line;
+ chunksAssociatedLines[chunkCount++] = lineCount;
+ line = malloc(2);
+ }
+ else
+ {
+ line = realloc(line, 2);
+ }
+ line[0] = script[i];
+ line[1] = 0;
+ chunks = realloc(chunks, (chunkCount + 1) * sizeof(char*));
+ chunksAssociatedLines = realloc(chunksAssociatedLines, (chunkCount + 1) * sizeof(int));
+ chunks[chunkCount] = line;
+ chunksAssociatedLines[chunkCount++] = lineCount;
+ line = malloc(0);
+ lineLen = 0;
+ }
+ else if (!inComment && script[i] == ';')
+ {
+ if (lineLen > 0)
+ {
+ line = realloc(line, lineLen + 1);
+ line[lineLen++] = 0;
+ chunks = realloc(chunks, (chunkCount + 1) * sizeof(char*));
+ chunksAssociatedLines = realloc(chunksAssociatedLines, (chunkCount + 1) * sizeof(int));
+ chunks[chunkCount] = line;
+ chunksAssociatedLines[chunkCount++] = lineCount;
+ line = malloc(0);
+ lineLen = 0;
+ }
+ }
+ }
+ if (lineLen > 0)
+ {
+ line = realloc(line, lineLen + 1);
+ line[lineLen++] = 0;
+ chunks = realloc(chunks, (chunkCount + 1) * sizeof(char*));
+ chunksAssociatedLines = realloc(chunksAssociatedLines, (chunkCount + 1) * sizeof(int));
+ chunks[chunkCount] = line;
+ chunksAssociatedLines[chunkCount++] = lineCount;
+ }
+ else
+ {
+ free(line);
+ }
+ for (int i = 0; i < chunkCount; i++)
+ {
+ int len = strlen(chunks[i]);
+ for (int j = 0; j < len; j++)
+ {
+ if (chunks[i][j] >= 'A' && chunks[i][j] <= 'Z')
+ {
+ chunks[i][j] += 'a' - 'A';
+ }
+ }
+ }
+ *chunksReturn = chunks;
+ *chunkLinesReturn = chunksAssociatedLines;
+ *countReturn = chunkCount;
+ return 1;
+}
+
+float qansel_parse_float_part(char* neg, char* str)
+{
+ float ret;
+ int len = strlen(str);
+ if (len > 2)
+ {
+ ret = atof(str);
+ if (str[len - 2] == 'p' && str[len - 1] == 'i')
+ {
+ ret *= M_PI;
+ }
+ }
+ else if (strcmp(str, "pi") == 0)
+ {
+ ret = M_PI;
+ }
+ else
+ {
+ ret = atof(str);
+ }
+ if (strcmp(neg, "-") == 0)
+ {
+ ret *= -1;
+ }
+ return ret;
+}
+
+int qansel_parse_float(char* str, float* returnFloat)
+{
+ *returnFloat = 0;
+ const char expr[] = "^(-|)([0-9][0-9]*\\.[0-9]*|[0-9][0-9]*|[0-9][0-9]*\\.[0-9]*pi|[0-9][0-9]*pi|pi)([/](-|)([0-9][0-9]*\\.[0-9]*|[0-9][0-9]*|[0-9][0-9]*\\.[0-9]*pi|[0-9][0-9]*pi|pi)|)$";
+ regex_t regex;
+ regmatch_t regmatches[10];
+ if (regcomp(®ex, expr, REG_EXTENDED | REG_ICASE)) return 0;
+ int ret = regexec(®ex, str, 10, regmatches, 0);
+ if (!ret)
+ {
+ int strbeg = regmatches[1].rm_so;
+ int strlen = regmatches[1].rm_eo - regmatches[1].rm_so;
+ char neg1[strlen + 1];
+ memcpy(neg1, str + strbeg, strlen);
+ neg1[strlen] = 0;
+
+ strbeg = regmatches[2].rm_so;
+ strlen = regmatches[2].rm_eo - regmatches[2].rm_so;
+ char numer[strlen + 1];
+ memcpy(numer, str + strbeg, strlen);
+ numer[strlen] = 0;
+ *returnFloat = qansel_parse_float_part(neg1, numer);
+
+ if (regmatches[3].rm_eo > regmatches[3].rm_so)
+ {
+ strbeg = regmatches[4].rm_so;
+ strlen = regmatches[4].rm_eo - regmatches[4].rm_so;
+ char neg2[strlen + 1];
+ memcpy(neg2, str + strbeg, strlen);
+ neg2[strlen] = 0;
+
+ strbeg = regmatches[5].rm_so;
+ strlen = regmatches[5].rm_eo - regmatches[5].rm_so;
+ char denom[strlen + 1];
+ memcpy(denom, str + strbeg, strlen);
+ denom[strlen] = 0;
+
+ float fdenom = qansel_parse_float_part(neg2, denom);
+ *returnFloat /= fdenom;
+ }
+ }
+ else if (ret == REG_NOMATCH)
+ {
+ return 0;
+ }
+ else
+ {
+ char errbuf[100];
+ regerror(ret, ®ex, errbuf, sizeof(errbuf));
+ fprintf(stderr, "QAnsel: %s.\n", errbuf);
+ exit(1);
+ }
+ regfree(®ex);
+
+ return 1;
+}
+
+int qansel_process_chunk(int index, char* chunk, int line, regmatch_t* regmatches, int* qubitCount, int* bitCount, unsigned char** binary, int* binarySize)
+{
+ unsigned short s0;
+ float d0, d1, d2;
+ unsigned char instr = 0;
+ unsigned char a0 = 0;
+ unsigned char a1 = 0;
+ unsigned char a2 = 0;
+ if (index == 0) //qreg
+ {
+ if (*qubitCount > 0)
+ {
+ fprintf(stderr, "QAnsel on line %i: Qubits can only be initialized once.\n", line);
+ return 0;
+ }
+ int strbeg = regmatches[1].rm_so;
+ int strlen = regmatches[1].rm_eo - regmatches[1].rm_so;
+ char tmp[strlen + 1];
+ memcpy(tmp, chunk + strbeg, strlen);
+ tmp[strlen] = 0;
+ int nump = atoi(tmp);
+ if (nump > QANSEL_QUBIT_LIMIT)
+ {
+ fprintf(stderr, "QAnsel on line %i: Initialized qubits cannot exceed %i.\n", line, QANSEL_QUBIT_LIMIT);
+ return 0;
+ }
+ *qubitCount = nump;
+ }
+ else if (index == 1) //creg
+ {
+ if (*bitCount > 0)
+ {
+ fprintf(stderr, "QAnsel on line %i: Classical bits can only be initialized once.\n", line);
+ return 0;
+ }
+ int strbeg = regmatches[1].rm_so;
+ int strlen = regmatches[1].rm_eo - regmatches[1].rm_so;
+ char tmp[strlen + 1];
+ memcpy(tmp, chunk + strbeg, strlen);
+ tmp[strlen] = 0;
+ int nump = atoi(tmp);
+ if (nump > QANSEL_QUBIT_LIMIT)
+ {
+ fprintf(stderr, "QAnsel on line %i: Initialized classical bits cannot exceed %i.\n", line, QANSEL_QUBIT_LIMIT);
+ return 0;
+ }
+ *bitCount = nump;
+ }
+ else if (index == 2 || index == 3 || index == 4 || index == 5) //single qubit instructions
+ {
+ if (*qubitCount == 0)
+ {
+ fprintf(stderr, "QAnsel on line %i: Quantum bit instruction used prior to initialization.\n", line);
+ return 0;
+ }
+ int rmp = 1;
+ {
+ int strbeg = regmatches[rmp].rm_so;
+ int strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so;
+ rmp++;
+ char tmp[strlen + 1];
+ memcpy(tmp, chunk + strbeg, strlen);
+ tmp[strlen] = 0;
+ if (strcmp(tmp, "rx") == 0) instr = QANSEL_INSTRUCTION_RX;
+ else if (strcmp(tmp, "ry") == 0) instr = QANSEL_INSTRUCTION_RY;
+ else if (strcmp(tmp, "rz") == 0) instr = QANSEL_INSTRUCTION_RZ;
+ else if (strcmp(tmp, "u1") == 0) instr = QANSEL_INSTRUCTION_U1;
+ else if (strcmp(tmp, "u2") == 0) instr = QANSEL_INSTRUCTION_U2;
+ else if (strcmp(tmp, "u3") == 0) instr = QANSEL_INSTRUCTION_U3;
+ else if (strcmp(tmp, "u") == 0) instr = QANSEL_INSTRUCTION_U3;
+ else if (strcmp(tmp, "reset") == 0) instr = QANSEL_INSTRUCTION_RESET;
+ else if (strcmp(tmp, "barrier") == 0) instr = QANSEL_INSTRUCTION_BARRIER;
+ else if (strcmp(tmp, "born") == 0) instr = QANSEL_INSTRUCTION_BORN;
+ else if (strcmp(tmp, "density") == 0) instr = QANSEL_INSTRUCTION_DENSITY;
+ else if (strcmp(tmp, "print") == 0) instr = QANSEL_INSTRUCTION_PRINT;
+ else if (strcmp(tmp, "not") == 0) instr = QANSEL_INSTRUCTION_X;
+ else if (strcmp(tmp, "x") == 0) instr = QANSEL_INSTRUCTION_X;
+ else if (strcmp(tmp, "y") == 0) instr = QANSEL_INSTRUCTION_Y;
+ else if (strcmp(tmp, "z") == 0) instr = QANSEL_INSTRUCTION_Z;
+ else if (strcmp(tmp, "h") == 0) instr = QANSEL_INSTRUCTION_H;
+ else if (strcmp(tmp, "s") == 0) instr = QANSEL_INSTRUCTION_S;
+ else if (strcmp(tmp, "t") == 0) instr = QANSEL_INSTRUCTION_T;
+ }
+ for (int i = 0; i < (index == 2 ? 0 : (index == 3 ? 1 : (index == 4 ? 2 : 3))); i++)
+ {
+ int strbeg = regmatches[rmp].rm_so;
+ int strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so;
+ rmp++;
+ char tmp[strlen + 1];
+ memcpy(tmp, chunk + strbeg, strlen);
+ tmp[strlen] = 0;
+ if (!qansel_parse_float(tmp, (i == 0 ? &d0 : (i == 1 ? &d1 : &d2))))
+ {
+ fprintf(stderr, "QAnsel on line %i: Invalid rotation value.\n", line);
+ return 0;
+ }
+ }
+ {
+ int strbeg = regmatches[rmp].rm_so;
+ int strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so;
+ rmp++;
+ if (strlen > 0)
+ {
+ strbeg = regmatches[rmp].rm_so;
+ strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so;
+ rmp++;
+ char tmp[strlen + 1];
+ memcpy(tmp, chunk + strbeg, strlen);
+ tmp[strlen] = 0;
+ a0 = atoi(tmp);
+ if (a0 >= *qubitCount)
+ {
+ fprintf(stderr, "QAnsel on line %i: Index `%i` exceeds allocated quantum bits.\n", line, a0);
+ return 0;
+ }
+ }
+ else
+ {
+ a0 = 0x0F;
+ if (instr == QANSEL_INSTRUCTION_DENSITY)
+ {
+ fprintf(stderr, "QAnsel on line %i: Density matrices can only be produced for individual qubits.\n", line, a0);
+ return 0;
+ }
+ }
+ }
+ switch (index)
+ {
+ case 2:
+ *binarySize += 2;
+ *binary = realloc(*binary, (*binarySize));
+ (*binary)[(*binarySize) - 2] = instr;
+ (*binary)[(*binarySize) - 1] = a0;
+ break;
+ case 3:
+ *binarySize += 2 + sizeof(float) * 1;
+ *binary = realloc(*binary, (*binarySize));
+ (*binary)[(*binarySize) - 2 - sizeof(float) * 1] = instr;
+ (*binary)[(*binarySize) - 1 - sizeof(float) * 1] = a0;
+ memcpy((*binary) + ((*binarySize) - sizeof(float)), &d0, sizeof(float));
+ break;
+ case 4:
+ *binarySize += 2 + sizeof(float) * 2;
+ *binary = realloc(*binary, (*binarySize));
+ (*binary)[(*binarySize) - 2 - sizeof(float) * 2] = instr;
+ (*binary)[(*binarySize) - 1 - sizeof(float) * 2] = a0;
+ memcpy((*binary) + ((*binarySize) - sizeof(float) * 2), &d0, sizeof(float));
+ memcpy((*binary) + ((*binarySize) - sizeof(float) * 1), &d1, sizeof(float));
+ break;
+ case 5:
+ *binarySize += 2 + sizeof(float) * 3;
+ *binary = realloc(*binary, (*binarySize));
+ (*binary)[(*binarySize) - 2 - sizeof(float) * 3] = instr;
+ (*binary)[(*binarySize) - 1 - sizeof(float) * 3] = a0;
+ memcpy((*binary) + ((*binarySize) - sizeof(float) * 3), &d0, sizeof(float));
+ memcpy((*binary) + ((*binarySize) - sizeof(float) * 2), &d1, sizeof(float));
+ memcpy((*binary) + ((*binarySize) - sizeof(float) * 1), &d2, sizeof(float));
+ break;
+ }
+ }
+ else if (index == 6) //measure instruction
+ {
+ if (*qubitCount == 0)
+ {
+ fprintf(stderr, "QAnsel on line %i: Quantum bit instruction used prior to initialization.\n", line);
+ return 0;
+ }
+ if (*bitCount == 0)
+ {
+ fprintf(stderr, "QAnsel on line %i: Classical bit instruction used prior to initialization.\n", line);
+ return 0;
+ }
+ int rmp = 1;
+ {
+ int strbeg = regmatches[rmp].rm_so;
+ int strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so;
+ rmp++;
+ if (strlen > 0)
+ {
+ strbeg = regmatches[rmp].rm_so;
+ strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so;
+ rmp++;
+ char tmp[strlen + 1];
+ memcpy(tmp, chunk + strbeg, strlen);
+ tmp[strlen] = 0;
+ a0 = atoi(tmp);
+ if (a0 >= *qubitCount)
+ {
+ fprintf(stderr, "QAnsel on line %i: Index `%i` exceeds allocated quantum bits.\n", line, a0);
+ return 0;
+ }
+ }
+ else
+ {
+ a0 = 0x0F;
+ }
+ }
+ {
+ int strbeg = regmatches[rmp].rm_so;
+ int strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so;
+ rmp++;
+ if (strlen > 0)
+ {
+ strbeg = regmatches[rmp].rm_so;
+ strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so;
+ rmp++;
+ char tmp[strlen + 1];
+ memcpy(tmp, chunk + strbeg, strlen);
+ tmp[strlen] = 0;
+ a1 = atoi(tmp);
+ if (a1 >= *bitCount)
+ {
+ fprintf(stderr, "QAnsel on line %i: Index `%i` exceeds allocated classical bits.\n", line, a1);
+ return 0;
+ }
+ a1 += 0x10;
+ }
+ else
+ {
+ a1 = 0x1F;
+ }
+ }
+ *binarySize += 3;
+ *binary = realloc(*binary, (*binarySize));
+ (*binary)[(*binarySize) - 3] = QANSEL_INSTRUCTION_MEASURE;
+ (*binary)[(*binarySize) - 2] = a0;
+ (*binary)[(*binarySize) - 1] = a1;
+ }
+ else if (index == 7) //classical bit instructions
+ {
+ if (*bitCount == 0)
+ {
+ fprintf(stderr, "QAnsel on line %i: Classical bit instruction used prior to initialization.\n", line);
+ return 0;
+ }
+ int rmp = 1;
+ {
+ int strbeg = regmatches[rmp].rm_so;
+ int strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so;
+ rmp++;
+ char tmp[strlen + 1];
+ memcpy(tmp, chunk + strbeg, strlen);
+ tmp[strlen] = 0;
+ if (strcmp(tmp, "sample") == 0) instr = QANSEL_INSTRUCTION_SAMPLE;
+ else if (strcmp(tmp, "reset") == 0) instr = QANSEL_INSTRUCTION_RESET;
+ else if (strcmp(tmp, "print") == 0) instr = QANSEL_INSTRUCTION_PRINT;
+ }
+ {
+ int strbeg = regmatches[rmp].rm_so;
+ int strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so;
+ rmp++;
+ if (strlen > 0)
+ {
+ strbeg = regmatches[rmp].rm_so;
+ strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so;
+ rmp++;
+ char tmp[strlen + 1];
+ memcpy(tmp, chunk + strbeg, strlen);
+ tmp[strlen] = 0;
+ a0 = atoi(tmp);
+ if (a0 >= *bitCount)
+ {
+ fprintf(stderr, "QAnsel on line %i: Index `%i` exceeds allocated classical bits.\n", line, a0);
+ return 0;
+ }
+ a0 += 0x10;
+ }
+ else
+ {
+ a0 = 0x1F;
+ }
+ }
+ *binarySize += 2;
+ *binary = realloc(*binary, (*binarySize));
+ (*binary)[(*binarySize) - 2] = instr;
+ (*binary)[(*binarySize) - 1] = a0;
+ }
+ else if (index == 8 || index == 9) //double qubit instructions
+ {
+ if (*qubitCount == 0)
+ {
+ fprintf(stderr, "QAnsel on line %i: Quantum bit instruction used prior to initialization.\n", line);
+ return 0;
+ }
+ int rmp = 1;
+ {
+ int strbeg = regmatches[rmp].rm_so;
+ int strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so;
+ rmp++;
+ char tmp[strlen + 1];
+ memcpy(tmp, chunk + strbeg, strlen);
+ tmp[strlen] = 0;
+ if (strcmp(tmp, "cx") == 0) instr = QANSEL_INSTRUCTION_CX;
+ if (strcmp(tmp, "cnot") == 0) instr = QANSEL_INSTRUCTION_CX;
+ if (strcmp(tmp, "ccnot") == 0) instr = QANSEL_INSTRUCTION_CCX;
+ if (strcmp(tmp, "ccx") == 0) instr = QANSEL_INSTRUCTION_CCX;
+ else if (strcmp(tmp, "toffoli") == 0) instr = QANSEL_INSTRUCTION_CCX;
+ else if (strcmp(tmp, "cswap") == 0) instr = QANSEL_INSTRUCTION_CSWAP;
+ else if (strcmp(tmp, "fredkin") == 0) instr = QANSEL_INSTRUCTION_CSWAP;
+ }
+ for (int i = 0; i < (index == 8 ? 2 : 3); i++)
+ {
+ int strbeg = regmatches[rmp].rm_so;
+ int strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so;
+ rmp++;
+ char tmp[strlen + 1];
+ memcpy(tmp, chunk + strbeg, strlen);
+ tmp[strlen] = 0;
+ int tmpi = atoi(tmp);
+ if (tmpi >= *qubitCount)
+ {
+ fprintf(stderr, "QAnsel on line %i: Index `%i` exceeds allocated quantum bits.\n", line, tmpi);
+ return 0;
+ }
+ switch (i)
+ {
+ case 0: a0 = tmpi; break;
+ case 1: a1 = tmpi; break;
+ case 2: a2 = tmpi; break;
+ }
+ }
+ if (index == 8)
+ {
+ *binarySize += 3;
+ *binary = realloc(*binary, (*binarySize));
+ (*binary)[(*binarySize) - 3] = instr;
+ (*binary)[(*binarySize) - 2] = a0;
+ (*binary)[(*binarySize) - 1] = a1;
+ }
+ else
+ {
+ *binarySize += 4;
+ *binary = realloc(*binary, (*binarySize));
+ (*binary)[(*binarySize) - 4] = instr;
+ (*binary)[(*binarySize) - 3] = a0;
+ (*binary)[(*binarySize) - 2] = a1;
+ (*binary)[(*binarySize) - 1] = a2;
+ }
+ }
+ else if (index == 10) //if instructions
+ {
+ if (*bitCount == 0)
+ {
+ fprintf(stderr, "QAnsel on line %i: Classical bit instruction used prior to initialization.\n", line);
+ return 0;
+ }
+ int rmp = 1;
+ {
+ int strbeg = regmatches[rmp].rm_so;
+ int strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so;
+ rmp++;
+ if (strlen > 0)
+ {
+ strbeg = regmatches[rmp].rm_so;
+ strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so;
+ rmp++;
+ char tmp[strlen + 1];
+ memcpy(tmp, chunk + strbeg, strlen);
+ tmp[strlen] = 0;
+ a0 = atoi(tmp);
+ if (a0 >= *bitCount)
+ {
+ fprintf(stderr, "QAnsel on line %i: Index `%i` exceeds allocated classical bits.\n", line, a0);
+ return 0;
+ }
+ a0 += 0x10;
+ }
+ else
+ {
+ a0 = 0x1F;
+ }
+ }
+ {
+ int strbeg = regmatches[rmp].rm_so;
+ int strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so;
+ rmp++;
+ char tmp[strlen + 1];
+ memcpy(tmp, chunk + strbeg, strlen);
+ tmp[strlen] = 0;
+ if (strlen == 0)
+ {
+ strbeg = regmatches[rmp].rm_so;
+ strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so;
+ rmp++;
+ char tmp[strlen + 1];
+ memcpy(tmp, chunk + strbeg, strlen);
+ tmp[strlen] = 0;
+ if (strcmp(tmp, "==") == 0) instr = QANSEL_INSTRUCTION_IF_E;
+ else if (strcmp(tmp, "!=") == 0) instr = QANSEL_INSTRUCTION_IF_NE;
+ else if (strcmp(tmp, "<>") == 0) instr = QANSEL_INSTRUCTION_IF_NE;
+ else if (strcmp(tmp, ">=") == 0) instr = QANSEL_INSTRUCTION_IF_GE;
+ else if (strcmp(tmp, "<=") == 0) instr = QANSEL_INSTRUCTION_IF_LE;
+ else if (strcmp(tmp, ">") == 0) instr = QANSEL_INSTRUCTION_IF_G;
+ else if (strcmp(tmp, "<") == 0) instr = QANSEL_INSTRUCTION_IF_L;
+ }
+ else
+ {
+ if (strcmp(tmp, "==") == 0) instr = QANSEL_INSTRUCTION_IF_E;
+ else if (strcmp(tmp, "!=") == 0) instr = QANSEL_INSTRUCTION_IF_NE;
+ else if (strcmp(tmp, "<>") == 0) instr = QANSEL_INSTRUCTION_IF_NE;
+ else if (strcmp(tmp, ">=") == 0) instr = QANSEL_INSTRUCTION_IF_GE;
+ else if (strcmp(tmp, "<=") == 0) instr = QANSEL_INSTRUCTION_IF_LE;
+ else if (strcmp(tmp, ">") == 0) instr = QANSEL_INSTRUCTION_IF_G;
+ else if (strcmp(tmp, "<") == 0) instr = QANSEL_INSTRUCTION_IF_L;
+ }
+ }
+ {
+ int strbeg = regmatches[rmp].rm_so;
+ int strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so;
+ rmp++;
+ char tmp[strlen + 1];
+ memcpy(tmp, chunk + strbeg, strlen);
+ tmp[strlen] = 0;
+ s0 = (unsigned short)atoi(tmp);
+ }
+ //printf("%s(%02x,%i)\n", qansel_instruction_to_string(instr), a0, s0);
+ *binarySize += 2 + sizeof(unsigned short);
+ *binary = realloc(*binary, (*binarySize));
+ (*binary)[(*binarySize) - 2 - sizeof(unsigned short)] = instr;
+ (*binary)[(*binarySize) - 1 - sizeof(unsigned short)] = a0;
+ memcpy((*binary) + ((*binarySize) - sizeof(unsigned short)), &s0, sizeof(unsigned short));
+ }
+ else if (index == 11) //floating point settings
+ {
+ int rmp = 1;
+ {
+ int strbeg = regmatches[rmp].rm_so;
+ int strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so;
+ rmp++;
+ char tmp[strlen + 1];
+ memcpy(tmp, chunk + strbeg, strlen);
+ tmp[strlen] = 0;
+ if (strcmp(tmp, "hvar") == 0) instr = QANSEL_INSTRUCTION_HVAR;
+ }
+ {
+ int strbeg = regmatches[rmp].rm_so;
+ int strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so;
+ rmp++;
+ char tmp[strlen + 1];
+ memcpy(tmp, chunk + strbeg, strlen);
+ tmp[strlen] = 0;
+ if (!qansel_parse_float(tmp, &d0))
+ {
+ fprintf(stderr, "QAnsel on line %i: Syntax error.\n", line);
+ return 0;
+ }
+ }
+ *binarySize += 1 + sizeof(float);
+ *binary = realloc(*binary, (*binarySize));
+ (*binary)[(*binarySize) - 1 - sizeof(float)] = instr;
+ memcpy((*binary) + ((*binarySize) - sizeof(float)), &d0, sizeof(float));
+ }
+ else if (index == 12) //lone instructions
+ {
+ int rmp = 1;
+ {
+ int strbeg = regmatches[rmp].rm_so;
+ int strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so;
+ rmp++;
+ char tmp[strlen + 1];
+ memcpy(tmp, chunk + strbeg, strlen);
+ tmp[strlen] = 0;
+ if (strcmp(tmp, "rand") == 0) instr = QANSEL_INSTRUCTION_RAND;
+ else if (strcmp(tmp, "exit") == 0) instr = QANSEL_INSTRUCTION_EXIT;
+ }
+ *binarySize += 1;
+ *binary = realloc(*binary, (*binarySize));
+ (*binary)[(*binarySize) - 1] = instr;
+ }
+ return 1;
+}
+
+int qansel_process_chunks(char** chunks, int* associatedLines, int count, unsigned char** retBinary, int* retSize)
+{
+ unsigned char* binary = malloc(0);
+ int binarySize = 0;
+ int qubitCount = 0;
+ int bitCount = 0;
+ char errbuf[100];
+ regex_t regex;
+ regmatch_t regmatches[10];
+ const char regexes[][1024] =
+ {
+ "^\\s*qreg\\s*q\\s*\\[\\s*([0-9][0-9]*)\\s*\\]\\s*$",
+ "^\\s*creg\\s*c\\s*\\[\\s*([0-9][0-9]*)\\s*\\]\\s*$",
+ "^\\s*(x|y|z|h|s|t|reset|barrier|born|density|print)\\s*q\\s*(\\[\\s*([0-9][0-9]*)\\s*\\]\\s*|)$",
+ "^\\s*(rx|ry|rz|u1)\\(\\s*([-/0-9PI.]*)\\s*\\)\\s*q\\s*(\\[\\s*([0-9][0-9]*)\\s*\\]\\s*|)$",
+ "^\\s*(u2)\\(\\s*([-/0-9PI.]*)\\s*,\\s*([-/0-9PI.]*)\\s*\\)\\s*q\\s*(\\[\\s*([0-9][0-9]*)\\s*\\]\\s*|)$",
+ "^\\s*(u|u3)\\(\\s*([-/0-9PI.]*)\\s*,\\s*([-/0-9PI.]*)\\s*,\\s*([-/0-9PI.]*)\\s*\\)\\s*q\\s*(\\[\\s*([0-9][0-9]*)\\s*\\]\\s*|)$",
+ "^\\s*measure\\s*q\\s*(\\[\\s*([0-9][0-9]*)\\s*\\]\\s*)\\s*->\\s*c\\c*(\\[\\s*([0-9][0-9]*)\\s*\\]\\s*)$",
+ "^\\s*(sample|reset|print)\\s*c\\s*(\\[\\s*([0-9][0-9]*)\\s*\\]\\s*|)$",
+ "^\\s*(cx|cnot|swap)\\s*q\\s*\\[\\s*([0-9][0-9]*)\\s*\\]\\s*,\\s*q\\s*\\[\\s*([0-9]*)\\s*\\]\\s*$",
+ "^\\s*(ccx|toffoli|cswap|fredkin)\\s*q\\s*\\[\\s*([0-9][0-9]*)\\s*\\]\\s*,\\s*q\\s*\\[\\s*([0-9][0-9]*)\\s*\\]\\s*,\\s*q\\s*\\[\\s*([0-9][0-9]*)\\s*\\]\\s*$",
+ "^\\s*if\\s*\\(\\s*c\\s*(\\[\\s*([0-9][0-9]*)\\s*\\]|)\\s*(==|!=|<>|>=|<=|>|<)\\s*([0-9][0-9]*)\\s*\\).*\\s*$",
+ "^\\s*(hvar)\\s*([-/0-9PI.]*)\\s*$",
+ "^\\s*(rand|exit)\\s*$",
+ };
+ int ret, status = 0, found;
+ for (int i = 0; i < count; i++)
+ {
+ found = 0;
+ for (int j = 0; j < sizeof(regexes) / sizeof(regexes[0]); j++)
+ {
+ if (regcomp(®ex, regexes[j], REG_EXTENDED | REG_ICASE))
+ {
+ printf("QAnsel: Regex fatal error.\n");
+ return 0;
+ }
+ ret = regexec(®ex, chunks[i], 10, regmatches, 0);
+ regfree(®ex);
+ if (!ret)
+ {
+ found = 1;
+ status = qansel_process_chunk(j, chunks[i], associatedLines[i], regmatches, &qubitCount, &bitCount, &binary, &binarySize);
+ break;
+ }
+ else if (ret == REG_NOMATCH) {}
+ else
+ {
+ regerror(ret, ®ex, errbuf, sizeof(errbuf));
+ fprintf(stderr, "QAnsel: %s.\n", errbuf);
+ return 0;
+ }
+ }
+ if (!status) break;
+ if (!found)
+ {
+ fprintf(stderr, "QAnsel on line %i: Invalid syntax.\n", associatedLines[i]);
+ return 0;
+ }
+ }
+ *retBinary = binary;
+ *retSize = binarySize;
+ return status;
+}
+
+int qanselBuildFromSource(char* source, unsigned char** binary, int* binarySize)
+{
+ char** chunks;
+ int* chunksAssociatedLines;
+ int chunksCount;
+ int status = qansel_read_script(source, &chunks, &chunksAssociatedLines, &chunksCount);
+ if (!status) return 0;
+ status = qansel_process_chunks(chunks, chunksAssociatedLines, chunksCount, binary, binarySize);
+ for (int i = 0; i < chunksCount; i++) free(chunks[i]);
+ free(chunks);
+ free(chunksAssociatedLines);
+ free(source);
+ if (!status)
+ {
+ *binarySize = 0;
+ free(*binary);
+ return 0;
+ }
+ return 1;
+
+}
+
--- /dev/null
+#ifndef __QANSEL_H__
+#define __QANSEL_H__
+
+#define QANSEL_MAX_SIZE 1073741824
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <regex.h>
+#include <time.h>
+#include "complex.c"
+#include "gates.c"
+#include "display.c"
+#include "chacha20.c"
+#define QANSEL_QUBITS_MAX 14
+unsigned char QANSEL_QUBIT_LIMIT = QANSEL_QUBITS_MAX;
+unsigned char QANSEL_HIDDEN_VARIABLE = 0;
+unsigned char QANSEL_USE_DISPLAY = 0;
+unsigned char QANSEL_VERBOSE = 0;
+FILE* QANSEL_RANDOM_FILE = NULL;
+#define QANSEL_MODE_BARE 0
+#define QANSEL_MODE_THREADED 1
+#define QANSEL_MODE_METAL 2
+#define QANSEL_MODE_METAL_THREADED 3
+unsigned char QANSEL_MODE = QANSEL_MODE_BARE;
+//#define SPEED_TEST
+
+#define QANSEL_INSTRUCTION_X 0x10
+#define QANSEL_INSTRUCTION_Y 0x11
+#define QANSEL_INSTRUCTION_Z 0x12
+#define QANSEL_INSTRUCTION_H 0x13
+#define QANSEL_INSTRUCTION_S 0x14
+#define QANSEL_INSTRUCTION_T 0x15
+#define QANSEL_INSTRUCTION_RX 0x20
+#define QANSEL_INSTRUCTION_RY 0x21
+#define QANSEL_INSTRUCTION_RZ 0x22
+#define QANSEL_INSTRUCTION_U1 0x23
+#define QANSEL_INSTRUCTION_U2 0x24
+#define QANSEL_INSTRUCTION_U3 0x25
+#define QANSEL_INSTRUCTION_CX 0x30
+#define QANSEL_INSTRUCTION_SWAP 0x31
+#define QANSEL_INSTRUCTION_CCX 0x40
+#define QANSEL_INSTRUCTION_CSWAP 0x41
+#define QANSEL_INSTRUCTION_MEASURE 0xD0
+#define QANSEL_INSTRUCTION_SAMPLE 0xD1
+#define QANSEL_INSTRUCTION_DENSITY 0xD2
+#define QANSEL_INSTRUCTION_BORN 0xD3
+#define QANSEL_INSTRUCTION_IF_E 0xE1
+#define QANSEL_INSTRUCTION_IF_NE 0xE2
+#define QANSEL_INSTRUCTION_IF_G 0xE3
+#define QANSEL_INSTRUCTION_IF_GE 0xE4
+#define QANSEL_INSTRUCTION_IF_L 0xE5
+#define QANSEL_INSTRUCTION_IF_LE 0xE6
+#define QANSEL_INSTRUCTION_RAND 0xF0
+#define QANSEL_INSTRUCTION_HVAR 0xF1
+#define QANSEL_INSTRUCTION_RESET 0xF2
+#define QANSEL_INSTRUCTION_PRINT 0xF3
+#define QANSEL_INSTRUCTION_BARRIER 0xF4
+#define QANSEL_INSTRUCTION_EXIT 0xF5
+
+#define QANSEL_FLAGS_EQUAL 0b00001
+#define QANSEL_FLAGS_GREATER 0b00010
+#define QANSEL_FLAGS_LESSER 0b00100
+
+#endif
\ No newline at end of file