ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/extra166y/ParallelArray.java
Revision: 1.17
Committed: Mon Nov 4 00:00:39 2013 UTC (10 years, 6 months ago) by jsr166
Branch: MAIN
Changes since 1.16: +1 -1 lines
Log Message:
stop using denigrated: Foo bar[];

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