Require Export Lia Arith Ring.
From Undecidability.Shared.Libs.PSL Require FinTypes.
Record leUpToC {X} (f g : X -> nat) : Type :=
{ c__leUpToC : nat;
correct__leUpToC : forall x, f x <= c__leUpToC * g x
}.
Arguments c__leUpToC {_ _ _ H} : rename.
Notation "f <=c g" := (@leUpToC _ f g) (at level 70, g at next level).
Instance leUpToC_preorder X: PreOrder (@leUpToC X).
Instance leUpToC_proper_eq X: Proper (Morphisms.pointwise_relation X eq ==> Morphisms.pointwise_relation X eq ==> arrow) (@leUpToC X).
Instance leUpToC_proper_eq_flip X: Proper (Morphisms.pointwise_relation X eq ==> Morphisms.pointwise_relation X eq ==> flip arrow) (@leUpToC X).
Instance le_leUpToC_subrelation X: subrelation (pointwise_relation X le) leUpToC.
Instance eq_leUpToC_subrelation X: subrelation (pointwise_relation X eq) leUpToC.
(* A record for easily expressing the subtype of functions up to some multiplicative constant. *)
Record UpToC {X} (F : X -> nat) : Type :=
mkUpToC
{
f__UpToC :> X -> nat;
correct__UpToC :> f__UpToC <=c F
}.
Add Printing Coercion f__UpToC.
Arguments f__UpToC : clear implicits.
Arguments f__UpToC {_} _ {_}.
destruct f as [? []];cbn. easy.
Qed.

Lemma upToC_S X (F f :X->nat) :
(fun _ => 1) <=c F
-> f <=c F
-> (fun x => S (f x)) <=c F.