diff --git a/doc/value/biblio.bib b/doc/value/biblio.bib
index afdbbf9218d7537cce903dde676973f4b123dbb2..d284b32a7af847422825480741062ef8d5d0dc05 100644
--- a/doc/value/biblio.bib
+++ b/doc/value/biblio.bib
@@ -115,3 +115,22 @@
   biburl    = {https://dblp.org/rec/bib/conf/sas/2018},
   bibsource = {dblp computer science bibliography, https://dblp.org}
 }
+
+
+@article{trace-partitioning,
+ author = {Rival, Xavier and Mauborgne, Laurent},
+ title = {The Trace Partitioning Abstract Domain},
+ journal = {ACM Trans. Program. Lang. Syst.},
+ issue_date = {August 2007},
+ volume = {29},
+ number = {5},
+ month = aug,
+ year = {2007},
+ issn = {0164-0925},
+ articleno = {26},
+ url = {http://doi.acm.org/10.1145/1275497.1275501},
+ doi = {10.1145/1275497.1275501},
+ acmid = {1275501},
+ publisher = {ACM},
+ address = {New York, NY, USA},
+} 
\ No newline at end of file
diff --git a/doc/value/examples/parametrizing/loop-unroll-const.c b/doc/value/examples/parametrizing/loop-unroll-const.c
index dad47c0b39970db177d8da0990f340547869be78..58211a63ed4c9ea947771b863c9489941549e173 100644
--- a/doc/value/examples/parametrizing/loop-unroll-const.c
+++ b/doc/value/examples/parametrizing/loop-unroll-const.c
@@ -1,5 +1,6 @@
 #define NROWS 10
-void main(void) {
+void main(void)
+{
   int a[NROWS][20] = {0};
   //@ loop unroll NROWS;
   for (int i = 0; i < 10; i++) {
diff --git a/doc/value/examples/parametrizing/loop-unroll-const.log b/doc/value/examples/parametrizing/loop-unroll-const.log
index 9071ef760702f7c63c8f525a0d9db24cc1a7fcec..4e1d575004122744df61587538cab466b0959b29 100644
--- a/doc/value/examples/parametrizing/loop-unroll-const.log
+++ b/doc/value/examples/parametrizing/loop-unroll-const.log
@@ -4,8 +4,8 @@
 [eva] Initial state computed
 [eva:initial-state] Values of globals at initialization
   
-[eva] loop-unroll-const.c:7: Trace partitioning superposing up to 100 states
-[eva] loop-unroll-const.c:7: Trace partitioning superposing up to 200 states
+[eva] loop-unroll-const.c:8: Trace partitioning superposing up to 100 states
+[eva] loop-unroll-const.c:8: Trace partitioning superposing up to 200 states
 [eva] done for function main
 [eva] ====== VALUES COMPUTED ======
 [eva:final-states] Values at end of function main:
diff --git a/doc/value/examples/parametrizing/loop-unroll-insuf.c b/doc/value/examples/parametrizing/loop-unroll-insuf.c
index 5058c9d40465278fcd2384a68c20b8ac5145ec31..f977bfe31f574efdb9f5a13ca0b3b2f9f14f06c2 100644
--- a/doc/value/examples/parametrizing/loop-unroll-insuf.c
+++ b/doc/value/examples/parametrizing/loop-unroll-insuf.c
@@ -1,4 +1,5 @@
-void main() {
+void main()
+{
   //@ loop unroll 20; // should be 21
   for (int i = 0 ; i <= 20 ; i ++) {
   }
diff --git a/doc/value/examples/parametrizing/loop-unroll-insuf.log b/doc/value/examples/parametrizing/loop-unroll-insuf.log
index 7527748a566d26ddc05c101e38be93f36658b2bf..6478cadfa123687fb56495c0684d673d42724499 100644
--- a/doc/value/examples/parametrizing/loop-unroll-insuf.log
+++ b/doc/value/examples/parametrizing/loop-unroll-insuf.log
@@ -4,8 +4,8 @@
 [eva] Initial state computed
 [eva:initial-state] Values of globals at initialization
   
-[eva:loop-unroll] loop-unroll-insuf.c:3: loop not completely unrolled
-[eva] loop-unroll-insuf.c:3: starting to merge loop iterations
+[eva:loop-unroll] loop-unroll-insuf.c:4: loop not completely unrolled
+[eva] loop-unroll-insuf.c:4: starting to merge loop iterations
 [eva] done for function main
 [eva] ====== VALUES COMPUTED ======
 [eva:final-states] Values at end of function main:
diff --git a/doc/value/examples/parametrizing/loop-unroll-nested.c b/doc/value/examples/parametrizing/loop-unroll-nested.c
index 7205a6d088a5e2cc53311f6117d8da4de7c159a9..62a61e7ad9e6836bcfec553030ef97988abf2119 100644
--- a/doc/value/examples/parametrizing/loop-unroll-nested.c
+++ b/doc/value/examples/parametrizing/loop-unroll-nested.c
@@ -1,11 +1,12 @@
 int t1[] = {1, 2, 3}, t2[] = {4, 5}, t3[] = {6, 7, 8, 9};
 int *t[] = {t1, t2, t3};
 int sizes[] = {3, 2, 4};
-void main(void) {
+void main(void)
+{
   int S = 0;
-  // loop unroll 3;
+  //@ loop unroll 3;
   for (int i = 0 ; i < 3 ; i++) {
-    // loop unroll sizes[i];
+    //@ loop unroll sizes[i];
     for (int j = 0 ; j < sizes[i] ; j++) {
       S += t[i][j];
     }
diff --git a/doc/value/examples/parametrizing/loop-unroll-nested.log b/doc/value/examples/parametrizing/loop-unroll-nested.log
index 5ff936dc9484d1016ed2a8f7f0350ff2732fa92d..d126c7d04246aba236742011e2b0e36f8f4d23e0 100644
--- a/doc/value/examples/parametrizing/loop-unroll-nested.log
+++ b/doc/value/examples/parametrizing/loop-unroll-nested.log
@@ -18,16 +18,10 @@
   sizes[0] ∈ {3}
        [1] ∈ {2}
        [2] ∈ {4}
-[eva] loop-unroll-nested.c:9: starting to merge loop iterations
-[eva:alarm] loop-unroll-nested.c:10: Warning: 
-  signed overflow. assert S + *(t[i] + j) ≤ 2147483647;
-[eva] loop-unroll-nested.c:7: starting to merge loop iterations
-[eva:alarm] loop-unroll-nested.c:10: Warning: 
-  out of bounds read. assert \valid_read(t[i] + j);
 [eva] done for function main
 [eva] ====== VALUES COMPUTED ======
 [eva:final-states] Values at end of function main:
-  S ∈ [0..2147483647]
+  S ∈ {45}
 [eva:summary] ====== ANALYSIS SUMMARY ======
   ----------------------------------------------------------------------------
   1 function analyzed (out of 1): 100% coverage.
@@ -35,9 +29,7 @@
   ----------------------------------------------------------------------------
   No errors or warnings raised during the analysis.
   ----------------------------------------------------------------------------
-  2 alarms generated by the analysis:
-       1 invalid memory access
-       1 integer overflow
+  0 alarms generated by the analysis.
   ----------------------------------------------------------------------------
   No logical properties have been reached by the analysis.
   ----------------------------------------------------------------------------
diff --git a/doc/value/examples/parametrizing/makefile b/doc/value/examples/parametrizing/makefile
index 74f6d633930c2a34e7dc807cd156f262ef801a0c..e2be7e2a93403c33937fceab58817dc1557785be 100644
--- a/doc/value/examples/parametrizing/makefile
+++ b/doc/value/examples/parametrizing/makefile
@@ -17,7 +17,9 @@ TARGETS = \
   ilevel.2.log \
 	loop-unroll-const.log \
 	loop-unroll-nested.log \
-	loop-unroll-insuf.log
+	loop-unroll-insuf.log \
+	split-array.log \
+	split-fabs.log
 
 .SECONDEXPANSION:
 .PHONY: all clean
@@ -38,6 +40,7 @@ context-depth.3.log: FCFLAGS += -context-width 1 -context-depth 1 -context-valid
 slevel.1.log: FCFLAGS += -slevel 55
 slevel.2.log: FCFLAGS += -slevel 28
 ilevel.2.log: FCFLAGS += -val-ilevel 16
+split-fabs.log: FCFLAGS += -eva-equality-domain
 
 nor.1.log nor.2.log: nor.c
 	time --format "\nuser time: %Us" $(FRAMAC) $(FCFLAGS) -val $< > $@ 2>&1
diff --git a/doc/value/examples/parametrizing/split-array.c b/doc/value/examples/parametrizing/split-array.c
new file mode 100644
index 0000000000000000000000000000000000000000..66c9037a253b117befc28cc21ac3cc5f86929128
--- /dev/null
+++ b/doc/value/examples/parametrizing/split-array.c
@@ -0,0 +1,14 @@
+int t1[] = {1, 2, 3}, t2[] = {4, 5}, t3[] = {6, 7, 8, 9};
+int *t[] = {t1, t2, t3};
+int sizes[] = {3, 2, 4};
+/*@ requires 0 <= i < 3; */
+int main(int i)
+{
+  int S = 0;
+  //@ split i;
+  //@ loop unroll sizes[i];
+  for (int j = 0 ; j < sizes[i] ; j++)
+    S += t[i][j];
+
+  return S;
+}
diff --git a/doc/value/examples/parametrizing/split-array.log b/doc/value/examples/parametrizing/split-array.log
new file mode 100644
index 0000000000000000000000000000000000000000..53a9ddd932748d851458163c1c4c9e1f4d461370
--- /dev/null
+++ b/doc/value/examples/parametrizing/split-array.log
@@ -0,0 +1,37 @@
+[kernel] Parsing split-array.c (with preprocessing)
+[eva] Analyzing a complete application starting at main
+[eva] Computing initial state
+[eva] Initial state computed
+[eva:initial-state] Values of globals at initialization
+  t1[0] ∈ {1}
+    [1] ∈ {2}
+    [2] ∈ {3}
+  t2[0] ∈ {4}
+    [1] ∈ {5}
+  t3[0] ∈ {6}
+    [1] ∈ {7}
+    [2] ∈ {8}
+    [3] ∈ {9}
+  t[0] ∈ {{ &t1[0] }}
+   [1] ∈ {{ &t2[0] }}
+   [2] ∈ {{ &t3[0] }}
+  sizes[0] ∈ {3}
+       [1] ∈ {2}
+       [2] ∈ {4}
+[eva:alarm] split-array.c:4: Warning: 
+  function main: precondition got status unknown.
+[eva] done for function main
+[eva] ====== VALUES COMPUTED ======
+[eva:final-states] Values at end of function main:
+  S ∈ {6; 9; 30}
+[eva:summary] ====== ANALYSIS SUMMARY ======
+  ----------------------------------------------------------------------------
+  1 function analyzed (out of 1): 100% coverage.
+  In this function, 9 statements reached (out of 9): 100% coverage.
+  ----------------------------------------------------------------------------
+  No errors or warnings raised during the analysis.
+  ----------------------------------------------------------------------------
+  0 alarms generated by the analysis.
+  ----------------------------------------------------------------------------
+  No logical properties have been reached by the analysis.
+  ----------------------------------------------------------------------------
diff --git a/doc/value/examples/parametrizing/split-fabs.c b/doc/value/examples/parametrizing/split-fabs.c
new file mode 100644
index 0000000000000000000000000000000000000000..92b25ba9fcb2dd4513927136f07bee1c96e52169
--- /dev/null
+++ b/doc/value/examples/parametrizing/split-fabs.c
@@ -0,0 +1,13 @@
+double fabs(double x)
+{
+  return x < 0.0 ? -x : x;
+}
+
+double main(double y)
+{
+  //@ split y < 0.0;
+  if (fabs(y) > 1.0)
+    y = y < 0 ? -1.0 : 1.0;
+  //@ merge y < 0.0;
+  return y;
+}
diff --git a/doc/value/examples/parametrizing/split-fabs.log b/doc/value/examples/parametrizing/split-fabs.log
new file mode 100644
index 0000000000000000000000000000000000000000..130b40492718c8d7d8fe39fff39e56c159223f92
--- /dev/null
+++ b/doc/value/examples/parametrizing/split-fabs.log
@@ -0,0 +1,23 @@
+[kernel] Parsing split-fabs.c (with preprocessing)
+[eva] Analyzing a complete application starting at main
+[eva] Computing initial state
+[eva] Initial state computed
+[eva:initial-state] Values of globals at initialization
+  
+[eva] done for function main
+[eva] ====== VALUES COMPUTED ======
+[eva:final-states] Values at end of function fabs:
+  
+[eva:final-states] Values at end of function main:
+  y ∈ [-1. .. 1.]
+[eva:summary] ====== ANALYSIS SUMMARY ======
+  ----------------------------------------------------------------------------
+  2 functions analyzed (out of 2): 100% coverage.
+  In these functions, 12 statements reached (out of 12): 100% coverage.
+  ----------------------------------------------------------------------------
+  No errors or warnings raised during the analysis.
+  ----------------------------------------------------------------------------
+  0 alarms generated by the analysis.
+  ----------------------------------------------------------------------------
+  No logical properties have been reached by the analysis.
+  ----------------------------------------------------------------------------
diff --git a/doc/value/main.tex b/doc/value/main.tex
index 62fb14dd0f03505ef305f334c8781dc024a46d4c..d9e502263777808b0cd5635c41e1b98737f6887f 100644
--- a/doc/value/main.tex
+++ b/doc/value/main.tex
@@ -2658,6 +2658,7 @@ Section \ref{command-line} presents the general usage options of \Eva{} in the
 command-line.
 The options described in section \ref{context} are correctness options,
 while the remaining sections (\ref{boucles-traitement},
+\ref{trace-partitioning},
 \ref{controlling-approximations} and \ref{sec:eva}) deal with performance
 tuning options. Section \ref{nonterm} presents a derived analysis to
 obtain information about non-termination.
@@ -3711,6 +3712,118 @@ line~7, by an invariant, that remains to be proven.
 %% less precisely.
 
 
+\section{Improving precision with reasoning by case}
+\label{trace-partitioning}
+
+Some formal proofs about programs require to use \emph{reasoning by cases}. \Eva can
+perform such reasonings through the use of the \emph{Trace Partitioning}
+\cite{trace-partitioning} techniques. These can be enabled manually or
+automatically. It is important to note that, whatever the method used, the
+partitioning and thus the reasoning by case stops at the end of a function
+and can only be extended past the function return if there is enough
+\lstinline|slevel| in the calling function.
+
+
+\subsection{Automatic partitioning on conditional structures}
+
+It sometimes happens that the cases we want to reason on are exactly the
+cases distinguished in the program in an \lstinline|if-then-else| or a
+\lstinline|switch| not far above.  even if these blocks are already closed
+at the point we need the reasoning by cases. Unless enough
+\lstinline|slevel| is available, the cases of a conditional structures are
+approximated together as soon as the analyzer leaves the block. \Eva can delay
+this approximation until after the statement where the reasoning
+by cases is needed.
+
+The global command-line parameter \lstinline|-eva-partition-history <n>|
+will delay the approximation for all conditional structures of the whole
+program. It takes a parameter \lstinline|<n>| which allow to control the delay.
+It represents the number of junction points for which we keep the incoming
+path (the cases) separated. A value of $1$ means that \Eva will reason by
+case on the previous \lstinline|if-then-else| until another
+\lstinline|if-then-else| is closed.
+
+This option has a very high cost on the analysis, theoretically increasing the
+analysis time by 2 for $n = 1$, and doubling each time $n$ is increased by $1$.
+The cost can even be higher if there are \lstinline|switch| instructions in the
+program. However, it can remove false alarms in a fully automatic way. Thus,
+the trade off might often be worth trying.
+
+Choosing a value for \lstinline|<n>| strictly greater than 1 is often not
+needed.
+
+
+\subsection{Manual partitioning on values}
+
+The reasoning by case can be forced inside a function by using \lstinline|split|
+annotations. These annotations must be given an expression which values
+correspond to the cases being enumerated. The example below show a usage
+of this annotation.
+
+\lstinputlisting{examples/parametrizing/split-array.c}
+
+The \lstinline|split| requires that the analyzer enumerate all the 3 possible
+values for \lstinline|i| and conduct a specialized analysis of the function for
+each of these values. Thereafter, the value of \lstinline|i| is always
+evalutated by \Eva{} as a singleton and it enables the use of a
+\lstinline|loop unroll| annotation on \lstinline|i|. This way, the result of
+the function can be exactly computed as the set of three possible value instead
+of an imprecise interval.
+
+\lstinputlisting[linerange={25-26}]
+  {examples/parametrizing/split-array.log}
+
+The \lstinline|split| can be any expression that evaluate to a {\it small}
+number of integer values. In particular, it can be C comparisons like in
+the following example.
+
+\lstinputlisting{examples/parametrizing/split-fabs.c}
+
+To be analyzed properly, the equality domain must be activated with the option
+\lstinline|-eva-equality-domain| (see section \ref{sec:symbolic-equalities})
+as we need the equality relations between the input and the output of the
+function \lstinline|fabs|, i.e. the relations \lstinline|x == \result| or
+\lstinline|x == -\result|. Then, the \lstinline|split| annotation placed before
+the call to \lstinline|fabs| allows us to reason by case and infer the relevant
+equality in each case.
+
+Note in the previous example the use of \lstinline|merge| annotation. These
+annotations ends the reasoning by cases and must use the exact same expression
+as a previous \lstinline|split|. In this example, the \lstinline|merge|
+annotation is not needed as the partitioning will be ended at the end of the
+function anyway. The use of \lstinline|merge| annotations is not mandatory,
+and are these annotations exists only to allow the user to mitigate the cost of
+the reasoning by cases.
+
+Alternatively to annotations, it is possible to use the command-line to
+reason by case during the whole analysis. The command line parameter
+\lstinline|-eva-partition-value <V>| forces the analyzer to reason at all times
+on single values of the global variable \lstinline|<V>|.
+
+There are three limitations to partitioning on values.
+
+\begin{enumerate}
+\item While the number of simultaneous splits (whether local with annotations
+  or global through command line) is not bounded, there can be only one split
+  per expression. If two \lstinline|split| annotation uses the same expression,
+  only the latest one encountered on the path will be kept. Although it is a
+  limitation, it can be used to define strategies where a reasoning by case is
+  controlled accross the whole program.
+\item The expression on which the split is done must evaluate to a bounded set
+  of values. Otherwise, the analysis would not be guaranteed to terminate. The
+  analysis must be precise enough in order to prove the boundedness. When \Eva{}
+  fails to prove that the number of possible values is lower than a defined limit,
+  either because the set is unbounded or because it failed to prove it,
+  it will raise a warning and cancel the split. The limit is arbitrary and
+  can be set with the option \lstinline|-eva-split-limit <n>|.
+\item When the expression is complex, the ability of \Eva{} to reason
+  precisely by cases depends on the activated abstract domains (see section
+  \ref{sec:eva}) and their capability to learn from the expression. \Eva{} will
+  try to detect this and will cancel the split and warn the user when it is
+  not useful.
+\end{enumerate}
+
+
 \section{Controlling approximations}
 \label{controlling-approximations}