diff --git a/libraries/common/heap.effekt b/libraries/common/heap.effekt index 2d69b30e9..3c5efb5db 100644 --- a/libraries/common/heap.effekt +++ b/libraries/common/heap.effekt @@ -1,15 +1,15 @@ module heap import resizable_array -// Resizable 2-ary min-heap, backed by a resizable array -// `cmp` defines the ordering of elements +/// Resizable 2-ary min-heap, backed by a resizable array +/// `cmp` defines the ordering of elements record Heap[T](rawContents: ResizableArray[T], cmp: (T, T) => Ordering at {}) -// Make a new Heap with the given comparison operation +/// Make a new Heap with the given comparison operation def heap[T](cmp: (T,T) => Ordering at {}) = Heap[T](resizableArray(), cmp) -// Make a new Heap with the given comparison operation and initial capacity +/// Make a new Heap with the given comparison operation and initial capacity def heap[T](cmp: (T,T) => Ordering at {}, capacity: Int) = Heap[T](resizableArray(capacity), cmp) @@ -69,25 +69,25 @@ namespace internal { } } -// Insert value into heap -// -// O(log n) worst case if capacity suffices, O(1) average +/// Insert value into heap +/// +/// O(log n) worst case if capacity suffices, O(1) average def insert[T](heap: Heap[T], value: T): Unit = { with on[OutOfBounds].panic(); val idx = heap.rawContents.add(value) internal::bubbleUp(heap, idx) } -// find and return (but not remove) the minimal element in this heap -// -// O(1) +/// find and return (but not remove) the minimal element in this heap +/// +/// O(1) def findMin[T](heap: Heap[T]): T / Exception[OutOfBounds] = { heap.rawContents.get(0) } -// find and remove the minimal element in this heap -// -// O(log n) +/// find and remove the minimal element in this heap +/// +/// O(log n) def deleteMin[T](heap: Heap[T]): T / Exception[OutOfBounds] = { val res = heap.rawContents.get(0) heap.rawContents.unsafeSet(0, heap.rawContents.popRight()) @@ -95,9 +95,9 @@ def deleteMin[T](heap: Heap[T]): T / Exception[OutOfBounds] = { res } -// Number of elements in the heap -// -// O(1) +/// Number of elements in the heap +/// +/// O(1) def size[T](heap: Heap[T]): Int = { heap.rawContents.size } diff --git a/libraries/common/resizable_array.effekt b/libraries/common/resizable_array.effekt index 1d50663b3..ebea29a83 100644 --- a/libraries/common/resizable_array.effekt +++ b/libraries/common/resizable_array.effekt @@ -8,71 +8,71 @@ record ResizableArray[T](rawSizePtr: Ref[Int], rawContentPtr: Ref[Array[T]]) // These numbers should be optimized based on benchmarking // According to https://en.wikipedia.org/wiki/Dynamic_array most use 1.5 or 2 -// -// Factor by which to grow the capacity when it becomes too small + +/// Factor by which to grow the capacity when it becomes too small val growFactor = 1.5 -// shrink array when size / capacity falls below this threshold -// should be < 1/growFactor +/// shrink array when size / capacity falls below this threshold +/// should be < 1/growFactor val shrinkThreshold = 0.4 -// Number of elements in the dynamic array -// -// O(1) +/// Number of elements in the dynamic array +/// +/// O(1) def size[T](arr: ResizableArray[T]) = arr.rawSizePtr.get -// Allocate a new, empty dynamic array with given initial capacity +/// Allocate a new, empty dynamic array with given initial capacity def resizableArray[T](capacity: Int): ResizableArray[T] = { ResizableArray(ref(0), ref(allocate(capacity))) } -// Allocate a new, empty dynamic array +/// Allocate a new, empty dynamic array def resizableArray[T](): ResizableArray[T] = resizableArray(8) -// Throw an OutOfBounds exception if index is not a valid index into arr +/// Throw an OutOfBounds exception if index is not a valid index into arr def boundsCheck[T](arr: ResizableArray[T], index: Int): Unit / Exception[OutOfBounds] = { if (index < 0 && index >= arr.size) { do raise(OutOfBounds(), "Array index out of bounds: " ++ show(index)) } } -// get the element at position index in the array -// -// precondition: index is a valid index into the array -// -// O(1) +/// get the element at position index in the array +/// +/// precondition: index is a valid index into the array +/// +/// O(1) def unsafeGet[T](arr: ResizableArray[T], index: Int): T = { arr.rawContentPtr.get.unsafeGet(index) } -// get the element at position index in the array -// -// O(1) +/// get the element at position index in the array +/// +/// O(1) def get[T](arr: ResizableArray[T], index: Int): T / Exception[OutOfBounds] = { arr.boundsCheck(index); arr.unsafeGet(index) } -// set the element at position index in the array -// -// precondition: index is a valid index into the array -// -// O(1) +/// set the element at position index in the array +/// +/// precondition: index is a valid index into the array +/// +/// O(1) def unsafeSet[T](arr: ResizableArray[T], index: Int, value: T): Unit = { arr.rawContentPtr.get.unsafeSet(index, value) } -// set the element at position index in the array -// -// O(1) +/// set the element at position index in the array +/// +/// O(1) def set[T](arr: ResizableArray[T], index: Int, value: T): Unit / Exception[OutOfBounds] = { arr.boundsCheck(index); arr.unsafeSet(index, value) } -// swap the elements at the given positions in the array -// -// precondition: both are valid indices into the array -// -// O(1) +/// swap the elements at the given positions in the array +/// +/// precondition: both are valid indices into the array +/// +/// O(1) def unsafeSwap[T](arr: ResizableArray[T], index1: Int, index2: Int): Unit = { val raw = arr.rawContentPtr.get val tmp = raw.unsafeGet(index1) @@ -80,19 +80,19 @@ def unsafeSwap[T](arr: ResizableArray[T], index1: Int, index2: Int): Unit = { raw.unsafeSet(index2, tmp) } -// swap the elements at the given positions in the array -// -// O(1) +/// swap the elements at the given positions in the array +/// +/// O(1) def swap[T](arr: ResizableArray[T], index1: Int, index2: Int): Unit / Exception[OutOfBounds] = { arr.boundsCheck(max(index1, index2)) arr.unsafeSwap(index1, index2) } -// Change the dynamic to have exactly the given capacity -// -// precondition: given capacity is at least the size of the array -// -// O(n) +/// Change the dynamic to have exactly the given capacity +/// +/// precondition: given capacity is at least the size of the array +/// +/// O(n) def unsafeSetCapacity[T](arr: ResizableArray[T], capacity: Int): Unit = { with on[OutOfBounds].panic val oldRaw = arr.rawContentPtr.get @@ -103,9 +103,9 @@ def unsafeSetCapacity[T](arr: ResizableArray[T], capacity: Int): Unit = { } } -// Change the dynamic to have exactly the given capacity -// -// O(n) +/// Change the dynamic to have exactly the given capacity +/// +/// O(n) def setCapacity[T](arr: ResizableArray[T], capacity: Int): Unit / Exception[OutOfBounds] = { if (arr.size > capacity) { do raise(OutOfBounds(), "Cannot change capacity of ResizableArray to " ++ capacity.show ++ " below size " ++ arr.size.show) @@ -113,9 +113,9 @@ def setCapacity[T](arr: ResizableArray[T], capacity: Int): Unit / Exception[OutO arr.unsafeSetCapacity(capacity) } -// If the shrinkThreshold is reached, shrink by growFactor, otherwise do nothing -// -// O(n) +/// If the shrinkThreshold is reached, shrink by growFactor, otherwise do nothing +/// +/// O(n) def maybeShrink[T](arr: ResizableArray[T]): Unit = { if(arr.size.toDouble < arr.rawContentPtr.get.size.toDouble * shrinkThreshold) { val newCap = max(arr.size, (arr.rawContentPtr.get.size.toDouble / growFactor).ceil) @@ -123,9 +123,9 @@ def maybeShrink[T](arr: ResizableArray[T]): Unit = { } } -// makes sure capacity is at least the given one -// -// O(given capacity - current capacity) amortized, O(n) worst case // TODO ? +/// makes sure capacity is at least the given one +/// +/// O(given capacity - current capacity) amortized, O(n) worst case // TODO ? def ensureCapacity[T](arr: ResizableArray[T], capacity: Int): Unit / Exception[OutOfBounds] = { if (arr.rawContentPtr.get.size < capacity) { val curCapd: Double = arr.rawContentPtr.get.size.toDouble @@ -135,10 +135,10 @@ def ensureCapacity[T](arr: ResizableArray[T], capacity: Int): Unit / Exception[O } } -// Set the value at given position, resizing if necessary -// Note: New elements might be uninitialized!!! -// -// O(max(1,index - n)) amortized, O(n) worst case if index > capacity +/// Set the value at given position, resizing if necessary +/// Note: New elements might be uninitialized!!! +/// +/// O(max(1,index - n)) amortized, O(n) worst case if index > capacity def setResizing[T](arr: ResizableArray[T], index: Int, value: T): Unit / Exception[OutOfBounds] = { if (index < 0) { do raise(OutOfBounds(), "Negative index " ++ index.show) @@ -151,10 +151,10 @@ def setResizing[T](arr: ResizableArray[T], index: Int, value: T): Unit / Excepti arr.rawSizePtr.set(index + 1) } -// Add a new element at the end of the resizable array. -// Return the index of the new element -// -// O(1) amortized, O(n) worst case +/// Add a new element at the end of the resizable array. +/// Return the index of the new element +/// +/// O(1) amortized, O(n) worst case def add[T](arr: ResizableArray[T], value: T): Int = { with on[OutOfBounds].panic(); val idx = arr.size @@ -162,9 +162,9 @@ def add[T](arr: ResizableArray[T], value: T): Int = { idx } -// Remove and return the rightmost element in the resizable array. -// -// O(1) amortized, O(n) worst case +/// Remove and return the rightmost element in the resizable array. +/// +/// O(1) amortized, O(n) worst case def popRight[T](arr: ResizableArray[T]): T / Exception[OutOfBounds] = { arr.boundsCheck(arr.size - 1) arr.rawSizePtr.set(arr.size - 1) diff --git a/libraries/common/union_find.effekt b/libraries/common/union_find.effekt index f0423110a..1e8baf9f8 100644 --- a/libraries/common/union_find.effekt +++ b/libraries/common/union_find.effekt @@ -2,8 +2,8 @@ module union_find import resizable_array import test -// Classic mutable union-find datastructur on integer indices, -// with union-by-rank and path compression. +/// Classic mutable union-find data structure on integer indices, +/// with union-by-rank and path compression. record UnionFind(rawElements: ResizableArray[Int]) namespace internal { @@ -47,16 +47,16 @@ def unionFind(): UnionFind = def unionFind(capacity: Int): UnionFind = UnionFind(resizableArray(capacity)) -// Make a new set in the union-find datastructure and return its index -// -// O(1) amortized, worst-case O(n) if the capacity does not suffice +/// Make a new set in the union-find datastructure and return its index +/// +/// O(1) amortized, worst-case O(n) if the capacity does not suffice def makeSet(u: UnionFind): Int = { u.rawElements.add(-1) } -// Find the representative of the given element. -// -// O(inverse-ackermann(n)) amortized +/// Find the representative of the given element. +/// +/// O(inverse-ackermann(n)) amortized def find(u: UnionFind, s: Int): Int / Exception[MissingValue] = { def goFind(s: Int): Int = { if (u.internal::isRoot(s)) { @@ -79,9 +79,9 @@ def find(u: UnionFind, s: Int): Int / Exception[MissingValue] = { root } -// Make it such that the sets *represented by* x and y are merged -// -// O(1) +/// Make it such that the sets *represented by* x and y are merged +/// +/// O(1) def unionRoots(u: UnionFind, x: Int, y: Int): Int / Exception[MissingValue] = { if(not(u.internal::isRoot(x) && u.internal::isRoot(y))) { panic("unionRoots should only be called on representatives") @@ -104,9 +104,9 @@ def unionRoots(u: UnionFind, x: Int, y: Int): Int / Exception[MissingValue] = { } } -// Make it so a and b are in the same set -// -// O(inverse-ackermann(n)) amortized +/// Make it so a and b are in the same set +/// +/// O(inverse-ackermann(n)) amortized def union(u: UnionFind, a: Int, b: Int): Int / Exception[MissingValue] = { val x = u.find(a) val y = u.find(b)