EdgeCutProblem *EdgeCutProblem::create(EdgeCutProblem *_parent) { EdgeCutProblem *graph = create(_parent->cn, _parent->nz); if (!graph) return NULL; graph->x = (double *)SuiteSparse_malloc(_parent->nz, sizeof(double)); graph->w = (double *)SuiteSparse_malloc(_parent->cn, sizeof(double)); if (!graph->x || !graph->w) { graph->~EdgeCutProblem(); return NULL; } graph->W = _parent->W; graph->parent = _parent; graph->clevel = graph->parent->clevel + 1; return graph; }
Int *GPUQREngine_FindStaircase ( Front *front // The front whose staircase we are computing ) { Int fm = front->fm; Int fn = front->fn; double *F = front->F; Int *Stair = (Int*) SuiteSparse_malloc(fn, sizeof(Int)); if(!F || !Stair) return NULL; Int lastStair = 0; for(int j=0; j<fn; j++) { int i; for(i=fm-1; i>lastStair && F[i*fn+j] == 0.0; i--); Stair[j] = lastStair = i; } return Stair; }
cs *read_matrix(const char *filename, MM_typecode &matcode) { LogInfo("Reading Matrix from " << std::string(filename) << "\n"); FILE *file = fopen(filename, "r"); if (!file) { LogError("Error: Cannot read file " << std::string(filename) << "\n"); return NULL; } LogInfo("Reading Matrix Market banner..."); if (mm_read_banner(file, &matcode) != 0) { LogError("Error: Could not process Matrix Market banner\n"); fclose(file); return NULL; } if (!mm_is_matrix(matcode) || !mm_is_sparse(matcode) || mm_is_complex(matcode)) { LogError( "Error: Unsupported matrix format - Must be real and sparse\n"); fclose(file); return NULL; } Int M, N, nz; if ((mm_read_mtx_crd_size(file, &M, &N, &nz)) != 0) { LogError("Error: Could not parse matrix dimension and size.\n"); fclose(file); return NULL; } if (M != N) { LogError("Error: Matrix must be square.\n"); fclose(file); return NULL; } LogInfo("Reading matrix data...\n"); Int *I = (Int *)SuiteSparse_malloc(static_cast<size_t>(nz), sizeof(Int)); Int *J = (Int *)SuiteSparse_malloc(static_cast<size_t>(nz), sizeof(Int)); double *val = (double *)SuiteSparse_malloc(static_cast<size_t>(nz), sizeof(double)); if (!I || !J || !val) { LogError("Error: Ran out of memory in Mongoose::read_matrix\n"); SuiteSparse_free(I); SuiteSparse_free(J); SuiteSparse_free(val); fclose(file); return NULL; } mm_read_mtx_crd_data(file, M, N, nz, I, J, val, matcode); fclose(file); // Close the file for (Int k = 0; k < nz; k++) { --I[k]; --J[k]; if (mm_is_pattern(matcode)) val[k] = 1; } cs *A = (cs *)SuiteSparse_malloc(1, sizeof(cs)); if (!A) { LogError("Error: Ran out of memory in Mongoose::read_matrix\n"); SuiteSparse_free(I); SuiteSparse_free(J); SuiteSparse_free(val); return NULL; } A->nzmax = nz; A->m = M; A->n = N; A->p = J; A->i = I; A->x = val; A->nz = nz; LogInfo("Compressing matrix from triplet to CSC format...\n"); cs *compressed_A = cs_compress(A); cs_spfree(A); if (!compressed_A) { LogError("Error: Ran out of memory in Mongoose::read_matrix\n"); return NULL; } return compressed_A; }
GLOBAL Int AMD_order ( Int n, const Int Ap [ ], const Int Ai [ ], Int P [ ], double Control [ ], double Info [ ] ) { Int *Len, *S, nz, i, *Pinv, info, status, *Rp, *Ri, *Cp, *Ci, ok ; size_t nzaat, slen ; double mem = 0 ; #ifndef NDEBUG AMD_debug_init ("amd") ; #endif /* clear the Info array, if it exists */ info = Info != (double *) NULL ; if (info) { for (i = 0 ; i < AMD_INFO ; i++) { Info [i] = EMPTY ; } Info [AMD_N] = n ; Info [AMD_STATUS] = AMD_OK ; } /* make sure inputs exist and n is >= 0 */ if (Ai == (Int *) NULL || Ap == (Int *) NULL || P == (Int *) NULL || n < 0) { if (info) Info [AMD_STATUS] = AMD_INVALID ; return (AMD_INVALID) ; /* arguments are invalid */ } if (n == 0) { return (AMD_OK) ; /* n is 0 so there's nothing to do */ } nz = Ap [n] ; if (info) { Info [AMD_NZ] = nz ; } if (nz < 0) { if (info) Info [AMD_STATUS] = AMD_INVALID ; return (AMD_INVALID) ; } /* check if n or nz will cause size_t overflow */ if (((size_t) n) >= SIZE_T_MAX / sizeof (Int) || ((size_t) nz) >= SIZE_T_MAX / sizeof (Int)) { if (info) Info [AMD_STATUS] = AMD_OUT_OF_MEMORY ; return (AMD_OUT_OF_MEMORY) ; /* problem too large */ } /* check the input matrix: AMD_OK, AMD_INVALID, or AMD_OK_BUT_JUMBLED */ status = AMD_valid (n, n, Ap, Ai) ; if (status == AMD_INVALID) { if (info) Info [AMD_STATUS] = AMD_INVALID ; return (AMD_INVALID) ; /* matrix is invalid */ } /* allocate two size-n integer workspaces */ Len = SuiteSparse_malloc (n, sizeof (Int)) ; Pinv = SuiteSparse_malloc (n, sizeof (Int)) ; mem += n ; mem += n ; if (!Len || !Pinv) { /* :: out of memory :: */ SuiteSparse_free (Len) ; SuiteSparse_free (Pinv) ; if (info) Info [AMD_STATUS] = AMD_OUT_OF_MEMORY ; return (AMD_OUT_OF_MEMORY) ; } if (status == AMD_OK_BUT_JUMBLED) { /* sort the input matrix and remove duplicate entries */ AMD_DEBUG1 (("Matrix is jumbled\n")) ; Rp = SuiteSparse_malloc (n+1, sizeof (Int)) ; Ri = SuiteSparse_malloc (nz, sizeof (Int)) ; mem += (n+1) ; mem += MAX (nz,1) ; if (!Rp || !Ri) { /* :: out of memory :: */ SuiteSparse_free (Rp) ; SuiteSparse_free (Ri) ; SuiteSparse_free (Len) ; SuiteSparse_free (Pinv) ; if (info) Info [AMD_STATUS] = AMD_OUT_OF_MEMORY ; return (AMD_OUT_OF_MEMORY) ; } /* use Len and Pinv as workspace to create R = A' */ AMD_preprocess (n, Ap, Ai, Rp, Ri, Len, Pinv) ; Cp = Rp ; Ci = Ri ; } else { /* order the input matrix as-is. No need to compute R = A' first */ Rp = NULL ; Ri = NULL ; Cp = (Int *) Ap ; Ci = (Int *) Ai ; } /* --------------------------------------------------------------------- */ /* determine the symmetry and count off-diagonal nonzeros in A+A' */ /* --------------------------------------------------------------------- */ nzaat = AMD_aat (n, Cp, Ci, Len, P, Info) ; AMD_DEBUG1 (("nzaat: %g\n", (double) nzaat)) ; ASSERT ((MAX (nz-n, 0) <= nzaat) && (nzaat <= 2 * (size_t) nz)) ; /* --------------------------------------------------------------------- */ /* allocate workspace for matrix, elbow room, and 6 size-n vectors */ /* --------------------------------------------------------------------- */ S = NULL ; slen = nzaat ; /* space for matrix */ ok = ((slen + nzaat/5) >= slen) ; /* check for size_t overflow */ slen += nzaat/5 ; /* add elbow room */ for (i = 0 ; ok && i < 7 ; i++) { ok = ((slen + n) > slen) ; /* check for size_t overflow */ slen += n ; /* size-n elbow room, 6 size-n work */ } mem += slen ; ok = ok && (slen < SIZE_T_MAX / sizeof (Int)) ; /* check for overflow */ ok = ok && (slen < Int_MAX) ; /* S[i] for Int i must be OK */ if (ok) { S = SuiteSparse_malloc (slen, sizeof (Int)) ; } AMD_DEBUG1 (("slen %g\n", (double) slen)) ; if (!S) { /* :: out of memory :: (or problem too large) */ SuiteSparse_free (Rp) ; SuiteSparse_free (Ri) ; SuiteSparse_free (Len) ; SuiteSparse_free (Pinv) ; if (info) Info [AMD_STATUS] = AMD_OUT_OF_MEMORY ; return (AMD_OUT_OF_MEMORY) ; } if (info) { /* memory usage, in bytes. */ Info [AMD_MEMORY] = mem * sizeof (Int) ; } /* --------------------------------------------------------------------- */ /* order the matrix */ /* --------------------------------------------------------------------- */ AMD_1 (n, Cp, Ci, P, Pinv, Len, slen, S, Control, Info) ; /* --------------------------------------------------------------------- */ /* free the workspace */ /* --------------------------------------------------------------------- */ SuiteSparse_free (Rp) ; SuiteSparse_free (Ri) ; SuiteSparse_free (Len) ; SuiteSparse_free (Pinv) ; SuiteSparse_free (S) ; if (info) Info [AMD_STATUS] = status ; return (status) ; /* successful ordering */ }
int main (int argc, char **argv) { double xr, xz, xmin, xmax ; double *Ax, *Az ; Long nrow, ncol, mkind, skind, *Ap, *Ai, i, *Zp, *Zi, asize, mkind2, skind2, znz, j, p, status, njumbled, nzeros, build_upper, zero_handling, fem, xsize, nelnz, nnz, kk, anz ; int ok ; char title [73], key [9], mtype [4], mtype2 [4], *filename, s [100], *As ; SuiteSparse_config config ; config.malloc_memory = malloc ; config.free_memory = free ; /* test arg-handling for RB functions */ status = RBread (NULL, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL) ; if (status != RBIO_ARG_ERROR) { printf ("RBtest failure (1)!\n") ; return (1) ; } status = RBreadraw (NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL) ; if (status != RBIO_ARG_ERROR) { printf ("RBtest failure (2)\n") ; return (1) ; } status = RBread ("no file", build_upper, zero_handling, title, key, mtype, &nrow, &ncol, &mkind, &skind, &asize, &znz, &Ap, &Ai, &Ax, &Az, &Zp, &Zi, &config) ; if (status != RBIO_FILE_IOERROR) { printf ("RBtest failure (3)\n") ; return (1) ; } status = RBreadraw ("no file", title, key, mtype, &nrow, &ncol, &nnz, &nelnz, &mkind, &skind, &fem, &xsize, &Ap, &Ai, &Ax, NULL) ; if (status != RBIO_FILE_IOERROR) { printf ("RBtest failure (4)\n") ; return (1) ; } status = RBwrite (NULL, NULL, NULL, 1, 1, NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL) ; if (status != RBIO_ARG_ERROR) { printf ("RBtest failure (5)\n") ; return (1) ; } status = RBkind (1, 1, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL) ; if (status != RBIO_ARG_ERROR) { printf ("RBtest failure (6)\n") ; return (1) ; } status = RBread ("matrices/m4.rb", 1, 2, title, key, mtype, &nrow, &ncol, &mkind, &skind, &asize, &znz, &Ap, &Ai, &Ax, NULL, &Zp, &Zi, &config) ; if (status != 0) { SuiteSparse_free (Ap, &config) ; SuiteSparse_free (Ai, &config) ; SuiteSparse_free (Ax, &config) ; SuiteSparse_free (Zp, &config) ; SuiteSparse_free (Zi, &config) ; printf ("RBread test failure (7) "ID"\n", status) ; return (1) ; } /* mangle the matrix */ Ap [0] = 1 ; status = RBwrite ("temp.rb", title, key, nrow, ncol, Ap, Ai, Ax, NULL, Zp, Zi, mkind, mtype2, NULL) ; if (status == RBIO_OK) { printf ("RBtest failure (8)\n") ; return (1) ; } Ap [0] = 0 ; Zp [0] = 1 ; status = RBwrite ("temp.rb", title, key, nrow, ncol, Ap, Ai, Ax, NULL, Zp, Zi, mkind, mtype2, NULL) ; if (status == RBIO_OK) { printf ("RBtest failure (9)\n") ; return (1) ; } Zp [0] = 0 ; /* valid matrix */ status = RBwrite ("temp.rb", title, key, nrow, ncol, Ap, Ai, Ax, NULL, Zp, Zi, mkind, NULL, NULL) ; if (status != RBIO_OK) { printf ("RBtest failure (10) "ID"\n", status) ; return (1) ; } /* valid matrix, different integer formats */ Ax [0] = 1e5 ; for (kk = 0 ; kk < 10 ; kk++) { sprintf (s, "temp_" ID ".rb", kk) ; status = RBwrite (s, title, key, nrow, ncol, Ap, Ai, Ax, NULL, Zp, Zi, mkind, NULL, NULL) ; if (status != RBIO_OK) { printf ("RBtest failure (11) "ID" "ID"\n", status, kk) ; return (1) ; } Ax [0] *= 10 ; } /* valid matrix, but with a very large integer */ Ax [0] = 1e9 + 1 ; status = RBwrite ("temp1.rb", title, key, nrow, ncol, Ap, Ai, Ax, NULL, Zp, Zi, mkind, NULL, NULL) ; if (status != RBIO_OK) { printf ("RBtest failure (12) "ID"\n", status) ; return (1) ; } /* valid matrix, but with a very large real */ Ax [0] = 1e100 ; status = RBwrite ("temp2.rb", title, key, nrow, ncol, Ap, Ai, Ax, NULL, Zp, Zi, mkind, NULL, NULL) ; if (status != RBIO_OK) { printf ("RBtest failure (13) "ID"\n", status) ; return (1) ; } /* valid matrix, but with a Z that overlaps A */ Ax [0] = 1 ; Zi [0] = 1 ; status = RBwrite ("temp3.rb", title, key, nrow, ncol, Ap, Ai, Ax, NULL, Zp, Zi, mkind, NULL, NULL) ; if (status != RBIO_OK) { printf ("RBtest failure (14) "ID"\n", status) ; return (1) ; } /* invalid file name */ status = RBwrite ("gunk/gunk.rb", title, key, nrow, ncol, Ap, Ai, Ax, NULL, Zp, Zi, mkind, NULL, NULL) ; if (status != RBIO_FILE_IOERROR) { printf ("RBtest failure (12) "ID"\n", status) ; return (1) ; } /* cannot write a matrix with no entries */ for (j = 0 ; j <= ncol ; j++) { Ap [j] = 0 ; Zp [j] = 0 ; } status = RBwrite ("temp.rb", title, key, nrow, ncol, Ap, Ai, Ax, NULL, Zp, Zi, mkind, NULL, NULL) ; if (status != RBIO_DIM_INVALID) { printf ("RBtest failure (13) "ID"\n", status) ; return (1) ; } SuiteSparse_free (Ap, &config) ; SuiteSparse_free (Ai, &config) ; SuiteSparse_free (Ax, &config) ; SuiteSparse_free (Zp, &config) ; SuiteSparse_free (Zi, &config) ; /* re-read a valid matrix */ status = RBread ("matrices/m4.rb", 1, 0, title, key, mtype, &nrow, &ncol, &mkind, &skind, &asize, &znz, &Ap, &Ai, &Ax, NULL, NULL, NULL, &config) ; if (status != 0) { SuiteSparse_free (Ap, &config) ; SuiteSparse_free (Ai, &config) ; SuiteSparse_free (Ax, &config) ; SuiteSparse_free (Zp, &config) ; SuiteSparse_free (Zi, &config) ; printf ("RBread test failure (14) "ID"\n", status) ; return (1) ; } status = RBok (nrow, ncol, asize, Ap, Ai, Ax, Az, NULL, mkind, &njumbled, &nzeros) ; if (status != RBIO_OK) { printf ("RBread test failure (15) "ID"\n", status) ; } status = RBok (nrow, ncol, asize, Ap, Ai, Ax, Az, NULL, -1, &njumbled, &nzeros) ; if (status != RBIO_MKIND_INVALID) { printf ("RBread test failure (16) "ID"\n", status) ; } status = RBok (-1, ncol, asize, Ap, Ai, Ax, Az, NULL, mkind, &njumbled, &nzeros) ; if (status != RBIO_DIM_INVALID) { printf ("RBread test failure (17) "ID"\n", status) ; } i = Ap [1] ; Ap [1] = 999999 ; status = RBok (nrow, ncol, asize, Ap, Ai, Ax, Az, NULL, mkind, &njumbled, &nzeros) ; if (status != RBIO_CP_INVALID) { printf ("RBread test failure (18) "ID"\n", status) ; } Ap [1] = i ; status = RBok (nrow, ncol, asize, Ap, NULL, Ax, Az, NULL, mkind, &njumbled, &nzeros) ; if (status != RBIO_ROW_INVALID) { printf ("RBread test failure (19) "ID"\n", status) ; } i = Ai [0] ; Ai [0] = 999999 ; status = RBok (nrow, ncol, asize, Ap, Ai, Ax, Az, NULL, mkind, &njumbled, &nzeros) ; if (status != RBIO_ROW_INVALID) { printf ("RBread test failure (20) "ID"\n", status) ; } Ai [0] = i ; i = Ai [1] ; Ai [1] = Ai [0] ; status = RBok (nrow, ncol, asize, Ap, Ai, Ax, Az, NULL, mkind, &njumbled, &nzeros) ; if (status != RBIO_JUMBLED) { printf ("RBread test failure (21) "ID"\n", status) ; } Ai [1] = i ; ok = 1 ; As = (char *) SuiteSparse_malloc (asize, sizeof (char), &ok, &config) ; for (i = 0 ; i < asize ; i++) As [i] = 1 ; status = RBok (nrow, ncol, asize, Ap, Ai, Ax, Az, As, 1, &njumbled, &nzeros) ; if (status != RBIO_OK) { printf ("RBread test failure (22) "ID"\n", status) ; } SuiteSparse_free (As, &config) ; printf ("RBtest OK\n") ; return (0) ; }
EdgeCutProblem *EdgeCutProblem::create(const Int _n, const Int _nz, Int *_p, Int *_i, double *_x, double *_w) { void *memoryLocation = SuiteSparse_malloc(1, sizeof(EdgeCutProblem)); if (!memoryLocation) return NULL; // Placement new EdgeCutProblem *graph = new (memoryLocation) EdgeCutProblem(); graph->shallow_p = (_p != NULL); graph->shallow_i = (_i != NULL); graph->shallow_x = (_x != NULL); graph->shallow_w = (_w != NULL); size_t n = static_cast<size_t>(_n); graph->n = _n; size_t nz = static_cast<size_t>(_nz); graph->nz = _nz; graph->p = (graph->shallow_p) ? _p : (Int *)SuiteSparse_calloc(n + 1, sizeof(Int)); graph->i = (graph->shallow_i) ? _i : (Int *)SuiteSparse_malloc(nz, sizeof(Int)); graph->x = _x; graph->w = _w; graph->X = 0.0; graph->W = 0.0; graph->H = 0.0; if (!graph->p || !graph->i) { graph->~EdgeCutProblem(); return NULL; } graph->partition = (bool *)SuiteSparse_malloc(n, sizeof(bool)); graph->vertexGains = (double *)SuiteSparse_malloc(n, sizeof(double)); graph->externalDegree = (Int *)SuiteSparse_calloc(n, sizeof(Int)); graph->bhIndex = (Int *)SuiteSparse_calloc(n, sizeof(Int)); graph->bhHeap[0] = (Int *)SuiteSparse_malloc(n, sizeof(Int)); graph->bhHeap[1] = (Int *)SuiteSparse_malloc(n, sizeof(Int)); graph->bhSize[0] = graph->bhSize[1] = 0; if (!graph->partition || !graph->vertexGains || !graph->externalDegree || !graph->bhIndex || !graph->bhHeap[0] || !graph->bhHeap[1]) { graph->~EdgeCutProblem(); return NULL; } graph->heuCost = 0.0; graph->cutCost = 0.0; graph->W0 = 0.0; graph->W1 = 0.0; graph->imbalance = 0.0; graph->parent = NULL; graph->clevel = 0; graph->cn = 0; graph->matching = (Int *)SuiteSparse_calloc(n, sizeof(Int)); graph->matchmap = (Int *)SuiteSparse_malloc(n, sizeof(Int)); graph->invmatchmap = (Int *)SuiteSparse_malloc(n, sizeof(Int)); graph->matchtype = (Int *)SuiteSparse_malloc(n, sizeof(Int)); graph->markArray = (Int *)SuiteSparse_calloc(n, sizeof(Int)); graph->markValue = 1; graph->singleton = -1; if (!graph->matching || !graph->matchmap || !graph->invmatchmap || !graph->markArray || !graph->matchtype) { graph->~EdgeCutProblem(); return NULL; } graph->initialized = false; return graph; }
void mexFunction ( int nargout, mxArray *pargout [ ], int nargin, const mxArray *pargin [ ] ) { Long *Ap, *Ai, *Zp, *Zi ; double *Ax, *Az, *Zx ; Long p, j, build_upper, zero_handling, nrow, ncol, mkind, skind, asize, znz, status ; char filename [LEN+1], title [73], key [9], mtype [4] ; /* ---------------------------------------------------------------------- */ /* check inputs */ /* ---------------------------------------------------------------------- */ if (nargin != 1 || nargout > 5 || !mxIsChar (pargin [0])) { mexErrMsgTxt ("Usage: [A Z title key mtype] = RBread (filename)") ; } /* ---------------------------------------------------------------------- */ /* get filename */ /* ---------------------------------------------------------------------- */ if (mxGetString (pargin [0], filename, LEN) != 0) { mexErrMsgTxt ("filename too long") ; } /* ---------------------------------------------------------------------- */ /* read the matrix */ /* ---------------------------------------------------------------------- */ build_upper = TRUE ; /* always build upper tri. part */ zero_handling = (nargout > 1) ? 2 : 1 ; /* prune or extract zeros */ status = RBread (filename, build_upper, zero_handling, title, key, mtype, &nrow, &ncol, &mkind, &skind, &asize, &znz, &Ap, &Ai, &Ax, &Az, &Zp, &Zi) ; if (status != RBIO_OK) { RBerror (status) ; mexErrMsgTxt ("error reading file") ; } /* ---------------------------------------------------------------------- */ /* return A to MATLAB */ /* ---------------------------------------------------------------------- */ pargout [0] = mxCreateSparse (0, 0, 0, (mkind == 2) ? mxCOMPLEX : mxREAL) ; mxFree (mxGetJc (pargout [0])) ; mxFree (mxGetIr (pargout [0])) ; mxFree (mxGetPr (pargout [0])) ; if (mkind == 2) mxFree (mxGetPi (pargout [0])) ; mxSetM (pargout [0], nrow) ; mxSetN (pargout [0], ncol) ; mxSetNzmax (pargout [0], asize) ; mxSetJc (pargout [0], (mwIndex *) Ap) ; mxSetIr (pargout [0], (mwIndex *) Ai) ; mxSetPr (pargout [0], Ax) ; if (mkind == 2) mxSetPi (pargout [0], Az) ; /* ---------------------------------------------------------------------- */ /* return Z to MATLAB */ /* ---------------------------------------------------------------------- */ if (nargout > 1) { Zx = (double *) SuiteSparse_malloc (znz, sizeof (double)) ; for (p = 0 ; p < znz ; p++) { Zx [p] = 1 ; } pargout [1] = mxCreateSparse (0, 0, 0, mxREAL) ; mxFree (mxGetJc (pargout [1])) ; mxFree (mxGetIr (pargout [1])) ; mxFree (mxGetPr (pargout [1])) ; mxSetM (pargout [1], nrow) ; mxSetN (pargout [1], ncol) ; mxSetNzmax (pargout [1], MAX (znz,1)) ; mxSetJc (pargout [1], (mwIndex *) Zp) ; mxSetIr (pargout [1], (mwIndex *) Zi) ; mxSetPr (pargout [1], Zx) ; } /* ---------------------------------------------------------------------- */ /* return title */ /* ---------------------------------------------------------------------- */ if (nargout > 2) { pargout [2] = mxCreateString (title) ; } /* ---------------------------------------------------------------------- */ /* return key */ /* ---------------------------------------------------------------------- */ if (nargout > 3) { pargout [3] = mxCreateString (key) ; } /* ---------------------------------------------------------------------- */ /* return mtype */ /* ---------------------------------------------------------------------- */ if (nargout > 4) { pargout [4] = mxCreateString (mtype) ; } }