├── dune-project ├── .gitignore ├── README.md ├── dune ├── COPYING ├── bitv.opam ├── bench.ml ├── bitv_string.ml ├── Makefile ├── sieve.ml ├── bitv_string.mli ├── CHANGES.md ├── test.ml ├── bitv.mli ├── bitv.ml └── LICENSE /dune-project: -------------------------------------------------------------------------------- 1 | (lang dune 2.0) 2 | 3 | (formatting 4 | (enabled_for dune)) 5 | 6 | (name bitv) 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | _opam 2 | _build 3 | .merlin 4 | export 5 | bitv.tex 6 | config.cache 7 | config.status 8 | META 9 | Makefile 10 | bitv.pdf 11 | test.ml 12 | autom4te.cache/ 13 | autom4te.cache 14 | a.out 15 | configure 16 | config.log 17 | *.cm* 18 | *.o 19 | *.aux 20 | *.log 21 | sieve.opt 22 | 23 | bench.exe 24 | perf.data 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # A bit vector library for OCaml 2 | 3 | ## Installation 4 | 5 | Installation is available via opam: 6 | 7 | ``` 8 | opam install bitv 9 | ``` 10 | 11 | ## Usage 12 | 13 | The library provides a single module, `Bitv`. The documentation is 14 | available [here](https://backtracking.github.io/bitv). 15 | 16 | ## Bug reports 17 | 18 | Please report bugs by 19 | [creating an issue](https://github.com/backtracking/bitv/issues/new). 20 | -------------------------------------------------------------------------------- /dune: -------------------------------------------------------------------------------- 1 | (library 2 | (public_name bitv) 3 | (flags 4 | (:standard -w -32)) 5 | (modules bitv)) 6 | 7 | (library 8 | (public_name bitv.string) 9 | (name bitv_string) 10 | (modules bitv_string) 11 | (libraries bitv)) 12 | 13 | (test 14 | (name test) 15 | (modules test) 16 | (libraries bitv)) 17 | 18 | (test 19 | (name sieve) 20 | (modules sieve) 21 | (libraries bitv)) 22 | 23 | (executable 24 | (name bench) 25 | (modules bench) 26 | (promote (until-clean)) 27 | (libraries unix bitv)) 28 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | bitv - Objective Caml bit vectors library 2 | Copyright (C) 1999 Jean-Christophe FILLIATRE 3 | 4 | This software is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU Library General Public 6 | License version 2, with the special exception on linking 7 | described in file LICENSE. 8 | 9 | This software is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 | 13 | -------------------------------------------------------------------------------- /bitv.opam: -------------------------------------------------------------------------------- 1 | opam-version: "2.0" 2 | name: "bitv" 3 | maintainer: "Jean-Christophe.Filliatre@cnrs.fr" 4 | authors: "Jean-Christophe Filliâtre" 5 | license: "LGPL-2.1-or-later" 6 | synopsis: "A bit vector library" 7 | description: "A bit vector library" 8 | homepage: "https://github.com/backtracking/bitv" 9 | bug-reports: "https://github.com/backtracking/bitv/issues" 10 | doc: "https://backtracking.github.io/bitv" 11 | depends: [ 12 | "ocaml" {>= "4.08"} 13 | "dune" {>= "2.0.0"} 14 | ] 15 | build: [ 16 | ["dune" "subst"] {dev} 17 | ["dune" "build" "-p" name "-j" jobs] 18 | ["dune" "runtest" "-p" name] {with-test} 19 | ] 20 | dev-repo: "git+https://github.com/backtracking/bitv.git" 21 | -------------------------------------------------------------------------------- /bench.ml: -------------------------------------------------------------------------------- 1 | 2 | (* sandbox to test performance *) 3 | 4 | open Format 5 | 6 | let time f x = 7 | let open Unix in 8 | let u = (times()).tms_utime in 9 | let y = f x in 10 | let ut = (times()).tms_utime -. u in 11 | printf "%2.2f@." ut; 12 | y 13 | 14 | open Bitv 15 | 16 | let () = Random.init 42 17 | let n = int_of_string Sys.argv.(1) 18 | let v = random n 19 | let () = printf "length = %d@." (length v) 20 | let () = if n < 200 then ( 21 | printf "%a@." M.print v; 22 | let p = fold_left (fun p b -> if b then p+1 else p) 0 v in 23 | printf "%d@." p 24 | ) 25 | let () = printf "%d@." (time pop v) 26 | (* let () = printf "%d@." (time pop_fast v) *) 27 | -------------------------------------------------------------------------------- /bitv_string.ml: -------------------------------------------------------------------------------- 1 | (**************************************************************************) 2 | (* *) 3 | (* Copyright (C) Jean-Christophe Filliatre *) 4 | (* *) 5 | (* This software is free software; you can redistribute it and/or *) 6 | (* modify it under the terms of the GNU Library General Public *) 7 | (* License version 2, with the special exception on linking *) 8 | (* described in file LICENSE. *) 9 | (* *) 10 | (* This software is distributed in the hope that it will be useful, *) 11 | (* but WITHOUT ANY WARRANTY; without even the implied warranty of *) 12 | (* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *) 13 | (* *) 14 | (**************************************************************************) 15 | 16 | 17 | include Bitv 18 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ########################################################################## 2 | # # 3 | # Copyright (C) Jean-Christophe Filliatre # 4 | # # 5 | # This software is free software; you can redistribute it and/or # 6 | # modify it under the terms of the GNU Library General Public # 7 | # License version 2, with the special exception on linking # 8 | # described in file LICENSE. # 9 | # # 10 | # This software is distributed in the hope that it will be useful, # 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of # 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # 13 | # # 14 | ########################################################################## 15 | 16 | all: 17 | dune build 18 | 19 | test: 20 | dune runtest 21 | 22 | doc: 23 | dune build @doc 24 | 25 | clean: 26 | dune clean 27 | -------------------------------------------------------------------------------- /sieve.ml: -------------------------------------------------------------------------------- 1 | 2 | (* Testing bitv on a simple Eratosthene's sieve *) 3 | 4 | open Bitv 5 | 6 | let sieve limit = 7 | if exceeds_max_length limit then invalid_arg "first_primes_upto"; 8 | let b = create (limit + 1) true in 9 | unsafe_set b 0 false; 10 | unsafe_set b 1 false; 11 | for i = 2 to limit / 2 do unsafe_set b (2 * i) false done; 12 | let rec loop n = 13 | if n <= limit then 14 | if unsafe_get b n then begin (* n is prime *) 15 | let rec mark i = 16 | if i <= limit then begin unsafe_set b i false; mark (i + 2*n) end 17 | in 18 | if n <= limit/n then mark (n * n); 19 | loop (n + 2) 20 | end else 21 | loop (n + 2) 22 | in 23 | loop 3; 24 | b 25 | 26 | let () = assert (pop (sieve 100) = 25) 27 | 28 | open Format 29 | let () = match Sys.argv with 30 | | [| _; n |] -> 31 | let n = int_of_string n in 32 | let p = Bitv.pop (sieve n) in 33 | printf "%d primes up to %d@." p n 34 | | _ -> () 35 | 36 | (* benchmarks (with OCaml 5.2) 37 | 38 | +------------+----------+------------+------------+------------+ 39 | | N | 10^8 | 10^9 | 2.10^9 | 3.10^9 | 40 | +------------+----------+------------+------------+------------+ 41 | | time (s) | 1.4 | 16.0 | 33.3 | 51.0 | 42 | +------------+----------+------------+------------+------------+ 43 | | #primes | 5761455 | 50847534 | 98222287 | 144449537 | 44 | +------------+----------+------------+------------+------------+ 45 | 46 | *) 47 | -------------------------------------------------------------------------------- /bitv_string.mli: -------------------------------------------------------------------------------- 1 | (**************************************************************************) 2 | (* *) 3 | (* Copyright (C) Jean-Christophe Filliatre *) 4 | (* *) 5 | (* This software is free software; you can redistribute it and/or *) 6 | (* modify it under the terms of the GNU Library General Public *) 7 | (* License version 2, with the special exception on linking *) 8 | (* described in file LICENSE. *) 9 | (* *) 10 | (* This software is distributed in the hope that it will be useful, *) 11 | (* but WITHOUT ANY WARRANTY; without even the implied warranty of *) 12 | (* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *) 13 | (* *) 14 | (**************************************************************************) 15 | 16 | (** @deprecated Now identical to {!Bitv}. *) 17 | 18 | type t 19 | 20 | val create : int -> bool -> t 21 | 22 | val init : int -> (int -> bool) -> t 23 | 24 | val set : t -> int -> bool -> unit 25 | 26 | val get : t -> int -> bool 27 | 28 | val length : t -> int 29 | 30 | val equal : t -> t -> bool 31 | 32 | val max_length : int 33 | (** @deprecated Use [exceed_max_length] instead. *) 34 | 35 | val exceeds_max_length : int -> bool 36 | 37 | val copy : t -> t 38 | 39 | val fill : t -> int -> int -> bool -> unit 40 | 41 | val iter : (bool -> unit) -> t -> unit 42 | val map : (bool -> bool) -> t -> t 43 | 44 | val iteri : (int -> bool -> unit) -> t -> unit 45 | val mapi : (int -> bool -> bool) -> t -> t 46 | 47 | val fold_left : ('a -> bool -> 'a) -> 'a -> t -> 'a 48 | val fold_right : (bool -> 'a -> 'a) -> t -> 'a -> 'a 49 | val foldi_left : ('a -> int -> bool -> 'a) -> 'a -> t -> 'a 50 | val foldi_right : (int -> bool -> 'a -> 'a) -> t -> 'a -> 'a 51 | 52 | val pop: t -> int 53 | 54 | val iteri_true : (int -> unit) -> t -> unit 55 | 56 | val bw_and : t -> t -> t 57 | val bw_or : t -> t -> t 58 | val bw_xor : t -> t -> t 59 | val bw_not : t -> t 60 | 61 | val to_list : t -> int list 62 | val of_list : int list -> t 63 | val of_list_with_length : int list -> int -> t 64 | 65 | (** {2 Only if you know what you are doing...} *) 66 | 67 | val unsafe_set : t -> int -> bool -> unit 68 | val unsafe_get : t -> int -> bool 69 | -------------------------------------------------------------------------------- /CHANGES.md: -------------------------------------------------------------------------------- 1 | 2 | # 2.1 (22/08/2025) 3 | - fixed bug in `random` 4 | - fixed negative `max_length` on JavaScript platform 5 | - new function `random` (much faster than `init n (fun _ -> Random.bool ())` 6 | - new in-place bitwise operations (contribution by Mathieu Barbin) 7 | - fixed division by zero in rotations of 0-length vectors 8 | (reported by Nikolaus Huber) 9 | - fixed integer overflows in bound tests in `fill`, `blit`, `sub` 10 | (fix by Nikolaus Huber) 11 | 12 | # 2.0 (18/05/2024) 13 | - Switch to bytes-based implementation. This is simpler and faster 14 | (up to 30% faster). 15 | `Bitv_string` is still there but deprecated (now identical to `Bitv`). 16 | - Functions `to_int...` do not fail anymore when bit vectors are small 17 | (and behave as if high bits are zero). 18 | - New function `tanimoto` (Tanimoto score) (contribution by François Berenger) 19 | 20 | # 1.6 (06/02/2021) 21 | - fixed build on 32-bit platforms e.g. js_of_ocaml (patch from Tim Bourke) 22 | - added `exceeds_max_length` to replace `max_length` (deprecated) 23 | 24 | # 1.5 (30/01/2021) 25 | - new functions `rotatel` and `rotater` (patch from Tim Bourke) 26 | 27 | # 1.4 (02/08/2020) 28 | - switch to dune build system, and opam 2.0 29 | - add to/of_bytes for machine-independant serialisation 30 | - fix binary serialisation when vector is larger than 2^32 31 | 32 | # 1.3 (14/12/2017) 33 | - fix compilation for OCaml 4.06 (safe-string) 34 | 35 | # 1.2 (10/02/2017) 36 | - added pop (population count, i.e., number of 1 bits) 37 | - suppressed some warnings with OCaml >= 4.00 38 | 39 | # 1.1 (10/04/2013) 40 | - installation using ocamlfind (if found) or in `ocamlc -where`/bitv otherwise 41 | - fixed of_int64_(u)s on a 32-bit architecture (thanks to Florent Monnier) 42 | 43 | # 1.0 (14/08/2012) 44 | - functions to/of_int64_s 45 | - new functions output_bin/input_bin for export/import in a 46 | machine-independent way (contribution from Bruno Guillaume) 47 | - fixed installation (patch from Bruno Guillaume) 48 | 49 | # 0.9 (20/06/2012) 50 | - fixed tarball (test.ml was missing) 51 | - patched installation to use $(DESTDIR), if any (patch from Bruno Guillaume) 52 | 53 | # 0.8 (28/02/2012) 54 | - two different modules L and M for conversions to and from string (least 55 | and most significant bits first, respectively); apologies for 56 | API incompatibility 57 | - improved implementation of iteri_true 58 | 59 | # 0.7 (03/04/2008) 60 | - fixed bug with unsafe_blit when len=0 (could affect blit, sub, append, 61 | concat and fill when used with 0-length bit vectors), thanks to Pat Rondon 62 | 63 | # 0.6 (18/02/2005) 64 | - added iteri_true 65 | - added foldi_left and foldi_right 66 | - patch for ocaml >= 3.08 (0xffffffff is no more accepted as a literal) 67 | - fixed Invalid_argument messages (now exactly the function name) 68 | 69 | # 0.5 (22/11/2002) 70 | - added print : formatter -> t -> unit 71 | - from_list now fails on negative indexes (patch from Karl Zilles) 72 | - from_list_with_length to specify the length (patch from Karl Zilles) 73 | 74 | # 0.4 (29/8/2002) 75 | - to_list/from_list to convert to/from lists of integers 76 | - added gray_iter to iterate over all bit vectors of length n 77 | - configuration with autoconf 78 | 79 | # 0.3 (31/5/2000) 80 | - fixed bug in bw_not thanks to Damir Jamsek 81 | 82 | # 0.2 (24/4/2000) 83 | - normalization, so that generic equality can be used 84 | - efficient implementations of append, sub, blit, concat and fill 85 | - documentation using ocamlweb 86 | - to_string, from_string 87 | - bitwise operations, all_zeros 88 | 89 | # 0.1 90 | - first release 91 | -------------------------------------------------------------------------------- /test.ml: -------------------------------------------------------------------------------- 1 | (* tests *) 2 | 3 | open Bitv 4 | open Bitv.M 5 | 6 | let () = 7 | let test len b = 8 | let v = create len b in 9 | assert (length v = len); 10 | assert (if b then all_ones v else all_zeros v); 11 | assert (bw_and v v = v); 12 | assert (bw_or v v = v); 13 | assert (bw_not (bw_not v) = v); 14 | in 15 | for len = 0 to 100 do test len false; test len true done 16 | 17 | (* 0-length blitting *) 18 | let v = create 30 true 19 | let () = assert (all_ones v) 20 | let () = blit v 0 v 30 0 21 | let () = assert (length v = 30) 22 | 23 | (* 0-length extraction *) 24 | let e = sub v 30 0 25 | let () = assert (length e = 0) 26 | let () = assert (equal e (Bitv.create 0 true)) 27 | 28 | (* 0-length concatenation *) 29 | let w = append v e 30 | let () = assert (length w = 30) 31 | let () = assert (equal w v) 32 | 33 | let w = append e v 34 | let () = assert (length w = 30) 35 | let () = assert (equal w v) 36 | 37 | (* filling *) 38 | let () = fill v 4 11 false 39 | let () = fill v 30 0 true 40 | let () = assert (length v = 30) 41 | let () = assert (to_string v = "111111111111111000000000001111") 42 | 43 | (* bitwise operations *) 44 | let s = sub v 2 4 45 | let () = assert (equal (bw_not (bw_not s)) s) 46 | let () = assert (equal (bw_and e e) e) 47 | 48 | (* bitwise in place operations *) 49 | let va = init 10 (fun i -> i mod 2 = 0) 50 | let vb = init 10 (fun i -> i mod 4 = 0) 51 | let vc = create 10 false 52 | let ve = create 3 false 53 | let () = 54 | assert (to_string va = "0101010101"); 55 | assert (to_string vb = "0100010001"); 56 | bw_and_in_place ~dst:vc va vb; 57 | assert (equal vc (bw_and va vb)); 58 | assert (equal vc vb); 59 | (try bw_and_in_place ~dst:ve va vb; assert false 60 | with Invalid_argument msg -> assert (msg = "Bitv.bw_and_in_place")); 61 | bw_or_in_place ~dst:vc va vb; 62 | assert (equal vc (bw_or va vb)); 63 | assert (equal vc va); 64 | (try bw_or_in_place ~dst:ve va vb; assert false 65 | with Invalid_argument msg -> assert (msg = "Bitv.bw_or_in_place")); 66 | bw_xor_in_place ~dst:vc va vb; 67 | assert (equal vc (bw_xor va vb)); 68 | assert (to_string vc = "0001000100"); 69 | (try bw_xor_in_place ~dst:ve va vb; assert false 70 | with Invalid_argument msg -> assert (msg = "Bitv.bw_xor_in_place")); 71 | bw_not_in_place ~dst:vc va; 72 | assert (to_string vc = "1010101010"); 73 | (try bw_not_in_place ~dst:ve va; assert false 74 | with Invalid_argument msg -> assert (msg = "Bitv.bw_not_in_place")); 75 | () 76 | 77 | (* Tanimoto score *) 78 | let () = 79 | let b0 = create 10 false in 80 | let b1 = create 10 true in 81 | let even = init 10 (fun i -> i mod 2 = 0) in 82 | let odd = init 10 (fun i -> i mod 2 = 1) in 83 | assert (tanimoto b0 b1 = 0.); 84 | assert (tanimoto b1 b1 = 1.); 85 | assert (compare (tanimoto b0 b0) nan = 0); 86 | assert (tanimoto even b1 = 0.5); 87 | assert (tanimoto odd b1 = 0.5) 88 | 89 | (* iteri_true *) 90 | let test_iteri_true n = 91 | let k = 1 + Random.int 5 in 92 | let v = init n (fun i -> i mod k = 0) in 93 | iteri_true (fun i -> assert (i mod k = 0)) v 94 | 95 | let () = 96 | for n = 0 to 1700 do test_iteri_true n done 97 | 98 | (* shifts *) 99 | 100 | let () = 101 | let v = of_string "110101110" in 102 | assert (equal (shiftl v 1) (of_string "101011100")); 103 | assert (equal (shiftl v (-1)) (of_string "011010111")); 104 | assert (equal (shiftr v 1) (of_string "011010111")) 105 | 106 | let test_shift n = 107 | let v = init n (fun _ -> Random.bool ()) in 108 | let k = Random.int n in 109 | let w = shiftr v k in 110 | for i = 0 to n-1-k do assert (get v (k+i) = get w i) done; 111 | for i = n-k to n-1 do assert (get w i = false) done 112 | 113 | let () = 114 | for n = 1 to 200 do test_shift n done 115 | 116 | (* rotations *) 117 | 118 | let () = 119 | let v = of_string "110101110" in 120 | assert (equal (rotatel v 1) (of_string "101011101")); 121 | assert (equal (rotatel v (-1)) (of_string "011010111")); 122 | assert (equal (rotater v 1) (of_string "011010111")); 123 | (* 0-length rotation *) 124 | let v = create 0 false in 125 | assert (length (rotatel v 0) = 0); 126 | assert (length (rotater v 0) = 0); 127 | () 128 | 129 | let test_rotate n = 130 | let v = init n (fun _ -> Random.bool ()) in 131 | let k = Random.int (2*n) - n in 132 | let w = rotatel v k in 133 | for i = 0 to n-1 do assert (get v i = get w ((i + n + k) mod n)) done 134 | 135 | let () = 136 | for n = 1 to 200 do test_rotate n done 137 | 138 | (* conversions to/from lists *) 139 | 140 | let () = 141 | let test len l = 142 | let v = of_list l in 143 | assert (length v = len); 144 | assert (to_list v = l); 145 | assert (v = of_list_with_length l len) 146 | in 147 | test 0 []; 148 | test 42 [41]; 149 | test 35 [0;1;2;3;5;8;13;21;34] 150 | 151 | (* conversions to/from strings *) 152 | 153 | let () = 154 | let bits0 = "1000011001000000000000000000000100000001110000000000000000000000000000000000011100000000110111000000000000000000000000000000000000000111011100" 155 | and bits1 = "1000011001000000000000000000000100000001110000000000000000000111100000000000000000000000110111000000000000000000000000000000000000000111011100" 156 | and zeros = "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" 157 | in 158 | assert (equal (of_string "1") (of_string "1")); 159 | assert (equal (of_string bits0) (of_string bits0)); 160 | assert (equal (of_string bits1) (of_string bits1)); 161 | assert (not (equal (of_string "") (of_string "0"))); 162 | assert (not (equal (of_string "1") (of_string "01"))); 163 | assert (not (equal (of_string "1") (of_string "10"))); 164 | assert (not (equal (of_string bits0) (of_string bits1))); 165 | assert (not (equal (of_string bits1) (of_string bits0))); 166 | assert (String.equal (to_string (of_string "")) ""); 167 | assert (String.equal (to_string (of_string "0")) "0"); 168 | assert (String.equal (to_string (of_string zeros)) zeros); 169 | assert (String.equal (to_string (of_string bits0)) bits0); 170 | assert (String.equal (to_string (of_string bits1)) bits1) 171 | 172 | (* conversions to/from integers *) 173 | 174 | let () = assert (to_int_s (M.of_string "101010") = 42) 175 | 176 | let test_conv size random fto fof = 177 | let test x = 178 | let v = fof x in 179 | assert (length v = size); 180 | assert (fto v = x) 181 | in 182 | for _ = 1 to 1000 do test (random ()) done 183 | 184 | let () = test_conv (Sys.word_size-2) Random.bits to_int_us of_int_us 185 | let random_int_s () = min_int + (Random.bits ()) + (Random.bits ()) 186 | let () = test_conv (Sys.word_size-1) random_int_s to_int_s of_int_s 187 | 188 | let random_int32_us () = Random.int32 Int32.max_int 189 | let () = test_conv 31 random_int32_us to_int32_us of_int32_us 190 | let random_int32_s () = 191 | Int32.add Int32.min_int (Int32.add (random_int32_us ()) (random_int32_us ())) 192 | let () = test_conv 32 random_int32_s to_int32_s of_int32_s 193 | 194 | let random_int64_us () = Random.int64 Int64.max_int 195 | let () = test_conv 63 random_int64_us to_int64_us of_int64_us 196 | let random_int64_s () = 197 | Int64.add Int64.min_int (Int64.add (random_int64_us ()) (random_int64_us ())) 198 | let () = test_conv 64 random_int64_s to_int64_s of_int64_s 199 | 200 | let random_native_us () = Random.nativeint Nativeint.max_int 201 | let random_native_s () = 202 | Nativeint.add Nativeint.min_int 203 | (Nativeint.add (random_native_us ()) (random_native_us ())) 204 | let () = test_conv Sys.word_size random_native_s to_nativeint_s of_nativeint_s 205 | let () = 206 | test_conv (Sys.word_size-1) random_native_us to_nativeint_us of_nativeint_us 207 | 208 | (* input/output *) 209 | 210 | let test_io v = 211 | let f = Filename.temp_file "bitv" "" in 212 | let c = open_out f in 213 | output_bin c v; 214 | close_out c; 215 | let c = open_in f in 216 | let w = input_bin c in 217 | close_in c; 218 | begin try Sys.remove f with _ -> () end; 219 | assert (equal v w) 220 | 221 | let test_bytes v = 222 | assert (equal (of_bytes (to_bytes v)) v) 223 | 224 | let test_equivalent v = 225 | let f = Filename.temp_file "bitv" "" in 226 | let c = open_out f in 227 | output_bin c v; 228 | close_out c; 229 | let c = open_in f in 230 | let len = in_channel_length c in 231 | let b = Bytes.create len in 232 | really_input c b 0 len; 233 | close_in c; 234 | begin try Sys.remove f with _ -> () end; 235 | assert (Bytes.equal b (to_bytes v)) 236 | 237 | let () = 238 | for n = 0 to 200 do 239 | let bv = init n (fun _ -> Random.bool ()) in 240 | test_io bv; 241 | test_bytes bv; 242 | test_equivalent bv; 243 | done 244 | 245 | (* fill *) 246 | let () = 247 | for len = 0 to 100 do 248 | let v = create len false in 249 | for i = 0 to len do 250 | fill v 0 i true; 251 | assert (pop v = i) 252 | done; 253 | for i = len downto 0 do 254 | fill v i (len - i) false; 255 | assert (pop v = i) 256 | done 257 | done 258 | 259 | let ones = create 30 true 260 | let () = assert (pop ones = 30) 261 | let zeros = create 30 false 262 | let () = assert (pop zeros = 0) 263 | let () = assert (equal (bw_or v ones) ones) 264 | let () = assert (equal (bw_and v ones) v) 265 | let () = assert (equal (bw_xor v zeros) v) 266 | let () = assert (equal (bw_xor v ones) (bw_not v)) 267 | let () = 268 | let dst = create 30 false in 269 | bw_not_in_place ~dst v; 270 | assert (equal (bw_xor v ones) dst) 271 | 272 | (* fill overflow *) 273 | let () = 274 | let t = create 10 false in 275 | try 276 | fill t Int.max_int 1 false; 277 | assert false 278 | with 279 | Invalid_argument _ -> assert true 280 | 281 | (* blit overflow *) 282 | let () = 283 | let t1 = create 10 false in 284 | let t2 = create 10 true in 285 | try 286 | blit t1 0 t2 Int.max_int 1; 287 | assert false 288 | with 289 | Invalid_argument _ -> assert true 290 | 291 | (* sub overflow *) 292 | let () = 293 | let t = create 10 false in 294 | try 295 | sub t Int.max_int 1 |> ignore; 296 | assert false 297 | with 298 | Invalid_argument _ -> assert true 299 | 300 | -------------------------------------------------------------------------------- /bitv.mli: -------------------------------------------------------------------------------- 1 | (**************************************************************************) 2 | (* *) 3 | (* Copyright (C) Jean-Christophe Filliatre *) 4 | (* *) 5 | (* This software is free software; you can redistribute it and/or *) 6 | (* modify it under the terms of the GNU Library General Public *) 7 | (* License version 2, with the special exception on linking *) 8 | (* described in file LICENSE. *) 9 | (* *) 10 | (* This software is distributed in the hope that it will be useful, *) 11 | (* but WITHOUT ANY WARRANTY; without even the implied warranty of *) 12 | (* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *) 13 | (* *) 14 | (**************************************************************************) 15 | 16 | (** This module implements bit vectors, as an abstract datatype [t]. 17 | Since bit vectors are particular cases of arrays, this module provides 18 | the same operations as module [Array]. It also provides bitwise operations 19 | and conversions to/from integer types. 20 | 21 | In the following, [false] stands for bit 0 and [true] for bit 1. *) 22 | 23 | type t 24 | (** the type of bit vectors *) 25 | 26 | (** {2 Creation, access and assignment.} *) 27 | 28 | val create : int -> bool -> t 29 | (** [(Bitv.create n b)] creates a new bit vector of length [n], 30 | initialized with [b]. *) 31 | 32 | val init : int -> (int -> bool) -> t 33 | (** [(Bitv.init n f)] returns a fresh vector of length [n], 34 | with bit number [i] initialized to the result of [(f i)]. *) 35 | 36 | val random: int -> t 37 | (** [Bitv.random n] returns a fresh vector of length [n] with random bits. 38 | This is equivalent to [Bitv.init n (fun _ -> Random.bool ())], 39 | but much faster. *) 40 | 41 | val set : t -> int -> bool -> unit 42 | (** [(Bitv.set v n b)] sets the [n]th bit of [v] to the value [b]. *) 43 | 44 | val get : t -> int -> bool 45 | (** [(Bitv.get v n)] returns the [n]th bit of [v]. *) 46 | 47 | val length : t -> int 48 | (** [Bitv.length] returns the length (number of elements) of the given 49 | vector. *) 50 | 51 | val equal : t -> t -> bool 52 | (** Returns [true] if two bit vectors are of the same length and 53 | with the same bits. *) 54 | 55 | val tanimoto : t -> t -> float 56 | (** [Bitv.tanimoto v1 v2] is |inter(v1,v2)| / |union(v1,v2)|. 57 | Also called the Jaccard score. 58 | (1 - tanimoto) is a proper distance. 59 | raises [Invalid_argument] if the two vectors do not have the same length *) 60 | 61 | val max_length : int 62 | (** This is typically [Sys.max_string_length * 8] but may be smaller 63 | on small platform (e.g. Javascript). *) 64 | 65 | val exceeds_max_length : int -> bool 66 | (** Returns true if the argument exceeds the maximum length of a bit vector 67 | (System dependent). *) 68 | 69 | (** {2 Copies and concatenations.} *) 70 | 71 | val copy : t -> t 72 | (** [(Bitv.copy v)] returns a copy of [v], 73 | that is, a fresh vector containing the same elements as [v]. *) 74 | 75 | val append : t -> t -> t 76 | (** [(Bitv.append v1 v2)] returns a fresh vector containing the 77 | concatenation of the vectors [v1] and [v2]. *) 78 | 79 | val concat : t list -> t 80 | (** [Bitv.concat] is similar to [Bitv.append], but catenates a list of 81 | vectors. *) 82 | 83 | (** {2 Sub-vectors and filling.} *) 84 | 85 | val sub : t -> int -> int -> t 86 | (** [(Bitv.sub v start len)] returns a fresh 87 | vector of length [len], containing the bits number [start] to 88 | [start + len - 1] of vector [v]. Raise [Invalid_argument 89 | "Bitv.sub"] if [start] and [len] do not designate a valid 90 | subvector of [v]; that is, if [start < 0], or [len < 0], or [start 91 | + len > Bitv.length a]. *) 92 | 93 | val fill : t -> int -> int -> bool -> unit 94 | (** [(Bitv.fill v ofs len b)] modifies the vector [v] in place, 95 | storing [b] in elements number [ofs] to [ofs + len - 1]. Raise 96 | [Invalid_argument "Bitv.fill"] if [ofs] and [len] do not designate 97 | a valid subvector of [v]. *) 98 | 99 | val blit : t -> int -> t -> int -> int -> unit 100 | (** [(Bitv.blit v1 o1 v2 o2 len)] copies [len] elements from vector 101 | [v1], starting at element number [o1], to vector [v2], starting at 102 | element number [o2]. It does not work correctly if [v1] and [v2] are 103 | the same vector with the source and destination chunks overlapping. 104 | Raise [Invalid_argument "Bitv.blit"] if [o1] and [len] do not 105 | designate a valid subvector of [v1], or if [o2] and [len] do not 106 | designate a valid subvector of [v2]. *) 107 | 108 | (** {2 Iterators} *) 109 | 110 | val iter : (bool -> unit) -> t -> unit 111 | (** [(Bitv.iter f v)] applies function [f] in turn to all 112 | the elements of [v]. *) 113 | 114 | val map : (bool -> bool) -> t -> t 115 | (** Given a function [f], [(Bitv.map f v)] applies [f] to all 116 | the elements of [v], and builds a vector with the results returned 117 | by [f]. *) 118 | 119 | val iteri : (int -> bool -> unit) -> t -> unit 120 | val mapi : (int -> bool -> bool) -> t -> t 121 | (** [Bitv.iteri] and [Bitv.mapi] are similar to [Bitv.iter] 122 | and [Bitv.map] respectively, but the function is applied to the 123 | index of the element as first argument, and the element itself as 124 | second argument. *) 125 | 126 | val fold_left : ('a -> bool -> 'a) -> 'a -> t -> 'a 127 | (** [(Bitv.fold_left f x v)] computes [f (... (f (f x (get v 0)) (get 128 | v 1)) ...) (get v (n-1))], where [n] is the length of the vector 129 | [v]. *) 130 | 131 | val fold_right : (bool -> 'a -> 'a) -> t -> 'a -> 'a 132 | (** [(Bitv.fold_right f a x)] computes [f (get v 0) (f (get v 1) 133 | ( ... (f (get v (n-1)) x) ...))], where [n] is the length of the 134 | vector [v]. *) 135 | 136 | val foldi_left : ('a -> int -> bool -> 'a) -> 'a -> t -> 'a 137 | val foldi_right : (int -> bool -> 'a -> 'a) -> t -> 'a -> 'a 138 | 139 | (** {2 Pop count and other iterations} *) 140 | 141 | val pop: t -> int 142 | (** Population count, i.e., number of 1 bits *) 143 | 144 | val iteri_true : (int -> unit) -> t -> unit 145 | (** [iteri_true f v] applies function [f] in turn to all indexes of 146 | the elements of [v] which are set (i.e. [true]); indexes are 147 | visited from least significant to most significant. *) 148 | 149 | val gray_iter : (t -> unit) -> int -> unit 150 | (** [gray_iter f n] iterates function [f] on all bit vectors 151 | of length [n], once each, using a Gray code. The order in which 152 | bit vectors are processed is unspecified. *) 153 | 154 | (** {2 Bitwise operations.} 155 | 156 | All the bitwise operations return fresh vectors. *) 157 | 158 | val bw_and : t -> t -> t 159 | (** bitwise AND; 160 | raises [Invalid_argument] if the two vectors do not have the same length *) 161 | 162 | val bw_or : t -> t -> t 163 | (** bitwise OR; 164 | raises [Invalid_argument] if the two vectors do not have the same length *) 165 | 166 | val bw_xor : t -> t -> t 167 | (** bitwise XOR; 168 | raises [Invalid_argument] if the two vectors do not have the same length *) 169 | 170 | val bw_not : t -> t 171 | (** bitwise NOT *) 172 | 173 | val shiftl : t -> int -> t 174 | (** moves bits from least to most significant; introduces zeros *) 175 | 176 | val shiftr : t -> int -> t 177 | (** moves bits from most to least significant; introduces zeros *) 178 | 179 | val rotatel : t -> int -> t 180 | (** moves bits from least to most significant with wraparound *) 181 | 182 | val rotater : t -> int -> t 183 | (** moves bits from most to least significant with wraparound *) 184 | 185 | (** {3 Bitwise in place operations.} 186 | 187 | This part of the API extends some bitwise operations by making them operate 188 | in place, that is mutating a destination bit vector supplied as a labeled 189 | argument [dst], rather than returning a fresh one. 190 | 191 | These in place operations support being called with [dst] being one of the 192 | operands supplied to the function call. 193 | 194 | For example [bw_and_in_place ~dst:a a b] will store in [a] the result of 195 | the operation [bw_and a b]. *) 196 | 197 | val bw_and_in_place : dst:t -> t -> t -> unit 198 | (** bitwise AND in place into [dst]; 199 | raises [Invalid_argument] if the three vectors do not have the same length *) 200 | 201 | val bw_or_in_place : dst:t -> t -> t -> unit 202 | (** bitwise OR in place into [dst]; 203 | raises [Invalid_argument] if the three vectors do not have the same length *) 204 | 205 | val bw_xor_in_place : dst:t -> t -> t -> unit 206 | (** bitwise XOR in place into [dst]; 207 | raises [Invalid_argument] if the three vectors do not have the same length *) 208 | 209 | val bw_not_in_place : dst:t -> t -> unit 210 | (** bitwise NOT in place into [dst]; 211 | raises [Invalid_argument] if the two vectors do not have the same length *) 212 | 213 | (** {2 Test functions} *) 214 | 215 | val all_zeros : t -> bool 216 | (** returns [true] if and only if the vector only contains zeros *) 217 | 218 | val all_ones : t -> bool 219 | (** returns [true] if and only if the vector only contains ones *) 220 | 221 | (** {2 Conversions to and from strings} *) 222 | 223 | (** With least significant bits first. *) 224 | module L : sig 225 | val to_string : t -> string 226 | val of_string : string -> t 227 | val print : Format.formatter -> t -> unit 228 | end 229 | 230 | (** With most significant bits first. *) 231 | module M : sig 232 | val to_string : t -> string 233 | val of_string : string -> t 234 | val print : Format.formatter -> t -> unit 235 | end 236 | 237 | (** {2 Input/output in a machine-independent format} 238 | 239 | The following functions export/import a bit vector to/from a channel or 240 | bytes, in a way that is compact, independent of the machine architecture, 241 | and independent of the OCaml version. 242 | For a bit vector of length [n], the number of bytes of this external 243 | representation is 8+ceil(n/8). *) 244 | 245 | val output_bin: out_channel -> t -> unit 246 | val input_bin: in_channel -> t 247 | 248 | val to_bytes: t -> bytes 249 | val of_bytes: bytes -> t 250 | 251 | (** {2 Conversions to and from lists of integers} 252 | 253 | The list gives the indices of bits which are set (i.e. [true]). *) 254 | 255 | val to_list : t -> int list 256 | val of_list : int list -> t 257 | val of_list_with_length : int list -> int -> t 258 | 259 | (** {2 Interpretation of bit vectors as integers} 260 | 261 | Least significant bit comes first (ie is at index 0 in the bit vector). 262 | [to_xxx] functions truncate when the bit vector is too wide. 263 | Suffix [_s] means that sign bit is kept, 264 | and [_us] that it is discarded. *) 265 | 266 | (** {3 type [int] (length 31/63 with sign, 30/62 without)} *) 267 | 268 | val of_int_s : int -> t 269 | val to_int_s : t -> int 270 | val of_int_us : int -> t 271 | val to_int_us : t -> int 272 | 273 | (** {3 type [Int32.t] (length 32 with sign, 31 without)} *) 274 | 275 | val of_int32_s : Int32.t -> t 276 | val to_int32_s : t -> Int32.t 277 | val of_int32_us : Int32.t -> t 278 | val to_int32_us : t -> Int32.t 279 | 280 | (** {3 type [Int64.t] (length 64 with sign, 63 without)} *) 281 | 282 | val of_int64_s : Int64.t -> t 283 | val to_int64_s : t -> Int64.t 284 | val of_int64_us : Int64.t -> t 285 | val to_int64_us : t -> Int64.t 286 | 287 | (** {3 type [Nativeint.t] (length 32/64 with sign, 31/63 without)} *) 288 | 289 | val of_nativeint_s : Nativeint.t -> t 290 | val to_nativeint_s : t -> Nativeint.t 291 | val of_nativeint_us : Nativeint.t -> t 292 | val to_nativeint_us : t -> Nativeint.t 293 | 294 | (** {2 Only if you know what you are doing...} *) 295 | 296 | val unsafe_set : t -> int -> bool -> unit 297 | val unsafe_get : t -> int -> bool 298 | -------------------------------------------------------------------------------- /bitv.ml: -------------------------------------------------------------------------------- 1 | (**************************************************************************) 2 | (* *) 3 | (* Copyright (C) Jean-Christophe Filliatre *) 4 | (* *) 5 | (* This software is free software; you can redistribute it and/or *) 6 | (* modify it under the terms of the GNU Library General Public *) 7 | (* License version 2, with the special exception on linking *) 8 | (* described in file LICENSE. *) 9 | (* *) 10 | (* This software is distributed in the hope that it will be useful, *) 11 | (* but WITHOUT ANY WARRANTY; without even the implied warranty of *) 12 | (* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *) 13 | (* *) 14 | (**************************************************************************) 15 | 16 | (* Bit vectors. The interface and part of the code are borrowed from the 17 | [Array] module of the OCaml standard library (but things are simplified 18 | here since we can always initialize a bit vector). This module also 19 | provides bitwise operations. *) 20 | 21 | (* We represent a bit vector by a string of bytes (field [bits]), and 22 | we keep the information of the size of the bit vector (field 23 | [length]) since it can not be figured out with the size of the 24 | array. *) 25 | 26 | let[@inline] byte s i = Char.code (Bytes.unsafe_get s i) 27 | 28 | let set_byte s i x = Bytes.unsafe_set s i (Char.unsafe_chr x) 29 | 30 | type t = { 31 | length : int; 32 | bits : Bytes.t } 33 | (* invariant: the unused high bits of the last byte are zeros (if any) *) 34 | 35 | let length v = v.length 36 | 37 | let[@inline] equal (v1: t) (v2: t) = v1 = v2 38 | 39 | let max_length = 40 | (* prevent overflow with 32-bit integers on JavaScript *) 41 | if max_int lsr 3 < Sys.max_string_length then max_int else 42 | Sys.max_string_length * 8 43 | 44 | let exceeds_max_length n = 45 | let s = n / 8 in 46 | (if n mod 8 = 0 then s else s + 1) > Sys.max_string_length 47 | 48 | let low_mask = Array.init 9 (fun i -> (1 lsl i) - 1) 49 | 50 | let create n b = 51 | if n < 0 || n > max_length then invalid_arg "Bitv.create"; 52 | let initv = if b then 255 else 0 in 53 | let q = n lsr 3 in 54 | let r = n land 7 in 55 | if r = 0 then 56 | { length = n; bits = Bytes.make q (Char.chr initv) } 57 | else begin 58 | let s = Bytes.make (q + 1) (Char.chr initv) in 59 | set_byte s q (initv land low_mask.(r)); 60 | { length = n; bits = s } 61 | end 62 | 63 | let normalize v = 64 | let r = v.length land 7 in 65 | if r > 0 then 66 | let b = v.bits in 67 | let s = Bytes.length b in 68 | set_byte b (s-1) ((byte b (s-1)) land low_mask.(r)) 69 | 70 | let copy v = { length = v.length; bits = Bytes.copy v.bits } 71 | 72 | let unsafe_get v n = 73 | let i = n lsr 3 in 74 | (byte v.bits i) land (1 lsl (n land 7)) > 0 75 | 76 | let get v n = 77 | if n < 0 || n >= v.length then invalid_arg "Bitv.get"; 78 | unsafe_get v n 79 | 80 | let unsafe_set v n b = 81 | let i = n lsr 3 in 82 | let c = byte v.bits i in 83 | let mask = 1 lsl (n land 7) in 84 | set_byte v.bits i (if b then c lor mask else c land (lnot mask)) 85 | 86 | let set v n b = 87 | if n < 0 || n >= v.length then invalid_arg "Bitv.set"; 88 | unsafe_set v n b 89 | 90 | (* [init] is implemented naively using [unsafe_set]. *) 91 | 92 | let init n f = 93 | let v = create n false in 94 | for i = 0 to pred n do unsafe_set v i (f i) done; 95 | v 96 | 97 | let random n = 98 | let v = create n false in 99 | let b = v.bits in 100 | let n = Bytes.length b in 101 | for i = 0 to n / 3 - 1 do let j = 3 * i in 102 | let bits = Random.bits () in 103 | set_byte b j (bits land 0xFF); 104 | set_byte b (j+1) ((bits lsr 8) land 0xFF); 105 | set_byte b (j+2) ((bits lsr 16) land 0xFF) 106 | done; 107 | for i = 3 * (n / 3) to n - 1 do set_byte b i (Random.int 256) done; 108 | normalize v; 109 | v 110 | 111 | let fill v ofs len b = 112 | if ofs < 0 || len < 0 || ofs > v.length - len then invalid_arg "Bitv.fill"; 113 | if len > 0 then ( 114 | (* incomplete first byte, if any (8-r bits) *) 115 | let r = ofs land 7 in 116 | let first = if r = 0 then 0 else min len (8-r) in 117 | for i = ofs to ofs + first-1 do unsafe_set v i b done; 118 | (* full bytes in the middle *) 119 | let start = (ofs + first) lsr 3 in 120 | let n = (len - first) lsr 3 in 121 | let x = Char.chr (if b then 0xFF else 0) in 122 | for i = start to start + n - 1 do Bytes.unsafe_set v.bits i x done; 123 | (* incomplete last byte, if any *) 124 | let s = (len - first) land 7 in 125 | if s > 0 then 126 | let stop = ofs + len in 127 | for i = stop - s to stop - 1 do unsafe_set v i b done 128 | ) 129 | 130 | (* All the iterators are implemented as for traditional arrays, using 131 | [unsafe_get]. For [iter] and [map], we do not precompute [(f 132 | true)] and [(f false)] since [f] may have side-effects. *) 133 | 134 | let iter f v = 135 | for i = 0 to v.length - 1 do f (unsafe_get v i) done 136 | 137 | let map f v = 138 | let l = v.length in 139 | let r = create l false in 140 | for i = 0 to l - 1 do 141 | unsafe_set r i (f (unsafe_get v i)) 142 | done; 143 | r 144 | 145 | let iteri f v = 146 | for i = 0 to v.length - 1 do f i (unsafe_get v i) done 147 | 148 | let mapi f v = 149 | let l = v.length in 150 | let r = create l false in 151 | for i = 0 to l - 1 do 152 | unsafe_set r i (f i (unsafe_get v i)) 153 | done; 154 | r 155 | 156 | let fold_left f x v = 157 | let r = ref x in 158 | for i = 0 to v.length - 1 do 159 | r := f !r (unsafe_get v i) 160 | done; 161 | !r 162 | 163 | let fold_right f v x = 164 | let r = ref x in 165 | for i = v.length - 1 downto 0 do 166 | r := f (unsafe_get v i) !r 167 | done; 168 | !r 169 | 170 | let foldi_left f x v = 171 | let r = ref x in 172 | for i = 0 to v.length - 1 do 173 | r := f !r i (unsafe_get v i) 174 | done; 175 | !r 176 | 177 | let foldi_right f v x = 178 | let r = ref x in 179 | for i = v.length - 1 downto 0 do 180 | r := f i (unsafe_get v i) !r 181 | done; 182 | !r 183 | 184 | (* 185 | let iteri_true f v = 186 | Bytes.iteri 187 | (fun i x -> let x = Char.code x in if x != 0 then begin 188 | let i = i lsl 3 in 189 | for j = 0 to 7 do if x land (1 lsl j) > 0 then f (i + j) done 190 | end) 191 | v.bits 192 | *) 193 | (* slightly more efficient by precomputing NTZ *) 194 | let ntz = Array.make 256 0 195 | let () = for i = 0 to 7 do ntz.(1 lsl i) <- i done 196 | let ntz8 x = Array.unsafe_get ntz x 197 | 198 | let iteri_true f v = 199 | Bytes.iteri 200 | (fun i c -> 201 | let i_bpi = i lsl 3 in 202 | let rec visit x = 203 | if x != 0 then begin 204 | let b = x land (-x) in 205 | f (i_bpi + ntz8 b); 206 | visit (x - b) 207 | end 208 | in 209 | visit (Char.code c)) 210 | v.bits 211 | 212 | (* Population count *) 213 | 214 | let rec naive_pop x = 215 | assert (x < 0x100); 216 | if x = 0 then 0 else 1 + naive_pop (x - (x land -x)) 217 | 218 | let pop8 = Array.init 0x100 naive_pop 219 | let pop8 n = Array.unsafe_get pop8 n 220 | 221 | let pop v = 222 | let n = Bytes.length v.bits in 223 | let b = v.bits in 224 | let rec loop acc i = 225 | if i >= n then acc else loop (acc + pop8 (byte b i)) (i + 1) in 226 | loop 0 0 227 | 228 | (* not better *) 229 | (* 230 | let pop16 n = pop8 (n land 0xFF) + pop8 (n lsr 8) 231 | let pop32 n = pop16 (n land 0xFFFF) + pop16 (n lsr 16) 232 | let popi32 n = pop32 (Int32.to_int n land 0xFFFF_FFFF) 233 | 234 | let pop_fast v = 235 | let b = v.bits in 236 | let n = Bytes.length b in 237 | let q = n lsr 2 in 238 | let r = ref 0 in 239 | for i = 0 to q - 1 do 240 | let i = i lsl 2 in 241 | r := !r + popi32 (Bytes.get_int32_ne b i) 242 | done; 243 | for i = q lsl 2 to n - 1 do 244 | r := !r + pop8 (byte b i) 245 | done; 246 | !r 247 | *) 248 | 249 | (* Bitwise operations. It is straigthforward, since bitwise operations 250 | can be realized by the corresponding bitwise operations over integers. 251 | However, one has to take care of normalizing the result of [bwnot] 252 | which introduces ones in highest significant positions. *) 253 | 254 | let[@inline always] bw_and_in_place_internal ~dst ~n b1 b2 = 255 | for i = 0 to n - 1 do 256 | set_byte dst i ((byte b1 i) land (byte b2 i)) 257 | done 258 | 259 | let bw_and_in_place ~dst v1 v2 = 260 | let l = v1.length in 261 | if l <> v2.length || l <> dst.length then invalid_arg "Bitv.bw_and_in_place"; 262 | let b1 = v1.bits 263 | and b2 = v2.bits in 264 | let n = Bytes.length b1 in 265 | bw_and_in_place_internal ~dst:dst.bits ~n b1 b2 266 | 267 | let bw_and v1 v2 = 268 | let l = v1.length in 269 | if l <> v2.length then invalid_arg "Bitv.bw_and"; 270 | let b1 = v1.bits 271 | and b2 = v2.bits in 272 | let n = Bytes.length b1 in 273 | let a = Bytes.make n (Char.chr 0) in 274 | bw_and_in_place_internal ~dst:a ~n b1 b2; 275 | { length = l; bits = a } 276 | 277 | let[@inline always] bw_or_in_place_internal ~dst ~n b1 b2 = 278 | for i = 0 to n - 1 do 279 | set_byte dst i ((byte b1 i) lor (byte b2 i)) 280 | done 281 | 282 | let bw_or_in_place ~dst v1 v2 = 283 | let l = v1.length in 284 | if l <> v2.length || l <> dst.length then invalid_arg "Bitv.bw_or_in_place"; 285 | let b1 = v1.bits 286 | and b2 = v2.bits in 287 | let n = Bytes.length b1 in 288 | bw_or_in_place_internal ~dst:dst.bits ~n b1 b2 289 | 290 | let bw_or v1 v2 = 291 | let l = v1.length in 292 | if l <> v2.length then invalid_arg "Bitv.bw_or"; 293 | let b1 = v1.bits 294 | and b2 = v2.bits in 295 | let n = Bytes.length b1 in 296 | let a = Bytes.make n (Char.chr 0) in 297 | bw_or_in_place_internal ~dst:a ~n b1 b2; 298 | { length = l; bits = a } 299 | 300 | let[@inline always] bw_xor_in_place_internal ~dst ~n b1 b2 = 301 | for i = 0 to n - 1 do 302 | set_byte dst i ((byte b1 i) lxor (byte b2 i)) 303 | done 304 | 305 | let bw_xor_in_place ~dst v1 v2 = 306 | let l = v1.length in 307 | if l <> v2.length || l <> dst.length then invalid_arg "Bitv.bw_xor_in_place"; 308 | let b1 = v1.bits 309 | and b2 = v2.bits in 310 | let n = Bytes.length b1 in 311 | bw_xor_in_place_internal ~dst:dst.bits ~n b1 b2 312 | 313 | let bw_xor v1 v2 = 314 | let l = v1.length in 315 | if l <> v2.length then invalid_arg "Bitv.bw_xor"; 316 | let b1 = v1.bits 317 | and b2 = v2.bits in 318 | let n = Bytes.length b1 in 319 | let a = Bytes.make n (Char.chr 0) in 320 | bw_xor_in_place_internal ~dst:a ~n b1 b2; 321 | { length = l; bits = a } 322 | 323 | let[@inline always] bw_not_in_place_internal ~dst ~n b = 324 | let a = dst.bits in 325 | for i = 0 to n - 1 do 326 | set_byte a i (255 land (lnot (byte b i))) 327 | done; 328 | normalize dst 329 | 330 | let bw_not_in_place ~dst v = 331 | let l = v.length in 332 | if l <> dst.length then invalid_arg "Bitv.bw_not_in_place"; 333 | let b = v.bits in 334 | let n = Bytes.length b in 335 | bw_not_in_place_internal ~dst ~n b 336 | 337 | let bw_not v = 338 | let b = v.bits in 339 | let n = Bytes.length b in 340 | let a = Bytes.make n (Char.chr 0) in 341 | let dst = { length = v.length; bits = a } in 342 | bw_not_in_place_internal ~dst ~n b; 343 | dst 344 | 345 | (* Coercions to/from lists of integers *) 346 | 347 | let of_list l = 348 | let n = 1 + List.fold_left max (-1) l in 349 | if n < 0 || n > max_length then invalid_arg "Bitv.of_list"; 350 | let b = create n false in 351 | let add_element i = 352 | (* negative numbers are invalid *) 353 | if i < 0 then invalid_arg "Bitv.of_list"; 354 | unsafe_set b i true 355 | in 356 | List.iter add_element l; 357 | b 358 | 359 | let of_list_with_length l len = 360 | if len < 0 || len > max_length then invalid_arg "Bitv.of_list_with_length"; 361 | let b = create len false in 362 | let add_element i = 363 | if i < 0 || i >= len then invalid_arg "Bitv.of_list_with_length"; 364 | unsafe_set b i true 365 | in 366 | List.iter add_element l; 367 | b 368 | 369 | let to_list b = 370 | let n = length b in 371 | let rec make i acc = 372 | if i < 0 then acc 373 | else make (pred i) (if unsafe_get b i then i :: acc else acc) 374 | in 375 | make (pred n) [] 376 | 377 | let[@inline] pos n = n lsr 3, n land 7 378 | 379 | let unsafe_getb b n = 380 | let i = n lsr 3 in 381 | (byte b i) land (1 lsl (n land 7)) > 0 382 | 383 | let unsafe_setb b n v = 384 | let i = n lsr 3 in 385 | let c = byte b i in 386 | let mask = 1 lsl (n land 7) in 387 | set_byte b i (if v then c lor mask else c land (lnot mask)) 388 | 389 | (* Copies v1[ofs1..ofs1+len[ into v2[ofs2..ofs2+len[ *) 390 | let unsafe_blit b1 ofs1 b2 ofs2 len = 391 | if len > 0 then 392 | if ofs1 land 7 = 0 && ofs2 land 7 = 0 && len land 7 = 0 then 393 | Bytes.blit b1 (ofs1 lsr 3) b2 (ofs2 lsr 3) (len lsr 3) 394 | else 395 | for i = 0 to len - 1 do 396 | unsafe_setb b2 (ofs2 + i) (unsafe_getb b1 (ofs1 + i)) 397 | done 398 | (* TODO: improve in other cases when bytes can be batch-copied *) 399 | 400 | let blit v1 ofs1 v2 ofs2 len = 401 | if len < 0 || ofs1 < 0 || ofs1 > v1.length - len 402 | || ofs2 < 0 || ofs2 > v2.length - len 403 | then invalid_arg "Bitv.blit"; 404 | unsafe_blit v1.bits ofs1 v2.bits ofs2 len 405 | 406 | let sub v ofs len = 407 | if ofs < 0 || len < 0 || ofs > v.length - len then invalid_arg "Bitv.sub"; 408 | let r = create len false in 409 | unsafe_blit v.bits ofs r.bits 0 len; 410 | r 411 | 412 | let append v1 v2 = 413 | let l1 = v1.length 414 | and l2 = v2.length in 415 | let r = create (l1 + l2) false in 416 | let b1 = v1.bits in 417 | let b = r.bits in 418 | Bytes.blit b1 0 b 0 (Bytes.length b1); 419 | unsafe_blit v2.bits 0 b l1 l2; 420 | r 421 | 422 | let concat vl = 423 | let size = List.fold_left (fun sz v -> sz + v.length) 0 vl in 424 | let res = create size false in 425 | let b = res.bits in 426 | let pos = ref 0 in 427 | List.iter 428 | (fun v -> 429 | let n = v.length in 430 | unsafe_blit v.bits 0 b !pos n; 431 | pos := !pos + n) 432 | vl; 433 | res 434 | 435 | (* Testing for all zeros and all ones. *) 436 | 437 | let all_zeros v = 438 | let b = v.bits in 439 | let n = Bytes.length b in 440 | let rec test i = i == n || (byte b i == 0) && test (succ i) in 441 | test 0 442 | 443 | let all_ones v = 444 | let b = v.bits in 445 | let n = Bytes.length b in 446 | let rec test i = 447 | if i == n - 1 then 448 | let m = v.length land 7 in 449 | byte b i == if m == 0 then 0xFF else low_mask.(m) 450 | else 451 | byte b i == 0xFF && test (succ i) 452 | in 453 | n = 0 || test 0 454 | 455 | 456 | (* Shift operations. It is easy to reuse [unsafe_blit], although it is 457 | probably slightly less efficient than a ad-hoc piece of code. *) 458 | 459 | let rec shiftl v d = 460 | if d == 0 then 461 | copy v 462 | else if d < 0 then 463 | shiftr v (-d) 464 | else begin 465 | let n = v.length in 466 | let r = create n false in 467 | if d < n then unsafe_blit v.bits 0 r.bits d (n - d); 468 | r 469 | end 470 | 471 | and shiftr v d = 472 | if d == 0 then 473 | copy v 474 | else if d < 0 then 475 | shiftl v (-d) 476 | else begin 477 | let n = v.length in 478 | let r = create n false in 479 | if d < n then unsafe_blit v.bits d r.bits 0 (n - d); 480 | r 481 | end 482 | 483 | (* Rotate operations. It is easy to reuse [unsafe_blit], although it is 484 | probably slightly less efficient than an ad-hoc piece of code. *) 485 | 486 | let rec rotatel v d = 487 | if d < 0 then 488 | rotater v (-d) 489 | else 490 | let n = v.length in 491 | if d == 0 || n == 0 then 492 | copy v 493 | else begin 494 | let d = d mod n in 495 | let r = create n false in 496 | unsafe_blit v.bits 0 r.bits d (n - d); (* shiftl *) 497 | unsafe_blit v.bits (n - d) r.bits 0 d; (* wraparound ms to ls *) 498 | r 499 | end 500 | 501 | and rotater v d = 502 | if d < 0 then 503 | rotatel v (-d) 504 | else 505 | let n = v.length in 506 | if d == 0 || n == 0 then 507 | copy v 508 | else begin 509 | let d = d mod n in 510 | let r = create n false in 511 | unsafe_blit v.bits d r.bits 0 (n - d); (* shiftr *) 512 | unsafe_blit v.bits 0 r.bits (n - d) d; (* wraparound ls to ms *) 513 | r 514 | end 515 | 516 | (* Iteration on all bit vectors of length [n] using a Gray code. *) 517 | 518 | let first_set v n = 519 | let rec lookup i = 520 | if i = n then raise Not_found ; 521 | if unsafe_get v i then i else lookup (i + 1) 522 | in 523 | lookup 0 524 | 525 | let gray_iter f n = 526 | let bv = create n false in 527 | let rec iter () = 528 | f bv; 529 | unsafe_set bv 0 (not (unsafe_get bv 0)); 530 | f bv; 531 | let pos = succ (first_set bv n) in 532 | if pos < n then begin 533 | unsafe_set bv pos (not (unsafe_get bv pos)); 534 | iter () 535 | end 536 | in 537 | if n > 0 then iter () 538 | 539 | module S(I : sig val least_first : bool end) = struct 540 | 541 | let to_string v = 542 | let n = v.length in 543 | let s = Bytes.make n '0' in 544 | for i = 0 to n - 1 do 545 | if unsafe_get v i then Bytes.set s (if I.least_first then i else n-1-i) '1' 546 | done; 547 | Bytes.unsafe_to_string s 548 | 549 | let print fmt v = Format.pp_print_string fmt (to_string v) 550 | 551 | let of_string s = 552 | let n = String.length s in 553 | let v = create n false in 554 | for i = 0 to n - 1 do 555 | let c = String.unsafe_get s i in 556 | if c = '1' then 557 | unsafe_set v (if I.least_first then i else n-1-i) true 558 | else 559 | if c <> '0' then invalid_arg "Bitv.of_string" 560 | done; 561 | v 562 | 563 | end 564 | module L = S(struct let least_first = true end) 565 | module M = S(struct let least_first = false end) 566 | 567 | let tanimoto v1 v2 = 568 | let l = v1.length in 569 | if l <> v2.length then invalid_arg "Bitv.tanimoto"; 570 | let a = pop v1 in 571 | let b = pop v2 in 572 | let c = pop (bw_and v1 v2) in 573 | (float c) /. (float (a + b - c)) 574 | 575 | (* Input/output in a machine-independent format. *) 576 | 577 | let bytes_of_int x = 578 | Bytes.init 8 (fun i -> Char.chr ((x lsr (8 * i)) land 0xFF)) 579 | 580 | let int_of_bytes b = 581 | assert (Bytes.length b = 8); 582 | let rec build x i = 583 | if i < 0 then x 584 | else build ((x lsl 8) lor Char.code (Bytes.get b i)) (pred i) 585 | in 586 | build 0 7 587 | 588 | let nb_of_bytes len = 589 | len lsr 3 + if len land 7 = 0 then 0 else 1 590 | 591 | let to_bin write v = 592 | bytes_of_int v.length |> Bytes.iter write; 593 | Bytes.iter write v.bits 594 | 595 | let output_bin out_ch v = 596 | let write = output_char out_ch in 597 | to_bin write v 598 | 599 | let to_bytes t = 600 | let buf = Buffer.create 0 in 601 | let write x = Buffer.add_char buf x in 602 | to_bin write t; 603 | Buffer.to_bytes buf 604 | 605 | let of_bin read = 606 | let len = Bytes.init 8 (fun _ -> read ()) |> int_of_bytes in 607 | let v = create len false in 608 | let b = v.bits in 609 | for i = 0 to Bytes.length b - 1 do 610 | Bytes.unsafe_set b i (read ()) 611 | done; 612 | v 613 | 614 | let input_bin in_ch = 615 | let read () = input_char in_ch in 616 | of_bin read 617 | 618 | let of_bytes b = 619 | let read = 620 | let p = ref 0 in 621 | fun () -> let ret = Bytes.get b !p in incr p; ret in 622 | of_bin read 623 | 624 | (*s To/from integers. *) 625 | 626 | let of_int_gen len getbyte getbit = 627 | let v = create len false in 628 | for i = 0 to (len lsr 3) - 1 do set_byte v.bits i (getbyte i) done; 629 | for i = len land (lnot 7) to len - 1 do unsafe_set v i (getbit i) done; 630 | v 631 | 632 | let getbyte x i = (x lsr (8*i)) land 0xFF 633 | let getbit x i = (x lsr i) land 1 > 0 634 | let of_int_us x = 635 | of_int_gen (Sys.int_size - 1) (getbyte x) (getbit x) 636 | let of_int_s x = 637 | of_int_gen Sys.int_size (getbyte x) (getbit x) 638 | 639 | let to_int_gen zero shiftor v = 640 | let x = ref zero in 641 | Bytes.iteri (fun i c -> x := shiftor !x (Char.code c) (8*i)) v.bits; 642 | !x 643 | 644 | let shiftor x b i = x lor (b lsl i) 645 | let to_int_us v = 646 | (* if v.length < Sys.int_size - 1 then invalid_arg "Bitv.to_int_us"; *) 647 | to_int_gen 0 shiftor v 648 | let to_int_s v = 649 | (* if v.length < Sys.int_size then invalid_arg "Bitv.to_int_s"; *) 650 | to_int_gen 0 shiftor v 651 | 652 | let getbyte32 x i = 653 | Int32.to_int (Int32.logand (Int32.shift_right x (8*i)) 0xFFl) 654 | let getbit32 x i = 655 | Int32.logand (Int32.shift_right x i) 1l > 0l 656 | let of_int32_us x = 657 | of_int_gen 31 (getbyte32 x) (getbit32 x) 658 | let of_int32_s x = 659 | of_int_gen 32 (getbyte32 x) (getbit32 x) 660 | 661 | let shiftor32 x b i = Int32.logor x (Int32.shift_left (Int32.of_int b) i) 662 | let to_int32_us v = to_int_gen 0l shiftor32 v 663 | let to_int32_s v = to_int_gen 0l shiftor32 v 664 | 665 | let getbyte64 x i = 666 | Int64.to_int (Int64.logand (Int64.shift_right x (8*i)) 0xFFL) 667 | let getbit64 x i = 668 | Int64.logand (Int64.shift_right x i) 1L > 0L 669 | let of_int64_us x = 670 | of_int_gen 63 (getbyte64 x) (getbit64 x) 671 | let of_int64_s x = 672 | of_int_gen 64 (getbyte64 x) (getbit64 x) 673 | 674 | let shiftor64 x b i = Int64.logor x (Int64.shift_left (Int64.of_int b) i) 675 | let to_int64_us v = to_int_gen 0L shiftor64 v 676 | let to_int64_s v = to_int_gen 0L shiftor64 v 677 | 678 | (* [Nativeint] *) 679 | let select_of f32 f64 = match Sys.word_size with 680 | | 32 -> (fun i -> f32 (Nativeint.to_int32 i)) 681 | | 64 -> (fun i -> f64 (Int64.of_nativeint i)) 682 | | _ -> assert false 683 | let of_nativeint_s = select_of of_int32_s of_int64_s 684 | let of_nativeint_us = select_of of_int32_us of_int64_us 685 | let select_to f32 f64 = match Sys.word_size with 686 | | 32 -> (fun i -> Nativeint.of_int32 (f32 i)) 687 | | 64 -> (fun i -> Int64.to_nativeint (f64 i)) 688 | | _ -> assert false 689 | let to_nativeint_s = select_to to_int32_s to_int64_s 690 | let to_nativeint_us = select_to to_int32_us to_int64_us 691 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | This library is distributed under the terms of the GNU Lesser General 3 | Public License (LGPL) version 2.1 (included below) or any later 4 | version. 5 | 6 | In addition to the permissions granted to you by the LGPL, you may 7 | combine or link a "work that uses the Library" with a publicly 8 | distributed version of this file to produce a combined library or 9 | application, then distribute that combined work under the terms of 10 | your choosing, with no requirement to comply with the obligations 11 | normally placed on you by section 4 of the LGPL version 2.1 (or the 12 | corresponding section of a later version of the LGPL should you choose 13 | to use a later version). 14 | 15 | ---------------------------------------------------------------------- 16 | 17 | GNU LESSER GENERAL PUBLIC LICENSE 18 | 19 | Version 2.1, February 1999 20 | 21 | Copyright (C) 1991, 1999 Free Software Foundation, Inc. 22 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 23 | Everyone is permitted to copy and distribute verbatim copies 24 | of this license document, but changing it is not allowed. 25 | 26 | [This is the first released version of the Lesser GPL. It also counts 27 | as the successor of the GNU Library Public License, version 2, hence 28 | the version number 2.1.] 29 | 30 | Preamble 31 | 32 | The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. 33 | 34 | This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. 35 | 36 | When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. 37 | 38 | To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. 39 | 40 | For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. 41 | 42 | We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. 43 | 44 | To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. 45 | 46 | Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. 47 | 48 | Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. 49 | 50 | When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. 51 | 52 | We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. 53 | 54 | For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. 55 | 56 | In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. 57 | 58 | Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. 59 | 60 | The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. 61 | 62 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 63 | 64 | 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". 65 | 66 | A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. 67 | 68 | The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) 69 | 70 | "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. 71 | 72 | Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 73 | 74 | 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. 75 | 76 | You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 77 | 78 | 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: 79 | 80 | a) The modified work must itself be a software library. 81 | b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. 82 | c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. 83 | d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. 84 | 85 | (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) 86 | 87 | These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. 88 | 89 | Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. 90 | 91 | In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 92 | 93 | 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. 94 | 95 | Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. 96 | 97 | This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 98 | 99 | 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. 100 | 101 | If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 102 | 103 | 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. 104 | 105 | However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. 106 | 107 | When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. 108 | 109 | If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) 110 | 111 | Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 112 | 113 | 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. 114 | 115 | You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: 116 | 117 | a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) 118 | b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. 119 | c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. 120 | d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. 121 | e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. 122 | 123 | For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. 124 | 125 | It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 126 | 127 | 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: 128 | 129 | a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. 130 | b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 131 | 132 | 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 133 | 134 | 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 135 | 136 | 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 137 | 138 | 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. 139 | 140 | If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. 141 | 142 | It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. 143 | 144 | This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 145 | 146 | 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 147 | 148 | 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. 149 | 150 | Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 151 | 152 | 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. 153 | 154 | NO WARRANTY 155 | 156 | 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 157 | 158 | 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 159 | END OF TERMS AND CONDITIONS 160 | 161 | How to Apply These Terms to Your New Libraries 162 | 163 | If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). 164 | 165 | To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. 166 | 167 | one line to give the library's name and an idea of what it does. 168 | Copyright (C) year name of author 169 | 170 | This library is free software; you can redistribute it and/or 171 | modify it under the terms of the GNU Lesser General Public 172 | License as published by the Free Software Foundation; either 173 | version 2.1 of the License, or (at your option) any later version. 174 | 175 | This library is distributed in the hope that it will be useful, 176 | but WITHOUT ANY WARRANTY; without even the implied warranty of 177 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 178 | Lesser General Public License for more details. 179 | 180 | You should have received a copy of the GNU Lesser General Public 181 | License along with this library; if not, write to the Free Software 182 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 183 | 184 | Also add information on how to contact you by electronic and paper mail. 185 | 186 | You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: 187 | 188 | Yoyodyne, Inc., hereby disclaims all copyright interest in 189 | the library `Frob' (a library for tweaking knobs) written 190 | by James Random Hacker. 191 | 192 | signature of Ty Coon, 1 April 1990 193 | Ty Coon, President of Vice 194 | 195 | That's all there is to it! 196 | 197 | -------------------------------------------------- 198 | --------------------------------------------------------------------------------