Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
90 commits
Select commit Hold shift + click to select a range
934cf98
Copied lineartwovarequalityanalysis and domain, including tests
leunam99 Jan 17, 2025
41135b8
added intervals, does not work yet
leunam99 Feb 3, 2025
231e164
Simple tests are working, no regression failures anymore
leunam99 Feb 5, 2025
5bdf17f
extended conditions + small cleanup
leunam99 Feb 10, 2025
f2e1fb6
Add config for gobcron testing
leunam99 Feb 12, 2025
003f332
second conf for testing
leunam99 Feb 14, 2025
8e5ff62
Take advantage of congruence information for refinement and asserts
leunam99 Feb 15, 2025
1d6ebc2
Fixes for meeting returning bot, Small cleanup
leunam99 Feb 17, 2025
a1b3eba
Fix refinement leading to bot, but not propagating
leunam99 Feb 17, 2025
e77e800
Fix evaluation using new context
leunam99 Feb 17, 2025
e30d79f
Modulo conditions supported
leunam99 Feb 18, 2025
e31836a
Fixed join not considering congruence constraints generated by rhs
leunam99 Feb 18, 2025
f215565
Fixed modular inverse for negative numbers, small adaptations
leunam99 Feb 19, 2025
5542e79
Indentation
leunam99 Feb 19, 2025
6da7797
Revert changes to affine_transform
leunam99 Feb 19, 2025
a84c202
More flexible invariant handling, refining all occuring vars
leunam99 Feb 22, 2025
7b7e55f
Better bounds checking for overflow, regression tests
leunam99 Feb 25, 2025
d5ec239
Splitting Subdomains into a separate file. Change function names ment…
leunam99 Feb 26, 2025
ce074de
Added Interface for Inequalities and integrated it into the lin2var_p…
leunam99 Feb 28, 2025
9e61cec
Simple Inequalities implemented, but not completely tested
leunam99 Mar 3, 2025
17047fa
transfering inequalities when assigning, bug fix in to_inequalities
leunam99 Mar 6, 2025
34331f1
Integrate Interval / Congruence with bounds into the original files
leunam99 Mar 6, 2025
c74832f
Use queries when assigning expressions
leunam99 Mar 6, 2025
2deec18
Fixed small bugs
leunam99 Mar 6, 2025
3fee377
Fixed more bugs
leunam99 Mar 6, 2025
280be0d
Fixed forget_variable not keeping invariant when root was deleted, ad…
leunam99 Mar 7, 2025
b602814
Make InEq stay sparse
leunam99 Mar 7, 2025
99ed24b
Fixed get_value not returning correct congruence information. Make al…
leunam99 Mar 7, 2025
cfad8f6
Revert changes to affine_transform, add comment why this is correct
leunam99 Mar 8, 2025
87bba0c
Make Termination Analysis use new domain instead of apron polyhedra (…
leunam99 Mar 11, 2025
8489b54
Fix TopIntOps returning usefull values for widening when bound is top
leunam99 Mar 11, 2025
2ccdc55
start of Complex linear inequalities, make join part of common action…
leunam99 Mar 20, 2025
937c0fc
fix accidentialy duplicated regression test
leunam99 Mar 20, 2025
6e8ee16
finish linear inequalities, generate inequalities with offset, allow …
leunam99 Mar 25, 2025
03b9f0a
small fixes, debugging output
leunam99 Mar 25, 2025
8788cdd
more fixing
leunam99 Mar 25, 2025
5b8fa24
make sure we only save relations for the roots, simple transfering
leunam99 Mar 26, 2025
582919b
remove value when the variable is replaced by a constant
leunam99 Mar 26, 2025
2222c20
fixed using wrong variable to calculate value refinements
leunam99 Mar 27, 2025
2ac6636
fixed looking at wrong bound in interval
leunam99 Mar 27, 2025
06bde16
larger rework of linear inequalities
leunam99 Apr 10, 2025
7ae6dda
first round of fixes
leunam99 Apr 10, 2025
f42c066
second round of fixes
leunam99 Apr 10, 2025
9b521db
make it non-strict equalities
leunam99 Apr 11, 2025
457ec76
missed value refinement
leunam99 Apr 11, 2025
e309216
more off-by-one errors
leunam99 Apr 11, 2025
7e29720
fix widening (and leq?)
leunam99 Apr 11, 2025
2d72269
leq fixed now?
leunam99 Apr 11, 2025
2cba0cf
another fix for leq where different kinds of bot did not return the c…
leunam99 Apr 11, 2025
0d22d78
join implement splitting
leunam99 Apr 26, 2025
2d4da5d
cache slopes
leunam99 Apr 26, 2025
cf60376
reworked limit to be lazy and need less memory
leunam99 Apr 29, 2025
549b38a
invariant implemented, TODO cleanup and sorting
leunam99 May 2, 2025
64f0810
fix substitution not handeling swapping sides
leunam99 May 2, 2025
c3a6db2
small fixes
leunam99 May 2, 2025
8c4de9f
renaming GT/LT to GE/LE to better reflect current purpose. Bugfixing …
leunam99 May 3, 2025
41f69c2
small fix: order correctly
leunam99 May 3, 2025
992c54c
refinement: general structure, allow for equality refinement, refine …
leunam99 May 3, 2025
069d3de
allow conversion to tcons for inverted conditions
leunam99 May 3, 2025
3ed88f2
refinement: refinement everywhere + some cleanup
leunam99 May 6, 2025
5d8207c
leq: do value refinement until fixpoint to properly represent relatio…
leunam99 May 7, 2025
b825fc0
in meet_relation, add some transitive inequalities. small fixes and c…
leunam99 May 12, 2025
40b19c0
small fixes
leunam99 May 12, 2025
9c534db
more fixes
leunam99 May 13, 2025
b2e7eaa
fixed join not being monotonic, also join inequalities where the othe…
leunam99 May 16, 2025
2dacbbe
accelerated narrowing, formatting
leunam99 May 19, 2025
22eb2b3
Allow division in linear relation if congruence proves exactness, sma…
leunam99 May 21, 2025
de4e5bb
do not lose value information when entering a function body
leunam99 May 23, 2025
17e223b
add missing
leunam99 Jun 14, 2025
3902ccc
Merge remote-tracking branch 'goblint/master'
leunam99 Jun 14, 2025
bc169d8
Rename file
leunam99 Jun 14, 2025
6890fa9
forgot adding dune file
leunam99 Jun 15, 2025
3019518
add weaker domains, proper options
leunam99 Jun 19, 2025
567301b
forgot staging formatting
leunam99 Jun 19, 2025
3c2b527
Merge branch 'goblint:master' into master
leunam99 Jun 23, 2025
287a6eb
keep map properly sparse, small fixes
leunam99 Jun 23, 2025
7ee3c88
use succ / pred
leunam99 Jun 23, 2025
1cc06dc
delete configuration for testing
leunam99 Jun 23, 2025
8ce2066
small fixes, remove asserts for performance
leunam99 Jun 24, 2025
d626bbd
fixed bug in join
leunam99 Jun 24, 2025
ec41fb5
revert last commit and include actual fix
leunam99 Jun 29, 2025
67f4207
Fix wrong results and other bugs, remove unused top function
leunam99 Jul 2, 2025
d00764a
fixes: do not report overflow in conversions to base, nontermination …
leunam99 Jul 5, 2025
7bc66ac
reenable interval narrowing after fixing underlying bug, disable asse…
leunam99 Jul 6, 2025
c093c14
fix regression test: wrong optimisation of join. Cleanup TODOs
leunam99 Jul 7, 2025
8426027
Merge branch 'master' into master
DrMichaelPetter Jul 16, 2025
d6f829f
move regression tests
leunam99 Jul 18, 2025
e9ef54f
Merge remote-tracking branch 'goblint/master'
leunam99 Jul 18, 2025
9ff7ece
Ignore division by zero in speculative execution
leunam99 Jul 22, 2025
de46b15
use Seq instead of Enum
leunam99 Jul 26, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions src/analyses/apron/linearTwoVarEqualityAnalysisPentagon.apron.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
(** {{!RelationAnalysis} Relational integer value analysis} using an OCaml implementation of the linear two-variable equalities domain ([lin2vareq]).

@see <http://doi.acm.org/10.1145/2049706.2049710> A. Flexeder, M. Petter, and H. Seidl Fast Interprocedural Linear Two-Variable Equalities. *)

open Analyses
include RelationAnalysis

module NoIneq = LinearTwoVarEqualityDomainPentagon.D2(RepresentantDomains.NoInequalties)
module PentagonIneq = LinearTwoVarEqualityDomainPentagon.D2(RepresentantDomains.InequalityFunctor(RepresentantDomains.PentagonCoeffs))
module PentagonOffsetIneq = LinearTwoVarEqualityDomainPentagon.D2(RepresentantDomains.InequalityFunctor(RepresentantDomains.PentagonOffsetCoeffs))
module FullIneq = LinearTwoVarEqualityDomainPentagon.D2(RepresentantDomains.InequalityFunctor(RepresentantDomains.TwoVarInequalitySet))

let spec_module: (module MCPSpec) Lazy.t =
lazy (
let (module AD) = match GobConfig.get_string "ana.lin2vareq_p.inequalities" with
| "none" -> (module NoIneq : RelationDomain.RD)
| "pentagon" -> (module PentagonIneq : RelationDomain.RD)
| "pentagon_offset" -> (module PentagonOffsetIneq : RelationDomain.RD)
| _ -> (module FullIneq : RelationDomain.RD) (*Other options differ only in the limit function*)
in
let module Priv = (val RelationPriv.get_priv ()) in
let module Spec =
struct
include SpecFunctor (Priv) (AD) (RelationPrecCompareUtil.DummyUtil)
let name () = "lin2vareq_p"
end
in
(module Spec)
)

let get_spec (): (module MCPSpec) =
Lazy.force spec_module

let after_config () =
let module Spec = (val get_spec ()) in
MCP.register_analysis (module Spec : MCPSpec);
GobConfig.set_string "ana.path_sens[+]" (Spec.name ())

let _ =
AfterConfig.register after_config
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
(* This analysis is empty on purpose. It serves only as an alternative dependency
in cases where the actual domain can't be used because of a missing library.
It was added because we don't want to fully depend on Apron. *)
4 changes: 2 additions & 2 deletions src/analyses/apron/relationAnalysis.apron.ml
Original file line number Diff line number Diff line change
Expand Up @@ -559,8 +559,8 @@ struct
Priv.thread_join ~force:true ask man.global id st
| Rand, _ ->
Option.map_default (fun lv ->
let st = invalidate_one ask man st lv in
assert_fn {man with local = st} (BinOp (Ge, Lval lv, zero, intType)) true
let st = invalidate_one ask man st lv in
assert_fn {man with local = st} (BinOp (Ge, Lval lv, zero, intType)) true
) st r
| _, _ ->
let st' = special_unknown_invalidate man f args in
Expand Down
26 changes: 14 additions & 12 deletions src/analyses/base.ml
Original file line number Diff line number Diff line change
Expand Up @@ -202,21 +202,23 @@ struct
| Mult -> ID.mul
| Div ->
fun x y ->
(match ID.equal_to Z.zero y with
| `Eq ->
M.error ~category:M.Category.Integer.div_by_zero ~tags:[CWE 369] "Second argument of division is zero"
| `Top ->
M.warn ~category:M.Category.Integer.div_by_zero ~tags:[CWE 369] "Second argument of division might be zero"
| `Neq -> ());
if not !AnalysisState.executing_speculative_computations then
(match ID.equal_to Z.zero y with
| `Eq ->
M.error ~category:M.Category.Integer.div_by_zero ~tags:[CWE 369] "Second argument of division is zero"
| `Top ->
M.warn ~category:M.Category.Integer.div_by_zero ~tags:[CWE 369] "Second argument of division might be zero"
| `Neq -> ());
ID.div x y
| Mod ->
fun x y ->
(match ID.equal_to Z.zero y with
| `Eq ->
M.error ~category:M.Category.Integer.div_by_zero ~tags:[CWE 369] "Second argument of modulo is zero"
| `Top ->
M.warn ~category:M.Category.Integer.div_by_zero ~tags:[CWE 369] "Second argument of modulo might be zero"
| `Neq -> ());
if not !AnalysisState.executing_speculative_computations then
(match ID.equal_to Z.zero y with
| `Eq ->
M.error ~category:M.Category.Integer.div_by_zero ~tags:[CWE 369] "Second argument of modulo is zero"
| `Top ->
M.warn ~category:M.Category.Integer.div_by_zero ~tags:[CWE 369] "Second argument of modulo might be zero"
| `Neq -> ());
ID.rem x y
| Lt -> ID.lt
| Gt -> ID.gt
Expand Down
2 changes: 1 addition & 1 deletion src/analyses/baseInvariant.ml
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ struct
let inv_bin_int (a, b) ikind c op =
let warn_and_top_on_zero x =
if GobOption.exists (Z.equal Z.zero) (ID.to_int x) then
(M.error ~category:M.Category.Integer.div_by_zero ~tags:[CWE 369] "Must Undefined Behavior: Second argument of div or mod is 0, continuing with top";
(if not !AnalysisState.executing_speculative_computations then M.error ~category:M.Category.Integer.div_by_zero ~tags:[CWE 369] "Must Undefined Behavior: Second argument of div or mod is 0, continuing with top";
ID.top_of ikind)
else
x
Expand Down
6 changes: 3 additions & 3 deletions src/autoTune.ml
Original file line number Diff line number Diff line change
Expand Up @@ -248,12 +248,12 @@ let focusOnMemSafetySpecification () =
let focusOnTermination (spec: Svcomp.Specification.t) =
match spec with
| Termination ->
let terminationAnas = ["threadflag"; "apron"] in
let terminationAnas = ["threadflag"; get_string "ana.autotune.extraTerminationDomain"] in
enableAnalyses "Specification: Termination" "termination analyses" terminationAnas;
set_string "sem.int.signed_overflow" "assume_none";
set_bool "ana.int.interval" true;
set_string "ana.apron.domain" "polyhedra"; (* TODO: Needed? *)
()
if get_string "ana.autotune.extraTerminationDomain" = "apron" then
set_string "ana.apron.domain" "polyhedra"; (* TODO: Needed? *)
| _ -> ()

let focusOnTermination () =
Expand Down
71 changes: 54 additions & 17 deletions src/cdomain/value/cdomains/int/congruenceDomain.ml
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
open IntDomain0
open GoblintCil

module type Norm = sig
val normalize : ikind -> (Z.t * Z.t) option -> (Z.t * Z.t) option
end

module Congruence : S with type int_t = Z.t and type t = (Z.t * Z.t) option =
module CongruenceFunctor (Norm : Norm): S with type int_t = Z.t and type t = (Z.t * Z.t) option =
struct
let name () = "congruences"
type int_t = Z.t
Expand All @@ -24,22 +27,7 @@ struct
let ( |: ) a b =
if a =: Z.zero then false else (b %: a) =: Z.zero

let normalize ik x =
match x with
| None -> None
| Some (c, m) ->
if m =: Z.zero then
if should_wrap ik then
Some (Size.cast ik c, m)
else
Some (c, m)
else
let m' = Z.abs m in
let c' = c %: m' in
if c' <: Z.zero then
Some (c' +: m', m')
else
Some (c' %: m', m')
let normalize = Norm.normalize

let range ik = Size.range ik

Expand Down Expand Up @@ -540,3 +528,52 @@ struct

let project ik p t = t
end

module Wrapping : Norm = struct

let (%:) = Z.rem
let (=:) = Z.equal
let (+:) = Z.add
let (<:) x y = Z.compare x y < 0

let normalize ik x =
match x with
| None -> None
| Some (c, m) ->
if m =: Z.zero then
if should_wrap ik then
Some (Size.cast ik c, m)
else
Some (c, m)
else
let m' = Z.abs m in
let c' = c %: m' in
if c' <: Z.zero then
Some (c' +: m', m')
else
Some (c' %: m', m')
end

module NoWrapping : Norm = struct

let (%:) = Z.rem
let (=:) = Z.equal
let (+:) = Z.add
let (<:) x y = Z.compare x y < 0

let normalize ik x =
match x with
| None -> None
| Some (c, m) ->
if m =: Z.zero then
Some (c, m)
else
let m' = Z.abs m in
let c' = c %: m' in
if c' <: Z.zero then
Some (c' +: m', m')
else
Some (c' %: m', m')
end

module Congruence = CongruenceFunctor(Wrapping)
3 changes: 3 additions & 0 deletions src/cdomain/value/cdomains/int/intDomTuple.ml
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ module IntDomTupleImpl = struct
let ending ?(suppress_ovwarn=false) ik = create2_ovc ik { fi2_ovc = fun (type a) (module I:SOverflow with type t = a and type int_t = int_t) -> I.ending ~suppress_ovwarn ik }
let of_interval ?(suppress_ovwarn=false) ik = create2_ovc ik { fi2_ovc = fun (type a) (module I:SOverflow with type t = a and type int_t = int_t) -> I.of_interval ~suppress_ovwarn ik }
let of_congruence ik = create2 { fi2 = fun (type a) (module I:SOverflow with type t = a and type int_t = int_t) -> I.of_congruence ik }
let to_congruence (_,_,_,c,_,_) = match c with Some c -> c | None -> I4.top_of IChar (*ikind is ignored, so choose an arbitrary one *)
let of_bitfield ik = create2 { fi2 = fun (type a) (module I:SOverflow with type t = a and type int_t = int_t) -> I.of_bitfield ik }

let refine_with_congruence ik ((a, b, c, d, e, f) : t) (cong : (int_t * int_t) option) : t=
Expand Down Expand Up @@ -556,6 +557,8 @@ struct
let no_intervalSet (x: I.t) = {x with v = IntDomTupleImpl.no_intervalSet x.v}

let no_bitfield (x: I.t) = {x with v = IntDomTupleImpl.no_bitfield x.v}

let to_congruence (x: I.t) = IntDomTupleImpl.to_congruence x.v
end

let of_const (i, ik, str) = IntDomTuple.of_int ik i
61 changes: 45 additions & 16 deletions src/cdomain/value/cdomains/int/intervalDomain.ml
Original file line number Diff line number Diff line change
@@ -1,28 +1,30 @@
open IntDomain0

module IntervalFunctor (Ints_t : IntOps.IntOps): SOverflow with type int_t = Ints_t.t and type t = (Ints_t.t * Ints_t.t) option =
struct
let name () = "intervals"
type int_t = Ints_t.t
type t = (Ints_t.t * Ints_t.t) option [@@deriving eq, ord, hash]
module IArith = IntervalArith (Ints_t)
(**TODO Better Naming!*)
module type BoundedIntOps = sig
include IntOps.IntOps

type t_interval = (t * t) option

val range : GoblintCil.ikind -> t * t
val top_of : GoblintCil.ikind -> t_interval
val bot_of : GoblintCil.ikind -> t_interval


val norm : ?suppress_ovwarn:bool -> ?cast:bool -> GoblintCil.ikind -> t_interval -> t_interval * overflow_info
end

module Bounded (Ints_t : IntOps.IntOps): BoundedIntOps with type t = Ints_t.t and type t_interval = (Ints_t.t * Ints_t.t) option = struct
include Ints_t
type t_interval = (Ints_t.t * Ints_t.t) option
let range ik = BatTuple.Tuple2.mapn Ints_t.of_bigint (Size.range ik)

let top_of ik = Some (range ik)
let bot () = None
let bot_of ik = bot () (* TODO: improve *)
let bot_of ik = None (* TODO: improve *)

let show = function None -> "bottom" | Some (x,y) -> "["^Ints_t.to_string x^","^Ints_t.to_string y^"]"

include Std (struct type nonrec t = t let name = name let top_of = top_of let bot_of = bot_of let show = show let equal = equal end)

let equal_to i = function
| None -> failwith "unsupported: equal_to with bottom"
| Some (a, b) ->
if a = b && b = i then `Eq else if Ints_t.compare a i <= 0 && Ints_t.compare i b <=0 then `Top else `Neq

let norm ?(suppress_ovwarn=false) ?(cast=false) ik : (t -> t * overflow_info) = function None -> (None, {underflow=false; overflow=false}) | Some (x,y) ->
let norm ?(suppress_ovwarn=false) ?(cast=false) ik : (t_interval -> t_interval * overflow_info) = function None -> (None, {underflow=false; overflow=false}) | Some (x,y) ->
if Ints_t.compare x y > 0 then
(None,{underflow=false; overflow=false})
else (
Expand Down Expand Up @@ -58,6 +60,31 @@ struct
(v, ov_info)
)

end

module BoundedIntervalFunctor (Ints_t : BoundedIntOps): SOverflow with type int_t = Ints_t.t and type t = Ints_t.t_interval =
struct
let name () = "intervals bounds injected"
type int_t = Ints_t.t
type t = (Ints_t.t * Ints_t.t) option [@@deriving eq, ord, hash]
module IArith = IntervalArith (Ints_t)

let range = Ints_t.range
let top_of = Ints_t.top_of
let norm = Ints_t.norm
let bot_of = Ints_t.bot_of

let bot () = None

let show = function None -> "bottom" | Some (x,y) -> "["^Ints_t.to_string x^","^Ints_t.to_string y^"]"

include Std (struct type nonrec t = t let name = name let top_of = top_of let bot_of = bot_of let show = show let equal = equal end)

let equal_to i = function
| None -> failwith "unsupported: equal_to with bottom"
| Some (a, b) ->
if a = b && b = i then `Eq else if Ints_t.compare a i <= 0 && Ints_t.compare i b <=0 then `Top else `Neq

let leq (x:t) (y:t) =
match x, y with
| None, _ -> true
Expand Down Expand Up @@ -444,5 +471,7 @@ struct
let project ik p t = t
end

module IntervalFunctor (Ints_t : IntOps.IntOps) = BoundedIntervalFunctor (Bounded(Ints_t))

module Interval = IntervalFunctor (IntOps.BigIntOps)
module Interval32 = IntDomWithDefaultIkind (IntDomLifter (SOverflowUnlifter (IntervalFunctor (IntOps.Int64Ops)))) (IntIkind)
1 change: 1 addition & 0 deletions src/cdomain/value/cdomains/intDomain_intf.ml
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,7 @@ sig
val no_intervalSet: t -> t
val no_bitfield: t -> t
val ikind: t -> ikind
val to_congruence : t -> (Z.t * Z.t) option
end

val of_const: Z.t * Cil.ikind * string option -> IntDomTuple.t
Expand Down
18 changes: 12 additions & 6 deletions src/cdomains/apron/linearTwoVarEqualityDomain.apron.ml
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,9 @@ module EqualitiesConjunction = struct
(** add/remove new variables to domain with particular indices; translates old indices to keep consistency
add if op = (+), remove if op = (-)
the semantics of indexes can be retrieved from apron: https://antoinemine.github.io/Apron/doc/api/ocaml/Dim.html *)
let modify_variables_in_domain (dim,map) indexes op =
if Array.length indexes = 0 then (dim,map) else

let modify_variables_in_domain_general map map_value indexes op =
if Array.length indexes = 0 then map else
let offsetlist = Array.to_list indexes in
let rec bumpvar delta i = function (* bump the variable i by delta; find delta by counting indices in offsetlist until we reach a larger index then our current parameter *)
| head::rest when i>=head -> bumpvar (delta+1) i rest (* rec call even when =, in order to correctly interpret double bumps *)
Expand All @@ -115,13 +116,18 @@ module EqualitiesConjunction = struct
IntHashtbl.add h x r;
r)
in
let rec bumpentry k (refvar,offset,divi) = function (* directly bumps lhs-variable during a run through indexes, bumping refvar explicitly with a new lookup in indexes *)
let rec bumpentry k value = function (* directly bumps lhs-variable during a run through indexes, bumping refvar explicitly with a new lookup in indexes *)

| (tbl,delta,head::rest) when k>=head -> bumpentry k (refvar,offset,divi) (tbl,delta+1,rest) (* rec call even when =, in order to correctly interpret double bumps *)
| (tbl,delta,lyst) (* k<head or lyst=[] *) -> (IntMap.add (op k delta) (BatOption.map (fun (c,v) -> (c,memobumpvar v)) refvar,offset,divi) tbl, delta, lyst)
| (tbl,delta,head::rest) when k>=head -> bumpentry k value (tbl,delta+1,rest) (* rec call even when =, in order to correctly interpret double bumps *)
| (tbl,delta,lyst) (* k<head or lyst=[] *) -> (IntMap.add (op k delta) (map_value memobumpvar value) tbl, delta, lyst)
in
let (a,_,_) = IntMap.fold bumpentry map (IntMap.empty,0,offsetlist) in (* Build new map during fold with bumped key/vals *)
(op dim (Array.length indexes), a)
a

let modify_variables_in_domain (dim,map) indexes op =
let map_value bumpvar (refvar,offset,divi) = (BatOption.map (fun (c,v) -> (c,bumpvar v)) refvar,offset,divi) in
(op dim (Array.length indexes), modify_variables_in_domain_general map map_value indexes op)


let modify_variables_in_domain m cols op = let res = modify_variables_in_domain m cols op in if M.tracing then
M.tracel "modify_dims" "dimarray bumping with (fun x -> x + %d) at positions [%s] in { %s } -> { %s }"
Expand Down
Loading
Loading