slice.odin 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925
  1. // Utility procedures for working with slices, including sorting and searching them.
  2. package slice
  3. import "base:intrinsics"
  4. import "base:builtin"
  5. import "core:math/bits"
  6. import "base:runtime"
  7. _ :: intrinsics
  8. _ :: builtin
  9. _ :: bits
  10. _ :: runtime
  11. /*
  12. Turn a pointer and a length into a slice.
  13. */
  14. @(require_results)
  15. from_ptr :: proc "contextless" (ptr: ^$T, count: int) -> []T {
  16. return ([^]T)(ptr)[:count]
  17. }
  18. /*
  19. Turn a pointer and a length into a byte slice.
  20. */
  21. @(require_results)
  22. bytes_from_ptr :: proc "contextless" (ptr: rawptr, byte_count: int) -> []byte {
  23. return ([^]byte)(ptr)[:byte_count]
  24. }
  25. /*
  26. Turn a slice into a byte slice.
  27. See `slice.reinterpret` to go the other way.
  28. */
  29. @(require_results)
  30. to_bytes :: proc "contextless" (s: []$T) -> []byte {
  31. return ([^]byte)(raw_data(s))[:len(s) * size_of(T)]
  32. }
  33. /*
  34. Turns a byte slice into a type.
  35. */
  36. @(require_results)
  37. to_type :: proc(buf: []u8, $T: typeid) -> (T, bool) #optional_ok {
  38. if len(buf) < size_of(T) {
  39. return {}, false
  40. }
  41. return intrinsics.unaligned_load((^T)(raw_data(buf))), true
  42. }
  43. /*
  44. Turn a slice of one type, into a slice of another type.
  45. Only converts the type and length of the slice itself.
  46. The length is rounded down to the nearest whole number of items.
  47. Example:
  48. import "core:fmt"
  49. import "core:slice"
  50. i64s_as_i32s :: proc() {
  51. large_items := []i64{1, 2, 3, 4}
  52. small_items := slice.reinterpret([]i32, large_items)
  53. assert(len(small_items) == 8)
  54. fmt.println(large_items, "->", small_items)
  55. }
  56. bytes_as_i64s :: proc() {
  57. small_items := [12]byte{}
  58. small_items[0] = 1
  59. small_items[8] = 2
  60. large_items := slice.reinterpret([]i64, small_items[:])
  61. assert(len(large_items) == 1) // only enough bytes to make 1 x i64; two would need at least 8 bytes.
  62. fmt.println(small_items, "->", large_items)
  63. }
  64. reinterpret_example :: proc() {
  65. i64s_as_i32s()
  66. bytes_as_i64s()
  67. }
  68. Output:
  69. [1, 2, 3, 4] -> [1, 0, 2, 0, 3, 0, 4, 0]
  70. [1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0] -> [1]
  71. */
  72. @(require_results)
  73. reinterpret :: proc "contextless" ($T: typeid/[]$U, s: []$V) -> []U {
  74. when size_of(U) == 0 || size_of(V) == 0 {
  75. return nil
  76. } else {
  77. bytes := to_bytes(s)
  78. n := len(bytes) / size_of(U)
  79. return ([^]U)(raw_data(bytes))[:n]
  80. }
  81. }
  82. swap :: proc(array: $T/[]$E, a, b: int) {
  83. when size_of(E) > 8 {
  84. ptr_swap_non_overlapping(&array[a], &array[b], size_of(E))
  85. } else {
  86. array[a], array[b] = array[b], array[a]
  87. }
  88. }
  89. swap_between :: proc(a, b: $T/[]$E) {
  90. n := builtin.min(len(a), len(b))
  91. if n >= 0 {
  92. ptr_swap_overlapping(&a[0], &b[0], size_of(E)*n)
  93. }
  94. }
  95. reverse :: proc(array: $T/[]$E) {
  96. n := len(array)/2
  97. for i in 0..<n {
  98. swap(array, i, len(array)-i-1)
  99. }
  100. }
  101. @(require_results)
  102. contains :: proc(array: $T/[]$E, value: E) -> bool where intrinsics.type_is_comparable(E) {
  103. _, found := linear_search(array, value)
  104. return found
  105. }
  106. /*
  107. Searches the given slice for the given element in O(n) time.
  108. If you need a custom search condition, see `linear_search_proc`
  109. Inputs:
  110. - array: The slice to search in.
  111. - key: The element to search for.
  112. Returns:
  113. - index: The index `i`, such that `array[i]` is the first occurrence of `key` in `array`, or -1 if `key` is not present in `array`.
  114. Example:
  115. index: int
  116. found: bool
  117. a := []i32{10, 10, 10, 20}
  118. index, found = linear_search_reverse(a, 10)
  119. assert(index == 0 && found == true)
  120. index, found = linear_search_reverse(a, 30)
  121. assert(index == -1 && found == false)
  122. // Note that `index == 1`, since it is relative to `a[2:]`
  123. index, found = linear_search_reverse(a[2:], 20)
  124. assert(index == 1 && found == true)
  125. */
  126. @(require_results)
  127. linear_search :: proc(array: $A/[]$T, key: T) -> (index: int, found: bool)
  128. where intrinsics.type_is_comparable(T) {
  129. for x, i in array {
  130. if x == key {
  131. return i, true
  132. }
  133. }
  134. return -1, false
  135. }
  136. /*
  137. Searches the given slice for the first element satisfying predicate `f` in O(n) time.
  138. Inputs:
  139. - array: The slice to search in.
  140. - f: The search condition.
  141. Returns:
  142. - index: The index `i`, such that `array[i]` is the first `x` in `array` for which `f(x) == true`, or -1 if such `x` does not exist.
  143. */
  144. @(require_results)
  145. linear_search_proc :: proc(array: $A/[]$T, f: proc(T) -> bool) -> (index: int, found: bool) {
  146. for x, i in array {
  147. if f(x) {
  148. return i, true
  149. }
  150. }
  151. return -1, false
  152. }
  153. /*
  154. Searches the given slice for the given element in O(n) time, starting from the
  155. slice end.
  156. If you need a custom search condition, see `linear_search_reverse_proc`
  157. Inputs:
  158. - array: The slice to search in.
  159. - key: The element to search for.
  160. Returns:
  161. - index: The index `i`, such that `array[i]` is the last occurrence of `key` in `array`, or -1 if `key` is not present in `array`.
  162. Example:
  163. index: int
  164. found: bool
  165. a := []i32{10, 10, 10, 20}
  166. index, found = linear_search_reverse(a, 20)
  167. assert(index == 3 && found == true)
  168. index, found = linear_search_reverse(a, 10)
  169. assert(index == 2 && found == true)
  170. index, found = linear_search_reverse(a, 30)
  171. assert(index == -1 && found == false)
  172. // Note that `index == 1`, since it is relative to `a[2:]`
  173. index, found = linear_search_reverse(a[2:], 20)
  174. assert(index == 1 && found == true)
  175. */
  176. @(require_results)
  177. linear_search_reverse :: proc(array: $A/[]$T, key: T) -> (index: int, found: bool)
  178. where intrinsics.type_is_comparable(T) {
  179. #reverse for x, i in array {
  180. if x == key {
  181. return i, true
  182. }
  183. }
  184. return -1, false
  185. }
  186. /*
  187. Searches the given slice for the last element satisfying predicate `f` in O(n)
  188. time, starting from the slice end.
  189. Inputs:
  190. - array: The slice to search in.
  191. - f: The search condition.
  192. Returns:
  193. - index: The index `i`, such that `array[i]` is the last `x` in `array` for which `f(x) == true`, or -1 if such `x` does not exist.
  194. */
  195. @(require_results)
  196. linear_search_reverse_proc :: proc(array: $A/[]$T, f: proc(T) -> bool) -> (index: int, found: bool) {
  197. #reverse for x, i in array {
  198. if f(x) {
  199. return i, true
  200. }
  201. }
  202. return -1, false
  203. }
  204. /*
  205. Searches the given slice for the given element.
  206. If the slice is not sorted, the returned index is unspecified and meaningless.
  207. If the value is found then the returned int is the index of the matching element.
  208. If there are multiple matches, then any one of the matches could be returned.
  209. If the value is not found then the returned int is the index where a matching
  210. element could be inserted while maintaining sorted order.
  211. For slices of more complex types see: `binary_search_by`
  212. Example:
  213. /*
  214. Looks up a series of four elements. The first is found, with a
  215. uniquely determined position; the second and third are not
  216. found; the fourth could match any position in `[1, 4]`.
  217. */
  218. index: int
  219. found: bool
  220. s := []i32{0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55}
  221. index, found = slice.binary_search(s, 13)
  222. assert(index == 9 && found == true)
  223. index, found = slice.binary_search(s, 4)
  224. assert(index == 7 && found == false)
  225. index, found = slice.binary_search(s, 100)
  226. assert(index == 13 && found == false)
  227. index, found = slice.binary_search(s, 1)
  228. assert(index >= 1 && index <= 4 && found == true)
  229. */
  230. @(require_results)
  231. binary_search :: proc(array: $A/[]$T, key: T) -> (index: int, found: bool)
  232. where intrinsics.type_is_ordered(T) #no_bounds_check {
  233. return binary_search_by(array, key, cmp_proc(T))
  234. }
  235. /*
  236. Searches the given slice for the given element.
  237. If the slice is not sorted, the returned index is unspecified and meaningless.
  238. If the value is found then the returned int is the index of the matching element.
  239. If there are multiple matches, then any one of the matches could be returned.
  240. If the value is not found then the returned int is the index where a matching
  241. element could be inserted while maintaining sorted order.
  242. The array elements and key may be different types. This allows the filter procedure
  243. to compare keys against a slice of structs, one struct value at a time.
  244. Returns:
  245. - index: int
  246. - found: bool
  247. */
  248. @(require_results)
  249. binary_search_by :: proc(array: $A/[]$T, key: $K, f: proc(T, K) -> Ordering) -> (index: int, found: bool) #no_bounds_check {
  250. n := len(array)
  251. left, right := 0, n
  252. for left < right {
  253. mid := int(uint(left+right) >> 1)
  254. if f(array[mid], key) == .Less {
  255. left = mid+1
  256. } else {
  257. // .Equal or .Greater
  258. right = mid
  259. }
  260. }
  261. return left, left < n && f(array[left], key) == .Equal
  262. }
  263. @(require_results)
  264. equal :: proc(a, b: $T/[]$E) -> bool where intrinsics.type_is_comparable(E) #no_bounds_check {
  265. if len(a) != len(b) {
  266. return false
  267. }
  268. when intrinsics.type_is_simple_compare(E) {
  269. if len(a) == 0 {
  270. // Empty slices are always equivalent to each other.
  271. //
  272. // This check is here in the event that a slice with a `data` of
  273. // nil is compared against a slice with a non-nil `data` but a
  274. // length of zero.
  275. //
  276. // In that case, `memory_compare` would return -1 or +1 because one
  277. // of the pointers is nil.
  278. return true
  279. }
  280. return runtime.memory_compare(raw_data(a), raw_data(b), len(a)*size_of(E)) == 0
  281. } else {
  282. for i in 0..<len(a) {
  283. if a[i] != b[i] {
  284. return false
  285. }
  286. }
  287. return true
  288. }
  289. }
  290. @(require_results)
  291. simple_equal :: proc(a, b: $T/[]$E) -> bool where intrinsics.type_is_simple_compare(E) {
  292. if len(a) != len(b) {
  293. return false
  294. }
  295. return runtime.memory_compare(raw_data(a), raw_data(b), len(a)*size_of(E)) == 0
  296. }
  297. /*
  298. return the prefix length common between slices `a` and `b`.
  299. slice.prefix_length([]u8{1, 2, 3, 4}, []u8{1}) -> 1
  300. slice.prefix_length([]u8{1, 2, 3, 4}, []u8{1, 2, 3}) -> 3
  301. slice.prefix_length([]u8{1, 2, 3, 4}, []u8{2, 3, 4}) -> 0
  302. */
  303. @(require_results)
  304. prefix_length :: proc(a, b: $T/[]$E) -> (n: int) where intrinsics.type_is_comparable(E) {
  305. _len := builtin.min(len(a), len(b))
  306. #no_bounds_check for n < _len && a[n] == b[n] {
  307. n += 1
  308. }
  309. return
  310. }
  311. @(require_results)
  312. has_prefix :: proc(array: $T/[]$E, needle: T) -> bool where intrinsics.type_is_comparable(E) {
  313. n := len(needle)
  314. if len(array) >= n {
  315. return equal(array[:n], needle)
  316. }
  317. return false
  318. }
  319. /*
  320. return the suffix length common between slices `a` and `b`.
  321. slice.suffix_length([]u8{1, 2, 3, 4}, []u8{1, 2, 3, 4}) -> 4
  322. slice.suffix_length([]u8{1, 2, 3, 4}, []u8{3, 4}) -> 2
  323. slice.suffix_length([]u8{1, 2, 3, 4}, []u8{1}) -> 0
  324. slice.suffix_length([]u8{1, 2, 3, 4}, []u8{1, 3, 5}) -> 0
  325. slice.suffix_length([]u8{3, 4, 5}, []u8{3, 5}) -> 1
  326. */
  327. @(require_results)
  328. suffix_length :: proc(a, b: $T/[]$E) -> (n: int) where intrinsics.type_is_comparable(E) {
  329. len_a, len_b := len(a), len(b)
  330. _len := builtin.min(len_a, len_b)
  331. #no_bounds_check for i := 1; i <= _len && a[len_a - i] == b[len_b - i]; i += 1 {
  332. n += 1
  333. }
  334. return
  335. }
  336. @(require_results)
  337. has_suffix :: proc(array: $T/[]$E, needle: T) -> bool where intrinsics.type_is_comparable(E) {
  338. array := array
  339. m, n := len(array), len(needle)
  340. if m >= n {
  341. return equal(array[m-n:], needle)
  342. }
  343. return false
  344. }
  345. zero :: proc(array: $T/[]$E) #no_bounds_check {
  346. if len(array) > 0 {
  347. intrinsics.mem_zero(raw_data(array), size_of(E)*len(array))
  348. }
  349. }
  350. fill :: proc(array: $T/[]$E, value: E) #no_bounds_check {
  351. if len(array) <= 0 {
  352. return
  353. }
  354. array[0] = value
  355. for i := 1; i < len(array); i *= 2 {
  356. copy(array[i:], array[:i])
  357. }
  358. }
  359. rotate_left :: proc(array: $T/[]$E, mid: int) {
  360. n := len(array)
  361. m := mid %% n
  362. k := n - m
  363. // FIXME: (ap29600) this cast is a temporary fix for the compiler not matching
  364. // [^T] with $P/^$T
  365. p := cast(^E)raw_data(array)
  366. ptr_rotate(m, ptr_add(p, m), k)
  367. }
  368. rotate_right :: proc(array: $T/[]$E, k: int) {
  369. rotate_left(array, -k)
  370. }
  371. swap_with_slice :: proc(a, b: $T/[]$E, loc := #caller_location) {
  372. assert(len(a) == len(b), "miss matching slice lengths", loc)
  373. ptr_swap_non_overlapping(raw_data(a), raw_data(b), len(a)*size_of(E))
  374. }
  375. @(require_results)
  376. concatenate :: proc(a: []$T/[]$E, allocator := context.allocator) -> (res: T, err: runtime.Allocator_Error) #optional_allocator_error {
  377. if len(a) == 0 {
  378. return
  379. }
  380. n := 0
  381. for s in a {
  382. n += len(s)
  383. }
  384. res = make(T, n, allocator) or_return
  385. i := 0
  386. for s in a {
  387. i += copy(res[i:], s)
  388. }
  389. return
  390. }
  391. // copies a slice into a new slice
  392. @(require_results)
  393. clone :: proc(a: $T/[]$E, allocator := context.allocator, loc := #caller_location) -> ([]E, runtime.Allocator_Error) #optional_allocator_error {
  394. d, err := make([]E, len(a), allocator, loc)
  395. copy(d[:], a)
  396. return d, err
  397. }
  398. // copies slice into a new dynamic array
  399. clone_to_dynamic :: proc(a: $T/[]$E, allocator := context.allocator, loc := #caller_location) -> ([dynamic]E, runtime.Allocator_Error) #optional_allocator_error {
  400. d, err := make([dynamic]E, len(a), allocator, loc)
  401. copy(d[:], a)
  402. return d, err
  403. }
  404. to_dynamic :: clone_to_dynamic
  405. // Converts slice into a dynamic array without cloning or allocating memory
  406. @(require_results)
  407. into_dynamic :: proc(a: $T/[]$E) -> [dynamic]E {
  408. s := transmute(runtime.Raw_Slice)a
  409. d := runtime.Raw_Dynamic_Array{
  410. data = s.data,
  411. len = 0,
  412. cap = s.len,
  413. allocator = runtime.nil_allocator(),
  414. }
  415. return transmute([dynamic]E)d
  416. }
  417. @(require_results)
  418. length :: proc(a: $T/[]$E) -> int {
  419. return len(a)
  420. }
  421. @(require_results)
  422. is_empty :: proc(a: $T/[]$E) -> bool {
  423. return len(a) == 0
  424. }
  425. // Gets the byte size of the backing data
  426. @(require_results)
  427. size :: proc "contextless" (a: $T/[]$E) -> int {
  428. return len(a) * size_of(E)
  429. }
  430. @(require_results)
  431. split_at :: proc(array: $T/[]$E, index: int) -> (a, b: T) {
  432. return array[:index], array[index:]
  433. }
  434. @(require_results)
  435. split_first :: proc(array: $T/[]$E) -> (first: E, rest: T) {
  436. return array[0], array[1:]
  437. }
  438. @(require_results)
  439. split_last :: proc(array: $T/[]$E) -> (rest: T, last: E) {
  440. n := len(array)-1
  441. return array[:n], array[n]
  442. }
  443. @(require_results)
  444. first :: proc(array: $T/[]$E) -> E {
  445. return array[0]
  446. }
  447. @(require_results)
  448. last :: proc(array: $T/[]$E) -> E {
  449. return array[len(array)-1]
  450. }
  451. @(require_results)
  452. first_ptr :: proc(array: $T/[]$E) -> ^E {
  453. if len(array) != 0 {
  454. return &array[0]
  455. }
  456. return nil
  457. }
  458. @(require_results)
  459. last_ptr :: proc(array: $T/[]$E) -> ^E {
  460. if len(array) != 0 {
  461. return &array[len(array)-1]
  462. }
  463. return nil
  464. }
  465. @(require_results)
  466. get :: proc(array: $T/[]$E, index: int) -> (value: E, ok: bool) {
  467. if uint(index) < len(array) {
  468. value = array[index]
  469. ok = true
  470. }
  471. return
  472. }
  473. @(require_results)
  474. get_ptr :: proc(array: $T/[]$E, index: int) -> (value: ^E, ok: bool) {
  475. if uint(index) < len(array) {
  476. value = &array[index]
  477. ok = true
  478. }
  479. return
  480. }
  481. @(require_results)
  482. as_ptr :: proc(array: $T/[]$E) -> [^]E {
  483. return raw_data(array)
  484. }
  485. @(require_results)
  486. mapper :: proc(s: $S/[]$U, f: proc(U) -> $V, allocator := context.allocator) -> (r: []V, err: runtime.Allocator_Error) #optional_allocator_error {
  487. r = make([]V, len(s), allocator) or_return
  488. for v, i in s {
  489. r[i] = f(v)
  490. }
  491. return
  492. }
  493. @(require_results)
  494. reduce :: proc(s: $S/[]$U, initializer: $V, f: proc(V, U) -> V) -> V {
  495. r := initializer
  496. for v in s {
  497. r = f(r, v)
  498. }
  499. return r
  500. }
  501. @(require_results)
  502. reduce_reverse :: proc(s: $S/[]$U, initializer: $V, f: proc(V, U) -> V) -> V {
  503. r := initializer
  504. for i := len(s)-1; i >= 0; i -= 1 {
  505. #no_bounds_check r = f(r, s[i])
  506. }
  507. return r
  508. }
  509. @(require_results)
  510. filter :: proc(s: $S/[]$U, f: proc(U) -> bool, allocator := context.allocator) -> (res: S, err: runtime.Allocator_Error) #optional_allocator_error {
  511. r := make([dynamic]U, 0, 0, allocator) or_return
  512. for v in s {
  513. if f(v) {
  514. append(&r, v)
  515. }
  516. }
  517. return r[:], nil
  518. }
  519. @(require_results)
  520. filter_reverse :: proc(s: $S/[]$U, f: proc(U) -> bool, allocator := context.allocator) -> (res: S, err: runtime.Allocator_Error) #optional_allocator_error {
  521. r := make([dynamic]U, 0, 0, allocator) or_return
  522. for i := len(s)-1; i >= 0; i -= 1 {
  523. #no_bounds_check v := s[i]
  524. if f(v) {
  525. append(&r, v)
  526. }
  527. }
  528. return r[:], nil
  529. }
  530. @(require_results)
  531. scanner :: proc (s: $S/[]$U, initializer: $V, f: proc(V, U) -> V, allocator := context.allocator) -> (res: []V, err: runtime.Allocator_Error) #optional_allocator_error {
  532. if len(s) == 0 { return }
  533. res = make([]V, len(s), allocator) or_return
  534. p := as_ptr(s)
  535. q := as_ptr(res)
  536. r := initializer
  537. for l := len(s); l > 0; l -= 1 {
  538. r = f(r, p[0])
  539. q[0] = r
  540. p = p[1:]
  541. q = q[1:]
  542. }
  543. return
  544. }
  545. @(require_results)
  546. repeat :: proc(s: $S/[]$U, count: int, allocator := context.allocator) -> (b: S, err: runtime.Allocator_Error) #optional_allocator_error {
  547. if count < 0 {
  548. panic("slice: negative repeat count")
  549. } else if count > 0 && (len(s)*count)/count != len(s) {
  550. panic("slice: repeat count will cause an overflow")
  551. }
  552. b = make(S, len(s)*count, allocator) or_return
  553. i := copy(b, s)
  554. for i < len(b) { // 2^N trick to reduce the need to copy
  555. copy(b[i:], b[:i])
  556. i *= 2
  557. }
  558. return
  559. }
  560. // 'unique' replaces consecutive runs of equal elements with a single copy.
  561. // The procedures modifies the slice in-place and returns the modified slice.
  562. @(require_results)
  563. unique :: proc(s: $S/[]$T) -> S where intrinsics.type_is_comparable(T) #no_bounds_check {
  564. if len(s) < 2 {
  565. return s
  566. }
  567. i := 1
  568. for j in 1..<len(s) {
  569. if s[j] != s[j-1] {
  570. if i != j {
  571. s[i] = s[j]
  572. }
  573. i += 1
  574. }
  575. }
  576. return s[:i]
  577. }
  578. // 'unique_proc' replaces consecutive runs of equal elements with a single copy using a comparison procedure
  579. // The procedures modifies the slice in-place and returns the modified slice.
  580. @(require_results)
  581. unique_proc :: proc(s: $S/[]$T, eq: proc(T, T) -> bool) -> S #no_bounds_check {
  582. if len(s) < 2 {
  583. return s
  584. }
  585. i := 1
  586. for j in 1..<len(s) {
  587. if !eq(s[j], s[j-1]) {
  588. if i != j {
  589. s[i] = s[j]
  590. }
  591. i += 1
  592. }
  593. }
  594. return s[:i]
  595. }
  596. @(require_results)
  597. min :: proc(s: $S/[]$T) -> (res: T, ok: bool) where intrinsics.type_is_ordered(T) #optional_ok {
  598. if len(s) != 0 {
  599. res = s[0]
  600. ok = true
  601. for v in s[1:] {
  602. res = builtin.min(res, v)
  603. }
  604. }
  605. return
  606. }
  607. @(require_results)
  608. max :: proc(s: $S/[]$T) -> (res: T, ok: bool) where intrinsics.type_is_ordered(T) #optional_ok {
  609. if len(s) != 0 {
  610. res = s[0]
  611. ok = true
  612. for v in s[1:] {
  613. res = builtin.max(res, v)
  614. }
  615. }
  616. return
  617. }
  618. @(require_results)
  619. min_max :: proc(s: $S/[]$T) -> (min, max: T, ok: bool) where intrinsics.type_is_ordered(T) {
  620. if len(s) != 0 {
  621. min, max = s[0], s[0]
  622. ok = true
  623. for v in s[1:] {
  624. min = builtin.min(min, v)
  625. max = builtin.max(max, v)
  626. }
  627. }
  628. return
  629. }
  630. // Find the index of the (first) minimum element in a slice.
  631. @(require_results)
  632. min_index :: proc(s: $S/[]$T) -> (min_index: int, ok: bool) where intrinsics.type_is_ordered(T) #optional_ok {
  633. if len(s) == 0 {
  634. return -1, false
  635. }
  636. min_index = 0
  637. min_value := s[0]
  638. for v, i in s[1:] {
  639. if v < min_value {
  640. min_value = v
  641. min_index = i+1
  642. }
  643. }
  644. return min_index, true
  645. }
  646. // Find the index of the (first) maximum element in a slice.
  647. @(require_results)
  648. max_index :: proc(s: $S/[]$T) -> (max_index: int, ok: bool) where intrinsics.type_is_ordered(T) #optional_ok {
  649. if len(s) == 0 {
  650. return -1, false
  651. }
  652. max_index = 0
  653. max_value := s[0]
  654. for v, i in s[1:] {
  655. if v > max_value {
  656. max_value = v
  657. max_index = i+1
  658. }
  659. }
  660. return max_index, true
  661. }
  662. @(require_results)
  663. any_of :: proc(s: $S/[]$T, value: T) -> bool where intrinsics.type_is_comparable(T) {
  664. for v in s {
  665. if v == value {
  666. return true
  667. }
  668. }
  669. return false
  670. }
  671. @(require_results)
  672. none_of :: proc(s: $S/[]$T, value: T) -> bool where intrinsics.type_is_comparable(T) {
  673. for v in s {
  674. if v == value {
  675. return false
  676. }
  677. }
  678. return true
  679. }
  680. @(require_results)
  681. all_of :: proc(s: $S/[]$T, value: T) -> bool where intrinsics.type_is_comparable(T) {
  682. if len(s) == 0 {
  683. return false
  684. }
  685. for v in s {
  686. if v != value {
  687. return false
  688. }
  689. }
  690. return true
  691. }
  692. @(require_results)
  693. any_of_proc :: proc(s: $S/[]$T, f: proc(T) -> bool) -> bool {
  694. for v in s {
  695. if f(v) {
  696. return true
  697. }
  698. }
  699. return false
  700. }
  701. @(require_results)
  702. none_of_proc :: proc(s: $S/[]$T, f: proc(T) -> bool) -> bool {
  703. for v in s {
  704. if f(v) {
  705. return false
  706. }
  707. }
  708. return true
  709. }
  710. @(require_results)
  711. all_of_proc :: proc(s: $S/[]$T, f: proc(T) -> bool) -> bool {
  712. if len(s) == 0 {
  713. return false
  714. }
  715. for v in s {
  716. if !f(v) {
  717. return false
  718. }
  719. }
  720. return true
  721. }
  722. @(require_results)
  723. count :: proc(s: $S/[]$T, value: T) -> (n: int) where intrinsics.type_is_comparable(T) {
  724. for v in s {
  725. if v == value {
  726. n += 1
  727. }
  728. }
  729. return
  730. }
  731. @(require_results)
  732. count_proc :: proc(s: $S/[]$T, f: proc(T) -> bool) -> (n: int) {
  733. for v in s {
  734. if f(v) {
  735. n += 1
  736. }
  737. }
  738. return
  739. }
  740. @(require_results)
  741. dot_product :: proc(a, b: $S/[]$T) -> (r: T, ok: bool)
  742. where intrinsics.type_is_numeric(T) {
  743. if len(a) != len(b) {
  744. return
  745. }
  746. #no_bounds_check for _, i in a {
  747. r += a[i] * b[i]
  748. }
  749. return r, true
  750. }
  751. // Convert a pointer to an enumerated array to a slice of the element type
  752. @(require_results)
  753. enumerated_array :: proc(ptr: ^$T) -> []intrinsics.type_elem_type(T)
  754. where intrinsics.type_is_enumerated_array(T) {
  755. return ([^]intrinsics.type_elem_type(T))(ptr)[:len(T)]
  756. }
  757. // Turn a `[]E` into `bit_set[E]`
  758. // e.g.:
  759. // bs := slice.enum_slice_to_bitset(my_flag_slice, rl.ConfigFlags)
  760. @(require_results)
  761. enum_slice_to_bitset :: proc(enums: []$E, $T: typeid/bit_set[E]) -> (bits: T) where intrinsics.type_is_enum(E), intrinsics.type_bit_set_elem_type(T) == E {
  762. for v in enums {
  763. bits += {v}
  764. }
  765. return
  766. }
  767. // Turn a `bit_set[E]` into a `[]E`
  768. // e.g.:
  769. // sl := slice.bitset_to_enum_slice(flag_buf[:], bs)
  770. @(require_results)
  771. bitset_to_enum_slice_with_buffer :: proc(buf: []$E, bs: $T) -> (slice: []E) where intrinsics.type_is_enum(E), intrinsics.type_bit_set_elem_type(T) == E {
  772. count := 0
  773. for v in bs {
  774. buf[count] = v
  775. count += 1
  776. }
  777. return buf[:count]
  778. }
  779. // Turn a `bit_set[E]` into a `[]E`, allocates
  780. // e.g.:
  781. // sl := slice.bitset_to_enum_slice(bs)
  782. @(require_results)
  783. bitset_to_enum_slice_with_make :: proc(bs: $T, $E: typeid, allocator := context.allocator) -> (slice: []E) where intrinsics.type_is_enum(E), intrinsics.type_bit_set_elem_type(T) == E {
  784. buf := make([]E, card(bs), allocator)
  785. return bitset_to_enum_slice(buf, bs)
  786. }
  787. bitset_to_enum_slice :: proc{bitset_to_enum_slice_with_make, bitset_to_enum_slice_with_buffer}