From: server Date: Sun, 10 Sep 2023 04:28:07 +0000 (-0400) Subject: Sun Sep 10 12:28:07 AM EDT 2023 X-Git-Url: http://www.foleosoft.com/?a=commitdiff_plain;h=36b7fca7faee53192b0bdeeb4b72bfe67c06056e;p=QAnsel.git Sun Sep 10 12:28:07 AM EDT 2023 --- 36b7fca7faee53192b0bdeeb4b72bfe67c06056e diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..9b20556 --- /dev/null +++ b/Makefile @@ -0,0 +1,2 @@ +all: + cd src && gcc QAnsel.c -g -o ../bin/QAnsel -lm -I/usr/include/SDL2 -D_REENTRANT -lSDL2 diff --git a/bin/QAnsel b/bin/QAnsel new file mode 100755 index 0000000..baa3cc7 Binary files /dev/null and b/bin/QAnsel differ diff --git a/examples/bb84.qsm b/examples/bb84.qsm new file mode 100644 index 0000000..a283806 --- /dev/null +++ b/examples/bb84.qsm @@ -0,0 +1,26 @@ +qreg q[2]; +creg c[1]; + +//Alice sends two bits 00 +h q[0]; +h q[1]; + +//Eve tries to measure the first +measure q[0] -> c[0]; + +//Bob applies the gate before measuring +h q[0]; +h q[1]; + +//The first should now be random noise +// while the second unmeasured one +// should be 0 +sample; + +//In a full BB84 Alice would randomly +// apply the gate or not apply the +// gate so Eve would have to guess +// and would inevitably end up +// turning the transferred bits +// into random noise whenever there +// is a wrong guess. \ No newline at end of file diff --git a/examples/bellstate.qsm b/examples/bellstate.qsm new file mode 100644 index 0000000..9168026 --- /dev/null +++ b/examples/bellstate.qsm @@ -0,0 +1,5 @@ +qreg q[2]; +h q[0]; +cx q[0], q[1]; + +sample; diff --git a/examples/encryption.qsm b/examples/encryption.qsm new file mode 100644 index 0000000..6be398b --- /dev/null +++ b/examples/encryption.qsm @@ -0,0 +1,6 @@ +qreg q[1]; +creg c[1]; +h q[0]; +measure q[0] -> c[0]; +print c; + diff --git a/examples/halfadder.qsm b/examples/halfadder.qsm new file mode 100644 index 0000000..af0f80b --- /dev/null +++ b/examples/halfadder.qsm @@ -0,0 +1,40 @@ +qreg q[3]; +creg c[2]; + +//0+0 +ccx q[0], q[1], q[2]; +cx q[0], q[1]; +measure q[1] -> c[0]; +measure q[2] -> c[1]; +print c; + +reset; + +//0+1 +x q[0]; +ccx q[0], q[1], q[2]; +cx q[0], q[1]; +measure q[1] -> c[0]; +measure q[2] -> c[1]; +print c; + +reset; + +//1+0 +x q[1]; +ccx q[0], q[1], q[2]; +cx q[0], q[1]; +measure q[1] -> c[0]; +measure q[2] -> c[1]; +print c; + +reset; + +//1+1 +x q[0]; +x q[1]; +ccx q[0], q[1], q[2]; +cx q[0], q[1]; +measure q[1] -> c[0]; +measure q[2] -> c[1]; +print c; \ No newline at end of file diff --git a/examples/swaptest.qsm b/examples/swaptest.qsm new file mode 100644 index 0000000..19454e0 --- /dev/null +++ b/examples/swaptest.qsm @@ -0,0 +1,9 @@ +qreg q[3]; +u(1,2,3) q[1]; +u(1,2,3) q[2]; + +h q[0]; +cswap q[0], q[1], q[2]; +h q[0]; + +sample q[0]; diff --git a/examples/teleportation.qsm b/examples/teleportation.qsm new file mode 100644 index 0000000..c9fac7d --- /dev/null +++ b/examples/teleportation.qsm @@ -0,0 +1,28 @@ +qreg q[3]; +creg c[2]; + +//qubit to teleport +u(1,2,3) q[0]; +print q[0]; //show qubit to teleport + +//shared entangled qubit +h q[1]; +cx q[1], q[2]; + +//correlate qubit to teleport +cx q[0], q[1]; + +//weaken correlation +h q[0]; + +//measure qubits +measure q[0] -> c[0]; +measure q[1] -> c[1]; + +//rotate based on measurement results +if(c==2) x q[2]; +if(c==1) z q[2]; +if(c==3) x q[2]; +if(c==3) z q[2]; + +print q[2]; //show teleported qubit \ No newline at end of file diff --git a/src/QAnsel.c b/src/QAnsel.c new file mode 100644 index 0000000..716d0e1 --- /dev/null +++ b/src/QAnsel.c @@ -0,0 +1,875 @@ +#include +#include +#include +#include +#include "complex.c" +#include "gates.c" +#include "display.c" +#include "chacha20.c" +#define QUBITS_MAX 11 + +typedef struct +{ + char n[128]; + uint8_t q0, q1, q2; + double arg0, arg1, arg2; +} QInstr; + +double qansel_rand() +{ + static uint64_t hiddenVariable = 0; + static uint32_t blockNumber = 0; + if (hiddenVariable == 0) + { + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + hiddenVariable = (uint64_t)ts.tv_sec * 1000000000LL + ts.tv_nsec; + } + uint8_t key[32]; + uint8_t nonce[12]; + uint64_t tmpVariable; + for (uint8_t i = 0; i < 32; i++) + { + if (i % 8 == 0) tmpVariable = hiddenVariable; + key[i] = tmpVariable & 0xFF; + tmpVariable >> 8; + + } + for (uint8_t i = 0; i < 12; i++) + { + nonce[i] = 0; + } + uint8_t* block = foleo_chacha20(key, nonce, blockNumber++, 4); + uint32_t num = 0; + for (uint8_t i = 0; i < 4; i++) + { + num = (num << 8) | block[i]; + } + return ((double)num) / ((double)UINT32_MAX); +} + +void qansel_cnot(cpx_mtx_t* stateVector, uint8_t qubitCount, uint8_t bitA, uint8_t bitB) +{ + uint32_t retLen = (uint8_t)pow(2, qubitCount); + cpx_mtx_t ret; + cpx_mtx_init(&ret, 1, retLen); + cpx_t n; + for (uint32_t i = 0; i < retLen; i++) + { + uint8_t bitAVal = (i >> bitA) & 1; + uint8_t bitBVal = (i >> bitB) & 1; + uint8_t bitBNew = bitAVal ? !bitBVal : bitBVal; + uint32_t 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, uint8_t qubitCount, uint8_t bitA, uint8_t bitB) +{ + uint32_t retLen = (uint8_t)pow(2, qubitCount); + cpx_mtx_t ret; + cpx_mtx_init(&ret, 1, retLen); + cpx_t n; + for (uint32_t i = 0; i < retLen; i++) + { + uint8_t bitAVal = (i >> bitA) & 1; + uint8_t bitBVal = (i >> bitB) & 1; + uint8_t bitANew = bitBVal; + uint8_t bitBNew = bitAVal; + uint32_t 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, uint8_t qubitCount, uint8_t bitA, uint8_t bitB, uint8_t bitC) +{ + uint32_t retLen = (uint8_t)pow(2, qubitCount); + cpx_mtx_t ret; + cpx_mtx_init(&ret, 1, retLen); + cpx_t n; + for (uint32_t i = 0; i < retLen; i++) + { + uint8_t bitAVal = (i >> bitA) & 1; + uint8_t bitBVal = (i >> bitB) & 1; + uint8_t bitCVal = (i >> bitC) & 1; + uint8_t bitBNew = bitAVal ? bitCVal : bitBVal; + uint8_t bitCNew = bitAVal ? bitBVal : bitCVal; + uint32_t 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, uint8_t qubitCount, uint8_t bitA, uint8_t bitB, uint8_t bitC) +{ + uint32_t retLen = (uint8_t)pow(2, qubitCount); + cpx_mtx_t ret; + cpx_mtx_init(&ret, 1, retLen); + cpx_t n; + for (uint32_t i = 0; i < retLen; i++) + { + uint8_t bitAVal = (i >> bitA) & 1; + uint8_t bitBVal = (i >> bitB) & 1; + uint8_t bitCVal = (i >> bitC) & 1; + uint8_t bitCNew = (bitAVal && bitBVal) ? !bitCVal : bitCVal; + uint32_t 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; +} + +double* qansel_unitary(double theta, double phi, double 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, uint8_t qubitCount, QInstr* instr) +{ + cpx_mtx_t tmp; + cpx_mtx_t gate; + gate.rows = 2; + gate.cols = 2; + double* gate_ptr; + switch (instr->n[0]) + { + case 'h': gate_ptr = Hadamard; break; + case 'x': gate_ptr = PauliX; break; + case 'y': gate_ptr = PauliY; break; + case 'z': gate_ptr = PauliZ; break; + case 's': gate_ptr = PhaseS; break; + case 't': gate_ptr = PhaseT; break; + case 'u': + gate_ptr = qansel_unitary(instr->arg0, instr->arg1, instr->arg2); + break; + default: gate_ptr = Identity; break; + } + + cpx_t n; + cpx_mtx_t filter; + cpx_mtx_init(&filter, 2, 2); + uint8_t qubit = qubitCount - (instr->q0) - 1; + if (qubit == 0) + { + memcpy(filter.ptr, gate_ptr, 16 * sizeof(double)); + } + else + { + memcpy(filter.ptr, Identity, 16 * sizeof(double)); + } + + for (uint8_t i = 1; i < qubitCount; i++) + { + cpx_mtx_init(&tmp, filter.rows * 2, filter.cols * 2); + if (qubit == i) + { + gate.ptr = gate_ptr; + } + else + { + gate.ptr = Identity; + } + cpx_mtx_knk(&tmp, &filter, &gate); + free(filter.ptr); + filter.ptr = tmp.ptr; + filter.rows = tmp.rows; + filter.cols = tmp.cols; + } + + cpx_mtx_init(&tmp, stateVector->rows, stateVector->cols); + cpx_mtx_mul(&tmp, stateVector, &filter); + free(stateVector->ptr); + stateVector->ptr = tmp.ptr; + free(filter.ptr); + if (instr->n[0] == 'u') free(gate_ptr); +} + + +uint8_t qansel_measure(cpx_mtx_t* stateVector, uint8_t qubitCount, uint8_t qubit) +{ + uint32_t qubitCountPow2 = (uint32_t)pow(2, qubitCount); + cpx_t n; + double prob0 = 0; + for (uint32_t i = 0; i < qubitCountPow2; i++) + { + uint8_t bit = (i >> qubit) & 1; + cpx_mtx_get(stateVector, 0, i, &n); + if (bit == 0) prob0 += cpx_magsqr(&n); + } + + double r = qansel_rand(); + uint8_t newBit = r < prob0 ? 0 : 1; + double probTot = 0; + for (uint32_t i = 0; i < qubitCountPow2; i++) + { + uint8_t 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); + } + + double multiplier = sqrt(1 / probTot); + for (uint32_t i = 0; i < qubitCountPow2; i++) + { + uint8_t 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; +} + +void qansel_run(uint8_t qubitCount, uint8_t bitCount, QInstr* instr, uint32_t instrLen, uint8_t gfx) +{ + uint32_t qubitCountPow2 = (uint32_t)pow(2, qubitCount); + + uint8_t bitVector[bitCount]; + cpx_mtx_t stateVector; + cpx_mtx_init(&stateVector, 1, qubitCountPow2); + cpx_mtx_set2(&stateVector, 0, 0, 1, 0); + if (gfx) display(&stateVector, qubitCount); + uint8_t flags; + + for (uint8_t i = 0; i < bitCount; i++) bitVector[i] = 0; + for (uint32_t i = 0; i < instrLen; i++) + { + if (strcmp(instr[i].n, "measure") == 0) + { + bitVector[instr[i].q1] = qansel_measure(&stateVector, qubitCount, instr[i].q0); + } + else if (strcmp(instr[i].n, "cswap") == 0) + { + qansel_fredkin(&stateVector, qubitCount, instr[i].q0, instr[i].q1, instr[i].q2); + } + else if (strcmp(instr[i].n, "ccx") == 0) + { + qansel_toffoli(&stateVector, qubitCount, instr[i].q0, instr[i].q1, instr[i].q2); + } + else if (strcmp(instr[i].n, "cx") == 0) + { + qansel_cnot(&stateVector, qubitCount, instr[i].q0, instr[i].q1); + } + else if (strcmp(instr[i].n, "swap") == 0) + { + qansel_swap(&stateVector, qubitCount, instr[i].q0, instr[i].q1); + } + else if (strcmp(instr[i].n, "if_all") == 0) + { + uint8_t val = 0; + for (int32_t j = bitCount - 1; j >= 0; j--) + { + val = (val << 1) | bitVector[j]; + } + if (val != instr[i].q0) i++; + } + else if (strcmp(instr[i].n, "if") == 0) + { + if (bitVector[instr[i].q0] != instr[i].q1) i++; + } + else if (strcmp(instr[i].n, "printq_all") == 0) + { + printf("[ "); cpx_mtx_print(&stateVector); printf(" ]\n"); + } + else if (strcmp(instr[i].n, "printc_all") == 0) + { + for (int32_t j = bitCount - 1; j >= 0; j--) + { + putchar('0' + bitVector[j]); + } + putchar('\n'); + } + else if (strcmp(instr[i].n, "printq") == 0) + { + cpx_mtx_t tmp; + cpx_mtx_init(&tmp, 1, 2); + for (uint32_t j = 0; j < qubitCountPow2; j++) + { + if ((j >> instr[i].q0) & 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); + } + } + double 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); + + printf("[ "); cpx_mtx_print(&tmp); printf(" ]\n"); + cpx_mtx_free(&tmp); + } + else if (strcmp(instr[i].n, "sample_all") == 0) + { + for (uint32_t j = 0; j < qubitCountPow2; j++) + { + uint32_t tmp = j; + for (uint8_t k = 0; k < qubitCount; k++) + { + putchar('0' + (tmp >> (qubitCount - 1) & 1)); + tmp <<= 1; + } + cpx_t n; + cpx_mtx_get(&stateVector, 0, j, &n); + printf(": %.00f%%\n", cpx_magsqr(&n) * 100); + } + } + else if (strcmp(instr[i].n, "sample") == 0) + { + double prob = 0; + for (uint32_t j = 0; j < qubitCountPow2; j++) + { + cpx_t n; + cpx_mtx_get(&stateVector, 0, j, &n); + if ((j >> instr[i].q0) & 1) + { + prob += cpx_magsqr(&n); + } + } + printf("%.00f%%\n", prob * 100.0); + } + else if (strcmp(instr[i].n, "reset") == 0) + { + cpx_mtx_set2(&stateVector, 0, 0, 1, 0); + for (uint32_t j = 1; j < qubitCountPow2; j++) + { + cpx_mtx_set2(&stateVector, 0, j, 0, 0); + } + for (uint8_t j = 0; j < bitCount; j++) + { + bitVector[j] = 0; + } + } + else + { + qansel_instruction(&stateVector, qubitCount, instr + i); + } + + if (gfx) display(&stateVector, qubitCount); + } + display(NULL, -1); + + cpx_mtx_free(&stateVector); +} + +void main() +{ + char** lines = malloc(0); + uint32_t* lineIDs = malloc(0); + char* text = malloc(0); + uint32_t textLen = 0; + uint32_t linesLen = 0; + int c; + int pc = -1; + uint8_t comment = 0; + uint8_t commentM = 0; + uint32_t lineID = 1; + uint8_t skipSpaces = 1; + uint8_t inGate = 0; + while ( (c = getchar()) != EOF ) + { + if (c == '/' && commentM == 0 && comment == 0) + { + commentM = 1; + } + else if (c == '/' && commentM == 1 && comment == 0) + { + comment = 1; + commentM = 0; + } + else if (c == '\n') + { + comment = 0; + commentM = 0; + lineID += 1; + } + else if (comment || (c == ' ' && skipSpaces)) {} + else if (c != '\n' && c != '\t' && c != ';' && (c != ')' || inGate)) + { + skipSpaces = 0; + if (c >= 'A' && c <= 'Z') c += 'a' - 'A'; + if (c == 'u') inGate = 1; + text = realloc(text, textLen + 1); + text[textLen++] = c; + pc = c; + } + else if (c == ';' || (c == ')' && !inGate)) + { + inGate = 0; + skipSpaces = 1; + if (c == ')') + { + text = realloc(text, textLen + 1); + text[textLen++] = ')'; + } + text = realloc(text, textLen + 1); + text[textLen++] = 0; + lineIDs = realloc(lineIDs, (linesLen + 1) * sizeof(uint32_t)); + lineIDs[linesLen] = lineID; + lines = realloc(lines, (linesLen + 1) * sizeof(char*)); + lines[linesLen] = malloc(strlen(text) + 1); + strcpy(lines[linesLen++], text); + text = realloc(text, 0); + textLen = 0; + pc = ';'; + } + } + text = realloc(text, textLen + 1); + text[textLen++] = 0; + if (strlen(text) > 0) + { + free(text); + fprintf(stderr, "QAnsel: Invalid trailing text.\n"); + exit(1); + } + free(text); + + uint8_t qubitCount = 0xFF; + uint8_t bitCount = 0xFF; + QInstr* instr = malloc(0); + uint32_t instrLen = 0; + + uint8_t errFound = 0; + for (uint32_t i = 0; i < linesLen; i++) + { + lineID = i; + + char g; + int q0, q1, q2; + float a0, a1, a2; + + if (sscanf(lines[i], "qreg q[%i]", &q0) == 1) + { + if (qubitCount == 0xFF) + { + qubitCount = q0; + if (qubitCount < 1 || qubitCount > QUBITS_MAX) + { + fprintf(stderr, "QAnsel: Invalid count"); + errFound = 1; + break; + } + } + else + { + fprintf(stderr, "QAnsel: Repeated initialization"); + errFound = 1; + break; + } + } + else if (sscanf(lines[i], "creg c[%i]", &q0) == 1) + { + if (bitCount == 0xFF) + { + bitCount = q0; + if (bitCount < 1 || bitCount > QUBITS_MAX) + { + fprintf(stderr, "QAnsel: Invalid count"); + errFound = 1; + break; + } + } + else + { + fprintf(stderr, "QAnsel: Repeated initialization"); + errFound = 1; + break; + } + } + else if (sscanf(lines[i], "u(%f,%f,%f) q[%i]", &a0, &a1, &a2, &q0) == 4) + { + if (qubitCount == 0xFF) + { + fprintf(stderr, "QAnsel: Instruction before initialization.\n"); + errFound = 1; + break; + } + if (q0 < 0 || q0 >= qubitCount) + { + fprintf(stderr, "QAnsel: Invalid index "); + errFound = 1; + break; + } + instr = realloc(instr, (instrLen + 1) * sizeof(QInstr)); + instr[instrLen].n[0] = 'u'; + instr[instrLen].n[1] = 0; + instr[instrLen].q0 = q0; + instr[instrLen].arg0 = a0; + instr[instrLen].arg1 = a1; + instr[instrLen++].arg2 = a2; + } + else if + ( + sscanf(lines[i], "h q[%i]", &q0) == 1 + || sscanf(lines[i], "x q[%i]", &q0) == 1 + || sscanf(lines[i], "y q[%i]", &q0) == 1 + || sscanf(lines[i], "z q[%i]", &q0) == 1 + || sscanf(lines[i], "t q[%i]", &q0) == 1 + || sscanf(lines[i], "z q[%i]", &q0) == 1 + ) + { + g = lines[i][0]; + if (qubitCount == 0xFF) + { + fprintf(stderr, "QAnsel: Instruction before initialization.\n"); + errFound = 1; + break; + } + if (q0 < 0 || q0 >= qubitCount) + { + fprintf(stderr, "QAnsel: Invalid index "); + errFound = 1; + break; + } + instr = realloc(instr, (instrLen + 1) * sizeof(QInstr)); + instr[instrLen].n[0] = g; + instr[instrLen].n[1] = 0; + instr[instrLen++].q0 = (uint8_t)q0; + } + else if (sscanf(lines[i], "cx q[%i], q[%i]", &q0, &q1) == 2) + { + if (qubitCount == 0xFF) + { + fprintf(stderr, "QAnsel: Instruction before initialization.\n"); + errFound = 1; + break; + } + if (q0 > qubitCount || q1 > qubitCount | q0 < 0 || q1 < 0 || q0 == q1) + { + fprintf(stderr, "QAnsel: Invalid index"); + errFound = 1; + break; + } + instr = realloc(instr, (instrLen + 1) * sizeof(QInstr)); + strcpy(instr[instrLen].n, "cx"); + instr[instrLen].q0 = q0; + instr[instrLen++].q1 = q1; + } + else if (sscanf(lines[i], "swap q[%i], q[%i]", &q0, &q1) == 2) + { + if (qubitCount == 0xFF) + { + fprintf(stderr, "QAnsel: Instruction before initialization.\n"); + errFound = 1; + break; + } + if (q0 > qubitCount || q1 > qubitCount | q0 < 0 || q1 < 0 || q0 == q1) + { + fprintf(stderr, "QAnsel: Invalid index"); + errFound = 1; + break; + } + instr = realloc(instr, (instrLen + 1) * sizeof(QInstr)); + strcpy(instr[instrLen].n, "swap"); + instr[instrLen].q0 = q0; + instr[instrLen++].q1 = q1; + } + else if + ( + sscanf(lines[i], "cswap q[%i], q[%i], q[%i]", &q0, &q1, &q2) == 3 + || sscanf(lines[i], "fredkin q[%i], q[%i], q[%i]", &q0, &q1, &q2) == 3 + ) + { + if (qubitCount == 0xFF) + { + fprintf(stderr, "QAnsel: Instruction before initialization.\n"); + errFound = 1; + break; + } + if (qubitCount < 3) + { + fprintf(stderr, "QAnsel: Three qubit gate used with insufficient qubits initialized.\n"); + errFound = 1; + break; + } + if (q0 >= qubitCount || q1 >= qubitCount || q2 >= qubitCount || q0 < 0 || q1< 0 || q2 < 0 || q0 == q1 || q1 == q2 || q0 == q2) + { + fprintf(stderr, "QAnsel: Invalid index"); + errFound = 1; + break; + } + instr = realloc(instr, (instrLen + 1) * sizeof(QInstr)); + strcpy(instr[instrLen].n, "cswap"); + instr[instrLen].q0 = q0; + instr[instrLen].q1 = q1; + instr[instrLen++].q2 = q2; + } + else if + ( + sscanf(lines[i], "ccx q[%i], q[%i], q[%i]", &q0, &q1, &q2) == 3 + || sscanf(lines[i], "toffoli q[%i], q[%i], q[%i]", &q0, &q1, &q2) == 3 + ) + { + if (qubitCount == 0xFF) + { + fprintf(stderr, "QAnsel: Instruction before initialization.\n"); + errFound = 1; + break; + } + if (qubitCount < 3) + { + fprintf(stderr, "QAnsel: Three qubit gate used with insufficient qubits initialized.\n"); + errFound = 1; + break; + } + if (q0 >= qubitCount || q1 >= qubitCount || q2 >= qubitCount || q0 < 0 || q1< 0 || q2 < 0 || q0 == q1 || q1 == q2 || q0 == q2) + { + fprintf(stderr, "QAnsel: Invalid index"); + errFound = 1; + break; + } + instr = realloc(instr, (instrLen + 1) * sizeof(QInstr)); + strcpy(instr[instrLen].n, "ccx"); + instr[instrLen].q0 = q0; + instr[instrLen].q1 = q1; + instr[instrLen++].q2 = q2; + } + else if (sscanf(lines[i], "measure q[%i] -> c[%i]", &q0, &q1) == 2) + { + if (bitCount == 0xFF) + { + fprintf(stderr, "QAnsel: Measure instruction used before bit initialization.\n"); + errFound = 1; + break; + } + if (q0 >= qubitCount || q1 >= bitCount || q0 < 0 || q1 < 0) + { + fprintf(stderr, "QAnsel: Invalid index"); + errFound = 1; + break; + } + instr = realloc(instr, (instrLen + 1) * sizeof(QInstr)); + strcpy(instr[instrLen].n, "measure"); + instr[instrLen].q0 = q0; + instr[instrLen++].q1 = q1; + } + else if (sscanf(lines[i], "if(c==%i)", &q0) == 1) + { + if (bitCount == 0xFF) + { + fprintf(stderr, "QAnsel: If instruction used before bit initialization.\n"); + errFound = 1; + break; + } + if (q0 < 0) + { + fprintf(stderr, "QAnsel: Invalid comparison"); + errFound = 1; + break; + } + instr = realloc(instr, (instrLen + 1) * sizeof(QInstr)); + strcpy(instr[instrLen].n, "if_all"); + instr[instrLen++].q0 = q0; + } + else if (sscanf(lines[i], "if(c[%i]==%i)", &q0, &q1) == 2) + { + if (bitCount == 0xFF) + { + fprintf(stderr, "QAnsel: If instruction used before bit initialization.\n"); + errFound = 1; + break; + } + if (q0 < 0 || q1 < 0 || q0 > bitCount) + { + fprintf(stderr, "QAnsel: Invalid comparison"); + errFound = 1; + break; + } + instr = realloc(instr, (instrLen + 1) * sizeof(QInstr)); + strcpy(instr[instrLen].n, "if"); + instr[instrLen].q0 = q0; + instr[instrLen++].q1 = q1; + } + else if (strcmp(lines[i], "print q") == 0) + { + if (qubitCount == 0xFF) + { + fprintf(stderr, "QAnsel: Qubit instruction used before initialization.\n"); + errFound = 1; + break; + } + instr = realloc(instr, (instrLen + 1) * sizeof(QInstr)); + strcpy(instr[instrLen].n, "printq_all"); + instrLen++; + } + else if (strcmp(lines[i], "print c") == 0) + { + if (bitCount == 0xFF) + { + fprintf(stderr, "QAnsel: Bit instruction used before initialization.\n"); + errFound = 1; + break; + } + instr = realloc(instr, (instrLen + 1) * sizeof(QInstr)); + strcpy(instr[instrLen].n, "printc_all"); + instrLen++; + } + else if (sscanf(lines[i], "print q[%i]", &q0) == 1) + { + if (qubitCount == 0xFF) + { + fprintf(stderr, "QAnsel: Qubit instruction used before initialization.\n"); + errFound = 1; + break; + } + if (q0 >= qubitCount || q0 < 0) + { + fprintf(stderr, "QAnsel: Invalid index"); + errFound = 1; + break; + } + instr = realloc(instr, (instrLen + 1) * sizeof(QInstr)); + strcpy(instr[instrLen].n, "printq"); + instr[instrLen++].q0 = q0; + } + else if (sscanf(lines[i], "print c[%i]", &q0) == 1) + { + if (bitCount == 0xFF) + { + fprintf(stderr, "QAnsel: Bit instruction used before initialization.\n"); + errFound = 1; + break; + } + if (q0 >= bitCount || q0 < 0) + { + fprintf(stderr, "QAnsel: Invalid index"); + errFound = 1; + break; + } + instr = realloc(instr, (instrLen + 1) * sizeof(QInstr)); + strcpy(instr[instrLen].n, "printc"); + instr[instrLen++].q0 = q0; + } + else if (strcmp(lines[i], "sample") == 0) + { + if (qubitCount == 0xFF) + { + fprintf(stderr, "QAnsel: Qubit instruction used before initialization.\n"); + errFound = 1; + break; + } + instr = realloc(instr, (instrLen + 1) * sizeof(QInstr)); + strcpy(instr[instrLen].n, "sample_all"); + instrLen++; + } + else if (sscanf(lines[i], "sample q[%i]", &q0) == 1) + { + if (qubitCount == 0xFF) + { + fprintf(stderr, "QAnsel: Qubit instruction used before initialization.\n"); + errFound = 1; + break; + } + if (q0 >= qubitCount || q0 < 0) + { + fprintf(stderr, "QAnsel: Invalid index"); + errFound = 1; + break; + } + instr = realloc(instr, (instrLen + 1) * sizeof(QInstr)); + strcpy(instr[instrLen].n, "sample"); + instr[instrLen++].q0 = q0; + } + else if (strcmp(lines[i], "reset") == 0) + { + if (qubitCount == 0xFF || bitCount == 0xFF) + { + fprintf(stderr, "QAnsel: Instruction used before initialization.\n"); + errFound = 1; + break; + } + instr = realloc(instr, (instrLen + 1) * sizeof(QInstr)); + strcpy(instr[instrLen].n, "reset"); + instrLen++; + } + else + { + fprintf(stderr, "QAnsel: Syntax error"); + errFound = 1; + break; + } + } + + for (uint32_t i = 0; i < linesLen; i++) free(lines[i]); + free(lines); + + if (errFound) + { + printf(" on line %i.\n", lineIDs[lineID]); + free(lineIDs); + free(instr); + exit(1); + } + + qansel_run(qubitCount, bitCount, instr, instrLen, 0); + free(instr); + free(lineIDs); +} diff --git a/src/chacha20.c b/src/chacha20.c new file mode 100644 index 0000000..6de9777 --- /dev/null +++ b/src/chacha20.c @@ -0,0 +1,111 @@ +#ifndef __FOLEO_CHACHA20__ +#define __FOLEO_CHACHA20__ +#include +#include + +static uint32_t foleo_chacha20_lr(uint32_t a, uint8_t b) +{ + return (a << b) | (a >> (32 - b)); +} + +static void foleo_chacha20_QR(uint32_t *cc, uint8_t a, uint8_t b, uint8_t c, uint8_t d) +{ + cc[a] += cc[b]; cc[d] ^= cc[a]; cc[d] = foleo_chacha20_lr(cc[d], 16); + cc[c] += cc[d]; cc[b] ^= cc[c]; cc[b] = foleo_chacha20_lr(cc[b], 12); + cc[a] += cc[b]; cc[d] ^= cc[a]; cc[d] = foleo_chacha20_lr(cc[d], 8); + cc[c] += cc[d]; cc[b] ^= cc[c]; cc[b] = foleo_chacha20_lr(cc[b], 7); +} + +static void foleo_chacha20_DR(uint32_t *cc) +{ + foleo_chacha20_QR(cc, 0, 4, 8, 12); + foleo_chacha20_QR(cc, 1, 5, 9, 13); + foleo_chacha20_QR(cc, 2, 6, 10, 14); + foleo_chacha20_QR(cc, 3, 7, 11, 15); + foleo_chacha20_QR(cc, 0, 5, 10, 15); + foleo_chacha20_QR(cc, 1, 6, 11, 12); + foleo_chacha20_QR(cc, 2, 7, 8, 13); + foleo_chacha20_QR(cc, 3, 4, 9, 14); +} + +static void foleo_chacha20_CB(uint32_t *cc) +{ + uint8_t i; + uint32_t x[16]; + for (i = 0; i < 16; i++) + { + x[i] = cc[i]; + } + for (i = 0; i < 10; i++) + { + foleo_chacha20_DR(cc); + } + for (i = 0; i < 16; i++) + { + cc[i] += x[i]; + } +} + +static void foleo_chacha20_S(uint32_t *cc, uint8_t *cs) +{ + for (uint8_t i = 0; i < 16; i++) + { + cs[4 * i] = (cc[i] & 0xFF); + cs[4 * i + 1] = ((cc[i] >> 8) & 0xFF); + cs[4 * i + 2] = ((cc[i] >> 16) & 0xFF); + cs[4 * i + 3] = ((cc[i] >> 24) & 0xFF); + } +} + +static void foleo_chacha20_block(uint8_t key[32], uint8_t nonce[12], uint32_t block, uint8_t out[64]) +{ + uint32_t cc[] = + { + 0x61707865, 0x3320646e, 0x79622d32, 0x6b206574, + + key[0] | (key[1] << 8) | (key[2] << 16) | (key[3] << 24), + key[4] | (key[5] << 8) | (key[6] << 16) | (key[7] << 24), + key[8] | (key[9] << 8) | (key[10] << 16) | (key[11] << 24), + key[12] | (key[13] << 8) | (key[14] << 16) | (key[15] << 24), + + key[16] | (key[17] << 8) | (key[18] << 16) | (key[19] << 24), + key[20] | (key[21] << 8) | (key[22] << 16) | (key[23] << 24), + key[24] | (key[25] << 8) | (key[26] << 16) | (key[27] << 24), + key[28] | (key[29] << 8) | (key[30] << 16) | (key[31] << 24), + + block, + + nonce[0] | (nonce[1] << 8) | (nonce[2] << 16) | (nonce[3] << 24), + nonce[4] | (nonce[5] << 8) | (nonce[6] << 16) | (nonce[7] << 24), + nonce[8] | (nonce[9] << 8) | (nonce[10] << 16) | (nonce[11] << 24) + }; + + foleo_chacha20_CB(cc); + foleo_chacha20_S(cc, out); +} + +/*Don't use block #0 if you are using this in conjunction with poly1305*/ +uint8_t* foleo_chacha20(uint8_t key[32], uint8_t nonce[12], uint32_t block, size_t count) +{ + if (count > (274877906944 - block * 64)) return NULL; + uint8_t* ret = malloc(0); + uint8_t ccblock[64]; + uint64_t size = 0; + while (count > 64) + { + ret = realloc(ret, size + 64); + foleo_chacha20_block(key, nonce, block++, ccblock); + for (uint8_t i = 0; i < 64; i++) ret[size + i] = ccblock[i]; + size += 64; + count -= 64; + } + if (count > 0) + { + ret = realloc(ret, size + count); + foleo_chacha20_block(key, nonce, block, ccblock); + for (uint8_t i = 0; i < count; i++) ret[size + i] = ccblock[i]; + } + return ret; +} + +#endif \ No newline at end of file diff --git a/src/complex.c b/src/complex.c new file mode 100644 index 0000000..e9736c4 --- /dev/null +++ b/src/complex.c @@ -0,0 +1,311 @@ +#ifndef __cpx__ +#define __cpx__ +#include +#include +#include + +typedef struct +{ + double real, imaginary; +} cpx_t; + +typedef struct +{ + double *ptr; + size_t rows, cols; +} cpx_mtx_t; + +uint8_t* cpx_str(cpx_t* n) +{ + uint8_t* r; + size_t z; + + double rl = n->real; + double ig = n->imaginary >= 0 ? n->imaginary : -(n->imaginary); + if (ig == 0) + { + z = snprintf(NULL, 0, "%f", rl); + r = malloc(z + 1); + sprintf(r, "%f", rl); + + } + else + { + uint8_t op = n->imaginary >= 0 ? '+' : '-'; + z = snprintf(NULL, 0, "%f %c %fi", rl, op, ig); + r = malloc(z + 1); + sprintf(r, "%f %c %fi", rl, op, ig); + } + return r; +} + +cpx_t cpx_new(double r, double i) +{ + cpx_t n; + n.real = r; + n.imaginary = i; + return n; +} + +void cpx_add(cpx_t* r, cpx_t* a, cpx_t* b) +{ + r->real = a->real + b->real; + r->imaginary = a->imaginary + b->imaginary; +} + +void cpx_sub(cpx_t* r, cpx_t* a, cpx_t* b) +{ + r->real = a->real - b->real; + r->imaginary = a->imaginary - b->imaginary; +} + +void cpx_mul(cpx_t* r, cpx_t* a, cpx_t* b) +{ + //FOIL + double first = a->real * b->real; //real + double outer = a->real * b->imaginary; //imaginary + double inner = a->imaginary * b->real; //imaginary + double last = -(a->imaginary * b->imaginary); //real + r->real = first + last; + r->imaginary = outer + inner; +} + +//non-complex matrix multiply +// shared = colsA = rowsB +void cpx_ncpx_mmul(double* ptrR, double* ptrA, double* ptrB, size_t rowsA, size_t colsB, size_t shared) +{ + size_t colsA = shared; + size_t rowsB = shared; + size_t rowsR = rowsA; + size_t colsR = colsB; + for (size_t rowR = 0; rowR < rowsR; rowR++) + { + for (size_t colR = 0; colR < colsR; colR++) + { + size_t posR = colR + rowR * colsR; + size_t rowA = rowR; + size_t colB = colR; + ptrR[posR] = 0; + for (size_t i = 0; i < shared; i++) + { + size_t posA = i + rowA * colsA; + size_t posB = colB + i * colsB; + ptrR[posR] += ptrA[posA] * ptrB[posB]; + } + } + } +} + +//non-complex kronecker product +void cpx_ncpx_mknk(double* ptrR, double* ptrA, double* ptrB, size_t rowsA, size_t colsA, size_t rowsB, size_t colsB) +{ + size_t rowsR = rowsA * rowsB; + size_t colsR = colsA * colsB; + for (size_t rowR = 0; rowR < rowsR; rowR++) + { + for (size_t colR = 0; colR < colsR; colR++) + { + size_t rowA = rowR / rowsB; + size_t colA = colR / colsB; + size_t rowB = rowR % rowsB; + size_t colB = colR % colsB; + printf(">%i,%i|%i<\n", colR, rowR, colR + rowR * colsR); + ptrR[colR + rowR * colsR] = + ptrA[colA + rowA * colsA] + * ptrB[colB + rowB * colsB] + ; + } + } +} + +double cpx_magsqr(cpx_t* n) +{ + return (n->real * n->real) + (n->imaginary * n->imaginary); +} + +double cpx_mag(cpx_t* n) +{ + return sqrt((n->real * n->real) + (n->imaginary * n->imaginary)); +} + +void cpx_mtx_mul(cpx_mtx_t* r, cpx_mtx_t* a, cpx_mtx_t* b) +{ + r->rows = a->rows; + r->cols = b->cols; + cpx_ncpx_mmul(r->ptr, a->ptr, b->ptr, a->rows * 2, b->cols * 2, a->cols * 2); +} + +void cpx_mtx_set(cpx_mtx_t* m, size_t row, size_t col, cpx_t* n) +{ + row *= 2; + col *= 2; + size_t cols = m->cols * 2; + m->ptr[col + row * cols] = n->real; + m->ptr[(col + 1) + row * cols] = -(n->imaginary); + m->ptr[col + (row + 1) * cols] = n->imaginary; + m->ptr[(col + 1) + (row + 1) * cols] = n->real; +} + +void cpx_mtx_set2(cpx_mtx_t* m, size_t row, size_t col, double real, double imaginary) +{ + row *= 2; + col *= 2; + size_t cols = m->cols * 2; + m->ptr[col + row * cols] = real; + m->ptr[(col + 1) + row * cols] = -imaginary; + m->ptr[col + (row + 1) * cols] = imaginary; + m->ptr[(col + 1) + (row + 1) * cols] = real; +} + +void cpx_mtx_get(cpx_mtx_t* m, size_t row, size_t col, cpx_t* n) +{ + row *= 2; + col *= 2; + size_t cols = m->cols * 2; + n->real = m->ptr[(col + 1) + (row + 1) * cols]; + n->imaginary = m->ptr[col + (row + 1) * cols]; +} + +double cpx_mtx_get_real(cpx_mtx_t* m, size_t row, size_t col) +{ + row *= 2; + col *= 2; + size_t cols = m->cols * 2; + return m->ptr[(col + 1) + (row + 1) * cols]; +} + +double cpx_mtx_get_imaginary(cpx_mtx_t* m, size_t row, size_t col) +{ + row *= 2; + col *= 2; + size_t cols = m->cols * 2; + return m->ptr[col + (row + 1) * cols]; +} + +void cpx_mtx_init(cpx_mtx_t* m, size_t rows, size_t cols) +{ + m->rows = rows; + m->cols = cols; + size_t z = (rows * 2) * (cols * 2); + m->ptr = malloc(z * sizeof(double)); + for (size_t i = 0; i < z; i++) m->ptr[i] = 0; +} + +void cpx_mtx_expand_row(cpx_mtx_t* m) +{ + m->rows += 1; + size_t z = (m->rows * 2) * (m->cols * 2); + m->ptr = realloc(m->ptr, z * sizeof(double)); +} + + +void cpx_mtx_free(cpx_mtx_t* m) +{ + if (m->ptr != NULL) free(m->ptr); + m->rows = 0; + m->cols = 0; +} + +void cpx_mtx_knk2 +( + double* ptrR, + size_t rowsR, + size_t colsR, + double* ptrA, + size_t rowsA, + size_t colsA, + double* ptrB, + size_t rowsB, + size_t colsB +) +{ + for (size_t rowR = 0; rowR < rowsR; rowR++) + { + for (size_t colR = 0; colR < colsR; colR++) + { + size_t rowA = rowR / rowsB; + size_t colA = colR / colsB; + size_t rowB = rowR % rowsB; + size_t colB = colR % colsB; + + double r1 = ptrA[((colA * 2) + 1) + ((rowA * 2) + 1) * (colsA * 2)]; + double i1 = ptrA[(colA * 2) + ((rowA * 2) + 1) * (colsA * 2)]; + double r2 = ptrB[((colB * 2) + 1) + ((rowB * 2) + 1) * (colsB * 2)]; + double i2 = ptrB[(colB * 2) + ((rowB * 2) + 1) * (colsB * 2)]; + + double first = r1 * r2; //real + double outer = r1 * i2; //imaginary + double inner = i1 * r2; //imaginary + double last = -(i1 * i2); //real + r1 = first + last; + i1 = outer + inner; + + ptrR[(colR * 2) + (rowR * 2) * (colsR * 2)] = r1; + ptrR[((colR * 2) + 1) + (rowR * 2) * (colsR * 2)] = -i1; + ptrR[(colR * 2) + ((rowR * 2) + 1) * (colsR * 2)] = i1; + ptrR[((colR * 2) + 1) + ((rowR * 2) + 1) * (colsR * 2)] = r1; + + } + } +} + +void cpx_mtx_knk(cpx_mtx_t* r, cpx_mtx_t* a, cpx_mtx_t* b) +{ + size_t rowsA = a->rows; + size_t colsA = a->cols; + size_t rowsB = b->rows; + size_t colsB = b->cols; + size_t rowsR = rowsA * rowsB; + size_t colsR = colsA * colsB; + cpx_mtx_init(r, rowsR, colsR); + for (size_t rowR = 0; rowR < rowsR; rowR++) + { + for (size_t colR = 0; colR < colsR; colR++) + { + size_t rowA = rowR / rowsB; + size_t colA = colR / colsB; + size_t rowB = rowR % rowsB; + size_t colB = colR % colsB; + cpx_t n1, n2; + + cpx_mtx_get(a, rowA, colA, &n1); + cpx_mtx_get(b, rowB, colB, &n2); + cpx_mul(&n1, &n1, &n2); + + cpx_mtx_set(r, rowR, colR, &n1); + } + } +} + + +void cpx_mtx_(cpx_mtx_t* m) +{ + for (size_t r = 0; r < m->rows * 2; r++) + { + for (size_t c = 0; c < m->cols * 2; c++) + { + if (c > 0) printf(", "); + printf("%f", m->ptr[c + r * m->cols * 2]); + } + printf("\n"); + } +} + +void cpx_mtx_print(cpx_mtx_t* m) +{ + for (size_t r = 0; r < m->rows; r++) + { + if (r > 0) printf("\n"); + for (size_t c = 0; c < m->cols; c++) + { + cpx_t n; + cpx_mtx_get(m, r, c, &n); + uint8_t* s = cpx_str(&n); + if (c > 0) printf(", "); + printf("%s", s); + free(s); + } + } +} + +#endif diff --git a/src/display.c b/src/display.c new file mode 100644 index 0000000..02ff639 --- /dev/null +++ b/src/display.c @@ -0,0 +1,122 @@ +#include +#include +#include +#include +#include +#include "complex.c" + +void DrawThickLine(SDL_Renderer* renderer, int x1, int y1, int x2, int y2, int thickness) { + int deltaX = x2 - x1; + int deltaY = y2 - y1; + float length = sqrt(deltaX * deltaX + deltaY * deltaY); + float nx = deltaY / length; + float ny = -deltaX / length; + int halfThickness = thickness / 2; + + for (int i = -halfThickness; i <= halfThickness; ++i) { + int offsetx = i * nx; + int offsety = i * ny; + SDL_RenderDrawLine(renderer, x1 + offsetx, y1 + offsety, x2 + offsetx, y2 + offsety); + } +} + +void display(cpx_mtx_t* stateVector, uint8_t qubitCount) +{ + 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; + int SCREEN_WIDTH = 640 * 2; + int SCREEN_HEIGHT = 480; + + if (stateVector == NULL) + { + SDL_DestroyRenderer(renderer); + SDL_DestroyWindow(window); + SDL_Quit(); + return; + } + + if (displayInitialized == 0) + { + if (SDL_Init(SDL_INIT_VIDEO)) + { + fprintf(stderr, "Failed to open graphical window.\n"); + exit(1); + } + window = SDL_CreateWindow + ( + "D", + SDL_WINDOWPOS_UNDEFINED, + SDL_WINDOWPOS_UNDEFINED, + SCREEN_WIDTH, + SCREEN_HEIGHT, + SDL_WINDOW_SHOWN + ); + if (window == NULL) + { + fprintf(stderr, "Failed to open graphical window.\n"); + exit(1); + } + renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_SOFTWARE); + if (renderer == NULL) + { + fprintf(stderr, "Failed to open graphical window.\n"); + exit(1); + } + displayInitialized = 1; + } + SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0x00, 0xFF); + SDL_RenderClear(renderer); + SDL_SetRenderDrawColor(renderer, 0x00, 0xFF, 0x00, 0x00); + + double p0 = 0; + double i0 = 0; + for (int i = -20; i < SCREEN_WIDTH; i++) + { + double p1 = 0; + double i1 = 0; + for (int j = 1; j <= qubitCountPow2; j++) + { + cpx_t n; + cpx_mtx_get(stateVector, 0, j - 1, &n); + p1 += (sin(i * ((2 * M_PI) / (SCREEN_WIDTH / j))) * (SCREEN_HEIGHT / 4)) * (n.real * n.real) * (n.real < 0 ? -1 : 1); + i1 += (cos(i * ((2 * M_PI) / (SCREEN_WIDTH / j))) * (SCREEN_HEIGHT / 4)) * (n.imaginary * n.imaginary) * (n.imaginary < 0 ? -1 : 1); + } + + int x0 = i - 1; + int y0 = p0; + int x1 = i; + int y1 = p1; + + x0 += i0 / 4; + y0 += i0 / 2; + x1 += i1 / 4; + y1 += i1 / 2; + + y0 += SCREEN_HEIGHT / 2; + y1 += SCREEN_HEIGHT / 2; + + if ( (i0 + i1) / 2 < 0) + { + SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF); + DrawThickLine(renderer, x0, SCREEN_HEIGHT / 2, x1, SCREEN_HEIGHT / 2, 5); + SDL_SetRenderDrawColor(renderer, 0x00, 0xFF, 0x00, 0x00); + DrawThickLine(renderer, x0, y0, x1, y1, 5); + } + else + { + DrawThickLine(renderer, x0, y0, x1, y1, 5); + SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF); + DrawThickLine(renderer, x0, SCREEN_HEIGHT / 2, x1, SCREEN_HEIGHT / 2, 5); + SDL_SetRenderDrawColor(renderer, 0x00, 0xFF, 0x00, 0x00); + } + p0 = p1; + i0 = i1; + } + + SDL_RenderPresent(renderer); // Update screen. + SDL_Delay(500); // Wait for two seconds. + +} \ No newline at end of file diff --git a/src/gates.c b/src/gates.c new file mode 100644 index 0000000..347a72e --- /dev/null +++ b/src/gates.c @@ -0,0 +1,81 @@ + +double Identity[] = +{ + 1, 0, 0, 0, + 0, 1, 0, 0, + + 0, 0, 1, 0, + 0, 0, 0, 1 +}; + +double PauliX[] = +{ + 0, 0, 1, 0, + 0, 0, 0, 1, + + 1, 0, 0, 0, + 0, 1, 0, 0 +}; + +double PauliY[] = +{ + 0, 0, 0, 1, + 0, 0, -1, 0, + + 0,-1, 0, 0, + 1, 0, 0, 0, +}; + +double PauliZ[] = +{ + 1, 0, 0, 0, + 0, 1, 0, 0, + + 0, 0, -1, 0, + 0, 0, 0,-1 +}; + +// 1/sqrt(2) +#define R 0.7071067811865475 +double Hadamard[] = +{ + R, 0, R, 0, + 0, R, 0, R, + + R, 0, -R, 0, + 0, R, 0,-R, +}; + +double PhaseS[] = +{ + 1, 0, 0, 0, + 0, 1, 0, 0, + + 0, 0, 0,-1, + 0, 0, 0, 0 +}; + +// 1/sqrt(2) + 1/sqrt(2)i +double PhaseT[] = +{ + 1, 0, 0, 0, + 0, 1, 0, 0, + + 0, 0, R,-R, + 0, 0, R, R +}; + +double ControlledNOT[] = +{ + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 1, + + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, +}; \ No newline at end of file