mirror of
https://github.com/libquantum/libquantum.git
synced 2025-10-03 16:51:37 +00:00
447 lines
9.0 KiB
C
447 lines
9.0 KiB
C
/* objcode.c: Quantum object code functions
|
|
|
|
Copyright 2003 Bjoern Butscher, Hendrik Weimer
|
|
|
|
This file is part of libquantum
|
|
|
|
libquantum is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published
|
|
by the Free Software Foundation; either version 3 of the License,
|
|
or (at your option) any later version.
|
|
|
|
libquantum is distributed in the hope that it will be useful, but
|
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with libquantum; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
MA 02110-1301, USA
|
|
|
|
*/
|
|
|
|
#include <stdarg.h>
|
|
#include <fcntl.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
|
|
#include "objcode.h"
|
|
#include "config.h"
|
|
#include "matrix.h"
|
|
#include "qureg.h"
|
|
#include "gates.h"
|
|
#include "measure.h"
|
|
#include "error.h"
|
|
|
|
/* status of the objcode functionality (0 = disabled) */
|
|
|
|
int opstatus = 0;
|
|
|
|
/* Generated OBJCODE data */
|
|
|
|
unsigned char *objcode = 0;
|
|
|
|
/* Current POSITION of the last instruction in the OBJCODE array */
|
|
|
|
unsigned long position = 0;
|
|
|
|
/* Number of ALLOCATED pages */
|
|
|
|
unsigned long allocated = 0;
|
|
|
|
/* file to write the object code to, if not given */
|
|
|
|
char *globalfile;
|
|
|
|
/* Convert a big integer to a byte array */
|
|
|
|
void
|
|
quantum_mu2char(MAX_UNSIGNED mu, unsigned char *buf)
|
|
{
|
|
int i, size;
|
|
|
|
size = sizeof(MAX_UNSIGNED);
|
|
|
|
for(i=0; i<size; i++)
|
|
{
|
|
buf[i] = mu / ((MAX_UNSIGNED) 1 << ((size - i - 1) * 8));
|
|
mu %= (MAX_UNSIGNED) 1 << ((size - i - 1) * 8);
|
|
}
|
|
}
|
|
|
|
/* Convert an integer to a byte array */
|
|
|
|
void
|
|
quantum_int2char(int j, unsigned char *buf)
|
|
{
|
|
int i, size;
|
|
|
|
size = sizeof(int);
|
|
|
|
for(i=0; i<size; i++)
|
|
{
|
|
buf[i] = j / (1 << ((size - i - 1) * 8));
|
|
j %= (1 << ((size - i - 1) * 8));
|
|
}
|
|
}
|
|
|
|
/* Copy the binary representation of a double to a byte array */
|
|
|
|
void
|
|
quantum_double2char(double d, unsigned char *buf)
|
|
{
|
|
int i;
|
|
unsigned char *p = (unsigned char *) &d;
|
|
|
|
for(i=0; i<sizeof(double); i++)
|
|
buf[i] = p[i];
|
|
}
|
|
|
|
MAX_UNSIGNED quantum_char2mu(unsigned char *buf)
|
|
{
|
|
int i, size;
|
|
MAX_UNSIGNED mu = 0;
|
|
|
|
size = sizeof(MAX_UNSIGNED);
|
|
|
|
for(i=size-1; i>=0 ; i--)
|
|
mu += buf[i] * ((MAX_UNSIGNED) 1 << (8 * (size - i - 1)));
|
|
|
|
return mu;
|
|
}
|
|
|
|
int quantum_char2int(unsigned char *buf)
|
|
{
|
|
int i, size;
|
|
int j = 0;
|
|
|
|
size = sizeof(int);
|
|
|
|
for(i=size-1; i>=0 ; i--)
|
|
j += buf[i] * (1 << (8 * (size - i - 1)));
|
|
|
|
return j;
|
|
}
|
|
|
|
double quantum_char2double(unsigned char *buf)
|
|
{
|
|
double *d = (double *) buf;
|
|
|
|
return *d;
|
|
}
|
|
|
|
|
|
/* Start object code recording */
|
|
|
|
void
|
|
quantum_objcode_start()
|
|
{
|
|
opstatus = 1;
|
|
allocated = 1;
|
|
objcode = malloc(OBJCODE_PAGE * sizeof(char));
|
|
|
|
if(!objcode)
|
|
quantum_error(QUANTUM_ENOMEM);
|
|
|
|
quantum_memman(OBJCODE_PAGE * sizeof(char));
|
|
}
|
|
|
|
/* Stop object code recording */
|
|
|
|
void
|
|
quantum_objcode_stop()
|
|
{
|
|
opstatus = 0;
|
|
free(objcode);
|
|
objcode = 0;
|
|
quantum_memman(- allocated * OBJCODE_PAGE * sizeof(char));
|
|
allocated = 0;
|
|
}
|
|
|
|
/* Store an operation with its arguments in the object code data */
|
|
|
|
int
|
|
quantum_objcode_put(unsigned char operation, ...)
|
|
{
|
|
int i, size = 0;
|
|
va_list args;
|
|
unsigned char buf[80];
|
|
double d;
|
|
MAX_UNSIGNED mu;
|
|
|
|
if(!opstatus)
|
|
return 0;
|
|
|
|
va_start(args, operation);
|
|
|
|
buf[0] = operation;
|
|
|
|
switch(operation)
|
|
{
|
|
case INIT:
|
|
mu = va_arg(args, MAX_UNSIGNED);
|
|
quantum_mu2char(mu, &buf[1]);
|
|
size = sizeof(MAX_UNSIGNED) + 1;
|
|
break;
|
|
case CNOT:
|
|
case COND_PHASE:
|
|
i = va_arg(args, int);
|
|
quantum_int2char(i, &buf[1]);
|
|
i = va_arg(args, int);
|
|
quantum_int2char(i, &buf[sizeof(int)+1]);
|
|
size = 2 * sizeof(int) + 1;
|
|
break;
|
|
case TOFFOLI:
|
|
i = va_arg(args, int);
|
|
quantum_int2char(i, &buf[1]);
|
|
i = va_arg(args, int);
|
|
quantum_int2char(i, &buf[sizeof(int)+1]);
|
|
i = va_arg(args, int);
|
|
quantum_int2char(i, &buf[2*sizeof(int)+1]);
|
|
size = 3 * sizeof(int) + 1;
|
|
break;
|
|
case SIGMA_X:
|
|
case SIGMA_Y:
|
|
case SIGMA_Z:
|
|
case HADAMARD:
|
|
case BMEASURE:
|
|
case BMEASURE_P:
|
|
case SWAPLEADS:
|
|
i = va_arg(args, int);
|
|
quantum_int2char(i, &buf[1]);
|
|
size = sizeof(int) + 1;
|
|
break;
|
|
case ROT_X:
|
|
case ROT_Y:
|
|
case ROT_Z:
|
|
case PHASE_KICK:
|
|
case PHASE_SCALE:
|
|
i = va_arg(args, int);
|
|
d = va_arg(args, double);
|
|
quantum_int2char(i, &buf[1]);
|
|
quantum_double2char(d, &buf[sizeof(int)+1]);
|
|
size = sizeof(int) + sizeof(double) + 1;
|
|
break;
|
|
case CPHASE_KICK:
|
|
i = va_arg(args, int);
|
|
quantum_int2char(i, &buf[1]);
|
|
i = va_arg(args, int);
|
|
quantum_int2char(i, &buf[sizeof(int)+1]);
|
|
d = va_arg(args, double);
|
|
quantum_double2char(d, &buf[2*sizeof(int)+1]);
|
|
size = 2 * sizeof(int) + sizeof(double) + 1;
|
|
break;
|
|
case MEASURE:
|
|
case NOP:
|
|
size = 1;
|
|
break;
|
|
default:
|
|
quantum_error(QUANTUM_EOPCODE);
|
|
}
|
|
|
|
if((position+size) / OBJCODE_PAGE > position / OBJCODE_PAGE)
|
|
{
|
|
allocated++;
|
|
objcode = realloc(objcode, allocated * OBJCODE_PAGE);
|
|
|
|
if(!objcode)
|
|
quantum_error(QUANTUM_ENOMEM);
|
|
|
|
quantum_memman(OBJCODE_PAGE * sizeof(char));
|
|
}
|
|
|
|
for(i=0; i<size; i++)
|
|
{
|
|
objcode[position] = buf[i];
|
|
position++;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
/* Save the recorded object code data to a file */
|
|
|
|
int
|
|
quantum_objcode_write(char *file)
|
|
{
|
|
FILE *fhd;
|
|
|
|
if(!opstatus)
|
|
{
|
|
fprintf(stderr, "Object code generation not active! Forgot to call quantum_objcode_start?\n");
|
|
return 1;
|
|
}
|
|
|
|
if(!file)
|
|
file = globalfile;
|
|
|
|
fhd = fopen(file, "w");
|
|
|
|
if (fhd == 0)
|
|
return -1;
|
|
|
|
fwrite(objcode, position, 1, fhd);
|
|
|
|
fclose(fhd);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Set a global variable containing the file to write the data to */
|
|
|
|
void
|
|
quantum_objcode_file(char *file)
|
|
{
|
|
globalfile = file;
|
|
}
|
|
|
|
/* This function is used as a hook before exiting, as atexit(3) does
|
|
not support to supply arguments to a function */
|
|
|
|
void
|
|
quantum_objcode_exit(char *file)
|
|
{
|
|
quantum_objcode_write(0);
|
|
quantum_objcode_stop();
|
|
}
|
|
|
|
/* Execute the contents of an object code file */
|
|
|
|
void
|
|
quantum_objcode_run(char *file, quantum_reg *reg)
|
|
{
|
|
int i, j, k, l;
|
|
FILE *fhd;
|
|
unsigned char operation;
|
|
unsigned char buf[OBJBUF_SIZE];
|
|
MAX_UNSIGNED mu;
|
|
double d;
|
|
|
|
fhd = fopen(file, "r");
|
|
|
|
if(!fhd)
|
|
{
|
|
fprintf(stderr, "quantum_objcode_run: Could not open %s: ", file);
|
|
perror(0);
|
|
return;
|
|
}
|
|
|
|
for(i=0; !feof(fhd); i++)
|
|
{
|
|
for(j=0; j<OBJBUF_SIZE; j++)
|
|
buf[j] = 0;
|
|
|
|
operation = fgetc(fhd);
|
|
switch(operation)
|
|
{
|
|
case INIT:
|
|
fread(buf, sizeof(MAX_UNSIGNED), 1, fhd);
|
|
mu = quantum_char2mu(buf);
|
|
*reg = quantum_new_qureg(mu, 12);
|
|
break;
|
|
|
|
case CNOT:
|
|
case COND_PHASE:
|
|
fread(buf, sizeof(int), 1, fhd);
|
|
j = quantum_char2int(buf);
|
|
fread(buf, sizeof(int), 1, fhd);
|
|
k = quantum_char2int(buf);
|
|
switch(operation)
|
|
{
|
|
case CNOT: quantum_cnot(j, k, reg);
|
|
break;
|
|
case COND_PHASE: quantum_cond_phase(j, k, reg);
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case TOFFOLI:
|
|
fread(buf, sizeof(int), 1, fhd);
|
|
j = quantum_char2int(buf);
|
|
fread(buf, sizeof(int), 1, fhd);
|
|
k = quantum_char2int(buf);
|
|
fread(buf, sizeof(int), 1, fhd);
|
|
l = quantum_char2int(buf);
|
|
quantum_toffoli(j, k, l, reg);
|
|
break;
|
|
|
|
case SIGMA_X:
|
|
case SIGMA_Y:
|
|
case SIGMA_Z:
|
|
case HADAMARD:
|
|
case BMEASURE:
|
|
case BMEASURE_P:
|
|
case SWAPLEADS:
|
|
fread(buf, sizeof(int), 1, fhd);
|
|
j = quantum_char2int(buf);
|
|
switch(operation)
|
|
{
|
|
case SIGMA_X: quantum_sigma_x(j, reg);
|
|
break;
|
|
case SIGMA_Y: quantum_sigma_y(j, reg);
|
|
break;
|
|
case SIGMA_Z: quantum_sigma_z(j, reg);
|
|
break;
|
|
case HADAMARD: quantum_hadamard(j, reg);
|
|
break;
|
|
case BMEASURE: quantum_bmeasure(j, reg);
|
|
break;
|
|
case BMEASURE_P: quantum_bmeasure_bitpreserve(j, reg);
|
|
break;
|
|
case SWAPLEADS: quantum_swaptheleads(j, reg);
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case ROT_X:
|
|
case ROT_Y:
|
|
case ROT_Z:
|
|
case PHASE_KICK:
|
|
case PHASE_SCALE:
|
|
fread(buf, sizeof(int), 1, fhd);
|
|
j = quantum_char2int(buf);
|
|
fread(buf, sizeof(double), 1, fhd);
|
|
d = quantum_char2double(buf);
|
|
switch(operation)
|
|
{
|
|
case ROT_X: quantum_r_x(j, d, reg);
|
|
break;
|
|
case ROT_Y: quantum_r_y(j, d, reg);
|
|
break;
|
|
case ROT_Z: quantum_r_z(j, d, reg);
|
|
break;
|
|
case PHASE_KICK: quantum_phase_kick(j, d, reg);
|
|
break;
|
|
case PHASE_SCALE: quantum_phase_scale(j, d, reg);
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case CPHASE_KICK:
|
|
fread(buf, sizeof(int), 1, fhd);
|
|
j = quantum_char2int(buf);
|
|
fread(buf, sizeof(int), 1, fhd);
|
|
k = quantum_char2int(buf);
|
|
fread(buf, sizeof(double), 1, fhd);
|
|
d = quantum_char2double(buf);
|
|
quantum_cond_phase_kick(j, k, d, reg);
|
|
break;
|
|
|
|
case MEASURE: quantum_measure(*reg);
|
|
break;
|
|
|
|
case NOP:
|
|
break;
|
|
|
|
default:
|
|
fprintf(stderr, "%i: Unknown opcode 0x(%X)!\n", i, operation);
|
|
return;
|
|
}
|
|
|
|
}
|
|
|
|
fclose(fhd);
|
|
|
|
}
|