001/*-
002 * Copyright 2016 Diamond Light Source Ltd.
003 *
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
010package org.eclipse.january.dataset;
011
012import java.util.Arrays;
013
014/**
015 * Base class for boolean iterators for pairs of dataset where the second dataset could be broadcast to the first and
016 * is used to select where {{@link #hasNext()} returns true. An optional third dataset can specify the output.
017 * For speed, there are public members.
018 */
019public abstract class BooleanIterator extends IndexIterator {
020
021        /**
022         * Create a boolean iterator that stops at every position in the choice dataset with a true value
023         * @param a primary dataset
024         * @param c choice dataset, can be null to choose all
025         * @since 2.1
026         */
027        public static BooleanIterator createIterator(Dataset a, Dataset c) {
028                return createIterator(true, a, c, null, false);
029        }
030
031        /**
032         * Create a boolean iterator that stops at every position in the choice dataset with a true value
033         * @param a primary dataset
034         * @param c choice dataset, can be null to choose all
035         * @param o output dataset, can be null
036         * @since 2.1
037         */
038        public static BooleanIterator createIterator(Dataset a, Dataset c, Dataset o) {
039                return createIterator(true, a, c, o, false);
040        }
041
042        /**
043         * Create a boolean iterator that stops at every position in the choice dataset where its value matches
044         * the given boolean
045         * @param v boolean value
046         * @param a primary dataset
047         * @param c choice dataset, can be null to choose all
048         * @param o output dataset, can be null
049         * @since 2.1
050         */
051        public static BooleanIterator createIterator(boolean v, Dataset a, Dataset c, Dataset o) {
052                return createIterator(v, a, c, o, false);
053        }
054
055        /**
056         * Create a boolean iterator that stops at every position in the choice dataset where its value matches
057         * the given boolean
058         * @param v boolean value
059         * @param a primary dataset
060         * @param c choice dataset, can be null to choose all
061         * @param o output dataset, can be null
062         * @param createIfNull if true create the output dataset if that is null
063         * @since 2.1
064         */
065        public static BooleanIterator createIterator(boolean v, Dataset a, Dataset c, Dataset o, boolean createIfNull) {
066                if (c == null) {
067                        return new BooleanNullIterator(a, o, createIfNull);
068                }
069                if (Arrays.equals(a.getShapeRef(), c.getShapeRef()) && a.getStrides() == null && c.getStrides() == null) {
070                        if (o == null || (o.getStrides() == null && Arrays.equals(a.getShapeRef(), o.getShapeRef()))) {
071                                return new BooleanContiguousIterator(v, a, c, o, createIfNull);
072                        }
073                }
074                return new BooleanBroadcastIterator(v, a, c, o, createIfNull);
075        }
076
077        protected final boolean value;
078
079        /**
080         * Index in choice dataset
081         */
082        public int cIndex;
083
084        /**
085         * Index in output dataset
086         */
087        public int oIndex;
088
089        /**
090         * Output dataset
091         */
092        protected Dataset oDataset;
093
094        final protected boolean outputA;
095
096        protected int[] maxShape;
097
098        protected final int aStep; // step over items
099        protected int oStep;
100        protected int aMax; // maximum index in array
101        protected int aStart, oStart;
102
103        protected Dataset aDataset;
104        protected Dataset cDataset;
105
106        /**
107         * @return choice
108         * @since 2.1
109         */
110        public Dataset getChoice() {
111                return cDataset;
112        }
113
114        @Override
115        public int[] getShape() {
116                return maxShape;
117        }
118
119        /**
120         * Construct a boolean iterator that stops at the given boolean value in choice dataset
121         * @param v boolean value
122         * @param a primary dataset
123         * @param c choice dataset
124         * @param o output dataset, can be null
125         */
126        protected BooleanIterator(boolean v, Dataset a, Dataset c, Dataset o) {
127                value = v;
128                aDataset = a;
129                aStep = a.getElementsPerItem();
130                cDataset = c;
131                oDataset = o;
132                outputA = a == o;
133                if (c != null && c == o) {
134                        throw new IllegalArgumentException("Output dataset must not be same as mask dataset");
135                }
136
137                if (c != null) {
138                        BroadcastUtils.checkItemSize(a, c, o);
139                } else if (o != null) {
140                        BroadcastUtils.checkItemSize(a, o);
141                }
142                if (o != null) {
143                        o.setDirty();
144                }
145        }
146
147        /**
148         * @return output dataset (can be null)
149         * @since 2.1
150         */
151        public Dataset getOutput() {
152                return oDataset;
153        }
154}