ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/extra166y/ParallelArray.java
Revision: 1.11
Committed: Tue Feb 5 17:35:37 2013 UTC (11 years, 2 months ago) by jsr166
Branch: MAIN
Changes since 1.10: +1 -1 lines
Log Message:
javadoc style

File Contents

# User Rev Content
1 dl 1.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 jsr166 1.2 * http://creativecommons.org/publicdomain/zero/1.0/
5 dl 1.1 */
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 jsr166 1.6 * <p>A ParallelArray is constructed by allocating, using, or copying
26 dl 1.1 * 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 jsr166 1.6 * <p>The ForkJoinPool used to construct a ParallelArray can be
35 dl 1.1 * 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 jsr166 1.9 * {@link ParallelArray#asList}. The {@code asList} view allows
46 dl 1.1 * 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 jsr166 1.9 * Collection's {@code toArray} method. The effects of mutative
53     * {@code asList} operations may also be achieved directly using
54 dl 1.1 * 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 jsr166 1.9 * ({@code int}, {@code short}, etc). And similarly use a
65     * ParallelDoubleArray for {@code float} data. (Further
66 dl 1.1 * specializations for these other types would add clutter without
67     * significantly improving performance beyond that of the Long and
68     * Double versions.)
69     *
70 jsr166 1.6 * <p>Most usages of ParallelArray involve sets of operations prefixed
71 dl 1.1 * with range bounds, filters, and mappings (including mappings that
72     * combine elements from other ParallelArrays), using
73 jsr166 1.9 * {@code withBounds}, {@code withFilter}, and {@code withMapping},
74 dl 1.1 * respectively. For example,
75 jsr166 1.9 * {@code aParallelArray.withFilter(aPredicate).all()} creates a new
76 dl 1.1 * ParallelArray containing only those elements matching the
77     * predicate. And for ParallelLongArrays a, b, and c,
78 jsr166 1.9 * {@code a.withMapping(CommonOps.longAdder(),b).withMapping(CommonOps.longAdder(),c).min()}
79 dl 1.1 * 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 jsr166 1.9 * dynamically enforced. For example, {@code pa.withMapping(op,
91     * pb.withFilter(f))} will compile but throw an exception upon
92 dl 1.1 * 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 jsr166 1.9 * {@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 dl 1.1 * useful when combining such expressions.
101     *
102 jsr166 1.9 * <p>This class includes some reductions, such as {@code min}, that
103 dl 1.1 * are commonly useful for most element types, as well as a combined
104 jsr166 1.9 * version, {@code summary}, that computes all of them in a single
105 dl 1.1 * 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 jsr166 1.9 * given a (fictional) {@code Student} class:
121 dl 1.1 *
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 jsr166 1.4 /** Returns the number of elements */
276 dl 1.1 public int size();
277 jsr166 1.4 /** Returns the minimum element, or null if empty */
278 dl 1.1 public T min();
279 jsr166 1.4 /** Returns the maximum element, or null if empty */
280 dl 1.1 public T max();
281 jsr166 1.4 /** Returns the index of the minimum element, or -1 if empty */
282 dl 1.1 public int indexOfMin();
283 jsr166 1.4 /** Returns the index of the maximum element, or -1 if empty */
284 dl 1.1 public int indexOfMax();
285     }
286    
287     /**
288 jsr166 1.4 * Returns the executor used for computations.
289 dl 1.1 * @return the executor
290     */
291     public ForkJoinPool getExecutor() { return ex; }
292    
293     /**
294 jsr166 1.8 * Applies the given procedure to elements.
295 dl 1.1 * @param procedure the procedure
296     */
297     public void apply(Procedure<? super T> procedure) {
298     super.apply(procedure);
299     }
300    
301     /**
302 jsr166 1.8 * Returns reduction of elements.
303 dl 1.1 * @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 jsr166 1.8 * Returns a new ParallelArray holding all elements.
313 dl 1.1 * @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 jsr166 1.8 * all elements.
322 dl 1.1 * @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 jsr166 1.8 * mapping to each index and current element value.
356 dl 1.1 * @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 jsr166 1.9 * {@code op(thisElement, otherElement)}.
390 dl 1.1 * @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 jsr166 1.9 * {@code op(thisElement, otherElement)}.
404 dl 1.1 * @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 jsr166 1.8 * or -1 if not present.
417 dl 1.1 * @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 jsr166 1.7 * @return the summary
454 dl 1.1 */
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 jsr166 1.7 * Comparables.
463     * @return the summary
464 dl 1.1 */
465     public ParallelArray.SummaryStatistics<T> summary() {
466     return super.summary();
467     }
468    
469     /**
470 jsr166 1.7 * Returns the minimum element, or null if empty.
471 dl 1.1 * @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 jsr166 1.7 * assuming that all elements are Comparables.
481 dl 1.1 * @return minimum element, or null if empty
482 jsr166 1.7 * @throws ClassCastException if any element is not Comparable
483 dl 1.1 */
484     public T min() {
485     return super.min();
486     }
487    
488     /**
489 jsr166 1.7 * Returns the maximum element, or null if empty.
490 dl 1.1 * @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 jsr166 1.7 * Returns the maximum element, or null if empty,
499     * assuming that all elements are Comparables.
500 dl 1.1 * @return maximum element, or null if empty
501 jsr166 1.7 * @throws ClassCastException if any element is not Comparable
502 dl 1.1 */
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 jsr166 1.9 * {@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 dl 1.1 * @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 jsr166 1.9 * 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 dl 1.1 * @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 jsr166 1.10 return super.precumulate(reducer, base);
536 dl 1.1 }
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 jsr166 1.7 * @throws ClassCastException if any element is not Comparable
555 dl 1.1 * @return this (to simplify use in expressions)
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 jsr166 1.9 * each element's {@code equals} method to test for duplication.
566 dl 1.1 * @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 jsr166 1.9 * Equivalent to {@code asList().addAll} but specialized for array
661 dl 1.1 * arguments and likely to be more efficient.
662     * @param other the elements to add
663     * @return this (to simplify use in expressions)
664     */
665 jsr166 1.3 public ParallelArray<T> addAll(T[] other) {
666 dl 1.1 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 jsr166 1.7 * returns true.
719 dl 1.1 * @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 jsr166 1.7 * true.
731 dl 1.1 * @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 jsr166 1.7 * true.
744 dl 1.1 * @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 jsr166 1.7 * filtered view (all filters must precede all mappings)
793 dl 1.1 */
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 jsr166 1.7 * filtered view (all filters must precede all mappings)
808 dl 1.1 */
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 jsr166 1.7 * filtered view (all filters must precede all mappings)
823 dl 1.1 */
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 jsr166 1.7 * filtered view (all filters must precede all mappings)
838 dl 1.1 */
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 jsr166 1.7 * filtered view (all filters must precede all mappings)
853 dl 1.1 */
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 jsr166 1.7 * filtered view (all filters must precede all mappings)
868 dl 1.1 */
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 jsr166 1.7 * filtered view (all filters must precede all mappings)
883 dl 1.1 */
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 jsr166 1.7 * filtered view (all filters must precede all mappings)
898 dl 1.1 */
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 jsr166 1.7 * filtered view (all filters must precede all mappings)
913 dl 1.1 */
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 jsr166 1.9 * {@code ListIterator} supporting add, remove, and set
967 dl 1.1 * operations is available via {@link #asList}.
968 jsr166 1.7 * @return an iterator stepping through each element
969 dl 1.1 */
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 jsr166 1.7 * Returns the element of the array at the given index.
1021 dl 1.1 * @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 jsr166 1.7 * Sets the element of the array at the given index to the given value.
1028 dl 1.1 * @param i the index
1029     * @param x the value
1030     */
1031     public void set(int i, T x) { array[i] = x; }
1032    
1033     /**
1034 jsr166 1.7 * Returns the underlying array used for computations.
1035 dl 1.1 * @return the array
1036     */
1037     public T[] getArray() { return array; }
1038    
1039     /**
1040 jsr166 1.11 * Equivalent to {@code asList().toString()}.
1041 dl 1.1 * @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 jsr166 1.7 * @throws IllegalArgumentException if newLimit less than zero
1056 dl 1.1 */
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 jsr166 1.4 * Makes len slots available at index.
1099 dl 1.1 */
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     }