aboutsummaryrefslogtreecommitdiff
path: root/mathcomp/algebra/ssrnum.v
diff options
context:
space:
mode:
authorEnrico Tassi2015-03-09 11:07:53 +0100
committerEnrico Tassi2015-03-09 11:24:38 +0100
commitfc84c27eac260dffd8f2fb1cb56d599f1e3486d9 (patch)
treec16205f1637c80833a4c4598993c29fa0fd8c373 /mathcomp/algebra/ssrnum.v
Initial commit
Diffstat (limited to 'mathcomp/algebra/ssrnum.v')
-rw-r--r--mathcomp/algebra/ssrnum.v4219
1 files changed, 4219 insertions, 0 deletions
diff --git a/mathcomp/algebra/ssrnum.v b/mathcomp/algebra/ssrnum.v
new file mode 100644
index 0000000..ab7afd0
--- /dev/null
+++ b/mathcomp/algebra/ssrnum.v
@@ -0,0 +1,4219 @@
+(* (c) Copyright Microsoft Corporation and Inria. All rights reserved. *)
+Require Import ssreflect ssrfun ssrbool eqtype ssrnat seq div choice fintype.
+Require Import bigop ssralg finset fingroup zmodp poly.
+
+(******************************************************************************)
+(* *)
+(* This file defines some classes to manipulate number structures, i.e *)
+(* structures with an order and a norm *)
+(* *)
+(* * NumDomain (Integral domain with an order and a norm) *)
+(* NumMixin == the mixin that provides an order and a norm over *)
+(* a ring and their characteristic properties. *)
+(* numDomainType == interface for a num integral domain. *)
+(* NumDomainType T m *)
+(* == packs the num mixin into a numberDomainType. The *)
+(* carrier T must have a integral domain structure. *)
+(* [numDomainType of T for S ] *)
+(* == T-clone of the numDomainType structure S. *)
+(* [numDomainType of T] *)
+(* == clone of a canonical numDomainType structure on T. *)
+(* *)
+(* * NumField (Field with an order and a norm) *)
+(* numFieldType == interface for a num field. *)
+(* [numFieldType of T] *)
+(* == clone of a canonical numFieldType structure on T *)
+(* *)
+(* * NumClosedField (Closed Field with an order and a norm) *)
+(* numClosedFieldType *)
+(* == interface for a num closed field. *)
+(* [numClosedFieldType of T] *)
+(* == clone of a canonical numClosedFieldType structure on T *)
+(* *)
+(* * RealDomain (Num domain where all elements are positive or negative) *)
+(* realDomainType == interface for a real integral domain. *)
+(* RealDomainType T r *)
+(* == packs the real axiom r into a realDomainType. The *)
+(* carrier T must have a num domain structure. *)
+(* [realDomainType of T for S ] *)
+(* == T-clone of the realDomainType structure S. *)
+(* [realDomainType of T] *)
+(* == clone of a canonical realDomainType structure on T. *)
+(* *)
+(* * RealField (Num Field where all elements are positive or negative) *)
+(* realFieldType == interface for a real field. *)
+(* [realFieldType of T] *)
+(* == clone of a canonical realFieldType structure on T *)
+(* *)
+(* * ArchiField (A Real Field with the archimedean axiom) *)
+(* archiFieldType == interface for an archimedean field. *)
+(* ArchiFieldType T r *)
+(* == packs the archimeadean axiom r into an archiFieldType. *)
+(* The carrier T must have a real field type structure. *)
+(* [archiFieldType of T for S ] *)
+(* == T-clone of the archiFieldType structure S. *)
+(* [archiFieldType of T] *)
+(* == clone of a canonical archiFieldType structure on T *)
+(* *)
+(* * RealClosedField (Real Field with the real closed axiom) *)
+(* realClosedFieldType *)
+(* == interface for a real closed field. *)
+(* RealClosedFieldType T r *)
+(* == packs the real closed axiom r into a *)
+(* realClodedFieldType. The carrier T must have a real *)
+(* field type structure. *)
+(* [realClosedFieldType of T for S ] *)
+(* == T-clone of the realClosedFieldType structure S. *)
+(* [realClosedFieldype of T] *)
+(* == clone of a canonical realClosedFieldType structure on *)
+(* T. *)
+(* *)
+(* Over these structures, we have the following operations *)
+(* `|x| == norm of x. *)
+(* x <= y <=> x is less than or equal to y (:= '|y - x| == y - x). *)
+(* x < y <=> x is less than y (:= (x <= y) && (x != y)). *)
+(* x <= y ?= iff C <-> x is less than y, or equal iff C is true. *)
+(* Num.sg x == sign of x: equal to 0 iff x = 0, to 1 iff x > 0, and *)
+(* to -1 in all other cases (including x < 0). *)
+(* x \is a Num.pos <=> x is positive (:= x > 0). *)
+(* x \is a Num.neg <=> x is negative (:= x < 0). *)
+(* x \is a Num.nneg <=> x is positive or 0 (:= x >= 0). *)
+(* x \is a Num.real <=> x is real (:= x >= 0 or x < 0). *)
+(* Num.min x y == minimum of x y *)
+(* Num.max x y == maximum of x y *)
+(* Num.bound x == in archimedean fields, and upper bound for x, i.e., *)
+(* and n such that `|x| < n%:R. *)
+(* Num.sqrt x == in a real-closed field, a positive square root of x if *)
+(* x >= 0, or 0 otherwise. *)
+(* *)
+(* There are now three distinct uses of the symbols <, <=, > and >=: *)
+(* 0-ary, unary (prefix) and binary (infix). *)
+(* 0. <%R, <=%R, >%R, >=%R stand respectively for lt, le, gt and ge. *)
+(* 1. (< x), (<= x), (> x), (>= x) stand respectively for *)
+(* (gt x), (ge x), (lt x), (le x). *)
+(* So (< x) is a predicate characterizing elements smaller than x. *)
+(* 2. (x < y), (x <= y), ... mean what they are expected to. *)
+(* These convention are compatible with haskell's, *)
+(* where ((< y) x) = (x < y) = ((<) x y), *)
+(* except that we write <%R instead of (<). *)
+(* *)
+(* - list of prefixes : *)
+(* p : positive *)
+(* n : negative *)
+(* sp : strictly positive *)
+(* sn : strictly negative *)
+(* i : interior = in [0, 1] or ]0, 1[ *)
+(* e : exterior = in [1, +oo[ or ]1; +oo[ *)
+(* w : non strict (weak) monotony *)
+(* *)
+(******************************************************************************)
+
+Set Implicit Arguments.
+Unset Strict Implicit.
+Unset Printing Implicit Defensive.
+
+Local Open Scope ring_scope.
+Import GRing.Theory.
+
+Reserved Notation "<= y" (at level 35).
+Reserved Notation ">= y" (at level 35).
+Reserved Notation "< y" (at level 35).
+Reserved Notation "> y" (at level 35).
+Reserved Notation "<= y :> T" (at level 35, y at next level).
+Reserved Notation ">= y :> T" (at level 35, y at next level).
+Reserved Notation "< y :> T" (at level 35, y at next level).
+Reserved Notation "> y :> T" (at level 35, y at next level).
+
+Module Num.
+
+(* Principal mixin; further classes add axioms rather than operations. *)
+Record mixin_of (R : ringType) := Mixin {
+ norm_op : R -> R;
+ le_op : rel R;
+ lt_op : rel R;
+ _ : forall x y, le_op (norm_op (x + y)) (norm_op x + norm_op y);
+ _ : forall x y, lt_op 0 x -> lt_op 0 y -> lt_op 0 (x + y);
+ _ : forall x, norm_op x = 0 -> x = 0;
+ _ : forall x y, le_op 0 x -> le_op 0 y -> le_op x y || le_op y x;
+ _ : {morph norm_op : x y / x * y};
+ _ : forall x y, (le_op x y) = (norm_op (y - x) == y - x);
+ _ : forall x y, (lt_op x y) = (y != x) && (le_op x y)
+}.
+
+Local Notation ring_for T b := (@GRing.Ring.Pack T b T).
+
+(* Base interface. *)
+Module NumDomain.
+
+Section ClassDef.
+
+Record class_of T := Class {
+ base : GRing.IntegralDomain.class_of T;
+ mixin : mixin_of (ring_for T base)
+}.
+Local Coercion base : class_of >-> GRing.IntegralDomain.class_of.
+Structure type := Pack {sort; _ : class_of sort; _ : Type}.
+Local Coercion sort : type >-> Sortclass.
+Variables (T : Type) (cT : type).
+Definition class := let: Pack _ c _ as cT' := cT return class_of cT' in c.
+Let xT := let: Pack T _ _ := cT in T.
+Notation xclass := (class : class_of xT).
+Definition clone c of phant_id class c := @Pack T c T.
+Definition pack b0 (m0 : mixin_of (ring_for T b0)) :=
+ fun bT b & phant_id (GRing.IntegralDomain.class bT) b =>
+ fun m & phant_id m0 m => Pack (@Class T b m) T.
+
+Definition eqType := @Equality.Pack cT xclass xT.
+Definition choiceType := @Choice.Pack cT xclass xT.
+Definition zmodType := @GRing.Zmodule.Pack cT xclass xT.
+Definition ringType := @GRing.Ring.Pack cT xclass xT.
+Definition comRingType := @GRing.ComRing.Pack cT xclass xT.
+Definition unitRingType := @GRing.UnitRing.Pack cT xclass xT.
+Definition comUnitRingType := @GRing.ComUnitRing.Pack cT xclass xT.
+Definition idomainType := @GRing.IntegralDomain.Pack cT xclass xT.
+
+End ClassDef.
+
+Module Exports.
+Coercion base : class_of >-> GRing.IntegralDomain.class_of.
+Coercion mixin : class_of >-> mixin_of.
+Coercion sort : type >-> Sortclass.
+Bind Scope ring_scope with sort.
+Coercion eqType : type >-> Equality.type.
+Canonical eqType.
+Coercion choiceType : type >-> Choice.type.
+Canonical choiceType.
+Coercion zmodType : type >-> GRing.Zmodule.type.
+Canonical zmodType.
+Coercion ringType : type >-> GRing.Ring.type.
+Canonical ringType.
+Coercion comRingType : type >-> GRing.ComRing.type.
+Canonical comRingType.
+Coercion unitRingType : type >-> GRing.UnitRing.type.
+Canonical unitRingType.
+Coercion comUnitRingType : type >-> GRing.ComUnitRing.type.
+Canonical comUnitRingType.
+Coercion idomainType : type >-> GRing.IntegralDomain.type.
+Canonical idomainType.
+Notation numDomainType := type.
+Notation NumMixin := Mixin.
+Notation NumDomainType T m := (@pack T _ m _ _ id _ id).
+Notation "[ 'numDomainType' 'of' T 'for' cT ]" := (@clone T cT _ idfun)
+ (at level 0, format "[ 'numDomainType' 'of' T 'for' cT ]") : form_scope.
+Notation "[ 'numDomainType' 'of' T ]" := (@clone T _ _ id)
+ (at level 0, format "[ 'numDomainType' 'of' T ]") : form_scope.
+End Exports.
+
+End NumDomain.
+Import NumDomain.Exports.
+
+Module Import Def. Section Def.
+Import NumDomain.
+Context {R : type}.
+Implicit Types (x y : R) (C : bool).
+
+Definition normr : R -> R := norm_op (class R).
+Definition ler : rel R := le_op (class R).
+Definition ltr : rel R := lt_op (class R).
+Local Notation "x <= y" := (ler x y) : ring_scope.
+Local Notation "x < y" := (ltr x y) : ring_scope.
+
+Definition ger : simpl_rel R := [rel x y | y <= x].
+Definition gtr : simpl_rel R := [rel x y | y < x].
+Definition lerif x y C : Prop := ((x <= y) * ((x == y) = C))%type.
+Definition sgr x : R := if x == 0 then 0 else if x < 0 then -1 else 1.
+Definition minr x y : R := if x <= y then x else y.
+Definition maxr x y : R := if y <= x then x else y.
+
+Definition Rpos : qualifier 0 R := [qualify x : R | 0 < x].
+Definition Rneg : qualifier 0 R := [qualify x : R | x < 0].
+Definition Rnneg : qualifier 0 R := [qualify x : R | 0 <= x].
+Definition Rreal : qualifier 0 R := [qualify x : R | (0 <= x) || (x <= 0)].
+End Def. End Def.
+
+(* Shorter qualified names, when Num.Def is not imported. *)
+Notation norm := normr.
+Notation le := ler.
+Notation lt := ltr.
+Notation ge := ger.
+Notation gt := gtr.
+Notation sg := sgr.
+Notation max := maxr.
+Notation min := minr.
+Notation pos := Rpos.
+Notation neg := Rneg.
+Notation nneg := Rnneg.
+Notation real := Rreal.
+
+Module Keys. Section Keys.
+Variable R : numDomainType.
+Fact Rpos_key : pred_key (@pos R). Proof. by []. Qed.
+Definition Rpos_keyed := KeyedQualifier Rpos_key.
+Fact Rneg_key : pred_key (@real R). Proof. by []. Qed.
+Definition Rneg_keyed := KeyedQualifier Rneg_key.
+Fact Rnneg_key : pred_key (@nneg R). Proof. by []. Qed.
+Definition Rnneg_keyed := KeyedQualifier Rnneg_key.
+Fact Rreal_key : pred_key (@real R). Proof. by []. Qed.
+Definition Rreal_keyed := KeyedQualifier Rreal_key.
+Definition ler_of_leif x y C (le_xy : @lerif R x y C) := le_xy.1 : le x y.
+End Keys. End Keys.
+
+(* (Exported) symbolic syntax. *)
+Module Import Syntax.
+Import Def Keys.
+
+Notation "`| x |" := (norm x) : ring_scope.
+
+Notation "<%R" := lt : ring_scope.
+Notation ">%R" := gt : ring_scope.
+Notation "<=%R" := le : ring_scope.
+Notation ">=%R" := ge : ring_scope.
+Notation "<?=%R" := lerif : ring_scope.
+
+Notation "< y" := (gt y) : ring_scope.
+Notation "< y :> T" := (< (y : T)) : ring_scope.
+Notation "> y" := (lt y) : ring_scope.
+Notation "> y :> T" := (> (y : T)) : ring_scope.
+
+Notation "<= y" := (ge y) : ring_scope.
+Notation "<= y :> T" := (<= (y : T)) : ring_scope.
+Notation ">= y" := (le y) : ring_scope.
+Notation ">= y :> T" := (>= (y : T)) : ring_scope.
+
+Notation "x < y" := (lt x y) : ring_scope.
+Notation "x < y :> T" := ((x : T) < (y : T)) : ring_scope.
+Notation "x > y" := (y < x) (only parsing) : ring_scope.
+Notation "x > y :> T" := ((x : T) > (y : T)) (only parsing) : ring_scope.
+
+Notation "x <= y" := (le x y) : ring_scope.
+Notation "x <= y :> T" := ((x : T) <= (y : T)) : ring_scope.
+Notation "x >= y" := (y <= x) (only parsing) : ring_scope.
+Notation "x >= y :> T" := ((x : T) >= (y : T)) (only parsing) : ring_scope.
+
+Notation "x <= y <= z" := ((x <= y) && (y <= z)) : ring_scope.
+Notation "x < y <= z" := ((x < y) && (y <= z)) : ring_scope.
+Notation "x <= y < z" := ((x <= y) && (y < z)) : ring_scope.
+Notation "x < y < z" := ((x < y) && (y < z)) : ring_scope.
+
+Notation "x <= y ?= 'iff' C" := (lerif x y C) : ring_scope.
+Notation "x <= y ?= 'iff' C :> R" := ((x : R) <= (y : R) ?= iff C)
+ (only parsing) : ring_scope.
+
+Coercion ler_of_leif : lerif >-> is_true.
+
+Canonical Rpos_keyed.
+Canonical Rneg_keyed.
+Canonical Rnneg_keyed.
+Canonical Rreal_keyed.
+
+End Syntax.
+
+Section ExtensionAxioms.
+
+Variable R : numDomainType.
+
+Definition real_axiom : Prop := forall x : R, x \is real.
+
+Definition archimedean_axiom : Prop := forall x : R, exists ub, `|x| < ub%:R.
+
+Definition real_closed_axiom : Prop :=
+ forall (p : {poly R}) (a b : R),
+ a <= b -> p.[a] <= 0 <= p.[b] -> exists2 x, a <= x <= b & root p x.
+
+End ExtensionAxioms.
+
+Local Notation num_for T b := (@NumDomain.Pack T b T).
+
+(* The rest of the numbers interface hierarchy. *)
+Module NumField.
+
+Section ClassDef.
+
+Record class_of R :=
+ Class { base : GRing.Field.class_of R; mixin : mixin_of (ring_for R base) }.
+Definition base2 R (c : class_of R) := NumDomain.Class (mixin c).
+Local Coercion base : class_of >-> GRing.Field.class_of.
+Local Coercion base2 : class_of >-> NumDomain.class_of.
+
+Structure type := Pack {sort; _ : class_of sort; _ : Type}.
+Local Coercion sort : type >-> Sortclass.
+Variables (T : Type) (cT : type).
+Definition class := let: Pack _ c _ as cT' := cT return class_of cT' in c.
+Let xT := let: Pack T _ _ := cT in T.
+Notation xclass := (class : class_of xT).
+Definition pack :=
+ fun bT b & phant_id (GRing.Field.class bT) (b : GRing.Field.class_of T) =>
+ fun mT m & phant_id (NumDomain.class mT) (@NumDomain.Class T b m) =>
+ Pack (@Class T b m) T.
+
+Definition eqType := @Equality.Pack cT xclass xT.
+Definition choiceType := @Choice.Pack cT xclass xT.
+Definition zmodType := @GRing.Zmodule.Pack cT xclass xT.
+Definition ringType := @GRing.Ring.Pack cT xclass xT.
+Definition comRingType := @GRing.ComRing.Pack cT xclass xT.
+Definition unitRingType := @GRing.UnitRing.Pack cT xclass xT.
+Definition comUnitRingType := @GRing.ComUnitRing.Pack cT xclass xT.
+Definition idomainType := @GRing.IntegralDomain.Pack cT xclass xT.
+Definition numDomainType := @NumDomain.Pack cT xclass xT.
+Definition fieldType := @GRing.Field.Pack cT xclass xT.
+Definition join_numDomainType := @NumDomain.Pack fieldType xclass xT.
+
+End ClassDef.
+
+Module Exports.
+Coercion base : class_of >-> GRing.Field.class_of.
+Coercion base2 : class_of >-> NumDomain.class_of.
+Coercion sort : type >-> Sortclass.
+Bind Scope ring_scope with sort.
+Coercion eqType : type >-> Equality.type.
+Canonical eqType.
+Coercion choiceType : type >-> Choice.type.
+Canonical choiceType.
+Coercion zmodType : type >-> GRing.Zmodule.type.
+Canonical zmodType.
+Coercion ringType : type >-> GRing.Ring.type.
+Canonical ringType.
+Coercion comRingType : type >-> GRing.ComRing.type.
+Canonical comRingType.
+Coercion unitRingType : type >-> GRing.UnitRing.type.
+Canonical unitRingType.
+Coercion comUnitRingType : type >-> GRing.ComUnitRing.type.
+Canonical comUnitRingType.
+Coercion idomainType : type >-> GRing.IntegralDomain.type.
+Canonical idomainType.
+Coercion numDomainType : type >-> NumDomain.type.
+Canonical numDomainType.
+Coercion fieldType : type >-> GRing.Field.type.
+Canonical fieldType.
+Notation numFieldType := type.
+Notation "[ 'numFieldType' 'of' T ]" := (@pack T _ _ id _ _ id)
+ (at level 0, format "[ 'numFieldType' 'of' T ]") : form_scope.
+End Exports.
+
+End NumField.
+Import NumField.Exports.
+
+Module ClosedField.
+
+Section ClassDef.
+
+Record class_of R := Class {
+ base : GRing.ClosedField.class_of R;
+ mixin : mixin_of (ring_for R base)
+}.
+Definition base2 R (c : class_of R) := NumField.Class (mixin c).
+Local Coercion base : class_of >-> GRing.ClosedField.class_of.
+Local Coercion base2 : class_of >-> NumField.class_of.
+
+Structure type := Pack {sort; _ : class_of sort; _ : Type}.
+Local Coercion sort : type >-> Sortclass.
+Variables (T : Type) (cT : type).
+Definition class := let: Pack _ c _ as cT' := cT return class_of cT' in c.
+Let xT := let: Pack T _ _ := cT in T.
+Notation xclass := (class : class_of xT).
+Definition pack :=
+ fun bT b & phant_id (GRing.ClosedField.class bT)
+ (b : GRing.ClosedField.class_of T) =>
+ fun mT m & phant_id (NumField.class mT) (@NumField.Class T b m) =>
+ Pack (@Class T b m) T.
+
+Definition eqType := @Equality.Pack cT xclass xT.
+Definition choiceType := @Choice.Pack cT xclass xT.
+Definition zmodType := @GRing.Zmodule.Pack cT xclass xT.
+Definition ringType := @GRing.Ring.Pack cT xclass xT.
+Definition comRingType := @GRing.ComRing.Pack cT xclass xT.
+Definition unitRingType := @GRing.UnitRing.Pack cT xclass xT.
+Definition comUnitRingType := @GRing.ComUnitRing.Pack cT xclass xT.
+Definition idomainType := @GRing.IntegralDomain.Pack cT xclass xT.
+Definition numDomainType := @NumDomain.Pack cT xclass xT.
+Definition fieldType := @GRing.Field.Pack cT xclass xT.
+Definition decFieldType := @GRing.DecidableField.Pack cT xclass xT.
+Definition closedFieldType := @GRing.ClosedField.Pack cT xclass xT.
+Definition join_dec_numDomainType := @NumDomain.Pack decFieldType xclass xT.
+Definition join_dec_numFieldType := @NumField.Pack decFieldType xclass xT.
+Definition join_numDomainType := @NumDomain.Pack closedFieldType xclass xT.
+Definition join_numFieldType := @NumField.Pack closedFieldType xclass xT.
+
+End ClassDef.
+
+Module Exports.
+Coercion base : class_of >-> GRing.ClosedField.class_of.
+Coercion base2 : class_of >-> NumField.class_of.
+Coercion sort : type >-> Sortclass.
+Bind Scope ring_scope with sort.
+Coercion eqType : type >-> Equality.type.
+Canonical eqType.
+Coercion choiceType : type >-> Choice.type.
+Canonical choiceType.
+Coercion zmodType : type >-> GRing.Zmodule.type.
+Canonical zmodType.
+Coercion ringType : type >-> GRing.Ring.type.
+Canonical ringType.
+Coercion comRingType : type >-> GRing.ComRing.type.
+Canonical comRingType.
+Coercion unitRingType : type >-> GRing.UnitRing.type.
+Canonical unitRingType.
+Coercion comUnitRingType : type >-> GRing.ComUnitRing.type.
+Canonical comUnitRingType.
+Coercion idomainType : type >-> GRing.IntegralDomain.type.
+Canonical idomainType.
+Coercion numDomainType : type >-> NumDomain.type.
+Canonical numDomainType.
+Coercion fieldType : type >-> GRing.Field.type.
+Canonical fieldType.
+Coercion decFieldType : type >-> GRing.DecidableField.type.
+Canonical decFieldType.
+Coercion closedFieldType : type >-> GRing.ClosedField.type.
+Canonical closedFieldType.
+Canonical join_dec_numDomainType.
+Canonical join_dec_numFieldType.
+Canonical join_numDomainType.
+Canonical join_numFieldType.
+Notation numClosedFieldType := type.
+Notation "[ 'numClosedFieldType' 'of' T ]" := (@pack T _ _ id _ _ id)
+ (at level 0, format "[ 'numClosedFieldType' 'of' T ]") : form_scope.
+End Exports.
+
+End ClosedField.
+Import ClosedField.Exports.
+
+Module RealDomain.
+
+Section ClassDef.
+
+Record class_of R :=
+ Class {base : NumDomain.class_of R; _ : @real_axiom (num_for R base)}.
+Local Coercion base : class_of >-> NumDomain.class_of.
+
+Structure type := Pack {sort; _ : class_of sort; _ : Type}.
+Local Coercion sort : type >-> Sortclass.
+Variables (T : Type) (cT : type).
+Definition class := let: Pack _ c _ as cT' := cT return class_of cT' in c.
+Let xT := let: Pack T _ _ := cT in T.
+Notation xclass := (class : class_of xT).
+Definition clone c of phant_id class c := @Pack T c T.
+Definition pack b0 (m0 : real_axiom (num_for T b0)) :=
+ fun bT b & phant_id (NumDomain.class bT) b =>
+ fun m & phant_id m0 m => Pack (@Class T b m) T.
+
+Definition eqType := @Equality.Pack cT xclass xT.
+Definition choiceType := @Choice.Pack cT xclass xT.
+Definition zmodType := @GRing.Zmodule.Pack cT xclass xT.
+Definition ringType := @GRing.Ring.Pack cT xclass xT.
+Definition comRingType := @GRing.ComRing.Pack cT xclass xT.
+Definition unitRingType := @GRing.UnitRing.Pack cT xclass xT.
+Definition comUnitRingType := @GRing.ComUnitRing.Pack cT xclass xT.
+Definition idomainType := @GRing.IntegralDomain.Pack cT xclass xT.
+Definition numDomainType := @NumDomain.Pack cT xclass xT.
+
+End ClassDef.
+
+Module Exports.
+Coercion base : class_of >-> NumDomain.class_of.
+Coercion sort : type >-> Sortclass.
+Bind Scope ring_scope with sort.
+Coercion eqType : type >-> Equality.type.
+Canonical eqType.
+Coercion choiceType : type >-> Choice.type.
+Canonical choiceType.
+Coercion zmodType : type >-> GRing.Zmodule.type.
+Canonical zmodType.
+Coercion ringType : type >-> GRing.Ring.type.
+Canonical ringType.
+Coercion comRingType : type >-> GRing.ComRing.type.
+Canonical comRingType.
+Coercion unitRingType : type >-> GRing.UnitRing.type.
+Canonical unitRingType.
+Coercion comUnitRingType : type >-> GRing.ComUnitRing.type.
+Canonical comUnitRingType.
+Coercion idomainType : type >-> GRing.IntegralDomain.type.
+Canonical idomainType.
+Coercion numDomainType : type >-> NumDomain.type.
+Canonical numDomainType.
+Notation realDomainType := type.
+Notation RealDomainType T m := (@pack T _ m _ _ id _ id).
+Notation "[ 'realDomainType' 'of' T 'for' cT ]" := (@clone T cT _ idfun)
+ (at level 0, format "[ 'realDomainType' 'of' T 'for' cT ]") : form_scope.
+Notation "[ 'realDomainType' 'of' T ]" := (@clone T _ _ id)
+ (at level 0, format "[ 'realDomainType' 'of' T ]") : form_scope.
+End Exports.
+
+End RealDomain.
+Import RealDomain.Exports.
+
+Module RealField.
+
+Section ClassDef.
+
+Record class_of R :=
+ Class { base : NumField.class_of R; mixin : real_axiom (num_for R base) }.
+Definition base2 R (c : class_of R) := RealDomain.Class (@mixin R c).
+Local Coercion base : class_of >-> NumField.class_of.
+Local Coercion base2 : class_of >-> RealDomain.class_of.
+
+Structure type := Pack {sort; _ : class_of sort; _ : Type}.
+Local Coercion sort : type >-> Sortclass.
+Variables (T : Type) (cT : type).
+Definition class := let: Pack _ c _ as cT' := cT return class_of cT' in c.
+Let xT := let: Pack T _ _ := cT in T.
+Notation xclass := (class : class_of xT).
+Definition pack :=
+ fun bT b & phant_id (NumField.class bT) (b : NumField.class_of T) =>
+ fun mT m & phant_id (RealDomain.class mT) (@RealDomain.Class T b m) =>
+ Pack (@Class T b m) T.
+
+Definition eqType := @Equality.Pack cT xclass xT.
+Definition choiceType := @Choice.Pack cT xclass xT.
+Definition zmodType := @GRing.Zmodule.Pack cT xclass xT.
+Definition ringType := @GRing.Ring.Pack cT xclass xT.
+Definition comRingType := @GRing.ComRing.Pack cT xclass xT.
+Definition unitRingType := @GRing.UnitRing.Pack cT xclass xT.
+Definition comUnitRingType := @GRing.ComUnitRing.Pack cT xclass xT.
+Definition idomainType := @GRing.IntegralDomain.Pack cT xclass xT.
+Definition numDomainType := @NumDomain.Pack cT xclass xT.
+Definition realDomainType := @RealDomain.Pack cT xclass xT.
+Definition fieldType := @GRing.Field.Pack cT xclass xT.
+Definition numFieldType := @NumField.Pack cT xclass xT.
+Definition join_realDomainType := @RealDomain.Pack numFieldType xclass xT.
+
+End ClassDef.
+
+Module Exports.
+Coercion base : class_of >-> NumField.class_of.
+Coercion base2 : class_of >-> RealDomain.class_of.
+Coercion sort : type >-> Sortclass.
+Bind Scope ring_scope with sort.
+Coercion eqType : type >-> Equality.type.
+Canonical eqType.
+Coercion choiceType : type >-> Choice.type.
+Canonical choiceType.
+Coercion zmodType : type >-> GRing.Zmodule.type.
+Canonical zmodType.
+Coercion ringType : type >-> GRing.Ring.type.
+Canonical ringType.
+Coercion comRingType : type >-> GRing.ComRing.type.
+Canonical comRingType.
+Coercion unitRingType : type >-> GRing.UnitRing.type.
+Canonical unitRingType.
+Coercion comUnitRingType : type >-> GRing.ComUnitRing.type.
+Canonical comUnitRingType.
+Coercion idomainType : type >-> GRing.IntegralDomain.type.
+Canonical idomainType.
+Coercion numDomainType : type >-> NumDomain.type.
+Canonical numDomainType.
+Coercion realDomainType : type >-> RealDomain.type.
+Canonical realDomainType.
+Coercion fieldType : type >-> GRing.Field.type.
+Canonical fieldType.
+Coercion numFieldType : type >-> NumField.type.
+Canonical numFieldType.
+Canonical join_realDomainType.
+Notation realFieldType := type.
+Notation "[ 'realFieldType' 'of' T ]" := (@pack T _ _ id _ _ id)
+ (at level 0, format "[ 'realFieldType' 'of' T ]") : form_scope.
+End Exports.
+
+End RealField.
+Import RealField.Exports.
+
+Module ArchimedeanField.
+
+Section ClassDef.
+
+Record class_of R :=
+ Class { base : RealField.class_of R; _ : archimedean_axiom (num_for R base) }.
+Local Coercion base : class_of >-> RealField.class_of.
+
+Structure type := Pack {sort; _ : class_of sort; _ : Type}.
+Local Coercion sort : type >-> Sortclass.
+Variables (T : Type) (cT : type).
+Definition class := let: Pack _ c _ as cT' := cT return class_of cT' in c.
+Let xT := let: Pack T _ _ := cT in T.
+Notation xclass := (class : class_of xT).
+Definition clone c of phant_id class c := @Pack T c T.
+Definition pack b0 (m0 : archimedean_axiom (num_for T b0)) :=
+ fun bT b & phant_id (RealField.class bT) b =>
+ fun m & phant_id m0 m => Pack (@Class T b m) T.
+
+Definition eqType := @Equality.Pack cT xclass xT.
+Definition choiceType := @Choice.Pack cT xclass xT.
+Definition zmodType := @GRing.Zmodule.Pack cT xclass xT.
+Definition ringType := @GRing.Ring.Pack cT xclass xT.
+Definition comRingType := @GRing.ComRing.Pack cT xclass xT.
+Definition unitRingType := @GRing.UnitRing.Pack cT xclass xT.
+Definition comUnitRingType := @GRing.ComUnitRing.Pack cT xclass xT.
+Definition idomainType := @GRing.IntegralDomain.Pack cT xclass xT.
+Definition numDomainType := @NumDomain.Pack cT xclass xT.
+Definition realDomainType := @RealDomain.Pack cT xclass xT.
+Definition fieldType := @GRing.Field.Pack cT xclass xT.
+Definition numFieldType := @NumField.Pack cT xclass xT.
+Definition realFieldType := @RealField.Pack cT xclass xT.
+
+End ClassDef.
+
+Module Exports.
+Coercion base : class_of >-> RealField.class_of.
+Coercion sort : type >-> Sortclass.
+Bind Scope ring_scope with sort.
+Coercion eqType : type >-> Equality.type.
+Canonical eqType.
+Coercion choiceType : type >-> Choice.type.
+Canonical choiceType.
+Coercion zmodType : type >-> GRing.Zmodule.type.
+Canonical zmodType.
+Coercion ringType : type >-> GRing.Ring.type.
+Canonical ringType.
+Coercion comRingType : type >-> GRing.ComRing.type.
+Canonical comRingType.
+Coercion unitRingType : type >-> GRing.UnitRing.type.
+Canonical unitRingType.
+Coercion comUnitRingType : type >-> GRing.ComUnitRing.type.
+Canonical comUnitRingType.
+Coercion idomainType : type >-> GRing.IntegralDomain.type.
+Canonical idomainType.
+Coercion numDomainType : type >-> NumDomain.type.
+Canonical numDomainType.
+Coercion realDomainType : type >-> RealDomain.type.
+Canonical realDomainType.
+Coercion fieldType : type >-> GRing.Field.type.
+Canonical fieldType.
+Coercion numFieldType : type >-> NumField.type.
+Canonical numFieldType.
+Coercion realFieldType : type >-> RealField.type.
+Canonical realFieldType.
+Notation archiFieldType := type.
+Notation ArchiFieldType T m := (@pack T _ m _ _ id _ id).
+Notation "[ 'archiFieldType' 'of' T 'for' cT ]" := (@clone T cT _ idfun)
+ (at level 0, format "[ 'archiFieldType' 'of' T 'for' cT ]") : form_scope.
+Notation "[ 'archiFieldType' 'of' T ]" := (@clone T _ _ id)
+ (at level 0, format "[ 'archiFieldType' 'of' T ]") : form_scope.
+End Exports.
+
+End ArchimedeanField.
+Import ArchimedeanField.Exports.
+
+Module RealClosedField.
+
+Section ClassDef.
+
+Record class_of R :=
+ Class { base : RealField.class_of R; _ : real_closed_axiom (num_for R base) }.
+Local Coercion base : class_of >-> RealField.class_of.
+
+Structure type := Pack {sort; _ : class_of sort; _ : Type}.
+Local Coercion sort : type >-> Sortclass.
+Variables (T : Type) (cT : type).
+Definition class := let: Pack _ c _ as cT' := cT return class_of cT' in c.
+Let xT := let: Pack T _ _ := cT in T.
+Notation xclass := (class : class_of xT).
+Definition clone c of phant_id class c := @Pack T c T.
+Definition pack b0 (m0 : real_closed_axiom (num_for T b0)) :=
+ fun bT b & phant_id (RealField.class bT) b =>
+ fun m & phant_id m0 m => Pack (@Class T b m) T.
+
+Definition eqType := @Equality.Pack cT xclass xT.
+Definition choiceType := @Choice.Pack cT xclass xT.
+Definition zmodType := @GRing.Zmodule.Pack cT xclass xT.
+Definition ringType := @GRing.Ring.Pack cT xclass xT.
+Definition comRingType := @GRing.ComRing.Pack cT xclass xT.
+Definition unitRingType := @GRing.UnitRing.Pack cT xclass xT.
+Definition comUnitRingType := @GRing.ComUnitRing.Pack cT xclass xT.
+Definition idomainType := @GRing.IntegralDomain.Pack cT xclass xT.
+Definition numDomainType := @NumDomain.Pack cT xclass xT.
+Definition realDomainType := @RealDomain.Pack cT xclass xT.
+Definition fieldType := @GRing.Field.Pack cT xclass xT.
+Definition numFieldType := @NumField.Pack cT xclass xT.
+Definition realFieldType := @RealField.Pack cT xclass xT.
+
+End ClassDef.
+
+Module Exports.
+Coercion base : class_of >-> RealField.class_of.
+Coercion sort : type >-> Sortclass.
+Bind Scope ring_scope with sort.
+Coercion eqType : type >-> Equality.type.
+Canonical eqType.
+Coercion choiceType : type >-> Choice.type.
+Canonical choiceType.
+Coercion zmodType : type >-> GRing.Zmodule.type.
+Canonical zmodType.
+Coercion ringType : type >-> GRing.Ring.type.
+Canonical ringType.
+Coercion comRingType : type >-> GRing.ComRing.type.
+Canonical comRingType.
+Coercion unitRingType : type >-> GRing.UnitRing.type.
+Canonical unitRingType.
+Coercion comUnitRingType : type >-> GRing.ComUnitRing.type.
+Canonical comUnitRingType.
+Coercion idomainType : type >-> GRing.IntegralDomain.type.
+Canonical idomainType.
+Coercion numDomainType : type >-> NumDomain.type.
+Canonical numDomainType.
+Coercion realDomainType : type >-> RealDomain.type.
+Canonical realDomainType.
+Coercion fieldType : type >-> GRing.Field.type.
+Canonical fieldType.
+Coercion numFieldType : type >-> NumField.type.
+Canonical numFieldType.
+Coercion realFieldType : type >-> RealField.type.
+Canonical realFieldType.
+Notation rcfType := Num.RealClosedField.type.
+Notation RcfType T m := (@pack T _ m _ _ id _ id).
+Notation "[ 'rcfType' 'of' T 'for' cT ]" := (@clone T cT _ idfun)
+ (at level 0, format "[ 'rcfType' 'of' T 'for' cT ]") : form_scope.
+Notation "[ 'rcfType' 'of' T ]" := (@clone T _ _ id)
+ (at level 0, format "[ 'rcfType' 'of' T ]") : form_scope.
+End Exports.
+
+End RealClosedField.
+Import RealClosedField.Exports.
+
+(* The elementary theory needed to support the definition of the derived *)
+(* operations for the extensions described above. *)
+Module Import Internals.
+
+Section Domain.
+Variable R : numDomainType.
+Implicit Types x y : R.
+
+(* Lemmas from the signature *)
+
+Lemma normr0_eq0 x : `|x| = 0 -> x = 0.
+Proof. by case: R x => ? [? []]. Qed.
+
+Lemma ler_norm_add x y : `|x + y| <= `|x| + `|y|.
+Proof. by case: R x y => ? [? []]. Qed.
+
+Lemma addr_gt0 x y : 0 < x -> 0 < y -> 0 < x + y.
+Proof. by case: R x y => ? [? []]. Qed.
+
+Lemma ger_leVge x y : 0 <= x -> 0 <= y -> (x <= y) || (y <= x).
+Proof. by case: R x y => ? [? []]. Qed.
+
+Lemma normrM : {morph norm : x y / x * y : R}.
+Proof. by case: R => ? [? []]. Qed.
+
+Lemma ler_def x y : (x <= y) = (`|y - x| == y - x).
+Proof. by case: R x y => ? [? []]. Qed.
+
+Lemma ltr_def x y : (x < y) = (y != x) && (x <= y).
+Proof. by case: R x y => ? [? []]. Qed.
+
+(* Basic consequences (just enough to get predicate closure properties). *)
+
+Lemma ger0_def x : (0 <= x) = (`|x| == x).
+Proof. by rewrite ler_def subr0. Qed.
+
+Lemma subr_ge0 x y : (0 <= x - y) = (y <= x).
+Proof. by rewrite ger0_def -ler_def. Qed.
+
+Lemma oppr_ge0 x : (0 <= - x) = (x <= 0).
+Proof. by rewrite -sub0r subr_ge0. Qed.
+
+Lemma ler01 : 0 <= 1 :> R.
+Proof.
+have n1_nz: `|1| != 0 :> R by apply: contraNneq (@oner_neq0 R) => /normr0_eq0->.
+by rewrite ger0_def -(inj_eq (mulfI n1_nz)) -normrM !mulr1.
+Qed.
+
+Lemma ltr01 : 0 < 1 :> R. Proof. by rewrite ltr_def oner_neq0 ler01. Qed.
+
+Lemma ltrW x y : x < y -> x <= y. Proof. by rewrite ltr_def => /andP[]. Qed.
+
+Lemma lerr x : x <= x.
+Proof.
+have n2: `|2%:R| == 2%:R :> R by rewrite -ger0_def ltrW ?addr_gt0 ?ltr01.
+rewrite ler_def subrr -(inj_eq (addrI `|0|)) addr0 -mulr2n -mulr_natr.
+by rewrite -(eqP n2) -normrM mul0r.
+Qed.
+
+Lemma le0r x : (0 <= x) = (x == 0) || (0 < x).
+Proof. by rewrite ltr_def; case: eqP => // ->; rewrite lerr. Qed.
+
+Lemma addr_ge0 x y : 0 <= x -> 0 <= y -> 0 <= x + y.
+Proof.
+rewrite le0r; case/predU1P=> [-> | x_pos]; rewrite ?add0r // le0r.
+by case/predU1P=> [-> | y_pos]; rewrite ltrW ?addr0 ?addr_gt0.
+Qed.
+
+Lemma pmulr_rgt0 x y : 0 < x -> (0 < x * y) = (0 < y).
+Proof.
+rewrite !ltr_def !ger0_def normrM mulf_eq0 negb_or => /andP[x_neq0 /eqP->].
+by rewrite x_neq0 (inj_eq (mulfI x_neq0)).
+Qed.
+
+(* Closure properties of the real predicates. *)
+
+Lemma posrE x : (x \is pos) = (0 < x). Proof. by []. Qed.
+Lemma nnegrE x : (x \is nneg) = (0 <= x). Proof. by []. Qed.
+Lemma realE x : (x \is real) = (0 <= x) || (x <= 0). Proof. by []. Qed.
+
+Fact pos_divr_closed : divr_closed (@pos R).
+Proof.
+split=> [|x y x_gt0 y_gt0]; rewrite posrE ?ltr01 //.
+have [Uy|/invr_out->] := boolP (y \is a GRing.unit); last by rewrite pmulr_rgt0.
+by rewrite -(pmulr_rgt0 _ y_gt0) mulrC divrK.
+Qed.
+Canonical pos_mulrPred := MulrPred pos_divr_closed.
+Canonical pos_divrPred := DivrPred pos_divr_closed.
+
+Fact nneg_divr_closed : divr_closed (@nneg R).
+Proof.
+split=> [|x y]; rewrite !nnegrE ?ler01 ?le0r // -!posrE.
+case/predU1P=> [-> _ | x_gt0]; first by rewrite mul0r eqxx.
+by case/predU1P=> [-> | y_gt0]; rewrite ?invr0 ?mulr0 ?eqxx // orbC rpred_div.
+Qed.
+Canonical nneg_mulrPred := MulrPred nneg_divr_closed.
+Canonical nneg_divrPred := DivrPred nneg_divr_closed.
+
+Fact nneg_addr_closed : addr_closed (@nneg R).
+Proof. by split; [exact: lerr | exact: addr_ge0]. Qed.
+Canonical nneg_addrPred := AddrPred nneg_addr_closed.
+Canonical nneg_semiringPred := SemiringPred nneg_divr_closed.
+
+Fact real_oppr_closed : oppr_closed (@real R).
+Proof. by move=> x; rewrite /= !realE oppr_ge0 orbC -!oppr_ge0 opprK. Qed.
+Canonical real_opprPred := OpprPred real_oppr_closed.
+
+Fact real_addr_closed : addr_closed (@real R).
+Proof.
+split=> [|x y Rx Ry]; first by rewrite realE lerr.
+without loss{Rx} x_ge0: x y Ry / 0 <= x.
+ case/orP: Rx => [? | x_le0]; first exact.
+ by rewrite -rpredN opprD; apply; rewrite ?rpredN ?oppr_ge0.
+case/orP: Ry => [y_ge0 | y_le0]; first by rewrite realE -nnegrE rpredD.
+by rewrite realE -[y]opprK orbC -oppr_ge0 opprB !subr_ge0 ger_leVge ?oppr_ge0.
+Qed.
+Canonical real_addrPred := AddrPred real_addr_closed.
+Canonical real_zmodPred := ZmodPred real_oppr_closed.
+
+Fact real_divr_closed : divr_closed (@real R).
+Proof.
+split=> [|x y Rx Ry]; first by rewrite realE ler01.
+without loss{Rx} x_ge0: x / 0 <= x.
+ case/orP: Rx => [? | x_le0]; first exact.
+ by rewrite -rpredN -mulNr; apply; rewrite ?oppr_ge0.
+without loss{Ry} y_ge0: y / 0 <= y; last by rewrite realE -nnegrE rpred_div.
+case/orP: Ry => [? | y_le0]; first exact.
+by rewrite -rpredN -mulrN -invrN; apply; rewrite ?oppr_ge0.
+Qed.
+Canonical real_mulrPred := MulrPred real_divr_closed.
+Canonical real_smulrPred := SmulrPred real_divr_closed.
+Canonical real_divrPred := DivrPred real_divr_closed.
+Canonical real_sdivrPred := SdivrPred real_divr_closed.
+Canonical real_semiringPred := SemiringPred real_divr_closed.
+Canonical real_subringPred := SubringPred real_divr_closed.
+Canonical real_divringPred := DivringPred real_divr_closed.
+
+End Domain.
+
+Lemma num_real (R : realDomainType) (x : R) : x \is real.
+Proof. by case: R x => T []. Qed.
+
+Fact archi_bound_subproof (R : archiFieldType) : archimedean_axiom R.
+Proof. by case: R => ? []. Qed.
+
+Section RealClosed.
+Variable R : rcfType.
+
+Lemma poly_ivt : real_closed_axiom R. Proof. by case: R => ? []. Qed.
+
+Fact sqrtr_subproof (x : R) :
+ exists2 y, 0 <= y & if 0 <= x return bool then y ^+ 2 == x else y == 0.
+Proof.
+case x_ge0: (0 <= x); last by exists 0; rewrite ?lerr.
+have le0x1: 0 <= x + 1 by rewrite -nnegrE rpredD ?rpred1.
+have [|y /andP[y_ge0 _]] := @poly_ivt ('X^2 - x%:P) _ _ le0x1.
+ rewrite !hornerE -subr_ge0 add0r opprK x_ge0 -expr2 sqrrD mulr1.
+ by rewrite addrAC !addrA addrK -nnegrE !rpredD ?rpredX ?rpred1.
+by rewrite rootE !hornerE subr_eq0; exists y.
+Qed.
+
+End RealClosed.
+
+End Internals.
+
+Module PredInstances.
+
+Canonical pos_mulrPred.
+Canonical pos_divrPred.
+
+Canonical nneg_addrPred.
+Canonical nneg_mulrPred.
+Canonical nneg_divrPred.
+Canonical nneg_semiringPred.
+
+Canonical real_addrPred.
+Canonical real_opprPred.
+Canonical real_zmodPred.
+Canonical real_mulrPred.
+Canonical real_smulrPred.
+Canonical real_divrPred.
+Canonical real_sdivrPred.
+Canonical real_semiringPred.
+Canonical real_subringPred.
+Canonical real_divringPred.
+
+End PredInstances.
+
+Module Import ExtraDef.
+
+Definition archi_bound {R} x := sval (sigW (@archi_bound_subproof R x)).
+
+Definition sqrtr {R} x := s2val (sig2W (@sqrtr_subproof R x)).
+
+End ExtraDef.
+
+Notation bound := archi_bound.
+Notation sqrt := sqrtr.
+
+Module Theory.
+
+Section NumIntegralDomainTheory.
+
+Variable R : numDomainType.
+Implicit Types x y z t : R.
+
+(* Lemmas from the signature (reexported from internals). *)
+
+Definition ler_norm_add x y : `|x + y| <= `|x| + `|y| := ler_norm_add x y.
+Definition addr_gt0 x y : 0 < x -> 0 < y -> 0 < x + y := @addr_gt0 R x y.
+Definition normr0_eq0 x : `|x| = 0 -> x = 0 := @normr0_eq0 R x.
+Definition ger_leVge x y : 0 <= x -> 0 <= y -> (x <= y) || (y <= x) :=
+ @ger_leVge R x y.
+Definition normrM : {morph normr : x y / x * y : R} := @normrM R.
+Definition ler_def x y : (x <= y) = (`|y - x| == y - x) := @ler_def R x y.
+Definition ltr_def x y : (x < y) = (y != x) && (x <= y) := @ltr_def R x y.
+
+(* Predicate and relation definitions. *)
+
+Lemma gerE x y : ge x y = (y <= x). Proof. by []. Qed.
+Lemma gtrE x y : gt x y = (y < x). Proof. by []. Qed.
+Lemma posrE x : (x \is pos) = (0 < x). Proof. by []. Qed.
+Lemma negrE x : (x \is neg) = (x < 0). Proof. by []. Qed.
+Lemma nnegrE x : (x \is nneg) = (0 <= x). Proof. by []. Qed.
+Lemma realE x : (x \is real) = (0 <= x) || (x <= 0). Proof. by []. Qed.
+
+(* General properties of <= and < *)
+
+Lemma lerr x : x <= x. Proof. exact: lerr. Qed.
+Lemma ltrr x : x < x = false. Proof. by rewrite ltr_def eqxx. Qed.
+Lemma ltrW x y : x < y -> x <= y. Proof. exact: ltrW. Qed.
+Hint Resolve lerr ltrr ltrW.
+
+Lemma ltr_neqAle x y : (x < y) = (x != y) && (x <= y).
+Proof. by rewrite ltr_def eq_sym. Qed.
+
+Lemma ler_eqVlt x y : (x <= y) = (x == y) || (x < y).
+Proof. by rewrite ltr_neqAle; case: eqP => // ->; rewrite lerr. Qed.
+
+Lemma lt0r x : (0 < x) = (x != 0) && (0 <= x). Proof. by rewrite ltr_def. Qed.
+Lemma le0r x : (0 <= x) = (x == 0) || (0 < x). Proof. exact: le0r. Qed.
+
+Lemma lt0r_neq0 (x : R) : 0 < x -> x != 0.
+Proof. by rewrite lt0r; case/andP. Qed.
+
+Lemma ltr0_neq0 (x : R) : 0 < x -> x != 0.
+Proof. by rewrite lt0r; case/andP. Qed.
+
+Lemma gtr_eqF x y : y < x -> x == y = false.
+Proof. by rewrite ltr_def; case/andP; move/negPf=> ->. Qed.
+
+Lemma ltr_eqF x y : x < y -> x == y = false.
+Proof. by move=> hyx; rewrite eq_sym gtr_eqF. Qed.
+
+Lemma pmulr_rgt0 x y : 0 < x -> (0 < x * y) = (0 < y).
+Proof. exact: pmulr_rgt0. Qed.
+
+Lemma pmulr_rge0 x y : 0 < x -> (0 <= x * y) = (0 <= y).
+Proof.
+by rewrite !le0r mulf_eq0; case: eqP => // [-> /negPf[] | _ /pmulr_rgt0->].
+Qed.
+
+(* Integer comparisons and characteristic 0. *)
+Lemma ler01 : 0 <= 1 :> R. Proof. exact: ler01. Qed.
+Lemma ltr01 : 0 < 1 :> R. Proof. exact: ltr01. Qed.
+Lemma ler0n n : 0 <= n%:R :> R. Proof. by rewrite -nnegrE rpred_nat. Qed.
+Hint Resolve ler01 ltr01 ler0n.
+Lemma ltr0Sn n : 0 < n.+1%:R :> R.
+Proof. by elim: n => // n; apply: addr_gt0. Qed.
+Lemma ltr0n n : (0 < n%:R :> R) = (0 < n)%N.
+Proof. by case: n => //= n; apply: ltr0Sn. Qed.
+Hint Resolve ltr0Sn.
+
+Lemma pnatr_eq0 n : (n%:R == 0 :> R) = (n == 0)%N.
+Proof. by case: n => [|n]; rewrite ?mulr0n ?eqxx // gtr_eqF. Qed.
+
+Lemma char_num : [char R] =i pred0.
+Proof. by case=> // p /=; rewrite !inE pnatr_eq0 andbF. Qed.
+
+(* Properties of the norm. *)
+
+Lemma ger0_def x : (0 <= x) = (`|x| == x). Proof. exact: ger0_def. Qed.
+Lemma normr_idP {x} : reflect (`|x| = x) (0 <= x).
+Proof. by rewrite ger0_def; apply: eqP. Qed.
+Lemma ger0_norm x : 0 <= x -> `|x| = x. Proof. exact: normr_idP. Qed.
+
+Lemma normr0 : `|0| = 0 :> R. Proof. exact: ger0_norm. Qed.
+Lemma normr1 : `|1| = 1 :> R. Proof. exact: ger0_norm. Qed.
+Lemma normr_nat n : `|n%:R| = n%:R :> R. Proof. exact: ger0_norm. Qed.
+Lemma normrMn x n : `|x *+ n| = `|x| *+ n.
+Proof. by rewrite -mulr_natl normrM normr_nat mulr_natl. Qed.
+
+Lemma normr_prod I r (P : pred I) (F : I -> R) :
+ `|\prod_(i <- r | P i) F i| = \prod_(i <- r | P i) `|F i|.
+Proof. exact: (big_morph norm normrM normr1). Qed.
+
+Lemma normrX n x : `|x ^+ n| = `|x| ^+ n.
+Proof. by rewrite -(card_ord n) -!prodr_const normr_prod. Qed.
+
+Lemma normr_unit : {homo (@norm R) : x / x \is a GRing.unit}.
+Proof.
+move=> x /= /unitrP [y [yx xy]]; apply/unitrP; exists `|y|.
+by rewrite -!normrM xy yx normr1.
+Qed.
+
+Lemma normrV : {in GRing.unit, {morph (@normr R) : x / x ^-1}}.
+Proof.
+move=> x ux; apply: (mulrI (normr_unit ux)).
+by rewrite -normrM !divrr ?normr1 ?normr_unit.
+Qed.
+
+Lemma normr0P {x} : reflect (`|x| = 0) (x == 0).
+Proof. by apply: (iffP eqP)=> [->|/normr0_eq0 //]; apply: normr0. Qed.
+
+Definition normr_eq0 x := sameP (`|x| =P 0) normr0P.
+
+Lemma normrN1 : `|-1| = 1 :> R.
+Proof.
+have: `|-1| ^+ 2 == 1 :> R by rewrite -normrX -signr_odd normr1.
+rewrite sqrf_eq1 => /orP[/eqP //|]; rewrite -ger0_def le0r oppr_eq0 oner_eq0.
+by move/(addr_gt0 ltr01); rewrite subrr ltrr.
+Qed.
+
+Lemma normrN x : `|- x| = `|x|.
+Proof. by rewrite -mulN1r normrM normrN1 mul1r. Qed.
+
+Lemma distrC x y : `|x - y| = `|y - x|.
+Proof. by rewrite -opprB normrN. Qed.
+
+Lemma ler0_def x : (x <= 0) = (`|x| == - x).
+Proof. by rewrite ler_def sub0r normrN. Qed.
+
+Lemma normr_id x : `|`|x| | = `|x|.
+Proof.
+have nz2: 2%:R != 0 :> R by rewrite pnatr_eq0.
+apply: (mulfI nz2); rewrite -{1}normr_nat -normrM mulr_natl mulr2n ger0_norm //.
+by rewrite -{2}normrN -normr0 -(subrr x) ler_norm_add.
+Qed.
+
+Lemma normr_ge0 x : 0 <= `|x|. Proof. by rewrite ger0_def normr_id. Qed.
+Hint Resolve normr_ge0.
+
+Lemma ler0_norm x : x <= 0 -> `|x| = - x.
+Proof. by move=> x_le0; rewrite -[r in _ = r]ger0_norm ?normrN ?oppr_ge0. Qed.
+
+Definition gtr0_norm x (hx : 0 < x) := ger0_norm (ltrW hx).
+Definition ltr0_norm x (hx : x < 0) := ler0_norm (ltrW hx).
+
+(* Comparision to 0 of a difference *)
+
+Lemma subr_ge0 x y : (0 <= y - x) = (x <= y). Proof. exact: subr_ge0. Qed.
+Lemma subr_gt0 x y : (0 < y - x) = (x < y).
+Proof. by rewrite !ltr_def subr_eq0 subr_ge0. Qed.
+Lemma subr_le0 x y : (y - x <= 0) = (y <= x).
+Proof. by rewrite -subr_ge0 opprB add0r subr_ge0. Qed.
+Lemma subr_lt0 x y : (y - x < 0) = (y < x).
+Proof. by rewrite -subr_gt0 opprB add0r subr_gt0. Qed.
+
+Definition subr_lte0 := (subr_le0, subr_lt0).
+Definition subr_gte0 := (subr_ge0, subr_gt0).
+Definition subr_cp0 := (subr_lte0, subr_gte0).
+
+(* Ordered ring properties. *)
+
+Lemma ler_asym : antisymmetric (<=%R : rel R).
+Proof.
+move=> x y; rewrite !ler_def distrC -opprB -addr_eq0 => /andP[/eqP->].
+by rewrite -mulr2n -mulr_natl mulf_eq0 subr_eq0 pnatr_eq0 => /eqP.
+Qed.
+
+Lemma eqr_le x y : (x == y) = (x <= y <= x).
+Proof. by apply/eqP/idP=> [->|/ler_asym]; rewrite ?lerr. Qed.
+
+Lemma ltr_trans : transitive (@ltr R).
+Proof.
+move=> y x z le_xy le_yz.
+by rewrite -subr_gt0 -(subrK y z) -addrA addr_gt0 ?subr_gt0.
+Qed.
+
+Lemma ler_lt_trans y x z : x <= y -> y < z -> x < z.
+Proof. by rewrite !ler_eqVlt => /orP[/eqP -> //|/ltr_trans]; apply. Qed.
+
+Lemma ltr_le_trans y x z : x < y -> y <= z -> x < z.
+Proof. by rewrite !ler_eqVlt => lxy /orP[/eqP <- //|/(ltr_trans lxy)]. Qed.
+
+Lemma ler_trans : transitive (@ler R).
+Proof.
+move=> y x z; rewrite !ler_eqVlt => /orP [/eqP -> //|lxy].
+by move=> /orP [/eqP <-|/(ltr_trans lxy) ->]; rewrite ?lxy orbT.
+Qed.
+
+Definition lter01 := (ler01, ltr01).
+Definition lterr := (lerr, ltrr).
+
+Lemma addr_ge0 x y : 0 <= x -> 0 <= y -> 0 <= x + y.
+Proof. exact: addr_ge0. Qed.
+
+Lemma lerifP x y C : reflect (x <= y ?= iff C) (if C then x == y else x < y).
+Proof.
+rewrite /lerif ler_eqVlt; apply: (iffP idP)=> [|[]].
+ by case: C => [/eqP->|lxy]; rewrite ?eqxx // lxy ltr_eqF.
+by move=> /orP[/eqP->|lxy] <-; rewrite ?eqxx // ltr_eqF.
+Qed.
+
+Lemma ltr_asym x y : x < y < x = false.
+Proof. by apply/negP=> /andP [/ltr_trans hyx /hyx]; rewrite ltrr. Qed.
+
+Lemma ler_anti : antisymmetric (@ler R).
+Proof. by move=> x y; rewrite -eqr_le=> /eqP. Qed.
+
+Lemma ltr_le_asym x y : x < y <= x = false.
+Proof. by rewrite ltr_neqAle -andbA -eqr_le eq_sym; case: (_ == _). Qed.
+
+Lemma ler_lt_asym x y : x <= y < x = false.
+Proof. by rewrite andbC ltr_le_asym. Qed.
+
+Definition lter_anti := (=^~ eqr_le, ltr_asym, ltr_le_asym, ler_lt_asym).
+
+Lemma ltr_geF x y : x < y -> (y <= x = false).
+Proof.
+by move=> xy; apply: contraTF isT=> /(ltr_le_trans xy); rewrite ltrr.
+Qed.
+
+Lemma ler_gtF x y : x <= y -> (y < x = false).
+Proof. by apply: contraTF=> /ltr_geF->. Qed.
+
+Definition ltr_gtF x y hxy := ler_gtF (@ltrW x y hxy).
+
+(* Norm and order properties. *)
+
+Lemma normr_le0 x : (`|x| <= 0) = (x == 0).
+Proof. by rewrite -normr_eq0 eqr_le normr_ge0 andbT. Qed.
+
+Lemma normr_lt0 x : `|x| < 0 = false.
+Proof. by rewrite ltr_neqAle normr_le0 normr_eq0 andNb. Qed.
+
+Lemma normr_gt0 x : (`|x| > 0) = (x != 0).
+Proof. by rewrite ltr_def normr_eq0 normr_ge0 andbT. Qed.
+
+Definition normrE x := (normr_id, normr0, normr1, normrN1, normr_ge0, normr_eq0,
+ normr_lt0, normr_le0, normr_gt0, normrN).
+
+End NumIntegralDomainTheory.
+
+Implicit Arguments ler01 [R].
+Implicit Arguments ltr01 [R].
+Implicit Arguments normr_idP [R x].
+Implicit Arguments normr0P [R x].
+Implicit Arguments lerifP [R x y C].
+Hint Resolve @ler01 @ltr01 lerr ltrr ltrW ltr_eqF ltr0Sn ler0n normr_ge0.
+
+Section NumIntegralDomainMonotonyTheory.
+
+Variables R R' : numDomainType.
+Implicit Types m n p : nat.
+Implicit Types x y z : R.
+Implicit Types u v w : R'.
+
+Section AcrossTypes.
+
+Variable D D' : pred R.
+Variable (f : R -> R').
+
+Lemma ltrW_homo : {homo f : x y / x < y} -> {homo f : x y / x <= y}.
+Proof. by move=> mf x y /=; rewrite ler_eqVlt => /orP[/eqP->|/mf/ltrW]. Qed.
+
+Lemma ltrW_nhomo : {homo f : x y /~ x < y} -> {homo f : x y /~ x <= y}.
+Proof. by move=> mf x y /=; rewrite ler_eqVlt => /orP[/eqP->|/mf/ltrW]. Qed.
+
+Lemma homo_inj_lt :
+ injective f -> {homo f : x y / x <= y} -> {homo f : x y / x < y}.
+Proof.
+by move=> fI mf x y /= hxy; rewrite ltr_neqAle (inj_eq fI) mf (ltr_eqF, ltrW).
+Qed.
+
+Lemma nhomo_inj_lt :
+ injective f -> {homo f : x y /~ x <= y} -> {homo f : x y /~ x < y}.
+Proof.
+by move=> fI mf x y /= hxy; rewrite ltr_neqAle (inj_eq fI) mf (gtr_eqF, ltrW).
+Qed.
+
+Lemma mono_inj : {mono f : x y / x <= y} -> injective f.
+Proof. by move=> mf x y /eqP; rewrite eqr_le !mf -eqr_le=> /eqP. Qed.
+
+Lemma nmono_inj : {mono f : x y /~ x <= y} -> injective f.
+Proof. by move=> mf x y /eqP; rewrite eqr_le !mf -eqr_le=> /eqP. Qed.
+
+Lemma lerW_mono : {mono f : x y / x <= y} -> {mono f : x y / x < y}.
+Proof.
+by move=> mf x y /=; rewrite !ltr_neqAle mf inj_eq //; apply: mono_inj.
+Qed.
+
+Lemma lerW_nmono : {mono f : x y /~ x <= y} -> {mono f : x y /~ x < y}.
+Proof.
+by move=> mf x y /=; rewrite !ltr_neqAle mf eq_sym inj_eq //; apply: nmono_inj.
+Qed.
+
+(* Monotony in D D' *)
+Lemma ltrW_homo_in :
+ {in D & D', {homo f : x y / x < y}} -> {in D & D', {homo f : x y / x <= y}}.
+Proof.
+by move=> mf x y hx hy /=; rewrite ler_eqVlt => /orP[/eqP->|/mf/ltrW] //; apply.
+Qed.
+
+Lemma ltrW_nhomo_in :
+ {in D & D', {homo f : x y /~ x < y}} -> {in D & D', {homo f : x y /~ x <= y}}.
+Proof.
+by move=> mf x y hx hy /=; rewrite ler_eqVlt => /orP[/eqP->|/mf/ltrW] //; apply.
+Qed.
+
+Lemma homo_inj_in_lt :
+ {in D & D', injective f} -> {in D & D', {homo f : x y / x <= y}} ->
+ {in D & D', {homo f : x y / x < y}}.
+Proof.
+move=> fI mf x y hx hy /= hxy; rewrite ltr_neqAle; apply/andP; split.
+ by apply: contraTN hxy => /eqP /fI -> //; rewrite ltrr.
+by rewrite mf // (ltr_eqF, ltrW).
+Qed.
+
+Lemma nhomo_inj_in_lt :
+ {in D & D', injective f} -> {in D & D', {homo f : x y /~ x <= y}} ->
+ {in D & D', {homo f : x y /~ x < y}}.
+Proof.
+move=> fI mf x y hx hy /= hxy; rewrite ltr_neqAle; apply/andP; split.
+ by apply: contraTN hxy => /eqP /fI -> //; rewrite ltrr.
+by rewrite mf // (gtr_eqF, ltrW).
+Qed.
+
+Lemma mono_inj_in : {in D &, {mono f : x y / x <= y}} -> {in D &, injective f}.
+Proof.
+by move=> mf x y hx hy /= /eqP; rewrite eqr_le !mf // -eqr_le => /eqP.
+Qed.
+
+Lemma nmono_inj_in :
+ {in D &, {mono f : x y /~ x <= y}} -> {in D &, injective f}.
+Proof.
+by move=> mf x y hx hy /= /eqP; rewrite eqr_le !mf // -eqr_le => /eqP.
+Qed.
+
+Lemma lerW_mono_in :
+ {in D &, {mono f : x y / x <= y}} -> {in D &, {mono f : x y / x < y}}.
+Proof.
+move=> mf x y hx hy /=; rewrite !ltr_neqAle mf // (@inj_in_eq _ _ D) //.
+exact: mono_inj_in.
+Qed.
+
+Lemma lerW_nmono_in :
+ {in D &, {mono f : x y /~ x <= y}} -> {in D &, {mono f : x y /~ x < y}}.
+Proof.
+move=> mf x y hx hy /=; rewrite !ltr_neqAle mf // eq_sym (@inj_in_eq _ _ D) //.
+exact: nmono_inj_in.
+Qed.
+
+End AcrossTypes.
+
+Section NatToR.
+
+Variable (f : nat -> R).
+
+Lemma ltn_ltrW_homo :
+ {homo f : m n / (m < n)%N >-> m < n} ->
+ {homo f : m n / (m <= n)%N >-> m <= n}.
+Proof. by move=> mf m n /=; rewrite leq_eqVlt => /orP[/eqP->|/mf/ltrW //]. Qed.
+
+Lemma ltn_ltrW_nhomo :
+ {homo f : m n / (n < m)%N >-> m < n} ->
+ {homo f : m n / (n <= m)%N >-> m <= n}.
+Proof. by move=> mf m n /=; rewrite leq_eqVlt => /orP[/eqP->|/mf/ltrW//]. Qed.
+
+Lemma homo_inj_ltn_lt :
+ injective f -> {homo f : m n / (m <= n)%N >-> m <= n} ->
+ {homo f : m n / (m < n)%N >-> m < n}.
+Proof.
+move=> fI mf m n /= hmn.
+by rewrite ltr_neqAle (inj_eq fI) mf ?neq_ltn ?hmn ?orbT // ltnW.
+Qed.
+
+Lemma nhomo_inj_ltn_lt :
+ injective f -> {homo f : m n / (n <= m)%N >-> m <= n} ->
+ {homo f : m n / (n < m)%N >-> m < n}.
+Proof.
+move=> fI mf m n /= hmn; rewrite ltr_def (inj_eq fI).
+by rewrite mf ?neq_ltn ?hmn // ltnW.
+Qed.
+
+Lemma leq_mono_inj : {mono f : m n / (m <= n)%N >-> m <= n} -> injective f.
+Proof. by move=> mf m n /eqP; rewrite eqr_le !mf -eqn_leq => /eqP. Qed.
+
+Lemma leq_nmono_inj : {mono f : m n / (n <= m)%N >-> m <= n} -> injective f.
+Proof. by move=> mf m n /eqP; rewrite eqr_le !mf -eqn_leq => /eqP. Qed.
+
+Lemma leq_lerW_mono :
+ {mono f : m n / (m <= n)%N >-> m <= n} ->
+ {mono f : m n / (m < n)%N >-> m < n}.
+Proof.
+move=> mf m n /=; rewrite !ltr_neqAle mf inj_eq ?ltn_neqAle 1?eq_sym //.
+exact: leq_mono_inj.
+Qed.
+
+Lemma leq_lerW_nmono :
+ {mono f : m n / (n <= m)%N >-> m <= n} ->
+ {mono f : m n / (n < m)%N >-> m < n}.
+Proof.
+move=> mf x y /=; rewrite ltr_neqAle mf eq_sym inj_eq ?ltn_neqAle 1?eq_sym //.
+exact: leq_nmono_inj.
+Qed.
+
+Lemma homo_leq_mono :
+ {homo f : m n / (m < n)%N >-> m < n} ->
+ {mono f : m n / (m <= n)%N >-> m <= n}.
+Proof.
+move=> mf m n /=; case: leqP; last by move=> /mf /ltr_geF.
+by rewrite leq_eqVlt => /orP[/eqP->|/mf/ltrW //]; rewrite lerr.
+Qed.
+
+Lemma nhomo_leq_mono :
+ {homo f : m n / (n < m)%N >-> m < n} ->
+ {mono f : m n / (n <= m)%N >-> m <= n}.
+Proof.
+move=> mf m n /=; case: leqP; last by move=> /mf /ltr_geF.
+by rewrite leq_eqVlt => /orP[/eqP->|/mf/ltrW //]; rewrite lerr.
+Qed.
+
+End NatToR.
+
+End NumIntegralDomainMonotonyTheory.
+
+Section NumDomainOperationTheory.
+
+Variable R : numDomainType.
+Implicit Types x y z t : R.
+
+(* Comparision and opposite. *)
+
+Lemma ler_opp2 : {mono -%R : x y /~ x <= y :> R}.
+Proof. by move=> x y /=; rewrite -subr_ge0 opprK addrC subr_ge0. Qed.
+Hint Resolve ler_opp2.
+Lemma ltr_opp2 : {mono -%R : x y /~ x < y :> R}.
+Proof. by move=> x y /=; rewrite lerW_nmono. Qed.
+Hint Resolve ltr_opp2.
+Definition lter_opp2 := (ler_opp2, ltr_opp2).
+
+Lemma ler_oppr x y : (x <= - y) = (y <= - x).
+Proof. by rewrite (monoRL (@opprK _) ler_opp2). Qed.
+
+Lemma ltr_oppr x y : (x < - y) = (y < - x).
+Proof. by rewrite (monoRL (@opprK _) (lerW_nmono _)). Qed.
+
+Definition lter_oppr := (ler_oppr, ltr_oppr).
+
+Lemma ler_oppl x y : (- x <= y) = (- y <= x).
+Proof. by rewrite (monoLR (@opprK _) ler_opp2). Qed.
+
+Lemma ltr_oppl x y : (- x < y) = (- y < x).
+Proof. by rewrite (monoLR (@opprK _) (lerW_nmono _)). Qed.
+
+Definition lter_oppl := (ler_oppl, ltr_oppl).
+
+Lemma oppr_ge0 x : (0 <= - x) = (x <= 0).
+Proof. by rewrite lter_oppr oppr0. Qed.
+
+Lemma oppr_gt0 x : (0 < - x) = (x < 0).
+Proof. by rewrite lter_oppr oppr0. Qed.
+
+Definition oppr_gte0 := (oppr_ge0, oppr_gt0).
+
+Lemma oppr_le0 x : (- x <= 0) = (0 <= x).
+Proof. by rewrite lter_oppl oppr0. Qed.
+
+Lemma oppr_lt0 x : (- x < 0) = (0 < x).
+Proof. by rewrite lter_oppl oppr0. Qed.
+
+Definition oppr_lte0 := (oppr_le0, oppr_lt0).
+Definition oppr_cp0 := (oppr_gte0, oppr_lte0).
+Definition lter_oppE := (oppr_cp0, lter_opp2).
+
+Lemma ge0_cp x : 0 <= x -> (- x <= 0) * (- x <= x).
+Proof. by move=> hx; rewrite oppr_cp0 hx (@ler_trans _ 0) ?oppr_cp0. Qed.
+
+Lemma gt0_cp x : 0 < x ->
+ (0 <= x) * (- x <= 0) * (- x <= x) * (- x < 0) * (- x < x).
+Proof.
+move=> hx; move: (ltrW hx) => hx'; rewrite !ge0_cp hx' //.
+by rewrite oppr_cp0 hx // (@ltr_trans _ 0) ?oppr_cp0.
+Qed.
+
+Lemma le0_cp x : x <= 0 -> (0 <= - x) * (x <= - x).
+Proof. by move=> hx; rewrite oppr_cp0 hx (@ler_trans _ 0) ?oppr_cp0. Qed.
+
+Lemma lt0_cp x :
+ x < 0 -> (x <= 0) * (0 <= - x) * (x <= - x) * (0 < - x) * (x < - x).
+Proof.
+move=> hx; move: (ltrW hx) => hx'; rewrite !le0_cp // hx'.
+by rewrite oppr_cp0 hx // (@ltr_trans _ 0) ?oppr_cp0.
+Qed.
+
+(* Properties of the real subset. *)
+
+Lemma ger0_real x : 0 <= x -> x \is real.
+Proof. by rewrite realE => ->. Qed.
+
+Lemma ler0_real x : x <= 0 -> x \is real.
+Proof. by rewrite realE orbC => ->. Qed.
+
+Lemma gtr0_real x : 0 < x -> x \is real.
+Proof. by move=> /ltrW/ger0_real. Qed.
+
+Lemma ltr0_real x : x < 0 -> x \is real.
+Proof. by move=> /ltrW/ler0_real. Qed.
+
+Lemma real0 : 0 \is @real R. Proof. by rewrite ger0_real. Qed.
+Hint Resolve real0.
+
+Lemma real1 : 1 \is @real R. Proof. by rewrite ger0_real. Qed.
+Hint Resolve real1.
+
+Lemma realn n : n%:R \is @real R. Proof. by rewrite ger0_real. Qed.
+
+Lemma ler_leVge x y : x <= 0 -> y <= 0 -> (x <= y) || (y <= x).
+Proof. by rewrite -!oppr_ge0 => /(ger_leVge _) h /h; rewrite !ler_opp2. Qed.
+
+Lemma real_leVge x y : x \is real -> y \is real -> (x <= y) || (y <= x).
+Proof.
+rewrite !realE; have [x_ge0 _|x_nge0 /= x_le0] := boolP (_ <= _); last first.
+ by have [/(ler_trans x_le0)->|_ /(ler_leVge x_le0) //] := boolP (0 <= _).
+by have [/(ger_leVge x_ge0)|_ /ler_trans->] := boolP (0 <= _); rewrite ?orbT.
+Qed.
+
+Lemma realB : {in real &, forall x y, x - y \is real}.
+Proof. exact: rpredB. Qed.
+
+Lemma realN : {mono (@GRing.opp R) : x / x \is real}.
+Proof. exact: rpredN. Qed.
+
+(* :TODO: add a rpredBC in ssralg *)
+Lemma realBC x y : (x - y \is real) = (y - x \is real).
+Proof. by rewrite -realN opprB. Qed.
+
+Lemma realD : {in real &, forall x y, x + y \is real}.
+Proof. exact: rpredD. Qed.
+
+(* dichotomy and trichotomy *)
+
+CoInductive ler_xor_gt (x y : R) : R -> R -> bool -> bool -> Set :=
+ | LerNotGt of x <= y : ler_xor_gt x y (y - x) (y - x) true false
+ | GtrNotLe of y < x : ler_xor_gt x y (x - y) (x - y) false true.
+
+CoInductive ltr_xor_ge (x y : R) : R -> R -> bool -> bool -> Set :=
+ | LtrNotGe of x < y : ltr_xor_ge x y (y - x) (y - x) false true
+ | GerNotLt of y <= x : ltr_xor_ge x y (x - y) (x - y) true false.
+
+CoInductive comparer x y : R -> R ->
+ bool -> bool -> bool -> bool -> bool -> bool -> Set :=
+ | ComparerLt of x < y : comparer x y (y - x) (y - x)
+ false false true false true false
+ | ComparerGt of x > y : comparer x y (x - y) (x - y)
+ false false false true false true
+ | ComparerEq of x = y : comparer x y 0 0
+ true true true true false false.
+
+Lemma real_lerP x y :
+ x \is real -> y \is real ->
+ ler_xor_gt x y `|x - y| `|y - x| (x <= y) (y < x).
+Proof.
+move=> xR /(real_leVge xR); have [le_xy _|Nle_xy /= le_yx] := boolP (_ <= _).
+ have [/(ler_lt_trans le_xy)|] := boolP (_ < _); first by rewrite ltrr.
+ by rewrite ler0_norm ?ger0_norm ?subr_cp0 ?opprB //; constructor.
+have [lt_yx|] := boolP (_ < _).
+ by rewrite ger0_norm ?ler0_norm ?subr_cp0 ?opprB //; constructor.
+by rewrite ltr_def le_yx andbT negbK=> /eqP exy; rewrite exy lerr in Nle_xy.
+Qed.
+
+Lemma real_ltrP x y :
+ x \is real -> y \is real ->
+ ltr_xor_ge x y `|x - y| `|y - x| (y <= x) (x < y).
+Proof. by move=> xR yR; case: real_lerP=> //; constructor. Qed.
+
+Lemma real_ltrNge : {in real &, forall x y, (x < y) = ~~ (y <= x)}.
+Proof. by move=> x y xR yR /=; case: real_lerP. Qed.
+
+Lemma real_lerNgt : {in real &, forall x y, (x <= y) = ~~ (y < x)}.
+Proof. by move=> x y xR yR /=; case: real_lerP. Qed.
+
+Lemma real_ltrgtP x y :
+ x \is real -> y \is real ->
+ comparer x y `|x - y| `|y - x|
+ (y == x) (x == y) (x <= y) (y <= x) (x < y) (x > y).
+Proof.
+move=> xR yR; case: real_lerP => // [le_yx|lt_xy]; last first.
+ by rewrite gtr_eqF // ltr_eqF // ler_gtF ?ltrW //; constructor.
+case: real_lerP => // [le_xy|lt_yx]; last first.
+ by rewrite ltr_eqF // gtr_eqF //; constructor.
+have /eqP ->: x == y by rewrite eqr_le le_yx le_xy.
+by rewrite subrr eqxx; constructor.
+Qed.
+
+CoInductive ger0_xor_lt0 (x : R) : R -> bool -> bool -> Set :=
+ | Ger0NotLt0 of 0 <= x : ger0_xor_lt0 x x false true
+ | Ltr0NotGe0 of x < 0 : ger0_xor_lt0 x (- x) true false.
+
+CoInductive ler0_xor_gt0 (x : R) : R -> bool -> bool -> Set :=
+ | Ler0NotLe0 of x <= 0 : ler0_xor_gt0 x (- x) false true
+ | Gtr0NotGt0 of 0 < x : ler0_xor_gt0 x x true false.
+
+CoInductive comparer0 x :
+ R -> bool -> bool -> bool -> bool -> bool -> bool -> Set :=
+ | ComparerGt0 of 0 < x : comparer0 x x false false false true false true
+ | ComparerLt0 of x < 0 : comparer0 x (- x) false false true false true false
+ | ComparerEq0 of x = 0 : comparer0 x 0 true true true true false false.
+
+Lemma real_ger0P x : x \is real -> ger0_xor_lt0 x `|x| (x < 0) (0 <= x).
+Proof.
+move=> hx; rewrite -{2}[x]subr0; case: real_ltrP;
+by rewrite ?subr0 ?sub0r //; constructor.
+Qed.
+
+Lemma real_ler0P x : x \is real -> ler0_xor_gt0 x `|x| (0 < x) (x <= 0).
+Proof.
+move=> hx; rewrite -{2}[x]subr0; case: real_ltrP;
+by rewrite ?subr0 ?sub0r //; constructor.
+Qed.
+
+Lemma real_ltrgt0P x :
+ x \is real ->
+ comparer0 x `|x| (0 == x) (x == 0) (x <= 0) (0 <= x) (x < 0) (x > 0).
+Proof.
+move=> hx; rewrite -{2}[x]subr0; case: real_ltrgtP;
+by rewrite ?subr0 ?sub0r //; constructor.
+Qed.
+
+Lemma real_neqr_lt : {in real &, forall x y, (x != y) = (x < y) || (y < x)}.
+Proof. by move=> * /=; case: real_ltrgtP. Qed.
+
+Lemma ler_sub_real x y : x <= y -> y - x \is real.
+Proof. by move=> le_xy; rewrite ger0_real // subr_ge0. Qed.
+
+Lemma ger_sub_real x y : x <= y -> x - y \is real.
+Proof. by move=> le_xy; rewrite ler0_real // subr_le0. Qed.
+
+Lemma ler_real y x : x <= y -> (x \is real) = (y \is real).
+Proof. by move=> le_xy; rewrite -(addrNK x y) rpredDl ?ler_sub_real. Qed.
+
+Lemma ger_real x y : y <= x -> (x \is real) = (y \is real).
+Proof. by move=> le_yx; rewrite -(ler_real le_yx). Qed.
+
+Lemma ger1_real x : 1 <= x -> x \is real. Proof. by move=> /ger_real->. Qed.
+Lemma ler1_real x : x <= 1 -> x \is real. Proof. by move=> /ler_real->. Qed.
+
+Lemma Nreal_leF x y : y \is real -> x \notin real -> (x <= y) = false.
+Proof. by move=> yR; apply: contraNF=> /ler_real->. Qed.
+
+Lemma Nreal_geF x y : y \is real -> x \notin real -> (y <= x) = false.
+Proof. by move=> yR; apply: contraNF=> /ger_real->. Qed.
+
+Lemma Nreal_ltF x y : y \is real -> x \notin real -> (x < y) = false.
+Proof. by move=> yR xNR; rewrite ltr_def Nreal_leF ?andbF. Qed.
+
+Lemma Nreal_gtF x y : y \is real -> x \notin real -> (y < x) = false.
+Proof. by move=> yR xNR; rewrite ltr_def Nreal_geF ?andbF. Qed.
+
+(* real wlog *)
+
+Lemma real_wlog_ler P :
+ (forall a b, P b a -> P a b) -> (forall a b, a <= b -> P a b) ->
+ forall a b : R, a \is real -> b \is real -> P a b.
+Proof.
+move=> sP hP a b ha hb; wlog: a b ha hb / a <= b => [hwlog|]; last exact: hP.
+by case: (real_lerP ha hb)=> [/hP //|/ltrW hba]; apply: sP; apply: hP.
+Qed.
+
+Lemma real_wlog_ltr P :
+ (forall a, P a a) -> (forall a b, (P b a -> P a b)) ->
+ (forall a b, a < b -> P a b) ->
+ forall a b : R, a \is real -> b \is real -> P a b.
+Proof.
+move=> rP sP hP; apply: real_wlog_ler=> // a b.
+by rewrite ler_eqVlt; case: (altP (_ =P _))=> [->|] //= _ lab; apply: hP.
+Qed.
+
+(* Monotony of addition *)
+Lemma ler_add2l x : {mono +%R x : y z / y <= z}.
+Proof.
+by move=> y z /=; rewrite -subr_ge0 opprD addrAC addNKr addrC subr_ge0.
+Qed.
+
+Lemma ler_add2r x : {mono +%R^~ x : y z / y <= z}.
+Proof. by move=> y z /=; rewrite ![_ + x]addrC ler_add2l. Qed.
+
+Lemma ltr_add2r z x y : (x + z < y + z) = (x < y).
+Proof. by rewrite (lerW_mono (ler_add2r _)). Qed.
+
+Lemma ltr_add2l z x y : (z + x < z + y) = (x < y).
+Proof. by rewrite (lerW_mono (ler_add2l _)). Qed.
+
+Definition ler_add2 := (ler_add2l, ler_add2r).
+Definition ltr_add2 := (ltr_add2l, ltr_add2r).
+Definition lter_add2 := (ler_add2, ltr_add2).
+
+(* Addition, subtraction and transitivity *)
+Lemma ler_add x y z t : x <= y -> z <= t -> x + z <= y + t.
+Proof. by move=> lxy lzt; rewrite (@ler_trans _ (y + z)) ?lter_add2. Qed.
+
+Lemma ler_lt_add x y z t : x <= y -> z < t -> x + z < y + t.
+Proof. by move=> lxy lzt; rewrite (@ler_lt_trans _ (y + z)) ?lter_add2. Qed.
+
+Lemma ltr_le_add x y z t : x < y -> z <= t -> x + z < y + t.
+Proof. by move=> lxy lzt; rewrite (@ltr_le_trans _ (y + z)) ?lter_add2. Qed.
+
+Lemma ltr_add x y z t : x < y -> z < t -> x + z < y + t.
+Proof. by move=> lxy lzt; rewrite ltr_le_add // ltrW. Qed.
+
+Lemma ler_sub x y z t : x <= y -> t <= z -> x - z <= y - t.
+Proof. by move=> lxy ltz; rewrite ler_add // lter_opp2. Qed.
+
+Lemma ler_lt_sub x y z t : x <= y -> t < z -> x - z < y - t.
+Proof. by move=> lxy lzt; rewrite ler_lt_add // lter_opp2. Qed.
+
+Lemma ltr_le_sub x y z t : x < y -> t <= z -> x - z < y - t.
+Proof. by move=> lxy lzt; rewrite ltr_le_add // lter_opp2. Qed.
+
+Lemma ltr_sub x y z t : x < y -> t < z -> x - z < y - t.
+Proof. by move=> lxy lzt; rewrite ltr_add // lter_opp2. Qed.
+
+Lemma ler_subl_addr x y z : (x - y <= z) = (x <= z + y).
+Proof. by rewrite (monoLR (addrK _) (ler_add2r _)). Qed.
+
+Lemma ltr_subl_addr x y z : (x - y < z) = (x < z + y).
+Proof. by rewrite (monoLR (addrK _) (ltr_add2r _)). Qed.
+
+Lemma ler_subr_addr x y z : (x <= y - z) = (x + z <= y).
+Proof. by rewrite (monoLR (addrNK _) (ler_add2r _)). Qed.
+
+Lemma ltr_subr_addr x y z : (x < y - z) = (x + z < y).
+Proof. by rewrite (monoLR (addrNK _) (ltr_add2r _)). Qed.
+
+Definition ler_sub_addr := (ler_subl_addr, ler_subr_addr).
+Definition ltr_sub_addr := (ltr_subl_addr, ltr_subr_addr).
+Definition lter_sub_addr := (ler_sub_addr, ltr_sub_addr).
+
+Lemma ler_subl_addl x y z : (x - y <= z) = (x <= y + z).
+Proof. by rewrite lter_sub_addr addrC. Qed.
+
+Lemma ltr_subl_addl x y z : (x - y < z) = (x < y + z).
+Proof. by rewrite lter_sub_addr addrC. Qed.
+
+Lemma ler_subr_addl x y z : (x <= y - z) = (z + x <= y).
+Proof. by rewrite lter_sub_addr addrC. Qed.
+
+Lemma ltr_subr_addl x y z : (x < y - z) = (z + x < y).
+Proof. by rewrite lter_sub_addr addrC. Qed.
+
+Definition ler_sub_addl := (ler_subl_addl, ler_subr_addl).
+Definition ltr_sub_addl := (ltr_subl_addl, ltr_subr_addl).
+Definition lter_sub_addl := (ler_sub_addl, ltr_sub_addl).
+
+Lemma ler_addl x y : (x <= x + y) = (0 <= y).
+Proof. by rewrite -{1}[x]addr0 lter_add2. Qed.
+
+Lemma ltr_addl x y : (x < x + y) = (0 < y).
+Proof. by rewrite -{1}[x]addr0 lter_add2. Qed.
+
+Lemma ler_addr x y : (x <= y + x) = (0 <= y).
+Proof. by rewrite -{1}[x]add0r lter_add2. Qed.
+
+Lemma ltr_addr x y : (x < y + x) = (0 < y).
+Proof. by rewrite -{1}[x]add0r lter_add2. Qed.
+
+Lemma ger_addl x y : (x + y <= x) = (y <= 0).
+Proof. by rewrite -{2}[x]addr0 lter_add2. Qed.
+
+Lemma gtr_addl x y : (x + y < x) = (y < 0).
+Proof. by rewrite -{2}[x]addr0 lter_add2. Qed.
+
+Lemma ger_addr x y : (y + x <= x) = (y <= 0).
+Proof. by rewrite -{2}[x]add0r lter_add2. Qed.
+
+Lemma gtr_addr x y : (y + x < x) = (y < 0).
+Proof. by rewrite -{2}[x]add0r lter_add2. Qed.
+
+Definition cpr_add := (ler_addl, ler_addr, ger_addl, ger_addl,
+ ltr_addl, ltr_addr, gtr_addl, gtr_addl).
+
+(* Addition with left member knwon to be positive/negative *)
+Lemma ler_paddl y x z : 0 <= x -> y <= z -> y <= x + z.
+Proof. by move=> *; rewrite -[y]add0r ler_add. Qed.
+
+Lemma ltr_paddl y x z : 0 <= x -> y < z -> y < x + z.
+Proof. by move=> *; rewrite -[y]add0r ler_lt_add. Qed.
+
+Lemma ltr_spaddl y x z : 0 < x -> y <= z -> y < x + z.
+Proof. by move=> *; rewrite -[y]add0r ltr_le_add. Qed.
+
+Lemma ltr_spsaddl y x z : 0 < x -> y < z -> y < x + z.
+Proof. by move=> *; rewrite -[y]add0r ltr_add. Qed.
+
+Lemma ler_naddl y x z : x <= 0 -> y <= z -> x + y <= z.
+Proof. by move=> *; rewrite -[z]add0r ler_add. Qed.
+
+Lemma ltr_naddl y x z : x <= 0 -> y < z -> x + y < z.
+Proof. by move=> *; rewrite -[z]add0r ler_lt_add. Qed.
+
+Lemma ltr_snaddl y x z : x < 0 -> y <= z -> x + y < z.
+Proof. by move=> *; rewrite -[z]add0r ltr_le_add. Qed.
+
+Lemma ltr_snsaddl y x z : x < 0 -> y < z -> x + y < z.
+Proof. by move=> *; rewrite -[z]add0r ltr_add. Qed.
+
+(* Addition with right member we know positive/negative *)
+Lemma ler_paddr y x z : 0 <= x -> y <= z -> y <= z + x.
+Proof. by move=> *; rewrite [_ + x]addrC ler_paddl. Qed.
+
+Lemma ltr_paddr y x z : 0 <= x -> y < z -> y < z + x.
+Proof. by move=> *; rewrite [_ + x]addrC ltr_paddl. Qed.
+
+Lemma ltr_spaddr y x z : 0 < x -> y <= z -> y < z + x.
+Proof. by move=> *; rewrite [_ + x]addrC ltr_spaddl. Qed.
+
+Lemma ltr_spsaddr y x z : 0 < x -> y < z -> y < z + x.
+Proof. by move=> *; rewrite [_ + x]addrC ltr_spsaddl. Qed.
+
+Lemma ler_naddr y x z : x <= 0 -> y <= z -> y + x <= z.
+Proof. by move=> *; rewrite [_ + x]addrC ler_naddl. Qed.
+
+Lemma ltr_naddr y x z : x <= 0 -> y < z -> y + x < z.
+Proof. by move=> *; rewrite [_ + x]addrC ltr_naddl. Qed.
+
+Lemma ltr_snaddr y x z : x < 0 -> y <= z -> y + x < z.
+Proof. by move=> *; rewrite [_ + x]addrC ltr_snaddl. Qed.
+
+Lemma ltr_snsaddr y x z : x < 0 -> y < z -> y + x < z.
+Proof. by move=> *; rewrite [_ + x]addrC ltr_snsaddl. Qed.
+
+(* x and y have the same sign and their sum is null *)
+Lemma paddr_eq0 (x y : R) :
+ 0 <= x -> 0 <= y -> (x + y == 0) = (x == 0) && (y == 0).
+Proof.
+rewrite le0r; case/orP=> [/eqP->|hx]; first by rewrite add0r eqxx.
+by rewrite (gtr_eqF hx) /= => hy; rewrite gtr_eqF // ltr_spaddl.
+Qed.
+
+Lemma naddr_eq0 (x y : R) :
+ x <= 0 -> y <= 0 -> (x + y == 0) = (x == 0) && (y == 0).
+Proof.
+by move=> lex0 ley0; rewrite -oppr_eq0 opprD paddr_eq0 ?oppr_cp0 // !oppr_eq0.
+Qed.
+
+Lemma addr_ss_eq0 (x y : R) :
+ (0 <= x) && (0 <= y) || (x <= 0) && (y <= 0) ->
+ (x + y == 0) = (x == 0) && (y == 0).
+Proof. by case/orP=> /andP []; [apply: paddr_eq0 | apply: naddr_eq0]. Qed.
+
+(* big sum and ler *)
+Lemma sumr_ge0 I (r : seq I) (P : pred I) (F : I -> R) :
+ (forall i, P i -> (0 <= F i)) -> 0 <= \sum_(i <- r | P i) (F i).
+Proof. exact: (big_ind _ _ (@ler_paddl 0)). Qed.
+
+Lemma ler_sum I (r : seq I) (P : pred I) (F G : I -> R) :
+ (forall i, P i -> F i <= G i) ->
+ \sum_(i <- r | P i) F i <= \sum_(i <- r | P i) G i.
+Proof. exact: (big_ind2 _ (lerr _) ler_add). Qed.
+
+Lemma psumr_eq0 (I : eqType) (r : seq I) (P : pred I) (F : I -> R) :
+ (forall i, P i -> 0 <= F i) ->
+ (\sum_(i <- r | P i) (F i) == 0) = (all (fun i => (P i) ==> (F i == 0)) r).
+Proof.
+elim: r=> [|a r ihr hr] /=; rewrite (big_nil, big_cons); first by rewrite eqxx.
+by case: ifP=> pa /=; rewrite ?paddr_eq0 ?ihr ?hr // sumr_ge0.
+Qed.
+
+(* :TODO: Cyril : See which form to keep *)
+Lemma psumr_eq0P (I : finType) (P : pred I) (F : I -> R) :
+ (forall i, P i -> 0 <= F i) -> \sum_(i | P i) F i = 0 ->
+ (forall i, P i -> F i = 0).
+Proof.
+move=> F_ge0 /eqP; rewrite psumr_eq0 // -big_all big_andE => /forallP hF i Pi.
+by move: (hF i); rewrite implyTb Pi /= => /eqP.
+Qed.
+
+(* mulr and ler/ltr *)
+
+Lemma ler_pmul2l x : 0 < x -> {mono *%R x : x y / x <= y}.
+Proof.
+by move=> x_gt0 y z /=; rewrite -subr_ge0 -mulrBr pmulr_rge0 // subr_ge0.
+Qed.
+
+Lemma ltr_pmul2l x : 0 < x -> {mono *%R x : x y / x < y}.
+Proof. by move=> x_gt0; apply: lerW_mono (ler_pmul2l _). Qed.
+
+Definition lter_pmul2l := (ler_pmul2l, ltr_pmul2l).
+
+Lemma ler_pmul2r x : 0 < x -> {mono *%R^~ x : x y / x <= y}.
+Proof. by move=> x_gt0 y z /=; rewrite ![_ * x]mulrC ler_pmul2l. Qed.
+
+Lemma ltr_pmul2r x : 0 < x -> {mono *%R^~ x : x y / x < y}.
+Proof. by move=> x_gt0; apply: lerW_mono (ler_pmul2r _). Qed.
+
+Definition lter_pmul2r := (ler_pmul2r, ltr_pmul2r).
+
+Lemma ler_nmul2l x : x < 0 -> {mono *%R x : x y /~ x <= y}.
+Proof.
+by move=> x_lt0 y z /=; rewrite -ler_opp2 -!mulNr ler_pmul2l ?oppr_gt0.
+Qed.
+
+Lemma ltr_nmul2l x : x < 0 -> {mono *%R x : x y /~ x < y}.
+Proof. by move=> x_lt0; apply: lerW_nmono (ler_nmul2l _). Qed.
+
+Definition lter_nmul2l := (ler_nmul2l, ltr_nmul2l).
+
+Lemma ler_nmul2r x : x < 0 -> {mono *%R^~ x : x y /~ x <= y}.
+Proof. by move=> x_lt0 y z /=; rewrite ![_ * x]mulrC ler_nmul2l. Qed.
+
+Lemma ltr_nmul2r x : x < 0 -> {mono *%R^~ x : x y /~ x < y}.
+Proof. by move=> x_lt0; apply: lerW_nmono (ler_nmul2r _). Qed.
+
+Definition lter_nmul2r := (ler_nmul2r, ltr_nmul2r).
+
+Lemma ler_wpmul2l x : 0 <= x -> {homo *%R x : y z / y <= z}.
+Proof.
+by rewrite le0r => /orP[/eqP-> y z | /ler_pmul2l/mono2W//]; rewrite !mul0r.
+Qed.
+
+Lemma ler_wpmul2r x : 0 <= x -> {homo *%R^~ x : y z / y <= z}.
+Proof. by move=> x_ge0 y z leyz; rewrite ![_ * x]mulrC ler_wpmul2l. Qed.
+
+Lemma ler_wnmul2l x : x <= 0 -> {homo *%R x : y z /~ y <= z}.
+Proof.
+by move=> x_le0 y z leyz; rewrite -![x * _]mulrNN ler_wpmul2l ?lter_oppE.
+Qed.
+
+Lemma ler_wnmul2r x : x <= 0 -> {homo *%R^~ x : y z /~ y <= z}.
+Proof.
+by move=> x_le0 y z leyz; rewrite -![_ * x]mulrNN ler_wpmul2r ?lter_oppE.
+Qed.
+
+(* Binary forms, for backchaining. *)
+
+Lemma ler_pmul x1 y1 x2 y2 :
+ 0 <= x1 -> 0 <= x2 -> x1 <= y1 -> x2 <= y2 -> x1 * x2 <= y1 * y2.
+Proof.
+move=> x1ge0 x2ge0 le_xy1 le_xy2; have y1ge0 := ler_trans x1ge0 le_xy1.
+exact: ler_trans (ler_wpmul2r x2ge0 le_xy1) (ler_wpmul2l y1ge0 le_xy2).
+Qed.
+
+Lemma ltr_pmul x1 y1 x2 y2 :
+ 0 <= x1 -> 0 <= x2 -> x1 < y1 -> x2 < y2 -> x1 * x2 < y1 * y2.
+Proof.
+move=> x1ge0 x2ge0 lt_xy1 lt_xy2; have y1gt0 := ler_lt_trans x1ge0 lt_xy1.
+by rewrite (ler_lt_trans (ler_wpmul2r x2ge0 (ltrW lt_xy1))) ?ltr_pmul2l.
+Qed.
+
+(* complement for x *+ n and <= or < *)
+
+Lemma ler_pmuln2r n : (0 < n)%N -> {mono (@GRing.natmul R)^~ n : x y / x <= y}.
+Proof.
+by case: n => // n _ x y /=; rewrite -mulr_natl -[y *+ _]mulr_natl ler_pmul2l.
+Qed.
+
+Lemma ltr_pmuln2r n : (0 < n)%N -> {mono (@GRing.natmul R)^~ n : x y / x < y}.
+Proof. by move/ler_pmuln2r/lerW_mono. Qed.
+
+Lemma pmulrnI n : (0 < n)%N -> injective ((@GRing.natmul R)^~ n).
+Proof. by move/ler_pmuln2r/mono_inj. Qed.
+
+Lemma eqr_pmuln2r n : (0 < n)%N -> {mono (@GRing.natmul R)^~ n : x y / x == y}.
+Proof. by move/pmulrnI/inj_eq. Qed.
+
+Lemma pmulrn_lgt0 x n : (0 < n)%N -> (0 < x *+ n) = (0 < x).
+Proof. by move=> n_gt0; rewrite -(mul0rn _ n) ltr_pmuln2r // mul0rn. Qed.
+
+Lemma pmulrn_llt0 x n : (0 < n)%N -> (x *+ n < 0) = (x < 0).
+Proof. by move=> n_gt0; rewrite -(mul0rn _ n) ltr_pmuln2r // mul0rn. Qed.
+
+Lemma pmulrn_lge0 x n : (0 < n)%N -> (0 <= x *+ n) = (0 <= x).
+Proof. by move=> n_gt0; rewrite -(mul0rn _ n) ler_pmuln2r // mul0rn. Qed.
+
+Lemma pmulrn_lle0 x n : (0 < n)%N -> (x *+ n <= 0) = (x <= 0).
+Proof. by move=> n_gt0; rewrite -(mul0rn _ n) ler_pmuln2r // mul0rn. Qed.
+
+Lemma ltr_wmuln2r x y n : x < y -> (x *+ n < y *+ n) = (0 < n)%N.
+Proof. by move=> ltxy; case: n=> // n; rewrite ltr_pmuln2r. Qed.
+
+Lemma ltr_wpmuln2r n : (0 < n)%N -> {homo (@GRing.natmul R)^~ n : x y / x < y}.
+Proof. by move=> n_gt0 x y /= / ltr_wmuln2r ->. Qed.
+
+Lemma ler_wmuln2r n : {homo (@GRing.natmul R)^~ n : x y / x <= y}.
+Proof. by move=> x y hxy /=; case: n=> // n; rewrite ler_pmuln2r. Qed.
+
+Lemma mulrn_wge0 x n : 0 <= x -> 0 <= x *+ n.
+Proof. by move=> /(ler_wmuln2r n); rewrite mul0rn. Qed.
+
+Lemma mulrn_wle0 x n : x <= 0 -> x *+ n <= 0.
+Proof. by move=> /(ler_wmuln2r n); rewrite mul0rn. Qed.
+
+Lemma ler_muln2r n x y : (x *+ n <= y *+ n) = ((n == 0%N) || (x <= y)).
+Proof. by case: n => [|n]; rewrite ?lerr ?eqxx // ler_pmuln2r. Qed.
+
+Lemma ltr_muln2r n x y : (x *+ n < y *+ n) = ((0 < n)%N && (x < y)).
+Proof. by case: n => [|n]; rewrite ?lerr ?eqxx // ltr_pmuln2r. Qed.
+
+Lemma eqr_muln2r n x y : (x *+ n == y *+ n) = (n == 0)%N || (x == y).
+Proof. by rewrite !eqr_le !ler_muln2r -orb_andr. Qed.
+
+(* More characteristic zero properties. *)
+
+Lemma mulrn_eq0 x n : (x *+ n == 0) = ((n == 0)%N || (x == 0)).
+Proof. by rewrite -mulr_natl mulf_eq0 pnatr_eq0. Qed.
+
+Lemma mulrIn x : x != 0 -> injective (GRing.natmul x).
+Proof.
+move=> x_neq0 m n; without loss /subnK <-: m n / (n <= m)%N.
+ by move=> IH eq_xmn; case/orP: (leq_total m n) => /IH->.
+by move/eqP; rewrite mulrnDr -subr_eq0 addrK mulrn_eq0 => /predU1P[-> | /idPn].
+Qed.
+
+Lemma ler_wpmuln2l x :
+ 0 <= x -> {homo (@GRing.natmul R x) : m n / (m <= n)%N >-> m <= n}.
+Proof. by move=> xge0 m n /subnK <-; rewrite mulrnDr ler_paddl ?mulrn_wge0. Qed.
+
+Lemma ler_wnmuln2l x :
+ x <= 0 -> {homo (@GRing.natmul R x) : m n / (n <= m)%N >-> m <= n}.
+Proof.
+by move=> xle0 m n hmn /=; rewrite -ler_opp2 -!mulNrn ler_wpmuln2l // oppr_cp0.
+Qed.
+
+Lemma mulrn_wgt0 x n : 0 < x -> 0 < x *+ n = (0 < n)%N.
+Proof. by case: n => // n hx; rewrite pmulrn_lgt0. Qed.
+
+Lemma mulrn_wlt0 x n : x < 0 -> x *+ n < 0 = (0 < n)%N.
+Proof. by case: n => // n hx; rewrite pmulrn_llt0. Qed.
+
+Lemma ler_pmuln2l x :
+ 0 < x -> {mono (@GRing.natmul R x) : m n / (m <= n)%N >-> m <= n}.
+Proof.
+move=> x_gt0 m n /=; case: leqP => hmn; first by rewrite ler_wpmuln2l // ltrW.
+rewrite -(subnK (ltnW hmn)) mulrnDr ger_addr ltr_geF //.
+by rewrite mulrn_wgt0 // subn_gt0.
+Qed.
+
+Lemma ltr_pmuln2l x :
+ 0 < x -> {mono (@GRing.natmul R x) : m n / (m < n)%N >-> m < n}.
+Proof. by move=> x_gt0; apply: leq_lerW_mono (ler_pmuln2l _). Qed.
+
+Lemma ler_nmuln2l x :
+ x < 0 -> {mono (@GRing.natmul R x) : m n / (n <= m)%N >-> m <= n}.
+Proof.
+by move=> x_lt0 m n /=; rewrite -ler_opp2 -!mulNrn ler_pmuln2l // oppr_gt0.
+Qed.
+
+Lemma ltr_nmuln2l x :
+ x < 0 -> {mono (@GRing.natmul R x) : m n / (n < m)%N >-> m < n}.
+Proof. by move=> x_lt0; apply: leq_lerW_nmono (ler_nmuln2l _). Qed.
+
+Lemma ler_nat m n : (m%:R <= n%:R :> R) = (m <= n)%N.
+Proof. by rewrite ler_pmuln2l. Qed.
+
+Lemma ltr_nat m n : (m%:R < n%:R :> R) = (m < n)%N.
+Proof. by rewrite ltr_pmuln2l. Qed.
+
+Lemma eqr_nat m n : (m%:R == n%:R :> R) = (m == n)%N.
+Proof. by rewrite (inj_eq (mulrIn _)) ?oner_eq0. Qed.
+
+Lemma pnatr_eq1 n : (n%:R == 1 :> R) = (n == 1)%N.
+Proof. exact: eqr_nat 1%N. Qed.
+
+Lemma lern0 n : (n%:R <= 0 :> R) = (n == 0%N).
+Proof. by rewrite -[0]/0%:R ler_nat leqn0. Qed.
+
+Lemma ltrn0 n : (n%:R < 0 :> R) = false.
+Proof. by rewrite -[0]/0%:R ltr_nat ltn0. Qed.
+
+Lemma ler1n n : 1 <= n%:R :> R = (1 <= n)%N. Proof. by rewrite -ler_nat. Qed.
+Lemma ltr1n n : 1 < n%:R :> R = (1 < n)%N. Proof. by rewrite -ltr_nat. Qed.
+Lemma lern1 n : n%:R <= 1 :> R = (n <= 1)%N. Proof. by rewrite -ler_nat. Qed.
+Lemma ltrn1 n : n%:R < 1 :> R = (n < 1)%N. Proof. by rewrite -ltr_nat. Qed.
+
+Lemma ltrN10 : -1 < 0 :> R. Proof. by rewrite oppr_lt0. Qed.
+Lemma lerN10 : -1 <= 0 :> R. Proof. by rewrite oppr_le0. Qed.
+Lemma ltr10 : 1 < 0 :> R = false. Proof. by rewrite ler_gtF. Qed.
+Lemma ler10 : 1 <= 0 :> R = false. Proof. by rewrite ltr_geF. Qed.
+Lemma ltr0N1 : 0 < -1 :> R = false. Proof. by rewrite ler_gtF // lerN10. Qed.
+Lemma ler0N1 : 0 <= -1 :> R = false. Proof. by rewrite ltr_geF // ltrN10. Qed.
+
+Lemma pmulrn_rgt0 x n : 0 < x -> 0 < x *+ n = (0 < n)%N.
+Proof. by move=> x_gt0; rewrite -(mulr0n x) ltr_pmuln2l. Qed.
+
+Lemma pmulrn_rlt0 x n : 0 < x -> x *+ n < 0 = false.
+Proof. by move=> x_gt0; rewrite -(mulr0n x) ltr_pmuln2l. Qed.
+
+Lemma pmulrn_rge0 x n : 0 < x -> 0 <= x *+ n.
+Proof. by move=> x_gt0; rewrite -(mulr0n x) ler_pmuln2l. Qed.
+
+Lemma pmulrn_rle0 x n : 0 < x -> x *+ n <= 0 = (n == 0)%N.
+Proof. by move=> x_gt0; rewrite -(mulr0n x) ler_pmuln2l ?leqn0. Qed.
+
+Lemma nmulrn_rgt0 x n : x < 0 -> 0 < x *+ n = false.
+Proof. by move=> x_lt0; rewrite -(mulr0n x) ltr_nmuln2l. Qed.
+
+Lemma nmulrn_rge0 x n : x < 0 -> 0 <= x *+ n = (n == 0)%N.
+Proof. by move=> x_lt0; rewrite -(mulr0n x) ler_nmuln2l ?leqn0. Qed.
+
+Lemma nmulrn_rle0 x n : x < 0 -> x *+ n <= 0.
+Proof. by move=> x_lt0; rewrite -(mulr0n x) ler_nmuln2l. Qed.
+
+(* (x * y) compared to 0 *)
+(* Remark : pmulr_rgt0 and pmulr_rge0 are defined above *)
+
+(* x positive and y right *)
+Lemma pmulr_rlt0 x y : 0 < x -> (x * y < 0) = (y < 0).
+Proof. by move=> x_gt0; rewrite -oppr_gt0 -mulrN pmulr_rgt0 // oppr_gt0. Qed.
+
+Lemma pmulr_rle0 x y : 0 < x -> (x * y <= 0) = (y <= 0).
+Proof. by move=> x_gt0; rewrite -oppr_ge0 -mulrN pmulr_rge0 // oppr_ge0. Qed.
+
+(* x positive and y left *)
+Lemma pmulr_lgt0 x y : 0 < x -> (0 < y * x) = (0 < y).
+Proof. by move=> x_gt0; rewrite mulrC pmulr_rgt0. Qed.
+
+Lemma pmulr_lge0 x y : 0 < x -> (0 <= y * x) = (0 <= y).
+Proof. by move=> x_gt0; rewrite mulrC pmulr_rge0. Qed.
+
+Lemma pmulr_llt0 x y : 0 < x -> (y * x < 0) = (y < 0).
+Proof. by move=> x_gt0; rewrite mulrC pmulr_rlt0. Qed.
+
+Lemma pmulr_lle0 x y : 0 < x -> (y * x <= 0) = (y <= 0).
+Proof. by move=> x_gt0; rewrite mulrC pmulr_rle0. Qed.
+
+(* x negative and y right *)
+Lemma nmulr_rgt0 x y : x < 0 -> (0 < x * y) = (y < 0).
+Proof. by move=> x_lt0; rewrite -mulrNN pmulr_rgt0 lter_oppE. Qed.
+
+Lemma nmulr_rge0 x y : x < 0 -> (0 <= x * y) = (y <= 0).
+Proof. by move=> x_lt0; rewrite -mulrNN pmulr_rge0 lter_oppE. Qed.
+
+Lemma nmulr_rlt0 x y : x < 0 -> (x * y < 0) = (0 < y).
+Proof. by move=> x_lt0; rewrite -mulrNN pmulr_rlt0 lter_oppE. Qed.
+
+Lemma nmulr_rle0 x y : x < 0 -> (x * y <= 0) = (0 <= y).
+Proof. by move=> x_lt0; rewrite -mulrNN pmulr_rle0 lter_oppE. Qed.
+
+(* x negative and y left *)
+Lemma nmulr_lgt0 x y : x < 0 -> (0 < y * x) = (y < 0).
+Proof. by move=> x_lt0; rewrite mulrC nmulr_rgt0. Qed.
+
+Lemma nmulr_lge0 x y : x < 0 -> (0 <= y * x) = (y <= 0).
+Proof. by move=> x_lt0; rewrite mulrC nmulr_rge0. Qed.
+
+Lemma nmulr_llt0 x y : x < 0 -> (y * x < 0) = (0 < y).
+Proof. by move=> x_lt0; rewrite mulrC nmulr_rlt0. Qed.
+
+Lemma nmulr_lle0 x y : x < 0 -> (y * x <= 0) = (0 <= y).
+Proof. by move=> x_lt0; rewrite mulrC nmulr_rle0. Qed.
+
+(* weak and symmetric lemmas *)
+Lemma mulr_ge0 x y : 0 <= x -> 0 <= y -> 0 <= x * y.
+Proof. by move=> x_ge0 y_ge0; rewrite -(mulr0 x) ler_wpmul2l. Qed.
+
+Lemma mulr_le0 x y : x <= 0 -> y <= 0 -> 0 <= x * y.
+Proof. by move=> x_le0 y_le0; rewrite -(mulr0 x) ler_wnmul2l. Qed.
+
+Lemma mulr_ge0_le0 x y : 0 <= x -> y <= 0 -> x * y <= 0.
+Proof. by move=> x_le0 y_le0; rewrite -(mulr0 x) ler_wpmul2l. Qed.
+
+Lemma mulr_le0_ge0 x y : x <= 0 -> 0 <= y -> x * y <= 0.
+Proof. by move=> x_le0 y_le0; rewrite -(mulr0 x) ler_wnmul2l. Qed.
+
+(* mulr_gt0 with only one case *)
+
+Lemma mulr_gt0 x y : 0 < x -> 0 < y -> 0 < x * y.
+Proof. by move=> x_gt0 y_gt0; rewrite pmulr_rgt0. Qed.
+
+(* Iterated products *)
+
+Lemma prodr_ge0 I r (P : pred I) (E : I -> R) :
+ (forall i, P i -> 0 <= E i) -> 0 <= \prod_(i <- r | P i) E i.
+Proof. by move=> Ege0; rewrite -nnegrE rpred_prod. Qed.
+
+Lemma prodr_gt0 I r (P : pred I) (E : I -> R) :
+ (forall i, P i -> 0 < E i) -> 0 < \prod_(i <- r | P i) E i.
+Proof. by move=> Ege0; rewrite -posrE rpred_prod. Qed.
+
+Lemma ler_prod I r (P : pred I) (E1 E2 : I -> R) :
+ (forall i, P i -> 0 <= E1 i <= E2 i) ->
+ \prod_(i <- r | P i) E1 i <= \prod_(i <- r | P i) E2 i.
+Proof.
+move=> leE12; elim/(big_load (fun x => 0 <= x)): _.
+elim/big_rec2: _ => // i x2 x1 /leE12/andP[le0Ei leEi12] [x1ge0 le_x12].
+by rewrite mulr_ge0 // ler_pmul.
+Qed.
+
+Lemma ltr_prod (E1 E2 : nat -> R) (n m : nat) :
+ (m < n)%N -> (forall i, (m <= i < n)%N -> 0 <= E1 i < E2 i) ->
+ \prod_(m <= i < n) E1 i < \prod_(m <= i < n) E2 i.
+Proof.
+elim: n m => // n ihn m; rewrite ltnS leq_eqVlt; case/orP => [/eqP -> | ltnm hE].
+ by move/(_ n) => /andb_idr; rewrite !big_nat1 leqnn ltnSn /=; case/andP.
+rewrite big_nat_recr ?[X in _ < X]big_nat_recr ?(ltnW ltnm) //=.
+move/andb_idr: (hE n); rewrite leqnn ltnW //=; case/andP => h1n h12n.
+rewrite big_nat_cond [X in _ < X * _]big_nat_cond; apply: ltr_pmul => //=.
+- apply: prodr_ge0 => i; rewrite andbT; case/andP=> hm hn.
+ by move/andb_idr: (hE i); rewrite hm /= ltnS ltnW //=; case/andP.
+rewrite -!big_nat_cond; apply: ihn => // i /andP [hm hn]; apply: hE.
+by rewrite hm ltnW.
+Qed.
+
+(* real of mul *)
+
+Lemma realMr x y : x != 0 -> x \is real -> (x * y \is real) = (y \is real).
+Proof.
+move=> x_neq0 xR; case: real_ltrgtP x_neq0 => // hx _; rewrite !realE.
+ by rewrite nmulr_rge0 // nmulr_rle0 // orbC.
+by rewrite pmulr_rge0 // pmulr_rle0 // orbC.
+Qed.
+
+Lemma realrM x y : y != 0 -> y \is real -> (x * y \is real) = (x \is real).
+Proof. by move=> y_neq0 yR; rewrite mulrC realMr. Qed.
+
+Lemma realM : {in real &, forall x y, x * y \is real}.
+Proof. exact: rpredM. Qed.
+
+Lemma realrMn x n : (n != 0)%N -> (x *+ n \is real) = (x \is real).
+Proof. by move=> n_neq0; rewrite -mulr_natl realMr ?realn ?pnatr_eq0. Qed.
+
+(* ler/ltr and multiplication between a positive/negative *)
+
+Lemma ger_pmull x y : 0 < y -> (x * y <= y) = (x <= 1).
+Proof. by move=> hy; rewrite -{2}[y]mul1r ler_pmul2r. Qed.
+
+Lemma gtr_pmull x y : 0 < y -> (x * y < y) = (x < 1).
+Proof. by move=> hy; rewrite -{2}[y]mul1r ltr_pmul2r. Qed.
+
+Lemma ger_pmulr x y : 0 < y -> (y * x <= y) = (x <= 1).
+Proof. by move=> hy; rewrite -{2}[y]mulr1 ler_pmul2l. Qed.
+
+Lemma gtr_pmulr x y : 0 < y -> (y * x < y) = (x < 1).
+Proof. by move=> hy; rewrite -{2}[y]mulr1 ltr_pmul2l. Qed.
+
+Lemma ler_pmull x y : 0 < y -> (y <= x * y) = (1 <= x).
+Proof. by move=> hy; rewrite -{1}[y]mul1r ler_pmul2r. Qed.
+
+Lemma ltr_pmull x y : 0 < y -> (y < x * y) = (1 < x).
+Proof. by move=> hy; rewrite -{1}[y]mul1r ltr_pmul2r. Qed.
+
+Lemma ler_pmulr x y : 0 < y -> (y <= y * x) = (1 <= x).
+Proof. by move=> hy; rewrite -{1}[y]mulr1 ler_pmul2l. Qed.
+
+Lemma ltr_pmulr x y : 0 < y -> (y < y * x) = (1 < x).
+Proof. by move=> hy; rewrite -{1}[y]mulr1 ltr_pmul2l. Qed.
+
+Lemma ger_nmull x y : y < 0 -> (x * y <= y) = (1 <= x).
+Proof. by move=> hy; rewrite -{2}[y]mul1r ler_nmul2r. Qed.
+
+Lemma gtr_nmull x y : y < 0 -> (x * y < y) = (1 < x).
+Proof. by move=> hy; rewrite -{2}[y]mul1r ltr_nmul2r. Qed.
+
+Lemma ger_nmulr x y : y < 0 -> (y * x <= y) = (1 <= x).
+Proof. by move=> hy; rewrite -{2}[y]mulr1 ler_nmul2l. Qed.
+
+Lemma gtr_nmulr x y : y < 0 -> (y * x < y) = (1 < x).
+Proof. by move=> hy; rewrite -{2}[y]mulr1 ltr_nmul2l. Qed.
+
+Lemma ler_nmull x y : y < 0 -> (y <= x * y) = (x <= 1).
+Proof. by move=> hy; rewrite -{1}[y]mul1r ler_nmul2r. Qed.
+
+Lemma ltr_nmull x y : y < 0 -> (y < x * y) = (x < 1).
+Proof. by move=> hy; rewrite -{1}[y]mul1r ltr_nmul2r. Qed.
+
+Lemma ler_nmulr x y : y < 0 -> (y <= y * x) = (x <= 1).
+Proof. by move=> hy; rewrite -{1}[y]mulr1 ler_nmul2l. Qed.
+
+Lemma ltr_nmulr x y : y < 0 -> (y < y * x) = (x < 1).
+Proof. by move=> hy; rewrite -{1}[y]mulr1 ltr_nmul2l. Qed.
+
+(* ler/ltr and multiplication between a positive/negative
+ and a exterior (1 <= _) or interior (0 <= _ <= 1) *)
+
+Lemma ler_pemull x y : 0 <= y -> 1 <= x -> y <= x * y.
+Proof. by move=> hy hx; rewrite -{1}[y]mul1r ler_wpmul2r. Qed.
+
+Lemma ler_nemull x y : y <= 0 -> 1 <= x -> x * y <= y.
+Proof. by move=> hy hx; rewrite -{2}[y]mul1r ler_wnmul2r. Qed.
+
+Lemma ler_pemulr x y : 0 <= y -> 1 <= x -> y <= y * x.
+Proof. by move=> hy hx; rewrite -{1}[y]mulr1 ler_wpmul2l. Qed.
+
+Lemma ler_nemulr x y : y <= 0 -> 1 <= x -> y * x <= y.
+Proof. by move=> hy hx; rewrite -{2}[y]mulr1 ler_wnmul2l. Qed.
+
+Lemma ler_pimull x y : 0 <= y -> x <= 1 -> x * y <= y.
+Proof. by move=> hy hx; rewrite -{2}[y]mul1r ler_wpmul2r. Qed.
+
+Lemma ler_nimull x y : y <= 0 -> x <= 1 -> y <= x * y.
+Proof. by move=> hy hx; rewrite -{1}[y]mul1r ler_wnmul2r. Qed.
+
+Lemma ler_pimulr x y : 0 <= y -> x <= 1 -> y * x <= y.
+Proof. by move=> hy hx; rewrite -{2}[y]mulr1 ler_wpmul2l. Qed.
+
+Lemma ler_nimulr x y : y <= 0 -> x <= 1 -> y <= y * x.
+Proof. by move=> hx hy; rewrite -{1}[y]mulr1 ler_wnmul2l. Qed.
+
+Lemma mulr_ile1 x y : 0 <= x -> 0 <= y -> x <= 1 -> y <= 1 -> x * y <= 1.
+Proof. by move=> *; rewrite (@ler_trans _ y) ?ler_pimull. Qed.
+
+Lemma mulr_ilt1 x y : 0 <= x -> 0 <= y -> x < 1 -> y < 1 -> x * y < 1.
+Proof. by move=> *; rewrite (@ler_lt_trans _ y) ?ler_pimull // ltrW. Qed.
+
+Definition mulr_ilte1 := (mulr_ile1, mulr_ilt1).
+
+Lemma mulr_ege1 x y : 1 <= x -> 1 <= y -> 1 <= x * y.
+Proof.
+by move=> le1x le1y; rewrite (@ler_trans _ y) ?ler_pemull // (ler_trans ler01).
+Qed.
+
+Lemma mulr_egt1 x y : 1 < x -> 1 < y -> 1 < x * y.
+Proof.
+by move=> le1x lt1y; rewrite (@ltr_trans _ y) // ltr_pmull // (ltr_trans ltr01).
+Qed.
+Definition mulr_egte1 := (mulr_ege1, mulr_egt1).
+Definition mulr_cp1 := (mulr_ilte1, mulr_egte1).
+
+(* ler and ^-1 *)
+
+Lemma invr_gt0 x : (0 < x^-1) = (0 < x).
+Proof.
+have [ux | nux] := boolP (x \is a GRing.unit); last by rewrite invr_out.
+by apply/idP/idP=> /ltr_pmul2r<-; rewrite mul0r (mulrV, mulVr) ?ltr01.
+Qed.
+
+Lemma invr_ge0 x : (0 <= x^-1) = (0 <= x).
+Proof. by rewrite !le0r invr_gt0 invr_eq0. Qed.
+
+Lemma invr_lt0 x : (x^-1 < 0) = (x < 0).
+Proof. by rewrite -oppr_cp0 -invrN invr_gt0 oppr_cp0. Qed.
+
+Lemma invr_le0 x : (x^-1 <= 0) = (x <= 0).
+Proof. by rewrite -oppr_cp0 -invrN invr_ge0 oppr_cp0. Qed.
+
+Definition invr_gte0 := (invr_ge0, invr_gt0).
+Definition invr_lte0 := (invr_le0, invr_lt0).
+
+Lemma divr_ge0 x y : 0 <= x -> 0 <= y -> 0 <= x / y.
+Proof. by move=> x_ge0 y_ge0; rewrite mulr_ge0 ?invr_ge0. Qed.
+
+Lemma divr_gt0 x y : 0 < x -> 0 < y -> 0 < x / y.
+Proof. by move=> x_gt0 y_gt0; rewrite pmulr_rgt0 ?invr_gt0. Qed.
+
+Lemma realV : {mono (@GRing.inv R) : x / x \is real}.
+Proof. exact: rpredV. Qed.
+
+(* ler and exprn *)
+Lemma exprn_ge0 n x : 0 <= x -> 0 <= x ^+ n.
+Proof. by move=> xge0; rewrite -nnegrE rpredX. Qed.
+
+Lemma realX n : {in real, forall x, x ^+ n \is real}.
+Proof. exact: rpredX. Qed.
+
+Lemma exprn_gt0 n x : 0 < x -> 0 < x ^+ n.
+Proof.
+by rewrite !lt0r expf_eq0 => /andP[/negPf-> /exprn_ge0->]; rewrite andbF.
+Qed.
+
+Definition exprn_gte0 := (exprn_ge0, exprn_gt0).
+
+Lemma exprn_ile1 n x : 0 <= x -> x <= 1 -> x ^+ n <= 1.
+Proof.
+move=> xge0 xle1; elim: n=> [|*]; rewrite ?expr0 // exprS.
+by rewrite mulr_ile1 ?exprn_ge0.
+Qed.
+
+Lemma exprn_ilt1 n x : 0 <= x -> x < 1 -> x ^+ n < 1 = (n != 0%N).
+Proof.
+move=> xge0 xlt1.
+case: n; [by rewrite eqxx ltrr | elim=> [|n ihn]; first by rewrite expr1].
+by rewrite exprS mulr_ilt1 // exprn_ge0.
+Qed.
+
+Definition exprn_ilte1 := (exprn_ile1, exprn_ilt1).
+
+Lemma exprn_ege1 n x : 1 <= x -> 1 <= x ^+ n.
+Proof.
+by move=> x_ge1; elim: n=> [|n ihn]; rewrite ?expr0 // exprS mulr_ege1.
+Qed.
+
+Lemma exprn_egt1 n x : 1 < x -> 1 < x ^+ n = (n != 0%N).
+Proof.
+move=> xgt1; case: n; first by rewrite eqxx ltrr.
+elim=> [|n ihn]; first by rewrite expr1.
+by rewrite exprS mulr_egt1 // exprn_ge0.
+Qed.
+
+Definition exprn_egte1 := (exprn_ege1, exprn_egt1).
+Definition exprn_cp1 := (exprn_ilte1, exprn_egte1).
+
+Lemma ler_iexpr x n : (0 < n)%N -> 0 <= x -> x <= 1 -> x ^+ n <= x.
+Proof. by case: n => n // *; rewrite exprS ler_pimulr // exprn_ile1. Qed.
+
+Lemma ltr_iexpr x n : 0 < x -> x < 1 -> (x ^+ n < x) = (1 < n)%N.
+Proof.
+case: n=> [|[|n]] //; first by rewrite expr0 => _ /ltr_gtF ->.
+by move=> x0 x1; rewrite exprS gtr_pmulr // ?exprn_ilt1 // ltrW.
+Qed.
+
+Definition lter_iexpr := (ler_iexpr, ltr_iexpr).
+
+Lemma ler_eexpr x n : (0 < n)%N -> 1 <= x -> x <= x ^+ n.
+Proof.
+case: n => // n _ x_ge1.
+by rewrite exprS ler_pemulr ?(ler_trans _ x_ge1) // exprn_ege1.
+Qed.
+
+Lemma ltr_eexpr x n : 1 < x -> (x < x ^+ n) = (1 < n)%N.
+Proof.
+move=> x_ge1; case: n=> [|[|n]] //; first by rewrite expr0 ltr_gtF.
+by rewrite exprS ltr_pmulr ?(ltr_trans _ x_ge1) ?exprn_egt1.
+Qed.
+
+Definition lter_eexpr := (ler_eexpr, ltr_eexpr).
+Definition lter_expr := (lter_iexpr, lter_eexpr).
+
+Lemma ler_wiexpn2l x :
+ 0 <= x -> x <= 1 -> {homo (GRing.exp x) : m n / (n <= m)%N >-> m <= n}.
+Proof.
+move=> xge0 xle1 m n /= hmn.
+by rewrite -(subnK hmn) exprD ler_pimull ?(exprn_ge0, exprn_ile1).
+Qed.
+
+Lemma ler_weexpn2l x :
+ 1 <= x -> {homo (GRing.exp x) : m n / (m <= n)%N >-> m <= n}.
+Proof.
+move=> xge1 m n /= hmn; rewrite -(subnK hmn) exprD.
+by rewrite ler_pemull ?(exprn_ge0, exprn_ege1) // (ler_trans _ xge1) ?ler01.
+Qed.
+
+Lemma ieexprn_weq1 x n : 0 <= x -> (x ^+ n == 1) = ((n == 0%N) || (x == 1)).
+Proof.
+move=> xle0; case: n => [|n]; first by rewrite expr0 eqxx.
+case: (@real_ltrgtP x 1); do ?by rewrite ?ger0_real.
++ by move=> x_lt1; rewrite ?ltr_eqF // exprn_ilt1.
++ by move=> x_lt1; rewrite ?gtr_eqF // exprn_egt1.
+by move->; rewrite expr1n eqxx.
+Qed.
+
+Lemma ieexprIn x : 0 < x -> x != 1 -> injective (GRing.exp x).
+Proof.
+move=> x_gt0 x_neq1 m n; without loss /subnK <-: m n / (n <= m)%N.
+ by move=> IH eq_xmn; case/orP: (leq_total m n) => /IH->.
+case: {m}(m - n)%N => // m /eqP/idPn[]; rewrite -[x ^+ n]mul1r exprD.
+by rewrite (inj_eq (mulIf _)) ?ieexprn_weq1 ?ltrW // expf_neq0 ?gtr_eqF.
+Qed.
+
+Lemma ler_iexpn2l x :
+ 0 < x -> x < 1 -> {mono (GRing.exp x) : m n / (n <= m)%N >-> m <= n}.
+Proof.
+move=> xgt0 xlt1; apply: (nhomo_leq_mono (nhomo_inj_ltn_lt _ _)); last first.
+ by apply: ler_wiexpn2l; rewrite ltrW.
+by apply: ieexprIn; rewrite ?ltr_eqF ?ltr_cpable.
+Qed.
+
+Lemma ltr_iexpn2l x :
+ 0 < x -> x < 1 -> {mono (GRing.exp x) : m n / (n < m)%N >-> m < n}.
+Proof. by move=> xgt0 xlt1; apply: (leq_lerW_nmono (ler_iexpn2l _ _)). Qed.
+
+Definition lter_iexpn2l := (ler_iexpn2l, ltr_iexpn2l).
+
+Lemma ler_eexpn2l x :
+ 1 < x -> {mono (GRing.exp x) : m n / (m <= n)%N >-> m <= n}.
+Proof.
+move=> xgt1; apply: (homo_leq_mono (homo_inj_ltn_lt _ _)); last first.
+ by apply: ler_weexpn2l; rewrite ltrW.
+by apply: ieexprIn; rewrite ?gtr_eqF ?gtr_cpable //; apply: ltr_trans xgt1.
+Qed.
+
+Lemma ltr_eexpn2l x :
+ 1 < x -> {mono (GRing.exp x) : m n / (m < n)%N >-> m < n}.
+Proof. by move=> xgt1; apply: (leq_lerW_mono (ler_eexpn2l _)). Qed.
+
+Definition lter_eexpn2l := (ler_eexpn2l, ltr_eexpn2l).
+
+Lemma ltr_expn2r n x y : 0 <= x -> x < y -> x ^+ n < y ^+ n = (n != 0%N).
+Proof.
+move=> xge0 xlty; case: n; first by rewrite ltrr.
+elim=> [|n IHn]; rewrite ?[_ ^+ _.+2]exprS //.
+rewrite (@ler_lt_trans _ (x * y ^+ n.+1)) ?ler_wpmul2l ?ltr_pmul2r ?IHn //.
+ by rewrite ltrW // ihn.
+by rewrite exprn_gt0 // (ler_lt_trans xge0).
+Qed.
+
+Lemma ler_expn2r n : {in nneg & , {homo ((@GRing.exp R)^~ n) : x y / x <= y}}.
+Proof.
+move=> x y /= x0 y0 xy; elim: n => [|n IHn]; rewrite !(expr0, exprS) //.
+by rewrite (@ler_trans _ (x * y ^+ n)) ?ler_wpmul2l ?ler_wpmul2r ?exprn_ge0.
+Qed.
+
+Definition lter_expn2r := (ler_expn2r, ltr_expn2r).
+
+Lemma ltr_wpexpn2r n :
+ (0 < n)%N -> {in nneg & , {homo ((@GRing.exp R)^~ n) : x y / x < y}}.
+Proof. by move=> ngt0 x y /= x0 y0 hxy; rewrite ltr_expn2r // -lt0n. Qed.
+
+Lemma ler_pexpn2r n :
+ (0 < n)%N -> {in nneg & , {mono ((@GRing.exp R)^~ n) : x y / x <= y}}.
+Proof.
+case: n => // n _ x y; rewrite !qualifE /= => x_ge0 y_ge0.
+have [-> | nzx] := eqVneq x 0; first by rewrite exprS mul0r exprn_ge0.
+rewrite -subr_ge0 subrXX pmulr_lge0 ?subr_ge0 //= big_ord_recr /=.
+rewrite subnn expr0 mul1r /= ltr_spaddr // ?exprn_gt0 ?lt0r ?nzx //.
+by rewrite sumr_ge0 // => i _; rewrite mulr_ge0 ?exprn_ge0.
+Qed.
+
+Lemma ltr_pexpn2r n :
+ (0 < n)%N -> {in nneg & , {mono ((@GRing.exp R)^~ n) : x y / x < y}}.
+Proof.
+by move=> n_gt0 x y x_ge0 y_ge0; rewrite !ltr_neqAle !eqr_le !ler_pexpn2r.
+Qed.
+
+Definition lter_pexpn2r := (ler_pexpn2r, ltr_pexpn2r).
+
+Lemma pexpIrn n : (0 < n)%N -> {in nneg &, injective ((@GRing.exp R)^~ n)}.
+Proof. by move=> n_gt0; apply: mono_inj_in (ler_pexpn2r _). Qed.
+
+(* expr and ler/ltr *)
+Lemma expr_le1 n x : (0 < n)%N -> 0 <= x -> (x ^+ n <= 1) = (x <= 1).
+Proof.
+by move=> ngt0 xge0; rewrite -{1}[1](expr1n _ n) ler_pexpn2r // [_ \in _]ler01.
+Qed.
+
+Lemma expr_lt1 n x : (0 < n)%N -> 0 <= x -> (x ^+ n < 1) = (x < 1).
+Proof.
+by move=> ngt0 xge0; rewrite -{1}[1](expr1n _ n) ltr_pexpn2r // [_ \in _]ler01.
+Qed.
+
+Definition expr_lte1 := (expr_le1, expr_lt1).
+
+Lemma expr_ge1 n x : (0 < n)%N -> 0 <= x -> (1 <= x ^+ n) = (1 <= x).
+Proof.
+by move=> ngt0 xge0; rewrite -{1}[1](expr1n _ n) ler_pexpn2r // [_ \in _]ler01.
+Qed.
+
+Lemma expr_gt1 n x : (0 < n)%N -> 0 <= x -> (1 < x ^+ n) = (1 < x).
+Proof.
+by move=> ngt0 xge0; rewrite -{1}[1](expr1n _ n) ltr_pexpn2r // [_ \in _]ler01.
+Qed.
+
+Definition expr_gte1 := (expr_ge1, expr_gt1).
+
+Lemma pexpr_eq1 x n : (0 < n)%N -> 0 <= x -> (x ^+ n == 1) = (x == 1).
+Proof. by move=> ngt0 xge0; rewrite !eqr_le expr_le1 // expr_ge1. Qed.
+
+Lemma pexprn_eq1 x n : 0 <= x -> (x ^+ n == 1) = (n == 0%N) || (x == 1).
+Proof. by case: n => [|n] xge0; rewrite ?eqxx // pexpr_eq1 ?gtn_eqF. Qed.
+
+Lemma eqr_expn2 n x y :
+ (0 < n)%N -> 0 <= x -> 0 <= y -> (x ^+ n == y ^+ n) = (x == y).
+Proof. by move=> ngt0 xge0 yge0; rewrite (inj_in_eq (pexpIrn _)). Qed.
+
+Lemma sqrp_eq1 x : 0 <= x -> (x ^+ 2 == 1) = (x == 1).
+Proof. by move/pexpr_eq1->. Qed.
+
+Lemma sqrn_eq1 x : x <= 0 -> (x ^+ 2 == 1) = (x == -1).
+Proof. by rewrite -sqrrN -oppr_ge0 -eqr_oppLR => /sqrp_eq1. Qed.
+
+Lemma ler_sqr : {in nneg &, {mono (fun x => x ^+ 2) : x y / x <= y}}.
+Proof. exact: ler_pexpn2r. Qed.
+
+Lemma ltr_sqr : {in nneg &, {mono (fun x => x ^+ 2) : x y / x < y}}.
+Proof. exact: ltr_pexpn2r. Qed.
+
+Lemma ler_pinv :
+ {in [pred x in GRing.unit | 0 < x] &, {mono (@GRing.inv R) : x y /~ x <= y}}.
+Proof.
+move=> x y /andP [ux hx] /andP [uy hy] /=.
+rewrite -(ler_pmul2l hx) -(ler_pmul2r hy).
+by rewrite !(divrr, mulrVK) ?unitf_gt0 // mul1r.
+Qed.
+
+Lemma ler_ninv :
+ {in [pred x in GRing.unit | x < 0] &, {mono (@GRing.inv R) : x y /~ x <= y}}.
+Proof.
+move=> x y /andP [ux hx] /andP [uy hy] /=.
+rewrite -(ler_nmul2l hx) -(ler_nmul2r hy).
+by rewrite !(divrr, mulrVK) ?unitf_lt0 // mul1r.
+Qed.
+
+Lemma ltr_pinv :
+ {in [pred x in GRing.unit | 0 < x] &, {mono (@GRing.inv R) : x y /~ x < y}}.
+Proof. exact: lerW_nmono_in ler_pinv. Qed.
+
+Lemma ltr_ninv :
+ {in [pred x in GRing.unit | x < 0] &, {mono (@GRing.inv R) : x y /~ x < y}}.
+Proof. exact: lerW_nmono_in ler_ninv. Qed.
+
+Lemma invr_gt1 x : x \is a GRing.unit -> 0 < x -> (1 < x^-1) = (x < 1).
+Proof.
+by move=> Ux xgt0; rewrite -{1}[1]invr1 ltr_pinv ?inE ?unitr1 ?ltr01 ?Ux.
+Qed.
+
+Lemma invr_ge1 x : x \is a GRing.unit -> 0 < x -> (1 <= x^-1) = (x <= 1).
+Proof.
+by move=> Ux xgt0; rewrite -{1}[1]invr1 ler_pinv ?inE ?unitr1 ?ltr01 // Ux.
+Qed.
+
+Definition invr_gte1 := (invr_ge1, invr_gt1).
+
+Lemma invr_le1 x (ux : x \is a GRing.unit) (hx : 0 < x) :
+ (x^-1 <= 1) = (1 <= x).
+Proof. by rewrite -invr_ge1 ?invr_gt0 ?unitrV // invrK. Qed.
+
+Lemma invr_lt1 x (ux : x \is a GRing.unit) (hx : 0 < x) : (x^-1 < 1) = (1 < x).
+Proof. by rewrite -invr_gt1 ?invr_gt0 ?unitrV // invrK. Qed.
+
+Definition invr_lte1 := (invr_le1, invr_lt1).
+Definition invr_cp1 := (invr_gte1, invr_lte1).
+
+(* norm *)
+
+Lemma real_ler_norm x : x \is real -> x <= `|x|.
+Proof.
+by case/real_ger0P=> hx //; rewrite (ler_trans (ltrW hx)) // oppr_ge0 ltrW.
+Qed.
+
+(* norm + add *)
+
+Lemma normr_real x : `|x| \is real. Proof. by rewrite ger0_real. Qed.
+Hint Resolve normr_real.
+
+Lemma ler_norm_sum I r (G : I -> R) (P : pred I):
+ `|\sum_(i <- r | P i) G i| <= \sum_(i <- r | P i) `|G i|.
+Proof.
+elim/big_rec2: _ => [|i y x _]; first by rewrite normr0.
+by rewrite -(ler_add2l `|G i|); apply: ler_trans; apply: ler_norm_add.
+Qed.
+
+Lemma ler_norm_sub x y : `|x - y| <= `|x| + `|y|.
+Proof. by rewrite (ler_trans (ler_norm_add _ _)) ?normrN. Qed.
+
+Lemma ler_dist_add z x y : `|x - y| <= `|x - z| + `|z - y|.
+Proof. by rewrite (ler_trans _ (ler_norm_add _ _)) // addrA addrNK. Qed.
+
+Lemma ler_sub_norm_add x y : `|x| - `|y| <= `|x + y|.
+Proof.
+rewrite -{1}[x](addrK y) lter_sub_addl.
+by rewrite (ler_trans (ler_norm_add _ _)) // addrC normrN.
+Qed.
+
+Lemma ler_sub_dist x y : `|x| - `|y| <= `|x - y|.
+Proof. by rewrite -[`|y|]normrN ler_sub_norm_add. Qed.
+
+Lemma ler_dist_dist x y : `|`|x| - `|y| | <= `|x - y|.
+Proof.
+have [||_|_] // := @real_lerP `|x| `|y|; last by rewrite ler_sub_dist.
+by rewrite distrC ler_sub_dist.
+Qed.
+
+Lemma ler_dist_norm_add x y : `| `|x| - `|y| | <= `| x + y |.
+Proof. by rewrite -[y]opprK normrN ler_dist_dist. Qed.
+
+Lemma real_ler_norml x y : x \is real -> (`|x| <= y) = (- y <= x <= y).
+Proof.
+move=> xR; wlog x_ge0 : x xR / 0 <= x => [hwlog|].
+ move: (xR) => /(@real_leVge 0) /orP [|/hwlog->|hx] //.
+ by rewrite -[x]opprK normrN ler_opp2 andbC ler_oppl hwlog ?realN ?oppr_ge0.
+rewrite ger0_norm //; have [le_xy|] := boolP (x <= y); last by rewrite andbF.
+by rewrite (ler_trans _ x_ge0) // oppr_le0 (ler_trans x_ge0).
+Qed.
+
+Lemma real_ler_normlP x y :
+ x \is real -> reflect ((-x <= y) * (x <= y)) (`|x| <= y).
+Proof.
+by move=> Rx; rewrite real_ler_norml // ler_oppl; apply: (iffP andP) => [] [].
+Qed.
+Implicit Arguments real_ler_normlP [x y].
+
+Lemma real_eqr_norml x y :
+ x \is real -> (`|x| == y) = ((x == y) || (x == -y)) && (0 <= y).
+Proof.
+move=> Rx.
+apply/idP/idP=> [|/andP[/pred2P[]-> /ger0_norm/eqP]]; rewrite ?normrE //.
+case: real_ler0P => // hx; rewrite 1?eqr_oppLR => /eqP exy.
+ by move: hx; rewrite exy ?oppr_le0 eqxx orbT //.
+by move: hx=> /ltrW; rewrite exy eqxx.
+Qed.
+
+Lemma real_eqr_norm2 x y :
+ x \is real -> y \is real -> (`|x| == `|y|) = (x == y) || (x == -y).
+Proof.
+move=> Rx Ry; rewrite real_eqr_norml // normrE andbT.
+by case: real_ler0P; rewrite // opprK orbC.
+Qed.
+
+Lemma real_ltr_norml x y : x \is real -> (`|x| < y) = (- y < x < y).
+Proof.
+move=> Rx; wlog x_ge0 : x Rx / 0 <= x => [hwlog|].
+ move: (Rx) => /(@real_leVge 0) /orP [|/hwlog->|hx] //.
+ by rewrite -[x]opprK normrN ltr_opp2 andbC ltr_oppl hwlog ?realN ?oppr_ge0.
+rewrite ger0_norm //; have [le_xy|] := boolP (x < y); last by rewrite andbF.
+by rewrite (ltr_le_trans _ x_ge0) // oppr_lt0 (ler_lt_trans x_ge0).
+Qed.
+
+Definition real_lter_norml := (real_ler_norml, real_ltr_norml).
+
+Lemma real_ltr_normlP x y :
+ x \is real -> reflect ((-x < y) * (x < y)) (`|x| < y).
+Proof.
+move=> Rx; rewrite real_ltr_norml // ltr_oppl.
+by apply: (iffP (@andP _ _)); case.
+Qed.
+Implicit Arguments real_ltr_normlP [x y].
+
+Lemma real_ler_normr x y : y \is real -> (x <= `|y|) = (x <= y) || (x <= - y).
+Proof.
+move=> Ry.
+have [xR|xNR] := boolP (x \is real); last by rewrite ?Nreal_leF ?realN.
+rewrite real_lerNgt ?real_ltr_norml // negb_and -?real_lerNgt ?realN //.
+by rewrite orbC ler_oppr.
+Qed.
+
+Lemma real_ltr_normr x y : y \is real -> (x < `|y|) = (x < y) || (x < - y).
+Proof.
+move=> Ry.
+have [xR|xNR] := boolP (x \is real); last by rewrite ?Nreal_ltF ?realN.
+rewrite real_ltrNge ?real_ler_norml // negb_and -?real_ltrNge ?realN //.
+by rewrite orbC ltr_oppr.
+Qed.
+
+Definition real_lter_normr := (real_ler_normr, real_ltr_normr).
+
+Lemma ler_nnorml x y : y < 0 -> `|x| <= y = false.
+Proof. by move=> y_lt0; rewrite ltr_geF // (ltr_le_trans y_lt0). Qed.
+
+Lemma ltr_nnorml x y : y <= 0 -> `|x| < y = false.
+Proof. by move=> y_le0; rewrite ler_gtF // (ler_trans y_le0). Qed.
+
+Definition lter_nnormr := (ler_nnorml, ltr_nnorml).
+
+Lemma real_ler_distl x y e :
+ x - y \is real -> (`|x - y| <= e) = (y - e <= x <= y + e).
+Proof. by move=> Rxy; rewrite real_lter_norml // !lter_sub_addl. Qed.
+
+Lemma real_ltr_distl x y e :
+ x - y \is real -> (`|x - y| < e) = (y - e < x < y + e).
+Proof. by move=> Rxy; rewrite real_lter_norml // !lter_sub_addl. Qed.
+
+Definition real_lter_distl := (real_ler_distl, real_ltr_distl).
+
+(* GG: pointless duplication }-( *)
+Lemma eqr_norm_id x : (`|x| == x) = (0 <= x). Proof. by rewrite ger0_def. Qed.
+Lemma eqr_normN x : (`|x| == - x) = (x <= 0). Proof. by rewrite ler0_def. Qed.
+Definition eqr_norm_idVN := =^~ (ger0_def, ler0_def).
+
+Lemma real_exprn_even_ge0 n x : x \is real -> ~~ odd n -> 0 <= x ^+ n.
+Proof.
+move=> xR even_n; have [/exprn_ge0 -> //|x_lt0] := real_ger0P xR.
+rewrite -[x]opprK -mulN1r exprMn -signr_odd (negPf even_n) expr0 mul1r.
+by rewrite exprn_ge0 ?oppr_ge0 ?ltrW.
+Qed.
+
+Lemma real_exprn_even_gt0 n x :
+ x \is real -> ~~ odd n -> (0 < x ^+ n) = (n == 0)%N || (x != 0).
+Proof.
+move=> xR n_even; rewrite lt0r real_exprn_even_ge0 ?expf_eq0 //.
+by rewrite andbT negb_and lt0n negbK.
+Qed.
+
+Lemma real_exprn_even_le0 n x :
+ x \is real -> ~~ odd n -> (x ^+ n <= 0) = (n != 0%N) && (x == 0).
+Proof.
+move=> xR n_even; rewrite !real_lerNgt ?rpred0 ?rpredX //.
+by rewrite real_exprn_even_gt0 // negb_or negbK.
+Qed.
+
+Lemma real_exprn_even_lt0 n x :
+ x \is real -> ~~ odd n -> (x ^+ n < 0) = false.
+Proof. by move=> xR n_even; rewrite ler_gtF // real_exprn_even_ge0. Qed.
+
+Lemma real_exprn_odd_ge0 n x :
+ x \is real -> odd n -> (0 <= x ^+ n) = (0 <= x).
+Proof.
+case/real_ger0P => [x_ge0|x_lt0] n_odd; first by rewrite exprn_ge0.
+apply: negbTE; rewrite ltr_geF //.
+case: n n_odd => // n /= n_even; rewrite exprS pmulr_llt0 //.
+by rewrite real_exprn_even_gt0 ?ler0_real ?ltrW // ltr_eqF ?orbT.
+Qed.
+
+Lemma real_exprn_odd_gt0 n x : x \is real -> odd n -> (0 < x ^+ n) = (0 < x).
+Proof.
+by move=> xR n_odd; rewrite !lt0r expf_eq0 real_exprn_odd_ge0; case: n n_odd.
+Qed.
+
+Lemma real_exprn_odd_le0 n x : x \is real -> odd n -> (x ^+ n <= 0) = (x <= 0).
+Proof.
+by move=> xR n_odd; rewrite !real_lerNgt ?rpred0 ?rpredX // real_exprn_odd_gt0.
+Qed.
+
+Lemma real_exprn_odd_lt0 n x : x \is real -> odd n -> (x ^+ n < 0) = (x < 0).
+Proof.
+by move=> xR n_odd; rewrite !real_ltrNge ?rpred0 ?rpredX // real_exprn_odd_ge0.
+Qed.
+
+(* GG: Could this be a better definition of "real" ? *)
+Lemma realEsqr x : (x \is real) = (0 <= x ^+ 2).
+Proof. by rewrite ger0_def normrX eqf_sqr -ger0_def -ler0_def. Qed.
+
+Lemma real_normK x : x \is real -> `|x| ^+ 2 = x ^+ 2.
+Proof. by move=> Rx; rewrite -normrX ger0_norm -?realEsqr. Qed.
+
+(* Binary sign ((-1) ^+ s). *)
+
+Lemma normr_sign s : `|(-1) ^+ s| = 1 :> R.
+Proof. by rewrite normrX normrN1 expr1n. Qed.
+
+Lemma normrMsign s x : `|(-1) ^+ s * x| = `|x|.
+Proof. by rewrite normrM normr_sign mul1r. Qed.
+
+Lemma signr_gt0 (b : bool) : (0 < (-1) ^+ b :> R) = ~~ b.
+Proof. by case: b; rewrite (ltr01, ltr0N1). Qed.
+
+Lemma signr_lt0 (b : bool) : ((-1) ^+ b < 0 :> R) = b.
+Proof. by case: b; rewrite // ?(ltrN10, ltr10). Qed.
+
+Lemma signr_ge0 (b : bool) : (0 <= (-1) ^+ b :> R) = ~~ b.
+Proof. by rewrite le0r signr_eq0 signr_gt0. Qed.
+
+Lemma signr_le0 (b : bool) : ((-1) ^+ b <= 0 :> R) = b.
+Proof. by rewrite ler_eqVlt signr_eq0 signr_lt0. Qed.
+
+(* This actually holds for char R != 2. *)
+Lemma signr_inj : injective (fun b : bool => (-1) ^+ b : R).
+Proof. exact: can_inj (fun x => 0 >= x) signr_le0. Qed.
+
+(* Ternary sign (sg). *)
+
+Lemma sgr_def x : sg x = (-1) ^+ (x < 0)%R *+ (x != 0).
+Proof. by rewrite /sg; do 2!case: ifP => //. Qed.
+
+Lemma neqr0_sign x : x != 0 -> (-1) ^+ (x < 0)%R = sgr x.
+Proof. by rewrite sgr_def => ->. Qed.
+
+Lemma gtr0_sg x : 0 < x -> sg x = 1.
+Proof. by move=> x_gt0; rewrite /sg gtr_eqF // ltr_gtF. Qed.
+
+Lemma ltr0_sg x : x < 0 -> sg x = -1.
+Proof. by move=> x_lt0; rewrite /sg x_lt0 ltr_eqF. Qed.
+
+Lemma sgr0 : sg 0 = 0 :> R. Proof. by rewrite /sgr eqxx. Qed.
+Lemma sgr1 : sg 1 = 1 :> R. Proof. by rewrite gtr0_sg // ltr01. Qed.
+Lemma sgrN1 : sg (-1) = -1 :> R. Proof. by rewrite ltr0_sg // ltrN10. Qed.
+Definition sgrE := (sgr0, sgr1, sgrN1).
+
+Lemma sqr_sg x : sg x ^+ 2 = (x != 0)%:R.
+Proof. by rewrite sgr_def exprMn_n sqrr_sign -mulnn mulnb andbb. Qed.
+
+Lemma mulr_sg_eq1 x y : (sg x * y == 1) = (x != 0) && (sg x == y).
+Proof.
+rewrite /sg eq_sym; case: ifP => _; first by rewrite mul0r oner_eq0.
+by case: ifP => _; rewrite ?mul1r // mulN1r eqr_oppLR.
+Qed.
+
+Lemma mulr_sg_eqN1 x y : (sg x * sg y == -1) = (x != 0) && (sg x == - sg y).
+Proof.
+move/sg: y => y; rewrite /sg eq_sym eqr_oppLR.
+case: ifP => _; first by rewrite mul0r oppr0 oner_eq0.
+by case: ifP => _; rewrite ?mul1r // mulN1r eqr_oppLR.
+Qed.
+
+Lemma sgr_eq0 x : (sg x == 0) = (x == 0).
+Proof. by rewrite -sqrf_eq0 sqr_sg pnatr_eq0; case: (x == 0). Qed.
+
+Lemma sgr_odd n x : x != 0 -> (sg x) ^+ n = (sg x) ^+ (odd n).
+Proof. by rewrite /sg; do 2!case: ifP => // _; rewrite ?expr1n ?signr_odd. Qed.
+
+Lemma sgrMn x n : sg (x *+ n) = (n != 0%N)%:R * sg x.
+Proof.
+case: n => [|n]; first by rewrite mulr0n sgr0 mul0r.
+by rewrite !sgr_def mulrn_eq0 mul1r pmulrn_llt0.
+Qed.
+
+Lemma sgr_nat n : sg n%:R = (n != 0%N)%:R :> R.
+Proof. by rewrite sgrMn sgr1 mulr1. Qed.
+
+Lemma sgr_id x : sg (sg x) = sg x.
+Proof. by rewrite !(fun_if sg) !sgrE. Qed.
+
+Lemma sgr_lt0 x : (sg x < 0) = (x < 0).
+Proof.
+rewrite /sg; case: eqP => [-> // | _].
+by case: ifP => _; rewrite ?ltrN10 // ltr_gtF.
+Qed.
+
+Lemma sgr_le0 x : (sgr x <= 0) = (x <= 0).
+Proof. by rewrite !ler_eqVlt sgr_eq0 sgr_lt0. Qed.
+
+(* sign and norm *)
+
+Lemma realEsign x : x \is real -> x = (-1) ^+ (x < 0)%R * `|x|.
+Proof. by case/real_ger0P; rewrite (mul1r, mulN1r) ?opprK. Qed.
+
+Lemma realNEsign x : x \is real -> - x = (-1) ^+ (0 < x)%R * `|x|.
+Proof. by move=> Rx; rewrite -normrN -oppr_lt0 -realEsign ?rpredN. Qed.
+
+Lemma real_normrEsign (x : R) (xR : x \is real) : `|x| = (-1) ^+ (x < 0)%R * x.
+Proof. by rewrite {3}[x]realEsign // signrMK. Qed.
+
+(* GG: pointless duplication... *)
+Lemma real_mulr_sign_norm x : x \is real -> (-1) ^+ (x < 0)%R * `|x| = x.
+Proof. by move/realEsign. Qed.
+
+Lemma real_mulr_Nsign_norm x : x \is real -> (-1) ^+ (0 < x)%R * `|x| = - x.
+Proof. by move/realNEsign. Qed.
+
+Lemma realEsg x : x \is real -> x = sgr x * `|x|.
+Proof.
+move=> xR; have [-> | ] := eqVneq x 0; first by rewrite normr0 mulr0.
+by move=> /neqr0_sign <-; rewrite -realEsign.
+Qed.
+
+Lemma normr_sg x : `|sg x| = (x != 0)%:R.
+Proof. by rewrite sgr_def -mulr_natr normrMsign normr_nat. Qed.
+
+Lemma sgr_norm x : sg `|x| = (x != 0)%:R.
+Proof. by rewrite /sg ler_gtF ?normr_ge0 // normr_eq0 mulrb if_neg. Qed.
+
+(* lerif *)
+
+Lemma lerif_refl x C : reflect (x <= x ?= iff C) C.
+Proof. by apply: (iffP idP) => [-> | <-] //; split; rewrite ?eqxx. Qed.
+
+Lemma lerif_trans x1 x2 x3 C12 C23 :
+ x1 <= x2 ?= iff C12 -> x2 <= x3 ?= iff C23 -> x1 <= x3 ?= iff C12 && C23.
+Proof.
+move=> ltx12 ltx23; apply/lerifP; rewrite -ltx12.
+case eqx12: (x1 == x2).
+ by rewrite (eqP eqx12) ltr_neqAle !ltx23 andbT; case C23.
+by rewrite (@ltr_le_trans _ x2) ?ltx23 // ltr_neqAle eqx12 ltx12.
+Qed.
+
+Lemma lerif_le x y : x <= y -> x <= y ?= iff (x >= y).
+Proof. by move=> lexy; split=> //; rewrite eqr_le lexy. Qed.
+
+Lemma lerif_eq x y : x <= y -> x <= y ?= iff (x == y).
+Proof. by []. Qed.
+
+Lemma ger_lerif x y C : x <= y ?= iff C -> (y <= x) = C.
+Proof. by case=> le_xy; rewrite eqr_le le_xy. Qed.
+
+Lemma ltr_lerif x y C : x <= y ?= iff C -> (x < y) = ~~ C.
+Proof. by move=> le_xy; rewrite ltr_neqAle !le_xy andbT. Qed.
+
+Lemma lerif_nat m n C : (m%:R <= n%:R ?= iff C :> R) = (m <= n ?= iff C)%N.
+Proof. by rewrite /lerif !ler_nat eqr_nat. Qed.
+
+Lemma mono_in_lerif (A : pred R) (f : R -> R) C :
+ {in A &, {mono f : x y / x <= y}} ->
+ {in A &, forall x y, (f x <= f y ?= iff C) = (x <= y ?= iff C)}.
+Proof.
+by move=> mf x y Ax Ay; rewrite /lerif mf ?(inj_in_eq (mono_inj_in mf)).
+Qed.
+
+Lemma mono_lerif (f : R -> R) C :
+ {mono f : x y / x <= y} ->
+ forall x y, (f x <= f y ?= iff C) = (x <= y ?= iff C).
+Proof. by move=> mf x y; rewrite /lerif mf (inj_eq (mono_inj _)). Qed.
+
+Lemma nmono_in_lerif (A : pred R) (f : R -> R) C :
+ {in A &, {mono f : x y /~ x <= y}} ->
+ {in A &, forall x y, (f x <= f y ?= iff C) = (y <= x ?= iff C)}.
+Proof.
+by move=> mf x y Ax Ay; rewrite /lerif eq_sym mf ?(inj_in_eq (nmono_inj_in mf)).
+Qed.
+
+Lemma nmono_lerif (f : R -> R) C :
+ {mono f : x y /~ x <= y} ->
+ forall x y, (f x <= f y ?= iff C) = (y <= x ?= iff C).
+Proof. by move=> mf x y; rewrite /lerif eq_sym mf ?(inj_eq (nmono_inj mf)). Qed.
+
+Lemma lerif_subLR x y z C : (x - y <= z ?= iff C) = (x <= z + y ?= iff C).
+Proof. by rewrite /lerif !eqr_le ler_subr_addr ler_subl_addr. Qed.
+
+Lemma lerif_subRL x y z C : (x <= y - z ?= iff C) = (x + z <= y ?= iff C).
+Proof. by rewrite -lerif_subLR opprK. Qed.
+
+Lemma lerif_add x1 y1 C1 x2 y2 C2 :
+ x1 <= y1 ?= iff C1 -> x2 <= y2 ?= iff C2 ->
+ x1 + x2 <= y1 + y2 ?= iff C1 && C2.
+Proof.
+rewrite -(mono_lerif _ (ler_add2r x2)) -(mono_lerif C2 (ler_add2l y1)).
+exact: lerif_trans.
+Qed.
+
+Lemma lerif_sum (I : finType) (P C : pred I) (E1 E2 : I -> R) :
+ (forall i, P i -> E1 i <= E2 i ?= iff C i) ->
+ \sum_(i | P i) E1 i <= \sum_(i | P i) E2 i ?= iff [forall (i | P i), C i].
+Proof.
+move=> leE12; rewrite -big_andE.
+elim/big_rec3: _ => [|i Ci m2 m1 /leE12]; first by rewrite /lerif lerr eqxx.
+exact: lerif_add.
+Qed.
+
+Lemma lerif_0_sum (I : finType) (P C : pred I) (E : I -> R) :
+ (forall i, P i -> 0 <= E i ?= iff C i) ->
+ 0 <= \sum_(i | P i) E i ?= iff [forall (i | P i), C i].
+Proof. by move/lerif_sum; rewrite big1_eq. Qed.
+
+Lemma real_lerif_norm x : x \is real -> x <= `|x| ?= iff (0 <= x).
+Proof.
+by move=> xR; rewrite ger0_def eq_sym; apply: lerif_eq; rewrite real_ler_norm.
+Qed.
+
+Lemma lerif_pmul x1 x2 y1 y2 C1 C2 :
+ 0 <= x1 -> 0 <= x2 -> x1 <= y1 ?= iff C1 -> x2 <= y2 ?= iff C2 ->
+ x1 * x2 <= y1 * y2 ?= iff (y1 * y2 == 0) || C1 && C2.
+Proof.
+move=> x1_ge0 x2_ge0 le_xy1 le_xy2; have [y_0 | ] := altP (_ =P 0).
+ apply/lerifP; rewrite y_0 /= mulf_eq0 !eqr_le x1_ge0 x2_ge0 !andbT.
+ move/eqP: y_0; rewrite mulf_eq0.
+ by case/pred2P=> <-; rewrite (le_xy1, le_xy2) ?orbT.
+rewrite /= mulf_eq0 => /norP[y1nz y2nz].
+have y1_gt0: 0 < y1 by rewrite ltr_def y1nz (ler_trans _ le_xy1).
+have [x2_0 | x2nz] := eqVneq x2 0.
+ apply/lerifP; rewrite -le_xy2 x2_0 eq_sym (negPf y2nz) andbF mulr0.
+ by rewrite mulr_gt0 // ltr_def y2nz -x2_0 le_xy2.
+have:= le_xy2; rewrite -(mono_lerif _ (ler_pmul2l y1_gt0)).
+by apply: lerif_trans; rewrite (mono_lerif _ (ler_pmul2r _)) // ltr_def x2nz.
+Qed.
+
+Lemma lerif_nmul x1 x2 y1 y2 C1 C2 :
+ y1 <= 0 -> y2 <= 0 -> x1 <= y1 ?= iff C1 -> x2 <= y2 ?= iff C2 ->
+ y1 * y2 <= x1 * x2 ?= iff (x1 * x2 == 0) || C1 && C2.
+Proof.
+rewrite -!oppr_ge0 -mulrNN -[x1 * x2]mulrNN => y1le0 y2le0 le_xy1 le_xy2.
+by apply: lerif_pmul => //; rewrite (nmono_lerif _ ler_opp2).
+Qed.
+
+Lemma lerif_pprod (I : finType) (P C : pred I) (E1 E2 : I -> R) :
+ (forall i, P i -> 0 <= E1 i) ->
+ (forall i, P i -> E1 i <= E2 i ?= iff C i) ->
+ let pi E := \prod_(i | P i) E i in
+ pi E1 <= pi E2 ?= iff (pi E2 == 0) || [forall (i | P i), C i].
+Proof.
+move=> E1_ge0 leE12 /=; rewrite -big_andE; elim/(big_load (fun x => 0 <= x)): _.
+elim/big_rec3: _ => [|i Ci m2 m1 Pi [m1ge0 le_m12]].
+ by split=> //; apply/lerifP; rewrite orbT.
+have Ei_ge0 := E1_ge0 i Pi; split; first by rewrite mulr_ge0.
+congr (lerif _ _ _): (lerif_pmul Ei_ge0 m1ge0 (leE12 i Pi) le_m12).
+by rewrite mulf_eq0 -!orbA; congr (_ || _); rewrite !orb_andr orbA orbb.
+Qed.
+
+(* Mean inequalities. *)
+
+Lemma real_lerif_mean_square_scaled x y :
+ x \is real -> y \is real -> x * y *+ 2 <= x ^+ 2 + y ^+ 2 ?= iff (x == y).
+Proof.
+move=> Rx Ry; rewrite -[_ *+ 2]add0r -lerif_subRL addrAC -sqrrB -subr_eq0.
+by rewrite -sqrf_eq0 eq_sym; apply: lerif_eq; rewrite -realEsqr rpredB.
+Qed.
+
+Lemma real_lerif_AGM2_scaled x y :
+ x \is real -> y \is real -> x * y *+ 4 <= (x + y) ^+ 2 ?= iff (x == y).
+Proof.
+move=> Rx Ry; rewrite sqrrD addrAC (mulrnDr _ 2) -lerif_subLR addrK.
+exact: real_lerif_mean_square_scaled.
+Qed.
+
+Lemma lerif_AGM_scaled (I : finType) (A : pred I) (E : I -> R) (n := #|A|) :
+ {in A, forall i, 0 <= E i *+ n} ->
+ \prod_(i in A) (E i *+ n) <= (\sum_(i in A) E i) ^+ n
+ ?= iff [forall i in A, forall j in A, E i == E j].
+Proof.
+elim: {A}_.+1 {-2}A (ltnSn #|A|) => // m IHm A leAm in E n * => Ege0.
+apply/lerifP; case: ifPn => [/forall_inP-Econstant | Enonconstant].
+ have [i /= Ai | A0] := pickP (mem A); last by rewrite [n]eq_card0 ?big_pred0.
+ have /eqfun_inP-E_i := Econstant i Ai; rewrite -(eq_bigr _ E_i) sumr_const.
+ by rewrite exprMn_n prodrMn -(eq_bigr _ E_i) prodr_const.
+set mu := \sum_(i in A) E i; pose En i := E i *+ n.
+pose cmp_mu s := [pred i | s * mu < s * En i].
+have{Enonconstant} has_cmp_mu e (s := (-1) ^+ e): {i | i \in A & cmp_mu s i}.
+ apply/sig2W/exists_inP; apply: contraR Enonconstant.
+ rewrite negb_exists_in => /forall_inP-mu_s_A.
+ have n_gt0 i: i \in A -> (0 < n)%N by rewrite [n](cardD1 i) => ->.
+ have{mu_s_A} mu_s_A i: i \in A -> s * En i <= s * mu.
+ move=> Ai; rewrite real_lerNgt ?mu_s_A ?rpredMsign ?ger0_real ?Ege0 //.
+ by rewrite -(pmulrn_lge0 _ (n_gt0 i Ai)) -sumrMnl sumr_ge0.
+ have [_ /esym/eqfun_inP] := lerif_sum (fun i Ai => lerif_eq (mu_s_A i Ai)).
+ rewrite sumr_const -/n -mulr_sumr sumrMnl -/mu mulrnAr eqxx => A_mu.
+ apply/forall_inP=> i Ai; apply/eqfun_inP=> j Aj.
+ by apply: (pmulrnI (n_gt0 i Ai)); apply: (can_inj (signrMK e)); rewrite !A_mu.
+have [[i Ai Ei_lt_mu] [j Aj Ej_gt_mu]] := (has_cmp_mu 1, has_cmp_mu 0)%N.
+rewrite {cmp_mu has_cmp_mu}/= !mul1r !mulN1r ltr_opp2 in Ei_lt_mu Ej_gt_mu.
+pose A' := [predD1 A & i]; pose n' := #|A'|.
+have [Dn n_gt0]: n = n'.+1 /\ (n > 0)%N by rewrite [n](cardD1 i) Ai.
+have i'j: j != i by apply: contraTneq Ej_gt_mu => ->; rewrite ltr_gtF.
+have{i'j} A'j: j \in A' by rewrite !inE Aj i'j.
+have mu_gt0: 0 < mu := ler_lt_trans (Ege0 i Ai) Ei_lt_mu.
+rewrite (bigD1 i) // big_andbC (bigD1 j) //= mulrA; set pi := \prod_(k | _) _.
+have [-> | nz_pi] := eqVneq pi 0; first by rewrite !mulr0 exprn_gt0.
+have{nz_pi} pi_gt0: 0 < pi.
+ by rewrite ltr_def nz_pi prodr_ge0 // => k /andP[/andP[_ /Ege0]].
+rewrite -/(En i) -/(En j); pose E' := [eta En with j |-> En i + En j - mu].
+have E'ge0 k: k \in A' -> E' k *+ n' >= 0.
+ case/andP=> /= _ Ak; apply: mulrn_wge0; case: ifP => _; last exact: Ege0.
+ by rewrite subr_ge0 ler_paddl ?Ege0 // ltrW.
+rewrite -/n Dn in leAm; have{leAm IHm E'ge0}: _ <= _ := IHm _ leAm _ E'ge0.
+have ->: \sum_(k in A') E' k = mu *+ n'.
+ apply: (addrI mu); rewrite -mulrS -Dn -sumrMnl (bigD1 i Ai) big_andbC /=.
+ rewrite !(bigD1 j A'j) /= addrCA eqxx !addrA subrK; congr (_ + _).
+ by apply: eq_bigr => k /andP[_ /negPf->].
+rewrite prodrMn exprMn_n -/n' ler_pmuln2r ?expn_gt0; last by case: (n').
+have ->: \prod_(k in A') E' k = E' j * pi.
+ by rewrite (bigD1 j) //=; congr *%R; apply: eq_bigr => k /andP[_ /negPf->].
+rewrite -(ler_pmul2l mu_gt0) -exprS -Dn mulrA; apply: ltr_le_trans.
+rewrite ltr_pmul2r //= eqxx -addrA mulrDr mulrC -ltr_subl_addl -mulrBl.
+by rewrite mulrC ltr_pmul2r ?subr_gt0.
+Qed.
+
+(* Polynomial bound. *)
+
+Implicit Type p : {poly R}.
+
+Lemma poly_disk_bound p b : {ub | forall x, `|x| <= b -> `|p.[x]| <= ub}.
+Proof.
+exists (\sum_(j < size p) `|p`_j| * b ^+ j) => x le_x_b.
+rewrite horner_coef (ler_trans (ler_norm_sum _ _ _)) ?ler_sum // => j _.
+rewrite normrM normrX ler_wpmul2l ?ler_expn2r ?unfold_in ?normr_ge0 //.
+exact: ler_trans (normr_ge0 x) le_x_b.
+Qed.
+
+End NumDomainOperationTheory.
+
+Hint Resolve ler_opp2 ltr_opp2 real0 real1 normr_real.
+Implicit Arguments ler_sqr [[R] x y].
+Implicit Arguments ltr_sqr [[R] x y].
+Implicit Arguments signr_inj [[R] x1 x2].
+Implicit Arguments real_ler_normlP [R x y].
+Implicit Arguments real_ltr_normlP [R x y].
+Implicit Arguments lerif_refl [R x C].
+Implicit Arguments mono_in_lerif [R A f C].
+Implicit Arguments nmono_in_lerif [R A f C].
+Implicit Arguments mono_lerif [R f C].
+Implicit Arguments nmono_lerif [R f C].
+
+Section NumDomainMonotonyTheoryForReals.
+
+Variables (R R' : numDomainType) (D : pred R) (f : R -> R').
+Implicit Types (m n p : nat) (x y z : R) (u v w : R').
+
+Lemma real_mono :
+ {homo f : x y / x < y} -> {in real &, {mono f : x y / x <= y}}.
+Proof.
+move=> mf x y xR yR /=; have [lt_xy | le_yx] := real_lerP xR yR.
+ by rewrite ltrW_homo.
+by rewrite ltr_geF ?mf.
+Qed.
+
+Lemma real_nmono :
+ {homo f : x y /~ x < y} -> {in real &, {mono f : x y /~ x <= y}}.
+Proof.
+move=> mf x y xR yR /=; have [lt_xy|le_yx] := real_ltrP xR yR.
+ by rewrite ltr_geF ?mf.
+by rewrite ltrW_nhomo.
+Qed.
+
+(* GG: Domain should precede condition. *)
+Lemma real_mono_in :
+ {in D &, {homo f : x y / x < y}} ->
+ {in [pred x in D | x \is real] &, {mono f : x y / x <= y}}.
+Proof.
+move=> Dmf x y /andP[hx xR] /andP[hy yR] /=.
+have [lt_xy|le_yx] := real_lerP xR yR; first by rewrite (ltrW_homo_in Dmf).
+by rewrite ltr_geF ?Dmf.
+Qed.
+
+Lemma real_nmono_in :
+ {in D &, {homo f : x y /~ x < y}} ->
+ {in [pred x in D | x \is real] &, {mono f : x y /~ x <= y}}.
+Proof.
+move=> Dmf x y /andP[hx xR] /andP[hy yR] /=.
+have [lt_xy|le_yx] := real_ltrP xR yR; last by rewrite (ltrW_nhomo_in Dmf).
+by rewrite ltr_geF ?Dmf.
+Qed.
+
+End NumDomainMonotonyTheoryForReals.
+
+Section FinGroup.
+
+Import GroupScope.
+
+Variables (R : numDomainType) (gT : finGroupType).
+Implicit Types G : {group gT}.
+
+Lemma natrG_gt0 G : #|G|%:R > 0 :> R.
+Proof. by rewrite ltr0n cardG_gt0. Qed.
+
+Lemma natrG_neq0 G : #|G|%:R != 0 :> R.
+Proof. by rewrite gtr_eqF // natrG_gt0. Qed.
+
+Lemma natr_indexg_gt0 G B : #|G : B|%:R > 0 :> R.
+Proof. by rewrite ltr0n indexg_gt0. Qed.
+
+Lemma natr_indexg_neq0 G B : #|G : B|%:R != 0 :> R.
+Proof. by rewrite gtr_eqF // natr_indexg_gt0. Qed.
+
+End FinGroup.
+
+Section NumFieldTheory.
+
+Variable F : numFieldType.
+Implicit Types x y z t : F.
+
+Lemma unitf_gt0 x : 0 < x -> x \is a GRing.unit.
+Proof. by move=> hx; rewrite unitfE eq_sym ltr_eqF. Qed.
+
+Lemma unitf_lt0 x : x < 0 -> x \is a GRing.unit.
+Proof. by move=> hx; rewrite unitfE ltr_eqF. Qed.
+
+Lemma lef_pinv : {in pos &, {mono (@GRing.inv F) : x y /~ x <= y}}.
+Proof. by move=> x y hx hy /=; rewrite ler_pinv ?inE ?unitf_gt0. Qed.
+
+Lemma lef_ninv : {in neg &, {mono (@GRing.inv F) : x y /~ x <= y}}.
+Proof. by move=> x y hx hy /=; rewrite ler_ninv ?inE ?unitf_lt0. Qed.
+
+Lemma ltf_pinv : {in pos &, {mono (@GRing.inv F) : x y /~ x < y}}.
+Proof. exact: lerW_nmono_in lef_pinv. Qed.
+
+Lemma ltf_ninv: {in neg &, {mono (@GRing.inv F) : x y /~ x < y}}.
+Proof. exact: lerW_nmono_in lef_ninv. Qed.
+
+Definition ltef_pinv := (lef_pinv, ltf_pinv).
+Definition ltef_ninv := (lef_ninv, ltf_ninv).
+
+Lemma invf_gt1 x : 0 < x -> (1 < x^-1) = (x < 1).
+Proof. by move=> x_gt0; rewrite -{1}[1]invr1 ltf_pinv ?posrE ?ltr01. Qed.
+
+Lemma invf_ge1 x : 0 < x -> (1 <= x^-1) = (x <= 1).
+Proof. by move=> x_lt0; rewrite -{1}[1]invr1 lef_pinv ?posrE ?ltr01. Qed.
+
+Definition invf_gte1 := (invf_ge1, invf_gt1).
+
+Lemma invf_le1 x : 0 < x -> (x^-1 <= 1) = (1 <= x).
+Proof. by move=> x_gt0; rewrite -invf_ge1 ?invr_gt0 // invrK. Qed.
+
+Lemma invf_lt1 x : 0 < x -> (x^-1 < 1) = (1 < x).
+Proof. by move=> x_lt0; rewrite -invf_gt1 ?invr_gt0 // invrK. Qed.
+
+Definition invf_lte1 := (invf_le1, invf_lt1).
+Definition invf_cp1 := (invf_gte1, invf_lte1).
+
+(* These lemma are all combinations of mono(LR|RL) with ler_[pn]mul2[rl]. *)
+Lemma ler_pdivl_mulr z x y : 0 < z -> (x <= y / z) = (x * z <= y).
+Proof. by move=> z_gt0; rewrite -(@ler_pmul2r _ z) ?mulfVK ?gtr_eqF. Qed.
+
+Lemma ltr_pdivl_mulr z x y : 0 < z -> (x < y / z) = (x * z < y).
+Proof. by move=> z_gt0; rewrite -(@ltr_pmul2r _ z) ?mulfVK ?gtr_eqF. Qed.
+
+Definition lter_pdivl_mulr := (ler_pdivl_mulr, ltr_pdivl_mulr).
+
+Lemma ler_pdivr_mulr z x y : 0 < z -> (y / z <= x) = (y <= x * z).
+Proof. by move=> z_gt0; rewrite -(@ler_pmul2r _ z) ?mulfVK ?gtr_eqF. Qed.
+
+Lemma ltr_pdivr_mulr z x y : 0 < z -> (y / z < x) = (y < x * z).
+Proof. by move=> z_gt0; rewrite -(@ltr_pmul2r _ z) ?mulfVK ?gtr_eqF. Qed.
+
+Definition lter_pdivr_mulr := (ler_pdivr_mulr, ltr_pdivr_mulr).
+
+Lemma ler_pdivl_mull z x y : 0 < z -> (x <= z^-1 * y) = (z * x <= y).
+Proof. by move=> z_gt0; rewrite mulrC ler_pdivl_mulr ?[z * _]mulrC. Qed.
+
+Lemma ltr_pdivl_mull z x y : 0 < z -> (x < z^-1 * y) = (z * x < y).
+Proof. by move=> z_gt0; rewrite mulrC ltr_pdivl_mulr ?[z * _]mulrC. Qed.
+
+Definition lter_pdivl_mull := (ler_pdivl_mull, ltr_pdivl_mull).
+
+Lemma ler_pdivr_mull z x y : 0 < z -> (z^-1 * y <= x) = (y <= z * x).
+Proof. by move=> z_gt0; rewrite mulrC ler_pdivr_mulr ?[z * _]mulrC. Qed.
+
+Lemma ltr_pdivr_mull z x y : 0 < z -> (z^-1 * y < x) = (y < z * x).
+Proof. by move=> z_gt0; rewrite mulrC ltr_pdivr_mulr ?[z * _]mulrC. Qed.
+
+Definition lter_pdivr_mull := (ler_pdivr_mull, ltr_pdivr_mull).
+
+Lemma ler_ndivl_mulr z x y : z < 0 -> (x <= y / z) = (y <= x * z).
+Proof. by move=> z_lt0; rewrite -(@ler_nmul2r _ z) ?mulfVK ?ltr_eqF. Qed.
+
+Lemma ltr_ndivl_mulr z x y : z < 0 -> (x < y / z) = (y < x * z).
+Proof. by move=> z_lt0; rewrite -(@ltr_nmul2r _ z) ?mulfVK ?ltr_eqF. Qed.
+
+Definition lter_ndivl_mulr := (ler_ndivl_mulr, ltr_ndivl_mulr).
+
+Lemma ler_ndivr_mulr z x y : z < 0 -> (y / z <= x) = (x * z <= y).
+Proof. by move=> z_lt0; rewrite -(@ler_nmul2r _ z) ?mulfVK ?ltr_eqF. Qed.
+
+Lemma ltr_ndivr_mulr z x y : z < 0 -> (y / z < x) = (x * z < y).
+Proof. by move=> z_lt0; rewrite -(@ltr_nmul2r _ z) ?mulfVK ?ltr_eqF. Qed.
+
+Definition lter_ndivr_mulr := (ler_ndivr_mulr, ltr_ndivr_mulr).
+
+Lemma ler_ndivl_mull z x y : z < 0 -> (x <= z^-1 * y) = (y <= z * x).
+Proof. by move=> z_lt0; rewrite mulrC ler_ndivl_mulr ?[z * _]mulrC. Qed.
+
+Lemma ltr_ndivl_mull z x y : z < 0 -> (x < z^-1 * y) = (y < z * x).
+Proof. by move=> z_lt0; rewrite mulrC ltr_ndivl_mulr ?[z * _]mulrC. Qed.
+
+Definition lter_ndivl_mull := (ler_ndivl_mull, ltr_ndivl_mull).
+
+Lemma ler_ndivr_mull z x y : z < 0 -> (z^-1 * y <= x) = (z * x <= y).
+Proof. by move=> z_lt0; rewrite mulrC ler_ndivr_mulr ?[z * _]mulrC. Qed.
+
+Lemma ltr_ndivr_mull z x y : z < 0 -> (z^-1 * y < x) = (z * x < y).
+Proof. by move=> z_lt0; rewrite mulrC ltr_ndivr_mulr ?[z * _]mulrC. Qed.
+
+Definition lter_ndivr_mull := (ler_ndivr_mull, ltr_ndivr_mull).
+
+Lemma natf_div m d : (d %| m)%N -> (m %/ d)%:R = m%:R / d%:R :> F.
+Proof. by apply: char0_natf_div; apply: (@char_num F). Qed.
+
+Lemma normfV : {morph (@norm F) : x / x ^-1}.
+Proof.
+move=> x /=; have [/normrV //|Nux] := boolP (x \is a GRing.unit).
+by rewrite !invr_out // unitfE normr_eq0 -unitfE.
+Qed.
+
+Lemma normf_div : {morph (@norm F) : x y / x / y}.
+Proof. by move=> x y /=; rewrite normrM normfV. Qed.
+
+Lemma invr_sg x : (sg x)^-1 = sgr x.
+Proof. by rewrite !(fun_if GRing.inv) !(invr0, invrN, invr1). Qed.
+
+Lemma sgrV x : sgr x^-1 = sgr x.
+Proof. by rewrite /sgr invr_eq0 invr_lt0. Qed.
+
+(* Interval midpoint. *)
+
+Local Notation mid x y := ((x + y) / 2%:R).
+
+Lemma midf_le x y : x <= y -> (x <= mid x y) * (mid x y <= y).
+Proof.
+move=> lexy; rewrite ler_pdivl_mulr ?ler_pdivr_mulr ?ltr0Sn //.
+by rewrite !mulrDr !mulr1 ler_add2r ler_add2l.
+Qed.
+
+Lemma midf_lt x y : x < y -> (x < mid x y) * (mid x y < y).
+Proof.
+move=> ltxy; rewrite ltr_pdivl_mulr ?ltr_pdivr_mulr ?ltr0Sn //.
+by rewrite !mulrDr !mulr1 ltr_add2r ltr_add2l.
+Qed.
+
+Definition midf_lte := (midf_le, midf_lt).
+
+(* The AGM, unscaled but without the nth root. *)
+
+Lemma real_lerif_mean_square x y :
+ x \is real -> y \is real -> x * y <= mid (x ^+ 2) (y ^+ 2) ?= iff (x == y).
+Proof.
+move=> Rx Ry; rewrite -(mono_lerif (ler_pmul2r (ltr_nat F 0 2))).
+by rewrite divfK ?pnatr_eq0 // mulr_natr; apply: real_lerif_mean_square_scaled.
+Qed.
+
+Lemma real_lerif_AGM2 x y :
+ x \is real -> y \is real -> x * y <= mid x y ^+ 2 ?= iff (x == y).
+Proof.
+move=> Rx Ry; rewrite -(mono_lerif (ler_pmul2r (ltr_nat F 0 4))).
+rewrite mulr_natr (natrX F 2 2) -exprMn divfK ?pnatr_eq0 //.
+exact: real_lerif_AGM2_scaled.
+Qed.
+
+Lemma lerif_AGM (I : finType) (A : pred I) (E : I -> F) :
+ let n := #|A| in let mu := (\sum_(i in A) E i) / n%:R in
+ {in A, forall i, 0 <= E i} ->
+ \prod_(i in A) E i <= mu ^+ n
+ ?= iff [forall i in A, forall j in A, E i == E j].
+Proof.
+move=> n mu Ege0; have [n0 | n_gt0] := posnP n.
+ by rewrite n0 -big_andE !(big_pred0 _ _ _ _ (card0_eq n0)); apply/lerifP.
+pose E' i := E i / n%:R.
+have defE' i: E' i *+ n = E i by rewrite -mulr_natr divfK ?pnatr_eq0 -?lt0n.
+have /lerif_AGM_scaled (i): i \in A -> 0 <= E' i *+ n by rewrite defE' => /Ege0.
+rewrite -/n -mulr_suml (eq_bigr _ (in1W defE')); congr (_ <= _ ?= iff _).
+by do 2![apply: eq_forallb_in => ? _]; rewrite -(eqr_pmuln2r n_gt0) !defE'.
+Qed.
+
+Implicit Type p : {poly F}.
+Lemma Cauchy_root_bound p : p != 0 -> {b | forall x, root p x -> `|x| <= b}.
+Proof.
+move=> nz_p; set a := lead_coef p; set n := (size p).-1.
+have [q Dp]: {q | forall x, x != 0 -> p.[x] = (a - q.[x^-1] / x) * x ^+ n}.
+ exists (- \poly_(i < n) p`_(n - i.+1)) => x nz_x.
+ rewrite hornerN mulNr opprK horner_poly mulrDl !mulr_suml addrC.
+ rewrite horner_coef polySpred // big_ord_recr (reindex_inj rev_ord_inj) /=.
+ rewrite -/n -lead_coefE; congr (_ + _); apply: eq_bigr=> i _.
+ by rewrite exprB ?unitfE // -exprVn mulrA mulrAC exprSr mulrA.
+have [b ub_q] := poly_disk_bound q 1; exists (b / `|a| + 1) => x px0.
+have b_ge0: 0 <= b by rewrite (ler_trans (normr_ge0 q.[1])) ?ub_q ?normr1.
+have{b_ge0} ba_ge0: 0 <= b / `|a| by rewrite divr_ge0 ?normr_ge0.
+rewrite real_lerNgt ?rpredD ?rpred1 ?ger0_real ?normr_ge0 //.
+apply: contraL px0 => lb_x; rewrite rootE.
+have x_ge1: 1 <= `|x| by rewrite (ler_trans _ (ltrW lb_x)) // ler_paddl.
+have nz_x: x != 0 by rewrite -normr_gt0 (ltr_le_trans ltr01).
+rewrite {}Dp // mulf_neq0 ?expf_neq0 // subr_eq0 eq_sym.
+have: (b / `|a|) < `|x| by rewrite (ltr_trans _ lb_x) // ltr_spaddr ?ltr01.
+apply: contraTneq => /(canRL (divfK nz_x))Dax.
+rewrite ltr_pdivr_mulr ?normr_gt0 ?lead_coef_eq0 // mulrC -normrM -{}Dax.
+by rewrite ler_gtF // ub_q // normfV invf_le1 ?normr_gt0.
+Qed.
+
+Import GroupScope.
+
+Lemma natf_indexg (gT : finGroupType) (G H : {group gT}) :
+ H \subset G -> #|G : H|%:R = (#|G|%:R / #|H|%:R)%R :> F.
+Proof. by move=> sHG; rewrite -divgS // natf_div ?cardSg. Qed.
+
+End NumFieldTheory.
+
+Section RealDomainTheory.
+
+Hint Resolve lerr.
+
+Variable R : realDomainType.
+Implicit Types x y z t : R.
+
+Lemma num_real x : x \is real. Proof. exact: num_real. Qed.
+Hint Resolve num_real.
+
+Lemma ler_total : total (@le R). Proof. by move=> x y; apply: real_leVge. Qed.
+
+Lemma ltr_total x y : x != y -> (x < y) || (y < x).
+Proof. by rewrite !ltr_def [_ == y]eq_sym => ->; apply: ler_total. Qed.
+
+Lemma wlog_ler P :
+ (forall a b, P b a -> P a b) -> (forall a b, a <= b -> P a b) ->
+ forall a b : R, P a b.
+Proof. by move=> sP hP a b; apply: real_wlog_ler. Qed.
+
+Lemma wlog_ltr P :
+ (forall a, P a a) ->
+ (forall a b, (P b a -> P a b)) -> (forall a b, a < b -> P a b) ->
+ forall a b : R, P a b.
+Proof. by move=> rP sP hP a b; apply: real_wlog_ltr. Qed.
+
+Lemma ltrNge x y : (x < y) = ~~ (y <= x). Proof. exact: real_ltrNge. Qed.
+
+Lemma lerNgt x y : (x <= y) = ~~ (y < x). Proof. exact: real_lerNgt. Qed.
+
+Lemma lerP x y : ler_xor_gt x y `|x - y| `|y - x| (x <= y) (y < x).
+Proof. exact: real_lerP. Qed.
+
+Lemma ltrP x y : ltr_xor_ge x y `|x - y| `|y - x| (y <= x) (x < y).
+Proof. exact: real_ltrP. Qed.
+
+Lemma ltrgtP x y :
+ comparer x y `|x - y| `|y - x| (y == x) (x == y)
+ (x <= y) (y <= x) (x < y) (x > y) .
+Proof. exact: real_ltrgtP. Qed.
+
+Lemma ger0P x : ger0_xor_lt0 x `|x| (x < 0) (0 <= x).
+Proof. exact: real_ger0P. Qed.
+
+Lemma ler0P x : ler0_xor_gt0 x `|x| (0 < x) (x <= 0).
+Proof. exact: real_ler0P. Qed.
+
+Lemma ltrgt0P x :
+ comparer0 x `|x| (0 == x) (x == 0) (x <= 0) (0 <= x) (x < 0) (x > 0).
+Proof. exact: real_ltrgt0P. Qed.
+
+Lemma neqr_lt x y : (x != y) = (x < y) || (y < x).
+Proof. exact: real_neqr_lt. Qed.
+
+Lemma eqr_leLR x y z t :
+ (x <= y -> z <= t) -> (y < x -> t < z) -> (x <= y) = (z <= t).
+Proof. by move=> *; apply/idP/idP; rewrite // !lerNgt; apply: contra. Qed.
+
+Lemma eqr_leRL x y z t :
+ (x <= y -> z <= t) -> (y < x -> t < z) -> (z <= t) = (x <= y).
+Proof. by move=> *; symmetry; apply: eqr_leLR. Qed.
+
+Lemma eqr_ltLR x y z t :
+ (x < y -> z < t) -> (y <= x -> t <= z) -> (x < y) = (z < t).
+Proof. by move=> *; rewrite !ltrNge; congr negb; apply: eqr_leLR. Qed.
+
+Lemma eqr_ltRL x y z t :
+ (x < y -> z < t) -> (y <= x -> t <= z) -> (z < t) = (x < y).
+Proof. by move=> *; symmetry; apply: eqr_ltLR. Qed.
+
+(* sign *)
+
+Lemma mulr_lt0 x y :
+ (x * y < 0) = [&& x != 0, y != 0 & (x < 0) (+) (y < 0)].
+Proof.
+have [x_gt0|x_lt0|->] /= := ltrgt0P x; last by rewrite mul0r.
+ by rewrite pmulr_rlt0 //; case: ltrgt0P.
+by rewrite nmulr_rlt0 //; case: ltrgt0P.
+Qed.
+
+Lemma neq0_mulr_lt0 x y :
+ x != 0 -> y != 0 -> (x * y < 0) = (x < 0) (+) (y < 0).
+Proof. by move=> x_neq0 y_neq0; rewrite mulr_lt0 x_neq0 y_neq0. Qed.
+
+Lemma mulr_sign_lt0 (b : bool) x :
+ ((-1) ^+ b * x < 0) = (x != 0) && (b (+) (x < 0)%R).
+Proof. by rewrite mulr_lt0 signr_lt0 signr_eq0. Qed.
+
+(* sign & norm*)
+
+Lemma mulr_sign_norm x : (-1) ^+ (x < 0)%R * `|x| = x.
+Proof. by rewrite real_mulr_sign_norm. Qed.
+
+Lemma mulr_Nsign_norm x : (-1) ^+ (0 < x)%R * `|x| = - x.
+Proof. by rewrite real_mulr_Nsign_norm. Qed.
+
+Lemma numEsign x : x = (-1) ^+ (x < 0)%R * `|x|.
+Proof. by rewrite -realEsign. Qed.
+
+Lemma numNEsign x : -x = (-1) ^+ (0 < x)%R * `|x|.
+Proof. by rewrite -realNEsign. Qed.
+
+Lemma normrEsign x : `|x| = (-1) ^+ (x < 0)%R * x.
+Proof. by rewrite -real_normrEsign. Qed.
+
+End RealDomainTheory.
+
+Hint Resolve num_real.
+
+Section RealDomainMonotony.
+
+Variables (R : realDomainType) (R' : numDomainType) (D : pred R) (f : R -> R').
+Implicit Types (m n p : nat) (x y z : R) (u v w : R').
+
+Hint Resolve (@num_real R).
+
+Lemma homo_mono : {homo f : x y / x < y} -> {mono f : x y / x <= y}.
+Proof. by move=> mf x y; apply: real_mono. Qed.
+
+Lemma nhomo_mono : {homo f : x y /~ x < y} -> {mono f : x y /~ x <= y}.
+Proof. by move=> mf x y; apply: real_nmono. Qed.
+
+Lemma homo_mono_in :
+ {in D &, {homo f : x y / x < y}} -> {in D &, {mono f : x y / x <= y}}.
+Proof.
+by move=> mf x y Dx Dy; apply: (real_mono_in mf); rewrite ?inE ?Dx ?Dy /=.
+Qed.
+
+Lemma nhomo_mono_in :
+ {in D &, {homo f : x y /~ x < y}} -> {in D &, {mono f : x y /~ x <= y}}.
+Proof.
+by move=> mf x y Dx Dy; apply: (real_nmono_in mf); rewrite ?inE ?Dx ?Dy /=.
+Qed.
+
+End RealDomainMonotony.
+
+Section RealDomainOperations.
+
+(* sgr section *)
+
+Variable R : realDomainType.
+Implicit Types x y z t : R.
+Hint Resolve (@num_real R).
+
+Lemma sgr_cp0 x :
+ ((sg x == 1) = (0 < x)) *
+ ((sg x == -1) = (x < 0)) *
+ ((sg x == 0) = (x == 0)).
+Proof.
+rewrite -[1]/((-1) ^+ false) -signrN lt0r lerNgt sgr_def.
+case: (x =P 0) => [-> | _]; first by rewrite !(eq_sym 0) !signr_eq0 ltrr eqxx.
+by rewrite !(inj_eq signr_inj) eqb_id eqbF_neg signr_eq0 //.
+Qed.
+
+CoInductive sgr_val x : R -> bool -> bool -> bool -> bool -> bool -> bool
+ -> bool -> bool -> bool -> bool -> bool -> bool -> R -> Set :=
+ | SgrNull of x = 0 : sgr_val x 0 true true true true false false
+ true false false true false false 0
+ | SgrPos of x > 0 : sgr_val x x false false true false false true
+ false false true false false true 1
+ | SgrNeg of x < 0 : sgr_val x (- x) false true false false true false
+ false true false false true false (-1).
+
+Lemma sgrP x :
+ sgr_val x `|x| (0 == x) (x <= 0) (0 <= x) (x == 0) (x < 0) (0 < x)
+ (0 == sg x) (-1 == sg x) (1 == sg x)
+ (sg x == 0) (sg x == -1) (sg x == 1) (sg x).
+Proof.
+by rewrite ![_ == sg _]eq_sym !sgr_cp0 /sg; case: ltrgt0P; constructor.
+Qed.
+
+Lemma normrEsg x : `|x| = sg x * x.
+Proof. by case: sgrP; rewrite ?(mul0r, mul1r, mulN1r). Qed.
+
+Lemma numEsg x : x = sg x * `|x|.
+Proof. by case: sgrP; rewrite !(mul1r, mul0r, mulrNN). Qed.
+
+(* GG: duplicate! *)
+Lemma mulr_sg_norm x : sg x * `|x| = x. Proof. by rewrite -numEsg. Qed.
+
+Lemma sgrM x y : sg (x * y) = sg x * sg y.
+Proof.
+rewrite !sgr_def mulr_lt0 andbA mulrnAr mulrnAl -mulrnA mulnb -negb_or mulf_eq0.
+by case: (~~ _) => //; rewrite signr_addb.
+Qed.
+
+Lemma sgrN x : sg (- x) = - sg x.
+Proof. by rewrite -mulrN1 sgrM sgrN1 mulrN1. Qed.
+
+Lemma sgrX n x : sg (x ^+ n) = (sg x) ^+ n.
+Proof. by elim: n => [|n IHn]; rewrite ?sgr1 // !exprS sgrM IHn. Qed.
+
+Lemma sgr_smul x y : sg (sg x * y) = sg x * sg y.
+Proof. by rewrite sgrM sgr_id. Qed.
+
+Lemma sgr_gt0 x : (sg x > 0) = (x > 0).
+Proof. by rewrite -sgr_cp0 sgr_id sgr_cp0. Qed.
+
+Lemma sgr_ge0 x : (sgr x >= 0) = (x >= 0).
+Proof. by rewrite !lerNgt sgr_lt0. Qed.
+
+(* norm section *)
+
+Lemma ler_norm x : (x <= `|x|).
+Proof. exact: real_ler_norm. Qed.
+
+Lemma ler_norml x y : (`|x| <= y) = (- y <= x <= y).
+Proof. exact: real_ler_norml. Qed.
+
+Lemma ler_normlP x y : reflect ((- x <= y) * (x <= y)) (`|x| <= y).
+Proof. exact: real_ler_normlP. Qed.
+Implicit Arguments ler_normlP [x y].
+
+Lemma eqr_norml x y : (`|x| == y) = ((x == y) || (x == -y)) && (0 <= y).
+Proof. exact: real_eqr_norml. Qed.
+
+Lemma eqr_norm2 x y : (`|x| == `|y|) = (x == y) || (x == -y).
+Proof. exact: real_eqr_norm2. Qed.
+
+Lemma ltr_norml x y : (`|x| < y) = (- y < x < y).
+Proof. exact: real_ltr_norml. Qed.
+
+Definition lter_norml := (ler_norml, ltr_norml).
+
+Lemma ltr_normlP x y : reflect ((-x < y) * (x < y)) (`|x| < y).
+Proof. exact: real_ltr_normlP. Qed.
+Implicit Arguments ltr_normlP [x y].
+
+Lemma ler_normr x y : (x <= `|y|) = (x <= y) || (x <= - y).
+Proof. by rewrite lerNgt ltr_norml negb_and -!lerNgt orbC ler_oppr. Qed.
+
+Lemma ltr_normr x y : (x < `|y|) = (x < y) || (x < - y).
+Proof. by rewrite ltrNge ler_norml negb_and -!ltrNge orbC ltr_oppr. Qed.
+
+Definition lter_normr := (ler_normr, ltr_normr).
+
+Lemma ler_distl x y e : (`|x - y| <= e) = (y - e <= x <= y + e).
+Proof. by rewrite lter_norml !lter_sub_addl. Qed.
+
+Lemma ltr_distl x y e : (`|x - y| < e) = (y - e < x < y + e).
+Proof. by rewrite lter_norml !lter_sub_addl. Qed.
+
+Definition lter_distl := (ler_distl, ltr_distl).
+
+Lemma exprn_even_ge0 n x : ~~ odd n -> 0 <= x ^+ n.
+Proof. by move=> even_n; rewrite real_exprn_even_ge0 ?num_real. Qed.
+
+Lemma exprn_even_gt0 n x : ~~ odd n -> (0 < x ^+ n) = (n == 0)%N || (x != 0).
+Proof. by move=> even_n; rewrite real_exprn_even_gt0 ?num_real. Qed.
+
+Lemma exprn_even_le0 n x : ~~ odd n -> (x ^+ n <= 0) = (n != 0%N) && (x == 0).
+Proof. by move=> even_n; rewrite real_exprn_even_le0 ?num_real. Qed.
+
+Lemma exprn_even_lt0 n x : ~~ odd n -> (x ^+ n < 0) = false.
+Proof. by move=> even_n; rewrite real_exprn_even_lt0 ?num_real. Qed.
+
+Lemma exprn_odd_ge0 n x : odd n -> (0 <= x ^+ n) = (0 <= x).
+Proof. by move=> even_n; rewrite real_exprn_odd_ge0 ?num_real. Qed.
+
+Lemma exprn_odd_gt0 n x : odd n -> (0 < x ^+ n) = (0 < x).
+Proof. by move=> even_n; rewrite real_exprn_odd_gt0 ?num_real. Qed.
+
+Lemma exprn_odd_le0 n x : odd n -> (x ^+ n <= 0) = (x <= 0).
+Proof. by move=> even_n; rewrite real_exprn_odd_le0 ?num_real. Qed.
+
+Lemma exprn_odd_lt0 n x : odd n -> (x ^+ n < 0) = (x < 0).
+Proof. by move=> even_n; rewrite real_exprn_odd_lt0 ?num_real. Qed.
+
+(* Special lemmas for squares. *)
+
+Lemma sqr_ge0 x : 0 <= x ^+ 2. Proof. by rewrite exprn_even_ge0. Qed.
+
+Lemma sqr_norm_eq1 x : (x ^+ 2 == 1) = (`|x| == 1).
+Proof. by rewrite sqrf_eq1 eqr_norml ler01 andbT. Qed.
+
+Lemma lerif_mean_square_scaled x y :
+ x * y *+ 2 <= x ^+ 2 + y ^+ 2 ?= iff (x == y).
+Proof. exact: real_lerif_mean_square_scaled. Qed.
+
+Lemma lerif_AGM2_scaled x y : x * y *+ 4 <= (x + y) ^+ 2 ?= iff (x == y).
+Proof. exact: real_lerif_AGM2_scaled. Qed.
+
+Section MinMax.
+
+(* GG: Many of the first lemmas hold unconditionally, and others hold for *)
+(* the real subset of a general domain. *)
+Lemma minrC : @commutative R R min.
+Proof. by move=> x y; rewrite /min; case: ltrgtP. Qed.
+
+Lemma minrr : @idempotent R min.
+Proof. by move=> x; rewrite /min if_same. Qed.
+
+Lemma minr_l x y : x <= y -> min x y = x.
+Proof. by rewrite /minr => ->. Qed.
+
+Lemma minr_r x y : y <= x -> min x y = y.
+Proof. by move/minr_l; rewrite minrC. Qed.
+
+Lemma maxrC : @commutative R R max.
+Proof. by move=> x y; rewrite /maxr; case: ltrgtP. Qed.
+
+Lemma maxrr : @idempotent R max.
+Proof. by move=> x; rewrite /max if_same. Qed.
+
+Lemma maxr_l x y : y <= x -> max x y = x.
+Proof. by move=> hxy; rewrite /max hxy. Qed.
+
+Lemma maxr_r x y : x <= y -> max x y = y.
+Proof. by move=> hxy; rewrite maxrC maxr_l. Qed.
+
+Lemma addr_min_max x y : min x y + max x y = x + y.
+Proof.
+case: (lerP x y)=> hxy; first by rewrite maxr_r ?minr_l.
+by rewrite maxr_l ?minr_r ?ltrW // addrC.
+Qed.
+
+Lemma addr_max_min x y : max x y + min x y = x + y.
+Proof. by rewrite addrC addr_min_max. Qed.
+
+Lemma minr_to_max x y : min x y = x + y - max x y.
+Proof. by rewrite -[x + y]addr_min_max addrK. Qed.
+
+Lemma maxr_to_min x y : max x y = x + y - min x y.
+Proof. by rewrite -[x + y]addr_max_min addrK. Qed.
+
+Lemma minrA x y z : min x (min y z) = min (min x y) z.
+Proof.
+rewrite /min; case: (lerP y z) => [hyz | /ltrW hyz].
+ by case: lerP => hxy; rewrite ?hyz // (@ler_trans _ y).
+case: lerP=> hxz; first by rewrite !(ler_trans hxz).
+case: (lerP x y)=> hxy; first by rewrite lerNgt hxz.
+by case: ltrgtP hyz.
+Qed.
+
+Lemma minrCA : @left_commutative R R min.
+Proof. by move=> x y z; rewrite !minrA [minr x y]minrC. Qed.
+
+Lemma minrAC : @right_commutative R R min.
+Proof. by move=> x y z; rewrite -!minrA [minr y z]minrC. Qed.
+
+CoInductive minr_spec x y : bool -> bool -> R -> Type :=
+| Minr_r of x <= y : minr_spec x y true false x
+| Minr_l of y < x : minr_spec x y false true y.
+
+Lemma minrP x y : minr_spec x y (x <= y) (y < x) (min x y).
+Proof.
+case: lerP=> hxy; first by rewrite minr_l //; constructor.
+by rewrite minr_r 1?ltrW //; constructor.
+Qed.
+
+Lemma oppr_max x y : - max x y = min (- x) (- y).
+Proof.
+case: minrP; rewrite lter_opp2 => hxy; first by rewrite maxr_l.
+by rewrite maxr_r // ltrW.
+Qed.
+
+Lemma oppr_min x y : - min x y = max (- x) (- y).
+Proof. by rewrite -[maxr _ _]opprK oppr_max !opprK. Qed.
+
+Lemma maxrA x y z : max x (max y z) = max (max x y) z.
+Proof. by apply/eqP; rewrite -eqr_opp !oppr_max minrA. Qed.
+
+Lemma maxrCA : @left_commutative R R max.
+Proof. by move=> x y z; rewrite !maxrA [maxr x y]maxrC. Qed.
+
+Lemma maxrAC : @right_commutative R R max.
+Proof. by move=> x y z; rewrite -!maxrA [maxr y z]maxrC. Qed.
+
+CoInductive maxr_spec x y : bool -> bool -> R -> Type :=
+| Maxr_r of y <= x : maxr_spec x y true false x
+| Maxr_l of x < y : maxr_spec x y false true y.
+
+Lemma maxrP x y : maxr_spec x y (y <= x) (x < y) (maxr x y).
+Proof.
+case: lerP => hxy; first by rewrite maxr_l //; constructor.
+by rewrite maxr_r 1?ltrW //; constructor.
+Qed.
+
+Lemma eqr_minl x y : (min x y == x) = (x <= y).
+Proof. by case: minrP=> hxy; rewrite ?eqxx // ltr_eqF. Qed.
+
+Lemma eqr_minr x y : (min x y == y) = (y <= x).
+Proof. by rewrite minrC eqr_minl. Qed.
+
+Lemma eqr_maxl x y : (max x y == x) = (y <= x).
+Proof. by case: maxrP=> hxy; rewrite ?eqxx // eq_sym ltr_eqF. Qed.
+
+Lemma eqr_maxr x y : (max x y == y) = (x <= y).
+Proof. by rewrite maxrC eqr_maxl. Qed.
+
+Lemma ler_minr x y z : (x <= min y z) = (x <= y) && (x <= z).
+Proof.
+case: minrP=> hyz.
+ by case: lerP=> hxy //; rewrite (ler_trans _ hyz).
+by case: lerP=> hxz; rewrite andbC // (ler_trans hxz) // ltrW.
+Qed.
+
+Lemma ler_minl x y z : (min y z <= x) = (y <= x) || (z <= x).
+Proof.
+case: minrP => hyz.
+ case: lerP => hyx //=; symmetry; apply: negbTE.
+ by rewrite -ltrNge (@ltr_le_trans _ y).
+case: lerP => hzx; rewrite orbC //=; symmetry; apply: negbTE.
+by rewrite -ltrNge (@ltr_trans _ z).
+Qed.
+
+Lemma ler_maxr x y z : (x <= max y z) = (x <= y) || (x <= z).
+Proof. by rewrite -lter_opp2 oppr_max ler_minl !ler_opp2. Qed.
+
+Lemma ler_maxl x y z : (max y z <= x) = (y <= x) && (z <= x).
+Proof. by rewrite -lter_opp2 oppr_max ler_minr !ler_opp2. Qed.
+
+Lemma ltr_minr x y z : (x < min y z) = (x < y) && (x < z).
+Proof. by rewrite !ltrNge ler_minl negb_or. Qed.
+
+Lemma ltr_minl x y z : (min y z < x) = (y < x) || (z < x).
+Proof. by rewrite !ltrNge ler_minr negb_and. Qed.
+
+Lemma ltr_maxr x y z : (x < max y z) = (x < y) || (x < z).
+Proof. by rewrite !ltrNge ler_maxl negb_and. Qed.
+
+Lemma ltr_maxl x y z : (max y z < x) = (y < x) && (z < x).
+Proof. by rewrite !ltrNge ler_maxr negb_or. Qed.
+
+Definition lter_minr := (ler_minr, ltr_minr).
+Definition lter_minl := (ler_minl, ltr_minl).
+Definition lter_maxr := (ler_maxr, ltr_maxr).
+Definition lter_maxl := (ler_maxl, ltr_maxl).
+
+Lemma addr_minl : @left_distributive R R +%R min.
+Proof.
+move=> x y z; case: minrP=> hxy; first by rewrite minr_l // ler_add2r.
+by rewrite minr_r // ltrW // ltr_add2r.
+Qed.
+
+Lemma addr_minr : @right_distributive R R +%R min.
+Proof.
+move=> x y z; case: minrP=> hxy; first by rewrite minr_l // ler_add2l.
+by rewrite minr_r // ltrW // ltr_add2l.
+Qed.
+
+Lemma addr_maxl : @left_distributive R R +%R max.
+Proof.
+move=> x y z; rewrite -[_ + _]opprK opprD oppr_max.
+by rewrite addr_minl -!opprD oppr_min !opprK.
+Qed.
+
+Lemma addr_maxr : @right_distributive R R +%R max.
+Proof.
+move=> x y z; rewrite -[_ + _]opprK opprD oppr_max.
+by rewrite addr_minr -!opprD oppr_min !opprK.
+Qed.
+
+Lemma minrK x y : max (min x y) x = x.
+Proof. by case: minrP => hxy; rewrite ?maxrr ?maxr_r // ltrW. Qed.
+
+Lemma minKr x y : min y (max x y) = y.
+Proof. by case: maxrP => hxy; rewrite ?minrr ?minr_l. Qed.
+
+Lemma maxr_minl : @left_distributive R R max min.
+Proof.
+move=> x y z; case: minrP => hxy.
+ by case: maxrP => hm; rewrite minr_l // ler_maxr (hxy, lerr) ?orbT.
+by case: maxrP => hyz; rewrite minr_r // ler_maxr (ltrW hxy, lerr) ?orbT.
+Qed.
+
+Lemma maxr_minr : @right_distributive R R max min.
+Proof. by move=> x y z; rewrite maxrC maxr_minl ![_ _ x]maxrC. Qed.
+
+Lemma minr_maxl : @left_distributive R R min max.
+Proof.
+move=> x y z; rewrite -[min _ _]opprK !oppr_min [- max x y]oppr_max.
+by rewrite maxr_minl !(oppr_max, oppr_min, opprK).
+Qed.
+
+Lemma minr_maxr : @right_distributive R R min max.
+Proof. by move=> x y z; rewrite minrC minr_maxl ![_ _ x]minrC. Qed.
+
+Lemma minr_pmulr x y z : 0 <= x -> x * min y z = min (x * y) (x * z).
+Proof.
+case: sgrP=> // hx _; first by rewrite hx !mul0r minrr.
+case: minrP=> hyz; first by rewrite minr_l // ler_pmul2l.
+by rewrite minr_r // ltrW // ltr_pmul2l.
+Qed.
+
+Lemma minr_nmulr x y z : x <= 0 -> x * min y z = max (x * y) (x * z).
+Proof.
+move=> hx; rewrite -[_ * _]opprK -mulNr minr_pmulr ?oppr_cp0 //.
+by rewrite oppr_min !mulNr !opprK.
+Qed.
+
+Lemma maxr_pmulr x y z : 0 <= x -> x * max y z = max (x * y) (x * z).
+Proof.
+move=> hx; rewrite -[_ * _]opprK -mulrN oppr_max minr_pmulr //.
+by rewrite oppr_min !mulrN !opprK.
+Qed.
+
+Lemma maxr_nmulr x y z : x <= 0 -> x * max y z = min (x * y) (x * z).
+Proof.
+move=> hx; rewrite -[_ * _]opprK -mulrN oppr_max minr_nmulr //.
+by rewrite oppr_max !mulrN !opprK.
+Qed.
+
+Lemma minr_pmull x y z : 0 <= x -> min y z * x = min (y * x) (z * x).
+Proof. by move=> *; rewrite mulrC minr_pmulr // ![_ * x]mulrC. Qed.
+
+Lemma minr_nmull x y z : x <= 0 -> min y z * x = max (y * x) (z * x).
+Proof. by move=> *; rewrite mulrC minr_nmulr // ![_ * x]mulrC. Qed.
+
+Lemma maxr_pmull x y z : 0 <= x -> max y z * x = max (y * x) (z * x).
+Proof. by move=> *; rewrite mulrC maxr_pmulr // ![_ * x]mulrC. Qed.
+
+Lemma maxr_nmull x y z : x <= 0 -> max y z * x = min (y * x) (z * x).
+Proof. by move=> *; rewrite mulrC maxr_nmulr // ![_ * x]mulrC. Qed.
+
+Lemma maxrN x : max x (- x) = `|x|.
+Proof.
+case: ger0P=> hx; first by rewrite maxr_l // ge0_cp //.
+by rewrite maxr_r // le0_cp // ltrW.
+Qed.
+
+Lemma maxNr x : max (- x) x = `|x|.
+Proof. by rewrite maxrC maxrN. Qed.
+
+Lemma minrN x : min x (- x) = - `|x|.
+Proof. by rewrite -[minr _ _]opprK oppr_min opprK maxNr. Qed.
+
+Lemma minNr x : min (- x) x = - `|x|.
+Proof. by rewrite -[minr _ _]opprK oppr_min opprK maxrN. Qed.
+
+End MinMax.
+
+Section PolyBounds.
+
+Variable p : {poly R}.
+
+Lemma poly_itv_bound a b : {ub | forall x, a <= x <= b -> `|p.[x]| <= ub}.
+Proof.
+have [ub le_p_ub] := poly_disk_bound p (Num.max `|a| `|b|).
+exists ub => x /andP[le_a_x le_x_b]; rewrite le_p_ub // ler_maxr !ler_normr.
+by have [_|_] := ler0P x; rewrite ?ler_opp2 ?le_a_x ?le_x_b orbT.
+Qed.
+
+Lemma monic_Cauchy_bound : p \is monic -> {b | forall x, x >= b -> p.[x] > 0}.
+Proof.
+move/monicP=> mon_p; pose n := (size p - 2)%N.
+have [p_le1 | p_gt1] := leqP (size p) 1.
+ exists 0 => x _; rewrite (size1_polyC p_le1) hornerC.
+ by rewrite -[p`_0]lead_coefC -size1_polyC // mon_p ltr01.
+pose lb := \sum_(j < n.+1) `|p`_j|; exists (lb + 1) => x le_ub_x.
+have x_ge1: 1 <= x; last have x_gt0 := ltr_le_trans ltr01 x_ge1.
+ by rewrite -(ler_add2l lb) ler_paddl ?sumr_ge0 // => j _; apply: normr_ge0.
+rewrite horner_coef -(subnK p_gt1) -/n addnS big_ord_recr /= addn1.
+rewrite [in p`__]subnSK // subn1 -lead_coefE mon_p mul1r -ltr_subl_addl sub0r.
+apply: ler_lt_trans (_ : lb * x ^+ n < _); last first.
+ rewrite exprS ltr_pmul2r ?exprn_gt0 ?(ltr_le_trans ltr01) //.
+ by rewrite -(ltr_add2r 1) ltr_spaddr ?ltr01.
+rewrite -sumrN mulr_suml ler_sum // => j _; apply: ler_trans (ler_norm _) _.
+rewrite normrN normrM ler_wpmul2l ?normr_ge0 // normrX.
+by rewrite ger0_norm ?(ltrW x_gt0) // ler_weexpn2l ?leq_ord.
+Qed.
+
+End PolyBounds.
+
+End RealDomainOperations.
+
+Section RealField.
+
+Variables (F : realFieldType) (x y : F).
+
+Lemma lerif_mean_square : x * y <= (x ^+ 2 + y ^+ 2) / 2%:R ?= iff (x == y).
+Proof. by apply: real_lerif_mean_square; apply: num_real. Qed.
+
+Lemma lerif_AGM2 : x * y <= ((x + y) / 2%:R)^+ 2 ?= iff (x == y).
+Proof. by apply: real_lerif_AGM2; apply: num_real. Qed.
+
+End RealField.
+
+Section ArchimedeanFieldTheory.
+
+Variables (F : archiFieldType) (x : F).
+
+Lemma archi_boundP : 0 <= x -> x < (bound x)%:R.
+Proof. by move/ger0_norm=> {1}<-; rewrite /bound; case: (sigW _). Qed.
+
+Lemma upper_nthrootP i : (bound x <= i)%N -> x < 2%:R ^+ i.
+Proof.
+rewrite /bound; case: (sigW _) => /= b le_x_b le_b_i.
+apply: ler_lt_trans (ler_norm x) (ltr_trans le_x_b _ ).
+by rewrite -natrX ltr_nat (leq_ltn_trans le_b_i) // ltn_expl.
+Qed.
+
+End ArchimedeanFieldTheory.
+
+Section RealClosedFieldTheory.
+
+Variable R : rcfType.
+Implicit Types a x y : R.
+
+Lemma poly_ivt : real_closed_axiom R. Proof. exact: poly_ivt. Qed.
+
+(* Square Root theory *)
+
+Lemma sqrtr_ge0 a : 0 <= sqrt a.
+Proof. by rewrite /sqrt; case: (sig2W _). Qed.
+Hint Resolve sqrtr_ge0.
+
+Lemma sqr_sqrtr a : 0 <= a -> sqrt a ^+ 2 = a.
+Proof.
+by rewrite /sqrt => a_ge0; case: (sig2W _) => /= x _; rewrite a_ge0 => /eqP.
+Qed.
+
+Lemma ler0_sqrtr a : a <= 0 -> sqrt a = 0.
+Proof.
+rewrite /sqrtr; case: (sig2W _) => x /= _.
+by have [//|_ /eqP//|->] := ltrgt0P a; rewrite mulf_eq0 orbb => /eqP.
+Qed.
+
+Lemma ltr0_sqrtr a : a < 0 -> sqrt a = 0.
+Proof. by move=> /ltrW; apply: ler0_sqrtr. Qed.
+
+CoInductive sqrtr_spec a : R -> bool -> bool -> R -> Type :=
+| IsNoSqrtr of a < 0 : sqrtr_spec a a false true 0
+| IsSqrtr b of 0 <= b : sqrtr_spec a (b ^+ 2) true false b.
+
+Lemma sqrtrP a : sqrtr_spec a a (0 <= a) (a < 0) (sqrt a).
+Proof.
+have [a_ge0|a_lt0] := ger0P a.
+ by rewrite -{1 2}[a]sqr_sqrtr //; constructor.
+by rewrite ltr0_sqrtr //; constructor.
+Qed.
+
+Lemma sqrtr_sqr a : sqrt (a ^+ 2) = `|a|.
+Proof.
+have /eqP : sqrt (a ^+ 2) ^+ 2 = `|a| ^+ 2.
+ by rewrite -normrX ger0_norm ?sqr_sqrtr ?sqr_ge0.
+rewrite eqf_sqr => /predU1P[-> //|ha].
+have := sqrtr_ge0 (a ^+ 2); rewrite (eqP ha) oppr_ge0 normr_le0 => /eqP ->.
+by rewrite normr0 oppr0.
+Qed.
+
+Lemma sqrtrM a b : 0 <= a -> sqrt (a * b) = sqrt a * sqrt b.
+Proof.
+case: (sqrtrP a) => // {a} a a_ge0 _; case: (sqrtrP b) => [b_lt0 | {b} b b_ge0].
+ by rewrite mulr0 ler0_sqrtr // nmulr_lle0 ?mulr_ge0.
+by rewrite mulrACA sqrtr_sqr ger0_norm ?mulr_ge0.
+Qed.
+
+Lemma sqrtr0 : sqrt 0 = 0 :> R.
+Proof. by move: (sqrtr_sqr 0); rewrite exprS mul0r => ->; rewrite normr0. Qed.
+
+Lemma sqrtr1 : sqrt 1 = 1 :> R.
+Proof. by move: (sqrtr_sqr 1); rewrite expr1n => ->; rewrite normr1. Qed.
+
+Lemma sqrtr_eq0 a : (sqrt a == 0) = (a <= 0).
+Proof.
+case: sqrtrP => [/ltrW ->|b]; first by rewrite eqxx.
+case: ltrgt0P => [b_gt0|//|->]; last by rewrite exprS mul0r lerr.
+by rewrite ltr_geF ?pmulr_rgt0.
+Qed.
+
+Lemma sqrtr_gt0 a : (0 < sqrt a) = (0 < a).
+Proof. by rewrite lt0r sqrtr_ge0 sqrtr_eq0 -ltrNge andbT. Qed.
+
+Lemma eqr_sqrt a b : 0 <= a -> 0 <= b -> (sqrt a == sqrt b) = (a == b).
+Proof.
+move=> a_ge0 b_ge0; apply/eqP/eqP=> [HS|->] //.
+by move: (sqr_sqrtr a_ge0); rewrite HS (sqr_sqrtr b_ge0).
+Qed.
+
+Lemma ler_wsqrtr : {homo @sqrt R : a b / a <= b}.
+Proof.
+move=> a b /= le_ab; case: (boolP (0 <= a))=> [pa|]; last first.
+ by rewrite -ltrNge; move/ltrW; rewrite -sqrtr_eq0; move/eqP->.
+rewrite -(@ler_pexpn2r R 2) ?nnegrE ?sqrtr_ge0 //.
+by rewrite !sqr_sqrtr // (ler_trans pa).
+Qed.
+
+Lemma ler_psqrt : {in @pos R &, {mono sqrt : a b / a <= b}}.
+Proof.
+apply: homo_mono_in => x y x_gt0 y_gt0.
+rewrite !ltr_neqAle => /andP[neq_xy le_xy].
+by rewrite ler_wsqrtr // eqr_sqrt ?ltrW // neq_xy.
+Qed.
+
+Lemma ler_sqrt a b : 0 < b -> (sqrt a <= sqrt b) = (a <= b).
+Proof.
+move=> b_gt0; have [a_le0|a_gt0] := ler0P a; last by rewrite ler_psqrt.
+by rewrite ler0_sqrtr // sqrtr_ge0 (ler_trans a_le0) ?ltrW.
+Qed.
+
+Lemma ltr_sqrt a b : 0 < b -> (sqrt a < sqrt b) = (a < b).
+Proof.
+move=> b_gt0; have [a_le0|a_gt0] := ler0P a; last first.
+ by rewrite (lerW_mono_in ler_psqrt).
+by rewrite ler0_sqrtr // sqrtr_gt0 b_gt0 (ler_lt_trans a_le0).
+Qed.
+
+End RealClosedFieldTheory.
+
+End Theory.
+
+Module RealMixin.
+
+Section RealMixins.
+
+Variables (R : idomainType) (le : rel R) (lt : rel R) (norm : R -> R).
+Local Infix "<=" := le.
+Local Infix "<" := lt.
+Local Notation "`| x |" := (norm x) : ring_scope.
+
+Section LeMixin.
+
+Hypothesis le0_add : forall x y, 0 <= x -> 0 <= y -> 0 <= x + y.
+Hypothesis le0_mul : forall x y, 0 <= x -> 0 <= y -> 0 <= x * y.
+Hypothesis le0_anti : forall x, 0 <= x -> x <= 0 -> x = 0.
+Hypothesis sub_ge0 : forall x y, (0 <= y - x) = (x <= y).
+Hypothesis le0_total : forall x, (0 <= x) || (x <= 0).
+Hypothesis normN: forall x, `|- x| = `|x|.
+Hypothesis ge0_norm : forall x, 0 <= x -> `|x| = x.
+Hypothesis lt_def : forall x y, (x < y) = (y != x) && (x <= y).
+
+Let le0N x : (0 <= - x) = (x <= 0). Proof. by rewrite -sub0r sub_ge0. Qed.
+Let leN_total x : 0 <= x \/ 0 <= - x.
+Proof. by apply/orP; rewrite le0N le0_total. Qed.
+
+Let le00 : (0 <= 0). Proof. by have:= le0_total 0; rewrite orbb. Qed.
+Let le01 : (0 <= 1).
+Proof.
+by case/orP: (le0_total 1)=> // ?; rewrite -[1]mul1r -mulrNN le0_mul ?le0N.
+Qed.
+
+Fact lt0_add x y : 0 < x -> 0 < y -> 0 < x + y.
+Proof.
+rewrite !lt_def => /andP[x_neq0 l0x] /andP[y_neq0 l0y]; rewrite le0_add //.
+rewrite andbT addr_eq0; apply: contraNneq x_neq0 => hxy.
+by rewrite [x]le0_anti // hxy -le0N opprK.
+Qed.
+
+Fact eq0_norm x : `|x| = 0 -> x = 0.
+Proof.
+case: (leN_total x) => /ge0_norm => [-> // | Dnx nx0].
+by rewrite -[x]opprK -Dnx normN nx0 oppr0.
+Qed.
+
+Fact le_def x y : (x <= y) = (`|y - x| == y - x).
+Proof.
+wlog ->: x y / x = 0 by move/(_ 0 (y - x)); rewrite subr0 sub_ge0 => ->.
+rewrite {x}subr0; apply/idP/eqP=> [/ge0_norm// | Dy].
+by have [//| ny_ge0] := leN_total y; rewrite -Dy -normN ge0_norm.
+Qed.
+
+Fact normM : {morph norm : x y / x * y}.
+Proof.
+move=> x y /=; wlog x_ge0 : x / 0 <= x.
+ by move=> IHx; case: (leN_total x) => /IHx//; rewrite mulNr !normN.
+wlog y_ge0 : y / 0 <= y; last by rewrite ?ge0_norm ?le0_mul.
+by move=> IHy; case: (leN_total y) => /IHy//; rewrite mulrN !normN.
+Qed.
+
+Fact le_normD x y : `|x + y| <= `|x| + `|y|.
+Proof.
+wlog x_ge0 : x y / 0 <= x.
+ by move=> IH; case: (leN_total x) => /IH// /(_ (- y)); rewrite -opprD !normN.
+rewrite -sub_ge0 ge0_norm //; have [y_ge0 | ny_ge0] := leN_total y.
+ by rewrite !ge0_norm ?subrr ?le0_add.
+rewrite -normN ge0_norm //; have [hxy|hxy] := leN_total (x + y).
+ by rewrite ge0_norm // opprD addrCA -addrA addKr le0_add.
+by rewrite -normN ge0_norm // opprK addrCA addrNK le0_add.
+Qed.
+
+Lemma le_total x y : (x <= y) || (y <= x).
+Proof. by rewrite -sub_ge0 -opprB le0N orbC -sub_ge0 le0_total. Qed.
+
+Definition Le :=
+ Mixin le_normD lt0_add eq0_norm (in2W le_total) normM le_def lt_def.
+
+Lemma Real (R' : numDomainType) & phant R' :
+ R' = NumDomainType R Le -> real_axiom R'.
+Proof. by move->. Qed.
+
+End LeMixin.
+
+Section LtMixin.
+
+Hypothesis lt0_add : forall x y, 0 < x -> 0 < y -> 0 < x + y.
+Hypothesis lt0_mul : forall x y, 0 < x -> 0 < y -> 0 < x * y.
+Hypothesis lt0_ngt0 : forall x, 0 < x -> ~~ (x < 0).
+Hypothesis sub_gt0 : forall x y, (0 < y - x) = (x < y).
+Hypothesis lt0_total : forall x, x != 0 -> (0 < x) || (x < 0).
+Hypothesis normN : forall x, `|- x| = `|x|.
+Hypothesis ge0_norm : forall x, 0 <= x -> `|x| = x.
+Hypothesis le_def : forall x y, (x <= y) = (y == x) || (x < y).
+
+Fact le0_add x y : 0 <= x -> 0 <= y -> 0 <= x + y.
+Proof.
+rewrite !le_def => /predU1P[->|x_gt0]; first by rewrite add0r.
+by case/predU1P=> [->|y_gt0]; rewrite ?addr0 ?x_gt0 ?lt0_add // orbT.
+Qed.
+
+Fact le0_mul x y : 0 <= x -> 0 <= y -> 0 <= x * y.
+Proof.
+rewrite !le_def => /predU1P[->|x_gt0]; first by rewrite mul0r eqxx.
+by case/predU1P=> [->|y_gt0]; rewrite ?mulr0 ?eqxx // orbC lt0_mul.
+Qed.
+
+Fact le0_anti x : 0 <= x -> x <= 0 -> x = 0.
+Proof. by rewrite !le_def => /predU1P[] // /lt0_ngt0/negPf-> /predU1P[]. Qed.
+
+Fact sub_ge0 x y : (0 <= y - x) = (x <= y).
+Proof. by rewrite !le_def subr_eq0 sub_gt0. Qed.
+
+Fact lt_def x y : (x < y) = (y != x) && (x <= y).
+Proof.
+rewrite le_def; case: eqP => //= ->; rewrite -sub_gt0 subrr.
+by apply/idP=> lt00; case/negP: (lt0_ngt0 lt00).
+Qed.
+
+Fact le0_total x : (0 <= x) || (x <= 0).
+Proof. by rewrite !le_def [0 == _]eq_sym; have [|/lt0_total] := altP eqP. Qed.
+
+Definition Lt :=
+ Le le0_add le0_mul le0_anti sub_ge0 le0_total normN ge0_norm lt_def.
+
+End LtMixin.
+
+End RealMixins.
+
+End RealMixin.
+
+End Num.
+
+Export Num.NumDomain.Exports Num.NumField.Exports Num.ClosedField.Exports.
+Export Num.RealDomain.Exports Num.RealField.Exports.
+Export Num.ArchimedeanField.Exports Num.RealClosedField.Exports.
+Export Num.Syntax Num.PredInstances.
+
+Notation RealLeMixin := Num.RealMixin.Le.
+Notation RealLtMixin := Num.RealMixin.Lt.
+Notation RealLeAxiom R := (Num.RealMixin.Real (Phant R) (erefl _)).