diff --git a/.gitignore b/.gitignore
index 7add466e870aa718c8d279e246433b0817781229..2f16c11cbe005c852493d1d9943900f5a411ea8e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,4 +4,6 @@
 *.dat
 *.sig
 *Theory*
+examples/sollya_inputs/*_coeffs_results*
+examples/sollya_inputs/*proof*
 
diff --git a/checkerScript.sml b/checkerScript.sml
index 771469cd00fc953c6637cd1e26c3a56188207189..ca7649f57e78b5e3178e4c784a1f488bfa942afc 100644
--- a/checkerScript.sml
+++ b/checkerScript.sml
@@ -10,16 +10,43 @@ open preamble;
 
 val _ = new_theory "checker";
 
-Definition exp_steps_def[simp]:
-  exp_steps:num = 10
+Definition approx_steps_def[simp]:
+  approx_steps:num = 10
 End
 
+Theorem exp_err_EVAL_THM = EVAL “inv (&FACT approx_steps * 2 pow (approx_steps - 1))”
+Theorem exp_poly_cst_EVAL_THM = EVAL “exp_poly approx_steps”
+
 Definition exp_err_def:
-  exp_err = ^(EVAL “inv (&FACT exp_steps * 2 pow (exp_steps - 1))” |> concl |> rhs)
+  exp_err = ^(exp_err_EVAL_THM |> concl |> rhs)
 End
 
 Definition exp_poly_cst:
-  exp_poly_cst = ^(EVAL “exp_poly exp_steps” |> concl |> rhs)
+  exp_poly_cst = ^(exp_poly_cst_EVAL_THM |> concl |> rhs)
+End
+
+Triviality one_inv_one:
+  1 * inv 1 = 1
+Proof
+  gs[REAL_MUL_RINV]
+QED
+
+Triviality mul_neg_one:
+  -1 * x = - x:real
+Proof
+  real_tac
+QED
+
+(** Still needs to be multiplied with x pow n **)
+Theorem cos_err_EVAL_THM = EVAL “inv (&FACT approx_steps)”
+Theorem cos_poly_cst_EVAL_THM = EVAL “cos_poly approx_steps” |> SIMP_RULE std_ss [one_inv_one, REAL_MUL_LID, mul_neg_one]
+
+Definition cos_err_def:
+  cos_err iv = (max (abs (FST iv)) (abs (SND iv))) pow approx_steps * ^(cos_err_EVAL_THM |> concl |> rhs)
+End
+
+Definition cos_poly_cst_def:
+  cos_poly_cst = ^(cos_poly_cst_EVAL_THM |> concl |> rhs)
 End
 
 (**
@@ -31,8 +58,10 @@ Definition approx_def:
   approx transc (iv:real#real) :(poly#real) option =
   case transc of
   | FUN tr VAR =>
-      if (iv = (0, 0.5) ∧ tr = "exp") then
+      if (iv = (0, 1 * inv 2) ∧ tr = "exp") then
         SOME (exp_poly_cst, exp_err)
+      else if (tr = "cos") then
+        SOME (cos_poly_cst, cos_err iv)
       else NONE
   | _ => NONE
 End
@@ -260,52 +289,91 @@ Theorem checker_soundness:
 Proof
   rpt strip_tac
   >> gs[checker_def, approx_def, CaseEq"option", CaseEq"prod", CaseEq"result",
-        CaseEq"transc", interp_def, getFun_def]
+        CaseEq"transc"] >> rpt VAR_EQ_TAC
   (* Step 1: Approximate the transcendental fun with its taylor series *)
   >> irule REAL_LE_TRANS
-  >> qexists_tac ‘abs (exp x - poly exp_poly_cst x) + abs (poly exp_poly_cst x - poly cert.poly x)’
+  >> qexists_tac ‘abs (interp (FUN tr VAR) x - poly transp x) + abs (poly transp x - poly cert.poly x)’
   >> conj_tac
   (* Approximation using triangle inequality *)
   >- (
-    ‘exp x - poly cert.poly x = (exp x - poly exp_poly_cst x) + (poly exp_poly_cst x - poly cert.poly x)’
-    by real_tac
+    qmatch_goalsub_abbrev_tac ‘abs (transc_fun - poly _ _) ≤ _’
+    >> ‘transc_fun - poly cert.poly x = (transc_fun - poly transp x) + (poly transp x - poly cert.poly x)’
+      by real_tac
     >> pop_assum $ rewrite_tac o single
     >> irule REAL_ABS_TRIANGLE)
-  >> ‘cert.eps = exp_err + (cert.eps - exp_err)’ by real_tac
+  (* Split the error into the error from Taylor series and the rest *)
+  >> ‘cert.eps = err + (cert.eps - err)’ by real_tac
   >> pop_assum $ once_rewrite_tac o single
+  (* Split the proof into proving two separate approximations *)
   >> irule REAL_LE_ADD2 >> reverse conj_tac
+  (* 1. error between Taylor series and certificate polynomial *)
   >- (
     gs[GSYM poly_compat, GSYM eval_simps]
     >> rewrite_tac [poly_compat]
     >> irule validateZeroesLeqErr_sound
-    >> qexists_tac ‘diff (exp_poly_cst -p cert.poly)’ >> gs[]
-    >> qexists_tac ‘(0, 1/2)’ >> gs[]
+    >> qexists_tac ‘diff (transp -p cert.poly)’ >> gs[]
+    >> qexists_tac ‘cert.iv’ >> gs[]
     >> qexists_tac ‘cert.zeroes’ >> gs[]
+    >> ‘FST cert.iv ≤ SND cert.iv’ by real_tac
     >> drule checkZeroes_sound
     >> disch_then drule >> gs[])
-  (* Now prove the Taylor series error
-  TODO: Make separate soundness proof *)
-  >> qspecl_then [‘x’, ‘exp_steps’] strip_assume_tac MCLAURIN_EXP_LE
+  (* 2. error between transcendental function and Taylor series *)
+  (* TODO: Make separate soundness proof *)
+  >> ‘(cert.iv = (0, 1 * inv 2) ∧ tr = "exp") ∨ tr = "cos"’ by (every_case_tac >> gs[])
+  (* exp function *)
+  >- (
+    gs[interp_def, getFun_def]
+    >> qspecl_then [‘x’, ‘approx_steps’] strip_assume_tac MCLAURIN_EXP_LE
+    >> pop_assum $ rewrite_tac o single
+    >> ‘poly exp_poly_cst x = evalPoly (exp_poly approx_steps) x’
+      by (gs[poly_compat] >> EVAL_TAC)
+    >> pop_assum $ rewrite_tac o single
+    >> gs[exp_sum_to_poly]
+    >> qmatch_goalsub_abbrev_tac ‘abs (exp_taylor + taylor_rem - exp_taylor) ≤ _’
+    >> ‘exp_taylor + taylor_rem - exp_taylor = taylor_rem’ by real_tac
+    >> pop_assum $ rewrite_tac o single
+    >> unabbrev_all_tac
+    >> ‘exp_err = inv (&FACT approx_steps * 2 pow (approx_steps - 1))’ by EVAL_TAC
+    >> pop_assum $ rewrite_tac o single
+    >> qspecl_then [‘approx_steps’, ‘x’,‘t’] mp_tac exp_remainder_bounded
+    >> impl_tac >> gs[]
+    >> real_tac)
+  (* cos function *)
+  >> gs[interp_def, getFun_def] >> rpt VAR_EQ_TAC
+  >> qspecl_then [‘x’, ‘approx_steps’] strip_assume_tac MCLAURIN_COS_LE
+  >> gs[]
   >> pop_assum $ rewrite_tac o single
-  >> ‘poly exp_poly_cst x = evalPoly (exp_poly exp_steps) x’
-     by (gs[poly_compat] >> EVAL_TAC)
+  >> ‘poly cos_poly_cst x = evalPoly (cos_poly approx_steps) x’
+    by (rewrite_tac [GSYM approx_steps_def, cos_poly_cst_EVAL_THM]
+        >> gs[poly_compat, cos_poly_cst_def])
   >> pop_assum $ rewrite_tac o single
-  >> gs[exp_sum_to_poly]
-  >> qmatch_goalsub_abbrev_tac ‘abs (exp_taylor + taylor_rem - exp_taylor) ≤ _’
-  >> ‘exp_taylor + taylor_rem - exp_taylor = taylor_rem’ by real_tac
+  >> gs[cos_sum_to_poly]
+  >> qmatch_goalsub_abbrev_tac ‘abs (cos_taylor + taylor_rem - cos_taylor) ≤ _’
+  >> ‘cos_taylor + taylor_rem - cos_taylor = taylor_rem’ by real_tac
   >> pop_assum $ rewrite_tac o single
   >> unabbrev_all_tac
-  >> ‘exp_err = inv (&FACT exp_steps * 2 pow (exp_steps - 1))’ by EVAL_TAC
+  >> ‘(x pow approx_steps) * cos t * inv (&FACT approx_steps) =
+      (cos t * ((x pow approx_steps) * inv (&FACT approx_steps)))’
+     by real_tac
+  >> ‘-(x pow approx_steps) * cos t * inv (&FACT approx_steps) =
+      -(cos t * ((x pow approx_steps) * inv (&FACT approx_steps)))’
+     by real_tac
+  >> rewrite_tac [GSYM approx_steps_def]
+  >> ntac 2 $ pop_assum $ rewrite_tac o single
+  >> rewrite_tac [ABS_NEG, Once ABS_MUL]
+  >> qmatch_goalsub_abbrev_tac ‘_ * err_cos_concr’
+  >> irule REAL_LE_TRANS
+  >> qexists_tac ‘ 1 * err_cos_concr’ >> conj_tac
+  >- (irule REAL_LE_RMUL_IMP >> unabbrev_all_tac >> gs[COS_BOUND, ABS_POS])
+  >> unabbrev_all_tac
+  >> rewrite_tac [REAL_MUL_LID, cos_err_def, ABS_MUL]
+  >> ‘abs (inv (&FACT approx_steps)) = inv (&FACT approx_steps)’
+     by (rewrite_tac[abs] >>  EVAL_TAC >> gs[])
   >> pop_assum $ rewrite_tac o single
-  >> qspecl_then [‘exp_steps’, ‘x’,‘t’] mp_tac exp_remainder_bounded
-  >> impl_tac >> gs[] >> reverse conj_tac
-  >- gs[REAL_INV_1OVER]
-  >> gs[abs] >> Cases_on ‘0 ≤ t’
-  >- (
-    irule REAL_LE_TRANS  >> qexists_tac ‘x’ >> gs[REAL_INV_1OVER])
-  >> irule REAL_LE_TRANS >> qexists_tac ‘-t’ >> conj_tac >- real_tac
-  >> irule REAL_LE_TRANS >> qexists_tac ‘x’
-  >> gs[REAL_INV_1OVER]
+  >> rewrite_tac[EVAL “(inv (&FACT approx_steps))”, ABS_MUL]
+  >> irule REAL_LE_RMUL_IMP >> gs[GSYM POW_ABS]
+  >> irule POW_LE >> gs[ABS_POS]
+  >> irule RealSimpsTheory.maxAbs >> gs[]
 QED
 
 val _ = export_theory();
diff --git a/examples/mockUpScript.sml b/examples/mockUpScript.sml
index 7b3c341db231245cd8d650503a54903d894aba35..330b6935f55fea2fe0b6bd14522a99cafcd9cf38 100644
--- a/examples/mockUpScript.sml
+++ b/examples/mockUpScript.sml
@@ -1,5 +1,5 @@
-open realTheory realLib RealArith stringTheory;
-open renameTheory realPolyTheory checkerDefsTheory;
+open realTheory realLib RealArith stringTheory ;
+open renameTheory realPolyTheory checkerDefsTheory checkerTheory sturmComputeTheory;
 open preamble;
 
 val _ = new_theory "mockUp";
@@ -12,18 +12,111 @@ val _ = new_theory "mockUp";
 Definition exp_example_def:
   exp_example =
   <|
-    transc := (\ x.  exp(x) );
-    poly :=  [
-        36028796527503441     * inv (2 pow 55);  (* c *)
-        2305847485481749147   * inv (2 pow 61);  (* x *)
-        18445094142862447103  * inv (2 pow 65);  (* x^2 *)
-        6162767460358145607   * inv (2 pow 65);  (* x^3 *)
-        2970172589018140341   * inv (2 pow 66);  (* x^4  *)
-        12670224417430857765  * inv (2 pow 70)   (* x^5 *)
-      ];
-    omega := [];
-    eps :=  8443227763790560011 * inv (2 pow 89) ;
+    transc := FUN "cos" VAR;
+poly := [
+     4289449735  * inv ( 2 pow  32 );
+     139975391  * inv ( 2 pow  33 );
+     -2408138823  * inv ( 2 pow  32 );
+     2948059219  * inv ( 2 pow  35 );
+    ];
+  eps :=  582015  * inv (2 pow 31 );
+  zeroes := [
+    ( 1966918861  * inv (2 pow 33 ),
+      3935725159  * inv (2 pow 34 ));
+    ( 2335336039  * inv (2 pow 32 ),
+      1167903949  * inv (2 pow 31 ));
+    ( 1856818381  * inv (2 pow 31 ),
+      3714108621  * inv (2 pow 32 ));
+    ];
+  iv :=
+    ( 858993459  * inv (2 pow 33 ),
+      1  * inv (2 pow 0 ));
+  omega := [];
   |>
 End
 
+(* Definition narrowStep_def: *)
+(*   narrowStep (l,h):(real#real) : (real#real) = *)
+(*   let dist = (h - l); *)
+(*       quart = dist / 8; *)
+(*       lN = l + quart; *)
+(*       hN = h - quart; *)
+(*   in *)
+(*     (lN,hN) *)
+(* End *)
+
+(* Definition doNarrow_def: *)
+(*   doNarrow (l,h) p = *)
+(*   if poly p l * poly p h ≤ 0 then *)
+(*     let (lN, hN) = narrowStep (l,h) *)
+(*     in *)
+(*       if poly p lN * poly p hN ≤ 0 then *)
+(*         (lN, hN) *)
+(*       else (l,h) *)
+(*   else (l,h) *)
+(* End *)
+
+(* Definition doNarrowExplicit_def: *)
+(*   doNarrowExplicit (l,h) p = *)
+(*   let (lN, hN) = doNarrow (l,h) p in *)
+(*   if poly p l * poly p h ≤ 0 then *)
+(*     let (lN, hN) = narrowStep (l,h) *)
+(*     in *)
+(*       if poly p lN * poly p hN ≤ 0 then *)
+(*         SOME (SOME (lN, hN)) *)
+(*       else SOME NONE *)
+(*   else NONE *)
+(* End *)
+
+(*
+val _ = computeLib.add_thms [REAL_INV_1OVER] computeLib.the_compset;
+val _ = computeLib.add_funs [polyTheory.poly_diff_def, polyTheory.poly_diff_aux_def, polyTheory.poly_def]
+*)
+
+(*
+val (transp, err) = EVAL “approx exp_example.transc exp_example.iv” |> concl |> rhs |> optionSyntax.dest_some |> pairSyntax.dest_pair
+val errorp = Parse.Term ‘^transp -p exp_example.poly’ |> EVAL |> rhs o concl
+val deriv1 = Parse.Term ‘diff ^errorp’ |> EVAL |> rhs o concl
+
+(* val test = Parse.Term ‘MAP (λ iv. doNarrowExplicit iv ^deriv1) exp_example.zeroes’ |> EVAL |> concl |> rhs *)
+(* val test2 = Parse.Term ‘MAP (λ ivopt. case ivopt of |SOME (SOME iv) => doNarrowExplicit iv ^deriv1 |_ => NONE) ^test’ |> EVAL |> rhs o concl *)
+(* val test3 = Parse.Term ‘MAP (λ ivopt. case ivopt of |SOME (SOME iv) => doNarrowExplicit iv ^deriv1 |_ => NONE) ^test2’ |> EVAL |> rhs o concl *)
+(* val test4 = Parse.Term ‘MAP (λ ivopt. case ivopt of |SOME (SOME iv) => doNarrowExplicit iv ^deriv1 |_ => NONE) ^test3’ |> EVAL |> rhs o concl *)
+(* val test4 = Parse.Term ‘MAP (λ ivopt. case ivopt of |SOME (SOME iv) => doNarrowExplicit iv ^deriv1 |_ => NONE) ^test4’ |> EVAL |> rhs o concl *)
+(* val test5 = Parse.Term ‘(MAP (λ ivopt. case ivopt of |SOME (SOME iv) => iv |_ => (0,0)) ^test4)’ |> EVAL |> rhs o concl *)
+
+(* val e1 = Parse.Term ‘getMaxWidth exp_example.zeroes’ |> EVAL |> rhs o concl *)
+(* val e2 = Parse.Term ‘getMaxWidth ^test5’ |> EVAL |> rhs o concl *)
+
+val sseq_aux = decls "sturm_seq_aux";
+val _ = computeLib.monitoring := SOME (same_const (hd sseq_aux));
+
+val sseq = Parse.Term ‘sturm_seq ^deriv1 (diff ^deriv1)’
+               |> EVAL
+               |> rhs o concl
+               |> optionSyntax.dest_some
+
+val res = Parse.Term ‘checkZeroes ^deriv1 (diff ^deriv1) exp_example.iv ^sseq exp_example.zeroes’
+            |> EVAL
+
+val res = Parse.Term ‘validateZeroesLeqErr ^errorp exp_example.iv exp_example.zeroes (exp_example.eps - ^err)’ |> EVAL
+
+val mAbs = Parse.Term ‘max (abs (FST exp_example.iv)) (abs (SND exp_example.iv))’ |> EVAL |> rhs o concl
+val B = Parse.Term ‘poly (MAP abs (diff ^errorp)) ^mAbs’ |> EVAL |> rhs o concl
+val e1 = Parse.Term ‘getMaxWidth ^test5’ |> EVAL |> rhs o concl
+val ub = Parse.Term ‘getMaxAbsLb ^errorp ^test5’ |> EVAL |> rhs o concl
+
+val err1 = Parse.Term ‘^ub + ^B * ^e1’ |> EVAL |> rhs o concl
+val err2 = Parse.Term ‘^err’ |> EVAL |> rhs o concl
+
+val res = Parse.Term ‘abs (poly ^errorp (FST exp_example.iv)) ≤ ^ub + ^B * ^e1’ |> EVAL
+val res2 = Parse.Term ‘abs (poly ^errorp (SND exp_example.iv)) ≤ ^ub + ^B * ^e1’ |> EVAL
+val res3 = Parse.Term ‘validBounds exp_example.iv exp_example.zeroes’ |> EVAL
+val res4 = Parse.Term ‘MAP (λ(u,v). poly (diff ^errorp) u * poly (diff ^errorp) v) exp_example.zeroes’ |> EVAL
+val res5 = Parse.Term ‘recordered (FST exp_example.iv) exp_example.zeroes (SND exp_example.iv)’ |> EVAL
+val res6 = Parse.Term ‘^ub + ^B * ^e1 ≤ (exp_example.eps - ^err)’ |> EVAL
+
+EVAL “checker exp_example”
+*)
+
 val _ = export_theory();
diff --git a/examples/sollya_inputs/cos_approx.sollya b/examples/sollya_inputs/cos_approx.sollya
new file mode 100644
index 0000000000000000000000000000000000000000..77213db39635a7396e69712bb6860eb7ac149ec2
--- /dev/null
+++ b/examples/sollya_inputs/cos_approx.sollya
@@ -0,0 +1,61 @@
+oldDisplay=display;
+display = powers!;  //putting ! after a command supresses its output
+
+approxPrec = 32;
+prec = approxPrec;
+deg = 3;
+f = cos(x);
+dom = [0.1; 1];
+p = fpminimax(f, deg, [|prec,prec...|], dom, absolute);
+
+derivativeZeros = findzeros(diff(p-f),dom); // here the derivativeZeros is a list of intervals that guarantee to contain the exact zeros
+//derivativeZeros = inf(dom).:derivativeZeros:.sup(dom);
+maximum=0;
+for t in derivativeZeros do {
+  r = evaluate(abs(p-f), t); // r is an interval, we should take its upper bound
+  if sup(r) > maximum then { maximum=sup(r); argmaximum=t; };
+  if (evaluate(diff(p-f),inf(t)) * evaluate (diff(p-f),sup(t)) <= 0 ) then {
+	print ("Ok zero:");
+    print ("    (", mantissa (inf(t)), " * inv (2 pow", -exponent(inf(t)), "),");
+    print ("     ", mantissa (sup(t)), " * inv (2 pow", -exponent(sup(t)), "));");
+  };
+};
+print("<|");
+print("  transc := FUN \"", f, "\" VAR;");
+print("  poly := [");
+for i from 0 to degree(p) do{
+    coeff_p = coeff(p, i);
+    print("    ", mantissa (coeff_p), " * inv ( 2 pow ", -exponent(coeff_p), ");");
+};
+print ("    ];");
+print("  eps := ", mantissa(maximum), " * inv (2 pow", -exponent(maximum), ");");
+print("  zeroes := [");
+for t in derivativeZeros do{
+    print ("    (", mantissa (inf(t)), " * inv (2 pow", -exponent(inf(t)), "),");
+    print ("     ", mantissa (sup(t)), " * inv (2 pow", -exponent(sup(t)), "));");
+};
+print ("    ];");
+print ("  iv := ");
+print ("    (", mantissa (inf(dom)), " * inv (2 pow", -exponent(inf(dom)), "),");
+print ("     ", mantissa (sup(dom)), " * inv (2 pow", -exponent(sup(dom)), "));");
+print ("  omega := [];");
+print("|>");
+
+/* Writing into a file */
+filename = "exp_coeffs_results.txt";
+write("Polynomial coefficients p_O,..., p_n represented as their mantissa and exponent, i.e. p_i=mantissa * 2^exponent\n") > filename;
+//attention, here ">" overwrites the file, use ">>" to append
+for i from 0 to degree(p) do{
+    coeff_p = coeff(p, i);
+    write(mantissa(coeff_p),"\t", exponent(coeff_p), "\n") >> filename;
+};
+write("The absolute error bound\n") >> filename;
+write(mantissa(maximum),"\t", exponent(maximum), "\n") >> filename;
+write(derivativeZeros, "\n") >> filename;
+
+
+/* Some sanity checks to verify that our eps is not smaller than the reliable bounds obtained with dedicated methods */
+display=oldDisplay!;
+print("We got epsilon:", maximum);
+print("Sanity check with supnorm:", supnorm(p, f, dom, absolute, 2^(-40)));
+print("Sanity check with infinity norm:", infnorm(p-f, dom, "proof.txt")); //here the last argument is rather for fun, it gives the proof of the bound, you can remove it.
diff --git a/examples/sollya_inputs/exp_approx2.sollya b/examples/sollya_inputs/exp_approx2.sollya
index 80d49cf295a1d0eb5fe2cb301e4ba5bedccf7e7a..433729cb18a4d76154b8c760d070282884279240 100644
--- a/examples/sollya_inputs/exp_approx2.sollya
+++ b/examples/sollya_inputs/exp_approx2.sollya
@@ -1,28 +1,49 @@
 oldDisplay=display;
 display = powers!;  //putting ! after a command supresses its output
 
-approxPrec = 54;
-deg = 5;
-f = sin(x);
-dom = [0; 0.5];
-p = fpminimax(f, deg, [|D,D...|], dom, absolute);
+approxPrec = 32;
+prec = approxPrec;
+deg = 3;
+f = exp(x);
+dom = [0; 0.4];
+p = fpminimax(f, deg, [|prec,prec...|], dom, absolute);
 
-derivativeZeros = findzeros(diff(p-f),dom); // here the derivativeZeros is a list of intervals that guarantee to contain the exact zeros 
-derivativeZeros = inf(dom).:derivativeZeros:.sup(dom);
+derivativeZeros = findzeros(diff(p-f),dom); // here the derivativeZeros is a list of intervals that guarantee to contain the exact zeros
+//derivativeZeros = inf(dom).:derivativeZeros:.sup(dom);
 maximum=0;
 for t in derivativeZeros do {
   r = evaluate(abs(p-f), t); // r is an interval, we should take its upper bound
   if sup(r) > maximum then { maximum=sup(r); argmaximum=t; };
+  if (evaluate(diff(p-f),inf(t)) * evaluate (diff(p-f),sup(t)) <= 0 ) then {
+	print ("Ok zero:");
+    print ("    (", mantissa (inf(t)), " * inv (2 pow", -exponent(inf(t)), "),");
+    print ("     ", mantissa (sup(t)), " * inv (2 pow", -exponent(sup(t)), "));");
+  };
 };
 print("<|");
-print("  transc := (\\ x. ", f, ");");
-print("  poly := ", p, ";");
-print("  eps := ", maximum, ";");
+print("  transc := FUN \"", f, "\" VAR;");
+print("  poly := [");
+for i from 0 to degree(p) do{
+    coeff_p = coeff(p, i);
+    print("    ", mantissa (coeff_p), " * inv ( 2 pow ", -exponent(coeff_p), ");");
+};
+print ("    ];");
+print("  eps := ", mantissa(maximum), " * inv (2 pow", -exponent(maximum), ");");
+print("  zeroes := [");
+for t in derivativeZeros do{
+    print ("    (", mantissa (inf(t)), " * inv (2 pow", -exponent(inf(t)), "),");
+    print ("     ", mantissa (sup(t)), " * inv (2 pow", -exponent(sup(t)), "));");
+};
+print ("    ];");
+print ("  iv := ");
+print ("    (", mantissa (inf(dom)), " * inv (2 pow", -exponent(inf(dom)), "),");
+print ("     ", mantissa (sup(dom)), " * inv (2 pow", -exponent(sup(dom)), "));");
+print ("  omega := [];");
 print("|>");
 
 /* Writing into a file */
 filename = "exp_coeffs_results.txt";
-write("Polynomial coefficients p_O,..., p_n represented as their mantissa and exponent, i.e. p_i=mantissa * 2^exponent\n") > filename;      
+write("Polynomial coefficients p_O,..., p_n represented as their mantissa and exponent, i.e. p_i=mantissa * 2^exponent\n") > filename;
 //attention, here ">" overwrites the file, use ">>" to append
 for i from 0 to degree(p) do{
     coeff_p = coeff(p, i);
@@ -30,6 +51,7 @@ for i from 0 to degree(p) do{
 };
 write("The absolute error bound\n") >> filename;
 write(mantissa(maximum),"\t", exponent(maximum), "\n") >> filename;
+write(derivativeZeros, "\n") >> filename;
 
 
 /* Some sanity checks to verify that our eps is not smaller than the reliable bounds obtained with dedicated methods */
diff --git a/mcLaurinApproxScript.sml b/mcLaurinApproxScript.sml
index 2b4240d50c8fe61609bc3dc8737ce640bbef591d..ac6b00decefdb94b7f241e43b26dae6f2ea068bb 100644
--- a/mcLaurinApproxScript.sml
+++ b/mcLaurinApproxScript.sml
@@ -226,6 +226,24 @@ Proof
   >> gs[]
 QED
 
+(** Mclaurin series for sqrt fucntion **)
+Theorem MCLAURIN_SQRT_LE:
+  ∀ x n. 0 < x ⇒
+         ∃t. abs(t) ≤ abs (x) ∧
+             (\n. sqrt(1+x) = 1 +
+                              sum(1,n)
+                                 (\m. -1 pow (m-1) *
+                                      inv(1+x) pow (((2*m - 1) DIV 2))
+                                      * inv(2 pow m) * &(FACT (m-1)) *
+                                      inv((2 pow (m-1)) *  &(FACT (m-1))) +
+                                      -1 pow (n-1) *
+                                       inv((1+t) pow (((2*n - 1) DIV 2)))
+                                       * inv(2 pow n) * &(FACT (n-1)) *
+                                       inv ((2 pow (n-1)) * &(FACT (n-1))))) n
+Proof
+  cheat
+QED
+
 (*** Prove lemma for bound on exp in the interval, x ∈ [0, 0.5]
 based on John Harrison's paper **)
 
@@ -293,7 +311,7 @@ Proof
 QED
 
 Theorem  REAL_EXP_MINUS1_BOUND_LEMMA:
-  !x. &0 <= x /\ x <= inv(&2) ==> &1 - exp(-x) <= &2 * x
+  ∀x. &0 ≤ x ∧ x ≤ inv(&2) ⇒ &1 - exp(-x) ≤ &2 * x
 Proof
   REPEAT STRIP_TAC >> REWRITE_TAC[REAL_LE_SUB_RADD]
   >> ONCE_REWRITE_TAC[REAL_ADD_SYM]
@@ -393,26 +411,72 @@ Proof
   >> gs[REAL_INV_MUL']
 QED
 
-(** Mclaurin series for sqrt fucntion **)
+Definition cos_poly_def:
+  cos_poly 0 = [] ∧
+  cos_poly (SUC n) =
+    if (EVEN n) then
+      cos_poly n ++ [-1 pow (n DIV 2) * inv (&FACT n)]
+    else cos_poly n ++ [0]
+End
 
-Theorem MCLAURIN_SQRT_LE:
-  ∀ x n. 0 < x ⇒
-         ∃t. abs(t) ≤ abs (x) ∧
-             (\n. sqrt(1+x) = 1 +
-                              sum(1,n)
-                                 (\m. -1 pow (m-1) *
-                                      inv(1+x) pow (((2*m - 1) DIV 2))
-                                      * inv(2 pow m) * &(FACT (m-1)) *
-                                      inv((2 pow (m-1)) *  &(FACT (m-1))) +
-                                      -1 pow (n-1) *
-                                       inv((1+t) pow (((2*n - 1) DIV 2)))
-                                       * inv(2 pow n) * &(FACT (n-1)) *
-                                       inv ((2 pow (n-1)) * &(FACT (n-1))))) n
+Theorem LENGTH_cos_poly:
+  LENGTH (cos_poly n) = n
 Proof
-  cheat
+  Induct_on ‘n’ >> gs[cos_poly_def]
+  >> cond_cases_tac >> gs[]
 QED
 
+Theorem cos_sum_to_poly:
+  ∀ n x. evalPoly (cos_poly n) x =
+       sum(0,n)
+          (λm.
+             (&FACT m)⁻¹ * x pow m *
+             if EVEN m then cos 0 * -1 pow (m DIV 2)
+             else sin 0 * -1 pow ((SUC m) DIV 2))
+Proof
+  Induct_on ‘n’ >> gs[sum, evalPoly_def, cos_poly_def]
+  >> cond_cases_tac
+  >> gs[evalPoly_app, COS_0, SIN_0, evalPoly_def, LENGTH_cos_poly]
+QED
 
-
+Theorem cos_even_remainder_bounded:
+  ∀ n.
+    EVEN n ⇒
+    inv (&FACT n) * cos t * x pow n * -1 pow (n DIV 2) ≤
+    abs(inv (&FACT n) * x pow n * -1 pow (n DIV 2))
+Proof
+  rpt strip_tac
+  >> ‘inv (&FACT n) * x pow n * -1 pow (n DIV 2) = inv (&FACT n) * 1 * x pow n * -1 pow (n DIV 2)’
+     by real_tac
+  >> pop_assum $ rewrite_tac o single
+  >> rewrite_tac[GSYM REAL_MUL_ASSOC]
+  >> once_rewrite_tac[REAL_ABS_MUL]
+  >> ‘0 ≤ inv (&FACT n)’
+     by gs[REAL_LE_INV]
+  >> ‘abs (inv (&FACT n)) = inv (&FACT n)’ by gs[abs]
+  >> pop_assum $ rewrite_tac o single
+  >> irule REAL_LE_LMUL_IMP
+  >> reverse conj_tac >- gs[]
+  >> once_rewrite_tac[REAL_ABS_MUL]
+  >> Cases_on ‘0 ≤ x pow n * -1 pow (n DIV 2)’
+  >- (
+    ‘abs (x pow n * -1 pow (n DIV 2)) = x pow n * -1 pow (n DIV 2)’ by gs[abs]
+    >> pop_assum $ rewrite_tac o single
+    >> irule REAL_LE_RMUL_IMP >> gs[COS_BOUNDS])
+  >> ‘x pow n * -1 pow (n DIV 2) < 0’ by real_tac
+  >> irule REAL_LE_TRANS
+  >> qexists_tac ‘-1 * (x pow n * -1 pow (n DIV 2))’
+  >> conj_tac
+  >- (
+    once_rewrite_tac [REAL_MUL_COMM]
+    >> drule REAL_LE_LMUL_NEG
+    >> disch_then $ qspecl_then [‘cos t’, ‘-1’] $ rewrite_tac o single
+    >> gs[COS_BOUNDS])
+  >> ‘∃ y. x pow n * -1 pow (n DIV 2) = -1 * y ∧ 0 ≤ y’
+    by (qexists_tac ‘-1 * x pow n * -1 pow (n DIV 2)’
+        >> real_tac)
+  >> qpat_x_assum `_ = -1 * y` $ rewrite_tac o single
+  >> gs[ABS_LE]
+QED
 
 val _ = export_theory();