201
202
203
204
205
206
207 INTEGER INFO, LDA, LDB, LWORK, M, N, NRHS, RANK
208 DOUBLE PRECISION RCOND
209
210
211 INTEGER IWORK( * )
212 DOUBLE PRECISION A( LDA, * ), B( LDB, * ), S( * ), WORK( * )
213
214
215
216
217
218 DOUBLE PRECISION ZERO, ONE, TWO
219 parameter( zero = 0.0d0, one = 1.0d0, two = 2.0d0 )
220
221
222 LOGICAL LQUERY
223 INTEGER IASCL, IBSCL, IE, IL, ITAU, ITAUP, ITAUQ,
224 $ LDWORK, LIWORK, MAXMN, MAXWRK, MINMN, MINWRK,
225 $ MM, MNTHR, NLVL, NWORK, SMLSIZ, WLALSD
226 DOUBLE PRECISION ANRM, BIGNUM, BNRM, EPS, SFMIN, SMLNUM
227
228
232
233
234 INTEGER ILAENV
235 DOUBLE PRECISION DLAMCH, DLANGE
237
238
239 INTRINSIC dble, int, log, max, min
240
241
242
243
244
245 info = 0
246 minmn = min( m, n )
247 maxmn = max( m, n )
248 mnthr =
ilaenv( 6,
'DGELSD',
' ', m, n, nrhs, -1 )
249 lquery = ( lwork.EQ.-1 )
250 IF( m.LT.0 ) THEN
251 info = -1
252 ELSE IF( n.LT.0 ) THEN
253 info = -2
254 ELSE IF( nrhs.LT.0 ) THEN
255 info = -3
256 ELSE IF( lda.LT.max( 1, m ) ) THEN
257 info = -5
258 ELSE IF( ldb.LT.max( 1, maxmn ) ) THEN
259 info = -7
260 END IF
261
262 smlsiz =
ilaenv( 9,
'DGELSD',
' ', 0, 0, 0, 0 )
263
264
265
266
267
268
269
270
271 minwrk = 1
272 liwork = 1
273 minmn = max( 1, minmn )
274 nlvl = max( int( log( dble( minmn ) / dble( smlsiz+1 ) ) /
275 $ log( two ) ) + 1, 0 )
276
277 IF( info.EQ.0 ) THEN
278 maxwrk = 1
279 liwork = 3*minmn*nlvl + 11*minmn
280 mm = m
281 IF( m.GE.n .AND. m.GE.mnthr ) THEN
282
283
284
285 mm = n
286 maxwrk = max( maxwrk, n+n*
ilaenv( 1,
'DGEQRF',
' ', m, n,
287 $ -1, -1 ) )
288 maxwrk = max( maxwrk, n+nrhs*
289 $
ilaenv( 1,
'DORMQR',
'LT', m, nrhs, n, -1 ) )
290 END IF
291 IF( m.GE.n ) THEN
292
293
294
295 maxwrk = max( maxwrk, 3*n+( mm+n )*
296 $
ilaenv( 1,
'DGEBRD',
' ', mm, n, -1, -1 ) )
297 maxwrk = max( maxwrk, 3*n+nrhs*
298 $
ilaenv( 1,
'DORMBR',
'QLT', mm, nrhs, n, -1 ) )
299 maxwrk = max( maxwrk, 3*n+( n-1 )*
300 $
ilaenv( 1,
'DORMBR',
'PLN', n, nrhs, n, -1 ) )
301 wlalsd = 9*n+2*n*smlsiz+8*n*nlvl+n*nrhs+(smlsiz+1)**2
302 maxwrk = max( maxwrk, 3*n+wlalsd )
303 minwrk = max( 3*n+mm, 3*n+nrhs, 3*n+wlalsd )
304 END IF
305 IF( n.GT.m ) THEN
306 wlalsd = 9*m+2*m*smlsiz+8*m*nlvl+m*nrhs+(smlsiz+1)**2
307 IF( n.GE.mnthr ) THEN
308
309
310
311
312 maxwrk = m + m*
ilaenv( 1,
'DGELQF',
' ', m, n, -1,
313 $ -1 )
314 maxwrk = max( maxwrk, m*m+4*m+2*m*
315 $
ilaenv( 1,
'DGEBRD',
' ', m, m, -1, -1 ) )
316 maxwrk = max( maxwrk, m*m+4*m+nrhs*
317 $
ilaenv( 1,
'DORMBR',
'QLT', m, nrhs, m,
318 $ -1 ) )
319 maxwrk = max( maxwrk, m*m+4*m+( m-1 )*
320 $
ilaenv( 1,
'DORMBR',
'PLN', m, nrhs, m,
321 $ -1 ) )
322 IF( nrhs.GT.1 ) THEN
323 maxwrk = max( maxwrk, m*m+m+m*nrhs )
324 ELSE
325 maxwrk = max( maxwrk, m*m+2*m )
326 END IF
327 maxwrk = max( maxwrk, m+nrhs*
328 $
ilaenv( 1,
'DORMLQ',
'LT', n, nrhs, m, -1 ) )
329 maxwrk = max( maxwrk, m*m+4*m+wlalsd )
330
331
332 maxwrk = max( maxwrk,
333 $ 4*m+m*m+max( m, 2*m-4, nrhs, n-3*m ) )
334 ELSE
335
336
337
338 maxwrk = 3*m + ( n+m )*
ilaenv( 1,
'DGEBRD',
' ', m, n,
339 $ -1, -1 )
340 maxwrk = max( maxwrk, 3*m+nrhs*
341 $
ilaenv( 1,
'DORMBR',
'QLT', m, nrhs, n,
342 $ -1 ) )
343 maxwrk = max( maxwrk, 3*m+m*
344 $
ilaenv( 1,
'DORMBR',
'PLN', n, nrhs, m,
345 $ -1 ) )
346 maxwrk = max( maxwrk, 3*m+wlalsd )
347 END IF
348 minwrk = max( 3*m+nrhs, 3*m+m, 3*m+wlalsd )
349 END IF
350 minwrk = min( minwrk, maxwrk )
351 work( 1 ) = maxwrk
352 iwork( 1 ) = liwork
353
354 IF( lwork.LT.minwrk .AND. .NOT.lquery ) THEN
355 info = -12
356 END IF
357 END IF
358
359 IF( info.NE.0 ) THEN
360 CALL xerbla(
'DGELSD', -info )
361 RETURN
362 ELSE IF( lquery ) THEN
363 GO TO 10
364 END IF
365
366
367
368 IF( m.EQ.0 .OR. n.EQ.0 ) THEN
369 rank = 0
370 RETURN
371 END IF
372
373
374
377 smlnum = sfmin / eps
378 bignum = one / smlnum
379
380
381
382 anrm =
dlange(
'M', m, n, a, lda, work )
383 iascl = 0
384 IF( anrm.GT.zero .AND. anrm.LT.smlnum ) THEN
385
386
387
388 CALL dlascl(
'G', 0, 0, anrm, smlnum, m, n, a, lda, info )
389 iascl = 1
390 ELSE IF( anrm.GT.bignum ) THEN
391
392
393
394 CALL dlascl(
'G', 0, 0, anrm, bignum, m, n, a, lda, info )
395 iascl = 2
396 ELSE IF( anrm.EQ.zero ) THEN
397
398
399
400 CALL dlaset(
'F', max( m, n ), nrhs, zero, zero, b, ldb )
401 CALL dlaset(
'F', minmn, 1, zero, zero, s, 1 )
402 rank = 0
403 GO TO 10
404 END IF
405
406
407
408 bnrm =
dlange(
'M', m, nrhs, b, ldb, work )
409 ibscl = 0
410 IF( bnrm.GT.zero .AND. bnrm.LT.smlnum ) THEN
411
412
413
414 CALL dlascl(
'G', 0, 0, bnrm, smlnum, m, nrhs, b, ldb,
415 $ info )
416 ibscl = 1
417 ELSE IF( bnrm.GT.bignum ) THEN
418
419
420
421 CALL dlascl(
'G', 0, 0, bnrm, bignum, m, nrhs, b, ldb,
422 $ info )
423 ibscl = 2
424 END IF
425
426
427
428 IF( m.LT.n )
429 $
CALL dlaset(
'F', n-m, nrhs, zero, zero, b( m+1, 1 ), ldb )
430
431
432
433 IF( m.GE.n ) THEN
434
435
436
437 mm = m
438 IF( m.GE.mnthr ) THEN
439
440
441
442 mm = n
443 itau = 1
444 nwork = itau + n
445
446
447
448
449 CALL dgeqrf( m, n, a, lda, work( itau ), work( nwork ),
450 $ lwork-nwork+1, info )
451
452
453
454
455 CALL dormqr(
'L',
'T', m, nrhs, n, a, lda, work( itau ),
456 $ b,
457 $ ldb, work( nwork ), lwork-nwork+1, info )
458
459
460
461 IF( n.GT.1 ) THEN
462 CALL dlaset(
'L', n-1, n-1, zero, zero, a( 2, 1 ),
463 $ lda )
464 END IF
465 END IF
466
467 ie = 1
468 itauq = ie + n
469 itaup = itauq + n
470 nwork = itaup + n
471
472
473
474
475 CALL dgebrd( mm, n, a, lda, s, work( ie ), work( itauq ),
476 $ work( itaup ), work( nwork ), lwork-nwork+1,
477 $ info )
478
479
480
481
482 CALL dormbr(
'Q',
'L',
'T', mm, nrhs, n, a, lda,
483 $ work( itauq ),
484 $ b, ldb, work( nwork ), lwork-nwork+1, info )
485
486
487
488 CALL dlalsd(
'U', smlsiz, n, nrhs, s, work( ie ), b, ldb,
489 $ rcond, rank, work( nwork ), iwork, info )
490 IF( info.NE.0 ) THEN
491 GO TO 10
492 END IF
493
494
495
496 CALL dormbr(
'P',
'L',
'N', n, nrhs, n, a, lda,
497 $ work( itaup ),
498 $ b, ldb, work( nwork ), lwork-nwork+1, info )
499
500 ELSE IF( n.GE.mnthr .AND. lwork.GE.4*m+m*m+
501 $ max( m, 2*m-4, nrhs, n-3*m, wlalsd ) ) THEN
502
503
504
505
506 ldwork = m
507 IF( lwork.GE.max( 4*m+m*lda+max( m, 2*m-4, nrhs, n-3*m ),
508 $ m*lda+m+m*nrhs, 4*m+m*lda+wlalsd ) )ldwork = lda
509 itau = 1
510 nwork = m + 1
511
512
513
514
515 CALL dgelqf( m, n, a, lda, work( itau ), work( nwork ),
516 $ lwork-nwork+1, info )
517 il = nwork
518
519
520
521 CALL dlacpy(
'L', m, m, a, lda, work( il ), ldwork )
522 CALL dlaset(
'U', m-1, m-1, zero, zero, work( il+ldwork ),
523 $ ldwork )
524 ie = il + ldwork*m
525 itauq = ie + m
526 itaup = itauq + m
527 nwork = itaup + m
528
529
530
531
532 CALL dgebrd( m, m, work( il ), ldwork, s, work( ie ),
533 $ work( itauq ), work( itaup ), work( nwork ),
534 $ lwork-nwork+1, info )
535
536
537
538
539 CALL dormbr(
'Q',
'L',
'T', m, nrhs, m, work( il ), ldwork,
540 $ work( itauq ), b, ldb, work( nwork ),
541 $ lwork-nwork+1, info )
542
543
544
545 CALL dlalsd(
'U', smlsiz, m, nrhs, s, work( ie ), b, ldb,
546 $ rcond, rank, work( nwork ), iwork, info )
547 IF( info.NE.0 ) THEN
548 GO TO 10
549 END IF
550
551
552
553 CALL dormbr(
'P',
'L',
'N', m, nrhs, m, work( il ), ldwork,
554 $ work( itaup ), b, ldb, work( nwork ),
555 $ lwork-nwork+1, info )
556
557
558
559 CALL dlaset(
'F', n-m, nrhs, zero, zero, b( m+1, 1 ), ldb )
560 nwork = itau + m
561
562
563
564
565 CALL dormlq(
'L',
'T', n, nrhs, m, a, lda, work( itau ), b,
566 $ ldb, work( nwork ), lwork-nwork+1, info )
567
568 ELSE
569
570
571
572 ie = 1
573 itauq = ie + m
574 itaup = itauq + m
575 nwork = itaup + m
576
577
578
579
580 CALL dgebrd( m, n, a, lda, s, work( ie ), work( itauq ),
581 $ work( itaup ), work( nwork ), lwork-nwork+1,
582 $ info )
583
584
585
586
587 CALL dormbr(
'Q',
'L',
'T', m, nrhs, n, a, lda,
588 $ work( itauq ),
589 $ b, ldb, work( nwork ), lwork-nwork+1, info )
590
591
592
593 CALL dlalsd(
'L', smlsiz, m, nrhs, s, work( ie ), b, ldb,
594 $ rcond, rank, work( nwork ), iwork, info )
595 IF( info.NE.0 ) THEN
596 GO TO 10
597 END IF
598
599
600
601 CALL dormbr(
'P',
'L',
'N', n, nrhs, m, a, lda,
602 $ work( itaup ),
603 $ b, ldb, work( nwork ), lwork-nwork+1, info )
604
605 END IF
606
607
608
609 IF( iascl.EQ.1 ) THEN
610 CALL dlascl(
'G', 0, 0, anrm, smlnum, n, nrhs, b, ldb,
611 $ info )
612 CALL dlascl(
'G', 0, 0, smlnum, anrm, minmn, 1, s, minmn,
613 $ info )
614 ELSE IF( iascl.EQ.2 ) THEN
615 CALL dlascl(
'G', 0, 0, anrm, bignum, n, nrhs, b, ldb,
616 $ info )
617 CALL dlascl(
'G', 0, 0, bignum, anrm, minmn, 1, s, minmn,
618 $ info )
619 END IF
620 IF( ibscl.EQ.1 ) THEN
621 CALL dlascl(
'G', 0, 0, smlnum, bnrm, n, nrhs, b, ldb,
622 $ info )
623 ELSE IF( ibscl.EQ.2 ) THEN
624 CALL dlascl(
'G', 0, 0, bignum, bnrm, n, nrhs, b, ldb,
625 $ info )
626 END IF
627
628 10 CONTINUE
629 work( 1 ) = maxwrk
630 iwork( 1 ) = liwork
631 RETURN
632
633
634
subroutine xerbla(srname, info)
subroutine dgebrd(m, n, a, lda, d, e, tauq, taup, work, lwork, info)
DGEBRD
subroutine dgelqf(m, n, a, lda, tau, work, lwork, info)
DGELQF
subroutine dgeqrf(m, n, a, lda, tau, work, lwork, info)
DGEQRF
integer function ilaenv(ispec, name, opts, n1, n2, n3, n4)
ILAENV
subroutine dlacpy(uplo, m, n, a, lda, b, ldb)
DLACPY copies all or part of one two-dimensional array to another.
subroutine dlalsd(uplo, smlsiz, n, nrhs, d, e, b, ldb, rcond, rank, work, iwork, info)
DLALSD uses the singular value decomposition of A to solve the least squares problem.
double precision function dlamch(cmach)
DLAMCH
double precision function dlange(norm, m, n, a, lda, work)
DLANGE returns the value of the 1-norm, Frobenius norm, infinity-norm, or the largest absolute value ...
subroutine dlascl(type, kl, ku, cfrom, cto, m, n, a, lda, info)
DLASCL multiplies a general rectangular matrix by a real scalar defined as cto/cfrom.
subroutine dlaset(uplo, m, n, alpha, beta, a, lda)
DLASET initializes the off-diagonal elements and the diagonal elements of a matrix to given values.
subroutine dormbr(vect, side, trans, m, n, k, a, lda, tau, c, ldc, work, lwork, info)
DORMBR
subroutine dormlq(side, trans, m, n, k, a, lda, tau, c, ldc, work, lwork, info)
DORMLQ
subroutine dormqr(side, trans, m, n, k, a, lda, tau, c, ldc, work, lwork, info)
DORMQR