Skip to content

Commit

Permalink
add some tests, add some interfaces
Browse files Browse the repository at this point in the history
  • Loading branch information
ztellman committed Sep 30, 2016
1 parent ab7aecb commit 5973591
Show file tree
Hide file tree
Showing 9 changed files with 154 additions and 7 deletions.
5 changes: 5 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
39 changes: 39 additions & 0 deletions src/io/lacuna/bifurcan/IList.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package io.lacuna.bifurcan;

import java.util.Iterator;
import java.util.NoSuchElementException;

/**
* @author ztellman
*/
public interface IList<V> {

IList<V> append(V value);

IList<V> set(long idx, V value);

V nth(long idx);

long size();

default Iterator<V> iterator() {
return new Iterator<V>() {

int idx = 0;

@Override
public boolean hasNext() {
return idx < size();
}

@Override
public V next() {
if (hasNext()) {
return nth(++idx);
} else {
throw new NoSuchElementException();
}
}
};
}
}
24 changes: 24 additions & 0 deletions src/io/lacuna/bifurcan/IMap.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package io.lacuna.bifurcan;

/**
* @author ztellman
*/
public interface IMap<K,V> {

interface Entry<K,V> {
K key();
V value();
}

IMap<K,V> put(K key, V value);

IMap<K,V> remove(K key);

V get(K key);

boolean contains(K key);

IList<Entry<K,V>> entries();

long size();
}
17 changes: 17 additions & 0 deletions src/io/lacuna/bifurcan/ISet.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package io.lacuna.bifurcan;

/**
* @author ztellman
*/
public interface ISet<V> {

ISet<V> add(V value);

ISet<V> remove(V value);

boolean contains(V value);

long size();

IList<V> elements();
}
2 changes: 1 addition & 1 deletion src/io/lacuna/bifurcan/utils/BitIntSet.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import java.util.Arrays;

/**
* A series of utility functions that use a bit-vector to store a sorted set of integers with arbitrary bit-lengths.
* A series of utility functions that use a bit-vector to store a sorted set of integers with bit-lengths within [1,64].
*
* @author ztellman
*/
Expand Down
38 changes: 33 additions & 5 deletions src/io/lacuna/bifurcan/utils/BitVector.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package io.lacuna.bifurcan.utils;

import static io.lacuna.bifurcan.utils.Bits.branchingBit;
import static io.lacuna.bifurcan.utils.Bits.maskAbove;
import static io.lacuna.bifurcan.utils.Bits.maskBelow;

/**
Expand All @@ -18,16 +20,16 @@ public static long[] create(int length) {
}

/**
* @param bitsPerVector the number of significant bits in vector
* @param vectors a list of bit-vectors
* @param bitLen the number of significant bits in each vector
* @param vectors a list of bit-vectors
* @return the bit-wise interleaving of the values, starting with the topmost bit of the 0th vector, followed by the
* topmost bit of the 1st vector, and downward from there
*/
public static long[] interleave(int bitsPerVector, long[] vectors) {
long[] interleaved = create(bitsPerVector * vectors.length);
public static long[] interleave(int bitLen, long[] vectors) {
long[] interleaved = create(bitLen * vectors.length);

int offset = (interleaved.length << 6) - 1;
for (int i = 0; i < bitsPerVector; i++) {
for (int i = 0; i < bitLen; i++) {
long mask = 1L << i;

for (int j = vectors.length - 1; j >= 0; j--) {
Expand All @@ -40,6 +42,32 @@ public static long[] interleave(int bitsPerVector, long[] vectors) {
return interleaved;
}

public static int branchingBit(long[] a, long[] b, int aIdx, int bIdx, int bitOffset, int bitLen) {
long mask = maskAbove(bitOffset & 63);
int branch = Bits.branchingBit(a[aIdx] & mask, b[bIdx] & mask);

if (branch >= 0) {
return branch;
}

aIdx++;
bIdx++;

int branchIdx = 64 - bitOffset;
int len = ((bitLen - (bitOffset + 1)) >> 6) + 1;

for (int i = 0; i < len; i++) {
branch = Bits.branchingBit(a[aIdx + i], b[bIdx + 1]);
if (branch >= 0) {
return branchIdx + branch;
} else {
branchIdx += 64;
}
}

return branchIdx > bitLen ? -1 : branchIdx;
}

/**
* Reads a bit range from the vector, which cannot be longer than 64 bits.
*
Expand Down
6 changes: 5 additions & 1 deletion src/io/lacuna/bifurcan/utils/Bits.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,11 @@ public static long maskAbove(int bits) {
}

public static int branchingBit(long a, long b) {
return bitLog2(highestBit(a ^ b, 1));
if (a == b) {
return -1;
} else {
return bitLog2(highestBit(a ^ b, 1));
}
}

}
1 change: 1 addition & 0 deletions test/bifurcan/bit_vector_test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
[java.util
ArrayList]
[io.lacuna.bifurcan.utils
Bits
BitVector]))

;;;
Expand Down
29 changes: 29 additions & 0 deletions test/bifurcan/bits_test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
[clojure.test.check.clojure-test :as ct :refer (defspec)])
(:import
[io.lacuna.bifurcan.utils
Bits
BitVector]))

(defn ->binary-string [x]
Expand All @@ -23,6 +24,30 @@
(apply interleave)
(apply str)))

(defn branching-bit [a b]
(let [bit (->> [(->> a ->binary-string (apply str))
(->> b ->binary-string (apply str))]
(apply map
(fn [index a b]
(when (not= a b)
index))
(range))
(remove nil?)
first)]
(if bit
(- 63 bit)
-1)))

#_(defspec branching-bit-vector-equivalence 1e4
(prop/for-all [[a b] (->> gen/large-integer
(repeat 3)
(apply gen/tuple)
(repeat 2)
(apply gen/tuple))
offset (gen/choose 0 64)
len (gen/choose 0 128)]
))

(defspec interleave-roundtrip 1e4
(prop/for-all [a (gen/resize Short/MAX_VALUE gen/pos-int)
b (gen/resize Short/MAX_VALUE gen/pos-int)]
Expand All @@ -32,3 +57,7 @@
(apply str)
(take-last 32)
(apply str)))))

(defspec branching-bit-equivalence 1e4
(prop/for-all [a gen/large-integer, b gen/large-integer]
(= (branching-bit a b) (Bits/branchingBit a b))))

0 comments on commit 5973591

Please sign in to comment.