@@ -6,41 +6,37 @@ import scala.reflect.ClassTag
66
77trait  IndexVectorLike [V ] extends  breeze.linalg.Vector [V ] with  VectorLike [V , IndexVectorLike [V ]] {
88
9-   //  TODO  unique ? 
9+   def   unique :   Boolean 
1010  def  ordered :  Boolean 
11- 
1211  def  reversed :  Boolean 
1312
1413  override  def  activeSize :  Int  =  length
15- 
1614  override  def  activeIterator :  Iterator [(Int , V )] =  iterator
17- 
1815  override  def  activeValuesIterator :  Iterator [V ] =  valuesIterator
19- 
2016  override  def  activeKeysIterator :  Iterator [Int ] =  keysIterator
21- 
2217  override  def  repr :  IndexVectorLike [V ] =  this 
23- 
2418  override  def  toString :  String  =  {
25-     valuesIterator.mkString(s " IndexVector( ordered=,  reversed= $reversed,  data=[ " , " , " " ])" 
19+     valuesIterator.mkString(s " Index(unique= $unique , ordered=,reversed= $reversed,data=[ " , " , " " ])" 
2620  }
2721
2822  override  def  copy :  IndexVector [V ]
2923
3024  def  merge (other : IndexVectorLike [V ])(implicit  ord : Ordering [V ], tag : ClassTag [V ]):  IndexVectorLike [V ] =  {
3125    var  vals  =  Array .concat(toArray, other.toArray)
32-     vals =  vals.distinct
26+     if (unique) {
27+       vals =  vals.distinct
28+     }
3329    if  (ordered) {
3430      vals =  vals.sorted(ord)
3531      if  (reversed) {
3632        vals =  vals.reverse
3733      }
3834    }
39-     IndexVector [V ](vals, ordered, reversed)
35+     IndexVector [V ](vals, unique,  ordered, reversed)
4036  }
4137
4238  def  indexOfUnexact (value : V )(implicit  ord : Ordering [V ]):  Option [(Int , Int )] =  {
43-     var  exact  =  indexOfExact(value)
39+     var  exact  =  if (unique)  indexOfExact(value)  else   None 
4440    if  (exact.isDefined) {
4541      Some ((exact.get, exact.get))
4642    } else  {
@@ -50,27 +46,52 @@ trait IndexVectorLike[V] extends breeze.linalg.Vector[V] with VectorLike[V, Inde
5046
5147  def  indexOfExact (value : V ):  Option [Int ]
5248
49+   //  returns range of indexes
50+   //    or index of first element that less and index of first element that great
51+   //    or None
52+   //  TODO tests
5353  def  indexOfBinarySearch (value : V )(implicit  ord : Ordering [V ]):  Option [(Int , Int )] =  {
54-     if  (! ordered) {
54+     if  (! ordered  ||  length  <   1 ) {
5555      return  None 
5656    }
5757
58-     var  leftIdx  =  0 
59-     var  rightIdx  =  this .length -  1 
58+     var  leftLeftIdx  =  0 
59+     var  rightRightIdx  =  this .length -  1 
6060
61-     if  (leftIdx >  rightIdx) {
62-       return  None 
61+     var  leftVal :  V  =  apply(leftLeftIdx)
62+     var  rightVal :  V  =  apply(rightRightIdx)
63+ 
64+     @ inline
65+     def  findSameRightIdx (leftIdx : Int , leftVal : V ) =  {
66+       var  rightIdx  =  leftIdx
67+       if  (! unique) {
68+         do  rightIdx +=  1 
69+         while  (rightIdx <  length &&  apply(rightIdx) ==  leftVal)
70+         rightIdx -=  1 
71+       }
72+       rightIdx
6373    }
6474
65-     var  leftVal :  V  =  apply(leftIdx)
66-     var  rightVal :  V  =  apply(rightIdx)
75+     @ inline
76+     def  findSameLeftIdx (rightIdx : Int , rightVal : V ) =  {
77+       var  leftIdx  =  rightIdx
78+       if  (! unique) {
79+         do  leftIdx -=  1 
80+         while  (rightIdx >  0  &&  apply(leftIdx) ==  rightVal)
81+         leftIdx +=  1 
82+       }
83+       leftIdx
84+     }
85+ 
86+     var  leftRightIdx  =  findSameRightIdx(leftLeftIdx, leftVal)
87+     var  rightLeftIdx  =  findSameLeftIdx(rightRightIdx, rightVal)
6788
6889    if  (leftVal ==  value) {
69-       return  Some ((leftIdx, leftIdx ))
90+       return  Some ((leftLeftIdx, leftRightIdx ))
7091    }
7192
7293    if  (rightVal ==  value) {
73-       return  Some ((rightIdx, rightIdx ))
94+       return  Some ((leftLeftIdx, rightLeftIdx ))
7495    }
7596
7697    if  (ord.lt(rightVal, value) ^  reversed) {
@@ -81,64 +102,75 @@ trait IndexVectorLike[V] extends breeze.linalg.Vector[V] with VectorLike[V, Inde
81102      return  None 
82103    }
83104
84-     while  (rightIdx  -  leftIdx  >  1 ) {
85-       val  midIdx  =  (rightIdx  +  leftIdx ) /  2 
105+     while  (rightLeftIdx  -  leftRightIdx  >  0 ) {
106+       val  midIdx  =  (rightLeftIdx  +  leftRightIdx ) /  2 
86107      val  midVal  =  apply(midIdx)
108+ 
109+       var  midLeftIdx  =  findSameLeftIdx(midIdx, midVal)
110+       var  midRightIdx  =  findSameRightIdx(midIdx, midVal)
111+ 
87112      if  (midVal ==  value) {
88-         return  Some ((midIdx, midIdx ))
113+         return  Some ((midLeftIdx, midRightIdx ))
89114      } else  if  (ord.lt(midVal, value) ^  reversed) {
90-         leftIdx =  midIdx
115+         leftLeftIdx =  midLeftIdx
116+         leftRightIdx =  midRightIdx
91117        leftVal =  midVal
92118      } else  if  (ord.gt(midVal, value) ^  reversed) {
93-         rightIdx =  midIdx
119+         rightRightIdx =  midRightIdx
120+         rightLeftIdx =  midLeftIdx
94121        rightVal =  midVal
95122      }
96123    }
97-     Some ((leftIdx, rightIdx ))
124+     Some ((leftRightIdx, rightLeftIdx ))
98125  }
99126
100127  def  sliceMask (mask : breeze.linalg.Vector [Boolean ]):  SliceIndexVector [V ] =  sliceMask(mask.valuesIterator)
101-   def  sliceMask (mask : Boolean * ):  SliceIndexVector [V ] =  sliceMask(mask.iterator )
102-   def  sliceMask (mask : Iterable [Boolean ]):  SliceIndexVector [V ] =  sliceMask(mask.iterator) 
103-   def   sliceMask ( mask :  Iterator [ Boolean ]) :   SliceIndexVector [ V ]  =  sliceSeq (mask.zipWithIndex.filter(_._1).map(_._2))
128+   def  sliceMask (mask : Boolean * ):  SliceIndexVector [V ] =  sliceMask(mask)
129+   def  sliceMask (mask : IterableOnce [Boolean ]):  SliceIndexVector [V ] = 
130+     sliceIdx (mask.iterator .zipWithIndex.filter(_._1).map(_._2))
104131
105-   def  sliceSeq (idx : breeze.linalg.Vector [Int ]):  SliceIndexVector [V ] =  sliceSeq(idx.valuesIterator)
106-   def  sliceSeq (idx : Int * ):  SliceIndexVector [V ] =  sliceSeq(idx.iterator)
107-   def  sliceSeq (idx : Iterable [Int ]):  SliceIndexVector [V ] =  sliceSeq(idx.iterator)
108-   def  sliceSeq (idx : Iterator [Int ]):  SliceIndexVector [V ]
132+   def  sliceIdx (idx : breeze.linalg.Vector [Int ]):  SliceIndexVector [V ] =  sliceIdx(idx.valuesIterator)
133+   def  sliceIdx (idx : Int * ):  SliceIndexVector [V ] =  sliceIdx(idx.iterator)
134+   def  sliceIdx (idx : IterableOnce [Int ]):  SliceIndexVector [V ]
109135
110-   def  sliceRange (start : Int , end : Int , step : Int , left : Boolean , right : Boolean , round : Boolean )
111-     :  SliceIndexVector [V ] =  sliceSeq (RoundArrayRange (length, start, end, step, left, right , round))
136+   def  sliceRange (start : Int , end : Int , step : Int , keepStart : Boolean , keepEnd : Boolean , round : Boolean )
137+     :  SliceIndexVector [V ] =  sliceIdx (RoundArrayRange (length, start, end, step, keepStart, keepEnd , round))
112138
113139  def  loc (v : V ):  Option [Int ] =  indexOfExact(v)
114140
115-   def  sliceLoc (v : breeze.linalg.Vector [V ]):  SliceIndexVector [V ] =  sliceLoc(v.valuesIterator)
116-   def  sliceLoc (v : V * ): SliceIndexVector [V ] =  sliceLoc(v.iterator)
117-   def  sliceLoc (v : Iterable [V ]):  SliceIndexVector [V ] =  sliceLoc(v.iterator)
118-   def  sliceLoc (v : Iterator [V ]):  SliceIndexVector [V ] =  {
119-     var  idxo  =  v.map(indexOfExact).filter(_.isDefined).map(_.get)
120-     sliceSeq(idxo)
141+   def  sliceLoc (vals : breeze.linalg.Vector [V ]):  SliceIndexVector [V ] =  sliceLoc(vals.valuesIterator)
142+   def  sliceLoc (vals : V * ): SliceIndexVector [V ] =  sliceLoc(vals.iterator)
143+   def  sliceLoc (vals : IterableOnce [V ]):  SliceIndexVector [V ] =  {
144+     sliceIdx(vals.iterator.map(indexOfExact).filter(_.isDefined).map(_.get))
121145  }
122146
123147  def  sliceLocRange (start : V , end : V , step : Int  =  1 ,
124-                     left : Boolean  =  true , right : Boolean  =  true , round : Boolean  =  true )
148+                     keepStart : Boolean  =  true , keepEnd : Boolean  =  true , round : Boolean  =  true )
125149                   (implicit  ord : Ordering [V ], tag : ClassTag [V ]):  SliceIndexVector [V ] =  {
126150      val  startIdx  =  indexOfUnexact(start)(ord)
127151      val  endIdx  =  indexOfUnexact(end)(ord)
128152      if (startIdx.isEmpty ||  endIdx.isEmpty) {
129-         IndexVectorLike .empty[V ].sliceSeq( Seq () )
153+         IndexVectorLike .empty[V ].sliceIdx( )
130154      } else  {
131155        sliceRange(
132-           if (step >  0 ) startIdx.get._2 else  startIdx.get._1,
133-           if (step >  0 ) endIdx.get._1 else  endIdx.get._2,
156+           if (step >  0 )
157+             if (! unique &&  keepStart &&  apply(startIdx.get._1) ==  start) startIdx.get._1 else  startIdx.get._2
158+           else 
159+             if (! unique &&  keepEnd &&  apply(startIdx.get._1) ==  start) startIdx.get._2 else  startIdx.get._1
160+           ,
161+           if (step >  0 )
162+             if (! unique &&  keepEnd &&  apply(endIdx.get._1) ==  end) startIdx.get._2 else  startIdx.get._1
163+           else 
164+             if (! unique &&  keepStart &&  apply(endIdx.get._1) ==  end) startIdx.get._1 else  startIdx.get._2
165+           ,
134166          step,
135-           left, right , round
167+           keepStart, keepEnd , round
136168        )
137169      }
138170  }
139171}
140172
141173object  IndexVectorLike  {
142174  def  empty [V ](implicit  ord : Ordering [V ], tag : ClassTag [V ])
143-   =  new  IndexVector [V ](Array [V ](),  true , false )(ord, tag)
175+   =  new  IndexVector [V ](Array .empty [V ],   true , true , false )(ord, tag)
144176}
0 commit comments