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         * @return boolean iterator
026         * @since 2.1
027         */
028        public static BooleanIterator createIterator(Dataset a, Dataset c) {
029                return createIterator(true, a, c, null, false);
030        }
031
032        /**
033         * Create a boolean iterator that stops at every position in the choice dataset with a true value
034         * @param a primary dataset
035         * @param c choice dataset, can be null to choose all
036         * @param o output dataset, can be null
037         * @return boolean iterator
038         * @since 2.1
039         */
040        public static BooleanIterator createIterator(Dataset a, Dataset c, Dataset o) {
041                return createIterator(true, a, c, o, false);
042        }
043
044        /**
045         * Create a boolean iterator that stops at every position in the choice dataset where its value matches
046         * the given boolean
047         * @param v boolean value
048         * @param a primary dataset
049         * @param c choice dataset, can be null to choose all
050         * @param o output dataset, can be null
051         * @return boolean iterator
052         * @since 2.1
053         */
054        public static BooleanIterator createIterator(boolean v, Dataset a, Dataset c, Dataset o) {
055                return createIterator(v, a, c, o, false);
056        }
057
058        /**
059         * Create a boolean iterator that stops at every position in the choice dataset where its value matches
060         * the given boolean
061         * @param v boolean value
062         * @param a primary dataset
063         * @param c choice dataset, can be null to choose all
064         * @param o output dataset, can be null
065         * @param createIfNull if true create the output dataset if that is null
066         * @return boolean iterator
067         * @since 2.1
068         */
069        public static BooleanIterator createIterator(boolean v, Dataset a, Dataset c, Dataset o, boolean createIfNull) {
070                if (c == null) {
071                        return new BooleanNullIterator(a, o, createIfNull);
072                }
073                if (Arrays.equals(a.getShapeRef(), c.getShapeRef()) && a.getStrides() == null && c.getStrides() == null) {
074                        if (o == null || (o.getStrides() == null && Arrays.equals(a.getShapeRef(), o.getShapeRef()))) {
075                                return new BooleanContiguousIterator(v, a, c, o, createIfNull);
076                        }
077                }
078                return new BooleanBroadcastIterator(v, a, c, o, createIfNull);
079        }
080
081        protected final boolean value;
082
083        /**
084         * Index in choice dataset
085         */
086        public int cIndex;
087
088        /**
089         * Index in output dataset
090         */
091        public int oIndex;
092
093        /**
094         * Output dataset
095         */
096        protected Dataset oDataset;
097
098        final protected boolean outputA;
099
100        protected int[] maxShape;
101
102        protected final int aStep; // step over items
103        protected int oStep;
104        protected int aMax; // maximum index in array
105        protected int aStart, oStart;
106
107        protected Dataset aDataset;
108        protected Dataset cDataset;
109
110        /**
111         * @return choice
112         * @since 2.1
113         */
114        public Dataset getChoice() {
115                return cDataset;
116        }
117
118        @Override
119        public int[] getShape() {
120                return maxShape;
121        }
122
123        /**
124         * Construct a boolean iterator that stops at the given boolean value in choice dataset
125         * @param v boolean value
126         * @param a primary dataset
127         * @param c choice dataset
128         * @param o output dataset, can be null
129         */
130        protected BooleanIterator(boolean v, Dataset a, Dataset c, Dataset o) {
131                value = v;
132                aDataset = a;
133                aStep = a.getElementsPerItem();
134                cDataset = c;
135                oDataset = o;
136                outputA = a == o;
137                if (c != null && c == o) {
138                        throw new IllegalArgumentException("Output dataset must not be same as mask dataset");
139                }
140
141                if (c != null) {
142                        BroadcastUtils.checkItemSize(a, c, o);
143                } else if (o != null) {
144                        BroadcastUtils.checkItemSize(a, o);
145                }
146                if (o != null) {
147                        o.setDirty();
148                }
149        }
150
151        /**
152         * @return output dataset (can be null)
153         * @since 2.1
154         */
155        public Dataset getOutput() {
156                return oDataset;
157        }
158}