Paper IV · Lean source
AlgebraicCompletion.lean
Selected results recorded Coverage and evidence
Compiler/replay evidence is reported for a subset or bounded block. No whole-work coverage is implied.
This viewer reads the retained source; it does not run Lean or assign new claim mappings.
Local imports (1)
KomorebiPaperIV/AlgebraicCompletion.lean458 lines
Original source path
Paper_IV_Verification_Closeout_v1.1.0/formalization/lean/KomorebiPaperIV/AlgebraicCompletion.leanSkip declarations and read code
1 /-
2 Copyright (c) 2026 Komorebi P. All rights reserved.
3 Authors: Komorebi P.
4 -/
5
6 import KomorebiPaperIV.Appell
7 import Mathlib.Data.Nat.Choose.Cast
8 import Mathlib.Algebra.Polynomial.BigOperators
9 import Mathlib.Algebra.Polynomial.Degree.IsMonicOfDegree
10 import Mathlib.Algebra.Polynomial.HasseDeriv
11 import Mathlib.RingTheory.PowerSeries.Expand
12 import Mathlib.Algebra.Polynomial.Div
13
14 /-!
15 # Algebraic completion for Paper IV
16
17 This file records branch-free algebraic statements from Paper IV that were not
18 part of the initial checkpoint. In particular, it proves the exact
19 factorial-rescaled triangular inverse system used for the normalized residue
20 sections.
21 -/
22
23 namespace Komorebi.PaperIV
24
25 open scoped PowerSeries
26
27 noncomputable section
28
29 section ResidueInverse
30
31 variable {K : Type*} [Field K] [CharZero K]
32
33 /-- The reduced normalized residue section
34 `j! * sum_n X^n / (N n + j)!`. -/
35 def normalizedResidueSection (N j : ℕ) : K⟦X⟧ :=
36 PowerSeries.mk fun n =>
37 (j.factorial : K) / ((N * n + j).factorial : K)
38
39 omit [CharZero K] in
40 @[simp]
41 theorem coeff_normalizedResidueSection (N j n : ℕ) :
42 PowerSeries.coeff n (normalizedResidueSection (K := K) N j) =
43 (j.factorial : K) / ((N * n + j).factorial : K) := by
44 simp [normalizedResidueSection]
45
46 @[simp]
47 theorem constantCoeff_normalizedResidueSection (N j : ℕ) :
48 (normalizedResidueSection (K := K) N j).constantCoeff = 1 := by
49 rw [← PowerSeries.coeff_zero_eq_constantCoeff]
50 rw [coeff_normalizedResidueSection]
51 have hj : (j.factorial : K) ≠ 0 := by
52 exact_mod_cast j.factorial_pos.ne'
53 simpa using div_self hj
54
55 /-- Paper IV's coefficient `C_{N,j}(n)`, including its `(N n)!` scaling. -/
56 def residueInverseCoeff (N j n : ℕ) : K :=
57 ((N * n).factorial : K) *
58 PowerSeries.coeff n (normalizedResidueSection (K := K) N j)⁻¹
59
60 /-- The exact factorial-rescaled triangular inverse identity of Theorem 9.2. -/
61 theorem residueInverseCoeff_triangular (N j n : ℕ) :
62 (∑ q ∈ Finset.range (n + 1),
63 ((N * n + j).choose (N * q) : K) *
64 residueInverseCoeff (K := K) N j q) =
65 if n = 0 then 1 else 0 := by
66 let D : K⟦X⟧ := normalizedResidueSection (K := K) N j
67 have hD : D.constantCoeff = 1 := by
68 simp [D]
69 have hunit : D.constantCoeff ≠ 0 := by simp [hD]
70 have hinv : D⁻¹ * D = 1 := by
71 rw [mul_comm]
72 exact PowerSeries.mul_inv_cancel D hunit
73 have hcoeff := congrArg (PowerSeries.coeff (R := K) n) hinv
74 rw [PowerSeries.coeff_mul,
75 Finset.Nat.sum_antidiagonal_eq_sum_range_succ_mk] at hcoeff
76 simp only [PowerSeries.coeff_one] at hcoeff
77 let scale : K := ((N * n + j).factorial : K) / (j.factorial : K)
78 have hterm (q : ℕ) (hq : q ∈ Finset.range (n + 1)) :
79 scale *
80 (PowerSeries.coeff q D⁻¹ * PowerSeries.coeff (n - q) D) =
81 ((N * n + j).choose (N * q) : K) *
82 residueInverseCoeff (K := K) N j q := by
83 have hqn : q ≤ n := Nat.le_of_lt_succ (Finset.mem_range.mp hq)
84 have hmul : N * q ≤ N * n := Nat.mul_le_mul_left N hqn
85 have hle : N * q ≤ N * n + j := hmul.trans (Nat.le_add_right _ _)
86 have hsplit : N * q + N * (n - q) = N * n := by
87 rw [← Nat.mul_add, Nat.add_sub_of_le hqn]
88 have hsub : N * n + j - N * q = N * (n - q) + j := by omega
89 have hfacj : (j.factorial : K) ≠ 0 := by
90 exact_mod_cast j.factorial_pos.ne'
91 have hfacq : ((N * q).factorial : K) ≠ 0 := by
92 exact_mod_cast (N * q).factorial_pos.ne'
93 have hfacrest : ((N * (n - q) + j).factorial : K) ≠ 0 := by
94 exact_mod_cast (N * (n - q) + j).factorial_pos.ne'
95 rw [show PowerSeries.coeff (n - q) D =
96 (j.factorial : K) / ((N * (n - q) + j).factorial : K) by
97 simp [D]]
98 rw [residueInverseCoeff]
99 rw [Nat.cast_choose K hle, hsub]
100 dsimp [scale]
101 field_simp
102 ring
103 calc
104 (∑ q ∈ Finset.range (n + 1),
105 ((N * n + j).choose (N * q) : K) *
106 residueInverseCoeff (K := K) N j q) =
107 ∑ q ∈ Finset.range (n + 1),
108 scale * (PowerSeries.coeff q D⁻¹ * PowerSeries.coeff (n - q) D) := by
109 apply Finset.sum_congr rfl
110 intro q hq
111 exact (hterm q hq).symm
112 _ = scale *
113 ∑ q ∈ Finset.range (n + 1),
114 PowerSeries.coeff q D⁻¹ * PowerSeries.coeff (n - q) D := by
115 rw [Finset.mul_sum]
116 _ = scale * (if n = 0 then 1 else 0) := by rw [hcoeff]
117 _ = if n = 0 then 1 else 0 := by
118 by_cases hn : n = 0
119 · subst n
120 have hj : (j.factorial : K) ≠ 0 := by
121 exact_mod_cast j.factorial_pos.ne'
122 simp [scale, hj]
123 · simp [hn]
124
125 @[simp]
126 theorem residueInverseCoeff_zero (N j : ℕ) :
127 residueInverseCoeff (K := K) N j 0 = 1 := by
128 simpa using residueInverseCoeff_triangular (K := K) N j 0
129
130 /-- The solved triangular recurrence displayed in Theorem 9.2. -/
131 theorem residueInverseCoeff_recurrence (N j n : ℕ) (hn : 0 < n) :
132 residueInverseCoeff (K := K) N j n =
133 -(∑ q ∈ Finset.range n,
134 ((N * n + j).choose (N * q) : K) *
135 residueInverseCoeff (K := K) N j q) /
136 ((N * n + j).choose (N * n) : K) := by
137 have hsum := residueInverseCoeff_triangular (K := K) N j n
138 have hn0 : n ≠ 0 := Nat.ne_of_gt hn
139 simp only [hn0, ↓reduceIte] at hsum
140 rw [Finset.sum_range_succ] at hsum
141 have hle : N * n ≤ N * n + j := by omega
142 have hden : ((N * n + j).choose (N * n) : K) ≠ 0 := by
143 exact_mod_cast (Nat.choose_pos hle).ne'
144 apply (eq_div_iff hden).2
145 linear_combination hsum
146
147 end ResidueInverse
148
149 section SparseAppell
150
151 variable {R : Type*} [CommRing R]
152
153 /-- Inflate block coefficients to the full EGF index set, putting zero away
154 from indices divisible by `N`. -/
155 def blockCoefficientSequence (N : ℕ) (c : ℕ → R) (q : ℕ) : R :=
156 if N ∣ q then c (q / N) else 0
157
158 @[simp]
159 theorem blockCoefficientSequence_mul (N : ℕ) (hN : 0 < N)
160 (c : ℕ → R) (n : ℕ) :
161 blockCoefficientSequence N c (N * n) = c n := by
162 simp [blockCoefficientSequence, Nat.mul_div_cancel_left n hN]
163
164 /-- A sparse Appell polynomial contains only the coefficient indices in the
165 specified congruence block. -/
166 theorem appellPolynomial_eq_sparse_sum (N m : ℕ) (c : ℕ → R) :
167 appellPolynomial (blockCoefficientSequence N c) m =
168 ∑ q ∈ (Finset.range (m + 1)).filter (fun q => N ∣ q),
169 Polynomial.C
170 ((m.choose q : R) * blockCoefficientSequence N c q) *
171 Polynomial.X ^ (m - q) := by
172 rw [appellPolynomial]
173 symm
174 refine Finset.sum_subset (Finset.filter_subset _ _) ?_
175 intro q hq hqfilter
176 have hnot : ¬N ∣ q := by
177 intro hdiv
178 apply hqfilter
179 exact Finset.mem_filter.mpr ⟨hq, hdiv⟩
180 rw [blockCoefficientSequence]
181 simp [hnot]
182
183 /-- Proposition 9.7 in exact block form: only the indices `N n ≤ m`
184 contribute to the Appell polynomial. -/
185 theorem appellPolynomial_eq_block_sum (N m : ℕ) (hN : 0 < N)
186 (c : ℕ → R) :
187 appellPolynomial (blockCoefficientSequence N c) m =
188 ∑ n ∈ Finset.range (m / N + 1),
189 Polynomial.C ((m.choose (N * n) : R) * c n) *
190 Polynomial.X ^ (m - N * n) := by
191 rw [appellPolynomial_eq_sparse_sum]
192 symm
193 refine Finset.sum_bij (fun n _ => N * n) ?_ ?_ ?_ ?_
194 · intro n hn
195 apply Finset.mem_filter.mpr
196 constructor
197 · apply Finset.mem_range.mpr
198 have hnle : n ≤ m / N := Nat.le_of_lt_succ (Finset.mem_range.mp hn)
199 have hmul : n * N ≤ m := (Nat.le_div_iff_mul_le hN).mp hnle
200 simpa [Nat.mul_comm] using Nat.lt_succ_of_le hmul
201 · exact dvd_mul_right N n
202 · intro n₁ _ n₂ _ heq
203 exact Nat.mul_left_cancel hN heq
204 · intro q hq
205 rcases Finset.mem_filter.mp hq with ⟨hqrange, hdiv⟩
206 rcases hdiv with ⟨n, rfl⟩
207 refine ⟨n, ?_, rfl⟩
208 apply Finset.mem_range.mpr
209 rw [Nat.lt_add_one_iff]
210 apply (Nat.le_div_iff_mul_le hN).mpr
211 have hNm : N * n ≤ m := Nat.le_of_lt_succ (Finset.mem_range.mp hqrange)
212 simpa [Nat.mul_comm] using hNm
213 · intro n hn
214 simp [blockCoefficientSequence_mul N hN]
215
216 /-- Every Appell polynomial with unit zeroth base coefficient is monic of its
217 displayed degree. -/
218 theorem appellPolynomial_isMonicOfDegree [Nontrivial R] (a : ℕ → R) (m : ℕ)
219 (ha : a 0 = 1) :
220 Polynomial.IsMonicOfDegree (appellPolynomial a m) m := by
221 rw [Polynomial.isMonicOfDegree_iff]
222 constructor
223 · rw [appellPolynomial]
224 apply Polynomial.natDegree_sum_le_of_forall_le
225 intro q hq
226 exact (Polynomial.natDegree_C_mul_X_pow_le _ _).trans (Nat.sub_le m q)
227 · rw [appellPolynomial, Polynomial.finsetSum_coeff]
228 rw [Finset.sum_eq_single 0]
229 · simp [ha]
230 · intro q hq hq0
231 rw [Polynomial.coeff_C_mul, Polynomial.coeff_X_pow]
232 have hqm : q ≤ m := Nat.le_of_lt_succ (Finset.mem_range.mp hq)
233 have hne : m ≠ m - q := by omega
234 simp [hne]
235 · simp
236
237 /-- The block form of Proposition 9.7 is monic when its zeroth reciprocal
238 coefficient is one. -/
239 theorem blockAppellPolynomial_isMonicOfDegree [Nontrivial R]
240 (N m : ℕ) (c : ℕ → R) (hc : c 0 = 1) :
241 Polynomial.IsMonicOfDegree
242 (appellPolynomial (blockCoefficientSequence N c) m) m := by
243 apply appellPolynomial_isMonicOfDegree
244 simp [blockCoefficientSequence, hc]
245
246 /-- Corollary 9.10: block-supported Appell polynomials transform by the
247 character `omega^m` whenever `omega^N = 1`. -/
248 theorem eval_appellPolynomial_block_covariance (N m : ℕ) (hN : 0 < N)
249 (c : ℕ → R) (omega x : R) (homega : omega ^ N = 1) :
250 (appellPolynomial (blockCoefficientSequence N c) m).eval (omega * x) =
251 omega ^ m *
252 (appellPolynomial (blockCoefficientSequence N c) m).eval x := by
253 rw [appellPolynomial_eq_block_sum N m hN c,
254 Polynomial.eval_finsetSum, Polynomial.eval_finsetSum]
255 rw [Finset.mul_sum]
256 apply Finset.sum_congr rfl
257 intro n hn
258 have hnle : n ≤ m / N := Nat.le_of_lt_succ (Finset.mem_range.mp hn)
259 have hmul : N * n ≤ m := by
260 have : n * N ≤ m := (Nat.le_div_iff_mul_le hN).mp hnle
261 simpa [Nat.mul_comm] using this
262 simp only [Polynomial.eval_mul, Polynomial.eval_C, Polynomial.eval_pow,
263 Polynomial.eval_X]
264 rw [mul_pow]
265 have hpow : omega ^ (m - N * n) = omega ^ m := by
266 calc
267 omega ^ (m - N * n) = omega ^ (m - N * n) * 1 := by rw [mul_one]
268 _ = omega ^ (m - N * n) * (omega ^ N) ^ n := by rw [homega, one_pow]
269 _ = omega ^ (m - N * n) * omega ^ (N * n) := by rw [pow_mul]
270 _ = omega ^ (m - N * n + N * n) := by rw [pow_add]
271 _ = omega ^ m := by rw [Nat.sub_add_cancel hmul]
272 rw [hpow]
273 ring
274
275 section ResidueAppell
276
277 variable {K : Type*} [Field K] [CharZero K]
278
279 omit [CharZero K] in
280 /-- Proposition 9.7 specialized to the reciprocal of the normalized residue
281 section from Theorem 9.2. -/
282 theorem residueAppellPolynomial_explicit (N j m : ℕ) (hN : 0 < N) :
283 appellPolynomial
284 (blockCoefficientSequence N
285 (residueInverseCoeff (K := K) N j)) m =
286 ∑ n ∈ Finset.range (m / N + 1),
287 Polynomial.C
288 ((m.choose (N * n) : K) * residueInverseCoeff (K := K) N j n) *
289 Polynomial.X ^ (m - N * n) := by
290 exact appellPolynomial_eq_block_sum N m hN _
291
292 /-- The residue-section Appell polynomial is monic of degree `m`. -/
293 theorem residueAppellPolynomial_isMonicOfDegree (N j m : ℕ) (_hN : 0 < N) :
294 Polynomial.IsMonicOfDegree
295 (appellPolynomial
296 (blockCoefficientSequence N
297 (residueInverseCoeff (K := K) N j)) m) m := by
298 exact blockAppellPolynomial_isMonicOfDegree N m _
299 (residueInverseCoeff_zero (K := K) N j)
300
301 omit [CharZero K] in
302 /-- Corollary 9.10 specialized to the normalized residue-section reciprocal. -/
303 theorem eval_residueAppellPolynomial_covariance (N j m : ℕ) (hN : 0 < N)
304 (omega x : K) (homega : omega ^ N = 1) :
305 (appellPolynomial
306 (blockCoefficientSequence N
307 (residueInverseCoeff (K := K) N j)) m).eval (omega * x) =
308 omega ^ m *
309 (appellPolynomial
310 (blockCoefficientSequence N
311 (residueInverseCoeff (K := K) N j)) m).eval x := by
312 exact eval_appellPolynomial_block_covariance N m hN _ omega x homega
313
314 end ResidueAppell
315
316 end SparseAppell
317
318 section DifferentialOperator
319
320 variable {R : Type*} [CommRing R]
321
322 /-- The finite action of a constant-coefficient formal symbol whose exponential
323 generating coefficients are `a`. Hasse derivatives encode the factors
324 `derivative^q / q!` without any characteristic-zero assumption. -/
325 def egfConstantCoeffAction (a : ℕ → R) (f : Polynomial R) : Polynomial R :=
326 ∑ q ∈ Finset.range (f.natDegree + 1),
327 Polynomial.C (a q) * Polynomial.hasseDeriv q f
328
329 /-- The first operator identity of Proposition 9.9: applying the formal symbol
330 with EGF coefficients `a` to `X^m` gives its Appell polynomial exactly. -/
331 theorem egfConstantCoeffAction_X_pow [Nontrivial R] (a : ℕ → R) (m : ℕ) :
332 egfConstantCoeffAction a (Polynomial.X ^ m) = appellPolynomial a m := by
333 rw [egfConstantCoeffAction, Polynomial.natDegree_X_pow, appellPolynomial]
334 apply Finset.sum_congr rfl
335 intro q _hq
336 rw [Polynomial.X_pow_eq_monomial, Polynomial.hasseDeriv_monomial]
337 simp only [mul_one, ← Polynomial.C_mul_X_pow_eq_monomial]
338 rw [← mul_assoc, ← map_mul]
339 congr 1
340 exact congrArg Polynomial.C (mul_comm (a q) (m.choose q : R))
341
342 /-- Proposition 9.9 specialized to the normalized residue-section reciprocal:
343 the corresponding finite constant-coefficient action produces the Appell
344 polynomial from `X^m`. -/
345 theorem egfConstantCoeffAction_residue_X_pow
346 {K : Type*} [Field K] [CharZero K] (N j m : ℕ) :
347 egfConstantCoeffAction
348 (blockCoefficientSequence N
349 (residueInverseCoeff (K := K) N j))
350 (Polynomial.X ^ m) =
351 appellPolynomial
352 (blockCoefficientSequence N
353 (residueInverseCoeff (K := K) N j)) m := by
354 exact egfConstantCoeffAction_X_pow _ m
355
356 end DifferentialOperator
357
358 section TruncatedOperatorInversion
359
360 variable {S : Type*} [CommRing S]
361
362 /-- Polynomial differential symbols evaluated at the formal derivative. -/
363 def polynomialDifferentialEval :
364 Polynomial S →+* Module.End S (Polynomial S) :=
365 Polynomial.eval₂RingHom' (algebraMap S (Module.End S (Polynomial S)))
366 Polynomial.derivative
367 fun a => Algebra.commute_algebraMap_left a Polynomial.derivative
368
369 @[simp]
370 theorem polynomialDifferentialEval_X :
371 polynomialDifferentialEval (S := S) Polynomial.X = Polynomial.derivative := by
372 simp [polynomialDifferentialEval]
373
374 /-- The degree-`d` truncation of a formal differential symbol. -/
375 def truncatedDifferentialOperator (d : ℕ) (A : S⟦X⟧) :
376 Module.End S (Polynomial S) :=
377 polynomialDifferentialEval (PowerSeries.trunc (d + 1) A)
378
379 theorem coeff_trunc_mul_trunc_of_lt (A B : S⟦X⟧) {d q : ℕ} (hq : q < d + 1) :
380 (PowerSeries.trunc (d + 1) A * PowerSeries.trunc (d + 1) B).coeff q =
381 PowerSeries.coeff q (A * B) := by
382 rw [Polynomial.coeff_mul, PowerSeries.coeff_mul]
383 apply Finset.sum_congr rfl
384 intro p hp
385 have hpadd : p.1 + p.2 = q := Finset.mem_antidiagonal.mp hp
386 have hp1 : p.1 < d + 1 := by omega
387 have hp2 : p.2 < d + 1 := by omega
388 simp only [PowerSeries.coeff_trunc, hp1, hp2, ↓reduceIte]
389
390 /-- If two formal symbols multiply to one, their degree-`d` truncations multiply
391 to one modulo `X^(d+1)`. -/
392 theorem X_pow_dvd_trunc_mul_trunc_sub_one {A B : S⟦X⟧} (d : ℕ)
393 (hAB : A * B = 1) :
394 Polynomial.X ^ (d + 1) ∣
395 PowerSeries.trunc (d + 1) A * PowerSeries.trunc (d + 1) B - 1 := by
396 rw [Polynomial.X_pow_dvd_iff]
397 intro q hq
398 rw [Polynomial.coeff_sub, coeff_trunc_mul_trunc_of_lt A B hq]
399 rw [hAB]
400 simp [PowerSeries.coeff_one, Polynomial.coeff_one]
401
402 /-- Constant-coefficient operator inversion on polynomials: if `A * B = 1`,
403 then the degree-`d` truncations of `A(∂)` and `B(∂)` compose to the
404 identity on every polynomial of degree at most `d`. -/
405 theorem truncatedDifferentialOperator_mul_apply_of_natDegree_le
406 {A B : S⟦X⟧} {d : ℕ} {p : Polynomial S} (hp : p.natDegree ≤ d)
407 (hAB : A * B = 1) :
408 (truncatedDifferentialOperator d A * truncatedDifferentialOperator d B) p = p := by
409 obtain ⟨Q, hQ⟩ := X_pow_dvd_trunc_mul_trunc_sub_one (S := S) d hAB
410 have hQ' :
411 PowerSeries.trunc (d + 1) A * PowerSeries.trunc (d + 1) B - 1 =
412 Q * Polynomial.X ^ (d + 1) := by
413 rw [hQ, mul_comm]
414 have heval := congrArg polynomialDifferentialEval hQ'
415 simp only [map_sub, map_mul, map_pow, map_one] at heval
416 have hderiv :
417 ((Polynomial.derivative : Module.End S (Polynomial S)) ^ (d + 1)) p = 0 := by
418 rw [Module.End.pow_apply]
419 exact Polynomial.iterate_derivative_eq_zero
420 (lt_of_le_of_lt hp (Nat.lt_succ_self d))
421 have happ := congrArg (fun T : Module.End S (Polynomial S) => T p) heval
422 rw [LinearMap.sub_apply, Module.End.mul_apply, Module.End.mul_apply,
423 Module.End.one_apply] at happ
424 rw [polynomialDifferentialEval_X] at happ
425 change
426 polynomialDifferentialEval (PowerSeries.trunc (d + 1) A)
427 (polynomialDifferentialEval (PowerSeries.trunc (d + 1) B) p) - p =
428 polynomialDifferentialEval Q
429 (((Polynomial.derivative : Module.End S (Polynomial S)) ^ (d + 1)) p) at happ
430 rw [hderiv, LinearMap.map_zero] at happ
431 change
432 (polynomialDifferentialEval (PowerSeries.trunc (d + 1) A) *
433 polynomialDifferentialEval (PowerSeries.trunc (d + 1) B)) p = p
434 exact sub_eq_zero.mp happ
435
436 /-- The `r = 1` inverse-operator relation of Proposition 9.9 for a normalized
437 residue section. `expand N` performs the substitution `w = z^N`; hence the
438 two displayed symbols are `Φₙ,ⱼ(z^N)` and its reciprocal. -/
439 theorem truncatedDifferentialOperator_normalizedResidueSection_inverse
440 {K : Type*} [Field K] [CharZero K] (N j d : ℕ) (hN : 0 < N)
441 {p : Polynomial K} (hp : p.natDegree ≤ d) :
442 (truncatedDifferentialOperator d
443 (PowerSeries.expand N hN.ne'
444 (normalizedResidueSection (K := K) N j)) *
445 truncatedDifferentialOperator d
446 (PowerSeries.expand N hN.ne'
447 (normalizedResidueSection (K := K) N j)⁻¹)) p = p := by
448 apply truncatedDifferentialOperator_mul_apply_of_natDegree_le hp
449 rw [← map_mul]
450 rw [PowerSeries.mul_inv_cancel]
451 · exact map_one _
452 · simp
453
454 end TruncatedOperatorInversion
455
456 end
457
458 end Komorebi.PaperIV
Original file and source record
This copy matches the recorded source file. Its publication here does not change the work’s review status.
SHA-256: 799249f2b51ac860dc460cca8d8e8279f8b01124a2a15fbcc21aea4e444b81ff
Back to Paper IV: Cyclic Analytic Functions, Reciprocal Families, and Spectral Zero Data