Skip to content

Commit b831ea4

Browse files
committed
Initial commit
1 parent 5930e56 commit b831ea4

210 files changed

Lines changed: 16394 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package azuretriple.primitivecontainer;
2+
3+
import static azuretriple.primitivecontainer.BitSet.major;
4+
import static azuretriple.primitivecontainer.BitSet.mask;
5+
6+
/** A bit set backed by a {@code long} array. */
7+
public abstract class ArrayBitSet implements BitSet
8+
{
9+
/** @return The backing array. Changes to this array affect the set. */
10+
public abstract long[] data();
11+
abstract void sizeLogic(final int major);
12+
13+
@Override
14+
public void set(final int v)
15+
{
16+
final int major = major(v);
17+
sizeLogic(major);
18+
data()[major] |= mask(v);
19+
}
20+
@Override
21+
public void unset(final int v)
22+
{
23+
final int major = major(v);
24+
if(major >= data().length) return;
25+
data()[major] &= ~mask(v);
26+
}
27+
@Override
28+
public boolean add(final int v)
29+
{
30+
final int major = major(v);
31+
sizeLogic(major);
32+
return data()[major] != (data()[major] |= mask(v));
33+
}
34+
@Override
35+
public boolean remove(final int v)
36+
{
37+
final int major = major(v);
38+
if(major >= data().length) return false;
39+
final long mask = mask(v);
40+
final boolean out = (data()[major] & mask) != 0L;
41+
data()[major] &= ~mask;
42+
return out;
43+
}
44+
@Override
45+
public boolean test(final int v)
46+
{
47+
final int major = major(v);
48+
return major < data().length && (data()[major] & mask(v)) != 0L;
49+
}
50+
51+
@Override
52+
public boolean equals(final Object obj)
53+
{
54+
return obj instanceof final BitSet b && BitSet.equals(this,b);
55+
}
56+
57+
@Override public abstract ArrayBitSet clone();
58+
}
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
package azuretriple.primitivecontainer;
2+
3+
/** A set which stores bit-packed boolean values. */
4+
public interface BitSet extends Cloneable
5+
{
6+
static int major(final int v) {return v >>> 6;}
7+
static long mask(final int v) {return 1L << (v & ((1 << 6) - 1));}
8+
9+
static boolean equals(final BitSet a,final BitSet b)
10+
{
11+
if(a == b) return true;
12+
final boolean f1 = a instanceof ArrayBitSet,
13+
f2 = b instanceof ArrayBitSet;
14+
if(f1 && f2) // Both sets are backed by an array.
15+
{
16+
final boolean g1 = a instanceof GrowableBitSet,
17+
g2 = b instanceof GrowableBitSet;
18+
// The logic can be simplified for two growable bit sets since their exact sizes are tracked.
19+
if(g1 && g2)
20+
{
21+
final GrowableBitSet ga = (GrowableBitSet)a,
22+
gb = (GrowableBitSet)b;
23+
// If the index of the highest non-zero values of both sets differ, then the sets are
24+
// obviously not equal.
25+
if(ga.highest != gb.highest) return false;
26+
final long[] da = ga.set,db = gb.set;
27+
// Iterate through both sets, returning false if any values differ.
28+
for(int i = 0;i <= ga.highest;++i) if(da[i] != db[i]) return false;
29+
return true;
30+
}
31+
// Get the data and lengths such that (||*a|| < ||*b||).
32+
final int la,lb;
33+
final long[] da,db;
34+
{
35+
final ArrayBitSet a1 = (ArrayBitSet)a,
36+
b1 = (ArrayBitSet)b;
37+
final int al = g1? ((GrowableBitSet)a1).highest + 1 : a1.data().length,
38+
bl = g2? ((GrowableBitSet)b1).highest + 1 : b1.data().length;
39+
if(al < bl)
40+
{
41+
// If the larger set is growable, that guarantees there is a value outside the smaller
42+
// set since the growable set tracks its size to the last value.
43+
if(g2) return false;
44+
la = al;
45+
lb = bl;
46+
da = a1.data();
47+
db = b1.data();
48+
}
49+
else
50+
{
51+
// ^^^ ditto
52+
if(g1 && al != bl) return false;
53+
la = bl;
54+
lb = al;
55+
da = b1.data();
56+
db = a1.data();
57+
}
58+
}
59+
int bi = 0;
60+
// Iterate through the smaller set, returning false if the corresponding value in the larger
61+
// set does not match.
62+
for(int ai = 0;ai < la;++ai,++bi) if(da[ai] != db[bi]) return false;
63+
// Iterate through the remainder of the larger set, returning false if any values are non-zero.
64+
while(bi < lb) if(db[bi++] != 0L) return false;
65+
return true;
66+
}
67+
if(f1 == f2) // Both sets are backed by a map.
68+
{
69+
final MapBitSet ma = (MapBitSet)a,mb = (MapBitSet)b;
70+
return ma.keys.equals(mb.keys) && ma.values.equals(mb.values);
71+
}
72+
final ArrayBitSet sa;
73+
final MapBitSet sb;
74+
if(f1)
75+
{
76+
sa = (ArrayBitSet)a;
77+
sb = (MapBitSet)b;
78+
}
79+
else
80+
{
81+
sa = (ArrayBitSet)b;
82+
sb = (MapBitSet)a;
83+
}
84+
final IntList k = sb.keys.data();
85+
final long[] data = sa.data();
86+
final int al = sa instanceof final GrowableBitSet g? g.highest+1 : data.length,
87+
bl = k.size();
88+
// If 'sb' is empty, ensure that 'sa' is too.
89+
if(bl == 0) {for(int i = 0;i < al;++i) if(data[i] != 0L) return false;}
90+
else
91+
{
92+
final int[] kd = k.data();
93+
// There is guaranteed to be at least one value outside 'sa' if size of its array is less than the
94+
// last key in 'sb'.
95+
if(al < kd[bl-1]+1) return false;
96+
final long[] v = sb.values.data();
97+
int ai = 0;
98+
for(int bi = 0;bi < bl;++bi)
99+
{
100+
// Iterate through all values in 'sa' between the previous and current key of 'sb', returning if
101+
// any are non-zero.
102+
while(ai < kd[bi]) if(data[ai++] != 0L) return false;
103+
// The value at the current key in both sets must match.
104+
if(data[ai++] != v[bi]) return false;
105+
}
106+
// All remaining values in 'sa' must be zero.
107+
while(ai < al) if(data[ai++] != 0L) return false;
108+
}
109+
return true;
110+
}
111+
112+
/** Sets the bit at the position specified by the argument. */
113+
void set(final int v);
114+
/** Clears the bit at the position specified by the argument. */
115+
void unset(final int v);
116+
/**
117+
* Sets the bit at the position specified by the argument.
118+
* @return {@code true} iff the set changed as a result of calling this function.
119+
*/
120+
boolean add(final int v);
121+
/**
122+
* Clears the bit at the position specified by the argument.
123+
* @return {@code true} iff the set changed as a result of calling this function.
124+
*/
125+
boolean remove(final int v);
126+
/** @return {@code true} iff the bit at the position specified by the argument is set. */
127+
boolean test(final int v);
128+
/** Clears all bits in this set. */
129+
void clear();
130+
131+
BitSet clone();
132+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package azuretriple.primitivecontainer;
2+
3+
/** A container which holds {@code byte}s. */
4+
public interface ByteContainer extends PrimitiveContainer
5+
{
6+
/** @return The backing array. Changes to this array affect the container. */
7+
default byte[] data() {return (byte[])((Container)this).arr;}
8+
/** @return A copy of all the values in this container in order. */
9+
default byte[] array() {return (byte[])((Container)this).arrayImpl();}
10+
11+
@Override ByteContainer clone();
12+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package azuretriple.primitivecontainer;
2+
3+
/** A list containing {@code byte}s. */
4+
public interface ByteList extends ByteContainer
5+
{
6+
/** @return {@code true} iff this list contains the same data as the argument. */
7+
default boolean equals(final ByteList other)
8+
{
9+
if(this == other) return true;
10+
final int s1 = ((List)this).size;
11+
if(s1 != ((List)other).size) return false;
12+
final byte[] d1 = data(),d2 = other.data();
13+
for(int i = 0;i < s1;++i) if(d1[i] != d2[i]) return false;
14+
return true;
15+
}
16+
17+
/** @return The value at the location specified by the argument. */
18+
default byte get(final int location)
19+
{
20+
// Could throw out-of-bounds, but that would mean a branch on a potential hot path.
21+
assert location < ((List)this).size;
22+
23+
return data()[location];
24+
}
25+
/** Sets the value at the specified location to the second argument. */
26+
default void set(final int location,final byte v)
27+
{
28+
// Could throw out-of-bounds, but that would mean a branch on a potential hot path.
29+
assert location < ((List)this).size;
30+
31+
data()[location] = v;
32+
}
33+
34+
/** Appends the values in the argument to the end of the list. */
35+
default void add(final byte[] v) {((List)this).add(v);}
36+
/** Appends the argument to the end of the list. */
37+
default void add(final byte v) {((List)this).addLogic(); data()[((List)this).size++] = v;}
38+
/** Inserts the specified values immediately before the specified location. */
39+
default void insert(final int location,final byte[] v) {((List)this).insert(location,v);}
40+
/** Inserts the specified value immediately before the specified location. */
41+
default void insert(final int location,final byte v) {((List)this).insertLogic(location); data()[location] = v;}
42+
/** Removes the last value from the list. */
43+
void delete();
44+
/** Removes the value at the specified location from the list. */
45+
void remove(final int location);
46+
/** Removes and returns the last value from the list. */
47+
default byte pop() {delete(); return data()[((List)this).size];}
48+
/** Removes and returns the value at the specified location from the list. */
49+
default byte extract(final int location) {final byte o = data()[location]; remove(location); return o;}
50+
51+
@Override ByteList clone();
52+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package azuretriple.primitivecontainer;
2+
3+
/** A queue containing {@code byte}s. */
4+
public interface ByteQueue extends ByteContainer
5+
{
6+
/** @return {@code true} iff this queue contains the same data as the argument. */
7+
default boolean equals(final ByteQueue other)
8+
{
9+
if(this == other) return true;
10+
final int s1 = size();
11+
if(s1 != other.size()) return false;
12+
final int l1 = data().length,l2 = other.data().length;
13+
for(int i = 0,a = ((Queue)this).start,b = ((Queue)other).start;i != s1;++i,a = (a+1)%l1,b = (b+1)%l2)
14+
if(data()[a] != other.data()[b])
15+
return false;
16+
return true;
17+
}
18+
19+
/** Appends the values in the argument to the queue. */
20+
default void push(final byte[] v) {((Queue)this).push(v);}
21+
/** Appends the value to the queue. */
22+
default void push(final byte v) {((Queue)this).pushLogic(); data()[((Queue)this).end++] = v;}
23+
/** Removes the value at the front of the queue. */
24+
void delete();
25+
/** Removes and returns the value from the front of the queue. */
26+
default byte pop() {final byte o = data()[((Queue)this).start]; delete(); return o;}
27+
/** @return The value at the front (i.e. least recently pushed value) of the queue. */
28+
default byte front() {assert !empty(); return data()[((Queue)this).start];}
29+
/** @return The value at the back (i.e. most recently pushed value) of the queue. */
30+
default byte back() {assert !empty(); return data()[((Queue)this).end-1];}
31+
32+
@Override ByteQueue clone();
33+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package azuretriple.primitivecontainer;
2+
3+
/** A set containing {@code byte}s. */
4+
public record ByteSet(OrderedByteList data) implements Cloneable
5+
{
6+
/** Creates a copy of the argument. */
7+
@SuppressWarnings("CopyConstructorMissesField")
8+
public ByteSet(final ByteSet other) {this(new OrderedByteList(other.data));}
9+
10+
/**
11+
* Adds the value to the set.
12+
* @return The index in the backing list where the value was inserted, or the inverted
13+
* index of the existing element if it already exists in the set.
14+
*/
15+
public int add(final byte v)
16+
{
17+
final int i = data.find(v);
18+
if(i >= 0) data.list.insert(i,v);
19+
return i;
20+
}
21+
/**
22+
* Removes the value from the set.
23+
* @return The index in the backing list where the value was removed, or the inverted
24+
* index where the element would have been removed if it was not in the set.
25+
*/
26+
public int remove(final byte v)
27+
{
28+
final int i = ~data.find(v);
29+
if(i >= 0) data.list.remove(i);
30+
return i;
31+
}
32+
/** @return {@code true} iff the value exists in the set. */
33+
public boolean contains(final byte v) {return data.find(v) < 0;}
34+
35+
@SuppressWarnings("MethodDoesntCallSuperMethod")
36+
@Override public ByteSet clone() {return new ByteSet(this);}
37+
}

0 commit comments

Comments
 (0)