docs: published CPC citation, and 9j/Fano X cost corrected to O(j^3) - #53
Merged
Merged
Conversation
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 Report✅ All modified and coverable lines are covered by tests. 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. 🚀 New features to boost your workflow:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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-citationnow carriesjournal/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. APaperURL is added to[project.urls]inpyproject.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.cand by measurement. Timings on one core, same conditions throughout: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:
(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).Corrected in
README.md,docs/reference.md, the performance note insrc/primes.h, and thewigner9j/fano_xdocstrings insrc/python/wignernjmodule.c.The published paper is deliberately left untouched.
🤖 Generated with Claude Code
https://claude.ai/code/session_016b8FqBwxGBi2cuuMuuYvBg