1use oxilean_kernel::{BinderInfo, Declaration, Environment, Expr, Level, Name};
6
7use super::types::{
8 BMOData, CalderonZygmundDecomp, CalderonZygmundOperator, Convolution, FourierMultiplierOp,
9 FourierRestrictionData, FourierTransform, HardySpace, HardySpaceAtom, LittlewoodPaleySquare,
10 MaximalFunctionData, MultilinearCZData, OscillatoryIntegralData,
11};
12
13pub fn app(f: Expr, a: Expr) -> Expr {
14 Expr::App(Box::new(f), Box::new(a))
15}
16pub fn app2(f: Expr, a: Expr, b: Expr) -> Expr {
17 app(app(f, a), b)
18}
19pub fn app3(f: Expr, a: Expr, b: Expr, c: Expr) -> Expr {
20 app(app2(f, a, b), c)
21}
22pub fn cst(s: &str) -> Expr {
23 Expr::Const(Name::str(s), vec![])
24}
25pub fn prop() -> Expr {
26 Expr::Sort(Level::zero())
27}
28pub fn type0() -> Expr {
29 Expr::Sort(Level::succ(Level::zero()))
30}
31pub fn pi(bi: BinderInfo, name: &str, dom: Expr, body: Expr) -> Expr {
32 Expr::Pi(bi, Name::str(name), Box::new(dom), Box::new(body))
33}
34pub fn arrow(a: Expr, b: Expr) -> Expr {
35 pi(BinderInfo::Default, "_", a, b)
36}
37pub fn bvar(n: u32) -> Expr {
38 Expr::BVar(n)
39}
40pub fn nat_ty() -> Expr {
41 cst("Nat")
42}
43pub fn real_ty() -> Expr {
44 cst("Real")
45}
46pub fn complex_ty() -> Expr {
47 cst("Complex")
48}
49pub fn int_ty() -> Expr {
50 cst("Int")
51}
52pub fn list_ty(elem: Expr) -> Expr {
53 app(cst("List"), elem)
54}
55pub fn schwartz_space_ty() -> Expr {
60 arrow(nat_ty(), type0())
61}
62pub fn tempered_distribution_ty() -> Expr {
66 arrow(nat_ty(), type0())
67}
68pub fn lp_space_ty() -> Expr {
72 arrow(real_ty(), arrow(nat_ty(), type0()))
73}
74pub fn weak_lp_space_ty() -> Expr {
79 arrow(real_ty(), arrow(nat_ty(), type0()))
80}
81pub fn torus_space_ty() -> Expr {
85 arrow(nat_ty(), type0())
86}
87pub fn fourier_coefficient_ty() -> Expr {
91 pi(
92 BinderInfo::Default,
93 "n",
94 nat_ty(),
95 arrow(
96 app(cst("L2Space"), bvar(0)),
97 arrow(list_ty(int_ty()), complex_ty()),
98 ),
99 )
100}
101pub fn fourier_transform_ty() -> Expr {
105 pi(
106 BinderInfo::Default,
107 "n",
108 nat_ty(),
109 arrow(
110 app(cst("SchwartzSpace"), bvar(0)),
111 app(cst("SchwartzSpace"), bvar(1)),
112 ),
113 )
114}
115pub fn inverse_fourier_transform_ty() -> Expr {
119 pi(
120 BinderInfo::Default,
121 "n",
122 nat_ty(),
123 arrow(
124 app(cst("SchwartzSpace"), bvar(0)),
125 app(cst("SchwartzSpace"), bvar(1)),
126 ),
127 )
128}
129pub fn plancherel_theorem_ty() -> Expr {
134 pi(
135 BinderInfo::Default,
136 "n",
137 nat_ty(),
138 arrow(app2(cst("LpSpace"), real_ty(), bvar(0)), prop()),
139 )
140}
141pub fn fourier_inversion_theorem_ty() -> Expr {
145 arrow(nat_ty(), prop())
146}
147pub fn convolution_theorem_ty() -> Expr {
151 arrow(nat_ty(), prop())
152}
153pub fn riesz_thorin_interpolation_ty() -> Expr {
159 pi(
160 BinderInfo::Default,
161 "p0",
162 real_ty(),
163 pi(
164 BinderInfo::Default,
165 "p1",
166 real_ty(),
167 arrow(real_ty(), arrow(real_ty(), prop())),
168 ),
169 )
170}
171pub fn marcinkiewicz_interpolation_ty() -> Expr {
176 pi(
177 BinderInfo::Default,
178 "p0",
179 real_ty(),
180 arrow(real_ty(), prop()),
181 )
182}
183pub fn bounded_operator_ty() -> Expr {
187 arrow(real_ty(), arrow(real_ty(), arrow(nat_ty(), type0())))
188}
189pub fn weak_type_bound_ty() -> Expr {
193 arrow(real_ty(), arrow(real_ty(), arrow(type0(), prop())))
194}
195pub fn hilbert_transform_ty() -> Expr {
199 pi(
200 BinderInfo::Default,
201 "n",
202 nat_ty(),
203 arrow(app2(cst("LpSpace"), real_ty(), bvar(0)), prop()),
204 )
205}
206pub fn riesz_transform_ty() -> Expr {
211 arrow(nat_ty(), arrow(nat_ty(), type0()))
212}
213pub fn cz_kernel_ty() -> Expr {
218 arrow(nat_ty(), type0())
219}
220pub fn cz_operator_ty() -> Expr {
224 pi(
225 BinderInfo::Default,
226 "n",
227 nat_ty(),
228 arrow(app(cst("CZKernel"), bvar(0)), type0()),
229 )
230}
231pub fn cz_theorem_ty() -> Expr {
236 pi(
237 BinderInfo::Default,
238 "n",
239 nat_ty(),
240 arrow(app(cst("CZOperator"), bvar(0)), prop()),
241 )
242}
243pub fn t1_theorem_ty() -> Expr {
248 arrow(nat_ty(), prop())
249}
250pub fn hardy_littlewood_maximal_ty() -> Expr {
254 pi(
255 BinderInfo::Default,
256 "n",
257 nat_ty(),
258 arrow(
259 app2(cst("LpSpace"), real_ty(), bvar(0)),
260 app2(cst("LpSpace"), real_ty(), bvar(1)),
261 ),
262 )
263}
264pub fn maximal_function_weak_bound_ty() -> Expr {
269 arrow(nat_ty(), prop())
270}
271pub fn maximal_function_strong_bound_ty() -> Expr {
275 arrow(nat_ty(), arrow(real_ty(), prop()))
276}
277pub fn vitali_covering_ty() -> Expr {
282 arrow(nat_ty(), prop())
283}
284pub fn bmo_space_ty() -> Expr {
289 arrow(nat_ty(), type0())
290}
291pub fn bmo_norm_ty() -> Expr {
295 pi(
296 BinderInfo::Default,
297 "n",
298 nat_ty(),
299 arrow(app(cst("BMOSpace"), bvar(0)), real_ty()),
300 )
301}
302pub fn john_nirenberg_inequality_ty() -> Expr {
307 arrow(nat_ty(), prop())
308}
309pub fn bmo_characterization_ty() -> Expr {
313 arrow(nat_ty(), prop())
314}
315pub fn hardy_space_ty() -> Expr {
320 arrow(real_ty(), arrow(nat_ty(), type0()))
321}
322pub fn atomic_decomposition_ty() -> Expr {
327 pi(
328 BinderInfo::Default,
329 "n",
330 nat_ty(),
331 arrow(app2(cst("HardySpace"), real_ty(), bvar(0)), prop()),
332 )
333}
334pub fn fefferman_stein_duality_ty() -> Expr {
338 arrow(nat_ty(), prop())
339}
340pub fn hardy_space_lp_embedding_ty() -> Expr {
344 arrow(real_ty(), arrow(nat_ty(), prop()))
345}
346pub fn littlewood_paley_decomposition_ty() -> Expr {
351 pi(
352 BinderInfo::Default,
353 "n",
354 nat_ty(),
355 arrow(app(cst("SchwartzSpace"), bvar(0)), type0()),
356 )
357}
358pub fn square_function_ty() -> Expr {
362 pi(
363 BinderInfo::Default,
364 "n",
365 nat_ty(),
366 arrow(app2(cst("LpSpace"), real_ty(), bvar(0)), real_ty()),
367 )
368}
369pub fn littlewood_paley_inequality_ty() -> Expr {
373 arrow(real_ty(), arrow(nat_ty(), prop()))
374}
375pub fn paley_block_ty() -> Expr {
380 arrow(nat_ty(), arrow(nat_ty(), type0()))
381}
382pub fn besov_space_ty() -> Expr {
387 pi(
388 BinderInfo::Default,
389 "s",
390 real_ty(),
391 pi(
392 BinderInfo::Default,
393 "p",
394 real_ty(),
395 pi(
396 BinderInfo::Default,
397 "q",
398 real_ty(),
399 arrow(nat_ty(), type0()),
400 ),
401 ),
402 )
403}
404pub fn triebel_lizorkin_space_ty() -> Expr {
409 pi(
410 BinderInfo::Default,
411 "s",
412 real_ty(),
413 pi(
414 BinderInfo::Default,
415 "p",
416 real_ty(),
417 pi(
418 BinderInfo::Default,
419 "q",
420 real_ty(),
421 arrow(nat_ty(), type0()),
422 ),
423 ),
424 )
425}
426pub fn symbol_class_ty() -> Expr {
431 pi(
432 BinderInfo::Default,
433 "m",
434 real_ty(),
435 pi(
436 BinderInfo::Default,
437 "rho",
438 real_ty(),
439 pi(
440 BinderInfo::Default,
441 "delta",
442 real_ty(),
443 arrow(nat_ty(), type0()),
444 ),
445 ),
446 )
447}
448#[allow(clippy::too_many_arguments)]
453pub fn pseudodiff_operator_ty() -> Expr {
454 pi(
455 BinderInfo::Default,
456 "m",
457 real_ty(),
458 pi(
459 BinderInfo::Default,
460 "rho",
461 real_ty(),
462 pi(
463 BinderInfo::Default,
464 "delta",
465 real_ty(),
466 arrow(nat_ty(), type0()),
467 ),
468 ),
469 )
470}
471pub fn pseudodiff_lp_bound_ty() -> Expr {
475 arrow(real_ty(), arrow(real_ty(), arrow(nat_ty(), prop())))
476}
477pub fn microlocalization_ty() -> Expr {
482 arrow(nat_ty(), type0())
483}
484pub fn elliptic_regularity_ty() -> Expr {
488 arrow(real_ty(), arrow(nat_ty(), prop()))
489}
490pub fn hp_atom_ty() -> Expr {
493 arrow(real_ty(), arrow(nat_ty(), type0()))
494}
495pub fn hp_riesz_factorization_ty() -> Expr {
498 arrow(real_ty(), arrow(nat_ty(), prop()))
499}
500pub fn vmo_space_ty() -> Expr {
503 arrow(nat_ty(), type0())
504}
505pub fn vmo_characterization_ty() -> Expr {
508 arrow(nat_ty(), prop())
509}
510pub fn cz_decomposition_ty() -> Expr {
513 pi(
514 BinderInfo::Default,
515 "n",
516 nat_ty(),
517 arrow(app2(cst("LpSpace"), real_ty(), bvar(0)), prop()),
518 )
519}
520pub fn stopping_time_argument_ty() -> Expr {
523 arrow(nat_ty(), prop())
524}
525pub fn mihlin_multiplier_theorem_ty() -> Expr {
529 arrow(nat_ty(), prop())
530}
531pub fn hormander_multiplier_theorem_ty() -> Expr {
534 arrow(nat_ty(), prop())
535}
536pub fn paraproduct_ty() -> Expr {
540 arrow(nat_ty(), type0())
541}
542pub fn paraproduct_boundedness_ty() -> Expr {
544 arrow(nat_ty(), prop())
545}
546pub fn muckenhoupt_ap_weight_ty() -> Expr {
550 arrow(real_ty(), arrow(nat_ty(), prop()))
551}
552pub fn weighted_lp_inequality_ty() -> Expr {
555 arrow(real_ty(), arrow(nat_ty(), prop()))
556}
557pub fn two_weight_inequality_ty() -> Expr {
560 arrow(type0(), arrow(nat_ty(), prop()))
561}
562pub fn sobolev_space_weighted_ty() -> Expr {
564 pi(
565 BinderInfo::Default,
566 "s",
567 real_ty(),
568 arrow(real_ty(), arrow(nat_ty(), type0())),
569 )
570}
571pub fn compact_group_fourier_ty() -> Expr {
574 arrow(type0(), type0())
575}
576pub fn nilpotent_group_fourier_ty() -> Expr {
578 arrow(type0(), type0())
579}
580pub fn sub_riemannian_laplacian_ty() -> Expr {
583 arrow(type0(), type0())
584}
585pub fn stationary_phase_expansion_ty() -> Expr {
588 arrow(nat_ty(), prop())
589}
590pub fn van_der_corput_lemma_ty() -> Expr {
593 arrow(nat_ty(), prop())
594}
595pub fn stein_tomas_restriction_ty() -> Expr {
599 arrow(nat_ty(), prop())
600}
601pub fn fourier_restriction_ty() -> Expr {
604 arrow(nat_ty(), arrow(type0(), prop()))
605}
606pub fn weyl_law_ty() -> Expr {
609 arrow(type0(), prop())
610}
611pub fn heat_kernel_ty() -> Expr {
614 arrow(type0(), type0())
615}
616pub fn lichnerowicz_inequality_ty() -> Expr {
619 arrow(type0(), prop())
620}
621pub fn gabor_frame_ty() -> Expr {
624 arrow(nat_ty(), type0())
625}
626pub fn wavelet_frame_ty() -> Expr {
629 arrow(nat_ty(), type0())
630}
631pub fn balian_low_theorem_ty() -> Expr {
635 prop()
636}
637pub fn frame_bounds_ty() -> Expr {
640 arrow(nat_ty(), prop())
641}
642pub fn uncertainty_principle_ty() -> Expr {
645 arrow(nat_ty(), prop())
646}
647pub fn hardy_space_on_group_ty() -> Expr {
650 arrow(type0(), type0())
651}
652pub fn build_harmonic_analysis_env(env: &mut Environment) {
654 let axioms: &[(&str, Expr)] = &[
655 ("SchwartzSpace", schwartz_space_ty()),
656 ("TemperedDistribution", tempered_distribution_ty()),
657 ("LpSpace", lp_space_ty()),
658 ("WeakLpSpace", weak_lp_space_ty()),
659 ("TorusSpace", torus_space_ty()),
660 ("L2Space", arrow(nat_ty(), type0())),
661 ("FourierCoefficient", fourier_coefficient_ty()),
662 ("FourierTransform", fourier_transform_ty()),
663 ("InverseFourierTransform", inverse_fourier_transform_ty()),
664 ("PlancherelTheorem", plancherel_theorem_ty()),
665 ("FourierInversionTheorem", fourier_inversion_theorem_ty()),
666 ("ConvolutionTheorem", convolution_theorem_ty()),
667 ("RieszThorinInterpolation", riesz_thorin_interpolation_ty()),
668 (
669 "MarcinkiewiczInterpolation",
670 marcinkiewicz_interpolation_ty(),
671 ),
672 ("BoundedOperator", bounded_operator_ty()),
673 ("WeakTypeBound", weak_type_bound_ty()),
674 ("HilbertTransform", hilbert_transform_ty()),
675 ("RieszTransform", riesz_transform_ty()),
676 ("CZKernel", cz_kernel_ty()),
677 ("CZOperator", cz_operator_ty()),
678 ("CZTheorem", cz_theorem_ty()),
679 ("T1Theorem", t1_theorem_ty()),
680 ("HardyLittlewoodMaximal", hardy_littlewood_maximal_ty()),
681 ("MaximalFunctionWeakBound", maximal_function_weak_bound_ty()),
682 (
683 "MaximalFunctionStrongBound",
684 maximal_function_strong_bound_ty(),
685 ),
686 ("VitaliCovering", vitali_covering_ty()),
687 ("BMOSpace", bmo_space_ty()),
688 ("BMONorm", bmo_norm_ty()),
689 ("JohnNirenbergInequality", john_nirenberg_inequality_ty()),
690 ("BMOCharacterization", bmo_characterization_ty()),
691 ("HardySpace", hardy_space_ty()),
692 ("AtomicDecomposition", atomic_decomposition_ty()),
693 ("FeffermanSteinDuality", fefferman_stein_duality_ty()),
694 ("HardySpaceLpEmbedding", hardy_space_lp_embedding_ty()),
695 (
696 "LittlewoodPaleyDecomposition",
697 littlewood_paley_decomposition_ty(),
698 ),
699 ("SquareFunction", square_function_ty()),
700 (
701 "LittlewoodPaleyInequality",
702 littlewood_paley_inequality_ty(),
703 ),
704 ("PaleyBlock", paley_block_ty()),
705 ("BesovSpace", besov_space_ty()),
706 ("TriebelLizorkinSpace", triebel_lizorkin_space_ty()),
707 ("SymbolClass", symbol_class_ty()),
708 ("PseudodiffOperator", pseudodiff_operator_ty()),
709 ("PseudodiffLpBound", pseudodiff_lp_bound_ty()),
710 ("Microlocalization", microlocalization_ty()),
711 ("EllipticRegularity", elliptic_regularity_ty()),
712 ("IsElliptic", arrow(type0(), prop())),
713 ("IsHypoelliptic", arrow(type0(), prop())),
714 ("IsSelfAdjoint", arrow(type0(), prop())),
715 ("IsUnitary", arrow(type0(), prop())),
716 ("HasBoundedExtension", arrow(type0(), prop())),
717 ("IsWeakType11", arrow(type0(), prop())),
718 (
719 "FourierMultiplier",
720 arrow(arrow(nat_ty(), complex_ty()), type0()),
721 ),
722 ("ConvolutionKernel", arrow(nat_ty(), type0())),
723 (
724 "PrincipalValueIntegral",
725 arrow(arrow(real_ty(), real_ty()), real_ty()),
726 ),
727 (
728 "OscillatoryIntegral",
729 arrow(nat_ty(), arrow(nat_ty(), real_ty())),
730 ),
731 (
732 "StationaryPhaseMethod",
733 arrow(arrow(real_ty(), real_ty()), prop()),
734 ),
735 ("SobolevSpace", arrow(real_ty(), arrow(nat_ty(), type0()))),
736 (
737 "SobolevEmbedding",
738 arrow(real_ty(), arrow(real_ty(), arrow(nat_ty(), prop()))),
739 ),
740 ("WaveFrontSet", arrow(type0(), arrow(nat_ty(), type0()))),
741 ("HpAtom", hp_atom_ty()),
742 ("HpRieszFactorization", hp_riesz_factorization_ty()),
743 ("VMOSpace", vmo_space_ty()),
744 ("VMOCharacterization", vmo_characterization_ty()),
745 ("CZDecomposition", cz_decomposition_ty()),
746 ("StoppingTimeArgument", stopping_time_argument_ty()),
747 ("MihlinMultiplierTheorem", mihlin_multiplier_theorem_ty()),
748 (
749 "HormanderMultiplierTheorem",
750 hormander_multiplier_theorem_ty(),
751 ),
752 ("Paraproduct", paraproduct_ty()),
753 ("ParaproductBoundedness", paraproduct_boundedness_ty()),
754 ("MuckenhouptApWeight", muckenhoupt_ap_weight_ty()),
755 ("WeightedLpInequality", weighted_lp_inequality_ty()),
756 ("TwoWeightInequality", two_weight_inequality_ty()),
757 ("SobolevSpaceWeighted", sobolev_space_weighted_ty()),
758 ("CompactGroupFourier", compact_group_fourier_ty()),
759 ("NilpotentGroupFourier", nilpotent_group_fourier_ty()),
760 ("SubRiemannianLaplacian", sub_riemannian_laplacian_ty()),
761 ("StationaryPhaseExpansion", stationary_phase_expansion_ty()),
762 ("VanDerCorputLemma", van_der_corput_lemma_ty()),
763 ("SteinTomasRestriction", stein_tomas_restriction_ty()),
764 ("FourierRestriction", fourier_restriction_ty()),
765 ("WeylLaw", weyl_law_ty()),
766 ("HeatKernel", heat_kernel_ty()),
767 ("LichnerowiczInequality", lichnerowicz_inequality_ty()),
768 ("GaborFrame", gabor_frame_ty()),
769 ("WaveletFrame", wavelet_frame_ty()),
770 ("BalianLowTheorem", balian_low_theorem_ty()),
771 ("FrameBounds", frame_bounds_ty()),
772 ("UncertaintyPrinciple", uncertainty_principle_ty()),
773 ("HardySpaceOnGroup", hardy_space_on_group_ty()),
774 ];
775 for (name, ty) in axioms {
776 env.add(Declaration::Axiom {
777 name: Name::str(*name),
778 univ_params: vec![],
779 ty: ty.clone(),
780 })
781 .ok();
782 }
783}
784pub fn dft(signal: &[f64]) -> Vec<(f64, f64)> {
789 let n = signal.len();
790 if n == 0 {
791 return vec![];
792 }
793 let two_pi_over_n = 2.0 * std::f64::consts::PI / n as f64;
794 (0..n)
795 .map(|k| {
796 let (re, im) = signal
797 .iter()
798 .enumerate()
799 .fold((0.0, 0.0), |(re, im), (j, &x)| {
800 let angle = two_pi_over_n * (k * j) as f64;
801 (re + x * angle.cos(), im - x * angle.sin())
802 });
803 (re, im)
804 })
805 .collect()
806}
807pub fn idft(spectrum: &[(f64, f64)]) -> Vec<f64> {
809 let n = spectrum.len();
810 if n == 0 {
811 return vec![];
812 }
813 let two_pi_over_n = 2.0 * std::f64::consts::PI / n as f64;
814 let n_f = n as f64;
815 (0..n)
816 .map(|j| {
817 spectrum
818 .iter()
819 .enumerate()
820 .map(|(k, &(re, im))| {
821 let angle = two_pi_over_n * (k * j) as f64;
822 (re * angle.cos() - im * angle.sin()) / n_f
823 })
824 .sum()
825 })
826 .collect()
827}
828pub fn dft_l2_norm_squared(spectrum: &[(f64, f64)]) -> f64 {
830 spectrum
831 .iter()
832 .map(|(re, im)| re * re + im * im)
833 .sum::<f64>()
834 / spectrum.len() as f64
835}
836pub fn signal_l2_norm_squared(signal: &[f64]) -> f64 {
838 signal.iter().map(|&x| x * x).sum()
839}
840pub fn discrete_maximal_function(signal: &[f64]) -> Vec<f64> {
845 let n = signal.len();
846 if n == 0 {
847 return vec![];
848 }
849 (0..n)
850 .map(|i| {
851 let mut best = signal[i].abs();
852 for r in 1..=n {
853 let lo = i.saturating_sub(r);
854 let hi = (i + r).min(n - 1);
855 let window: f64 = (lo..=hi).map(|j| signal[j].abs()).sum();
856 let avg = window / (hi - lo + 1) as f64;
857 if avg > best {
858 best = avg;
859 }
860 if lo == 0 && hi == n - 1 {
861 break;
862 }
863 }
864 best
865 })
866 .collect()
867}
868pub fn discrete_bmo_seminorm(signal: &[f64]) -> f64 {
873 let n = signal.len();
874 if n <= 1 {
875 return 0.0;
876 }
877 let mut best = 0.0_f64;
878 for lo in 0..n {
879 for hi in lo..n {
880 let len = (hi - lo + 1) as f64;
881 let mean: f64 = (lo..=hi).map(|i| signal[i]).sum::<f64>() / len;
882 let osc: f64 = (lo..=hi).map(|i| (signal[i] - mean).abs()).sum::<f64>() / len;
883 if osc > best {
884 best = osc;
885 }
886 }
887 }
888 best
889}
890pub fn riesz_thorin_bound(m0: f64, m1: f64, t: f64) -> f64 {
895 m0.powf(1.0 - t) * m1.powf(t)
896}
897pub fn interpolated_exponent(p0: f64, p1: f64, t: f64) -> f64 {
899 let inv_p = (1.0 - t) / p0 + t / p1;
900 1.0 / inv_p
901}
902#[cfg(test)]
903mod tests {
904 use super::*;
905 #[test]
906 fn test_dft_constant_signal() {
907 let signal = vec![1.0, 1.0, 1.0, 1.0];
908 let spectrum = dft(&signal);
909 assert!(
910 (spectrum[0].0 - 4.0).abs() < 1e-10,
911 "DFT[0] re = {}",
912 spectrum[0].0
913 );
914 assert!(spectrum[0].1.abs() < 1e-10, "DFT[0] im = {}", spectrum[0].1);
915 for k in 1..4 {
916 let mag = (spectrum[k].0 * spectrum[k].0 + spectrum[k].1 * spectrum[k].1).sqrt();
917 assert!(mag < 1e-10, "DFT[{}] magnitude = {}", k, mag);
918 }
919 }
920 #[test]
921 fn test_plancherel_dft() {
922 let signal = vec![1.0, 2.0, 3.0, 4.0];
923 let spectrum = dft(&signal);
924 let signal_norm_sq = signal_l2_norm_squared(&signal);
925 let spectrum_norm_sq = dft_l2_norm_squared(&spectrum);
926 assert!(
927 (signal_norm_sq - spectrum_norm_sq).abs() < 1e-8,
928 "Plancherel: signal_norm² = {}, spectrum_norm² = {}",
929 signal_norm_sq,
930 spectrum_norm_sq
931 );
932 }
933 #[test]
934 fn test_idft_roundtrip() {
935 let signal = vec![1.0, -1.0, 2.0, 0.5];
936 let spectrum = dft(&signal);
937 let recovered = idft(&spectrum);
938 for (i, (&orig, rec)) in signal.iter().zip(recovered.iter()).enumerate() {
939 assert!(
940 (orig - rec).abs() < 1e-10,
941 "roundtrip mismatch at {}: {} vs {}",
942 i,
943 orig,
944 rec
945 );
946 }
947 }
948 #[test]
949 fn test_discrete_maximal_function_monotone_dominates() {
950 let signal = vec![1.0, -2.0, 3.0, -1.0, 0.5];
951 let mf = discrete_maximal_function(&signal);
952 for (i, (&x, &mx)) in signal.iter().zip(mf.iter()).enumerate() {
953 assert!(
954 mx >= x.abs() - 1e-12,
955 "M[f][{}] = {} < |f[{}]| = {}",
956 i,
957 mx,
958 i,
959 x.abs()
960 );
961 }
962 }
963 #[test]
964 fn test_bmo_seminorm_constant() {
965 let signal = vec![5.0; 8];
966 let bmo = discrete_bmo_seminorm(&signal);
967 assert!(bmo.abs() < 1e-10, "BMO of constant = {}", bmo);
968 }
969 #[test]
970 fn test_bmo_seminorm_step() {
971 let signal = vec![0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0];
972 let bmo = discrete_bmo_seminorm(&signal);
973 assert!(
974 bmo > 0.0,
975 "BMO of step function should be positive, got {}",
976 bmo
977 );
978 }
979 #[test]
980 fn test_riesz_thorin_bounds() {
981 let m0 = 2.0_f64;
982 let m1 = 8.0_f64;
983 assert!((riesz_thorin_bound(m0, m1, 0.0) - m0).abs() < 1e-10);
984 assert!((riesz_thorin_bound(m0, m1, 1.0) - m1).abs() < 1e-10);
985 let expected_half = (m0 * m1).sqrt();
986 assert!((riesz_thorin_bound(m0, m1, 0.5) - expected_half).abs() < 1e-10);
987 }
988 #[test]
989 fn test_build_harmonic_analysis_env() {
990 let mut env = Environment::new();
991 build_harmonic_analysis_env(&mut env);
992 assert!(!env.is_empty());
993 }
994 #[test]
995 fn test_hardy_space_atom_canonical() {
996 let atom = HardySpaceAtom::canonical(8, 0, 7);
997 assert!(atom.is_valid_atom(), "canonical atom should be valid");
998 }
999 #[test]
1000 fn test_hardy_space_atom_zero_mean() {
1001 let values = vec![0.25, 0.25, -0.25, -0.25];
1002 let atom = HardySpaceAtom::new(0, 3, values);
1003 assert!(atom.has_zero_mean());
1004 assert!(atom.satisfies_linfty_bound());
1005 assert!(atom.has_compact_support());
1006 assert!(atom.is_valid_atom());
1007 }
1008 #[test]
1009 fn test_hardy_space_atom_not_valid_nonzero_mean() {
1010 let values = vec![0.5, 0.5];
1011 let atom = HardySpaceAtom::new(0, 1, values);
1012 assert!(!atom.has_zero_mean());
1013 assert!(!atom.is_valid_atom());
1014 }
1015 #[test]
1016 fn test_cz_decomposition_basic() {
1017 let signal = vec![1.0, 1.0, 5.0, 1.0, 1.0];
1018 let cz = CalderonZygmundDecomp::new(signal, 2.0);
1019 assert!(cz.verify_decomposition());
1020 assert!(cz.good_part_bounded());
1021 }
1022 #[test]
1023 fn test_cz_decomposition_constant() {
1024 let signal = vec![1.0; 8];
1025 let cz = CalderonZygmundDecomp::new(signal, 2.0);
1026 assert!(cz.verify_decomposition());
1027 let g = cz.good_part();
1028 for (gi, si) in g.iter().zip(cz.signal.iter()) {
1029 assert!((gi - si).abs() < 1e-12);
1030 }
1031 }
1032 #[test]
1033 fn test_fourier_multiplier_identity() {
1034 let n = 8;
1035 let multiplier = FourierMultiplierOp::new(vec![1.0; n]);
1036 let signal = vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0];
1037 let result = multiplier.apply(&signal);
1038 for (r, s) in result.iter().zip(signal.iter()) {
1039 assert!((r - s).abs() < 1e-10, "identity: {} vs {}", r, s);
1040 }
1041 }
1042 #[test]
1043 fn test_fourier_multiplier_zero() {
1044 let n = 4;
1045 let multiplier = FourierMultiplierOp::new(vec![0.0; n]);
1046 let signal = vec![1.0, 2.0, 3.0, 4.0];
1047 let result = multiplier.apply(&signal);
1048 for &r in &result {
1049 assert!(r.abs() < 1e-10, "zero multiplier: {}", r);
1050 }
1051 }
1052 #[test]
1053 fn test_fourier_multiplier_l2_norm() {
1054 let multiplier = FourierMultiplierOp::hilbert_multiplier(8);
1055 let norm = multiplier.l2_operator_norm();
1056 assert!((norm - 1.0).abs() < 1e-12, "Hilbert norm = {}", norm);
1057 assert!(multiplier.is_l2_bounded());
1058 }
1059 #[test]
1060 fn test_littlewood_paley_square_function_trivial() {
1061 let lp = LittlewoodPaleySquare::new(vec![0.0; 8]);
1062 let sf = lp.square_function_pointwise();
1063 for &v in &sf {
1064 assert!(v.abs() < 1e-10, "zero signal SF: {}", v);
1065 }
1066 }
1067 #[test]
1068 fn test_littlewood_paley_square_function_norms() {
1069 let signal = vec![1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0];
1070 let lp = LittlewoodPaleySquare::new(signal);
1071 let (sq_norm, sig_norm, ratio) = lp.verify_lp_inequality();
1072 assert!(
1073 sig_norm > 0.0,
1074 "signal norm should be positive, got {}",
1075 sig_norm
1076 );
1077 assert!(
1078 ratio > 0.0,
1079 "LP ratio should be positive: sq={} sig={} ratio={}",
1080 sq_norm,
1081 sig_norm,
1082 ratio
1083 );
1084 }
1085 #[test]
1086 fn test_build_env_has_new_axioms() {
1087 let mut env = Environment::new();
1088 build_harmonic_analysis_env(&mut env);
1089 for name in &[
1090 "VMOSpace",
1091 "HpAtom",
1092 "MihlinMultiplierTheorem",
1093 "Paraproduct",
1094 "MuckenhouptApWeight",
1095 "SteinTomasRestriction",
1096 "WeylLaw",
1097 "GaborFrame",
1098 "WaveletFrame",
1099 "BalianLowTheorem",
1100 "UncertaintyPrinciple",
1101 ] {
1102 assert!(
1103 env.contains(&Name::str(*name)),
1104 "Missing new axiom: {}",
1105 name
1106 );
1107 }
1108 }
1109}
1110pub fn build_env() -> Environment {
1112 let mut env = Environment::new();
1113 build_harmonic_analysis_env(&mut env);
1114 env
1115}
1116#[cfg(test)]
1117mod tests_harmonic_analysis_ext {
1118 use super::*;
1119 #[test]
1120 fn test_cz_operator() {
1121 let h = CalderonZygmundOperator::hilbert_transform();
1122 assert!(h.l2_bounded);
1123 assert!(h.lp_boundedness(2.0));
1124 assert!(h.lp_boundedness(3.0));
1125 assert!(!h.lp_boundedness(1.0));
1126 assert!(h.weak_type_one_one());
1127 assert!(h.t1_theorem_condition().contains("T(1)"));
1128 }
1129 #[test]
1130 fn test_maximal_function() {
1131 let mf = MaximalFunctionData::new(1, vec![1.0, 3.0, 2.0, 4.0, 1.0]);
1132 let m2 = mf.hl_maximal_at(2, 1);
1133 assert!((m2 - 4.0).abs() < 1e-10);
1134 let weak = mf.weak_type_bound_approx(1.0);
1135 assert!((weak - 11.0).abs() < 1e-10);
1136 let lp = mf.lp_norm_estimate(2.0);
1137 assert!(lp > 0.0);
1138 }
1139 #[test]
1140 fn test_oscillatory_integral() {
1141 let oi = OscillatoryIntegralData::new("x^2", "χ", 100.0, 2);
1142 let decay = oi.stationary_phase_decay();
1143 assert!((decay - 0.01).abs() < 1e-10);
1144 let vdc = oi.van_der_corput_bound(2);
1145 assert!((vdc - 0.1).abs() < 1e-10);
1146 }
1147 #[test]
1148 fn test_fourier_restriction() {
1149 let fr = FourierRestrictionData::new("S^2", 3);
1150 assert!((fr.stein_tomas_p - 4.0).abs() < 1e-10);
1151 assert!(fr.stein_tomas_statement().contains("Stein-Tomas"));
1152 }
1153}
1154#[cfg(test)]
1155mod tests_harmonic_analysis_ext2 {
1156 use super::*;
1157 #[test]
1158 fn test_bmo_data() {
1159 let bmo = BMOData::new(vec![3.0, 3.0, 3.0]);
1160 assert!(bmo.bmo_seminorm < 1e-10);
1161 assert!(bmo.is_vmo_approx(1e-9));
1162 let bmo2 = BMOData::new(vec![1.0, 5.0, 1.0, 5.0]);
1163 assert!(bmo2.bmo_seminorm > 0.0);
1164 assert!(!bmo2.is_vmo_approx(0.1));
1165 }
1166 #[test]
1167 fn test_riesz_transform() {
1168 let r1 = CalderonZygmundOperator::riesz_transform(1, 3);
1169 assert_eq!(r1.name, "R_1");
1170 assert_eq!(r1.dimension, 3);
1171 assert!(r1.weak_type_one_one());
1172 assert!(r1.cotlar_stein_description().contains("R_1"));
1173 }
1174}
1175#[cfg(test)]
1176mod tests_harmonic_analysis_ext3 {
1177 use super::*;
1178 #[test]
1179 fn test_multilinear_cz() {
1180 let mcz = MultilinearCZData::new("T", 2);
1181 assert_eq!(mcz.m, 2);
1182 assert!(mcz.is_bounded);
1183 let r = MultilinearCZData::holder_exponent(&[2.0, 2.0]);
1184 assert!((r - 1.0).abs() < 1e-10);
1185 }
1186}