1/* BEGIN LICENSE BLOCK
2 * Version: CMPL 1.1
3 *
4 * The contents of this file are subject to the Cisco-style Mozilla Public
5 * License Version 1.1 (the "License"); you may not use this file except
6 * in compliance with the License.  You may obtain a copy of the License
7 * at www.eclipse-clp.org/license.
8 *
9 * Software distributed under the License is distributed on an "AS IS"
10 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See
11 * the License for the specific language governing rights and limitations
12 * under the License.
13 *
14 * The Original Code is  The ECLiPSe Constraint Logic Programming System.
15 * The Initial Developer of the Original Code is  Cisco Systems, Inc.
16 * Portions created by the Initial Developer are
17 * Copyright (C) 2001-2006 Cisco Systems, Inc.  All Rights Reserved.
18 *
19 * Contributor(s): Warwick Harvey, IC-Parc.
20 *
21 * END LICENSE BLOCK */
22
23/*--------------------------------------------------------------------
24**
25** Low-level C functions for implementing bitmaps.
26**
27** System:       ECLiPSe Constraint Logic Programming System
28** Author/s:     Warwick Harvey, IC-Parc
29**
30** This file provides low-level primitives for manipulating bitmaps (e.g.
31** for use in representing finite domains in IC).
32**
33**--------------------------------------------------------------------
34**
35** TODO:
36**
37** - For completeness, there should be a few more functions:
38**   + create(+Offs, +IntBitmap, -Map)
39**   + remove_range(?Map, +From, +To, -Change)
40**   + subtract_from(?Map1, +Map2, -Change)
41**
42**-------------------------------------------------------------------*/
43
44/*----------------------------------------------------------------------
45**
46** Load some needed header files.
47**
48*/
49
50#include <string.h>		/* for memcpy() */
51
52#include "external.h"
53#include "bitmap.h"
54
55/*
56** Sketch of bitmap data structure to represent finite domains.
57**
58**	bm(
59**		offset,		% offset to apply to values before
60**				% converting to an index position.
61**				% Note: must be multiple of word size.
62**		low,		% lowest word containing non-zero bits
63**		high,		% highest word containing non-zero bits
64**		bits[0],
65**		...
66**		bits[low],
67**		...
68**		bits[high],
69**		...
70**	)
71**
72**	bits[0] .. bits[low-1] contain zeroes
73**	bits[high+1] .. bits[(original high)] contain zeroes
74**	bits[low] contains at least one set bit
75**	bits[high] contains at least one set bit
76**
77** Actually, we get a bit lazy, and don't necessarily blank out all words
78** outisde the domain on updates.
79**
80** In this module, `low' and `high' in variable names are generally used to
81** refer to word index positions within the bitmap structure, while `min'
82** and `max' are used to refer to the values being represented.
83**
84** *** Note:
85**	Offsets are done relative to original values rather than index
86**	positions in order to avoid most (unfortunately not all) problems
87**	with division of negative numbers.  *Sigh*  This way, after
88**	adjusting by the offset, everything within the domain is
89**	non-negative and works fine.
90*/
91
92/*----------------------------------------------------------------------
93**
94** Define some useful constants and macros.
95**
96*/
97
98    /* Bits per word. */
99#define BPW		(8 * (int) sizeof(word))
100
101    /* Word with all bits set. */
102#define ALLBITS		MAX_U_WORD
103
104    /* Word with just low bit set. */
105#define LOWBIT		((word) 1)
106
107    /* Word with just high bit set. */
108#define HIGHBIT		(((word) 1) << (BPW - 1))
109
110    /* Word with all bits set from bit n up. */
111#define BitsFrom(n)	(ALLBITS << (n))
112
113    /* Word with all bits set up to bit n. */
114#define BitsTo(n)	((uword) ALLBITS >> (BPW-1-(n)))
115
116    /* Word with just bit n set. */
117#define Bit(n)		(LOWBIT << (n))
118
119
120    /*
121    ** Offsets into bitmap data structures.
122    */
123
124#define OFF_OFFSET	2
125#define OFF_LOW		3
126#define OFF_HIGH	4
127#define OFF_BITS	5
128
129#define HEADER_BYTES	(3 * sizeof(word))
130
131    /*
132    ** Bitmap access convenience macros.
133    */
134
135#define Offset(bitmap)		((bitmap)[OFF_OFFSET])
136#define Low(bitmap)		((bitmap)[OFF_LOW])
137#define High(bitmap)		((bitmap)[OFF_HIGH])
138#define Bits(bitmap)		((bitmap) + OFF_BITS)
139
140    /*
141    ** Find the value of the minimum (maximum) element in the bitmap, given
142    ** the low (high) word.
143    */
144#define bitmap_low_to_min(bitmap, low) \
145	    ((low) * BPW + lsb(*(Bits(bitmap) + (low))))
146#define bitmap_high_to_max(bitmap, high) \
147	    ((high) * BPW + msb(*(Bits(bitmap) + (high))))
148
149
150/*
151** Some fake macros to make bitmaps look a bit like their own types -
152** cf. sepia.h.
153**
154** Some public ones are in bitmap.h
155*/
156
157    /* Push a bitmap with the specified number of data words onto the heap. */
158#define Push_Bitmap(pstruct, words)	{			\
159	    pstruct = (uword *) TG;				\
160	    Push_Buffer(HEADER_BYTES + words * sizeof(word))	\
161	}
162
163    /* Copy the given bitmap, keeping only the data words from low to high. */
164#define Copy_Bitmap(bitmap, low, high, new_bitmap)	{	\
165	    int words = (high) - (low) + 1;			\
166								\
167	    Push_Bitmap(new_bitmap, words);			\
168	    Offset(new_bitmap) = Offset(bitmap) + (low) * BPW;	\
169	    Low(new_bitmap) = 0;				\
170	    High(new_bitmap) = words - 1;			\
171	    memcpy(Bits(new_bitmap), Bits(bitmap) + (low),	\
172			    sizeof(word) * words);		\
173	}
174
175    /*
176    ** Copy the given bitmap, but only if it needs to be trailed (i.e.
177    ** hasn't already been copied in this choice point).  Set `needed' based
178    ** on whether the copy was done or not.
179    */
180#define Copy_Bitmap_If_Needed(bitmap, low, high, new_bitmap, needed)	\
181	if (Trail_Needed(bitmap)) {					\
182	    Copy_Bitmap(bitmap, low, high, new_bitmap);			\
183	    needed = 1;							\
184	} else {							\
185	    new_bitmap = bitmap;					\
186	    needed = 0;							\
187	}
188
189
190/*----------------------------------------------------------------------
191**
192** Low-level bit-hacking functions.
193**
194*/
195
196    /*
197    ** bit_count(bits)
198    **      Return the number of bits in the word `bits'.
199    */
200int
201bit_count(uword bits)
202{
203#define MASK1   (ALLBITS / 0x03)
204#define MASK2   (ALLBITS / 0x05)
205#define MASK3   (ALLBITS / 0x11)
206
207	bits = ((bits >> 1) & MASK1) + (bits & MASK1);
208	bits = ((bits >> 2) & MASK2) + (bits & MASK2);
209	bits = ((bits >> 4) + bits) & MASK3;
210	bits = ((bits >> 8) + bits);
211	bits = ((bits >> 16) + bits);
212#if (SIZEOF_WORD > 4)
213	bits = ((bits >> 32) + bits);
214#endif
215	return bits & 0xFF;	/* safe, works for word size to 128 bytes */
216}
217
218
219    /*
220    ** lsb(bits)
221    **      Returns the position of the least significant set bit in the
222    **      given word.  Positions are numbered starting from 0 for the
223    **      least significant bit position.  If no bits are set, then the
224    **      position returned is the size of a word in bits (i.e. it's as if
225    **      a set bit has been tacked on to the most significant end of the
226    **      word).
227    */
228int
229lsb(uword bits)
230{
231	int pos = 0;
232	if (!bits) {
233	    return BPW;
234	}
235#if (SIZEOF_WORD > 4)
236	if (!(bits & 0xffffffff)) {
237	    pos += 32;
238	    bits >>= 32;
239	}
240#endif
241	if (!(bits & 0xffff)) {
242	    pos += 16;
243	    bits >>= 16;
244	}
245	if (!(bits & 0xff)) {
246	    pos += 8;
247	    bits >>= 8;
248	}
249	if (!(bits & 0xf)) {
250	    pos += 4;
251	    bits >>= 4;
252	}
253	if (!(bits & 0x3)) {
254	    pos += 2;
255	    bits >>= 2;
256	}
257	if (!(bits & 0x1)) {
258	    pos += 1;
259	}
260	return pos;
261}
262
263    /*
264    ** msb(bits)
265    **      Returns the position of the most significant set bit in the
266    **      given word.  Positions are numbered starting from 0 for the
267    **      least significant bit position.  If no bits are set, then the
268    **      position returned is -1 (i.e. it's as if a set bit has been
269    **      tacked on to the least significant end of the word).
270    */
271int
272msb(uword bits)
273{
274	int pos = 0;
275	if (!bits) {
276	    return -1;
277	}
278#if (SIZEOF_WORD > 4)
279	if (bits & UWSUF(0xffffffff00000000)) {
280	    pos += 32;
281	    bits >>= 32;
282	}
283#endif
284	if (bits & 0xffff0000) {
285	    pos += 16;
286	    bits >>= 16;
287	}
288	if (bits & 0xff00) {
289	    pos += 8;
290	    bits >>= 8;
291	}
292	if (bits & 0xf0) {
293	    pos += 4;
294	    bits >>= 4;
295	}
296	if (bits & 0xc) {
297	    pos += 2;
298	    bits >>= 2;
299	}
300	if (bits & 0x2) {
301	    pos += 1;
302	}
303	return pos;
304}
305
306
307/*----------------------------------------------------------------------
308**
309** Exported bitmap functions.
310**
311*/
312
313    /*
314    ** create_bitmap(++Min, ++Max, -Bitmap)
315    **      Create a bitmap containing all elements from Min to Max.
316    */
317int
318p_create_bitmap(value vmin, type tmin, value vmax, type tmax, value vbm, type tbm)
319{
320	uword	*bitmap;
321	word	result;
322
323	Check_Integer(tmin);
324	Check_Integer(tmax);
325
326	result = create_bitmap(vmin.nint, vmax.nint, &bitmap);
327	Return_If_Not_Success(result);
328
329	Return_Bitmap(vbm, tbm, bitmap);
330
331	Succeed
332}
333
334word
335create_bitmap(word min, word max, uword **bm_ptr)
336{
337	uword	*bitmap;
338	uword	*bits_ptr;
339	word	high, offset;
340	word	words;
341
342	if (max < min) {
343	    Fail
344	}
345
346	/*
347	** Compute the offset, making sure that the modulus of negative
348	** numbers stupidity is handled correctly.
349	*/
350	offset = min;
351	min %= BPW;
352	if (min < 0) {
353	    min += BPW;
354	}
355	offset -= min;
356
357	max -= offset;
358
359	high = max / BPW;
360	words = high + 1;
361
362	Push_Bitmap(bitmap, words);
363	Offset(bitmap) = offset;
364	Low(bitmap) = 0;
365	High(bitmap) = high;
366
367	bits_ptr = Bits(bitmap);
368	if (words == 1) {
369	    *bits_ptr = BitsFrom(min % BPW) & BitsTo(max % BPW);
370	} else {
371	    /* words >= 2 */
372	    *bits_ptr = BitsFrom(min % BPW);
373	    bits_ptr++;
374
375	    while (--words > 1) {
376		*bits_ptr = ALLBITS;
377		bits_ptr++;
378	    }
379
380	    *bits_ptr = BitsTo(max % BPW);
381	}
382
383	*bm_ptr = bitmap;
384
385	Succeed
386}
387
388
389    /*
390    ** set_bitmap_lwb(+Bitmap, ++Min, -Result, -NewBitmap)
391    **      Remove all elements smaller than Min from Bitmap, yielding
392    **      NewBitmap.  The predicate always succeeds, with Result
393    **      returning the following flags as appropriate:
394    **
395    **      	RES_CHANGED	Bitmap was modified
396    **      	RES_SLACK	Imposed bound less than Min
397    **      	RES_EMPTY	Bitmap is now empty
398    **
399    **      Note that Bitmap is updated destructively, and should not be
400    **      referred to again after the call to this predicate.
401    */
402int
403p_set_bitmap_lwb(value vbm, type tbm, value vmin, type tmin,
404		value vresult, type tresult, value vnew_bm, type tnew_bm)
405{
406	word	*new_bitmap;
407	word	result;
408
409	Check_Bitmap(tbm);
410	Check_Integer(tmin);
411
412	result = set_bitmap_lwb(vbm.wptr, vmin.nint, (uword **) &new_bitmap);
413
414	Return_Integer(vresult, tresult, result);
415	Return_Bitmap(vnew_bm, tnew_bm, new_bitmap);
416
417	Succeed
418}
419
420word
421set_bitmap_lwb(uword *bitmap, word min, uword **new_bm_ptr)
422{
423	word	*new_bitmap;
424	uword	*bits_ptr;
425	uword	bits;
426	word	low, old_low, high, offset;
427	word	result, old_min, old_max;
428	int	copied;
429
430	old_low = Low(bitmap);
431	high = High(bitmap);
432	offset = Offset(bitmap);
433	min -= offset;
434	old_min = bitmap_low_to_min(bitmap, old_low);
435	old_max = bitmap_high_to_max(bitmap, high);
436
437	if (old_min > old_max) {
438	    /* Old domain was empty. */
439	    result = RES_EMPTY;
440	    new_bitmap = bitmap;
441	} else if (min <= old_min) {
442	    /* Imposed bound is weak. */
443	    if (min == old_min) {
444		result = 0;
445	    } else {
446		result = RES_SLACK;
447	    }
448	    new_bitmap = bitmap;
449	} else if (min > old_max) {
450	    /* Domain is now empty. */
451	    result = RES_EMPTY + RES_CHANGED;
452	    Copy_Bitmap_If_Needed(bitmap, high, high, new_bitmap, copied);
453	    if (copied) {
454		*Bits(new_bitmap) = 0;
455	    } else {
456		Low(new_bitmap) = high;
457		*(Bits(new_bitmap) + high) = 0;
458	    }
459	} else {
460	    /* Bound prunes bitmap. */
461	    low = min / BPW;
462	    bits_ptr = Bits(bitmap) + low;
463	    bits = *bits_ptr;
464	    bits &= BitsFrom(min % BPW);
465
466	    if (!bits) {
467		/* Low word now empty. */
468		result = RES_CHANGED + RES_SLACK;
469
470		do {
471		    bits_ptr++;
472		    low++;
473		} while (!*bits_ptr);
474
475		Copy_Bitmap_If_Needed(bitmap, low, high, new_bitmap, copied);
476		if (!copied) {
477		    Low(new_bitmap) = low;
478		}
479	    } else {
480		/* Check whether min has been excluded. */
481		if (bits & Bit(min % BPW)) {
482		    result = RES_CHANGED;
483		} else {
484		    result = RES_CHANGED + RES_SLACK;
485		}
486
487		Copy_Bitmap_If_Needed(bitmap, low, high, new_bitmap, copied);
488		if (copied) {
489		    bits_ptr = Bits(new_bitmap);
490		} else {
491		    Low(new_bitmap) = low;
492		}
493		*bits_ptr = bits;
494	    }
495	}
496
497	*new_bm_ptr = new_bitmap;
498	return result;
499}
500
501
502    /*
503    ** set_bitmap_upb(+Bitmap, ++Max, -Result, -NewBitmap)
504    **      Remove all elements larger than Max from Bitmap, yielding
505    **      NewBitmap.  The predicate always succeeds, with Result
506    **      returning the following flags as appropriate:
507    **
508    **      	RES_CHANGED	Bitmap was modified
509    **      	RES_SLACK	Imposed bound greater than Max
510    **      	RES_EMPTY	Bitmap is now empty
511    **
512    **      Note that Bitmap is updated destructively, and should not be
513    **      referred to again after the call to this predicate.
514    */
515int
516p_set_bitmap_upb(value vbm, type tbm, value vmax, type tmax,
517		value vresult, type tresult, value vnew_bm, type tnew_bm)
518{
519	uword	*new_bitmap;
520	word	result;
521
522	Check_Bitmap(tbm);
523	Check_Integer(tmax);
524
525	result = set_bitmap_upb(vbm.wptr, vmax.nint, &new_bitmap);
526
527	Return_Integer(vresult, tresult, result);
528	Return_Bitmap(vnew_bm, tnew_bm, new_bitmap);
529
530	Succeed
531}
532
533word
534set_bitmap_upb(uword *bitmap, word max, uword **new_bm_ptr)
535{
536	uword	*new_bitmap;
537	uword	*bits_ptr;
538	uword	bits;
539	word	low, high, old_high, offset;
540	word	result, old_min, old_max;
541	int	copied;
542
543	low = Low(bitmap);
544	old_high = High(bitmap);
545	offset = Offset(bitmap);
546	max -= offset;
547	old_min = bitmap_low_to_min(bitmap, low);
548	old_max = bitmap_high_to_max(bitmap, old_high);
549
550	if (old_max < old_min) {
551	    /* Old domain was empty. */
552	    result = RES_EMPTY;
553	    new_bitmap = bitmap;
554	} else if (max >= old_max) {
555	    /* Imposed bound is weak. */
556	    if (max == old_max) {
557		result = 0;
558	    } else {
559		result = RES_SLACK;
560	    }
561	    new_bitmap = bitmap;
562	} else if (max < old_min) {
563	    /* Domain is now empty. */
564	    result = RES_EMPTY + RES_CHANGED;
565	    Copy_Bitmap_If_Needed(bitmap, low, low, new_bitmap, copied);
566	    if (copied) {
567		*Bits(new_bitmap) = 0;
568	    } else {
569		High(new_bitmap) = low;
570		*(Bits(new_bitmap) + low) = 0;
571	    }
572	} else {
573	    /* Bound prunes bitmap. */
574	    high = max / BPW;
575	    bits_ptr = Bits(bitmap) + high;
576	    bits = *bits_ptr;
577	    bits &= BitsTo(max % BPW);
578
579	    if (!bits) {
580		/* High word now empty. */
581		result = RES_CHANGED + RES_SLACK;
582
583		do {
584		    bits_ptr--;
585		    high--;
586		} while (!*bits_ptr);
587
588		Copy_Bitmap_If_Needed(bitmap, low, high, new_bitmap, copied);
589		if (!copied) {
590		    High(new_bitmap) = high;
591		}
592	    } else {
593		/* Check whether max has been excluded. */
594		if (bits & Bit(max % BPW)) {
595		    result = RES_CHANGED;
596		} else {
597		    result = RES_CHANGED + RES_SLACK;
598		}
599
600		Copy_Bitmap_If_Needed(bitmap, low, high, new_bitmap, copied);
601		if (copied) {
602		    bits_ptr = Bits(new_bitmap) + High(new_bitmap);
603		} else {
604		    High(new_bitmap) = high;
605		}
606		*bits_ptr = bits;
607	    }
608	}
609
610	*new_bm_ptr = new_bitmap;
611	return result;
612}
613
614
615    /*
616    ** remove_bitmap_element(+Bitmap, ++Elem, -Result, -NewBitmap)
617    **      Remove the element Elem from Bitmap, yielding NewBitmap.  The
618    **      predicate always succeeds, with Result returning the following
619    **      flags as appropriate:
620    **
621    **      	RES_CHANGED	Bitmap was modified
622    **      	RES_SLACK	Elem falls outside Bitmap's range
623    **      	RES_EMPTY	Bitmap is now empty
624    **
625    **      Note that Bitmap is updated destructively, and should not be
626    **      referred to again after the call to this predicate.
627    */
628int
629p_remove_bitmap_element(value vbm, type tbm, value vel, type tel,
630		value vresult, type tresult, value vnew_bm, type tnew_bm)
631{
632	uword	*new_bitmap;
633	word	result;
634
635	Check_Bitmap(tbm);
636	Check_Integer(tel);
637
638	result = remove_bitmap_element(vbm.wptr, vel.nint, &new_bitmap);
639
640	Return_Integer(vresult, tresult, result);
641	Return_Bitmap(vnew_bm, tnew_bm, new_bitmap);
642
643	Succeed
644}
645
646word
647remove_bitmap_element(uword *bitmap, word el, uword **new_bm_ptr)
648{
649	uword	*new_bitmap;
650	uword	*bits_ptr;
651	uword	bits;
652	word	low, high, offset, pos;
653	word	result, min, max;
654	int	bitmap_updated;
655	int	copied;
656
657	low = Low(bitmap);
658	high = High(bitmap);
659	offset = Offset(bitmap);
660	el -= offset;
661	min = bitmap_low_to_min(bitmap, low);
662	max = bitmap_high_to_max(bitmap, high);
663
664	if (min > max) {
665	    /* Old domain was empty. */
666	    result = RES_EMPTY;
667	    new_bitmap = bitmap;
668	} else if (el < min || el > max) {
669	    /* Excluded element is outside current domain. */
670	    result = RES_SLACK;
671	    new_bitmap = bitmap;
672	} else if (el == min && el == max) {
673	    /* Excluded element is the only element. */
674	    result = RES_CHANGED + RES_EMPTY;
675	    Copy_Bitmap_If_Needed(bitmap, low, high, new_bitmap, copied);
676	    if (copied) {
677		*Bits(new_bitmap) = 0;
678	    } else {
679		*(Bits(new_bitmap) + low) = 0;
680	    }
681	} else {
682	    pos = el / BPW;
683
684	    bits_ptr = Bits(bitmap) + pos;
685	    bits = *bits_ptr;
686	    bits &= ~Bit(el % BPW);
687
688	    /*
689	    ** Handle various special cases and determine result code.
690	    */
691
692	    bitmap_updated = 0;
693	    if (el == min) {
694		/* Excluded element is lower bound. */
695		result = RES_CHANGED;
696
697		if (bits == 0) {
698		    do {
699			bits_ptr++;
700			low++;
701		    } while (!*bits_ptr);
702
703		    Copy_Bitmap_If_Needed(bitmap, low, high, new_bitmap, copied);
704		    if (!copied) {
705			Low(new_bitmap) = low;
706		    }
707		    bitmap_updated = 1;
708		}
709	    } else if (el == max) {
710		/* Excluded element is upper bound. */
711		result = RES_CHANGED;
712
713		if (bits == 0) {
714		    do {
715			bits_ptr--;
716			high--;
717		    } while (!*bits_ptr);
718
719		    Copy_Bitmap_If_Needed(bitmap, low, high, new_bitmap, copied);
720		    if (!copied) {
721			High(new_bitmap) = high;
722		    }
723		    bitmap_updated = 1;
724		}
725	    } else {
726		if (bits == *bits_ptr) {
727		    result = 0;
728		    new_bitmap = bitmap;
729		    bitmap_updated = 1;
730		} else {
731		    result = RES_CHANGED;
732		}
733	    }
734
735	    /*
736	    ** Default bitmap processing.
737	    */
738
739	    if (!bitmap_updated) {
740		Copy_Bitmap_If_Needed(bitmap, low, high, new_bitmap, copied);
741		if (copied) {
742		    bits_ptr = Bits(new_bitmap) + pos - low;
743		}
744		*bits_ptr = bits;
745	    }
746	}
747
748	*new_bm_ptr = new_bitmap;
749	return result;
750}
751
752
753    /*
754    ** remove_bitmap_range(+Bitmap, ++Lo, ++Hi, -Result, -NewBitmap)
755    **      Remove all the elements from Lo to Hi (inclusive) from Bitmap,
756    **      yielding NewBitmap.  The predicate always succeeds, with Result
757    **      returning the following flags as appropriate:
758    **
759    **      	RES_CHANGED	Bitmap was modified
760    **      	RES_SLACK	Lo..Hi falls outside Bitmap's range
761    **      	RES_EMPTY	Bitmap is now empty
762    **
763    **      Note that Bitmap is updated destructively, and should not be
764    **      referred to again after the call to this predicate.
765    */
766int
767p_remove_bitmap_range(value vbm, type tbm, value vlo, type tlo, value vhi, type thi,
768		value vresult, type tresult, value vnew_bm, type tnew_bm)
769{
770	uword	*new_bitmap;
771	word	result;
772
773	Check_Bitmap(tbm);
774	Check_Integer(tlo);
775	Check_Integer(thi);
776
777	result = remove_bitmap_range(vbm.wptr, vlo.nint, vhi.nint, &new_bitmap);
778
779	Return_Integer(vresult, tresult, result);
780	Return_Bitmap(vnew_bm, tnew_bm, new_bitmap);
781
782	Succeed
783}
784
785word
786remove_bitmap_range(uword *bitmap, word lo0, word hi0, uword **new_bm_ptr)
787{
788	uword	*new_bitmap;
789	uword	*bits_ptr;
790	uword	bits;
791	word	low, high, offset, pos, limit;
792	word	result, min, max;
793	int	copied;
794
795	low = Low(bitmap);
796	high = High(bitmap);
797	offset = Offset(bitmap);
798	lo0 -= offset;
799	hi0 -= offset;
800	min = bitmap_low_to_min(bitmap, low);
801	max = bitmap_high_to_max(bitmap, high);
802
803	if (lo0 > hi0) {
804	    /* Nothing to exclude. */
805	    result = RES_SLACK;
806	    new_bitmap = bitmap;
807	} else if (hi0 >= max) {
808	    return set_bitmap_upb(bitmap, lo0 - 1, new_bm_ptr);
809	} else if (lo0 <= min) {
810	    return set_bitmap_lwb(bitmap, hi0 + 1, new_bm_ptr);
811	} else if (min > max) {
812	    /* Old domain was empty. */
813	    result = RES_EMPTY;
814	    new_bitmap = bitmap;
815	} else {
816	    /* min < lo0 <= hi0 < hi */
817
818	    pos = lo0 / BPW;
819	    limit = hi0 / BPW;
820
821	    bits_ptr = Bits(bitmap) + pos;
822	    bits = *bits_ptr;
823
824	    if (pos == limit) {
825		bits &= ~(BitsFrom(lo0 % BPW) & BitsTo(hi0 % BPW));
826	    } else {
827		bits &= ~BitsFrom(lo0 % BPW);
828	    }
829
830	    if (bits == *bits_ptr) {
831		result = 0;
832		new_bitmap = bitmap;
833	    } else {
834		result = RES_CHANGED;
835		Copy_Bitmap_If_Needed(bitmap, low, high, new_bitmap, copied);
836		if (copied) {
837		    pos -= low;
838		    limit -= low;
839		    low = 0;
840		    /* Don't care about high. */
841		    bits_ptr = Bits(new_bitmap) + pos;
842		    bitmap = new_bitmap;
843		}
844		*bits_ptr = bits;
845	    }
846
847	    if (pos < limit) {
848		pos++;
849		bits_ptr++;
850		bits = *bits_ptr;
851
852		while (pos < limit) {
853		    if (bits != 0) {
854			if (result != RES_CHANGED) {
855			    result = RES_CHANGED;
856			    Copy_Bitmap_If_Needed(bitmap, low, high, new_bitmap, copied);
857			    if (copied) {
858				pos -= low;
859				limit -= low;
860				low = 0;
861				/* Don't care about high. */
862				bits_ptr = Bits(new_bitmap) + pos;
863				bitmap = new_bitmap;
864			    }
865			}
866			*bits_ptr = 0;
867		    }
868
869		    pos++;
870		    bits_ptr++;
871		    bits = *bits_ptr;
872		}
873
874		bits &= ~BitsTo(hi0 % BPW);
875
876		if (bits != *bits_ptr) {
877		    if (result != RES_CHANGED) {
878			result = RES_CHANGED;
879			Copy_Bitmap_If_Needed(bitmap, low, high, new_bitmap, copied);
880			if (copied) {
881			    pos -= low;
882			    limit -= low;
883			    low = 0;
884			    /* Don't care about high. */
885			    bits_ptr = Bits(new_bitmap) + pos;
886			}
887		    }
888		    *bits_ptr = bits;
889		}
890	    }
891	}
892
893	*new_bm_ptr = new_bitmap;
894	return result;
895}
896
897
898    /*
899    ** bitmap_intersect_into(+Bitmap, +Bitmap2, -Result, -NewBitmap)
900    **      Remove from Bitmap all elements which do not appear in Bitmap2,
901    **      yielding NewBitmap.  The predicate always succeeds, with Result
902    **      returning the following flags as appropriate:
903    **
904    **      	RES_CHANGED	Bitmap was modified
905    **      	RES_SLACK	Bitmap's bounds were modified
906    **      	RES_EMPTY	Bitmap is now empty
907    **
908    **      Note that Bitmap is updated destructively, and should not be
909    **      referred to again after the call to this predicate.
910    */
911int
912p_bitmap_intersect_into(value vbm, type tbm, value vbm2, type tbm2,
913		value vresult, type tresult, value vnew_bm, type tnew_bm)
914{
915	uword	*new_bitmap;
916	word	result;
917
918	Check_Bitmap(tbm);
919	Check_Bitmap(tbm2);
920
921	result = bitmap_intersect_into(vbm.wptr, vbm2.wptr, 0, &new_bitmap);
922
923	Return_Integer(vresult, tresult, result);
924	Return_Bitmap(vnew_bm, tnew_bm, new_bitmap);
925
926	Succeed
927}
928
929    /*
930    ** Note that we allow a word-sized offset for bitmap2, since shifts of
931    ** that size are efficient.  Non-word-sized offsets incur a performance
932    ** penalty, and so are handled by a separate function,
933    ** bitmap_shifted_intersect_into().
934    */
935word
936bitmap_intersect_into(uword *bitmap, uword *bitmap2, word offset_adj, uword **new_bm_ptr)
937{
938	uword	*new_bitmap;
939	uword	*bits_ptr;
940	uword	*bits_ptr2;
941	uword	low_bits, high_bits, bits;
942	word	low, high, offset;
943	word	low2, high2, offset2;
944	word	min, max;
945	word	min2, max2;
946	word	pos;
947	word	delta;
948	word	result;
949	int	copied;
950
951	low = Low(bitmap);
952	high = High(bitmap);
953	offset = Offset(bitmap);
954	low2 = Low(bitmap2);
955	high2 = High(bitmap2);
956	offset2 = Offset(bitmap2) + offset_adj;
957	min = bitmap_low_to_min(bitmap, low);
958	max = bitmap_high_to_max(bitmap, high);
959	min2 = bitmap_low_to_min(bitmap2, low2);
960	max2 = bitmap_high_to_max(bitmap2, high2);
961
962	/* Add delta to convert an index for bitmap to an index for bitmap2. */
963	/* This division works OK even if offset2 < offset since it is exact. */
964	delta = (offset - offset2) / BPW;
965
966	if (min > max) {
967	    /* Old domain was empty. */
968	    result = RES_EMPTY;
969	    new_bitmap = bitmap;
970	} else if (min2 + offset2 > max + offset || max2 + offset2 < min + offset) {
971	    /* Bitmaps don't overlap, so intersection guaranteed empty. */
972	    result = RES_CHANGED + RES_EMPTY;
973	    Copy_Bitmap_If_Needed(bitmap, low, low, new_bitmap, copied);
974	    if (copied) {
975		*Bits(new_bitmap) = 0;
976	    } else {
977		High(new_bitmap) = low;
978		*(Bits(new_bitmap) + low) = 0;
979	    }
980	} else {
981	    /*
982	    ** Note: we don't worry about setting result to RES_CHANGED for
983	    ** bounds changes made here, since we test for them at the end
984	    ** (in order to more easily establish whether to set RES_SLACK).
985	    */
986
987	    if (low2 - delta > low) {
988		low = low2 - delta;
989	    }
990	    if (high2 - delta < high) {
991		high = high2 - delta;
992	    }
993
994	    /* Find lowest word in result with bit set. */
995
996	    bits_ptr = Bits(bitmap) + low;
997	    low_bits = *bits_ptr;
998	    bits_ptr2 = Bits(bitmap2) + low + delta;
999	    low_bits &= *bits_ptr2;
1000
1001	    while (!low_bits && low < high) {
1002		/* Low word empty. */
1003		bits_ptr++;
1004		bits_ptr2++;
1005		low++;
1006		low_bits = *bits_ptr;
1007		low_bits &= *bits_ptr2;
1008	    }
1009
1010	    /* Find highest word in result with bit set. */
1011
1012	    if (high > low) {
1013		bits_ptr = Bits(bitmap) + high;
1014		high_bits = *bits_ptr;
1015		bits_ptr2 = Bits(bitmap2) + high + delta;
1016		high_bits &= *bits_ptr2;
1017
1018		while (!high_bits && high > low) {
1019		    /* High word empty. */
1020		    bits_ptr--;
1021		    bits_ptr2--;
1022		    high--;
1023		    high_bits = *bits_ptr;
1024		    high_bits &= *bits_ptr2;
1025		}
1026	    }
1027
1028	    Copy_Bitmap_If_Needed(bitmap, low, high, new_bitmap, copied);
1029	    if (copied) {
1030		/*
1031		** Note that offset and delta may have been invalidated as well
1032		** as low and high.  offset is not used any more, but we need
1033		** to make sure we adjust delta correctly.
1034		*/
1035		delta += low - Low(new_bitmap);
1036		low = Low(new_bitmap);
1037		high = High(new_bitmap);
1038	    } else {
1039		Low(new_bitmap) = low;
1040		High(new_bitmap) = high;
1041	    }
1042
1043	    bits_ptr = Bits(new_bitmap) + low;
1044	    if (low_bits == 0) {
1045		/* Bitmap now empty. */
1046		result = RES_CHANGED + RES_EMPTY;
1047		*bits_ptr = low_bits;
1048	    } else {
1049		result = 0;
1050
1051		/* Update low word. */
1052
1053		if (low_bits != *bits_ptr) {
1054		    result = RES_CHANGED;
1055		    *bits_ptr = low_bits;
1056		}
1057
1058		if (high > low) {
1059		    /* Update intermediate words. */
1060
1061		    pos = low + 1;
1062		    bits_ptr++;
1063		    bits_ptr2 = Bits(bitmap2) + pos + delta;
1064
1065		    while (pos < high) {
1066			bits = *bits_ptr & *bits_ptr2;
1067			if (bits != *bits_ptr) {
1068			    result = RES_CHANGED;
1069			    *bits_ptr = bits;
1070			}
1071
1072			pos++;
1073			bits_ptr++;
1074			bits_ptr2++;
1075		    }
1076
1077		    /* Update high word. */
1078
1079		    if (high_bits != *bits_ptr) {
1080			result = RES_CHANGED;
1081			*bits_ptr = high_bits;
1082		    }
1083		}
1084
1085		/* Is it worth checking for no change and freeing new_bitmap? */
1086
1087		if (bitmap_low_to_min(new_bitmap, low) > min ||
1088			bitmap_high_to_max(new_bitmap, high) < max) {
1089		    result = RES_CHANGED + RES_SLACK;
1090		}
1091	    }
1092	}
1093
1094	*new_bm_ptr = new_bitmap;
1095	return result;
1096}
1097
1098
1099    /*
1100    ** bitmap_shifted_intersect_into(+Bitmap, +Bitmap2, ++Shift, -Result, -NewBitmap)
1101    **      Remove from Bitmap all elements which do not appear in Bitmap2
1102    **      after it has been shifted by Shift, yielding NewBitmap.  The
1103    **      predicate always succeeds, with Result returning the following
1104    **      flags as appropriate:
1105    **
1106    **      	RES_CHANGED	Bitmap was modified
1107    **      	RES_SLACK	Bitmap's bounds were modified
1108    **      	RES_EMPTY	Bitmap is now empty
1109    **
1110    **      Note that Bitmap is updated destructively, and should not be
1111    **      referred to again after the call to this predicate.
1112    */
1113int
1114p_bitmap_shifted_intersect_into(value vbm, type tbm, value vbm2, type tbm2,
1115		value vshift, type tshift, value vresult, type tresult,
1116		value vnew_bm, type tnew_bm)
1117{
1118	uword	*new_bitmap;
1119	word	result;
1120
1121	Check_Bitmap(tbm);
1122	Check_Bitmap(tbm2);
1123	Check_Integer(tshift);
1124
1125	result = bitmap_shifted_intersect_into(vbm.wptr, vbm2.wptr,
1126		vshift.nint, &new_bitmap);
1127
1128	Return_Integer(vresult, tresult, result);
1129	Return_Bitmap(vnew_bm, tnew_bm, new_bitmap);
1130
1131	Succeed
1132}
1133
1134/*
1135Intersect bitmap2 into bitmap, as if every element of bitmap2 has had
1136"shift" added to it.  "shift" is decomposed into a word-sized component
1137offset_adj and the (non-negative) remainder bit_adj.
1138
1139          bit 32i       bit 32i+bit_adj   bit 32i+31
1140            lsb           word i     v    msb
1141            |. . . . . . . . . . . . . . . .|
1142    |. . . . . . . . . . . . . . . .|. . . . . . . . . . . . . . . .|
1143    lsb      ^ word i-offset_adj-1         word i-offset_adj      msb
1144       bit 32i-shift
1145    = 32(i-offset_adj-1) + (32-bit_adj)
1146*/
1147word
1148bitmap_shifted_intersect_into(uword *bitmap, uword *bitmap2, word shift, uword **new_bm_ptr)
1149{
1150	uword	*new_bitmap;
1151	uword	*bits_ptr;
1152	uword	*bits_ptr2;
1153	uword	low_bits, high_bits, bits, tmp;
1154	word	low, high, offset;
1155	word	low2, high2, offset2;
1156	word	min, max;
1157	word	min2, max2;
1158	word	offset_adj, bit_adj;
1159	word	pos;
1160	word	delta;
1161	word	result;
1162	int	copied;
1163
1164	bit_adj = shift % BPW;
1165	if (bit_adj == 0) {
1166	    /* Word-sized shift, so use the more efficient function. */
1167	    return bitmap_intersect_into(bitmap, bitmap2, shift, new_bm_ptr);
1168	}
1169	if (bit_adj < 0) {
1170	    bit_adj += BPW;
1171	}
1172	offset_adj = shift - bit_adj;
1173
1174	low = Low(bitmap);
1175	high = High(bitmap);
1176	offset = Offset(bitmap);
1177	low2 = Low(bitmap2);
1178	high2 = High(bitmap2);
1179	offset2 = Offset(bitmap2) + offset_adj;
1180	min = bitmap_low_to_min(bitmap, low);
1181	max = bitmap_high_to_max(bitmap, high);
1182	min2 = bitmap_low_to_min(bitmap2, low2);
1183	max2 = bitmap_high_to_max(bitmap2, high2);
1184
1185	/* Add delta to convert an index for bitmap to an index for bitmap2. */
1186	/* This division works OK even if offset2 < offset since it is exact. */
1187	delta = (offset - offset2) / BPW;
1188
1189	if (min > max) {
1190	    /* Old domain was empty. */
1191	    result = RES_EMPTY;
1192	    new_bitmap = bitmap;
1193	} else if (min2 + offset2 + bit_adj > max + offset
1194		|| max2 + offset2 + bit_adj < min + offset) {
1195	    /* Bitmaps don't overlap, so intersection guaranteed empty. */
1196	    result = RES_CHANGED + RES_EMPTY;
1197	    Copy_Bitmap_If_Needed(bitmap, low, low, new_bitmap, copied);
1198	    if (copied) {
1199		*Bits(new_bitmap) = 0;
1200	    } else {
1201		High(new_bitmap) = low;
1202		*(Bits(new_bitmap) + low) = 0;
1203	    }
1204	} else {
1205	    /*
1206	    ** Note: we don't worry about setting result to RES_CHANGED for
1207	    ** bounds changes made here, since we test for them at the end
1208	    ** (in order to more easily establish whether to set RES_SLACK).
1209	    */
1210
1211	    /*
1212	    ** We set low and high to the lowest and highest word of bitmap
1213	    ** that may affect the outcome; note that the lowest word of
1214	    ** bitmap2 that may affect the outcome may be low + delta - 1;
1215	    ** note also that low + delta - 1 and high + delta may not exist
1216	    ** in bitmap2.
1217	    */
1218
1219	    if (low2 - delta > low) {
1220		low = low2 - delta;
1221	    }
1222	    if (high2 + 1 - delta < high) {
1223		high = high2 + 1 - delta;
1224	    }
1225
1226	    /* Find lowest word in result with bit set. */
1227
1228	    bits_ptr = Bits(bitmap) + low;
1229	    low_bits = *bits_ptr;
1230	    bits_ptr2 = Bits(bitmap2) + low + delta;
1231	    /* If low2 == high2, bits_ptr2 may be out of bounds already. */
1232	    if (high2 < low + delta) {
1233		tmp = 0;
1234	    } else {
1235		tmp = (*bits_ptr2) << bit_adj;
1236	    }
1237	    /* Take into account the bits from the word below if it exists. */
1238	    if (low2 < low + delta) {
1239		tmp |= (*(bits_ptr2 - 1)) >> (BPW - bit_adj);
1240	    }
1241	    low_bits &= tmp;
1242
1243	    while (!low_bits && low < high) {
1244		/* Low word empty. */
1245		bits_ptr++;
1246		low++;
1247		low_bits = *bits_ptr;
1248		tmp = (*bits_ptr2) >> (BPW - bit_adj);
1249		bits_ptr2++;
1250		tmp |= (*bits_ptr2) << bit_adj;
1251		low_bits &= tmp;
1252	    }
1253
1254	    /* Find highest word in result with bit set. */
1255
1256	    if (high > low) {
1257		bits_ptr = Bits(bitmap) + high;
1258		high_bits = *bits_ptr;
1259		bits_ptr2 = Bits(bitmap2) + high + delta - 1;
1260		tmp = (*bits_ptr2) >> (BPW - bit_adj);
1261		if (high2 >= high + delta) {
1262		    tmp |= (*(bits_ptr2 + 1)) << bit_adj;
1263		}
1264		high_bits &= tmp;
1265
1266		while (!high_bits && high > low) {
1267		    /* High word empty. */
1268		    bits_ptr--;
1269		    high--;
1270		    high_bits = *bits_ptr;
1271		    tmp = (*bits_ptr2) << bit_adj;
1272		    bits_ptr2--;
1273		    tmp |= (*bits_ptr2) >> (BPW - bit_adj);
1274		    high_bits &= tmp;
1275		}
1276	    }
1277
1278	    Copy_Bitmap_If_Needed(bitmap, low, high, new_bitmap, copied);
1279	    if (copied) {
1280		/*
1281		** Note that offset and delta may have been invalidated as well
1282		** as low and high.  offset is not used any more, but we need
1283		** to make sure we adjust delta correctly.
1284		*/
1285		delta += low - Low(new_bitmap);
1286		low = Low(new_bitmap);
1287		high = High(new_bitmap);
1288	    } else {
1289		Low(new_bitmap) = low;
1290		High(new_bitmap) = high;
1291	    }
1292
1293	    bits_ptr = Bits(new_bitmap) + low;
1294	    if (low_bits == 0) {
1295		/* Bitmap now empty. */
1296		result = RES_CHANGED + RES_EMPTY;
1297		*bits_ptr = low_bits;
1298	    } else {
1299		result = 0;
1300
1301		/* Update low word. */
1302
1303		if (low_bits != *bits_ptr) {
1304		    result = RES_CHANGED;
1305		    *bits_ptr = low_bits;
1306		}
1307
1308		if (high > low) {
1309		    /* Update intermediate words. */
1310
1311		    pos = low + 1;
1312		    bits_ptr++;
1313		    bits_ptr2 = Bits(bitmap2) + pos + delta - 1;
1314
1315		    while (pos < high) {
1316			bits = *bits_ptr;
1317			tmp = (*bits_ptr2) >> (BPW - bit_adj);
1318			bits_ptr2++;
1319			tmp |= (*bits_ptr2) << bit_adj;
1320			bits &= tmp;
1321			if (bits != *bits_ptr) {
1322			    result = RES_CHANGED;
1323			    *bits_ptr = bits;
1324			}
1325
1326			pos++;
1327			bits_ptr++;
1328		    }
1329
1330		    /* Update high word. */
1331
1332		    if (high_bits != *bits_ptr) {
1333			result = RES_CHANGED;
1334			*bits_ptr = high_bits;
1335		    }
1336		}
1337
1338		/* Is it worth checking for no change and freeing new_bitmap? */
1339
1340		if (bitmap_low_to_min(new_bitmap, low) > min ||
1341			bitmap_high_to_max(new_bitmap, high) < max) {
1342		    result = RES_CHANGED + RES_SLACK;
1343		}
1344	    }
1345	}
1346
1347	*new_bm_ptr = new_bitmap;
1348	return result;
1349}
1350
1351
1352    /*
1353    ** bitmaps_have_non_empty_intersection(+Bitmap, +Bitmap2)
1354    **      Test whether Bitmap and Bitmap2 have non-empty intersection.
1355    */
1356
1357int
1358p_bitmaps_have_non_empty_intersection(value vbm, type tbm, value vbm2, type tbm2)
1359{
1360	Check_Bitmap(tbm);
1361	Check_Bitmap(tbm2);
1362
1363	return bitmaps_have_non_empty_intersection(vbm.wptr, vbm2.wptr);
1364}
1365
1366int
1367bitmaps_have_non_empty_intersection(uword *bitmap, uword *bitmap2)
1368{
1369	uword	*bits_ptr;
1370	uword	*bits_ptr2;
1371	uword	low_bits;
1372	word	low, high, offset;
1373	word	low2, high2, offset2;
1374	word	delta;
1375
1376	low = Low(bitmap);
1377	high = High(bitmap);
1378	low2 = Low(bitmap2);
1379	high2 = High(bitmap2);
1380
1381        if (low2 > high || high2 < low) {
1382	    /* Bitmaps don't overlap, so intersection guaranteed empty. */
1383	    Fail
1384	}
1385
1386	offset = Offset(bitmap);
1387	offset2 = Offset(bitmap2);
1388
1389	/* Add delta to convert an index for bitmap to an index for bitmap2. */
1390	/* This division works OK even if offset2 < offset since it is exact. */
1391	delta = (offset - offset2) / BPW;
1392
1393	if (low2 - delta > low) {
1394	    low = low2 - delta;
1395	}
1396	if (high2 - delta < high) {
1397	    high = high2 - delta;
1398	}
1399
1400	/* Find a word with bit set. */
1401
1402	bits_ptr = Bits(bitmap) + low;
1403	low_bits = *bits_ptr;
1404	bits_ptr2 = Bits(bitmap2) + low + delta;
1405	low_bits &= *bits_ptr2;
1406
1407	while (!low_bits && low < high) {
1408	    /* Low word empty. */
1409	    bits_ptr++;
1410	    bits_ptr2++;
1411	    low++;
1412	    low_bits = *bits_ptr;
1413	    low_bits &= *bits_ptr2;
1414	}
1415
1416	/* No common set bits */
1417	if (low_bits == 0) {
1418	    Fail
1419	}
1420
1421	Succeed
1422}
1423
1424    /*
1425    ** bitmap_union(+Bitmap, +Bitmap2, -NewBitmap)
1426    **
1427    **      Join all elements from Bitmap and Bitmap2, yielding
1428    **      NewBitmap.
1429    */
1430int
1431p_bitmap_union(value vbm, type tbm, value vbm2, type tbm2, value vnew_bm, type tnew_bm)
1432{
1433	uword	*new_bitmap;
1434	word	result;
1435
1436	Check_Bitmap(tbm);
1437	Check_Bitmap(tbm2);
1438
1439	result = bitmap_union(vbm.wptr, vbm2.wptr, &new_bitmap);
1440
1441	Return_If_Not_Success(result);
1442	Return_Bitmap(vnew_bm, tnew_bm, new_bitmap);
1443
1444	Succeed
1445}
1446
1447word
1448bitmap_union(uword *bitmap, uword *bitmap2, uword **new_bm_ptr)
1449{
1450	uword	*new_bitmap;
1451	uword	*bits_ptr;
1452	uword	*bits_ptr2;
1453	uword	*new_bits_ptr;
1454	word	low, high, offset;
1455	word	low2, high2, offset2;
1456	word	new_low, new_high, new_offset;
1457	word	min, max;
1458	word	min2, max2;
1459	word    delta, start, stop;
1460	word    delta2, start2, stop2;
1461	word	pos;
1462	word	result;
1463	word    new_words;
1464
1465	low = Low(bitmap);
1466	high = High(bitmap);
1467	offset = Offset(bitmap);
1468	low2 = Low(bitmap2);
1469	high2 = High(bitmap2);
1470	offset2 = Offset(bitmap2);
1471	min = offset + bitmap_low_to_min(bitmap, low);
1472	max = offset + bitmap_high_to_max(bitmap, high);
1473	min2 = offset2 + bitmap_low_to_min(bitmap2, low2);
1474	max2 = offset2 + bitmap_high_to_max(bitmap2, high2);
1475
1476
1477	if (min > max) {
1478	    /* bitmap 1 domain was empty. */
1479	    Copy_Bitmap(bitmap2, low2, high2, new_bitmap);
1480	    result = PSUCCEED;
1481	} else if (min2 > max2) {
1482	    /* bitmap 2 domain was empty. */
1483	    Copy_Bitmap(bitmap, low, high, new_bitmap);
1484	    result = PSUCCEED;
1485	} else {
1486	    /* Create a new bitmap from min(min,min2) to max(max,max2) */
1487	    result = create_bitmap((min<min2)?min:min2,
1488				   (max>max2)?max:max2,
1489				   &new_bitmap);
1490	    Return_If_Not_Success(result);
1491
1492	    new_low = Low(new_bitmap);
1493	    new_high = High(new_bitmap);
1494	    new_offset = Offset(new_bitmap);
1495	    new_words = new_high + 1;
1496
1497	    /*
1498            printf("low=%d, high=%d, offset=%d, min=%d, max=%d\n",
1499		   low, high, offset, min, max);
1500	    printf("low2=%d, high2=%d, offset2=%d, min2=%d, max2=%d\n",
1501		   low2, high2, offset2, min2, max2);
1502	    printf("new_low=%d, new_high=%d, new_offset=%d, new_words=%d, new_min=%d, new_max=%d\n",
1503		   new_low, new_high, new_offset, new_words,
1504		   bitmap_low_to_min(new_bitmap, new_low),
1505		   bitmap_high_to_max(new_bitmap, new_high));
1506	    */
1507
1508	    /*
1509	    ** Copy words from bitmap and bitmap2 taking the bitunion where
1510	    ** appropriate.
1511	    */
1512	    delta = (new_offset - offset) / BPW;
1513	    delta2 = (new_offset - offset2) / BPW;
1514	    start = low - delta;
1515	    stop = high - delta;
1516	    start2 = low2 - delta2;
1517	    stop2 = high2 - delta2;
1518
1519	    new_bits_ptr = Bits(new_bitmap);
1520	    bits_ptr = Bits(bitmap) + delta;
1521	    bits_ptr2 = Bits(bitmap2) + delta2;
1522
1523	    /*
1524	    printf("start=%d, stop=%d, start2=%d, stop2=%d\n",
1525		   start, stop, start2, stop2);
1526	    */
1527
1528	    /* pos is the index with new_bitmap */
1529	    for(pos=0; pos < new_words; pos++) {
1530		if ((pos >= start) && (pos <= stop)) {
1531		    /* copy the word from bitmap */
1532		    *new_bits_ptr = *bits_ptr;
1533		} else {
1534		    /* zero the memory */
1535		    *new_bits_ptr = 0;
1536		}
1537		/* bitwise union the words from bitmap2 */
1538		if ((pos >= start2) && (pos <= stop2)) {
1539		    /* or the word from bitmap2 */
1540		    *new_bits_ptr |= *bits_ptr2;
1541		}
1542
1543		bits_ptr++;
1544		bits_ptr2++;
1545		new_bits_ptr++;
1546	    }
1547	    result = PSUCCEED;
1548	}
1549
1550	*new_bm_ptr = new_bitmap;
1551	return result;
1552}
1553
1554
1555    /*
1556    ** copy_bitmap(+Bitmap, -NewBitmap)
1557    **      Make a new copy of Bitmap and return it as NewBitmap.  The
1558    **      predicate always succeeds.
1559    */
1560int
1561p_copy_bitmap(value vbm, type tbm, value vnew_bm, type tnew_bm)
1562{
1563	uword	*new_bitmap;
1564
1565	Check_Bitmap(tbm);
1566
1567	copy_bitmap(vbm.wptr, &new_bitmap);
1568
1569	Return_Bitmap(vnew_bm, tnew_bm, new_bitmap);
1570
1571	Succeed
1572}
1573
1574void
1575copy_bitmap(uword *bitmap, uword **new_bm_ptr)
1576{
1577	uword	*new_bitmap;
1578	word	low, high;
1579
1580	low = Low(bitmap);
1581	high = High(bitmap);
1582	Copy_Bitmap(bitmap, low, high, new_bitmap);
1583
1584	*new_bm_ptr = new_bitmap;
1585}
1586
1587
1588    /*
1589    ** copy_bitmap_shifted(+Bitmap, ++Shift, -NewBitmap)
1590    **      Make a new copy of Bitmap, shifted by Shift and return it as
1591    **      NewBitmap.
1592    */
1593int
1594p_copy_bitmap_shifted(value vbm, type tbm, value vshift, type tshift, value vnew_bm, type tnew_bm)
1595{
1596	uword	*new_bitmap;
1597
1598	Check_Bitmap(tbm);
1599	Check_Integer(tshift);
1600
1601	copy_bitmap_shifted(vbm.wptr, vshift.nint, &new_bitmap);
1602
1603	Return_Bitmap(vnew_bm, tnew_bm, new_bitmap);
1604
1605	Succeed
1606}
1607
1608void
1609copy_bitmap_shifted(uword *bitmap, word shift, uword **new_bm_ptr)
1610{
1611	uword	*new_bitmap;
1612	word	low, high;
1613	word	offset_adj, bit_adj;
1614	word	words, i;
1615	uword	*bits_ptr, *new_bits_ptr;
1616	uword	tmp;
1617
1618	low = Low(bitmap);
1619	high = High(bitmap);
1620	bit_adj = shift % BPW;
1621	if (bit_adj < 0) bit_adj += BPW;
1622	offset_adj = shift - bit_adj;
1623
1624	if (bit_adj == 0) {
1625	    /* Easy case: we can just copy the bitmap and adjust the offset. */
1626	    Copy_Bitmap(bitmap, low, high, new_bitmap);
1627	    Offset(new_bitmap) += offset_adj;
1628	} else {
1629	    /* Have to do some bit-twiddling to shift the bitmap contents. */
1630	    words = high - low + 2; /* Lazy: might not need the extra word. */
1631	    Push_Bitmap(new_bitmap, words);
1632	    bits_ptr = Bits(bitmap) + low;
1633	    new_bits_ptr = Bits(new_bitmap);
1634	    *new_bits_ptr = (*bits_ptr) << bit_adj;
1635	    /* Low word might be empty, but then next guaranteed not. */
1636	    Low(new_bitmap) = (*new_bits_ptr == 0);
1637	    new_bits_ptr++;
1638	    for (i = low; i < high; i++) {
1639		tmp = (*bits_ptr) >> (BPW - bit_adj);
1640		bits_ptr++;
1641		tmp |= (*bits_ptr) << bit_adj;
1642		*new_bits_ptr = tmp;
1643		new_bits_ptr++;
1644	    }
1645	    *new_bits_ptr = (*bits_ptr) >> (BPW - bit_adj);
1646	    /* High word might be empty, but then previous guaranteed not. */
1647	    High(new_bitmap) = words - 1 - (*new_bits_ptr == 0);
1648	    Offset(new_bitmap) = Offset(bitmap) + low * BPW + offset_adj;
1649	}
1650
1651	*new_bm_ptr = new_bitmap;
1652}
1653
1654
1655    /*
1656    ** bitmap_range(+Bitmap, -Min, -Max)
1657    **      Return the smallest and largest elements from Bitmap.  Fails if
1658    **      Bitmap is empty.
1659    */
1660int
1661p_bitmap_range(value vbm, type tbm, value vmin, type tmin, value vmax, type tmax)
1662{
1663	word	min, max;
1664
1665	Check_Bitmap(tbm);
1666
1667	if (bitmap_range(vbm.wptr, &min, &max) != 0) {
1668	    Fail
1669	}
1670
1671	Return_Integer(vmin, tmin, min);
1672	Return_Integer(vmax, tmax, max);
1673
1674	Succeed
1675}
1676
1677word
1678bitmap_range(uword *bitmap, word *min_ptr, word *max_ptr)
1679{
1680	word	low, high, offset;
1681	word	min, max;
1682
1683	low = Low(bitmap);
1684	high = High(bitmap);
1685	offset = Offset(bitmap);
1686
1687	min = bitmap_low_to_min(bitmap, low);
1688	max = bitmap_high_to_max(bitmap, high);
1689
1690	if (min > max) {
1691	    return RES_EMPTY;
1692	} else {
1693	    *min_ptr = min + offset;
1694	    *max_ptr = max + offset;
1695	    return 0;
1696	}
1697}
1698
1699
1700    /*
1701    ** get_bitmap_lwb(+Bitmap, -Min)
1702    **      Return the smallest element from Bitmap.  Fails if Bitmap is
1703    **      empty.
1704    */
1705int
1706p_get_bitmap_lwb(value vbm, type tbm, value vmin, type tmin)
1707{
1708	word	min;
1709
1710	Check_Bitmap(tbm);
1711
1712	if (get_bitmap_lwb(vbm.wptr, &min) != 0) {
1713	    Fail
1714	}
1715
1716	Return_Integer(vmin, tmin, min);
1717
1718	Succeed
1719}
1720
1721word
1722get_bitmap_lwb(uword *bitmap, word *min_ptr)
1723{
1724	word	low;
1725	word	min;
1726
1727	low = Low(bitmap);
1728
1729	min = bitmap_low_to_min(bitmap, low);
1730
1731	if (min >= (low + 1) * BPW) {
1732	    return RES_EMPTY;
1733	} else {
1734	    *min_ptr = min + Offset(bitmap);
1735	    return 0;
1736	}
1737}
1738
1739
1740    /*
1741    ** get_bitmap_upb(+Bitmap, -Max)
1742    **      Return the largest element from Bitmap.  Fails if Bitmap is
1743    **      empty.
1744    */
1745int
1746p_get_bitmap_upb(value vbm, type tbm, value vmax, type tmax)
1747{
1748	word	max;
1749
1750	Check_Bitmap(tbm);
1751
1752	if (get_bitmap_upb(vbm.wptr, &max) != 0) {
1753	    Fail
1754	}
1755
1756	Return_Integer(vmax, tmax, max);
1757
1758	Succeed
1759}
1760
1761word
1762get_bitmap_upb(uword *bitmap, word *max_ptr)
1763{
1764	word	high;
1765	word	max;
1766
1767	high = High(bitmap);
1768
1769	max = bitmap_high_to_max(bitmap, high);
1770
1771	if (max < high * BPW) {
1772	    return RES_EMPTY;
1773	} else {
1774	    *max_ptr = max + Offset(bitmap);
1775	    return 0;
1776	}
1777}
1778
1779
1780    /*
1781    ** next_greater_member(+Bitmap, ++Curr, -Next)
1782    **      Return the smallest element in Bitmap which is greater than
1783    **      Curr.  Fails if there is no such element.
1784    */
1785int
1786p_next_greater_member(value vbm, type tbm, value vcurr, type tcurr, value vnext, type tnext)
1787{
1788	word	next;
1789	word	result;
1790
1791	Check_Bitmap(tbm);
1792	Check_Integer(tcurr);
1793
1794	result = next_greater_member(vbm.wptr, vcurr.nint, &next);
1795	if (Result_Is_Empty(result)) {
1796	    Fail
1797	}
1798
1799	Return_Integer(vnext, tnext, next);
1800
1801	Succeed
1802}
1803
1804    /* Returns RES_EMPTY if there is no element larger than curr. */
1805    /* Returns RES_SLACK if next is not curr+1. */
1806word
1807next_greater_member(uword *bitmap, word curr, word *next_ptr)
1808{
1809	uword	*bits_ptr;
1810	uword	bits;
1811	word	low, high, offset, pos;
1812	word	next;
1813
1814	low = Low(bitmap);
1815	high = High(bitmap);
1816	offset = Offset(bitmap);
1817	next = curr - offset + 1;
1818
1819	if (next < 0) {
1820	    /* Avoid division/modulus of a negative number problems. */
1821	    pos = -1;
1822	} else {
1823	    pos = next / BPW;
1824	}
1825
1826	if (pos > high) {
1827	    return RES_EMPTY;
1828	}
1829	if (pos < low) {
1830	    pos = low;
1831	    bits_ptr = Bits(bitmap) + pos;
1832	    bits = *bits_ptr;
1833	} else {
1834	    bits_ptr = Bits(bitmap) + pos;
1835	    bits = *bits_ptr & BitsFrom(next % BPW);
1836	}
1837
1838	while (!bits) {
1839	    if (pos >= high) {
1840		return RES_EMPTY;
1841	    }
1842	    pos++;
1843	    bits_ptr++;
1844	    bits = *bits_ptr;
1845	}
1846
1847	next = pos * BPW + lsb(bits);
1848	next += offset;
1849	*next_ptr = next;
1850
1851	if (next == curr + 1) {
1852	    return 0;
1853	} else {
1854	    /* Skipped a hole. */
1855	    return RES_SLACK;
1856	}
1857}
1858
1859
1860    /*
1861    ** next_smaller_member(+Bitmap, ++Curr, -Next)
1862    **      Return the largest element in Bitmap which is less than Curr.
1863    **      Fails if there is no such element.
1864    */
1865int
1866p_next_smaller_member(value vbm, type tbm, value vcurr, type tcurr, value vnext, type tnext)
1867{
1868	word	next;
1869	word	result;
1870
1871	Check_Bitmap(tbm);
1872	Check_Integer(tcurr);
1873
1874	result = next_smaller_member(vbm.wptr, vcurr.nint, &next);
1875	if (Result_Is_Empty(result)) {
1876	    Fail
1877	}
1878
1879	Return_Integer(vnext, tnext, next);
1880
1881	Succeed
1882}
1883
1884    /* Returns RES_EMPTY if there is no element smaller than curr. */
1885    /* Returns RES_SLACK if next is not curr-1. */
1886word
1887next_smaller_member(uword *bitmap, word curr, word *next_ptr)
1888{
1889	uword	*bits_ptr;
1890	uword	bits;
1891	word	low, high, offset, pos;
1892	word	next;
1893
1894	low = Low(bitmap);
1895	high = High(bitmap);
1896	offset = Offset(bitmap);
1897	next = curr - offset - 1;
1898
1899	if (next < 0) {
1900	    /* Avoid division/modulus of a negative number problems. */
1901	    return RES_EMPTY;
1902	} else {
1903	    pos = next / BPW;
1904	}
1905
1906	if (pos < low) {
1907	    return RES_EMPTY;
1908	}
1909	if (pos > high) {
1910	    pos = high;
1911	    bits_ptr = Bits(bitmap) + pos;
1912	    bits = *bits_ptr;
1913	} else {
1914	    bits_ptr = Bits(bitmap) + pos;
1915	    bits = *bits_ptr & BitsTo(next % BPW);
1916	}
1917
1918	while (!bits) {
1919	    if (pos <= low) {
1920		return RES_EMPTY;
1921	    }
1922	    pos--;
1923	    bits_ptr--;
1924	    bits = *bits_ptr;
1925	}
1926
1927	next = pos * BPW + msb(bits);
1928	next += offset;
1929	*next_ptr = next;
1930
1931	if (next == curr - 1) {
1932	    return 0;
1933	} else {
1934	    /* Skipped a hole. */
1935	    return RES_SLACK;
1936	}
1937}
1938
1939
1940    /*
1941    ** next_greater_non_member(+Bitmap, ++Curr, -Next)
1942    **      Return the smallest element not in Bitmap which is greater than
1943    **      Curr.  Always succeeds.
1944    */
1945int
1946p_next_greater_non_member(value vbm, type tbm, value vcurr, type tcurr, value vnext, type tnext)
1947{
1948	word	next;
1949
1950	Check_Bitmap(tbm);
1951	Check_Integer(tcurr);
1952
1953	next_greater_non_member(vbm.wptr, vcurr.nint, &next);
1954
1955	Return_Integer(vnext, tnext, next);
1956
1957	Succeed
1958}
1959
1960    /* Returns RES_SLACK if next is not curr+1. */
1961word
1962next_greater_non_member(uword *bitmap, word curr, word *next_ptr)
1963{
1964	uword	*bits_ptr;
1965	uword	nobits;
1966	word	low, high, offset, pos;
1967	word	next;
1968
1969	low = Low(bitmap);
1970	high = High(bitmap);
1971	offset = Offset(bitmap);
1972	next = curr - offset + 1;
1973
1974	/* Avoid division/modulus of a negative number problems. */
1975	if (next >= 0) {
1976	    pos = next / BPW;
1977
1978	    if (pos >= low && pos <= high) {
1979		bits_ptr = Bits(bitmap) + pos;
1980		nobits = (~*bits_ptr) & BitsFrom(next % BPW);
1981
1982		while (!nobits) {
1983		    if (pos >= high) {
1984			break;
1985		    }
1986		    pos++;
1987		    bits_ptr++;
1988		    nobits = ~*bits_ptr;
1989		}
1990
1991		next = pos * BPW + lsb(nobits);
1992	    }
1993	}
1994
1995	next += offset;
1996	*next_ptr = next;
1997
1998	if (next == curr + 1) {
1999	    return 0;
2000	} else {
2001	    /* Skipped a member. */
2002	    return RES_SLACK;
2003	}
2004}
2005
2006
2007    /*
2008    ** next_smaller_non_member(+Bitmap, ++Curr, -Next)
2009    **      Return the largest element not in Bitmap which is less than
2010    **      Curr.  Always succeeds.
2011    */
2012int
2013p_next_smaller_non_member(value vbm, type tbm, value vcurr, type tcurr, value vnext, type tnext)
2014{
2015	word	next;
2016
2017	Check_Bitmap(tbm);
2018	Check_Integer(tcurr);
2019
2020	next_smaller_non_member(vbm.wptr, vcurr.nint, &next);
2021
2022	Return_Integer(vnext, tnext, next);
2023
2024	Succeed
2025}
2026
2027    /* Returns RES_SLACK if next is not curr+1. */
2028word
2029next_smaller_non_member(uword *bitmap, word curr, word *next_ptr)
2030{
2031	uword	*bits_ptr;
2032	uword	nobits;
2033	word	low, high, offset, pos;
2034	word	next;
2035
2036	low = Low(bitmap);
2037	high = High(bitmap);
2038	offset = Offset(bitmap);
2039	next = curr - offset - 1;
2040
2041	/* Avoid division/modulus of a negative number problems. */
2042	if (next >= 0) {
2043	    pos = next / BPW;
2044
2045	    if (pos >= low && pos <= high) {
2046		bits_ptr = Bits(bitmap) + pos;
2047		nobits = (~*bits_ptr) & BitsTo(next % BPW);
2048
2049		while (!nobits) {
2050		    if (pos <= low) {
2051			break;
2052		    }
2053		    pos--;
2054		    bits_ptr--;
2055		    nobits = ~*bits_ptr;
2056		}
2057
2058		next = pos * BPW + msb(nobits);
2059	    }
2060	}
2061
2062	next += offset;
2063	*next_ptr = next;
2064
2065	if (next == curr - 1) {
2066	    return 0;
2067	} else {
2068	    /* Skipped a member. */
2069	    return RES_SLACK;
2070	}
2071}
2072
2073
2074    /*
2075    ** bitmap_size(+Bitmap, -Size)
2076    **      Return the number of elements in Bitmap (i.e. number of bits
2077    **      set).  Always succeeds.
2078    */
2079int
2080p_bitmap_size(value vbm, type tbm, value vsize, type tsize)
2081{
2082	word	size;
2083
2084	Check_Bitmap(tbm);
2085
2086	size = bitmap_size(vbm.wptr);
2087
2088	Return_Integer(vsize, tsize, size);
2089
2090	Succeed
2091}
2092
2093word
2094bitmap_size(uword *bitmap)
2095{
2096	uword	*bits_ptr;
2097	word	high, pos;
2098	word	count;
2099
2100	high = High(bitmap);
2101
2102	pos = Low(bitmap);
2103	bits_ptr = Bits(bitmap) + pos;
2104	count = 0;
2105
2106	while (pos <= high) {
2107	    count += bit_count(*bits_ptr);
2108	    pos++;
2109	    bits_ptr++;
2110	}
2111
2112	return count;
2113}
2114
2115
2116    /*
2117    ** bitmap_contains(+Bitmap, ++Elem)
2118    **      Succeeds iff Bitmap contains the element Elem.
2119    */
2120int
2121p_bitmap_contains(value vbm, type tbm, value vel, type tel)
2122{
2123	Check_Bitmap(tbm);
2124	Check_Integer(tel);
2125
2126	return bitmap_contains(vbm.wptr, vel.nint);
2127}
2128
2129word
2130bitmap_contains(uword *bitmap, word el)
2131{
2132	uword	*bits_ptr;
2133	word	low, high, offset, pos;
2134
2135	low = Low(bitmap);
2136	high = High(bitmap);
2137	offset = Offset(bitmap);
2138
2139	el -= offset;
2140	if (el < 0) {
2141	    return PFAIL;
2142	}
2143
2144	pos = el / BPW;
2145
2146	if (pos < low || pos > high) {
2147	    return PFAIL;
2148	} else {
2149	    bits_ptr = Bits(bitmap) + pos;
2150
2151	    return ((*bits_ptr & Bit(el % BPW)) ? PSUCCEED : PFAIL);
2152	}
2153}
2154
2155
2156    /*
2157    ** bitmap_contains_range(+Bitmap, ++Min, ++Max)
2158    **      Succeeds iff Bitmap contains every element from Min to Max,
2159    **      inclusive.
2160    */
2161int
2162p_bitmap_contains_range(value vbm, type tbm, value vmin, type tmin, value vmax, type tmax)
2163{
2164	Check_Bitmap(tbm);
2165	Check_Integer(tmin);
2166	Check_Integer(tmax);
2167
2168	return bitmap_contains_range(vbm.wptr, vmin.nint, vmax.nint);
2169}
2170
2171word
2172bitmap_contains_range(uword *bitmap, word min, word max)
2173{
2174	uword	*bits_ptr;
2175	uword	mask;
2176	word	low, high, offset, pos, limit;
2177
2178	if (max < min) {
2179	    /* Empty range. */
2180	    return PSUCCEED;
2181	}
2182
2183	low = Low(bitmap);
2184	high = High(bitmap);
2185	offset = Offset(bitmap);
2186	min -= offset;
2187	max -= offset;
2188
2189	/* We do this check before division in case min or max are negative. */
2190	if (min < low * BPW || max > high * BPW + BPW - 1) {
2191	    /* Bitmap does not contain range. */
2192	    return PFAIL;
2193	}
2194
2195	pos = min/BPW;
2196	limit = max/BPW;
2197
2198	bits_ptr = Bits(bitmap) + pos;
2199
2200	if (pos == limit) {
2201	    mask = BitsFrom(min % BPW) & BitsTo(max % BPW);
2202	    if ((*bits_ptr & mask) != mask) {
2203		return PFAIL;
2204	    }
2205	} else {
2206	    mask = BitsFrom(min % BPW);
2207	    if ((*bits_ptr & mask) != mask) {
2208		return PFAIL;
2209	    }
2210
2211	    pos++;
2212	    bits_ptr++;
2213
2214	    while (pos < limit) {
2215		if (*bits_ptr != ALLBITS) {
2216		    return PFAIL;
2217		}
2218
2219		pos++;
2220		bits_ptr++;
2221	    }
2222
2223	    mask = BitsTo(max % BPW);
2224	    if ((*bits_ptr & mask) != mask) {
2225		return PFAIL;
2226	    }
2227	}
2228
2229	return PSUCCEED;
2230}
2231
2232
2233    /*
2234    ** compare_bitmaps(?Res, +Bitmap, +Bitmap2)
2235    **      Compares Bitmap and Bitmap2 to see if they are equivalent
2236    **      (Res = (=)), Bitmap is a subset of Bitmap2 (Res = (<)), or
2237    **      Bitmap is a superset of Bitmap2 (Res = (>)).  Fails if none of
2238    **      these conditions are true (the bitmaps are incomparable).
2239    */
2240int
2241p_compare_bitmaps(value vres, type tres, value vbm, type tbm, value vbm2, type tbm2)
2242{
2243	int	res;
2244	dident	result;
2245
2246	Check_Bitmap(tbm);
2247	Check_Bitmap(tbm2);
2248
2249	if (compare_bitmaps(vbm.wptr, vbm2.wptr, &res) == PFAIL) {
2250	    Fail
2251	}
2252
2253	if (res < 0)
2254	    result = d_.inf0;
2255	else if (res > 0)
2256	    result = d_.sup0;
2257	else
2258	    result = d_.unify0;
2259
2260	Return_Unify_Atom(vres, tres, result);
2261}
2262
2263word
2264compare_bitmaps(uword *bitmap, uword *bitmap2, int *res_ptr)
2265{
2266	uword	*bits_ptr;
2267	uword	*bits_ptr2;
2268	uword	bits, bits2;
2269	uword	intersection;
2270	word	low, high, offset;
2271	word	low2, high2, offset2;
2272	word	pos;
2273	word	delta;
2274	int	res;
2275
2276	if (bitmap == bitmap2)
2277	{
2278	    *res_ptr = 0;
2279	    return PSUCCEED;
2280	}
2281
2282	low = Low(bitmap);
2283	high = High(bitmap);
2284	offset = Offset(bitmap);
2285	low2 = Low(bitmap2);
2286	high2 = High(bitmap2);
2287	offset2 = Offset(bitmap2);
2288
2289	/* Add delta to convert an index for bitmap to an index for bitmap2. */
2290	/* This works OK even if offset2 < offset since the division is exact. */
2291	delta = (offset - offset2) / BPW;
2292
2293	if (low + delta < low2) {
2294	    res = 1;
2295	    low = low2 - delta;
2296	} else if (low2 < low + delta) {
2297	    res = -1;
2298	} else {
2299	    res = 0;
2300	}
2301
2302	if (high + delta > high2) {
2303	    if (res < 0) {
2304		return PFAIL;
2305	    }
2306	    res = 1;
2307	    high = high2 - delta;
2308	} else if (high2 > high + delta) {
2309	    if (res > 0) {
2310		return PFAIL;
2311	    }
2312	    res = -1;
2313	}
2314
2315	pos = low;
2316	bits_ptr = Bits(bitmap) + pos;
2317	bits_ptr2 = Bits(bitmap2) + pos + delta;
2318
2319	while (pos <= high) {
2320	    bits = *bits_ptr;
2321	    bits2 = *bits_ptr2;
2322	    intersection = bits & bits2;
2323
2324	    if (intersection != bits) {
2325		/* bits2 is not a superset of or equal to bits. */
2326		if (res < 0) {
2327		    return PFAIL;
2328		}
2329		/* Assume bits is a superset of bits2. */
2330		res = 1;
2331	    }
2332	    if (intersection != bits2) {
2333		/* bits is not a superset of or equal to bits2. */
2334		if (res > 0) {
2335		    return PFAIL;
2336		}
2337		res = -1;
2338	    }
2339
2340	    pos++;
2341	    bits_ptr++;
2342	    bits_ptr2++;
2343	}
2344
2345	*res_ptr = res;
2346	return PSUCCEED;
2347}
2348
2349
2350