aa
IBitSet.java
Go to the documentation of this file.
1 package com.cliffc.aa.util;
2 
3 import org.jetbrains.annotations.NotNull;
4 
5 import java.util.Iterator;
6 
7 // Standard bit-set but supports the notion of an 'infinite extension' of 1.
8 // i.e. all bits past the end are either 0 or 1.
9 // Supports update-in-place, mutable, NOT hash-consed
10 public class IBitSet implements Iterable<Integer> {
11  private boolean _sign; // false=infinite zeros, true=infinite ones
12  private final AryInt _bits = new AryInt();
13 
14  // Since mutable, please do not mutate these
15  public static final IBitSet EMPTY = new IBitSet();
16  public static final IBitSet FULL = new IBitSet().flip();
17 
18  private static int idx (int i) { return i>>5; }
19  private static int mask(int i) { return 1<<(i&31); }
20 
21  // Test; returns the value
22  public boolean tst(int idx) { return _sign != _tst(idx); }
23  private boolean _tst(int idx) { return (_bits.atX(idx(idx)) & mask(idx)) != 0; }
24 
25  // Test and set; returns the old value
26  public boolean set(int idx) { return _sign ? !_clr(idx) : _set(idx); }
27  public boolean clr(int idx) { return _sign ? !_set(idx) : _clr(idx); }
28 
29  private boolean _set(int idx) {
30  int widx = idx (idx);
31  int mask = mask(idx);
32  int bits = _bits.atX(widx);
33  _bits.setX(widx, bits | mask);
34  return (bits&mask)!=0;
35  }
36  private boolean _clr(int idx) {
37  int widx = idx (idx);
38  int mask = mask(idx);
39  int bits = _bits.atX(widx);
40  _bits.setX(widx, bits & ~mask);
41  while( _bits._len>0 && _bits.last()==0 ) _bits.pop(); // Shrink
42  return (bits&mask)!=0;
43  }
44  // Constant-time, invert all bits
45  public IBitSet flip() { _sign=!_sign; return this; }
46 
47  public int bitCount() {
48  assert !_sign; // Infinite if sign is set
49  int sum=0;
50  for( int i=0; i<_bits._len; i++ )
51  sum += Integer.bitCount(_bits._es[i]);
52  return sum;
53  }
54  public int max( ) {
55  assert !_sign; // Infinite if sign is set
56  if( _bits._len==0 ) return 0;
57  return (31 - Integer.numberOfLeadingZeros(_bits.last()))+((_bits._len-1)<<5);
58  }
59 
60  private int wd(int x) { return _bits._es[x]; }
61  private int xd(int x) {
62  int b = _bits.atX(x); // zero extend if off end
63  return _sign ? ~b : b;// adjust for sign
64  }
65 
66  public IBitSet clear() {
67  _sign=false;
68  _bits.clear();
69  return this;
70  }
71 
72  // OR-into-this
73  public IBitSet or( IBitSet bs ) {
74  _sign |= bs._sign;
75  for( int i=0; i<bs._bits._len; i++ )
76  _bits.setX(i,_bits.atX(i)|bs.wd(i));
77  return this;
78  }
79  // SUBTRACT-from-this
80  public void subtract( IBitSet bs ) {
81  for( int i=0; i<bs._bits._len; i++ )
82  _bits.setX(i,_bits.atX(i)&~bs.wd(i));
83  }
84  // True if set is empty. The flipped set is never empty.
85  public boolean is_empty() { return _bits._len==0 && !_sign; }
86 
87  // False if any bits in common
88  public boolean disjoint( IBitSet bs ) {
89  if( is_empty() ) return true; // Empty set must be disjoint
90  if( bs.is_empty() ) return true; // Empty set must be disjoint
91  if( _sign && bs._sign ) return false; // Both extensions are set
92  IBitSet min = this;
93  if( _bits._len > bs._bits._len ) { min=bs; bs=this; } // max in bs
94  if( min._sign && min._bits._len < bs._bits._len ) return false; // Extension in min overlaps last bits in max
95  for( int i=0; i<min._bits._len; i++ )
96  if( (min.wd(i)&bs.wd(i))!= 0 )
97  return false;
98  return true;
99  }
100 
101  // Does 'this' subset 'bs'?
102  // True if all bits in common: "bs== this.OR (bs)".
103  public boolean subsetsX( IBitSet bs ) {
104  assert !bs.is_empty(); // Undefined
105  int max=Math.max(_bits._len,bs._bits._len);
106  for( int i=0; i<max; i++ )
107  if( (xd(i)|bs.xd(i)) != bs.xd(i) ) // All bits in common
108  return false;
109  return true;
110  }
111 
112  @Override public String toString() { return toString(new SB()).toString(); }
113  public SB toString(SB sb) {
114  if( _bits._len==0 ) return sb.p(_sign?"[...]":"[]");
115  int x = -1; // No range-in-process
116  sb.p('[');
117  for( int i=0; i<_bits._len*32+1; i++ ) {
118  if( tst(i) ) {
119  if( x==-1 ) x=i; // Start a range
120  } else {
121  if( x!=-1 ) { // End a range
122  if( x+1==i ) sb.p(x).p(',');
123  else if( x+2==i ) sb.p(x).p(',').p(i-1).p(',');
124  else sb.p(x).p("...").p(i-1).p(',');
125  x = -1;
126  }
127  }
128  }
129  if( x != -1 ) sb.p(x).p("...,"); // Close open range
130  return sb.unchar().p(']');
131  }
132 
134  @NotNull @Override public Iterator<Integer> iterator() { return new Iter(); }
135  private class Iter implements Iterator<Integer> {
136  int _i=-1;
137  @Override public boolean hasNext() {
138  int idx;
139  while( (idx=idx(++_i)) < _bits._len )
140  if( (_bits._es[idx]&mask(_i)) != 0 )
141  return true;
142  return false;
143  }
144  @Override public Integer next() {
145  if( idx(_i) < _bits._len ) return _i;
146  throw new java.util.NoSuchElementException();
147  }
148  }
149 }
com.cliffc.aa.util.IBitSet.subtract
void subtract(IBitSet bs)
Definition: IBitSet.java:80
com.cliffc.aa.util.AryInt.atX
int atX(int i)
Definition: AryInt.java:27
com.cliffc.aa.util.IBitSet.clr
boolean clr(int idx)
Definition: IBitSet.java:27
com.cliffc.aa.util.IBitSet.max
int max()
Definition: IBitSet.java:54
com.cliffc.aa.util.IBitSet.Iter.next
Integer next()
Definition: IBitSet.java:144
com.cliffc.aa.util.IBitSet._set
boolean _set(int idx)
Definition: IBitSet.java:29
com.cliffc.aa.util.IBitSet.Iter.hasNext
boolean hasNext()
Definition: IBitSet.java:137
com.cliffc.aa.util.IBitSet.clear
IBitSet clear()
Definition: IBitSet.java:66
com.cliffc.aa.util.IBitSet.is_empty
boolean is_empty()
Definition: IBitSet.java:85
com.cliffc.aa.util.IBitSet.flip
IBitSet flip()
Definition: IBitSet.java:45
com.cliffc.aa.util.IBitSet.Iter._i
int _i
Definition: IBitSet.java:136
com.cliffc.aa.util.IBitSet.mask
static int mask(int i)
Definition: IBitSet.java:19
com.cliffc.aa.util.IBitSet
Definition: IBitSet.java:10
com.cliffc.aa.util.IBitSet._clr
boolean _clr(int idx)
Definition: IBitSet.java:36
com.cliffc.aa.util.SB.unchar
SB unchar()
Definition: SB.java:58
Iterable
com.cliffc.aa.util.IBitSet.xd
int xd(int x)
Definition: IBitSet.java:61
com.cliffc.aa.util.IBitSet.disjoint
boolean disjoint(IBitSet bs)
Definition: IBitSet.java:88
com.cliffc.aa.util.IBitSet.wd
int wd(int x)
Definition: IBitSet.java:60
com.cliffc.aa.util.IBitSet.tst
boolean tst(int idx)
Definition: IBitSet.java:22
com.cliffc.aa.util.AryInt.pop
int pop()
Definition: AryInt.java:37
com.cliffc.aa.util.IBitSet.idx
static int idx(int i)
Definition: IBitSet.java:18
com.cliffc.aa.util.AryInt._es
int[] _es
Definition: AryInt.java:9
com.cliffc.aa.util.IBitSet._sign
boolean _sign
Definition: IBitSet.java:11
com.cliffc.aa.util.SB
Tight/tiny StringBuilder wrapper.
Definition: SB.java:8
com.cliffc.aa.util.IBitSet.iterator
Iterator< Integer > iterator()
Definition: IBitSet.java:134
com.cliffc.aa.util.IBitSet._tst
boolean _tst(int idx)
Definition: IBitSet.java:23
com.cliffc.aa.util.IBitSet.toString
String toString()
Definition: IBitSet.java:112
com.cliffc.aa.util.AryInt.last
int last()
Definition: AryInt.java:31
com.cliffc.aa.util.IBitSet._bits
final AryInt _bits
Definition: IBitSet.java:12
com.cliffc.aa.util.SB.p
SB p(String s)
Definition: SB.java:13
com.cliffc.aa.util.AryInt.clear
void clear()
Remove all elements.
Definition: AryInt.java:84
com.cliffc.aa.util.IBitSet.Iter
Definition: IBitSet.java:135
com.cliffc.aa.util.IBitSet.subsetsX
boolean subsetsX(IBitSet bs)
Definition: IBitSet.java:103
com.cliffc.aa.util.IBitSet.EMPTY
static final IBitSet EMPTY
Definition: IBitSet.java:15
com.cliffc.aa.util.AryInt.setX
int setX(int i, int e)
Definition: AryInt.java:87
com.cliffc.aa.util.IBitSet.or
IBitSet or(IBitSet bs)
Definition: IBitSet.java:73
com.cliffc.aa.util.AryInt
Definition: AryInt.java:8
com.cliffc.aa.util.AryInt._len
int _len
Definition: AryInt.java:10
com.cliffc.aa.util.IBitSet.FULL
static final IBitSet FULL
Definition: IBitSet.java:16
com.cliffc.aa.util.IBitSet.bitCount
int bitCount()
Definition: IBitSet.java:47
com.cliffc.aa.util.IBitSet.toString
SB toString(SB sb)
Definition: IBitSet.java:113