/* * mexcdf4.c Mex-file for NetCDF activities. * * Copyright 1992-1995 Charles R. Denham, ZYDECO. * All Rights Reserved. * * Version begun Tuesday, July 14, 1992 6:59:54 PM * Current version Tuesday, January 31, 1995 3:28:22 PM * * This source-code uses the MATLAB Version 4 Mex-file syntax. * * Use mexcdf4.c to build mexcdf4.mex, then rename to "mexcdf.mex". * * Macintosh MPW example: * * cmex mexcdf4.c cdflib.o xdrlib.o # MATLAB Version 4. * rename mexcdf4.mex mexcdf.mex # Rename the result. * * This Mex-file invokes the complete C-Language NetCDF interface, * as described in the NetCDF Users Guide. All of the specified * NetCDF input arguments are required. All output arguments are * optional. * * Matlab Syntax: * * [out1, out2, ...] = mexcdf('operation', in1, in2, ...) * * Extensions: * * 1. Dimensions and variables accessible by id or name. * 2. Attributes accessible by name or number. * 3. Parameters accessible by number or name. * 4. Prepended "nc" not necessary for operation names. * 5. Prepended "NC_" not necessary for specifying parameters. * 6. Parameter names not case-sensitive. * 7. Required lengths default to actual lengths via -1. * 8. Scaling via "scale_factor" and "add_offset" attributes. * 9. SETOPTS to set NetCDF options. NC_FATAL is disabled. * 10. ERR to get the error-code of the most recent operation. * 11. PARAMETER to access parameters by name. * 12. USAGE to list NCMEX syntax. * */ # include # include # include # include # include # include "cmex.h" # include "netcdf.h" # include "mexcdf.h" static VOID Usage (VOID); static Matrix * SetNum (Matrix *); static Matrix * SetStr (Matrix *); static char * Mat2Str (Matrix *); static Matrix * Str2Mat (char *); static int * Mat2Int (Matrix *); static Matrix * Int2Mat (int *, int, int); static long * Mat2Long (Matrix *); static Matrix * Long2Mat (long *, int, int); static int Scalar2Int (Matrix *); static Matrix * Int2Scalar (int); static long Scalar2Long (Matrix *); static Matrix * Long2Scalar (long); static int Count (Matrix *); static int Parameter (Matrix *); static VOID Free (VOIDPP); static DOUBLE Scale_Factor (int, int); static DOUBLE Add_Offset (int, int); static int Convert (OPCODE, nc_type, int, VOIDP, DOUBLE, DOUBLE, DOUBLE *); /* MexFunction(): Mex-file entry point. */ void mexFunction ( INT nlhs, Matrix * plhs[], INT nrhs, Matrix * prhs[] ) { char * opname; OPCODE opcode; Matrix * mat; int status; char * path; int cmode; int mode; int cdfid; int ndims; int nvars; int natts; int recdim; char * name; long length; int dimid; nc_type datatype; int * dim; int varid; long * coords; VOIDP value; long * start; long * count; long * stride; long * imap; long recnum; long nrecvars; int * recvarids; long * recsizes; VOIDPP datap; /* pointers for record access. */ int len; int incdf; int invar; int outcdf; int outvar; int attnum; char * attname; char * newname; int fillmode; int i; int m; int n; char * p; char buffer[MAX_BUFFER]; DOUBLE * pr; DOUBLE addoffset; DOUBLE scalefactor; int autoscale; /* do auto-scaling if this flag is non-zero. */ /* Disable the NC_FATAL option from ncopts. */ if (ncopts & NC_FATAL) { ncopts -= NC_FATAL; } /* Display usage if less than one input argument. */ if (nrhs < 1) { Usage(); return; } /* Convert the operation name to its opcode. */ opname = Mat2Str(prhs[0]); for (i = 0; i < strlen(opname); i++) { opname[i] = (char) tolower((int) opname[i]); } p = opname; if (strncmp(p, "nc", 2) == 0) { /* Trim away "nc". */ p += 2; } i = 0; opcode = NONE; while (ops[i].opcode != NONE) { if (!strcmp(p, ops[i].opname)) { opcode = ops[i].opcode; if (ops[i].nrhs > nrhs) { printf("MEXCDF: opname = %s\n", opname); mexErrMsgTxt("MEXCDF: Too few input arguments.\n"); } else if (0 && ops[i].nlhs > nlhs) { /* Disabled. */ printf("MEXCDF: opname = %s\n", opname); mexErrMsgTxt("MEXCDF: Too few output arguments.\n"); } break; } else { i++; } } if (opcode == NONE) { printf("MEXCDF: opname = %s\n", opname); mexErrMsgTxt("MEXCDF: No such operation.\n"); } Free((VOIDPP) & opname); /* Extract the cdfid by number. */ switch (opcode) { case USAGE: case CREATE: case OPEN: case TYPELEN: case SETOPTS: case ERR: case PARAMETER: break; default: cdfid = Scalar2Int(prhs[1]); break; } /* Extract the dimid by number or name. */ switch (opcode) { case DIMINQ: case DIMRENAME: if (mxIsNumeric(prhs[2])) { dimid = Scalar2Int(prhs[2]); } else { name = Mat2Str(prhs[2]); dimid = ncdimid(cdfid, name); Free((VOIDPP) & name); } break; default: break; } /* Extract the varid by number or name. */ switch (opcode) { case VARINQ: case VARPUT1: case VARGET1: case VARPUT: case VARGET: case VARPUTG: case VARGETG: case VARRENAME: case ATTPUT: case ATTINQ: case ATTGET: case ATTCOPY: case ATTNAME: case ATTRENAME: case ATTDEL: if (mxIsNumeric(prhs[2])) { varid = Scalar2Int(prhs[2]); } else { name = Mat2Str(prhs[2]); varid = ncvarid(cdfid, name); Free((VOIDPP) & name); if (varid == -1) { varid = Parameter(prhs[2]); } } break; default: break; } /* Extract the attname by name or number. */ switch (opcode) { case ATTPUT: case ATTINQ: case ATTGET: case ATTCOPY: case ATTRENAME: case ATTDEL: if (mxIsNumeric(prhs[3])) { attnum = Scalar2Int(prhs[3]); attname = (char *) calloc(MAX_NC_NAME, sizeof(char)); status = ncattname(cdfid, varid, attnum, attname); } else { attname = Mat2Str(prhs[3]); } break; default: break; } /* Extract the "add_offset" and "scale_factor" attributes. */ switch (opcode) { case VARPUT1: case VARGET1: case VARPUT: case VARGET: case VARPUTG: case VARGETG: addoffset = Add_Offset(cdfid, varid); scalefactor = Scale_Factor(cdfid, varid); if (scalefactor == 0.0) { scalefactor = 1.0; } break; default: break; } /* Perform the NetCDF operation. */ switch (opcode) { case USAGE: Usage(); break; case CREATE: path = Mat2Str(prhs[1]); if (nrhs > 2) { cmode = Parameter(prhs[2]); } else { cmode = NC_NOCLOBBER; /* Default. */ } cdfid = nccreate(path, cmode); plhs[0] = Int2Scalar(cdfid); plhs[1] = Int2Scalar((cdfid >= 0) ? 0 : -1); Free((VOIDPP) & path); break; case OPEN: path = Mat2Str(prhs[1]); if (nrhs > 2) { mode = Parameter(prhs[2]); } else { mode = NC_NOWRITE; /* Default. */ } cdfid = ncopen(path, mode); plhs[0] = Int2Scalar(cdfid); plhs[1] = Int2Scalar((cdfid >= 0) ? 0 : -1); Free((VOIDPP) & path); break; case REDEF: status = ncredef(cdfid); plhs[0] = Int2Scalar(status); break; case ENDEF: status = ncendef(cdfid); plhs[0] = Int2Scalar(status); break; case CLOSE: status = ncclose(cdfid); plhs[0] = Int2Scalar(status); break; case INQUIRE: status = ncinquire(cdfid, & ndims, & nvars, & natts, & recdim); if (nlhs > 1) { plhs[0] = Int2Scalar(ndims); plhs[1] = Int2Scalar(nvars); plhs[2] = Int2Scalar(natts); plhs[3] = Int2Scalar(recdim); plhs[4] = Int2Scalar(status); } else { /* Default to 1 x 5 row vector. */ plhs[0] = mxCreateFull(1, 5, REAL); pr = mxGetPr(plhs[0]); if (status == 0) { pr[0] = (DOUBLE) ndims; pr[1] = (DOUBLE) nvars; pr[2] = (DOUBLE) natts; pr[3] = (DOUBLE) recdim; } pr[4] = (DOUBLE) status; } break; case SYNC: status = ncsync(cdfid); plhs[0] = Int2Scalar(status); break; case ABORT: status = ncabort(cdfid); plhs[0] = Int2Scalar(status); break; case DIMDEF: name = Mat2Str(prhs[2]); length = Parameter(prhs[3]); dimid = ncdimdef(cdfid, name, length); plhs[0] = Int2Scalar(dimid); plhs[1] = Int2Scalar((dimid >= 0) ? 0 : dimid); Free((VOIDPP) & name); break; case DIMID: name = Mat2Str(prhs[2]); dimid = ncdimid(cdfid, name); plhs[0] = Int2Scalar(dimid); plhs[1] = Int2Scalar((dimid >= 0) ? 0 : dimid); Free((VOIDPP) & name); break; case DIMINQ: name = (char *) calloc(MAX_NC_NAME, sizeof(char)); status = ncdiminq(cdfid, dimid, name, & length); plhs[0] = Str2Mat(name); plhs[1] = Long2Scalar(length); plhs[2] = Int2Scalar(status); Free((VOIDPP) & name); break; case DIMRENAME: name = Mat2Str(prhs[3]); status = ncdimrename(cdfid, dimid, name); plhs[0] = Int2Scalar(status); Free((VOIDPP) & name); break; case VARDEF: name = Mat2Str(prhs[2]); datatype = (nc_type) Parameter(prhs[3]); ndims = Scalar2Int(prhs[4]); if (ndims == -1) { ndims = Count(prhs[5]); } dim = Mat2Int(prhs[5]); varid = ncvardef(cdfid, name, datatype, ndims, dim); Free((VOIDPP) & name); plhs[0] = Int2Scalar(varid); plhs[1] = Int2Scalar((varid >= 0) ? 0 : varid); break; case VARID: name = Mat2Str(prhs[2]); varid = ncvarid(cdfid, name); Free((VOIDPP) & name); plhs[0] = Int2Scalar(varid); plhs[1] = Int2Scalar((varid >= 0) ? 0 : varid); break; case VARINQ: name = (char *) calloc(MAX_NC_NAME, sizeof(char)); dim = (int *) calloc(MAX_VAR_DIMS, sizeof(int)); status = ncvarinq(cdfid, varid, name, & datatype, & ndims, dim, & natts); plhs[0] = Str2Mat(name); plhs[1] = Int2Scalar(datatype); plhs[2] = Int2Scalar(ndims); plhs[3] = Int2Mat(dim, 1, ndims); plhs[4] = Int2Scalar(natts); plhs[5] = Int2Scalar(status); Free((VOIDPP) & name); Free((VOIDPP) & dim); break; case VARPUT1: coords = Mat2Long(prhs[3]); name = (char *) calloc(MAX_NC_NAME, sizeof(char)); dim = (int *) calloc(MAX_NC_DIMS, sizeof(int)); status = ncvarinq(cdfid, varid, name, & datatype, & ndims, dim, & natts); Free((VOIDPP) & name); Free((VOIDPP) & dim); pr = mxGetPr(prhs[4]); autoscale = (nrhs > 5 && Scalar2Int(prhs[5]) != 0); if (!autoscale) { scalefactor = 1.0; addoffset = 0.0; } status = Convert(opcode, datatype, 1, buffer, scalefactor, addoffset, pr); status = ncvarput1(cdfid, varid, coords, buffer); plhs[0] = Int2Scalar(status); Free((VOIDPP) & coords); break; case VARGET1: coords = Mat2Long(prhs[3]); autoscale = (nrhs > 4 && Scalar2Int(prhs[4]) != 0); if (!autoscale) { scalefactor = 1.0; addoffset = 0.0; } name = (char *) calloc(MAX_NC_NAME, sizeof(char)); dim = (int *) calloc(MAX_NC_DIMS, sizeof(int)); status = ncvarinq(cdfid, varid, name, & datatype, & ndims, dim, & natts); Free((VOIDPP) & name); Free((VOIDPP) & dim); plhs[0] = Int2Scalar(0); if (datatype == NC_CHAR) { mat = SetStr(plhs[0]); if (mat != NULL) { plhs[0] = mat; } } pr = mxGetPr(plhs[0]); status = ncvarget1(cdfid, varid, coords, buffer); status = Convert(opcode, datatype, 1, buffer, scalefactor, addoffset, pr); plhs[1] = Int2Scalar(status); Free((VOIDPP) & coords); break; case VARPUT: start = Mat2Long(prhs[3]); count = Mat2Long(prhs[4]); pr = mxGetPr(prhs[5]); autoscale = (nrhs > 6 && Scalar2Int(prhs[6]) != 0); if (!autoscale) { scalefactor = 1.0; addoffset = 0.0; } name = (char *) calloc(MAX_NC_NAME, sizeof(char)); dim = (int *) calloc(MAX_NC_DIMS, sizeof(int)); status = ncvarinq(cdfid, varid, name, & datatype, & ndims, dim, & natts); for (i = 0; i < ndims; i++) { if (count[i] == -1) { status = ncdiminq(cdfid, dim[i], name, & count[i]); count[i] -= start[i]; } } Free((VOIDPP) & name); Free((VOIDPP) & dim); len = 0; if (ndims > 0) { len = 1; for (i = 0; i < ndims; i++) { len *= count[i]; } } value = (VOIDP) calloc(len, nctypelen(datatype)); status = Convert(opcode, datatype, len, value, scalefactor, addoffset, pr); status = ncvarput(cdfid, varid, start, count, value); Free((VOIDPP) & value); plhs[0] = Int2Scalar(status); Free((VOIDPP) & start); Free((VOIDPP) & count); break; case VARGET: start = Mat2Long(prhs[3]); count = Mat2Long(prhs[4]); autoscale = (nrhs > 5 && Scalar2Int(prhs[5]) != 0); if (!autoscale) { scalefactor = 1.0; addoffset = 0.0; } name = (char *) calloc(MAX_NC_NAME, sizeof(char)); dim = (int *) calloc(MAX_NC_DIMS, sizeof(int)); status = ncvarinq(cdfid, varid, name, & datatype, & ndims, dim, & natts); for (i = 0; i < ndims; i++) { if (count[i] == -1) { status = ncdiminq(cdfid, dim[i], name, & count[i]); count[i] -= start[i]; } } Free((VOIDPP) & name); Free((VOIDPP) & dim); m = 0; n = 0; if (ndims > 0) { m = count[0]; n = count[0]; for (i = 1; i < ndims; i++) { n *= count[i]; if (count[i] > 1) { m = count[i]; } } n /= m; } len = m * n; plhs[0] = mxCreateFull(m, n, REAL); if (datatype == NC_CHAR) { mat = SetStr(plhs[0]); if (mat != NULL) { plhs[0] = mat; } } pr = mxGetPr(plhs[0]); value = (VOIDP) calloc(len, nctypelen(datatype)); status = ncvarget(cdfid, varid, start, count, value); status = Convert(opcode, datatype, len, value, scalefactor, addoffset, pr); Free((VOIDPP) & value); plhs[1] = Int2Scalar(status); Free((VOIDPP) & start); Free((VOIDPP) & count); break; case VARPUTG: start = Mat2Long(prhs[3]); count = Mat2Long(prhs[4]); stride = Mat2Long(prhs[5]); imap = NULL; if (nrhs > 7) { pr = mxGetPr(prhs[7]); } else { pr = mxGetPr(prhs[6]); } autoscale = (nrhs > 8 && Scalar2Int(prhs[8]) != 0); if (!autoscale) { scalefactor = 1.0; addoffset = 0.0; } name = (char *) calloc(MAX_NC_NAME, sizeof(char)); dim = (int *) calloc(MAX_NC_DIMS, sizeof(int)); status = ncvarinq(cdfid, varid, name, & datatype, & ndims, dim, & natts); for (i = 0; i < ndims; i++) { if (count[i] == -1) { status = ncdiminq(cdfid, dim[i], name, & count[i]); count[i] -= start[i]; } } Free((VOIDPP) & name); Free((VOIDPP) & dim); len = 0; if (ndims > 0) { len = 1; for (i = 0; i < ndims; i++) { len *= count[i]; } } value = (VOIDP) calloc(len, nctypelen(datatype)); status = Convert(opcode, datatype, len, value, scalefactor, addoffset, pr); status = ncvarputg(cdfid, varid, start, count, stride, imap, value); Free((VOIDPP) & value); plhs[0] = Int2Scalar(status); Free((VOIDPP) & stride); Free((VOIDPP) & count); Free((VOIDPP) & start); break; case VARGETG: start = Mat2Long(prhs[3]); count = Mat2Long(prhs[4]); stride = Mat2Long(prhs[5]); imap = NULL; autoscale = (nrhs > 7 && Scalar2Int(prhs[7]) != 0); if (!autoscale) { scalefactor = 1.0; addoffset = 0.0; } name = (char *) calloc(MAX_NC_NAME, sizeof(char)); dim = (int *) calloc(MAX_NC_DIMS, sizeof(int)); status = ncvarinq(cdfid, varid, name, & datatype, & ndims, dim, & natts); for (i = 0; i < ndims; i++) { if (count[i] == -1) { status = ncdiminq(cdfid, dim[i], name, & count[i]); count[i] -= start[i]; } } Free((VOIDPP) & name); Free((VOIDPP) & dim); m = 0; n = 0; if (ndims > 0) { m = count[0]; n = count[0]; for (i = 1; i < ndims; i++) { n *= count[i]; if (count[i] > 1) { m = count[i]; } } n /= m; } len = m * n; plhs[0] = mxCreateFull(m, n, REAL); if (datatype == NC_CHAR) { mat = SetStr(plhs[0]); if (mat != NULL) { plhs[0] = mat; } } pr = mxGetPr(plhs[0]); value = (VOIDP) calloc(len, nctypelen(datatype)); status = ncvargetg(cdfid, varid, start, count, stride, imap, value); status = Convert(opcode, datatype, len, value, scalefactor, addoffset, pr); Free((VOIDPP) & value); plhs[1] = Int2Scalar(status); Free((VOIDPP) & stride); Free((VOIDPP) & count); Free((VOIDPP) & start); break; case VARRENAME: name = Mat2Str(prhs[3]); status = ncdimrename(cdfid, varid, name); plhs[0] = Int2Scalar(status); Free((VOIDPP) & name); break; case ATTPUT: datatype = (nc_type) Parameter(prhs[4]); len = Scalar2Int(prhs[5]); if (len == -1) { len = Count(prhs[6]); } pr = mxGetPr(prhs[6]); value = (VOIDP) calloc(len, nctypelen(datatype)); status = Convert(opcode, datatype, len, value, (DOUBLE) 1.0, (DOUBLE) 0.0, pr); status = ncattput(cdfid, varid, attname, datatype, len, value); Free((VOIDPP) & value); plhs[0] = Int2Scalar(status); Free((VOIDPP) & attname); break; case ATTINQ: status = ncattinq(cdfid, varid, attname, & datatype, & len); plhs[0] = Int2Scalar((int) datatype); plhs[1] = Int2Scalar(len); plhs[2] = Int2Scalar(status); Free((VOIDPP) & attname); break; case ATTGET: status = ncattinq(cdfid, varid, attname, & datatype, & len); plhs[0] = mxCreateFull(1, len, REAL); if (datatype == NC_CHAR) { mat = SetStr(plhs[0]); if (mat != NULL) { plhs[0] = mat; } } pr = mxGetPr(plhs[0]); value = (VOIDP) calloc(len, nctypelen(datatype)); status = ncattget(cdfid, varid, attname, value); status = Convert(opcode, datatype, len, value, 1.0, 0.0, pr); Free((VOIDPP) & value); plhs[1] = Int2Scalar(status); Free((VOIDPP) & attname); break; case ATTCOPY: incdf = cdfid; invar = varid; outcdf = Scalar2Int(prhs[4]); if (mxIsNumeric(prhs[5])) { outvar = Scalar2Int(prhs[2]); } else { name = Mat2Str(prhs[5]); outvar = ncvarid(cdfid, name); Free((VOIDPP) & name); } status = ncattcopy(incdf, invar, attname, outcdf, outvar); plhs[0] = Int2Scalar(status); Free((VOIDPP) & attname); break; case ATTNAME: attnum = Scalar2Int(prhs[3]); attname = (char *) calloc(MAX_NC_NAME, sizeof(char)); status = ncattname(cdfid, varid, attnum, attname); plhs[0] = Str2Mat(attname); plhs[1] = Int2Scalar(status); Free((VOIDPP) & attname); break; case ATTRENAME: newname = Mat2Str(plhs[4]); status = ncattrename(cdfid, varid, attname, newname); plhs[0] = Int2Scalar(status); Free((VOIDPP) & attname); Free((VOIDPP) & newname); break; case ATTDEL: status = ncattdel(cdfid, varid, attname); plhs[0] = Int2Scalar(status); Free((VOIDPP) & attname); break; case RECPUT: recnum = Scalar2Long(prhs[2]); pr = mxGetPr(prhs[3]); autoscale = (nrhs > 4 && Scalar2Int(prhs[4]) != 0); if (!autoscale) { scalefactor = 1.0; addoffset = 0.0; } recvarids = (int *) calloc(MAX_VAR_DIMS, sizeof(int)); recsizes = (long *) calloc(MAX_VAR_DIMS, sizeof(long)); datap = (VOIDPP) calloc(MAX_VAR_DIMS, sizeof(VOIDP)); status = ncrecinq(cdfid, & nrecvars, recvarids, recsizes); if (status == -1) { plhs[0] = Int2Scalar(status); break; } length = 0; n = 0; for (i = 0; i < nrecvars; i++) { ncvarinq(cdfid, recvarids[i], NULL, & datatype, NULL, NULL, NULL); length += recsizes[i]; n += (recsizes[i] / nctypelen(datatype)); } if (Count(prhs[3]) < n) { status = -1; plhs[0] = Int2Scalar(status); break; } if ((value = (VOIDP) calloc((int) length, sizeof(char))) == NULL) { status = -1; plhs[0] = Int2Scalar(status); break; } length = 0; p = value; for (i = 0; i < nrecvars; i++) { datap[i] = p; p += recsizes[i]; } p = (char *) value; pr = mxGetPr(prhs[3]); for (i = 0; i < nrecvars; i++) { ncvarinq(cdfid, recvarids[i], NULL, & datatype, NULL, NULL, NULL); length = recsizes[i] / nctypelen(datatype); if (autoscale) { addoffset = Add_Offset(cdfid, recvarids[i]); scalefactor = Scale_Factor(cdfid, recvarids[i]); if (scalefactor == 0.0) { scalefactor = 1.0; } } Convert(opcode, datatype, length, (VOIDP) p, scalefactor, addoffset, pr); pr += length; p += recsizes[i]; } status = ncrecput(cdfid, recnum, datap); plhs[0] = Int2Scalar(status); Free ((VOIDPP) & value); Free ((VOIDPP) & datap); Free ((VOIDPP) & recsizes); Free ((VOIDPP) & recvarids); break; case RECGET: recnum = Scalar2Long(prhs[2]); autoscale = (nrhs > 3 && Scalar2Int(prhs[3]) != 0); if (!autoscale) { scalefactor = 1.0; addoffset = 0.0; } recvarids = (int *) calloc(MAX_VAR_DIMS, sizeof(int)); recsizes = (long *) calloc(MAX_VAR_DIMS, sizeof(long)); datap = (VOIDPP) calloc(MAX_VAR_DIMS, sizeof(VOIDP)); status = ncrecinq(cdfid, & nrecvars, recvarids, recsizes); if (status == -1) { Free ((VOIDPP) & recsizes); Free ((VOIDPP) & recvarids); plhs[1] = Int2Scalar(status); break; } if (nrecvars == 0) { Free ((VOIDPP) & recsizes); Free ((VOIDPP) & recvarids); plhs[0] = create_matrix(0, 0, REAL); break; } length = 0; n = 0; for (i = 0; i < nrecvars; i++) { ncvarinq(cdfid, recvarids[i], NULL, & datatype, NULL, NULL, NULL); length += recsizes[i]; n += (recsizes[i] / nctypelen(datatype)); } if ((value = (VOIDP) calloc((int) length, sizeof(char))) == NULL) { status = -1; plhs[1] = Int2Scalar(status); break; } if (value == NULL) { status = -1; plhs[1] = Int2Scalar(status); break; } length = 0; p = value; for (i = 0; i < nrecvars; i++) { datap[i] = p; p += recsizes[i]; } if ((status = ncrecget(cdfid, recnum, datap)) == -1) { plhs[1] = Int2Scalar(status); break; } m = 1; plhs[0] = mxCreateFull(m, n, REAL); if (plhs[0] == NULL) { status = -1; plhs[1] = Int2Scalar(status); break; } pr = mxGetPr(plhs[0]); p = (char *) value; for (i = 0; i < nrecvars; i++) { status = ncvarinq(cdfid, recvarids[i], NULL, & datatype, NULL, NULL, NULL); if (status == -1) { plhs[1] = Int2Scalar(status); break; } length = recsizes[i] / nctypelen(datatype); if (autoscale) { addoffset = Add_Offset(cdfid, recvarids[i]); scalefactor = Scale_Factor(cdfid, recvarids[i]); if (scalefactor == 0.0) { scalefactor = 1.0; } } Convert(opcode, datatype, length, (VOIDP) p, scalefactor, addoffset, pr); pr += length; p += recsizes[i]; } plhs[1] = Int2Scalar(status); Free ((VOIDPP) & value); Free ((VOIDPP) & datap); Free ((VOIDPP) & recsizes); Free ((VOIDPP) & recvarids); break; case RECINQ: recvarids = (int *) calloc(MAX_VAR_DIMS, sizeof(int)); recsizes = (long *) calloc(MAX_VAR_DIMS, sizeof(long)); status = ncrecinq(cdfid, & nrecvars, recvarids, recsizes); if (status != -1) { for (i = 0; i < nrecvars; i++) { ncvarinq(cdfid, recvarids[i], NULL, & datatype, NULL, NULL, NULL); recsizes[i] /= nctypelen(datatype); } m = 1; n = nrecvars; plhs[0] = Int2Mat(recvarids, m, n); plhs[1] = Long2Mat(recsizes, m, n); } plhs[2] = Int2Scalar(status); Free ((VOIDPP) & recsizes); Free ((VOIDPP) & recvarids); break; case TYPELEN: datatype = (nc_type) Parameter(prhs[1]); len = nctypelen(datatype); plhs[0] = Int2Scalar(len); plhs[1] = Int2Scalar((len >= 0) ? 0 : 1); break; case SETFILL: fillmode = Scalar2Int(prhs[1]); status = ncsetfill(cdfid, fillmode); plhs[0] = Int2Scalar(status); plhs[1] = Int2Scalar(0); break; case SETOPTS: plhs[0] = Int2Scalar(ncopts); plhs[1] = Int2Scalar(0); ncopts = Scalar2Int(prhs[1]); break; case ERR: plhs[0] = Int2Scalar(ncerr); plhs[1] = Int2Scalar(0); break; case PARAMETER: if (nrhs > 1) { plhs[0] = Int2Scalar(Parameter(prhs[1])); plhs[1] = Int2Scalar(0); } else { i = 0; while (strcmp(parms[i].name, "NONE") != 0) { printf("%12d %s\n", parms[i].code, parms[i].name); i++; } plhs[0] = Int2Scalar(0); plhs[1] = Int2Scalar(-1); } break; default: break; } return; } /* Convert(): Convert between DOUBLE and NetCDF numeric types. */ static int Convert ( OPCODE opcode, nc_type datatype, int len, VOIDP value, DOUBLE scalefactor, DOUBLE addoffset, DOUBLE * pr ) { char * pbyte; char * pchar; short * pshort; long * plong; float * pfloat; double * pdouble; int i; int status; status = 0; switch (opcode) { case VARPUT: case VARPUT1: case ATTPUT: switch (datatype) { case NC_BYTE: pbyte = (char *) value; for (i = 0; i < len; i++) { *pbyte++ = (char) ((*pr++ - addoffset) / scalefactor); } break; case NC_CHAR: pchar = (char *) value; for (i = 0; i < len; i++) { *pchar++ = (char) ((*pr++ - addoffset) / scalefactor); } break; case NC_SHORT: pshort = (short *) value; for (i = 0; i < len; i++) { *pshort++ = (short) ((*pr++ - addoffset) / scalefactor); } break; case NC_LONG: plong = (long *) value; for (i = 0; i < len; i++) { *plong++ = (long) ((*pr++ - addoffset) / scalefactor); } break; case NC_FLOAT: pfloat = (float *) value; for (i = 0; i < len; i++) { *pfloat++ = (float) ((*pr++ - addoffset) / scalefactor); } break; case NC_DOUBLE: pdouble = (double *) value; for (i = 0; i < len; i++) { *pdouble++ = (double) ((*pr++ - addoffset) / scalefactor); } break; default: status = -1; break; } break; case VARGET: case VARGET1: case ATTGET: switch (datatype) { case NC_BYTE: pbyte = (char *) value; for (i = 0; i < len; i++) { *pr++ = (DOUBLE) *pbyte++; } break; case NC_CHAR: pchar = (char *) value; for (i = 0; i < len; i++) { *pr++ = addoffset + scalefactor * (DOUBLE) *pchar++; } break; case NC_SHORT: pshort = (short *) value; for (i = 0; i < len; i++) { *pr++ = addoffset + scalefactor * (DOUBLE) *pshort++; } break; case NC_LONG: plong = (long *) value; for (i = 0; i < len; i++) { *pr++ = addoffset + scalefactor * (DOUBLE) *plong++; } break; case NC_FLOAT: pfloat = (float *) value; for (i = 0; i < len; i++) { *pr++ = addoffset + scalefactor * (DOUBLE) *pfloat++; } break; case NC_DOUBLE: pdouble = (double *) value; for (i = 0; i < len; i++) { *pr++ = addoffset + scalefactor * (DOUBLE) *pdouble++; } break; default: status = -1; break; } break; case VARPUTG: case RECPUT: switch (datatype) { case NC_BYTE: pbyte = (char *) value; for (i = 0; i < len; i++) { *pbyte++ = (char) ((*pr++ - addoffset) / scalefactor); } break; case NC_CHAR: pchar = (char *) value; for (i = 0; i < len; i++) { *pchar++ = (char) ((*pr++ - addoffset) / scalefactor); } break; case NC_SHORT: pshort = (short *) value; for (i = 0; i < len; i++) { *pshort++ = (short) ((*pr++ - addoffset) / scalefactor); } break; case NC_LONG: plong = (long *) value; for (i = 0; i < len; i++) { *plong++ = (long) ((*pr++ - addoffset) / scalefactor); } break; case NC_FLOAT: pfloat = (float *) value; for (i = 0; i < len; i++) { *pfloat++ = (float) ((*pr++ - addoffset) / scalefactor); } break; case NC_DOUBLE: pdouble = (double *) value; for (i = 0; i < len; i++) { *pdouble++ = (double) ((*pr++ - addoffset) / scalefactor); } break; default: status = -1; break; } break; case VARGETG: case RECGET: switch (datatype) { case NC_BYTE: pbyte = (char *) value; for (i = 0; i < len; i++) { *pr++ = (DOUBLE) *pbyte++; } break; case NC_CHAR: pchar = (char *) value; for (i = 0; i < len; i++) { *pr++ = addoffset + scalefactor * (DOUBLE) *pchar++; } break; case NC_SHORT: pshort = (short *) value; for (i = 0; i < len; i++) { *pr++ = addoffset + scalefactor * (DOUBLE) *pshort++; } break; case NC_LONG: plong = (long *) value; for (i = 0; i < len; i++) { *pr++ = addoffset + scalefactor * (DOUBLE) *plong++; } break; case NC_FLOAT: pfloat = (float *) value; for (i = 0; i < len; i++) { *pr++ = addoffset + scalefactor * (DOUBLE) *pfloat++; } break; case NC_DOUBLE: pdouble = (double *) value; for (i = 0; i < len; i++) { *pr++ = addoffset + scalefactor * (DOUBLE) *pdouble++; } break; default: status = -1; break; } break; default: status = -1; break; } return (status); } /* Usage(): Print information on NCMEX usage. */ static VOID Usage ( ) { # if defined __DATE__ # if defined __TIME__ # if !defined __FILE__ # define __FILE__ "mexcdf.c" # endif printf("Program %s Version %s %s\n", __FILE__, __DATE__, __TIME__); # endif # endif printf("Copyright (C) 1992 Charles R. Denham, ZYDECO.\n"); printf("All Rights Reserved.\n"); # if defined VERBOSE printf("\n"); printf("mexcdf(\'USAGE\')\n"); printf("\n"); printf("mexcdf(\'CREATE\', \'path\', cmode) ==> [cdfid, status]\n"); printf("mexcdf(\'OPEN\', \'path\', mode) ==> [cdfid, status]\n"); printf("mexcdf(\'REDEF\', cdfid) ==> status\n"); printf("mexcdf(\'ENDEF\', cdfid) ==> status\n"); printf("mexcdf(\'INQUIRE\', cdfid) ==> [ndims, nvars, natts, recdim, status]\n"); printf("mexcdf(\'SYNC\', cdfid) ==> status\n"); printf("mexcdf(\'ABORT\', cdfid) ==> status\n"); printf("mexcdf(\'CLOSE\', cdfid) ==> status\n"); printf("\n"); printf("mexcdf(\'DIMDEF\', cdfid, \'name\', length) ==> [dimid, status]\n"); printf("mexcdf(\'DIMID\', cdfid, \'name\') ==> [dimid, status]\n"); printf("mexcdf(\'DIMINQ\', cdfid, dimid) ==> [\'name\', length, status]\n"); printf("mexcdf(\'DIMRENAME\', cdfid, \'name\') ==> status\n"); printf("\n"); printf("mexcdf(\'VARDEF\', cdfid, \'name\', datatype, ndims, [dim]) ==> [varid, status]\n"); printf("mexcdf(\'VARID\', cdfid, \'name\') ==> [varid, status]\n"); printf("mexcdf(\'VARINQ\', cdfid, varid) ==> [\'name\', datatype, ndims, [dim], natts, status]\n"); printf("mexcdf(\'VARPUT1\', cdfid, varid, [coords], value, autoscale) ==> status\n"); printf("mexcdf(\'VARGET1\', cdfid, varid, [coords], flag) ==> [value, status]\n"); printf("mexcdf(\'VARPUT\', cdfid, varid, [start], [count], [value], autoscale) ==> status\n"); printf("mexcdf(\'VARGET\', cdfid, varid, [start], [count], autoscale) ==> [[value], status]\n"); printf("mexcdf(\'VARPUTG\', cdfid, varid, [start], [count], [stride], [imap], [value], autoscale) ==> status\n"); printf("mexcdf(\'VARGETG\', cdfid, varid, [start], [count], [stride], [imap], autoscale) ==> [[value], status]\n"); printf("mexcdf(\'VARRENAME\', cdfid, varid, \'name\') ==> status\n"); printf("\n"); printf("mexcdf(\'ATTPUT\', cdfid, varid, \'name\', datatype, len, [value]) ==> status\n"); printf("mexcdf(\'ATTINQ\', cdfid, varid, \'name\') ==> [datatype, len, status]\n"); printf("mexcdf(\'ATTGET\', cdfid, varid, \'name\') ==> [[value], len, status]\n"); printf("mexcdf(\'ATTCOPY\', incdf, invar, \'name\', outcdf, outvar) ==> status\n"); printf("mexcdf(\'ATTNAME\', cdfid, varid, attnum) ==> [\'name\', status]\n"); printf("mexcdf(\'ATTRENAME\', cdfid, varid, \'name\', \'newname\') ==> status\n"); printf("mexcdf(\'ATTDEL\', cdfid, varid, \'name\') ==> status\n"); printf("\n"); printf("mexcdf(\'RECPUT\', cdfid, recnum, [data], autoscale) ==> status\n"); printf("mexcdf(\'RECGET\', cdfid, recnum, autoscale) ==> [[data], status]\n"); printf("mexcdf(\'RECINQ\', cdfid) ==> [[recvarids], [recsizes], status]\n"); printf("\n"); printf("mexcdf(\'TYPELEN\', datatype) ==> [len, status]\n"); printf("mexcdf(\'SETFILL\', cdfid, fillmode) ==> [old_fillmode, status]\n"); printf("mexcdf(\'SETOPTS\', ncopts) ==> [old_ncopts, status]\n"); printf("mexcdf(\'ERR\') ==> [ncerr, status]\n"); printf("mexcdf(\'PARAMETER\', \'NC_...\') ==> [code, status]\n"); # else int i; int j; i = 0; while (ops[i].opcode != NONE) { printf("mexcdf(\'%s\'", ops[i].opname); for (j = 1; j < ops[i].nrhs; j++) { printf(", in%d", j); } printf(")"); if (ops[i].nlhs > 0) { printf(" ==> ["); for (j = 1; j <= ops[i].nlhs; j++) { printf("out%d", j); if (j < ops[i].nlhs) { printf(", "); } } printf("]"); } printf("\n"); i++; } # endif return; } /* Parameter(): Get NetCDF parameter by name. */ static int Parameter ( Matrix * mat ) { int parameter; char * p; char * q; int i; parameter = -1; if (mxIsNumeric(mat)) { parameter = Scalar2Int(mat); } else { p = Mat2Str(mat); q = p; for (i = 0; i < strlen(p); i++) { *q = (char) toupper((int) *q); q++; } if (strncmp(p, "NC_", 3) == 0) { /* Trim away "NC_". */ q = p + 3; } else { q = p; } i = 0; while (strcmp(parms[i].name, "NONE") != 0) { if (strncmp(q, parms[i].name, parms[i].len) == 0) { parameter = parms[i].code; break; } else { i++; } } Free ((VOIDPP) & p); } return (parameter); } /* Scale_Factor: Return "scale_factor" attribute as DOUBLE. */ static DOUBLE Scale_Factor ( int cdfid, int varid ) { int status; nc_type datatype; int len; char value[32]; DOUBLE d; d = 1.0; if ((status = ncattinq(cdfid, varid, "scale_factor", &datatype, &len)) == -1) { } else if ((status = ncattget(cdfid, varid, "scale_factor", value)) == -1) { } else { switch (datatype) { case NC_BYTE: d = (DOUBLE) *((char *) value); break; case NC_CHAR: d = (DOUBLE) *((char *) value); break; case NC_SHORT: d = (DOUBLE) *((short *) value); break; case NC_LONG: d = (DOUBLE) *((long *) value); break; case NC_FLOAT: d = (DOUBLE) *((float *) value); break; case NC_DOUBLE: d = (DOUBLE) *((double *) value); break; default: break; } } return (d); } /* Add_Offset: Return "add_offset" attribute as DOUBLE. */ static DOUBLE Add_Offset ( int cdfid, int varid ) { int status; nc_type datatype; int len; char value[32]; DOUBLE d; d = 0.0; if ((status = ncattinq(cdfid, varid, "add_offset", &datatype, &len)) == -1) { } else if ((status = ncattget(cdfid, varid, "add_offset", value)) == -1) { } else { switch (datatype) { case NC_BYTE: d = (DOUBLE) *((char *) value); break; case NC_CHAR: d = (DOUBLE) *((char *) value); break; case NC_SHORT: d = (DOUBLE) *((short *) value); break; case NC_LONG: d = (DOUBLE) *((long *) value); break; case NC_FLOAT: d = (DOUBLE) *((float *) value); break; case NC_DOUBLE: d = (DOUBLE) *((double *) value); break; default: break; } } return (d); } /* SetNum(): Convert matrix display-type to numeric. */ static Matrix * SetNum ( Matrix * mat ) { Matrix * result = NULL; int status; if (mxIsString(mat)) { mexSetTrapFlag(1); status = mexCallMATLAB(1, & result, 1, & mat, "abs"); if (status == 1) { result = NULL; } mexSetTrapFlag(0); } return (result); } /* SetStr(): Convert matrix display-type to string. */ static Matrix * SetStr ( Matrix * mat ) { Matrix * result = NULL; int status; if (mxIsNumeric(mat)) { mexSetTrapFlag(1); status = mexCallMATLAB(1, & result, 1, & mat, "setstr"); if (status == 1) { result = NULL; } mexSetTrapFlag(0); } return (result); } /* Mat2Str(): Return string from a string-matrix. */ static char * Mat2Str ( Matrix * mat ) { DOUBLE * pr; char * p; char * str; int len; int i; len = mxGetM(mat) * mxGetN(mat); str = (char *) calloc(len + 1, sizeof(char)); p = str; pr = mxGetPr(mat); for (i = 0; i < len; i++) { *p++ = (char) *pr++; } *p = '\0'; return (str); } /* Str2Mat(): Convert string into a string-matrix. */ static Matrix * Str2Mat ( char * str ) { Matrix * mat; mat = mxCreateString(str); return (mat); } /* Mat2Long(): Return matrix values as a long integer array. */ static long * Mat2Long ( Matrix * mat ) { DOUBLE * pr; long * plong; long * p; int len; int i; len = mxGetM(mat) * mxGetN(mat); plong = (long *) calloc(len, sizeof(long)); p = plong; pr = mxGetPr(mat); for (i = 0; i < len; i++) { *p++ = (long) *pr++; } return (plong); } /* Long2Mat(): Convert long integer array to a matrix. */ static Matrix * Long2Mat ( long * plong, int m, int n ) { Matrix * mat; DOUBLE * pr; long * p; int len; int i; mat = mxCreateFull(m, n, REAL); pr = mxGetPr(mat); p = plong; len = m * n; for (i = 0; i < len; i++) { *pr++ = (long) *p++; } return (mat); } /* Mat2Int(): Return matrix values as an integer array. */ static int * Mat2Int ( Matrix * mat ) { DOUBLE * pr; int * pint; int * p; int len; int i; len = mxGetM(mat) * mxGetN(mat); pint = (int *) calloc(len, sizeof(int)); p = pint; pr = mxGetPr(mat); for (i = 0; i < len; i++) { *p++ = (int) *pr++; } return (pint); } /* Int2Mat(): Convert integer array to a matrix. */ static Matrix * Int2Mat ( int * pint, int m, int n ) { Matrix * mat; DOUBLE * pr; int * p; int len; int i; mat = mxCreateFull(m, n, REAL); pr = mxGetPr(mat); p = pint; len = m * n; for (i = 0; i < len; i++) { *pr++ = (int) *p++; } return (mat); } /* Int2Scalar(): Convert integer value to a scalar matrix. */ static Matrix * Int2Scalar ( int i ) { Matrix * scalar; scalar = mxCreateFull(1, 1, REAL); *(mxGetPr(scalar)) = (DOUBLE) i; return (scalar); } /* Scalar2Int(): Return integer value of a scalar matrix.*/ static int Scalar2Int ( Matrix * scalar ) { return ((int) *(mxGetPr(scalar))); } /* Long2Scalar(): Convert long integer value to a scalar matrix. */ static Matrix * Long2Scalar ( long along ) { Matrix * scalar; scalar = mxCreateFull(1, 1, REAL); *(mxGetPr(scalar)) = (DOUBLE) along; return (scalar); } /* Scalar2Long(): Return long integer value of a scalar matrix. */ static long Scalar2Long ( Matrix * scalar ) { return ((long) *(mxGetPr(scalar))); } /* Count(): Element count of a matrix. */ static int Count ( Matrix * mat ) { return ((int) (mxGetM(mat) * mxGetN(mat))); } /* Free(): De-allocate memory by address of pointer. */ static VOID Free ( VOIDPP p ) { if (*p) { free(*p); *p = (VOIDP) 0; } }