Browse Source

Add to `core:slice` `reduce_reverse`, `filter_reverse`, `repeat`

gingerBill 1 year ago
parent
commit
04ca22b9ea
1 changed files with 42 additions and 3 deletions
  1. 42 3
      core/slice/slice.odin

+ 42 - 3
core/slice/slice.odin

@@ -444,14 +444,35 @@ reduce :: proc(s: $S/[]$U, initializer: $V, f: proc(V, U) -> V) -> V {
 }
 
 @(require_results)
-filter :: proc(s: $S/[]$U, f: proc(U) -> bool, allocator := context.allocator) -> S {
-	r := make([dynamic]U, 0, 0, allocator)
+reduce_reverse :: proc(s: $S/[]$U, initializer: $V, f: proc(V, U) -> V) -> V {
+	r := initializer
+	for i := len(s)-1; i >= 0; i -= 1 {
+		#no_bounds_check r = f(r, s[i])
+	}
+	return r
+}
+
+@(require_results)
+filter :: proc(s: $S/[]$U, f: proc(U) -> bool, allocator := context.allocator) -> (res: S, err: runtime.Allocator_Error) #optional_allocator_error {
+	r := make([dynamic]U, 0, 0, allocator) or_return
 	for v in s {
 		if f(v) {
 			append(&r, v)
 		}
 	}
-	return r[:]
+	return r[:], nil
+}
+
+@(require_results)
+filter_reverse :: proc(s: $S/[]$U, f: proc(U) -> bool, allocator := context.allocator) -> (res: S, err: runtime.Allocator_Error) #optional_allocator_error {
+	r := make([dynamic]U, 0, 0, allocator) or_return
+	for i := len(s)-1; i >= 0; i -= 1 {
+		#no_bounds_check v := s[i]
+		if f(v) {
+			append(&r, v)
+		}
+	}
+	return r[:], nil
 }
 
 @(require_results)
@@ -474,6 +495,24 @@ scanner :: proc (s: $S/[]$U, initializer: $V, f: proc(V, U) -> V, allocator := c
 }
 
 
+@(require_results)
+repeat :: proc(s: $S/[]$U, count: int, allocator := context.allocator) -> (b: S, err: runtime.Allocator_Error) #optional_allocator_error {
+	if count < 0 {
+		panic("slice: negative repeat count")
+	} else if count > 0 && (len(s)*count)/count != len(s) {
+		panic("slice: repeat count will cause an overflow")
+	}
+
+	b = make(S, len(s)*count, allocator) or_return
+	i := copy(b, s)
+	for i < len(b) { // 2^N trick to reduce the need to copy
+		copy(b[i:], b[:i])
+		i *= 2
+	}
+	return
+}
+
+
 @(require_results)
 min :: proc(s: $S/[]$T) -> (res: T, ok: bool) where intrinsics.type_is_ordered(T) #optional_ok {
 	if len(s) != 0 {