Skip to content

Instantly share code, notes, and snippets.

@demonixis
Created December 4, 2012 10:38
Show Gist options
  • Star 23 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save demonixis/4202528 to your computer and use it in GitHub Desktop.
Save demonixis/4202528 to your computer and use it in GitHub Desktop.
JavaScript Math helper
var MathHelper = {
// Get a value between two values
clamp: function (value, min, max) {
if (value < min) {
return min;
}
else if (value > max) {
return max;
}
return value;
},
// Get the linear interpolation between two value
lerp: function (value1, value2, amount) {
amount = amount < 0 ? 0 : amount;
amount = amount > 1 ? 1 : amount;
return value1 + (value2 - value1) * amount;
}
};
@vickylance
Copy link

Nice..Thanks

@geowar1
Copy link

geowar1 commented Apr 28, 2017

Math.lerp function has two issues… First: the "amount" can be less than zero or greater than one; this allows for extrapolation (see: wikipedia); so no reason to pin between these values. Second: the value1 + (value2 - value1) * amount; equation is Imprecise, it does not guarantee v = v1 when t = 1, due to floating-point arithmetic error. (see wikipedia)
Use return (1 - amount) * value1 + amount * value2; instead;

@geowar1
Copy link

geowar1 commented Apr 28, 2017

Also, clamp can be made faster by using Math.min & Math.max instead of the conditional comparison expressions; use:
return Math.min(Math.max(value, min), max); instead.

@geowar1
Copy link

geowar1 commented Apr 28, 2017

Another useful math routine is wrap:

Math.wrap = function(inValue, inMin, inMax) {
valueRange = inMax - inMin;
return (inMin + ((((inValue - inMin) % valueRange) + valueRange) % valueRange));
}

Use it like this:

angle = Math.wrap(angle, 0, 360); // wrap between 0 & 360°
angle = Math.wrap(angle, -90, +90); // wrap between +/-90°

@mvasilkov
Copy link

@geowar1 Did you benchmark the Math.min(Math.max()) being faster? I'd be surprised if that was true.

@domske
Copy link

domske commented Aug 4, 2017

The "if" method of clamp is ca. 4,5 times faster than the math min/max method.
Tested with chrome version 60.0.3112.90 64bit.

Benchmark:
Run the clamp function x-times (e.g. 1 000 000 000) with limits min 25% of range (x-times) and max 75%.

function runBench(func) {
  console.log("Benchmark '" + func.name +"' running ...");

  let value = 0;
  let now = new Date().getTime();
  let range = 1000000000;
  let rangeMin = range * 0.25; 
  let rangeMax = range * 0.75;

  for (let i = 0; i < range; i++) {
    value = func(i, rangeMin, rangeMax);
  }

  console.log("Time: " + (new Date().getTime() - now) + " ms");
}

runBench(clamp1); // alternate with clamp2

If you run the benchmark tests sequentially the second test is always slower.
It's weird. The tests influence each other.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment