slice.odin 21 KB

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