| 846 | |
| 847 | template<class I> |
| 848 | forceinline ModEvent |
| 849 | IntVarImp::minus_v(Space& home, I& i, bool depends) { |
| 850 | if (depends) { |
| 851 | Iter::Values::ToRanges<I> r(i); |
| 852 | return minus_r(home, r, true); |
| 853 | } |
| 854 | |
| 855 | // Skip all values that are too small |
| 856 | while (i() && (i.val() < dom.min())) |
| 857 | ++i; |
| 858 | |
| 859 | // Is there no value left or all are too large? |
| 860 | if (!i() || (i.val() > dom.max())) |
| 861 | return ME_INT_NONE; |
| 862 | |
| 863 | int v = i.val(); |
| 864 | // Skip values that are the same |
| 865 | do { |
| 866 | ++i; |
| 867 | } while (i() && (i.val() == v)); |
| 868 | |
| 869 | // Is there only a single value to be pruned? |
| 870 | if (!i() || (i.val() > dom.max())) |
| 871 | return nq_full(home,v); |
| 872 | |
| 873 | // Set up two sentinel elements |
| 874 | RangeList f, l; |
| 875 | // Put all ranges between sentinels |
| 876 | if (range()) { |
| 877 | // Create a new rangelist just for simplicity |
| 878 | RangeList* n = new (home) RangeList(min(),max(),&f,&l); |
| 879 | f.prevnext(nullptr,n); l.prevnext(n,nullptr); |
| 880 | } else { |
| 881 | // Link the two sentinel elements |
| 882 | f.prevnext(nullptr,fst()); l.prevnext(lst(),nullptr); |
| 883 | fst()->prev(nullptr,&f); lst()->next(nullptr,&l); |
| 884 | } |
| 885 | |
| 886 | // Number of values removed (potential holes) |
| 887 | unsigned int h = 0; |
| 888 | // The previous range |
| 889 | RangeList* p = &f; |
| 890 | // The current range |
| 891 | RangeList* r = f.next(nullptr); |
| 892 | |
| 893 | while (true) { |
| 894 | assert((r != &f) && (r != &l)); |
| 895 | if (v > r->max()) { |
| 896 | // Move to next range |
| 897 | RangeList* n=r->next(p); p=r; r=n; |
| 898 | if (r == &l) |
| 899 | break; |
| 900 | } else { |
| 901 | if ((v == r->min()) && (v == r->max())) { |
| 902 | // Remove range |
| 903 | h++; |
| 904 | RangeList* n=r->next(p); |
| 905 | p->next(r,n); n->prev(r,p); |