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