@@ -544,3 +544,79 @@ uaddUscaleZeroR (USnoc d qd) (USnoc e qe) prf =
544544 rewrite uaddUscaleZeroR d e (predEq' prf) in
545545 rewrite qMulZeroL qe in
546546 rewrite qAddZeroR qd in Refl
547+
548+ ||| The `Just`-headed tail-combinator `uadd` uses on a USnoc/USnoc pair:
549+ ||| `uadd (USnoc a p) (USnoc b s) = combMaybe (qAdd p s) (uadd a b)`.
550+ combMaybe : Q -> Maybe Uvec -> Maybe Uvec
551+ combMaybe p Nothing = Nothing
552+ combMaybe p (Just d) = Just (USnoc d p)
553+
554+ ||| `uadd` on a USnoc pair reduces to `combMaybe` of the tail sum (definitional
555+ ||| once the tail sum is scrutinised).
556+ uaddUSnocReduce : (a, b : Uvec) -> (p, s : Q)
557+ -> uadd (USnoc a p) (USnoc b s) = combMaybe (qAdd p s) (uadd a b)
558+ uaddUSnocReduce a b p s with (uadd a b)
559+ _ | Nothing = Refl
560+ _ | Just d = Refl
561+
562+ ||| Invert a successful USnoc/USnoc sum: recover the tail sum and the head.
563+ uaddSnocSplit : (a, b : Uvec) -> (p, s : Q) -> (z : Uvec)
564+ -> uadd (USnoc a p) (USnoc b s) = Just z
565+ -> (c : Uvec ** (uadd a b = Just c, z = USnoc c (qAdd p s)))
566+ uaddSnocSplit a b p s z prf with (uadd a b)
567+ _ | Nothing = void (nothingNotJust' prf)
568+ _ | Just cc = (cc ** (Refl , sym (justInj' prf)))
569+
570+ ||| Lift `qReassoc` to usage vectors: the two reassociations of the additive
571+ ||| substitution accounting agree as `Maybe Uvec` (mirrors Coq `vec_reassoc`).
572+ vecReassoc : (du, dg1, dg2 : Uvec) -> (q', q1, q2 : Q) -> (dgr1, dgr2, dg : Uvec)
573+ -> uadd dg1 (uscale q1 du) = Just dgr1
574+ -> uadd dg2 (uscale q2 du) = Just dgr2
575+ -> uadd dg1 (uscale q' dg2) = Just dg
576+ -> uadd dgr1 (uscale q' dgr2) = uadd dg (uscale (qAdd q1 (qMul q' q2)) du)
577+ vecReassoc UEmpty UEmpty UEmpty q' q1 q2 dgr1 dgr2 dg h1 h2 h3 =
578+ rewrite sym (justInj' h1) in rewrite sym (justInj' h2) in rewrite sym (justInj' h3) in Refl
579+ vecReassoc UEmpty (USnoc _ _ ) _ q' q1 q2 dgr1 dgr2 dg h1 h2 h3 = void (nothingNotJust' h1)
580+ vecReassoc UEmpty UEmpty (USnoc _ _ ) q' q1 q2 dgr1 dgr2 dg h1 h2 h3 = void (nothingNotJust' h2)
581+ vecReassoc (USnoc du0 qd) UEmpty _ q' q1 q2 dgr1 dgr2 dg h1 h2 h3 = void (nothingNotJust' h1)
582+ vecReassoc (USnoc du0 qd) (USnoc _ _ ) UEmpty q' q1 q2 dgr1 dgr2 dg h1 h2 h3 = void (nothingNotJust' h2)
583+ vecReassoc (USnoc du0 qd) (USnoc dg1' dgq1) (USnoc dg2' dgq2) q' q1 q2 dgr1 dgr2 dg h1 h2 h3 =
584+ let (r1 ** (e1, hr1)) = uaddSnocSplit dg1' (uscale q1 du0) dgq1 (qMul q1 qd) dgr1 h1
585+ (r2 ** (e2, hr2)) = uaddSnocSplit dg2' (uscale q2 du0) dgq2 (qMul q2 qd) dgr2 h2
586+ (dm ** (e3, hdg)) = uaddSnocSplit dg1' (uscale q' dg2') dgq1 (qMul q' dgq2) dg h3
587+ ih = vecReassoc du0 dg1' dg2' q' q1 q2 r1 r2 dm e1 e2 e3
588+ in rewrite hr1 in rewrite hr2 in rewrite hdg in
589+ trans (uaddUSnocReduce r1 (uscale q' r2) (qAdd dgq1 (qMul q1 qd))
590+ (qMul q' (qAdd dgq2 (qMul q2 qd))))
591+ (trans (cong2 combMaybe (sym (qReassoc dgq1 dgq2 qd q' q1 q2)) ih)
592+ (sym (uaddUSnocReduce dm (uscale (qAdd q1 (qMul q' q2)) du0)
593+ (qAdd dgq1 (qMul q' dgq2)) (qMul (qAdd q1 (qMul q' q2)) qd))))
594+
595+ ||| The additive-split substitution accounting: combine the two recursive
596+ ||| residuals (mirrors Coq `subst_reassoc_add`).
597+ public export
598+ substReassocAdd : (dg1, dgr1, dg2, dgr2, dg, du : Uvec) -> (q', q1, q2 : Q)
599+ -> uadd dg1 (uscale q1 du) = Just dgr1
600+ -> uadd dg2 (uscale q2 du) = Just dgr2
601+ -> uadd dg1 (uscale q' dg2) = Just dg
602+ -> (dgr : Uvec ** (uadd dg (uscale (qAdd q1 (qMul q' q2)) du) = Just dgr,
603+ uadd dgr1 (uscale q' dgr2) = Just dgr))
604+ substReassocAdd dg1 dgr1 dg2 dgr2 dg du q' q1 q2 h1 h2 h3 =
605+ let hlen = trans (uaddLen dg1 (uscale q' dg2) dg h3)
606+ (trans (uaddLenEq dg1 (uscale q1 du) dgr1 h1)
607+ (trans (uscaleLen q1 du) (sym (uscaleLen (qAdd q1 (qMul q' q2)) du))))
608+ (dgr ** hdgr) = uaddTotal dg (uscale (qAdd q1 (qMul q' q2)) du) hlen
609+ in (dgr ** (hdgr, trans (vecReassoc du dg1 dg2 q' q1 q2 dgr1 dgr2 dg h1 h2 h3) hdgr))
610+
611+ ||| Multiplicative-split variant (`q' = One`) — mirrors Coq `subst_reassoc_mult`.
612+ public export
613+ substReassocMult : (dg1, dgr1, dg2, dgr2, dg, du : Uvec) -> (q1, q2 : Q)
614+ -> uadd dg1 (uscale q1 du) = Just dgr1
615+ -> uadd dg2 (uscale q2 du) = Just dgr2
616+ -> uadd dg1 dg2 = Just dg
617+ -> (dgr : Uvec ** (uadd dg (uscale (qAdd q1 q2) du) = Just dgr,
618+ uadd dgr1 dgr2 = Just dgr))
619+ substReassocMult dg1 dgr1 dg2 dgr2 dg du q1 q2 h1 h2 h3 =
620+ let (dgr ** (ha, hb)) = substReassocAdd dg1 dgr1 dg2 dgr2 dg du One q1 q2 h1 h2
621+ (rewrite uscaleOne dg2 in h3)
622+ in (dgr ** (rewrite sym (qMulOneL q2) in ha, rewrite sym (uscaleOne dgr2) in hb))
0 commit comments