    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}