core/matlab/examples/mex/explore.c

00001 /*=================================================================
00002  * The main routine analyzes all incoming (right-hand side) arguments 
00003  *
00004  * Copyright 1984-2006 The MathWorks, Inc.
00005  * $Revision: 1.1 $ 
00006  *  
00007  *=================================================================*/
00008 
00009 #include <stdio.h>
00010 #include <string.h>
00011 #include "mex.h"
00012  
00013 
00014 void        display_subscript(const mxArray *array_ptr, mwSize index);
00015 void        get_characteristics(const mxArray  *array_ptr);
00016 mxClassID   analyze_class(const mxArray *array_ptr);
00017 
00018 
00019 /* Pass analyze_cell a pointer to a cell mxArray.  Each element
00020    in a cell mxArray is called a "cell"; each cell holds zero
00021    or one mxArray.  analyze_cell accesses each cell and displays
00022    information about it. */  
00023 static void
00024 analyze_cell(const mxArray *cell_array_ptr)
00025 {
00026   mwSize total_num_of_cells;
00027   mwIndex index;
00028   const mxArray *cell_element_ptr;
00029   
00030   total_num_of_cells = mxGetNumberOfElements(cell_array_ptr); 
00031   mexPrintf("total num of cells = %d\n", total_num_of_cells);
00032   mexPrintf("\n");
00033 
00034   /* Each cell mxArray contains m-by-n cells; Each of these cells
00035      is an mxArray. */ 
00036   for (index=0; index<total_num_of_cells; index++)  {
00037     mexPrintf("\n\n\t\tCell Element: ");
00038     display_subscript(cell_array_ptr, index);
00039     mexPrintf("\n");
00040     cell_element_ptr = mxGetCell(cell_array_ptr, index);
00041     if (cell_element_ptr == NULL) {
00042       mexPrintf("\tEmpty Cell\n");
00043     } else {
00044       /* Display a top banner. */
00045       mexPrintf("------------------------------------------------\n");
00046       get_characteristics(cell_element_ptr);
00047       analyze_class(cell_element_ptr);
00048       mexPrintf("\n");
00049     }
00050   }
00051   mexPrintf("\n");
00052 }
00053 
00054 
00055 /* Pass analyze_structure a pointer to a structure mxArray.  Each element
00056    in a structure mxArray holds one or more fields; each field holds zero
00057    or one mxArray.  analyze_structure accesses every field of every
00058    element and displays information about it. */ 
00059 static void
00060 analyze_structure(const mxArray *structure_array_ptr)
00061 {
00062   mwSize total_num_of_elements;
00063   mwIndex index;
00064   int number_of_fields, field_index;
00065   const char  *field_name;
00066   const mxArray *field_array_ptr;
00067   
00068 
00069   mexPrintf("\n");
00070   total_num_of_elements = mxGetNumberOfElements(structure_array_ptr); 
00071   number_of_fields = mxGetNumberOfFields(structure_array_ptr);
00072   
00073   /* Walk through each structure element. */
00074   for (index=0; index<total_num_of_elements; index++)  {
00075     
00076     /* For the given index, walk through each field. */ 
00077     for (field_index=0; field_index<number_of_fields; field_index++)  {
00078       mexPrintf("\n\t\t");
00079       display_subscript(structure_array_ptr, index);
00080          field_name = mxGetFieldNameByNumber(structure_array_ptr, 
00081                                              field_index);
00082       mexPrintf(".%s\n", field_name);
00083       field_array_ptr = mxGetFieldByNumber(structure_array_ptr, 
00084                        index, 
00085                        field_index);
00086       if (field_array_ptr == NULL) {
00087     mexPrintf("\tEmpty Field\n");
00088       } else {
00089          /* Display a top banner. */
00090          mexPrintf("------------------------------------------------\n");
00091          get_characteristics(field_array_ptr);
00092          analyze_class(field_array_ptr);
00093          mexPrintf("\n");
00094       }
00095     }
00096       mexPrintf("\n\n");
00097   }
00098   
00099   
00100 }
00101 
00102 
00103 /* Pass analyze_string a pointer to a char mxArray.  Each element
00104    in a char mxArray holds one 2-byte character (an mxChar); 
00105    analyze_string displays the contents of the input char mxArray
00106    one row at a time.  Since adjoining row elements are NOT stored in 
00107    successive indices, analyze_string has to do a bit of math to
00108    figure out where the next letter in a string is stored. */ 
00109 static void
00110 analyze_string(const mxArray *string_array_ptr)
00111 {
00112   char *buf;
00113   mwSize number_of_dimensions, buflen; 
00114   const mwSize *dims;
00115   mwSize d, page, total_number_of_pages, elements_per_page;
00116   
00117   /* Allocate enough memory to hold the converted string. */ 
00118   buflen = mxGetNumberOfElements(string_array_ptr) + 1;
00119   buf = mxCalloc(buflen, sizeof(char));
00120   
00121   /* Copy the string data from string_array_ptr and place it into buf. */ 
00122   if (mxGetString(string_array_ptr, buf, buflen) != 0)
00123     mexErrMsgTxt("Could not convert string data.");
00124   
00125   /* Get the shape of the input mxArray. */
00126   dims = mxGetDimensions(string_array_ptr);
00127   number_of_dimensions = mxGetNumberOfDimensions(string_array_ptr);
00128   
00129   elements_per_page = dims[0] * dims[1];
00130   /* total_number_of_pages = dims[2] x dims[3] x ... x dims[N-1] */ 
00131   total_number_of_pages = 1;
00132   for (d=2; d<number_of_dimensions; d++) {
00133     total_number_of_pages *= dims[d];
00134   }
00135   
00136   for (page=0; page < total_number_of_pages; page++) {
00137     mwSize row;
00138     /* On each page, walk through each row. */ 
00139     for (row=0; row<dims[0]; row++)  {
00140       mwSize column;     
00141       mwSize index = (page * elements_per_page) + row;
00142       mexPrintf("\t");
00143       display_subscript(string_array_ptr, index);
00144       mexPrintf(" ");
00145       
00146       /* Walk along each column in the current row. */ 
00147       for (column=0; column<dims[1]; column++) {
00148         mexPrintf("%c",buf[index]);
00149         index += dims[0];
00150       }
00151       mexPrintf("\n");
00152 
00153     }
00154     
00155   } 
00156 }
00157 
00158 
00159 /* Pass analyze_sparse a pointer to a sparse mxArray.  A sparse mxArray
00160    only stores its nonzero elements.  The values of the nonzero elements 
00161    are stored in the pr and pi arrays.  The tricky part of analyzing
00162    sparse mxArray's is figuring out the indices where the nonzero
00163    elements are stored.  (See the mxSetIr and mxSetJc reference pages
00164    for details. */  
00165 static void
00166 analyze_sparse(const mxArray *array_ptr)
00167 {
00168   double  *pr, *pi;
00169   mwIndex  *ir, *jc;
00170   mwSize      col, total=0;
00171   mwIndex   starting_row_index, stopping_row_index, current_row_index;
00172   mwSize      n;
00173   
00174   /* Get the starting positions of all four data arrays. */ 
00175   pr = mxGetPr(array_ptr);
00176   pi = mxGetPi(array_ptr);
00177   ir = mxGetIr(array_ptr);
00178   jc = mxGetJc(array_ptr);
00179   
00180   /* Display the nonzero elements of the sparse array. */ 
00181   n = mxGetN(array_ptr);
00182   for (col=0; col<n; col++)  { 
00183     starting_row_index = jc[col]; 
00184     stopping_row_index = jc[col+1]; 
00185     if (starting_row_index == stopping_row_index)
00186       continue;
00187     else {
00188       for (current_row_index = starting_row_index; 
00189        current_row_index < stopping_row_index; 
00190        current_row_index++)  {
00191     if (mxIsComplex(array_ptr))  {
00192       mexPrintf("\t(%"FMT_SIZE_T"u,%"FMT_SIZE_T"u) = %g+%g i\n", 
00193                     ir[current_row_index]+1, 
00194                     col+1, pr[total], pi[total]);
00195       total++;
00196     } else {
00197       mexPrintf("\t(%"FMT_SIZE_T"u,%"FMT_SIZE_T"u) = %g\n", 
00198                     ir[current_row_index]+1, 
00199             col+1, pr[total++]);
00200         }
00201       }
00202     }
00203   }
00204 }
00205 
00206 static void
00207 analyze_int8(const mxArray *array_ptr)
00208 {
00209   signed char   *pr, *pi; 
00210   mwSize total_num_of_elements, index; 
00211   
00212   pr = (signed char *)mxGetData(array_ptr);
00213   pi = (signed char *)mxGetImagData(array_ptr);
00214   total_num_of_elements = mxGetNumberOfElements(array_ptr);
00215   
00216   for (index=0; index<total_num_of_elements; index++)  {
00217     mexPrintf("\t");
00218     display_subscript(array_ptr, index);
00219     if (mxIsComplex(array_ptr)) {
00220       mexPrintf(" = %d + %di\n", *pr++, *pi++); 
00221     } else {
00222       mexPrintf(" = %d\n", *pr++);
00223     }
00224   } 
00225 }
00226 
00227 
00228 static void
00229 analyze_uint8(const mxArray *array_ptr)
00230 {
00231   unsigned char *pr, *pi; 
00232   mwSize total_num_of_elements, index; 
00233   
00234   pr = (unsigned char *)mxGetData(array_ptr);
00235   pi = (unsigned char *)mxGetImagData(array_ptr);
00236   total_num_of_elements = mxGetNumberOfElements(array_ptr);
00237   
00238   for (index=0; index<total_num_of_elements; index++)  {
00239     mexPrintf("\t");
00240     display_subscript(array_ptr, index);
00241     if (mxIsComplex(array_ptr)) {
00242       mexPrintf(" = %u + %ui\n", *pr, *pi++); 
00243     } else {
00244       mexPrintf(" = %u\n", *pr++);
00245     }
00246   } 
00247 }
00248 
00249 
00250 static void
00251 analyze_int16(const mxArray *array_ptr)
00252 {
00253   short int *pr, *pi; 
00254   mwSize total_num_of_elements, index; 
00255   
00256   pr = (short int *)mxGetData(array_ptr);
00257   pi = (short int *)mxGetImagData(array_ptr);
00258   total_num_of_elements = mxGetNumberOfElements(array_ptr);
00259   
00260   for (index=0; index<total_num_of_elements; index++)  {
00261     mexPrintf("\t");
00262     display_subscript(array_ptr, index);
00263     if (mxIsComplex(array_ptr)) {
00264       mexPrintf(" = %d + %di\n", *pr++, *pi++); 
00265     } else {
00266       mexPrintf(" = %d\n", *pr++);
00267     }
00268   } 
00269 }
00270 
00271 
00272 static void
00273 analyze_uint16(const mxArray *array_ptr)
00274 {
00275   unsigned short int *pr, *pi; 
00276   mwSize total_num_of_elements, index; 
00277   
00278   pr = (unsigned short int *)mxGetData(array_ptr);
00279   pi = (unsigned short int *)mxGetImagData(array_ptr);
00280   total_num_of_elements = mxGetNumberOfElements(array_ptr);
00281   
00282   for (index=0; index<total_num_of_elements; index++)  {
00283     mexPrintf("\t");
00284     display_subscript(array_ptr, index);
00285     if (mxIsComplex(array_ptr)) {
00286       mexPrintf(" = %u + %ui\n", *pr++, *pi++); 
00287     } else {
00288       mexPrintf(" = %u\n", *pr++);
00289     }
00290   } 
00291 }
00292 
00293 
00294 
00295 static void
00296 analyze_int32(const mxArray *array_ptr)
00297 {
00298   int *pr, *pi; 
00299   mwSize total_num_of_elements, index; 
00300   
00301   pr = (int *)mxGetData(array_ptr);
00302   pi = (int *)mxGetImagData(array_ptr);
00303   total_num_of_elements = mxGetNumberOfElements(array_ptr);
00304   
00305   for (index=0; index<total_num_of_elements; index++)  {
00306     mexPrintf("\t");
00307     display_subscript(array_ptr, index);
00308     if (mxIsComplex(array_ptr)) {
00309       mexPrintf(" = %d + %di\n", *pr++, *pi++); 
00310     } else {
00311       mexPrintf(" = %d\n", *pr++);
00312     }
00313   } 
00314 }
00315 
00316 
00317 static void
00318 analyze_uint32(const mxArray *array_ptr)
00319 {
00320   unsigned int *pr, *pi; 
00321   mwSize total_num_of_elements, index; 
00322   
00323   pr = (unsigned int *)mxGetData(array_ptr);
00324   pi = (unsigned int *)mxGetImagData(array_ptr);
00325   total_num_of_elements = mxGetNumberOfElements(array_ptr);
00326   
00327   for (index=0; index<total_num_of_elements; index++)  {
00328     mexPrintf("\t");
00329     display_subscript(array_ptr, index);
00330     if (mxIsComplex(array_ptr)) { 
00331       mexPrintf(" = %u + %ui\n", *pr++, *pi++); 
00332     } else {
00333       mexPrintf(" = %u\n", *pr++);
00334     }
00335   } 
00336 }
00337 
00338 static void
00339 analyze_int64(const mxArray *array_ptr)
00340 {
00341   int64_T *pr, *pi; 
00342   mwSize total_num_of_elements, index; 
00343   
00344   pr = (int64_T *)mxGetData(array_ptr);
00345   pi = (int64_T *)mxGetImagData(array_ptr);
00346   total_num_of_elements = mxGetNumberOfElements(array_ptr);
00347   
00348   for (index=0; index<total_num_of_elements; index++)  {
00349     mexPrintf("\t");
00350     display_subscript(array_ptr, index);
00351     if (mxIsComplex(array_ptr)) { 
00352       mexPrintf(" = %" FMT64 "d + %" FMT64 "di\n", *pr++, *pi++); 
00353     } else {
00354       mexPrintf(" = %" FMT64 "d\n", *pr++);
00355     }
00356   } 
00357 }
00358 
00359 
00360 static void
00361 analyze_uint64(const mxArray *array_ptr)
00362 {
00363   uint64_T *pr, *pi; 
00364   mwSize total_num_of_elements, index; 
00365   
00366   pr = (uint64_T *)mxGetData(array_ptr);
00367   pi = (uint64_T *)mxGetImagData(array_ptr);
00368   total_num_of_elements = mxGetNumberOfElements(array_ptr);
00369   
00370   for (index=0; index<total_num_of_elements; index++)  {
00371     mexPrintf("\t");
00372     display_subscript(array_ptr, index);
00373     if (mxIsComplex(array_ptr)) {
00374       mexPrintf(" = %" FMT64 "u + %" FMT64 "ui\n", *pr++, *pi++); 
00375     } else {
00376       mexPrintf(" = %" FMT64 "u\n", *pr++);
00377     }
00378   } 
00379 }
00380 
00381 
00382 static void
00383 analyze_single(const mxArray *array_ptr)
00384 {
00385   float *pr, *pi; 
00386   mwSize total_num_of_elements, index; 
00387   
00388   pr = (float *)mxGetData(array_ptr);
00389   pi = (float *)mxGetImagData(array_ptr);
00390   total_num_of_elements = mxGetNumberOfElements(array_ptr);
00391   
00392   for (index=0; index<total_num_of_elements; index++)  {
00393     mexPrintf("\t");
00394     display_subscript(array_ptr, index);
00395     if (mxIsComplex(array_ptr)){ 
00396       mexPrintf(" = %g + %gi\n", *pr++, *pi++); 
00397     } else {
00398       mexPrintf(" = %g\n", *pr++);
00399     }
00400   } 
00401 }
00402 
00403 
00404 static void
00405 analyze_double(const mxArray *array_ptr)
00406 {
00407   double *pr, *pi; 
00408   mwSize total_num_of_elements, index; 
00409   
00410   pr = mxGetPr(array_ptr);
00411   pi = mxGetPi(array_ptr);
00412   total_num_of_elements = mxGetNumberOfElements(array_ptr);
00413   
00414   for (index=0; index<total_num_of_elements; index++)  {
00415     mexPrintf("\t");
00416     display_subscript(array_ptr, index);
00417     if (mxIsComplex(array_ptr)) { 
00418       mexPrintf(" = %g + %gi\n", *pr++, *pi++); 
00419     } else {
00420       mexPrintf(" = %g\n", *pr++);
00421     }
00422   } 
00423 }
00424 
00425 static void
00426 analyze_logical(const mxArray *array_ptr)
00427 {
00428     mxLogical *pr;
00429     mwSize total_num_of_elements, index;
00430     total_num_of_elements = mxGetNumberOfElements(array_ptr);
00431     pr = (mxLogical *)mxGetData(array_ptr);
00432     for (index=0; index<total_num_of_elements; index++)  {
00433         mexPrintf("\t");
00434         display_subscript(array_ptr, index);
00435         if (*pr++) {
00436             mexPrintf(" = true\n");
00437         } else {
00438             mexPrintf(" = false\n");
00439         }
00440     }
00441 }
00442 
00443 
00444 /* Pass analyze_full a pointer to any kind of numeric mxArray.  
00445    analyze_full figures out what kind of numeric mxArray this is. */ 
00446 static void
00447 analyze_full(const mxArray *numeric_array_ptr)
00448 {
00449   mxClassID   category;
00450   
00451   category = mxGetClassID(numeric_array_ptr);
00452   switch (category)  {
00453      case mxINT8_CLASS:   analyze_int8(numeric_array_ptr);   break; 
00454      case mxUINT8_CLASS:  analyze_uint8(numeric_array_ptr);  break;
00455      case mxINT16_CLASS:  analyze_int16(numeric_array_ptr);  break;
00456      case mxUINT16_CLASS: analyze_uint16(numeric_array_ptr); break;
00457      case mxINT32_CLASS:  analyze_int32(numeric_array_ptr);  break;
00458      case mxUINT32_CLASS: analyze_uint32(numeric_array_ptr); break;
00459      case mxINT64_CLASS:  analyze_int64(numeric_array_ptr);  break;
00460      case mxUINT64_CLASS: analyze_uint64(numeric_array_ptr); break;
00461      case mxSINGLE_CLASS: analyze_single(numeric_array_ptr); break; 
00462      case mxDOUBLE_CLASS: analyze_double(numeric_array_ptr); break;
00463      default: break;
00464   }
00465 }
00466 
00467 
00468 /* Display the subscript associated with the given index. */ 
00469 void
00470 display_subscript(const mxArray *array_ptr, mwSize index)
00471 {
00472   mwSize     inner, subindex, total, d, q, number_of_dimensions; 
00473   mwSize       *subscript;
00474   const mwSize *dims;
00475   
00476   number_of_dimensions = mxGetNumberOfDimensions(array_ptr);
00477   subscript = mxCalloc(number_of_dimensions, sizeof(mwSize));
00478   dims = mxGetDimensions(array_ptr); 
00479   
00480   mexPrintf("(");
00481   subindex = index;
00482   for (d = number_of_dimensions-1; ; d--) { /* loop termination is at the end */
00483     
00484     for (total=1, inner=0; inner<d; inner++)  
00485       total *= dims[inner]; 
00486     
00487     subscript[d] = subindex / total;
00488     subindex = subindex % total;
00489     if (d == 0) {
00490         break;
00491     }
00492   }
00493   
00494   for (q=0; q<number_of_dimensions-1; q++) {
00495     mexPrintf("%d,", subscript[q] + 1);
00496   }
00497   mexPrintf("%d)", subscript[number_of_dimensions-1] + 1);
00498   
00499   mxFree(subscript);
00500 }
00501 
00502 
00503 
00504 /* get_characteristics figures out the size, and category 
00505    of the input array_ptr, and then displays all this information. */ 
00506 void
00507 get_characteristics(const mxArray *array_ptr)
00508 {
00509   const char    *class_name;
00510   const mwSize  *dims;
00511   char          *shape_string;
00512   char          *temp_string;
00513   mwSize        c;
00514   mwSize        number_of_dimensions; 
00515   size_t        length_of_shape_string;
00516 
00517   /* Display the mxArray's Dimensions; for example, 5x7x3.  
00518      If the mxArray's Dimensions are too long to fit, then just
00519      display the number of dimensions; for example, 12-D. */ 
00520   number_of_dimensions = mxGetNumberOfDimensions(array_ptr);
00521   dims = mxGetDimensions(array_ptr);
00522   
00523   /* alloc memory for shape_string w.r.t thrice the number of dimensions */
00524   /* (so that we can also add the 'x')                                   */
00525   shape_string=(char *)mxCalloc(number_of_dimensions*3,sizeof(char));
00526   shape_string[0]='\0';
00527   temp_string=(char *)mxCalloc(64, sizeof(char));
00528 
00529   for (c=0; c<number_of_dimensions; c++) {
00530     sprintf(temp_string, "%"FMT_SIZE_T"dx", dims[c]);
00531     strcat(shape_string, temp_string);
00532   }
00533 
00534   length_of_shape_string = strlen(shape_string);
00535   /* replace the last 'x' with a space */
00536   shape_string[length_of_shape_string-1]='\0';
00537   if (length_of_shape_string > 16) {
00538     sprintf(shape_string, "%"FMT_SIZE_T"u-D", number_of_dimensions); 
00539   }
00540   mexPrintf("Dimensions: %s\n", shape_string);
00541   
00542   /* Display the mxArray's class (category). */
00543   class_name = mxGetClassName(array_ptr);
00544   mexPrintf("Class Name: %s%s\n", class_name,
00545         mxIsSparse(array_ptr) ? " (sparse)" : "");
00546   
00547   /* Display a bottom banner. */
00548   mexPrintf("------------------------------------------------\n");
00549   
00550   /* free up memory for shape_string */
00551   mxFree(shape_string);
00552 }
00553 
00554 
00555 
00556 /* Determine the category (class) of the input array_ptr, and then
00557    branch to the appropriate analysis routine. */
00558 mxClassID
00559 analyze_class(const mxArray *array_ptr)
00560 {
00561     mxClassID  category;
00562     
00563     category = mxGetClassID(array_ptr);
00564     
00565     if (mxIsSparse(array_ptr)) {
00566        analyze_sparse(array_ptr);
00567     } else {
00568        switch (category) {
00569           case mxLOGICAL_CLASS: analyze_logical(array_ptr);    break;
00570           case mxCHAR_CLASS:    analyze_string(array_ptr);     break;
00571           case mxSTRUCT_CLASS:  analyze_structure(array_ptr);  break;
00572           case mxCELL_CLASS:    analyze_cell(array_ptr);       break;
00573           case mxUNKNOWN_CLASS: mexWarnMsgTxt("Unknown class."); break;
00574           default:              analyze_full(array_ptr);       break;
00575        }
00576     }
00577     
00578     return(category);
00579 }
00580 
00581 /* mexFunction is the gateway routine for the MEX-file. */ 
00582 void
00583 mexFunction( int nlhs, mxArray *plhs[],
00584              int nrhs, const mxArray *prhs[] )
00585 {
00586   int        i;
00587   (void) nlhs;     /* unused parameters */
00588   (void) plhs;
00589 
00590 /* Check to see if we are on a platform that does not support the compatibility layer. */
00591 #if defined(_LP64) || defined (_WIN64)
00592 #ifdef MX_COMPAT_32
00593   for (i=0; i<nrhs; i++)  {
00594       if (mxIsSparse(prhs[i])) {
00595           mexErrMsgIdAndTxt("MATLAB:explore:NoSparseCompat",
00596                     "MEX-files compiled on a 64-bit platform that use sparse array functions need to be compiled using -largeArrayDims.");
00597       }
00598   }
00599 #endif
00600 #endif
00601 
00602 
00603  /* Look at each input (right-hand-side) argument. */
00604   for (i=0; i<nrhs; i++)  {
00605     mexPrintf("\n\n");
00606     /* Display a top banner. */
00607     mexPrintf("------------------------------------------------\n");
00608     /* Display which argument */
00609     mexPrintf("Name: %s%d%c\n", "prhs[",i,']');     
00610   
00611     get_characteristics(prhs[i]);
00612     analyze_class(prhs[i]);
00613   }
00614 }
00615 

GridLAB-DTM Version 1.0
An open-source project initiated by the US Department of Energy