    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}