summaryrefslogtreecommitdiff
path: root/modules/cacsd/src/slicot/ib01ad.f
blob: 1cb993f05a9b1137f9ced73ce8a49f0be55c9caa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
      SUBROUTINE IB01AD( METH, ALG, JOBD, BATCH, CONCT, CTRL, NOBR, M,
     $                   L, NSMP, U, LDU, Y, LDY, N, R, LDR, SV, RCOND,
     $                   TOL, IWORK, DWORK, LDWORK, IWARN, INFO )
C
C     RELEASE 4.0, WGS COPYRIGHT 2000.
C
C     PURPOSE
C
C     To preprocess the input-output data for estimating the matrices 
C     of a linear time-invariant dynamical system and to find an 
C     estimate of the system order. The input-output data can,
C     optionally, be processed sequentially.
C
C     ARGUMENTS
C
C     Mode Parameters
C
C     METH    CHARACTER*1
C             Specifies the subspace identification method to be used,
C             as follows:
C             = 'M':  MOESP  algorithm with past inputs and outputs;
C             = 'N':  N4SID  algorithm.
C
C     ALG     CHARACTER*1
C             Specifies the algorithm for computing the triangular
C             factor R, as follows:
C             = 'C':  Cholesky algorithm applied to the correlation
C                     matrix of the input-output data;
C             = 'F':  Fast QR algorithm;
C             = 'Q':  QR algorithm applied to the concatenated block
C                     Hankel matrices.
C
C     JOBD    CHARACTER*1
C             Specifies whether or not the matrices B and D should later
C             be computed using the MOESP approach, as follows:
C             = 'M':  the matrices B and D should later be computed
C                     using the MOESP approach;
C             = 'N':  the matrices B and D should not be computed using
C                     the MOESP approach.
C             This parameter is not relevant for METH = 'N'.
C
C     BATCH   CHARACTER*1
C             Specifies whether or not sequential data processing is to
C             be used, and, for sequential processing, whether or not
C             the current data block is the first block, an intermediate
C             block, or the last block, as follows:
C             = 'F':  the first block in sequential data processing;
C             = 'I':  an intermediate block in sequential data
C                     processing;
C             = 'L':  the last block in sequential data processing;
C             = 'O':  one block only (non-sequential data processing).
C             NOTE that when  100  cycles of sequential data processing
C                  are completed for  BATCH = 'I',  a warning is
C                  issued, to prevent for an infinite loop.
C
C     CONCT   CHARACTER*1
C             Specifies whether or not the successive data blocks in
C             sequential data processing belong to a single experiment,
C             as follows:
C             = 'C':  the current data block is a continuation of the
C                     previous data block and/or it will be continued
C                     by the next data block;
C             = 'N':  there is no connection between the current data
C                     block and the previous and/or the next ones.
C             This parameter is not used if BATCH = 'O'.
C
C     CTRL    CHARACTER*1
C             Specifies whether or not the user's confirmation of the
C             system order estimate is desired, as follows:
C             = 'C':  user's confirmation;
C             = 'N':  no confirmation.
C             If  CTRL = 'C',  a reverse communication routine,  IB01OY,
C             is indirectly called (by SLICOT Library routine IB01OD), 
C             and, after inspecting the singular values and system order
C             estimate,  n,  the user may accept  n  or set a new value.
C             IB01OY  is not called if CTRL = 'N'.
C
C     Input/Output Parameters
C
C     NOBR    (input) INTEGER
C             The number of block rows,  s,  in the input and output
C             block Hankel matrices to be processed.  NOBR > 0.
C             (In the MOESP theory,  NOBR  should be larger than  n,
C             the estimated dimension of state vector.)
C
C     M       (input) INTEGER
C             The number of system inputs.  M >= 0.
C             When M = 0, no system inputs are processed.
C
C     L       (input) INTEGER
C             The number of system outputs.  L > 0.
C
C     NSMP    (input) INTEGER
C             The number of rows of matrices  U  and  Y  (number of
C             samples,  t). (When sequential data processing is used,
C             NSMP  is the number of samples of the current data
C             block.)
C             NSMP >= 2*(M+L+1)*NOBR - 1,  for non-sequential
C                                          processing;
C             NSMP >= 2*NOBR,  for sequential processing.
C             The total number of samples when calling the routine with
C             BATCH = 'L'  should be at least  2*(M+L+1)*NOBR - 1.
C             The  NSMP  argument may vary from a cycle to another in
C             sequential data processing, but  NOBR, M,  and  L  should
C             be kept constant. For efficiency, it is advisable to use
C             NSMP  as large as possible.
C
C     U       (input) DOUBLE PRECISION array, dimension (LDU,M)
C             The leading NSMP-by-M part of this array must contain the
C             t-by-m input-data sequence matrix  U,
C             U = [u_1 u_2 ... u_m].  Column  j  of  U  contains the
C             NSMP  values of the j-th input component for consecutive
C             time increments.
C             If M = 0, this array is not referenced.
C
C     LDU     INTEGER
C             The leading dimension of the array U.
C             LDU >= NSMP, if M > 0;
C             LDU >= 1,    if M = 0.
C
C     Y       (input) DOUBLE PRECISION array, dimension (LDY,L)
C             The leading NSMP-by-L part of this array must contain the
C             t-by-l output-data sequence matrix  Y,
C             Y = [y_1 y_2 ... y_l].  Column  j  of  Y  contains the
C             NSMP  values of the j-th output component for consecutive
C             time increments.
C
C     LDY     INTEGER
C             The leading dimension of the array Y.  LDY >= NSMP.
C
C     N       (output) INTEGER
C             The estimated order of the system.
C             If  CTRL = 'C',  the estimated order has been reset to a
C             value specified by the user.
C
C     R       (output or input/output) DOUBLE PRECISION array, dimension
C             ( LDR,2*(M+L)*NOBR )
C             On exit, if ALG = 'C' and BATCH = 'F' or 'I', the leading
C             2*(M+L)*NOBR-by-2*(M+L)*NOBR upper triangular part of this
C             array contains the current upper triangular part of the
C             correlation matrix in sequential data processing.
C             If ALG = 'F' and BATCH = 'F' or 'I', the array R is not
C             referenced.
C             On exit, if INFO = 0, ALG = 'Q', and BATCH = 'F' or 'I',
C             the leading 2*(M+L)*NOBR-by-2*(M+L)*NOBR upper triangular
C             part of this array contains the current upper triangular
C             factor R from the QR factorization of the concatenated
C             block Hankel matrices. Denote  R_ij, i,j = 1:4,  the 
C             ij submatrix of  R,  partitioned by M*NOBR,  M*NOBR, 
C             L*NOBR,  and  L*NOBR  rows and columns. 
C             On exit, if INFO = 0 and BATCH = 'L' or 'O', the leading
C             2*(M+L)*NOBR-by-2*(M+L)*NOBR upper triangular part of
C             this array contains the matrix S, the processed upper
C             triangular factor R from the QR factorization of the
C             concatenated block Hankel matrices, as required by other
C             subroutines. Specifically, let  S_ij, i,j = 1:4,  be the
C             ij submatrix of  S,  partitioned by M*NOBR,  L*NOBR, 
C             M*NOBR,  and  L*NOBR  rows and columns. The submatrix 
C             S_22  contains the matrix of left singular vectors needed
C             subsequently. Useful information is stored in  S_11  and 
C             in the block-column  S_14 : S_44.  For METH = 'M' and 
C             JOBD = 'M', the upper triangular part of  S_31  contains
C             the upper triangular factor in the QR factorization of the
C             matrix  R_1c = [ R_12'  R_22'  R_11' ]',  and  S_12 
C             contains the corresponding leading part of the transformed
C             matrix  R_2c = [ R_13'  R_23'  R_14' ]'.  For  METH = 'N',
C             the subarray  S_41 : S_43  contains the transpose of the
C             matrix contained in  S_14 : S_34. 
C             The details of the contents of R need not be known if this
C             routine is followed by SLICOT Library routine IB01BD.
C             On entry, if ALG = 'C', or ALG = 'Q', and BATCH = 'I' or 
C             'L', the leading  2*(M+L)*NOBR-by-2*(M+L)*NOBR  upper
C             triangular part of this array must contain the upper
C             triangular matrix R computed at the previous call of this
C             routine in sequential data processing. The array R need
C             not be set on entry if ALG = 'F' or if BATCH = 'F' or 'O'.
C
C     LDR     INTEGER
C             The leading dimension of the array  R.
C             LDR >= MAX( 2*(M+L)*NOBR, 3*M*NOBR ),
C                                  for METH = 'M' and JOBD = 'M';
C             LDR >= 2*(M+L)*NOBR, for METH = 'M' and JOBD = 'N' or
C                                  for METH = 'N'.
C
C     SV      (output) DOUBLE PRECISION array, dimension ( L*NOBR )
C             The singular values used to estimate the system order.
C
C     Tolerances
C
C     RCOND   DOUBLE PRECISION
C             The tolerance to be used for estimating the rank of
C             matrices. If the user sets  RCOND > 0,  the given value
C             of  RCOND  is used as a lower bound for the reciprocal
C             condition number;  an m-by-n matrix whose estimated
C             condition number is less than  1/RCOND  is considered to  
C             be of full rank.  If the user sets  RCOND <= 0,  then an 
C             implicitly computed, default tolerance, defined by 
C             RCONDEF = m*n*EPS,  is used instead, where  EPS  is the 
C             relative machine precision (see LAPACK Library routine 
C             DLAMCH).
C             This parameter is not used for  METH = 'M'.
C
C     TOL     DOUBLE PRECISION
C             Absolute tolerance used for determining an estimate of
C             the system order. If  TOL >= 0,  the estimate is
C             indicated by the index of the last singular value greater
C             than or equal to  TOL.  (Singular values less than  TOL
C             are considered as zero.) When  TOL = 0,  an internally
C             computed default value,  TOL = NOBR*EPS*SV(1),  is used,
C             where  SV(1)  is the maximal singular value, and  EPS  is
C             the relative machine precision (see LAPACK Library routine
C             DLAMCH). When  TOL < 0,  the estimate is indicated by the
C             index of the singular value that has the largest
C             logarithmic gap to its successor.
C
C     Workspace
C
C     IWORK   INTEGER array, dimension (LIWORK)
C             LIWORK >= (M+L)*NOBR, if METH = 'N';
C             LIWORK >= M+L, if METH = 'M' and ALG = 'F';
C             LIWORK >= 0,   if METH = 'M' and ALG = 'C' or 'Q'.
C
C     DWORK   DOUBLE PRECISION array, dimension (LDWORK)
C             On exit, if  INFO = 0,  DWORK(1) returns the optimal value
C             of LDWORK,  and, for  METH = 'N',  and  BATCH = 'L'  or
C             'O',  DWORK(2)  and  DWORK(3)  contain the reciprocal 
C             condition numbers of the triangular factors of the 
C             matrices  U_f  and  r_1  [6].
C             On exit, if  INFO = -23,  DWORK(1)  returns the minimum
C             value of LDWORK.
C             Let
C             k = 0,               if CONCT = 'N' and ALG = 'C' or 'Q';
C             k = 2*NOBR-1,        if CONCT = 'C' and ALG = 'C' or 'Q';
C             k = 2*NOBR*(M+L+1),  if CONCT = 'N' and ALG = 'F';
C             k = 2*NOBR*(M+L+2),  if CONCT = 'C' and ALG = 'F'.
C             The first (M+L)*k elements of  DWORK  should be preserved
C             during successive calls of the routine with  BATCH = 'F'
C             or  'I',  till the final call with  BATCH = 'L'.
C
C     LDWORK  INTEGER
C             The length of the array DWORK.
C             LDWORK >= (4*NOBR-2)*(M+L), if ALG = 'C', BATCH = 'F' or
C                             'I' and CONCT = 'C';
C             LDWORK >= 1, if ALG = 'C', BATCH = 'F' or 'I' and 
C                             CONCT = 'N';
C             LDWORK >= max((4*NOBR-2)*(M+L), 5*L*NOBR), if METH = 'M',
C                             ALG = 'C', BATCH = 'L' and CONCT = 'C';
C             LDWORK >= max((2*M-1)*NOBR, (M+L)*NOBR, 5*L*NOBR), 
C                             if METH = 'M', JOBD = 'M', ALG = 'C',
C                              BATCH = 'O', or 
C                             (BATCH = 'L' and CONCT = 'N');
C             LDWORK >= 5*L*NOBR, if METH = 'M', JOBD = 'N', ALG = 'C',
C                              BATCH = 'O', or 
C                             (BATCH = 'L' and CONCT = 'N');
C             LDWORK >= 5*(M+L)*NOBR, if METH = 'N', ALG = 'C', and
C                             BATCH = 'L' or 'O';
C             LDWORK >= (M+L)*2*NOBR*(M+L+3), if ALG = 'F',
C                             BATCH <> 'O' and CONCT = 'C';
C             LDWORK >= (M+L)*2*NOBR*(M+L+1), if ALG = 'F',
C                             BATCH = 'F', 'I' and CONCT = 'N';
C             LDWORK >= (M+L)*4*NOBR*(M+L+1)+(M+L)*2*NOBR, if ALG = 'F',
C                             BATCH = 'L' and CONCT = 'N', or
C                             BATCH = 'O';
C             LDWORK >= 4*(M+L)*NOBR, if ALG = 'Q', BATCH = 'F', and 
C                             LDR >= NS = NSMP - 2*NOBR + 1;
C             LDWORK >= max(4*(M+L)*NOBR, 5*L*NOBR), if METH = 'M',
C                             ALG = 'Q', BATCH = 'O', and LDR >= NS;
C             LDWORK >= 5*(M+L)*NOBR, if METH = 'N', ALG = 'Q',
C                             BATCH = 'O', and LDR >= NS;
C             LDWORK >= 6*(M+L)*NOBR, if ALG = 'Q', (BATCH = 'F' or 'O',
C                             and LDR < NS), or (BATCH = 'I' or 
C                             'L' and CONCT = 'N');
C             LDWORK >= 4*(NOBR+1)*(M+L)*NOBR, if ALG = 'Q', BATCH = 'I'
C                             or 'L' and CONCT = 'C'.
C             The workspace used for ALG = 'Q' is 
C                       LDRWRK*2*(M+L)*NOBR + 4*(M+L)*NOBR, 
C             where LDRWRK = LDWORK/(2*(M+L)*NOBR) - 2; recommended 
C             value LDRWRK = NS, assuming a large enough cache size.
C             For good performance,  LDWORK  should be larger.
C
C     Warning Indicator
C
C     IWARN   INTEGER
C             = 0:  no warning;
C             = 1:  the number of 100 cycles in sequential data
C                   processing has been exhausted without signaling
C                   that the last block of data was get; the cycle
C                   counter was reinitialized;
C             = 2:  a fast algorithm was requested (ALG = 'C' or 'F'),
C                   but it failed, and the QR algorithm was then used
C                   (non-sequential data processing);
C             = 3:  all singular values were exactly zero, hence  N = 0
C                   (both input and output were identically zero);
C             = 4:  the least squares problems with coefficient matrix
C                   U_f,  used for computing the weighted oblique
C                   projection (for METH = 'N'), have a rank-deficient
C                   coefficient matrix;
C             = 5:  the least squares problem with coefficient matrix
C                   r_1  [6], used for computing the weighted oblique
C                   projection (for METH = 'N'), has a rank-deficient
C                   coefficient matrix.
C             NOTE: the values 4 and 5 of IWARN have no significance
C                   for the identification problem. 
C
C     Error Indicator
C
C     INFO    INTEGER
C             = 0:  successful exit;
C             < 0:  if INFO = -i, the i-th argument had an illegal
C                   value;
C             = 1:  a fast algorithm was requested (ALG = 'C', or 'F')
C                   in sequential data processing, but it failed; the
C                   routine can be repeatedly called again using the
C                   standard QR algorithm;
C             = 2:  the singular value decomposition (SVD) algorithm did
C                   not converge.
C
C     METHOD
C
C     The procedure consists in three main steps, the first step being
C     performed by one of the three algorithms included.
C
C     1.a) For non-sequential data processing using QR algorithm, a
C     t x 2(m+l)s  matrix H is constructed, where  
C
C          H = [ Uf'         Up'      Y'      ],  for METH = 'M',
C                  s+1,2s,t    1,s,t   1,2s,t
C
C          H = [ U'       Y'      ],              for METH = 'N',
C                 1,2s,t   1,2s,t
C
C     and  Up     , Uf        , U      , and  Y        are block Hankel
C            1,s,t    s+1,2s,t   1,2s,t        1,2s,t
C     matrices defined in terms of the input and output data [3].
C     A QR factorization is used to compress the data.
C     The fast QR algorithm uses a QR factorization which exploits 
C     the block-Hankel structure. Actually, the Cholesky factor of H'*H
C     is computed.
C
C     1.b) For sequential data processing using QR algorithm, the QR
C     decomposition is done sequentially, by updating the upper
C     triangular factor  R.  This is also performed internally if the
C     workspace is not large enough to accommodate an entire batch.
C
C     1.c) For non-sequential or sequential data processing using
C     Cholesky algorithm, the correlation matrix of input-output data is
C     computed (sequentially, if requested), taking advantage of the
C     block Hankel structure [7].  Then, the Cholesky factor of the
C     correlation matrix is found, if possible.
C
C     2) A singular value decomposition (SVD) of a certain matrix is
C     then computed, which reveals the order  n  of the system as the
C     number of "non-zero" singular values. For the MOESP approach, this
C     matrix is  [ R_24'  R_34' ]' := R(ms+1:(2m+l)s,(2m+l)s+1:2(m+l)s),
C     where  R  is the upper triangular factor  R  constructed by SLICOT
C     Library routine  IB01MD.  For the N4SID approach, a weighted
C     oblique projection is computed from the upper triangular factor  R
C     and its SVD is then found.
C
C     3) The singular values are compared to the given, or default TOL,
C     and the estimated order  n  is returned, possibly after user's
C     confirmation.
C
C     REFERENCES
C
C     [1] Verhaegen M., and Dewilde, P.
C         Subspace Model Identification. Part 1: The output-error 
C         state-space model identification class of algorithms.
C         Int. J. Control, 56, pp. 1187-1210, 1992.
C
C     [2] Verhaegen M.
C         Subspace Model Identification. Part 3: Analysis of the
C         ordinary output-error state-space model identification
C         algorithm.
C         Int. J. Control, 58, pp. 555-586, 1993.
C
C     [3] Verhaegen M.
C         Identification of the deterministic part of MIMO state space
C         models given in innovations form from input-output data.
C         Automatica, Vol.30, No.1, pp.61-74, 1994.
C
C     [4] Van Overschee, P., and De Moor, B.
C         N4SID: Subspace Algorithms for the Identification of
C         Combined Deterministic-Stochastic Systems.
C         Automatica, Vol.30, No.1, pp. 75-93, 1994.
C
C     [5] Peternell, K., Scherrer, W. and Deistler, M.
C         Statistical Analysis of Novel Subspace Identification Methods.
C         Signal Processing, 52, pp. 161-177, 1996.
C
C     [6] Sima, V.
C         Subspace-based Algorithms for Multivariable System 
C         Identification.
C         Studies in Informatics and Control, 5, pp. 335-344, 1996.
C
C     [7] Sima, V.
C         Cholesky or QR Factorization for Data Compression in 
C         Subspace-based Identification ?
C         Proceedings of the Second NICONET Workshop on ``Numerical 
C         Control Software: SLICOT, a Useful Tool in Industry'', 
C         December 3, 1999, INRIA Rocquencourt, France, pp. 75-80, 1999.
C
C     NUMERICAL ASPECTS
C
C     The implemented method is numerically stable (when QR algorithm is
C     used), reliable and efficient. The fast Cholesky or QR algorithms
C     are more efficient, but the accuracy could diminish by forming the
C     correlation matrix.
C     The most time-consuming computational step is step 1:
C                                        2 
C     The QR algorithm needs 0(t(2(m+l)s) ) floating point operations.
C                                           2              3
C     The Cholesky algorithm needs 0(2t(m+l) s)+0((2(m+l)s) ) floating 
C     point operations.
C                                          2           3 2 
C     The fast QR algorithm needs 0(2t(m+l) s)+0(4(m+l) s ) floating 
C     point operations.
C                                                3
C     Step 2 of the algorithm requires 0(((m+l)s) ) floating point 
C     operations.
C
C     FURTHER COMMENTS
C
C     For ALG = 'Q', BATCH = 'O' and LDR < NS, or BATCH <> 'O', the  
C     calculations could be rather inefficient if only minimal workspace
C     (see argument LDWORK) is provided. It is advisable to provide as
C     much workspace as possible. Almost optimal efficiency can be 
C     obtained for  LDWORK = (NS+2)*(2*(M+L)*NOBR),  assuming that the 
C     cache size is large enough to accommodate R, U, Y, and DWORK.
C
C     CONTRIBUTOR
C
C     V. Sima, Katholieke Universiteit Leuven, Feb. 2000.
C
C     REVISIONS
C
C     August 2000.
C
C     KEYWORDS
C
C     Cholesky decomposition, Hankel matrix, identification methods, 
C     multivariable systems, QR decomposition, singular value 
C     decomposition.
C
C     ******************************************************************
C
C     .. Scalar Arguments ..
      DOUBLE PRECISION   RCOND, TOL
      INTEGER            INFO, IWARN, L, LDR, LDU, LDWORK, LDY, M, N,
     $                   NOBR, NSMP
      CHARACTER          ALG, BATCH, CONCT, CTRL, JOBD, METH
C     .. Array Arguments ..
      INTEGER            IWORK(*)
      DOUBLE PRECISION   DWORK(*), R(LDR, *), SV(*), U(LDU, *), 
     $                   Y(LDY, *)
C     .. Local Scalars ..
      INTEGER            IWARNL, LMNOBR, LNOBR, MAXWRK, MINWRK, MNOBR,
     $                   NOBR21, NR, NS, NSMPSM
      LOGICAL            CHALG, CONNEC, CONTRL, FIRST, FQRALG, INTERM,
     $                   JOBDM, LAST, MOESP, N4SID, ONEBCH, QRALG
C     .. External Functions ..
      LOGICAL            LSAME 
      EXTERNAL           LSAME
C     .. External Subroutines ..
      EXTERNAL           IB01MD, IB01ND, IB01OD, XERBLA
C     .. Intrinsic Functions ..
      INTRINSIC          MAX
C     .. Save Statement ..
C        MAXWRK  is used to store the optimal workspace.
C        NSMPSM  is used to sum up the  NSMP  values for  BATCH <> 'O'.
      SAVE               MAXWRK, NSMPSM
C     ..
C     .. Executable Statements ..
C
C     Decode the scalar input parameters.
C
      MOESP  = LSAME( METH,  'M' )
      N4SID  = LSAME( METH,  'N' )
      FQRALG = LSAME( ALG,   'F' )
      QRALG  = LSAME( ALG,   'Q' )
      CHALG  = LSAME( ALG,   'C' )
      JOBDM  = LSAME( JOBD,  'M' )
      ONEBCH = LSAME( BATCH, 'O' )
      FIRST  = LSAME( BATCH, 'F' ) .OR. ONEBCH
      INTERM = LSAME( BATCH, 'I' )
      LAST   = LSAME( BATCH, 'L' ) .OR. ONEBCH
      CONTRL = LSAME( CTRL,  'C' )
C
      IF( .NOT.ONEBCH ) THEN
         CONNEC = LSAME( CONCT, 'C' )
      ELSE
         CONNEC = .FALSE.
      END IF
C
      MNOBR  = M*NOBR
      LNOBR  = L*NOBR
      LMNOBR = LNOBR  + MNOBR
      NR     = LMNOBR + LMNOBR
      NOBR21 = 2*NOBR - 1
      IWARN  = 0
      INFO   = 0
      IF( FIRST ) THEN
         MAXWRK = 1
         NSMPSM = 0
      END IF
      NSMPSM = NSMPSM + NSMP
C
C     Check the scalar input parameters.
C
      IF( .NOT.( MOESP .OR. N4SID ) ) THEN
         INFO = -1
      ELSE IF( .NOT.( FQRALG .OR. QRALG .OR. CHALG ) ) THEN
         INFO = -2
      ELSE IF( MOESP .AND. .NOT.( JOBDM .OR. LSAME( JOBD, 'N' ) ) ) THEN
         INFO = -3
      ELSE IF( .NOT.( FIRST .OR. INTERM .OR. LAST ) ) THEN
         INFO = -4
      ELSE IF( .NOT. ONEBCH ) THEN
         IF( .NOT.( CONNEC .OR. LSAME( CONCT, 'N' ) ) )
     $      INFO = -5
      END IF
      IF( INFO.EQ.0 ) THEN
         IF( .NOT.( CONTRL .OR. LSAME( CTRL, 'N' ) ) ) THEN
            INFO = -6
         ELSE IF( NOBR.LE.0 ) THEN
            INFO = -7
         ELSE IF( M.LT.0 ) THEN
            INFO = -8
         ELSE IF( L.LE.0 ) THEN
            INFO = -9
         ELSE IF( NSMP.LT.2*NOBR .OR.
     $            ( LAST .AND. NSMPSM.LT.NR+NOBR21 ) ) THEN
            INFO = -10
         ELSE IF( LDU.LT.1 .OR. ( M.GT.0 .AND. LDU.LT.NSMP ) ) THEN
            INFO = -12
         ELSE IF( LDY.LT.NSMP ) THEN
            INFO = -14
         ELSE IF( LDR.LT.NR .OR. ( MOESP .AND. JOBDM .AND. 
     $            LDR.LT.3*MNOBR ) ) THEN
            INFO = -17
         ELSE
C
C           Compute workspace.
C           (Note: Comments in the code beginning "Workspace:" describe
C           the minimal amount of workspace needed at that point in the
C           code, as well as the preferred amount for good performance.)
C
            NS = NSMP - NOBR21
            IF ( CHALG ) THEN
               IF ( .NOT.LAST ) THEN
                  IF ( CONNEC ) THEN
                     MINWRK = 2*( NR - M - L )
                  ELSE
                     MINWRK = 1
                  END IF
               ELSE IF ( MOESP ) THEN
                  IF ( CONNEC .AND. .NOT.ONEBCH ) THEN
                     MINWRK = MAX( 2*( NR - M - L ), 5*LNOBR )
                  ELSE
                     MINWRK = 5*LNOBR
                     IF ( JOBDM ) 
     $                  MINWRK = MAX( 2*MNOBR - NOBR, LMNOBR, MINWRK )
                  END IF
               ELSE
                  MINWRK = 5*LMNOBR
               END IF
            ELSE IF ( FQRALG ) THEN
               IF ( .NOT.ONEBCH .AND. CONNEC ) THEN
                  MINWRK = NR*( M + L + 3 )
               ELSE IF ( FIRST .OR. INTERM ) THEN
                  MINWRK = NR*( M + L + 1 )
               ELSE 
                  MINWRK = 2*NR*( M + L + 1 ) + NR
               END IF
            ELSE 
               MINWRK = 2*NR
               IF ( ONEBCH .AND. LDR.GE.NS ) THEN
                  IF ( MOESP ) THEN
                     MINWRK = MAX( MINWRK, 5*LNOBR )
                  ELSE
                     MINWRK = 5*LMNOBR
                  END IF
               END IF
               IF ( FIRST ) THEN
                  IF ( LDR.LT.NS ) THEN
                     MINWRK = MINWRK + NR
                  END IF
               ELSE
                  IF ( CONNEC ) THEN
                     MINWRK = MINWRK*( NOBR + 1 )
                  ELSE
                     MINWRK = MINWRK + NR
                  END IF
               END IF
            END IF
C
            MAXWRK = MINWRK
C
            IF( LDWORK.LT.MINWRK ) THEN
               INFO = -23
               DWORK( 1 ) = MINWRK
            END IF
         END IF
      END IF       
C
C     Return if there are illegal arguments.
C
      IF( INFO.NE.0 ) THEN
         CALL XERBLA( 'IB01AD', -INFO )
         RETURN
      END IF
C
C     Compress the input-output data.
C     Workspace: need   c*(M+L)*NOBR, where c is a constant depending
C                       on the algorithm and the options used
C                       (see SLICOT Library routine IB01MD);
C                prefer larger.
C
      CALL IB01MD( METH, ALG, BATCH, CONCT, NOBR, M, L, NSMP, U, LDU, Y,
     $             LDY, R, LDR, IWORK, DWORK, LDWORK, IWARN, INFO )
C
      IF ( INFO.EQ.1 ) THEN
C
C        Error return: A fast algorithm was requested (ALG = 'C', 'F')
C        in sequential data processing, but it failed. 
C
         RETURN
      END IF
C
      MAXWRK = MAX( MAXWRK, INT( DWORK( 1 ) ) )
C
      IF ( .NOT.LAST ) THEN
C
C        Return to get new data.
C
         RETURN
      END IF
C
C     Find the singular value decomposition (SVD) giving the system
C     order, and perform related preliminary calculations needed for
C     computing the system matrices.
C     Workspace: need   max( (2*M-1)*NOBR, (M+L)*NOBR, 5*L*NOBR ),
C                                          if METH = 'M';
C                            5*(M+L)*NOBR, if METH = 'N';
C                prefer larger.
C
      CALL IB01ND( METH, JOBD, NOBR, M, L, R, LDR, SV, RCOND, IWORK,
     $             DWORK, LDWORK, IWARNL, INFO )
      IWARN = MAX( IWARN, IWARNL )
C
      IF ( INFO.EQ.2 ) THEN
C
C        Error return: the singular value decomposition (SVD) algorithm
C        did not converge.
C
         RETURN
      END IF
C
C     Estimate the system order.
C
      CALL IB01OD( CTRL, NOBR, L, SV, N, TOL, IWARNL, INFO )
      IWARN = MAX( IWARN, IWARNL )
C
C     Return optimal workspace in  DWORK(1).
C
      DWORK( 1 ) = MAX( MAXWRK,  INT( DWORK( 1 ) ) )
      RETURN
C
C *** Last line of IB01AD ***
      END