Skip to content

Intrinsic primitive via discovered OPS — given only f, produce F via uniformly-convergent OPS expansion in the discovered measure dμ_f #1017

@crowlogic

Description

@crowlogic

Proposal

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.

The expansion coefficients of F in the OPS basis,

c_n = ⟨F, p_n^{(f)}⟩_{ν_F} / ⟨p_n^{(f)}, p_n^{(f)}⟩_{ν_F}

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)

  1. 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.
  2. σ 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.

  3. Coefficient extraction c_n of F. Integration by parts in the OPS inner product, using F' = f:

    c_n · h_n = ⟨F, p_n⟩ = boundary terms involving F(a), F(b)
                             + ⟨f, P̃_n⟩
    

    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.

  4. 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.

Net result

The user calls

try (PrimitiveByOPS F = new PrimitiveByOPS(f, a, b, basePoint, bits)) {
    Complex value = F.evaluate(x, 1, bits, null);   // F(x) − F(basePoint)
}

— 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)

Implementation steps

  1. 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.
  2. 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).
  3. Add the Clenshaw evaluate path driven by (β_j, γ_j).
  4. 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.
  5. 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).
  • Crowley, qrh.tex §9.7 (the σ recurrence as implemented in MuntzPadeApproximant, issue Replace Hankel bordered-inverse with Chebyshev orthogonal-polynomial recurrence (sliding-window σ-table) #1016).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions