Graphviz 14.1.2~dev.20260118.1035
Loading...
Searching...
No Matches
matrix_ops.c
Go to the documentation of this file.
1/*************************************************************************
2 * Copyright (c) 2011 AT&T Intellectual Property
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * https://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors: Details at https://graphviz.org
9 *************************************************************************/
10
11#include "config.h"
12
13#include <neatogen/matrix_ops.h>
14#include <stdbool.h>
15#include <stdlib.h>
16#include <stdio.h>
17#include <math.h>
18#include <util/alloc.h>
19
20static const double p_iteration_threshold = 1e-3;
21
22bool power_iteration(double *const *square_mat, int n, int neigs, double **eigs) {
23 /* compute the 'neigs' top eigenvectors of 'square_mat' using power iteration */
24
25 int i;
26 double *tmp_vec = gv_calloc(n, sizeof(double));
27 double *last_vec = gv_calloc(n, sizeof(double));
28 double angle;
29 int iteration = 0;
30 const int Max_iterations = 30 * n;
31
32 double tol = 1 - p_iteration_threshold;
33
34 if (neigs >= n) {
35 neigs = n;
36 }
37
38 double *const evals = gv_calloc(neigs, sizeof(evals[0]));
39 for (i = 0; i < neigs; i++) {
40 double *const curr_vector = eigs[i];
41 /* guess the i-th eigen vector */
42 choose:
43 for (int j = 0; j < n; j++)
44 curr_vector[j] = rand() % 100;
45 /* orthogonalize against higher eigenvectors */
46 for (int j = 0; j < i; j++) {
47 const double alpha = -vectors_inner_product(n, eigs[j], curr_vector);
48 scadd(curr_vector, n - 1, alpha, eigs[j]);
49 }
50 double len = norm(curr_vector, n - 1);
51 if (len < 1e-10) {
52 // we have chosen a vector colinear with previous ones
53 goto choose;
54 }
55 vectors_scalar_mult(n, curr_vector, 1.0 / len, curr_vector);
56 iteration = 0;
57 do {
58 iteration++;
59 copy_vector(n, curr_vector, last_vec);
60
61 right_mult_with_vector_d(square_mat, n, n, curr_vector,
62 tmp_vec);
63 copy_vector(n, tmp_vec, curr_vector);
64
65 /* orthogonalize against higher eigenvectors */
66 for (int j = 0; j < i; j++) {
67 const double alpha = -vectors_inner_product(n, eigs[j], curr_vector);
68 scadd(curr_vector, n - 1, alpha, eigs[j]);
69 }
70 len = norm(curr_vector, n - 1);
71 if (len < 1e-10 || iteration > Max_iterations) {
72 /* We have reached the null space (e.vec. associated with e.val. 0) */
73 goto exit;
74 }
75
76 vectors_scalar_mult(n, curr_vector, 1.0 / len, curr_vector);
77 angle = vectors_inner_product(n, curr_vector, last_vec);
78 } while (fabs(angle) < tol);
79 evals[i] = angle * len; /* this is the Rayleigh quotient (up to errors due to orthogonalization):
80 u*(A*u)/||A*u||)*||A*u||, where u=last_vec, and ||u||=1
81 */
82 }
83 exit:
84 for (; i < neigs; i++) {
85 /* compute the smallest eigenvector, which are */
86 /* probably associated with eigenvalue 0 and for */
87 /* which power-iteration is dangerous */
88 double *const curr_vector = eigs[i];
89 /* guess the i-th eigen vector */
90 for (int j = 0; j < n; j++)
91 curr_vector[j] = rand() % 100;
92 /* orthogonalize against higher eigenvectors */
93 for (int j = 0; j < i; j++) {
94 const double alpha = -vectors_inner_product(n, eigs[j], curr_vector);
95 scadd(curr_vector, n - 1, alpha, eigs[j]);
96 }
97 const double len = norm(curr_vector, n - 1);
98 vectors_scalar_mult(n, curr_vector, 1.0 / len, curr_vector);
99 evals[i] = 0;
100
101 }
102
103 /* sort vectors by their evals, for overcoming possible mis-convergence: */
104 for (i = 0; i < neigs - 1; i++) {
105 int largest_index = i;
106 double largest_eval = evals[largest_index];
107 for (int j = i + 1; j < neigs; j++) {
108 if (largest_eval < evals[j]) {
109 largest_index = j;
110 largest_eval = evals[largest_index];
111 }
112 }
113 if (largest_index != i) { /* exchange eigenvectors: */
114 copy_vector(n, eigs[i], tmp_vec);
115 copy_vector(n, eigs[largest_index], eigs[i]);
116 copy_vector(n, tmp_vec, eigs[largest_index]);
117
118 evals[largest_index] = evals[i];
119 evals[i] = largest_eval;
120 }
121 }
122
123 free(evals);
124 free(tmp_vec);
125 free(last_vec);
126
127 return iteration <= Max_iterations;
128}
129
130void
131mult_dense_mat(double **A, float **B, int dim1, int dim2, int dim3,
132 float ***CC)
133{
134 // A is dim1 × dim2, B is dim2 × dim3, C = A × B
135
136 float *storage = gv_calloc(dim1 * dim3, sizeof(storage[0]));
137 float **const C = *CC = gv_calloc(dim1, sizeof(C[0]));
138
139 for (int i = 0; i < dim1; i++) {
140 C[i] = storage;
141 storage += dim3;
142 }
143
144 for (int i = 0; i < dim1; i++) {
145 for (int j = 0; j < dim3; j++) {
146 double sum = 0;
147 for (int k = 0; k < dim2; k++) {
148 sum += A[i][k] * B[k][j];
149 }
150 C[i][j] = (float)sum;
151 }
152 }
153}
154
155void
156mult_dense_mat_d(double **A, float **B, int dim1, int dim2, int dim3,
157 double ***CC)
158{
159 // A is dim1 × dim2, B is dim2 × dim3, C = A × B
160
161 int i, j, k;
162 double sum;
163
164 double *storage = gv_calloc(dim1 * dim3, sizeof(double));
165 double **C = *CC = gv_calloc(dim1, sizeof(double *));
166
167 for (i = 0; i < dim1; i++) {
168 C[i] = storage;
169 storage += dim3;
170 }
171
172 for (i = 0; i < dim1; i++) {
173 for (j = 0; j < dim3; j++) {
174 sum = 0;
175 for (k = 0; k < dim2; k++) {
176 sum += A[i][k] * B[k][j];
177 }
178 C[i][j] = sum;
179 }
180 }
181}
182
183void
185 int dim2, float ***CC)
186{
187 // A is dim1 × dim1 and sparse, B is dim2 × dim1, C = A × B
188
189 int i, j;
190 double sum;
191 float *ewgts;
192 int *edges;
193 float *storage = gv_calloc(dim1 * dim2, sizeof(A[0]));
194 float **C = *CC = gv_calloc(dim1, sizeof(A));
195
196 for (i = 0; i < dim1; i++) {
197 C[i] = storage;
198 storage += dim2;
199 }
200
201 for (i = 0; i < dim1; i++) {
202 edges = A[i].edges;
203 ewgts = A[i].ewgts;
204 const size_t nedges = A[i].nedges;
205 for (j = 0; j < dim2; j++) {
206 sum = 0;
207 for (size_t k = 0; k < nedges; k++) {
208 sum += ewgts[k] * B[j][edges[k]];
209 }
210 C[i][j] = (float) (sum);
211 }
212 }
213}
214
215/* Scaled add - fills double vec1 with vec1 + alpha*vec2 over range*/
216void scadd(double *vec1, int end, double fac, double *vec2) {
217 int i;
218
219 for (i = end + 1; i; i--) {
220 (*vec1++) += fac * (*vec2++);
221 }
222}
223
224/* Returns 2-norm of a double n-vector over range. */
225double norm(double *vec, int end) {
226 return sqrt(vectors_inner_product(end + 1, vec, vec));
227}
228
229void orthog1(int n, double *vec /* vector to be orthogonalized against 1 */
230 )
231{
232 int i;
233 double *pntr;
234 double sum;
235
236 sum = 0.0;
237 pntr = vec;
238 for (i = n; i; i--) {
239 sum += *pntr++;
240 }
241 sum /= n;
242 pntr = vec;
243 for (i = n; i; i--) {
244 *pntr++ -= sum;
245 }
246}
247
248#define RANGE 500
249
250void init_vec_orth1(int n, double *vec)
251{
252 /* randomly generate a vector orthogonal to 1 (i.e., with mean 0) */
253 int i;
254
255 for (i = 0; i < n; i++)
256 vec[i] = rand() % RANGE;
257
258 orthog1(n, vec);
259}
260
261void
262right_mult_with_vector(vtx_data * matrix, int n, double *vector,
263 double *result)
264{
265 int i;
266
267 double res;
268 for (i = 0; i < n; i++) {
269 res = 0;
270 for (size_t j = 0; j < matrix[i].nedges; j++)
271 res += matrix[i].ewgts[j] * vector[matrix[i].edges[j]];
272 result[i] = res;
273 }
274}
275
276void
277right_mult_with_vector_f(float **matrix, int n, double *vector,
278 double *result)
279{
280 int i, j;
281
282 double res;
283 for (i = 0; i < n; i++) {
284 res = 0;
285 for (j = 0; j < n; j++)
286 res += matrix[i][j] * vector[j];
287 result[i] = res;
288 }
289}
290
291void
292vectors_subtraction(int n, double *vector1, double *vector2,
293 double *result)
294{
295 int i;
296 for (i = 0; i < n; i++) {
297 result[i] = vector1[i] - vector2[i];
298 }
299}
300
301void
302vectors_addition(int n, double *vector1, double *vector2, double *result)
303{
304 int i;
305 for (i = 0; i < n; i++) {
306 result[i] = vector1[i] + vector2[i];
307 }
308}
309
310void vectors_scalar_mult(int n, const double *vector, double alpha,
311 double *result) {
312 int i;
313 for (i = 0; i < n; i++) {
314 result[i] = vector[i] * alpha;
315 }
316}
317
318void copy_vector(int n, const double *restrict source, double *restrict dest) {
319 int i;
320 for (i = 0; i < n; i++)
321 dest[i] = source[i];
322}
323
324double vectors_inner_product(int n, const double *vector1,
325 const double *vector2) {
326 int i;
327 double result = 0;
328 for (i = 0; i < n; i++) {
329 result += vector1[i] * vector2[i];
330 }
331
332 return result;
333}
334
335double max_abs(int n, double *vector)
336{
337 double max_val = -1e50;
338 int i;
339 for (i = 0; i < n; i++)
340 max_val = fmax(max_val, fabs(vector[i]));
341
342 return max_val;
343}
344
345void
347 int dim1, int dim2,
348 double *vector, double *result)
349{
350 // matrix is dim2 × dim1, vector has dim2 components,
351 // result = matrixᵀ × vector
352 int i, j;
353
354 double res;
355 for (i = 0; i < dim1; i++) {
356 res = 0;
357 for (j = 0; j < dim2; j++)
358 res += matrix[j][i] * vector[j];
359 result[i] = res;
360 }
361}
362
363void right_mult_with_vector_d(double *const *matrix, int dim1, int dim2,
364 double *vector, double *result) {
365 // matrix is dim1 × dim2, vector has dim2 components,
366 // result = matrix × vector
367 int i, j;
368
369 double res;
370 for (i = 0; i < dim1; i++) {
371 res = 0;
372 for (j = 0; j < dim2; j++)
373 res += matrix[i][j] * vector[j];
374 result[i] = res;
375 }
376}
377
378/*****************************
379** Single precision (float) **
380** version **
381*****************************/
382
383void orthog1f(int n, float *vec)
384{
385 int i;
386 float *pntr;
387 float sum;
388
389 sum = 0.0;
390 pntr = vec;
391 for (i = n; i; i--) {
392 sum += *pntr++;
393 }
394 sum /= n;
395 pntr = vec;
396 for (i = n; i; i--) {
397 *pntr++ -= sum;
398 }
399}
400
402 (float *packed_matrix, int n, float *vector, float *result) {
403 /* packed matrix is the upper-triangular part of a symmetric matrix arranged in a vector row-wise */
404 int i, j, index;
405 float vector_i;
406
407 float res;
408 for (i = 0; i < n; i++) {
409 result[i] = 0;
410 }
411 for (index = 0, i = 0; i < n; i++) {
412 res = 0;
413 vector_i = vector[i];
414 /* deal with main diag */
415 res += packed_matrix[index++] * vector_i;
416 /* deal with off diag */
417 for (j = i + 1; j < n; j++, index++) {
418 res += packed_matrix[index] * vector[j];
419 result[j] += packed_matrix[index] * vector_i;
420 }
421 result[i] += res;
422 }
423}
424
425void
426vectors_subtractionf(int n, float *vector1, float *vector2, float *result)
427{
428 int i;
429 for (i = 0; i < n; i++) {
430 result[i] = vector1[i] - vector2[i];
431 }
432}
433
434void
435vectors_additionf(int n, float *vector1, float *vector2, float *result)
436{
437 int i;
438 for (i = 0; i < n; i++) {
439 result[i] = vector1[i] + vector2[i];
440 }
441}
442
443void
444vectors_mult_additionf(int n, float *vector1, float alpha, float *vector2)
445{
446 int i;
447 for (i = 0; i < n; i++) {
448 vector1[i] = vector1[i] + alpha * vector2[i];
449 }
450}
451
452void copy_vectorf(int n, float *source, float *dest)
453{
454 int i;
455 for (i = 0; i < n; i++)
456 dest[i] = source[i];
457}
458
459double vectors_inner_productf(int n, float *vector1, float *vector2)
460{
461 int i;
462 double result = 0;
463 for (i = 0; i < n; i++) {
464 result += vector1[i] * vector2[i];
465 }
466
467 return result;
468}
469
470void set_vector_val(int n, double val, double *result)
471{
472 int i;
473 for (i = 0; i < n; i++)
474 result[i] = val;
475}
476
477void set_vector_valf(int n, float val, float* result)
478{
479 int i;
480 for (i = 0; i < n; i++)
481 result[i] = val;
482}
483
484double max_absf(int n, float *vector)
485{
486 int i;
487 float max_val = -1e30f;
488 for (i = 0; i < n; i++)
489 max_val = fmaxf(max_val, fabsf(vector[i]));
490
491 return max_val;
492}
493
494void square_vec(int n, float *vec)
495{
496 int i;
497 for (i = 0; i < n; i++) {
498 vec[i] *= vec[i];
499 }
500}
501
502void invert_vec(int n, float *vec)
503{
504 int i;
505 for (i = 0; i < n; i++) {
506 if (vec[i] != 0.0) {
507 vec[i] = 1.0f / vec[i];
508 }
509 }
510}
511
512void sqrt_vecf(int n, float *source, float *target)
513{
514 int i;
515 for (i = 0; i < n; i++) {
516 if (source[i] >= 0.0) {
517 target[i] = sqrtf(source[i]);
518 }
519 }
520}
521
522void invert_sqrt_vec(int n, float *vec)
523{
524 int i;
525 for (i = 0; i < n; i++) {
526 if (vec[i] > 0.0) {
527 vec[i] = 1.0f / sqrtf(vec[i]);
528 }
529 }
530}
Memory allocation wrappers that exit on failure.
static void * gv_calloc(size_t nmemb, size_t size)
Definition alloc.h:26
#define A(n, t)
Definition expr.h:76
#define CC
Definition gc.c:47
static double len(glCompPoint p)
Definition glutils.c:138
void free(void *)
#define B
Definition hierarchy.c:120
double vectors_inner_product(int n, const double *vector1, const double *vector2)
Definition matrix_ops.c:324
void orthog1f(int n, float *vec)
Definition matrix_ops.c:383
void right_mult_with_vector_d(double *const *matrix, int dim1, int dim2, double *vector, double *result)
Definition matrix_ops.c:363
void right_mult_with_vector_transpose(double **matrix, int dim1, int dim2, double *vector, double *result)
Definition matrix_ops.c:346
void init_vec_orth1(int n, double *vec)
Definition matrix_ops.c:250
void right_mult_with_vector(vtx_data *matrix, int n, double *vector, double *result)
Definition matrix_ops.c:262
void invert_vec(int n, float *vec)
Definition matrix_ops.c:502
void copy_vector(int n, const double *restrict source, double *restrict dest)
Definition matrix_ops.c:318
void right_mult_with_vector_f(float **matrix, int n, double *vector, double *result)
Definition matrix_ops.c:277
void mult_sparse_dense_mat_transpose(vtx_data *A, double **B, int dim1, int dim2, float ***CC)
Definition matrix_ops.c:184
void invert_sqrt_vec(int n, float *vec)
Definition matrix_ops.c:522
double max_absf(int n, float *vector)
Definition matrix_ops.c:484
void vectors_additionf(int n, float *vector1, float *vector2, float *result)
Definition matrix_ops.c:435
void mult_dense_mat(double **A, float **B, int dim1, int dim2, int dim3, float ***CC)
Definition matrix_ops.c:131
void set_vector_valf(int n, float val, float *result)
Definition matrix_ops.c:477
void orthog1(int n, double *vec)
Definition matrix_ops.c:229
void copy_vectorf(int n, float *source, float *dest)
Definition matrix_ops.c:452
void sqrt_vecf(int n, float *source, float *target)
Definition matrix_ops.c:512
void set_vector_val(int n, double val, double *result)
Definition matrix_ops.c:470
bool power_iteration(double *const *square_mat, int n, int neigs, double **eigs)
Definition matrix_ops.c:22
void scadd(double *vec1, int end, double fac, double *vec2)
Definition matrix_ops.c:216
void right_mult_with_vector_ff(float *packed_matrix, int n, float *vector, float *result)
Definition matrix_ops.c:402
#define RANGE
Definition matrix_ops.c:248
void mult_dense_mat_d(double **A, float **B, int dim1, int dim2, int dim3, double ***CC)
Definition matrix_ops.c:156
void vectors_mult_additionf(int n, float *vector1, float alpha, float *vector2)
Definition matrix_ops.c:444
void square_vec(int n, float *vec)
Definition matrix_ops.c:494
static const double p_iteration_threshold
Definition matrix_ops.c:20
double max_abs(int n, double *vector)
Definition matrix_ops.c:335
double norm(double *vec, int end)
Definition matrix_ops.c:225
void vectors_subtraction(int n, double *vector1, double *vector2, double *result)
Definition matrix_ops.c:292
void vectors_addition(int n, double *vector1, double *vector2, double *result)
Definition matrix_ops.c:302
void vectors_scalar_mult(int n, const double *vector, double alpha, double *result)
Definition matrix_ops.c:310
void vectors_subtractionf(int n, float *vector1, float *vector2, float *result)
Definition matrix_ops.c:426
double vectors_inner_productf(int n, float *vector1, float *vector2)
Definition matrix_ops.c:459
#define C
Definition pack.c:32
static int nedges
total no. of edges used in routing
Definition routespl.c:32
#define alpha
Definition shapes.c:4058
static const double tol
size_t nedges
no. of neighbors, including self
Definition sparsegraph.h:29