dynare/mex/sources/bytecode/testing/mex_interface.cc

523 lines
12 KiB
C++

/*
* Copyright © 2007-2011 Dynare Team
*
* This file is part of Dynare.
*
* Dynare 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.
*
* Dynare 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 Dynare. If not, see <http://www.gnu.org/licenses/>.
*/
#include "mex_interface.hh"
#include <cstring>
#include <sstream>
using namespace std;
map<string, mxArray *> mxglobal;
mxArray_tag::mxArray_tag()
{
type = mxDOUBLE_CLASS;
Ir = NULL;
Jc = NULL;
Nzmax = 0;
field_name.clear();
field_array.clear();
size_1 = 0;
size_2 = 0;
data = NULL;
}
int
mexPrintf(const char *str, ...)
{
va_list args;
int retval;
va_start(args, str);
retval = vprintf(str, args);
va_end(args);
return retval;
}
void
mexErrMsgTxt(const string str)
{
perror(str.c_str());
exit(EXIT_FAILURE);
}
void
mexWarnMsgTxt(const string str)
{
perror(str.c_str());
}
void
mxFree(void *to_release)
{
free(to_release);
}
void *
mxMalloc(unsigned int amount)
{
return malloc(amount);
}
void *
mxRealloc(void *to_extend, unsigned int amount)
{
return realloc(to_extend, amount);
}
void *
mxCalloc(unsigned int nb_elements, unsigned int amount_per_element)
{
return calloc(nb_elements, amount_per_element);
}
void
mexEvalString(const string str)
{
}
double *
mxGetPr(const mxArray *b_m)
{
return b_m->data;
}
mxArray *
mxCreateDoubleMatrix(unsigned int rows, unsigned int cols, mxData_type mx_type)
{
mxArray *Array = new mxArray;
Array->type = mxDOUBLE_CLASS;
Array->size_1 = rows;
Array->size_2 = cols;
Array->data = (double *) mxMalloc(rows*cols*sizeof(double));
return (Array);
}
mxArray *
mxCreateCharArray(unsigned int rows, unsigned int cols, mxData_type mx_type)
{
mxArray *Array = new mxArray;
Array->type = mxCHAR_CLASS;
Array->size_1 = rows;
Array->size_2 = cols;
Array->data = (double *) mxMalloc(2*rows*cols*sizeof(char));
return (Array);
}
mxArray *
mxCreateSparse(unsigned int rows, unsigned int cols, unsigned int nz_max, mxData_type mx_type)
{
mxArray *Array = new mxArray;
Array->type = mxSPARSE_CLASS;
Array->size_1 = rows;
Array->size_2 = cols;
Array->Nzmax = nz_max;
Array->data = (double *) mxMalloc(nz_max*sizeof(double));
Array->Ir = (mwIndex *) mxMalloc(nz_max*sizeof(mwIndex));
Array->Jc = (mwIndex *) mxMalloc((cols+1)*sizeof(mwIndex));
return (Array);
}
mxArray *
mxCreateDoubleScalar(double value)
{
mxArray *Array = new mxArray;
Array->type = mxSINGLE_CLASS;
Array->size_1 = 1;
Array->size_2 = 1;
Array->data = (double *) mxMalloc(sizeof(double));
Array->data[0] = value;
return (Array);
}
mxArray *
mxCreatNULLMatrix()
{
return NULL;
}
mxArray *
mxCreateStructMatrix(unsigned int rows, unsigned int cols, unsigned int nfields, const vector<string> &fieldnames)
{
mxArray *Array = new mxArray;
Array->type = mxSTRUCT_CLASS;
Array->size_1 = rows;
Array->size_2 = cols;
for (unsigned int i = 0; i < nfields; i++)
Array->field_name.push_back(fieldnames[i]);
return Array;
}
void
mxDestroyArray(mxArray *A_m)
{
mxFree(A_m->data);
if (A_m->Ir)
mxFree(A_m->Ir);
if (A_m->Jc)
mxFree(A_m->Jc);
mxFree(A_m);
}
mxArray *
mxSetNzmax(mxArray *A_m, mwSize nz_max)
{
A_m->Nzmax = nz_max;
A_m->data = (double *) mxRealloc(A_m->data, nz_max*sizeof(double));
A_m->Ir = (mwIndex *) mxRealloc(A_m->Ir, nz_max*sizeof(mwIndex));
return (A_m);
}
void
mexCallMATLAB(unsigned int n_lhs, mxArray *matrix_lhs[], unsigned int n_rhs, mxArray *matrix_rhs[], const char *function)
{
if (strncmp(function, "disp", 4) == 0)
{
int cols = mxGetN(matrix_rhs[0]);
int rows = mxGetM(matrix_rhs[0]);
if (matrix_rhs[0]->type == mxCHAR_CLASS)
{
char *p = (char *) matrix_rhs[0]->data;
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
mexPrintf("%c", p[2*(i+j*rows)]);
mexPrintf("\n");
}
}
else
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
mexPrintf("%8.4f ", matrix_rhs[0]->data[i+j*rows]);
mexPrintf("\n");
}
}
}
mxArray *
mexGetVariable(const char *space_name, const char *matrix_name)
{
if (strncmp(space_name, "global", 6) != 0)
mexErrMsgTxt("space_name not handle in mexGetVariable\n");
return mxglobal[matrix_name];
}
int
mxGetFieldNumber(const mxArray *Struct, const char *field_name)
{
vector<string>::const_iterator it = find(Struct->field_name.begin(), Struct->field_name.end(), field_name);
if (it == Struct->field_name.end())
{
stringstream tmp;
tmp << "unknown field name '" << field_name << "' in mxGetFieldNumber\n";
mexErrMsgTxt(tmp.str());
}
return it - Struct->field_name.begin();
}
mxArray *
mxGetFieldByNumber(mxArray *Struct, unsigned int pos, unsigned int field_number)
{
if (pos > Struct->size_1 * Struct->size_2)
mexErrMsgTxt("index out of range in mxGetFieldByNumber\n");
if (field_number > Struct->field_name.size())
mexErrMsgTxt("field_number out of range in mxGetFieldByNumber\n");
return Struct->field_array[pos][field_number];
}
int
mxAddField(mxArray *Struct, const char *fieldname)
{
if (!mxIsStruct(Struct))
return -1;
else
{
Struct->field_name.push_back(fieldname);
return Struct->field_name.size();
}
}
void
mxSetFieldByNumber(mxArray *Struct, mwIndex index, unsigned int field_number, mxArray *pvalue)
{
if (index >= Struct->size_1 * Struct->size_2)
mexErrMsgTxt("index out of range in mxSetFieldByNumber\n");
unsigned int nfields = Struct->field_name.size();
if (field_number >= nfields)
mexErrMsgTxt("field_number out of range in mxSetFieldByNumber\n");
while (Struct->field_array.size() <= index)
Struct->field_array.push_back(vector<mxArray *>(nfields, NULL));
Struct->field_array[index][field_number] = pvalue;
}
int
mxGetString(const mxArray *array, char *buf, unsigned int buflen)
{
unsigned int size;
if (!mxIsChar(array))
return -1;
else if (buflen <= (size = mxGetNumberOfElements(array)))
return -1;
else
{
char *pchar = (char *) array->data;
for (unsigned int i = 0; i < size; i++)
buf[i] = pchar[2*i];
buf[size+1] = ' ';
}
return 0;
}
mxArray *
mxDuplicateArray(const mxArray *array)
{
unsigned int Size;
unsigned int i;
vector<mxArray *>::const_iterator it_v_array;
vector<string>::const_iterator it_v_string;
mxArray *Array = (mxArray *) mxMalloc(sizeof(mxArray));
Array->type = array->type;
Array->size_1 = array->size_1;
Array->size_2 = Array->size_2;
switch (array->type)
{
case mxDOUBLE_CLASS:
case mxSINGLE_CLASS:
Size = array->size_1*array->size_2*sizeof(double);
Array->data = (double *) mxMalloc(Size);
memcpy(Array->data, array->data, Size);
break;
case mxSTRUCT_CLASS:
for (i = 0; i < array->size_1 * array->size_2; i++)
for (it_v_array = array->field_array[i].begin(); it_v_array != array->field_array[i].end(); it_v_array++)
Array->field_array[i].push_back(mxDuplicateArray(*it_v_array));
for (it_v_string = array->field_name.begin(); it_v_string != array->field_name.end(); it_v_string++)
Array->field_name.push_back(*it_v_string);
break;
case mxSPARSE_CLASS:
Array->Nzmax = array->Nzmax;
Size = array->Nzmax * sizeof(double);
Array->data = (double *) mxMalloc(Size);
memcpy(Array->data, array->data, Size);
Size = array->Nzmax * sizeof(mwIndex);
Array->Ir = (mwIndex *) mxMalloc(Size);
memcpy(Array->Ir, array->Ir, Size);
Size = array->size_2*sizeof(mwIndex);
Array->Jc = (mwIndex *) mxMalloc(Size);
memcpy(Array->Jc, array->Jc, Size);
break;
case mxCHAR_CLASS:
Size = 2*array->size_1*array->size_2*sizeof(char);
Array->data = (double *) mxMalloc(Size);
memcpy(Array->data, array->data, Size);
break;
default:
ostringstream tmp;
tmp << "Array type not handle: " << array->type << "\n";
mexErrMsgTxt(tmp.str());
}
return (Array);
}
mxArray *
read_struct(FILE *fid)
{
unsigned int nfields = 0;
fscanf(fid, "%d", &nfields);
unsigned int size_1, size_2;
fscanf(fid, "%d", &size_1);
fscanf(fid, "%d", &size_2);
vector<string> fieldnames;
vector<mxArray *> v_Array;
vector<vector<mxArray * >> vv_Array;
for (unsigned int j = 0; j < size_1 * size_2; j++)
{
for (unsigned int i = 0; i < nfields; i++)
{
char name[512];
fscanf(fid, "%s", name);
if (j == 0)
fieldnames.push_back(name);
v_Array.push_back(read_Array(fid));
}
vv_Array.push_back(v_Array);
v_Array.clear();
}
mxArray *Struct;
Struct = mxCreateStructMatrix(size_1, size_2, nfields, fieldnames);
for (unsigned int j = 0; j < size_1 * size_2; j++)
{
v_Array = vv_Array[j];
for (unsigned int i = 0; i < nfields; i++)
{
mxSetFieldByNumber(Struct, j, i, v_Array[i]);
}
}
return Struct;
}
mxArray *
read_double_array(FILE *fid)
{
int size_1, size_2;
fscanf(fid, "%d", &size_1);
fscanf(fid, "%d", &size_2);
mxArray *A = mxCreateDoubleMatrix(size_1, size_2, mxREAL);
double *data = mxGetPr(A);
float f;
for (int i = 0; i < size_1*size_2; i++)
{
fscanf(fid, "%f", &f);
data[i] = f;
}
return A;
}
mxArray *
read_char_array(FILE *fid)
{
unsigned int size_1, size_2;
fscanf(fid, "%d", &size_1);
fscanf(fid, "%d", &size_2);
mxArray *A = mxCreateCharArray(size_1, size_2, mxREAL);
char *data = (char *) mxGetPr(A);
char pchar[size_2+1];
for (unsigned int i = 0; i < size_1; i++)
{
fscanf(fid, "%s", pchar);
for (unsigned int j = 0; j < strlen(pchar); j++)
data[2*(i+j*size_1)] = pchar[j];
for (unsigned int j = strlen(pchar); j < size_2; j++)
data[2*(i+j*size_1)] = ' ';
}
return A;
}
mxArray *
read_Array(FILE *fid)
{
mxArray *Array;
mxArray_type array_type;
unsigned int j;
fscanf(fid, "%d", &j);
array_type = static_cast<mxArray_type>(j);
switch (array_type)
{
case mxDOUBLE_CLASS:
case mxSINGLE_CLASS:
Array = read_double_array(fid);
break;
case mxSTRUCT_CLASS:
Array = read_struct(fid);
break;
case mxCHAR_CLASS:
Array = read_char_array(fid);
break;
default:
ostringstream tmp;
tmp << "Array type not handle in read_Array: " << array_type << "\n";
mexErrMsgTxt(tmp.str());
}
return (Array);
}
void
load_global(char *file_name)
{
FILE *fid;
ostringstream tmp_out("");
tmp_out << file_name << "_options.txt";
fid = fopen(tmp_out.str().c_str(), "r");
if (fid == NULL)
{
string s = "Can't open file ";
s += tmp_out.str().c_str();
mexErrMsgTxt(s);
}
mxglobal["options_"] = read_struct(fid);
fclose(fid);
tmp_out.str("");
tmp_out << file_name << "_M.txt";
fid = fopen(tmp_out.str().c_str(), "r");
if (fid == NULL)
{
string s = "Can't open file ";
s += tmp_out.str().c_str();
mexErrMsgTxt(s);
}
mxglobal["M_"] = read_struct(fid);
fclose(fid);
tmp_out.str("");
tmp_out << file_name << "_oo.txt";
fid = fopen(tmp_out.str().c_str(), "r");
if (fid == NULL)
{
string s = "Can't open file ";
s += tmp_out.str().c_str();
mexErrMsgTxt(s);
}
mxglobal["oo_"] = read_struct(fid);
fclose(fid);
}
void
Free_simple_array(mxArray *array)
{
mxFree(array->data);
delete array;
}
void
Free_struct_array(mxArray *array)
{
for (unsigned int i = 0; i < array->size_1 * array->size_2; i++)
for (unsigned int j = 0; j < array->field_name.size(); j++)
Free_Array(array->field_array[i][j]);
delete array;
}
void
Free_Array(mxArray *array)
{
switch (array->type)
{
case mxDOUBLE_CLASS:
case mxSINGLE_CLASS:
case mxCHAR_CLASS:
Free_simple_array(array);
break;
case mxSTRUCT_CLASS:
Free_struct_array(array);
break;
default:
mexErrMsgTxt("Array type not handle in read_Array\n");
}
}
void
Free_global()
{
for (map<string, mxArray *>::iterator it = mxglobal.begin(); it != mxglobal.end(); it++)
Free_Array(it->second);
}