Mantid
Loading...
Searching...
No Matches
SLSQPMinimizer.cpp
Go to the documentation of this file.
3
4#include <algorithm>
5#include <cassert>
6#include <cmath>
7#include <sstream>
8
9namespace Mantid::Kernel::Math {
10namespace {
12// Forward-declaration of minimizer
13int slsqp_(int *m, int *meq, const int *la, int *n, double *x, double *xl, double *xu, const double *f, double *c__,
14 double *g, double *a, double *acc, int *iter, int *mode, double *w, const int *l_w__, int *jw,
15 const int *l_jw__);
17} // namespace
18
24std::vector<double> SLSQPMinimizer::minimize(const std::vector<double> &x0) const {
25 assert(numParameters() == x0.size());
26
27 // slsqp parameters
28 auto m = static_cast<int>(numEqualityConstraints() + numInequalityConstraints());
29 auto meq = static_cast<int>(numEqualityConstraints());
30 int la = std::max(1, m);
31 auto n = static_cast<int>(numParameters());
32
33 std::vector<double> x = x0;
34 std::vector<double> xl(n, -1e12), xu(n, 1e12); // bounds
35 // Function value holder
36 double fx(0.0);
37 // Constraint value holder
38 std::vector<double> constraintValues(m, 0.0);
39
40 // slsqp requires gradient array to be one longer than number of parameters
41 std::vector<double> gradient(m_nparams + 1, 0.0);
42
43 double acc = 1e-06; // acceptance
44 int majiter = 100;
45 int mode = 0; // Starts in mode 0
46
47 // workspace spaces for slsqp
48 int n1 = n + 1;
49 int mineq = m - meq + n1 + n1;
50 int len_w = (3 * n1 + m) * (n1 + 1) + (n1 - meq + 1) * (mineq + 2) + 2 * mineq + (n1 + mineq) * (n1 - meq) + 2 * meq +
51 n1 + (n + 1) * n / 2 + 2 * m + 3 * n + 3 * n1 + 1;
52 int len_jw = mineq;
53 std::vector<double> vec_w(len_w, 0.0);
54 double *w = vec_w.data();
55 std::vector<int> vec_jw(len_jw, 0);
56 int *jw = vec_jw.data();
57
58 while (true) {
59 if (mode == 0 || mode == 1) // objective and constraint evaluation required
60 {
61 // Compute objective function
62 fx = fvalue(x);
63 evaluateConstraints(constraintValues, x);
64 }
65 if (mode == 0 || mode == -1) // gradient evaluation required
66 {
67 // Compute the derivatives of the objective function
68 fprime(gradient, x);
69 }
70 // Call SLSQP
71 slsqp_(&m, &meq, &la, &n, x.data(), xl.data(), xu.data(), &fx, constraintValues.data(), gradient.data(),
72 m_constraintNorms.data(), &acc, &majiter, &mode, w, &len_w, jw, &len_jw);
73
74 // If exit mode is not -1 or 1, slsqp has completed
75 if (mode != 1 && mode != -1)
76 break;
77 }
78 return x;
79}
80
86void SLSQPMinimizer::fprime(std::vector<double> &grad, const std::vector<double> &x) const {
87 assert(grad.size() > numParameters()); // > for slsqp
88
89 const double epsilon(1e-08);
90
91 double f0 = fvalue(x);
92 std::vector<double> tmp = x;
93 for (size_t i = 0; i < numParameters(); ++i) {
94 double &xi = tmp[i];
95 const double curx = xi; // copy
96 xi += epsilon;
97 grad[i] = (fvalue(tmp) - f0) / epsilon;
98 xi = curx;
99 }
100}
101
107void SLSQPMinimizer::evaluateConstraints(std::vector<double> &constrValues, const std::vector<double> &x) const {
108 assert(numEqualityConstraints() + numInequalityConstraints() == constrValues.size());
109
110 // Need to compute position in flat array
111 const size_t numConstrs(constrValues.size());
112 for (size_t i = 0; i < numConstrs; ++i) {
113 double value(0.0);
114 for (size_t j = 0; j < numParameters(); ++j) {
115 value += m_constraintNorms[j * numConstrs + i] * x[j];
116 }
117 constrValues[i] = value;
118 }
119}
120
130void SLSQPMinimizer::initializeConstraints(const DblMatrix &equality, const DblMatrix &inequality) {
131 const size_t totalNumConstr = numEqualityConstraints() + numInequalityConstraints();
132 if (totalNumConstr == 0)
133 return;
134
135 // Sanity checks on matrix sizes
136 for (size_t i = 0; i < 2; ++i) {
137 size_t ncols(0);
138 std::string matrix;
139 if (i == 0) {
140 ncols = equality.numCols();
141 matrix = "equality";
142 } else {
143 ncols = inequality.numCols();
144 matrix = "inequality";
145 }
146
147 if (ncols > 0 && ncols != numParameters()) {
148 std::ostringstream os;
149 os << "SLSQPMinimizer::initializeConstraints - Invalid " << matrix
150 << " constraint matrix. Number of columns must match number of "
151 "parameters. ncols="
152 << ncols << ", nparams=" << numParameters();
153 throw std::invalid_argument(os.str());
154 }
155 }
156
157 // --- Constraint Vector Layout As Required By SLSQP -----
158 // The equality constraints are specified first, followed by the inequality
159 // constraints. The constraints
160 // should be written column-wise such that to get move between successive
161 // values of the same constraint you
162 // jump (numEqualityConstraints()+numInequalityConstraints()) in the array.
163 // The array is then padded
164 // by (numEqualityConstraints()+numInEqualityConstraints()) zeroes
165 const size_t constrVecSize = totalNumConstr * numParameters() + totalNumConstr;
166 m_constraintNorms.resize(constrVecSize, 0.0);
167
168 size_t constrCounter(0);
169 while (constrCounter < totalNumConstr) {
170 const DblMatrix *constrMatrix(nullptr);
171 if (constrCounter < numEqualityConstraints())
172 constrMatrix = &equality;
173 else
174 constrMatrix = &inequality;
175
176 for (size_t i = 0; i < constrMatrix->numRows(); ++i, ++constrCounter) {
177 const auto matrixRow = (*constrMatrix)[i];
178 for (size_t j = 0; j < constrMatrix->numCols(); ++j) {
179 m_constraintNorms[j * totalNumConstr + constrCounter] = matrixRow[j];
180 }
181 }
182 }
183 assert(totalNumConstr == constrCounter);
184}
185
186namespace {
188
189//---------------------------------------------------------------------------------------------------//
190//
191// The following code was translated from fortran using f2c and then
192// hand-cleaned so that it will
193// compile without the f2c headers.
194//
195// The main entry point is the slsqp_ function. All others are helpers.
196//
197// By hand changes:
198// - doublereal --> double
199// - integer --> int
200// - real --> float
201//
202// Line 2639: Commented out next_fmt declaration and corresponding fmt_
203// statements that cause compiler
204// warnings and are unused
205//---------------------------------------------------------------------------------------------------//
206
207/* Table of constant values */
208static int c__0 = 0;
209static int c__1 = 1;
210static int c__2 = 2;
211
212double d_sign(const double *a, const double *b) {
213 double x;
214 x = (*a >= 0 ? *a : -*a);
215 return (*b >= 0 ? x : -x);
216}
217
218// --------------------- Forward declarations of helpers ---------------------
219int slsqpb_(int * /*m*/, int * /*meq*/, const int * /*la*/, int * /*n*/, double * /*x*/, double * /*xl*/,
220 double * /*xu*/, const double * /*f*/, double * /*c__*/, double * /*g*/, double * /*a*/, double * /*acc*/,
221 int * /*iter*/, int * /*mode*/, double * /*r__*/, double * /*l*/, double * /*x0*/, double * /*mu*/,
222 double * /*s*/, double * /*u*/, double * /*v*/, double * /*w*/, int * /*iw*/);
223int dcopy___(const int *n, double const *dx, const int *incx, double *dy, const int *incy);
224int daxpy_sl__(const int *n, const double *da, double const *dx, const int *incx, double *dy, const int *incy);
225int lsq_(int *m, int *meq, int *n, const int *nl, const int *la, double *l, double const *g, double *a, double *b,
226 double *xl, double *xu, double *x, double *y, double *w, int *jw, int *mode);
227double ddot_sl__(const int *n, double const *dx, const int *incx, double const *dy, const int *incy);
228int dscal_sl__(const int *n, const double *da, double *dx, const int *incx);
229double linmin_(int *mode, const double *ax, const double *bx, const double *f, const double *tol);
230double dnrm2___(const int *n, double const *dx, const int *incx);
231int ldl_(const int *n, double *a, double *z__, const double *sigma, double *w);
232int lsei_(double *c__, double *d__, double *e, double *f, double *g, double *h__, const int *lc, const int *mc,
233 const int *le, const int *me, const int *lg, const int *mg, const int *n, double *x, double *xnrm, double *w,
234 int *jw, int *mode);
235int h12_(const int *mode, const int *lpivot, const int *l1, const int *m, double *u, const int *iue, double *up,
236 double *c__, const int *ice, const int *icv, const int *ncv);
237int hfti_(double *a, const int *mda, const int *m, const int *n, double *b, const int *mdb, const int *nb,
238 const double *tau, int *krank, double *rnorm, double *h__, double *g, int *ip);
239int lsi_(double *e, double *f, double *g, double *h__, const int *le, const int *me, const int *lg, const int *mg,
240 const int *n, double *x, double *xnorm, double *w, int *jw, int *mode);
241int ldp_(double *g, const int *mg, const int *m, const int *n, double *h__, double *x, double *xnorm, double *w,
242 int *index, int *mode);
243int nnls_(double *a, const int *mda, const int *m, const int *n, double *b, double *x, double *rnorm, double *w,
244 double *z__, int *index, int *mode);
245int dsrotg_(double *da, double *db, double *c__, double *s);
246int dsrot_(const int *n, double *dx, const int *incx, double *dy, const int *incy, const double *c__, const double *s);
247//----------------------------------------------------------------------------
248
249/* ALGORITHM 733, COLLECTED ALGORITHMS FROM ACM. */
250/* TRANSACTIONS ON MATHEMATICAL SOFTWARE, */
251/* VOL. 20, NO. 3, SEPTEMBER, 1994, PP. 262-281. */
252/* http://doi.acm.org/10.1145/192115.192124 */
253
254/* http://permalink.gmane.org/gmane.comp.python.scientific.devel/6725 */
255/* ------ */
256/* From: Deborah Cotton <cotton@hq.acm.org> */
257/* Date: Fri, 14 Sep 2007 12:35:55 -0500 */
258/* Subject: RE: Algorithm License requested */
259/* To: Alan Isaac */
260
261/* Prof. Issac, */
262
263/* In that case, then because the author consents to [the ACM] releasing */
264/* the code currently archived at http://www.netlib.org/toms/733 under the
265 */
266/* BSD license, the ACM hereby releases this code under the BSD license. */
267
268/* Regards, */
269
270/* Deborah Cotton, Copyright & Permissions */
271/* ACM Publications */
272/* 2 Penn Plaza, Suite 701** */
273/* New York, NY 10121-0701 */
274/* permissions@acm.org */
275/* 212.869.7440 ext. 652 */
276/* Fax. 212.869.0481 */
277/* ------ */
278
279/* *********************************************************************** */
280/* optimizer * */
281/* *********************************************************************** */
282int slsqp_(int *m, int *meq, const int *la, int *n, double *x, double *xl, double *xu, const double *f, double *c__,
283 double *g, double *a, double *acc, int *iter, int *mode, double *w, const int *l_w__, int *jw,
284 const int *l_jw__) {
285 /* System generated locals */
286 int a_dim1, a_offset, i__1, i__2;
287
288 /* Local variables */
289 static int n1, il, im, ir, is, iu, iv, iw, ix, mineq;
290
291 /* SLSQP S EQUENTIAL L EAST SQ UARES P ROGRAMMING */
292 /* TO SOLVE GENERAL NONLINEAR OPTIMIZATION PROBLEMS */
293 /* *********************************************************************** */
294 /* * * */
295 /* * * */
296 /* * A NONLINEAR PROGRAMMING METHOD WITH * */
297 /* * QUADRATIC PROGRAMMING SUBPROBLEMS * */
298 /* * * */
299 /* * * */
300 /* * THIS SUBROUTINE SOLVES THE GENERAL NONLINEAR PROGRAMMING PROBLEM * */
301 /* * * */
302 /* * MINIMIZE F(X) * */
303 /* * * */
304 /* * SUBJECT TO C (X) .EQ. 0 , J = 1,...,MEQ * */
305 /* * J * */
306 /* * * */
307 /* * C (X) .GE. 0 , J = MEQ+1,...,M * */
308 /* * J * */
309 /* * * */
310 /* * XL .LE. X .LE. XU , I = 1,...,N. * */
311 /* * I I I * */
312 /* * * */
313 /* * THE ALGORITHM IMPLEMENTS THE METHOD OF HAN AND POWELL * */
314 /* * WITH BFGS-UPDATE OF THE B-MATRIX AND L1-TEST FUNCTION * */
315 /* * WITHIN THE STEPLENGTH ALGORITHM. * */
316 /* * * */
317 /* * PARAMETER DESCRIPTION: * */
318 /* * ( * MEANS THIS PARAMETER WILL BE CHANGED DURING CALCULATION ) * */
319 /* * * */
320 /* * M IS THE TOTAL NUMBER OF CONSTRAINTS, M .GE. 0 * */
321 /* * MEQ IS THE NUMBER OF EQUALITY CONSTRAINTS, MEQ .GE. 0 * */
322 /* * LA SEE A, LA .GE. MAX(M,1) * */
323 /* * N IS THE NUMBER OF VARIBLES, N .GE. 1 * */
324 /* * * X() X() STORES THE CURRENT ITERATE OF THE N VECTOR X * */
325 /* * ON ENTRY X() MUST BE INITIALIZED. ON EXIT X() * */
326 /* * STORES THE SOLUTION VECTOR X IF MODE = 0. * */
327 /* * XL() XL() STORES AN N VECTOR OF LOWER BOUNDS XL TO X. * */
328 /* * XU() XU() STORES AN N VECTOR OF UPPER BOUNDS XU TO X. * */
329 /* * F IS THE VALUE OF THE OBJECTIVE FUNCTION. * */
330 /* * C() C() STORES THE M VECTOR C OF CONSTRAINTS, * */
331 /* * EQUALITY CONSTRAINTS (IF ANY) FIRST. * */
332 /* * DIMENSION OF C MUST BE GREATER OR EQUAL LA, * */
333 /* * which must be GREATER OR EQUAL MAX(1,M). * */
334 /* * G() G() STORES THE N VECTOR G OF PARTIALS OF THE * */
335 /* * OBJECTIVE FUNCTION; DIMENSION OF G MUST BE * */
336 /* * GREATER OR EQUAL N+1. * */
337 /* * A(),LA,M,N THE LA BY N + 1 ARRAY A() STORES * */
338 /* * THE M BY N MATRIX A OF CONSTRAINT NORMALS. * */
339 /* * A() HAS FIRST DIMENSIONING PARAMETER LA, * */
340 /* * WHICH MUST BE GREATER OR EQUAL MAX(1,M). * */
341 /* * F,C,G,A MUST ALL BE SET BY THE USER BEFORE EACH CALL. * */
342 /* * * ACC ABS(ACC) CONTROLS THE FINAL ACCURACY. * */
343 /* * IF ACC .LT. ZERO AN EXACT LINESEARCH IS PERFORMED,* */
344 /* * OTHERWISE AN ARMIJO-TYPE LINESEARCH IS USED. * */
345 /* * * ITER PRESCRIBES THE MAXIMUM NUMBER OF ITERATIONS. * */
346 /* * ON EXIT ITER INDICATES THE NUMBER OF ITERATIONS. * */
347 /* * * MODE MODE CONTROLS CALCULATION: * */
348 /* * REVERSE COMMUNICATION IS USED IN THE SENSE THAT * */
349 /* * THE PROGRAM IS INITIALIZED BY MODE = 0; THEN IT IS* */
350 /* * TO BE CALLED REPEATEDLY BY THE USER UNTIL A RETURN* */
351 /* * WITH MODE .NE. IABS(1) TAKES PLACE. * */
352 /* * IF MODE = -1 GRADIENTS HAVE TO BE CALCULATED, * */
353 /* * WHILE WITH MODE = 1 FUNCTIONS HAVE TO BE CALCULATED */
354 /* * MODE MUST NOT BE CHANGED BETWEEN SUBSEQUENT CALLS * */
355 /* * OF SQP. * */
356 /* * EVALUATION MODES: * */
357 /* * MODE = -1: GRADIENT EVALUATION, (G&A) * */
358 /* * 0: ON ENTRY: INITIALIZATION, (F,G,C&A) * */
359 /* * ON EXIT : REQUIRED ACCURACY FOR SOLUTION OBTAINED * */
360 /* * 1: FUNCTION EVALUATION, (F&C) * */
361 /* * * */
362 /* * FAILURE MODES: * */
363 /* * 2: NUMBER OF EQUALITY CONTRAINTS LARGER THAN N * */
364 /* * 3: MORE THAN 3*N ITERATIONS IN LSQ SUBPROBLEM * */
365 /* * 4: INEQUALITY CONSTRAINTS INCOMPATIBLE * */
366 /* * 5: SINGULAR MATRIX E IN LSQ SUBPROBLEM * */
367 /* * 6: SINGULAR MATRIX C IN LSQ SUBPROBLEM * */
368 /* * 7: RANK-DEFICIENT EQUALITY CONSTRAINT SUBPROBLEM HFTI* */
369 /* * 8: POSITIVE DIRECTIONAL DERIVATIVE FOR LINESEARCH * */
370 /* * 9: MORE THAN ITER ITERATIONS IN SQP * */
371 /* * >=10: WORKING SPACE W OR JW TOO SMALL, * */
372 /* * W SHOULD BE ENLARGED TO L_W=MODE/1000 * */
373 /* * JW SHOULD BE ENLARGED TO L_JW=MODE-1000*L_W * */
374 /* * * W(), L_W W() IS A ONE DIMENSIONAL WORKING SPACE, * */
375 /* * THE LENGTH L_W OF WHICH SHOULD BE AT LEAST * */
376 /* * (3*N1+M)*(N1+1) for LSQ * */
377 /* * +(N1-MEQ+1)*(MINEQ+2) + 2*MINEQ for LSI * */
378 /* * +(N1+MINEQ)*(N1-MEQ) + 2*MEQ + N1 for LSEI * */
379 /* * + N1*N/2 + 2*M + 3*N + 3*N1 + 1 for SLSQPB * */
380 /* * with MINEQ = M - MEQ + 2*N1 & N1 = N+1 * */
381 /* * NOTICE: FOR PROPER DIMENSIONING OF W IT IS RECOMMENDED TO * */
382 /* * COPY THE FOLLOWING STATEMENTS INTO THE HEAD OF * */
383 /* * THE CALLING PROGRAM (AND REMOVE THE COMMENT C) * */
384 /* ####################################################################### */
385 /* INT LEN_W, LEN_JW, M, N, N1, MEQ, MINEQ */
386 /* PARAMETER (M=... , MEQ=... , N=... ) */
387 /* PARAMETER (N1= N+1, MINEQ= M-MEQ+N1+N1) */
388 /* PARAMETER (LEN_W= */
389 /* $ (3*N1+M)*(N1+1) */
390 /* $ +(N1-MEQ+1)*(MINEQ+2) + 2*MINEQ */
391 /* $ +(N1+MINEQ)*(N1-MEQ) + 2*MEQ + N1 */
392 /* $ +(N+1)*N/2 + 2*M + 3*N + 3*N1 + 1, */
393 /* $ LEN_JW=MINEQ) */
394 /* DOUBLE PRECISION W(LEN_W) */
395 /* INT JW(LEN_JW) */
396 /* ####################################################################### */
397 /* * THE FIRST M+N+N*N1/2 ELEMENTS OF W MUST NOT BE * */
398 /* * CHANGED BETWEEN SUBSEQUENT CALLS OF SLSQP. * */
399 /* * ON RETURN W(1) ... W(M) CONTAIN THE MULTIPLIERS * */
400 /* * ASSOCIATED WITH THE GENERAL CONSTRAINTS, WHILE * */
401 /* * W(M+1) ... W(M+N(N+1)/2) STORE THE CHOLESKY FACTOR* */
402 /* * L*D*L(T) OF THE APPROXIMATE HESSIAN OF THE * */
403 /* * LAGRANGIAN COLUMNWISE DENSE AS LOWER TRIANGULAR * */
404 /* * UNIT MATRIX L WITH D IN ITS 'DIAGONAL' and * */
405 /* * W(M+N(N+1)/2+N+2 ... W(M+N(N+1)/2+N+2+M+2N) * */
406 /* * CONTAIN THE MULTIPLIERS ASSOCIATED WITH ALL * */
407 /* * ALL CONSTRAINTS OF THE QUADRATIC PROGRAM FINDING * */
408 /* * THE SEARCH DIRECTION TO THE SOLUTION X* * */
409 /* * * JW(), L_JW JW() IS A ONE DIMENSIONAL INT WORKING SPACE * */
410 /* * THE LENGTH L_JW OF WHICH SHOULD BE AT LEAST * */
411 /* * MINEQ * */
412 /* * with MINEQ = M - MEQ + 2*N1 & N1 = N+1 * */
413 /* * * */
414 /* * THE USER HAS TO PROVIDE THE FOLLOWING SUBROUTINES: * */
415 /* * LDL(N,A,Z,SIG,W) : UPDATE OF THE LDL'-FACTORIZATION. * */
416 /* * LINMIN(A,B,F,TOL) : LINESEARCH ALGORITHM IF EXACT = 1 * */
417 /* * LSQ(M,MEQ,LA,N,NC,C,D,A,B,XL,XU,X,LAMBDA,W,....) : * */
418 /* * * */
419 /* * SOLUTION OF THE QUADRATIC PROGRAM * */
420 /* * QPSOL IS RECOMMENDED: * */
421 /* * PE GILL, W MURRAY, MA SAUNDERS, MH WRIGHT: * */
422 /* * USER'S GUIDE FOR SOL/QPSOL: * */
423 /* * A FORTRAN PACKAGE FOR QUADRATIC PROGRAMMING, * */
424 /* * TECHNICAL REPORT SOL 83-7, JULY 1983 * */
425 /* * DEPARTMENT OF OPERATIONS RESEARCH, STANFORD UNIVERSITY * */
426 /* * STANFORD, CA 94305 * */
427 /* * QPSOL IS THE MOST ROBUST AND EFFICIENT QP-SOLVER * */
428 /* * AS IT ALLOWS WARM STARTS WITH PROPER WORKING SETS * */
429 /* * * */
430 /* * IF IT IS NOT AVAILABLE USE LSEI, A CONSTRAINT LINEAR LEAST * */
431 /* * SQUARES SOLVER IMPLEMENTED USING THE SOFTWARE HFTI, LDP, NNLS * */
432 /* * FROM C.L. LAWSON, R.J.HANSON: SOLVING LEAST SQUARES PROBLEMS, * */
433 /* * PRENTICE HALL, ENGLEWOOD CLIFFS, 1974. * */
434 /* * LSEI COMES WITH THIS PACKAGE, together with all necessary SR's. * */
435 /* * * */
436 /* * TOGETHER WITH A COUPLE OF SUBROUTINES FROM BLAS LEVEL 1 * */
437 /* * * */
438 /* * SQP IS HEAD SUBROUTINE FOR BODY SUBROUTINE SQPBDY * */
439 /* * IN WHICH THE ALGORITHM HAS BEEN IMPLEMENTED. * */
440 /* * * */
441 /* * IMPLEMENTED BY: DIETER KRAFT, DFVLR OBERPFAFFENHOFEN * */
442 /* * as described in Dieter Kraft: A Software Package for * */
443 /* * Sequential Quadratic Programming * */
444 /* * DFVLR-FB 88-28, 1988 * */
445 /* * which should be referenced if the user publishes results of SLSQP * */
446 /* * * */
447 /* * DATE: APRIL - OCTOBER, 1981. * */
448 /* * STATUS: DECEMBER, 31-ST, 1984. * */
449 /* * STATUS: MARCH , 21-ST, 1987, REVISED TO FORTAN 77 * */
450 /* * STATUS: MARCH , 20-th, 1989, REVISED TO MS-FORTRAN * */
451 /* * STATUS: APRIL , 14-th, 1989, HESSE in-line coded * */
452 /* * STATUS: FEBRUARY, 28-th, 1991, FORTRAN/2 Version 1.04 * */
453 /* * accepts Statement Functions * */
454 /* * STATUS: MARCH , 1-st, 1991, tested with SALFORD * */
455 /* * FTN77/386 COMPILER VERS 2.40* */
456 /* * in protected mode * */
457 /* * * */
458 /* *********************************************************************** */
459 /* * * */
460 /* * Copyright 1991: Dieter Kraft, FHM * */
461 /* * * */
462 /* *********************************************************************** */
463 /* dim(W) = N1*(N1+1) + MEQ*(N1+1) + MINEQ*(N1+1) for LSQ */
464 /* +(N1-MEQ+1)*(MINEQ+2) + 2*MINEQ for LSI */
465 /* +(N1+MINEQ)*(N1-MEQ) + 2*MEQ + N1 for LSEI */
466 /* + N1*N/2 + 2*M + 3*N +3*N1 + 1 for SLSQPB */
467 /* with MINEQ = M - MEQ + 2*N1 & N1 = N+1 */
468 /* CHECK LENGTH OF WORKING ARRAYS */
469 /* Parameter adjustments */
470 --c__;
471 a_dim1 = *la;
472 a_offset = 1 + a_dim1;
473 a -= a_offset;
474 --g;
475 --xu;
476 --xl;
477 --x;
478 --w;
479 --jw;
480
481 /* Function Body */
482 n1 = *n + 1;
483 mineq = *m - *meq + n1 + n1;
484 il = (n1 * 3 + *m) * (n1 + 1) + (n1 - *meq + 1) * (mineq + 2) + (mineq << 1) + (n1 + mineq) * (n1 - *meq) +
485 (*meq << 1) + n1 * *n / 2 + (*m << 1) + *n * 3 + (n1 << 2) + 1;
486 /* Computing MAX */
487 i__1 = mineq, i__2 = n1 - *meq;
488 im = std::max(i__1, i__2);
489 if (*l_w__ < il || *l_jw__ < im) {
490 *mode = std::max(10, il) * 1000;
491 *mode += std::max(10, im);
492 return 0;
493 }
494 /* PREPARE DATA FOR CALLING SQPBDY - INITIAL ADDRESSES IN W */
495 im = 1;
496 il = im + std::max(1, *m);
497 il = im + *la;
498 ix = il + n1 * *n / 2 + 1;
499 ir = ix + *n;
500 is = ir + *n + *n + std::max(1, *m);
501 is = ir + *n + *n + *la;
502 iu = is + n1;
503 iv = iu + n1;
504 iw = iv + n1;
505
506 slsqpb_(m, meq, la, n, &x[1], &xl[1], &xu[1], f, &c__[1], &g[1], &a[a_offset], acc, iter, mode, &w[ir], &w[il],
507 &w[ix], &w[im], &w[is], &w[iu], &w[iv], &w[iw], &jw[1]);
508 return 0;
509} /* slsqp_ */
510
511int slsqpb_(int *m, int *meq, const int *la, int *n, double *x, double *xl, double *xu, const double *f, double *c__,
512 double *g, double *a, double *acc, int *iter, int *mode, double *r__, double *l, double *x0, double *mu,
513 double *s, double *u, double *v, double *w, int *iw) {
514 /* Initialized data */
515
516 static double zero = 0.;
517 static double one = 1.;
518 static double alfmin = .1;
519 static double hun = 100.;
520 static double ten = 10.;
521 static double two = 2.;
522
523 /* System generated locals */
524 int a_dim1, a_offset, i__1, i__2;
525 double d__1, d__2;
526
527 /* Local variables */
528 static int i__, j, k;
529 static double t, f0, h1, h2, h3, h4;
530 static int n1, n2, n3;
531 static double t0, gs;
532 static double tol;
533 static int line;
534 static double alpha;
535 static int iexact;
536 static int incons, ireset, itermx;
537
538 /* NONLINEAR PROGRAMMING BY SOLVING SEQUENTIALLY QUADRATIC PROGRAMS */
539 /* - L1 - LINE SEARCH, POSITIVE DEFINITE BFGS UPDATE - */
540 /* BODY SUBROUTINE FOR SLSQP */
541 /* dim(W) = N1*(N1+1) + MEQ*(N1+1) + MINEQ*(N1+1) for LSQ */
542 /* +(N1-MEQ+1)*(MINEQ+2) + 2*MINEQ */
543 /* +(N1+MINEQ)*(N1-MEQ) + 2*MEQ + N1 for LSEI */
544 /* with MINEQ = M - MEQ + 2*N1 & N1 = N+1 */
545 /* Parameter adjustments */
546 --mu;
547 --c__;
548 --v;
549 --u;
550 --s;
551 --x0;
552 --l;
553 --r__;
554 a_dim1 = *la;
555 a_offset = 1 + a_dim1;
556 a -= a_offset;
557 --g;
558 --xu;
559 --xl;
560 --x;
561 --w;
562 --iw;
563
564 /* Function Body */
565 if (*mode < 0) {
566 goto L260;
567 } else if (*mode == 0) {
568 goto L100;
569 } else {
570 goto L220;
571 }
572L100:
573 itermx = *iter;
574 if (*acc >= zero) {
575 iexact = 0;
576 } else {
577 iexact = 1;
578 }
579 *acc = std::abs(*acc);
580 tol = ten * *acc;
581 *iter = 0;
582 ireset = 0;
583 n1 = *n + 1;
584 n2 = n1 * *n / 2;
585 n3 = n2 + 1;
586 s[1] = zero;
587 mu[1] = zero;
588 dcopy___(n, &s[1], &c__0, &s[1], &c__1);
589 dcopy___(m, &mu[1], &c__0, &mu[1], &c__1);
590/* RESET BFGS MATRIX */
591L110:
592 ++ireset;
593 if (ireset > 5) {
594 goto L255;
595 }
596 l[1] = zero;
597 dcopy___(&n2, &l[1], &c__0, &l[1], &c__1);
598 j = 1;
599 i__1 = *n;
600 for (i__ = 1; i__ <= i__1; ++i__) {
601 l[j] = one;
602 j = j + n1 - i__;
603 /* L120: */
604 }
605/* MAIN ITERATION : SEARCH DIRECTION, STEPLENGTH, LDL'-UPDATE */
606L130:
607 ++(*iter);
608 *mode = 9;
609 if (*iter > itermx) {
610 goto L330;
611 }
612 /* SEARCH DIRECTION AS SOLUTION OF QP - SUBPROBLEM */
613 dcopy___(n, &xl[1], &c__1, &u[1], &c__1);
614 dcopy___(n, &xu[1], &c__1, &v[1], &c__1);
615 d__1 = -one;
616 daxpy_sl__(n, &d__1, &x[1], &c__1, &u[1], &c__1);
617 d__1 = -one;
618 daxpy_sl__(n, &d__1, &x[1], &c__1, &v[1], &c__1);
619 h4 = one;
620 lsq_(m, meq, n, &n3, la, &l[1], &g[1], &a[a_offset], &c__[1], &u[1], &v[1], &s[1], &r__[1], &w[1], &iw[1], mode);
621 /* AUGMENTED PROBLEM FOR INCONSISTENT LINEARIZATION */
622 if (*mode == 6) {
623 if (*n == *meq) {
624 *mode = 4;
625 }
626 }
627 if (*mode == 4) {
628 i__1 = *m;
629 for (j = 1; j <= i__1; ++j) {
630 if (j <= *meq) {
631 a[j + n1 * a_dim1] = -c__[j];
632 } else {
633 /* Computing MAX */
634 d__1 = -c__[j];
635 a[j + n1 * a_dim1] = std::max(d__1, zero);
636 }
637 /* L140: */
638 }
639 s[1] = zero;
640 dcopy___(n, &s[1], &c__0, &s[1], &c__1);
641 h3 = zero;
642 g[n1] = zero;
643 l[n3] = hun;
644 s[n1] = one;
645 u[n1] = zero;
646 v[n1] = one;
647 incons = 0;
648 L150:
649 lsq_(m, meq, &n1, &n3, la, &l[1], &g[1], &a[a_offset], &c__[1], &u[1], &v[1], &s[1], &r__[1], &w[1], &iw[1], mode);
650 h4 = one - s[n1];
651 if (*mode == 4) {
652 l[n3] = ten * l[n3];
653 ++incons;
654 if (incons > 5) {
655 goto L330;
656 }
657 goto L150;
658 } else if (*mode != 1) {
659 goto L330;
660 }
661 } else if (*mode != 1) {
662 goto L330;
663 }
664 /* UPDATE MULTIPLIERS FOR L1-TEST */
665 i__1 = *n;
666 for (i__ = 1; i__ <= i__1; ++i__) {
667 v[i__] = g[i__] - ddot_sl__(m, &a[i__ * a_dim1 + 1], &c__1, &r__[1], &c__1);
668 /* L160: */
669 }
670 f0 = *f;
671 dcopy___(n, &x[1], &c__1, &x0[1], &c__1);
672 gs = ddot_sl__(n, &g[1], &c__1, &s[1], &c__1);
673 h1 = std::abs(gs);
674 h2 = zero;
675 i__1 = *m;
676 for (j = 1; j <= i__1; ++j) {
677 if (j <= *meq) {
678 h3 = c__[j];
679 } else {
680 h3 = zero;
681 }
682 /* Computing MAX */
683 d__1 = -c__[j];
684 h2 += std::max(d__1, h3);
685 h3 = (d__1 = r__[j], std::abs(d__1));
686 /* Computing MAX */
687 d__1 = h3, d__2 = (mu[j] + h3) / two;
688 mu[j] = std::max(d__1, d__2);
689 h1 += h3 * (d__1 = c__[j], std::abs(d__1));
690 /* L170: */
691 }
692 /* CHECK CONVERGENCE */
693 *mode = 0;
694 if (h1 < *acc && h2 < *acc) {
695 goto L330;
696 }
697 h1 = zero;
698 i__1 = *m;
699 for (j = 1; j <= i__1; ++j) {
700 if (j <= *meq) {
701 h3 = c__[j];
702 } else {
703 h3 = zero;
704 }
705 /* Computing MAX */
706 d__1 = -c__[j];
707 h1 += mu[j] * std::max(d__1, h3);
708 /* L180: */
709 }
710 t0 = *f + h1;
711 h3 = gs - h1 * h4;
712 *mode = 8;
713 if (h3 >= zero) {
714 goto L110;
715 }
716 /* LINE SEARCH WITH AN L1-TESTFUNCTION */
717 line = 0;
718 alpha = one;
719 if (iexact == 1) {
720 goto L210;
721 }
722/* INEXACT LINESEARCH */
723L190:
724 ++line;
725 h3 = alpha * h3;
726 dscal_sl__(n, &alpha, &s[1], &c__1);
727 dcopy___(n, &x0[1], &c__1, &x[1], &c__1);
728 daxpy_sl__(n, &one, &s[1], &c__1, &x[1], &c__1);
729 *mode = 1;
730 goto L330;
731L200:
732 if (h1 <= h3 / ten || line > 10) {
733 goto L240;
734 }
735 /* Computing MAX */
736 d__1 = h3 / (two * (h3 - h1));
737 alpha = std::max(d__1, alfmin);
738 goto L190;
739/* EXACT LINESEARCH */
740L210:
741 if (line != 3) {
742 alpha = linmin_(&line, &alfmin, &one, &t, &tol);
743 dcopy___(n, &x0[1], &c__1, &x[1], &c__1);
744 daxpy_sl__(n, &alpha, &s[1], &c__1, &x[1], &c__1);
745 *mode = 1;
746 goto L330;
747 }
748 dscal_sl__(n, &alpha, &s[1], &c__1);
749 goto L240;
750/* CALL FUNCTIONS AT CURRENT X */
751L220:
752 t = *f;
753 i__1 = *m;
754 for (j = 1; j <= i__1; ++j) {
755 if (j <= *meq) {
756 h1 = c__[j];
757 } else {
758 h1 = zero;
759 }
760 /* Computing MAX */
761 d__1 = -c__[j];
762 t += mu[j] * std::max(d__1, h1);
763 /* L230: */
764 }
765 h1 = t - t0;
766 switch (iexact + 1) {
767 case 1:
768 goto L200;
769 case 2:
770 goto L210;
771 }
772/* CHECK CONVERGENCE */
773L240:
774 h3 = zero;
775 i__1 = *m;
776 for (j = 1; j <= i__1; ++j) {
777 if (j <= *meq) {
778 h1 = c__[j];
779 } else {
780 h1 = zero;
781 }
782 /* Computing MAX */
783 d__1 = -c__[j];
784 h3 += std::max(d__1, h1);
785 /* L250: */
786 }
787 if (((d__1 = *f - f0, std::abs(d__1)) < *acc || dnrm2___(n, &s[1], &c__1) < *acc) && h3 < *acc) {
788 *mode = 0;
789 } else {
790 *mode = -1;
791 }
792 goto L330;
793/* CHECK relaxed CONVERGENCE in case of positive directional derivative */
794L255:
795 if (((d__1 = *f - f0, std::abs(d__1)) < tol || dnrm2___(n, &s[1], &c__1) < tol) && h3 < tol) {
796 *mode = 0;
797 } else {
798 *mode = 8;
799 }
800 goto L330;
801/* CALL JACOBIAN AT CURRENT X */
802/* UPDATE CHOLESKY-FACTORS OF HESSIAN MATRIX BY MODIFIED BFGS FORMULA */
803L260:
804 i__1 = *n;
805 for (i__ = 1; i__ <= i__1; ++i__) {
806 u[i__] = g[i__] - ddot_sl__(m, &a[i__ * a_dim1 + 1], &c__1, &r__[1], &c__1) - v[i__];
807 /* L270: */
808 }
809 /* L'*S */
810 k = 0;
811 for (i__ = 1; i__ <= i__1; ++i__) {
812 h1 = zero;
813 ++k;
814 i__2 = *n;
815 for (j = i__ + 1; j <= i__2; ++j) {
816 ++k;
817 h1 += l[k] * s[j];
818 /* L280: */
819 }
820 v[i__] = s[i__] + h1;
821 /* L290: */
822 }
823 /* D*L'*S */
824 k = 1;
825 for (i__ = 1; i__ <= i__1; ++i__) {
826 v[i__] = l[k] * v[i__];
827 k = k + n1 - i__;
828 /* L300: */
829 }
830 /* L*D*L'*S */
831 for (i__ = *n; i__ >= 1; --i__) {
832 h1 = zero;
833 k = i__;
834 i__1 = i__ - 1;
835 for (j = 1; j <= i__1; ++j) {
836 h1 += l[k] * v[j];
837 k = k + *n - j;
838 /* L310: */
839 }
840 v[i__] += h1;
841 /* L320: */
842 }
843 h1 = ddot_sl__(n, &s[1], &c__1, &u[1], &c__1);
844 h2 = ddot_sl__(n, &s[1], &c__1, &v[1], &c__1);
845 h3 = h2 * .2;
846 if (h1 < h3) {
847 h4 = (h2 - h3) / (h2 - h1);
848 h1 = h3;
849 dscal_sl__(n, &h4, &u[1], &c__1);
850 d__1 = one - h4;
851 daxpy_sl__(n, &d__1, &v[1], &c__1, &u[1], &c__1);
852 }
853 d__1 = one / h1;
854 ldl_(n, &l[1], &u[1], &d__1, &v[1]);
855 d__1 = -one / h2;
856 ldl_(n, &l[1], &v[1], &d__1, &u[1]);
857 /* END OF MAIN ITERATION */
858 goto L130;
859/* END OF SLSQPB */
860L330:
861 return 0;
862} /* slsqpb_ */
863
864int lsq_(int *m, int *meq, int *n, const int *nl, const int *la, double *l, double const *g, double *a, double *b,
865 double *xl, double *xu, double *x, double *y, double *w, int *jw, int *mode) {
866 /* Initialized data */
867
868 static double zero = 0.;
869 static double one = 1.;
870
871 /* System generated locals */
872 int a_dim1, a_offset, i__1, i__2;
873 double d__1;
874
875 /* Local variables */
876 static int i__, i1, i2, i3, i4, m1, n1, n2, n3, ic, id, ie, if__, ig, ih, il, im, ip, iu, iw;
877 static double diag;
878 static int mineq;
879 static double xnorm;
880
881 /* MINIMIZE with respect to X */
882 /* ||E*X - F|| */
883 /* 1/2 T */
884 /* WITH UPPER TRIANGULAR MATRIX E = +D *L , */
885 /* -1/2 -1 */
886 /* AND VECTOR F = -D *L *G, */
887 /* WHERE THE UNIT LOWER TRIDIANGULAR MATRIX L IS STORED COLUMNWISE */
888 /* DENSE IN THE N*(N+1)/2 ARRAY L WITH VECTOR D STORED IN ITS */
889 /* 'DIAGONAL' THUS SUBSTITUTING THE ONE-ELEMENTS OF L */
890 /* SUBJECT TO */
891 /* A(J)*X - B(J) = 0 , J=1,...,MEQ, */
892 /* A(J)*X - B(J) >=0, J=MEQ+1,...,M, */
893 /* XL(I) <= X(I) <= XU(I), I=1,...,N, */
894 /* ON ENTRY, THE USER HAS TO PROVIDE THE ARRAYS L, G, A, B, XL, XU. */
895 /* WITH DIMENSIONS: L(N*(N+1)/2), G(N), A(LA,N), B(M), XL(N), XU(N) */
896 /* THE WORKING ARRAY W MUST HAVE AT LEAST THE FOLLOWING DIMENSION: */
897 /* DIM(W) = (3*N+M)*(N+1) for LSQ */
898 /* +(N-MEQ+1)*(MINEQ+2) + 2*MINEQ for LSI */
899 /* +(N+MINEQ)*(N-MEQ) + 2*MEQ + N for LSEI */
900 /* with MINEQ = M - MEQ + 2*N */
901 /* ON RETURN, NO ARRAY WILL BE CHANGED BY THE SUBROUTINE. */
902 /* X STORES THE N-DIMENSIONAL SOLUTION VECTOR */
903 /* Y STORES THE VECTOR OF LAGRANGE MULTIPLIERS OF DIMENSION */
904 /* M+N+N (CONSTRAINTS+LOWER+UPPER BOUNDS) */
905 /* MODE IS A SUCCESS-FAILURE FLAG WITH THE FOLLOWING MEANINGS: */
906 /* MODE=1: SUCCESSFUL COMPUTATION */
907 /* 2: ERROR RETURN BECAUSE OF WRONG DIMENSIONS (N<1) */
908 /* 3: ITERATION COUNT EXCEEDED BY NNLS */
909 /* 4: INEQUALITY CONSTRAINTS INCOMPATIBLE */
910 /* 5: MATRIX E IS NOT OF FULL RANK */
911 /* 6: MATRIX C IS NOT OF FULL RANK */
912 /* 7: RANK DEFECT IN HFTI */
913 /* coded Dieter Kraft, april 1987 */
914 /* revised march 1989 */
915 /* Parameter adjustments */
916 --y;
917 --x;
918 --xu;
919 --xl;
920 --g;
921 --l;
922 --b;
923 a_dim1 = *la;
924 a_offset = 1 + a_dim1;
925 a -= a_offset;
926 --w;
927 --jw;
928
929 /* Function Body */
930 n1 = *n + 1;
931 mineq = *m - *meq;
932 m1 = mineq + *n + *n;
933 /* determine whether to solve problem */
934 /* with inconsistent linerarization (n2=1) */
935 /* or not (n2=0) */
936 n2 = n1 * *n / 2 + 1;
937 if (n2 == *nl) {
938 n2 = 0;
939 } else {
940 n2 = 1;
941 }
942 n3 = *n - n2;
943 /* RECOVER MATRIX E AND VECTOR F FROM L AND G */
944 i2 = 1;
945 i3 = 1;
946 i4 = 1;
947 ie = 1;
948 if__ = *n * *n + 1;
949 i__1 = n3;
950 for (i__ = 1; i__ <= i__1; ++i__) {
951 i1 = n1 - i__;
952 diag = sqrt(l[i2]);
953 w[i3] = zero;
954 dcopy___(&i1, &w[i3], &c__0, &w[i3], &c__1);
955 i__2 = i1 - n2;
956 dcopy___(&i__2, &l[i2], &c__1, &w[i3], n);
957 i__2 = i1 - n2;
958 dscal_sl__(&i__2, &diag, &w[i3], n);
959 w[i3] = diag;
960 i__2 = i__ - 1;
961 w[if__ - 1 + i__] = (g[i__] - ddot_sl__(&i__2, &w[i4], &c__1, &w[if__], &c__1)) / diag;
962 i2 = i2 + i1 - n2;
963 i3 += n1;
964 i4 += *n;
965 /* L10: */
966 }
967 if (n2 == 1) {
968 w[i3] = l[*nl];
969 w[i4] = zero;
970 dcopy___(&n3, &w[i4], &c__0, &w[i4], &c__1);
971 w[if__ - 1 + *n] = zero;
972 }
973 d__1 = -one;
974 dscal_sl__(n, &d__1, &w[if__], &c__1);
975 ic = if__ + *n;
976 id = ic + *meq * *n;
977 if (*meq > 0) {
978 /* RECOVER MATRIX C FROM UPPER PART OF A */
979 i__1 = *meq;
980 for (i__ = 1; i__ <= i__1; ++i__) {
981 dcopy___(n, &a[i__ + a_dim1], la, &w[ic - 1 + i__], meq);
982 /* L20: */
983 }
984 /* RECOVER VECTOR D FROM UPPER PART OF B */
985 dcopy___(meq, &b[1], &c__1, &w[id], &c__1);
986 d__1 = -one;
987 dscal_sl__(meq, &d__1, &w[id], &c__1);
988 }
989 ig = id + *meq;
990 if (mineq > 0) {
991 /* RECOVER MATRIX G FROM LOWER PART OF A */
992 i__1 = mineq;
993 for (i__ = 1; i__ <= i__1; ++i__) {
994 dcopy___(n, &a[*meq + i__ + a_dim1], la, &w[ig - 1 + i__], &m1);
995 /* L30: */
996 }
997 }
998 /* AUGMENT MATRIX G BY +I AND -I */
999 ip = ig + mineq;
1000 i__1 = *n;
1001 for (i__ = 1; i__ <= i__1; ++i__) {
1002 w[ip - 1 + i__] = zero;
1003 dcopy___(n, &w[ip - 1 + i__], &c__0, &w[ip - 1 + i__], &m1);
1004 /* L40: */
1005 }
1006 w[ip] = one;
1007 i__1 = m1 + 1;
1008 dcopy___(n, &w[ip], &c__0, &w[ip], &i__1);
1009 im = ip + *n;
1010 i__1 = *n;
1011 for (i__ = 1; i__ <= i__1; ++i__) {
1012 w[im - 1 + i__] = zero;
1013 dcopy___(n, &w[im - 1 + i__], &c__0, &w[im - 1 + i__], &m1);
1014 /* L50: */
1015 }
1016 w[im] = -one;
1017 i__1 = m1 + 1;
1018 dcopy___(n, &w[im], &c__0, &w[im], &i__1);
1019 ih = ig + m1 * *n;
1020 if (mineq > 0) {
1021 /* RECOVER H FROM LOWER PART OF B */
1022 dcopy___(&mineq, &b[*meq + 1], &c__1, &w[ih], &c__1);
1023 d__1 = -one;
1024 dscal_sl__(&mineq, &d__1, &w[ih], &c__1);
1025 }
1026 /* AUGMENT VECTOR H BY XL AND XU */
1027 il = ih + mineq;
1028 dcopy___(n, &xl[1], &c__1, &w[il], &c__1);
1029 iu = il + *n;
1030 dcopy___(n, &xu[1], &c__1, &w[iu], &c__1);
1031 d__1 = -one;
1032 dscal_sl__(n, &d__1, &w[iu], &c__1);
1033 iw = iu + *n;
1034 i__1 = std::max(1, *meq);
1035 lsei_(&w[ic], &w[id], &w[ie], &w[if__], &w[ig], &w[ih], &i__1, meq, n, n, &m1, &m1, n, &x[1], &xnorm, &w[iw], &jw[1],
1036 mode);
1037 if (*mode == 1) {
1038 /* restore Lagrange multipliers */
1039 dcopy___(m, &w[iw], &c__1, &y[1], &c__1);
1040 dcopy___(&n3, &w[iw + *m], &c__1, &y[*m + 1], &c__1);
1041 dcopy___(&n3, &w[iw + *m + *n], &c__1, &y[*m + n3 + 1], &c__1);
1042 }
1043 /* END OF SUBROUTINE LSQ */
1044 return 0;
1045} /* lsq_ */
1046
1047int lsei_(double *c__, double *d__, double *e, double *f, double *g, double *h__, const int *lc, const int *mc,
1048 const int *le, const int *me, const int *lg, const int *mg, const int *n, double *x, double *xnrm, double *w,
1049 int *jw, int *mode) {
1050 /* Initialized data */
1051
1052 static double epmach = 2.22e-16;
1053 static double zero = 0.;
1054
1055 /* System generated locals */
1056 int c_dim1, c_offset, e_dim1, e_offset, g_dim1, g_offset, i__1, i__2, i__3;
1057 double d__1;
1058
1059 /* Local variables */
1060 static int i__, j, k, l;
1061 static double t;
1062 static int ie, if__, ig, iw, mc1;
1063 static int krank;
1064
1065 /* FOR MODE=1, THE SUBROUTINE RETURNS THE SOLUTION X OF */
1066 /* EQUALITY & INEQUALITY CONSTRAINED LEAST SQUARES PROBLEM LSEI : */
1067 /* MIN ||E*X - F|| */
1068 /* X */
1069 /* S.T. C*X = D, */
1070 /* G*X >= H. */
1071 /* USING QR DECOMPOSITION & ORTHOGONAL BASIS OF NULLSPACE OF C */
1072 /* CHAPTER 23.6 OF LAWSON & HANSON: SOLVING LEAST SQUARES PROBLEMS. */
1073 /* THE FOLLOWING DIMENSIONS OF THE ARRAYS DEFINING THE PROBLEM */
1074 /* ARE NECESSARY */
1075 /* DIM(E) : FORMAL (LE,N), ACTUAL (ME,N) */
1076 /* DIM(F) : FORMAL (LE ), ACTUAL (ME ) */
1077 /* DIM(C) : FORMAL (LC,N), ACTUAL (MC,N) */
1078 /* DIM(D) : FORMAL (LC ), ACTUAL (MC ) */
1079 /* DIM(G) : FORMAL (LG,N), ACTUAL (MG,N) */
1080 /* DIM(H) : FORMAL (LG ), ACTUAL (MG ) */
1081 /* DIM(X) : FORMAL (N ), ACTUAL (N ) */
1082 /* DIM(W) : 2*MC+ME+(ME+MG)*(N-MC) for LSEI */
1083 /* +(N-MC+1)*(MG+2)+2*MG for LSI */
1084 /* DIM(JW): MAX(MG,L) */
1085 /* ON ENTRY, THE USER HAS TO PROVIDE THE ARRAYS C, D, E, F, G, AND H. */
1086 /* ON RETURN, ALL ARRAYS WILL BE CHANGED BY THE SUBROUTINE. */
1087 /* X STORES THE SOLUTION VECTOR */
1088 /* XNORM STORES THE RESIDUUM OF THE SOLUTION IN EUCLIDIAN NORM */
1089 /* W STORES THE VECTOR OF LAGRANGE MULTIPLIERS IN ITS FIRST */
1090 /* MC+MG ELEMENTS */
1091 /* MODE IS A SUCCESS-FAILURE FLAG WITH THE FOLLOWING MEANINGS: */
1092 /* MODE=1: SUCCESSFUL COMPUTATION */
1093 /* 2: ERROR RETURN BECAUSE OF WRONG DIMENSIONS (N<1) */
1094 /* 3: ITERATION COUNT EXCEEDED BY NNLS */
1095 /* 4: INEQUALITY CONSTRAINTS INCOMPATIBLE */
1096 /* 5: MATRIX E IS NOT OF FULL RANK */
1097 /* 6: MATRIX C IS NOT OF FULL RANK */
1098 /* 7: RANK DEFECT IN HFTI */
1099 /* 18.5.1981, DIETER KRAFT, DFVLR OBERPFAFFENHOFEN */
1100 /* 20.3.1987, DIETER KRAFT, DFVLR OBERPFAFFENHOFEN */
1101 /* Parameter adjustments */
1102 --d__;
1103 --f;
1104 --h__;
1105 --x;
1106 g_dim1 = *lg;
1107 g_offset = 1 + g_dim1;
1108 g -= g_offset;
1109 e_dim1 = *le;
1110 e_offset = 1 + e_dim1;
1111 e -= e_offset;
1112 c_dim1 = *lc;
1113 c_offset = 1 + c_dim1;
1114 c__ -= c_offset;
1115 --w;
1116 --jw;
1117
1118 /* Function Body */
1119 *mode = 2;
1120 if (*mc > *n) {
1121 goto L75;
1122 }
1123 l = *n - *mc;
1124 mc1 = *mc + 1;
1125 iw = (l + 1) * (*mg + 2) + (*mg << 1) + *mc;
1126 ie = iw + *mc + 1;
1127 if__ = ie + *me * l;
1128 ig = if__ + *me;
1129 /* TRIANGULARIZE C AND APPLY FACTORS TO E AND G */
1130 i__1 = *mc;
1131 for (i__ = 1; i__ <= i__1; ++i__) {
1132 /* Computing MIN */
1133 i__2 = i__ + 1;
1134 j = std::min(i__2, *lc);
1135 i__2 = i__ + 1;
1136 i__3 = *mc - i__;
1137 h12_(&c__1, &i__, &i__2, n, &c__[i__ + c_dim1], lc, &w[iw + i__], &c__[j + c_dim1], lc, &c__1, &i__3);
1138 i__2 = i__ + 1;
1139 h12_(&c__2, &i__, &i__2, n, &c__[i__ + c_dim1], lc, &w[iw + i__], &e[e_offset], le, &c__1, me);
1140 /* L10: */
1141 i__2 = i__ + 1;
1142 h12_(&c__2, &i__, &i__2, n, &c__[i__ + c_dim1], lc, &w[iw + i__], &g[g_offset], lg, &c__1, mg);
1143 }
1144 /* SOLVE C*X=D AND MODIFY F */
1145 *mode = 6;
1146 i__2 = *mc;
1147 for (i__ = 1; i__ <= i__2; ++i__) {
1148 if ((d__1 = c__[i__ + i__ * c_dim1], std::abs(d__1)) < epmach) {
1149 goto L75;
1150 }
1151 i__1 = i__ - 1;
1152 x[i__] = (d__[i__] - ddot_sl__(&i__1, &c__[i__ + c_dim1], lc, &x[1], &c__1)) / c__[i__ + i__ * c_dim1];
1153 /* L15: */
1154 }
1155 *mode = 1;
1156 w[mc1] = zero;
1157 i__2 = *mg - *mc;
1158 dcopy___(&i__2, &w[mc1], &c__0, &w[mc1], &c__1);
1159 if (*mc == *n) {
1160 goto L50;
1161 }
1162 i__2 = *me;
1163 for (i__ = 1; i__ <= i__2; ++i__) {
1164 /* L20: */
1165 w[if__ - 1 + i__] = f[i__] - ddot_sl__(mc, &e[i__ + e_dim1], le, &x[1], &c__1);
1166 }
1167 /* STORE TRANSFORMED E & G */
1168 i__2 = *me;
1169 for (i__ = 1; i__ <= i__2; ++i__) {
1170 /* L25: */
1171 dcopy___(&l, &e[i__ + mc1 * e_dim1], le, &w[ie - 1 + i__], me);
1172 }
1173 i__2 = *mg;
1174 for (i__ = 1; i__ <= i__2; ++i__) {
1175 /* L30: */
1176 dcopy___(&l, &g[i__ + mc1 * g_dim1], lg, &w[ig - 1 + i__], mg);
1177 }
1178 if (*mg > 0) {
1179 goto L40;
1180 }
1181 /* SOLVE LS WITHOUT INEQUALITY CONSTRAINTS */
1182 *mode = 7;
1183 k = std::max(*le, *n);
1184 t = sqrt(epmach);
1185 hfti_(&w[ie], me, me, &l, &w[if__], &k, &c__1, &t, &krank, xnrm, &w[1], &w[l + 1], &jw[1]);
1186 dcopy___(&l, &w[if__], &c__1, &x[mc1], &c__1);
1187 if (krank != l) {
1188 goto L75;
1189 }
1190 *mode = 1;
1191 goto L50;
1192/* MODIFY H AND SOLVE INEQUALITY CONSTRAINED LS PROBLEM */
1193L40:
1194 i__2 = *mg;
1195 for (i__ = 1; i__ <= i__2; ++i__) {
1196 /* L45: */
1197 h__[i__] -= ddot_sl__(mc, &g[i__ + g_dim1], lg, &x[1], &c__1);
1198 }
1199 lsi_(&w[ie], &w[if__], &w[ig], &h__[1], me, me, mg, mg, &l, &x[mc1], xnrm, &w[mc1], &jw[1], mode);
1200 if (*mc == 0) {
1201 goto L75;
1202 }
1203 t = dnrm2___(mc, &x[1], &c__1);
1204 *xnrm = sqrt(*xnrm * *xnrm + t * t);
1205 if (*mode != 1) {
1206 goto L75;
1207 }
1208/* SOLUTION OF ORIGINAL PROBLEM AND LAGRANGE MULTIPLIERS */
1209L50:
1210 i__2 = *me;
1211 for (i__ = 1; i__ <= i__2; ++i__) {
1212 /* L55: */
1213 f[i__] = ddot_sl__(n, &e[i__ + e_dim1], le, &x[1], &c__1) - f[i__];
1214 }
1215 i__2 = *mc;
1216 for (i__ = 1; i__ <= i__2; ++i__) {
1217 /* L60: */
1218 d__[i__] = ddot_sl__(me, &e[i__ * e_dim1 + 1], &c__1, &f[1], &c__1) -
1219 ddot_sl__(mg, &g[i__ * g_dim1 + 1], &c__1, &w[mc1], &c__1);
1220 }
1221 for (i__ = *mc; i__ >= 1; --i__) {
1222 /* L65: */
1223 i__2 = i__ + 1;
1224 h12_(&c__2, &i__, &i__2, n, &c__[i__ + c_dim1], lc, &w[iw + i__], &x[1], &c__1, &c__1, &c__1);
1225 }
1226 for (i__ = *mc; i__ >= 1; --i__) {
1227 /* Computing MIN */
1228 i__2 = i__ + 1;
1229 j = std::min(i__2, *lc);
1230 i__2 = *mc - i__;
1231 w[i__] = (d__[i__] - ddot_sl__(&i__2, &c__[j + i__ * c_dim1], &c__1, &w[j], &c__1)) / c__[i__ + i__ * c_dim1];
1232 /* L70: */
1233 }
1234/* END OF SUBROUTINE LSEI */
1235L75:
1236 return 0;
1237} /* lsei_ */
1238
1239int lsi_(double *e, double *f, double *g, double *h__, const int *le, const int *me, const int *lg, const int *mg,
1240 const int *n, double *x, double *xnorm, double *w, int *jw, int *mode) {
1241 /* Initialized data */
1242
1243 static double epmach = 2.22e-16;
1244 static double one = 1.;
1245
1246 /* System generated locals */
1247 int e_dim1, e_offset, g_dim1, g_offset, i__1, i__2, i__3;
1248 double d__1;
1249
1250 /* Local variables */
1251 static int i__, j;
1252 static double t;
1253
1254 /* FOR MODE=1, THE SUBROUTINE RETURNS THE SOLUTION X OF */
1255 /* INEQUALITY CONSTRAINED LINEAR LEAST SQUARES PROBLEM: */
1256 /* MIN ||E*X-F|| */
1257 /* X */
1258 /* S.T. G*X >= H */
1259 /* THE ALGORITHM IS BASED ON QR DECOMPOSITION AS DESCRIBED IN */
1260 /* CHAPTER 23.5 OF LAWSON & HANSON: SOLVING LEAST SQUARES PROBLEMS */
1261 /* THE FOLLOWING DIMENSIONS OF THE ARRAYS DEFINING THE PROBLEM */
1262 /* ARE NECESSARY */
1263 /* DIM(E) : FORMAL (LE,N), ACTUAL (ME,N) */
1264 /* DIM(F) : FORMAL (LE ), ACTUAL (ME ) */
1265 /* DIM(G) : FORMAL (LG,N), ACTUAL (MG,N) */
1266 /* DIM(H) : FORMAL (LG ), ACTUAL (MG ) */
1267 /* DIM(X) : N */
1268 /* DIM(W) : (N+1)*(MG+2) + 2*MG */
1269 /* DIM(JW): LG */
1270 /* ON ENTRY, THE USER HAS TO PROVIDE THE ARRAYS E, F, G, AND H. */
1271 /* ON RETURN, ALL ARRAYS WILL BE CHANGED BY THE SUBROUTINE. */
1272 /* X STORES THE SOLUTION VECTOR */
1273 /* XNORM STORES THE RESIDUUM OF THE SOLUTION IN EUCLIDIAN NORM */
1274 /* W STORES THE VECTOR OF LAGRANGE MULTIPLIERS IN ITS FIRST */
1275 /* MG ELEMENTS */
1276 /* MODE IS A SUCCESS-FAILURE FLAG WITH THE FOLLOWING MEANINGS: */
1277 /* MODE=1: SUCCESSFUL COMPUTATION */
1278 /* 2: ERROR RETURN BECAUSE OF WRONG DIMENSIONS (N<1) */
1279 /* 3: ITERATION COUNT EXCEEDED BY NNLS */
1280 /* 4: INEQUALITY CONSTRAINTS INCOMPATIBLE */
1281 /* 5: MATRIX E IS NOT OF FULL RANK */
1282 /* 03.01.1980, DIETER KRAFT: CODED */
1283 /* 20.03.1987, DIETER KRAFT: REVISED TO FORTRAN 77 */
1284 /* Parameter adjustments */
1285 --f;
1286 --jw;
1287 --h__;
1288 --x;
1289 g_dim1 = *lg;
1290 g_offset = 1 + g_dim1;
1291 g -= g_offset;
1292 e_dim1 = *le;
1293 e_offset = 1 + e_dim1;
1294 e -= e_offset;
1295 --w;
1296
1297 /* Function Body */
1298 /* QR-FACTORS OF E AND APPLICATION TO F */
1299 i__1 = *n;
1300 for (i__ = 1; i__ <= i__1; ++i__) {
1301 /* Computing MIN */
1302 i__2 = i__ + 1;
1303 j = std::min(i__2, *n);
1304 i__2 = i__ + 1;
1305 i__3 = *n - i__;
1306 h12_(&c__1, &i__, &i__2, me, &e[i__ * e_dim1 + 1], &c__1, &t, &e[j * e_dim1 + 1], &c__1, le, &i__3);
1307 /* L10: */
1308 i__2 = i__ + 1;
1309 h12_(&c__2, &i__, &i__2, me, &e[i__ * e_dim1 + 1], &c__1, &t, &f[1], &c__1, &c__1, &c__1);
1310 }
1311 /* TRANSFORM G AND H TO GET LEAST DISTANCE PROBLEM */
1312 *mode = 5;
1313 i__2 = *mg;
1314 for (i__ = 1; i__ <= i__2; ++i__) {
1315 i__1 = *n;
1316 for (j = 1; j <= i__1; ++j) {
1317 if ((d__1 = e[j + j * e_dim1], std::abs(d__1)) < epmach) {
1318 goto L50;
1319 }
1320 /* L20: */
1321 i__3 = j - 1;
1322 g[i__ + j * g_dim1] =
1323 (g[i__ + j * g_dim1] - ddot_sl__(&i__3, &g[i__ + g_dim1], lg, &e[j * e_dim1 + 1], &c__1)) / e[j + j * e_dim1];
1324 }
1325 /* L30: */
1326 h__[i__] -= ddot_sl__(n, &g[i__ + g_dim1], lg, &f[1], &c__1);
1327 }
1328 /* SOLVE LEAST DISTANCE PROBLEM */
1329 ldp_(&g[g_offset], lg, mg, n, &h__[1], &x[1], xnorm, &w[1], &jw[1], mode);
1330 if (*mode != 1) {
1331 goto L50;
1332 }
1333 /* SOLUTION OF ORIGINAL PROBLEM */
1334 daxpy_sl__(n, &one, &f[1], &c__1, &x[1], &c__1);
1335 for (i__ = *n; i__ >= 1; --i__) {
1336 /* Computing MIN */
1337 i__2 = i__ + 1;
1338 j = std::min(i__2, *n);
1339 /* L40: */
1340 i__2 = *n - i__;
1341 x[i__] = (x[i__] - ddot_sl__(&i__2, &e[i__ + j * e_dim1], le, &x[j], &c__1)) / e[i__ + i__ * e_dim1];
1342 }
1343 /* Computing MIN */
1344 i__2 = *n + 1;
1345 j = std::min(i__2, *me);
1346 i__2 = *me - *n;
1347 t = dnrm2___(&i__2, &f[j], &c__1);
1348 *xnorm = sqrt(*xnorm * *xnorm + t * t);
1349/* END OF SUBROUTINE LSI */
1350L50:
1351 return 0;
1352} /* lsi_ */
1353
1354int ldp_(double *g, const int *mg, const int *m, const int *n, double *h__, double *x, double *xnorm, double *w,
1355 int *index, int *mode) {
1356 /* Initialized data */
1357
1358 static double zero = 0.;
1359 static double one = 1.;
1360
1361 /* System generated locals */
1362 int g_dim1, g_offset, i__1, i__2;
1363 double d__1;
1364
1365 /* Local variables */
1366 static int i__, j, n1, if__, iw, iy, iz;
1367 static double fac;
1368 static double rnorm;
1369 static int iwdual;
1370
1371 /* T */
1372 /* MINIMIZE 1/2 X X SUBJECT TO G * X >= H. */
1373 /* C.L. LAWSON, R.J. HANSON: 'SOLVING LEAST SQUARES PROBLEMS' */
1374 /* PRENTICE HALL, ENGLEWOOD CLIFFS, NEW JERSEY, 1974. */
1375 /* PARAMETER DESCRIPTION: */
1376 /* G(),MG,M,N ON ENTRY G() STORES THE M BY N MATRIX OF */
1377 /* LINEAR INEQUALITY CONSTRAINTS. G() HAS FIRST */
1378 /* DIMENSIONING PARAMETER MG */
1379 /* H() ON ENTRY H() STORES THE M VECTOR H REPRESENTING */
1380 /* THE RIGHT SIDE OF THE INEQUALITY SYSTEM */
1381 /* REMARK: G(),H() WILL NOT BE CHANGED DURING CALCULATIONS BY LDP */
1382 /* X() ON ENTRY X() NEED NOT BE INITIALIZED. */
1383 /* ON EXIT X() STORES THE SOLUTION VECTOR X IF MODE=1. */
1384 /* XNORM ON EXIT XNORM STORES THE EUCLIDIAN NORM OF THE */
1385 /* SOLUTION VECTOR IF COMPUTATION IS SUCCESSFUL */
1386 /* W() W IS A ONE DIMENSIONAL WORKING SPACE, THE LENGTH */
1387 /* OF WHICH SHOULD BE AT LEAST (M+2)*(N+1) + 2*M */
1388 /* ON EXIT W() STORES THE LAGRANGE MULTIPLIERS */
1389 /* ASSOCIATED WITH THE CONSTRAINTS */
1390 /* AT THE SOLUTION OF PROBLEM LDP */
1391 /* INDEX() INDEX() IS A ONE DIMENSIONAL INT WORKING SPACE */
1392 /* OF LENGTH AT LEAST M */
1393 /* MODE MODE IS A SUCCESS-FAILURE FLAG WITH THE FOLLOWING */
1394 /* MEANINGS: */
1395 /* MODE=1: SUCCESSFUL COMPUTATION */
1396 /* 2: ERROR RETURN BECAUSE OF WRONG DIMENSIONS (N.LE.0) */
1397 /* 3: ITERATION COUNT EXCEEDED BY NNLS */
1398 /* 4: INEQUALITY CONSTRAINTS INCOMPATIBLE */
1399 /* Parameter adjustments */
1400 --index;
1401 --h__;
1402 --x;
1403 g_dim1 = *mg;
1404 g_offset = 1 + g_dim1;
1405 g -= g_offset;
1406 --w;
1407
1408 /* Function Body */
1409 *mode = 2;
1410 if (*n <= 0) {
1411 goto L50;
1412 }
1413 /* STATE DUAL PROBLEM */
1414 *mode = 1;
1415 x[1] = zero;
1416 dcopy___(n, &x[1], &c__0, &x[1], &c__1);
1417 *xnorm = zero;
1418 if (*m == 0) {
1419 goto L50;
1420 }
1421 iw = 0;
1422 i__1 = *m;
1423 for (j = 1; j <= i__1; ++j) {
1424 i__2 = *n;
1425 for (i__ = 1; i__ <= i__2; ++i__) {
1426 ++iw;
1427 /* L10: */
1428 w[iw] = g[j + i__ * g_dim1];
1429 }
1430 ++iw;
1431 /* L20: */
1432 w[iw] = h__[j];
1433 }
1434 if__ = iw + 1;
1435 i__1 = *n;
1436 for (i__ = 1; i__ <= i__1; ++i__) {
1437 ++iw;
1438 /* L30: */
1439 w[iw] = zero;
1440 }
1441 w[iw + 1] = one;
1442 n1 = *n + 1;
1443 iz = iw + 2;
1444 iy = iz + n1;
1445 iwdual = iy + *m;
1446 /* SOLVE DUAL PROBLEM */
1447 nnls_(&w[1], &n1, &n1, m, &w[if__], &w[iy], &rnorm, &w[iwdual], &w[iz], &index[1], mode);
1448 if (*mode != 1) {
1449 goto L50;
1450 }
1451 *mode = 4;
1452 if (rnorm <= zero) {
1453 goto L50;
1454 }
1455 /* COMPUTE SOLUTION OF PRIMAL PROBLEM */
1456 fac = one - ddot_sl__(m, &h__[1], &c__1, &w[iy], &c__1);
1457 d__1 = one + fac;
1458 if (d__1 - one <= zero) {
1459 goto L50;
1460 }
1461 *mode = 1;
1462 fac = one / fac;
1463 i__1 = *n;
1464 for (j = 1; j <= i__1; ++j) {
1465 /* L40: */
1466 x[j] = fac * ddot_sl__(m, &g[j * g_dim1 + 1], &c__1, &w[iy], &c__1);
1467 }
1468 *xnorm = dnrm2___(n, &x[1], &c__1);
1469 /* COMPUTE LAGRANGE MULTIPLIERS FOR PRIMAL PROBLEM */
1470 w[1] = zero;
1471 dcopy___(m, &w[1], &c__0, &w[1], &c__1);
1472 daxpy_sl__(m, &fac, &w[iy], &c__1, &w[1], &c__1);
1473/* END OF SUBROUTINE LDP */
1474L50:
1475 return 0;
1476} /* ldp_ */
1477
1478int nnls_(double *a, const int *mda, const int *m, const int *n, double *b, double *x, double *rnorm, double *w,
1479 double *z__, int *index, int *mode) {
1480 /* Initialized data */
1481
1482 static double zero = 0.;
1483 static double one = 1.;
1484 static double factor = .01;
1485
1486 /* System generated locals */
1487 int a_dim1, a_offset, i__1, i__2;
1488 double d__1;
1489
1490 /* Local variables */
1491 static double c__;
1492 static int i__, j, k, l;
1493 static double s, t;
1494 static int ii, jj, ip, iz, jz;
1495 static double up;
1496 static int iz1, iz2, npp1, iter;
1497 static double wmax, alpha, asave;
1498 static int itmax, izmax, nsetp;
1499 static double unorm;
1500
1501 /* C.L.LAWSON AND R.J.HANSON, JET PROPULSION LABORATORY: */
1502 /* 'SOLVING LEAST SQUARES PROBLEMS'. PRENTICE-HALL.1974 */
1503 /* ********** NONNEGATIVE LEAST SQUARES ********** */
1504 /* GIVEN AN M BY N MATRIX, A, AND AN M-VECTOR, B, COMPUTE AN */
1505 /* N-VECTOR, X, WHICH SOLVES THE LEAST SQUARES PROBLEM */
1506 /* A*X = B SUBJECT TO X >= 0 */
1507 /* A(),MDA,M,N */
1508 /* MDA IS THE FIRST DIMENSIONING PARAMETER FOR THE ARRAY,A(). */
1509 /* ON ENTRY A() CONTAINS THE M BY N MATRIX,A. */
1510 /* ON EXIT A() CONTAINS THE PRODUCT Q*A, */
1511 /* WHERE Q IS AN M BY M ORTHOGONAL MATRIX GENERATED */
1512 /* IMPLICITLY BY THIS SUBROUTINE. */
1513 /* EITHER M>=N OR M<N IS PERMISSIBLE. */
1514 /* THERE IS NO RESTRICTION ON THE RANK OF A. */
1515 /* B() ON ENTRY B() CONTAINS THE M-VECTOR, B. */
1516 /* ON EXIT B() CONTAINS Q*B. */
1517 /* X() ON ENTRY X() NEED NOT BE INITIALIZED. */
1518 /* ON EXIT X() WILL CONTAIN THE SOLUTION VECTOR. */
1519 /* RNORM ON EXIT RNORM CONTAINS THE EUCLIDEAN NORM OF THE */
1520 /* RESIDUAL VECTOR. */
1521 /* W() AN N-ARRAY OF WORKING SPACE. */
1522 /* ON EXIT W() WILL CONTAIN THE DUAL SOLUTION VECTOR. */
1523 /* W WILL SATISFY W(I)=0 FOR ALL I IN SET P */
1524 /* AND W(I)<=0 FOR ALL I IN SET Z */
1525 /* Z() AN M-ARRAY OF WORKING SPACE. */
1526 /* INDEX()AN INT WORKING ARRAY OF LENGTH AT LEAST N. */
1527 /* ON EXIT THE CONTENTS OF THIS ARRAY DEFINE THE SETS */
1528 /* P AND Z AS FOLLOWS: */
1529 /* INDEX(1) THRU INDEX(NSETP) = SET P. */
1530 /* INDEX(IZ1) THRU INDEX (IZ2) = SET Z. */
1531 /* IZ1=NSETP + 1 = NPP1, IZ2=N. */
1532 /* MODE THIS IS A SUCCESS-FAILURE FLAG WITH THE FOLLOWING MEANING: */
1533 /* 1 THE SOLUTION HAS BEEN COMPUTED SUCCESSFULLY. */
1534 /* 2 THE DIMENSIONS OF THE PROBLEM ARE WRONG, */
1535 /* EITHER M <= 0 OR N <= 0. */
1536 /* 3 ITERATION COUNT EXCEEDED, MORE THAN 3*N ITERATIONS. */
1537 /* Parameter adjustments */
1538 --z__;
1539 --b;
1540 --index;
1541 --w;
1542 --x;
1543 a_dim1 = *mda;
1544 a_offset = 1 + a_dim1;
1545 a -= a_offset;
1546
1547 /* Function Body */
1548 /* revised Dieter Kraft, March 1983 */
1549 *mode = 2;
1550 if (*m <= 0 || *n <= 0) {
1551 goto L290;
1552 }
1553 *mode = 1;
1554 iter = 0;
1555 itmax = *n * 3;
1556 /* STEP ONE (INITIALIZE) */
1557 i__1 = *n;
1558 for (i__ = 1; i__ <= i__1; ++i__) {
1559 /* L100: */
1560 index[i__] = i__;
1561 }
1562 iz1 = 1;
1563 iz2 = *n;
1564 nsetp = 0;
1565 npp1 = 1;
1566 x[1] = zero;
1567 dcopy___(n, &x[1], &c__0, &x[1], &c__1);
1568/* STEP TWO (COMPUTE DUAL VARIABLES) */
1569/* .....ENTRY LOOP A */
1570L110:
1571 if (iz1 > iz2 || nsetp >= *m) {
1572 goto L280;
1573 }
1574 i__1 = iz2;
1575 for (iz = iz1; iz <= i__1; ++iz) {
1576 j = index[iz];
1577 /* L120: */
1578 i__2 = *m - nsetp;
1579 w[j] = ddot_sl__(&i__2, &a[npp1 + j * a_dim1], &c__1, &b[npp1], &c__1);
1580 }
1581/* STEP THREE (TEST DUAL VARIABLES) */
1582L130:
1583 wmax = zero;
1584 i__2 = iz2;
1585 for (iz = iz1; iz <= i__2; ++iz) {
1586 j = index[iz];
1587 if (w[j] <= wmax) {
1588 goto L140;
1589 }
1590 wmax = w[j];
1591 izmax = iz;
1592 L140:;
1593 }
1594 /* .....EXIT LOOP A */
1595 if (wmax <= zero) {
1596 goto L280;
1597 }
1598 iz = izmax;
1599 j = index[iz];
1600 /* STEP FOUR (TEST INDEX J FOR LINEAR DEPENDENCY) */
1601 asave = a[npp1 + j * a_dim1];
1602 i__2 = npp1 + 1;
1603 h12_(&c__1, &npp1, &i__2, m, &a[j * a_dim1 + 1], &c__1, &up, &z__[1], &c__1, &c__1, &c__0);
1604 unorm = dnrm2___(&nsetp, &a[j * a_dim1 + 1], &c__1);
1605 t = factor * (d__1 = a[npp1 + j * a_dim1], std::abs(d__1));
1606 d__1 = unorm + t;
1607 if (d__1 - unorm <= zero) {
1608 goto L150;
1609 }
1610 dcopy___(m, &b[1], &c__1, &z__[1], &c__1);
1611 i__2 = npp1 + 1;
1612 h12_(&c__2, &npp1, &i__2, m, &a[j * a_dim1 + 1], &c__1, &up, &z__[1], &c__1, &c__1, &c__1);
1613 if (z__[npp1] / a[npp1 + j * a_dim1] > zero) {
1614 goto L160;
1615 }
1616L150:
1617 a[npp1 + j * a_dim1] = asave;
1618 w[j] = zero;
1619 goto L130;
1620/* STEP FIVE (ADD COLUMN) */
1621L160:
1622 dcopy___(m, &z__[1], &c__1, &b[1], &c__1);
1623 index[iz] = index[iz1];
1624 index[iz1] = j;
1625 ++iz1;
1626 nsetp = npp1;
1627 ++npp1;
1628 i__2 = iz2;
1629 for (jz = iz1; jz <= i__2; ++jz) {
1630 jj = index[jz];
1631 /* L170: */
1632 h12_(&c__2, &nsetp, &npp1, m, &a[j * a_dim1 + 1], &c__1, &up, &a[jj * a_dim1 + 1], &c__1, mda, &c__1);
1633 }
1634 k = std::min(npp1, *mda);
1635 w[j] = zero;
1636 i__2 = *m - nsetp;
1637 dcopy___(&i__2, &w[j], &c__0, &a[k + j * a_dim1], &c__1);
1638/* STEP SIX (SOLVE LEAST SQUARES SUB-PROBLEM) */
1639/* .....ENTRY LOOP B */
1640L180:
1641 for (ip = nsetp; ip >= 1; --ip) {
1642 if (ip == nsetp) {
1643 goto L190;
1644 }
1645 d__1 = -z__[ip + 1];
1646 daxpy_sl__(&ip, &d__1, &a[jj * a_dim1 + 1], &c__1, &z__[1], &c__1);
1647 L190:
1648 jj = index[ip];
1649 /* L200: */
1650 z__[ip] /= a[ip + jj * a_dim1];
1651 }
1652 ++iter;
1653 if (iter <= itmax) {
1654 goto L220;
1655 }
1656L210:
1657 *mode = 3;
1658 goto L280;
1659/* STEP SEVEN TO TEN (STEP LENGTH ALGORITHM) */
1660L220:
1661 alpha = one;
1662 jj = 0;
1663 i__2 = nsetp;
1664 for (ip = 1; ip <= i__2; ++ip) {
1665 if (z__[ip] > zero) {
1666 goto L230;
1667 }
1668 l = index[ip];
1669 t = -x[l] / (z__[ip] - x[l]);
1670 if (alpha < t) {
1671 goto L230;
1672 }
1673 alpha = t;
1674 jj = ip;
1675 L230:;
1676 }
1677 i__2 = nsetp;
1678 for (ip = 1; ip <= i__2; ++ip) {
1679 l = index[ip];
1680 /* L240: */
1681 x[l] = (one - alpha) * x[l] + alpha * z__[ip];
1682 }
1683 /* .....EXIT LOOP B */
1684 if (jj == 0) {
1685 goto L110;
1686 }
1687 /* STEP ELEVEN (DELETE COLUMN) */
1688 i__ = index[jj];
1689L250:
1690 x[i__] = zero;
1691 ++jj;
1692 i__2 = nsetp;
1693 for (j = jj; j <= i__2; ++j) {
1694 ii = index[j];
1695 index[j - 1] = ii;
1696 dsrotg_(&a[j - 1 + ii * a_dim1], &a[j + ii * a_dim1], &c__, &s);
1697 t = a[j - 1 + ii * a_dim1];
1698 dsrot_(n, &a[j - 1 + a_dim1], mda, &a[j + a_dim1], mda, &c__, &s);
1699 a[j - 1 + ii * a_dim1] = t;
1700 a[j + ii * a_dim1] = zero;
1701 /* L260: */
1702 dsrot_(&c__1, &b[j - 1], &c__1, &b[j], &c__1, &c__, &s);
1703 }
1704 npp1 = nsetp;
1705 --nsetp;
1706 --iz1;
1707 index[iz1] = i__;
1708 if (nsetp <= 0) {
1709 goto L210;
1710 }
1711 i__2 = nsetp;
1712 for (jj = 1; jj <= i__2; ++jj) {
1713 i__ = index[jj];
1714 if (x[i__] <= zero) {
1715 goto L250;
1716 }
1717 /* L270: */
1718 }
1719 dcopy___(m, &b[1], &c__1, &z__[1], &c__1);
1720 goto L180;
1721/* STEP TWELVE (SOLUTION) */
1722L280:
1723 k = std::min(npp1, *m);
1724 i__2 = *m - nsetp;
1725 *rnorm = dnrm2___(&i__2, &b[k], &c__1);
1726 if (npp1 > *m) {
1727 w[1] = zero;
1728 dcopy___(n, &w[1], &c__0, &w[1], &c__1);
1729 }
1730/* END OF SUBROUTINE NNLS */
1731L290:
1732 return 0;
1733} /* nnls_ */
1734
1735int hfti_(double *a, const int *mda, const int *m, const int *n, double *b, const int *mdb, const int *nb,
1736 const double *tau, int *krank, double *rnorm, double *h__, double *g, int *ip) {
1737 /* Initialized data */
1738
1739 static double zero = 0.;
1740 static double factor = .001;
1741
1742 /* System generated locals */
1743 int a_dim1, a_offset, b_dim1, b_offset, i__1, i__2, i__3;
1744 double d__1;
1745
1746 /* Local variables */
1747 static int i__, j, k, l;
1748 static int jb, kp1;
1749 static double tmp, hmax;
1750 static int lmax, ldiag;
1751
1752 /* RANK-DEFICIENT LEAST SQUARES ALGORITHM AS DESCRIBED IN: */
1753 /* C.L.LAWSON AND R.J.HANSON, JET PROPULSION LABORATORY, 1973 JUN 12 */
1754 /* TO APPEAR IN 'SOLVING LEAST SQUARES PROBLEMS', PRENTICE-HALL, 1974 */
1755 /* A(*,*),MDA,M,N THE ARRAY A INITIALLY CONTAINS THE M x N MATRIX A */
1756 /* OF THE LEAST SQUARES PROBLEM AX = B. */
1757 /* THE FIRST DIMENSIONING PARAMETER MDA MUST SATISFY */
1758 /* MDA >= M. EITHER M >= N OR M < N IS PERMITTED. */
1759 /* THERE IS NO RESTRICTION ON THE RANK OF A. */
1760 /* THE MATRIX A WILL BE MODIFIED BY THE SUBROUTINE. */
1761 /* B(*,*),MDB,NB IF NB = 0 THE SUBROUTINE WILL MAKE NO REFERENCE */
1762 /* TO THE ARRAY B. IF NB > 0 THE ARRAY B() MUST */
1763 /* INITIALLY CONTAIN THE M x NB MATRIX B OF THE */
1764 /* THE LEAST SQUARES PROBLEM AX = B AND ON RETURN */
1765 /* THE ARRAY B() WILL CONTAIN THE N x NB SOLUTION X. */
1766 /* IF NB>1 THE ARRAY B() MUST BE DOUBLE SUBSCRIPTED */
1767 /* WITH FIRST DIMENSIONING PARAMETER MDB>=MAX(M,N), */
1768 /* IF NB=1 THE ARRAY B() MAY BE EITHER SINGLE OR */
1769 /* DOUBLE SUBSCRIPTED. */
1770 /* TAU ABSOLUTE TOLERANCE PARAMETER FOR PSEUDORANK */
1771 /* DETERMINATION, PROVIDED BY THE USER. */
1772 /* KRANK PSEUDORANK OF A, SET BY THE SUBROUTINE. */
1773 /* RNORM ON EXIT, RNORM(J) WILL CONTAIN THE EUCLIDIAN */
1774 /* NORM OF THE RESIDUAL VECTOR FOR THE PROBLEM */
1775 /* DEFINED BY THE J-TH COLUMN VECTOR OF THE ARRAY B. */
1776 /* H(), G() ARRAYS OF WORKING SPACE OF LENGTH >= N. */
1777 /* IP() INT ARRAY OF WORKING SPACE OF LENGTH >= N */
1778 /* RECORDING PERMUTATION INDICES OF COLUMN VECTORS */
1779 /* Parameter adjustments */
1780 --ip;
1781 --g;
1782 --h__;
1783 a_dim1 = *mda;
1784 a_offset = 1 + a_dim1;
1785 a -= a_offset;
1786 --rnorm;
1787 b_dim1 = *mdb;
1788 b_offset = 1 + b_dim1;
1789 b -= b_offset;
1790
1791 /* Function Body */
1792 k = 0;
1793 ldiag = std::min(*m, *n);
1794 if (ldiag <= 0) {
1795 goto L270;
1796 }
1797 /* COMPUTE LMAX */
1798 i__1 = ldiag;
1799 for (j = 1; j <= i__1; ++j) {
1800 if (j == 1) {
1801 goto L20;
1802 }
1803 lmax = j;
1804 i__2 = *n;
1805 for (l = j; l <= i__2; ++l) {
1806 /* Computing 2nd power */
1807 d__1 = a[j - 1 + l * a_dim1];
1808 h__[l] -= d__1 * d__1;
1809 /* L10: */
1810 if (h__[l] > h__[lmax]) {
1811 lmax = l;
1812 }
1813 }
1814 d__1 = hmax + factor * h__[lmax];
1815 if (d__1 - hmax > zero) {
1816 goto L50;
1817 }
1818 L20:
1819 lmax = j;
1820 i__2 = *n;
1821 for (l = j; l <= i__2; ++l) {
1822 h__[l] = zero;
1823 i__3 = *m;
1824 for (i__ = j; i__ <= i__3; ++i__) {
1825 /* L30: */
1826 /* Computing 2nd power */
1827 d__1 = a[i__ + l * a_dim1];
1828 h__[l] += d__1 * d__1;
1829 }
1830 /* L40: */
1831 if (h__[l] > h__[lmax]) {
1832 lmax = l;
1833 }
1834 }
1835 hmax = h__[lmax];
1836 /* COLUMN INTERCHANGES IF NEEDED */
1837 L50:
1838 ip[j] = lmax;
1839 if (ip[j] == j) {
1840 goto L70;
1841 }
1842 i__2 = *m;
1843 for (i__ = 1; i__ <= i__2; ++i__) {
1844 tmp = a[i__ + j * a_dim1];
1845 a[i__ + j * a_dim1] = a[i__ + lmax * a_dim1];
1846 /* L60: */
1847 a[i__ + lmax * a_dim1] = tmp;
1848 }
1849 h__[lmax] = h__[j];
1850 /* J-TH TRANSFORMATION AND APPLICATION TO A AND B */
1851 L70:
1852 /* Computing MIN */
1853 i__2 = j + 1;
1854 i__ = std::min(i__2, *n);
1855 i__2 = j + 1;
1856 i__3 = *n - j;
1857 h12_(&c__1, &j, &i__2, m, &a[j * a_dim1 + 1], &c__1, &h__[j], &a[i__ * a_dim1 + 1], &c__1, mda, &i__3);
1858 /* L80: */
1859 i__2 = j + 1;
1860 h12_(&c__2, &j, &i__2, m, &a[j * a_dim1 + 1], &c__1, &h__[j], &b[b_offset], &c__1, mdb, nb);
1861 }
1862 /* DETERMINE PSEUDORANK */
1863 i__2 = ldiag;
1864 for (j = 1; j <= i__2; ++j) {
1865 /* L90: */
1866 if ((d__1 = a[j + j * a_dim1], std::abs(d__1)) <= *tau) {
1867 goto L100;
1868 }
1869 }
1870 k = ldiag;
1871 goto L110;
1872L100:
1873 k = j - 1;
1874L110:
1875 kp1 = k + 1;
1876 /* NORM OF RESIDUALS */
1877 i__2 = *nb;
1878 for (jb = 1; jb <= i__2; ++jb) {
1879 /* L130: */
1880 i__1 = *m - k;
1881 rnorm[jb] = dnrm2___(&i__1, &b[kp1 + jb * b_dim1], &c__1);
1882 }
1883 if (k > 0) {
1884 goto L160;
1885 }
1886 i__1 = *nb;
1887 for (jb = 1; jb <= i__1; ++jb) {
1888 i__2 = *n;
1889 for (i__ = 1; i__ <= i__2; ++i__) {
1890 /* L150: */
1891 b[i__ + jb * b_dim1] = zero;
1892 }
1893 }
1894 goto L270;
1895L160:
1896 if (k == *n) {
1897 goto L180;
1898 }
1899 /* HOUSEHOLDER DECOMPOSITION OF FIRST K ROWS */
1900 for (i__ = k; i__ >= 1; --i__) {
1901 /* L170: */
1902 i__2 = i__ - 1;
1903 h12_(&c__1, &i__, &kp1, n, &a[i__ + a_dim1], mda, &g[i__], &a[a_offset], mda, &c__1, &i__2);
1904 }
1905L180:
1906 i__2 = *nb;
1907 for (jb = 1; jb <= i__2; ++jb) {
1908 /* SOLVE K*K TRIANGULAR SYSTEM */
1909 for (i__ = k; i__ >= 1; --i__) {
1910 /* Computing MIN */
1911 i__1 = i__ + 1;
1912 j = std::min(i__1, *n);
1913 /* L210: */
1914 i__1 = k - i__;
1915 b[i__ + jb * b_dim1] =
1916 (b[i__ + jb * b_dim1] - ddot_sl__(&i__1, &a[i__ + j * a_dim1], mda, &b[j + jb * b_dim1], &c__1)) /
1917 a[i__ + i__ * a_dim1];
1918 }
1919 /* COMPLETE SOLUTION VECTOR */
1920 if (k == *n) {
1921 goto L240;
1922 }
1923 i__1 = *n;
1924 for (j = kp1; j <= i__1; ++j) {
1925 /* L220: */
1926 b[j + jb * b_dim1] = zero;
1927 }
1928 i__1 = k;
1929 for (i__ = 1; i__ <= i__1; ++i__) {
1930 /* L230: */
1931 h12_(&c__2, &i__, &kp1, n, &a[i__ + a_dim1], mda, &g[i__], &b[jb * b_dim1 + 1], &c__1, mdb, &c__1);
1932 }
1933 /* REORDER SOLUTION ACCORDING TO PREVIOUS COLUMN INTERCHANGES */
1934 L240:
1935 for (j = ldiag; j >= 1; --j) {
1936 if (ip[j] == j) {
1937 goto L250;
1938 }
1939 l = ip[j];
1940 tmp = b[l + jb * b_dim1];
1941 b[l + jb * b_dim1] = b[j + jb * b_dim1];
1942 b[j + jb * b_dim1] = tmp;
1943 L250:;
1944 }
1945 }
1946L270:
1947 *krank = k;
1948 return 0;
1949} /* hfti_ */
1950
1951int h12_(const int *mode, const int *lpivot, const int *l1, const int *m, double *u, const int *iue, double *up,
1952 double *c__, const int *ice, const int *icv, const int *ncv) {
1953 /* Initialized data */
1954
1955 static double one = 1.;
1956 static double zero = 0.;
1957
1958 /* System generated locals */
1959 int u_dim1, u_offset, i__1, i__2;
1960 double d__1;
1961
1962 /* Local variables */
1963 static double b;
1964 static int i__, j, i2, i3, i4;
1965 static double cl, sm;
1966 static int incr;
1967 static double clinv;
1968
1969 /* C.L.LAWSON AND R.J.HANSON, JET PROPULSION LABORATORY, 1973 JUN 12 */
1970 /* TO APPEAR IN 'SOLVING LEAST SQUARES PROBLEMS', PRENTICE-HALL, 1974 */
1971 /* CONSTRUCTION AND/OR APPLICATION OF A SINGLE */
1972 /* HOUSEHOLDER TRANSFORMATION Q = I + U*(U**T)/B */
1973 /* MODE = 1 OR 2 TO SELECT ALGORITHM H1 OR H2 . */
1974 /* LPIVOT IS THE INDEX OF THE PIVOT ELEMENT. */
1975 /* L1,M IF L1 <= M THE TRANSFORMATION WILL BE CONSTRUCTED TO */
1976 /* ZERO ELEMENTS INDEXED FROM L1 THROUGH M. */
1977 /* IF L1 > M THE SUBROUTINE DOES AN IDENTITY TRANSFORMATION. */
1978 /* U(),IUE,UP */
1979 /* ON ENTRY TO H1 U() STORES THE PIVOT VECTOR. */
1980 /* IUE IS THE STORAGE INCREMENT BETWEEN ELEMENTS. */
1981 /* ON EXIT FROM H1 U() AND UP STORE QUANTITIES DEFINING */
1982 /* THE VECTOR U OF THE HOUSEHOLDER TRANSFORMATION. */
1983 /* ON ENTRY TO H2 U() AND UP */
1984 /* SHOULD STORE QUANTITIES PREVIOUSLY COMPUTED BY H1. */
1985 /* THESE WILL NOT BE MODIFIED BY H2. */
1986 /* C() ON ENTRY TO H1 OR H2 C() STORES A MATRIX WHICH WILL BE */
1987 /* REGARDED AS A SET OF VECTORS TO WHICH THE HOUSEHOLDER */
1988 /* TRANSFORMATION IS TO BE APPLIED. */
1989 /* ON EXIT C() STORES THE SET OF TRANSFORMED VECTORS. */
1990 /* ICE STORAGE INCREMENT BETWEEN ELEMENTS OF VECTORS IN C(). */
1991 /* ICV STORAGE INCREMENT BETWEEN VECTORS IN C(). */
1992 /* NCV NUMBER OF VECTORS IN C() TO BE TRANSFORMED. */
1993 /* IF NCV <= 0 NO OPERATIONS WILL BE DONE ON C(). */
1994 /* Parameter adjustments */
1995 u_dim1 = *iue;
1996 u_offset = 1 + u_dim1;
1997 u -= u_offset;
1998 --c__;
1999
2000 /* Function Body */
2001 if (0 >= *lpivot || *lpivot >= *l1 || *l1 > *m) {
2002 goto L80;
2003 }
2004 cl = (d__1 = u[*lpivot * u_dim1 + 1], std::abs(d__1));
2005 if (*mode == 2) {
2006 goto L30;
2007 }
2008 /* ****** CONSTRUCT THE TRANSFORMATION ****** */
2009 i__1 = *m;
2010 for (j = *l1; j <= i__1; ++j) {
2011 sm = (d__1 = u[j * u_dim1 + 1], std::abs(d__1));
2012 /* L10: */
2013 cl = std::max(sm, cl);
2014 }
2015 if (cl <= zero) {
2016 goto L80;
2017 }
2018 clinv = one / cl;
2019 /* Computing 2nd power */
2020 d__1 = u[*lpivot * u_dim1 + 1] * clinv;
2021 sm = d__1 * d__1;
2022 i__1 = *m;
2023 for (j = *l1; j <= i__1; ++j) {
2024 /* L20: */
2025 /* Computing 2nd power */
2026 d__1 = u[j * u_dim1 + 1] * clinv;
2027 sm += d__1 * d__1;
2028 }
2029 cl *= sqrt(sm);
2030 if (u[*lpivot * u_dim1 + 1] > zero) {
2031 cl = -cl;
2032 }
2033 *up = u[*lpivot * u_dim1 + 1] - cl;
2034 u[*lpivot * u_dim1 + 1] = cl;
2035 goto L40;
2036/* ****** APPLY THE TRANSFORMATION I+U*(U**T)/B TO C ****** */
2037L30:
2038 if (cl <= zero) {
2039 goto L80;
2040 }
2041L40:
2042 if (*ncv <= 0) {
2043 goto L80;
2044 }
2045 b = *up * u[*lpivot * u_dim1 + 1];
2046 if (b >= zero) {
2047 goto L80;
2048 }
2049 b = one / b;
2050 i2 = 1 - *icv + *ice * (*lpivot - 1);
2051 incr = *ice * (*l1 - *lpivot);
2052 i__1 = *ncv;
2053 for (j = 1; j <= i__1; ++j) {
2054 i2 += *icv;
2055 i3 = i2 + incr;
2056 i4 = i3;
2057 sm = c__[i2] * *up;
2058 i__2 = *m;
2059 for (i__ = *l1; i__ <= i__2; ++i__) {
2060 sm += c__[i3] * u[i__ * u_dim1 + 1];
2061 /* L50: */
2062 i3 += *ice;
2063 }
2064 if (sm == zero) {
2065 goto L70;
2066 }
2067 sm *= b;
2068 c__[i2] += sm * *up;
2069 i__2 = *m;
2070 for (i__ = *l1; i__ <= i__2; ++i__) {
2071 c__[i4] += sm * u[i__ * u_dim1 + 1];
2072 /* L60: */
2073 i4 += *ice;
2074 }
2075 L70:;
2076 }
2077L80:
2078 return 0;
2079} /* h12_ */
2080
2081int ldl_(const int *n, double *a, double *z__, const double *sigma, double *w) {
2082 /* Initialized data */
2083
2084 static double zero = 0.;
2085 static double one = 1.;
2086 static double four = 4.;
2087 static double epmach = 2.22e-16;
2088
2089 /* System generated locals */
2090 int i__1, i__2;
2091
2092 /* Local variables */
2093 static int i__, j;
2094 static double t, u, v;
2095 static int ij;
2096 static double tp, beta, gamma, alpha, delta;
2097
2098 /* LDL LDL' - RANK-ONE - UPDATE */
2099 /* PURPOSE: */
2100 /* UPDATES THE LDL' FACTORS OF MATRIX A BY RANK-ONE MATRIX */
2101 /* SIGMA*Z*Z' */
2102 /* INPUT ARGUMENTS: (* MEANS PARAMETERS ARE CHANGED DURING EXECUTION) */
2103 /* N : ORDER OF THE COEFFICIENT MATRIX A */
2104 /* * A : POSITIVE DEFINITE MATRIX OF DIMENSION N; */
2105 /* ONLY THE LOWER TRIANGLE IS USED AND IS STORED COLUMN BY */
2106 /* COLUMN AS ONE DIMENSIONAL ARRAY OF DIMENSION N*(N+1)/2. */
2107 /* * Z : VECTOR OF DIMENSION N OF UPDATING ELEMENTS */
2108 /* SIGMA : SCALAR FACTOR BY WHICH THE MODIFYING DYADE Z*Z' IS */
2109 /* MULTIPLIED */
2110 /* OUTPUT ARGUMENTS: */
2111 /* A : UPDATED LDL' FACTORS */
2112 /* WORKING ARRAY: */
2113 /* W : VECTOR OP DIMENSION N (USED ONLY IF SIGMA .LT. ZERO) */
2114 /* METHOD: */
2115 /* THAT OF FLETCHER AND POWELL AS DESCRIBED IN : */
2116 /* FLETCHER,R.,(1974) ON THE MODIFICATION OF LDL' FACTORIZATION. */
2117 /* POWELL,M.J.D. MATH.COMPUTATION 28, 1067-1078. */
2118 /* IMPLEMENTED BY: */
2119 /* KRAFT,D., DFVLR - INSTITUT FUER DYNAMIK DER FLUGSYSTEME */
2120 /* D-8031 OBERPFAFFENHOFEN */
2121 /* STATUS: 15. JANUARY 1980 */
2122 /* SUBROUTINES REQUIRED: NONE */
2123 /* Parameter adjustments */
2124 --w;
2125 --z__;
2126 --a;
2127
2128 /* Function Body */
2129 if (*sigma == zero) {
2130 goto L280;
2131 }
2132 ij = 1;
2133 t = one / *sigma;
2134 if (*sigma > zero) {
2135 goto L220;
2136 }
2137 /* PREPARE NEGATIVE UPDATE */
2138 i__1 = *n;
2139 for (i__ = 1; i__ <= i__1; ++i__) {
2140 /* L150: */
2141 w[i__] = z__[i__];
2142 }
2143 for (i__ = 1; i__ <= i__1; ++i__) {
2144 v = w[i__];
2145 t += v * v / a[ij];
2146 i__2 = *n;
2147 for (j = i__ + 1; j <= i__2; ++j) {
2148 ++ij;
2149 /* L160: */
2150 w[j] -= v * a[ij];
2151 }
2152 /* L170: */
2153 ++ij;
2154 }
2155 if (t >= zero) {
2156 t = epmach / *sigma;
2157 }
2158 for (i__ = 1; i__ <= i__1; ++i__) {
2159 j = *n + 1 - i__;
2160 ij -= i__;
2161 u = w[j];
2162 w[j] = t;
2163 /* L210: */
2164 t -= u * u / a[ij];
2165 }
2166L220:
2167 /* HERE UPDATING BEGINS */
2168 i__1 = *n;
2169 for (i__ = 1; i__ <= i__1; ++i__) {
2170 v = z__[i__];
2171 delta = v / a[ij];
2172 if (*sigma < zero) {
2173 tp = w[i__];
2174 }
2175 if (*sigma > zero) {
2176 tp = t + delta * v;
2177 }
2178 alpha = tp / t;
2179 a[ij] = alpha * a[ij];
2180 if (i__ == *n) {
2181 goto L280;
2182 }
2183 beta = delta / tp;
2184 if (alpha > four) {
2185 goto L240;
2186 }
2187 i__2 = *n;
2188 for (j = i__ + 1; j <= i__2; ++j) {
2189 ++ij;
2190 z__[j] -= v * a[ij];
2191 /* L230: */
2192 a[ij] += beta * z__[j];
2193 }
2194 goto L260;
2195 L240:
2196 gamma = t / tp;
2197 i__2 = *n;
2198 for (j = i__ + 1; j <= i__2; ++j) {
2199 ++ij;
2200 u = a[ij];
2201 a[ij] = gamma * u + beta * z__[j];
2202 /* L250: */
2203 z__[j] -= v * u;
2204 }
2205 L260:
2206 ++ij;
2207 /* L270: */
2208 t = tp;
2209 }
2210L280:
2211 return 0;
2212 /* END OF LDL */
2213} /* ldl_ */
2214
2215double linmin_(int *mode, const double *ax, const double *bx, const double *f, const double *tol) {
2216 /* Initialized data */
2217
2218 static double c__ = .381966011;
2219 static double eps = 1.5e-8;
2220 static double zero = 0.;
2221
2222 /* System generated locals */
2223 double ret_val, d__1;
2224
2225 /* Local variables */
2226 static double a, b, d__, e, m, p, q, r__, u, v, w, x, fu, fv, fw, fx, tol1, tol2;
2227
2228 /* LINMIN LINESEARCH WITHOUT DERIVATIVES */
2229 /* PURPOSE: */
2230 /* TO FIND THE ARGUMENT LINMIN WHERE THE FUNCTION F TAKES IT'S MINIMUM */
2231 /* ON THE INTERVAL AX, BX. */
2232 /* COMBINATION OF GOLDEN SECTION AND SUCCESSIVE QUADRATIC INTERPOLATION. */
2233 /* INPUT ARGUMENTS: (* MEANS PARAMETERS ARE CHANGED DURING EXECUTION) */
2234 /* *MODE SEE OUTPUT ARGUMENTS */
2235 /* AX LEFT ENDPOINT OF INITIAL INTERVAL */
2236 /* BX RIGHT ENDPOINT OF INITIAL INTERVAL */
2237 /* F FUNCTION VALUE AT LINMIN WHICH IS TO BE BROUGHT IN BY */
2238 /* REVERSE COMMUNICATION CONTROLLED BY MODE */
2239 /* TOL DESIRED LENGTH OF INTERVAL OF UNCERTAINTY OF FINAL RESULT */
2240 /* OUTPUT ARGUMENTS: */
2241 /* LINMIN ABSCISSA APPROXIMATING THE POINT WHERE F ATTAINS A MINIMUM */
2242 /* MODE CONTROLS REVERSE COMMUNICATION */
2243 /* MUST BE SET TO 0 INITIALLY, RETURNS WITH INTERMEDIATE */
2244 /* VALUES 1 AND 2 WHICH MUST NOT BE CHANGED BY THE USER, */
2245 /* ENDS WITH CONVERGENCE WITH VALUE 3. */
2246 /* WORKING ARRAY: */
2247 /* NONE */
2248 /* METHOD: */
2249 /* THIS FUNCTION SUBPROGRAM IS A SLIGHTLY MODIFIED VERSION OF THE */
2250 /* ALGOL 60 PROCEDURE LOCALMIN GIVEN IN */
2251 /* R.P. BRENT: ALGORITHMS FOR MINIMIZATION WITHOUT DERIVATIVES, */
2252 /* PRENTICE-HALL (1973). */
2253 /* IMPLEMENTED BY: */
2254 /* KRAFT, D., DFVLR - INSTITUT FUER DYNAMIK DER FLUGSYSTEME */
2255 /* D-8031 OBERPFAFFENHOFEN */
2256 /* STATUS: 31. AUGUST 1984 */
2257 /* SUBROUTINES REQUIRED: NONE */
2258 /* EPS = SQUARE - ROOT OF MACHINE PRECISION */
2259 /* C = GOLDEN SECTION RATIO = (3-SQRT(5))/2 */
2260 switch (*mode) {
2261 case 1:
2262 goto L10;
2263 case 2:
2264 goto L55;
2265 }
2266 /* INITIALIZATION */
2267 a = *ax;
2268 b = *bx;
2269 e = zero;
2270 v = a + c__ * (b - a);
2271 w = v;
2272 x = w;
2273 ret_val = x;
2274 *mode = 1;
2275 goto L100;
2276/* MAIN LOOP STARTS HERE */
2277L10:
2278 fx = *f;
2279 fv = fx;
2280 fw = fv;
2281L20:
2282 m = (a + b) * .5;
2283 tol1 = eps * std::abs(x) + *tol;
2284 tol2 = tol1 + tol1;
2285 /* TEST CONVERGENCE */
2286 if ((d__1 = x - m, std::abs(d__1)) <= tol2 - (b - a) * .5) {
2287 goto L90;
2288 }
2289 r__ = zero;
2290 q = r__;
2291 p = q;
2292 if (std::abs(e) <= tol1) {
2293 goto L30;
2294 }
2295 /* FIT PARABOLA */
2296 r__ = (x - w) * (fx - fv);
2297 q = (x - v) * (fx - fw);
2298 p = (x - v) * q - (x - w) * r__;
2299 q -= r__;
2300 q += q;
2301 if (q > zero) {
2302 p = -p;
2303 }
2304 if (q < zero) {
2305 q = -q;
2306 }
2307 r__ = e;
2308 e = d__;
2309/* IS PARABOLA ACCEPTABLE */
2310L30:
2311 if (std::abs(p) >= (d__1 = q * r__, std::abs(d__1)) * .5 || p <= q * (a - x) || p >= q * (b - x)) {
2312 goto L40;
2313 }
2314 /* PARABOLIC INTERPOLATION STEP */
2315 d__ = p / q;
2316 /* F MUST NOT BE EVALUATED TOO CLOSE TO A OR B */
2317 if (u - a < tol2) {
2318 d__1 = m - x;
2319 d__ = d_sign(&tol1, &d__1);
2320 }
2321 if (b - u < tol2) {
2322 d__1 = m - x;
2323 d__ = d_sign(&tol1, &d__1);
2324 }
2325 goto L50;
2326/* GOLDEN SECTION STEP */
2327L40:
2328 if (x >= m) {
2329 e = a - x;
2330 }
2331 if (x < m) {
2332 e = b - x;
2333 }
2334 d__ = c__ * e;
2335/* F MUST NOT BE EVALUATED TOO CLOSE TO X */
2336L50:
2337 if (std::abs(d__) < tol1) {
2338 d__ = d_sign(&tol1, &d__);
2339 }
2340 u = x + d__;
2341 ret_val = u;
2342 *mode = 2;
2343 goto L100;
2344L55:
2345 fu = *f;
2346 /* UPDATE A, B, V, W, AND X */
2347 if (fu > fx) {
2348 goto L60;
2349 }
2350 if (u >= x) {
2351 a = x;
2352 }
2353 if (u < x) {
2354 b = x;
2355 }
2356 v = w;
2357 fv = fw;
2358 w = x;
2359 fw = fx;
2360 x = u;
2361 fx = fu;
2362 goto L85;
2363L60:
2364 if (u < x) {
2365 a = u;
2366 }
2367 if (u >= x) {
2368 b = u;
2369 }
2370 if (fu <= fw || w == x) {
2371 goto L70;
2372 }
2373 if (fu <= fv || v == x || v == w) {
2374 goto L80;
2375 }
2376 goto L85;
2377L70:
2378 v = w;
2379 fv = fw;
2380 w = u;
2381 fw = fu;
2382 goto L85;
2383L80:
2384 v = u;
2385 fv = fu;
2386L85:
2387 goto L20;
2388/* END OF MAIN LOOP */
2389L90:
2390 ret_val = x;
2391 *mode = 3;
2392L100:
2393 return ret_val;
2394 /* END OF LINMIN */
2395} /* linmin_ */
2396
2397/* ## Following a selection from BLAS Level 1 */
2398int daxpy_sl__(const int *n, const double *da, double const *dx, const int *incx, double *dy, int const *incy) {
2399 /* System generated locals */
2400 int i__1;
2401
2402 /* Local variables */
2403 static int i__, m, ix, iy, mp1;
2404
2405 /* CONSTANT TIMES A VECTOR PLUS A VECTOR. */
2406 /* USES UNROLLED LOOPS FOR INCREMENTS EQUAL TO ONE. */
2407 /* JACK DONGARRA, LINPACK, 3/11/78. */
2408 /* Parameter adjustments */
2409 --dy;
2410 --dx;
2411
2412 /* Function Body */
2413 if (*n <= 0) {
2414 return 0;
2415 }
2416 if (*da == 0.) {
2417 return 0;
2418 }
2419 if (*incx == 1 && *incy == 1) {
2420 goto L20;
2421 }
2422 /* CODE FOR UNEQUAL INCREMENTS OR EQUAL INCREMENTS */
2423 /* NOT EQUAL TO 1 */
2424 ix = 1;
2425 iy = 1;
2426 if (*incx < 0) {
2427 ix = (-(*n) + 1) * *incx + 1;
2428 }
2429 if (*incy < 0) {
2430 iy = (-(*n) + 1) * *incy + 1;
2431 }
2432 i__1 = *n;
2433 for (i__ = 1; i__ <= i__1; ++i__) {
2434 dy[iy] += *da * dx[ix];
2435 ix += *incx;
2436 iy += *incy;
2437 /* L10: */
2438 }
2439 return 0;
2440/* CODE FOR BOTH INCREMENTS EQUAL TO 1 */
2441/* CLEAN-UP LOOP */
2442L20:
2443 m = *n % 4;
2444 if (m == 0) {
2445 goto L40;
2446 }
2447 i__1 = m;
2448 for (i__ = 1; i__ <= i__1; ++i__) {
2449 dy[i__] += *da * dx[i__];
2450 /* L30: */
2451 }
2452 if (*n < 4) {
2453 return 0;
2454 }
2455L40:
2456 mp1 = m + 1;
2457 i__1 = *n;
2458 for (i__ = mp1; i__ <= i__1; i__ += 4) {
2459 dy[i__] += *da * dx[i__];
2460 dy[i__ + 1] += *da * dx[i__ + 1];
2461 dy[i__ + 2] += *da * dx[i__ + 2];
2462 dy[i__ + 3] += *da * dx[i__ + 3];
2463 /* L50: */
2464 }
2465 return 0;
2466} /* daxpy_sl__ */
2467
2468int dcopy___(const int *n, double const *dx, const int *incx, double *dy, int const *incy) {
2469 /* System generated locals */
2470 int i__1;
2471
2472 /* Local variables */
2473 static int i__, m, ix, iy, mp1;
2474
2475 /* COPIES A VECTOR, X, TO A VECTOR, Y. */
2476 /* USES UNROLLED LOOPS FOR INCREMENTS EQUAL TO ONE. */
2477 /* JACK DONGARRA, LINPACK, 3/11/78. */
2478 /* Parameter adjustments */
2479 --dy;
2480 --dx;
2481
2482 /* Function Body */
2483 if (*n <= 0) {
2484 return 0;
2485 }
2486 if (*incx == 1 && *incy == 1) {
2487 goto L20;
2488 }
2489 /* CODE FOR UNEQUAL INCREMENTS OR EQUAL INCREMENTS */
2490 /* NOT EQUAL TO 1 */
2491 ix = 1;
2492 iy = 1;
2493 if (*incx < 0) {
2494 ix = (-(*n) + 1) * *incx + 1;
2495 }
2496 if (*incy < 0) {
2497 iy = (-(*n) + 1) * *incy + 1;
2498 }
2499 i__1 = *n;
2500 for (i__ = 1; i__ <= i__1; ++i__) {
2501 dy[iy] = dx[ix];
2502 ix += *incx;
2503 iy += *incy;
2504 /* L10: */
2505 }
2506 return 0;
2507/* CODE FOR BOTH INCREMENTS EQUAL TO 1 */
2508/* CLEAN-UP LOOP */
2509L20:
2510 m = *n % 7;
2511 if (m == 0) {
2512 goto L40;
2513 }
2514 i__1 = m;
2515 for (i__ = 1; i__ <= i__1; ++i__) {
2516 dy[i__] = dx[i__];
2517 /* L30: */
2518 }
2519 if (*n < 7) {
2520 return 0;
2521 }
2522L40:
2523 mp1 = m + 1;
2524 i__1 = *n;
2525 for (i__ = mp1; i__ <= i__1; i__ += 7) {
2526 dy[i__] = dx[i__];
2527 dy[i__ + 1] = dx[i__ + 1];
2528 dy[i__ + 2] = dx[i__ + 2];
2529 dy[i__ + 3] = dx[i__ + 3];
2530 dy[i__ + 4] = dx[i__ + 4];
2531 dy[i__ + 5] = dx[i__ + 5];
2532 dy[i__ + 6] = dx[i__ + 6];
2533 /* L50: */
2534 }
2535 return 0;
2536} /* dcopy___ */
2537
2538double ddot_sl__(const int *n, double const *dx, const int *incx, double const *dy, int const *incy) {
2539 /* System generated locals */
2540 int i__1;
2541 double ret_val;
2542
2543 /* Local variables */
2544 static int i__, m, ix, iy, mp1;
2545 static double dtemp;
2546
2547 /* FORMS THE DOT PRODUCT OF TWO VECTORS. */
2548 /* USES UNROLLED LOOPS FOR INCREMENTS EQUAL TO ONE. */
2549 /* JACK DONGARRA, LINPACK, 3/11/78. */
2550 /* Parameter adjustments */
2551 --dy;
2552 --dx;
2553
2554 /* Function Body */
2555 ret_val = 0.;
2556 dtemp = 0.;
2557 if (*n <= 0) {
2558 return ret_val;
2559 }
2560 if (*incx == 1 && *incy == 1) {
2561 goto L20;
2562 }
2563 /* CODE FOR UNEQUAL INCREMENTS OR EQUAL INCREMENTS */
2564 /* NOT EQUAL TO 1 */
2565 ix = 1;
2566 iy = 1;
2567 if (*incx < 0) {
2568 ix = (-(*n) + 1) * *incx + 1;
2569 }
2570 if (*incy < 0) {
2571 iy = (-(*n) + 1) * *incy + 1;
2572 }
2573 i__1 = *n;
2574 for (i__ = 1; i__ <= i__1; ++i__) {
2575 dtemp += dx[ix] * dy[iy];
2576 ix += *incx;
2577 iy += *incy;
2578 /* L10: */
2579 }
2580 ret_val = dtemp;
2581 return ret_val;
2582/* CODE FOR BOTH INCREMENTS EQUAL TO 1 */
2583/* CLEAN-UP LOOP */
2584L20:
2585 m = *n % 5;
2586 if (m == 0) {
2587 goto L40;
2588 }
2589 i__1 = m;
2590 for (i__ = 1; i__ <= i__1; ++i__) {
2591 dtemp += dx[i__] * dy[i__];
2592 /* L30: */
2593 }
2594 if (*n < 5) {
2595 goto L60;
2596 }
2597L40:
2598 mp1 = m + 1;
2599 i__1 = *n;
2600 for (i__ = mp1; i__ <= i__1; i__ += 5) {
2601 dtemp = dtemp + dx[i__] * dy[i__] + dx[i__ + 1] * dy[i__ + 1] + dx[i__ + 2] * dy[i__ + 2] +
2602 dx[i__ + 3] * dy[i__ + 3] + dx[i__ + 4] * dy[i__ + 4];
2603 /* L50: */
2604 }
2605L60:
2606 ret_val = dtemp;
2607 return ret_val;
2608} /* ddot_sl__ */
2609
2610double dnrm2___(const int *n, double const *dx, int const *incx) {
2611 /* Initialized data */
2612
2613 static double zero = 0.;
2614 static double one = 1.;
2615 static double cutlo = 8.232e-11;
2616 static double cuthi = 1.304e19;
2617
2618 /* Format strings */
2619 /* -- Unused -- */
2620 /* static char fmt_30[] = "";
2621 static char fmt_50[] = "";
2622 static char fmt_70[] = "";
2623 static char fmt_110[] = ""; */
2624
2625 /* System generated locals */
2626 int i__1, i__2;
2627 double ret_val, d__1;
2628
2629 /* Local variables */
2630 static int i__, j, nn;
2631 static double sum, xmax;
2632 static int next;
2633 static double hitest;
2634
2635 /* Assigned format variables */
2636 /* static char *next_fmt = fmt_30; */ /* Avoid compiler warning */
2637
2638 /* Parameter adjustments */
2639 --dx;
2640
2641 /* Function Body */
2642 /* EUCLIDEAN NORM OF THE N-VECTOR STORED IN DX() WITH STORAGE */
2643 /* INCREMENT INCX . */
2644 /* IF N .LE. 0 RETURN WITH RESULT = 0. */
2645 /* IF N .GE. 1 THEN INCX MUST BE .GE. 1 */
2646 /* C.L.LAWSON, 1978 JAN 08 */
2647 /* FOUR PHASE METHOD USING TWO BUILT-IN CONSTANTS THAT ARE */
2648 /* HOPEFULLY APPLICABLE TO ALL MACHINES. */
2649 /* CUTLO = MAXIMUM OF SQRT(U/EPS) OVER ALL KNOWN MACHINES. */
2650 /* CUTHI = MINIMUM OF SQRT(V) OVER ALL KNOWN MACHINES. */
2651 /* WHERE */
2652 /* EPS = SMALLEST NO. SUCH THAT EPS + 1. .GT. 1. */
2653 /* U = SMALLEST POSITIVE NO. (UNDERFLOW LIMIT) */
2654 /* V = LARGEST NO. (OVERFLOW LIMIT) */
2655 /* BRIEF OUTLINE OF ALGORITHM.. */
2656 /* PHASE 1 SCANS ZERO COMPONENTS. */
2657 /* MOVE TO PHASE 2 WHEN A COMPONENT IS NONZERO AND .LE. CUTLO */
2658 /* MOVE TO PHASE 3 WHEN A COMPONENT IS .GT. CUTLO */
2659 /* MOVE TO PHASE 4 WHEN A COMPONENT IS .GE. CUTHI/M */
2660 /* WHERE M = N FOR X() REAL AND M = 2*N FOR COMPLEX. */
2661 /* VALUES FOR CUTLO AND CUTHI.. */
2662 /* FROM THE ENVIRONMENTAL PARAMETERS LISTED IN THE IMSL CONVERTER */
2663 /* DOCUMENT THE LIMITING VALUES ARE AS FOLLOWS.. */
2664 /* CUTLO, S.P. U/EPS = 2**(-102) FOR HONEYWELL. CLOSE SECONDS ARE */
2665 /* UNIVAC AND DEC AT 2**(-103) */
2666 /* THUS CUTLO = 2**(-51) = 4.44089E-16 */
2667 /* CUTHI, S.P. V = 2**127 FOR UNIVAC, HONEYWELL, AND DEC. */
2668 /* THUS CUTHI = 2**(63.5) = 1.30438E19 */
2669 /* CUTLO, D.P. U/EPS = 2**(-67) FOR HONEYWELL AND DEC. */
2670 /* THUS CUTLO = 2**(-33.5) = 8.23181D-11 */
2671 /* CUTHI, D.P. SAME AS S.P. CUTHI = 1.30438D19 */
2672 /* DATA CUTLO, CUTHI / 8.232D-11, 1.304D19 / */
2673 /* DATA CUTLO, CUTHI / 4.441E-16, 1.304E19 / */
2674 if (*n > 0) {
2675 goto L10;
2676 }
2677 ret_val = zero;
2678 goto L300;
2679L10:
2680 next = 0;
2681 /* next_fmt = fmt_30; */
2682 sum = zero;
2683 nn = *n * *incx;
2684 /* BEGIN MAIN LOOP */
2685 i__ = 1;
2686L20:
2687 switch (next) {
2688 case 0:
2689 goto L30;
2690 case 1:
2691 goto L50;
2692 case 2:
2693 goto L70;
2694 case 3:
2695 goto L110;
2696 }
2697L30:
2698 if ((d__1 = dx[i__], std::abs(d__1)) > cutlo) {
2699 goto L85;
2700 }
2701 next = 1;
2702 /* next_fmt = fmt_50 */;
2703 xmax = zero;
2704/* PHASE 1. SUM IS ZERO */
2705L50:
2706 if (dx[i__] == zero) {
2707 goto L200;
2708 }
2709 if ((d__1 = dx[i__], std::abs(d__1)) > cutlo) {
2710 goto L85;
2711 }
2712 /* PREPARE FOR PHASE 2. */
2713 next = 2;
2714 /* next_fmt = fmt_70; */
2715 goto L105;
2716/* PREPARE FOR PHASE 4. */
2717L100:
2718 i__ = j;
2719 next = 3;
2720 /* next_fmt = fmt_110; */
2721 sum = sum / dx[i__] / dx[i__];
2722L105:
2723 xmax = (d__1 = dx[i__], std::abs(d__1));
2724 goto L115;
2725/* PHASE 2. SUM IS SMALL. */
2726/* SCALE TO AVOID DESTRUCTIVE UNDERFLOW. */
2727L70:
2728 if ((d__1 = dx[i__], std::abs(d__1)) > cutlo) {
2729 goto L75;
2730 }
2731/* COMMON CODE FOR PHASES 2 AND 4. */
2732/* IN PHASE 4 SUM IS LARGE. SCALE TO AVOID OVERFLOW. */
2733L110:
2734 if ((d__1 = dx[i__], std::abs(d__1)) <= xmax) {
2735 goto L115;
2736 }
2737 /* Computing 2nd power */
2738 d__1 = xmax / dx[i__];
2739 sum = one + sum * (d__1 * d__1);
2740 xmax = (d__1 = dx[i__], std::abs(d__1));
2741 goto L200;
2742L115:
2743 /* Computing 2nd power */
2744 d__1 = dx[i__] / xmax;
2745 sum += d__1 * d__1;
2746 goto L200;
2747/* PREPARE FOR PHASE 3. */
2748L75:
2749 sum = sum * xmax * xmax;
2750/* FOR REAL OR D.P. SET HITEST = CUTHI/N */
2751/* FOR COMPLEX SET HITEST = CUTHI/(2*N) */
2752L85:
2753 hitest = cuthi / static_cast<float>(*n);
2754 /* PHASE 3. SUM IS MID-RANGE. NO SCALING. */
2755 i__1 = nn;
2756 i__2 = *incx;
2757 for (j = i__; i__2 < 0 ? j >= i__1 : j <= i__1; j += i__2) {
2758 if ((d__1 = dx[j], std::abs(d__1)) >= hitest) {
2759 goto L100;
2760 }
2761 /* L95: */
2762 /* Computing 2nd power */
2763 d__1 = dx[j];
2764 sum += d__1 * d__1;
2765 }
2766 ret_val = sqrt(sum);
2767 goto L300;
2768L200:
2769 i__ += *incx;
2770 if (i__ <= nn) {
2771 goto L20;
2772 }
2773 /* END OF MAIN LOOP. */
2774 /* COMPUTE SQUARE ROOT AND ADJUST FOR SCALING. */
2775 ret_val = xmax * sqrt(sum);
2776L300:
2777 return ret_val;
2778} /* dnrm2___ */
2779
2780int dsrot_(const int *n, double *dx, const int *incx, double *dy, const int *incy, const double *c__, const double *s) {
2781 /* System generated locals */
2782 int i__1;
2783
2784 /* Local variables */
2785 static int i__, ix, iy;
2786 static double dtemp;
2787
2788 /* APPLIES A PLANE ROTATION. */
2789 /* JACK DONGARRA, LINPACK, 3/11/78. */
2790 /* Parameter adjustments */
2791 --dy;
2792 --dx;
2793
2794 /* Function Body */
2795 if (*n <= 0) {
2796 return 0;
2797 }
2798 if (*incx == 1 && *incy == 1) {
2799 goto L20;
2800 }
2801 /* CODE FOR UNEQUAL INCREMENTS OR EQUAL INCREMENTS NOT EQUAL */
2802 /* TO 1 */
2803 ix = 1;
2804 iy = 1;
2805 if (*incx < 0) {
2806 ix = (-(*n) + 1) * *incx + 1;
2807 }
2808 if (*incy < 0) {
2809 iy = (-(*n) + 1) * *incy + 1;
2810 }
2811 i__1 = *n;
2812 for (i__ = 1; i__ <= i__1; ++i__) {
2813 dtemp = *c__ * dx[ix] + *s * dy[iy];
2814 dy[iy] = *c__ * dy[iy] - *s * dx[ix];
2815 dx[ix] = dtemp;
2816 ix += *incx;
2817 iy += *incy;
2818 /* L10: */
2819 }
2820 return 0;
2821/* CODE FOR BOTH INCREMENTS EQUAL TO 1 */
2822L20:
2823 i__1 = *n;
2824 for (i__ = 1; i__ <= i__1; ++i__) {
2825 dtemp = *c__ * dx[i__] + *s * dy[i__];
2826 dy[i__] = *c__ * dy[i__] - *s * dx[i__];
2827 dx[i__] = dtemp;
2828 /* L30: */
2829 }
2830 return 0;
2831} /* dsrot_ */
2832
2833int dsrotg_(double *da, double *db, double *c__, double *s) {
2834 /* Initialized data */
2835
2836 static double one = 1.;
2837 static double zero = 0.;
2838
2839 /* System generated locals */
2840 double d__1, d__2;
2841
2842 /* Local variables */
2843 static double r__, z__, roe, scale;
2844
2845 /* CONSTRUCT GIVENS PLANE ROTATION. */
2846 /* JACK DONGARRA, LINPACK, 3/11/78. */
2847 /* MODIFIED 9/27/86. */
2848 roe = *db;
2849 if (std::abs(*da) > std::abs(*db)) {
2850 roe = *da;
2851 }
2852 scale = std::abs(*da) + std::abs(*db);
2853 if (scale != zero) {
2854 goto L10;
2855 }
2856 *c__ = one;
2857 *s = zero;
2858 r__ = zero;
2859 goto L20;
2860L10:
2861 /* Computing 2nd power */
2862 d__1 = *da / scale;
2863 /* Computing 2nd power */
2864 d__2 = *db / scale;
2865 r__ = scale * sqrt(d__1 * d__1 + d__2 * d__2);
2866 r__ = d_sign(&one, &roe) * r__;
2867 *c__ = *da / r__;
2868 *s = *db / r__;
2869L20:
2870 z__ = *s;
2871 if (std::abs(*c__) > zero && std::abs(*c__) <= *s) {
2872 z__ = one / *c__;
2873 }
2874 *da = r__;
2875 *db = z__;
2876 return 0;
2877} /* dsrotg_ */
2878
2879int dscal_sl__(const int *n, const double *da, double *dx, const int *incx) {
2880 /* System generated locals */
2881 int i__1, i__2;
2882
2883 /* Local variables */
2884 static int i__, m, mp1, nincx;
2885
2886 /* SCALES A VECTOR BY A CONSTANT. */
2887 /* USES UNROLLED LOOPS FOR INCREMENT EQUAL TO ONE. */
2888 /* JACK DONGARRA, LINPACK, 3/11/78. */
2889 /* Parameter adjustments */
2890 --dx;
2891
2892 /* Function Body */
2893 if (*n <= 0) {
2894 return 0;
2895 }
2896 if (*incx == 1) {
2897 goto L20;
2898 }
2899 /* CODE FOR INCREMENT NOT EQUAL TO 1 */
2900 nincx = *n * *incx;
2901 i__1 = nincx;
2902 i__2 = *incx;
2903 for (i__ = 1; i__2 < 0 ? i__ >= i__1 : i__ <= i__1; i__ += i__2) {
2904 dx[i__] = *da * dx[i__];
2905 /* L10: */
2906 }
2907 return 0;
2908/* CODE FOR INCREMENT EQUAL TO 1 */
2909/* CLEAN-UP LOOP */
2910L20:
2911 m = *n % 5;
2912 if (m == 0) {
2913 goto L40;
2914 }
2915 i__2 = m;
2916 for (i__ = 1; i__ <= i__2; ++i__) {
2917 dx[i__] = *da * dx[i__];
2918 /* L30: */
2919 }
2920 if (*n < 5) {
2921 return 0;
2922 }
2923L40:
2924 mp1 = m + 1;
2925 i__2 = *n;
2926 for (i__ = mp1; i__ <= i__2; i__ += 5) {
2927 dx[i__] = *da * dx[i__];
2928 dx[i__ + 1] = *da * dx[i__ + 1];
2929 dx[i__ + 2] = *da * dx[i__ + 2];
2930 dx[i__ + 3] = *da * dx[i__ + 3];
2931 dx[i__ + 4] = *da * dx[i__ + 4];
2932 /* L50: */
2933 }
2934 return 0;
2935} /* dscal_sl__ */
2936
2938
2939} // namespace
2940
2941} // namespace Mantid::Kernel::Math
gsl_vector * tmp
static std::unique_ptr< QThreadPool > tp
double value
The value of the point.
Definition FitMW.cpp:51
double sigma
Definition GetAllEi.cpp:156
std::map< DeltaEMode::Type, std::string > index
void initializeConstraints(const DblMatrix &equality, const DblMatrix &inequality)
Create constraint array.
std::vector< double > minimize(const std::vector< double > &x0) const
Perform the minimization.
const size_t m_nparams
Number of parameters under minimization.
void evaluateConstraints(std::vector< double > &constrValues, const std::vector< double > &x) const
Compute values of constraints.
void fprime(std::vector< double > &grad, const std::vector< double > &x) const
Compute derivative numerically.
double fvalue(const std::vector< double > &x) const
Compute the value of the objective function.
std::vector< double > m_constraintNorms
Holder for constraint normals.
size_t numRows() const
Return the number of rows in the matrix.
Definition Matrix.h:144
size_t numCols() const
Return the number of columns in the matrix.
Definition Matrix.h:147