@@ -24,37 +24,37 @@ def resizableArray[T](capacity: Int): ResizableArray[T] = {
2424 ResizableArray(ref(0), ref(unsafeAllocate(capacity)))
2525}
2626
27- /// Aallocatellocate a new, empty dynamic array
27+ /// Aallocate a new, empty dynamic array
2828def resizableArray[T](): ResizableArray[T] = resizableArray(8)
2929
30- /// Panics if index is not a valid index into arr
31- def boundsCheck[T](arr: ResizableArray[T], index: Int): Unit = {
30+
31+ /// Throw an OutOfBounds exception if index is not a valid index into arr
32+ def boundsCheck[T](arr: ResizableArray[T], index: Int): Unit / Exception[OutOfBounds] =
3233 if (index < 0 || index >= arr.size) {
33- panic( "Array index out of bounds" )
34+ do raise(OutOfBounds(), "Array index out of bounds: " ++ show(index) )
3435 }
35- }
3636
3737
3838/// get the element at position index in the array
3939///
4040/// O(1)
41- def get[T](arr: ResizableArray[T], index: Int): T = {
41+ def get[T](arr: ResizableArray[T], index: Int): T / Exception[OutOfBounds] = {
4242 arr.boundsCheck(index);
4343 arr.rawContentPtr.get.get(index)
4444}
4545
4646/// set the element at position index in the array
4747///
4848/// O(1)
49- def set[T](arr: ResizableArray[T], index: Int, value: T): Unit = {
49+ def set[T](arr: ResizableArray[T], index: Int, value: T): Unit / Exception[OutOfBounds] = {
5050 arr.boundsCheck(index);
5151 arr.rawContentPtr.get.set(index, value)
5252}
5353
5454/// swap the elements at the given positions in the array
5555///
5656/// O(1)
57- def swap[T](arr: ResizableArray[T], index1: Int, index2: Int): Unit = {
57+ def swap[T](arr: ResizableArray[T], index1: Int, index2: Int): Unit / Exception[OutOfBounds] = {
5858 arr.boundsCheck(max(index1, index2))
5959 val raw = arr.rawContentPtr.get
6060 val tmp = raw.get(index1)
@@ -66,9 +66,9 @@ def swap[T](arr: ResizableArray[T], index1: Int, index2: Int): Unit = {
6666/// This only changes the size of the backing array, not the `size`.
6767///
6868/// O(n)
69- def setCapacity[T](arr: ResizableArray[T], capacity: Int): Unit = {
69+ def setCapacity[T](arr: ResizableArray[T], capacity: Int): Unit / Exception[OutOfBounds] = {
7070 if (arr.size > capacity) {
71- panic( "Cannot change capacity of ResizableArray." )
71+ do raise(OutOfBounds(), "Cannot change capacity of ResizableArray to " ++ capacity.show ++ " below size " ++ arr.size.show )
7272 }
7373 val oldRaw = arr.rawContentPtr.get
7474 if (oldRaw.size != capacity) {
@@ -81,7 +81,7 @@ def setCapacity[T](arr: ResizableArray[T], capacity: Int): Unit = {
8181/// If the shrinkThreshold is reached, shrink by growFactor, otherwise do nothing
8282///
8383/// O(n)
84- def maybeShrink[T](arr: ResizableArray[T]): Unit = {
84+ def maybeShrink[T](arr: ResizableArray[T]): Unit / Exception[OutOfBounds] = {
8585 if(arr.size.toDouble < arr.rawContentPtr.get.size.toDouble * shrinkThreshold) {
8686 val newCap = max(arr.size, (arr.rawContentPtr.get.size.toDouble / growFactor).ceil)
8787 arr.setCapacity(newCap)
@@ -91,7 +91,7 @@ def maybeShrink[T](arr: ResizableArray[T]): Unit = {
9191/// makes sure capacity is at least the given one
9292///
9393/// O(given capacity - current capacity) amortized, O(n) worst case // TODO ?
94- def ensureCapacity[T](arr: ResizableArray[T], capacity: Int): Unit = {
94+ def ensureCapacity[T](arr: ResizableArray[T], capacity: Int): Unit / Exception[OutOfBounds] = {
9595 if (arr.rawContentPtr.get.size < capacity) {
9696 val curCapd: Double = arr.rawContentPtr.get.size.toDouble
9797 val minGrowCapacity: Int = (curCapd * growFactor + 1.0).toInt
@@ -104,7 +104,13 @@ def ensureCapacity[T](arr: ResizableArray[T], capacity: Int): Unit = {
104104/// Note: New elements might be uninitialized!!!
105105///
106106/// O(max(1,index - n)) amortized, O(n) worst case if index > capacity
107- def setResizing[T](arr: ResizableArray[T], index: Int, value: T): Unit = {
107+ def setResizing[T](arr: ResizableArray[T], index: Int, value: T): Unit / Exception[OutOfBounds] = {
108+ if (index < 0) {
109+ do raise(OutOfBounds(), "Negative index " ++ index.show)
110+ }
111+ if (index < arr.size) {
112+ arr.rawContentPtr.get.set(index, value)
113+ }
108114 ensureCapacity(arr, index + 1)
109115 arr.rawContentPtr.get.set(index, value)
110116 if (index >= arr.size) arr.rawSizePtr.set(index + 1)
@@ -115,6 +121,7 @@ def setResizing[T](arr: ResizableArray[T], index: Int, value: T): Unit = {
115121///
116122/// O(1) amortized, O(n) worst case
117123def add[T](arr: ResizableArray[T], value: T): Int = {
124+ with on[OutOfBounds].panic();
118125 val idx = arr.size
119126 arr.setResizing(idx, value)
120127 idx
@@ -123,7 +130,7 @@ def add[T](arr: ResizableArray[T], value: T): Int = {
123130/// Remove and return the rightmost element in the resizable array.
124131///
125132/// O(1) amortized, O(n) worst case
126- def popRight[T](arr: ResizableArray[T]): T = {
133+ def popRight[T](arr: ResizableArray[T]): T / Exception[OutOfBounds] = {
127134 val last = arr.size - 1
128135 arr.boundsCheck(last)
129136 val r = arr.rawContentPtr.get.get(last)
@@ -187,7 +194,7 @@ def foreachReversed[T](arr: ResizableArray[T]){ body: T => Unit }: Unit = {
187194def toList[T](arr: ResizableArray[T]): List[T] = {
188195 def go(i: Int, acc: List[T]): List[T] = {
189196 if (i < 0) { acc } else {
190- go(i - 1, Cons(arr.get(i), acc))
197+ go(i - 1, Cons(arr.rawContentPtr.get. get(i), acc))
191198 }
192199 }
193200 go(arr.size - 1, Nil())
0 commit comments