ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/extra166y/ParallelArray.java
Revision: 1.18
Committed: Sun Jan 18 20:17:32 2015 UTC (9 years, 3 months ago) by jsr166
Branch: MAIN
CVS Tags: HEAD
Changes since 1.17: +1 -0 lines
Log Message:
exactly one blank line before and after package statements

File Contents

# Content
1 /*
2 * Written by Doug Lea with assistance from members of JCP JSR-166
3 * Expert Group and released to the public domain, as explained at
4 * http://creativecommons.org/publicdomain/zero/1.0/
5 */
6
7 package extra166y;
8
9 import jsr166y.*;
10 import static extra166y.Ops.*;
11 import java.util.*;
12 import java.util.concurrent.atomic.*;
13 import java.lang.reflect.Array;
14
15 /**
16 * An array supporting parallel operations.
17 *
18 * <p>A ParallelArray maintains a {@link ForkJoinPool} and an
19 * array in order to provide parallel aggregate operations. The main
20 * operations are to <em>apply</em> some procedure to each element, to
21 * <em>map</em> each element to a new element, to <em>replace</em>
22 * each element, to <em>select</em> a subset of elements based on
23 * matching a predicate or ranges of indices, and to <em>reduce</em>
24 * all elements into a single value such as a sum.
25 *
26 * <p>A ParallelArray is constructed by allocating, using, or copying
27 * an array, using one of the static factory methods {@link #create},
28 * {@link #createEmpty}, {@link #createUsingHandoff} and {@link
29 * #createFromCopy}. Upon construction, the encapsulated array managed
30 * by the ParallelArray must not be shared between threads without
31 * external synchronization. In particular, as is the case with any
32 * array, access by another thread of an element of a ParallelArray
33 * while another operation is in progress has undefined effects.
34 *
35 * <p>The ForkJoinPool used to construct a ParallelArray can be
36 * shared safely by other threads (and used in other
37 * ParallelArrays). To avoid the overhead associated with creating
38 * multiple executors, it is often a good idea to use the {@link
39 * #defaultExecutor()} across all ParallelArrays. However, you might
40 * choose to use different ones for the sake of controlling processor
41 * usage, isolating faults, and/or ensuring progress.
42 *
43 * <p>A ParallelArray is not a List. It relies on random access across
44 * array elements to support efficient parallel operations. However,
45 * a ParallelArray can be viewed and manipulated as a List, via method
46 * {@link ParallelArray#asList}. The {@code asList} view allows
47 * incremental insertion and modification of elements while setting up
48 * a ParallelArray, generally before using it for parallel
49 * operations. Similarly, the list view may be useful when accessing
50 * the results of computations in sequential contexts. A
51 * ParallelArray may also be created using the elements of any other
52 * Collection, by constructing from the array returned by the
53 * Collection's {@code toArray} method. The effects of mutative
54 * {@code asList} operations may also be achieved directly using
55 * method {@link #setLimit} along with element-by-element access
56 * methods {@link #get}</tt> and {@link #set}.
57 *
58 * <p>While ParallelArrays can be based on any kind of an object
59 * array, including "boxed" types such as Long, parallel operations on
60 * scalar "unboxed" type are likely to be substantially more
61 * efficient. For this reason, classes {@link ParallelLongArray} and
62 * {@link ParallelDoubleArray} are also supplied, and designed to
63 * smoothly interoperate with ParallelArrays. You should also use a
64 * ParallelLongArray for processing other integral scalar data
65 * ({@code int}, {@code short}, etc). And similarly use a
66 * ParallelDoubleArray for {@code float} data. (Further
67 * specializations for these other types would add clutter without
68 * significantly improving performance beyond that of the Long and
69 * Double versions.)
70 *
71 * <p>Most usages of ParallelArray involve sets of operations prefixed
72 * with range bounds, filters, and mappings (including mappings that
73 * combine elements from other ParallelArrays), using
74 * {@code withBounds}, {@code withFilter}, and {@code withMapping},
75 * respectively. For example,
76 * {@code aParallelArray.withFilter(aPredicate).all()} creates a new
77 * ParallelArray containing only those elements matching the
78 * predicate. And for ParallelLongArrays a, b, and c,
79 * {@code a.withMapping(CommonOps.longAdder(),b).withMapping(CommonOps.longAdder(),c).min()}
80 * returns the minimum value of a[i]+b[i]+c[i] for all i. As
81 * illustrated below, a <em>mapping</em> often represents accessing
82 * some field or invoking some method of an element. These versions
83 * are typically more efficient than performing selections, then
84 * mappings, then other operations in multiple (parallel) steps. The
85 * basic ideas and usages of filtering and mapping are similar to
86 * those in database query systems such as SQL, but take a more
87 * restrictive form. Series of filter and mapping prefixes may each
88 * be cascaded, but all filter prefixes must precede all mapping
89 * prefixes, to ensure efficient execution in a single parallel step.
90 * In cases of combined mapping expressions, this rule is only
91 * dynamically enforced. For example, {@code pa.withMapping(op,
92 * pb.withFilter(f))} will compile but throw an exception upon
93 * execution because the filter precedes the mapping.
94 *
95 * <p>While series of filters and mappings are allowed, it is
96 * usually more efficient to combine them into single filters or
97 * mappings when possible. For example
98 * {@code pa.withMapping(addOne).withMapping(addOne)} is generally
99 * less efficient than {@code pa.withMapping(addTwo)}. Methods
100 * {@code withIndexedFilter} and {@code withIndexedMapping} may be
101 * useful when combining such expressions.
102 *
103 * <p>This class includes some reductions, such as {@code min}, that
104 * are commonly useful for most element types, as well as a combined
105 * version, {@code summary}, that computes all of them in a single
106 * parallel step, which is normally more efficient than computing each
107 * in turn.
108 *
109 * <p>The methods in this class are designed to perform efficiently
110 * with both large and small pools, even with single-thread pools on
111 * uniprocessors. However, there is some overhead in parallelizing
112 * operations, so short computations on small arrays might not execute
113 * faster than sequential versions, and might even be slower.
114 *
115 * <p><b>Sample usages</b>.
116 *
117 * The main difference between programming with plain arrays and
118 * programming with aggregates is that you must separately define each
119 * of the component functions on elements. For example, the following
120 * returns the maximum Grade Point Average across all senior students,
121 * given a (fictional) {@code Student} class:
122 *
123 * <pre>
124 * import static Ops.*;
125 * class StudentStatistics {
126 * ParallelArray&lt;Student&gt; students = ...
127 * // ...
128 * public double getMaxSeniorGpa() {
129 * return students.withFilter(isSenior).withMapping(gpaField).max();
130 * }
131 *
132 * // helpers:
133 * static final class IsSenior implements Predicate&lt;Student&gt; {
134 * public boolean op(Student s) { return s.credits &gt; 90; }
135 * }
136 * static final IsSenior isSenior = new IsSenior();
137 * static final class GpaField implements ObjectToDouble&lt;Student&gt; {
138 * public double op(Student s) { return s.gpa; }
139 * }
140 * static final GpaField gpaField = new GpaField();
141 * }
142 * </pre>
143 */
144 public class ParallelArray<T> extends AbstractParallelAnyArray.OUPap<T> implements Iterable<T> {
145 /*
146 * See classes PAS and AbstractParallelAnyArray for most of the underlying parallel execution
147 * code and explanation.
148 */
149
150 /**
151 * Returns a common default executor for use in ParallelArrays.
152 * This executor arranges enough parallelism to use most, but not
153 * necessarily all, of the available processors on this system.
154 * @return the executor
155 */
156 public static ForkJoinPool defaultExecutor() {
157 return PAS.defaultExecutor();
158 }
159
160 /** Lazily constructed list view */
161 AsList listView;
162
163 /**
164 * Constructor for use by subclasses to create a new ParallelArray
165 * using the given executor, and initially using the supplied
166 * array, with effective size bound by the given limit. This
167 * constructor is designed to enable extensions via
168 * subclassing. To create a ParallelArray, use {@link #create},
169 * {@link #createEmpty}, {@link #createUsingHandoff} or {@link
170 * #createFromCopy}.
171 * @param executor the executor
172 * @param array the array
173 * @param limit the upper bound limit
174 */
175 protected ParallelArray(ForkJoinPool executor, T[] array, int limit) {
176 super(executor, 0, limit, array);
177 if (executor == null || array == null)
178 throw new NullPointerException();
179 if (limit < 0 || limit > array.length)
180 throw new IllegalArgumentException();
181 }
182
183 /**
184 * Trusted internal version of protected constructor.
185 */
186 ParallelArray(ForkJoinPool executor, T[] array) {
187 super(executor, 0, array.length, array);
188 }
189
190 /**
191 * Creates a new ParallelArray using the given executor and
192 * an array of the given size constructed using the
193 * indicated base element type.
194 * @param size the array size
195 * @param elementType the type of the elements
196 * @param executor the executor
197 */
198 public static <T> ParallelArray<T> create
199 (int size, Class<? super T> elementType,
200 ForkJoinPool executor) {
201 T[] array = (T[])Array.newInstance(elementType, size);
202 return new ParallelArray<T>(executor, array, size);
203 }
204
205 /**
206 * Creates a new ParallelArray initially using the given array and
207 * executor. In general, the handed off array should not be used
208 * for other purposes once constructing this ParallelArray. The
209 * given array may be internally replaced by another array in the
210 * course of methods that add or remove elements.
211 * @param handoff the array
212 * @param executor the executor
213 */
214 public static <T> ParallelArray<T> createUsingHandoff
215 (T[] handoff, ForkJoinPool executor) {
216 return new ParallelArray<T>(executor, handoff, handoff.length);
217 }
218
219 /**
220 * Creates a new ParallelArray using the given executor and
221 * initially holding copies of the given
222 * source elements.
223 * @param source the source of initial elements
224 * @param executor the executor
225 */
226 public static <T> ParallelArray<T> createFromCopy
227 (T[] source, ForkJoinPool executor) {
228 // For now, avoid copyOf so people can compile with Java5
229 int size = source.length;
230 T[] array = (T[])Array.newInstance
231 (source.getClass().getComponentType(), size);
232 System.arraycopy(source, 0, array, 0, size);
233 return new ParallelArray<T>(executor, array, size);
234 }
235
236 /**
237 * Creates a new ParallelArray using an array of the given size,
238 * initially holding copies of the given source truncated or
239 * padded with nulls to obtain the specified length.
240 * @param source the source of initial elements
241 * @param size the array size
242 * @param executor the executor
243 */
244 public static <T> ParallelArray<T> createFromCopy
245 (int size, T[] source, ForkJoinPool executor) {
246 // For now, avoid copyOf so people can compile with Java5
247 T[] array = (T[])Array.newInstance
248 (source.getClass().getComponentType(), size);
249 System.arraycopy(source, 0, array, 0,
250 Math.min(source.length, size));
251 return new ParallelArray<T>(executor, array, size);
252 }
253
254 /**
255 * Creates a new ParallelArray using the given executor and an
256 * array of the given size constructed using the indicated base
257 * element type, but with an initial effective size of zero,
258 * enabling incremental insertion via {@link ParallelArray#asList}
259 * operations.
260 * @param size the array size
261 * @param elementType the type of the elements
262 * @param executor the executor
263 */
264 public static <T> ParallelArray<T> createEmpty
265 (int size, Class<? super T> elementType,
266 ForkJoinPool executor) {
267 T[] array = (T[])Array.newInstance(elementType, size);
268 return new ParallelArray<T>(executor, array, 0);
269 }
270
271 /**
272 * Summary statistics for a possibly bounded, filtered, and/or
273 * mapped ParallelArray.
274 */
275 public static interface SummaryStatistics<T> {
276 /** Returns the number of elements */
277 public int size();
278 /** Returns the minimum element, or null if empty */
279 public T min();
280 /** Returns the maximum element, or null if empty */
281 public T max();
282 /** Returns the index of the minimum element, or -1 if empty */
283 public int indexOfMin();
284 /** Returns the index of the maximum element, or -1 if empty */
285 public int indexOfMax();
286 }
287
288 /**
289 * Returns the executor used for computations.
290 * @return the executor
291 */
292 public ForkJoinPool getExecutor() { return ex; }
293
294 /**
295 * Applies the given procedure to elements.
296 * @param procedure the procedure
297 */
298 public void apply(Procedure<? super T> procedure) {
299 super.apply(procedure);
300 }
301
302 /**
303 * Returns reduction of elements.
304 * @param reducer the reducer
305 * @param base the result for an empty array
306 * @return reduction
307 */
308 public T reduce(Reducer<T> reducer, T base) {
309 return super.reduce(reducer, base);
310 }
311
312 /**
313 * Returns a new ParallelArray holding all elements.
314 * @return a new ParallelArray holding all elements
315 */
316 public ParallelArray<T> all() {
317 return super.all();
318 }
319
320 /**
321 * Returns a new ParallelArray with the given element type holding
322 * all elements.
323 * @param elementType the type of the elements
324 * @return a new ParallelArray holding all elements
325 */
326 public ParallelArray<T> all(Class<? super T> elementType) {
327 return super.all(elementType);
328 }
329
330 /**
331 * Replaces elements with the results of applying the given transform
332 * to their current values.
333 * @param op the op
334 * @return this (to simplify use in expressions)
335 */
336 public ParallelArray<T> replaceWithMapping
337 (Op<? super T, ? extends T> op) {
338 super.replaceWithMapping(op);
339 return this;
340 }
341
342 /**
343 * Replaces elements with the results of applying the given
344 * mapping to their indices.
345 * @param op the op
346 * @return this (to simplify use in expressions)
347 */
348 public ParallelArray<T> replaceWithMappedIndex
349 (IntToObject<? extends T> op) {
350 super.replaceWithMappedIndex(op);
351 return this;
352 }
353
354 /**
355 * Replaces elements with the results of applying the given
356 * mapping to each index and current element value.
357 * @param op the op
358 * @return this (to simplify use in expressions)
359 */
360 public ParallelArray<T> replaceWithMappedIndex
361 (IntAndObjectToObject<? super T, ? extends T> op) {
362 super.replaceWithMappedIndex(op);
363 return this;
364 }
365
366 /**
367 * Replaces elements with the results of applying the given
368 * generator.
369 * @param generator the generator
370 * @return this (to simplify use in expressions)
371 */
372 public ParallelArray<T> replaceWithGeneratedValue
373 (Generator<? extends T> generator) {
374 super.replaceWithGeneratedValue(generator);
375 return this;
376 }
377
378 /**
379 * Replaces elements with the given value.
380 * @param value the value
381 * @return this (to simplify use in expressions)
382 */
383 public ParallelArray<T> replaceWithValue(T value) {
384 super.replaceWithValue(value);
385 return this;
386 }
387
388 /**
389 * Replaces elements with results of applying
390 * {@code op(thisElement, otherElement)}.
391 * @param other the other array
392 * @param combiner the combiner
393 * @return this (to simplify use in expressions)
394 */
395 public <V,W> ParallelArray<T> replaceWithMapping
396 (BinaryOp<? super T, ? super V, ? extends T> combiner,
397 ParallelArrayWithMapping<W,V> other) {
398 super.replaceWithMapping(combiner, other);
399 return this;
400 }
401
402 /**
403 * Replaces elements with results of applying
404 * {@code op(thisElement, otherElement)}.
405 * @param other the other array
406 * @param combiner the combiner
407 * @return this (to simplify use in expressions)
408 */
409 public ParallelArray<T> replaceWithMapping
410 (BinaryOp<T,T,T> combiner, T[] other) {
411 super.replaceWithMapping(combiner, other);
412 return this;
413 }
414
415 /**
416 * Returns the index of some element equal to given target,
417 * or -1 if not present.
418 * @param target the element to search for
419 * @return the index or -1 if not present
420 */
421 public int indexOf(T target) {
422 return super.indexOf(target);
423 }
424
425 /**
426 * Assuming this array is sorted, returns the index of an element
427 * equal to given target, or -1 if not present. If the array
428 * is not sorted, the results are undefined.
429 * @param target the element to search for
430 * @return the index or -1 if not present
431 */
432 public int binarySearch(T target) {
433 return super.binarySearch(target);
434 }
435
436 /**
437 * Assuming this array is sorted with respect to the given
438 * comparator, returns the index of an element equal to given
439 * target, or -1 if not present. If the array is not sorted, the
440 * results are undefined.
441 * @param target the element to search for
442 * @param comparator the comparator
443 * @return the index or -1 if not present
444 */
445 public int binarySearch(T target, Comparator<? super T> comparator) {
446 return super.binarySearch(target, comparator);
447 }
448
449 /**
450 * Returns summary statistics, using the given comparator
451 * to locate minimum and maximum elements.
452 * @param comparator the comparator to use for
453 * locating minimum and maximum elements
454 * @return the summary
455 */
456 public ParallelArray.SummaryStatistics<T> summary
457 (Comparator<? super T> comparator) {
458 return super.summary(comparator);
459 }
460
461 /**
462 * Returns summary statistics, assuming that all elements are
463 * Comparables.
464 * @return the summary
465 */
466 public ParallelArray.SummaryStatistics<T> summary() {
467 return super.summary();
468 }
469
470 /**
471 * Returns the minimum element, or null if empty.
472 * @param comparator the comparator
473 * @return minimum element, or null if empty
474 */
475 public T min(Comparator<? super T> comparator) {
476 return super.min(comparator);
477 }
478
479 /**
480 * Returns the minimum element, or null if empty,
481 * assuming that all elements are Comparables.
482 * @return minimum element, or null if empty
483 * @throws ClassCastException if any element is not Comparable
484 */
485 public T min() {
486 return super.min();
487 }
488
489 /**
490 * Returns the maximum element, or null if empty.
491 * @param comparator the comparator
492 * @return maximum element, or null if empty
493 */
494 public T max(Comparator<? super T> comparator) {
495 return super.max(comparator);
496 }
497
498 /**
499 * Returns the maximum element, or null if empty,
500 * assuming that all elements are Comparables.
501 * @return maximum element, or null if empty
502 * @throws ClassCastException if any element is not Comparable
503 */
504 public T max() {
505 return super.max();
506 }
507
508 /**
509 * Replaces each element with the running cumulation of applying
510 * the given reducer. For example, if the contents are the numbers
511 * {@code 1, 2, 3}, and the reducer operation adds numbers, then
512 * after invocation of this method, the contents would be {@code 1,
513 * 3, 6} (that is, {@code 1, 1+2, 1+2+3}).
514 * @param reducer the reducer
515 * @param base the result for an empty array
516 * @return this (to simplify use in expressions)
517 */
518 public ParallelArray<T> cumulate(Reducer<T> reducer, T base) {
519 super.cumulate(reducer, base);
520 return this;
521 }
522
523 /**
524 * Replaces each element with the cumulation of applying the given
525 * reducer to all previous values, and returns the total
526 * reduction. For example, if the contents are the numbers {@code 1,
527 * 2, 3}, and the reducer operation adds numbers, then after
528 * invocation of this method, the contents would be {@code 0, 1,
529 * 3} (that is, {@code 0, 0+1, 0+1+2}, and the return value
530 * would be 6 (that is, {@code 1+2+3}).
531 * @param reducer the reducer
532 * @param base the result for an empty array
533 * @return the total reduction
534 */
535 public T precumulate(Reducer<T> reducer, T base) {
536 return super.precumulate(reducer, base);
537 }
538
539 /**
540 * Sorts the array. Unlike Arrays.sort, this sort does
541 * not guarantee that elements with equal keys maintain their
542 * relative position in the array.
543 * @param comparator the comparator to use
544 * @return this (to simplify use in expressions)
545 */
546 public ParallelArray<T> sort(Comparator<? super T> comparator) {
547 super.sort(comparator);
548 return this;
549 }
550
551 /**
552 * Sorts the array, assuming all elements are Comparable. Unlike
553 * Arrays.sort, this sort does not guarantee that elements
554 * with equal keys maintain their relative position in the array.
555 * @return this (to simplify use in expressions)
556 * @throws ClassCastException if any element is not Comparable
557 */
558 public ParallelArray<T> sort() {
559 super.sort();
560 return this;
561 }
562
563 /**
564 * Returns a new ParallelArray containing only the non-null unique
565 * elements of this array (that is, without any duplicates), using
566 * each element's {@code equals} method to test for duplication.
567 * @return the new ParallelArray
568 */
569 public ParallelArray<T> allUniqueElements() {
570 return super.allUniqueElements();
571 }
572
573 /**
574 * Returns a new ParallelArray containing only the non-null unique
575 * elements of this array (that is, without any duplicates), using
576 * reference identity to test for duplication.
577 * @return the new ParallelArray
578 */
579 public ParallelArray<T> allNonidenticalElements() {
580 return super.allNonidenticalElements();
581 }
582
583 /**
584 * Removes from the array all elements for which the given
585 * selector holds.
586 * @param selector the selector
587 * @return this (to simplify use in expressions)
588 */
589 public ParallelArray<T> removeAll(Predicate<? super T> selector) {
590 OFPap<T> v = new OFPap<T>(ex, 0, fence, array, selector);
591 PAS.FJRemoveAllDriver f = new PAS.FJRemoveAllDriver(v, 0, fence);
592 ex.invoke(f);
593 removeSlotsAt(f.offset, fence);
594 return this;
595 }
596
597 /**
598 * Returns true if all elements at the same relative positions
599 * of this and other array are equal.
600 * @param other the other array
601 * @return true if equal
602 */
603 public <U,V> boolean hasAllEqualElements
604 (ParallelArrayWithMapping<U,V> other) {
605 return super.hasAllEqualElements(other);
606 }
607
608 /**
609 * Returns true if all elements at the same relative positions
610 * of this and other array are identical.
611 * @param other the other array
612 * @return true if equal
613 */
614 public <U,V> boolean hasAllIdenticalElements
615 (ParallelArrayWithMapping<U,V> other) {
616 return super.hasAllIdenticalElements(other);
617 }
618
619 /**
620 * Removes consecutive elements that are equal (or null),
621 * shifting others leftward, and possibly decreasing size. This
622 * method may be used after sorting to ensure that this
623 * ParallelArray contains a set of unique elements.
624 * @return this (to simplify use in expressions)
625 */
626 public ParallelArray<T> removeConsecutiveDuplicates() {
627 // Sequential implementation for now
628 int k = 0;
629 int n = fence;
630 Object[] arr = this.array;
631 Object last = null;
632 for (int i = k; i < n; ++i) {
633 Object x = arr[i];
634 if (x != null && (last == null || !last.equals(x)))
635 arr[k++] = last = x;
636 }
637 removeSlotsAt(k, n);
638 return this;
639 }
640
641 /**
642 * Removes null elements, shifting others leftward, and possibly
643 * decreasing size.
644 * @return this (to simplify use in expressions)
645 */
646 public ParallelArray<T> removeNulls() {
647 // Sequential implementation for now
648 int k = 0;
649 int n = fence;
650 Object[] arr = this.array;
651 for (int i = k; i < n; ++i) {
652 Object x = arr[i];
653 if (x != null)
654 arr[k++] = x;
655 }
656 removeSlotsAt(k, n);
657 return this;
658 }
659
660 /**
661 * Equivalent to {@code asList().addAll} but specialized for array
662 * arguments and likely to be more efficient.
663 * @param other the elements to add
664 * @return this (to simplify use in expressions)
665 */
666 public ParallelArray<T> addAll(T[] other) {
667 int csize = other.length;
668 int end = fence;
669 insertSlotsAt(end, csize);
670 System.arraycopy(other, 0, array, end, csize);
671 return this;
672 }
673
674 /**
675 * Appends all (possibly bounded, filtered, or mapped) elements of
676 * the given ParallelArray, resizing and/or reallocating this
677 * array if necessary.
678 * @param other the elements to add
679 * @return this (to simplify use in expressions)
680 */
681 public <V> ParallelArray<T> addAll
682 (ParallelArrayWithMapping<V,T> other) {
683 int end = fence;
684 if (other.hasFilter()) {
685 PAS.FJOAppendAllDriver r = new PAS.FJOAppendAllDriver
686 (other, end, array);
687 ex.invoke(r);
688 array = (T[])(r.results);
689 fence = end + r.resultSize;
690 }
691 else {
692 int csize = other.size();
693 insertSlotsAt(end, csize);
694 if (other.hasMap())
695 ex.invoke(new PAS.FJOMap(other, other.origin, other.fence,
696 null, array, end - other.origin));
697 else
698 System.arraycopy(other.array, 0, array, end, csize);
699 }
700 return this;
701 }
702
703 /**
704 * Returns an operation prefix that causes a method to
705 * operate only on the elements of the array between
706 * firstIndex (inclusive) and upperBound (exclusive).
707 * @param firstIndex the lower bound (inclusive)
708 * @param upperBound the upper bound (exclusive)
709 * @return operation prefix
710 */
711 public ParallelArrayWithBounds<T> withBounds
712 (int firstIndex, int upperBound) {
713 return super.withBounds(firstIndex, upperBound);
714 }
715
716 /**
717 * Returns an operation prefix that causes a method to operate
718 * only on the elements of the array for which the given selector
719 * returns true.
720 * @param selector the selector
721 * @return operation prefix
722 */
723 public ParallelArrayWithFilter<T> withFilter
724 (Predicate<? super T> selector) {
725 return super.withFilter(selector);
726 }
727
728 /**
729 * Returns an operation prefix that causes a method to operate
730 * only on elements for which the given binary selector returns
731 * true.
732 * @param selector the selector
733 * @return operation prefix
734 */
735 public <V,W> ParallelArrayWithFilter<T> withFilter
736 (BinaryPredicate<? super T, ? super V> selector,
737 ParallelArrayWithMapping<W,V> other) {
738 return super.withFilter(selector, other);
739 }
740
741 /**
742 * Returns an operation prefix that causes a method to operate
743 * only on elements for which the given indexed selector returns
744 * true.
745 * @param selector the selector
746 * @return operation prefix
747 */
748 public ParallelArrayWithFilter<T> withIndexedFilter
749 (IntAndObjectPredicate<? super T> selector) {
750 return super.withIndexedFilter(selector);
751 }
752
753 /**
754 * Returns an operation prefix that causes a method to operate
755 * on mapped elements of the array using the given op.
756 * @param op the op
757 * @return operation prefix
758 */
759 public <U> ParallelArrayWithMapping<T,U> withMapping
760 (Op<? super T, ? extends U> op) {
761 return super.withMapping(op);
762 }
763
764 /**
765 * Returns an operation prefix that causes a method to operate
766 * on mapped elements of the array using the given op.
767 * @param op the op
768 * @return operation prefix
769 */
770 public ParallelArrayWithDoubleMapping<T> withMapping
771 (ObjectToDouble<? super T> op) {
772 return super.withMapping(op);
773 }
774
775 /**
776 * Returns an operation prefix that causes a method to operate
777 * on mapped elements of the array using the given op.
778 * @param op the op
779 * @return operation prefix
780 */
781 public ParallelArrayWithLongMapping<T> withMapping
782 (ObjectToLong<? super T> op) {
783 return super.withMapping(op);
784 }
785
786 /**
787 * Returns an operation prefix that causes a method to operate
788 * on binary mappings of this array and the other array.
789 * @param combiner the combiner
790 * @param other the other array
791 * @return operation prefix
792 * @throws IllegalArgumentException if other array is a
793 * filtered view (all filters must precede all mappings)
794 */
795 public <U,V,W> ParallelArrayWithMapping<T,V> withMapping
796 (BinaryOp<? super T, ? super U, ? extends V> combiner,
797 ParallelArrayWithMapping<W,U> other) {
798 return super.withMapping(combiner, other);
799 }
800
801 /**
802 * Returns an operation prefix that causes a method to operate
803 * on binary mappings of this array and the other array.
804 * @param combiner the combiner
805 * @param other the other array
806 * @return operation prefix
807 * @throws IllegalArgumentException if other array is a
808 * filtered view (all filters must precede all mappings)
809 */
810 public <V> ParallelArrayWithMapping<T,V> withMapping
811 (ObjectAndDoubleToObject<? super T, ? extends V> combiner,
812 ParallelDoubleArrayWithDoubleMapping other) {
813 return super.withMapping(combiner, other);
814 }
815
816 /**
817 * Returns an operation prefix that causes a method to operate
818 * on binary mappings of this array and the other array.
819 * @param combiner the combiner
820 * @param other the other array
821 * @return operation prefix
822 * @throws IllegalArgumentException if other array is a
823 * filtered view (all filters must precede all mappings)
824 */
825 public <V> ParallelArrayWithMapping<T,V> withMapping
826 (ObjectAndLongToObject<? super T, ? extends V> combiner,
827 ParallelLongArrayWithLongMapping other) {
828 return super.withMapping(combiner, other);
829 }
830
831 /**
832 * Returns an operation prefix that causes a method to operate
833 * on binary mappings of this array and the other array.
834 * @param combiner the combiner
835 * @param other the other array
836 * @return operation prefix
837 * @throws IllegalArgumentException if other array is a
838 * filtered view (all filters must precede all mappings)
839 */
840 public <U,W> ParallelArrayWithDoubleMapping<T> withMapping
841 (ObjectAndObjectToDouble<? super T, ? super U> combiner,
842 ParallelArrayWithMapping<W,U> other) {
843 return super.withMapping(combiner, other);
844 }
845
846 /**
847 * Returns an operation prefix that causes a method to operate
848 * on binary mappings of this array and the other array.
849 * @param combiner the combiner
850 * @param other the other array
851 * @return operation prefix
852 * @throws IllegalArgumentException if other array is a
853 * filtered view (all filters must precede all mappings)
854 */
855 public ParallelArrayWithDoubleMapping<T> withMapping
856 (ObjectAndDoubleToDouble<? super T> combiner,
857 ParallelDoubleArrayWithDoubleMapping other) {
858 return super.withMapping(combiner, other);
859 }
860
861 /**
862 * Returns an operation prefix that causes a method to operate
863 * on binary mappings of this array and the other array.
864 * @param combiner the combiner
865 * @param other the other array
866 * @return operation prefix
867 * @throws IllegalArgumentException if other array is a
868 * filtered view (all filters must precede all mappings)
869 */
870 public ParallelArrayWithDoubleMapping<T> withMapping
871 (ObjectAndLongToDouble<? super T> combiner,
872 ParallelLongArrayWithLongMapping other) {
873 return super.withMapping(combiner, other);
874 }
875
876 /**
877 * Returns an operation prefix that causes a method to operate
878 * on binary mappings of this array and the other array.
879 * @param combiner the combiner
880 * @param other the other array
881 * @return operation prefix
882 * @throws IllegalArgumentException if other array is a
883 * filtered view (all filters must precede all mappings)
884 */
885 public <U,W> ParallelArrayWithLongMapping<T> withMapping
886 (ObjectAndObjectToLong<? super T, ? super U> combiner,
887 ParallelArrayWithMapping<W,U> other) {
888 return super.withMapping(combiner, other);
889 }
890
891 /**
892 * Returns an operation prefix that causes a method to operate
893 * on binary mappings of this array and the other array.
894 * @param combiner the combiner
895 * @param other the other array
896 * @return operation prefix
897 * @throws IllegalArgumentException if other array is a
898 * filtered view (all filters must precede all mappings)
899 */
900 public ParallelArrayWithLongMapping<T> withMapping
901 (ObjectAndDoubleToLong<? super T> combiner,
902 ParallelDoubleArrayWithDoubleMapping other) {
903 return super.withMapping(combiner, other);
904 }
905
906 /**
907 * Returns an operation prefix that causes a method to operate
908 * on binary mappings of this array and the other array.
909 * @param combiner the combiner
910 * @param other the other array
911 * @return operation prefix
912 * @throws IllegalArgumentException if other array is a
913 * filtered view (all filters must precede all mappings)
914 */
915 public ParallelArrayWithLongMapping<T> withMapping
916 (ObjectAndLongToLong<? super T> combiner,
917 ParallelLongArrayWithLongMapping other) {
918 return super.withMapping(combiner, other);
919 }
920
921 /**
922 * Returns an operation prefix that causes a method to operate on
923 * mappings of this array using the given mapper that accepts as
924 * arguments an element's current index and value, and produces a
925 * new value. Index-based mappings allow parallel computation of
926 * many common array operations. For example, you could create
927 * function to average the values at the same index of multiple
928 * arrays and apply it using this method.
929 * @param mapper the mapper
930 * @return operation prefix
931 */
932 public <U> ParallelArrayWithMapping<T,U> withIndexedMapping
933 (IntAndObjectToObject<? super T, ? extends U> mapper) {
934 return super.withIndexedMapping(mapper);
935 }
936
937 /**
938 * Returns an operation prefix that causes a method to operate on
939 * mappings of this array using the given mapper that accepts as
940 * arguments an element's current index and value, and produces a
941 * new value.
942 * @param mapper the mapper
943 * @return operation prefix
944 */
945 public ParallelArrayWithDoubleMapping<T> withIndexedMapping
946 (IntAndObjectToDouble<? super T> mapper) {
947 return super.withIndexedMapping(mapper);
948 }
949
950 /**
951 * Returns an operation prefix that causes a method to operate on
952 * mappings of this array using the given mapper that accepts as
953 * arguments an element's current index and value, and produces a
954 * new value.
955 * @param mapper the mapper
956 * @return operation prefix
957 */
958 public ParallelArrayWithLongMapping<T> withIndexedMapping
959 (IntAndObjectToLong<? super T> mapper) {
960 return super.withIndexedMapping(mapper);
961 }
962
963 /**
964 * Returns an iterator stepping through each element of the array
965 * up to the current limit. This iterator does <em>not</em>
966 * support the remove operation. However, a full
967 * {@code ListIterator} supporting add, remove, and set
968 * operations is available via {@link #asList}.
969 * @return an iterator stepping through each element
970 */
971 public Iterator<T> iterator() {
972 return new ParallelArrayIterator<T>(array, fence);
973 }
974
975 static final class ParallelArrayIterator<T> implements Iterator<T> {
976 int cursor;
977 final T[] arr;
978 final int hi;
979 ParallelArrayIterator(T[] a, int limit) { arr = a; hi = limit; }
980 public boolean hasNext() { return cursor < hi; }
981 public T next() {
982 if (cursor >= hi)
983 throw new NoSuchElementException();
984 return arr[cursor++];
985 }
986 public void remove() {
987 throw new UnsupportedOperationException();
988 }
989 }
990
991 // List support
992
993 /**
994 * Returns a view of this ParallelArray as a List. This List has
995 * the same structural and performance characteristics as {@link
996 * ArrayList}, and may be used to modify, replace or extend the
997 * bounds of the array underlying this ParallelArray. The methods
998 * supported by this list view are <em>not</em> in general
999 * implemented as parallel operations. This list is also not
1000 * itself thread-safe. In particular, performing list updates
1001 * while other parallel operations are in progress has undefined
1002 * (and surely undesired) effects.
1003 * @return a list view
1004 */
1005 public List<T> asList() {
1006 AsList lv = listView;
1007 if (lv == null)
1008 listView = lv = new AsList();
1009 return lv;
1010 }
1011
1012 /**
1013 * Returns the effective size of the underlying array. The
1014 * effective size is the current limit, if used (see {@link
1015 * #setLimit}), or the length of the array otherwise.
1016 * @return the effective size of array
1017 */
1018 public int size() { return fence; }
1019
1020 /**
1021 * Returns the element of the array at the given index.
1022 * @param i the index
1023 * @return the element of the array at the given index
1024 */
1025 public T get(int i) { return array[i]; }
1026
1027 /**
1028 * Sets the element of the array at the given index to the given value.
1029 * @param i the index
1030 * @param x the value
1031 */
1032 public void set(int i, T x) { array[i] = x; }
1033
1034 /**
1035 * Returns the underlying array used for computations.
1036 * @return the array
1037 */
1038 public T[] getArray() { return array; }
1039
1040 /**
1041 * Equivalent to {@code asList().toString()}.
1042 * @return a string representation
1043 */
1044 public String toString() {
1045 return asList().toString();
1046 }
1047
1048
1049 /**
1050 * Ensures that the underlying array can be accessed up to the
1051 * given upper bound, reallocating and copying the underlying
1052 * array to expand if necessary. Or, if the given limit is less
1053 * than the length of the underlying array, causes computations to
1054 * ignore elements past the given limit.
1055 * @param newLimit the new upper bound
1056 * @throws IllegalArgumentException if newLimit less than zero
1057 */
1058 public final void setLimit(int newLimit) {
1059 if (newLimit < 0)
1060 throw new IllegalArgumentException();
1061 int cap = array.length;
1062 if (newLimit > cap)
1063 resizeArray(newLimit);
1064 fence = newLimit;
1065 }
1066
1067 final void replaceElementsWith(T[] a) {
1068 System.arraycopy(a, 0, array, 0, a.length);
1069 fence = a.length;
1070 }
1071
1072 final void resizeArray(int newCap) {
1073 int cap = array.length;
1074 if (newCap > cap) {
1075 Class elementType = array.getClass().getComponentType();
1076 T[] a =(T[])Array.newInstance(elementType, newCap);
1077 System.arraycopy(array, 0, a, 0, cap);
1078 array = a;
1079 }
1080 }
1081
1082 final void insertElementAt(int index, T e) {
1083 int hi = fence++;
1084 if (hi >= array.length)
1085 resizeArray((hi * 3)/2 + 1);
1086 if (hi > index)
1087 System.arraycopy(array, index, array, index+1, hi - index);
1088 array[index] = e;
1089 }
1090
1091 final void appendElement(T e) {
1092 int hi = fence++;
1093 if (hi >= array.length)
1094 resizeArray((hi * 3)/2 + 1);
1095 array[hi] = e;
1096 }
1097
1098 /**
1099 * Makes len slots available at index.
1100 */
1101 final void insertSlotsAt(int index, int len) {
1102 if (len <= 0)
1103 return;
1104 int cap = array.length;
1105 int newSize = fence + len;
1106 if (cap < newSize) {
1107 cap = (cap * 3)/2 + 1;
1108 if (cap < newSize)
1109 cap = newSize;
1110 resizeArray(cap);
1111 }
1112 if (index < fence)
1113 System.arraycopy(array, index, array, index + len, fence - index);
1114 fence = newSize;
1115 }
1116
1117 final void removeSlotAt(int index) {
1118 System.arraycopy(array, index + 1, array, index, fence - index - 1);
1119 array[--fence] = null;
1120 }
1121
1122 final void removeSlotsAt(int fromIndex, int toIndex) {
1123 if (fromIndex < toIndex) {
1124 int size = fence;
1125 System.arraycopy(array, toIndex, array, fromIndex, size - toIndex);
1126 int newSize = size - (toIndex - fromIndex);
1127 fence = newSize;
1128 while (size > newSize)
1129 array[--size] = null;
1130 }
1131 }
1132
1133 final int seqIndexOf(Object target) {
1134 T[] arr = array;
1135 int end = fence;
1136 if (target == null) {
1137 for (int i = 0; i < end; i++)
1138 if (arr[i] == null)
1139 return i;
1140 } else {
1141 for (int i = 0; i < end; i++)
1142 if (target.equals(arr[i]))
1143 return i;
1144 }
1145 return -1;
1146 }
1147
1148 final int seqLastIndexOf(Object target) {
1149 T[] arr = array;
1150 int last = fence - 1;
1151 if (target == null) {
1152 for (int i = last; i >= 0; i--)
1153 if (arr[i] == null)
1154 return i;
1155 } else {
1156 for (int i = last; i >= 0; i--)
1157 if (target.equals(arr[i]))
1158 return i;
1159 }
1160 return -1;
1161 }
1162
1163 final class ListIter implements ListIterator<T> {
1164 int cursor;
1165 int lastRet;
1166 T[] arr; // cache array and bound
1167 int hi;
1168 ListIter(int lo) {
1169 this.cursor = lo;
1170 this.lastRet = -1;
1171 this.arr = ParallelArray.this.array;
1172 this.hi = ParallelArray.this.fence;
1173 }
1174
1175 public boolean hasNext() {
1176 return cursor < hi;
1177 }
1178
1179 public T next() {
1180 int i = cursor;
1181 if (i < 0 || i >= hi)
1182 throw new NoSuchElementException();
1183 T next = arr[i];
1184 lastRet = i;
1185 cursor = i + 1;
1186 return next;
1187 }
1188
1189 public void remove() {
1190 int k = lastRet;
1191 if (k < 0)
1192 throw new IllegalStateException();
1193 ParallelArray.this.removeSlotAt(k);
1194 hi = ParallelArray.this.fence;
1195 if (lastRet < cursor)
1196 cursor--;
1197 lastRet = -1;
1198 }
1199
1200 public boolean hasPrevious() {
1201 return cursor > 0;
1202 }
1203
1204 public T previous() {
1205 int i = cursor - 1;
1206 if (i < 0 || i >= hi)
1207 throw new NoSuchElementException();
1208 T previous = arr[i];
1209 lastRet = cursor = i;
1210 return previous;
1211 }
1212
1213 public int nextIndex() {
1214 return cursor;
1215 }
1216
1217 public int previousIndex() {
1218 return cursor - 1;
1219 }
1220
1221 public void set(T e) {
1222 int i = lastRet;
1223 if (i < 0 || i >= hi)
1224 throw new NoSuchElementException();
1225 arr[i] = e;
1226 }
1227
1228 public void add(T e) {
1229 int i = cursor;
1230 ParallelArray.this.insertElementAt(i, e);
1231 arr = ParallelArray.this.array;
1232 hi = ParallelArray.this.fence;
1233 lastRet = -1;
1234 cursor = i + 1;
1235 }
1236 }
1237
1238 final class AsList extends AbstractList<T> implements RandomAccess {
1239 public T get(int i) {
1240 if (i >= fence)
1241 throw new IndexOutOfBoundsException();
1242 return array[i];
1243 }
1244
1245 public T set(int i, T x) {
1246 if (i >= fence)
1247 throw new IndexOutOfBoundsException();
1248 T[] arr = array;
1249 T t = arr[i];
1250 arr[i] = x;
1251 return t;
1252 }
1253
1254 public boolean isEmpty() {
1255 return fence == 0;
1256 }
1257
1258 public int size() {
1259 return fence;
1260 }
1261
1262 public Iterator<T> iterator() {
1263 return new ListIter(0);
1264 }
1265
1266 public ListIterator<T> listIterator() {
1267 return new ListIter(0);
1268 }
1269
1270 public ListIterator<T> listIterator(int index) {
1271 if (index < 0 || index > fence)
1272 throw new IndexOutOfBoundsException();
1273 return new ListIter(index);
1274 }
1275
1276 public boolean add(T e) {
1277 appendElement(e);
1278 return true;
1279 }
1280
1281 public void add(int index, T e) {
1282 if (index < 0 || index > fence)
1283 throw new IndexOutOfBoundsException();
1284 insertElementAt(index, e);
1285 }
1286
1287 public boolean addAll(Collection<? extends T> c) {
1288 int csize = c.size();
1289 if (csize == 0)
1290 return false;
1291 int hi = fence;
1292 setLimit(hi + csize);
1293 T[] arr = array;
1294 for (T e : c)
1295 arr[hi++] = e;
1296 return true;
1297 }
1298
1299 public boolean addAll(int index, Collection<? extends T> c) {
1300 if (index < 0 || index > fence)
1301 throw new IndexOutOfBoundsException();
1302 int csize = c.size();
1303 if (csize == 0)
1304 return false;
1305 insertSlotsAt(index, csize);
1306 T[] arr = array;
1307 for (T e : c)
1308 arr[index++] = e;
1309 return true;
1310 }
1311
1312 public void clear() {
1313 T[] arr = array;
1314 for (int i = 0; i < fence; ++i)
1315 arr[i] = null;
1316 fence = 0;
1317 }
1318
1319 public boolean remove(Object o) {
1320 int idx = seqIndexOf(o);
1321 if (idx < 0)
1322 return false;
1323 removeSlotAt(idx);
1324 return true;
1325 }
1326
1327 public T remove(int index) {
1328 T oldValue = get(index);
1329 removeSlotAt(index);
1330 return oldValue;
1331 }
1332
1333 public void removeRange(int fromIndex, int toIndex) {
1334 removeSlotsAt(fromIndex, toIndex);
1335 }
1336
1337 public boolean contains(Object o) {
1338 return seqIndexOf(o) >= 0;
1339 }
1340
1341 public int indexOf(Object o) {
1342 return seqIndexOf(o);
1343 }
1344
1345 public int lastIndexOf(Object o) {
1346 return seqLastIndexOf(o);
1347 }
1348
1349 public Object[] toArray() {
1350 int len = fence;
1351 Object[] a = new Object[len];
1352 System.arraycopy(array, 0, a, 0, len);
1353 return a;
1354 }
1355
1356 public <V> V[] toArray(V[] a) {
1357 int len = fence;
1358 if (a.length < len) {
1359 Class elementType = a.getClass().getComponentType();
1360 a =(V[])Array.newInstance(elementType, len);
1361 }
1362 System.arraycopy(array, 0, a, 0, len);
1363 if (a.length > len)
1364 a[len] = null;
1365 return a;
1366 }
1367 }
1368
1369 }