From 85281b2f2afa9613de7c00ceed24cca7764804ea Mon Sep 17 00:00:00 2001 From: Joachim Klein Date: Fri, 21 Jul 2017 12:52:38 +0000 Subject: [PATCH] common.iterable: add several helper classes [with Steffen Maercker] git-svn-id: https://www.prismmodelchecker.org/svn/prism/prism/trunk@12082 bbc10eb1-c90d-0410-af57-cb519fbb1720 --- prism/src/common/iterable/EmptyIterable.java | 99 ++++++ prism/src/common/iterable/EmptyIterator.java | 111 +++++++ .../common/iterable/FilteringIterator.java | 285 ++++++++++++++++++ prism/src/common/iterable/IterableDouble.java | 36 +++ prism/src/common/iterable/IterableInt.java | 36 +++ prism/src/common/iterable/IterableLong.java | 36 +++ .../src/common/iterable/RangeIntIterable.java | 87 ++++++ .../common/iterable/SingletonIterator.java | 137 +++++++++ 8 files changed, 827 insertions(+) create mode 100644 prism/src/common/iterable/EmptyIterable.java create mode 100644 prism/src/common/iterable/EmptyIterator.java create mode 100644 prism/src/common/iterable/FilteringIterator.java create mode 100644 prism/src/common/iterable/IterableDouble.java create mode 100644 prism/src/common/iterable/IterableInt.java create mode 100644 prism/src/common/iterable/IterableLong.java create mode 100644 prism/src/common/iterable/RangeIntIterable.java create mode 100644 prism/src/common/iterable/SingletonIterator.java diff --git a/prism/src/common/iterable/EmptyIterable.java b/prism/src/common/iterable/EmptyIterable.java new file mode 100644 index 00000000..31b66316 --- /dev/null +++ b/prism/src/common/iterable/EmptyIterable.java @@ -0,0 +1,99 @@ +//============================================================================== +// +// Copyright (c) 2016- +// Authors: +// * Steffen Maercker (TU Dresden) +// * Joachim Klein (TU Dresden) +// +//------------------------------------------------------------------------------ +// +// This file is part of PRISM. +// +// PRISM is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// PRISM is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with PRISM; if not, write to the Free Software Foundation, +// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +//============================================================================== + + +package common.iterable; + +import java.util.Iterator; + +/** + * Base class for Iterables returning empty iterators, + * static helpers for common primitive iterators. + */ +public abstract class EmptyIterable implements Iterable +{ + private static final Of OF = new Of<>(); + private static final OfInt OF_INT = new OfInt(); + private static final OfDouble OF_DOUBLE = new OfDouble(); + + @SuppressWarnings("unchecked") + public static Of Of() { + return (Of) OF; + } + + public static OfInt OfInt() { + return OF_INT; + } + + public static OfDouble OfDouble() { + return OF_DOUBLE; + } + + public static class Of extends EmptyIterable + { + private Of() {}; + + @Override + public Iterator iterator() + { + return EmptyIterator.Of(); + } + } + + public static class OfInt extends EmptyIterable implements IterableInt + { + private OfInt() {}; + + @Override + public EmptyIterator.OfInt iterator() + { + return EmptyIterator.OfInt(); + } + } + + public static class OfLong extends EmptyIterable implements IterableLong + { + private OfLong() {}; + + @Override + public EmptyIterator.OfLong iterator() + { + return EmptyIterator.OfLong(); + } + } + + public static class OfDouble extends EmptyIterable implements IterableDouble + { + private OfDouble() {}; + + @Override + public EmptyIterator.OfDouble iterator() + { + return EmptyIterator.OfDouble(); + } + } +} diff --git a/prism/src/common/iterable/EmptyIterator.java b/prism/src/common/iterable/EmptyIterator.java new file mode 100644 index 00000000..c468648e --- /dev/null +++ b/prism/src/common/iterable/EmptyIterator.java @@ -0,0 +1,111 @@ +//============================================================================== +// +// Copyright (c) 2016- +// Authors: +// * Steffen Maercker (TU Dresden) +// * Joachim Klein (TU Dresden) +// +//------------------------------------------------------------------------------ +// +// This file is part of PRISM. +// +// PRISM is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// PRISM is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with PRISM; if not, write to the Free Software Foundation, +// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +//============================================================================== + +package common.iterable; + +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.PrimitiveIterator; + +/** + * Base class for empty Iterators, + * static helpers for common primitive iterators. + */ +public abstract class EmptyIterator implements Iterator +{ + private static final Of OF = new Of<>(); + private static final OfInt OF_INT = new OfInt(); + private static final OfLong OF_LONG = new OfLong(); + private static final OfDouble OF_DOUBLE = new OfDouble(); + + @SuppressWarnings("unchecked") + public static Of Of() { + return (Of) OF; + } + + public static OfInt OfInt() { + return OF_INT; + } + + public static OfLong OfLong() { + return OF_LONG; + } + + public static OfDouble OfDouble() { + return OF_DOUBLE; + } + + @Override + public boolean hasNext() + { + return false; + } + + public static class Of extends EmptyIterator + { + private Of() {}; + + @Override + public T next() + { + throw new NoSuchElementException(); + } + } + + public static class OfInt extends EmptyIterator implements PrimitiveIterator.OfInt + { + private OfInt() {}; + + @Override + public int nextInt() + { + throw new NoSuchElementException(); + } + } + + public static class OfLong extends EmptyIterator implements PrimitiveIterator.OfLong + { + private OfLong() {}; + + @Override + public long nextLong() + { + throw new NoSuchElementException(); + } + } + + public static class OfDouble extends EmptyIterator implements PrimitiveIterator.OfDouble + { + private OfDouble() {}; + + @Override + public double nextDouble() + { + throw new NoSuchElementException(); + } + } +} diff --git a/prism/src/common/iterable/FilteringIterator.java b/prism/src/common/iterable/FilteringIterator.java new file mode 100644 index 00000000..f5e1904e --- /dev/null +++ b/prism/src/common/iterable/FilteringIterator.java @@ -0,0 +1,285 @@ +//============================================================================== +// +// Copyright (c) 2016- +// Authors: +// * Steffen Maercker (TU Dresden) +// * Joachim Klein (TU Dresden) +// +//------------------------------------------------------------------------------ +// +// This file is part of PRISM. +// +// PRISM is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// PRISM is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with PRISM; if not, write to the Free Software Foundation, +// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +//============================================================================== + +package common.iterable; + +import java.util.HashSet; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.Objects; +import java.util.PrimitiveIterator; +import java.util.Set; +import java.util.function.DoublePredicate; +import java.util.function.IntPredicate; +import java.util.function.LongPredicate; +import java.util.function.Predicate; + +/** + * Base class for filtering iterators, + * static helpers for common filtering task (deduping). + */ +public abstract class FilteringIterator implements Iterator +{ + protected final Iterator iterator; + protected boolean hasNext; + + public static Iterator nonNull(Iterable iterable) + { + return nonNull(iterable.iterator()); + } + + public static Iterator nonNull(Iterator iterator) + { + if (iterator instanceof PrimitiveIterator) { + return iterator; + } + return new FilteringIterator.Of<>(iterator, Objects::nonNull); + } + + public FilteringIterator(final Iterable iterable) + { + this(iterable.iterator()); + } + + public FilteringIterator(final Iterator iterator) + { + this.iterator = iterator; + } + + @Override + public boolean hasNext() + { + return hasNext; + } + + protected void requireNext() + { + if (!hasNext) { + throw new NoSuchElementException(); + } + } + + /** + * Obtain filtering iterator for the given iterator, + * filtering duplicate elements (via HashSet, requires + * that {@code equals()} and {@code hashCode()} are properly + * implemented). + */ + public static Iterator dedupe(final Iterator iterator) + { + final Set elements = new HashSet<>(); + return new FilteringIterator.Of<>(iterator, (Predicate) elements::add); + } + + /** + * Obtain filtering iterator for the given primitive int iterator, + * filtering duplicate elements (via HashSet). + */ + public static OfInt dedupe(final PrimitiveIterator.OfInt iterator) + { + // TODO: use BitSet? Evaluate performance in practice... + final Set elements = new HashSet<>(); + return new FilteringIterator.OfInt(iterator, (IntPredicate) elements::add); + } + + /** + * Obtain filtering iterator for the given primitive long iterator, + * filtering duplicate elements (via HashSet). + */ + public static OfLong dedupe(final PrimitiveIterator.OfLong iterator) + { + final Set elements = new HashSet<>(); + return new FilteringIterator.OfLong(iterator, (LongPredicate) elements::add); + } + + /** + * Obtain filtering iterator for the given primitive double iterator, + * filtering duplicate elements (via HashSet). + */ + public static OfDouble dedupe(final PrimitiveIterator.OfDouble iterator) + { + final Set elements = new HashSet<>(); + return new FilteringIterator.OfDouble(iterator, (DoublePredicate) elements::add); + } + + public static class Of extends FilteringIterator + { + protected final Predicate predicate; + private T next; + + public Of(Iterable iterable, Predicate predicate) + { + this(iterable.iterator(), predicate); + } + + public Of(Iterator iterator, Predicate predicate) + { + super(iterator); + this.predicate = predicate; + seekNext(); + } + + @Override + public T next() + { + requireNext(); + T current = next; + seekNext(); + return current; + } + + private void seekNext() + { + while (iterator.hasNext()) { + next = iterator.next(); + if (predicate.test(next)) { + hasNext = true; + return; + } + } + hasNext = false; + next = null; + } + } + + public static class OfInt extends FilteringIterator implements PrimitiveIterator.OfInt + { + protected final IntPredicate predicate; + private int next; + + public OfInt(IterableInt iterable, IntPredicate predicate) + { + this(iterable.iterator(), predicate); + } + + public OfInt(PrimitiveIterator.OfInt iterator, IntPredicate predicate) + { + super(iterator); + this.predicate = predicate; + seekNext(); + } + + @Override + public int nextInt() + { + requireNext(); + int current = next; + seekNext(); + return current; + } + + private void seekNext() + { + while (iterator.hasNext()) { + next = ((PrimitiveIterator.OfInt) iterator).nextInt(); + if (predicate.test(next)) { + hasNext = true; + return; + } + } + hasNext = false; + } + } + + public static class OfLong extends FilteringIterator implements PrimitiveIterator.OfLong + { + protected final LongPredicate predicate; + private long next; + + public OfLong(IterableLong iterable, LongPredicate predicate) + { + this(iterable.iterator(), predicate); + } + + public OfLong(PrimitiveIterator.OfLong iterator, LongPredicate predicate) + { + super(iterator); + this.predicate = predicate; + seekNext(); + } + + @Override + public long nextLong() + { + requireNext(); + long current = next; + seekNext(); + return current; + } + + private void seekNext() + { + while (iterator.hasNext()) { + next = ((PrimitiveIterator.OfLong) iterator).nextLong(); + if (predicate.test(next)) { + hasNext = true; + return; + } + } + hasNext = false; + } + } + + public static class OfDouble extends FilteringIterator implements PrimitiveIterator.OfDouble + { + protected final DoublePredicate predicate; + private double next; + + public OfDouble(IterableDouble iterable, DoublePredicate predicate) + { + this(iterable.iterator(), predicate); + } + + public OfDouble(PrimitiveIterator.OfDouble iterator, DoublePredicate predicate) + { + super(iterator); + this.predicate = predicate; + seekNext(); + } + + @Override + public double nextDouble() + { + requireNext(); + double current = next; + seekNext(); + return current; + } + + private void seekNext() + { + while (iterator.hasNext()) { + next = ((PrimitiveIterator.OfDouble) iterator).nextDouble(); + if (predicate.test(next)) { + hasNext = true; + return; + } + } + hasNext = false; + } + } +} diff --git a/prism/src/common/iterable/IterableDouble.java b/prism/src/common/iterable/IterableDouble.java new file mode 100644 index 00000000..f2690013 --- /dev/null +++ b/prism/src/common/iterable/IterableDouble.java @@ -0,0 +1,36 @@ +//============================================================================== +// +// Copyright (c) 2016- +// Authors: +// * Steffen Maercker (TU Dresden) +// +//------------------------------------------------------------------------------ +// +// This file is part of PRISM. +// +// PRISM is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// PRISM is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with PRISM; if not, write to the Free Software Foundation, +// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +//============================================================================== + +package common.iterable; + +import java.util.PrimitiveIterator.OfDouble; + +/** Iterable for a PrimitiveIterator.OfDouble */ +public interface IterableDouble extends Iterable +{ + @Override + public OfDouble iterator(); +} diff --git a/prism/src/common/iterable/IterableInt.java b/prism/src/common/iterable/IterableInt.java new file mode 100644 index 00000000..db8e4253 --- /dev/null +++ b/prism/src/common/iterable/IterableInt.java @@ -0,0 +1,36 @@ +//============================================================================== +// +// Copyright (c) 2016- +// Authors: +// * Steffen Maercker (TU Dresden) +// +//------------------------------------------------------------------------------ +// +// This file is part of PRISM. +// +// PRISM is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// PRISM is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with PRISM; if not, write to the Free Software Foundation, +// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +//============================================================================== + +package common.iterable; + +import java.util.PrimitiveIterator.OfInt; + +/** Iterable for a PrimitiveIterator.OfInt */ +public interface IterableInt extends Iterable +{ + @Override + public OfInt iterator(); +} diff --git a/prism/src/common/iterable/IterableLong.java b/prism/src/common/iterable/IterableLong.java new file mode 100644 index 00000000..c113ef73 --- /dev/null +++ b/prism/src/common/iterable/IterableLong.java @@ -0,0 +1,36 @@ +//============================================================================== +// +// Copyright (c) 2016- +// Authors: +// * Steffen Maercker (TU Dresden) +// +//------------------------------------------------------------------------------ +// +// This file is part of PRISM. +// +// PRISM is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// PRISM is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with PRISM; if not, write to the Free Software Foundation, +// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +//============================================================================== + +package common.iterable; + +import java.util.PrimitiveIterator.OfLong; + +/** Iterable for a PrimitiveIterator.OfLong */ +public interface IterableLong extends Iterable +{ + @Override + public OfLong iterator(); +} diff --git a/prism/src/common/iterable/RangeIntIterable.java b/prism/src/common/iterable/RangeIntIterable.java new file mode 100644 index 00000000..c8e220d8 --- /dev/null +++ b/prism/src/common/iterable/RangeIntIterable.java @@ -0,0 +1,87 @@ +//============================================================================== +// +// Copyright (c) 2016- +// Authors: +// * Joachim Klein (TU Dresden) +// +//------------------------------------------------------------------------------ +// +// This file is part of PRISM. +// +// PRISM is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// PRISM is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with PRISM; if not, write to the Free Software Foundation, +// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +//============================================================================== + + +package common.iterable; + +import java.util.PrimitiveIterator; + +/** + * An Iterable that returns a Primitive.OfInt iterator for all the integers + * between two values, first and last (inclusive). + * If first > last, then the sequence is descending (first, first-1, ..., last+1, last), + * otherwise it is ascending (first, first+1, ..., last-1, last). + */ +public class RangeIntIterable implements IterableInt +{ + /** The first integer of the sequence */ + final private int first; + /** The last integer of the sequence */ + final private int last; + /** Are we ascending? */ + final private boolean ascending; + + /** + * Constructor + * @param first the first integer in the sequence + * @param last the last integer in the sequence + */ + public RangeIntIterable(int first, int last) + { + this.first = first; + this.last = last; + ascending = (first <= last); + } + + @Override + public PrimitiveIterator.OfInt iterator() + { + return new PrimitiveIterator.OfInt() + { + int current = first; + + @Override + public boolean hasNext() + { + if (ascending) { + return current <= last; + } else { + return current >= last; + } + } + + @Override + public int nextInt() + { + if (ascending) { + return current++; + } else { + return current--; + } + } + }; + } +} diff --git a/prism/src/common/iterable/SingletonIterator.java b/prism/src/common/iterable/SingletonIterator.java new file mode 100644 index 00000000..62a5e365 --- /dev/null +++ b/prism/src/common/iterable/SingletonIterator.java @@ -0,0 +1,137 @@ +//============================================================================== +// +// Copyright (c) 2016- +// Authors: +// * Steffen Maercker (TU Dresden) +// +//------------------------------------------------------------------------------ +// +// This file is part of PRISM. +// +// PRISM is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// PRISM is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with PRISM; if not, write to the Free Software Foundation, +// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +//============================================================================== + +package common.iterable; + +import java.util.Iterator; +import java.util.Optional; +import java.util.OptionalDouble; +import java.util.OptionalInt; +import java.util.OptionalLong; +import java.util.PrimitiveIterator; + +/** + * Base class for an iterator that ranges over a single element, + * static helpers for common primitive iterators. + */ +public abstract class SingletonIterator implements Iterator +{ + public static class Of extends SingletonIterator + { + private Optional element; + + public Of(T element) + { + this.element = Optional.of(element); + } + + @Override + public boolean hasNext() + { + return element.isPresent(); + } + + @Override + public T next() + { + Optional result = element; + element = Optional.empty(); + return result.get(); + } + } + + public static class OfInt extends SingletonIterator implements PrimitiveIterator.OfInt + { + private OptionalInt element; + + public OfInt(int element) + { + this.element = OptionalInt.of(element); + } + + @Override + public boolean hasNext() + { + return element.isPresent(); + } + + @Override + public int nextInt() + { + OptionalInt result = element; + element = OptionalInt.empty(); + return result.getAsInt(); + } + } + + public static class OfLong extends SingletonIterator implements PrimitiveIterator.OfLong + { + private OptionalLong element; + + public OfLong(Long element) + { + this.element = OptionalLong.of(element); + } + + @Override + public boolean hasNext() + { + return element.isPresent(); + } + + @Override + public long nextLong() + { + OptionalLong result = element; + element = OptionalLong.empty(); + return result.getAsLong(); + } + } + + public static class OfDouble extends SingletonIterator implements PrimitiveIterator.OfDouble + { + private OptionalDouble element; + + public OfDouble(double element) + { + this.element = OptionalDouble.of(element); + } + + @Override + public boolean hasNext() + { + return element.isPresent(); + } + + @Override + public double nextDouble() + { + OptionalDouble result = element; + element = OptionalDouble.empty(); + return result.getAsDouble(); + } + } +}