Skip to content

Commit

Permalink
Merge branch 'main' into hongbo/bigarray_equal
Browse files Browse the repository at this point in the history
  • Loading branch information
bobzhang authored Aug 31, 2024
2 parents 9f98d07 + c6e1617 commit a588f06
Show file tree
Hide file tree
Showing 10 changed files with 253 additions and 230 deletions.
4 changes: 2 additions & 2 deletions array/array_test.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -486,9 +486,9 @@ test "shuffle_in_place" {
inspect!(arr, content="[3, 2, 1, 5, 6, 7, 4]")
}

test "find_index" {
test "search_by" {
let arr : Array[Int] = [1, 2, 3, 4, 5, 6, 7]
let index = arr.find_index(fn(x) { x == 3 })
let index = arr.search_by(fn(x) { x == 3 })
assert_eq!(index, Some(2))
}

Expand Down
8 changes: 4 additions & 4 deletions array/fixedarray_sort.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -436,15 +436,15 @@ fn fixed_test_sort(f : (FixedArray[Int]) -> Unit) -> Unit! {
f(arr)
assert_eq!(arr, [1, 2, 3, 4, 5])
let arr = FixedArray::make(1000, 0)
for i = 0; i < 1000; i = i + 1 {
for i in 0..<1000 {
arr[i] = 1000 - i - 1
}
for i = 10; i < 1000; i = i + 10 {
arr.swap(i, i - 1)
}
f(arr)
let expected = FixedArray::make(1000, 0)
for i = 0; i < 1000; i = i + 1 {
for i in 0..<1000 {
expected[i] = i
}
assert_eq!(arr, expected)
Expand All @@ -471,15 +471,15 @@ test "stable_sort" {
arr.stable_sort()
assert_eq!(arr, [1, 2, 3, 4, 5])
let arr = FixedArray::make(1000, 0)
for i = 0; i < 1000; i = i + 1 {
for i in 0..<1000 {
arr[i] = 1000 - i - 1
}
for i = 10; i < 1000; i = i + 10 {
arr.swap(i, i - 1)
}
arr.stable_sort()
let expected = FixedArray::make(1000, 0)
for i = 0; i < 1000; i = i + 1 {
for i in 0..<1000 {
expected[i] = i
}
assert_eq!(arr, expected)
Expand Down
4 changes: 2 additions & 2 deletions array/fixedarray_test.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ test "FixedArray::from_array with non-empty array" {
let array : Array[Int] = [1, 2, 3, 4, 5]
let fixedArray = FixedArray::from_array(array)
assert_eq!(fixedArray.length(), 5)
for i = 0; i < 5; i = i + 1 {
for i in 0..<5 {
assert_eq!(fixedArray[i], array[i])
}
}
Expand All @@ -31,7 +31,7 @@ test "FixedArray::from_array with array of different type" {
let array : Array[String] = ["a", "b", "c"]
let fixedArray = FixedArray::from_array(array)
assert_eq!(fixedArray.length(), 3)
for i = 0; i < 3; i = i + 1 {
for i in 0..<3 {
assert_eq!(fixedArray[i], array[i])
}
}
Expand Down
4 changes: 2 additions & 2 deletions array/sort.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -234,15 +234,15 @@ fn test_sort(f : (Array[Int]) -> Unit) -> Unit! {
f(arr)
assert_eq!(arr, [1, 2, 3, 4, 5])
let arr = Array::new(capacity=1000)
for i = 0; i < 1000; i = i + 1 {
for i in 0..<1000 {
arr.push(1000 - i - 1)
}
for i = 10; i < 1000; i = i + 10 {
arr.swap(i, i - 1)
}
f(arr)
let expected = Array::new(capacity=1000)
for i = 0; i < 1000; i = i + 1 {
for i in 0..<1000 {
expected.push(i)
}
assert_eq!(arr, expected)
Expand Down
112 changes: 62 additions & 50 deletions builtin/array.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -227,10 +227,11 @@ pub fn drain[T](self : Array[T], begin : Int, end : Int) -> Array[T] {
/// let v2 = [6, 7, 8]
/// v1.append(v2)
/// ```
/// TODO: could be made more efficient
/// TODO: could be made more efficient doing direct mem.copy
pub fn append[T](self : Array[T], other : Array[T]) -> Unit {
for i = 0; i < other.length(); i = i + 1 {
self.push(other[i])
self.reserve_capacity(self.length() + other.length())
for v in other {
self.push(v)
}
}

Expand All @@ -246,8 +247,8 @@ pub fn append[T](self : Array[T], other : Array[T]) -> Unit {
/// v.each(fn (x) {sum = sum + x})
/// ```
pub fn each[T](self : Array[T], f : (T) -> Unit) -> Unit {
for i = 0; i < self.length(); i = i + 1 {
f(self[i])
for v in self {
f(v)
}
}

Expand All @@ -266,8 +267,8 @@ pub fn rev_each[T](self : Array[T], f : (T) -> Unit) -> Unit {
/// v.eachi(fn (i, x) {sum = sum + x + i})
/// ```
pub fn eachi[T](self : Array[T], f : (Int, T) -> Unit) -> Unit {
for i = 0; i < self.length(); i = i + 1 {
f(i, self[i])
for i, v in self {
f(i, v)
}
}

Expand Down Expand Up @@ -312,8 +313,8 @@ pub fn map[T, U](self : Array[T], f : (T) -> U) -> Array[U] {
return []
}
let arr = Array::make_uninit(self.length())
for i = 0; i < self.length(); i = i + 1 {
arr.buffer()[i] = f(self.buffer()[i])
for i, v in self {
arr.buffer()[i] = f(v)
}
arr
}
Expand All @@ -326,8 +327,8 @@ pub fn map[T, U](self : Array[T], f : (T) -> U) -> Array[U] {
/// v.map_inplace(fn (x) {x + 1})
/// ```
pub fn map_inplace[T](self : Array[T], f : (T) -> T) -> Unit {
for i = 0; i < self.length(); i = i + 1 {
self.buffer()[i] = f(self.buffer()[i])
for i, v in self {
self[i] = f(v)
}
}

Expand All @@ -343,8 +344,8 @@ pub fn mapi[T, U](self : Array[T], f : (Int, T) -> U) -> Array[U] {
return []
}
let arr = Array::make_uninit(self.length())
for i = 0; i < self.length(); i = i + 1 {
arr.buffer()[i] = f(i, self.buffer()[i])
for i, v in self {
arr.buffer()[i] = f(i, v)
}
arr
}
Expand All @@ -357,8 +358,8 @@ pub fn mapi[T, U](self : Array[T], f : (Int, T) -> U) -> Array[U] {
/// v.mapi_inplace(fn (i, x) {x + i})
/// ```
pub fn mapi_inplace[T](self : Array[T], f : (Int, T) -> T) -> Unit {
for i = 0; i < self.length(); i = i + 1 {
self[i] = f(i, self[i])
for i, v in self {
self[i] = f(i, v)
}
}

Expand All @@ -371,7 +372,11 @@ pub fn mapi_inplace[T](self : Array[T], f : (Int, T) -> T) -> Unit {
/// ```
pub fn filter[T](self : Array[T], f : (T) -> Bool) -> Array[T] {
let arr = []
self.each(fn(e) { if f(e) { arr.push(e) } })
for v in self {
if f(v) {
arr.push(v)
}
}
arr
}

Expand Down Expand Up @@ -466,8 +471,8 @@ pub fn split_at[T](self : Array[T], index : Int) -> (Array[T], Array[T]) {
/// v.contains(3)
/// ```
pub fn contains[T : Eq](self : Array[T], value : T) -> Bool {
for i = 0; i < self.length(); i = i + 1 {
if self.buffer()[i] == value {
for v in self {
if v == value {
break true
}
} else {
Expand Down Expand Up @@ -568,8 +573,34 @@ pub fn strip_suffix[T : Eq](self : Array[T], suffix : Array[T]) -> Array[T]? {
/// v.search(3)
/// ```
pub fn search[T : Eq](self : Array[T], value : T) -> Int? {
for i = 0; i < self.length(); i = i + 1 {
if self.buffer()[i] == value {
for i, v in self {
if v == value {
break Some(i)
}
} else {
None
}
}

/// @alert deprecated "Use `search_by` instead."
pub fn find_index[T](self : Array[T], f : (T) -> Bool) -> Int? {
search_by(self, f)
}

/// Search the index of the first element that satisfies the predicate.
//
/// # Example
///
/// ```
/// let v = [1, 2, 3, 4, 5]
/// match v.search_by(fn(x) { x == 3 }) {
/// Some(index) => println(index) // 2
/// None => println("Not found")
/// }
/// ```
pub fn search_by[T](self : Array[T], f : (T) -> Bool) -> Int? {
for i, v in self {
if f(v) {
break Some(i)
}
} else {
Expand Down Expand Up @@ -636,7 +667,7 @@ pub fn binary_search[T : Compare](
/// assert_eq!(result, Ok(0)) // The element 3 is found at index 0
/// ```
/// # Type Parameters
/// - `T`: The type of elements in the array. It must implement the `Eq` trait.
/// - `T`: The type of elements in the array.
///
/// # Arguments
/// - `self`: The array in which to perform the search.
Expand Down Expand Up @@ -730,13 +761,14 @@ pub fn remove[T](self : Array[T], index : Int) -> T {
/// ```
/// TODO: perf could be improved
pub fn retain[T](self : Array[T], f : (T) -> Bool) -> Unit {
let mut i = 0
while i < self.length() {
if f(self.buffer()[i]).not() {
self.remove(i) |> ignore
} else {
i = i + 1
for i = 0, j = 0; i < self.length(); {
if f(self.buffer()[i]) {
self.buffer()[j] = self.buffer()[i]
continue i + 1, j + 1
}
continue i + 1, j
} else {
self.set_length(j)
}
}

Expand Down Expand Up @@ -795,10 +827,11 @@ pub fn insert[T](self : Array[T], index : Int, value : T) -> Unit {
/// ```
/// [[3, 4], [5, 6]].flatten()
/// ```
/// TODO: perf could be improved by pre-allocated
pub fn flatten[T](self : Array[Array[T]]) -> Array[T] {
let v = []
for i = 0; i < self.length(); i = i + 1 {
v.append(self[i])
for arr in self {
v.append(arr)
}
v
}
Expand Down Expand Up @@ -1078,24 +1111,3 @@ pub fn shrink_to_fit[T](self : Array[T]) -> Unit {
pub fn to_string[T : Show](self : Array[T]) -> String {
Show::to_string(self)
}

/// Find the index of the first element that satisfies the predicate.
//
/// # Example
///
/// ```
/// let v = [1, 2, 3, 4, 5]
/// match v.find_index(fn(x) { x == 3 }) {
/// Some(index) => println(index) // 2
/// None => println("Not found")
/// }
/// ```
pub fn find_index[T](self : Array[T], f : (T) -> Bool) -> Int? {
for i = 0; i < self.length(); i = i + 1 {
if f(self[i]) {
break Some(i)
}
} else {
None
}
}
21 changes: 16 additions & 5 deletions builtin/array_test.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ test "array_from_fixed_array" {
test "array_make" {
let arr = Array::make(5, 42)
assert_eq!(arr.length(), 5)
for i = 0; i < 5; i = i + 1 {
for i in 0..<5 {
assert_eq!(arr[i], 42)
}
}
Expand Down Expand Up @@ -116,7 +116,16 @@ test "array_append" {
let arr2 = [4, 5, 6]
arr1.append(arr2)
assert_eq!(arr1.length(), 6)
// assert_eq!(arr1.capacity(), 6)
assert_eq!(arr1[3], 4)
let cap = 20
let arr3 = Array::new(capacity=cap)
arr3.resize(cap, 10)
arr1.append(arr3)
assert_eq!(arr1.length(), 6 + cap)
// assert_eq!(arr1.capacity(), arr1.length())
// Not testing capacity as it may be platform/algorithm
// dependent and not guaranteed to be equal to length
}

test "array_each" {
Expand Down Expand Up @@ -309,8 +318,10 @@ test "array_remove" {

test "array_retain" {
let arr = [1, 2, 3, 4, 5]
assert_eq!(arr.capacity(), 5)
arr.retain(fn(x) { x % 2 == 0 })
assert_eq!(arr.length(), 2)
assert_eq!(arr.capacity(), 5)
assert_eq!(arr[0], 2)
assert_eq!(arr[1], 4)
}
Expand Down Expand Up @@ -500,9 +511,9 @@ test "array_split" {
)
}

test "array_find_index" {
inspect!([1, 2, 3, 4, 5].find_index(fn(x) { x % 2 == 0 }), content="Some(1)")
inspect!([1, 2, 3, 4, 5].find_index(fn(x) { x > 5 }), content="None")
test "array_search_by" {
inspect!([1, 2, 3, 4, 5].search_by(fn(x) { x % 2 == 0 }), content="Some(1)")
inspect!([1, 2, 3, 4, 5].search_by(fn(x) { x > 5 }), content="None")
}

test "shrink_to_fit" {
Expand Down Expand Up @@ -556,7 +567,7 @@ test "array_binary_search_str_test" {

struct TestStruct {
num : Int
} derive(Eq)
}

test "array_binary_search_by_test" {
let arr = [{ num: 10 }, { num: 22 }, { num: 35 }, { num: 48 }]
Expand Down
12 changes: 6 additions & 6 deletions builtin/arraycore.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,11 @@ fn resize_buffer[T](self : Array[T], new_capacity : Int) -> Unit {
test "array_unsafe_blit_fixed" {
let src = FixedArray::make(5, 0)
let dst = UninitializedArray::make(5)
for i = 0; i < 5; i = i + 1 {
for i in 0..<5 {
src[i] = i + 1
}
UninitializedArray::unsafe_blit_fixed(dst, 0, src, 0, 5)
for i = 0; i < 5; i = i + 1 {
for i in 0..<5 {
assert_eq!(dst[i], src[i])
}
}
Expand All @@ -123,11 +123,11 @@ test "array_resize_buffer" {
test "UninitializedArray::unsafe_blit_fixed" {
let src = FixedArray::make(5, 0)
let dst = UninitializedArray::make(5)
for i = 0; i < 5; i = i + 1 {
for i in 0..<5 {
src[i] = i + 1
}
UninitializedArray::unsafe_blit_fixed(dst, 0, src, 0, 5)
for i = 0; i < 5; i = i + 1 {
for i in 0..<5 {
assert_eq!(dst[i], src[i])
}
}
Expand All @@ -150,11 +150,11 @@ test "Array::resize_buffer" {
test "UninitializedArray::unsafe_blit_fixed" {
let src = FixedArray::make(5, 0)
let dst = UninitializedArray::make(5)
for i = 0; i < 5; i = i + 1 {
for i in 0..<5 {
src[i] = i + 1
}
UninitializedArray::unsafe_blit_fixed(dst, 0, src, 0, 5)
for i = 0; i < 5; i = i + 1 {
for i in 0..<5 {
assert_eq!(dst[i], src[i])
}
}
Expand Down
Loading

0 comments on commit a588f06

Please sign in to comment.