1 /*******************************************************************************
2 *
3 *       This file is part of the General Hidden Markov Model Library,
4 *       GHMM version __VERSION__, see http://ghmm.org
5 *
6 *       Filename: ghmm/ghmm/matrix.c
7 *       Authors:  Bernhard Knab, Benjamin Georgi
8 *
9 *       Copyright (C) 1998-2004 Alexander Schliep
10 *       Copyright (C) 1998-2001 ZAIK/ZPR, Universitaet zu Koeln
11 *       Copyright (C) 2002-2004 Max-Planck-Institut fuer Molekulare Genetik,
12 *                               Berlin
13 *
14 *       Contact: schliep@ghmm.org
15 *
16 *       This library is free software; you can redistribute it and/or
17 *       modify it under the terms of the GNU Library General Public
18 *       License as published by the Free Software Foundation; either
19 *       version 2 of the License, or (at your option) any later version.
20 *
21 *       This library is distributed in the hope that it will be useful,
22 *       but WITHOUT ANY WARRANTY; without even the implied warranty of
23 *       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24 *       Library General Public License for more details.
25 *
26 *       You should have received a copy of the GNU Library General Public
27 *       License along with this library; if not, write to the Free
28 *       Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 *
30 *
31 *       This file is version $Revision: 2267 $
32 *                       from $Date: 2009-04-24 11:01:58 -0400 (Fri, 24 Apr 2009) $
33 *             last change by $Author: grunau $.
34 *
35 *******************************************************************************/
36 
37 #ifdef HAVE_CONFIG_H
38 #  include "../config.h"
39 #endif
40 
41 #include <math.h>
42 #include <float.h>
43 
44 #include "ghmmconfig.h"
45 
46 #include "matrix.h"
47 #include "vector.h"
48 #include "model.h"
49 #include "rng.h"
50 #include "randvar.h"
51 #include "mes.h"
52 #include "ghmm_internals.h"
53 
54 #include "obsolete.h"
55 
56 #ifdef GHMM_OBSOLETE
57 static void lrdecomp (int dim, double **a, double *p);
58 static void lyequalsb (double **a, double *b, double *p, int dim, double *y);
59 static void ltranspxequalsy (double **a, double *y, double *p, int dim,
60                              double *x);
61 
62 /*============================================================================*/
63 
ighmm_cmatrix_read(scanner_t * s,double ** matrix,int max_zeile,int max_spalte)64 int ighmm_cmatrix_read (scanner_t * s, double **matrix, int max_zeile,
65                    int max_spalte)
66 {
67 #define CUR_PROC "ighmm_cmatrix_read"
68   int len = 0, zeile = 0;
69   ighmm_scanner_consume (s, '{');
70   if (s->err)
71     return (-1);
72   while (!s->eof && !s->err && s->c - '}') {
73     if (zeile >= max_zeile) {
74       ighmm_scanner_error (s, "too many rows in matrix");
75       return (-1);
76     }
77     /* Memory allocation takes place in scanner_get_double_earray */
78     matrix[zeile] = scanner_get_double_earray (s, &len);
79     if (len != max_spalte) {
80       ighmm_scanner_error (s, "wrong number of elements in matrix");
81       return (-1);
82     }
83     ighmm_scanner_consume (s, ';');
84     if (s->err) {
85       ighmm_scanner_error (s, "missing ';' or wrong number of columns");
86       return (-1);
87     }
88     zeile++;
89   }
90   ighmm_scanner_consume (s, '}');
91   if (s->err)
92     return (-1);
93   if (zeile < max_zeile) {
94     ighmm_scanner_error (s, "rows missing in matrix");
95     return (-1);
96   }
97   return (0);
98 #undef CUR_PROC
99 }                               /* ighmm_cmatrix_read */
100 
101 /*============================================================================*/
102 #endif /* GHHM_OBSOLETE */
103 
104 #ifdef GHMM_UNSUPPORTED
ighmm_dmatrix_read(scanner_t * s,int ** matrix,int max_zeile,int max_spalte)105 int ighmm_dmatrix_read (scanner_t * s, int **matrix, int max_zeile, int max_spalte)
106 {
107 #define CUR_PROC "ighmm_dmatrix_read"
108   int len = 0, zeile = 0;
109   ighmm_scanner_consume (s, '{');
110   if (s->err)
111     return (-1);
112   while (!s->eof && !s->err && s->c - '}') {
113     if (zeile >= max_zeile) {
114       ighmm_scanner_error (s, "too many rows in matrix");
115       return (-1);
116     }
117     /* Memory allocation takes place in scanner_get_int_array */
118     matrix[zeile] = scanner_get_int_array (s, &len);
119     if (len != max_spalte) {
120       ighmm_scanner_error (s, "wrong number of elements in matrix");
121       return (-1);
122     }
123     ighmm_scanner_consume (s, ';');
124     if (s->err) {
125       ighmm_scanner_error (s, "missing ';' or wrong number of columns");
126       return (-1);
127     }
128     zeile++;
129   }
130   ighmm_scanner_consume (s, '}');
131   if (s->err)
132     return (-1);
133   if (zeile < max_zeile) {
134     ighmm_scanner_error (s, "rows missing in matrix");
135     return (-1);
136   }
137   return (0);
138 #undef CUR_PROC
139 }                               /* ighmm_dmatrix_read */
140 #endif /* GHMM_UNSUPPORTED */
141 
142 /*============================================================================*/
143 
144 /* allocation of matrices with fixed dimensions  */
ighmm_cmatrix_stat_alloc(int n,int m)145 double **ighmm_cmatrix_stat_alloc (int n, int m)
146 {
147 #define CUR_PROC "ighmm_cmatrix_stat_alloc"
148   int i;
149   double **A;
150   double *tmp;
151 
152   /* if (!(A = ighmm_calloc (n * sizeof (*A) + n * m * sizeof (**A)))) { */
153 
154 
155   if (!(A = ighmm_calloc (n * sizeof (double*) + n * m * sizeof (double)))) {
156     GHMM_LOG_QUEUED(LCONVERTED);
157     goto STOP;
158   }
159 
160   tmp = (double *) (A + n);
161   for (i = 0; i < n; i++) {
162     A[i] = tmp;
163     tmp += m;
164   }
165   return A;
166 STOP:
167   ighmm_cmatrix_stat_free (&A);
168   return NULL;
169 #undef CUR_PROC
170 }
171 
172 
ighmm_cmatrix_stat_free(double *** matrix)173 int ighmm_cmatrix_stat_free (double ***matrix)
174 {
175 #define CUR_PROC "ighmm_cmatrix_stat_free"
176   mes_check_ptr (matrix, return (-1));
177   if (!*matrix)
178     return (0);
179   free (*matrix);
180   return 0;
181 #undef CUR_PROC
182 }
183 
184 /*============================================================================*/
185 
186 /* allocation of matrices with fixed dimensions  */
ighmm_dmatrix_stat_alloc(int n,int m)187 int **ighmm_dmatrix_stat_alloc(int n, int m)
188 {
189 #define CUR_PROC "ighmm_dmatrix_stat_alloc"
190   int i;
191   int **A;
192   int *tmp;
193   if (!(A = ighmm_calloc (n * sizeof(int*) + n * m * sizeof (int)))) {
194     GHMM_LOG_QUEUED(LCONVERTED);
195     goto STOP;
196   }
197 
198   tmp = (int *) (A + n);
199   for (i = 0; i < n; i++) {
200     A[i] = tmp;
201     tmp += m;
202   }
203   return A;
204 STOP:
205   ighmm_dmatrix_stat_free (&A);
206   return NULL;
207 #undef CUR_PROC
208 }
209 
210 
ighmm_dmatrix_stat_free(int *** matrix)211 int ighmm_dmatrix_stat_free (int ***matrix)
212 {
213 #define CUR_PROC "ighmm_dmatrix_stat_free"
214   mes_check_ptr (matrix, return (-1));
215   if (!*matrix)
216     return (0);
217   free (*matrix);
218   return 0;
219 #undef CUR_PROC
220 }
221 
222 
223 /*============================================================================*/
224 
225 
ighmm_cmatrix_alloc(int zeilen,int spalten)226 double **ighmm_cmatrix_alloc (int zeilen, int spalten)
227 {
228 #define CUR_PROC "ighmm_cmatrix_alloc"
229   double **matrix;
230   int i;
231 
232   /*printf("*** ighmm_cmatrix_alloc %d zeilen, %d spalten:\n",zeilen, spalten);*/
233 
234   ARRAY_CALLOC (matrix, zeilen);
235   for (i = 0; i < zeilen; i++)
236     ARRAY_CALLOC (matrix[i], spalten);
237   return matrix;
238 STOP:     /* Label STOP from ARRAY_[CM]ALLOC */
239   ighmm_cmatrix_free (&matrix, zeilen);
240   return NULL;
241 #undef CUR_PROC
242 }                               /* ighmm_cmatrix_alloc */
243 
244 
ighmm_cmatrix_3d_alloc(int i,int j,int k)245 double *** ighmm_cmatrix_3d_alloc(int i, int j, int k) {
246 #define CUR_PROC "ighmm_cmatrix_3d_alloc"
247   double *** matrix;
248   int a, b;
249 
250   /* printf("*** ighmm_cmatrix_alloc %d zeilen, %d spalten:\n",zeilen, spalten); */
251 
252   ARRAY_CALLOC (matrix, i);
253   for (a = 0; a < i; a++) {
254     ARRAY_CALLOC (matrix[a], j);
255     for (b=0; b<j; b++) {
256       ARRAY_CALLOC (matrix[a][b], k);
257     }
258   }
259   return matrix;
260 STOP:     /* Label STOP from ARRAY_[CM]ALLOC */
261   ighmm_cmatrix_3d_free(&matrix, i, j);
262   return NULL;
263 #undef CUR_PROC
264 } /* ighmm_cmatrix_3d_alloc */
265 
266 /** gets a pointer on a 3d matrix and rows and cols **/
ighmm_cmatrix_3d_free(double **** matrix,int i,int j)267 int ighmm_cmatrix_3d_free(double **** matrix, int i, int j) {
268 # define CUR_PROC "ighmm_cmatrix_3d_free"
269   int a,b;
270   mes_check_ptr(matrix, return(-1));
271   if ( !*matrix) return(0);
272   for (a = i - 1; a >=  0; a--) {
273     for (b=j-1; b>=0; b--)
274       m_free((*matrix)[a][b]);
275     m_free((*matrix)[a]);
276   }
277   m_free(*matrix);
278   return (0);
279 # undef CUR_PROC
280 } /* ighmm_cmatrix_3d_free */
281 
ighmm_cmatrix_free(double *** matrix,long rows)282 int ighmm_cmatrix_free(double ***matrix, long rows) {
283 # define CUR_PROC "ighmm_cmatrix_free"
284   long i;
285   mes_check_ptr(matrix, return (-1));
286 
287   if (*matrix) {
288     for (i=0; i<rows; i++)
289       m_free((*matrix)[i]);
290     m_free(*matrix);
291   }
292   return (0);
293 # undef CUR_PROC
294 }                               /* ighmm_cmatrix_free */
295 
296 
297 
298 /*============================================================================*/
299 
300 
301 
ighmm_cmatrix_alloc_copy(int zeilen,int spalten,double ** copymatrix)302 double **ighmm_cmatrix_alloc_copy (int zeilen, int spalten, double **copymatrix)
303 {
304 #define CUR_PROC "ighmm_cmatrix_alloc_copy"
305   double **matrix;
306   int i, j;
307   ARRAY_CALLOC (matrix, zeilen);
308   for (i = 0; i < zeilen; i++) {
309     ARRAY_CALLOC (matrix[i], spalten);
310     for (j = 0; j < spalten; j++)
311       matrix[i][j] = copymatrix[i][j];
312   }
313   return matrix;
314 STOP:     /* Label STOP from ARRAY_[CM]ALLOC */
315   ighmm_cmatrix_free (&matrix, zeilen);
316   return NULL;
317 #undef CUR_PROC
318 }                               /* ighmm_cmatrix_alloc_copy */
319 
320 /*============================================================================*/
321 
ighmm_dmatrix_alloc(int zeilen,int spalten)322 int **ighmm_dmatrix_alloc (int zeilen, int spalten)
323 {
324 #define CUR_PROC "ighmm_dmatrix_alloc"
325   int **matrix;
326   int i;
327   ARRAY_CALLOC (matrix, zeilen);
328   for (i = 0; i < zeilen; i++)
329     ARRAY_CALLOC (matrix[i], spalten);
330   return matrix;
331 STOP:     /* Label STOP from ARRAY_[CM]ALLOC */
332   ighmm_dmatrix_free (&matrix, zeilen);
333   return NULL;
334 #undef CUR_PROC
335 }                               /* ighmm_dmatrix_alloc */
336 
337 /*============================================================================*/
338 
ighmm_dmatrix_free(int *** matrix,long rows)339 int ighmm_dmatrix_free (int ***matrix, long rows)
340 {
341 # define CUR_PROC "ighmm_dmatrix_free"
342   long i;
343   mes_check_ptr (matrix, return (-1));
344   if (*matrix) {
345     for (i=0; i<rows; i++)
346       m_free((*matrix)[i]);
347     m_free(*matrix);
348   }
349   return (0);
350 # undef CUR_PROC
351 }                               /* ighmm_dmatrix_free */
352 
353 /*============================================================================*/
354 /*============================================================================*/
355 
ighmm_dmatrix_3d_alloc(int zeilen,int spalten,int hoehe)356 int*** ighmm_dmatrix_3d_alloc(int zeilen, int spalten, int hoehe) {
357 #define CUR_PROC "ighmm_dmatrix_alloc"
358   int ***matrix;
359   int i, j;
360   ARRAY_CALLOC (matrix, zeilen);
361   for (i = 0; i < zeilen; i++) {
362     ARRAY_CALLOC (matrix[i], spalten);
363     for (j=0; j < spalten; j++)
364       ARRAY_CALLOC (matrix[i][j], hoehe);
365   }
366   return matrix;
367 STOP:     /* Label STOP from ARRAY_[CM]ALLOC */
368   ighmm_dmatrix_3d_free(&matrix, zeilen, spalten);
369   return NULL;
370 #undef CUR_PROC
371 } /* ighmm_dmatrix_3d_alloc */
372 
373 /*============================================================================*/
374 
ighmm_dmatrix_3d_free(int **** matrix,int zeilen,int spalten)375 int ighmm_dmatrix_3d_free(int **** matrix, int zeilen, int spalten) {
376 # define CUR_PROC "ighmm_dmatrix_free"
377   long i, j;
378   mes_check_ptr(matrix, return(-1));
379   if ( !*matrix ) return(0);
380   for (i = zeilen - 1; i >= 0; i--) {
381     for (j=spalten - 1; j >= 0; j--)
382       m_free((*matrix)[i][j]);
383     m_free((*matrix)[i]);
384   }
385   m_free(*matrix);
386   return (0);
387 # undef CUR_PROC
388 } /* ighmm_dmatrix_3d_free */
389 
390 
391 #ifdef GHMM_OBSOLETE
392 /*============================================================================*/
ighmm_cmatrix_print(FILE * file,double ** matrix,int zeilen,int spalten,char * tab,char * separator,char * ending)393 void ighmm_cmatrix_print(FILE *file, double **matrix, int zeilen, int spalten,
394 		    char *tab, char *separator, char *ending) {
395   int i;
396   for (i = 0; i < zeilen; i++)
397     ighmm_cvector_print (file, matrix[i], spalten, tab, separator, ending);
398 }                               /* ighmm_cmatrix_print */
399 #endif /* GHMM_OBSOLETE */
400 
401 #ifdef GHMM_UNSUPPORTED
402 /*============================================================================*/
ighmm_cmatrix_print_prec(FILE * file,double ** matrix,int zeilen,int spalten,int width,int prec,char * tab,char * separator,char * ending)403 void ighmm_cmatrix_print_prec (FILE * file, double **matrix, int zeilen,
404                           int spalten, int width, int prec, char *tab,
405                           char *separator, char *ending)
406 {
407   int i;
408   for (i = 0; i < zeilen; i++)
409     ighmm_cvector_print_prec (file, matrix[i], spalten, width, prec,
410                          tab, separator, ending);
411 }                               /* ighmm_cmatrix_print_prec */
412 
413 /*============================================================================*/
ighmm_dmatrix_print(FILE * file,int ** matrix,int zeilen,int spalten,char * tab,char * separator,char * ending)414 void ighmm_dmatrix_print (FILE * file, int **matrix, int zeilen, int spalten,
415                      char *tab, char *separator, char *ending)
416 {
417   int i;
418   for (i = 0; i < zeilen; i++)
419     ighmm_dvector_print (file, matrix[i], spalten, tab, separator, ending);
420 }                               /* ighmm_dmatrix_print */
421 #endif /* GHMM_UNSUPPORTED */
422 
423 #ifdef GHMM_OBSOLETE
424 /*============================================================================*/
ighmm_cmatrix_notzero_columns(double ** matrix,int row,int max_col)425 int ighmm_cmatrix_notzero_columns (double **matrix, int row, int max_col)
426 {
427   int i, count = 0;
428   for (i = 0; i < max_col; i++)
429     if (matrix[row][i])
430       count++;
431   return count;
432 }                               /* ighmm_cmatrix_notzero_columns */
433 
434 /*============================================================================*/
ighmm_cmatrix_notzero_rows(double ** matrix,int col,int max_row)435 int ighmm_cmatrix_notzero_rows (double **matrix, int col, int max_row)
436 {
437   int i, count = 0;
438   for (i = 0; i < max_row; i++)
439     if (matrix[i][col])
440       count++;
441   return count;
442 }                               /* matrix_d__notzero_rows */
443 
444 /*============================================================================*/
445 /* Scales the row vectors of a matrix to have the sum 1 */
ighmm_cmatrix_normalize(double ** matrix,int rows,int cols)446 int ighmm_cmatrix_normalize (double **matrix, int rows, int cols)
447 {
448 #define CUR_PROC "ighmm_cmatrix_normalize"
449   int i;
450   for (i = 0; i < rows; i++)
451     if (ighmm_cvector_normalize (matrix[i], cols) == -1)
452       ighmm_mes (MES_WIN, "WARNING: sum row[%d] == 0!\n", i);
453   /* return (-1); */
454   return 0;
455 #undef CUR_PROC
456 }                               /* ighmm_cmatrix_normalize */
457 
458 /*============================================================================*/
ighmm_cmatrix_random_values(double ** matrix,int rows,int cols,double min,double max)459 void ighmm_cmatrix_random_values (double **matrix, int rows, int cols,
460                              double min, double max)
461 {
462   int i, j;
463   double interval;
464   if (max < min) {
465     min = 0.0;
466     max = 1.0;
467   }
468   interval = max - min;
469   for (i = 0; i < rows; i++)
470     for (j = 0; j < cols; j++)
471       matrix[i][j] = min + GHMM_RNG_UNIFORM (RNG) * interval;
472 }                               /* ighmm_cmatrix_random_values */
473 
474 /*============================================================================*/
475 /* Fixed value for final state */
ighmm_cmatrix_random_const_values(double ** matrix,int rows,int cols,double min,double max,double c)476 void ighmm_cmatrix_random_const_values (double **matrix, int rows, int cols,
477                                    double min, double max, double c)
478 {
479   int i, j;
480   double interval;
481   if (rows < 1) {
482     ighmm_mes (MES_WIN, "WARNING: rows = %d not allowed\n", rows);
483     return;
484   }
485   if (max < min) {
486     min = 0.0;
487     max = 1.0;
488   }
489   interval = max - min;
490   for (i = 0; i < rows - 1; i++)
491     for (j = 0; j < cols; j++)
492       matrix[i][j] = min + GHMM_RNG_UNIFORM (RNG) * interval;
493   for (j = 0; j < cols; j++)
494     matrix[rows - 1][j] = c;
495 }                               /* ighmm_cmatrix_random_const_values */
496 
497 
498 /*============================================================================*/
ighmm_cmatrix_const_values(double ** matrix,int rows,int cols,double c)499 void ighmm_cmatrix_const_values (double **matrix, int rows, int cols, double c)
500 {
501   int i, j;
502   for (i = 0; i < rows; i++)
503     for (j = 0; j < cols; j++)
504       matrix[i][j] = c;
505 }                               /* ighmm_cmatrix_const_values */
506 
507 /*============================================================================*/
ighmm_cmatrix_random_left_right(double ** matrix,int rows,int cols)508 void ighmm_cmatrix_random_left_right (double **matrix, int rows, int cols)
509 {
510   int i, j;
511   for (i = 0; i < rows; i++)
512     for (j = 0; j < cols; j++)
513       if (j == i || j == i + 1)
514         matrix[i][j] = GHMM_RNG_UNIFORM (RNG);
515       else
516         matrix[i][j] = 0.0;
517 }                               /* ighmm_cmatrix_random_values */
518 
519 /*============================================================================*/
ighmm_cmatrix_left_right_strict(double ** matrix,int rows,int cols)520 void ighmm_cmatrix_left_right_strict (double **matrix, int rows, int cols)
521 {
522   int i, j;
523   for (i = 0; i < rows; i++)
524     for (j = 0; j < cols; j++)
525       if (j == i + 1)
526         matrix[i][j] = 1.0;
527       else
528         matrix[i][j] = 0.0;
529 }                               /* ighmm_cmatrix_left_right_strict */
530 
531 /*============================================================================*/
ighmm_cmatrix_gaussrows_values(double ** matrix,int rows,int cols,double ** mue,double u)532 int ighmm_cmatrix_gaussrows_values (double **matrix, int rows, int cols,
533                                double **mue, double u)
534 {
535 # define CUR_PROC "matrix_gaussrows_values"
536   int res = -1;
537   double *mean;
538   int i, j;
539   if (u <= 0.0) {
540     GHMM_LOG(LCONVERTED, "sigma^2 <= 0.0 not allowed\n");
541     goto STOP;
542   }
543   if (*mue == NULL) {
544     /* for each row, a random mean value mean[i] in (0, cols-1) */
545     ARRAY_CALLOC (mean, rows);
546     for (i = 0; i < rows; i++)
547       mean[i] = GHMM_RNG_UNIFORM (RNG) * (cols - 1);
548     /* for (i = 0; i < rows; i++) printf("%6.4f ", mean[i]); printf("\n"); */
549     *mue = mean;
550   }
551   else
552     /* Check, if the mean value is on the right interval */
553     mean = *mue;
554   for (i = 0; i < rows; i++) {
555     /* Gauss-distribution around the mean value for each state. */
556     for (j = 0; j < cols; j++) {
557       matrix[i][j] = ighmm_rand_normal_density ((double) j, mean[i], u);
558       if (matrix[i][j] == -1) {
559         GHMM_LOG_QUEUED(LCONVERTED);
560         goto STOP;
561       }
562       /* To avoid zero: (Cheap version!!) */
563       if (matrix[i][j] < 0.0001)
564         matrix[i][j] = 0.0001;  /* The Output has only 4 significant digits! */
565     }
566   }
567   res = 0;
568 STOP:     /* Label STOP from ARRAY_[CM]ALLOC */
569   return (res);
570 # undef CUR_PROC
571 }                               /* matrix_gaussrows_values */
572 
573 /*============================================================================*/
ighmm_cmatrix_const_preserve_struct(double ** matrix,int rows,int cols,double c)574 void ighmm_cmatrix_const_preserve_struct (double **matrix, int rows, int cols,
575                                      double c)
576 {
577   int i, j;
578   for (i = 0; i < rows; i++)
579     for (j = 0; j < cols; j++) {
580       if (matrix[i][j] != 0)
581         matrix[i][j] = c;
582     }
583 }                               /* ighmm_cmatrix_const_preserve_struct */
584 
585 /*============================================================================*/
ighmm_cmatrix_random_preserve_struct(double ** matrix,int rows,int cols)586 void ighmm_cmatrix_random_preserve_struct (double **matrix, int rows, int cols)
587 {
588   int i, j;
589   for (i = 0; i < rows; i++)
590     for (j = 0; j < cols; j++) {
591       if (matrix[i][j] != 0)
592         matrix[i][j] = GHMM_RNG_UNIFORM (RNG);
593     }
594 }                               /* ighmm_cmatrix_random_preserve_struct */
595 
596 /*============================================================================*/
ighmm_cmatrix_transpose(double ** A,int rows,int cols,double ** A_T)597 void ighmm_cmatrix_transpose (double **A, int rows, int cols, double **A_T)
598 {
599   int i, j;
600   for (i = 0; i < rows; i++)
601     for (j = 0; j < cols; j++)
602       A_T[j][i] = A[i][j];
603 }                               /* ighmm_cmatrix_transpose */
604 
605 
606 /*----------------------------------------------------------------------------*/
607 /* Decomposes a positiv definit, symmetric matrix A in L*L-T, that is except for
608    the diagonal, L (= lower triangular marix) is stored in A. The Diagonal is
609    stored in a vector p.
610 */
lrdecomp(int dim,double ** a,double * p)611 static void lrdecomp (int dim, double **a, double *p)
612 {
613   int k, i, j;
614   double x;
615   for (i = 0; i < dim; i++) {
616     for (j = i; j < dim; j++) {
617       x = a[i][j];
618       for (k = i - 1; k >= 0; k--)
619         x = x - a[j][k] * a[i][k];
620       if (i == j) {
621         if (x < DBL_MIN)
622           ighmm_mes (MES_WIN, "FEHLER: Pivotel.<=0!");
623         p[i] = 1 / sqrt (x);
624       }
625       else
626         a[j][i] = x * p[i];
627     }
628   }
629 }
630 
631 /*----------------------------------------------------------------------------*/
632 /* Solves L*y=b, L is a lower triangular matrix stored in A, p=1/diagonal elements. */
lyequalsb(double ** a,double * b,double * p,int dim,double * y)633 static void lyequalsb (double **a, double *b, double *p, int dim, double *y)
634 {
635   int k, j;
636   for (k = 0; k < dim; k++) {
637     y[k] = b[k];
638     for (j = 0; j < k; j++)
639       y[k] = y[k] - a[k][j] * y[j];
640     y[k] = y[k] * p[k];
641   }
642 }
643 
644 /*----------------------------------------------------------------------------*/
645 /* Solves L-T*x=y, L-T an upper triangular matrix, BUT saved in A as L! */
ltranspxequalsy(double ** a,double * y,double * p,int dim,double * x)646 static void ltranspxequalsy (double **a, double *y, double *p, int dim,
647                              double *x)
648 {
649   int k, j;
650   for (k = dim - 1; k >= 0; k--) {
651     x[k] = y[k];
652     for (j = k + 1; j < dim; j++)
653       x[k] = x[k] - a[j][k] * x[j];
654     x[k] = x[k] * p[k];
655   }
656 }
657 
658 
659 /*============================================================================*/
660 /* Solves a linear equation system for a symmetric, positiv definite matrix. */
ighmm_cmatrix_cholesky(double ** a,double * b,int dim,double * x)661 int ighmm_cmatrix_cholesky (double **a, double *b, int dim, double *x)
662 {
663 #define CUR_PROC "ighmm_cmatrix_cholesky"
664   int res = -1;
665   double *p, *y;
666   ARRAY_CALLOC (p, dim);
667   ARRAY_CALLOC (y, dim);
668   lrdecomp (dim, a, p);
669   lyequalsb (a, b, p, dim, y);
670   ltranspxequalsy (a, y, p, dim, x);
671   res = 0;
672 STOP:     /* Label STOP from ARRAY_[CM]ALLOC */
673   return (res);
674 #undef CUR_PROC
675 }
676 
677 /* Finds the determinant of a symetric, positiv definit matrix. */
ighmm_cmatrix_det_symposdef(double ** a,int dim,double * det)678 int ighmm_cmatrix_det_symposdef (double **a, int dim, double *det)
679 {
680 #define CUR_PROC "ighmm_cmatrix_det_symposdef"
681   int res = -1;
682   int i;
683   double *p, r;
684   ARRAY_CALLOC (p, dim);
685   lrdecomp (dim, a, p);
686   *det = 1.0;
687   for (i = 0; i < dim; i++) {
688     r = 1 / p[i];
689     *det *= (r * r);
690   }
691   res = 0;
692 STOP:     /* Label STOP from ARRAY_[CM]ALLOC */
693   return (res);
694 #undef CUR_PROC
695 }
696 
697 /*============================================================================*/
698 /* Copies a matrix, the memory allocations must to be done outside! */
ighmm_cmatrix_copy(double ** src,double ** target,int rows,int cols)699 void ighmm_cmatrix_copy (double **src, double **target, int rows, int cols)
700 {
701   int i, j;
702 
703   for (i = 0; i < rows; i++)
704     for (j = 0; j < cols; j++)
705       target[i][j] = src[i][j];
706 }
707 
708 /*============================================================================*/
709 /**
710   Checks whether a quadratic double matrix is stochastic
711   @return 0/1 flag for true/false
712   @param  matrix double NxN matrix to be checked
713   @param  N      number of rows/columns (matrix must be quadaratic)
714   */
ighmm_cmatrix_check_stochasticity(double ** matrix,int N)715 int ighmm_cmatrix_check_stochasticity (double **matrix, int N)
716 {
717   int i, j;
718   double row_sum;
719   int stochastic = 1;
720 
721   for (i = 0; i < N; i++) {
722     row_sum = 0.0;
723     for (j = 0; j < N; j++) {
724       row_sum = row_sum + matrix[i][j];
725     }
726     if (row_sum != 1.0) {
727       stochastic = 0;
728       break;
729     }
730   }
731   return (stochastic);
732 }
733 #endif /* GHMM_OBSOLETE */
734