1 /* util.c */
2
3 #include "../IV.h"
4
5 /*--------------------------------------------------------------------*/
6 /*
7 -----------------------------------------------------------
8 shift the base of the entries and adjust the dimensions
9 note: this is a dangerous operation because the iv->vec
10 does not point to the base of the entries any longer,
11 and thus if the object owns its entries and it is called
12 to resize them or to free them, malloc and free will choke.
13
14 USE WITH CAUTION!
15
16 created -- 96aug25, cca
17 modified -- 96aug28, cca
18 structure changed
19 -----------------------------------------------------------
20 */
21 void
IV_shiftBase(IV * iv,int offset)22 IV_shiftBase (
23 IV *iv,
24 int offset
25 ) {
26 if ( iv == NULL ) {
27 fprintf(stderr, "\n fatal error in IV_shiftBase(%p,%d)"
28 "\n bad input\n", iv, offset) ;
29 exit(-1) ;
30 }
31 iv->vec += offset ;
32 iv->size -= offset ;
33 iv->maxsize -= offset ;
34
35 return ; }
36
37 /*--------------------------------------------------------------------*/
38 /*
39 -----------------------------
40 push an entry onto the list
41
42 created -- 95oct06, cca
43 modified -- 95aug28, cca
44 structure has changed
45 modified -- 96dec08, cca
46 maxsize added to structure
47 -----------------------------
48 */
49 void
IV_push(IV * iv,int val)50 IV_push (
51 IV *iv,
52 int val
53 ) {
54 if ( iv == NULL ) {
55 fprintf(stderr, "\n fatal error in IV_push(%p,%d)"
56 "\n bad input\n", iv, val) ;
57 exit(-1) ;
58 }
59 /*
60 fprintf(stdout, "\n %% iv %p, size %d, maxsize %d, entries %p",
61 iv, iv->size, iv->maxsize, iv->vec) ;
62 fflush(stdout) ;
63 */
64 if ( iv->size == iv->maxsize ) {
65 if ( iv->maxsize == 0 ) {
66 IV_setMaxsize(iv, 10) ;
67 } else {
68 IV_setMaxsize(iv, 2*iv->maxsize) ;
69 }
70 }
71 iv->vec[iv->size++] = val ;
72
73 return ; }
74
75 /*--------------------------------------------------------------------*/
76 /*
77 ---------------------------
78 minimum and maximum entries
79
80 created -- 95oct06, cca
81 ---------------------------
82 */
83 int
IV_min(IV * iv)84 IV_min (
85 IV *iv
86 ) {
87 int i ;
88
89 if ( iv == NULL || iv->size <= 0 || iv->vec == NULL ) {
90 fprintf(stderr, "\n fatal error in IV_min(%p), size = %d, vec = %p",
91 iv, iv->size, iv->vec) ;
92 exit(-1) ;
93 }
94 return(IVmin(iv->size, iv->vec, &i)) ; }
95
96 int
IV_max(IV * iv)97 IV_max (
98 IV *iv
99 ) {
100 int i ;
101
102 if ( iv == NULL || iv->size <= 0 || iv->vec == NULL ) {
103 fprintf(stderr, "\n fatal error in IV_max(%p), size = %d, vec = %p",
104 iv, iv->size, iv->vec) ;
105 exit(-1) ;
106 }
107 return(IVmax(iv->size, iv->vec, &i)) ; }
108
109 int
IV_sum(IV * iv)110 IV_sum (
111 IV *iv
112 ) {
113 int i ;
114
115 if ( iv == NULL || iv->size <= 0 || iv->vec == NULL ) {
116 fprintf(stderr, "\n fatal error in IV_sum(%p), size = %d, vec = %p",
117 iv, iv->size, iv->vec) ;
118 exit(-1) ;
119 }
120 return(IVsum(iv->size, iv->vec)) ; }
121
122 /*--------------------------------------------------------------------*/
123 /*
124 -------------------------------------------------------
125 sort each index list into ascending or descending order
126
127 created -- 95oct06, cca
128 -------------------------------------------------------
129 */
130 void
IV_sortUp(IV * iv)131 IV_sortUp (
132 IV *iv
133 ) {
134 if ( iv == NULL || iv->size <= 0 || iv->vec == NULL ) {
135 fprintf(stderr,
136 "\n fatal error in IV_sortUp(%p), size = %d, vec = %p",
137 iv, iv->size, iv->vec) ;
138 exit(-1) ;
139 }
140 IVqsortUp(iv->size, iv->vec) ;
141
142 return ; }
143
144 void
IV_sortDown(IV * iv)145 IV_sortDown (
146 IV *iv
147 ) {
148 if ( iv == NULL || iv->size <= 0 || iv->vec == NULL ) {
149 fprintf(stderr,
150 "\n fatal error in IV_sortDown(%p), size = %d, vec = %p",
151 iv, iv->size, iv->vec) ;
152 exit(-1) ;
153 }
154 IVqsortDown(iv->size, iv->vec) ;
155
156 return ; }
157
158 /*--------------------------------------------------------------------*/
159 /*
160 -----------------------
161 ramp the entries
162
163 created -- 95oct06, cca
164 -----------------------
165 */
166 void
IV_ramp(IV * iv,int base,int incr)167 IV_ramp (
168 IV *iv,
169 int base,
170 int incr
171 ) {
172 if ( iv == NULL || iv->size <= 0 || iv->vec == NULL ) {
173 fprintf(stderr,
174 "\n fatal error in IV_ramp(%p,%d,%d), size = %d, vec = %p",
175 iv, base, incr, iv->size, iv->vec) ;
176 exit(-1) ;
177 }
178 IVramp(iv->size, iv->vec, base, incr) ;
179
180 return ; }
181
182 /*--------------------------------------------------------------------*/
183 /*
184 -----------------------
185 shuffle the list
186
187 created -- 95oct06, cca
188 -----------------------
189 */
190 void
IV_shuffle(IV * iv,int seed)191 IV_shuffle (
192 IV *iv,
193 int seed
194 ) {
195 if ( iv == NULL || iv->size <= 0 || iv->vec == NULL ) {
196 fprintf(stderr,
197 "\n fatal error in IV_shuffle(%p,%d), size = %d, vec = %p",
198 iv, seed, iv->size, iv->vec) ;
199 exit(-1) ;
200 }
201 IVshuffle(iv->size, iv->vec, seed) ;
202
203 return ; }
204
205 /*--------------------------------------------------------------------*/
206 /*
207 ----------------------------------------------
208 return the number of bytes taken by the object
209
210 created -- 95oct06, cca
211 ----------------------------------------------
212 */
213 int
IV_sizeOf(IV * iv)214 IV_sizeOf (
215 IV *iv
216 ) {
217 int nbytes ;
218
219 if ( iv == NULL ) {
220 fprintf(stderr, "\n fatal error in IV_sizeOf(%p)"
221 "\n bad input \n", iv) ;
222 exit(-1) ;
223 }
224 nbytes = sizeof(struct _IV) ;
225 if ( iv->owned == 1 ) {
226 nbytes += iv->maxsize * sizeof(int) ;
227 }
228 return(nbytes) ; }
229
230 /*--------------------------------------------------------------------*/
231 /*
232 ----------------------------------------------------------------
233 keep entries that are tagged, move others to end and adjust size
234
235 created -- 95oct06, cca
236 ----------------------------------------------------------------
237 */
238 void
IV_filterKeep(IV * iv,int tags[],int keepTag)239 IV_filterKeep (
240 IV *iv,
241 int tags[],
242 int keepTag
243 ) {
244 int i, j, w, size ;
245 int *vec ;
246 /*
247 ---------------
248 check the input
249 ---------------
250 */
251 if ( iv == NULL || tags == NULL ) {
252 fprintf(stderr, "\n fatal error in IV_filterKeep(%p,%p,%d)"
253 "\n bad input", iv, tags, keepTag) ;
254 exit(-1) ;
255 }
256 size = iv->size ;
257 vec = iv->vec ;
258 /*
259 --------------------------------------------
260 move untagged entries to the end of the list
261 --------------------------------------------
262 */
263 for ( i = 0, j = size ; i < j ; ) {
264 w = vec[i] ;
265 if ( tags[w] != keepTag ) {
266 vec[i] = vec[j-1] ;
267 vec[j-1] = w ;
268 j-- ;
269 } else {
270 i++ ;
271 }
272 }
273 /*
274 -------------------
275 reset the list size
276 -------------------
277 */
278 iv->size = j ;
279
280 return ; }
281
282 /*--------------------------------------------------------------------*/
283 /*
284 ---------------------------------------------------------
285 move purge entries that are tagged to end and adjust size
286
287 created -- 95oct06, cca
288 ---------------------------------------------------------
289 */
290 void
IV_filterPurge(IV * iv,int tags[],int purgeTag)291 IV_filterPurge (
292 IV *iv,
293 int tags[],
294 int purgeTag
295 ) {
296 int i, j, size, w ;
297 int *vec ;
298 /*
299 ---------------
300 check the input
301 ---------------
302 */
303 if ( iv == NULL || tags == NULL ) {
304 fprintf(stderr, "\n fatal error in IV_filterPurge(%p,%p,%d)"
305 "\n bad input", iv, tags, purgeTag) ;
306 exit(-1) ;
307 }
308 size = iv->size ;
309 vec = iv->vec ;
310 /*
311 --------------------------------------------
312 move untagged entries to the end of the list
313 --------------------------------------------
314 */
315 for ( i = 0, j = size ; i < j ; ) {
316 w = vec[i] ;
317 if ( tags[w] == purgeTag ) {
318 vec[i] = vec[j-1] ;
319 vec[j-1] = w ;
320 j-- ;
321 } else {
322 i++ ;
323 }
324 }
325 /*
326 -------------------
327 reset the list size
328 -------------------
329 */
330 iv->size = j ;
331
332 return ; }
333
334 /*--------------------------------------------------------------------*/
335 /*
336 --------------------------------------------
337 iterator :
338 return the pointer to the head of the vector
339
340 created -- 95oct06, cca
341 --------------------------------------------
342 */
343 int *
IV_first(IV * iv)344 IV_first (
345 IV *iv
346 ) {
347 int *pi ;
348 /*
349 ---------------
350 check the input
351 ---------------
352 */
353 if ( iv == NULL ) {
354 fprintf(stderr, "\n fatal error in IV_first(%p)"
355 "\n bad input", iv) ;
356 exit(-1) ;
357 }
358 if ( iv->size == 0 ) {
359 pi = NULL ;
360 } else {
361 pi = iv->vec ;
362 }
363 return(pi) ; }
364
365 /*--------------------------------------------------------------------*/
366 /*
367 -----------------------------------------------------
368 iterator :
369 return the pointer to the next location in the vector
370
371 created -- 95oct06, cca
372 -----------------------------------------------------
373 */
374 int *
IV_next(IV * iv,int * pi)375 IV_next (
376 IV *iv,
377 int *pi
378 ) {
379 int offset ;
380 /*
381 ---------------
382 check the input
383 ---------------
384 */
385 if ( iv == NULL || pi == NULL ) {
386 fprintf(stderr, "\n fatal error in IV_next(%p,%p)"
387 "\n bad input", iv, pi) ;
388 fflush(stderr) ;
389 exit(-1) ;
390 }
391 /*
392 ---------------
393 check the input
394 ---------------
395 */
396 if ( (offset = pi - iv->vec) < 0 || offset >= iv->size ) {
397 /*
398 -----------------------------
399 error, offset is out of range
400 -----------------------------
401 */
402 fprintf(stderr, "\n fatal error in IV_next(%p,%p)"
403 "\n offset = %d, must be in [0,%d)",
404 iv, pi, offset, iv->size) ;
405 fflush(stderr) ;
406 exit(-1) ;
407 } else if ( offset == iv->size - 1 ) {
408 /*
409 ----------------------------
410 end of the list, return NULL
411 ----------------------------
412 */
413 pi = NULL ;
414 } else {
415 /*
416 ----------------------------------------
417 middle of the list, return next location
418 ----------------------------------------
419 */
420 pi++ ;
421 }
422 return(pi) ; }
423
424 /*--------------------------------------------------------------------*/
425 /*
426 --------------------------
427 fill a vector with a value
428
429 created -- 96jun22, cca
430 --------------------------
431 */
432 void
IV_fill(IV * iv,int value)433 IV_fill (
434 IV *iv,
435 int value
436 ) {
437 /*
438 ---------------
439 check the input
440 ---------------
441 */
442 if ( iv == NULL ) {
443 fprintf(stderr, "\n fatal error in IV_fill(%p,%d)"
444 "\n bad input\n", iv, value) ;
445 exit(-1) ;
446 }
447 if ( iv->size > 0 ) {
448 IVfill(iv->size, iv->vec, value) ;
449 }
450
451 return ; }
452
453 /*--------------------------------------------------------------------*/
454 /*
455 --------------------------------------
456 copy entries from iv2 into iv1.
457 note: this is a "mapped" copy,
458 iv1 and iv2 need not be the same size.
459
460 created -- 96aug31, cca
461 --------------------------------------
462 */
463 void
IV_copy(IV * iv1,IV * iv2)464 IV_copy (
465 IV *iv1,
466 IV *iv2
467 ) {
468 int ii, size ;
469 int *vec1, *vec2 ;
470 /*
471 ---------------
472 check the input
473 ---------------
474 */
475 if ( iv1 == NULL || iv2 == NULL ) {
476 fprintf(stderr, "\n fatal error in IV_copy(%p,%p)"
477 "\n bad input\n", iv1, iv2) ;
478 exit(-1) ;
479 }
480 size = iv1->size ;
481 if ( size > iv2->size ) {
482 size = iv2->size ;
483 }
484 vec1 = iv1->vec ;
485 vec2 = iv2->vec ;
486 for ( ii = 0 ; ii < size ; ii++ ) {
487 vec1[ii] = vec2[ii] ;
488 }
489 return ; }
490
491 /*--------------------------------------------------------------------*/
492 /*
493 --------------------------------------------------
494 increment the loc'th location of the vector by one
495 and return the new value
496
497 created -- 96dec18, cca
498 --------------------------------------------------
499 */
500 int
IV_increment(IV * iv,int loc)501 IV_increment (
502 IV *iv,
503 int loc
504 ) {
505 /*
506 ---------------
507 check the input
508 ---------------
509 */
510 if ( iv == NULL || loc < 0 || loc >= iv->size ) {
511 fprintf(stderr, "\n fatal error in IV_increment(%p,%d)"
512 "\n bad input\n", iv, loc) ;
513 if ( iv != NULL ) {
514 fprintf(stderr, "\n loc = %d, size = %d", loc, iv->size) ;
515 }
516 exit(-1) ;
517 }
518 return(++iv->vec[loc]) ; }
519
520 /*--------------------------------------------------------------------*/
521 /*
522 --------------------------------------------------
523 decrement the loc'th location of the vector by one
524 and return the new value
525
526 created -- 96dec18, cca
527 --------------------------------------------------
528 */
529 int
IV_decrement(IV * iv,int loc)530 IV_decrement (
531 IV *iv,
532 int loc
533 ) {
534 /*
535 ---------------
536 check the input
537 ---------------
538 */
539 if ( iv == NULL || loc < 0 || loc >= iv->size ) {
540 fprintf(stderr, "\n fatal error in IV_decrement(%p,%d)"
541 "\n bad input\n", iv, loc) ;
542 if ( iv != NULL ) {
543 fprintf(stderr, "\n loc = %d, size = %d", loc, iv->size) ;
544 }
545 exit(-1) ;
546 }
547 return(--iv->vec[loc]) ; }
548
549 /*--------------------------------------------------------------------*/
550 /*
551 ------------------------------------------------------------
552 return the first location in the vector that contains value.
553 if value is not present, -1 is returned. cost is linear in
554 the size of the vector
555
556 created -- 96jan15, cca
557 ------------------------------------------------------------
558 */
559 int
IV_findValue(IV * iv,int value)560 IV_findValue (
561 IV *iv,
562 int value
563 ) {
564 int ii, n ;
565 int *vec ;
566 /*
567 ---------------
568 check the input
569 ---------------
570 */
571 if ( iv == NULL ) {
572 fprintf(stderr, "\n fatal error in IV_findValue(%p,%d)"
573 "\n bad input\n", iv, value) ;
574 exit(-1) ;
575 }
576 if ( (n = iv->size) <= 0 || (vec = iv->vec) == NULL ) {
577 return(-1) ;
578 }
579 for ( ii = 0 ; ii < n ; ii++ ) {
580 if ( vec[ii] == value ) {
581 return(ii) ;
582 }
583 }
584 return(-1) ; }
585
586 /*--------------------------------------------------------------------*/
587 /*
588 ---------------------------------------------------------------
589 return a location in the vector that contains value.
590 the entries in the vector are assumed to be in ascending order.
591 if value is not present, -1 is returned. cost is logarithmic in
592 the size of the vector
593
594 created -- 96jan15, cca
595 ---------------------------------------------------------------
596 */
597 int
IV_findValueAscending(IV * iv,int value)598 IV_findValueAscending (
599 IV *iv,
600 int value
601 ) {
602 int left, mid, n, right ;
603 int *vec ;
604 /*
605 ---------------
606 check the input
607 ---------------
608 */
609 if ( iv == NULL ) {
610 fprintf(stderr, "\n fatal error in IV_findValueAscending(%p,%d)"
611 "\n bad input\n", iv, value) ;
612 exit(-1) ;
613 }
614 if ( (n = iv->size) <= 0 || (vec = iv->vec) == NULL ) {
615 return(-1) ;
616 }
617 left = 0 ;
618 right = n - 1 ;
619 if ( vec[left] == value ) {
620 return(left) ;
621 } else if ( vec[right] == value ) {
622 return(right) ;
623 } else {
624 while ( left < right - 1 ) {
625 mid = (left + right)/2 ;
626 if ( vec[mid] == value ) {
627 return(mid) ;
628 } else if ( vec[mid] < value ) {
629 left = mid ;
630 } else {
631 right = mid ;
632 }
633 }
634 }
635 return(-1) ; }
636
637 /*--------------------------------------------------------------------*/
638 /*
639 ----------------------------------------------------------------
640 return a location in the vector that contains value.
641 the entries in the vector are assumed to be in descending order.
642 if value is not present, -1 is returned. cost is logarithmic in
643 the size of the vector
644
645 created -- 96jan15, cca
646 ----------------------------------------------------------------
647 */
648 int
IV_findValueDescending(IV * iv,int value)649 IV_findValueDescending (
650 IV *iv,
651 int value
652 ) {
653 int left, mid, n, right ;
654 int *vec ;
655 /*
656 ---------------
657 check the input
658 ---------------
659 */
660 if ( iv == NULL ) {
661 fprintf(stderr, "\n fatal error in IV_findValueDescending(%p,%d)"
662 "\n bad input\n", iv, value) ;
663 exit(-1) ;
664 }
665 if ( (n = iv->size) <= 0 || (vec = iv->vec) == NULL ) {
666 return(-1) ;
667 }
668 left = 0 ;
669 right = n - 1 ;
670 if ( vec[left] == value ) {
671 return(left) ;
672 } else if ( vec[right] == value ) {
673 return(right) ;
674 } else {
675 while ( left < right - 1 ) {
676 mid = (left + right)/2 ;
677 if ( vec[mid] == value ) {
678 return(mid) ;
679 } else if ( vec[mid] > value ) {
680 left = mid ;
681 } else {
682 right = mid ;
683 }
684 }
685 }
686 return(-1) ; }
687
688 /*--------------------------------------------------------------------*/
689 /*
690 ----------------------------------------------------
691 purpose -- return invlistIV, an IV object
692 that contains the inverse map,
693 i.e., invlist[list[ii]] = ii.
694 other entries of invlist[] are -1.
695 all entries in listIV must be nonnegative
696
697 created -- 98aug12, cca
698 ----------------------------------------------------
699 */
700 IV *
IV_inverseMap(IV * listIV)701 IV_inverseMap (
702 IV *listIV
703 ) {
704 int ii, maxval, n ;
705 int *invlist, *list ;
706 IV *invlistIV ;
707 /*
708 ---------------
709 check the input
710 ---------------
711 */
712 if ( listIV == NULL ) {
713 fprintf(stderr, "\n fatal error in IV_inverseMap()"
714 "\n bad input\n") ;
715 exit(-1) ;
716 }
717 IV_sizeAndEntries(listIV, &n, &list) ;
718 if ( n <= 0 && list == NULL ) {
719 fprintf(stderr, "\n fatal error in IV_inverseMap()"
720 "\n size = %d, list = %p\n", n, list) ;
721 exit(-1) ;
722 }
723 for ( ii = 0, maxval = -1 ; ii < n ; ii++ ) {
724 if ( list[ii] < 0 ) {
725 fprintf(stderr, "\n fatal error in IV_inverseMap()"
726 "\n list[%d] = %d, must be positive\n", ii, list[ii]) ;
727 exit(-1) ;
728 }
729 if ( maxval < list[ii] ) {
730 maxval = list[ii] ;
731 }
732 }
733 invlistIV = IV_new() ;
734 IV_init(invlistIV, 1 + maxval, NULL) ;
735 IV_fill(invlistIV, -1) ;
736 invlist = IV_entries(invlistIV) ;
737 for ( ii = 0 ; ii < n ; ii++ ) {
738 if ( invlist[list[ii]] != -1 ) {
739 fprintf(stderr, "\n fatal error in IV_inverseMap()"
740 "\n repeated list value %d\n", list[ii]) ;
741 exit(-1) ;
742 }
743 invlist[list[ii]] = ii ;
744 }
745 return(invlistIV) ; }
746
747 /*--------------------------------------------------------------------*/
748 /*
749 -----------------------------------------------------------
750 purpose -- return an IV object that contains the locations
751 of all instances of target in listIV. this is
752 used when listIV is a map from [0,n) to a finite
753 set (like processors) and we want to find all
754 entries that are mapped to a specific processor.
755
756 created -- 98aug12, cca
757 -----------------------------------------------------------
758 */
759 IV *
IV_targetEntries(IV * listIV,int target)760 IV_targetEntries (
761 IV *listIV,
762 int target
763 ) {
764 int count, ii, n ;
765 int *entries, *list ;
766 IV *entriesIV ;
767 /*
768 ---------------
769 check the input
770 ---------------
771 */
772 if ( listIV == NULL ) {
773 fprintf(stderr, "\n fatal error in IV_targetEntries()"
774 "\n bad input\n") ;
775 exit(-1) ;
776 }
777 IV_sizeAndEntries(listIV, &n, &list) ;
778 if ( n <= 0 && list == NULL ) {
779 fprintf(stderr, "\n fatal error in IV_targetEntries()"
780 "\n size = %d, list = %p\n", n, list) ;
781 exit(-1) ;
782 }
783 for ( ii = count = 0 ; ii < n ; ii++ ) {
784 if ( list[ii] == target ) {
785 count++ ;
786 }
787 }
788 entriesIV = IV_new() ;
789 if ( count > 0 ) {
790 IV_init(entriesIV, count, NULL) ;
791 entries = IV_entries(entriesIV) ;
792 for ( ii = count = 0 ; ii < n ; ii++ ) {
793 if ( list[ii] == target ) {
794 entries[count++] = ii ;
795 }
796 }
797 }
798 return(entriesIV) ; }
799
800 /*--------------------------------------------------------------------*/
801