/**
* This code is released under the
* Apache License Version 2.0 http://www.apache.org/licenses/.
*
* (c) Daniel Lemire, http://lemire.me/en/
*/
package me.lemire.integercompression.differential;
/**
* Generic class to compute differential coding.
*
* @author Daniel Lemire
*
*/
public final class Delta {
/**
* Apply differential coding (in-place).
*
* @param data
* data to be modified
*/
public static void delta(int[] data) {
for (int i = data.length - 1; i > 0; --i) {
data[i] -= data[i - 1];
}
}
/**
* Apply differential coding (in-place) given an initial value.
*
* @param data
* data to be modified
* @param start
* starting index
* @param length
* number of integers to process
* @param init
* initial value
* @return next initial vale
*/
public static int delta(int[] data, int start, int length, int init) {
final int nextinit = data[start + length - 1];
for (int i = length - 1; i > 0; --i) {
data[start + i] -= data[start + i - 1];
}
data[start] -= init;
return nextinit;
}
/**
* Compute differential coding given an initial value. Output is written
* to a provided array: must have length "length" or better.
*
* @param data
* data to be modified
* @param start
* starting index
* @param length
* number of integers to process
* @param init
* initial value
* @param out
* output array
* @return next initial vale
*/
public static int delta(int[] data, int start, int length, int init,
int[] out) {
for (int i = length - 1; i > 0; --i) {
out[i] = data[start + i] - data[start + i - 1];
}
out[0] = data[start] - init;
return data[start + length - 1];
}
/**
* Undo differential coding (in-place). Effectively computes a prefix
* sum.
*
* @param data
* to be modified.
*/
public static void inverseDelta(int[] data) {
for (int i = 1; i < data.length; ++i) {
data[i] += data[i - 1];
}
}
/**
* Undo differential coding (in-place). Effectively computes a prefix
* sum. Like inverseDelta, only faster.
*
* @param data
* to be modified
*/
public static void fastinverseDelta(int[] data) {
int sz0 = data.length / 4 * 4;
int i = 1;
if (sz0 >= 4) {
int a = data[0];
for (; i < sz0 - 4; i += 4) {
a = data[i] += a;
a = data[i + 1] += a;
a = data[i + 2] += a;
a = data[i + 3] += a;
}
}
for (; i != data.length; ++i) {
data[i] += data[i - 1];
}
}
/**
* Undo differential coding (in-place). Effectively computes a prefix
* sum. Like inverseDelta, only faster. Uses an initial value.
*
* @param data
* to be modified
* @param start
* starting index
* @param length
* number of integers to process
* @param init
* initial value
* @return next initial value
*/
public static int fastinverseDelta(int[] data, int start, int length,
int init) {
data[start] += init;
int sz0 = length / 4 * 4;
int i = 1;
if (sz0 >= 4) {
int a = data[start];
for (; i < sz0 - 4; i += 4) {
a = data[start + i] += a;
a = data[start + i + 1] += a;
a = data[start + i + 2] += a;
a = data[start + i + 3] += a;
}
}
for (; i != length; ++i) {
data[start + i] += data[start + i - 1];
}
return data[start + length - 1];
}
}