/* GaussFit - A System for Least Squares and Robust Estimation Source Code Copyright (C) 1987 by William H. Jefferys, Michael J. Fitzpatrick and Barbara E. McArthur All Rights Reserved. */ /* ImitationMIDAS table routines */ #include #include #include "strings.h" #include #include "house.h" #include "defines.h" #include "array.h" #include "datum.h" #include "simpledefs.h" #include "prototypes.p" #include "alloc.h" INFO now; static int lastcol = 0; static int lastrow = 0; double expan[4] = { 1.5,1.33333,1.25,1.2}; /*series for row reallocation*/ char *strcpy(); MIDAS *midasopen(fname) /* open midas file, keyword name in environment file has filename */ char *fname; { FILE *fp; MIDAS *tabla; if(!(fp = fopen(fname,"r"))) /* try to open the file */ fatalerror("Data or Parameter File %s Does Not Exist\n",fname); tabla = (MIDAS*)MemAlloc("MIDASFP",(long)sizeof(MIDAS)+18); strcpy(tabla->fname,fname); /* copy file name into table header */ strcpy(now.fname,fname); /* copy file name into table header */ now.col = 0; now.row = 0; midasread(fp,tabla); /* read data into table */ return tabla; /* return table pointer */ } MIDAS *midaswrite(tabla,outtabla,closeit) /* close midas table*/ MIDAS *tabla; char *outtabla; int closeit; { FILE *fp; int i,j,num; double diffround,truncnum; if(tabla) /* see if it's open */ { if(!(fp=fopen(outtabla,"w"))) /* open file for writing */ fatalerror("Can't open output MIDAS table %s\n",tabla->fname); for(i=0;incols;i++) /*print out column headers */ fprintf(fp,"%s\t",tabla->colname[i]); fprintf(fp,"\n"); for(i=0;incols;i++) /*print out column type */ fprintf(fp,"%s\t",tabla->coltype[i]); fprintf(fp,"\n"); for(i=0;inrows;i++) /* do for each row */ { for(j=0;jncols;j++) /* print out each entry in the row */ { if ((num = strcmp(tabla->coltype[j],"double")) == 0) printdouble(fp,tabla->value[i][j],1); else if ((num = strcmp(tabla->coltype[j],"char")) == 0) printchars(fp,tabla,i,j); } fprintf(fp,"\n"); } /* fflush(fp); flush the file before closing */ fclose(fp); /* close file */ if (closeit) { if ((num= strcmp(outtabla,tabla->fname)) == 0) { freethestructure(tabla); lastrow = 0; lastcol = 0; } } return NULL; } else fatalerror("Could not close data or paramter file that was never opened: %s\n",tabla->fname); } printchars(fp,tabla,i,j) FILE *fp; MIDAS *tabla; int i,j; { int num; if ((tabla->value[i][j] < UUND) && (tabla->value[i][j] > LUND)) fprintf(fp,"#N/A\t"); else if ((num = strcmp(tabla->cvalue[i][(int)tabla->value[i][j]], "UND")) == 0) fprintf(fp,"#N/A\t"); else fprintf(fp,"%s\t",tabla->cvalue[i][(int)tabla->value[i][j]]); } freethestructure(tabla) MIDAS *tabla; { int i, j; for (i = 0; i ncols; i++) { /* free dynamically allocated space */ freemem("colname", (char*)tabla->colname[i]); freemem("coltype", (char*)tabla->coltype[i]); } for (j = 0; j < tabla->nrows; j++) freemem("value", (char*)tabla->value[j]); freemem("midasrow", (char*)tabla->midasrow); freemem("rowarray", (char*)tabla->rowarray); freemem("cvalue", (char*)tabla->cvalue); freemem("tabla", (char*)tabla); } midasread(fp,tabla) /*readMIDAS table from a file */ FILE *fp; MIDAS *tabla; { int i,j,ccc,num; static int m; double dnum; char *getword(); int result; double *rowalloc(); char *wordalloc(); char line[MAXLIN],*lineptr, word[LSTRLEN], **charalloc(); makespace(tabla); /* allocate space */ gettableheader(fp, tabla); /* get column names and types*/ i = 0; tabla->nrows =MIDASROWS; /*initially set number of rows toMIDASROWS */ result= 0; while (!(result=getline(line,MAXLIN-1,fp)) == 0) /* get line from file */ { if (i >= tabla->nrows) /* if there are more lines that rows allocated */ addspace(tabla); now.row = i; /* allocate space for storage of doubles */ tabla->midasrow = rowalloc(tabla); /* if there is character data allocate space for char strings */ if (tabla->cncols >0) tabla->charrow = charalloc(tabla); ccc = 0; /* number of char columns */ for (j=0;jncols;j++) { now.col = j; lineptr = getword(line,word);/* get next word, remove it from line */ if (lineptr == NULL) /* attempt to read past end of line */ fatalerror2("Midas Read Error. Attempt to read value past end of line number: %d, file: %s.\n",i,tabla->fname); strcpy(line,lineptr); if ((num = strcmp(tabla->coltype[j],"double")) == 0) /* if column in double */ loaddouble(tabla,i,j,word); else if ((num = strcmp(tabla->coltype[j],"char")) == 0) /*if column is character */ { *(tabla->charrow+ccc) = wordalloc(word); /* add char string to next position in charrow */ *(tabla->midasrow+j) = (double)ccc; /* add column number of char data to position in double data matrix */ ccc++; /* increment number of char columns */ } else { fatalerror2("Column type missing or in error for column %d in file %s\n",j,tabla->fname); } } *(tabla->rowarray+i) = tabla->midasrow; /* load next element of rowarray with midasrow */ if (tabla->cncols > 0) *(tabla->chararray+i) = tabla->charrow; /* load next element of chararray with charrow */ i++; } tabla->nrows = i; /* fflush(fp); flush the file before closing */ fclose(fp); } addspace(tabla) MIDAS *tabla; { static int m; if (m>3 || m<0) m = 0; tabla->nrows = (int)((float)tabla->nrows*(expan[m])); /* reallocate using series for max efficiency */ rowrealloc(tabla); /* reallocate the rows: add rows */ m++; } loaddouble(tabla,i,j,word) MIDAS *tabla; int i,j; char *word; { int num; double dnum; if ((num=strcmp(word,"#N/A")) == 0) /* if the value is undefined */ dnum = UND; /* set double to undefined */ else { num = sscanf(word,"%lf",&dnum); /* read double num from word string */ /*printf("word = %s, dnum = %lf %24.17lf\n",word,dnum,dnum);*/ /* check argument return for function */ if (num == EOF) fatalerror2("Midas Read Error. Attempt to read double value past end of line number: %d, file: %s.\n",i,tabla->fname); if (num == 0) fatalerror("Midas Read Error. No value exists in file: % s.\n",tabla->fname); } *(tabla->midasrow+j) = dnum; /*load double number into ne xt position in midasrow */ } gettableheader(fp, tabla) /* read in colnames and coltypes from table file */ FILE *fp; MIDAS *tabla; { char *p,*getword(),*wordalloc(); int result; char line[MAXLIN],name[LSTRLEN],*lineptr; int num, nlines,ch,nonames; result = 0; if ((result = getline(line,MAXLIN-1,fp)) == 0) /* get line */ fatalerror("Midas Read Error. Unable to read first line of file: %s.\n",tabla->fname); tabla->ncols = 0; nlines = 0; while (!((lineptr = getword(line,name)) == NULL)) /* get name from line, remove it from line */ { tabla->ncols = tabla->ncols + 1; colheadrealloc(tabla); strcpy(line,lineptr); ch = name[0]; if ((!(isalpha(ch))) && (ch != '_')) fatalerror("Midas Read Error file %s. Column Name does not begin with alpha.\n",tabla->fname); *(tabla->colname+nlines) = wordalloc(name); /* load p into colname */ if (tabla->colname[nlines] == NULL) fatalerror("Midas Read Error file %s. Table missing colname line.\n",tabla->fname); nlines++; } if((result =getline(line,MAXLIN-1,fp)) == 0) /* get coltype ) line */ fatalerror("Midas Read Error file %s. Table missing column type line.\n Type must be double or char separated by tabs or blanks.\n",tabla->fname); tabla->cncols = 0; nonames = nlines; nlines = 0; while (!((lineptr = getword(line,name)) == NULL)) /* get name from line, remove it from line */ { strcpy(line,lineptr); *(tabla->coltype+nlines) = wordalloc(name); /* load column type */ if (tabla->coltype[nlines] == NULL) fatalerror("Midas Read Error file %s. File missing coltype line.\n Type must be double or char separated by tabs or blanks.\n",tabla->fname); if (!(((num = strcmp(tabla->coltype[nlines],"double")) == 0) || ((num = strcmp(tabla->coltype[nlines],"char")) == 0))) /* if incorrect column type */ fatalerror("Midas Read Error file %s. Coltype is invalid type must be either char or double.\n",tabla->fname); if ((num = strcmp(tabla->coltype[nlines],"char")) == 0) tabla->cncols++; nlines++; } if (tabla->coltype[tabla->ncols-1] == NULL) fatalerror("Midas Read Error file %s. File missing coltype line.\n Type must be double or char separated by tabs or blanks.\n",tabla->fname); if (nonames != nlines) fatalerror("Midas Read Error file %s. File missing coltype delcaration.\n Type must be double or char separated by tabs or blanks.\n",tabla->fname); return; } makespace(tabla) /* initial space allocation for table */ MIDAS *tabla; { long rowarraysize,chararraysize,namesize; int i; rowarraysize = (long)(MIDASROWS * (long)sizeof(double*));/*size of rowarray */ tabla->rowarray = (double**)MemAlloc("rowarray",rowarraysize); chararraysize = (long)(MIDASROWS * (long)sizeof(char*)); /* size of chararray */ tabla->chararray = (char***)MemAlloc("chararry",chararraysize); lastcol = MIDASCOLS; namesize = (long)(lastcol * sizeof(char*)); /* size of colname and coltype */ tabla->colname = (char**)MemAlloc("colname",namesize); tabla->coltype = (char**)MemAlloc("coltype",namesize); tabla->value = tabla->rowarray; /* set value struct to rowarray */ tabla->midasrow = NULL; tabla->charrow = NULL; tabla->charitem = NULL; tabla->cvalue = tabla->chararray; /* set cvalue struct to chararray */ } double *rowalloc(tabla) /* allocate space for a double row */ MIDAS *tabla; { double *x; int i; long midasrowsize; midasrowsize = (long)lastcol * sizeof(double); /* size of array of double values */ x = (double*)MemAlloc("midasrow",midasrowsize); for (i=0; i < lastcol; i++) x[i] = (double)UND; /* set values to undefined */ return x; } char **charalloc(tabla) /* allocate space for a char string row */ MIDAS *tabla; { char **x; int i; long charrowsize; tabla->charitem=(char*)MemAlloc("charitem",(long)LSTRLEN); charrowsize = (long)tabla->cncols*sizeof(char*); /* size of array of character strings */ x = (char**)MemAlloc("charrow",charrowsize); sscanf("UND","%s",tabla->charitem); for (i=0;i < tabla->cncols; i++) *(x+i) = tabla->charitem; /* set items to undefined initially */ return x; } double getmidasval(tabla,name,row) /* get a value from the table index by column "name and row */ MIDAS *tabla; char *name; int row; { if (--row < 0) fatalerror( "Getmidasval Error Request for negative rownumber--MIDAS file %s\n", tabla->fname); if(row < tabla->nrows) { /* if row has been read */ int i; for(i=0; incols; i++) { /* find the desired column */ if((strcmp(name,tabla->colname[i])==0)&& (strcmp("double",tabla->coltype[i])==0)) { return tabla->value[row][i]; /* return value found */ } } } return (double)UND; /* return UND if rows or columns doesn't exist */ } char *getmidasstr(tabla,name,row) /* get string from table corresponding to keyword s */ MIDAS *tabla; char *name; int row; { row = row -1; /* to adjust to c beginning arrays at 0 */ if (row <0) fatalerror("Getmidasstr Error Request for negative rownumber--MIDAS file %s\n",tabla->fname); if(row < tabla->nrows) /* if row has been read */ { int i; for(i=0;incols;i++) /* scan table rows */ { if((strcmp(name,tabla->colname[i])==0)&& (strcmp("char",tabla->coltype[i])==0)) { return (tabla->cvalue[row][(int)tabla->value[row][i]]); /* return value found */ } } } return NULL; /* if not found, return NULL pointer */ } putmidasval(tabla,name,row,dval) /* put a value int o the table at column "name" and row */ MIDAS *tabla; char *name; int row; double dval; { int col,i; char buffer[STRLEN],*wordalloc(); col = -1; row = row -1; /* to adjust to c beginning arrays at 0 */ if (row <0) fatalerror("Putmidasval Error Request for negative rownumber--MIDAS file %s\n",tabla->fname); for(i=0;incols;i++) /* look for column */ { if ((strcmp(name,tabla->colname[i])==0) && (strcmp("double",tabla->coltype[i])==0)) { /* if found, put value into column at desired row */ col = i; putmidasvalcol(tabla,row,col,dval); return; } } /* if not found reallocate space and add */ col = tabla->ncols; tabla->ncols++;/* increment number of columns */ colheadrealloc(tabla); /* reallocate space for extra column in table header */ tabla->colname[col] = wordalloc(name); /* copy column name into header */ tabla->coltype[col] = wordalloc("double"); /* copy column type into header */ colrealloc(tabla);/* reallocate space for extra column in body of table */ for(i=0;inrows;i++) { /* zero out the column */ tabla->rowarray[i][col] = (double)UND; } putmidasvalcol(tabla,row,col,dval); /* put value into column at desired row */ } putmidasvalcol(tabla,row,col,dval) /* put value into table at col #, ro #, specified (name not used) */ MIDAS *tabla; int row,col; double dval; { int j,i, old; double *rowalloc(); if (col <0) fatalerror("Putmidasval Error Request for negative colnumber--MIDAS file %s\n",tabla->fname); if(row >= tabla->nrows) /* if row does not exist */ { old = tabla->nrows; tabla->nrows = row+1; rowrealloc(tabla); /* allocate space for new double row pointers */ for (i=old;inrows;i++) { tabla->midasrow = rowalloc(tabla); /* allocate space for new double row */ for(j=0;jncols;j++) /* zero out row */ *(tabla->midasrow+j) = (double)UND; *(tabla->rowarray+i) = tabla->midasrow; /* fill rowarray with midasrow */ } tabla->value = tabla->rowarray; } tabla->value[row][col] = dval; /* insert value into table at [row][col] */ } putmidasstr(tabla,name,row,cval) /* put a value int o the table at column "name" and row */ MIDAS *tabla; char *name; int row; char *cval; { int col,i; char buffer[STRLEN],*wordalloc(); row = row -1; /* to adjust to c beginning arrays at 0 */ if (row <0) fatalerror("Putmidasstr Error Request for negative rownumber--MIDAS file %s\n",tabla->fname); for(col=0;colncols;col++) /* look for column */ if ((strcmp(name,tabla->colname[col])==0) && (strcmp("char",tabla->coltype[col])==0)) { /* if found, put value into column at desired row */ putmidasstrcol(tabla,row,col,cval); return; } /* if not found reallocate space and add */ col = tabla->ncols; tabla->ncols++;/* increment number of columns */ tabla->cncols++;/* increment number of char columns */ colheadrealloc(tabla); /* reallocate space for header (add column) */ tabla->colname[col] = wordalloc(name); /* copy column name into header */ tabla->coltype[col] = wordalloc("char"); /* copy column type into header */ colrealloc(tabla); /* reallocate space for body of table (add column) */ for(i=0;inrows;i++) /* zero out the column */ { tabla->value[i][col] = tabla->cncols-1; tabla->cvalue[i][(int)tabla->value[i][col]] = wordalloc("UND"); } putmidasstrcol(tabla,row,col,cval); /* put value into column at desired row */ } putmidasstrcol(tabla,row,col,cval) /* put value into table at col #, ro #, specified (name not used) */ MIDAS *tabla; int row,col; char *cval; { int j,i, old; char *p; double dval; double *rowalloc(); char **charalloc(),*wordalloc(); if(tabla->nrows <= row) /* if row does not exist */ { old = tabla->nrows; tabla->nrows = row+1; rowrealloc(tabla); /* reallocate row pointer array */ for (i=old;inrows;i++) { tabla->charrow = charalloc(tabla); /* allocate new char row */ tabla->midasrow = rowalloc(tabla); /* allocate new double row */ for(j=0;jncols;j++) /* zero out row */ { if (strcmp("double",tabla->coltype[j])==0) *(tabla->midasrow+j) = (double)UND; else if (strcmp("char",tabla->coltype[j])==0) *(tabla->midasrow+j) = tabla->value[0][j]; } for(j=0;jcncols;j++) /* zero out character row */ *(tabla->charrow+j) = "UND"; *(tabla->rowarray+i) = tabla->midasrow; /* set next element of rowarray to double row */ *(tabla->chararray+i) = tabla->charrow; /* set next element of chararray to char row */ } } tabla->value[row][col] = tabla->value[0][col]; /* insert column number into double matrix */ tabla->cvalue[row][(int)tabla->value[row][col]] = wordalloc(cval); /* insert value into table at [row][col] */ } rowrealloc(tabla)/* reallocate space of double pointer array */ MIDAS *tabla; { int i; long rerowarraysize=0,rechararraysize=0; rerowarraysize = (long)(tabla->nrows*sizeof(double*));/* size to allocate */ tabla->rowarray = (double**)Reallocate("rowarray",rerowarraysize,(char*)tabla->rowarray);/* reallocate rowarray */ if (tabla->rowarray == NULL) fatalerror("Memory Manager Error in row reallocation --MIDAS file %s\n", tabla->fname); tabla->value = tabla->rowarray; rechararraysize = (long)(tabla->nrows*sizeof(char*)); /* size of new char pointer chararray */ tabla->chararray = (char***)Reallocate("chararray",rechararraysize,(char*)tabla->chararray); /* reallocate space */ if (tabla->chararray== NULL) /* test space */ fatalerror("Memory Manager Error in row reallocation --MIDAS file %s\n", tabla->fname); tabla->cvalue = tabla->chararray; /* set table structure to new space */ lastrow = tabla->nrows; } colheadrealloc(tabla) /* reallocate space for table header (column name and type*/ MIDAS *tabla; { long renamesize; if (tabla->ncols+1 >= lastcol) { lastcol = tabla->ncols + 8; renamesize = (long)(lastcol * sizeof(char*)); /* new size */ tabla->colname = (char**)Reallocate("colname",renamesize,(char*)tabla->colname); /* reallocate colname space */ tabla->coltype = (char**)Reallocate("coltype",renamesize,(char*)tabla->coltype); /* reallocate column type space */ } } colrealloc(tabla) /* reallocate space in body of table for more columns */ MIDAS *tabla; { char **charalloc(); int i,col,num; long remidasrowsize=0,recharrowsize=0; int nrow; remidasrowsize = (long)(tabla->ncols*sizeof(double)); /* size of array of double values */ recharrowsize = (long)(tabla->cncols*sizeof(char*)); nrow = tabla->nrows; if (tabla->ncols >MIDASCOLS) /* if columns are greater than initial increment */ { col = tabla->ncols-1; if (((num = strcmp(tabla->coltype[col],"double")) == 0) || ((num = strcmp(tabla->coltype[col],"char")) == 0)) /* for both coltypes do this */ { for (i=0;irowarray+i) != NULL) { /*free((char*)(*(tabla->rowarray+i))); */ *(tabla->rowarray+i) = (double*)Reallocate("rowarray",remidasrowsize,(char*)*(tabla->rowarray+i)); /* reallocate - add column to midasrow space */ if(*(tabla->rowarray+i) == NULL) fatalerror("Memory Manager Error in column reallocation for doubles--MIDAS file %s\n", tabla->fname); } } tabla->value = tabla->rowarray; } if ((num = strcmp(tabla->coltype[col],"char")) == 0) /* for char cols only */ { for (i=0;icncols == 1) /* if this is first char column */ { tabla->charrow = charalloc(tabla); *(tabla->chararray+i) = tabla->charrow; } else if (tabla->cncols >1) /* else if this is >1 char column */ { if (*(tabla->chararray+i) != NULL) { /*tabla->cncols++;*/ /*free((char*)(*(tabla->chararray+i)));*/ *(tabla->chararray+i) = (char**)Reallocate("chararray",recharrowsize,(char*)*(tabla->chararray+i)); /* reallocate size of charrow for another column */ if (*(tabla->chararray+i) == NULL) fatalerror("Memory Manager Error in column reallocation for characters--MIDAS file %s\n", tabla->fname); } } } tabla->cvalue = tabla->chararray; } if (((num = strcmp(tabla->coltype[col],"double")) != 0) && ((num = strcmp(tabla->coltype[col],"char")) != 0)) { /* if coltypes are invalid fatal error */ fatalerror("Bad column type in file %s.\n",tabla->fname); } } } /* Added routines for extra actions mostly for filters */ copytable(tabla,outtabla) /* copies table file to a new table file */ MIDAS *tabla; char *outtabla; { midaswrite(tabla,outtabla,1); } getnumrows(tabla) /* return number of rows in table */ MIDAS *tabla; { return (tabla->nrows); } getnumcols(tabla) /* return number of cols in table */ MIDAS *tabla; { return (tabla->ncols); } char *getcolname(col,tabla) /* get name of specific column in midastable */ MIDAS *tabla; int col; { if (col <= getnumcols(tabla)) return tabla->colname[col]; return NULL; } changecolname(tabla,oldname,newname) /* change name of column in table */ MIDAS *tabla; char *oldname, *newname; { int i,num; for(i=0;i< tabla->ncols; i++) /* find the desired column */ if((num = strcmp(oldname,tabla->colname[i]))==0) { tabla->colname[i]=newname; return 1; /* return 1 for success */ } return 0; /* return 0 for failure */ } setundef(tabla,colname,row,type) /* set value to undefined */ MIDAS *tabla; int row; char *colname,*type; { int j,num; char *cval; double dval; if (row <0) fatalerror("Setundef Error Request for negative rownumber--MIDAS file %s\n",tabla->fname); if ((num = strcmp(type,"double")) == 0) { dval = (double)UND; putmidasval(tabla,colname,row,dval); return 1; } else if ((num=strcmp(type,"char")) == 0) { cval=(char*)MemAlloc("column name",(long)sizeof(LSTRLEN)); sscanf("UND","%s",cval); putmidasstr(tabla,colname,row,cval); return 1; } else return 0; /* return 0 for failure */ } char *getword(line,word) /* get the next word from line and remove it from line */ char *line, *word; { int i ,status,numtabs = 0; ; for (i=0;i<(LSTRLEN-1);i++) /* for the length of the word */ word[i] = ' '; /* set the word to blank */ if ((*line == '\n') || (*line == '\0')) return NULL; /* if end of line or null return */ while (status = isspace(*line)) { if (*line == '\t') numtabs++; ++line; /* skip blanks or tabs */ } if ((*line == '\n') || (*line == '\0')) return NULL; /* if end of line or null return */ if (numtabs >= 2) { warningerror("Data missing in file: %s,\n On line: %d col: %d\n",now.fname,(now.row)+1,(now.col)+1); *word++ = '0'; } else { while (!(isspace(*line)) && (*line != '\0')) /* while not blanks or tabs */ { if ((*line == '\n') || (*line == '\0')) return NULL; *word++ = *line++; /* fill word from line */ } } *word++='\0'; return line; /* return incremented line */ } char *wordalloc(word1) char *word1; { int num; if ((num=strcmp(word1,"#N/A")) == 0) /* if it is undefined */ return "UND"; else return wordfill(word1); } getline(s, lim,fp) char s[]; int lim; FILE *fp; { int c,i; int noblanks; i = 0; noblanks = 0; while (--lim >0 && (c=fgetc(fp)) != EOF && c != '\n') { s[i++] = c; if(!(isspace(c))) noblanks = 1; } if (c == '\n' || c == EOF) { s[i++] = '\n'; } if (c == EOF) { i--; ungetc(c,fp); } s[i] = '\0'; if(noblanks) return(i); else return 0; }