la.c 37 KB

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