Coverage Report

Created: 2023-09-25 06:05

/src/igraph/vendor/lapack/dtrsen.c
Line
Count
Source (jump to first uncovered line)
1
/*  -- translated by f2c (version 20191129).
2
   You must link the resulting object file with libf2c:
3
  on Microsoft Windows system, link with libf2c.lib;
4
  on Linux or Unix systems, link with .../path/to/libf2c.a -lm
5
  or, if you install libf2c.a in a standard place, with -lf2c -lm
6
  -- in that order, at the end of the command line, as in
7
    cc *.o -lf2c -lm
8
  Source for libf2c is in /netlib/f2c/libf2c.zip, e.g.,
9
10
    http://www.netlib.org/f2c/libf2c.zip
11
*/
12
13
#include "f2c.h"
14
15
/* Table of constant values */
16
17
static integer c_n1 = -1;
18
19
/* > \brief \b DTRSEN   
20
21
    =========== DOCUMENTATION ===========   
22
23
   Online html documentation available at   
24
              http://www.netlib.org/lapack/explore-html/   
25
26
   > \htmlonly   
27
   > Download DTRSEN + dependencies   
28
   > <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dtrsen.
29
f">   
30
   > [TGZ]</a>   
31
   > <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dtrsen.
32
f">   
33
   > [ZIP]</a>   
34
   > <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dtrsen.
35
f">   
36
   > [TXT]</a>   
37
   > \endhtmlonly   
38
39
    Definition:   
40
    ===========   
41
42
         SUBROUTINE DTRSEN( JOB, COMPQ, SELECT, N, T, LDT, Q, LDQ, WR, WI,   
43
                            M, S, SEP, WORK, LWORK, IWORK, LIWORK, INFO )   
44
45
         CHARACTER          COMPQ, JOB   
46
         INTEGER            INFO, LDQ, LDT, LIWORK, LWORK, M, N   
47
         DOUBLE PRECISION   S, SEP   
48
         LOGICAL            SELECT( * )   
49
         INTEGER            IWORK( * )   
50
         DOUBLE PRECISION   Q( LDQ, * ), T( LDT, * ), WI( * ), WORK( * ),   
51
        $                   WR( * )   
52
53
54
   > \par Purpose:   
55
    =============   
56
   >   
57
   > \verbatim   
58
   >   
59
   > DTRSEN reorders the real Schur factorization of a real matrix   
60
   > A = Q*T*Q**T, so that a selected cluster of eigenvalues appears in   
61
   > the leading diagonal blocks of the upper quasi-triangular matrix T,   
62
   > and the leading columns of Q form an orthonormal basis of the   
63
   > corresponding right invariant subspace.   
64
   >   
65
   > Optionally the routine computes the reciprocal condition numbers of   
66
   > the cluster of eigenvalues and/or the invariant subspace.   
67
   >   
68
   > T must be in Schur canonical form (as returned by DHSEQR), that is,   
69
   > block upper triangular with 1-by-1 and 2-by-2 diagonal blocks; each   
70
   > 2-by-2 diagonal block has its diagonal elements equal and its   
71
   > off-diagonal elements of opposite sign.   
72
   > \endverbatim   
73
74
    Arguments:   
75
    ==========   
76
77
   > \param[in] JOB   
78
   > \verbatim   
79
   >          JOB is CHARACTER*1   
80
   >          Specifies whether condition numbers are required for the   
81
   >          cluster of eigenvalues (S) or the invariant subspace (SEP):   
82
   >          = 'N': none;   
83
   >          = 'E': for eigenvalues only (S);   
84
   >          = 'V': for invariant subspace only (SEP);   
85
   >          = 'B': for both eigenvalues and invariant subspace (S and   
86
   >                 SEP).   
87
   > \endverbatim   
88
   >   
89
   > \param[in] COMPQ   
90
   > \verbatim   
91
   >          COMPQ is CHARACTER*1   
92
   >          = 'V': update the matrix Q of Schur vectors;   
93
   >          = 'N': do not update Q.   
94
   > \endverbatim   
95
   >   
96
   > \param[in] SELECT   
97
   > \verbatim   
98
   >          SELECT is LOGICAL array, dimension (N)   
99
   >          SELECT specifies the eigenvalues in the selected cluster. To   
100
   >          select a real eigenvalue w(j), SELECT(j) must be set to   
101
   >          .TRUE.. To select a complex conjugate pair of eigenvalues   
102
   >          w(j) and w(j+1), corresponding to a 2-by-2 diagonal block,   
103
   >          either SELECT(j) or SELECT(j+1) or both must be set to   
104
   >          .TRUE.; a complex conjugate pair of eigenvalues must be   
105
   >          either both included in the cluster or both excluded.   
106
   > \endverbatim   
107
   >   
108
   > \param[in] N   
109
   > \verbatim   
110
   >          N is INTEGER   
111
   >          The order of the matrix T. N >= 0.   
112
   > \endverbatim   
113
   >   
114
   > \param[in,out] T   
115
   > \verbatim   
116
   >          T is DOUBLE PRECISION array, dimension (LDT,N)   
117
   >          On entry, the upper quasi-triangular matrix T, in Schur   
118
   >          canonical form.   
119
   >          On exit, T is overwritten by the reordered matrix T, again in   
120
   >          Schur canonical form, with the selected eigenvalues in the   
121
   >          leading diagonal blocks.   
122
   > \endverbatim   
123
   >   
124
   > \param[in] LDT   
125
   > \verbatim   
126
   >          LDT is INTEGER   
127
   >          The leading dimension of the array T. LDT >= max(1,N).   
128
   > \endverbatim   
129
   >   
130
   > \param[in,out] Q   
131
   > \verbatim   
132
   >          Q is DOUBLE PRECISION array, dimension (LDQ,N)   
133
   >          On entry, if COMPQ = 'V', the matrix Q of Schur vectors.   
134
   >          On exit, if COMPQ = 'V', Q has been postmultiplied by the   
135
   >          orthogonal transformation matrix which reorders T; the   
136
   >          leading M columns of Q form an orthonormal basis for the   
137
   >          specified invariant subspace.   
138
   >          If COMPQ = 'N', Q is not referenced.   
139
   > \endverbatim   
140
   >   
141
   > \param[in] LDQ   
142
   > \verbatim   
143
   >          LDQ is INTEGER   
144
   >          The leading dimension of the array Q.   
145
   >          LDQ >= 1; and if COMPQ = 'V', LDQ >= N.   
146
   > \endverbatim   
147
   >   
148
   > \param[out] WR   
149
   > \verbatim   
150
   >          WR is DOUBLE PRECISION array, dimension (N)   
151
   > \endverbatim   
152
   > \param[out] WI   
153
   > \verbatim   
154
   >          WI is DOUBLE PRECISION array, dimension (N)   
155
   >   
156
   >          The real and imaginary parts, respectively, of the reordered   
157
   >          eigenvalues of T. The eigenvalues are stored in the same   
158
   >          order as on the diagonal of T, with WR(i) = T(i,i) and, if   
159
   >          T(i:i+1,i:i+1) is a 2-by-2 diagonal block, WI(i) > 0 and   
160
   >          WI(i+1) = -WI(i). Note that if a complex eigenvalue is   
161
   >          sufficiently ill-conditioned, then its value may differ   
162
   >          significantly from its value before reordering.   
163
   > \endverbatim   
164
   >   
165
   > \param[out] M   
166
   > \verbatim   
167
   >          M is INTEGER   
168
   >          The dimension of the specified invariant subspace.   
169
   >          0 < = M <= N.   
170
   > \endverbatim   
171
   >   
172
   > \param[out] S   
173
   > \verbatim   
174
   >          S is DOUBLE PRECISION   
175
   >          If JOB = 'E' or 'B', S is a lower bound on the reciprocal   
176
   >          condition number for the selected cluster of eigenvalues.   
177
   >          S cannot underestimate the true reciprocal condition number   
178
   >          by more than a factor of sqrt(N). If M = 0 or N, S = 1.   
179
   >          If JOB = 'N' or 'V', S is not referenced.   
180
   > \endverbatim   
181
   >   
182
   > \param[out] SEP   
183
   > \verbatim   
184
   >          SEP is DOUBLE PRECISION   
185
   >          If JOB = 'V' or 'B', SEP is the estimated reciprocal   
186
   >          condition number of the specified invariant subspace. If   
187
   >          M = 0 or N, SEP = norm(T).   
188
   >          If JOB = 'N' or 'E', SEP is not referenced.   
189
   > \endverbatim   
190
   >   
191
   > \param[out] WORK   
192
   > \verbatim   
193
   >          WORK is DOUBLE PRECISION array, dimension (MAX(1,LWORK))   
194
   >          On exit, if INFO = 0, WORK(1) returns the optimal LWORK.   
195
   > \endverbatim   
196
   >   
197
   > \param[in] LWORK   
198
   > \verbatim   
199
   >          LWORK is INTEGER   
200
   >          The dimension of the array WORK.   
201
   >          If JOB = 'N', LWORK >= max(1,N);   
202
   >          if JOB = 'E', LWORK >= max(1,M*(N-M));   
203
   >          if JOB = 'V' or 'B', LWORK >= max(1,2*M*(N-M)).   
204
   >   
205
   >          If LWORK = -1, then a workspace query is assumed; the routine   
206
   >          only calculates the optimal size of the WORK array, returns   
207
   >          this value as the first entry of the WORK array, and no error   
208
   >          message related to LWORK is issued by XERBLA.   
209
   > \endverbatim   
210
   >   
211
   > \param[out] IWORK   
212
   > \verbatim   
213
   >          IWORK is INTEGER array, dimension (MAX(1,LIWORK))   
214
   >          On exit, if INFO = 0, IWORK(1) returns the optimal LIWORK.   
215
   > \endverbatim   
216
   >   
217
   > \param[in] LIWORK   
218
   > \verbatim   
219
   >          LIWORK is INTEGER   
220
   >          The dimension of the array IWORK.   
221
   >          If JOB = 'N' or 'E', LIWORK >= 1;   
222
   >          if JOB = 'V' or 'B', LIWORK >= max(1,M*(N-M)).   
223
   >   
224
   >          If LIWORK = -1, then a workspace query is assumed; the   
225
   >          routine only calculates the optimal size of the IWORK array,   
226
   >          returns this value as the first entry of the IWORK array, and   
227
   >          no error message related to LIWORK is issued by XERBLA.   
228
   > \endverbatim   
229
   >   
230
   > \param[out] INFO   
231
   > \verbatim   
232
   >          INFO is INTEGER   
233
   >          = 0: successful exit   
234
   >          < 0: if INFO = -i, the i-th argument had an illegal value   
235
   >          = 1: reordering of T failed because some eigenvalues are too   
236
   >               close to separate (the problem is very ill-conditioned);   
237
   >               T may have been partially reordered, and WR and WI   
238
   >               contain the eigenvalues in the same order as in T; S and   
239
   >               SEP (if requested) are set to zero.   
240
   > \endverbatim   
241
242
    Authors:   
243
    ========   
244
245
   > \author Univ. of Tennessee   
246
   > \author Univ. of California Berkeley   
247
   > \author Univ. of Colorado Denver   
248
   > \author NAG Ltd.   
249
250
   > \date April 2012   
251
252
   > \ingroup doubleOTHERcomputational   
253
254
   > \par Further Details:   
255
    =====================   
256
   >   
257
   > \verbatim   
258
   >   
259
   >  DTRSEN first collects the selected eigenvalues by computing an   
260
   >  orthogonal transformation Z to move them to the top left corner of T.   
261
   >  In other words, the selected eigenvalues are the eigenvalues of T11   
262
   >  in:   
263
   >   
264
   >          Z**T * T * Z = ( T11 T12 ) n1   
265
   >                         (  0  T22 ) n2   
266
   >                            n1  n2   
267
   >   
268
   >  where N = n1+n2 and Z**T means the transpose of Z. The first n1 columns   
269
   >  of Z span the specified invariant subspace of T.   
270
   >   
271
   >  If T has been obtained from the real Schur factorization of a matrix   
272
   >  A = Q*T*Q**T, then the reordered real Schur factorization of A is given   
273
   >  by A = (Q*Z)*(Z**T*T*Z)*(Q*Z)**T, and the first n1 columns of Q*Z span   
274
   >  the corresponding invariant subspace of A.   
275
   >   
276
   >  The reciprocal condition number of the average of the eigenvalues of   
277
   >  T11 may be returned in S. S lies between 0 (very badly conditioned)   
278
   >  and 1 (very well conditioned). It is computed as follows. First we   
279
   >  compute R so that   
280
   >   
281
   >                         P = ( I  R ) n1   
282
   >                             ( 0  0 ) n2   
283
   >                               n1 n2   
284
   >   
285
   >  is the projector on the invariant subspace associated with T11.   
286
   >  R is the solution of the Sylvester equation:   
287
   >   
288
   >                        T11*R - R*T22 = T12.   
289
   >   
290
   >  Let F-norm(M) denote the Frobenius-norm of M and 2-norm(M) denote   
291
   >  the two-norm of M. Then S is computed as the lower bound   
292
   >   
293
   >                      (1 + F-norm(R)**2)**(-1/2)   
294
   >   
295
   >  on the reciprocal of 2-norm(P), the true reciprocal condition number.   
296
   >  S cannot underestimate 1 / 2-norm(P) by more than a factor of   
297
   >  sqrt(N).   
298
   >   
299
   >  An approximate error bound for the computed average of the   
300
   >  eigenvalues of T11 is   
301
   >   
302
   >                         EPS * norm(T) / S   
303
   >   
304
   >  where EPS is the machine precision.   
305
   >   
306
   >  The reciprocal condition number of the right invariant subspace   
307
   >  spanned by the first n1 columns of Z (or of Q*Z) is returned in SEP.   
308
   >  SEP is defined as the separation of T11 and T22:   
309
   >   
310
   >                     sep( T11, T22 ) = sigma-min( C )   
311
   >   
312
   >  where sigma-min(C) is the smallest singular value of the   
313
   >  n1*n2-by-n1*n2 matrix   
314
   >   
315
   >     C  = kprod( I(n2), T11 ) - kprod( transpose(T22), I(n1) )   
316
   >   
317
   >  I(m) is an m by m identity matrix, and kprod denotes the Kronecker   
318
   >  product. We estimate sigma-min(C) by the reciprocal of an estimate of   
319
   >  the 1-norm of inverse(C). The true reciprocal 1-norm of inverse(C)   
320
   >  cannot differ from sigma-min(C) by more than a factor of sqrt(n1*n2).   
321
   >   
322
   >  When SEP is small, small changes in T can cause large changes in   
323
   >  the invariant subspace. An approximate bound on the maximum angular   
324
   >  error in the computed right invariant subspace is   
325
   >   
326
   >                      EPS * norm(T) / SEP   
327
   > \endverbatim   
328
   >   
329
    =====================================================================   
330
   Subroutine */ int igraphdtrsen_(char *job, char *compq, logical *select, integer 
331
  *n, doublereal *t, integer *ldt, doublereal *q, integer *ldq, 
332
  doublereal *wr, doublereal *wi, integer *m, doublereal *s, doublereal 
333
  *sep, doublereal *work, integer *lwork, integer *iwork, integer *
334
  liwork, integer *info)
335
0
{
336
    /* System generated locals */
337
0
    integer q_dim1, q_offset, t_dim1, t_offset, i__1, i__2;
338
0
    doublereal d__1, d__2;
339
340
    /* Builtin functions */
341
0
    double sqrt(doublereal);
342
343
    /* Local variables */
344
0
    integer k, n1, n2, kk, nn, ks;
345
0
    doublereal est;
346
0
    integer kase;
347
0
    logical pair;
348
0
    integer ierr;
349
0
    logical swap;
350
0
    doublereal scale;
351
0
    extern logical igraphlsame_(char *, char *);
352
0
    integer isave[3], lwmin = 0;
353
0
    logical wantq, wants;
354
0
    doublereal rnorm;
355
0
    extern /* Subroutine */ int igraphdlacn2_(integer *, doublereal *, doublereal *,
356
0
       integer *, doublereal *, integer *, integer *);
357
0
    extern doublereal igraphdlange_(char *, integer *, integer *, doublereal *, 
358
0
      integer *, doublereal *);
359
0
    extern /* Subroutine */ int igraphdlacpy_(char *, integer *, integer *, 
360
0
      doublereal *, integer *, doublereal *, integer *), 
361
0
      igraphxerbla_(char *, integer *, ftnlen);
362
0
    logical wantbh;
363
0
    extern /* Subroutine */ int igraphdtrexc_(char *, integer *, doublereal *, 
364
0
      integer *, doublereal *, integer *, integer *, integer *, 
365
0
      doublereal *, integer *);
366
0
    integer liwmin;
367
0
    logical wantsp, lquery;
368
0
    extern /* Subroutine */ int igraphdtrsyl_(char *, char *, integer *, integer *, 
369
0
      integer *, doublereal *, integer *, doublereal *, integer *, 
370
0
      doublereal *, integer *, doublereal *, integer *);
371
372
373
/*  -- LAPACK computational routine (version 3.4.1) --   
374
    -- LAPACK is a software package provided by Univ. of Tennessee,    --   
375
    -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--   
376
       April 2012   
377
378
379
    =====================================================================   
380
381
382
       Decode and test the input parameters   
383
384
       Parameter adjustments */
385
0
    --select;
386
0
    t_dim1 = *ldt;
387
0
    t_offset = 1 + t_dim1;
388
0
    t -= t_offset;
389
0
    q_dim1 = *ldq;
390
0
    q_offset = 1 + q_dim1;
391
0
    q -= q_offset;
392
0
    --wr;
393
0
    --wi;
394
0
    --work;
395
0
    --iwork;
396
397
    /* Function Body */
398
0
    wantbh = igraphlsame_(job, "B");
399
0
    wants = igraphlsame_(job, "E") || wantbh;
400
0
    wantsp = igraphlsame_(job, "V") || wantbh;
401
0
    wantq = igraphlsame_(compq, "V");
402
403
0
    *info = 0;
404
0
    lquery = *lwork == -1;
405
0
    if (! igraphlsame_(job, "N") && ! wants && ! wantsp) {
406
0
  *info = -1;
407
0
    } else if (! igraphlsame_(compq, "N") && ! wantq) {
408
0
  *info = -2;
409
0
    } else if (*n < 0) {
410
0
  *info = -4;
411
0
    } else if (*ldt < max(1,*n)) {
412
0
  *info = -6;
413
0
    } else if (*ldq < 1 || wantq && *ldq < *n) {
414
0
  *info = -8;
415
0
    } else {
416
417
/*        Set M to the dimension of the specified invariant subspace,   
418
          and test LWORK and LIWORK. */
419
420
0
  *m = 0;
421
0
  pair = FALSE_;
422
0
  i__1 = *n;
423
0
  for (k = 1; k <= i__1; ++k) {
424
0
      if (pair) {
425
0
    pair = FALSE_;
426
0
      } else {
427
0
    if (k < *n) {
428
0
        if (t[k + 1 + k * t_dim1] == 0.) {
429
0
      if (select[k]) {
430
0
          ++(*m);
431
0
      }
432
0
        } else {
433
0
      pair = TRUE_;
434
0
      if (select[k] || select[k + 1]) {
435
0
          *m += 2;
436
0
      }
437
0
        }
438
0
    } else {
439
0
        if (select[*n]) {
440
0
      ++(*m);
441
0
        }
442
0
    }
443
0
      }
444
/* L10: */
445
0
  }
446
447
0
  n1 = *m;
448
0
  n2 = *n - *m;
449
0
  nn = n1 * n2;
450
451
0
  if (wantsp) {
452
/* Computing MAX */
453
0
      i__1 = 1, i__2 = nn << 1;
454
0
      lwmin = max(i__1,i__2);
455
0
      liwmin = max(1,nn);
456
0
  } else if (igraphlsame_(job, "N")) {
457
0
      lwmin = max(1,*n);
458
0
      liwmin = 1;
459
0
  } else if (igraphlsame_(job, "E")) {
460
0
      lwmin = max(1,nn);
461
0
      liwmin = 1;
462
0
  }
463
464
0
  if (*lwork < lwmin && ! lquery) {
465
0
      *info = -15;
466
0
  } else if (*liwork < liwmin && ! lquery) {
467
0
      *info = -17;
468
0
  }
469
0
    }
470
471
0
    if (*info == 0) {
472
0
  work[1] = (doublereal) lwmin;
473
0
  iwork[1] = liwmin;
474
0
    }
475
476
0
    if (*info != 0) {
477
0
  i__1 = -(*info);
478
0
  igraphxerbla_("DTRSEN", &i__1, (ftnlen)6);
479
0
  return 0;
480
0
    } else if (lquery) {
481
0
  return 0;
482
0
    }
483
484
/*     Quick return if possible. */
485
486
0
    if (*m == *n || *m == 0) {
487
0
  if (wants) {
488
0
      *s = 1.;
489
0
  }
490
0
  if (wantsp) {
491
0
      *sep = igraphdlange_("1", n, n, &t[t_offset], ldt, &work[1]);
492
0
  }
493
0
  goto L40;
494
0
    }
495
496
/*     Collect the selected blocks at the top-left corner of T. */
497
498
0
    ks = 0;
499
0
    pair = FALSE_;
500
0
    i__1 = *n;
501
0
    for (k = 1; k <= i__1; ++k) {
502
0
  if (pair) {
503
0
      pair = FALSE_;
504
0
  } else {
505
0
      swap = select[k];
506
0
      if (k < *n) {
507
0
    if (t[k + 1 + k * t_dim1] != 0.) {
508
0
        pair = TRUE_;
509
0
        swap = swap || select[k + 1];
510
0
    }
511
0
      }
512
0
      if (swap) {
513
0
    ++ks;
514
515
/*              Swap the K-th block to position KS. */
516
517
0
    ierr = 0;
518
0
    kk = k;
519
0
    if (k != ks) {
520
0
        igraphdtrexc_(compq, n, &t[t_offset], ldt, &q[q_offset], ldq, &
521
0
          kk, &ks, &work[1], &ierr);
522
0
    }
523
0
    if (ierr == 1 || ierr == 2) {
524
525
/*                 Blocks too close to swap: exit. */
526
527
0
        *info = 1;
528
0
        if (wants) {
529
0
      *s = 0.;
530
0
        }
531
0
        if (wantsp) {
532
0
      *sep = 0.;
533
0
        }
534
0
        goto L40;
535
0
    }
536
0
    if (pair) {
537
0
        ++ks;
538
0
    }
539
0
      }
540
0
  }
541
/* L20: */
542
0
    }
543
544
0
    if (wants) {
545
546
/*        Solve Sylvester equation for R:   
547
548
             T11*R - R*T22 = scale*T12 */
549
550
0
  igraphdlacpy_("F", &n1, &n2, &t[(n1 + 1) * t_dim1 + 1], ldt, &work[1], &n1);
551
0
  igraphdtrsyl_("N", "N", &c_n1, &n1, &n2, &t[t_offset], ldt, &t[n1 + 1 + (n1 
552
0
    + 1) * t_dim1], ldt, &work[1], &n1, &scale, &ierr);
553
554
/*        Estimate the reciprocal of the condition number of the cluster   
555
          of eigenvalues. */
556
557
0
  rnorm = igraphdlange_("F", &n1, &n2, &work[1], &n1, &work[1]);
558
0
  if (rnorm == 0.) {
559
0
      *s = 1.;
560
0
  } else {
561
0
      *s = scale / (sqrt(scale * scale / rnorm + rnorm) * sqrt(rnorm));
562
0
  }
563
0
    }
564
565
0
    if (wantsp) {
566
567
/*        Estimate sep(T11,T22). */
568
569
0
  est = 0.;
570
0
  kase = 0;
571
0
L30:
572
0
  igraphdlacn2_(&nn, &work[nn + 1], &work[1], &iwork[1], &est, &kase, isave);
573
0
  if (kase != 0) {
574
0
      if (kase == 1) {
575
576
/*              Solve  T11*R - R*T22 = scale*X. */
577
578
0
    igraphdtrsyl_("N", "N", &c_n1, &n1, &n2, &t[t_offset], ldt, &t[n1 + 
579
0
      1 + (n1 + 1) * t_dim1], ldt, &work[1], &n1, &scale, &
580
0
      ierr);
581
0
      } else {
582
583
/*              Solve T11**T*R - R*T22**T = scale*X. */
584
585
0
    igraphdtrsyl_("T", "T", &c_n1, &n1, &n2, &t[t_offset], ldt, &t[n1 + 
586
0
      1 + (n1 + 1) * t_dim1], ldt, &work[1], &n1, &scale, &
587
0
      ierr);
588
0
      }
589
0
      goto L30;
590
0
  }
591
592
0
  *sep = scale / est;
593
0
    }
594
595
0
L40:
596
597
/*     Store the output eigenvalues in WR and WI. */
598
599
0
    i__1 = *n;
600
0
    for (k = 1; k <= i__1; ++k) {
601
0
  wr[k] = t[k + k * t_dim1];
602
0
  wi[k] = 0.;
603
/* L50: */
604
0
    }
605
0
    i__1 = *n - 1;
606
0
    for (k = 1; k <= i__1; ++k) {
607
0
  if (t[k + 1 + k * t_dim1] != 0.) {
608
0
      wi[k] = sqrt((d__1 = t[k + (k + 1) * t_dim1], abs(d__1))) * sqrt((
609
0
        d__2 = t[k + 1 + k * t_dim1], abs(d__2)));
610
0
      wi[k + 1] = -wi[k];
611
0
  }
612
/* L60: */
613
0
    }
614
615
0
    work[1] = (doublereal) lwmin;
616
0
    iwork[1] = liwmin;
617
618
0
    return 0;
619
620
/*     End of DTRSEN */
621
622
0
} /* igraphdtrsen_ */
623