Skip to content

Commit

Permalink
Merge branch 'master' into stable
Browse files Browse the repository at this point in the history
  • Loading branch information
c-cube committed Oct 11, 2017
2 parents f24d983 + d6f7f15 commit ad8a61a
Show file tree
Hide file tree
Showing 30 changed files with 388 additions and 82 deletions.
2 changes: 1 addition & 1 deletion .merlin
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@ PKG threads
PKG threads.posix
PKG lwt
PKG qcheck
FLG -w +a -w -4 -w -44
FLG -w +a-4-44-48-60
2 changes: 2 additions & 0 deletions .ocp-indent
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
match_clause=2
with=2
3 changes: 2 additions & 1 deletion AUTHORS.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,5 @@
- Glenn Slotte (glennsl)
- @LemonBoy
- Leonid Rozenberg (@rleonid)
- Bikal Gurung (@bikalgurung)
- Bikal Gurung (@bikalgurung)
- Fabian Hemmer (copy)
20 changes: 20 additions & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
@@ -1,5 +1,25 @@
= Changelog

== 1.4

- add `CCMap.union`
- add `CCRef.swap`
- add `CCArray.swap`
- change signature of `CCWBTree.get_rank`
- add `CCWBTree.get_rank{,_exn}`

- more efficient `List.map` Using efficient chunking algorithm
- Fix `CCVector.append_array` (empty vector case)
- `CCFQueue.take_back_exn` raised InvalidArg instead of Empty on an empty queue
- faster `CCString.{prefix,suffix}`
- speed improvements and benchmarks for `CCString.{prefix,suffix}`

- add ocp-indent file
- fix `CCFun.tap` example in doc
- specify behavior of `CCFQueue.take_{front,back}_l` in some corner cases
- More tests for CCVector.append and CCVector.append_array
- assertions and cleanup in `CCPool`

== 1.3

- deprecate `CCBool.negate`
Expand Down
2 changes: 1 addition & 1 deletion HOWTO.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ can be removed.
. `make update_next_tag` (to update `@since` comments; be careful not to change symlinks)
. check status of modules (`{b status: foo}`) and update if required;
removed deprecated functions, etc.
. update `CHANGELOG.md` (see its end to find the right git command)
. update `CHANGELOG.adoc` (see its end to find the right git command)
. commit the changes
. `git checkout stable`
. `git merge master`
Expand Down
10 changes: 2 additions & 8 deletions README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -96,14 +96,8 @@ and <<tutorial,the tutorial below>> for a gentle introduction.
In general, see http://c-cube.github.io/ocaml-containers/last/ or
http://cedeela.fr/~simon/software/containers for the **API documentation**.

Some examples can be found link:doc/containers.adoc[there].

API documentation by version:

- http://c-cube.github.io/ocaml-containers/dev/[dev branch]
- http://c-cube.github.io/ocaml-containers/1.0/[1.0]
- http://c-cube.github.io/ocaml-containers/0.19/[0.19]
- http://c-cube.github.io/ocaml-containers/0.17/[0.17]
Some examples can be found link:doc/containers.adoc[there],
per-version doc http://c-cube.github.io/ocaml-containers/[there].

[[build]]
== Build
Expand Down
2 changes: 1 addition & 1 deletion _oasis
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
OASISFormat: 0.4
Name: containers
Version: 1.3
Version: 1.4
Homepage: https://github.com/c-cube/ocaml-containers
Authors: Simon Cruanes
License: BSD-2-clause
Expand Down
98 changes: 98 additions & 0 deletions benchs/run_benchs.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1177,6 +1177,99 @@ module Str = struct
let bench_find = bench_find_ ~dir:`Direct
let bench_rfind = bench_find_ ~dir:`Reverse

module Pre = struct
let prefix_rec ~pre s =
let rec same s1 s2 i =
if i = String.length s1 then true
else (
String.unsafe_get s1 i = String.unsafe_get s2 i && same s1 s2 (i+1)
)
in
String.length pre <= String.length s &&
same pre s 0

let prefix_while ~pre s =
String.length pre <= String.length s &&
begin
let i = ref 0 in
while !i < String.length pre &&
String.unsafe_get s !i = String.unsafe_get pre !i
do incr i done;
!i = String.length pre
end

exception Exit_false

let prefix_for_exn ~pre s =
String.length pre <= String.length s &&
try
for i=0 to String.length pre-1 do
if String.unsafe_get s i != String.unsafe_get pre i
then raise Exit_false
done;
true
with Exit_false -> false

let prefix_sub ~pre:prfx s =
let len_s = String.length s in
let len_p = String.length prfx in
if len_s < len_p then
false
else
let sub = String.sub s 0 len_p in
CCString.equal prfx sub

let bat_prefix ~pre:p str =
let len = String.length p in
if String.length str < len then false
else
let rec loop str p i =
if i = len then true
else if String.unsafe_get str i <> String.unsafe_get p i then false
else loop str p (i + 1)
in loop str p 0

let make ~max_len ~max_len_prefix n =
let rand = Random.State.make_self_init () in
let input =
Array.init n
(fun _ ->
let str =
QCheck.Gen.(string_size ~gen:printable (10 -- max_len))
|> QCheck.Gen.generate1 ~rand
in
let prfx_len = Random.State.int rand (min max_len_prefix (String.length str + 1)) in
let prfx =
if Random.State.bool rand then
String.sub str 0 prfx_len
else
String.sub str (String.length str - prfx_len) prfx_len
in
(prfx, str))
in
let output =
Array.map
(fun (pre, str) -> prefix_rec ~pre str)
input
in
let test f () =
Array.iteri
(fun i (pre, y) ->
let res = f ~pre y in
assert (res = output.(i)))
input
in
Benchmark.throughputN 3
[
"containers", test CCString.prefix, ();
"while_unsafe", test prefix_while, ();
"rec_unsafe", test prefix_rec, ();
"for_exn_unsafe", test prefix_for_exn, ();
"sub_eq", test prefix_sub, ();
"bat_prefix", test bat_prefix, ();
]
end

let () = B.Tree.register (
"string" @>>>
[ "find" @>>>
Expand Down Expand Up @@ -1205,6 +1298,11 @@ module Str = struct
; "50" @>> app_ints (bench_rfind ~size:50) [100; 100_000; 500_000]
; "500" @>> app_ints (bench_rfind ~size:500) [100_000; 500_000]
];
"prefix" @>>>
[ "max_len:1000,max_pre_len:15" @>> app_ints (Pre.make ~max_len:1000 ~max_len_prefix:15) [100; 1_000];
"max_len:1000,max_pre_len:100" @>> app_ints (Pre.make ~max_len:1000 ~max_len_prefix:100) [100; 1_000];
"max_len:1000,max_pre_len:300" @>> app_ints (Pre.make ~max_len:1000 ~max_len_prefix:300) [100; 1_000];
]
])

end
Expand Down
1 change: 1 addition & 0 deletions doc/intro.txt
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ CCFlatHashtbl
CCGraph
CCHashSet
CCHashTrie
CCHet
CCImmutArray
CCIntMap
CCMixmap
Expand Down
2 changes: 1 addition & 1 deletion opam
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
opam-version: "1.2"
name: "containers"
version: "1.2"
version: "1.4"
author: "Simon Cruanes"
maintainer: "simon.cruanes@inria.fr"
build: [
Expand Down
9 changes: 4 additions & 5 deletions setup.ml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
(* setup.ml generated for the first time by OASIS v0.4.4 *)

(* OASIS_START *)
(* DO NOT EDIT (digest: a62cfaee59320a25dee6d9bbad9cd339) *)
(* DO NOT EDIT (digest: b1097bcfb2d6eab143d1ac25252d8b14) *)
(*
Regenerated by OASIS v0.4.10
Visit http://oasis.forge.ocamlcore.org for more information and
Expand Down Expand Up @@ -7041,7 +7041,7 @@ let setup_t =
{
oasis_version = "0.4";
ocaml_version = Some (OASISVersion.VGreaterEqual "4.00.1");
version = "1.3";
version = "1.4";
license =
OASISLicense.DEP5License
(OASISLicense.DEP5Unit
Expand Down Expand Up @@ -8900,16 +8900,15 @@ let setup_t =
};
oasis_fn = Some "_oasis";
oasis_version = "0.4.10";
oasis_digest =
Some "\164\233\1428\169\160\007\155\182\180\021s\193\n\134-";
oasis_digest = Some "\213\002\219\227i{sJJ\160\246\216o\167\\^";
oasis_exec = None;
oasis_setup_args = [];
setup_update = false
};;

let setup () = BaseSetup.setup setup_t;;

# 8913 "setup.ml"
# 8912 "setup.ml"
let setup_t = BaseCompat.Compat_0_4.adapt_setup_t setup_t
open BaseCompat.Compat_0_4
(* OASIS_STOP *)
Expand Down
29 changes: 29 additions & 0 deletions src/core/CCArray.ml
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,35 @@ let compare cmp a b =
compare CCOrd.compare [| 1; 2; 3 |] [| 1; 2; |] > 0
*)

(* swap elements of array *)
let swap a i j =
if i<>j then (
let tmp = a.(i) in
a.(i) <- a.(j);
a.(j) <- tmp;
)

(*$T
let a = [| 1;2;3 |] in \
swap a 0 1; \
a = [| 2;1;3 |]
let a = [| 1;2;3 |] in \
swap a 0 2; \
a = [| 3;2;1 |]
*)

(*$QR
Q.(array small_int) (fun a ->
let b = Array.copy a in
for i = 0 to Array.length a-1 do
for j = i+1 to Array.length a-1 do
swap a i j; done; done;
for i = 0 to Array.length a-1 do
for j = i+1 to Array.length a-1 do
swap a i j; done; done;
a=b)
*)

(* shuffle a[i...j[ using the given int random generator
See http://en.wikipedia.org/wiki/Fisher-Yates_shuffle *)
let _shuffle _rand_int a i j =
Expand Down
10 changes: 7 additions & 3 deletions src/core/CCArray.mli
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ val equal : 'a equal -> 'a t equal

val compare : 'a ord -> 'a t ord

val swap : 'a t -> int -> int -> unit
(** [swap arr i j] swaps elements at indices [i] and [j].
@since 1.4 *)

val get : 'a t -> int -> 'a

val get_safe : 'a t -> int -> 'a option
Expand Down Expand Up @@ -71,10 +75,10 @@ val sorted : ('a -> 'a -> int) -> 'a t -> 'a array

val sort_indices : ('a -> 'a -> int) -> 'a t -> int array
(** [sort_indices cmp a] returns a new array [b], with the same length as [a],
such that [b.(i)] is the index at which the [i]-th element of [sorted cmp a]
such that [b.(i)] is the index at which the [i]-th element of [sorted cmp a]
appears in [a]. [a] is not modified.
In other words, [map (fun i -> a.(i)) (sort_indices cmp a) = sorted cmp a].
In other words, [map (fun i -> a.(i)) (sort_indices cmp a) = sorted cmp a].
[sort_indices] yields the inverse permutation of {!sort_ranking}.
@since 1.0 *)
Expand All @@ -84,7 +88,7 @@ val sort_ranking : ('a -> 'a -> int) -> 'a t -> int array
such that [b.(i)] is the index at which the [i]-the element of [a] appears
in [sorted cmp a]. [a] is not modified.
In other words, [map (fun i -> (sorted cmp a).(i)) (sort_ranking cmp a) = a].
In other words, [map (fun i -> (sorted cmp a).(i)) (sort_ranking cmp a) = a].
[sort_ranking] yields the inverse permutation of {!sort_indices}.
In the absence of duplicate elements in [a], we also have
Expand Down
8 changes: 4 additions & 4 deletions src/core/CCFormat.mli
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ val some : 'a printer -> 'a option printer
"what is your @{<White>favorite color@}? @{<blue>blue@}! No, @{<red>red@}! Ahhhhhhh@.";;
]}
{b status: experimental}
{b status: unstable}
@since 0.15 *)

val set_color_tag_handling : t -> unit
Expand All @@ -177,13 +177,13 @@ val set_color_default : bool -> unit
val with_color : string -> 'a printer -> 'a printer
(** [with_color "Blue" pp] behaves like the printer [pp], but with the given
style.
{b status: experimental}
{b status: unstable}
@since 0.16 *)

val with_colorf : string -> t -> ('a, t, unit, unit) format4 -> 'a
(** [with_colorf "Blue" out "%s %d" "yolo" 42] will behave like {!Format.fprintf},
but wrapping the content with the given style
{b status: experimental}
{b status: unstable}
@since 0.16 *)

val with_color_sf : string -> ('a, t, unit, string) format4 -> 'a
Expand All @@ -193,7 +193,7 @@ val with_color_sf : string -> ('a, t, unit, string) format4 -> 'a
{[
CCFormat.with_color_sf "red" "%a" CCFormat.Dump.(list int) [1;2;3] |> print_endline;;
]}
{b status: experimental}
{b status: unstable}
@since 0.21 *)

val with_color_ksf : f:(string -> 'b) -> string -> ('a, t, unit, 'b) format4 -> 'a
Expand Down
2 changes: 1 addition & 1 deletion src/core/CCFun.mli
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ val tap : ('a -> _) -> 'a -> 'a
in a pipeline, for instance:
{[CCArray.(1 -- 10)
|> tap CCArray.shuffle
|> tap CCArray.sort Pervasives.compare
|> tap @@ CCArray.sort Pervasives.compare
]}
*)

Expand Down
Loading

0 comments on commit ad8a61a

Please sign in to comment.