Package limn.math

Class Scalars

java.lang.Object
limn.math.Scalars

public final class Scalars extends Object
The handful of scalar helpers every module reaches for — clamp, lerp, smoothstep — in one place, with one answer each.

They used to be private statics: six copies of clamp, three of clamp01 with three different bodies, and the three did not agree on the one input that matters, NaN. Math.min(1, Math.max(0, NaN)) is NaN, and a NaN that leaves a clamp goes on to a gain, an alpha, a progress fraction, where it is not "out of range" but poison. So clamp01(float) answers 0 for NaN, and that is the rule for all of them: a clamp never lets NaN through.

The inline Math.max(lo, Math.min(hi, v)) that fills widget code is not what this replaces. It is idiomatic, it reads at a glance, and it is right. What this replaces is a private method with a name, whose body a reader has to go and check.

  • Method Summary

    Modifier and Type
    Method
    Description
    static float
    clamp(float v, float lo, float hi)
    v held to [lo, hi].
    static int
    clamp(int v, int lo, int hi)
    v held to [lo, hi].
    static double
    clamp01(double v)
    v held to [0, 1]; NaN answers 0.
    static float
    clamp01(float v)
    v held to [0, 1]; NaN answers 0.
    static float
    lerp(float a, float b, float t)
    Linear interpolation: a at t = 0, b at t = 1, and beyond either for a t outside the unit range — this does not clamp, because an animation that overshoots is asking for exactly that.
    static float
    smoothstep(float t)
    The smooth ease-in-out ramp 3t² − 2t³, zero velocity at both ends, with t held to the unit range first so that the curve never leaves it.

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Method Details

    • clamp

      public static float clamp(float v, float lo, float hi)
      v held to [lo, hi]. NaN answers lo. A range with hi < lo answers lo: there is no value in an empty range, and the lower bound is the one every caller that hits this case wanted.
      Parameters:
      v - the value
      lo - the lower bound, inclusive
      hi - the upper bound, inclusive
      Returns:
      the nearest value in the range
    • clamp

      public static int clamp(int v, int lo, int hi)
      v held to [lo, hi]. A range with hi < lo answers lo.
      Parameters:
      v - the value
      lo - the lower bound, inclusive
      hi - the upper bound, inclusive
      Returns:
      the nearest value in the range
    • clamp01

      public static float clamp01(float v)
      v held to [0, 1]; NaN answers 0.
      Parameters:
      v - the value
      Returns:
      the nearest value in the unit range
    • clamp01

      public static double clamp01(double v)
      v held to [0, 1]; NaN answers 0.
      Parameters:
      v - the value
      Returns:
      the nearest value in the unit range
    • lerp

      public static float lerp(float a, float b, float t)
      Linear interpolation: a at t = 0, b at t = 1, and beyond either for a t outside the unit range — this does not clamp, because an animation that overshoots is asking for exactly that.
      Parameters:
      a - the value at zero
      b - the value at one
      t - the fraction
      Returns:
      a + (b - a) * t
    • smoothstep

      public static float smoothstep(float t)
      The smooth ease-in-out ramp 3t² − 2t³, zero velocity at both ends, with t held to the unit range first so that the curve never leaves it.
      Parameters:
      t - the fraction
      Returns:
      the eased fraction, in [0, 1]