la.c 32 KB

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