/
IndexedSeq.scala
147 lines (111 loc) · 5.71 KB
/
IndexedSeq.scala
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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/*
* Scala (https://www.scala-lang.org)
*
* Copyright EPFL and Lightbend, Inc.
*
* Licensed under Apache License 2.0
* (http://www.apache.org/licenses/LICENSE-2.0).
*
* See the NOTICE file distributed with this work for
* additional information regarding copyright ownership.
*/
package scala
package collection
import scala.annotation.{nowarn, tailrec}
import scala.collection.Searching.{Found, InsertionPoint, SearchResult}
import scala.collection.Stepper.EfficientSplit
import scala.math.Ordering
/** Base trait for indexed sequences that have efficient `apply` and `length` */
trait IndexedSeq[+A] extends Seq[A]
with IndexedSeqOps[A, IndexedSeq, IndexedSeq[A]]
with IterableFactoryDefaults[A, IndexedSeq] {
@nowarn("""cat=deprecation&origin=scala\.collection\.Iterable\.stringPrefix""")
override protected[this] def stringPrefix: String = "IndexedSeq"
override def iterableFactory: SeqFactory[IndexedSeq] = IndexedSeq
}
@SerialVersionUID(3L)
object IndexedSeq extends SeqFactory.Delegate[IndexedSeq](immutable.IndexedSeq)
/** Base trait for indexed Seq operations */
trait IndexedSeqOps[+A, +CC[_], +C] extends Any with SeqOps[A, CC, C] { self =>
def iterator: Iterator[A] = view.iterator
override def stepper[S <: Stepper[_]](implicit shape: StepperShape[A, S]): S with EfficientSplit = {
import convert.impl._
val s = shape.shape match {
case StepperShape.IntShape => new IntIndexedSeqStepper (this.asInstanceOf[IndexedSeqOps[Int, AnyConstr, _]], 0, length)
case StepperShape.LongShape => new LongIndexedSeqStepper (this.asInstanceOf[IndexedSeqOps[Long, AnyConstr, _]], 0, length)
case StepperShape.DoubleShape => new DoubleIndexedSeqStepper(this.asInstanceOf[IndexedSeqOps[Double, AnyConstr, _]], 0, length)
case _ => shape.parUnbox(new AnyIndexedSeqStepper[A](this, 0, length))
}
s.asInstanceOf[S with EfficientSplit]
}
override def reverseIterator: Iterator[A] = view.reverseIterator
/* TODO 2.14+ uncomment and delete related code in IterableOnce
@tailrec private def foldl[B](start: Int, end: Int, z: B, op: (B, A) => B): B =
if (start == end) z
else foldl(start + 1, end, op(z, apply(start)), op)
*/
@tailrec private def foldr[B](start: Int, end: Int, z: B, op: (A, B) => B): B =
if (start == end) z
else foldr(start, end - 1, op(apply(end - 1), z), op)
//override def foldLeft[B](z: B)(op: (B, A) => B): B = foldl(0, length, z, op)
override def foldRight[B](z: B)(op: (A, B) => B): B = foldr(0, length, z, op)
//override def reduceLeft[B >: A](op: (B, A) => B): B = if (length > 0) foldl(1, length, apply(0), op) else super.reduceLeft(op)
//override def reduceRight[B >: A](op: (A, B) => B): B = if (length > 0) foldr(0, length - 1, apply(length - 1), op) else super.reduceRight(op)
override def view: IndexedSeqView[A] = new IndexedSeqView.Id[A](this)
@deprecated("Use .view.slice(from, until) instead of .view(from, until)", "2.13.0")
override def view(from: Int, until: Int): IndexedSeqView[A] = view.slice(from, until)
override protected def reversed: Iterable[A] = new IndexedSeqView.Reverse(this)
// Override transformation operations to use more efficient views than the default ones
override def prepended[B >: A](elem: B): CC[B] = iterableFactory.from(new IndexedSeqView.Prepended(elem, this))
override def take(n: Int): C = fromSpecific(new IndexedSeqView.Take(this, n))
override def takeRight(n: Int): C = fromSpecific(new IndexedSeqView.TakeRight(this, n))
override def drop(n: Int): C = fromSpecific(new IndexedSeqView.Drop(this, n))
override def dropRight(n: Int): C = fromSpecific(new IndexedSeqView.DropRight(this, n))
override def map[B](f: A => B): CC[B] = iterableFactory.from(new IndexedSeqView.Map(this, f))
override def reverse: C = fromSpecific(new IndexedSeqView.Reverse(this))
override def slice(from: Int, until: Int): C = fromSpecific(new IndexedSeqView.Slice(this, from, until))
override def head: A =
if (!isEmpty) apply(0)
else throw new NoSuchElementException(s"head of empty ${
self match {
case self: IndexedSeq[_] => self.collectionClassName
case _ => toString
}
}")
override def headOption: Option[A] = if (isEmpty) None else Some(head)
override def last: A =
if (!isEmpty) apply(length - 1)
else throw new NoSuchElementException(s"last of empty ${
self match {
case self: IndexedSeq[_] => self.collectionClassName
case _ => toString
}
}")
// We already inherit an efficient `lastOption = if (isEmpty) None else Some(last)`
override final def lengthCompare(len: Int): Int = Integer.compare(length, len)
override def knownSize: Int = length
override final def lengthCompare(that: Iterable[_]): Int = {
val res = that.sizeCompare(length)
// can't just invert the result, because `-Int.MinValue == Int.MinValue`
if (res == Int.MinValue) 1 else -res
}
override def search[B >: A](elem: B)(implicit ord: Ordering[B]): SearchResult =
binarySearch(elem, 0, length)(ord)
override def search[B >: A](elem: B, from: Int, to: Int)(implicit ord: Ordering[B]): SearchResult =
binarySearch(elem, from, to)(ord)
@tailrec
private[this] def binarySearch[B >: A](elem: B, from: Int, to: Int)
(implicit ord: Ordering[B]): SearchResult = {
if (from < 0) binarySearch(elem, 0, to)
else if (to > length) binarySearch(elem, from, length)
else if (to <= from) InsertionPoint(from)
else {
val idx = from + (to - from - 1) / 2
math.signum(ord.compare(elem, apply(idx))) match {
case -1 => binarySearch(elem, from, idx)(ord)
case 1 => binarySearch(elem, idx + 1, to)(ord)
case _ => Found(idx)
}
}
}
}