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