ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166y/forkjoin/PAS.java
Revision: 1.3
Committed: Thu Jan 17 23:25:35 2008 UTC (16 years, 5 months ago) by dl
Branch: MAIN
Changes since 1.2: +437 -162 lines
Log Message:
Promote prefix classes to top level; simplify usages in expressions

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/licenses/publicdomain
5 */
6
7 package jsr166y.forkjoin;
8 import static jsr166y.forkjoin.Ops.*;
9 import java.util.*;
10 import java.util.concurrent.atomic.*;
11 import java.lang.reflect.Array;
12
13 /**
14 * Shared internal support for ParallelArray and specializations.
15 *
16 * The majority of operations take a similar form: Class Prefix serves
17 * as the base of prefix classes, also serving as parameters for
18 * single-step fork+join parallel tasks using subclasses of FJBase and
19 * FJSearchBase. Prefix instances hold the non-operation-specific
20 * control and data accessors needed for a task as a whole (as opposed
21 * to subtasks), and also house some of the leaf methods that perform
22 * the actual array processing. The leaf methods are for the most part
23 * just plain array operations. They are boringly repetitive in order
24 * to flatten out and minimize inner-loop overhead, as well as to
25 * minimize call-chain depth. This makes it more likely that dynamic
26 * compilers can go the rest of the way, and hoist per-element method
27 * call dispatch, so we have a good chance to speed up processing via
28 * parallelism rather than lose due to dispatch and indirection
29 * overhead. The dispatching from Prefix to FJ and back is otherwise
30 * Visitor-pattern-like, allowing the basic parallelism control for
31 * most FJ tasks to be centralized.
32 *
33 * Operations taking forms other than single-step fork/join
34 * (SelectAll, sort, scan, etc) are organized in basically similar
35 * ways, but don't always follow as regular patterns.
36 *
37 * Note the extensive use of raw types. Arrays and generics do not
38 * work together very well. It is more manageable to avoid them here,
39 * and let the public classes perform casts in and out to the
40 * processing here.
41 */
42 class PAS {
43 private PAS() {} // all-static, non-instantiable
44
45 /** Global default executor */
46 private static volatile ForkJoinPool defaultExecutor;
47 /** Lock for on-demand initialization of defaultExecutor */
48 private static final Object poolLock = new Object();
49
50 static ForkJoinExecutor defaultExecutor() {
51 ForkJoinPool p = defaultExecutor; // double-check
52 if (p == null) {
53 synchronized(poolLock) {
54 p = defaultExecutor;
55 if (p == null) {
56 // use ceil(7/8 * ncpus)
57 int nprocs = Runtime.getRuntime().availableProcessors();
58 int nthreads = nprocs - (nprocs >>> 3);
59 defaultExecutor = p = new ForkJoinPool(nthreads);
60 }
61 }
62 }
63 return p;
64 }
65
66 /**
67 * Base of prefix classes.
68 */
69 static abstract class Prefix {
70 final ForkJoinExecutor ex;
71 final int firstIndex;
72 int upperBound;
73 int threshold; // subtask split control; computed on first use
74
75 Prefix(ForkJoinExecutor ex, int firstIndex, int upperBound) {
76 this.ex = ex;
77 this.firstIndex = firstIndex;
78 this.upperBound = upperBound;
79 int n = upperBound - firstIndex;
80 int p = ex.getParallelismLevel();
81 }
82
83 /**
84 * Returns size threshold for splitting into subtask. By
85 * default, uses about 8 times as many tasks as threads
86 */
87 final int getThreshold() {
88 int t = threshold;
89 if (t == 0) {
90 int n = upperBound - firstIndex;
91 int p = ex.getParallelismLevel();
92 threshold = t = (p > 1) ? (1 + n / (p << 3)) : n;
93 }
94 return t;
95 }
96
97 /**
98 * Access methods for ref, double, long. Checking for
99 * null/false return is used as a sort of type test. These
100 * are used to avoid duplication in non-performance-critical
101 * aspects of control, as well as to provide a simple default
102 * mechanism for extensions.
103 */
104 Object[] ogetArray() { return null; }
105 double[] dgetArray() { return null; }
106 long[] lgetArray() { return null; }
107 boolean hasMap() { return false; }
108 boolean hasFilter() { return false; }
109 boolean isSelected(int index) { return true; }
110 Object oget(int index) { return null; }
111 double dget(int index) { return 0.0; }
112 long lget(int index) { return 0L; }
113
114 /*
115 * Leaf methods for FJ tasks. Default versions use isSelected,
116 * oget, dget, etc. But most are overridden in most concrete
117 * classes to avoid per-element dispatching.
118 */
119 void leafApply(int lo, int hi, Procedure procedure) {
120 for (int i = lo; i < hi; ++i)
121 if (isSelected(i))
122 procedure.op(oget(i));
123 }
124
125 void leafApply(int lo, int hi, DoubleProcedure procedure) {
126 for (int i = lo; i < hi; ++i)
127 if (isSelected(i))
128 procedure.op(dget(i));
129 }
130
131 void leafApply(int lo, int hi, LongProcedure procedure) {
132 for (int i = lo; i < hi; ++i)
133 if (isSelected(i))
134 procedure.op(lget(i));
135 }
136
137 Object leafReduce(int lo, int hi, Reducer reducer, Object base) {
138 boolean gotFirst = false;
139 Object r = base;
140 for (int i = lo; i < hi; ++i) {
141 if (isSelected(i)) {
142 Object x = oget(i);
143 if (!gotFirst) {
144 gotFirst = true;
145 r = x;
146 }
147 else
148 r = reducer.op(r, x);
149 }
150 }
151 return r;
152 }
153
154 double leafReduce(int lo, int hi, DoubleReducer reducer, double base) {
155 boolean gotFirst = false;
156 double r = base;
157 for (int i = lo; i < hi; ++i) {
158 if (isSelected(i)) {
159 double x = dget(i);
160 if (!gotFirst) {
161 gotFirst = true;
162 r = x;
163 }
164 else
165 r = reducer.op(r, x);
166 }
167 }
168 return r;
169 }
170
171 long leafReduce(int lo, int hi, LongReducer reducer, long base) {
172 boolean gotFirst = false;
173 long r = base;
174 for (int i = lo; i < hi; ++i) {
175 if (isSelected(i)) {
176 long x = lget(i);
177 if (!gotFirst) {
178 gotFirst = true;
179 r = x;
180 }
181 else
182 r = reducer.op(r, x);
183 }
184 }
185 return r;
186 }
187
188 // copy elements, ignoring selector, but applying mapping
189 void leafTransfer(int lo, int hi, Object[] dest, int offset) {
190 for (int i = lo; i < hi; ++i)
191 dest[offset++] = oget(i);
192 }
193
194 void leafTransfer(int lo, int hi, double[] dest, int offset) {
195 for (int i = lo; i < hi; ++i)
196 dest[offset++] = dget(i);
197 }
198
199 void leafTransfer(int lo, int hi, long[] dest, int offset) {
200 for (int i = lo; i < hi; ++i)
201 dest[offset++] = lget(i);
202 }
203
204 // copy elements indexed in indices[loIdx..hiIdx], ignoring
205 // selector, but applying mapping
206 void leafTransferByIndex(int[] indices, int loIdx, int hiIdx,
207 Object[] dest, int offset) {
208 for (int i = loIdx; i < hiIdx; ++i)
209 dest[offset++] = oget(indices[i]);
210 }
211
212 void leafTransferByIndex(int[] indices, int loIdx, int hiIdx,
213 double[] dest, int offset) {
214 for (int i = loIdx; i < hiIdx; ++i)
215 dest[offset++] = dget(indices[i]);
216 }
217
218 void leafTransferByIndex(int[] indices, int loIdx, int hiIdx,
219 long[] dest, int offset) {
220 for (int i = loIdx; i < hiIdx; ++i)
221 dest[offset++] = lget(indices[i]);
222 }
223
224 // add indices of selected elements to index array; return #added
225 abstract int leafIndexSelected(int lo, int hi, boolean positive,
226 int[] indices);
227
228 // move selected elements to indices starting at offset,
229 // return final offset
230 abstract int leafMoveSelected(int lo, int hi, int offset,
231 boolean positive);
232
233 // move elements indexed by indices[loIdx...hiIdx] starting
234 // at given offset
235 abstract void leafMoveByIndex(int[] indices, int loIdx,
236 int hiIdx, int offset);
237
238 /**
239 * Shared support for select/map all -- probe filter, map, and
240 * type to start selection driver, or do parallel mapping, or
241 * just copy,
242 */
243 final Object[] allObjects(Class elementType) {
244 if (hasFilter()) {
245 if (elementType == null) {
246 if (!hasMap())
247 elementType = ogetArray().getClass().getComponentType();
248 else
249 elementType = Object.class;
250 }
251 PAS.FJOSelectAllDriver r = new PAS.FJOSelectAllDriver
252 (this, elementType);
253 ex.invoke(r);
254 return r.results;
255 }
256 else {
257 int n = upperBound - firstIndex;
258 Object[] dest;
259 if (hasMap()) {
260 if (elementType == null)
261 dest = new Object[n];
262 else
263 dest = (Object[])Array.newInstance(elementType, n);
264 ex.invoke(new PAS.FJOMap(this, firstIndex, upperBound,
265 null, dest, firstIndex));
266 }
267 else {
268 Object[] array = ogetArray();
269 if (elementType == null)
270 elementType = array.getClass().getComponentType();
271 dest = (Object[])Array.newInstance(elementType, n);
272 System.arraycopy(array, firstIndex, dest, 0, n);
273 }
274 return dest;
275 }
276 }
277
278 final double[] allDoubles() {
279 if (hasFilter()) {
280 PAS.FJDSelectAllDriver r = new PAS.FJDSelectAllDriver(this);
281 ex.invoke(r);
282 return r.results;
283 }
284 else {
285 int n = upperBound - firstIndex;
286 double[] dest = new double[n];
287 if (hasMap()) {
288 ex.invoke(new PAS.FJDMap(this, firstIndex, upperBound,
289 null, dest, firstIndex));
290 }
291 else {
292 double[] array = dgetArray();
293 System.arraycopy(array, firstIndex, dest, 0, n);
294 }
295 return dest;
296 }
297 }
298
299 final long[] allLongs() {
300 if (hasFilter()) {
301 PAS.FJLSelectAllDriver r = new PAS.FJLSelectAllDriver(this);
302 ex.invoke(r);
303 return r.results;
304 }
305 else {
306 int n = upperBound - firstIndex;
307 long[] dest = new long[n];
308 if (hasMap()) {
309 ex.invoke(new PAS.FJLMap(this, firstIndex, upperBound,
310 null, dest, firstIndex));
311 }
312 else {
313 long[] array = lgetArray();
314 System.arraycopy(array, firstIndex, dest, 0, n);
315 }
316 return dest;
317 }
318 }
319
320 // Iterator support
321 class SequentiallyAsDouble implements Iterable<Double> {
322 public Iterator<Double> iterator() {
323 if (hasFilter())
324 return new FilteredAsDoubleIterator();
325 else
326 return new UnfilteredAsDoubleIterator();
327 }
328 }
329
330 class UnfilteredAsDoubleIterator implements Iterator<Double> {
331 int cursor = firstIndex;
332 public boolean hasNext() { return cursor < upperBound; }
333 public Double next() {
334 if (cursor >= upperBound)
335 throw new NoSuchElementException();
336 return Double.valueOf(dget(cursor++));
337 }
338 public void remove() {
339 throw new UnsupportedOperationException();
340 }
341 }
342
343 class FilteredAsDoubleIterator implements Iterator<Double> {
344 double next;
345 int cursor;
346 FilteredAsDoubleIterator() {
347 cursor = firstIndex;
348 advance() ;
349 }
350 private void advance() {
351 while (cursor < upperBound) {
352 if (isSelected(cursor)) {
353 next = dget(cursor);
354 break;
355 }
356 cursor++;
357 }
358 }
359
360 public boolean hasNext() { return cursor < upperBound; }
361 public Double next() {
362 if (cursor >= upperBound)
363 throw new NoSuchElementException();
364 Double x = Double.valueOf(next);
365 cursor++;
366 advance();
367 return x;
368 }
369 public void remove() {
370 throw new UnsupportedOperationException();
371 }
372 }
373
374 class SequentiallyAsLong implements Iterable<Long> {
375 public Iterator<Long> iterator() {
376 if (hasFilter())
377 return new FilteredAsLongIterator();
378 else
379 return new UnfilteredAsLongIterator();
380 }
381 }
382
383 class UnfilteredAsLongIterator implements Iterator<Long> {
384 int cursor = firstIndex;
385 public boolean hasNext() { return cursor < upperBound; }
386 public Long next() {
387 if (cursor >= upperBound)
388 throw new NoSuchElementException();
389 return Long.valueOf(lget(cursor++));
390 }
391 public void remove() {
392 throw new UnsupportedOperationException();
393 }
394 }
395
396 class FilteredAsLongIterator implements Iterator<Long> {
397 long next;
398 int cursor;
399 FilteredAsLongIterator() {
400 cursor = firstIndex;
401 advance() ;
402 }
403 private void advance() {
404 while (cursor < upperBound) {
405 if (isSelected(cursor)) {
406 next = lget(cursor);
407 break;
408 }
409 cursor++;
410 }
411 }
412
413 public boolean hasNext() { return cursor < upperBound; }
414 public Long next() {
415 if (cursor >= upperBound)
416 throw new NoSuchElementException();
417 Long x = Long.valueOf(next);
418 cursor++;
419 advance();
420 return x;
421 }
422 public void remove() {
423 throw new UnsupportedOperationException();
424 }
425 }
426
427 class Sequentially<U> implements Iterable<U> {
428 public Iterator<U> iterator() {
429 if (hasFilter())
430 return new FilteredIterator<U>();
431 else
432 return new UnfilteredIterator<U>();
433 }
434 }
435
436 class UnfilteredIterator<U> implements Iterator<U> {
437 int cursor = firstIndex;
438 public boolean hasNext() { return cursor < upperBound; }
439 public U next() {
440 if (cursor >= upperBound)
441 throw new NoSuchElementException();
442 return (U)oget(cursor++);
443 }
444 public void remove() {
445 throw new UnsupportedOperationException();
446 }
447 }
448
449 class FilteredIterator<U> implements Iterator<U> {
450 Object next;
451 int cursor;
452 FilteredIterator() {
453 cursor = firstIndex;
454 advance() ;
455 }
456 private void advance() {
457 while (cursor < upperBound) {
458 if (isSelected(cursor)) {
459 next = oget(cursor);
460 break;
461 }
462 cursor++;
463 }
464 }
465
466 public boolean hasNext() { return cursor < upperBound; }
467 public U next() {
468 if (cursor >= upperBound)
469 throw new NoSuchElementException();
470 U x = (U)next;
471 cursor++;
472 advance();
473 return x;
474 }
475 public void remove() {
476 throw new UnsupportedOperationException();
477 }
478 }
479
480 }
481
482 /**
483 * Base of object ref array prefix classes
484 */
485 static abstract class OPrefix<T> extends PAS.Prefix {
486 T[] array;
487 OPrefix(ForkJoinExecutor ex, int firstIndex, int upperBound,
488 T[] array) {
489 super(ex, firstIndex, upperBound);
490 this.array = array;
491 }
492
493 final Object[] ogetArray() { return this.array; }
494 Predicate getPredicate() { return null; }
495
496 final void leafMoveByIndex(int[] indices, int loIdx,
497 int hiIdx, int offset) {
498 final Object[] array = this.array;
499 for (int i = loIdx; i < hiIdx; ++i)
500 array[offset++] = array[indices[i]];
501 }
502
503 final int leafIndexSelected(int lo, int hi, boolean positive,
504 int[] indices){
505 final Predicate s = getPredicate();
506 if (s == null)
507 return unfilteredLeafIndexSelected(lo, hi, positive, indices);
508 final Object[] array = this.array;
509 int k = 0;
510 for (int i = lo; i < hi; ++i) {
511 if (s.op(array[i]) == positive)
512 indices[lo + k++] = i;
513 }
514 return k;
515 }
516
517 final int unfilteredLeafIndexSelected(int lo, int hi, boolean positive,
518 int[] indices) {
519 int k = 0;
520 if (positive) {
521 final Object[] array = this.array;
522 for (int i = lo; i < hi; ++i) {
523 indices[lo + k++] = i;
524 }
525 }
526 return k;
527 }
528
529 final int leafMoveSelected(int lo, int hi, int offset,
530 boolean positive) {
531 final Predicate s = getPredicate();
532 if (s == null)
533 return unfilteredLeafMoveSelected(lo, hi, offset, positive);
534 final Object[] array = this.array;
535 for (int i = lo; i < hi; ++i) {
536 Object t = array[i];
537 if (s.op(t) == positive)
538 array[offset++] = t;
539 }
540 return offset;
541 }
542
543 final int unfilteredLeafMoveSelected(int lo, int hi, int offset,
544 boolean positive) {
545 if (positive) {
546 final Object[] array = this.array;
547 for (int i = lo; i < hi; ++i) {
548 array[offset++] = array[i];
549 }
550 }
551 return offset;
552 }
553
554 final int computeSize() {
555 Predicate s = getPredicate();
556 if (s == null)
557 return upperBound - firstIndex;
558 PAS.FJOCountSelected f = new PAS.FJOCountSelected
559 (this, firstIndex, upperBound, null, s);
560 ex.invoke(f);
561 return f.count;
562 }
563
564 final int computeAnyIndex() {
565 Predicate s = getPredicate();
566 if (s == null)
567 return (firstIndex < upperBound)? firstIndex : -1;
568 AtomicInteger result = new AtomicInteger(-1);
569 PAS.FJOSelectAny f = new PAS.FJOSelectAny
570 (this, firstIndex, upperBound, null, result, s);
571 ex.invoke(f);
572 return result.get();
573 }
574
575 }
576
577 /**
578 * Base of double array prefix classes
579 */
580 static abstract class DPrefix extends PAS.Prefix {
581 double[] array;
582 DPrefix(ForkJoinExecutor ex, int firstIndex, int upperBound,
583 double[] array) {
584 super(ex, firstIndex, upperBound);
585 this.array = array;
586 }
587
588 final double[] dgetArray() { return this.array; }
589 DoublePredicate getPredicate() { return null; }
590
591 final void leafMoveByIndex(int[] indices, int loIdx,
592 int hiIdx, int offset) {
593 final double[] array = this.array;
594 for (int i = loIdx; i < hiIdx; ++i)
595 array[offset++] = array[indices[i]];
596 }
597
598 final int leafIndexSelected(int lo, int hi, boolean positive,
599 int[] indices){
600 final DoublePredicate s = getPredicate();
601 if (s == null)
602 return unfilteredLeafIndexSelected(lo, hi, positive, indices);
603 final double[] array = this.array;
604 int k = 0;
605 for (int i = lo; i < hi; ++i) {
606 if (s.op(array[i]) == positive)
607 indices[lo + k++] = i;
608 }
609 return k;
610 }
611
612 final int unfilteredLeafIndexSelected(int lo, int hi, boolean positive,
613 int[] indices) {
614 int k = 0;
615 if (positive) {
616 final double[] array = this.array;
617 for (int i = lo; i < hi; ++i) {
618 indices[lo + k++] = i;
619 }
620 }
621 return k;
622 }
623
624 final int leafMoveSelected(int lo, int hi, int offset,
625 boolean positive) {
626 final DoublePredicate s = getPredicate();
627 if (s == null)
628 return unfilteredLeafMoveSelected(lo, hi, offset, positive);
629 final double[] array = this.array;
630 for (int i = lo; i < hi; ++i) {
631 double t = array[i];
632 if (s.op(t) == positive)
633 array[offset++] = t;
634 }
635 return offset;
636 }
637
638 final int unfilteredLeafMoveSelected(int lo, int hi, int offset,
639 boolean positive) {
640 if (positive) {
641 final double[] array = this.array;
642 for (int i = lo; i < hi; ++i) {
643 array[offset++] = array[i];
644 }
645 }
646 return offset;
647 }
648
649 final int computeSize() {
650 DoublePredicate s = getPredicate();
651 if (s == null)
652 return upperBound - firstIndex;
653 PAS.FJDCountSelected f = new PAS.FJDCountSelected
654 (this, firstIndex, upperBound, null, s);
655 ex.invoke(f);
656 return f.count;
657 }
658
659 final int computeAnyIndex() {
660 DoublePredicate s = getPredicate();
661 if (s == null)
662 return (firstIndex < upperBound)? firstIndex : -1;
663 AtomicInteger result = new AtomicInteger(-1);
664 PAS.FJDSelectAny f = new PAS.FJDSelectAny
665 (this, firstIndex, upperBound, null, result, s);
666 ex.invoke(f);
667 return result.get();
668 }
669
670 }
671
672 /**
673 * Base of long array prefix classes
674 */
675 static abstract class LPrefix extends PAS.Prefix {
676 long[] array;
677 LPrefix(ForkJoinExecutor ex, int firstIndex, int upperBound,
678 long[] array) {
679 super(ex, firstIndex, upperBound);
680 this.array = array;
681 }
682
683 final long[] lgetArray() { return this.array; }
684 LongPredicate getPredicate() { return null; }
685
686 final void leafMoveByIndex(int[] indices, int loIdx,
687 int hiIdx, int offset) {
688 final long[] array = this.array;
689 for (int i = loIdx; i < hiIdx; ++i)
690 array[offset++] = array[indices[i]];
691 }
692
693 final int leafIndexSelected(int lo, int hi, boolean positive,
694 int[] indices){
695 final LongPredicate s = getPredicate();
696 if (s == null)
697 return unfilteredLeafIndexSelected(lo, hi, positive, indices);
698 final long[] array = this.array;
699 int k = 0;
700 for (int i = lo; i < hi; ++i) {
701 if (s.op(array[i]) == positive)
702 indices[lo + k++] = i;
703 }
704 return k;
705 }
706
707 final int unfilteredLeafIndexSelected(int lo, int hi, boolean positive,
708 int[] indices) {
709 int k = 0;
710 if (positive) {
711 final long[] array = this.array;
712 for (int i = lo; i < hi; ++i) {
713 indices[lo + k++] = i;
714 }
715 }
716 return k;
717 }
718
719 final int leafMoveSelected(int lo, int hi, int offset,
720 boolean positive) {
721 final LongPredicate s = getPredicate();
722 if (s == null)
723 return unfilteredLeafMoveSelected(lo, hi, offset, positive);
724 final long[] array = this.array;
725 for (int i = lo; i < hi; ++i) {
726 long t = array[i];
727 if (s.op(t) == positive)
728 array[offset++] = t;
729 }
730 return offset;
731 }
732
733 final int unfilteredLeafMoveSelected(int lo, int hi, int offset,
734 boolean positive) {
735 if (positive) {
736 final long[] array = this.array;
737 for (int i = lo; i < hi; ++i) {
738 array[offset++] = array[i];
739 }
740 }
741 return offset;
742 }
743
744 final int computeSize() {
745 LongPredicate s = getPredicate();
746 if (s == null)
747 return upperBound - firstIndex;
748 PAS.FJLCountSelected f = new PAS.FJLCountSelected
749 (this, firstIndex, upperBound, null, s);
750 ex.invoke(f);
751 return f.count;
752 }
753
754 final int computeAnyIndex() {
755 LongPredicate s = getPredicate();
756 if (s == null)
757 return (firstIndex < upperBound)? firstIndex : -1;
758 AtomicInteger result = new AtomicInteger(-1);
759 PAS.FJLSelectAny f = new PAS.FJLSelectAny
760 (this, firstIndex, upperBound, null, result, s);
761 ex.invoke(f);
762 return result.get();
763 }
764
765 }
766
767 /**
768 * Base for most divide-and-conquer tasks used for computing
769 * ParallelArray operations. Rather than pure recursion, it links
770 * right-hand-sides and then joins up the tree, exploiting cases
771 * where tasks aren't stolen. This generates and joins tasks with
772 * a bit less overhead than pure recursive style -- there are only
773 * as many tasks as leaves (no strictly internal nodes).
774 *
775 * Split control relies on prefix.getThreshold(), which is
776 * expected to err on the side of generating too many tasks. To
777 * counterblance, if a task pops off its smallest subtask, it
778 * directly runs its leaf action rather than possibly replitting.
779 *
780 * There are, with a few exceptions, three flavors of each FJBase
781 * subclass, prefixed FJO (object reference), FJD (double) and FJL
782 * (long).
783 */
784 static abstract class FJBase extends RecursiveAction {
785 final Prefix prefix;
786 final int lo;
787 final int hi;
788 final FJBase next; // the next task that creator should join
789 FJBase(Prefix prefix, int lo, int hi, FJBase next) {
790 this.prefix = prefix;
791 this.lo = lo;
792 this.hi = hi;
793 this.next = next;
794 }
795
796 public final void compute() {
797 int g = prefix.getThreshold();
798 int l = lo;
799 int h = hi;
800 if (h - l > g)
801 internalCompute(l, h, g);
802 else
803 atLeaf(l, h);
804 }
805
806 final void internalCompute(int l, int h, int g) {
807 FJBase r = null;
808 do {
809 int rh = h;
810 h = (l + h) >>> 1;
811 (r = newSubtask(h, rh, r)).fork();
812 } while (h - l > g);
813 atLeaf(l, h);
814 do {
815 if (ForkJoinWorkerThread.removeIfNextLocalTask(r))
816 r.atLeaf(r.lo, r.hi);
817 else
818 r.join();
819 onReduce(r);
820 r = r.next;
821 } while (r != null);
822 }
823
824 /** Leaf computation */
825 abstract void atLeaf(int l, int h);
826 /** Operation performed after joining right subtask -- default noop */
827 void onReduce(FJBase right) {}
828 /** Factory method to create new subtask, normally of current type */
829 abstract FJBase newSubtask(int l, int h, FJBase r);
830 }
831
832 // apply
833
834 static final class FJOApply extends FJBase {
835 final Procedure procedure;
836 FJOApply(Prefix prefix, int lo, int hi, FJBase next,
837 Procedure procedure) {
838 super(prefix, lo, hi, next);
839 this.procedure = procedure;
840 }
841 FJBase newSubtask(int l, int h, FJBase r) {
842 return new FJOApply(prefix, l, h, r, procedure);
843 }
844 void atLeaf(int l, int h) {
845 prefix.leafApply(l, h, procedure);
846 }
847 }
848
849 static final class FJDApply extends FJBase {
850 final DoubleProcedure procedure;
851 FJDApply(Prefix prefix, int lo, int hi, FJBase next,
852 DoubleProcedure procedure) {
853 super(prefix, lo, hi, next);
854 this.procedure = procedure;
855 }
856 FJBase newSubtask(int l, int h, FJBase r) {
857 return new FJDApply(prefix, l, h, r, procedure);
858 }
859 void atLeaf(int l, int h) {
860 prefix.leafApply(l, h, procedure);
861 }
862 }
863
864 static final class FJLApply extends FJBase {
865 final LongProcedure procedure;
866 FJLApply(Prefix prefix, int lo, int hi, FJBase next,
867 LongProcedure procedure) {
868 super(prefix, lo, hi, next);
869 this.procedure = procedure;
870 }
871 FJBase newSubtask(int l, int h, FJBase r) {
872 return new FJLApply(prefix, l, h, r, procedure);
873 }
874 void atLeaf(int l, int h) {
875 prefix.leafApply(l, h, procedure);
876 }
877 }
878
879 // reduce
880
881 static final class FJOReduce extends FJBase {
882 final Reducer reducer;
883 Object result;
884 FJOReduce(Prefix prefix, int lo, int hi, FJBase next,
885 Reducer reducer, Object base) {
886 super(prefix, lo, hi, next);
887 this.reducer = reducer;
888 this.result = base;
889 }
890 FJBase newSubtask(int l, int h, FJBase r) {
891 return new FJOReduce(prefix, l, h, r, reducer, result);
892 }
893 void atLeaf(int l, int h) {
894 result = prefix.leafReduce(l, h, reducer, result);
895 }
896 void onReduce(FJBase right) {
897 result = reducer.op(result, ((FJOReduce)right).result);
898 }
899 }
900
901 static final class FJDReduce extends FJBase {
902 final DoubleReducer reducer;
903 double result;
904 FJDReduce(Prefix prefix, int lo, int hi, FJBase next,
905 DoubleReducer reducer, double base) {
906 super(prefix, lo, hi, next);
907 this.reducer = reducer;
908 this.result = base;
909 }
910 FJBase newSubtask(int l, int h, FJBase r) {
911 return new FJDReduce(prefix, l, h, r, reducer, result);
912 }
913 void atLeaf(int l, int h) {
914 result = prefix.leafReduce(l, h, reducer, result);
915 }
916 void onReduce(FJBase right) {
917 result = reducer.op(result, ((FJDReduce)right).result);
918 }
919 }
920
921 static final class FJLReduce extends FJBase {
922 final LongReducer reducer;
923 long result;
924 FJLReduce(Prefix prefix, int lo, int hi, FJBase next,
925 LongReducer reducer, long base) {
926 super(prefix, lo, hi, next);
927 this.reducer = reducer;
928 this.result = base;
929 }
930 FJBase newSubtask(int l, int h, FJBase r) {
931 return new FJLReduce(prefix, l, h, r, reducer, result);
932 }
933 void atLeaf(int l, int h) {
934 result = prefix.leafReduce(l, h, reducer, result);
935 }
936 void onReduce(FJBase right) {
937 result = reducer.op(result, ((FJLReduce)right).result);
938 }
939 }
940
941 // map
942
943 static final class FJOMap extends FJBase {
944 final Object[] dest;
945 final int offset;
946 FJOMap(Prefix prefix, int lo, int hi, FJBase next, Object[] dest,
947 int offset) {
948 super(prefix, lo, hi, next);
949 this.dest = dest;
950 this.offset = offset;
951 }
952 FJBase newSubtask(int l, int h, FJBase r) {
953 return new FJOMap(prefix, l, h, r, dest, offset);
954 }
955 void atLeaf(int l, int h) {
956 prefix.leafTransfer(l, h, dest, l - offset);
957 }
958 }
959
960 static final class FJDMap extends FJBase {
961 final double[] dest;
962 final int offset;
963 FJDMap(Prefix prefix, int lo, int hi, FJBase next, double[] dest,
964 int offset) {
965 super(prefix, lo, hi, next);
966 this.dest = dest;
967 this.offset = offset;
968 }
969 FJBase newSubtask(int l, int h, FJBase r) {
970 return new FJDMap(prefix, l, h, r, dest, offset);
971 }
972 void atLeaf(int l, int h) {
973 prefix.leafTransfer(l, h, dest, l - offset);
974 }
975 }
976
977 static final class FJLMap extends FJBase {
978 final long[] dest;
979 final int offset;
980 FJLMap(Prefix prefix, int lo, int hi, FJBase next, long[] dest,
981 int offset) {
982 super(prefix, lo, hi, next);
983 this.dest = dest;
984 this.offset = offset;
985 }
986 FJBase newSubtask(int l, int h, FJBase r) {
987 return new FJLMap(prefix, l, h, r, dest, offset);
988 }
989 void atLeaf(int l, int h) {
990 prefix.leafTransfer(l, h, dest, l - offset);
991 }
992 }
993
994 // transform
995
996 static final class FJOTransform extends FJBase {
997 final Op op;
998 FJOTransform(Prefix prefix, int lo, int hi, FJBase next,
999 Op op) {
1000 super(prefix, lo, hi, next);
1001 this.op = op;
1002 }
1003 FJBase newSubtask(int l, int h, FJBase r) {
1004 return new FJOTransform(prefix, l, h, r, op);
1005 }
1006 void atLeaf(int l, int h) {
1007 OPrefix p = (OPrefix)prefix;
1008 Object[] array = p.array;
1009 Predicate s = p.getPredicate();
1010 if (s == null)
1011 leafTransform(l, h, array);
1012 else
1013 leafTransform(l, h, array, s);
1014 }
1015 void leafTransform(int l, int h, Object[] array) {
1016 for (int i = l; i < h; ++i)
1017 array[i] = op.op(array[i]);
1018 }
1019 void leafTransform(int l, int h, Object[] array, Predicate s) {
1020 for (int i = l; i < h; ++i) {
1021 Object x = array[i];
1022 if (s.op(x))
1023 array[i] = op.op(x);
1024 }
1025 }
1026 }
1027
1028 static final class FJDTransform extends FJBase {
1029 final DoubleOp op;
1030 FJDTransform(Prefix prefix, int lo, int hi, FJBase next,
1031 DoubleOp op) {
1032 super(prefix, lo, hi, next);
1033 this.op = op;
1034 }
1035 FJBase newSubtask(int l, int h, FJBase r) {
1036 return new FJDTransform(prefix, l, h, r, op);
1037 }
1038 void atLeaf(int l, int h) {
1039 DPrefix p = (DPrefix)prefix;
1040 double[] array = p.array;
1041 DoublePredicate s = p.getPredicate();
1042 if (s == null)
1043 leafTransform(l, h, array);
1044 else
1045 leafTransform(l, h, array, s);
1046 }
1047 void leafTransform(int l, int h, double[] array) {
1048 for (int i = l; i < h; ++i)
1049 array[i] = op.op(array[i]);
1050 }
1051
1052 void leafTransform(int l, int h, double[] array, DoublePredicate s) {
1053 for (int i = l; i < h; ++i) {
1054 double x = array[i];
1055 if (s.op(x))
1056 array[i] = op.op(x);
1057 }
1058 }
1059 }
1060
1061 static final class FJLTransform extends FJBase {
1062 final LongOp op;
1063 FJLTransform(Prefix prefix, int lo, int hi, FJBase next,
1064 LongOp op) {
1065 super(prefix, lo, hi, next);
1066 this.op = op;
1067 }
1068 FJBase newSubtask(int l, int h, FJBase r) {
1069 return new FJLTransform(prefix, l, h, r, op);
1070 }
1071 void atLeaf(int l, int h) {
1072 LPrefix p = (LPrefix)prefix;
1073 long[] array = p.array;
1074 LongPredicate s = p.getPredicate();
1075 if (s == null)
1076 leafTransform(l, h, array);
1077 else
1078 leafTransform(l, h, array, s);
1079 }
1080 void leafTransform(int l, int h, long[] array) {
1081 for (int i = l; i < h; ++i)
1082 array[i] = op.op(array[i]);
1083 }
1084
1085 void leafTransform(int l, int h, long[] array, LongPredicate s) {
1086 for (int i = l; i < h; ++i) {
1087 long x = array[i];
1088 if (s.op(x))
1089 array[i] = op.op(x);
1090 }
1091 }
1092 }
1093
1094 // index map
1095
1096 static final class FJOIndexMap extends FJBase {
1097 final IntToObject op;
1098 FJOIndexMap(Prefix prefix, int lo, int hi, FJBase next,
1099 IntToObject op) {
1100 super(prefix, lo, hi, next);
1101 this.op = op;
1102 }
1103 FJBase newSubtask(int l, int h, FJBase r) {
1104 return new FJOIndexMap(prefix, l, h, r, op);
1105 }
1106 void atLeaf(int l, int h) {
1107 OPrefix p = (OPrefix)prefix;
1108 Object[] array = p.array;
1109 Predicate s = p.getPredicate();
1110 if (s == null)
1111 leafIndexMap(l, h, array);
1112 else
1113 leafIndexMap(l, h, array, s);
1114 }
1115 void leafIndexMap(int l, int h, Object[] array) {
1116 for (int i = l; i < h; ++i)
1117 array[i] = op.op(i);
1118 }
1119
1120 void leafIndexMap(int l, int h, Object[] array, Predicate s) {
1121 for (int i = l; i < h; ++i) {
1122 Object x = array[i];
1123 if (s.op(x))
1124 array[i] = op.op(i);
1125 }
1126 }
1127 }
1128
1129 static final class FJDIndexMap extends FJBase {
1130 final IntToDouble op;
1131 FJDIndexMap(Prefix prefix, int lo, int hi, FJBase next,
1132 IntToDouble op) {
1133 super(prefix, lo, hi, next);
1134 this.op = op;
1135 }
1136 FJBase newSubtask(int l, int h, FJBase r) {
1137 return new FJDIndexMap(prefix, l, h, r, op);
1138 }
1139 void atLeaf(int l, int h) {
1140 DPrefix p = (DPrefix)prefix;
1141 double[] array = p.array;
1142 DoublePredicate s = p.getPredicate();
1143 if (s == null)
1144 leafIndexMap(l, h, array);
1145 else
1146 leafIndexMap(l, h, array, s);
1147 }
1148 void leafIndexMap(int l, int h, double[] array) {
1149 for (int i = l; i < h; ++i)
1150 array[i] = op.op(i);
1151 }
1152
1153 void leafIndexMap(int l, int h, double[] array, DoublePredicate s) {
1154 for (int i = l; i < h; ++i) {
1155 double x = array[i];
1156 if (s.op(x))
1157 array[i] = op.op(i);
1158 }
1159 }
1160 }
1161
1162 static final class FJLIndexMap extends FJBase {
1163 final IntToLong op;
1164 FJLIndexMap(Prefix prefix, int lo, int hi, FJBase next,
1165 IntToLong op) {
1166 super(prefix, lo, hi, next);
1167 this.op = op;
1168 }
1169 FJBase newSubtask(int l, int h, FJBase r) {
1170 return new FJLIndexMap(prefix, l, h, r, op);
1171 }
1172 void atLeaf(int l, int h) {
1173 LPrefix p = (LPrefix)prefix;
1174 long[] array = p.array;
1175 LongPredicate s = p.getPredicate();
1176 if (s == null)
1177 leafIndexMap(l, h, array);
1178 else
1179 leafIndexMap(l, h, array, s);
1180 }
1181 void leafIndexMap(int l, int h, long[] array) {
1182 for (int i = l; i < h; ++i)
1183 array[i] = op.op(i);
1184 }
1185
1186 void leafIndexMap(int l, int h, long[] array, LongPredicate s) {
1187 for (int i = l; i < h; ++i) {
1188 long x = array[i];
1189 if (s.op(x))
1190 array[i] = op.op(i);
1191 }
1192 }
1193 }
1194
1195 // binary index map
1196
1197 static final class FJOBinaryIndexMap extends FJBase {
1198 final IntAndObjectToObject op;
1199 FJOBinaryIndexMap(Prefix prefix, int lo, int hi, FJBase next,
1200 IntAndObjectToObject op) {
1201 super(prefix, lo, hi, next);
1202 this.op = op;
1203 }
1204 FJBase newSubtask(int l, int h, FJBase r) {
1205 return new FJOBinaryIndexMap(prefix, l, h, r, op);
1206 }
1207 void atLeaf(int l, int h) {
1208 OPrefix p = (OPrefix)prefix;
1209 Object[] array = p.array;
1210 Predicate s = p.getPredicate();
1211 if (s == null)
1212 leafBinaryIndexMap(l, h, array);
1213 else
1214 leafBinaryIndexMap(l, h, array, s);
1215 }
1216 void leafBinaryIndexMap(int l, int h, Object[] array) {
1217 for (int i = l; i < h; ++i)
1218 array[i] = op.op(i, array[i]);
1219 }
1220
1221 void leafBinaryIndexMap(int l, int h, Object[] array, Predicate s) {
1222 for (int i = l; i < h; ++i) {
1223 Object x = array[i];
1224 if (s.op(x))
1225 array[i] = op.op(i, x);
1226 }
1227 }
1228 }
1229
1230 static final class FJDBinaryIndexMap extends FJBase {
1231 final IntAndDoubleToDouble op;
1232 FJDBinaryIndexMap(Prefix prefix, int lo, int hi, FJBase next,
1233 IntAndDoubleToDouble op) {
1234 super(prefix, lo, hi, next);
1235 this.op = op;
1236 }
1237 FJBase newSubtask(int l, int h, FJBase r) {
1238 return new FJDBinaryIndexMap(prefix, l, h, r, op);
1239 }
1240 void atLeaf(int l, int h) {
1241 DPrefix p = (DPrefix)prefix;
1242 double[] array = p.array;
1243 DoublePredicate s = p.getPredicate();
1244 if (s == null)
1245 leafBinaryIndexMap(l, h, array);
1246 else
1247 leafBinaryIndexMap(l, h, array, s);
1248 }
1249 void leafBinaryIndexMap(int l, int h, double[] array) {
1250 for (int i = l; i < h; ++i)
1251 array[i] = op.op(i, array[i]);
1252 }
1253
1254 void leafBinaryIndexMap(int l, int h, double[] array, DoublePredicate s) {
1255 for (int i = l; i < h; ++i) {
1256 double x = array[i];
1257 if (s.op(x))
1258 array[i] = op.op(i, x);
1259 }
1260 }
1261 }
1262
1263 static final class FJLBinaryIndexMap extends FJBase {
1264 final IntAndLongToLong op;
1265 FJLBinaryIndexMap(Prefix prefix, int lo, int hi, FJBase next,
1266 IntAndLongToLong op) {
1267 super(prefix, lo, hi, next);
1268 this.op = op;
1269 }
1270 FJBase newSubtask(int l, int h, FJBase r) {
1271 return new FJLBinaryIndexMap(prefix, l, h, r, op);
1272 }
1273 void atLeaf(int l, int h) {
1274 LPrefix p = (LPrefix)prefix;
1275 long[] array = p.array;
1276 LongPredicate s = p.getPredicate();
1277 if (s == null)
1278 leafBinaryIndexMap(l, h, array);
1279 else
1280 leafBinaryIndexMap(l, h, array, s);
1281 }
1282 void leafBinaryIndexMap(int l, int h, long[] array) {
1283 for (int i = l; i < h; ++i)
1284 array[i] = op.op(i, array[i]);
1285 }
1286
1287 void leafBinaryIndexMap(int l, int h, long[] array, LongPredicate s) {
1288 for (int i = l; i < h; ++i) {
1289 long x = array[i];
1290 if (s.op(x))
1291 array[i] = op.op(i, x);
1292 }
1293 }
1294 }
1295
1296
1297 // generate
1298
1299 static final class FJOGenerate extends FJBase {
1300 final Generator generator;
1301 FJOGenerate(Prefix prefix, int lo, int hi, FJBase next,
1302 Generator generator) {
1303 super(prefix, lo, hi, next);
1304 this.generator = generator;
1305 }
1306 FJBase newSubtask(int l, int h, FJBase r) {
1307 return new FJOGenerate(prefix, l, h, r, generator);
1308 }
1309 void atLeaf(int l, int h) {
1310 OPrefix p = (OPrefix)prefix;
1311 Object[] array = p.array;
1312 Predicate s = p.getPredicate();
1313 if (s == null)
1314 leafGenerate(l, h, array);
1315 else
1316 leafGenerate(l, h, array, s);
1317 }
1318 void leafGenerate(int l, int h, Object[] array) {
1319 for (int i = l; i < h; ++i)
1320 array[i] = generator.op();
1321 }
1322
1323 void leafGenerate(int l, int h, Object[] array, Predicate s) {
1324 for (int i = l; i < h; ++i) {
1325 if (s.op(array[i]))
1326 array[i] = generator.op();
1327 }
1328 }
1329 }
1330
1331 static final class FJDGenerate extends FJBase {
1332 final DoubleGenerator generator;
1333 FJDGenerate(Prefix prefix, int lo, int hi, FJBase next,
1334 DoubleGenerator generator) {
1335 super(prefix, lo, hi, next);
1336 this.generator = generator;
1337 }
1338 FJBase newSubtask(int l, int h, FJBase r) {
1339 return new FJDGenerate(prefix, l, h, r, generator);
1340 }
1341 void atLeaf(int l, int h) {
1342 DPrefix p = (DPrefix)prefix;
1343 double[] array = p.array;
1344 DoublePredicate s = p.getPredicate();
1345 if (s == null)
1346 leafGenerate(l, h, array);
1347 else
1348 leafGenerate(l, h, array, s);
1349 }
1350 void leafGenerate(int l, int h, double[] array) {
1351 for (int i = l; i < h; ++i)
1352 array[i] = generator.op();
1353 }
1354
1355 void leafGenerate(int l, int h, double[] array, DoublePredicate s) {
1356 for (int i = l; i < h; ++i) {
1357 if (s.op(array[i]))
1358 array[i] = generator.op();
1359 }
1360 }
1361 }
1362
1363 static final class FJLGenerate extends FJBase {
1364 final LongGenerator generator;
1365 FJLGenerate(Prefix prefix, int lo, int hi, FJBase next,
1366 LongGenerator generator) {
1367 super(prefix, lo, hi, next);
1368 this.generator = generator;
1369 }
1370 FJBase newSubtask(int l, int h, FJBase r) {
1371 return new FJLGenerate(prefix, l, h, r, generator);
1372 }
1373 void atLeaf(int l, int h) {
1374 LPrefix p = (LPrefix)prefix;
1375 long[] array = p.array;
1376 LongPredicate s = p.getPredicate();
1377 if (s == null)
1378 leafGenerate(l, h, array);
1379 else
1380 leafGenerate(l, h, array, s);
1381 }
1382 void leafGenerate(int l, int h, long[] array) {
1383 for (int i = l; i < h; ++i)
1384 array[i] = generator.op();
1385 }
1386
1387 void leafGenerate(int l, int h, long[] array, LongPredicate s) {
1388 for (int i = l; i < h; ++i) {
1389 if (s.op(array[i]))
1390 array[i] = generator.op();
1391 }
1392 }
1393 }
1394
1395 // fill
1396
1397 static final class FJOFill extends FJBase {
1398 final Object value;
1399 FJOFill(Prefix prefix, int lo, int hi, FJBase next, Object value) {
1400 super(prefix, lo, hi, next);
1401 this.value = value;
1402 }
1403 FJBase newSubtask(int l, int h, FJBase r) {
1404 return new FJOFill(prefix, l, h, r, value);
1405 }
1406 void atLeaf(int l, int h) {
1407 OPrefix p = (OPrefix)prefix;
1408 Object[] array = p.array;
1409 Predicate s = p.getPredicate();
1410 if (s == null)
1411 leafFill(l, h, array);
1412 else
1413 leafFill(l, h, array, s);
1414 }
1415 void leafFill(int l, int h, Object[] array) {
1416 for (int i = l; i < h; ++i)
1417 array[i] = value;
1418 }
1419
1420 void leafFill(int l, int h, Object[] array, Predicate s) {
1421 for (int i = l; i < h; ++i) {
1422 if (s.op(array[i]))
1423 array[i] = value;
1424 }
1425 }
1426 }
1427
1428 static final class FJDFill extends FJBase {
1429 final double value;
1430 FJDFill(Prefix prefix, int lo, int hi, FJBase next, double value) {
1431 super(prefix, lo, hi, next);
1432 this.value = value;
1433 }
1434 FJBase newSubtask(int l, int h, FJBase r) {
1435 return new FJDFill(prefix, l, h, r, value);
1436 }
1437 void atLeaf(int l, int h) {
1438 DPrefix p = (DPrefix)prefix;
1439 double[] array = p.array;
1440 DoublePredicate s = p.getPredicate();
1441 if (s == null)
1442 leafFill(l, h, array);
1443 else
1444 leafFill(l, h, array, s);
1445 }
1446 void leafFill(int l, int h, double[] array) {
1447 for (int i = l; i < h; ++i)
1448 array[i] = value;
1449 }
1450
1451 void leafFill(int l, int h, double[] array, DoublePredicate s) {
1452 for (int i = l; i < h; ++i) {
1453 if (s.op(array[i]))
1454 array[i] = value;
1455 }
1456 }
1457 }
1458
1459 static final class FJLFill extends FJBase {
1460 final long value;
1461 FJLFill(Prefix prefix, int lo, int hi, FJBase next, long value) {
1462 super(prefix, lo, hi, next);
1463 this.value = value;
1464 }
1465 FJBase newSubtask(int l, int h, FJBase r) {
1466 return new FJLFill(prefix, l, h, r, value);
1467 }
1468 void atLeaf(int l, int h) {
1469 LPrefix p = (LPrefix)prefix;
1470 long[] array = p.array;
1471 LongPredicate s = p.getPredicate();
1472 if (s == null)
1473 leafFill(l, h, array);
1474 else
1475 leafFill(l, h, array, s);
1476 }
1477 void leafFill(int l, int h, long[] array) {
1478 for (int i = l; i < h; ++i)
1479 array[i] = value;
1480 }
1481
1482 void leafFill(int l, int h, long[] array, LongPredicate s) {
1483 for (int i = l; i < h; ++i) {
1484 if (s.op(array[i]))
1485 array[i] = value;
1486 }
1487 }
1488 }
1489
1490 // combine in place
1491
1492 static final class FJOCombineInPlace extends FJBase {
1493 final Object[] other;
1494 final int otherOffset;
1495 final BinaryOp combiner;
1496 FJOCombineInPlace(Prefix prefix, int lo, int hi, FJBase next,
1497 Object[] other, int otherOffset,
1498 BinaryOp combiner) {
1499 super(prefix, lo, hi, next);
1500 this.other = other;
1501 this.otherOffset = otherOffset;
1502 this.combiner = combiner;
1503 }
1504 FJBase newSubtask(int l, int h, FJBase r) {
1505 return new FJOCombineInPlace
1506 (prefix, l, h, r, other, otherOffset, combiner);
1507 }
1508 void atLeaf(int l, int h) {
1509 OPrefix p = (OPrefix)prefix;
1510 Object[] array = p.array;
1511 Predicate s = p.getPredicate();
1512 if (s == null)
1513 leafCombineInPlace(l, h, array);
1514 else
1515 leafCombineInPlace(l, h, array, s);
1516 }
1517 void leafCombineInPlace(int l, int h, Object[] array) {
1518 for (int i = l; i < h; ++i)
1519 array[i] = combiner.op(array[i], other[i+otherOffset]);
1520 }
1521
1522 void leafCombineInPlace(int l, int h, Object[] array, Predicate s) {
1523 for (int i = l; i < h; ++i) {
1524 Object x = array[i];
1525 if (s.op(x))
1526 array[i] = combiner.op(x, other[i+otherOffset]);
1527 }
1528 }
1529 }
1530
1531 static final class FJDCombineInPlace extends FJBase {
1532 final double[] other;
1533 final int otherOffset;
1534 final BinaryDoubleOp combiner;
1535 FJDCombineInPlace(Prefix prefix, int lo, int hi, FJBase next,
1536 double[] other, int otherOffset,
1537 BinaryDoubleOp combiner) {
1538 super(prefix, lo, hi, next);
1539 this.other = other;
1540 this.otherOffset = otherOffset;
1541 this.combiner = combiner;
1542 }
1543 FJBase newSubtask(int l, int h, FJBase r) {
1544 return new FJDCombineInPlace
1545 (prefix, l, h, r, other, otherOffset, combiner);
1546 }
1547 void atLeaf(int l, int h) {
1548 DPrefix p = (DPrefix)prefix;
1549 double[] array = p.array;
1550 DoublePredicate s = p.getPredicate();
1551 if (s == null)
1552 leafCombineInPlace(l, h, array);
1553 else
1554 leafCombineInPlace(l, h, array, s);
1555 }
1556 void leafCombineInPlace(int l, int h, double[] array) {
1557 for (int i = l; i < h; ++i)
1558 array[i] = combiner.op(array[i], other[i+otherOffset]);
1559 }
1560
1561 void leafCombineInPlace(int l, int h, double[] array, DoublePredicate s) {
1562 for (int i = l; i < h; ++i) {
1563 double x = array[i];
1564 if (s.op(x))
1565 array[i] = combiner.op(x, other[i+otherOffset]);
1566 }
1567 }
1568 }
1569
1570 static final class FJLCombineInPlace extends FJBase {
1571 final long[] other;
1572 final int otherOffset;
1573 final BinaryLongOp combiner;
1574 FJLCombineInPlace(Prefix prefix, int lo, int hi, FJBase next,
1575 long[] other, int otherOffset,
1576 BinaryLongOp combiner) {
1577 super(prefix, lo, hi, next);
1578 this.other = other;
1579 this.otherOffset = otherOffset;
1580 this.combiner = combiner;
1581 }
1582 FJBase newSubtask(int l, int h, FJBase r) {
1583 return new FJLCombineInPlace
1584 (prefix, l, h, r, other, otherOffset, combiner);
1585 }
1586 void atLeaf(int l, int h) {
1587 LPrefix p = (LPrefix)prefix;
1588 long[] array = p.array;
1589 LongPredicate s = p.getPredicate();
1590 if (s == null)
1591 leafCombineInPlace(l, h, array);
1592 else
1593 leafCombineInPlace(l, h, array, s);
1594 }
1595 void leafCombineInPlace(int l, int h, long[] array) {
1596 for (int i = l; i < h; ++i)
1597 array[i] = combiner.op(array[i], other[i+otherOffset]);
1598 }
1599
1600 void leafCombineInPlace(int l, int h, long[] array, LongPredicate s) {
1601 for (int i = l; i < h; ++i) {
1602 long x = array[i];
1603 if (s.op(x))
1604 array[i] = combiner.op(x, other[i+otherOffset]);
1605 }
1606 }
1607 }
1608
1609 static final class FJOPACombineInPlace extends FJBase {
1610 final ParallelArray other;
1611 final int otherOffset;
1612 final BinaryOp combiner;
1613 FJOPACombineInPlace(Prefix prefix, int lo, int hi, FJBase next,
1614 ParallelArray other, int otherOffset,
1615 BinaryOp combiner) {
1616 super(prefix, lo, hi, next);
1617 this.other = other;
1618 this.otherOffset = otherOffset;
1619 this.combiner = combiner;
1620 }
1621 FJBase newSubtask(int l, int h, FJBase r) {
1622 return new FJOPACombineInPlace
1623 (prefix, l, h, r, other, otherOffset, combiner);
1624 }
1625 void atLeaf(int l, int h) {
1626 OPrefix p = (OPrefix)prefix;
1627 Object[] array = p.array;
1628 Predicate s = p.getPredicate();
1629 if (s == null)
1630 leafPACombineInPlace(l, h, array);
1631 else
1632 leafPACombineInPlace(l, h, array, s);
1633 }
1634 void leafPACombineInPlace(int l, int h, Object[] array) {
1635 for (int i = l; i < h; ++i)
1636 array[i] = combiner.op(array[i], other.oget(i+otherOffset));
1637 }
1638
1639 void leafPACombineInPlace(int l, int h, Object[] array, Predicate s) {
1640 for (int i = l; i < h; ++i) {
1641 Object x = array[i];
1642 if (s.op(x))
1643 array[i] = combiner.op(x, other.oget(i+otherOffset));
1644 }
1645 }
1646 }
1647
1648 static final class FJDPACombineInPlace extends FJBase {
1649 final ParallelDoubleArray other;
1650 final int otherOffset;
1651 final BinaryDoubleOp combiner;
1652 FJDPACombineInPlace(Prefix prefix, int lo, int hi, FJBase next,
1653 ParallelDoubleArray other, int otherOffset,
1654 BinaryDoubleOp combiner) {
1655 super(prefix, lo, hi, next);
1656 this.other = other;
1657 this.otherOffset = otherOffset;
1658 this.combiner = combiner;
1659 }
1660 FJBase newSubtask(int l, int h, FJBase r) {
1661 return new FJDPACombineInPlace
1662 (prefix, l, h, r, other, otherOffset, combiner);
1663 }
1664 void atLeaf(int l, int h) {
1665 DPrefix p = (DPrefix)prefix;
1666 double[] array = p.array;
1667 DoublePredicate s = p.getPredicate();
1668 if (s == null)
1669 leafPACombineInPlace(l, h, array);
1670 else
1671 leafPACombineInPlace(l, h, array, s);
1672 }
1673 void leafPACombineInPlace(int l, int h, double[] array) {
1674 for (int i = l; i < h; ++i)
1675 array[i] = combiner.op(array[i], other.dget(i+otherOffset));
1676 }
1677
1678 void leafPACombineInPlace(int l, int h, double[] array, DoublePredicate s) {
1679 for (int i = l; i < h; ++i) {
1680 double x = array[i];
1681 if (s.op(x))
1682 array[i] = combiner.op(x, other.dget(i+otherOffset));
1683 }
1684 }
1685 }
1686
1687 static final class FJLPACombineInPlace extends FJBase {
1688 final ParallelLongArray other;
1689 final int otherOffset;
1690 final BinaryLongOp combiner;
1691 FJLPACombineInPlace(Prefix prefix, int lo, int hi, FJBase next,
1692 ParallelLongArray other, int otherOffset,
1693 BinaryLongOp combiner) {
1694 super(prefix, lo, hi, next);
1695 this.other = other;
1696 this.otherOffset = otherOffset;
1697 this.combiner = combiner;
1698 }
1699 FJBase newSubtask(int l, int h, FJBase r) {
1700 return new FJLPACombineInPlace
1701 (prefix, l, h, r, other, otherOffset, combiner);
1702 }
1703 void atLeaf(int l, int h) {
1704 LPrefix p = (LPrefix)prefix;
1705 long[] array = p.array;
1706 LongPredicate s = p.getPredicate();
1707 if (s == null)
1708 leafPACombineInPlace(l, h, array);
1709 else
1710 leafPACombineInPlace(l, h, array, s);
1711 }
1712 void leafPACombineInPlace(int l, int h, long[] array) {
1713 for (int i = l; i < h; ++i)
1714 array[i] = combiner.op(array[i], other.lget(i+otherOffset));
1715 }
1716
1717 void leafPACombineInPlace(int l, int h, long[] array, LongPredicate s) {
1718 for (int i = l; i < h; ++i) {
1719 long x = array[i];
1720 if (s.op(x))
1721 array[i] = combiner.op(x, other.lget(i+otherOffset));
1722 }
1723 }
1724 }
1725
1726 // stats
1727
1728 static final class FJOStats extends FJBase
1729 implements ParallelArray.SummaryStatistics {
1730 final Comparator comparator;
1731 public int size() { return size; }
1732 public Object min() { return min; }
1733 public Object max() { return max; }
1734 public int indexOfMin() { return indexOfMin; }
1735 public int indexOfMax() { return indexOfMax; }
1736 int size;
1737 Object min;
1738 Object max;
1739 int indexOfMin;
1740 int indexOfMax;
1741 FJOStats(Prefix prefix, int lo, int hi, FJBase next,
1742 Comparator comparator) {
1743 super(prefix, lo, hi, next);
1744 this.comparator = comparator;
1745 this.indexOfMin = -1;
1746 this.indexOfMax = -1;
1747 }
1748 FJBase newSubtask(int l, int h, FJBase r) {
1749 return new FJOStats(prefix, l, h, r, comparator);
1750 }
1751 void onReduce(FJBase right) {
1752 FJOStats r = (FJOStats)right;
1753 size += r.size;
1754 updateMin(r.indexOfMin, r.min);
1755 updateMax(r.indexOfMax, r.max);
1756 }
1757 void updateMin(int i, Object x) {
1758 if (i >= 0 &&
1759 (indexOfMin < 0 || comparator.compare(min, x) > 0)) {
1760 min = x;
1761 indexOfMin = i;
1762 }
1763 }
1764 void updateMax(int i, Object x) {
1765 if (i >= 0 &&
1766 (indexOfMax < 0 || comparator.compare(max, x) < 0)) {
1767 max = x;
1768 indexOfMax = i;
1769 }
1770 }
1771
1772 void atLeaf(int l, int h) {
1773 if (prefix.hasFilter()) {
1774 filteredAtLeaf(l, h);
1775 return;
1776 }
1777 size = h - l;
1778 for (int i = l; i < h; ++i) {
1779 Object x = prefix.oget(i);
1780 updateMin(i, x);
1781 updateMax(i, x);
1782 }
1783 }
1784
1785 void filteredAtLeaf(int l, int h) {
1786 for (int i = l; i < h; ++i) {
1787 if (prefix.isSelected(i)) {
1788 Object x = prefix.oget(i);
1789 ++size;
1790 updateMin(i, x);
1791 updateMax(i, x);
1792 }
1793 }
1794 }
1795
1796 public String toString() {
1797 return
1798 "size: " + size +
1799 " min: " + min + " (index " + indexOfMin +
1800 ") max: " + max + " (index " + indexOfMax + ")";
1801 }
1802
1803 }
1804
1805 static final class FJDStats extends FJBase
1806 implements ParallelDoubleArray.SummaryStatistics {
1807 final DoubleComparator comparator;
1808 public int size() { return size; }
1809 public double min() { return min; }
1810 public double max() { return max; }
1811 public double sum() { return sum; }
1812 public double average() { return sum / size; }
1813 public int indexOfMin() { return indexOfMin; }
1814 public int indexOfMax() { return indexOfMax; }
1815 int size;
1816 double min;
1817 double max;
1818 double sum;
1819 int indexOfMin;
1820 int indexOfMax;
1821 FJDStats(Prefix prefix, int lo, int hi, FJBase next,
1822 DoubleComparator comparator) {
1823 super(prefix, lo, hi, next);
1824 this.comparator = comparator;
1825 this.indexOfMin = -1;
1826 this.indexOfMax = -1;
1827 this.min = Double.MAX_VALUE;
1828 this.max = -Double.MAX_VALUE;
1829 }
1830 FJBase newSubtask(int l, int h, FJBase r) {
1831 return new FJDStats(prefix, l, h, r, comparator);
1832 }
1833 void onReduce(FJBase right) {
1834 FJDStats r = (FJDStats)right;
1835 size += r.size;
1836 sum += r.sum;
1837 updateMin(r.indexOfMin, r.min);
1838 updateMax(r.indexOfMax, r.max);
1839 }
1840 void updateMin(int i, double x) {
1841 if (i >= 0 &&
1842 (indexOfMin < 0 || comparator.compare(min, x) > 0)) {
1843 min = x;
1844 indexOfMin = i;
1845 }
1846 }
1847 void updateMax(int i, double x) {
1848 if (i >= 0 &&
1849 (indexOfMax < 0 || comparator.compare(max, x) < 0)) {
1850 max = x;
1851 indexOfMax = i;
1852 }
1853 }
1854 void atLeaf(int l, int h) {
1855 if (prefix.hasFilter()) {
1856 filteredAtLeaf(l, h);
1857 return;
1858 }
1859 size = h - l;
1860 for (int i = l; i < h; ++i) {
1861 double x = prefix.dget(i);
1862 sum += x;
1863 updateMin(i, x);
1864 updateMax(i, x);
1865 }
1866 }
1867
1868 void filteredAtLeaf(int l, int h) {
1869 for (int i = l; i < h; ++i) {
1870 if (prefix.isSelected(i)) {
1871 double x = prefix.dget(i);
1872 ++size;
1873 sum += x;
1874 updateMin(i, x);
1875 updateMax(i, x);
1876 }
1877 }
1878 }
1879
1880 public String toString() {
1881 return
1882 "size: " + size +
1883 " min: " + min + " (index " + indexOfMin +
1884 ") max: " + max + " (index " + indexOfMax +
1885 ") sum: " + sum;
1886 }
1887 }
1888
1889 static final class FJLStats extends FJBase
1890 implements ParallelLongArray.SummaryStatistics {
1891 final LongComparator comparator;
1892 public int size() { return size; }
1893 public long min() { return min; }
1894 public long max() { return max; }
1895 public long sum() { return sum; }
1896 public double average() { return (double)sum / size; }
1897 public int indexOfMin() { return indexOfMin; }
1898 public int indexOfMax() { return indexOfMax; }
1899 int size;
1900 long min;
1901 long max;
1902 long sum;
1903 int indexOfMin;
1904 int indexOfMax;
1905 FJLStats(Prefix prefix, int lo, int hi, FJBase next,
1906 LongComparator comparator) {
1907 super(prefix, lo, hi, next);
1908 this.comparator = comparator;
1909 this.indexOfMin = -1;
1910 this.indexOfMax = -1;
1911 this.min = Long.MAX_VALUE;
1912 this.max = Long.MIN_VALUE;
1913 }
1914 FJBase newSubtask(int l, int h, FJBase r) {
1915 return new FJLStats(prefix, l, h, r, comparator);
1916 }
1917 void onReduce(FJBase right) {
1918 FJLStats r = (FJLStats)right;
1919 size += r.size;
1920 sum += r.sum;
1921 updateMin(r.indexOfMin, r.min);
1922 updateMax(r.indexOfMax, r.max);
1923 }
1924 void updateMin(int i, long x) {
1925 if (i >= 0 &&
1926 (indexOfMin < 0 || comparator.compare(min, x) > 0)) {
1927 min = x;
1928 indexOfMin = i;
1929 }
1930 }
1931 void updateMax(int i, long x) {
1932 if (i >= 0 &&
1933 (indexOfMax < 0 || comparator.compare(max, x) < 0)) {
1934 max = x;
1935 indexOfMax = i;
1936 }
1937 }
1938
1939 void atLeaf(int l, int h) {
1940 if (prefix.hasFilter()) {
1941 filteredAtLeaf(l, h);
1942 return;
1943 }
1944 size = h - l;
1945 for (int i = l; i < h; ++i) {
1946 long x = prefix.lget(i);
1947 sum += x;
1948 updateMin(i, x);
1949 updateMax(i, x);
1950 }
1951 }
1952
1953 void filteredAtLeaf(int l, int h) {
1954 for (int i = l; i < h; ++i) {
1955 if (prefix.isSelected(i)) {
1956 long x = prefix.lget(i);
1957 ++size;
1958 sum += x;
1959 updateMin(i, x);
1960 updateMax(i, x);
1961 }
1962 }
1963 }
1964
1965 public String toString() {
1966 return
1967 "size: " + size +
1968 " min: " + min + " (index " + indexOfMin +
1969 ") max: " + max + " (index " + indexOfMax +
1970 ") sum: " + sum;
1971 }
1972 }
1973
1974 // count
1975
1976 static final class FJOCountSelected extends FJBase {
1977 final Predicate selector;
1978 int count;
1979 FJOCountSelected(Prefix prefix, int lo, int hi, FJBase next,
1980 Predicate selector) {
1981 super(prefix, lo, hi, next);
1982 this.selector = selector;
1983 }
1984 FJBase newSubtask(int l, int h, FJBase r) {
1985 return new FJOCountSelected(prefix, l, h, r, selector);
1986 }
1987 void onReduce(FJBase right) {
1988 count += ((FJOCountSelected)right).count;
1989 }
1990 void atLeaf(int l, int h) {
1991 final Object[] array = prefix.ogetArray();
1992 if (array == null) return;
1993 final Predicate sel = this.selector;
1994 if (sel == null)
1995 count = h - l;
1996 else {
1997 int n = 0;
1998 for (int i = l; i < h; ++i) {
1999 if (sel.op(array[i]))
2000 ++n;
2001 }
2002 count = n;
2003 }
2004 }
2005 }
2006
2007 static final class FJDCountSelected extends FJBase {
2008 final DoublePredicate selector;
2009 int count;
2010 FJDCountSelected(Prefix prefix, int lo, int hi, FJBase next,
2011 DoublePredicate selector) {
2012 super(prefix, lo, hi, next);
2013 this.selector = selector;
2014 }
2015 FJBase newSubtask(int l, int h, FJBase r) {
2016 return new FJDCountSelected(prefix, l, h, r, selector);
2017 }
2018 void onReduce(FJBase right) {
2019 count += ((FJDCountSelected)right).count;
2020 }
2021 void atLeaf(int l, int h) {
2022 final double[] array = prefix.dgetArray();
2023 if (array == null) return;
2024 final DoublePredicate sel = this.selector;
2025 if (sel == null)
2026 count = h - l;
2027 else {
2028 int n = 0;
2029 for (int i = l; i < h; ++i) {
2030 if (sel.op(array[i]))
2031 ++n;
2032 }
2033 count = n;
2034 }
2035 }
2036 }
2037
2038 static final class FJLCountSelected extends FJBase {
2039 final LongPredicate selector;
2040 int count;
2041 FJLCountSelected(Prefix prefix, int lo, int hi, FJBase next,
2042 LongPredicate selector) {
2043 super(prefix, lo, hi, next);
2044 this.selector = selector;
2045 }
2046 FJBase newSubtask(int l, int h, FJBase r) {
2047 return new FJLCountSelected(prefix, l, h, r, selector);
2048 }
2049 void onReduce(FJBase right) {
2050 count += ((FJLCountSelected)right).count;
2051 }
2052 void atLeaf(int l, int h) {
2053 final long[] array = prefix.lgetArray();
2054 if (array == null) return;
2055 final LongPredicate sel = this.selector;
2056 if (sel == null)
2057 count = h - l;
2058 else {
2059 int n = 0;
2060 for (int i = l; i < h; ++i) {
2061 if (sel.op(array[i]))
2062 ++n;
2063 }
2064 count = n;
2065 }
2066 }
2067 }
2068
2069 /**
2070 * Base for cancellable search tasks. Same idea as FJBase
2071 * but cancels tasks when result nonnegative.
2072 */
2073 static abstract class FJSearchBase extends RecursiveAction {
2074 final Prefix prefix;
2075 final int lo;
2076 final int hi;
2077 final FJSearchBase next;
2078 final AtomicInteger result;
2079
2080 FJSearchBase(Prefix prefix, int lo, int hi,
2081 FJSearchBase next,
2082 AtomicInteger result) {
2083 this.prefix = prefix;
2084 this.lo = lo;
2085 this.hi = hi;
2086 this.next = next;
2087 this.result = result;
2088 }
2089
2090 public void compute() {
2091 if (result.get() >= 0)
2092 return;
2093 FJSearchBase r = null;
2094 int l = lo;
2095 int h = hi;
2096 int g = prefix.getThreshold();
2097 while (h - l > g) {
2098 int rh = h;
2099 h = (l + h) >>> 1;
2100 (r = newSubtask(h, rh, r)).fork();
2101 }
2102 atLeaf(l, h);
2103 boolean stopping = false;
2104 while (r != null) {
2105 stopping |= result.get() >= 0;
2106 if (ForkJoinWorkerThread.removeIfNextLocalTask(r)) {
2107 if (!stopping)
2108 r.atLeaf(r.lo, r.hi);
2109 }
2110 else if (stopping)
2111 r.cancel();
2112 else
2113 r.join();
2114 r = r.next;
2115 }
2116 }
2117 abstract FJSearchBase newSubtask(int l, int h, FJSearchBase r);
2118 abstract void atLeaf(int l, int h);
2119 }
2120
2121 // select any
2122
2123 static final class FJOSelectAny extends FJSearchBase {
2124 final Predicate selector;
2125 FJOSelectAny(Prefix prefix, int lo, int hi, FJSearchBase next,
2126 AtomicInteger result, Predicate selector) {
2127 super(prefix, lo, hi, next, result);
2128 this.selector = selector;
2129 }
2130 FJSearchBase newSubtask(int l, int h, FJSearchBase r) {
2131 return new FJOSelectAny(prefix, l, h, r, result, selector);
2132 }
2133 void atLeaf(int l, int h) {
2134 final Object[] array = prefix.ogetArray();
2135 if (array == null) return;
2136 for (int i = l; i < h; ++i) {
2137 if (selector.op(array[i])) {
2138 result.compareAndSet(-1, i);
2139 break;
2140 }
2141 else if (result.get() >= 0)
2142 break;
2143 }
2144 }
2145 }
2146
2147 static final class FJDSelectAny extends FJSearchBase {
2148 final DoublePredicate selector;
2149 FJDSelectAny(Prefix prefix, int lo, int hi, FJSearchBase next,
2150 AtomicInteger result, DoublePredicate selector) {
2151 super(prefix, lo, hi, next, result);
2152 this.selector = selector;
2153 }
2154 FJSearchBase newSubtask(int l, int h, FJSearchBase r) {
2155 return new FJDSelectAny(prefix, l, h, r, result, selector);
2156 }
2157 void atLeaf(int l, int h) {
2158 final double[] array = prefix.dgetArray();
2159 if (array == null) return;
2160 for (int i = l; i < h; ++i) {
2161 if (selector.op(array[i])) {
2162 result.compareAndSet(-1, i);
2163 break;
2164 }
2165 else if (result.get() >= 0)
2166 break;
2167 }
2168 }
2169 }
2170
2171 static final class FJLSelectAny extends FJSearchBase {
2172 final LongPredicate selector;
2173 FJLSelectAny(Prefix prefix, int lo, int hi, FJSearchBase next,
2174 AtomicInteger result, LongPredicate selector) {
2175 super(prefix, lo, hi, next, result);
2176 this.selector = selector;
2177 }
2178 FJSearchBase newSubtask(int l, int h, FJSearchBase r) {
2179 return new FJLSelectAny(prefix, l, h, r, result, selector);
2180 }
2181 void atLeaf(int l, int h) {
2182 final long[] array = prefix.lgetArray();
2183 if (array == null) return;
2184 for (int i = l; i < h; ++i) {
2185 if (selector.op(array[i])) {
2186 result.compareAndSet(-1, i);
2187 break;
2188 }
2189 else if (result.get() >= 0)
2190 break;
2191 }
2192 }
2193 }
2194
2195 // index of
2196
2197 static final class FJOIndexOf extends FJSearchBase {
2198 final Object target;
2199 FJOIndexOf(Prefix prefix, int lo, int hi, FJSearchBase next,
2200 AtomicInteger result, Object target) {
2201 super(prefix, lo, hi, next, result);
2202 this.target = target;
2203 }
2204 FJSearchBase newSubtask(int l, int h, FJSearchBase r) {
2205 return new FJOIndexOf(prefix, l, h, r, result, target);
2206 }
2207 void atLeaf(int l, int h) {
2208 final Object[] array = prefix.ogetArray();
2209 if (array == null) return;
2210 for (int i = l; i < h; ++i) {
2211 if (target.equals(array[i])) {
2212 result.compareAndSet(-1, i);
2213 break;
2214 }
2215 else if (result.get() >= 0)
2216 break;
2217 }
2218 }
2219 }
2220
2221 static final class FJDIndexOf extends FJSearchBase {
2222 final double target;
2223 FJDIndexOf(Prefix prefix, int lo, int hi, FJSearchBase next,
2224 AtomicInteger result, double target) {
2225 super(prefix, lo, hi, next, result);
2226 this.target = target;
2227 }
2228 FJSearchBase newSubtask(int l, int h, FJSearchBase r) {
2229 return new FJDIndexOf(prefix, l, h, r, result, target);
2230 }
2231 void atLeaf(int l, int h) {
2232 final double[] array = prefix.dgetArray();
2233 if (array == null) return;
2234 for (int i = l; i < h; ++i) {
2235 if (target == (array[i])) {
2236 result.compareAndSet(-1, i);
2237 break;
2238 }
2239 else if (result.get() >= 0)
2240 break;
2241 }
2242 }
2243 }
2244
2245 static final class FJLIndexOf extends FJSearchBase {
2246 final long target;
2247 FJLIndexOf(Prefix prefix, int lo, int hi, FJSearchBase next,
2248 AtomicInteger result, long target) {
2249 super(prefix, lo, hi, next, result);
2250 this.target = target;
2251 }
2252 FJSearchBase newSubtask(int l, int h, FJSearchBase r) {
2253 return new FJLIndexOf(prefix, l, h, r, result, target);
2254 }
2255 void atLeaf(int l, int h) {
2256 final long[] array = prefix.lgetArray();
2257 if (array == null) return;
2258 for (int i = l; i < h; ++i) {
2259 if (target == (array[i])) {
2260 result.compareAndSet(-1, i);
2261 break;
2262 }
2263 else if (result.get() >= 0)
2264 break;
2265 }
2266 }
2267 }
2268
2269 // select all
2270
2271 /**
2272 * SelectAll proceeds in two passes. In the first phase, indices
2273 * of matching elements are recorded in indices array. In second
2274 * pass, once the size of results is known and result array is
2275 * constructed in driver, the matching elements are placed into
2276 * corresponding result positions.
2277 */
2278 static final class FJSelectAll extends RecursiveAction {
2279 final FJSelectAllDriver driver;
2280 FJSelectAll left, right;
2281 final int lo;
2282 final int hi;
2283 int count; // number of matching elements
2284 int offset;
2285 boolean isInternal; // true if this is a non-leaf node
2286
2287 FJSelectAll(FJSelectAllDriver driver, int lo, int hi) {
2288 this.driver = driver;
2289 this.lo = lo;
2290 this.hi = hi;
2291 }
2292
2293 public void compute() {
2294 int l = lo;
2295 int h = hi;
2296 FJSelectAllDriver d = driver;
2297 if (d.phase == 0) {
2298 Prefix p = d.prefix;
2299 if (isInternal = (h - l > p.getThreshold()))
2300 internalPhase0();
2301 else
2302 count = p.leafIndexSelected(l, h, true, d.indices);
2303 }
2304 else if (count != 0) {
2305 if (isInternal)
2306 internalPhase1();
2307 else
2308 d.leafPhase1(l, l+count, offset);
2309 }
2310 }
2311
2312 void internalPhase0() {
2313 int mid = (lo + hi) >>> 1;
2314 FJSelectAll l = new FJSelectAll(driver, lo, mid);
2315 FJSelectAll r = new FJSelectAll(driver, mid, hi);
2316 forkJoin(l, r);
2317 int ln = l.count;
2318 if (ln != 0)
2319 left = l;
2320 int rn = r.count;
2321 if (rn != 0)
2322 right = r;
2323 count = ln + rn;
2324 }
2325
2326 void internalPhase1() {
2327 int k = offset;
2328 if (left != null) {
2329 int ln = left.count;
2330 left.offset = k;
2331 left.reinitialize();
2332 if (right != null) {
2333 right.offset = k + ln;
2334 right.reinitialize();
2335 forkJoin(left, right);
2336 }
2337 else
2338 left.compute();
2339 }
2340 else if (right != null) {
2341 right.offset = k;
2342 right.compute();
2343 }
2344 }
2345 }
2346
2347 static abstract class FJSelectAllDriver extends RecursiveAction {
2348 final int[] indices;
2349 final Prefix prefix;
2350 int phase;
2351 FJSelectAllDriver(Prefix prefix) {
2352 this.prefix = prefix;
2353 int n = prefix.upperBound - prefix.firstIndex;
2354 indices = new int[n];
2355 }
2356 public final void compute() {
2357 FJSelectAll r = new FJSelectAll
2358 (this, prefix.firstIndex, prefix.upperBound);
2359 r.compute();
2360 createResults(r.count);
2361 phase = 1;
2362 r.compute();
2363 }
2364 abstract void createResults(int size);
2365 abstract void leafPhase1(int loIdx, int hiIdx, int offset);
2366 }
2367
2368 static final class FJOSelectAllDriver extends FJSelectAllDriver {
2369 final Class elementType;
2370 Object[] results;
2371 FJOSelectAllDriver(Prefix prefix, Class elementType) {
2372 super(prefix);
2373 this.elementType = elementType;
2374 }
2375 void createResults(int size) {
2376 results = (Object[])Array.newInstance(elementType, size);
2377 }
2378 void leafPhase1(int loIdx, int hiIdx, int offset) {
2379 prefix.leafTransferByIndex(indices, loIdx, hiIdx, results, offset);
2380 }
2381 }
2382
2383 static final class FJDSelectAllDriver extends FJSelectAllDriver {
2384 double[] results;
2385 FJDSelectAllDriver(Prefix prefix) {
2386 super(prefix);
2387 }
2388 void createResults(int size) {
2389 results = new double[size];
2390 }
2391 void leafPhase1(int loIdx, int hiIdx, int offset) {
2392 prefix.leafTransferByIndex(indices, loIdx, hiIdx, results, offset);
2393 }
2394 }
2395
2396 static final class FJLSelectAllDriver extends FJSelectAllDriver {
2397 long[] results;
2398 FJLSelectAllDriver(Prefix prefix) {
2399 super(prefix);
2400 }
2401 void createResults(int size) {
2402 results = new long[size];
2403 }
2404 void leafPhase1(int loIdx, int hiIdx, int offset) {
2405 prefix.leafTransferByIndex(indices, loIdx, hiIdx, results, offset);
2406 }
2407 }
2408
2409 /**
2410 * Root node for FJRemoveAll. Spawns subtasks and shifts elements
2411 * as indices become available, bypassing index array creation
2412 * when offsets are known. This differs from SelectAll mainly in
2413 * that data movement is all done by the driver rather than in a
2414 * second parallel pass.
2415 */
2416 static final class FJRemoveAllDriver extends RecursiveAction {
2417 final Prefix prefix;
2418 final int lo;
2419 final int hi;
2420 final int[] indices;
2421 int offset;
2422 FJRemoveAllDriver(Prefix prefix, int lo, int hi) {
2423 this.prefix = prefix;
2424 this.lo = lo;
2425 this.hi = hi;
2426 this.indices = new int[hi - lo];
2427 }
2428
2429 public void compute() {
2430 FJRemoveAll r = null;
2431 int l = lo;
2432 int h = hi;
2433 int g = prefix.getThreshold();
2434 while (h - l > g) {
2435 int rh = h;
2436 h = (l + h) >>> 1;
2437 (r = new FJRemoveAll(prefix, h, rh, r, indices)).fork();
2438 }
2439 int k = prefix.leafMoveSelected(l, h, l, false);
2440 while (r != null) {
2441 if (ForkJoinWorkerThread.removeIfNextLocalTask(r))
2442 k = prefix.leafMoveSelected(r.lo, r.hi, k, false);
2443 else {
2444 r.join();
2445 int n = r.count;
2446 if (n != 0)
2447 prefix.leafMoveByIndex(indices, r.lo, r.lo+n, k);
2448 k += n;
2449 FJRemoveAll rr = r.right;
2450 if (rr != null)
2451 k = inorderMove(rr, k);
2452 }
2453 r = r.next;
2454 }
2455 offset = k;
2456 }
2457
2458 /**
2459 * Inorder traversal to move indexed elements across reachable
2460 * nodes. This guarantees that element shifts don't overwrite
2461 * those still being used by active subtasks.
2462 */
2463 static int inorderMove(FJRemoveAll t, int index) {
2464 while (t != null) {
2465 int n = t.count;
2466 if (n != 0)
2467 t.prefix.leafMoveByIndex(t.indices, t.lo, t.lo+n, index);
2468 index += n;
2469 FJRemoveAll p = t.next;
2470 if (p != null)
2471 index = inorderMove(p, index);
2472 t = t.right;
2473 }
2474 return index;
2475 }
2476 }
2477
2478 /**
2479 * Basic FJ tssk for non-root FJRemoveAll nodes. Differs from
2480 * FJBase because it requires maintaing explicit right pointers so
2481 * FJRemoveAllDriver can traverse them
2482 */
2483 static final class FJRemoveAll extends RecursiveAction {
2484 final Prefix prefix;
2485 final int lo;
2486 final int hi;
2487 final FJRemoveAll next;
2488 final int[] indices;
2489 int count;
2490 FJRemoveAll right;
2491 FJRemoveAll(Prefix prefix, int lo, int hi, FJRemoveAll next,
2492 int[] indices) {
2493 this.prefix = prefix;
2494 this.lo = lo;
2495 this.hi = hi;
2496 this.next = next;
2497 this.indices = indices;
2498 }
2499
2500 public void compute() {
2501 FJRemoveAll r = null;
2502 int l = lo;
2503 int h = hi;
2504 int g = prefix.getThreshold();
2505 while (h - l > g) {
2506 int rh = h;
2507 h = (l + h) >>> 1;
2508 (r = new FJRemoveAll(prefix, h, rh, r, indices)).fork();
2509 }
2510 right = r;
2511 count = prefix.leafIndexSelected(l, h, false, indices);
2512 while (r != null) {
2513 if (ForkJoinWorkerThread.removeIfNextLocalTask(r))
2514 r.count = prefix.leafIndexSelected
2515 (r.lo, r.hi, false, indices);
2516 else
2517 r.join();
2518 r = r.next;
2519 }
2520 }
2521 }
2522
2523 // unique elements
2524
2525 static final class FJUniquifier extends FJBase {
2526 final UniquifierTable table;
2527 int count;
2528 FJUniquifier(Prefix prefix, int lo, int hi, FJBase next,
2529 UniquifierTable table) {
2530 super(prefix, lo, hi, next);
2531 this.table = table;
2532 }
2533 FJBase newSubtask(int l, int h, FJBase r) {
2534 return new FJUniquifier(prefix, l, h, r, table);
2535 }
2536 void atLeaf(int l, int h) {
2537 count = table.addElements(l, h);
2538 }
2539 void onReduce(FJBase right) {
2540 count += ((FJUniquifier)right).count;
2541 }
2542 }
2543
2544 /**
2545 * Base class of fixed-size hash tables for
2546 * uniquification. Opportunistically subclasses
2547 * AtomicLongArray. The high word of each slot is the cached
2548 * massaged hash of an element, and the low word contains its
2549 * index, plus one, to ensure that a zero tab entry means
2550 * empty. The mechanics for this are just folded into the
2551 * main addElements method.
2552 * Each leaf step places source array elements into table,
2553 * Even though this table undergoes a lot of contention when
2554 * elements are concurrently inserted by parallel threads, it is
2555 * generally faster to do this than to have separate tables and
2556 * then merge them.
2557 */
2558 static abstract class UniquifierTable extends AtomicLongArray {
2559 UniquifierTable(int size) {
2560 super(tableSizeFor(size));
2561 }
2562
2563 /** Returns a good size for table */
2564 static int tableSizeFor(int n) {
2565 int padded = n + (n >>> 1) + 1;
2566 if (padded < n) // int overflow
2567 throw new OutOfMemoryError();
2568 int s = 8;
2569 while (s < padded) s <<= 1;
2570 return s;
2571 }
2572
2573 // Same hashcode conditioning as HashMap
2574 static int hash(int h) {
2575 h ^= (h >>> 20) ^ (h >>> 12);
2576 return h ^ (h >>> 7) ^ (h >>> 4);
2577 }
2578
2579 /**
2580 * Add source elements from lo to hi; return count
2581 * of number of unique elements inserted
2582 */
2583 abstract int addElements(int lo, int hi);
2584 }
2585
2586 static final class OUniquifierTable extends UniquifierTable {
2587 final Object[] source;
2588 final Predicate selector;
2589 final boolean byIdentity;
2590 OUniquifierTable(int size, Object[] array, Predicate selector,
2591 boolean byIdentity) {
2592 super(size);
2593 this.source = array;
2594 this.selector = selector;
2595 this.byIdentity = byIdentity;
2596 }
2597
2598 int addElements(int lo, int hi) {
2599 final Predicate selector = this.selector;
2600 final Object[] src = source;
2601 final int mask = length() - 1;
2602 int count = 0;
2603 for (int k = lo; k < hi; ++k) {
2604 Object x = src[k];
2605 if (x == null || (selector != null && !selector.op(x)))
2606 continue;
2607 int hc = byIdentity? System.identityHashCode(x): x.hashCode();
2608 int hash = hash(hc);
2609 long entry = (((long)hash) << 32) + (k + 1);
2610 int idx = hash & mask;
2611 for (;;) {
2612 long d = get(idx);
2613 if (d != 0) {
2614 if ((int)(d >>> 32) == hash) {
2615 Object y = src[(int)((d - 1) & 0x7fffffffL)];
2616 if (byIdentity? (x == y) : x.equals(y))
2617 break;
2618 }
2619 idx = (idx + 1) & mask;
2620 }
2621 else if (compareAndSet(idx, 0, entry)) {
2622 ++count;
2623 break;
2624 }
2625 }
2626 }
2627 return count;
2628 }
2629
2630 /**
2631 * Return new array holding all elements.
2632 */
2633 Object[] uniqueElements(int size) {
2634 Object[] src = source;
2635 Class sclass = src.getClass().getComponentType();
2636 Object[] res = (Object[])Array.newInstance(sclass, size);
2637 int k = 0;
2638 int n = length();
2639 for (int i = 0; i < n && k < size; ++i) {
2640 long d = get(i);
2641 if (d != 0)
2642 res[k++] = src[((int)((d - 1) & 0x7fffffffL))];
2643 }
2644 return res;
2645 }
2646 }
2647
2648 static final class DUniquifierTable extends UniquifierTable {
2649 final double[] source;
2650 final DoublePredicate selector;
2651 DUniquifierTable(int size, double[] array,
2652 DoublePredicate selector) {
2653 super(size);
2654 this.source = array;
2655 this.selector = selector;
2656 }
2657
2658 int addElements(int lo, int hi) {
2659 final DoublePredicate selector = this.selector;
2660 final double[] src = source;
2661 final int mask = length() - 1;
2662 int count = 0;
2663 for (int k = lo; k < hi; ++k) {
2664 double x = src[k];
2665 if (selector != null && !selector.op(x))
2666 continue;
2667 long bits = Double.doubleToLongBits(x);
2668 int hash = hash((int)(bits ^ (bits >>> 32)));;
2669 long entry = (((long)hash) << 32) + (k + 1);
2670 int idx = hash & mask;
2671 for (;;) {
2672 long d = get(idx);
2673 if (d != 0) {
2674 if ((int)(d >>> 32) == hash &&
2675 x == (src[(int)((d - 1) & 0x7fffffffL)]))
2676 break;
2677 idx = (idx + 1) & mask;
2678 }
2679 else if (compareAndSet(idx, 0, entry)) {
2680 ++count;
2681 break;
2682 }
2683 }
2684 }
2685 return count;
2686 }
2687
2688 double[] uniqueElements(int size) {
2689 double[] res = new double[size];
2690 double[] src = source;
2691 int k = 0;
2692 int n = length();
2693 for (int i = 0; i < n && k < size; ++i) {
2694 long d = get(i);
2695 if (d != 0)
2696 res[k++] = src[((int)((d - 1) & 0x7fffffffL))];
2697 }
2698 return res;
2699 }
2700 }
2701
2702 static final class LUniquifierTable extends UniquifierTable {
2703 final long[] source;
2704 final LongPredicate selector;
2705 LUniquifierTable(int size, long[] array, LongPredicate selector) {
2706 super(size);
2707 this.source = array;
2708 this.selector = selector;
2709 }
2710
2711 int addElements(int lo, int hi) {
2712 final LongPredicate selector = this.selector;
2713 final long[] src = source;
2714 final int mask = length() - 1;
2715 int count = 0;
2716 for (int k = lo; k < hi; ++k) {
2717 long x = src[k];
2718 if (selector != null && !selector.op(x))
2719 continue;
2720 int hash = hash((int)(x ^ (x >>> 32)));
2721 long entry = (((long)hash) << 32) + (k + 1);
2722 int idx = hash & mask;
2723 for (;;) {
2724 long d = get(idx);
2725 if (d != 0) {
2726 if ((int)(d >>> 32) == hash &&
2727 x == (src[(int)((d - 1) & 0x7fffffffL)]))
2728 break;
2729 idx = (idx + 1) & mask;
2730 }
2731 else if (compareAndSet(idx, 0, entry)) {
2732 ++count;
2733 break;
2734 }
2735 }
2736 }
2737 return count;
2738 }
2739
2740 long[] uniqueElements(int size) {
2741 long[] res = new long[size];
2742 long[] src = source;
2743 int k = 0;
2744 int n = length();
2745 for (int i = 0; i < n && k < size; ++i) {
2746 long d = get(i);
2747 if (d != 0)
2748 res[k++] = src[((int)((d - 1) & 0x7fffffffL))];
2749 }
2750 return res;
2751 }
2752 }
2753
2754 /**
2755 * Sorter classes based mainly on CilkSort
2756 * <A href="http://supertech.lcs.mit.edu/cilk/"> Cilk</A>:
2757 * Basic algorithm:
2758 * if array size is small, just use a sequential quicksort
2759 * Otherwise:
2760 * 1. Break array in half.
2761 * 2. For each half,
2762 * a. break the half in half (i.e., quarters),
2763 * b. sort the quarters
2764 * c. merge them together
2765 * 3. merge together the two halves.
2766 *
2767 * One reason for splitting in quarters is that this guarantees
2768 * that the final sort is in the main array, not the workspace
2769 * array. (workspace and main swap roles on each subsort step.)
2770 * Leaf-level sorts use a Sequential quicksort, that in turn uses
2771 * insertion sort if under threshold. Otherwise it uses median of
2772 * three to pick pivot, and loops rather than recurses along left
2773 * path.
2774 *
2775 * It is sad but true that sort and merge performance are
2776 * sensitive enough to inner comparison overhead to warrant
2777 * creating 6 versions (not just 3) -- one each for natural
2778 * comparisons vs supplied comparators.
2779 */
2780 static final class FJOSorter extends RecursiveAction {
2781 final Comparator cmp;
2782 final Object[] a; // array to be sorted.
2783 final Object[] w; // workspace for merge
2784 final int origin; // origin of the part of array we deal with
2785 final int n; // Number of elements in (sub)arrays.
2786 final int gran; // split control
2787 FJOSorter(Comparator cmp,
2788 Object[] a, Object[] w, int origin, int n, int gran) {
2789 this.cmp = cmp;
2790 this.a = a; this.w = w; this.origin = origin; this.n = n;
2791 this.gran = gran;
2792 }
2793
2794 public void compute() {
2795 int l = origin;
2796 int g = gran;
2797 if (n > g) {
2798 int h = n >>> 1; // half
2799 int q = n >>> 2; // lower quarter index
2800 int u = h + q; // upper quarter
2801 forkJoin(new FJSubSorter
2802 (new FJOSorter(cmp, a, w, l, q, g),
2803 new FJOSorter(cmp, a, w, l+q, h-q, g),
2804 new FJOMerger(cmp, a, w, l, q,
2805 l+q, h-q, l, g, null)),
2806 new FJSubSorter
2807 (new FJOSorter(cmp, a, w, l+h, q, g),
2808 new FJOSorter(cmp, a, w, l+u, n-u, g),
2809 new FJOMerger(cmp, a, w, l+h, q,
2810 l+u, n-u, l+h, g, null)));
2811 new FJOMerger(cmp, w, a, l, h,
2812 l+h, n-h, l, g, null).compute();
2813 }
2814 else
2815 oquickSort(a, cmp, l, l+n-1);
2816 }
2817 }
2818
2819 static final class FJOCSorter extends RecursiveAction {
2820 final Comparable[] a; final Comparable[] w;
2821 final int origin; final int n; final int gran;
2822 FJOCSorter(Comparable[] a, Comparable[] w,
2823 int origin, int n, int gran) {
2824 this.a = a; this.w = w; this.origin = origin; this.n = n;
2825 this.gran = gran;
2826 }
2827 public void compute() {
2828 int l = origin;
2829 int g = gran;
2830 if (n > g) {
2831 int h = n >>> 1;
2832 int q = n >>> 2;
2833 int u = h + q;
2834 forkJoin(new FJSubSorter
2835 (new FJOCSorter(a, w, l, q, g),
2836 new FJOCSorter(a, w, l+q, h-q, g),
2837 new FJOCMerger(a, w, l, q,
2838 l+q, h-q, l, g, null)),
2839 new FJSubSorter
2840 (new FJOCSorter(a, w, l+h, q, g),
2841 new FJOCSorter(a, w, l+u, n-u, g),
2842 new FJOCMerger(a, w, l+h, q,
2843 l+u, n-u, l+h, g, null)));
2844 new FJOCMerger(w, a, l, h,
2845 l+h, n-h, l, g, null).compute();
2846 }
2847 else
2848 ocquickSort(a, l, l+n-1);
2849 }
2850 }
2851
2852 static final class FJDSorter extends RecursiveAction {
2853 final DoubleComparator cmp; final double[] a; final double[] w;
2854 final int origin; final int n; final int gran;
2855 FJDSorter(DoubleComparator cmp,
2856 double[] a, double[] w, int origin, int n, int gran) {
2857 this.cmp = cmp;
2858 this.a = a; this.w = w; this.origin = origin; this.n = n;
2859 this.gran = gran;
2860 }
2861 public void compute() {
2862 int l = origin;
2863 int g = gran;
2864 if (n > g) {
2865 int h = n >>> 1;
2866 int q = n >>> 2;
2867 int u = h + q;
2868 forkJoin(new FJSubSorter
2869 (new FJDSorter(cmp, a, w, l, q, g),
2870 new FJDSorter(cmp, a, w, l+q, h-q, g),
2871 new FJDMerger(cmp, a, w, l, q,
2872 l+q, h-q, l, g, null)),
2873 new FJSubSorter
2874 (new FJDSorter(cmp, a, w, l+h, q, g),
2875 new FJDSorter(cmp, a, w, l+u, n-u, g),
2876 new FJDMerger(cmp, a, w, l+h, q,
2877 l+u, n-u, l+h, g, null)));
2878 new FJDMerger(cmp, w, a, l, h,
2879 l+h, n-h, l, g, null).compute();
2880 }
2881 else
2882 dquickSort(a, cmp, l, l+n-1);
2883 }
2884 }
2885
2886 static final class FJDCSorter extends RecursiveAction {
2887 final double[] a; final double[] w;
2888 final int origin; final int n; final int gran;
2889 FJDCSorter(double[] a, double[] w, int origin,
2890 int n, int gran) {
2891 this.a = a; this.w = w; this.origin = origin; this.n = n;
2892 this.gran = gran;
2893 }
2894 public void compute() {
2895 int l = origin;
2896 int g = gran;
2897 if (n > g) {
2898 int h = n >>> 1;
2899 int q = n >>> 2;
2900 int u = h + q;
2901 forkJoin(new FJSubSorter
2902 (new FJDCSorter(a, w, l, q, g),
2903 new FJDCSorter(a, w, l+q, h-q, g),
2904 new FJDCMerger(a, w, l, q,
2905 l+q, h-q, l, g, null)),
2906 new FJSubSorter
2907 (new FJDCSorter(a, w, l+h, q, g),
2908 new FJDCSorter(a, w, l+u, n-u, g),
2909 new FJDCMerger(a, w, l+h, q,
2910 l+u, n-u, l+h, g, null)));
2911 new FJDCMerger(w, a, l, h,
2912 l+h, n-h, l, g, null).compute();
2913 }
2914 else
2915 dcquickSort(a, l, l+n-1);
2916 }
2917 }
2918
2919 static final class FJLSorter extends RecursiveAction {
2920 final LongComparator cmp; final long[] a; final long[] w;
2921 final int origin; final int n; final int gran;
2922 FJLSorter(LongComparator cmp,
2923 long[] a, long[] w, int origin, int n, int gran) {
2924 this.cmp = cmp;
2925 this.a = a; this.w = w; this.origin = origin; this.n = n;
2926 this.gran = gran;
2927 }
2928
2929 public void compute() {
2930 int l = origin;
2931 int g = gran;
2932 if (n > g) {
2933 int h = n >>> 1;
2934 int q = n >>> 2;
2935 int u = h + q;
2936 forkJoin(new FJSubSorter
2937 (new FJLSorter(cmp, a, w, l, q, g),
2938 new FJLSorter(cmp, a, w, l+q, h-q, g),
2939 new FJLMerger(cmp, a, w, l, q,
2940 l+q, h-q, l, g, null)),
2941 new FJSubSorter
2942 (new FJLSorter(cmp, a, w, l+h, q, g),
2943 new FJLSorter(cmp, a, w, l+u, n-u, g),
2944 new FJLMerger(cmp, a, w, l+h, q,
2945 l+u, n-u, l+h, g, null)));
2946 new FJLMerger(cmp, w, a, l, h,
2947 l+h, n-h, l, g, null).compute();
2948 }
2949 else
2950 lquickSort(a, cmp, l, l+n-1);
2951 }
2952 }
2953
2954 static final class FJLCSorter extends RecursiveAction {
2955 final long[] a; final long[] w;
2956 final int origin; final int n; final int gran;
2957 FJLCSorter(long[] a, long[] w, int origin,
2958 int n, int gran) {
2959 this.a = a; this.w = w; this.origin = origin; this.n = n;
2960 this.gran = gran;
2961 }
2962 public void compute() {
2963 int l = origin;
2964 int g = gran;
2965 if (n > g) {
2966 int h = n >>> 1;
2967 int q = n >>> 2;
2968 int u = h + q;
2969 forkJoin(new FJSubSorter
2970 (new FJLCSorter(a, w, l, q, g),
2971 new FJLCSorter(a, w, l+q, h-q, g),
2972 new FJLCMerger(a, w, l, q,
2973 l+q, h-q, l, g, null)),
2974 new FJSubSorter
2975 (new FJLCSorter(a, w, l+h, q, g),
2976 new FJLCSorter(a, w, l+u, n-u, g),
2977 new FJLCMerger(a, w, l+h, q,
2978 l+u, n-u, l+h, g, null)));
2979 new FJLCMerger(w, a, l, h,
2980 l+h, n-h, l, g, null).compute();
2981 }
2982 else
2983 lcquickSort(a, l, l+n-1);
2984 }
2985 }
2986
2987 /** Utility class to sort half a partitioned array */
2988 static final class FJSubSorter extends RecursiveAction {
2989 final RecursiveAction left;
2990 final RecursiveAction right;
2991 final RecursiveAction merger;
2992 FJSubSorter(RecursiveAction left, RecursiveAction right,
2993 RecursiveAction merger){
2994 this.left = left; this.right = right; this.merger = merger;
2995 }
2996 public void compute() {
2997 forkJoin(left, right);
2998 merger.compute();
2999 }
3000 }
3001
3002 /**
3003 * Perform merging for FJSorter. If big enough, splits Left
3004 * partition in half; finds the greatest point in Right partition
3005 * less than the beginning of the second half of Left via binary
3006 * search; and then, in parallel, merges left half of Left with
3007 * elements of Right up to split point, and merges right half of
3008 * Left with elements of R past split point. At leaf, it just
3009 * sequentially merges. This is all messy to code; sadly we need
3010 * six versions.
3011 */
3012 static final class FJOMerger extends RecursiveAction {
3013 final Comparator cmp;
3014 final Object[] a; // partitioned array.
3015 final Object[] w; // Output array.
3016 final int lo; // relative origin of left side of a
3017 final int ln; // number of elements on left of a
3018 final int ro; // relative origin of right side of a
3019 final int rn; // number of elements on right of a
3020 final int wo; // origin for output
3021 final int gran;
3022 final FJOMerger next;
3023
3024 FJOMerger(Comparator cmp, Object[] a, Object[] w,
3025 int lo, int ln, int ro, int rn, int wo,
3026 int gran, FJOMerger next) {
3027 this.cmp = cmp;
3028 this.a = a; this.w = w;
3029 this.lo = lo; this.ln = ln;
3030 this.ro = ro; this.rn = rn;
3031 this.wo = wo;
3032 this.gran = gran;
3033 this.next = next;
3034 }
3035
3036 public void compute() {
3037 // spawn right subtasks
3038 FJOMerger rights = null;
3039 int nleft = ln;
3040 int nright = rn;
3041 while (nleft > gran) {
3042 int lh = nleft >>> 1;
3043 int splitIndex = lo + lh;
3044 Object split = a[splitIndex];
3045 // binary search r for split
3046 int rl = 0;
3047 int rh = nright;
3048 while (rl < rh) {
3049 int mid = (rl + rh) >>> 1;
3050 if (cmp.compare(split, a[ro + mid]) <= 0)
3051 rh = mid;
3052 else
3053 rl = mid + 1;
3054 }
3055 (rights = new FJOMerger
3056 (cmp, a, w, splitIndex, nleft-lh, ro+rh,
3057 nright-rh, wo+lh+rh, gran, rights)).fork();
3058 nleft = lh;
3059 nright = rh;
3060 }
3061
3062 // sequentially merge
3063 int l = lo;
3064 int lFence = lo + nleft;
3065 int r = ro;
3066 int rFence = ro + nright;
3067 int k = wo;
3068 while (l < lFence && r < rFence) {
3069 Object al = a[l];
3070 Object ar = a[r];
3071 Object t;
3072 if (cmp.compare(al, ar) <= 0) {++l; t=al;} else {++r; t=ar;}
3073 w[k++] = t;
3074 }
3075 while (l < lFence)
3076 w[k++] = a[l++];
3077 while (r < rFence)
3078 w[k++] = a[r++];
3079
3080 // join subtasks
3081 while (rights != null) {
3082 if (ForkJoinWorkerThread.removeIfNextLocalTask(rights))
3083 rights.compute();
3084 else
3085 rights.join();
3086 rights = rights.next;
3087 }
3088 }
3089 }
3090
3091 static final class FJOCMerger extends RecursiveAction {
3092 final Comparable[] a; final Comparable[] w;
3093 final int lo; final int ln; final int ro; final int rn; final int wo;
3094 final int gran;
3095 final FJOCMerger next;
3096 FJOCMerger(Comparable[] a, Comparable[] w, int lo,
3097 int ln, int ro, int rn, int wo,
3098 int gran, FJOCMerger next) {
3099 this.a = a; this.w = w;
3100 this.lo = lo; this.ln = ln; this.ro = ro; this.rn = rn;
3101 this.wo = wo;
3102 this.gran = gran;
3103 this.next = next;
3104 }
3105
3106 public void compute() {
3107 FJOCMerger rights = null;
3108 int nleft = ln;
3109 int nright = rn;
3110 while (nleft > gran) {
3111 int lh = nleft >>> 1;
3112 int splitIndex = lo + lh;
3113 Comparable split = a[splitIndex];
3114 int rl = 0;
3115 int rh = nright;
3116 while (rl < rh) {
3117 int mid = (rl + rh) >>> 1;
3118 if (split.compareTo(a[ro + mid]) <= 0)
3119 rh = mid;
3120 else
3121 rl = mid + 1;
3122 }
3123 (rights = new FJOCMerger
3124 (a, w, splitIndex, nleft-lh, ro+rh,
3125 nright-rh, wo+lh+rh, gran, rights)).fork();
3126 nleft = lh;
3127 nright = rh;
3128 }
3129
3130 int l = lo;
3131 int lFence = lo + nleft;
3132 int r = ro;
3133 int rFence = ro + nright;
3134 int k = wo;
3135 while (l < lFence && r < rFence) {
3136 Comparable al = a[l];
3137 Comparable ar = a[r];
3138 Comparable t;
3139 if (al.compareTo(ar) <= 0) {++l; t=al;} else {++r; t=ar; }
3140 w[k++] = t;
3141 }
3142 while (l < lFence)
3143 w[k++] = a[l++];
3144 while (r < rFence)
3145 w[k++] = a[r++];
3146
3147 while (rights != null) {
3148 if (ForkJoinWorkerThread.removeIfNextLocalTask(rights))
3149 rights.compute();
3150 else
3151 rights.join();
3152 rights = rights.next;
3153 }
3154 }
3155 }
3156
3157 static final class FJDMerger extends RecursiveAction {
3158 final DoubleComparator cmp; final double[] a; final double[] w;
3159 final int lo; final int ln; final int ro; final int rn; final int wo;
3160 final int gran;
3161 final FJDMerger next;
3162 FJDMerger(DoubleComparator cmp, double[] a, double[] w,
3163 int lo, int ln, int ro, int rn, int wo,
3164 int gran, FJDMerger next) {
3165 this.cmp = cmp;
3166 this.a = a; this.w = w;
3167 this.lo = lo; this.ln = ln;
3168 this.ro = ro; this.rn = rn;
3169 this.wo = wo;
3170 this.gran = gran;
3171 this.next = next;
3172 }
3173 public void compute() {
3174 FJDMerger rights = null;
3175 int nleft = ln;
3176 int nright = rn;
3177 while (nleft > gran) {
3178 int lh = nleft >>> 1;
3179 int splitIndex = lo + lh;
3180 double split = a[splitIndex];
3181 int rl = 0;
3182 int rh = nright;
3183 while (rl < rh) {
3184 int mid = (rl + rh) >>> 1;
3185 if (cmp.compare(split, a[ro + mid]) <= 0)
3186 rh = mid;
3187 else
3188 rl = mid + 1;
3189 }
3190 (rights = new FJDMerger
3191 (cmp, a, w, splitIndex, nleft-lh, ro+rh,
3192 nright-rh, wo+lh+rh, gran, rights)).fork();
3193 nleft = lh;
3194 nright = rh;
3195 }
3196
3197 int l = lo;
3198 int lFence = lo + nleft;
3199 int r = ro;
3200 int rFence = ro + nright;
3201 int k = wo;
3202 while (l < lFence && r < rFence) {
3203 double al = a[l];
3204 double ar = a[r];
3205 double t;
3206 if (cmp.compare(al, ar) <= 0) {++l; t=al;} else {++r; t=ar; }
3207 w[k++] = t;
3208 }
3209 while (l < lFence)
3210 w[k++] = a[l++];
3211 while (r < rFence)
3212 w[k++] = a[r++];
3213
3214 while (rights != null) {
3215 if (ForkJoinWorkerThread.removeIfNextLocalTask(rights))
3216 rights.compute();
3217 else
3218 rights.join();
3219 rights = rights.next;
3220 }
3221 }
3222 }
3223
3224 static final class FJDCMerger extends RecursiveAction {
3225 final double[] a; final double[] w;
3226 final int lo; final int ln; final int ro; final int rn; final int wo;
3227 final int gran;
3228 final FJDCMerger next;
3229 FJDCMerger(double[] a, double[] w, int lo,
3230 int ln, int ro, int rn, int wo,
3231 int gran, FJDCMerger next) {
3232 this.a = a; this.w = w;
3233 this.lo = lo; this.ln = ln;
3234 this.ro = ro; this.rn = rn;
3235 this.wo = wo;
3236 this.gran = gran;
3237 this.next = next;
3238 }
3239 public void compute() {
3240 FJDCMerger rights = null;
3241 int nleft = ln;
3242 int nright = rn;
3243 while (nleft > gran) {
3244 int lh = nleft >>> 1;
3245 int splitIndex = lo + lh;
3246 double split = a[splitIndex];
3247 int rl = 0;
3248 int rh = nright;
3249 while (rl < rh) {
3250 int mid = (rl + rh) >>> 1;
3251 if (split <= a[ro + mid])
3252 rh = mid;
3253 else
3254 rl = mid + 1;
3255 }
3256 (rights = new FJDCMerger
3257 (a, w, splitIndex, nleft-lh, ro+rh,
3258 nright-rh, wo+lh+rh, gran, rights)).fork();
3259 nleft = lh;
3260 nright = rh;
3261 }
3262
3263 int l = lo;
3264 int lFence = lo + nleft;
3265 int r = ro;
3266 int rFence = ro + nright;
3267 int k = wo;
3268 while (l < lFence && r < rFence) {
3269 double al = a[l];
3270 double ar = a[r];
3271 double t;
3272 if (al <= ar) {++l; t=al;} else {++r; t=ar; }
3273 w[k++] = t;
3274 }
3275 while (l < lFence)
3276 w[k++] = a[l++];
3277 while (r < rFence)
3278 w[k++] = a[r++];
3279
3280 while (rights != null) {
3281 if (ForkJoinWorkerThread.removeIfNextLocalTask(rights))
3282 rights.compute();
3283 else
3284 rights.join();
3285 rights = rights.next;
3286 }
3287 }
3288 }
3289
3290 static final class FJLMerger extends RecursiveAction {
3291 final LongComparator cmp; final long[] a; final long[] w;
3292 final int lo; final int ln; final int ro; final int rn; final int wo;
3293 final int gran;
3294 final FJLMerger next;
3295 FJLMerger(LongComparator cmp, long[] a, long[] w,
3296 int lo, int ln, int ro, int rn, int wo,
3297 int gran, FJLMerger next) {
3298 this.cmp = cmp;
3299 this.a = a; this.w = w;
3300 this.lo = lo; this.ln = ln;
3301 this.ro = ro; this.rn = rn;
3302 this.wo = wo;
3303 this.gran = gran;
3304 this.next = next;
3305 }
3306 public void compute() {
3307 FJLMerger rights = null;
3308 int nleft = ln;
3309 int nright = rn;
3310 while (nleft > gran) {
3311 int lh = nleft >>> 1;
3312 int splitIndex = lo + lh;
3313 long split = a[splitIndex];
3314 int rl = 0;
3315 int rh = nright;
3316 while (rl < rh) {
3317 int mid = (rl + rh) >>> 1;
3318 if (cmp.compare(split, a[ro + mid]) <= 0)
3319 rh = mid;
3320 else
3321 rl = mid + 1;
3322 }
3323 (rights = new FJLMerger
3324 (cmp, a, w, splitIndex, nleft-lh, ro+rh,
3325 nright-rh, wo+lh+rh, gran, rights)).fork();
3326 nleft = lh;
3327 nright = rh;
3328 }
3329
3330 int l = lo;
3331 int lFence = lo + nleft;
3332 int r = ro;
3333 int rFence = ro + nright;
3334 int k = wo;
3335 while (l < lFence && r < rFence) {
3336 long al = a[l];
3337 long ar = a[r];
3338 long t;
3339 if (cmp.compare(al, ar) <= 0) {++l; t=al;} else {++r; t=ar;}
3340 w[k++] = t;
3341 }
3342 while (l < lFence)
3343 w[k++] = a[l++];
3344 while (r < rFence)
3345 w[k++] = a[r++];
3346
3347 while (rights != null) {
3348 if (ForkJoinWorkerThread.removeIfNextLocalTask(rights))
3349 rights.compute();
3350 else
3351 rights.join();
3352 rights = rights.next;
3353 }
3354 }
3355 }
3356
3357 static final class FJLCMerger extends RecursiveAction {
3358 final long[] a; final long[] w;
3359 final int lo; final int ln; final int ro; final int rn; final int wo;
3360 final int gran;
3361 final FJLCMerger next;
3362 FJLCMerger(long[] a, long[] w, int lo,
3363 int ln, int ro, int rn, int wo,
3364 int gran, FJLCMerger next) {
3365 this.a = a; this.w = w;
3366 this.lo = lo; this.ln = ln;
3367 this.ro = ro; this.rn = rn;
3368 this.wo = wo;
3369 this.gran = gran;
3370 this.next = next;
3371 }
3372 public void compute() {
3373 FJLCMerger rights = null;
3374 int nleft = ln;
3375 int nright = rn;
3376 while (nleft > gran) {
3377 int lh = nleft >>> 1;
3378 int splitIndex = lo + lh;
3379 long split = a[splitIndex];
3380 int rl = 0;
3381 int rh = nright;
3382 while (rl < rh) {
3383 int mid = (rl + rh) >>> 1;
3384 if (split <= a[ro + mid])
3385 rh = mid;
3386 else
3387 rl = mid + 1;
3388 }
3389 (rights = new FJLCMerger
3390 (a, w, splitIndex, nleft-lh, ro+rh,
3391 nright-rh, wo+lh+rh, gran, rights)).fork();
3392 nleft = lh;
3393 nright = rh;
3394 }
3395
3396 int l = lo;
3397 int lFence = lo + nleft;
3398 int r = ro;
3399 int rFence = ro + nright;
3400 int k = wo;
3401 while (l < lFence && r < rFence) {
3402 long al = a[l];
3403 long ar = a[r];
3404 long t;
3405 if (al <= ar) {++l; t=al;} else {++r; t = ar;}
3406 w[k++] = t;
3407 }
3408 while (l < lFence)
3409 w[k++] = a[l++];
3410 while (r < rFence)
3411 w[k++] = a[r++];
3412
3413 while (rights != null) {
3414 if (ForkJoinWorkerThread.removeIfNextLocalTask(rights))
3415 rights.compute();
3416 else
3417 rights.join();
3418 rights = rights.next;
3419 }
3420 }
3421 }
3422
3423 /** Cutoff for when to use insertion-sort instead of quicksort */
3424 static final int INSERTION_SORT_THRESHOLD = 8;
3425
3426 // Six nearly identical versions of quicksort
3427
3428 static void oquickSort(Object[] a, Comparator cmp, int lo, int hi) {
3429 for (;;) {
3430 if (hi - lo <= INSERTION_SORT_THRESHOLD) {
3431 for (int i = lo + 1; i <= hi; i++) {
3432 Object t = a[i];
3433 int j = i - 1;
3434 while (j >= lo && cmp.compare(t, a[j]) < 0) {
3435 a[j+1] = a[j];
3436 --j;
3437 }
3438 a[j+1] = t;
3439 }
3440 return;
3441 }
3442
3443 int mid = (lo + hi) >>> 1;
3444 if (cmp.compare(a[lo], a[mid]) > 0) {
3445 Object t = a[lo]; a[lo] = a[mid]; a[mid] = t;
3446 }
3447 if (cmp.compare(a[mid], a[hi]) > 0) {
3448 Object t = a[mid]; a[mid] = a[hi]; a[hi] = t;
3449 if (cmp.compare(a[lo], a[mid]) > 0) {
3450 Object u = a[lo]; a[lo] = a[mid]; a[mid] = u;
3451 }
3452 }
3453
3454 Object pivot = a[mid];
3455 int left = lo+1;
3456 int right = hi-1;
3457 for (;;) {
3458 while (cmp.compare(pivot, a[right]) < 0)
3459 --right;
3460 while (left < right && cmp.compare(pivot, a[left]) >= 0)
3461 ++left;
3462 if (left < right) {
3463 Object t = a[left]; a[left] = a[right]; a[right] = t;
3464 --right;
3465 }
3466 else break;
3467 }
3468
3469 oquickSort(a, cmp, lo, left);
3470 lo = left + 1;
3471 }
3472 }
3473
3474 static void ocquickSort(Comparable[] a, int lo, int hi) {
3475 for (;;) {
3476 if (hi - lo <= INSERTION_SORT_THRESHOLD) {
3477 for (int i = lo + 1; i <= hi; i++) {
3478 Comparable t = a[i];
3479 int j = i - 1;
3480 while (j >= lo && t.compareTo(a[j]) < 0) {
3481 a[j+1] = a[j];
3482 --j;
3483 }
3484 a[j+1] = t;
3485 }
3486 return;
3487 }
3488
3489 int mid = (lo + hi) >>> 1;
3490 if (a[lo].compareTo(a[mid]) > 0) {
3491 Comparable t = a[lo]; a[lo] = a[mid]; a[mid] = t;
3492 }
3493 if (a[mid].compareTo(a[hi]) > 0) {
3494 Comparable t = a[mid]; a[mid] = a[hi]; a[hi] = t;
3495 if (a[lo].compareTo(a[mid]) > 0) {
3496 Comparable u = a[lo]; a[lo] = a[mid]; a[mid] = u;
3497 }
3498 }
3499
3500 Comparable pivot = a[mid];
3501 int left = lo+1;
3502 int right = hi-1;
3503 for (;;) {
3504 while (pivot.compareTo(a[right]) < 0)
3505 --right;
3506 while (left < right && pivot.compareTo(a[left]) >= 0)
3507 ++left;
3508 if (left < right) {
3509 Comparable t = a[left]; a[left] = a[right]; a[right] = t;
3510 --right;
3511 }
3512 else break;
3513 }
3514
3515 ocquickSort(a, lo, left);
3516 lo = left + 1;
3517 }
3518 }
3519
3520 static void dquickSort(double[] a, DoubleComparator cmp, int lo, int hi) {
3521 for (;;) {
3522 if (hi - lo <= INSERTION_SORT_THRESHOLD) {
3523 for (int i = lo + 1; i <= hi; i++) {
3524 double t = a[i];
3525 int j = i - 1;
3526 while (j >= lo && cmp.compare(t, a[j]) < 0) {
3527 a[j+1] = a[j];
3528 --j;
3529 }
3530 a[j+1] = t;
3531 }
3532 return;
3533 }
3534
3535 int mid = (lo + hi) >>> 1;
3536 if (cmp.compare(a[lo], a[mid]) > 0) {
3537 double t = a[lo]; a[lo] = a[mid]; a[mid] = t;
3538 }
3539 if (cmp.compare(a[mid], a[hi]) > 0) {
3540 double t = a[mid]; a[mid] = a[hi]; a[hi] = t;
3541 if (cmp.compare(a[lo], a[mid]) > 0) {
3542 double u = a[lo]; a[lo] = a[mid]; a[mid] = u;
3543 }
3544 }
3545
3546 double pivot = a[mid];
3547 int left = lo+1;
3548 int right = hi-1;
3549 for (;;) {
3550 while (cmp.compare(pivot, a[right]) < 0)
3551 --right;
3552 while (left < right && cmp.compare(pivot, a[left]) >= 0)
3553 ++left;
3554 if (left < right) {
3555 double t = a[left]; a[left] = a[right]; a[right] = t;
3556 --right;
3557 }
3558 else break;
3559 }
3560
3561 dquickSort(a, cmp, lo, left);
3562 lo = left + 1;
3563 }
3564 }
3565
3566 static void dcquickSort(double[] a, int lo, int hi) {
3567 for (;;) {
3568 if (hi - lo <= INSERTION_SORT_THRESHOLD) {
3569 for (int i = lo + 1; i <= hi; i++) {
3570 double t = a[i];
3571 int j = i - 1;
3572 while (j >= lo && t < a[j]) {
3573 a[j+1] = a[j];
3574 --j;
3575 }
3576 a[j+1] = t;
3577 }
3578 return;
3579 }
3580
3581 int mid = (lo + hi) >>> 1;
3582 if (a[lo] > a[mid]) {
3583 double t = a[lo]; a[lo] = a[mid]; a[mid] = t;
3584 }
3585 if (a[mid] > a[hi]) {
3586 double t = a[mid]; a[mid] = a[hi]; a[hi] = t;
3587 if (a[lo] > a[mid]) {
3588 double u = a[lo]; a[lo] = a[mid]; a[mid] = u;
3589 }
3590 }
3591
3592 double pivot = a[mid];
3593 int left = lo+1;
3594 int right = hi-1;
3595 for (;;) {
3596 while (pivot < a[right])
3597 --right;
3598 while (left < right && pivot >= a[left])
3599 ++left;
3600 if (left < right) {
3601 double t = a[left]; a[left] = a[right]; a[right] = t;
3602 --right;
3603 }
3604 else break;
3605 }
3606
3607 dcquickSort(a, lo, left);
3608 lo = left + 1;
3609 }
3610 }
3611
3612 static void lquickSort(long[] a, LongComparator cmp, int lo, int hi) {
3613 for (;;) {
3614 if (hi - lo <= INSERTION_SORT_THRESHOLD) {
3615 for (int i = lo + 1; i <= hi; i++) {
3616 long t = a[i];
3617 int j = i - 1;
3618 while (j >= lo && cmp.compare(t, a[j]) < 0) {
3619 a[j+1] = a[j];
3620 --j;
3621 }
3622 a[j+1] = t;
3623 }
3624 return;
3625 }
3626
3627 int mid = (lo + hi) >>> 1;
3628 if (cmp.compare(a[lo], a[mid]) > 0) {
3629 long t = a[lo]; a[lo] = a[mid]; a[mid] = t;
3630 }
3631 if (cmp.compare(a[mid], a[hi]) > 0) {
3632 long t = a[mid]; a[mid] = a[hi]; a[hi] = t;
3633 if (cmp.compare(a[lo], a[mid]) > 0) {
3634 long u = a[lo]; a[lo] = a[mid]; a[mid] = u;
3635 }
3636 }
3637
3638 long pivot = a[mid];
3639 int left = lo+1;
3640 int right = hi-1;
3641 for (;;) {
3642 while (cmp.compare(pivot, a[right]) < 0)
3643 --right;
3644 while (left < right && cmp.compare(pivot, a[left]) >= 0)
3645 ++left;
3646 if (left < right) {
3647 long t = a[left]; a[left] = a[right]; a[right] = t;
3648 --right;
3649 }
3650 else break;
3651 }
3652
3653 lquickSort(a, cmp, lo, left);
3654 lo = left + 1;
3655 }
3656 }
3657
3658 static void lcquickSort(long[] a, int lo, int hi) {
3659 for (;;) {
3660 if (hi - lo <= INSERTION_SORT_THRESHOLD) {
3661 for (int i = lo + 1; i <= hi; i++) {
3662 long t = a[i];
3663 int j = i - 1;
3664 while (j >= lo && t < a[j]) {
3665 a[j+1] = a[j];
3666 --j;
3667 }
3668 a[j+1] = t;
3669 }
3670 return;
3671 }
3672
3673 int mid = (lo + hi) >>> 1;
3674 if (a[lo] > a[mid]) {
3675 long t = a[lo]; a[lo] = a[mid]; a[mid] = t;
3676 }
3677 if (a[mid] > a[hi]) {
3678 long t = a[mid]; a[mid] = a[hi]; a[hi] = t;
3679 if (a[lo] > a[mid]) {
3680 long u = a[lo]; a[lo] = a[mid]; a[mid] = u;
3681 }
3682 }
3683
3684 long pivot = a[mid];
3685 int left = lo+1;
3686 int right = hi-1;
3687 for (;;) {
3688 while (pivot < a[right])
3689 --right;
3690 while (left < right && pivot >= a[left])
3691 ++left;
3692 if (left < right) {
3693 long t = a[left]; a[left] = a[right]; a[right] = t;
3694 --right;
3695 }
3696 else break;
3697 }
3698
3699 lcquickSort(a, lo, left);
3700 lo = left + 1;
3701 }
3702 }
3703
3704 /**
3705 * Cumulative scan
3706 *
3707 * A basic version of scan is straightforward.
3708 * Keep dividing by two to threshold segment size, and then:
3709 * Pass 1: Create tree of partial sums for each segment
3710 * Pass 2: For each segment, cumulate with offset of left sibling
3711 * See G. Blelloch's http://www.cs.cmu.edu/~scandal/alg/scan.html
3712 *
3713 * This version improves performance within FJ framework mainly by
3714 * allowing second pass of ready left-hand sides to proceed even
3715 * if some right-hand side first passes are still executing. It
3716 * also combines first and second pass for leftmost segment, and
3717 * for cumulate (not precumulate) also skips first pass for
3718 * rightmost segment (whose result is not needed for second pass).
3719 *
3720 * To manage this, it relies on "phase" phase/state control field
3721 * maintaining bits CUMULATE, SUMMED, and FINISHED. CUMULATE is
3722 * main phase bit. When false, segments compute only their sum.
3723 * When true, they cumulate array elements. CUMULATE is set at
3724 * root at beginning of second pass and then propagated down. But
3725 * it may also be set earlier for subtrees with lo==firstIndex (the
3726 * left spine of tree). SUMMED is a one bit join count. For leafs,
3727 * set when summed. For internal nodes, becomes true when one
3728 * child is summed. When second child finishes summing, it then
3729 * moves up tree to trigger cumulate phase. FINISHED is also a one
3730 * bit join count. For leafs, it is set when cumulated. For
3731 * internal nodes, it becomes true when one child is cumulated.
3732 * When second child finishes cumulating, it then moves up tree,
3733 * excecuting finish() at the root.
3734 *
3735 * This class maintains only the basic control logic. Subclasses
3736 * maintain the "in" and "out" fields, and *Ops classes perform
3737 * computations
3738 */
3739 static abstract class FJScan extends AsyncAction {
3740 static final int CUMULATE = 1;
3741 static final int SUMMED = 2;
3742 static final int FINISHED = 4;
3743
3744 final FJScan parent;
3745 final FJScanOp op;
3746 FJScan left, right;
3747 volatile int phase; // phase/state
3748 final int lo;
3749 final int hi;
3750
3751 static final AtomicIntegerFieldUpdater<FJScan> phaseUpdater =
3752 AtomicIntegerFieldUpdater.newUpdater(FJScan.class, "phase");
3753
3754 FJScan(FJScan parent, FJScanOp op, int lo, int hi) {
3755 this.parent = parent;
3756 this.op = op;
3757 this.lo = lo;
3758 this.hi = hi;
3759 }
3760
3761 /** Returns true if can CAS CUMULATE bit true */
3762 final boolean transitionToCumulate() {
3763 int c;
3764 while (((c = phase) & CUMULATE) == 0)
3765 if (phaseUpdater.compareAndSet(this, c, c | CUMULATE))
3766 return true;
3767 return false;
3768 }
3769
3770 public final void compute() {
3771 if (hi - lo > op.threshold) {
3772 if (left == null) { // first pass
3773 int mid = (lo + hi) >>> 1;
3774 left = op.newSubtask(this, lo, mid);
3775 right = op.newSubtask(this, mid, hi);
3776 }
3777
3778 boolean cumulate = (phase & CUMULATE) != 0;
3779 if (cumulate)
3780 op.pushDown(this, left, right);
3781
3782 if (!cumulate || right.transitionToCumulate())
3783 right.fork();
3784 if (!cumulate || left.transitionToCumulate())
3785 left.compute();
3786 }
3787 else {
3788 int cb;
3789 for (;;) { // Establish action: sum, cumulate, or both
3790 int b = phase;
3791 if ((b & FINISHED) != 0) // already done
3792 return;
3793 if ((b & CUMULATE) != 0)
3794 cb = FINISHED;
3795 else if (lo == op.firstIndex) // combine leftmost
3796 cb = (SUMMED|FINISHED);
3797 else
3798 cb = SUMMED;
3799 if (phaseUpdater.compareAndSet(this, b, b|cb))
3800 break;
3801 }
3802
3803 if (cb == SUMMED)
3804 op.sumLeaf(lo, hi, this);
3805 else if (cb == FINISHED)
3806 op.cumulateLeaf(lo, hi, this);
3807 else if (cb == (SUMMED|FINISHED))
3808 op.sumAndCumulateLeaf(lo, hi, this);
3809
3810 // propagate up
3811 FJScan ch = this;
3812 FJScan par = parent;
3813 for (;;) {
3814 if (par == null) {
3815 if ((cb & FINISHED) != 0)
3816 ch.finish();
3817 break;
3818 }
3819 int pb = par.phase;
3820 if ((pb & cb & FINISHED) != 0) { // both finished
3821 ch = par;
3822 par = par.parent;
3823 }
3824 else if ((pb & cb & SUMMED) != 0) { // both summed
3825 op.pushUp(par, par.left, par.right);
3826 int refork =
3827 ((pb & CUMULATE) == 0 &&
3828 par.lo == op.firstIndex)? CUMULATE : 0;
3829 int nextPhase = pb|cb|refork;
3830 if (pb == nextPhase ||
3831 phaseUpdater.compareAndSet(par, pb, nextPhase)) {
3832 if (refork != 0)
3833 par.fork();
3834 cb = SUMMED; // drop finished bit
3835 ch = par;
3836 par = par.parent;
3837 }
3838 }
3839 else if (phaseUpdater.compareAndSet(par, pb, pb|cb))
3840 break;
3841 }
3842 }
3843 }
3844
3845 // no-op versions of methods to get/set in/out, overridden as
3846 // appropriate in subclasses
3847 Object ogetIn() { return null; }
3848 Object ogetOut() { return null; }
3849 void rsetIn(Object x) { }
3850 void rsetOut(Object x) { }
3851
3852 double dgetIn() { return 0; }
3853 double dgetOut() { return 0; }
3854 void dsetIn(double x) { }
3855 void dsetOut(double x) { }
3856
3857 long lgetIn() { return 0; }
3858 long lgetOut() { return 0; }
3859 void lsetIn(long x) { }
3860 void lsetOut(long x) { }
3861 }
3862
3863 // Subclasses adding in/out fields of the appropriate type
3864 static final class FJOScan extends FJScan {
3865 Object in;
3866 Object out;
3867 FJOScan(FJScan parent, FJScanOp op, int lo, int hi) {
3868 super(parent, op, lo, hi);
3869 }
3870 Object ogetIn() { return in; }
3871 Object ogetOut() { return out; }
3872 void rsetIn(Object x) { in = x; }
3873 void rsetOut(Object x) { out = x; }
3874 }
3875
3876 static final class FJDScan extends FJScan {
3877 double in;
3878 double out;
3879 FJDScan(FJScan parent, FJScanOp op, int lo, int hi) {
3880 super(parent, op, lo, hi);
3881 }
3882 double dgetIn() { return in; }
3883 double dgetOut() { return out; }
3884 void dsetIn(double x) { in = x; }
3885 void dsetOut(double x) { out = x; }
3886
3887 }
3888
3889 static final class FJLScan extends FJScan {
3890 long in;
3891 long out;
3892 FJLScan(FJScan parent, FJScanOp op, int lo, int hi) {
3893 super(parent, op, lo, hi);
3894 }
3895 long lgetIn() { return in; }
3896 long lgetOut() { return out; }
3897 void lsetIn(long x) { in = x; }
3898 void lsetOut(long x) { out = x; }
3899 }
3900
3901 /**
3902 * Computational operations for FJSCan
3903 */
3904 static abstract class FJScanOp {
3905 final int threshold;
3906 final int firstIndex;
3907 final int upperBound;
3908 FJScanOp(Prefix prefix) {
3909 this.firstIndex = prefix.firstIndex;
3910 this.upperBound = prefix.upperBound;
3911 this.threshold = prefix.getThreshold();
3912 }
3913 abstract void pushDown(FJScan parent, FJScan left, FJScan right);
3914 abstract void pushUp(FJScan parent, FJScan left, FJScan right);
3915 abstract void sumLeaf(int lo, int hi, FJScan f);
3916 abstract void cumulateLeaf(int lo, int hi, FJScan f);
3917 abstract void sumAndCumulateLeaf(int lo, int hi, FJScan f);
3918 abstract FJScan newSubtask(FJScan parent, int lo, int hi);
3919 }
3920
3921 static abstract class FJOScanOp extends FJScanOp {
3922 final Object[] array;
3923 final Reducer reducer;
3924 final Object base;
3925 FJOScanOp(OPrefix prefix, Reducer reducer, Object base) {
3926 super(prefix);
3927 this.array = prefix.array;
3928 this.reducer = reducer;
3929 this.base = base;
3930 }
3931 final void pushDown(FJScan parent, FJScan left, FJScan right) {
3932 Object pin = parent.ogetIn();
3933 left.rsetIn(pin);
3934 right.rsetIn(reducer.op(pin, left.ogetOut()));
3935 }
3936 final void pushUp(FJScan parent, FJScan left, FJScan right) {
3937 parent.rsetOut(reducer.op(left.ogetOut(),
3938 right.ogetOut()));
3939 }
3940 final FJScan newSubtask(FJScan parent, int lo, int hi) {
3941 FJOScan f = new FJOScan(parent, this, lo, hi);
3942 f.in = base;
3943 f.out = base;
3944 return f;
3945 }
3946 }
3947
3948 static final class FJOCumulateOp extends FJOScanOp {
3949 FJOCumulateOp(OPrefix prefix, Reducer reducer, Object base) {
3950 super(prefix, reducer, base);
3951 }
3952 void sumLeaf(int lo, int hi, FJScan f) {
3953 Object sum = base;
3954 if (hi != upperBound) {
3955 Object[] arr = array;
3956 for (int i = lo; i < hi; ++i)
3957 sum = reducer.op(sum, arr[i]);
3958 }
3959 f.rsetOut(sum);
3960 }
3961 void cumulateLeaf(int lo, int hi, FJScan f) {
3962 Object[] arr = array;
3963 Object sum = f.ogetIn();
3964 for (int i = lo; i < hi; ++i)
3965 arr[i] = sum = reducer.op(sum, arr[i]);
3966 }
3967 void sumAndCumulateLeaf(int lo, int hi, FJScan f) {
3968 Object[] arr = array;
3969 Object sum = base;
3970 for (int i = lo; i < hi; ++i)
3971 arr[i] = sum = reducer.op(sum, arr[i]);
3972 f.rsetOut(sum);
3973 }
3974 }
3975
3976 static final class FJOPrecumulateOp extends FJOScanOp {
3977 FJOPrecumulateOp(OPrefix prefix, Reducer reducer, Object base) {
3978 super(prefix, reducer, base);
3979 }
3980 void sumLeaf(int lo, int hi, FJScan f) {
3981 Object[] arr = array;
3982 Object sum = base;
3983 for (int i = lo; i < hi; ++i)
3984 sum = reducer.op(sum, arr[i]);
3985 f.rsetOut(sum);
3986 }
3987 void cumulateLeaf(int lo, int hi, FJScan f) {
3988 Object[] arr = array;
3989 Object sum = f.ogetIn();
3990 for (int i = lo; i < hi; ++i) {
3991 Object x = arr[i];
3992 arr[i] = sum;
3993 sum = reducer.op(sum, x);
3994 }
3995 }
3996 void sumAndCumulateLeaf(int lo, int hi, FJScan f) {
3997 Object[] arr = array;
3998 Object sum = base;
3999 for (int i = lo; i < hi; ++i) {
4000 Object x = arr[i];
4001 arr[i] = sum;
4002 sum = reducer.op(sum, x);
4003 }
4004 f.rsetOut(sum);
4005 }
4006 }
4007
4008 static abstract class FJDScanOp extends FJScanOp {
4009 final double[] array;
4010 final DoubleReducer reducer;
4011 final double base;
4012 FJDScanOp(DPrefix prefix, DoubleReducer reducer, double base) {
4013 super(prefix);
4014 this.array = prefix.array;
4015 this.reducer = reducer;
4016 this.base = base;
4017 }
4018 final void pushDown(FJScan parent, FJScan left, FJScan right) {
4019 double pin = parent.dgetIn();
4020 left.dsetIn(pin);
4021 right.dsetIn(reducer.op(pin, left.dgetOut()));
4022 }
4023 final void pushUp(FJScan parent, FJScan left, FJScan right) {
4024 parent.dsetOut(reducer.op(left.dgetOut(),
4025 right.dgetOut()));
4026 }
4027 final FJScan newSubtask(FJScan parent, int lo, int hi) {
4028 FJDScan f = new FJDScan(parent, this, lo, hi);
4029 f.in = base;
4030 f.out = base;
4031 return f;
4032 }
4033 }
4034
4035 static final class FJDCumulateOp extends FJDScanOp {
4036 FJDCumulateOp(DPrefix prefix, DoubleReducer reducer, double base) {
4037 super(prefix, reducer, base);
4038 }
4039 void sumLeaf(int lo, int hi, FJScan f) {
4040 double sum = base;
4041 if (hi != upperBound) {
4042 double[] arr = array;
4043 for (int i = lo; i < hi; ++i)
4044 sum = reducer.op(sum, arr[i]);
4045 }
4046 f.dsetOut(sum);
4047 }
4048 void cumulateLeaf(int lo, int hi, FJScan f) {
4049 double[] arr = array;
4050 double sum = f.dgetIn();
4051 for (int i = lo; i < hi; ++i)
4052 arr[i] = sum = reducer.op(sum, arr[i]);
4053 }
4054 void sumAndCumulateLeaf(int lo, int hi, FJScan f) {
4055 double[] arr = array;
4056 double sum = base;
4057 for (int i = lo; i < hi; ++i)
4058 arr[i] = sum = reducer.op(sum, arr[i]);
4059 f.dsetOut(sum);
4060 }
4061 }
4062
4063 static final class FJDPrecumulateOp extends FJDScanOp {
4064 FJDPrecumulateOp(DPrefix prefix, DoubleReducer reducer, double base) {
4065 super(prefix, reducer, base);
4066 }
4067 void sumLeaf(int lo, int hi, FJScan f) {
4068 double[] arr = array;
4069 double sum = base;
4070 for (int i = lo; i < hi; ++i)
4071 sum = reducer.op(sum, arr[i]);
4072 f.dsetOut(sum);
4073 }
4074 void cumulateLeaf(int lo, int hi, FJScan f) {
4075 double[] arr = array;
4076 double sum = f.dgetIn();
4077 for (int i = lo; i < hi; ++i) {
4078 double x = arr[i];
4079 arr[i] = sum;
4080 sum = reducer.op(sum, x);
4081 }
4082 }
4083 void sumAndCumulateLeaf(int lo, int hi, FJScan f) {
4084 double[] arr = array;
4085 double sum = base;
4086 for (int i = lo; i < hi; ++i) {
4087 double x = arr[i];
4088 arr[i] = sum;
4089 sum = reducer.op(sum, x);
4090 }
4091 f.dsetOut(sum);
4092 }
4093 }
4094
4095 static abstract class FJLScanOp extends FJScanOp {
4096 final long[] array;
4097 final LongReducer reducer;
4098 final long base;
4099 FJLScanOp(LPrefix prefix, LongReducer reducer, long base) {
4100 super(prefix);
4101 this.array = prefix.array;
4102 this.reducer = reducer;
4103 this.base = base;
4104 }
4105 final void pushDown(FJScan parent, FJScan left, FJScan right) {
4106 long pin = parent.lgetIn();
4107 left.lsetIn(pin);
4108 right.lsetIn(reducer.op(pin, left.lgetOut()));
4109 }
4110 final void pushUp(FJScan parent, FJScan left, FJScan right) {
4111 parent.lsetOut(reducer.op(left.lgetOut(),
4112 right.lgetOut()));
4113 }
4114 final FJScan newSubtask(FJScan parent, int lo, int hi) {
4115 FJLScan f = new FJLScan(parent, this, lo, hi);
4116 f.in = base;
4117 f.out = base;
4118 return f;
4119 }
4120 }
4121
4122 static final class FJLCumulateOp extends FJLScanOp {
4123 FJLCumulateOp(LPrefix prefix, LongReducer reducer, long base) {
4124 super(prefix, reducer, base);
4125 }
4126 void sumLeaf(int lo, int hi, FJScan f) {
4127 long sum = base;
4128 if (hi != upperBound) {
4129 long[] arr = array;
4130 for (int i = lo; i < hi; ++i)
4131 sum = reducer.op(sum, arr[i]);
4132 }
4133 f.lsetOut(sum);
4134 }
4135 void cumulateLeaf(int lo, int hi, FJScan f) {
4136 long[] arr = array;
4137 long sum = f.lgetIn();
4138 for (int i = lo; i < hi; ++i)
4139 arr[i] = sum = reducer.op(sum, arr[i]);
4140 }
4141 void sumAndCumulateLeaf(int lo, int hi, FJScan f) {
4142 long[] arr = array;
4143 long sum = base;
4144 for (int i = lo; i < hi; ++i)
4145 arr[i] = sum = reducer.op(sum, arr[i]);
4146 f.lsetOut(sum);
4147 }
4148 }
4149
4150 static final class FJLPrecumulateOp extends FJLScanOp {
4151 FJLPrecumulateOp(LPrefix prefix, LongReducer reducer, long base) {
4152 super(prefix, reducer, base);
4153 }
4154 void sumLeaf(int lo, int hi, FJScan f) {
4155 long[] arr = array;
4156 long sum = base;
4157 for (int i = lo; i < hi; ++i)
4158 sum = reducer.op(sum, arr[i]);
4159 f.lsetOut(sum);
4160 }
4161 void cumulateLeaf(int lo, int hi, FJScan f) {
4162 long[] arr = array;
4163 long sum = f.lgetIn();
4164 for (int i = lo; i < hi; ++i) {
4165 long x = arr[i];
4166 arr[i] = sum;
4167 sum = reducer.op(sum, x);
4168 }
4169 }
4170 void sumAndCumulateLeaf(int lo, int hi, FJScan f) {
4171 long[] arr = array;
4172 long sum = base;
4173 for (int i = lo; i < hi; ++i) {
4174 long x = arr[i];
4175 arr[i] = sum;
4176 sum = reducer.op(sum, x);
4177 }
4178 f.lsetOut(sum);
4179 }
4180 }
4181
4182 // specialized versions for plus
4183
4184 static abstract class FJDScanPlusOp extends FJScanOp {
4185 final double[] array;
4186 FJDScanPlusOp(DPrefix prefix) {
4187 super(prefix);
4188 this.array = prefix.array;
4189 }
4190 final void pushDown(FJScan parent, FJScan left, FJScan right) {
4191 double pin = parent.dgetIn();
4192 left.dsetIn(pin);
4193 right.dsetIn(pin + left.dgetOut());
4194 }
4195 final void pushUp(FJScan parent, FJScan left, FJScan right) {
4196 parent.dsetOut(left.dgetOut() + right.dgetOut());
4197 }
4198 final FJScan newSubtask(FJScan parent, int lo, int hi) {
4199 FJDScan f = new FJDScan(parent, this, lo, hi);
4200 f.in = 0.0;
4201 f.out = 0.0;
4202 return f;
4203 }
4204 }
4205
4206 static final class FJDCumulatePlusOp extends FJDScanPlusOp {
4207 FJDCumulatePlusOp(DPrefix prefix) {
4208 super(prefix);
4209 }
4210 void sumLeaf(int lo, int hi, FJScan f) {
4211 double sum = 0.0;
4212 if (hi != upperBound) {
4213 double[] arr = array;
4214 for (int i = lo; i < hi; ++i)
4215 sum += arr[i];
4216 }
4217 f.dsetOut(sum);
4218 }
4219 void cumulateLeaf(int lo, int hi, FJScan f) {
4220 double[] arr = array;
4221 double sum = f.dgetIn();
4222 for (int i = lo; i < hi; ++i)
4223 arr[i] = sum += arr[i];
4224 }
4225 void sumAndCumulateLeaf(int lo, int hi, FJScan f) {
4226 double[] arr = array;
4227 double sum = 0.0;
4228 for (int i = lo; i < hi; ++i)
4229 arr[i] = sum += arr[i];
4230 f.dsetOut(sum);
4231 }
4232 }
4233
4234 static final class FJDPrecumulatePlusOp extends FJDScanPlusOp {
4235 FJDPrecumulatePlusOp(DPrefix prefix) {
4236 super(prefix);
4237 }
4238 void sumLeaf(int lo, int hi, FJScan f) {
4239 double[] arr = array;
4240 double sum = 0.0;
4241 for (int i = lo; i < hi; ++i)
4242 sum += arr[i];
4243 f.dsetOut(sum);
4244 }
4245 void cumulateLeaf(int lo, int hi, FJScan f) {
4246 double[] arr = array;
4247 double sum = f.dgetIn();
4248 for (int i = lo; i < hi; ++i) {
4249 double x = arr[i];
4250 arr[i] = sum;
4251 sum += x;
4252 }
4253 }
4254 void sumAndCumulateLeaf(int lo, int hi, FJScan f) {
4255 double[] arr = array;
4256 double sum = 0.0;
4257 for (int i = lo; i < hi; ++i) {
4258 double x = arr[i];
4259 arr[i] = sum;
4260 sum += x;
4261 }
4262 f.dsetOut(sum);
4263 }
4264 }
4265
4266 static abstract class FJLScanPlusOp extends FJScanOp {
4267 final long[] array;
4268 FJLScanPlusOp(LPrefix prefix) {
4269 super(prefix);
4270 this.array = prefix.array;
4271 }
4272 final void pushDown(FJScan parent, FJScan left, FJScan right) {
4273 long pin = parent.lgetIn();
4274 left.lsetIn(pin);
4275 right.lsetIn(pin + left.lgetOut());
4276 }
4277
4278 final void pushUp(FJScan parent, FJScan left, FJScan right) {
4279 parent.lsetOut(left.lgetOut() + right.lgetOut());
4280 }
4281
4282 final FJScan newSubtask(FJScan parent, int lo, int hi) {
4283 FJLScan f = new FJLScan(parent, this, lo, hi);
4284 f.in = 0L;
4285 f.out = 0L;
4286 return f;
4287 }
4288 }
4289
4290 static final class FJLCumulatePlusOp extends FJLScanPlusOp {
4291 FJLCumulatePlusOp(LPrefix prefix) {
4292 super(prefix);
4293 }
4294 void sumLeaf(int lo, int hi, FJScan f) {
4295 long sum = 0L;
4296 if (hi != upperBound) {
4297 long[] arr = array;
4298 for (int i = lo; i < hi; ++i)
4299 sum += arr[i];
4300 }
4301 f.lsetOut(sum);
4302 }
4303 void cumulateLeaf(int lo, int hi, FJScan f) {
4304 long[] arr = array;
4305 long sum = f.lgetIn();
4306 for (int i = lo; i < hi; ++i)
4307 arr[i] = sum += arr[i];
4308 }
4309 void sumAndCumulateLeaf(int lo, int hi, FJScan f) {
4310 long[] arr = array;
4311 long sum = 0L;
4312 for (int i = lo; i < hi; ++i)
4313 arr[i] = sum += arr[i];
4314 f.lsetOut(sum);
4315 }
4316 }
4317
4318 static final class FJLPrecumulatePlusOp extends FJLScanPlusOp {
4319 FJLPrecumulatePlusOp(LPrefix prefix) {
4320 super(prefix);
4321 }
4322 void sumLeaf(int lo, int hi, FJScan f) {
4323 long[] arr = array;
4324 long sum = 0L;
4325 for (int i = lo; i < hi; ++i)
4326 sum += arr[i];
4327 f.lsetOut(sum);
4328 }
4329 void cumulateLeaf(int lo, int hi, FJScan f) {
4330 long[] arr = array;
4331 long sum = f.lgetIn();
4332 for (int i = lo; i < hi; ++i) {
4333 long x = arr[i];
4334 arr[i] = sum;
4335 sum += x;
4336 }
4337 }
4338 void sumAndCumulateLeaf(int lo, int hi, FJScan f) {
4339 long[] arr = array;
4340 long sum = 0L;
4341 for (int i = lo; i < hi; ++i) {
4342 long x = arr[i];
4343 arr[i] = sum;
4344 sum += x;
4345 }
4346 f.lsetOut(sum);
4347 }
4348 }
4349
4350 // Zillions of little classes to support binary ops
4351 // ToDo: specialize to flatten dispatch
4352
4353 static <T,U,V> IntAndObjectToObject<T,V> indexedMapper
4354 (final BinaryOp<? super T, ? super U, ? extends V> combiner,
4355 final ParallelArray<U> u, final int firstIndex) {
4356 return new IntAndObjectToObject<T,V>() {
4357 final int offset = u.firstIndex - firstIndex;
4358 public V op(int i, T a) { return combiner.op(a, (U)(u.oget(i+offset))); }
4359 };
4360 }
4361
4362 static <T,U> IntAndObjectToDouble<T> indexedMapper
4363 (final ObjectAndObjectToDouble<? super T, ? super U> combiner,
4364 final ParallelArray<U> u, final int firstIndex) {
4365 return new IntAndObjectToDouble<T>() {
4366 final int offset = u.firstIndex - firstIndex;
4367 public double op(int i, T a) { return combiner.op(a, (U)(u.oget(i+offset))); }
4368 };
4369 }
4370
4371 static <T,U> IntAndObjectToLong<T> indexedMapper
4372 (final ObjectAndObjectToLong<? super T, ? super U> combiner,
4373 final ParallelArray<U> u, final int firstIndex) {
4374 return new IntAndObjectToLong<T>() {
4375 final int offset = u.firstIndex - firstIndex;
4376 public long op(int i, T a) { return combiner.op(a, (U)(u.oget(i+offset))); }
4377 };
4378 }
4379
4380 static <T,V> IntAndObjectToObject<T,V> indexedMapper
4381 (final ObjectAndDoubleToObject<? super T, ? extends V> combiner,
4382 final ParallelDoubleArray u, final int firstIndex) {
4383 return new IntAndObjectToObject<T,V>() {
4384 final int offset = u.firstIndex - firstIndex;
4385 public V op(int i, T a) { return combiner.op(a, u.dget(i+offset)); }
4386 };
4387 }
4388
4389 static <T> IntAndObjectToDouble<T> indexedMapper
4390 (final ObjectAndDoubleToDouble<? super T> combiner,
4391 final ParallelDoubleArray u, final int firstIndex) {
4392 return new IntAndObjectToDouble<T>() {
4393 final int offset = u.firstIndex - firstIndex;
4394 public double op(int i, T a) { return combiner.op(a, u.dget(i+offset)); }
4395 };
4396 }
4397
4398 static <T,U> IntAndObjectToLong<T> indexedMapper
4399 (final ObjectAndDoubleToLong<? super T> combiner,
4400 final ParallelDoubleArray u, final int firstIndex) {
4401 return new IntAndObjectToLong<T>() {
4402 final int offset = u.firstIndex - firstIndex;
4403 public long op(int i, T a) { return combiner.op(a, u.dget(i+offset)); }
4404 };
4405 }
4406
4407 static <T,V> IntAndObjectToObject<T,V> indexedMapper
4408 (final ObjectAndLongToObject<? super T, ? extends V> combiner,
4409 final ParallelLongArray u, final int firstIndex) {
4410 return new IntAndObjectToObject<T,V>() {
4411 final int offset = u.firstIndex - firstIndex;
4412 public V op(int i, T a) { return combiner.op(a, u.lget(i+offset)); }
4413 };
4414 }
4415
4416 static <T> IntAndObjectToDouble<T> indexedMapper
4417 (final ObjectAndLongToDouble<? super T> combiner,
4418 final ParallelLongArray u, final int firstIndex) {
4419 return new IntAndObjectToDouble<T>() {
4420 final int offset = u.firstIndex - firstIndex;
4421 public double op(int i, T a) { return combiner.op(a, u.lget(i+offset)); }
4422 };
4423 }
4424
4425 static <T> IntAndObjectToLong<T> indexedMapper
4426 (final ObjectAndLongToLong<? super T> combiner,
4427 final ParallelLongArray u, final int firstIndex) {
4428 return new IntAndObjectToLong<T>() {
4429 final int offset = u.firstIndex - firstIndex;
4430 public long op(int i, T a) { return combiner.op(a, u.lget(i+offset)); }
4431 };
4432 }
4433
4434 static <U,V> IntAndDoubleToObject<V> indexedMapper
4435 (final DoubleAndObjectToObject<? super U, ? extends V> combiner,
4436 final ParallelArray<U> u, final int firstIndex) {
4437 return new IntAndDoubleToObject<V>() {
4438 final int offset = u.firstIndex - firstIndex;
4439 public V op(int i, double a) { return combiner.op(a, (U)(u.oget(i+offset))); }
4440 };
4441 }
4442
4443 static <U> IntAndDoubleToDouble indexedMapper
4444 (final DoubleAndObjectToDouble<? super U> combiner,
4445 final ParallelArray<U> u, final int firstIndex) {
4446 return new IntAndDoubleToDouble() {
4447 final int offset = u.firstIndex - firstIndex;
4448 public double op(int i, double a) { return combiner.op(a, (U)(u.oget(i+offset))); }
4449 };
4450 }
4451
4452 static <U> IntAndDoubleToLong indexedMapper
4453 (final DoubleAndObjectToLong<? super U> combiner,
4454 final ParallelArray<U> u, final int firstIndex) {
4455 return new IntAndDoubleToLong() {
4456 final int offset = u.firstIndex - firstIndex;
4457 public long op(int i, double a) { return combiner.op(a, (U)(u.oget(i+offset))); }
4458 };
4459 }
4460
4461 static <V> IntAndDoubleToObject<V> indexedMapper
4462 (final DoubleAndDoubleToObject<? extends V> combiner,
4463 final ParallelDoubleArray u, final int firstIndex) {
4464 return new IntAndDoubleToObject<V>() {
4465 final int offset = u.firstIndex - firstIndex;
4466 public V op(int i, double a) { return combiner.op(a, u.dget(i+offset)); }
4467 };
4468 }
4469
4470 static IntAndDoubleToDouble indexedMapper
4471 (final BinaryDoubleOp combiner,
4472 final ParallelDoubleArray u, final int firstIndex) {
4473 return new IntAndDoubleToDouble() {
4474 final int offset = u.firstIndex - firstIndex;
4475 public double op(int i, double a) { return combiner.op(a, u.dget(i+offset)); }
4476 };
4477 }
4478
4479 static IntAndDoubleToLong indexedMapper
4480 (final DoubleAndDoubleToLong combiner,
4481 final ParallelDoubleArray u, final int firstIndex) {
4482 return new IntAndDoubleToLong() {
4483 final int offset = u.firstIndex - firstIndex;
4484 public long op(int i, double a) { return combiner.op(a, u.dget(i+offset)); }
4485 };
4486 }
4487
4488 static <V> IntAndDoubleToObject<V> indexedMapper
4489 (final DoubleAndLongToObject<? extends V> combiner,
4490 final ParallelLongArray u, final int firstIndex) {
4491 return new IntAndDoubleToObject<V>() {
4492 final int offset = u.firstIndex - firstIndex;
4493 public V op(int i, double a) { return combiner.op(a, u.lget(i+offset)); }
4494 };
4495 }
4496
4497 static IntAndDoubleToDouble indexedMapper
4498 (final DoubleAndLongToDouble combiner,
4499 final ParallelLongArray u, final int firstIndex) {
4500 return new IntAndDoubleToDouble() {
4501 final int offset = u.firstIndex - firstIndex;
4502 public double op(int i, double a) { return combiner.op(a, u.lget(i+offset)); }
4503 };
4504 }
4505
4506 static IntAndDoubleToLong indexedMapper
4507 (final DoubleAndLongToLong combiner,
4508 final ParallelLongArray u, final int firstIndex) {
4509 return new IntAndDoubleToLong() {
4510 final int offset = u.firstIndex - firstIndex;
4511 public long op(int i, double a) { return combiner.op(a, u.lget(i+offset)); }
4512 };
4513 }
4514
4515 static <U,V> IntAndLongToObject<V> indexedMapper
4516 (final LongAndObjectToObject<? super U, ? extends V> combiner,
4517 final ParallelArray<U> u, final int firstIndex) {
4518 return new IntAndLongToObject<V>() {
4519 final int offset = u.firstIndex - firstIndex;
4520 public V op(int i, long a) { return combiner.op(a, (U)(u.oget(i+offset))); }
4521 };
4522 }
4523
4524 static <U> IntAndLongToDouble indexedMapper
4525 (final LongAndObjectToDouble<? super U> combiner,
4526 final ParallelArray<U> u, final int firstIndex) {
4527 return new IntAndLongToDouble() {
4528 final int offset = u.firstIndex - firstIndex;
4529 public double op(int i, long a) { return combiner.op(a, (U)(u.oget(i+offset))); }
4530 };
4531 }
4532
4533 static <U> IntAndLongToLong indexedMapper
4534 (final LongAndObjectToLong<? super U> combiner,
4535 final ParallelArray<U> u, final int firstIndex) {
4536 return new IntAndLongToLong() {
4537 final int offset = u.firstIndex - firstIndex;
4538 public long op(int i, long a) { return combiner.op(a, (U)(u.oget(i+offset))); }
4539 };
4540 }
4541
4542 static <V> IntAndLongToObject<V> indexedMapper
4543 (final LongAndDoubleToObject<? extends V> combiner,
4544 final ParallelDoubleArray u, final int firstIndex) {
4545 return new IntAndLongToObject<V>() {
4546 final int offset = u.firstIndex - firstIndex;
4547 public V op(int i, long a) { return combiner.op(a, u.dget(i+offset)); }
4548 };
4549 }
4550
4551 static IntAndLongToDouble indexedMapper
4552 (final LongAndDoubleToDouble combiner,
4553 final ParallelDoubleArray u, final int firstIndex) {
4554 return new IntAndLongToDouble() {
4555 final int offset = u.firstIndex - firstIndex;
4556 public double op(int i, long a) { return combiner.op(a, u.dget(i+offset)); }
4557 };
4558 }
4559
4560 static IntAndLongToLong indexedMapper
4561 (final LongAndDoubleToLong combiner,
4562 final ParallelDoubleArray u, final int firstIndex) {
4563 return new IntAndLongToLong() {
4564 final int offset = u.firstIndex - firstIndex;
4565 public long op(int i, long a) { return combiner.op(a, u.dget(i+offset)); }
4566 };
4567 }
4568
4569 static <V> IntAndLongToObject<V> indexedMapper
4570 (final LongAndLongToObject<? extends V> combiner,
4571 final ParallelLongArray u, final int firstIndex) {
4572 return new IntAndLongToObject<V>() {
4573 final int offset = u.firstIndex - firstIndex;
4574 public V op(int i, long a) { return combiner.op(a, u.lget(i+offset)); }
4575 };
4576 }
4577
4578 static IntAndLongToDouble indexedMapper
4579 (final LongAndLongToDouble combiner,
4580 final ParallelLongArray u, final int firstIndex) {
4581 return new IntAndLongToDouble() {
4582 final int offset = u.firstIndex - firstIndex;
4583 public double op(int i, long a) { return combiner.op(a, u.lget(i+offset)); }
4584 };
4585 }
4586
4587 static IntAndLongToLong indexedMapper
4588 (final BinaryLongOp combiner,
4589 final ParallelLongArray u, final int firstIndex) {
4590 return new IntAndLongToLong() {
4591 final int offset = u.firstIndex - firstIndex;
4592 public long op(int i, long a) { return combiner.op(a, u.lget(i+offset)); }
4593 };
4594 }
4595
4596 static <T,U,V> IntAndObjectToObject<T,V> compoundIndexedMapper
4597 (final IntAndObjectToObject<? super T, ? extends U> fst,
4598 final IntAndObjectToObject<? super U, ? extends V> snd) {
4599 return new IntAndObjectToObject<T,V>() {
4600 public V op(int i, T a) { return snd.op(i, fst.op(i, a)); }
4601 };
4602 }
4603
4604 static <T,U> IntAndObjectToDouble<T> compoundIndexedMapper
4605 (final IntAndObjectToObject<? super T, ? extends U> fst,
4606 final IntAndObjectToDouble<? super U> snd) {
4607 return new IntAndObjectToDouble<T>() {
4608 public double op(int i, T a) { return snd.op(i, fst.op(i, a)); }
4609 };
4610 }
4611
4612 static <T,U> IntAndObjectToLong<T> compoundIndexedMapper
4613 (final IntAndObjectToObject<? super T, ? extends U> fst,
4614 final IntAndObjectToLong<? super U> snd) {
4615 return new IntAndObjectToLong<T>() {
4616 public long op(int i, T a) { return snd.op(i, fst.op(i, a)); }
4617 };
4618 }
4619
4620 static <U,V> IntAndDoubleToObject<V> compoundIndexedMapper
4621 (final IntAndDoubleToObject<? extends U> fst,
4622 final IntAndObjectToObject<? super U, ? extends V> snd) {
4623 return new IntAndDoubleToObject<V>() {
4624 public V op(int i, double a) { return snd.op(i, fst.op(i, a)); }
4625 };
4626 }
4627
4628 static <U> IntAndDoubleToDouble compoundIndexedMapper
4629 (final IntAndDoubleToObject<? extends U> fst,
4630 final IntAndObjectToDouble<? super U> snd) {
4631 return new IntAndDoubleToDouble() {
4632 public double op(int i, double a) { return snd.op(i, fst.op(i, a)); }
4633 };
4634 }
4635
4636 static <U> IntAndDoubleToLong compoundIndexedMapper
4637 (final IntAndDoubleToObject<? extends U> fst,
4638 final IntAndObjectToLong<? super U> snd) {
4639 return new IntAndDoubleToLong() {
4640 public long op(int i, double a) { return snd.op(i, fst.op(i, a)); }
4641 };
4642 }
4643
4644 static <U,V> IntAndLongToObject<V> compoundIndexedMapper
4645 (final IntAndLongToObject<? extends U> fst,
4646 final IntAndObjectToObject<? super U, ? extends V> snd) {
4647 return new IntAndLongToObject<V>() {
4648 public V op(int i, long a) { return snd.op(i, fst.op(i, a)); }
4649 };
4650 }
4651
4652 static <U> IntAndLongToDouble compoundIndexedMapper
4653 (final IntAndLongToObject<? extends U> fst,
4654 final IntAndObjectToDouble<? super U> snd) {
4655 return new IntAndLongToDouble() {
4656 public double op(int i, long a) { return snd.op(i, fst.op(i, a)); }
4657 };
4658 }
4659
4660 static <U> IntAndLongToLong compoundIndexedMapper
4661 (final IntAndLongToObject<? extends U> fst,
4662 final IntAndObjectToLong<? super U> snd) {
4663 return new IntAndLongToLong() {
4664 public long op(int i, long a) { return snd.op(i, fst.op(i, a)); }
4665 };
4666 }
4667
4668 static <T,V> IntAndObjectToObject<T,V> compoundIndexedMapper
4669 (final IntAndObjectToDouble<? super T> fst,
4670 final IntAndDoubleToObject<? extends V> snd) {
4671 return new IntAndObjectToObject<T,V>() {
4672 public V op(int i, T a) { return snd.op(i, fst.op(i, a)); }
4673 };
4674 }
4675
4676 static <T> IntAndObjectToDouble<T> compoundIndexedMapper
4677 (final IntAndObjectToDouble<? super T> fst,
4678 final IntAndDoubleToDouble snd) {
4679 return new IntAndObjectToDouble<T>() {
4680 public double op(int i, T a) { return snd.op(i, fst.op(i, a)); }
4681 };
4682 }
4683
4684 static <T> IntAndObjectToLong<T> compoundIndexedMapper
4685 (final IntAndObjectToLong<? super T> fst,
4686 final IntAndLongToLong snd) {
4687 return new IntAndObjectToLong<T>() {
4688 public long op(int i, T a) { return snd.op(i, fst.op(i, a)); }
4689 };
4690 }
4691
4692 static <V> IntAndDoubleToObject<V> compoundIndexedMapper
4693 (final IntAndDoubleToLong fst,
4694 final IntAndLongToObject<? extends V> snd) {
4695 return new IntAndDoubleToObject<V>() {
4696 public V op(int i, double a) { return snd.op(i, fst.op(i, a)); }
4697 };
4698 }
4699
4700 static IntAndDoubleToDouble compoundIndexedMapper
4701 (final IntAndDoubleToDouble fst,
4702 final IntAndDoubleToDouble snd) {
4703 return new IntAndDoubleToDouble() {
4704 public double op(int i, double a) { return snd.op(i, fst.op(i, a)); }
4705 };
4706 }
4707
4708 static IntAndDoubleToLong compoundIndexedMapper
4709 (final IntAndDoubleToDouble fst,
4710 final IntAndDoubleToLong snd) {
4711 return new IntAndDoubleToLong() {
4712 public long op(int i, double a) { return snd.op(i, fst.op(i, a)); }
4713 };
4714 }
4715
4716 static <V> IntAndLongToObject<V> compoundIndexedMapper
4717 (final IntAndLongToDouble fst,
4718 final IntAndDoubleToObject<? extends V> snd) {
4719 return new IntAndLongToObject<V>() {
4720 public V op(int i, long a) { return snd.op(i, fst.op(i, a)); }
4721 };
4722 }
4723
4724 static IntAndLongToDouble compoundIndexedMapper
4725 (final IntAndLongToDouble fst,
4726 final IntAndDoubleToDouble snd) {
4727 return new IntAndLongToDouble() {
4728 public double op(int i, long a) { return snd.op(i, fst.op(i, a)); }
4729 };
4730 }
4731
4732 static IntAndLongToLong compoundIndexedMapper
4733 (final IntAndLongToDouble fst,
4734 final IntAndDoubleToLong snd) {
4735 return new IntAndLongToLong() {
4736 public long op(int i, long a) { return snd.op(i, fst.op(i, a)); }
4737 };
4738 }
4739
4740 static <T,V> IntAndObjectToObject<T,V> compoundIndexedMapper
4741 (final IntAndObjectToLong<? super T> fst,
4742 final IntAndLongToObject<? extends V> snd) {
4743 return new IntAndObjectToObject<T,V>() {
4744 public V op(int i, T a) { return snd.op(i, fst.op(i, a)); }
4745 };
4746 }
4747
4748 static <T> IntAndObjectToDouble<T> compoundIndexedMapper
4749 (final IntAndObjectToLong<? super T> fst,
4750 final IntAndLongToDouble snd) {
4751 return new IntAndObjectToDouble<T>() {
4752 public double op(int i, T a) { return snd.op(i, fst.op(i, a)); }
4753 };
4754 }
4755
4756 static <T> IntAndObjectToLong<T> compoundIndexedMapper
4757 (final IntAndObjectToDouble<? super T> fst,
4758 final IntAndDoubleToLong snd) {
4759 return new IntAndObjectToLong<T>() {
4760 public long op(int i, T a) { return snd.op(i, fst.op(i, a)); }
4761 };
4762 }
4763
4764 static <V> IntAndDoubleToObject<V> compoundIndexedMapper
4765 (final IntAndDoubleToDouble fst,
4766 final IntAndDoubleToObject<? extends V> snd) {
4767 return new IntAndDoubleToObject<V>() {
4768 public V op(int i, double a) { return snd.op(i, fst.op(i, a)); }
4769 };
4770 }
4771
4772 static IntAndDoubleToDouble compoundIndexedMapper
4773 (final IntAndDoubleToLong fst,
4774 final IntAndLongToDouble snd) {
4775 return new IntAndDoubleToDouble() {
4776 public double op(int i, double a) { return snd.op(i, fst.op(i, a)); }
4777 };
4778 }
4779
4780 static IntAndDoubleToLong compoundIndexedMapper
4781 (final IntAndDoubleToLong fst,
4782 final IntAndLongToLong snd) {
4783 return new IntAndDoubleToLong() {
4784 public long op(int i, double a) { return snd.op(i, fst.op(i, a)); }
4785 };
4786 }
4787
4788 static <V> IntAndLongToObject<V> compoundIndexedMapper
4789 (final IntAndLongToLong fst,
4790 final IntAndLongToObject<? extends V> snd) {
4791 return new IntAndLongToObject<V>() {
4792 public V op(int i, long a) { return snd.op(i, fst.op(i, a)); }
4793 };
4794 }
4795
4796 static IntAndLongToDouble compoundIndexedMapper
4797 (final IntAndLongToLong fst,
4798 final IntAndLongToDouble snd) {
4799 return new IntAndLongToDouble() {
4800 public double op(int i, long a) { return snd.op(i, fst.op(i, a)); }
4801 };
4802 }
4803
4804 static IntAndLongToLong compoundIndexedMapper
4805 (final IntAndLongToLong fst,
4806 final IntAndLongToLong snd) {
4807 return new IntAndLongToLong() {
4808 public long op(int i, long a) { return snd.op(i, fst.op(i, a)); }
4809 };
4810 }
4811
4812 static <T,U,V> IntAndObjectToObject<T,V> compoundIndexedMapper
4813 (final IntAndObjectToObject<? super T, ? extends U> fst,
4814 final Op<? super U, ? extends V> snd) {
4815 return new IntAndObjectToObject<T,V>() {
4816 public V op(int i, T a) { return snd.op(fst.op(i, a)); }
4817 };
4818 }
4819
4820 static <T,U> IntAndObjectToDouble<T> compoundIndexedMapper
4821 (final IntAndObjectToObject<? super T, ? extends U> fst,
4822 final ObjectToDouble<? super U> snd) {
4823 return new IntAndObjectToDouble<T>() {
4824 public double op(int i, T a) { return snd.op(fst.op(i, a)); }
4825 };
4826 }
4827
4828 static <T,U> IntAndObjectToLong<T> compoundIndexedMapper
4829 (final IntAndObjectToObject<? super T, ? extends U> fst,
4830 final ObjectToLong<? super U> snd) {
4831 return new IntAndObjectToLong<T>() {
4832 public long op(int i, T a) { return snd.op(fst.op(i, a)); }
4833 };
4834 }
4835
4836 static <U,V> IntAndDoubleToObject<V> compoundIndexedMapper
4837 (final IntAndDoubleToObject<? extends U> fst,
4838 final Op<? super U, ? extends V> snd) {
4839 return new IntAndDoubleToObject<V>() {
4840 public V op(int i, double a) { return snd.op(fst.op(i, a)); }
4841 };
4842 }
4843
4844 static <U> IntAndDoubleToDouble compoundIndexedMapper
4845 (final IntAndDoubleToObject<? extends U> fst,
4846 final ObjectToDouble<? super U> snd) {
4847 return new IntAndDoubleToDouble() {
4848 public double op(int i, double a) { return snd.op(fst.op(i, a)); }
4849 };
4850 }
4851
4852 static <U> IntAndDoubleToLong compoundIndexedMapper
4853 (final IntAndDoubleToObject<? extends U> fst,
4854 final ObjectToLong<? super U> snd) {
4855 return new IntAndDoubleToLong() {
4856 public long op(int i, double a) { return snd.op(fst.op(i, a)); }
4857 };
4858 }
4859
4860 static <U,V> IntAndLongToObject<V> compoundIndexedMapper
4861 (final IntAndLongToObject<? extends U> fst,
4862 final Op<? super U, ? extends V> snd) {
4863 return new IntAndLongToObject<V>() {
4864 public V op(int i, long a) { return snd.op(fst.op(i, a)); }
4865 };
4866 }
4867
4868 static <U> IntAndLongToDouble compoundIndexedMapper
4869 (final IntAndLongToObject<? extends U> fst,
4870 final ObjectToDouble<? super U> snd) {
4871 return new IntAndLongToDouble() {
4872 public double op(int i, long a) { return snd.op(fst.op(i, a)); }
4873 };
4874 }
4875
4876 static <U> IntAndLongToLong compoundIndexedMapper
4877 (final IntAndLongToObject<? extends U> fst,
4878 final ObjectToLong<? super U> snd) {
4879 return new IntAndLongToLong() {
4880 public long op(int i, long a) { return snd.op(fst.op(i, a)); }
4881 };
4882 }
4883
4884 static <T,V> IntAndObjectToObject<T,V> compoundIndexedMapper
4885 (final IntAndObjectToDouble<? super T> fst,
4886 final DoubleToObject<? extends V> snd) {
4887 return new IntAndObjectToObject<T,V>() {
4888 public V op(int i, T a) { return snd.op(fst.op(i, a)); }
4889 };
4890 }
4891
4892 static <T> IntAndObjectToDouble<T> compoundIndexedMapper
4893 (final IntAndObjectToDouble<? super T> fst,
4894 final DoubleOp snd) {
4895 return new IntAndObjectToDouble<T>() {
4896 public double op(int i, T a) { return snd.op(fst.op(i, a)); }
4897 };
4898 }
4899
4900 static <T> IntAndObjectToLong<T> compoundIndexedMapper
4901 (final IntAndObjectToDouble<? super T> fst,
4902 final DoubleToLong snd) {
4903 return new IntAndObjectToLong<T>() {
4904 public long op(int i, T a) { return snd.op(fst.op(i, a)); }
4905 };
4906 }
4907
4908 static <V> IntAndDoubleToObject<V> compoundIndexedMapper
4909 (final IntAndDoubleToDouble fst,
4910 final DoubleToObject<? extends V> snd) {
4911 return new IntAndDoubleToObject<V>() {
4912 public V op(int i, double a) { return snd.op(fst.op(i, a)); }
4913 };
4914 }
4915
4916 static IntAndDoubleToDouble compoundIndexedMapper
4917 (final IntAndDoubleToDouble fst,
4918 final DoubleOp snd) {
4919 return new IntAndDoubleToDouble() {
4920 public double op(int i, double a) { return snd.op(fst.op(i, a)); }
4921 };
4922 }
4923
4924 static IntAndDoubleToLong compoundIndexedMapper
4925 (final IntAndDoubleToDouble fst,
4926 final DoubleToLong snd) {
4927 return new IntAndDoubleToLong() {
4928 public long op(int i, double a) { return snd.op(fst.op(i, a)); }
4929 };
4930 }
4931
4932 static <V> IntAndLongToObject<V> compoundIndexedMapper
4933 (final IntAndLongToDouble fst,
4934 final DoubleToObject<? extends V> snd) {
4935 return new IntAndLongToObject<V>() {
4936 public V op(int i, long a) { return snd.op(fst.op(i, a)); }
4937 };
4938 }
4939
4940 static IntAndLongToDouble compoundIndexedMapper
4941 (final IntAndLongToDouble fst,
4942 final DoubleOp snd) {
4943 return new IntAndLongToDouble() {
4944 public double op(int i,long a) { return snd.op(fst.op(i, a)); }
4945 };
4946 }
4947
4948 static IntAndLongToLong compoundIndexedMapper
4949 (final IntAndLongToDouble fst,
4950 final DoubleToLong snd) {
4951 return new IntAndLongToLong() {
4952 public long op(int i, long a) { return snd.op(fst.op(i, a)); }
4953 };
4954 }
4955
4956 static <T,V> IntAndObjectToObject<T,V> compoundIndexedMapper
4957 (final IntAndObjectToLong<? super T> fst,
4958 final LongToObject<? extends V> snd) {
4959 return new IntAndObjectToObject<T,V>() {
4960 public V op(int i, T a) { return snd.op(fst.op(i, a)); }
4961 };
4962 }
4963
4964 static <T> IntAndObjectToDouble<T> compoundIndexedMapper
4965 (final IntAndObjectToLong<? super T> fst,
4966 final LongToDouble snd) {
4967 return new IntAndObjectToDouble<T>() {
4968 public double op(int i, T a) { return snd.op(fst.op(i, a)); }
4969 };
4970 }
4971
4972 static <T> IntAndObjectToLong<T> compoundIndexedMapper
4973 (final IntAndObjectToLong<? super T> fst,
4974 final LongOp snd) {
4975 return new IntAndObjectToLong<T>() {
4976 public long op(int i, T a) { return snd.op(fst.op(i, a)); }
4977 };
4978 }
4979
4980 static <V> IntAndDoubleToObject<V> compoundIndexedMapper
4981 (final IntAndDoubleToLong fst,
4982 final LongToObject<? extends V> snd) {
4983 return new IntAndDoubleToObject<V>() {
4984 public V op(int i, double a) { return snd.op(fst.op(i, a)); }
4985 };
4986 }
4987
4988 static IntAndDoubleToDouble compoundIndexedMapper
4989 (final IntAndDoubleToLong fst,
4990 final LongToDouble snd) {
4991 return new IntAndDoubleToDouble() {
4992 public double op(int i, double a) { return snd.op(fst.op(i, a)); }
4993 };
4994 }
4995
4996 static IntAndDoubleToLong compoundIndexedMapper
4997 (final IntAndDoubleToLong fst,
4998 final LongOp snd) {
4999 return new IntAndDoubleToLong() {
5000 public long op(int i, double a) { return snd.op(fst.op(i, a)); }
5001 };
5002 }
5003
5004 static <V> IntAndLongToObject<V> compoundIndexedMapper
5005 (final IntAndLongToLong fst,
5006 final LongToObject<? extends V> snd) {
5007 return new IntAndLongToObject<V>() {
5008 public V op(int i, long a) { return snd.op(fst.op(i, a)); }
5009 };
5010 }
5011
5012 static IntAndLongToDouble compoundIndexedMapper
5013 (final IntAndLongToLong fst,
5014 final LongToDouble snd) {
5015 return new IntAndLongToDouble() {
5016 public double op(int i,long a) { return snd.op(fst.op(i, a)); }
5017 };
5018 }
5019
5020 static IntAndLongToLong compoundIndexedMapper
5021 (final IntAndLongToLong fst,
5022 final LongOp snd) {
5023 return new IntAndLongToLong() {
5024 public long op(int i, long a) { return snd.op(fst.op(i, a)); }
5025 };
5026 }
5027
5028 static <T,U,V> IntAndObjectToObject<T,V> compoundIndexedMapper
5029 (final Op<? super T, ? extends U> fst,
5030 final IntAndObjectToObject<? super U, ? extends V> snd) {
5031 return new IntAndObjectToObject<T,V>() {
5032 public V op(int i, T a) { return snd.op(i, fst.op(a)); }
5033 };
5034 }
5035
5036 static <T,U> IntAndObjectToDouble<T> compoundIndexedMapper
5037 (final Op<? super T, ? extends U> fst,
5038 final IntAndObjectToDouble<? super U> snd) {
5039 return new IntAndObjectToDouble<T>() {
5040 public double op(int i, T a) { return snd.op(i, fst.op(a)); }
5041 };
5042 }
5043
5044 static <T,U> IntAndObjectToLong<T> compoundIndexedMapper
5045 (final Op<? super T, ? extends U> fst,
5046 final IntAndObjectToLong<? super U> snd) {
5047 return new IntAndObjectToLong<T>() {
5048 public long op(int i, T a) { return snd.op(i, fst.op(a)); }
5049 };
5050 }
5051
5052 static <U,V> IntAndDoubleToObject<V> compoundIndexedMapper
5053 (final DoubleToObject<? extends U> fst,
5054 final IntAndObjectToObject<? super U, ? extends V> snd) {
5055 return new IntAndDoubleToObject<V>() {
5056 public V op(int i, double a) { return snd.op(i, fst.op(a)); }
5057 };
5058 }
5059
5060 static <U> IntAndDoubleToDouble compoundIndexedMapper
5061 (final DoubleToObject<? extends U> fst,
5062 final IntAndObjectToDouble<? super U> snd) {
5063 return new IntAndDoubleToDouble() {
5064 public double op(int i, double a) { return snd.op(i, fst.op(a)); }
5065 };
5066 }
5067
5068 static <U> IntAndDoubleToLong compoundIndexedMapper
5069 (final DoubleToObject<? extends U> fst,
5070 final IntAndObjectToLong<? super U> snd) {
5071 return new IntAndDoubleToLong() {
5072 public long op(int i, double a) { return snd.op(i, fst.op(a)); }
5073 };
5074 }
5075
5076 static <U,V> IntAndLongToObject<V> compoundIndexedMapper
5077 (final LongToObject<? extends U> fst,
5078 final IntAndObjectToObject<? super U, ? extends V> snd) {
5079 return new IntAndLongToObject<V>() {
5080 public V op(int i, long a) { return snd.op(i, fst.op(a)); }
5081 };
5082 }
5083
5084 static <U> IntAndLongToDouble compoundIndexedMapper
5085 (final LongToObject<? extends U> fst,
5086 final IntAndObjectToDouble<? super U> snd) {
5087 return new IntAndLongToDouble() {
5088 public double op(int i, long a) { return snd.op(i, fst.op(a)); }
5089 };
5090 }
5091
5092 static <U> IntAndLongToLong compoundIndexedMapper
5093 (final LongToObject<? extends U> fst,
5094 final IntAndObjectToLong<? super U> snd) {
5095 return new IntAndLongToLong() {
5096 public long op(int i, long a) { return snd.op(i, fst.op(a)); }
5097 };
5098 }
5099
5100 static <T,V> IntAndObjectToObject<T,V> compoundIndexedMapper
5101 (final ObjectToDouble<? super T> fst,
5102 final IntAndDoubleToObject<? extends V> snd) {
5103 return new IntAndObjectToObject<T,V>() {
5104 public V op(int i, T a) { return snd.op(i, fst.op(a)); }
5105 };
5106 }
5107
5108 static <T> IntAndObjectToDouble<T> compoundIndexedMapper
5109 (final ObjectToDouble<? super T> fst,
5110 final IntAndDoubleToDouble snd) {
5111 return new IntAndObjectToDouble<T>() {
5112 public double op(int i, T a) { return snd.op(i, fst.op(a)); }
5113 };
5114 }
5115
5116 static <T> IntAndObjectToLong<T> compoundIndexedMapper
5117 (final ObjectToDouble<? super T> fst,
5118 final IntAndDoubleToLong snd) {
5119 return new IntAndObjectToLong<T>() {
5120 public long op(int i, T a) { return snd.op(i, fst.op(a)); }
5121 };
5122 }
5123
5124 static <V> IntAndDoubleToObject<V> compoundIndexedMapper
5125 (final DoubleOp fst,
5126 final IntAndDoubleToObject<? extends V> snd) {
5127 return new IntAndDoubleToObject<V>() {
5128 public V op(int i, double a) { return snd.op(i, fst.op(a)); }
5129 };
5130 }
5131
5132 static IntAndDoubleToDouble compoundIndexedMapper
5133 (final DoubleOp fst,
5134 final IntAndDoubleToDouble snd) {
5135 return new IntAndDoubleToDouble() {
5136 public double op(int i, double a) { return snd.op(i, fst.op(a)); }
5137 };
5138 }
5139
5140 static IntAndDoubleToLong compoundIndexedMapper
5141 (final DoubleOp fst,
5142 final IntAndDoubleToLong snd) {
5143 return new IntAndDoubleToLong() {
5144 public long op(int i, double a) { return snd.op(i, fst.op(a)); }
5145 };
5146 }
5147
5148 static <V> IntAndLongToObject<V> compoundIndexedMapper
5149 (final LongToDouble fst,
5150 final IntAndDoubleToObject<? extends V> snd) {
5151 return new IntAndLongToObject<V>() {
5152 public V op(int i, long a) { return snd.op(i, fst.op(a)); }
5153 };
5154 }
5155
5156 static IntAndLongToDouble compoundIndexedMapper
5157 (final LongToDouble fst,
5158 final IntAndDoubleToDouble snd) {
5159 return new IntAndLongToDouble() {
5160 public double op(int i, long a) { return snd.op(i, fst.op(a)); }
5161 };
5162 }
5163
5164 static IntAndLongToLong compoundIndexedMapper
5165 (final LongToDouble fst,
5166 final IntAndDoubleToLong snd) {
5167 return new IntAndLongToLong() {
5168 public long op(int i, long a) { return snd.op(i, fst.op(a)); }
5169 };
5170 }
5171
5172 static <T,V> IntAndObjectToObject<T,V> compoundIndexedMapper
5173 (final ObjectToLong<? super T> fst,
5174 final IntAndLongToObject<? extends V> snd) {
5175 return new IntAndObjectToObject<T,V>() {
5176 public V op(int i, T a) { return snd.op(i, fst.op(a)); }
5177 };
5178 }
5179
5180 static <T> IntAndObjectToDouble<T> compoundIndexedMapper
5181 (final ObjectToLong<? super T> fst,
5182 final IntAndLongToDouble snd) {
5183 return new IntAndObjectToDouble<T>() {
5184 public double op(int i, T a) { return snd.op(i, fst.op(a)); }
5185 };
5186 }
5187
5188 static <T> IntAndObjectToLong<T> compoundIndexedMapper
5189 (final ObjectToLong<? super T> fst,
5190 final IntAndLongToLong snd) {
5191 return new IntAndObjectToLong<T>() {
5192 public long op(int i, T a) { return snd.op(i, fst.op(a)); }
5193 };
5194 }
5195
5196 static <V> IntAndDoubleToObject<V> compoundIndexedMapper
5197 (final DoubleToLong fst,
5198 final IntAndLongToObject<? extends V> snd) {
5199 return new IntAndDoubleToObject<V>() {
5200 public V op(int i, double a) { return snd.op(i, fst.op(a)); }
5201 };
5202 }
5203
5204 static IntAndDoubleToDouble compoundIndexedMapper
5205 (final DoubleToLong fst,
5206 final IntAndLongToDouble snd) {
5207 return new IntAndDoubleToDouble() {
5208 public double op(int i, double a) { return snd.op(i, fst.op(a)); }
5209 };
5210 }
5211
5212 static IntAndDoubleToLong compoundIndexedMapper
5213 (final DoubleToLong fst,
5214 final IntAndLongToLong snd) {
5215 return new IntAndDoubleToLong() {
5216 public long op(int i, double a) { return snd.op(i, fst.op(a)); }
5217 };
5218 }
5219
5220 static <V> IntAndLongToObject<V> compoundIndexedMapper
5221 (final LongOp fst,
5222 final IntAndLongToObject<? extends V> snd) {
5223 return new IntAndLongToObject<V>() {
5224 public V op(int i, long a) { return snd.op(i, fst.op(a)); }
5225 };
5226 }
5227
5228 static IntAndLongToDouble compoundIndexedMapper
5229 (final LongOp fst,
5230 final IntAndLongToDouble snd) {
5231 return new IntAndLongToDouble() {
5232 public double op(int i, long a) { return snd.op(i, fst.op(a)); }
5233 };
5234 }
5235
5236 static IntAndLongToLong compoundIndexedMapper
5237 (final LongOp fst,
5238 final IntAndLongToLong snd) {
5239 return new IntAndLongToLong() {
5240 public long op(int i, long a) { return snd.op(i, fst.op(a)); }
5241 };
5242 }
5243
5244 }