kernel-Nat.totient_mul_of_coprime
- Kind
- kernel-term
- Status
- checked
Supports: totient(m*n) = totient(m)*totient(n) under gcd(m,n) = 1, with the whole rendered type pinned.
test "$(cargo run -q -p axeyum-lean-kernel --example nat_theorem_inventory -- totient_mul_of_coprime 2>/dev/null | tr '\t' ' ' | grep -Fc 'Nat.totient_mul_of_coprime 3 ((x0 : AxNat) -> ((x1 : AxNat) -> ((x2 : Eq.{1} AxNat (AxNat.gcd x0 x1) (AxNat.succ AxNat.zero)) -> Eq.{1} AxNat (AxNat.totient (AxNat.mul x0 x1)) (AxNat.mul (AxNat.totient x0) (AxNat.totient x1)))))')" -ge 1 Evidence notes
The grep pins the WHOLE rendered type, not the name. That matters here in a specific way: the kernel re-derives the type from the proof term and so refuses a FALSE theorem, but it cannot notice a statement that is weaker or transposed, and this one has two such neighbours that both type-check. Weakening the hypothesis from `Eq (gcd x0 x1) 1` to anything satisfiable-by-more-pairs would make the theorem unsound and is pinned by quoting the hypothesis verbatim; transposing the conclusion to `mul (totient x1) (totient x0)` is a genuinely different theorem (the Rust test asserts `!def_eq` between the two at free variables) and is pinned by quoting the factor order. `nat_theorem_inventory` exits non-zero for a name that does not exist, and `grep -Fc` consumes the whole pipe with the count then tested, rather than `grep -q`, which would SIGPIPE the producer under pipefail. Measured 2026-08-30: `nat_theorem_inventory` consumes only ONE name argument -- given two names in either order it reports on the LAST one only -- so exactly one is passed here.