src);
/**
* Checks equality between n-dimensional arrays.
diff --git a/ndarray/src/main/java/org/tensorflow/ndarray/NdArrays.java b/ndarray/src/main/java/org/tensorflow/ndarray/NdArrays.java
index 8ad55ca..d79b781 100644
--- a/ndarray/src/main/java/org/tensorflow/ndarray/NdArrays.java
+++ b/ndarray/src/main/java/org/tensorflow/ndarray/NdArrays.java
@@ -1,23 +1,21 @@
/*
- Copyright 2019 The TensorFlow Authors. All Rights Reserved.
+Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
+ http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- =======================================================================
- */
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+=======================================================================
+*/
package org.tensorflow.ndarray;
-import org.tensorflow.ndarray.impl.dense.DenseNdArray;
-import org.tensorflow.ndarray.impl.dense.IntDenseNdArray;
import org.tensorflow.ndarray.buffer.BooleanDataBuffer;
import org.tensorflow.ndarray.buffer.ByteDataBuffer;
import org.tensorflow.ndarray.buffer.DataBuffer;
@@ -29,14 +27,22 @@
import org.tensorflow.ndarray.buffer.ShortDataBuffer;
import org.tensorflow.ndarray.impl.dense.BooleanDenseNdArray;
import org.tensorflow.ndarray.impl.dense.ByteDenseNdArray;
+import org.tensorflow.ndarray.impl.dense.DenseNdArray;
import org.tensorflow.ndarray.impl.dense.DoubleDenseNdArray;
import org.tensorflow.ndarray.impl.dense.FloatDenseNdArray;
+import org.tensorflow.ndarray.impl.dense.IntDenseNdArray;
import org.tensorflow.ndarray.impl.dense.LongDenseNdArray;
import org.tensorflow.ndarray.impl.dense.ShortDenseNdArray;
-
-/**
- * Utility class for instantiating {@link NdArray} objects.
- */
+import org.tensorflow.ndarray.impl.dimension.DimensionalSpace;
+import org.tensorflow.ndarray.impl.sparse.BooleanSparseNdArray;
+import org.tensorflow.ndarray.impl.sparse.ByteSparseNdArray;
+import org.tensorflow.ndarray.impl.sparse.DoubleSparseNdArray;
+import org.tensorflow.ndarray.impl.sparse.FloatSparseNdArray;
+import org.tensorflow.ndarray.impl.sparse.IntSparseNdArray;
+import org.tensorflow.ndarray.impl.sparse.LongSparseNdArray;
+import org.tensorflow.ndarray.impl.sparse.ShortSparseNdArray;
+
+/** Utility class for instantiating {@link NdArray} objects. */
public final class NdArrays {
// BYTE ARRAYS
@@ -54,8 +60,8 @@ public static ByteNdArray scalarOf(byte value) {
/**
* Creates a byte vector (rank 1) initialized with the given values.
*
- * Modifying the data of the returned vector will also impact the values in the array
- * passed in parameter.
+ *
Modifying the data of the returned vector will also impact the values in the array passed in
+ * parameter.
*
* @param values vector values
* @return new byte vector
@@ -90,13 +96,51 @@ public static ByteNdArray ofBytes(Shape shape) {
* @param shape shape of the array
* @param buffer buffer to wrap
* @return new byte N-dimensional array
- * @throws IllegalArgumentException if shape is null, has unknown dimensions or has size bigger
- * in the buffer size
+ * @throws IllegalArgumentException if shape is null, has unknown dimensions or has size bigger in
+ * the buffer size
*/
public static ByteNdArray wrap(Shape shape, ByteDataBuffer buffer) {
return ByteDenseNdArray.create(buffer, shape);
}
+ /**
+ * Creates a Sparse array of byte values with a default value of zero
+ *
+ * @param indices A 2-D LongNdArray of shape {@code [N, ndims]}, that specifies the indices of the
+ * elements in the sparse array that contain non-default values (elements are zero-indexed).
+ * For example, {@code indices=[[1,3,1], [2,4,0]]} specifies that the elements with indexes of
+ * {@code [1,3,1]} and {@code [2,4,0]} have non-default values.
+ * @param values A 1-D ByteNdArray of shape {@code [N]}, which supplies the values for each
+ * element in indices. For example, given {@code indices=[[1,3,1], [2,4,0]]}, the parameter {@code
+ * values=[18, 3]} specifies that element {@code [1,3,1]} of the sparse NdArray has a value of
+ * {@code 18}, and element {@code [2,4,0]} of the NdArray has a value of {@code 3}.
+ * @param shape the shape of the dense array represented by this sparse array.
+ * @return the byte sparse array.
+ */
+ public static ByteSparseNdArray sparseOf(LongNdArray indices, ByteNdArray values, Shape shape) {
+ return ByteSparseNdArray.create(indices, values, DimensionalSpace.create(shape));
+ }
+
+ /**
+ * Creates a Sparse array of byte values
+ *
+ * @param indices A 2-D LongNdArray of shape {@code [N, ndims]}, that specifies the indices of the
+ * elements in the sparse array that contain non-default values (elements are zero-indexed).
+ * For example, {@code indices=[[1,3,1], [2,4,0]]} specifies that the elements with indexes of
+ * {@code [1,3,1]} and {@code [2,4,0]} have non default values.
+ * @param values A 1-D ByteNdArray of shape {@code [N]}, which supplies the values for each
+ * element in indices. For example, given {@code indices=[[1,3,1], [2,4,0]]}, the parameter {@code
+ * values=[18, 3]} specifies that element {@code [1,3,1]} of the sparse NdArray has a value of
+ * {@code 18}, and element {@code [2,4,0]} of the NdArray has a value of {@code 3}.
+ * @param defaultValue Scalar value to set for indices not specified in 'indices'
+ * @param shape the shape of the dense array represented by this sparse array.
+ * @return the byte sparse array.
+ */
+ public static ByteSparseNdArray sparseOf(
+ LongNdArray indices, ByteNdArray values, byte defaultValue, Shape shape) {
+ return ByteSparseNdArray.create(indices, values, defaultValue, DimensionalSpace.create(shape));
+ }
+
// LONG ARRAYS
/**
@@ -112,8 +156,8 @@ public static LongNdArray scalarOf(long value) {
/**
* Creates a long vector (rank 1) initialized with the given values.
*
- *
Modifying the data of the returned vector will also impact the values in the array
- * passed in parameter.
+ *
Modifying the data of the returned vector will also impact the values in the array passed in
+ * parameter.
*
* @param values vector values
* @return new long vector
@@ -145,13 +189,51 @@ public static LongNdArray ofLongs(Shape shape) {
* @param shape shape of the array
* @param buffer buffer to wrap
* @return new long N-dimensional array
- * @throws IllegalArgumentException if shape is null, has unknown dimensions or has size bigger
- * in the buffer size
+ * @throws IllegalArgumentException if shape is null, has unknown dimensions or has size bigger in
+ * the buffer size
*/
public static LongNdArray wrap(Shape shape, LongDataBuffer buffer) {
return LongDenseNdArray.create(buffer, shape);
}
+ /**
+ * Creates a Sparse array of long values with a default value of zero
+ *
+ * @param indices A 2-D LongNdArray of shape {@code [N, ndims]}, that specifies the indices of the
+ * elements in the sparse array that contain non-default values (elements are zero-indexed).
+ * For example, {@code indices=[[1,3,1], [2,4,0]]} specifies that the elements with indexes of
+ * {@code [1,3,1]} and {@code [2,4,0]} have non-default values.
+ * @param values A 1-D LongNdArray of shape {@code [N]}, which supplies the values for each
+ * element in indices. For example, given {@code indices=[[1,3,1], [2,4,0]]}, the parameter {@code
+ * values=[18L, 3L]} specifies that element {@code [1,3,1]} of the sparse NdArray has a value of
+ * {@code 18L}, and element {@code [2,4,0]} of the NdArray has a value of {@code 3L}.
+ * @param shape the shape of the dense array represented by this sparse array.
+ * @return the long sparse array.
+ */
+ public static LongSparseNdArray sparseOf(LongNdArray indices, LongNdArray values, Shape shape) {
+ return LongSparseNdArray.create(indices, values, DimensionalSpace.create(shape));
+ }
+
+ /**
+ * Creates a Sparse array of long values with a default value of zero
+ *
+ * @param indices A 2-D LongNdArray of shape {@code [N, ndims]}, that specifies the indices of the
+ * elements in the sparse array that contain non-default values (elements are zero-indexed).
+ * For example, {@code indices=[[1,3,1], [2,4,0]]} specifies that the elements with indexes of
+ * {@code [1,3,1]} and {@code [2,4,0]} have non-default values.
+ * @param values A 1-D LongNdArray of shape {@code [N]}, which supplies the values for each
+ * element in indices. For example, given {@code indices=[[1,3,1], [2,4,0]]}, the parameter {@code
+ * values=[18L, 3L]} specifies that element {@code [1,3,1]} of the sparse NdArray has a value of
+ * {@code 18L}, and element {@code [2,4,0]} of the NdArray has a value of {@code 3L}.
+ * @param defaultValue Scalar value to set for indices not specified in 'indices'
+ * @param shape the shape of the dense array represented by this sparse array.
+ * @return the long sparse array.
+ */
+ public static LongSparseNdArray sparseOf(
+ LongNdArray indices, LongNdArray values, long defaultValue, Shape shape) {
+ return LongSparseNdArray.create(indices, values, defaultValue, DimensionalSpace.create(shape));
+ }
+
// INT ARRAYS
/**
@@ -167,8 +249,8 @@ public static IntNdArray scalarOf(int value) {
/**
* Creates a int vector (rank 1) initialized with the given values.
*
- *
Modifying the data of the returned vector will also impact the values in the array
- * passed in parameter.
+ *
Modifying the data of the returned vector will also impact the values in the array passed in
+ * parameter.
*
* @param values vector values
* @return new int vector
@@ -200,13 +282,51 @@ public static IntNdArray ofInts(Shape shape) {
* @param shape shape of the array
* @param buffer buffer to wrap
* @return new int N-dimensional array
- * @throws IllegalArgumentException if shape is null, has unknown dimensions or has size bigger
- * in the buffer size
+ * @throws IllegalArgumentException if shape is null, has unknown dimensions or has size bigger in
+ * the buffer size
*/
public static IntNdArray wrap(Shape shape, IntDataBuffer buffer) {
return IntDenseNdArray.create(buffer, shape);
}
+ /**
+ * Creates a Sparse array of int values with a default value of zero.
+ *
+ * @param indices A 2-D LongNdArray of shape {@code [N, ndims]}, that specifies the indices of the
+ * elements in the sparse array that contain non-default values (elements are zero-indexed).
+ * For example, {@code indices=[[1,3,1], [2,4,0]]} specifies that the elements with indexes of
+ * {@code [1,3,1]} and {@code [2,4,0]} have non-default values.
+ * @param values A 1-D IntNdArray of shape {@code [N]}, which supplies the values for each element
+ * in indices. For example, given {@code indices=[[1,3,1], [2,4,0]]}, the parameter {@code
+ * values=[18, 3]} specifies that element {@code [1,3,1]} of the sparse NdArray has a value of
+ * {@code 18}, and element {@code [2,4,0]} of the NdArray has a value of {@code 3}.
+ * @param shape the shape of the dense array represented by this sparse array.
+ * @return the int sparse array.
+ */
+ public static IntSparseNdArray sparseOf(LongNdArray indices, IntNdArray values, Shape shape) {
+ return IntSparseNdArray.create(indices, values, DimensionalSpace.create(shape));
+ }
+
+ /**
+ * Creates a Sparse array of int values
+ *
+ * @param indices A 2-D LongNdArray of shape {@code [N, ndims]}, that specifies the indices of the
+ * elements in the sparse array that contain non-default values (elements are zero-indexed).
+ * For example, {@code indices=[[1,3,1], [2,4,0]]} specifies that the elements with indexes of
+ * {@code [1,3,1]} and {@code [2,4,0]} have non-default values.
+ * @param values A 1-D IntNdArray of shape {@code [N]}, which supplies the values for each element
+ * in indices. For example, given {@code indices=[[1,3,1], [2,4,0]]}, the parameter {@code
+ * values=[18, 3]} specifies that element {@code [1,3,1]} of the sparse NdArray has a value of
+ * {@code 18}, and element {@code [2,4,0]} of the NdArray has a value of {@code 3}.
+ * @param defaultValue Scalar value to set for indices not specified in 'indices'
+ * @param shape the shape of the dense array represented by this sparse array.
+ * @return the int sparse array.
+ */
+ public static IntSparseNdArray sparseOf(
+ LongNdArray indices, IntNdArray values, int defaultValue, Shape shape) {
+ return IntSparseNdArray.create(indices, values, defaultValue, DimensionalSpace.create(shape));
+ }
+
// SHORT ARRAYS
/**
@@ -222,8 +342,8 @@ public static ShortNdArray scalarOf(short value) {
/**
* Creates a short vector (rank 1) initialized with the given values.
*
- *
Modifying the data of the returned vector will also impact the values in the array
- * passed in parameter.
+ *
Modifying the data of the returned vector will also impact the values in the array passed in
+ * parameter.
*
* @param values vector values
* @return new short vector
@@ -255,13 +375,51 @@ public static ShortNdArray ofShorts(Shape shape) {
* @param shape shape of the array
* @param buffer buffer to wrap
* @return new short N-dimensional array
- * @throws IllegalArgumentException if shape is null, has unknown dimensions or has size bigger
- * in the buffer size
+ * @throws IllegalArgumentException if shape is null, has unknown dimensions or has size bigger in
+ * the buffer size
*/
public static ShortNdArray wrap(Shape shape, ShortDataBuffer buffer) {
return ShortDenseNdArray.create(buffer, shape);
}
+ /**
+ * Creates a Sparse array of short values with a default value of zero
+ *
+ * @param indices A 2-D LongNdArray of shape {@code [N, ndims]}, that specifies the indices of the
+ * elements in the sparse array that contain non-default values (elements are zero-indexed).
+ * For example, {@code indices=[[1,3,1], [2,4,0]]} specifies that the elements with indexes of
+ * {@code [1,3,1]} and {@code [2,4,0]} have non-default values.
+ * @param values A 1-D ShortNdArray of shape {@code [N]}, which supplies the values for each
+ * element in indices. For example, given {@code indices=[[1,3,1], [2,4,0]]}, the parameter {@code
+ * values=[18, 3]} specifies that element {@code [1,3,1]} of the sparse NdArray has a value of
+ * {@code 18}, and element {@code [2,4,0]} of the NdArray has a value of {@code 3}.
+ * @param shape the shape of the dense array represented by this sparse array.
+ * @return the short sparse array.
+ */
+ public static ShortSparseNdArray sparseOf(LongNdArray indices, ShortNdArray values, Shape shape) {
+ return ShortSparseNdArray.create(indices, values, DimensionalSpace.create(shape));
+ }
+
+ /**
+ * Creates a Sparse array of short values
+ *
+ * @param indices A 2-D LongNdArray of shape {@code [N, ndims]}, that specifies the indices of the
+ * elements in the sparse array that contain non-default values (elements are zero-indexed).
+ * For example, {@code indices=[[1,3,1], [2,4,0]]} specifies that the elements with indexes of
+ * {@code [1,3,1]} and {@code [2,4,0]} have non-default values.
+ * @param values A 1-D ShortNdArray of shape {@code [N]}, which supplies the values for each
+ * element in indices. For example, given {@code indices=[[1,3,1], [2,4,0]]}, the parameter {@code
+ * values=[18, 3]} specifies that element {@code [1,3,1]} of the sparse NdArray has a value of
+ * {@code 18}, and element {@code [2,4,0]} of the NdArray has a value of {@code 3}.
+ * @param defaultValue Scalar value to set for indices not specified in 'indices'
+ * @param shape the shape of the dense array represented by this sparse array.
+ * @return the short sparse array.
+ */
+ public static ShortSparseNdArray sparseOf(
+ LongNdArray indices, ShortNdArray values, short defaultValue, Shape shape) {
+ return ShortSparseNdArray.create(indices, values, defaultValue, DimensionalSpace.create(shape));
+ }
+
// FLOAT ARRAYS
/**
@@ -277,8 +435,8 @@ public static FloatNdArray scalarOf(float value) {
/**
* Creates a float vector (rank 1) initialized with the given values.
*
- *
Modifying the data of the returned vector will also impact the values in the array
- * passed in parameter.
+ *
Modifying the data of the returned vector will also impact the values in the array passed in
+ * parameter.
*
* @param values vector values
* @return new float vector
@@ -310,13 +468,51 @@ public static FloatNdArray ofFloats(Shape shape) {
* @param shape shape of the array
* @param buffer buffer to wrap
* @return new float N-dimensional array
- * @throws IllegalArgumentException if shape is null, has unknown dimensions or has size bigger
- * in the buffer size
+ * @throws IllegalArgumentException if shape is null, has unknown dimensions or has size bigger in
+ * the buffer size
*/
public static FloatNdArray wrap(Shape shape, FloatDataBuffer buffer) {
return FloatDenseNdArray.create(buffer, shape);
}
+ /**
+ * Creates a Sparse array of float values with a default value of zero
+ *
+ * @param indices A 2-D LongNdArray of shape {@code [N, ndims]}, that specifies the indices of the
+ * elements in the sparse array that contain non-default values (elements are zero-indexed).
+ * For example, {@code indices=[[1,3,1], [2,4,0]]} specifies that the elements with indexes of
+ * {@code [1,3,1]} and {@code [2,4,0]} have non-default values.
+ * @param values A 1-D FloatNdArray of shape {@code [N]}, which supplies the values for each
+ * element in indices. For example, given {@code indices=[[1,3,1], [2,4,0]]}, the parameter {@code
+ * values=[18f, 3.8f]} specifies that element {@code [1,3,1]} of the sparse NdArray has a value of
+ * {@code 18f}, and element {@code [2,4,0]} of the NdArray has a value of {@code 3.8f}.
+ * @param shape the shape of the dense array represented by this sparse array.
+ * @return the float sparse array.
+ */
+ public static FloatSparseNdArray sparseOf(LongNdArray indices, FloatNdArray values, Shape shape) {
+ return FloatSparseNdArray.create(indices, values, DimensionalSpace.create(shape));
+ }
+
+ /**
+ * Creates a Sparse array of float values
+ *
+ * @param indices A 2-D LongNdArray of shape {@code [N, ndims]}, that specifies the indices of the
+ * elements in the sparse array that contain non-default values (elements are zero-indexed).
+ * For example, {@code indices=[[1,3,1], [2,4,0]]} specifies that the elements with indexes of
+ * {@code [1,3,1]} and {@code [2,4,0]} have non-default values.
+ * @param values A 1-D FloatNdArray of shape {@code [N]}, which supplies the values for each
+ * element in indices. For example, given {@code indices=[[1,3,1], [2,4,0]]}, the parameter {@code
+ * values=[18f, 3.8f]} specifies that element {@code [1,3,1]} of the sparse NdArray has a value of
+ * {@code 18f}, and element {@code [2,4,0]} of the NdArray has a value of {@code 3.8f}.
+ * @param defaultValue Scalar value to set for indices not specified in 'indices'
+ * @param shape the shape of the dense array represented by this sparse array.
+ * @return the float sparse array.
+ */
+ public static FloatSparseNdArray sparseOf(
+ LongNdArray indices, FloatNdArray values, float defaultValue, Shape shape) {
+ return FloatSparseNdArray.create(indices, values, defaultValue, DimensionalSpace.create(shape));
+ }
+
// DOUBLE ARRAYS
/**
@@ -332,8 +528,8 @@ public static DoubleNdArray scalarOf(double value) {
/**
* Creates a double vector (rank 1) initialized with the given values.
*
- *
Modifying the data of the returned vector will also impact the values in the array
- * passed in parameter.
+ *
Modifying the data of the returned vector will also impact the values in the array passed in
+ * parameter.
*
* @param values vector values
* @return new double vector
@@ -365,13 +561,53 @@ public static DoubleNdArray ofDoubles(Shape shape) {
* @param shape shape of the array
* @param buffer buffer to wrap
* @return new double N-dimensional array
- * @throws IllegalArgumentException if shape is null, has unknown dimensions or has size bigger
- * in the buffer size
+ * @throws IllegalArgumentException if shape is null, has unknown dimensions or has size bigger in
+ * the buffer size
*/
public static DoubleNdArray wrap(Shape shape, DoubleDataBuffer buffer) {
return DoubleDenseNdArray.create(buffer, shape);
}
+ /**
+ * Creates a Sparse array of double values with a default value of zero
+ *
+ * @param indices A 2-D LongNdArray of shape {@code [N, ndims]}, that specifies the indices of the
+ * elements in the sparse array that contain non-default values (elements are zero-indexed).
+ * For example, {@code indices=[[1,3,1], [2,4,0]]} specifies that the elements with indexes of
+ * {@code [1,3,1]} and {@code [2,4,0]} have non-default values.
+ * @param values A 1-D DoubleNdArray of shape {@code [N]}, which supplies the values for each
+ * element in indices. For example, given {@code indices=[[1,3,1], [2,4,0]]}, the parameter {@code
+ * values=[18, 3.8]} specifies that element {@code [1,3,1]} of the sparse NdArray has a value of
+ * {@code 18}, and element {@code [2,4,0]} of the NdArray has a value of {@code 3.8}.
+ * @param shape the shape of the dense array represented by this sparse array.
+ * @return the float sparse array.
+ */
+ public static DoubleSparseNdArray sparseOf(
+ LongNdArray indices, DoubleNdArray values, Shape shape) {
+ return DoubleSparseNdArray.create(indices, values, DimensionalSpace.create(shape));
+ }
+
+ /**
+ * Creates a Sparse array of double values
+ *
+ * @param indices A 2-D LongNdArray of shape {@code [N, ndims]}, that specifies the indices of the
+ * elements in the sparse array that contain non-default values (elements are zero-indexed).
+ * For example, {@code indices=[[1,3,1], [2,4,0]]} specifies that the elements with indexes of
+ * {@code [1,3,1]} and {@code [2,4,0]} have non-default values.
+ * @param values A 1-D DoubleNdArray of shape {@code [N]}, which supplies the values for each
+ * element in indices. For example, given {@code indices=[[1,3,1], [2,4,0]]}, the parameter {@code
+ * values=[18, 3.8]} specifies that element {@code [1,3,1]} of the sparse NdArray has a value of
+ * {@code 18}, and element {@code [2,4,0]} of the NdArray has a value of {@code 3.8}.
+ * @param defaultValue Scalar value to set for indices not specified in 'indices'
+ * @param shape the shape of the dense array represented by this sparse array.
+ * @return the float sparse array.
+ */
+ public static DoubleSparseNdArray sparseOf(
+ LongNdArray indices, DoubleNdArray values, double defaultValue, Shape shape) {
+ return DoubleSparseNdArray.create(
+ indices, values, defaultValue, DimensionalSpace.create(shape));
+ }
+
// BOOLEAN ARRAYS
/**
@@ -387,8 +623,8 @@ public static BooleanNdArray scalarOf(boolean value) {
/**
* Creates a boolean vector (rank 1) initialized with the given values.
*
- *
Modifying the data of the returned vector will also impact the values in the array
- * passed in parameter.
+ *
Modifying the data of the returned vector will also impact the values in the array passed in
+ * parameter.
*
* @param values vector values
* @return new boolean vector
@@ -420,13 +656,55 @@ public static BooleanNdArray ofBooleans(Shape shape) {
* @param shape shape of the array
* @param buffer buffer to wrap
* @return new boolean N-dimensional array
- * @throws IllegalArgumentException if shape is null, has unknown dimensions or has size bigger
- * in the buffer size
+ * @throws IllegalArgumentException if shape is null, has unknown dimensions or has size bigger in
+ * the buffer size
*/
public static BooleanNdArray wrap(Shape shape, BooleanDataBuffer buffer) {
return BooleanDenseNdArray.create(buffer, shape);
}
+ /**
+ * Creates a Sparse array of boolean values with a default value of 'false'
+ *
+ * @param indices A 2-D LongNdArray of shape {@code [N, ndims]}, that specifies the indices of the
+ * elements in the sparse array that contain non-default values (elements are zero-indexed).
+ * For example, {@code indices=[[1,3,1], [2,4,0]]} specifies that the elements with indexes of
+ * {@code [1,3,1]} and {@code [2,4,0]} have non-default values.
+ * @param values A 1-D BooleanNdArray of shape {@code [N]}, which supplies the values for each
+ * element in indices. For example, given {@code indices=[[1,3,1], [2,4,0]]}, the parameter {@code
+ * values=[true, true]} specifies that element {@code [1,3,1]} of the sparse NdArray has a value
+ * of true, and element {@code [2,4,0]} of the NdArray has a value of true. All other values are
+ * false.
+ * @param shape the shape of the dense array represented by this sparse array.
+ * @return the float sparse array.
+ */
+ public static BooleanSparseNdArray sparseOf(
+ LongNdArray indices, BooleanNdArray values, Shape shape) {
+ return BooleanSparseNdArray.create(indices, values, DimensionalSpace.create(shape));
+ }
+
+ /**
+ * Creates a Sparse array of boolean values
+ *
+ * @param indices A 2-D LongNdArray of shape {@code [N, ndims]}, that specifies the indices of the
+ * elements in the sparse array that contain non-default values (elements are zero-indexed).
+ * For example, {@code indices=[[1,3,1], [2,4,0]]} specifies that the elements with indexes of
+ * {@code [1,3,1]} and {@code [2,4,0]} have non-default values.
+ * @param values A 1-D BooleanNdArray of shape {@code [N]}, which supplies the values for each
+ * element in indices. For example, given {@code indices=[[1,3,1], [2,4,0]]}, the parameter {@code
+ * values=[true, true]} specifies that element {@code [1,3,1]} of the sparse NdArray has a value
+ * of true, and element {@code [2,4,0]} of the NdArray has a value of true. All other values are
+ * false.
+ * @param defaultValue Scalar value to set for indices not specified in 'indices'
+ * @param shape the shape of the dense array represented by this sparse array.
+ * @return the float sparse array.
+ */
+ public static BooleanSparseNdArray sparseOf(
+ LongNdArray indices, BooleanNdArray values, boolean defaultValue, Shape shape) {
+ return BooleanSparseNdArray.create(
+ indices, values, defaultValue, DimensionalSpace.create(shape));
+ }
+
// OBJECT ARRAYS
/**
@@ -441,14 +719,14 @@ public static NdArray scalarOfObject(T value) {
if (value == null) {
throw new IllegalArgumentException();
}
- return ofObjects((Class)value.getClass(), Shape.scalar()).setObject(value);
+ return ofObjects((Class) value.getClass(), Shape.scalar()).setObject(value);
}
/**
* Creates a vector (rank 1) initialized with the given values.
*
- * Modifying the data of the returned vector will also impact the values in the array
- * passed in parameter.
+ *
Modifying the data of the returned vector will also impact the values in the array passed in
+ * parameter.
*
* @param values vector values
* @param the data type
@@ -485,11 +763,55 @@ public static NdArray ofObjects(Class clazz, Shape shape) {
* @param buffer buffer to wrap
* @param the data type
* @return new N-dimensional array
- * @throws IllegalArgumentException if shape is null, has unknown dimensions or has size bigger
- * in the buffer size
+ * @throws IllegalArgumentException if shape is null, has unknown dimensions or has size bigger in
+ * the buffer size
*/
public static NdArray wrap(Shape shape, DataBuffer buffer) {
return DenseNdArray.wrap(buffer, shape);
}
-}
+ /**
+ * Creates a Sparse array of values with a null default value
+ *
+ * @param type the class type represented by this sparse array.
+ * @param indices A 2-D LongNdArray of shape {@code [N, ndims]}, that specifies the indices of the
+ * elements in the sparse array that contain non-default values (elements are zero-indexed).
+ * For example, {@code indices=[[1,3,1], [2,4,0]]} specifies that the elements with indexes of
+ * {@code [1,3,1]} and {@code [2,4,0]} have non-default values.
+ * @param values A 1-D NdArray of shape {@code [N]}, which supplies the values for each element in
+ * indices. For example, given {@code indices=[[1,3,1], [2,4,0]]}, the parameter {@code
+ * values=["one", "two"]} specifies that element {@code [1,3,1]} of the sparse NdArray has a
+ * value of "one", and element {@code [2,4,0]} of the NdArray has a value of "two"". All other
+ * values are null.
+ * @param shape the shape of the dense array represented by this sparse array.
+ * @return the float sparse array.
+ */
+ public static NdArray sparseOfObjects(
+ Class type, LongNdArray indices, NdArray values, Shape shape) {
+ return org.tensorflow.ndarray.impl.sparse.SparseNdArray.create(
+ type, indices, values, DimensionalSpace.create(shape));
+ }
+
+ /**
+ * Creates a Sparse array of values
+ *
+ * @param type the class type represented by this sparse array.
+ * @param indices A 2-D LongNdArray of shape {@code [N, ndims]}, that specifies the indices of the
+ * elements in the sparse array that contain non-default values (elements are zero-indexed).
+ * For example, {@code indices=[[1,3,1], [2,4,0]]} specifies that the elements with indexes of
+ * {@code [1,3,1]} and {@code [2,4,0]} have non-default values.
+ * @param values A 1-D NdArray of shape {@code [N]}, which supplies the values for each element in
+ * indices. For example, given {@code indices=[[1,3,1], [2,4,0]]}, the parameter {@code
+ * values=["one", "two"]} specifies that element {@code [1,3,1]} of the sparse NdArray has a
+ * value of "one", and element {@code [2,4,0]} of the NdArray has a value of "two"". All other
+ * values are null.
+ * @param defaultValue Scalar value to set for indices not specified in 'indices'
+ * @param shape the shape of the dense array represented by this sparse array.
+ * @return the float sparse array.
+ */
+ public static NdArray sparseOfObjects(
+ Class type, LongNdArray indices, NdArray values, T defaultValue, Shape shape) {
+ return org.tensorflow.ndarray.impl.sparse.SparseNdArray.create(
+ type, indices, values, defaultValue, DimensionalSpace.create(shape));
+ }
+}
diff --git a/ndarray/src/main/java/org/tensorflow/ndarray/Shape.java b/ndarray/src/main/java/org/tensorflow/ndarray/Shape.java
index 85a9054..d8bb2bb 100644
--- a/ndarray/src/main/java/org/tensorflow/ndarray/Shape.java
+++ b/ndarray/src/main/java/org/tensorflow/ndarray/Shape.java
@@ -17,7 +17,9 @@
package org.tensorflow.ndarray;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.List;
/**
* The shape of a Tensor or {@link NdArray}.
@@ -74,8 +76,8 @@ public static Shape scalar() {
* Shape scalar = Shape.of()
* }
*
- * @param dimensionSizes number of elements in each dimension of this shape, if any, or
- * {@link Shape#UNKNOWN_SIZE} if unknown.
+ * @param dimensionSizes number of elements in each dimension of this shape, if any, or {@link
+ * Shape#UNKNOWN_SIZE} if unknown.
* @return a new shape
*/
public static Shape of(long... dimensionSizes) {
@@ -108,13 +110,34 @@ public long size() {
* an unknown size, {@link Shape#UNKNOWN_SIZE} is returned.
*
* @param i the index of the dimension to get the size for. If this Shape has a known number of
- * dimensions, it must be < {@link Shape#numDimensions()}. The index may be negative, in which
- * case the position is counted from the end of the shape. E.g.: {@code size(-1)} returns the
- * size of the last dimension, {@code size(-2)} the size of the second to last dimension etc.
+ * dimensions, it must be < {@link Shape#numDimensions()}. The index may be negative, in
+ * which case the position is counted from the end of the shape. E.g.: {@code size(-1)}
+ * returns the size of the last dimension, {@code size(-2)} the size of the second to last
+ * dimension etc.
* @return The size of the dimension with the given index if known, {@link Shape#UNKNOWN_SIZE}
* otherwise.
+ * @deprecated Renamed to {@link #get(int)}.
*/
- public long size(int i) {
+ @Deprecated
+ public long size(int i){
+ return get(i);
+ }
+
+ /**
+ * The size of the dimension with the given index.
+ *
+ * If {@link Shape#isUnknown()} is true or the size of the dimension with the given index has
+ * an unknown size, {@link Shape#UNKNOWN_SIZE} is returned.
+ *
+ * @param i the index of the dimension to get the size for. If this Shape has a known number of
+ * dimensions, it must be < {@link Shape#numDimensions()}. The index may be negative, in
+ * which case the position is counted from the end of the shape. E.g.: {@code size(-1)}
+ * returns the size of the last dimension, {@code size(-2)} the size of the second to last
+ * dimension etc.
+ * @return The size of the dimension with the given index if known, {@link Shape#UNKNOWN_SIZE}
+ * otherwise.
+ */
+ public long get(int i) {
if (dimensionSizes == null) {
return UNKNOWN_SIZE;
} else if (i >= 0) {
@@ -177,6 +200,24 @@ public long[] asArray() {
}
}
+ /**
+ * Returns a defensive copy of the this Shape's axes. Changes to the returned list do not change
+ * this Shape's state. Returns null if {@link Shape#isUnknown()} is true.
+ */
+ public List toListOrNull() {
+ long[] array = asArray();
+ if (array == null) {
+ return null;
+ }
+
+ List list = new ArrayList<>(array.length);
+ for (long l : array) {
+ list.add(l);
+ }
+
+ return list;
+ }
+
@Override
public int hashCode() {
return dimensionSizes != null ? Arrays.hashCode(dimensionSizes) : super.hashCode();
@@ -186,6 +227,7 @@ public int hashCode() {
* Equals implementation for Shapes. Two Shapes are considered equal iff:
*
*
+ *
*
* - the number of dimensions is defined and equal for both
*
- the size of each dimension is defined and equal for both
@@ -236,7 +278,8 @@ public Shape head() {
* Returns an n-dimensional Shape with the dimensions matching the first n dimensions of this
* shape
*
- * @param n the number of leading dimensions to get, must be <= than {@link Shape#numDimensions()}
+ * @param n the number of leading dimensions to get, must be <= than {@link
+ * Shape#numDimensions()}
* @return an n-dimensional Shape with the first n dimensions matching the first n dimensions of
* this Shape
*/
@@ -252,7 +295,9 @@ public Shape take(int n) {
/** Returns a new Shape, with this Shape's first dimension removed. */
public Shape tail() {
- if (dimensionSizes.length < 2) return Shape.of();
+ if (dimensionSizes.length < 2) {
+ return Shape.of();
+ }
return Shape.of(Arrays.copyOfRange(dimensionSizes, 1, dimensionSizes.length));
}
@@ -276,15 +321,21 @@ public Shape takeLast(int n) {
}
/**
- * Return a {@code end - begin} dimensional shape with dimensions matching this Shape from {@code begin} to {@code end}.
+ * Return a {@code end - begin} dimensional shape with dimensions matching this Shape from {@code
+ * begin} to {@code end}.
+ *
* @param begin Where to start the sub-shape.
* @param end Where to end the sub-shape, exclusive.
* @return the sub-shape bounded by begin and end.
*/
- public Shape subShape(int begin, int end){
+ public Shape subShape(int begin, int end) {
if (end > numDimensions()) {
throw new ArrayIndexOutOfBoundsException(
- "End index " + end + " out of bounds: shape only has " + numDimensions() + " dimensions.");
+ "End index "
+ + end
+ + " out of bounds: shape only has "
+ + numDimensions()
+ + " dimensions.");
}
if (begin < 0) {
throw new ArrayIndexOutOfBoundsException(
@@ -423,7 +474,7 @@ public boolean isCompatibleWith(Shape shape) {
return false;
}
for (int i = 0; i < numDimensions(); i++) {
- if (!isCompatible(size(i), shape.size(i))) {
+ if (!isCompatible(get(i), shape.get(i))) {
return false;
}
}
diff --git a/ndarray/src/main/java/org/tensorflow/ndarray/ShortNdArray.java b/ndarray/src/main/java/org/tensorflow/ndarray/ShortNdArray.java
index f9335b4..022ccf7 100644
--- a/ndarray/src/main/java/org/tensorflow/ndarray/ShortNdArray.java
+++ b/ndarray/src/main/java/org/tensorflow/ndarray/ShortNdArray.java
@@ -68,6 +68,9 @@ public interface ShortNdArray extends NdArray {
*/
ShortNdArray setShort(short value, long... coordinates);
+ @Override
+ ShortNdArray withShape(Shape shape);
+
@Override
ShortNdArray slice(Index... coordinates);
@@ -97,12 +100,12 @@ default ShortNdArray setObject(Short value, long... coordinates) {
ShortNdArray copyTo(NdArray dst);
@Override
- ShortNdArray read(DataBuffer dst);
+ ShortNdArray copyTo(DataBuffer dst);
- ShortNdArray read(ShortDataBuffer dst);
+ ShortNdArray copyTo(ShortDataBuffer dst);
@Override
- ShortNdArray write(DataBuffer src);
+ ShortNdArray copyFrom(DataBuffer src);
- ShortNdArray write(ShortDataBuffer src);
+ ShortNdArray copyFrom(ShortDataBuffer src);
}
diff --git a/ndarray/src/main/java/org/tensorflow/ndarray/SparseNdArray.java b/ndarray/src/main/java/org/tensorflow/ndarray/SparseNdArray.java
new file mode 100644
index 0000000..ab91d1c
--- /dev/null
+++ b/ndarray/src/main/java/org/tensorflow/ndarray/SparseNdArray.java
@@ -0,0 +1,50 @@
+/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+=======================================================================*/
+package org.tensorflow.ndarray;
+
+/**
+ * Interface for Sparse Arrays
+ *
+ * @param the type that the array contains
+ * @param the type of dense NdArray
+ */
+public interface SparseNdArray> extends NdArray {
+ /**
+ * Gets the Indices
+ *
+ *
Indices are a A 2-D long array of shape {@code [N, ndims]}, that specifies the indices of
+ * the elements in the sparse array that contain nonzero values (elements are zero-indexed).
+ *
+ *
For example, {@code indices=[[1,3], [2,4]]} specifies that the elements with indexes of
+ * coordinates {@code [1,3]} and {@code [2,4]} have nonzero values.
+ *
+ * @return the Indices
+ */
+ LongNdArray getIndices();
+
+ /**
+ * Gets the values.
+ *
+ *
Values are a 1-D array of any type and shape {@code [N]}, that supplies the values for each
+ * element in indices.
+ *
+ *
For example, given {@code indices=[[1,3], [2,4]]}, and {@code values=[18, 3.6]} specifies
+ * that element {@code [1,3]} of the sparse array has a value of {@code 18}, and element {@code
+ * [2,4]} of the sparse array has a value of {@code 3.6}.
+ *
+ * @return the values
+ */
+ U getValues();
+}
diff --git a/ndarray/src/main/java/org/tensorflow/ndarray/StdArrays.java b/ndarray/src/main/java/org/tensorflow/ndarray/StdArrays.java
index 7d847bd..7367165 100644
--- a/ndarray/src/main/java/org/tensorflow/ndarray/StdArrays.java
+++ b/ndarray/src/main/java/org/tensorflow/ndarray/StdArrays.java
@@ -2010,7 +2010,7 @@ public static void copyFrom(IntNdArray src, int[] dst) {
if (src.size() > dst.length) {
throw new ArrayIndexOutOfBoundsException(String.valueOf(src.size()) + " > " + dst.length);
}
- src.read(DataBuffers.of(dst, false, false));
+ src.copyTo(DataBuffers.of(dst, false, false));
}
/**
@@ -2113,7 +2113,7 @@ public static void copyFrom(LongNdArray src, long[] dst) {
if (src.size() > dst.length) {
throw new ArrayIndexOutOfBoundsException(String.valueOf(src.size()) + " > " + dst.length);
}
- src.read(DataBuffers.of(dst, false, false));
+ src.copyTo(DataBuffers.of(dst, false, false));
}
/**
@@ -2216,7 +2216,7 @@ public static void copyFrom(FloatNdArray src, float[] dst) {
if (src.size() > dst.length) {
throw new ArrayIndexOutOfBoundsException(String.valueOf(src.size()) + " > " + dst.length);
}
- src.read(DataBuffers.of(dst, false, false));
+ src.copyTo(DataBuffers.of(dst, false, false));
}
/**
@@ -2319,7 +2319,7 @@ public static void copyFrom(DoubleNdArray src, double[] dst) {
if (src.size() > dst.length) {
throw new ArrayIndexOutOfBoundsException(String.valueOf(src.size()) + " > " + dst.length);
}
- src.read(DataBuffers.of(dst, false, false));
+ src.copyTo(DataBuffers.of(dst, false, false));
}
/**
@@ -2422,7 +2422,7 @@ public static void copyFrom(ByteNdArray src, byte[] dst) {
if (src.size() > dst.length) {
throw new ArrayIndexOutOfBoundsException(String.valueOf(src.size()) + " > " + dst.length);
}
- src.read(DataBuffers.of(dst, false, false));
+ src.copyTo(DataBuffers.of(dst, false, false));
}
/**
@@ -2525,7 +2525,7 @@ public static void copyFrom(ShortNdArray src, short[] dst) {
if (src.size() > dst.length) {
throw new ArrayIndexOutOfBoundsException(String.valueOf(src.size()) + " > " + dst.length);
}
- src.read(DataBuffers.of(dst, false, false));
+ src.copyTo(DataBuffers.of(dst, false, false));
}
/**
@@ -2628,7 +2628,7 @@ public static void copyFrom(BooleanNdArray src, boolean[] dst) {
if (src.size() > dst.length) {
throw new ArrayIndexOutOfBoundsException(String.valueOf(src.size()) + " > " + dst.length);
}
- src.read(DataBuffers.of(dst, false, false));
+ src.copyTo(DataBuffers.of(dst, false, false));
}
/**
@@ -2732,7 +2732,7 @@ public static void copyFrom(NdArray src, T[] dst) {
if (src.size() > dst.length) {
throw new ArrayIndexOutOfBoundsException(String.valueOf(src.size()) + " > " + dst.length);
}
- src.read(DataBuffers.of(dst, false, false));
+ src.copyTo(DataBuffers.of(dst, false, false));
}
/**
@@ -3798,9 +3798,9 @@ private static int[] computeArrayDims(NdArray> ndArray, int expectedRank) {
}
int[] arrayShape = new int[expectedRank];
for (int i = 0; i < expectedRank; ++i) {
- long dimSize = shape.size(i);
+ long dimSize = shape.get(i);
if (dimSize > Integer.MAX_VALUE) {
- throw new IllegalArgumentException("Dimension " + i + " is too large to fit in a standard array (" + shape.size(i) + ")");
+ throw new IllegalArgumentException("Dimension " + i + " is too large to fit in a standard array (" + shape.get(i) + ")");
}
arrayShape[i] = (int)dimSize;
}
diff --git a/ndarray/src/main/java/org/tensorflow/ndarray/impl/AbstractNdArray.java b/ndarray/src/main/java/org/tensorflow/ndarray/impl/AbstractNdArray.java
index 690dedc..cf0d9f1 100644
--- a/ndarray/src/main/java/org/tensorflow/ndarray/impl/AbstractNdArray.java
+++ b/ndarray/src/main/java/org/tensorflow/ndarray/impl/AbstractNdArray.java
@@ -1,30 +1,38 @@
/*
- Copyright 2019 The TensorFlow Authors. All Rights Reserved.
+Copyright 2019 The TensorFlow Authors. All Rights Reserved.
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
+ http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- =======================================================================
- */
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+=======================================================================
+*/
package org.tensorflow.ndarray.impl;
-import java.util.Iterator;
import org.tensorflow.ndarray.NdArray;
import org.tensorflow.ndarray.NdArraySequence;
import org.tensorflow.ndarray.Shape;
import org.tensorflow.ndarray.impl.dimension.DimensionalSpace;
+import java.util.Iterator;
+import java.util.Objects;
+
@SuppressWarnings("unchecked")
public abstract class AbstractNdArray> implements NdArray {
+ protected final DimensionalSpace dimensions;
+
+ protected AbstractNdArray(DimensionalSpace dimensions) {
+ this.dimensions = dimensions;
+ }
+
public abstract U slice(long position, DimensionalSpace dimensions);
public DimensionalSpace dimensions() {
@@ -39,7 +47,7 @@ public Shape shape() {
@Override
public NdArraySequence scalars() {
// negative if this array is a scalar, should be handled in `elements(dimIdx)`
- return (NdArraySequence)elements(shape().numDimensions() - 1);
+ return (NdArraySequence) elements(shape().numDimensions() - 1);
}
@Override
@@ -55,11 +63,7 @@ public boolean equals(Object obj) {
if (!(obj instanceof NdArray)) {
return false;
}
- return slowEquals((NdArray>)obj);
- }
-
- protected AbstractNdArray(DimensionalSpace dimensions) {
- this.dimensions = dimensions;
+ return slowEquals((NdArray>) obj);
}
protected void slowCopyTo(NdArray array) {
@@ -77,16 +81,19 @@ protected int slowHashCode() {
}
protected boolean slowEquals(NdArray> array) {
- if (!shape().equals(array.shape())) { // this guarantees also that we have the same number of scalar values
+ if (!shape()
+ .equals(
+ array.shape())) { // this guarantees also that we have the same number of scalar values
return false;
}
- for (Iterator extends NdArray>> thisIter = scalars().iterator(), otherIter = array.scalars().iterator(); thisIter.hasNext();) {
- if (!thisIter.next().getObject().equals(otherIter.next().getObject())) {
+ for (Iterator extends NdArray>> thisIter = scalars().iterator(),
+ otherIter = array.scalars().iterator();
+ thisIter.hasNext(); ) {
+ // Use Object.equals to handle nulls.
+ if (!Objects.equals(thisIter.next().getObject(), otherIter.next().getObject())) {
return false;
}
}
return true;
}
-
- protected final DimensionalSpace dimensions;
}
diff --git a/ndarray/src/main/java/org/tensorflow/ndarray/impl/Validator.java b/ndarray/src/main/java/org/tensorflow/ndarray/impl/Validator.java
index 285d099..3e0ba20 100644
--- a/ndarray/src/main/java/org/tensorflow/ndarray/impl/Validator.java
+++ b/ndarray/src/main/java/org/tensorflow/ndarray/impl/Validator.java
@@ -30,13 +30,13 @@ public static void copyToNdArrayArgs(NdArray> ndArray, NdArray> otherNdArray
}
}
- public static void readToBufferArgs(NdArray> ndArray, DataBuffer> dst) {
+ public static void copyToBufferArgs(NdArray> ndArray, DataBuffer> dst) {
if (dst.size() < ndArray.size()) {
throw new BufferOverflowException();
}
}
- public static void writeFromBufferArgs(NdArray> ndArray, DataBuffer> src) {
+ public static void copyFromBufferArgs(NdArray> ndArray, DataBuffer> src) {
if (src.size() < ndArray.size()) {
throw new BufferUnderflowException();
}
diff --git a/ndarray/src/main/java/org/tensorflow/ndarray/impl/buffer/raw/UnsafeReference.java b/ndarray/src/main/java/org/tensorflow/ndarray/impl/buffer/raw/UnsafeReference.java
index 7b95eac..a8cc16d 100644
--- a/ndarray/src/main/java/org/tensorflow/ndarray/impl/buffer/raw/UnsafeReference.java
+++ b/ndarray/src/main/java/org/tensorflow/ndarray/impl/buffer/raw/UnsafeReference.java
@@ -36,24 +36,24 @@ static boolean isAvailable() {
theUnsafe.setAccessible(true);
Object instance = theUnsafe.get(null);
if (instance.getClass() == clazz) {
- // Validate that this Unsafe instance exposes all methods we need
- clazz.getDeclaredMethod("getByte", Object.class, long.class);
- clazz.getDeclaredMethod("putByte", Object.class, long.class, byte.class);
- clazz.getDeclaredMethod("getShort", Object.class, long.class);
- clazz.getDeclaredMethod("putShort", Object.class, long.class, short.class);
- clazz.getDeclaredMethod("getInt", Object.class, long.class);
- clazz.getDeclaredMethod("putInt", Object.class, long.class, int.class);
- clazz.getDeclaredMethod("getLong", Object.class, long.class);
- clazz.getDeclaredMethod("putLong", Object.class, long.class, long.class);
- clazz.getDeclaredMethod("getFloat", Object.class, long.class);
- clazz.getDeclaredMethod("putFloat", Object.class, long.class, float.class);
- clazz.getDeclaredMethod("getDouble", Object.class, long.class);
- clazz.getDeclaredMethod("putDouble", Object.class, long.class, double.class);
- clazz.getDeclaredMethod("getBoolean", Object.class, long.class);
- clazz.getDeclaredMethod("putBoolean", Object.class, long.class, boolean.class);
- clazz.getDeclaredMethod("copyMemory", Object.class, long.class, Object.class, long.class, long.class);
- clazz.getDeclaredMethod("arrayBaseOffset", Class.class);
- clazz.getDeclaredMethod("arrayIndexScale", Class.class);
+ checkMethod(clazz, "getByte", Object.class, long.class);
+ checkMethod(clazz, "putByte", Object.class, long.class, byte.class);
+ checkMethod(clazz, "getShort", Object.class, long.class);
+ checkMethod(clazz, "putShort", Object.class, long.class, short.class);
+ checkMethod(clazz, "getInt", Object.class, long.class);
+ checkMethod(clazz, "putInt", Object.class, long.class, int.class);
+ checkMethod(clazz, "getLong", Object.class, long.class);
+ checkMethod(clazz, "putLong", Object.class, long.class, long.class);
+ checkMethod(clazz, "getFloat", Object.class, long.class);
+ checkMethod(clazz, "putFloat", Object.class, long.class, float.class);
+ checkMethod(clazz, "getDouble", Object.class, long.class);
+ checkMethod(clazz, "putDouble", Object.class, long.class, double.class);
+ checkMethod(clazz, "getBoolean", Object.class, long.class);
+ checkMethod(clazz, "putBoolean", Object.class, long.class, boolean.class);
+ checkMethod(clazz, "copyMemory", Object.class, long.class, Object.class, long.class, long.class);
+ checkMethod(clazz, "arrayBaseOffset", Class.class);
+ checkMethod(clazz, "arrayIndexScale", Class.class);
+
unsafe = (Unsafe) instance;
}
} catch (ClassNotFoundException | NoSuchMethodException | NoSuchFieldException | SecurityException | IllegalAccessException | ClassCastException ex) {
@@ -61,4 +61,14 @@ static boolean isAvailable() {
}
UNSAFE = unsafe;
}
+
+ /**
+ * Validate that this Unsafe instance exposes this method
+ *
+ * ErrorProne does not like that we do nothing with the returned method... but there is nothing to do with it, so disable the check
+ */
+ @SuppressWarnings("ReturnValueIgnored")
+ private static void checkMethod(Class> unsafeClass, String methodName, Class>... parameterTypes) throws NoSuchMethodException {
+ unsafeClass.getDeclaredMethod(methodName, parameterTypes);
+ }
}
diff --git a/ndarray/src/main/java/org/tensorflow/ndarray/impl/dense/AbstractDenseNdArray.java b/ndarray/src/main/java/org/tensorflow/ndarray/impl/dense/AbstractDenseNdArray.java
index 0497095..a22518d 100644
--- a/ndarray/src/main/java/org/tensorflow/ndarray/impl/dense/AbstractDenseNdArray.java
+++ b/ndarray/src/main/java/org/tensorflow/ndarray/impl/dense/AbstractDenseNdArray.java
@@ -18,6 +18,7 @@
import org.tensorflow.ndarray.NdArray;
import org.tensorflow.ndarray.NdArraySequence;
+import org.tensorflow.ndarray.Shape;
import org.tensorflow.ndarray.impl.AbstractNdArray;
import org.tensorflow.ndarray.impl.dimension.RelativeDimensionalSpace;
import org.tensorflow.ndarray.impl.sequence.FastElementSequence;
@@ -43,7 +44,7 @@ public NdArraySequence elements(int dimensionIdx) {
DimensionalSpace elemDims = dimensions().from(dimensionIdx + 1);
try {
DataBufferWindow extends DataBuffer> elemWindow = buffer().window(elemDims.physicalSize());
- U element = instantiate(elemWindow.buffer(), elemDims);
+ U element = instantiateView(elemWindow.buffer(), elemDims);
return new FastElementSequence(this, dimensionIdx, element, elemWindow);
} catch (UnsupportedOperationException e) {
// If buffer windows are not supported, fallback to slicing (and slower) sequence
@@ -51,10 +52,21 @@ public NdArraySequence elements(int dimensionIdx) {
}
}
+ @Override
+ public U withShape(Shape shape) {
+ if (shape == null || shape.isUnknown() || shape.size() != this.shape().size()) {
+ throw new IllegalArgumentException("Shape " + shape + " cannot be used to reshape ndarray of shape " + this.shape());
+ }
+ if (shape.equals(this.shape())) {
+ return (U)this;
+ }
+ return instantiateView(buffer(), DimensionalSpace.create(shape));
+ }
+
@Override
public U slice(long position, DimensionalSpace sliceDimensions) {
DataBuffer sliceBuffer = buffer().slice(position, sliceDimensions.physicalSize());
- return instantiate(sliceBuffer, sliceDimensions);
+ return instantiateView(sliceBuffer, sliceDimensions);
}
@Override
@@ -89,15 +101,15 @@ public U setObject(T value, long... coords) {
}
@Override
- public U read(DataBuffer dst) {
- Validator.readToBufferArgs(this, dst);
+ public U copyTo(DataBuffer dst) {
+ Validator.copyToBufferArgs(this, dst);
DataTransfer.execute(buffer(), dimensions(), dst, DataTransfer::ofValue);
return (U)this;
}
@Override
- public U write(DataBuffer src) {
- Validator.writeFromBufferArgs(this, src);
+ public U copyFrom(DataBuffer src) {
+ Validator.copyFromBufferArgs(this, src);
DataTransfer.execute(src, buffer(), dimensions(), DataTransfer::ofValue);
return (U)this;
}
@@ -132,13 +144,22 @@ public boolean equals(Object obj) {
return buffer().equals(other.buffer());
}
+ /**
+ * A String showing the type and shape of this dense ndarray.
+ * @return A string containing the type and shape.
+ */
+ @Override
+ public String toString() {
+ return this.getClass().getSimpleName() + "(shape=" + this.shape() + ")";
+ }
+
protected AbstractDenseNdArray(DimensionalSpace dimensions) {
super(dimensions);
}
abstract protected DataBuffer buffer();
- abstract U instantiate(DataBuffer buffer, DimensionalSpace dimensions);
+ abstract U instantiateView(DataBuffer buffer, DimensionalSpace dimensions);
long positionOf(long[] coords, boolean isValue) {
if (coords == null || coords.length == 0) {
diff --git a/ndarray/src/main/java/org/tensorflow/ndarray/impl/dense/BooleanDenseNdArray.java b/ndarray/src/main/java/org/tensorflow/ndarray/impl/dense/BooleanDenseNdArray.java
index 0764146..c3df6e8 100644
--- a/ndarray/src/main/java/org/tensorflow/ndarray/impl/dense/BooleanDenseNdArray.java
+++ b/ndarray/src/main/java/org/tensorflow/ndarray/impl/dense/BooleanDenseNdArray.java
@@ -55,15 +55,15 @@ public BooleanNdArray copyTo(NdArray dst) {
}
@Override
- public BooleanNdArray read(BooleanDataBuffer dst) {
- Validator.readToBufferArgs(this, dst);
+ public BooleanNdArray copyTo(BooleanDataBuffer dst) {
+ Validator.copyToBufferArgs(this, dst);
DataTransfer.execute(buffer, dimensions(), dst, DataTransfer::ofBoolean);
return this;
}
@Override
- public BooleanNdArray write(BooleanDataBuffer src) {
- Validator.writeFromBufferArgs(this, src);
+ public BooleanNdArray copyFrom(BooleanDataBuffer src) {
+ Validator.copyFromBufferArgs(this, src);
DataTransfer.execute(src, buffer, dimensions(), DataTransfer::ofBoolean);
return this;
}
@@ -73,7 +73,7 @@ protected BooleanDenseNdArray(BooleanDataBuffer buffer, Shape shape) {
}
@Override
- BooleanDenseNdArray instantiate(DataBuffer buffer, DimensionalSpace dimensions) {
+ BooleanDenseNdArray instantiateView(DataBuffer buffer, DimensionalSpace dimensions) {
return new BooleanDenseNdArray((BooleanDataBuffer)buffer, dimensions);
}
diff --git a/ndarray/src/main/java/org/tensorflow/ndarray/impl/dense/ByteDenseNdArray.java b/ndarray/src/main/java/org/tensorflow/ndarray/impl/dense/ByteDenseNdArray.java
index 172432b..1f01ce6 100644
--- a/ndarray/src/main/java/org/tensorflow/ndarray/impl/dense/ByteDenseNdArray.java
+++ b/ndarray/src/main/java/org/tensorflow/ndarray/impl/dense/ByteDenseNdArray.java
@@ -55,15 +55,15 @@ public ByteNdArray copyTo(NdArray dst) {
}
@Override
- public ByteNdArray read(ByteDataBuffer dst) {
- Validator.readToBufferArgs(this, dst);
+ public ByteNdArray copyTo(ByteDataBuffer dst) {
+ Validator.copyToBufferArgs(this, dst);
DataTransfer.execute(buffer, dimensions(), dst, DataTransfer::ofByte);
return this;
}
@Override
- public ByteNdArray write(ByteDataBuffer src) {
- Validator.writeFromBufferArgs(this, src);
+ public ByteNdArray copyFrom(ByteDataBuffer src) {
+ Validator.copyFromBufferArgs(this, src);
DataTransfer.execute(src, buffer, dimensions(), DataTransfer::ofByte);
return this;
}
@@ -73,7 +73,7 @@ protected ByteDenseNdArray(ByteDataBuffer buffer, Shape shape) {
}
@Override
- ByteDenseNdArray instantiate(DataBuffer buffer, DimensionalSpace dimensions) {
+ ByteDenseNdArray instantiateView(DataBuffer buffer, DimensionalSpace dimensions) {
return new ByteDenseNdArray((ByteDataBuffer)buffer, dimensions);
}
diff --git a/ndarray/src/main/java/org/tensorflow/ndarray/impl/dense/DenseNdArray.java b/ndarray/src/main/java/org/tensorflow/ndarray/impl/dense/DenseNdArray.java
index 819d95d..18b3755 100644
--- a/ndarray/src/main/java/org/tensorflow/ndarray/impl/dense/DenseNdArray.java
+++ b/ndarray/src/main/java/org/tensorflow/ndarray/impl/dense/DenseNdArray.java
@@ -45,7 +45,7 @@ protected DenseNdArray(DataBuffer buffer, Shape shape) {
}
@Override
- DenseNdArray instantiate(DataBuffer buffer, DimensionalSpace dimensions) {
+ DenseNdArray instantiateView(DataBuffer buffer, DimensionalSpace dimensions) {
return new DenseNdArray<>(buffer, dimensions);
}
diff --git a/ndarray/src/main/java/org/tensorflow/ndarray/impl/dense/DoubleDenseNdArray.java b/ndarray/src/main/java/org/tensorflow/ndarray/impl/dense/DoubleDenseNdArray.java
index f54b8d0..d983d16 100644
--- a/ndarray/src/main/java/org/tensorflow/ndarray/impl/dense/DoubleDenseNdArray.java
+++ b/ndarray/src/main/java/org/tensorflow/ndarray/impl/dense/DoubleDenseNdArray.java
@@ -55,15 +55,15 @@ public DoubleNdArray copyTo(NdArray dst) {
}
@Override
- public DoubleNdArray read(DoubleDataBuffer dst) {
- Validator.readToBufferArgs(this, dst);
+ public DoubleNdArray copyTo(DoubleDataBuffer dst) {
+ Validator.copyToBufferArgs(this, dst);
DataTransfer.execute(buffer, dimensions(), dst, DataTransfer::ofDouble);
return this;
}
@Override
- public DoubleNdArray write(DoubleDataBuffer src) {
- Validator.writeFromBufferArgs(this, src);
+ public DoubleNdArray copyFrom(DoubleDataBuffer src) {
+ Validator.copyFromBufferArgs(this, src);
DataTransfer.execute(src, buffer, dimensions(), DataTransfer::ofDouble);
return this;
}
@@ -73,7 +73,7 @@ protected DoubleDenseNdArray(DoubleDataBuffer buffer, Shape shape) {
}
@Override
- DoubleDenseNdArray instantiate(DataBuffer buffer, DimensionalSpace dimensions) {
+ DoubleDenseNdArray instantiateView(DataBuffer buffer, DimensionalSpace dimensions) {
return new DoubleDenseNdArray((DoubleDataBuffer)buffer, dimensions);
}
diff --git a/ndarray/src/main/java/org/tensorflow/ndarray/impl/dense/FloatDenseNdArray.java b/ndarray/src/main/java/org/tensorflow/ndarray/impl/dense/FloatDenseNdArray.java
index 196b5ef..779e047 100644
--- a/ndarray/src/main/java/org/tensorflow/ndarray/impl/dense/FloatDenseNdArray.java
+++ b/ndarray/src/main/java/org/tensorflow/ndarray/impl/dense/FloatDenseNdArray.java
@@ -55,15 +55,15 @@ public FloatNdArray copyTo(NdArray dst) {
}
@Override
- public FloatNdArray read(FloatDataBuffer dst) {
- Validator.readToBufferArgs(this, dst);
+ public FloatNdArray copyTo(FloatDataBuffer dst) {
+ Validator.copyToBufferArgs(this, dst);
DataTransfer.execute(buffer, dimensions(), dst, DataTransfer::ofFloat);
return this;
}
@Override
- public FloatNdArray write(FloatDataBuffer src) {
- Validator.writeFromBufferArgs(this, src);
+ public FloatNdArray copyFrom(FloatDataBuffer src) {
+ Validator.copyFromBufferArgs(this, src);
DataTransfer.execute(src, buffer, dimensions(), DataTransfer::ofFloat);
return this;
}
@@ -73,7 +73,7 @@ protected FloatDenseNdArray(FloatDataBuffer buffer, Shape shape) {
}
@Override
- FloatDenseNdArray instantiate(DataBuffer buffer, DimensionalSpace dimensions) {
+ FloatDenseNdArray instantiateView(DataBuffer buffer, DimensionalSpace dimensions) {
return new FloatDenseNdArray((FloatDataBuffer) buffer, dimensions);
}
diff --git a/ndarray/src/main/java/org/tensorflow/ndarray/impl/dense/IntDenseNdArray.java b/ndarray/src/main/java/org/tensorflow/ndarray/impl/dense/IntDenseNdArray.java
index a7af498..4e2183d 100644
--- a/ndarray/src/main/java/org/tensorflow/ndarray/impl/dense/IntDenseNdArray.java
+++ b/ndarray/src/main/java/org/tensorflow/ndarray/impl/dense/IntDenseNdArray.java
@@ -55,15 +55,15 @@ public IntNdArray copyTo(NdArray dst) {
}
@Override
- public IntNdArray read(IntDataBuffer dst) {
- Validator.readToBufferArgs(this, dst);
+ public IntNdArray copyTo(IntDataBuffer dst) {
+ Validator.copyToBufferArgs(this, dst);
DataTransfer.execute(buffer, dimensions(), dst, DataTransfer::ofInt);
return this;
}
@Override
- public IntNdArray write(IntDataBuffer src) {
- Validator.writeFromBufferArgs(this, src);
+ public IntNdArray copyFrom(IntDataBuffer src) {
+ Validator.copyFromBufferArgs(this, src);
DataTransfer.execute(src, buffer, dimensions(), DataTransfer::ofInt);
return this;
}
@@ -73,7 +73,7 @@ protected IntDenseNdArray(IntDataBuffer buffer, Shape shape) {
}
@Override
- IntDenseNdArray instantiate(DataBuffer buffer, DimensionalSpace dimensions) {
+ IntDenseNdArray instantiateView(DataBuffer buffer, DimensionalSpace dimensions) {
return new IntDenseNdArray((IntDataBuffer)buffer, dimensions);
}
diff --git a/ndarray/src/main/java/org/tensorflow/ndarray/impl/dense/LongDenseNdArray.java b/ndarray/src/main/java/org/tensorflow/ndarray/impl/dense/LongDenseNdArray.java
index cd56dad..cde91a3 100644
--- a/ndarray/src/main/java/org/tensorflow/ndarray/impl/dense/LongDenseNdArray.java
+++ b/ndarray/src/main/java/org/tensorflow/ndarray/impl/dense/LongDenseNdArray.java
@@ -55,15 +55,15 @@ public LongNdArray copyTo(NdArray dst) {
}
@Override
- public LongNdArray read(LongDataBuffer dst) {
- Validator.readToBufferArgs(this, dst);
+ public LongNdArray copyTo(LongDataBuffer dst) {
+ Validator.copyToBufferArgs(this, dst);
DataTransfer.execute(buffer, dimensions(), dst, DataTransfer::ofLong);
return this;
}
@Override
- public LongNdArray write(LongDataBuffer src) {
- Validator.writeFromBufferArgs(this, src);
+ public LongNdArray copyFrom(LongDataBuffer src) {
+ Validator.copyFromBufferArgs(this, src);
DataTransfer.execute(src, buffer, dimensions(), DataTransfer::ofLong);
return this;
}
@@ -73,7 +73,7 @@ protected LongDenseNdArray(LongDataBuffer buffer, Shape shape) {
}
@Override
- LongDenseNdArray instantiate(DataBuffer buffer, DimensionalSpace dimensions) {
+ LongDenseNdArray instantiateView(DataBuffer buffer, DimensionalSpace dimensions) {
return new LongDenseNdArray((LongDataBuffer)buffer, dimensions);
}
diff --git a/ndarray/src/main/java/org/tensorflow/ndarray/impl/dense/ShortDenseNdArray.java b/ndarray/src/main/java/org/tensorflow/ndarray/impl/dense/ShortDenseNdArray.java
index 291c01a..8d0dfc8 100644
--- a/ndarray/src/main/java/org/tensorflow/ndarray/impl/dense/ShortDenseNdArray.java
+++ b/ndarray/src/main/java/org/tensorflow/ndarray/impl/dense/ShortDenseNdArray.java
@@ -55,15 +55,15 @@ public ShortNdArray copyTo(NdArray dst) {
}
@Override
- public ShortNdArray read(ShortDataBuffer dst) {
- Validator.readToBufferArgs(this, dst);
+ public ShortNdArray copyTo(ShortDataBuffer dst) {
+ Validator.copyToBufferArgs(this, dst);
DataTransfer.execute(buffer, dimensions(), dst, DataTransfer::ofShort);
return this;
}
@Override
- public ShortNdArray write(ShortDataBuffer src) {
- Validator.writeFromBufferArgs(this, src);
+ public ShortNdArray copyFrom(ShortDataBuffer src) {
+ Validator.copyFromBufferArgs(this, src);
DataTransfer.execute(src, buffer, dimensions(), DataTransfer::ofShort);
return this;
}
@@ -73,7 +73,7 @@ protected ShortDenseNdArray(ShortDataBuffer buffer, Shape shape) {
}
@Override
- ShortDenseNdArray instantiate(DataBuffer buffer, DimensionalSpace dimensions) {
+ ShortDenseNdArray instantiateView(DataBuffer buffer, DimensionalSpace dimensions) {
return new ShortDenseNdArray((ShortDataBuffer)buffer, dimensions);
}
diff --git a/ndarray/src/main/java/org/tensorflow/ndarray/impl/dimension/DimensionalSpace.java b/ndarray/src/main/java/org/tensorflow/ndarray/impl/dimension/DimensionalSpace.java
index 7d0f022..71d1677 100644
--- a/ndarray/src/main/java/org/tensorflow/ndarray/impl/dimension/DimensionalSpace.java
+++ b/ndarray/src/main/java/org/tensorflow/ndarray/impl/dimension/DimensionalSpace.java
@@ -28,7 +28,7 @@ public static DimensionalSpace create(Shape shape) {
// Start from the last dimension, where all elements are continuous
for (int i = dimensions.length - 1, elementSize = 1; i >= 0; --i) {
- dimensions[i] = new Axis(shape.size(i), elementSize);
+ dimensions[i] = new Axis(shape.get(i), elementSize);
elementSize *= dimensions[i].numElements();
}
return new DimensionalSpace(dimensions, shape);
@@ -144,7 +144,7 @@ public DimensionalSpace from(int dimensionStart) {
throw new IndexOutOfBoundsException();
}
Dimension[] newDimensions = Arrays.copyOfRange(dimensions, dimensionStart, dimensions.length);
- if (segmentationIdx > dimensionStart) {
+ if (segmentationIdx >= dimensionStart) {
return new DimensionalSpace(newDimensions, segmentationIdx - dimensionStart);
}
return new DimensionalSpace(newDimensions);
@@ -189,7 +189,9 @@ public long positionOf(long[] coords) {
return position;
}
- /** Succinct description of the shape meant for debugging. */
+ /**
+ * Succinct description of the shape meant for debugging.
+ */
@Override
public String toString() {
return Arrays.toString(dimensions);
diff --git a/ndarray/src/main/java/org/tensorflow/ndarray/impl/sparse/AbstractSparseNdArray.java b/ndarray/src/main/java/org/tensorflow/ndarray/impl/sparse/AbstractSparseNdArray.java
new file mode 100644
index 0000000..e4a2fba
--- /dev/null
+++ b/ndarray/src/main/java/org/tensorflow/ndarray/impl/sparse/AbstractSparseNdArray.java
@@ -0,0 +1,550 @@
+/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+=======================================================================*/
+package org.tensorflow.ndarray.impl.sparse;
+
+import org.tensorflow.ndarray.IllegalRankException;
+import org.tensorflow.ndarray.LongNdArray;
+import org.tensorflow.ndarray.NdArray;
+import org.tensorflow.ndarray.NdArraySequence;
+import org.tensorflow.ndarray.NdArrays;
+import org.tensorflow.ndarray.Shape;
+import org.tensorflow.ndarray.SparseNdArray;
+import org.tensorflow.ndarray.impl.AbstractNdArray;
+import org.tensorflow.ndarray.impl.dense.AbstractDenseNdArray;
+import org.tensorflow.ndarray.impl.dimension.Dimension;
+import org.tensorflow.ndarray.impl.dimension.DimensionalSpace;
+import org.tensorflow.ndarray.impl.dimension.RelativeDimensionalSpace;
+import org.tensorflow.ndarray.impl.sequence.SingleElementSequence;
+import org.tensorflow.ndarray.impl.sequence.SlicingElementSequence;
+import org.tensorflow.ndarray.index.Index;
+
+import java.nio.ReadOnlyBufferException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.LongStream;
+
+/**
+ * Abstract base class for sparse array.
+ *
+ * A sparse array as two separate dense arrays: indices, values, and a shape that represents the
+ * dense shape.
+ *
+ *
NOTE: all Sparse Arrays are readonly for the {@link #set(NdArray, long...)} and
+ * {@link #setObject(Object, long...)} methods
+ *
+ *
{@code
+ * FloatSparseNdArray st = new FloatSparseNdArray(
+ * StdArrays.of(new long[][] {{0, 0}, {1, 2}}),
+ * NdArrays.vectorOf(1f, 2f),
+ * Shape.of(3, 4));
+ *
+ * }
+ *
+ * represents the dense array:
+ *
+ *
{@code
+ * [[1, 0, 0, 0]
+ * [0, 0, 2, 0]
+ * [0, 0, 0, 0]]
+ *
+ * }
+ *
+ * @param the type that the array contains
+ * @param the type of dense NdArray
+ */
+public abstract class AbstractSparseNdArray> extends AbstractNdArray
+ implements SparseNdArray {
+ /**
+ * A 2-D long array of shape {@code [N, ndims]}, that specifies the indices of the elements in the
+ * sparse array that contain non-default values (elements are zero-indexed).
+ *
+ * For example, {@code indices=[[1,3], [2,4]]} specifies that the elements with indexes of
+ * coordinates {@code [1,3]} and {@code [2,4]} have non-default values.
+ */
+ private LongNdArray indices;
+
+ /**
+ * A 1-D array of any type and shape {@code [N]}, that supplies the values for each element in
+ * indices.
+ *
+ *
For example, given {@code indices=[[1,3], [2,4]]}, and {@code values=[18, 3.6]} specifies
+ * that element {@code [1,3]} of the sparse array has a value of {@code 18}, and element {@code
+ * [2,4]} of the sparse array has a value of {@code 3.6}.
+ */
+ private U values;
+
+ /**
+ * Scalar value to set for indices not specified in {@link #getIndices()} This will default to
+ * zero, false, or the empty string depending on the data type of the values.
+ */
+ private T defaultValue;
+
+ /**
+ * Scalar NdArray to use for indices not specified in {@link #getIndices()} This will default to
+ * zero, false, or the empty string depending on the data type of the values, otherwise it will
+ * contain the defaultValue.
+ */
+ private U defaultArray;
+
+ /**
+ * Creates an abstract SparseNdArray
+ *
+ * @param indices A 2-D LongNdArray of shape {@code [N, ndims]}, that specifies the indices of the
+ * elements in the sparse array that contain non-default values (elements are zero-indexed).
+ * For example, {@code indices=[[1,3], [2,4]]} specifies that the elements with indexes of
+ * {@code [1,3]} and {@code [2,4]} have non-default values.
+ * @param values A 1-D NdArray of any type and shape {@code [N]}, which supplies the values for
+ * each element in indices. For example, given {@code indices=[[1,3], [2,4]]}, the parameter
+ * {@code values=[18, 3.6]} specifies that element {@code [1,3]} of the sparse NdArray has a
+ * value of {@code 18}, and element {@code [2,4]} of the NdArray has a value of {@code 3.6}.
+ * @param defaultValue Scalar value to set for indices not specified in {@link #indices}
+ * @param dimensions the dimensional space for the dense object represented by this sparse array.
+ */
+ protected AbstractSparseNdArray(
+ LongNdArray indices, U values, T defaultValue, DimensionalSpace dimensions) {
+ super(dimensions);
+ this.indices = indices;
+ this.values = values;
+ setDefaultValue(defaultValue);
+
+ // sanity checks on shapes, indices (shape = {@code [N, ndims]}, where N is the number of values
+ // (shape = {@code [N]}}.
+ if (this.indices.shape().get(0) != this.values.shape().get(0)) {
+ throw new IllegalArgumentException(
+ String.format(
+ "The number of rows in indices (%d) does not match the number of elements in values(%d).",
+ this.indices.shape().get(0), this.values.shape().get(0)));
+ }
+
+ // sanity checks on shapes, indices (shape = {@code [N, ndims]}, where ndims = the number of
+ // dimensions in the dense shape.
+ if (this.indices.shape().get(1) != shape().numDimensions()) {
+ throw new IllegalArgumentException(
+ String.format(
+ "The number of columns in indices (%d) does not match the number of dimensions in shape (%d).",
+ this.indices.shape().get(1), shape().get(0)));
+ }
+ }
+
+ /**
+ * Creates an abstract SparseNdArray
+ *
+ * @param defaultValue Scalar value to set for indices not specified in {@link #getIndices()}
+ * @param dimensions the dimensional space for the dense object represented by this sparse array,
+ */
+ protected AbstractSparseNdArray(T defaultValue, DimensionalSpace dimensions) {
+ super(dimensions);
+ setDefaultValue(defaultValue);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public NdArraySequence elements(int dimensionIdx) {
+ if (dimensionIdx >= shape().numDimensions()) {
+ throw new IllegalArgumentException(
+ "Cannot iterate elements in dimension '"
+ + dimensionIdx
+ + "' of array with shape "
+ + shape());
+ }
+ if (rank() == 0 && dimensionIdx < 0) {
+ return new SingleElementSequence<>(this);
+ }
+ DimensionalSpace elemDims = dimensions().from(dimensionIdx + 1);
+
+ return new SlicingElementSequence<>(this, dimensionIdx, elemDims);
+ }
+
+ /**
+ * Computes the coordinates based on a relative position to the beginning of the dimension space.
+ *
+ * @param dimensions the dimension space
+ * @param position relative position to the beginning of the dimension space.
+ * @return the coordinates
+ */
+ // TODO should have automatical access to the coordinates from which this position is coming from.
+ // But that will require some refactoring even at the dense level.
+ protected long[] toCoordinates(DimensionalSpace dimensions, long position) {
+ long[] result = new long[dimensions.numDimensions()];
+ long p = position;
+
+ for (int dim = 0; dim < dimensions.numDimensions(); dim++) {
+ Dimension dimension = dimensions.get(dim);
+ result[dim] = p / dimension.elementSize();
+ p = p % dimension.elementSize();
+ }
+ return result;
+ }
+
+ /**
+ * Converts the given set of indices coordinates to a long array of coordinates.
+ *
+ *
The shape of the NdArray is {@code [ndims]}
+ *
+ * @param l the LongNdArray containing the coordinates
+ * @return the long array containing the coordinates.
+ */
+ protected long[] getIndicesCoordinates(LongNdArray l) {
+ long[] results = new long[(int) l.size()];
+ for (int i = 0; i < l.size(); i++) {
+ results[i] = l.getLong(i);
+ }
+ return results;
+ }
+
+ /**
+ * Converts this sparse array to a dense array.
+ *
+ * @return the dense array.
+ */
+ public abstract U toDense();
+
+ @Override
+ public U withShape(Shape shape) {
+ throw new UnsupportedOperationException("Sparse NdArrays cannot be viewed with a different shape");
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public NdArray slice(Index... indices) {
+ if (indices == null) {
+ throw new IllegalArgumentException("Slicing requires at least one index");
+ }
+ RelativeDimensionalSpace sliceDimensions = dimensions().mapTo(indices);
+ return slice(sliceDimensions.position(), sliceDimensions);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public NdArray get(long... coordinates) {
+ return slice(positionOf(coordinates, false), dimensions().from(coordinates.length));
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public T getObject(long... coordinates) {
+ if (coordinates.length != shape().numDimensions()) {
+ throw new IllegalRankException(
+ String.format(
+ "Length of coordinates (%s)%s does not match the rank %d",
+ coordinates.length, Arrays.toString(coordinates), shape().numDimensions()));
+ }
+ long index = locateIndex(coordinates);
+ if (index >= 0) {
+ return getValues().getObject(index);
+ } else {
+ return defaultValue;
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public NdArray setObject(T value, long... coords) {
+ throw new ReadOnlyBufferException();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public NdArray set(NdArray src, long... coordinates) {
+ throw new ReadOnlyBufferException();
+ }
+
+ /**
+ * Creates a dense array of the type that this sparse array represents.
+ *
+ * @param shape the shape of the dense array.
+ * @return the dense of the type that this sparse array represents.
+ */
+ public abstract U createValues(Shape shape);
+
+ /** {@inheritDoc} */
+ @Override
+ public NdArray copyTo(NdArray dst) {
+ if (dst instanceof AbstractSparseNdArray) {
+ AbstractSparseNdArray sparse = (AbstractSparseNdArray) dst;
+ LongNdArray indicesCopy = NdArrays.ofLongs(indices.shape());
+ this.indices.copyTo(indicesCopy);
+ U valuesCopy = createValues(values.shape());
+ this.values.copyTo(valuesCopy);
+ sparse.setIndices(indicesCopy);
+ sparse.setValues(valuesCopy);
+ } else {
+ U dense = toDense();
+ dense.copyTo(dst);
+ }
+ return this;
+ }
+
+ /**
+ * Computes the position within the dense array given by the coordinates
+ *
+ * @param coords the coordinates within the dense array
+ * @param isValue indicator whether the coordinates represents a value or higher level dimension.
+ * @return the position within the array
+ */
+ protected long positionOf(long[] coords, boolean isValue) {
+ if (coords == null || coords.length == 0) {
+ return 0;
+ }
+ Validator.coordinates(dimensions, coords, isValue);
+ return dimensions.positionOf(coords);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected void slowCopyTo(NdArray array) {
+ if (array instanceof AbstractDenseNdArray) {
+ AbstractDenseNdArray dst = (AbstractDenseNdArray) array;
+ long offset = 0L;
+ for (NdArray s : scalars()) {
+ dst.setObject(s.getObject(), offset++);
+ }
+ } else if (array instanceof AbstractSparseNdArray) {
+ AbstractSparseNdArray dst = (AbstractSparseNdArray) array;
+ indices.copyTo(dst.getIndices());
+ values.copyTo(dst.values);
+ } else {
+ super.slowCopyTo(array);
+ }
+ }
+
+ /**
+ * Gets the Indices
+ *
+ * @return the Indices
+ */
+ public LongNdArray getIndices() {
+ return indices;
+ }
+
+ /**
+ * Sets the Indices
+ *
+ * @param indices the Indices
+ */
+ public void setIndices(LongNdArray indices) {
+ this.indices = indices;
+ }
+
+ /**
+ * Gets the values
+ *
+ * @return the values
+ */
+ public U getValues() {
+ return values;
+ }
+
+ /**
+ * Sets the values
+ *
+ * @param values the values
+ */
+ public void setValues(U values) {
+ this.values = values;
+ }
+
+ /**
+ * Gets the values index by coordinates
+ *
+ * @param coordinates the coordinates to locate
+ * @return index of the coordinates, if the coordinates are contained in the {@code indices}
+ * array; otherwise, {@code (-(insertion point) - 1)}. The insertion point is defined as the
+ * point at which the {@code coordinates} would be inserted into the {@code indices} array:
+ * the index of the first element greater than the key, or {@code indices.shape().get(0)}; if
+ * all elements in the array are less than the specified key. Note that this guarantees that
+ * the return value will be {@code >= 0}, only if the coordinates are found.
+ */
+ protected long locateIndex(long[] coordinates) {
+ long size = indices.shape().get(0);
+ LongNdArray coordArray = NdArrays.vectorOf(coordinates);
+ return binarySearch(size, coordArray);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public int hashCode() {
+ if (dimensions().isSegmented()) {
+ return slowHashCode();
+ }
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + indices.hashCode();
+ result = prime * result + values.hashCode();
+ result = prime * result + shape().hashCode();
+ return result;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof AbstractSparseNdArray)) {
+ return super.equals(obj);
+ }
+ AbstractSparseNdArray, ?> other = (AbstractSparseNdArray, ?>) obj;
+ if (!shape().equals(other.shape())) {
+ return false;
+ }
+ if (!indices.equals(other.indices)) {
+ return false;
+ }
+ return values.equals(other.values);
+ }
+
+ /**
+ * A String showing the type, default value, number of elements and
+ * the dense shape of this sparse ndarray.
+ * @return A string containing the type, default value, number of elements and shape.
+ */
+ @Override
+ public String toString() {
+ long numElements = values == null ? 0 : values.size();
+ String strDefault;
+ if (defaultValue == null) {
+ strDefault = "";
+ } else if (defaultValue instanceof Number) {
+ strDefault = defaultValue.toString();
+ } else {
+ strDefault = "'" + defaultValue + "'";
+ }
+ return this.getClass().getSimpleName() + "(defaultValue=" + strDefault
+ + ", numElements=" + numElements + ", shape=" + this.shape() + ")";
+ }
+
+ /**
+ * Performs a binary search on the indices array to locate the index of the specified coordinates.
+ * The indices array must be sorted by coordinates, row major.
+ *
+ * @param toIndex the index of the last element (exclusive) to be searched
+ * @param coordinates the coordinates to locate
+ * @return index of the coordinates, if the coordinates are contained in the {@code indices}
+ * array; otherwise, {@code (-(insertion point) - 1)}. The insertion point is defined as the
+ * point at which the {@code coordinates} would be inserted into the {@code indices} array:
+ * the index of the first element greater than the key, or {@code indices.shape().get(0)}; if
+ * all elements in the array are less than the specified key. Note that this guarantees that
+ * the return value will be @{code >= 0}, only if the coordinates are found.
+ */
+ private long binarySearch(long toIndex, LongNdArray coordinates) {
+
+ long low = 0;
+ long high = toIndex - 1;
+
+ while (low <= high) {
+ long mid = (low + high) >>> 1;
+ LongNdArray comparable = indices.get(mid);
+ int rc = compareCoordinates(comparable, coordinates);
+ if (rc < 0) { // less than
+ low = mid + 1;
+ } else if (rc > 0) { // higher than
+ high = mid - 1;
+ } else { // match
+ return mid;
+ }
+ }
+ return -(low + 1); // no match
+ }
+
+ /**
+ * Sorts the indices and values in ascending row-major coordinates.
+ *
+ * @return this instance
+ */
+ @SuppressWarnings("UnusedReturnValue")
+ public AbstractSparseNdArray sortIndicesAndValues() {
+
+ // indices will contain the indexes into the indices and values ndArrays, resorted.
+ List indexes = new ArrayList<>();
+ // create a range for the length of values
+ LongStream.range(0, values.size()).forEach(indexes::add);
+
+ // then sort this range based on ascending row-wise coordinates.
+ indexes.sort((a, b) -> compareCoordinates(indices.get(a), indices.get(b)));
+
+ LongNdArray newIndices = NdArrays.ofLongs(indices.shape());
+ U newValues = createValues(values.shape());
+ // used the sorted indexes to set up the sorted Indices and Values
+ for (long i = 0; i < indexes.size(); i++) {
+ long moveIndex = indexes.get((int) i);
+ newIndices.set(indices.get(moveIndex), i);
+ newValues.setObject(values.getObject(moveIndex), i);
+ }
+ indices = newIndices;
+ values = newValues;
+ return this;
+ }
+
+ /**
+ * Compares its two arguments for row major coordinate order.
+ *
+ * @return a negative integer, zero, or a positive integer as the first argument is less than,
+ * equal to, or greater than the second.
+ */
+ private int compareCoordinates(LongNdArray a, LongNdArray b) {
+ int rc = (int) (a.size() - b.size());
+ if (rc != 0) {
+ return rc;
+ }
+
+ for (long i = 0; i < a.size(); i++) {
+ long l = a.getLong(i);
+ rc = (int) (l - b.getLong(i));
+ if (rc != 0) {
+ return rc;
+ }
+ }
+ return 0;
+ }
+
+ /**
+ * Scalar value to set for indices not specified in {@link #indices}, defaults to zero, false, or
+ * the empty String depending on the data type.
+ */
+ public T getDefaultValue() {
+ return defaultValue;
+ }
+
+ /**
+ * Sets the defaultValue
+ *
+ * @param defaultValue the default value
+ */
+ public void setDefaultValue(T defaultValue) {
+ this.defaultValue = defaultValue;
+ defaultArray = null;
+ }
+
+ /**
+ * Creates the NdArray with the default value as a scalar
+ *
+ * @return the default NdArray of the default value as a scalar
+ */
+ public abstract U createDefaultArray();
+
+ /**
+ * Scalar NdArray to use for indices not specified in {@link #getIndices()} This will default to
+ * zero, false, or the empty string depending on the data type of the values, otherwise it will
+ * contain the {@link #defaultValue}.
+ */
+ public U getDefaultArray() {
+ if (defaultArray == null) {
+ defaultArray = createDefaultArray();
+ }
+ return defaultArray;
+ }
+}
diff --git a/ndarray/src/main/java/org/tensorflow/ndarray/impl/sparse/BooleanSparseNdArray.java b/ndarray/src/main/java/org/tensorflow/ndarray/impl/sparse/BooleanSparseNdArray.java
new file mode 100644
index 0000000..d5d8d72
--- /dev/null
+++ b/ndarray/src/main/java/org/tensorflow/ndarray/impl/sparse/BooleanSparseNdArray.java
@@ -0,0 +1,428 @@
+/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+=======================================================================*/
+package org.tensorflow.ndarray.impl.sparse;
+
+import org.tensorflow.ndarray.BooleanNdArray;
+import org.tensorflow.ndarray.LongNdArray;
+import org.tensorflow.ndarray.NdArray;
+import org.tensorflow.ndarray.NdArrays;
+import org.tensorflow.ndarray.Shape;
+import org.tensorflow.ndarray.StdArrays;
+import org.tensorflow.ndarray.buffer.BooleanDataBuffer;
+import org.tensorflow.ndarray.buffer.DataBuffer;
+import org.tensorflow.ndarray.buffer.DataBuffers;
+import org.tensorflow.ndarray.impl.dimension.DimensionalSpace;
+import org.tensorflow.ndarray.impl.sparse.slice.BooleanSparseSlice;
+import org.tensorflow.ndarray.index.Index;
+
+import java.nio.ReadOnlyBufferException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * sparse array for the boolean data type
+ *
+ * A sparse array as two separate dense arrays: indices, values, and a shape that represents the
+ * dense shape.
+ *
+ *
NOTE: all Sparse Arrays are readonly for the {@link #set(NdArray, long...)} and
+ * {@link #setObject(Boolean, long...)} methods
+ *
+ *
{@code
+ * FloatSparseNdArray st = new BooleanSparseNdArray(
+ * StdArrays.of(new long[][] {{0, 0}, {1, 2}}),
+ * NdArrays.vectorOf(true, true),
+ * Shape.of(3, 4));
+ *
+ * }
+ *
+ * represents the dense array:
+ *
+ *
{@code
+ * [[true, false, false, false]
+ * [false, false, true, false]
+ * [false, false, false, false]]
+ *
+ * }
+ */
+public class BooleanSparseNdArray extends AbstractSparseNdArray
+ implements BooleanNdArray {
+
+ /**
+ * Creates a BooleanSparseNdArray
+ *
+ * @param indices A 2-D LongNdArray of shape {@code [N, ndims]}, that specifies the indices of the
+ * elements in the sparse array that contain non-default values (elements are zero-indexed).
+ * For example, {@code indices=[[1,3], [2,4]]} specifies that the elements with indexes of
+ * {@code [1,3]} and {@code [2,4]} have non-default values.
+ * @param values A 1-D NdArray of Boolean type and shape {@code [N]}, which supplies the values
+ * for each element in indices. For example, given {@code indices=[[1,3], [2,4]]}, the
+ * parameter {@code values=[18, 3.6]} specifies that element {@code [1,3]} of the sparse
+ * NdArray has a value of {@code 18}, and element {@code [2,4]} of the NdArray has a value of
+ * {@code 3.6}.
+ * @param defaultValue Scalar value to set for indices not specified in {@link #getIndices()}
+ * @param dimensions the dimensional space for the dense object represented by this sparse array,
+ */
+ protected BooleanSparseNdArray(
+ LongNdArray indices,
+ BooleanNdArray values,
+ boolean defaultValue,
+ DimensionalSpace dimensions) {
+ super(indices, values, defaultValue, dimensions);
+ }
+
+ /**
+ * Creates a BooleanSparseNdArray with a default value of false.
+ *
+ * @param indices A 2-D LongNdArray of shape {@code [N, ndims]}, that specifies the indices of the
+ * elements in the sparse array that contain non-default values (elements are zero-indexed).
+ * For example, {@code indices=[[1,3], [2,4]]} specifies that the elements with indexes of
+ * {@code [1,3]} and {@code [2,4]} have non-default values.
+ * @param values A 1-D NdArray of Boolean type and shape {@code [N]}, which supplies the values
+ * for each element in indices. For example, given {@code indices=[[1,3], [2,4]]}, the
+ * parameter {@code values=[18, 3.6]} specifies that element {@code [1,3]} of the sparse
+ * NdArray has a value of {@code 18}, and element {@code [2,4]} of the NdArray has a value of
+ * {@code 3.6}.
+ * @param dimensions the dimensional space for the dense object represented by this sparse array,
+ */
+ BooleanSparseNdArray(LongNdArray indices, BooleanNdArray values, DimensionalSpace dimensions) {
+ this(indices, values, false, dimensions);
+ }
+
+ /**
+ * Creates a BooleanSparseNdArray
+ *
+ * @param dataBuffer a dense dataBuffer used to create the spars array
+ * @param dimensions the dimensional space for the dense object represented by this sparse array,
+ */
+ BooleanSparseNdArray(BooleanDataBuffer dataBuffer, DimensionalSpace dimensions) {
+ this(dataBuffer, false, dimensions);
+ }
+
+ /**
+ * Creates a BooleanSparseNdArray
+ *
+ * @param dataBuffer a dense dataBuffer used to create the spars array
+ * @param defaultValue Scalar value to set for indices not specified in {@link #getIndices()}
+ * @param dimensions the dimensional space for the dense object represented by this sparse array,
+ */
+ BooleanSparseNdArray(
+ BooleanDataBuffer dataBuffer, boolean defaultValue, DimensionalSpace dimensions) {
+ super(defaultValue, dimensions);
+ // use write to set up the indices and values
+ copyFrom(dataBuffer);
+ }
+
+ /**
+ * Creates a zero-filled BooleanSparseNdArray
+ *
+ * @param dimensions the dimensional space for the dense object represented by this sparse array,
+ */
+ BooleanSparseNdArray(DimensionalSpace dimensions) {
+ this(false, dimensions);
+ }
+
+ /**
+ * Creates a zero-filled BooleanSparseNdArray
+ *
+ * @param defaultValue Scalar value to set for indices not specified in {@link #getIndices()}
+ * @param dimensions the dimensional space for the dense object represented by this sparse array,
+ */
+ BooleanSparseNdArray(boolean defaultValue, DimensionalSpace dimensions) {
+ super(defaultValue, dimensions);
+ }
+
+ /**
+ * Creates a new BooleanSparseNdArray
+ *
+ * @param indices A 2-D LongNdArray of shape {@code [N, ndims]}, that specifies the indices of the
+ * elements in the sparse array that contain non-default values (elements are zero-indexed).
+ * For example, {@code indices=[[1,3], [2,4]]} specifies that the elements with indexes of
+ * {@code [1,3]} and {@code [2,4]} have non-default values.
+ * @param values A 1-D NdArray of any type and shape {@code [N]}, which supplies the values for
+ * each element in indices. For example, given {@code indices=[[1,3], [2,4]]}, the parameter
+ * {@code values=[18, 3.6]} specifies that element {@code [1,3]} of the sparse NdArray has a
+ * value of {@code 18}, and element {@code [2,4]} of the NdArray has a value of {@code 3.6}.
+ * @param dimensions the dimensional space for the dense object represented by this sparse array.
+ * @return the new Sparse Array
+ */
+ public static BooleanSparseNdArray create(
+ LongNdArray indices, BooleanNdArray values, DimensionalSpace dimensions) {
+ return new BooleanSparseNdArray(indices, values, dimensions);
+ }
+
+ /**
+ * Creates a new BooleanSparseNdArray
+ *
+ * @param indices A 2-D LongNdArray of shape {@code [N, ndims]}, that specifies the indices of the
+ * elements in the sparse array that contain non-default values (elements are zero-indexed).
+ * For example, {@code indices=[[1,3], [2,4]]} specifies that the elements with indexes of
+ * {@code [1,3]} and {@code [2,4]} have non-default values.
+ * @param values A 1-D NdArray of any type and shape {@code [N]}, which supplies the values for
+ * each element in indices. For example, given {@code indices=[[1,3], [2,4]]}, the parameter
+ * {@code values=[18, 3.6]} specifies that element {@code [1,3]} of the sparse NdArray has a
+ * value of {@code 18}, and element {@code [2,4]} of the NdArray has a value of {@code 3.6}.
+ * @param defaultValue Scalar value to set for indices not specified in {@link #getIndices()}
+ * @param dimensions the dimensional space for the dense object represented by this sparse array.
+ * @return the new Sparse Array
+ */
+ public static BooleanSparseNdArray create(
+ LongNdArray indices,
+ BooleanNdArray values,
+ boolean defaultValue,
+ DimensionalSpace dimensions) {
+ return new BooleanSparseNdArray(indices, values, defaultValue, dimensions);
+ }
+
+ /**
+ * Creates a new BooleanSparseNdArray from a data buffer
+ *
+ * @param dataBuffer the databuffer containing the dense array
+ * @param dimensions the dimensional space for the sparse array
+ * @return the new Sparse Array
+ */
+ public static BooleanSparseNdArray create(
+ BooleanDataBuffer dataBuffer, DimensionalSpace dimensions) {
+ return new BooleanSparseNdArray(dataBuffer, dimensions);
+ }
+
+ /**
+ * Creates a new BooleanSparseNdArray from a data buffer
+ *
+ * @param dataBuffer the databuffer containing the dense array
+ * @param defaultValue Scalar value to set for indices not specified in {@link #getIndices()}
+ * @param dimensions the dimensional space for the sparse array
+ * @return the new Sparse Array
+ */
+ public static BooleanSparseNdArray create(
+ BooleanDataBuffer dataBuffer, boolean defaultValue, DimensionalSpace dimensions) {
+ return new BooleanSparseNdArray(dataBuffer, defaultValue, dimensions);
+ }
+
+ /**
+ * Creates a new empty BooleanSparseNdArray from a data buffer
+ *
+ * @param dimensions the dimensions array
+ * @return the new Sparse Array
+ */
+ public static BooleanSparseNdArray create(DimensionalSpace dimensions) {
+ return new BooleanSparseNdArray(dimensions);
+ }
+
+ /**
+ * Creates a new empty BooleanSparseNdArray from a data buffer
+ *
+ * @param dimensions the dimensions array
+ * @param defaultValue Scalar value to set for indices not specified in {@link #getIndices()}
+ * @return the new Sparse Array
+ */
+ public static BooleanSparseNdArray create(boolean defaultValue, DimensionalSpace dimensions) {
+ return new BooleanSparseNdArray(defaultValue, dimensions);
+ }
+
+ /**
+ * Creates a new empty BooleanSparseNdArray from a float data buffer
+ *
+ * @param buffer the data buffer
+ * @param shape the shape of the sparse array.
+ * @return the new Sparse Array
+ */
+ public static BooleanSparseNdArray create(BooleanDataBuffer buffer, Shape shape) {
+ return new BooleanSparseNdArray(buffer, DimensionalSpace.create(shape));
+ }
+
+ /**
+ * Creates a new empty BooleanSparseNdArray from a float data buffer
+ *
+ * @param buffer the data buffer
+ * @param defaultValue Scalar value to set for indices not specified in {@link #getIndices()}
+ * @param shape the shape of the sparse array.
+ * @return the new Sparse Array
+ */
+ public static BooleanSparseNdArray create(
+ BooleanDataBuffer buffer, boolean defaultValue, Shape shape) {
+ return new BooleanSparseNdArray(buffer, defaultValue, DimensionalSpace.create(shape));
+ }
+
+ /**
+ * Creates a new BooleanSparseNdArray from a BooleanNdArray
+ *
+ * @param src the BooleanNdArray
+ * @return the new Sparse Array
+ */
+ public static BooleanSparseNdArray create(BooleanNdArray src) {
+ BooleanDataBuffer buffer = DataBuffers.ofBooleans(src.size());
+ src.copyTo(buffer);
+ return new BooleanSparseNdArray(buffer, DimensionalSpace.create(src.shape()));
+ }
+ /**
+ * Creates a new BooleanSparseNdArray from a BooleanNdArray
+ *
+ * @param defaultValue Scalar value to set for indices not specified in {@link #getIndices()}
+ * @param src the BooleanNdArray
+ * @return the new Sparse Array
+ */
+ public static BooleanSparseNdArray create(BooleanNdArray src, boolean defaultValue) {
+ BooleanDataBuffer buffer = DataBuffers.ofBooleans(src.size());
+ src.copyTo(buffer);
+ return new BooleanSparseNdArray(buffer, defaultValue, DimensionalSpace.create(src.shape()));
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public BooleanNdArray createDefaultArray() {
+ return NdArrays.scalarOf(getDefaultValue());
+ }
+
+ /**
+ * Creates a BooleanNdArray of the specified shape
+ *
+ * @param shape the shape of the dense array.
+ * @return a BooleanNdArray of the specified shape
+ */
+ public BooleanNdArray createValues(Shape shape) {
+ return NdArrays.ofBooleans(shape);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public BooleanNdArray slice(long position, DimensionalSpace sliceDimensions) {
+ return new BooleanSparseSlice(this, position, sliceDimensions);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean getBoolean(long... coordinates) {
+ return getObject(coordinates);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public BooleanNdArray setBoolean(boolean value, long... coordinates) {
+ throw new ReadOnlyBufferException();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public BooleanNdArray copyTo(DataBuffer dst) {
+ return copyTo((BooleanDataBuffer) dst);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public BooleanNdArray copyTo(BooleanDataBuffer dst) {
+ // set the values in buf to the default, then overwrite with indices/values
+ Boolean[] defaults = new Boolean[(int) shape().size()];
+ Arrays.fill(defaults, getDefaultValue());
+ dst.write(defaults);
+
+ AtomicInteger i = new AtomicInteger();
+ getIndices()
+ .elements(0)
+ .forEachIndexed(
+ (idx, l) -> {
+ long[] coordinates = getIndicesCoordinates(l);
+ boolean value = getValues().getBoolean(i.getAndIncrement());
+ dst.setObject(value, dimensions.positionOf(coordinates));
+ });
+ return this;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public BooleanNdArray copyFrom(BooleanDataBuffer src) {
+ List indices = new ArrayList<>();
+ List values = new ArrayList<>();
+
+ for (long i = 0; i < src.size(); i++) {
+ if (!src.getObject(i).equals(getDefaultValue())) {
+ indices.add(toCoordinates(dimensions, i));
+ values.add(src.getObject(i));
+ }
+ }
+ long[][] indicesArray = new long[indices.size()][];
+ boolean[] valuesArray = new boolean[values.size()];
+ for (int i = 0; i < indices.size(); i++) {
+ indicesArray[i] = indices.get(i);
+ valuesArray[i] = values.get(i);
+ }
+
+ setIndices(StdArrays.ndCopyOf(indicesArray));
+ setValues(NdArrays.vectorOf(valuesArray));
+ return this;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public BooleanNdArray copyFrom(DataBuffer src) {
+ return copyFrom((BooleanDataBuffer) src);
+ }
+
+ /**
+ * Converts the sparse array to a dense array
+ *
+ * @return the dense array
+ */
+ public BooleanNdArray toDense() {
+ BooleanDataBuffer dataBuffer = DataBuffers.ofBooleans(shape().size());
+ copyTo(dataBuffer);
+ return NdArrays.wrap(shape(), dataBuffer);
+ }
+
+ /**
+ * Populates this sparse array from a dense array
+ *
+ * @param src the dense array
+ * @return this sparse array
+ */
+ public BooleanNdArray fromDense(BooleanNdArray src) {
+ BooleanDataBuffer buffer = DataBuffers.ofBooleans(src.size());
+ src.copyTo(buffer);
+ copyFrom(buffer);
+ return this;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public BooleanNdArray slice(Index... indices) {
+ return (BooleanNdArray) super.slice(indices);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public BooleanNdArray get(long... coordinates) {
+ return (BooleanNdArray) super.get(coordinates);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public BooleanNdArray setObject(Boolean value, long... coordinates) {
+ throw new ReadOnlyBufferException();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public BooleanNdArray set(NdArray src, long... coordinates) {
+ throw new ReadOnlyBufferException();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public BooleanNdArray copyTo(NdArray dst) {
+ return (BooleanNdArray) super.copyTo(dst);
+ }
+}
diff --git a/ndarray/src/main/java/org/tensorflow/ndarray/impl/sparse/ByteSparseNdArray.java b/ndarray/src/main/java/org/tensorflow/ndarray/impl/sparse/ByteSparseNdArray.java
new file mode 100644
index 0000000..633ca49
--- /dev/null
+++ b/ndarray/src/main/java/org/tensorflow/ndarray/impl/sparse/ByteSparseNdArray.java
@@ -0,0 +1,418 @@
+/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+=======================================================================*/
+package org.tensorflow.ndarray.impl.sparse;
+
+import org.tensorflow.ndarray.ByteNdArray;
+import org.tensorflow.ndarray.LongNdArray;
+import org.tensorflow.ndarray.NdArray;
+import org.tensorflow.ndarray.NdArrays;
+import org.tensorflow.ndarray.Shape;
+import org.tensorflow.ndarray.StdArrays;
+import org.tensorflow.ndarray.buffer.ByteDataBuffer;
+import org.tensorflow.ndarray.buffer.DataBuffer;
+import org.tensorflow.ndarray.buffer.DataBuffers;
+import org.tensorflow.ndarray.impl.dimension.DimensionalSpace;
+import org.tensorflow.ndarray.impl.sparse.slice.ByteSparseSlice;
+import org.tensorflow.ndarray.index.Index;
+
+import java.nio.ReadOnlyBufferException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * sparse array for the byte data type
+ *
+ * A sparse array as two separate dense arrays: indices, values, and a shape that represents the
+ * dense shape.
+ *
+ *
NOTE: all Sparse Arrays are readonly for the {@link #set(NdArray, long...)} and
+ * {@link #setObject(Byte, long...)} methods
+ *
+ *
{@code
+ * ByteSparseNdArray st = new ByteSparseNdArray(
+ * StdArrays.of(new long[][] {{0, 0}, {1, 2}}),
+ * NdArrays.vectorOf((byte)1, (byte)255),
+ * Shape.of(3, 4));
+ *
+ * }
+ *
+ * represents the dense array:
+ *
+ *
{@code
+ * [[(byte)1, (byte)0, (byte)0, (byte)0]
+ * [(byte)0, (byte)0, (byte)1, (byte)0]
+ * [(byte)0, (byte)0, (byte)0, (byte)0]]
+ *
+ * }
+ */
+public class ByteSparseNdArray extends AbstractSparseNdArray
+ implements ByteNdArray {
+
+ /**
+ * Creates a ByteSparseNdArray with a default value of zero.
+ *
+ * @param indices A 2-D LongNdArray of shape {@code [N, ndims]}, that specifies the indices of the
+ * elements in the sparse array that contain non-default values (elements are zero-indexed).
+ * For example, {@code indices=[[1,3], [2,4]]} specifies that the elements with indexes of
+ * {@code [1,3]} and {@code [2,4]} have non-default values.
+ * @param values A 1-D NdArray of Byte type and shape {@code [N]}, which supplies the values for
+ * each element in indices. For example, given {@code indices=[[1,3], [2,4]]}, the parameter
+ * {@code values=[18, 3.6]} specifies that element {@code [1,3]} of the sparse NdArray has a
+ * value of {@code 18}, and element {@code [2,4]} of the NdArray has a value of {@code 3.6}.
+ * @param defaultValue Scalar value to set for indices not specified in {@link #getIndices()}
+ * @param dimensions the dimensional space for the dense object represented by this sparse array,
+ */
+ protected ByteSparseNdArray(
+ LongNdArray indices, ByteNdArray values, byte defaultValue, DimensionalSpace dimensions) {
+ super(indices, values, defaultValue, dimensions);
+ }
+
+ /**
+ * Creates a ByteSparseNdArray
+ *
+ * @param indices A 2-D LongNdArray of shape {@code [N, ndims]}, that specifies the indices of the
+ * elements in the sparse array that contain non-default values (elements are zero-indexed).
+ * For example, {@code indices=[[1,3], [2,4]]} specifies that the elements with indexes of
+ * {@code [1,3]} and {@code [2,4]} have non-default values.
+ * @param values A 1-D NdArray of Byte type and shape {@code [N]}, which supplies the values for
+ * each element in indices. For example, given {@code indices=[[1,3], [2,4]]}, the parameter
+ * {@code values=[18, 3.6]} specifies that element {@code [1,3]} of the sparse NdArray has a
+ * value of {@code 18}, and element {@code [2,4]} of the NdArray has a value of {@code 3.6}.
+ * @param dimensions the dimensional space for the dense object represented by this sparse array,
+ */
+ ByteSparseNdArray(LongNdArray indices, ByteNdArray values, DimensionalSpace dimensions) {
+ this(indices, values, (byte) 0, dimensions);
+ }
+
+ /**
+ * Creates a ByteSparseNdArray
+ *
+ * @param dataBuffer a dense dataBuffer used to create the spars array
+ * @param dimensions the dimensional space for the dense object represented by this sparse array,
+ */
+ ByteSparseNdArray(ByteDataBuffer dataBuffer, DimensionalSpace dimensions) {
+ this(dataBuffer, (byte) 0, dimensions);
+ }
+
+ /**
+ * Creates a ByteSparseNdArray
+ *
+ * @param dataBuffer a dense dataBuffer used to create the spars array
+ * @param defaultValue Scalar value to set for indices not specified in {@link #getIndices()}
+ * @param dimensions the dimensional space for the dense object represented by this sparse array,
+ */
+ ByteSparseNdArray(ByteDataBuffer dataBuffer, byte defaultValue, DimensionalSpace dimensions) {
+ super(defaultValue, dimensions);
+ // use write to set up the indices and values
+ copyFrom(dataBuffer);
+ }
+
+ /**
+ * Creates a zero-filled ByteSparseNdArray
+ *
+ * @param dimensions the dimensional space for the dense object represented by this sparse array,
+ */
+ ByteSparseNdArray(DimensionalSpace dimensions) {
+ this((byte) 0, dimensions);
+ }
+
+ /**
+ * Creates a zero-filled ByteSparseNdArray
+ *
+ * @param defaultValue Scalar value to set for indices not specified in {@link #getIndices()}
+ * @param dimensions the dimensional space for the dense object represented by this sparse array,
+ */
+ ByteSparseNdArray(byte defaultValue, DimensionalSpace dimensions) {
+ super(defaultValue, dimensions);
+ }
+
+ /**
+ * Creates a new ByteSparseNdArray
+ *
+ * @param indices A 2-D LongNdArray of shape {@code [N, ndims]}, that specifies the indices of the
+ * elements in the sparse array that contain non-default values (elements are zero-indexed).
+ * For example, {@code indices=[[1,3], [2,4]]} specifies that the elements with indexes of
+ * {@code [1,3]} and {@code [2,4]} have non-default values.
+ * @param values A 1-D NdArray of any type and shape {@code [N]}, which supplies the values for
+ * each element in indices. For example, given {@code indices=[[1,3], [2,4]]}, the parameter
+ * {@code values=[18, 3.6]} specifies that element {@code [1,3]} of the sparse NdArray has a
+ * value of {@code 18}, and element {@code [2,4]} of the NdArray has a value of {@code 3.6}.
+ * @param dimensions the dimensional space for the dense object represented by this sparse array.
+ * @return the new Sparse Array
+ */
+ public static ByteSparseNdArray create(
+ LongNdArray indices, ByteNdArray values, DimensionalSpace dimensions) {
+ return new ByteSparseNdArray(indices, values, dimensions);
+ }
+
+ /**
+ * Creates a new ByteSparseNdArray
+ *
+ * @param indices A 2-D LongNdArray of shape {@code [N, ndims]}, that specifies the indices of the
+ * elements in the sparse array that contain non-default values (elements are zero-indexed).
+ * For example, {@code indices=[[1,3], [2,4]]} specifies that the elements with indexes of
+ * {@code [1,3]} and {@code [2,4]} have non-default values.
+ * @param values A 1-D NdArray of any type and shape {@code [N]}, which supplies the values for
+ * each element in indices. For example, given {@code indices=[[1,3], [2,4]]}, the parameter
+ * {@code values=[18, 3.6]} specifies that element {@code [1,3]} of the sparse NdArray has a
+ * value of {@code 18}, and element {@code [2,4]} of the NdArray has a value of {@code 3.6}.
+ * @param defaultValue Scalar value to set for indices not specified in {@link #getIndices()}
+ * @param dimensions the dimensional space for the dense object represented by this sparse array.
+ * @return the new Sparse Array
+ */
+ public static ByteSparseNdArray create(
+ LongNdArray indices, ByteNdArray values, byte defaultValue, DimensionalSpace dimensions) {
+ return new ByteSparseNdArray(indices, values, defaultValue, dimensions);
+ }
+
+ /**
+ * Creates a new ByteSparseNdArray from a data buffer
+ *
+ * @param dataBuffer the databuffer containing the dense array
+ * @param dimensions the dimensional space for the sparse array
+ * @return the new Sparse Array
+ */
+ public static ByteSparseNdArray create(ByteDataBuffer dataBuffer, DimensionalSpace dimensions) {
+ return new ByteSparseNdArray(dataBuffer, dimensions);
+ }
+
+ /**
+ * Creates a new ByteSparseNdArray from a data buffer
+ *
+ * @param dataBuffer the databuffer containing the dense array
+ * @param defaultValue Scalar value to set for indices not specified in {@link #getIndices()}
+ * @param dimensions the dimensional space for the sparse array
+ * @return the new Sparse Array
+ */
+ public static ByteSparseNdArray create(
+ ByteDataBuffer dataBuffer, byte defaultValue, DimensionalSpace dimensions) {
+ return new ByteSparseNdArray(dataBuffer, defaultValue, dimensions);
+ }
+
+ /**
+ * Creates a new empty ByteSparseNdArray from a data buffer
+ *
+ * @param dimensions the dimensions array
+ * @return the new Sparse Array
+ */
+ public static ByteSparseNdArray create(DimensionalSpace dimensions) {
+ return new ByteSparseNdArray(dimensions);
+ }
+
+ /**
+ * Creates a new empty ByteSparseNdArray from a data buffer
+ *
+ * @param defaultValue Scalar value to set for indices not specified in {@link #getIndices()}
+ * @param dimensions the dimensions array
+ * @return the new Sparse Array
+ */
+ public static ByteSparseNdArray create(byte defaultValue, DimensionalSpace dimensions) {
+ return new ByteSparseNdArray(defaultValue, dimensions);
+ }
+
+ /**
+ * Creates a new empty ByteSparseNdArray from a float data buffer
+ *
+ * @param buffer the data buffer
+ * @param shape the shape of the sparse array.
+ * @return the new Sparse Array
+ */
+ public static ByteSparseNdArray create(ByteDataBuffer buffer, Shape shape) {
+ return new ByteSparseNdArray(buffer, DimensionalSpace.create(shape));
+ }
+
+ /**
+ * Creates a new empty ByteSparseNdArray from a float data buffer
+ *
+ * @param buffer the data buffer
+ * @param defaultValue Scalar value to set for indices not specified in {@link #getIndices()}
+ * @param shape the shape of the sparse array.
+ * @return the new Sparse Array
+ */
+ public static ByteSparseNdArray create(ByteDataBuffer buffer, byte defaultValue, Shape shape) {
+ return new ByteSparseNdArray(buffer, defaultValue, DimensionalSpace.create(shape));
+ }
+
+ /**
+ * Creates a new ByteSparseNdArray from a ByteNdArray
+ *
+ * @param src the ByteNdArray
+ * @return the new Sparse Array
+ */
+ public static ByteSparseNdArray create(ByteNdArray src) {
+ ByteDataBuffer buffer = DataBuffers.ofBytes(src.size());
+ src.copyTo(buffer);
+ return new ByteSparseNdArray(buffer, DimensionalSpace.create(src.shape()));
+ }
+
+ /**
+ * Creates a new ByteSparseNdArray from a ByteNdArray
+ *
+ * @param src the ByteNdArray
+ * @param defaultValue Scalar value to set for indices not specified in {@link #getIndices()}
+ * @return the new Sparse Array
+ */
+ public static ByteSparseNdArray create(ByteNdArray src, byte defaultValue) {
+ ByteDataBuffer buffer = DataBuffers.ofBytes(src.size());
+ src.copyTo(buffer);
+ return new ByteSparseNdArray(buffer, defaultValue, DimensionalSpace.create(src.shape()));
+ }
+
+ /**
+ * Creates a ByteNdArray of the specified shape
+ *
+ * @param shape the shape of the dense array.
+ * @return a ByteNdArray of the specified shape
+ */
+ public ByteNdArray createValues(Shape shape) {
+ return NdArrays.ofBytes(shape);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public ByteNdArray slice(long position, DimensionalSpace sliceDimensions) {
+ return new ByteSparseSlice(this, position, sliceDimensions);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public byte getByte(long... coordinates) {
+ return getObject(coordinates);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public ByteNdArray setByte(byte value, long... coordinates) {
+ throw new ReadOnlyBufferException();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public ByteNdArray copyTo(DataBuffer dst) {
+ return copyTo((ByteDataBuffer) dst);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public ByteNdArray copyTo(ByteDataBuffer dst) {
+ // set the values in buf to the default, then overwrite with indices/values
+ Byte[] defaults = new Byte[(int) shape().size()];
+ Arrays.fill(defaults, getDefaultValue());
+ dst.write(defaults);
+
+ AtomicInteger i = new AtomicInteger();
+ getIndices()
+ .elements(0)
+ .forEachIndexed(
+ (idx, l) -> {
+ long[] coordinates = getIndicesCoordinates(l);
+ byte value = getValues().getByte(i.getAndIncrement());
+ dst.setObject(value, dimensions.positionOf(coordinates));
+ });
+ return this;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public ByteNdArray copyFrom(ByteDataBuffer src) {
+ List indices = new ArrayList<>();
+ List values = new ArrayList<>();
+
+ for (long i = 0; i < src.size(); i++) {
+ if (!src.getObject(i).equals(getDefaultValue())) {
+ indices.add(toCoordinates(dimensions, i));
+ values.add(src.getObject(i));
+ }
+ }
+ long[][] indicesArray = new long[indices.size()][];
+ byte[] valuesArray = new byte[values.size()];
+ for (int i = 0; i < indices.size(); i++) {
+ indicesArray[i] = indices.get(i);
+ valuesArray[i] = values.get(i);
+ }
+
+ setIndices(StdArrays.ndCopyOf(indicesArray));
+ setValues(NdArrays.vectorOf(valuesArray));
+ return this;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public ByteNdArray copyFrom(DataBuffer src) {
+ return copyFrom((ByteDataBuffer) src);
+ }
+
+ /**
+ * Converts the sparse array to a dense array
+ *
+ * @return the dense array
+ */
+ public ByteNdArray toDense() {
+ ByteDataBuffer dataBuffer = DataBuffers.ofBytes(shape().size());
+ copyTo(dataBuffer);
+ return NdArrays.wrap(shape(), dataBuffer);
+ }
+
+ /**
+ * Populates this sparse array from a dense array
+ *
+ * @param src the dense array
+ * @return this sparse array
+ */
+ public ByteNdArray fromDense(ByteNdArray src) {
+ ByteDataBuffer buffer = DataBuffers.ofBytes(src.size());
+ src.copyTo(buffer);
+ copyFrom(buffer);
+ return this;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public ByteNdArray slice(Index... indices) {
+ return (ByteNdArray) super.slice(indices);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public ByteNdArray get(long... coordinates) {
+ return (ByteNdArray) super.get(coordinates);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public ByteNdArray setObject(Byte value, long... coordinates) {
+ throw new ReadOnlyBufferException();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public ByteNdArray set(NdArray src, long... coordinates) {
+ throw new ReadOnlyBufferException();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public ByteNdArray copyTo(NdArray dst) {
+ return (ByteNdArray) super.copyTo(dst);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public ByteNdArray createDefaultArray() {
+ return NdArrays.scalarOf(getDefaultValue());
+ }
+}
diff --git a/ndarray/src/main/java/org/tensorflow/ndarray/impl/sparse/DoubleSparseNdArray.java b/ndarray/src/main/java/org/tensorflow/ndarray/impl/sparse/DoubleSparseNdArray.java
new file mode 100644
index 0000000..35b3541
--- /dev/null
+++ b/ndarray/src/main/java/org/tensorflow/ndarray/impl/sparse/DoubleSparseNdArray.java
@@ -0,0 +1,419 @@
+/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+=======================================================================*/
+package org.tensorflow.ndarray.impl.sparse;
+
+import org.tensorflow.ndarray.DoubleNdArray;
+import org.tensorflow.ndarray.LongNdArray;
+import org.tensorflow.ndarray.NdArray;
+import org.tensorflow.ndarray.NdArrays;
+import org.tensorflow.ndarray.Shape;
+import org.tensorflow.ndarray.StdArrays;
+import org.tensorflow.ndarray.buffer.DataBuffer;
+import org.tensorflow.ndarray.buffer.DataBuffers;
+import org.tensorflow.ndarray.buffer.DoubleDataBuffer;
+import org.tensorflow.ndarray.impl.dimension.DimensionalSpace;
+import org.tensorflow.ndarray.impl.sparse.slice.DoubleSparseSlice;
+import org.tensorflow.ndarray.index.Index;
+
+import java.nio.ReadOnlyBufferException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * A sparse array for the double data type
+ *
+ * A sparse array as two separate dense arrays: indices, values, and a shape that represents the
+ * dense shape.
+ *
+ *
NOTE: all Sparse Arrays are readonly for the {@link #set(NdArray, long...)} and
+ * {@link #setObject(Double, long...)} methods
+ *
+ *
{@code
+ * DoubleSparseNdArray st = new DoubleSparseNdArray(
+ * StdArrays.of(new long[][] {{0, 0}, {1, 2}}),
+ * NdArrays.vectorsOf(new double[] {1, 2}),
+ * Shape.of(3, 4));
+ *
+ * }
+ *
+ * represents the dense array:
+ *
+ *
{@code
+ * [[1, 0, 0, 0]
+ * [0, 0, 2, 0]
+ * [0, 0, 0, 0]]
+ *
+ * }
+ */
+public class DoubleSparseNdArray extends AbstractSparseNdArray
+ implements DoubleNdArray {
+
+ /**
+ * Creates a DoubleSparseNdArray
+ *
+ * @param indices A 2-D LongNdArray of shape {@code [N, ndims]}, that specifies the indices of the
+ * elements in the sparse array that contain non-default values (elements are zero-indexed).
+ * For example, {@code indices=[[1,3], [2,4]]} specifies that the elements with indexes of
+ * {@code [1,3]} and {@code [2,4]} have non-default values.
+ * @param values A 1-D DoubleNdArray of shape {@code [N]}, which supplies the values for each
+ * element in indices. For example, given {@code indices=[[1,3], [2,4]]}, the parameter {@code
+ * values=[18, 3.6]} specifies that element {@code [1,3]} of the sparse NdArray has a value of
+ * {@code 18}, and element {@code [2,4]} of the NdArray has a value of {@code 3.6}.
+ * @param defaultValue Scalar value to set for indices not specified in {@link #getIndices()}
+ * @param dimensions the dimensional space for the dense object represented by this sparse array,
+ */
+ protected DoubleSparseNdArray(
+ LongNdArray indices, DoubleNdArray values, double defaultValue, DimensionalSpace dimensions) {
+ super(indices, values, defaultValue, dimensions);
+ }
+
+ /**
+ * Creates a DoubleSparseNdArray with a default value of zero.
+ *
+ * @param indices A 2-D LongNdArray of shape {@code [N, ndims]}, that specifies the indices of the
+ * elements in the sparse array that contain non-default values (elements are zero-indexed).
+ * For example, {@code indices=[[1,3], [2,4]]} specifies that the elements with indexes of
+ * {@code [1,3]} and {@code [2,4]} have non-default values.
+ * @param values A 1-D DoubleNdArray of shape {@code [N]}, which supplies the values for each
+ * element in indices. For example, given {@code indices=[[1,3], [2,4]]}, the parameter {@code
+ * values=[18, 3.6]} specifies that element {@code [1,3]} of the sparse NdArray has a value of
+ * {@code 18}, and element {@code [2,4]} of the NdArray has a value of {@code 3.6}.
+ * @param dimensions the dimensional space for the dense object represented by this sparse array,
+ */
+ DoubleSparseNdArray(LongNdArray indices, DoubleNdArray values, DimensionalSpace dimensions) {
+ this(indices, values, 0d, dimensions);
+ }
+
+ /**
+ * Creates a DoubleSparseNdArray
+ *
+ * @param dataBuffer a dense dataBuffer used to create the spars array
+ * @param dimensions the dimensional space for the dense object represented by this sparse array,
+ */
+ DoubleSparseNdArray(DoubleDataBuffer dataBuffer, DimensionalSpace dimensions) {
+ this(dataBuffer, 0d, dimensions);
+ }
+ /**
+ * Creates a DoubleSparseNdArray
+ *
+ * @param dataBuffer a dense dataBuffer used to create the spars array
+ * @param defaultValue Scalar value to set for indices not specified in {@link #getIndices()}
+ * @param dimensions the dimensional space for the dense object represented by this sparse array,
+ */
+ DoubleSparseNdArray(
+ DoubleDataBuffer dataBuffer, double defaultValue, DimensionalSpace dimensions) {
+ super(defaultValue, dimensions);
+ // use write to set up the indices and values
+ copyFrom(dataBuffer);
+ }
+
+ /**
+ * Creates a zero-filled DoubleSparseNdArray
+ *
+ * @param dimensions the dimensional space for the dense object represented by this sparse array,
+ */
+ DoubleSparseNdArray(DimensionalSpace dimensions) {
+ this(0d, dimensions);
+ }
+
+ /**
+ * Creates a zero-filled DoubleSparseNdArray
+ *
+ * @param defaultValue Scalar value to set for indices not specified in {@link #getIndices()}
+ * @param dimensions the dimensional space for the dense object represented by this sparse array,
+ */
+ DoubleSparseNdArray(double defaultValue, DimensionalSpace dimensions) {
+ super(defaultValue, dimensions);
+ }
+
+ /**
+ * Creates a new DoubleSparseNdArray
+ *
+ * @param indices A 2-D LongNdArray of shape {@code [N, ndims]}, that specifies the indices of the
+ * elements in the sparse array that contain non-default values (elements are zero-indexed).
+ * For example, {@code indices=[[1,3], [2,4]]} specifies that the elements with indexes of
+ * {@code [1,3]} and {@code [2,4]} have non-default values.
+ * @param values A 1-D NdArray of any type and shape {@code [N]}, which supplies the values for
+ * each element in indices. For example, given {@code indices=[[1,3], [2,4]]}, the parameter
+ * {@code values=[18, 3.6]} specifies that element {@code [1,3]} of the sparse NdArray has a
+ * value of {@code 18}, and element {@code [2,4]} of the NdArray has a value of {@code 3.6}.
+ * @param dimensions the dimensional space for the dense object represented by this sparse array.
+ * @return the new Sparse Array
+ */
+ public static DoubleSparseNdArray create(
+ LongNdArray indices, DoubleNdArray values, DimensionalSpace dimensions) {
+ return new DoubleSparseNdArray(indices, values, dimensions);
+ }
+
+ /**
+ * Creates a new DoubleSparseNdArray
+ *
+ * @param indices A 2-D LongNdArray of shape {@code [N, ndims]}, that specifies the indices of the
+ * elements in the sparse array that contain non-default values (elements are zero-indexed).
+ * For example, {@code indices=[[1,3], [2,4]]} specifies that the elements with indexes of
+ * {@code [1,3]} and {@code [2,4]} have non-default values.
+ * @param values A 1-D NdArray of any type and shape {@code [N]}, which supplies the values for
+ * each element in indices. For example, given {@code indices=[[1,3], [2,4]]}, the parameter
+ * {@code values=[18, 3.6]} specifies that element {@code [1,3]} of the sparse NdArray has a
+ * value of {@code 18}, and element {@code [2,4]} of the NdArray has a value of {@code 3.6}.
+ * @param defaultValue Scalar value to set for indices not specified in {@link #getIndices()}
+ * @param dimensions the dimensional space for the dense object represented by this sparse array.
+ * @return the new Sparse Array
+ */
+ public static DoubleSparseNdArray create(
+ LongNdArray indices, DoubleNdArray values, double defaultValue, DimensionalSpace dimensions) {
+ return new DoubleSparseNdArray(indices, values, defaultValue, dimensions);
+ }
+
+ /**
+ * Creates a new DoubleSparseNdArray from a data buffer
+ *
+ * @param dataBuffer the databuffer containing the dense array
+ * @param dimensions the dimensional space for the sparse array
+ * @return the new Sparse Array
+ */
+ public static DoubleSparseNdArray create(
+ DoubleDataBuffer dataBuffer, DimensionalSpace dimensions) {
+ return new DoubleSparseNdArray(dataBuffer, dimensions);
+ }
+
+ /**
+ * Creates a new DoubleSparseNdArray from a data buffer
+ *
+ * @param dataBuffer the databuffer containing the dense array
+ * @param defaultValue Scalar value to set for indices not specified in {@link #getIndices()}
+ * @param dimensions the dimensional space for the sparse array
+ * @return the new Sparse Array
+ */
+ public static DoubleSparseNdArray create(
+ DoubleDataBuffer dataBuffer, double defaultValue, DimensionalSpace dimensions) {
+ return new DoubleSparseNdArray(dataBuffer, defaultValue, dimensions);
+ }
+
+ /**
+ * Creates a new empty DoubleSparseNdArray from a data buffer
+ *
+ * @param dimensions the dimensions array
+ * @return the new Sparse Array
+ */
+ public static DoubleSparseNdArray create(DimensionalSpace dimensions) {
+ return new DoubleSparseNdArray(dimensions);
+ }
+
+ /**
+ * Creates a new empty DoubleSparseNdArray from a data buffer
+ *
+ * @param defaultValue Scalar value to set for indices not specified in {@link #getIndices()}
+ * @param dimensions the dimensions array
+ * @return the new Sparse Array
+ */
+ public static DoubleSparseNdArray create(double defaultValue, DimensionalSpace dimensions) {
+ return new DoubleSparseNdArray(defaultValue, dimensions);
+ }
+
+ /**
+ * Creates a new empty DoubleSparseNdArray from a double data buffer
+ *
+ * @param buffer the data buffer
+ * @param shape the shape of the sparse array.
+ * @return the new Sparse Array
+ */
+ public static DoubleSparseNdArray create(DoubleDataBuffer buffer, Shape shape) {
+ return new DoubleSparseNdArray(buffer, DimensionalSpace.create(shape));
+ }
+
+ /**
+ * Creates a new empty DoubleSparseNdArray from a double data buffer
+ *
+ * @param buffer the data buffer
+ * @param defaultValue Scalar value to set for indices not specified in {@link #getIndices()}
+ * @param shape the shape of the sparse array.
+ * @return the new Sparse Array
+ */
+ public static DoubleSparseNdArray create(
+ DoubleDataBuffer buffer, double defaultValue, Shape shape) {
+ return new DoubleSparseNdArray(buffer, defaultValue, DimensionalSpace.create(shape));
+ }
+
+ /**
+ * Creates a new DoubleSparseNdArray from a DoubleNdArray
+ *
+ * @param src the DoubleNdArray
+ * @return the new Sparse Array
+ */
+ public static DoubleSparseNdArray create(DoubleNdArray src) {
+ DoubleDataBuffer buffer = DataBuffers.ofDoubles(src.size());
+ src.copyTo(buffer);
+ return new DoubleSparseNdArray(buffer, DimensionalSpace.create(src.shape()));
+ }
+ /**
+ * Creates a new DoubleSparseNdArray from a DoubleNdArray
+ *
+ * @param src the DoubleNdArray
+ * @param defaultValue Scalar value to set for indices not specified in {@link #getIndices()}
+ * @return the new Sparse Array
+ */
+ public static DoubleSparseNdArray create(DoubleNdArray src, double defaultValue) {
+ DoubleDataBuffer buffer = DataBuffers.ofDoubles(src.size());
+ src.copyTo(buffer);
+ return new DoubleSparseNdArray(buffer, defaultValue, DimensionalSpace.create(src.shape()));
+ }
+
+ /**
+ * Creates a DoubleNdArray of the specified shape
+ *
+ * @param shape the shape of the dense array.
+ * @return a DoubleNdArray of the specified shape
+ */
+ public DoubleNdArray createValues(Shape shape) {
+ return NdArrays.ofDoubles(shape);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public DoubleNdArray slice(long position, DimensionalSpace sliceDimensions) {
+ return new DoubleSparseSlice(this, position, sliceDimensions);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public double getDouble(long... coordinates) {
+ return getObject(coordinates);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public DoubleNdArray setDouble(double value, long... coordinates) {
+ throw new ReadOnlyBufferException();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public DoubleNdArray copyTo(DataBuffer dst) {
+ return copyTo((DoubleDataBuffer) dst);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public DoubleNdArray copyTo(DoubleDataBuffer dst) {
+ // set buf to the default values, then overwrite with the indices/values.
+ Double[] defaults = new Double[(int) shape().size()];
+ Arrays.fill(defaults, getDefaultValue());
+ dst.write(defaults);
+
+ AtomicInteger i = new AtomicInteger();
+ getIndices()
+ .elements(0)
+ .forEachIndexed(
+ (idx, l) -> {
+ long[] coordinates = getIndicesCoordinates(l);
+ double value = getValues().getDouble(i.getAndIncrement());
+ dst.setObject(value, dimensions.positionOf(coordinates));
+ });
+ return this;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public DoubleNdArray copyFrom(DoubleDataBuffer src) {
+ List indices = new ArrayList<>();
+ List values = new ArrayList<>();
+
+ for (long i = 0; i < src.size(); i++) {
+ if (!src.getObject(i).equals(getDefaultValue())) {
+ indices.add(toCoordinates(dimensions, i));
+ values.add(src.getObject(i));
+ }
+ }
+ long[][] indicesArray = new long[indices.size()][];
+ double[] valuesArray = new double[values.size()];
+ for (int i = 0; i < indices.size(); i++) {
+ indicesArray[i] = indices.get(i);
+ valuesArray[i] = values.get(i);
+ }
+
+ setIndices(StdArrays.ndCopyOf(indicesArray));
+ setValues(NdArrays.vectorOf(valuesArray));
+ return this;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public DoubleNdArray copyFrom(DataBuffer src) {
+ return copyFrom((DoubleDataBuffer) src);
+ }
+
+ /**
+ * Converts the sparse array to a dense array
+ *
+ * @return the dense array
+ */
+ public DoubleNdArray toDense() {
+ DoubleDataBuffer dataBuffer = DataBuffers.ofDoubles(shape().size());
+ copyTo(dataBuffer);
+ return NdArrays.wrap(shape(), dataBuffer);
+ }
+
+ /**
+ * Populates this sparse array from a dense array
+ *
+ * @param src the dense array
+ * @return this sparse array
+ */
+ public DoubleNdArray fromDense(DoubleNdArray src) {
+ DoubleDataBuffer buffer = DataBuffers.ofDoubles(src.size());
+ src.copyTo(buffer);
+ copyFrom(buffer);
+ return this;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public DoubleNdArray slice(Index... indices) {
+ return (DoubleNdArray) super.slice(indices);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public DoubleNdArray get(long... coordinates) {
+ return (DoubleNdArray) super.get(coordinates);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public DoubleNdArray setObject(Double value, long... coordinates) {
+ throw new ReadOnlyBufferException();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public DoubleNdArray set(NdArray src, long... coordinates) {
+ throw new ReadOnlyBufferException();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public DoubleNdArray copyTo(NdArray dst) {
+ return (DoubleNdArray) super.copyTo(dst);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public DoubleNdArray createDefaultArray() {
+ return NdArrays.scalarOf(getDefaultValue());
+ }
+}
diff --git a/ndarray/src/main/java/org/tensorflow/ndarray/impl/sparse/FloatSparseNdArray.java b/ndarray/src/main/java/org/tensorflow/ndarray/impl/sparse/FloatSparseNdArray.java
new file mode 100644
index 0000000..88f34b1
--- /dev/null
+++ b/ndarray/src/main/java/org/tensorflow/ndarray/impl/sparse/FloatSparseNdArray.java
@@ -0,0 +1,417 @@
+/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+=======================================================================*/
+package org.tensorflow.ndarray.impl.sparse;
+
+import org.tensorflow.ndarray.FloatNdArray;
+import org.tensorflow.ndarray.LongNdArray;
+import org.tensorflow.ndarray.NdArray;
+import org.tensorflow.ndarray.NdArrays;
+import org.tensorflow.ndarray.Shape;
+import org.tensorflow.ndarray.StdArrays;
+import org.tensorflow.ndarray.buffer.DataBuffer;
+import org.tensorflow.ndarray.buffer.DataBuffers;
+import org.tensorflow.ndarray.buffer.FloatDataBuffer;
+import org.tensorflow.ndarray.impl.dimension.DimensionalSpace;
+import org.tensorflow.ndarray.impl.sparse.slice.FloatSparseSlice;
+import org.tensorflow.ndarray.index.Index;
+
+import java.nio.ReadOnlyBufferException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * sparse array for the float data type
+ *
+ * A sparse array as two separate dense arrays: indices, values, and a shape that represents the
+ * dense shape.
+ *
+ *
NOTE: all Sparse Arrays are readonly for the {@link #set(NdArray, long...)} and
+ * {@link #setObject(Float, long...)} methods
+ *
+ *
{@code
+ * FloatSparseNdArray st = new FloatSparseNdArray(
+ * StdArrays.of(new long[][] {{0, 0}, {1, 2}}),
+ * NdArrays.vectorOf(1f, 3.14f}),
+ * Shape.of(3, 4));
+ *
+ * }
+ *
+ * represents the dense array:
+ *
+ *
{@code
+ * [[1, 0, 0, 0]
+ * [0, 0, 3.14, 0]
+ * [0, 0, 0, 0]]
+ *
+ * }
+ */
+public class FloatSparseNdArray extends AbstractSparseNdArray
+ implements FloatNdArray {
+
+ /**
+ * Creates a FloatSparseNdArray
+ *
+ * @param indices A 2-D LongNdArray of shape {@code [N, ndims]}, that specifies the indices of the
+ * elements in the sparse array that contain non-default values (elements are zero-indexed).
+ * For example, {@code indices=[[1,3], [2,4]]} specifies that the elements with indexes of
+ * {@code [1,3]} and {@code [2,4]} have non-default values.
+ * @param values A 1-D FloatNdArray of shape {@code [N]}, which supplies the values for each
+ * element in indices. For example, given {@code indices=[[1,3], [2,4]]}, the parameter {@code
+ * values=[18, 3.6]} specifies that element {@code [1,3]} of the sparse NdArray has a value of
+ * {@code 18}, and element {@code [2,4]} of the NdArray has a value of {@code 3.6}.
+ * @param defaultValue Scalar value to set for indices not specified in {@link #getIndices()}
+ * @param dimensions the dimensional space for the dense object represented by this sparse array,
+ */
+ protected FloatSparseNdArray(
+ LongNdArray indices, FloatNdArray values, float defaultValue, DimensionalSpace dimensions) {
+ super(indices, values, defaultValue, dimensions);
+ }
+
+ /**
+ * Creates a FloatSparseNdArray with a default value of zero.
+ *
+ * @param indices A 2-D LongNdArray of shape {@code [N, ndims]}, that specifies the indices of the
+ * elements in the sparse array that contain non-default values (elements are zero-indexed).
+ * For example, {@code indices=[[1,3], [2,4]]} specifies that the elements with indexes of
+ * {@code [1,3]} and {@code [2,4]} have non-default values.
+ * @param values A 1-D FloatNdArray of shape {@code [N]}, which supplies the values for each
+ * element in indices. For example, given {@code indices=[[1,3], [2,4]]}, the parameter {@code
+ * values=[18, 3.6]} specifies that element {@code [1,3]} of the sparse NdArray has a value of
+ * {@code 18}, and element {@code [2,4]} of the NdArray has a value of {@code 3.6}.
+ * @param dimensions the dimensional space for the dense object represented by this sparse array,
+ */
+ FloatSparseNdArray(LongNdArray indices, FloatNdArray values, DimensionalSpace dimensions) {
+ this(indices, values, 0f, dimensions);
+ }
+
+ /**
+ * Creates a FloatSparseNdArray
+ *
+ * @param dataBuffer a dense dataBuffer used to create the spars array
+ * @param dimensions the dimensional space for the dense object represented by this sparse array,
+ */
+ FloatSparseNdArray(FloatDataBuffer dataBuffer, DimensionalSpace dimensions) {
+ this(dataBuffer, 0f, dimensions);
+ }
+
+ /**
+ * Creates a FloatSparseNdArray
+ *
+ * @param dataBuffer a dense dataBuffer used to create the spars array
+ * @param defaultValue Scalar value to set for indices not specified in {@link #getIndices()}
+ * @param dimensions the dimensional space for the dense object represented by this sparse array,
+ */
+ FloatSparseNdArray(FloatDataBuffer dataBuffer, float defaultValue, DimensionalSpace dimensions) {
+ super(defaultValue, dimensions);
+ // use write to set up the indices and values
+ copyFrom(dataBuffer);
+ }
+
+ /**
+ * Creates a zero-filled FloatSparseNdArray
+ *
+ * @param dimensions the dimensional space for the dense object represented by this sparse array,
+ */
+ FloatSparseNdArray(DimensionalSpace dimensions) {
+ this(0f, dimensions);
+ }
+
+ /**
+ * Creates a zero-filled FloatSparseNdArray
+ *
+ * @param defaultValue Scalar value to set for indices not specified in {@link #getIndices()}
+ * @param dimensions the dimensional space for the dense object represented by this sparse array,
+ */
+ FloatSparseNdArray(float defaultValue, DimensionalSpace dimensions) {
+ super(defaultValue, dimensions);
+ }
+
+ /**
+ * Creates a new FloatSparseNdArray
+ *
+ * @param indices A 2-D LongNdArray of shape {@code [N, ndims]}, that specifies the indices of the
+ * elements in the sparse array that contain non-default values (elements are zero-indexed).
+ * For example, {@code indices=[[1,3], [2,4]]} specifies that the elements with indexes of
+ * {@code [1,3]} and {@code [2,4]} have non-default values.
+ * @param values A 1-D NdArray of any type and shape {@code [N]}, which supplies the values for
+ * each element in indices. For example, given {@code indices=[[1,3], [2,4]]}, the parameter
+ * {@code values=[18, 3.6]} specifies that element {@code [1,3]} of the sparse NdArray has a
+ * value of {@code 18}, and element {@code [2,4]} of the NdArray has a value of {@code 3.6}.
+ * @param dimensions the dimensional space for the dense object represented by this sparse array.
+ * @return the new Sparse Array
+ */
+ public static FloatSparseNdArray create(
+ LongNdArray indices, FloatNdArray values, DimensionalSpace dimensions) {
+ return new FloatSparseNdArray(indices, values, dimensions);
+ }
+
+ /**
+ * Creates a new FloatSparseNdArray
+ *
+ * @param indices A 2-D LongNdArray of shape {@code [N, ndims]}, that specifies the indices of the
+ * elements in the sparse array that contain non-default values (elements are zero-indexed).
+ * For example, {@code indices=[[1,3], [2,4]]} specifies that the elements with indexes of
+ * {@code [1,3]} and {@code [2,4]} have non-default values.
+ * @param values A 1-D NdArray of any type and shape {@code [N]}, which supplies the values for
+ * each element in indices. For example, given {@code indices=[[1,3], [2,4]]}, the parameter
+ * {@code values=[18, 3.6]} specifies that element {@code [1,3]} of the sparse NdArray has a
+ * value of {@code 18}, and element {@code [2,4]} of the NdArray has a value of {@code 3.6}.
+ * @param defaultValue Scalar value to set for indices not specified in {@link #getIndices()}
+ * @param dimensions the dimensional space for the dense object represented by this sparse array.
+ * @return the new Sparse Array
+ */
+ public static FloatSparseNdArray create(
+ LongNdArray indices, FloatNdArray values, float defaultValue, DimensionalSpace dimensions) {
+ return new FloatSparseNdArray(indices, values, defaultValue, dimensions);
+ }
+
+ /**
+ * Creates a new FloatSparseNdArray from a data buffer
+ *
+ * @param dataBuffer the databuffer containing the dense array
+ * @param dimensions the dimensional space for the sparse array
+ * @return the new Sparse Array
+ */
+ public static FloatSparseNdArray create(FloatDataBuffer dataBuffer, DimensionalSpace dimensions) {
+ return new FloatSparseNdArray(dataBuffer, dimensions);
+ }
+
+ /**
+ * Creates a new FloatSparseNdArray from a data buffer
+ *
+ * @param dataBuffer the databuffer containing the dense array
+ * @param defaultValue Scalar value to set for indices not specified in {@link #getIndices()}
+ * @param dimensions the dimensional space for the sparse array
+ * @return the new Sparse Array
+ */
+ public static FloatSparseNdArray create(
+ FloatDataBuffer dataBuffer, float defaultValue, DimensionalSpace dimensions) {
+ return new FloatSparseNdArray(dataBuffer, defaultValue, dimensions);
+ }
+
+ /**
+ * Creates a new empty FloatSparseNdArray from a data buffer
+ *
+ * @param dimensions the dimensions array
+ * @return the new Sparse Array
+ */
+ public static FloatSparseNdArray create(DimensionalSpace dimensions) {
+ return new FloatSparseNdArray(dimensions);
+ }
+
+ /**
+ * Creates a new empty FloatSparseNdArray from a data buffer
+ *
+ * @param defaultValue Scalar value to set for indices not specified in {@link #getIndices()}
+ * @param dimensions the dimensions array
+ * @return the new Sparse Array
+ */
+ public static FloatSparseNdArray create(float defaultValue, DimensionalSpace dimensions) {
+ return new FloatSparseNdArray(defaultValue, dimensions);
+ }
+
+ /**
+ * Creates a new empty FloatSparseNdArray from a float data buffer
+ *
+ * @param buffer the data buffer
+ * @param shape the shape of the sparse array.
+ * @return the new Sparse Array
+ */
+ public static FloatSparseNdArray create(FloatDataBuffer buffer, Shape shape) {
+ return new FloatSparseNdArray(buffer, DimensionalSpace.create(shape));
+ }
+
+ /**
+ * Creates a new empty FloatSparseNdArray from a float data buffer
+ *
+ * @param buffer the data buffer
+ * @param defaultValue Scalar value to set for indices not specified in {@link #getIndices()}
+ * @param shape the shape of the sparse array.
+ * @return the new Sparse Array
+ */
+ public static FloatSparseNdArray create(FloatDataBuffer buffer, float defaultValue, Shape shape) {
+ return new FloatSparseNdArray(buffer, defaultValue, DimensionalSpace.create(shape));
+ }
+
+ /**
+ * Creates a new FloatSparseNdArray from a FloatNdArray
+ *
+ * @param src the FloatNdArray
+ * @return the new Sparse Array
+ */
+ public static FloatSparseNdArray create(FloatNdArray src) {
+ FloatDataBuffer buffer = DataBuffers.ofFloats(src.size());
+ src.copyTo(buffer);
+ return new FloatSparseNdArray(buffer, DimensionalSpace.create(src.shape()));
+ }
+ /**
+ * Creates a new FloatSparseNdArray from a FloatNdArray
+ *
+ * @param src the FloatNdArray
+ * @param defaultValue Scalar value to set for indices not specified in {@link #getIndices()}
+ * @return the new Sparse Array
+ */
+ public static FloatSparseNdArray create(FloatNdArray src, float defaultValue) {
+ FloatDataBuffer buffer = DataBuffers.ofFloats(src.size());
+ src.copyTo(buffer);
+ return new FloatSparseNdArray(buffer, defaultValue, DimensionalSpace.create(src.shape()));
+ }
+
+ /**
+ * Creates a FloatNdArray of the specified shape
+ *
+ * @param shape the shape of the dense array.
+ * @return a FloatNdArray of the specified shape
+ */
+ public FloatNdArray createValues(Shape shape) {
+ return NdArrays.ofFloats(shape);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public FloatNdArray slice(long position, DimensionalSpace sliceDimensions) {
+ return new FloatSparseSlice(this, position, sliceDimensions);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public float getFloat(long... coordinates) {
+ return getObject(coordinates);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public FloatNdArray setFloat(float value, long... coordinates) {
+ throw new ReadOnlyBufferException();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public FloatNdArray copyTo(DataBuffer dst) {
+ return copyTo((FloatDataBuffer) dst);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public FloatNdArray copyTo(FloatDataBuffer dst) {
+ // set the values in buf to the default, then overwrite with indices/values
+ Float[] defaults = new Float[(int) shape().size()];
+ Arrays.fill(defaults, getDefaultValue());
+ dst.write(defaults);
+
+ AtomicInteger i = new AtomicInteger();
+ getIndices()
+ .elements(0)
+ .forEachIndexed(
+ (idx, l) -> {
+ long[] coordinates = getIndicesCoordinates(l);
+ float value = getValues().getFloat(i.getAndIncrement());
+ dst.setObject(value, dimensions.positionOf(coordinates));
+ });
+ return this;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public FloatNdArray copyFrom(FloatDataBuffer src) {
+ List indices = new ArrayList<>();
+ List values = new ArrayList<>();
+
+ for (long i = 0; i < src.size(); i++) {
+ if (!src.getObject(i).equals(getDefaultValue())) {
+ indices.add(toCoordinates(dimensions, i));
+ values.add(src.getObject(i));
+ }
+ }
+ long[][] indicesArray = new long[indices.size()][];
+ float[] valuesArray = new float[values.size()];
+ for (int i = 0; i < indices.size(); i++) {
+ indicesArray[i] = indices.get(i);
+ valuesArray[i] = values.get(i);
+ }
+
+ setIndices(StdArrays.ndCopyOf(indicesArray));
+ setValues(NdArrays.vectorOf(valuesArray));
+ return this;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public FloatNdArray copyFrom(DataBuffer src) {
+ return copyFrom((FloatDataBuffer) src);
+ }
+
+ /**
+ * Converts the sparse array to a dense array
+ *
+ * @return the dense array
+ */
+ public FloatNdArray toDense() {
+ FloatDataBuffer dataBuffer = DataBuffers.ofFloats(shape().size());
+ copyTo(dataBuffer);
+ return NdArrays.wrap(shape(), dataBuffer);
+ }
+
+ /**
+ * Populates this sparse array from a dense array
+ *
+ * @param src the dense array
+ * @return this sparse array
+ */
+ public FloatNdArray fromDense(FloatNdArray src) {
+ FloatDataBuffer buffer = DataBuffers.ofFloats(src.size());
+ src.copyTo(buffer);
+ copyFrom(buffer);
+ return this;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public FloatNdArray slice(Index... indices) {
+ return (FloatNdArray) super.slice(indices);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public FloatNdArray get(long... coordinates) {
+ return (FloatNdArray) super.get(coordinates);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public FloatNdArray setObject(Float value, long... coordinates) {
+ throw new ReadOnlyBufferException();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public FloatNdArray set(NdArray src, long... coordinates) {
+ throw new ReadOnlyBufferException();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public FloatNdArray copyTo(NdArray dst) {
+ return (FloatNdArray) super.copyTo(dst);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public FloatNdArray createDefaultArray() {
+ return NdArrays.scalarOf(getDefaultValue());
+ }
+}
diff --git a/ndarray/src/main/java/org/tensorflow/ndarray/impl/sparse/IntSparseNdArray.java b/ndarray/src/main/java/org/tensorflow/ndarray/impl/sparse/IntSparseNdArray.java
new file mode 100644
index 0000000..d79c441
--- /dev/null
+++ b/ndarray/src/main/java/org/tensorflow/ndarray/impl/sparse/IntSparseNdArray.java
@@ -0,0 +1,432 @@
+/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+=======================================================================*/
+package org.tensorflow.ndarray.impl.sparse;
+
+import org.tensorflow.ndarray.IntNdArray;
+import org.tensorflow.ndarray.LongNdArray;
+import org.tensorflow.ndarray.NdArray;
+import org.tensorflow.ndarray.NdArrays;
+import org.tensorflow.ndarray.Shape;
+import org.tensorflow.ndarray.StdArrays;
+import org.tensorflow.ndarray.buffer.DataBuffer;
+import org.tensorflow.ndarray.buffer.DataBuffers;
+import org.tensorflow.ndarray.buffer.IntDataBuffer;
+import org.tensorflow.ndarray.impl.dimension.DimensionalSpace;
+import org.tensorflow.ndarray.impl.sparse.slice.IntSparseSlice;
+import org.tensorflow.ndarray.index.Index;
+
+import java.nio.ReadOnlyBufferException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * sparse array for the int data type
+ *
+ * A sparse array as two separate dense arrays: indices, values, and a shape that represents the
+ * dense shape.
+ *
+ *
NOTE: all Sparse Arrays are readonly for the {@link #set(NdArray, long...)} and
+ * {@link #setObject(Integer, long...)} methods
+ *
+ *
{@code
+ * IntSparseNdArray st = new IntSparseNdArray(
+ * StdArrays.of(new long[][] {{0, 0}, {1, 2}}),
+ * NdArrays.vectorOf(1, 256),
+ * Shape.of(3, 4));
+ *
+ * }
+ *
+ * represents the dense array:
+ *
+ *
{@code
+ * [[1, 0, 0, 0]
+ * [0, 0, 256, 0]
+ * [0, 0, 0, 0]]
+ *
+ * }
+ */
+public class IntSparseNdArray extends AbstractSparseNdArray
+ implements IntNdArray {
+
+ /**
+ * Creates a IntSparseNdArray
+ *
+ * @param indices A 2-D LongNdArray of shape {@code [N, ndims]}, that specifies the indices of the
+ * elements in the sparse array that contain non-default values (elements are zero-indexed).
+ * For example, {@code indices=[[1,3], [2,4]]} specifies that the elements with indexes of
+ * {@code [1,3]} and {@code [2,4]} have non-default values.
+ * @param values A 1-D IntNdArray of shape {@code [N]}, which supplies the values for each element
+ * in indices. For example, given {@code indices=[[1,3], [2,4]]}, the parameter {@code
+ * values=[18, 3.6]} specifies that element {@code [1,3]} of the sparse NdArray has a value of
+ * {@code 18}, and element {@code [2,4]} of the NdArray has a value of {@code 3.6}.
+ * @param defaultValue Scalar value to set for indices not specified in {@link #getIndices()}
+ * @param dimensions the dimensional space for the dense object represented by this sparse array,
+ */
+ protected IntSparseNdArray(
+ LongNdArray indices, IntNdArray values, int defaultValue, DimensionalSpace dimensions) {
+ super(indices, values, defaultValue, dimensions);
+ }
+
+ /**
+ * Creates a IntSparseNdArray with a default value of zero.
+ *
+ * @param indices A 2-D LongNdArray of shape {@code [N, ndims]}, that specifies the indices of the
+ * elements in the sparse array that contain non-default values (elements are zero-indexed).
+ * For example, {@code indices=[[1,3], [2,4]]} specifies that the elements with indexes of
+ * {@code [1,3]} and {@code [2,4]} have non-default values.
+ * @param values A 1-D IntNdArray of shape {@code [N]}, which supplies the values for each element
+ * in indices. For example, given {@code indices=[[1,3], [2,4]]}, the parameter {@code
+ * values=[18, 3.6]} specifies that element {@code [1,3]} of the sparse NdArray has a value of
+ * {@code 18}, and element {@code [2,4]} of the NdArray has a value of {@code 3.6}.
+ * @param dimensions the dimensional space for the dense object represented by this sparse array,
+ */
+ IntSparseNdArray(LongNdArray indices, IntNdArray values, DimensionalSpace dimensions) {
+ this(indices, values, 0, dimensions);
+ }
+
+ /**
+ * Creates a IntSparseNdArray
+ *
+ * @param dataBuffer a dense dataBuffer used to create the spars array
+ * @param dimensions the dimensional space for the dense object represented by this sparse array,
+ */
+ IntSparseNdArray(IntDataBuffer dataBuffer, DimensionalSpace dimensions) {
+ this(dataBuffer, 0, dimensions);
+ }
+ /**
+ * Creates a IntSparseNdArray
+ *
+ * @param dataBuffer a dense dataBuffer used to create the spars array
+ * @param dimensions the dimensional space for the dense object represented by this sparse array,
+ */
+ IntSparseNdArray(IntDataBuffer dataBuffer, int defaultValue, DimensionalSpace dimensions) {
+ super(defaultValue, dimensions);
+ // use write to set up the indices and values
+ copyFrom(dataBuffer);
+ }
+
+ /**
+ * Creates a zero-filled IntSparseNdArray
+ *
+ * @param dimensions the dimensional space for the dense object represented by this sparse array,
+ */
+ IntSparseNdArray(DimensionalSpace dimensions) {
+ this(0, dimensions);
+ }
+
+ /**
+ * Creates a zero-filled IntSparseNdArray
+ *
+ * @param dimensions the dimensional space for the dense object represented by this sparse array,
+ */
+ IntSparseNdArray(int defaultValue, DimensionalSpace dimensions) {
+ super(defaultValue, dimensions);
+ }
+
+ /**
+ * Creates a new IntSparseNdArray
+ *
+ * @param indices A 2-D LongNdArray of shape {@code [N, ndims]}, that specifies the indices of the
+ * elements in the sparse array that contain non-default values (elements are zero-indexed).
+ * For example, {@code indices=[[1,3], [2,4]]} specifies that the elements with indexes of
+ * {@code [1,3]} and {@code [2,4]} have non-default values.
+ * @param values A 1-D NdArray of any type and shape {@code [N]}, which supplies the values for
+ * each element in indices. For example, given {@code indices=[[1,3], [2,4]]}, the parameter
+ * {@code values=[18, 3.6]} specifies that element {@code [1,3]} of the sparse NdArray has a
+ * value of {@code 18}, and element {@code [2,4]} of the NdArray has a value of {@code 3.6}.
+ * @param dimensions the dimensional space for the dense object represented by this sparse array.
+ * @return the new Sparse Array
+ */
+ public static IntSparseNdArray create(
+ LongNdArray indices, IntNdArray values, DimensionalSpace dimensions) {
+ return new IntSparseNdArray(indices, values, dimensions);
+ }
+
+ /**
+ * Creates a new IntSparseNdArray
+ *
+ * @param indices A 2-D LongNdArray of shape {@code [N, ndims]}, that specifies the indices of the
+ * elements in the sparse array that contain non-default values (elements are zero-indexed).
+ * For example, {@code indices=[[1,3], [2,4]]} specifies that the elements with indexes of
+ * {@code [1,3]} and {@code [2,4]} have non-default values.
+ * @param values A 1-D NdArray of any type and shape {@code [N]}, which supplies the values for
+ * each element in indices. For example, given {@code indices=[[1,3], [2,4]]}, the parameter
+ * {@code values=[18, 3.6]} specifies that element {@code [1,3]} of the sparse NdArray has a
+ * value of {@code 18}, and element {@code [2,4]} of the NdArray has a value of {@code 3.6}.
+ * @param dimensions the dimensional space for the dense object represented by this sparse array.
+ * @return the new Sparse Array
+ */
+ public static IntSparseNdArray create(
+ LongNdArray indices, IntNdArray values, int defaultValue, DimensionalSpace dimensions) {
+ return new IntSparseNdArray(indices, values, defaultValue, dimensions);
+ }
+
+ /**
+ * Creates a new IntSparseNdArray from a data buffer
+ *
+ * @param dataBuffer the databuffer containing the dense array
+ * @param dimensions the dimensional space for the sparse array
+ * @return the new Sparse Array
+ */
+ public static IntSparseNdArray create(IntDataBuffer dataBuffer, DimensionalSpace dimensions) {
+ return new IntSparseNdArray(dataBuffer, dimensions);
+ }
+
+ /**
+ * Creates a new IntSparseNdArray from a data buffer
+ *
+ * @param dataBuffer the databuffer containing the dense array
+ * @param dimensions the dimensional space for the sparse array
+ * @return the new Sparse Array
+ */
+ public static IntSparseNdArray create(
+ IntDataBuffer dataBuffer, int defaultValue, DimensionalSpace dimensions) {
+ return new IntSparseNdArray(dataBuffer, defaultValue, dimensions);
+ }
+
+ /**
+ * Creates a new empty IntSparseNdArray from a data buffer
+ *
+ * @param dimensions the dimensions array
+ * @return the new Sparse Array
+ */
+ public static IntSparseNdArray create(DimensionalSpace dimensions) {
+ return new IntSparseNdArray(dimensions);
+ }
+
+ /**
+ * Creates a new empty IntSparseNdArray from a data buffer
+ *
+ * @param dimensions the dimensions array
+ * @return the new Sparse Array
+ */
+ public static IntSparseNdArray create(int defaultValue, DimensionalSpace dimensions) {
+ return new IntSparseNdArray(defaultValue, dimensions);
+ }
+
+ /**
+ * Creates a new empty IntSparseNdArray from a data buffer
+ *
+ * @param shape the shape of the debse array that this sparse array represents
+ * @return the new Sparse Array
+ */
+ public static IntSparseNdArray create(Shape shape) {
+ return new IntSparseNdArray(DimensionalSpace.create(shape));
+ }
+ /**
+ * Creates a new empty IntSparseNdArray from a data buffer
+ *
+ * @param defaultValue Scalar value to set for indices not specified in {@link #getIndices()}
+ * @param shape the shape of the debse array that this sparse array represents
+ * @return the new Sparse Array
+ */
+ public static IntSparseNdArray create(int defaultValue, Shape shape) {
+ return new IntSparseNdArray(defaultValue, DimensionalSpace.create(shape));
+ }
+
+ /**
+ * Creates a new empty IntSparseNdArray from a int data buffer
+ *
+ * @param buffer the data buffer
+ * @param shape the shape of the sparse array.
+ * @return the new Sparse Array
+ */
+ public static IntSparseNdArray create(IntDataBuffer buffer, Shape shape) {
+ return new IntSparseNdArray(buffer, DimensionalSpace.create(shape));
+ }
+
+ /**
+ * Creates a new empty IntSparseNdArray from a int data buffer
+ *
+ * @param buffer the data buffer
+ * @param defaultValue Scalar value to set for indices not specified in {@link #getIndices()}
+ * @param shape the shape of the sparse array.
+ * @return the new Sparse Array
+ */
+ public static IntSparseNdArray create(IntDataBuffer buffer, int defaultValue, Shape shape) {
+ return new IntSparseNdArray(buffer, defaultValue, DimensionalSpace.create(shape));
+ }
+
+ /**
+ * Creates a new IntSparseNdArray from a IntNdArray
+ *
+ * @param src the IntNdArray
+ * @return the new Sparse Array
+ */
+ public static IntSparseNdArray create(IntNdArray src) {
+ IntDataBuffer buffer = DataBuffers.ofInts(src.size());
+ src.copyTo(buffer);
+ return new IntSparseNdArray(buffer, DimensionalSpace.create(src.shape()));
+ }
+
+ /**
+ * Creates a new IntSparseNdArray from a IntNdArray
+ *
+ * @param src the IntNdArray
+ * @param defaultValue Scalar value to set for indices not specified in {@link #getIndices()}
+ * @return the new Sparse Array
+ */
+ public static IntSparseNdArray create(IntNdArray src, int defaultValue) {
+ IntDataBuffer buffer = DataBuffers.ofInts(src.size());
+ src.copyTo(buffer);
+ return new IntSparseNdArray(buffer, defaultValue, DimensionalSpace.create(src.shape()));
+ }
+
+ /**
+ * Creates a IntNdArray of the specified shape
+ *
+ * @param shape the shape of the dense array.
+ * @return a IntNdArray of the specified shape
+ */
+ public IntNdArray createValues(Shape shape) {
+ return NdArrays.ofInts(shape);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public IntNdArray slice(long position, DimensionalSpace sliceDimensions) {
+ return new IntSparseSlice(this, position, sliceDimensions);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public int getInt(long... coordinates) {
+ return getObject(coordinates);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public IntNdArray setInt(int value, long... coordinates) {
+ throw new ReadOnlyBufferException();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public IntNdArray copyTo(DataBuffer dst) {
+ return copyTo((IntDataBuffer) dst);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public IntNdArray copyTo(IntDataBuffer dst) {
+ // set the values in buf to the default, then overwrite with indices/values
+ Integer[] defaults = new Integer[(int) shape().size()];
+ Arrays.fill(defaults, getDefaultValue());
+ dst.write(defaults);
+
+ AtomicInteger i = new AtomicInteger();
+ getIndices()
+ .elements(0)
+ .forEachIndexed(
+ (idx, l) -> {
+ long[] coordinates = getIndicesCoordinates(l);
+ int value = getValues().getInt(i.getAndIncrement());
+ dst.setObject(value, dimensions.positionOf(coordinates));
+ });
+ return this;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public IntNdArray copyFrom(IntDataBuffer src) {
+ List indices = new ArrayList<>();
+ List values = new ArrayList<>();
+
+ for (long i = 0; i < src.size(); i++) {
+ if (!src.getObject(i).equals(getDefaultValue())) {
+ indices.add(toCoordinates(dimensions, i));
+ values.add(src.getObject(i));
+ }
+ }
+ long[][] indicesArray = new long[indices.size()][];
+ int[] valuesArray = new int[values.size()];
+ for (int i = 0; i < indices.size(); i++) {
+ indicesArray[i] = indices.get(i);
+ valuesArray[i] = values.get(i);
+ }
+
+ setIndices(StdArrays.ndCopyOf(indicesArray));
+ setValues(NdArrays.vectorOf(valuesArray));
+ return this;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public IntNdArray copyFrom(DataBuffer src) {
+ return copyFrom((IntDataBuffer) src);
+ }
+
+ /**
+ * Converts the sparse array to a dense array
+ *
+ * @return the dense array
+ */
+ public IntNdArray toDense() {
+ IntDataBuffer dataBuffer = DataBuffers.ofInts(shape().size());
+ copyTo(dataBuffer);
+ return NdArrays.wrap(shape(), dataBuffer);
+ }
+
+ /**
+ * Populates this sparse array from a dense array
+ *
+ * @param src the dense array
+ * @return this sparse array
+ */
+ public IntNdArray fromDense(IntNdArray src) {
+ IntDataBuffer buffer = DataBuffers.ofInts(src.size());
+ src.copyTo(buffer);
+ copyFrom(buffer);
+ return this;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public IntNdArray slice(Index... indices) {
+ return (IntNdArray) super.slice(indices);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public IntNdArray get(long... coordinates) {
+ return (IntNdArray) super.get(coordinates);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public IntNdArray setObject(Integer value, long... coordinates) {
+ throw new ReadOnlyBufferException();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public IntNdArray set(NdArray src, long... coordinates) {
+ throw new ReadOnlyBufferException();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public IntNdArray copyTo(NdArray dst) {
+ return (IntNdArray) super.copyTo(dst);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public IntNdArray createDefaultArray() {
+ return NdArrays.scalarOf(getDefaultValue());
+ }
+}
diff --git a/ndarray/src/main/java/org/tensorflow/ndarray/impl/sparse/LongSparseNdArray.java b/ndarray/src/main/java/org/tensorflow/ndarray/impl/sparse/LongSparseNdArray.java
new file mode 100644
index 0000000..1c01198
--- /dev/null
+++ b/ndarray/src/main/java/org/tensorflow/ndarray/impl/sparse/LongSparseNdArray.java
@@ -0,0 +1,417 @@
+/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+=======================================================================*/
+package org.tensorflow.ndarray.impl.sparse;
+
+import org.tensorflow.ndarray.LongNdArray;
+import org.tensorflow.ndarray.NdArray;
+import org.tensorflow.ndarray.NdArrays;
+import org.tensorflow.ndarray.Shape;
+import org.tensorflow.ndarray.StdArrays;
+import org.tensorflow.ndarray.buffer.DataBuffer;
+import org.tensorflow.ndarray.buffer.DataBuffers;
+import org.tensorflow.ndarray.buffer.LongDataBuffer;
+import org.tensorflow.ndarray.impl.dimension.DimensionalSpace;
+import org.tensorflow.ndarray.impl.sparse.slice.LongSparseSlice;
+import org.tensorflow.ndarray.index.Index;
+
+import java.nio.ReadOnlyBufferException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * sparse array for the long data type
+ *
+ * A sparse array as two separate dense arrays: indices, values, and a shape that represents the
+ * dense shape.
+ *
+ *
NOTE: all Sparse Arrays are readonly for the {@link #set(NdArray, long...)} and
+ * {@link #setObject(Long, long...)} methods
+ *
+ *
{@code
+ * LongSparseNdArray st = new LongSparseNdArray(
+ * StdArrays.of(new long[][] {{0, 0}, {1, 2}}),
+ * NdArrays.vectorOf(1L, 256L),
+ * Shape.of(3, 4));
+ *
+ * }
+ *
+ * represents the dense array:
+ *
+ *
{@code
+ * [[1, 0, 0, 0]
+ * [0, 0, 256, 0]
+ * [0, 0, 0, 0]]
+ *
+ * }
+ */
+public class LongSparseNdArray extends AbstractSparseNdArray
+ implements LongNdArray {
+
+ /**
+ * Creates a LongSparseNdArray
+ *
+ * @param indices A 2-D LongNdArray of shape {@code [N, ndims]}, that specifies the indices of the
+ * elements in the sparse array that contain non-default values (elements are zero-indexed).
+ * For example, {@code indices=[[1,3], [2,4]]} specifies that the elements with indexes of
+ * {@code [1,3]} and {@code [2,4]} have non-default values.
+ * @param values A 1-D LongNdArray of shape {@code [N]}, which supplies the values for each
+ * element in indices. For example, given {@code indices=[[1,3], [2,4]]}, the parameter {@code
+ * values=[18, 3.6]} specifies that element {@code [1,3]} of the sparse NdArray has a value of
+ * {@code 18}, and element {@code [2,4]} of the NdArray has a value of {@code 3.6}.
+ * @param defaultValue Scalar value to set for indices not specified in {@link #getIndices()}
+ * @param dimensions the dimensional space for the dense object represented by this sparse array,
+ */
+ protected LongSparseNdArray(
+ LongNdArray indices, LongNdArray values, long defaultValue, DimensionalSpace dimensions) {
+ super(indices, values, defaultValue, dimensions);
+ }
+
+ /**
+ * Creates a LongSparseNdArray with a default value of zero.
+ *
+ * @param indices A 2-D LongNdArray of shape {@code [N, ndims]}, that specifies the indices of the
+ * elements in the sparse array that contain non-default values (elements are zero-indexed).
+ * For example, {@code indices=[[1,3], [2,4]]} specifies that the elements with indexes of
+ * {@code [1,3]} and {@code [2,4]} have non-default values.
+ * @param values A 1-D LongNdArray of shape {@code [N]}, which supplies the values for each
+ * element in indices. For example, given {@code indices=[[1,3], [2,4]]}, the parameter {@code
+ * values=[18, 3.6]} specifies that element {@code [1,3]} of the sparse NdArray has a value of
+ * {@code 18}, and element {@code [2,4]} of the NdArray has a value of {@code 3.6}.
+ * @param dimensions the dimensional space for the dense object represented by this sparse array,
+ */
+ LongSparseNdArray(LongNdArray indices, LongNdArray values, DimensionalSpace dimensions) {
+ this(indices, values, 0L, dimensions);
+ }
+
+ /**
+ * Creates a LongSparseNdArray
+ *
+ * @param dataBuffer a dense dataBuffer used to create the spars array
+ * @param dimensions the dimensional space for the dense object represented by this sparse array,
+ */
+ LongSparseNdArray(LongDataBuffer dataBuffer, DimensionalSpace dimensions) {
+ this(dataBuffer, 0L, dimensions);
+ }
+
+ /**
+ * Creates a LongSparseNdArray
+ *
+ * @param dataBuffer a dense dataBuffer used to create the spars array
+ * @param defaultValue Scalar value to set for indices not specified in {@link #getIndices()}
+ * @param dimensions the dimensional space for the dense object represented by this sparse array,
+ */
+ LongSparseNdArray(LongDataBuffer dataBuffer, long defaultValue, DimensionalSpace dimensions) {
+ super(defaultValue, dimensions);
+ // use write to set up the indices and values
+ copyFrom(dataBuffer);
+ }
+
+ /**
+ * Creates a zero-filled LongSparseNdArray
+ *
+ * @param dimensions the dimensional space for the dense object represented by this sparse array,
+ */
+ LongSparseNdArray(DimensionalSpace dimensions) {
+ this(0L, dimensions);
+ }
+
+ /**
+ * Creates a zero-filled LongSparseNdArray
+ *
+ * @param defaultValue Scalar value to set for indices not specified in {@link #getIndices()}
+ * @param dimensions the dimensional space for the dense object represented by this sparse array,
+ */
+ LongSparseNdArray(long defaultValue, DimensionalSpace dimensions) {
+ super(defaultValue, dimensions);
+ }
+
+ /**
+ * Creates a new LongSparseNdArray
+ *
+ * @param indices A 2-D LongNdArray of shape {@code [N, ndims]}, that specifies the indices of the
+ * elements in the sparse array that contain non-default values (elements are zero-indexed).
+ * For example, {@code indices=[[1,3], [2,4]]} specifies that the elements with indexes of
+ * {@code [1,3]} and {@code [2,4]} have non-default values.
+ * @param values A 1-D NdArray of any type and shape {@code [N]}, which supplies the values for
+ * each element in indices. For example, given {@code indices=[[1,3], [2,4]]}, the parameter
+ * {@code values=[18, 3.6]} specifies that element {@code [1,3]} of the sparse NdArray has a
+ * value of {@code 18}, and element {@code [2,4]} of the NdArray has a value of {@code 3.6}.
+ * @param dimensions the dimensional space for the dense object represented by this sparse array.
+ * @return the new Sparse Array
+ */
+ public static LongSparseNdArray create(
+ LongNdArray indices, LongNdArray values, DimensionalSpace dimensions) {
+ return new LongSparseNdArray(indices, values, dimensions);
+ }
+
+ /**
+ * Creates a new LongSparseNdArray
+ *
+ * @param indices A 2-D LongNdArray of shape {@code [N, ndims]}, that specifies the indices of the
+ * elements in the sparse array that contain non-default values (elements are zero-indexed).
+ * For example, {@code indices=[[1,3], [2,4]]} specifies that the elements with indexes of
+ * {@code [1,3]} and {@code [2,4]} have non-default values.
+ * @param values A 1-D NdArray of any type and shape {@code [N]}, which supplies the values for
+ * each element in indices. For example, given {@code indices=[[1,3], [2,4]]}, the parameter
+ * {@code values=[18, 3.6]} specifies that element {@code [1,3]} of the sparse NdArray has a
+ * value of {@code 18}, and element {@code [2,4]} of the NdArray has a value of {@code 3.6}.
+ * @param defaultValue Scalar value to set for indices not specified in {@link #getIndices()}
+ * @param dimensions the dimensional space for the dense object represented by this sparse array.
+ * @return the new Sparse Array
+ */
+ public static LongSparseNdArray create(
+ LongNdArray indices, LongNdArray values, long defaultValue, DimensionalSpace dimensions) {
+ return new LongSparseNdArray(indices, values, defaultValue, dimensions);
+ }
+
+ /**
+ * Creates a new LongSparseNdArray from a data buffer
+ *
+ * @param dataBuffer the databuffer containing the dense array
+ * @param dimensions the dimensional space for the sparse array
+ * @return the new Sparse Array
+ */
+ public static LongSparseNdArray create(LongDataBuffer dataBuffer, DimensionalSpace dimensions) {
+ return new LongSparseNdArray(dataBuffer, dimensions);
+ }
+
+ /**
+ * Creates a new LongSparseNdArray from a data buffer
+ *
+ * @param dataBuffer the databuffer containing the dense array
+ * @param defaultValue Scalar value to set for indices not specified in {@link #getIndices()}
+ * @param dimensions the dimensional space for the sparse array
+ * @return the new Sparse Array
+ */
+ public static LongSparseNdArray create(
+ LongDataBuffer dataBuffer, long defaultValue, DimensionalSpace dimensions) {
+ return new LongSparseNdArray(dataBuffer, defaultValue, dimensions);
+ }
+
+ /**
+ * Creates a new empty LongSparseNdArray from a data buffer
+ *
+ * @param dimensions the dimensions array
+ * @return the new Sparse Array
+ */
+ public static LongSparseNdArray create(DimensionalSpace dimensions) {
+ return new LongSparseNdArray(dimensions);
+ }
+
+ /**
+ * Creates a new empty LongSparseNdArray from a data buffer
+ *
+ * @param defaultValue Scalar value to set for indices not specified in {@link #getIndices()}
+ * @param dimensions the dimensions array
+ * @return the new Sparse Array
+ */
+ public static LongSparseNdArray create(long defaultValue, DimensionalSpace dimensions) {
+ return new LongSparseNdArray(defaultValue, dimensions);
+ }
+
+ /**
+ * Creates a new empty LongSparseNdArray from a long data buffer
+ *
+ * @param buffer the data buffer
+ * @param shape the shape of the sparse array.
+ * @return the new Sparse Array
+ */
+ public static LongSparseNdArray create(LongDataBuffer buffer, Shape shape) {
+ return new LongSparseNdArray(buffer, DimensionalSpace.create(shape));
+ }
+
+ /**
+ * Creates a new empty LongSparseNdArray from a long data buffer
+ *
+ * @param buffer the data buffer
+ * @param defaultValue Scalar value to set for indices not specified in {@link #getIndices()}
+ * @param shape the shape of the sparse array.
+ * @return the new Sparse Array
+ */
+ public static LongSparseNdArray create(LongDataBuffer buffer, long defaultValue, Shape shape) {
+ return new LongSparseNdArray(buffer, defaultValue, DimensionalSpace.create(shape));
+ }
+
+ /**
+ * Creates a new LongSparseNdArray from a LongNdArray
+ *
+ * @param src the LongNdArray
+ * @return the new Sparse Array
+ */
+ public static LongSparseNdArray create(LongNdArray src) {
+ LongDataBuffer buffer = DataBuffers.ofLongs(src.size());
+ src.copyTo(buffer);
+ return new LongSparseNdArray(buffer, DimensionalSpace.create(src.shape()));
+ }
+
+ /**
+ * Creates a new LongSparseNdArray from a LongNdArray
+ *
+ * @param src the LongNdArray
+ * @param defaultValue Scalar value to set for indices not specified in {@link #getIndices()}
+ * @return the new Sparse Array
+ */
+ public static LongSparseNdArray create(LongNdArray src, long defaultValue) {
+ LongDataBuffer buffer = DataBuffers.ofLongs(src.size());
+ src.copyTo(buffer);
+ return new LongSparseNdArray(buffer, defaultValue, DimensionalSpace.create(src.shape()));
+ }
+
+ /**
+ * Creates a LongNdArray of the specified shape
+ *
+ * @param shape the shape of the dense array.
+ * @return a LongNdArray of the specified shape
+ */
+ public LongNdArray createValues(Shape shape) {
+ return NdArrays.ofLongs(shape);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public LongNdArray slice(long position, DimensionalSpace sliceDimensions) {
+ return new LongSparseSlice(this, position, sliceDimensions);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public long getLong(long... coordinates) {
+ return getObject(coordinates);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public LongNdArray setLong(long value, long... coordinates) {
+ throw new ReadOnlyBufferException();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public LongNdArray copyTo(DataBuffer dst) {
+ return copyTo((LongDataBuffer) dst);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public LongNdArray copyTo(LongDataBuffer dst) {
+ // set the values in buf to the default, then overwrite with indices/values
+ Long[] defaults = new Long[(int) shape().size()];
+ Arrays.fill(defaults, getDefaultValue());
+ dst.write(defaults);
+
+ AtomicLong i = new AtomicLong();
+ getIndices()
+ .elements(0)
+ .forEachIndexed(
+ (idx, l) -> {
+ long[] coordinates = getIndicesCoordinates(l);
+ long value = getValues().getLong(i.getAndIncrement());
+ dst.setObject(value, dimensions.positionOf(coordinates));
+ });
+ return this;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public LongNdArray copyFrom(LongDataBuffer src) {
+ List indices = new ArrayList<>();
+ List values = new ArrayList<>();
+
+ for (long i = 0; i < src.size(); i++) {
+ if (!src.getObject(i).equals(getDefaultValue())) {
+ indices.add(toCoordinates(dimensions, i));
+ values.add(src.getObject(i));
+ }
+ }
+ long[][] indicesArray = new long[indices.size()][];
+ long[] valuesArray = new long[values.size()];
+ for (int i = 0; i < indices.size(); i++) {
+ indicesArray[i] = indices.get(i);
+ valuesArray[i] = values.get(i);
+ }
+
+ setIndices(StdArrays.ndCopyOf(indicesArray));
+ setValues(NdArrays.vectorOf(valuesArray));
+ return this;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public LongNdArray copyFrom(DataBuffer src) {
+ return copyFrom((LongDataBuffer) src);
+ }
+
+ /**
+ * Converts the sparse array to a dense array
+ *
+ * @return the dense array
+ */
+ public LongNdArray toDense() {
+ LongDataBuffer dataBuffer = DataBuffers.ofLongs(shape().size());
+ copyTo(dataBuffer);
+ return NdArrays.wrap(shape(), dataBuffer);
+ }
+
+ /**
+ * Populates this sparse array from a dense array
+ *
+ * @param src the dense array
+ * @return this sparse array
+ */
+ public LongNdArray fromDense(LongNdArray src) {
+ LongDataBuffer buffer = DataBuffers.ofLongs(src.size());
+ src.copyTo(buffer);
+ copyFrom(buffer);
+ return this;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public LongNdArray slice(Index... indices) {
+ return (LongNdArray) super.slice(indices);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public LongNdArray get(long... coordinates) {
+ return (LongNdArray) super.get(coordinates);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public LongNdArray setObject(Long value, long... coordinates) {
+ throw new ReadOnlyBufferException();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public LongNdArray set(NdArray src, long... coordinates) {
+ throw new ReadOnlyBufferException();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public LongNdArray copyTo(NdArray dst) {
+ return (LongNdArray) super.copyTo(dst);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public LongNdArray createDefaultArray() {
+ return NdArrays.scalarOf(getDefaultValue());
+ }
+}
diff --git a/ndarray/src/main/java/org/tensorflow/ndarray/impl/sparse/ShortSparseNdArray.java b/ndarray/src/main/java/org/tensorflow/ndarray/impl/sparse/ShortSparseNdArray.java
new file mode 100644
index 0000000..051a7cb
--- /dev/null
+++ b/ndarray/src/main/java/org/tensorflow/ndarray/impl/sparse/ShortSparseNdArray.java
@@ -0,0 +1,418 @@
+/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+=======================================================================*/
+package org.tensorflow.ndarray.impl.sparse;
+
+import org.tensorflow.ndarray.LongNdArray;
+import org.tensorflow.ndarray.NdArray;
+import org.tensorflow.ndarray.NdArrays;
+import org.tensorflow.ndarray.Shape;
+import org.tensorflow.ndarray.ShortNdArray;
+import org.tensorflow.ndarray.StdArrays;
+import org.tensorflow.ndarray.buffer.DataBuffer;
+import org.tensorflow.ndarray.buffer.DataBuffers;
+import org.tensorflow.ndarray.buffer.ShortDataBuffer;
+import org.tensorflow.ndarray.impl.dimension.DimensionalSpace;
+import org.tensorflow.ndarray.impl.sparse.slice.ShortSparseSlice;
+import org.tensorflow.ndarray.index.Index;
+
+import java.nio.ReadOnlyBufferException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * sparse array for the short data type
+ *
+ * A sparse array as two separate dense arrays: indices, values, and a shape that represents the
+ * dense shape.
+ *
+ *
NOTE: all Sparse Arrays are readonly for the {@link #set(NdArray, long...)} and
+ * {@link #setObject(Short, long...)} methods
+ *
+ *
{@code
+ * ShortSparseNdArray st = new ShortSparseNdArray(
+ * StdArrays.of(new long[][] {{0, 0}, {1, 2}}),
+ * NdArrays.vectorOf((short)1, (short)256}),
+ * Shape.of(3, 4));
+ *
+ * }
+ *
+ * represents the dense array:
+ *
+ *
{@code
+ * [[1, 0, 0, 0]
+ * [0, 0, 256, 0]
+ * [0, 0, 0, 0]]
+ *
+ * }
+ */
+public class ShortSparseNdArray extends AbstractSparseNdArray
+ implements ShortNdArray {
+
+ /**
+ * Creates a ShortSparseNdArray
+ *
+ * @param indices A 2-D LongNdArray of shape {@code [N, ndims]}, that specifies the indices of the
+ * elements in the sparse array that contain non-default values (elements are zero-indexed).
+ * For example, {@code indices=[[1,3], [2,4]]} specifies that the elements with indexes of
+ * {@code [1,3]} and {@code [2,4]} have non-default values.
+ * @param values A 1-D ShortNdArray of shape {@code [N]}, which supplies the values for each
+ * element in indices. For example, given {@code indices=[[1,3], [2,4]]}, the parameter {@code
+ * values=[18, 3.6]} specifies that element {@code [1,3]} of the sparse NdArray has a value of
+ * {@code 18}, and element {@code [2,4]} of the NdArray has a value of {@code 3.6}.
+ * @param defaultValue Scalar value to set for indices not specified in {@link #getIndices()}
+ * @param dimensions the dimensional space for the dense object represented by this sparse array,
+ */
+ protected ShortSparseNdArray(
+ LongNdArray indices, ShortNdArray values, short defaultValue, DimensionalSpace dimensions) {
+ super(indices, values, defaultValue, dimensions);
+ }
+
+ /**
+ * Creates a ShortSparseNdArray with a default value of zero.
+ *
+ * @param indices A 2-D LongNdArray of shape {@code [N, ndims]}, that specifies the indices of the
+ * elements in the sparse array that contain non-default values (elements are zero-indexed).
+ * For example, {@code indices=[[1,3], [2,4]]} specifies that the elements with indexes of
+ * {@code [1,3]} and {@code [2,4]} have non-default values.
+ * @param values A 1-D ShortNdArray of shape {@code [N]}, which supplies the values for each
+ * element in indices. For example, given {@code indices=[[1,3], [2,4]]}, the parameter {@code
+ * values=[18, 3.6]} specifies that element {@code [1,3]} of the sparse NdArray has a value of
+ * {@code 18}, and element {@code [2,4]} of the NdArray has a value of {@code 3.6}.
+ * @param dimensions the dimensional space for the dense object represented by this sparse array,
+ */
+ ShortSparseNdArray(LongNdArray indices, ShortNdArray values, DimensionalSpace dimensions) {
+ this(indices, values, (short) 0, dimensions);
+ }
+
+ /**
+ * Creates a ShortSparseNdArray
+ *
+ * @param dataBuffer a dense dataBuffer used to create the spars array
+ * @param dimensions the dimensional space for the dense object represented by this sparse array,
+ */
+ ShortSparseNdArray(ShortDataBuffer dataBuffer, DimensionalSpace dimensions) {
+ this(dataBuffer, (short) 0, dimensions);
+ }
+
+ /**
+ * Creates a ShortSparseNdArray
+ *
+ * @param dataBuffer a dense dataBuffer used to create the spars array
+ * @param defaultValue Scalar value to set for indices not specified in {@link #getIndices()}
+ * @param dimensions the dimensional space for the dense object represented by this sparse array,
+ */
+ ShortSparseNdArray(ShortDataBuffer dataBuffer, short defaultValue, DimensionalSpace dimensions) {
+ super(defaultValue, dimensions);
+ // use write to set up the indices and values
+ copyFrom(dataBuffer);
+ }
+
+ /**
+ * Creates a zero-filled ShortSparseNdArray
+ *
+ * @param dimensions the dimensional space for the dense object represented by this sparse array,
+ */
+ ShortSparseNdArray(DimensionalSpace dimensions) {
+ this((short) 0, dimensions);
+ }
+
+ /**
+ * Creates a zero-filled ShortSparseNdArray
+ *
+ * @param defaultValue Scalar value to set for indices not specified in {@link #getIndices()}
+ * @param dimensions the dimensional space for the dense object represented by this sparse array,
+ */
+ ShortSparseNdArray(short defaultValue, DimensionalSpace dimensions) {
+ super(defaultValue, dimensions);
+ }
+
+ /**
+ * Creates a new ShortSparseNdArray
+ *
+ * @param indices A 2-D LongNdArray of shape {@code [N, ndims]}, that specifies the indices of the
+ * elements in the sparse array that contain non-default values (elements are zero-indexed).
+ * For example, {@code indices=[[1,3], [2,4]]} specifies that the elements with indexes of
+ * {@code [1,3]} and {@code [2,4]} have non-default values.
+ * @param values A 1-D NdArray of any type and shape {@code [N]}, which supplies the values for
+ * each element in indices. For example, given {@code indices=[[1,3], [2,4]]}, the parameter
+ * {@code values=[18, 3.6]} specifies that element {@code [1,3]} of the sparse NdArray has a
+ * value of {@code 18}, and element {@code [2,4]} of the NdArray has a value of {@code 3.6}.
+ * @param dimensions the dimensional space for the dense object represented by this sparse array.
+ * @return the new Sparse Array
+ */
+ public static ShortSparseNdArray create(
+ LongNdArray indices, ShortNdArray values, DimensionalSpace dimensions) {
+ return new ShortSparseNdArray(indices, values, dimensions);
+ }
+
+ /**
+ * Creates a new ShortSparseNdArray
+ *
+ * @param indices A 2-D LongNdArray of shape {@code [N, ndims]}, that specifies the indices of the
+ * elements in the sparse array that contain non-default values (elements are zero-indexed).
+ * For example, {@code indices=[[1,3], [2,4]]} specifies that the elements with indexes of
+ * {@code [1,3]} and {@code [2,4]} have non-default values.
+ * @param values A 1-D NdArray of any type and shape {@code [N]}, which supplies the values for
+ * each element in indices. For example, given {@code indices=[[1,3], [2,4]]}, the parameter
+ * {@code values=[18, 3.6]} specifies that element {@code [1,3]} of the sparse NdArray has a
+ * value of {@code 18}, and element {@code [2,4]} of the NdArray has a value of {@code 3.6}.
+ * @param defaultValue Scalar value to set for indices not specified in {@link #getIndices()}
+ * @param dimensions the dimensional space for the dense object represented by this sparse array.
+ * @return the new Sparse Array
+ */
+ public static ShortSparseNdArray create(
+ LongNdArray indices, ShortNdArray values, short defaultValue, DimensionalSpace dimensions) {
+ return new ShortSparseNdArray(indices, values, defaultValue, dimensions);
+ }
+
+ /**
+ * Creates a new ShortSparseNdArray from a data buffer
+ *
+ * @param dataBuffer the databuffer containing the dense array
+ * @param dimensions the dimensional space for the sparse array
+ * @return the new Sparse Array
+ */
+ public static ShortSparseNdArray create(ShortDataBuffer dataBuffer, DimensionalSpace dimensions) {
+ return new ShortSparseNdArray(dataBuffer, dimensions);
+ }
+
+ /**
+ * Creates a new ShortSparseNdArray from a data buffer
+ *
+ * @param dataBuffer the databuffer containing the dense array
+ * @param defaultValue Scalar value to set for indices not specified in {@link #getIndices()}
+ * @param dimensions the dimensional space for the sparse array
+ * @return the new Sparse Array
+ */
+ public static ShortSparseNdArray create(
+ ShortDataBuffer dataBuffer, short defaultValue, DimensionalSpace dimensions) {
+ return new ShortSparseNdArray(dataBuffer, defaultValue, dimensions);
+ }
+
+ /**
+ * Creates a new empty ShortSparseNdArray from a data buffer
+ *
+ * @param dimensions the dimensions array
+ * @return the new Sparse Array
+ */
+ public static ShortSparseNdArray create(DimensionalSpace dimensions) {
+ return new ShortSparseNdArray(dimensions);
+ }
+
+ /**
+ * Creates a new empty ShortSparseNdArray from a data buffer
+ *
+ * @param defaultValue Scalar value to set for indices not specified in {@link #getIndices()}
+ * @param dimensions the dimensions array
+ * @return the new Sparse Array
+ */
+ public static ShortSparseNdArray create(short defaultValue, DimensionalSpace dimensions) {
+ return new ShortSparseNdArray(defaultValue, dimensions);
+ }
+
+ /**
+ * Creates a new empty ShortSparseNdArray from a short data buffer
+ *
+ * @param buffer the data buffer
+ * @param shape the shape of the sparse array.
+ * @return the new Sparse Array
+ */
+ public static ShortSparseNdArray create(ShortDataBuffer buffer, Shape shape) {
+ return new ShortSparseNdArray(buffer, DimensionalSpace.create(shape));
+ }
+
+ /**
+ * Creates a new empty ShortSparseNdArray from a short data buffer
+ *
+ * @param buffer the data buffer
+ * @param defaultValue Scalar value to set for indices not specified in {@link #getIndices()}
+ * @param shape the shape of the sparse array.
+ * @return the new Sparse Array
+ */
+ public static ShortSparseNdArray create(ShortDataBuffer buffer, short defaultValue, Shape shape) {
+ return new ShortSparseNdArray(buffer, defaultValue, DimensionalSpace.create(shape));
+ }
+
+ /**
+ * Creates a new ShortSparseNdArray from a ShortNdArray
+ *
+ * @param src the ShortNdArray
+ * @return the new Sparse Array
+ */
+ public static ShortSparseNdArray create(ShortNdArray src) {
+ ShortDataBuffer buffer = DataBuffers.ofShorts(src.size());
+ src.copyTo(buffer);
+ return new ShortSparseNdArray(buffer, DimensionalSpace.create(src.shape()));
+ }
+
+ /**
+ * Creates a new ShortSparseNdArray from a ShortNdArray
+ *
+ * @param src the ShortNdArray
+ * @param defaultValue Scalar value to set for indices not specified in {@link #getIndices()}
+ * @return the new Sparse Array
+ */
+ public static ShortSparseNdArray create(ShortNdArray src, short defaultValue) {
+ ShortDataBuffer buffer = DataBuffers.ofShorts(src.size());
+ src.copyTo(buffer);
+ return new ShortSparseNdArray(buffer, defaultValue, DimensionalSpace.create(src.shape()));
+ }
+
+ /**
+ * Creates a ShortNdArray of the specified shape
+ *
+ * @param shape the shape of the dense array.
+ * @return a ShortNdArray of the specified shape
+ */
+ public ShortNdArray createValues(Shape shape) {
+ return NdArrays.ofShorts(shape);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public ShortNdArray slice(long position, DimensionalSpace sliceDimensions) {
+ return new ShortSparseSlice(this, position, sliceDimensions);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public short getShort(long... coordinates) {
+ return getObject(coordinates);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public ShortNdArray setShort(short value, long... coordinates) {
+ throw new ReadOnlyBufferException();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public ShortNdArray copyTo(DataBuffer dst) {
+ return copyTo((ShortDataBuffer) dst);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public ShortNdArray copyTo(ShortDataBuffer dst) {
+ // set the values in buf to the default, then overwrite with indices/values
+ Short[] defaults = new Short[(int) shape().size()];
+ Arrays.fill(defaults, getDefaultValue());
+ dst.write(defaults);
+
+ AtomicInteger i = new AtomicInteger();
+ getIndices()
+ .elements(0)
+ .forEachIndexed(
+ (idx, l) -> {
+ long[] coordinates = getIndicesCoordinates(l);
+ short value = getValues().getShort(i.getAndIncrement());
+ dst.setObject(value, dimensions.positionOf(coordinates));
+ });
+ return this;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public ShortNdArray copyFrom(ShortDataBuffer src) {
+ List indices = new ArrayList<>();
+ List values = new ArrayList<>();
+
+ for (short i = 0; i < src.size(); i++) {
+ if (!src.getObject(i).equals(getDefaultValue())) {
+ indices.add(toCoordinates(dimensions, i));
+ values.add(src.getObject(i));
+ }
+ }
+ long[][] indicesArray = new long[indices.size()][];
+ short[] valuesArray = new short[values.size()];
+ for (int i = 0; i < indices.size(); i++) {
+ indicesArray[i] = indices.get(i);
+ valuesArray[i] = values.get(i);
+ }
+
+ setIndices(StdArrays.ndCopyOf(indicesArray));
+ setValues(NdArrays.vectorOf(valuesArray));
+ return this;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public ShortNdArray copyFrom(DataBuffer src) {
+ return copyFrom((ShortDataBuffer) src);
+ }
+
+ /**
+ * Converts the sparse array to a dense array
+ *
+ * @return the dense array
+ */
+ public ShortNdArray toDense() {
+ ShortDataBuffer dataBuffer = DataBuffers.ofShorts(shape().size());
+ copyTo(dataBuffer);
+ return NdArrays.wrap(shape(), dataBuffer);
+ }
+
+ /**
+ * Populates this sparse array from a dense array
+ *
+ * @param src the dense array
+ * @return this sparse array
+ */
+ public ShortNdArray fromDense(ShortNdArray src) {
+ ShortDataBuffer buffer = DataBuffers.ofShorts(src.size());
+ src.copyTo(buffer);
+ copyFrom(buffer);
+ return this;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public ShortNdArray slice(Index... indices) {
+ return (ShortNdArray) super.slice(indices);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public ShortNdArray get(long... coordinates) {
+ return (ShortNdArray) super.get(coordinates);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public ShortNdArray setObject(Short value, long... coordinates) {
+ throw new ReadOnlyBufferException();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public ShortNdArray set(NdArray src, long... coordinates) {
+ throw new ReadOnlyBufferException();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public ShortNdArray copyTo(NdArray dst) {
+ return (ShortNdArray) super.copyTo(dst);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public ShortNdArray createDefaultArray() {
+ return NdArrays.scalarOf(getDefaultValue());
+ }
+}
diff --git a/ndarray/src/main/java/org/tensorflow/ndarray/impl/sparse/SparseNdArray.java b/ndarray/src/main/java/org/tensorflow/ndarray/impl/sparse/SparseNdArray.java
new file mode 100644
index 0000000..c6d93f2
--- /dev/null
+++ b/ndarray/src/main/java/org/tensorflow/ndarray/impl/sparse/SparseNdArray.java
@@ -0,0 +1,418 @@
+/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+=======================================================================*/
+package org.tensorflow.ndarray.impl.sparse;
+
+import org.tensorflow.ndarray.LongNdArray;
+import org.tensorflow.ndarray.NdArray;
+import org.tensorflow.ndarray.NdArrays;
+import org.tensorflow.ndarray.Shape;
+import org.tensorflow.ndarray.StdArrays;
+import org.tensorflow.ndarray.buffer.DataBuffer;
+import org.tensorflow.ndarray.buffer.DataBuffers;
+import org.tensorflow.ndarray.impl.dimension.DimensionalSpace;
+import org.tensorflow.ndarray.impl.sparse.slice.ObjectSparseSlice;
+
+import java.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * sparse array for the any data type
+ *
+ * A sparse array has two separate dense arrays: indices, values, and a shape that represents the
+ * dense shape.
+ *
+ *
NOTE: all Sparse Arrays are readonly for the {@link #set(NdArray, long...)} and
+ * {@link #setObject(Object, long...)} methods
+ *
+ *
{@code
+ * SparseNdArray st = new SparseNdArray<>(
+ * StdArrays.of(new long[][] {{0, 0}, {1, 2}}),
+ * NdArrays.vectorOf("first", "second"),
+ * Shape.of(3, 4));
+ *
+ * }
+ *
+ * represents the dense array:
+ *
+ *
{@code
+ * [[true, false, false, false]
+ * [false, false, true, false]
+ * [false, false, false, false]]
+ *
+ * }
+ */
+public class SparseNdArray> extends AbstractSparseNdArray
+ implements org.tensorflow.ndarray.SparseNdArray {
+
+ private final Class type;
+
+ /**
+ * Creates a SparseNdArray
+ *
+ * @param indices A 2-D LongNdArray of shape {@code [N, ndims]}, that specifies the indices of the
+ * elements in the sparse array that contain non-default values (elements are zero-indexed).
+ * For example, {@code indices=[[1,3], [2,4]]} specifies that the elements with indexes of
+ * {@code [1,3]} and {@code [2,4]} have non-default values.
+ * @param values A 1-D NdArray of Boolean type and shape {@code [N]}, which supplies the values
+ * for each element in indices. For example, given {@code indices=[[1,3], [2,4]]}, the
+ * parameter {@code values=[18, 3.6]} specifies that element {@code [1,3]} of the sparse
+ * NdArray has a value of {@code 18}, and element {@code [2,4]} of the NdArray has a value of
+ * {@code 3.6}.
+ * @param defaultValue Scalar value to set for indices not specified in {@link #getIndices()}
+ * @param dimensions the dimensional space for the dense object represented by this sparse array,
+ */
+ protected SparseNdArray(
+ Class type, LongNdArray indices, U values, T defaultValue, DimensionalSpace dimensions) {
+ super(indices, values, defaultValue, dimensions);
+ this.type = type;
+ }
+
+ /**
+ * Creates a SparseNdArray with a default value of null.
+ *
+ * @param indices A 2-D LongNdArray of shape {@code [N, ndims]}, that specifies the indices of the
+ * elements in the sparse array that contain non-default values (elements are zero-indexed).
+ * For example, {@code indices=[[1,3], [2,4]]} specifies that the elements with indexes of
+ * {@code [1,3]} and {@code [2,4]} have non-default values.
+ * @param values A 1-D NdArray of Boolean type and shape {@code [N]}, which supplies the values
+ * for each element in indices. For example, given {@code indices=[[1,3], [2,4]]}, the
+ * parameter {@code values=[18, 3.6]} specifies that element {@code [1,3]} of the sparse
+ * NdArray has a value of {@code 18}, and element {@code [2,4]} of the NdArray has a value of
+ * {@code 3.6}.
+ * @param dimensions the dimensional space for the dense object represented by this sparse array,
+ */
+ SparseNdArray(Class type, LongNdArray indices, U values, DimensionalSpace dimensions) {
+ this(type, indices, values, null, dimensions);
+ }
+
+ /**
+ * Creates a SparseNdArray
+ *
+ * @param dataBuffer a dense dataBuffer used to create the spars array
+ * @param dimensions the dimensional space for the dense object represented by this sparse array,
+ */
+ SparseNdArray(Class type, DataBuffer dataBuffer, DimensionalSpace dimensions) {
+ this(type, dataBuffer, null, dimensions);
+ }
+
+ /**
+ * Creates a SparseNdArray
+ *
+ * @param dataBuffer a dense dataBuffer used to create the spars array
+ * @param defaultValue Scalar value to set for indices not specified in {@link #getIndices()}
+ * @param dimensions the dimensional space for the dense object represented by this sparse array,
+ */
+ SparseNdArray(
+ Class type, DataBuffer dataBuffer, T defaultValue, DimensionalSpace dimensions) {
+ super(defaultValue, dimensions);
+ this.type = type;
+ // use write to set up the indices and values
+ copyFrom(dataBuffer);
+ }
+
+ /**
+ * Creates a zero-filled SparseNdArray
+ *
+ * @param dimensions the dimensional space for the dense object represented by this sparse array,
+ */
+ SparseNdArray(Class type, DimensionalSpace dimensions) {
+ this(type, (T) null, dimensions);
+ }
+
+ /**
+ * Creates a zero-filled SparseNdArray
+ *
+ * @param defaultValue Scalar value to set for indices not specified in {@link #getIndices()}
+ * @param dimensions the dimensional space for the dense object represented by this sparse array,
+ */
+ SparseNdArray(Class type, T defaultValue, DimensionalSpace dimensions) {
+ super(defaultValue, dimensions);
+ this.type = type;
+ }
+
+ /**
+ * Creates a new SparseNdArray
+ *
+ * @param indices A 2-D LongNdArray of shape {@code [N, ndims]}, that specifies the indices of the
+ * elements in the sparse array that contain non-default values (elements are zero-indexed).
+ * For example, {@code indices=[[1,3], [2,4]]} specifies that the elements with indexes of
+ * {@code [1,3]} and {@code [2,4]} have non-default values.
+ * @param values A 1-D NdArray of any type and shape {@code [N]}, which supplies the values for
+ * each element in indices. For example, given {@code indices=[[1,3], [2,4]]}, the parameter
+ * {@code values=[18, 3.6]} specifies that element {@code [1,3]} of the sparse NdArray has a
+ * value of {@code 18}, and element {@code [2,4]} of the NdArray has a value of {@code 3.6}.
+ * @param dimensions the dimensional space for the dense object represented by this sparse array.
+ * @return the new Sparse Array
+ */
+ public static > SparseNdArray create(
+ Class type, LongNdArray indices, U values, DimensionalSpace dimensions) {
+ return new SparseNdArray<>(type, indices, values, dimensions);
+ }
+
+ /**
+ * Creates a new SparseNdArray
+ *
+ * @param indices A 2-D LongNdArray of shape {@code [N, ndims]}, that specifies the indices of the
+ * elements in the sparse array that contain non-default values (elements are zero-indexed).
+ * For example, {@code indices=[[1,3], [2,4]]} specifies that the elements with indexes of
+ * {@code [1,3]} and {@code [2,4]} have non-default values.
+ * @param values A 1-D NdArray of any type and shape {@code [N]}, which supplies the values for
+ * each element in indices. For example, given {@code indices=[[1,3], [2,4]]}, the parameter
+ * {@code values=[18, 3.6]} specifies that element {@code [1,3]} of the sparse NdArray has a
+ * value of {@code 18}, and element {@code [2,4]} of the NdArray has a value of {@code 3.6}.
+ * @param defaultValue Scalar value to set for indices not specified in {@link #getIndices()}
+ * @param dimensions the dimensional space for the dense object represented by this sparse array.
+ * @return the new Sparse Array
+ */
+ public static > SparseNdArray create(
+ Class type, LongNdArray indices, U values, T defaultValue, DimensionalSpace dimensions) {
+ return new SparseNdArray<>(type, indices, values, defaultValue, dimensions);
+ }
+
+ /**
+ * Creates a new SparseNdArray from a data buffer
+ *
+ * @param dataBuffer the databuffer containing the dense array
+ * @param dimensions the dimensional space for the sparse array
+ * @return the new Sparse Array
+ */
+ public static > SparseNdArray create(
+ Class type, DataBuffer dataBuffer, DimensionalSpace dimensions) {
+ return new SparseNdArray<>(type, dataBuffer, dimensions);
+ }
+
+ /**
+ * Creates a new SparseNdArray from a data buffer
+ *
+ * @param dataBuffer the databuffer containing the dense array
+ * @param defaultValue Scalar value to set for indices not specified in {@link #getIndices()}
+ * @param dimensions the dimensional space for the sparse array
+ * @return the new Sparse Array
+ */
+ public static > SparseNdArray create(
+ Class type, DataBuffer dataBuffer, T defaultValue, DimensionalSpace dimensions) {
+ return new SparseNdArray<>(type, dataBuffer, defaultValue, dimensions);
+ }
+
+ /**
+ * Creates a new empty SparseNdArray from a data buffer
+ *
+ * @param dimensions the dimensions array
+ * @return the new Sparse Array
+ */
+ public static > SparseNdArray create(
+ Class type, DimensionalSpace dimensions) {
+ return new SparseNdArray<>(type, dimensions);
+ }
+
+ /**
+ * Creates a new empty SparseNdArray from a data buffer
+ *
+ * @param dimensions the dimensions array
+ * @param defaultValue Scalar value to set for indices not specified in {@link #getIndices()}
+ * @return the new Sparse Array
+ */
+ public static > SparseNdArray create(
+ Class type, T defaultValue, DimensionalSpace dimensions) {
+ return new SparseNdArray<>(type, defaultValue, dimensions);
+ }
+
+ /**
+ * Creates a new empty SparseNdArray from a float data buffer
+ *
+ * @param buffer the data buffer
+ * @param shape the shape of the sparse array.
+ * @return the new Sparse Array
+ */
+ public static > SparseNdArray create(
+ Class type, DataBuffer buffer, Shape shape) {
+ return new SparseNdArray<>(type, buffer, DimensionalSpace.create(shape));
+ }
+
+ /**
+ * Creates a new empty SparseNdArray from a float data buffer
+ *
+ * @param buffer the data buffer
+ * @param defaultValue Scalar value to set for indices not specified in {@link #getIndices()}
+ * @param shape the shape of the sparse array.
+ * @return the new Sparse Array
+ */
+ public static > SparseNdArray