    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}