From 4c3956857bb4fbfe88ce39a4588a6326e618ace0 Mon Sep 17 00:00:00 2001 From: miha-q <> Date: Sat, 9 Mar 2024 20:53:46 -0500 Subject: [PATCH] Sat Mar 9 08:53:46 PM EST 2024 --- src/QAnsel.c | 785 +++---------------------------------- src/{core.c => bytecode.c} | 113 ++---- src/complex.c | 37 +- src/display.c | 49 ++- src/openqasm.c | 762 +++++++++++++++++++++++++++++++++++ src/qansel.h | 64 +++ 6 files changed, 981 insertions(+), 829 deletions(-) rename src/{core.c => bytecode.c} (91%) create mode 100644 src/openqasm.c create mode 100644 src/qansel.h diff --git a/src/QAnsel.c b/src/QAnsel.c index cb11e3a..9722181 100644 --- a/src/QAnsel.c +++ b/src/QAnsel.c @@ -1,751 +1,67 @@ -#include -#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; @@ -757,19 +73,16 @@ void main(int argc, char** argv) 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 diff --git a/src/core.c b/src/bytecode.c similarity index 91% rename from src/core.c rename to src/bytecode.c index dc32ab2..63cf248 100644 --- a/src/core.c +++ b/src/bytecode.c @@ -1,60 +1,3 @@ -#include -#include -#include -#include -#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]; @@ -100,7 +43,13 @@ const char* qansel_instruction_to_string(unsigned char instr) 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; @@ -113,25 +62,24 @@ float qansel_rand_h() } float qansel_rand_t() { - if (RANDOM_FILE) + if (QANSEL_RANDOM_FILE) { unsigned int num = 0; for (unsigned char i = 0; i < 4; i++) { - num = (num << 8) | fgetc(RANDOM_FILE); + num = (num << 8) | fgetc(QANSEL_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(); + 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) @@ -350,11 +298,11 @@ void qansel_instruction //us2 = get_time(); //printf("\tTranspose: %lu\n", us2 - us1); #else - if (MODE == MODE_METAL && tmp.cols >= 64) + 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 ((MODE == MODE_THREADED || MODE == MODE_METAL_THREADED) && tmp.cols >= 64) + 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); } @@ -388,11 +336,11 @@ void qansel_instruction us2 = get_time(); printf("\tBare: %lu\n", us2 - us1); #else - if ((MODE == MODE_METAL || MODE == MODE_METAL_THREADED) && tmp.cols >= 64) + 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 (MODE == MODE_THREADED && tmp.cols >= 64) + 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); } @@ -803,9 +751,9 @@ unsigned char qansel_compare(unsigned char* bitVector, int bitCount, int PC, uns return ret; } -void qansel_crawl(unsigned char* program, int programSize, int* qubitCount, int* bitCount, int* sample) +int qansel_crawl(unsigned char* program, int programSize, int* qubitCount, int* bitCount, int* sample) { - printf("Crawling program . . .\n"); + if (QANSEL_VERBOSE) printf("Crawling program . . .\n"); int PC = 0; *qubitCount = 0; *bitCount = 0; @@ -817,7 +765,7 @@ void qansel_crawl(unsigned char* program, int programSize, int* qubitCount, int* { if ((program[PC + 1] < 0x10 || program[PC + 1] > 0x1D) && program[PC + 1] != 0x1F) { - fprintf(stderr, "QAnsel (%04X): Invalid index.\n", PC); + if (QANSEL_VERBOSE) fprintf(stderr, "QAnsel (%04X): Invalid index.\n", PC); } else { @@ -827,21 +775,22 @@ void qansel_crawl(unsigned char* program, int programSize, int* qubitCount, int* if (next == 0) { printf("QAnsel (%04X): Invalid instruction 0x%02x.\n", PC, program[PC]); - exit(1); + 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); - exit(1); + return 0; } 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); + 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) @@ -853,7 +802,7 @@ void qansel_run(unsigned char* program, int programSize, int qubitCount, int bit cpx_mtx_t stateVector; cpx_mtx_init(&stateVector, 1, qubitCountPow2); cpx_mtx_set2(&stateVector, 0, 0, 1, 0); - //if (gfx) display(&stateVector, qubitCount); + 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; @@ -976,14 +925,14 @@ void qansel_run(unsigned char* program, int programSize, int qubitCount, int bit qansel_reset(&stateVector, bitVector, qubitCount, bitCount, a0); break; case QANSEL_INSTRUCTION_HVAR: - HIDDEN_VARIABLE = 1; + 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: - HIDDEN_VARIABLE = 0; + QANSEL_HIDDEN_VARIABLE = 0; break; case QANSEL_INSTRUCTION_IF_E: a0 = program[PC + 1]; @@ -1026,6 +975,7 @@ void qansel_run(unsigned char* program, int programSize, int qubitCount, int bit } } PC += next; + if (QANSEL_USE_DISPLAY) { QANSEL_USE_DISPLAY = display(&stateVector, qubitCount, QANSEL_USE_DISPLAY); } } if (outputBitVector != NULL) { @@ -1035,9 +985,11 @@ void qansel_run(unsigned char* program, int programSize, int qubitCount, int bit } } cpx_mtx_free(&stateVector); + if (QANSEL_USE_DISPLAY) { display(NULL, 0, 0); } + } -void qansel_execute(unsigned char* buff, int sizeofbuff) +int qanselExecuteBytecode(unsigned char* buff, int sizeofbuff) { struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); @@ -1049,7 +1001,11 @@ void qansel_execute(unsigned char* buff, int sizeofbuff) int pos = 0; int qubitCount, bitCount, sample; - qansel_crawl(buff, sizeofbuff, &qubitCount, &bitCount, &sample); + if (!qansel_crawl(buff, sizeofbuff, &qubitCount, &bitCount, &sample)) + { + return 0; + } + if (sample != 0xFF) { unsigned short stats[65536]; @@ -1104,4 +1060,5 @@ void qansel_execute(unsigned char* buff, int sizeofbuff) { qansel_run(buff, sizeofbuff, qubitCount, bitCount, NULL); } + return 1; } diff --git a/src/complex.c b/src/complex.c index f9a57b7..c1ab4e6 100644 --- a/src/complex.c +++ b/src/complex.c @@ -90,6 +90,40 @@ void cpx_mtx_get(cpx_mtx_t* m, int row, int col, cpx_t* n) 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); @@ -733,8 +767,7 @@ void cpx_mtx_knk_metal_2x2(float* ptrR, float* ptrA, float* ptrB, int rowsA, int 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; diff --git a/src/display.c b/src/display.c index 1862610..5b5ff66 100644 --- a/src/display.c +++ b/src/display.c @@ -20,18 +20,18 @@ void DrawThickLine(SDL_Renderer* renderer, int x1, int y1, int x2, int y2, int t } } -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; @@ -41,14 +41,16 @@ void display(cpx_mtx_t* stateVector, uint8_t qubitCount) 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 @@ -62,17 +64,25 @@ void display(cpx_mtx_t* stateVector, uint8_t qubitCount) ); 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); @@ -124,7 +134,20 @@ void display(cpx_mtx_t* stateVector, uint8_t qubitCount) 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 diff --git a/src/openqasm.c b/src/openqasm.c new file mode 100644 index 0000000..f451fa5 --- /dev/null +++ b/src/openqasm.c @@ -0,0 +1,762 @@ +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; + +} + diff --git a/src/qansel.h b/src/qansel.h new file mode 100644 index 0000000..ef55269 --- /dev/null +++ b/src/qansel.h @@ -0,0 +1,64 @@ +#ifndef __QANSEL_H__ +#define __QANSEL_H__ + +#define QANSEL_MAX_SIZE 1073741824 +#include +#include +#include +#include +#include +#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 -- 2.39.5