package linksem
A formalisation of the core ELF and DWARF file formats written in Lem
Install
Dune Dependency
Authors
Maintainers
Sources
0.8.tar.gz
md5=2075c56715539b3b8f54ae65cc808b8c
sha512=f7c16e4036a1440a6a8d13707a43f0f9f9db0c68489215f948cc300b6a164dba5bf852e58f89503e9d9f38180ee658d9478156ca1a1ef64d6861eec5f9cf43d2
doc/src/linksem_zarith/multimap.ml.html
Source file multimap.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
(*Generated by Lem from multimap.lem.*) open Lem_bool open Lem_basic_classes open Lem_maybe open Lem_function open Lem_num open Lem_list open Lem_set open Lem_set_extra open Lem_assert_extra open Missing_pervasives open Lem_string open Show (* HMM. Is the right thing instead to implement multiset first? Probably. *) (* This is a set of pairs * augmented with operations implementing a particular kind of * map. * * This map differs from the Lem map in the following ways. * * 0. The basic idea: it's a multimap, so a single key, supplied as a "query", * can map to many (key, value) results. * But PROBLEM: how do we store them in a tree? We're using OCaml's * Set implementation underneath, and that doesn't allow duplicates. * * 1. ANSWER: require keys still be unique, but that the user supplies an * equivalence relation on them, which * is coarser-grained than the ordering relation * used to order the set. It must be consistent with it, though: * equivalent keys should appear as a contiguous range in the * ordering. * * 2. This allows many "non-equal" keys, hence present independently * in the set of pairs, to be "equivalent" for the purposes of a * query. * * 3. The coarse-grained equivalence relation can be supplied on a * per-query basis, meaning that different queries on the same * set can query by finer or coarser criteria (while respecting * the requirement to be consistent with the ordering). * * Although this seems more complicated than writing a map from * k to list (k, v), which would allow us to ditch the finer ordering, * it scales better (no lists) and allows certain range queries which * would be harder to implement under that approach. It also has the * nice property that the inverse multimap is represented as the same * set but with the pairs reversed. *) type( 'k, 'v) multimap = ('k * 'v) Pset.set (* In order for bisection search within a set to work, * we need the equivalence class to tell us whether we're less than or * greater than the members of the key's class. * It effectively identifies a set of ranges. *) type 'k key_equiv = 'k -> 'k -> bool (* val hasMapping : forall 'k 'v. key_equiv 'k -> multimap 'k 'v -> bool let inline hasMapping equiv m = *) (* val mappingCount : forall 'k 'v. key_equiv 'k -> multimap 'k 'v -> natural val any : forall 'k 'v. ('k -> 'v -> bool) -> multimap 'k 'v -> bool val all : forall 'k 'v. ('k -> 'v -> bool) -> multimap 'k 'v -> bool *) (*val findLowestKVWithKEquivTo : forall 'k 'v. Ord 'k, Ord 'v, SetType 'k, SetType 'v => 'k -> key_equiv 'k -> multimap 'k 'v -> maybe ('k * 'v) -> maybe ('k * 'v)*) let rec findLowestKVWithKEquivTo dict_Basic_classes_Ord_k dict_Basic_classes_Ord_v dict_Basic_classes_SetType_k dict_Basic_classes_SetType_v k equiv subSet maybeBest:('k*'v)option= ((match Pset.choose_and_split subSet with None -> (* empty subset *) maybeBest | Some(lower, ((chosenK: 'k), (chosenV : 'v)), higher) -> (* is k equiv to chosen? *) if equiv k chosenK then (* is chosen less than our current best? *) let (bestK, bestV) = ((match maybeBest with None -> (chosenK, chosenV) | Some(currentBestK, currentBestV) -> if pairLess dict_Basic_classes_Ord_v dict_Basic_classes_Ord_k (chosenK, chosenV) (currentBestK, currentBestV) then (chosenK, chosenV) else (currentBestK, currentBestV) )) in (* recurse down lower subSet; best is whichever is lower *) findLowestKVWithKEquivTo dict_Basic_classes_Ord_k dict_Basic_classes_Ord_v dict_Basic_classes_SetType_k dict_Basic_classes_SetType_v k equiv lower (Some(bestK, bestV)) else (* k is not equiv to chosen; do we need to look lower or higher? *) if dict_Basic_classes_Ord_k.isLess_method k chosenK then (* k is lower, so look lower for equivs-to-k *) findLowestKVWithKEquivTo dict_Basic_classes_Ord_k dict_Basic_classes_Ord_v dict_Basic_classes_SetType_k dict_Basic_classes_SetType_v k equiv lower maybeBest else (* k is higher *) findLowestKVWithKEquivTo dict_Basic_classes_Ord_k dict_Basic_classes_Ord_v dict_Basic_classes_SetType_k dict_Basic_classes_SetType_v k equiv higher maybeBest )) (*val testEquiv : natural -> natural -> bool*) let testEquiv x y:bool= (if ( Nat_big_num.greater_equal x( (Nat_big_num.of_int 3)) && (Nat_big_num.less x( (Nat_big_num.of_int 5)) && (Nat_big_num.greater_equal y( (Nat_big_num.of_int 3)) && Nat_big_num.less_equal y( (Nat_big_num.of_int 5))))) then true else if ( Nat_big_num.less x( (Nat_big_num.of_int 3)) && Nat_big_num.less y( (Nat_big_num.of_int 3))) then true else if ( Nat_big_num.greater x( (Nat_big_num.of_int 5)) && Nat_big_num.greater y( (Nat_big_num.of_int 5))) then true else false) (* assert lowest_simple: findLowestKVWithKEquivTo 4 testEquiv ({ (1, 0); (2, 0); (3, 0); (4, 0); (5, 0); (6, 0) } : set (natural * natural)) Nothing = Just (3, 0) assert lowest_kv: findLowestKVWithKEquivTo 4 testEquiv ({ (1, 0); (2, 0); (3, 0); (3, 1); (4, 0); (5, 0); (6, 0) } : set (natural * natural)) Nothing = Just (3, 0) assert lowest_empty: findLowestKVWithKEquivTo 4 testEquiv ({} : set (natural * natural)) Nothing = Nothing assert lowest_onepast: findLowestKVWithKEquivTo 4 testEquiv ({ (6, 0) } : set (natural * natural)) Nothing = Nothing assert lowest_oneprev: findLowestKVWithKEquivTo 4 testEquiv ({ (2, 0) } : set (natural * natural)) Nothing = Nothing *) (* Note we can't just use findLowestEquiv with inverted relations, because * chooseAndSplit returns us (lower, chosen, higher) and we need to swap * around how we consume that. *) (*val findHighestKVWithKEquivTo : forall 'k 'v. Ord 'k, Ord 'v, SetType 'k, SetType 'v => 'k -> key_equiv 'k -> multimap 'k 'v -> maybe ('k * 'v) -> maybe ('k * 'v)*) let rec findHighestKVWithKEquivTo dict_Basic_classes_Ord_k dict_Basic_classes_Ord_v dict_Basic_classes_SetType_k dict_Basic_classes_SetType_v k equiv subSet maybeBest:('k*'v)option= ((match Pset.choose_and_split subSet with None -> (* empty subset *) maybeBest | Some(lower, ((chosenK: 'k), (chosenV : 'v)), higher) -> (* is k equiv to chosen? *) if equiv k chosenK then (* is chosen greater than our current best? *) let (bestK, bestV) = ((match maybeBest with None -> (chosenK, chosenV) | Some(currentBestK, currentBestV) -> if pairGreater dict_Basic_classes_Ord_k dict_Basic_classes_Ord_v (chosenK, chosenV) (currentBestK, currentBestV) then (chosenK, chosenV) else (currentBestK, currentBestV) )) in (* recurse down higher-than-chosen subSet; best is whichever is higher *) findHighestKVWithKEquivTo dict_Basic_classes_Ord_k dict_Basic_classes_Ord_v dict_Basic_classes_SetType_k dict_Basic_classes_SetType_v k equiv higher (Some(bestK, bestV)) else (* k is not equiv to chosen; do we need to look lower or higher? * NOTE: the pairs in the set must be lexicographically ordered! *) if dict_Basic_classes_Ord_k.isGreater_method k chosenK then (* k is higher than chosen, so look higher for equivs-to-k *) findHighestKVWithKEquivTo dict_Basic_classes_Ord_k dict_Basic_classes_Ord_v dict_Basic_classes_SetType_k dict_Basic_classes_SetType_v k equiv higher maybeBest else (* k is lower than chosen, so look lower *) findHighestKVWithKEquivTo dict_Basic_classes_Ord_k dict_Basic_classes_Ord_v dict_Basic_classes_SetType_k dict_Basic_classes_SetType_v k equiv lower maybeBest )) (* let _ = Missing_pervasives.errln ("choose_and_split {3, 4, 5} is " ^ (match Set_extra.chooseAndSplit ({3;4;5} : set natural) with Just (l, m, r) -> (show (toList l, m, toList r)) | Nothing -> "Nothing" end)) *) (* assert highest_simple: findHighestKVWithKEquivTo 4 testEquiv ({ (1, 0); (2, 0); (3, 0); (4, 0); (5, 0); (6, 0) } : set (natural * natural)) Nothing = Just (5, 0) assert highest_kv: findHighestKVWithKEquivTo 4 testEquiv ({ (1, 0); (2, 0); (3, 0); (4, 0); (5, 0); (5, 1); (6, 0) } : set (natural * natural)) Nothing = Just (5, 1) assert highest_empty: findHighestKVWithKEquivTo 4 testEquiv ({} : set (natural * natural)) Nothing = Nothing assert highest_onepast: findHighestKVWithKEquivTo 4 testEquiv ({ (6, 0) } : set (natural * natural)) Nothing = Nothing assert highest_oneprev: findHighestKVWithKEquivTo 4 testEquiv ({ (2, 0) } : set (natural * natural)) Nothing = Nothing *) (* get the list of all pairs with key equiv to k. *) (*val lookupBy : forall 'k 'v. Ord 'k, Ord 'v, SetType 'k, SetType 'v => key_equiv 'k -> 'k -> multimap 'k 'v -> list ('k * 'v)*) let lookupBy0 dict_Basic_classes_Ord_k dict_Basic_classes_Ord_v dict_Basic_classes_SetType_k dict_Basic_classes_SetType_v equiv k m:('k*'v)list= ( (* Find the lowest and highest elements equiv to k. * We do this using chooseAndSplit recursively. *)(match findLowestKVWithKEquivTo dict_Basic_classes_Ord_k dict_Basic_classes_Ord_v dict_Basic_classes_SetType_k dict_Basic_classes_SetType_v k equiv m None with None -> [] | Some lowestEquiv -> let (highestEquiv : ('k * 'v)) = ( (* We can't just invert the relation on the set, because * the whole set is ordered *)(match findHighestKVWithKEquivTo dict_Basic_classes_Ord_k dict_Basic_classes_Ord_v dict_Basic_classes_SetType_k dict_Basic_classes_SetType_v k equiv m None with None -> failwith "impossible: lowest equiv but no highest equiv" | Some highestEquiv -> highestEquiv )) in (* FIXME: split is currently needlessly inefficient on OCaml! *) let (lowerThanLow, highEnough) = (Lem_set.split (instance_Basic_classes_SetType_tup2_dict dict_Basic_classes_SetType_k dict_Basic_classes_SetType_v) (instance_Basic_classes_Ord_tup2_dict dict_Basic_classes_Ord_k dict_Basic_classes_Ord_v) lowestEquiv m) in let (wanted, tooHigh) = (Lem_set.split (instance_Basic_classes_SetType_tup2_dict dict_Basic_classes_SetType_k dict_Basic_classes_SetType_v) (instance_Basic_classes_Ord_tup2_dict dict_Basic_classes_Ord_k dict_Basic_classes_Ord_v) highestEquiv highEnough) in (* NOTE that lowestEquiv is a single element; we want to include * *all those equiv to it*, which may be non-equal. FIXME: use splitMember, * although that needs fixing in Lem (plus an optimised OCaml version). *) List.rev_append (List.rev (List.rev_append (List.rev (Pset.elements (let x2 =(Pset.from_list (pairCompare dict_Basic_classes_SetType_k.setElemCompare_method dict_Basic_classes_SetType_v.setElemCompare_method) []) in Pset.fold (fun s x2 -> if Lem.orderingEqual 0 (pairCompare dict_Basic_classes_Ord_k.compare_method dict_Basic_classes_Ord_v.compare_method s lowestEquiv) then Pset.add s x2 else x2) m x2))) (Pset.elements wanted))) ( (* don't include the lowest and highest twice, if they're the same *) if pairLess dict_Basic_classes_Ord_v dict_Basic_classes_Ord_k lowestEquiv highestEquiv then (Pset.elements (let x2 =(Pset.from_list (pairCompare dict_Basic_classes_SetType_k.setElemCompare_method dict_Basic_classes_SetType_v.setElemCompare_method) []) in Pset.fold (fun s x2 -> if Lem.orderingEqual 0 (pairCompare dict_Basic_classes_Ord_k.compare_method dict_Basic_classes_Ord_v.compare_method s highestEquiv) then Pset.add s x2 else x2) m x2)) else [] ) )) (* let _ = Missing_pervasives.errln ("lookupBy testEquiv 4 { (1, 0); (2, 0); (3, 0); (4, 0); (5, 0); (6, 0) } is : " ^ (show (lookupBy testEquiv 4 ({ (1, 0); (2, 0); (3, 0); (4, 0); (5, 0); (6, 0) } : set (natural * natural))))) *) (* assert lookup_simple : lookupBy testEquiv 4 ({ (1, 0); (2, 0); (3, 0); (4, 0); (5, 0); (6, 0) } : set (natural * natural)) = ([(3, 0); (4, 0); (5, 0)] : list (natural * natural)) assert lookup_kv : lookupBy testEquiv 4 ({ (1, 0); (2, 0); (3, 0); (4, 0); (4, 1); (5, 0); (6, 0) } : set (natural * natural)) = ([(3, 0); (4, 0); (4, 1); (5, 0)] : list (natural * natural)) assert lookup_empty: lookupBy testEquiv 4 ({} : set (natural * natural)) = ([]: list (natural * natural)) assert lookup_singleton: lookupBy testEquiv 4 ({(5, 0)} : set (natural * natural)) = ([(5, 0)]: list (natural * natural)) assert lookup_onepast: lookupBy testEquiv 4 ({ (6, 0) } : set (natural * natural)) = ([] : list (natural * natural)) assert lookup_oneprev: lookupBy testEquiv 4 ({ (2, 0) } : set (natural * natural)) = ([] : list (natural * natural)) *) (* To delete all pairs with key equiv to k, can use deleteBy *)
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>