Skip to content

refactor: template SScalar on the derivative order - #87

Merged
oberbichler merged 1 commit into
mainfrom
refactor/sscalar-order-template
Jul 27, 2026
Merged

oberbichler merged 1 commit into
mainfrom
refactor/sscalar-order-template

Conversation

@oberbichler

@oberbichler oberbichler commented Jul 27, 2026 •

Copy link
Copy Markdown
Owner

Groundwork for named second-order derivatives. On its own this changes no behaviour — it makes room for one.

What

SScalar<TScalar> becomes SScalar<TOrder, TScalar>, mirroring DDScalar, where the order is the first template parameter and the Python name carries one letter per order — DScalar and DDScalar.

The constraint is requires(TOrder == 1): second order is not implemented in this PR, so SScalar<2, double> is a clear constraint violation rather than a silent instantiation that would compute a zero Hessian.

error: constraints not satisfied for class template 'SScalar' [with TOrder = 2, TScalar = double]
note: because '2L == 1' (2 == 1) evaluated to false

Mechanical throughout: 25 template heads and 55 type uses in the header, one site in the bindings, seven in the tests. No behaviour change, which the characterization suite from #84 confirms without a single expected value being touched.

The C++ spelling changes

hyperjet::SScalar<double> becomes hyperjet::SScalar<1, double>. Putting the order first is what makes the two class templates consistent. The alternative — ordering it <TScalar, TOrder> so the old spelling keeps working — would have left the library with two different conventions for the same concept. The Python name hj.SScalar is unchanged.

Verification

  • C++ 106 test cases, 1473 assertions — Debug with -Werror
  • Python 248 passed, hj.SScalar still exposes the same 35 methods
  • clang-format --Werror clean

Where this is going

Second order is a dense triangular Hessian over the sorted names from #85 — the position of a name in that vector is the index the Hessian is laid out over. The design is settled and the groundwork done:

  • merge_names produces the union in one pass and records where each operand's names land, which is what the Hessian has to be scattered along
  • the accumulation is taken verbatim in the shape DDScalar uses, where 1473 assertions already cover it
  • all 24 second-order coefficients were extracted from the corresponding DDScalar functions rather than transcribed by hand

Not in this PR, and deliberately so. A first attempt at wiring the 29 call sites used a script that collected all regex matches up front and then replaced them sequentially; after the first replacement the later search strings no longer existed, and str.replace became a silent no-op. It reported atan2 as converted when it was not. Left unnoticed, that would have shipped functions returning a silently zero Hessian — the worst failure mode for an AD library, since it computes rather than crashes.

So the follow-up writes symbolically generated second-order expectations for all 24 functions before the conversion, so a missed one fails a test instead of nothing at all.

Mirrors DDScalar, where the order is the first template parameter and the
Python name carries one letter per order -- DScalar and DDScalar. SScalar
becomes SScalar<TOrder, TScalar>, constrained to order 1 for now since second
order is not implemented yet, so SScalar<2, double> is a clear error rather
than a silent instantiation.

Mechanical: 25 template heads and 55 type uses in the header, one site in the
bindings, seven in the tests. No behaviour change, which the characterization
suite confirms without a single expected value being touched.

This breaks hyperjet::SScalar<double> for C++ callers, who now write
hyperjet::SScalar<1, double>. Putting the order first is what makes the two
class templates consistent; the alternative, ordering it <TScalar, TOrder> to
keep the old spelling working, would have left the library with two different
conventions.
@oberbichler
oberbichler merged commit f060bab into main Jul 27, 2026
17 checks passed
@oberbichler
oberbichler deleted the refactor/sscalar-order-template branch July 27, 2026 17:18
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