hamster 1.0.1.pre.rc2 → 1.0.1.pre.rc3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (482) hide show
  1. checksums.yaml +4 -4
  2. data/lib/hamster.rb +2 -2
  3. data/lib/hamster/core_ext.rb +0 -1
  4. data/lib/hamster/core_ext/enumerable.rb +17 -17
  5. data/lib/hamster/core_ext/io.rb +15 -17
  6. data/lib/hamster/deque.rb +229 -0
  7. data/lib/hamster/enumerable.rb +147 -105
  8. data/lib/hamster/experimental/mutable_queue.rb +2 -2
  9. data/lib/hamster/hash.rb +488 -82
  10. data/lib/hamster/immutable.rb +4 -0
  11. data/lib/hamster/list.rb +839 -196
  12. data/lib/hamster/read_copy_update.rb +1 -0
  13. data/lib/hamster/set.rb +317 -54
  14. data/lib/hamster/sorted_set.rb +1014 -0
  15. data/lib/hamster/trie.rb +67 -47
  16. data/lib/hamster/undefined.rb +1 -3
  17. data/lib/hamster/vector.rb +989 -76
  18. data/lib/hamster/version.rb +1 -1
  19. data/spec/{hamster → lib/hamster}/core_ext/array_spec.rb +1 -1
  20. data/spec/{hamster → lib/hamster}/core_ext/enumerable_spec.rb +4 -0
  21. data/spec/{hamster → lib/hamster}/core_ext/io_spec.rb +0 -0
  22. data/spec/lib/hamster/deque/clear_spec.rb +34 -0
  23. data/spec/lib/hamster/deque/construction_spec.rb +30 -0
  24. data/spec/lib/hamster/deque/copying_spec.rb +20 -0
  25. data/spec/lib/hamster/deque/dequeue_spec.rb +27 -0
  26. data/spec/lib/hamster/deque/empty_spec.rb +42 -0
  27. data/spec/{hamster/queue → lib/hamster/deque}/enqueue_spec.rb +7 -10
  28. data/spec/lib/hamster/deque/head_spec.rb +20 -0
  29. data/spec/lib/hamster/deque/inspect_spec.rb +24 -0
  30. data/spec/lib/hamster/deque/last_spec.rb +20 -0
  31. data/spec/lib/hamster/deque/marshal_spec.rb +34 -0
  32. data/spec/lib/hamster/deque/new_spec.rb +44 -0
  33. data/spec/lib/hamster/deque/pop_spec.rb +25 -0
  34. data/spec/lib/hamster/deque/random_modification_spec.rb +34 -0
  35. data/spec/{hamster/queue → lib/hamster/deque}/size_spec.rb +4 -9
  36. data/spec/lib/hamster/deque/to_a_spec.rb +27 -0
  37. data/spec/{hamster/queue → lib/hamster/deque}/to_ary_spec.rb +6 -6
  38. data/spec/lib/hamster/deque/to_list_spec.rb +26 -0
  39. data/spec/lib/hamster/deque/unshift_spec.rb +26 -0
  40. data/spec/{hamster → lib/hamster}/experimental/mutable_set/add_qm_spec.rb +0 -0
  41. data/spec/{hamster → lib/hamster}/experimental/mutable_set/add_spec.rb +0 -0
  42. data/spec/{hamster → lib/hamster}/experimental/mutable_set/delete_qm_spec.rb +0 -0
  43. data/spec/{hamster → lib/hamster}/experimental/mutable_set/delete_spec.rb +0 -0
  44. data/spec/{hamster → lib/hamster}/hash/all_spec.rb +10 -0
  45. data/spec/lib/hamster/hash/any_spec.rb +56 -0
  46. data/spec/lib/hamster/hash/assoc_spec.rb +52 -0
  47. data/spec/lib/hamster/hash/clear_spec.rb +43 -0
  48. data/spec/lib/hamster/hash/construction_spec.rb +39 -0
  49. data/spec/{hamster → lib/hamster}/hash/copying_spec.rb +2 -4
  50. data/spec/lib/hamster/hash/default_proc_spec.rb +73 -0
  51. data/spec/lib/hamster/hash/delete_spec.rb +40 -0
  52. data/spec/lib/hamster/hash/each_spec.rb +78 -0
  53. data/spec/lib/hamster/hash/each_with_index_spec.rb +30 -0
  54. data/spec/lib/hamster/hash/empty_spec.rb +46 -0
  55. data/spec/lib/hamster/hash/eql_spec.rb +70 -0
  56. data/spec/lib/hamster/hash/except_spec.rb +43 -0
  57. data/spec/lib/hamster/hash/fetch_spec.rb +58 -0
  58. data/spec/lib/hamster/hash/filter_spec.rb +58 -0
  59. data/spec/lib/hamster/hash/find_spec.rb +44 -0
  60. data/spec/lib/hamster/hash/flat_map_spec.rb +36 -0
  61. data/spec/lib/hamster/hash/flatten_spec.rb +99 -0
  62. data/spec/lib/hamster/hash/get_spec.rb +80 -0
  63. data/spec/lib/hamster/hash/has_key_spec.rb +32 -0
  64. data/spec/lib/hamster/hash/has_value_spec.rb +28 -0
  65. data/spec/{hamster → lib/hamster}/hash/hash_spec.rb +5 -12
  66. data/spec/{hamster → lib/hamster}/hash/immutable_spec.rb +0 -0
  67. data/spec/lib/hamster/hash/inspect_spec.rb +31 -0
  68. data/spec/lib/hamster/hash/invert_spec.rb +31 -0
  69. data/spec/lib/hamster/hash/key_spec.rb +28 -0
  70. data/spec/{hamster → lib/hamster}/hash/keys_spec.rb +3 -6
  71. data/spec/lib/hamster/hash/map_spec.rb +46 -0
  72. data/spec/{hamster → lib/hamster}/hash/marshal_spec.rb +3 -3
  73. data/spec/lib/hamster/hash/merge_spec.rb +77 -0
  74. data/spec/lib/hamster/hash/min_max_spec.rb +50 -0
  75. data/spec/lib/hamster/hash/new_spec.rb +71 -0
  76. data/spec/{hamster → lib/hamster}/hash/none_spec.rb +12 -14
  77. data/spec/lib/hamster/hash/partition_spec.rb +36 -0
  78. data/spec/lib/hamster/hash/pretty_print_spec.rb +35 -0
  79. data/spec/lib/hamster/hash/put_spec.rb +81 -0
  80. data/spec/lib/hamster/hash/reduce_spec.rb +36 -0
  81. data/spec/lib/hamster/hash/remove_spec.rb +62 -0
  82. data/spec/lib/hamster/hash/reverse_each_spec.rb +28 -0
  83. data/spec/lib/hamster/hash/sample_spec.rb +14 -0
  84. data/spec/{hamster → lib/hamster}/hash/size_spec.rb +2 -2
  85. data/spec/lib/hamster/hash/slice_spec.rb +45 -0
  86. data/spec/lib/hamster/hash/sort_spec.rb +27 -0
  87. data/spec/lib/hamster/hash/store_spec.rb +54 -0
  88. data/spec/lib/hamster/hash/take_spec.rb +36 -0
  89. data/spec/lib/hamster/hash/to_a_spec.rb +14 -0
  90. data/spec/lib/hamster/hash/to_hash_spec.rb +22 -0
  91. data/spec/{hamster → lib/hamster}/hash/uniq_spec.rb +2 -4
  92. data/spec/lib/hamster/hash/values_at_spec.rb +14 -0
  93. data/spec/lib/hamster/hash/values_spec.rb +25 -0
  94. data/spec/{hamster → lib/hamster}/immutable/copying_spec.rb +0 -0
  95. data/spec/{hamster → lib/hamster}/immutable/immutable_spec.rb +0 -0
  96. data/spec/{hamster → lib/hamster}/immutable/memoize_spec.rb +2 -2
  97. data/spec/{hamster → lib/hamster}/immutable/new_spec.rb +0 -0
  98. data/spec/{hamster → lib/hamster}/immutable/transform_spec.rb +0 -0
  99. data/spec/{hamster → lib/hamster}/immutable/transform_unless_spec.rb +0 -0
  100. data/spec/lib/hamster/list/add_spec.rb +20 -0
  101. data/spec/lib/hamster/list/all_spec.rb +60 -0
  102. data/spec/{hamster → lib/hamster}/list/any_spec.rb +12 -20
  103. data/spec/{hamster → lib/hamster}/list/append_spec.rb +9 -10
  104. data/spec/lib/hamster/list/at_spec.rb +30 -0
  105. data/spec/lib/hamster/list/break_spec.rb +70 -0
  106. data/spec/{hamster → lib/hamster}/list/cadr_spec.rb +5 -8
  107. data/spec/{hamster → lib/hamster}/list/chunk_spec.rb +5 -8
  108. data/spec/{hamster → lib/hamster}/list/clear_spec.rb +4 -7
  109. data/spec/lib/hamster/list/combination_spec.rb +34 -0
  110. data/spec/{hamster → lib/hamster}/list/compact_spec.rb +5 -8
  111. data/spec/lib/hamster/list/compare_spec.rb +31 -0
  112. data/spec/{hamster → lib/hamster}/list/cons_spec.rb +5 -9
  113. data/spec/lib/hamster/list/construction_spec.rb +118 -0
  114. data/spec/{hamster → lib/hamster}/list/copying_spec.rb +3 -7
  115. data/spec/lib/hamster/list/count_spec.rb +37 -0
  116. data/spec/lib/hamster/list/cycle_spec.rb +29 -0
  117. data/spec/lib/hamster/list/delete_at_spec.rb +19 -0
  118. data/spec/lib/hamster/list/delete_spec.rb +17 -0
  119. data/spec/{hamster → lib/hamster}/list/drop_spec.rb +5 -8
  120. data/spec/lib/hamster/list/drop_while_spec.rb +39 -0
  121. data/spec/lib/hamster/list/each_slice_spec.rb +52 -0
  122. data/spec/lib/hamster/list/each_spec.rb +43 -0
  123. data/spec/lib/hamster/list/each_with_index_spec.rb +29 -0
  124. data/spec/{hamster → lib/hamster}/list/elem_index_spec.rb +4 -14
  125. data/spec/{hamster → lib/hamster}/list/elem_indices_spec.rb +5 -9
  126. data/spec/{hamster → lib/hamster}/list/empty_spec.rb +4 -13
  127. data/spec/{hamster → lib/hamster}/list/eql_spec.rb +2 -8
  128. data/spec/lib/hamster/list/fill_spec.rb +50 -0
  129. data/spec/{hamster → lib/hamster}/list/filter_spec.rb +3 -2
  130. data/spec/{hamster → lib/hamster}/list/find_all_spec.rb +3 -2
  131. data/spec/{hamster → lib/hamster}/list/find_index_spec.rb +4 -14
  132. data/spec/{hamster → lib/hamster}/list/find_indices_spec.rb +11 -9
  133. data/spec/{hamster → lib/hamster}/list/find_spec.rb +10 -16
  134. data/spec/{hamster → lib/hamster}/list/flat_map_spec.rb +0 -0
  135. data/spec/{hamster → lib/hamster}/list/flatten_spec.rb +5 -8
  136. data/spec/{hamster → lib/hamster}/list/grep_spec.rb +9 -17
  137. data/spec/{hamster → lib/hamster}/list/group_by_spec.rb +8 -24
  138. data/spec/{hamster → lib/hamster}/list/hash_spec.rb +4 -12
  139. data/spec/{hamster → lib/hamster}/list/head_spec.rb +2 -7
  140. data/spec/{hamster → lib/hamster}/list/include_spec.rb +4 -13
  141. data/spec/{hamster → lib/hamster}/list/init_spec.rb +5 -9
  142. data/spec/lib/hamster/list/inits_spec.rb +29 -0
  143. data/spec/lib/hamster/list/insert_spec.rb +47 -0
  144. data/spec/lib/hamster/list/inspect_spec.rb +30 -0
  145. data/spec/{hamster → lib/hamster}/list/intersperse_spec.rb +5 -8
  146. data/spec/lib/hamster/list/join_spec.rb +64 -0
  147. data/spec/lib/hamster/list/last_spec.rb +24 -0
  148. data/spec/{hamster → lib/hamster}/list/map_spec.rb +11 -20
  149. data/spec/lib/hamster/list/maximum_spec.rb +42 -0
  150. data/spec/{hamster → lib/hamster}/list/merge_by_spec.rb +4 -13
  151. data/spec/{hamster → lib/hamster}/list/merge_spec.rb +0 -0
  152. data/spec/lib/hamster/list/minimum_spec.rb +42 -0
  153. data/spec/lib/hamster/list/multithreading_spec.rb +48 -0
  154. data/spec/{hamster → lib/hamster}/list/none_spec.rb +11 -21
  155. data/spec/{hamster → lib/hamster}/list/one_spec.rb +12 -22
  156. data/spec/lib/hamster/list/partition_spec.rb +116 -0
  157. data/spec/lib/hamster/list/permutation_spec.rb +56 -0
  158. data/spec/{hamster → lib/hamster}/list/pop_spec.rb +1 -1
  159. data/spec/lib/hamster/list/product_spec.rb +24 -0
  160. data/spec/lib/hamster/list/reduce_spec.rb +97 -0
  161. data/spec/{hamster → lib/hamster}/list/remove_spec.rb +9 -19
  162. data/spec/{hamster → lib/hamster}/list/reverse_spec.rb +7 -14
  163. data/spec/lib/hamster/list/rotate_spec.rb +37 -0
  164. data/spec/lib/hamster/list/sample_spec.rb +14 -0
  165. data/spec/{hamster → lib/hamster}/list/select_spec.rb +3 -2
  166. data/spec/{hamster → lib/hamster}/list/size_spec.rb +4 -13
  167. data/spec/lib/hamster/list/slice_spec.rb +230 -0
  168. data/spec/{hamster → lib/hamster}/list/sorting_spec.rb +10 -20
  169. data/spec/lib/hamster/list/span_spec.rb +77 -0
  170. data/spec/{hamster → lib/hamster}/list/split_at_spec.rb +13 -14
  171. data/spec/lib/hamster/list/subsequences_spec.rb +24 -0
  172. data/spec/lib/hamster/list/sum_spec.rb +24 -0
  173. data/spec/lib/hamster/list/tail_spec.rb +31 -0
  174. data/spec/lib/hamster/list/tails_spec.rb +29 -0
  175. data/spec/{hamster → lib/hamster}/list/take_spec.rb +5 -8
  176. data/spec/{hamster → lib/hamster}/list/take_while_spec.rb +11 -17
  177. data/spec/lib/hamster/list/to_a_spec.rb +40 -0
  178. data/spec/{hamster → lib/hamster}/list/to_ary_spec.rb +1 -3
  179. data/spec/{hamster → lib/hamster}/list/to_list_spec.rb +3 -7
  180. data/spec/{hamster → lib/hamster}/list/to_set_spec.rb +2 -10
  181. data/spec/lib/hamster/list/transpose_spec.rb +20 -0
  182. data/spec/{hamster → lib/hamster}/list/union_spec.rb +5 -12
  183. data/spec/{hamster → lib/hamster}/list/uniq_spec.rb +5 -8
  184. data/spec/{hamster → lib/hamster}/list/zip_spec.rb +2 -9
  185. data/spec/lib/hamster/set/add_spec.rb +76 -0
  186. data/spec/{hamster → lib/hamster}/set/all_spec.rb +18 -14
  187. data/spec/{hamster → lib/hamster}/set/any_spec.rb +19 -16
  188. data/spec/{hamster → lib/hamster}/set/clear_spec.rb +8 -11
  189. data/spec/{hamster → lib/hamster}/set/compact_spec.rb +4 -7
  190. data/spec/{hamster → lib/hamster}/set/construction_spec.rb +4 -8
  191. data/spec/{hamster → lib/hamster}/set/copying_spec.rb +3 -5
  192. data/spec/{hamster → lib/hamster}/set/count_spec.rb +11 -16
  193. data/spec/lib/hamster/set/delete_spec.rb +72 -0
  194. data/spec/lib/hamster/set/difference_spec.rb +50 -0
  195. data/spec/lib/hamster/set/disjoint_spec.rb +26 -0
  196. data/spec/lib/hamster/set/each_spec.rb +46 -0
  197. data/spec/lib/hamster/set/empty_spec.rb +47 -0
  198. data/spec/{hamster → lib/hamster}/set/eqeq_spec.rb +0 -0
  199. data/spec/{hamster → lib/hamster}/set/eql_spec.rb +7 -1
  200. data/spec/lib/hamster/set/exclusion_spec.rb +48 -0
  201. data/spec/lib/hamster/set/filter_spec.rb +74 -0
  202. data/spec/{hamster → lib/hamster}/set/find_spec.rb +7 -11
  203. data/spec/lib/hamster/set/flatten_spec.rb +47 -0
  204. data/spec/{hamster → lib/hamster}/set/foreach_spec.rb +5 -4
  205. data/spec/{hamster → lib/hamster}/set/grep_spec.rb +1 -1
  206. data/spec/lib/hamster/set/group_by_spec.rb +60 -0
  207. data/spec/lib/hamster/set/hash_spec.rb +23 -0
  208. data/spec/lib/hamster/set/head_spec.rb +31 -0
  209. data/spec/{hamster → lib/hamster}/set/immutable_spec.rb +0 -0
  210. data/spec/lib/hamster/set/include_spec.rb +61 -0
  211. data/spec/lib/hamster/set/inspect_spec.rb +48 -0
  212. data/spec/lib/hamster/set/intersect_spec.rb +26 -0
  213. data/spec/lib/hamster/set/intersection_spec.rb +53 -0
  214. data/spec/lib/hamster/set/join_spec.rb +65 -0
  215. data/spec/lib/hamster/set/map_spec.rb +60 -0
  216. data/spec/{hamster → lib/hamster}/set/marshal_spec.rb +3 -3
  217. data/spec/{hamster → lib/hamster}/set/maximum_spec.rb +6 -15
  218. data/spec/{hamster → lib/hamster}/set/minimum_spec.rb +6 -16
  219. data/spec/lib/hamster/set/new_spec.rb +54 -0
  220. data/spec/{hamster → lib/hamster}/set/none_spec.rb +15 -15
  221. data/spec/{hamster → lib/hamster}/set/one_spec.rb +14 -16
  222. data/spec/lib/hamster/set/partition_spec.rb +53 -0
  223. data/spec/{hamster → lib/hamster}/set/product_spec.rb +6 -6
  224. data/spec/lib/hamster/set/reduce_spec.rb +56 -0
  225. data/spec/lib/hamster/set/remove_spec.rb +51 -0
  226. data/spec/{hamster/set/each_spec.rb → lib/hamster/set/reverse_each_spec.rb} +8 -7
  227. data/spec/lib/hamster/set/sample_spec.rb +14 -0
  228. data/spec/{hamster → lib/hamster}/set/size_spec.rb +0 -1
  229. data/spec/{hamster → lib/hamster}/set/sorting_spec.rb +17 -13
  230. data/spec/lib/hamster/set/subset_spec.rb +52 -0
  231. data/spec/lib/hamster/set/sum_spec.rb +24 -0
  232. data/spec/lib/hamster/set/superset_spec.rb +52 -0
  233. data/spec/lib/hamster/set/to_a_spec.rb +31 -0
  234. data/spec/lib/hamster/set/to_list_spec.rb +37 -0
  235. data/spec/{hamster → lib/hamster}/set/to_set_spec.rb +2 -6
  236. data/spec/lib/hamster/set/union_spec.rb +55 -0
  237. data/spec/{hamster → lib/hamster}/set/uniq_spec.rb +2 -5
  238. data/spec/lib/hamster/sorted_set/above_spec.rb +52 -0
  239. data/spec/lib/hamster/sorted_set/add_spec.rb +63 -0
  240. data/spec/lib/hamster/sorted_set/at_spec.rb +25 -0
  241. data/spec/lib/hamster/sorted_set/below_spec.rb +52 -0
  242. data/spec/lib/hamster/sorted_set/between_spec.rb +52 -0
  243. data/spec/lib/hamster/sorted_set/clear_spec.rb +35 -0
  244. data/spec/lib/hamster/sorted_set/construction_spec.rb +29 -0
  245. data/spec/lib/hamster/sorted_set/delete_at_spec.rb +19 -0
  246. data/spec/lib/hamster/sorted_set/delete_spec.rb +81 -0
  247. data/spec/{hamster/set → lib/hamster/sorted_set}/difference_spec.rb +5 -9
  248. data/spec/lib/hamster/sorted_set/disjoint_spec.rb +26 -0
  249. data/spec/lib/hamster/sorted_set/drop_spec.rb +29 -0
  250. data/spec/lib/hamster/sorted_set/drop_while_spec.rb +35 -0
  251. data/spec/lib/hamster/sorted_set/each_spec.rb +31 -0
  252. data/spec/lib/hamster/sorted_set/empty_spec.rb +37 -0
  253. data/spec/lib/hamster/sorted_set/eql_spec.rb +121 -0
  254. data/spec/{hamster/set → lib/hamster/sorted_set}/exclusion_spec.rb +4 -9
  255. data/spec/lib/hamster/sorted_set/fetch_spec.rb +65 -0
  256. data/spec/lib/hamster/sorted_set/filter_spec.rb +62 -0
  257. data/spec/lib/hamster/sorted_set/find_index_spec.rb +33 -0
  258. data/spec/lib/hamster/sorted_set/first_spec.rb +21 -0
  259. data/spec/lib/hamster/sorted_set/from_spec.rb +52 -0
  260. data/spec/lib/hamster/sorted_set/group_by_spec.rb +58 -0
  261. data/spec/lib/hamster/sorted_set/include_spec.rb +24 -0
  262. data/spec/lib/hamster/sorted_set/inspect_spec.rb +38 -0
  263. data/spec/lib/hamster/sorted_set/intersect_spec.rb +26 -0
  264. data/spec/lib/hamster/sorted_set/intersection_spec.rb +29 -0
  265. data/spec/lib/hamster/sorted_set/last_spec.rb +37 -0
  266. data/spec/lib/hamster/sorted_set/map_spec.rb +36 -0
  267. data/spec/lib/hamster/sorted_set/marshal_spec.rb +37 -0
  268. data/spec/lib/hamster/sorted_set/minimum_spec.rb +22 -0
  269. data/spec/lib/hamster/sorted_set/new_spec.rb +52 -0
  270. data/spec/lib/hamster/sorted_set/reverse_each_spec.rb +29 -0
  271. data/spec/lib/hamster/sorted_set/sample_spec.rb +14 -0
  272. data/spec/lib/hamster/sorted_set/size_spec.rb +18 -0
  273. data/spec/lib/hamster/sorted_set/slice_spec.rb +241 -0
  274. data/spec/lib/hamster/sorted_set/sorting_spec.rb +45 -0
  275. data/spec/lib/hamster/sorted_set/subset_spec.rb +48 -0
  276. data/spec/lib/hamster/sorted_set/superset_spec.rb +48 -0
  277. data/spec/lib/hamster/sorted_set/take_spec.rb +26 -0
  278. data/spec/lib/hamster/sorted_set/take_while_spec.rb +34 -0
  279. data/spec/lib/hamster/sorted_set/to_set_spec.rb +19 -0
  280. data/spec/lib/hamster/sorted_set/union_spec.rb +28 -0
  281. data/spec/lib/hamster/sorted_set/up_to_spec.rb +52 -0
  282. data/spec/lib/hamster/sorted_set/values_at_spec.rb +34 -0
  283. data/spec/lib/hamster/vector/add_spec.rb +68 -0
  284. data/spec/{hamster → lib/hamster}/vector/any_spec.rb +0 -0
  285. data/spec/lib/hamster/vector/assoc_spec.rb +36 -0
  286. data/spec/lib/hamster/vector/bsearch_spec.rb +58 -0
  287. data/spec/lib/hamster/vector/clear_spec.rb +34 -0
  288. data/spec/lib/hamster/vector/combination_spec.rb +82 -0
  289. data/spec/lib/hamster/vector/compact_spec.rb +30 -0
  290. data/spec/lib/hamster/vector/compare_spec.rb +32 -0
  291. data/spec/lib/hamster/vector/concat_spec.rb +35 -0
  292. data/spec/{hamster → lib/hamster}/vector/copying_spec.rb +3 -6
  293. data/spec/lib/hamster/vector/count_spec.rb +18 -0
  294. data/spec/lib/hamster/vector/delete_at_spec.rb +54 -0
  295. data/spec/lib/hamster/vector/delete_spec.rb +31 -0
  296. data/spec/lib/hamster/vector/drop_spec.rb +35 -0
  297. data/spec/lib/hamster/vector/drop_while_spec.rb +55 -0
  298. data/spec/lib/hamster/vector/each_index_spec.rb +41 -0
  299. data/spec/lib/hamster/vector/each_spec.rb +47 -0
  300. data/spec/lib/hamster/vector/each_with_index_spec.rb +40 -0
  301. data/spec/lib/hamster/vector/empty_spec.rb +44 -0
  302. data/spec/lib/hamster/vector/eql_spec.rb +77 -0
  303. data/spec/lib/hamster/vector/exist_spec.rb +4 -4
  304. data/spec/lib/hamster/vector/exists_spec.rb +4 -4
  305. data/spec/lib/hamster/vector/fetch_spec.rb +65 -0
  306. data/spec/lib/hamster/vector/fill_spec.rb +89 -0
  307. data/spec/lib/hamster/vector/filter_spec.rb +64 -0
  308. data/spec/{hamster → lib/hamster}/vector/first_spec.rb +2 -6
  309. data/spec/lib/hamster/vector/flatten_spec.rb +44 -0
  310. data/spec/lib/hamster/vector/get_spec.rb +75 -0
  311. data/spec/lib/hamster/vector/group_by_spec.rb +58 -0
  312. data/spec/{hamster → lib/hamster}/vector/include_spec.rb +2 -6
  313. data/spec/lib/hamster/vector/insert_spec.rb +69 -0
  314. data/spec/lib/hamster/vector/inspect_spec.rb +50 -0
  315. data/spec/{hamster/set → lib/hamster/vector}/join_spec.rb +23 -18
  316. data/spec/{hamster → lib/hamster}/vector/last_spec.rb +12 -3
  317. data/spec/{hamster → lib/hamster}/vector/length_spec.rb +12 -3
  318. data/spec/lib/hamster/vector/ltlt_spec.rb +20 -2
  319. data/spec/lib/hamster/vector/map_spec.rb +52 -0
  320. data/spec/lib/hamster/vector/marshal_spec.rb +32 -0
  321. data/spec/lib/hamster/vector/maximum_spec.rb +36 -0
  322. data/spec/lib/hamster/vector/minimum_spec.rb +36 -0
  323. data/spec/lib/hamster/vector/multiply_spec.rb +48 -0
  324. data/spec/lib/hamster/vector/new_spec.rb +51 -0
  325. data/spec/lib/hamster/vector/partition_spec.rb +53 -0
  326. data/spec/lib/hamster/vector/permutation_spec.rb +92 -0
  327. data/spec/lib/hamster/vector/pop_spec.rb +27 -0
  328. data/spec/lib/hamster/vector/product_spec.rb +71 -0
  329. data/spec/lib/hamster/vector/reduce_spec.rb +108 -0
  330. data/spec/lib/hamster/vector/remove_spec.rb +44 -0
  331. data/spec/lib/hamster/vector/repeated_combination_spec.rb +78 -0
  332. data/spec/lib/hamster/vector/repeated_permutation_spec.rb +94 -0
  333. data/spec/lib/hamster/vector/reverse_each_spec.rb +32 -0
  334. data/spec/lib/hamster/vector/reverse_spec.rb +22 -0
  335. data/spec/lib/hamster/vector/rindex_spec.rb +37 -0
  336. data/spec/lib/hamster/vector/rotate_spec.rb +74 -0
  337. data/spec/lib/hamster/vector/sample_spec.rb +14 -0
  338. data/spec/{hamster → lib/hamster}/vector/set_spec.rb +48 -14
  339. data/spec/lib/hamster/vector/shift_spec.rb +28 -0
  340. data/spec/lib/hamster/vector/shuffle_spec.rb +44 -0
  341. data/spec/lib/hamster/vector/slice_spec.rb +241 -0
  342. data/spec/lib/hamster/vector/sorting_spec.rb +57 -0
  343. data/spec/{hamster/set → lib/hamster/vector}/sum_spec.rb +3 -9
  344. data/spec/lib/hamster/vector/take_spec.rb +29 -0
  345. data/spec/lib/hamster/vector/take_while_spec.rb +35 -0
  346. data/spec/{hamster → lib/hamster}/vector/to_a_spec.rb +11 -12
  347. data/spec/{hamster → lib/hamster}/vector/to_ary_spec.rb +0 -0
  348. data/spec/{hamster/set → lib/hamster/vector}/to_list_spec.rb +7 -12
  349. data/spec/lib/hamster/vector/to_set_spec.rb +23 -0
  350. data/spec/lib/hamster/vector/transpose_spec.rb +49 -0
  351. data/spec/lib/hamster/vector/uniq_spec.rb +56 -0
  352. data/spec/lib/hamster/vector/unshift_spec.rb +29 -0
  353. data/spec/lib/hamster/vector/values_at_spec.rb +34 -0
  354. data/spec/lib/hamster/vector/zip_spec.rb +58 -0
  355. data/spec/spec_helper.rb +34 -1
  356. metadata +684 -467
  357. data/lib/hamster/core_ext/enumerator.rb +0 -16
  358. data/lib/hamster/experimental/mutable_stack.rb +0 -30
  359. data/lib/hamster/groupable.rb +0 -12
  360. data/lib/hamster/queue.rb +0 -86
  361. data/lib/hamster/sorter.rb +0 -25
  362. data/lib/hamster/stack.rb +0 -77
  363. data/lib/hamster/tuple.rb +0 -24
  364. data/spec/hamster/core_ext/enumerator_spec.rb +0 -19
  365. data/spec/hamster/experimental/mutable_stack/pop_spec.rb +0 -35
  366. data/spec/hamster/experimental/mutable_stack/push_spec.rb +0 -21
  367. data/spec/hamster/hash/any_spec.rb +0 -52
  368. data/spec/hamster/hash/clear_spec.rb +0 -29
  369. data/spec/hamster/hash/construction_spec.rb +0 -27
  370. data/spec/hamster/hash/delete_spec.rb +0 -38
  371. data/spec/hamster/hash/each_spec.rb +0 -30
  372. data/spec/hamster/hash/empty_spec.rb +0 -27
  373. data/spec/hamster/hash/eql_spec.rb +0 -70
  374. data/spec/hamster/hash/except_spec.rb +0 -22
  375. data/spec/hamster/hash/fetch_spec.rb +0 -72
  376. data/spec/hamster/hash/filter_spec.rb +0 -48
  377. data/spec/hamster/hash/find_spec.rb +0 -45
  378. data/spec/hamster/hash/get_spec.rb +0 -55
  379. data/spec/hamster/hash/has_key_spec.rb +0 -26
  380. data/spec/hamster/hash/inspect_spec.rb +0 -24
  381. data/spec/hamster/hash/map_spec.rb +0 -49
  382. data/spec/hamster/hash/merge_spec.rb +0 -30
  383. data/spec/hamster/hash/new_spec.rb +0 -21
  384. data/spec/hamster/hash/put_spec.rb +0 -67
  385. data/spec/hamster/hash/reduce_spec.rb +0 -52
  386. data/spec/hamster/hash/remove_spec.rb +0 -48
  387. data/spec/hamster/hash/slice_spec.rb +0 -26
  388. data/spec/hamster/hash/values_spec.rb +0 -29
  389. data/spec/hamster/list/add_spec.rb +0 -11
  390. data/spec/hamster/list/all_spec.rb +0 -84
  391. data/spec/hamster/list/at_spec.rb +0 -37
  392. data/spec/hamster/list/break_spec.rb +0 -73
  393. data/spec/hamster/list/combinations_spec.rb +0 -41
  394. data/spec/hamster/list/construction_spec.rb +0 -137
  395. data/spec/hamster/list/count_spec.rb +0 -52
  396. data/spec/hamster/list/cycle_spec.rb +0 -36
  397. data/spec/hamster/list/drop_while_spec.rb +0 -47
  398. data/spec/hamster/list/each_slice_spec.rb +0 -64
  399. data/spec/hamster/list/each_spec.rb +0 -56
  400. data/spec/hamster/list/each_with_index_spec.rb +0 -33
  401. data/spec/hamster/list/inits_spec.rb +0 -34
  402. data/spec/hamster/list/inspect_spec.rb +0 -33
  403. data/spec/hamster/list/join_spec.rb +0 -64
  404. data/spec/hamster/list/last_spec.rb +0 -34
  405. data/spec/hamster/list/maximum_spec.rb +0 -58
  406. data/spec/hamster/list/minimum_spec.rb +0 -58
  407. data/spec/hamster/list/partition_spec.rb +0 -63
  408. data/spec/hamster/list/product_spec.rb +0 -34
  409. data/spec/hamster/list/reduce_spec.rb +0 -72
  410. data/spec/hamster/list/slice_spec.rb +0 -40
  411. data/spec/hamster/list/span_spec.rb +0 -75
  412. data/spec/hamster/list/sum_spec.rb +0 -34
  413. data/spec/hamster/list/tail_spec.rb +0 -38
  414. data/spec/hamster/list/tails_spec.rb +0 -34
  415. data/spec/hamster/list/to_a_spec.rb +0 -42
  416. data/spec/hamster/queue/clear_spec.rb +0 -28
  417. data/spec/hamster/queue/construction_spec.rb +0 -34
  418. data/spec/hamster/queue/dequeue_spec.rb +0 -30
  419. data/spec/hamster/queue/empty_spec.rb +0 -35
  420. data/spec/hamster/queue/head_spec.rb +0 -25
  421. data/spec/hamster/queue/inspect_spec.rb +0 -23
  422. data/spec/hamster/queue/to_a_spec.rb +0 -32
  423. data/spec/hamster/queue/to_list_spec.rb +0 -34
  424. data/spec/hamster/set/add_spec.rb +0 -40
  425. data/spec/hamster/set/delete_spec.rb +0 -38
  426. data/spec/hamster/set/empty_spec.rb +0 -25
  427. data/spec/hamster/set/filter_spec.rb +0 -72
  428. data/spec/hamster/set/flatten_spec.rb +0 -47
  429. data/spec/hamster/set/group_by_spec.rb +0 -56
  430. data/spec/hamster/set/hash_spec.rb +0 -20
  431. data/spec/hamster/set/head_spec.rb +0 -28
  432. data/spec/hamster/set/include_spec.rb +0 -27
  433. data/spec/hamster/set/inspect_spec.rb +0 -24
  434. data/spec/hamster/set/intersection_spec.rb +0 -36
  435. data/spec/hamster/set/map_spec.rb +0 -49
  436. data/spec/hamster/set/new_spec.rb +0 -21
  437. data/spec/hamster/set/partition_spec.rb +0 -59
  438. data/spec/hamster/set/reduce_spec.rb +0 -62
  439. data/spec/hamster/set/remove_spec.rb +0 -48
  440. data/spec/hamster/set/subset_spec.rb +0 -31
  441. data/spec/hamster/set/superset_spec.rb +0 -31
  442. data/spec/hamster/set/to_a_spec.rb +0 -32
  443. data/spec/hamster/set/union_spec.rb +0 -35
  444. data/spec/hamster/sorter/immutable_spec.rb +0 -9
  445. data/spec/hamster/stack/clear_spec.rb +0 -28
  446. data/spec/hamster/stack/construction_spec.rb +0 -34
  447. data/spec/hamster/stack/copying_spec.rb +0 -23
  448. data/spec/hamster/stack/empty_spec.rb +0 -23
  449. data/spec/hamster/stack/eql_spec.rb +0 -48
  450. data/spec/hamster/stack/immutable_spec.rb +0 -9
  451. data/spec/hamster/stack/inspect_spec.rb +0 -23
  452. data/spec/hamster/stack/peek_spec.rb +0 -30
  453. data/spec/hamster/stack/pop_spec.rb +0 -31
  454. data/spec/hamster/stack/push_spec.rb +0 -31
  455. data/spec/hamster/stack/size_spec.rb +0 -25
  456. data/spec/hamster/stack/to_a_spec.rb +0 -32
  457. data/spec/hamster/stack/to_ary.rb +0 -37
  458. data/spec/hamster/stack/to_list_spec.rb +0 -25
  459. data/spec/hamster/trie/remove_spec.rb +0 -117
  460. data/spec/hamster/tuple/construction_spec.rb +0 -30
  461. data/spec/hamster/tuple/copying_spec.rb +0 -17
  462. data/spec/hamster/tuple/eql_spec.rb +0 -78
  463. data/spec/hamster/tuple/first_spec.rb +0 -14
  464. data/spec/hamster/tuple/immutable_spec.rb +0 -9
  465. data/spec/hamster/tuple/inspect_spec.rb +0 -14
  466. data/spec/hamster/tuple/last_spec.rb +0 -14
  467. data/spec/hamster/tuple/to_a_spec.rb +0 -30
  468. data/spec/hamster/tuple/to_ary_spec.rb +0 -37
  469. data/spec/hamster/undefined/erase_spec.rb +0 -36
  470. data/spec/hamster/vector/add_spec.rb +0 -56
  471. data/spec/hamster/vector/clear_spec.rb +0 -28
  472. data/spec/hamster/vector/each_spec.rb +0 -35
  473. data/spec/hamster/vector/each_with_index_spec.rb +0 -33
  474. data/spec/hamster/vector/empty_spec.rb +0 -32
  475. data/spec/hamster/vector/eql_spec.rb +0 -53
  476. data/spec/hamster/vector/filter_spec.rb +0 -58
  477. data/spec/hamster/vector/get_spec.rb +0 -58
  478. data/spec/hamster/vector/inspect_spec.rb +0 -33
  479. data/spec/hamster/vector/map_spec.rb +0 -57
  480. data/spec/hamster/vector/new_spec.rb +0 -48
  481. data/spec/hamster/vector/reduce_spec.rb +0 -62
  482. data/spec/lib/hamster/vector/cons_spec.rb +0 -48
@@ -1,8 +1,9 @@
1
1
  module Hamster
2
+ # @private
2
3
  class Trie
3
4
  def self.[](pairs)
4
5
  result = self.new(0)
5
- pairs.each { |key, val| result.send(:put!, key, val) }
6
+ pairs.each { |key, val| result.put!(key, val) }
6
7
  result
7
8
  end
8
9
 
@@ -27,21 +28,29 @@ module Hamster
27
28
  end
28
29
 
29
30
  # Calls <tt>block</tt> once for each entry in the trie, passing the key-value pair as parameters.
30
- def each
31
+ def each(&block)
31
32
  @entries.each { |entry| yield(entry) if entry }
32
33
  @children.each do |child|
33
- child.each { |entry| yield(entry) } if child
34
+ child.each(&block) if child
34
35
  end
35
36
  nil
36
37
  end
37
38
 
39
+ def reverse_each(&block)
40
+ @children.reverse_each do |child|
41
+ child.reverse_each(&block) if child
42
+ end
43
+ @entries.reverse_each { |entry| yield(entry) if entry }
44
+ nil
45
+ end
46
+
38
47
  def reduce(memo)
39
48
  each { |entry| memo = yield(memo, entry) }
40
49
  memo
41
50
  end
42
51
 
43
52
  def filter
44
- reduce(self) { |trie, entry| yield(entry) ? trie : trie.delete(entry.key) }
53
+ reduce(self) { |trie, entry| yield(entry) ? trie : trie.delete(entry[0]) }
45
54
  end
46
55
 
47
56
  # Returns a copy of <tt>self</tt> with the given value associated with the key.
@@ -51,13 +60,13 @@ module Hamster
51
60
 
52
61
  if !entry
53
62
  entries = @entries.dup
54
- key = key.dup.freeze if key.is_a?(String)
55
- entries[index] = Entry.new(key, value)
63
+ key = key.dup.freeze if key.is_a?(String) && !key.frozen?
64
+ entries[index] = [key, value].freeze
56
65
  Trie.new(@significant_bits, @size + 1, entries, @children)
57
- elsif entry.key.eql?(key)
66
+ elsif entry[0].eql?(key)
58
67
  entries = @entries.dup
59
- key = key.dup.freeze if key.is_a?(String)
60
- entries[index] = Entry.new(key, value)
68
+ key = key.dup.freeze if key.is_a?(String) && !key.frozen?
69
+ entries[index] = [key, value].freeze
61
70
  Trie.new(@significant_bits, @size, entries, @children)
62
71
  else
63
72
  children = @children.dup
@@ -74,11 +83,36 @@ module Hamster
74
83
  end
75
84
  end
76
85
 
86
+ # Returns <tt>self</tt> after overwriting the element associated with the specified key.
87
+ def put!(key, value)
88
+ index = index_for(key)
89
+ entry = @entries[index]
90
+ if !entry
91
+ @size += 1
92
+ key = key.dup.freeze if key.is_a?(String) && !key.frozen?
93
+ @entries[index] = [key, value].freeze
94
+ elsif entry[0].eql?(key)
95
+ key = key.dup.freeze if key.is_a?(String) && !key.frozen?
96
+ @entries[index] = [key, value].freeze
97
+ else
98
+ child = @children[index]
99
+ if child
100
+ old_child_size = child.size
101
+ @children[index] = child.put!(key, value)
102
+ @size += child.size - old_child_size
103
+ else
104
+ @children[index] = Trie.new(@significant_bits + 5).put!(key, value)
105
+ @size += 1
106
+ end
107
+ end
108
+ self
109
+ end
110
+
77
111
  # Retrieves the entry corresponding to the given key. If not found, returns <tt>nil</tt>.
78
112
  def get(key)
79
113
  index = index_for(key)
80
114
  entry = @entries[index]
81
- if entry && entry.key.eql?(key)
115
+ if entry && entry[0].eql?(key)
82
116
  entry
83
117
  else
84
118
  child = @children[index]
@@ -93,7 +127,26 @@ module Hamster
93
127
 
94
128
  def include?(key, value)
95
129
  entry = get(key)
96
- entry && value.eql?(entry.value)
130
+ entry && value.eql?(entry[1])
131
+ end
132
+
133
+ def at(index)
134
+ @entries.each do |entry|
135
+ if entry
136
+ return entry if index == 0
137
+ index -= 1
138
+ end
139
+ end
140
+ @children.each do |child|
141
+ if child
142
+ if child.size >= index+1
143
+ return child.at(index)
144
+ else
145
+ index -= child.size
146
+ end
147
+ end
148
+ end
149
+ nil
97
150
  end
98
151
 
99
152
  # Returns <tt>true</tt> if . <tt>eql?</tt> is synonymous with <tt>==</tt>
@@ -101,7 +154,7 @@ module Hamster
101
154
  return true if equal?(other)
102
155
  return false unless instance_of?(other.class) && size == other.size
103
156
  each do |entry|
104
- return false unless other.include?(entry.key, entry.value)
157
+ return false unless other.include?(entry[0], entry[1])
105
158
  end
106
159
  true
107
160
  end
@@ -109,38 +162,13 @@ module Hamster
109
162
 
110
163
  protected
111
164
 
112
- # Returns <tt>self</tt> after overwriting the element associated with the specified key.
113
- def put!(key, value)
114
- index = index_for(key)
115
- entry = @entries[index]
116
- if !entry
117
- @size += 1
118
- key = key.dup.freeze if key.is_a?(String)
119
- @entries[index] = Entry.new(key, value)
120
- elsif entry.key.eql?(key)
121
- key = key.dup.freeze if key.is_a?(String)
122
- @entries[index] = Entry.new(key, value)
123
- else
124
- child = @children[index]
125
- if child
126
- old_child_size = child.size
127
- @children[index] = child.put!(key, value)
128
- @size += child.size - old_child_size
129
- else
130
- @children[index] = Trie.new(@significant_bits + 5).put!(key, value)
131
- @size += 1
132
- end
133
- end
134
- self
135
- end
136
-
137
165
  # Returns a replacement instance after removing the specified key.
138
166
  # If not found, returns <tt>self</tt>.
139
167
  # If empty, returns <tt>nil</tt>.
140
168
  def find_and_delete(key)
141
169
  index = index_for(key)
142
170
  entry = @entries[index]
143
- if entry && entry.key.eql?(key)
171
+ if entry && entry[0].eql?(key)
144
172
  return delete_at(index)
145
173
  else
146
174
  child = @children[index]
@@ -184,16 +212,8 @@ module Hamster
184
212
  def copy_size(copy)
185
213
  copy ? copy.size : 0
186
214
  end
187
-
188
- class Entry
189
- attr_reader :key, :value
190
-
191
- def initialize(key, value)
192
- @key = key
193
- @value = value
194
- end
195
- end
196
215
  end
197
216
 
217
+ # @private
198
218
  EmptyTrie = Hamster::Trie.new(0)
199
219
  end
@@ -1,7 +1,5 @@
1
1
  module Hamster
2
+ # @private
2
3
  module Undefined
3
- def self.erase(value)
4
- value unless value.equal?(self)
5
- end
6
4
  end
7
5
  end
@@ -1,177 +1,1090 @@
1
1
  require "forwardable"
2
- require "hamster/undefined"
3
2
  require "hamster/immutable"
4
3
  require "hamster/enumerable"
5
4
 
6
5
  module Hamster
7
6
  def self.vector(*items)
8
- Vector.new(items)
7
+ items.empty? ? EmptyVector : Vector.new(items.freeze)
9
8
  end
10
9
 
10
+ # A `Vector` is an ordered, integer-indexed collection of objects. Like `Array`,
11
+ # `Vector` indexing starts at 0. Also like `Array`, negative indexes count back
12
+ # from the end of the `Vector`.
13
+ #
14
+ # `Vector`'s interface is modeled after that of `Array`, minus all the methods
15
+ # which do destructive updates. Some methods which modify `Array`s destructively
16
+ # (like {#insert} or {#delete_at}) are included, but they return new `Vectors`
17
+ # and leave the existing one unchanged.
18
+ #
19
+ # = Creating New Vectors
20
+ #
21
+ # Hamster.vector('a', 'b', 'c')
22
+ # Hamster::Vector.new([:first, :second, :third])
23
+ # Hamster::Vector[1, 2, 3, 4, 5]
24
+ #
25
+ # = Retrieving Items from Vectors
26
+ #
27
+ # require 'hamster/vector'
28
+ # vector = Hamster.vector(1, 2, 3, 4, 5)
29
+ # vector[0] # => 1
30
+ # vector[-1] # => 5
31
+ # vector[0,3] # => Hamster::Vector[1, 2, 3]
32
+ # vector[1..-1] # => Hamster::Vector[2, 3, 4, 5]
33
+ # vector.first # => 1
34
+ # vector.last # => 5
35
+ #
36
+ # = Creating Modified Vectors
37
+ #
38
+ # vector.add(6) # => Hamster::Vector[1, 2, 3, 4, 5, 6]
39
+ # vector.insert(1, :a, :b) # => Hamster::Vector[1, :a, :b, 2, 3, 4, 5]
40
+ # vector.delete_at(2) # => Hamster::Vector[1, 2, 4, 5]
41
+ # vector + [6, 7] # => Hamster::Vector[1, 2, 3, 4, 5, 6, 7]
42
+ #
43
+ # Other `Array`-like methods like {#select}, {#map}, {#shuffle}, {#uniq}, {#reverse},
44
+ # {#rotate}, {#flatten}, {#sort}, {#sort_by}, {#take}, {#drop}, {#take_while},
45
+ # {#drop_while}, {#fill}, {#product}, and {#transpose} are also supported.
46
+ #
11
47
  class Vector
12
48
  extend Forwardable
13
49
  include Immutable
14
50
  include Enumerable
15
51
 
52
+ # @private
16
53
  BLOCK_SIZE = 32
54
+ # @private
17
55
  INDEX_MASK = BLOCK_SIZE - 1
56
+ # @private
18
57
  BITS_PER_LEVEL = 5
19
58
 
59
+ # Return the number of items in this `Vector`
60
+ # @return [Integer]
20
61
  attr_reader :size
21
62
  def_delegator :self, :size, :length
22
63
 
23
64
  class << self
24
- alias :alloc :new
25
-
26
- def new(items=[])
27
- items.empty? ? empty : alloc(items)
28
- end
29
-
65
+ # Create a new `Vector` populated with the given items.
66
+ # @return [Vector]
30
67
  def [](*items)
31
- new(items)
68
+ new(items.freeze)
32
69
  end
33
70
 
71
+ # Return an empty `Vector`. If used on a subclass, returns an empty instance
72
+ # of that class.
73
+ #
74
+ # @return [Vector]
34
75
  def empty
35
- @empty ||= self.alloc
76
+ @empty ||= self.new
77
+ end
78
+
79
+ # "Raw" allocation of a new `Vector`. Used internally to create a new
80
+ # instance quickly after building a modified trie.
81
+ #
82
+ # @return [Vector]
83
+ # @private
84
+ def alloc(root, size, levels)
85
+ obj = allocate
86
+ obj.instance_variable_set(:@root, root)
87
+ obj.instance_variable_set(:@size, size)
88
+ obj.instance_variable_set(:@levels, levels)
89
+ obj
36
90
  end
37
91
  end
38
92
 
39
- def initialize(items=[])
40
- @root = items
41
- @size = items.size
42
- @levels = 0
43
- while @root.size > 32
44
- @root = @root.each_slice(32).to_a
45
- @levels += 1
93
+ def initialize(items=[].freeze)
94
+ items = items.to_a
95
+ if items.size <= 32
96
+ items = items.dup.freeze if !items.frozen?
97
+ @root, @size, @levels = items, items.size, 0
98
+ else
99
+ root, size, levels = items, items.size, 0
100
+ while root.size > 32
101
+ root = root.each_slice(32).to_a
102
+ levels += 1
103
+ end
104
+ @root, @size, @levels = root.freeze, size, levels
46
105
  end
47
106
  end
48
107
 
108
+ # Return `true` if this `Vector` contains no items.
109
+ #
110
+ # @return [Boolean]
49
111
  def empty?
50
112
  @size == 0
51
113
  end
52
114
  def_delegator :self, :empty?, :null?
53
115
 
116
+ # Return the first item in the `Vector`. If the vector is empty, return `nil`.
117
+ #
118
+ # @return [Object]
54
119
  def first
55
120
  get(0)
56
121
  end
57
122
  def_delegator :self, :first, :head
58
123
 
124
+ # Return the last item in the `Vector`. If the vector is empty, return `nil`.
125
+ #
126
+ # @return [Object]
59
127
  def last
60
128
  get(-1)
61
129
  end
62
130
 
131
+ # Return a new `Vector` with `item` added after the last occupied position.
132
+ #
133
+ # @param item [Object] The object to insert at the end of the vector
134
+ # @return [Vector]
63
135
  def add(item)
64
- transform do
65
- update_leaf_node(@size, item)
66
- @size += 1
67
- end
136
+ update_root(@size, item)
68
137
  end
69
138
  def_delegator :self, :add, :<<
70
- def_delegator :self, :add, :cons
71
139
  def_delegator :self, :add, :conj
72
140
  def_delegator :self, :add, :conjoin
141
+ def_delegator :self, :add, :push
73
142
 
74
- # def delete(index)
75
- # end
76
-
77
- def set(index, item = Undefined)
78
- return set(index, yield(get(index))) if item.equal?(Undefined)
79
- raise IndexError if empty? || index == @size
80
- raise IndexError if index.abs > @size
81
- return set(@size + index, item) if index < 0
82
- transform do
83
- update_leaf_node(index, item)
84
- end
143
+ # Return a new `Vector` with the item at `index` replaced by `item`. If the
144
+ # `item` argument is missing, but an optional code block is provided, it will
145
+ # be passed the existing item and what the block returns will replace it.
146
+ #
147
+ # @param index [Integer] The index to update
148
+ # @param item [Object] The object to insert into that position
149
+ # @return [Vector]
150
+ def set(index, item = yield(get(index)))
151
+ raise IndexError if @size == 0
152
+ index += @size if index < 0
153
+ raise IndexError if index > @size || index < 0
154
+ update_root(index, item)
85
155
  end
86
156
 
157
+ # Retrieve the item at `index`. If there is none (either the provided index
158
+ # is too high or too low), return `nil`.
159
+ #
160
+ # @param index [Integer] The index to retrieve
161
+ # @return [Object]
87
162
  def get(index)
88
- return nil if empty? || index == @size
89
- return nil if index.abs > @size
90
- return get(@size + index) if index < 0
91
- leaf_node_for(@root, root_index_bits, index)[index & INDEX_MASK]
163
+ return nil if @size == 0
164
+ index += @size if index < 0
165
+ return nil if index >= @size || index < 0
166
+ leaf_node_for(@root, @levels * BITS_PER_LEVEL, index)[index & INDEX_MASK]
92
167
  end
93
- def_delegator :self, :get, :[]
94
168
  def_delegator :self, :get, :at
95
169
 
170
+ # Retrieve the value at `index`, or use the provided default value or block,
171
+ # or otherwise raise an `IndexError`.
172
+ #
173
+ # @overload fetch(index)
174
+ # Retrieve the value at the given index, or raise an `IndexError` if it is
175
+ # not found.
176
+ # @param index [Integer] The index to look up
177
+ # @overload fetch(index) { |index| ... }
178
+ # Retrieve the value at the given index, or call the optional
179
+ # code block (with the non-existent index) and get its return value.
180
+ # @yield [index] The index which does not exist
181
+ # @yieldreturn [Object] Object to return instead
182
+ # @param index [Integer] The index to look up
183
+ # @overload fetch(index, default)
184
+ # Retrieve the value at the given index, or else return the provided
185
+ # `default` value.
186
+ # @param index [Integer] The index to look up
187
+ # @param default [Object] Object to return if the key is not found
188
+ #
189
+ # @return [Object]
190
+ def fetch(index, default = (missing_default = true))
191
+ if index >= -@size && index < @size
192
+ get(index)
193
+ elsif block_given?
194
+ yield(index)
195
+ elsif !missing_default
196
+ default
197
+ else
198
+ raise IndexError, "index #{index} outside of vector bounds"
199
+ end
200
+ end
201
+
202
+ # Element reference. Return the item at a specific index, or a specified,
203
+ # contiguous range of items (as a new `Vector`).
204
+ #
205
+ # @overload vector[index]
206
+ # Return the item at `index`.
207
+ # @param index [Integer] The index to retrieve.
208
+ # @overload vector[start, length]
209
+ # Return a subvector starting at index `start` and continuing for `length` elements.
210
+ # @param start [Integer] The index to start retrieving items from.
211
+ # @param length [Integer] The number of items to retrieve.
212
+ # @overload vector[range]
213
+ # Return a subvector specified by the given `range` of indices.
214
+ # @param range [Range] The range of indices to retrieve.
215
+ #
216
+ # @return [Object]
217
+ def [](arg, length = (missing_length = true))
218
+ if missing_length
219
+ if arg.is_a?(Range)
220
+ from, to = arg.begin, arg.end
221
+ from += @size if from < 0
222
+ to += @size if to < 0
223
+ to += 1 if !arg.exclude_end?
224
+ length = to - from
225
+ length = 0 if length < 0
226
+ subsequence(from, length)
227
+ else
228
+ get(arg)
229
+ end
230
+ else
231
+ arg += @size if arg < 0
232
+ subsequence(arg, length)
233
+ end
234
+ end
235
+ def_delegator :self, :[], :slice
236
+
237
+ # Return a new `Vector` with the given values inserted before the element at `index`.
238
+ #
239
+ # @param index [Integer] The index where the new items should go
240
+ # @param items [Array] The items to add
241
+ # @return [Vector]
242
+ def insert(index, *items)
243
+ raise IndexError if index < -@size
244
+ index += @size if index < 0
245
+
246
+ if index < @size
247
+ suffix = flatten_suffix(@root, @levels * BITS_PER_LEVEL, index, [])
248
+ suffix.unshift(*items)
249
+ elsif index == @size
250
+ suffix = items
251
+ else
252
+ suffix = Array.new(index - @size, nil).concat(items)
253
+ index = @size
254
+ end
255
+
256
+ replace_suffix(index, suffix)
257
+ end
258
+
259
+ # Return a new `Vector` with the element at `index` removed. If the given `index`
260
+ # does not exist, return `self`.
261
+ #
262
+ # @param index [Integer] The index to remove
263
+ # @return [Vector]
264
+ def delete_at(index)
265
+ return self if index >= @size || index < -@size
266
+ index += @size if index < 0
267
+
268
+ suffix = flatten_suffix(@root, @levels * BITS_PER_LEVEL, index, [])
269
+ replace_suffix(index, suffix.tap { |a| a.shift })
270
+ end
271
+
272
+ # Return a new `Vector` with the last element removed. If empty, just return `self`.
273
+ # @return [Vector]
274
+ def pop
275
+ return self if @size == 0
276
+ replace_suffix(@size-1, [])
277
+ end
278
+
279
+ # Return a new `Vector` with `obj` inserted before the first element, moving
280
+ # the other elements upwards.
281
+ # @param obj [Object] The value to prepend
282
+ # @return [Vector]
283
+ def unshift(obj)
284
+ insert(0, obj)
285
+ end
286
+
287
+ # Return a new `Vector` with the first element removed. If empty, just return `self`.
288
+ # @return [Vector]
289
+ def shift
290
+ delete_at(0)
291
+ end
292
+
293
+ # Call the given block once for each item in the vector, passing each
294
+ # item from first to last successively to the block.
295
+ #
296
+ # @return [self]
96
297
  def each(&block)
97
- return self unless block_given?
98
- traverse_depth_first(&block)
99
- nil
298
+ return to_enum unless block_given?
299
+ traverse_depth_first(@root, @levels, &block)
300
+ self
100
301
  end
101
302
 
102
- def map(&block)
103
- return self unless block_given?
104
- reduce(self.class.empty) { |vector, item| vector.add(yield(item)) }
303
+ # Call the given block once for each item in the vector, passing each
304
+ # item starting from the last, and counting back to the first, successively to
305
+ # the block.
306
+ #
307
+ # @return [self]
308
+ def reverse_each(&block)
309
+ return enum_for(:reverse_each) unless block_given?
310
+ reverse_traverse_depth_first(@root, @levels, &block)
311
+ self
105
312
  end
106
- def_delegator :self, :map, :collect
107
313
 
314
+ # Return a new `Vector` containing all elements for which the given block returns
315
+ # true.
316
+ #
317
+ # @return [Vector]
108
318
  def filter
109
- return self unless block_given?
319
+ return enum_for(:filter) unless block_given?
110
320
  reduce(self.class.empty) { |vector, item| yield(item) ? vector.add(item) : vector }
111
321
  end
112
322
 
323
+ # Return a new `Vector` with all items which are equal to `obj` removed.
324
+ # `#==` is used for checking equality.
325
+ #
326
+ # @param obj [Object] The object to remove (every occurrence)
327
+ # @return [Vector]
328
+ def delete(obj)
329
+ filter { |item| item != obj }
330
+ end
331
+
332
+ # Invoke the given block once for each item in the vector, and return a new
333
+ # `Vector` containing the values returned by the block.
334
+ #
335
+ # @return [Vector]
336
+ def map
337
+ return enum_for(:map) if not block_given?
338
+ return self if empty?
339
+ self.class.new(super)
340
+ end
341
+ def_delegator :self, :map, :collect
342
+
343
+ # Return a new `Vector` with the same elements as this one, but randomly permuted.
344
+ #
345
+ # @return [Vector]
346
+ def shuffle
347
+ self.class.new(((array = to_a).frozen? ? array.shuffle : array.shuffle!).freeze)
348
+ end
349
+
350
+ # Return a new `Vector` with no duplicate elements, as determined by `#hash` and
351
+ # `#eql?`. For each group of equivalent elements, only the first will be retained.
352
+ #
353
+ # @return [Vector]
354
+ def uniq
355
+ self.class.new(((array = to_a).frozen? ? array.uniq : array.uniq!).freeze)
356
+ end
357
+
358
+ # Return a new `Vector` with the same elements as this one, but in reverse order.
359
+ #
360
+ # @return [Vector]
361
+ def reverse
362
+ self.class.new(((array = to_a).frozen? ? array.reverse : array.reverse!).freeze)
363
+ end
364
+
365
+ # Return a new `Vector` with the same elements, but rotated so that the one at
366
+ # index `count` is the first element of the new vector. If `count` is positive,
367
+ # the elements will be shifted left, and those shifted past the lowest position
368
+ # will be moved to the end. If `count` is negative, the elements will be shifted
369
+ # right, and those shifted past the last position will be moved to the beginning.
370
+ #
371
+ # @param count [Integer] The number of positions to shift items by
372
+ # @return [Vector]
373
+ def rotate(count = 1)
374
+ return self if (count % @size) == 0
375
+ self.class.new(((array = to_a).frozen? ? array.rotate(count) : array.rotate!(count)).freeze)
376
+ end
377
+
378
+ # Return a new `Vector` with all nested vectors and arrays recursively "flattened
379
+ # out", that is, their elements inserted into the new `Vector` in the place where
380
+ # the nested array/vector originally was. If an optional `level` argument is
381
+ # provided, the flattening will only be done recursively that number of times.
382
+ # A `level` of 0 means not to flatten at all, 1 means to only flatten nested
383
+ # arrays/vectors which are directly contained within this `Vector`.
384
+ #
385
+ # @param level [Integer] The depth to which flattening should be applied
386
+ # @return [Vector]
387
+ def flatten(level = nil)
388
+ return self if level == 0
389
+ self.class.new(((array = to_a).frozen? ? array.flatten(level) : array.flatten!(level)).freeze)
390
+ end
391
+
392
+ # Return a new `Vector` built by concatenating this one with `other`. `other`
393
+ # can be any object which is convertible to an `Array` using `#to_a`.
394
+ #
395
+ # @param other [Enumerable] The collection to concatenate onto this vector
396
+ # @return [Vector]
397
+ def +(other)
398
+ other = other.to_a
399
+ other = other.dup if other.frozen?
400
+ replace_suffix(@size, other)
401
+ end
402
+ def_delegator :self, :+, :concat
403
+
404
+ # `others` should be arrays and/or vectors. The corresponding elements from this
405
+ # `Vector` and each of `others` (that is, the elements with the same indices)
406
+ # will be gathered into arrays.
407
+ #
408
+ # If an optional block is provided, each such array will be passed successively
409
+ # to the block. Otherwise, a new `Vector` of all those arrays will be returned.
410
+ #
411
+ # @param others [Array] The arrays/vectors to zip together with this one
412
+ # @return [Vector, nil]
413
+ def zip(*others)
414
+ if block_given?
415
+ super
416
+ else
417
+ self.class.new(super)
418
+ end
419
+ end
420
+
421
+ # Return a new `Vector` with the same items, but sorted. The sort order will
422
+ # be determined by comparing items using `#<=>`, or if an optional code block
423
+ # is provided, by using it as a comparator. The block should accept 2 parameters,
424
+ # and should return 0, 1, or -1 if the first parameter is equal to, greater than,
425
+ # or less than the second parameter (respectively).
426
+ #
427
+ # @return [Vector]
428
+ def sort
429
+ self.class.new(super)
430
+ end
431
+
432
+ # Return a new `Vector` with the same items, but sorted. The sort order will be
433
+ # determined by mapping the items through the given block to obtain sort keys,
434
+ # and then sorting the keys according to their natural sort order.
435
+ #
436
+ # @return [Vector]
437
+ def sort_by
438
+ self.class.new(super)
439
+ end
440
+
441
+ # Drop the first `n` elements and return the rest in a new `Vector`.
442
+ # @param n [Integer] The number of elements to remove
443
+ # @return [Vector]
444
+ def drop(n)
445
+ self.class.new(super)
446
+ end
447
+
448
+ # Return only the first `n` elements in a new `Vector`.
449
+ # @param n [Integer] The number of elements to retain
450
+ # @return [Vector]
451
+ def take(n)
452
+ self.class.new(super)
453
+ end
454
+
455
+ # Drop elements up to, but not including, the first element for which the
456
+ # block returns `nil` or `false`. Gather the remaining elements into a new
457
+ # `Vector`. If no block is given, an `Enumerator` is returned instead.
458
+ #
459
+ # @return [Vector, Enumerator]
460
+ def drop_while
461
+ return enum_for(:drop_while) if not block_given?
462
+ self.class.new(super)
463
+ end
464
+
465
+ # Gather elements up to, but not including, the first element for which the
466
+ # block returns `nil` or `false`, and return them in a new `Vector`. If no block
467
+ # is given, an `Enumerator` is returned instead.
468
+ #
469
+ # @return [Vector, Enumerator]
470
+ def take_while
471
+ return enum_for(:take_while) if not block_given?
472
+ self.class.new(super)
473
+ end
474
+
475
+ # Repetition. Return a new `Vector` built by concatenating `times` copies
476
+ # of this one together.
477
+ #
478
+ # @param times [Integer] The number of times to repeat the elements in this vector
479
+ # @return [Vector]
480
+ def *(times)
481
+ return self.class.empty if times == 0
482
+ return self if times == 1
483
+ result = (to_a * times)
484
+ result.is_a?(Array) ? self.class.new(result) : result
485
+ end
486
+
487
+ # Replace a range of indexes with the given object.
488
+ #
489
+ # @overload fill(obj)
490
+ # Return a new `Vector` of the same size, with every index set to `obj`.
491
+ # @overload fill(obj, start)
492
+ # Return a new `Vector` with all indexes from `start` to the end of the
493
+ # vector set to `obj`.
494
+ # @overload fill(obj, start, length)
495
+ # Return a new `Vector` with `length` indexes, beginning from `start`,
496
+ # set to `obj`.
497
+ #
498
+ # @return [Vector]
499
+ def fill(obj, index = 0, length = nil)
500
+ raise IndexError if index < -@size
501
+ index += @size if index < 0
502
+ length ||= @size - index # to the end of the array, if no length given
503
+
504
+ if index < @size
505
+ suffix = flatten_suffix(@root, @levels * BITS_PER_LEVEL, index, [])
506
+ suffix.fill(obj, 0, length)
507
+ elsif index == @size
508
+ suffix = Array.new(length, obj)
509
+ else
510
+ suffix = Array.new(index - @size, nil).concat(Array.new(length, obj))
511
+ index = @size
512
+ end
513
+
514
+ replace_suffix(index, suffix)
515
+ end
516
+
517
+ # When invoked with a block, yields all combinations of length `n` of items
518
+ # from the `Vector`, and then returns `self`. There is no guarantee about
519
+ # which order the combinations will be yielded in.
520
+ #
521
+ # If no block is given, an `Enumerator` is returned instead.
522
+ #
523
+ # @return [self, Enumerator]
524
+ def combination(n)
525
+ return enum_for(:combination, n) if not block_given?
526
+ return self if n < 0 || @size < n
527
+ if n == 0
528
+ yield []
529
+ elsif n == 1
530
+ each { |item| yield [item] }
531
+ elsif n == @size
532
+ yield self.to_a
533
+ else
534
+ combos = lambda do |result,index,remaining|
535
+ while @size - index > remaining
536
+ if remaining == 1
537
+ yield result.dup << get(index)
538
+ else
539
+ combos[result.dup << get(index), index+1, remaining-1]
540
+ end
541
+ index += 1
542
+ end
543
+ index.upto(@size-1) { |i| result << get(i) }
544
+ yield result
545
+ end
546
+ combos[[], 0, n]
547
+ end
548
+ self
549
+ end
550
+
551
+ # When invoked with a block, yields all repeated combinations of length `n` of
552
+ # items from the `Vector`, and then returns `self`. A "repeated combination" is
553
+ # one in which any item from the `Vector` can appear consecutively any number of
554
+ # times.
555
+ #
556
+ # There is no guarantee about which order the combinations will be yielded in.
557
+ #
558
+ # If no block is given, an `Enumerator` is returned instead.
559
+ #
560
+ # @return [self, Enumerator]
561
+ def repeated_combination(n)
562
+ return enum_for(:repeated_combination, n) if not block_given?
563
+ if n < 0
564
+ # yield nothing
565
+ elsif n == 0
566
+ yield []
567
+ elsif n == 1
568
+ each { |item| yield [item] }
569
+ elsif @size == 0
570
+ # yield nothing
571
+ else
572
+ combos = lambda do |result,index,remaining|
573
+ while index < @size-1
574
+ if remaining == 1
575
+ yield result.dup << get(index)
576
+ else
577
+ combos[result.dup << get(index), index, remaining-1]
578
+ end
579
+ index += 1
580
+ end
581
+ item = get(index)
582
+ remaining.times { result << item }
583
+ yield result
584
+ end
585
+ combos[[], 0, n]
586
+ end
587
+ self
588
+ end
589
+
590
+ # Yields all permutations of length `n` of items from the `Vector`, and then
591
+ # returns `self`. If no length `n` is specified, permutations of all elements
592
+ # will be yielded.
593
+ #
594
+ # There is no guarantee about which order the permutations will be yielded in.
595
+ #
596
+ # If no block is given, an `Enumerator` is returned instead.
597
+ #
598
+ # @return [self, Enumerator]
599
+ def permutation(n = @size)
600
+ return enum_for(:permutation, n) if not block_given?
601
+ if n < 0 || @size < n
602
+ # yield nothing
603
+ elsif n == 0
604
+ yield []
605
+ elsif n == 1
606
+ each { |item| yield [item] }
607
+ else
608
+ used, result = [], []
609
+ perms = lambda do |index|
610
+ 0.upto(@size-1) do |i|
611
+ if !used[i]
612
+ result[index] = get(i)
613
+ if index < n-1
614
+ used[i] = true
615
+ perms[index+1]
616
+ used[i] = false
617
+ else
618
+ yield result.dup
619
+ end
620
+ end
621
+ end
622
+ end
623
+ perms[0]
624
+ end
625
+ self
626
+ end
627
+
628
+ # When invoked with a block, yields all repeated permutations of length `n` of
629
+ # items from the `Vector`, and then returns `self`. A "repeated permutation" is
630
+ # one where any item from the `Vector` can appear any number of times, and in
631
+ # any position (not just consecutively)
632
+ #
633
+ # If no length `n` is specified, permutations of all elements will be yielded.
634
+ # There is no guarantee about which order the permutations will be yielded in.
635
+ #
636
+ # If no block is given, an `Enumerator` is returned instead.
637
+ #
638
+ # @return [self, Enumerator]
639
+ def repeated_permutation(n = @size)
640
+ return enum_for(:repeated_permutation, n) if not block_given?
641
+ if n < 0
642
+ # yield nothing
643
+ elsif n == 0
644
+ yield []
645
+ elsif n == 1
646
+ each { |item| yield [item] }
647
+ else
648
+ result = []
649
+ perms = lambda do |index|
650
+ 0.upto(@size-1) do |i|
651
+ result[index] = get(i)
652
+ if index < n-1
653
+ perms[index+1]
654
+ else
655
+ yield result.dup
656
+ end
657
+ end
658
+ end
659
+ perms[0]
660
+ end
661
+ self
662
+ end
663
+
664
+ # With one or more vector or array arguments, return the cartesian product of
665
+ # this vector's elements and those of each argument; with no arguments, return the
666
+ # result of multiplying all this vector's items together.
667
+ #
668
+ # @overload product(*vectors)
669
+ # Return a `Vector` of all combinations of elements from this `Vector` and each
670
+ # of the given vectors or arrays. The length of the returned `Vector` is the product
671
+ # of `self.size` and the size of each argument vector or array.
672
+ # @overload product
673
+ # Return the result of multiplying all the items in this `Vector` together.
674
+ #
675
+ # @return [Vector]
676
+ def product(*vectors)
677
+ # if no vectors passed, return "product" as in result of multiplying all items
678
+ return super if vectors.empty?
679
+
680
+ vectors.unshift(self)
681
+
682
+ if vectors.any?(&:empty?)
683
+ return block_given? ? self : []
684
+ end
685
+
686
+ counters = Array.new(vectors.size, 0)
687
+
688
+ bump_counters = lambda do
689
+ i = vectors.size-1
690
+ counters[i] += 1
691
+ while counters[i] == vectors[i].size
692
+ counters[i] = 0
693
+ i -= 1
694
+ return true if i == -1 # we are done
695
+ counters[i] += 1
696
+ end
697
+ false # not done yet
698
+ end
699
+ build_array = lambda do
700
+ array = []
701
+ counters.each_with_index { |index,i| array << vectors[i][index] }
702
+ array
703
+ end
704
+
705
+ if block_given?
706
+ while true
707
+ yield build_array[]
708
+ return self if bump_counters[]
709
+ end
710
+ else
711
+ result = []
712
+ while true
713
+ result << build_array[]
714
+ return result if bump_counters[]
715
+ end
716
+ end
717
+ end
718
+
719
+ # Assume all elements are vectors or arrays and transpose the rows and columns.
720
+ # In other words, take the first element of each nested vector/array and gather
721
+ # them together into a new `Vector`. Do likewise for the second, third, and so on
722
+ # down to the end of each nested vector/array. Gather all the resulting `Vectors`
723
+ # into a new `Vector` and return it.
724
+ #
725
+ # This operation is closely related to {#zip}. The result is almost the same as
726
+ # calling {#zip} on the first nested vector/array with the others supplied as
727
+ # arguments.
728
+ #
729
+ # @return [Vector]
730
+ def transpose
731
+ return self.class.empty if empty?
732
+ result = Array.new(first.size) { [] }
733
+
734
+ 0.upto(@size-1) do |i|
735
+ source = get(i)
736
+ if source.size != result.size
737
+ raise IndexError, "element size differs (#{source.size} should be #{result.size})"
738
+ end
739
+
740
+ 0.upto(result.size-1) do |j|
741
+ result[j].push(source[j])
742
+ end
743
+ end
744
+
745
+ result.map! { |a| self.class.new(a) }
746
+ self.class.new(result)
747
+ end
748
+
749
+ # By using binary search, finds a value from this `Vector` which meets the
750
+ # condition defined by the provided block. Behavior is just like `Array#bsearch`.
751
+ # See `Array#bsearch` for details.
752
+ #
753
+ # @return [Object]
754
+ def bsearch
755
+ low, high, result = 0, @size, nil
756
+ while low < high
757
+ mid = (low + ((high - low) >> 1))
758
+ val = get(mid)
759
+ v = yield val
760
+ if v.is_a? Numeric
761
+ if v == 0
762
+ return val
763
+ elsif v > 0
764
+ high = mid
765
+ else
766
+ low = mid + 1
767
+ end
768
+ elsif v == true
769
+ result = val
770
+ high = mid
771
+ elsif !v
772
+ low = mid + 1
773
+ else
774
+ raise TypeError, "wrong argument type #{v.class} (must be numeric, true, false, or nil)"
775
+ end
776
+ end
777
+ result
778
+ end
779
+
780
+ # Return an empty `Vector` instance, of the same class as this one. Useful if you
781
+ # have multiple subclasses of `Vector` and want to treat them polymorphically.
782
+ #
783
+ # @return [Vector]
113
784
  def clear
114
- EmptyVector
785
+ self.class.empty
786
+ end
787
+
788
+ # Return a randomly chosen item from this `Vector`. If the vector is empty, return `nil`.
789
+ #
790
+ # @return [Object]
791
+ def sample
792
+ get(rand(@size))
793
+ end
794
+
795
+ # Return a new `Vector` with only the elements at the given `indices`, in the
796
+ # order specified by `indices`. If any of the `indices` do not exist, `nil`s will
797
+ # appear in their places.
798
+ #
799
+ # @param indices [Array] The indices to retrieve and gather into a new `Vector`
800
+ # @return [Vector]
801
+ def values_at(*indices)
802
+ self.class.new(indices.map { |i| get(i) }.freeze)
803
+ end
804
+
805
+ # Return the index of the last element which is equal to the provided object,
806
+ # or for which the provided block returns true.
807
+ #
808
+ # @overload rindex(obj)
809
+ # Return the index of the last element in this `Vector` which is `#==` to `obj`.
810
+ # @overload rindex { |item| ... }
811
+ # Return the index of the last element in this `Vector` for which the block
812
+ # returns true. (Iteration starts from the last element, counts back, and
813
+ # stops as soon as a matching element is found.)
814
+ #
815
+ # @return [Index]
816
+ def rindex(obj = (missing_arg = true))
817
+ i = @size - 1
818
+ if missing_arg
819
+ if block_given?
820
+ reverse_each { |item| return i if yield item; i -= 1 }
821
+ nil
822
+ else
823
+ enum_for(:rindex)
824
+ end
825
+ else
826
+ reverse_each { |item| return i if item == obj; i -= 1 }
827
+ nil
828
+ end
115
829
  end
116
830
 
117
- def inspect
118
- to_a.inspect
831
+ # Assumes all elements are nested, indexable collections, and searches through them,
832
+ # comparing `obj` with the first element of each nested collection. Return the
833
+ # first nested collection which matches, or `nil` if none is found.
834
+ #
835
+ # @param obj [Object] The object to search for
836
+ # @return [Object]
837
+ def assoc(obj)
838
+ each { |array| return array if obj == array[0] }
839
+ nil
119
840
  end
120
841
 
842
+ # Assumes all elements are nested, indexable collections, and searches through them,
843
+ # comparing `obj` with the second element of each nested collection. Return the
844
+ # first nested collection which matches, or `nil` if none is found.
845
+ #
846
+ # @param obj [Object] The object to search for
847
+ # @return [Object]
848
+ def rassoc(obj)
849
+ each { |array| return array if obj == array[1] }
850
+ nil
851
+ end
852
+
853
+ # Return an `Array` with the same elements, in the same order. The returned
854
+ # `Array` may or may not be frozen.
855
+ #
856
+ # @return [Array]
857
+ def to_a
858
+ if @levels == 0
859
+ @root
860
+ else
861
+ flatten_node(@root, @levels * BITS_PER_LEVEL, [])
862
+ end
863
+ end
864
+
865
+ # Return true if `other` has the same type and contents as this `Vector`.
866
+ #
867
+ # @param other [Object] The collection to compare with
868
+ # @return [Boolean]
121
869
  def eql?(other)
122
870
  return true if other.equal?(self)
123
871
  return false unless instance_of?(other.class) && @size == other.size
124
872
  @root.eql?(other.instance_variable_get(:@root))
125
873
  end
126
- def_delegator :self, :eql?, :==
874
+
875
+ # See `Object#hash`.
876
+ # @return [Integer]
877
+ def hash
878
+ reduce(0) { |hash, item| (hash << 5) - hash + item.hash }
879
+ end
880
+
881
+ # @return [::Array]
882
+ # @private
883
+ def marshal_dump
884
+ to_a
885
+ end
886
+
887
+ # @private
888
+ def marshal_load(array)
889
+ initialize(array.freeze)
890
+ end
127
891
 
128
892
  private
129
893
 
130
- def traverse_depth_first(node = @root, level = @levels, &block)
894
+ def traverse_depth_first(node, level, &block)
131
895
  return node.each(&block) if level == 0
132
896
  node.each { |child| traverse_depth_first(child, level - 1, &block) }
133
897
  end
134
898
 
135
- def leaf_node_for(node, child_index_bits, index)
136
- return node if child_index_bits == 0
137
- child_index = (index >> child_index_bits) & INDEX_MASK
138
- leaf_node_for(node[child_index], child_index_bits - BITS_PER_LEVEL, index)
899
+ def reverse_traverse_depth_first(node, level, &block)
900
+ return node.reverse_each(&block) if level == 0
901
+ node.reverse_each { |child| reverse_traverse_depth_first(child, level - 1, &block) }
902
+ end
903
+
904
+ def leaf_node_for(node, bitshift, index)
905
+ while bitshift > 0
906
+ node = node[(index >> bitshift) & INDEX_MASK]
907
+ bitshift -= BITS_PER_LEVEL
908
+ end
909
+ node
910
+ end
911
+
912
+ def update_root(index, item)
913
+ root, levels = @root, @levels
914
+ while index >= (1 << (BITS_PER_LEVEL * (levels + 1)))
915
+ root = [root].freeze
916
+ levels += 1
917
+ end
918
+ root = update_leaf_node(root, levels * BITS_PER_LEVEL, index, item)
919
+ self.class.alloc(root, @size > index ? @size : index + 1, levels)
920
+ end
921
+
922
+ def update_leaf_node(node, bitshift, index, item)
923
+ slot_index = (index >> bitshift) & INDEX_MASK
924
+ if bitshift > 0
925
+ old_child = node[slot_index] || []
926
+ item = update_leaf_node(old_child, bitshift - BITS_PER_LEVEL, index, item)
927
+ end
928
+ node.dup.tap { |n| n[slot_index] = item }.freeze
139
929
  end
140
930
 
141
- def update_leaf_node(index, item)
142
- copy_leaf_node_for(new_root, root_index_bits, index)[index & INDEX_MASK] = item
931
+ def flatten_range(node, bitshift, from, to)
932
+ from_slot = (from >> bitshift) & INDEX_MASK
933
+ to_slot = (to >> bitshift) & INDEX_MASK
934
+
935
+ if bitshift == 0 # are we at the bottom?
936
+ node.slice(from_slot, to_slot-from_slot+1)
937
+ elsif from_slot == to_slot
938
+ flatten_range(node[from_slot], bitshift - BITS_PER_LEVEL, from, to)
939
+ else
940
+ # the following bitmask can be used to pick out the part of the from/to indices
941
+ # which will be used to direct path BELOW this node
942
+ mask = ((1 << bitshift) - 1)
943
+ result = []
944
+
945
+ if from & mask == 0
946
+ flatten_node(node[from_slot], bitshift - BITS_PER_LEVEL, result)
947
+ else
948
+ result.concat(flatten_range(node[from_slot], bitshift - BITS_PER_LEVEL, from, from | mask))
949
+ end
950
+
951
+ (from_slot+1).upto(to_slot-1) do |slot_index|
952
+ flatten_node(node[slot_index], bitshift - BITS_PER_LEVEL, result)
953
+ end
954
+
955
+ if to & mask == mask
956
+ flatten_node(node[to_slot], bitshift - BITS_PER_LEVEL, result)
957
+ else
958
+ result.concat(flatten_range(node[to_slot], bitshift - BITS_PER_LEVEL, to & ~mask, to))
959
+ end
960
+
961
+ result
962
+ end
143
963
  end
144
964
 
145
- def copy_leaf_node_for(node, child_index_bits, index)
146
- return node if child_index_bits == 0
147
- child_index = (index >> child_index_bits) & INDEX_MASK
148
- child_node = node[child_index]
149
- if child_node
150
- child_node = child_node.dup
965
+ def flatten_node(node, bitshift, result)
966
+ if bitshift == 0
967
+ result.concat(node)
968
+ elsif bitshift == BITS_PER_LEVEL
969
+ node.each { |a| result.concat(a) }
151
970
  else
152
- child_node = []
971
+ bitshift -= BITS_PER_LEVEL
972
+ node.each { |a| flatten_node(a, bitshift, result) }
153
973
  end
154
- node[child_index] = child_node
155
- copy_leaf_node_for(child_node, child_index_bits - BITS_PER_LEVEL, index)
974
+ result
156
975
  end
157
976
 
158
- def new_root
159
- if full?
160
- @levels += 1
161
- @root = [@root]
977
+ def subsequence(from, length)
978
+ return nil if from > @size || from < 0 || length < 0
979
+ length = @size - from if @size < from + length
980
+ return self.class.empty if length == 0
981
+ self.class.new(flatten_range(@root, @levels * BITS_PER_LEVEL, from, from + length - 1))
982
+ end
983
+
984
+ def flatten_suffix(node, bitshift, from, result)
985
+ from_slot = (from >> bitshift) & INDEX_MASK
986
+
987
+ if bitshift == 0
988
+ if from_slot == 0
989
+ result.concat(node)
990
+ else
991
+ result.concat(node.slice(from_slot, 32)) # entire suffix of node. excess length is ignored by #slice
992
+ end
162
993
  else
163
- @root = @root.dup
994
+ mask = ((1 << bitshift) - 1)
995
+ if from & mask == 0
996
+ from_slot.upto(node.size-1) do |i|
997
+ flatten_node(node[i], bitshift - BITS_PER_LEVEL, result)
998
+ end
999
+ elsif child = node[from_slot]
1000
+ flatten_suffix(child, bitshift - BITS_PER_LEVEL, from, result)
1001
+ (from_slot+1).upto(node.size-1) do |i|
1002
+ flatten_node(node[i], bitshift - BITS_PER_LEVEL, result)
1003
+ end
1004
+ end
1005
+ result
164
1006
  end
165
1007
  end
166
1008
 
167
- def full?
168
- (@size >> root_index_bits) > 31
1009
+ def replace_suffix(from, suffix)
1010
+ # new suffix can go directly after existing elements
1011
+ raise IndexError if from > @size
1012
+ root, levels = @root, @levels
1013
+
1014
+ if (from >> (BITS_PER_LEVEL * (@levels + 1))) != 0
1015
+ # index where new suffix goes doesn't fall within current tree
1016
+ # we will need to deepen tree
1017
+ root = [root].freeze
1018
+ levels += 1
1019
+ end
1020
+
1021
+ new_size = from + suffix.size
1022
+ root = replace_node_suffix(root, levels * BITS_PER_LEVEL, from, suffix)
1023
+
1024
+ if !suffix.empty?
1025
+ levels.times { suffix = suffix.each_slice(32).to_a }
1026
+ root.concat(suffix)
1027
+ while root.size > 32
1028
+ root = root.each_slice(32).to_a
1029
+ levels += 1
1030
+ end
1031
+ else
1032
+ while root.size == 1 && levels > 0
1033
+ root = root[0]
1034
+ levels -= 1
1035
+ end
1036
+ end
1037
+
1038
+ self.class.alloc(root.freeze, new_size, levels)
169
1039
  end
170
1040
 
171
- def root_index_bits
172
- @levels * BITS_PER_LEVEL
1041
+ def replace_node_suffix(node, bitshift, from, suffix)
1042
+ from_slot = (from >> bitshift) & INDEX_MASK
1043
+
1044
+ if bitshift == 0
1045
+ if from_slot == 0
1046
+ suffix.shift(32)
1047
+ else
1048
+ node.take(from_slot).concat(suffix.shift(32 - from_slot))
1049
+ end
1050
+ else
1051
+ mask = ((1 << bitshift) - 1)
1052
+ if from & mask == 0
1053
+ if from_slot == 0
1054
+ new_node = suffix.shift(32 * (1 << bitshift))
1055
+ while bitshift != 0
1056
+ new_node = new_node.each_slice(32).to_a
1057
+ bitshift -= BITS_PER_LEVEL
1058
+ end
1059
+ new_node
1060
+ else
1061
+ result = node.take(from_slot)
1062
+ remainder = suffix.shift((32 - from_slot) * (1 << bitshift))
1063
+ while bitshift != 0
1064
+ remainder = remainder.each_slice(32).to_a
1065
+ bitshift -= BITS_PER_LEVEL
1066
+ end
1067
+ result.concat(remainder)
1068
+ end
1069
+ elsif child = node[from_slot]
1070
+ result = node.take(from_slot)
1071
+ result.push(replace_node_suffix(child, bitshift - BITS_PER_LEVEL, from, suffix))
1072
+ remainder = suffix.shift((31 - from_slot) * (1 << bitshift))
1073
+ while bitshift != 0
1074
+ remainder = remainder.each_slice(32).to_a
1075
+ bitshift -= BITS_PER_LEVEL
1076
+ end
1077
+ result.concat(remainder)
1078
+ else
1079
+ raise "Shouldn't happen"
1080
+ end
1081
+ end
173
1082
  end
174
1083
  end
175
1084
 
176
- EmptyVector = Hamster::Vector.new
1085
+ # The canonical empty `Vector`. Returned by `Hamster.vector` and `Vector[]` when
1086
+ # invoked with no arguments; also returned by `Vector.empty`. Prefer using this
1087
+ # one rather than creating many empty vectors using `Vector.new`.
1088
+ #
1089
+ EmptyVector = Hamster::Vector.empty
177
1090
  end