slice.odin 20 KB

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