Skip to content

Commit

Permalink
Use doc-comment syntax
Browse files Browse the repository at this point in the history
  • Loading branch information
marzipankaiser committed Nov 5, 2024
1 parent ea25548 commit 597bded
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 89 deletions.
32 changes: 16 additions & 16 deletions libraries/common/heap.effekt
Original file line number Diff line number Diff line change
@@ -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)

Expand Down Expand Up @@ -69,35 +69,35 @@ 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())
internal::sinkDown(heap, 0)
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
}
Expand Down
118 changes: 59 additions & 59 deletions libraries/common/resizable_array.effekt
Original file line number Diff line number Diff line change
Expand Up @@ -8,91 +8,91 @@ 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)
raw.unsafeSet(index1, raw.unsafeGet(index2))
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
Expand All @@ -103,29 +103,29 @@ 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)
}
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)
arr.unsafeSetCapacity(newCap)
}
}

// 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
Expand All @@ -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)
Expand All @@ -151,20 +151,20 @@ 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
arr.setResizing(idx, value)
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)
Expand Down
28 changes: 14 additions & 14 deletions libraries/common/union_find.effekt
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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)) {
Expand All @@ -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")
Expand All @@ -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)
Expand Down

0 comments on commit 597bded

Please sign in to comment.