Added script front-end for primer-design code
[htsworkflow.git] / htswanalysis / MACS / lib / gsl / gsl-1.11 / linalg / balance.c
1 /* linalg/balance.c
2  * 
3  * Copyright (C) 2001, 2004, 2007 Brian Gough
4  * 
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 3 of the License, or (at
8  * your option) any later version.
9  * 
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  * 
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  */
19
20 /* Balance a general matrix by scaling the columns
21  *
22  * B =  A D
23  *
24  * where D is a diagonal matrix
25  */
26
27 #include <config.h>
28 #include <stdlib.h>
29 #include <gsl/gsl_math.h>
30 #include <gsl/gsl_vector.h>
31 #include <gsl/gsl_matrix.h>
32 #include <gsl/gsl_blas.h>
33
34 #include <gsl/gsl_linalg.h>
35
36 int
37 gsl_linalg_balance_columns (gsl_matrix * A, gsl_vector * D)
38 {
39   const size_t N = A->size2;
40   size_t j;
41
42   if (D->size != A->size2)
43     {
44       GSL_ERROR("length of D must match second dimension of A", GSL_EINVAL);
45     }
46   
47   gsl_vector_set_all (D, 1.0);
48
49   for (j = 0; j < N; j++)
50     {
51       gsl_vector_view A_j = gsl_matrix_column (A, j);
52       
53       double s = gsl_blas_dasum(&A_j.vector);
54       
55       double f = 1.0;
56       
57       if (s == 0.0 || !gsl_finite(s))
58         {
59           gsl_vector_set (D, j, f);
60           continue;
61         }
62
63       /* FIXME: we could use frexp() here */
64
65       while (s > 1.0)
66         {
67           s /= 2.0;
68           f *= 2.0;
69         }
70       
71       while (s < 0.5)
72         {
73           s *= 2.0;
74           f /= 2.0;
75         }
76       
77       gsl_vector_set (D, j, f);
78
79       if (f != 1.0)
80         {
81           gsl_blas_dscal(1.0/f, &A_j.vector);
82         }
83     }
84
85   return GSL_SUCCESS;
86 }