/compiler/2.0/Nov2010/src/utils/resizearray.fs

https://github.com/dmohl/fsharppowerpack_Net40 · F# · 325 lines · 257 code · 57 blank · 11 comment · 78 complexity · bd77c367cd7865600a42415f2e86b3d0 MD5 · raw file

  1. //----------------------------------------------------------------------------
  2. //
  3. // Copyright (c) 2002-2010 Microsoft Corporation.
  4. //
  5. // This source code is subject to terms and conditions of the Apache License, Version 2.0. A
  6. // copy of the license can be found in the License.html file at the root of this distribution.
  7. // By using this source code in any fashion, you are agreeing to be bound
  8. // by the terms of the Apache License, Version 2.0.
  9. //
  10. // You must not remove this notice, or any other, from this software.
  11. //----------------------------------------------------------------------------
  12. namespace Internal.Utilities
  13. open Microsoft.FSharp.Core
  14. open Microsoft.FSharp.Core.OptimizedClosures
  15. [<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
  16. module internal ResizeArray =
  17. let length (arr: ResizeArray<'T>) = arr.Count
  18. let get (arr: ResizeArray<'T>) (n: int) = arr.[n]
  19. let set (arr: ResizeArray<'T>) (n: int) (x:'T) = arr.[n] <- x
  20. let create (n: int) x = new ResizeArray<_> (seq { for _ in 1 .. n -> x })
  21. let init (n: int) (f: int -> 'T) = new ResizeArray<_> (seq { for i in 0 .. n-1 -> f i })
  22. let blit (arr1: ResizeArray<'T>) start1 (arr2: ResizeArray<'T>) start2 len =
  23. if start1 < 0 then invalidArg "start1" "index must be positive"
  24. if start2 < 0 then invalidArg "start2" "index must be positive"
  25. if len < 0 then invalidArg "len" "length must be positive"
  26. if start1 + len > length arr1 then invalidArg "start1" "(start1+len) out of range"
  27. if start2 + len > length arr2 then invalidArg "start2" "(start2+len) out of range"
  28. for i = 0 to len - 1 do
  29. arr2.[start2+i] <- arr1.[start1 + i]
  30. let concat (arrs: ResizeArray<'T> list) = new ResizeArray<_> (seq { for arr in arrs do for x in arr do yield x })
  31. let append (arr1: ResizeArray<'T>) (arr2: ResizeArray<'T>) = concat [arr1; arr2]
  32. let sub (arr: ResizeArray<'T>) start len =
  33. if start < 0 then invalidArg "start" "index must be positive"
  34. if len < 0 then invalidArg "len" "length must be positive"
  35. if start + len > length arr then invalidArg "len" "length must be positive"
  36. new ResizeArray<_> (seq { for i in start .. start+len-1 -> arr.[i] })
  37. let fill (arr: ResizeArray<'T>) (start: int) (len: int) (x:'T) =
  38. if start < 0 then invalidArg "start" "index must be positive"
  39. if len < 0 then invalidArg "len" "length must be positive"
  40. if start + len > length arr then invalidArg "len" "length must be positive"
  41. for i = start to start + len - 1 do
  42. arr.[i] <- x
  43. let copy (arr: ResizeArray<'T>) = new ResizeArray<_>(arr)
  44. let toList (arr: ResizeArray<_>) =
  45. let mutable res = []
  46. for i = length arr - 1 downto 0 do
  47. res <- arr.[i] :: res
  48. res
  49. let ofList (l: _ list) =
  50. let len = l.Length
  51. let res = new ResizeArray<_>(len)
  52. let rec add = function
  53. | [] -> ()
  54. | e::l -> res.Add(e); add l
  55. add l
  56. res
  57. let iter f (arr: ResizeArray<_>) =
  58. for i = 0 to arr.Count - 1 do
  59. f arr.[i]
  60. let map f (arr: ResizeArray<_>) =
  61. let len = length arr
  62. let res = new ResizeArray<_>(len)
  63. for i = 0 to len - 1 do
  64. res.Add(f arr.[i])
  65. res
  66. let mapi f (arr: ResizeArray<_>) =
  67. let f = FSharpFunc<_,_,_>.Adapt(f)
  68. let len = length arr
  69. let res = new ResizeArray<_>(len)
  70. for i = 0 to len - 1 do
  71. res.Add(f.Invoke(i, arr.[i]))
  72. res
  73. let iteri f (arr: ResizeArray<_>) =
  74. let f = FSharpFunc<_,_,_>.Adapt(f)
  75. for i = 0 to arr.Count - 1 do
  76. f.Invoke(i, arr.[i])
  77. let exists (f: 'T -> bool) (arr: ResizeArray<'T>) =
  78. let len = length arr
  79. let rec loop i = i < len && (f arr.[i] || loop (i+1))
  80. loop 0
  81. let forall f (arr: ResizeArray<_>) =
  82. let len = length arr
  83. let rec loop i = i >= len || (f arr.[i] && loop (i+1))
  84. loop 0
  85. let indexNotFound() = raise (new System.Collections.Generic.KeyNotFoundException("An index satisfying the predicate was not found in the collection"))
  86. let find f (arr: ResizeArray<_>) =
  87. let rec loop i =
  88. if i >= length arr then indexNotFound()
  89. elif f arr.[i] then arr.[i]
  90. else loop (i+1)
  91. loop 0
  92. let tryPick f (arr: ResizeArray<_>) =
  93. let rec loop i =
  94. if i >= length arr then None else
  95. match f arr.[i] with
  96. | None -> loop(i+1)
  97. | res -> res
  98. loop 0
  99. let tryFind f (arr: ResizeArray<_>) =
  100. let rec loop i =
  101. if i >= length arr then None
  102. elif f arr.[i] then Some arr.[i]
  103. else loop (i+1)
  104. loop 0
  105. let iter2 f (arr1: ResizeArray<'T>) (arr2: ResizeArray<'b>) =
  106. let f = FSharpFunc<_,_,_>.Adapt(f)
  107. let len1 = length arr1
  108. if len1 <> length arr2 then invalidArg "arr2" "the arrays have different lengths"
  109. for i = 0 to len1 - 1 do
  110. f.Invoke(arr1.[i], arr2.[i])
  111. let map2 f (arr1: ResizeArray<'T>) (arr2: ResizeArray<'b>) =
  112. let f = FSharpFunc<_,_,_>.Adapt(f)
  113. let len1 = length arr1
  114. if len1 <> length arr2 then invalidArg "arr2" "the arrays have different lengths"
  115. let res = new ResizeArray<_>(len1)
  116. for i = 0 to len1 - 1 do
  117. res.Add(f.Invoke(arr1.[i], arr2.[i]))
  118. res
  119. let choose f (arr: ResizeArray<_>) =
  120. let res = new ResizeArray<_>()
  121. for i = 0 to length arr - 1 do
  122. match f arr.[i] with
  123. | None -> ()
  124. | Some b -> res.Add(b)
  125. res
  126. let filter f (arr: ResizeArray<_>) =
  127. let res = new ResizeArray<_>()
  128. for i = 0 to length arr - 1 do
  129. let x = arr.[i]
  130. if f x then res.Add(x)
  131. res
  132. let partition f (arr: ResizeArray<_>) =
  133. let res1 = new ResizeArray<_>()
  134. let res2 = new ResizeArray<_>()
  135. for i = 0 to length arr - 1 do
  136. let x = arr.[i]
  137. if f x then res1.Add(x) else res2.Add(x)
  138. res1, res2
  139. let rev (arr: ResizeArray<_>) =
  140. let len = length arr
  141. let res = new ResizeArray<_>(len)
  142. for i = len - 1 downto 0 do
  143. res.Add(arr.[i])
  144. res
  145. let foldBack (f : 'T -> 'State -> 'State) (arr: ResizeArray<'T>) (acc: 'State) =
  146. let mutable res = acc
  147. let len = length arr
  148. for i = len - 1 downto 0 do
  149. res <- f (get arr i) res
  150. res
  151. let fold (f : 'State -> 'T -> 'State) (acc: 'State) (arr: ResizeArray<'T>) =
  152. let mutable res = acc
  153. let len = length arr
  154. for i = 0 to len - 1 do
  155. res <- f res (get arr i)
  156. res
  157. let toArray (arr: ResizeArray<'T>) = arr.ToArray()
  158. let ofArray (arr: 'T[]) = new ResizeArray<_>(arr)
  159. let toSeq (arr: ResizeArray<'T>) = Seq.readonly arr
  160. let sort f (arr: ResizeArray<'T>) = arr.Sort (System.Comparison(f))
  161. let sortBy f (arr: ResizeArray<'T>) = arr.Sort (System.Comparison(fun x y -> compare (f x) (f y)))
  162. let exists2 f (arr1: ResizeArray<_>) (arr2: ResizeArray<_>) =
  163. let len1 = length arr1
  164. if len1 <> length arr2 then invalidArg "arr2" "the arrays have different lengths"
  165. let rec loop i = i < len1 && (f arr1.[i] arr2.[i] || loop (i+1))
  166. loop 0
  167. let findIndex f (arr: ResizeArray<_>) =
  168. let rec go n = if n >= length arr then indexNotFound() elif f arr.[n] then n else go (n+1)
  169. go 0
  170. let findIndexi f (arr: ResizeArray<_>) =
  171. let rec go n = if n >= length arr then indexNotFound() elif f n arr.[n] then n else go (n+1)
  172. go 0
  173. let foldSub f acc (arr: ResizeArray<_>) start fin =
  174. let mutable res = acc
  175. for i = start to fin do
  176. res <- f res arr.[i]
  177. res
  178. let foldBackSub f (arr: ResizeArray<_>) start fin acc =
  179. let mutable res = acc
  180. for i = fin downto start do
  181. res <- f arr.[i] res
  182. res
  183. let reduce f (arr : ResizeArray<_>) =
  184. let arrn = length arr
  185. if arrn = 0 then invalidArg "arr" "the input array may not be empty"
  186. else foldSub f arr.[0] arr 1 (arrn - 1)
  187. let reduceBack f (arr: ResizeArray<_>) =
  188. let arrn = length arr
  189. if arrn = 0 then invalidArg "arr" "the input array may not be empty"
  190. else foldBackSub f arr 0 (arrn - 2) arr.[arrn - 1]
  191. let fold2 f (acc: 'T) (arr1: ResizeArray<'T1>) (arr2: ResizeArray<'T2>) =
  192. let f = FSharpFunc<_,_,_,_>.Adapt(f)
  193. let mutable res = acc
  194. let len = length arr1
  195. if len <> length arr2 then invalidArg "arr2" "the arrays have different lengths"
  196. for i = 0 to len - 1 do
  197. res <- f.Invoke(res,arr1.[i],arr2.[i])
  198. res
  199. let foldBack2 f (arr1: ResizeArray<'T1>) (arr2: ResizeArray<'T2>) (acc: 'b) =
  200. let f = FSharpFunc<_,_,_,_>.Adapt(f)
  201. let mutable res = acc
  202. let len = length arr1
  203. if len <> length arr2 then invalidArg "arr2" "the arrays have different lengths"
  204. for i = len - 1 downto 0 do
  205. res <- f.Invoke(arr1.[i],arr2.[i],res)
  206. res
  207. let forall2 f (arr1: ResizeArray<_>) (arr2: ResizeArray<_>) =
  208. let len1 = length arr1
  209. if len1 <> length arr2 then invalidArg "arr2" "the arrays have different lengths"
  210. let rec loop i = i >= len1 || (f arr1.[i] arr2.[i] && loop (i+1))
  211. loop 0
  212. let isEmpty (arr: ResizeArray<_>) = length (arr: ResizeArray<_>) = 0
  213. let iteri2 f (arr1: ResizeArray<'T>) (arr2: ResizeArray<'b>) =
  214. let f = FSharpFunc<_,_,_,_>.Adapt(f)
  215. let len1 = length arr1
  216. if len1 <> length arr2 then invalidArg "arr2" "the arrays have different lengths"
  217. for i = 0 to len1 - 1 do
  218. f.Invoke(i,arr1.[i], arr2.[i])
  219. let mapi2 (f: int -> 'T -> 'b -> 'c) (arr1: ResizeArray<'T>) (arr2: ResizeArray<'b>) =
  220. let f = FSharpFunc<_,_,_,_>.Adapt(f)
  221. let len1 = length arr1
  222. if len1 <> length arr2 then invalidArg "arr2" "the arrays have different lengths"
  223. init len1 (fun i -> f.Invoke(i, arr1.[i], arr2.[i]))
  224. let scanBackSub f (arr: ResizeArray<'T>) start fin acc =
  225. let f = FSharpFunc<_,_,_>.Adapt(f)
  226. let mutable state = acc
  227. let res = create (2+fin-start) acc
  228. for i = fin downto start do
  229. state <- f.Invoke(arr.[i], state)
  230. res.[i - start] <- state
  231. res
  232. let scanSub f acc (arr : ResizeArray<'T>) start fin =
  233. let f = FSharpFunc<_,_,_>.Adapt(f)
  234. let mutable state = acc
  235. let res = create (fin-start+2) acc
  236. for i = start to fin do
  237. state <- f.Invoke(state, arr.[i])
  238. res.[i - start+1] <- state
  239. res
  240. let scan f acc (arr : ResizeArray<'T>) =
  241. let arrn = length arr
  242. scanSub f acc arr 0 (arrn - 1)
  243. let scanBack f (arr : ResizeArray<'T>) acc =
  244. let arrn = length arr
  245. scanBackSub f arr 0 (arrn - 1) acc
  246. let singleton x =
  247. let res = new ResizeArray<_>(1)
  248. res.Add(x)
  249. res
  250. let tryFindIndex f (arr: ResizeArray<'T>) =
  251. let rec go n = if n >= length arr then None elif f arr.[n] then Some n else go (n+1)
  252. go 0
  253. let tryFindIndexi f (arr: ResizeArray<'T>) =
  254. let rec go n = if n >= length arr then None elif f n arr.[n] then Some n else go (n+1)
  255. go 0
  256. let zip (arr1: ResizeArray<_>) (arr2: ResizeArray<_>) =
  257. let len1 = length arr1
  258. if len1 <> length arr2 then invalidArg "arr2" "the arrays have different lengths"
  259. init len1 (fun i -> arr1.[i], arr2.[i])
  260. let unzip (arr: ResizeArray<_>) =
  261. let len = length arr
  262. let res1 = new ResizeArray<_>(len)
  263. let res2 = new ResizeArray<_>(len)
  264. for i = 0 to len - 1 do
  265. let x,y = arr.[i]
  266. res1.Add(x)
  267. res2.Add(y)
  268. res1,res2