forked from functionaljava/functionaljava
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathBitSet.java
More file actions
204 lines (165 loc) · 5.59 KB
/
BitSet.java
File metadata and controls
204 lines (165 loc) · 5.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
package fj.data.hamt;
import fj.Equal;
import fj.F2;
import fj.Monoid;
import fj.Show;
import fj.data.List;
import fj.data.Stream;
/**
* A sequence of bits representing a value. The most significant bit (the
* bit with the highest value) is the leftmost bit and has the highest index.
* For example, the BitSet("1011") represents the decimal number 11 and has
* indices [3, 0] inclusive where the bit with the lowest value has the lowest
* index and is the rightmost bit.
*
* Created by maperr on 31/05/2016.
*/
public final class BitSet {
public static final int TRUE_BIT = 1;
public static final int FALSE_BIT = 0;
public static final BitSet EMPTY = new BitSet(FALSE_BIT);
public static final long BASE_LONG = 1L;
public static final int MAX_BIT_SIZE = Long.SIZE;
public static final int MAX_BIT_INDEX = Long.SIZE - 1;
private final long value;
private BitSet(final long l) {
value = l;
}
public static BitSet empty() {
return EMPTY;
}
public static BitSet longBitSet(final long l) {
return new BitSet(l);
}
public static BitSet listBitSet(final List<Boolean> list) {
final int n = list.length();
if (n > MAX_BIT_SIZE) {
throw new IllegalArgumentException("Does not support lists greater than " + MAX_BIT_SIZE + " bits, actual size is " + n);
}
long result = 0;
for (Boolean b: list) {
result = (result << 1) | toInt(b);
}
return longBitSet(result);
}
public static BitSet streamBitSet(final Stream<Boolean> s) {
return listBitSet(s.toList());
}
public static BitSet stringBitSet(final String s) {
return streamBitSet(Stream.fromString(s).map(BitSet::toBoolean));
}
public boolean isSet(final int index) {
return (value & (BASE_LONG << index)) != 0;
}
public boolean isEmpty() {
return value == 0;
}
public BitSet set(final int index) {
return longBitSet(value | (BASE_LONG << index));
}
public BitSet set(final int index, boolean b) {
return b ? set(index) : clear(index);
}
public BitSet clear(final int index) {
return longBitSet(value & ~(BASE_LONG << index));
}
public long longValue() {
return value;
}
public BitSet and(final BitSet bs) {
return longBitSet(value & bs.longValue());
}
public BitSet or(final BitSet bs) {
return longBitSet(value | bs.longValue());
}
public BitSet shiftRight(final int n) {
return longBitSet(value >> n);
}
public BitSet shiftLeft(final int n) {
return longBitSet(value << n);
}
public int bitsUsed() {
return toStream().length();
}
public int bitsOn() {
return toStream().foldLeft((acc, b) -> acc + (b ? 1 : 0), 0);
}
/**
* Returns a stream of boolean where the head is the most significant bit
* (the bit with the largest value)
*/
public Stream<Boolean> toStream() {
return Stream.fromString(Long.toBinaryString(value)).map(BitSet::toBoolean).dropWhile(b -> !b);
}
@Override
public String toString() {
return Show.bitSetShow.showS(this);
}
@Override
public boolean equals(Object obj) {
return Equal.equals0(BitSet.class, this, obj, Equal.bitSetSequal);
}
public int bitsToRight(final int index) {
if (index >= MAX_BIT_SIZE) {
throw new IllegalArgumentException("Does not support an index " +
"greater than or equal to " + MAX_BIT_SIZE + " bits, actual argument is " + index);
}
int pos = index - 1;
long mask = BASE_LONG << (pos);
int result = 0;
while (pos >= 0) {
if ((mask & value) != 0) {
result++;
}
mask = mask >> 1;
pos--;
}
return result;
}
public List<Boolean> toList() {
return toStream().toList();
}
public <A> A foldRight(final F2<Boolean, A, A> f, A acc) {
return toStream().foldRight(b -> p -> f.f(b, p._1()), acc);
}
public <A> A foldLeft(final F2<A, Boolean, A> f, A acc) {
return toStream().foldLeft(f, acc);
}
public BitSet xor(final BitSet bs) {
return longBitSet(value ^ bs.longValue());
}
public BitSet not() {
return longBitSet(~value);
}
public BitSet takeLower(final int n) {
return streamBitSet(toStream().reverse().take(n).reverse());
}
public BitSet takeUpper(final int n) {
String zero = Integer.toString(FALSE_BIT);
String current = asString();
String pad = Monoid.stringMonoid.sumLeft(List.replicate(MAX_BIT_SIZE - current.length(), zero));
return stringBitSet(pad + current.substring(0, Math.max(n - pad.length(), 0)));
}
/**
* Returns the bit set from indices in the range from low (inclusive)
* to high(exclusive) from the least significant bit (on the right),
* e.g. "101101".range(1, 4) == "0110"
*/
public BitSet range(final int highIndex, final int lowIndex) {
int max = Math.max(lowIndex, highIndex);
int min = Math.min(lowIndex, highIndex);
return new BitSet(max == min ? 0L : (value << (64 - max)) >>> (64 - max + min));
}
public static boolean toBoolean(final char c) {
return c != '0';
}
public static boolean toBoolean(final int i) {
return i != FALSE_BIT;
}
public static int toInt(final boolean b) {
return b ? TRUE_BIT : FALSE_BIT;
}
public String asString() {
return Long.toBinaryString(value);
}
}