You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Compute the primitive F(x) = ∫ f(t) dt of an arbitrary integrand f (real, complex, or sign-changing) on its domain by intrinsically discovering — from f alone, with no externally-supplied measure, basis, or auxiliary data — the unique (up to the integration constant +C) measure dμ_f and associated orthogonal polynomial sequence (OPS) {p_n^{(f)}} such that the partial sums
F_N(x) = Σ_{n=0}^{N} c_n · p_n^{(f)}(x)
converge uniformly to F on the domain.
The construction is intrinsic to f: the only input is the integrand. The measure dμ_f is discovered, not selected. The OPS, the three-term recurrence coefficients (β_j, γ_j), the Jacobi matrix, the expansion coefficients c_n of F, and ultimately F itself, are all produced by a single Θ(M²) sweep driven by the existing MuntzPadeApproximant σ-sliding-window engine (issue #1016).
Mathematical setup
Given f on a compact (or compactified) domain D, the primitive F has its own moment sequence
m_k = ∫_D t^k · dν_F(t) k = 0, 1, 2, …
where dν_F is the unique (up to +C) measure/distribution whose moments characterize F via the Hamburger–Nevanlinna correspondence. Equivalently, the Cauchy transform of dν_F,
ĝ_F(z) = ∫_D dν_F(t) / (z − t)
is determined by f alone (one integration of f against the geometric kernel Σ t^k / z^{k+1} produces the moments m_k, term by term).
On a compact domain, the moment problem for dν_F is determinate, so dν_F is unique. The OPS {p_n^{(f)}} orthogonal w.r.t. dν_F is then unique by Gram–Schmidt. The (β_j, γ_j) of that OPS is what the σ-window machinery already in MuntzPadeApproximant computes from the moment sequence.
reduce to a finite expression in f and (β_j, γ_j) via integration by parts (F' = f is the integrand we started with — no extra data needed). The partial sums F_N converge uniformly to F on D by the standard OPS-expansion theorem upgraded by Jackson-type smoothness: F is one degree smoother than f, so its coefficients decay one power faster than the corresponding expansion of f — uniform convergence is automatic whenever f's expansion is L²-convergent, which on a compact domain is automatic for f ∈ L^1.
The signed / complex case (sign-changing f, complex-valued f) is handled identically — dν_F becomes signed or complex, the OPS exists formally via the same recurrence, and h_j ∈ ℂ instead of h_j > 0. The only new failure mode is h_j straddling zero, which is exactly the HankelDegeneracyException / PrecisionExhaustedException pair the σ engine already throws.
Architecture
One new class — call it PrimitiveByOPS (final name negotiable) — composed on top of the existing MuntzPadeApproximant σ engine. No new native code, no new SWIG, no new matrix machinery: every piece of computation is a ComplexPolynomial / Complex operation already in arb4j.
public final class PrimitiveByOPS implements ComplexFunction, AutoCloseable
{
PrimitiveByOPS(ComplexFunction f, Complex domainStart, Complex domainEnd,
Complex basePoint, int workingBits) { … }
@Override Complex evaluate(Complex x, int order, int bits, Complex result);
}
Pipeline (all driven from f alone)
Moment extraction. Compute m_k = ∫_{a..b} t^k · f(t) dt for k = 0..2M−1 to working precision. M is discovered adaptively, same ΦBound-style monotone-refinement loop as MuntzPadeApproximant.evaluate. The integration of t^k · f(t) is the only place f is touched as a callable; from this point forward everything is a finite computation on the moment sequence.
For analytic f given as an arb4j expression — moments are computable symbolically against monomials in many cases; fall back to Gauss-Legendre or Clenshaw–Curtis quadrature on the moment integrand otherwise.
For f given as a callable ComplexFunction — moments by adaptive quadrature at workingBits. The quadrature precision is the bottleneck; everything downstream is exact in the moment sequence.
σ recurrence. Hand the moment sequence to the existing σ engine. Out come (β_j, γ_j) for j = 1..M, the OPS {p_n^{(f)}} implicitly via the Jacobi matrix J = diag(β_j) + offdiag(√γ_j), and the monic OPS polynomials Q_M if needed. This is literally the code from MuntzPadeApproximant.growOne(). The plan is to factor that code out of MuntzPadeApproximant into a reusable ChebyshevRecurrenceState helper class that both MuntzPadeApproximant and PrimitiveByOPS instantiate. Internal-only refactor; the public API of MuntzPadeApproximant is unaffected.
Coefficient extraction c_n of F. Integration by parts in the OPS inner product, using F' = f:
where P̃_n is the antiderivative of p_n (a polynomial of degree n+1, expressible in the OPS basis via the (β, γ) recurrence). The boundary F(a) is the +C ambiguity — fixed by choosing the base point at which F is declared zero. F(b) is then Σ c_n · p_n(b), consistent with the expansion.
Each c_n is a finite linear combination of the moments m_k and the recurrence coefficients — Θ(n) work per coefficient, Θ(M²) total.
Clenshaw evaluation.F(x) = Σ_{n=0}^{M} c_n · p_n^{(f)}(x) evaluated by Clenshaw recurrence using (β_j, γ_j) directly — no need to ever materialize the polynomials. Θ(M) per evaluate(x, …) call.
Adaptive convergence
Same shape as MuntzPadeApproximant.evaluate: monotone-refinement loop on M, with a ΦBound-style estimator measuring |F_M(x) − F_{M−1}(x)|² / (|F_{M−1}(x) − F_{M−2}(x)| − |F_M(x) − F_{M−1}(x)|) (Aitken acceleration of the convergence rate). Stop when below 2^{−bits}.
Spectral convergence (exponential in M for analytic f) means typical M ≈ 10–30 at 128 bits, same regime as the Müntz–Padé path.
Failure modes
Inherited from the σ engine:
HankelDegeneracyException(j) — moment functional indefinite at order j for sign-changing f whose moments happen to make h_j = 0 exactly. Rare; signals the expansion has a singular pivot at that order. Caller can retry with a slightly perturbed base point or domain.
PrecisionExhaustedException(j, bits) — h_j straddles zero at working precision. Caller retries with workingBits ← 2·workingBits.
The "+C ambiguity" is not a failure mode — it's a free parameter exposed as the basePoint constructor argument.
— no measure supplied, no basis chosen, no quadrature rule selected. The integrand f and the domain go in; the primitive comes out, evaluable at any point in the domain, with the OPS / measure / Jacobi matrix discovered intrinsically.
Out of scope (for this issue)
Multi-dimensional integrands (would require multivariate OPS — separate construction).
Singular integrands at the endpoints (would require a pre-extracted Jacobi-type weight; not "intrinsic to f" anymore — separate issue if it ever comes up).
Refactor MuntzPadeApproximant to extract the σ-window + Q/P state machine into a reusable ChebyshevRecurrenceState helper. No behavior change; MuntzPadeApproximant becomes a thin client of the helper. Full test suite re-run.
Add PrimitiveByOPS with the pipeline above. Quadrature for moment extraction lives behind a small interface so it can be swapped (initial impl: adaptive Gauss-Legendre at working precision).
Add the Clenshaw evaluate path driven by (β_j, γ_j).
Add an integration test: pick f(t) = sin(t) on [0, π], compare F(π) to 2 and F(π/2) to 1; pick f(t) = e^{−t²} on [−4, 4], compare F(∞) − F(−∞) to √π; pick a sign-changing analytic f and verify uniform error below 2^{−bits} at a grid of test points.
Document in docs/ how the construction discovers dμ_f from f alone.
References
Stahl & Totik, General Orthogonal Polynomials (1992), Ch. 4 (Markov's theorem, uniform convergence of Padé convergents off the support).
Akhiezer, The Classical Moment Problem (1965), Ch. 1–2 (Hamburger / Nevanlinna correspondence; moment-problem determinacy on compact support).
Gautschi, Orthogonal Polynomials: Computation and Approximation (2004), Ch. 2 (modified Chebyshev algorithm = the σ-sliding-window engine).
Proposal
Compute the primitive
F(x) = ∫ f(t) dtof an arbitrary integrandf(real, complex, or sign-changing) on its domain by intrinsically discovering — fromfalone, with no externally-supplied measure, basis, or auxiliary data — the unique (up to the integration constant +C) measuredμ_fand associated orthogonal polynomial sequence (OPS){p_n^{(f)}}such that the partial sumsconverge uniformly to
Fon the domain.The construction is intrinsic to
f: the only input is the integrand. The measuredμ_fis discovered, not selected. The OPS, the three-term recurrence coefficients(β_j, γ_j), the Jacobi matrix, the expansion coefficientsc_nofF, and ultimatelyFitself, are all produced by a single Θ(M²) sweep driven by the existingMuntzPadeApproximantσ-sliding-window engine (issue #1016).Mathematical setup
Given
fon a compact (or compactified) domainD, the primitiveFhas its own moment sequencewhere
dν_Fis the unique (up to +C) measure/distribution whose moments characterizeFvia the Hamburger–Nevanlinna correspondence. Equivalently, the Cauchy transform ofdν_F,is determined by
falone (one integration offagainst the geometric kernelΣ t^k / z^{k+1}produces the momentsm_k, term by term).On a compact domain, the moment problem for
dν_Fis determinate, sodν_Fis unique. The OPS{p_n^{(f)}}orthogonal w.r.t.dν_Fis then unique by Gram–Schmidt. The (β_j, γ_j) of that OPS is what the σ-window machinery already inMuntzPadeApproximantcomputes from the moment sequence.The expansion coefficients of
Fin the OPS basis,reduce to a finite expression in
fand(β_j, γ_j)via integration by parts (F' = fis the integrand we started with — no extra data needed). The partial sumsF_Nconverge uniformly toFonDby the standard OPS-expansion theorem upgraded by Jackson-type smoothness:Fis one degree smoother thanf, so its coefficients decay one power faster than the corresponding expansion off— uniform convergence is automatic wheneverf's expansion is L²-convergent, which on a compact domain is automatic forf ∈ L^1.The signed / complex case (sign-changing
f, complex-valuedf) is handled identically —dν_Fbecomes signed or complex, the OPS exists formally via the same recurrence, andh_j ∈ ℂinstead ofh_j > 0. The only new failure mode ish_jstraddling zero, which is exactly theHankelDegeneracyException/PrecisionExhaustedExceptionpair the σ engine already throws.Architecture
One new class — call it
PrimitiveByOPS(final name negotiable) — composed on top of the existingMuntzPadeApproximantσ engine. No new native code, no new SWIG, no new matrix machinery: every piece of computation is aComplexPolynomial/Complexoperation already in arb4j.Pipeline (all driven from
falone)Moment extraction. Compute
m_k = ∫_{a..b} t^k · f(t) dtfork = 0..2M−1to working precision.Mis discovered adaptively, sameΦBound-style monotone-refinement loop asMuntzPadeApproximant.evaluate. The integration oft^k · f(t)is the only placefis touched as a callable; from this point forward everything is a finite computation on the moment sequence.fgiven as an arb4j expression — moments are computable symbolically against monomials in many cases; fall back to Gauss-Legendre or Clenshaw–Curtis quadrature on the moment integrand otherwise.fgiven as a callableComplexFunction— moments by adaptive quadrature atworkingBits. The quadrature precision is the bottleneck; everything downstream is exact in the moment sequence.σ recurrence. Hand the moment sequence to the existing σ engine. Out come
(β_j, γ_j)forj = 1..M, the OPS{p_n^{(f)}}implicitly via the Jacobi matrixJ = diag(β_j) + offdiag(√γ_j), and the monic OPS polynomialsQ_Mif needed. This is literally the code fromMuntzPadeApproximant.growOne(). The plan is to factor that code out ofMuntzPadeApproximantinto a reusableChebyshevRecurrenceStatehelper class that bothMuntzPadeApproximantandPrimitiveByOPSinstantiate. Internal-only refactor; the public API ofMuntzPadeApproximantis unaffected.Coefficient extraction
c_nofF. Integration by parts in the OPS inner product, usingF' = f:where
P̃_nis the antiderivative ofp_n(a polynomial of degreen+1, expressible in the OPS basis via the (β, γ) recurrence). The boundaryF(a)is the +C ambiguity — fixed by choosing the base point at whichFis declared zero.F(b)is thenΣ c_n · p_n(b), consistent with the expansion.Each
c_nis a finite linear combination of the momentsm_kand the recurrence coefficients — Θ(n) work per coefficient, Θ(M²) total.Clenshaw evaluation.
F(x) = Σ_{n=0}^{M} c_n · p_n^{(f)}(x)evaluated by Clenshaw recurrence using(β_j, γ_j)directly — no need to ever materialize the polynomials. Θ(M) perevaluate(x, …)call.Adaptive convergence
Same shape as
MuntzPadeApproximant.evaluate: monotone-refinement loop onM, with aΦBound-style estimator measuring|F_M(x) − F_{M−1}(x)|² / (|F_{M−1}(x) − F_{M−2}(x)| − |F_M(x) − F_{M−1}(x)|)(Aitken acceleration of the convergence rate). Stop when below2^{−bits}.Spectral convergence (exponential in
Mfor analyticf) means typicalM ≈ 10–30at 128 bits, same regime as the Müntz–Padé path.Failure modes
Inherited from the σ engine:
HankelDegeneracyException(j)— moment functional indefinite at orderjfor sign-changingfwhose moments happen to makeh_j = 0exactly. Rare; signals the expansion has a singular pivot at that order. Caller can retry with a slightly perturbed base point or domain.PrecisionExhaustedException(j, bits)—h_jstraddles zero at working precision. Caller retries withworkingBits ← 2·workingBits.The "+C ambiguity" is not a failure mode — it's a free parameter exposed as the
basePointconstructor argument.Net result
The user calls
— no measure supplied, no basis chosen, no quadrature rule selected. The integrand
fand the domain go in; the primitive comes out, evaluable at any point in the domain, with the OPS / measure / Jacobi matrix discovered intrinsically.Out of scope (for this issue)
f" anymore — separate issue if it ever comes up).Θ(M log² M)half-GCD recurrence path (out-of-scope for Replace Hankel bordered-inverse with Chebyshev orthogonal-polynomial recurrence (sliding-window σ-table) #1016, same reasoning here).Implementation steps
MuntzPadeApproximantto extract the σ-window + Q/P state machine into a reusableChebyshevRecurrenceStatehelper. No behavior change;MuntzPadeApproximantbecomes a thin client of the helper. Full test suite re-run.PrimitiveByOPSwith the pipeline above. Quadrature for moment extraction lives behind a small interface so it can be swapped (initial impl: adaptive Gauss-Legendre at working precision).evaluatepath driven by(β_j, γ_j).f(t) = sin(t)on[0, π], compareF(π)to2andF(π/2)to1; pickf(t) = e^{−t²}on[−4, 4], compareF(∞) − F(−∞)to√π; pick a sign-changing analyticfand verify uniform error below2^{−bits}at a grid of test points.docs/how the construction discoversdμ_ffromfalone.References
qrh.tex§9.7 (the σ recurrence as implemented inMuntzPadeApproximant, issue Replace Hankel bordered-inverse with Chebyshev orthogonal-polynomial recurrence (sliding-window σ-table) #1016).