Skip to content

Commit

Permalink
Merge branch 'main' into mdx
Browse files Browse the repository at this point in the history
  • Loading branch information
dlesbre committed May 15, 2024
2 parents d941eb7 + a702db3 commit cf805e7
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 46 deletions.
19 changes: 13 additions & 6 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,32 @@

## Detailed changes

**Breaking changes:**
- Renamed `MakeCustom` to `MakeCustomMap`, added new functor `MakeCustomSet`.
`MakeCustomMap` changed to take a new argument to specify the `'a value` type.
- Renamed `MakeCustomHeterogeneous` to `MakeCustomHeterogeneousMap`, added new functor
`MakeCustomHeterogeneousSet`.
- Renamed `NODE_WITH_ID.get_id` to `NODE_WITH_ID.to_int`, this allows using
instances `NODE_WITH_ID` directly as a `KEY`.
- Renamed `VALUE` to `HETEROGENEOUS_VALUE`, added a `VALUE` module type (previously unnamed).
- Renamed `min_binding`, `max_binding`, `pop_minimum`, `pop_maximum`, `min_elt`
and `max_elt` to `unsigned_min_binding`, `unsigned_max_binding`,
`pop_unsigned_minimum`, `pop_unsigned_maximum`, `unsigned_min_elt`
and `unsigned_max_elt` respectively, to clarify that these functions consider
negative numbers as larger than positive ones.

**New features:**
- Added new interface `MAP_WITH_VALUE` which is the same as `MAP` but with a custom
type `'a value` instead of just `'a`.
- `MakeCustomMap` changed to take a new argument to specify the `'a value` type.
- Added `HashconsedNode`, `HashconsedSetNode` as well as four functors to create
hash-consed heterogeneous/homogeneous maps/sets: `MakeHashconsedMap`, `MakeHashconsedSet`,
`MakeHashconsedHeterogeneousMap` and `MakeHashconsedHeterogeneousSet`.
- Now support using negative keys. Trees are built using the bitwise representation
of integer, meaning they effectively use an unsigned order. Negative keys are
considered bigger than positive keys, `0` is the minimal number and `-1` the maximal one.
- Renamed `min_binding`, `max_binding`, `pop_minimum`, `pop_maximum`, `min_elt`
and `max_elt` to `unsigned_min_binding`, `unsigned_max_binding`,
`pop_unsigned_minimum`, `pop_unsigned_maximum`, `unsigned_min_elt`
and `unsigned_max_elt` respectively, to clarify that these functions consider
negative numbers as larger than positive ones.
- Added new functions `fold_on_nonequal_inter` and `fold_on_nonequal_union` to maps.

**Bug fixes:**
- Fixed a bug where `NodeWithId` wasn't incrementing ids properly
- `zarith` is no longer a dependency, used GCC's `__builtin_clz` as a faster
method of finding an integer's highest bit.
Expand Down
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,8 @@ dune build @doc
- hash-consed versions of heterogeneous/homogeneous maps/sets are
available. These provide constant time equality and comparison, and ensure
maps/set with the same constants are always physically equal. It comes at the cost
of more memory usage a slightly slower constructors.
of a constant overhead in memory usage (at worst, as hash-consing may allow memory gains) and constant time overhead
when calling constructors.

## Quick overview

Expand Down Expand Up @@ -137,6 +138,10 @@ These uniquely number their nodes, which means:
the documentation of `HASHED_VALUE.polyeq` for details.
Note that this is the case in the default implementations `HashedValue`
and `HeterogeneousHashedValue`.
- All hash-consing functors are **generative**, since each functor call will
create a new hash-table to store the created nodes. Calling a functor
twice with same arguments will lead to two numbering systems for identifiers,
and thus the types should not be considered compatible.

### Interfaces

Expand Down
7 changes: 6 additions & 1 deletion index.mld
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,8 @@ dune build @doc
{li Additionally, hashconsed versions of heterogeneous/homogeneous maps/sets are
available. These provide constant time equality and comparison, and ensure
maps/set with the same constants are always physically equal. It comes at the cost
of more memory usage a slightly slower constructors.}}
of a constant overhead in memory usage (at worst, as hash-consing may allow
memory gains) and constant time overhead when calling constructors.}}

{1 Quick overview}

Expand Down Expand Up @@ -130,6 +131,10 @@ The functors used to build maps and sets are the following:
Note that this is the case in the default implementations
{{!PatriciaTree.HashedValue}[HashedValue]}
and {{!PatriciaTree.HeterogeneousHashedValue}[HeterogeneousHashedValue]}.
- All hash-consing functors are {b generative}, since each functor call will
create a new hash-table to store the created nodes. Calling a functor
twice with same arguments will lead to two numbering systems for identifiers,
and thus the types should not be considered compatible.
}}

{2 Interfaces}
Expand Down
30 changes: 15 additions & 15 deletions patriciaTree.ml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ end

module type NODE_WITH_ID = sig
include NODE
val get_id: 'a t -> int
val to_int: 'a t -> int
end

module type HASH_CONSED_NODE = sig
Expand Down Expand Up @@ -495,7 +495,7 @@ module NodeWithId(Key:sig type 'a t end)(Value:HETEROGENEOUS_VALUE):NODE_WITH_ID
| NBranch{prefix;branching_bit;tree0;tree1;_} -> Branch{prefix;branching_bit;tree0;tree1}
| NLeaf{key;value;_} -> Leaf{key;value}

let get_id = function
let to_int = function
| NEmpty -> 0
| NBranch{id;_} -> id
| NLeaf{id;_} -> id
Expand Down Expand Up @@ -633,7 +633,7 @@ module HashconsedNode(Key:HETEROGENEOUS_KEY)(Value:HETEROGENEOUS_HASHED_VALUE)()
| NBranch{prefix;branching_bit;tree0;tree1;_} -> Branch{prefix;branching_bit;tree0;tree1}
| NLeaf{key;value;_} -> Leaf{key;value}

let get_id = function
let to_int = function
| NEmpty -> 0
| NBranch{ id; _ } -> id
| NLeaf{ id; _ } -> id
Expand All @@ -654,7 +654,7 @@ module HashconsedNode(Key:HETEROGENEOUS_KEY)(Value:HETEROGENEOUS_HASHED_VALUE)()
| NBranch{prefix=prefixa;branching_bit=branching_bita;tree0=tree0a;tree1=tree1a;_},
NBranch{prefix=prefixb;branching_bit=branching_bitb;tree0=tree0b;tree1=tree1b;_} ->
prefixa == prefixb && branching_bita == branching_bitb &&
get_id tree0a = get_id tree0b && get_id tree1a = get_id tree1b
to_int tree0a = to_int tree0b && to_int tree1a = to_int tree1b
| _ -> false

let hash (AnyMap x) = match x with
Expand All @@ -664,7 +664,7 @@ module HashconsedNode(Key:HETEROGENEOUS_KEY)(Value:HETEROGENEOUS_HASHED_VALUE)()
(hash lsl 1) lor 1
(* All leaf hashes are odd *)
| NBranch{prefix; branching_bit; tree0; tree1; _} -> (* All branch hashes are even *)
(sdbm (prefix lor branching_bit) @@ sdbm (get_id tree0) (get_id tree1)) lsl 1
(sdbm (prefix lor branching_bit) @@ sdbm (to_int tree0) (to_int tree1)) lsl 1
end

module WeakHash = Weak.Make(HashArg)
Expand All @@ -688,8 +688,8 @@ module HashconsedNode(Key:HETEROGENEOUS_KEY)(Value:HETEROGENEOUS_HASHED_VALUE)()
| x, NEmpty -> x
| _ -> try_find (NBranch{prefix;branching_bit;tree0;tree1;id=(!count)})

let equal x y = Int.equal (get_id x) (get_id y)
let compare x y = Int.compare (get_id x) (get_id y)
let equal x y = x == y
let compare x y = Int.compare (to_int x) (to_int y)
end

module HashconsedSetNode(Key:HETEROGENEOUS_KEY)(): HASH_CONSED_NODE
Expand All @@ -715,7 +715,7 @@ module HashconsedSetNode(Key:HETEROGENEOUS_KEY)(): HASH_CONSED_NODE
| NBranch{prefix;branching_bit;tree0;tree1;_} -> Branch{prefix;branching_bit;tree0;tree1}
| NLeaf{ key; _ } -> Leaf{ key; value=() }

let get_id = function
let to_int = function
| NEmpty -> 0
| NBranch{ id; _ } -> id
| NLeaf{ id; _ } -> id
Expand All @@ -741,7 +741,7 @@ module HashconsedSetNode(Key:HETEROGENEOUS_KEY)(): HASH_CONSED_NODE
| NEmpty -> 0
| NLeaf{key; _} -> ((Key.to_int key) lsl 1) lor 1 (* All leaf hashes are odd *)
| NBranch{prefix; branching_bit; tree0; tree1; _} -> (* All branch hashes are even *)
(sdbm (prefix lor branching_bit) @@ sdbm (get_id tree0) (get_id tree1)) lsl 1
(sdbm (prefix lor branching_bit) @@ sdbm (to_int tree0) (to_int tree1)) lsl 1
end

module WeakHash = Weak.Make(HashArg)
Expand All @@ -764,8 +764,8 @@ module HashconsedSetNode(Key:HETEROGENEOUS_KEY)(): HASH_CONSED_NODE
| x, NEmpty -> x
| _ -> try_find (NBranch{prefix;branching_bit;tree0;tree1;id=(!count)})

let equal x y = Int.equal (get_id x) (get_id y)
let compare x y = Int.compare (get_id x) (get_id y)
let equal x y = x == y
let compare x y = Int.compare (to_int x) (to_int y)
end

(** {1 Keys and values} *)
Expand Down Expand Up @@ -1952,7 +1952,7 @@ module MakeHashconsedHeterogeneousMap(Key:HETEROGENEOUS_KEY)(Value:HETEROGENEOUS

let equal = Node.equal
let compare = Node.compare
let get_id = Node.get_id
let to_int = Node.to_int
end

module MakeHashconsedHeterogeneousSet(Key:HETEROGENEOUS_KEY)() = struct
Expand All @@ -1961,15 +1961,15 @@ module MakeHashconsedHeterogeneousSet(Key:HETEROGENEOUS_KEY)() = struct

let equal = Node.equal
let compare = Node.compare
let get_id = Node.get_id
let to_int = Node.to_int
end

module MakeHashconsedSet(Key : KEY)() = struct
module Node = HashconsedSetNode(HeterogeneousKeyFromKey(Key))()
include MakeCustomSet(Key)(Node)
let equal = Node.equal
let compare = Node.compare
let get_id = Node.get_id
let to_int = Node.to_int
end

module MakeHashconsedMap(Key: KEY)(Value: HASHED_VALUE)() = struct
Expand All @@ -1979,5 +1979,5 @@ module MakeHashconsedMap(Key: KEY)(Value: HASHED_VALUE)() = struct

let equal = Node.equal
let compare = Node.compare
let get_id = Node.get_id
let to_int = Node.to_int
end
Loading

0 comments on commit cf805e7

Please sign in to comment.