~ubuntu-branches/ubuntu/wily/openms/wily

« back to all changes in this revision

Viewing changes to source/MATH/MISC/NNLS/NNLS.C

  • Committer: Package Import Robot
  • Author(s): Filippo Rusconi
  • Date: 2012-11-12 15:58:12 UTC
  • Revision ID: package-import@ubuntu.com-20121112155812-vr15wtg9b50cuesg
Tags: upstream-1.9.0
ImportĀ upstreamĀ versionĀ 1.9.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// -*- mode: C++; tab-width: 2; -*-
 
2
// vi: set ts=2:
 
3
//
 
4
// --------------------------------------------------------------------------
 
5
//                   OpenMS Mass Spectrometry Framework 
 
6
// --------------------------------------------------------------------------
 
7
//  Copyright (C) 2003-2011 -- Oliver Kohlbacher, Knut Reinert
 
8
//
 
9
//  This library is free software; you can redistribute it and/or
 
10
//  modify it under the terms of the GNU Lesser General Public
 
11
//  License as published by the Free Software Foundation; either
 
12
//  version 2.1 of the License, or (at your option) any later version.
 
13
//
 
14
//  This library 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 GNU
 
17
//  Lesser General Public License for more details.
 
18
//
 
19
//  You should have received a copy of the GNU Lesser General Public
 
20
//  License along with this library; if not, write to the Free Software
 
21
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
22
//
 
23
// --------------------------------------------------------------------------
 
24
// $Maintainer: Chris Bielow $
 
25
// $Authors: Chris Bielow $
 
26
// --------------------------------------------------------------------------
 
27
 
 
28
 
 
29
#include <cmath>
 
30
#include <algorithm>
 
31
#include <OpenMS/MATH/MISC/NNLS/NNLS.h>
 
32
 
 
33
/*
 
34
 
 
35
 The code below was converted from FORTRAN using f2c from http://www.netlib.org/lawson-hanson/all
 
36
 Some modifications were made, in order for it to run properly (search for "--removed", "-- added" and "--changed" in the code below)
 
37
 
 
38
*/
 
39
 
 
40
namespace OpenMS 
 
41
{
 
42
 
 
43
  namespace NNLS
 
44
  {
 
45
 
 
46
    /* start of original code (with modification as described above) */
 
47
 
 
48
    /* nnls.F -- translated by f2c (version 20100827).
 
49
       You must link the resulting object file with libf2c:
 
50
            on Microsoft Windows system, link with libf2c.lib;
 
51
            on Linux or Unix systems, link with .../path/to/libf2c.a -lm
 
52
            or, if you install libf2c.a in a standard place, with -lf2c -lm
 
53
            -- in that order, at the end of the command line, as in
 
54
                    cc *.o -lf2c -lm
 
55
            Source for libf2c is in /netlib/f2c/libf2c.zip, e.g.,
 
56
 
 
57
                    http://www.netlib.org/f2c/libf2c.zip
 
58
    */
 
59
 
 
60
    /* #include "f2c.h" -- removed */
 
61
 
 
62
    /* Table of constant values */
 
63
 
 
64
    static integer c__1 = 1;
 
65
    static integer c__0 = 0;
 
66
    static integer c__2 = 2;
 
67
 
 
68
    /*     SUBROUTINE NNLS  (A,MDA,M,N,B,X,RNORM,W,ZZ,INDEX,MODE) */
 
69
 
 
70
    /*  Algorithm NNLS: NONNEGATIVE LEAST SQUARES */
 
71
 
 
72
    /*  The original version of this code was developed by */
 
73
    /*  Charles L. Lawson and Richard J. Hanson at Jet Propulsion Laboratory */
 
74
    /*  1973 JUN 15, and published in the book */
 
75
    /*  "SOLVING LEAST SQUARES PROBLEMS", Prentice-HalL, 1974. */
 
76
    /*  Revised FEB 1995 to accompany reprinting of the book by SIAM. */
 
77
 
 
78
    /*     GIVEN AN M BY N MATRIX, A, AND AN M-VECTOR, B,  COMPUTE AN */
 
79
    /*     N-VECTOR, X, THAT SOLVES THE LEAST SQUARES PROBLEM */
 
80
 
 
81
    /*                      A * X = B  SUBJECT TO X .GE. 0 */
 
82
    /*     ------------------------------------------------------------------ */
 
83
    /*                     Subroutine Arguments */
 
84
 
 
85
    /*     A(),MDA,M,N     MDA IS THE FIRST DIMENSIONING PARAMETER FOR THE */
 
86
    /*                     ARRAY, A().   ON ENTRY A() CONTAINS THE M BY N */
 
87
    /*                     MATRIX, A.           ON EXIT A() CONTAINS */
 
88
    /*                     THE PRODUCT MATRIX, Q*A , WHERE Q IS AN */
 
89
    /*                     M BY M ORTHOGONAL MATRIX GENERATED IMPLICITLY BY */
 
90
    /*                     THIS SUBROUTINE. */
 
91
    /*     B()     ON ENTRY B() CONTAINS THE M-VECTOR, B.   ON EXIT B() CON- */
 
92
    /*             TAINS Q*B. */
 
93
    /*     X()     ON ENTRY X() NEED NOT BE INITIALIZED.  ON EXIT X() WILL */
 
94
    /*             CONTAIN THE SOLUTION VECTOR. */
 
95
    /*     RNORM   ON EXIT RNORM CONTAINS THE EUCLIDEAN NORM OF THE */
 
96
    /*             RESIDUAL VECTOR. */
 
97
    /*     W()     AN N-ARRAY OF WORKING SPACE.  ON EXIT W() WILL CONTAIN */
 
98
    /*             THE DUAL SOLUTION VECTOR.   W WILL SATISFY W(I) = 0. */
 
99
    /*             FOR ALL I IN SET P  AND W(I) .LE. 0. FOR ALL I IN SET Z */
 
100
    /*     ZZ()     AN M-ARRAY OF WORKING SPACE. */
 
101
    /*     INDEX()     AN INTEGER WORKING ARRAY OF LENGTH AT LEAST N. */
 
102
    /*                 ON EXIT THE CONTENTS OF THIS ARRAY DEFINE THE SETS */
 
103
    /*                 P AND Z AS FOLLOWS.. */
 
104
 
 
105
    /*                 INDEX(1)   THRU INDEX(NSETP) = SET P. */
 
106
    /*                 INDEX(IZ1) THRU INDEX(IZ2)   = SET Z. */
 
107
    /*                 IZ1 = NSETP + 1 = NPP1 */
 
108
    /*                 IZ2 = N */
 
109
    /*     MODE    THIS IS A SUCCESS-FAILURE FLAG WITH THE FOLLOWING */
 
110
    /*             MEANINGS. */
 
111
    /*             1     THE SOLUTION HAS BEEN COMPUTED SUCCESSFULLY. */
 
112
    /*             2     THE DIMENSIONS OF THE PROBLEM ARE BAD. */
 
113
    /*                   EITHER M .LE. 0 OR N .LE. 0. */
 
114
    /*             3    ITERATION COUNT EXCEEDED.  MORE THAN 3*N ITERATIONS. */
 
115
 
 
116
    /*     ------------------------------------------------------------------ */
 
117
    /* Subroutine */ int nnls_(doublereal *a, integer *mda, integer *m, integer *
 
118
            n, doublereal *b, doublereal *x, doublereal *rnorm, doublereal *w, 
 
119
            doublereal *zz, integer *index, integer *mode)
 
120
    {
 
121
        /* System generated locals */
 
122
        integer a_dim1, a_offset, i__1, i__2;
 
123
        doublereal d__1, d__2;
 
124
 
 
125
        /* Builtin functions */
 
126
        /* double sqrt(doublereal); --removed */
 
127
        /* integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void); -- removed */
 
128
 
 
129
        /* Local variables */
 
130
        static integer i__, j, l;
 
131
        static doublereal t;
 
132
        /* Subroutine */ int g1_(doublereal *, doublereal *, doublereal *, doublereal *, doublereal *);
 
133
        static doublereal cc;
 
134
        /* Subroutine */ int h12_(integer *, integer *, integer *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, integer *, integer *);
 
135
        static integer ii, jj, ip;
 
136
        static doublereal sm;
 
137
        static integer iz, jz;
 
138
        static doublereal up, ss;
 
139
        static integer iz1, iz2, npp1;
 
140
        doublereal diff_(doublereal *, doublereal *);
 
141
        static integer iter;
 
142
        static doublereal temp, wmax, alpha, asave;
 
143
        static integer itmax, izmax, nsetp;
 
144
        static doublereal dummy, unorm, ztest;
 
145
        static integer rtnkey;
 
146
 
 
147
        /* Fortran I/O blocks */
 
148
        /* static cilist io___22 = { 0, 6, 0, "(/a)", 0 }; --removed */
 
149
 
 
150
 
 
151
    /*     ------------------------------------------------------------------ */
 
152
    /*     integer INDEX(N) */
 
153
    /*     double precision A(MDA,N), B(M), W(N), X(N), ZZ(M) */
 
154
    /*     ------------------------------------------------------------------ */
 
155
        /* Parameter adjustments */
 
156
        a_dim1 = *mda;
 
157
        a_offset = 1 + a_dim1;
 
158
        a -= a_offset;
 
159
        --b;
 
160
        --x;
 
161
        --w;
 
162
        --zz;
 
163
        --index;
 
164
 
 
165
        /* Function Body */
 
166
        *mode = 1;
 
167
        if (*m <= 0 || *n <= 0) {
 
168
            *mode = 2;
 
169
            return 0;
 
170
        }
 
171
        iter = 0;
 
172
        itmax = *n * 3;
 
173
 
 
174
    /*                    INITIALIZE THE ARRAYS INDEX() AND X(). */
 
175
 
 
176
        i__1 = *n;
 
177
        for (i__ = 1; i__ <= i__1; ++i__) {
 
178
            x[i__] = 0.;
 
179
    /* L20: */
 
180
            index[i__] = i__;
 
181
        }
 
182
 
 
183
        iz2 = *n;
 
184
        iz1 = 1;
 
185
        nsetp = 0;
 
186
        npp1 = 1;
 
187
    /*                             ******  MAIN LOOP BEGINS HERE  ****** */
 
188
    L30:
 
189
    /*                  QUIT IF ALL COEFFICIENTS ARE ALREADY IN THE SOLUTION. */
 
190
    /*                        OR IF M COLS OF A HAVE BEEN TRIANGULARIZED. */
 
191
 
 
192
        if (iz1 > iz2 || nsetp >= *m) {
 
193
            goto L350;
 
194
        }
 
195
 
 
196
    /*         COMPUTE COMPONENTS OF THE DUAL (NEGATIVE GRADIENT) VECTOR W(). */
 
197
 
 
198
        i__1 = iz2;
 
199
        for (iz = iz1; iz <= i__1; ++iz) {
 
200
            j = index[iz];
 
201
            sm = 0.;
 
202
            i__2 = *m;
 
203
            for (l = npp1; l <= i__2; ++l) {
 
204
    /* L40: */
 
205
                sm += a[l + j * a_dim1] * b[l];
 
206
            }
 
207
            w[j] = sm;
 
208
    /* L50: */
 
209
        }
 
210
    /*                                   FIND LARGEST POSITIVE W(J). */
 
211
    L60:
 
212
        wmax = 0.;
 
213
        i__1 = iz2;
 
214
        for (iz = iz1; iz <= i__1; ++iz) {
 
215
            j = index[iz];
 
216
            if (w[j] > wmax) {
 
217
                wmax = w[j];
 
218
                izmax = iz;
 
219
            }
 
220
    /* L70: */
 
221
        }
 
222
 
 
223
    /*             IF WMAX .LE. 0. GO TO TERMINATION. */
 
224
    /*             THIS INDICATES SATISFACTION OF THE KUHN-TUCKER CONDITIONS. */
 
225
 
 
226
        if (wmax <= 0.) {
 
227
            goto L350;
 
228
        }
 
229
        iz = izmax;
 
230
        j = index[iz];
 
231
 
 
232
    /*     THE SIGN OF W(J) IS OK FOR J TO BE MOVED TO SET P. */
 
233
    /*     BEGIN THE TRANSFORMATION AND CHECK NEW DIAGONAL ELEMENT TO AVOID */
 
234
    /*     NEAR LINEAR DEPENDENCE. */
 
235
 
 
236
        asave = a[npp1 + j * a_dim1];
 
237
        i__1 = npp1 + 1;
 
238
        h12_(&c__1, &npp1, &i__1, m, &a[j * a_dim1 + 1], &c__1, &up, &dummy, &
 
239
                c__1, &c__1, &c__0);
 
240
        unorm = 0.;
 
241
        if (nsetp != 0) {
 
242
            i__1 = nsetp;
 
243
            for (l = 1; l <= i__1; ++l) {
 
244
    /* L90: */
 
245
    /* Computing 2nd power */
 
246
                d__1 = a[l + j * a_dim1];
 
247
                unorm += d__1 * d__1;
 
248
            }
 
249
        }
 
250
        unorm = sqrt(unorm);
 
251
        d__2 = unorm + (d__1 = a[npp1 + j * a_dim1], fabs(d__1)) * .01; /* --changed */
 
252
        if (diff_(&d__2, &unorm) > 0.) {
 
253
 
 
254
    /*        COL J IS SUFFICIENTLY INDEPENDENT.  COPY B INTO ZZ, UPDATE ZZ */
 
255
    /*        AND SOLVE FOR ZTEST ( = PROPOSED NEW VALUE FOR X(J) ). */
 
256
 
 
257
            i__1 = *m;
 
258
            for (l = 1; l <= i__1; ++l) {
 
259
    /* L120: */
 
260
                zz[l] = b[l];
 
261
            }
 
262
            i__1 = npp1 + 1;
 
263
            h12_(&c__2, &npp1, &i__1, m, &a[j * a_dim1 + 1], &c__1, &up, &zz[1], &
 
264
                    c__1, &c__1, &c__1);
 
265
            ztest = zz[npp1] / a[npp1 + j * a_dim1];
 
266
 
 
267
    /*                                     SEE IF ZTEST IS POSITIVE */
 
268
 
 
269
            if (ztest > 0.) {
 
270
                goto L140;
 
271
            }
 
272
        }
 
273
 
 
274
    /*     REJECT J AS A CANDIDATE TO BE MOVED FROM SET Z TO SET P. */
 
275
    /*     RESTORE A(NPP1,J), SET W(J)=0., AND LOOP BACK TO TEST DUAL */
 
276
    /*     COEFFS AGAIN. */
 
277
 
 
278
        a[npp1 + j * a_dim1] = asave;
 
279
        w[j] = 0.;
 
280
        goto L60;
 
281
 
 
282
    /*     THE INDEX  J=INDEX(IZ)  HAS BEEN SELECTED TO BE MOVED FROM */
 
283
    /*     SET Z TO SET P.    UPDATE B,  UPDATE INDICES,  APPLY HOUSEHOLDER */
 
284
    /*     TRANSFORMATIONS TO COLS IN NEW SET Z,  ZERO SUBDIAGONAL ELTS IN */
 
285
    /*     COL J,  SET W(J)=0. */
 
286
 
 
287
    L140:
 
288
        i__1 = *m;
 
289
        for (l = 1; l <= i__1; ++l) {
 
290
    /* L150: */
 
291
            b[l] = zz[l];
 
292
        }
 
293
 
 
294
        index[iz] = index[iz1];
 
295
        index[iz1] = j;
 
296
        ++iz1;
 
297
        nsetp = npp1;
 
298
        ++npp1;
 
299
 
 
300
        if (iz1 <= iz2) {
 
301
            i__1 = iz2;
 
302
            for (jz = iz1; jz <= i__1; ++jz) {
 
303
                jj = index[jz];
 
304
                h12_(&c__2, &nsetp, &npp1, m, &a[j * a_dim1 + 1], &c__1, &up, &a[
 
305
                        jj * a_dim1 + 1], &c__1, mda, &c__1);
 
306
    /* L160: */
 
307
            }
 
308
        }
 
309
 
 
310
        if (nsetp != *m) {
 
311
            i__1 = *m;
 
312
            for (l = npp1; l <= i__1; ++l) {
 
313
    /* L180: */
 
314
                a[l + j * a_dim1] = 0.;
 
315
            }
 
316
        }
 
317
 
 
318
        w[j] = 0.;
 
319
    /*                                SOLVE THE TRIANGULAR SYSTEM. */
 
320
    /*                                STORE THE SOLUTION TEMPORARILY IN ZZ(). */
 
321
        rtnkey = 1;
 
322
        goto L400;
 
323
    L200:
 
324
 
 
325
    /*                       ******  SECONDARY LOOP BEGINS HERE ****** */
 
326
 
 
327
    /*                          ITERATION COUNTER. */
 
328
 
 
329
    L210:
 
330
        ++iter;
 
331
        if (iter > itmax) {
 
332
            *mode = 3;
 
333
            /* s_wsfe(&io___22);  
 
334
            do_fio(&c__1, " NNLS quitting on iteration count.", (ftnlen)34);
 
335
            e_wsfe(); --removed */
 
336
            goto L350;
 
337
        }
 
338
 
 
339
    /*                    SEE IF ALL NEW CONSTRAINED COEFFS ARE FEASIBLE. */
 
340
    /*                                  IF NOT COMPUTE ALPHA. */
 
341
 
 
342
        alpha = 2.;
 
343
        i__1 = nsetp;
 
344
        for (ip = 1; ip <= i__1; ++ip) {
 
345
            l = index[ip];
 
346
            if (zz[ip] <= 0.) {
 
347
                t = -x[l] / (zz[ip] - x[l]);
 
348
                if (alpha > t) {
 
349
                    alpha = t;
 
350
                    jj = ip;
 
351
                }
 
352
            }
 
353
    /* L240: */
 
354
        }
 
355
 
 
356
    /*          IF ALL NEW CONSTRAINED COEFFS ARE FEASIBLE THEN ALPHA WILL */
 
357
    /*          STILL = 2.    IF SO EXIT FROM SECONDARY LOOP TO MAIN LOOP. */
 
358
 
 
359
        if (alpha == 2.) {
 
360
            goto L330;
 
361
        }
 
362
 
 
363
    /*          OTHERWISE USE ALPHA WHICH WILL BE BETWEEN 0. AND 1. TO */
 
364
    /*          INTERPOLATE BETWEEN THE OLD X AND THE NEW ZZ. */
 
365
 
 
366
        i__1 = nsetp;
 
367
        for (ip = 1; ip <= i__1; ++ip) {
 
368
            l = index[ip];
 
369
            x[l] += alpha * (zz[ip] - x[l]);
 
370
    /* L250: */
 
371
        }
 
372
 
 
373
    /*        MODIFY A AND B AND THE INDEX ARRAYS TO MOVE COEFFICIENT I */
 
374
    /*        FROM SET P TO SET Z. */
 
375
 
 
376
        i__ = index[jj];
 
377
    L260:
 
378
        x[i__] = 0.;
 
379
 
 
380
        if (jj != nsetp) {
 
381
            ++jj;
 
382
            i__1 = nsetp;
 
383
            for (j = jj; j <= i__1; ++j) {
 
384
                ii = index[j];
 
385
                index[j - 1] = ii;
 
386
                g1_(&a[j - 1 + ii * a_dim1], &a[j + ii * a_dim1], &cc, &ss, &a[j 
 
387
                        - 1 + ii * a_dim1]);
 
388
                a[j + ii * a_dim1] = 0.;
 
389
                i__2 = *n;
 
390
                for (l = 1; l <= i__2; ++l) {
 
391
                    if (l != ii) {
 
392
 
 
393
    /*                 Apply procedure G2 (CC,SS,A(J-1,L),A(J,L)) */
 
394
 
 
395
                        temp = a[j - 1 + l * a_dim1];
 
396
                        a[j - 1 + l * a_dim1] = cc * temp + ss * a[j + l * a_dim1]
 
397
                                ;
 
398
                        a[j + l * a_dim1] = -ss * temp + cc * a[j + l * a_dim1];
 
399
                    }
 
400
    /* L270: */
 
401
                }
 
402
 
 
403
    /*                 Apply procedure G2 (CC,SS,B(J-1),B(J)) */
 
404
 
 
405
                temp = b[j - 1];
 
406
                b[j - 1] = cc * temp + ss * b[j];
 
407
                b[j] = -ss * temp + cc * b[j];
 
408
    /* L280: */
 
409
            }
 
410
        }
 
411
 
 
412
        npp1 = nsetp;
 
413
        --nsetp;
 
414
        --iz1;
 
415
        index[iz1] = i__;
 
416
 
 
417
    /*        SEE IF THE REMAINING COEFFS IN SET P ARE FEASIBLE.  THEY SHOULD */
 
418
    /*        BE BECAUSE OF THE WAY ALPHA WAS DETERMINED. */
 
419
    /*        IF ANY ARE INFEASIBLE IT IS DUE TO ROUND-OFF ERROR.  ANY */
 
420
    /*        THAT ARE NONPOSITIVE WILL BE SET TO ZERO */
 
421
    /*        AND MOVED FROM SET P TO SET Z. */
 
422
 
 
423
        i__1 = nsetp;
 
424
        for (jj = 1; jj <= i__1; ++jj) {
 
425
            i__ = index[jj];
 
426
            if (x[i__] <= 0.) {
 
427
                goto L260;
 
428
            }
 
429
    /* L300: */
 
430
        }
 
431
 
 
432
    /*         COPY B( ) INTO ZZ( ).  THEN SOLVE AGAIN AND LOOP BACK. */
 
433
 
 
434
        i__1 = *m;
 
435
        for (i__ = 1; i__ <= i__1; ++i__) {
 
436
    /* L310: */
 
437
            zz[i__] = b[i__];
 
438
        }
 
439
        rtnkey = 2;
 
440
        goto L400;
 
441
    L320:
 
442
        goto L210;
 
443
    /*                      ******  END OF SECONDARY LOOP  ****** */
 
444
 
 
445
    L330:
 
446
        i__1 = nsetp;
 
447
        for (ip = 1; ip <= i__1; ++ip) {
 
448
            i__ = index[ip];
 
449
    /* L340: */
 
450
            x[i__] = zz[ip];
 
451
        }
 
452
    /*        ALL NEW COEFFS ARE POSITIVE.  LOOP BACK TO BEGINNING. */
 
453
        goto L30;
 
454
 
 
455
    /*                        ******  END OF MAIN LOOP  ****** */
 
456
 
 
457
    /*                        COME TO HERE FOR TERMINATION. */
 
458
    /*                     COMPUTE THE NORM OF THE FINAL RESIDUAL VECTOR. */
 
459
 
 
460
    L350:
 
461
        sm = 0.;
 
462
        if (npp1 <= *m) {
 
463
            i__1 = *m;
 
464
            for (i__ = npp1; i__ <= i__1; ++i__) {
 
465
    /* L360: */
 
466
    /* Computing 2nd power */
 
467
                d__1 = b[i__];
 
468
                sm += d__1 * d__1;
 
469
            }
 
470
        } else {
 
471
            i__1 = *n;
 
472
            for (j = 1; j <= i__1; ++j) {
 
473
    /* L380: */
 
474
                w[j] = 0.;
 
475
            }
 
476
        }
 
477
        *rnorm = sqrt(sm);
 
478
        return 0;
 
479
 
 
480
    /*     THE FOLLOWING BLOCK OF CODE IS USED AS AN INTERNAL SUBROUTINE */
 
481
    /*     TO SOLVE THE TRIANGULAR SYSTEM, PUTTING THE SOLUTION IN ZZ(). */
 
482
 
 
483
    L400:
 
484
        i__1 = nsetp;
 
485
        for (l = 1; l <= i__1; ++l) {
 
486
            ip = nsetp + 1 - l;
 
487
            if (l != 1) {
 
488
                i__2 = ip;
 
489
                for (ii = 1; ii <= i__2; ++ii) {
 
490
                    zz[ii] -= a[ii + jj * a_dim1] * zz[ip + 1];
 
491
    /* L410: */
 
492
                }
 
493
            }
 
494
            jj = index[ip];
 
495
            zz[ip] /= a[ip + jj * a_dim1];
 
496
    /* L430: */
 
497
        }
 
498
        switch (rtnkey) {
 
499
            case 1:  goto L200;
 
500
            case 2:  goto L320;
 
501
        }
 
502
        return 0;
 
503
    } /* nnls_ */
 
504
 
 
505
    /* Subroutine */ int g1_(doublereal *a, doublereal *b, doublereal *cterm, 
 
506
            doublereal *sterm, doublereal *sig)
 
507
    {
 
508
        /* System generated locals */
 
509
        doublereal d__1;
 
510
 
 
511
        /* Builtin functions */
 
512
        /* double sqrt(doublereal), d_sign(doublereal *, doublereal *); --removed */
 
513
 
 
514
        /* Local variables */
 
515
        static doublereal xr, yr;
 
516
 
 
517
 
 
518
    /*     COMPUTE ORTHOGONAL ROTATION MATRIX.. */
 
519
 
 
520
    /*  The original version of this code was developed by */
 
521
    /*  Charles L. Lawson and Richard J. Hanson at Jet Propulsion Laboratory */
 
522
    /*  1973 JUN 12, and published in the book */
 
523
    /*  "SOLVING LEAST SQUARES PROBLEMS", Prentice-HalL, 1974. */
 
524
    /*  Revised FEB 1995 to accompany reprinting of the book by SIAM. */
 
525
 
 
526
    /*     COMPUTE.. MATRIX   (C, S) SO THAT (C, S)(A) = (SQRT(A**2+B**2)) */
 
527
    /*                        (-S,C)         (-S,C)(B)   (   0          ) */
 
528
    /*     COMPUTE SIG = SQRT(A**2+B**2) */
 
529
    /*        SIG IS COMPUTED LAST TO ALLOW FOR THE POSSIBILITY THAT */
 
530
    /*        SIG MAY BE IN THE SAME LOCATION AS A OR B . */
 
531
    /*     ------------------------------------------------------------------ */
 
532
    /*     ------------------------------------------------------------------ */
 
533
        if (fabs(*a) > fabs(*b)) {
 
534
            xr = *b / *a;
 
535
    /* Computing 2nd power */
 
536
            d__1 = xr;
 
537
            yr = sqrt(d__1 * d__1 + 1.);
 
538
            d__1 = 1. / yr;
 
539
            *cterm = d_sign_(d__1, *a); /* --changed */
 
540
            *sterm = *cterm * xr;
 
541
            *sig = fabs(*a) * yr;
 
542
            return 0;
 
543
        }
 
544
        if (*b != 0.) {
 
545
            xr = *a / *b;
 
546
    /* Computing 2nd power */
 
547
            d__1 = xr;
 
548
            yr = sqrt(d__1 * d__1 + 1.);
 
549
            d__1 = 1. / yr;
 
550
            *sterm = d_sign_(d__1, *b); /* --changed */
 
551
            *cterm = *sterm * xr;
 
552
            *sig = fabs(*b) * yr;
 
553
            return 0;
 
554
        }
 
555
        *sig = 0.;
 
556
        *cterm = 0.;
 
557
        *sterm = 1.;
 
558
        return 0;
 
559
    } /* g1_ */
 
560
 
 
561
    /*     SUBROUTINE H12 (MODE,LPIVOT,L1,M,U,IUE,UP,C,ICE,ICV,NCV) */
 
562
 
 
563
    /*  CONSTRUCTION AND/OR APPLICATION OF A SINGLE */
 
564
    /*  HOUSEHOLDER TRANSFORMATION..     Q = I + U*(U**T)/B */
 
565
 
 
566
    /*  The original version of this code was developed by */
 
567
    /*  Charles L. Lawson and Richard J. Hanson at Jet Propulsion Laboratory */
 
568
    /*  1973 JUN 12, and published in the book */
 
569
    /*  "SOLVING LEAST SQUARES PROBLEMS", Prentice-HalL, 1974. */
 
570
    /*  Revised FEB 1995 to accompany reprinting of the book by SIAM. */
 
571
    /*     ------------------------------------------------------------------ */
 
572
    /*                     Subroutine Arguments */
 
573
 
 
574
    /*     MODE   = 1 OR 2   Selects Algorithm H1 to construct and apply a */
 
575
    /*            Householder transformation, or Algorithm H2 to apply a */
 
576
    /*            previously constructed transformation. */
 
577
    /*     LPIVOT IS THE INDEX OF THE PIVOT ELEMENT. */
 
578
    /*     L1,M   IF L1 .LE. M   THE TRANSFORMATION WILL BE CONSTRUCTED TO */
 
579
    /*            ZERO ELEMENTS INDEXED FROM L1 THROUGH M.   IF L1 GT. M */
 
580
    /*            THE SUBROUTINE DOES AN IDENTITY TRANSFORMATION. */
 
581
    /*     U(),IUE,UP    On entry with MODE = 1, U() contains the pivot */
 
582
    /*            vector.  IUE is the storage increment between elements. */
 
583
    /*            On exit when MODE = 1, U() and UP contain quantities */
 
584
    /*            defining the vector U of the Householder transformation. */
 
585
    /*            on entry with MODE = 2, U() and UP should contain */
 
586
    /*            quantities previously computed with MODE = 1.  These will */
 
587
    /*            not be modified during the entry with MODE = 2. */
 
588
    /*     C()    ON ENTRY with MODE = 1 or 2, C() CONTAINS A MATRIX WHICH */
 
589
    /*            WILL BE REGARDED AS A SET OF VECTORS TO WHICH THE */
 
590
    /*            HOUSEHOLDER TRANSFORMATION IS TO BE APPLIED. */
 
591
    /*            ON EXIT C() CONTAINS THE SET OF TRANSFORMED VECTORS. */
 
592
    /*     ICE    STORAGE INCREMENT BETWEEN ELEMENTS OF VECTORS IN C(). */
 
593
    /*     ICV    STORAGE INCREMENT BETWEEN VECTORS IN C(). */
 
594
    /*     NCV    NUMBER OF VECTORS IN C() TO BE TRANSFORMED. IF NCV .LE. 0 */
 
595
    /*            NO OPERATIONS WILL BE DONE ON C(). */
 
596
    /*     ------------------------------------------------------------------ */
 
597
    /* Subroutine */ int h12_(integer *mode, integer *lpivot, integer *l1, 
 
598
            integer *m, doublereal *u, integer *iue, doublereal *up, doublereal *
 
599
            c__, integer *ice, integer *icv, integer *ncv)
 
600
    {
 
601
        /* System generated locals */
 
602
        integer u_dim1, u_offset, i__1, i__2;
 
603
        doublereal d__1, d__2;
 
604
 
 
605
        /* Builtin functions */
 
606
        /* double sqrt(doublereal); --removed */
 
607
 
 
608
        /* Local variables */
 
609
        static doublereal b;
 
610
        static integer i__, j, i2, i3, i4;
 
611
        static doublereal cl, sm;
 
612
        static integer incr;
 
613
        static doublereal clinv;
 
614
 
 
615
    /*     ------------------------------------------------------------------ */
 
616
    /*     double precision U(IUE,M) */
 
617
    /*     ------------------------------------------------------------------ */
 
618
        /* Parameter adjustments */
 
619
        u_dim1 = *iue;
 
620
        u_offset = 1 + u_dim1;
 
621
        u -= u_offset;
 
622
        --c__;
 
623
 
 
624
        /* Function Body */
 
625
        if (0 >= *lpivot || *lpivot >= *l1 || *l1 > *m) {
 
626
            return 0;
 
627
        }
 
628
        cl = (d__1 = u[*lpivot * u_dim1 + 1], fabs(d__1));
 
629
        if (*mode == 2) {
 
630
            goto L60;
 
631
        }
 
632
    /*                            ****** CONSTRUCT THE TRANSFORMATION. ****** */
 
633
        i__1 = *m;
 
634
        for (j = *l1; j <= i__1; ++j) {
 
635
    /* L10: */
 
636
    /* Computing MAX */
 
637
            d__2 = (d__1 = u[j * u_dim1 + 1], fabs(d__1));
 
638
            cl = std::max(d__2,cl);  /* --changed */
 
639
        }
 
640
        if (cl <= 0.) {
 
641
            goto L130;
 
642
        } else {
 
643
            goto L20;
 
644
        }
 
645
    L20:
 
646
        clinv = 1. / cl;
 
647
    /* Computing 2nd power */
 
648
        d__1 = u[*lpivot * u_dim1 + 1] * clinv;
 
649
        sm = d__1 * d__1;
 
650
        i__1 = *m;
 
651
        for (j = *l1; j <= i__1; ++j) {
 
652
    /* L30: */
 
653
    /* Computing 2nd power */
 
654
            d__1 = u[j * u_dim1 + 1] * clinv;
 
655
            sm += d__1 * d__1;
 
656
        }
 
657
        cl *= sqrt(sm);
 
658
        if (u[*lpivot * u_dim1 + 1] <= 0.) {
 
659
            goto L50;
 
660
        } else {
 
661
            goto L40;
 
662
        }
 
663
    L40:
 
664
        cl = -cl;
 
665
    L50:
 
666
        *up = u[*lpivot * u_dim1 + 1] - cl;
 
667
        u[*lpivot * u_dim1 + 1] = cl;
 
668
        goto L70;
 
669
    /*            ****** APPLY THE TRANSFORMATION  I+U*(U**T)/B  TO C. ****** */
 
670
 
 
671
    L60:
 
672
        if (cl <= 0.) {
 
673
            goto L130;
 
674
        } else {
 
675
            goto L70;
 
676
        }
 
677
    L70:
 
678
        if (*ncv <= 0) {
 
679
            return 0;
 
680
        }
 
681
        b = *up * u[*lpivot * u_dim1 + 1];
 
682
    /*                       B  MUST BE NONPOSITIVE HERE.  IF B = 0., RETURN. */
 
683
 
 
684
        if (b >= 0.) {
 
685
            goto L130;
 
686
        } else {
 
687
            goto L80;
 
688
        }
 
689
    L80:
 
690
        b = 1. / b;
 
691
        i2 = 1 - *icv + *ice * (*lpivot - 1);
 
692
        incr = *ice * (*l1 - *lpivot);
 
693
        i__1 = *ncv;
 
694
        for (j = 1; j <= i__1; ++j) {
 
695
            i2 += *icv;
 
696
            i3 = i2 + incr;
 
697
            i4 = i3;
 
698
            sm = c__[i2] * *up;
 
699
            i__2 = *m;
 
700
            for (i__ = *l1; i__ <= i__2; ++i__) {
 
701
                sm += c__[i3] * u[i__ * u_dim1 + 1];
 
702
    /* L90: */
 
703
                i3 += *ice;
 
704
            }
 
705
            if (sm != 0.) {
 
706
                goto L100;
 
707
            } else {
 
708
                goto L120;
 
709
            }
 
710
    L100:
 
711
            sm *= b;
 
712
            c__[i2] += sm * *up;
 
713
            i__2 = *m;
 
714
            for (i__ = *l1; i__ <= i__2; ++i__) {
 
715
                c__[i4] += sm * u[i__ * u_dim1 + 1];
 
716
    /* L110: */
 
717
                i4 += *ice;
 
718
            }
 
719
    L120:
 
720
            ;
 
721
        }
 
722
    L130:
 
723
        return 0;
 
724
    } /* h12_ */
 
725
 
 
726
    doublereal diff_(doublereal *x, doublereal *y)
 
727
    {
 
728
        /* System generated locals */
 
729
        doublereal ret_val;
 
730
 
 
731
 
 
732
    /*  Function used in tests that depend on machine precision. */
 
733
 
 
734
    /*  The original version of this code was developed by */
 
735
    /*  Charles L. Lawson and Richard J. Hanson at Jet Propulsion Laboratory */
 
736
    /*  1973 JUN 7, and published in the book */
 
737
    /*  "SOLVING LEAST SQUARES PROBLEMS", Prentice-HalL, 1974. */
 
738
    /*  Revised FEB 1995 to accompany reprinting of the book by SIAM. */
 
739
 
 
740
        ret_val = *x - *y;
 
741
        return ret_val;
 
742
    } /* diff_ */
 
743
 
 
744
    /* -- added manually */
 
745
    double d_sign_(double& a, double& b)
 
746
    {
 
747
      double x = (a >= 0 ? a : - a);
 
748
      return (b >= 0 ? x : -x);
 
749
    }
 
750
 
 
751
  } // namespace NNLS
 
752
} // namespace OpenMS