multiArray.ml 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. (*
  2. * MultiArray - Resizeable Big Ocaml arrays
  3. * Copyright (C) 2012 Nicolas Cannasse
  4. *
  5. * This library is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU Lesser General Public
  7. * License as published by the Free Software Foundation; either
  8. * version 2.1 of the License, or (at your option) any later version,
  9. * with the special exception on linking described in file LICENSE.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this library; if not, write to the Free Software
  18. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  19. *)
  20. type 'a intern
  21. external ilen : 'a intern -> int = "%obj_size"
  22. let idup (x : 'a intern) = if ilen x = 0 then x else (Obj.magic (Obj.dup (Obj.repr x)) : 'a intern)
  23. let imake tag len = (Obj.magic (Obj.new_block tag len) : 'a intern)
  24. external iget : 'a intern -> int -> 'a = "%obj_field"
  25. external iset : 'a intern -> int -> 'a -> unit = "%obj_set_field"
  26. type 'a t = {
  27. mutable arr : 'a intern intern;
  28. mutable len : int;
  29. }
  30. exception Invalid_arg of int * string * string
  31. let invalid_arg n f p = raise (Invalid_arg (n,f,p))
  32. let length d = d.len
  33. (* create 1K chunks, which allows up to 4GB elements *)
  34. let nbits = 10
  35. let size = 1 lsl nbits
  36. let mask = size - 1
  37. let create() =
  38. {
  39. len = 0;
  40. arr = imake 0 0;
  41. }
  42. let init len f =
  43. let count = (len + size - 1) lsr nbits in
  44. let d = {
  45. len = len;
  46. arr = imake 0 count;
  47. } in
  48. let max = count - 1 in
  49. for i = 0 to max do
  50. let arr = imake 0 size in
  51. iset d.arr i arr;
  52. for j = 0 to (if i = max then len land mask else size) - 1 do
  53. iset arr j (f ((i lsl nbits) + j))
  54. done;
  55. done;
  56. d
  57. let make len e =
  58. let count = (len + size - 1) lsr nbits in
  59. let d = {
  60. len = len;
  61. arr = imake 0 count;
  62. } in
  63. let max = count - 1 in
  64. for i = 0 to max do
  65. let arr = imake 0 size in
  66. iset d.arr i arr;
  67. for j = 0 to (if i = max then len land mask else size) - 1 do
  68. iset arr j e
  69. done;
  70. done;
  71. d
  72. let empty d =
  73. d.len = 0
  74. let unsafe_get d idx =
  75. iget (iget d.arr (idx lsr nbits)) (idx land mask)
  76. let unsafe_set d idx v =
  77. iset (iget d.arr (idx lsr nbits)) (idx land mask) v
  78. let get d idx =
  79. if idx < 0 || idx >= d.len then invalid_arg idx "get" "index";
  80. iget (iget d.arr (idx lsr nbits)) (idx land mask)
  81. let set d idx v =
  82. if idx < 0 || idx >= d.len then invalid_arg idx "set" "index";
  83. iset (iget d.arr (idx lsr nbits)) (idx land mask) v
  84. let add d v =
  85. let asize = ilen d.arr in
  86. if d.len >= asize lsl nbits then begin
  87. let narr = imake 0 (asize + 1) in
  88. for i = 0 to asize-1 do
  89. iset narr i (iget d.arr i);
  90. done;
  91. iset narr asize (imake 0 size);
  92. d.arr <- narr;
  93. end;
  94. iset (iget d.arr (d.len lsr nbits)) (d.len land mask) v;
  95. d.len <- d.len + 1
  96. let clear d =
  97. d.len <- 0;
  98. d.arr <- imake 0 0
  99. let reset_pos d =
  100. d.len <- 0
  101. let of_array src =
  102. let c = create() in
  103. Array.iteri (fun i v -> add c v) src;
  104. c
  105. let of_list src =
  106. let c = create() in
  107. List.iter (add c) src;
  108. c
  109. let iter f d =
  110. let max = ilen d.arr - 1 in
  111. for i = 0 to max do
  112. let arr = iget d.arr i in
  113. for j = 0 to (if i = max then (d.len land mask) else size) - 1 do
  114. f (iget arr j)
  115. done;
  116. done
  117. let iteri f d =
  118. let max = ilen d.arr - 1 in
  119. for i = 0 to max do
  120. let arr = iget d.arr i in
  121. for j = 0 to (if i = max then (d.len land mask) else size) - 1 do
  122. f ((i lsl nbits) + j) (iget arr j)
  123. done;
  124. done
  125. let map f d =
  126. let max = ilen d.arr - 1 in
  127. let d2 = {
  128. len = d.len;
  129. arr = imake 0 (max + 1);
  130. } in
  131. for i = 0 to max do
  132. let arr = iget d.arr i in
  133. let narr = imake 0 size in
  134. iset d2.arr i narr;
  135. for j = 0 to (if i = max then (d.len land mask) else size) - 1 do
  136. iset narr j (f (iget arr j))
  137. done;
  138. done;
  139. d2
  140. let mapi f d =
  141. let max = ilen d.arr - 1 in
  142. let d2 = {
  143. len = d.len;
  144. arr = imake 0 (max + 1);
  145. } in
  146. for i = 0 to max do
  147. let arr = iget d.arr i in
  148. let narr = imake 0 size in
  149. iset d2.arr i narr;
  150. for j = 0 to (if i = max then (d.len land mask) else size) - 1 do
  151. iset narr j (f ((i lsl nbits) + j) (iget arr j))
  152. done;
  153. done;
  154. d2
  155. let fold_left f acc d =
  156. let acc = ref acc in
  157. let max = ilen d.arr - 1 in
  158. for i = 0 to max do
  159. let arr = iget d.arr i in
  160. for j = 0 to (if i = max then (d.len land mask) else size) - 1 do
  161. acc := f !acc (iget arr j)
  162. done;
  163. done;
  164. !acc