Skip to main content

oxilean_std/complex/
functions.rs

1//! Auto-generated module
2//!
3//! 🤖 Generated with [SplitRS](https://github.com/cool-japan/splitrs)
4#![allow(clippy::items_after_test_module)]
5
6use oxilean_kernel::{BinderInfo, Declaration, Environment, Expr, Level, Name};
7use std::f64::consts::PI;
8
9use super::complex_type::Complex;
10use super::types::{MobiusTransform, C64};
11
12#[allow(dead_code)]
13pub fn app(f: Expr, a: Expr) -> Expr {
14    Expr::App(Box::new(f), Box::new(a))
15}
16#[allow(dead_code)]
17pub fn app2(f: Expr, a: Expr, b: Expr) -> Expr {
18    app(app(f, a), b)
19}
20#[allow(dead_code)]
21pub fn app3(f: Expr, a: Expr, b: Expr, c: Expr) -> Expr {
22    app(app2(f, a, b), c)
23}
24pub fn cst(s: &str) -> Expr {
25    Expr::Const(Name::str(s), vec![])
26}
27#[allow(dead_code)]
28pub fn prop() -> Expr {
29    Expr::Sort(Level::zero())
30}
31pub fn type0() -> Expr {
32    Expr::Sort(Level::succ(Level::zero()))
33}
34pub fn pi(bi: BinderInfo, name: &str, dom: Expr, body: Expr) -> Expr {
35    Expr::Pi(bi, Name::str(name), Box::new(dom), Box::new(body))
36}
37pub fn arrow(a: Expr, b: Expr) -> Expr {
38    pi(BinderInfo::Default, "_", a, b)
39}
40#[allow(dead_code)]
41pub fn impl_pi(name: &str, dom: Expr, body: Expr) -> Expr {
42    pi(BinderInfo::Implicit, name, dom, body)
43}
44pub fn bvar(n: u32) -> Expr {
45    Expr::BVar(n)
46}
47pub fn real_ty() -> Expr {
48    cst("Real")
49}
50pub fn complex_ty() -> Expr {
51    cst("Complex")
52}
53pub fn nat_ty() -> Expr {
54    cst("Nat")
55}
56/// Complex : Type  (ℂ = ℝ × ℝ as a structure)
57pub fn complex_type_decl() -> Expr {
58    type0()
59}
60/// Complex.mk : Real → Real → Complex
61pub fn complex_mk_ty() -> Expr {
62    arrow(real_ty(), arrow(real_ty(), complex_ty()))
63}
64/// Complex.re : Complex → Real
65pub fn complex_re_ty() -> Expr {
66    arrow(complex_ty(), real_ty())
67}
68/// Complex.im : Complex → Real
69pub fn complex_im_ty() -> Expr {
70    arrow(complex_ty(), real_ty())
71}
72/// Complex.add : Complex → Complex → Complex
73pub fn complex_add_ty() -> Expr {
74    arrow(complex_ty(), arrow(complex_ty(), complex_ty()))
75}
76/// Complex.mul : Complex → Complex → Complex
77pub fn complex_mul_ty() -> Expr {
78    arrow(complex_ty(), arrow(complex_ty(), complex_ty()))
79}
80/// Complex.neg : Complex → Complex
81pub fn complex_neg_ty() -> Expr {
82    arrow(complex_ty(), complex_ty())
83}
84/// Complex.conj : Complex → Complex  (complex conjugate: a + bi → a - bi)
85pub fn complex_conj_ty() -> Expr {
86    arrow(complex_ty(), complex_ty())
87}
88/// Complex.normSq : Complex → Real  (|z|² = re² + im²)
89pub fn complex_norm_sq_ty() -> Expr {
90    arrow(complex_ty(), real_ty())
91}
92/// Complex.abs : Complex → Real  (|z| = √(re² + im²))
93pub fn complex_abs_ty() -> Expr {
94    arrow(complex_ty(), real_ty())
95}
96/// Complex.arg : Complex → Real  (argument, in (-π, π])
97pub fn complex_arg_ty() -> Expr {
98    arrow(complex_ty(), real_ty())
99}
100/// Complex.exp : Complex → Complex  (complex exponential)
101pub fn complex_exp_ty() -> Expr {
102    arrow(complex_ty(), complex_ty())
103}
104/// Complex.log : Complex → Complex  (principal value logarithm)
105pub fn complex_log_ty() -> Expr {
106    arrow(complex_ty(), complex_ty())
107}
108/// Complex.pow : Complex → Nat → Complex
109pub fn complex_pow_ty() -> Expr {
110    arrow(complex_ty(), arrow(nat_ty(), complex_ty()))
111}
112/// Complex.sqrt : Complex → Complex  (principal square root)
113pub fn complex_sqrt_ty() -> Expr {
114    arrow(complex_ty(), complex_ty())
115}
116/// Complex.ofReal : Real → Complex  (coercion ℝ → ℂ)
117pub fn complex_of_real_ty() -> Expr {
118    arrow(real_ty(), complex_ty())
119}
120/// Complex.I : Complex  (imaginary unit i = (0, 1))
121pub fn complex_i_ty() -> Expr {
122    complex_ty()
123}
124/// Euler's formula: exp(i·θ) = cos(θ) + i·sin(θ)
125pub fn euler_formula_ty() -> Expr {
126    pi(
127        BinderInfo::Default,
128        "theta",
129        real_ty(),
130        app2(
131            app(cst("Eq"), complex_ty()),
132            app(
133                cst("Complex.exp"),
134                app2(
135                    cst("Complex.mul"),
136                    cst("Complex.I"),
137                    app(cst("Complex.ofReal"), bvar(0)),
138                ),
139            ),
140            app2(
141                cst("Complex.add"),
142                app(cst("Complex.ofReal"), app(cst("Real.cos"), bvar(0))),
143                app2(
144                    cst("Complex.mul"),
145                    cst("Complex.I"),
146                    app(cst("Complex.ofReal"), app(cst("Real.sin"), bvar(0))),
147                ),
148            ),
149        ),
150    )
151}
152/// De Moivre's theorem: (cos θ + i·sin θ)^n = cos(n·θ) + i·sin(n·θ)
153pub fn de_moivre_theorem_ty() -> Expr {
154    pi(
155        BinderInfo::Default,
156        "theta",
157        real_ty(),
158        pi(
159            BinderInfo::Default,
160            "n",
161            nat_ty(),
162            app2(
163                app(cst("Eq"), complex_ty()),
164                app2(
165                    cst("Complex.pow"),
166                    app2(
167                        cst("Complex.add"),
168                        app(cst("Complex.ofReal"), app(cst("Real.cos"), bvar(1))),
169                        app2(
170                            cst("Complex.mul"),
171                            cst("Complex.I"),
172                            app(cst("Complex.ofReal"), app(cst("Real.sin"), bvar(1))),
173                        ),
174                    ),
175                    bvar(0),
176                ),
177                app2(
178                    cst("Complex.add"),
179                    app(
180                        cst("Complex.ofReal"),
181                        app(
182                            cst("Real.cos"),
183                            app2(cst("Real.mul"), app(cst("Nat.cast"), bvar(0)), bvar(1)),
184                        ),
185                    ),
186                    app2(
187                        cst("Complex.mul"),
188                        cst("Complex.I"),
189                        app(
190                            cst("Complex.ofReal"),
191                            app(
192                                cst("Real.sin"),
193                                app2(cst("Real.mul"), app(cst("Nat.cast"), bvar(0)), bvar(1)),
194                            ),
195                        ),
196                    ),
197                ),
198            ),
199        ),
200    )
201}
202/// Fundamental theorem of algebra: every non-constant polynomial over ℂ has a root
203pub fn fundamental_theorem_algebra_ty() -> Expr {
204    pi(
205        BinderInfo::Default,
206        "p",
207        app(cst("Polynomial"), complex_ty()),
208        arrow(
209            app(cst("Polynomial.degree_pos"), bvar(0)),
210            app(
211                cst("Exists"),
212                pi(
213                    BinderInfo::Default,
214                    "z",
215                    complex_ty(),
216                    app2(
217                        app(cst("Eq"), complex_ty()),
218                        app2(cst("Polynomial.eval"), bvar(0), bvar(1)),
219                        app(
220                            cst("Complex.ofReal"),
221                            app(
222                                cst("Real.ofNat"),
223                                Expr::Lit(oxilean_kernel::Literal::Nat(0)),
224                            ),
225                        ),
226                    ),
227                ),
228            ),
229        ),
230    )
231}
232/// Liouville's theorem: every bounded entire function is constant
233pub fn liouville_theorem_ty() -> Expr {
234    pi(
235        BinderInfo::Default,
236        "f",
237        arrow(complex_ty(), complex_ty()),
238        arrow(
239            app(cst("IsEntire"), bvar(0)),
240            arrow(
241                app(cst("IsBounded"), bvar(0)),
242                app(cst("IsConstant"), bvar(0)),
243            ),
244        ),
245    )
246}
247/// Cauchy's integral theorem: ∮_C f(z) dz = 0 for holomorphic f and closed curve C
248pub fn cauchy_integral_theorem_ty() -> Expr {
249    pi(
250        BinderInfo::Default,
251        "f",
252        arrow(complex_ty(), complex_ty()),
253        pi(
254            BinderInfo::Default,
255            "C",
256            app(cst("ClosedCurve"), complex_ty()),
257            arrow(
258                app(cst("IsHolomorphic"), bvar(1)),
259                app2(
260                    app(cst("Eq"), complex_ty()),
261                    app2(cst("ContourIntegral"), bvar(1), bvar(0)),
262                    app(
263                        cst("Complex.ofReal"),
264                        Expr::Lit(oxilean_kernel::Literal::Nat(0)),
265                    ),
266                ),
267            ),
268        ),
269    )
270}
271/// n-th roots of unity: z^n = 1 has exactly n solutions in ℂ
272pub fn roots_of_unity_ty() -> Expr {
273    pi(
274        BinderInfo::Default,
275        "n",
276        nat_ty(),
277        arrow(
278            app2(
279                cst("Nat.lt"),
280                Expr::Lit(oxilean_kernel::Literal::Nat(0)),
281                bvar(0),
282            ),
283            app2(
284                app(cst("Eq"), nat_ty()),
285                app(cst("Fintype.card"), app(cst("rootsOfUnity"), bvar(0))),
286                bvar(0),
287            ),
288        ),
289    )
290}
291/// CauchyRiemann: holomorphicity ↔ Cauchy-Riemann equations
292/// ∀ f : ℂ → ℂ, IsHolomorphic f ↔ SatisfiesCauchyRiemann f
293pub fn cauchy_riemann_ty() -> Expr {
294    pi(
295        BinderInfo::Default,
296        "f",
297        arrow(complex_ty(), complex_ty()),
298        app2(
299            app(cst("Iff"), prop()),
300            app(cst("IsHolomorphic"), bvar(0)),
301            app(cst("SatisfiesCauchyRiemann"), bvar(0)),
302        ),
303    )
304}
305/// Cauchy integral formula: f(z₀) = (1/2πi) ∮ f(z)/(z-z₀) dz
306pub fn cauchy_integral_formula_ty() -> Expr {
307    pi(
308        BinderInfo::Default,
309        "f",
310        arrow(complex_ty(), complex_ty()),
311        pi(
312            BinderInfo::Default,
313            "C",
314            app(cst("ClosedCurve"), complex_ty()),
315            pi(
316                BinderInfo::Default,
317                "z0",
318                complex_ty(),
319                arrow(
320                    app(cst("IsHolomorphicOn"), app2(cst("Pair"), bvar(2), bvar(1))),
321                    arrow(
322                        app2(cst("InsideCurve"), bvar(0), bvar(1)),
323                        app2(
324                            app(cst("Eq"), complex_ty()),
325                            app(bvar(2), bvar(0)),
326                            app2(cst("ContourIntegralFormula"), bvar(2), bvar(1)),
327                        ),
328                    ),
329                ),
330            ),
331        ),
332    )
333}
334/// Residue theorem: ∮_C f dz = 2πi · Σ Res(f, zₖ)
335pub fn residue_theorem_ty() -> Expr {
336    pi(
337        BinderInfo::Default,
338        "f",
339        arrow(complex_ty(), complex_ty()),
340        pi(
341            BinderInfo::Default,
342            "C",
343            app(cst("ClosedCurve"), complex_ty()),
344            arrow(
345                app(cst("IsMeromorphicOn"), app2(cst("Pair"), bvar(1), bvar(0))),
346                app2(
347                    app(cst("Eq"), complex_ty()),
348                    app2(cst("ContourIntegral"), bvar(1), bvar(0)),
349                    app2(cst("ResidueSum"), bvar(1), bvar(0)),
350                ),
351            ),
352        ),
353    )
354}
355/// Analytic continuation: two entire functions agreeing on an open set agree everywhere
356pub fn analytic_continuation_ty() -> Expr {
357    pi(
358        BinderInfo::Default,
359        "f",
360        arrow(complex_ty(), complex_ty()),
361        pi(
362            BinderInfo::Default,
363            "g",
364            arrow(complex_ty(), complex_ty()),
365            arrow(
366                app(cst("IsEntire"), bvar(1)),
367                arrow(
368                    app(cst("IsEntire"), bvar(0)),
369                    arrow(
370                        app2(cst("AgreeOnOpenSet"), bvar(1), bvar(0)),
371                        app2(cst("FunEq"), bvar(1), bvar(0)),
372                    ),
373                ),
374            ),
375        ),
376    )
377}
378/// Picard's little theorem: a non-constant entire function omits at most one value
379pub fn picard_little_theorem_ty() -> Expr {
380    pi(
381        BinderInfo::Default,
382        "f",
383        arrow(complex_ty(), complex_ty()),
384        arrow(
385            app(cst("IsEntire"), bvar(0)),
386            arrow(
387                app2(cst("Not"), prop(), app(cst("IsConstant"), bvar(0))),
388                app2(cst("OmitsAtMostOne"), bvar(0), complex_ty()),
389            ),
390        ),
391    )
392}
393/// Picard's great theorem: near an essential singularity, f is densely surjective (minus at most one point)
394pub fn picard_great_theorem_ty() -> Expr {
395    pi(
396        BinderInfo::Default,
397        "f",
398        arrow(complex_ty(), complex_ty()),
399        pi(
400            BinderInfo::Default,
401            "z0",
402            complex_ty(),
403            arrow(
404                app2(cst("IsEssentialSingularity"), bvar(1), bvar(0)),
405                app2(cst("DenseImageNearPoint"), bvar(1), bvar(0)),
406            ),
407        ),
408    )
409}
410/// Weierstrass factorization theorem: every entire function factors via its zero set
411pub fn weierstrass_factorization_ty() -> Expr {
412    pi(
413        BinderInfo::Default,
414        "f",
415        arrow(complex_ty(), complex_ty()),
416        arrow(
417            app(cst("IsEntire"), bvar(0)),
418            app2(cst("HasWeierstrassFactorization"), bvar(0), complex_ty()),
419        ),
420    )
421}
422/// Meromorphic function on the Riemann sphere is a rational function
423pub fn meromorphic_riemann_sphere_ty() -> Expr {
424    pi(
425        BinderInfo::Default,
426        "f",
427        arrow(complex_ty(), complex_ty()),
428        app2(
429            app(cst("Iff"), prop()),
430            app(cst("IsMeromorphicOnSphere"), bvar(0)),
431            app(cst("IsRationalFunction"), bvar(0)),
432        ),
433    )
434}
435/// Riemann mapping theorem: every simply connected proper open subset of ℂ is conformally equivalent to the disk
436pub fn riemann_mapping_theorem_ty() -> Expr {
437    pi(
438        BinderInfo::Default,
439        "U",
440        app(cst("OpenSet"), complex_ty()),
441        arrow(
442            app(cst("IsSimplyConnected"), bvar(0)),
443            arrow(
444                app2(cst("ProperSubset"), bvar(0), complex_ty()),
445                app2(cst("ConformallyEquivalent"), bvar(0), cst("UnitDisk")),
446            ),
447        ),
448    )
449}
450/// Möbius transformations form a group (PSL(2,ℂ))
451pub fn mobius_group_ty() -> Expr {
452    app(cst("IsGroup"), cst("MobiusGroup"))
453}
454/// Every Möbius transformation is a conformal automorphism of the Riemann sphere
455pub fn mobius_conformal_ty() -> Expr {
456    pi(
457        BinderInfo::Default,
458        "m",
459        cst("MobiusGroup"),
460        app(cst("IsConformalAutomorphism"), bvar(0)),
461    )
462}
463/// Laurent series convergence: every meromorphic function has a Laurent series in an annulus
464pub fn laurent_series_ty() -> Expr {
465    pi(
466        BinderInfo::Default,
467        "f",
468        arrow(complex_ty(), complex_ty()),
469        pi(
470            BinderInfo::Default,
471            "z0",
472            complex_ty(),
473            arrow(
474                app2(cst("IsIsolatedSingularity"), bvar(1), bvar(0)),
475                app2(cst("HasLaurentSeries"), bvar(1), bvar(0)),
476            ),
477        ),
478    )
479}
480/// Argument principle: (1/2πi)∮ f'/f dz = Z - P (zeros minus poles)
481pub fn argument_principle_ty() -> Expr {
482    pi(
483        BinderInfo::Default,
484        "f",
485        arrow(complex_ty(), complex_ty()),
486        pi(
487            BinderInfo::Default,
488            "C",
489            app(cst("ClosedCurve"), complex_ty()),
490            arrow(
491                app(cst("IsMeromorphicOn"), app2(cst("Pair"), bvar(1), bvar(0))),
492                app2(
493                    app(cst("Eq"), nat_ty()),
494                    app2(cst("WindingNumberIntegral"), bvar(1), bvar(0)),
495                    app2(
496                        cst("Nat.sub"),
497                        app2(cst("CountZeros"), bvar(1), bvar(0)),
498                        app2(cst("CountPoles"), bvar(1), bvar(0)),
499                    ),
500                ),
501            ),
502        ),
503    )
504}
505/// Rouché's theorem: if |f| > |g| on C, then f and f+g have the same number of zeros inside C
506pub fn rouche_theorem_ty() -> Expr {
507    pi(
508        BinderInfo::Default,
509        "f",
510        arrow(complex_ty(), complex_ty()),
511        pi(
512            BinderInfo::Default,
513            "g",
514            arrow(complex_ty(), complex_ty()),
515            pi(
516                BinderInfo::Default,
517                "C",
518                app(cst("ClosedCurve"), complex_ty()),
519                arrow(
520                    app2(
521                        cst("DominatesOnCurve"),
522                        bvar(2),
523                        app2(cst("Pair"), bvar(1), bvar(0)),
524                    ),
525                    app2(
526                        app(cst("Eq"), nat_ty()),
527                        app2(cst("CountZeros"), bvar(2), bvar(0)),
528                        app2(
529                            cst("CountZeros"),
530                            app2(cst("FunAdd"), bvar(2), bvar(1)),
531                            bvar(0),
532                        ),
533                    ),
534                ),
535            ),
536        ),
537    )
538}
539/// Mittag-Leffler theorem: meromorphic function with prescribed poles exists
540pub fn mittag_leffler_theorem_ty() -> Expr {
541    pi(
542        BinderInfo::Default,
543        "poles",
544        app(cst("List"), complex_ty()),
545        pi(
546            BinderInfo::Default,
547            "parts",
548            app(cst("List"), app(cst("LaurentPrincipalPart"), complex_ty())),
549            arrow(
550                app2(cst("CompatiblePolesAndParts"), bvar(1), bvar(0)),
551                app(
552                    cst("Exists"),
553                    pi(
554                        BinderInfo::Default,
555                        "f",
556                        arrow(complex_ty(), complex_ty()),
557                        app2(
558                            cst("HasPrescribedPoles"),
559                            bvar(0),
560                            app2(cst("Pair"), bvar(2), bvar(1)),
561                        ),
562                    ),
563                ),
564            ),
565        ),
566    )
567}
568/// Runge's theorem: holomorphic functions on a compact set can be approximated by rational functions
569pub fn runge_theorem_ty() -> Expr {
570    pi(
571        BinderInfo::Default,
572        "K",
573        app(cst("CompactSet"), complex_ty()),
574        pi(
575            BinderInfo::Default,
576            "f",
577            arrow(complex_ty(), complex_ty()),
578            arrow(
579                app(
580                    cst("IsHolomorphicOnCompact"),
581                    app2(cst("Pair"), bvar(1), bvar(0)),
582                ),
583                app2(
584                    cst("UniformlyApproximableBy"),
585                    app2(cst("Pair"), bvar(1), bvar(0)),
586                    cst("RationalFunctions"),
587                ),
588            ),
589        ),
590    )
591}
592/// Hardy space H^p is a Banach space for p ≥ 1
593pub fn hardy_banach_ty() -> Expr {
594    pi(
595        BinderInfo::Default,
596        "p",
597        real_ty(),
598        arrow(
599            app2(
600                cst("Real.le"),
601                Expr::Lit(oxilean_kernel::Literal::Nat(1)),
602                bvar(0),
603            ),
604            app(cst("IsBanachSpace"), app(cst("HardySpace"), bvar(0))),
605        ),
606    )
607}
608/// Nevanlinna's first fundamental theorem: T(r, f) = m(r, f) + N(r, f) + O(1)
609pub fn nevanlinna_first_theorem_ty() -> Expr {
610    pi(
611        BinderInfo::Default,
612        "f",
613        arrow(complex_ty(), complex_ty()),
614        arrow(
615            app(cst("IsMeromorphic"), bvar(0)),
616            app(cst("NevanlinnaFirstFundamentalTheorem"), bvar(0)),
617        ),
618    )
619}
620/// Nevanlinna's second fundamental theorem: sum of Nevanlinna deficiencies ≤ 2
621pub fn nevanlinna_second_theorem_ty() -> Expr {
622    pi(
623        BinderInfo::Default,
624        "f",
625        arrow(complex_ty(), complex_ty()),
626        arrow(
627            app(cst("IsEntire"), bvar(0)),
628            app2(
629                app(cst("Real.le"), prop()),
630                app(cst("NevanlinnaDeficiencySum"), bvar(0)),
631                Expr::Lit(oxilean_kernel::Literal::Nat(2)),
632            ),
633        ),
634    )
635}
636/// Bloch's theorem: image of unit disk contains a disk of radius B (Bloch's constant)
637pub fn bloch_theorem_ty() -> Expr {
638    pi(
639        BinderInfo::Default,
640        "f",
641        arrow(complex_ty(), complex_ty()),
642        arrow(
643            app(cst("IsHolomorphicOnDisk"), bvar(0)),
644            app2(cst("ImageContainsDisk"), bvar(0), cst("BlochConstant")),
645        ),
646    )
647}
648/// Weierstrass ℘-function is an elliptic function for its lattice
649pub fn weierstrass_p_ty() -> Expr {
650    pi(
651        BinderInfo::Default,
652        "L",
653        app(cst("Lattice"), complex_ty()),
654        app(cst("IsEllipticFunction"), app(cst("WeierstrassP"), bvar(0))),
655    )
656}
657/// Liouville theorem for elliptic functions: bounded implies constant
658pub fn elliptic_liouville_ty() -> Expr {
659    pi(
660        BinderInfo::Default,
661        "L",
662        app(cst("Lattice"), complex_ty()),
663        pi(
664            BinderInfo::Default,
665            "f",
666            arrow(complex_ty(), complex_ty()),
667            arrow(
668                app2(cst("IsEllipticFunctionForLattice"), bvar(0), bvar(1)),
669                arrow(
670                    app(cst("IsBounded"), bvar(0)),
671                    app(cst("IsConstant"), bvar(0)),
672                ),
673            ),
674        ),
675    )
676}
677/// The space of modular forms of weight k is finite-dimensional
678pub fn modular_form_finite_dim_ty() -> Expr {
679    pi(
680        BinderInfo::Default,
681        "k",
682        nat_ty(),
683        app(
684            cst("IsFiniteDimensional"),
685            app(cst("ModularFormSpace"), bvar(0)),
686        ),
687    )
688}
689/// Hartogs' theorem: holomorphic functions in several variables extend across compact singularities
690pub fn hartogs_theorem_ty() -> Expr {
691    pi(
692        BinderInfo::Default,
693        "n",
694        nat_ty(),
695        pi(
696            BinderInfo::Default,
697            "U",
698            app(cst("OpenSet"), app(cst("CVec"), bvar(0))),
699            pi(
700                BinderInfo::Default,
701                "K",
702                app(cst("CompactSet"), app(cst("CVec"), bvar(1))),
703                arrow(
704                    app2(cst("IsCompactlyContained"), bvar(0), bvar(1)),
705                    arrow(
706                        app(cst("IsSimplyConnected"), bvar(1)),
707                        app2(cst("HolomorphicFunctionsExtend"), bvar(1), bvar(0)),
708                    ),
709                ),
710            ),
711        ),
712    )
713}
714/// Oka's theorem: pseudoconvex ↔ domain of holomorphy in ℂⁿ
715pub fn oka_theorem_ty() -> Expr {
716    pi(
717        BinderInfo::Default,
718        "D",
719        app(cst("Domain"), cst("CnSpace")),
720        app2(
721            app(cst("Iff"), prop()),
722            app(cst("IsPseudoconvex"), bvar(0)),
723            app(cst("IsDomainOfHolomorphy"), bvar(0)),
724        ),
725    )
726}
727/// Bohr's theorem: |f| < 1 on disk ⟹ power series converges in disk of radius 1/3
728pub fn bohr_theorem_ty() -> Expr {
729    pi(
730        BinderInfo::Default,
731        "f",
732        arrow(complex_ty(), complex_ty()),
733        arrow(
734            app(cst("IsHolomorphicOnDisk"), bvar(0)),
735            arrow(
736                app(cst("BoundedByOneOnDisk"), bvar(0)),
737                app2(
738                    cst("PowerSeriesConvergesInDisk"),
739                    bvar(0),
740                    cst("BohrConstant"),
741                ),
742            ),
743        ),
744    )
745}
746/// Paley-Wiener: L² function is bandlimited ↔ Fourier transform has compact support
747pub fn paley_wiener_theorem_ty() -> Expr {
748    pi(
749        BinderInfo::Default,
750        "f",
751        arrow(real_ty(), complex_ty()),
752        app2(
753            app(cst("Iff"), prop()),
754            app(cst("IsBandlimited"), bvar(0)),
755            app(cst("FourierTransformHasCompactSupport"), bvar(0)),
756        ),
757    )
758}
759/// Hadamard factorization theorem: entire function of finite order has Weierstrass product form
760pub fn hadamard_factorization_ty() -> Expr {
761    pi(
762        BinderInfo::Default,
763        "f",
764        arrow(complex_ty(), complex_ty()),
765        pi(
766            BinderInfo::Default,
767            "rho",
768            real_ty(),
769            arrow(
770                app(cst("IsEntire"), bvar(1)),
771                arrow(
772                    app2(cst("HasFiniteOrder"), bvar(1), bvar(0)),
773                    app2(cst("HasHadamardFactorization"), bvar(1), bvar(0)),
774                ),
775            ),
776        ),
777    )
778}
779/// Schwarz-Pick lemma: holomorphic self-map of the unit disk is a hyperbolic contraction
780pub fn schwarz_pick_lemma_ty() -> Expr {
781    pi(
782        BinderInfo::Default,
783        "f",
784        arrow(complex_ty(), complex_ty()),
785        arrow(
786            app(cst("IsSelfMapOfDisk"), bvar(0)),
787            app(cst("IsHyperbolicContraction"), bvar(0)),
788        ),
789    )
790}
791/// Jensen's formula: log|f(0)| = Σ log(r/|zₖ|) + (1/2π)∫₀²π log|f(re^{iθ})| dθ
792pub fn jensen_formula_ty() -> Expr {
793    pi(
794        BinderInfo::Default,
795        "f",
796        arrow(complex_ty(), complex_ty()),
797        pi(
798            BinderInfo::Default,
799            "r",
800            real_ty(),
801            arrow(
802                app(cst("IsHolomorphicOnDisk"), bvar(1)),
803                arrow(
804                    app2(
805                        cst("Real.lt"),
806                        Expr::Lit(oxilean_kernel::Literal::Nat(0)),
807                        bvar(0),
808                    ),
809                    app2(cst("JensenEquality"), bvar(1), bvar(0)),
810                ),
811            ),
812        ),
813    )
814}
815/// Phragmén-Lindelöf: maximum modulus principle extended to unbounded sectors
816pub fn phragmen_lindelof_ty() -> Expr {
817    pi(
818        BinderInfo::Default,
819        "f",
820        arrow(complex_ty(), complex_ty()),
821        pi(
822            BinderInfo::Default,
823            "S",
824            app(cst("OpenSector"), complex_ty()),
825            arrow(
826                app(cst("IsHolomorphicOn"), app2(cst("Pair"), bvar(1), bvar(0))),
827                arrow(
828                    app(
829                        cst("BoundedOnBoundary"),
830                        app2(cst("Pair"), bvar(1), bvar(0)),
831                    ),
832                    app(cst("BoundedOn"), app2(cst("Pair"), bvar(1), bvar(0))),
833                ),
834            ),
835        ),
836    )
837}
838/// Riemann zeta function extends meromorphically to ℂ with a simple pole at s = 1
839pub fn riemann_zeta_meromorphic_ty() -> Expr {
840    app(cst("IsMeromorphic"), cst("RiemannZeta"))
841}
842/// Riemann hypothesis (as axiom): non-trivial zeros of ζ lie on Re(s) = 1/2
843pub fn riemann_hypothesis_ty() -> Expr {
844    pi(
845        BinderInfo::Default,
846        "s",
847        complex_ty(),
848        arrow(
849            app2(cst("IsNontrivialZeroOfZeta"), bvar(0), cst("RiemannZeta")),
850            app2(
851                app(cst("Eq"), real_ty()),
852                app(cst("Complex.re"), bvar(0)),
853                Expr::Lit(oxilean_kernel::Literal::Nat(0)),
854            ),
855        ),
856    )
857}
858/// Build the complex number environment, registering all axioms and theorems.
859#[allow(dead_code)]
860pub fn build_complex_env(env: &mut Environment) -> Result<(), String> {
861    let _ = env.add(Declaration::Axiom {
862        name: Name::str("Complex"),
863        univ_params: vec![],
864        ty: complex_type_decl(),
865    });
866    let _ = env.add(Declaration::Axiom {
867        name: Name::str("Complex.mk"),
868        univ_params: vec![],
869        ty: complex_mk_ty(),
870    });
871    let _ = env.add(Declaration::Axiom {
872        name: Name::str("Complex.re"),
873        univ_params: vec![],
874        ty: complex_re_ty(),
875    });
876    let _ = env.add(Declaration::Axiom {
877        name: Name::str("Complex.im"),
878        univ_params: vec![],
879        ty: complex_im_ty(),
880    });
881    let _ = env.add(Declaration::Axiom {
882        name: Name::str("Complex.add"),
883        univ_params: vec![],
884        ty: complex_add_ty(),
885    });
886    let _ = env.add(Declaration::Axiom {
887        name: Name::str("Complex.mul"),
888        univ_params: vec![],
889        ty: complex_mul_ty(),
890    });
891    let _ = env.add(Declaration::Axiom {
892        name: Name::str("Complex.neg"),
893        univ_params: vec![],
894        ty: complex_neg_ty(),
895    });
896    let _ = env.add(Declaration::Axiom {
897        name: Name::str("Complex.conj"),
898        univ_params: vec![],
899        ty: complex_conj_ty(),
900    });
901    let _ = env.add(Declaration::Axiom {
902        name: Name::str("Complex.normSq"),
903        univ_params: vec![],
904        ty: complex_norm_sq_ty(),
905    });
906    let _ = env.add(Declaration::Axiom {
907        name: Name::str("Complex.abs"),
908        univ_params: vec![],
909        ty: complex_abs_ty(),
910    });
911    let _ = env.add(Declaration::Axiom {
912        name: Name::str("Complex.arg"),
913        univ_params: vec![],
914        ty: complex_arg_ty(),
915    });
916    let _ = env.add(Declaration::Axiom {
917        name: Name::str("Complex.exp"),
918        univ_params: vec![],
919        ty: complex_exp_ty(),
920    });
921    let _ = env.add(Declaration::Axiom {
922        name: Name::str("Complex.log"),
923        univ_params: vec![],
924        ty: complex_log_ty(),
925    });
926    let _ = env.add(Declaration::Axiom {
927        name: Name::str("Complex.pow"),
928        univ_params: vec![],
929        ty: complex_pow_ty(),
930    });
931    let _ = env.add(Declaration::Axiom {
932        name: Name::str("Complex.sqrt"),
933        univ_params: vec![],
934        ty: complex_sqrt_ty(),
935    });
936    let _ = env.add(Declaration::Axiom {
937        name: Name::str("Complex.ofReal"),
938        univ_params: vec![],
939        ty: complex_of_real_ty(),
940    });
941    let _ = env.add(Declaration::Axiom {
942        name: Name::str("Complex.I"),
943        univ_params: vec![],
944        ty: complex_i_ty(),
945    });
946    let _ = env.add(Declaration::Axiom {
947        name: Name::str("Complex.euler_formula"),
948        univ_params: vec![],
949        ty: euler_formula_ty(),
950    });
951    let _ = env.add(Declaration::Axiom {
952        name: Name::str("Complex.de_moivre"),
953        univ_params: vec![],
954        ty: de_moivre_theorem_ty(),
955    });
956    let _ = env.add(Declaration::Axiom {
957        name: Name::str("Complex.fundamental_theorem_algebra"),
958        univ_params: vec![],
959        ty: fundamental_theorem_algebra_ty(),
960    });
961    let _ = env.add(Declaration::Axiom {
962        name: Name::str("Complex.liouville"),
963        univ_params: vec![],
964        ty: liouville_theorem_ty(),
965    });
966    let _ = env.add(Declaration::Axiom {
967        name: Name::str("Complex.cauchy_integral"),
968        univ_params: vec![],
969        ty: cauchy_integral_theorem_ty(),
970    });
971    let _ = env.add(Declaration::Axiom {
972        name: Name::str("Complex.roots_of_unity_card"),
973        univ_params: vec![],
974        ty: roots_of_unity_ty(),
975    });
976    let _ = env.add(Declaration::Axiom {
977        name: Name::str("ComplexAnalysis.cauchy_riemann"),
978        univ_params: vec![],
979        ty: cauchy_riemann_ty(),
980    });
981    let _ = env.add(Declaration::Axiom {
982        name: Name::str("ComplexAnalysis.cauchy_integral_formula"),
983        univ_params: vec![],
984        ty: cauchy_integral_formula_ty(),
985    });
986    let _ = env.add(Declaration::Axiom {
987        name: Name::str("ComplexAnalysis.residue_theorem"),
988        univ_params: vec![],
989        ty: residue_theorem_ty(),
990    });
991    let _ = env.add(Declaration::Axiom {
992        name: Name::str("ComplexAnalysis.analytic_continuation"),
993        univ_params: vec![],
994        ty: analytic_continuation_ty(),
995    });
996    let _ = env.add(Declaration::Axiom {
997        name: Name::str("ComplexAnalysis.picard_little"),
998        univ_params: vec![],
999        ty: picard_little_theorem_ty(),
1000    });
1001    let _ = env.add(Declaration::Axiom {
1002        name: Name::str("ComplexAnalysis.picard_great"),
1003        univ_params: vec![],
1004        ty: picard_great_theorem_ty(),
1005    });
1006    let _ = env.add(Declaration::Axiom {
1007        name: Name::str("ComplexAnalysis.weierstrass_factorization"),
1008        univ_params: vec![],
1009        ty: weierstrass_factorization_ty(),
1010    });
1011    let _ = env.add(Declaration::Axiom {
1012        name: Name::str("ComplexAnalysis.meromorphic_riemann_sphere"),
1013        univ_params: vec![],
1014        ty: meromorphic_riemann_sphere_ty(),
1015    });
1016    let _ = env.add(Declaration::Axiom {
1017        name: Name::str("ComplexAnalysis.riemann_mapping"),
1018        univ_params: vec![],
1019        ty: riemann_mapping_theorem_ty(),
1020    });
1021    let _ = env.add(Declaration::Axiom {
1022        name: Name::str("ComplexAnalysis.mobius_group"),
1023        univ_params: vec![],
1024        ty: mobius_group_ty(),
1025    });
1026    let _ = env.add(Declaration::Axiom {
1027        name: Name::str("ComplexAnalysis.mobius_conformal"),
1028        univ_params: vec![],
1029        ty: mobius_conformal_ty(),
1030    });
1031    let _ = env.add(Declaration::Axiom {
1032        name: Name::str("ComplexAnalysis.laurent_series"),
1033        univ_params: vec![],
1034        ty: laurent_series_ty(),
1035    });
1036    let _ = env.add(Declaration::Axiom {
1037        name: Name::str("ComplexAnalysis.argument_principle"),
1038        univ_params: vec![],
1039        ty: argument_principle_ty(),
1040    });
1041    let _ = env.add(Declaration::Axiom {
1042        name: Name::str("ComplexAnalysis.rouche"),
1043        univ_params: vec![],
1044        ty: rouche_theorem_ty(),
1045    });
1046    let _ = env.add(Declaration::Axiom {
1047        name: Name::str("ComplexAnalysis.mittag_leffler"),
1048        univ_params: vec![],
1049        ty: mittag_leffler_theorem_ty(),
1050    });
1051    let _ = env.add(Declaration::Axiom {
1052        name: Name::str("ComplexAnalysis.runge"),
1053        univ_params: vec![],
1054        ty: runge_theorem_ty(),
1055    });
1056    let _ = env.add(Declaration::Axiom {
1057        name: Name::str("ComplexAnalysis.hardy_banach"),
1058        univ_params: vec![],
1059        ty: hardy_banach_ty(),
1060    });
1061    let _ = env.add(Declaration::Axiom {
1062        name: Name::str("ComplexAnalysis.nevanlinna_first"),
1063        univ_params: vec![],
1064        ty: nevanlinna_first_theorem_ty(),
1065    });
1066    let _ = env.add(Declaration::Axiom {
1067        name: Name::str("ComplexAnalysis.nevanlinna_second"),
1068        univ_params: vec![],
1069        ty: nevanlinna_second_theorem_ty(),
1070    });
1071    let _ = env.add(Declaration::Axiom {
1072        name: Name::str("ComplexAnalysis.bloch"),
1073        univ_params: vec![],
1074        ty: bloch_theorem_ty(),
1075    });
1076    let _ = env.add(Declaration::Axiom {
1077        name: Name::str("ComplexAnalysis.weierstrass_p_elliptic"),
1078        univ_params: vec![],
1079        ty: weierstrass_p_ty(),
1080    });
1081    let _ = env.add(Declaration::Axiom {
1082        name: Name::str("ComplexAnalysis.elliptic_liouville"),
1083        univ_params: vec![],
1084        ty: elliptic_liouville_ty(),
1085    });
1086    let _ = env.add(Declaration::Axiom {
1087        name: Name::str("ComplexAnalysis.modular_form_finite_dim"),
1088        univ_params: vec![],
1089        ty: modular_form_finite_dim_ty(),
1090    });
1091    let _ = env.add(Declaration::Axiom {
1092        name: Name::str("ComplexAnalysis.hartogs"),
1093        univ_params: vec![],
1094        ty: hartogs_theorem_ty(),
1095    });
1096    let _ = env.add(Declaration::Axiom {
1097        name: Name::str("ComplexAnalysis.oka"),
1098        univ_params: vec![],
1099        ty: oka_theorem_ty(),
1100    });
1101    let _ = env.add(Declaration::Axiom {
1102        name: Name::str("ComplexAnalysis.bohr"),
1103        univ_params: vec![],
1104        ty: bohr_theorem_ty(),
1105    });
1106    let _ = env.add(Declaration::Axiom {
1107        name: Name::str("ComplexAnalysis.paley_wiener"),
1108        univ_params: vec![],
1109        ty: paley_wiener_theorem_ty(),
1110    });
1111    let _ = env.add(Declaration::Axiom {
1112        name: Name::str("ComplexAnalysis.hadamard_factorization"),
1113        univ_params: vec![],
1114        ty: hadamard_factorization_ty(),
1115    });
1116    let _ = env.add(Declaration::Axiom {
1117        name: Name::str("ComplexAnalysis.schwarz_pick"),
1118        univ_params: vec![],
1119        ty: schwarz_pick_lemma_ty(),
1120    });
1121    let _ = env.add(Declaration::Axiom {
1122        name: Name::str("ComplexAnalysis.jensen_formula"),
1123        univ_params: vec![],
1124        ty: jensen_formula_ty(),
1125    });
1126    let _ = env.add(Declaration::Axiom {
1127        name: Name::str("ComplexAnalysis.phragmen_lindelof"),
1128        univ_params: vec![],
1129        ty: phragmen_lindelof_ty(),
1130    });
1131    let _ = env.add(Declaration::Axiom {
1132        name: Name::str("ComplexAnalysis.riemann_zeta_meromorphic"),
1133        univ_params: vec![],
1134        ty: riemann_zeta_meromorphic_ty(),
1135    });
1136    let _ = env.add(Declaration::Axiom {
1137        name: Name::str("ComplexAnalysis.riemann_hypothesis"),
1138        univ_params: vec![],
1139        ty: riemann_hypothesis_ty(),
1140    });
1141    Ok(())
1142}
1143/// Numerically integrate f along a circular contour centered at `center` with given `radius`.
1144/// Uses `n_points` equally spaced quadrature nodes (trapezoidal rule on the circle).
1145/// Returns the integral ∮ f(z) dz (NOT divided by 2πi).
1146#[allow(dead_code)]
1147pub fn contour_integrate_circular<F>(f: F, center: Complex, radius: f64, n_points: usize) -> Complex
1148where
1149    F: Fn(Complex) -> Complex,
1150{
1151    if n_points == 0 {
1152        return Complex::zero();
1153    }
1154    let mut sum = Complex::zero();
1155    for k in 0..n_points {
1156        let theta = 2.0 * PI * k as f64 / n_points as f64;
1157        let z = center.add(Complex::from_polar(radius, theta));
1158        let dz = Complex::from_polar(radius, theta + PI / 2.0).scale(2.0 * PI / n_points as f64);
1159        sum = sum.add(f(z).mul(dz));
1160    }
1161    sum
1162}
1163/// Discrete Fourier Transform: X[k] = Σ_{n=0}^{N-1} x[n] · e^(-2πi·k·n/N).
1164#[allow(dead_code)]
1165pub fn dft(signal: &[Complex]) -> Vec<Complex> {
1166    let n = signal.len();
1167    if n == 0 {
1168        return vec![];
1169    }
1170    (0..n)
1171        .map(|k| {
1172            (0..n)
1173                .map(|j| {
1174                    let angle = -2.0 * PI * k as f64 * j as f64 / n as f64;
1175                    signal[j].mul(Complex::from_polar(1.0, angle))
1176                })
1177                .fold(Complex::zero(), |acc, x| acc.add(x))
1178        })
1179        .collect()
1180}
1181/// Inverse Discrete Fourier Transform: x[n] = (1/N) Σ_{k=0}^{N-1} X[k] · e^(2πi·k·n/N).
1182#[allow(dead_code)]
1183pub fn idft(spectrum: &[Complex]) -> Vec<Complex> {
1184    let n = spectrum.len();
1185    if n == 0 {
1186        return vec![];
1187    }
1188    let scale = 1.0 / n as f64;
1189    (0..n)
1190        .map(|j| {
1191            (0..n)
1192                .map(|k| {
1193                    let angle = 2.0 * PI * k as f64 * j as f64 / n as f64;
1194                    spectrum[k].mul(Complex::from_polar(1.0, angle))
1195                })
1196                .fold(Complex::zero(), |acc, x| acc.add(x))
1197                .scale(scale)
1198        })
1199        .collect()
1200}
1201/// Cooley-Tukey radix-2 FFT (N must be a power of two; falls back to DFT otherwise).
1202#[allow(dead_code)]
1203pub fn fft(signal: &[Complex]) -> Vec<Complex> {
1204    let n = signal.len();
1205    if n <= 1 {
1206        return signal.to_vec();
1207    }
1208    if n & (n - 1) != 0 {
1209        return dft(signal);
1210    }
1211    let evens: Vec<Complex> = signal.iter().step_by(2).cloned().collect();
1212    let odds: Vec<Complex> = signal.iter().skip(1).step_by(2).cloned().collect();
1213    let mut e = fft(&evens);
1214    let mut o = fft(&odds);
1215    e.resize(n, Complex::zero());
1216    o.resize(n, Complex::zero());
1217    let mut result = vec![Complex::zero(); n];
1218    let half = n / 2;
1219    for k in 0..half {
1220        let twiddle = Complex::from_polar(1.0, -2.0 * PI * k as f64 / n as f64);
1221        let t = twiddle.mul(o[k]);
1222        result[k] = e[k].add(t);
1223        result[k + half] = e[k].sub(t);
1224    }
1225    result
1226}
1227/// Newton's method for finding a root of f (with derivative df), starting at z0.
1228/// Returns `Some(root)` if converged within `max_iter` iterations to within `tol`.
1229#[allow(dead_code)]
1230pub fn newton_method<F, Df>(f: F, df: Df, z0: Complex, max_iter: usize, tol: f64) -> Option<Complex>
1231where
1232    F: Fn(Complex) -> Complex,
1233    Df: Fn(Complex) -> Complex,
1234{
1235    let mut z = z0;
1236    for _ in 0..max_iter {
1237        let fz = f(z);
1238        if fz.abs() < tol {
1239            return Some(z);
1240        }
1241        let dfz = df(z);
1242        z = z.sub(fz.div(dfz)?);
1243    }
1244    if f(z).abs() < tol {
1245        Some(z)
1246    } else {
1247        None
1248    }
1249}
1250/// Check membership in the Mandelbrot set: iterate z ↦ z² + c from z = 0.
1251/// Returns `None` if c is in the set (within `max_iter`), or `Some(escape_iter)`.
1252#[allow(dead_code)]
1253pub fn mandelbrot_iter(c: Complex, max_iter: usize) -> Option<usize> {
1254    let mut z = Complex::zero();
1255    for i in 0..max_iter {
1256        if z.norm_sq() > 4.0 {
1257            return Some(i);
1258        }
1259        z = z.mul(z).add(c);
1260    }
1261    None
1262}
1263/// Render a simple ASCII Mandelbrot set for a given rectangular region.
1264/// Returns a `Vec<String>` with one row per line.
1265#[allow(dead_code)]
1266pub fn mandelbrot_ascii(
1267    re_min: f64,
1268    re_max: f64,
1269    im_min: f64,
1270    im_max: f64,
1271    width: usize,
1272    height: usize,
1273    max_iter: usize,
1274) -> Vec<String> {
1275    let chars: Vec<char> = " .:-=+*#%@".chars().collect();
1276    let n_chars = chars.len();
1277    (0..height)
1278        .map(|row| {
1279            let im = im_max - (im_max - im_min) * row as f64 / height as f64;
1280            (0..width)
1281                .map(|col| {
1282                    let re = re_min + (re_max - re_min) * col as f64 / width as f64;
1283                    let c = Complex::new(re, im);
1284                    let idx = match mandelbrot_iter(c, max_iter) {
1285                        None => n_chars - 1,
1286                        Some(i) => (i * (n_chars - 1) / max_iter).min(n_chars - 2),
1287                    };
1288                    chars[idx]
1289                })
1290                .collect()
1291        })
1292        .collect()
1293}
1294/// Sieve of Eratosthenes: returns the first `count` prime numbers.
1295#[allow(dead_code)]
1296pub fn sieve_of_eratosthenes(count: usize) -> Vec<u64> {
1297    if count == 0 {
1298        return vec![];
1299    }
1300    let limit = ((count as f64 * (count as f64).max(2.0).ln() * 1.3) as usize).max(20);
1301    let mut is_prime = vec![true; limit + 1];
1302    is_prime[0] = false;
1303    if limit >= 1 {
1304        is_prime[1] = false;
1305    }
1306    let mut i = 2usize;
1307    while i * i <= limit {
1308        if is_prime[i] {
1309            let mut j = i * i;
1310            while j <= limit {
1311                is_prime[j] = false;
1312                j += i;
1313            }
1314        }
1315        i += 1;
1316    }
1317    is_prime
1318        .iter()
1319        .enumerate()
1320        .filter(|(_, &p)| p)
1321        .map(|(i, _)| i as u64)
1322        .take(count)
1323        .collect()
1324}
1325/// Approximate the Riemann zeta function ζ(s) via the first `n_terms` of the Dirichlet series.
1326/// Converges for Re(s) > 1; use `n_terms` ≥ 1000 for reasonable accuracy.
1327#[allow(dead_code)]
1328pub fn riemann_zeta_approx(s: Complex, n_terms: usize) -> Complex {
1329    (1..=n_terms)
1330        .map(|n| {
1331            let log_n = Complex::new((n as f64).ln(), 0.0);
1332            s.neg().mul(log_n).exp()
1333        })
1334        .fold(Complex::zero(), |acc, x| acc.add(x))
1335}
1336/// Euler product approximation of ζ(s): ∏_{p prime} 1/(1 - p^{-s}) over the first `n_primes` primes.
1337#[allow(dead_code)]
1338pub fn riemann_zeta_euler_product(s: Complex, n_primes: usize) -> Complex {
1339    let primes = sieve_of_eratosthenes(n_primes);
1340    primes.iter().fold(Complex::one(), |acc, &p| {
1341        let log_p = Complex::new((p as f64).ln(), 0.0);
1342        let p_neg_s = s.neg().mul(log_p).exp();
1343        let denom = Complex::one().sub(p_neg_s);
1344        match Complex::one().div(denom) {
1345            Some(factor) => acc.mul(factor),
1346            None => acc,
1347        }
1348    })
1349}
1350#[cfg(test)]
1351mod tests {
1352    use super::*;
1353    use std::f64::consts::E;
1354    const EPS: f64 = 1e-10;
1355    #[test]
1356    fn test_complex_add() {
1357        let z = Complex::new(1.0, 2.0);
1358        let w = Complex::new(3.0, -1.0);
1359        let sum = z + w;
1360        assert!((sum.re - 4.0).abs() < EPS);
1361        assert!((sum.im - 1.0).abs() < EPS);
1362    }
1363    #[test]
1364    fn test_complex_mul() {
1365        let z = Complex::new(1.0, 2.0);
1366        let w = Complex::new(3.0, 4.0);
1367        let prod = z * w;
1368        assert!((prod.re - (-5.0)).abs() < EPS);
1369        assert!((prod.im - 10.0).abs() < EPS);
1370    }
1371    #[test]
1372    fn test_complex_conj() {
1373        let z = Complex::new(3.0, 4.0);
1374        let c = z.conj();
1375        assert!((c.re - 3.0).abs() < EPS);
1376        assert!((c.im - (-4.0)).abs() < EPS);
1377    }
1378    #[test]
1379    fn test_complex_abs() {
1380        let z = Complex::new(3.0, 4.0);
1381        assert!((z.abs() - 5.0).abs() < EPS);
1382    }
1383    #[test]
1384    fn test_complex_div() {
1385        let z = Complex::new(1.0, 0.0);
1386        let w = Complex::new(0.0, 1.0);
1387        let q = z.div(w).expect("div operation should succeed");
1388        assert!((q.re - 0.0).abs() < EPS);
1389        assert!((q.im - (-1.0)).abs() < EPS);
1390    }
1391    #[test]
1392    fn test_euler_formula() {
1393        let theta = PI;
1394        let z = Complex::new(0.0, theta).exp();
1395        assert!((z.re - (-1.0)).abs() < 1e-10);
1396        assert!(z.im.abs() < 1e-10);
1397    }
1398    #[test]
1399    fn test_euler_e_to_half_pi_i() {
1400        let z = Complex::new(0.0, PI / 2.0).exp();
1401        assert!(z.re.abs() < 1e-10);
1402        assert!((z.im - 1.0).abs() < 1e-10);
1403    }
1404    #[test]
1405    fn test_complex_exp_real() {
1406        let z = Complex::new(1.0, 0.0).exp();
1407        assert!((z.re - E).abs() < EPS);
1408        assert!(z.im.abs() < EPS);
1409    }
1410    #[test]
1411    fn test_complex_log_inverse() {
1412        let z = Complex::new(1.0, 1.0);
1413        let log_z = z.log().expect("log should succeed");
1414        let exp_log_z = log_z.exp();
1415        assert!((exp_log_z.re - z.re).abs() < EPS);
1416        assert!((exp_log_z.im - z.im).abs() < EPS);
1417    }
1418    #[test]
1419    fn test_complex_sqrt() {
1420        let z = Complex::new(-1.0, 0.0);
1421        let s = z.sqrt();
1422        assert!(s.re.abs() < EPS);
1423        assert!((s.im - 1.0).abs() < EPS);
1424    }
1425    #[test]
1426    fn test_complex_powi() {
1427        let z = Complex::i();
1428        let z2 = z.powi(2);
1429        assert!((z2.re - (-1.0)).abs() < EPS);
1430        assert!(z2.im.abs() < EPS);
1431        let z4 = z.powi(4);
1432        assert!((z4.re - 1.0).abs() < EPS);
1433        assert!(z4.im.abs() < EPS);
1434    }
1435    #[test]
1436    fn test_roots_of_unity() {
1437        let roots = Complex::roots_of_unity(4);
1438        assert_eq!(roots.len(), 4);
1439        for r in &roots {
1440            assert!((r.abs() - 1.0).abs() < EPS);
1441        }
1442        for r in &roots {
1443            let r4 = r.powi(4);
1444            assert!((r4.re - 1.0).abs() < EPS);
1445            assert!(r4.im.abs() < EPS);
1446        }
1447    }
1448    #[test]
1449    fn test_nth_roots() {
1450        let one = Complex::one();
1451        let roots = one.nth_roots(3);
1452        assert_eq!(roots.len(), 3);
1453        for r in &roots {
1454            let r3 = r.powi(3);
1455            assert!((r3.re - 1.0).abs() < EPS, "r^3 ≠ 1: {:?}", r3);
1456            assert!(r3.im.abs() < EPS, "r^3.im ≠ 0: {:?}", r3.im);
1457        }
1458    }
1459    #[test]
1460    fn test_complex_cos_sin() {
1461        let z = Complex::zero();
1462        assert!((z.cos().re - 1.0).abs() < EPS);
1463        assert!(z.sin().re.abs() < EPS);
1464        let pi_z = Complex::new(PI, 0.0);
1465        assert!((pi_z.cos().re - (-1.0)).abs() < EPS);
1466    }
1467    #[test]
1468    fn test_polar_roundtrip() {
1469        let z = Complex::new(3.0, 4.0);
1470        let (r, theta) = z.to_polar();
1471        let z2 = Complex::from_polar(r, theta);
1472        assert!((z2.re - z.re).abs() < EPS);
1473        assert!((z2.im - z.im).abs() < EPS);
1474    }
1475    #[test]
1476    fn test_sinh_cosh() {
1477        let z = Complex::new(1.0, 0.0);
1478        let c2 = z.cosh().mul(z.cosh());
1479        let s2 = z.sinh().mul(z.sinh());
1480        let diff = c2.sub(s2);
1481        assert!((diff.re - 1.0).abs() < EPS);
1482        assert!(diff.im.abs() < EPS);
1483    }
1484    #[test]
1485    fn test_asin_sin_roundtrip() {
1486        let z = Complex::new(0.5, 0.3);
1487        let sin_z = z.sin();
1488        let asin_sin_z = sin_z.asin().expect("asin should succeed");
1489        assert!((asin_sin_z.re - z.re).abs() < 1e-9);
1490        assert!((asin_sin_z.im - z.im).abs() < 1e-9);
1491    }
1492    #[test]
1493    fn test_acos_cos_roundtrip() {
1494        let z = Complex::new(0.7, 0.0);
1495        let cos_z = z.cos();
1496        let acos_cos_z = cos_z.acos().expect("acos should succeed");
1497        assert!((acos_cos_z.re - z.re).abs() < 1e-9);
1498        assert!(acos_cos_z.im.abs() < 1e-9);
1499    }
1500    #[test]
1501    fn test_atan_roundtrip() {
1502        let z = Complex::new(0.3, 0.2);
1503        let atan_z = z.atan().expect("atan should succeed");
1504        let tan_atan_z = atan_z.tan().expect("tan should succeed");
1505        assert!((tan_atan_z.re - z.re).abs() < 1e-9);
1506        assert!((tan_atan_z.im - z.im).abs() < 1e-9);
1507    }
1508    #[test]
1509    fn test_dft_idft_roundtrip() {
1510        let signal = vec![
1511            Complex::new(1.0, 0.0),
1512            Complex::new(0.0, 1.0),
1513            Complex::new(-1.0, 0.0),
1514            Complex::new(0.0, -1.0),
1515        ];
1516        let spectrum = dft(&signal);
1517        let recovered = idft(&spectrum);
1518        assert_eq!(recovered.len(), signal.len());
1519        for (a, b) in signal.iter().zip(recovered.iter()) {
1520            assert!(
1521                a.approx_eq(*b, 1e-10),
1522                "DFT/IDFT roundtrip failed: {:?} vs {:?}",
1523                a,
1524                b
1525            );
1526        }
1527    }
1528    #[test]
1529    fn test_fft_matches_dft() {
1530        let signal: Vec<Complex> = (0u32..8)
1531            .map(|k| Complex::from_polar(1.0, 2.0 * PI * k as f64 / 8.0))
1532            .collect();
1533        let dft_result = dft(&signal);
1534        let fft_result = fft(&signal);
1535        assert_eq!(dft_result.len(), fft_result.len());
1536        for (a, b) in dft_result.iter().zip(fft_result.iter()) {
1537            assert!(
1538                a.approx_eq(*b, 1e-9),
1539                "FFT/DFT mismatch: {:?} vs {:?}",
1540                a,
1541                b
1542            );
1543        }
1544    }
1545    #[test]
1546    fn test_newton_method_sqrt2() {
1547        let root = newton_method(
1548            |z| z.mul(z).sub(Complex::new(2.0, 0.0)),
1549            |z| z.scale(2.0),
1550            Complex::new(1.5, 0.0),
1551            50,
1552            1e-12,
1553        );
1554        let r = root.expect("Newton should converge");
1555        assert!((r.re - 2.0_f64.sqrt()).abs() < 1e-10);
1556        assert!(r.im.abs() < 1e-10);
1557    }
1558    #[test]
1559    fn test_newton_method_complex_root() {
1560        let root = newton_method(
1561            |z| z.mul(z).add(Complex::one()),
1562            |z| z.scale(2.0),
1563            Complex::new(0.1, 1.0),
1564            50,
1565            1e-12,
1566        );
1567        let r = root.expect("Newton should converge to i");
1568        assert!(r.re.abs() < 1e-10);
1569        assert!((r.im - 1.0).abs() < 1e-10);
1570    }
1571    #[test]
1572    fn test_mandelbrot_zero_in_set() {
1573        assert_eq!(mandelbrot_iter(Complex::zero(), 100), None);
1574    }
1575    #[test]
1576    fn test_mandelbrot_large_escape() {
1577        let result = mandelbrot_iter(Complex::new(2.5, 0.0), 100);
1578        assert!(result.is_some());
1579    }
1580    #[test]
1581    fn test_riemann_zeta_s2() {
1582        let s = Complex::new(2.0, 0.0);
1583        let zeta = riemann_zeta_approx(s, 10_000);
1584        let expected = PI * PI / 6.0;
1585        assert!((zeta.re - expected).abs() < 0.01, "ζ(2) ≈ {}", zeta.re);
1586        assert!(zeta.im.abs() < 0.01);
1587    }
1588    #[test]
1589    fn test_sieve_first_primes() {
1590        let primes = sieve_of_eratosthenes(5);
1591        assert_eq!(primes, vec![2, 3, 5, 7, 11]);
1592    }
1593    #[test]
1594    fn test_mobius_identity() {
1595        let id = MobiusTransform::identity();
1596        let z = Complex::new(2.0, 3.0);
1597        let result = id.apply(z).expect("apply should succeed");
1598        assert!(result.approx_eq(z, EPS));
1599    }
1600    #[test]
1601    fn test_mobius_compose_invert() {
1602        let f = MobiusTransform::new(
1603            Complex::one(),
1604            Complex::one(),
1605            Complex::one(),
1606            Complex::new(2.0, 0.0),
1607        )
1608        .expect("operation should succeed");
1609        let f_inv = f.invert().expect("invert should succeed");
1610        let z = Complex::new(1.0, 1.0);
1611        let round = f
1612            .apply(z)
1613            .and_then(|w| f_inv.apply(w))
1614            .expect("Complex::new should succeed");
1615        assert!(round.approx_eq(z, 1e-10));
1616    }
1617    #[test]
1618    fn test_mobius_fixed_points() {
1619        let f = MobiusTransform::new(
1620            Complex::zero(),
1621            Complex::one(),
1622            Complex::one(),
1623            Complex::zero(),
1624        )
1625        .expect("operation should succeed");
1626        let fps = f.fixed_points();
1627        assert_eq!(fps.len(), 2);
1628        for fp in &fps {
1629            let fz = f.apply(*fp).expect("apply should succeed");
1630            assert!(fz.approx_eq(*fp, 1e-10), "fixed point check: {:?}", fp);
1631        }
1632    }
1633    #[test]
1634    fn test_contour_integral_constant() {
1635        let integral = contour_integrate_circular(|_| Complex::one(), Complex::zero(), 1.0, 1024);
1636        assert!(integral.abs() < 1e-10, "∮ 1 dz ≠ 0: {:?}", integral);
1637    }
1638    #[test]
1639    fn test_build_complex_env() {
1640        let mut env = Environment::new();
1641        let _ = env.add(Declaration::Axiom {
1642            name: Name::str("Real"),
1643            univ_params: vec![],
1644            ty: type0(),
1645        });
1646        let _ = env.add(Declaration::Axiom {
1647            name: Name::str("Nat"),
1648            univ_params: vec![],
1649            ty: type0(),
1650        });
1651        let _ = env.add(Declaration::Axiom {
1652            name: Name::str("Polynomial"),
1653            univ_params: vec![],
1654            ty: arrow(type0(), type0()),
1655        });
1656        let _ = env.add(Declaration::Axiom {
1657            name: Name::str("IsEntire"),
1658            univ_params: vec![],
1659            ty: impl_pi(
1660                "alpha",
1661                type0(),
1662                arrow(arrow(complex_ty(), complex_ty()), prop()),
1663            ),
1664        });
1665        let _ = env.add(Declaration::Axiom {
1666            name: Name::str("IsBounded"),
1667            univ_params: vec![],
1668            ty: impl_pi(
1669                "alpha",
1670                type0(),
1671                arrow(arrow(complex_ty(), complex_ty()), prop()),
1672            ),
1673        });
1674        let _ = env.add(Declaration::Axiom {
1675            name: Name::str("IsConstant"),
1676            univ_params: vec![],
1677            ty: impl_pi(
1678                "alpha",
1679                type0(),
1680                arrow(arrow(complex_ty(), complex_ty()), prop()),
1681            ),
1682        });
1683        let _ = env.add(Declaration::Axiom {
1684            name: Name::str("IsHolomorphic"),
1685            univ_params: vec![],
1686            ty: arrow(arrow(complex_ty(), complex_ty()), prop()),
1687        });
1688        let _ = env.add(Declaration::Axiom {
1689            name: Name::str("ClosedCurve"),
1690            univ_params: vec![],
1691            ty: arrow(type0(), type0()),
1692        });
1693        let _ = env.add(Declaration::Axiom {
1694            name: Name::str("ContourIntegral"),
1695            univ_params: vec![],
1696            ty: arrow(
1697                arrow(complex_ty(), complex_ty()),
1698                arrow(app(cst("ClosedCurve"), complex_ty()), complex_ty()),
1699            ),
1700        });
1701        let _ = env.add(Declaration::Axiom {
1702            name: Name::str("rootsOfUnity"),
1703            univ_params: vec![],
1704            ty: arrow(nat_ty(), type0()),
1705        });
1706        let _ = env.add(Declaration::Axiom {
1707            name: Name::str("Fintype.card"),
1708            univ_params: vec![],
1709            ty: arrow(type0(), nat_ty()),
1710        });
1711        let _ = env.add(Declaration::Axiom {
1712            name: Name::str("Polynomial.degree_pos"),
1713            univ_params: vec![],
1714            ty: impl_pi(
1715                "alpha",
1716                type0(),
1717                arrow(app(cst("Polynomial"), bvar(0)), prop()),
1718            ),
1719        });
1720        let _ = env.add(Declaration::Axiom {
1721            name: Name::str("Polynomial.eval"),
1722            univ_params: vec![],
1723            ty: impl_pi(
1724                "alpha",
1725                type0(),
1726                arrow(app(cst("Polynomial"), bvar(0)), arrow(bvar(0), bvar(0))),
1727            ),
1728        });
1729        let _ = env.add(Declaration::Axiom {
1730            name: Name::str("Real.ofNat"),
1731            univ_params: vec![],
1732            ty: arrow(nat_ty(), real_ty()),
1733        });
1734        let result = build_complex_env(&mut env);
1735        assert!(result.is_ok());
1736    }
1737}
1738/// Cauchy integral formula computation (simple approximation).
1739#[allow(dead_code)]
1740pub fn cauchy_integral_approx<F>(f: F, center: C64, radius: f64, n_points: usize) -> C64
1741where
1742    F: Fn(C64) -> C64,
1743{
1744    let mut sum = C64::zero();
1745    let dt = 2.0 * std::f64::consts::PI / n_points as f64;
1746    for k in 0..n_points {
1747        let t = k as f64 * dt;
1748        let z = center.add(&C64::from_polar(radius, t));
1749        let fz = f(z);
1750        let dz = C64::new(-radius * t.sin(), radius * t.cos());
1751        sum = sum.add(&fz.mul(&dz));
1752    }
1753    let factor = C64::new(0.0, -1.0 / (2.0 * std::f64::consts::PI));
1754    let result = sum.mul(&factor);
1755    C64::new(result.re * dt, result.im * dt)
1756}