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