slice.odin 20 KB

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