aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHenning Baldersheim <balder@yahoo-inc.com>2024-01-28 19:28:42 +0100
committerGitHub <noreply@github.com>2024-01-28 19:28:42 +0100
commit6992a234c6e474dbe95e446bd1cdc50bdb452414 (patch)
tree17abc9faf9e43147ee195b0dbe9259eb361b3a6d
parent140ed00756d8b45ee622fdd61d2df91dd133133a (diff)
parentc824e1209fdd979612ccead027889eb6294b4652 (diff)
Merge pull request #30084 from vespa-engine/bratseth/tensor-cleanupv8.294.50
Minor cleanup
-rw-r--r--container-search/src/main/java/com/yahoo/fs4/MapEncoder.java4
-rw-r--r--container-search/src/main/java/com/yahoo/prelude/cluster/ClusterSearcher.java30
-rw-r--r--container-search/src/main/java/com/yahoo/search/query/ranking/RankProperties.java8
-rw-r--r--vespajlib/abi-spec.json4
-rw-r--r--vespajlib/src/main/java/com/yahoo/tensor/DirectIndexedAddress.java11
-rw-r--r--vespajlib/src/main/java/com/yahoo/tensor/IndexedDoubleTensor.java3
-rw-r--r--vespajlib/src/main/java/com/yahoo/tensor/IndexedTensor.java4
-rw-r--r--vespajlib/src/main/java/com/yahoo/tensor/MixedTensor.java26
-rw-r--r--vespajlib/src/main/java/com/yahoo/tensor/PartialAddress.java8
-rw-r--r--vespajlib/src/main/java/com/yahoo/tensor/Tensor.java45
-rw-r--r--vespajlib/src/main/java/com/yahoo/tensor/TensorAddress.java38
-rw-r--r--vespajlib/src/main/java/com/yahoo/tensor/TensorType.java2
-rw-r--r--vespajlib/src/main/java/com/yahoo/tensor/functions/Concat.java6
-rw-r--r--vespajlib/src/main/java/com/yahoo/tensor/functions/Join.java6
-rw-r--r--vespajlib/src/main/java/com/yahoo/tensor/impl/Label.java22
-rw-r--r--vespajlib/src/main/java/com/yahoo/tensor/impl/TensorAddressAny.java26
-rw-r--r--vespajlib/src/main/java/com/yahoo/tensor/impl/TensorAddressAny1.java6
-rw-r--r--vespajlib/src/main/java/com/yahoo/tensor/impl/TensorAddressAny2.java6
-rw-r--r--vespajlib/src/main/java/com/yahoo/tensor/impl/TensorAddressAny3.java6
-rw-r--r--vespajlib/src/main/java/com/yahoo/tensor/impl/TensorAddressAny4.java6
-rw-r--r--vespajlib/src/main/java/com/yahoo/tensor/impl/TensorAddressAnyN.java13
-rw-r--r--vespajlib/src/main/java/com/yahoo/tensor/impl/TensorAddressEmpty.java9
-rw-r--r--vespajlib/src/test/java/com/yahoo/tensor/impl/TensorAddressAnyTestCase.java10
23 files changed, 187 insertions, 112 deletions
diff --git a/container-search/src/main/java/com/yahoo/fs4/MapEncoder.java b/container-search/src/main/java/com/yahoo/fs4/MapEncoder.java
index 84b2b482403..4f31db0fc86 100644
--- a/container-search/src/main/java/com/yahoo/fs4/MapEncoder.java
+++ b/container-search/src/main/java/com/yahoo/fs4/MapEncoder.java
@@ -20,7 +20,7 @@ public class MapEncoder {
// TODO: Time to refactor
- private static byte [] getUtf8(Object value) {
+ private static byte[] getUtf8(Object value) {
if (value == null) {
return Utf8.toBytes("");
} else if (value instanceof Tensor) {
@@ -62,7 +62,7 @@ public class MapEncoder {
public static int encodeMap(String mapName, Map<String,?> map, ByteBuffer buffer) {
if (map.isEmpty()) return 0;
- byte [] utf8 = Utf8.toBytes(mapName);
+ byte[] utf8 = Utf8.toBytes(mapName);
buffer.putInt(utf8.length);
buffer.put(utf8);
buffer.putInt(map.size());
diff --git a/container-search/src/main/java/com/yahoo/prelude/cluster/ClusterSearcher.java b/container-search/src/main/java/com/yahoo/prelude/cluster/ClusterSearcher.java
index 441c4326355..88cc7ad7b2d 100644
--- a/container-search/src/main/java/com/yahoo/prelude/cluster/ClusterSearcher.java
+++ b/container-search/src/main/java/com/yahoo/prelude/cluster/ClusterSearcher.java
@@ -172,6 +172,21 @@ public class ClusterSearcher extends Searcher {
}
@Override
+ public Result search(Query query, Execution execution) {
+ validateQueryTimeout(query);
+ validateQueryCache(query);
+ Searcher searcher = server;
+ if (searcher == null) {
+ return new Result(query, ErrorMessage.createNoBackendsInService("Could not search"));
+ }
+ if (query.getTimeLeft() <= 0) {
+ return new Result(query, ErrorMessage.createTimeout("No time left for searching"));
+ }
+
+ return doSearch(searcher, query, execution);
+ }
+
+ @Override
public void fill(com.yahoo.search.Result result, String summaryClass, Execution execution) {
Query query = result.getQuery();
@@ -192,21 +207,6 @@ public class ClusterSearcher extends Searcher {
}
}
- @Override
- public Result search(Query query, Execution execution) {
- validateQueryTimeout(query);
- validateQueryCache(query);
- Searcher searcher = server;
- if (searcher == null) {
- return new Result(query, ErrorMessage.createNoBackendsInService("Could not search"));
- }
- if (query.getTimeLeft() <= 0) {
- return new Result(query, ErrorMessage.createTimeout("No time left for searching"));
- }
-
- return doSearch(searcher, query, execution);
- }
-
private void validateQueryTimeout(Query query) {
if (query.getTimeout() <= maxQueryTimeout) return;
diff --git a/container-search/src/main/java/com/yahoo/search/query/ranking/RankProperties.java b/container-search/src/main/java/com/yahoo/search/query/ranking/RankProperties.java
index 4ac5375807b..fd0b6543f28 100644
--- a/container-search/src/main/java/com/yahoo/search/query/ranking/RankProperties.java
+++ b/container-search/src/main/java/com/yahoo/search/query/ranking/RankProperties.java
@@ -38,16 +38,12 @@ public class RankProperties implements Cloneable {
/** Adds a property by full name to a value */
public void put(String name, Object value) {
- List<Object> list = properties.get(name);
- if (list == null) {
- list = new ArrayList<>();
- properties.put(name, list);
- }
+ List<Object> list = properties.computeIfAbsent(name, k -> new ArrayList<>());
list.add(value);
}
/**
- * Returns a read-only list of properties properties by full name.
+ * Returns a read-only list of properties by full name.
* If this is not set, null is returned. If this is explicitly set to
* have no values, and empty list is returned.
*/
diff --git a/vespajlib/abi-spec.json b/vespajlib/abi-spec.json
index 1f44d90f924..452b2dc0da9 100644
--- a/vespajlib/abi-spec.json
+++ b/vespajlib/abi-spec.json
@@ -1266,7 +1266,7 @@
"public static com.yahoo.tensor.Tensor from(double)"
],
"fields" : [
- "public static final int INVALID_INDEX"
+ "public static final int invalidIndex"
]
},
"com.yahoo.tensor.TensorAddress$Builder" : {
@@ -1324,7 +1324,7 @@
"public static java.lang.String labelToString(java.lang.String)",
"public com.yahoo.tensor.TensorAddress partialCopy(int[])",
"public com.yahoo.tensor.TensorAddress fullAddressOf(java.util.List, int[])",
- "public com.yahoo.tensor.TensorAddress sparsePartialAddress(com.yahoo.tensor.TensorType, java.util.List)",
+ "public com.yahoo.tensor.TensorAddress mappedPartialAddress(com.yahoo.tensor.TensorType, java.util.List)",
"public bridge synthetic int compareTo(java.lang.Object)"
],
"fields" : [ ]
diff --git a/vespajlib/src/main/java/com/yahoo/tensor/DirectIndexedAddress.java b/vespajlib/src/main/java/com/yahoo/tensor/DirectIndexedAddress.java
index 37752361876..4379d50520c 100644
--- a/vespajlib/src/main/java/com/yahoo/tensor/DirectIndexedAddress.java
+++ b/vespajlib/src/main/java/com/yahoo/tensor/DirectIndexedAddress.java
@@ -7,19 +7,25 @@ package com.yahoo.tensor;
* long stride = addr.getStride(dimension)
* i = 0...size_of_dimension
* double value = tensor.get(base + i * stride);
+ *
+ * @author baldersheim
*/
public final class DirectIndexedAddress {
+
private final DimensionSizes sizes;
- private final int [] indexes;
+ private final int[] indexes;
private long directIndex;
+
private DirectIndexedAddress(DimensionSizes sizes) {
this.sizes = sizes;
indexes = new int[sizes.dimensions()];
directIndex = 0;
}
+
static DirectIndexedAddress of(DimensionSizes sizes) {
return new DirectIndexedAddress(sizes);
}
+
/** Sets the current index of a dimension */
public void setIndex(int dimension, int index) {
if (index < 0 || index >= sizes.size(dimension)) {
@@ -29,10 +35,13 @@ public final class DirectIndexedAddress {
directIndex += getStride(dimension) * diff;
indexes[dimension] = index;
}
+
/** Retrieve the index that can be used for direct lookup in an indexed tensor. */
public long getDirectIndex() { return directIndex; }
+
/** returns the stride to be used for the given dimension */
public long getStride(int dimension) {
return sizes.productOfDimensionsAfter(dimension);
}
+
}
diff --git a/vespajlib/src/main/java/com/yahoo/tensor/IndexedDoubleTensor.java b/vespajlib/src/main/java/com/yahoo/tensor/IndexedDoubleTensor.java
index 085f9172095..53f50fc4d02 100644
--- a/vespajlib/src/main/java/com/yahoo/tensor/IndexedDoubleTensor.java
+++ b/vespajlib/src/main/java/com/yahoo/tensor/IndexedDoubleTensor.java
@@ -78,9 +78,6 @@ class IndexedDoubleTensor extends IndexedTensor {
@Override
public Builder cell(TensorAddress address, double value) {
- if (address == null) {
- return null;
- }
values[(int)toValueIndex(address, sizes(), type)] = value;
return this;
}
diff --git a/vespajlib/src/main/java/com/yahoo/tensor/IndexedTensor.java b/vespajlib/src/main/java/com/yahoo/tensor/IndexedTensor.java
index a428524612b..fc0473c635a 100644
--- a/vespajlib/src/main/java/com/yahoo/tensor/IndexedTensor.java
+++ b/vespajlib/src/main/java/com/yahoo/tensor/IndexedTensor.java
@@ -172,7 +172,7 @@ public abstract class IndexedTensor implements Tensor {
static long toValueIndex(TensorAddress address, DimensionSizes sizes, TensorType type) {
long valueIndex = 0;
- for (int i = 0, sz = address.size(); i < sz; i++) {
+ for (int i = 0, size = address.size(); i < size; i++) {
long label = address.numericLabel(i);
if (label >= sizes.size(i))
throw new IllegalArgumentException(address + " is not within the bounds of " + type);
@@ -1058,7 +1058,7 @@ public abstract class IndexedTensor implements Tensor {
/** In this case we can reuse the source index computation for the iteration index */
private final static class EqualSizeMultiDimensionIndexes extends MultiDimensionIndexes {
- private long lastComputedSourceValueIndex = Tensor.INVALID_INDEX;
+ private long lastComputedSourceValueIndex = Tensor.invalidIndex;
private EqualSizeMultiDimensionIndexes(DimensionSizes sizes, List<Integer> iterateDimensions, long[] initialIndexes, long size) {
super(sizes, sizes, iterateDimensions, initialIndexes, size);
diff --git a/vespajlib/src/main/java/com/yahoo/tensor/MixedTensor.java b/vespajlib/src/main/java/com/yahoo/tensor/MixedTensor.java
index d4469f447cb..65c6677e7e3 100644
--- a/vespajlib/src/main/java/com/yahoo/tensor/MixedTensor.java
+++ b/vespajlib/src/main/java/com/yahoo/tensor/MixedTensor.java
@@ -107,27 +107,30 @@ public class MixedTensor implements Tensor {
@Override
public Iterator<Cell> cellIterator() {
return new Iterator<>() {
+
final Iterator<DenseSubspace> blockIterator = index.denseSubspaces.iterator();
- DenseSubspace currBlock = null;
final int[] labels = new int[index.indexedDimensions.size()];
+ DenseSubspace currentBlock = null;
int currOffset = index.denseSubspaceSize;
int prevOffset = -1;
+
@Override
public boolean hasNext() {
return (currOffset < index.denseSubspaceSize || blockIterator.hasNext());
}
+
@Override
public Cell next() {
if (currOffset == index.denseSubspaceSize) {
- currBlock = blockIterator.next();
+ currentBlock = blockIterator.next();
currOffset = 0;
}
if (currOffset != prevOffset) { // Optimization for index.denseSubspaceSize == 1
index.denseOffsetToAddress(currOffset, labels);
}
- TensorAddress fullAddr = currBlock.sparseAddress.fullAddressOf(index.type.dimensions(), labels);
+ TensorAddress fullAddr = currentBlock.sparseAddress.fullAddressOf(index.type.dimensions(), labels);
prevOffset = currOffset;
- double value = currBlock.cells[currOffset++];
+ double value = currentBlock.cells[currOffset++];
return new Cell(fullAddr, value);
}
};
@@ -140,20 +143,23 @@ public class MixedTensor implements Tensor {
@Override
public Iterator<Double> valueIterator() {
return new Iterator<>() {
+
final Iterator<DenseSubspace> blockIterator = index.denseSubspaces.iterator();
- double[] currBlock = null;
+ double[] currentBlock = null;
int currOffset = index.denseSubspaceSize;
+
@Override
public boolean hasNext() {
return (currOffset < index.denseSubspaceSize || blockIterator.hasNext());
}
+
@Override
public Double next() {
if (currOffset == index.denseSubspaceSize) {
- currBlock = blockIterator.next().cells;
+ currentBlock = blockIterator.next().cells;
currOffset = 0;
}
- return currBlock[currOffset++];
+ return currentBlock[currOffset++];
}
};
}
@@ -319,7 +325,7 @@ public class MixedTensor implements Tensor {
@Override
public Tensor.Builder cell(TensorAddress address, double value) {
- TensorAddress sparsePart = address.sparsePartialAddress(index.sparseType, index.type.dimensions());
+ TensorAddress sparsePart = address.mappedPartialAddress(index.sparseType, index.type.dimensions());
int denseOffset = index.denseOffsetOf(address);
double[] denseSubspace = denseSubspace(sparsePart);
denseSubspace[denseOffset] = value;
@@ -438,7 +444,7 @@ public class MixedTensor implements Tensor {
private final TensorType denseType;
private final List<TensorType.Dimension> mappedDimensions;
private final List<TensorType.Dimension> indexedDimensions;
- private final int [] indexedDimensionsSize;
+ private final int[] indexedDimensionsSize;
private ImmutableMap<TensorAddress, Integer> sparseMap;
private List<DenseSubspace> denseSubspaces;
@@ -473,7 +479,7 @@ public class MixedTensor implements Tensor {
}
private DenseSubspace blockOf(TensorAddress address) {
- TensorAddress sparsePart = address.sparsePartialAddress(sparseType, type.dimensions());
+ TensorAddress sparsePart = address.mappedPartialAddress(sparseType, type.dimensions());
Integer blockNum = sparseMap.get(sparsePart);
if (blockNum == null || blockNum >= denseSubspaces.size()) {
return null;
diff --git a/vespajlib/src/main/java/com/yahoo/tensor/PartialAddress.java b/vespajlib/src/main/java/com/yahoo/tensor/PartialAddress.java
index da643d8c173..8852bcd1ff3 100644
--- a/vespajlib/src/main/java/com/yahoo/tensor/PartialAddress.java
+++ b/vespajlib/src/main/java/com/yahoo/tensor/PartialAddress.java
@@ -4,13 +4,13 @@ package com.yahoo.tensor;
import com.yahoo.tensor.impl.Label;
/**
- * An address to a subset of a tensors' cells, specifying a label for some but not necessarily all of the tensors
+ * An address to a subset of a tensors' cells, specifying a label for some, but not necessarily all, of the tensors
* dimensions.
*
* @author bratseth
*/
// Implementation notes:
-// - These are created in inner (though not inner-most) loops so they are implemented with minimal allocation.
+// - These are created in inner (though not innermost) loops, so they are implemented with minimal allocation.
// We also avoid non-essential error checking.
// - We can add support for string labels later without breaking the API
public class PartialAddress {
@@ -36,7 +36,7 @@ public class PartialAddress {
for (int i = 0; i < dimensionNames.length; i++)
if (dimensionNames[i].equals(dimensionName))
return labels[i];
- return Tensor.INVALID_INDEX;
+ return Tensor.invalidIndex;
}
/** Returns the label of this dimension, or null if no label is specified for it */
@@ -68,7 +68,7 @@ public class PartialAddress {
long[] numericLabels = new long[labels.length];
for (int i = 0; i < type.dimensions().size(); i++) {
long label = numericLabel(type.dimensions().get(i).name());
- if (label == Tensor.INVALID_INDEX)
+ if (label == Tensor.invalidIndex)
throw new IllegalArgumentException(type + " dimension names does not match " + this);
numericLabels[i] = label;
}
diff --git a/vespajlib/src/main/java/com/yahoo/tensor/Tensor.java b/vespajlib/src/main/java/com/yahoo/tensor/Tensor.java
index d650b88f202..ac9dc4e4eca 100644
--- a/vespajlib/src/main/java/com/yahoo/tensor/Tensor.java
+++ b/vespajlib/src/main/java/com/yahoo/tensor/Tensor.java
@@ -40,7 +40,7 @@ import static com.yahoo.tensor.functions.ScalarFunctions.Hamming;
* A multidimensional array which can be used in computations.
* <p>
* A tensor consists of a set of <i>dimension</i> names and a set of <i>cells</i> containing scalar <i>values</i>.
- * Each cell is is identified by its <i>address</i>, which consists of a set of dimension-label pairs which defines
+ * Each cell is identified by its <i>address</i>, which consists of a set of dimension-label pairs which defines
* the location of that cell. Both dimensions and labels are string on the form of an identifier or integer.
* <p>
* The size of the set of dimensions of a tensor is called its <i>rank</i>.
@@ -55,7 +55,9 @@ import static com.yahoo.tensor.functions.ScalarFunctions.Hamming;
* @author bratseth
*/
public interface Tensor {
- int INVALID_INDEX = -1;
+
+ /** The constant signaling a nonexisting value in operations addressing tensor values by index. */
+ int invalidIndex = -1;
// ----------------- Accessors
@@ -65,25 +67,24 @@ public interface Tensor {
default boolean isEmpty() { return size() == 0; }
/**
- * Returns the number of cells in this.
- * Allows for very large tensors, but if you only handle size in the int range
- * prefer sizeAsInt().
- **/
+ * Returns the number of cells in this, allowing for very large tensors.
+ * Prefer sizeAsInt in implementations that cannot handle sizes outside the int range.
+ */
default long size() {
return sizeAsInt();
}
/**
- * Safe way to get size as an int and detect when not possible.
- * Prefer this over size() as
- * @return size() as an int
+ * Returns the size of this as an int or throws an exception if it is too large to fit in an int.
+ * Prefer this over size() with implementations that only handle sizes in the int range.
+ *
+ * @throws IndexOutOfBoundsException if the size is too large to fit in an int
*/
default int sizeAsInt() {
- long sz = size();
- if (sz > Integer.MAX_VALUE) {
- throw new IndexOutOfBoundsException("size = " + sz + ", which is too large to fit in an int");
- }
- return (int) sz;
+ long size = size();
+ if (size > Integer.MAX_VALUE)
+ throw new IndexOutOfBoundsException("size = " + size + ", which is too large to fit in an int");
+ return (int) size;
}
/** Returns the value of a cell, or 0.0 if this cell does not exist */
@@ -91,7 +92,8 @@ public interface Tensor {
/** Returns true if this cell exists */
boolean has(TensorAddress address);
- /** null = no value present. More efficient that if (t.has(key)) t.get(key) */
+
+ /** Returns the value at this address, or null of it does not exist. */
Double getAsDouble(TensorAddress address);
/**
@@ -132,7 +134,7 @@ public interface Tensor {
/**
* Returns a new tensor where existing cells in this tensor have been
* modified according to the given operation and cells in the given map.
- * Cells in the map outside of existing cells are thus ignored.
+ * Cells in the map outside existing cells are thus ignored.
*
* @param op the modifying function
* @param cells the cells to modify
@@ -151,9 +153,9 @@ public interface Tensor {
/**
* Returns a new tensor where existing cells in this tensor have been
- * removed according to the given set of addresses. Only valid for sparse
+ * removed according to the given set of addresses. Only valid for mapped
* or mixed tensors. For mixed tensors, addresses are assumed to only
- * contain the sparse dimensions, as the entire dense subspace is removed.
+ * contain the mapped dimensions, as the entire indexed subspace is removed.
*
* @param addresses list of addresses to remove
* @return a new tensor where cells have been removed
@@ -503,11 +505,10 @@ public interface Tensor {
public TensorAddress getKey() { return address; }
/**
- * Returns the direct index which can be used to locate this cell, or -1 if not available.
- * This is for optimizations mapping between tensors where this is possible without creating a
- * TensorAddress.
+ * Returns the direct index which can be used to locate this cell, or Tensor.invalidIndex if not available.
+ * This is for optimizations mapping between tensors where this is possible without creating a TensorAddress.
*/
- long getDirectIndex() { return INVALID_INDEX; }
+ long getDirectIndex() { return invalidIndex; }
/** Returns the value as a double */
@Override
diff --git a/vespajlib/src/main/java/com/yahoo/tensor/TensorAddress.java b/vespajlib/src/main/java/com/yahoo/tensor/TensorAddress.java
index 59a5e2a49b1..5c2c4d77fad 100644
--- a/vespajlib/src/main/java/com/yahoo/tensor/TensorAddress.java
+++ b/vespajlib/src/main/java/com/yahoo/tensor/TensorAddress.java
@@ -32,9 +32,7 @@ public abstract class TensorAddress implements Comparable<TensorAddress> {
return TensorAddressAny.of(labels);
}
- /**
- * Returns the number of labels in this
- */
+ /** Returns the number of labels in this */
public abstract int size();
/**
@@ -69,10 +67,10 @@ public abstract class TensorAddress implements Comparable<TensorAddress> {
@Override
public String toString() {
StringBuilder sb = new StringBuilder("cell address (");
- int sz = size();
- if (sz > 0) {
+ int size = size();
+ if (size > 0) {
sb.append(label(0));
- for (int i = 1; i < sz; i++) {
+ for (int i = 1; i < size; i++) {
sb.append(',').append(label(i));
}
}
@@ -113,9 +111,9 @@ public abstract class TensorAddress implements Comparable<TensorAddress> {
return TensorAddressAny.ofUnsafe(labels);
}
- /** Creates a complete address by taking the sparse dimmensions from this and the indexed from the densePart */
- public TensorAddress fullAddressOf(List<TensorType.Dimension> dimensions, int [] densePart) {
- int [] labels = new int[dimensions.size()];
+ /** Creates a complete address by taking the mapped dimmensions from this and the indexed from the indexedPart */
+ public TensorAddress fullAddressOf(List<TensorType.Dimension> dimensions, int[] densePart) {
+ int[] labels = new int[dimensions.size()];
int mappedIndex = 0;
int indexedIndex = 0;
for (int i = 0; i < labels.length; i++) {
@@ -131,11 +129,17 @@ public abstract class TensorAddress implements Comparable<TensorAddress> {
return TensorAddressAny.ofUnsafe(labels);
}
- /** Extracts the sparse(non-indexed) dimensions of the address */
- public TensorAddress sparsePartialAddress(TensorType sparseType, List<TensorType.Dimension> dimensions) {
+ /**
+ * Returns an address containing the mapped dimensions of this.
+ *
+ * @param mappedType the type of the mapped subset of the type this is an address of;
+ * which is also the type of the returned address
+ * @param dimensions all the dimensions of the type this is an address of
+ */
+ public TensorAddress mappedPartialAddress(TensorType mappedType, List<TensorType.Dimension> dimensions) {
if (dimensions.size() != size())
throw new IllegalArgumentException("Tensor type of " + this + " is not the same size as " + this);
- TensorAddress.Builder builder = new TensorAddress.Builder(sparseType);
+ TensorAddress.Builder builder = new TensorAddress.Builder(mappedType);
for (int i = 0; i < dimensions.size(); ++i) {
TensorType.Dimension dimension = dimensions.get(i);
if ( ! dimension.isIndexed())
@@ -150,9 +154,9 @@ public abstract class TensorAddress implements Comparable<TensorAddress> {
final TensorType type;
final int[] labels;
- private static int [] createEmptyLabels(int size) {
- int [] labels = new int[size];
- Arrays.fill(labels, Tensor.INVALID_INDEX);
+ private static int[] createEmptyLabels(int size) {
+ int[] labels = new int[size];
+ Arrays.fill(labels, Tensor.invalidIndex);
return labels;
}
@@ -174,7 +178,7 @@ public abstract class TensorAddress implements Comparable<TensorAddress> {
var mappedSubtype = type.mappedSubtype();
if (mappedSubtype.rank() != 1)
throw new IllegalArgumentException("Cannot add a label without explicit dimension to a tensor of type " +
- type + ": Must have exactly one sparse dimension");
+ type + ": Must have exactly one mapped dimension");
add(mappedSubtype.dimensions().get(0).name(), label);
return this;
}
@@ -212,7 +216,7 @@ public abstract class TensorAddress implements Comparable<TensorAddress> {
void validate() {
for (int i = 0; i < labels.length; i++)
- if (labels[i] == Tensor.INVALID_INDEX)
+ if (labels[i] == Tensor.invalidIndex)
throw new IllegalArgumentException("Missing a label for dimension '" +
type.dimensions().get(i).name() + "' for " + type);
}
diff --git a/vespajlib/src/main/java/com/yahoo/tensor/TensorType.java b/vespajlib/src/main/java/com/yahoo/tensor/TensorType.java
index 62ed4ad683c..6b81d023a9a 100644
--- a/vespajlib/src/main/java/com/yahoo/tensor/TensorType.java
+++ b/vespajlib/src/main/java/com/yahoo/tensor/TensorType.java
@@ -204,7 +204,7 @@ public class TensorType {
for (int i = 0; i < dimensions.size(); i++)
if (dimensions.get(i).name().equals(dimension))
return i;
- return Tensor.INVALID_INDEX;
+ return Tensor.invalidIndex;
}
/* Returns the bound of this dimension if it is present and bound in this, empty otherwise */
diff --git a/vespajlib/src/main/java/com/yahoo/tensor/functions/Concat.java b/vespajlib/src/main/java/com/yahoo/tensor/functions/Concat.java
index 37ca7f979a1..dcfba5ecfad 100644
--- a/vespajlib/src/main/java/com/yahoo/tensor/functions/Concat.java
+++ b/vespajlib/src/main/java/com/yahoo/tensor/functions/Concat.java
@@ -172,7 +172,7 @@ public class Concat<NAMETYPE extends Name> extends PrimitiveTensorFunction<NAMET
private TensorAddress combineAddresses(TensorAddress a, int[] aToIndexes, TensorAddress b, int[] bToIndexes,
TensorType concatType, long concatOffset, String concatDimension) {
long[] combinedLabels = new long[concatType.dimensions().size()];
- Arrays.fill(combinedLabels, Tensor.INVALID_INDEX);
+ Arrays.fill(combinedLabels, Tensor.invalidIndex);
int concatDimensionIndex = concatType.indexOfDimension(concatDimension).get();
mapContent(a, combinedLabels, aToIndexes, concatDimensionIndex, concatOffset); // note: This sets a nonsensical value in the concat dimension
boolean compatible = mapContent(b, combinedLabels, bToIndexes, concatDimensionIndex, concatOffset); // ... which is overwritten by the right value here
@@ -191,7 +191,7 @@ public class Concat<NAMETYPE extends Name> extends PrimitiveTensorFunction<NAMET
private int[] mapIndexes(TensorType fromType, TensorType toType) {
int[] toIndexes = new int[fromType.dimensions().size()];
for (int i = 0; i < fromType.dimensions().size(); i++)
- toIndexes[i] = toType.indexOfDimension(fromType.dimensions().get(i).name()).orElse(Tensor.INVALID_INDEX);
+ toIndexes[i] = toType.indexOfDimension(fromType.dimensions().get(i).name()).orElse(Tensor.invalidIndex);
return toIndexes;
}
@@ -208,7 +208,7 @@ public class Concat<NAMETYPE extends Name> extends PrimitiveTensorFunction<NAMET
to[toIndex] = from.numericLabel(i) + concatOffset;
}
else {
- if (to[toIndex] != Tensor.INVALID_INDEX && to[toIndex] != from.numericLabel(i)) return false;
+ if (to[toIndex] != Tensor.invalidIndex && to[toIndex] != from.numericLabel(i)) return false;
to[toIndex] = from.numericLabel(i);
}
}
diff --git a/vespajlib/src/main/java/com/yahoo/tensor/functions/Join.java b/vespajlib/src/main/java/com/yahoo/tensor/functions/Join.java
index 047d8ee6ef0..14adcc8f18a 100644
--- a/vespajlib/src/main/java/com/yahoo/tensor/functions/Join.java
+++ b/vespajlib/src/main/java/com/yahoo/tensor/functions/Join.java
@@ -378,7 +378,7 @@ public class Join<NAMETYPE extends Name> extends PrimitiveTensorFunction<NAMETYP
private static TensorAddress joinAddresses(TensorAddress a, int[] aToIndexes, TensorAddress b, int[] bToIndexes,
TensorType joinedType) {
int[] joinedLabels = new int[joinedType.dimensions().size()];
- Arrays.fill(joinedLabels, Tensor.INVALID_INDEX);
+ Arrays.fill(joinedLabels, Tensor.invalidIndex);
mapContent(a, joinedLabels, aToIndexes);
boolean compatible = mapContent(b, joinedLabels, bToIndexes);
if ( ! compatible) return null;
@@ -392,10 +392,10 @@ public class Join<NAMETYPE extends Name> extends PrimitiveTensorFunction<NAMETYP
* occupied by a different value
*/
private static boolean mapContent(TensorAddress from, int[] to, int[] indexMap) {
- for (int i = 0, sz = from.size(); i < sz; i++) {
+ for (int i = 0, size = from.size(); i < size; i++) {
int toIndex = indexMap[i];
int label = Convert.safe2Int(from.numericLabel(i));
- if (to[toIndex] != Tensor.INVALID_INDEX && to[toIndex] != label)
+ if (to[toIndex] != Tensor.invalidIndex && to[toIndex] != label)
return false;
to[toIndex] = label;
}
diff --git a/vespajlib/src/main/java/com/yahoo/tensor/impl/Label.java b/vespajlib/src/main/java/com/yahoo/tensor/impl/Label.java
index 0ab1454eb58..a09c0223d28 100644
--- a/vespajlib/src/main/java/com/yahoo/tensor/impl/Label.java
+++ b/vespajlib/src/main/java/com/yahoo/tensor/impl/Label.java
@@ -7,16 +7,26 @@ import java.util.Arrays;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
+/**
+ * A label is a value of a mapped dimension of a tensor.
+ * This class provides a mapping of labels to numbers which allow for more efficient computation with
+ * mapped tensor dimensions.
+ *
+ * @author baldersheim
+ */
public class Label {
- private static final String [] SMALL_INDEXES = createSmallIndexesAsStrings(1000);
+
+ private static final String[] SMALL_INDEXES = createSmallIndexesAsStrings(1000);
+
private final static Map<String, Integer> string2Enum = new ConcurrentHashMap<>();
+
// Index 0 is unused, that is a valid positive number
// 1(-1) is reserved for the Tensor.INVALID_INDEX
- private static volatile String [] uniqueStrings = {"UNIQUE_UNUSED_MAGIC", "Tensor.INVALID_INDEX"};
+ private static volatile String[] uniqueStrings = {"UNIQUE_UNUSED_MAGIC", "Tensor.INVALID_INDEX"};
private static int numUniqeStrings = 2;
private static String[] createSmallIndexesAsStrings(int count) {
- String [] asStrings = new String[count];
+ String[] asStrings = new String[count];
for (int i = 0; i < count; i++) {
asStrings[i] = String.valueOf(i);
}
@@ -46,7 +56,7 @@ public class Label {
}
public static int toNumber(String s) {
- if (s == null) { return Tensor.INVALID_INDEX; }
+ if (s == null) { return Tensor.invalidIndex; }
try {
if (validNumericIndex(s)) {
return Integer.parseInt(s);
@@ -55,14 +65,16 @@ public class Label {
}
return string2Enum.computeIfAbsent(s, Label::addNewUniqueString);
}
+
public static String fromNumber(int v) {
if (v >= 0) {
return asNumericString(v);
} else {
- if (v == Tensor.INVALID_INDEX) { return null; }
+ if (v == Tensor.invalidIndex) { return null; }
return uniqueStrings[-v];
}
}
+
public static String fromNumber(long v) {
return fromNumber(Convert.safe2Int(v));
}
diff --git a/vespajlib/src/main/java/com/yahoo/tensor/impl/TensorAddressAny.java b/vespajlib/src/main/java/com/yahoo/tensor/impl/TensorAddressAny.java
index 31863c99a74..2e70811a67c 100644
--- a/vespajlib/src/main/java/com/yahoo/tensor/impl/TensorAddressAny.java
+++ b/vespajlib/src/main/java/com/yahoo/tensor/impl/TensorAddressAny.java
@@ -18,6 +18,7 @@ import static com.yahoo.tensor.impl.Label.fromNumber;
* @author baldersheim
*/
abstract public class TensorAddressAny extends TensorAddress {
+
@Override
public String label(int i) {
return fromNumber((int)numericLabel(i));
@@ -26,37 +27,47 @@ abstract public class TensorAddressAny extends TensorAddress {
public static TensorAddress of() {
return TensorAddressEmpty.empty;
}
+
public static TensorAddress of(String label) {
return new TensorAddressAny1(toNumber(label));
}
+
public static TensorAddress of(String label0, String label1) {
return new TensorAddressAny2(toNumber(label0), toNumber(label1));
}
+
public static TensorAddress of(String label0, String label1, String label2) {
return new TensorAddressAny3(toNumber(label0), toNumber(label1), toNumber(label2));
}
+
public static TensorAddress of(String label0, String label1, String label2, String label3) {
return new TensorAddressAny4(toNumber(label0), toNumber(label1), toNumber(label2), toNumber(label3));
}
- public static TensorAddress of(String [] labels) {
- int [] labelsAsInt = new int[labels.length];
+
+ public static TensorAddress of(String[] labels) {
+ int[] labelsAsInt = new int[labels.length];
for (int i = 0; i < labels.length; i++) {
labelsAsInt[i] = toNumber(labels[i]);
}
return ofUnsafe(labelsAsInt);
}
+
public static TensorAddress of(int label) {
return new TensorAddressAny1(sanitize(label));
}
+
public static TensorAddress of(int label0, int label1) {
return new TensorAddressAny2(sanitize(label0), sanitize(label1));
}
+
public static TensorAddress of(int label0, int label1, int label2) {
return new TensorAddressAny3(sanitize(label0), sanitize(label1), sanitize(label2));
}
+
public static TensorAddress of(int label0, int label1, int label2, int label3) {
return new TensorAddressAny4(sanitize(label0), sanitize(label1), sanitize(label2), sanitize(label3));
}
+
public static TensorAddress of(int ... labels) {
return switch (labels.length) {
case 0 -> of();
@@ -72,6 +83,7 @@ abstract public class TensorAddressAny extends TensorAddress {
}
};
}
+
public static TensorAddress of(long label) {
return of(safe2Int(label));
}
@@ -96,7 +108,7 @@ abstract public class TensorAddressAny extends TensorAddress {
case 3 -> ofUnsafe(safe2Int(labels[0]), safe2Int(labels[1]), safe2Int(labels[2]));
case 4 -> ofUnsafe(safe2Int(labels[0]), safe2Int(labels[1]), safe2Int(labels[2]), safe2Int(labels[3]));
default -> {
- int [] labelsAsInt = new int[labels.length];
+ int[] labelsAsInt = new int[labels.length];
for (int i = 0; i < labels.length; i++) {
labelsAsInt[i] = safe2Int(labels[i]);
}
@@ -108,15 +120,19 @@ abstract public class TensorAddressAny extends TensorAddress {
private static TensorAddress ofUnsafe(int label) {
return new TensorAddressAny1(label);
}
+
private static TensorAddress ofUnsafe(int label0, int label1) {
return new TensorAddressAny2(label0, label1);
}
+
private static TensorAddress ofUnsafe(int label0, int label1, int label2) {
return new TensorAddressAny3(label0, label1, label2);
}
+
private static TensorAddress ofUnsafe(int label0, int label1, int label2, int label3) {
return new TensorAddressAny4(label0, label1, label2, label3);
}
+
public static TensorAddress ofUnsafe(int ... labels) {
return switch (labels.length) {
case 0 -> of();
@@ -127,10 +143,12 @@ abstract public class TensorAddressAny extends TensorAddress {
default -> new TensorAddressAnyN(labels);
};
}
+
private static int sanitize(int label) {
- if (label < Tensor.INVALID_INDEX) {
+ if (label < Tensor.invalidIndex) {
throw new IndexOutOfBoundsException("cell label " + label + " must be positive");
}
return label;
}
+
}
diff --git a/vespajlib/src/main/java/com/yahoo/tensor/impl/TensorAddressAny1.java b/vespajlib/src/main/java/com/yahoo/tensor/impl/TensorAddressAny1.java
index a2b0d318a50..a9be6173781 100644
--- a/vespajlib/src/main/java/com/yahoo/tensor/impl/TensorAddressAny1.java
+++ b/vespajlib/src/main/java/com/yahoo/tensor/impl/TensorAddressAny1.java
@@ -5,11 +5,14 @@ package com.yahoo.tensor.impl;
import com.yahoo.tensor.TensorAddress;
/**
- * Single dimension
+ * A one-dimensional address.
+ *
* @author baldersheim
*/
final class TensorAddressAny1 extends TensorAddressAny {
+
private final int label;
+
TensorAddressAny1(int label) { this.label = label; }
@Override public int size() { return 1; }
@@ -34,4 +37,5 @@ final class TensorAddressAny1 extends TensorAddressAny {
public boolean equals(Object o) {
return (o instanceof TensorAddressAny1 any) && (label == any.label);
}
+
}
diff --git a/vespajlib/src/main/java/com/yahoo/tensor/impl/TensorAddressAny2.java b/vespajlib/src/main/java/com/yahoo/tensor/impl/TensorAddressAny2.java
index d77a689852f..43f65d495cf 100644
--- a/vespajlib/src/main/java/com/yahoo/tensor/impl/TensorAddressAny2.java
+++ b/vespajlib/src/main/java/com/yahoo/tensor/impl/TensorAddressAny2.java
@@ -7,11 +7,14 @@ import com.yahoo.tensor.TensorAddress;
import static java.lang.Math.abs;
/**
- * 2 dimensional address
+ * A two-dimensional address.
+ *
* @author baldersheim
*/
final class TensorAddressAny2 extends TensorAddressAny {
+
private final int label0, label1;
+
TensorAddressAny2(int label0, int label1) {
this.label0 = label0;
this.label1 = label1;
@@ -46,4 +49,5 @@ final class TensorAddressAny2 extends TensorAddressAny {
public boolean equals(Object o) {
return (o instanceof TensorAddressAny2 any) && (label0 == any.label0) && (label1 == any.label1);
}
+
}
diff --git a/vespajlib/src/main/java/com/yahoo/tensor/impl/TensorAddressAny3.java b/vespajlib/src/main/java/com/yahoo/tensor/impl/TensorAddressAny3.java
index 95e14bd375c..c22ff47b3c4 100644
--- a/vespajlib/src/main/java/com/yahoo/tensor/impl/TensorAddressAny3.java
+++ b/vespajlib/src/main/java/com/yahoo/tensor/impl/TensorAddressAny3.java
@@ -7,11 +7,14 @@ import com.yahoo.tensor.TensorAddress;
import static java.lang.Math.abs;
/**
- * 3 dimensional address
+ * A three-dimensional address.
+ *
* @author baldersheim
*/
final class TensorAddressAny3 extends TensorAddressAny {
+
private final int label0, label1, label2;
+
TensorAddressAny3(int label0, int label1, int label2) {
this.label0 = label0;
this.label1 = label1;
@@ -54,4 +57,5 @@ final class TensorAddressAny3 extends TensorAddressAny {
(label1 == any.label1) &&
(label2 == any.label2);
}
+
}
diff --git a/vespajlib/src/main/java/com/yahoo/tensor/impl/TensorAddressAny4.java b/vespajlib/src/main/java/com/yahoo/tensor/impl/TensorAddressAny4.java
index 8a45483340e..6eb6b9216bf 100644
--- a/vespajlib/src/main/java/com/yahoo/tensor/impl/TensorAddressAny4.java
+++ b/vespajlib/src/main/java/com/yahoo/tensor/impl/TensorAddressAny4.java
@@ -7,11 +7,14 @@ import com.yahoo.tensor.TensorAddress;
import static java.lang.Math.abs;
/**
- * 4 dimensional address
+ * A four-dimensional address.
+ *
* @author baldersheim
*/
final class TensorAddressAny4 extends TensorAddressAny {
+
private final int label0, label1, label2, label3;
+
TensorAddressAny4(int label0, int label1, int label2, int label3) {
this.label0 = label0;
this.label1 = label1;
@@ -59,4 +62,5 @@ final class TensorAddressAny4 extends TensorAddressAny {
(label2 == any.label2) &&
(label3 == any.label3);
}
+
}
diff --git a/vespajlib/src/main/java/com/yahoo/tensor/impl/TensorAddressAnyN.java b/vespajlib/src/main/java/com/yahoo/tensor/impl/TensorAddressAnyN.java
index acd7ed60722..d5bac62bf18 100644
--- a/vespajlib/src/main/java/com/yahoo/tensor/impl/TensorAddressAnyN.java
+++ b/vespajlib/src/main/java/com/yahoo/tensor/impl/TensorAddressAnyN.java
@@ -9,22 +9,26 @@ import java.util.Arrays;
import static java.lang.Math.abs;
/**
- * N dimensional address
+ * An n-dimensional address.
+ *
* @author baldersheim
*/
final class TensorAddressAnyN extends TensorAddressAny {
- private final int [] labels;
- TensorAddressAnyN(int [] labels) {
+
+ private final int[] labels;
+
+ TensorAddressAnyN(int[] labels) {
if (labels.length < 1) throw new IllegalArgumentException("Need at least 1 label");
this.labels = labels;
}
@Override public int size() { return labels.length; }
+
@Override public long numericLabel(int i) { return labels[i]; }
@Override
public TensorAddress withLabel(int labelIndex, long label) {
- int [] copy = Arrays.copyOf(labels, labels.length);
+ int[] copy = Arrays.copyOf(labels, labels.length);
copy[labelIndex] = Convert.safe2Int(label);
return new TensorAddressAnyN(copy);
}
@@ -45,4 +49,5 @@ final class TensorAddressAnyN extends TensorAddressAny {
}
return true;
}
+
}
diff --git a/vespajlib/src/main/java/com/yahoo/tensor/impl/TensorAddressEmpty.java b/vespajlib/src/main/java/com/yahoo/tensor/impl/TensorAddressEmpty.java
index 2d9cd3eed78..eb7e62e913b 100644
--- a/vespajlib/src/main/java/com/yahoo/tensor/impl/TensorAddressEmpty.java
+++ b/vespajlib/src/main/java/com/yahoo/tensor/impl/TensorAddressEmpty.java
@@ -5,13 +5,18 @@ package com.yahoo.tensor.impl;
import com.yahoo.tensor.TensorAddress;
/**
- * 0 dimesional/empty address
+ * A zero-dimensional address.
+ *
* @author baldersheim
*/
final class TensorAddressEmpty extends TensorAddressAny {
+
static TensorAddress empty = new TensorAddressEmpty();
+
private TensorAddressEmpty() {}
+
@Override public int size() { return 0; }
+
@Override public long numericLabel(int i) { throw new IllegalArgumentException("Empty address with no labels"); }
@Override
@@ -21,6 +26,8 @@ final class TensorAddressEmpty extends TensorAddressAny {
@Override
public int hashCode() { return 0; }
+
@Override
public boolean equals(Object o) { return o instanceof TensorAddressEmpty; }
+
}
diff --git a/vespajlib/src/test/java/com/yahoo/tensor/impl/TensorAddressAnyTestCase.java b/vespajlib/src/test/java/com/yahoo/tensor/impl/TensorAddressAnyTestCase.java
index ae13b95052b..18ff1f6a1d3 100644
--- a/vespajlib/src/test/java/com/yahoo/tensor/impl/TensorAddressAnyTestCase.java
+++ b/vespajlib/src/test/java/com/yahoo/tensor/impl/TensorAddressAnyTestCase.java
@@ -6,11 +6,15 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
+/**
+ * @author baldersheim
+ */
public class TensorAddressAnyTestCase {
+
@Test
void testSize() {
for (int i = 0; i < 10; i++) {
- int [] indexes = new int [i];
+ int[] indexes = new int[i];
assertEquals(i, of(indexes).size());
}
}
@@ -18,8 +22,8 @@ public class TensorAddressAnyTestCase {
@Test
void testNumericStringEquality() {
for (int i = 0; i < 10; i++) {
- int [] numericIndexes = new int [i];
- String [] stringIndexes = new String[i];
+ int[] numericIndexes = new int[i];
+ String[] stringIndexes = new String[i];
for (int j = 0; j < i; j++) {
numericIndexes[j] = j;
stringIndexes[j] = String.valueOf(j);