From 36b7fca7faee53192b0bdeeb4b72bfe67c06056e Mon Sep 17 00:00:00 2001 From: server Date: Sun, 10 Sep 2023 00:28:07 -0400 Subject: [PATCH 1/1] Sun Sep 10 12:28:07 AM EDT 2023 --- Makefile | 2 + bin/QAnsel | Bin 0 -> 66112 bytes examples/bb84.qsm | 26 ++ examples/bellstate.qsm | 5 + examples/encryption.qsm | 6 + examples/halfadder.qsm | 40 ++ examples/swaptest.qsm | 9 + examples/teleportation.qsm | 28 ++ src/QAnsel.c | 875 +++++++++++++++++++++++++++++++++++++ src/chacha20.c | 111 +++++ src/complex.c | 311 +++++++++++++ src/display.c | 122 ++++++ src/gates.c | 81 ++++ 13 files changed, 1616 insertions(+) create mode 100644 Makefile create mode 100755 bin/QAnsel create mode 100644 examples/bb84.qsm create mode 100644 examples/bellstate.qsm create mode 100644 examples/encryption.qsm create mode 100644 examples/halfadder.qsm create mode 100644 examples/swaptest.qsm create mode 100644 examples/teleportation.qsm create mode 100644 src/QAnsel.c create mode 100644 src/chacha20.c create mode 100644 src/complex.c create mode 100644 src/display.c create mode 100644 src/gates.c 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 0000000000000000000000000000000000000000..baa3cc764d04649e48e350b8908cc56af433b66d GIT binary patch literal 66112 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 HoUHmEfnM1o literal 0 HcmV?d00001 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 -- 2.39.5