Class WireMath
The codec arithmetic of 03-wire-protocol § 12 (decisions W1–W10): quantization, normalized values, angles, smallest-three quaternions, half floats and low-bit ticks, written so that C#, the TypeScript SDK and the engine produce bit-identical integer codes and bit-identical decoded doubles.
public static class WireMath
- Inheritance
-
WireMath
- Inherited Members
Remarks
The rules that make that true (W1). All arithmetic is binary64: a float32 input is widened first (exact) and a result is narrowed only after
decoding. Ties round half away from zero — never Round(double)'s default to-even, never floor(x + 0.5). Values are clamped in
double before any integer conversion. Only + − × ÷, Sqrt(double), Floor(double), Abs(double) and
comparisons appear; powers of two come from Pow2(int), built by doubling, never from Pow(double, double). Nothing here may call
FusedMultiplyAdd(double, double, double) or a MultiplyAddEstimate: a fused result differs in the last bit from the TypeScript one.
Operators evaluate left to right, one IEEE operation each, exactly as the formulas in § 12 are written. Reordering a product "for speed" changes the last bit and breaks the golden vectors — that is the point of having them.
Fields
CanonicalNaN
The one NaN a decoder produces: bits 0x7FF8000000000000. JavaScript has a single observable NaN, so a decoded NaN that kept its sign or payload
could never be bit-exact across languages. NaN is not it — its sign bit is set.
public static readonly double CanonicalNaN
Field Value
Sqrt1Over2
√½, identical to TypeScript's Math.SQRT1_2.
public static readonly double Sqrt1Over2
Field Value
Tau
2π, as C#'s Tau and TypeScript's 2 * Math.PI both spell it.
public const double Tau = 6.283185307179586
Field Value
Methods
CanonicalizeNaN(double)
Replaces any NaN with CanonicalNaN.
public static double CanonicalizeNaN(double value)
Parameters
valuedoubleA decoded value.
Returns
- double
The value, or the canonical NaN.
DecodeAngle(int, int)
Decodes an angle: (q × 2π) / 2ᵇ.
public static double DecodeAngle(int q, int bits)
Parameters
Returns
- double
Radians in [−π, π).
DecodeHalf(ushort)
Decodes IEEE half bits, widened exactly.
public static double DecodeHalf(ushort bits)
Parameters
bitsushortThe half's bits.
Returns
- double
The value; every NaN pattern decodes as CanonicalNaN.
DecodeQuant(uint, double, double, int)
Decodes a quant code: min + q × step. Never clamps.
public static double DecodeQuant(uint q, double min, double max, int bits)
Parameters
quintThe code.
mindoubleThe declared minimum.
maxdoubleThe declared maximum.
bitsint8, 16, 24 or 32.
Returns
- double
The value, in [min, max − step].
DecodeQuantWithStep(uint, double, double)
Decodes a quant code with its step precomputed by QuantStep(double, double, int): the same operations, so the same bits.
public static double DecodeQuantWithStep(uint q, double min, double step)
Parameters
Returns
- double
The value.
DecodeQuat3(uint, Span<double>)
Decodes a smallest-three rotation into xyzw.
public static void DecodeQuat3(uint bits, Span<double> xyzw)
Parameters
DecodeSnorm(int, int)
Decodes a snorm: max(q / (2ᵇ⁻¹ − 1), −1).
public static double DecodeSnorm(int q, int bits)
Parameters
Returns
- double
A value in [−1, 1]; −1, 0 and 1 exact.
DecodeTickLo(ushort, uint)
Rebuilds an absolute tick from its low 16 bits against the frame's tick, assuming it is in the past and less than 2¹⁶ ticks old.
public static uint DecodeTickLo(ushort low, uint frameTick)
Parameters
Returns
- uint
The absolute tick.
DecodeUnorm(uint, int)
Decodes a unorm: q / (2ᵇ − 1) — a division, not a multiplication by the reciprocal, which differs in the last bit.
public static double DecodeUnorm(uint q, int bits)
Parameters
Returns
- double
A value in [0, 1]; 0 and 1 exact.
DecodeVec(int, double, int)
Decodes one vec component; the code −2ᵇ⁻¹ reads as −(2ᵇ⁻¹ − 1).
public static double DecodeVec(int q, double scale, int bits)
Parameters
Returns
- double
The value.
DecodeVel(int, double, int, int)
Decodes one vel axis to world units per tick: (q × posStep) / quantaDiv.
public static double DecodeVel(int q, double posStep, int quantaDiv, int bits)
Parameters
qintThe signed code.
posStepdoubleThe linked position codec's step on this axis.
quantaDivintThe divisor.
bitsint8, 16, 24 or 32.
Returns
- double
Displacement per tick.
EncodeAngle(double, int)
Encodes an angle as a two's-complement code over [−π, π).
public static int EncodeAngle(double theta, int bits)
Parameters
thetadoubleRadians; non-finite values, and values whose code would exceed 2⁵³ in magnitude, encode as 0.
bitsint8, 16, 24 or 32.
Returns
- int
The signed code, in [−2ᵇ⁻¹, 2ᵇ⁻¹).
EncodeHalf(double)
Converts a double to IEEE half bits directly (ties to even, overflow to infinity), with NaN canonicalized to 0x7E00.
public static ushort EncodeHalf(double value)
Parameters
valuedoubleThe value, in its source precision.
Returns
- ushort
The half's bits.
EncodeQuant(double, double, double, int)
Encodes a quant value (or one pos axis) over [min, max) at bits bits: step = (max − min) / 2ᵇ.
public static uint EncodeQuant(double v, double min, double max, int bits)
Parameters
vdoubleThe value; NaN, −∞ and anything below min encode as 0, anything at or above max − step/2 clamps to the top code.
mindoubleThe declared minimum (inclusive).
maxdoubleThe declared maximum (exclusive).
bitsint8, 16, 24 or 32.
Returns
- uint
The code, in [0, 2ᵇ − 1].
EncodeQuat3(double, double, double, double)
Encodes a rotation as smallest-three in 32 bits: index in bits 0–1, then three 10-bit signed components, ascending axis order.
public static uint EncodeQuat3(double x, double y, double z, double w)
Parameters
Returns
- uint
The 32-bit code.
EncodeSingle(double)
The single-precision bits a value encodes to: narrowing ties to even, NaN canonicalized to 0x7FC00000.
public static uint EncodeSingle(double value)
Parameters
valuedoubleThe value.
Returns
- uint
The single's bits.
EncodeSnorm(double, int)
Encodes a snorm: q = rha(clamp(v, −1, 1) × (2ᵇ⁻¹ − 1)).
public static int EncodeSnorm(double v, int bits)
Parameters
Returns
- int
The signed code.
EncodeUnorm(double, int)
Encodes a unorm: q = rhu(v × (2ᵇ − 1)), clamped to [0, 2ᵇ − 1].
public static uint EncodeUnorm(double v, int bits)
Parameters
Returns
- uint
The code.
EncodeVec(double, double, int)
Encodes one vec component: scale is one step; signed, clamped symmetrically to ±(2ᵇ⁻¹ − 1).
public static int EncodeVec(double v, double scale, int bits)
Parameters
Returns
- int
The signed code.
EncodeVel(double, double, int, int)
Encodes one vel axis: displacement per tick in units of the axis' position step ÷ quantaDiv, signed, symmetric clamp.
public static int EncodeVel(double d, double posStep, int quantaDiv, int bits)
Parameters
ddoubleDisplacement per tick, in world units; NaN encodes as 0.
posStepdoubleThe linked position codec's step on this axis.
quantaDivintThe divisor, an integer ≥ 1.
bitsint8, 16, 24 or 32.
Returns
- int
The signed code.
Pow2(int)
2ᵇ as an exact double, for b in [0, 64].
public static double Pow2(int b)
Parameters
bintThe exponent.
Returns
- double
2ᵇ.
QuantStep(double, double, int)
The quantization step of a quant or pos axis: (max − min) / 2ᵇ.
public static double QuantStep(double min, double max, int bits)
Parameters
Returns
- double
The step.
RoundHalfAwayFromZero(double)
Rounds half away from zero (rha).
public static double RoundHalfAwayFromZero(double x)
Parameters
xdoubleThe value.
Returns
- double
The nearest integer, ties away from zero.
SymmetricLimit(int)
The largest magnitude of a symmetric signed code: 2ᵇ⁻¹ − 1.
public static int SymmetricLimit(int bits)
Parameters
bitsint8, 16, 24 or 32.
Returns
- int
The limit.