Skip to content

docs: published CPC citation, and 9j/Fano X cost corrected to O(j^3) - #53

Merged
susilehtola merged 2 commits into
mainfrom
docs/published-citation-and-complexity
Aug 27, 2026
Merged

docs: published CPC citation, and 9j/Fano X cost corrected to O(j^3)#53
susilehtola merged 2 commits into
mainfrom
docs/published-citation-and-complexity

Conversation

@susilehtola

Copy link
Copy Markdown
Owner

Two documentation commits. No code changes, so no behaviour or performance difference; 27/27 tests pass and the build is warning-free under -Wall -Wextra.

1. Cite the published CPC reference instead of the arXiv preprint

The descriptor paper has appeared as S. Lehtola, libwignernj: a reusable C/C++/Fortran/Python library for exact Wigner symbols and related coefficients, Comput. Phys. Commun. 329, 110342 (2026), doi:10.1016/j.cpc.2026.110342.

Updated everywhere the library points at its own paper: CITATION.cff (preferred-citation now carries journal/volume/start/doi), the README citation section and BibTeX snippet, docs/reference.md, CLAUDE.md, and the citation comment in every public header, the Fortran module and the Python package docstring. The arXiv identifier is kept as a secondary pointer to the preprint version. A Paper URL is added to [project.urls] in pyproject.toml.

The historical CHANGELOG entry recording when the citation was first added still names the preprint; it is left verbatim as a record of what was true at that release.

2. Correct the 9j/Fano X asymptotic cost from O(j⁴) to O(j³)

The old O(j⁴) double-counted. The 9j term count is O(j²) (an outer loop over O(j) values of the intermediate k, each running three Racah sums of O(j) terms) and each elementary bigint operation costs O(j), which multiplies to O(j³). The stated justification was wrong too: the per-k accumulators are Θ(j)-bit, not "size-O(j²)", and the three big×big products per k are O(j^1.58) under the Karatsuba path, so they never dominate the Racah sums.

Confirmed from the loop structure in src/wigner9j.c and by measurement. Timings on one core, same conditions throughout:

j = 200 j = 1000 log-log slope
3j 0.016 ms 0.338 ms 1.89
6j 0.207 ms 4.04 ms 1.85
9j 229 ms 27 540 ms 2.98

The machine was loaded, so the absolute numbers are upper bounds; the slopes are ratios and cancel the penalty.

Two dependent claims were wrong for the same reason and are corrected alongside, since fixing only the exponent would have left the page self-contradictory:

  • Bigint growth. "~j/ln 2 bits, since the LCM denominator grows as the primorial" was wrong in magnitude and mechanism. Growth is linear in j, measured at ≈9.5·j bits (6j tuple) and ≈40·j bits (9j tuple), flat to three significant figures over j = 32…2048, driven by the outer triangle coefficients where Δ² = (j!)³/(3j+1)! cancels the j ln j terms and leaves 3j log₂3 ≈ 4.75·j bits per Δ. The 6j Racah sum contributes nothing, its (z+1)! numerator making every term integral so the LCM denominator is exactly 1. The 3j sum has no such numerator factorial, so its LCM survives at Θ(j log j) bits and the 3j is strictly O(j² log j).
  • Wall-clock horizons. These followed from the wrong exponent and were orders of magnitude out at the top end: 3j/6j at j ~ 5000 listed as "minutes" against an actual few to tens of milliseconds, and 9j at j ~ 1000 as "~ hours" against an actual ~10 s. Rebuilt from the descriptor paper's benchmark data using the corrected exponents, with a note that the slopes below j ~ 200 are pre-asymptotic.

Corrected in README.md, docs/reference.md, the performance note in src/primes.h, and the wigner9j / fano_x docstrings in src/python/wignernjmodule.c.

The published paper is deliberately left untouched.

🤖 Generated with Claude Code

https://claude.ai/code/session_016b8FqBwxGBi2cuuMuuYvBg

susilehtola and others added 2 commits August 27, 2026 14:30
The descriptor paper has appeared as S. Lehtola, "libwignernj: a
reusable C/C++/Fortran/Python library for exact Wigner symbols and
related coefficients", Comput. Phys. Commun. 329, 110342 (2026),
doi:10.1016/j.cpc.2026.110342.

Updated everywhere the library points at its own paper: CITATION.cff
(preferred-citation now carries journal/volume/start/doi), the README
citation section and BibTeX snippet, docs/reference.md, CLAUDE.md, and
the citation comment in every public header, the Fortran module and the
Python package docstring.

The arXiv identifier is kept as a secondary pointer to the preprint
version, in CITATION.cff under identifiers and in the README BibTeX
entry as eprint/archivePrefix.  A Paper URL is added to
[project.urls] in pyproject.toml.

The historical CHANGELOG entry recording when the citation was first
added still names the preprint; it is left verbatim as a record of
what was true at that release.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016b8FqBwxGBi2cuuMuuYvBg
Documentation only; no code change, so no behaviour or performance
difference.

The old O(j^4) double-counted.  The 9j term count is O(j^2) -- an outer
loop over O(j) values of the intermediate k, each running three Racah
sums of O(j) terms -- and each elementary bigint operation costs O(j),
which multiplies to O(j^3).  The stated justification was wrong too:
the per-k accumulators are Theta(j)-bit, not "size-O(j^2)", and the
three big-by-big products per k are O(j^1.58) under the Karatsuba path,
so they never dominate the Racah sums.  That is also why the effective
exponent approaches 3 from below rather than sitting on it.

Confirmed from the loop structure in src/wigner9j.c (the Pass-1 and
Pass-2 k loops, the inner term loop with one mul/div/add per term, and
the per-k combination) and by measurement.  Paired timings on one core,
same conditions throughout, give log-log slopes over j = 200 -> 1000 of

  3j  0.016 ms -> 0.338 ms    slope 1.89
  6j  0.207 ms -> 4.04  ms    slope 1.85
  9j  229   ms -> 27540 ms    slope 2.98

The machine was loaded, so the absolute numbers are upper bounds; the
slopes are ratios and cancel the penalty.

Two dependent claims were wrong for the same reason and are corrected
alongside, since fixing only the exponent would have left the page
self-contradictory:

- Bigint growth.  "~j/ln 2 bits, since the LCM denominator grows as the
  primorial" was wrong in magnitude and mechanism.  Growth is linear in
  j, measured at ~9.5*j bits for the 6j tuple and ~40*j bits for the 9j
  tuple, flat to three significant figures over j = 32..2048, and it is
  driven by the outer triangle coefficients: Delta^2 = (j!)^3/(3j+1)!
  cancels the j ln j terms and leaves 3j log2(3) ~ 4.75*j bits per
  Delta.  The 6j Racah sum contributes nothing, its (z+1)! numerator
  making every term integral so the LCM denominator is exactly 1.  The
  3j sum has no such numerator factorial, so its LCM survives at
  Theta(j log j) bits and the 3j is strictly O(j^2 log j), not O(j^2).

- Wall-clock horizons.  These followed from the wrong exponent and were
  orders of magnitude out at the top end: 3j/6j at j ~ 5000 listed as
  "minutes" against an actual few to tens of milliseconds, and 9j at
  j ~ 1000 as "~ hours" against an actual ~10 s.  Rebuilt from the
  descriptor paper's benchmark data using the corrected exponents, with
  a note that the slopes below j ~ 200 (~1.3 for 3j and 6j, ~2.3 for
  9j) are pre-asymptotic, so a reader benchmarking at small j does not
  conclude the stated exponents are wrong again.

Corrected in README.md, docs/reference.md, the performance note in
src/primes.h, and the wigner9j / fano_x docstrings in
src/python/wignernjmodule.c.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016b8FqBwxGBi2cuuMuuYvBg
@codecov

codecov Bot commented Aug 27, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 94.87%. Comparing base (8976d3a) to head (41253f8).

Additional details and impacted files
@@           Coverage Diff           @@
##             main      #53   +/-   ##
=======================================
  Coverage   94.87%   94.87%           
=======================================
  Files          47       47           
  Lines        3493     3493           
  Branches      443      443           
=======================================
  Hits         3314     3314           
  Misses        165      165           
  Partials       14       14           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@susilehtola
susilehtola merged commit 529ab42 into main Aug 27, 2026
30 checks passed
@susilehtola
susilehtola deleted the docs/published-citation-and-complexity branch August 27, 2026 11:49
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.

1 participant