Inspired by this answer: https://stackoverflow.com/a/41196499
This implementation improves upon the above answer by only running the PascalTriangle functions once during initialization and using the compiled results in all subsequent calls to the function.
// (nthOrder should be a positive integer, not a float.)
// values higher than 15 show some strange behavior.
function SmoothMaker(nthOrder){
var preCalculatedValues = []
for(var n = 0; n <= nthOrder - 1; n++){
var precalculatedValue = PascalTriangle(-nthOrder, n) * PascalTriangle(2 * nthOrder - 1, nthOrder - n - 1)
preCalculatedValues.push(precalculatedValue)
}
function PascalTriangle(a, b){
var result = 1
for(var i = 1; i <= b; i++){
result *= ((a - (i - 1)) / i)
}
return result
}
return function(x){
var order = preCalculatedValues.length
return preCalculatedValues.reduce(function(result, precalcValue, index, array){
var power = order + index
result += Math.pow(x, power) * precalcValue
return result
}, 0)
}
}
Example usage:
const ctx = document.createElement("canvas").getContext("2d")
document.body.appendChild(ctx.canvas)
ctx.canvas.width = 300
ctx.canvas.height = 300
ctx.beginPath()
const ChosenOrder = 4
const Smooth = SmoothMaker(ChosenOrder)
for(var i = 0; i < ctx.canvas.width; i++){
var part = i / ctx.canvas.width
var value = Smooth(part) * ctx.canvas.height
ctx.lineTo(i, value)
}
ctx.stroke()