The core module lean/FrcCore/Quaternion.lean — the substrate from first principles, no Mathlib, no axioms (the modules in order: Nat, Pigeonhole, Shell, Series, Cycle, Ring, FrameCore, Frame, Parity, Transform, Orbit, Sum, Theme/Projective, Theme/Fourier, Theme/Fractional, Theme/Lifts, Theme/Dichotomy, Theme/Rotations, Theme/Heisenberg, Theme/Spectra, Theme/Exclusivity, Theme/Quadratic, Theme/Extension, Theme/Tally, Theme/Numbers, Theme/Logic, Theme/SecondOrder, Theme/Formation, Theme/Field, Theme/Foundation, Theme/Drive, Theme/Carrier, Theme/Subject, Theme/Pair, Theme/Hopf, Theme/Symbol, Theme/Gravity, Theme/Quantum, Theme/Unitary, Theme/Interactions, Theme/Horizon, Theme/Shift, Theme/Lattice, Theme/Drift, Theme/Observation, Theme/Interference, Theme/Composite, Theme/Ladder, Meridian, Fourier, Algebra, Epi, Dimensions, Poly, Quaternion, Causality, Representation, Reductio, Godel, Finitism, Geometry, Complex, Instances, Rh, Entropy, Dirac, Gravity, S13, Qm, Pnp, Keys/Frame, Keys/Extension, Keys/Projective, Keys/Fourier, Keys/Numbers, Keys/Logic, Keys/Foundation, Keys/Carrier, Keys/Subject, Keys/Gravity, Keys/Quantum, Keys/Interactions, Keys/Horizon): 40 theorems (12 definitions): 40 with no axioms, 0 at tier 1 (propext, Quot.sound), 0 at tier 2 (Classical.choice), 0 red; the mark's colour is the library's (green, the core; red a proof the gate rejects), each declaration's axioms on hover; the small plain glyph marks a definition (no proof, no axioms; on the ledger pages the plain glyph is instead a module cited as a whole). Each declaration is anchored; the ledger predicates cite them by name. ▶ open in Lean Live · axioms.log.
1import FrcCore.Algebra2import FrcCore.Theme.Extension34/-!5# FrcCore.Quaternion — the framed quaternions and the window (1:E6, the finitary clause); the Lie-algebra layer (1:E7, 1:E8)67A signed window integer is a pair of naturals `(u, v)` read as `u − v` in the shell (no `Int`: the core's8integers are the shell's own readings). A framed quaternion is four such pairs; the Hamilton product is9computed on the pairs, and `read_mul` says the product of the readings is the reading of the product — the10composition is exact. `quaternion_window` adds the bounds: with coordinates in the window `H` and a shell11`p > 8H²`, the product's coordinates lie in the window `4H²`, and the shell reading determines the integer12product among the window's quaternions. No axioms.1314The Lie-algebra layer works on quaternions over the shell (`Quat`, with `conj`, `nrm`, `cross`, `dot`). Its identities are15decided by a normaliser: `RE.sound` expands both sides of an identity into sorted lists of monomials and compares them by a16kernel computation, so an identity is one `decide +kernel`. 1:E7: the rotation `x ↦ q x q̄ / N(q)` is the Cayley17transform `(aI − S_v)⁻¹(aI + S_v)` (`rot_cayley`, `cayley_inj`), the half-turn at `a = 0` (`half_turn`), with kernel the18scalars (`rot_trivial`) and `ρ_{−q} = ρ_q` (`rot_neg`). 1:E8: `(1+u)(1+w) = (1 − u·w) + (u + w + u × w)` (`one_add_mul`),19the composition law (`compose`), the bracket (`bracket`). No axioms.2021Since the ledger migration (task LM17) the quaternions over the shell, their norm and the ring normaliser live in the22extension theme (`Theme/Extension.lean`) under their names; this module keeps the window and the Lie-algebra layer.23-/2425namespace FRC26namespace Shell27namespace Frame2829variable {p : Nat} [Pos p]3031/-- A signed window integer: `(u, v)` stands for `u − v`. -/32abbrev SInt := Nat × Nat3334
def sread (x : SInt) : Shell p := ofNat x.1 + -(ofNat x.2)35
def sadd (x y : SInt) : SInt := (x.1 + y.1, x.2 + y.2)36
def sneg (x : SInt) : SInt := (x.2, x.1)37
def smul (x y : SInt) : SInt := (x.1 * y.1 + x.2 * y.2, x.1 * y.2 + x.2 * y.1)38/-- The canonical pair of the same value: one component zero. -/39
def snorm (x : SInt) : SInt := (x.1 - x.2, x.2 - x.1)4041
theorem prod_ext {x y : SInt} (h1 : x.1 = y.1) (h2 : x.2 = y.2) : x = y :=42 match x, y, h1, h2 with43 | (_, _), (_, _), h1, h2 => by cases h1; cases h2; rfl4445
theorem sread_add (x y : SInt) : (sread (sadd x y) : Shell p) = sread x + sread y := by46 unfold sread sadd47 show ofNat (x.1 + y.1) + -(ofNat (x.2 + y.2)) = ofNat x.1 + -(ofNat x.2) + (ofNat y.1 + -(ofNat y.2))48 rw [← ofNat_add, ← ofNat_add, neg_add_rev, add_assoc, add_assoc, ← add_assoc (-(ofNat x.2)),49 add_comm (-(ofNat x.2)) (ofNat y.1), add_assoc]5051
theorem sread_neg (x : SInt) : (sread (sneg x) : Shell p) = -(sread x) := by52 unfold sread sneg53 show ofNat x.2 + -(ofNat x.1) = -(ofNat x.1 + -(ofNat x.2))54 rw [neg_add_rev, neg_neg, add_comm]5556
theorem sread_mul (x y : SInt) : (sread (smul x y) : Shell p) = sread x * sread y := by57 unfold sread smul58 show ofNat (x.1 * y.1 + x.2 * y.2) + -(ofNat (x.1 * y.2 + x.2 * y.1)) =59 (ofNat x.1 + -(ofNat x.2)) * (ofNat y.1 + -(ofNat y.2))60 rw [right_distrib, left_distrib, left_distrib, ← mul_neg, ← neg_mul, neg_mul_neg, ← ofNat_add, ← ofNat_add,61 ← ofNat_mul, ← ofNat_mul, ← ofNat_mul, ← ofNat_mul, neg_add_rev]62 -- a + d + (-b + -c) = a + -b + (-c + d)63 rw [add_assoc, add_assoc]64 refine congrArg (ofNat x.1 * ofNat y.1 + ·) ?_65 rw [← add_assoc, add_comm (ofNat x.2 * ofNat y.2), add_assoc, add_comm (ofNat x.2 * ofNat y.2)]6667
theorem sread_norm (x : SInt) : (sread (snorm x) : Shell p) = sread x := by68 unfold sread snorm69 match Nat.decLe x.2 x.1 with70 | .isTrue h =>71 have e : x.2 - x.1 = 0 := FRC.Nat.sub_eq_zero_of_le h72 show ofNat (x.1 - x.2) + -(ofNat (x.2 - x.1)) = ofNat x.1 + -(ofNat x.2)73 rw [e]74 have e0 : (ofNat 0 : Shell p) = 0 := rfl75 rw [e0, neg_zero, add_zero]76 have e1 : x.1 = (x.1 - x.2) + x.2 := (FRC.Nat.sub_add_cancel h).symm77 calc ofNat (x.1 - x.2) = ofNat (x.1 - x.2) + 0 := (add_zero _).symm78 _ = ofNat (x.1 - x.2) + (ofNat x.2 + -(ofNat x.2)) := by rw [add_neg]79 _ = ofNat (x.1 - x.2 + x.2) + -(ofNat x.2) := by rw [← add_assoc, ofNat_add]80 _ = ofNat x.1 + -(ofNat x.2) := by rw [← e1]81 | .isFalse h =>82 have h' : x.1 ≤ x.2 := Nat.le_of_lt (Nat.lt_of_not_le h)83 have e : x.1 - x.2 = 0 := FRC.Nat.sub_eq_zero_of_le h'84 show ofNat (x.1 - x.2) + -(ofNat (x.2 - x.1)) = ofNat x.1 + -(ofNat x.2)85 rw [e]86 have e0 : (ofNat 0 : Shell p) = 0 := rfl87 rw [e0, zero_add]88 have e1 : x.2 = (x.2 - x.1) + x.1 := (FRC.Nat.sub_add_cancel h').symm89 calc (-(ofNat (x.2 - x.1)) : Shell p) = (0 : Shell p) + -(ofNat (x.2 - x.1)) := (zero_add _).symm90 _ = (ofNat x.1 + -(ofNat x.1)) + -(ofNat (x.2 - x.1)) := by rw [add_neg]91 _ = ofNat x.1 + -((ofNat (x.2 - x.1) : Shell p) + ofNat x.1) := by92 rw [add_assoc, neg_add_rev, add_comm (-(ofNat x.1))]93 _ = ofNat x.1 + -(ofNat x.2) := by rw [ofNat_add, ← e1]9495/-- The window bound: both components at most `H`, one of them zero. -/96
def SBound (H : Nat) (x : SInt) : Prop := x.1 ≤ H ∧ x.2 ≤ H ∧ (x.1 = 0 ∨ x.2 = 0)9798
theorem sneg_bound {H : Nat} {x : SInt} (h : SBound H x) : SBound H (sneg x) :=99 ⟨h.2.1, h.1, match h.2.2 with | Or.inl e => Or.inr e | Or.inr e => Or.inl e⟩100101
theorem smul_bound {H : Nat} {x y : SInt} (hx : SBound H x) (hy : SBound H y) : SBound (H * H) (smul x y) := by102 unfold smul103 have b11 := Nat.mul_le_mul hx.1 hy.1104 have b22 := Nat.mul_le_mul hx.2.1 hy.2.1105 have b12 := Nat.mul_le_mul hx.1 hy.2.1106 have b21 := Nat.mul_le_mul hx.2.1 hy.1107 match hx.2.2, hy.2.2 with108 | Or.inl e, Or.inl f =>109 refine ⟨?_, ?_, Or.inr ?_⟩110 · show x.1 * y.1 + x.2 * y.2 ≤ H * H111 rw [e, Nat.zero_mul, Nat.zero_add]; exact b22112 · show x.1 * y.2 + x.2 * y.1 ≤ H * H113 rw [e, f, Nat.zero_mul, Nat.mul_zero]; exact Nat.zero_le _114 · show x.1 * y.2 + x.2 * y.1 = 0115 rw [e, f, Nat.zero_mul, Nat.mul_zero]116 | Or.inl e, Or.inr f =>117 refine ⟨?_, ?_, Or.inl ?_⟩118 · show x.1 * y.1 + x.2 * y.2 ≤ H * H119 rw [e, f, Nat.zero_mul, Nat.mul_zero]; exact Nat.zero_le _120 · show x.1 * y.2 + x.2 * y.1 ≤ H * H121 rw [e, Nat.zero_mul, Nat.zero_add]; exact b21122 · show x.1 * y.1 + x.2 * y.2 = 0123 rw [e, f, Nat.zero_mul, Nat.mul_zero]124 | Or.inr e, Or.inl f =>125 refine ⟨?_, ?_, Or.inl ?_⟩126 · show x.1 * y.1 + x.2 * y.2 ≤ H * H127 rw [e, f, Nat.mul_zero, Nat.zero_mul]; exact Nat.zero_le _128 · show x.1 * y.2 + x.2 * y.1 ≤ H * H129 rw [e, Nat.zero_mul, Nat.add_zero]; exact b12130 · show x.1 * y.1 + x.2 * y.2 = 0131 rw [e, f, Nat.mul_zero, Nat.zero_mul]132 | Or.inr e, Or.inr f =>133 refine ⟨?_, ?_, Or.inr ?_⟩134 · show x.1 * y.1 + x.2 * y.2 ≤ H * H135 rw [e, Nat.zero_mul, Nat.add_zero]; exact b11136 · show x.1 * y.2 + x.2 * y.1 ≤ H * H137 rw [e, f, Nat.mul_zero, Nat.zero_mul]; exact Nat.zero_le _138 · show x.1 * y.2 + x.2 * y.1 = 0139 rw [e, f, Nat.mul_zero, Nat.zero_mul]140141/-- Four window terms of size `M` add to a pair with both components at most `4M`. -/142
theorem sum4_bound {M : Nat} {t1 t2 t3 t4 : SInt} (h1 : SBound M t1) (h2 : SBound M t2) (h3 : SBound M t3)143 (h4 : SBound M t4) :144 (sadd (sadd t1 t2) (sadd t3 t4)).1 ≤ 4 * M ∧ (sadd (sadd t1 t2) (sadd t3 t4)).2 ≤ 4 * M := by145 unfold sadd146 rw [four_mul_eq, Nat.add_assoc (M + M) M M]147 exact ⟨Nat.add_le_add (Nat.add_le_add h1.1 h2.1) (Nat.add_le_add h3.1 h4.1),148 Nat.add_le_add (Nat.add_le_add h1.2.1 h2.2.1) (Nat.add_le_add h3.2.1 h4.2.1)⟩149150
theorem snorm_bound {M : Nat} {x : SInt} (h1 : x.1 ≤ M) (h2 : x.2 ≤ M) : SBound M (snorm x) := by151 unfold snorm152 refine ⟨Nat.le_trans (Nat.sub_le _ _) h1, Nat.le_trans (Nat.sub_le _ _) h2, ?_⟩153 match Nat.decLe x.2 x.1 with154 | .isTrue h => exact Or.inr (FRC.Nat.sub_eq_zero_of_le h)155 | .isFalse h => exact Or.inl (FRC.Nat.sub_eq_zero_of_le (Nat.le_of_lt (Nat.lt_of_not_le h)))156157/-- The signed window law: two canonical pairs of size `M`, `2M < p`, with the same reading are equal. -/158
theorem sread_inj {M : Nat} (hM : 2 * M < p) {x y : SInt} (hx : SBound M x) (hy : SBound M y)159 (h : (sread x : Shell p) = sread y) : x = y := by160 unfold sread at h161 have h' : (ofNat (x.1 + y.2) : Shell p) = ofNat (y.1 + x.2) := by162 rw [← ofNat_add, ← ofNat_add]163 calc ofNat x.1 + ofNat y.2 = ofNat x.1 + -(ofNat x.2) + (ofNat x.2 + ofNat y.2) := by164 rw [add_assoc, ← add_assoc (-(ofNat x.2)), neg_add, zero_add]165 _ = ofNat y.1 + -(ofNat y.2) + (ofNat x.2 + ofNat y.2) := by rw [h]166 _ = ofNat y.1 + ofNat x.2 := by167 rw [add_assoc, add_comm (ofNat x.2), ← add_assoc (-(ofNat y.2)), neg_add, zero_add]168 have hv := val_injective h'169 rw [val_ofNat, val_ofNat] at hv170 have l1 : x.1 + y.2 < p := Nat.lt_of_le_of_lt (Nat.add_le_add hx.1 hy.2.1) (Nat.two_mul M ▸ hM)171 have l2 : y.1 + x.2 < p := Nat.lt_of_le_of_lt (Nat.add_le_add hy.1 hx.2.1) (Nat.two_mul M ▸ hM)172 rw [FRC.Nat.mod_eq_of_lt l1, FRC.Nat.mod_eq_of_lt l2] at hv173 -- hv : x.1 + y.2 = y.1 + x.2174 match hx.2.2, hy.2.2 with175 | Or.inl e, Or.inl f =>176 rw [e, f, Nat.zero_add, Nat.zero_add] at hv177 exact prod_ext (e.trans f.symm) hv.symm178 | Or.inl e, Or.inr f =>179 rw [e, f, Nat.zero_add] at hv180 -- hv : 0 = y.1 + x.2181 have hy1 : y.1 = 0 := Nat.eq_zero_of_add_eq_zero_right hv.symm182 have hx2 : x.2 = 0 := Nat.eq_zero_of_add_eq_zero_left hv.symm183 exact prod_ext (e.trans hy1.symm) (hx2.trans f.symm)184 | Or.inr e, Or.inl f =>185 rw [e, f, Nat.zero_add] at hv186 -- hv : x.1 + y.2 = 0187 have hx1 : x.1 = 0 := Nat.eq_zero_of_add_eq_zero_right hv188 have hy2 : y.2 = 0 := Nat.eq_zero_of_add_eq_zero_left hv189 exact prod_ext (hx1.trans f.symm) (e.trans hy2.symm)190 | Or.inr e, Or.inr f =>191 rw [e, f, Nat.add_zero, Nat.add_zero] at hv192 exact prod_ext hv (e.trans f.symm)193194/-- A framed quaternion with signed window coordinates. -/195
structure IQuat where196 a : SInt197 b : SInt198 c : SInt199 d : SInt200201/-- The Hamilton product on the window pairs, the same formula. -/202
def IQuat.mul (q r : IQuat) : IQuat :=203 ⟨sadd (sadd (smul q.a r.a) (sneg (smul q.b r.b))) (sadd (sneg (smul q.c r.c)) (sneg (smul q.d r.d))),204 sadd (sadd (smul q.a r.b) (smul q.b r.a)) (sadd (smul q.c r.d) (sneg (smul q.d r.c))),205 sadd (sadd (smul q.a r.c) (sneg (smul q.b r.d))) (sadd (smul q.c r.a) (smul q.d r.b)),206 sadd (sadd (smul q.a r.d) (smul q.b r.c)) (sadd (sneg (smul q.c r.b)) (smul q.d r.a))⟩207208
def IQuat.read (q : IQuat) : Quat p := ⟨sread q.a, sread q.b, sread q.c, sread q.d⟩209
def IQuat.norm (q : IQuat) : IQuat := ⟨snorm q.a, snorm q.b, snorm q.c, snorm q.d⟩210
def QBound (H : Nat) (q : IQuat) : Prop := SBound H q.a ∧ SBound H q.b ∧ SBound H q.c ∧ SBound H q.d211212
theorem IQuat.ext' {q r : IQuat} (ha : q.a = r.a) (hb : q.b = r.b) (hc : q.c = r.c) (hd : q.d = r.d) : q = r := by213 cases q; cases r; cases ha; cases hb; cases hc; cases hd; rfl214215/-- 1:E6, exact composition — the reading of the integer product is the product of the readings. -/216
theorem read_mul (q r : IQuat) : ((IQuat.mul q r).read : Quat p) = Quat.mul q.read r.read := by217 unfold IQuat.mul IQuat.read Quat.mul218 rw [sread_add, sread_add, sread_add, sread_add, sread_add, sread_add, sread_add, sread_add, sread_add,219 sread_add, sread_add, sread_add, sread_neg, sread_neg, sread_neg, sread_neg, sread_neg, sread_neg,220 sread_mul, sread_mul, sread_mul, sread_mul, sread_mul, sread_mul, sread_mul, sread_mul, sread_mul,221 sread_mul, sread_mul, sread_mul, sread_mul, sread_mul, sread_mul, sread_mul]222223
theorem read_norm (q : IQuat) : (q.norm.read : Quat p) = q.read := by224 unfold IQuat.norm IQuat.read225 rw [sread_norm, sread_norm, sread_norm, sread_norm]226227
theorem norm_bound {H : Nat} {q r : IQuat} (hq : QBound H q) (hr : QBound H r) :228 QBound (4 * (H * H)) (IQuat.mul q r).norm := by229 have m := fun {x y : SInt} (hx : SBound H x) (hy : SBound H y) => smul_bound hx hy230 refine ⟨?_, ?_, ?_, ?_⟩231 · have := sum4_bound (m hq.1 hr.1) (sneg_bound (m hq.2.1 hr.2.1)) (sneg_bound (m hq.2.2.1 hr.2.2.1))232 (sneg_bound (m hq.2.2.2 hr.2.2.2))233 exact snorm_bound this.1 this.2234 · have := sum4_bound (m hq.1 hr.2.1) (m hq.2.1 hr.1) (m hq.2.2.1 hr.2.2.2) (sneg_bound (m hq.2.2.2 hr.2.2.1))235 exact snorm_bound this.1 this.2236 · have := sum4_bound (m hq.1 hr.2.2.1) (sneg_bound (m hq.2.1 hr.2.2.2)) (m hq.2.2.1 hr.1) (m hq.2.2.2 hr.2.1)237 exact snorm_bound this.1 this.2238 · have := sum4_bound (m hq.1 hr.2.2.2) (m hq.2.1 hr.2.2.1) (sneg_bound (m hq.2.2.1 hr.2.1)) (m hq.2.2.2 hr.1)239 exact snorm_bound this.1 this.2240241/-- 1:E6, the finitary clause — framed quaternions with window coordinates `≤ H`, read in a shell `p > 8H²`,242compose exactly: the product of the readings is the reading of the integer product; that product's243coordinates lie in the window `4H²`; and the reading determines it among the window's quaternions. -/244
theorem quaternion_window {H : Nat} (hH : 8 * (H * H) < p) {q r : IQuat} (hq : QBound H q) (hr : QBound H r) :245 ((IQuat.mul q r).read : Quat p) = Quat.mul q.read r.read ∧246 QBound (4 * (H * H)) (IQuat.mul q r).norm ∧247 ∀ s : IQuat, QBound (4 * (H * H)) s → (s.read : Quat p) = (IQuat.mul q r).read → s = (IQuat.mul q r).norm := by248 refine ⟨read_mul q r, norm_bound hq hr, ?_⟩249 intro s hs he250 have hn := norm_bound hq hr251 have hM : 2 * (4 * (H * H)) < p := by rw [← Nat.mul_assoc]; exact hH252 rw [← read_norm (IQuat.mul q r)] at he253 unfold IQuat.read at he254 exact IQuat.ext' (sread_inj hM hs.1 hn.1 (congrArg Quat.a he)) (sread_inj hM hs.2.1 hn.2.1 (congrArg Quat.b he))255 (sread_inj hM hs.2.2.1 hn.2.2.1 (congrArg Quat.c he)) (sread_inj hM hs.2.2.2 hn.2.2.2 (congrArg Quat.d he))256257/-! ## 1:E7 — the Lie-algebra layer, one axis -/258259/-- 1:E7, conjugation keeps a pure quaternion pure: the scalar part of `q x q̄` vanishes. -/260
theorem rot_pure (q x : Quat p) (hx : x.a = 0) : (Quat.conjBy q x).a = 0 := by261 rw [Quat.pure_eq hx]262 exact RE.sound (look [q.a, q.b, q.c, q.d, x.b, x.c, x.d]) (QR.conjBy (QR.v 0) (QR.pv 4)).a .zero (by decide +kernel)263264/-- 1:E7, the Cayley form cleared of the norm: for `q = a + v` and a pure `x`, the conjugate `y = q x q̄` satisfies265`(aI − S_v) y = N(q) (aI + S_v) x`, where `S_v x = v × x`. -/266
theorem rot_cayley (q x : Quat p) (hx : x.a = 0) :267 Quat.add (Quat.smul q.a (Quat.conjBy q x)) (Quat.neg (Quat.cross (Quat.vec q) (Quat.conjBy q x))) =268 Quat.smul (Quat.nrm q) (Quat.add (Quat.smul q.a x) (Quat.cross (Quat.vec q) x)) := by269 rw [Quat.pure_eq hx]270 exact QR.sound (look [q.a, q.b, q.c, q.d, x.b, x.c, x.d])271 (QR.add (QR.smul (.var 0) (QR.conjBy (QR.v 0) (QR.pv 4))) (QR.neg (QR.cross (QR.vec (QR.v 0)) (QR.conjBy (QR.v 0) (QR.pv 4)))))272 (QR.smul (QR.nrm (QR.v 0)) (QR.add (QR.smul (.var 0) (QR.pv 4)) (QR.cross (QR.vec (QR.v 0)) (QR.pv 4)))) (by decide +kernel)273274/-- 1:E7, the half-turn: for pure `v` and `x`, `v x v̄ = N(v) x + 2 v × (v × x)`, so `ρ_v = I + 2N(v)⁻¹ S_v²`. -/275
theorem half_turn (v x : Quat p) (hv : v.a = 0) (hx : x.a = 0) :276 Quat.conjBy v x = Quat.add (Quat.smul (Quat.nrm v) x) (Quat.add (Quat.cross v (Quat.cross v x)) (Quat.cross v (Quat.cross v x))) := by277 rw [Quat.pure_eq hv, Quat.pure_eq hx]278 exact QR.sound (look [v.b, v.c, v.d, x.b, x.c, x.d])279 (QR.conjBy (QR.pv 0) (QR.pv 3))280 (QR.add (QR.smul (QR.nrm (QR.pv 0)) (QR.pv 3)) (QR.add (QR.cross (QR.pv 0) (QR.cross (QR.pv 0) (QR.pv 3))) (QR.cross (QR.pv 0) (QR.cross (QR.pv 0) (QR.pv 3))))) (by decide +kernel)281282/-- 1:E7, the key identity of uniqueness: with `w = a z − v × z`, `a (a² + N(v)) z = a² w + a (v × w) + (v · w) v`. -/283
theorem cayley_key (a : Shell p) (v z : Quat p) (hv : v.a = 0) (hz : z.a = 0) :284 Quat.smul (a * (a * a + Quat.dot v v)) z =285 Quat.add (Quat.add (Quat.smul (a * a) (Quat.add (Quat.smul a z) (Quat.neg (Quat.cross v z))))286 (Quat.smul a (Quat.cross v (Quat.add (Quat.smul a z) (Quat.neg (Quat.cross v z))))))287 (Quat.smul (Quat.dot v (Quat.add (Quat.smul a z) (Quat.neg (Quat.cross v z)))) v) := by288 rw [Quat.pure_eq hv, Quat.pure_eq hz]289 exact QR.sound (look [a, v.b, v.c, v.d, z.b, z.c, z.d])290 (QR.smul (.mul (.var 0) (.add (.mul (.var 0) (.var 0)) (QR.dot (QR.pv 1) (QR.pv 1)))) (QR.pv 4))291 (QR.add (QR.add (QR.smul (.mul (.var 0) (.var 0)) (QR.add (QR.smul (.var 0) (QR.pv 4)) (QR.neg (QR.cross (QR.pv 1) (QR.pv 4)))))292 (QR.smul (.var 0) (QR.cross (QR.pv 1) (QR.add (QR.smul (.var 0) (QR.pv 4)) (QR.neg (QR.cross (QR.pv 1) (QR.pv 4)))))))293 (QR.smul (QR.dot (QR.pv 1) (QR.add (QR.smul (.var 0) (QR.pv 4)) (QR.neg (QR.cross (QR.pv 1) (QR.pv 4))))) (QR.pv 1))) (by decide +kernel)294295
theorem add_neg_q (q : Quat p) : Quat.add q (Quat.neg q) = ⟨0, 0, 0, 0⟩ :=296 QR.sound (look [q.a, q.b, q.c, q.d]) (QR.add (QR.v 0) (QR.neg (QR.v 0))) ⟨.zero, .zero, .zero, .zero⟩ (by decide +kernel)297298
theorem key_zero (a : Shell p) (v : Quat p) :299 Quat.add (Quat.add (Quat.smul (a * a) ⟨0, 0, 0, 0⟩) (Quat.smul a (Quat.cross v ⟨0, 0, 0, 0⟩)))300 (Quat.smul (Quat.dot v ⟨0, 0, 0, 0⟩) v) = ⟨0, 0, 0, 0⟩ :=301 QR.sound (look [a, v.a, v.b, v.c, v.d])302 (QR.add (QR.add (QR.smul (.mul (.var 0) (.var 0)) ⟨.zero, .zero, .zero, .zero⟩) (QR.smul (.var 0) (QR.cross (QR.v 1) ⟨.zero, .zero, .zero, .zero⟩)))303 (QR.smul (QR.dot (QR.v 1) ⟨.zero, .zero, .zero, .zero⟩) (QR.v 1))) ⟨.zero, .zero, .zero, .zero⟩ (by decide +kernel)304305/-- 1:E7, `aI − S_v` is injective on pure quaternions when `a ≠ 0` and `a² + N(v) ≠ 0` (a field shell). -/306
theorem cayley_inj {κ : Nat} {g : Shell p} (F : Frame p κ g) {a : Shell p} {v z : Quat p} (hv : v.a = 0) (hz : z.a = 0)307 (ha : a ≠ 0) (hn : a * a + Quat.dot v v ≠ 0) (h : Quat.smul a z = Quat.cross v z) : z = ⟨0, 0, 0, 0⟩ := by308 have hw : Quat.add (Quat.smul a z) (Quat.neg (Quat.cross v z)) = ⟨0, 0, 0, 0⟩ := by rw [h]; exact add_neg_q _309 have key := cayley_key a v z hv hz310 rw [hw, key_zero] at key311 have hc : a * (a * a + Quat.dot v v) ≠ 0 := fun e =>312 match F.mul_eq_zero e with313 | .inl e1 => ha e1314 | .inr e2 => hn e2315 have comp : ∀ t : Shell p, a * (a * a + Quat.dot v v) * t = 0 → t = 0 := fun t e =>316 match F.mul_eq_zero e with317 | .inl e1 => absurd e1 hc318 | .inr e2 => e2319 exact Quat.ext4 hz (comp _ (congrArg Quat.b key)) (comp _ (congrArg Quat.c key)) (comp _ (congrArg Quat.d key))320321/-! ## 1:E8 — the Lie-algebra layer, two axes and range -/322323/-- 1:E8, the product of two Gibbs quaternions: `(1 + u)(1 + w) = (1 − u·w) + (u + w + u × w)` for pure `u`, `w`. -/324
theorem one_add_mul (u w : Quat p) (hu : u.a = 0) (hw : w.a = 0) :325 Quat.mul (Quat.add (Quat.sc 1) u) (Quat.add (Quat.sc 1) w) =326 Quat.add (Quat.sc (1 + -(Quat.dot u w))) (Quat.add (Quat.add u w) (Quat.cross u w)) := by327 rw [Quat.pure_eq hu, Quat.pure_eq hw]328 exact QR.sound (look [u.b, u.c, u.d, w.b, w.c, w.d])329 (QR.mul (QR.add (QR.sc .one) (QR.pv 0)) (QR.add (QR.sc .one) (QR.pv 3)))330 (QR.add (QR.sc (.add .one (.neg (QR.dot (QR.pv 0) (QR.pv 3))))) (QR.add (QR.add (QR.pv 0) (QR.pv 3)) (QR.cross (QR.pv 0) (QR.pv 3)))) (by decide +kernel)331332/-- 1:E8, the bracket: `uw − wu = 2 u × w` for pure `u`, `w`. -/333
theorem bracket (u w : Quat p) (hu : u.a = 0) (hw : w.a = 0) :334 Quat.add (Quat.mul u w) (Quat.neg (Quat.mul w u)) = Quat.add (Quat.cross u w) (Quat.cross u w) := by335 rw [Quat.pure_eq hu, Quat.pure_eq hw]336 exact QR.sound (look [u.b, u.c, u.d, w.b, w.c, w.d])337 (QR.add (QR.mul (QR.pv 0) (QR.pv 3)) (QR.neg (QR.mul (QR.pv 3) (QR.pv 0)))) (QR.add (QR.cross (QR.pv 0) (QR.pv 3)) (QR.cross (QR.pv 0) (QR.pv 3))) (by decide +kernel)338339/-- 1:E8, conjugation is multiplicative: `(qr) x (qr)‾ = q (r x r̄) q̄`. -/340
theorem rot_mul (q r x : Quat p) : Quat.conjBy (Quat.mul q r) x = Quat.conjBy q (Quat.conjBy r x) :=341 QR.sound (look [q.a, q.b, q.c, q.d, r.a, r.b, r.c, r.d, x.a, x.b, x.c, x.d]) (QR.conjBy (QR.mul (QR.v 0) (QR.v 4)) (QR.v 8))342 (QR.conjBy (QR.v 0) (QR.conjBy (QR.v 4) (QR.v 8))) (by decide +kernel)343344/-- 1:E8, scaling: `(sq) x (sq)‾ = s² q x q̄` and `N(sq) = s² N(q)`, so the rotation of `q` depends on `q` up to a scalar. -/345
theorem rot_smul (s : Shell p) (q x : Quat p) :346 Quat.conjBy (Quat.smul s q) x = Quat.smul (s * s) (Quat.conjBy q x) ∧ Quat.nrm (Quat.smul s q) = s * s * Quat.nrm q :=347 ⟨QR.sound (look [s, q.a, q.b, q.c, q.d, x.a, x.b, x.c, x.d]) (QR.conjBy (QR.smul (.var 0) (QR.v 1)) (QR.v 5))348 (QR.smul (.mul (.var 0) (.var 0)) (QR.conjBy (QR.v 1) (QR.v 5))) (by decide +kernel),349 RE.sound (look [s, q.a, q.b, q.c, q.d]) (QR.nrm (QR.smul (.var 0) (QR.v 1))) (.mul (.mul (.var 0) (.var 0)) (QR.nrm (QR.v 1))) (by decide +kernel)⟩350351/-- 1:E8, the half-turn case: at `u · w = 1` the product `(1 + u)(1 + w)` is the pure quaternion `u + w + u × w`. -/352
theorem one_add_mul_half (u w : Quat p) (hu : u.a = 0) (hw : w.a = 0) (h1 : Quat.dot u w = 1) :353 Quat.mul (Quat.add (Quat.sc 1) u) (Quat.add (Quat.sc 1) w) = Quat.add (Quat.sc 0) (Quat.add (Quat.add u w) (Quat.cross u w)) := by354 rw [one_add_mul u w hu hw, h1, add_neg]355356/-- 1:E7, the sign: `ρ_{−q} = ρ_q` (`(−q) x (−q)‾ = q x q̄`, `N(−q) = N(q)`); the window rotations of an axis come in357pairs `±(a, t)`, which bounds them by `2H² + 2H` (`FRC.Algebra.card_image_le_of_neg`). -/358
theorem rot_neg (q x : Quat p) : Quat.conjBy (Quat.neg q) x = Quat.conjBy q x ∧ Quat.nrm (Quat.neg q) = Quat.nrm q :=359 ⟨QR.sound (look [q.a, q.b, q.c, q.d, x.a, x.b, x.c, x.d]) (QR.conjBy (QR.neg (QR.v 0)) (QR.v 4)) (QR.conjBy (QR.v 0) (QR.v 4)) (by decide +kernel),360 RE.sound (look [q.a, q.b, q.c, q.d]) (QR.nrm (QR.neg (QR.v 0))) (QR.nrm (QR.v 0)) (by decide +kernel)⟩361362
theorem smul_sc_add (s s' : Shell p) (m : Quat p) :363 Quat.smul s (Quat.add (Quat.sc 1) (Quat.smul s' m)) = Quat.add (Quat.sc s) (Quat.smul (s * s') m) :=364 QR.sound (look [s, s', m.a, m.b, m.c, m.d]) (QR.smul (.var 0) (QR.add (QR.sc .one) (QR.smul (.var 1) (QR.v 2))))365 (QR.add (QR.sc (.var 0)) (QR.smul (.mul (.var 0) (.var 1)) (QR.v 2))) (by decide +kernel)366367
theorem smul_one_q (m : Quat p) : Quat.smul 1 m = m :=368 QR.sound (look [m.a, m.b, m.c, m.d]) (QR.smul .one (QR.v 0)) (QR.v 0) (by decide +kernel)369370
theorem smul_smul_q (s t : Shell p) (m : Quat p) : Quat.smul s (Quat.smul t m) = Quat.smul (s * t) m :=371 QR.sound (look [s, t, m.a, m.b, m.c, m.d]) (QR.smul (.var 0) (QR.smul (.var 1) (QR.v 2))) (QR.smul (.mul (.var 0) (.var 1)) (QR.v 2)) (by decide +kernel)372373
theorem conjBy_smul (q y : Quat p) (t : Shell p) : Quat.conjBy q (Quat.smul t y) = Quat.smul t (Quat.conjBy q y) :=374 QR.sound (look [q.a, q.b, q.c, q.d, t, y.a, y.b, y.c, y.d]) (QR.conjBy (QR.v 0) (QR.smul (.var 4) (QR.v 5)))375 (QR.smul (.var 4) (QR.conjBy (QR.v 0) (QR.v 5))) (by decide +kernel)376377
theorem inv_chain (nu nw s nc Nu Nw Nc : Shell p) (hu : Nu * nu = 1) (hw : Nw * nw = 1) (hc : Nc * nc = 1)378 (hN : Nu * Nw = s * s * Nc) : nu * nw * (s * s) = nc := by379 have e1 : nu * nw * (s * s) = nc * (nu * nw * (s * s * Nc)) := by380 calc nu * nw * (s * s) = nu * nw * (s * s) * (Nc * nc) := by rw [hc, mul_one]381 _ = nc * (nu * nw * (s * s * Nc)) :=382 RE.sound (look [nu, nw, s, nc, Nc])383 (.mul (.mul (.mul (.var 0) (.var 1)) (.mul (.var 2) (.var 2))) (.mul (.var 4) (.var 3)))384 (.mul (.var 3) (.mul (.mul (.var 0) (.var 1)) (.mul (.mul (.var 2) (.var 2)) (.var 4)))) (by decide +kernel)385 have e2 : nu * nw * (Nu * Nw) = (Nu * nu) * (Nw * nw) :=386 RE.sound (look [nu, nw, Nu, Nw]) (.mul (.mul (.var 0) (.var 1)) (.mul (.var 2) (.var 3)))387 (.mul (.mul (.var 2) (.var 0)) (.mul (.var 3) (.var 1))) (by decide +kernel)388 rw [e1, ← hN, e2, hu, hw, mul_one, mul_one]389390/-- 1:E8, the composition law: for pure `u`, `w` with `1 + N(u)`, `1 + N(w)`, `1 − u·w` and `1 + N(u∘w)` invertible391(inverses `nu`, `nw`, `s'`, `nc`), `ρ_{1+u} ρ_{1+w} = ρ_{1+u∘w}` with `u∘w = (u + w + u × w)/(1 − u·w)`; here392`ρ_q x = N(q)⁻¹ q x q̄`. -/393
theorem compose (u w x : Quat p) (hu : u.a = 0) (hw : w.a = 0) (s' nu nw nc : Shell p)394 (hs : (1 + -(Quat.dot u w)) * s' = 1)395 (hnu : Quat.nrm (Quat.add (Quat.sc 1) u) * nu = 1) (hnw : Quat.nrm (Quat.add (Quat.sc 1) w) * nw = 1)396 (hnc : Quat.nrm (Quat.add (Quat.sc 1) (Quat.smul s' (Quat.add (Quat.add u w) (Quat.cross u w)))) * nc = 1) :397 Quat.smul nu (Quat.conjBy (Quat.add (Quat.sc 1) u) (Quat.smul nw (Quat.conjBy (Quat.add (Quat.sc 1) w) x))) =398 Quat.smul nc (Quat.conjBy (Quat.add (Quat.sc 1) (Quat.smul s' (Quat.add (Quat.add u w) (Quat.cross u w)))) x) := by399 have hP : Quat.mul (Quat.add (Quat.sc 1) u) (Quat.add (Quat.sc 1) w) =400 Quat.smul (1 + -(Quat.dot u w)) (Quat.add (Quat.sc 1) (Quat.smul s' (Quat.add (Quat.add u w) (Quat.cross u w)))) := by401 rw [smul_sc_add, hs, smul_one_q, one_add_mul u w hu hw]402 have hN : Quat.nrm (Quat.add (Quat.sc 1) u) * Quat.nrm (Quat.add (Quat.sc 1) w) =403 (1 + -(Quat.dot u w)) * (1 + -(Quat.dot u w)) *404 Quat.nrm (Quat.add (Quat.sc 1) (Quat.smul s' (Quat.add (Quat.add u w) (Quat.cross u w)))) := by405 rw [← nrm_mul, hP, (rot_smul _ _ x).2]406 rw [conjBy_smul, smul_smul_q, ← rot_mul, hP, (rot_smul _ _ x).1, smul_smul_q, inv_chain nu nw _ nc _ _ _ hnu hnw hnc hN]407408
theorem add_cancel_q {r m : Quat p} (h : Quat.add r m = r) : m = ⟨0, 0, 0, 0⟩ := by409 have c : ∀ x y : Shell p, x + y = x → y = 0 := fun x y e => add_right_cancel (c := x) (by rw [add_comm, e, zero_add])410 exact Quat.ext4 (c _ _ (congrArg Quat.a h)) (c _ _ (congrArg Quat.b h)) (c _ _ (congrArg Quat.c h)) (c _ _ (congrArg Quat.d h))411412
theorem cayley_trivial_id (q x : Quat p) (hx : x.a = 0) :413 Quat.add (Quat.add (Quat.smul q.a (Quat.smul (Quat.nrm q) x)) (Quat.neg (Quat.cross (Quat.vec q) (Quat.smul (Quat.nrm q) x))))414 (Quat.smul (1 + 1) (Quat.smul (Quat.nrm q) (Quat.cross (Quat.vec q) x))) =415 Quat.smul (Quat.nrm q) (Quat.add (Quat.smul q.a x) (Quat.cross (Quat.vec q) x)) := by416 rw [Quat.pure_eq hx]417 exact QR.sound (look [q.a, q.b, q.c, q.d, x.b, x.c, x.d])418 (QR.add (QR.add (QR.smul (.var 0) (QR.smul (QR.nrm (QR.v 0)) (QR.pv 4))) (QR.neg (QR.cross (QR.vec (QR.v 0)) (QR.smul (QR.nrm (QR.v 0)) (QR.pv 4)))))419 (QR.smul (.add .one .one) (QR.smul (QR.nrm (QR.v 0)) (QR.cross (QR.vec (QR.v 0)) (QR.pv 4)))))420 (QR.smul (QR.nrm (QR.v 0)) (QR.add (QR.smul (.var 0) (QR.pv 4)) (QR.cross (QR.vec (QR.v 0)) (QR.pv 4)))) (by decide +kernel)421422/-- 1:E7, the kernel: on a field shell, a rotation `ρ_q` (`N(q) ≠ 0`) that fixes every pure quaternion has `q` a423scalar — so `a + t v ↦ ρ_{a+tv}` is injective on the pairs modulo the scalars, and the axis group of424`FRC.Algebra.axis_group` is the rotation group of the axis. -/425
theorem rot_trivial {κ : Nat} {g : Shell p} (F : Frame p κ g) (q : Quat p) (hN : Quat.nrm q ≠ 0)426 (h : ∀ x : Quat p, x.a = 0 → Quat.conjBy q x = Quat.smul (Quat.nrm q) x) : q.b = 0 ∧ q.c = 0 ∧ q.d = 0 := by427 have key : ∀ x : Quat p, x.a = 0 → Quat.smul (1 + 1) (Quat.smul (Quat.nrm q) (Quat.cross (Quat.vec q) x)) = ⟨0, 0, 0, 0⟩ := by428 intro x hx429 have E := rot_cayley q x hx430 rw [h x hx] at E431 have I := cayley_trivial_id q x hx432 rw [← E] at I433 exact add_cancel_q I434 have h2 : (1 + 1 : Shell p) ≠ 0 := by rw [← two_eq_one_add_one]; exact F.two_ne_zero435 have z : ∀ t : Shell p, (1 + 1) * (Quat.nrm q * t) = 0 → t = 0 := fun t e =>436 match F.mul_eq_zero e with437 | .inl e1 => absurd e1 h2438 | .inr e2 => match F.mul_eq_zero e2 with439 | .inl e3 => absurd e3 hN440 | .inr e4 => e4441 have kb := key ⟨0, 1, 0, 0⟩ rfl442 have kc := key ⟨0, 0, 1, 0⟩ rfl443 have hd : q.d = 0 := z _ (by444 have := congrArg Quat.c kb445 simp only [Quat.smul, Quat.cross, Quat.vec] at this446 rw [mul_one, mul_zero, neg_zero, add_zero] at this; exact this)447 have hcneg : -q.c = 0 := z _ (by448 have := congrArg Quat.d kb449 simp only [Quat.smul, Quat.cross, Quat.vec] at this450 rw [mul_zero, mul_one] at this451 rw [zero_add] at this; exact this)452 have hb : q.b = 0 := z _ (by453 have := congrArg Quat.d kc454 simp only [Quat.smul, Quat.cross, Quat.vec] at this455 rw [mul_one, mul_zero, neg_zero, add_zero] at this; exact this)456 refine ⟨hb, ?_, hd⟩457 rw [← neg_neg q.c, hcneg, neg_zero]458459end Frame460end Shell461end FRC462463namespace FRC.Algebra464-- Ledger predicates of 1-algebra (generated by make_predicates.py from docs/1-algebra/1-algebra-ledger.json; edit the ledger, not this section)465set_option linter.defProp false in466/-- 1:E6 (p01030) — Continuous symmetry, the non-abelian case resolved by the window: the framed quaternions $W_H^{4}$, read in a shell $\p>8H^{2}$, compose exactly (products land in $W_{4H^{2}}$); normalised, they are an $\varepsilon$-net of $SO(3)$ with $\varepsilon\le2\arcsin(1/H)$ (round $Hs$ to the lattice). At $H=3$, $\p=73$: $38.9^\circ<\varepsilon_0$, finer than any finite subgroup; measured $30.0^\circ$. -/467
def p01030 := And.intro @FRC.Shell.Frame.quaternion_window (@FRC.Shell.Frame.read_mul)468/-- 1:E7 (p01032) — The Lie-algebra layer, one axis: on a shell $\p>8H^{2}$, for $q=a+v\in W_H^{4}$ with $v\ne0$, the rotation $\rho_q\colon x\mapsto qxq^{-1}$ is the Cayley step (8:C3) of the self-adjoint $\eta S_v$ (E2's $\eta$, $S_vx=v\times x$, $N(v)=v\cdot v$) at $\alpha=\eta/(\nu a)$, and the half-turn $U_\infty=I+2N(v)^{-1}S_v^{2}$ at $a=0$. With $U_\infty$ these steps form a cyclic group of order $\p-\bigl(\tfrac{N(v)}{\p}\bigr)$ containing every iterate; at most $2H^{2}+2H$ of its elements are window rotations. -/469
theorem p01032 : (∀ {p : Nat} [FRC.Pos p] (q x : FRC.Shell.Frame.Quat p), x.a = (0 : FRC.Shell p) → (FRC.Shell.Frame.Quat.smul q.a (q.conjBy x)).add (q.vec.cross (q.conjBy x)).neg = FRC.Shell.Frame.Quat.smul q.nrm ((FRC.Shell.Frame.Quat.smul q.a x).add (q.vec.cross x))) ∧ (∀ {p : Nat} [FRC.Pos p] {κ : Nat} {g : FRC.Shell p}, FRC.Shell.Frame p κ g → ∀ {a : FRC.Shell p} {v z : FRC.Shell.Frame.Quat p}, v.a = (0 : FRC.Shell p) → z.a = (0 : FRC.Shell p) → a ≠ (0 : FRC.Shell p) → a * a + v.dot v ≠ (0 : FRC.Shell p) → FRC.Shell.Frame.Quat.smul a z = v.cross z → z = { a := (0 : FRC.Shell p), b := (0 : FRC.Shell p), c := (0 : FRC.Shell p), d := (0 : FRC.Shell p) }) ∧ (∀ {p : Nat} [FRC.Pos p] (v x : FRC.Shell.Frame.Quat p), v.a = (0 : FRC.Shell p) → x.a = (0 : FRC.Shell p) → v.conjBy x = (FRC.Shell.Frame.Quat.smul v.nrm x).add ((v.cross (v.cross x)).add (v.cross (v.cross x)))) ∧ (∀ {p : Nat} [FRC.Pos p] {κ : Nat} {g : FRC.Shell p}, FRC.Shell.Frame p κ g → ∀ (q : FRC.Shell.Frame.Quat p), q.nrm ≠ (0 : FRC.Shell p) → (∀ (x : FRC.Shell.Frame.Quat p), x.a = (0 : FRC.Shell p) → q.conjBy x = FRC.Shell.Frame.Quat.smul q.nrm x) → q.b = (0 : FRC.Shell p) ∧ q.c = (0 : FRC.Shell p) ∧ q.d = (0 : FRC.Shell p)) ∧ ∀ {p : Nat} [FRC.Pos p] (q x : FRC.Shell.Frame.Quat p), q.neg.conjBy x = q.conjBy x ∧ q.neg.nrm = q.nrm :=470 And.intro @FRC.Shell.Frame.rot_cayley (And.intro @FRC.Shell.Frame.cayley_inj (And.intro @FRC.Shell.Frame.half_turn (And.intro @FRC.Shell.Frame.rot_trivial (@FRC.Shell.Frame.rot_neg))))471/-- 1:E8 (p01033) — The Lie-algebra layer, two axes and range: for pure quaternions $u,w$ with $1+N(u)$, $1+N(w)$ and $1-u\cdot w$ nonzero, $\rho_{1+u}\rho_{1+w}=\rho_{1+u\circ w}$ with $u\circ w=(u+w+u\times w)/(1-u\cdot w)$, the bracket being $[u,w]=2u\times w$; at $u\cdot w=1$ the product is the half-turn about $u+w+u\times w$. The entries of $q^{m}$, $q\in W_H^{4}$, are at most $(2H)^{m}$, and $q^{m}$ reads back from the shell iff $2\|q^{m}\|_\infty<\p$ (D2). -/472
theorem p01033 : (∀ {p : Nat} [FRC.Pos p] (u w x : FRC.Shell.Frame.Quat p), u.a = (0 : FRC.Shell p) → w.a = (0 : FRC.Shell p) → ∀ (s' nu nw nc : FRC.Shell p), ((1 : FRC.Shell p) + -u.dot w) * s' = (1 : FRC.Shell p) → ((FRC.Shell.Frame.Quat.sc (1 : FRC.Shell p)).add u).nrm * nu = (1 : FRC.Shell p) → ((FRC.Shell.Frame.Quat.sc (1 : FRC.Shell p)).add w).nrm * nw = (1 : FRC.Shell p) → ((FRC.Shell.Frame.Quat.sc (1 : FRC.Shell p)).add (FRC.Shell.Frame.Quat.smul s' ((u.add w).add (u.cross w)))).nrm * nc = (1 : FRC.Shell p) → FRC.Shell.Frame.Quat.smul nu (((FRC.Shell.Frame.Quat.sc (1 : FRC.Shell p)).add u).conjBy (FRC.Shell.Frame.Quat.smul nw (((FRC.Shell.Frame.Quat.sc (1 : FRC.Shell p)).add w).conjBy x))) = FRC.Shell.Frame.Quat.smul nc (((FRC.Shell.Frame.Quat.sc (1 : FRC.Shell p)).add (FRC.Shell.Frame.Quat.smul s' ((u.add w).add (u.cross w)))).conjBy x)) ∧ (∀ {p : Nat} [FRC.Pos p] (u w : FRC.Shell.Frame.Quat p), u.a = (0 : FRC.Shell p) → w.a = (0 : FRC.Shell p) → ((FRC.Shell.Frame.Quat.sc (1 : FRC.Shell p)).add u).mul ((FRC.Shell.Frame.Quat.sc (1 : FRC.Shell p)).add w) = (FRC.Shell.Frame.Quat.sc ((1 : FRC.Shell p) + -u.dot w)).add ((u.add w).add (u.cross w))) ∧ (∀ {p : Nat} [FRC.Pos p] (u w : FRC.Shell.Frame.Quat p), u.a = (0 : FRC.Shell p) → w.a = (0 : FRC.Shell p) → u.dot w = (1 : FRC.Shell p) → ((FRC.Shell.Frame.Quat.sc (1 : FRC.Shell p)).add u).mul ((FRC.Shell.Frame.Quat.sc (1 : FRC.Shell p)).add w) = (FRC.Shell.Frame.Quat.sc (0 : FRC.Shell p)).add ((u.add w).add (u.cross w))) ∧ (∀ {p : Nat} [FRC.Pos p] (u w : FRC.Shell.Frame.Quat p), u.a = (0 : FRC.Shell p) → w.a = (0 : FRC.Shell p) → (u.mul w).add (w.mul u).neg = (u.cross w).add (u.cross w)) ∧ (∀ {p : Nat} [FRC.Pos p] (q r x : FRC.Shell.Frame.Quat p), (q.mul r).conjBy x = q.conjBy (r.conjBy x)) ∧ ∀ {p : Nat} [FRC.Pos p] (q r : FRC.Shell.Frame.Quat p), (q.mul r).nrm = q.nrm * r.nrm :=473 And.intro @FRC.Shell.Frame.compose (And.intro @FRC.Shell.Frame.one_add_mul (And.intro @FRC.Shell.Frame.one_add_mul_half (And.intro @FRC.Shell.Frame.bracket (And.intro @FRC.Shell.Frame.rot_mul (@FRC.Shell.Frame.nrm_mul)))))474-- end ledger predicates475end FRC.Algebra476

