1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
/* __ *\
** ________ ___ / / ___ Scala API **
** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL **
** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
** /____/\___/_/ |_/____/_/ | | **
** |/ **
\* */
package scala.collection.parallel.immutable
import scala.collection.immutable.NumericRange
import scala.collection.parallel.Combiner
import scala.collection.generic.CanCombineFrom
import scala.collection.parallel.ParIterableIterator
/** Parallel ranges for numeric types.
*
* $paralleliterableinfo
*
* $sideeffects
*
* @param range the sequential range this parallel range was obtained from
*
* @author Aleksandar Prokopec
* @since 2.9
*
* @define Coll `immutable.ParRange`
* @define coll immutable parallel range
*/
@SerialVersionUID(1L)
class ParNumericRange[T](val range: NumericRange[T])(implicit num: Integral[T])
extends ParSeq[T]
with Serializable
{
self =>
def seq = range
@inline final def length = range.length
@inline final def apply(idx: Int) = range.apply(idx);
def parallelIterator = new ParNumericRangeIterator with SCPI
type SCPI = SignalContextPassingIterator[ParNumericRangeIterator]
class ParNumericRangeIterator(range: NumericRange[T] = self.range, num: Integral[T] = self.num)
extends ParIterator {
me: SignalContextPassingIterator[ParNumericRangeIterator] =>
override def toString = "ParNumericRangeIterator(over: " + range + ")"
private var ind = 0
private val len = range.length
final def remaining = len - ind
final def hasNext = ind < len
final def next = if (hasNext) {
val r = range.apply(ind)
ind += 1
r
} else Iterator.empty.next
private def rangeleft: NumericRange[T] = range.drop(ind)
def dup = new ParNumericRangeIterator(rangeleft) with SCPI
def split = {
val rleft = rangeleft
val elemleft = rleft.length
if (elemleft < 2) Seq(new ParNumericRangeIterator(rleft) with SCPI)
else Seq(
new ParNumericRangeIterator(rleft.take(elemleft / 2)) with SCPI,
new ParNumericRangeIterator(rleft.drop(elemleft / 2)) with SCPI
)
}
def psplit(sizes: Int*) = {
var rleft = rangeleft
for (sz <- sizes) yield {
val fronttaken = rleft.take(sz)
rleft = rleft.drop(sz)
new ParNumericRangeIterator(fronttaken) with SCPI
}
}
/* accessors */
override def foreach[U](f: T => U): Unit = {
rangeleft.foreach(f)
ind = len
}
override def reduce[U >: T](op: (U, U) => U): U = {
val r = rangeleft.reduceLeft(op)
ind = len
r
}
/* transformers */
override def map2combiner[S, That](f: T => S, cb: Combiner[S, That]): Combiner[S, That] = {
while (hasNext) {
cb += f(next)
}
cb
}
}
}
object ParNumericRange {
def apply[T](start: T, end: T, step: T, inclusive: Boolean)(implicit num: Integral[T]) = new ParNumericRange[T](
if (inclusive) NumericRange.inclusive(start, end, step)(num)
else NumericRange.apply(start, end, step)(num)
)
}
|