Skip to content

Commit

Permalink
bytedeco#391 Move out Index as an interface and create a separate c…
Browse files Browse the repository at this point in the history
…lass `CustomStridesIndex` to keep the previous logic. Add also `DefaultIndex`
  • Loading branch information
matteodg committed Apr 20, 2020
1 parent 01b234a commit 34c5f3d
Show file tree
Hide file tree
Showing 5 changed files with 250 additions and 52 deletions.
87 changes: 87 additions & 0 deletions src/main/java/org/bytedeco/javacpp/indexer/CustomStridesIndex.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*
* Copyright (C) 2016-2019 Samuel Audet
*
* Licensed either under the Apache License, Version 2.0, or (at your option)
* under the terms of the GNU General Public License as published by
* the Free Software Foundation (subject to the "Classpath" exception),
* either version 2, or any later version (collectively, 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.gnu.org/licenses/
* http://www.gnu.org/software/classpath/license.html
*
* or as provided in the LICENSE.txt file that accompanied this code.
* 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.bytedeco.javacpp.indexer;

/**
* TODO
*
* @author Matteo Di Giovinazzo
*/
public class CustomStridesIndex implements Index {

protected final long[] sizes;

protected final long[] strides;

/**
* TODO
*
* @param sizes
* @param strides The number of elements to skip to reach the next element in a given dimension.
* {@code strides[i] > strides[i + 1] && strides[strides.length - 1] == 1} preferred.
*/
protected CustomStridesIndex(long[] sizes, long[] strides) {
this.sizes = sizes;
this.strides = strides;
}

public static Index customStrides(long[] sizes, long[] strides) {
return new CustomStridesIndex(sizes, strides);
}

@Override
public long[] sizes() { return sizes; }

@Deprecated
@Override
public long[] strides() { return strides; }

@Override
public long index(long i) {
return i * strides[0];
}

@Override
public long index(long i, long j) {
return i * strides[0] + j * strides[1];
}

@Override
public long index(long i, long j, long k) {
return i * strides[0] + j * strides[1] + k * strides[2];
}

/**
* Computes the linear index as the dot product of indices and strides.
*
* @param indices of each dimension
* @return index to access array or buffer
*/
@Override
public long index(long... indices) {
long index = 0;
for (int i = 0; i < indices.length && i < strides.length; i++) {
index += indices[i] * strides[i];
}
return index;
}
}
51 changes: 51 additions & 0 deletions src/main/java/org/bytedeco/javacpp/indexer/DefaultIndex.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Copyright (C) 2016-2019 Samuel Audet
*
* Licensed either under the Apache License, Version 2.0, or (at your option)
* under the terms of the GNU General Public License as published by
* the Free Software Foundation (subject to the "Classpath" exception),
* either version 2, or any later version (collectively, 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.gnu.org/licenses/
* http://www.gnu.org/software/classpath/license.html
*
* or as provided in the LICENSE.txt file that accompanied this code.
* 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.bytedeco.javacpp.indexer;

/**
* TODO
*
* @author Matteo Di Giovinazzo
*/
public class DefaultIndex extends CustomStridesIndex {

protected DefaultIndex(long... sizes) {
super(sizes, strides(sizes));
}

public static Index defaultIndex(long... sizes) {
return new DefaultIndex(sizes);
}

/**
* Returns default (row-major contiguous) strides for the given sizes.
*/
public static long[] strides(long... sizes) {
long[] strides = new long[sizes.length];
strides[sizes.length - 1] = 1;
for (int i = sizes.length - 2; i >= 0; i--) {
strides[i] = strides[i + 1] * sizes[i + 1];
}
return strides;
}

}
70 changes: 70 additions & 0 deletions src/main/java/org/bytedeco/javacpp/indexer/Index.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* Copyright (C) 2016-2019 Samuel Audet
*
* Licensed either under the Apache License, Version 2.0, or (at your option)
* under the terms of the GNU General Public License as published by
* the Free Software Foundation (subject to the "Classpath" exception),
* either version 2, or any later version (collectively, 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.gnu.org/licenses/
* http://www.gnu.org/software/classpath/license.html
*
* or as provided in the LICENSE.txt file that accompanied this code.
* 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.bytedeco.javacpp.indexer;

/**
* TODO
*
* @author Matteo Di Giovinazzo
*/
public interface Index {

/**
* TODO
*
* @param i
* @return
*/
long index(long i);

/**
* TODO
*
* @param i
* @param j
* @return
*/
long index(long i, long j);

/**
* TODO
*
* @param i
* @param j
* @param k
* @return
*/
long index(long i, long j, long k);

/**
* TODO
*
* @param indices
* @return
*/
long index(long... indices);

long[] sizes();

@Deprecated
long[] strides();
}
71 changes: 26 additions & 45 deletions src/main/java/org/bytedeco/javacpp/indexer/Indexer.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,12 @@

package org.bytedeco.javacpp.indexer;

import java.nio.Buffer;
import org.bytedeco.javacpp.Pointer;

import java.nio.Buffer;

import static org.bytedeco.javacpp.indexer.CustomStridesIndex.customStrides;

/**
* Top-level class of all data indexers, providing easy-to-use and efficient
* multidimensional access to primitive arrays, NIO buffers, and the raw memory interface.
Expand All @@ -49,34 +52,46 @@ public abstract class Indexer implements AutoCloseable {
release();
}

protected static final long[] ONE_STRIDE = { 1 };
@Deprecated protected static final long[] ONE_STRIDE = { 1 };

/**
* The number of elements in each dimension.
* These values are not typically used by the indexer.
*/
protected long[] sizes;
@Deprecated protected long[] sizes;
/**
* The number of elements to skip to reach the next element in a given dimension.
* {@code strides[i] > strides[i + 1] && strides[strides.length - 1] == 1} preferred.
*/
protected long[] strides;
@Deprecated protected long[] strides;
/**
* TODO
*/
protected Index index;

/** Constructor to set the {@link #index}. */
protected Indexer(Index index) {
this.index = index;
this.sizes = index.sizes();
this.strides = index.strides();
}

/** Constructor to set the {@link #sizes} and {@link #strides}. */
protected Indexer(long[] sizes, long[] strides) {
@Deprecated protected Indexer(long[] sizes, long[] strides) {
this(customStrides(sizes, strides));
this.sizes = sizes;
this.strides = strides;
}

/** Returns {@link #sizes} */
public long[] sizes() { return sizes; }
@Deprecated public long[] sizes() { return sizes; }
/** Returns {@link #strides} */
public long[] strides() { return strides; }
@Deprecated public long[] strides() { return strides; }

/** Returns {@code sizes[i]} */
public long size(int i) { return sizes[i]; }
@Deprecated public long size(int i) { return sizes[i]; }
/** Returns {@code strides[i]} */
public long stride(int i) { return strides[i]; }
@Deprecated public long stride(int i) { return strides[i]; }

/** Returns {@code sizes.length > 0 && sizes.length < 4 ? sizes[0] : -1} */
@Deprecated public long rows() { return sizes.length > 0 && sizes.length < 4 ? sizes[0] : -1; }
Expand All @@ -99,45 +114,11 @@ protected static final long checkIndex(long i, long size) {
/**
* Returns default (row-major contiguous) strides for the given sizes.
*/
@Deprecated
public static long[] strides(long... sizes) {
long[] strides = new long[sizes.length];
strides[sizes.length - 1] = 1;
for (int i = sizes.length - 2; i >= 0; i--) {
strides[i] = strides[i + 1] * sizes[i + 1];
}
return strides;
}

protected class Index {
public long index(long i) {
return i * strides[0];
}

public long index(long i, long j) {
return i * strides[0] + j * strides[1];
}

public long index(long i, long j, long k) {
return i * strides[0] + j * strides[1] + k * strides[2];
}

/**
* Computes the linear index as the dot product of indices and strides.
*
* @param indices of each dimension
* @return index to access array or buffer
*/
public long index(long... indices) {
long index = 0;
for (int i = 0; i < indices.length && i < strides.length; i++) {
index += indices[i] * strides[i];
}
return index;
}
return DefaultIndex.strides(sizes);
}

protected Index index = new Index();

/** Returns {@code index.index(i)}. */
public long index(long i) {
return index.index(i);
Expand Down
23 changes: 16 additions & 7 deletions src/test/java/org/bytedeco/javacpp/IndexerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
import org.bytedeco.javacpp.indexer.BooleanIndexer;
import org.bytedeco.javacpp.indexer.ByteIndexer;
import org.bytedeco.javacpp.indexer.CharIndexer;
import org.bytedeco.javacpp.indexer.CustomStridesIndex;
import static org.bytedeco.javacpp.indexer.CustomStridesIndex.customStrides;
import org.bytedeco.javacpp.indexer.DoubleIndexer;
import org.bytedeco.javacpp.indexer.FloatIndexer;
import org.bytedeco.javacpp.indexer.HalfIndexer;
Expand All @@ -42,6 +44,9 @@
import org.bytedeco.javacpp.indexer.UShortIndexer;
import org.bytedeco.javacpp.indexer.UIntIndexer;
import org.bytedeco.javacpp.indexer.ULongIndexer;
import org.bytedeco.javacpp.indexer.DefaultIndex;
import static org.bytedeco.javacpp.indexer.DefaultIndex.defaultIndex;
import org.bytedeco.javacpp.indexer.Index;
import org.bytedeco.javacpp.tools.Builder;
import org.junit.AfterClass;
import org.junit.BeforeClass;
Expand Down Expand Up @@ -74,36 +79,40 @@ public class IndexerTest {
}

static class TestIndexer extends Indexer {
TestIndexer(long[] sizes) { super(sizes, Indexer.strides(sizes)); }
TestIndexer(Index index) { super(index); }
public void release() { }
public double getDouble(long... indices) { return 0; }
public Indexer putDouble(long[] indices, double value) { return this; }
}

@Test public void testIndexer() {
System.out.println("Indexer");
@Test public void testDefaultStrides() {
long[] sizes = {640, 480, 3};
long[] strides = Indexer.strides(sizes);
long[] strides = DefaultIndex.strides(sizes);
System.out.println(Arrays.toString(strides));
assertEquals(1440, strides[0]);
assertEquals( 3, strides[1]);
assertEquals( 1, strides[2]);
}

@Test public void testIndexer() {
System.out.println("Indexer");
long[] sizes = {640, 480, 3};

TestIndexer indexer = new TestIndexer(sizes);
TestIndexer indexer = new TestIndexer(defaultIndex(sizes));
assertEquals(indexer.size(0), indexer.rows());
assertEquals(indexer.size(0), indexer.height());
assertEquals(indexer.size(1), indexer.cols());
assertEquals(indexer.size(1), indexer.width());
assertEquals(indexer.size(2), indexer.channels());

indexer = new TestIndexer(new long[] {640, 480});
indexer = new TestIndexer(defaultIndex(new long[] {640, 480}));
assertEquals(indexer.size(0), indexer.rows());
assertEquals(indexer.size(0), indexer.height());
assertEquals(indexer.size(1), indexer.cols());
assertEquals(indexer.size(1), indexer.width());
assertEquals(-1, indexer.channels());

indexer = new TestIndexer(new long[] {640});
indexer = new TestIndexer(defaultIndex(new long[] {640}));
assertEquals(indexer.size(0), indexer.rows());
assertEquals(indexer.size(0), indexer.height());
assertEquals(-1, indexer.cols());
Expand Down

0 comments on commit 34c5f3d

Please sign in to comment.