function spalma(cfg) {
var defaults = {
min:0,
max:1,
distfun:function(a,b) { return Math.sqrt((a-b)*(a-b));},
resolution:10000,
data:[1,2,3,4,5],
loop: true
}
cfg=Object.assign({}, defaults, cfg);
var {data,min,max,distfun,resolution,loop} = cfg;
if (typeof(data)!='function')
data = Smooth(data, { method: 'cubic', clip: loop?'periodic':'clamp' });
var samples=[];
var dist=[];
for(var i=0; i<resolution; i++) {
let x = min+(max-min)*i/resolution;
samples[i]=data(x);
}
samples[resolution] = loop ? samples[0] : samples[resolution-1];
dist[0]=0;
for(var i=1; i<=resolution; i++) {
var d = distfun(samples[i-1], samples[i]);
dist[i] = dist[i-1]+d;
}
var totdist=dist[resolution];
var xmark=[];
var step = totdist/resolution;
var m = Smooth(dist, { method: 'cubic', clip: 'clamp' });
for(var i=0; i<=resolution; i++) {
var d=totdist*i/resolution;
var left=0, right=1;
for(var j=0; j<30; j++) {
var mean = (left+right)/2;
var md = m(resolution*mean);
if (md>d)
right=mean;
else
left=mean;
}
xmark[i] = (left+right)/2;
}
xmark[0]=0;
xmark[resolution] = 1;
var remapped = [];
for(var i=0; i<=resolution; i++)
remapped[i]=data(min+xmark[i]*(max-min));
xmark=null;
dist=null;
samples=null;
return remapped;
}