From ab110b694d8f8f4dcbe3fc4f7b25a625ed0be18a Mon Sep 17 00:00:00 2001 From: Guillaume Bury Date: Mon, 23 Mar 2015 17:59:34 +0100 Subject: [PATCH] New module for Persistent Arrays --- _oasis | 2 +- doc/intro.txt | 1 + src/data/CCPersistentArray.ml | 80 +++++++++++++++++++++++++++++ src/data/CCPersistentArray.mli | 92 ++++++++++++++++++++++++++++++++++ 4 files changed, 174 insertions(+), 1 deletion(-) create mode 100644 src/data/CCPersistentArray.ml create mode 100644 src/data/CCPersistentArray.mli diff --git a/_oasis b/_oasis index 1bc41b99..cda0e31d 100644 --- a/_oasis +++ b/_oasis @@ -71,7 +71,7 @@ Library "containers_data" Path: src/data Modules: CCMultiMap, CCMultiSet, CCTrie, CCFlatHashtbl, CCCache, CCPersistentHashtbl, CCDeque, CCFQueue, CCBV, CCMixtbl, - CCMixmap, CCRingBuffer, CCIntMap + CCMixmap, CCRingBuffer, CCIntMap, CCPersistentArray BuildDepends: bytes FindlibParent: containers FindlibName: data diff --git a/doc/intro.txt b/doc/intro.txt index 8c23d683..3db1fe94 100644 --- a/doc/intro.txt +++ b/doc/intro.txt @@ -71,6 +71,7 @@ CCMixmap CCMixtbl CCMultiMap CCMultiSet +CCPersistentArray CCPersistentHashtbl CCRingBuffer CCTrie diff --git a/src/data/CCPersistentArray.ml b/src/data/CCPersistentArray.ml new file mode 100644 index 00000000..fb7b3991 --- /dev/null +++ b/src/data/CCPersistentArray.ml @@ -0,0 +1,80 @@ +(* +copyright (c) 2013-2015, Guillaume Bury +all rights reserved. + +redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. redistributions in binary +form must reproduce the above copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other materials provided with +the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*) + + +(* Persistent arrays *) + +type 'a t = 'a data ref +and 'a data = + | Array of 'a array + | Diff of int * 'a * 'a t + +let make n a = ref (Array (Array.make n a)) +let init n f = ref (Array (Array.init n f)) + +let rec _reroot t k = match !t with + | Array a -> k a + | Diff (i, v, t') -> + _reroot t' (fun a -> + let v' = a.(i) in + a.(i) <- v; + t := Array a; + t' := Diff(i, v', t); + k a + ) + +let reroot t = match !t with + | Array a -> a + | _ -> _reroot t (fun x -> x) + +let get t i = match !t with + | Array a -> a.(i) + | _ -> (reroot t).(i) + +let set t i v = + let a = reroot t in + let old = a.(i) in + a.(i) <- v; + let t' = ref (Array a) in + t := Diff (i, old, t'); + t' + +let length t = Array.length (reroot t) + +let map f t = ref (Array (Array.map f (reroot t))) +let mapi f t = ref (Array (Array.mapi f (reroot t))) + +let iter f t = Array.iter f (reroot t) +let iteri f t = Array.iteri f (reroot t) + +let fold_left f acc t = Array.fold_left f acc (reroot t) +let fold_right f t acc = Array.fold_right f (reroot t) acc + +let to_array t = Array.copy (reroot t) +let of_array a = init (Array.length a) (fun i -> a.(i)) + +let to_list t = Array.to_list (reroot t) +let of_list l = ref (Array (Array.of_list l)) + diff --git a/src/data/CCPersistentArray.mli b/src/data/CCPersistentArray.mli new file mode 100644 index 00000000..b8a77166 --- /dev/null +++ b/src/data/CCPersistentArray.mli @@ -0,0 +1,92 @@ +(* +copyright (c) 2013-2015, Guillaume Bury +all rights reserved. + +redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. redistributions in binary +form must reproduce the above copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other materials provided with +the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*) + + +(** {1 Persistent Arrays} + +@since NEXT_RELEASE *) + +type 'a t +(** The type of persistent arrays *) + +val make : int -> 'a -> 'a t +(** [make n x] returns a persistent array of length n, with [x]. All the + elements of this new array are initially physically equal to x + (in the sense of the == predicate). Consequently, if x is mutable, it is + shared among all elements of the array, and modifying x through one of the + array entries will modify all other entries at the same time. + @raise Invalid_argument if [n < 0] or [n > Sys.max_array_length]. + If the value of x is a floating-point number, then the maximum size is + only [Sys.max_array_length / 2].*) + +val init : int -> (int -> 'a) -> 'a t +(** [make n f] returns a persistent array of length n, with element + [i] initialized to the result of [f i]. + @raise Invalid_argument if [n < 0] or [n > Sys.max_array_length]. + If the value of x is a floating-point number, then the maximum size is + only [Sys.max_array_length / 2].*) + +val get : 'a t -> int -> 'a +(** [get a i] Returns the element with index [i] from the array [a]. + @raise Invalid_argument "index out of bounds" if [n] is outside the + range [0] to [Array.length a - 1].*) + +val set : 'a t -> int -> 'a -> 'a t +(** [set a i v] sets the element index [i] from the array [a] to [v]. + @raise Invalid_argument "index out of bounds" if [n] is outside the + range [0] to [Array.length a - 1].*) + +val length : 'a t -> int +(** Returns the length of the persistent array. *) + +val map : ('a -> 'b) -> 'a t -> 'b t +val mapi : (int -> 'a -> 'b) -> 'a t -> 'b t +(** Applies the given function to all elements of the array, and returns + a persistent array initialized by the results of f. In the case of [mapi], + the function is also given the index of the element. + It is equivalent to [fun f t -> init (fun i -> f (get t i))]. *) + +val iter : ('a -> unit) -> 'a t -> unit +val iteri : (int -> 'a -> unit) -> 'a t -> unit +(** [iter f t] applies function [f] to all elements of the persistent array, in order + from element [0] to element [length t - 1]. *) + +val fold_left : ('a -> 'b -> 'a) -> 'a -> 'b t -> 'a +val fold_right : ('a -> 'b -> 'b) -> 'a t -> 'b -> 'b +(** Fold on the elements of the array. *) + +val to_array : 'a t -> 'a array +(** [to_array t] returns a mutable copy of [t]. *) + +val of_array : 'a array -> 'a t +(** [from_array a] returns an immutable copy of [a]. *) + +val to_list : 'a t -> 'a list +(** [to_list t] returns the list of elements in [t]. *) + +val of_list : 'a list -> 'a t +(** [of_list l] returns a fresh persistent array containing the elements of [l]. *) + +