1ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin/*
2ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
3ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *
5ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * This code is free software; you can redistribute it and/or modify it
6ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * under the terms of the GNU General Public License version 2 only, as
7ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * published by the Free Software Foundation.  Oracle designates this
8ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * particular file as subject to the "Classpath" exception as provided
9ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * by Oracle in the LICENSE file that accompanied this code.
10ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *
11ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * This code is distributed in the hope that it will be useful, but WITHOUT
12ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * version 2 for more details (a copy is included in the LICENSE file that
15ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * accompanied this code).
16ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *
17ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * You should have received a copy of the GNU General Public License version
18ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * 2 along with this work; if not, write to the Free Software Foundation,
19ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *
21ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * or visit www.oracle.com if you need additional information or have any
23ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * questions.
24ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin */
25ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkinpackage java.util.stream;
26ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
27ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkinimport java.util.ArrayDeque;
28ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkinimport java.util.Arrays;
29ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkinimport java.util.Collection;
30ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkinimport java.util.Deque;
31ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkinimport java.util.List;
32ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkinimport java.util.Objects;
33ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkinimport java.util.Spliterator;
34ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkinimport java.util.Spliterators;
35ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkinimport java.util.concurrent.CountedCompleter;
36ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkinimport java.util.function.BinaryOperator;
37ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkinimport java.util.function.Consumer;
38ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkinimport java.util.function.DoubleConsumer;
39ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkinimport java.util.function.IntConsumer;
40ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkinimport java.util.function.IntFunction;
41ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkinimport java.util.function.LongConsumer;
42ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkinimport java.util.function.LongFunction;
43ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
44ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin/**
45ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * Factory methods for constructing implementations of {@link Node} and
46ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * {@link Node.Builder} and their primitive specializations.  Fork/Join tasks
47ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * for collecting output from a {@link PipelineHelper} to a {@link Node} and
48ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * flattening {@link Node}s.
49ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *
50ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * @since 1.8
51ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin */
52ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkinfinal class Nodes {
53ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
54ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    private Nodes() {
55ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        throw new Error("no instances");
56ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
57ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
58ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
59ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * The maximum size of an array that can be allocated.
60ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
61ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    static final long MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
62ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
63ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    // IllegalArgumentException messages
64ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    static final String BAD_SIZE = "Stream size exceeds max array size";
65ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
66ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    @SuppressWarnings("rawtypes")
67ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    private static final Node EMPTY_NODE = new EmptyNode.OfRef();
68ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    private static final Node.OfInt EMPTY_INT_NODE = new EmptyNode.OfInt();
69ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    private static final Node.OfLong EMPTY_LONG_NODE = new EmptyNode.OfLong();
70ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    private static final Node.OfDouble EMPTY_DOUBLE_NODE = new EmptyNode.OfDouble();
71ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
72ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    // General shape-based node creation methods
73ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
74ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
75ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * Produces an empty node whose count is zero, has no children and no content.
76ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
77ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @param <T> the type of elements of the created node
78ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @param shape the shape of the node to be created
79ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @return an empty node.
80ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
81ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    @SuppressWarnings("unchecked")
82ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    static <T> Node<T> emptyNode(StreamShape shape) {
83ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        switch (shape) {
84ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            case REFERENCE:    return (Node<T>) EMPTY_NODE;
85ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            case INT_VALUE:    return (Node<T>) EMPTY_INT_NODE;
86ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            case LONG_VALUE:   return (Node<T>) EMPTY_LONG_NODE;
87ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            case DOUBLE_VALUE: return (Node<T>) EMPTY_DOUBLE_NODE;
88ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            default:
89ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                throw new IllegalStateException("Unknown shape " + shape);
90ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
91ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
92ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
93ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
94ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * Produces a concatenated {@link Node} that has two or more children.
95ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * <p>The count of the concatenated node is equal to the sum of the count
96ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * of each child. Traversal of the concatenated node traverses the content
97ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * of each child in encounter order of the list of children. Splitting a
98ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * spliterator obtained from the concatenated node preserves the encounter
99ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * order of the list of children.
100ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
101ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * <p>The result may be a concatenated node, the input sole node if the size
102ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * of the list is 1, or an empty node.
103ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
104ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @param <T> the type of elements of the concatenated node
105ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @param shape the shape of the concatenated node to be created
106ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @param left the left input node
107ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @param right the right input node
108ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @return a {@code Node} covering the elements of the input nodes
109ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @throws IllegalStateException if all {@link Node} elements of the list
110ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * are an not instance of type supported by this factory.
111ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
112ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    @SuppressWarnings("unchecked")
113ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    static <T> Node<T> conc(StreamShape shape, Node<T> left, Node<T> right) {
114ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        switch (shape) {
115ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            case REFERENCE:
116ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return new ConcNode<>(left, right);
117ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            case INT_VALUE:
118ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return (Node<T>) new ConcNode.OfInt((Node.OfInt) left, (Node.OfInt) right);
119ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            case LONG_VALUE:
120ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return (Node<T>) new ConcNode.OfLong((Node.OfLong) left, (Node.OfLong) right);
121ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            case DOUBLE_VALUE:
122ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return (Node<T>) new ConcNode.OfDouble((Node.OfDouble) left, (Node.OfDouble) right);
123ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            default:
124ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                throw new IllegalStateException("Unknown shape " + shape);
125ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
126ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
127ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
128ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    // Reference-based node methods
129ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
130ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
131ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * Produces a {@link Node} describing an array.
132ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
133ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * <p>The node will hold a reference to the array and will not make a copy.
134ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
135ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @param <T> the type of elements held by the node
136ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @param array the array
137ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @return a node holding an array
138ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
139ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    static <T> Node<T> node(T[] array) {
140ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        return new ArrayNode<>(array);
141ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
142ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
143ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
144ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * Produces a {@link Node} describing a {@link Collection}.
145ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * <p>
146ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * The node will hold a reference to the collection and will not make a copy.
147ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
148ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @param <T> the type of elements held by the node
149ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @param c the collection
150ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @return a node holding a collection
151ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
152ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    static <T> Node<T> node(Collection<T> c) {
153ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        return new CollectionNode<>(c);
154ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
155ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
156ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
157ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * Produces a {@link Node.Builder}.
158ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
159ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @param exactSizeIfKnown -1 if a variable size builder is requested,
160ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * otherwise the exact capacity desired.  A fixed capacity builder will
161ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * fail if the wrong number of elements are added to the builder.
162ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @param generator the array factory
163ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @param <T> the type of elements of the node builder
164ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @return a {@code Node.Builder}
165ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
166ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    static <T> Node.Builder<T> builder(long exactSizeIfKnown, IntFunction<T[]> generator) {
167ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        return (exactSizeIfKnown >= 0 && exactSizeIfKnown < MAX_ARRAY_SIZE)
168ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin               ? new FixedNodeBuilder<>(exactSizeIfKnown, generator)
169ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin               : builder();
170ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
171ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
172ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
173ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * Produces a variable size @{link Node.Builder}.
174ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
175ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @param <T> the type of elements of the node builder
176ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @return a {@code Node.Builder}
177ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
178ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    static <T> Node.Builder<T> builder() {
179ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        return new SpinedNodeBuilder<>();
180ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
181ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
182ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    // Int nodes
183ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
184ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
185ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * Produces a {@link Node.OfInt} describing an int[] array.
186ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
187ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * <p>The node will hold a reference to the array and will not make a copy.
188ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
189ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @param array the array
190ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @return a node holding an array
191ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
192ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    static Node.OfInt node(int[] array) {
193ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        return new IntArrayNode(array);
194ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
195ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
196ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
197ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * Produces a {@link Node.Builder.OfInt}.
198ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
199ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @param exactSizeIfKnown -1 if a variable size builder is requested,
200ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * otherwise the exact capacity desired.  A fixed capacity builder will
201ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * fail if the wrong number of elements are added to the builder.
202ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @return a {@code Node.Builder.OfInt}
203ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
204ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    static Node.Builder.OfInt intBuilder(long exactSizeIfKnown) {
205ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        return (exactSizeIfKnown >= 0 && exactSizeIfKnown < MAX_ARRAY_SIZE)
206ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin               ? new IntFixedNodeBuilder(exactSizeIfKnown)
207ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin               : intBuilder();
208ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
209ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
210ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
211ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * Produces a variable size @{link Node.Builder.OfInt}.
212ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
213ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @return a {@code Node.Builder.OfInt}
214ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
215ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    static Node.Builder.OfInt intBuilder() {
216ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        return new IntSpinedNodeBuilder();
217ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
218ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
219ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    // Long nodes
220ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
221ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
222ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * Produces a {@link Node.OfLong} describing a long[] array.
223ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * <p>
224ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * The node will hold a reference to the array and will not make a copy.
225ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
226ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @param array the array
227ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @return a node holding an array
228ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
229ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    static Node.OfLong node(final long[] array) {
230ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        return new LongArrayNode(array);
231ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
232ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
233ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
234ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * Produces a {@link Node.Builder.OfLong}.
235ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
236ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @param exactSizeIfKnown -1 if a variable size builder is requested,
237ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * otherwise the exact capacity desired.  A fixed capacity builder will
238ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * fail if the wrong number of elements are added to the builder.
239ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @return a {@code Node.Builder.OfLong}
240ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
241ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    static Node.Builder.OfLong longBuilder(long exactSizeIfKnown) {
242ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        return (exactSizeIfKnown >= 0 && exactSizeIfKnown < MAX_ARRAY_SIZE)
243ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin               ? new LongFixedNodeBuilder(exactSizeIfKnown)
244ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin               : longBuilder();
245ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
246ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
247ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
248ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * Produces a variable size @{link Node.Builder.OfLong}.
249ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
250ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @return a {@code Node.Builder.OfLong}
251ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
252ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    static Node.Builder.OfLong longBuilder() {
253ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        return new LongSpinedNodeBuilder();
254ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
255ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
256ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    // Double nodes
257ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
258ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
259ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * Produces a {@link Node.OfDouble} describing a double[] array.
260ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
261ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * <p>The node will hold a reference to the array and will not make a copy.
262ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
263ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @param array the array
264ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @return a node holding an array
265ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
266ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    static Node.OfDouble node(final double[] array) {
267ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        return new DoubleArrayNode(array);
268ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
269ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
270ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
271ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * Produces a {@link Node.Builder.OfDouble}.
272ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
273ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @param exactSizeIfKnown -1 if a variable size builder is requested,
274ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * otherwise the exact capacity desired.  A fixed capacity builder will
275ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * fail if the wrong number of elements are added to the builder.
276ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @return a {@code Node.Builder.OfDouble}
277ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
278ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    static Node.Builder.OfDouble doubleBuilder(long exactSizeIfKnown) {
279ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        return (exactSizeIfKnown >= 0 && exactSizeIfKnown < MAX_ARRAY_SIZE)
280ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin               ? new DoubleFixedNodeBuilder(exactSizeIfKnown)
281ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin               : doubleBuilder();
282ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
283ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
284ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
285ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * Produces a variable size @{link Node.Builder.OfDouble}.
286ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
287ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @return a {@code Node.Builder.OfDouble}
288ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
289ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    static Node.Builder.OfDouble doubleBuilder() {
290ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        return new DoubleSpinedNodeBuilder();
291ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
292ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
293ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    // Parallel evaluation of pipelines to nodes
294ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
295ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
296ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * Collect, in parallel, elements output from a pipeline and describe those
297ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * elements with a {@link Node}.
298ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
299ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @implSpec
300ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * If the exact size of the output from the pipeline is known and the source
301ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * {@link Spliterator} has the {@link Spliterator#SUBSIZED} characteristic,
302ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * then a flat {@link Node} will be returned whose content is an array,
303ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * since the size is known the array can be constructed in advance and
304ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * output elements can be placed into the array concurrently by leaf
305ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * tasks at the correct offsets.  If the exact size is not known, output
306ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * elements are collected into a conc-node whose shape mirrors that
307ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * of the computation. This conc-node can then be flattened in
308ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * parallel to produce a flat {@code Node} if desired.
309ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
310ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @param helper the pipeline helper describing the pipeline
311ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @param flattenTree whether a conc node should be flattened into a node
312ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *                    describing an array before returning
313ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @param generator the array generator
314ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @return a {@link Node} describing the output elements
315ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
316ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    public static <P_IN, P_OUT> Node<P_OUT> collect(PipelineHelper<P_OUT> helper,
317ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                                    Spliterator<P_IN> spliterator,
318ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                                    boolean flattenTree,
319ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                                    IntFunction<P_OUT[]> generator) {
320ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        long size = helper.exactOutputSizeIfKnown(spliterator);
321ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        if (size >= 0 && spliterator.hasCharacteristics(Spliterator.SUBSIZED)) {
322ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (size >= MAX_ARRAY_SIZE)
323ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                throw new IllegalArgumentException(BAD_SIZE);
324ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            P_OUT[] array = generator.apply((int) size);
325ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            new SizedCollectorTask.OfRef<>(spliterator, helper, array).invoke();
326ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return node(array);
327ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        } else {
328ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            Node<P_OUT> node = new CollectorTask.OfRef<>(helper, generator, spliterator).invoke();
329ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return flattenTree ? flatten(node, generator) : node;
330ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
331ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
332ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
333ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
334ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * Collect, in parallel, elements output from an int-valued pipeline and
335ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * describe those elements with a {@link Node.OfInt}.
336ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
337ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @implSpec
338ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * If the exact size of the output from the pipeline is known and the source
339ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * {@link Spliterator} has the {@link Spliterator#SUBSIZED} characteristic,
340ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * then a flat {@link Node} will be returned whose content is an array,
341ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * since the size is known the array can be constructed in advance and
342ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * output elements can be placed into the array concurrently by leaf
343ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * tasks at the correct offsets.  If the exact size is not known, output
344ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * elements are collected into a conc-node whose shape mirrors that
345ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * of the computation. This conc-node can then be flattened in
346ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * parallel to produce a flat {@code Node.OfInt} if desired.
347ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
348ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @param  the type of elements from the source Spliterator
349ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @param helper the pipeline helper describing the pipeline
350ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @param flattenTree whether a conc node should be flattened into a node
351ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *                    describing an array before returning
352ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @return a {@link Node.OfInt} describing the output elements
353ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
354ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    public static <P_IN> Node.OfInt collectInt(PipelineHelper<Integer> helper,
355ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                               Spliterator<P_IN> spliterator,
356ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                               boolean flattenTree) {
357ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        long size = helper.exactOutputSizeIfKnown(spliterator);
358ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        if (size >= 0 && spliterator.hasCharacteristics(Spliterator.SUBSIZED)) {
359ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (size >= MAX_ARRAY_SIZE)
360ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                throw new IllegalArgumentException(BAD_SIZE);
361ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            int[] array = new int[(int) size];
362ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            new SizedCollectorTask.OfInt<>(spliterator, helper, array).invoke();
363ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return node(array);
364ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
365ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        else {
366ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            Node.OfInt node = new CollectorTask.OfInt<>(helper, spliterator).invoke();
367ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return flattenTree ? flattenInt(node) : node;
368ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
369ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
370ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
371ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
372ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * Collect, in parallel, elements output from a long-valued pipeline and
373ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * describe those elements with a {@link Node.OfLong}.
374ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
375ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @implSpec
376ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * If the exact size of the output from the pipeline is known and the source
377ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * {@link Spliterator} has the {@link Spliterator#SUBSIZED} characteristic,
378ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * then a flat {@link Node} will be returned whose content is an array,
379ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * since the size is known the array can be constructed in advance and
380ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * output elements can be placed into the array concurrently by leaf
381ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * tasks at the correct offsets.  If the exact size is not known, output
382ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * elements are collected into a conc-node whose shape mirrors that
383ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * of the computation. This conc-node can then be flattened in
384ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * parallel to produce a flat {@code Node.OfLong} if desired.
385ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
386ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @param  the type of elements from the source Spliterator
387ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @param helper the pipeline helper describing the pipeline
388ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @param flattenTree whether a conc node should be flattened into a node
389ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *                    describing an array before returning
390ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @return a {@link Node.OfLong} describing the output elements
391ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
392ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    public static <P_IN> Node.OfLong collectLong(PipelineHelper<Long> helper,
393ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                                 Spliterator<P_IN> spliterator,
394ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                                 boolean flattenTree) {
395ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        long size = helper.exactOutputSizeIfKnown(spliterator);
396ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        if (size >= 0 && spliterator.hasCharacteristics(Spliterator.SUBSIZED)) {
397ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (size >= MAX_ARRAY_SIZE)
398ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                throw new IllegalArgumentException(BAD_SIZE);
399ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            long[] array = new long[(int) size];
400ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            new SizedCollectorTask.OfLong<>(spliterator, helper, array).invoke();
401ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return node(array);
402ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
403ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        else {
404ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            Node.OfLong node = new CollectorTask.OfLong<>(helper, spliterator).invoke();
405ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return flattenTree ? flattenLong(node) : node;
406ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
407ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
408ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
409ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
410ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * Collect, in parallel, elements output from n double-valued pipeline and
411ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * describe those elements with a {@link Node.OfDouble}.
412ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
413ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @implSpec
414ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * If the exact size of the output from the pipeline is known and the source
415ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * {@link Spliterator} has the {@link Spliterator#SUBSIZED} characteristic,
416ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * then a flat {@link Node} will be returned whose content is an array,
417ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * since the size is known the array can be constructed in advance and
418ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * output elements can be placed into the array concurrently by leaf
419ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * tasks at the correct offsets.  If the exact size is not known, output
420ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * elements are collected into a conc-node whose shape mirrors that
421ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * of the computation. This conc-node can then be flattened in
422ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * parallel to produce a flat {@code Node.OfDouble} if desired.
423ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
424ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @param  the type of elements from the source Spliterator
425ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @param helper the pipeline helper describing the pipeline
426ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @param flattenTree whether a conc node should be flattened into a node
427ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *                    describing an array before returning
428ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @return a {@link Node.OfDouble} describing the output elements
429ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
430ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    public static <P_IN> Node.OfDouble collectDouble(PipelineHelper<Double> helper,
431ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                                     Spliterator<P_IN> spliterator,
432ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                                     boolean flattenTree) {
433ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        long size = helper.exactOutputSizeIfKnown(spliterator);
434ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        if (size >= 0 && spliterator.hasCharacteristics(Spliterator.SUBSIZED)) {
435ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (size >= MAX_ARRAY_SIZE)
436ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                throw new IllegalArgumentException(BAD_SIZE);
437ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            double[] array = new double[(int) size];
438ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            new SizedCollectorTask.OfDouble<>(spliterator, helper, array).invoke();
439ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return node(array);
440ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
441ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        else {
442ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            Node.OfDouble node = new CollectorTask.OfDouble<>(helper, spliterator).invoke();
443ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return flattenTree ? flattenDouble(node) : node;
444ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
445ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
446ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
447ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    // Parallel flattening of nodes
448ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
449ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
450ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * Flatten, in parallel, a {@link Node}.  A flattened node is one that has
451ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * no children.  If the node is already flat, it is simply returned.
452ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
453ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @implSpec
454ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * If a new node is to be created, the generator is used to create an array
455ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * whose length is {@link Node#count()}.  Then the node tree is traversed
456ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * and leaf node elements are placed in the array concurrently by leaf tasks
457ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * at the correct offsets.
458ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
459ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @param <T> type of elements contained by the node
460ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @param node the node to flatten
461ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @param generator the array factory used to create array instances
462ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @return a flat {@code Node}
463ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
464ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    public static <T> Node<T> flatten(Node<T> node, IntFunction<T[]> generator) {
465ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        if (node.getChildCount() > 0) {
466ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            long size = node.count();
467ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (size >= MAX_ARRAY_SIZE)
468ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                throw new IllegalArgumentException(BAD_SIZE);
469ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            T[] array = generator.apply((int) size);
470ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            new ToArrayTask.OfRef<>(node, array, 0).invoke();
471ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return node(array);
472ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        } else {
473ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return node;
474ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
475ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
476ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
477ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
478ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * Flatten, in parallel, a {@link Node.OfInt}.  A flattened node is one that
479ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * has no children.  If the node is already flat, it is simply returned.
480ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
481ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @implSpec
482ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * If a new node is to be created, a new int[] array is created whose length
483ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * is {@link Node#count()}.  Then the node tree is traversed and leaf node
484ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * elements are placed in the array concurrently by leaf tasks at the
485ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * correct offsets.
486ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
487ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @param node the node to flatten
488ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @return a flat {@code Node.OfInt}
489ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
490ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    public static Node.OfInt flattenInt(Node.OfInt node) {
491ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        if (node.getChildCount() > 0) {
492ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            long size = node.count();
493ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (size >= MAX_ARRAY_SIZE)
494ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                throw new IllegalArgumentException(BAD_SIZE);
495ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            int[] array = new int[(int) size];
496ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            new ToArrayTask.OfInt(node, array, 0).invoke();
497ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return node(array);
498ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        } else {
499ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return node;
500ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
501ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
502ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
503ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
504ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * Flatten, in parallel, a {@link Node.OfLong}.  A flattened node is one that
505ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * has no children.  If the node is already flat, it is simply returned.
506ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
507ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @implSpec
508ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * If a new node is to be created, a new long[] array is created whose length
509ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * is {@link Node#count()}.  Then the node tree is traversed and leaf node
510ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * elements are placed in the array concurrently by leaf tasks at the
511ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * correct offsets.
512ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
513ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @param node the node to flatten
514ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @return a flat {@code Node.OfLong}
515ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
516ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    public static Node.OfLong flattenLong(Node.OfLong node) {
517ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        if (node.getChildCount() > 0) {
518ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            long size = node.count();
519ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (size >= MAX_ARRAY_SIZE)
520ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                throw new IllegalArgumentException(BAD_SIZE);
521ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            long[] array = new long[(int) size];
522ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            new ToArrayTask.OfLong(node, array, 0).invoke();
523ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return node(array);
524ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        } else {
525ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return node;
526ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
527ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
528ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
529ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
530ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * Flatten, in parallel, a {@link Node.OfDouble}.  A flattened node is one that
531ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * has no children.  If the node is already flat, it is simply returned.
532ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
533ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @implSpec
534ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * If a new node is to be created, a new double[] array is created whose length
535ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * is {@link Node#count()}.  Then the node tree is traversed and leaf node
536ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * elements are placed in the array concurrently by leaf tasks at the
537ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * correct offsets.
538ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
539ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @param node the node to flatten
540ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @return a flat {@code Node.OfDouble}
541ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
542ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    public static Node.OfDouble flattenDouble(Node.OfDouble node) {
543ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        if (node.getChildCount() > 0) {
544ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            long size = node.count();
545ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (size >= MAX_ARRAY_SIZE)
546ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                throw new IllegalArgumentException(BAD_SIZE);
547ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            double[] array = new double[(int) size];
548ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            new ToArrayTask.OfDouble(node, array, 0).invoke();
549ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return node(array);
550ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        } else {
551ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return node;
552ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
553ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
554ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
555ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    // Implementations
556ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
557ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    private static abstract class EmptyNode<T, T_ARR, T_CONS> implements Node<T> {
558ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        EmptyNode() { }
559ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
560ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
561ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public T[] asArray(IntFunction<T[]> generator) {
562ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return generator.apply(0);
563ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
564ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
565ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public void copyInto(T_ARR array, int offset) { }
566ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
567ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
568ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public long count() {
569ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return 0;
570ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
571ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
572ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public void forEach(T_CONS consumer) { }
573ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
574ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        private static class OfRef<T> extends EmptyNode<T, T[], Consumer<? super T>> {
575ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            private OfRef() {
576ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                super();
577ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
578ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
579ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
580ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            public Spliterator<T> spliterator() {
581ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return Spliterators.emptySpliterator();
582ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
583ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
584ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
585ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        private static final class OfInt
586ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                extends EmptyNode<Integer, int[], IntConsumer>
587ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                implements Node.OfInt {
588ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
589ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            OfInt() { } // Avoid creation of special accessor
590ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
591ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
592ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            public Spliterator.OfInt spliterator() {
593ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return Spliterators.emptyIntSpliterator();
594ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
595ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
596ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
597ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            public int[] asPrimitiveArray() {
598ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return EMPTY_INT_ARRAY;
599ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
600ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
601ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
602ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        private static final class OfLong
603ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                extends EmptyNode<Long, long[], LongConsumer>
604ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                implements Node.OfLong {
605ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
606ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            OfLong() { } // Avoid creation of special accessor
607ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
608ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
609ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            public Spliterator.OfLong spliterator() {
610ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return Spliterators.emptyLongSpliterator();
611ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
612ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
613ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
614ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            public long[] asPrimitiveArray() {
615ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return EMPTY_LONG_ARRAY;
616ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
617ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
618ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
619ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        private static final class OfDouble
620ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                extends EmptyNode<Double, double[], DoubleConsumer>
621ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                implements Node.OfDouble {
622ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
623ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            OfDouble() { } // Avoid creation of special accessor
624ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
625ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
626ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            public Spliterator.OfDouble spliterator() {
627ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return Spliterators.emptyDoubleSpliterator();
628ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
629ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
630ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
631ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            public double[] asPrimitiveArray() {
632ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return EMPTY_DOUBLE_ARRAY;
633ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
634ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
635ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
636ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
637ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /** Node class for a reference array */
638ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    private static class ArrayNode<T> implements Node<T> {
639ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        final T[] array;
640ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        int curSize;
641ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
642ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @SuppressWarnings("unchecked")
643ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        ArrayNode(long size, IntFunction<T[]> generator) {
644ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (size >= MAX_ARRAY_SIZE)
645ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                throw new IllegalArgumentException(BAD_SIZE);
646ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.array = generator.apply((int) size);
647ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.curSize = 0;
648ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
649ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
650ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        ArrayNode(T[] array) {
651ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.array = array;
652ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.curSize = array.length;
653ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
654ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
655ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        // Node
656ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
657ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
658ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public Spliterator<T> spliterator() {
659ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return Arrays.spliterator(array, 0, curSize);
660ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
661ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
662ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
663ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public void copyInto(T[] dest, int destOffset) {
664ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            System.arraycopy(array, 0, dest, destOffset, curSize);
665ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
666ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
667ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
668ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public T[] asArray(IntFunction<T[]> generator) {
669ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (array.length == curSize) {
670ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return array;
671ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            } else {
672ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                throw new IllegalStateException();
673ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
674ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
675ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
676ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
677ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public long count() {
678ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return curSize;
679ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
680ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
681ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
682ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public void forEach(Consumer<? super T> consumer) {
683ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            for (int i = 0; i < curSize; i++) {
684ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                consumer.accept(array[i]);
685ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
686ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
687ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
688ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        //
689ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
690ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
691ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public String toString() {
692ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return String.format("ArrayNode[%d][%s]",
693ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                 array.length - curSize, Arrays.toString(array));
694ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
695ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
696ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
697ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /** Node class for a Collection */
698ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    private static final class CollectionNode<T> implements Node<T> {
699ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        private final Collection<T> c;
700ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
701ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        CollectionNode(Collection<T> c) {
702ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.c = c;
703ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
704ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
705ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        // Node
706ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
707ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
708ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public Spliterator<T> spliterator() {
709ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return c.stream().spliterator();
710ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
711ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
712ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
713ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public void copyInto(T[] array, int offset) {
714ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            for (T t : c)
715ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                array[offset++] = t;
716ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
717ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
718ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
719ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @SuppressWarnings("unchecked")
720ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public T[] asArray(IntFunction<T[]> generator) {
721ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return c.toArray(generator.apply(c.size()));
722ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
723ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
724ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
725ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public long count() {
726ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return c.size();
727ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
728ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
729ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
730ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public void forEach(Consumer<? super T> consumer) {
731ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            c.forEach(consumer);
732ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
733ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
734ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        //
735ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
736ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
737ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public String toString() {
738ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return String.format("CollectionNode[%d][%s]", c.size(), c);
739ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
740ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
741ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
742ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
743ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * Node class for an internal node with two or more children
744ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
745ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    private static abstract class AbstractConcNode<T, T_NODE extends Node<T>> implements Node<T> {
746ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        protected final T_NODE left;
747ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        protected final T_NODE right;
748ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        private final long size;
749ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
750ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        AbstractConcNode(T_NODE left, T_NODE right) {
751ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.left = left;
752ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.right = right;
753ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            // The Node count will be required when the Node spliterator is
754ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            // obtained and it is cheaper to aggressively calculate bottom up
755ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            // as the tree is built rather than later on from the top down
756ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            // traversing the tree
757ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.size = left.count() + right.count();
758ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
759ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
760ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
761ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public int getChildCount() {
762ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return 2;
763ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
764ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
765ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
766ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public T_NODE getChild(int i) {
767ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (i == 0) return left;
768ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (i == 1) return right;
769ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            throw new IndexOutOfBoundsException();
770ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
771ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
772ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
773ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public long count() {
774ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return size;
775ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
776ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
777ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
778ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    static final class ConcNode<T>
779ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            extends AbstractConcNode<T, Node<T>>
780ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            implements Node<T> {
781ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
782ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        ConcNode(Node<T> left, Node<T> right) {
783ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            super(left, right);
784ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
785ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
786ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
787ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public Spliterator<T> spliterator() {
788ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return new Nodes.InternalNodeSpliterator.OfRef<>(this);
789ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
790ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
791ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
792ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public void copyInto(T[] array, int offset) {
793ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            Objects.requireNonNull(array);
794ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            left.copyInto(array, offset);
795ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            // Cast to int is safe since it is the callers responsibility to
796ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            // ensure that there is sufficient room in the array
797ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            right.copyInto(array, offset + (int) left.count());
798ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
799ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
800ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
801ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public T[] asArray(IntFunction<T[]> generator) {
802ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            long size = count();
803ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (size >= MAX_ARRAY_SIZE)
804ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                throw new IllegalArgumentException(BAD_SIZE);
805ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            T[] array = generator.apply((int) size);
806ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            copyInto(array, 0);
807ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return array;
808ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
809ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
810ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
811ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public void forEach(Consumer<? super T> consumer) {
812ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            left.forEach(consumer);
813ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            right.forEach(consumer);
814ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
815ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
816ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
817ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public Node<T> truncate(long from, long to, IntFunction<T[]> generator) {
818ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (from == 0 && to == count())
819ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return this;
820ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            long leftCount = left.count();
821ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (from >= leftCount)
822ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return right.truncate(from - leftCount, to - leftCount, generator);
823ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            else if (to <= leftCount)
824ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return left.truncate(from, to, generator);
825ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            else {
826ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return Nodes.conc(getShape(), left.truncate(from, leftCount, generator),
827ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                  right.truncate(0, to - leftCount, generator));
828ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
829ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
830ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
831ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
832ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public String toString() {
833ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (count() < 32) {
834ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return String.format("ConcNode[%s.%s]", left, right);
835ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            } else {
836ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return String.format("ConcNode[size=%d]", count());
837ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
838ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
839ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
840ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        private abstract static class OfPrimitive<E, T_CONS, T_ARR,
841ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                                  T_SPLITR extends Spliterator.OfPrimitive<E, T_CONS, T_SPLITR>,
842ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                                  T_NODE extends Node.OfPrimitive<E, T_CONS, T_ARR, T_SPLITR, T_NODE>>
843ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                extends AbstractConcNode<E, T_NODE>
844ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                implements Node.OfPrimitive<E, T_CONS, T_ARR, T_SPLITR, T_NODE> {
845ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
846ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            OfPrimitive(T_NODE left, T_NODE right) {
847ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                super(left, right);
848ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
849ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
850ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
851ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            public void forEach(T_CONS consumer) {
852ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                left.forEach(consumer);
853ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                right.forEach(consumer);
854ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
855ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
856ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
857ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            public void copyInto(T_ARR array, int offset) {
858ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                left.copyInto(array, offset);
859ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                // Cast to int is safe since it is the callers responsibility to
860ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                // ensure that there is sufficient room in the array
861ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                right.copyInto(array, offset + (int) left.count());
862ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
863ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
864ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
865ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            public T_ARR asPrimitiveArray() {
866ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                long size = count();
867ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                if (size >= MAX_ARRAY_SIZE)
868ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    throw new IllegalArgumentException(BAD_SIZE);
869ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                T_ARR array = newArray((int) size);
870ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                copyInto(array, 0);
871ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return array;
872ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
873ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
874ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
875ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            public String toString() {
876ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                if (count() < 32)
877ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    return String.format("%s[%s.%s]", this.getClass().getName(), left, right);
878ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                else
879ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    return String.format("%s[size=%d]", this.getClass().getName(), count());
880ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
881ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
882ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
883ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        static final class OfInt
884ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                extends ConcNode.OfPrimitive<Integer, IntConsumer, int[], Spliterator.OfInt, Node.OfInt>
885ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                implements Node.OfInt {
886ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
887ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            OfInt(Node.OfInt left, Node.OfInt right) {
888ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                super(left, right);
889ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
890ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
891ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
892ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            public Spliterator.OfInt spliterator() {
893ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return new InternalNodeSpliterator.OfInt(this);
894ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
895ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
896ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
897ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        static final class OfLong
898ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                extends ConcNode.OfPrimitive<Long, LongConsumer, long[], Spliterator.OfLong, Node.OfLong>
899ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                implements Node.OfLong {
900ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
901ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            OfLong(Node.OfLong left, Node.OfLong right) {
902ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                super(left, right);
903ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
904ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
905ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
906ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            public Spliterator.OfLong spliterator() {
907ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return new InternalNodeSpliterator.OfLong(this);
908ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
909ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
910ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
911ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        static final class OfDouble
912ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                extends ConcNode.OfPrimitive<Double, DoubleConsumer, double[], Spliterator.OfDouble, Node.OfDouble>
913ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                implements Node.OfDouble {
914ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
915ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            OfDouble(Node.OfDouble left, Node.OfDouble right) {
916ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                super(left, right);
917ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
918ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
919ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
920ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            public Spliterator.OfDouble spliterator() {
921ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return new InternalNodeSpliterator.OfDouble(this);
922ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
923ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
924ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
925ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
926ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /** Abstract class for spliterator for all internal node classes */
927ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    private static abstract class InternalNodeSpliterator<T,
928ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                                          S extends Spliterator<T>,
929ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                                          N extends Node<T>>
930ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            implements Spliterator<T> {
931ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        // Node we are pointing to
932ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        // null if full traversal has occurred
933ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        N curNode;
934ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
935ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        // next child of curNode to consume
936ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        int curChildIndex;
937ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
938ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        // The spliterator of the curNode if that node is last and has no children.
939ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        // This spliterator will be delegated to for splitting and traversing.
940ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        // null if curNode has children
941ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        S lastNodeSpliterator;
942ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
943ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        // spliterator used while traversing with tryAdvance
944ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        // null if no partial traversal has occurred
945ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        S tryAdvanceSpliterator;
946ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
947ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        // node stack used when traversing to search and find leaf nodes
948ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        // null if no partial traversal has occurred
949ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        Deque<N> tryAdvanceStack;
950ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
951ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        InternalNodeSpliterator(N curNode) {
952ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.curNode = curNode;
953ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
954ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
955ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        /**
956ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         * Initiate a stack containing, in left-to-right order, the child nodes
957ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         * covered by this spliterator
958ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         */
959ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @SuppressWarnings("unchecked")
960ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        protected final Deque<N> initStack() {
961ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            // Bias size to the case where leaf nodes are close to this node
962ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            // 8 is the minimum initial capacity for the ArrayDeque implementation
963ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            Deque<N> stack = new ArrayDeque<>(8);
964ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            for (int i = curNode.getChildCount() - 1; i >= curChildIndex; i--)
965ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                stack.addFirst((N) curNode.getChild(i));
966ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return stack;
967ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
968ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
969ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        /**
970ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         * Depth first search, in left-to-right order, of the node tree, using
971ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         * an explicit stack, to find the next non-empty leaf node.
972ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         */
973ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @SuppressWarnings("unchecked")
974ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        protected final N findNextLeafNode(Deque<N> stack) {
975ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            N n = null;
976ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            while ((n = stack.pollFirst()) != null) {
977ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                if (n.getChildCount() == 0) {
978ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    if (n.count() > 0)
979ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        return n;
980ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                } else {
981ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    for (int i = n.getChildCount() - 1; i >= 0; i--)
982ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        stack.addFirst((N) n.getChild(i));
983ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                }
984ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
985ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
986ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return null;
987ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
988ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
989ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @SuppressWarnings("unchecked")
990ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        protected final boolean initTryAdvance() {
991ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (curNode == null)
992ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return false;
993ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
994ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (tryAdvanceSpliterator == null) {
995ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                if (lastNodeSpliterator == null) {
996ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    // Initiate the node stack
997ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    tryAdvanceStack = initStack();
998ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    N leaf = findNextLeafNode(tryAdvanceStack);
999ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    if (leaf != null)
1000ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        tryAdvanceSpliterator = (S) leaf.spliterator();
1001ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    else {
1002ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        // A non-empty leaf node was not found
1003ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        // No elements to traverse
1004ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        curNode = null;
1005ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        return false;
1006ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    }
1007ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                }
1008ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                else
1009ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    tryAdvanceSpliterator = lastNodeSpliterator;
1010ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1011ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return true;
1012ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1013ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1014ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1015ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @SuppressWarnings("unchecked")
1016ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public final S trySplit() {
1017ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (curNode == null || tryAdvanceSpliterator != null)
1018ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return null; // Cannot split if fully or partially traversed
1019ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            else if (lastNodeSpliterator != null)
1020ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return (S) lastNodeSpliterator.trySplit();
1021ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            else if (curChildIndex < curNode.getChildCount() - 1)
1022ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return (S) curNode.getChild(curChildIndex++).spliterator();
1023ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            else {
1024ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                curNode = (N) curNode.getChild(curChildIndex);
1025ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                if (curNode.getChildCount() == 0) {
1026ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    lastNodeSpliterator = (S) curNode.spliterator();
1027ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    return (S) lastNodeSpliterator.trySplit();
1028ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                }
1029ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                else {
1030ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    curChildIndex = 0;
1031ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    return (S) curNode.getChild(curChildIndex++).spliterator();
1032ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                }
1033ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1034ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1035ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1036ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1037ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public final long estimateSize() {
1038ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (curNode == null)
1039ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return 0;
1040ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1041ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            // Will not reflect the effects of partial traversal.
1042ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            // This is compliant with the specification
1043ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (lastNodeSpliterator != null)
1044ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return lastNodeSpliterator.estimateSize();
1045ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            else {
1046ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                long size = 0;
1047ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                for (int i = curChildIndex; i < curNode.getChildCount(); i++)
1048ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    size += curNode.getChild(i).count();
1049ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return size;
1050ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1051ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1052ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1053ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1054ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public final int characteristics() {
1055ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return Spliterator.SIZED;
1056ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1057ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1058ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        private static final class OfRef<T>
1059ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                extends InternalNodeSpliterator<T, Spliterator<T>, Node<T>> {
1060ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1061ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            OfRef(Node<T> curNode) {
1062ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                super(curNode);
1063ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1064ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1065ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
1066ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            public boolean tryAdvance(Consumer<? super T> consumer) {
1067ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                if (!initTryAdvance())
1068ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    return false;
1069ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1070ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                boolean hasNext = tryAdvanceSpliterator.tryAdvance(consumer);
1071ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                if (!hasNext) {
1072ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    if (lastNodeSpliterator == null) {
1073ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        // Advance to the spliterator of the next non-empty leaf node
1074ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        Node<T> leaf = findNextLeafNode(tryAdvanceStack);
1075ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        if (leaf != null) {
1076ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                            tryAdvanceSpliterator = leaf.spliterator();
1077ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                            // Since the node is not-empty the spliterator can be advanced
1078ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                            return tryAdvanceSpliterator.tryAdvance(consumer);
1079ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        }
1080ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    }
1081ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    // No more elements to traverse
1082ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    curNode = null;
1083ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                }
1084ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return hasNext;
1085ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1086ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1087ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
1088ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            public void forEachRemaining(Consumer<? super T> consumer) {
1089ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                if (curNode == null)
1090ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    return;
1091ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1092ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                if (tryAdvanceSpliterator == null) {
1093ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    if (lastNodeSpliterator == null) {
1094ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        Deque<Node<T>> stack = initStack();
1095ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        Node<T> leaf;
1096ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        while ((leaf = findNextLeafNode(stack)) != null) {
1097ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                            leaf.forEach(consumer);
1098ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        }
1099ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        curNode = null;
1100ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    }
1101ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    else
1102ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        lastNodeSpliterator.forEachRemaining(consumer);
1103ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                }
1104ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                else
1105ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    while(tryAdvance(consumer)) { }
1106ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1107ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1108ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1109ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        private static abstract class OfPrimitive<T, T_CONS, T_ARR,
1110ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                                  T_SPLITR extends Spliterator.OfPrimitive<T, T_CONS, T_SPLITR>,
1111ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                                  N extends Node.OfPrimitive<T, T_CONS, T_ARR, T_SPLITR, N>>
1112ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                extends InternalNodeSpliterator<T, T_SPLITR, N>
1113ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                implements Spliterator.OfPrimitive<T, T_CONS, T_SPLITR> {
1114ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1115ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            OfPrimitive(N cur) {
1116ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                super(cur);
1117ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1118ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1119ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
1120ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            public boolean tryAdvance(T_CONS consumer) {
1121ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                if (!initTryAdvance())
1122ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    return false;
1123ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1124ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                boolean hasNext = tryAdvanceSpliterator.tryAdvance(consumer);
1125ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                if (!hasNext) {
1126ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    if (lastNodeSpliterator == null) {
1127ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        // Advance to the spliterator of the next non-empty leaf node
1128ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        N leaf = findNextLeafNode(tryAdvanceStack);
1129ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        if (leaf != null) {
1130ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                            tryAdvanceSpliterator = leaf.spliterator();
1131ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                            // Since the node is not-empty the spliterator can be advanced
1132ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                            return tryAdvanceSpliterator.tryAdvance(consumer);
1133ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        }
1134ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    }
1135ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    // No more elements to traverse
1136ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    curNode = null;
1137ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                }
1138ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return hasNext;
1139ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1140ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1141ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
1142ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            public void forEachRemaining(T_CONS consumer) {
1143ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                if (curNode == null)
1144ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    return;
1145ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1146ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                if (tryAdvanceSpliterator == null) {
1147ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    if (lastNodeSpliterator == null) {
1148ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        Deque<N> stack = initStack();
1149ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        N leaf;
1150ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        while ((leaf = findNextLeafNode(stack)) != null) {
1151ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                            leaf.forEach(consumer);
1152ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        }
1153ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        curNode = null;
1154ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    }
1155ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    else
1156ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        lastNodeSpliterator.forEachRemaining(consumer);
1157ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                }
1158ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                else
1159ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    while(tryAdvance(consumer)) { }
1160ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1161ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1162ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1163ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        private static final class OfInt
1164ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                extends OfPrimitive<Integer, IntConsumer, int[], Spliterator.OfInt, Node.OfInt>
1165ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                implements Spliterator.OfInt {
1166ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1167ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            OfInt(Node.OfInt cur) {
1168ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                super(cur);
1169ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1170ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1171ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1172ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        private static final class OfLong
1173ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                extends OfPrimitive<Long, LongConsumer, long[], Spliterator.OfLong, Node.OfLong>
1174ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                implements Spliterator.OfLong {
1175ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1176ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            OfLong(Node.OfLong cur) {
1177ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                super(cur);
1178ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1179ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1180ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1181ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        private static final class OfDouble
1182ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                extends OfPrimitive<Double, DoubleConsumer, double[], Spliterator.OfDouble, Node.OfDouble>
1183ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                implements Spliterator.OfDouble {
1184ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1185ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            OfDouble(Node.OfDouble cur) {
1186ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                super(cur);
1187ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1188ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1189ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
1190ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1191ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
1192ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * Fixed-sized builder class for reference nodes
1193ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
1194ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    private static final class FixedNodeBuilder<T>
1195ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            extends ArrayNode<T>
1196ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            implements Node.Builder<T> {
1197ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1198ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        FixedNodeBuilder(long size, IntFunction<T[]> generator) {
1199ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            super(size, generator);
1200ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            assert size < MAX_ARRAY_SIZE;
1201ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1202ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1203ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1204ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public Node<T> build() {
1205ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (curSize < array.length)
1206ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                throw new IllegalStateException(String.format("Current size %d is less than fixed size %d",
1207ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                                              curSize, array.length));
1208ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return this;
1209ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1210ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1211ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1212ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public void begin(long size) {
1213ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (size != array.length)
1214ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                throw new IllegalStateException(String.format("Begin size %d is not equal to fixed size %d",
1215ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                                              size, array.length));
1216ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            curSize = 0;
1217ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1218ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1219ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1220ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public void accept(T t) {
1221ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (curSize < array.length) {
1222ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                array[curSize++] = t;
1223ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            } else {
1224ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                throw new IllegalStateException(String.format("Accept exceeded fixed size of %d",
1225ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                                              array.length));
1226ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1227ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1228ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1229ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1230ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public void end() {
1231ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (curSize < array.length)
1232ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                throw new IllegalStateException(String.format("End size %d is less than fixed size %d",
1233ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                                              curSize, array.length));
1234ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1235ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1236ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1237ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public String toString() {
1238ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return String.format("FixedNodeBuilder[%d][%s]",
1239ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                 array.length - curSize, Arrays.toString(array));
1240ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1241ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
1242ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1243ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
1244ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * Variable-sized builder class for reference nodes
1245ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
1246ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    private static final class SpinedNodeBuilder<T>
1247ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            extends SpinedBuffer<T>
1248ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            implements Node<T>, Node.Builder<T> {
1249ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        private boolean building = false;
1250ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1251ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        SpinedNodeBuilder() {} // Avoid creation of special accessor
1252ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1253ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1254ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public Spliterator<T> spliterator() {
1255ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            assert !building : "during building";
1256ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return super.spliterator();
1257ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1258ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1259ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1260ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public void forEach(Consumer<? super T> consumer) {
1261ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            assert !building : "during building";
1262ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            super.forEach(consumer);
1263ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1264ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1265ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        //
1266ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1267ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public void begin(long size) {
1268ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            assert !building : "was already building";
1269ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            building = true;
1270ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            clear();
1271ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            ensureCapacity(size);
1272ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1273ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1274ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1275ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public void accept(T t) {
1276ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            assert building : "not building";
1277ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            super.accept(t);
1278ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1279ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1280ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1281ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public void end() {
1282ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            assert building : "was not building";
1283ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            building = false;
1284ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            // @@@ check begin(size) and size
1285ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1286ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1287ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1288ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public void copyInto(T[] array, int offset) {
1289ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            assert !building : "during building";
1290ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            super.copyInto(array, offset);
1291ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1292ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1293ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1294ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public T[] asArray(IntFunction<T[]> arrayFactory) {
1295ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            assert !building : "during building";
1296ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return super.asArray(arrayFactory);
1297ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1298ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1299ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1300ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public Node<T> build() {
1301ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            assert !building : "during building";
1302ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return this;
1303ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1304ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
1305ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1306ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    //
1307ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1308ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    private static final int[] EMPTY_INT_ARRAY = new int[0];
1309ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    private static final long[] EMPTY_LONG_ARRAY = new long[0];
1310ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    private static final double[] EMPTY_DOUBLE_ARRAY = new double[0];
1311ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1312ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    private static class IntArrayNode implements Node.OfInt {
1313ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        final int[] array;
1314ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        int curSize;
1315ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1316ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        IntArrayNode(long size) {
1317ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (size >= MAX_ARRAY_SIZE)
1318ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                throw new IllegalArgumentException(BAD_SIZE);
1319ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.array = new int[(int) size];
1320ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.curSize = 0;
1321ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1322ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1323ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        IntArrayNode(int[] array) {
1324ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.array = array;
1325ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.curSize = array.length;
1326ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1327ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1328ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        // Node
1329ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1330ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1331ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public Spliterator.OfInt spliterator() {
1332ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return Arrays.spliterator(array, 0, curSize);
1333ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1334ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1335ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1336ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public int[] asPrimitiveArray() {
1337ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (array.length == curSize) {
1338ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return array;
1339ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            } else {
1340ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return Arrays.copyOf(array, curSize);
1341ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1342ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1343ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1344ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1345ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public void copyInto(int[] dest, int destOffset) {
1346ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            System.arraycopy(array, 0, dest, destOffset, curSize);
1347ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1348ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1349ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1350ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public long count() {
1351ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return curSize;
1352ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1353ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1354ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1355ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public void forEach(IntConsumer consumer) {
1356ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            for (int i = 0; i < curSize; i++) {
1357ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                consumer.accept(array[i]);
1358ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1359ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1360ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1361ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1362ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public String toString() {
1363ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return String.format("IntArrayNode[%d][%s]",
1364ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                 array.length - curSize, Arrays.toString(array));
1365ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1366ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
1367ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1368ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    private static class LongArrayNode implements Node.OfLong {
1369ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        final long[] array;
1370ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        int curSize;
1371ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1372ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        LongArrayNode(long size) {
1373ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (size >= MAX_ARRAY_SIZE)
1374ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                throw new IllegalArgumentException(BAD_SIZE);
1375ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.array = new long[(int) size];
1376ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.curSize = 0;
1377ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1378ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1379ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        LongArrayNode(long[] array) {
1380ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.array = array;
1381ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.curSize = array.length;
1382ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1383ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1384ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1385ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public Spliterator.OfLong spliterator() {
1386ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return Arrays.spliterator(array, 0, curSize);
1387ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1388ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1389ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1390ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public long[] asPrimitiveArray() {
1391ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (array.length == curSize) {
1392ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return array;
1393ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            } else {
1394ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return Arrays.copyOf(array, curSize);
1395ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1396ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1397ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1398ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1399ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public void copyInto(long[] dest, int destOffset) {
1400ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            System.arraycopy(array, 0, dest, destOffset, curSize);
1401ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1402ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1403ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1404ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public long count() {
1405ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return curSize;
1406ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1407ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1408ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1409ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public void forEach(LongConsumer consumer) {
1410ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            for (int i = 0; i < curSize; i++) {
1411ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                consumer.accept(array[i]);
1412ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1413ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1414ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1415ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1416ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public String toString() {
1417ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return String.format("LongArrayNode[%d][%s]",
1418ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                 array.length - curSize, Arrays.toString(array));
1419ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1420ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
1421ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1422ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    private static class DoubleArrayNode implements Node.OfDouble {
1423ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        final double[] array;
1424ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        int curSize;
1425ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1426ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        DoubleArrayNode(long size) {
1427ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (size >= MAX_ARRAY_SIZE)
1428ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                throw new IllegalArgumentException(BAD_SIZE);
1429ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.array = new double[(int) size];
1430ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.curSize = 0;
1431ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1432ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1433ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        DoubleArrayNode(double[] array) {
1434ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.array = array;
1435ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.curSize = array.length;
1436ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1437ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1438ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1439ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public Spliterator.OfDouble spliterator() {
1440ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return Arrays.spliterator(array, 0, curSize);
1441ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1442ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1443ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1444ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public double[] asPrimitiveArray() {
1445ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (array.length == curSize) {
1446ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return array;
1447ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            } else {
1448ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return Arrays.copyOf(array, curSize);
1449ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1450ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1451ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1452ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1453ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public void copyInto(double[] dest, int destOffset) {
1454ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            System.arraycopy(array, 0, dest, destOffset, curSize);
1455ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1456ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1457ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1458ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public long count() {
1459ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return curSize;
1460ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1461ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1462ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1463ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public void forEach(DoubleConsumer consumer) {
1464ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            for (int i = 0; i < curSize; i++) {
1465ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                consumer.accept(array[i]);
1466ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1467ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1468ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1469ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1470ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public String toString() {
1471ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return String.format("DoubleArrayNode[%d][%s]",
1472ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                 array.length - curSize, Arrays.toString(array));
1473ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1474ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
1475ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1476ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    private static final class IntFixedNodeBuilder
1477ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            extends IntArrayNode
1478ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            implements Node.Builder.OfInt {
1479ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1480ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        IntFixedNodeBuilder(long size) {
1481ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            super(size);
1482ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            assert size < MAX_ARRAY_SIZE;
1483ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1484ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1485ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1486ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public Node.OfInt build() {
1487ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (curSize < array.length) {
1488ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                throw new IllegalStateException(String.format("Current size %d is less than fixed size %d",
1489ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                                              curSize, array.length));
1490ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1491ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1492ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return this;
1493ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1494ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1495ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1496ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public void begin(long size) {
1497ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (size != array.length) {
1498ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                throw new IllegalStateException(String.format("Begin size %d is not equal to fixed size %d",
1499ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                                              size, array.length));
1500ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1501ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1502ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            curSize = 0;
1503ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1504ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1505ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1506ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public void accept(int i) {
1507ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (curSize < array.length) {
1508ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                array[curSize++] = i;
1509ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            } else {
1510ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                throw new IllegalStateException(String.format("Accept exceeded fixed size of %d",
1511ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                                              array.length));
1512ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1513ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1514ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1515ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1516ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public void end() {
1517ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (curSize < array.length) {
1518ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                throw new IllegalStateException(String.format("End size %d is less than fixed size %d",
1519ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                                              curSize, array.length));
1520ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1521ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1522ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1523ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1524ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public String toString() {
1525ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return String.format("IntFixedNodeBuilder[%d][%s]",
1526ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                 array.length - curSize, Arrays.toString(array));
1527ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1528ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
1529ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1530ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    private static final class LongFixedNodeBuilder
1531ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            extends LongArrayNode
1532ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            implements Node.Builder.OfLong {
1533ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1534ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        LongFixedNodeBuilder(long size) {
1535ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            super(size);
1536ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            assert size < MAX_ARRAY_SIZE;
1537ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1538ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1539ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1540ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public Node.OfLong build() {
1541ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (curSize < array.length) {
1542ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                throw new IllegalStateException(String.format("Current size %d is less than fixed size %d",
1543ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                                              curSize, array.length));
1544ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1545ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1546ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return this;
1547ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1548ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1549ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1550ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public void begin(long size) {
1551ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (size != array.length) {
1552ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                throw new IllegalStateException(String.format("Begin size %d is not equal to fixed size %d",
1553ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                                              size, array.length));
1554ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1555ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1556ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            curSize = 0;
1557ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1558ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1559ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1560ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public void accept(long i) {
1561ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (curSize < array.length) {
1562ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                array[curSize++] = i;
1563ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            } else {
1564ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                throw new IllegalStateException(String.format("Accept exceeded fixed size of %d",
1565ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                                              array.length));
1566ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1567ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1568ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1569ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1570ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public void end() {
1571ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (curSize < array.length) {
1572ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                throw new IllegalStateException(String.format("End size %d is less than fixed size %d",
1573ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                                              curSize, array.length));
1574ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1575ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1576ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1577ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1578ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public String toString() {
1579ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return String.format("LongFixedNodeBuilder[%d][%s]",
1580ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                 array.length - curSize, Arrays.toString(array));
1581ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1582ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
1583ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1584ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    private static final class DoubleFixedNodeBuilder
1585ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            extends DoubleArrayNode
1586ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            implements Node.Builder.OfDouble {
1587ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1588ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        DoubleFixedNodeBuilder(long size) {
1589ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            super(size);
1590ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            assert size < MAX_ARRAY_SIZE;
1591ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1592ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1593ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1594ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public Node.OfDouble build() {
1595ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (curSize < array.length) {
1596ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                throw new IllegalStateException(String.format("Current size %d is less than fixed size %d",
1597ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                                              curSize, array.length));
1598ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1599ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1600ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return this;
1601ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1602ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1603ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1604ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public void begin(long size) {
1605ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (size != array.length) {
1606ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                throw new IllegalStateException(String.format("Begin size %d is not equal to fixed size %d",
1607ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                                              size, array.length));
1608ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1609ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1610ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            curSize = 0;
1611ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1612ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1613ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1614ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public void accept(double i) {
1615ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (curSize < array.length) {
1616ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                array[curSize++] = i;
1617ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            } else {
1618ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                throw new IllegalStateException(String.format("Accept exceeded fixed size of %d",
1619ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                                              array.length));
1620ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1621ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1622ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1623ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1624ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public void end() {
1625ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (curSize < array.length) {
1626ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                throw new IllegalStateException(String.format("End size %d is less than fixed size %d",
1627ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                                              curSize, array.length));
1628ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1629ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1630ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1631ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1632ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public String toString() {
1633ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return String.format("DoubleFixedNodeBuilder[%d][%s]",
1634ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                 array.length - curSize, Arrays.toString(array));
1635ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1636ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
1637ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1638ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    private static final class IntSpinedNodeBuilder
1639ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            extends SpinedBuffer.OfInt
1640ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            implements Node.OfInt, Node.Builder.OfInt {
1641ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        private boolean building = false;
1642ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1643ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        IntSpinedNodeBuilder() {} // Avoid creation of special accessor
1644ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1645ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1646ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public Spliterator.OfInt spliterator() {
1647ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            assert !building : "during building";
1648ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return super.spliterator();
1649ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1650ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1651ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1652ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public void forEach(IntConsumer consumer) {
1653ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            assert !building : "during building";
1654ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            super.forEach(consumer);
1655ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1656ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1657ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        //
1658ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1659ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public void begin(long size) {
1660ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            assert !building : "was already building";
1661ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            building = true;
1662ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            clear();
1663ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            ensureCapacity(size);
1664ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1665ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1666ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1667ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public void accept(int i) {
1668ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            assert building : "not building";
1669ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            super.accept(i);
1670ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1671ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1672ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1673ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public void end() {
1674ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            assert building : "was not building";
1675ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            building = false;
1676ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            // @@@ check begin(size) and size
1677ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1678ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1679ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1680ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public void copyInto(int[] array, int offset) throws IndexOutOfBoundsException {
1681ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            assert !building : "during building";
1682ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            super.copyInto(array, offset);
1683ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1684ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1685ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1686ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public int[] asPrimitiveArray() {
1687ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            assert !building : "during building";
1688ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return super.asPrimitiveArray();
1689ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1690ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1691ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1692ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public Node.OfInt build() {
1693ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            assert !building : "during building";
1694ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return this;
1695ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1696ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
1697ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1698ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    private static final class LongSpinedNodeBuilder
1699ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            extends SpinedBuffer.OfLong
1700ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            implements Node.OfLong, Node.Builder.OfLong {
1701ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        private boolean building = false;
1702ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1703ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        LongSpinedNodeBuilder() {} // Avoid creation of special accessor
1704ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1705ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1706ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public Spliterator.OfLong spliterator() {
1707ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            assert !building : "during building";
1708ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return super.spliterator();
1709ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1710ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1711ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1712ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public void forEach(LongConsumer consumer) {
1713ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            assert !building : "during building";
1714ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            super.forEach(consumer);
1715ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1716ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1717ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        //
1718ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1719ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public void begin(long size) {
1720ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            assert !building : "was already building";
1721ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            building = true;
1722ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            clear();
1723ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            ensureCapacity(size);
1724ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1725ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1726ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1727ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public void accept(long i) {
1728ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            assert building : "not building";
1729ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            super.accept(i);
1730ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1731ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1732ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1733ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public void end() {
1734ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            assert building : "was not building";
1735ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            building = false;
1736ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            // @@@ check begin(size) and size
1737ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1738ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1739ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1740ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public void copyInto(long[] array, int offset) {
1741ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            assert !building : "during building";
1742ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            super.copyInto(array, offset);
1743ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1744ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1745ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1746ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public long[] asPrimitiveArray() {
1747ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            assert !building : "during building";
1748ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return super.asPrimitiveArray();
1749ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1750ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1751ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1752ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public Node.OfLong build() {
1753ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            assert !building : "during building";
1754ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return this;
1755ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1756ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
1757ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1758ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    private static final class DoubleSpinedNodeBuilder
1759ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            extends SpinedBuffer.OfDouble
1760ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            implements Node.OfDouble, Node.Builder.OfDouble {
1761ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        private boolean building = false;
1762ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1763ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        DoubleSpinedNodeBuilder() {} // Avoid creation of special accessor
1764ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1765ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1766ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public Spliterator.OfDouble spliterator() {
1767ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            assert !building : "during building";
1768ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return super.spliterator();
1769ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1770ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1771ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1772ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public void forEach(DoubleConsumer consumer) {
1773ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            assert !building : "during building";
1774ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            super.forEach(consumer);
1775ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1776ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1777ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        //
1778ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1779ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public void begin(long size) {
1780ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            assert !building : "was already building";
1781ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            building = true;
1782ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            clear();
1783ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            ensureCapacity(size);
1784ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1785ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1786ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1787ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public void accept(double i) {
1788ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            assert building : "not building";
1789ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            super.accept(i);
1790ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1791ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1792ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1793ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public void end() {
1794ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            assert building : "was not building";
1795ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            building = false;
1796ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            // @@@ check begin(size) and size
1797ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1798ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1799ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1800ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public void copyInto(double[] array, int offset) {
1801ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            assert !building : "during building";
1802ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            super.copyInto(array, offset);
1803ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1804ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1805ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1806ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public double[] asPrimitiveArray() {
1807ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            assert !building : "during building";
1808ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return super.asPrimitiveArray();
1809ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1810ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1811ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1812ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public Node.OfDouble build() {
1813ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            assert !building : "during building";
1814ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return this;
1815ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1816ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
1817ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1818ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /*
1819ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * This and subclasses are not intended to be serializable
1820ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
1821ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    @SuppressWarnings("serial")
1822ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    private static abstract class SizedCollectorTask<P_IN, P_OUT, T_SINK extends Sink<P_OUT>,
1823ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                                     K extends SizedCollectorTask<P_IN, P_OUT, T_SINK, K>>
1824ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            extends CountedCompleter<Void>
1825ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            implements Sink<P_OUT> {
1826ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        protected final Spliterator<P_IN> spliterator;
1827ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        protected final PipelineHelper<P_OUT> helper;
1828ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        protected final long targetSize;
1829ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        protected long offset;
1830ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        protected long length;
1831ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        // For Sink implementation
1832ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        protected int index, fence;
1833ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1834ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        SizedCollectorTask(Spliterator<P_IN> spliterator,
1835ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                           PipelineHelper<P_OUT> helper,
1836ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                           int arrayLength) {
1837ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            assert spliterator.hasCharacteristics(Spliterator.SUBSIZED);
1838ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.spliterator = spliterator;
1839ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.helper = helper;
1840ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.targetSize = AbstractTask.suggestTargetSize(spliterator.estimateSize());
1841ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.offset = 0;
1842ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.length = arrayLength;
1843ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1844ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1845ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        SizedCollectorTask(K parent, Spliterator<P_IN> spliterator,
1846ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                           long offset, long length, int arrayLength) {
1847ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            super(parent);
1848ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            assert spliterator.hasCharacteristics(Spliterator.SUBSIZED);
1849ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.spliterator = spliterator;
1850ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.helper = parent.helper;
1851ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.targetSize = parent.targetSize;
1852ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.offset = offset;
1853ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.length = length;
1854ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1855ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (offset < 0 || length < 0 || (offset + length - 1 >= arrayLength)) {
1856ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                throw new IllegalArgumentException(
1857ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        String.format("offset and length interval [%d, %d + %d) is not within array size interval [0, %d)",
1858ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                      offset, offset, length, arrayLength));
1859ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1860ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1861ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1862ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1863ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public void compute() {
1864ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            SizedCollectorTask<P_IN, P_OUT, T_SINK, K> task = this;
1865ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            Spliterator<P_IN> rightSplit = spliterator, leftSplit;
1866ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            while (rightSplit.estimateSize() > task.targetSize &&
1867ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                   (leftSplit = rightSplit.trySplit()) != null) {
1868ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                task.setPendingCount(1);
1869ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                long leftSplitSize = leftSplit.estimateSize();
1870ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                task.makeChild(leftSplit, task.offset, leftSplitSize).fork();
1871ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                task = task.makeChild(rightSplit, task.offset + leftSplitSize,
1872ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                      task.length - leftSplitSize);
1873ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1874ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1875ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            assert task.offset + task.length < MAX_ARRAY_SIZE;
1876ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @SuppressWarnings("unchecked")
1877ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            T_SINK sink = (T_SINK) task;
1878ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            task.helper.wrapAndCopyInto(sink, rightSplit);
1879ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            task.propagateCompletion();
1880ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1881ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1882ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        abstract K makeChild(Spliterator<P_IN> spliterator, long offset, long size);
1883ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1884ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
1885ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public void begin(long size) {
1886ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (size > length)
1887ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                throw new IllegalStateException("size passed to Sink.begin exceeds array length");
1888ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            // Casts to int are safe since absolute size is verified to be within
1889ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            // bounds when the root concrete SizedCollectorTask is constructed
1890ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            // with the shared array
1891ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            index = (int) offset;
1892ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            fence = index + (int) length;
1893ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1894ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1895ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @SuppressWarnings("serial")
1896ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        static final class OfRef<P_IN, P_OUT>
1897ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                extends SizedCollectorTask<P_IN, P_OUT, Sink<P_OUT>, OfRef<P_IN, P_OUT>>
1898ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                implements Sink<P_OUT> {
1899ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            private final P_OUT[] array;
1900ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1901ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            OfRef(Spliterator<P_IN> spliterator, PipelineHelper<P_OUT> helper, P_OUT[] array) {
1902ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                super(spliterator, helper, array.length);
1903ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                this.array = array;
1904ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1905ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1906ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            OfRef(OfRef<P_IN, P_OUT> parent, Spliterator<P_IN> spliterator,
1907ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                  long offset, long length) {
1908ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                super(parent, spliterator, offset, length, parent.array.length);
1909ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                this.array = parent.array;
1910ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1911ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1912ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
1913ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            OfRef<P_IN, P_OUT> makeChild(Spliterator<P_IN> spliterator,
1914ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                         long offset, long size) {
1915ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return new OfRef<>(this, spliterator, offset, size);
1916ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1917ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1918ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
1919ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            public void accept(P_OUT value) {
1920ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                if (index >= fence) {
1921ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    throw new IndexOutOfBoundsException(Integer.toString(index));
1922ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                }
1923ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                array[index++] = value;
1924ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1925ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1926ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1927ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @SuppressWarnings("serial")
1928ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        static final class OfInt<P_IN>
1929ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                extends SizedCollectorTask<P_IN, Integer, Sink.OfInt, OfInt<P_IN>>
1930ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                implements Sink.OfInt {
1931ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            private final int[] array;
1932ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1933ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            OfInt(Spliterator<P_IN> spliterator, PipelineHelper<Integer> helper, int[] array) {
1934ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                super(spliterator, helper, array.length);
1935ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                this.array = array;
1936ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1937ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1938ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            OfInt(SizedCollectorTask.OfInt<P_IN> parent, Spliterator<P_IN> spliterator,
1939ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                  long offset, long length) {
1940ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                super(parent, spliterator, offset, length, parent.array.length);
1941ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                this.array = parent.array;
1942ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1943ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1944ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
1945ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            SizedCollectorTask.OfInt<P_IN> makeChild(Spliterator<P_IN> spliterator,
1946ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                                     long offset, long size) {
1947ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return new SizedCollectorTask.OfInt<>(this, spliterator, offset, size);
1948ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1949ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1950ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
1951ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            public void accept(int value) {
1952ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                if (index >= fence) {
1953ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    throw new IndexOutOfBoundsException(Integer.toString(index));
1954ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                }
1955ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                array[index++] = value;
1956ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1957ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1958ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1959ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @SuppressWarnings("serial")
1960ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        static final class OfLong<P_IN>
1961ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                extends SizedCollectorTask<P_IN, Long, Sink.OfLong, OfLong<P_IN>>
1962ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                implements Sink.OfLong {
1963ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            private final long[] array;
1964ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1965ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            OfLong(Spliterator<P_IN> spliterator, PipelineHelper<Long> helper, long[] array) {
1966ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                super(spliterator, helper, array.length);
1967ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                this.array = array;
1968ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1969ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1970ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            OfLong(SizedCollectorTask.OfLong<P_IN> parent, Spliterator<P_IN> spliterator,
1971ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                   long offset, long length) {
1972ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                super(parent, spliterator, offset, length, parent.array.length);
1973ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                this.array = parent.array;
1974ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1975ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1976ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
1977ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            SizedCollectorTask.OfLong<P_IN> makeChild(Spliterator<P_IN> spliterator,
1978ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                                      long offset, long size) {
1979ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return new SizedCollectorTask.OfLong<>(this, spliterator, offset, size);
1980ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1981ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1982ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
1983ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            public void accept(long value) {
1984ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                if (index >= fence) {
1985ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    throw new IndexOutOfBoundsException(Integer.toString(index));
1986ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                }
1987ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                array[index++] = value;
1988ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
1989ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
1990ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1991ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @SuppressWarnings("serial")
1992ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        static final class OfDouble<P_IN>
1993ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                extends SizedCollectorTask<P_IN, Double, Sink.OfDouble, OfDouble<P_IN>>
1994ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                implements Sink.OfDouble {
1995ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            private final double[] array;
1996ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
1997ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            OfDouble(Spliterator<P_IN> spliterator, PipelineHelper<Double> helper, double[] array) {
1998ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                super(spliterator, helper, array.length);
1999ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                this.array = array;
2000ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
2001ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
2002ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            OfDouble(SizedCollectorTask.OfDouble<P_IN> parent, Spliterator<P_IN> spliterator,
2003ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                     long offset, long length) {
2004ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                super(parent, spliterator, offset, length, parent.array.length);
2005ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                this.array = parent.array;
2006ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
2007ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
2008ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
2009ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            SizedCollectorTask.OfDouble<P_IN> makeChild(Spliterator<P_IN> spliterator,
2010ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                                        long offset, long size) {
2011ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return new SizedCollectorTask.OfDouble<>(this, spliterator, offset, size);
2012ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
2013ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
2014ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
2015ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            public void accept(double value) {
2016ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                if (index >= fence) {
2017ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    throw new IndexOutOfBoundsException(Integer.toString(index));
2018ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                }
2019ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                array[index++] = value;
2020ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
2021ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
2022ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
2023ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
2024ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    @SuppressWarnings("serial")
2025ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    private static abstract class ToArrayTask<T, T_NODE extends Node<T>,
2026ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                              K extends ToArrayTask<T, T_NODE, K>>
2027ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            extends CountedCompleter<Void> {
2028ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        protected final T_NODE node;
2029ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        protected final int offset;
2030ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
2031ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        ToArrayTask(T_NODE node, int offset) {
2032ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.node = node;
2033ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.offset = offset;
2034ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
2035ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
2036ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        ToArrayTask(K parent, T_NODE node, int offset) {
2037ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            super(parent);
2038ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.node = node;
2039ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.offset = offset;
2040ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
2041ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
2042ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        abstract void copyNodeToArray();
2043ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
2044ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        abstract K makeChild(int childIndex, int offset);
2045ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
2046ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
2047ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public void compute() {
2048ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            ToArrayTask<T, T_NODE, K> task = this;
2049ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            while (true) {
2050ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                if (task.node.getChildCount() == 0) {
2051ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    task.copyNodeToArray();
2052ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    task.propagateCompletion();
2053ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    return;
2054ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                }
2055ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                else {
2056ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    task.setPendingCount(task.node.getChildCount() - 1);
2057ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
2058ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    int size = 0;
2059ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    int i = 0;
2060ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    for (;i < task.node.getChildCount() - 1; i++) {
2061ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        K leftTask = task.makeChild(i, task.offset + size);
2062ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        size += leftTask.node.count();
2063ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                        leftTask.fork();
2064ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    }
2065ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    task = task.makeChild(i, task.offset + size);
2066ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                }
2067ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
2068ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
2069ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
2070ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @SuppressWarnings("serial")
2071ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        private static final class OfRef<T>
2072ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                extends ToArrayTask<T, Node<T>, OfRef<T>> {
2073ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            private final T[] array;
2074ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
2075ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            private OfRef(Node<T> node, T[] array, int offset) {
2076ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                super(node, offset);
2077ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                this.array = array;
2078ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
2079ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
2080ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            private OfRef(OfRef<T> parent, Node<T> node, int offset) {
2081ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                super(parent, node, offset);
2082ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                this.array = parent.array;
2083ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
2084ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
2085ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
2086ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            OfRef<T> makeChild(int childIndex, int offset) {
2087ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return new OfRef<>(this, node.getChild(childIndex), offset);
2088ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
2089ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
2090ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
2091ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            void copyNodeToArray() {
2092ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                node.copyInto(array, offset);
2093ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
2094ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
2095ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
2096ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @SuppressWarnings("serial")
2097ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        private static class OfPrimitive<T, T_CONS, T_ARR,
2098ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                         T_SPLITR extends Spliterator.OfPrimitive<T, T_CONS, T_SPLITR>,
2099ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                                         T_NODE extends Node.OfPrimitive<T, T_CONS, T_ARR, T_SPLITR, T_NODE>>
2100ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                extends ToArrayTask<T, T_NODE, OfPrimitive<T, T_CONS, T_ARR, T_SPLITR, T_NODE>> {
2101ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            private final T_ARR array;
2102ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
2103ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            private OfPrimitive(T_NODE node, T_ARR array, int offset) {
2104ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                super(node, offset);
2105ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                this.array = array;
2106ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
2107ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
2108ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            private OfPrimitive(OfPrimitive<T, T_CONS, T_ARR, T_SPLITR, T_NODE> parent, T_NODE node, int offset) {
2109ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                super(parent, node, offset);
2110ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                this.array = parent.array;
2111ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
2112ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
2113ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
2114ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            OfPrimitive<T, T_CONS, T_ARR, T_SPLITR, T_NODE> makeChild(int childIndex, int offset) {
2115ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                return new OfPrimitive<>(this, node.getChild(childIndex), offset);
2116ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
2117ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
2118ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            @Override
2119ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            void copyNodeToArray() {
2120ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                node.copyInto(array, offset);
2121ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
2122ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
2123ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
2124ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @SuppressWarnings("serial")
2125ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        private static final class OfInt
2126ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                extends OfPrimitive<Integer, IntConsumer, int[], Spliterator.OfInt, Node.OfInt> {
2127ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            private OfInt(Node.OfInt node, int[] array, int offset) {
2128ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                super(node, array, offset);
2129ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
2130ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
2131ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
2132ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @SuppressWarnings("serial")
2133ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        private static final class OfLong
2134ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                extends OfPrimitive<Long, LongConsumer, long[], Spliterator.OfLong, Node.OfLong> {
2135ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            private OfLong(Node.OfLong node, long[] array, int offset) {
2136ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                super(node, array, offset);
2137ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
2138ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
2139ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
2140ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @SuppressWarnings("serial")
2141ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        private static final class OfDouble
2142ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                extends OfPrimitive<Double, DoubleConsumer, double[], Spliterator.OfDouble, Node.OfDouble> {
2143ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            private OfDouble(Node.OfDouble node, double[] array, int offset) {
2144ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                super(node, array, offset);
2145ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
2146ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
2147ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
2148ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
2149ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    @SuppressWarnings("serial")
2150ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    private static class CollectorTask<P_IN, P_OUT, T_NODE extends Node<P_OUT>, T_BUILDER extends Node.Builder<P_OUT>>
2151ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            extends AbstractTask<P_IN, P_OUT, T_NODE, CollectorTask<P_IN, P_OUT, T_NODE, T_BUILDER>> {
2152ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        protected final PipelineHelper<P_OUT> helper;
2153ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        protected final LongFunction<T_BUILDER> builderFactory;
2154ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        protected final BinaryOperator<T_NODE> concFactory;
2155ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
2156ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        CollectorTask(PipelineHelper<P_OUT> helper,
2157ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                      Spliterator<P_IN> spliterator,
2158ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                      LongFunction<T_BUILDER> builderFactory,
2159ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                      BinaryOperator<T_NODE> concFactory) {
2160ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            super(helper, spliterator);
2161ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.helper = helper;
2162ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.builderFactory = builderFactory;
2163ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.concFactory = concFactory;
2164ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
2165ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
2166ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        CollectorTask(CollectorTask<P_IN, P_OUT, T_NODE, T_BUILDER> parent,
2167ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                      Spliterator<P_IN> spliterator) {
2168ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            super(parent, spliterator);
2169ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            helper = parent.helper;
2170ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            builderFactory = parent.builderFactory;
2171ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            concFactory = parent.concFactory;
2172ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
2173ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
2174ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
2175ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        protected CollectorTask<P_IN, P_OUT, T_NODE, T_BUILDER> makeChild(Spliterator<P_IN> spliterator) {
2176ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return new CollectorTask<>(this, spliterator);
2177ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
2178ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
2179ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
2180ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @SuppressWarnings("unchecked")
2181ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        protected T_NODE doLeaf() {
2182ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            T_BUILDER builder = builderFactory.apply(helper.exactOutputSizeIfKnown(spliterator));
2183ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return (T_NODE) helper.wrapAndCopyInto(builder, spliterator).build();
2184ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
2185ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
2186ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @Override
2187ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        public void onCompletion(CountedCompleter<?> caller) {
2188ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            if (!isLeaf())
2189ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                setLocalResult(concFactory.apply(leftChild.getLocalResult(), rightChild.getLocalResult()));
2190ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            super.onCompletion(caller);
2191ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
2192ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
2193ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @SuppressWarnings("serial")
2194ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        private static final class OfRef<P_IN, P_OUT>
2195ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                extends CollectorTask<P_IN, P_OUT, Node<P_OUT>, Node.Builder<P_OUT>> {
2196ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            OfRef(PipelineHelper<P_OUT> helper,
2197ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                  IntFunction<P_OUT[]> generator,
2198ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                  Spliterator<P_IN> spliterator) {
2199ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                super(helper, spliterator, s -> builder(s, generator), ConcNode::new);
2200ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
2201ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
2202ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
2203ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @SuppressWarnings("serial")
2204ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        private static final class OfInt<P_IN>
2205ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                extends CollectorTask<P_IN, Integer, Node.OfInt, Node.Builder.OfInt> {
2206ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            OfInt(PipelineHelper<Integer> helper, Spliterator<P_IN> spliterator) {
2207ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                super(helper, spliterator, Nodes::intBuilder, ConcNode.OfInt::new);
2208ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
2209ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
2210ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
2211ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @SuppressWarnings("serial")
2212ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        private static final class OfLong<P_IN>
2213ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                extends CollectorTask<P_IN, Long, Node.OfLong, Node.Builder.OfLong> {
2214ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            OfLong(PipelineHelper<Long> helper, Spliterator<P_IN> spliterator) {
2215ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                super(helper, spliterator, Nodes::longBuilder, ConcNode.OfLong::new);
2216ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
2217ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
2218ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
2219ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        @SuppressWarnings("serial")
2220ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        private static final class OfDouble<P_IN>
2221ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                extends CollectorTask<P_IN, Double, Node.OfDouble, Node.Builder.OfDouble> {
2222ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            OfDouble(PipelineHelper<Double> helper, Spliterator<P_IN> spliterator) {
2223ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                super(helper, spliterator, Nodes::doubleBuilder, ConcNode.OfDouble::new);
2224ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
2225ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
2226ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
2227ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin}
2228