Skip to content

Commit ba8f12e

Browse files
sjoelundOpenModelica-Hudson
authored andcommitted
Handle double matrix when strings are expected
This handles some versions of matlab that save character or integer matrices using double precision.
1 parent d2bbe7a commit ba8f12e

File tree

1 file changed

+125
-107
lines changed

1 file changed

+125
-107
lines changed

SimulationRuntime/c/util/read_matlab4.c

Lines changed: 125 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ int mat_element_length(int type)
9191
int t = (type%10);
9292
if(m) return -1; /* We require IEEE Little Endian for now */
9393
if(o) return -1; /* Reserved number; forced 0 */
94+
if(t == 1 && p == 0) return 8; /* Double text matrix? */
9495
if(t == 1 && p != 5) return -1; /* Text matrix? Force element length=1 */
9596
if(t == 2) return -1; /* Sparse matrix fails */
9697
switch (p) {
@@ -152,6 +153,65 @@ void remSpaces(char *ch){
152153
}
153154
}
154155

156+
/* Read n elements into str; convert from double if necessary, etc */
157+
static int read_chars(int type, size_t n, FILE *file, char *str)
158+
{
159+
int p = (type%100)/10;
160+
if (p == 0) { /* Double */
161+
double d=0.0;
162+
int k;
163+
for (k=0; k<n; k++) {
164+
if (fread(&d, sizeof(double), 1, file) != 1) {
165+
return 1;
166+
}
167+
str[k] = (char) d;
168+
}
169+
return 0;
170+
} else if (p == 5) { /* Byte */
171+
return fread(str,n,1,file) != 1;
172+
}
173+
return 1;
174+
}
175+
176+
static int read_int32(int type, size_t n, FILE *file, int32_t *val)
177+
{
178+
int p = (type%100)/10;
179+
if (p == 0) { /* Double */
180+
double d=0.0;
181+
int k;
182+
for (k=0; k<n; k++) {
183+
if (fread(&d, sizeof(double), 1, file) != 1) {
184+
return 1;
185+
}
186+
val[k] = (int32_t) d;
187+
}
188+
return 0;
189+
} else if (p == 2) { /* int32 */
190+
return fread(val,n*sizeof(int32_t),1,file) != 1;
191+
}
192+
return 1;
193+
}
194+
195+
static int read_double(int type, size_t n, FILE *file, double *val)
196+
{
197+
int p = (type%100)/10;
198+
if (p == 0) { /* Double */
199+
return fread(val,n*sizeof(double),1,file) != 1;
200+
} else if (p == 1) { /* float */
201+
float f=0.0;
202+
int k;
203+
for (k=0; k<n; k++) {
204+
if (fread(&f, sizeof(float), 1, file) != 1) {
205+
return 1;
206+
}
207+
val[k] = (double) f;
208+
}
209+
return 0;
210+
}
211+
return 1;
212+
}
213+
214+
155215
/* Returns 0 on success; the error message on error */
156216
const char* omc_new_matlab4_reader(const char *filename, ModelicaMatReader *reader)
157217
{
@@ -172,16 +232,8 @@ const char* omc_new_matlab4_reader(const char *filename, ModelicaMatReader *read
172232
int nr = fread(&hdr,sizeof(MHeader_t),1,reader->file);
173233
size_t matrix_length,element_length;
174234
char *name;
175-
reader->doublePrecision = 1;
176235
if(nr != 1) return "Corrupt header (1)";
177-
/* fprintf(stderr, "Found matrix type=%04d mrows=%d ncols=%d imagf=%d namelen=%d\n", hdr.type, hdr.mrows, hdr.ncols, hdr.imagf, hdr.namelen); */
178-
if(hdr.type != matrixTypes[i])
179-
{
180-
if((i > 3) && (hdr.type == 10))
181-
reader->doublePrecision = 0;
182-
else
183-
return "Matrix type mismatch";
184-
}
236+
/* fprintf(stderr, "Found matrix %d=%s type=%04d mrows=%d ncols=%d imagf=%d namelen=%d\n", i, name, hdr.type, hdr.mrows, hdr.ncols, hdr.imagf, hdr.namelen); */
185237
if(hdr.imagf > 1) return "Matrix uses imaginary numbers";
186238
if((element_length = mat_element_length(hdr.type)) == -1) return "Could not determine size of matrix elements";
187239
name = (char*) malloc(hdr.namelen);
@@ -209,8 +261,8 @@ const char* omc_new_matlab4_reader(const char *filename, ModelicaMatReader *read
209261
char tmp[45];
210262
if(hdr.mrows != 4) return "Aclass matrix does not have 4 rows";
211263
if(hdr.ncols != 11) return "Aclass matrix does not have 11 cols";
212-
if(fread(tmp,hdr.ncols*hdr.mrows,1,reader->file) != 1) {
213-
return "Corrupt header: Aclass matrix";
264+
if (read_chars(hdr.type, hdr.ncols*hdr.mrows, reader->file, tmp)) {
265+
return "Could not read: Aclass matrix as text";
214266
}
215267
for(k=0; k<hdr.mrows; k++) {
216268
char row[12];
@@ -230,7 +282,7 @@ const char* omc_new_matlab4_reader(const char *filename, ModelicaMatReader *read
230282
/* fprintf(stderr, "use binNormal format\n"); */
231283
binTrans = 0;
232284
} else {
233-
fprintf(stderr, "row 3: %s\n", row);
285+
/* fprintf(stderr, "row 3: %s\n", row); */
234286
return "Aclass matrix does not match binTrans or binNormal format";
235287
}
236288
}
@@ -247,20 +299,21 @@ const char* omc_new_matlab4_reader(const char *filename, ModelicaMatReader *read
247299
if(binTrans==1) {
248300
for(k=0; k<hdr.ncols; k++) {
249301
reader->allInfo[k].name = (char*) malloc(hdr.mrows+1);
250-
if(fread(reader->allInfo[k].name,hdr.mrows,1,reader->file) != 1) return "Corrupt header: names matrix";
302+
if (read_chars(hdr.type, hdr.mrows, reader->file, reader->allInfo[k].name)) {
303+
return "Could not read: names matrix as text";
304+
}
251305
reader->allInfo[k].name[hdr.mrows] = '\0';
252306
reader->allInfo[k].isParam = -1;
253307
reader->allInfo[k].index = -1;
254308
remSpaces(reader->allInfo[k].name);
255-
/* fprintf(stderr, " Adding variable %s\n", reader->allInfo[k].name); */
309+
/* fprintf(stderr, " Adding variable '%s'\n", reader->allInfo[k].name); */
256310
}
257311
}
258312
if(binTrans==0) {
259-
uint32_t j;
260-
char* tmp = (char*) malloc(hdr.ncols*hdr.mrows+1);
261-
if(fread(tmp,hdr.ncols*hdr.mrows,1,reader->file) != 1) {
262-
free(tmp);
263-
return "Corrupt header: names matrix";
313+
uint32_t j;
314+
char* tmp = (char*) malloc(hdr.ncols*hdr.mrows+1);
315+
if (read_chars(hdr.type, hdr.ncols*hdr.mrows, reader->file, tmp)) {
316+
return "Could not read: names matrix as text";
264317
}
265318
for(k=0; k<hdr.mrows; k++) {
266319
reader->allInfo[k].name = (char*) malloc(hdr.ncols+1);
@@ -271,7 +324,7 @@ const char* omc_new_matlab4_reader(const char *filename, ModelicaMatReader *read
271324
reader->allInfo[k].isParam = -1;
272325
reader->allInfo[k].index = -1;
273326
remSpaces(reader->allInfo[k].name);
274-
/* fprintf(stderr, " Adding variable %s\n", reader->allInfo[k].name); */
327+
/* fprintf(stderr, " Adding variable '%s'\n", reader->allInfo[k].name); */
275328
}
276329
free(tmp);
277330
}
@@ -282,23 +335,25 @@ const char* omc_new_matlab4_reader(const char *filename, ModelicaMatReader *read
282335
if(binTrans==1) {
283336
for(k=0; k<hdr.ncols; k++) {
284337
reader->allInfo[k].descr = (char*) malloc(hdr.mrows+1);
285-
if(fread(reader->allInfo[k].descr,hdr.mrows,1,reader->file) != 1) return "Corrupt header: names matrix";
338+
if (read_chars(hdr.type, hdr.mrows, reader->file, reader->allInfo[k].descr)) {
339+
return "Could not read: description matrix as text";
340+
}
286341
reader->allInfo[k].descr[hdr.mrows] = '\0';
287-
}
342+
/* fprintf(stderr, " Adding description %s\n", reader->allInfo[k].descr); */
343+
}
288344
} else if(binTrans==0) {
289345
uint32_t j;
290346
char* tmp = (char*) malloc(hdr.ncols*hdr.mrows+1);
291-
if(fread(tmp,hdr.ncols*hdr.mrows,1,reader->file) != 1) {
292-
free(tmp);
293-
return "Corrupt header: names matrix";
347+
if (read_chars(hdr.type, hdr.ncols*hdr.mrows, reader->file, tmp)) {
348+
return "Could not read: description matrix as text";
294349
}
295350
for(k=0; k<hdr.mrows; k++) {
296351
reader->allInfo[k].descr = (char*) malloc(hdr.ncols+1);
297352
for(j=0; j<hdr.ncols; j++) {
298353
reader->allInfo[k].descr[j] = tmp[j*hdr.mrows+k];
299354
}
300355
reader->allInfo[k].descr[hdr.ncols] = '\0';
301-
/* fprintf(stderr, " Adding variable %s\n", reader->allInfo[k].name); */
356+
/* fprintf(stderr, " Adding description %s\n", reader->allInfo[k].descr); */
302357
}
303358
free(tmp);
304359
}
@@ -307,7 +362,7 @@ const char* omc_new_matlab4_reader(const char *filename, ModelicaMatReader *read
307362
case 3: { /* "dataInfo" */
308363
unsigned int k;
309364
int32_t *tmp = (int32_t*) malloc(sizeof(int32_t)*hdr.ncols*hdr.mrows);
310-
if(1 != fread(tmp,sizeof(int32_t)*hdr.ncols*hdr.mrows,1,reader->file)) {
365+
if (read_int32(hdr.type, hdr.ncols*hdr.mrows, reader->file, tmp)) {
311366
free(tmp); tmp=NULL;
312367
return "Corrupt header: dataInfo matrix";
313368
}
@@ -331,72 +386,50 @@ const char* omc_new_matlab4_reader(const char *filename, ModelicaMatReader *read
331386
break;
332387
}
333388
case 4: { /* "data_1" */
389+
unsigned int k;
334390
if(binTrans==1) {
335-
unsigned int k;
336391
if(hdr.mrows == 0) return "data_1 matrix does not contain at least 1 variable";
337392
if(hdr.ncols != 2 && hdr.ncols != 1) return "data_1 matrix does not have 1 or 2 cols";
338393
reader->nparam = hdr.mrows;
339-
if(reader->doublePrecision==1)
340-
{
341-
reader->params = (double*) malloc(hdr.mrows*hdr.ncols*sizeof(double));
342-
if(1 != fread(reader->params,matrix_length,1,reader->file)) return "Corrupt header: data_1 matrix";
343-
}
344-
else
345-
{
346-
float *buffer = (float*) malloc(hdr.mrows*hdr.ncols*sizeof(float));
347-
reader->params = (double*) malloc(hdr.mrows*hdr.ncols*sizeof(double));
348-
if(1 != fread(buffer,matrix_length,1,reader->file)) return "Corrupt header: data_1 matrix";
349-
for(k=0;k<hdr.mrows*hdr.ncols;k++)
350-
{
351-
reader->params[k] = buffer[k];
352-
}
353-
free(buffer);
394+
reader->params = (double*) malloc(hdr.mrows*hdr.ncols*sizeof(double));
395+
if (read_double(hdr.type, hdr.mrows*hdr.ncols, reader->file, reader->params)) {
396+
return "Corrupt header: data_1 matrix";
354397
}
355398
/* fprintf(stderr, " startTime = %.6g\n", reader->params[0]);
356399
* fprintf(stderr, " stopTime = %.6g\n", reader->params[1]); */
357-
for(k=1; k<reader->nparam; k++) {
358-
if(hdr.ncols == 2 && reader->params[k] != reader->params[k+reader->nparam]) return "data_1 matrix contained parameter that changed between start and stop-time";
359-
/* fprintf(stderr, " Parameter[%d] = %.6g\n", k, reader->params[k]); */
360-
}
361400
}
362401
if(binTrans==0) {
363-
unsigned int k,j;
402+
unsigned int j;
364403
if(hdr.ncols == 0) return "data_1 matrix does not contain at least 1 variable";
365404
if(hdr.mrows != 2 && hdr.mrows != 1) return "data_1 matrix does not have 1 or 2 rows";
366405
reader->nparam = hdr.ncols;
367-
if(reader->doublePrecision==1)
368-
{
369-
double *tmp=NULL;
370-
tmp = (double*) malloc(hdr.mrows*hdr.ncols*sizeof(double));
371-
reader->params = (double*) malloc(hdr.mrows*hdr.ncols*sizeof(double));
372-
if(1 != fread(tmp,matrix_length,1,reader->file)) return "Corrupt header: data_1 matrix";
373-
for(k=0; k<hdr.mrows; k++) {
374-
for(j=0; j<hdr.ncols; j++) {
375-
reader->params[k*hdr.ncols+j] = tmp[k +j*hdr.mrows];
376-
}
377-
}
378-
free(tmp);
406+
double *tmp=NULL;
407+
tmp = (double*) malloc(hdr.mrows*hdr.ncols*sizeof(double));
408+
reader->params = (double*) malloc(hdr.mrows*hdr.ncols*sizeof(double));
409+
if (read_double(hdr.type, hdr.mrows*hdr.ncols, reader->file, tmp)) {
410+
return "Corrupt header: data_1 matrix";
379411
}
380-
else
381-
{
382-
float *tmp=NULL;
383-
tmp = (float*) malloc(hdr.mrows*hdr.ncols*sizeof(float));
384-
reader->params = (double*) malloc(hdr.mrows*hdr.ncols*sizeof(double));
385-
if(1 != fread(tmp,matrix_length,1,reader->file)) return "Corrupt header: data_1 matrix";
386-
for(k=0; k<hdr.mrows; k++) {
387-
for(j=0; j<hdr.ncols; j++) {
388-
reader->params[k*hdr.ncols+j] = tmp[k +j*hdr.mrows];
389-
}
412+
for(k=0; k<hdr.mrows; k++) {
413+
for(j=0; j<hdr.ncols; j++) {
414+
reader->params[k*hdr.ncols+j] = tmp[k +j*hdr.mrows];
390415
}
391-
free(tmp);
392-
}
393-
for(k=1; k<reader->nparam; k++) {
394-
if(hdr.mrows == 2 && reader->params[k] != reader->params[k+reader->nparam]) return "data_1 matrix contained parameter that changed between start and stop-time";
395416
}
417+
free(tmp);
418+
}
419+
for(k=1; k<reader->nparam; k++) {
420+
if(hdr.mrows == 2 && reader->params[k] != reader->params[k+reader->nparam]) return "data_1 matrix contained parameter that changed between start and stop-time";
396421
}
397422
break;
398423
}
399424
case 5: { /* "data_2" */
425+
int p = (hdr.type / 10)%10;
426+
if (p==0) {
427+
reader->doublePrecision=1;
428+
} else if (p==1) {
429+
reader->doublePrecision=0;
430+
} else {
431+
return "data_2 matrix not in double/float representation";
432+
}
400433
if(binTrans==1) {
401434
reader->nrows = hdr.ncols;
402435
/* Allow empty matrix; it's not a complete file, but ok... */
@@ -414,42 +447,27 @@ const char* omc_new_matlab4_reader(const char *filename, ModelicaMatReader *read
414447
reader->nvar = hdr.ncols;
415448
reader->var_offset = ftell(reader->file);
416449
reader->vars = (double**) calloc(reader->nvar*2,sizeof(double*));
417-
if(reader->doublePrecision==1)
418-
{
419-
double *tmp=NULL;
420-
tmp = (double*) malloc(hdr.mrows*hdr.ncols*sizeof(double));
421-
if(1 != fread(tmp,matrix_length,1,reader->file)) return "Corrupt header: data_2 matrix";
422-
for(k=0; k<hdr.ncols; k++) {
423-
reader->vars[k] = (double*) malloc(hdr.mrows*sizeof(double));
424-
for(j=0; j<hdr.mrows; j++) {
425-
reader->vars[k][j] = tmp[j+k*hdr.mrows];
426-
}
427-
}
428-
for(k=reader->nvar; k<reader->nvar*2; k++) {
429-
reader->vars[k] = (double*) malloc(hdr.mrows*sizeof(double));
430-
for(j=0; j<hdr.mrows; j++) {
431-
reader->vars[k][j] = -reader->vars[k-reader->nvar][j];
432-
}
433-
}
434-
free(tmp);
435-
} else {
436-
float *tmp=NULL;
437-
tmp = (float*) malloc(hdr.mrows*hdr.ncols*sizeof(float));
438-
if(1 != fread(tmp,matrix_length,1,reader->file)) return "Corrupt header: data_2 matrix";
439-
for(k=0; k<hdr.ncols; k++) {
440-
reader->vars[k] = (double*) malloc(hdr.mrows*sizeof(double));
441-
for(j=0; j<hdr.mrows; j++) {
442-
reader->vars[k][j] = tmp[j+k*hdr.mrows];
443-
}
450+
451+
452+
double *tmp=NULL;
453+
tmp = (double*) malloc(hdr.mrows*hdr.ncols*sizeof(double));
454+
if (read_double(hdr.type, hdr.mrows*hdr.ncols, reader->file, tmp)) {
455+
return "Corrupt header: data_2 matrix";
456+
}
457+
for(k=0; k<hdr.ncols; k++) {
458+
reader->vars[k] = (double*) malloc(hdr.mrows*sizeof(double));
459+
for(j=0; j<hdr.mrows; j++) {
460+
reader->vars[k][j] = tmp[j+k*hdr.mrows];
444461
}
445-
for(k=reader->nvar; k<reader->nvar*2; k++) {
446-
reader->vars[k] = (double*) malloc(hdr.mrows*sizeof(double));
447-
for(j=0; j<hdr.mrows; j++) {
448-
reader->vars[k][j] = -reader->vars[k-reader->nvar][j];
449-
}
462+
}
463+
for(k=reader->nvar; k<reader->nvar*2; k++) {
464+
reader->vars[k] = (double*) malloc(hdr.mrows*sizeof(double));
465+
for(j=0; j<hdr.mrows; j++) {
466+
reader->vars[k][j] = -reader->vars[k-reader->nvar][j];
450467
}
451-
free(tmp);
452468
}
469+
free(tmp);
470+
453471
if(-1==fseek(reader->file,matrix_length,SEEK_CUR)) return "Corrupt header: data_2 matrix";
454472
}
455473
break;

0 commit comments

Comments
 (0)