GRASS 8 Programmer's Manual  8.5.0dev(2025)-c070206eb1
la.c
Go to the documentation of this file.
1 /******************************************************************************
2  * la.c
3  * wrapper modules for linear algebra problems
4  * linking to BLAS / LAPACK (and others?)
5 
6  * @Copyright David D.Gray <ddgray@armadce.demon.co.uk>
7  * 26th. Sep. 2000
8  * Last updated:
9  * 2006-11-23
10  * 2015-01-20
11 
12  * This file is part of GRASS. It is free software. You can
13  * redistribute it and/or modify it under the terms of
14  * the GNU General Public License as published by the Free Software
15  * Foundation; either version 2 of the License, or (at your option)
16  * any later version.
17 
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22 
23  ******************************************************************************/
24 
25 #include <grass/config.h>
26 
27 #if defined(HAVE_LIBBLAS) && defined(HAVE_LIBLAPACK)
28 
29 #include <math.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 
34 #if defined(_MSC_VER)
35 #include <complex.h>
36 #define LAPACK_COMPLEX_CUSTOM
37 #define lapack_complex_float _Fcomplex
38 #define lapack_complex_double _Dcomplex
39 #endif
40 
41 #include <lapacke.h>
42 #if defined(HAVE_CBLAS_ATLAS_H)
43 #include <cblas-atlas.h>
44 #else
45 #include <cblas.h>
46 #endif // HAVE_CBLAS_ATLAS_H
47 
48 #include <grass/gis.h>
49 #include <grass/glocale.h>
50 #include <grass/la.h>
51 
52 static int egcmp(const void *pa, const void *pb);
53 
54 /*!
55  * \fn mat_struct *G_matrix_init(int rows, int cols, int ldim)
56  *
57  * \brief Initialize a matrix structure
58  *
59  * Initialize a matrix structure
60  *
61  * \param rows
62  * \param cols
63  * \param ldim
64  * \return mat_struct
65  */
66 mat_struct *G_matrix_init(int rows, int cols, int ldim)
67 {
68  mat_struct *tmp_arry;
69 
70  if (rows < 1 || cols < 1 || ldim < rows) {
71  G_warning(_("Matrix dimensions out of range"));
72  return NULL;
73  }
74 
75  tmp_arry = (mat_struct *)G_malloc(sizeof(mat_struct));
76  tmp_arry->rows = rows;
77  tmp_arry->cols = cols;
78  tmp_arry->ldim = ldim;
79  tmp_arry->type = MATRIX_;
80  tmp_arry->v_indx = -1;
81 
82  tmp_arry->vals = (double *)G_calloc(ldim * cols, sizeof(double));
83  tmp_arry->is_init = 1;
84 
85  return tmp_arry;
86 }
87 
88 /*!
89  * \fn int G_matrix_zero (mat_struct *A)
90  *
91  * \brief Clears (or resets) the matrix values to 0
92  *
93  * \param A
94  * \return 0 on error; 1 on success
95  */
97 {
98  if (!A->vals)
99  return 0;
100 
101  memset(A->vals, 0, (A->ldim * A->cols) * sizeof(double));
102 
103  return 1;
104 }
105 
106 /*!
107  * \fn int G_matrix_set(mat_struct *A, int rows, int cols, int ldim)
108  *
109  * \brief Set parameters for an initialized matrix
110  *
111  * Set parameters for matrix <b>A</b> that is allocated,
112  * but not yet fully initialized. Is an alternative to G_matrix_init().
113  *
114  * \param A
115  * \param rows
116  * \param cols
117  * \param ldim
118  * \return int
119  */
120 int G_matrix_set(mat_struct *A, int rows, int cols, int ldim)
121 {
122  if (rows < 1 || cols < 1 || ldim < 0) {
123  G_warning(_("Matrix dimensions out of range"));
124  return -1;
125  }
126 
127  A->rows = rows;
128  A->cols = cols;
129  A->ldim = ldim;
130  A->type = MATRIX_;
131  A->v_indx = -1;
132 
133  A->vals = (double *)G_calloc(ldim * cols, sizeof(double));
134  A->is_init = 1;
135 
136  return 0;
137 }
138 
139 /*!
140  * \fn mat_struct *G_matrix_copy (const mat_struct *A)
141  *
142  * \brief Copy a matrix
143  *
144  * Copy matrix <b>A</b> by exactly duplicating its contents.
145  *
146  * \param A
147  * \return mat_struct
148  */
150 {
151  mat_struct *B;
152 
153  if (!A->is_init) {
154  G_warning(_("Matrix is not initialised fully."));
155  return NULL;
156  }
157 
158  if ((B = G_matrix_init(A->rows, A->cols, A->ldim)) == NULL) {
159  G_warning(_("Unable to allocate space for matrix copy"));
160  return NULL;
161  }
162 
163  memcpy(&B->vals[0], &A->vals[0],
164  (size_t)A->cols * A->ldim * sizeof(double));
165 
166  return B;
167 }
168 
169 /*!
170  * \fn mat_struct *G_matrix_add (mat_struct *mt1, mat_struct *mt2)
171  *
172  * \brief Adds two matrices
173  *
174  * Adds two matrices <b>mt1</b> and <b>mt2</b> and returns a
175  * resulting matrix. The return structure is automatically initialized.
176  *
177  * \param mt1
178  * \param mt2
179  * \return mat_struct
180  */
182 {
183  return G__matrix_add(mt1, mt2, 1, 1);
184 }
185 
186 /*!
187  * \fn mat_struct *G_matrix_subtract (mat_struct *mt1, mat_struct *mt2)
188  *
189  * \brief Subtract two matrices
190  *
191  * Subtracts two matrices <b>mt1</b> and <b>mt2</b> and returns
192  * a resulting matrix. The return matrix is automatically initialized.
193  *
194  * \param mt1
195  * \param mt2
196  * \return mat_struct
197  */
199 {
200  return G__matrix_add(mt1, mt2, 1, -1);
201 }
202 
203 /*!
204  * \fn mat_struct *G_matrix_scalar_mul(double scalar, mat_struct *matrix,
205  * mat_struct *out)
206  *
207  * \brief Calculates the scalar-matrix multiplication
208  *
209  * Calculates the scalar-matrix multiplication
210  *
211  * \param scalar
212  * \param matrix
213  * \param out
214  * \return mat_struct
215  */
216 mat_struct *G_matrix_scalar_mul(double scalar, mat_struct *matrix,
217  mat_struct *out)
218 {
219  int m, n, i, j;
220 
221  if (matrix == NULL) {
222  G_warning(_("Input matrix is uninitialized"));
223  return NULL;
224  }
225 
226  if (out == NULL)
227  out = G_matrix_init(matrix->rows, matrix->cols, matrix->rows);
228 
229  if (out->rows != matrix->rows || out->cols != matrix->cols)
230  out = G_matrix_resize(out, matrix->rows, matrix->cols);
231 
232  m = matrix->rows;
233  n = matrix->cols;
234 
235  for (i = 0; i < m; i++) {
236  for (j = 0; j < n; j++) {
237  double value = scalar * G_matrix_get_element(matrix, i, j);
238 
239  G_matrix_set_element(out, i, j, value);
240  }
241  }
242 
243  return (out);
244 }
245 
246 /*!
247  * \fn mat_struct *G_matrix_scale (mat_struct *mt1, const double c)
248  *
249  * \brief Scale a matrix by a scalar value
250  *
251  * Scales matrix <b>mt1</b> by scalar value <b>c</b>. The
252  * resulting matrix is automatically initialized.
253  *
254  * \param mt1
255  * \param c
256  * \return mat_struct
257  */
258 mat_struct *G_matrix_scale(mat_struct *mt1, const double c)
259 {
260  return G__matrix_add(mt1, NULL, c, 0);
261 }
262 
263 /*!
264  * \fn mat_struct *G__matrix_add (mat_struct *mt1, mat_struct *mt2, const double
265  * c1, const double c2)
266  *
267  * \brief General add/subtract/scalar multiply routine
268  *
269  * General add/subtract/scalar multiply routine. <b>c2</b> may be
270  * zero, but <b>c1</b> must be non-zero.
271  *
272  * \param mt1
273  * \param mt2
274  * \param c1
275  * \param c2
276  * \return mat_struct
277  */
278 mat_struct *G__matrix_add(mat_struct *mt1, mat_struct *mt2, const double c1,
279  const double c2)
280 {
281  mat_struct *mt3;
282  int i, j; /* loop variables */
283 
284  if (c1 == 0) {
285  G_warning(_("First scalar multiplier must be non-zero"));
286  return NULL;
287  }
288 
289  if (c2 == 0) {
290  if (!mt1->is_init) {
291  G_warning(_("One or both input matrices uninitialised"));
292  return NULL;
293  }
294  }
295 
296  else {
297 
298  if (!((mt1->is_init) && (mt2->is_init))) {
299  G_warning(_("One or both input matrices uninitialised"));
300  return NULL;
301  }
302 
303  if (mt1->rows != mt2->rows || mt1->cols != mt2->cols) {
304  G_warning(_("Matrix order does not match"));
305  return NULL;
306  }
307  }
308 
309  if ((mt3 = G_matrix_init(mt1->rows, mt1->cols, mt1->ldim)) == NULL) {
310  G_warning(_("Unable to allocate space for matrix sum"));
311  return NULL;
312  }
313 
314  if (c2 == 0) {
315 
316  for (i = 0; i < mt3->rows; i++) {
317  for (j = 0; j < mt3->cols; j++) {
318  mt3->vals[i + mt3->ldim * j] =
319  c1 * mt1->vals[i + mt1->ldim * j];
320  }
321  }
322  }
323 
324  else {
325 
326  for (i = 0; i < mt3->rows; i++) {
327  for (j = 0; j < mt3->cols; j++) {
328  mt3->vals[i + mt3->ldim * j] =
329  c1 * mt1->vals[i + mt1->ldim * j] +
330  c2 * mt2->vals[i + mt2->ldim * j];
331  }
332  }
333  }
334 
335  return mt3;
336 }
337 
338 /*!
339  * \fn mat_struct *G_matrix_product (mat_struct *mt1, mat_struct *mt2)
340  *
341  * \brief Returns product of two matrices
342  *
343  * Returns a matrix with the product of matrix <b>mt1</b> and
344  * <b>mt2</b>. The return matrix is automatically initialized.
345  *
346  * \param mt1
347  * \param mt2
348  * \return mat_struct
349  */
351 {
352  mat_struct *mt3;
353  double unity = 1., zero = 0.;
354  int rows, cols, interdim, lda, ldb;
355 
356  if (!((mt1->is_init) || (mt2->is_init))) {
357  G_warning(_("One or both input matrices uninitialised"));
358  return NULL;
359  }
360 
361  if (mt1->cols != mt2->rows) {
362  G_warning(_("Matrix order does not match"));
363  return NULL;
364  }
365 
366  if ((mt3 = G_matrix_init(mt1->rows, mt2->cols, mt1->ldim)) == NULL) {
367  G_warning(_("Unable to allocate space for matrix product"));
368  return NULL;
369  }
370 
371  /* Call the driver */
372 
373  rows = (int)mt1->rows;
374  interdim = (int)mt1->cols;
375  cols = (int)mt2->cols;
376 
377  lda = (int)mt1->ldim;
378  ldb = (int)mt2->ldim;
379 
380  cblas_dgemm(CblasColMajor, CblasNoTrans, CblasNoTrans, rows, cols, interdim,
381  unity, mt1->vals, lda, mt2->vals, ldb, zero, mt3->vals, lda);
382 
383  return mt3;
384 }
385 
386 /*!
387  * \fn mat_struct *G_matrix_transpose (mat_struct *mt)
388  *
389  * \brief Transpose a matrix
390  *
391  * Transpose matrix <b>m1</b> by creating a new one and
392  * populating with transposed elements. The return matrix is
393  * automatically initialized.
394  *
395  * \param mt
396  * \return mat_struct
397  */
399 {
400  mat_struct *mt1;
401  int ldim, ldo;
402  double *dbo, *dbt, *dbx, *dby;
403  int cnt, cnt2;
404 
405  /* Word align the workspace blocks */
406  if (mt->cols % 2 == 0)
407  ldim = mt->cols;
408  else
409  ldim = mt->cols + 1;
410 
411  mt1 = G_matrix_init(mt->cols, mt->rows, ldim);
412 
413  /* Set initial values for reading arrays */
414  dbo = &mt->vals[0];
415  dbt = &mt1->vals[0];
416  ldo = mt->ldim;
417 
418  for (cnt = 0; cnt < mt->cols; cnt++) {
419  dbx = dbo;
420  dby = dbt;
421 
422  for (cnt2 = 0; cnt2 < ldo - 1; cnt2++) {
423  *dby = *dbx;
424  dby += ldim;
425  dbx++;
426  }
427 
428  *dby = *dbx;
429 
430  if (cnt < mt->cols - 1) {
431  dbo += ldo;
432  dbt++;
433  }
434  }
435 
436  return mt1;
437 }
438 
439 /*!
440  * \fn int G_matrix_LU_solve (const mat_struct *mt1, mat_struct **xmat0,
441  * const mat_struct *bmat, mat_type mtype)
442  *
443  * \brief Solve a general system A.X = B
444  *
445  * Solve a general system A.X = B, where A is a NxN matrix, X and B are
446  * NxC matrices, and we are to solve for C arrays in X given B. Uses LU
447  * decomposition.<br>
448  * Links to LAPACK function dgesv_() and similar to perform the core routine.
449  * (By default solves for a general non-symmetric matrix.)<br>
450  * mtype is a flag to indicate what kind of matrix (real/complex, Hermitian,
451  * symmetric, general etc.) is used (NONSYM, SYM, HERMITIAN).<br>
452  * <b>Warning:</b> NOT YET COMPLETE: only some solutions' options
453  * available. Now, only general real matrix is supported.
454  *
455  * \param mt1
456  * \param xmat0
457  * \param bmat
458  * \param mtype
459  * \return int
460  */
461 
462 /*** NOT YET COMPLETE: only some solutions' options available ***/
463 
464 int G_matrix_LU_solve(const mat_struct *mt1, mat_struct **xmat0,
465  const mat_struct *bmat, mat_type mtype)
466 {
467  mat_struct *wmat, *xmat, *mtx;
468 
469  if (mt1->is_init == 0 || bmat->is_init == 0) {
470  G_warning(_("Input: one or both data matrices uninitialised"));
471  return -1;
472  }
473 
474  if (mt1->rows != mt1->cols || mt1->rows < 1) {
475  G_warning(_("Principal matrix is not properly dimensioned"));
476  return -1;
477  }
478 
479  if (bmat->cols < 1) {
480  G_warning(_("Input: you must have at least one array to solve"));
481  return -1;
482  }
483 
484  /* Now create solution matrix by copying the original coefficient matrix */
485  if ((xmat = G_matrix_copy(bmat)) == NULL) {
486  G_warning(_("Could not allocate space for solution matrix"));
487  return -1;
488  }
489 
490  /* Create working matrix for the coefficient array */
491  if ((mtx = G_matrix_copy(mt1)) == NULL) {
492  G_warning(_("Could not allocate space for working matrix"));
493  return -1;
494  }
495 
496  /* Copy the contents of the data matrix, to preserve the
497  original information
498  */
499  if ((wmat = G_matrix_copy(bmat)) == NULL) {
500  G_warning(_("Could not allocate space for working matrix"));
501  return -1;
502  }
503 
504  /* Now call appropriate LA driver to solve equations */
505  switch (mtype) {
506 
507  case NONSYM: {
508  int *perm, res_info;
509  int num_eqns, nrhs, lda, ldb;
510 
511  perm = (int *)G_malloc(wmat->rows * sizeof(int));
512 
513  /* Set fields to pass to fortran routine */
514  num_eqns = (int)mt1->rows;
515  nrhs = (int)wmat->cols;
516  lda = (int)mt1->ldim;
517  ldb = (int)wmat->ldim;
518 
519  /* Call LA driver */
520  res_info = LAPACKE_dgesv(LAPACK_COL_MAJOR, num_eqns, nrhs, mtx->vals,
521  lda, perm, wmat->vals, ldb);
522 
523  /* Copy the results from the modified data matrix, taking account
524  of pivot permutations ???
525  */
526 
527  /*
528  for(indx1 = 0; indx1 < num_eqns; indx1++) {
529  iperm = perm[indx1];
530  ptin = &wmat->vals[0] + indx1;
531  ptout = &xmat->vals[0] + iperm;
532 
533  for(indx2 = 0; indx2 < nrhs - 1; indx2++) {
534  *ptout = *ptin;
535  ptin += wmat->ldim;
536  ptout += xmat->ldim;
537  }
538 
539  *ptout = *ptin;
540  }
541  */
542 
543  memcpy(xmat->vals, wmat->vals,
544  (size_t)wmat->cols * wmat->ldim * sizeof(double));
545 
546  /* Free temp arrays */
547  G_free(perm);
548  G_matrix_free(wmat);
549  G_matrix_free(mtx);
550 
551  if (res_info > 0) {
552  G_warning(
553  _("Matrix (or submatrix is singular). Solution undetermined"));
554  return 1;
555  }
556  else if (res_info < 0) {
557  G_warning(_("Problem in LA routine."));
558  return -1;
559  }
560  break;
561  }
562  default: {
563  G_warning(_("Procedure not yet available for selected matrix type"));
564  return -1;
565  }
566  } /* end switch */
567 
568  *xmat0 = xmat;
569 
570  return 0;
571 }
572 
573 /*!
574  * \fn mat_struct *G_matrix_inverse (mat_struct *mt)
575  *
576  * \brief Returns the matrix inverse
577  *
578  * Calls G_matrix_LU_solve() to obtain matrix inverse using LU
579  * decomposition. Returns NULL on failure.
580  *
581  * \param mt
582  * \return mat_struct
583  */
585 {
586  mat_struct *mt0, *res;
587  int i, j, k; /* loop */
588 
589  if (mt->rows != mt->cols) {
590  G_warning(_("Matrix is not square. Cannot determine inverse"));
591  return NULL;
592  }
593 
594  if ((mt0 = G_matrix_init(mt->rows, mt->rows, mt->ldim)) == NULL) {
595  G_warning(_("Unable to allocate space for matrix"));
596  return NULL;
597  }
598 
599  /* Set `B' matrix to unit matrix */
600  for (i = 0; i < mt0->rows - 1; i++) {
601  mt0->vals[i + i * mt0->ldim] = 1.0;
602 
603  for (j = i + 1; j < mt0->cols; j++) {
604  mt0->vals[i + j * mt0->ldim] = mt0->vals[j + i * mt0->ldim] = 0.0;
605  }
606  }
607 
608  mt0->vals[mt0->rows - 1 + (mt0->rows - 1) * mt0->ldim] = 1.0;
609 
610  /* Solve system */
611  if ((k = G_matrix_LU_solve(mt, &res, mt0, NONSYM)) == 1) {
612  G_warning(_("Matrix is singular"));
613  G_matrix_free(mt0);
614  return NULL;
615  }
616  else if (k < 0) {
617  G_warning(_("Problem in LA procedure."));
618  G_matrix_free(mt0);
619  return NULL;
620  }
621  else {
622  G_matrix_free(mt0);
623  return res;
624  }
625 }
626 
627 /*!
628  * \fn void G_matrix_free (mat_struct *mt)
629  *
630  * \brief Free up allocated matrix
631  *
632  * Free up allocated matrix.
633  *
634  * \param mt
635  * \return void
636  */
638 {
639  if (mt->is_init)
640  G_free(mt->vals);
641 
642  G_free(mt);
643 }
644 
645 /*!
646  * \fn void G_matrix_print (mat_struct *mt)
647  *
648  * \brief Print out a matrix
649  *
650  * Print out a representation of the matrix to standard output.
651  *
652  * \param mt
653  * \return void
654  */
656 {
657  int i, j;
658  char buf[2048], numbuf[64];
659 
660  for (i = 0; i < mt->rows; i++) {
661  G_strlcpy(buf, "", sizeof(buf));
662 
663  for (j = 0; j < mt->cols; j++) {
664  snprintf(numbuf, sizeof(numbuf), "%14.6f",
665  G_matrix_get_element(mt, i, j));
666  strcat(buf, numbuf);
667  if (j < mt->cols - 1)
668  strcat(buf, ", ");
669  }
670 
671  G_message("%s", buf);
672  }
673 
674  fprintf(stderr, "\n");
675 }
676 
677 /*!
678  * \fn int G_matrix_set_element (mat_struct *mt, int rowval, int colval, double
679  * val)
680  *
681  * \brief Set the value of the (i, j)th element
682  *
683  * Set the value of the (i, j)th element to a double value. Index values
684  * are C-like ie. zero-based. The row number is given first as is
685  * conventional. Returns -1 if the accessed cell is outside the bounds.
686  *
687  * \param mt
688  * \param rowval
689  * \param colval
690  * \param val
691  * \return int
692  */
693 int G_matrix_set_element(mat_struct *mt, int rowval, int colval, double val)
694 {
695  if (!mt->is_init) {
696  G_warning(_("Element array has not been allocated"));
697  return -1;
698  }
699 
700  if (rowval >= mt->rows || colval >= mt->cols || rowval < 0 || colval < 0) {
701  G_warning(_("Specified element is outside array bounds"));
702  return -1;
703  }
704 
705  mt->vals[rowval + colval * mt->ldim] = (double)val;
706 
707  return 0;
708 }
709 
710 /*!
711  * \fn double G_matrix_get_element (mat_struct *mt, int rowval, int colval)
712  *
713  * \brief Retrieve value of the (i,j)th element
714  *
715  * Retrieve the value of the (i, j)th element to a double value. Index
716  * values are C-like ie. zero-based.
717  * <b>Note:</b> Does currently not set an error flag for bounds checking.
718  *
719  * \param mt
720  * \param rowval
721  * \param colval
722  * \return double
723  */
724 double G_matrix_get_element(mat_struct *mt, int rowval, int colval)
725 {
726  double val;
727 
728  /* Should do some checks, but this would require an error control
729  system: later? */
730 
731  return (val = (double)mt->vals[rowval + colval * mt->ldim]);
732 }
733 
734 /*!
735  * \fn vec_struct *G_matvect_get_column (mat_struct *mt, int col)
736  *
737  * \brief Retrieve a column of the matrix to a vector structure
738  *
739  * Retrieve a column of matrix <b>mt</b> to a returning vector structure
740  *
741  * \param mt
742  * \param col
743  * \return vec_struct
744  */
746 {
747  int i; /* loop */
748  vec_struct *vc1;
749 
750  if (col < 0 || col >= mt->cols) {
751  G_warning(_("Specified matrix column index is outside range"));
752  return NULL;
753  }
754 
755  if (!mt->is_init) {
756  G_warning(_("Matrix is not initialised"));
757  return NULL;
758  }
759 
760  if ((vc1 = G_vector_init(mt->rows, mt->ldim, CVEC)) == NULL) {
761  G_warning(_("Could not allocate space for vector structure"));
762  return NULL;
763  }
764 
765  for (i = 0; i < mt->rows; i++)
766  G_matrix_set_element((mat_struct *)vc1, i, 0,
767  G_matrix_get_element(mt, i, col));
768 
769  return vc1;
770 }
771 
772 /*!
773  * \fn vec_struct *G_matvect_get_row (mat_struct *mt, int row)
774  *
775  * \brief Retrieve a row of the matrix to a vector structure
776  *
777  * Retrieves a row from matrix <b>mt</b> and returns it in a vector
778  * structure.
779  *
780  * \param mt
781  * \param row
782  * \return vec_struct
783  */
785 {
786  int i; /* loop */
787  vec_struct *vc1;
788 
789  if (row < 0 || row >= mt->cols) {
790  G_warning(_("Specified matrix row index is outside range"));
791  return NULL;
792  }
793 
794  if (!mt->is_init) {
795  G_warning(_("Matrix is not initialised"));
796  return NULL;
797  }
798 
799  if ((vc1 = G_vector_init(mt->cols, mt->ldim, RVEC)) == NULL) {
800  G_warning(_("Could not allocate space for vector structure"));
801  return NULL;
802  }
803 
804  for (i = 0; i < mt->cols; i++)
805  G_matrix_set_element((mat_struct *)vc1, 0, i,
806  G_matrix_get_element(mt, row, i));
807 
808  return vc1;
809 }
810 
811 /*!
812  * \fn int G_matvect_extract_vector (mat_struct *mt, vtype vt, int indx)
813  *
814  * \brief Convert matrix to vector
815  *
816  * Convert the matrix <b>mt</b> to a vector structure. The vtype,
817  * <b>vt</b>, is RVEC or CVEC which specifies a row vector or column
818  * vector. The index, <b>indx</b>, indicates the row/column number (zero based).
819  *
820  * \param mt
821  * \param vt
822  * \param indx
823  * \return int
824  */
826 {
827  if (vt == RVEC && indx >= mt->rows) {
828  G_warning(_("Specified row index is outside range"));
829  return -1;
830  }
831 
832  else if (vt == CVEC && indx >= mt->cols) {
833  G_warning(_("Specified column index is outside range"));
834  return -1;
835  }
836 
837  switch (vt) {
838 
839  case RVEC: {
840  mt->type = ROWVEC_;
841  mt->v_indx = indx;
842  break;
843  }
844 
845  case CVEC: {
846  mt->type = COLVEC_;
847  mt->v_indx = indx;
848  break;
849  }
850 
851  default: {
852  G_warning(_("Unknown vector type."));
853  return -1;
854  }
855  }
856 
857  return 0;
858 }
859 
860 /*!
861  * \fn int G_matvect_retrieve_matrix (vec_struct *vc)
862  *
863  * \brief Revert a vector to matrix
864  *
865  * Revert vector <b>vc</b> to a matrix.
866  *
867  * \param vc
868  * \return int
869  */
871 {
872  /* We have to take the integrity of the vector structure
873  largely on trust
874  */
875 
876  vc->type = MATRIX_;
877  vc->v_indx = -1;
878 
879  return 0;
880 }
881 
882 /*!
883  * \fn vec_struct *G_matvect_product(mat_struct *A, vec_struct *b, vec_struct
884  * *out)
885  *
886  * \brief Calculates the matrix-vector product
887  *
888  * Calculates the product of a matrix and a vector
889  *
890  * \param A
891  * \param b
892  * \return vec_struct
893  */
895 {
896  unsigned int i, m, n, j;
897  register double sum;
898 
899  /* G_message("A=%d,%d,%d", A->cols, A->rows, A->ldim); */
900  /* G_message("B=%d,%d,%d", b->cols, b->rows, b->ldim); */
901  if (A->cols != b->cols) {
902  G_warning(_("Input matrix and vector have differing dimensions1"));
903 
904  return NULL;
905  }
906  if (!out) {
907  G_warning(_("Output vector is uninitialized"));
908  return NULL;
909  }
910  /* if (out->ldim != A->rows) { */
911  /* G_warning (_("Output vector has incorrect dimension")); */
912  /* exit(1); */
913  /* return NULL; */
914  /* } */
915 
916  m = A->rows;
917  n = A->cols;
918 
919  for (i = 0; i < m; i++) {
920  sum = 0.0;
921  /* int width = A->rows; */
922 
923  for (j = 0; j < n; j++) {
924 
925  sum +=
926  G_matrix_get_element(A, i, j) * G_matrix_get_element(b, 0, j);
927  /*sum += A->vals[i + j * width] * b->vals[j]; */
928  out->vals[i] = sum;
929  }
930  }
931  return (out);
932 }
933 
934 /*!
935  * \fn vec_struct *G_vector_init (int cells, int ldim, vtype vt)
936  *
937  * \brief Initialize a vector structure
938  *
939  * Returns an initialized vector structure with <b>cell</b> cells,
940  * of dimension <b>ldim</b>, and of type <b>vt</b>.
941  *
942  * \param cells
943  * \param ldim
944  * \param vt
945  * \return vec_struct
946  */
947 vec_struct *G_vector_init(int cells, int ldim, vtype vt)
948 {
949  vec_struct *tmp_arry;
950 
951  if ((cells < 1) || (vt == RVEC && ldim < 1) ||
952  (vt == CVEC && ldim < cells) || ldim < 0) {
953  G_warning("Vector dimensions out of range.");
954  return NULL;
955  }
956 
957  tmp_arry = (vec_struct *)G_malloc(sizeof(vec_struct));
958 
959  if (vt == RVEC) {
960  tmp_arry->rows = 1;
961  tmp_arry->cols = cells;
962  tmp_arry->ldim = ldim;
963  tmp_arry->type = ROWVEC_;
964  }
965 
966  else if (vt == CVEC) {
967  tmp_arry->rows = cells;
968  tmp_arry->cols = 1;
969  tmp_arry->ldim = ldim;
970  tmp_arry->type = COLVEC_;
971  }
972 
973  tmp_arry->v_indx = 0;
974 
975  tmp_arry->vals = (double *)G_calloc(ldim * tmp_arry->cols, sizeof(double));
976  tmp_arry->is_init = 1;
977 
978  return tmp_arry;
979 }
980 
981 /*!
982  * \fn void G_vector_free (vec_struct *v)
983  *
984  * \brief Free an allocated vector structure
985  *
986  * Free an allocated vector structure.
987  *
988  * \param v
989  * \return void
990  */
992 {
993  if (v->is_init)
994  G_free(v->vals);
995 
996  G_free(v);
997 }
998 
999 /*!
1000  * \fn vec_struct *G_vector_sub (vec_struct *v1, vec_struct *v2, vec_struct
1001  * *out)
1002  *
1003  * \brief Subtract two vectors
1004  *
1005  * Subtracts two vectors, <b>v1</b> and <b>v2</b>, and returns and
1006  * populates vector <b>out</b>.
1007  *
1008  * \param v1
1009  * \param v2
1010  * \param out
1011  * \return vec_struct
1012  */
1014 {
1015  int idx1, idx2, idx0;
1016  int i;
1017 
1018  if (!out->is_init) {
1019  G_warning(_("Output vector is uninitialized"));
1020  return NULL;
1021  }
1022 
1023  if (v1->type != v2->type) {
1024  G_warning(_("Vectors are not of the same type"));
1025  return NULL;
1026  }
1027 
1028  if (v1->type != out->type) {
1029  G_warning(_("Output vector is of incorrect type"));
1030  return NULL;
1031  }
1032 
1033  if (v1->type == MATRIX_) {
1034  G_warning(_("Matrices not allowed"));
1035  return NULL;
1036  }
1037 
1038  if ((v1->type == ROWVEC_ && v1->cols != v2->cols) ||
1039  (v1->type == COLVEC_ && v1->rows != v2->rows)) {
1040  G_warning(_("Vectors have differing dimensions"));
1041  return NULL;
1042  }
1043 
1044  if ((v1->type == ROWVEC_ && v1->cols != out->cols) ||
1045  (v1->type == COLVEC_ && v1->rows != out->rows)) {
1046  G_warning(_("Output vector has incorrect dimension"));
1047  return NULL;
1048  }
1049 
1050  idx1 = (v1->v_indx > 0) ? v1->v_indx : 0;
1051  idx2 = (v2->v_indx > 0) ? v2->v_indx : 0;
1052  idx0 = (out->v_indx > 0) ? out->v_indx : 0;
1053 
1054  if (v1->type == ROWVEC_) {
1055  for (i = 0; i < v1->cols; i++)
1056  G_matrix_set_element(out, idx0, i,
1057  G_matrix_get_element(v1, idx1, i) -
1058  G_matrix_get_element(v2, idx2, i));
1059  }
1060  else {
1061  for (i = 0; i < v1->rows; i++)
1062  G_matrix_set_element(out, i, idx0,
1063  G_matrix_get_element(v1, i, idx1) -
1064  G_matrix_get_element(v2, i, idx2));
1065  }
1066 
1067  return out;
1068 }
1069 
1070 /*!
1071  * \fn int G_vector_set (vec_struct *A, int cells, int ldim, vtype vt, int
1072  * vindx)
1073  *
1074  * \brief Set parameters for vector structure
1075  *
1076  * Set parameters for a vector structure that is
1077  * allocated but not yet initialised fully. The vtype is RVEC or
1078  * CVEC which specifies a row vector or column vector.
1079  *
1080  * \param A
1081  * \param cells
1082  * \param ldim
1083  * \param vt
1084  * \param vindx
1085  * \return int
1086  */
1087 int G_vector_set(vec_struct *A, int cells, int ldim, vtype vt, int vindx)
1088 {
1089  if ((cells < 1) || (vt == RVEC && ldim < 1) ||
1090  (vt == CVEC && ldim < cells) || ldim < 0) {
1091  G_warning(_("Vector dimensions out of range"));
1092  return -1;
1093  }
1094 
1095  if ((vt == RVEC && vindx >= A->cols) || (vt == CVEC && vindx >= A->rows)) {
1096  G_warning(_("Row/column out of range"));
1097  return -1;
1098  }
1099 
1100  if (vt == RVEC) {
1101  A->rows = 1;
1102  A->cols = cells;
1103  A->ldim = ldim;
1104  A->type = ROWVEC_;
1105  }
1106  else {
1107  A->rows = cells;
1108  A->cols = 1;
1109  A->ldim = ldim;
1110  A->type = COLVEC_;
1111  }
1112 
1113  if (vindx < 0)
1114  A->v_indx = 0;
1115  else
1116  A->v_indx = vindx;
1117 
1118  A->vals = (double *)G_calloc(ldim * A->cols, sizeof(double));
1119  A->is_init = 1;
1120 
1121  return 0;
1122 }
1123 
1124 /*!
1125  * \fn double G_vector_norm_euclid (vec_struct *vc)
1126  *
1127  * \brief Calculates euclidean norm
1128  *
1129  * Calculates the euclidean norm of a row or column vector, using BLAS
1130  * routine dnrm2_().
1131  *
1132  * \param vc
1133  * \return double
1134  */
1136 {
1137  int incr, Nval;
1138  double *startpt;
1139 
1140  if (!vc->is_init)
1141  G_fatal_error(_("Matrix is not initialised"));
1142 
1143  if (vc->type == ROWVEC_) {
1144  Nval = (int)vc->cols;
1145  incr = (int)vc->ldim;
1146  if (vc->v_indx < 0)
1147  startpt = vc->vals;
1148  else
1149  startpt = vc->vals + vc->v_indx;
1150  }
1151  else {
1152  Nval = (int)vc->rows;
1153  incr = 1;
1154  if (vc->v_indx < 0)
1155  startpt = vc->vals;
1156  else
1157  startpt = vc->vals + vc->v_indx * vc->ldim;
1158  }
1159 
1160  /* Call the BLAS routine dnrm2_() */
1161  return cblas_dnrm2(Nval, startpt, incr);
1162 }
1163 
1164 /*!
1165  * \fn double G_vector_norm_maxval (vec_struct *vc, int vflag)
1166  *
1167  * \brief Calculates maximum value
1168  *
1169  * Calculates the maximum value of a row or column vector.
1170  * The vflag setting defines which value to be calculated:
1171  * vflag:
1172  * 1 Indicates maximum value<br>
1173  * -1 Indicates minimum value<br>
1174  * 0 Indicates absolute value [???]
1175  *
1176  * \param vc
1177  * \param vflag
1178  * \return double
1179  */
1180 double G_vector_norm_maxval(vec_struct *vc, int vflag)
1181 {
1182  double xval, *startpt, *curpt;
1183  double cellval;
1184  int ncells, incr;
1185 
1186  if (!vc->is_init)
1187  G_fatal_error(_("Matrix is not initialised"));
1188 
1189  if (vc->type == ROWVEC_) {
1190  ncells = (int)vc->cols;
1191  incr = (int)vc->ldim;
1192  if (vc->v_indx < 0)
1193  startpt = vc->vals;
1194  else
1195  startpt = vc->vals + vc->v_indx;
1196  }
1197  else {
1198  ncells = (int)vc->rows;
1199  incr = 1;
1200  if (vc->v_indx < 0)
1201  startpt = vc->vals;
1202  else
1203  startpt = vc->vals + vc->v_indx * vc->ldim;
1204  }
1205 
1206  xval = *startpt;
1207  curpt = startpt;
1208 
1209  while (ncells > 0) {
1210  if (curpt != startpt) {
1211  switch (vflag) {
1212 
1213  case MAX_POS: {
1214  if (*curpt > xval)
1215  xval = *curpt;
1216  break;
1217  }
1218 
1219  case MAX_NEG: {
1220  if (*curpt < xval)
1221  xval = *curpt;
1222  break;
1223  }
1224 
1225  case MAX_ABS: {
1226  cellval = (double)(*curpt);
1227  if (hypot(cellval, cellval) > (double)xval)
1228  xval = *curpt;
1229  }
1230  } /* switch */
1231  } /* if(curpt != startpt) */
1232 
1233  curpt += incr;
1234  ncells--;
1235  }
1236 
1237  return (double)xval;
1238 }
1239 
1240 /*!
1241  * \fn double G_vector_norm1 (vec_struct *vc)
1242  *
1243  * \brief Calculates the 1-norm of a vector
1244  *
1245  * Calculates the 1-norm of a vector
1246  *
1247  * \param vc
1248  * \return double
1249  */
1251 {
1252  double result = 0.0;
1253  int idx;
1254  int i;
1255 
1256  if (!vc->is_init) {
1257  G_warning(_("Matrix is not initialised"));
1258  return NAN;
1259  }
1260 
1261  idx = (vc->v_indx > 0) ? vc->v_indx : 0;
1262 
1263  if (vc->type == ROWVEC_) {
1264  for (i = 0; i < vc->cols; i++)
1265  result += fabs(G_matrix_get_element(vc, idx, i));
1266  }
1267  else {
1268  for (i = 0; i < vc->rows; i++)
1269  result += fabs(G_matrix_get_element(vc, i, idx));
1270  }
1271 
1272  return result;
1273 }
1274 
1275 /*!
1276  * \fn vec_struct *G_vector_product (vec_struct *v1, vec_struct *v2, vec_struct
1277  * *out)
1278  *
1279  * \brief Calculates the vector product
1280  *
1281  * Calculates the vector product of two vectors
1282  *
1283  * \param v1
1284  * \param v2
1285  * \param out Output vector
1286  * \return vec_struct
1287  */
1289 {
1290  int idx1, idx2, idx0;
1291  int i;
1292 
1293  if (!out->is_init) {
1294  G_warning(_("Output vector is uninitialized"));
1295  return NULL;
1296  }
1297 
1298  if (v1->type != v2->type) {
1299  G_warning(_("Vectors are not of the same type"));
1300  return NULL;
1301  }
1302 
1303  if (v1->type != out->type) {
1304  G_warning(_("Output vector is not the same type as others"));
1305  return NULL;
1306  }
1307 
1308  if (v1->type == MATRIX_) {
1309  G_warning(_("Matrices not allowed"));
1310  return NULL;
1311  }
1312 
1313  if ((v1->type == ROWVEC_ && v1->cols != v2->cols) ||
1314  (v1->type == COLVEC_ && v1->rows != v2->rows)) {
1315  G_warning(_("Vectors have differing dimensions"));
1316  return NULL;
1317  }
1318 
1319  if ((v1->type == ROWVEC_ && v1->cols != out->cols) ||
1320  (v1->type == COLVEC_ && v1->rows != out->rows)) {
1321  G_warning(_("Output vector has incorrect dimension"));
1322  return NULL;
1323  }
1324 
1325  idx1 = (v1->v_indx > 0) ? v1->v_indx : 0;
1326  idx2 = (v2->v_indx > 0) ? v2->v_indx : 0;
1327  idx0 = (out->v_indx > 0) ? out->v_indx : 0;
1328 
1329  if (v1->type == ROWVEC_) {
1330  for (i = 0; i < v1->cols; i++)
1331  G_matrix_set_element(out, idx0, i,
1332  G_matrix_get_element(v1, idx1, i) *
1333  G_matrix_get_element(v2, idx2, i));
1334  }
1335  else {
1336  for (i = 0; i < v1->rows; i++)
1337  G_matrix_set_element(out, i, idx0,
1338  G_matrix_get_element(v1, i, idx1) *
1339  G_matrix_get_element(v2, i, idx2));
1340  }
1341 
1342  return out;
1343 }
1344 
1345 /*!
1346  * \fn vec_struct *G_vector_copy (const vec_struct *vc1, int comp_flag)
1347  *
1348  * \brief Returns a vector copied from <b>vc1</b>. Underlying structure
1349  * is preserved unless DO_COMPACT flag.
1350  *
1351  * \param vc1
1352  * \param comp_flag
1353  * \return vec_struct
1354  */
1355 vec_struct *G_vector_copy(const vec_struct *vc1, int comp_flag)
1356 {
1357  vec_struct *tmp_arry;
1358  int incr1, incr2;
1359  double *startpt1, *startpt2, *curpt1, *curpt2;
1360  int cnt;
1361 
1362  if (!vc1->is_init) {
1363  G_warning(_("Vector structure is not initialised"));
1364  return NULL;
1365  }
1366 
1367  tmp_arry = (vec_struct *)G_malloc(sizeof(vec_struct));
1368 
1369  if (comp_flag == DO_COMPACT) {
1370  if (vc1->type == ROWVEC_) {
1371  tmp_arry->rows = 1;
1372  tmp_arry->cols = vc1->cols;
1373  tmp_arry->ldim = 1;
1374  tmp_arry->type = ROWVEC_;
1375  tmp_arry->v_indx = 0;
1376  }
1377  else if (vc1->type == COLVEC_) {
1378  tmp_arry->rows = vc1->rows;
1379  tmp_arry->cols = 1;
1380  tmp_arry->ldim = vc1->ldim;
1381  tmp_arry->type = COLVEC_;
1382  tmp_arry->v_indx = 0;
1383  }
1384  else {
1385  G_warning("Type is not vector.");
1386  return NULL;
1387  }
1388  }
1389  else if (comp_flag == NO_COMPACT) {
1390  tmp_arry->v_indx = vc1->v_indx;
1391  tmp_arry->rows = vc1->rows;
1392  tmp_arry->cols = vc1->cols;
1393  tmp_arry->ldim = vc1->ldim;
1394  tmp_arry->type = vc1->type;
1395  }
1396  else {
1397  G_warning("Copy method must be specified: [DO,NO]_COMPACT.\n");
1398  return NULL;
1399  }
1400 
1401  tmp_arry->vals =
1402  (double *)G_calloc(tmp_arry->ldim * tmp_arry->cols, sizeof(double));
1403  if (comp_flag == DO_COMPACT) {
1404  if (tmp_arry->type == ROWVEC_) {
1405  startpt1 = tmp_arry->vals;
1406  startpt2 = vc1->vals + vc1->v_indx;
1407  curpt1 = startpt1;
1408  curpt2 = startpt2;
1409  incr1 = 1;
1410  incr2 = vc1->ldim;
1411  cnt = vc1->cols;
1412  }
1413  else if (tmp_arry->type == COLVEC_) {
1414  startpt1 = tmp_arry->vals;
1415  startpt2 = vc1->vals + vc1->v_indx * vc1->ldim;
1416  curpt1 = startpt1;
1417  curpt2 = startpt2;
1418  incr1 = 1;
1419  incr2 = 1;
1420  cnt = vc1->rows;
1421  }
1422  else {
1423  G_warning("Structure type is not vector.");
1424  return NULL;
1425  }
1426  }
1427  else if (comp_flag == NO_COMPACT) {
1428  startpt1 = tmp_arry->vals;
1429  startpt2 = vc1->vals;
1430  curpt1 = startpt1;
1431  curpt2 = startpt2;
1432  incr1 = 1;
1433  incr2 = 1;
1434  cnt = vc1->ldim * vc1->cols;
1435  }
1436  else {
1437  G_warning("Copy method must be specified: [DO,NO]_COMPACT.\n");
1438  return NULL;
1439  }
1440 
1441  while (cnt > 0) {
1442  memcpy(curpt1, curpt2, sizeof(double));
1443  curpt1 += incr1;
1444  curpt2 += incr2;
1445  cnt--;
1446  }
1447 
1448  tmp_arry->is_init = 1;
1449 
1450  return tmp_arry;
1451 }
1452 
1453 /*!
1454  * \fn int G_matrix_read (FILE *fp, mat_struct *out)
1455  *
1456  * \brief Read a matrix from a file stream
1457  *
1458  * Populates matrix structure <b>out</b> with matrix read from file
1459  * stream <b>fp</b>. Matrix <b>out</b> is automatically initialized.
1460  * Returns -1 on error and 0 on success.
1461  *
1462  * \param fp
1463  * \param out
1464  * \return int
1465  */
1466 int G_matrix_read(FILE *fp, mat_struct *out)
1467 {
1468  char buff[100];
1469  int rows, cols;
1470  int i, j, row;
1471  double val;
1472 
1473  /* skip comments */
1474  for (;;) {
1475  if (!G_getl(buff, sizeof(buff), fp))
1476  return -1;
1477  if (buff[0] != '#')
1478  break;
1479  }
1480 
1481  if (sscanf(buff, "Matrix: %d by %d", &rows, &cols) != 2) {
1482  G_warning(_("Input format error"));
1483  return -1;
1484  }
1485 
1486  G_matrix_set(out, rows, cols, rows);
1487 
1488  for (i = 0; i < rows; i++) {
1489  if (fscanf(fp, "row%d:", &row) != 1 || row != i) {
1490  G_warning(_("Input format error"));
1491  return -1;
1492  }
1493  for (j = 0; j < cols; j++) {
1494  if (fscanf(fp, "%lf:", &val) != 1) {
1495  G_warning(_("Input format error"));
1496  return -1;
1497  }
1498 
1499  G_matrix_set_element(out, i, j, val);
1500  }
1501  }
1502 
1503  return 0;
1504 }
1505 
1506 /*!
1507  * \fn mat_struct *G_matrix_resize(mat_struct *in, int rows, int cols)
1508  *
1509  * \brief Resizes a matrix
1510  *
1511  * Resizes a matrix
1512  *
1513  * \param in
1514  * \param rows
1515  * \param cols
1516  * \return mat_struct
1517  */
1518 mat_struct *G_matrix_resize(mat_struct *in, int rows, int cols)
1519 {
1520  mat_struct *matrix;
1521 
1522  matrix = G_matrix_init(rows, cols, rows);
1523  int i, j, p /*, index = 0 */;
1524 
1525  for (i = 0; i < rows; i++)
1526  for (j = 0; j < cols; j++)
1527  G_matrix_set_element(matrix, i, j, G_matrix_get_element(in, i, j));
1528  /* matrix->vals[index++] = in->vals[i + j * cols]; */
1529 
1530  int old_size = in->rows * in->cols;
1531  int new_size = rows * cols;
1532 
1533  if (new_size > old_size)
1534  for (p = old_size; p < new_size; p++)
1535  G_matrix_set_element(matrix, i, j, 0.0);
1536 
1537  return (matrix);
1538 }
1539 
1540 /*!
1541  * \fn int G_matrix_stdin(mat_struct *out)
1542  *
1543  * \brief Read a matrix from standard input
1544  *
1545  * Populates matrix <b>out</b> with matrix read from stdin. Matrix
1546  * <b>out</b> is automatically initialized. Returns -1 on failure or 0
1547  * on success.
1548  *
1549  * \param out
1550  * \return int
1551  */
1553 {
1554  return G_matrix_read(stdin, out);
1555 }
1556 
1557 /*!
1558  * \fn int G_matrix_eigen_sort (vec_struct *d, mat_struct *m)
1559  *
1560  * \brief Sort eigenvectors according to eigenvalues
1561  *
1562  * Sort eigenvectors according to eigenvalues. Returns 0.
1563  *
1564  * \param d
1565  * \param m
1566  * \return int
1567  */
1569 {
1570  mat_struct tmp;
1571  int i, j;
1572  int idx;
1573 
1574  G_matrix_set(&tmp, m->rows + 1, m->cols, m->ldim + 1);
1575 
1576  idx = (d->v_indx > 0) ? d->v_indx : 0;
1577 
1578  /* concatenate (vertically) m and d into tmp */
1579  for (i = 0; i < m->cols; i++) {
1580  for (j = 0; j < m->rows; j++)
1581  G_matrix_set_element(&tmp, j + 1, i, G_matrix_get_element(m, j, i));
1582  if (d->type == ROWVEC_)
1583  G_matrix_set_element(&tmp, 0, i, G_matrix_get_element(d, idx, i));
1584  else
1585  G_matrix_set_element(&tmp, 0, i, G_matrix_get_element(d, i, idx));
1586  }
1587 
1588  /* sort the combined matrix */
1589  qsort(tmp.vals, tmp.cols, tmp.ldim * sizeof(double), egcmp);
1590 
1591  /* split tmp into m and d */
1592  for (i = 0; i < m->cols; i++) {
1593  for (j = 0; j < m->rows; j++)
1594  G_matrix_set_element(m, j, i, G_matrix_get_element(&tmp, j + 1, i));
1595  if (d->type == ROWVEC_)
1596  G_matrix_set_element(d, idx, i, G_matrix_get_element(&tmp, 0, i));
1597  else
1598  G_matrix_set_element(d, i, idx, G_matrix_get_element(&tmp, 0, i));
1599  }
1600 
1601  G_free(tmp.vals);
1602 
1603  return 0;
1604 }
1605 
1606 static int egcmp(const void *pa, const void *pb)
1607 {
1608  double a = *(double *const)pa;
1609  double b = *(double *const)pb;
1610 
1611  if (a > b)
1612  return 1;
1613  if (a < b)
1614  return -1;
1615 
1616  return 0;
1617 }
1618 
1619 #endif // HAVE_LIBLAPACK HAVE_LIBBLAS
1620 
#define NULL
Definition: ccmath.h:32
void G_free(void *)
Free allocated memory.
Definition: gis/alloc.c:147
#define G_calloc(m, n)
Definition: defs/gis.h:95
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
void G_warning(const char *,...) __attribute__((format(printf
#define G_malloc(n)
Definition: defs/gis.h:94
void G_message(const char *,...) __attribute__((format(printf
int G_getl(char *, int, FILE *)
Gets a line of text from a file.
Definition: getl.c:33
size_t G_strlcpy(char *, const char *, size_t)
Safe string copy function.
Definition: strlcpy.c:52
#define _(str)
Definition: glocale.h:10
vec_struct * G_matvect_product(mat_struct *A, vec_struct *b, vec_struct *out)
Calculates the matrix-vector product.
Definition: la.c:894
double G_vector_norm_maxval(vec_struct *vc, int vflag)
Calculates maximum value.
Definition: la.c:1180
vec_struct * G_matvect_get_column(mat_struct *mt, int col)
Retrieve a column of the matrix to a vector structure.
Definition: la.c:745
vec_struct * G_vector_sub(vec_struct *v1, vec_struct *v2, vec_struct *out)
Subtract two vectors.
Definition: la.c:1013
int G_matvect_retrieve_matrix(vec_struct *vc)
Revert a vector to matrix.
Definition: la.c:870
double G_vector_norm_euclid(vec_struct *vc)
Calculates euclidean norm.
Definition: la.c:1135
mat_struct * G_matrix_subtract(mat_struct *mt1, mat_struct *mt2)
Subtract two matrices.
Definition: la.c:198
mat_struct * G_matrix_add(mat_struct *mt1, mat_struct *mt2)
Adds two matrices.
Definition: la.c:181
double G_matrix_get_element(mat_struct *mt, int rowval, int colval)
Retrieve value of the (i,j)th element.
Definition: la.c:724
mat_struct * G__matrix_add(mat_struct *mt1, mat_struct *mt2, const double c1, const double c2)
Definition: la.c:278
mat_struct * G_matrix_inverse(mat_struct *mt)
Returns the matrix inverse.
Definition: la.c:584
int G_matrix_stdin(mat_struct *out)
Read a matrix from standard input.
Definition: la.c:1552
void G_matrix_print(mat_struct *mt)
Print out a matrix.
Definition: la.c:655
mat_struct * G_matrix_copy(const mat_struct *A)
Copy a matrix.
Definition: la.c:149
mat_struct * G_matrix_resize(mat_struct *in, int rows, int cols)
Resizes a matrix.
Definition: la.c:1518
int G_matvect_extract_vector(mat_struct *mt, vtype vt, int indx)
Convert matrix to vector.
Definition: la.c:825
vec_struct * G_vector_init(int cells, int ldim, vtype vt)
Initialize a vector structure.
Definition: la.c:947
mat_struct * G_matrix_product(mat_struct *mt1, mat_struct *mt2)
Returns product of two matrices.
Definition: la.c:350
int G_matrix_LU_solve(const mat_struct *mt1, mat_struct **xmat0, const mat_struct *bmat, mat_type mtype)
Solve a general system A.X = B.
Definition: la.c:464
vec_struct * G_vector_product(vec_struct *v1, vec_struct *v2, vec_struct *out)
Calculates the vector product.
Definition: la.c:1288
mat_struct * G_matrix_init(int rows, int cols, int ldim)
Initialize a matrix structure.
Definition: la.c:66
int suppress_empty_translation_unit_compiler_warning
Definition: la.c:1621
double G_vector_norm1(vec_struct *vc)
Calculates the 1-norm of a vector.
Definition: la.c:1250
int G_matrix_read(FILE *fp, mat_struct *out)
Read a matrix from a file stream.
Definition: la.c:1466
int G_matrix_eigen_sort(vec_struct *d, mat_struct *m)
Sort eigenvectors according to eigenvalues.
Definition: la.c:1568
mat_struct * G_matrix_scale(mat_struct *mt1, const double c)
Scale a matrix by a scalar value.
Definition: la.c:258
void G_vector_free(vec_struct *v)
Free an allocated vector structure.
Definition: la.c:991
vec_struct * G_matvect_get_row(mat_struct *mt, int row)
Retrieve a row of the matrix to a vector structure.
Definition: la.c:784
void G_matrix_free(mat_struct *mt)
Free up allocated matrix.
Definition: la.c:637
vec_struct * G_vector_copy(const vec_struct *vc1, int comp_flag)
Returns a vector copied from vc1. Underlying structure is preserved unless DO_COMPACT flag.
Definition: la.c:1355
int G_vector_set(vec_struct *A, int cells, int ldim, vtype vt, int vindx)
Definition: la.c:1087
int G_matrix_set_element(mat_struct *mt, int rowval, int colval, double val)
Definition: la.c:693
mat_struct * G_matrix_transpose(mat_struct *mt)
Transpose a matrix.
Definition: la.c:398
mat_struct * G_matrix_scalar_mul(double scalar, mat_struct *matrix, mat_struct *out)
Calculates the scalar-matrix multiplication.
Definition: la.c:216
int G_matrix_set(mat_struct *A, int rows, int cols, int ldim)
Set parameters for an initialized matrix.
Definition: la.c:120
int G_matrix_zero(mat_struct *A)
Clears (or resets) the matrix values to 0.
Definition: la.c:96
Wrapper headers for BLAS/LAPACK.
#define DO_COMPACT
Definition: la.h:35
vtype
Definition: la.h:44
@ CVEC
Definition: la.h:44
@ RVEC
Definition: la.h:44
#define MAX_NEG
Definition: la.h:32
#define MAX_ABS
Definition: la.h:33
mat_type
Definition: la.h:42
@ NONSYM
Definition: la.h:42
#define NO_COMPACT
Definition: la.h:36
#define MAX_POS
Definition: la.h:31
@ COLVEC_
Definition: la.h:43
@ MATRIX_
Definition: la.h:43
@ ROWVEC_
Definition: la.h:43
double b
Definition: r_raster.c:39
Definition: la.h:53
int v_indx
Definition: la.h:56
mat_spec type
Definition: la.h:55
int rows
Definition: la.h:59
int is_init
Definition: la.h:63
int ldim
Definition: la.h:60
double * vals
Definition: la.h:62
int cols
Definition: la.h:59