Notation "\big [ op / idx ]_ ( i < n ) F" :=
  (\big[op/idx]_(i : ordinal n) F) : big_scope.Local Notation "x + y" := (plus x y).Notation "\max_ ( i 'in' A ) F" :=
 (\big[maxn/0%N]_(i in A) F%N) : nat_scope.

(* Specifications: *)
Lemma big_load R (K K' : R -> Type) idx op I r (P : pred I) F : K (\big[op/idx]_(i <- r | P i) F i) * K' (\big[op/idx]_(i <- r | P i) F i) -> K' (\big[op/idx]_(i <- r | P i) F i).
Lemma big_rec3 I r (P : pred I) F1 F2 F3 (K_F : forall i y1 y2 y3, P i -> K y1 y2 y3 -> K (op1 (F1 i) y1) (op2 (F2 i) y2) (op3 (F3 i) y3)) : K (\big[op1/id1]_(i <- r | P i) F1 i) (\big[op2/id2]_(i <- r | P i) F2 i) (\big[op3/id3]_(i <- r | P i) F3 i).
Lemma big_ind3 I r (P : pred I) F1 F2 F3 (K_F : forall i, P i -> K (F1 i) (F2 i) (F3 i)) : K (\big[op1/id1]_(i <- r | P i) F1 i) (\big[op2/id2]_(i <- r | P i) F2 i) (\big[op3/id3]_(i <- r | P i) F3 i).
Lemma big_rec2 I r (P : pred I) F1 F2 (K_F : forall i y1 y2, P i -> K y1 y2 -> K (op1 (F1 i) y1) (op2 (F2 i) y2)) : K (\big[op1/id1]_(i <- r | P i) F1 i) (\big[op2/id2]_(i <- r | P i) F2 i).
Lemma big_ind2 I r (P : pred I) F1 F2 (K_F : forall i, P i -> K (F1 i) (F2 i)) : K (\big[op1/id1]_(i <- r | P i) F1 i) (\big[op2/id2]_(i <- r | P i) F2 i).
Lemma big_morph I r (P : pred I) F : f (\big[op2/id2]_(i <- r | P i) F i) = \big[op1/id1]_(i <- r | P i) f (F i).
Lemma big_rec I r (P : pred I) F (Kop : forall i x, P i -> K x -> K (op (F i) x)) : K (\big[op/idx]_(i <- r | P i) F i).
Lemma big_ind I r (P : pred I) F (K_F : forall i, P i -> K (F i)) : K (\big[op/idx]_(i <- r | P i) F i).
Lemma eq_big_op I r (P : pred I) F (K_F : forall i, P i -> K (F i)) : \big[op/idx]_(i <- r | P i) F i = \big[op'/idx]_(i <- r | P i) F i.
Lemma big_endo I r (P : pred I) F : f (\big[op/idx]_(i <- r | P i) F i) = \big[op/idx]_(i <- r | P i) f (F i).
Lemma big_filter r (P : pred I) F : \big[op/idx]_(i <- filter P r) F i = \big[op/idx]_(i <- r | P i) F i.
Lemma big_filter_cond r (P1 P2 : pred I) F : \big[op/idx]_(i <- filter P1 r | P2 i) F i = \big[op/idx]_(i <- r | P1 i && P2 i) F i.
Lemma eq_bigl r (P1 P2 : pred I) F : P1 =1 P2 -> \big[op/idx]_(i <- r | P1 i) F i = \big[op/idx]_(i <- r | P2 i) F i.
Lemma big_andbC r (P Q : pred I) F : \big[op/idx]_(i <- r | P i && Q i) F i = \big[op/idx]_(i <- r | Q i && P i) F i.
Lemma eq_bigr r (P : pred I) F1 F2 : (forall i, P i -> F1 i = F2 i) -> \big[op/idx]_(i <- r | P i) F1 i = \big[op/idx]_(i <- r | P i) F2 i.
Lemma eq_big r (P1 P2 : pred I) F1 F2 : P1 =1 P2 -> (forall i, P1 i -> F1 i = F2 i) -> \big[op/idx]_(i <- r | P1 i) F1 i = \big[op/idx]_(i <- r | P2 i) F2 i.
Lemma congr_big r1 r2 (P1 P2 : pred I) F1 F2 : r1 = r2 -> P1 =1 P2 -> (forall i, P1 i -> F1 i = F2 i) -> \big[op/idx]_(i <- r1 | P1 i) F1 i = \big[op/idx]_(i <- r2 | P2 i) F2 i.
Lemma big_cons i r (P : pred I) F : let x := \big[op/idx]_(j <- r | P j) F j in \big[op/idx]_(j <- i :: r | P j) F j = if P i then op (F i) x else x.
Lemma big_map J (h : J -> I) r (P : pred I) F : \big[op/idx]_(i <- map h r | P i) F i = \big[op/idx]_(j <- r | P (h j)) F (h j).
Lemma big_nth x0 r (P : pred I) F : \big[op/idx]_(i <- r | P i) F i = \big[op/idx]_(0 <= i < size r | P (nth x0 r i)) (F (nth x0 r i)).
Lemma big_hasC r (P : pred I) F : ~~ has P r -> \big[op/idx]_(i <- r | P i) F i = idx.
Lemma big_pred0_eq (r : seq I) F : \big[op/idx]_(i <- r | false) F i = idx.
Lemma big_pred0 r (P : pred I) F : P =1 xpred0 -> \big[op/idx]_(i <- r | P i) F i = idx.
Lemma big_cat_nested r1 r2 (P : pred I) F : let x := \big[op/idx]_(i <- r2 | P i) F i in \big[op/idx]_(i <- r1 ++ r2 | P i) F i = \big[op/x]_(i <- r1 | P i) F i.
Lemma big_catl r1 r2 (P : pred I) F : ~~ has P r2 -> \big[op/idx]_(i <- r1 ++ r2 | P i) F i = \big[op/idx]_(i <- r1 | P i) F i.
Lemma big_catr r1 r2 (P : pred I) F : ~~ has P r1 -> \big[op/idx]_(i <- r1 ++ r2 | P i) F i = \big[op/idx]_(i <- r2 | P i) F i.
Lemma big_const_seq r (P : pred I) x : \big[op/idx]_(i <- r | P i) x = iter (count P r) (op x) idx.
Lemma big_nat_cond m n (P : pred nat) F : \big[op/idx]_(m <= i < n | P i) F i = \big[op/idx]_(m <= i < n | (m <= i < n) && P i) F i.
Lemma big_nat m n F : \big[op/idx]_(m <= i < n) F i = \big[op/idx]_(m <= i < n | m <= i < n) F i.
Lemma congr_big_nat m1 n1 m2 n2 P1 P2 F1 F2 : m1 = m2 -> n1 = n2 -> (forall i, m1 <= i < n2 -> P1 i = P2 i) -> (forall i, P1 i && (m1 <= i < n2) -> F1 i = F2 i) -> \big[op/idx]_(m1 <= i < n1 | P1 i) F1 i = \big[op/idx]_(m2 <= i < n2 | P2 i) F2 i.
Lemma eq_big_nat m n F1 F2 : (forall i, m <= i < n -> F1 i = F2 i) -> \big[op/idx]_(m <= i < n) F1 i = \big[op/idx]_(m <= i < n) F2 i.
Lemma big_geq m n (P : pred nat) F : m >= n -> \big[op/idx]_(m <= i < n | P i) F i = idx.
Lemma big_addn m n a (P : pred nat) F : \big[op/idx]_(m + a <= i < n | P i) F i = \big[op/idx]_(m <= i < n - a | P (i + a)) F (i + a).
Lemma big_mkord n (P : pred nat) F : \big[op/idx]_(0 <= i < n | P i) F i = \big[op/idx]_(i < n | P i) F i.
Lemma big_nat_widen m n1 n2 (P : pred nat) F : n1 <= n2 -> \big[op/idx]_(m <= i < n1 | P i) F i = \big[op/idx]_(m <= i < n2 | P i && (i < n1)) F i.
Lemma big_ord_widen_cond n1 n2 (P : pred nat) (F : nat -> R) : n1 <= n2 -> \big[op/idx]_(i < n1 | P i) F i = \big[op/idx]_(i < n2 | P i && (i < n1)) F i.
Lemma big_ord_widen n1 n2 (F : nat -> R) : n1 <= n2 -> \big[op/idx]_(i < n1) F i = \big[op/idx]_(i < n2 | i < n1) F i.
Lemma big_ord0 P F : \big[op/idx]_(i < 0 | P i) F i = idx.
Lemma big_tnth I r (P : pred I) F : let r_ := tnth (in_tuple r) in \big[op/idx]_(i <- r | P i) F i = \big[op/idx]_(i < size r | P (r_ i)) (F (r_ i)).
Lemma big_ord_narrow n1 n2 F (le_n12 : n1 <= n2) : let w := widen_ord le_n12 in \big[op/idx]_(i < n2 | i < n1) F i = \big[op/idx]_(i < n1) F (w i).
Lemma big_const_nat m n x : \big[op/idx]_(m <= i < n) x = iter (n - m) (op x) idx.
Lemma big_const_ord n x : \big[op/idx]_(i < n) x = iter n (op x) idx.
Lemma big_nseq_cond I n a (P : pred I) F : \big[op/idx]_(i <- nseq n a | P i) F i = if P a then iter n (op (F a)) idx else idx.
Lemma big_nseq I n a (F : I -> R): \big[op/idx]_(i <- nseq n a) F i = iter n (op (F a)) idx.
Lemma eq_big_idx_seq idx' I r (P : pred I) F : right_id idx' *%M -> has P r -> \big[*%M/idx']_(i <- r | P i) F i =\big[*%M/1]_(i <- r | P i) F i.
Lemma eq_big_idx idx' (I : finType) i0 (P : pred I) F : P i0 -> right_id idx' *%M -> \big[*%M/idx']_(i | P i) F i =\big[*%M/1]_(i | P i) F i.
Lemma big1_eq I r (P : pred I) : \big[*%M/1]_(i <- r | P i) 1 = 1.
Lemma big1 I r (P : pred I) F : (forall i, P i -> F i = 1) -> \big[*%M/1]_(i <- r | P i) F i = 1.
Lemma big_mkcond I r (P : pred I) F : \big[*%M/1]_(i <- r | P i) F i = \big[*%M/1]_(i <- r) (if P i then F i else 1).
Lemma big_mkcondr I r (P Q : pred I) F : \big[*%M/1]_(i <- r | P i && Q i) F i = \big[*%M/1]_(i <- r | P i) (if Q i then F i else 1).
Lemma big_mkcondl I r (P Q : pred I) F : \big[*%M/1]_(i <- r | P i && Q i) F i = \big[*%M/1]_(i <- r | Q i) (if P i then F i else 1).
Lemma big_cat I r1 r2 (P : pred I) F : \big[*%M/1]_(i <- r1 ++ r2 | P i) F i = \big[*%M/1]_(i <- r1 | P i) F i * \big[*%M/1]_(i <- r2 | P i) F i.
Lemma big_pred1 (I : finType) i (P : pred I) F : P =1 pred1 i -> \big[*%M/1]_(j | P j) F j = F i.
Lemma big_cat_nat n m p (P : pred nat) F : m <= n -> n <= p -> \big[*%M/1]_(m <= i < p | P i) F i = (\big[*%M/1]_(m <= i < n | P i) F i) * (\big[*%M/1]_(n <= i < p | P i) F i).
Lemma big_sumType (I1 I2 : finType) (P : pred (I1 + I2)) F : \big[*%M/1]_(i | P i) F i = (\big[*%M/1]_(i | P (inl _ i)) F (inl _ i)) * (\big[*%M/1]_(i | P (inr _ i)) F (inr _ i)).
Lemma big_flatten I rr (P : pred I) F : \big[*%M/1]_(i <- flatten rr | P i) F i = \big[*%M/1]_(r <- rr) \big[*%M/1]_(i <- r | P i) F i.
Lemma eq_big_perm (I : eqType) r1 r2 (P : pred I) F : perm_eq r1 r2 -> \big[*%M/1]_(i <- r1 | P i) F i = \big[*%M/1]_(i <- r2 | P i) F i.
Lemma big_uniq (I : finType) (r : seq I) F : uniq r -> \big[*%M/1]_(i <- r) F i = \big[*%M/1]_(i in r) F i.
Lemma big_undup (I : eqType) (r : seq I) (P : pred I) F : idempotent *%M -> \big[*%M/1]_(i <- undup r | P i) F i = \big[*%M/1]_(i <- r | P i) F i.
Lemma eq_big_idem (I : eqType) (r1 r2 : seq I) (P : pred I) F : idempotent *%M -> r1 =i r2 -> \big[*%M/1]_(i <- r1 | P i) F i = \big[*%M/1]_(i <- r2 | P i) F i.
Lemma big_undup_iterop_count (I : eqType) (r : seq I) (P : pred I) F : \big[*%M/1]_(i <- undup r | P i) iterop (count_mem i r) *%M (F i) 1 = \big[*%M/1]_(i <- r | P i) F i.
Lemma big_split I r (P : pred I) F1 F2 : \big[*%M/1]_(i <- r | P i) (F1 i * F2 i) = \big[*%M/1]_(i <- r | P i) F1 i * \big[*%M/1]_(i <- r | P i) F2 i.
Lemma bigID I r (a P : pred I) F : \big[*%M/1]_(i <- r | P i) F i = \big[*%M/1]_(i <- r | P i && a i) F i * \big[*%M/1]_(i <- r | P i && ~~ a i) F i.
Lemma reindex_inj (I : finType) (h : I -> I) (P : pred I) F : injective h -> \big[*%M/1]_(i | P i) F i = \big[*%M/1]_(j | P (h j)) F (h j).
Lemma exchange_big_dep I J rI rJ (P : pred I) (Q : I -> pred J) (xQ : pred J) F : (forall i j, P i -> Q i j -> xQ j) -> \big[*%M/1]_(i <- rI | P i) \big[*%M/1]_(j <- rJ | Q i j) F i j = \big[*%M/1]_(j <- rJ | xQ j) \big[*%M/1]_(i <- rI | P i && Q i j) F i j.
Lemma exchange_big I J rI rJ (P : pred I) (Q : pred J) F : \big[*%M/1]_(i <- rI | P i) \big[*%M/1]_(j <- rJ | Q j) F i j = \big[*%M/1]_(j <- rJ | Q j) \big[*%M/1]_(i <- rI | P i) F i j.
Lemma exchange_big_dep_nat m1 n1 m2 n2 (P : pred nat) (Q : rel nat) (xQ : pred nat) F : (forall i j, m1 <= i < n1 -> m2 <= j < n2 -> P i -> Q i j -> xQ j) -> \big[*%M/1]_(m1 <= i < n1 | P i) \big[*%M/1]_(m2 <= j < n2 | Q i j) F i j = \big[*%M/1]_(m2 <= j < n2 | xQ j) \big[*%M/1]_(m1 <= i < n1 | P i && Q i j) F i j.
Lemma exchange_big_nat m1 n1 m2 n2 (P Q : pred nat) F : \big[*%M/1]_(m1 <= i < n1 | P i) \big[*%M/1]_(m2 <= j < n2 | Q j) F i j = \big[*%M/1]_(m2 <= j < n2 | Q j) \big[*%M/1]_(m1 <= i < n1 | P i) F i j.
Lemma big_distrl I r a (P : pred I) F : \big[+%M/0]_(i <- r | P i) F i * a = \big[+%M/0]_(i <- r | P i) (F i * a).
Lemma big_distrr I r a (P : pred I) F : a * \big[+%M/0]_(i <- r | P i) F i = \big[+%M/0]_(i <- r | P i) (a * F i).
Lemma big_distrlr I J rI rJ (pI : pred I) (pJ : pred J) F G : (\big[+%M/0]_(i <- rI | pI i) F i) * (\big[+%M/0]_(j <- rJ | pJ j) G j) = \big[+%M/0]_(i <- rI | pI i) \big[+%M/0]_(j <- rJ | pJ j) (F i * G j).
Lemma big_has : \big[orb/false]_(i <- r) B i = has B r.
Lemma big_all : \big[andb/true]_(i <- r) B i = all B r.
Lemma big_has_cond : \big[orb/false]_(i <- r | P i) B i = has (predI P B) r.
Lemma sum1_count J (r : seq J) (a : pred J) : \sum_(j <- r | a j) 1 = count a r.
Lemma sum1_size J (r : seq J) : \sum_(j <- r) 1 = size r.
Lemma sum_nat_const_nat n1 n2 n : \sum_(n1 <= i < n2) n = (n2 - n1) * n.
Lemma prod_nat_const_nat n1 n2 n : \prod_(n1 <= i < n2) n = n ^ (n2 - n1).
Lemma leq_sum I r (P : pred I) (E1 E2 : I -> nat) : (forall i, P i -> E1 i <= E2 i) -> \sum_(i <- r | P i) E1 i <= \sum_(i <- r | P i) E2 i.
Lemma prodn_cond_gt0 I r (P : pred I) F : (forall i, P i -> 0 < F i) -> 0 < \prod_(i <- r | P i) F i.
Lemma prodn_gt0 I r (P : pred I) F : (forall i, 0 < F i) -> 0 < \prod_(i <- r | P i) F i.
Lemma leq_bigmax_cond (I : finType) (P : pred I) F i0 : P i0 -> F i0 <= \max_(i | P i) F i.
Lemma leq_bigmax (I : finType) F (i0 : I) : F i0 <= \max_i F i.
Lemma bigmax_leqP (I : finType) (P : pred I) m F : reflect (forall i, P i -> F i <= m) (\max_(i | P i) F i <= m).
Lemma bigmax_sup (I : finType) i0 (P : pred I) m F : P i0 -> m <= F i0 -> m <= \max_(i | P i) F i.
Lemma expn_sum m I r (P : pred I) F : (m ^ (\sum_(i <- r | P i) F i) = \prod_(i <- r | P i) m ^ F i)%N.