]> foleosoft.com Git - QAnsel.git/commitdiff
Mon Mar 18 06:14:19 PM EDT 2024
authormiha-q <>
Mon, 18 Mar 2024 22:14:19 +0000 (18:14 -0400)
committermiha-q <>
Mon, 18 Mar 2024 22:14:19 +0000 (18:14 -0400)
bin/QAnsel
examples/hiddenvariable.txt [deleted file]
src/bytecode.c
src/complex.c
src/context.c [new file with mode: 0644]
src/hardware.c
src/main.c
src/openqasm.c
src/qansel.h

index df10cea7c469d53137bdd117d6d6f409af83e528..347663844e56a383667a53a3863b25cce2464905 100755 (executable)
Binary files a/bin/QAnsel and b/bin/QAnsel differ
diff --git a/examples/hiddenvariable.txt b/examples/hiddenvariable.txt
deleted file mode 100644 (file)
index 747d512..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-qreg q[1];
-creg c[4];
-
-hvar 12.34;
-h q[0]; measure q[0] -> c[0];
-h q[0]; measure q[0] -> c[1];
-h q[0]; measure q[0] -> c[2];
-h q[0]; measure q[0] -> c[3];
-print c;
-
-rand;
-h q[0]; measure q[0] -> c[0];
-h q[0]; measure q[0] -> c[1];
-h q[0]; measure q[0] -> c[2];
-h q[0]; measure q[0] -> c[3];
-print c;
-
-hvar 43.21;
-h q[0]; measure q[0] -> c[0];
-h q[0]; measure q[0] -> c[1];
-h q[0]; measure q[0] -> c[2];
-h q[0]; measure q[0] -> c[3];
-print c;
-
index ac53737420b01bc265f8a60314e0007b5c2e4819..6db18a84c5b275c96788df0ed197922f72cd4feb 100644 (file)
@@ -26,7 +26,6 @@ const char* qansel_instruction_to_string(unsigned char instr)
                case QANSEL_INSTRUCTION_CCX: return "QANSEL_INSTRUCTION_CCX";
                case QANSEL_INSTRUCTION_CSWAP: return "QANSEL_INSTRUCTION_CSWAP";
                case QANSEL_INSTRUCTION_MEASURE: return "QANSEL_INSTRUCTION_MEASURE";
-               case QANSEL_INSTRUCTION_SAMPLE: return "QANSEL_INSTRUCTION_SAMPLE";
                case QANSEL_INSTRUCTION_DENSITY: return "QANSEL_INSTRUCTION_DENSITY";
                case QANSEL_INSTRUCTION_BORN: return "QANSEL_INSTRUCTION_BORN";
                case QANSEL_INSTRUCTION_IF_E: return "QANSEL_INSTRUCTION_JUMP_E";
@@ -35,10 +34,8 @@ const char* qansel_instruction_to_string(unsigned char instr)
                case QANSEL_INSTRUCTION_IF_GE: return "QANSEL_INSTRUCTION_JUMP_GE";
                case QANSEL_INSTRUCTION_IF_L: return "QANSEL_INSTRUCTION_JUMP_L";
                case QANSEL_INSTRUCTION_IF_LE: return "QANSEL_INSTRUCTION_JUMP_LE";
-               case QANSEL_INSTRUCTION_RAND: return "QANSEL_INSTRUCTION_RAND";
-               case QANSEL_INSTRUCTION_HVAR: return "QANSEL_INSTRUCTION_HVAR";
-               case QANSEL_INSTRUCTION_RESET: return "QANSEL_INSTRUCTION_RESET";
                case QANSEL_INSTRUCTION_PRINT: return "QANSEL_INSTRUCTION_PRINT";
+               case QANSEL_INSTRUCTION_RESET: return "QANSEL_INSTRUCTION_RESET";
                case QANSEL_INSTRUCTION_BARRIER: return "QANSEL_INSTRUCTION_BARRIER";
                case QANSEL_INSTRUCTION_EXIT: return "QANSEL_INSTRUCTION_EXIT";
        }
@@ -60,14 +57,20 @@ float qansel_rand_h()
 {
        return ((float)rand()) / ((float)RAND_MAX);
 }
-float qansel_rand_t()
+float qansel_rand_t(QAnselContext* ctx)
 {
-       if (QANSEL_RANDOM_FILE)
+       if (ctx->hardware_rng != QANSEL_HARDWARE_NONE)
        {
                unsigned int num = 0;
                for (unsigned char i = 0; i < 4; i++)
                {
-                       num = (num << 8) | fgetc(QANSEL_RANDOM_FILE);
+                       unsigned char r = 0;
+                       switch (ctx->hardware_rng)
+                       {
+                               case QANSEL_HARDWARE_TRUERNG: r = fgetc(ctx->random_file); break;
+                               case QANSEL_HARDWARE_RDSEED: r = qansel_hardware_rand(); break;
+                       }
+                       num = (num << 8) | r;
                }
                return ((float)num) / ((float)UINT32_MAX);
        }
@@ -77,11 +80,6 @@ float qansel_rand_t()
        }
 }
 
-float qansel_rand()
-{
-       return QANSEL_HIDDEN_VARIABLE ? qansel_rand_h() : qansel_rand_t();
-}
-
 void qansel_cnot(cpx_mtx_t* stateVector, unsigned char qubitCount, unsigned char bitA, unsigned char bitB)
 {
        if (bitA >= qubitCount || bitB >= qubitCount) return;
@@ -264,6 +262,7 @@ void qansel_instruction_queue
 
 void qansel_instruction
 (
+       QAnselContext* ctx,
        cpx_mtx_t* stateVector,
        int qubitCount,
        unsigned char instr,
@@ -381,11 +380,11 @@ void qansel_instruction
                //us2 = get_time();
                //printf("\tTranspose: %lu\n", us2 - us1);
                #else
-               if ((QANSEL_MODE & QANSEL_MODE_METAL) && !(QANSEL_MODE & QANSEL_MODE_THREADED) && tmp.cols >= 64)
+               if (((ctx->optimization_level) & QANSEL_MODE_METAL) && !((ctx->optimization_level) & QANSEL_MODE_THREADED) && tmp.cols >= 64)
                {
                        cpx_mtx_knk_metal_2x2(tmp.ptr, filter.ptr, gate.ptr, filter.rows, filter.cols, gate.rows, gate.cols);
                }
-               else if ((QANSEL_MODE & QANSEL_MODE_THREADED) && tmp.cols >= 64)
+               else if (((ctx->optimization_level) & QANSEL_MODE_THREADED) && tmp.cols >= 64)
                {
                        cpx_mtx_knk_threads_2x2(tmp.ptr, filter.ptr, gate.ptr, filter.rows, filter.cols, gate.rows, gate.cols);
                }
@@ -419,11 +418,11 @@ void qansel_instruction
        us2 = get_time();
        printf("\tBare: %lu\n", us2 - us1);
        #else
-       if ((QANSEL_MODE & QANSEL_MODE_METAL) && tmp.cols >= 64)
+       if (((ctx->optimization_level) & QANSEL_MODE_METAL) && tmp.cols >= 64)
        {
                cpx_mtx_dot_metal(tmp.ptr, stateVector->ptr, filter.ptr, stateVector->rows, stateVector->cols, filter.rows, filter.cols);
        }
-       else if ((QANSEL_MODE & QANSEL_MODE_THREADED) && tmp.cols >= 64)
+       else if (((ctx->optimization_level) & QANSEL_MODE_THREADED) && tmp.cols >= 64)
        {
                cpx_mtx_dot_threads(tmp.ptr, stateVector->ptr, filter.ptr, stateVector->rows, stateVector->cols, filter.rows, filter.cols);
        }
@@ -438,7 +437,7 @@ void qansel_instruction
        if (needToFreeGate) free(gate_ptr);
 }
 
-unsigned char qansel_measure(cpx_mtx_t* stateVector, unsigned char qubitCount, unsigned char qubit)
+unsigned char qansel_measure(QAnselContext* ctx, cpx_mtx_t* stateVector, unsigned char qubitCount, unsigned char qubit)
 {
        unsigned int qubitCountPow2 = (unsigned int)pow(2, qubitCount);
        cpx_t n;
@@ -450,7 +449,7 @@ unsigned char qansel_measure(cpx_mtx_t* stateVector, unsigned char qubitCount, u
                if (bit == 0) prob0 += cpx_magsqr(&n);
        }
 
-       float r = qansel_rand();
+       float r = (ctx->hidden_variable) ? qansel_rand_h() : qansel_rand_t(ctx);
        unsigned char newBit = r < prob0 ? 0 : 1;
        float probTot = 0;
        for (unsigned int i = 0; i < qubitCountPow2; i++)
@@ -511,7 +510,6 @@ int qansel_get_instruction_bitmax(unsigned char* ptr, int offset, int* bitmax, i
                        if (a0 > QANSEL_QBOUND_UPPER && a0 != QANSEL_ALL_QUANTUM) return 0;
                        if (a0 != QANSEL_ALL_QUANTUM) *qbitmax = a0 + 1;
                        return 1;
-               case QANSEL_INSTRUCTION_SAMPLE:
                case QANSEL_INSTRUCTION_IF_E:
                case QANSEL_INSTRUCTION_IF_NE:
                case QANSEL_INSTRUCTION_IF_G:
@@ -563,23 +561,53 @@ int qansel_get_instruction_bitmax(unsigned char* ptr, int offset, int* bitmax, i
                        *qbitmax = a0 + 1;
                        *bitmax = (a1 - QANSEL_CBOUND_LOWER) + 1;
                        return 1;
-               case QANSEL_INSTRUCTION_RAND:
-               case QANSEL_INSTRUCTION_HVAR:
                case QANSEL_INSTRUCTION_EXIT:
                        return 1;
        }
        return 0;
 }
 
-int qansel_get_barrier(int** q, int qubitCount, int bitCount, unsigned char* binary, int pos)
+int qansel_get_instruction_size(unsigned char instr)
 {
-
-       unsigned char instr = binary[pos];
        switch (instr)
        {
-               case QANSEL_INSTRUCTION_SAMPLE:
-               case QANSEL_INSTRUCTION_RAND:
-               case QANSEL_INSTRUCTION_HVAR:
+               case QANSEL_INSTRUCTION_X: return 1 + 1;
+               case QANSEL_INSTRUCTION_Y: return 1 + 1;
+               case QANSEL_INSTRUCTION_Z: return 1 + 1;
+               case QANSEL_INSTRUCTION_H: return 1 + 1;
+               case QANSEL_INSTRUCTION_S: return 1 + 1;
+               case QANSEL_INSTRUCTION_T: return 1 + 1;
+               case QANSEL_INSTRUCTION_RX: return 1 + 1 + sizeof(float);
+               case QANSEL_INSTRUCTION_RY: return 1 + 1 + sizeof(float);
+               case QANSEL_INSTRUCTION_RZ: return 1 + 1 + sizeof(float);
+               case QANSEL_INSTRUCTION_U1: return 1 + 1 + sizeof(float);
+               case QANSEL_INSTRUCTION_U2: return 1 + 1 + sizeof(float) * 2;
+               case QANSEL_INSTRUCTION_U3: return 1 + 1 + sizeof(float) * 3;
+               case QANSEL_INSTRUCTION_CX: return 1 + 2;
+               case QANSEL_INSTRUCTION_SWAP: return 1 + 2;
+               case QANSEL_INSTRUCTION_CCX: return 1 + 3;
+               case QANSEL_INSTRUCTION_CSWAP: return 1 + 3;
+               case QANSEL_INSTRUCTION_MEASURE: return 1 + 2;
+               case QANSEL_INSTRUCTION_DENSITY: return 1 + 1;
+               case QANSEL_INSTRUCTION_BORN: return 1 + 1;
+               case QANSEL_INSTRUCTION_IF_E: return 1 + 1 + sizeof(unsigned short);
+               case QANSEL_INSTRUCTION_IF_NE: return 1 + 1 + sizeof(unsigned short);
+               case QANSEL_INSTRUCTION_IF_G: return 1 + 1 + sizeof(unsigned short);
+               case QANSEL_INSTRUCTION_IF_GE: return 1 + 1 + sizeof(unsigned short);
+               case QANSEL_INSTRUCTION_IF_L: return 1 + 1 + sizeof(unsigned short);
+               case QANSEL_INSTRUCTION_IF_LE: return 1 + 1 + sizeof(unsigned short);
+               case QANSEL_INSTRUCTION_RESET: return 1 + 1;
+               case QANSEL_INSTRUCTION_PRINT: return 1 + 1;
+               case QANSEL_INSTRUCTION_BARRIER: return 1 + 1;
+               case QANSEL_INSTRUCTION_EXIT: return 1;
+       }
+       return 0;
+}
+
+void qansel_get_barrier(QBytecode** qbc, int idx)
+{
+       switch ((*qbc)[idx].op)
+       {
                case QANSEL_INSTRUCTION_EXIT:
                case QANSEL_INSTRUCTION_IF_E:
                case QANSEL_INSTRUCTION_IF_NE:
@@ -587,8 +615,8 @@ int qansel_get_barrier(int** q, int qubitCount, int bitCount, unsigned char* bin
                case QANSEL_INSTRUCTION_IF_GE:
                case QANSEL_INSTRUCTION_IF_L:
                case QANSEL_INSTRUCTION_IF_LE:
-                       *q = NULL;
-                       return 0;
+                       (*qbc)[idx].barrier_width = 0;
+                       return;
                case QANSEL_INSTRUCTION_X:
                case QANSEL_INSTRUCTION_Y:
                case QANSEL_INSTRUCTION_Z:
@@ -601,122 +629,55 @@ int qansel_get_barrier(int** q, int qubitCount, int bitCount, unsigned char* bin
                case QANSEL_INSTRUCTION_U1:
                case QANSEL_INSTRUCTION_U2:
                case QANSEL_INSTRUCTION_U3:
-                       //only barrier single-qubit instructions if
-                       //      they are nexted in an if statement
-                       if (pos >= (1 + sizeof(unsigned short)))
-                       {
-                               switch (binary[pos - (1 + sizeof(unsigned short))])
-                               {
-                                       case QANSEL_INSTRUCTION_IF_E:
-                                       case QANSEL_INSTRUCTION_IF_NE:
-                                       case QANSEL_INSTRUCTION_IF_G:
-                                       case QANSEL_INSTRUCTION_IF_GE:
-                                       case QANSEL_INSTRUCTION_IF_L:
-                                       case QANSEL_INSTRUCTION_IF_LE:
-                                               *q = malloc(1);
-                                               (*q)[0] = binary[pos + 1] + QANSEL_QBOUND_LOWER;
-                                               return 1;
-                               }
-                       }
-                       *q = NULL;
-                       return 0;
+                       (*qbc)[idx].barrier_width = 1;
+                       (*qbc)[idx].barrier[0] = (*qbc)[idx].bytes[1];
+                       return;
                case QANSEL_INSTRUCTION_MEASURE:
                case QANSEL_INSTRUCTION_DENSITY:
-                       *q = malloc(2);
-                       (*q)[0] = binary[pos + 1] + QANSEL_QBOUND_LOWER;
-                       (*q)[1] = binary[pos + 2] + QANSEL_CBOUND_LOWER;
-                       return 1;
+                       (*qbc)[idx].barrier_width = 2;
+                       (*qbc)[idx].barrier[0] = (*qbc)[idx].bytes[1];
+                       (*qbc)[idx].barrier[1] = (*qbc)[idx].bytes[2];
+                       return;
                case QANSEL_INSTRUCTION_BORN:
                case QANSEL_INSTRUCTION_BARRIER:
                case QANSEL_INSTRUCTION_PRINT:
                case QANSEL_INSTRUCTION_RESET:
-                       switch (binary[pos + 1])
+                       switch ((*qbc)[idx].bytes[1])
                        {
                                case QANSEL_ALL:
-                                       *q = malloc(sizeof(int) * (qubitCount + bitCount));
-                                       for (int i = 0; i < qubitCount; i++)
-                                       {
-                                               (*q)[i] = i + QANSEL_QBOUND_LOWER;
-                                       }
-                                       for (int i = 0; i < bitCount; i++)
-                                       {
-                                               (*q)[i] = i + QANSEL_CBOUND_LOWER;
-                                       }
-                                       return qubitCount + bitCount;
+                                       (*qbc)[idx].barrier_width = QANSEL_QUBITS_MAX * 2;
+                                       for (int i = 0; i < QANSEL_QUBITS_MAX; i++) (*qbc)[idx].barrier[i] = i;
+                                       for (int i = 0; i < QANSEL_QUBITS_MAX; i++) (*qbc)[idx].barrier[i] = i + QANSEL_CBOUND_LOWER;
+                                       return;
                                case QANSEL_ALL_QUANTUM:
-                                       *q = malloc(sizeof(int) * qubitCount);
-                                       for (int i = 0; i < qubitCount; i++)
-                                       {
-                                               (*q)[i] = i + QANSEL_QBOUND_LOWER;
-                                       }
-                                       return qubitCount;
+                                       (*qbc)[idx].barrier_width = QANSEL_QUBITS_MAX;
+                                       for (int i = 0; i < QANSEL_QUBITS_MAX; i++) (*qbc)[idx].barrier[i] = i;
+                                       return;
                                case QANSEL_ALL_CLASSIC:
-                                       *q = malloc(sizeof(int) * bitCount);
-                                       for (int i = 0; i < bitCount; i++)
-                                       {
-                                               (*q)[i] = i + QANSEL_CBOUND_LOWER;
-                                       }
-                                       return bitCount;
+                                       (*qbc)[idx].barrier_width = QANSEL_QUBITS_MAX;
+                                       for (int i = 0; i < QANSEL_QUBITS_MAX; i++) (*qbc)[idx].barrier[i] = i + QANSEL_CBOUND_LOWER;
+                                       return;
                                default:
-                                       *q = malloc(1);
-                                       (*q)[0] = binary[pos + 1];
-                                       return 1;
+                                       (*qbc)[idx].barrier_width = 1;
+                                       (*qbc)[idx].barrier[0] = (*qbc)[idx].bytes[1];
+                                       return;
                        }
                case QANSEL_INSTRUCTION_CX:
                case QANSEL_INSTRUCTION_SWAP:
-                       *q = malloc(2);
-                       (*q)[0] = binary[pos + 1] + QANSEL_QBOUND_LOWER;
-                       (*q)[1] = binary[pos + 2] + QANSEL_QBOUND_LOWER;
-                       return 2;
+                       (*qbc)[idx].barrier_width = 2;
+                       (*qbc)[idx].barrier[0] = (*qbc)[idx].bytes[1];
+                       (*qbc)[idx].barrier[1] = (*qbc)[idx].bytes[2];
+                       return;
                case QANSEL_INSTRUCTION_CCX:
                case QANSEL_INSTRUCTION_CSWAP:
-                       *q = malloc(3);
-                       (*q)[0] = binary[pos + 1] + QANSEL_QBOUND_LOWER;
-                       (*q)[1] = binary[pos + 2] + QANSEL_QBOUND_LOWER;
-                       (*q)[2] = binary[pos + 3] + QANSEL_QBOUND_LOWER;
-                       return 3;
-       }
-       fprintf(stderr, "QAnsel (%04X): Unknown error in barrier analysis.\n", pos);
-}
-
-int qansel_get_instruction_size(unsigned char instr)
-{
-       switch (instr)
-       {
-               case QANSEL_INSTRUCTION_X: return 1 + 1;
-               case QANSEL_INSTRUCTION_Y: return 1 + 1;
-               case QANSEL_INSTRUCTION_Z: return 1 + 1;
-               case QANSEL_INSTRUCTION_H: return 1 + 1;
-               case QANSEL_INSTRUCTION_S: return 1 + 1;
-               case QANSEL_INSTRUCTION_T: return 1 + 1;
-               case QANSEL_INSTRUCTION_RX: return 1 + 1 + sizeof(float);
-               case QANSEL_INSTRUCTION_RY: return 1 + 1 + sizeof(float);
-               case QANSEL_INSTRUCTION_RZ: return 1 + 1 + sizeof(float);
-               case QANSEL_INSTRUCTION_U1: return 1 + 1 + sizeof(float);
-               case QANSEL_INSTRUCTION_U2: return 1 + 1 + sizeof(float) * 2;
-               case QANSEL_INSTRUCTION_U3: return 1 + 1 + sizeof(float) * 3;
-               case QANSEL_INSTRUCTION_CX: return 1 + 2;
-               case QANSEL_INSTRUCTION_SWAP: return 1 + 2;
-               case QANSEL_INSTRUCTION_CCX: return 1 + 3;
-               case QANSEL_INSTRUCTION_CSWAP: return 1 + 3;
-               case QANSEL_INSTRUCTION_MEASURE: return 1 + 2;
-               case QANSEL_INSTRUCTION_SAMPLE: return 1 + 1;
-               case QANSEL_INSTRUCTION_DENSITY: return 1 + 1;
-               case QANSEL_INSTRUCTION_BORN: return 1 + 1;
-               case QANSEL_INSTRUCTION_IF_E: return 1 + 1 + sizeof(unsigned short);
-               case QANSEL_INSTRUCTION_IF_NE: return 1 + 1 + sizeof(unsigned short);
-               case QANSEL_INSTRUCTION_IF_G: return 1 + 1 + sizeof(unsigned short);
-               case QANSEL_INSTRUCTION_IF_GE: return 1 + 1 + sizeof(unsigned short);
-               case QANSEL_INSTRUCTION_IF_L: return 1 + 1 + sizeof(unsigned short);
-               case QANSEL_INSTRUCTION_IF_LE: return 1 + 1 + sizeof(unsigned short);
-               case QANSEL_INSTRUCTION_RAND: return 1;
-               case QANSEL_INSTRUCTION_HVAR: return 1 + sizeof(float);
-               case QANSEL_INSTRUCTION_RESET: return 1 + 1;
-               case QANSEL_INSTRUCTION_PRINT: return 1 + 1;
-               case QANSEL_INSTRUCTION_BARRIER: return 1 + 1;
-               case QANSEL_INSTRUCTION_EXIT: return 1;
+                       (*qbc)[idx].barrier_width = 3;
+                       (*qbc)[idx].barrier[0] = (*qbc)[idx].bytes[1];
+                       (*qbc)[idx].barrier[1] = (*qbc)[idx].bytes[2];
+                       (*qbc)[idx].barrier[2] = (*qbc)[idx].bytes[3];
+                       return;
        }
-       return 0;
+       fprintf(stderr, "QAnsel (#%i): Unknown error in barrier analysis.\n", idx);
+       exit(1);
 }
 
 void qansel_born(cpx_mtx_t* stateVector, int PC, int qubitCount, unsigned char q0)
@@ -870,7 +831,7 @@ int qansel_get_int(unsigned char* program, int offset)
        return ret;
 }
 
-void qansel_reset(cpx_mtx_t* stateVector, unsigned char* bitVector, int qubitCount, int bitCount, unsigned char q0)
+void qansel_reset(QAnselContext* ctx, cpx_mtx_t* stateVector, unsigned char* bitVector, int qubitCount, int bitCount, unsigned char q0)
 {
        unsigned int qubitCountPow2 = (unsigned int)pow(2, qubitCount);
        if (q0 == QANSEL_ALL)
@@ -902,10 +863,10 @@ void qansel_reset(cpx_mtx_t* stateVector, unsigned char* bitVector, int qubitCou
        }
        else if (q0 <= QANSEL_QBOUND_UPPER)
        {
-               unsigned char bit = qansel_measure(stateVector, qubitCount, q0);
+               unsigned char bit = qansel_measure(ctx, stateVector, qubitCount, q0);
                if (bit)
                {
-                       qansel_instruction(stateVector, qubitCount, QANSEL_INSTRUCTION_X, q0, 0, 0, 0, NULL);
+                       qansel_instruction(ctx, stateVector, qubitCount, QANSEL_INSTRUCTION_X, q0, 0, 0, 0, NULL);
                }
        }
        else if (q0 >= QANSEL_CBOUND_LOWER && q0 <= QANSEL_CBOUND_UPPER)
@@ -939,27 +900,62 @@ unsigned char qansel_compare(unsigned char* bitVector, int bitCount, int PC, uns
        return ret;
 }
 
-int qansel_crawl(unsigned char* program, int programSize, int* qubitCount, int* bitCount, int* sample)
+//computes program efficiency
+//     points are awarded for how long strings of single qubit
+//     instructions are 
+int qansel_efficiency(QBytecode* program, int programSize, int head)
 {
-       if (QANSEL_VERBOSE) printf("Crawling program . . .\n");
+       int score = 0;
+       int tmpscore = 0;
+       int idx = head;
+
+       for (int i = 0; i < programSize; i++)
+       {
+               switch (program[idx].op)
+               {
+                       case QANSEL_INSTRUCTION_X:
+                       case QANSEL_INSTRUCTION_Y:
+                       case QANSEL_INSTRUCTION_Z:
+                       case QANSEL_INSTRUCTION_H:
+                       case QANSEL_INSTRUCTION_S:
+                       case QANSEL_INSTRUCTION_T:
+                       case QANSEL_INSTRUCTION_RX:
+                       case QANSEL_INSTRUCTION_RY:
+                       case QANSEL_INSTRUCTION_RZ:
+                       case QANSEL_INSTRUCTION_U1:
+                       case QANSEL_INSTRUCTION_U2:
+                       case QANSEL_INSTRUCTION_U3:
+                               switch (tmpscore)
+                               {
+                                       case 0: tmpscore = 1; break;
+                                       default: tmpscore *= 2;
+                               }
+                       break;
+                       case QANSEL_INSTRUCTION_IF_E:
+                       case QANSEL_INSTRUCTION_IF_NE:
+                       case QANSEL_INSTRUCTION_IF_G:
+                       case QANSEL_INSTRUCTION_IF_GE:
+                       case QANSEL_INSTRUCTION_IF_L:
+                       case QANSEL_INSTRUCTION_IF_LE:
+                       break;
+                       default:
+                               if (tmpscore > 1) score += tmpscore;
+                               tmpscore = 0;
+               }
+               idx = program[idx].next;
+       }
+       return score;
+}
+
+int qansel_crawl(QAnselContext* ctx, unsigned char* program, int programSize, int* qubitCount, int* bitCount)
+{
+       if (ctx->verbose) printf("Crawling program . . .\n");
        int PC = 0;
        *qubitCount = 0;
        *bitCount = 0;
-       *sample = QANSEL_ALL;
        while (PC < programSize)
        {
                int next = qansel_get_instruction_size(program[PC]);
-               if (program[PC] == QANSEL_INSTRUCTION_SAMPLE)
-               {
-                       if ((program[PC + 1] < QANSEL_CBOUND_LOWER || program[PC + 1] > QANSEL_CBOUND_UPPER) && program[PC + 1] != QANSEL_ALL_CLASSIC)
-                       {
-                               if (QANSEL_VERBOSE) fprintf(stderr, "QAnsel (%04X): Invalid index.\n", PC);
-                       }
-                       else
-                       {
-                               *sample = program[PC + 1] - QANSEL_CBOUND_LOWER;
-                       }
-               }
                if (next == 0)
                {
                        printf("QAnsel (%04X): Invalid instruction 0x%02x.\n", PC, program[PC]);
@@ -976,14 +972,249 @@ int qansel_crawl(unsigned char* program, int programSize, int* qubitCount, int*
                if (qbitmax > *qubitCount) *qubitCount = qbitmax;
                PC += next;
        }
-       if (QANSEL_VERBOSE) printf("Quantum bits allocated: %i\n", *qubitCount);
-       if (QANSEL_VERBOSE) printf("Classical bits allocated: %i\n", *bitCount);
+       if (ctx->verbose) printf("Quantum bits allocated: %i\n", *qubitCount);
+       if (ctx->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)
+void qansel_reorder(QAnselContext* ctx, unsigned char* program, int programSize)
 {
-       int useQueue = (QANSEL_MODE & QANSEL_MODE_QUEUE) ? 1 : 0;
+       if (ctx->verbose) printf("Reordering . . .\n");
+
+       //break out program for easier manipulation
+       QBytecode* ramInstr = malloc(0);
+       int ramInstrLen = 0;
+       int copyifop = 0;
+       unsigned char ifop[16];
+       int PC = 0;
+
+       while (PC < programSize)
+       {
+               int next = qansel_get_instruction_size(program[PC]);
+               switch (program[PC])
+               {
+                       case QANSEL_INSTRUCTION_IF_E:
+                       case QANSEL_INSTRUCTION_IF_NE:
+                       case QANSEL_INSTRUCTION_IF_G:
+                       case QANSEL_INSTRUCTION_IF_GE:
+                       case QANSEL_INSTRUCTION_IF_L:
+                       case QANSEL_INSTRUCTION_IF_LE:
+                               memcpy(ifop, program + PC, next);
+                               copyifop = 1;
+                               PC += next;
+                       continue;
+               }
+               ramInstr = realloc(ramInstr, sizeof(QBytecode) * (ramInstrLen + 1));
+               ramInstr[ramInstrLen].size = next;
+               memcpy(ramInstr[ramInstrLen].bytes, program + PC, next);
+               ramInstr[ramInstrLen].op = program[PC];
+               ramInstr[ramInstrLen].use_ifop = copyifop;
+               if (copyifop)
+               {
+                       memcpy(ramInstr[ramInstrLen].ifop, ifop, sizeof(ifop));
+                       copyifop = 0;
+               }
+               ramInstrLen++;
+               PC += next;
+       }
+       for (int i = 0; i < ramInstrLen; i++)
+       {
+               if (i == 0)
+               {
+                       ramInstr[0].prev = -1;
+                       ramInstr[0].next = ramInstrLen > 1 ? 1 : -1;
+               }
+               else if (i == ramInstrLen - 1)
+               {
+                       ramInstr[ramInstrLen - 1].prev = i - 1;
+                       ramInstr[ramInstrLen - 1].next = -1;
+               }
+               else
+               {
+                       ramInstr[i].prev = i - 1;
+                       ramInstr[i].next = i + 1;
+               }
+               //we can only rearrange single-qubit instructions
+               //      so treat other instructions as pre-checked
+               switch (ramInstr[i].op)
+               {
+                       case QANSEL_INSTRUCTION_X:
+                       case QANSEL_INSTRUCTION_Y:
+                       case QANSEL_INSTRUCTION_Z:
+                       case QANSEL_INSTRUCTION_H:
+                       case QANSEL_INSTRUCTION_S:
+                       case QANSEL_INSTRUCTION_T:
+                       case QANSEL_INSTRUCTION_RX:
+                       case QANSEL_INSTRUCTION_RY:
+                       case QANSEL_INSTRUCTION_RZ:
+                       case QANSEL_INSTRUCTION_U1:
+                       case QANSEL_INSTRUCTION_U2:
+                       case QANSEL_INSTRUCTION_U3:
+                               ramInstr[i].checked = 0;
+                       break;
+                       default: ramInstr[i].checked = 1;
+               }
+       }
+
+       for (int i = 0; i < ramInstrLen; i++)
+       {
+               qansel_get_barrier(&ramInstr, i);
+       }
+
+       QBytecode* reordered[2];
+       reordered[0] = malloc(ramInstrLen * sizeof(QBytecode));
+       reordered[1] = malloc(ramInstrLen * sizeof(QBytecode));
+       memcpy(reordered[0], ramInstr, ramInstrLen * sizeof(QBytecode));
+       memcpy(reordered[1], ramInstr, ramInstrLen * sizeof(QBytecode));
+       
+       int efficiency = qansel_efficiency(ramInstr, ramInstrLen, 0);
+       int head[2];
+       head[0] = 0;
+       head[1] = 0;
+       for (int reorid = 0; reorid < 2; reorid++)
+       {
+               while (1)
+               {
+                       //find the next unchecked instruction
+                       int found = -1;
+                       int idx = head[reorid];
+                       for (int i = 0; i < ramInstrLen; i++)
+                       {
+                               if (reordered[reorid][idx].checked == 0)
+                               {
+                                       found = idx;
+                                       break;
+                               }
+                               idx = reordered[reorid][idx].next;
+                       }
+                       if (found == -1) break;
+                       //check if it can be moved up
+                       reordered[reorid][found].checked = 1;
+                       int blocked = 0;
+                       idx = reordered[reorid][idx].prev;
+                       while (idx != -1)
+                       {
+                               for (int i = 0; i < reordered[reorid][idx].barrier_width; i++)
+                               {
+                                       //verify no classical bit barrier
+                                       if (reordered[reorid][found].use_ifop)
+                                       {
+                                               switch (reordered[reorid][found].ifop[1])
+                                               {
+                                                       case QANSEL_ALL_CLASSIC:
+                                                       case QANSEL_ALL:
+                                                               blocked = 1;
+                                                       break;
+                                                       default:
+                                                               if (reordered[reorid][found].ifop[1] == reordered[reorid][idx].barrier[i])
+                                                                       blocked = 1;
+                                               }
+                                               if (blocked) break;
+                                       }
+                                       //verify no quantum bit barrier
+                                       if (reordered[reorid][found].bytes[1] == reordered[reorid][idx].barrier[i])
+                                       {
+                                               blocked = 1;
+                                               break;
+                                       }
+                               }
+                               if (blocked) break;
+                               idx = reordered[reorid][idx].prev;
+                       }
+                       if (reordered[reorid][found].prev != idx)
+                       {
+                               QBytecode* tmpbc = malloc(ramInstrLen * sizeof(QBytecode));
+                               memcpy(tmpbc, reordered[reorid], ramInstrLen * sizeof(QBytecode));
+                               reordered[reorid][ reordered[reorid][found].prev ].next = reordered[reorid][found].next;
+                               if (reordered[reorid][found].next != -1)
+                               {
+                                       reordered[reorid][ reordered[reorid][found].next ].prev = reordered[reorid][found].prev;
+                               }
+
+                               if (idx == -1)
+                               {
+                                       reordered[reorid][head[reorid]].prev = found;
+                                       reordered[reorid][found].next = head[reorid];
+                                       reordered[reorid][found].prev = -1;
+                                       head[reorid] = found;
+                               }
+                               else
+                               {
+                                       reordered[reorid][ reordered[reorid][idx].next ].prev = found;
+                                       reordered[reorid][found].next = reordered[reorid][idx].next;
+                                       reordered[reorid][found].prev = idx;
+                                       reordered[reorid][idx].next = found;
+                               }
+                               if (reorid == 1)
+                               {
+                                       int tmpeff = qansel_efficiency(reordered[reorid], ramInstrLen, head[reorid]);
+                                       if (tmpeff >= efficiency)
+                                       {
+                                               efficiency = tmpeff;
+                                       }
+                                       else
+                                       {
+                                               memcpy(reordered[reorid], tmpbc, ramInstrLen * sizeof(QBytecode));
+                                       }
+                               }
+                               free(tmpbc);
+                       }
+               }
+       }
+
+       efficiency = qansel_efficiency(ramInstr, ramInstrLen, 0);
+       int best = -1;
+       int besti = -1;
+       for (int i = 0; i < 2; i++)
+       {
+               int tmpeff = qansel_efficiency(reordered[i], ramInstrLen, head[i]);
+               if (tmpeff > best)
+               {
+                       besti = i;
+                       best = tmpeff;
+               }
+       }
+       if (best > efficiency)
+       {
+               memcpy(ramInstr, reordered[besti], ramInstrLen * sizeof(QBytecode));
+       }
+       for (int i = 0; i < 2; i++)
+       {
+               free(reordered[i]);
+       }
+
+       int copyloc = 0;
+       for (int i = 0; i < ramInstrLen; i++)
+       {
+               int next;
+               if (ramInstr[i].use_ifop)
+               {
+                       next = qansel_get_instruction_size(ramInstr[i].ifop[0]);
+                       memcpy(program + copyloc, ramInstr[i].ifop, next);
+                       copyloc += next;
+               }
+               next = qansel_get_instruction_size(ramInstr[i].op);
+               memcpy(program + copyloc, ramInstr[i].bytes, next);
+               copyloc += next;
+       }
+
+       if (ctx->verbose)
+       {
+               if (best > efficiency)
+               {
+                       printf("Efficiency score increased from %i to %i.\n", efficiency, best);
+               }
+               else
+               {
+                       printf("Could not increase efficiency.\n");
+               }
+       }
+}
+
+void qansel_run(QAnselContext* ctx, unsigned char* program, int programSize, int qubitCount, int bitCount, unsigned char* outputBitVector)
+{
+       int useQueue = ((ctx->optimization_level) & QANSEL_MODE_QUEUE) ? 1 : 0;
        int PC = 0;
        unsigned int qubitCountPow2 = (unsigned int)pow(2, qubitCount);
        unsigned char bitVector[bitCount];
@@ -1003,7 +1234,7 @@ void qansel_run(unsigned char* program, int programSize, int qubitCount, int bit
                        queueVector[i].cols = 2;
                }
        }
-       if (QANSEL_USE_DISPLAY) { QANSEL_USE_DISPLAY = display(&stateVector, qubitCount, QANSEL_USE_DISPLAY); }
+       if (ctx->display_delay) { ctx->display_delay = display(&stateVector, qubitCount, ctx->display_delay); }
        unsigned char skip = 0, a0 = 0, a1 = 0, a2 = 0;
        unsigned char flags = 0;
        unsigned short tmp = 0;
@@ -1051,12 +1282,9 @@ void qansel_run(unsigned char* program, int programSize, int qubitCount, int bit
                                        case QANSEL_INSTRUCTION_IF_GE:
                                        case QANSEL_INSTRUCTION_IF_L:
                                        case QANSEL_INSTRUCTION_IF_LE:
-                                       case QANSEL_INSTRUCTION_SAMPLE:
-                                       case QANSEL_INSTRUCTION_HVAR:
-                                       case QANSEL_INSTRUCTION_RAND:
                                                break;
                                        default:
-                                               qansel_instruction(&stateVector, qubitCount, instr, 0, 0, 0, 0, &queueVector);
+                                               qansel_instruction(ctx, &stateVector, qubitCount, instr, 0, 0, 0, 0, &queueVector);
                                                for (int i = 0; i < qubitCount; i++)
                                                {
                                                        memcpy(queueVector[i].ptr, Identity, sizeof(Identity));
@@ -1116,7 +1344,7 @@ void qansel_run(unsigned char* program, int programSize, int qubitCount, int bit
                                        }
                                        a0 = program[PC + 1];
                                        if (useQueue) qansel_instruction_queue(&queueVector, qubitCount, instr, a0, f0, f1, f2);
-                                       else qansel_instruction(&stateVector, qubitCount, instr, a0, f0, f1, f2, NULL);
+                                       else qansel_instruction(ctx, &stateVector, qubitCount, instr, a0, f0, f1, f2, NULL);
                                break;
                                case QANSEL_INSTRUCTION_CX:
                                        a0 = program[PC + 1];
@@ -1143,7 +1371,7 @@ void qansel_run(unsigned char* program, int programSize, int qubitCount, int bit
                                case QANSEL_INSTRUCTION_MEASURE:
                                        a0 = program[PC + 1];
                                        a1 = program[PC + 2] - QANSEL_CBOUND_LOWER;
-                                       bitVector[a1] = qansel_measure(&stateVector, qubitCount, a0);
+                                       bitVector[a1] = qansel_measure(ctx, &stateVector, qubitCount, a0);
                                break;
                                case QANSEL_INSTRUCTION_BORN:
                                        a0 = program[PC + 1];
@@ -1162,17 +1390,7 @@ void qansel_run(unsigned char* program, int programSize, int qubitCount, int bit
                                break;
                                case QANSEL_INSTRUCTION_RESET:
                                        a0 = program[PC + 1];
-                                       qansel_reset(&stateVector, bitVector, qubitCount, bitCount, a0);
-                               break;
-                               case QANSEL_INSTRUCTION_HVAR:
-                                       QANSEL_HIDDEN_VARIABLE = 1;
-                                       float tmp1 = qansel_get_float(program, PC + 1);
-                                       unsigned int tmp2;
-                                       memcpy(&tmp2, &tmp1, sizeof(unsigned int));
-                                       srand(tmp2);
-                               break;
-                               case QANSEL_INSTRUCTION_RAND:
-                                       QANSEL_HIDDEN_VARIABLE = 0;
+                                       qansel_reset(ctx, &stateVector, bitVector, qubitCount, bitCount, a0);
                                break;
                                case QANSEL_INSTRUCTION_IF_E:
                                        a0 = program[PC + 1];
@@ -1210,12 +1428,11 @@ void qansel_run(unsigned char* program, int programSize, int qubitCount, int bit
                                        flags = qansel_compare(bitVector, bitCount, PC, a0, tmp);
                                        skip = 1; if ((flags & QANSEL_FLAGS_LESSER) && (flags & QANSEL_FLAGS_EQUAL)) skip = 0;
                                break;
-                               case QANSEL_INSTRUCTION_SAMPLE: break;
 
                        }
                }
                PC += next;
-               if (QANSEL_USE_DISPLAY) { QANSEL_USE_DISPLAY = display(&stateVector, qubitCount, QANSEL_USE_DISPLAY); }
+               if (ctx->display_delay) { ctx->display_delay = display(&stateVector, qubitCount, ctx->display_delay); }
        }
        if (outputBitVector != NULL)
        {
@@ -1233,28 +1450,36 @@ void qansel_run(unsigned char* program, int programSize, int qubitCount, int bit
                }
                free(queueVector);
        }
-       if (QANSEL_USE_DISPLAY) { display(NULL, 0, 0); }
+       if (ctx->display_delay) { display(NULL, 0, 0); }
 
 }
 
-int qanselExecuteBytecode(unsigned char* buff, int sizeofbuff)
+int qanselExecuteBytecode(unsigned char* buff, int sizeofbuff, QAnselContext* ctx)
 {
+       if (!qanselContextValidate(ctx)) return 0;
        struct timespec ts;
        clock_gettime(CLOCK_MONOTONIC, &ts);
        float seed = (float)((unsigned long)ts.tv_sec * 1000000000LL + ts.tv_nsec);
        qansel_rand_s(seed);
 
+       if (ctx != NULL && ctx->hidden_variable != 0)
+       {
+               unsigned int tmp;
+               memcpy(&tmp, &(ctx->hidden_variable), sizeof(unsigned int));
+               srand(tmp);
+       }
+
        unsigned short vals;
        float valf; 
        int pos = 0;
 
-       int qubitCount, bitCount, sample;
-       if (!qansel_crawl(buff, sizeofbuff, &qubitCount, &bitCount, &sample))
+       int qubitCount, bitCount;
+       if (!qansel_crawl(ctx, buff, sizeofbuff, &qubitCount, &bitCount))
        {
                return 0;
        }
 
-       if (sample != QANSEL_ALL)
+       if (ctx != NULL && ctx->sampling_shots > 0)
        {
                unsigned short stats[65536];
                for (unsigned int i = 0; i < (1 << bitCount); i++)
@@ -1264,10 +1489,10 @@ int qanselExecuteBytecode(unsigned char* buff, int sizeofbuff)
                unsigned char bitVect[bitCount];
                memset(bitVect, 0, bitCount);
                for (int i = 0; i < bitCount; i++) bitVect[i] = 0;
-               unsigned int shots = QANSEL_SAMPLE_COUNT;
+               unsigned int shots = ctx->sampling_shots;
                for (unsigned int i = 0; i < shots; i++)
                {
-                       qansel_run(buff, sizeofbuff, qubitCount, bitCount, bitVect);
+                       qansel_run(ctx, buff, sizeofbuff, qubitCount, bitCount, bitVect);
                        unsigned short stat = 0;
                        for (signed char j = bitCount - 1; j >= 0; j--)
                        {
@@ -1282,22 +1507,22 @@ int qanselExecuteBytecode(unsigned char* buff, int sizeofbuff)
                        for (unsigned char j = 0; j < bitCount; j++)
                        {
                                unsigned char bit = (tmp >> (bitCount - 1) & 1);
-                               if (j == (bitCount - sample - 1) && bit)
+                               if (j == (bitCount - (ctx->sampling_bit) - 1) && bit)
                                {
                                        count += stats[i];
                                }
-                               if (sample == QANSEL_ALL_QUANTUM)
+                               if ((ctx->sampling_bit) == QANSEL_ALL)
                                {
                                        putchar('0' + bit);
                                }
                                tmp <<= 1;
                        }
-                       if (sample == QANSEL_ALL_QUANTUM)
+                       if ((ctx->sampling_bit) == QANSEL_ALL)
                        {
                                printf(": %.1f%%\n", ((float)stats[i] / (float)shots) * (float)100);
                        }
                }
-               if (sample != QANSEL_ALL_QUANTUM)
+               if ((ctx->sampling_bit) != QANSEL_ALL)
                {
                        float prob = ((float)count / (float)shots) * (float)100;
                        printf("0: %.1f%%\n", ((float)100)-prob);
@@ -1306,7 +1531,7 @@ int qanselExecuteBytecode(unsigned char* buff, int sizeofbuff)
        }
        else
        {
-               qansel_run(buff, sizeofbuff, qubitCount, bitCount, NULL);
+               qansel_run(ctx, buff, sizeofbuff, qubitCount, bitCount, NULL);
        }
        return 1;
 }
index f9481e81013b66c531d556d6e1edaaf8af8f57f0..bc1d3d75eb7e9ca893883e888e975db0b840ef86 100644 (file)
@@ -1,13 +1,5 @@
 #ifndef __cpx__
 #define __cpx__
-#include <stdint.h>
-#include <stddef.h>
-#include <math.h>
-#include <pthread.h>
-#include <string.h>
-#include "hardware.c"
-#include "kernel_cpu.cl"
-#include "kernel_gpu.cl"
 typedef struct
 {
     float real, imaginary;
@@ -19,9 +11,9 @@ typedef struct
     int rows, cols;
 } cpx_mtx_t;
 
-uint8_t* cpx_str(cpx_t* n)
+unsigned char* cpx_str(cpx_t* n)
 {
-    uint8_t* r;
+    unsigned char* r;
     int z;
 
     float rl = n->real;
@@ -35,7 +27,7 @@ uint8_t* cpx_str(cpx_t* n)
     }
     else
     {
-        uint8_t op = n->imaginary >= 0 ? '+' : '-';
+        unsigned char 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);
@@ -149,7 +141,7 @@ void cpx_mtx_print(cpx_mtx_t* m)
         {
             cpx_t n;
             cpx_mtx_get(m, r, c, &n);
-            uint8_t* s = cpx_str(&n);
+            unsigned char* s = cpx_str(&n);
             if (c > 0) printf(", ");
             printf("%s", s);
             free(s);
@@ -218,7 +210,7 @@ void* cpx_mtx_knk_threads_run(void *context)
 void cpx_mtx_knk_threads(float* ptrR, float* ptrA, float* ptrB, int rowsA, int colsA, int rowsB, int colsB)
 {
        int delimeter = rowsA * rowsB;
-       int cores = get_core_count();
+       int cores = qansel_get_core_count();
        int threadCount = cores;
        if (threadCount > delimeter) threadCount = delimeter;
        int delimetersPerThread = delimeter / threadCount;
@@ -245,7 +237,7 @@ void cpx_mtx_knk_threads(float* ptrR, float* ptrA, float* ptrB, int rowsA, int c
             exit(1);
         }
        }
-    for (uint32_t i = 0; i < threadCount; i++)
+    for (unsigned int i = 0; i < threadCount; i++)
     {
         if (pthread_join(threads[i], NULL))
         {
@@ -283,7 +275,7 @@ void* cpx_mtx_knk_threads_2x2_run(void *context)
 void cpx_mtx_knk_threads_2x2(float* ptrR, float* ptrA, float* ptrB, int rowsA, int colsA, int rowsB, int colsB)
 {
        int delimeter = (rowsA * rowsB) / 2;
-       int cores = get_core_count();
+       int cores = qansel_get_core_count();
        int threadCount = cores;
        if (threadCount > delimeter) threadCount = delimeter;
        int delimetersPerThread = delimeter / threadCount;
@@ -310,7 +302,7 @@ void cpx_mtx_knk_threads_2x2(float* ptrR, float* ptrA, float* ptrB, int rowsA, i
             exit(1);
         }
        }
-    for (uint32_t i = 0; i < threadCount; i++)
+    for (unsigned int i = 0; i < threadCount; i++)
     {
         if (pthread_join(threads[i], NULL))
         {
@@ -334,7 +326,7 @@ void* cpx_mtx_dot_threads_run(void *context)
 void cpx_mtx_dot_threads(float* ptrR, float* ptrA, float* ptrB, int rowsA, int colsA, int rowsB, int colsB)
 {
     int delimeter = colsB;
-       int cores = get_core_count();
+       int cores = qansel_get_core_count();
        int threadCount = cores;
        if (threadCount > delimeter) threadCount = delimeter;
        int delimeterPerThread = delimeter / threadCount;
@@ -360,7 +352,7 @@ void cpx_mtx_dot_threads(float* ptrR, float* ptrA, float* ptrB, int rowsA, int c
             exit(1);
         }
        }
-    for (uint32_t i = 0; i < threadCount; i++)
+    for (unsigned int i = 0; i < threadCount; i++)
     {
         if (pthread_join(threads[i], NULL))
         {
@@ -458,7 +450,7 @@ const char* clGetErrorString(cl_int err)
 }
 
 
-uint8_t cpx_mtx_begin()
+unsigned char cpx_mtx_begin(unsigned char verbose)
 {
        cl_uint count;
        cl_int err;
@@ -467,9 +459,9 @@ uint8_t cpx_mtx_begin()
        if (err != CL_SUCCESS || count == 0)
        {
                if (err == 0)
-                       fprintf(stderr, "GPU error: No supported platforms found.\n");
+                       fprintf(stderr, "QAnsel (GPU): No supported platforms found.\n");
                else
-                       fprintf(stderr, "GPU error: clGetPlatformIDs() failed.\n");
+                       fprintf(stderr, "QAnsel (GPU): clGetPlatformIDs() failed.\n");
                return 0;
        }
 
@@ -477,32 +469,42 @@ uint8_t cpx_mtx_begin()
        if (err != CL_SUCCESS || count == 0)
        {
                if (count == 0)
-                       fprintf(stderr, "GPU error: No supported GPUs found.\n");
+                       fprintf(stderr, "QAnsel (GPU): No supported GPUs found.\n");
                else
-                       fprintf(stderr, "GPU error: clGetDeviceIDs() failed.\n");
+                       fprintf(stderr, "QAnsel (GPU): clGetDeviceIDs() failed.\n");
                return 0;
        }
 
-       //size_t size;
-       //clGetDeviceInfo(cpx_mtx_device_id, CL_DEVICE_NAME, 0, NULL, &size);
-       //char str[size];
-       //clGetDeviceInfo(cpx_mtx_device_id, CL_DEVICE_NAME, size, str, NULL);
-       //printf("%s\n", str);
+       size_t size;
+       err = clGetDeviceInfo(cpx_mtx_device_id, CL_DEVICE_NAME, 0, NULL, &size);
+       if (err != CL_SUCCESS)
+       {
+               fprintf(stderr, "QAnsel: Unknown GPU error.\n");
+               return 0;
+       }
+       char str[size];
+       err = clGetDeviceInfo(cpx_mtx_device_id, CL_DEVICE_NAME, size, str, NULL);
+       if (err != CL_SUCCESS)
+       {
+               fprintf(stderr, "QAnsel: Unknown GPU error.\n");
+               return 0;
+       }
+       if (verbose) printf("QAnsel: Hardware `%s` selected.\n", str);
 
        cpx_mtx_context = clCreateContext(NULL, 1, &cpx_mtx_device_id, NULL, NULL, &err);
        if (err != CL_SUCCESS)
        {
-               fprintf(stderr, "GPU error: clCreateContext() failed.\n");
+               fprintf(stderr, "QAnsel (GPU): clCreateContext() failed.\n");
                return 0;
        }
 
        cpx_mtx_command_queue = clCreateCommandQueue(cpx_mtx_context, cpx_mtx_device_id, 0, &err);
        if (err != CL_SUCCESS)
        {
-               fprintf(stderr, "GPU error: clCreateCommandQueue() failed.\n");
+               fprintf(stderr, "QAnsel (GPU): clCreateCommandQueue() failed.\n");
                err = clReleaseContext(cpx_mtx_context);
                if (err != CL_SUCCESS)
-                       fprintf(stderr, "GPU error: clReleaseContext() failed.\n");
+                       fprintf(stderr, "QAnsel (GPU): clReleaseContext() failed.\n");
                return 0;
        }
        return 1;
@@ -514,12 +516,12 @@ void cpx_mtx_clean()
        err = clReleaseCommandQueue(cpx_mtx_command_queue);
        if (err != CL_SUCCESS)
        {
-               fprintf(stderr, "GPU error: clReleaseCommandQueue() failed.\n");
+               fprintf(stderr, "QAnsel (GPU): clReleaseCommandQueue() failed.\n");
        }
        err = clReleaseContext(cpx_mtx_context);
        if (err != CL_SUCCESS)
        {
-               fprintf(stderr, "GPU error: clReleaseContext() failed.\n");
+               fprintf(stderr, "QAnsel (GPU): clReleaseContext() failed.\n");
        }
        free(cpx_mtx_cache);
 }
@@ -650,7 +652,7 @@ void cpx_copy(float* ptr, cl_mem* buff, size_t* buff_size)
             exit(1);
         }
        }
-    for (uint32_t i = 0; i < threadCount; i++)
+    for (unsigned int i = 0; i < threadCount; i++)
     {
         if (pthread_join(threads[i], NULL))
         {
@@ -674,7 +676,7 @@ void cpx_mtx_knk_metal(float* ptrR, float* ptrA, float* ptrB, int rowsA, int col
        cl_mem memR = clCreateBuffer(cpx_mtx_context, CL_MEM_WRITE_ONLY, sizeR, NULL, &err); gpuerr(err);
        
        //Populate buffers
-       unsigned long long int q = get_time();
+       unsigned long long int q = qansel_get_time();
        err = clEnqueueWriteBuffer(cpx_mtx_command_queue, memA, CL_TRUE, 0, sizeA, ptrA, 0, NULL, NULL);
     gpuerr(err);
        err = clEnqueueWriteBuffer(cpx_mtx_command_queue, memB, CL_TRUE, 0, sizeB, ptrB, 0, NULL, NULL);
diff --git a/src/context.c b/src/context.c
new file mode 100644 (file)
index 0000000..27528ce
--- /dev/null
@@ -0,0 +1,111 @@
+int qanselContextValidate(QAnselContext* ctx)
+{
+       if (ctx->memory_limit == 0) ctx->memory_limit = QANSEL_QUBITS_MAX;
+       if (ctx->memory_limit > QANSEL_QUBITS_MAX)
+       {
+               fprintf(stderr, "QAnsel: Invalid memory limit.\n", ctx->memory_limit);
+               return 0;
+       }
+       
+       if (ctx->sampling_shots < 0 || ctx->sampling_shots > 100000)
+       {
+               fprintf(stderr, "QAnsel: Invalid number of shots.\n");
+               return 0;
+       }
+       if (ctx->display_delay < 0 || ctx->display_delay > 100)
+       {
+               fprintf(stderr, "QAnsel: Invalid display settings.\n");
+               return 0;
+       }
+       if (ctx->optimization_level < QANSEL_MODE_BARE || ctx->optimization_level > (QANSEL_MODE_THREADED | QANSEL_MODE_METAL | QANSEL_MODE_QUEUE))
+       {
+               fprintf(stderr, "QAnsel: Invalid optimization settings.\n");
+               return 0;
+       }
+
+       switch (ctx->hardware_rng)
+       {
+               case QANSEL_HARDWARE_NONE:
+               case QANSEL_HARDWARE_AUTO:
+               case QANSEL_HARDWARE_TRUERNG:
+               case QANSEL_HARDWARE_RDSEED:
+                       break;
+               default:
+                       fprintf(stderr, "QAnsel: Invalid hardware settings.\n");
+                       return 0;
+       }
+
+       return 1;
+
+}
+
+int qanselContextBegin(QAnselContext* ctx)
+{
+       if (ctx->memory_limit == 0) ctx->memory_limit = QANSEL_QUBITS_MAX;
+       if (ctx->memory_limit > QANSEL_QUBITS_MAX)
+       {
+               fprintf(stderr, "QAnsel: Invalid memory limit.\n", ctx->memory_limit);
+               return 0;
+       }
+       
+       if (ctx->sampling_shots < 0 || ctx->sampling_shots > 100000)
+       {
+               fprintf(stderr, "QAnsel: Invalid number of shots.\n");
+               return 0;
+       }
+       if (ctx->display_delay < 0 || ctx->display_delay > 100)
+       {
+               fprintf(stderr, "QAnsel: Invalid display settings.\n");
+               return 0;
+       }
+       if (ctx->optimization_level < QANSEL_MODE_BARE || ctx->optimization_level > (QANSEL_MODE_THREADED | QANSEL_MODE_METAL | QANSEL_MODE_QUEUE))
+       {
+               fprintf(stderr, "QAnsel: Invalid optimization settings.\n");
+               return 0;
+       }
+
+       if (ctx->hardware_rng == QANSEL_HARDWARE_AUTO)
+       {
+               ctx->random_file = fopen("/dev/TrueRNG0", "r");
+               if (ctx->random_file == NULL)
+               {
+                       if (qansel_hardware_rand_supported())
+                       {
+                               if (ctx->verbose) printf("QAnsel: Hardware `Intel Secure Key Technology` selected.\n");
+                               ctx->hardware_rng = QANSEL_HARDWARE_RDSEED;
+                       }
+                       else
+                       {
+                               fprintf(stderr, "QAnsel: No supported hardware random number generator found.\n");
+                               return 0;
+                       }
+               }
+               else
+               {
+                       if (ctx->verbose) printf("QAnsel: Hardware `TrueRNG` selected.\n");
+                       ctx->hardware_rng = QANSEL_HARDWARE_TRUERNG;
+               }
+       }
+       if (ctx->optimization_level & QANSEL_MODE_METAL)
+       {
+               if (!cpx_mtx_begin(ctx->verbose))
+               {
+                       fprintf(stderr, "QAnsel: No supported hardware accelerator found.\n");
+                       return 0;
+               }
+       }
+       if (ctx->sampling_shots == 0)
+       {
+               ctx->sampling_shots = QANSEL_SHOTS_DEFAULT;
+       }
+
+       return 1;
+
+}
+
+int qanselContextEnd(QAnselContext* ctx)
+{
+       if (ctx->random_file != NULL) fclose(ctx->random_file);
+       if (ctx->optimization_level & QANSEL_MODE_METAL) cpx_mtx_clean();
+       return 1;
+}
\ No newline at end of file
index 3b6d3b293fe69739e71d93e1cd47c89c3da72e86..89c1d5408e948b53ecd964587846771914079b2a 100644 (file)
@@ -1,15 +1,4 @@
-#include <stdio.h>
-#include <time.h>
-#if defined(_WIN32) || defined(_WIN64)
-#include <windows.h>
-#elif defined(__linux__)
-#include <unistd.h>
-#include <sys/time.h>
-#elif defined(__APPLE__)
-#include <sys/sysctl.h>
-#endif
-
-int ___get_core_count()
+int qansel___get_core_count()
 {
     #if defined(_WIN32) || defined(_WIN64)
     SYSTEM_INFO sysinfo;
@@ -39,12 +28,12 @@ int ___get_core_count()
     #endif
 }
 
-int get_core_count()
+int qansel_get_core_count()
 {
     static int coreCount = -1;
     if (coreCount == -1)
     {
-        coreCount = ___get_core_count();
+        coreCount = qansel___get_core_count();
         if (coreCount == -1)
         {
             coreCount = 1;
@@ -53,7 +42,7 @@ int get_core_count()
     return coreCount;
 }
 
-unsigned long int get_time()
+unsigned long int qansel_get_time()
 {
     struct timeval tv;
     gettimeofday(&tv,NULL);
@@ -66,7 +55,9 @@ int qansel_hardware_rand_supported()
     #if defined(__x86_64__) || defined(__i386__)
     int result = 0;
 
-    // Execute CPUID instruction with feature request
+    //Check for RDSEED
+    //  https://en.wikipedia.org/wiki/CPUID#Calling_CPUID
+    //  accessed 14-03-2024
     __asm__ volatile
         (
             "mov $7, %%eax;mov $0, %%ecx;cpuid;mov %%ebx, %0;"
@@ -79,7 +70,10 @@ int qansel_hardware_rand_supported()
     return 0;
     #endif
 }
-int qansel_hardware_rand()
-{
 
+unsigned char qansel_hardware_rand()
+{
+    unsigned long long int r;
+    __asm__ volatile ("1:;rdseed %0;;jnc 1b;" : "=r" (r));
+    return r & 0xFF;
 }
index e7dd096d44f041bde617c414f8e8667289d2b321..675640cbed12187a332e0b7ced796581ea9b4bab 100644 (file)
@@ -13,6 +13,9 @@ void display_help()
        printf("                       used to set an even lower limit.\n");
        printf("              -sX      Used for setting the number of shots\n");
        printf("                       when sampling to X.\n");
+       printf("              -hX      Use a hidden variable rather than\n");
+       printf("                       randomly generating measurement\n");
+       printf("                       results.\n");
        printf("              -r       Enables a supported hardware random\n");
        printf("                       number generator.\n");
        printf("              -v       Enables verbose mode.\n");
@@ -29,67 +32,25 @@ void display_help()
 
 void main(int argc, char** argv)
 {
+       QAnselContext ctx = {0};
 
-       printf("%i\n", qansel_hardware_rand_supported());
-       return;
        int opt;
-       int maximumQubitSettings = QANSEL_QUBITS_MAX;
-       int hardwarerngSetting = 0;
-       
-    while ((opt = getopt(argc, argv, "o:q:d:s:rvq?")) != -1)
+    while ((opt = getopt(argc, argv, "o:q:d:s:h:rvq?")) != -1)
        {
                switch (opt)
                {
-                       case 'o': QANSEL_MODE = atoi(optarg); break;
-                       case 'd': QANSEL_USE_DISPLAY = atoi(optarg); break;
-                       case 'q': QANSEL_QUBIT_LIMIT = atoi(optarg); break;
-                       case 's': QANSEL_SAMPLE_COUNT = atoi(optarg); break;
-                       case 'r': hardwarerngSetting = 1; break;
-                       case 'v': QANSEL_VERBOSE = 1; break;
+                       case 'o': ctx.optimization_level = atoi(optarg); break;
+                       case 'd': ctx.display_delay = atoi(optarg); break;
+                       case 'q': ctx.memory_limit = atoi(optarg); break;
+                       case 's': ctx.sampling_shots = atoi(optarg); break;
+                       case 'r': ctx.hardware_rng = 1; break;
+                       case 'h': ctx.hidden_variable = atof(optarg); break;
+                       case 'v': ctx.verbose = 1; break;
                        case '?': display_help(); break;
                        default: exit(1);
                }
        }
 
-       if (QANSEL_SAMPLE_COUNT < 0 || QANSEL_SAMPLE_COUNT > 100000)
-       {
-               fprintf(stderr, "QAnsel: Invalid number of shots.\n");
-               exit(1);
-       }
-       if (QANSEL_USE_DISPLAY < 0 || QANSEL_USE_DISPLAY > 100)
-       {
-               fprintf(stderr, "QAnsel: Invalid display settings.\n");
-               exit(1);
-       }
-       if (QANSEL_MODE < QANSEL_MODE_BARE || QANSEL_MODE > (QANSEL_MODE_THREADED | QANSEL_MODE_METAL | QANSEL_MODE_QUEUE))
-       {
-               fprintf(stderr, "QAnsel: Invalid optimization settings.\n");
-               exit(1);
-       }
-       if (QANSEL_QUBIT_LIMIT <= 0 || QANSEL_QUBIT_LIMIT > QANSEL_QUBITS_MAX)
-       {
-               fprintf(stderr, "QAnsel: Invalid limit for quantum bits.\n");
-               exit(1);
-       }
-
-       if (hardwarerngSetting == 1)
-       {
-               QANSEL_RANDOM_FILE = fopen("/dev/TrueRNG0", "r");
-               if (QANSEL_RANDOM_FILE == NULL)
-               {
-                       fprintf(stderr, "QAnsel: No supported hardware random number generator found.\n");
-                       exit(1);
-               }
-       }
-       if (QANSEL_MODE & QANSEL_MODE_METAL)
-       {
-               if (!cpx_mtx_begin())
-               {
-                       fprintf(stderr, "QAnsel: No supported hardware accelerator found.\n");
-                       exit(1);
-               }
-       }
-
        char* script = malloc(0);
        size_t scriptSize = 0;
        int c;
@@ -103,14 +64,14 @@ void main(int argc, char** argv)
 
        unsigned char* bytecode;
        int bytecodeSize;
-       if (qanselBuildFromSource(script, &bytecode, &bytecodeSize))
+
+       if (!qanselContextBegin(&ctx)) exit(1);
+       if (qanselBuildFromSource(script, &bytecode, &bytecodeSize, &ctx))
        {
-               qanselExecuteBytecode(bytecode, bytecodeSize);
+               qanselExecuteBytecode(bytecode, bytecodeSize, &ctx);
+               free(bytecode);
        }
-       free(bytecode);
-
-       if (QANSEL_RANDOM_FILE != NULL) fclose(QANSEL_RANDOM_FILE);
-       if (QANSEL_MODE & QANSEL_MODE_METAL) cpx_mtx_clean();
+       qanselContextEnd(&ctx);
        return;
 
 }
\ No newline at end of file
index 2a3fbaae22e1b8ed3b516e095aae50b6c9d7eb6e..24b65bcb1cf75916b572953a0c54aecd0435e701 100644 (file)
@@ -202,7 +202,7 @@ int qansel_parse_float(char* str, float* returnFloat)
        return 1;
 }
 
-int qansel_process_chunk(int index, char* chunk, int line, regmatch_t* regmatches, int* qubitCount, int* bitCount, unsigned char** binary, int* binarySize)
+int qansel_process_chunk(int index, char* chunk, int line, regmatch_t* regmatches, int* qubitCount, int* bitCount, unsigned char** binary, int* binarySize, QAnselContext* ctx, int samplingshots)
 {
        unsigned short s0;
        float d0, d1, d2;
@@ -223,9 +223,9 @@ int qansel_process_chunk(int index, char* chunk, int line, regmatch_t* regmatche
                memcpy(tmp, chunk + strbeg, strlen);
                tmp[strlen] = 0;
                int nump = atoi(tmp);
-               if (nump > QANSEL_QUBIT_LIMIT)
+               if (nump > ctx->memory_limit)
                {
-                       fprintf(stderr, "QAnsel on line %i: Initialized qubits cannot exceed %i.\n", line, QANSEL_QUBIT_LIMIT);
+                       fprintf(stderr, "QAnsel on line %i: Initialized qubits cannot exceed %i.\n", line, ctx->memory_limit);
                        return 0;
                }
                *qubitCount = nump;
@@ -243,9 +243,9 @@ int qansel_process_chunk(int index, char* chunk, int line, regmatch_t* regmatche
                memcpy(tmp, chunk + strbeg, strlen);
                tmp[strlen] = 0;
                int nump = atoi(tmp);
-               if (nump > QANSEL_QUBIT_LIMIT)
+               if (nump > ctx->memory_limit)
                {
-                       fprintf(stderr, "QAnsel on line %i: Initialized classical bits cannot exceed %i.\n", line, QANSEL_QUBIT_LIMIT);
+                       fprintf(stderr, "QAnsel on line %i: Initialized classical bits cannot exceed %i.\n", line, ctx->memory_limit);
                        return 0;
                }
                *bitCount = nump;
@@ -445,7 +445,7 @@ int qansel_process_chunk(int index, char* chunk, int line, regmatch_t* regmatche
                        char tmp[strlen + 1];
                        memcpy(tmp, chunk + strbeg, strlen);
                        tmp[strlen] = 0;
-                       if (strcmp(tmp, "sample") == 0) instr = QANSEL_INSTRUCTION_SAMPLE;
+                       if (strcmp(tmp, "sample") == 0) instr = 0x00;
                        else if (strcmp(tmp, "reset") == 0) instr = QANSEL_INSTRUCTION_RESET;
                        else if (strcmp(tmp, "print") == 0) instr = QANSEL_INSTRUCTION_PRINT;
                }
@@ -474,10 +474,20 @@ int qansel_process_chunk(int index, char* chunk, int line, regmatch_t* regmatche
                                a0 = QANSEL_ALL_CLASSIC;
                        }
                }
-               *binarySize += 2;
-               *binary = realloc(*binary, (*binarySize));
-               (*binary)[(*binarySize) - 2] = instr;
-               (*binary)[(*binarySize) - 1] = a0;
+               if (instr == 0x00) //sample
+               {
+                       if (a0 == QANSEL_ALL_QUANTUM) a0 = QANSEL_ALL;
+                       else a0 = a0 - QANSEL_CBOUND_LOWER; 
+                       ctx->sampling_bit = a0;
+                       ctx->sampling_shots = samplingshots;
+               }
+               else
+               {
+                       *binarySize += 2;
+                       *binary = realloc(*binary, (*binarySize));
+                       (*binary)[(*binarySize) - 2] = instr;
+                       (*binary)[(*binarySize) - 1] = a0;
+               }
        }
        else if (index == 8 || index == 9) //double qubit instructions
        {
@@ -634,7 +644,7 @@ int qansel_process_chunk(int index, char* chunk, int line, regmatch_t* regmatche
                        char tmp[strlen + 1];
                        memcpy(tmp, chunk + strbeg, strlen);
                        tmp[strlen] = 0;
-                       if (strcmp(tmp, "hvar") == 0) instr = QANSEL_INSTRUCTION_HVAR;
+                       if (strcmp(tmp, "hvar") == 0) instr = 1;
                }
                {
                        int strbeg = regmatches[rmp].rm_so;
@@ -649,10 +659,10 @@ int qansel_process_chunk(int index, char* chunk, int line, regmatch_t* regmatche
                                return 0;
                        }
                }
-               *binarySize += 1 + sizeof(float);
-               *binary = realloc(*binary, (*binarySize));
-               (*binary)[(*binarySize) - 1 - sizeof(float)] = instr;
-               memcpy((*binary) + ((*binarySize) - sizeof(float)), &d0, sizeof(float));
+               switch (instr)
+               {
+                       case 1: ctx->hidden_variable = d0; break;
+               }
        }
        else if (index == 12) //lone instructions
        {
@@ -664,7 +674,11 @@ int qansel_process_chunk(int index, char* chunk, int line, regmatch_t* regmatche
                        char tmp[strlen + 1];
                        memcpy(tmp, chunk + strbeg, strlen);
                        tmp[strlen] = 0;
-                       if (strcmp(tmp, "rand") == 0) instr = QANSEL_INSTRUCTION_RAND;
+                       if (strcmp(tmp, "rand") == 0)
+                       {
+                               ctx->hidden_variable = 0;
+                               return 1;
+                       }
                        else if (strcmp(tmp, "exit") == 0) instr = QANSEL_INSTRUCTION_EXIT;
                }
                *binarySize += 1;
@@ -674,7 +688,7 @@ int qansel_process_chunk(int index, char* chunk, int line, regmatch_t* regmatche
        return 1;
 }
 
-int qansel_process_chunks(char** chunks, int* associatedLines, int count, unsigned char** retBinary, int* retSize)
+int qansel_process_chunks(char** chunks, int* associatedLines, int count, unsigned char** retBinary, int* retSize, QAnselContext* ctx, int samplingshots)
 {
        unsigned char* binary = malloc(0);
        int binarySize = 0;
@@ -715,7 +729,7 @@ int qansel_process_chunks(char** chunks, int* associatedLines, int count, unsign
                        if (!ret)
                        {
                                found = 1;
-                               status = qansel_process_chunk(j, chunks[i], associatedLines[i], regmatches, &qubitCount, &bitCount, &binary, &binarySize);
+                               status = qansel_process_chunk(j, chunks[i], associatedLines[i], regmatches, &qubitCount, &bitCount, &binary, &binarySize, ctx, samplingshots);
                                break;
                        }
                        else if (ret == REG_NOMATCH) {}
@@ -738,14 +752,17 @@ int qansel_process_chunks(char** chunks, int* associatedLines, int count, unsign
        return status;
 }
 
-int qanselBuildFromSource(char* source, unsigned char** binary, int* binarySize)
+int qanselBuildFromSource(char* source, unsigned char** binary, int* binarySize, QAnselContext* ctx)
 {
+       if (!qanselContextValidate(ctx)) return 0;
        char** chunks;
        int* chunksAssociatedLines;
        int chunksCount;
        int status = qansel_read_script(source, &chunks, &chunksAssociatedLines, &chunksCount);
+       int samplingshots = ctx->sampling_shots;
+       ctx->sampling_shots = 0;
        if (!status) return 0;
-       status = qansel_process_chunks(chunks, chunksAssociatedLines, chunksCount, binary, binarySize);
+       status = qansel_process_chunks(chunks, chunksAssociatedLines, chunksCount, binary, binarySize, ctx, samplingshots);
        for (int i = 0; i < chunksCount; i++) free(chunks[i]);
        free(chunks);
        free(chunksAssociatedLines);
@@ -756,6 +773,8 @@ int qanselBuildFromSource(char* source, unsigned char** binary, int* binarySize)
                free(*binary);
                return 0;
        }
+
+       //qansel_reorder(ctx, *binary, *binarySize);
        return 1;
 
 }
index 60a932be80f2dcf37e603f223aa21f8bec779d99..875e169e643d4e0b9876b25beed1ece9dc698e86 100644 (file)
@@ -7,25 +7,30 @@
 #include <math.h>
 #include <regex.h>
 #include <time.h>
-#include "complex.c"
-#include "gates.c"
-#include "display.c"
+#include <pthread.h>
+#include <string.h>
+#include <time.h>
+#if defined(_WIN32) || defined(_WIN64)
+#include <windows.h>
+#elif defined(__linux__)
+#include <unistd.h>
+#include <sys/time.h>
+#elif defined(__APPLE__)
+#include <sys/sysctl.h>
+#endif
+
+#define QANSEL_SHOTS_DEFAULT 1000
 #define QANSEL_QUBITS_MAX 16
-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;
-unsigned char QANSEL_USE_QUEUE = 0;
-#define QANSEL_DEFAULT_SAMPLE_COUNT 1000
-int QANSEL_SAMPLE_COUNT = QANSEL_DEFAULT_SAMPLE_COUNT;
-FILE* QANSEL_RANDOM_FILE = NULL;
 #define QANSEL_MODE_BARE 0
 #define QANSEL_MODE_THREADED 1
 #define QANSEL_MODE_METAL 2
 #define QANSEL_MODE_QUEUE 4
-unsigned char QANSEL_MODE = QANSEL_MODE_BARE;
 //#define SPEED_TEST
 
+#define QANSEL_HARDWARE_NONE 0
+#define QANSEL_HARDWARE_AUTO 1
+#define QANSEL_HARDWARE_TRUERNG 2
+#define QANSEL_HARDWARE_RDSEED 3
 #define QANSEL_INSTRUCTION_X 0x10
 #define QANSEL_INSTRUCTION_Y 0x11
 #define QANSEL_INSTRUCTION_Z 0x12
@@ -43,21 +48,18 @@ unsigned char QANSEL_MODE = QANSEL_MODE_BARE;
 #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_DENSITY 0xD1
+#define QANSEL_INSTRUCTION_BORN 0xD2
 #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_INSTRUCTION_PRINT 0xF0
+#define QANSEL_INSTRUCTION_RESET 0xF1
+#define QANSEL_INSTRUCTION_BARRIER 0xF2
+#define QANSEL_INSTRUCTION_EXIT 0xF3
 
 #define QANSEL_FLAGS_EQUAL   0b00001
 #define QANSEL_FLAGS_GREATER 0b00010
@@ -72,6 +74,40 @@ unsigned char QANSEL_MODE = QANSEL_MODE_BARE;
 #define QANSEL_ALL_CLASSIC 0x3F
 #define QANSEL_ALL 0xFF
 
+typedef struct
+{
+       unsigned char memory_limit;
+       unsigned char hardware_rng;
+       unsigned char verbose;
+       unsigned char optimization_level;
+       unsigned char sampling_bit;
+       float hidden_variable;
+       int display_delay;
+       int sampling_shots;
+       FILE* random_file;
+} QAnselContext;
+
+typedef struct
+{
+       int size;
+       unsigned char bytes[16];
+       int barrier_width;
+       unsigned char barrier[QANSEL_QUBITS_MAX * 2];
+       int next;
+       int prev;
+       int checked;
+       int op;
+       unsigned char ifop[16];
+       int use_ifop;
+} QBytecode;
+
+#include "kernel_cpu.cl"
+#include "kernel_gpu.cl"
+#include "hardware.c"
+#include "complex.c"
+#include "context.c"
+#include "gates.c"
+#include "display.c"
 #include "bytecode.c"
 #include "openqasm.c"
 #endif
\ No newline at end of file