From 52229fdedf69caf1eb7a601efa5394029a17ee61 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fran=C3=A7ois=20Bobot?= <francois.bobot@cea.fr>
Date: Fri, 23 Apr 2021 08:20:06 +0200
Subject: [PATCH] Import from Bin:a1af7a0 Src:66b5297cc farith:a93db57

---
 Src/COLIBRI/arith.pl     | 417 +++++++++++++++++++--------------------
 Src/COLIBRI/col_solve.pl |   8 +-
 Src/COLIBRI/notify.pl    |  13 +-
 Src/COLIBRI/rbox.pl      |   2 +-
 Src/COLIBRI/realarith.pl | 247 +++++++++++++++++------
 Src/COLIBRI/solve.pl     |  17 +-
 6 files changed, 422 insertions(+), 282 deletions(-)

diff --git a/Src/COLIBRI/arith.pl b/Src/COLIBRI/arith.pl
index f7d02ebbf..728931bb2 100755
--- a/Src/COLIBRI/arith.pl
+++ b/Src/COLIBRI/arith.pl
@@ -1383,13 +1383,13 @@ no_lin_mult(A,B,C) :-
 
 
 mult_int(A,_,A,_,C,_) ?- !,
-	power(A,2,C).
+    power(A,2,C).
 mult_int(A,TA,B,TB,C,TC) :-
-	get_priority(Prio),
-	set_priority(1),
-	mult_bis(A,TA,B,TB,C,TC),
-	set_priority(Prio),
-	wake_if_other_scheduled(Prio).
+    get_priority(Prio),
+    set_priority(1),
+    mult_bis(A,TA,B,TB,C,TC),
+    set_priority(Prio),
+    wake_if_other_scheduled(Prio).
 
 % on cherche (-X) * (-Y) = C --> X * Y = C 
 check_mult_opp(A,B,C,Continue) :-
@@ -1404,136 +1404,136 @@ check_mult_opp(A,B,C,Continue) :-
     ;   Continue = 1).
 
 mult_bis(A,TA,B,TB,C,TC) :-
-	mfd:get_intervals(A,IA),
-	mfd:get_intervals(B,IB),
-	mfd:get_intervals(C,IC),
-	save_cstr_suspensions((A,B,C)),
-	%% Point fixe sur les projections de congruence
-	%% on peut aller jusqu'a instancier A,B ou C
-	fp_congr_mult(A,B,C),
-	mult_inst(A,B,C,Continue),
-	(var(Continue) ->
-		true
-	;	mult_free(A,B,C,Continue1),
-		check_exists_power_int_with_mult_args(A,B,C,Continue1,Continue2),
-		(var(Continue2) ->
-			true
-		;	%% Factorisation avec un mult_int
-			clear_Goal(mult_int,A,B,C),
-			%% On regarde si on a un div_mod_int(C,A,...)
-			%% ou div_mod_int(C,B,...)
-			check_fusion_div_mod_int(mult_int,A,B,C),
-			check_zero_mult_int(A,B,C),
+    mfd:get_intervals(A,IA),
+    mfd:get_intervals(B,IB),
+    mfd:get_intervals(C,IC),
+    save_cstr_suspensions((A,B,C)),
+    % Point fixe sur les projections de congruence
+    % on peut aller jusqu'a instancier A,B ou C
+    fp_congr_mult(A,B,C),
+    mult_inst(A,B,C,Continue),
+    (var(Continue) ->
+        true
+    ;   mult_free(A,B,C,Continue1),
+        check_exists_power_int_with_mult_args(A,B,C,Continue1,Continue2),
+        (var(Continue2) ->
+            true
+        ;   % Factorisation avec un mult_int
+            clear_Goal(mult_int,A,B,C),
+            % On regarde si on a un div_mod_int(C,A,...)
+            % ou div_mod_int(C,B,...)
+            check_fusion_div_mod_int(mult_int,A,B,C),
+            check_zero_mult_int(A,B,C),
             check_assoc_dist(mult_int,A,B,C),
-			%% On a peut etre reduit A,B,C avant
-			mfd:get_intervals(A,NIA),
-			mfd:get_intervals(B,NIB),
-			mfd:get_intervals(C,NIC),
-			check_reduced(IA,NIA,TA),
-			check_reduced(IB,NIB,TB),
-			check_reduced(IC,NIC,TC),
-			((var(TA),var(TB),var(TC)) ->
-				%% Probleme avec arith_sched sans doute
-				TA = 1,
-				TB = 1,
-				TC = 1
-			;	true),
-			%% Calcul des projections
-			mult_free_proj(A,TA,B,TB,C,TC),
-			int_check_notify_constrained(A,IA),
-			int_check_notify_constrained(B,IB),
-			int_check_notify_constrained(C,IC),
-			check_before_susp_mult(A,B,C))).
+            % On a peut etre reduit A,B,C avant
+            mfd:get_intervals(A,NIA),
+            mfd:get_intervals(B,NIB),
+            mfd:get_intervals(C,NIC),
+            check_reduced(IA,NIA,TA),
+            check_reduced(IB,NIB,TB),
+            check_reduced(IC,NIC,TC),
+            ((var(TA),var(TB),var(TC)) ->
+                % Probleme avec arith_sched sans doute
+                TA = 1,
+                TB = 1,
+                TC = 1
+            ;   true),
+            % Calcul des projections
+            mult_free_proj(A,TA,B,TB,C,TC),
+            int_check_notify_constrained(A,IA),
+            int_check_notify_constrained(B,IB),
+            int_check_notify_constrained(C,IC),
+            check_before_susp_mult(A,B,C))).
 
 
 check_exists_power_int_with_mult_args(X,Y,Z,1,Continue) ?- !,
-	((get_saved_cstr_suspensions(LS),
-	  member((Susp,power_int(A,_,N,B,_)),LS),
-	  B == Z, 			%% A^N = Z
-	  (A == X, V = Y;	%% A*Y = Z
-	   A == Y, V = X))  %% A*X = Z
-	->
-		PN is N - 1,
-		(not_unify(A,0) ->
-			%% le mult_int va devenir un power_int
-			power(A,PN,V)
-		;	Continue = 1,
-			%% le mult_int reste mais on reduit selon le power_int
-			copy_term(A,CA),
-			mfd:dvar_remove_element(CA,0),
-			copy_term(V,CV),
-			Mod2 is PN mod 2,
-			power_int_ter(CA,1,PN,Mod2,CV,1),
-			mfd:get_intervals(CA,ICA),
-			mfd:(A:: [0|ICA]))
-	;	Continue = 1).
+    ((get_saved_cstr_suspensions(LS),
+      member((Susp,power_int(A,_,N,B,_)),LS),
+      B == Z, 			%% A^N = Z
+      (A == X, V = Y;	%% A*Y = Z
+       A == Y, V = X))  %% A*X = Z
+    ->
+        PN is N - 1,
+        (not_unify(A,0) ->
+            % le mult_int va devenir un power_int
+            power(A,PN,V)
+        ;   Continue = 1,
+            % le mult_int reste mais on reduit selon le power_int
+            copy_term(A,CA),
+            mfd:dvar_remove_element(CA,0),
+            copy_term(V,CV),
+            Mod2 is PN mod 2,
+            power_int_ter(CA,1,PN,Mod2,CV,1),
+            mfd:get_intervals(CA,ICA),
+            mfd:(A:: [0|ICA]))
+    ;   Continue = 1).
 check_exists_power_int_with_mult_args(_,_,_,_,_).
 
 
 %% Peut on enlever 0 de A,B,C ?
 check_zero_mult_int(A,B,C) :-
-	(not_unify(C,0) ->
-		%% on peut enlever 0 dans A et B
-		mfd:dvar_remove_element(A,0),
-		mfd:dvar_remove_element(B,0)
-	;	((not_unify(A,0),
-		  not_unify(B,0))
-		->
-			%% on peut enlever 0 dans C
-			mfd:dvar_remove_element(C,0)
-		;	true)).
+    (not_unify(C,0) ->
+        % on peut enlever 0 dans A et B
+        mfd:dvar_remove_element(A,0),
+        mfd:dvar_remove_element(B,0)
+    ;   ((not_unify(A,0),
+          not_unify(B,0))
+        ->
+            % on peut enlever 0 dans C
+            mfd:dvar_remove_element(C,0)
+        ;   true)).
 
 %% Exploitation d'instanciations
 mult_inst(A,B,C,Continue) :-
-	(integer(A) ->
-		(integer(B) ->
-			C0 is A * B,
+    (integer(A) ->
+        (integer(B) ->
+            C0 is A * B,
             protected_unify(C,C0)
-		;	(A == 0 ->
-				protected_unify(C = 0)
-			;	(A == 1 ->
-					protected_unify(C = B)
-				;	(integer(C) ->
-						B0 is C // A,
+        ;   (A == 0 ->
+                protected_unify(C = 0)
+            ;   (A == 1 ->
+                    protected_unify(C = B)
+                ;   (integer(C) ->
+                        B0 is C // A,
                         protected_unify(B,B0),
-						C is A * B
-					;	(A == -1 ->
-							no_lin_op(B,C)
-						;	Continue = 1)))))
-	;	(integer(B) ->
-			(B == 0 ->
-				protected_unify(C = 0)
-			;	(B == 1 ->
-					protected_unify(C = A)
-				;	(integer(C) ->
-						A0 is C // B,
+                        C is A * B
+                    ;   (A == -1 ->
+                            no_lin_op(B,C)
+                        ;   Continue = 1)))))
+    ;   (integer(B) ->
+            (B == 0 ->
+                protected_unify(C = 0)
+            ;   (B == 1 ->
+                    protected_unify(C = A)
+                ;   (integer(C) ->
+                        A0 is C // B,
                         protected_unify(A,A0),
-						C is A * B
-					;	(B == -1 ->
-							no_lin_op(A,C)
-						;	Continue = 1))))
-		;	(integer(C) ->
-				(C == 0 ->
-					(not_unify(A,0) ->
-						protected_unify(B = 0)
-					;	(not_unify(B,0) ->
-							protected_unify(A = 0)
-						;	Continue = 1))
-				;	(C == 1 ->
-						mfd:quiet_set_intervals(A,[-1,1]),
-						A = B
-					;	(C == -1 ->
-							mfd:quiet_set_intervals(A,[-1,1]),
-							no_lin_op(A,B)
-						;	%% On pourrait ameliorer en remarquant
-							%% que A et B divisent C !!
-							OpC is -C,
-							(C > 0 ->
-								InterAB = [OpC .. -1, 1 .. C]
-							;	InterAB = [C .. -1, 1 .. OpC]),
-							mfd:([A,B] :: InterAB),
-							Continue = 1)))
-			;	Continue = 1))).
+                        C is A * B
+                    ;   (B == -1 ->
+                            no_lin_op(A,C)
+                        ;   Continue = 1))))
+        ;   (integer(C) ->
+                (C == 0 ->
+                    (not_unify(A,0) ->
+                        protected_unify(B = 0)
+                    ;   (not_unify(B,0) ->
+                            protected_unify(A = 0)
+                        ;   Continue = 1))
+                ;   (C == 1 ->
+                        mfd:quiet_set_intervals(A,[-1,1]),
+                        A = B
+                    ;   (C == -1 ->
+                            mfd:quiet_set_intervals(A,[-1,1]),
+                            no_lin_op(A,B)
+                        ;   % On pourrait ameliorer en remarquant
+                            % que A et B divisent C !!
+                            OpC is -C,
+                            (C > 0 ->
+                                InterAB = [OpC .. -1, 1 .. C]
+                            ;   InterAB = [C .. -1, 1 .. OpC]),
+                            mfd:([A,B] :: InterAB),
+                            Continue = 1)))
+            ;   Continue = 1))).
 
 %% Exploitation d'identites entre arguments
 mult_free(A,B,C,NContinue) :-
@@ -1542,7 +1542,7 @@ mult_free(A,B,C,NContinue) :-
             protected_unify(B = 1)
         ;   (not_unify(B,1) ->
                 protected_unify(A = 0)
-            ;	Continue = 1))
+            ;   Continue = 1))
     ;   (B == C  ->
             (not_unify(B,0) ->
                 protected_unify(A = 1)
@@ -1634,13 +1634,12 @@ mult_free_rec(Cpt,A,TA,B,TB,C,TC) :-
 
 
 check_before_susp_mult(A,B,C) :-
-	check_mult_int_ineqs(A,B,C),
+    check_mult_int_ineqs(A,B,C),
     mult_inst(A,B,C,Continue),
-	(var(Continue) ->
-		true
-	;	set_prio_inst([A,B,C],4,5,Prio),
-		%%set_prio_inst([A,B,C],3,4,Prio),
-		
+    (var(Continue) ->
+        true
+    ;   set_prio_inst([A,B,C],4,5,Prio),
+        %set_prio_inst([A,B,C],3,4,Prio),
         my_suspend(mult_int(A,_,B,_,C,_), Prio, (A,B,C) -> suspend:constrained)).
 
 check_mult_int_ineqs(A,B,C) :-
@@ -2019,89 +2018,89 @@ check_zero_and_mult_interval(Val1,Val2,Val) :- !,
 	congr_mult_directe(Val1,Val2,Val).
 */
 check_zero_and_mult_interval(Val1,Val2,Val) :-
-	(get_type(Val,_) ->
-		true
-	;	% Val non initialise
-		mfd:dvar_range(Val1,Low1,High1),
-		mfd:dvar_range(Val2,Low2,High2),
-		mult_intervals(Low1..High1,Low2..High2,Low,High),
-		mfd:quiet_set_intervals(Val,[Low..High])),
-	%% On fait le menage (on l'a peut etre enleve au tour precedent)
-	(not_unify(Val,0) ->
-		mfd:dvar_remove_element(Val1,0),
-		mfd:dvar_remove_element(Val2,0),
-		mult_interval(Val1,Val2,Val)
-	;	(not_unify(Val1,0) ->
-			(not_unify(Val2,0) ->
-				mult_interval(Val1,Val2,Val)
-			;	%% On met 0 de cote pour le resultat
-				%% et on calcule sur une copie de Val2 privee de 0
-				((mfd:copy_domain(Val1,CVal1),
-				  get_congr(Val1,C1,M1),
-				  launch_congr(CVal1,C1,M1),
-				  mfd:copy_domain(Val2,CVal2),
-				  get_congr(Val2,C2,M2),
-				  launch_congr(CVal2,C2,M2),
-				  mfd:dvar_remove_element(CVal2,0),
-				  mfd:copy_domain(Val,CVal),
-				  get_congr(Val,C,M),
-				  launch_congr(CVal,C,M),
-				  mfd:dvar_remove_element(CVal,0),
-				  copy_delta(Val1,Val2,CVal1,CVal2),
-				  mult_interval(CVal1,CVal2,CVal))
-				->
-					%% mult_interval a pu modifier CVal1 et CVal2
-					%% On ne peut recopier tel quel le delta(CVal1,CVal2)
-					mfd:dvar_domain(CVal1,DomCVal1),
-					mfd:dvar_set(Val1,DomCVal1),
-					mfd:dvar_domain(CVal2,DomCVal2),
-					mfd:dom_union(dom([0]),DomCVal2,NDomVal2),
-					mfd:dvar_set(Val2,NDomVal2),
-					mfd:dvar_domain(CVal,DomCVal),
-					mfd:dom_union(dom([0]),DomCVal,NDomVal),
-					mfd:dvar_set(Val,NDomVal)
-				;	%% On a echoue en elevant 0 de Val2
-					%% donc solution uniquement pour Val2 = 0
-					protected_unify(Val2 = 0),
-					protected_unify(Val = 0)))
-		;	(not_unify(Val2,0) ->
-				%% On met 0 de cote pour le resultat
-				%% et on calcule sur une copie de Val1 privee de 0
-				((mfd:copy_domain(Val1,CVal1),
-				  get_congr(Val1,C1,M1),
-				  launch_congr(CVal1,C1,M1),
-				  mfd:dvar_remove_element(CVal1,0),
-				  mfd:copy_domain(Val2,CVal2),
-				  get_congr(Val2,C2,M2),
-				  launch_congr(CVal2,C2,M2),
-				  mfd:copy_domain(Val,CVal),
-				  get_congr(Val,C,M),
-				  launch_congr(CVal,C,M),
-				  mfd:dvar_remove_element(CVal,0),
-				  copy_delta(Val1,Val2,CVal1,CVal2),
-				  mult_interval(CVal1,CVal2,CVal))
-				->
-					%% mult_interval a pu modifier CVal1 et CVal2
-					%% On ne peut recopier tel quel le delta(CVal1,CVal2)
-					mfd:dvar_domain(CVal1,DomCVal1),
-					mfd:dom_union(dom([0]),DomCVal1,NDomVal1),
-					mfd:dvar_set(Val1,NDomVal1),
-					mfd:dvar_domain(CVal2,DomCVal2),
-					mfd:dvar_set(Val2,DomCVal2),
-					mfd:dvar_domain(CVal,DomCVal),
-					mfd:dom_union(dom([0]),DomCVal,NDomVal),
-					mfd:dvar_set(Val,NDomVal)
-				;	%% On a echoue en elevant 0 de Val1
-					%% donc solution uniquement pour Val1 = 0
-					protected_unify(Val1 = 0),
-					protected_unify(Val = 0))
-			;	mult_interval(Val1,Val2,Val)))),
-	congr_mult_directe(Val1,Val2,Val).
+    (get_type(Val,_) ->
+        true
+    ;   % Val non initialise
+        mfd:dvar_range(Val1,Low1,High1),
+        mfd:dvar_range(Val2,Low2,High2),
+        mult_intervals(Low1..High1,Low2..High2,Low,High),
+        mfd:quiet_set_intervals(Val,[Low..High])),
+    % On fait le menage (on l'a peut etre enleve au tour precedent)
+    (not_unify(Val,0) ->
+        mfd:dvar_remove_element(Val1,0),
+        mfd:dvar_remove_element(Val2,0),
+        mult_interval(Val1,Val2,Val)
+    ;   (not_unify(Val1,0) ->
+            (not_unify(Val2,0) ->
+                mult_interval(Val1,Val2,Val)
+            ;   % On met 0 de cote pour le resultat
+                % et on calcule sur une copie de Val2 privee de 0
+                ((mfd:copy_domain(Val1,CVal1),
+                  get_congr(Val1,C1,M1),
+                  launch_congr(CVal1,C1,M1),
+                  mfd:copy_domain(Val2,CVal2),
+                  get_congr(Val2,C2,M2),
+                  launch_congr(CVal2,C2,M2),
+                  mfd:dvar_remove_element(CVal2,0),
+                  mfd:copy_domain(Val,CVal),
+                  get_congr(Val,C,M),
+                  launch_congr(CVal,C,M),
+                  mfd:dvar_remove_element(CVal,0),
+                  copy_delta(Val1,Val2,CVal1,CVal2),
+                  mult_interval(CVal1,CVal2,CVal))
+                ->
+                    % mult_interval a pu modifier CVal1 et CVal2
+                    % On ne peut recopier tel quel le delta(CVal1,CVal2)
+                    mfd:dvar_domain(CVal1,DomCVal1),
+                    mfd:dvar_set(Val1,DomCVal1),
+                    mfd:dvar_domain(CVal2,DomCVal2),
+                    mfd:dom_union(dom([0]),DomCVal2,NDomVal2),
+                    mfd:dvar_set(Val2,NDomVal2),
+                    mfd:dvar_domain(CVal,DomCVal),
+                    mfd:dom_union(dom([0]),DomCVal,NDomVal),
+                    mfd:dvar_set(Val,NDomVal)
+                ;   % On a echoue en elevant 0 de Val2
+                    % donc solution uniquement pour Val2 = 0
+                    protected_unify(Val2 = 0),
+                    protected_unify(Val = 0)))
+        ;   (not_unify(Val2,0) ->
+                % On met 0 de cote pour le resultat
+                % et on calcule sur une copie de Val1 privee de 0
+                ((mfd:copy_domain(Val1,CVal1),
+                  get_congr(Val1,C1,M1),
+                  launch_congr(CVal1,C1,M1),
+                  mfd:dvar_remove_element(CVal1,0),
+                  mfd:copy_domain(Val2,CVal2),
+                  get_congr(Val2,C2,M2),
+                  launch_congr(CVal2,C2,M2),
+                  mfd:copy_domain(Val,CVal),
+                  get_congr(Val,C,M),
+                  launch_congr(CVal,C,M),
+                  mfd:dvar_remove_element(CVal,0),
+                  copy_delta(Val1,Val2,CVal1,CVal2),
+                  mult_interval(CVal1,CVal2,CVal))
+                ->
+                    % mult_interval a pu modifier CVal1 et CVal2
+                    % On ne peut recopier tel quel le delta(CVal1,CVal2)
+                    mfd:dvar_domain(CVal1,DomCVal1),
+                    mfd:dom_union(dom([0]),DomCVal1,NDomVal1),
+                    mfd:dvar_set(Val1,NDomVal1),
+                    mfd:dvar_domain(CVal2,DomCVal2),
+                    mfd:dvar_set(Val2,DomCVal2),
+                    mfd:dvar_domain(CVal,DomCVal),
+                    mfd:dom_union(dom([0]),DomCVal,NDomVal),
+                    mfd:dvar_set(Val,NDomVal)
+                ;   % On a echoue en elevant 0 de Val1
+                    % donc solution uniquement pour Val1 = 0
+                    protected_unify(Val1 = 0),
+                    protected_unify(Val = 0))
+            ;   mult_interval(Val1,Val2,Val)))),
+    congr_mult_directe(Val1,Val2,Val).
 
 copy_delta(A,B,CA,CB) :-
-	(get_deltas(A,B,S,C) ->
-		launch_delta(CA,CB,S,C)
-	;	true).
+    (get_deltas(A,B,S,C) ->
+        launch_delta(CA,CB,S,C)
+    ;   true).
 
 %% Multiplication intervalle par intervalle de Val1 par Val2
 %% Puis intersection du domaine calcule
diff --git a/Src/COLIBRI/col_solve.pl b/Src/COLIBRI/col_solve.pl
index b5484eb96..857883376 100644
--- a/Src/COLIBRI/col_solve.pl
+++ b/Src/COLIBRI/col_solve.pl
@@ -807,19 +807,19 @@ smt_test(TO,Size) :-
     %StrDir = "./QF_FP/ramalho/", % 4 (min_solve)(cvc4 19)(bitwuzla 17)
     %StrDir = "./QF_FP/griggio/", % 42 (min_solve, delta 0 pour cast
                                  % float->double) 51 sans simplex !! (cvc4 89)(bitwuzla 74) 
-    %StrDir = "./QF_FP/schanda/spark/", % 7 (min_solve avec X =< (X+Y)/2 =< Y) (ncvc4 8)(bitwuzla 3)
+    StrDir = "./QF_FP/schanda/spark/", % 6 (min_solve avec X =< (X+Y)/2 =< Y) (ncvc4 8)(bitwuzla 3)
     %StrDir = "./QF_FP/wintersteiger/", % tout OK
 
 %-----------------------------------------------------------------
-    StrDir = "./QF_UF/", % 
+    %StrDir = "./QF_UF/", % 426 (pour 1061)
 %----------------------------------------------------------------    
     %StrDir = "./QF_AUFBV/", % 
 %----------------------------------------------------------------    
-    %StrDir = "./QF_UFIDL/", % 
+    %StrDir = "./QF_UFIDL/", % 290 (pour 329)
 %----------------------------------------------------------------    
     %StrDir = "./QF_UFLIA/", % 104 (pour 129)
 %----------------------------------------------------------------    
-    %StrDir = "./QF_UFLRA/", % 142 (pour 384)
+    %StrDir = "./QF_UFLRA/", % 141 (pour 384)
 %----------------------------------------------------------------
     %StrDir = "./QF_ABV/bench_ab/",
     %StrDir = "./QF_ABV/bmc-arrays/", 
diff --git a/Src/COLIBRI/notify.pl b/Src/COLIBRI/notify.pl
index 143f14842..e49d8f8a7 100755
--- a/Src/COLIBRI/notify.pl
+++ b/Src/COLIBRI/notify.pl
@@ -194,16 +194,15 @@ wake_if_other_scheduled :-
 %% avec un niveau de priorite inferieur strictement a "Prio" 
 wake_if_other_scheduled(1) :- !.
 wake_if_other_scheduled(Prio) :-
-    WPrio is max(1,Prio - 1),
-    last_scheduled(ScheduledSusps),
-    (check_no_scheduled(Prio,ScheduledSusps) ->
+    (check_no_scheduled_prio(Prio) ->
         true
-    ;   wake_scheduled,
+    ;   wake,
         true).
 
-:- export wake_scheduled/0.
-wake_scheduled :-
-    wake.
+check_no_scheduled_prio(Prio) :-
+    last_scheduled(ScheduledSusps),
+    check_no_scheduled(Prio,ScheduledSusps).
+    
 
 /*
 	;	(getval(use_delta,0)@eclipse ->
diff --git a/Src/COLIBRI/rbox.pl b/Src/COLIBRI/rbox.pl
index edea1d076..7a616ce74 100755
--- a/Src/COLIBRI/rbox.pl
+++ b/Src/COLIBRI/rbox.pl
@@ -381,7 +381,7 @@ is_float_number(Var) :-
     float(Var),
     !.
 is_float_number(V{rbox:rf(RF,_)}) ?-
-    atomic(RF),
+    nonvar(RF),
     get_type(V,Type),
     once (RF == float;
           RF == float_int;
diff --git a/Src/COLIBRI/realarith.pl b/Src/COLIBRI/realarith.pl
index fe7469f53..704af1937 100755
--- a/Src/COLIBRI/realarith.pl
+++ b/Src/COLIBRI/realarith.pl
@@ -2263,7 +2263,17 @@ cast_double_to_float_bis(Rnd,A,B) :-
         HB1 = HA0
     ;   HB1 = HB0),
     set_typed_intervals(B,float_simple,[LB1..HB1]),
-    % pas de projection inverse pour l'instant
+    % Si on a deux float_int qui tiennent dans la mantisse simple
+    % on peut intersecter les intervalles des deux !!
+    ((is_float_int_number(A), % donc B aussi
+      is_inside_mantissa(float_simple,A))
+    ->
+        mreal:get_intervals(B,IB),
+        mreal:set_typed_intervals(A,float_simple,IB),
+        mreal:get_intervals(A,IA),
+        mreal:set_typed_intervals(B,float_simple,IA)
+    ;   % Pas de projection inverse pour l'instant
+        true),
     (ground((A,B)) ->
         (var(Rnd) ->
             % on peut reduire Rnd
@@ -2297,6 +2307,8 @@ cast_double_to_float_bis(Rnd,A,B) :-
 
 launch_delta_double_to_float(_,D,F) :- !.
 /*
+% Le flottant n'a que des zeros en poid faible de la mantisse double
+% quand le flottant cible est "normal"
 launch_delta_double_to_float(rne,D,F) ?-
     var(A),
     var(B),
@@ -2348,6 +2360,16 @@ cast_double_to_float_bis(A,B) :-
             get_dvar_fintervals(B,IB1),
             inv_cast_double_to_float_intervals(IB1,NIA),
             mreal:set_typed_intervals(A,float_double,NIA),
+            % Si on a deux float_int qui tiennent dans la mantisse simple
+            % on peut intersecter les intervalles des deux !!
+            ((is_float_int_number(A), % donc B aussi
+              is_inside_mantissa(float_simple,A))
+            ->
+                mreal:get_intervals(B,NewIB),
+                mreal:set_typed_intervals(A,float_simple,NewIB),
+                mreal:get_intervals(A,NewIA),
+                mreal:set_typed_intervals(B,float_simple,NewIA)
+            ;   true),
             check_before_susp_cast_double_to_float_bis(A,B))),
     check_simple_float_bounds(B),
     set_priority(Prio),
@@ -2458,7 +2480,6 @@ check_before_susp_cast_double_to_float_bis(A,B) :-
             inv_cast_double_to_float_interval(B,IA),
             mreal:set_typed_intervals(A,float_double,[IA])
         ;   cast_double_to_float_ineqs(A,B),
-            
             my_suspend(cast_double_to_float_bis(A,B),3,(A,B)->suspend:constrained))).
 
 cast_double_to_float_ineqs(A,B) :-
@@ -9958,45 +9979,65 @@ mult_real_ineqs(Type,A,B,C) :-
     bin_op_real_ineq(Type,mult_real1,A,B,C).
 
 % seulement dans le cas ou les arguments sont signés
-% et un est instancié
+%mult_real_int_ineqs(SA,SB,A,B,C) :- !.
 mult_real_int_ineqs(SA,SB,A,B,C) :-
-    nonvar(SA),
-    nonvar(SB),
-    var(C),
-    (nonvar(A) ->
-        var(B),
-        Cst = A,
-        Other = B
-    ;   nonvar(B),
-        Cst = B,
-        Other = A),
-    !,
-    rational(Cst,RCst),
-    (is_real_box_rat(Other,RL) ->
-        RH = RL
-    ;   mreal:dvar_range(Other,RL,RH)),
-    % A REVOIRE
-    (RL == -1.0Inf ->
-        % donc RH <> 1.0Inf, S = neg
-        (RCst > 0 ->
-            L = RL,
-            H is RCst * rational(RH)
-        ;   H = 1.0Inf,
-            L is RCst * rational(RL))
-    ;   (RH == 1.0Inf ->
-            % S = pos
-            (RCst > 0 ->
-                L is RCst * rational(RL),
-                H = 1.0Inf
-            ;   L = -1.0Inf,
-                H is RCst * rational(RL))
-        ;   B1 is RCst * rational(RL),
-            B2 is RCst * rational(RH),
-            sort([B1,B2],[L,H]))),
-    launch_delta(Other,C,+,L..H).
-mult_real_int_ineqs(SA,SB,A,B,C).
+    (not_zero(C) ->
+        NZ = 1,
+        forbid_zero(real,A),
+        forbid_zero(real,B)
+    ;   ((not_zero(A),
+          not_zero(B))
+        ->
+            NZ = 1,
+            forbid_zero(real,C)
+        ;   true)),
+    % A revoir et generaliser
+    ((getval(use_delta,1)@eclipse,
+      nonvar(SA),
+      nonvar(SB),
+      var(C))
+    ->
+        once (get_sign(C,SC);true),
+        (var(A) ->
+            mult_real_int_ineqs0(NZ,SC,SA,A,B,C)
+        ;   true),
+        (var(B) ->
+            mult_real_int_ineqs0(NZ,SC,SB,B,A,C)
+        ;   true)
+    ;   true).
+
+mult_real_int_ineqs0(NZ,SC,SOther,Other,Fact,C) :-
+    % Fact * Other = C
+    minus_real_interval(real,C,Other,Diff),
+    mreal:dvar_range(Diff,LD0,HD0),
+    (SOther \== SC ->
+        (SOther == pos ->
+            % C neg, Other >= C
+            HD1 is min(HD0,0.0),
+            LD1 = LD0
+        ;   % Other neg, C pos, Other =< C
+            HD1 = HD0,
+            LD1 is min(LD0,0.0))
+    ;   LD1 = LD0,
+        HD1 = HD0),
+    (LD1 == -1.0Inf ->
+        LD = LD1
+    ;   ((LD1 == 0.0,
+          nonvar(NZ),
+          not_unify(Fact,1.0))
+        ->
+            LD = 1_1
+        ;   rational(LD1,LD))),
+    (HD1 == 1.0Inf ->
+        HD = HD1
+    ;   ((HD1 == 0.0,
+          nonvar(NZ),
+          not_unify(Fact,1.0))
+        ->
+            HD is -1_1
+        ;   rational(HD1,HD))),
+    launch_delta(Other,C,+,LD..HD).
 
-        
 op_rel(<,>).
 op_rel(>,<).
 op_rel(=<,>=).
@@ -12919,9 +12960,10 @@ check_div_mult_exact(Type,A,B,C,_,Continue) :-
 % average_real_ineqs(Type,A,B,C) :- !.
 % Bizarre !!
 average_real_ineqs(Type,A,B,C) :-
-    ((B == 2.0,
-      get_saved_cstr_suspensions(LSusp),
-      member((S,add_real1(Type,X,Y,AA)),LSusp),
+    B == 2.0,
+    !,
+    get_saved_cstr_suspensions(LSusp),
+    ((member((S,add_real1(Type,X,Y,AA)),LSusp),
       AA == A,
       var(X),
       var(Y),
@@ -12929,6 +12971,7 @@ average_real_ineqs(Type,A,B,C) :-
       occurs(Rel,(<,=<,>,>=)))
     ->
         (getval(use_delta,1)@eclipse ->
+            call(spy_here)@eclipse,
             (occurs(Rel,(=<,<)) ->
                 launch_real_ineq(=<,Type,X,C),
                 launch_real_ineq(=<,Type,C,Y)
@@ -12939,7 +12982,76 @@ average_real_ineqs(Type,A,B,C) :-
                 launch_geq_real(Type,C,X)
             ;   launch_geq_real(Type,X,C),
                 launch_geq_real(Type,C,Y)))
-    ;   true).
+    ;   ((once (member((_,cast_float_to_double_bis(FA,DA)),LSusp),
+                DA == A),% double(FA)/2 = C
+          get_cstr_suspensions(FA,LSFA),
+          once (member(SA,LSFA),
+                get_suspension_data(SA,goal,div_real1(float_simple,FFA,D,FAd2)),
+                D == 2.0,
+                FFA == FA),
+          get_cstr_suspensions(FAd2,LSFAd2),
+          member(SFAd2,LSFAd2),
+          get_suspension_data(SFAd2,goal,
+                              cast_float_to_double_bis(FFAd2,DAd2)),
+          FFAd2 == FAd2) % double(FA/2) = DAd2
+        ->
+            % double(FA)/2 = double(FA/2)
+            protected_unify(C,DAd2)
+        ;   ((once (member_begin_end((_,cast_float_to_double_bis(CC,DC)),LSusp,NLSusp,End,End),
+                    CC == C, % double(A/2) = DC
+                    member((_,cast_float_to_double_bis(AA,DA)),NLSusp),
+                    AA == A),% double(A) = DA
+              get_cstr_suspensions(DA,LSDA),
+              member(SDA,LSDA),
+              get_suspension_data(SA,goal,div_real1(float_double,DDA,D,DAd2)),
+              D == 2.0,
+              DDA == DA) % double(A)/2 = DAd2
+            ->
+                % double(A/2) = double(A)/2
+                protected_unify(DC,DAd2)
+            ;   % normal(C),A/2 = C, float(double(A)/2) ?
+                ((Type == float_simple,
+                  not not (isNormal(Type,C,BN),
+                           BN == 1),
+                  once (member((_,cast_float_to_double_bis(AA,DA)),LSusp),
+                        AA == A),
+                  % double(A) = DA
+                  get_cstr_suspensions(DA,LSDA),
+                  once (member(SDA,LSDA),
+                        get_suspension_data(SDA,goal,div_real1(_,DDA,D,
+                                                               DAd2)),
+                        D == 2.0,
+                        DDA == DA),
+                  % double(A)/2 == DAd2
+                  get_cstr_suspensions(DAd2,LSDAd2),
+                  member(SDAd2,LSDAd2),
+                  get_suspension_data(SDAd2,goal,
+                                      cast_double_to_float_bis(DDAd2,
+                                                               FDAd2)),
+                  DDAd2 == DAd2)% floar(double(A)/2) = FDAD2
+                ->
+                    protected_unify(C,FDAd2)
+                ;   % float(double(A))/2 = A/2 ?
+                    ((once (member_begin_end((_,cast_float_to_double_bis(FA,AA)),
+                                             LSusp,NLSusp,End,End),
+                            AA == A, % double(FA) = A
+                                     % float(double(FA)/2) ?
+                            member((_,cast_double_to_float_bis(CC,FC)),
+                                   NLSusp),
+                            CC == C),
+                      % FA/2 = FAd2 ?
+                      get_cstr_suspensions(FA,LSFA),
+                      member(SFA,LSFA),
+                      get_suspension_data(SFA,goal,div_real1(_,FFA,D,FAd2)),
+                      D = 2.0,
+                      FFA == FA,
+                      not not (isNormal(float_simple,FAd2,BN),
+                               BN == 1))
+                    ->
+                        call(spy_here)@eclipse,
+                        protected_unify(FC,FAd2)
+                    ;   true))))).
+average_real_ineqs(Type,A,B,C).
 
 %% PMO si les 3 args sont des float_int entre -2^53 et 2^53 on peut
 %% deleguer le calcul de mult_real aux entiers
@@ -13095,19 +13207,36 @@ div_real_ineqs(Type,A,B,C) :-
 %div_real_ineqs(Type,A,B,C).
 div_real_ineqs(Type,A,B,C) :-
     bin_op_real_ineq(Type,div_real1,A,B,C).
-                    
+
+%On peut etre plus precis sur les float_int
 div_real_int_ineqs(SA,SB,A,B,C) :-
-    var(A),
-    var(C),
-    nonvar(SA),
-    (nonvar(B),
-     not_inf_bounds(B),
-     rational(B,RB);
-     is_real_box_rat(B,RB)),
-    !,
-    InvB is 1_1/RB,
-    mult_real_int_ineqs(SA,SB,A,InvB,C).
-div_real_int_ineqs(_,_,_,_,_).
+    (not_zero(C) ->
+        NZ = 1,
+        forbid_zero(real,A)
+    ;   (not_zero(A) ->
+            NZ = 1,
+            forbid_zero(real,C)
+        ;   true)),
+    % A revoir et generaliser
+    ((getval(use_delta,1)@eclipse,
+      nonvar(SA),
+      nonvar(SB),
+      var(C))
+    ->
+        once (get_sign(C,SC);true),
+        (var(A) ->
+            mult_real_int_ineqs0(NZ,SC,SA,A,B,C),
+            % en float_int B divise A donc A=C*B
+            ((var(B),
+              is_float_int_number(A),
+              is_float_int_number(B),
+              is_float_int_number(C))
+            ->
+                mult_real_int_ineqs0(NZ,SA,SB,B,C,A)
+            ;   true)
+        ;   true)
+    ;   true).
+
 
 exists_mult_with_abs_op_B(SB,B) :-
     get_saved_cstr_suspensions(LSusp),
@@ -13890,8 +14019,12 @@ div_real_inst0(Type,A,B,C,Continue) :-
                                 ;   Continue0 = 1)))
                     ;   (float(B) ->
                             (float(C) ->
-                                inv1_div_real_float_min_max(Type,C,B,A1,A2,Continue),
-                                mreal:set_typed_intervals(A,Type,[A1..A2])
+                                inv1_div_real_float_min_max(Type,C,B,A1,A2,Continue0),
+                                mreal:set_typed_intervals(A,Type,[A1..A2]),
+                                % Essai BM
+                                (var(A) ->
+                                    Continue = 1
+                                ;   true)
                             ;   % A et C variables
                                 ((Type \==  real,
                                   dvar_size(Type,C,2))
diff --git a/Src/COLIBRI/solve.pl b/Src/COLIBRI/solve.pl
index 60153db4d..1d6bbbb9e 100644
--- a/Src/COLIBRI/solve.pl
+++ b/Src/COLIBRI/solve.pl
@@ -11046,12 +11046,24 @@ remove_seen_vars([V|Seen],L,NL) :-
     ;   remove_seen_vars(Seen,L,NL)).
       
 
+/*
 choose_fd_var([Adj|UseList],Var,Size,NUseList) :-
     % Recolte des variables de plus grand cycle
     % ne dependant d'aucune autre (MaxCycleVars)
     % et apparaissant dans une adjacence singleton ou paire avec  resultat connu
     % ou bien dans une adjacence ne contenant que des MaxCycleVars
+    min_vars([Adj|UseList],MinVars,NUseList),
+    MinVars \== [],
+    var_with_max_cstr_min_dom(MinVars,Var,Size).
+%    var_with_min_dom_max_cstr(MinVars,Var,Size).
+*/
 
+% Nouvelle version plus simple
+choose_fd_var([Adj|UseList],Var,Size,NUseList) :-
+    % Recolte des variables de plus grand cycle
+    % ne dependant d'aucune autre (MaxCycleVars)
+    % et apparaissant dans une adjacence singleton ou paire avec  resultat connu
+    % ou bien dans une adjacence ne contenant que des MaxCycleVars
     delayed_goals(DG),
     term_variables(DG,Vars0),
     filter_constrained_vars(Vars0,MinVars0),
@@ -11060,15 +11072,12 @@ choose_fd_var([Adj|UseList],Var,Size,NUseList) :-
         (is_real_box_rat(V,_) ->
             OV = IV
         ;   OV = [V|IV])),
-%    min_vars([Adj|UseList],MinVars,NUseList),
-
     MinVars \== [],
-%%    var_with_min_dom_max_cstr(MinVars,Var,Size).
-%    var_with_max_cstr_min_dom(MinVars,Var,Size).
     leaf_vars([Adj|UseList],Leaves,NUseList),
     leaf_var_with_max_cstr_min_dom(MinVars,[],Var,Size).
 %    leaf_var_with_max_cstr_min_dom(MinVars,Leaves,Var,Size).
 
+
 leaf_vars(UseList,Leaves,NUseList) :-
     (foreach((V,D,A),UseList),
      fromto([],IT,OT,NUseList0) do
-- 
GitLab