Skip Navigation Links
Numerical Libraries
Linear Algebra
Differential Equations
Optimization
Samples
Skip Navigation Links
Linear Algebra
CSLapack
CSBlas
   1:  #region Translated by Jose Antonio De Santiago-Castillo.
   2:   
   3:  //Translated by Jose Antonio De Santiago-Castillo. 
   4:  //E-mail:JAntonioDeSantiago@gmail.com
   5:  //Web: www.DotNumerics.com
   6:  //
   7:  //Fortran to C# Translation.
   8:  //Translated by:
   9:  //F2CSharp Version 0.71 (November 10, 2009)
  10:  //Code Optimizations: None
  11:  //
  12:  #endregion
  13:   
  14:  using System;
  15:  using DotNumerics.FortranLibrary;
  16:   
  17:  namespace DotNumerics.CSLapack
  18:  {
  19:      /// <summary>
  20:      /// -- LAPACK auxiliary routine (version 3.1) --
  21:      /// Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd..
  22:      /// November 2006
  23:      /// Purpose
  24:      /// =======
  25:      /// 
  26:      /// DLASDQ computes the singular value decomposition (SVD) of a real
  27:      /// (upper or lower) bidiagonal matrix with diagonal D and offdiagonal
  28:      /// E, accumulating the transformations if desired. Letting B denote
  29:      /// the input bidiagonal matrix, the algorithm computes orthogonal
  30:      /// matrices Q and P such that B = Q * S * P' (P' denotes the transpose
  31:      /// of P). The singular values S are overwritten on D.
  32:      /// 
  33:      /// The input matrix U  is changed to U  * Q  if desired.
  34:      /// The input matrix VT is changed to P' * VT if desired.
  35:      /// The input matrix C  is changed to Q' * C  if desired.
  36:      /// 
  37:      /// See "Computing  Small Singular Values of Bidiagonal Matrices With
  38:      /// Guaranteed High Relative Accuracy," by J. Demmel and W. Kahan,
  39:      /// LAPACK Working Note #3, for a detailed description of the algorithm.
  40:      /// 
  41:      ///</summary>
  42:      public class DLASDQ
  43:      {
  44:      
  45:   
  46:          #region Dependencies
  47:          
  48:          DBDSQR _dbdsqr; DLARTG _dlartg; DLASR _dlasr; DSWAP _dswap; XERBLA _xerbla; LSAME _lsame; 
  49:   
  50:          #endregion
  51:   
  52:   
  53:          #region Fields
  54:          
  55:          const double ZERO = 0.0E+0; bool ROTATE = false; int I = 0; int ISUB = 0; int IUPLO = 0; int J = 0; int NP1 = 0; 
  56:          int SQRE1 = 0;double CS = 0; double R = 0; double SMIN = 0; double SN = 0; 
  57:   
  58:          #endregion
  59:   
  60:          public DLASDQ(DBDSQR dbdsqr, DLARTG dlartg, DLASR dlasr, DSWAP dswap, XERBLA xerbla, LSAME lsame)
  61:          {
  62:      
  63:   
  64:              #region Set Dependencies
  65:              
  66:              this._dbdsqr = dbdsqr; this._dlartg = dlartg; this._dlasr = dlasr; this._dswap = dswap; this._xerbla = xerbla; 
  67:              this._lsame = lsame;
  68:   
  69:              #endregion
  70:   
  71:          }
  72:      
  73:          public DLASDQ()
  74:          {
  75:      
  76:   
  77:              #region Dependencies (Initialization)
  78:              
  79:              LSAME lsame = new LSAME();
  80:              DLAMC3 dlamc3 = new DLAMC3();
  81:              DLAS2 dlas2 = new DLAS2();
  82:              DCOPY dcopy = new DCOPY();
  83:              XERBLA xerbla = new XERBLA();
  84:              DLASQ5 dlasq5 = new DLASQ5();
  85:              DLAZQ4 dlazq4 = new DLAZQ4();
  86:              IEEECK ieeeck = new IEEECK();
  87:              IPARMQ iparmq = new IPARMQ();
  88:              DROT drot = new DROT();
  89:              DSCAL dscal = new DSCAL();
  90:              DSWAP dswap = new DSWAP();
  91:              DLAMC1 dlamc1 = new DLAMC1(dlamc3);
  92:              DLAMC4 dlamc4 = new DLAMC4(dlamc3);
  93:              DLAMC5 dlamc5 = new DLAMC5(dlamc3);
  94:              DLAMC2 dlamc2 = new DLAMC2(dlamc3, dlamc1, dlamc4, dlamc5);
  95:              DLAMCH dlamch = new DLAMCH(lsame, dlamc2);
  96:              DLARTG dlartg = new DLARTG(dlamch);
  97:              DLASCL dlascl = new DLASCL(lsame, dlamch, xerbla);
  98:              DLASQ6 dlasq6 = new DLASQ6(dlamch);
  99:              DLAZQ3 dlazq3 = new DLAZQ3(dlasq5, dlasq6, dlazq4, dlamch);
 100:              DLASRT dlasrt = new DLASRT(lsame, xerbla);
 101:              ILAENV ilaenv = new ILAENV(ieeeck, iparmq);
 102:              DLASQ2 dlasq2 = new DLASQ2(dlazq3, dlasrt, xerbla, dlamch, ilaenv);
 103:              DLASQ1 dlasq1 = new DLASQ1(dcopy, dlas2, dlascl, dlasq2, dlasrt, xerbla, dlamch);
 104:              DLASR dlasr = new DLASR(lsame, xerbla);
 105:              DLASV2 dlasv2 = new DLASV2(dlamch);
 106:              DBDSQR dbdsqr = new DBDSQR(lsame, dlamch, dlartg, dlas2, dlasq1, dlasr, dlasv2, drot, dscal, dswap
 107:                                         , xerbla);
 108:   
 109:              #endregion
 110:   
 111:   
 112:              #region Set Dependencies
 113:              
 114:              this._dbdsqr = dbdsqr; this._dlartg = dlartg; this._dlasr = dlasr; this._dswap = dswap; this._xerbla = xerbla; 
 115:              this._lsame = lsame;
 116:   
 117:              #endregion
 118:   
 119:          }
 120:          /// <summary>
 121:          /// Purpose
 122:          /// =======
 123:          /// 
 124:          /// DLASDQ computes the singular value decomposition (SVD) of a real
 125:          /// (upper or lower) bidiagonal matrix with diagonal D and offdiagonal
 126:          /// E, accumulating the transformations if desired. Letting B denote
 127:          /// the input bidiagonal matrix, the algorithm computes orthogonal
 128:          /// matrices Q and P such that B = Q * S * P' (P' denotes the transpose
 129:          /// of P). The singular values S are overwritten on D.
 130:          /// 
 131:          /// The input matrix U  is changed to U  * Q  if desired.
 132:          /// The input matrix VT is changed to P' * VT if desired.
 133:          /// The input matrix C  is changed to Q' * C  if desired.
 134:          /// 
 135:          /// See "Computing  Small Singular Values of Bidiagonal Matrices With
 136:          /// Guaranteed High Relative Accuracy," by J. Demmel and W. Kahan,
 137:          /// LAPACK Working Note #3, for a detailed description of the algorithm.
 138:          /// 
 139:          ///</summary>
 140:          /// <param name="UPLO">
 141:          /// (input) CHARACTER*1
 142:          /// On entry, UPLO specifies whether the input bidiagonal matrix
 143:          /// is upper or lower bidiagonal, and wether it is square are
 144:          /// not.
 145:          /// UPLO = 'U' or 'u'   B is upper bidiagonal.
 146:          /// UPLO = 'L' or 'l'   B is lower bidiagonal.
 147:          ///</param>
 148:          /// <param name="SQRE">
 149:          /// (input) INTEGER
 150:          /// = 0: then the input matrix is N-by-N.
 151:          /// = 1: then the input matrix is N-by-(N+1) if UPLU = 'U' and
 152:          /// (N+1)-by-N if UPLU = 'L'.
 153:          /// 
 154:          /// The bidiagonal matrix has
 155:          /// N = NL + NR + 1 rows and
 156:          /// M = N + SQRE .GE. N columns.
 157:          ///</param>
 158:          /// <param name="N">
 159:          /// (input) INTEGER
 160:          /// On entry, N specifies the number of rows and columns
 161:          /// in the matrix. N must be at least 0.
 162:          ///</param>
 163:          /// <param name="NCVT">
 164:          /// (input) INTEGER
 165:          /// On entry, NCVT specifies the number of columns of
 166:          /// the matrix VT. NCVT must be at least 0.
 167:          ///</param>
 168:          /// <param name="NRU">
 169:          /// (input) INTEGER
 170:          /// On entry, NRU specifies the number of rows of
 171:          /// the matrix U. NRU must be at least 0.
 172:          ///</param>
 173:          /// <param name="NCC">
 174:          /// (input) INTEGER
 175:          /// On entry, NCC specifies the number of columns of
 176:          /// the matrix C. NCC must be at least 0.
 177:          ///</param>
 178:          /// <param name="D">
 179:          /// (input/output) DOUBLE PRECISION array, dimension (N)
 180:          /// On entry, D contains the diagonal entries of the
 181:          /// bidiagonal matrix whose SVD is desired. On normal exit,
 182:          /// D contains the singular values in ascending order.
 183:          ///</param>
 184:          /// <param name="E">
 185:          /// (input/output) DOUBLE PRECISION array.
 186:          /// dimension is (N-1) if SQRE = 0 and N if SQRE = 1.
 187:          /// On entry, the entries of E contain the offdiagonal entries
 188:          /// of the bidiagonal matrix whose SVD is desired. On normal
 189:          /// exit, E will contain 0. If the algorithm does not converge,
 190:          /// D and E will contain the diagonal and superdiagonal entries
 191:          /// of a bidiagonal matrix orthogonally equivalent to the one
 192:          /// given as input.
 193:          ///</param>
 194:          /// <param name="VT">
 195:          /// (input/output) DOUBLE PRECISION array, dimension (LDVT, NCVT)
 196:          /// On entry, contains a matrix which on exit has been
 197:          /// premultiplied by P', dimension N-by-NCVT if SQRE = 0
 198:          /// and (N+1)-by-NCVT if SQRE = 1 (not referenced if NCVT=0).
 199:          ///</param>
 200:          /// <param name="LDVT">
 201:          /// (input) INTEGER
 202:          /// On entry, LDVT specifies the leading dimension of VT as
 203:          /// declared in the calling (sub) program. LDVT must be at
 204:          /// least 1. If NCVT is nonzero LDVT must also be at least N.
 205:          ///</param>
 206:          /// <param name="U">
 207:          /// (input/output) DOUBLE PRECISION array, dimension (LDU, N)
 208:          /// On entry, contains a  matrix which on exit has been
 209:          /// postmultiplied by Q, dimension NRU-by-N if SQRE = 0
 210:          /// and NRU-by-(N+1) if SQRE = 1 (not referenced if NRU=0).
 211:          ///</param>
 212:          /// <param name="LDU">
 213:          /// (input) INTEGER
 214:          /// On entry, LDU  specifies the leading dimension of U as
 215:          /// declared in the calling (sub) program. LDU must be at
 216:          /// least max( 1, NRU ) .
 217:          ///</param>
 218:          /// <param name="C">
 219:          /// (input/output) DOUBLE PRECISION array, dimension (LDC, NCC)
 220:          /// On entry, contains an N-by-NCC matrix which on exit
 221:          /// has been premultiplied by Q'  dimension N-by-NCC if SQRE = 0
 222:          /// and (N+1)-by-NCC if SQRE = 1 (not referenced if NCC=0).
 223:          ///</param>
 224:          /// <param name="LDC">
 225:          /// (input) INTEGER
 226:          /// On entry, LDC  specifies the leading dimension of C as
 227:          /// declared in the calling (sub) program. LDC must be at
 228:          /// least 1. If NCC is nonzero, LDC must also be at least N.
 229:          ///</param>
 230:          /// <param name="WORK">
 231:          /// (workspace) DOUBLE PRECISION array, dimension (4*N)
 232:          /// Workspace. Only referenced if one of NCVT, NRU, or NCC is
 233:          /// nonzero, and if N is at least 2.
 234:          ///</param>
 235:          /// <param name="INFO">
 236:          /// (output) INTEGER
 237:          /// On exit, a value of 0 indicates a successful exit.
 238:          /// If INFO .LT. 0, argument number -INFO is illegal.
 239:          /// If INFO .GT. 0, the algorithm did not converge, and INFO
 240:          /// specifies how many superdiagonals did not converge.
 241:          ///</param>
 242:          public void Run(string UPLO, int SQRE, int N, int NCVT, int NRU, int NCC
 243:                           , ref double[] D, int offset_d, ref double[] E, int offset_e, ref double[] VT, int offset_vt, int LDVT, ref double[] U, int offset_u, int LDU
 244:                           , ref double[] C, int offset_c, int LDC, ref double[] WORK, int offset_work, ref int INFO)
 245:          {
 246:   
 247:              #region Array Index Correction
 248:              
 249:               int o_d = -1 + offset_d;  int o_e = -1 + offset_e;  int o_vt = -1 - LDVT + offset_vt;  int o_u = -1 - LDU + offset_u; 
 250:               int o_c = -1 - LDC + offset_c; int o_work = -1 + offset_work; 
 251:   
 252:              #endregion
 253:   
 254:   
 255:              #region Strings
 256:              
 257:              UPLO = UPLO.Substring(0, 1);  
 258:   
 259:              #endregion
 260:   
 261:   
 262:              #region Prolog
 263:              
 264:              // *
 265:              // *  -- LAPACK auxiliary routine (version 3.1) --
 266:              // *     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd..
 267:              // *     November 2006
 268:              // *
 269:              // *     .. Scalar Arguments ..
 270:              // *     ..
 271:              // *     .. Array Arguments ..
 272:              // *     ..
 273:              // *
 274:              // *  Purpose
 275:              // *  =======
 276:              // *
 277:              // *  DLASDQ computes the singular value decomposition (SVD) of a real
 278:              // *  (upper or lower) bidiagonal matrix with diagonal D and offdiagonal
 279:              // *  E, accumulating the transformations if desired. Letting B denote
 280:              // *  the input bidiagonal matrix, the algorithm computes orthogonal
 281:              // *  matrices Q and P such that B = Q * S * P' (P' denotes the transpose
 282:              // *  of P). The singular values S are overwritten on D.
 283:              // *
 284:              // *  The input matrix U  is changed to U  * Q  if desired.
 285:              // *  The input matrix VT is changed to P' * VT if desired.
 286:              // *  The input matrix C  is changed to Q' * C  if desired.
 287:              // *
 288:              // *  See "Computing  Small Singular Values of Bidiagonal Matrices With
 289:              // *  Guaranteed High Relative Accuracy," by J. Demmel and W. Kahan,
 290:              // *  LAPACK Working Note #3, for a detailed description of the algorithm.
 291:              // *
 292:              // *  Arguments
 293:              // *  =========
 294:              // *
 295:              // *  UPLO  (input) CHARACTER*1
 296:              // *        On entry, UPLO specifies whether the input bidiagonal matrix
 297:              // *        is upper or lower bidiagonal, and wether it is square are
 298:              // *        not.
 299:              // *           UPLO = 'U' or 'u'   B is upper bidiagonal.
 300:              // *           UPLO = 'L' or 'l'   B is lower bidiagonal.
 301:              // *
 302:              // *  SQRE  (input) INTEGER
 303:              // *        = 0: then the input matrix is N-by-N.
 304:              // *        = 1: then the input matrix is N-by-(N+1) if UPLU = 'U' and
 305:              // *             (N+1)-by-N if UPLU = 'L'.
 306:              // *
 307:              // *        The bidiagonal matrix has
 308:              // *        N = NL + NR + 1 rows and
 309:              // *        M = N + SQRE >= N columns.
 310:              // *
 311:              // *  N     (input) INTEGER
 312:              // *        On entry, N specifies the number of rows and columns
 313:              // *        in the matrix. N must be at least 0.
 314:              // *
 315:              // *  NCVT  (input) INTEGER
 316:              // *        On entry, NCVT specifies the number of columns of
 317:              // *        the matrix VT. NCVT must be at least 0.
 318:              // *
 319:              // *  NRU   (input) INTEGER
 320:              // *        On entry, NRU specifies the number of rows of
 321:              // *        the matrix U. NRU must be at least 0.
 322:              // *
 323:              // *  NCC   (input) INTEGER
 324:              // *        On entry, NCC specifies the number of columns of
 325:              // *        the matrix C. NCC must be at least 0.
 326:              // *
 327:              // *  D     (input/output) DOUBLE PRECISION array, dimension (N)
 328:              // *        On entry, D contains the diagonal entries of the
 329:              // *        bidiagonal matrix whose SVD is desired. On normal exit,
 330:              // *        D contains the singular values in ascending order.
 331:              // *
 332:              // *  E     (input/output) DOUBLE PRECISION array.
 333:              // *        dimension is (N-1) if SQRE = 0 and N if SQRE = 1.
 334:              // *        On entry, the entries of E contain the offdiagonal entries
 335:              // *        of the bidiagonal matrix whose SVD is desired. On normal
 336:              // *        exit, E will contain 0. If the algorithm does not converge,
 337:              // *        D and E will contain the diagonal and superdiagonal entries
 338:              // *        of a bidiagonal matrix orthogonally equivalent to the one
 339:              // *        given as input.
 340:              // *
 341:              // *  VT    (input/output) DOUBLE PRECISION array, dimension (LDVT, NCVT)
 342:              // *        On entry, contains a matrix which on exit has been
 343:              // *        premultiplied by P', dimension N-by-NCVT if SQRE = 0
 344:              // *        and (N+1)-by-NCVT if SQRE = 1 (not referenced if NCVT=0).
 345:              // *
 346:              // *  LDVT  (input) INTEGER
 347:              // *        On entry, LDVT specifies the leading dimension of VT as
 348:              // *        declared in the calling (sub) program. LDVT must be at
 349:              // *        least 1. If NCVT is nonzero LDVT must also be at least N.
 350:              // *
 351:              // *  U     (input/output) DOUBLE PRECISION array, dimension (LDU, N)
 352:              // *        On entry, contains a  matrix which on exit has been
 353:              // *        postmultiplied by Q, dimension NRU-by-N if SQRE = 0
 354:              // *        and NRU-by-(N+1) if SQRE = 1 (not referenced if NRU=0).
 355:              // *
 356:              // *  LDU   (input) INTEGER
 357:              // *        On entry, LDU  specifies the leading dimension of U as
 358:              // *        declared in the calling (sub) program. LDU must be at
 359:              // *        least max( 1, NRU ) .
 360:              // *
 361:              // *  C     (input/output) DOUBLE PRECISION array, dimension (LDC, NCC)
 362:              // *        On entry, contains an N-by-NCC matrix which on exit
 363:              // *        has been premultiplied by Q'  dimension N-by-NCC if SQRE = 0
 364:              // *        and (N+1)-by-NCC if SQRE = 1 (not referenced if NCC=0).
 365:              // *
 366:              // *  LDC   (input) INTEGER
 367:              // *        On entry, LDC  specifies the leading dimension of C as
 368:              // *        declared in the calling (sub) program. LDC must be at
 369:              // *        least 1. If NCC is nonzero, LDC must also be at least N.
 370:              // *
 371:              // *  WORK  (workspace) DOUBLE PRECISION array, dimension (4*N)
 372:              // *        Workspace. Only referenced if one of NCVT, NRU, or NCC is
 373:              // *        nonzero, and if N is at least 2.
 374:              // *
 375:              // *  INFO  (output) INTEGER
 376:              // *        On exit, a value of 0 indicates a successful exit.
 377:              // *        If INFO < 0, argument number -INFO is illegal.
 378:              // *        If INFO > 0, the algorithm did not converge, and INFO
 379:              // *        specifies how many superdiagonals did not converge.
 380:              // *
 381:              // *  Further Details
 382:              // *  ===============
 383:              // *
 384:              // *  Based on contributions by
 385:              // *     Ming Gu and Huan Ren, Computer Science Division, University of
 386:              // *     California at Berkeley, USA
 387:              // *
 388:              // *  =====================================================================
 389:              // *
 390:              // *     .. Parameters ..
 391:              // *     ..
 392:              // *     .. Local Scalars ..
 393:              // *     ..
 394:              // *     .. External Subroutines ..
 395:              // *     ..
 396:              // *     .. External Functions ..
 397:              // *     ..
 398:              // *     .. Intrinsic Functions ..
 399:              //      INTRINSIC          MAX;
 400:              // *     ..
 401:              // *     .. Executable Statements ..
 402:              // *
 403:              // *     Test the input parameters.
 404:              // *
 405:   
 406:              #endregion
 407:   
 408:   
 409:              #region Body
 410:              
 411:              INFO = 0;
 412:              IUPLO = 0;
 413:              if (this._lsame.Run(UPLO, "U")) IUPLO = 1;
 414:              if (this._lsame.Run(UPLO, "L")) IUPLO = 2;
 415:              if (IUPLO == 0)
 416:              {
 417:                  INFO =  - 1;
 418:              }
 419:              else
 420:              {
 421:                  if ((SQRE < 0) || (SQRE > 1))
 422:                  {
 423:                      INFO =  - 2;
 424:                  }
 425:                  else
 426:                  {
 427:                      if (N < 0)
 428:                      {
 429:                          INFO =  - 3;
 430:                      }
 431:                      else
 432:                      {
 433:                          if (NCVT < 0)
 434:                          {
 435:                              INFO =  - 4;
 436:                          }
 437:                          else
 438:                          {
 439:                              if (NRU < 0)
 440:                              {
 441:                                  INFO =  - 5;
 442:                              }
 443:                              else
 444:                              {
 445:                                  if (NCC < 0)
 446:                                  {
 447:                                      INFO =  - 6;
 448:                                  }
 449:                                  else
 450:                                  {
 451:                                      if ((NCVT == 0 && LDVT < 1) || (NCVT > 0 && LDVT < Math.Max(1, N)))
 452:                                      {
 453:                                          INFO =  - 10;
 454:                                      }
 455:                                      else
 456:                                      {
 457:                                          if (LDU < Math.Max(1, NRU))
 458:                                          {
 459:                                              INFO =  - 12;
 460:                                          }
 461:                                          else
 462:                                          {
 463:                                              if ((NCC == 0 && LDC < 1) || (NCC > 0 && LDC < Math.Max(1, N)))
 464:                                              {
 465:                                                  INFO =  - 14;
 466:                                              }
 467:                                          }
 468:                                      }
 469:                                  }
 470:                              }
 471:                          }
 472:                      }
 473:                  }
 474:              }
 475:              if (INFO != 0)
 476:              {
 477:                  this._xerbla.Run("DLASDQ",  - INFO);
 478:                  return;
 479:              }
 480:              if (N == 0) return;
 481:              // *
 482:              // *     ROTATE is true if any singular vectors desired, false otherwise
 483:              // *
 484:              ROTATE = (NCVT > 0) || (NRU > 0) || (NCC > 0);
 485:              NP1 = N + 1;
 486:              SQRE1 = SQRE;
 487:              // *
 488:              // *     If matrix non-square upper bidiagonal, rotate to be lower
 489:              // *     bidiagonal.  The rotations are on the right.
 490:              // *
 491:              if ((IUPLO == 1) && (SQRE1 == 1))
 492:              {
 493:                  for (I = 1; I <= N - 1; I++)
 494:                  {
 495:                      this._dlartg.Run(D[I + o_d], E[I + o_e], ref CS, ref SN, ref R);
 496:                      D[I + o_d] = R;
 497:                      E[I + o_e] = SN * D[I + 1 + o_d];
 498:                      D[I + 1 + o_d] = CS * D[I + 1 + o_d];
 499:                      if (ROTATE)
 500:                      {
 501:                          WORK[I + o_work] = CS;
 502:                          WORK[N + I + o_work] = SN;
 503:                      }
 504:                  }
 505:                  this._dlartg.Run(D[N + o_d], E[N + o_e], ref CS, ref SN, ref R);
 506:                  D[N + o_d] = R;
 507:                  E[N + o_e] = ZERO;
 508:                  if (ROTATE)
 509:                  {
 510:                      WORK[N + o_work] = CS;
 511:                      WORK[N + N + o_work] = SN;
 512:                  }
 513:                  IUPLO = 2;
 514:                  SQRE1 = 0;
 515:                  // *
 516:                  // *        Update singular vectors if desired.
 517:                  // *
 518:                  if (NCVT > 0)
 519:                  {
 520:                      this._dlasr.Run("L", "V", "F", NP1, NCVT, WORK, 1 + o_work
 521:                                      , WORK, NP1 + o_work, ref VT, offset_vt, LDVT);
 522:                  }
 523:              }
 524:              // *
 525:              // *     If matrix lower bidiagonal, rotate to be upper bidiagonal
 526:              // *     by applying Givens rotations on the left.
 527:              // *
 528:              if (IUPLO == 2)
 529:              {
 530:                  for (I = 1; I <= N - 1; I++)
 531:                  {
 532:                      this._dlartg.Run(D[I + o_d], E[I + o_e], ref CS, ref SN, ref R);
 533:                      D[I + o_d] = R;
 534:                      E[I + o_e] = SN * D[I + 1 + o_d];
 535:                      D[I + 1 + o_d] = CS * D[I + 1 + o_d];
 536:                      if (ROTATE)
 537:                      {
 538:                          WORK[I + o_work] = CS;
 539:                          WORK[N + I + o_work] = SN;
 540:                      }
 541:                  }
 542:                  // *
 543:                  // *        If matrix (N+1)-by-N lower bidiagonal, one additional
 544:                  // *        rotation is needed.
 545:                  // *
 546:                  if (SQRE1 == 1)
 547:                  {
 548:                      this._dlartg.Run(D[N + o_d], E[N + o_e], ref CS, ref SN, ref R);
 549:                      D[N + o_d] = R;
 550:                      if (ROTATE)
 551:                      {
 552:                          WORK[N + o_work] = CS;
 553:                          WORK[N + N + o_work] = SN;
 554:                      }
 555:                  }
 556:                  // *
 557:                  // *        Update singular vectors if desired.
 558:                  // *
 559:                  if (NRU > 0)
 560:                  {
 561:                      if (SQRE1 == 0)
 562:                      {
 563:                          this._dlasr.Run("R", "V", "F", NRU, N, WORK, 1 + o_work
 564:                                          , WORK, NP1 + o_work, ref U, offset_u, LDU);
 565:                      }
 566:                      else
 567:                      {
 568:                          this._dlasr.Run("R", "V", "F", NRU, NP1, WORK, 1 + o_work
 569:                                          , WORK, NP1 + o_work, ref U, offset_u, LDU);
 570:                      }
 571:                  }
 572:                  if (NCC > 0)
 573:                  {
 574:                      if (SQRE1 == 0)
 575:                      {
 576:                          this._dlasr.Run("L", "V", "F", N, NCC, WORK, 1 + o_work
 577:                                          , WORK, NP1 + o_work, ref C, offset_c, LDC);
 578:                      }
 579:                      else
 580:                      {
 581:                          this._dlasr.Run("L", "V", "F", NP1, NCC, WORK, 1 + o_work
 582:                                          , WORK, NP1 + o_work, ref C, offset_c, LDC);
 583:                      }
 584:                  }
 585:              }
 586:              // *
 587:              // *     Call DBDSQR to compute the SVD of the reduced real
 588:              // *     N-by-N upper bidiagonal matrix.
 589:              // *
 590:              this._dbdsqr.Run("U", N, NCVT, NRU, NCC, ref D, offset_d
 591:                               , ref E, offset_e, ref VT, offset_vt, LDVT, ref U, offset_u, LDU, ref C, offset_c
 592:                               , LDC, ref WORK, offset_work, ref INFO);
 593:              // *
 594:              // *     Sort the singular values into ascending order (insertion sort on
 595:              // *     singular values, but only one transposition per singular vector)
 596:              // *
 597:              for (I = 1; I <= N; I++)
 598:              {
 599:                  // *
 600:                  // *        Scan for smallest D(I).
 601:                  // *
 602:                  ISUB = I;
 603:                  SMIN = D[I + o_d];
 604:                  for (J = I + 1; J <= N; J++)
 605:                  {
 606:                      if (D[J + o_d] < SMIN)
 607:                      {
 608:                          ISUB = J;
 609:                          SMIN = D[J + o_d];
 610:                      }
 611:                  }
 612:                  if (ISUB != I)
 613:                  {
 614:                      // *
 615:                      // *           Swap singular values and vectors.
 616:                      // *
 617:                      D[ISUB + o_d] = D[I + o_d];
 618:                      D[I + o_d] = SMIN;
 619:                      if (NCVT > 0) this._dswap.Run(NCVT, ref VT, ISUB+1 * LDVT + o_vt, LDVT, ref VT, I+1 * LDVT + o_vt, LDVT);
 620:                      if (NRU > 0) this._dswap.Run(NRU, ref U, 1+ISUB * LDU + o_u, 1, ref U, 1+I * LDU + o_u, 1);
 621:                      if (NCC > 0) this._dswap.Run(NCC, ref C, ISUB+1 * LDC + o_c, LDC, ref C, I+1 * LDC + o_c, LDC);
 622:                  }
 623:              }
 624:              // *
 625:              return;
 626:              // *
 627:              // *     End of DLASDQ
 628:              // *
 629:   
 630:              #endregion
 631:   
 632:          }
 633:      }
 634:  }