30 #include <grass/config.h>
32 #if defined(HAVE_LIBLAPACK) && defined(HAVE_LIBBLAS)
34 #include <grass/gis.h>
35 #include <grass/glocale.h>
39 static int egcmp(
const void *pa,
const void *pb);
55 mat_struct *G_matrix_init(
int rows,
int cols,
int ldim)
59 if (rows < 1 || cols < 1 || ldim < rows) {
60 G_warning(_(
"Matrix dimensions out of range"));
64 tmp_arry = (mat_struct *) G_malloc(
sizeof(mat_struct));
65 tmp_arry->rows = rows;
66 tmp_arry->cols =
cols;
67 tmp_arry->ldim = ldim;
68 tmp_arry->type = MATRIX_;
69 tmp_arry->v_indx = -1;
71 tmp_arry->vals = (doublereal *) G_calloc(ldim * cols,
sizeof(doublereal));
72 tmp_arry->is_init = 1;
87 int G_matrix_zero(mat_struct * A)
92 memset(A->vals, 0,
sizeof(A->vals));
113 int G_matrix_set(mat_struct * A,
int rows,
int cols,
int ldim)
115 if (rows < 1 || cols < 1 || ldim < 0) {
116 G_warning(_(
"Matrix dimensions out of range"));
126 A->vals = (doublereal *) G_calloc(ldim * cols,
sizeof(doublereal));
144 mat_struct *G_matrix_copy(
const mat_struct * A)
149 G_warning(_(
"Matrix is not initialised fully."));
153 if ((B = G_matrix_init(A->rows, A->cols, A->ldim)) ==
NULL) {
154 G_warning(_(
"Unable to allocate space for matrix copy"));
158 memcpy(&B->vals[0], &A->vals[0], A->cols * A->ldim *
sizeof(doublereal));
177 mat_struct *G_matrix_add(mat_struct * mt1, mat_struct * mt2)
179 return G__matrix_add(mt1, mt2, 1, 1);
196 mat_struct *G_matrix_subtract(mat_struct * mt1, mat_struct * mt2)
198 return G__matrix_add(mt1, mt2, 1, -1);
215 mat_struct *G_matrix_scale(mat_struct * mt1,
const double c)
217 return G__matrix_add(mt1,
NULL, c, 0);
236 mat_struct *G__matrix_add(mat_struct * mt1, mat_struct * mt2,
const double c1,
243 G_warning(_(
"First scalar multiplier must be non-zero"));
249 G_warning(_(
"One or both input matrices uninitialised"));
256 if (!((mt1->is_init) && (mt2->is_init))) {
257 G_warning(_(
"One or both input matrices uninitialised"));
261 if (mt1->rows != mt2->rows || mt1->cols != mt2->cols) {
262 G_warning(_(
"Matrix order does not match"));
267 if ((mt3 = G_matrix_init(mt1->rows, mt1->cols, mt1->ldim)) ==
NULL) {
268 G_warning(_(
"Unable to allocate space for matrix sum"));
274 for (i = 0; i < mt3->rows; i++) {
275 for (j = 0; j < mt3->cols; j++) {
276 mt3->vals[i + mt3->ldim * j] =
277 c1 * mt1->vals[i + mt1->ldim * j];
284 for (i = 0; i < mt3->rows; i++) {
285 for (j = 0; j < mt3->cols; j++) {
286 mt3->vals[i + mt3->ldim * j] =
287 c1 * mt1->vals[i + mt1->ldim * j] + c2 * mt2->vals[i +
299 #if defined(HAVE_LIBBLAS)
314 mat_struct *G_matrix_product(mat_struct * mt1, mat_struct * mt2)
317 doublereal unity = 1, zero = 0;
318 integer rows,
cols, interdim, lda, ldb;
319 integer1 no_trans =
'n';
321 if (!((mt1->is_init) || (mt2->is_init))) {
322 G_warning(_(
"One or both input matrices uninitialised"));
326 if (mt1->cols != mt2->rows) {
327 G_warning(_(
"Matrix order does not match"));
331 if ((mt3 = G_matrix_init(mt1->rows, mt2->cols, mt1->ldim)) ==
NULL) {
332 G_warning(_(
"Unable to allocate space for matrix product"));
338 rows = (integer) mt1->rows;
339 interdim = (integer) mt1->cols;
340 cols = (integer) mt2->cols;
342 lda = (integer) mt1->ldim;
343 ldb = (integer) mt2->ldim;
345 f77_dgemm(&no_trans, &no_trans, &rows, &cols, &interdim, &unity,
346 mt1->vals, &lda, mt2->vals, &ldb, &zero, mt3->vals, &lda);
352 #warning G_matrix_product() not compiled; requires BLAS library
368 mat_struct *G_matrix_transpose(mat_struct * mt)
372 doublereal *dbo, *dbt, *dbx, *dby;
376 if (mt->cols % 2 == 0)
381 mt1 = G_matrix_init(mt->cols, mt->rows, ldim);
388 for (cnt = 0; cnt < mt->cols; cnt++) {
392 for (cnt2 = 0; cnt2 < ldo - 1; cnt2++) {
400 if (cnt < mt->cols - 1) {
410 #if defined(HAVE_LIBBLAS) && defined(HAVE_LIBLAPACK)
438 G_matrix_LU_solve(
const mat_struct * mt1, mat_struct ** xmat0,
439 const mat_struct * bmat, mat_type mtype)
441 mat_struct *wmat, *xmat, *mtx;
443 if (mt1->is_init == 0 || bmat->is_init == 0) {
444 G_warning(_(
"Input: one or both data matrices uninitialised"));
448 if (mt1->rows != mt1->cols || mt1->rows < 1) {
449 G_warning(_(
"Principal matrix is not properly dimensioned"));
453 if (bmat->cols < 1) {
454 G_warning(_(
"Input: you must have at least one array to solve"));
459 if ((xmat = G_matrix_copy(bmat)) ==
NULL) {
460 G_warning(_(
"Could not allocate space for solution matrix"));
465 if ((mtx = G_matrix_copy(mt1)) ==
NULL) {
466 G_warning(_(
"Could not allocate space for working matrix"));
473 if ((wmat = G_matrix_copy(bmat)) ==
NULL) {
474 G_warning(_(
"Could not allocate space for working matrix"));
483 integer *perm, res_info;
484 integer num_eqns, nrhs, lda, ldb;
486 perm = (integer *) G_malloc(wmat->rows);
489 num_eqns = (integer) mt1->rows;
490 nrhs = (integer) wmat->cols;
491 lda = (integer) mt1->ldim;
492 ldb = (integer) wmat->ldim;
495 f77_dgesv(&num_eqns, &nrhs, mtx->vals, &lda, perm, wmat->vals,
518 memcpy(xmat->vals, wmat->vals,
519 wmat->cols * wmat->ldim *
sizeof(doublereal));
527 G_warning(_(
"Matrix (or submatrix is singular). Solution undetermined"));
530 else if (res_info < 0) {
538 G_warning(_(
"Procedure not yet available for selected matrix type"));
549 #warning G_matrix_LU_solve() not compiled; requires BLAS and LAPACK libraries
552 #if defined(HAVE_LIBBLAS) && defined(HAVE_LIBLAPACK)
566 mat_struct *G_matrix_inverse(mat_struct * mt)
568 mat_struct *mt0, *res;
571 if (mt->rows != mt->cols) {
572 G_warning(_(
"Matrix is not square. Cannot determine inverse"));
576 if ((mt0 = G_matrix_init(mt->rows, mt->rows, mt->ldim)) ==
NULL) {
577 G_warning(_(
"Unable to allocate space for matrix"));
582 for (i = 0; i < mt0->rows - 1; i++) {
583 mt0->vals[i + i * mt0->ldim] = 1.0;
585 for (j = i + 1; j < mt0->cols; j++) {
586 mt0->vals[i + j * mt0->ldim] = mt0->vals[j + i * mt0->ldim] = 0.0;
590 mt0->vals[mt0->rows - 1 + (mt0->rows - 1) * mt0->ldim] = 1.0;
593 if ((k = G_matrix_LU_solve(mt, &res, mt0, NONSYM)) == 1) {
599 G_warning(_(
"Problem in LA procedure."));
610 #warning G_matrix_inverse() not compiled; requires BLAS and LAPACK libraries
625 void G_matrix_free(mat_struct * mt)
645 void G_matrix_print(mat_struct * mt)
648 char buf[64], numbuf[64];
650 for (i = 0; i < mt->rows; i++) {
653 for (j = 0; j < mt->cols; j++) {
655 sprintf(numbuf,
"%14.6f", G_matrix_get_element(mt, i, j));
657 if (j < mt->cols - 1)
664 fprintf(stderr,
"\n");
684 int G_matrix_set_element(mat_struct * mt,
int rowval,
int colval,
double val)
687 G_warning(_(
"Element array has not been allocated"));
691 if (rowval >= mt->rows || colval >= mt->cols || rowval < 0 || colval < 0) {
692 G_warning(_(
"Specified element is outside array bounds"));
696 mt->vals[rowval + colval * mt->ldim] = (doublereal) val;
717 double G_matrix_get_element(mat_struct * mt,
int rowval,
int colval)
724 return (val = (
double)mt->vals[rowval + colval * mt->ldim]);
740 vec_struct *G_matvect_get_column(mat_struct * mt,
int col)
745 if (col < 0 || col >= mt->cols) {
746 G_warning(_(
"Specified matrix column index is outside range"));
751 G_warning(_(
"Matrix is not initialised"));
755 if ((vc1 = G_vector_init(mt->rows, mt->ldim, CVEC)) ==
NULL) {
756 G_warning(_(
"Could not allocate space for vector structure"));
760 for (i = 0; i < mt->rows; i++)
761 G_matrix_set_element((mat_struct *) vc1, i, 0,
762 G_matrix_get_element(mt, i, col));
781 vec_struct *G_matvect_get_row(mat_struct * mt,
int row)
786 if (row < 0 || row >= mt->cols) {
787 G_warning(_(
"Specified matrix row index is outside range"));
792 G_warning(_(
"Matrix is not initialised"));
796 if ((vc1 = G_vector_init(mt->cols, mt->ldim, RVEC)) ==
NULL) {
797 G_warning(_(
"Could not allocate space for vector structure"));
801 for (i = 0; i < mt->cols; i++)
802 G_matrix_set_element((mat_struct *) vc1, 0, i,
803 G_matrix_get_element(mt, row, i));
824 int G_matvect_extract_vector(mat_struct * mt,
vtype vt,
int indx)
826 if (vt == RVEC && indx >= mt->rows) {
827 G_warning(_(
"Specified row index is outside range"));
831 else if (vt == CVEC && indx >= mt->cols) {
832 G_warning(_(
"Specified column index is outside range"));
874 int G_matvect_retrieve_matrix(vec_struct * vc)
901 vec_struct *G_vector_init(
int cells,
int ldim,
vtype vt)
903 vec_struct *tmp_arry;
905 if ((cells < 1) || (vt == RVEC && ldim < 1)
906 || (vt == CVEC && ldim < cells) || ldim < 0) {
907 G_warning(
"Vector dimensions out of range.");
911 tmp_arry = (vec_struct *) G_malloc(
sizeof(vec_struct));
915 tmp_arry->cols = cells;
916 tmp_arry->ldim = ldim;
917 tmp_arry->type = ROWVEC_;
920 else if (vt == CVEC) {
921 tmp_arry->rows = cells;
923 tmp_arry->ldim = ldim;
924 tmp_arry->type = COLVEC_;
927 tmp_arry->v_indx = 0;
929 tmp_arry->vals = (doublereal *) G_calloc(ldim * tmp_arry->cols,
931 tmp_arry->is_init = 1;
948 void G_vector_free(vec_struct * v)
971 vec_struct *G_vector_sub(vec_struct * v1, vec_struct * v2, vec_struct * out)
973 int idx1, idx2, idx0;
977 G_warning(_(
"Output vector is uninitialized"));
981 if (v1->type != v2->type) {
982 G_warning(_(
"Vectors are not of the same type"));
986 if (v1->type != out->type) {
987 G_warning(_(
"Output vector is of incorrect type"));
991 if (v1->type == MATRIX_) {
996 if ((v1->type == ROWVEC_ && v1->cols != v2->cols) ||
997 (v1->type == COLVEC_ && v1->rows != v2->rows)) {
998 G_warning(_(
"Vectors have differing dimensions"));
1002 if ((v1->type == ROWVEC_ && v1->cols != out->cols) ||
1003 (v1->type == COLVEC_ && v1->rows != out->rows)) {
1004 G_warning(_(
"Output vector has incorrect dimension"));
1008 idx1 = (v1->v_indx > 0) ? v1->v_indx : 0;
1009 idx2 = (v2->v_indx > 0) ? v2->v_indx : 0;
1010 idx0 = (out->v_indx > 0) ? out->v_indx : 0;
1012 if (v1->type == ROWVEC_) {
1013 for (i = 0; i < v1->cols; i++)
1014 G_matrix_set_element(out, idx0, i,
1015 G_matrix_get_element(v1, idx1, i) -
1016 G_matrix_get_element(v2, idx2, i));
1019 for (i = 0; i < v1->rows; i++)
1020 G_matrix_set_element(out, i, idx0,
1021 G_matrix_get_element(v1, i, idx1) -
1022 G_matrix_get_element(v2, i, idx2));
1046 int G_vector_set(vec_struct * A,
int cells,
int ldim,
vtype vt,
int vindx)
1048 if ((cells < 1) || (vt == RVEC && ldim < 1)
1049 || (vt == CVEC && ldim < cells) || ldim < 0) {
1050 G_warning(_(
"Vector dimensions out of range"));
1054 if ((vt == RVEC && vindx >= A->cols) || (vt == CVEC && vindx >= A->rows)) {
1055 G_warning(_(
"Row/column out of range"));
1077 A->vals = (doublereal *) G_calloc(ldim * A->cols,
sizeof(doublereal));
1085 #if defined(HAVE_LIBBLAS)
1099 double G_vector_norm_euclid(vec_struct * vc)
1102 doublereal *startpt;
1107 if (vc->type == ROWVEC_) {
1108 Nval = (integer) vc->cols;
1109 incr = (integer) vc->ldim;
1113 startpt = vc->vals + vc->v_indx;
1116 Nval = (integer) vc->rows;
1121 startpt = vc->vals + vc->v_indx * vc->ldim;
1125 return (
double)f77_dnrm2(&Nval, startpt, &incr);
1129 #warning G_vector_norm_euclid() not compiled; requires BLAS library
1150 double G_vector_norm_maxval(vec_struct * vc,
int vflag)
1152 doublereal xval, *startpt, *curpt;
1159 if (vc->type == ROWVEC_) {
1160 ncells = (integer) vc->cols;
1161 incr = (integer) vc->ldim;
1165 startpt = vc->vals + vc->v_indx;
1168 ncells = (integer) vc->rows;
1173 startpt = vc->vals + vc->v_indx * vc->ldim;
1179 while (ncells > 0) {
1180 if (curpt != startpt) {
1199 cellval = (double)(*curpt);
1200 if (hypot(cellval, cellval) > (double)xval)
1210 return (
double)xval;
1225 double G_vector_norm1(vec_struct * vc)
1227 double result = 0.0;
1232 G_warning(_(
"Matrix is not initialised"));
1236 idx = (vc->v_indx > 0) ? vc->v_indx : 0;
1238 if (vc->type == ROWVEC_) {
1239 for (i = 0; i < vc->cols; i++)
1240 result += fabs(G_matrix_get_element(vc, idx, i));
1243 for (i = 0; i < vc->rows; i++)
1244 result += fabs(G_matrix_get_element(vc, i, idx));
1262 vec_struct *G_vector_copy(
const vec_struct * vc1,
int comp_flag)
1264 vec_struct *tmp_arry;
1266 doublereal *startpt1, *startpt2, *curpt1, *curpt2;
1269 if (!vc1->is_init) {
1270 G_warning(_(
"Vector structure is not initialised"));
1274 tmp_arry = (vec_struct *) G_malloc(
sizeof(vec_struct));
1276 if (comp_flag == DO_COMPACT) {
1277 if (vc1->type == ROWVEC_) {
1279 tmp_arry->cols = vc1->cols;
1281 tmp_arry->type = ROWVEC_;
1282 tmp_arry->v_indx = 0;
1284 else if (vc1->type == COLVEC_) {
1285 tmp_arry->rows = vc1->rows;
1287 tmp_arry->ldim = vc1->ldim;
1288 tmp_arry->type = COLVEC_;
1289 tmp_arry->v_indx = 0;
1296 else if (comp_flag == NO_COMPACT) {
1297 tmp_arry->v_indx = vc1->v_indx;
1298 tmp_arry->rows = vc1->rows;
1299 tmp_arry->cols = vc1->cols;
1300 tmp_arry->ldim = vc1->ldim;
1301 tmp_arry->type = vc1->type;
1304 G_warning(
"Copy method must be specified: [DO,NO]_COMPACT.\n");
1308 tmp_arry->vals = (doublereal *) G_calloc(tmp_arry->ldim * tmp_arry->cols,
1309 sizeof(doublereal));
1310 if (comp_flag == DO_COMPACT) {
1311 if (tmp_arry->type == ROWVEC_) {
1312 startpt1 = tmp_arry->vals;
1313 startpt2 = vc1->vals + vc1->v_indx;
1320 else if (tmp_arry->type == COLVEC_) {
1321 startpt1 = tmp_arry->vals;
1322 startpt2 = vc1->vals + vc1->v_indx * vc1->ldim;
1330 G_warning(
"Structure type is not vector.");
1334 else if (comp_flag == NO_COMPACT) {
1335 startpt1 = tmp_arry->vals;
1336 startpt2 = vc1->vals;
1341 cnt = vc1->ldim * vc1->cols;
1344 G_warning(
"Copy method must be specified: [DO,NO]_COMPACT.\n");
1349 memcpy(curpt1, curpt2,
sizeof(doublereal));
1355 tmp_arry->is_init = 1;
1375 int G_matrix_read(FILE * fp, mat_struct * out)
1384 if (!
G_getl(buff,
sizeof(buff), fp))
1390 if (sscanf(buff,
"Matrix: %d by %d", &rows, &cols) != 2) {
1395 G_matrix_set(out, rows, cols, rows);
1397 for (i = 0; i < rows; i++) {
1398 if (fscanf(fp,
"row%d:", &row) != 1 || row != i) {
1402 for (j = 0; j <
cols; j++) {
1403 if (fscanf(fp,
"%lf:", &val) != 1) {
1408 G_matrix_set_element(out, i, j, val);
1429 int G_matrix_stdin(mat_struct * out)
1431 return G_matrix_read(stdin, out);
1447 int G_matrix_eigen_sort(vec_struct * d, mat_struct * m)
1453 G_matrix_set(&tmp, m->rows + 1, m->cols, m->ldim + 1);
1455 idx = (d->v_indx > 0) ? d->v_indx : 0;
1458 for (i = 0; i < m->cols; i++) {
1459 for (j = 0; j < m->rows; j++)
1460 G_matrix_set_element(&tmp, j + 1, i,
1461 G_matrix_get_element(m, j, i));
1462 if (d->type == ROWVEC_)
1463 G_matrix_set_element(&tmp, 0, i, G_matrix_get_element(d, idx, i));
1465 G_matrix_set_element(&tmp, 0, i, G_matrix_get_element(d, i, idx));
1469 qsort(tmp.vals, tmp.cols, tmp.ldim *
sizeof(doublereal), egcmp);
1472 for (i = 0; i < m->cols; i++) {
1473 for (j = 0; j < m->rows; j++)
1474 G_matrix_set_element(m, j, i,
1475 G_matrix_get_element(&tmp, j + 1, i));
1476 if (d->type == ROWVEC_)
1477 G_matrix_set_element(d, idx, i, G_matrix_get_element(&tmp, 0, i));
1479 G_matrix_set_element(d, i, idx, G_matrix_get_element(&tmp, 0, i));
1488 static int egcmp(
const void *pa,
const void *pb)
1490 double a = *(doublereal *
const)pa;
1491 double b = *(doublereal *
const)pb;
sprintf(buf2,"%s", G3D_CATS_ELEMENT)
void G_free(void *buf)
Free allocated memory.
void G_message(const char *msg,...)
Print a message to stderr.
char buf[GNAME_MAX+sizeof(G3D_DIRECTORY)+2]
int G_getl(char *buf, int n, FILE *fd)
gets a line of text from a file
G_warning("category support for [%s] in mapset [%s] %s", name, mapset, type)
int G_fatal_error(const char *msg,...)
Print a fatal error message to stderr.