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_mul X (F1 F2 f1 f2 :X->nat) :
f1 <=c F1
-> f2 <=c F2
-> (fun x => f1 x * f2 x) <=c (fun x => F1 x * F2 x).