1 /*
2 ElmerGrid - A simple mesh generation and manipulation utility
3 Copyright (C) 1995- , CSC - IT Center for Science Ltd.
4
5 Author: Peter Raback
6 Email: elmeradm@csc.fi
7 Address: CSC - IT Center for Science Ltd.
8 Keilaranta 14
9 02101 Espoo, Finland
10
11 This program is free software; you can redistribute it and/or
12 modify it under the terms of the GNU General Public License
13 as published by the Free Software Foundation; either version 2
14 of the License, or (at your option) any later version.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24 */
25
26 #include <stdio.h>
27 #include <stddef.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <math.h>
31 #include <sys/types.h>
32 #include <time.h>
33
34 /* Possible monitoring of memory usage, if supported */
35 #define MEM_USAGE 0
36 #if MEM_USAGE
37 #include <sys/resource.h>
38 #endif
39
40 #include "egutils.h"
41
42 #define FREE_ARG char*
43 #define SHOWMEM 0
44
45 #if SHOWMEM
46 static int nfloat=0, nint=0, cumnfloat=0, cumnint=0, locnint, locnfloat;
47
MemoryUsage()48 int MemoryUsage()
49 {
50 if(locnint > 1000 || locnfloat > 1000)
51 printf("Memory used real %d %d %d int %d %d %d\n",
52 nfloat,cumnfloat,locnfloat,nint,cumnint,locnint);
53 locnfloat = locnint = 0;
54 }
55 #endif
56
57
58 /* The following routines are copied from the book
59 "Numerical Recipes in C, The art of scientific computing"
60 by Cambridge University Press and include the following
61
62 Non-Copyright Notice: This appendix and its utility routines are
63 herewith placed into the public domain. Anyone may copy them freely
64 for any purpose. We of course accept no liability whatsoever for
65 any such use. */
66
67
68
nrerror(const char error_text[])69 void nrerror(const char error_text[])
70 /* standerd error handler */
71 {
72 fprintf(stderr,"run-time error...\n");
73 fprintf(stderr,"%s\n",error_text);
74 fprintf(stderr,"...now exiting to system...\n");
75 exit(1);
76 }
77
78
79 /* Vector initialization */
80
vector(int nl,int nh)81 float *vector(int nl,int nh)
82 /* allocate a float vector with subscript range v[nl..nh] */
83 {
84 float *v;
85
86 v = (float*)malloc((size_t) (nh-nl+1+1)*sizeof(float));
87 if (!v) nrerror("allocation failure in vector()");
88 return(v-nl+1);
89 }
90
91
92
ivector(int nl,int nh)93 int *ivector(int nl,int nh)
94 /* Allocate an int vector with subscript range v[nl..nh] */
95 {
96 int *v;
97
98 if( nh < nl ) {
99 printf("Allocation impossible in ivector: %d %d\n",nl,nh);
100 exit(1);
101 }
102
103 v=(int*) malloc((size_t) (nh-nl+1+1)*sizeof(int));
104 if (!v) nrerror("allocation failure in ivector()");
105
106 #if SHOWMEM
107 locnint = (nh-nl+1+1);
108 nint += locnint;
109 cumnint += locnint;
110 MemoryUsage();
111 #endif
112
113 return(v-nl+1);
114 }
115
116
cvector(int nl,int nh)117 unsigned char *cvector(int nl,int nh)
118 /* allocate an unsigned char vector with subscript range v[nl..nh] */
119 {
120 unsigned char *v;
121
122 v=(unsigned char *)malloc((size_t) (nh-nl+1+1)*sizeof(unsigned char));
123 if (!v) nrerror("allocation failure in cvector()");
124 return(v-nl+1);
125 }
126
127
lvector(int nl,int nh)128 unsigned long *lvector(int nl,int nh)
129 /* allocate an unsigned long vector with subscript range v[nl..nh] */
130 {
131 unsigned long *v;
132
133 v=(unsigned long *)malloc((size_t) (nh-nl+1+1)*sizeof(unsigned long));
134 if (!v) nrerror("allocation failure in lvector()");
135 return(v-nl+1);
136 }
137
138
139
dvector(int nl,int nh)140 double *dvector(int nl,int nh)
141 /* allocate a double vector with subscript range v[nl..nh] */
142 {
143 double *v;
144
145 if( nh < nl ) {
146 printf("Allocation impossible in dvector: %d %d\n",nl,nh);
147 exit(1);
148 }
149
150 v=(double *)malloc((size_t) (nh-nl+1+1)*sizeof(double));
151 if (!v) nrerror("allocation failure in dvector()");
152
153 #if SHOWMEM
154 locnfloat = nh-nl+1+1;
155 nfloat += locnfloat;
156 cumnfloat += locnfloat;
157 MemoryUsage();
158 #endif
159
160 return(v-nl+1);
161 }
162
163
164 /* Matrix initialization */
165
matrix(int nrl,int nrh,int ncl,int nch)166 float **matrix(int nrl,int nrh,int ncl,int nch)
167 /* allocate a float matrix with subscript range m[nrl..nrh][ncl..nch] */
168 {
169 int i, nrow=nrh-nrl+1, ncol=nch-ncl+1;
170 float **m;
171
172 /* allocate pointers to rows */
173 m=(float **) malloc((size_t) (nrow+1)*sizeof(float*));
174 if (!m) nrerror("allocation failure 1 in matrix()");
175 m += 1;
176 m -= nrl;
177
178 /* allocate rows and set pointers to them */
179 m[nrl]=(float *) malloc((size_t)((nrow*ncol+1)*sizeof(float)));
180 if (!m[nrl]) nrerror("allocation failure 2 in matrix()");
181 m[nrl] += 1;
182 m[nrl] -= ncl;
183
184 for(i=nrl+1;i<=nrh;i++)
185 m[i]=m[i-1]+ncol;
186
187 return(m);
188 }
189
190
dmatrix(int nrl,int nrh,int ncl,int nch)191 double **dmatrix(int nrl,int nrh,int ncl,int nch)
192 /* allocate a double matrix with subscript range m[nrl..nrh][ncl..nch] */
193 {
194 int i, nrow=nrh-nrl+1, ncol=nch-ncl+1;
195 double **m;
196
197 if( nrh < nrl || nch < ncl ) {
198 printf("Allocation impossible in dmatrix: %d %d %d %d\n",nrl,nrh,ncl,nch);
199 exit(1);
200 }
201
202
203
204 /* allocate pointers to rows */
205 m=(double **) malloc((size_t) (nrow+1)*sizeof(double*));
206 if (!m) nrerror("allocation failure 1 in dmatrix()");
207 m += 1;
208 m -= nrl;
209
210
211 /* allocate rows and set pointers to them */
212 m[nrl]=(double *) malloc((size_t)((nrow*ncol+1)*sizeof(double)));
213 if (!m[nrl]) nrerror("allocation failure 2 in dmatrix()");
214 m[nrl] += 1;
215 m[nrl] -= ncl;
216
217 for(i=nrl+1;i<=nrh;i++)
218 m[i]=m[i-1]+ncol;
219
220 #if SHOWMEM
221 locnfloat = (nrow+1 + (nrow*ncol+1));
222 nfloat += locnfloat;
223 cumnfloat += locnfloat;
224 MemoryUsage();
225 #endif
226
227 return(m);
228 }
229
230
imatrix(int nrl,int nrh,int ncl,int nch)231 int **imatrix(int nrl,int nrh,int ncl,int nch)
232 /* allocate an int matrix with subscript range m[nrl..nrh][ncl..nch] */
233 {
234 int i, nrow=nrh-nrl+1, ncol=nch-ncl+1;
235 int **m;
236
237 if( nrh < nrl || nch < ncl ) {
238 printf("Allocation impossible in imatrix: %d %d %d %d\n",nrl,nrh,ncl,nch);
239 exit(1);
240 }
241
242 /* allocate pointers to rows */
243 m=(int **) malloc((size_t) (nrow+1)*sizeof(int*));
244 if (!m) nrerror("allocation failure 1 in imatrix()");
245 m += 1;
246 m -= nrl;
247
248 /* allocate rows and set pointers to them */
249 m[nrl]=(int *) malloc((size_t)((nrow*ncol+1)*sizeof(int)));
250 if (!m[nrl]) nrerror("allocation failure 2 in imatrix()");
251 m[nrl] += 1;
252 m[nrl] -= ncl;
253
254 for(i=nrl+1;i<=nrh;i++)
255 m[i]=m[i-1]+ncol;
256
257 #if SHOWMEM
258 locnint = (nrow+1 + (nrow*ncol+1));
259 nint += locnint;
260 cumnint += locnint;
261 MemoryUsage();
262 #endif
263
264 return(m);
265 }
266
267
268
submatrix(float ** a,int oldrl,int oldrh,int oldcl,int oldch,int newrl,int newcl)269 float **submatrix(float **a,int oldrl,int oldrh,int oldcl,int oldch,int newrl,int newcl)
270 /* point a submatrix [newrl..][newcl..] to a[oldrl..oldrh][oldcl..oldch] */
271 {
272 int i,j, nrow=oldrh-oldrl+1, ncol=oldcl-newcl;
273 float **m;
274
275 /* allocate array of pointers to rows */
276 m=(float **) malloc((size_t) ((nrow+1)*sizeof(float*)));
277 if (!m) nrerror("allocation failure in submatrix()");
278 m += 1;
279 m -= newrl;
280
281 /* set pointers to rows */
282 for(i=oldrl,j=newrl;i<=oldrh;i++,j++)
283 m[j]=a[i]+ncol;
284
285 return(m);
286 }
287
288 /* Tensor initialization */
289
f3tensor(int nrl,int nrh,int ncl,int nch,int ndl,int ndh)290 double ***f3tensor(int nrl,int nrh,int ncl,int nch,int ndl,int ndh)
291 /* allocate a double 3tensor with range t[nrl..nrh][ncl..nch][ndl..ndh] */
292 {
293 int i,j,nrow=nrh-nrl+1,ncol=nch-ncl+1,ndep=ndh-ndl+1;
294 double ***t;
295
296 t=(double***) malloc((size_t)((nrow+1)*sizeof(double***)));
297 if (!t) nrerror("allocation failure 1 in f3tensor()");
298 t += 1;
299 t -= nrl;
300
301 t[nrl]=(double**) malloc((size_t)((nrow*ncol+1)*sizeof(double*)));
302 if(!t[nrl]) nrerror("allocation failure 2 in f3tensor()");
303 t[nrl] += 1;
304 t[nrl] -= ncl;
305
306 t[nrl][ncl]=(double*) malloc((size_t)((nrow*ncol*ndep+1)*sizeof(double)));
307 if(!t[nrl][ncl]) nrerror("allocation failure 3 in f3tensor()");
308 t[nrl][ncl] += 1;
309 t[nrl][ncl] -= ndl;
310
311 for(j=ncl+1;j<=nch;j++) t[nrl][j] = t[nrl][j-1]+ndep;
312 for(i=nrl+1;i<=nrh;i++) {
313 t[i] = t[i-1]+ncol;
314 t[i][ncl] = t[i-1][ncl]+ncol*ndep;
315 for(j=ncl+1;j<=nch;j++) t[i][j] = t[i][j-1]+ndep;
316 }
317 return(t);
318 }
319
320
321 /* Deallocation routines */
322
free_vector(float * v,int nl,int nh)323 void free_vector(float *v,int nl,int nh)
324 {
325 free((FREE_ARG) (v+nl-1));
326 }
327
free_ivector(int * v,int nl,int nh)328 void free_ivector(int *v,int nl,int nh)
329 {
330 #if SHOWMEM
331 cumnint -= (nh-nl+1+1);
332 #endif
333
334 free((FREE_ARG) (v+nl-1));
335 }
336
free_cvector(unsigned char * v,int nl,int nh)337 void free_cvector(unsigned char *v,int nl,int nh)
338 {
339 free((FREE_ARG) (v+nl-1));
340 }
341
free_lvector(unsigned long * v,int nl,int nh)342 void free_lvector(unsigned long *v,int nl,int nh)
343 {
344 free((FREE_ARG) (v+nl-1));
345 }
346
347
free_dvector(double * v,int nl,int nh)348 void free_dvector(double *v,int nl,int nh)
349 {
350 #if SHOWMEM
351 cumnfloat -= (nh-nl+1+1);
352 #endif
353
354 free((FREE_ARG) (v+nl-1));
355 }
356
free_matrix(float ** m,int nrl,int nrh,int ncl,int nch)357 void free_matrix(float **m,int nrl,int nrh,int ncl,int nch)
358 {
359 free((FREE_ARG) (m[nrl]+ncl-1));
360 free((FREE_ARG) (m+nrl-1));
361 }
362
free_dmatrix(double ** m,int nrl,int nrh,int ncl,int nch)363 void free_dmatrix(double **m,int nrl,int nrh,int ncl,int nch)
364 {
365 #if SHOWMEM
366 int nrow=nrh-nrl+1;
367 int ncol=nch-ncl+1;
368 cumnfloat -= (nrow+1 + (nrow*ncol+1));
369 #endif
370
371 free((FREE_ARG) (m[nrl]+ncl-1));
372 free((FREE_ARG) (m+nrl-1));
373 }
374
free_imatrix(int ** m,int nrl,int nrh,int ncl,int nch)375 void free_imatrix(int **m,int nrl,int nrh,int ncl,int nch)
376 {
377 #if SHOWMEM
378 int nrow=nrh-nrl+1;
379 int ncol=nch-ncl+1;
380 cumnint -= (nrow+1 + (nrow*ncol+1));
381 #endif
382
383 free((FREE_ARG) (m[nrl]+ncl-1));
384 free((FREE_ARG) (m+nrl-1));
385 }
386
free_submatrix(float ** b,int nrl,int nrh,int ncl,int nch)387 void free_submatrix(float **b,int nrl,int nrh,int ncl,int nch)
388 {
389 free((FREE_ARG) (b+nrl-1));
390 }
391
free_f3tensor(double *** t,int nrl,int nrh,int ncl,int nch,int ndl,int ndh)392 void free_f3tensor(double ***t,int nrl,int nrh,int ncl,int nch,int ndl,int ndh)
393 {
394 free((FREE_ARG) (t[nrl][ncl]+ndl-1));
395 free((FREE_ARG) (t[nrl]+ncl-1));
396 free((FREE_ARG) (t+nrl-1));
397 }
398
399
400 /* -------------------------------: common.c :----------------------------
401 Includes common operations for operating vectors and such. */
402
403
404 static Real timer_t0, timer_dt;
405 static int timer_active = FALSE;
406 static char timer_filename[600];
407
timer_init()408 void timer_init()
409 {
410 timer_active = FALSE;
411 }
412
413
timer_activate(const char * prefix)414 void timer_activate(const char *prefix)
415 {
416 Real time;
417 timer_active = TRUE;
418
419 time = clock() / (double)CLOCKS_PER_SEC;
420
421 AddExtension(prefix,timer_filename,"time");
422
423 printf("Activating timer (s): %.2f\n",time);
424 printf("Saving timer info to file %s\n",timer_filename);
425
426 timer_dt = time;
427 timer_t0 = time;
428 }
429
430
timer_show()431 void timer_show()
432 {
433 static int visited = 0;
434 Real time;
435 FILE *out;
436 #if MEM_USAGE
437 int who,ret;
438 Real memusage;
439 static struct rusage usage;
440 #endif
441
442 if(!timer_active) return;
443
444 time = clock() / (double)CLOCKS_PER_SEC;
445 printf("Elapsed time (s): %.2f %.2f\n",time-timer_t0,time-timer_dt);
446
447 #if MEM_USAGE
448 who = RUSAGE_SELF;
449 ret = getrusage( who, &usage );
450 if( !ret ) {
451 printf("maxrss %ld\n",usage.ru_maxrss);
452 printf("ixrss %ld\n",usage.ru_ixrss);
453 printf("idrss %ld\n",usage.ru_idrss);
454 printf("isrss %ld\n",usage.ru_isrss);
455
456 memusage = (double) 1.0 * usage.ru_maxrss;
457 }
458 else {
459 printf("Failed to obtain resource usage!\n");
460 memusage = 0.0;
461 }
462 #endif
463
464 visited = visited + 1;
465 if( visited == 1 ) {
466 out = fopen(timer_filename,"w");
467 }
468 else {
469 out = fopen(timer_filename,"a");
470 }
471
472 #if MEM_USAGE
473 fprintf(out,"%3d %12.4le %12.4le %12.4le\n",visited,time-timer_t0,time-timer_dt,memusage);
474 #else
475 fprintf(out,"%3d %12.4le %12.4le\n",visited,time-timer_t0,time-timer_dt);
476 #endif
477
478 fclose(out);
479
480 timer_dt = time;
481 }
482
483
484
485
bigerror(const char error_text[])486 void bigerror(const char error_text[])
487 {
488 fprintf(stderr,"The program encountered a major error...\n");
489 fprintf(stderr,"%s\n",error_text);
490 fprintf(stderr,"...now exiting to system...\n");
491 exit(1);
492 }
493
494
smallerror(const char error_text[])495 void smallerror(const char error_text[])
496 {
497 fprintf(stderr,"The program encountered a minor error...\n");
498 fprintf(stderr,"%s\n",error_text);
499 fprintf(stderr,"...we'll try to continue...\n");
500 }
501
502
503
FileExists(char * filename)504 int FileExists(char *filename)
505 {
506 FILE *in;
507
508 if((in = fopen(filename,"r")) == NULL)
509 return(FALSE);
510 else {
511 fclose(in);
512 return(TRUE);
513 }
514 }
515
516
Minimum(Real * vector,int first,int last)517 Real Minimum(Real *vector,int first,int last)
518 /* Returns the smallest value of vector in range [first,last]. */
519 {
520 Real min;
521 int i;
522
523 min=vector[first];
524 for(i=first+1;i<=last;i++)
525 if(min>vector[i]) min=vector[i];
526
527 return(min);
528 }
529
530
Minimi(Real * vector,int first,int last)531 int Minimi(Real *vector,int first,int last)
532 /* Returns the position of the smallest value of vector in range [first,last]. */
533 {
534 Real min;
535 int i,mini;
536
537 mini=first;
538 min=vector[first];
539 for(i=first+1;i<=last;i++)
540 if(min>vector[i])
541 min=vector[(mini=i)];
542
543 return(mini);
544 }
545
546
Maximum(Real * vector,int first,int last)547 Real Maximum(Real *vector,int first,int last)
548 /* Returns the largest value of vector in range [first,last]. */
549 {
550 Real max;
551 int i;
552
553 max=vector[first];
554 for(i=first+1;i<=last;i++)
555 if(max<vector[i]) max=vector[i];
556
557 return(max);
558 }
559
560
Maximi(Real * vector,int first,int last)561 int Maximi(Real *vector,int first,int last)
562 /* Returns the position of the largest value of vector in range [first,last]. */
563 {
564 Real max;
565 int i,maxi;
566
567 maxi=-1;
568 max=vector[first];
569 for(i=first+1;i<=last;i++)
570 if(max<vector[i])
571 max=vector[(maxi=i)];
572
573 return(maxi);
574 }
575
576
577
AddExtension(const char * fname1,char * fname2,const char * newext)578 void AddExtension(const char *fname1,char *fname2,const char *newext)
579 /* Changes the extension of a filename.
580 'fname1' - the original filename
581 'fname2' - the new filename
582 'newext' - the new extension
583 If there is originally no extension it's appended. In this case
584 there has to be room for the extension.
585 */
586 {
587 char *ptr1,*ptr2;
588
589 strcpy(fname2,fname1);
590 ptr1 = strrchr(fname2, '.');
591
592 if (ptr1) {
593 int badpoint=FALSE;
594 ptr2 = strrchr(fname2, '/');
595 if(ptr2 && ptr2 > ptr1) badpoint = TRUE;
596 if(!badpoint) *ptr1 = '\0';
597 }
598 strcat(fname2, ".");
599 strcat(fname2,newext);
600 }
601
602
StringToStrings(const char * buf,char args[10][15],int maxcnt,char separator)603 int StringToStrings(const char *buf,char args[10][15],int maxcnt,char separator)
604 /* Finds real numbers separated by a certain separator from a string.
605 'buf' - input string ending to a EOF
606 'dest' - a vector of real numbers
607 'maxcnt' - maximum number of real numbers to be read
608 'separator' - the separator of real numbers
609 The number of numbers found is returned in the function value.
610 */
611 {
612 int i,cnt,totlen,finish;
613 char *ptr1 = (char *)buf, *ptr2;
614
615
616 totlen = strlen(buf);
617 finish = 0;
618 cnt = 0;
619
620 if (!buf[0]) return 0;
621
622 do {
623 ptr2 = strchr(ptr1,separator);
624 if(ptr2) {
625 for(i=0;i<15;i++) {
626 args[cnt][i] = ptr1[i];
627 if(ptr1 + i >= ptr2) break;
628 }
629 args[cnt][i] = '\0';
630 ptr1 = ptr2+1;
631 }
632 else {
633 for(i=0;i<15;i++) {
634 if(ptr1 + i >= buf+totlen) break;
635 args[cnt][i] = ptr1[i];
636 }
637 args[cnt][i] = '\0';
638 finish = 1;
639 }
640
641 cnt++;
642 } while (cnt < maxcnt && !finish);
643
644 return cnt;
645 }
646
647
StringToReal(const char * buf,Real * dest,int maxcnt,char separator)648 int StringToReal(const char *buf,Real *dest,int maxcnt,char separator)
649 /* Finds real numbers separated by a certain separator from a string.
650 'buf' - input string ending to a EOF
651 'dest' - a vector of real numbers
652 'maxcnt' - maximum number of real numbers to be read
653 'separator' - the separator of real numbers
654 The number of numbers found is returned in the function value.
655 */
656 {
657 int cnt = 0;
658 char *ptr1 = (char *)buf, *ptr2;
659
660 if (!buf[0]) return 0;
661 do {
662 ptr2 = strchr(ptr1,separator);
663 if (ptr2) ptr2[0] = '\0';
664 dest[cnt++] = atof(ptr1);
665 if (ptr2) ptr1 = ptr2+1;
666 } while (cnt < maxcnt && ptr2 != NULL);
667
668 return cnt;
669 }
670
671
StringToInteger(const char * buf,int * dest,int maxcnt,char separator)672 int StringToInteger(const char *buf,int *dest,int maxcnt,char separator)
673 {
674 int cnt = 0;
675 char *ptr1 = (char *)buf, *ptr2;
676 int ival;
677
678 if (!buf[0]) return 0;
679 do {
680
681 ptr2 = strchr(ptr1,separator);
682 if (ptr2) ptr2[0] = '\0';
683 ival = atoi(ptr1);
684
685 dest[cnt++] = ival;
686
687 if (ptr2) ptr1 = ptr2+1;
688 } while (cnt < maxcnt && ptr2 != NULL);
689
690 return cnt;
691 }
692
StringToIntegerNoZero(const char * buf,int * dest,int maxcnt,char separator)693 int StringToIntegerNoZero(const char *buf,int *dest,int maxcnt,char separator)
694 {
695 int cnt = 0;
696 char *ptr1 = (char *)buf, *ptr2;
697 int ival;
698
699 if (!buf[0]) return 0;
700 do {
701
702 ptr2 = strchr(ptr1,separator);
703 if (ptr2) ptr2[0] = '\0';
704 ival = atoi(ptr1);
705
706 if(ival == 0) break;
707
708 dest[cnt++] = ival;
709
710 if (ptr2) ptr1 = ptr2+1;
711 } while (cnt < maxcnt && ptr2 != NULL);
712
713 return cnt;
714 }
715
716
next_int(char ** start)717 int next_int(char **start)
718 {
719 int i;
720 char *end;
721
722 i = strtol(*start,&end,10);
723 *start = end;
724 return(i);
725 }
726
next_int_n(char ** start,int n)727 int next_int_n(char **start, int n)
728 {
729 int i;
730 char *end = *start+n;
731 char saved = *end;
732
733 *end = '\0';
734 i = strtol(*start,NULL,10);
735 *end = saved;
736 *start = end;
737 return(i);
738 }
739
next_real(char ** start)740 Real next_real(char **start)
741 {
742 Real r;
743 char *end;
744
745 r = strtod(*start,&end);
746
747 *start = end;
748 return(r);
749 }
750
751
752 /*
753 * sort: sort an (double) array to ascending order, and move the elements of
754 * another (integer) array accordingly. the latter can be used as track
755 * keeper of where an element in the sorted order at position (k) was in
756 * in the original order (Ord[k]), if it is initialized to contain
757 * numbers (0..N-1) before calling sort.
758 *
759 * Parameters:
760 *
761 * N: int / number of entries in the arrays.
762 * Key: double[N] / array to be sorted.
763 * Ord: int[N] / change this accordingly.
764 */
SortIndex(int N,double * Key,int * Ord)765 void SortIndex( int N, double *Key, int *Ord )
766 {
767 double CurrentKey;
768
769 int CurrentOrd;
770
771 int CurLastPos;
772 int CurHalfPos;
773
774 int i;
775 int j;
776
777 /* Initialize order */
778 for(i=1;i<=N;i++)
779 Ord[i] = i;
780
781 CurHalfPos = N / 2 + 1;
782 CurLastPos = N;
783 while( 1 ) {
784 if ( CurHalfPos > 1 ) {
785 CurHalfPos--;
786 CurrentKey = Key[CurHalfPos];
787 CurrentOrd = Ord[CurHalfPos];
788 } else {
789 CurrentKey = Key[CurLastPos];
790 CurrentOrd = Ord[CurLastPos];
791 Key[CurLastPos] = Key[1];
792 Ord[CurLastPos] = Ord[1];
793 CurLastPos--;
794 if ( CurLastPos == 1 ) {
795 Key[1] = CurrentKey;
796 Ord[1] = CurrentOrd;
797 return;
798 }
799 }
800 i = CurHalfPos;
801 j = 2 * CurHalfPos;
802 while( j <= CurLastPos ) {
803 if ( j < CurLastPos && Key[j] < Key[j + 1] ) {
804 j++;
805 }
806 if ( CurrentKey < Key[j] ) {
807 Key[i] = Key[j];
808 Ord[i] = Ord[j];
809 i = j;
810 j += i;
811 } else {
812 j = CurLastPos + 1;
813 }
814 }
815 Key[i] = CurrentKey;
816 Ord[i] = CurrentOrd;
817 }
818
819 }
820
821
822
823