Skip to content

Commit 6a0c058

Browse files
authored
Add cross-correlation and auto-correlation (TheAlgorithms#4984)
1 parent 9bef5a1 commit 6a0c058

File tree

4 files changed

+216
-0
lines changed

4 files changed

+216
-0
lines changed
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package com.thealgorithms.maths;
2+
3+
/**
4+
* Class for linear auto-correlation of a discrete signal
5+
*
6+
* @author Athina-Frederiki Swinkels
7+
* @version 2.0
8+
*/
9+
10+
public class AutoCorrelation {
11+
12+
/**
13+
* Discrete linear auto-correlation function.
14+
* Input and output signals have starting index 0.
15+
*
16+
* @param x The discrete signal
17+
* @return The result of the auto-correlation of signals x. The result is also a signal.
18+
*/
19+
public static double[] autoCorrelation(double[] x) {
20+
21+
/*
22+
To find the auto-correlation of a discrete signal x, we perform cross-correlation between x signal and itself.
23+
Here's an example:
24+
x=[1,2,1,1]
25+
y=[1,2,1,1]
26+
27+
i=0: [1,2,1,1]
28+
[1,2,1,1] result[0]=1*1=1
29+
30+
i=1: [1,2,1,1]
31+
[1,2,1,1] result[1]=1*1+2*1=3
32+
33+
i=2: [1,2,1,1]
34+
[1,2,1,1] result[2]=1*2+2*1+1*1=5
35+
36+
i=3: [1,2,1,1]
37+
[1,2,1,1] result[3]=1*1+2*2+1*1+1*1=7
38+
39+
i=4: [1,2,1,1]
40+
[1,2,1,1] result[4]=2*1+1*2+1*1=5
41+
42+
i=5: [1,2,1,1]
43+
[1,2,1,1] result[5]=1*1+1*2=3
44+
45+
i=1: [1,2,1,1]
46+
[1,2,1,1] result[6]=1*1=1
47+
48+
result=[1,3,5,7,5,3,1]
49+
50+
51+
*/
52+
53+
return CrossCorrelation.crossCorrelation(x, x);
54+
}
55+
}
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
package com.thealgorithms.maths;
2+
3+
/**
4+
* Class for linear cross-correlation of two discrete signals
5+
*
6+
* @author Athina-Frederiki Swinkels
7+
* @version 1.0
8+
*/
9+
10+
public class CrossCorrelation {
11+
12+
/**
13+
* Discrete linear cross-correlation function.
14+
* Input and output signals have starting index 0.
15+
*
16+
* @param x The first discrete signal
17+
* @param y The second discrete signal
18+
* @return The result of the cross-correlation of signals x,y. The result is also a signal.
19+
*/
20+
public static double[] crossCorrelation(double[] x, double[] y) {
21+
// The result signal's length is the sum of the input signals' lengths minus 1
22+
double[] result = new double[x.length + y.length - 1];
23+
int N = result.length;
24+
25+
/*
26+
To find the cross-correlation between 2 discrete signals x & y, we start by "placing" the second signal
27+
y under the first signal x, shifted to the left so that the last value of y meets the first value of x
28+
and for every new position (i++) of the result signal, we shift y signal one position to the right, until
29+
the first y-value meets the last x-value. The result-value for each position is the sum of all x*y meeting
30+
values.
31+
Here's an example:
32+
x=[1,2,1,1]
33+
y=[1,1,2,1]
34+
35+
i=0: [1,2,1,1]
36+
[1,1,2,1] result[0]=1*1=1
37+
38+
i=1: [1,2,1,1]
39+
[1,1,2,1] result[1]=1*2+2*1=4
40+
41+
i=2: [1,2,1,1]
42+
[1,1,2,1] result[2]=1*1+2*2+1*1=6
43+
44+
i=3: [1,2,1,1]
45+
[1,1,2,1] result[3]=1*1+2*1+1*2+1*1=6
46+
47+
i=4: [1,2,1,1]
48+
[1,1,2,1] result[4]=2*1+1*1+1*2=5
49+
50+
i=5: [1,2,1,1]
51+
[1,1,2,1] result[5]=1*1+1*1=2
52+
53+
i=1: [1,2,1,1]
54+
[1,1,2,1] result[6]=1*1=1
55+
56+
result=[1,4,6,6,5,2,1]
57+
58+
59+
60+
61+
To find the result[i] value for each i:0->N-1, the positions of x-signal in which the 2 signals meet
62+
are calculated: kMin<=k<=kMax.
63+
The variable 'yStart' indicates the starting index of y in each sum calculation.
64+
The variable 'count' increases the index of y-signal by 1, to move to the next value.
65+
*/
66+
int yStart = y.length;
67+
for (int i = 0; i < N; i++) {
68+
result[i] = 0;
69+
70+
int kMin = Math.max(i - (y.length - 1), 0);
71+
int kMax = Math.min(i, x.length - 1);
72+
73+
if (i < y.length) {
74+
yStart--;
75+
}
76+
77+
int count = 0;
78+
for (int k = kMin; k <= kMax; k++) {
79+
result[i] += x[k] * y[yStart + count];
80+
count++;
81+
}
82+
}
83+
84+
// The calculated cross-correlation of x & y signals is returned here.
85+
return result;
86+
}
87+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package com.thealgorithms.maths;
2+
3+
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
4+
5+
import org.junit.jupiter.params.ParameterizedTest;
6+
import org.junit.jupiter.params.provider.CsvSource;
7+
8+
/**
9+
* Test class for AutoCorrelation class
10+
*
11+
* @author Athina-Frederiki Swinkels
12+
* @version 2.0
13+
*/
14+
15+
public class AutoCorrelationTest {
16+
17+
@ParameterizedTest
18+
@CsvSource({"1;2;1;1, 1;3;5;7;5;3;1", "1;2;3, 3;8;14;8;3", "1.5;2.3;3.1;4.2, 6.3;14.31;23.6;34.79;23.6;14.31;6.3"})
19+
20+
public void testAutoCorrelationParameterized(String input, String expected) {
21+
double[] array = convertStringToArray(input);
22+
double[] expectedResult = convertStringToArray(expected);
23+
24+
double[] result = AutoCorrelation.autoCorrelation(array);
25+
26+
assertArrayEquals(expectedResult, result, 0.0001);
27+
}
28+
29+
private double[] convertStringToArray(String input) {
30+
String[] elements = input.split(";");
31+
double[] result = new double[elements.length];
32+
for (int i = 0; i < elements.length; i++) {
33+
result[i] = Double.parseDouble(elements[i]);
34+
}
35+
return result;
36+
}
37+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package com.thealgorithms.maths;
2+
3+
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
4+
5+
import org.junit.jupiter.params.ParameterizedTest;
6+
import org.junit.jupiter.params.provider.CsvSource;
7+
8+
/**
9+
* Test class for CrossCorrelation class
10+
*
11+
* @author Athina-Frederiki Swinkels
12+
* @version 2.0
13+
*/
14+
public class CrossCorrelationTest {
15+
16+
@ParameterizedTest
17+
@CsvSource({"1;2;1;1, 1;1;2;1, 1;4;6;6;5;2;1", "1;2;3, 1;2;3;4;5, 5;14;26;20;14;8;3", "1;2;3;4;5, 1;2;3, 3;8;14;20;26;14;5", "1.5;2.3;3.1;4.2, 1.1;2.2;3.3, 4.95;10.89;16.94;23.21;12.65;4.62"})
18+
19+
public void testCrossCorrelationParameterized(String input1, String input2, String expected) {
20+
double[] array1 = convertStringToArray(input1);
21+
double[] array2 = convertStringToArray(input2);
22+
double[] expectedResult = convertStringToArray(expected);
23+
24+
double[] result = CrossCorrelation.crossCorrelation(array1, array2);
25+
26+
assertArrayEquals(expectedResult, result, 0.0001);
27+
}
28+
29+
private double[] convertStringToArray(String input) {
30+
String[] elements = input.split(";");
31+
double[] result = new double[elements.length];
32+
for (int i = 0; i < elements.length; i++) {
33+
result[i] = Double.parseDouble(elements[i]);
34+
}
35+
return result;
36+
}
37+
}

0 commit comments

Comments
 (0)