163 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			163 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
#include "clapack.h"
 | 
						|
 | 
						|
/* Subroutine */ int slarfg_(integer *n, real *alpha, real *x, integer *incx, 
 | 
						|
	real *tau)
 | 
						|
{
 | 
						|
    /* System generated locals */
 | 
						|
    integer i__1;
 | 
						|
    real r__1;
 | 
						|
 | 
						|
    /* Builtin functions */
 | 
						|
    double r_sign(real *, real *);
 | 
						|
 | 
						|
    /* Local variables */
 | 
						|
    integer j, knt;
 | 
						|
    real beta;
 | 
						|
    extern doublereal snrm2_(integer *, real *, integer *);
 | 
						|
    extern /* Subroutine */ int sscal_(integer *, real *, real *, integer *);
 | 
						|
    real xnorm;
 | 
						|
    extern doublereal slapy2_(real *, real *), slamch_(char *);
 | 
						|
    real safmin, rsafmn;
 | 
						|
 | 
						|
 | 
						|
/*  -- LAPACK auxiliary routine (version 3.1) -- */
 | 
						|
/*     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */
 | 
						|
/*     November 2006 */
 | 
						|
 | 
						|
/*     .. Scalar Arguments .. */
 | 
						|
/*     .. */
 | 
						|
/*     .. Array Arguments .. */
 | 
						|
/*     .. */
 | 
						|
 | 
						|
/*  Purpose */
 | 
						|
/*  ======= */
 | 
						|
 | 
						|
/*  SLARFG generates a real elementary reflector H of order n, such */
 | 
						|
/*  that */
 | 
						|
 | 
						|
/*        H * ( alpha ) = ( beta ),   H' * H = I. */
 | 
						|
/*            (   x   )   (   0  ) */
 | 
						|
 | 
						|
/*  where alpha and beta are scalars, and x is an (n-1)-element real */
 | 
						|
/*  vector. H is represented in the form */
 | 
						|
 | 
						|
/*        H = I - tau * ( 1 ) * ( 1 v' ) , */
 | 
						|
/*                      ( v ) */
 | 
						|
 | 
						|
/*  where tau is a real scalar and v is a real (n-1)-element */
 | 
						|
/*  vector. */
 | 
						|
 | 
						|
/*  If the elements of x are all zero, then tau = 0 and H is taken to be */
 | 
						|
/*  the unit matrix. */
 | 
						|
 | 
						|
/*  Otherwise  1 <= tau <= 2. */
 | 
						|
 | 
						|
/*  Arguments */
 | 
						|
/*  ========= */
 | 
						|
 | 
						|
/*  N       (input) INTEGER */
 | 
						|
/*          The order of the elementary reflector. */
 | 
						|
 | 
						|
/*  ALPHA   (input/output) REAL */
 | 
						|
/*          On entry, the value alpha. */
 | 
						|
/*          On exit, it is overwritten with the value beta. */
 | 
						|
 | 
						|
/*  X       (input/output) REAL array, dimension */
 | 
						|
/*                         (1+(N-2)*abs(INCX)) */
 | 
						|
/*          On entry, the vector x. */
 | 
						|
/*          On exit, it is overwritten with the vector v. */
 | 
						|
 | 
						|
/*  INCX    (input) INTEGER */
 | 
						|
/*          The increment between elements of X. INCX > 0. */
 | 
						|
 | 
						|
/*  TAU     (output) REAL */
 | 
						|
/*          The value tau. */
 | 
						|
 | 
						|
/*  ===================================================================== */
 | 
						|
 | 
						|
/*     .. Parameters .. */
 | 
						|
/*     .. */
 | 
						|
/*     .. Local Scalars .. */
 | 
						|
/*     .. */
 | 
						|
/*     .. External Functions .. */
 | 
						|
/*     .. */
 | 
						|
/*     .. Intrinsic Functions .. */
 | 
						|
/*     .. */
 | 
						|
/*     .. External Subroutines .. */
 | 
						|
/*     .. */
 | 
						|
/*     .. Executable Statements .. */
 | 
						|
 | 
						|
    /* Parameter adjustments */
 | 
						|
    --x;
 | 
						|
 | 
						|
    /* Function Body */
 | 
						|
    if (*n <= 1) {
 | 
						|
	*tau = 0.f;
 | 
						|
	return 0;
 | 
						|
    }
 | 
						|
 | 
						|
    i__1 = *n - 1;
 | 
						|
    xnorm = snrm2_(&i__1, &x[1], incx);
 | 
						|
 | 
						|
    if (xnorm == 0.f) {
 | 
						|
 | 
						|
/*        H  =  I */
 | 
						|
 | 
						|
	*tau = 0.f;
 | 
						|
    } else {
 | 
						|
 | 
						|
/*        general case */
 | 
						|
 | 
						|
	r__1 = slapy2_(alpha, &xnorm);
 | 
						|
	beta = -r_sign(&r__1, alpha);
 | 
						|
	safmin = slamch_("S") / slamch_("E");
 | 
						|
	if (dabs(beta) < safmin) {
 | 
						|
 | 
						|
/*           XNORM, BETA may be inaccurate; scale X and recompute them */
 | 
						|
 | 
						|
	    rsafmn = 1.f / safmin;
 | 
						|
	    knt = 0;
 | 
						|
L10:
 | 
						|
	    ++knt;
 | 
						|
	    i__1 = *n - 1;
 | 
						|
	    sscal_(&i__1, &rsafmn, &x[1], incx);
 | 
						|
	    beta *= rsafmn;
 | 
						|
	    *alpha *= rsafmn;
 | 
						|
	    if (dabs(beta) < safmin) {
 | 
						|
		goto L10;
 | 
						|
	    }
 | 
						|
 | 
						|
/*           New BETA is at most 1, at least SAFMIN */
 | 
						|
 | 
						|
	    i__1 = *n - 1;
 | 
						|
	    xnorm = snrm2_(&i__1, &x[1], incx);
 | 
						|
	    r__1 = slapy2_(alpha, &xnorm);
 | 
						|
	    beta = -r_sign(&r__1, alpha);
 | 
						|
	    *tau = (beta - *alpha) / beta;
 | 
						|
	    i__1 = *n - 1;
 | 
						|
	    r__1 = 1.f / (*alpha - beta);
 | 
						|
	    sscal_(&i__1, &r__1, &x[1], incx);
 | 
						|
 | 
						|
/*           If ALPHA is subnormal, it may lose relative accuracy */
 | 
						|
 | 
						|
	    *alpha = beta;
 | 
						|
	    i__1 = knt;
 | 
						|
	    for (j = 1; j <= i__1; ++j) {
 | 
						|
		*alpha *= safmin;
 | 
						|
/* L20: */
 | 
						|
	    }
 | 
						|
	} else {
 | 
						|
	    *tau = (beta - *alpha) / beta;
 | 
						|
	    i__1 = *n - 1;
 | 
						|
	    r__1 = 1.f / (*alpha - beta);
 | 
						|
	    sscal_(&i__1, &r__1, &x[1], incx);
 | 
						|
	    *alpha = beta;
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
    return 0;
 | 
						|
 | 
						|
/*     End of SLARFG */
 | 
						|
 | 
						|
} /* slarfg_ */
 |