la.c 32 KB

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