Skip to content

Commit

Permalink
Allow users to set null values
Browse files Browse the repository at this point in the history
Let the user specify a null value for a sparse hypercube. Some people
might prefer zeroes to NaNs.
  • Loading branch information
iamsrp-deshaw committed Aug 16, 2024
1 parent 830b190 commit edebef1
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 74 deletions.
43 changes: 28 additions & 15 deletions java/src/main/java/com/deshaw/hypercube/DoubleSparseHypercube.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,14 @@ public class DoubleSparseHypercube
extends AbstractDoubleHypercube
{
/**
* The primitive null value as a long.
* The map which we use to store the values.
*/
private static final long NULL = double2long(Double.NaN);
private final LongToLongConcurrentCuckooHashMap myMap;

/**
* The map which we use to store the values.
* The {@code double} null value as a {@code long}.
*/
private final LongToLongConcurrentCuckooHashMap myMap;
private final long myNull;

// ----------------------------------------------------------------------

Expand Down Expand Up @@ -99,30 +99,43 @@ private static long long2long(final long v)
// ----------------------------------------------------------------------

/**
* Constructor with a default loading of {@code 0.1}.
* Constructor with a default {@code null} value, and a loading of
* {@code 0.1}.
*/
public DoubleSparseHypercube(final Dimension<?>[] dimensions)
throws IllegalArgumentException,
NullPointerException
{
this(dimensions, 0.1);
this(dimensions, Double.NaN, 0.1);
}

/**
* Constructor with a given loading.
* Constructor with a given {@code null} value and loading.
*
* @param nullValue The value used to for missing entries.
* @param loading The value used to determine the initial backing space
* capacity as a function of the logical size of the
* hypercube.
*/
public DoubleSparseHypercube(final Dimension<?>[] dimensions, final double loading)
public DoubleSparseHypercube(
final Dimension<?>[] dimensions,
final double nullValue,
final double loading
)
throws IllegalArgumentException,
NullPointerException
{
super(dimensions);

if (Double.isNaN(loading)) {
throw new IllegalArgumentException("Given a NaN loading value");
}
final int capacity =
(int)Math.max(13,
Math.min(Integer.MAX_VALUE,
getSize() * Math.max(0.0, Math.min(1.0, loading))));
myMap = new LongToLongConcurrentCuckooHashMap(capacity);

myNull = double2long(nullValue);
}

/**
Expand Down Expand Up @@ -225,7 +238,7 @@ public void toFlattened(final long srcPos,

preRead();
for (int i=0; i < length; i++) {
dst[dstPos + i] = long2double(myMap.get(srcPos + i, NULL));
dst[dstPos + i] = long2double(myMap.get(srcPos + i, myNull));
}
}

Expand Down Expand Up @@ -318,7 +331,7 @@ public double getAt(final long index)
);
}
preRead();
return long2double(myMap.get(index, NULL));
return long2double(myMap.get(index, myNull));
}

/**
Expand Down Expand Up @@ -353,13 +366,13 @@ protected Map<String,Boolean> createFlags()
}

/**
* Put a value into the map, in such a way that understand NULLs.
* Put a value into the map, in such a way that understand null values.
*/
private void mapPut(final long index, final long value)
{
// If we happen to be inserting a NULL then that really means we are
// If we happen to be inserting a null then that really means we are
// removing an entry from the sparse map
if (value == NULL) {
if (value == myNull) {
myMap.remove(index);
}
else {
Expand All @@ -368,4 +381,4 @@ private void mapPut(final long index, final long value)
}
}

// [[[end]]] (checksum: 7a064e0963bdf6be05eededdb3904777)
// [[[end]]] (checksum: 92af0879f0b1fb300dd185573c5883ec)
43 changes: 28 additions & 15 deletions java/src/main/java/com/deshaw/hypercube/FloatSparseHypercube.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,14 @@ public class FloatSparseHypercube
extends AbstractFloatHypercube
{
/**
* The primitive null value as a long.
* The map which we use to store the values.
*/
private static final long NULL = float2long(Float.NaN);
private final LongToLongConcurrentCuckooHashMap myMap;

/**
* The map which we use to store the values.
* The {@code float} null value as a {@code long}.
*/
private final LongToLongConcurrentCuckooHashMap myMap;
private final long myNull;

// ----------------------------------------------------------------------

Expand Down Expand Up @@ -99,30 +99,43 @@ private static long long2long(final long v)
// ----------------------------------------------------------------------

/**
* Constructor with a default loading of {@code 0.1}.
* Constructor with a default {@code null} value, and a loading of
* {@code 0.1}.
*/
public FloatSparseHypercube(final Dimension<?>[] dimensions)
throws IllegalArgumentException,
NullPointerException
{
this(dimensions, 0.1);
this(dimensions, Float.NaN, 0.1);
}

/**
* Constructor with a given loading.
* Constructor with a given {@code null} value and loading.
*
* @param nullValue The value used to for missing entries.
* @param loading The value used to determine the initial backing space
* capacity as a function of the logical size of the
* hypercube.
*/
public FloatSparseHypercube(final Dimension<?>[] dimensions, final double loading)
public FloatSparseHypercube(
final Dimension<?>[] dimensions,
final float nullValue,
final double loading
)
throws IllegalArgumentException,
NullPointerException
{
super(dimensions);

if (Double.isNaN(loading)) {
throw new IllegalArgumentException("Given a NaN loading value");
}
final int capacity =
(int)Math.max(13,
Math.min(Integer.MAX_VALUE,
getSize() * Math.max(0.0, Math.min(1.0, loading))));
myMap = new LongToLongConcurrentCuckooHashMap(capacity);

myNull = float2long(nullValue);
}

/**
Expand Down Expand Up @@ -225,7 +238,7 @@ public void toFlattened(final long srcPos,

preRead();
for (int i=0; i < length; i++) {
dst[dstPos + i] = long2float(myMap.get(srcPos + i, NULL));
dst[dstPos + i] = long2float(myMap.get(srcPos + i, myNull));
}
}

Expand Down Expand Up @@ -318,7 +331,7 @@ public float getAt(final long index)
);
}
preRead();
return long2float(myMap.get(index, NULL));
return long2float(myMap.get(index, myNull));
}

/**
Expand Down Expand Up @@ -353,13 +366,13 @@ protected Map<String,Boolean> createFlags()
}

/**
* Put a value into the map, in such a way that understand NULLs.
* Put a value into the map, in such a way that understand null values.
*/
private void mapPut(final long index, final long value)
{
// If we happen to be inserting a NULL then that really means we are
// If we happen to be inserting a null then that really means we are
// removing an entry from the sparse map
if (value == NULL) {
if (value == myNull) {
myMap.remove(index);
}
else {
Expand All @@ -368,4 +381,4 @@ private void mapPut(final long index, final long value)
}
}

// [[[end]]] (checksum: 050c646d52635157d9e47c0a81473eb4)
// [[[end]]] (checksum: f4cc734f1748a64b97f91e9b2caac2ec)
43 changes: 28 additions & 15 deletions java/src/main/java/com/deshaw/hypercube/IntegerSparseHypercube.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,14 @@ public class IntegerSparseHypercube
extends AbstractIntegerHypercube
{
/**
* The primitive null value as a long.
* The map which we use to store the values.
*/
private static final long NULL = int2long(0);
private final LongToLongConcurrentCuckooHashMap myMap;

/**
* The map which we use to store the values.
* The {@code int} null value as a {@code long}.
*/
private final LongToLongConcurrentCuckooHashMap myMap;
private final long myNull;

// ----------------------------------------------------------------------

Expand Down Expand Up @@ -99,30 +99,43 @@ private static long long2long(final long v)
// ----------------------------------------------------------------------

/**
* Constructor with a default loading of {@code 0.1}.
* Constructor with a default {@code null} value, and a loading of
* {@code 0.1}.
*/
public IntegerSparseHypercube(final Dimension<?>[] dimensions)
throws IllegalArgumentException,
NullPointerException
{
this(dimensions, 0.1);
this(dimensions, 0, 0.1);
}

/**
* Constructor with a given loading.
* Constructor with a given {@code null} value and loading.
*
* @param nullValue The value used to for missing entries.
* @param loading The value used to determine the initial backing space
* capacity as a function of the logical size of the
* hypercube.
*/
public IntegerSparseHypercube(final Dimension<?>[] dimensions, final double loading)
public IntegerSparseHypercube(
final Dimension<?>[] dimensions,
final int nullValue,
final double loading
)
throws IllegalArgumentException,
NullPointerException
{
super(dimensions);

if (Double.isNaN(loading)) {
throw new IllegalArgumentException("Given a NaN loading value");
}
final int capacity =
(int)Math.max(13,
Math.min(Integer.MAX_VALUE,
getSize() * Math.max(0.0, Math.min(1.0, loading))));
myMap = new LongToLongConcurrentCuckooHashMap(capacity);

myNull = int2long(nullValue);
}

/**
Expand Down Expand Up @@ -225,7 +238,7 @@ public void toFlattened(final long srcPos,

preRead();
for (int i=0; i < length; i++) {
dst[dstPos + i] = long2int(myMap.get(srcPos + i, NULL));
dst[dstPos + i] = long2int(myMap.get(srcPos + i, myNull));
}
}

Expand Down Expand Up @@ -318,7 +331,7 @@ public int getAt(final long index)
);
}
preRead();
return long2int(myMap.get(index, NULL));
return long2int(myMap.get(index, myNull));
}

/**
Expand Down Expand Up @@ -353,13 +366,13 @@ protected Map<String,Boolean> createFlags()
}

/**
* Put a value into the map, in such a way that understand NULLs.
* Put a value into the map, in such a way that understand null values.
*/
private void mapPut(final long index, final long value)
{
// If we happen to be inserting a NULL then that really means we are
// If we happen to be inserting a null then that really means we are
// removing an entry from the sparse map
if (value == NULL) {
if (value == myNull) {
myMap.remove(index);
}
else {
Expand All @@ -368,4 +381,4 @@ private void mapPut(final long index, final long value)
}
}

// [[[end]]] (checksum: 16cfdf905b69c20e965c624a658b7f6a)
// [[[end]]] (checksum: 7454a9f5e52b6ab8e4bfa52ced8a9cce)
Loading

0 comments on commit edebef1

Please sign in to comment.