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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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