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