Deterministic Gaussian Sampling
Loading...
Searching...
No Matches
squared_euclidean_distance_utils.h
1#ifndef SQUARED_EUCLIDIAN_DISTANCE_UTILS_H
2#define SQUARED_EUCLIDIAN_DISTANCE_UTILS_H
3
4#include <gsl/gsl_blas.h>
5#include <gsl/gsl_matrix.h>
6#include <gsl/gsl_vector.h>
7#include <omp.h>
8
9#include <algorithm>
10#include <cassert>
11#include <iostream>
12
13// #define USE_OMP
14
20 public:
21 SquaredEuclideanDistanceUtils(size_t L, size_t M, size_t N)
22 : L(L), M(M), N(N) {}
23
25
26 virtual double getDistance(size_t xi, size_t yi) const = 0;
27
28 size_t getL() const { return L; }
29 size_t getM() const { return M; }
30 size_t getN() const { return N; }
38 virtual void calculateDistance(const gsl_matrix* x, const gsl_matrix* y) = 0;
39
40 protected:
41 size_t L;
42 size_t M;
43 size_t N;
44
45 protected:
53 static gsl_matrix convToMatrix(const gsl_vector* v, size_t N) noexcept {
54 assert(v->size % N == 0);
55 size_t rows = v->size / N;
56 return gsl_matrix_view_array(v->data, rows, N).matrix;
57 }
58};
59
71
77 public:
78 SquaredEuclideanDistanceUtilsLM(size_t L, size_t M, size_t N)
80
82};
83
90 public:
91 SquaredEuclideanDistance_LL_matrix(size_t L, size_t N)
93 distanceMatrix = gsl_matrix_alloc(L, L);
94 }
95
97 if (distanceMatrix) {
98 gsl_matrix_free(distanceMatrix);
99 }
100 }
101
102 inline double getDistance(size_t xi, size_t xj) const override {
103 assert(xi < L && xj < L);
104 return gsl_matrix_get(distanceMatrix, xi, xj);
105 }
106
107 void calculateDistance(const gsl_matrix* x, const gsl_matrix* y) override {
108 (void)y;
109#ifdef USE_OMP
110#pragma omp parallel for collapse(2)
111#endif
112 for (size_t i = 0; i < L; ++i) {
113 for (size_t j = 0; j < L; ++j) {
114 if (i == j) {
115 gsl_matrix_set(distanceMatrix, i, j, 0.00);
116 continue;
117 }
118 double sum = 0.0;
119 for (size_t k = 0; k < N; ++k) {
120 const double diff = gsl_matrix_get(x, i, k) - gsl_matrix_get(x, j, k);
121 sum += diff * diff;
122 }
123 gsl_matrix_set(distanceMatrix, i, j, sum);
124 }
125 }
126 }
127
128 private:
129 gsl_matrix* distanceMatrix = nullptr;
130};
131
142 public:
145 distanceMatrix = gsl_matrix_alloc(L, L);
146 means = gsl_vector_alloc(L);
147 xxt = gsl_matrix_alloc(L, L);
148 }
149
151 if (distanceMatrix) gsl_matrix_free(distanceMatrix);
152 if (means) gsl_vector_free(means);
153 if (xxt) gsl_matrix_free(xxt);
154 }
155
156 inline double getDistance(size_t xi, size_t xj) const override {
157 assert(xi < L && xj < L);
158 return gsl_matrix_get(distanceMatrix, xi, xj);
159 }
160
161 void calculateDistance(const gsl_matrix* x, const gsl_matrix*) override {
162#ifdef USE_OMP
163#pragma omp parallel for
164#endif
165 for (size_t i = 0; i < L; i++) {
167 double xi_sq_norm = 0.0;
168 gsl_blas_ddot(&(xi.vector), &(xi.vector), &xi_sq_norm);
169 gsl_vector_set(means, i, xi_sq_norm);
170 }
171
172 gsl_blas_dgemm(CblasNoTrans, CblasTrans, 1.0, x, x, 0.0, xxt);
173
174#ifdef USE_OMP
175#pragma omp parallel for collapse(2)
176#endif
177 for (size_t i = 0; i < L; ++i) {
178 for (size_t j = 0; j < L; ++j) {
179 const double dist = gsl_vector_get(means, i) +
180 gsl_vector_get(means, j) -
181 2 * gsl_matrix_get(xxt, i, j);
182 gsl_matrix_set(distanceMatrix, i, j, dist);
183 }
184 }
185 }
186
187 private:
188 gsl_matrix* distanceMatrix = nullptr;
189 gsl_vector* means = nullptr;
190 gsl_matrix* xxt = nullptr;
191};
192
203 public:
206 distanceVector = gsl_vector_alloc(((L * L) - L) / 2);
207 }
208
210 if (distanceVector) gsl_vector_free(distanceVector);
211 }
212
213 inline double getDistance(size_t xi, size_t xj) const override {
214 assert(xi < L && xj < L);
215 if (xi == xj) return 0.00;
216 if (xi < xj) std::swap(xi, xj);
217 return gsl_vector_get(distanceVector, distIndex(xi, xj));
218 }
219
220 void calculateDistance(const gsl_matrix* x, const gsl_matrix* y) override {
221 (void)y;
222#ifdef USE_OMP
223#pragma omp parallel for
224#endif
225 for (size_t i = 1; i < L; i++) {
226 for (size_t j = 0; j < i; j++) {
227 const size_t distanceIndex = distIndex(i, j);
228 double sum = 0.0;
229 for (size_t k = 0; k < N; k++) {
230 const double diff = gsl_matrix_get(x, i, k) - gsl_matrix_get(x, j, k);
231 sum += diff * diff;
232 }
233 gsl_vector_set(distanceVector, distanceIndex, sum);
234 }
235 }
236 }
237
238 private:
239 inline size_t distIndex(size_t i, size_t j) const {
240 return ((i - 1) * i) / 2 + j;
241 }
242 inline size_t diffIndex(size_t i, size_t j, size_t k) const {
243 return distIndex(i, j) * N + k;
244 }
245 inline size_t diffIndex(size_t distIndex, size_t k) const {
246 return distIndex * N + k;
247 }
248
249 gsl_vector* distanceVector = nullptr;
250};
251
265 public:
268 distanceVector = gsl_vector_alloc(((L * L) - L) / 2);
269 means = gsl_vector_alloc(L);
270 }
271
273 if (distanceVector) gsl_vector_free(distanceVector);
274 };
275
276 double getDistance(size_t xi, size_t xj) const override {
277 assert(xi < L && xj < L);
278 if (xi == xj) return 0.00;
279 if (xi < xj) std::swap(xi, xj);
280 return gsl_vector_get(distanceVector, ((xi - 1) * xi) / 2 + xj);
281 }
282
283 void calculateDistance(const gsl_matrix* x, const gsl_matrix* y) override {
284 (void)y;
285#ifdef USE_OMP
286#pragma omp parallel for
287#endif
288 for (size_t i = 0; i < L; i++) {
290 double xi_sq_norm = 0.0;
291 gsl_blas_ddot(&(xi.vector), &(xi.vector), &xi_sq_norm);
292 gsl_vector_set(means, i, xi_sq_norm);
293 }
294
295#ifdef USE_OMP
296#pragma omp parallel for collapse(2)
297#endif
298 for (size_t i = 1; i < L; i++) {
299 for (size_t j = 0; j < i; j++) {
302
303 double xi_sq_norm = gsl_vector_get(means, i) + gsl_vector_get(means, j);
304
305 double xi_xj_dot = 0.0;
306 gsl_blas_ddot(&(xi.vector), &(xj.vector), &xi_xj_dot);
307
308 double dist = xi_sq_norm - 2.0 * xi_xj_dot;
309 if (dist < 0.0) dist = 0.0;
310
311 gsl_vector_set(distanceVector, ((i - 1) * i) / 2 + j, dist);
312 }
313 }
314 }
315
316 private:
317 gsl_vector* distanceVector = nullptr;
318 gsl_vector* means = nullptr;
319};
320
327 public:
328 SquaredEuclideanDistance_LM_matrix(size_t L, size_t M, size_t N)
329
331 distanceMatrix = gsl_matrix_alloc(L, M);
332 }
333
335 if (distanceMatrix) gsl_matrix_free(distanceMatrix);
336 }
337
338 double getDistance(size_t xi, size_t yi) const override {
339 assert(xi < L && yi < M);
340 return gsl_matrix_get(distanceMatrix, xi, yi);
341 }
342
343 void calculateDistance(const gsl_matrix* x, const gsl_matrix* y) override {
344#ifdef USE_OMP
345#pragma omp parallel for collapse(2)
346#endif
347 for (size_t i = 0; i < L; i++) {
348 for (size_t j = 0; j < M; j++) {
349 double sum = 0.0;
350 for (size_t k = 0; k < N; k++) {
351 const double diff = gsl_matrix_get(x, i, k) - gsl_matrix_get(y, j, k);
352 sum += diff * diff;
353 }
354 gsl_matrix_set(distanceMatrix, i, j, sum);
355 }
356 }
357 }
358
359 private:
360 gsl_matrix* distanceMatrix = nullptr;
361};
362
373 public:
374 SquaredEuclideanDistance_LM_matrix_optimized(size_t L, size_t M, size_t N)
376 distanceMatrix = gsl_matrix_alloc(L, M);
377 meansX = gsl_vector_alloc(L);
378 meansY = gsl_vector_alloc(M);
379 xyt = gsl_matrix_alloc(L, M);
380 }
381
383 if (distanceMatrix) gsl_matrix_free(distanceMatrix);
384 if (meansX) gsl_vector_free(meansX);
385 if (meansY) gsl_vector_free(meansY);
386 if (xyt) gsl_matrix_free(xyt);
387 }
388
389 double getDistance(size_t xi, size_t yi) const override {
390 assert(xi < L && yi < M);
391 return gsl_matrix_get(distanceMatrix, xi, yi);
392 }
393
394 void calculateDistance(const gsl_matrix* x, const gsl_matrix* y) override {
395#ifdef USE_OMP
396#pragma omp parallel for
397#endif
398 for (size_t i = 0; i < L; i++) {
400 double xi_sq_norm = 0.0;
401 gsl_blas_ddot(&(xi.vector), &(xi.vector), &xi_sq_norm);
402 gsl_vector_set(meansX, i, xi_sq_norm);
403 }
404
405#ifdef USE_OMP
406#pragma omp parallel for
407#endif
408 for (size_t j = 0; j < M; j++) {
410 double yj_sq_norm = 0.0;
411 gsl_blas_ddot(&(yj.vector), &(yj.vector), &yj_sq_norm);
412 gsl_vector_set(meansY, j, yj_sq_norm);
413 }
414
415 gsl_blas_dgemm(CblasNoTrans, CblasTrans, 1.0, x, y, 0.0, xyt);
416
417#ifdef USE_OMP
418#pragma omp parallel for collapse(2)
419#endif
420 for (size_t i = 0; i < L; ++i) {
421 for (size_t j = 0; j < M; ++j) {
422 const double dist = gsl_vector_get(meansX, i) +
423 gsl_vector_get(meansY, j) -
424 2 * gsl_matrix_get(xyt, i, j);
425 gsl_matrix_set(distanceMatrix, i, j, dist);
426 }
427 }
428 }
429
430 private:
431 gsl_matrix* distanceMatrix = nullptr;
432 gsl_vector* meansX = nullptr;
433 gsl_vector* meansY = nullptr;
434 gsl_matrix* xyt = nullptr;
435};
436
437#endif // SQUARED_EUCLIDIAN_DISTANCE_UTILS_H
base class for implementations calculating squared euclidean distances with just one set of vectors
Definition squared_euclidean_distance_utils.h:64
base class for implementations calculating squared euclidean distances with two set of vectors
Definition squared_euclidean_distance_utils.h:76
helper class to calculate squared euclidean distance between all linear combinations of two vector se...
Definition squared_euclidean_distance_utils.h:19
static gsl_matrix convToMatrix(const gsl_vector *v, size_t N) noexcept
convert an gsl_vector to a N column gsl_matrix
Definition squared_euclidean_distance_utils.h:53
virtual void calculateDistance(const gsl_matrix *x, const gsl_matrix *y)=0
calculate all squared euclidean distance between vectors contained as columns in x and y
implements a optimized version for calculating squared euclidean distances store in a LxL matrix
Definition squared_euclidean_distance_utils.h:141
void calculateDistance(const gsl_matrix *x, const gsl_matrix *) override
calculate all squared euclidean distance between vectors contained as columns in x and y
Definition squared_euclidean_distance_utils.h:161
implements the naive calculation of all squared euclidean distances store in a LxL matrix
Definition squared_euclidean_distance_utils.h:89
void calculateDistance(const gsl_matrix *x, const gsl_matrix *y) override
calculate all squared euclidean distance between vectors contained as columns in x and y
Definition squared_euclidean_distance_utils.h:107
implements a vectorized version of calculating squared euclidean distances store in a vector
Definition squared_euclidean_distance_utils.h:264
void calculateDistance(const gsl_matrix *x, const gsl_matrix *y) override
calculate all squared euclidean distance between vectors contained as columns in x and y
Definition squared_euclidean_distance_utils.h:283
implements a vectorized version of calculating squared euclidean distances store in a vector
Definition squared_euclidean_distance_utils.h:202
void calculateDistance(const gsl_matrix *x, const gsl_matrix *y) override
calculate all squared euclidean distance between vectors contained as columns in x and y
Definition squared_euclidean_distance_utils.h:220
implements a optimized version for calculating squared euclidean distances store in a LxM matrix
Definition squared_euclidean_distance_utils.h:372
void calculateDistance(const gsl_matrix *x, const gsl_matrix *y) override
calculate all squared euclidean distance between vectors contained as columns in x and y
Definition squared_euclidean_distance_utils.h:394
implements the naive calculation of all squared euclidean distances store in a LxM matrix
Definition squared_euclidean_distance_utils.h:326
void calculateDistance(const gsl_matrix *x, const gsl_matrix *y) override
calculate all squared euclidean distance between vectors contained as columns in x and y
Definition squared_euclidean_distance_utils.h:343
Definition dirac_to_dirac_approx_short.h:9