summaryrefslogtreecommitdiff
path: root/src/library/scala/collection/parallel/immutable/ParRange.scala
blob: ab5e5095157b8b80b35484cc95ec632304be1e0f (plain) (blame)
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
package scala.collection.parallel.immutable



import scala.collection.immutable.Range
import scala.collection.immutable.RangeUtils
import scala.collection.parallel.ParSeq
import scala.collection.parallel.Combiner
import scala.collection.generic.CanCombineFrom
import scala.collection.parallel.ParIterableIterator



class ParRange(range: Range)
extends ParSeq[Int] {
self =>

  def seq = range

  @inline
  final def length = range.length

  @inline
  final def apply(idx: Int) = range.apply(idx)

  def parallelIterator = new ParRangeIterator with SCPI

  type SCPI = SignalContextPassingIterator[ParRangeIterator]

  class ParRangeIterator(range: Range = self.range)
  extends ParIterator {
  me: SignalContextPassingIterator[ParRangeIterator] =>
    override def toString = "ParRangeIterator(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 = range.drop(ind)

    def dup = new ParRangeIterator(rangeleft) with SCPI

    def split = {
      val rleft = rangeleft
      val elemleft = rleft.length
      if (elemleft < 2) Seq(new ParRangeIterator(rleft) with SCPI)
      else Seq(
        new ParRangeIterator(rleft.take(elemleft / 2)) with SCPI,
        new ParRangeIterator(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 ParRangeIterator(fronttaken) with SCPI
      }
    }

    /* accessors */

    override def foreach[U](f: Int => U): Unit = {
      rangeleft.foreach(f)
      ind = len
    }

    override def reduce[U >: Int](op: (U, U) => U): U = {
      val r = rangeleft.reduceLeft(op)
      ind = len
      r
    }

    /* transformers */

    override def map2combiner[S, That](f: Int => S, cb: Combiner[S, That]): Combiner[S, That] = {
      while (hasNext) {
        cb += f(next)
      }
      cb
    }

  }

}


object ParRange {
  def apply(start: Int, end: Int, step: Int, inclusive: Boolean) = new ParRange(
    if (inclusive) new Range.Inclusive(start, end, step)
    else new Range(start, end, step)
  )
}