la.c 32 KB

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