sclass CompressToInterpolatedDoubleArray { // raw data to compress (integers) int[] data; // output InterpolatedDoubleArray result; // options settable double slopeTolerance = 0.01; // internal new IntBuffer indices; new DoubleBuffer values; *(int[] *data) {} InterpolatedDoubleArray get() { int iData = 0; while (iData < data.length) { int startValue = data[iData]; // possible range of actual floating point starting value DoubleRange startValueRange = doubleRange(startValue-0.5, startValue+0.5); // see how far the straight line goes from iData DoubleRange totalSlopeRange = null; int jData; // our straight line ends at jData-1 for (jData = iData+1; jData < data.length; jData++) { double x = data[jData], h = jData-iData; // possible range of actual floating point value DoubleRange xRange = doubleRange(x-0.5, x+0.5); // most generous range for possible slope depending // on possible floating point values at start and end DoubleRange slopeRange = doubleRange( (xRange.start-startValueRange.end)/h, (xRange.end-startValueRange.start)/h); // grow range a little to avoid size 0 ranges slopeRange = growRange(slopeTolerance, slopeRange); //printVars(+iData, +jData, +slopeRange, +totalSlopeRange); if (totalSlopeRange == null) totalSlopeRange = slopeRange; else { slopeRange = intersectRanges(slopeRange, totalSlopeRange); if (empty(slopeRange)) break; else totalSlopeRange = slopeRange; } } indices.add(iData); values.add(data[iData]); iData = max(iData+1, jData-1); } ret result = new InterpolatedDoubleArray(indices.toArrayNonNull(), values.toArrayNonNull()); } }