1 /*****************************************************************************
2 Major portions of this software are copyrighted by the Medical College
3 of Wisconsin, 1994-2000, and are released under the Gnu General Public
4 License, Version 2. See the file README.Copyright for details.
5 ******************************************************************************/
6
7 #include "afni.h"
8 #include "afni_plugin.h"
9
10 #ifndef ALLOW_PLUGINS
11 # error "Plugins not properly set up -- see machdep.h"
12 #endif
13
14 /***********************************************************************
15 Plugin to extract 3D brick data
16 ************************************************************************/
17 typedef struct
18 {
19 int nxx; /* number of voxels in the x direction */
20 int nyy; /* number of voxels in the y direction */
21 int nzz; /* number of voxels in the z direction */
22 char *dsetname; /* prefix of data set analyzed */
23 int errcode; /* error code number returned from function */
24 int out; /* flag for writing to a file */
25 int format;
26 int iloc;
27 int xloc;
28 int yloc;
29 int zloc;
30 int fimonly; /* set to 1 if no threshold is available */
31 int DoInt;
32 int DoThres;
33 int DoInd;
34 int intind;
35 int thrind;
36 int Nsub;
37 int isanat;
38 int isfunc;
39 float mini, maxi, minth, maxth;
40 char * strout;
41 FILE * outfile;
42 FILE * outlogfile;
43 char outname[PLUGIN_MAX_STRING_RANGE]; /* output data file name */
44 }extract_data;
45
46
47 static char helpstring[] =
48 " 3Ddump98 Plugin\n"
49 "This plugin is used to write to an ascii file the data present in AFNI bricks.\n"
50 "You can apply intenstity or threshold masks to the voxel data that is being extracted.\n\n"
51 "Plugin Inputs:\n\n"
52 " 1- Dataset :\n"
53 " 3D brick -> 3D AFNI brick of the type :\n"
54 " fim, fith, fico, fbuc, etc...\n"
55 " spgr, epan.\n\n"
56 " 2- SubBrick info : (Optional) \n"
57 " Intensity -> Index of the subbrick to be used\n"
58 " as an intensity subbrick.\n"
59 " Threshold -> Index of the subbrick to be used \n"
60 " as a threshold subbrick.\n"
61 " While the subbrick indices are obvious when dealing with most bricks\n"
62 " You might need to specified them for bricks of the type bucket\n\n"
63 " 3- Intensity Mask : (optional) \n"
64 " Minimum -> Minimum boundary for intensity value (inclusive)\n"
65 " Maximum -> Maximum boundary for intensity value (inclusive)\n"
66 " Data from voxels with intensity between Minimum and Maximum \n"
67 " are written to 'Filename'.\n\n"
68 " 4- Threshold Mask : (optional) \n"
69 " Minimum -> Minimum boundary for threshold value (inclusive)\n"
70 " Maximum -> Maximum boundary for threshold value (inclusive)\n"
71 " Data from voxels with threshold value between Minimum and Maximum \n"
72 " are written to 'Filename'.\n\n"
73 " 5- Output : \n"
74 " Filename -> Name of ascii output file. \n"
75 " If no name is specified, the default is\n"
76 " the prefix of the inbut brick with the \n"
77 " extension '.3Ddump' appended at the end.\n"
78 " A LOG file, 'Filename.log' is also written to disk.\n"
79 " The log file contains all the parameters settings used\n"
80 " for generating 'Filename'.\n"
81 " The format of 'Filename' is as follows :\n"
82 " 1- Voxel Index (VI) : Each voxel in an AFNI brick has a unique index.\n"
83 " Indices map directly to XYZ coordinates.\n"
84 " See AFNI plugin documentations for more info.\n"
85 " 2..4- Voxel coordinates (X Y Z) : Those are the voxel slice coordinates.\n"
86 " You can see these coordinates in the upper left side\n"
87 " of the AFNI window. To do so, you must first switch the\n"
88 " voxel coordinate units from mm to slice coordinates.\n"
89 " Define Datamode -> Misc -> Voxel Coords ?\n"
90 " PS: The coords that show up in the graph window\n"
91 " could be different from those in the upper left side \n"
92 " of AFNI's main window.\n"
93 " 5..n- Subbrick values (Sb1 Sb2 ... Sbn) : Voxel values at each subbrick.\n\n"
94 "If you have/find questions/comments/bugs about the plugin, \n"
95 "send me an E-mail: ziad@image.bien.mu.edu\n\n"
96 " Ziad Saad Nov. 9 97, latest update Aug. 26 99.\n\n"
97 ;
98
99 /* Significant update Aug. 26 99 */
100 /* The indexing into Storear has been swapped (columns became rows and rows columns.
101 That's because each subbrick was not stored in a vector on N elements, rather in N vectors
102 of 1 element each. That made the allocation process very slow, especially now that Bob has
103 malloc and calloc going through his own macros. */
104
105 /*-------- strings for output format and some definitions -----------*/
106
107 static char * yn_strings[] = { "n" , "y" };
108
109 #define NUM_YN_STRINGS (sizeof(yn_strings)/sizeof(char *))
110
111 #define YUP 1
112 #define NOPE 0
113
114 #define ERROR_FILEWRITE 2
115 #define ERROR_OPTIONS 3
116
117 /*---------- prototypes for internal routines ----------*/
118 static int filexists (char *);
119
120 static char * DUMP_main( PLUGIN_interface * ) ;
121
122 static int Dumpit( extract_data* , THD_3dim_dataset * ) ;
123
124 static void write_ud (extract_data*);
125
126 static char **allocate2D (int rows,int cols,int element_size);
127
128 static void free2D(char **a,int rows);
129
130 static int equal_strings (char *s1,char *s2);
131
132
133 /***********************************************************************
134 Set up the interface to the user
135 ************************************************************************/
136
137 DEFINE_PLUGIN_PROTOTYPE
138
PLUGIN_init(int ncall)139 PLUGIN_interface * PLUGIN_init( int ncall )
140 {
141 PLUGIN_interface * plint ;
142
143 CHECK_IF_ALLOWED("3DDUMP98","3D Dump98") ; /* 30 Sep 2016 */
144
145 if( ncall > 0 ) return NULL ; /* only one interface */
146
147 /*-- set titles and call point --*/
148
149 plint = PLUTO_new_interface( "3D Dump98" , "Ascii dump of 3D Dataset" , helpstring ,
150 PLUGIN_CALL_VIA_MENU , DUMP_main ) ;
151
152 PLUTO_set_runlabels( plint , "Dump+Keep" , "Dump+Close" ) ; /* 04 Nov 2003 */
153
154 /*-- first line of input: Dataset --*/
155
156 PLUTO_add_option( plint , "Dataset" , "Dataset" , TRUE ) ;
157 PLUTO_add_dataset(plint , "3D brick" ,
158 ANAT_ALL_MASK , FUNC_ALL_MASK ,
159 SESSION_ALL_MASK |
160 DIMEN_ALL_MASK | BRICK_ALLREAL_MASK ) ;
161
162 /*-- second line of input: intensity and threshold brick indices --*/
163
164
165 PLUTO_add_option( plint ,
166 "SubBrik info" , /* label at left of input line */
167 "Index" , /* tag to return to plugin */
168 FALSE /* is this mandatory? */
169 ) ;
170 PLUTO_add_number( plint ,
171 "Intensity" , /* label next to chooser */
172 1 , /* smallest possible value */
173 10000 , /* largest possible value (inactivated for now)*/
174 0 , /* decimal shift (none in this case) */
175 0 , /* default value */
176 FALSE /* allow user to edit value? */
177 ) ;
178
179 PLUTO_add_number( plint ,
180 "Threshold" , /* label next to chooser */
181 1 , /* smallest possible value */
182 10000 , /* largest possible value (inactivated for now)*/
183 0 , /* decimal shift (none in this case) */
184 2 , /* default value */
185 FALSE /* allow user to edit value? */
186 ) ;
187 /*-- Third line of input: intensity mask --*/
188
189 PLUTO_add_option( plint ,
190 "Intensity Mask" , /* label at left of input line */
191 "Intensity" , /* tag to return to plugin */
192 FALSE /* is this mandatory? */
193 ) ;
194
195 PLUTO_add_number( plint ,
196 "Minimum" , /* label next to chooser */
197 -100000 , /* smallest possible value */
198 100000 , /* largest possible value (inactivated for now)*/
199 0 , /* decimal shift (none in this case) */
200 0 , /* default value */
201 TRUE /* allow user to edit value? */
202 ) ;
203
204 PLUTO_add_number( plint ,
205 "Maximum" , /* label next to chooser */
206 -10000 , /* smallest possible value */
207 10000 , /* largest possible value (inactivated for now)*/
208 0 , /* decimal shift (none in this case) */
209 0 , /* default value */
210 TRUE /* allow user to edit value? */
211 ) ;
212
213 /*-- Fourth line of input: threshold mask --*/
214
215 PLUTO_add_option( plint ,
216 "Threshold Mask" , /* label at left of input line */
217 "Threshold" , /* tag to return to plugin */
218 FALSE /* is this mandatory? */
219 ) ;
220
221 PLUTO_add_number( plint ,
222 "Minimum" , /* label next to chooser */
223 -10000 , /* smallest possible value */
224 10000 , /* largest possible value (inactivated for now)*/
225 0 , /* decimal shift (none in this case) */
226 0 , /* default value */
227 TRUE /* allow user to edit value? */
228 ) ;
229
230 PLUTO_add_number( plint ,
231 "Maximum" , /* label next to chooser */
232 -10000 , /* smallest possible value */
233 10000 , /* largest possible value (inactivated for now)*/
234 0 , /* decimal shift (none in this case) */
235 1 , /* default value */
236 TRUE /* allow user to edit value? */
237 ) ;
238
239 /*---------- 5th line: output stuff ----------*/
240
241 PLUTO_add_option( plint ,
242 "Output" , /* label at left of input line */
243 "Output" , /* tag to return to plugin */
244 TRUE /* is this mandatory? */
245 ) ;
246
247 PLUTO_add_string( plint ,
248 "Filename" , /* label next to textfield */
249 0,NULL , /* no fixed strings to choose among */
250 19 /* 19 spaces for typing in value */
251 ) ;
252
253 return plint ;
254 }
255
256 /***************************************************************************
257 Main routine for this plugin (will be called from AFNI).
258 ****************************************************************************/
259
DUMP_main(PLUGIN_interface * plint)260 static char * DUMP_main( PLUGIN_interface * plint )
261 {
262 extract_data uda,*ud;
263 MCW_idcode * idc ;
264 THD_3dim_dataset * xset , * yset ;
265 char * tag ;
266 int demean ,ndmp,nprf;
267 char *str, *nprfxstr, *mssg;
268 float minx , maxx , minthr , maxthr ;
269
270 str = (char *) calloc (PLUGIN_MAX_STRING_RANGE+10,sizeof(char));
271 nprfxstr = (char *) calloc (PLUGIN_MAX_STRING_RANGE+20,sizeof(char));
272 /* Do not allocate more space for mssg, because AFNI would choke on it*/
273 mssg = (char *) calloc (PLUGIN_MAX_STRING_RANGE,sizeof(char));
274 memset(&uda, 0, sizeof(extract_data));
275 if (str == NULL || nprfxstr == NULL || mssg == NULL )
276 return "********************\n"
277 "Could not Allocate\n"
278 "a teeni weeni bit of\n"
279 "Memory ! \n"
280 "********************\n";
281
282 ud = &uda; /* ud now points to an allocated space */
283
284 /*--------------------------------------------------------------------*/
285 /*----- Check inputs from AFNI to see if they are reasonable-ish -----*/
286 tag = PLUTO_get_optiontag(plint) ;
287
288 if (tag == NULL)
289 {
290 return "************************\n"
291 "Bad 1st line option \n"
292 "************************" ;
293 }
294
295
296 idc = PLUTO_get_idcode(plint) ; /* get 1st dataset item */
297 xset = PLUTO_find_dset(idc) ; /* get ptr to dataset */
298 if( xset == NULL )
299 return "**********************\n"
300 "Cannot find Dataset #1\n"
301 "**********************" ;
302
303 ud->dsetname = DSET_FILECODE (xset);
304 ud->Nsub = DSET_NVALS (xset);
305
306 /*--------- loop over ramining options ---------*/
307 ud->DoInt = NOPE;
308 ud->DoThres = NOPE;
309 ud->DoInd = NOPE;
310
311 ud->intind = 1; /* The first subbrick is numbered 1 here, it makes more sense to the user.*/
312 ud->thrind = 2;
313
314 do
315 {
316 tag = PLUTO_get_optiontag(plint) ;
317 if (tag == NULL) break;
318
319 if (equal_strings (tag, "Index") == 1)
320 {
321 ud->DoInd = YUP;
322 ud->intind = PLUTO_get_number(plint) ;
323 ud->thrind = PLUTO_get_number(plint) ;
324 continue;
325 }
326
327 if (equal_strings (tag, "Intensity") == 1)
328 {
329 ud->DoInt = YUP;
330 ud->mini = PLUTO_get_number(plint) ;
331 ud->maxi = PLUTO_get_number(plint) ;
332 continue;
333 }
334
335 if (equal_strings (tag, "Threshold") == 1)
336 {
337 ud->DoThres = YUP;
338 ud->minth = PLUTO_get_number(plint) ;
339 ud->maxth = PLUTO_get_number(plint) ;
340 continue;
341 }
342
343 if (equal_strings (tag, "Output") == 1)
344 {
345 ud->strout = PLUTO_get_string(plint) ;
346 continue;
347 }
348
349
350 } while (1);
351
352 if ( ISFUNC(xset) ) ud->isfunc = YUP;
353 else ud->isfunc = NOPE;
354
355 if ( ISANAT(xset) ) ud->isanat = YUP;
356 else ud->isanat = NOPE;
357
358 if (xset->func_type == FUNC_FIM_TYPE)
359 ud->fimonly = 1;
360 else
361 ud->fimonly = 0;
362
363 if (ud->isanat && (ud->DoThres== YUP || ud->DoInd == YUP))
364 {
365 return "*************************************\n"
366 "Can't use threshold or index options \n"
367 "for fim or ANAT type bricks !\n"
368 "*************************************" ;
369 }
370
371
372 if (ud->DoInd == YUP && (ud->fimonly == YUP && ud->isfunc == YUP))
373 {
374 return "*******************************\n"
375 "Can't specify Indices for fim\n"
376 "type bricks, they only have one !\n"
377 "*******************************" ;
378 }
379
380
381 /* Check for plausibility of input parameters */
382 if ((ud->DoInt && (ud->maxi < ud->mini)) || (ud->DoThres && (ud->maxth < ud->minth)))
383 {
384 return "**********************\n"
385 "Something's wrong with\n"
386 "min and max values.\n"
387 "**********************" ;
388 }
389 if (ud->DoInd && (ud->intind > ud->Nsub || ud->thrind > ud->Nsub))
390 {
391
392 return "**********************\n"
393 "One or both of the indices\n"
394 "is larger than the maximum\n"
395 "number of sub-bricks\n"
396 "**********************" ;
397 }
398
399 /*------------------------------------------------------*/
400 /*----- Open the output file for writing operation -----*/
401
402 /*if strout is null or of length 0, use the a default name */
403 if (ud->strout == NULL)
404 nprf = 0;
405 else
406 nprf = 1;
407
408
409 if (nprf == 1 && (int)strlen(ud->strout) == 0)
410 nprf = 0;
411
412
413 if (nprf == 0)
414 {
415 sprintf (nprfxstr,"%s.3Ddump",DSET_PREFIX(xset));
416 ud->strout = nprfxstr;
417 }
418
419
420 sprintf (str,"%s.log",ud->strout);
421
422 if ((filexists(ud->strout) == 1) || (filexists(str) == 1))
423 {
424 return "**************************************\n"
425 "Output file(s) exists, can't overwrite\n"
426 "**************************************\n";
427 }
428
429 ud->outfile = fopen (ud->strout,"w");
430 ud->outlogfile = fopen (str,"w");
431
432 if ((ud->outfile == NULL) || (ud->outlogfile == NULL))
433 {
434 return "*****************************************\n"
435 "Could not open Output file(s) for writing\n"
436 "Check permissions.\n"
437 "*****************************************\n";
438 }
439
440 /*------------------------------------------------------*/
441 /*---------- At this point, the inputs are OK ----------*/
442
443 /*-- do the actual work --*/
444 ndmp = Dumpit( ud , xset ) ;
445
446 if( ndmp < -1.0 )
447 {
448 switch (ndmp)
449 {
450 case -2:
451 return "********************************************\n"
452 "Fatal Error: Could not allocate memory\n"
453 "(this is a message brought to you by Dumpit)\n"
454 "********************************************\n" ;
455 break;
456 default:
457 return "*********************************\n"
458 "Error while dumping data\n"
459 "*********************************" ;
460
461 break;
462
463 }
464 }
465
466 /*-- put the output to the screen --*/
467
468 /* That output message was too long. AFNI was crashing, must ask Bob to allow more verbose messages */
469
470 /*sprintf(mssg , " Dataset %s was dumped.\n"
471 "%d voxels (%5f %% of total) met the boundary conditions.\n"
472 , DSET_FILECODE(xset) , ndmp , (float)ndmp/(float)(ud->nxx * ud->nyy * ud-> nzz)*100.0) ;*/
473
474 /* That's shorter */
475 sprintf(mssg , "%d voxels (%5f %% of total) were dumped.\n"
476 , ndmp , (float)ndmp/(float)(ud->nxx * ud->nyy * ud-> nzz)*100.0) ;
477
478 PLUTO_popup_message( plint , mssg ) ;
479
480
481
482 fclose (ud->outfile);
483 fclose (ud->outlogfile);
484 free (nprfxstr);
485 free (str);
486 free (mssg);
487
488 return NULL ; /* null string returned means all was OK */
489 }
490
491
Dumpit(extract_data * ud,THD_3dim_dataset * xset)492 static int Dumpit( extract_data* ud, THD_3dim_dataset * xset)
493 {
494 void * xar ;
495 void * thar ;
496 float * fxar ;
497 float ** Storear;
498 int ii , jj, nxyz , fxar_new = 0 ,xpos,ypos,zpos , ndmp, pass;
499
500 ndmp = -1;
501
502 /*-- get datasets sizes --*/
503
504 ud->nxx = xset->daxes->nxx;
505 ud->nyy = xset->daxes->nyy;
506 ud->nzz = xset->daxes->nzz;
507
508 nxyz = xset->daxes->nxx * xset->daxes->nyy * xset->daxes->nzz ;
509
510 /* Allocate space for data storage */
511 fxar = (float *) malloc( sizeof(float) * nxyz ) ; fxar_new = 1 ;
512 Storear = (float **) allocate2D (ud->Nsub ,nxyz ,sizeof(float)); /* changed from : allocate2D (nxyz ,ud->Nsub,sizeof(float)) */
513
514 if (fxar == NULL || Storear == NULL)
515 {
516 return -2;
517 }
518
519 /*-- load the first dataset into memory --*/
520
521 DSET_load( xset ) ;
522
523 /* Store Bricks in 2D array */
524 for (ii = 0;ii < ud->Nsub; ++ii)
525 {
526 xar = DSET_ARRAY(xset,ii) ; /* get the array */
527 EDIT_coerce_scale_type (nxyz,DSET_BRICK_FACTOR(xset,ii),
528 DSET_BRICK_TYPE(xset,ii), xar, MRI_float,fxar ) ;
529
530 /* Store the iith sub-brick in Storear array */
531 for (jj = 0; jj < nxyz; ++jj)
532 Storear[ii][jj] = fxar[jj]; /* changed from : Storear[jj][ii] */
533 }
534
535 DSET_unload( xset ) ; /* don't need this in memory anymore */
536
537 /* Dump the input info data to the log file */
538 write_ud (ud);
539
540
541 /* Now dump the data that meets the threshold */
542
543 if( 1 ){
544 for( ii=0 ; ii < nxyz ; ii++ ){
545 pass = YUP;
546 if (pass && ud->DoInt)
547 {
548 if (Storear[ud->intind-1][ii] < ud->mini || Storear[ud->intind-1][ii] > ud->maxi) /* changed both from : Storear[ii][ud->intind-1]*/
549 pass = NOPE;
550 }
551
552 if (pass && ud->DoThres)
553 {
554 if (Storear[ud->thrind-1][ii] < ud->minth || Storear[ud->thrind-1][ii] > ud->maxth)/* changed both from : Storear[ii][ud->intind-1]*/
555 pass = NOPE;
556 }
557
558 if (pass)
559 {
560 zpos = (int)ii / (int)(xset->daxes->nxx * xset->daxes->nyy);
561 ypos = (int)(ii - zpos * xset->daxes->nxx * xset->daxes->nyy) / xset->daxes->nxx;
562 xpos = ii - ( ypos * xset->daxes->nxx ) - ( zpos * xset->daxes->nxx * xset->daxes->nyy ) ;
563
564 fprintf (ud->outfile,"%d\t%d\t%d\t%d\t",ii,xpos,ypos,zpos);
565
566 for (jj = 0; jj < ud->Nsub; ++jj)
567 fprintf (ud->outfile," %f\t",Storear[jj][ii]); /* changed from: Storear[ii][jj] */
568
569 fprintf (ud->outfile,"\n");
570
571 ++ndmp;
572 }
573 }
574
575 /* increment by one because I want it to start at 0 */
576 ++ndmp;
577 }
578
579
580 fprintf (ud->outlogfile,"\n%d voxel points met the threshold conditions\n",ndmp);
581
582 /*-- free up arrays --*/
583
584
585 if( fxar_new )
586 {
587 free(fxar) ;
588 }
589 else
590 {
591 DSET_unload(xset) ;
592 }
593
594
595 free2D ((char **)Storear,ud->Nsub); /* changed from free2D ((char **)Storear,nxyz); */
596
597
598 return ndmp ;
599 }
600
601
602 /* ************************************************************ */
603 /* function to check for file existence */
604 /* ************************************************************ */
605
filexists(char * f_name)606 static int filexists (char *f_name)
607 {/*filexists*/
608 FILE *outfile;
609
610 outfile = fopen (f_name,"r");
611 if (outfile == NULL)
612 return (0);
613 else
614 fclose (outfile);
615 return (1);
616
617 }/*filexists*/
618
619 /* ************************************************************ */
620 /* function to create log file */
621 /* ************************************************************ */
622
write_ud(extract_data * ud)623 void write_ud (extract_data* ud)
624 {
625 fprintf (ud->outlogfile,"\n\nUser Data Values \n");
626 fprintf (ud->outlogfile,"Input data set file name= %s\n",ud->dsetname);
627 fprintf (ud->outlogfile,"Is the file fim only type ? = %d\n",ud->fimonly);
628 fprintf (ud->outlogfile,"Number of Subbricks : %d\n",ud->Nsub);
629 fprintf (ud->outlogfile,"output file name = %s\n",ud->strout);
630 fprintf (ud->outlogfile,"Number of voxels in X direction = %d\n",ud->nxx);
631 fprintf (ud->outlogfile,"Number of voxels in Y direction = %d\n",ud->nyy);
632 fprintf (ud->outlogfile,"Number of voxels in Z direction = %d\n",ud->nzz);
633 fprintf (ud->outlogfile,"Do intensity mask ? = %d\n",ud->DoInt);
634 fprintf (ud->outlogfile,"Minimum intensity = %f\n",ud->mini);
635 fprintf (ud->outlogfile,"Maximum intensity = %f\n",ud->maxi);
636 fprintf (ud->outlogfile,"Do threshold mask ? = %d\n",ud->DoThres);
637 fprintf (ud->outlogfile,"Minimum threshold = %f\n",ud->minth);
638 fprintf (ud->outlogfile,"Maximum threshold = %f\n",ud->maxth);
639 fprintf (ud->outlogfile,"Select Intensity and Threshold indices = %d\n",ud->DoInd);
640 fprintf (ud->outlogfile,"Intensity index = %d\n",ud->intind);
641 fprintf (ud->outlogfile,"Threshold index = %d\n",ud->thrind);
642 fprintf (ud->outlogfile,"\nThe format for the output file is the following:\n");
643 fprintf (ud->outlogfile,"VI\tX\tY\tZ\tSb1\tSb2\t... Sbn\n\n");
644
645
646 return;
647 }
648
649 /* ************************************************************ */
650 /* function to allocate 2D arrays */
651 /* ************************************************************ */
652
allocate2D(int rows,int cols,int element_size)653 static char **allocate2D (int rows,int cols,int element_size)
654
655 {
656 int i, j;
657 char **A;
658
659 /* try to allocate the request */
660 switch(element_size) {
661 case sizeof(short): { /* integer matrix */
662 short **int_matrix;
663 int_matrix = (short **)calloc(rows,sizeof(short *));
664 if(!int_matrix) {
665 printf("\nError making pointers in %dx%d int matrix\n"
666 ,rows,cols);
667 return(NULL);
668 /* exit(1);*/
669 }
670 for(i = 0 ; i < rows ; i++) {
671 int_matrix[i] = (short *)calloc(cols,sizeof(short));
672 if(!int_matrix[i]) {
673 printf("\nError making row %d in %dx%d int matrix\n"
674 ,i,rows,cols);
675 for(j=0;j<=i;j++) {
676 if(int_matrix[j])
677 free(int_matrix[j]);
678 }
679 free(int_matrix);
680 return(NULL);
681 /* exit(1);*/
682 }
683 }
684 A = (char **)int_matrix;
685 break;
686 }
687 case sizeof(float): { /* float matrix */
688 float **float_matrix;
689 float_matrix = (float **)calloc(rows,sizeof(float *));
690 if(!float_matrix) {
691 printf("\nError making pointers in %dx%d float matrix\n"
692 ,rows,cols);
693 return(NULL);
694 /* exit(1);*/
695 }
696 for(i = 0 ; i < rows ; i++) {
697 float_matrix[i] = (float *)calloc(cols,sizeof(float));
698 if(!float_matrix[i]) {
699 printf("\nError making row %d in %dx%d float matrix\n"
700 ,i,rows,cols);
701 for(j=0;j<=i;j++) {
702 if(float_matrix[j])
703 free(float_matrix[j]);
704 }
705 free(float_matrix);
706 return(NULL);
707 /* exit(1);*/
708 }
709 }
710 A = (char **)float_matrix;
711 break;
712 }
713 case sizeof(double): { /* double matrix */
714 double **double_matrix;
715 double_matrix = (double **)calloc(rows,sizeof(double *));
716 if(!double_matrix) {
717 printf("\nError making pointers in %dx%d double matrix\n"
718 ,rows,cols);
719 return(NULL);
720 /* exit(1);*/
721 }
722 for(i = 0 ; i < rows ; i++) {
723 double_matrix[i] = (double *)calloc(cols,sizeof(double));
724 if(!double_matrix[i]) {
725 printf("\nError making row %d in %dx%d double matrix\n"
726 ,i,rows,cols);
727 for(j=0;j<=i;j++) {
728 if(double_matrix[j])
729 free(double_matrix[j]);
730 }
731 free(double_matrix);
732 return(NULL);
733
734 /* exit(1);*/
735 }
736 }
737 A = (char **)double_matrix;
738 break;
739 }
740 default:
741 printf("\nERROR in matrix_allocate: unsupported type\n");
742 return(NULL);
743 /* exit(1);*/
744 }
745 return(A);
746 }
747
748 /* ************************************************************ */
749 /* function to free 2D arrays */
750 /* ************************************************************ */
free2D(char ** a,int rows)751 static void free2D(char **a,int rows)
752
753 {
754 int i;
755
756 /* free each row of data */
757 for(i = 0 ; i < rows ; i++) free(a[i]);
758
759 /* free each row pointer */
760 free((char *)a);
761 a = NULL; /* set to null for error */
762
763 return;
764 }
765
766 /* ************************************************************ */
767 /* function to Check if strings are equal */
768 /* ************************************************************ */
769
770
equal_strings(char * s1,char * s2)771 int equal_strings (char *s1,char *s2)
772
773 {
774 int i=0;
775
776 if (s1 == NULL && s2 == NULL) return (-2);
777
778 if ((s1 == NULL && s2 != NULL) || (s1 != NULL && s2 == NULL)) return (-1);
779
780 while (s1[i] == s2[i]
781 && s1[i] != '\0' && s2[i] != '\0') ++i;
782
783 if (s1[i] == '\0' && s2[i] == '\0') return (1);
784 else return (0);
785
786 }
787