let inferisign_lem00 = 
prove_by_refinement( `x1 < x3 ==> x3 < x2 ==> (!x. x1 < x /\ x < x2 ==> P x) ==> (!x. x1 < x /\ x < x3 ==> P x) /\ (!x. (x = x3) ==> P x) /\ (!x. x3 < x /\ x < x2 ==> P x)`,
(* {{{ Proof *) [ REPEAT STRIP_TAC; FIRST_ASSUM MATCH_MP_TAC; ASM_REWRITE_TAC[]; MATCH_MP_TAC REAL_LT_TRANS; EXISTS_TAC `x3`; ASM_REWRITE_TAC[]; FIRST_ASSUM MATCH_MP_TAC; ASM_REWRITE_TAC[]; FIRST_ASSUM MATCH_MP_TAC; ASM_REWRITE_TAC[]; MATCH_MP_TAC REAL_LT_TRANS; EXISTS_TAC `x3`; ASM_REWRITE_TAC[]; ]);;
(* }}} *)
let neg_neg_neq_thm = 
prove_by_refinement( `!x y p. x < y /\ poly p x < &0 /\ poly p y < &0 /\ (!z. x < z /\ z < y ==> ~(poly (poly_diff p) z = &0)) ==> (!z. x < z /\ z < y ==> poly p z < &0)`,
(* {{{ Proof *) [ REPEAT STRIP_TAC; REWRITE_TAC[ARITH_RULE `x < y <=> ~(y <= x)`]; STRIP_TAC; MP_TAC (ISPECL [`p:real list`;`x:real`;`z:real`] POLY_MVT); ASM_REWRITE_TAC[]; STRIP_TAC; CLAIM `&0 < poly p z - poly p x`; LABEL_ALL_TAC; USE_THEN "Z-3" MP_TAC; USE_THEN "Z-8" MP_TAC; REAL_ARITH_TAC; STRIP_TAC; CLAIM `&0 < (z - x) * poly (poly_diff p) x'`; REPEAT_N 2 (POP_ASSUM MP_TAC) THEN REAL_ARITH_TAC; ASM_REWRITE_TAC[REAL_MUL_GT]; REPEAT STRIP_TAC; CLAIM `&0 < z - x`; LABEL_ALL_TAC; USE_THEN "Z-8" MP_TAC THEN REAL_ARITH_TAC; LABEL_ALL_TAC; USE_THEN "Z-1" MP_TAC THEN REAL_ARITH_TAC; (* save *) MP_TAC (ISPECL [`p:real list`;`z:real`;`y:real`] POLY_MVT); ASM_REWRITE_TAC[]; STRIP_TAC; CLAIM `poly p y - poly p z < &0`; LABEL_ALL_TAC; USE_THEN "Z-13" MP_TAC; USE_THEN "Z-9" MP_TAC; REAL_ARITH_TAC; STRIP_TAC; CLAIM `&0 < y - z`; LABEL_ALL_TAC; USE_THEN "Z-11" MP_TAC THEN REAL_ARITH_TAC; STRIP_TAC; CLAIM `(y - z) * poly (poly_diff p) x'' < &0`; POP_ASSUM IGNORE; POP_ASSUM MP_TAC; POP_ASSUM MP_TAC; REAL_ARITH_TAC; ASM_REWRITE_TAC[REAL_MUL_LT]; REPEAT STRIP_TAC; REPEAT_N 3 (POP_ASSUM MP_TAC); REAL_ARITH_TAC; CLAIM `x' < x''`; MATCH_MP_TAC REAL_LT_TRANS; EXISTS_TAC `z`; ASM_REWRITE_TAC[]; STRIP_TAC; MP_TAC (ISPECL [`poly_diff p`;`x':real`;`x'':real`] (REWRITE_RULE[real_gt] POLY_IVT_NEG)); ASM_REWRITE_TAC[]; STRIP_TAC; CLAIM `x < x''' /\ x''' < y`; STRIP_TAC; MATCH_MP_TAC REAL_LT_TRANS; EXISTS_TAC `x'`; ASM_REWRITE_TAC[]; MATCH_MP_TAC REAL_LT_TRANS; EXISTS_TAC `x''`; ASM_REWRITE_TAC[]; ASM_MESON_TAC[]; ]);;
(* }}} *)
let neg_neg_neq_thm2 = 
prove_by_refinement( `!x y p. x < y ==> poly p x < &0 ==> poly p y < &0 ==> (!z. x < z /\ z < y ==> ~(poly (poly_diff p) z = &0)) ==> (!z. x < z /\ z < y ==> poly p z < &0)`,
(* {{{ Proof *) [ REPEAT_N 7 STRIP_TAC; MATCH_MP_TAC neg_neg_neq_thm; ASM_MESON_TAC[]; ]);;
(* }}} *)
let pos_pos_neq_thm = 
prove_by_refinement( `!x y p. x < y /\ &0 < poly p x /\ &0 < poly p y /\ (!z. x < z /\ z < y ==> ~(poly (poly_diff p) z = &0)) ==> (!z. x < z /\ z < y ==> &0 < poly p z)`,
(* {{{ Proof *) [ REPEAT STRIP_TAC; REWRITE_TAC[ARITH_RULE `x < y <=> ~(y <= x)`]; STRIP_TAC; MP_TAC (ISPECL [`p:real list`;`x:real`;`z:real`] POLY_MVT); ASM_REWRITE_TAC[]; STRIP_TAC; CLAIM `poly p z - poly p x < &0`; LABEL_ALL_TAC; USE_THEN "Z-3" MP_TAC; USE_THEN "Z-8" MP_TAC; REAL_ARITH_TAC; STRIP_TAC; CLAIM `(z - x) * poly (poly_diff p) x' < &0`; REPEAT_N 2 (POP_ASSUM MP_TAC) THEN REAL_ARITH_TAC; ASM_REWRITE_TAC[REAL_MUL_LT]; REPEAT STRIP_TAC; CLAIM `&0 < z - x`; LABEL_ALL_TAC; USE_THEN "Z-8" MP_TAC THEN REAL_ARITH_TAC; LABEL_ALL_TAC; USE_THEN "Z-1" MP_TAC THEN REAL_ARITH_TAC; (* save *) MP_TAC (ISPECL [`p:real list`;`z:real`;`y:real`] POLY_MVT); ASM_REWRITE_TAC[]; STRIP_TAC; CLAIM `&0 < poly p y - poly p z`; LABEL_ALL_TAC; USE_THEN "Z-13" MP_TAC; USE_THEN "Z-9" MP_TAC; REAL_ARITH_TAC; STRIP_TAC; CLAIM `&0 < y - z`; LABEL_ALL_TAC; USE_THEN "Z-11" MP_TAC THEN REAL_ARITH_TAC; STRIP_TAC; CLAIM `&0 < (y - z) * poly (poly_diff p) x''`; POP_ASSUM IGNORE; POP_ASSUM MP_TAC; POP_ASSUM MP_TAC; REAL_ARITH_TAC; ASM_REWRITE_TAC[REAL_MUL_GT]; REPEAT STRIP_TAC; REPEAT_N 3 (POP_ASSUM MP_TAC); REAL_ARITH_TAC; CLAIM `x' < x''`; MATCH_MP_TAC REAL_LT_TRANS; EXISTS_TAC `z`; ASM_REWRITE_TAC[]; STRIP_TAC; MP_TAC (ISPECL [`poly_diff p`;`x':real`;`x'':real`] (REWRITE_RULE[real_gt] POLY_IVT_POS)); ASM_REWRITE_TAC[]; STRIP_TAC; CLAIM `x < x''' /\ x''' < y`; STRIP_TAC; MATCH_MP_TAC REAL_LT_TRANS; EXISTS_TAC `x'`; ASM_REWRITE_TAC[]; MATCH_MP_TAC REAL_LT_TRANS; EXISTS_TAC `x''`; ASM_REWRITE_TAC[]; ASM_MESON_TAC[]; ]);;
(* }}} *)
let pos_pos_neq_thm2 = 
prove_by_refinement( `!x y p. x < y ==> poly p x > &0 ==> poly p y > &0 ==> (!z. x < z /\ z < y ==> ~(poly (poly_diff p) z = &0)) ==> (!z. x < z /\ z < y ==> poly p z > &0)`,
(* {{{ Proof *) [ REWRITE_TAC[real_gt]; REPEAT_N 7 STRIP_TAC; MATCH_MP_TAC pos_pos_neq_thm; ASM_MESON_TAC[]; ]);;
(* }}} *)
let pos_neg_neq_thm = 
prove_by_refinement( `!x y p. x < y /\ &0 < poly p x /\ poly p y < &0 /\ (!z. x < z /\ z < y ==> ~(poly (poly_diff p) z = &0)) ==> ?X. x < X /\ X < y /\ (poly p X = &0) /\ (!z. x < z /\ z < X ==> &0 < poly p z) /\ (!z. X < z /\ z < y ==> poly p z < &0)`,
(* {{{ Proof *) [ REPEAT STRIP_TAC; MP_TAC (ISPECL [`p:real list`;`x:real`;`y:real`] POLY_IVT_NEG); REWRITE_TAC[real_gt]; ASM_REWRITE_TAC[]; DISCH_THEN (X_CHOOSE_TAC `X:real`); POP_ASSUM MP_TAC THEN STRIP_TAC; EXISTS_TAC `X`; ASM_REWRITE_TAC[]; STRIP_TAC; REPEAT STRIP_TAC; (* save *) ONCE_REWRITE_TAC[ARITH_RULE `x < y <=> ~(y < x \/ (x = y))`]; STRIP_TAC; MP_TAC (ISPECL [`p:real list`;`x:real`;`z:real`] POLY_MVT); ASM_REWRITE_TAC[]; DISCH_THEN (X_CHOOSE_TAC `N:real`); POP_ASSUM MP_TAC THEN STRIP_TAC; CLAIM `poly p z - poly p x < &0`; LABEL_ALL_TAC; USE_THEN "Z-3" MP_TAC; USE_THEN "Z-11" MP_TAC; REAL_ARITH_TAC; STRIP_TAC; CLAIM `(z - x) * poly (poly_diff p) N < &0`; REPEAT_N 2 (POP_ASSUM MP_TAC) THEN REAL_ARITH_TAC; ASM_REWRITE_TAC[REAL_MUL_LT]; REPEAT STRIP_TAC; CLAIM `&0 < z - x`; LABEL_ALL_TAC; USE_THEN "Z-8" MP_TAC THEN REAL_ARITH_TAC; LABEL_ALL_TAC; USE_THEN "Z-1" MP_TAC THEN REAL_ARITH_TAC; (* save *) MP_TAC (ISPECL [`p:real list`;`z:real`;`X:real`] POLY_MVT); ASM_REWRITE_TAC[]; DISCH_THEN (X_CHOOSE_TAC `M:real`); POP_ASSUM MP_TAC THEN STRIP_TAC; CLAIM `&0 < &0 - poly p z`; LABEL_ALL_TAC; USE_THEN "Z-9" MP_TAC; REAL_ARITH_TAC; STRIP_TAC; CLAIM `&0 < X - z`; LABEL_ALL_TAC; USE_THEN "Z-11" MP_TAC THEN REAL_ARITH_TAC; STRIP_TAC; CLAIM `&0 < (X - z) * poly (poly_diff p) M`; POP_ASSUM IGNORE; POP_ASSUM MP_TAC; POP_ASSUM MP_TAC; REAL_ARITH_TAC; REWRITE_TAC[REAL_MUL_GT]; REPEAT STRIP_TAC; POP_ASSUM IGNORE; POP_ASSUM MP_TAC; POP_ASSUM MP_TAC; REAL_ARITH_TAC; CLAIM `N < M`; MATCH_MP_TAC REAL_LT_TRANS; EXISTS_TAC `z`; ASM_REWRITE_TAC[]; STRIP_TAC; MP_TAC (ISPECL [`poly_diff p`;`N:real`;`M:real`] (REWRITE_RULE[real_gt] POLY_IVT_POS)); ASM_REWRITE_TAC[]; DISCH_THEN (X_CHOOSE_TAC `K:real`); POP_ASSUM MP_TAC THEN STRIP_TAC; (* save *) CLAIM `x < K /\ K < y`; STRIP_TAC; MATCH_MP_TAC REAL_LT_TRANS; EXISTS_TAC `N`; ASM_REWRITE_TAC[]; MATCH_MP_TAC REAL_LT_TRANS; EXISTS_TAC `M`; ASM_REWRITE_TAC[]; MATCH_MP_TAC REAL_LT_TRANS; EXISTS_TAC `X`; ASM_REWRITE_TAC[]; ASM_MESON_TAC[]; (* save *) POP_ASSUM (ASSUME_TAC o GSYM); MP_TAC (ISPECL [`p:real list`;`z:real`;`X:real`] POLY_MVT); ASM_REWRITE_TAC[]; REAL_SIMP_TAC; ONCE_REWRITE_TAC[REAL_ARITH `(x:real = y) <=> (y = x)`]; ASM_REWRITE_TAC[REAL_ENTIRE]; DISCH_THEN (X_CHOOSE_TAC `M:real`); POP_ASSUM MP_TAC THEN STRIP_TAC; LABEL_ALL_TAC; POP_ASSUM MP_TAC; USE_THEN "Z-4" MP_TAC THEN REAL_ARITH_TAC; CLAIM `x < M /\ M < y`; STRIP_TAC; MATCH_MP_TAC REAL_LT_TRANS; EXISTS_TAC `z`; ASM_REWRITE_TAC[]; MATCH_MP_TAC REAL_LT_TRANS; EXISTS_TAC `X`; ASM_REWRITE_TAC[]; ASM_MESON_TAC[]; (* save *) REPEAT STRIP_TAC; ONCE_REWRITE_TAC[ARITH_RULE `x < y <=> ~(y < x \/ (x = y))`]; STRIP_TAC; MP_TAC (ISPECL [`p:real list`;`X:real`;`z:real`] POLY_MVT); ASM_REWRITE_TAC[]; DISCH_THEN (X_CHOOSE_TAC `N:real`); POP_ASSUM MP_TAC THEN STRIP_TAC; POP_ASSUM MP_TAC; REAL_SIMP_TAC; STRIP_TAC; CLAIM `&0 < (z - X) * poly (poly_diff p) N`; LABEL_ALL_TAC; USE_THEN "Z-3" MP_TAC; POP_ASSUM MP_TAC THEN REAL_ARITH_TAC; ASM_REWRITE_TAC[REAL_MUL_GT]; REPEAT STRIP_TAC; CLAIM `&0 < z - X`; LABEL_ALL_TAC; USE_THEN "Z-7" MP_TAC THEN REAL_ARITH_TAC; LABEL_ALL_TAC; USE_THEN "Z-1" MP_TAC THEN REAL_ARITH_TAC; (* save *) MP_TAC (ISPECL [`p:real list`;`z:real`;`y:real`] POLY_MVT); LABEL_ALL_TAC; USE_THEN "Z-6" (REWRITE_TAC o list); DISCH_THEN (X_CHOOSE_TAC `M:real`); POP_ASSUM MP_TAC THEN STRIP_TAC; CLAIM `poly p y - poly p z < &0`; LABEL_ALL_TAC; USE_THEN "Z-12" MP_TAC; USE_THEN "Z-5" MP_TAC; REAL_ARITH_TAC; STRIP_TAC; CLAIM `&0 < y - z`; LABEL_ALL_TAC; USE_THEN "Z-6" MP_TAC THEN REAL_ARITH_TAC; STRIP_TAC; CLAIM `(y - z) * poly (poly_diff p) M < &0`; POP_ASSUM IGNORE; POP_ASSUM MP_TAC; POP_ASSUM MP_TAC; REAL_ARITH_TAC; REWRITE_TAC[REAL_MUL_LT]; REPEAT STRIP_TAC; POP_ASSUM IGNORE; POP_ASSUM MP_TAC; POP_ASSUM MP_TAC; REAL_ARITH_TAC; CLAIM `N < M`; MATCH_MP_TAC REAL_LT_TRANS; EXISTS_TAC `z`; ASM_REWRITE_TAC[]; STRIP_TAC; MP_TAC (ISPECL [`poly_diff p`;`N:real`;`M:real`] (REWRITE_RULE[real_gt] POLY_IVT_NEG)); ASM_REWRITE_TAC[]; DISCH_THEN (X_CHOOSE_TAC `K:real`); POP_ASSUM MP_TAC THEN STRIP_TAC; (* save *) CLAIM `x < K /\ K < y`; STRIP_TAC; MATCH_MP_TAC REAL_LT_TRANS; EXISTS_TAC `N`; ASM_REWRITE_TAC[]; MATCH_MP_TAC REAL_LT_TRANS; EXISTS_TAC `X`; ASM_REWRITE_TAC[]; MATCH_MP_TAC REAL_LT_TRANS; EXISTS_TAC `M`; ASM_REWRITE_TAC[]; ASM_MESON_TAC[]; (* save *) MP_TAC (ISPECL [`p:real list`;`X:real`;`z:real`] POLY_MVT); ASM_REWRITE_TAC[]; REAL_SIMP_TAC; ONCE_REWRITE_TAC[REAL_ARITH `(x:real = y) <=> (y = x)`]; ASM_REWRITE_TAC[REAL_ENTIRE]; DISCH_THEN (X_CHOOSE_TAC `M:real`); POP_ASSUM MP_TAC THEN STRIP_TAC; LABEL_ALL_TAC; POP_ASSUM MP_TAC; USE_THEN "Z-5" MP_TAC THEN REAL_ARITH_TAC; CLAIM `x < M /\ M < y`; STRIP_TAC; MATCH_MP_TAC REAL_LT_TRANS; EXISTS_TAC `X`; ASM_REWRITE_TAC[]; MATCH_MP_TAC REAL_LT_TRANS; EXISTS_TAC `z`; ASM_REWRITE_TAC[]; ASM_MESON_TAC[]; ]);;
(* }}} *)
let pos_neg_neq_thm2 = 
prove_by_refinement( `!x y p. x < y ==> poly p x > &0 ==> poly p y < &0 ==> (!z. x < z /\ z < y ==> ~(poly (poly_diff p) z = &0)) ==> ?X. x < X /\ X < y /\ (!z. (z = X) ==> (poly p z = &0)) /\ (!z. x < z /\ z < X ==> poly p z > &0) /\ (!z. X < z /\ z < y ==> poly p z < &0)`,
(* {{{ Proof *) [ REWRITE_TAC[real_gt]; REPEAT STRIP_TAC; MP_TAC (ISPECL[`x:real`;`y:real`;`p:real list`] pos_neg_neq_thm); ASM_REWRITE_TAC[]; REPEAT STRIP_TAC; EXISTS_TAC `X`; ASM_MESON_TAC[]; ]);;
(* }}} *)
let neg_pos_neq_thm = 
prove_by_refinement( `!x y p. x < y /\ poly p x < &0 /\ &0 < poly p y /\ (!z. x < z /\ z < y ==> ~(poly (poly_diff p) z = &0)) ==> ?X. x < X /\ X < y /\ (poly p X = &0) /\ (!z. x < z /\ z < X ==> poly p z < &0) /\ (!z. X < z /\ z < y ==> &0 < poly p z)`,
(* {{{ Proof *) [ REPEAT STRIP_TAC; MP_TAC (ISPECL [`p:real list`;`x:real`;`y:real`] POLY_IVT_POS); REWRITE_TAC[real_gt]; ASM_REWRITE_TAC[]; DISCH_THEN (X_CHOOSE_TAC `X:real`); POP_ASSUM MP_TAC THEN STRIP_TAC; EXISTS_TAC `X`; ASM_REWRITE_TAC[]; STRIP_TAC; REPEAT STRIP_TAC; (* save *) ONCE_REWRITE_TAC[ARITH_RULE `x < y <=> ~(y < x \/ (x = y))`]; STRIP_TAC; MP_TAC (ISPECL [`p:real list`;`x:real`;`z:real`] POLY_MVT); ASM_REWRITE_TAC[]; DISCH_THEN (X_CHOOSE_TAC `N:real`); POP_ASSUM MP_TAC THEN STRIP_TAC; CLAIM `&0 < poly p z - poly p x`; LABEL_ALL_TAC; USE_THEN "Z-3" MP_TAC; USE_THEN "Z-11" MP_TAC; REAL_ARITH_TAC; STRIP_TAC; CLAIM `&0 < (z - x) * poly (poly_diff p) N`; REPEAT_N 2 (POP_ASSUM MP_TAC) THEN REAL_ARITH_TAC; ASM_REWRITE_TAC[REAL_MUL_GT]; REPEAT STRIP_TAC; CLAIM `&0 < z - x`; LABEL_ALL_TAC; USE_THEN "Z-8" MP_TAC THEN REAL_ARITH_TAC; LABEL_ALL_TAC; USE_THEN "Z-1" MP_TAC THEN REAL_ARITH_TAC; (* save *) MP_TAC (ISPECL [`p:real list`;`z:real`;`X:real`] POLY_MVT); ASM_REWRITE_TAC[]; DISCH_THEN (X_CHOOSE_TAC `M:real`); POP_ASSUM MP_TAC THEN STRIP_TAC; CLAIM `&0 - poly p z < &0`; LABEL_ALL_TAC; USE_THEN "Z-9" MP_TAC; REAL_ARITH_TAC; STRIP_TAC; CLAIM `&0 < X - z`; LABEL_ALL_TAC; USE_THEN "Z-11" MP_TAC THEN REAL_ARITH_TAC; STRIP_TAC; CLAIM `(X - z) * poly (poly_diff p) M < &0`; POP_ASSUM IGNORE; POP_ASSUM MP_TAC; POP_ASSUM MP_TAC; REAL_ARITH_TAC; REWRITE_TAC[REAL_MUL_LT]; REPEAT STRIP_TAC; POP_ASSUM IGNORE; POP_ASSUM MP_TAC; POP_ASSUM MP_TAC; REAL_ARITH_TAC; CLAIM `N < M`; MATCH_MP_TAC REAL_LT_TRANS; EXISTS_TAC `z`; ASM_REWRITE_TAC[]; STRIP_TAC; MP_TAC (ISPECL [`poly_diff p`;`N:real`;`M:real`] (REWRITE_RULE[real_gt] POLY_IVT_NEG)); ASM_REWRITE_TAC[]; DISCH_THEN (X_CHOOSE_TAC `K:real`); POP_ASSUM MP_TAC THEN STRIP_TAC; (* save *) CLAIM `x < K /\ K < y`; STRIP_TAC; MATCH_MP_TAC REAL_LT_TRANS; EXISTS_TAC `N`; ASM_REWRITE_TAC[]; MATCH_MP_TAC REAL_LT_TRANS; EXISTS_TAC `M`; ASM_REWRITE_TAC[]; MATCH_MP_TAC REAL_LT_TRANS; EXISTS_TAC `X`; ASM_REWRITE_TAC[]; ASM_MESON_TAC[]; (* save *) MP_TAC (ISPECL [`p:real list`;`z:real`;`X:real`] POLY_MVT); ASM_REWRITE_TAC[]; REAL_SIMP_TAC; ONCE_REWRITE_TAC[REAL_ARITH `(x:real = y) <=> (y = x)`]; ASM_REWRITE_TAC[REAL_ENTIRE]; DISCH_THEN (X_CHOOSE_TAC `M:real`); POP_ASSUM MP_TAC THEN STRIP_TAC; LABEL_ALL_TAC; POP_ASSUM MP_TAC; USE_THEN "Z-4" MP_TAC THEN REAL_ARITH_TAC; CLAIM `x < M /\ M < y`; STRIP_TAC; MATCH_MP_TAC REAL_LT_TRANS; EXISTS_TAC `z`; ASM_REWRITE_TAC[]; MATCH_MP_TAC REAL_LT_TRANS; EXISTS_TAC `X`; ASM_REWRITE_TAC[]; ASM_MESON_TAC[]; (* save *) REPEAT STRIP_TAC; ONCE_REWRITE_TAC[ARITH_RULE `x < y <=> ~(y < x \/ (x = y))`]; STRIP_TAC; MP_TAC (ISPECL [`p:real list`;`X:real`;`z:real`] POLY_MVT); ASM_REWRITE_TAC[]; DISCH_THEN (X_CHOOSE_TAC `N:real`); POP_ASSUM MP_TAC THEN STRIP_TAC; POP_ASSUM MP_TAC; REAL_SIMP_TAC; STRIP_TAC; CLAIM `(z - X) * poly (poly_diff p) N < &0`; LABEL_ALL_TAC; USE_THEN "Z-3" MP_TAC; POP_ASSUM MP_TAC THEN REAL_ARITH_TAC; ASM_REWRITE_TAC[REAL_MUL_LT]; REPEAT STRIP_TAC; CLAIM `&0 < z - X`; LABEL_ALL_TAC; USE_THEN "Z-7" MP_TAC THEN REAL_ARITH_TAC; LABEL_ALL_TAC; USE_THEN "Z-1" MP_TAC THEN REAL_ARITH_TAC; (* save *) MP_TAC (ISPECL [`p:real list`;`z:real`;`y:real`] POLY_MVT); LABEL_ALL_TAC; USE_THEN "Z-6" (REWRITE_TAC o list); DISCH_THEN (X_CHOOSE_TAC `M:real`); POP_ASSUM MP_TAC THEN STRIP_TAC; CLAIM `&0 < poly p y - poly p z`; LABEL_ALL_TAC; USE_THEN "Z-12" MP_TAC; USE_THEN "Z-5" MP_TAC; REAL_ARITH_TAC; STRIP_TAC; CLAIM `&0 < y - z`; LABEL_ALL_TAC; USE_THEN "Z-6" MP_TAC THEN REAL_ARITH_TAC; STRIP_TAC; CLAIM `&0 < (y - z) * poly (poly_diff p) M`; POP_ASSUM IGNORE; POP_ASSUM MP_TAC; POP_ASSUM MP_TAC; REAL_ARITH_TAC; REWRITE_TAC[REAL_MUL_GT]; REPEAT STRIP_TAC; POP_ASSUM IGNORE; POP_ASSUM MP_TAC; POP_ASSUM MP_TAC; REAL_ARITH_TAC; CLAIM `N < M`; MATCH_MP_TAC REAL_LT_TRANS; EXISTS_TAC `z`; ASM_REWRITE_TAC[]; STRIP_TAC; MP_TAC (ISPECL [`poly_diff p`;`N:real`;`M:real`] (REWRITE_RULE[real_gt] POLY_IVT_POS)); ASM_REWRITE_TAC[]; DISCH_THEN (X_CHOOSE_TAC `K:real`); POP_ASSUM MP_TAC THEN STRIP_TAC; (* save *) CLAIM `x < K /\ K < y`; STRIP_TAC; MATCH_MP_TAC REAL_LT_TRANS; EXISTS_TAC `N`; ASM_REWRITE_TAC[]; MATCH_MP_TAC REAL_LT_TRANS; EXISTS_TAC `X`; ASM_REWRITE_TAC[]; MATCH_MP_TAC REAL_LT_TRANS; EXISTS_TAC `M`; ASM_REWRITE_TAC[]; ASM_MESON_TAC[]; (* save *) POP_ASSUM (ASSUME_TAC o GSYM); MP_TAC (ISPECL [`p:real list`;`X:real`;`z:real`] POLY_MVT); ASM_REWRITE_TAC[]; REAL_SIMP_TAC; ONCE_REWRITE_TAC[REAL_ARITH `(x:real = y) <=> (y = x)`]; ASM_REWRITE_TAC[REAL_ENTIRE]; DISCH_THEN (X_CHOOSE_TAC `M:real`); POP_ASSUM MP_TAC THEN STRIP_TAC; LABEL_ALL_TAC; POP_ASSUM MP_TAC; USE_THEN "Z-5" MP_TAC THEN REAL_ARITH_TAC; CLAIM `x < M /\ M < y`; STRIP_TAC; MATCH_MP_TAC REAL_LT_TRANS; EXISTS_TAC `X`; ASM_REWRITE_TAC[]; MATCH_MP_TAC REAL_LT_TRANS; EXISTS_TAC `z`; ASM_REWRITE_TAC[]; ASM_MESON_TAC[]; ]);;
(* }}} *)
let neg_pos_neq_thm2 = 
prove_by_refinement( `!x y p. x < y ==> poly p x < &0 ==> poly p y > &0 ==> (!z. x < z /\ z < y ==> ~(poly (poly_diff p) z = &0)) ==> ?X. x < X /\ X < y /\ (!z. (z = X) ==> (poly p z = &0)) /\ (!z. x < z /\ z < X ==> poly p z < &0) /\ (!z. X < z /\ z < y ==> poly p z > &0)`,
(* {{{ Proof *) [ REWRITE_TAC[real_gt]; REPEAT STRIP_TAC; MP_TAC (ISPECL[`x:real`;`y:real`;`p:real list`] neg_pos_neq_thm); ASM_REWRITE_TAC[]; REPEAT STRIP_TAC; EXISTS_TAC `X`; ASM_MESON_TAC[]; ]);;
(* }}} *)
let lt_nz_thm = 
prove_by_refinement( `(!x. x1 < x /\ x < x2 ==> poly p x < &0) ==> (!x. x1 < x /\ x < x2 ==> ~(poly p x = &0))`,
(* {{{ Proof *) [ MESON_TAC[REAL_LT_NZ]; ]);;
(* }}} *)
let gt_nz_thm = 
prove_by_refinement( `(!x. x1 < x /\ x < x2 ==> poly p x > &0) ==> (!x. x1 < x /\ x < x2 ==> ~(poly p x = &0))`,
(* {{{ Proof *) [ MESON_TAC[REAL_LT_NZ;real_gt]; ]);;
(* }}} *)
let eq_eq_false_thm = 
prove_by_refinement( `!x y p. x < y ==> (poly p x = &0) ==> (poly p y = &0) ==> (!z. x < z /\ z < y ==> ~(poly (poly_diff p) z = &0)) ==> F`,
(* {{{ Proof *) [ REPEAT_N 3 STRIP_TAC; DISCH_THEN (fun x -> MP_TAC (MATCH_MP (ISPEC `p:real list` POLY_MVT) x) THEN ASSUME_TAC x); REPEAT STRIP_TAC; LABEL_ALL_TAC; CLAIM `poly p y - poly p x = &0`; REWRITE_TAC[real_sub]; ASM_REWRITE_TAC[]; REAL_ARITH_TAC; DISCH_THEN (REWRITE_ASSUMS o list); CLAIM `&0 < y - x`; USE_THEN "Z-6" MP_TAC THEN REAL_ARITH_TAC; POP_ASSUM (MP_TAC o ISPEC `x':real`); RULE_ASSUM_TAC GSYM; POP_ASSUM IGNORE THEN POP_ASSUM IGNORE; ASM_REWRITE_TAC[]; STRIP_TAC; STRIP_TAC; ASM_MESON_TAC[REAL_ENTIRE;REAL_POS_NZ]; ]);;
(* }}} *)
let neg_zero_neg_thm = 
prove_by_refinement( `!x y p. x < y ==> poly p x < &0 ==> (poly p y = &0) ==> (!z. x < z /\ z < y ==> ~(poly (poly_diff p) z = &0)) ==> (!z. x < z /\ z < y ==> poly p z < &0)`,
(* {{{ Proof *) [ REPEAT STRIP_TAC; REWRITE_TAC[ARITH_RULE `x < y <=> ~(y <= x)`]; REWRITE_TAC[ARITH_RULE `x <= y <=> (x < y \/ (x = y))`]; STRIP_TAC; MP_TAC (ISPECL [`p:real list`;`x:real`;`z:real`] POLY_MVT); ASM_REWRITE_TAC[]; STRIP_TAC; CLAIM `poly p z - poly p x > &0`; LABEL_ALL_TAC; USE_THEN "Z-3" MP_TAC; USE_THEN "Z-8" MP_TAC; REAL_ARITH_TAC; STRIP_TAC; CLAIM `(z - x) * poly (poly_diff p) x' > &0`; REPEAT_N 2 (POP_ASSUM MP_TAC) THEN REAL_ARITH_TAC; REWRITE_TAC[real_gt]; ASM_REWRITE_TAC[REAL_MUL_GT]; REPEAT STRIP_TAC; CLAIM `&0 < z - x`; LABEL_ALL_TAC; USE_THEN "Z-8" MP_TAC THEN REAL_ARITH_TAC; STRIP_TAC; CLAIM `(z - x) * poly (poly_diff p) x' < &0`; REWRITE_TAC[REAL_MUL_LT]; DISJ2_TAC; ASM_REWRITE_TAC[]; ASM_MESON_TAC[REAL_LT_ANTISYM]; (* save *) MP_TAC (ISPECL [`p:real list`;`z:real`;`y:real`] POLY_MVT); ASM_REWRITE_TAC[]; STRIP_TAC; CLAIM `&0 - poly p z < &0`; LABEL_ALL_TAC; USE_THEN "Z-9" MP_TAC; REAL_ARITH_TAC; STRIP_TAC; CLAIM `&0 < y - z`; LABEL_ALL_TAC; USE_THEN "Z-11" MP_TAC THEN REAL_ARITH_TAC; STRIP_TAC; CLAIM `(y - z) * poly (poly_diff p) x'' < &0`; POP_ASSUM IGNORE; POP_ASSUM MP_TAC; POP_ASSUM MP_TAC; REAL_ARITH_TAC; ASM_REWRITE_TAC[REAL_MUL_LT]; REPEAT STRIP_TAC; REPEAT_N 3 (POP_ASSUM MP_TAC); REAL_ARITH_TAC; (* save *) CLAIM `x' < x''`; MATCH_MP_TAC REAL_LT_TRANS; EXISTS_TAC `z`; ASM_REWRITE_TAC[]; STRIP_TAC; MP_TAC (ISPECL [`poly_diff p`;`x':real`;`x'':real`] (REWRITE_RULE[real_gt] POLY_IVT_NEG)); REWRITE_ASSUMS[real_gt]; ASM_REWRITE_TAC[]; STRIP_TAC; CLAIM `x < x''' /\ x''' < y`; STRIP_TAC; MATCH_MP_TAC REAL_LT_TRANS; EXISTS_TAC `x'`; ASM_REWRITE_TAC[]; MATCH_MP_TAC REAL_LT_TRANS; EXISTS_TAC `x''`; ASM_REWRITE_TAC[]; ASM_MESON_TAC[]; (* save *) MP_TAC (ISPECL[`z:real`;`y:real`;`p:real list`] eq_eq_false_thm); POP_ASSUM (ASSUME_TAC o GSYM); ASM_REWRITE_TAC[]; REPEAT_N 2 STRIP_TAC; FIRST_ASSUM MATCH_MP_TAC; ASM_REWRITE_TAC[]; MATCH_MP_TAC REAL_LT_TRANS; EXISTS_TAC `z`; ASM_REWRITE_TAC[]; ]);;
(* }}} *)
let pos_zero_pos_thm = 
prove_by_refinement( `!x y p. x < y ==> poly p x > &0 ==> (poly p y = &0) ==> (!z. x < z /\ z < y ==> ~(poly (poly_diff p) z = &0)) ==> (!z. x < z /\ z < y ==> poly p z > &0)`,
(* {{{ Proof *) [ REPEAT STRIP_TAC; REWRITE_TAC[ARITH_RULE `x > y <=> ~(y >= x)`]; REWRITE_TAC[ARITH_RULE `x >= y <=> (x > y \/ (x = y))`]; STRIP_TAC; MP_TAC (ISPECL [`p:real list`;`x:real`;`z:real`] POLY_MVT); ASM_REWRITE_TAC[]; STRIP_TAC; CLAIM `poly p z - poly p x < &0`; LABEL_ALL_TAC; USE_THEN "Z-3" MP_TAC; USE_THEN "Z-8" MP_TAC; REAL_ARITH_TAC; STRIP_TAC; CLAIM `(z - x) * poly (poly_diff p) x' < &0`; REPEAT_N 2 (POP_ASSUM MP_TAC) THEN REAL_ARITH_TAC; REWRITE_TAC[real_gt]; ASM_REWRITE_TAC[REAL_MUL_LT]; REPEAT STRIP_TAC; CLAIM `&0 < z - x`; LABEL_ALL_TAC; USE_THEN "Z-8" MP_TAC THEN REAL_ARITH_TAC; STRIP_TAC; CLAIM `&0 < (z - x) * poly (poly_diff p) x'`; REWRITE_TAC[REAL_MUL_GT]; DISJ2_TAC; ASM_REWRITE_TAC[]; ASM_MESON_TAC[REAL_LT_ANTISYM]; (* save *) MP_TAC (ISPECL [`p:real list`;`z:real`;`y:real`] POLY_MVT); ASM_REWRITE_TAC[]; STRIP_TAC; CLAIM `&0 - poly p z > &0`; LABEL_ALL_TAC; USE_THEN "Z-9" MP_TAC; REAL_ARITH_TAC; STRIP_TAC; CLAIM `&0 < y - z`; LABEL_ALL_TAC; USE_THEN "Z-11" MP_TAC THEN REAL_ARITH_TAC; STRIP_TAC; CLAIM `(y - z) * poly (poly_diff p) x'' > &0`; POP_ASSUM IGNORE; POP_ASSUM MP_TAC; POP_ASSUM MP_TAC; REAL_ARITH_TAC; ASM_REWRITE_TAC[REAL_MUL_GT;REAL_MUL_LT;real_gt;]; REPEAT STRIP_TAC; REPEAT_N 3 (POP_ASSUM MP_TAC); REAL_ARITH_TAC; (* save *) CLAIM `x' < x''`; MATCH_MP_TAC REAL_LT_TRANS; EXISTS_TAC `z`; ASM_REWRITE_TAC[]; STRIP_TAC; MP_TAC (ISPECL [`poly_diff p`;`x':real`;`x'':real`] (REWRITE_RULE[real_gt] POLY_IVT_POS)); REWRITE_ASSUMS[real_gt]; ASM_REWRITE_TAC[]; STRIP_TAC; CLAIM `x < x''' /\ x''' < y`; STRIP_TAC; MATCH_MP_TAC REAL_LT_TRANS; EXISTS_TAC `x'`; ASM_REWRITE_TAC[]; MATCH_MP_TAC REAL_LT_TRANS; EXISTS_TAC `x''`; ASM_REWRITE_TAC[]; ASM_MESON_TAC[]; (* save *) MP_TAC (ISPECL[`z:real`;`y:real`;`p:real list`] eq_eq_false_thm); POP_ASSUM (ASSUME_TAC o GSYM); ASM_REWRITE_TAC[]; REPEAT_N 2 STRIP_TAC; FIRST_ASSUM MATCH_MP_TAC; ASM_REWRITE_TAC[]; MATCH_MP_TAC REAL_LT_TRANS; EXISTS_TAC `z`; ASM_REWRITE_TAC[]; ]);;
(* }}} *)
let zero_neg_neg_thm = 
prove_by_refinement( `!x y p. x < y ==> (poly p x = &0) ==> (poly p y < &0) ==> (!z. x < z /\ z < y ==> ~(poly (poly_diff p) z = &0)) ==> (!z. x < z /\ z < y ==> poly p z < &0)`,
(* {{{ Proof *) [ REPEAT STRIP_TAC; REWRITE_TAC[ARITH_RULE `x < y <=> ~(y <= x)`]; REWRITE_TAC[ARITH_RULE `x <= y <=> (x < y \/ (x = y))`]; STRIP_TAC; MP_TAC (ISPECL [`p:real list`;`x:real`;`z:real`] POLY_MVT); ASM_REWRITE_TAC[]; STRIP_TAC; CLAIM `poly p z - &0 > &0`; LABEL_ALL_TAC; USE_THEN "Z-3" MP_TAC; USE_THEN "Z-8" MP_TAC; REAL_ARITH_TAC; STRIP_TAC; CLAIM `(z - x) * poly (poly_diff p) x' > &0`; REPEAT_N 2 (POP_ASSUM MP_TAC) THEN REAL_ARITH_TAC; REWRITE_TAC[real_gt]; ASM_REWRITE_TAC[REAL_MUL_LT;REAL_MUL_GT;]; REPEAT STRIP_TAC; CLAIM `&0 < z - x`; LABEL_ALL_TAC; USE_THEN "Z-8" MP_TAC THEN REAL_ARITH_TAC; STRIP_TAC; CLAIM `&0 > (z - x) * poly (poly_diff p) x'`; REWRITE_TAC[REAL_MUL_GT;real_gt;REAL_MUL_LT;]; DISJ2_TAC; ASM_REWRITE_TAC[]; ASM_MESON_TAC[REAL_LT_ANTISYM]; (* save *) MP_TAC (ISPECL [`p:real list`;`z:real`;`y:real`] POLY_MVT); ASM_REWRITE_TAC[]; STRIP_TAC; CLAIM `poly p y - poly p z < &0`; LABEL_ALL_TAC; USE_THEN "Z-13" MP_TAC; USE_THEN "Z-9" MP_TAC; REAL_ARITH_TAC; STRIP_TAC; CLAIM `&0 < y - z`; LABEL_ALL_TAC; USE_THEN "Z-11" MP_TAC THEN REAL_ARITH_TAC; STRIP_TAC; CLAIM `(y - z) * poly (poly_diff p) x'' < &0`; POP_ASSUM IGNORE; POP_ASSUM MP_TAC; POP_ASSUM MP_TAC; REAL_ARITH_TAC; ASM_REWRITE_TAC[REAL_MUL_GT;REAL_MUL_LT;real_gt;]; REPEAT STRIP_TAC; REPEAT_N 3 (POP_ASSUM MP_TAC); REAL_ARITH_TAC; (* save *) CLAIM `x' < x''`; MATCH_MP_TAC REAL_LT_TRANS; EXISTS_TAC `z`; ASM_REWRITE_TAC[]; STRIP_TAC; MP_TAC (ISPECL [`poly_diff p`;`x':real`;`x'':real`] (REWRITE_RULE[real_gt] POLY_IVT_NEG)); REWRITE_ASSUMS[real_gt]; ASM_REWRITE_TAC[]; STRIP_TAC; CLAIM `x < x''' /\ x''' < y`; STRIP_TAC; MATCH_MP_TAC REAL_LT_TRANS; EXISTS_TAC `x'`; ASM_REWRITE_TAC[]; MATCH_MP_TAC REAL_LT_TRANS; EXISTS_TAC `x''`; ASM_REWRITE_TAC[]; ASM_MESON_TAC[]; (* save *) MP_TAC (ISPECL[`x:real`;`z:real`;`p:real list`] eq_eq_false_thm); POP_ASSUM (ASSUME_TAC o GSYM); ASM_REWRITE_TAC[]; REPEAT_N 2 STRIP_TAC; FIRST_ASSUM MATCH_MP_TAC; ASM_REWRITE_TAC[]; MATCH_MP_TAC REAL_LT_TRANS; EXISTS_TAC `z`; ASM_REWRITE_TAC[]; ]);;
(* }}} *)
let zero_pos_pos_thm = 
prove_by_refinement( `!x y p. x < y ==> (poly p x = &0) ==> (poly p y > &0) ==> (!z. x < z /\ z < y ==> ~(poly (poly_diff p) z = &0)) ==> (!z. x < z /\ z < y ==> poly p z > &0)`,
(* {{{ Proof *) [ REPEAT STRIP_TAC; REWRITE_TAC[ARITH_RULE `x > y <=> ~(y >= x)`]; REWRITE_TAC[ARITH_RULE `x >= y <=> (x > y \/ (x = y))`]; STRIP_TAC; MP_TAC (ISPECL [`p:real list`;`z:real`;`y:real`] POLY_MVT); ASM_REWRITE_TAC[]; STRIP_TAC; CLAIM `poly p y - poly p z > &0`; LABEL_ALL_TAC; USE_THEN "Z-7" MP_TAC; USE_THEN "Z-3" MP_TAC; REAL_ARITH_TAC; STRIP_TAC; CLAIM `(y - z) * poly (poly_diff p) x' > &0`; REPEAT_N 2 (POP_ASSUM MP_TAC) THEN REAL_ARITH_TAC; REWRITE_TAC[real_gt]; ASM_REWRITE_TAC[REAL_MUL_LT;REAL_MUL_GT;]; REPEAT STRIP_TAC; LABEL_ALL_TAC; USE_THEN "Z-1" MP_TAC; USE_THEN "Z-7" MP_TAC; REAL_ARITH_TAC; (* save *) MP_TAC (ISPECL [`p:real list`;`x:real`;`z:real`] POLY_MVT); ASM_REWRITE_TAC[]; STRIP_TAC; CLAIM `poly p z - &0 < &0`; LABEL_ALL_TAC; USE_THEN "Z-9" MP_TAC; REAL_ARITH_TAC; STRIP_TAC; CLAIM `&0 < z - x`; LABEL_ALL_TAC; USE_THEN "Z-12" MP_TAC THEN REAL_ARITH_TAC; STRIP_TAC; CLAIM `(z - x) * poly (poly_diff p) x'' < &0`; POP_ASSUM IGNORE; POP_ASSUM MP_TAC; POP_ASSUM MP_TAC; REAL_ARITH_TAC; ASM_REWRITE_TAC[REAL_MUL_GT;REAL_MUL_LT;real_gt;]; REPEAT STRIP_TAC; REPEAT_N 3 (POP_ASSUM MP_TAC); REAL_ARITH_TAC; (* save *) CLAIM `x'' < x'`; MATCH_MP_TAC REAL_LT_TRANS; EXISTS_TAC `z`; ASM_REWRITE_TAC[]; STRIP_TAC; MP_TAC (ISPECL [`poly_diff p`;`x'':real`;`x':real`] (REWRITE_RULE[real_gt] POLY_IVT_POS)); REWRITE_ASSUMS[real_gt]; ASM_REWRITE_TAC[]; STRIP_TAC; CLAIM `x < x''' /\ x''' < y`; STRIP_TAC; MATCH_MP_TAC REAL_LT_TRANS; EXISTS_TAC `x''`; ASM_REWRITE_TAC[]; MATCH_MP_TAC REAL_LT_TRANS; EXISTS_TAC `x'`; ASM_REWRITE_TAC[]; ASM_MESON_TAC[]; (* save *) MP_TAC (ISPECL[`x:real`;`z:real`;`p:real list`] eq_eq_false_thm); POP_ASSUM (ASSUME_TAC o GSYM); ASM_REWRITE_TAC[]; REPEAT_N 2 STRIP_TAC; FIRST_ASSUM MATCH_MP_TAC; ASM_REWRITE_TAC[]; MATCH_MP_TAC REAL_LT_TRANS; EXISTS_TAC `z`; ASM_REWRITE_TAC[]; ]);;
(* }}} *)