Skip to content

Partially Addresses #100 - #111

Open
ryanmrichard wants to merge 5 commits into
wavefunction91:masterfrom
ryanmrichard:master
Open

Partially Addresses #100#111
ryanmrichard wants to merge 5 commits into
wavefunction91:masterfrom
ryanmrichard:master

Conversation

@ryanmrichard

Copy link
Copy Markdown

Accomplishes:

  • Script for rewriting all pre-tabulated angular grids.
  • Introduces macros to wrap the type of integers and real numbers.
  • Adds compile option to store weights as strings.
  • Adds a CI test to check the compilation option.

N.B. Conflicts with the approach in #110.

ryanmrichard and others added 5 commits August 31, 2026 12:10
The tabulated solid-angle grids are declared

    template <typename T> struct lebedev_laikov_N {
      static constexpr std::array<cartesian_pt_t<T>,N> points = {...};
      static constexpr std::array<T,N> weights = {...};
    };

`constexpr` requires a literal type, so instantiating any of these over a type
that is not literal -- an interval type wrapping boost::numeric::interval, or an
uncertainty-propagating scalar holding a map of dependencies -- fails to
compile. That is the mechanical barrier to using the library with such types.

This commit adds the machinery to store the tables in a fixed type and convert
them to the quadrature's value type on read; the tables themselves are rewritten
in a following commit.

config.hpp defines `ixx_int` and `ixx_real`, the `IXX_INT` / `IXX_REAL` macros
that denote which kind a literal is, and the `INTEGRATORXX_ENABLE_STRING_REALS`
build option. types.hpp includes it, so the macros reach every table file
through the existing `*_grids.hpp` umbrellas with no new include lines.

The split between the two kinds is integer vs. non-integer rather than exactly-
representable vs. not. Measured across all 231 tables, of 1,919,804 literals
1,913,026 are non-integral and *none* of those is exactly representable as a
double; the only exactly-representable values in the corpus are the 6,778
occurrences of 0 and +/-1 at the axis points. So integrality is the distinction
that carries information, which is what `from_integer` / `from_real` capture.
`divide_integer` covers the case of a constant that is the ratio of two
integers, so the division is the only rounding rather than being inherited from
a constant the compiler already rounded.

fp_traits is the single seam through which every operation whose meaning depends
on the value type is routed, so that supporting a new type is a matter of
specializing one class rather than auditing every quadrature. It carries only
the conversions here; the math functions arrive with the quadratures that call
them.

Under ENABLE_STRING_REALS `ixx_real` becomes a `std::string_view` and IXX_REAL
captures its argument's source text rather than a double. A double literal has
already lost precision by the time any code can inspect it, so a type more
precise than double -- or one that must bound its own error -- cannot recover
the intended value from it; carrying the decimal text lets such a type parse it
directly. The default `from_real` still parses via double, so the option is
inert until a type specializes it. It is applied to the `integratorxx` target
rather than to a directory because it changes the type of a table entry: in the
non-header-only build the library's own TUs in src/ and its consumers must agree
on what `ixx_real` is.

copy_grid, the tables' only consumer, does the conversion. It also grows a
branch for equal-weight grids, which record a point count in place of a weight
table; the Womersley tables take that form in the following commit.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Performs the rewrite of the 231 tabulated solid-angle grids to the ixx_real
literal policy: element type `T` -> `ixx_real`, every table entry wrapped in
`IXX_REAL(...)`, and the Womersley grids' computed weights replaced by the point
count they are derived from.

A script rather than a hand edit because the change touches ~1.9 million
literals, and because it is idempotent: the transformation can be replayed after
syncing tables from upstream instead of being reapplied by hand across 231
files. `--check` reports what would change without writing, so CI or a reviewer
can confirm the committed tables are what the script produces.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Generated by

    python3 scripts/retype_s2_tables.py

and reproducible from this commit's parent by re-running it; the script is
idempotent, so `--check` reports no changes against the result.

The 231 tables switch to `ixx_real` elements with every entry wrapped in
IXX_REAL, which is what lifts the literal-type requirement that `constexpr`
imposes on them. The surrounding `template <typename T>` is left in place though
T is no longer used by the table itself, so that none of the ~30 dispatch
branches in each of the four family headers has to change.

Entries whose value is integral (0 and +/-1 at the axis points) are wrapped in
IXX_REAL too, despite the rule that integral literals are spelled IXX_INT: a
std::array is homogeneous, so they must share their neighbours' element type.
They convert exactly either way.

The 125 Womersley tables did not tabulate weights at all -- they built them with
`create_array<N, T>(4.0 * M_PI / N.0)`, which is templated on T (so it breaks
for non-literal types), pre-divides in double, and materializes N identical
values. They now record only the point count, and copy_grid forms the weight as
pi times the exact rational 4/N: one rounding instead of two, correct under
ENABLE_STRING_REALS, and a true enclosure for types that bound their own error.
That reassociation moves the weight by one ulp for 29 of the 125 sizes -- it is
strictly the more accurate of the two -- and by nothing at all for the other 96.
The Lebedev-Laikov, Delley, and Ahrens-Beylkin grids are unchanged bitwise.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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