Skip to content

Commit

Permalink
#391 Add HyperslabIndex
Browse files Browse the repository at this point in the history
  • Loading branch information
matteodg committed Apr 20, 2020
1 parent 9e13085 commit 8b9ca61
Show file tree
Hide file tree
Showing 2 changed files with 241 additions and 0 deletions.
107 changes: 107 additions & 0 deletions src/main/java/org/bytedeco/javacpp/indexer/HyperslabIndex.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*
* 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;

/**
* A hyperslab is a rectangular pattern defined by four arrays.
* <p>
* The {@code start} defines the origin of the hyperslab in the original coordinates.
* The {@code stride} is the number of elements to increment between selected elements.
* A stride of '1' is every element, a stride of '2' is every second element, etc.
* The default stride is 1.
* The {@code count} is the number of elements in the hyperslab selection.
* When the stride is 1, the selection is a hyper rectangle with a corner at {@code start}
* and size {@code count[0]} by {@code count[1]} by ...
* When stride is greater than one, the hyperslab bounded by start and the corners
* defined by {@code stride[n] * count[n]}.
* The {@code block} is a count on the number of repetitions of the hyperslab.
* The default block size is '1', which is one hyperslab. A block of 2 would be
* two hyperslabs in that dimension, with the second starting at {@code start[n]+ (count[n] * stride[n]) + 1}.
*
* @author Matteo Di Giovinazzo
* @see <a href="https://portal.hdfgroup.org/display/HDF5/Reading+From+or+Writing+To+a+Subset+of+a+Dataset">Reading From
* or Writing To a Subset of a Dataset</a>
* @see <a href="https://portal.hdfgroup.org/display/HDF5/H5S_SELECT_HYPERSLAB">H5S_SELECT_HYPERSLAB</a>
* @see <a href="https://support.hdfgroup.org/HDF5/doc1.6/UG/12_Dataspaces.html">Dataspaces</a>
*/
public class HyperslabIndex implements Index {

protected long[] sizes;
private final long[] physicalStrides;
//
protected long[] starts;
protected long[] strides;
protected long[] counts;
protected long[] blocks;

protected HyperslabIndex(long[] sizes, long[] starts, long[] strides, long[] counts, long[] blocks) {
this.sizes = sizes;
this.starts = starts;
this.strides = strides;
this.counts = counts;
this.blocks = blocks;
this.physicalStrides = DefaultIndex.strides(sizes);
}

public static Index hyperslab(long[] sizes, long[] starts, long[] strides, long[] counts, long[] blocks) {
return new HyperslabIndex(sizes, starts, strides, counts, blocks);
}

@Override
public long index(long i) {
return (starts[0] + strides[0] * (i / blocks[0]) + (i % blocks[0])) * physicalStrides[0];
}

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

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

@Override
public long index(long... indices) {
long index = 0;
for (int i = 0; i < indices.length; i++) {
long coordinate = indices[i];
long mappedCoordinate = starts[i] + strides[i] * (coordinate / blocks[i]) + (coordinate % blocks[i]);
index += mappedCoordinate * physicalStrides[i];
}
return index;
}

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

@Override
public long[] strides() {
return physicalStrides;
}
}
134 changes: 134 additions & 0 deletions src/test/java/org/bytedeco/javacpp/indexer/HyperslabIndexTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
/*
* Copyright (C) 2014-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;

import org.junit.BeforeClass;
import org.junit.Test;

import static org.bytedeco.javacpp.indexer.HyperslabIndex.hyperslab;
import static org.junit.Assert.assertEquals;

public class HyperslabIndexTest {

private static float[] ARRAY;

@BeforeClass
public static void beforeClass() {
ARRAY = new float[12 * 10];
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
ARRAY[i * 10 + j] = i * 10f + j;
}
}
for (int i = 11; i < 12; i++) {
for (int j = 0; j < 10; j++) {
ARRAY[i * 10 + j] = -1f;
}
}
}

@Test
public void testIndexI() {
long[] sizes = new long[]{120};
Index index = hyperslab(
sizes,
new long[]{1},
new long[]{4},
new long[]{2},
new long[]{3}
);
FloatIndexer indexer1d = FloatIndexer.create(ARRAY, index);

assertEquals(1f, indexer1d.get(0), 0f);
assertEquals(2f, indexer1d.get(1), 0f);
assertEquals(3f, indexer1d.get(2), 0f);
assertEquals(5f, indexer1d.get(3), 0f);
assertEquals(6f, indexer1d.get(4), 0f);
assertEquals(7f, indexer1d.get(5), 0f);
}

@Test
public void testIndexIJ() {
long[] sizes = new long[]{12, 10};
Index index = hyperslab(
sizes,
new long[]{1, 1},
new long[]{4, 3},
new long[]{2, 3},
new long[]{3, 2}
);

FloatIndexer indexer2d = FloatIndexer.create(ARRAY, index);

assertEquals(11f, indexer2d.get(0, 0), 0f);
assertEquals(21f, indexer2d.get(1, 0), 0f);
assertEquals(31f, indexer2d.get(2, 0), 0f);
assertEquals(51f, indexer2d.get(3, 0), 0f);
assertEquals(61f, indexer2d.get(4, 0), 0f);
assertEquals(71f, indexer2d.get(5, 0), 0f);
//
assertEquals(12f, indexer2d.get(0, 1), 0f);
assertEquals(22f, indexer2d.get(1, 1), 0f);
assertEquals(32f, indexer2d.get(2, 1), 0f);
assertEquals(52f, indexer2d.get(3, 1), 0f);
assertEquals(62f, indexer2d.get(4, 1), 0f);
assertEquals(72f, indexer2d.get(5, 1), 0f);
//
//
assertEquals(14f, indexer2d.get(0, 2), 0f);
assertEquals(24f, indexer2d.get(1, 2), 0f);
assertEquals(34f, indexer2d.get(2, 2), 0f);
assertEquals(54f, indexer2d.get(3, 2), 0f);
assertEquals(64f, indexer2d.get(4, 2), 0f);
assertEquals(74f, indexer2d.get(5, 2), 0f);
//
assertEquals(15f, indexer2d.get(0, 3), 0f);
assertEquals(25f, indexer2d.get(1, 3), 0f);
assertEquals(35f, indexer2d.get(2, 3), 0f);
assertEquals(55f, indexer2d.get(3, 3), 0f);
assertEquals(65f, indexer2d.get(4, 3), 0f);
assertEquals(75f, indexer2d.get(5, 3), 0f);
//
//
assertEquals(17f, indexer2d.get(0, 4), 0f);
assertEquals(27f, indexer2d.get(1, 4), 0f);
assertEquals(37f, indexer2d.get(2, 4), 0f);
assertEquals(57f, indexer2d.get(3, 4), 0f);
assertEquals(67f, indexer2d.get(4, 4), 0f);
assertEquals(77f, indexer2d.get(5, 4), 0f);
//
assertEquals(18f, indexer2d.get(0, 5), 0f);
assertEquals(28f, indexer2d.get(1, 5), 0f);
assertEquals(38f, indexer2d.get(2, 5), 0f);
assertEquals(58f, indexer2d.get(3, 5), 0f);
assertEquals(68f, indexer2d.get(4, 5), 0f);
assertEquals(78f, indexer2d.get(5, 5), 0f);
}

@Test
public void testIndexIJK() {
}

@Test
public void testIndexIndices() {
}
}

0 comments on commit 8b9ca61

Please sign in to comment.