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}