slice.odin 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. package slice
  2. import "core:intrinsics"
  3. import "core:builtin"
  4. import "core:math/bits"
  5. import "core:mem"
  6. _ :: intrinsics
  7. _ :: builtin
  8. _ :: bits
  9. _ :: mem
  10. swap :: proc(array: $T/[]$E, a, b: int) {
  11. when size_of(E) > 8 {
  12. ptr_swap_non_overlapping(&array[a], &array[b], size_of(E))
  13. } else {
  14. array[a], array[b] = array[b], array[a]
  15. }
  16. }
  17. swap_between :: proc(a, b: $T/[]$E) {
  18. n := builtin.min(len(a), len(b))
  19. if n >= 0 {
  20. ptr_swap_overlapping(&a[0], &b[0], size_of(E)*n)
  21. }
  22. }
  23. reverse :: proc(array: $T/[]$E) {
  24. n := len(array)/2
  25. for i in 0..<n {
  26. a, b := i, len(array)-i-1
  27. array[a], array[b] = array[b], array[a]
  28. }
  29. }
  30. contains :: proc(array: $T/[]$E, value: E) -> bool where intrinsics.type_is_comparable(E) {
  31. _, found := linear_search(array, value)
  32. return found
  33. }
  34. linear_search :: proc(array: $A/[]$T, key: T) -> (index: int, found: bool)
  35. where intrinsics.type_is_comparable(T) #no_bounds_check {
  36. for x, i in array {
  37. if x == key {
  38. return i, true
  39. }
  40. }
  41. return -1, false
  42. }
  43. linear_search_proc :: proc(array: $A/[]$T, f: proc(T) -> bool) -> (index: int, found: bool) #no_bounds_check {
  44. for x, i in array {
  45. if f(x) {
  46. return i, true
  47. }
  48. }
  49. return -1, false
  50. }
  51. binary_search :: proc(array: $A/[]$T, key: T) -> (index: int, found: bool)
  52. where intrinsics.type_is_ordered(T) #no_bounds_check {
  53. n := len(array)
  54. switch n {
  55. case 0:
  56. return -1, false
  57. case 1:
  58. if array[0] == key {
  59. return 0, true
  60. }
  61. return -1, false
  62. }
  63. lo, hi := 0, n-1
  64. for array[hi] != array[lo] && key >= array[lo] && key <= array[hi] {
  65. when intrinsics.type_is_ordered_numeric(T) {
  66. // NOTE(bill): This is technically interpolation search
  67. m := lo + int((key - array[lo]) * T(hi - lo) / (array[hi] - array[lo]))
  68. } else {
  69. m := lo + (hi - lo)/2
  70. }
  71. switch {
  72. case array[m] < key:
  73. lo = m + 1
  74. case key < array[m]:
  75. hi = m - 1
  76. case:
  77. return m, true
  78. }
  79. }
  80. if key == array[lo] {
  81. return lo, true
  82. }
  83. return -1, false
  84. }
  85. equal :: proc(a, b: $T/[]$E) -> bool where intrinsics.type_is_comparable(E) {
  86. if len(a) != len(b) {
  87. return false
  88. }
  89. when intrinsics.type_is_simple_compare(E) {
  90. return mem.compare_ptrs(raw_data(a), raw_data(b), len(a)*size_of(E)) == 0
  91. } else {
  92. for i in 0..<len(a) {
  93. if a[i] != b[i] {
  94. return false
  95. }
  96. }
  97. return true
  98. }
  99. }
  100. simple_equal :: proc(a, b: $T/[]$E) -> bool where intrinsics.type_is_simple_compare(E) {
  101. if len(a) != len(b) {
  102. return false
  103. }
  104. return mem.compare_ptrs(raw_data(a), raw_data(b), len(a)*size_of(E)) == 0
  105. }
  106. has_prefix :: proc(array: $T/[]$E, needle: E) -> bool where intrinsics.type_is_comparable(E) {
  107. n := len(needle)
  108. if len(array) >= n {
  109. return equal(array[:n], needle)
  110. }
  111. return false
  112. }
  113. has_suffix :: proc(array: $T/[]$E, needle: E) -> bool where intrinsics.type_is_comparable(E) {
  114. array := array
  115. m, n := len(array), len(needle)
  116. if m >= n {
  117. return equal(array[m-n:], needle)
  118. }
  119. return false
  120. }
  121. fill :: proc(array: $T/[]$E, value: E) #no_bounds_check {
  122. if len(array) <= 0 {
  123. return
  124. }
  125. array[0] = value
  126. for i := 1; i < len(array); i *= 2 {
  127. copy(array[i:], array[:i])
  128. }
  129. }
  130. rotate_left :: proc(array: $T/[]$E, mid: int) {
  131. n := len(array)
  132. m := mid %% n
  133. k := n - m
  134. p := raw_data(array)
  135. ptr_rotate(mid, ptr_add(p, mid), k)
  136. }
  137. rotate_right :: proc(array: $T/[]$E, k: int) {
  138. rotate_left(array, -k)
  139. }
  140. swap_with_slice :: proc(a, b: $T/[]$E, loc := #caller_location) {
  141. assert(len(a) == len(b), "miss matching slice lengths", loc)
  142. ptr_swap_non_overlapping(raw_data(a), raw_data(b), len(a)*size_of(E))
  143. }
  144. concatenate :: proc(a: []$T/[]$E, allocator := context.allocator) -> (res: T) {
  145. if len(a) == 0 {
  146. return
  147. }
  148. n := 0
  149. for s in a {
  150. n += len(s)
  151. }
  152. res = make(T, n, allocator)
  153. i := 0
  154. for s in a {
  155. i += copy(res[i:], s)
  156. }
  157. return
  158. }
  159. // copies slice into a new dynamic array
  160. clone :: proc(a: $T/[]$E, allocator := context.allocator) -> []E {
  161. d := make([]E, len(a), allocator)
  162. copy(d[:], a)
  163. return d
  164. }
  165. // copies slice into a new dynamic array
  166. to_dynamic :: proc(a: $T/[]$E, allocator := context.allocator) -> [dynamic]E {
  167. d := make([dynamic]E, len(a), allocator)
  168. copy(d[:], a)
  169. return d
  170. }
  171. // Converts slice into a dynamic array without cloning or allocating memory
  172. into_dynamic :: proc(a: $T/[]$E) -> [dynamic]E {
  173. s := transmute(mem.Raw_Slice)a
  174. d := mem.Raw_Dynamic_Array{
  175. data = s.data,
  176. len = 0,
  177. cap = s.len,
  178. allocator = mem.nil_allocator(),
  179. }
  180. return transmute([dynamic]E)d
  181. }
  182. length :: proc(a: $T/[]$E) -> int {
  183. return len(a)
  184. }
  185. is_empty :: proc(a: $T/[]$E) -> bool {
  186. return len(a) == 0
  187. }
  188. split_at :: proc(array: $T/[]$E, index: int) -> (a, b: T) {
  189. return array[:index], array[index:]
  190. }
  191. split_first :: proc(array: $T/[]$E) -> (first: E, rest: T) {
  192. return array[0], array[1:]
  193. }
  194. split_last :: proc(array: $T/[]$E) -> (rest: T, last: E) {
  195. n := len(array)-1
  196. return array[:n], array[n]
  197. }
  198. first :: proc(array: $T/[]$E) -> E {
  199. return array[0]
  200. }
  201. last :: proc(array: $T/[]$E) -> E {
  202. return array[len(array)-1]
  203. }
  204. first_ptr :: proc(array: $T/[]$E) -> ^E {
  205. if len(array) != 0 {
  206. return &array[0]
  207. }
  208. return nil
  209. }
  210. last_ptr :: proc(array: $T/[]$E) -> ^E {
  211. if len(array) != 0 {
  212. return &array[len(array)-1]
  213. }
  214. return nil
  215. }
  216. get :: proc(array: $T/[]$E, index: int) -> (value: E, ok: bool) {
  217. if 0 <= index && index < len(array) {
  218. value = array[index]
  219. ok = true
  220. }
  221. return
  222. }
  223. get_ptr :: proc(array: $T/[]$E, index: int) -> (value: ^E, ok: bool) {
  224. if 0 <= index && index < len(array) {
  225. value = &array[index]
  226. ok = true
  227. }
  228. return
  229. }
  230. as_ptr :: proc(array: $T/[]$E) -> ^E {
  231. return raw_data(array)
  232. }
  233. mapper :: proc(s: $S/[]$U, f: proc(U) -> $V, allocator := context.allocator) -> []V {
  234. r := make([]V, len(s), allocator)
  235. for v, i in s {
  236. r[i] = f(v)
  237. }
  238. return r
  239. }
  240. reduce :: proc(s: $S/[]$U, initializer: $V, f: proc(V, U) -> V) -> V {
  241. r := initializer
  242. for v in s {
  243. r = f(r, v)
  244. }
  245. return r
  246. }
  247. filter :: proc(s: $S/[]$U, f: proc(U) -> bool, allocator := context.allocator) -> S {
  248. r := make([dynamic]U, 0, 0, allocator)
  249. for v in s {
  250. if f(v) {
  251. append(&r, v)
  252. }
  253. }
  254. return r[:]
  255. }
  256. min :: proc(s: $S/[]$T) -> (res: T, ok: bool) where intrinsics.type_is_ordered(T) #optional_ok {
  257. if len(s) != 0 {
  258. res = s[0]
  259. ok = true
  260. for v in s[1:] {
  261. res = builtin.min(res, v)
  262. }
  263. }
  264. return
  265. }
  266. max :: proc(s: $S/[]$T) -> (res: T, ok: bool) where intrinsics.type_is_ordered(T) #optional_ok {
  267. if len(s) != 0 {
  268. res = s[0]
  269. ok = true
  270. for v in s[1:] {
  271. res = builtin.max(res, v)
  272. }
  273. }
  274. return
  275. }
  276. dot_product :: proc(a, b: $S/[]$T) -> T
  277. where intrinsics.type_is_numeric(T) {
  278. if len(a) != len(b) {
  279. panic("slice.dot_product: slices of unequal length")
  280. }
  281. r: T
  282. #no_bounds_check for _, i in a {
  283. r += a[i] * b[i]
  284. }
  285. return r
  286. }