sbols.f 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837
  1. *DECK SBOLS
  2. SUBROUTINE SBOLS (W, MDW, MROWS, NCOLS, BL, BU, IND, IOPT, X,
  3. + RNORM, MODE, RW, IW)
  4. C***BEGIN PROLOGUE SBOLS
  5. C***PURPOSE Solve the problem
  6. C E*X = F (in the least squares sense)
  7. C with bounds on selected X values.
  8. C***LIBRARY SLATEC
  9. C***CATEGORY K1A2A, G2E, G2H1, G2H2
  10. C***TYPE SINGLE PRECISION (SBOLS-S, DBOLS-D)
  11. C***KEYWORDS BOUNDS, CONSTRAINTS, INEQUALITY, LEAST SQUARES, LINEAR
  12. C***AUTHOR Hanson, R. J., (SNLA)
  13. C***DESCRIPTION
  14. C
  15. C The user must have dimension statements of the form:
  16. C
  17. C DIMENSION W(MDW,NCOLS+1), BL(NCOLS), BU(NCOLS),
  18. C * X(NCOLS+NX), RW(5*NCOLS)
  19. C INTEGER IND(NCOLS), IOPT(1+NI), IW(2*NCOLS)
  20. C
  21. C (here NX=number of extra locations required for option 4; NX=0
  22. C for no options; NX=NCOLS if this option is in use. Here NI=number
  23. C of extra locations required for options 1-6; NI=0 for no
  24. C options.)
  25. C
  26. C INPUT
  27. C -----
  28. C
  29. C --------------------
  30. C W(MDW,*),MROWS,NCOLS
  31. C --------------------
  32. C The array W(*,*) contains the matrix [E:F] on entry. The matrix
  33. C [E:F] has MROWS rows and NCOLS+1 columns. This data is placed in
  34. C the array W(*,*) with E occupying the first NCOLS columns and the
  35. C right side vector F in column NCOLS+1. The row dimension, MDW, of
  36. C the array W(*,*) must satisfy the inequality MDW .ge. MROWS.
  37. C Other values of MDW are errors. The values of MROWS and NCOLS
  38. C must be positive. Other values are errors. There is an exception
  39. C to this when using option 1 for accumulation of blocks of
  40. C equations. In that case MROWS is an OUTPUT variable ONLY, and the
  41. C matrix data for [E:F] is placed in W(*,*), one block of rows at a
  42. C time. MROWS contains the number of rows in the matrix after
  43. C triangularizing several blocks of equations. This is an OUTPUT
  44. C parameter ONLY when option 1 is used. See IOPT(*) CONTENTS
  45. C for details about option 1.
  46. C
  47. C ------------------
  48. C BL(*),BU(*),IND(*)
  49. C ------------------
  50. C These arrays contain the information about the bounds that the
  51. C solution values are to satisfy. The value of IND(J) tells the
  52. C type of bound and BL(J) and BU(J) give the explicit values for
  53. C the respective upper and lower bounds.
  54. C
  55. C 1. For IND(J)=1, require X(J) .ge. BL(J).
  56. C (the value of BU(J) is not used.)
  57. C 2. For IND(J)=2, require X(J) .le. BU(J).
  58. C (the value of BL(J) is not used.)
  59. C 3. For IND(J)=3, require X(J) .ge. BL(J) and
  60. C X(J) .le. BU(J).
  61. C 4. For IND(J)=4, no bounds on X(J) are required.
  62. C (the values of BL(J) and BU(J) are not used.)
  63. C
  64. C Values other than 1,2,3 or 4 for IND(J) are errors. In the case
  65. C IND(J)=3 (upper and lower bounds) the condition BL(J) .gt. BU(J)
  66. C is an error.
  67. C
  68. C -------
  69. C IOPT(*)
  70. C -------
  71. C This is the array where the user can specify nonstandard options
  72. C for SBOLSM( ). Most of the time this feature can be ignored by
  73. C setting the input value IOPT(1)=99. Occasionally users may have
  74. C needs that require use of the following subprogram options. For
  75. C details about how to use the options see below: IOPT(*) CONTENTS.
  76. C
  77. C Option Number Brief Statement of Purpose
  78. C ------ ------ ----- --------- -- -------
  79. C 1 Return to user for accumulation of blocks
  80. C of least squares equations.
  81. C 2 Check lengths of all arrays used in the
  82. C subprogram.
  83. C 3 Standard scaling of the data matrix, E.
  84. C 4 User provides column scaling for matrix E.
  85. C 5 Provide option array to the low-level
  86. C subprogram SBOLSM( ).
  87. C 6 Move the IOPT(*) processing pointer.
  88. C 99 No more options to change.
  89. C
  90. C ----
  91. C X(*)
  92. C ----
  93. C This array is used to pass data associated with option 4. Ignore
  94. C this parameter if this option is not used. Otherwise see below:
  95. C IOPT(*) CONTENTS.
  96. C
  97. C OUTPUT
  98. C ------
  99. C
  100. C ----------
  101. C X(*),RNORM
  102. C ----------
  103. C The array X(*) contains a solution (if MODE .ge.0 or .eq.-22) for
  104. C the constrained least squares problem. The value RNORM is the
  105. C minimum residual vector length.
  106. C
  107. C ----
  108. C MODE
  109. C ----
  110. C The sign of MODE determines whether the subprogram has completed
  111. C normally, or encountered an error condition or abnormal status. A
  112. C value of MODE .ge. 0 signifies that the subprogram has completed
  113. C normally. The value of MODE (.GE. 0) is the number of variables
  114. C in an active status: not at a bound nor at the value ZERO, for
  115. C the case of free variables. A negative value of MODE will be one
  116. C of the cases -37,-36,...,-22, or -17,...,-2. Values .lt. -1
  117. C correspond to an abnormal completion of the subprogram. To
  118. C understand the abnormal completion codes see below: ERROR
  119. C MESSAGES for SBOLS( ). AN approximate solution will be returned
  120. C to the user only when max. iterations is reached, MODE=-22.
  121. C Values for MODE=-37,...,-22 come from the low-level subprogram
  122. C SBOLSM(). See the section ERROR MESSAGES for SBOLSM() in the
  123. C documentation for SBOLSM().
  124. C
  125. C -----------
  126. C RW(*),IW(*)
  127. C -----------
  128. C These are working arrays with 5*NCOLS and 2*NCOLS entries.
  129. C (normally the user can ignore the contents of these arrays,
  130. C but they must be dimensioned properly.)
  131. C
  132. C IOPT(*) CONTENTS
  133. C ------- --------
  134. C The option array allows a user to modify internal variables in
  135. C the subprogram without recompiling the source code. A central
  136. C goal of the initial software design was to do a good job for most
  137. C people. Thus the use of options will be restricted to a select
  138. C group of users. The processing of the option array proceeds as
  139. C follows: a pointer, here called LP, is initially set to the value
  140. C 1. This value is updated as each option is processed. At the
  141. C pointer position the option number is extracted and used for
  142. C locating other information that allows for options to be changed.
  143. C The portion of the array IOPT(*) that is used for each option is
  144. C fixed; the user and the subprogram both know how many locations
  145. C are needed for each option. A great deal of error checking is
  146. C done by the subprogram on the contents of the option array.
  147. C Nevertheless it is still possible to give the subprogram optional
  148. C input that is meaningless. For example option 4 uses the
  149. C locations X(NCOLS+IOFF),...,X(NCOLS+IOFF+NCOLS-1) for passing
  150. C scaling data. The user must manage the allocation of these
  151. C locations.
  152. C
  153. C 1
  154. C -
  155. C This option allows the user to solve problems with a large number
  156. C of rows compared to the number of variables. The idea is that the
  157. C subprogram returns to the user (perhaps many times) and receives
  158. C new least squares equations from the calling program unit.
  159. C Eventually the user signals "that's all" and then computes the
  160. C solution with one final call to subprogram SBOLS( ). The value of
  161. C MROWS is an OUTPUT variable when this option is used. Its value
  162. C is always in the range 0 .le. MROWS .le. NCOLS+1. It is equal to
  163. C the number of rows after the triangularization of the entire set
  164. C of equations. If LP is the processing pointer for IOPT(*), the
  165. C usage for the sequential processing of blocks of equations is
  166. C
  167. C IOPT(LP)=1
  168. C Move block of equations to W(*,*) starting at
  169. C the first row of W(*,*).
  170. C IOPT(LP+3)=# of rows in the block; user defined
  171. C
  172. C The user now calls SBOLS( ) in a loop. The value of IOPT(LP+1)
  173. C directs the user's action. The value of IOPT(LP+2) points to
  174. C where the subsequent rows are to be placed in W(*,*).
  175. C
  176. C .<LOOP
  177. C . CALL SBOLS()
  178. C . IF(IOPT(LP+1) .EQ. 1) THEN
  179. C . IOPT(LP+3)=# OF ROWS IN THE NEW BLOCK; USER DEFINED
  180. C . PLACE NEW BLOCK OF IOPT(LP+3) ROWS IN
  181. C . W(*,*) STARTING AT ROW IOPT(LP+2).
  182. C .
  183. C . IF( THIS IS THE LAST BLOCK OF EQUATIONS ) THEN
  184. C . IOPT(LP+1)=2
  185. C .<------CYCLE LOOP
  186. C . ELSE IF (IOPT(LP+1) .EQ. 2) THEN
  187. C <-------EXIT LOOP SOLUTION COMPUTED IF MODE .GE. 0
  188. C . ELSE
  189. C . ERROR CONDITION; SHOULD NOT HAPPEN.
  190. C .<END LOOP
  191. C
  192. C Use of this option adds 4 to the required length of IOPT(*).
  193. C
  194. C
  195. C 2
  196. C -
  197. C This option is useful for checking the lengths of all arrays used
  198. C by SBOLS() against their actual requirements for this problem.
  199. C The idea is simple: the user's program unit passes the declared
  200. C dimension information of the arrays. These values are compared
  201. C against the problem-dependent needs within the subprogram. If any
  202. C of the dimensions are too small an error message is printed and a
  203. C negative value of MODE is returned, -11 to -17. The printed error
  204. C message tells how long the dimension should be. If LP is the
  205. C processing pointer for IOPT(*),
  206. C
  207. C IOPT(LP)=2
  208. C IOPT(LP+1)=Row dimension of W(*,*)
  209. C IOPT(LP+2)=Col. dimension of W(*,*)
  210. C IOPT(LP+3)=Dimensions of BL(*),BU(*),IND(*)
  211. C IOPT(LP+4)=Dimension of X(*)
  212. C IOPT(LP+5)=Dimension of RW(*)
  213. C IOPT(LP+6)=Dimension of IW(*)
  214. C IOPT(LP+7)=Dimension of IOPT(*)
  215. C .
  216. C CALL SBOLS()
  217. C
  218. C Use of this option adds 8 to the required length of IOPT(*).
  219. C
  220. C 3
  221. C -
  222. C This option changes the type of scaling for the data matrix E.
  223. C Nominally each nonzero column of E is scaled so that the
  224. C magnitude of its largest entry is equal to the value ONE. If LP
  225. C is the processing pointer for IOPT(*),
  226. C
  227. C IOPT(LP)=3
  228. C IOPT(LP+1)=1,2 or 3
  229. C 1= Nominal scaling as noted;
  230. C 2= Each nonzero column scaled to have length ONE;
  231. C 3= Identity scaling; scaling effectively suppressed.
  232. C .
  233. C CALL SBOLS()
  234. C
  235. C Use of this option adds 2 to the required length of IOPT(*).
  236. C
  237. C 4
  238. C -
  239. C This option allows the user to provide arbitrary (positive)
  240. C column scaling for the matrix E. If LP is the processing pointer
  241. C for IOPT(*),
  242. C
  243. C IOPT(LP)=4
  244. C IOPT(LP+1)=IOFF
  245. C X(NCOLS+IOFF),...,X(NCOLS+IOFF+NCOLS-1)
  246. C = Positive scale factors for cols. of E.
  247. C .
  248. C CALL SBOLS()
  249. C
  250. C Use of this option adds 2 to the required length of IOPT(*) and
  251. C NCOLS to the required length of X(*).
  252. C
  253. C 5
  254. C -
  255. C This option allows the user to provide an option array to the
  256. C low-level subprogram SBOLSM(). If LP is the processing pointer
  257. C for IOPT(*),
  258. C
  259. C IOPT(LP)=5
  260. C IOPT(LP+1)= Position in IOPT(*) where option array
  261. C data for SBOLSM() begins.
  262. C .
  263. C CALL SBOLS()
  264. C
  265. C Use of this option adds 2 to the required length of IOPT(*).
  266. C
  267. C 6
  268. C -
  269. C Move the processing pointer (either forward or backward) to the
  270. C location IOPT(LP+1). The processing point is moved to entry
  271. C LP+2 of IOPT(*) if the option is left with -6 in IOPT(LP). For
  272. C example to skip over locations 3,...,NCOLS+2 of IOPT(*),
  273. C
  274. C IOPT(1)=6
  275. C IOPT(2)=NCOLS+3
  276. C (IOPT(I), I=3,...,NCOLS+2 are not defined here.)
  277. C IOPT(NCOLS+3)=99
  278. C CALL SBOLS()
  279. C
  280. C CAUTION: Misuse of this option can yield some very hard
  281. C -to-find bugs. Use it with care.
  282. C
  283. C 99
  284. C --
  285. C There are no more options to change.
  286. C
  287. C Only option numbers -99, -6,-5,...,-1, 1,2,...,6, and 99 are
  288. C permitted. Other values are errors. Options -99,-1,...,-6 mean
  289. C that the respective options 99,1,...,6 are left at their default
  290. C values. An example is the option to modify the (rank) tolerance:
  291. C
  292. C IOPT(1)=-3 Option is recognized but not changed
  293. C IOPT(2)=2 Scale nonzero cols. to have length ONE
  294. C IOPT(3)=99
  295. C
  296. C ERROR MESSAGES for SBOLS()
  297. C ----- -------- --- -------
  298. C
  299. C WARNING IN...
  300. C SBOLS(). MDW=(I1) MUST BE POSITIVE.
  301. C IN ABOVE MESSAGE, I1= 0
  302. C ERROR NUMBER = 2
  303. C (NORMALLY A RETURN TO THE USER TAKES PLACE FOLLOWING THIS MESSAGE.)
  304. C
  305. C WARNING IN...
  306. C SBOLS(). NCOLS=(I1) THE NO. OF VARIABLES MUST BE POSITIVE.
  307. C IN ABOVE MESSAGE, I1= 0
  308. C ERROR NUMBER = 3
  309. C (NORMALLY A RETURN TO THE USER TAKES PLACE FOLLOWING THIS MESSAGE.)
  310. C
  311. C WARNING IN...
  312. C SBOLS(). FOR J=(I1), IND(J)=(I2) MUST BE 1-4.
  313. C IN ABOVE MESSAGE, I1= 1
  314. C IN ABOVE MESSAGE, I2= 0
  315. C ERROR NUMBER = 4
  316. C (NORMALLY A RETURN TO THE USER TAKES PLACE FOLLOWING THIS MESSAGE.)
  317. C
  318. C WARNING IN...
  319. C SBOLS(). FOR J=(I1), BOUND BL(J)=(R1) IS .GT. BU(J)=(R2).
  320. C IN ABOVE MESSAGE, I1= 1
  321. C IN ABOVE MESSAGE, R1= 0.
  322. C IN ABOVE MESSAGE, R2= ABOVE MESSAGE, I1= 0
  323. C ERROR NUMBER = 6
  324. C (NORMALLY A RETURN TO THE USER TAKES PLACE FOLLOWING THIS MESSAGE.)
  325. C
  326. C WARNING IN...
  327. C SBOLS(). ISCALE OPTION=(I1) MUST BE 1-3.
  328. C IN ABOVE MESSAGE, I1= 0
  329. C ERROR NUMBER = 7
  330. C (NORMALLY A RETURN TO THE USER TAKES PLACE FOLLOWING THIS MESSAGE.)
  331. C
  332. C WARNING IN...
  333. C SBOLS(). OFFSET PAST X(NCOLS) (I1) FOR USER-PROVIDED COLUMN SCALING
  334. C MUST BE POSITIVE.
  335. C IN ABOVE MESSAGE, I1= 0
  336. C ERROR NUMBER = 8
  337. C (NORMALLY A RETURN TO THE USER TAKES PLACE FOLLOWING THIS MESSAGE.)
  338. C
  339. C WARNING IN...
  340. C SBOLS(). EACH PROVIDED COL. SCALE FACTOR MUST BE POSITIVE.
  341. C COMPONENT (I1) NOW = (R1).
  342. C IN ABOVE MESSAGE, I1= ND. .LE. MDW=(I2).
  343. C IN ABOVE MESSAGE, I1= 1
  344. C IN ABOVE MESSAGE, I2= 0
  345. C ERROR NUMBER = 10
  346. C (NORMALLY A RETURN TO THE USER TAKES PLACE FOLLOWING THIS MESSAGE.)
  347. C
  348. C WARNING IN...
  349. C SBOLS().THE ROW DIMENSION OF W(,)=(I1) MUST BE .GE.THE NUMBER OF ROWS=
  350. C (I2).
  351. C IN ABOVE MESSAGE, I1= 0
  352. C IN ABOVE MESSAGE, I2= 1
  353. C ERROR NUMBER = 11
  354. C (NORMALLY A RETURN TO THE USER TAKES PLACE FOLLOWING THIS MESSAGE.)
  355. C
  356. C WARNING IN...
  357. C SBOLS(). THE COLUMN DIMENSION OF W(,)=(I1) MUST BE .GE. NCOLS+1=(I2).
  358. C IN ABOVE MESSAGE, I1= 0
  359. C IN ABOVE MESSAGE, I2= 2
  360. C ERROR NUMBER = 12
  361. C (NORMALLY A RETURN TO THE USER TAKES PLACE FOLLOWING THIS MESSAGE.)
  362. C
  363. C WARNING IN...
  364. C SBOLS().THE DIMENSIONS OF THE ARRAYS BL(),BU(), AND IND()=(I1) MUST BE
  365. C .GE. NCOLS=(I2).
  366. C IN ABOVE MESSAGE, I1= 0
  367. C IN ABOVE MESSAGE, I2= 1
  368. C ERROR NUMBER = 13
  369. C (NORMALLY A RETURN TO THE USER TAKES PLACE FOLLOWING THIS MESSAGE.)
  370. C
  371. C WARNING IN...
  372. C SBOLS(). THE DIMENSION OF X()=(I1) MUST BE .GE. THE REQD. LENGTH=(I2).
  373. C IN ABOVE MESSAGE, I1= 0
  374. C IN ABOVE MESSAGE, I2= 2
  375. C ERROR NUMBER = 14
  376. C (NORMALLY A RETURN TO THE USER TAKES PLACE FOLLOWING THIS MESSAGE.)
  377. C
  378. C WARNING IN...
  379. C SBOLS(). THE DIMENSION OF RW()=(I1) MUST BE .GE. 5*NCOLS=(I2).
  380. C IN ABOVE MESSAGE, I1= 0
  381. C IN ABOVE MESSAGE, I2= 3
  382. C ERROR NUMBER = 15
  383. C (NORMALLY A RETURN TO THE USER TAKES PLACE FOLLOWING THIS MESSAGE.)
  384. C
  385. C WARNING IN...
  386. C SBOLS() THE DIMENSION OF IW()=(I1) MUST BE .GE. 2*NCOLS=(I2).
  387. C IN ABOVE MESSAGE, I1= 0
  388. C IN ABOVE MESSAGE, I2= 2
  389. C ERROR NUMBER = 16
  390. C (NORMALLY A RETURN TO THE USER TAKES PLACE FOLLOWING THIS MESSAGE.)
  391. C
  392. C WARNING IN...
  393. C SBOLS() THE DIMENSION OF IOPT()=(I1) MUST BE .GE. THE REQD. LEN.=(I2).
  394. C IN ABOVE MESSAGE, I1= 0
  395. C IN ABOVE MESSAGE, I2= 1
  396. C ERROR NUMBER = 17
  397. C (NORMALLY A RETURN TO THE USER TAKES PLACE FOLLOWING THIS MESSAGE.)
  398. C
  399. C***REFERENCES R. J. Hanson, Linear least squares with bounds and
  400. C linear constraints, Report SAND82-1517, Sandia
  401. C Laboratories, August 1982.
  402. C***ROUTINES CALLED ISAMAX, SBOLSM, SCOPY, SNRM2, SROT, SROTG, XERMSG
  403. C***REVISION HISTORY (YYMMDD)
  404. C 821220 DATE WRITTEN
  405. C 861211 REVISION DATE from Version 3.2
  406. C 891214 Prologue converted to Version 4.0 format. (BAB)
  407. C 900510 Convert XERRWV calls to XERMSG calls. (RWC)
  408. C 920501 Reformatted the REFERENCES section. (WRB)
  409. C***END PROLOGUE SBOLS
  410. C
  411. C SOLVE LINEAR LEAST SQUARES SYSTEM WITH BOUNDS ON
  412. C SELECTED VARIABLES.
  413. C REVISED 850329-1400
  414. C REVISED YYMMDD-HHMM
  415. C TO CHANGE THIS SUBPROGRAM FROM SINGLE TO DOUBLE PRECISION BEGIN
  416. C EDITING AT THE CARD 'C++'.
  417. C CHANGE THIS SUBPROGRAM NAME TO DBOLS AND THE STRINGS
  418. C /SCOPY/ TO /DCOPY/, /SBOL/ TO /DBOL/,
  419. C /SNRM2/ TO /DNRM2/, /ISAMAX/ TO /IDAMAX/,
  420. C /SROTG/ TO /DROTG/, /SROT/ TO /DROT/, /E0/ TO /D0/,
  421. C /REAL / TO /DOUBLE PRECISION/.
  422. C ++
  423. REAL W(MDW,*),BL(*),BU(*),X(*),RW(*)
  424. REAL SC, SS, ONE, SNRM2, RNORM, ZERO
  425. C
  426. C THIS VARIABLE SHOULD REMAIN TYPE REAL.
  427. INTEGER IND(*),IOPT(*),IW(*)
  428. LOGICAL CHECKL
  429. CHARACTER*8 XERN1, XERN2
  430. CHARACTER*16 XERN3, XERN4
  431. SAVE IGO,LOCACC,LOPT,ISCALE
  432. DATA IGO/0/
  433. C***FIRST EXECUTABLE STATEMENT SBOLS
  434. NERR = 0
  435. MODE = 0
  436. IF (IGO.EQ.0) THEN
  437. C DO(CHECK VALIDITY OF INPUT DATA)
  438. C PROCEDURE(CHECK VALIDITY OF INPUT DATA)
  439. C
  440. C SEE THAT MDW IS .GT.0. GROSS CHECK ONLY.
  441. IF (MDW.LE.0) THEN
  442. WRITE (XERN1, '(I8)') MDW
  443. CALL XERMSG ('SLATEC', 'SBOLS', 'MDW = ' // XERN1 //
  444. * ' MUST BE POSITIVE.', 2, 1)
  445. C DO(RETURN TO USER PROGRAM UNIT)
  446. GO TO 190
  447. ENDIF
  448. C
  449. C SEE THAT NUMBER OF UNKNOWNS IS POSITIVE.
  450. IF (NCOLS.LE.0) THEN
  451. WRITE (XERN1, '(I8)') NCOLS
  452. CALL XERMSG ('SLATEC', 'SBOLS', 'NCOLS = ' // XERN1 //
  453. * ' THE NO. OF VARIABLES MUST BE POSITIVE.', 3, 1)
  454. C DO(RETURN TO USER PROGRAM UNIT)
  455. GO TO 190
  456. ENDIF
  457. C
  458. C SEE THAT CONSTRAINT INDICATORS ARE ALL WELL-DEFINED.
  459. DO 10 J = 1,NCOLS
  460. IF (IND(J).LT.1 .OR. IND(J).GT.4) THEN
  461. WRITE (XERN1, '(I8)') J
  462. WRITE (XERN2, '(I8)') IND(J)
  463. CALL XERMSG ('SLATEC', 'SBOLS',
  464. * 'IND(' // XERN1 // ') = ' // XERN2 //
  465. * ' MUST BE 1-4.', 4, 1)
  466. C DO(RETURN TO USER PROGRAM UNIT)
  467. GO TO 190
  468. ENDIF
  469. 10 CONTINUE
  470. C
  471. C SEE THAT BOUNDS ARE CONSISTENT.
  472. DO 20 J = 1,NCOLS
  473. IF (IND(J).EQ.3) THEN
  474. IF (BL(J).GT.BU(J)) THEN
  475. WRITE (XERN1, '(I8)') J
  476. WRITE (XERN3, '(1PE15.6)') BL(J)
  477. WRITE (XERN4, '(1PE15.6)') BU(J)
  478. CALL XERMSG ('SLATEC', 'SBOLS',
  479. * 'BOUND BL(' // XERN1 // ') = ' // XERN3 //
  480. * ' IS .GT. BU(' // XERN1 // ') = ' // XERN4,
  481. * 5, 1)
  482. C DO(RETURN TO USER PROGRAM UNIT)
  483. GO TO 190
  484. ENDIF
  485. ENDIF
  486. 20 CONTINUE
  487. C END PROCEDURE
  488. C DO(PROCESS OPTION ARRAY)
  489. C PROCEDURE(PROCESS OPTION ARRAY)
  490. ZERO = 0.E0
  491. ONE = 1.E0
  492. CHECKL = .FALSE.
  493. LENX = NCOLS
  494. ISCALE = 1
  495. IGO = 2
  496. LOPT = 0
  497. LP = 0
  498. LDS = 0
  499. 30 CONTINUE
  500. LP = LP + LDS
  501. IP = IOPT(LP+1)
  502. JP = ABS(IP)
  503. C
  504. C TEST FOR NO MORE OPTIONS.
  505. IF (IP.EQ.99) THEN
  506. IF (LOPT.EQ.0) LOPT = LP + 1
  507. GO TO 50
  508. ELSE IF (JP.EQ.99) THEN
  509. LDS = 1
  510. GO TO 30
  511. ELSE IF (JP.EQ.1) THEN
  512. IF (IP.GT.0) THEN
  513. C
  514. C SET UP DIRECTION FLAG, ROW STACKING POINTER
  515. C LOCATION, AND LOCATION FOR NUMBER OF NEW ROWS.
  516. LOCACC = LP + 2
  517. C
  518. C IOPT(LOCACC-1)=OPTION NUMBER FOR SEQ. ACCUMULATION.
  519. C CONTENTS.. IOPT(LOCACC )=USER DIRECTION FLAG, 1 OR 2.
  520. C IOPT(LOCACC+1)=ROW STACKING POINTER.
  521. C IOPT(LOCACC+2)=NUMBER OF NEW ROWS TO PROCESS.
  522. C USER ACTION WITH THIS OPTION..
  523. C (SET UP OPTION DATA FOR SEQ. ACCUMULATION IN IOPT(*).
  524. C MUST ALSO START PROCESS WITH IOPT(LOCACC)=1.)
  525. C (MOVE BLOCK OF EQUATIONS INTO W(*,*) STARTING AT FIRST
  526. C ROW OF W(*,*). SET IOPT(LOCACC+2)=NO. OF ROWS IN BLOCK.)
  527. C LOOP
  528. C CALL SBOLS()
  529. C
  530. C IF(IOPT(LOCACC) .EQ. 1) THEN
  531. C STACK EQUAS., STARTING AT ROW IOPT(LOCACC+1),
  532. C INTO W(*,*).
  533. C SET IOPT(LOCACC+2)=NO. OF EQUAS.
  534. C IF LAST BLOCK OF EQUAS., SET IOPT(LOCACC)=2.
  535. C ELSE IF IOPT(LOCACC) .EQ. 2) THEN
  536. C (PROCESS IS OVER. EXIT LOOP.)
  537. C ELSE
  538. C (ERROR CONDITION. SHOULD NOT HAPPEN.)
  539. C END IF
  540. C END LOOP
  541. C SET IOPT(LOCACC-1)=-OPTION NUMBER FOR SEQ. ACCUMULATION.
  542. C CALL SBOLS( )
  543. IOPT(LOCACC+1) = 1
  544. IGO = 1
  545. ENDIF
  546. LDS = 4
  547. GO TO 30
  548. ELSE IF (JP.EQ.2) THEN
  549. IF (IP.GT.0) THEN
  550. C
  551. C GET ACTUAL LENGTHS OF ARRAYS FOR CHECKING AGAINST NEEDS.
  552. LOCDIM = LP + 2
  553. C
  554. C LMDW.GE.MROWS
  555. C LNDW.GE.NCOLS+1
  556. C LLB .GE.NCOLS
  557. C LLX .GE.NCOLS+EXTRA REQD. IN OPTIONS.
  558. C LLRW.GE.5*NCOLS
  559. C LLIW.GE.2*NCOLS
  560. C LIOP.GE. AMOUNT REQD. FOR IOPTION ARRAY.
  561. LMDW = IOPT(LOCDIM)
  562. LNDW = IOPT(LOCDIM+1)
  563. LLB = IOPT(LOCDIM+2)
  564. LLX = IOPT(LOCDIM+3)
  565. LLRW = IOPT(LOCDIM+4)
  566. LLIW = IOPT(LOCDIM+5)
  567. LIOPT = IOPT(LOCDIM+6)
  568. CHECKL = .TRUE.
  569. ENDIF
  570. LDS = 8
  571. GO TO 30
  572. C
  573. C OPTION TO MODIFY THE COLUMN SCALING.
  574. ELSE IF (JP.EQ.3) THEN
  575. IF (IP.GT.0) THEN
  576. ISCALE = IOPT(LP+2)
  577. C
  578. C SEE THAT ISCALE IS 1 THRU 3.
  579. IF (ISCALE.LT.1 .OR. ISCALE.GT.3) THEN
  580. WRITE (XERN1, '(I8)') ISCALE
  581. CALL XERMSG ('SLATEC', 'SBOLS', 'ISCALE OPTION = '
  582. * // XERN1 // ' MUST BE 1-3', 7, 1)
  583. C DO(RETURN TO USER PROGRAM UNIT)
  584. GO TO 190
  585. ENDIF
  586. ENDIF
  587. LDS = 2
  588. C CYCLE FOREVER
  589. GO TO 30
  590. C
  591. C IN THIS OPTION THE USER HAS PROVIDED SCALING. THE
  592. C SCALE FACTORS FOR THE COLUMNS BEGIN IN X(NCOLS+IOPT(LP+2)).
  593. ELSE IF (JP.EQ.4) THEN
  594. IF (IP.GT.0) THEN
  595. ISCALE = 4
  596. IF (IOPT(LP+2).LE.0) THEN
  597. WRITE (XERN1, '(I8)') IOPT(LP+2)
  598. CALL XERMSG ('SLATEC', 'SBOLS',
  599. * 'OFFSET PAST X(NCOLS) (' // XERN1 //
  600. * ') FOR USER-PROVIDED COLUMN SCALING MUST BE POSITIVE.',
  601. * 8, 1)
  602. C DO(RETURN TO USER PROGRAM UNIT)
  603. GO TO 190
  604. ENDIF
  605. CALL SCOPY(NCOLS,X(NCOLS+IOPT(LP+2)),1,RW,1)
  606. LENX = LENX + NCOLS
  607. DO 40 J = 1,NCOLS
  608. IF (RW(J).LE.ZERO) THEN
  609. WRITE (XERN1, '(I8)') J
  610. WRITE (XERN3, '(1PE15.6)') RW(J)
  611. CALL XERMSG ('SLATEC', 'SBOLS',
  612. * 'EACH PROVIDED COLUMN SCALE FACTOR ' //
  613. * 'MUST BE POSITIVE.$$COMPONENT ' // XERN1 //
  614. * ' NOW = ' // XERN3, 9, 1)
  615. C DO(RETURN TO USER PROGRAM UNIT)
  616. GO TO 190
  617. ENDIF
  618. 40 CONTINUE
  619. ENDIF
  620. LDS = 2
  621. C CYCLE FOREVER
  622. GO TO 30
  623. C
  624. C IN THIS OPTION AN OPTION ARRAY IS PROVIDED TO SBOLSM().
  625. ELSE IF (JP.EQ.5) THEN
  626. IF (IP.GT.0) THEN
  627. LOPT = IOPT(LP+2)
  628. ENDIF
  629. LDS = 2
  630. C CYCLE FOREVER
  631. GO TO 30
  632. C
  633. C THIS OPTION USES THE NEXT LOC OF IOPT(*) AS AN
  634. C INCREMENT TO SKIP.
  635. ELSE IF (JP.EQ.6) THEN
  636. IF (IP.GT.0) THEN
  637. LP = IOPT(LP+2) - 1
  638. LDS = 0
  639. ELSE
  640. LDS = 2
  641. ENDIF
  642. C CYCLE FOREVER
  643. GO TO 30
  644. C
  645. C NO VALID OPTION NUMBER WAS NOTED. THIS IS AN ERROR CONDITION.
  646. ELSE
  647. WRITE (XERN1, '(I8)') JP
  648. CALL XERMSG ('SLATEC', 'SBOLS', 'THE OPTION NUMBER = ' //
  649. * XERN1 // ' IS NOT DEFINED.', 6, 1)
  650. C DO(RETURN TO USER PROGRAM UNIT)
  651. GO TO 190
  652. ENDIF
  653. 50 CONTINUE
  654. C END PROCEDURE
  655. IF (CHECKL) THEN
  656. C DO(CHECK LENGTHS OF ARRAYS)
  657. C PROCEDURE(CHECK LENGTHS OF ARRAYS)
  658. C
  659. C THIS FEATURE ALLOWS THE USER TO MAKE SURE THAT THE
  660. C ARRAYS ARE LONG ENOUGH FOR THE INTENDED PROBLEM SIZE AND USE.
  661. IF (LMDW.LT.MROWS) THEN
  662. WRITE (XERN1, '(I8)') LMDW
  663. WRITE (XERN2, '(I8)') MROWS
  664. CALL XERMSG ('SLATEC', 'SBOLS',
  665. * 'THE ROW DIMENSION OF W(,) = ' // XERN1 //
  666. * ' MUST BE .GE. THE NUMBER OF ROWS = ' // XERN2,
  667. * 11, 1)
  668. GO TO 190
  669. ENDIF
  670. IF (LNDW.LT.NCOLS+1) THEN
  671. WRITE (XERN1, '(I8)') LNDW
  672. WRITE (XERN2, '(I8)') NCOLS+1
  673. CALL XERMSG ('SLATEC', 'SBOLS',
  674. * 'THE COLUMN DIMENSION OF W(,) = ' // XERN1 //
  675. * ' MUST BE .GE. NCOLS+1 = ' // XERN2, 12, 1)
  676. C DO(RETURN TO USER PROGRAM UNIT)
  677. GO TO 190
  678. ENDIF
  679. IF (LLB.LT.NCOLS) THEN
  680. WRITE (XERN1, '(I8)') LLB
  681. WRITE (XERN2, '(I8)') NCOLS
  682. CALL XERMSG ('SLATEC', 'SBOLS',
  683. * 'THE DIMENSIONS OF THE ARRAYS BL(), BU(), AND IND() = '
  684. * // XERN1 // ' MUST BE .GE. NCOLS = ' // XERN2,
  685. * 13, 1)
  686. C DO(RETURN TO USER PROGRAM UNIT)
  687. GO TO 190
  688. ENDIF
  689. IF (LLX.LT.LENX) THEN
  690. WRITE (XERN1, '(I8)') LLX
  691. WRITE (XERN2, '(I8)') LENX
  692. CALL XERMSG ('SLATEC', 'SBOLS',
  693. * 'THE DIMENSION OF X() = ' // XERN1 //
  694. * ' MUST BE .GE. THE REQUIRED LENGTH = ' // XERN2,
  695. * 14, 1)
  696. C DO(RETURN TO USER PROGRAM UNIT)
  697. GO TO 190
  698. ENDIF
  699. IF (LLRW.LT.5*NCOLS) THEN
  700. WRITE (XERN1, '(I8)') LLRW
  701. WRITE (XERN2, '(I8)') 5*NCOLS
  702. CALL XERMSG ('SLATEC', 'SBOLS',
  703. * 'THE DIMENSION OF RW() = ' // XERN1 //
  704. * ' MUST BE .GE. 5*NCOLS = ' // XERN2, 15, 1)
  705. C DO(RETURN TO USER PROGRAM UNIT)
  706. GO TO 190
  707. ENDIF
  708. IF (LLIW.LT.2*NCOLS) THEN
  709. WRITE (XERN1, '(I8)') LLIW
  710. WRITE (XERN2, '(I8)') 2*NCOLS
  711. CALL XERMSG ('SLATEC', 'SBOLS',
  712. * 'THE DIMENSION OF IW() = ' // XERN1 //
  713. * ' MUST BE .GE. 2*NCOLS = ' // XERN2, 16, 1)
  714. C DO(RETURN TO USER PROGRAM UNIT)
  715. GO TO 190
  716. ENDIF
  717. IF (LIOPT.LT.LP+1) THEN
  718. WRITE (XERN1, '(I8)') LIOPT
  719. WRITE (XERN2, '(I8)') LP+1
  720. CALL XERMSG ('SLATEC', 'SBOLS',
  721. * 'THE DIMENSION OF IOPT() = ' // XERN1 //
  722. * ' MUST BE .GE. THE REQD. LEN = ' // XERN2, 17, 1)
  723. C DO(RETURN TO USER PROGRAM UNIT)
  724. GO TO 190
  725. ENDIF
  726. C END PROCEDURE
  727. ENDIF
  728. ENDIF
  729. GO TO (60,90),IGO
  730. GO TO 180
  731. C
  732. C GO BACK TO THE USER FOR ACCUMULATION OF LEAST SQUARES
  733. C EQUATIONS AND DIRECTIONS TO QUIT PROCESSING.
  734. C CASE 1
  735. 60 CONTINUE
  736. C DO(ACCUMULATE LEAST SQUARES EQUATIONS)
  737. C PROCEDURE(ACCUMULATE LEAST SQUARES EQUATIONS)
  738. MROWS = IOPT(LOCACC+1) - 1
  739. INROWS = IOPT(LOCACC+2)
  740. MNEW = MROWS + INROWS
  741. IF (MNEW.LT.0 .OR. MNEW.GT.MDW) THEN
  742. WRITE (XERN1, '(I8)') MNEW
  743. WRITE (XERN2, '(I8)') MDW
  744. CALL XERMSG ('SLATEC', 'SBOLS', 'NO. OF ROWS = ' // XERN1 //
  745. * ' MUST BE .GE. 0 .AND. .LE. MDW = ' // XERN2, 10, 1)
  746. C DO(RETURN TO USER PROGRAM UNIT)
  747. GO TO 190
  748. ENDIF
  749. DO 80 J = 1,MIN(NCOLS+1,MNEW)
  750. DO 70 I = MNEW,MAX(MROWS,J) + 1,-1
  751. IBIG = ISAMAX(I-J,W(J,J),1) + J - 1
  752. C
  753. C PIVOT FOR INCREASED STABILITY.
  754. CALL SROTG(W(IBIG,J),W(I,J),SC,SS)
  755. CALL SROT(NCOLS+1-J,W(IBIG,J+1),MDW,W(I,J+1),MDW,SC,SS)
  756. W(I,J) = ZERO
  757. 70 CONTINUE
  758. 80 CONTINUE
  759. MROWS = MIN(NCOLS+1,MNEW)
  760. IOPT(LOCACC+1) = MROWS + 1
  761. IGO = IOPT(LOCACC)
  762. C END PROCEDURE
  763. IF (IGO.EQ.2) THEN
  764. IGO = 0
  765. ENDIF
  766. GO TO 180
  767. C CASE 2
  768. 90 CONTINUE
  769. C DO(INITIALIZE VARIABLES AND DATA VALUES)
  770. C PROCEDURE(INITIALIZE VARIABLES AND DATA VALUES)
  771. DO 150 J = 1,NCOLS
  772. GO TO (100,110,120,130),ISCALE
  773. GO TO 140
  774. 100 CONTINUE
  775. C CASE 1
  776. C
  777. C THIS IS THE NOMINAL SCALING. EACH NONZERO
  778. C COL. HAS MAX. NORM EQUAL TO ONE.
  779. IBIG = ISAMAX(MROWS,W(1,J),1)
  780. RW(J) = ABS(W(IBIG,J))
  781. IF (RW(J).EQ.ZERO) THEN
  782. RW(J) = ONE
  783. ELSE
  784. RW(J) = ONE/RW(J)
  785. ENDIF
  786. GO TO 140
  787. 110 CONTINUE
  788. C CASE 2
  789. C
  790. C THIS CHOICE OF SCALING MAKES EACH NONZERO COLUMN
  791. C HAVE EUCLIDEAN LENGTH EQUAL TO ONE.
  792. RW(J) = SNRM2(MROWS,W(1,J),1)
  793. IF (RW(J).EQ.ZERO) THEN
  794. RW(J) = ONE
  795. ELSE
  796. RW(J) = ONE/RW(J)
  797. ENDIF
  798. GO TO 140
  799. 120 CONTINUE
  800. C CASE 3
  801. C
  802. C THIS CASE EFFECTIVELY SUPPRESSES SCALING BY SETTING
  803. C THE SCALING MATRIX TO THE IDENTITY MATRIX.
  804. RW(1) = ONE
  805. CALL SCOPY(NCOLS,RW,0,RW,1)
  806. GO TO 160
  807. 130 CONTINUE
  808. C CASE 4
  809. GO TO 160
  810. 140 CONTINUE
  811. 150 CONTINUE
  812. 160 CONTINUE
  813. C END PROCEDURE
  814. C DO(SOLVE BOUNDED LEAST SQUARES PROBLEM)
  815. C PROCEDURE(SOLVE BOUNDED LEAST SQUARES PROBLEM)
  816. C
  817. C INITIALIZE IBASIS(*), J=1,NCOLS, AND IBB(*), J=1,NCOLS,
  818. C TO =J,AND =1, FOR USE IN SBOLSM( ).
  819. DO 170 J = 1,NCOLS
  820. IW(J) = J
  821. IW(J+NCOLS) = 1
  822. RW(3*NCOLS+J) = BL(J)
  823. RW(4*NCOLS+J) = BU(J)
  824. 170 CONTINUE
  825. CALL SBOLSM(W,MDW,MROWS,NCOLS,RW(3*NCOLS+1),RW(4*NCOLS+1),IND,
  826. . IOPT(LOPT),X,RNORM,MODE,RW(NCOLS+1),RW(2*NCOLS+1),RW,
  827. . IW,IW(NCOLS+1))
  828. C END PROCEDURE
  829. IGO = 0
  830. 180 CONTINUE
  831. RETURN
  832. C PROCEDURE(RETURN TO USER PROGRAM UNIT)
  833. 190 IF(MODE.GE.0)MODE = -NERR
  834. IGO = 0
  835. RETURN
  836. C END PROCEDURE
  837. END