From cd3ec4b1b740f746364d5a5e7ea19bf01700d89d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fran=C3=A7ois=20Bobot?= <francois.bobot@cea.fr>
Date: Fri, 30 Jun 2023 17:50:19 +0200
Subject: [PATCH] Import from Src:010e79722 farith:a93db57

---
 Src/COLIBRI/check_ineq.pl          |    2 +-
 Src/COLIBRI/check_lin_expr.pl      |    2 +-
 Src/COLIBRI/col_solve.pl           |   18 +-
 Src/COLIBRI/colibri.pl             |    2 +
 Src/COLIBRI/mod.pl                 |    1 +
 Src/COLIBRI/mreal.pl               |    9 +-
 Src/COLIBRI/ndelta.pl              |   11 +-
 Src/COLIBRI/new_parser_builtins.pl |   21 +
 Src/COLIBRI/rbox.pl                |   14 +-
 Src/COLIBRI/realarith.pl           |  300 +++---
 Src/COLIBRI/smt_import.pl          |  172 +++-
 Src/COLIBRI/solve.pl               |  481 ++++++----
 Src/COLIBRI/solve_util.pl          |    3 +
 Src/COLIBRI/trigo.pl               | 1351 ++++++++++++++++++++++++++++
 14 files changed, 2011 insertions(+), 376 deletions(-)
 create mode 100644 Src/COLIBRI/trigo.pl

diff --git a/Src/COLIBRI/check_ineq.pl b/Src/COLIBRI/check_ineq.pl
index ed15c39c5..dfb4d60c5 100644
--- a/Src/COLIBRI/check_ineq.pl
+++ b/Src/COLIBRI/check_ineq.pl
@@ -398,7 +398,7 @@ exists_diff_Rel(A,B) :-
             get_suspension_data(S,goal,Goal),
             (Goal = diff_real(_,X,Y);
              Goal = gt_real(_,X,Y);
-             fp_eq_reif(_,X,Y,Z),
+             Goal = fp_eq_reif(_,X,Y,Z),
              Z == 0)),
         ((X,Y) == (A,B); (X,Y) == (B,A))).
 
diff --git a/Src/COLIBRI/check_lin_expr.pl b/Src/COLIBRI/check_lin_expr.pl
index 54b3d46c1..cab1fe108 100755
--- a/Src/COLIBRI/check_lin_expr.pl
+++ b/Src/COLIBRI/check_lin_expr.pl
@@ -18,7 +18,7 @@ check_exists_lin_expr_giving_diff_args(Type,A,B,Stop) :-
     !,
     (block(col_timeout(try_check_exists_lin_expr_giving_diff_args(Type,A,B,Stop),
              0.5,
-             %1.0Inf,
+%             1.0Inf,
              true),
           Tag,
           (exit_block(Tag),
diff --git a/Src/COLIBRI/col_solve.pl b/Src/COLIBRI/col_solve.pl
index aad4ca1ad..c048f9582 100644
--- a/Src/COLIBRI/col_solve.pl
+++ b/Src/COLIBRI/col_solve.pl
@@ -1362,17 +1362,17 @@ smt_unit_test(TO,CI) :-
 %-----------------------------------------------------------------------    
     %StrDir = "./QF_AUFBVFP/20210301-Alive2/",% 1/1
 %------------------------------------------------------------------------
-    %StrDir = "./QF_ABVFPLRA/", % 0/74
-    %StrDir = "./QF_ABVFPLRA/20190429-UltimateAutomizerSvcomp2019/",% 0/41
-    %StrDir = "./QF_ABVFPLRA/20170501-Heizmann-UltimateAutomizer/",% 0/33
+    %StrDir = "./QF_ABVFPLRA/", % 1?(0)/74
+    %StrDir = "./QF_ABVFPLRA/20190429-UltimateAutomizerSvcomp2019/",% 1?(0)/41
+    %StrDir = "./QF_ABVFPLRA/20170501-Heizmann-UltimateAutomizer/",% 1??(0)/33
 %------------------------------------------------------------------------
     %StrDir = "./QF_ABVFP/",
-    %StrDir = "./QF_ABVFP/20170428-Liew-KLEE/", % 122/18033 TO (1 I,
+    %StrDir = "./QF_ABVFP/20170428-Liew-KLEE/", % 113/18033 TO (1 I,
     % 177 u) (69 sans simplex) (cvc4 76)
-    %StrDir = "./QF_ABVFP/20170501-Heizmann-UltimateAutomizer/", % 0/96 TO
+    %StrDir = "./QF_ABVFP/20170501-Heizmann-UltimateAutomizer/", % 1/96 TO
 %------------------------------------------------------------------------
     %StrDir = "./QF_BVFP/",
-    %StrDir = "./QF_BVFP/20170428-Liew-KLEE/", % 38(40)/17156 (89 u)
+    %StrDir = "./QF_BVFP/20170428-Liew-KLEE/", % 40/17156 (89 u)
     %StrDir = "./QF_BVFP/20170501-Heizmann-UltimateAutomizer/", % 0/4 TO
     %StrDir = "./QF_BVFP/ramalho/", % 0/32 TO
     %StrDir = "./QF_BVFP/schanda/spark/", % 1/8 TO
@@ -1385,16 +1385,16 @@ smt_unit_test(TO,CI) :-
     %StrDir = "./QF_FPLRA/schanda/spark/",% 0/2 TO
     %StrDir = "./QF_FPLRA/2019-Gudemann/",% 2/13 (3/13 en 2s)
 %------------------------------------------------------------------------
-    StrDir = "./QF_BVFPLRA/",
+    %StrDir = "./QF_BVFPLRA/",
     %StrDir = "./QF_BVFPLRA/20170501-Heizmann-UltimateAutomizer/",% 0/15 TO
-    %StrDir = "./QF_BVFPLRA/20190429-UltimateAutomizerSvcomp2019/",% 10/152 (11 u) (12/152 en 2s)
+    %StrDir = "./QF_BVFPLRA/20190429-UltimateAutomizerSvcomp2019/",% 10(9)/152 (11 u) (12/152 en 2s)
     %StrDir = "./QF_BVFPLRA/2019-Gudemann/",% 0/1 TO
 %------------------------------------------------------------------------
     %StrDir = "./QF_FP/20170501-Heizmann-UltimateAutomizer/", % 0/2 TO
     %StrDir = "./QF_FP/20190429-UltimateAutomizerSvcomp2019/", % 0/24
     %StrDir = "./QF_FP/20210211-Vector/", % 0/91
     %StrDir = "./QF_FP/ramalho/",% 0/38 T0 (5/38 en 2s)
-    %StrDir = "./QF_FP/griggio/", % 45 TO en 24s (cvc4 90 en 60s) (65/214 en 2s)
+    StrDir = "./QF_FP/griggio/", % 44 TO en 24s (cvc4 90 en 60s) (65/214 en 2s)
     %StrDir = "./QF_FP/schanda/spark/",% 5/46 TO (7 en 2s)
     %StrDir = "./QF_FP/wintersteiger/", % 0/39994
 %-----------------------------------------------------------------------    
diff --git a/Src/COLIBRI/colibri.pl b/Src/COLIBRI/colibri.pl
index 97918421e..141e8a094 100755
--- a/Src/COLIBRI/colibri.pl
+++ b/Src/COLIBRI/colibri.pl
@@ -279,6 +279,8 @@ init_colibri :-
                arith,
                mod_arith,
                realarith,
+               % NEW
+               trigo,
                dump_constraints,
                smt_import,
                simplex_ocaml,
diff --git a/Src/COLIBRI/mod.pl b/Src/COLIBRI/mod.pl
index c8cac0d93..fdb8a9f17 100755
--- a/Src/COLIBRI/mod.pl
+++ b/Src/COLIBRI/mod.pl
@@ -161,6 +161,7 @@ print_mod(_{mod:congr(R,M)}, Attribute) :-
 
 exists_congr(Num,C,Mod) :-
     number(Num),
+    abs(Num) =\= 1.0Inf,
     once (integer(Num);
           is_float_int_number(Num)),
     !,
diff --git a/Src/COLIBRI/mreal.pl b/Src/COLIBRI/mreal.pl
index ce147d3bb..b88a9085a 100755
--- a/Src/COLIBRI/mreal.pl
+++ b/Src/COLIBRI/mreal.pl
@@ -780,7 +780,8 @@ set_var_domain(V{mreal:OldDom},Type,Inter,S,Wake) ?- !,
         (NInterval == OldInter ->
             true
         ;   ((NInterval = [Val],
-              float(Val)) ->
+              float(Val))
+            ->
                 (Type == real ->
                     abs(Val) =\= 1.0Inf
                 ;   true),
@@ -788,7 +789,8 @@ set_var_domain(V{mreal:OldDom},Type,Inter,S,Wake) ?- !,
             ;   arg(3,OldDom,OS),
                 setarg(2,OldDom,NInterval),
                 setarg(3,OldDom,NS),
-                ((get_sign(V,SV), SV \== OSV; % on devient signe
+                ((Type == real;
+                  get_sign(V,SV), SV \== OSV; % on devient signe
                   is_float_int_number(V);
                   is_not_float_int_number(V);
                   check_threshold(NInterval,NS,OldInter,OS))
@@ -973,7 +975,8 @@ dvar_set(Var{mreal:dom(Type,Inter0,S0)},dom(Type,Inter,S)) ?- !,
     reduce_float_int(Var,Type,Inter,S,Inter1,S1),
     Inter1 \== [],
     ((Inter1 = [Val],
-      float(Val)) ->
+      float(Val))
+    ->
         (Type == real ->
             abs(Val) =\= 1.0Inf
         ;   true),
diff --git a/Src/COLIBRI/ndelta.pl b/Src/COLIBRI/ndelta.pl
index b9c190bb6..8b792c085 100755
--- a/Src/COLIBRI/ndelta.pl
+++ b/Src/COLIBRI/ndelta.pl
@@ -351,7 +351,7 @@ check_pu(T1,T2) :-
           call(getval(from_pu,0))@eclipse)
         ->
             call(spy_here)@eclipse,
-            writeln(output,pb_unify_from_pu)
+            writeln(output,pb_unify_from_pu(T1,T2))
         ;   call(setval(from_pu,0))@eclipse)
     ;   true).
 
@@ -1307,6 +1307,13 @@ launch_delta_bis1(X,Y,S,C) :-
 % on ignore les distances nulles (pbs sinon)
 %launch_delta_bis2(X,Y,S,0,CheckCycle,LoopOnly,Abort) ?- !.
 launch_delta_bis2(X,Y,S0,C,CheckCycle,_LoopOnly,Abort) :-
+    ((C = LC..HC,
+      HC < LC)
+    ->
+        call(spy_here)@eclipse,
+        writeln(output,pb_launch_delta_bis2(X,Y,S0,C)),
+        fail
+    ;   true),
     once (getval(use_delta,1)@eclipse ->
              true
          ;   (once (get_type(X,T);
@@ -1340,7 +1347,7 @@ launch_delta_bis2(X,Y,S0,C,CheckCycle,_LoopOnly,Abort) :-
                     % On a reduit un arc d'une ou plusieurs boucles
                     % on doit verifier chaque boucle connexe
                     CheckCycle = 1
-                    % LoopOnly = 1
+                                 % LoopOnly = 1
                 ;   true)))
     ;   % On n'avait pas de delta entre X et Y
         (same_CC(X,Y) ->
diff --git a/Src/COLIBRI/new_parser_builtins.pl b/Src/COLIBRI/new_parser_builtins.pl
index 7e83f16d8..08d60ceac 100644
--- a/Src/COLIBRI/new_parser_builtins.pl
+++ b/Src/COLIBRI/new_parser_builtins.pl
@@ -86,15 +86,36 @@ add_new_parser_builtins :-
                                          [real,real],real)]),
     p_simplex_ocaml_add_builtins([builtin("colibri_min_fp",[],[],[m,e],[],
                                          [fp(m,e),fp(m,e)],fp(m,e))]),
+    p_simplex_ocaml_add_builtins([builtin("colibri_sqrt",[],[],[],[],
+                                         [real],real)]),
     p_simplex_ocaml_add_builtins([builtin("colibri_exp_real",[],[],[],[],
                                          [real],real)]),
+    p_simplex_ocaml_add_builtins([builtin("colibri_exp",[],[],[],[],
+                                         [real],real)]),
     p_simplex_ocaml_add_builtins([builtin("colibri_exp_fp",[],[],[m,e],[],
                                          [fp(m,e)],fp(m,e))]),
     p_simplex_ocaml_add_builtins([builtin("colibri_ln_real",[],[],[],[],
                                          [real],real)]),
+    p_simplex_ocaml_add_builtins([builtin("colibri_ln",[],[],[],[],
+                                         [real],real)]),
     p_simplex_ocaml_add_builtins([builtin("colibri_ln_fp",[],[],[m,e],[],
                                          [fp(m,e)],fp(m,e))]),
+    p_simplex_ocaml_add_builtins([builtin("colibri_sin",[],[],[],[],
+                                         [real],real)]),
+    p_simplex_ocaml_add_builtins([builtin("colibri_cos",[],[],[],[],
+                                         [real],real)]),
+    p_simplex_ocaml_add_builtins([builtin("colibri_tan",[],[],[],[],
+                                         [real],real)]),
+    p_simplex_ocaml_add_builtins([builtin("colibri_asin",[],[],[],[],
+                                         [real],real)]),
+    p_simplex_ocaml_add_builtins([builtin("colibri_acos",[],[],[],[],
+                                         [real],real)]),
+    p_simplex_ocaml_add_builtins([builtin("colibri_atan",[],[],[],[],
+                                         [real],real)]),
+    p_simplex_ocaml_add_builtins([builtin("colibri_pi",[],[],[],[],
+                                         [],real)]),
 % pour inities
+    p_simplex_ocaml_add_builtins([builtin("colibri_range",[],[],[],[],[real,real,real],real)]),
     p_simplex_ocaml_add_builtins([builtin("colibri_setIntegral",[],[],[],[],
                                          [real],real)]),
 % Utilisés pour définition semantique et aussi par AdaCore
diff --git a/Src/COLIBRI/rbox.pl b/Src/COLIBRI/rbox.pl
index 6179ad97f..264ea9c9e 100755
--- a/Src/COLIBRI/rbox.pl
+++ b/Src/COLIBRI/rbox.pl
@@ -254,19 +254,26 @@ print_rbox(Var{rbox:rf(RF,NaN)}, Attribute) :-
 %----------------------------------------------------------------
 % Les lanceurs/observateurs de status
 %----------------------------------------------------------------
+:- import is_mpi_var/4 from colibri.
 launch_box(Var) :-
     var(Var),
+    !,
     get_priority(Prio),
     set_priority(1),
     ((mreal:get_intervals(Var,[L..H]),
-      get_next_float(float_double,L,NL),
-      NL == H)
+      get_next_float(real,L,NL),
+      NL =:= H) % attention aux zeros
     ->
         % on a bien une boite
-        launch_box_prio(Var,_)
+        launch_box_prio(Var,_),
+        (is_mpi_var(Var,PV,_,_) ->
+            protected_unify(Var,PV)
+        ;   true)
     ;   true),
     set_priority(Prio),
     wake_if_other_scheduled(Prio).
+launch_box(_Var).
+
 launch_box_rat(Var,Rat) :-
     % Attention Var et Rat peuvent etre instancies
     get_priority(Prio),
@@ -283,6 +290,7 @@ launch_box_rat(Var,Rat) :-
    from colibri.
 
 %% Variable deja attribuee
+:- export launch_box_prio/2.
 launch_box_prio(Var{rbox:rf(RF,NaN)},Rat) ?- !,
     NaN == 0,
     RF \== float,
diff --git a/Src/COLIBRI/realarith.pl b/Src/COLIBRI/realarith.pl
index bb54cd527..a3833f9aa 100644
--- a/Src/COLIBRI/realarith.pl
+++ b/Src/COLIBRI/realarith.pl
@@ -1,7 +1,6 @@
 %% Par defaut on utilise les simplifications
 :- setval(real_simp,1)@eclipse.
 
-
 %% ARITHMETIQUE RELLE ET FLOTTANTE SELON LA
 %% VARIABLE GLOBALLE "float_eval" (real ou float_simple ou float_double )
 %% PMO pour l instant seule real et float_double sont implantees mais le materiel
@@ -1751,8 +1750,6 @@ real_from_rat(Rat,R) :-
             protected_unify(R,LR)
         ;   Inter = [LR..HR],
             real_vars(real,R),
-            get_reif_var_depth_from_labchoice(DD),
-            insert_dep_inst(inst_cstr(DD,R)),
             mreal:set_typed_intervals(R,real,Inter),
             add_real_cst(Rat,R),
             launch_box_rat(R,Rat))).
@@ -3399,9 +3396,9 @@ is_op_real(Type,A,OpA) :-
     get_saved_cstr_suspensions(LS),
     member((_,op_real1(Type,X,Y)),LS),
     (A == X ->
-        OpA == Y
+        protected_unify(OpA,Y)
     ;   A == Y,
-        OpA == X).
+        protected_unify(OpA,X)).
 
 
 check_2box(real,L) ?- !,
@@ -3686,83 +3683,85 @@ forbid_OpInf(Type,V) :-
 
 forbid_Inf(real,V) :- !.
 forbid_Inf(Type,V) :-
-	(float(V) ->
-		V \== 1.0Inf
-	;	get_previous_float(Type,1.0Inf,Max),
-		mreal:dvar_remove_greater(V,Max)).
+    (float(V) ->
+        V \== 1.0Inf
+    ;   get_previous_float(Type,1.0Inf,Max),
+        mreal:dvar_remove_greater(V,Max)).
 
 
 %%greatest_interval_not_absorbing(_,_,B,0.0) :- !.
 greatest_interval_not_absorbing(add,Type,B,Inter) :-
-	greatest_interval_not_absorbing(Type,B,Inter).
+    greatest_interval_not_absorbing(Type,B,Inter).
 greatest_interval_not_absorbing(minus,Type,B,Inter) :-
-	(float(B) ->
-		norm_zero_op(real,B,OpB),
-		greatest_interval_not_absorbing(Type,OpB,Inter)
-	;	mreal:get_intervals(B,IB),
-		get_float_int_status(B,FIB),%%PMO
-		split_neg_pos_real(Type,FIB,IB,NegB,PosB,_),
-		(last(NegB,NB) ->
-			min_max_inter(NB,_,OpMinPos),
-			MinPos is -OpMinPos
-		;	true),
-		(PosB = [PB|_] ->
-			min_max_inter(PB,OpMaxNeg,_),
-			MaxNeg is -OpMaxNeg
-		;	true),
-		greatest_interval_not_absorbing_interval(Type,MaxNeg,MinPos,Inter)).
+    (float(B) ->
+        norm_zero_op(real,B,OpB),
+        greatest_interval_not_absorbing(Type,OpB,Inter)
+    ;   mreal:get_intervals(B,IB),
+        get_float_int_status(B,FIB),%%PMO
+        split_neg_pos_real(Type,FIB,IB,NegB,PosB,_),
+        (last(NegB,NB) ->
+            min_max_inter(NB,_,OpMinPos),
+            MinPos is -OpMinPos
+        ;   true),
+        (PosB = [PB|_] ->
+            min_max_inter(PB,OpMaxNeg,_),
+            MaxNeg is -OpMaxNeg
+        ;   true),
+        greatest_interval_not_absorbing_interval(Type,MaxNeg,MinPos,Inter)).
 
 
 greatest_interval_not_absorbing(Type,B,Low..High) :-
-	%% B <> 0.0
-	float(B),!,
-	greatest_interval_not_absorbing_val(Type,B,Low,High).
+    % B <> 0.0
+    float(B),!,
+    greatest_interval_not_absorbing_val(Type,B,Low,High).
 greatest_interval_not_absorbing(Type,B,Low..High) :-
-	mreal:get_intervals(B,IB),
-	get_float_int_status(B,FIB),%%PMO
-	split_neg_pos_real(Type,FIB,IB,NegB,PosB,_),
-	(last(NegB,NB) ->
-		min_max_inter(NB,_,MaxNeg)
-	;	true),
-	(PosB = [PB|_] ->
-		min_max_inter(PB,MinPos,_)
-	;	true),
-	greatest_interval_not_absorbing_interval(Type,MaxNeg,MinPos,Low..High).
+    mreal:get_intervals(B,IB),
+    get_float_int_status(B,FIB),%%PMO
+    split_neg_pos_real(Type,FIB,IB,NegB,PosB,_),
+    (last(NegB,NB) ->
+        min_max_inter(NB,_,MaxNeg)
+    ;   (Type == real ->
+            MaxNeg = 0.0
+        ;   MaxNeg = -0.0)),
+    (PosB = [PB|_] ->
+        min_max_inter(PB,MinPos,_)
+    ;   MinPos = 0.0),
+    greatest_interval_not_absorbing_interval(Type,MaxNeg,MinPos,Low..High).
 
 
 greatest_interval_not_absorbing_interval(Type,MaxNeg,MinPos,Low..High) :-
-	(nonvar(MaxNeg) ->
-		greatest_interval_not_absorbing_val(Type,MaxNeg,L1,H1),
-		(nonvar(MinPos)->
-			greatest_interval_not_absorbing_val(Type,MinPos,L2,H2),
-			Low is max(L1,L2),
-			High is min(H1,H2)
-		;	Low = L1,
-			High = H1)
-	;	%% nonvar(MinPos)
-		greatest_interval_not_absorbing_val(Type,MinPos,Low,High)).
+    (nonvar(MaxNeg) ->
+        greatest_interval_not_absorbing_val(Type,MaxNeg,L1,H1),
+        (nonvar(MinPos)->
+            greatest_interval_not_absorbing_val(Type,MinPos,L2,H2),
+            Low is max(L1,L2),
+            High is min(H1,H2)
+        ;   Low = L1,
+            High = H1)
+    ;   % nonvar(MinPos)
+        greatest_interval_not_absorbing_val(Type,MinPos,Low,High)).
 
 %% On calcule le plus grand intervalle dont toute valeur
 %% absorbe B
 greatest_interval_not_absorbing_val(Type,B,Low,High) :-
-	AbsB is abs(B),
-	floor_log2(AbsB,FL2),
-	(AbsB is 2.0^FL2 ->
-		%% On est sur une puissance de 2
-		%% SH est le plus petit flottant positif qui absorbe AbsB
-		SH is 2.0^(FL2+get_mantissa_size(Type)+1),
-		get_previous_float(Type,SH,H),
-		get_next_float(Type,SH,OpL),
-		L is - OpL
-	;	%% Entre 2 puissances de deux, le premier positif est a 2^(54+FL2)
-		SH is 2.0^(FL2+get_mantissa_size(Type)+2),
-		get_previous_float(Type,SH,H),
-		L is -SH),
-	(B > 0.0 ->
-		Low = L,
-		High = H
-	;	Low is -H,
-		High is -L).
+    AbsB is abs(B),
+    floor_log2(AbsB,FL2),
+    (AbsB is 2.0^FL2 ->
+        % On est sur une puissance de 2
+        % SH est le plus petit flottant positif qui absorbe AbsB
+        SH is 2.0^(FL2+get_mantissa_size(Type)+1),
+        get_previous_float(Type,SH,H),
+        get_next_float(Type,SH,OpL),
+        L is - OpL
+    ;   % Entre 2 puissances de deux, le premier positif est a 2^(54+FL2)
+        SH is 2.0^(FL2+get_mantissa_size(Type)+2),
+        get_previous_float(Type,SH,H),
+        L is -SH),
+    (B > 0.0 ->
+        Low = L,
+        High = H
+    ;   Low is -H,
+        High is -L).
 
 add_real_zeroes(real,_,_,C) ?- !,
     protected_unify(C,0.0).
@@ -3965,7 +3964,12 @@ add_real_inst0(real,A,B,C,Continue) :- !,
         ;   (C == 0.0 ->
                 Stop = 1,
                 op_real(real,A,B)
-            ;   true))),
+            ;   ((is_real_box(A),
+                  is_real_box(B))
+                ->
+                    add_real_interval(real,A,B,C),
+                    launch_box(C)
+                ;   true)))),
     (nonvar(Stop) ->
         true
     ;   (nonvar(BoxGoal) ->
@@ -5639,7 +5643,7 @@ minus_real_int_ineqs(A,B,C) :-
 
 op_real_int_ineqs(A,OpA) :-
     getval(use_delta,1)@eclipse,
-    get_sign(A,SA),
+    get_sign_real(A,SA),
     !,
     (SA == pos ->
         % SOpA = neg
@@ -7570,8 +7574,10 @@ cast_real_int(A,B) :-
     cast_real_int_type(Type,A,B).
 
 cast_real_int_type(real,A,B) ?- !,
+    ensure_not_NaN(A),
     cast_real_int(real,A,B).
 cast_real_int_type(Type,A,B) :-
+    ensure_not_NaN(A),
     cast_fp_int(Type,A,B).
 
 cast_fp_int(Type,A,B) :-
@@ -7591,13 +7597,14 @@ cast_fp_int(Type,A,B) :-
     cast_fp_int(Cond,Type,A,B).
 
 cast_fp_int(0,Type,A,B) ?- !,
+    ensure_not_NaN(A),
     cast_real_int(Type,A,B).
 cast_fp_int(1,Type,A,B) ?- !,
     uninterp(cast_fp_int,cast_fp_int,[Type],int,[A],B).
 cast_fp_int(Cond,Type,A,B) :-
     get_priority(Prio),
-	set_priority(1),
-	((check_not_NaN(A),
+    set_priority(1),
+    ((check_not_NaN(A),
       not_inf([A]))
     ->
         protected_unify(Cond,0),
@@ -7618,6 +7625,7 @@ cast_real_int(Type,A,B) :-
     get_priority(Prio),
     set_priority(1),
     set_lazy_domain(Type,A),
+    ensure_not_NaN(A),
     save_cstr_suspensions((A,B)),
     (not_inf_bounds(A) ->
         % on peut dimensioner B
@@ -8247,12 +8255,22 @@ op_real_inst(real,A,B,Continue) :- !,
                     %launch_box_rat(A,RatA),
                     check_op_rat(B,A),
                     BoxGoal = op_real1(real,B,A)
-                ;   same_box_float_number_status(A,B,Box),
-                    Continue = 1)),
+                ;   ((is_real_box(A),
+                      is_mpi_var(A,PA,OPA,_))
+                    ->
+                        protected_unify(A,PA),
+                        protected_unify(B,OPA)
+                    ;   ((is_mpi_var(B,PB,OPB,_),
+                          is_real_box(B))
+                        ->
+                            protected_unify(B,PB),
+                            protected_unify(A,OPB)
+                        ;   same_box_float_number_status(A,B,Box),
+                            Continue = 1)))),
             (var(Continue) ->
-                check_rbox_cstrs(2,BoxGoal),
                 (nonvar(BoxGoal) ->
                     % parano
+                    check_rbox_cstrs(2,BoxGoal),
                     check_op_rat(A,B)
                 ;   true)
             ;   true))).
@@ -8379,7 +8397,6 @@ check_before_susp_op_real(Type,A,B) :-
         (MinA >= 0 ->
             AA = B, BB = A
         ;   AA = A, BB = B),
-        
         my_suspend(op_real1(Type,AA,BB),2,(AA,BB)->suspend:constrained)).
 
 
@@ -10314,12 +10331,10 @@ diff_real_value(Var,Val) :-
 		
 
 get_sign_real(A,SA) :-
-    mreal:mindomain(A,MinA),
-    mreal:maxdomain(A,MaxA),
-    (MinA >= 0.0 ->
-        % donc 0 est pos
+    mreal:dvar_range(A,L,H) ,
+    (L >= 0.0 ->
         SA = pos
-    ;   MaxA =< 0.0,
+    ;   H =< 0.0,
         SA = neg).
     
 %% On force le signe d'un argument
@@ -10419,12 +10434,13 @@ mult_real_int_ineqs(SA,SB,A,B,C) :-
             forbid_zero(real,C)
         ;   true)),
     % A revoir et generaliser
+    once (get_sign_real(C,SC);true),
     ((getval(use_delta,1)@eclipse,
       nonvar(SA),
       nonvar(SB),
+      nonvar(SC),
       var(C))
     ->
-        once (get_sign(C,SC);true),
         (var(A) ->
             mult_real_int_ineqs0(NZ,SC,SA,A,B,C)
         ;   true),
@@ -10436,10 +10452,13 @@ mult_real_int_ineqs(SA,SB,A,B,C) :-
 mult_real_int_ineqs0(NZ,SC,SOther,Other,Fact,C) :-
     % Fact * Other = C
     minus_real_interval(real,C,Other,Diff),
+    % C - Other = Diff -> C = Diff + Other
     mreal:dvar_range(Diff,LD0,HD0),
+    launch_delta(Other,C,+,LD0..HD0).
+/*
     (SOther \== SC ->
         (SOther == pos ->
-            % C neg, Other >= C
+            % C neg, Other pos, Other >= C
             HD1 is min(HD0,0.0),
             LD1 = LD0
         ;   % Other neg, C pos, Other =< C
@@ -10457,13 +10476,15 @@ mult_real_int_ineqs0(NZ,SC,SOther,Other,Fact,C) :-
         ;   rational(LD1,LD))),
     (HD1 == 1.0Inf ->
         HD = HD1
-    ;   ((HD1 == 0.0,
+    ;   call(spy_here)@eclipse,
+        ((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(>,<).
@@ -11096,14 +11117,6 @@ get_first_normal_div_mult(_,DN) :-
     %DN is 2.0^(-1022).
     DN = 2.2250738585072014e-308.
 
-is_op_real(V,OpV) :-
-    (number(V) ->
-        number(OpV),
-        OpV is -V
-    ;   get_saved_cstr_suspensions(LS),
-        member((Susp,op_real1(_,X,Y)),LS),
-        ((X,Y) == (V,OpV); (X,Y) == (OpV,V))).
-
 %% A * B = -A
 mult_real_op_arg_res(Type,A,B,Continue) :-
     (Type == real ->
@@ -12734,12 +12747,14 @@ div_real_dom(Rel12,FI1,FI2,FI,Dom1,Dom2,Dom,NewDom) :-
         (Z1 == 0.0 ->
             mreal:dom_intersection(dom(real,[0.0],1),Dom,NewDom,_)
         ;   (MP1 == 1.0 ->
-                mreal:dom_intersection(Dom2,Dom,NDom,_)
-            ;   % -1
+                %mreal:dom_intersection(Dom2,Dom,NDom,_)
+                mreal:dom_intersection(Dom1,Dom,NDom,_),
+                reduce_float_int_domain(real,FI,NDom,NewDom)
+            ;   % MP1 == -1.0
                 op_real_intervals(Type,Inter1,-1.0Inf,[],Inter),
                 mreal:list_to_typed_dom(real,Inter,NDom0),
-                mreal:dom_intersection(Dom,NDom0,NDom,_)),
-            reduce_float_int_domain(real,FI,NDom,NewDom))
+                mreal:dom_intersection(Dom,NDom0,NDom,_),
+                reduce_float_int_domain(real,FI,NDom,NewDom)))
     ;   ((Inter1 = [I1],
           Inter2 = [I2])
         ->
@@ -13877,6 +13892,7 @@ div_real_ineqs(Type,A,B,C) :-
 
 %On peut etre plus precis sur les float_int
 div_real_int_ineqs(SA,SB,A,B,C) :-
+    % B <> 0,
     (not_zero(C) ->
         NZ = 1,
         forbid_zero(real,A)
@@ -13885,12 +13901,13 @@ div_real_int_ineqs(SA,SB,A,B,C) :-
             forbid_zero(real,C)
         ;   true)),
     % A revoir et generaliser
+    once (get_sign_real(C,SC);true),
     ((getval(use_delta,1)@eclipse,
       nonvar(SA),
       nonvar(SB),
+      nonvar(SC),
       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
@@ -17162,7 +17179,7 @@ square_real_type(Type,A,B) :-
 
 square_real(Type,A,B) :-
     ensure_not_NaN((A,B)),
-    (ground(A) ->
+    (nonvar(A) ->
         mult_real_inst(Type,A,A,B,_)
     ;   set_lazy_domain(Type,A),
         set_lazy_domain(Type,B),
@@ -17810,33 +17827,33 @@ sqrt_real_interval(Type,A,B) :-
 
 
 sqrt_real1(Type,A,B) :-
-	get_priority(Prio),
-	set_priority(1),
-	sqrt_real_bis(Type,A,B),
-	set_priority(Prio),
-	wake_if_other_scheduled(Prio).
+    get_priority(Prio),
+    set_priority(1),
+    sqrt_real_bis(Type,A,B),
+    set_priority(Prio),
+    wake_if_other_scheduled(Prio).
 
 
 sqrt_real_bis(Type,Val1,Val) :-
-	(Val1 == Val ->
-		(Type == real ->
+    (Val1 == Val ->
+        (Type == real ->
             mreal:set_typed_intervals(Val,Type,[0.0,1.0])
         ;   mreal:set_typed_intervals(Val,Type,[-0.0,0.0,1.0,1.0Inf]))
-	;	save_cstr_suspensions((Val1,Val)),
-		(Type ==  real ->
-			(not_zero(Val1)	->
-				forbid_zero(Type,Val)
-			;	(not_zero(Val) ->
-					forbid_zero(Type,Val1)
-				;	true))
-		;	%% Inutile en float
-			true),
-		check_exists_sqrt_real(Type,Val1,Val),
-		sqrt_real_inst(Type,Val1,Val,Continue),
-		(nonvar(Continue) ->
-			sqrt_real_rec(Type,Val1,Val),
-			check_before_susp_sqrt_real(Type,Val1,Val)
-		;	true)).
+    ;   save_cstr_suspensions((Val1,Val)),
+        (Type ==  real ->
+            (not_zero(Val1) ->
+                forbid_zero(Type,Val)
+            ;   (not_zero(Val) ->
+                    forbid_zero(Type,Val1)
+                ;   true))
+        ;   % Inutile en float
+            true),
+        check_exists_sqrt_real(Type,Val1,Val),
+        sqrt_real_inst(Type,Val1,Val,Continue),
+        (nonvar(Continue) ->
+            sqrt_real_rec(Type,Val1,Val),
+            check_before_susp_sqrt_real(Type,Val1,Val)
+        ;   true)).
 
 
 sqrt_real_rec(Type,Val1,Val) :-
@@ -19062,6 +19079,7 @@ refute_diff_real_with_gt_lt(Type,A,B,Stop) :-
     var(Stop),
     getval(use_delta,1)@eclipse,
     getval(refutation_chk,0)@eclipse,
+    get_priority(Prio),
     once (mreal:get_intervals(A,[L,H]),
           number(L),number(H),
           Var = A,Other = B;
@@ -19093,7 +19111,7 @@ refute_diff_real_with_gt_lt(Type,A,B,Stop) :-
             ;   set_priority(1),
                 protected_unify(Var,H),
                 launch_diff_real(Type,Var,Other))
-        ;   set_priority(1),
+        ;   set_priority(Prio),
             protected_unify(Var,L),
             launch_diff_real(Type,Var,Other))
     ;   Continue = 1),
@@ -19111,7 +19129,7 @@ refute_diff_real_with_gt_lt(Type,A,B,Stop) :-
               mreal:dvar_range(Var,L,H),
               setval(rangeVar,(L,H)))
         ->
-            set_priority(1),
+            set_priority(Prio),
             Stop = 1,
             lin_gt_real(A,B),
             gt_real(Type,A,B),
@@ -19125,7 +19143,7 @@ refute_diff_real_with_gt_lt(Type,A,B,Stop) :-
                   mreal:dvar_range(Var,L,H),
                   setval(rangeVar,[ORange,(L,H)]))
             ->
-                set_priority(1),
+                set_priority(Prio),
                 Stop = 1,
                 ORange = (L,H),
                 interval_from_bounds(L,H,Inter),
@@ -19133,7 +19151,7 @@ refute_diff_real_with_gt_lt(Type,A,B,Stop) :-
                 lin_gt_real(B,A),
                 gt_real(Type,B,A)
             % lin_solve_var inutile ici
-            ;   set_priority(1),
+            ;   set_priority(Prio),
                 getval(rangeVar,[(L1,H1),(L2,H2)]),
                 list_to_intervals(Type,[L1..H1,L2..H2],Intervals),
                 mreal:set_typed_intervals(Var,Type,Intervals),
@@ -19292,7 +19310,8 @@ diff_real_number_box(Type,A,B,_,Continue) :-
     A \== B,
     (float(A) ->
         ((float(B);
-          is_real_box(B)) ->
+          is_real_box(B))
+        ->
             true
         ;   (is_removable_real_value_in_var(Type,diff,A,B,L,H) ->
                 mreal:set_typed_intervals(B,Type,[-1.0Inf..L,H..1.0Inf])
@@ -19314,10 +19333,17 @@ diff_real_number_box(Type,A,B,_,Continue) :-
                     ->
                         % marche aussi si variables quand IA <> IB
                         RatA \== RatB
-                    ;   % Si IA = IB, il y a des solutions reelles mais
-                        % pas de forme resolue: on garde diff_real
-                        % en esperant une unification provoquant le fail
-                        Continue = 1)
+                    ;   % c'est le moment de regarder si on est sur des *pi*
+                        (is_mpi_var(A,PA,OPA,_) ->
+                            protected_unify(A,PA),
+                            (is_mpi_var(B,PB,OPB,_) ->
+                                protected_unify(B,PB),
+                                A \== B
+                            ;   % Si IA = IB, il y a des solutions reelles mais
+                                % pas de forme resolue: on garde diff_real
+                                % en esperant une unification provoquant le fail
+                                Continue = 1)
+                        ;   Continue = 1))
                 ;   CheckIntersection = 1))
         ;   (is_removable_real_value_in_var(Type,diff,B,A,L,H) ->
                 (float(B) ->
@@ -19735,7 +19761,15 @@ geq_real_number_box(real,A,B,Continue) ?- !,
                       rational(MinA) > RB)
                       ->
                         true
-                    ;	Continue = 1)
+                    ;	(is_mpi_var(A,PA,OPA,_) ->
+                            protected_unify(A,PA),
+                            (is_mpi_var(B,PB,OPB,_) ->
+                                protected_unify(B,PB),
+                                (A == B ->
+                                    true
+                                ;   Continue = 1)
+                            ;   Continue = 1)
+                        ;   Continue = 1))
                 ;   % A real_box et B intervalle
                     % on ne peut enlever que au dessus de MaxA
                     % et on garde la contrainte (pour le cas = ?)
@@ -20171,8 +20205,14 @@ gt_real_boxA(A,B,Continue) :-
                 MaxA >= MaxB,
                 (MinA >= MaxB ->
                     true
-                ;   % Les rbox interdisent A = B
-                    Continue = 1)
+                ;   (is_mpi_var(A,PA,OPA,_) ->
+                        protected_unify(A,PA),
+                        (is_mpi_var(A,PB,OPB,_) ->
+                            protected_unify(B,PB),
+                            A \== B
+                        ;   Continue = 1)
+                    ;   % Les rbox interdisent A = B
+                        Continue = 1))
             ;   (is_float_number(B) ->
                     % MinA < A
                     mreal:dvar_remove_greater(B,MinA)
diff --git a/Src/COLIBRI/smt_import.pl b/Src/COLIBRI/smt_import.pl
index 425adb586..0ecd85539 100644
--- a/Src/COLIBRI/smt_import.pl
+++ b/Src/COLIBRI/smt_import.pl
@@ -1,4 +1,4 @@
-
+:- pragma(noexpand).
 :- set_flag(syntax_option,iso_base_prefix).
 :- set_flag(syntax_option,based_bignums).
 
@@ -200,11 +200,9 @@ check_overloaded(colibri_real_isIntegral,colibri_isIntegral) :- !.
 check_overloaded(colibri_fp_isIntegral,colibri_isIntegral) :- !.
 check_overloaded(colibri_min_int,colibri_min) :- !.
 check_overloaded(colibri_min_real,colibri_min) :- !.
-%check_overloaded(colibri_min_fp,colibri_min) :- !.
 check_overloaded(colibri_min_fp,'fp.min') :- !.
 check_overloaded(colibri_max_int,colibri_max) :- !.
 check_overloaded(colibri_max_real,colibri_max) :- !.
-%check_overloaded(colibri_max_fp,colibri_max) :- !.
 check_overloaded(colibri_max_fp,'fp.max') :- !.
 check_overloaded(colibri_exp_real,colibri_exp) :- !.
 check_overloaded(colibri_exp_fp,colibri_exp) :- !.
@@ -362,7 +360,8 @@ term_from_dolmen_const(nan(E,S),Term) ?- !,
     Term = '_'('NaN',E,S).
 term_from_dolmen_const(fp(S,E,M),Term) ?- !,
     Term = fp(bv("b",S),bv("b",E),bv("b",M)).
-
+term_from_dolmen_const(colibri_builtin(S,_),Term) ?- !,
+    term_string(Term,S).
 
 build_cterm(CId,TId,CTerms,Term) :-
     get_col_id(CId,TId,ColId,Chainable),
@@ -607,7 +606,11 @@ check_sat0 :-
                 ((occurs(F,(isNaN,isNormal,isSubnormal,
                             isInfinite,isFinite,isZero,
                             isPositive,isNegative,
-                            uninterp,fp_eq1));
+                            uninterp,fp_eq1,
+                            sin_cos_value));
+                  occurs(F,(sinr,cosr)),
+                  arg(1,Goal,SC),
+                  is_real_box(SC);
                   (Goal = chk_nan_reif(_,_,_,CN);
                    ((% not_int
                         Goal = diff_int(V1,V2);
@@ -689,7 +692,8 @@ check_sat0 :-
     ;   writeln(output,Diag)).
 
 check_sat_vars :-
-    not not check_sat_vars0.
+%    not not check_sat_vars0.
+    check_sat_vars0.
 check_sat_vars0 :-
     init_real_cst,
     init_seen_expr,
@@ -713,6 +717,14 @@ check_sat_vars0 :-
                spy_here,
                call(Goal)))),
     setval(diag_code,(sat,1))@eclipse,
+
+    delayed_goals(NGoals),
+    term_variables(NGoals,GoalsVars),
+    (foreach(GV,GoalsVars),
+     foreach((GV,0,[]),NGoalsVars) do
+        trigo_no_rat(GV)),
+    once solve_cstrs_list([NGoalsVars]),
+
     % pas de residue,sinon wrong_sat
     suspensions(LSusp),
     (foreach(Susp,LSusp) do
@@ -721,7 +733,11 @@ check_sat_vars0 :-
         ((occurs(F,(isNaN,isNormal,isSubnormal,
                     isInfinite,isFinite,isZero,
                     isPositive,isNegative,
-                    uninterp,fp_eq1));
+                    uninterp,fp_eq1,
+                    sin_cos_value));
+          occurs(F,(sinr,cosr)),
+          arg(1,Goal,SC),
+          is_real_box(SC);
           (Goal = chk_nan_reif(_,_,_,CN);
            ((% not_int
              Goal = diff_int(V1,V2);
@@ -791,6 +807,11 @@ get_assignment :-
 
 % apres un check-sat
 get_model :-
+    (get_model0 ->
+        true
+    ;   Warn = "(warning: unknown error in get-model)",
+        writeln(error,Warn)).
+get_model0 :-
     (getval(diag_code,(_,1))@eclipse;
      getval(unknown_quantifier_abstraction,1)@eclipse),
     !,
@@ -833,7 +854,7 @@ get_model :-
     ;   true),
     setval(use_delta,UD)@eclipse,
     setval(use_simplex,US)@eclipse.
-get_model.
+get_model0.
 
 get_initial_variable_type(V,Type0,Type) :-
     (get_variable_type(V,TypeI) ->
@@ -857,6 +878,11 @@ get_initial_type(sort(Sort),Sort) :- !.
 
 % apres un check-sat
 get_value(LExpr) :-
+    (get_value0(LExpr) ->
+        true
+    ;   Warn = "(warning: unknown error in get-value)",
+        writeln(error,Warn)).
+get_value0(LExpr) :-
     (getval(diag_code,(_,1))@eclipse;
      getval(unknown_quantifier_abstraction,1)@eclipse),
     !,
@@ -925,8 +951,9 @@ get_value(LExpr) :-
                 as(Expr,Type) $= Res),
             ((nonvar(Res);
               %FType == sort;
-              FType == real,
-              is_real_box(Res))
+              FType == real)
+              % trop strict pour la tigo !
+              %is_real_box(Res))
             ->
                 true
             ;   ((FType == array;
@@ -939,7 +966,7 @@ get_value(LExpr) :-
     ;   true),
     setval(use_delta,UD)@eclipse,
     setval(use_simplex,US)@eclipse.
-get_value(_).
+get_value0(_).
 
 remove_all_as(Atom,Atom) :-
     atomic(Atom),
@@ -1007,24 +1034,35 @@ dump_type_val(real,Val0,Val) ?- !,
     dump_type_val('Real',Val0,Val).
 dump_type_val('Real',Val0,NVal) ?- !,
     (var(Val0) ->
-        (known_real_box(Val0,SNum,SDen,Neg) ->
-            (SDen == "1" ->
-                concat_string([SNum,".0"],Val)
-            ;   concat_string(["(/ ",SNum,".0 ",SDen,".0)"],Val))
-        ;   mreal:dvar_range(Val0,L,H),
-            rational(L,RL),
-            rational(H,RH),
-            protected_numerator(RL,NumL),
-            protected_denominator(RL,DenL),
-            (DenL == 1 ->
-                concat_string([NumL,".0"],SL)
-            ;   concat_string(["(/ ",NumL,".0 ",DenL,".0)"],SL)),
-            protected_numerator(RH,NumH),
-            protected_denominator(RH,DenH),
-            (DenH == 1 ->
-                concat_string([NumH,".0"],SH)
-            ;   concat_string(["(/ ",NumH,".0 ",DenH,".0)"],SH)),
-            concat_string(["(range ",SL," ",SH,")"], Val))
+        mreal:dvar_range(Val0,L,H),
+        (is_decimal_string(L) ->
+            number_string(L,SL0)
+        ;   true),
+        (is_decimal_string(H) ->
+            number_string(H,SH0)
+        ;   true),
+        ((nonvar(SL0),
+          nonvar(SH0))
+        ->
+            SL = SL0,
+            SH = SH0
+        ;   (known_real_box(Val0,SNum,SDen,Neg) ->
+                (SDen == "1" ->
+                    concat_string([SNum,".0"],Val)
+                ;   concat_string(["(/ ",SNum,".0 ",SDen,".0)"],Val))
+            ;   rational(L,RL),
+                rational(H,RH),
+                protected_numerator(RL,NumL),
+                protected_denominator(RL,DenL),
+                (DenL == 1 ->
+                    concat_string([NumL,".0"],SL)
+                ;   concat_string(["(/ ",NumL,".0 ",DenL,".0)"],SL)),
+                protected_numerator(RH,NumH),
+                protected_denominator(RH,DenH),
+                (DenH == 1 ->
+                    concat_string([NumH,".0"],SH)
+                ;   concat_string(["(/ ",NumH,".0 ",DenH,".0)"],SH)))),
+        concat_string(["(colibri_range ",SL," ",SH,")"], Val)
     ;   rational(Val0,Val1),
         (Val1 < 0_1 ->
             Neg = 1,
@@ -1099,7 +1137,14 @@ dump_type_val(OType,Val,SVal) :-
     atom_string(OType,SOType),
     split_string(SOType,"|","",LSOType),
     join_string(LSOType,"",SEndVal0),
-    concat_string(["(as |@uc_",SEndVal0,"_",Cpt,"| ",SEndVal,")"],SVal).
+    concat_string(["(as |@uc_",SEndVal0,"_",Cpt,"| ",SEndVal,")"],
+                  SVal).
+
+is_decimal_string(F) :-
+    float(F),
+    number_string(F,SF),
+    split_string(SF,"e","",L),
+    L = [_].
 
 build_end_val_from_old_type([],[]) :- !.
 build_end_val_from_old_type([OType|OTypes],[NType|NTypes]) :- !,
@@ -1532,11 +1577,12 @@ defined_smt_func(F/Ar,IArgs,Type,IExpr) :-
                   FIArg0 == FIArg),
             protected_unify(FIArg,IArg),
             OE = OE1,
-            ((nonvar(IArgType),
-              IArgType = sort(Sort))
-            ->
-                % Peuplement des valeurs de Sort
-                new_sort_val(Sort)
+            (nonvar(IArgType) ->
+                findall(Sort,cgiveInstanceAndPath(sort(_),IArgType,
+                                                  sort(Sort),_),LSs),
+                (foreach(Sort,LSs) do
+                    % Peuplement de valeurs de Sort pour les diff
+                    new_sort_val(Sort))
             ;   true)),
         (FType == Type ->
             IExpr = IExpr0
@@ -1557,11 +1603,13 @@ defined_smt_func(F/Ar,IArgs,Type,IExpr) :-
             ->
                 NIArg = IArg
             ;   NIArg = as(IArg,IArgType)),
-            ((nonvar(IArgType),
-              IArgType = sort(Sort))
-            ->
-                % Peuplement des valeurs de Sort
-                new_sort_val(Sort)
+            call(spy_here)@eclipse,
+            (nonvar(IArgType) ->
+                findall(Sort,cgiveInstanceAndPath(sort(_),IArgType,
+                                                  sort(Sort),_),LSs),
+                (foreach(Sort,LSs) do
+                    % Peuplement de valeurs de Sort pour les diff
+                    new_sort_val(Sort))
             ;   true)),
         Term =.. [F|NIArgs],
         (Profile == real_int ->
@@ -2177,6 +2225,7 @@ smt_interp0('_'(FCst,EB,SB),as(Val,Type),Type) :- !,
     fp_cst(FCst,EB,SB,Val,Type).
 smt_interp0(true,as(1,bool),bool) :- !.
 smt_interp0(false,as(0,bool),bool) :- !.
+smt_interp0(colibri_pi,as(pi,real),real) :- !.
 smt_interp0(Atom,IAtom,Type) :-
     atomic(Atom),
     !,
@@ -2567,13 +2616,54 @@ smt_interp0(colibri_ln(A),Ln,Type) :-
     (Type == real ->
         Ln = ln(IA)
     ;   Ln = fp_ln(IA)).
+
+smt_interp0(colibri_range(A,LA,HA),Exp,real) :-
+    smt_interp(A,A0,real),
+    smt_interp(LA,RL,real),
+    smt_interp(HA,RH,real),
+    Exp = as(range(A0,RL,RH),real).
+smt_interp0(colibri_sin(A),Exp,real) :-
+    smt_interp(A,IA0,real),
+    !,
+    add_as(real,IA0,IA),
+    Exp = sin(IA).
+smt_interp0(colibri_cos(A),Exp,real) :-
+    smt_interp(A,IA0,real),
+    !,
+    add_as(real,IA0,IA),
+    Exp = cos(IA).
+smt_interp0(colibri_tan(A),Exp,real) :-
+    smt_interp(A,IA0,real),
+    !,
+    add_as(Type,IA0,IA),
+    Exp = tan(IA).
+smt_interp0(colibri_asin(A),Exp,real) :-
+    smt_interp(A,IA0,real),
+    !,
+    add_as(real,IA0,IA),
+    Exp = asin(IA).
+smt_interp0(colibri_acos(A),Exp,real) :-
+    smt_interp(A,IA0,real),
+    !,
+    add_as(real,IA0,IA),
+    Exp = acos(IA).
+smt_interp0(colibri_atan(A),Exp,real) :-
+    smt_interp(A,IA0,real),
+    !,
+    add_as(Type,IA0,IA),
+    Exp = atan(IA).
+
 smt_interp0(colibri_isIntegral(A),Exp,bool) :-
-    smt_interp(A,IA0,Type0),
+    smt_interp(A,IA0,Type),
     real_type(Type0,Type),
     !,
     add_as(Type,IA0,IA),
     Exp = isIntegral(IA).
 % uniquement pour les "real"
+smt_interp0(colibri_sqrt(A),Res,real) :- !,
+    smt_interp(A,IA0,real),
+    add_as(real,IA0,IA),
+    Res = sqrt(IA).
 smt_interp0(colibri_setIntegral(A),Exp,real) :-
     smt_interp(A,IA0,real),
     !,
diff --git a/Src/COLIBRI/solve.pl b/Src/COLIBRI/solve.pl
index 2be984352..f66f3bf6a 100644
--- a/Src/COLIBRI/solve.pl
+++ b/Src/COLIBRI/solve.pl
@@ -4847,22 +4847,32 @@ diff_array(Type,A,const_array(TI,TE,Const)) ?- !,
 diff_array(Type,A,B) :-
     get_priority(P),
     set_priority(1),
-    Type = array(TI,TE),
-    (getval(check_sat_vars,1)@eclipse ->
-        % Il existe un indice commun ou les elements sont non
-        % unifiables
-        check_diff_array(TE,A,B)
-    ;   (real_type(TI,_) ->
-            real_vars(TI,I)
-        ;   % ok pour les "sort" aussi
-            int_vars(TI,I)),
-        (real_type(TE,_) ->
-            real_vars(TE,[EA,EB])
-        ;   % ok pour les "sort/array" aussi
-            int_vars(TE,[EA,EB])),
-        smtlib_select(Type,A,I,EA),
-        smtlib_select(Type,B,I,EB),
-        diff_reif(TE,_,EA,EB,1)),
+    attached_suspensions(diff_array,LS),
+    ((member(S,LS),
+      get_suspension_data(S,goal,diff_array(Type,X,Y)),
+      (A == X ->
+          B == Y
+      ;   A == Y,
+          B == X))
+    ->
+        true
+    ;   Type = array(TI,TE),
+        (getval(check_sat_vars,1)@eclipse ->
+            % Il existe un indice commun ou les elements sont non
+            % unifiables
+            check_diff_array(TE,A,B)
+        ;   (real_type(TI,_) ->
+                real_vars(TI,I)
+            ;   % ok pour les "sort" aussi
+                int_vars(TI,I)),
+            (real_type(TE,_) ->
+                real_vars(TE,[EA,EB])
+            ;   % ok pour les "sort/array" aussi
+                int_vars(TE,[EA,EB])),
+            smtlib_select(Type,A,I,EA),
+            smtlib_select(Type,B,I,EB),
+            diff_reif(TE,_,EA,EB,1),
+            my_suspend(diff_array(Type,A,B),0,trigger(diff_array)))),
 /*
 % ANCIENNE VERSION MOINS RAPIDE QUE LES "select" !!!
     ;   hash_create(SureA),
@@ -6254,6 +6264,10 @@ unfold_real_expr(X,_D,Cstr,Type,R) :-
         exit_block(syntax)),
     %insert_dep_inst(inst_cstr(D,X)),
     Cstr = true.
+unfold_real_expr(pi,D,Cstr,Type,R) ?- !,
+    Type = real,
+    Cstr = true,
+    R is mpi.
 unfold_real_expr(X,_,Cstr,Type,FX) :-
     float(X),!,
     ensure_not_NaN(FX),
@@ -7017,15 +7031,6 @@ unfold_real_expr(fp_mul(Rnd0,EA,EB),D,Cstr,Type,R) ?-
                                         isZero(as(A,Type)),
                                         as(0,bool)))),
                             D,Cond,bool,BCond)),
-/*
-            unfold_int_expr(chk_nan(isNaN(as(A,Type)) or isNaN(as(B,Type)),
-                                as(1,bool),
-                                chk_nan(isInfinite(as(A,Type)),
-                                    isZero(as(B,Type)),
-                                    (isInfinite(as(B,Type)) and
-                                     isZero(as(A,Type))))),
-                            D,Cond,bool,BCond)),
-*/
         !,
         (BCond == 0 ->
             ensure_not_NaN((A,B,R))
@@ -7438,7 +7443,10 @@ unfold_real_expr(sqrt(EA),D,Cstr,RType,R) ?-
     real_type(RType,Type),
     !,
     insert_dep_inst(dep(R,D,[A])),
-    make_conj(CA,(ensure_not_NaN([A,R]),geq_real(Type,A,-0.0),sqrt_real(Type,A,R)),Cstr).
+    (Type == real ->
+        Z = 0.0
+    ;   Z = -0.0),
+    make_conj(CA,(ensure_not_NaN([A,R]),geq_real(Type,A,Z),sqrt_real(Type,A,R)),Cstr).
 
 unfold_real_expr(ln(EA),D,Cstr,RType,R) ?- !,
     ND is D + 1,
@@ -7494,6 +7502,65 @@ unfold_real_expr(fp_exp(EA),D,Cstr,Type,R) ?-
         make_conj(CNaN,CA,CNA),
         make_conj(CNA,fp_exp(NaN,Type,A,R),Cstr)).
 
+unfold_real_expr(range(EA,LA,HA),D,Cstr,Type,A) ?-
+    ND is D + 1,
+    Type = real,
+    unfold_real_expr(EA,ND,CA,real,A),
+    unfold_real_expr(LA,ND,CL,real,L),
+    unfold_real_expr(HA,ND,CH,real,H),
+    !,
+    real_vars(real,A),
+    insert_dep_inst(dep(A,D,[L,H])),
+    unfold_int_expr(((as(A,real) $>= as(L,real)) and
+                     (as(A,real) $=< as(H,real))),
+                    ND,CBool,bool,1),
+    make_conj(CA,CL,CAL),
+    make_conj(CH,CAL,Cstr0),
+    make_conj(CBool,Cstr0,Cstr).
+    
+unfold_real_expr(sin(EA),D,Cstr,RType,R) ?-
+    ND is D + 1,
+    unfold_real_expr(EA,ND,CA,RType,A),
+    Type = real,
+    !,
+    insert_dep_inst(dep(R,D,[A])),
+    make_conj(CA,sin_real(A,R),Cstr).
+unfold_real_expr(cos(EA),D,Cstr,RType,R) ?-
+    ND is D + 1,
+    unfold_real_expr(EA,ND,CA,RType,A),
+    Type = real,
+    !,
+    insert_dep_inst(dep(R,D,[A])),
+    make_conj(CA,cos_real(A,R),Cstr).
+unfold_real_expr(tan(EA),D,Cstr,RType,R) ?-
+    ND is D + 1,
+    unfold_real_expr(EA,ND,CA,RType,A),
+    Type = real,
+    !,
+    insert_dep_inst(dep(R,D,[A])),
+    make_conj(CA,tan_real(A,R),Cstr).
+unfold_real_expr(asin(EA),D,Cstr,RType,R) ?-
+    ND is D + 1,
+    unfold_real_expr(EA,ND,CA,RType,A),
+    Type = real,
+    !,
+    insert_dep_inst(dep(R,D,[A])),
+    make_conj(CA,asin_real(A,R),Cstr).
+unfold_real_expr(acos(EA),D,Cstr,RType,R) ?-
+    ND is D + 1,
+    unfold_real_expr(EA,ND,CA,RType,A),
+    Type = real,
+    !,
+    insert_dep_inst(dep(R,D,[A])),
+    make_conj(CA,acos_real(A,R),Cstr).
+unfold_real_expr(atan(EA),D,Cstr,RType,R) ?-
+    ND is D + 1,
+    unfold_real_expr(EA,ND,CA,RType,A),
+    Type = real,
+    !,
+    insert_dep_inst(dep(R,D,[A])),
+    make_conj(CA,atan_real(A,R),Cstr).
+
 unfold_real_expr(fp_min(EA,EB),D,Cstr,Type,R) ?- !,
     ND is D + 1,
     unfold_real_expr(EA,ND,CA,Type,A),
@@ -7593,6 +7660,40 @@ unfold_real_expr(ite(Cond,Then,Else),D,Cstr,RType,R) ?-
 unfold_real_expr(let(T,E),D,Cstr,Type,R) ?- !,
     unfold_let(real,T,E,D,true,Cstr,Type,R).
 
+unfold_real_expr(chk_nan(Cond,Then,Else),D,Cstr,Type,R) ?-
+    ND is D + 1,
+    unfold_int_expr(Cond,ND,CC,bool,RCond),
+    unfold_real_expr(Then,ND,CT,Type,RT),
+    unfold_real_expr(Else,ND,CE,Type,RE),
+    !,
+    int_vars(bool,RCond),
+    real_vars(real,R),
+    insert_dep_inst(dep(R,D,[RCond,RT,RE])),
+    insert_dep_inst(dep(RT,D,[RCond])),
+    insert_dep_inst(dep(RE,D,[RCond])),
+    (not_unify(RT,R) ->
+        blocked_unify(RCond,0),
+        blocked_unify(RE,R),
+        make_conj(CC,CE,Cstr)
+    ;   (not_unify(RE,R) ->
+            blocked_unify(RCond,1),
+            blocked_unify(RT,R),
+            make_conj(CC,CT,Cstr)
+        ;   ((RT == RE,
+              CT == true,
+              CE == true)
+            ->
+                % on ignore Cond
+                blocked_unify(R,RT),
+                Cstr = true
+            ;   (var(RCond) ->
+                    make_conj(CC,chk_nan_reif(RCond,(RT,CT),(RE,CE),R),Cstr)
+                ;   (RCond == 1 ->
+                        Cstr = CT,
+                        blocked_unify(R=RT)
+                    ;   Cstr = CE,
+                        blocked_unify(R=RE)))))).
+
 unfold_real_expr(uninterp(Term),D,Cstr,Type,R) ?- !,
     nonvar(Term),
     Term =.. [F|ArgsTypes],
@@ -7612,7 +7713,8 @@ unfold_real_expr(uninterp(Term),D,Cstr,Type,R) ?- !,
         ;   make_conj(IC,(SetType,AC),OC))),
     !,
     insert_dep_inst(dep(R,D,IArgs)),
-    make_conj(ACstrs,(real_vars(Type,R),uninterp_trigger(F,Types,Type,Trigger),uninterp(F,Trigger,Types,Type,IArgs,R)),Cstr).
+    make_conj(ACstrs,(real_vars(Type,R),uninterp_trigger(F,Types,Type,Trigger),
+                      uninterp(F,Trigger,Types,Type,IArgs,R)),Cstr).
     
 unfold_real_expr(Expr,_,_,_,_) :-
     spy_here,
@@ -9839,6 +9941,7 @@ uninterp(F,Trigger,TypeArgs,TypeR,Args,R) :-
                       check_diff_array(TE,R,CR)
                   ;   not_unify(R,CR)),
                   only_one_neq_args_pair(TypeArgs,Args,CArgs,TA,A,CA))
+                  %%TA \= array(_,_))
                 ->
                     call_priority(diff_reif(TA,_Kill,A,CA,1),2)
                 ;   true))
@@ -10009,6 +10112,7 @@ chk_undef_float_to_real(Bool,TypeF,A,R) :-
         ;   true)),
     (nonvar(Bool) ->
         (Bool == 0 ->
+            ensure_not_NaN(A),
             float_to_real(TypeF,A,R)
         ;   undef_float_to_real(TypeF,A,R))
     ;   save_cstr_suspensions(A),
@@ -10025,30 +10129,13 @@ chk_undef_float_to_real(Bool,TypeF,A,R) :-
 undef_float_to_real(Type,A,R) :-
     uninterp_trigger(float_to_real,[Type],real,Trigger),
     uninterp(float_to_real,Trigger,[Type],real,[A],R).
-/*
-undef_float_to_real(Type,A,R) :-
-    get_priority(Prio),
-    set_priority(1),
-    (ground(A) ->
-        (check_seen_expr(undef_float_to_real(Type,A),RR,Type) ->
-            protected_unify(R,RR)
-        ;   add_seen_expr(undef_float_to_real(Type,A),R,Type))
-    ;   save_cstr_suspensions(A),
-        get_saved_cstr_suspensions(LSusp),
-        ((member((Susp,undef_float_to_real(Type,AA,RR)),LSusp),
-          AA == A)
-        ->
-            protected_unify(R,RR)
-        ;   my_suspend(undef_float_to_real(Type,A,R),0,A->suspend:constrained))),
-    set_priority(Prio),
-    wake_if_other_scheduled(Prio).
-*/
 
 % A est le round(Rnd,EA)
 % on peut utiliser cast_real_int
 chk_undef_float_to_ubv(Bool,TypeF,Size,A,R) :-
     (nonvar(Bool) ->
         (Bool == 0 ->
+            ensure_not_NaN(A),
             cast_real_int(TypeF,A,SR),
             to_intNu(Size,SR,R)
         ;   set_lazy_domain(TypeF,A),
@@ -10068,25 +10155,6 @@ chk_undef_float_to_ubv(Bool,TypeF,Size,A,R) :-
 undef_float_to_ubv(Type,Size,A,R) :-
     uninterp_trigger(float_to_ubv,[Type],uint(Size),Trigger),
     uninterp(float_to_ubv,Trigger,[Type],uint(Size),[A],R).
-/*
-undef_float_to_ubv(Type,Size,A,R) :-
-    get_priority(Prio),
-    set_priority(1),
-    (ground(A) ->
-        (check_seen_expr(undef_float_to_ubv(Type,Size,A),RR,Type) ->
-            protected_unify(R,RR)
-        ;   add_seen_expr(undef_float_to_ubv(Type,Size,A),R,Type))
-    ;   save_cstr_suspensions(A),
-        get_saved_cstr_suspensions(LSusp),
-        ((member((Susp,undef_float_to_ubv(Type,Size,AA,RR)),LSusp),
-          AA == A)
-        ->
-            protected_unify(R,RR)
-        ;   my_suspend(undef_float_to_ubv(Type,Size,A,R),0,
-                       A->suspend:constrained))),
-    set_priority(Prio),
-    wake_if_other_scheduled(Prio).
-*/
 
 
 % A est le round(Rnd,EA)
@@ -10095,6 +10163,7 @@ undef_float_to_ubv(Type,Size,A,R) :-
 chk_undef_float_to_sbv(Bool,TypeF,Size,A,R) :-
     (nonvar(Bool) ->
         (Bool == 0 ->
+            ensure_not_NaN(A),
             cast_real_int(TypeF,A,SR),
             to_intNu(Size,SR,R)
         ;   set_lazy_domain(TypeF,A),
@@ -11592,6 +11661,8 @@ get_range(V,_,V,V).
    ;   (local reference(new_dep))).
 
 solve_cstrs :-
+    % la TRIGO peut désactiver le simplex
+    getval(use_simplex,US)@eclipse,
     garbage_collect,
     setval(nbFail,0)@eclipse,
     setval(ihm_stat,0)@eclipse,
@@ -11602,10 +11673,15 @@ solve_cstrs :-
     (DepConstraints \= [] ->
         clear_single_inst_cstr(DepConstraints,NDepConstraints),
         build_single_use_list(NDepConstraints,NSplitUseList),
-        once solve_cstrs_list([NSplitUseList]),
+        (solve_cstrs_list([NSplitUseList]) ->
+            setval(use_simplex,US)@eclipse
+        ;   setval(use_simplex,US)@eclipse,
+            fail),
         % Si on continue dans la ligne de requete
         init_dep_constraints(_NPC)
-    ;   true).
+    ;   true),
+    attached_suspensions(diff_array,LS),
+    (foreach(S,LS) do kill_suspension(S)).
 
 try_noNaN :-
     attached_suspensions(isNaN,LS),
@@ -11637,7 +11713,7 @@ solve_cstrs_list([UseList|SplitUseList]) :-
     (current_suspension(_) ->
         % filtrage 3B: on rogne les bords gauche et droit des feuilles
         % dans la limite du threshold (meme pour les entiers)
-        narrow_leaves(UseList),
+        %narrow_leaves(UseList),
         %reduce_lin_vars_bounds(UseList),
         init_last_var_fail,
         solve_cstrs2(UseList,[],0),
@@ -11961,8 +12037,8 @@ choose_fd_var([Adj|UseList],Var,Size,NUseList) :-
     MinVars \== [],
     leaf_vars([Adj|UseList],Leaves,NUseList),
     leaf_var_with_max_cstr_min_dom(MinVars,[],Var,Size).
-    %var_with_min_dom_max_cstr(MinVars,Var,Size).
-%%    leaf_var_with_max_cstr_min_dom(MinVars,Leaves,Var,Size).
+%%    var_with_min_dom_max_cstr(MinVars,Var,Size).
+%    leaf_var_with_max_cstr_min_dom(MinVars,Leaves,Var,Size).
 
 
 leaf_vars(UseList,Leaves,NUseList) :-
@@ -12086,6 +12162,7 @@ clean_uselist_var(V,C,Adj,UseList,NC,NAdj,NUseList) :-
 filter_not_box_constrained_vars([],[]).
 filter_not_box_constrained_vars([V|L],NL) :-
     ((no_constraint(V);
+      is_sin_cos_value(V);
       is_real_box(V))
     ->
         NL = ENL
@@ -12095,6 +12172,7 @@ filter_not_box_constrained_vars([V|L],NL) :-
 filter_constrained_vars([],[]).
 filter_constrained_vars([V|L],NL) :-
     ((no_constraint(V);
+      is_sin_cos_value(V);
       is_real_box_rat(V,_))
     ->
         NL = ENL
@@ -12224,15 +12302,15 @@ is_two_values_var(V) :-
 
 keep_choosable_vars([],_,[]).
 keep_choosable_vars([V|LV],DGVars,NLV) :-
-	((nonvar(V);
+    ((nonvar(V);
       is_real_box(V);
       get_type(V,T),
       T = array(_,_);
       not occurs(V,DGVars))
-	->
-		NLV = EndNLV
-	;	NLV = [V|EndNLV]),
-	keep_choosable_vars(LV,DGVars,EndNLV).
+    ->
+        NLV = EndNLV
+    ;   NLV = [V|EndNLV]),
+    keep_choosable_vars(LV,DGVars,EndNLV).
 
 
 add_adj_to_sufficient(Adj,NAdj,Sufficient,EndSufficient) :-
@@ -12415,66 +12493,70 @@ real_int_size(V,Size) :-
     sum_intervals_size_congr(ILIV,S,Mod,Size).
 
 var_with_max_cstr_min_dom([V|LV],Var,MinSize) :-
-    ((get_type(V,Type),
-      Type \= array(_,_))
-    ->
-        (LV == [] ->
-            Var = V,
-            dvar_size_check_real(Type,V,MinSize)
-        ;   dvar_size_check_real(Type,V,Size),
-            constraints_number(V,NbV),
-            var_with_max_cstr_min_dom1(LV,V,Size,NbV,Var,MinSize))
-    ;   var_with_max_cstr_min_dom(LV,Var,MinSize)).
+    (is_sin_cos_value(V) ->
+        var_with_max_cstr_min_dom(LV,Var,MinSize)
+    ;   ((get_type(V,Type),
+          Type \= array(_,_))
+        ->
+            (LV == [] ->
+                Var = V,
+                dvar_size_check_real(Type,V,MinSize)
+            ;   dvar_size_check_real(Type,V,Size),
+                constraints_number(V,NbV),
+                var_with_max_cstr_min_dom1(LV,V,Size,NbV,Var,MinSize))
+        ;   var_with_max_cstr_min_dom(LV,Var,MinSize))).
 
 var_with_max_cstr_min_dom1([],V,Size,_NbV,V,Size).
 var_with_max_cstr_min_dom1([VV|LV],IV,IS,INb,Var,MinSize) :-
     % plus de Array
-    get_type(VV,Type),
-    ((is_real_box(IV),
-      not is_real_box(VV))
-    ->
-        OV = VV,
-        dvar_size_check_real(Type,VV,OS),
-        constraints_number(VV,ONb)
-    ;   ((is_real_box(VV),
-          not is_real_box(IV))
+    (is_sin_cos_value(VV) ->
+        var_with_max_cstr_min_dom1(LV,IV,IS,INb,Var,MinSize)
+    ;   get_type(VV,Type),
+        ((is_real_box(IV),
+          not is_real_box(VV))
         ->
-            OV = IV,
-            OS = IS,
-            ONb = INb
-        ;   dvar_size_check_real(Type,VV,Size),
-            ((IS == 2,
-              Size > 2)
+            OV = VV,
+            dvar_size_check_real(Type,VV,OS),
+            constraints_number(VV,ONb)
+        ;   ((is_real_box(VV),
+              not is_real_box(IV))
             ->
-                % priorite aux booleens
+                OV = IV,
                 OS = IS,
-                ONb = INb,
-                OV = IV
-            ;   constraints_number(VV,NbVar),
-                ((IS > 2,
-                  Size == 2)
+                ONb = INb
+            ;   dvar_size_check_real(Type,VV,Size),
+                ((IS == 2,
+                  Size > 2)
                 ->
                     % priorite aux booleens
-                    ONb = NbVar,
-                    OS = Size,
-                    OV = VV
-                ;   (NbVar > INb ->
-                        OV = VV,
+                    OS = IS,
+                    ONb = INb,
+                    OV = IV
+                ;   constraints_number(VV,NbVar),
+                    ((IS > 2,
+                      Size == 2)
+                    ->
+                        % priorite aux booleens
                         ONb = NbVar,
-                        OS = Size
-                    ;   (NbVar < INb ->
-                            OV = IV,
-                            ONb = INb,
-                            OS = IS
-                        ;   % NbVar == INb
-                            (Size < IS ->
-                                OV = VV,
-                                ONb = NbVar,
-                                OS = Size
-                            ;   OV = IV,
+                        OS = Size,
+                        OV = VV
+                    ;   (NbVar > INb ->
+                            OV = VV,
+                            ONb = NbVar,
+                            OS = Size
+                        ;   (NbVar < INb ->
+                                OV = IV,
                                 ONb = INb,
-                                OS = IS))))))),
-    var_with_max_cstr_min_dom1(LV,OV,OS,ONb,Var,MinSize).
+                                OS = IS
+                            ;   % NbVar == INb
+                                (Size < IS ->
+                                    OV = VV,
+                                    ONb = NbVar,
+                                    OS = Size
+                                ;   OV = IV,
+                                    ONb = INb,
+                                    OS = IS))))))),
+        var_with_max_cstr_min_dom1(LV,OV,OS,ONb,Var,MinSize)).
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %%   VERSIONS ADAPTEES DES PREDICATS DE "Noyau/fd_solve.pl"
@@ -12597,11 +12679,14 @@ simple_resol_int(Int) :-
                          mfd:dvar_remove_element(Int,1),
                          simple_resol_int(Int)))
                 ;   simple_resol_int1(Int))
-            ;   (protected_unify(Int,0);
-                 mfd:dvar_remove_element(Int,0),
+
+            ;   Val = 0,
+                (protected_unify(Int,Val);
+                 mfd:dvar_remove_element(Int,Val),
                  simple_resol_int(Int))),
             1)
-    ;   true).
+        ;   true).
+
 
 simple_resol_int1(Int) :-
     (var(Int) ->
@@ -12755,36 +12840,36 @@ simple_resol_float(Var) :-
             (   mreal:set_typed_intervals(Var,Type,[Inter])
             ;   (once member_begin_end(Inter,IList,NIList,End,End)),
                 mreal:set_typed_intervals(Var,Type,NIList))
+        
         ;   % Un seul intervalle
             % ESSAI BM: on regarde d'abord le min puis le max
             % avant de piocher au hasard
             IList = [Min0..Max0],
             (Var = Min0 ;
+             Var = Max0 ;
              get_next_float(Type,Min0,Min1),
-             mreal:set_typed_intervals(Var,Type,[Min1..Max0]),
-             (Var = Max0 ;
-              get_previous_float(Type,Max0,Max1),
-              mreal:set_typed_intervals(Var,Type,[Min1..Max1]),
-              (nonvar(Var) ->
-                  true
-              ;   mreal:dvar_range(Var,Min,Max),
-                  (is_float_int_number(Var) ->
-                      % On reutilise le choix de la version entiere
-                      get_small_random_value_in_real_interval_float_int(Type,Min..Max,Value)
-                  ;   get_small_random_value_in_real_interval(Type,Min..Max,Size,Value)),
-                  random_less(2,Rand),
-                  % On essaye Value, puis au dessus/dessous de Value
-                  (   Var = Value
-                  ;   (Rand == 0 ->
-                          get_next_zfloat(Type,Value,Next),
-                          mreal:dvar_remove_smaller(Var,Next)
-                      ;   get_previous_zfloat(Type,Value,Prev),
-                          mreal:dvar_remove_greater(Var,Prev))
-                  ;   (Rand == 0 ->
-                          get_previous_zfloat(Type,Value,Prev),
-                          mreal:dvar_remove_greater(Var,Prev)
-                      ;   get_next_zfloat(Type,Value,Next),
-                          mreal:dvar_remove_smaller(Var,Next))))))),
+             get_previous_float(Type,Max0,Max1),
+             mreal:set_typed_intervals(Var,Type,[Min1..Max1])),
+            (nonvar(Var) ->
+                true
+            ;   mreal:dvar_range(Var,Min,Max),
+                (is_float_int_number(Var) ->
+                    % On reutilise le choix de la version entiere
+                    get_small_random_value_in_real_interval_float_int(Type,Min..Max,Value)
+                ;   get_small_random_value_in_real_interval(Type,Min..Max,Size,Value)),
+                random_less(2,Rand),
+                % On essaye Value, puis au dessus/dessous de Value
+                (   Var = Value
+                ;   (Rand == 0 ->
+                        get_next_zfloat(Type,Value,Next),
+                        mreal:dvar_remove_smaller(Var,Next)
+                    ;   get_previous_zfloat(Type,Value,Prev),
+                        mreal:dvar_remove_greater(Var,Prev))
+                ;   (Rand == 0 ->
+                        get_previous_zfloat(Type,Value,Prev),
+                        mreal:dvar_remove_greater(Var,Prev)
+                    ;   get_next_zfloat(Type,Value,Next),
+                        mreal:dvar_remove_smaller(Var,Next))))),
         my_notify_constrained(Var)
     ;   true).
 
@@ -12812,6 +12897,19 @@ simple_resol_real(Var) :-
     simple_resol_real_int(Var).
 */
 simple_resol_real(Var) :-
+    is_trigo_no_rat(Var),
+    mpis(_,_,Pi,OpPi,Pid2,OpPid2,Pid4,OpPid4,TPid4,OTPid4),
+    Choices = [OpPi,OpPid2,OTPid4,OpPid2,OpPid4,0.0,Pid4,Pid2,TPid4,Pi],
+    member(Val,Choices),
+    protected_unify(Var,Val). 
+simple_resol_real(Var) :-
+    (is_trigo_no_rat(Var) ->
+        mpis(_,_,Pi,OpPi,Pid2,OpPid2,Pid4,OpPid4,TPid4,OTPid4),
+        Choices = [OpPi,OpPid2,OTPid4,OpPid2,OpPid4,0.0,Pid4,Pid2,TPid4,Pi],
+        (foreach(Val,Choices),
+         param(Var) do
+            diff_real(real,Var,Val))
+    ;   true),
     (var(Var) ->
         mreal:get_intervals(Var,IList),
         (IList = [_,_|_] ->
@@ -12822,17 +12920,20 @@ simple_resol_real(Var) :-
                 mreal:set_typed_intervals(Var,real,NIList))
         ;   % Un seul intervalle real
             IList = [Min0..Max0],
+            (is_real_box(Var) ->
+                Rbox = 1
+            ;   true),
             ((is_float_number(Var),
-              not is_real_box(Var))
+              var(Rbox))
             ->
                 % ESSAI BM: on regarde d'abord le min puis le max
                 % avant de piocher au hasard
-                (Var = Min0 ;
+                (protected_unify(Var,Min0) ;
                  get_next_float(real,Min0,Min1),
                  (Min1 == 1.0Inf ->
                      launch_box(Var)
                  ;   mreal:set_typed_intervals(Var,real,[Min1..Max0]),
-                     (Var = Max0 ;
+                     (protected_unify(Var,Max0) ;
                       get_previous_float(real,Max0,Max1),
                       (Max1 == -1.0Inf ->
                           launch_box(Var)
@@ -12851,7 +12952,7 @@ simple_resol_real(Var) :-
                               get_previous_float(real,Value,PV)),
                           random_less(2,Rand),
                           % On essaye Value, puis au dessus/dessous de Value
-                          (   Var = Value
+                          (   protected_unify(Var,Value)
                           ;   (Rand == 0 ->
                                   set_typed_intervals(Var,real,[NV..1.0Inf])
                               ;   set_typed_intervals(Var,real,[-1.0Inf..PV]))
@@ -12860,7 +12961,8 @@ simple_resol_real(Var) :-
                               ;   set_typed_intervals(Var,real,[NV..1.0Inf])))))))
             ;   mreal:dvar_range(Var,Min,Max),
                 mreal:dvar_size(Var,Size),
-                (not (Size == 2,
+                (not (nonvar(Rbox);
+                      Size == 2,
                       (Min == -1.0Inf;
                        Max == 1.0Inf))
                 ->
@@ -12874,7 +12976,7 @@ simple_resol_real(Var) :-
                     random_less(2,Rand),
                     % On essaye Value, puis au dessus/dessous de Value
                     (   % echec is +/-Inf
-                        Var = Value
+                        protected_unify(Var,Value)
                     ;   (Rand == 0 ->
                             set_typed_intervals(Var,real,[NV..1.0Inf])
                         ;   set_typed_intervals(Var,real,[-1.0Inf..PV]))
@@ -12884,23 +12986,29 @@ simple_resol_real(Var) :-
 
                     ;   % on essaye les boites autour de Value
                         set_typed_intervals(Var,real,[PV..Value]),
-                        get_rand_rat_in_rbox(Var,PV,Value,Rat),
-                        (launch_box_rat(Var,Rat);
+                        (not is_trigo_no_rat(Var),
+                         get_rand_rat_in_rbox(Var,PV,Value,Rat),
+                         launch_box_rat(Var,Rat);
                          launch_box(Var))
                     ;   set_typed_intervals(Var,real,[Value..NV]),
-                        get_rand_rat_in_rbox(Var,Value,NV,Rat),
-                        (launch_box_rat(Var,Rat);
+                        (not is_trigo_no_rat(Var),
+                         get_rand_rat_in_rbox(Var,Value,NV,Rat),
+                         launch_box_rat(Var,Rat);
+                         % on boucle
                          launch_box(Var)))
-                ;   (is_real_box(Var) ->
+                ;   (nonvar(Rbox) ->
                         get_rand_rat_in_rbox(Var,Min,Max,Rat),
                         (launch_box_rat(Var,Rat);
-                         launch_box(Var))
+                         trigo_no_rat(Var),
+                         Ratfailed = 1)
                     ;   (Min == -1.0Inf ->
                             Value = Max
                         ;   Value = Min),
-                        (  Var = Value
+                        (  protected_unify(Var,Value)
                         ;  launch_box(Var)))))),
-        my_notify_constrained(Var)
+        (nonvar(Ratfailed) ->
+            true
+        ;   my_notify_constrained(Var))
     ;   true).
 
 simple_resol_real_int(Var) :-
@@ -13115,42 +13223,43 @@ inst_rnd(Enum) :-
     protected_unify(Enum,Enum0).
 
 inst_int(Int) :-
-	nonvar(Int),
-	!.
+    nonvar(Int),
+    !.
 inst_int(Int) :-
     dvar_intervals(int,Int,IList),
-	abs_min_interval(IList,Inter),
-	min_max_inter(Inter,L,H),
-	Size is 1 + H - L,
-	mod:get_congr(Int,C,Mod),
-	get_small_random_value_in_interval(Inter,Size,C,Mod,Int0),
+    abs_min_interval(IList,Inter),
+    min_max_inter(Inter,L,H),
+    Size is 1 + H - L,
+    mod:get_congr(Int,C,Mod),
+    get_small_random_value_in_interval(Inter,Size,C,Mod,Int0),
     protected_unify(Int,Int0).
 
 inst_real(Real) :-
-	nonvar(Real),
-	!.
+    (nonvar(Real);
+     is_real_box(Real)),
+    !.
 inst_real(Real) :-
-	dvar_intervals(real,Real,IList),
-	abs_min_interval(IList,Inter),
-	get_small_random_value_in_real_interval(real,Inter,_,Real0),
+    dvar_intervals(real,Real,IList),
+    abs_min_interval(IList,Inter),
+    get_small_random_value_in_real_interval(real,Inter,_,Real0),
     protected_unify(Real,Real0).
 
 inst_float_double(Real) :-
-	nonvar(Real),
-	!.
+    nonvar(Real),
+    !.
 inst_float_double(Real) :-
-	dvar_intervals(float_double,Real,IList),
-	abs_min_interval(IList,Inter),
-	get_small_random_value_in_real_interval(float_double,Inter,_,Real0),
+    dvar_intervals(float_double,Real,IList),
+    abs_min_interval(IList,Inter),
+    get_small_random_value_in_real_interval(float_double,Inter,_,Real0),
     protected_unify(Real,Real0).
 
 inst_float_simple(Real) :-
-	nonvar(Real),
-	!.
+    nonvar(Real),
+    !.
 inst_float_simple(Real) :-
-	dvar_intervals(float_simple,Real,IList),
-	abs_min_interval(IList,Inter),
-	get_small_random_value_in_real_interval(float_simple,Inter,_,Real0),
+    dvar_intervals(float_simple,Real,IList),
+    abs_min_interval(IList,Inter),
+    get_small_random_value_in_real_interval(float_simple,Inter,_,Real0),
     protected_unify(Real,Real0).
 
 
diff --git a/Src/COLIBRI/solve_util.pl b/Src/COLIBRI/solve_util.pl
index 4d1716db4..6e269a5f5 100755
--- a/Src/COLIBRI/solve_util.pl
+++ b/Src/COLIBRI/solve_util.pl
@@ -529,6 +529,9 @@ get_small_random_value_in_real_interval(Inter,Size,Res) :-
 	get_small_random_value_in_real_interval(Type,Inter,Size,Res).
 
 %%:- mode get_small_random_value_in_real_interval(++,++,++,?).
+get_small_random_value_in_real_interval(Type,LH..LH,_Size,Res) ?- !,
+    protected_unify(Res,LH).
+    
 get_small_random_value_in_real_interval(Type,Low..High,_Size,Res) :-
     Low =< 0.0,
     High >= 0.0,
diff --git a/Src/COLIBRI/trigo.pl b/Src/COLIBRI/trigo.pl
new file mode 100644
index 000000000..769f6b8ec
--- /dev/null
+++ b/Src/COLIBRI/trigo.pl
@@ -0,0 +1,1351 @@
+/*
+BUG sur:
+real_vars(real, (A, T, S, C)), tan_real(A, T), sin_real(A, S),
+ cos_real(A, C), A $: -1e-8 .. 0.0, A = -1e-8, solve_cstrs.
+-> fail
+Le pb vient de cos_real qui impose A = 0.0 ?
+le fact_periodic du cos doit rester pour tuer le sinr correspondant
+sinon le sinr_rec imposera 1 pour cos en forcant pi/2 pour NA 
+et donc 0 pour A !
+*/
+
+:- setval(bpis,1).
+:- export use_bpis/0.
+use_bpis :-
+    setval(bpis,1).
+:- export no_bpis/0.
+no_bpis :-
+    setval(bpis,0).
+:- local reference(pis).
+%:- import launch_box_prio/2 from colibr. 
+:- export mpis/8.
+mpis(DPi,OpDPi,Pi,OpPi,Pid2,OpPid2,Pid4,OpPid4,TPid4,OTPid4) :-
+    getval(pis,Pis),
+    (Pis == 0 ->
+        (getval(bpis,0)@colibri ->
+            DPi is 2.0*pi,
+            OpDPi is -DPi,
+            Pi is pi,
+            OpPi is -Pi,
+            Pid2 is Pi/2.0,
+            OpPid2 is -Pid2,
+            % pour sin(A)=cos(A)
+            Pid4 is Pi/4.0,
+            OPid4 is -Pid4,
+            % pour sin(-A)=cos(A)
+            TPid4 is 3*(Pi/4),
+            OTPid4 is -TPid4
+        ;   % on est trop précis avec des rbox !!!!
+            % 2pi
+            DPi0 is 2.0*pi,
+            get_next_float(real,DPi0,DPi1),
+            set_intervals(real,DPi,[DPi0..DPi1]),
+            launch_box_prio(DPi,_),
+            % -2pi
+            ODPi0 is -DPi0,
+            get_previous_float(real,ODPi0,ODPi1),
+            set_intervals(real,OpDPi,[ODPi1..ODPi0]),
+            launch_box_prio(OpDPi,_),
+            % pi
+            Pi0 is pi,
+            get_next_float(real,Pi0,Pi1),
+            set_intervals(real,Pi,[Pi0..Pi1]),
+            launch_box_prio(Pi,_),
+            % -pi
+            set_lazy_domain(real,OpPi),
+            op_real_interval(real,Pi,OpPi),
+            launch_box_prio(OpPi,_),
+            % pi/2
+            Pi0d2 is Pi0/2.0,
+            Pi1d2 is Pi1/2.0,
+            set_intervals(real,Pid2,[Pi0d2..Pi1d2]),
+            launch_box_prio(Pid2,_),
+            % -pi/2
+            set_lazy_domain(real,OpPid2),
+            op_real_interval(real,Pid2,OpPid2),
+            launch_box_prio(OpPid2,_),
+            % pi/4
+            Pi0d4 is Pi0d2/2.0,
+            Pi1d4 is Pi1d2/2.0,
+            set_intervals(real,Pid4,[Pi0d4..Pi1d4]),
+            launch_box_prio(Pid4,_),
+            % -pi/4
+            set_lazy_domain(real,OpPid4),
+            op_real_interval(real,Pid4,OpPid4),
+            launch_box_prio(OpPid4,_),
+            % 3pi/4
+            set_lazy_domain(real,TPid4),
+            set_intervals(real,TPid4,[2.3561944901923448 .. 2.3561944901923453]),
+            launch_box_prio(TPid4,_),
+            % -3pi/4
+            set_lazy_domain(real,OTPid4),
+            op_real_interval(real,TPid4,OTPid4),
+            launch_box_prio(OTPid4,_)),
+        setval(pis,(DPi,OpDPi,Pi,OpPi,Pid2,OpPid2,Pid4,OpPid4,TPid4,OTPid4))
+    ;   Pis = (DPi,OpDPi,Pi,OpPi,Pid2,OpPid2,Pid4,OpPid4,TPid4,OTPid4)).
+
+m2pi(DPi) :-
+    mpis(DPi0,_,_,_,_,_,_,_,_,_),
+    protected_unify(DPi0,DPi).
+mpi(Pi) :-
+    mpis(_,_,Pi0,_,_,_,_,_,_,_),
+    protected_unify(Pi0,Pi).
+moppi(OpPi) :-
+    mpis(_,_,_,OpPi0,_,_,_,_,_,_),
+    protected_unify(OpPi0,OpPi).
+mpid2(Pid2) :-
+    mpis(_,_,_,_,Pid20,_,_,_,_,_),
+    protected_unify(Pid20,Pid2).
+moppid2(OpPid2) :-
+    mpis(_,_,_,_,_,OpPid20,_,_,_,_),
+    protected_unify(OpPid20,OpPid2).
+mpid4(Pid4) :-
+    mpis(_,_,_,_,_,_,Pid40,_,_,_),
+    protected_unify(Pid40,Pid4).
+moppid4(OpPid4) :-
+    mpis(_,_,_,_,_,_,_,OpPid40,_,_),
+    protected_unify(OpPid40,OpPid4).
+mtpid4(TPid4) :-
+    mpis(_,_,_,_,_,_,_,_,TPid40,_),
+    protected_unify(TPid40,TPid4).
+moptpid4(OTPid4) :-
+    mpis(_,_,_,_,_,_,_,_,_,OTPid40),
+    protected_unify(OTPid40,OTPid4).
+
+:- export is_mis_mpi_var/4.
+is_mpi_var(V,PV,OPV,Name) :-
+    is_real_box(V),
+    mpis(DPi,OpDPi,Pi,OpPi,Pid2,OpPid2,Pid4,OpPid4,TPid4,OTPid4),
+    mreal:get_intervals(V,IV),
+    mreal:get_intervals(Pi,Ip),
+    (IV == Ip ->
+        Name = pi,
+        PV = Pi,
+        OPV = OpPi
+    ;   mreal:get_intervals(OpPi,Iop),
+        (IV == Iop ->
+            Name = -pi,
+            PV = OpPi,
+            OPV = Pi
+        ;   mreal:get_intervals(Pid2,Ipd2),
+            (IV == Ipd2 ->
+                Name = pi/2.0,
+                PV = Pid2,
+                OPV = OpPid2
+            ;   mreal:get_intervals(OpPid2,Iopd2),
+                (IV == Iopd2 ->
+                    Name = -pi/2.0,
+                    PV = OpPid2,
+                    OPV = Pid2
+                ;   mreal:get_intervals(DPi,Idp),
+                    (IV == Idp ->
+                        Name = 2.0*pi,
+                        PV = DPi,
+                        OPV = OpDPi
+                    ;   mreal:get_intervals(OpDPi,IOdp),
+                        (IV == IOdp ->
+                            Name = -2.0*pi,
+                            PV = OpDPi,
+                            OPV = DPi
+                        ;   mreal:get_intervals(Pid4,Ipd4),
+                            (IV == Ipd4 ->
+                                Name = pi/4.0,
+                                PV = Pid4,
+                                OPV = OpPid4
+                            ;   mreal:get_intervals(OpPid4,Iopd4),
+                                (IV == Iopd4 ->
+                                    Name = -pi/4.0,
+                                    PV = OpPid4,
+                                    OPV = Pid4
+                                ;   mreal:get_intervals(TPid4,Itpid4),
+                                    (IV == Itpid4 ->
+                                        Name = 3.0/4.0*pi,
+                                        PV = TPid4,
+                                        OPV = OTPid4
+                                    ;   mreal:get_intervals(OTPid4,Iotpid4),
+                                        Name = -3.0/4.0*pi,
+                                        IV == Iotpid4,
+                                        PV = OTPid4,
+                                        OPV = TPid4))))))))).
+
+% pour interdire d'instancier une variable trigo par un rat
+:- local reference(trigo_no_rat).
+:- export trigo_no_rat/1.
+trigo_no_rat(A) :-
+    var(A),
+    !,
+    getval(trigo_no_rat,L),
+    (L \== 0 ->
+        (occurs(A,L) ->
+            true
+        ;   setval(trigo_no_rat,[A|L]))
+    ;   setval(trigo_no_rat,[A])).
+trigo_no_rat(A).
+
+:- export is_trigo_no_rat/1.
+is_trigo_no_rat(A) :-
+    var(A),
+    getval(trigo_no_rat,L)@colibri,
+    occurs(A,L).
+
+% sinus real
+sin_real(A,Sin) :-
+    get_priority(P),
+    set_priority(1),
+    no_simplex,
+    (exists_fact_periodic(sin,A,_,Res) ->
+        % on a un autre sin sur A
+        % factorisation
+        protected_unify(Sin,Res)
+    ;   real_vars(real,A),
+        set_intervals(real,Sin,[-1.0 .. 1.0]),
+        % invariant
+        % sin(A+k2pi) = sin(A)
+        sin_cos_tan_period(sin,A,NA,K,Sin,Stop),
+        (var(Stop) ->
+            trigo_no_rat(Sin),
+            real_vars_have_same_sign(NA,Sin),
+            sinr0(NA,Sin)
+        ;   true)),
+    set_priority(P),
+    wake_if_other_scheduled(P).
+
+real_vars_have_same_sign(0.0,0.0) ?- !.
+real_vars_have_same_sign(A,B) :-
+    (((number(A) ->
+          A =\= 0.0
+      ;   true),
+      get_sign_real(A,SAB);
+      (number(B) ->
+          B =\= 0.0
+      ;   true),
+      get_sign_real(B,SAB))
+    ->
+        set_sign(real,A,SAB),
+        set_sign(real,B,SAB)
+    ;   suspensions(A,LS),
+        ((member(Susp,LS),
+          get_suspension_data(Susp,goal,real_vars_have_same_sign(AA,BB)),
+          (AA == A ->
+              BB == B
+          ;   AA == B,
+              BB == A))
+         ->
+            true
+        ;   my_suspend(real_vars_have_same_sign(A,B),0,(A,B)->suspend:constrained))).
+
+exists_fact_periodic(SCT,A,CNA,CRes) :-
+    get_cstr_suspensions(A,LS),
+    once (member(Susp,LS),
+          get_suspension_data(Susp,goal,fact_periodic(SCT,CA,CNA,CK,CKP,CRes)),
+          A == CA).
+        
+        
+sin_cos_tan_period(SCT,A,NA,K,Res,Stop) :-
+    trigo_no_rat(A),
+    trigo_no_rat(NA),
+    trigo_no_rat(KP),
+    trigo_no_rat(Res),
+    (((SCT == sin ->
+          inside_Pid2(A)
+      ;   SCT == cos,
+          inside_Pi(A)),
+      attached_suspensions(sin_val,LSusp),
+      member(Susp,LSusp),
+      get_suspension_data(Susp,goal,sin_cos_value(AA,Sin,Cos)),
+      once (Res == Sin;
+            Res == Cos),
+      (SCT == sin ->
+          inside_Pid2(AA)
+      ;   SCT == cos,
+          inside_Pi(AA)))
+    ->
+        protected_unify(A,AA),
+        protected_unify(A,NA),
+        protected_unify(K,0.0),
+        Stop = 1
+    ;   true),
+    (var(Stop) ->
+        set_lazy_domain(real,NA),
+        real_vars(real_int,K),
+        save_cstr_suspensions((A,NA,Res)),
+        get_saved_cstr_suspensions(LS),
+        (foreach((S,Goal),LS),
+         param(SCT,A,NA,K,Res,Stop) do
+            ((Goal = fact_periodic(CSCT,CA,CNA,CK,CKP,CRes),
+              (A == CA;
+               Res == CRes))
+            ->
+                ((A == CA,
+                  occurs(SCT,(sin,cos)),
+                  occurs(CSCT,(sin,cos)))
+                ->
+                    % on a un autre sin/cos sur A
+                    % meme periode, factorisation sur NA et K
+                    protected_unify(NA,CNA),
+                    protected_unify(K,CK),
+                    protected_unify(KP,CKP),
+                    (CSCT == SCT ->
+                        Stop = 1,
+                        protected_unify(Res,CRes)
+                    ;   true)
+                ;   ((SCT == tan,
+                      CSCT == SCT,
+                      (A == CA;
+                       Res == CRes))
+                    ->
+                        % tan,tan
+                        ((A == CA;
+                          (inside_Pid2(A),
+                           inside_Pid2(CA)))
+                        ->
+                            Stop = 1,
+                            protected_unify(A,CA),
+                            protected_unify(K,CK),
+                            protected_unify(K,0.0),
+                            protected_unify(Res,CRes)
+                        ;   protected_unify(NA,CNA),
+                            protected_unify(Res,CRes))
+                    ;   true))
+             ;   true))
+    ;   true),
+    (nonvar(Stop) ->
+        true
+    ;   real_vars(real,A),
+        real_vars(real_int,K),
+        set_lazy_domain(real,NA),
+        % periodicité: 
+        % sin et cos : sin(A+K*2pi) = sin(A)
+        % tan(A + pi) = tan(pi)
+        % pour forcer le plus grand K ?
+        mpis(DPi,_,Pi,OpPi,Pid2,OpPid2,_,_,_,_),
+        ((mreal:dvar_range(A,LA,HA),
+          (SCT \== tan ->
+              % sin, cos
+              VMin = OpPi,
+              VMax = Pi
+          ;   VMin = OpPid2,
+              VMax = Pid2),
+          mreal:dvar_range(VMax,_,Max),
+          mreal:dvar_range(VMin,Min,_),
+          LA >= Min,
+          HA =< Max)
+        ->
+            protected_unify(K,0.0),
+            protected_unify(KP,0.0),
+            protected_unify(A,NA),
+            (SCT == tan ->
+                true
+            ;   NStop = 1)
+        ;   true),
+        (nonvar(NStop) ->
+            true
+        ;   (SCT == tan ->
+                NMax = Pid2,
+                NOpMax = OpPid2,
+                set_lazy_domain(real,Res),
+                Period = Pi
+            ;   set_intervals(real,Res,[-1.0 .. 1.0]),
+                NMax = Pi,
+                NOpMax = OpPi,
+                Period = DPi),
+            launch_geq_real(real,NA,NOpMax),
+            launch_geq_real(real,NMax,NA),
+            mult_real(real,K,Period,KP),
+            add_real(real,NA,KP,A),
+            fact_periodic(SCT,A,NA,K,KP,Res))).
+
+
+/*
+fact_periodic(SCT,A,NA,K,KP,Res) :-
+    SCT == sin,
+    once (K == 0.0;
+          KP == 0.0),
+    !,
+    call_priority((protected_unify(A,NA),
+                   protected_unify(K,0.0),
+                   protected_unify(KP,0.0)),
+                  1).
+*/
+fact_periodic(SCT,A,NA,K,KP,Res) :-
+    get_priority(P),
+    set_priority(1),
+    trigo_no_rat(A),
+    trigo_no_rat(NA),
+    trigo_no_rat(KP),
+    trigo_no_rat(Res),
+    ((SCT == sin,
+      (A \== 0.0,
+       get_sign_real(A,SA);
+       NA \== 0.0,
+       get_sign_real(NA,SA);
+       Res \== 0.0,
+       get_sign_real(Res,SA)))
+    ->
+        set_sign(real,A,SA),
+        set_sign(real,NA,SA),
+        set_sign(real,Res,SA)
+    ;   true),
+    ((mreal:dvar_range(A,LA,HA),
+      mpis(_,_,Pi,OpPi,Pid2,OpPid2,_,_,_,_),
+      (SCT \== tan ->
+          % sin, cos
+          VMin = OpPi,
+          VMax = Pi
+      ;   VMin = OpPid2,
+          VMax = Pid2),
+      mreal:dvar_range(VMax,_,Max),
+      mreal:dvar_range(VMin,Min,_),
+      LA >= Min,
+      HA =< Max)
+    ->
+        protected_unify(K,0.0)
+    ;   true),
+    (K == 0.0 ->
+        protected_unify(A,NA),
+        protected_unify(KP,0.0)
+    ;   true),
+    ((SCT == tan; % trace pour atan
+      var(A),  % trace pour sin/cos si pas de sin_cos_value
+      not is_real_box(A))
+    ->
+        periodic_not_accurate(SCT,A,Res,Stop),
+        (nonvar(Stop) ->
+            protected_unify(K,0.0),
+            protected_unify(KP,0.0)
+        ;   Continue = 1),
+        (nonvar(Continue) ->
+            (exists_fact_periodic(SCT,A,CNA,CRes) ->
+                protected_unify(Res,CRes),
+                protected_unify(NA,CNA)
+            ;   my_suspend(fact_periodic(SCT,A,NA,K,KP,Res),0,(A,NA,K,KP,Res)->
+                              suspend:constrained))
+        ;   true)
+    ;   true),
+    set_priority(P),
+    wake_if_other_scheduled(P).
+
+
+periodic_not_accurate(cos,A,Cos,Stop) ?- !,
+    % imprécision de cos
+    mreal:dvar_range(A,L,H),
+    ((L >= -1e-8,
+      H =< 1e-8)
+    ->
+        Stop = 1,
+        get_previous_float(real,1.0,L1),
+        get_next_float(real,1.0,H1),
+        set_intervals(real,Cos,[L1..H1])
+    ;   true).
+periodic_not_accurate(_,_,_,_Stop).
+
+sinr0(A,Sin) :-
+    % si A : -p1..0 -> sin(A) = -sin(-A)
+    % si A : 0..pi -> sin(A) = -sin(-A)
+    sinr(A,Sin).
+sinr(0.0,Sin) ?- !,
+    protected_unify(Sin,0.0).
+sinr(A,0.0) ?- !,
+    (A == 0.0 ->
+        true
+    ;   mreal:dvar_range(A,LA,HA),
+        mpis(_,_,Pi,OpPi,_,_,_,_,_,_),
+        mreal:get_intervals(Pi,IAp),
+        mreal:get_intervals(OpPi,IAn),
+        append(IAn,IAp,IA),
+        (exists_diff_Rel(A,0.0) -> 
+            set_intervals(real,A,IA),
+            %int_vars(bool,Bool),
+            set_intervals(int,Bool,[0,1]),
+            insert_dep_inst(inst_cstr(0,Bool)),
+            isNegative(real,A,Bool),
+            chk_nan_reif(Bool,(OpPi,true),(Pi,true),A)
+        ;   set_intervals(real,A,[0.0|IA]),
+            %int_vars(bool,Bool),
+            set_intervals(int,Bool,[0,1]),
+            insert_dep_inst(inst_cstr(0,Bool)),
+            isZero(real,A,Bool),
+            chk_nan_reif(Bool,
+                         (0.0,true),
+                         (A,
+                          (%int_vars(bool,Bool1),
+                           set_intervals(int,Bool1,[0,1]),
+                           insert_dep_inst(inst_cstr(0,Bool1)),
+                           isNegative(real,A,Bool1),
+                           chk_nan_reif(Bool1,(OpPi,true),(Pi,true),A))),
+                         A))).
+sinr(A,1.0) ?- !,
+    Pid2 is mpid2,
+    %mreal:get_intervals(Pid2,IA),
+    %set_intervals(real,A,IA).
+    protected_unify(A,Pid2).
+sinr(A,-1.0) ?- !,
+    OpPid2 is moppid2,
+    %mreal:get_intervals(OpPid2,IA),
+    %set_intervals(real,A,IA).
+    protected_unify(A,OpPid2).
+sinr(A,Sin) :- 
+    (number(A),
+     RA = A;
+     is_real_box_rat(A,RA)),
+    !,
+    sin_cos_val(RA,Sin,_).
+sinr(A,Sin) :-
+    is_real_box(A),
+    mpis(_,_,Pi,OpPi,Pid2,OpPid2,Pid4,_,TPid4,OpTPid4),
+    mreal:get_intervals(A,IA),
+    mreal:get_intervals(Pi,IPi),
+    mreal:get_intervals(OpPi,IOpPi),
+    ((IA == IPi,
+      NA = Pi;
+      IA == IOpPi,
+      NA = OpPi)
+    ->
+        !,
+        protected_unify(A,NA),
+        protected_unify(Sin,0.0)
+    ;   mreal:get_intervals(Pid2,IPid2),
+        (IA == IPid2 ->
+            !,
+            protected_unify(A,Pid2),
+            protected_unify(Sin,1.0)
+        ;   mreal:get_intervals(OpPid2,IOpPid2),
+            (IA == IOpPid2 ->
+                !,
+                protected_unify(A,OpPid2),
+                protected_unify(Sin,-1.0)
+            ;   mreal:get_intervals(Pid4,IPid4),
+                (IA == IPid4 ->
+                    !,
+                    sin_cos_val(A,Sin,Sin)
+                ;   mreal:get_intervals(OpTPid4,IOTPd4),
+                    IA == IOTPd4,
+                    !,
+                    sin_cos_val(A,Sin,Sin))))).
+sinr(A,Sin) :-
+    get_priority(P),
+    set_priority(1),
+    save_cstr_suspensions((A,Sin)),
+    ((get_sign_real(A,SA);
+      get_sign_real(Sin,SA))
+    ->
+        set_sign(real,A,SA),
+        set_sign(real,Sin,SA),
+        (SA == pos ->
+            % 0 .. A .. pi
+            mpi(Pi),
+            geq_real(real,A,0.0),
+            geq_real(real,Pi,A)
+        ;   % neg: -pi .. A .. 0
+            moppi(OpPi),
+            geq_real(real,A,OpPi),
+            geq_real(real,0.0,A))
+    ;   true),
+    (A == Sin ->
+        set_intervals(real,A,[-2.1498999999999986e-8..2.1498999999999986e-8])
+    ;   true),
+    (inside_Pid2(A) ->
+        InPid2 = 1
+    ;   true),
+    (nonvar(InPid2) ->
+        attached_suspensions(sin_val,LS),
+        ((member(SV,LS),
+          get_suspension_data(SV,goal,sin_cos_value(AA0,SA0,_)),
+          Sin == SA0,
+          inside_Pid2(AA0))
+        ->
+            protected_unify(A,AA0)
+        ;   true)
+    ;   true),
+    get_saved_cstr_suspensions(LSusp),
+    (foreach((S,Goal),LSusp),
+     param(A,Sin,InPid2,SeqC) do
+        ((Goal = sinr(AA,SA),
+          (A == AA;
+           nonvar(InPid2),
+           inside_Pid2(AA),
+           Sin == SA))
+        ->
+            % factorisation
+            kill_suspension(S),
+            protected_unify(A,AA),
+            protected_unify(Sin,SA)
+        ;   ((Goal = cosr(AA,Cos),
+              Cos == Sin)
+            ->
+                ((A == AA,
+                  get_sign_real(A,pos))
+                ->
+                    % A pos
+                    SeqC = 1,
+                    mpid4(Pid4),
+                    protected_unify(A,Pid4)
+                ;   ((get_sign_real(A,neg),
+                      is_op_real(real,A,OpA),
+                      AA == OpA)
+                    ->
+                        % A neg: -3*pi/4
+                        SeqC = 1,
+                        moptpid4(OpTPid4),
+                        protected_unify(A,OpTPid4)
+                    ;   true))
+            ;   true))),
+    (nonvar(SeqC) ->
+        trigo_no_rat(A),
+        protected_unify(Sin,Cos),
+        sin_cos_val(A,Sin,Cos)
+    ;   sinr_rec(A,Sin),
+        sin_cos_ineqs(sin,A,Sin),
+        (number(A) ->
+            sin_cos_val(A,Sin,Cos)
+        ;   my_suspend(sinr(A,Sin),5,(A,Sin)->suspend:constrained))),
+    set_priority(P),
+    wake_if_other_scheduled(P).
+
+inside_Pid2(Var) :-
+    mpid2(Pid2),
+    mreal:dvar_range(Pid2,_,H),
+    OpH is -H,
+    mreal:dvar_range(Var,LA,HA),
+    OpH =< LA,
+    H >= HA.
+inside_Pi(Var) :-
+    mpi(Pi),
+    mreal:dvar_range(Pi,_,H),
+    OpH is -H,
+    mreal:dvar_range(Var,LA,HA),
+    OpH =< LA,
+    H >= HA.
+
+%sin_cos_ineqs(_,A,B) ?- !.
+
+sin_cos_ineqs(sin,A,A) ?- !. % deja traite
+sin_cos_ineqs(sin,A,Sin) :-
+    % A = Sin sur -2.1498999999999986e-8 .. 2.1498999999999986e-8
+    mreal:dvar_range(A,LA,HA),
+    % sur 0..pid2 -> 0..1, Rel = >=
+    % sur pid2..pi -> 1..0, Rel = >
+    % donc 0+..pi -> Rel = > (= autour de 0)
+    
+    % sur -pi..-pid2 -> 0..-1, Rel = <
+    % sur -pid2..0 -> -1..0, Rel = =<
+    % donc -pi..-0 -> Rel = < (= autour de 0)
+    
+    (LA >= 0.0 ->
+        (LA > 2.1498999999999986e-8 ->
+            Rel = '>'
+        ;   Rel = '>='),
+        launch_real_ineq(Rel,real,A,Sin)
+    ;   (HA =< 0.0 ->
+            (HA < -2.1498999999999986e-8 ->
+                Rel = '<'
+            ;   Rel = '=<'),
+            launch_real_ineq(Rel,real,A,Sin)
+        ;   true)).
+sin_cos_ineqs(cos,A,A) ?- !. % deja traite
+sin_cos_ineqs(cos,A,Cos) :-
+    % on est sur 0..pi
+    % A = Cos sur 0.73908513321516056 .. 0.73908513321516067
+    % sur pi/2..pi, décroissant -> 0..-1 Cos < A, Rel = '>'
+    % sur 0..pi/2 -> 1..0, 
+    %   Rel = '=<' jusqu'a 0.73908513321516067, '>=' après
+    mreal:dvar_range(A,LA,HA),
+    Pid2 is pi/2.0,
+    (LA >= Pid2 ->
+        launch_real_ineq(>=,real,A,Cos)
+    ;   (HA =< Pid2 ->
+            (HA =< 0.73908513321516067 ->
+                launch_real_ineq(>=,real,Cos,A)
+            ;   (LA >= 0.73908513321516067 ->
+                    launch_real_ineq(>=,real,A,Cos)
+                ;   true))
+        ;   true)).
+                    
+sin_cos_val(Val,Sin,Cos) :-
+    get_priority(P),
+    set_priority(1),
+    sin_cos_val0(Val,Sin,Cos),
+    set_priority(P),
+    wake_if_other_scheduled(P).
+
+sin_cos_val0(0.0,Sin,Cos) ?- !,
+    protected_unify(Sin,0.0),
+    protected_unify(Cos,1.0).
+sin_cos_val0(Val,Sin,Cos) :-
+    nonvar(Val),
+    mpis(_,_,Pi,OpPi,Pid2,OpPid2,_,_,_,_),
+    mreal:get_intervals(Pi,Ip),
+    mreal:get_intervals(OpPi,Iop),
+    ((mreal:in_interval(Ip,Val);
+      mreal:in_interval(Iop,Val))
+    ->
+        !,
+        protected_unify(Sin,0.0),
+        protected_unify(Cos,-1.0)
+    ;   mreal:get_intervals(Pid2,Ipd2),
+        (mreal:in_interval(Ipd2,Val) ->
+            !,
+            protected_unify(Sin,1.0),
+            protected_unify(Cos,0.0)
+        ;   mreal:get_intervals(OpPid2,Iopd2),
+            mreal:in_interval(Iopd2,Val),
+            !,
+            protected_unify(Sin,-1.0),
+            protected_unify(Cos,0.0))).
+sin_cos_val0(A,Sin,Cos) :-
+    attached_suspensions(sin_val,LS),
+    ((member(Susp,LS),
+      get_suspension_data(Susp,goal,sin_cos_value(AA,SA,CA)),
+      A == AA)
+    ->
+        protected_unify(Sin,SA),
+        protected_unify(Cos,CA)
+    ;   real_vars(real,(VS,VC)),
+        set_intervals(real,VS,[-1.0 .. 1.0]),
+        set_intervals(real,VC,[-1.0 .. 1.0]),
+        ((is_real_box(A),
+          Sin == Cos)
+        ->
+            sin_cos_pid4(Sin),
+            protected_unify(Sin,VS),
+            protected_unify(VS,VC)
+        ;   sin(A,S),
+            get_previous_float(real,S,PS),
+            get_next_float(real,S,NS),
+            set_intervals(real,VS,[PS..NS]),
+            protected_unify(Sin,VS),
+            (A == S ->
+                % A <> 0, imprécision de sin autour de 0
+                launch_box_prio(Sin,_)
+            ;   true),
+            cos(A,C),
+            get_previous_float(real,C,PC),
+            get_next_float(real,C,NC),
+            set_intervals(real,VC,[PC..NC]),
+            protected_unify(Cos,VC)),
+        trigo_no_rat(A),
+        trigo_no_rat(VS),
+        trigo_no_rat(VC),
+        sin_cos_value(A,VS,VC)).
+
+sin_cos_pid4(SC) :-
+    % +/-sqrt(2)/2
+    (get_sign_real(SC,neg) ->
+        ISC = [-0.70710678118654757 .. -0.70710678118654746]
+    ;   ISC = [0.70710678118654746 .. 0.70710678118654757]),
+    set_intervals(real,SC,ISC),
+    trigo_no_rat(SC),
+    launch_box_prio(SC,_).
+
+sin_cos_value(A,VS,VC) :-
+    mreal:dvar_range(VS,LS,HS),
+    (get_next_float(real,LS,HS) ->
+        launch_box_prio(VS,_)
+    ;   true),
+    mreal:dvar_range(VC,LC,HC),
+    (get_next_float(real,LC,HC) ->
+        launch_box_prio(VC,_)
+    ;   true),
+    my_suspend(sin_cos_value(A,VS,VC),0,[(A,VS,VC)->suspend:constrained,trigger(sin_val)]).
+
+    
+is_sin_cos_value(Var) :-
+    is_real_box(Var),
+    mpis(DPi,OpDPi,Pi,OpPi,Pid2,OpPid2,Pid4,OpPid4,TPid4,OTPid4),
+    mreal:get_intervals(Var,IV),
+    mreal:get_intervals(DPi,Idp),
+    mreal:get_intervals(OpDPi,Iodp),
+    mreal:get_intervals(Pi,Ip),
+    mreal:get_intervals(OpPi,Iop),
+    mreal:get_intervals(Pid2,Ipd2),
+    mreal:get_intervals(OpPid2,Iopd2),
+    mreal:get_intervals(Pid4,Ipd4),
+    mreal:get_intervals(OpPid4,Iopd4),
+    mreal:get_intervals(TPid4,Itpd4),
+    mreal:get_intervals(OTPid4,Iotpd4),
+    (member(IV,[Idp,Iodp,Ip,Iop,Ipd2,Iopd2,Ipd4,Iopd4,Itpd4,Iotpd4]) ->
+        true
+    ;   is_trigo_no_rat(Var)).
+
+
+sin_val_min(0.0,Res) ?- !,
+    Res = 0.0.
+sin_val_min(A,Res) :-
+    abs(A,AA),
+    (AA =:= pi ->
+        Res = 0.0
+    ;   (A =:= pi/2 ->
+            Res = 1.0
+        ;   (A =:= -pi/2 ->
+                Res = -1.0
+            ;   sin(A,S),
+                get_previous_float(real,S,Res)))).
+sin_val_max(0.0,Res) ?- !,
+    Res = 0.0.
+sin_val_max(A,Res) :-
+    abs(A,AA),
+    (AA =:= pi ->
+        Res = 0.0
+    ;   (A =:= pi/2 ->
+            Res = 1.0
+        ;   (A =:= -pi/2 ->
+                Res = -1.0
+            ;   sin(A,S),
+                get_next_float(real,S,Res)))).
+
+asin_val_min(A,Min) :-
+    asin(A,S),
+    get_previous_float(real,S,Min).
+asin_val_max(A,Max) :-
+    asin(A,S),
+    get_next_float(real,S,Max).
+
+sinr_rec(A,Sin) :-
+    Pid2 is pi/2.0,
+    OpPid2 is - Pid2,
+    sinr_rec0(A,Pid2,OpPid2,Sin).
+
+sinr_rec0(A,Pid2,OpPid2,Sin) :-
+    mreal:get_intervals(A,As),
+    mreal:get_intervals(Sin,Sins),
+    sin_intervals(As,Pid2,OpPid2,Sins0),
+    (is_real_box(Sin) ->
+        list_to_intervals(real,Sins0,IS0),
+        check_intervals_intersection(IS0,Sins)
+    ;   set_intervals(real,Sin,Sins0)),
+    mreal:get_intervals(Sin,NSins),
+    
+    asin_intervals0(NSins,As1),
+    (is_real_box(A)->
+        list_to_intervals(real,As1,IAs1),
+        check_intervals_intersection(IAs1,As)
+    ;   set_intervals(real,A,As1)),
+    mreal:get_intervals(A,NAs),
+    ((As == NAs,
+      Sins == NSins)
+    ->
+        true
+    ;   sinr_rec0(A,Pid2,OpPid2,Sin)).
+
+sin_intervals(LI,NLI) :-
+    Pid2 is mpid2,
+    OpPid2 is - Pid2,
+    sin_intervals(LI,Pid2,OpPid2,NLI).
+
+sin_intervals([],_,_,[]).
+sin_intervals([I|LI],Pid2,OpPid2,NewLI) :-
+    min_max_inter(I,L,H),
+    (L < OpPid2 ->
+        (H =< OpPid2 ->
+            % -pi..-pi/2 on est décroissant
+            sin_val_max(L,NH),
+            sin_val_min(H,NL),
+            NLI = LI,
+            NewLI = [NL..NH|ENewLI]
+        ;   (H =< 0.0 ->
+                % -pi..0 -> -pi..-pi/2 U -pi/2..0
+                NLI = [L..OpPid2,OpPid2..H|LI],
+                NewLI = ENewLI
+            ;   (H =< pi/2 ->
+                    % -pi..pi/2 -> -pi..-pi/2 U -pi/2..pi/2
+                    NLI = [L..OpPid2,OpPid2..H|LI],
+                    NewLI = ENewLI
+                ;   % -pi..pi -> -pi..-pi/2 U -pi/2..pi/2 U pi/2..pi
+                    NLI = [L..OpPid2,OpPid2..Pid2, Pid2..H|LI],
+                    NewLI = ENewLI)))
+    ;   % L >= OpPid2 
+        (H =< Pid2 ->
+            % -pi/2..pi/2 on est croissant
+            sin_val_min(L,NL),
+            sin_val_max(H,NH),
+            NLI = LI,
+            NewLI = [NL..NH|ENewLI]
+        ;   (L >= Pid2 ->
+                % pi/2..pi on est décroissant
+                sin_val_max(L,NH),
+                sin_val_min(H,NL),
+                NLI = LI,
+                NewLI = [NL..NH|ENewLI]
+            ;   % -pi/2..pi -> 0..pi/2 U pi/2..pi
+                NLI = [L..Pid2,Pid2..H|LI],
+                NewLI = ENewLI))),
+    sin_intervals(NLI,Pid2,OpPid2,ENewLI).
+
+asin_intervals0([],[]).
+asin_intervals0([I|LI],NLI) :-
+    Pid2 is pi/2,
+    Pi is pi,
+    min_max_inter(I,L,H),
+    (H =< 0.0 ->
+        % on est dans -1 .. 0 donc asin dans -pi/2 .. 0 U -pi .. -pi/2
+        % [asin(L)..asin(H)] U [-pi-asin(H) .. -pi/2-asin(L)]
+        asin_val_min(L,AL),
+        asin_val_max(H,AH),
+        % AL..AH dans -pi/2 ..0, symétrie autour de -pi/2
+        NAH0 is -Pi - AL,
+        NAL0 is -Pi - AH,
+        get_previous_float(real,NAL0,NAL),
+        get_next_float(real,NAH0,NAH),
+        append([AL..AH,NAL..NAH],ENLI,NLI),
+        asin_intervals0(LI,ENLI)
+    ;   (L >= 0.0 ->
+            % [asin(L)..asin(H)] U [pi-asin(H) .. pi-asin(L)]
+            asin_val_min(L,AL),
+            asin_val_max(H,AH),
+            NAH1 is Pi - AL,
+            NAL1 is Pi - AH,
+            get_previous_float(real,NAL1,NAL),
+            get_next_float(real,NAH1,NAH),
+            append([AL..AH,NAL..NAH],ENLI,NLI),
+            asin_intervals0(LI,ENLI)
+        ;   asin_intervals0([L..0.0,0.0..H|LI],NLI))).
+            
+
+cosr(0.0,Cos) ?- !,
+    protected_unify(Cos,1.0).
+cosr(A,0.0) ?- !,
+    mpis(_,_,_,_,Pid2,OpPid2,_,_,_,_),
+    mreal:get_intervals(Pid2,I1),
+    mreal:get_intervals(OpPid2,I2),
+    append(I2,I1,IA),
+    set_intervals(real,A,IA),
+    %int_vars(bool,Bool),
+    set_intervals(int,Bool,[0,1]),
+    insert_dep_inst(inst_cstr(0,Bool)),
+    isNegative(real,A,Bool),
+    chk_nan_reif(Bool,(OpPid2,true),(Pid2,true),A).
+
+cosr(A,1.0) ?- !,
+    protected_unify(A,0.0).
+cosr(A,-1.0) ?- !,
+    mpis(_,_,Pi,OpPi,_,_,_,_,_,_),
+    mreal:get_intervals(Pi,I1),
+    mreal:get_intervals(OpPi,I2),
+    append(I2,I1,IA),
+    set_intervals(real,A,IA),
+    %int_vars(bool,Bool),
+    set_intervals(int,Bool,[0,1]),
+    insert_dep_inst(inst_cstr(0,Bool)),
+    isNegative(real,A,Bool),
+    chk_nan_reif(Bool,(OpPi,true),(Pi,true),A).
+
+cosr(A,Cos) :- 
+    (number(A),
+     RA = A;
+     is_real_box_rat(A,RA)),
+    !,
+    sin_cos_val(RA,_,Cos).
+cosr(A,Cos) :-
+    is_real_box(A),
+    mpis(_,_,Pi,OpPi,Pid2,OpPid2,_,_,_,_),
+    mreal:get_intervals(A,IA),
+    mreal:get_intervals(Pid2,IPid2),
+    mreal:get_intervals(OpPid2,IOpPid2),
+    ((IA == IPid2,
+      NA = Pid2;
+      IA == IOpPid2,
+      NA = OpPid2)
+    ->
+        !,
+        protected_unify(A,NA),
+        protected_unify(Cos,0.0)
+    ;   mreal:get_intervals(Pi,IPi),
+        mreal:get_intervals(OpPi,IOpPi),
+        once (IA == IPi,
+              NA = Pi;
+              IA == IOpPi,
+              NA = OpPi),
+        !,
+        protected_unify(A,NA),
+        protected_unify(Cos,-1.0)).
+cosr(A,Cos) :-
+    get_priority(P),
+    set_priority(1),
+    % cos(-A) = cos(A), passage dans 0..pi
+    (get_sign_real(A,SA) ->
+        % si fail on passe aux cas suivants
+        set_priority(P),
+        SA == neg,
+        !,
+        op_real(real,A,OpA),
+        trigo_no_rat(A),
+        trigo_no_rat(OpA),
+        cosr(OpA,Cos)
+    ;   !,
+        save_cstr_suspensions(A),
+        get_saved_cstr_suspensions(LSusp),
+        ((member((Susp,cosr(AA,CC)),LSusp),
+          A == AA)
+        ->
+            set_priority(P),
+            protected_unify(Cos,CC)
+        ;   %int_vars(bool,Bool),
+            set_intervals(int,Bool,[0,1]),
+            insert_dep_inst(inst_cstr(0,Bool)),
+            % pour forcer le signe, pos en priorite au labeling
+            isNegative(real,A,Bool),
+            (nonvar(Bool) ->
+                set_priority(P),
+                (Bool == 0 ->
+                    % pos
+                    set_sign(real,A,pos)
+                ;   % neg
+                    set_sign(real,A,neg)),
+                cosr(A,Cos)
+            ;   set_priority(P),
+                my_suspend(cosr(A,Cos),3,(A,Cos,Bool)->suspend:constrained)))).
+cosr(A,Cos) :-
+    get_priority(P),
+    set_priority(1),
+    save_cstr_suspensions((A,Cos)),
+    get_saved_cstr_suspensions(LSusp),
+    % 0 .. A .. pi,
+    % si A =< pi/2 alors Cos >= 0
+    % sinon Cos =< 0
+    mpid2(Pid2),
+    (get_sign_real(Cos,SC) ->
+        % A pos
+        (SC == neg ->
+            % pi/2 .. A .. pi
+            launch_geq_real(real,A,Pid2)
+        ;   % pos: 0 .. A .. pi/2
+            launch_geq_real(real,Pid2,A))
+    ;   true),
+    (exists_diff_Rel(Cos,0.0) ->
+        launch_diff_real(real,A,Pid2)
+    ;   true),
+    (A == Cos ->
+        set_intervals(real,A,[0.73908513321516056 .. 0.73908513321516067])
+    ;   true),
+    % si on a un sin_cos_value(AA,SS,Cos) avec A et AA pos
+    % on peut factoriser !!!
+    attached_suspensions(sin_val,LS),
+    ((member(S,LS),
+      get_suspension_data(S,goal,sin_cos_value(AA,SS,CC)),
+      get_sign_real(AA,pos),
+      CC == Cos)
+    ->
+        Stop = 1,
+        protected_unify(A,AA)
+    ;   (foreach((S,Goal),LSusp),
+         param(A,Cos,SeqC,Stop) do
+            ((Goal = cosr(AA,CA),
+              (A == AA;
+               var(Cos),
+               % entre 0 et pi c'est bon
+               Cos == CA))
+            ->
+                % factorisation
+                kill_suspension(S),
+                protected_unify(A,AA),
+                protected_unify(Cos,CA)
+            ;   ((Goal = sinr(AA,Sin),
+                  Cos == Sin)
+                ->
+                    (A == AA ->
+                        % A pos
+                        SeqC = 1,
+                        mpid4(Pid4),
+                        protected_unify(A,Pid4)
+                    ;   ((get_sign_real(AA,neg),
+                          is_op_real(real,A,OpA),
+                          AA == OpA)
+                        ->
+                            % AA neg donc A: 3*pi/4
+                            SeqC = 1,
+                            mtpid4(TPid4),
+                            protected_unify(A,TPid4)
+                        ;   true))
+                ;   ((Goal = sin_cos_value(AA,SA,CA),
+                      SA == CA,
+                      (A == AA;
+                       is_mpi_var(A,PosA,NegA,_),
+                       AA == NegA))
+                    ->
+                        Stop = 1,
+                        protected_unify(Cos,CA)
+                    ;   true))))),
+    (nonvar(Stop) ->
+        true
+    ;   (nonvar(SeqC) ->
+            trigo_no_rat(A),
+            protected_unify(Sin,Cos),
+            sin_cos_val(A,Sin,Cos)
+        ;   cosr_rec(A,Cos),
+            sin_cos_ineqs(cos,A,Cos),
+            (number(A) ->
+                sin_cos_val(A,Sin,Cos)
+            ;   my_suspend(cosr(A,Cos),5,(A,Cos)->suspend:constrained)))),
+    set_priority(P),
+    wake_if_other_scheduled(P).
+
+cos_val_min(0.0,Res) ?- !,
+    Res = 1.0.
+cos_val_min(A,Res) :-
+    abs(A,AA),
+    (AA =:= pi ->
+        Res = -1.0
+    ;   (AA =:= pi/2 ->
+            Res = 0.0
+        ;   cos(A,S),
+            get_previous_float(real,S,Res))).
+cos_val_max(0.0,Res) ?- !,
+    Res = 1.0.
+cos_val_max(A,Res) :-
+    abs(A,AA),
+    (AA =:= pi ->
+        Res = -1.0
+    ;   (AA =:= pi/2 ->
+            Res = 0.0
+        ;   cos(A,S),
+            get_next_float(real,S,Res))).
+
+acos_val_min(A,Min) :-
+    acos(A,S),
+    get_previous_float(real,S,Min).
+acos_val_max(A,Max) :-
+    acos(A,S),
+    get_next_float(real,S,Max).
+
+cosr_rec(A,Cos) :-
+    mreal:get_intervals(A,As),
+    mreal:get_intervals(Cos,Coss),
+    
+    cos_intervals(As,Coss0),
+    (is_real_box(Cos) ->
+        list_to_intervals(real,Coss0,IC),
+        check_intervals_intersection(IC,Coss)
+    ;   set_intervals(real,Cos,Coss0)),
+    mreal:get_intervals(Cos,NCoss),
+    
+    inv_acos_intervals(NCoss,Ac1),
+    (is_real_box(A) ->
+        list_to_intervals(real,Ac1,IA1),
+        check_intervals_intersection(IA1,As)
+    ;   set_intervals(real,A,Ac1)),
+    mreal:get_intervals(A,NAs),
+    ((As == NAs,
+      Coss == NCoss)
+    ->
+        true
+    ;   cosr_rec(A,Cos)).
+
+% on est dans 0..pi: cos décroissant
+cos_intervals([],[]).
+cos_intervals([I|LI],NLI) :-
+    min_max_inter(I,L,H),
+    cos_val_max(L,NH),
+    cos_val_min(H,NL),
+    NLI = [NL..NH|ENLI],
+    cos_intervals(LI,ENLI).
+
+% on vient de 0..pi et on est dans -1..1
+% décroissant sur 0 .. pi
+inv_acos_intervals([],[]).
+inv_acos_intervals([I|LI],NLI) :-
+    min_max_inter(I,L,H),
+    acos_val_min(H,NL),
+    acos_val_max(L,NH),
+    NLI = [NL..NH|ENLI],
+    inv_acos_intervals(LI,ENLI).
+
+
+cos_real(A,Cos) :-
+    get_priority(P),
+    set_priority(1),
+    no_simplex,
+    (exists_fact_periodic(cos,A,_,Res) ->
+        % on a un autre cos sur A
+        % factorisation
+        protected_unify(Cos,Res)
+    ;   real_vars(real,A),
+        set_intervals(real,Cos,[-1.0 .. 1.0]),
+        sin_cos_tan_period(cos,A,NA,_,Cos,Stop),
+        (var(Stop) ->
+            trigo_no_rat(Cos),
+            cosr(NA,Cos)
+        ;   true)),
+    set_priority(P),
+    wake_if_other_scheduled(P).
+
+tan_real(A,Tan) :-
+    (exists_fact_periodic(tan,A,_,Res) ->
+        protected_unify(Tan,Res)
+    ;   real_vars(real,(A,Tan)),
+        trigo_no_rat(A),
+        trigo_no_rat(Tan),
+
+        cos_real(A,Cos),
+        ((exists_diff_Rel(Cos,0.0),
+          exists_diff_Rel(Tan,0.0))
+        ->
+            launch_diff_real(real,A,0.0)
+        ;   true),
+
+        ((number(Tan),
+          exists_diff_Rel(Cos,0.0),
+          occurs(Tan,(-1.0,0.0,1.0)))
+        ->
+            (Tan == -1.0 ->
+                Goal = (op_real(real,Sin,OpSin),protected_unify(OpSin,Cos),sin_real(A,Sin))
+            ;   (Tan == 0.0 ->
+                    Goal = (protected_unify(Sin,0.0),sin_real(A,Sin))
+                ;   % Tan == 1.0
+                    Goal = (protected_unify(Sin,Cos),sin_real(A,Sin)))),
+            call(Goal)
+        ;   set_intervals(int,Bool,[0,1]),
+            (as(Cos,real) $= as(0.0,real)) #= as(Bool,bool),
+            tan_real(Bool,A,Cos,Tan))).
+
+tan_real(1,A,_,Tan) ?- !,
+    as(Tan,real) $= as(uninterp(tan(as(A,real))),real).
+tan_real(0,A,Cos,Tan) ?- !,
+    get_priority(P),
+    set_priority(1),
+    ((number(Tan),
+      exists_diff_Rel(Cos,0.0),
+      occurs(Tan,(-1.0,0.0,1.0)))
+    ->
+        (Tan == -1.0 ->
+            Goal = (op_real(real,Sin,OpSin),protected_unify(OpSin,Cos),sin_real(A,Sin))
+        ;   (Tan == 0.0 ->
+                Goal = (protected_unify(Sin,0.0),sin_real(A,Sin))
+            ;   % Tan == 1.0
+                Goal = (protected_unify(Sin,Cos),sin_real(A,Sin)))),
+        call(Goal)
+    ;   sin_cos_tan_period(tan,A,NA,K,Tan,Stop),
+        (nonvar(Stop) ->
+            true
+        ;   (A == Tan ->
+                protected_unify(NA,0.0)
+            ;   sin_real(NA,Sin),
+                cos_real(NA,Cos),
+                div_real(real,Sin,Cos,Tan)))),
+    set_priority(P),
+    wake_if_other_scheduled(P).
+tan_real(Bool,A,Cos,Tan) :-
+    my_suspend(tan_real(Bool,A,Cos,Tan),0,Bool->suspend:inst).
+
+
+% Versions naives de asin/acos/atan
+% pas définies partout danger !!!
+asin_real(Sin,A) :-
+    real_vars(real,(Sin,A)),
+    set_intervals(int,B,[0,1]),
+    insert_dep_inst(inst_cstr(0,B)),
+    ((as(Sin,real) $< as(-1.0,real)) or 
+     (as(Sin,real) $> as(1.0,real))) #=
+    not(as(B,bool)),
+    asin_real(B,Sin,A).
+asin_real(0,Sin,A) ?- !,
+    as(Sin,real) $= uninterp(asin(as(A,real))).
+asin_real(1,Sin,A) ?- !,
+    trigo_no_rat(A),
+    trigo_no_rat(Sin),
+    % inversible vers -pi/2..pi/2
+    mpid2(Pid2),
+    mreal:dvar_range(Pid2,_,Max),
+    Min is - Max,
+    set_intervals(real,A,[Min..Max]),
+    asin_intervals(Sin,A),
+    sin_real(A,Sin).
+asin_real(B,Sin,A) :-
+    my_suspend(asin_real(B,Sin,A),0,B->my_suspend:inst).
+
+asin_intervals(Sin,A) :-
+    mreal:get_intervals(Sin,ISs),
+    asin_intervals0(ISs,IAs),
+    set_intervals(real,A,IAs).
+
+
+acos_real(Cos,A) :-
+    real_vars(real,(Cos,A)),
+    set_intervals(int,B,[0,1]),
+    insert_dep_inst(inst_cstr(0,B)),
+    ((as(Cos,real) $< as(-1.0,real)) or 
+     (as(Cos,real) $> as(1.0,real))) #=
+    not(as(B,bool)),
+    acos_real(B,Cos,A).
+
+acos_real(0,Cos,A) ?- !,
+    as(Cos,real) $= uninterp(acos(as(A,real))).
+acos_real(1,Cos,A) ?- !,
+    get_priority(P),
+    set_priority(1),
+    trigo_no_rat(A),
+    trigo_no_rat(Cos),
+    % inversible vers 0..pi
+    mpi(Pi),
+    launch_geq_real(real,A,0.0),
+    launch_geq_real(real,Pi,A),
+    acos_intervals(Cos,A),
+    % si on a un cosr/sin_cos_value sur Cos avec
+    % un AA dans 0..pi alors A = AA
+    get_cstr_suspensions(Cos,LS),
+    ((member(S,LS),
+      get_suspension_data(S,goal,G),
+      (G = cosr(_,AA,CC);
+       G = cosr(AA,CC)),
+      Cos == CC,
+      inside_0Pi(AA))
+    ->
+        protected_unify(A,AA)
+    ;   attached_suspensions(sin_val,NLS),
+        ((member(NS,NLS),
+          get_suspension_data(NS,goal,sin_cos_value(AA,_,CC)),
+          Cos == CC,
+          inside_0Pi(AA))
+        ->
+            protected_unify(A,AA)
+        ;   cos_real(A,Cos))),
+    set_priority(P),
+    wake_if_other_scheduled(P).
+acos_real(B,Cos,A) :-
+    my_suspend(acos_real(B,Cos,A),0,B->my_suspend:inst).
+
+inside_0Pi(V) :-
+    mpi(Pi),
+    mreal:dvar_range(V,L,H),
+    mreal:dvar_range(Pi,_,PM),
+    0.0 =< L,
+    PM >= H.
+
+acos_intervals(Cos,A) :-
+    mreal:get_intervals(Cos,ICs),
+    inv_acos_intervals(ICs,PIAs),
+    op_real_intervals(real,PIAs,0.0,[],NIAs),
+    append(NIAs,PIAs,IAs),
+    set_intervals(real,A,IAs).
+
+
+atan_real(Tan,A) :-
+    real_vars(real,(Tan,A)),
+    trigo_no_rat(Tan),
+    trigo_no_rat(A),
+    % inversible vers ]-pi/2..pi/2[
+    ((get_sign_real(Tan,S);
+      get_sign_real(A,S))
+    ->
+        set_sign(real,Tan,S),
+        set_sign(real,A,S)
+    ;   true),
+    moppid2(OpPid2),
+    mpid2(Pid2),
+    gt_real(real,A,OpPid2),
+    gt_real(real,Pid2,A),
+    atan_intervals(Tan,A),
+    tan_real(A,Tan).
+
+atan_intervals(Tan,A) :-
+    mreal:get_intervals(Tan,ITs),
+    (foreach(IT,ITs),
+     foreach(IA,IAs) do
+        (IT = L..H ->
+            atan(L,L0),
+            atan(H,H0)
+        ;   atan(IT,L0),
+            H0 = L0),
+        get_previous_float(real,L0,LA),
+        get_next_float(real,H0,HA),
+        IA = LA..HA),
+    set_intervals(real,A,IAs).
\ No newline at end of file
-- 
GitLab