001/*- 002 ******************************************************************************* 003 * Copyright (c) 2011, 2016 Diamond Light Source Ltd. 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the Eclipse Public License v1.0 006 * which accompanies this distribution, and is available at 007 * http://www.eclipse.org/legal/epl-v10.html 008 * 009 * Contributors: 010 * Peter Chang - initial API and implementation and/or initial documentation 011 *******************************************************************************/ 012 013package org.eclipse.january.dataset; 014 015import java.util.Arrays; 016 017 018/** 019 * Class to run over non-contiguous or fragmented datasets 020 */ 021public class DiscontiguousIterator extends IndexIterator { 022 final private int[] shape; 023 final private int endrank; // last dimensions index 024 final private int[] gaps; // gaps in dataset 025 final private int imax; // maximum index in array 026 final private int istep; // step over items 027 final private int[] pos; // position in dataset 028 029 /** 030 * Constructor for an iterator over the elements of a dataset that are 031 * within the dimensions 032 * 033 * @param shape 034 * @param dataShape 035 * @param length of entire data array 036 */ 037 public DiscontiguousIterator(final int[] shape, final int[] dataShape, final int length) { 038 this(shape, dataShape, length, 1); 039 } 040 041 /** 042 * Constructor for an iterator over the elements of a dataset that are 043 * within the dimensions 044 * 045 * @param shape 046 * @param dataShape 047 * @param length of entire data array 048 * @param isize number of elements in an item 049 */ 050 public DiscontiguousIterator(final int[] shape, final int[] dataShape, final int length, final int isize) { 051 this.shape = shape; 052 endrank = shape.length - 1; 053 istep = isize; 054 pos = new int[endrank + 1]; 055 pos[endrank] = -1; 056 index = -isize; 057 imax = length; 058 059 gaps = new int[endrank + 1]; 060 int chunk = isize; 061 for (int i = endrank; i >= 0; i--) { 062 gaps[i] = (dataShape[i] - shape[i])*chunk; 063 chunk *= dataShape[i]; 064 } 065 } 066 067 @Override 068 public boolean hasNext() { 069 // now move on one position 070 int j = endrank; 071 for (; j >= 0; j--) { 072 pos[j]++; 073 if (pos[j] >= shape[j]) { 074 pos[j] = 0; 075 index += gaps[j]; 076 } else { 077 break; 078 } 079 } 080 if (j == -1) { 081 index = imax; 082 return false; 083 } 084 085 index += istep; 086 return index < imax; 087 } 088 089 @Override 090 public int[] getPos() { 091 return pos; 092 } 093 094 @Override 095 public void reset() { 096 Arrays.fill(pos, 0); 097 pos[endrank] = -1; 098 index = -istep; 099 } 100 101 @Override 102 public int[] getShape() { 103 return shape; 104 } 105}