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 contiguous datasets and keep track of position. Note this is slower than ContiguousIterator
020 */
021public class ContiguousIteratorWithPosition extends IndexIterator {
022        final private int[] shape;
023        final private int endrank; // last dimensions index
024        final private int imax; // maximum index in array
025        final private int istep; // step over items
026        final private int[] pos; // position in dataset
027
028        /**
029         * Constructor for an iterator over the items of a dataset that are
030         * within the dimensions
031         *
032         * @param shape to use
033         * @param length of entire data array
034         */
035        public ContiguousIteratorWithPosition(final int[] shape, final int length) {
036                this(shape, length, 1);
037        }
038
039        /**
040         * Constructor for an iterator over the items of a dataset that are
041         * within the dimensions
042         *
043         * @param shape to use
044         * @param length of entire data array
045         * @param isize number of elements in an item
046         */
047        public ContiguousIteratorWithPosition(final int[] shape, final int length, final int isize) {
048                final int rank = shape == null ? 0 : shape.length;
049                this.shape = shape;
050                endrank = rank - 1;
051                istep = isize;
052                if (rank == 0) {
053                        pos = new int[0];
054                } else {
055                        pos = new int[endrank + 1];
056                        pos[endrank] = -1;
057                }
058                index = -isize;
059                imax = length * isize;
060        }
061
062        @Override
063        public boolean hasNext() {
064                // now move on one position
065                int j = endrank;
066                for (; j >= 0; j--) {
067                        pos[j]++;
068                        if (pos[j] >= shape[j]) {
069                                pos[j] = 0;
070                        } else {
071                                break;
072                        }
073                }
074                if (j == -1 && endrank >= 0) {
075                        return false;
076                }
077
078                index += istep;
079                return index < imax;
080        }
081
082        /**
083         * @return position indices (nb not a copy)
084         */
085        @Override
086        public int[] getPos() {
087                return pos;
088        }
089
090        @Override
091        public void reset() {
092                if (shape != null && shape.length > 0) {
093                        Arrays.fill(pos, 0);
094                        pos[endrank] = -1;
095                }
096                index = -istep;
097        }
098
099        @Override
100        public int[] getShape() {
101                return shape;
102        }
103}