Quaternion schema, conversion helpers, normalization helpers, interpolation helpers, and quaternion-derived rotation matrices.
Schema and access model
Fields
QUATERNION: empty-Tuplemarker.entries: stored component collection. Ordinary quaternion values use x, y, z, w order, with w at ordinal 3.
Ordinary numeric quaternion construction, casts, arithmetic, normalization, and interpolation return independent values. Component reads are views into entries; a mutable receiver permits writes, and an immutable receiver produces an immutable view.
Access
@
(ordinal quaternion -- ref) Returns a component view.!
(value ordinal quaternion --) Writes one component.- Ordinary four-component quaternions return 4; malformed/raw wrappers can return other counts.
Constructors and conversions
Quaternion
(entryPrototype -- quaternion) Constructs a quaternion object with four entries created from the supplied prototype.- For example,
Real32Quaternionhas four zeroReal32entries; it is notidentityQuaternion.
quaternion
(entries -- quaternion) Constructs a new wrapper around the supplied entries using their construction semantics.- The raw-entry form does not validate component count or uniformity. Quaternion arithmetic expects four compatible numeric components in x, y, z, w order.
- It also accepts a recognized 3×3 matrix of matching real components and converts it to a quaternion. Supply a rotation matrix; orthogonality and normalization are not validated.
- Other shapes fall back to the raw entries wrapper, not to a general matrix conversion. See the value-ownership rule.
axisAngleQuaternion
(axisAngle -- quaternion) Constructs a quaternion from an axis and angle.- Takes
(axisX axisY axisZ angle)with compatible real component schemas; angle is in radians. - Returns
(axisX*sin(angle/2), axisY*sin(angle/2), axisZ*sin(angle/2), cos(angle/2)). - Does not normalize the axis. Supply a unit axis for a unit rotation quaternion; use
rotationQuaternionfor a three-component rotation vector.
identityQuaternion
(entry -- quaternion) Constructs an identity quaternion in the entry schema.- Returns components
(0,0,0,1).
matrix
(quaternion -- matrix) Converts a quaternion to three rows of three components.- Uses the row-vector convention:
vector matrix *applies the rotation. A unit quaternion is required for the usual rotation-matrix guarantee; matrix does not normalize it. - For components
(x,y,z,w), the rows are:
(1-2y^2-2z^2, 2xy+2zw, 2xz-2yw)
(2xy-2zw, 1-2x^2-2z^2, 2yz+2xw)
(2xz+2yw, 2yz-2xw, 1-2x^2-2y^2)
quaternionCast
(quaternion schema -- quaternion) Constructs entries in the supplied numeric target schema.vector
(quaternion -- vector) Returns an independent component collection.rotationQuaternion
(rotation -- quaternion)
(rotation threshold -- quaternion) Converts a three-component rotation vector to a quaternion.- The vector's length is the rotation angle in radians. The explicit threshold must be real and is cast to the rotation component schema; the default is
1e-12. - Returns identity when squaredLength(rotation) is strictly less than threshold². Otherwise normalizes the vector and uses its length as the axis-angle angle. Equality takes the conversion path.
- A zero threshold does not protect a zero vector from division by zero.
Algebraic operations
*
(left right -- quaternion) Scales a quaternion or composes two quaternions.- Supports
(quaternion scalar -- quaternion),(scalar quaternion -- quaternion), and(q0 q1 -- quaternion). A scalar must match the component schema; quaternion operands need compatible matching component schemas. No implicit cross-schema conversion is supplied. - Quaternion multiplication composes the row-vector orientations in operand order: q0's rotation followed by q1's. In conventional Hamilton-product notation its components equal q1 ⊗ q0.
- Follows the value-ownership rule.
+
(left right -- quaternion) Adds quaternion components.- Adds components pairwise and requires compatible quaternion component schemas. The result uses that component schema and follows the value-ownership rule.
conj
(quaternion -- quaternion) Returns (x, y, z, -w), the negative of the usual quaternion conjugate.- For a unit quaternion it represents the inverse orientation, since opposite quaternion signs represent the same rotation.
- Follows the value-ownership rule.
dot
(left right -- value) Returns the component dot product.- Requires compatible quaternion components and returns the component numeric schema.
squaredLength
(quaternion -- value) Returns the squared Euclidean length in the component numeric schema.unit
(quaternion -- quaternion) Divides quaternion components by their Euclidean norm.- Requires real components and does not guard a zero norm. A runtime zero norm can produce NaN components.
unitChecked
(quaternion -- quaternion) Normalizes or returns identity below the default threshold.- Uses threshold
1e-6cast to the quaternion component schema. SeeunitCheckedWithThresholdfor the comparison and failure rules.
unitCheckedWithThreshold
(quaternion threshold -- quaternion) Normalizes or returns identity using an explicit threshold.- Requires real quaternion components and a threshold with the same real schema.
- Returns identity only when squaredLength is strictly less than threshold²; equality takes normalization. The threshold is squared, so its sign does not change the comparison. Use a positive nonzero threshold to protect a zero quaternion.
- A runtime zero norm can produce NaN components.
Interpolation and stabilization
Bare Quaternion interpolation requires matching real component schemas; fraction and explicit epsilon must have that schema. Fractions are not clamped to [0,1]; values outside it extrapolate on the interpolating path.
nlerp
(q0 q1 fraction -- quaternion) Linearly blends two quaternions and applies checked normalization.- Flips the copied q1 when dot(q0,q1) is negative, linearly blends the entries, and applies
unitChecked. Neither input is changed. - Follows the value-ownership rule.
slerp
(q0 q1 fraction -- quaternion) Interpolates unit quaternions with spherical weights and default epsilon.- Adjusts the sign of q1 when dot(q0,q1) is negative, then uses spherical weights unless the adjusted dot product is greater than 1 − epsilon.
- Expects unit input quaternions, does not generally normalize its returned quaternion, and uses default epsilon
1e-6in the fraction schema. - Follows the value-ownership rule.
Known issue: for nearly parallel inputs (sign-adjusted dot above 1 − epsilon) the sign-adjusted second quaternion is returned without interpolation for every fraction, so fraction 0 need not return the first.
slerpWithEpsilon
(q0 q1 fraction epsilon -- quaternion) Interpolates unit quaternions with an explicit epsilon.- Uses the same sign choice and spherical path as
slerp. The explicit epsilon must match the real component schema, and positive epsilon is required for ordinary use. - With identical inputs and epsilon 0, the spherical-weight calculation can produce NaN. The near-dot behavior is described in the slerp known-issue note.
- Follows the value-ownership rule.
Examples
Schema access
"Quaternion.fieldCount" use
"Quaternion.identityQuaternion" use
"control" use
{} () {} [
Real32 identityQuaternion fieldCount printStack _:;
] "main" exportFunction
Expected Output During Compilation
4
Zero-angle construction
"Quaternion.axisAngleQuaternion" use
"control" use
{} () {} [
(0.0r32 0.0r32 1.0r32 0.0r32) axisAngleQuaternion printStack _:;
] "main" exportFunction
Expected Output During Compilation
{
QUATERNION: ();
entries: (0.0r32 0.0r32 0.0r32 1.0r32);
}
Matrix conversion
"Quaternion.identityQuaternion" use
"Quaternion.matrix" use
"control" use
{} () {} [
q: Real32 identityQuaternion;
q matrix printStack _:;
] "main" exportFunction
Expected Output During Compilation
((1.0r32 0.0r32 0.0r32) (0.0r32 1.0r32 0.0r32) (0.0r32 0.0r32 1.0r32))
Checked normalization fallback
"Quaternion.quaternion" use
"Quaternion.unitChecked" use
"control" use
{} () {} [
q: (0.0r32 0.0r32 0.0r32 0.0r32) quaternion;
q unitChecked printStack _:;
] "main" exportFunction
Expected Output During Compilation
{
QUATERNION: ();
entries: (0.0r32 0.0r32 0.0r32 1.0r32);
}
Runtime matrix check
"Quaternion.identityQuaternion" use
"Quaternion.matrix" use
"String" use
"algebra" use
"control" use
{} Int32 {} [
q: Real32 identityQuaternion;
m: q matrix;
expected: ((1.0r32 0.0r32 0.0r32) (0.0r32 1.0r32 0.0r32) (0.0r32 0.0r32 1.0r32));
m expected = print
LF print
0
] "main" exportFunction
Expected Output
TRUE