Graphviz  2.29.20120524.0446
lib/neatogen/matrix_ops.c
Go to the documentation of this file.
00001 /* $Id$ $Revision$ */
00002 /* vim:set shiftwidth=4 ts=8: */
00003 
00004 /*************************************************************************
00005  * Copyright (c) 2011 AT&T Intellectual Property 
00006  * All rights reserved. This program and the accompanying materials
00007  * are made available under the terms of the Eclipse Public License v1.0
00008  * which accompanies this distribution, and is available at
00009  * http://www.eclipse.org/legal/epl-v10.html
00010  *
00011  * Contributors: See CVS logs. Details at http://www.graphviz.org/
00012  *************************************************************************/
00013 
00014 
00015 #include "matrix_ops.h"
00016 #include "memory.h"
00017 #include <stdlib.h>
00018 #include <stdio.h>
00019 #include <math.h>
00020 
00021 static double p_iteration_threshold = 1e-3;
00022 
00023 int
00024 power_iteration(double **square_mat, int n, int neigs, double **eigs,
00025                 double *evals, int initialize)
00026 {
00027     /* compute the 'neigs' top eigenvectors of 'square_mat' using power iteration */
00028 
00029     int i, j;
00030     double *tmp_vec = N_GNEW(n, double);
00031     double *last_vec = N_GNEW(n, double);
00032     double *curr_vector;
00033     double len;
00034     double angle;
00035     double alpha;
00036     int iteration = 0;
00037     int largest_index;
00038     double largest_eval;
00039     int Max_iterations = 30 * n;
00040 
00041     double tol = 1 - p_iteration_threshold;
00042 
00043     if (neigs >= n) {
00044         neigs = n;
00045     }
00046 
00047     for (i = 0; i < neigs; i++) {
00048         curr_vector = eigs[i];
00049         /* guess the i-th eigen vector */
00050       choose:
00051         if (initialize)
00052             for (j = 0; j < n; j++)
00053                 curr_vector[j] = rand() % 100;
00054         /* orthogonalize against higher eigenvectors */
00055         for (j = 0; j < i; j++) {
00056             alpha = -dot(eigs[j], 0, n - 1, curr_vector);
00057             scadd(curr_vector, 0, n - 1, alpha, eigs[j]);
00058         }
00059         len = norm(curr_vector, 0, n - 1);
00060         if (len < 1e-10) {
00061             /* We have chosen a vector colinear with prvious ones */
00062             goto choose;
00063         }
00064         vecscale(curr_vector, 0, n - 1, 1.0 / len, curr_vector);
00065         iteration = 0;
00066         do {
00067             iteration++;
00068             cpvec(last_vec, 0, n - 1, curr_vector);
00069 
00070             right_mult_with_vector_d(square_mat, n, n, curr_vector,
00071                                      tmp_vec);
00072             cpvec(curr_vector, 0, n - 1, tmp_vec);
00073 
00074             /* orthogonalize against higher eigenvectors */
00075             for (j = 0; j < i; j++) {
00076                 alpha = -dot(eigs[j], 0, n - 1, curr_vector);
00077                 scadd(curr_vector, 0, n - 1, alpha, eigs[j]);
00078             }
00079             len = norm(curr_vector, 0, n - 1);
00080             if (len < 1e-10 || iteration > Max_iterations) {
00081                 /* We have reached the null space (e.vec. associated with e.val. 0) */
00082                 goto exit;
00083             }
00084 
00085             vecscale(curr_vector, 0, n - 1, 1.0 / len, curr_vector);
00086             angle = dot(curr_vector, 0, n - 1, last_vec);
00087         } while (fabs(angle) < tol);
00088         evals[i] = angle * len; /* this is the Rayleigh quotient (up to errors due to orthogonalization):
00089                                    u*(A*u)/||A*u||)*||A*u||, where u=last_vec, and ||u||=1
00090                                  */
00091     }
00092   exit:
00093     for (; i < neigs; i++) {
00094         /* compute the smallest eigenvector, which are  */
00095         /* probably associated with eigenvalue 0 and for */
00096         /* which power-iteration is dangerous */
00097         curr_vector = eigs[i];
00098         /* guess the i-th eigen vector */
00099         for (j = 0; j < n; j++)
00100             curr_vector[j] = rand() % 100;
00101         /* orthogonalize against higher eigenvectors */
00102         for (j = 0; j < i; j++) {
00103             alpha = -dot(eigs[j], 0, n - 1, curr_vector);
00104             scadd(curr_vector, 0, n - 1, alpha, eigs[j]);
00105         }
00106         len = norm(curr_vector, 0, n - 1);
00107         vecscale(curr_vector, 0, n - 1, 1.0 / len, curr_vector);
00108         evals[i] = 0;
00109 
00110     }
00111 
00112 
00113     /* sort vectors by their evals, for overcoming possible mis-convergence: */
00114     for (i = 0; i < neigs - 1; i++) {
00115         largest_index = i;
00116         largest_eval = evals[largest_index];
00117         for (j = i + 1; j < neigs; j++) {
00118             if (largest_eval < evals[j]) {
00119                 largest_index = j;
00120                 largest_eval = evals[largest_index];
00121             }
00122         }
00123         if (largest_index != i) {       /* exchange eigenvectors: */
00124             cpvec(tmp_vec, 0, n - 1, eigs[i]);
00125             cpvec(eigs[i], 0, n - 1, eigs[largest_index]);
00126             cpvec(eigs[largest_index], 0, n - 1, tmp_vec);
00127 
00128             evals[largest_index] = evals[i];
00129             evals[i] = largest_eval;
00130         }
00131     }
00132 
00133     free(tmp_vec);
00134     free(last_vec);
00135 
00136     return (iteration <= Max_iterations);
00137 }
00138 
00139 
00140 
00141 void
00142 mult_dense_mat(double **A, float **B, int dim1, int dim2, int dim3,
00143                float ***CC)
00144 {
00145 /*
00146   A is dim1 x dim2, B is dim2 x dim3, C = A x B 
00147 */
00148 
00149     double sum;
00150     int i, j, k;
00151     float *storage;
00152     float **C = *CC;
00153     if (C != NULL) {
00154         storage = (float *) realloc(C[0], dim1 * dim3 * sizeof(A[0]));
00155         *CC = C = (float **) realloc(C, dim1 * sizeof(A));
00156     } else {
00157         storage = (float *) malloc(dim1 * dim3 * sizeof(A[0]));
00158         *CC = C = (float **) malloc(dim1 * sizeof(A));
00159     }
00160 
00161     for (i = 0; i < dim1; i++) {
00162         C[i] = storage;
00163         storage += dim3;
00164     }
00165 
00166     for (i = 0; i < dim1; i++) {
00167         for (j = 0; j < dim3; j++) {
00168             sum = 0;
00169             for (k = 0; k < dim2; k++) {
00170                 sum += A[i][k] * B[k][j];
00171             }
00172             C[i][j] = (float) (sum);
00173         }
00174     }
00175 }
00176 
00177 void
00178 mult_dense_mat_d(double **A, float **B, int dim1, int dim2, int dim3,
00179                  double ***CC)
00180 {
00181 /*
00182   A is dim1 x dim2, B is dim2 x dim3, C = A x B 
00183 */
00184     double **C = *CC;
00185     double *storage;
00186     int i, j, k;
00187     double sum;
00188 
00189     if (C != NULL) {
00190         storage = (double *) realloc(C[0], dim1 * dim3 * sizeof(double));
00191         *CC = C = (double **) realloc(C, dim1 * sizeof(double *));
00192     } else {
00193         storage = (double *) malloc(dim1 * dim3 * sizeof(double));
00194         *CC = C = (double **) malloc(dim1 * sizeof(double *));
00195     }
00196 
00197     for (i = 0; i < dim1; i++) {
00198         C[i] = storage;
00199         storage += dim3;
00200     }
00201 
00202     for (i = 0; i < dim1; i++) {
00203         for (j = 0; j < dim3; j++) {
00204             sum = 0;
00205             for (k = 0; k < dim2; k++) {
00206                 sum += A[i][k] * B[k][j];
00207             }
00208             C[i][j] = sum;
00209         }
00210     }
00211 }
00212 
00213 void
00214 mult_sparse_dense_mat_transpose(vtx_data * A, double **B, int dim1,
00215                                 int dim2, float ***CC)
00216 {
00217 /*
00218   A is dim1 x dim1 and sparse, B is dim2 x dim1, C = A x B 
00219 */
00220 
00221     float *storage;
00222     int i, j, k;
00223     double sum;
00224     float *ewgts;
00225     int *edges;
00226     int nedges;
00227     float **C = *CC;
00228     if (C != NULL) {
00229         storage = (float *) realloc(C[0], dim1 * dim2 * sizeof(A[0]));
00230         *CC = C = (float **) realloc(C, dim1 * sizeof(A));
00231     } else {
00232         storage = (float *) malloc(dim1 * dim2 * sizeof(A[0]));
00233         *CC = C = (float **) malloc(dim1 * sizeof(A));
00234     }
00235 
00236     for (i = 0; i < dim1; i++) {
00237         C[i] = storage;
00238         storage += dim2;
00239     }
00240 
00241     for (i = 0; i < dim1; i++) {
00242         edges = A[i].edges;
00243         ewgts = A[i].ewgts;
00244         nedges = A[i].nedges;
00245         for (j = 0; j < dim2; j++) {
00246             sum = 0;
00247             for (k = 0; k < nedges; k++) {
00248                 sum += ewgts[k] * B[j][edges[k]];
00249             }
00250             C[i][j] = (float) (sum);
00251         }
00252     }
00253 }
00254 
00255 
00256 
00257 /* Copy a range of a double vector to a double vector */
00258 void cpvec(double *copy, int beg, int end, double *vec)
00259 {
00260     int i;
00261 
00262     copy = copy + beg;
00263     vec = vec + beg;
00264     for (i = end - beg + 1; i; i--) {
00265         *copy++ = *vec++;
00266     }
00267 }
00268 
00269 /* Returns scalar product of two double n-vectors. */
00270 double dot(double *vec1, int beg, int end, double *vec2)
00271 {
00272     int i;
00273     double sum;
00274 
00275     sum = 0.0;
00276     vec1 = vec1 + beg;
00277     vec2 = vec2 + beg;
00278     for (i = end - beg + 1; i; i--) {
00279         sum += (*vec1++) * (*vec2++);
00280     }
00281     return (sum);
00282 }
00283 
00284 
00285 /* Scaled add - fills double vec1 with vec1 + alpha*vec2 over range*/
00286 void scadd(double *vec1, int beg, int end, double fac, double *vec2)
00287 {
00288     int i;
00289 
00290     vec1 = vec1 + beg;
00291     vec2 = vec2 + beg;
00292     for (i = end - beg + 1; i; i--) {
00293         (*vec1++) += fac * (*vec2++);
00294     }
00295 }
00296 
00297 /* Scale - fills vec1 with alpha*vec2 over range, double version */
00298 void vecscale(double *vec1, int beg, int end, double alpha, double *vec2)
00299 {
00300     int i;
00301 
00302     vec1 += beg;
00303     vec2 += beg;
00304     for (i = end - beg + 1; i; i--) {
00305         (*vec1++) = alpha * (*vec2++);
00306     }
00307 }
00308 
00309 /* Returns 2-norm of a double n-vector over range. */
00310 double norm(double *vec, int beg, int end)
00311 {
00312     return (sqrt(dot(vec, beg, end, vec)));
00313 }
00314 
00315 
00316 #ifndef __cplusplus
00317 
00318 /* inline */
00319 void orthog1(int n, double *vec /* vector to be orthogonalized against 1 */
00320     )
00321 {
00322     int i;
00323     double *pntr;
00324     double sum;
00325 
00326     sum = 0.0;
00327     pntr = vec;
00328     for (i = n; i; i--) {
00329         sum += *pntr++;
00330     }
00331     sum /= n;
00332     pntr = vec;
00333     for (i = n; i; i--) {
00334         *pntr++ -= sum;
00335     }
00336 }
00337 
00338 #define RANGE 500
00339 
00340 /* inline */
00341 void init_vec_orth1(int n, double *vec)
00342 {
00343     /* randomly generate a vector orthogonal to 1 (i.e., with mean 0) */
00344     int i;
00345 
00346     for (i = 0; i < n; i++)
00347         vec[i] = rand() % RANGE;
00348 
00349     orthog1(n, vec);
00350 }
00351 
00352 /* inline */
00353 void
00354 right_mult_with_vector(vtx_data * matrix, int n, double *vector,
00355                        double *result)
00356 {
00357     int i, j;
00358 
00359     double res;
00360     for (i = 0; i < n; i++) {
00361         res = 0;
00362         for (j = 0; j < matrix[i].nedges; j++)
00363             res += matrix[i].ewgts[j] * vector[matrix[i].edges[j]];
00364         result[i] = res;
00365     }
00366     /* orthog1(n,vector); */
00367 }
00368 
00369 /* inline */
00370 void
00371 right_mult_with_vector_f(float **matrix, int n, double *vector,
00372                          double *result)
00373 {
00374     int i, j;
00375 
00376     double res;
00377     for (i = 0; i < n; i++) {
00378         res = 0;
00379         for (j = 0; j < n; j++)
00380             res += matrix[i][j] * vector[j];
00381         result[i] = res;
00382     }
00383     /* orthog1(n,vector); */
00384 }
00385 
00386 /* inline */
00387 void
00388 vectors_subtraction(int n, double *vector1, double *vector2,
00389                     double *result)
00390 {
00391     int i;
00392     for (i = 0; i < n; i++) {
00393         result[i] = vector1[i] - vector2[i];
00394     }
00395 }
00396 
00397 /* inline */
00398 void
00399 vectors_addition(int n, double *vector1, double *vector2, double *result)
00400 {
00401     int i;
00402     for (i = 0; i < n; i++) {
00403         result[i] = vector1[i] + vector2[i];
00404     }
00405 }
00406 
00407 #ifdef UNUSED
00408 /* inline */
00409 void
00410 vectors_mult_addition(int n, double *vector1, double alpha,
00411                       double *vector2)
00412 {
00413     int i;
00414     for (i = 0; i < n; i++) {
00415         vector1[i] = vector1[i] + alpha * vector2[i];
00416     }
00417 }
00418 #endif
00419 
00420 /* inline */
00421 void
00422 vectors_scalar_mult(int n, double *vector, double alpha, double *result)
00423 {
00424     int i;
00425     for (i = 0; i < n; i++) {
00426         result[i] = vector[i] * alpha;
00427     }
00428 }
00429 
00430 /* inline */
00431 void copy_vector(int n, double *source, double *dest)
00432 {
00433     int i;
00434     for (i = 0; i < n; i++)
00435         dest[i] = source[i];
00436 }
00437 
00438 /* inline */
00439 double vectors_inner_product(int n, double *vector1, double *vector2)
00440 {
00441     int i;
00442     double result = 0;
00443     for (i = 0; i < n; i++) {
00444         result += vector1[i] * vector2[i];
00445     }
00446 
00447     return result;
00448 }
00449 
00450 /* inline */
00451 double max_abs(int n, double *vector)
00452 {
00453     double max_val = -1e50;
00454     int i;
00455     for (i = 0; i < n; i++)
00456         if (fabs(vector[i]) > max_val)
00457             max_val = fabs(vector[i]);
00458 
00459     return max_val;
00460 }
00461 
00462 #ifdef UNUSED
00463 /* inline */
00464 void orthogvec(int n, double *vec1,     /* vector to be orthogonalized */
00465                double *vec2     /* normalized vector to be orthogonalized against */
00466     )
00467 {
00468     double alpha;
00469     if (vec2 == NULL) {
00470         return;
00471     }
00472 
00473     alpha = -vectors_inner_product(n, vec1, vec2);
00474 
00475     vectors_mult_addition(n, vec1, alpha, vec2);
00476 }
00477 
00478  /* sparse matrix extensions: */
00479 
00480 /* inline */
00481 void mat_mult_vec(vtx_data * L, int n, double *vec, double *result)
00482 {
00483     /* compute result= -L*vec */
00484     int i, j;
00485     double sum;
00486     int *edges;
00487     float *ewgts;
00488 
00489     for (i = 0; i < n; i++) {
00490         sum = 0;
00491         edges = L[i].edges;
00492         ewgts = L[i].ewgts;
00493         for (j = 0; j < L[i].nedges; j++) {
00494             sum -= ewgts[j] * vec[edges[j]];
00495         }
00496         result[i] = sum;
00497     }
00498 }
00499 #endif
00500 
00501 /* inline */
00502 void
00503 right_mult_with_vector_transpose(double **matrix,
00504                                  int dim1, int dim2,
00505                                  double *vector, double *result)
00506 {
00507     /* matrix is dim2 x dim1, vector has dim2 components, result=matrix^T x vector */
00508     int i, j;
00509 
00510     double res;
00511     for (i = 0; i < dim1; i++) {
00512         res = 0;
00513         for (j = 0; j < dim2; j++)
00514             res += matrix[j][i] * vector[j];
00515         result[i] = res;
00516     }
00517 }
00518 
00519 /* inline */
00520 void
00521 right_mult_with_vector_d(double **matrix,
00522                          int dim1, int dim2,
00523                          double *vector, double *result)
00524 {
00525     /* matrix is dim1 x dim2, vector has dim2 components, result=matrix x vector */
00526     int i, j;
00527 
00528     double res;
00529     for (i = 0; i < dim1; i++) {
00530         res = 0;
00531         for (j = 0; j < dim2; j++)
00532             res += matrix[i][j] * vector[j];
00533         result[i] = res;
00534     }
00535 }
00536 
00537 
00538 /*****************************
00539 ** Single precision (float) **
00540 ** version                  **
00541 *****************************/
00542 
00543 /* inline */
00544 void orthog1f(int n, float *vec)
00545 {
00546     int i;
00547     float *pntr;
00548     float sum;
00549 
00550     sum = 0.0;
00551     pntr = vec;
00552     for (i = n; i; i--) {
00553         sum += *pntr++;
00554     }
00555     sum /= n;
00556     pntr = vec;
00557     for (i = n; i; i--) {
00558         *pntr++ -= sum;
00559     }
00560 }
00561 
00562 #ifdef UNUSED
00563 /* inline */
00564 void right_mult_with_vectorf
00565     (vtx_data * matrix, int n, float *vector, float *result) {
00566     int i, j;
00567 
00568     float res;
00569     for (i = 0; i < n; i++) {
00570         res = 0;
00571         for (j = 0; j < matrix[i].nedges; j++)
00572             res += matrix[i].ewgts[j] * vector[matrix[i].edges[j]];
00573         result[i] = res;
00574     }
00575 }
00576 
00577 /* inline */
00578 void right_mult_with_vector_fd
00579     (float **matrix, int n, float *vector, double *result) {
00580     int i, j;
00581 
00582     float res;
00583     for (i = 0; i < n; i++) {
00584         res = 0;
00585         for (j = 0; j < n; j++)
00586             res += matrix[i][j] * vector[j];
00587         result[i] = res;
00588     }
00589 }
00590 #endif
00591 
00592 /* inline */
00593 void right_mult_with_vector_ff
00594     (float *packed_matrix, int n, float *vector, float *result) {
00595     /* packed matrix is the upper-triangular part of a symmetric matrix arranged in a vector row-wise */
00596     int i, j, index;
00597     float vector_i;
00598 
00599     float res;
00600     for (i = 0; i < n; i++) {
00601         result[i] = 0;
00602     }
00603     for (index = 0, i = 0; i < n; i++) {
00604         res = 0;
00605         vector_i = vector[i];
00606         /* deal with main diag */
00607         res += packed_matrix[index++] * vector_i;
00608         /* deal with off diag */
00609         for (j = i + 1; j < n; j++, index++) {
00610             res += packed_matrix[index] * vector[j];
00611             result[j] += packed_matrix[index] * vector_i;
00612         }
00613         result[i] += res;
00614     }
00615 }
00616 
00617 /* inline */
00618 void
00619 vectors_substractionf(int n, float *vector1, float *vector2, float *result)
00620 {
00621     int i;
00622     for (i = 0; i < n; i++) {
00623         result[i] = vector1[i] - vector2[i];
00624     }
00625 }
00626 
00627 /* inline */
00628 void
00629 vectors_additionf(int n, float *vector1, float *vector2, float *result)
00630 {
00631     int i;
00632     for (i = 0; i < n; i++) {
00633         result[i] = vector1[i] + vector2[i];
00634     }
00635 }
00636 
00637 /* inline */
00638 void
00639 vectors_mult_additionf(int n, float *vector1, float alpha, float *vector2)
00640 {
00641     int i;
00642     for (i = 0; i < n; i++) {
00643         vector1[i] = vector1[i] + alpha * vector2[i];
00644     }
00645 }
00646 
00647 /* inline */
00648 void vectors_scalar_multf(int n, float *vector, float alpha, float *result)
00649 {
00650     int i;
00651     for (i = 0; i < n; i++) {
00652         result[i] = (float) vector[i] * alpha;
00653     }
00654 }
00655 
00656 /* inline */
00657 void copy_vectorf(int n, float *source, float *dest)
00658 {
00659     int i;
00660     for (i = 0; i < n; i++)
00661         dest[i] = source[i];
00662 }
00663 
00664 /* inline */
00665 double vectors_inner_productf(int n, float *vector1, float *vector2)
00666 {
00667     int i;
00668     double result = 0;
00669     for (i = 0; i < n; i++) {
00670         result += vector1[i] * vector2[i];
00671     }
00672 
00673     return result;
00674 }
00675 
00676 /* inline */
00677 void set_vector_val(int n, double val, double *result)
00678 {
00679     int i;
00680     for (i = 0; i < n; i++)
00681         result[i] = val;
00682 }
00683 
00684 /* inline */
00685 void set_vector_valf(int n, float val, float* result)
00686 {
00687     int i;
00688     for (i = 0; i < n; i++)
00689         result[i] = val;
00690 }
00691 
00692 /* inline */
00693 double max_absf(int n, float *vector)
00694 {
00695     int i;
00696     float max_val = -1e30f;
00697     for (i = 0; i < n; i++)
00698         if (fabs(vector[i]) > max_val)
00699             max_val = (float) (fabs(vector[i]));
00700 
00701     return max_val;
00702 }
00703 
00704 /* inline */
00705 void square_vec(int n, float *vec)
00706 {
00707     int i;
00708     for (i = 0; i < n; i++) {
00709         vec[i] *= vec[i];
00710     }
00711 }
00712 
00713 /* inline */
00714 void invert_vec(int n, float *vec)
00715 {
00716     int i;
00717     float v;
00718     for (i = 0; i < n; i++) {
00719         if ((v = vec[i]) != 0.0)
00720             vec[i] = 1.0f / v;
00721     }
00722 }
00723 
00724 /* inline */
00725 void sqrt_vec(int n, float *vec)
00726 {
00727     int i;
00728     double d;
00729     for (i = 0; i < n; i++) {
00730         /* do this in two steps to avoid a bug in gcc-4.00 on AIX */
00731         d = sqrt(vec[i]);
00732         vec[i] = (float) d;
00733     }
00734 }
00735 
00736 /* inline */
00737 void sqrt_vecf(int n, float *source, float *target)
00738 {
00739     int i;
00740     double d;
00741     float v;
00742     for (i = 0; i < n; i++) {
00743         if ((v = source[i]) >= 0.0) {
00744             /* do this in two steps to avoid a bug in gcc-4.00 on AIX */
00745             d = sqrt(v);
00746             target[i] = (float) d;
00747         }
00748     }
00749 }
00750 
00751 /* inline */
00752 void invert_sqrt_vec(int n, float *vec)
00753 {
00754     int i;
00755     double d;
00756     float v;
00757     for (i = 0; i < n; i++) {
00758         if ((v = vec[i]) > 0.0) {
00759             /* do this in two steps to avoid a bug in gcc-4.00 on AIX */
00760             d = 1. / sqrt(v);
00761             vec[i] = (float) d;
00762         }
00763     }
00764 }
00765 
00766 #ifdef UNUSED
00767 /* inline */
00768 void init_vec_orth1f(int n, float *vec)
00769 {
00770     /* randomly generate a vector orthogonal to 1 (i.e., with mean 0) */
00771     int i;
00772 
00773     for (i = 0; i < n; i++)
00774         vec[i] = (float) (rand() % RANGE);
00775 
00776     orthog1f(n, vec);
00777 }
00778 
00779 
00780  /* sparse matrix extensions: */
00781 
00782 /* inline */
00783 void mat_mult_vecf(vtx_data * L, int n, float *vec, float *result)
00784 {
00785     /* compute result= -L*vec */
00786     int i, j;
00787     float sum;
00788     int *edges;
00789     float *ewgts;
00790 
00791     for (i = 0; i < n; i++) {
00792         sum = 0;
00793         edges = L[i].edges;
00794         ewgts = L[i].ewgts;
00795         for (j = 0; j < L[i].nedges; j++) {
00796             sum -= ewgts[j] * vec[edges[j]];
00797         }
00798         result[i] = sum;
00799     }
00800 }
00801 #endif
00802 
00803 #endif