// 
// Decompiled by Procyon v0.6.0
// 

package it.unimi.dsi.fastutil.booleans;

import java.util.NoSuchElementException;
import java.util.Arrays;
import it.unimi.dsi.fastutil.SafeMath;
import java.util.Comparator;
import java.util.function.Consumer;
import java.io.Serializable;
import java.util.Objects;
import java.util.Spliterator;

public final class BooleanSpliterators
{
    static final int BASE_SPLITERATOR_CHARACTERISTICS = 256;
    public static final int COLLECTION_SPLITERATOR_CHARACTERISTICS = 320;
    public static final int LIST_SPLITERATOR_CHARACTERISTICS = 16720;
    public static final int SET_SPLITERATOR_CHARACTERISTICS = 321;
    private static final int SORTED_CHARACTERISTICS = 20;
    public static final int SORTED_SET_SPLITERATOR_CHARACTERISTICS = 341;
    public static final EmptySpliterator EMPTY_SPLITERATOR;
    
    private BooleanSpliterators() {
    }
    
    public static BooleanSpliterator singleton(final boolean element) {
        return new SingletonSpliterator(element);
    }
    
    public static BooleanSpliterator singleton(final boolean element, final BooleanComparator comparator) {
        return new SingletonSpliterator(element, comparator);
    }
    
    public static BooleanSpliterator wrap(final boolean[] array, final int offset, final int length) {
        BooleanArrays.ensureOffsetLength(array, offset, length);
        return new ArraySpliterator(array, offset, length, 0);
    }
    
    public static BooleanSpliterator wrap(final boolean[] array) {
        return new ArraySpliterator(array, 0, array.length, 0);
    }
    
    public static BooleanSpliterator wrap(final boolean[] array, final int offset, final int length, final int additionalCharacteristics) {
        BooleanArrays.ensureOffsetLength(array, offset, length);
        return new ArraySpliterator(array, offset, length, additionalCharacteristics);
    }
    
    public static BooleanSpliterator wrapPreSorted(final boolean[] array, final int offset, final int length, final int additionalCharacteristics, final BooleanComparator comparator) {
        BooleanArrays.ensureOffsetLength(array, offset, length);
        return new ArraySpliteratorWithComparator(array, offset, length, additionalCharacteristics, comparator);
    }
    
    public static BooleanSpliterator wrapPreSorted(final boolean[] array, final int offset, final int length, final BooleanComparator comparator) {
        return wrapPreSorted(array, offset, length, 0, comparator);
    }
    
    public static BooleanSpliterator wrapPreSorted(final boolean[] array, final BooleanComparator comparator) {
        return wrapPreSorted(array, 0, array.length, comparator);
    }
    
    public static BooleanSpliterator asBooleanSpliterator(final Spliterator i) {
        if (i instanceof BooleanSpliterator) {
            return (BooleanSpliterator)i;
        }
        return new SpliteratorWrapper(i);
    }
    
    public static BooleanSpliterator asBooleanSpliterator(final Spliterator i, final BooleanComparator comparatorOverride) {
        if (i instanceof BooleanSpliterator) {
            throw new IllegalArgumentException("Cannot override comparator on instance that is already a " + BooleanSpliterator.class.getSimpleName());
        }
        return new SpliteratorWrapperWithComparator(i, comparatorOverride);
    }
    
    public static void onEachMatching(final BooleanSpliterator spliterator, final BooleanPredicate predicate, final BooleanConsumer action) {
        Objects.requireNonNull(predicate);
        Objects.requireNonNull(action);
        ((Spliterator.OfPrimitive<T, BooleanConsumer, T_SPLITR>)spliterator).forEachRemaining(value -> {
            if (predicate.test(value)) {
                action.accept(value);
            }
        });
    }
    
    public static BooleanSpliterator concat(final BooleanSpliterator... a) {
        return concat(a, 0, a.length);
    }
    
    public static BooleanSpliterator concat(final BooleanSpliterator[] a, final int offset, final int length) {
        return new SpliteratorConcatenator(a, offset, length);
    }
    
    public static BooleanSpliterator asSpliterator(final BooleanIterator iter, final long size, final int additionalCharacterisitcs) {
        return new SpliteratorFromIterator(iter, size, additionalCharacterisitcs);
    }
    
    public static BooleanSpliterator asSpliteratorFromSorted(final BooleanIterator iter, final long size, final int additionalCharacterisitcs, final BooleanComparator comparator) {
        return new SpliteratorFromIteratorWithComparator(iter, size, additionalCharacterisitcs, comparator);
    }
    
    public static BooleanSpliterator asSpliteratorUnknownSize(final BooleanIterator iter, final int characterisitcs) {
        return new SpliteratorFromIterator(iter, characterisitcs);
    }
    
    public static BooleanSpliterator asSpliteratorFromSortedUnknownSize(final BooleanIterator iter, final int additionalCharacterisitcs, final BooleanComparator comparator) {
        return new SpliteratorFromIteratorWithComparator(iter, additionalCharacterisitcs, comparator);
    }
    
    public static BooleanIterator asIterator(final BooleanSpliterator spliterator) {
        return new IteratorFromSpliterator(spliterator);
    }
    
    static {
        EMPTY_SPLITERATOR = new EmptySpliterator();
    }
    
    public static class EmptySpliterator implements BooleanSpliterator, Serializable, Cloneable
    {
        private static final long serialVersionUID = 8379247926738230492L;
        private static final int CHARACTERISTICS = 16448;
        
        protected EmptySpliterator() {
        }
        
        @Override
        public boolean tryAdvance(final BooleanConsumer action) {
            return false;
        }
        
        @Deprecated
        @Override
        public boolean tryAdvance(final Consumer<? super Boolean> action) {
            return false;
        }
        
        @Override
        public BooleanSpliterator trySplit() {
            return null;
        }
        
        @Override
        public long estimateSize() {
            return 0L;
        }
        
        @Override
        public int characteristics() {
            return 16448;
        }
        
        @Override
        public void forEachRemaining(final BooleanConsumer action) {
        }
        
        @Deprecated
        @Override
        public void forEachRemaining(final Consumer<? super Boolean> action) {
        }
        
        public Object clone() {
            return BooleanSpliterators.EMPTY_SPLITERATOR;
        }
        
        private Object readResolve() {
            return BooleanSpliterators.EMPTY_SPLITERATOR;
        }
    }
    
    private static class SingletonSpliterator implements BooleanSpliterator
    {
        private final boolean element;
        private final BooleanComparator comparator;
        private boolean consumed;
        private static final int CHARACTERISTICS = 17749;
        
        public SingletonSpliterator(final boolean element) {
            this(element, null);
        }
        
        public SingletonSpliterator(final boolean element, final BooleanComparator comparator) {
            this.consumed = false;
            this.element = element;
            this.comparator = comparator;
        }
        
        @Override
        public boolean tryAdvance(final BooleanConsumer action) {
            Objects.requireNonNull(action);
            if (this.consumed) {
                return false;
            }
            this.consumed = true;
            action.accept(this.element);
            return true;
        }
        
        @Override
        public BooleanSpliterator trySplit() {
            return null;
        }
        
        @Override
        public long estimateSize() {
            return this.consumed ? 0 : 1;
        }
        
        @Override
        public int characteristics() {
            return 17749;
        }
        
        @Override
        public void forEachRemaining(final BooleanConsumer action) {
            Objects.requireNonNull(action);
            if (!this.consumed) {
                this.consumed = true;
                action.accept(this.element);
            }
        }
        
        @Override
        public BooleanComparator getComparator() {
            return this.comparator;
        }
        
        @Override
        public long skip(final long n) {
            if (n < 0L) {
                throw new IllegalArgumentException("Argument must be nonnegative: " + n);
            }
            if (n == 0L || this.consumed) {
                return 0L;
            }
            this.consumed = true;
            return 1L;
        }
    }
    
    private static class ArraySpliterator implements BooleanSpliterator
    {
        private static final int BASE_CHARACTERISTICS = 16720;
        final boolean[] array;
        private final int offset;
        private int length;
        private int curr;
        final int characteristics;
        
        public ArraySpliterator(final boolean[] array, final int offset, final int length, final int additionalCharacteristics) {
            this.array = array;
            this.offset = offset;
            this.length = length;
            this.characteristics = (0x4150 | additionalCharacteristics);
        }
        
        @Override
        public boolean tryAdvance(final BooleanConsumer action) {
            if (this.curr >= this.length) {
                return false;
            }
            Objects.requireNonNull(action);
            action.accept(this.array[this.offset + this.curr++]);
            return true;
        }
        
        @Override
        public long estimateSize() {
            return this.length - this.curr;
        }
        
        @Override
        public int characteristics() {
            return this.characteristics;
        }
        
        protected ArraySpliterator makeForSplit(final int newOffset, final int newLength) {
            return new ArraySpliterator(this.array, newOffset, newLength, this.characteristics);
        }
        
        @Override
        public BooleanSpliterator trySplit() {
            final int retLength = this.length - this.curr >> 1;
            if (retLength <= 1) {
                return null;
            }
            final int myNewCurr = this.curr + retLength;
            final int retOffset = this.offset + this.curr;
            this.curr = myNewCurr;
            return this.makeForSplit(retOffset, retLength);
        }
        
        @Override
        public void forEachRemaining(final BooleanConsumer action) {
            Objects.requireNonNull(action);
            while (this.curr < this.length) {
                action.accept(this.array[this.offset + this.curr]);
                ++this.curr;
            }
        }
        
        @Override
        public long skip(long n) {
            if (n < 0L) {
                throw new IllegalArgumentException("Argument must be nonnegative: " + n);
            }
            if (this.curr >= this.length) {
                return 0L;
            }
            final int remaining = this.length - this.curr;
            if (n < remaining) {
                this.curr = SafeMath.safeLongToInt(this.curr + n);
                return n;
            }
            n = remaining;
            this.curr = this.length;
            return n;
        }
    }
    
    private static class ArraySpliteratorWithComparator extends ArraySpliterator
    {
        private final BooleanComparator comparator;
        
        public ArraySpliteratorWithComparator(final boolean[] array, final int offset, final int length, final int additionalCharacteristics, final BooleanComparator comparator) {
            super(array, offset, length, additionalCharacteristics | 0x14);
            this.comparator = comparator;
        }
        
        @Override
        protected ArraySpliteratorWithComparator makeForSplit(final int newOffset, final int newLength) {
            return new ArraySpliteratorWithComparator(this.array, newOffset, newLength, this.characteristics, this.comparator);
        }
        
        @Override
        public BooleanComparator getComparator() {
            return this.comparator;
        }
    }
    
    private static class SpliteratorWrapper implements BooleanSpliterator
    {
        final Spliterator<Boolean> i;
        
        public SpliteratorWrapper(final Spliterator<Boolean> i) {
            this.i = i;
        }
        
        @Override
        public boolean tryAdvance(final BooleanConsumer action) {
            return this.i.tryAdvance(action);
        }
        
        @Deprecated
        @Override
        public boolean tryAdvance(final Consumer<? super Boolean> action) {
            return this.i.tryAdvance(action);
        }
        
        @Override
        public void forEachRemaining(final BooleanConsumer action) {
            this.i.forEachRemaining(action);
        }
        
        @Deprecated
        @Override
        public void forEachRemaining(final Consumer<? super Boolean> action) {
            this.i.forEachRemaining(action);
        }
        
        @Override
        public long estimateSize() {
            return this.i.estimateSize();
        }
        
        @Override
        public int characteristics() {
            return this.i.characteristics();
        }
        
        @Override
        public BooleanComparator getComparator() {
            return BooleanComparators.asBooleanComparator(this.i.getComparator());
        }
        
        @Override
        public BooleanSpliterator trySplit() {
            final Spliterator<Boolean> innerSplit = this.i.trySplit();
            if (innerSplit == null) {
                return null;
            }
            return new SpliteratorWrapper(innerSplit);
        }
    }
    
    private static class SpliteratorWrapperWithComparator extends SpliteratorWrapper
    {
        final BooleanComparator comparator;
        
        public SpliteratorWrapperWithComparator(final Spliterator<Boolean> i, final BooleanComparator comparator) {
            super(i);
            this.comparator = comparator;
        }
        
        @Override
        public BooleanComparator getComparator() {
            return this.comparator;
        }
        
        @Override
        public BooleanSpliterator trySplit() {
            final Spliterator<Boolean> innerSplit = this.i.trySplit();
            if (innerSplit == null) {
                return null;
            }
            return new SpliteratorWrapperWithComparator(innerSplit, this.comparator);
        }
    }
    
    public abstract static class AbstractIndexBasedSpliterator extends AbstractBooleanSpliterator
    {
        protected int pos;
        
        protected AbstractIndexBasedSpliterator(final int initialPos) {
            this.pos = initialPos;
        }
        
        protected abstract boolean get(final int p0);
        
        protected abstract int getMaxPos();
        
        protected abstract BooleanSpliterator makeForSplit(final int p0, final int p1);
        
        protected int computeSplitPoint() {
            return this.pos + (this.getMaxPos() - this.pos) / 2;
        }
        
        private void splitPointCheck(final int splitPoint, final int observedMax) {
            if (splitPoint < this.pos || splitPoint > observedMax) {
                throw new IndexOutOfBoundsException("splitPoint " + splitPoint + " outside of range of current position " + this.pos + " and range end " + observedMax);
            }
        }
        
        @Override
        public int characteristics() {
            return 16720;
        }
        
        @Override
        public long estimateSize() {
            return this.getMaxPos() - (long)this.pos;
        }
        
        @Override
        public boolean tryAdvance(final BooleanConsumer action) {
            if (this.pos >= this.getMaxPos()) {
                return false;
            }
            action.accept(this.get(this.pos++));
            return true;
        }
        
        @Override
        public void forEachRemaining(final BooleanConsumer action) {
            final int max = this.getMaxPos();
            while (this.pos < max) {
                action.accept(this.get(this.pos));
                ++this.pos;
            }
        }
        
        @Override
        public long skip(long n) {
            if (n < 0L) {
                throw new IllegalArgumentException("Argument must be nonnegative: " + n);
            }
            final int max = this.getMaxPos();
            if (this.pos >= max) {
                return 0L;
            }
            final int remaining = max - this.pos;
            if (n < remaining) {
                this.pos = SafeMath.safeLongToInt(this.pos + n);
                return n;
            }
            n = remaining;
            this.pos = max;
            return n;
        }
        
        @Override
        public BooleanSpliterator trySplit() {
            final int max = this.getMaxPos();
            final int splitPoint = this.computeSplitPoint();
            if (splitPoint == this.pos || splitPoint == max) {
                return null;
            }
            this.splitPointCheck(splitPoint, max);
            final int oldPos = this.pos;
            final BooleanSpliterator maybeSplit = this.makeForSplit(oldPos, splitPoint);
            if (maybeSplit != null) {
                this.pos = splitPoint;
            }
            return maybeSplit;
        }
    }
    
    public abstract static class EarlyBindingSizeIndexBasedSpliterator extends AbstractIndexBasedSpliterator
    {
        protected final int maxPos;
        
        protected EarlyBindingSizeIndexBasedSpliterator(final int initialPos, final int maxPos) {
            super(initialPos);
            this.maxPos = maxPos;
        }
        
        @Override
        protected final int getMaxPos() {
            return this.maxPos;
        }
    }
    
    public abstract static class LateBindingSizeIndexBasedSpliterator extends AbstractIndexBasedSpliterator
    {
        protected int maxPos;
        private boolean maxPosFixed;
        
        protected LateBindingSizeIndexBasedSpliterator(final int initialPos) {
            super(initialPos);
            this.maxPos = -1;
            this.maxPosFixed = false;
        }
        
        protected LateBindingSizeIndexBasedSpliterator(final int initialPos, final int fixedMaxPos) {
            super(initialPos);
            this.maxPos = -1;
            this.maxPos = fixedMaxPos;
            this.maxPosFixed = true;
        }
        
        protected abstract int getMaxPosFromBackingStore();
        
        @Override
        protected final int getMaxPos() {
            return this.maxPosFixed ? this.maxPos : this.getMaxPosFromBackingStore();
        }
        
        @Override
        public BooleanSpliterator trySplit() {
            final BooleanSpliterator maybeSplit = super.trySplit();
            if (!this.maxPosFixed && maybeSplit != null) {
                this.maxPos = this.getMaxPosFromBackingStore();
                this.maxPosFixed = true;
            }
            return maybeSplit;
        }
    }
    
    private static class SpliteratorConcatenator implements BooleanSpliterator
    {
        private static final int EMPTY_CHARACTERISTICS = 16448;
        private static final int CHARACTERISTICS_NOT_SUPPORTED_WHILE_MULTIPLE = 5;
        final BooleanSpliterator[] a;
        int offset;
        int length;
        long remainingEstimatedExceptCurrent;
        int characteristics;
        
        public SpliteratorConcatenator(final BooleanSpliterator[] a, final int offset, final int length) {
            this.remainingEstimatedExceptCurrent = Long.MAX_VALUE;
            this.characteristics = 0;
            this.a = a;
            this.offset = offset;
            this.length = length;
            this.remainingEstimatedExceptCurrent = this.recomputeRemaining();
            this.characteristics = this.computeCharacteristics();
        }
        
        private long recomputeRemaining() {
            int curLength = this.length - 1;
            int curOffset = this.offset + 1;
            long result = 0L;
            while (curLength > 0) {
                final long cur = this.a[curOffset++].estimateSize();
                --curLength;
                if (cur == Long.MAX_VALUE) {
                    return Long.MAX_VALUE;
                }
                result += cur;
                if (result == Long.MAX_VALUE || result < 0L) {
                    return Long.MAX_VALUE;
                }
            }
            return result;
        }
        
        private int computeCharacteristics() {
            if (this.length <= 0) {
                return 16448;
            }
            int current = -1;
            int curLength = this.length;
            int curOffset = this.offset;
            if (curLength > 1) {
                current &= 0xFFFFFFFA;
            }
            while (curLength > 0) {
                current &= this.a[curOffset++].characteristics();
                --curLength;
            }
            return current;
        }
        
        private void advanceNextSpliterator() {
            if (this.length <= 0) {
                throw new AssertionError((Object)"advanceNextSpliterator() called with none remaining");
            }
            ++this.offset;
            --this.length;
            this.remainingEstimatedExceptCurrent = this.recomputeRemaining();
        }
        
        @Override
        public boolean tryAdvance(final BooleanConsumer action) {
            boolean any = false;
            while (this.length > 0) {
                if (((Spliterator.OfPrimitive<T, BooleanConsumer, T_SPLITR>)this.a[this.offset]).tryAdvance(action)) {
                    any = true;
                    break;
                }
                this.advanceNextSpliterator();
            }
            return any;
        }
        
        @Override
        public void forEachRemaining(final BooleanConsumer action) {
            while (this.length > 0) {
                ((Spliterator.OfPrimitive<T, BooleanConsumer, T_SPLITR>)this.a[this.offset]).forEachRemaining(action);
                this.advanceNextSpliterator();
            }
        }
        
        @Deprecated
        @Override
        public void forEachRemaining(final Consumer<? super Boolean> action) {
            while (this.length > 0) {
                this.a[this.offset].forEachRemaining(action);
                this.advanceNextSpliterator();
            }
        }
        
        @Override
        public long estimateSize() {
            if (this.length <= 0) {
                return 0L;
            }
            final long est = this.a[this.offset].estimateSize() + this.remainingEstimatedExceptCurrent;
            if (est < 0L) {
                return Long.MAX_VALUE;
            }
            return est;
        }
        
        @Override
        public int characteristics() {
            return this.characteristics;
        }
        
        @Override
        public BooleanComparator getComparator() {
            if (this.length == 1 && (this.characteristics & 0x4) != 0x0) {
                return this.a[this.offset].getComparator();
            }
            throw new IllegalStateException();
        }
        
        @Override
        public BooleanSpliterator trySplit() {
            switch (this.length) {
                case 0: {
                    return null;
                }
                case 1: {
                    final BooleanSpliterator split = this.a[this.offset].trySplit();
                    this.characteristics = this.a[this.offset].characteristics();
                    return split;
                }
                case 2: {
                    final BooleanSpliterator split = this.a[this.offset++];
                    --this.length;
                    this.characteristics = this.a[this.offset].characteristics();
                    this.remainingEstimatedExceptCurrent = 0L;
                    return split;
                }
                default: {
                    final int mid = this.length >> 1;
                    final int ret_offset = this.offset;
                    final int new_offset = this.offset + mid;
                    final int ret_length = mid;
                    final int new_length = this.length - mid;
                    this.offset = new_offset;
                    this.length = new_length;
                    this.remainingEstimatedExceptCurrent = this.recomputeRemaining();
                    this.characteristics = this.computeCharacteristics();
                    return new SpliteratorConcatenator(this.a, ret_offset, ret_length);
                }
            }
        }
        
        @Override
        public long skip(final long n) {
            long skipped = 0L;
            if (this.length <= 0) {
                return 0L;
            }
            while (skipped < n && this.length >= 0) {
                final long curSkipped = this.a[this.offset].skip(n - skipped);
                skipped += curSkipped;
                if (skipped < n) {
                    this.advanceNextSpliterator();
                }
            }
            return skipped;
        }
    }
    
    private static class SpliteratorFromIterator implements BooleanSpliterator
    {
        private static final int BATCH_INCREMENT_SIZE = 1024;
        private static final int BATCH_MAX_SIZE = 33554432;
        private final BooleanIterator iter;
        final int characteristics;
        private final boolean knownSize;
        private long size;
        private int nextBatchSize;
        private BooleanSpliterator delegate;
        
        SpliteratorFromIterator(final BooleanIterator iter, final int characteristics) {
            this.size = Long.MAX_VALUE;
            this.nextBatchSize = 1024;
            this.delegate = null;
            this.iter = iter;
            this.characteristics = (0x100 | characteristics);
            this.knownSize = false;
        }
        
        SpliteratorFromIterator(final BooleanIterator iter, final long size, final int additionalCharacteristics) {
            this.size = Long.MAX_VALUE;
            this.nextBatchSize = 1024;
            this.delegate = null;
            this.iter = iter;
            this.knownSize = true;
            this.size = size;
            if ((additionalCharacteristics & 0x1000) != 0x0) {
                this.characteristics = (0x100 | additionalCharacteristics);
            }
            else {
                this.characteristics = (0x4140 | additionalCharacteristics);
            }
        }
        
        @Override
        public boolean tryAdvance(final BooleanConsumer action) {
            if (this.delegate != null) {
                final boolean hadRemaining = ((Spliterator.OfPrimitive<T, BooleanConsumer, T_SPLITR>)this.delegate).tryAdvance(action);
                if (!hadRemaining) {
                    this.delegate = null;
                }
                return hadRemaining;
            }
            if (!this.iter.hasNext()) {
                return false;
            }
            --this.size;
            action.accept(this.iter.nextBoolean());
            return true;
        }
        
        @Override
        public void forEachRemaining(final BooleanConsumer action) {
            if (this.delegate != null) {
                ((Spliterator.OfPrimitive<T, BooleanConsumer, T_SPLITR>)this.delegate).forEachRemaining(action);
                this.delegate = null;
            }
            this.iter.forEachRemaining(action);
            this.size = 0L;
        }
        
        @Override
        public long estimateSize() {
            if (this.delegate != null) {
                return this.delegate.estimateSize();
            }
            if (!this.iter.hasNext()) {
                return 0L;
            }
            return (this.knownSize && this.size >= 0L) ? this.size : Long.MAX_VALUE;
        }
        
        @Override
        public int characteristics() {
            return this.characteristics;
        }
        
        protected BooleanSpliterator makeForSplit(final boolean[] batch, final int len) {
            return BooleanSpliterators.wrap(batch, 0, len, this.characteristics);
        }
        
        @Override
        public BooleanSpliterator trySplit() {
            if (!this.iter.hasNext()) {
                return null;
            }
            int batchSizeEst;
            boolean[] batch;
            int actualSeen;
            for (batchSizeEst = ((this.knownSize && this.size > 0L) ? ((int)Math.min(this.nextBatchSize, this.size)) : this.nextBatchSize), batch = new boolean[batchSizeEst], actualSeen = 0; actualSeen < batchSizeEst && this.iter.hasNext(); batch[actualSeen++] = this.iter.nextBoolean(), --this.size) {}
            if (batchSizeEst < this.nextBatchSize && this.iter.hasNext()) {
                for (batch = Arrays.copyOf(batch, this.nextBatchSize); this.iter.hasNext() && actualSeen < this.nextBatchSize; batch[actualSeen++] = this.iter.nextBoolean(), --this.size) {}
            }
            this.nextBatchSize = Math.min(33554432, this.nextBatchSize + 1024);
            final BooleanSpliterator split = this.makeForSplit(batch, actualSeen);
            if (!this.iter.hasNext()) {
                this.delegate = split;
                return split.trySplit();
            }
            return split;
        }
        
        @Override
        public long skip(final long n) {
            if (n < 0L) {
                throw new IllegalArgumentException("Argument must be nonnegative: " + n);
            }
            if (this.iter instanceof BooleanBigListIterator) {
                final long skipped = ((BooleanBigListIterator)this.iter).skip(n);
                this.size -= skipped;
                return skipped;
            }
            long skippedSoFar;
            int skipped2;
            for (skippedSoFar = 0L; skippedSoFar < n && this.iter.hasNext(); skippedSoFar += skipped2) {
                skipped2 = this.iter.skip(SafeMath.safeLongToInt(Math.min(n, 2147483647L)));
                this.size -= skipped2;
            }
            return skippedSoFar;
        }
    }
    
    private static class SpliteratorFromIteratorWithComparator extends SpliteratorFromIterator
    {
        private final BooleanComparator comparator;
        
        SpliteratorFromIteratorWithComparator(final BooleanIterator iter, final int additionalCharacteristics, final BooleanComparator comparator) {
            super(iter, additionalCharacteristics | 0x14);
            this.comparator = comparator;
        }
        
        SpliteratorFromIteratorWithComparator(final BooleanIterator iter, final long size, final int additionalCharacteristics, final BooleanComparator comparator) {
            super(iter, size, additionalCharacteristics | 0x14);
            this.comparator = comparator;
        }
        
        @Override
        public BooleanComparator getComparator() {
            return this.comparator;
        }
        
        @Override
        protected BooleanSpliterator makeForSplit(final boolean[] array, final int len) {
            return BooleanSpliterators.wrapPreSorted(array, 0, len, this.characteristics, this.comparator);
        }
    }
    
    private static final class IteratorFromSpliterator implements BooleanIterator, BooleanConsumer
    {
        private final BooleanSpliterator spliterator;
        private boolean holder;
        private boolean hasPeeked;
        
        IteratorFromSpliterator(final BooleanSpliterator spliterator) {
            this.holder = false;
            this.hasPeeked = false;
            this.spliterator = spliterator;
        }
        
        @Override
        public void accept(final boolean item) {
            this.holder = item;
        }
        
        @Override
        public boolean hasNext() {
            if (this.hasPeeked) {
                return true;
            }
            final boolean hadElement = ((Spliterator.OfPrimitive<T, IteratorFromSpliterator, T_SPLITR>)this.spliterator).tryAdvance(this);
            return hadElement && (this.hasPeeked = true);
        }
        
        @Override
        public boolean nextBoolean() {
            if (this.hasPeeked) {
                this.hasPeeked = false;
                return this.holder;
            }
            final boolean hadElement = ((Spliterator.OfPrimitive<T, IteratorFromSpliterator, T_SPLITR>)this.spliterator).tryAdvance(this);
            if (!hadElement) {
                throw new NoSuchElementException();
            }
            return this.holder;
        }
        
        @Override
        public void forEachRemaining(final BooleanConsumer action) {
            if (this.hasPeeked) {
                this.hasPeeked = false;
                action.accept(this.holder);
            }
            ((Spliterator.OfPrimitive<T, BooleanConsumer, T_SPLITR>)this.spliterator).forEachRemaining(action);
        }
        
        @Override
        public int skip(int n) {
            if (n < 0) {
                throw new IllegalArgumentException("Argument must be nonnegative: " + n);
            }
            int skipped = 0;
            if (this.hasPeeked) {
                this.hasPeeked = false;
                this.spliterator.skip(1L);
                ++skipped;
                --n;
            }
            if (n > 0) {
                skipped += SafeMath.safeLongToInt(this.spliterator.skip(n));
            }
            return skipped;
        }
    }
}
