pub fn generator_increment<const D: usize, const DP1: usize, const DP2: usize>(
rot: Tensor<D>,
dt: Tensor<D>,
blocks: usize,
range: f64,
) -> Tensor<DP2>Expand description
The quaternion per-step rotation vector gₜ = Δₜ · range·π·tanh(‖r‖)·r̂, one
per head and quaternion block (feed it to quat_from_scaled_axis).
The magnitude — not each component — is bounded, so the axis is exactly the
direction of the projection; see bound_rotation_vector.
Unlike the abelian angle_increment, the generators are projected per
head: rot carries nheads · 3 · J channels, so every head turns about
its own data-dependent axis rather than sharing one axis and differing only
in Δ. Sharing would make the heads’ rotations a one-parameter family of
each other — the abelian path can afford that (its rotations commute, so a
per-head angle is the only freedom there is), but for a non-abelian
transition the axis is the expressive part: two heads turning about
different axes track different words, which is the whole point of having
more than one.
DP1 = D + 1, DP2 = D + 2: a sequence-shaped call (rot [b, s, h·3·J],
dt [b, s, h]) yields [b, s, h, J, 3] and a single-token call
(rot [b, h·3·J], dt [b, h]) yields [b, h, J, 3].