persistable sclass InterpolatedDoubleArray is IntSize { int[] indices; double[] values; *(int[] *indices, double[] *values) {} public int size aka length() { ret empty(indices) ? 0 : last(indices)+1; } int nPillars() { ret l(indices); } double[] toDoubleArray aka get() { int n = length(); double[] array = new[n]; for (int i = 0; i < indices.length; i++) { int iEnd = indices[i]; double value = values[i]; array[iEnd] = value; if (i > 0) { int iStart = indices[i-1]; if (iStart+1 < iEnd) { double startValue = values[i-1]; double step = (value-startValue)/(iEnd-iStart), val = startValue; for (int j = iStart+1; j < iEnd; j++) { val += step; array[j] = val; } } } } ret array; } int[] rounded() { ret iroundDoubleArray(get()); } double[] indicesAndValues() { int n = nPillars(); double[] array = new[n*2]; for i to n: { array[i*2] = indices[i]; array[i*2+1] = values[i]; } ret array; } double[] indicesAndValues_withoutFirstAndLastIndex() { int n = nPillars(); double[] array = new[max(1, n*2-2)]; int j = 0; for i to n: { if (i != 0 && i != n-1) array[j++] = indices[i]; array[j++] = values[i]; } ret array; } int nInts_withoutFirstAndLastIndex() { ret max(1, nPillars()*2-2); } int nInts() { ret nPillars()*2; } InterpolatedDoubleArray topPart(int nPillars) { ret new InterpolatedDoubleArray( takeFirst(nPillars, indices), takeFirst(nPillars, values)); } }