229
230
231
232
233
234
235 INTEGER LDX, LDU1, LDU2, LDV1T, LDV2T, LWORK, M, P, Q
236
237
238 INTEGER IWORK( * )
239 DOUBLE PRECISION RESULT( 15 ), RWORK( * ), THETA( * )
240 COMPLEX*16 U1( LDU1, * ), U2( LDU2, * ), V1T( LDV1T, * ),
241 $ V2T( LDV2T, * ), WORK( LWORK ), X( LDX, * ),
242 $ XF( LDX, * )
243
244
245
246
247
248 DOUBLE PRECISION REALONE, REALZERO
249 parameter( realone = 1.0d0, realzero = 0.0d0 )
250 COMPLEX*16 ZERO, ONE
251 parameter( zero = (0.0d0,0.0d0), one = (1.0d0,0.0d0) )
252 DOUBLE PRECISION PIOVER2
253 parameter( piover2 = 1.57079632679489661923132169163975144210d0 )
254
255
256 INTEGER I, INFO, R
257 DOUBLE PRECISION EPS2, RESID, ULP, ULPINV
258
259
260 DOUBLE PRECISION DLAMCH, ZLANGE, ZLANHE
262
263
266
267
268 INTRINSIC cos, dble, dcmplx, max, min, real, sin
269
270
271
272 ulp =
dlamch(
'Precision' )
273 ulpinv = realone / ulp
274
275
276
277 CALL zlaset(
'Full', m, m, zero, one, work, ldx )
278 CALL zherk(
'Upper',
'Conjugate transpose', m, m, -realone,
279 $ x, ldx, realone, work, ldx )
280 IF (m.GT.0) THEN
281 eps2 = max( ulp,
282 $
zlange(
'1', m, m, work, ldx, rwork ) / dble( m ) )
283 ELSE
284 eps2 = ulp
285 END IF
286 r = min( p, m-p, q, m-q )
287
288
289
290 CALL zlacpy(
'Full', m, m, x, ldx, xf, ldx )
291
292
293
294 CALL zuncsd(
'Y',
'Y',
'Y',
'Y',
'N',
'D', m, p, q, xf(1,1), ldx,
295 $ xf(1,q+1), ldx, xf(p+1,1), ldx, xf(p+1,q+1), ldx,
296 $ theta, u1, ldu1, u2, ldu2, v1t, ldv1t, v2t, ldv2t,
297 $ work, lwork, rwork, 17*(r+2), iwork, info )
298
299
300
301 CALL zlacpy(
'Full', m, m, x, ldx, xf, ldx )
302
303 CALL zgemm(
'No transpose',
'Conjugate transpose', p, q, q, one,
304 $ xf, ldx, v1t, ldv1t, zero, work, ldx )
305
306 CALL zgemm(
'Conjugate transpose',
'No transpose', p, q, p, one,
307 $ u1, ldu1, work, ldx, zero, xf, ldx )
308
309 DO i = 1, min(p,q)-r
310 xf(i,i) = xf(i,i) - one
311 END DO
312 DO i = 1, r
313 xf(min(p,q)-r+i,min(p,q)-r+i) =
314 $ xf(min(p,q)-r+i,min(p,q)-r+i) - dcmplx( cos(theta(i)),
315 $ 0.0d0 )
316 END DO
317
318 CALL zgemm(
'No transpose',
'Conjugate transpose', p, m-q, m-q,
319 $ one, xf(1,q+1), ldx, v2t, ldv2t, zero, work, ldx )
320
321 CALL zgemm(
'Conjugate transpose',
'No transpose', p, m-q, p,
322 $ one, u1, ldu1, work, ldx, zero, xf(1,q+1), ldx )
323
324 DO i = 1, min(p,m-q)-r
325 xf(p-i+1,m-i+1) = xf(p-i+1,m-i+1) + one
326 END DO
327 DO i = 1, r
328 xf(p-(min(p,m-q)-r)+1-i,m-(min(p,m-q)-r)+1-i) =
329 $ xf(p-(min(p,m-q)-r)+1-i,m-(min(p,m-q)-r)+1-i) +
330 $ dcmplx( sin(theta(r-i+1)), 0.0d0 )
331 END DO
332
333 CALL zgemm(
'No transpose',
'Conjugate transpose', m-p, q, q, one,
334 $ xf(p+1,1), ldx, v1t, ldv1t, zero, work, ldx )
335
336 CALL zgemm(
'Conjugate transpose',
'No transpose', m-p, q, m-p,
337 $ one, u2, ldu2, work, ldx, zero, xf(p+1,1), ldx )
338
339 DO i = 1, min(m-p,q)-r
340 xf(m-i+1,q-i+1) = xf(m-i+1,q-i+1) - one
341 END DO
342 DO i = 1, r
343 xf(m-(min(m-p,q)-r)+1-i,q-(min(m-p,q)-r)+1-i) =
344 $ xf(m-(min(m-p,q)-r)+1-i,q-(min(m-p,q)-r)+1-i) -
345 $ dcmplx( sin(theta(r-i+1)), 0.0d0 )
346 END DO
347
348 CALL zgemm(
'No transpose',
'Conjugate transpose', m-p, m-q, m-q,
349 $ one, xf(p+1,q+1), ldx, v2t, ldv2t, zero, work, ldx )
350
351 CALL zgemm(
'Conjugate transpose',
'No transpose', m-p, m-q, m-p,
352 $ one, u2, ldu2, work, ldx, zero, xf(p+1,q+1), ldx )
353
354 DO i = 1, min(m-p,m-q)-r
355 xf(p+i,q+i) = xf(p+i,q+i) - one
356 END DO
357 DO i = 1, r
358 xf(p+(min(m-p,m-q)-r)+i,q+(min(m-p,m-q)-r)+i) =
359 $ xf(p+(min(m-p,m-q)-r)+i,q+(min(m-p,m-q)-r)+i) -
360 $ dcmplx( cos(theta(i)), 0.0d0 )
361 END DO
362
363
364
365 resid =
zlange(
'1', p, q, xf, ldx, rwork )
366 result( 1 ) = ( resid / real(max(1,p,q)) ) / eps2
367
368
369
370 resid =
zlange(
'1', p, m-q, xf(1,q+1), ldx, rwork )
371 result( 2 ) = ( resid / real(max(1,p,m-q)) ) / eps2
372
373
374
375 resid =
zlange(
'1', m-p, q, xf(p+1,1), ldx, rwork )
376 result( 3 ) = ( resid / real(max(1,m-p,q)) ) / eps2
377
378
379
380 resid =
zlange(
'1', m-p, m-q, xf(p+1,q+1), ldx, rwork )
381 result( 4 ) = ( resid / real(max(1,m-p,m-q)) ) / eps2
382
383
384
385 CALL zlaset(
'Full', p, p, zero, one, work, ldu1 )
386 CALL zherk(
'Upper',
'Conjugate transpose', p, p, -realone,
387 $ u1, ldu1, realone, work, ldu1 )
388
389
390
391 resid =
zlanhe(
'1',
'Upper', p, work, ldu1, rwork )
392 result( 5 ) = ( resid / real(max(1,p)) ) / ulp
393
394
395
396 CALL zlaset(
'Full', m-p, m-p, zero, one, work, ldu2 )
397 CALL zherk(
'Upper',
'Conjugate transpose', m-p, m-p, -realone,
398 $ u2, ldu2, realone, work, ldu2 )
399
400
401
402 resid =
zlanhe(
'1',
'Upper', m-p, work, ldu2, rwork )
403 result( 6 ) = ( resid / real(max(1,m-p)) ) / ulp
404
405
406
407 CALL zlaset(
'Full', q, q, zero, one, work, ldv1t )
408 CALL zherk(
'Upper',
'No transpose', q, q, -realone,
409 $ v1t, ldv1t, realone, work, ldv1t )
410
411
412
413 resid =
zlanhe(
'1',
'Upper', q, work, ldv1t, rwork )
414 result( 7 ) = ( resid / real(max(1,q)) ) / ulp
415
416
417
418 CALL zlaset(
'Full', m-q, m-q, zero, one, work, ldv2t )
419 CALL zherk(
'Upper',
'No transpose', m-q, m-q, -realone,
420 $ v2t, ldv2t, realone, work, ldv2t )
421
422
423
424 resid =
zlanhe(
'1',
'Upper', m-q, work, ldv2t, rwork )
425 result( 8 ) = ( resid / real(max(1,m-q)) ) / ulp
426
427
428
429 result( 9 ) = realzero
430 DO i = 1, r
431 IF( theta(i).LT.realzero .OR. theta(i).GT.piover2 ) THEN
432 result( 9 ) = ulpinv
433 END IF
434 IF( i.GT.1) THEN
435 IF ( theta(i).LT.theta(i-1) ) THEN
436 result( 9 ) = ulpinv
437 END IF
438 END IF
439 END DO
440
441
442
443 CALL zlaset(
'Full', q, q, zero, one, work, ldx )
444 CALL zherk(
'Upper',
'Conjugate transpose', q, m, -realone,
445 $ x, ldx, realone, work, ldx )
446 IF (m.GT.0) THEN
447 eps2 = max( ulp,
448 $
zlange(
'1', q, q, work, ldx, rwork ) / dble( m ) )
449 ELSE
450 eps2 = ulp
451 END IF
452 r = min( p, m-p, q, m-q )
453
454
455
456 CALL zlacpy(
'Full', m, m, x, ldx, xf, ldx )
457
458
459
460 CALL zuncsd2by1(
'Y',
'Y',
'Y', m, p, q, xf(1,1), ldx, xf(p+1,1),
461 $ ldx, theta, u1, ldu1, u2, ldu2, v1t, ldv1t, work,
462 $ lwork, rwork, 17*(r+2), iwork, info )
463
464
465
466 CALL zgemm(
'No transpose',
'Conjugate transpose', p, q, q, one,
467 $ x, ldx, v1t, ldv1t, zero, work, ldx )
468
469 CALL zgemm(
'Conjugate transpose',
'No transpose', p, q, p, one,
470 $ u1, ldu1, work, ldx, zero, x, ldx )
471
472 DO i = 1, min(p,q)-r
473 x(i,i) = x(i,i) - one
474 END DO
475 DO i = 1, r
476 x(min(p,q)-r+i,min(p,q)-r+i) =
477 $ x(min(p,q)-r+i,min(p,q)-r+i) - dcmplx( cos(theta(i)),
478 $ 0.0d0 )
479 END DO
480
481 CALL zgemm(
'No transpose',
'Conjugate transpose', m-p, q, q, one,
482 $ x(p+1,1), ldx, v1t, ldv1t, zero, work, ldx )
483
484 CALL zgemm(
'Conjugate transpose',
'No transpose', m-p, q, m-p,
485 $ one, u2, ldu2, work, ldx, zero, x(p+1,1), ldx )
486
487 DO i = 1, min(m-p,q)-r
488 x(m-i+1,q-i+1) = x(m-i+1,q-i+1) - one
489 END DO
490 DO i = 1, r
491 x(m-(min(m-p,q)-r)+1-i,q-(min(m-p,q)-r)+1-i) =
492 $ x(m-(min(m-p,q)-r)+1-i,q-(min(m-p,q)-r)+1-i) -
493 $ dcmplx( sin(theta(r-i+1)), 0.0d0 )
494 END DO
495
496
497
498 resid =
zlange(
'1', p, q, x, ldx, rwork )
499 result( 10 ) = ( resid / real(max(1,p,q)) ) / eps2
500
501
502
503 resid =
zlange(
'1', m-p, q, x(p+1,1), ldx, rwork )
504 result( 11 ) = ( resid / real(max(1,m-p,q)) ) / eps2
505
506
507
508 CALL zlaset(
'Full', p, p, zero, one, work, ldu1 )
509 CALL zherk(
'Upper',
'Conjugate transpose', p, p, -realone,
510 $ u1, ldu1, realone, work, ldu1 )
511
512
513
514 resid =
zlanhe(
'1',
'Upper', p, work, ldu1, rwork )
515 result( 12 ) = ( resid / real(max(1,p)) ) / ulp
516
517
518
519 CALL zlaset(
'Full', m-p, m-p, zero, one, work, ldu2 )
520 CALL zherk(
'Upper',
'Conjugate transpose', m-p, m-p, -realone,
521 $ u2, ldu2, realone, work, ldu2 )
522
523
524
525 resid =
zlanhe(
'1',
'Upper', m-p, work, ldu2, rwork )
526 result( 13 ) = ( resid / real(max(1,m-p)) ) / ulp
527
528
529
530 CALL zlaset(
'Full', q, q, zero, one, work, ldv1t )
531 CALL zherk(
'Upper',
'No transpose', q, q, -realone,
532 $ v1t, ldv1t, realone, work, ldv1t )
533
534
535
536 resid =
zlanhe(
'1',
'Upper', q, work, ldv1t, rwork )
537 result( 14 ) = ( resid / real(max(1,q)) ) / ulp
538
539
540
541 result( 15 ) = realzero
542 DO i = 1, r
543 IF( theta(i).LT.realzero .OR. theta(i).GT.piover2 ) THEN
544 result( 15 ) = ulpinv
545 END IF
546 IF( i.GT.1) THEN
547 IF ( theta(i).LT.theta(i-1) ) THEN
548 result( 15 ) = ulpinv
549 END IF
550 END IF
551 END DO
552
553 RETURN
554
555
556
subroutine zgemm(transa, transb, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc)
ZGEMM
subroutine zherk(uplo, trans, n, k, alpha, a, lda, beta, c, ldc)
ZHERK
subroutine zlacpy(uplo, m, n, a, lda, b, ldb)
ZLACPY copies all or part of one two-dimensional array to another.
double precision function dlamch(cmach)
DLAMCH
double precision function zlange(norm, m, n, a, lda, work)
ZLANGE returns the value of the 1-norm, Frobenius norm, infinity-norm, or the largest absolute value ...
double precision function zlanhe(norm, uplo, n, a, lda, work)
ZLANHE returns the value of the 1-norm, or the Frobenius norm, or the infinity norm,...
subroutine zlaset(uplo, m, n, alpha, beta, a, lda)
ZLASET initializes the off-diagonal elements and the diagonal elements of a matrix to given values.
subroutine zuncsd2by1(jobu1, jobu2, jobv1t, m, p, q, x11, ldx11, x21, ldx21, theta, u1, ldu1, u2, ldu2, v1t, ldv1t, work, lwork, rwork, lrwork, iwork, info)
ZUNCSD2BY1
recursive subroutine zuncsd(jobu1, jobu2, jobv1t, jobv2t, trans, signs, m, p, q, x11, ldx11, x12, ldx12, x21, ldx21, x22, ldx22, theta, u1, ldu1, u2, ldu2, v1t, ldv1t, v2t, ldv2t, work, lwork, rwork, lrwork, iwork, info)
ZUNCSD