| 173 | } |
| 174 | |
| 175 | pub fn distance_correlation(x: &[f64], y: &[f64]) -> CodependenceResult<f64> { |
| 176 | if x.len() != y.len() { |
| 177 | return Err(CodependenceError::InputLengthMismatch); |
| 178 | } |
| 179 | let n = x.len(); |
| 180 | if n < 2 { |
| 181 | return Err(CodependenceError::InputTooShort); |
| 182 | } |
| 183 | |
| 184 | let mut a = vec![0.0; n * n]; |
| 185 | let mut b = vec![0.0; n * n]; |
| 186 | |
| 187 | for i in 0..n { |
| 188 | for j in 0..n { |
| 189 | a[i * n + j] = (x[i] - x[j]).abs(); |
| 190 | b[i * n + j] = (y[i] - y[j]).abs(); |
| 191 | } |
| 192 | } |
| 193 | |
| 194 | let mut row_mean_a = vec![0.0; n]; |
| 195 | let mut col_mean_a = vec![0.0; n]; |
| 196 | let mut row_mean_b = vec![0.0; n]; |
| 197 | let mut col_mean_b = vec![0.0; n]; |
| 198 | |
| 199 | for i in 0..n { |
| 200 | let mut sum_a = 0.0; |
| 201 | let mut sum_b = 0.0; |
| 202 | for j in 0..n { |
| 203 | sum_a += a[i * n + j]; |
| 204 | sum_b += b[i * n + j]; |
| 205 | } |
| 206 | row_mean_a[i] = sum_a / n as f64; |
| 207 | row_mean_b[i] = sum_b / n as f64; |
| 208 | } |
| 209 | |
| 210 | for j in 0..n { |
| 211 | let mut sum_a = 0.0; |
| 212 | let mut sum_b = 0.0; |
| 213 | for i in 0..n { |
| 214 | sum_a += a[i * n + j]; |
| 215 | sum_b += b[i * n + j]; |
| 216 | } |
| 217 | col_mean_a[j] = sum_a / n as f64; |
| 218 | col_mean_b[j] = sum_b / n as f64; |
| 219 | } |
| 220 | |
| 221 | let mean_a = a.iter().sum::<f64>() / (n * n) as f64; |
| 222 | let mean_b = b.iter().sum::<f64>() / (n * n) as f64; |
| 223 | |
| 224 | let mut d_cov_xx = 0.0; |
| 225 | let mut d_cov_xy = 0.0; |
| 226 | let mut d_cov_yy = 0.0; |
| 227 | |
| 228 | for i in 0..n { |
| 229 | for j in 0..n { |
| 230 | let a_centered = a[i * n + j] - row_mean_a[i] - col_mean_a[j] + mean_a; |
| 231 | let b_centered = b[i * n + j] - row_mean_b[i] - col_mean_b[j] + mean_b; |
| 232 | d_cov_xx += a_centered * a_centered; |