Vixen
caa30e12
csharp
public static class WaterMath

The arithmetic both hosts of the evaluator agree on, to the last bit.

Read the guide page for this →

Remarks

[35 § Risks](../../docs/plan/35-water.md#risks), decided in W1 rather than discovered in W7. The seam test between the C# evaluator and the Raven one states a tolerance of exact, and exact float agreement between a CPU and a SPIR-V implementation is a real claim that sin and cos do not support: the Vulkan specification allows OpSin 8192 ULP of error over the useful range, and a driver is free to use a hardware special-function unit whose polynomial nobody has written down.

So the wave sum does not call the intrinsic on either side. It calls SinCos, which is a stated polynomial in stated operations — and Raven/Library/Water/Surface.rvn spells out the same one.

⚠ What that actually bought, measured rather than claimed. Doc 35 asked for exact, and WaterSurfaceSeamDeviceTests measures 2 × 10⁻⁴ m — because a device is free to contract a multiply and an add into one FMA even where the source does not, and the Metal translation layer this repository's Vulkan device runs behind does. The residue is a one-ULP difference in the phase, and it therefore grows linearly with it: a millionth of a metre at a hundred radians, a twentieth of a millimetre at five thousand. Against the intrinsic's licensed 8192 ULP — which at those phases is not a rounding difference but a different wave — the polynomial is still what makes any bound sayable.

⚠ The range reduction is the part that has to be exact, not the polynomial. A polynomial evaluated on a reduced argument is a handful of fused-free multiply-adds and will agree anywhere; the reduction subtracts a multiple of π, and by a phase of a hundred thousand radians — twenty minutes of water time at a plausible frequency — a naive subtraction has lost every digit that mattered. Reduce therefore splits π into four pieces, the first three of which carry few enough significant bits that multiplying them by the number of half-cycles is exact, and subtracts them in order.

⚠ Nothing here may be rewritten into a fused multiply-add. An FMA computes one rounding where the written expression computes two, so a host that contracts and a host that does not disagree in the last bit — which is the whole of what this file exists to prevent. C# does not contract on its own and Raven's emitters are told not to; the parenthesisation below is load-bearing and not style.

Fields and properties (5)

  • public const float PiA

    The first and largest piece of π: 201 ⁄ 64, which is nine significant bits.

  • public const float PiB

    The second piece, also exact against its multiplier.

  • public const float PiC

    The third.

  • public const float PiD

    And the remainder, which carries what is left of π's tail.

  • public const float Tau

    Two π.

Methods (8)

  • public static void SinCos(float radians, out float sin, out float cos)

    The sine and cosine of an angle, by the polynomial both hosts implement.

  • public static float Sin(float radians)

    The sine of an angle, by SinCos.

  • public static float Cos(float radians)

    The cosine of an angle, by SinCos.

  • public static float Reduce(float radians, out bool flipped)

    Brings an angle into [−π, π], saying whether the sign has to flip.

  • public static uint Hash(uint seed, int index)

    A hash of a seed and an index, for a spectrum that is the same everywhere.

  • public static float Unit(uint hash, int stream)

    One of a hash's several independent 0…1 draws.

  • public static float Saturate(float value)

    Clamps to 0…1.

  • public static float SmoothStep(float edge0, float edge1, float value)

    A smooth 0…1 ramp between two edges, with zero derivative at both.

Used by (11)

  • BuoyancyVixen.Water
  • GerstnerWaveVixen.Water
  • WaterAttenuationVixen.Water
  • WaterBodyVixen.Water
  • WaterEvaluatorVixen.Water
  • WaterFieldVixen.Water
  • WaterMathTestsVixen.Water.Tests
  • WaterProfilePointVixen.Water
  • WaterRipplesVixen.Water
  • WaterSurfaceMeshVixen.Water
  • WaterWaveSpectrumVixen.Water