Skip to content

Enrich the tests, fix the wrapper defects they expose, and document the conventions - #158

Merged
shinaoka merged 26 commits into
mainfrom
test/enrich-coverage
Sep 25, 2026
Merged

shinaoka merged 26 commits into
mainfrom
test/enrich-coverage

Conversation

@shinaoka

@shinaoka shinaoka commented Sep 25, 2026 •

Copy link
Copy Markdown
Member

Summary

This PR does four things:

  • Tests. It brings the test suite up to the mandatory coverage of spm-agent-rules/testing.md, and runs the dormant :cinterface items (Tests tagged :cinterface do not compile against the current C_API (8 errors on main) #155) and Aqua in Pkg.test() again.
  • Oracle tests. It adds tests whose reference values do not come from libsparseir.
  • Defects. It fixes the wrapper defects the new tests exposed. Backend defects are reported upstream and pinned.
  • Documentation. It documents the conventions the code implements, with the notation shared by the sparse-ir documentation, the tutorial and the Python wrapper.

Behavior changes (user-visible)

  • Invalid parameters: these throw DomainError / ArgumentError before the C call:

    • β, ωmax, ε or Λ that is not positive and finite (Λ = 0 is now rejected too)
    • a max_size other than -1 or a positive integer
    • a kernel or SVE that does not match β ωmax
    • DLR poles outside [-ωmax, ωmax]

    Before, these gave an ErrorException, a misleading kernel-cutoff message, or a wrong basis built silently. The kernel/sve_result keyword defaults are now nothing, and the default objects are built after validation.

  • Evaluation domains: u(τ) outside [-β, β] and v(ω) outside [-ωmax, ωmax] throw DomainError. Before, this was a Rust panic (Out-of-domain τ/ω in spir_funcs_eval/spir_funcs_batch_eval and out-of-range points in spir_tau_sampling_new panic, collapsed to SPIR_INTERNAL_ERROR instead of SPIR_INVALID_ARGUMENT (core Rust + C ABI) sparse-ir-rs#266).

  • uhat: it now checks its argument:

    • a MatsubaraFreq of the other statistics throws ArgumentError
    • an integer of the wrong parity throws DomainError
    • integers are accepted (they raised FieldError)

    uhat[l], uhat[a:b], length and zeta now work; all raised MethodError before, although they were documented. The DLR gains u and uhat (its single-pole functions).

  • Input arrays: evaluate, fit, evaluate!, fit!, from_IR and to_IR accept any AbstractArray with a real or complex element type. The input is converted to Float64/ComplexF64 explicitly; before, views raised MethodError and Float32/integer input raised ArgumentError. Non-finite input and wrong lengths are reported before the call.

  • Matsubara sampling points: they must be exact integers of the right parity; 1.9 used to raise InexactError. A MatsubaraFreq of the other statistics throws ArgumentError. With positive_only=true, negative points and genuinely complex coefficients in evaluate throw ArgumentError.

  • Augmented positive_only sampling: MatsubaraSampling(AugmentedBasis(...); positive_only=true) with the default points works now. The positive-only default points of augmented bases were a truncated set followed by uninitialized memory, so the sampling either failed or, for a bosonic vertex basis, sampled silently at garbage frequencies. They are now the non-negative half of the full set, as for a plain basis.

  • Basis truncation: basis[1:n] now truncates a FiniteTempBasis to its n most significant singular values. It raised MethodError, which also broke AugmentedBasis truncation.

  • Function sets:

  • MatsubaraSampling of an AugmentedBasis: it checks its points like that of a plain basis. TauConst and TauLinear throw ArgumentError at a frequency of the other statistics; they used to raise MethodError.

  • TauConst and TauLinear are bosonic-only: TauConst{Fermionic} and TauLinear{Fermionic} throw ArgumentError, and so does augmenting a fermionic basis with them. For fermions their Matsubara values were not the Fourier transforms of their τ functions; e.g. TauConst gave 0 at every odd n, where the transform is 2i√β/(πn).

  • Augmentation instances: an instance passed to AugmentedBasis must have the basis's β, and TauConst/TauLinear a bosonic basis. MatsubaraConst takes the statistics of the basis.

    • Before, a β mismatch was accepted silently, and an instance of the other statistics failed with a MethodError from create(::Tuple, …).
    • The existing test create(MatsubaraConst(42), basis) with β = 1000 pinned the silent pass-through. It now uses the basis's β and checks that a mismatch throws.
  • Accessors: s(basis), u(basis), v(basis) and uhat(basis) work. They were documented but had no methods.

  • RegularizedBoseKernel is deprecated (Base.depwarn); LogisticKernel is the default for both statistics. Its docstring had the sign of the denominator wrong and called it fermionic.

  • DLR: MatsubaraSampling(dlr) without points uses the default points of the IR basis, as in the Python wrapper; it used to fail. A DLR on anything but a FiniteTempBasis, or an SVE of another kernel type, throws ArgumentError.

  • evaluate!/fit!: they reject an output that shares memory with the input.

  • cond with positive_only=true: it is now the condition number of the real least-squares problem that fit solves (fix(capi): spir_sampling_get_cond_num reports the condition number of the complex half matrix for positive-only Matsubara samplings, not of the real least-squares problem that fit solves sparse-ir-rs#270).

  • Local libsparseir builds (Pkg.build() with ../sparse-ir-rs, as in CI_with_latest_rust_backend) now load the bindings generated from that library's header, deps/C_API.jl.

    • Since a5d08b9 the generator wrote them there, but the package kept loading src/C_API.jl. The latest-backend CI therefore tested stale bindings against a newer library.
    • Against sparse-ir-rs main, whose spir_basis_get_default_matsus_ext takes the buffer capacity separately since sparse-ir-rs#274, this gave 7 errors.
    • default_matsubara_sampling_points(::AugmentedBasis) now calls that getter in whichever form the loaded bindings have.
  • Matsubara sampling points in any order: the C library orders them ascending.

    • MatsubaraSampling kept sampling_points in the caller's order, but evaluate/fit worked in the sorted order. Custom points given in another order therefore silently mismatched the data, for plain, positive-only, augmented and DLR bases alike.
    • The points are now passed sorted, and the data is reordered along dim, as TauSampling already follows the given order.
    • Found while fixing the tutorials; the Python fix is Keep the given order of Matsubara sampling points sparse-ir#87.
  • Docstrings: every export now has one.

    • The MatsubaraFreq docstring had the statistics labels swapped.
    • README and docs link to the v2 tutorial and sparse-ir-rs.
  • Error types: generic error(...) calls became SparseIRError (with the status), ArgumentError, DomainError or BoundsError.

Documentation

The docstrings, README, docs/src/guide.md and the docs index now state the conventions the code implements, with the notation of the new sparse-ir-doc page Notation and conventions (SpM-lab/sparse-ir-doc#5). Library code is unchanged, and src/C_API.jl (generated) is untouched.

  • Conventions now stated:
    • the parity ζ and G(τ+β) = (−1)^ζ G(τ);
    • Matsubara frequencies ν = nπ/β with the reduced frequency n, and the Fourier transform with its inverse;
    • U_l, S_l and V_l with l from 0 (basis.u[l+1] is U_l), orthonormality and the sign rule U_l(β⁻) > 0;
    • G_l = −S_l ρ_l, with ρ = A for fermions and A/tanh(βω/2) for bosons;
    • the τ domain [−β, β] with the four endpoint rules;
    • default points: the roots of U_L and V_L, and Matsubara sign changes with n = 0 in bosonic sets;
    • positive_only (n ≥ 0, G(−iν) = G(iν)*), and the DLR coefficients and functions.
  • Wrong statements fixed:
    • the DLR frequency formula held for fermions only;
    • "extrema" for the default points;
    • the SVEResult signature, and the claim that ε truncates the SVE;
    • FiniteTempBasisSet field types and getters;
    • a factorize keyword that does not exist, and l < naug in the AugmentedBasis formula;
    • Λ ≥ βωmax in the README (the code requires equality);
    • "Matsubura" and "Fredhold".
  • guide.md: rewritten for the wrapper over libsparseir.
    • The pure-Julia internals, the fabricated show output, the inverted iω formula and the "4 additional sampling frequencies" are gone.
    • All REPL outputs are regenerated with the current package.
  • Checks:
    • JuliaFormatter, typos with the CI config, and Pkg.test() (unchanged counts) all pass.
    • Documenter (non-draft) builds with only the two pre-existing git-remote warnings, and all @refs resolve.
    • The README and guide code blocks run.

Backend defects found

All were reported to SpM-lab/sparse-ir-rs. All but #273 are fixed on its main branch.

CI tests both the released libsparseir_jll and sparse-ir-rs main (CI_with_latest_rust_backend), so a pinned defect can be present on one backend and fixed on the other. The pins therefore test two states:

  • the known defect is recorded as @test_broken;
  • any other result must pass.

Once every tested backend has the fix, the broken branch can go.

Tests

  • Counts: before, 871 passed, 23 items, :julia only (runtests 8m28s). After, 17672 passed, 5 broken, 54 items (runtests 4m30s) with libsparseir_jll 0.8.4; 17677 passed with a local build of sparse-ir-rs main, as in CI_with_latest_rust_backend. Julia 1.10 and 1.13 were run on an earlier commit of this branch.
  • :cinterface: repaired; 21 call sites lacked the backend argument. Closes Tests tagged :cinterface do not compile against the current C_API (8 errors on main) #155. Their progress prints were removed and their random coefficients seeded.
  • New files: sir_testsetup.jl (SVE/basis cache), oracle_tests.jl, boundary_tests.jl and public_surface_tests.jl. The surface test also checks that every export is documented, which restored the lost LogisticKernel docstring.
  • Existing tests: @test true, #== ==# blocks and ErrorException expectations were replaced. The DLR tests now check pole-sum data at 300ε instead of a 10 % relative error.
  • Formatting: JuliaFormatter was applied to the changed files (REPOSITORY_RULES). Commit 3b59198 is formatter-only, and the later fix commits are formatted too.
  • Oracle mutation check: every broken reference must fail by at least 1e3 × atol.
O1 pole sign (tau)                       max error/atol = 3.33e7  ok
O1 statistics swapped (iv)               max error/atol = 6.67e7  ok
O1 n -> n+2 (iv)                         max error/atol = 1.05e8  ok
O2 Fourier sign                          max error/atol = 1.09e10  ok
O2 n -> n+2                              max error/atol = 1.09e10  ok
O3 u(tau) instead of u(beta - tau)       max error/atol = 6.67e7  ok
O3 Re/Im parity swapped                  max error/atol = 3.23e7  ok
O3 periodicity sign swapped              max error/atol = 2.0e10  ok
O4 DLR statistics swapped                max error/atol = 2.21e10  ok
O4 DLR pole sign                         max error/atol = 1.0e10  ok

Companion PRs: SpM-lab/sparse-ir#86 (Python, merged), SpM-lab/sparse-ir-doc#5 (notation page), SpM-lab/sparse-ir-rs#286 (#273 fix, merged).

🤖 Generated with Claude Code

shinaoka and others added 24 commits September 25, 2026 21:35
…ration items

test/spir/sir_testsetup.jl caches one SVE per (Λ, ε) and one basis per
parameter set; the DLR and integration items, which rebuilt the same
bases many times, use it. The DLR round trips are built from pole sums
and checked at 300ε instead of a 10 % relative error. aqua_tests.jl
checked the module Tensor4All and carried no tag, so it never ran.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The :cinterface items called the sampling and DLR entry points without the
GEMM backend argument, used the old name spir_kernel_domain and an old
arity of spir_sve_result_new; runtests.jl only ran :julia items, so none
of this was noticed. The calls are updated, three untagged items are
tagged, the integration item computes its SVE once, and runtests.jl now
runs every item. Closes #155.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
β, ωmax and ε are checked before the default kernel and SVE are built, so
a bad value is reported as a DomainError naming it (β < 0 used to surface
as a negative kernel cutoff, ωmax = 0 and ε < 0 as ErrorException from the
C library). Λ = 0, max_size = 0, a kernel or SVE whose cutoff does not
match β ωmax (the C library builds a wrong basis from it) and DLR poles
outside [-ωmax, ωmax] (a Rust panic, SpM-lab/sparse-ir-rs#266) are
rejected. Generic error(...) calls become status checks.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…indexable

u(τ) outside [-β, β] and v(ω) outside [-ωmax, ωmax] reached a Rust panic
(SpM-lab/sparse-ir-rs#266); they now throw DomainError. uhat knows its
statistics: a MatsubaraFreq of the other statistics throws ArgumentError,
an integer of the wrong parity DomainError, and integers are accepted
(they raised FieldError). basis.uhat[l], uhat[a:b], length(uhat) and
zeta(uhat), promised by the FiniteTempBasis docstring, raised MethodError.
The DLR gains the u and uhat of its poles, as in the Python wrapper.
Augmented functions keep their type when sliced, convert integer
Matsubara indices and no longer return Vector{Number}.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ore calling C

evaluate, fit, evaluate!, fit!, from_IR and to_IR accept any AbstractArray
with a real or complex element type and convert it to Array{Float64} or
Array{ComplexF64} before the call; views and transposes raised
MethodError and Float32 or integer input ArgumentError. Non-finite input
and a wrong length along dim are reported before the call. Matsubara
sampling points must be exact integers of the right parity (1.9 raised
InexactError), and with positive_only=true negative points and genuinely
complex coefficients in evaluate throw ArgumentError.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
O1: a single pole against its closed forms in τ and Matsubara frequency
(both statistics, β = 10 and 1000). O2: uhat against the Fourier integral
of u. O3: reflection, Re/Im parity and (anti)periodicity. O4: sign
changes, orthonormality, default-point structure and the closed forms of
the DLR functions. O5: round trips for Λ = 0.1 .. 1e5 and ε down to 1e-15.
The same checks and tolerances are in the Python suite.

The asymptotic regime of uhat (|n| ≥ 40Λ) is wrong in the backend for
l ≡ 1, 2 (mod 4) (SpM-lab/sparse-ir-rs#265); it is pinned with
@test_broken so that a backend fix reports an unexpected pass.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The table is compared with names(SparseIR) in both directions and calls
each export once with a meaningful check; the second table evaluates,
indexes, slices and differentiates u, v, uhat, the augmented functions and
the DLR functions. It replaces the isdefined-only audit item, which would
not have noticed any of the MethodErrors fixed in this branch.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… policy

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
default_matsubara_sampling_points(::AugmentedBasis; positive_only=true)
passed the point count as the point limit to
spir_basis_get_default_matsus_ext, which then wrote a truncated set and
left the rest of the undef buffer uninitialized ([0, 2, 4, 12,
16009984664321, 16009971678512] for a bosonic vertex basis).
MatsubaraSampling(AugmentedBasis(...); positive_only=true) either failed
with a misleading error or, for the bosonic vertex basis, silently sampled
at garbage frequencies. The points are now the non-negative half of the
full set, as for a plain basis.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The full-set branch of default_matsubara_sampling_points(::AugmentedBasis)
returned the raw undef buffer, trusting the C library to fill all of it.
It now starts from zeros and returns only the n_points_returned entries the
library reports, and throws SparseIRError if that count exceeds the buffer.
The current backends fill the buffer exactly, so the result is unchanged.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
_check_cutoff had been inserted between the @doc block and the struct, so
the docstring attached to nothing: ?LogisticKernel and the API reference
were empty. The helper now precedes the docstring. The public-surface test
checks that every export is documented, apart from three that never were.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- basis[1:n] truncates a FiniteTempBasis to its n most significant singular
  values (MethodError before, which also broke AugmentedBasis truncation);
  other ranges throw ArgumentError or BoundsError.
- size of u, v and uhat is a tuple, as Base.size requires (it was an Int).
- Empty selections of basis functions throw ArgumentError before the call;
  the C library panics on them (SpM-lab/sparse-ir-rs#269).
- u(x) accepts untyped vectors of real points (MethodError before).
- MatsubaraSampling of an AugmentedBasis checks its points like that of a
  plain basis: non-integers and other statistics throw ArgumentError, the
  wrong parity DomainError, negative points with positive_only
  ArgumentError, and 1e300 no longer raises InexactError.
- TauConst and TauLinear throw ArgumentError at a frequency of the other
  statistics (MethodError before).
- MatsubaraSampling of a DLR without points uses the default points of its
  IR basis, as in the Python wrapper (it failed with "sampling_points must
  not be empty"); a DLR on anything but a FiniteTempBasis throws
  ArgumentError.
- An SVE of another kernel type throws ArgumentError (MethodError before).
- evaluate! and fit! reject an output that shares memory with the input.
- cond of a positive_only MatsubaraSampling is the condition number of the
  real least-squares problem the fit solves; the C library reports that of
  the complex matrix (SpM-lab/sparse-ir-rs#270).
- The C handles are released if building a basis or DLR fails half way.
- FermionicFreq, BosonicFreq and pioverbeta are documented, and every
  export now has a docstring; docstrings say ωmax must be positive.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The :cinterface items printed progress and debug values and drew
coefficients from the unseeded global RNG; they now use seeded StableRNGs
and report nothing beyond the test results, and three commented-out lines
are removed. The integration item reports the relative error through the
failing @test instead of @info. REPOSITORY_RULES states precisely that the
references of the oracle tests, not the tests, avoid libsparseir.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The tutorial link pointed to the tutorial of sparse-ir v1, which is now
marked deprecated, and the C library links to the archived C++
libsparseir repository. They now point to
https://spm-lab.github.io/sparse-ir-tutorial-v2/ and to sparse-ir-rs,
which builds the libsparseir C API.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
TauConst{Fermionic} and TauLinear{Fermionic} were accepted, but their
Matsubara values were those of the bosonic functions, not the transforms
of their own imaginary-time forms (TauConst gave 0 at every odd frequency
instead of 2i√β/(πn)), so the tau and Matsubara columns of a fermionic
augmented basis disagreed. Both now throw ArgumentError for fermions, as
in the Python wrapper, and AugmentedBasis(fermionic basis, TauConst)
throws ArgumentError instead of MethodError. The docstrings state the
functions and their transforms.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
abstract.jl documents s(basis), u(basis), v(basis) and uhat(basis), but
the functions had no methods, so every call threw MethodError. They now
return the fields: s and v for a FiniteTempBasis, and u and uhat for a
FiniteTempBasis, an AugmentedBasis and a DiscreteLehmannRepresentation.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…#273)

RegularizedBoseKernel now calls Base.depwarn; LogisticKernel is the
default kernel for both statistics. Its docstring had the sign of the
denominator wrong and called it fermionic; it now gives the kernel in
dimensionless and physical units (irbasis paper, Chikano et al., Computer
Physics Communications 240, 181 (2019), Eqs. (1)-(3)).

For ωmax ≠ 1 libsparseir scales the singular values of a
RegularizedBoseKernel basis by ωmax^-1 instead of ωmax^+1
(SpM-lab/sparse-ir-rs#273). The new oracle item O6 compares
Σ_l U_l S_l V_l with the physical kernel at ωmax = 2 as @test_broken until
the fix is released. kernel_tests.jl checks the deprecation with
@test_deprecated.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
create(aug::AbstractAugmentation, basis) returned any instance unchanged,
so a TauConst(5.0) augmented a β = 10 basis (normalized for the wrong β,
and failing outside [-5, 5]), and an instance of the other statistics
failed with a MethodError from create(::Tuple, ...). An instance now needs
the basis's β and statistics; MatsubaraConst, which does not depend on the
statistics, takes the basis's (as the comment on MatsubaraConst(β) said).

The existing test create(MatsubaraConst(42), basis) with β = 1000 pinned
the unchecked pass-through; it now uses the basis's β and checks that the
mismatch throws.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…a fixed backend

CI runs both the released libsparseir and sparse-ir-rs main
(CI_with_latest_rust_backend). A plain @test_broken fails as an unexpected
pass on whichever backend already has a fix, so the #265 and #273 pins now
test two states: the known defect is recorded as broken (for #265 an error
above 1e3 tol, the defect gives 1e6 to 1e7; for #273 exactly the kernel
divided by ωmax²), and any other result must meet the tolerance. With the
fixed sparse-ir-rs branch the #273 check passes with an error of 2.2e-11.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The docstrings now use the notation of the sparse-ir-doc notation page
and state the conventions the code implements:

- Statistics: the parity ζ (1 fermions, 0 bosons), G(τ + β) = (-1)^ζ G(τ);
  Matsubara frequencies iν with the reduced frequency n (ν = nπ/β), the
  ordinary index m only in zeta (n = 2m + ζ); the inverse Fourier transform.
- FiniteTempBasis: U_l, S_l, V_l with l from 0 (basis.u[l+1] is U_l),
  orthonormality on [0, β] and [-ωmax, ωmax], sign U_l(β⁻) > 0, the scaling
  from the dimensionless SVE, G_l = -S_l ρ_l with ρ = A (fermions) and
  A/tanh(βω/2) (bosons), the τ domain [-β, β] with the extension and the
  endpoint rules (+0.0, β, -0.0, -β), the Fourier transform of uhat.
- LogisticKernel: the physical form, G(τ) = -∫ K ρ, G(iν) = ∫ A/(iν - ω).
- Default points: roots of U_L in (0, β) (unfolded in (-β/2, β/2]), sign
  changes of the first discarded Û_l with n = 0 in bosonic sets, DLR poles
  at the roots of V_L (not extrema). positive_only is "non-negative" and
  asserts G(-iν) = G(iν)*; the types of the Matsubara points.
- DLR: pole weights of ρ for both statistics, û_p = tanh(βω̄_p/2)/(iν - ω̄_p)
  for bosons (the old G(iv) = Σ a/(iv - w) held for fermions only),
  to_IR = -S_l Σ_p V_l(ω̄_p) c_p.
- SVEResult: the actual signature (positional ε; lmax and n_gauss are
  ignored by libsparseir), ε does not truncate the SVE.
- FiniteTempBasisSet: wn_f/wn_b are Vector{FermionicFreq}/Vector{BosonicFreq},
  ε is required, use_positive_taus, the getters are functions.
- MatsubaraSampling: drop the nonexistent factorize keyword.
- AugmentedBasis: l ≤ naug (was the 0-based l < naug), τ and n instead of x,
  which spellings and statistics are supported, default points.
- overlap: the default range [0, β] for u and [-ωmax, ωmax] for v.
- The double-double threshold is ε < 1e-8 (measured), not √eps ≈ 1.49e-8.
- Typos and leftovers: Fredholm, Matsubara, ϵ -> ε, "or None", the
  self-reference "matches SparseIR.jl signature", the period comment.

Only docstrings and comments change; src/C_API.jl (generated) is untouched.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
guide.md described the pure-Julia SparseIR 1.0.18: choose_accuracy,
CentrosymmSVE, matrices, GenericLinearAlgebra, MultiFloats and Bessels.jl,
the old show output, a factorize keyword that throws MethodError,
iω = i(2n+1)β/π, machine epsilon although ε = 1e-6 is passed, and
"4 additional sampling frequencies". It now describes the current wrapper
over libsparseir (the same SVE algorithm, done in the C library), with
the notation of the notation page: iν and the reduced frequency n, hats
only on Û_l, l from 0, U_l/S_l/V_l for the physical and u_l/s_l/v_l for
the dimensionless SVE, ε truncating the basis (L = 20) while the SVE
keeps 38 values, default points as roots and sign changes. Every REPL
output is regenerated from SparseIR 2.1.5 with libsparseir_jll 0.8.4,
the outline notes that it is REPL code (as a file its loop variables
become local), and the figures, which still carry 1-based labels, are
explained in the text.

README.md: Λ = βωmax (the code requires equality; ωmax is the basis
cutoff, not the bandwidth), U_l/S_l/V_l, G_l = -S_l ρ_l and the bosonic
weight, Julia 1.10+, the libsparseir_jll dependency, rtol as in the
guide, iν variable names. README.md and docs/src/index.md link the
notation page; index.md summarizes the main conventions.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
deps/build.jl builds ../sparse-ir-rs into deps/ and generates bindings from
its header into deps/C_API.jl (the generator writes there since a5d08b9),
but the package kept including src/C_API.jl, the bindings for
libsparseir_jll. CI_with_latest_rust_backend therefore called a newer
library through stale ccall signatures. Against sparse-ir-rs main, where
spir_basis_get_default_matsus_ext takes the buffer capacity separately
(sparse-ir-rs#274), the augmented-basis default points failed with
SPIR_INVALID_ARGUMENT (7 errors).

src/SparseIR.jl now includes deps/C_API.jl when the local library is
present, and default_matsubara_sampling_points(::AugmentedBasis) calls the
getter in whichever form the loaded bindings have. README and
REPOSITORY_RULES describe the actual behavior.

Pkg.test: 17630 passed, 5 broken with libsparseir_jll 0.8.4; 17635 passed
with a local build of sparse-ir-rs main (d8fa1d7), where the pinned #265
and #273 defects are fixed.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
shinaoka and others added 2 commits September 25, 2026 21:50
The C library orders Matsubara sampling points ascending. MatsubaraSampling
kept `sampling_points` in the caller's order but evaluate and fit worked in
the sorted order, so custom points in any other order silently mismatched
the data (plain, positive-only, augmented and DLR bases alike).

The wrapper now passes the points sorted, keeps the permutation, and
reorders the data along `dim` in evaluate/evaluate!/fit/fit!, as TauSampling
already follows the given order. Sorted (default) points take no extra work.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The docstrings said the unfolded default τ points are symmetric about 0.
For an odd number of points one of them is β/2, which has no partner, so
reversing them maps τ to -τ only for an even number; reversing the folded
default points maps τ to β - τ in every case. MatsubaraSampling now states
that its points may be given in any order.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@shinaoka
shinaoka enabled auto-merge September 25, 2026 12:51
@shinaoka
shinaoka merged commit a6cd395 into main Sep 25, 2026
17 checks passed
@shinaoka
shinaoka deleted the test/enrich-coverage branch September 25, 2026 13:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Tests tagged :cinterface do not compile against the current C_API (8 errors on main)

1 participant