| 675 | |
| 676 | template<class I> |
| 677 | forceinline ModEvent |
| 678 | IntVarImp::minus_r(Space& home, I& i, bool depends) { |
| 679 | if (depends) { |
| 680 | IntVarImpFwd j(this); |
| 681 | Iter::Ranges::Diff<IntVarImpFwd,I> ij(j,i); |
| 682 | return narrow_r(home,ij,true); |
| 683 | } |
| 684 | |
| 685 | // Skip all ranges that are too small |
| 686 | while (i() && (i.max() < dom.min())) |
| 687 | ++i; |
| 688 | |
| 689 | // Is there no range left or all are too large? |
| 690 | if (!i() || (i.min() > dom.max())) |
| 691 | return ME_INT_NONE; |
| 692 | |
| 693 | int i_min = i.min(); |
| 694 | int i_max = i.max(); |
| 695 | ++i; |
| 696 | |
| 697 | if ((i_min <= dom.min()) && (i_max >= dom.max())) |
| 698 | return fail(home); |
| 699 | |
| 700 | if ((i_min > dom.min()) && (i_max >= dom.max())) |
| 701 | return lq(home,i_min-1); |
| 702 | |
| 703 | if ((i_min <= dom.min()) && (i_max < dom.max()) && |
| 704 | (!i() || (i.min() > dom.max()))) |
| 705 | return gq(home,i_max+1); |
| 706 | |
| 707 | // Set up two sentinel elements |
| 708 | RangeList f, l; |
| 709 | // Put all ranges between sentinels |
| 710 | if (range()) { |
| 711 | // Create a new rangelist just for simplicity |
| 712 | RangeList* n = new (home) RangeList(min(),max(),&f,&l); |
| 713 | f.prevnext(nullptr,n); l.prevnext(n,nullptr); |
| 714 | } else { |
| 715 | // Link the two sentinel elements |
| 716 | f.prevnext(nullptr,fst()); l.prevnext(lst(),nullptr); |
| 717 | fst()->prev(nullptr,&f); lst()->next(nullptr,&l); |
| 718 | } |
| 719 | |
| 720 | // Number of values removed (potential holes) |
| 721 | unsigned int h = 0; |
| 722 | // The previous range |
| 723 | RangeList* p = &f; |
| 724 | // The current range |
| 725 | RangeList* r = f.next(nullptr); |
| 726 | |
| 727 | while (true) { |
| 728 | assert((r != &f) && (r != &l)); |
| 729 | if (i_min > r->max()) { |
| 730 | RangeList* n=r->next(p); p=r; r=n; |
| 731 | if (r == &l) |
| 732 | break; |
| 733 | } else if (i_max < r->min()) { |
| 734 | if (!i()) |