Esempio n. 1
0
/* zQsolve -- solves Qx = b, Q is an orthogonal matrix stored in compact
	form a la QRfactor()
	-- may be in-situ */
ZVEC	*_zQsolve(ZMAT* QR, ZVEC* diag, ZVEC* b, ZVEC *x, ZVEC *tmp)
{
    unsigned int	dynamic;
    int		k, limit;
    Real	beta, r_ii, tmp_val;
    
    limit = min(QR->m,QR->n);
    dynamic = FALSE;
    if ( ! QR || ! diag || ! b )
	error(E_NULL,"_zQsolve");
    if ( diag->dim < limit || b->dim != QR->m )
	error(E_SIZES,"_zQsolve");
    x = zv_resize(x,QR->m);
    if ( tmp == ZVNULL )
	dynamic = TRUE;
    tmp = zv_resize(tmp,QR->m);
    
    /* apply H/holder transforms in normal order */
    x = zv_copy(b,x);
    for ( k = 0 ; k < limit ; k++ )
    {
	zget_col(QR,k,tmp);
	r_ii = zabs(tmp->ve[k]);
	tmp->ve[k] = diag->ve[k];
	tmp_val = (r_ii*zabs(diag->ve[k]));
	beta = ( tmp_val == 0.0 ) ? 0.0 : 1.0/tmp_val;
	/* hhtrvec(tmp,beta->ve[k],k,x,x); */
	zhhtrvec(tmp,beta,k,x,x);
    }
    
    if ( dynamic )
	ZV_FREE(tmp);
    
    return (x);
}
Esempio n. 2
0
/* zQRfactor -- forms the QR factorisation of A
	-- factorisation stored in compact form as described above
	(not quite standard format) */
ZMAT	*zQRfactor(ZMAT* A, ZVEC* diag)
{
    unsigned int	k,limit;
    Real	beta;
    STATIC	ZVEC	*tmp1=ZVNULL, *w=ZVNULL;
    
    if ( ! A || ! diag )
	error(E_NULL,"zQRfactor");
    limit = min(A->m,A->n);
    if ( diag->dim < limit )
	error(E_SIZES,"zQRfactor");
    
    tmp1 = zv_resize(tmp1,A->m);
    w    = zv_resize(w,   A->n);
    MEM_STAT_REG(tmp1,TYPE_ZVEC);
    MEM_STAT_REG(w,   TYPE_ZVEC);
    
    for ( k=0; k<limit; k++ )
    {
	/* get H/holder vector for the k-th column */
	zget_col(A,k,tmp1);
	zhhvec(tmp1,k,&beta,tmp1,&A->me[k][k]);
	diag->ve[k] = tmp1->ve[k];
	
	/* apply H/holder vector to remaining columns */
	tracecatch(_zhhtrcols(A,k,k+1,tmp1,beta,w),"zQRfactor");
    }

#ifdef	THREADSAFE
    ZV_FREE(tmp1);	ZV_FREE(w);
#endif

    return (A);
}
Esempio n. 3
0
/* zmakeQ -- constructs orthogonal matrix from Householder vectors stored in
   compact QR form */
ZMAT	*zmakeQ(ZMAT *QR, ZVEC *diag, ZMAT *Qout)
{
    STATIC	ZVEC	*tmp1=ZVNULL,*tmp2=ZVNULL;
    unsigned int	i, limit;
    Real	beta, r_ii, tmp_val;
    int	j;

    limit = min(QR->m,QR->n);
    if ( ! QR || ! diag )
	error(E_NULL,"zmakeQ");
    if ( diag->dim < limit )
	error(E_SIZES,"zmakeQ");
    Qout = zm_resize(Qout,QR->m,QR->m);

    tmp1 = zv_resize(tmp1,QR->m);	/* contains basis vec & columns of Q */
    tmp2 = zv_resize(tmp2,QR->m);	/* contains H/holder vectors */
    MEM_STAT_REG(tmp1,TYPE_ZVEC);
    MEM_STAT_REG(tmp2,TYPE_ZVEC);

    for ( i=0; i<QR->m ; i++ )
    {	/* get i-th column of Q */
	/* set up tmp1 as i-th basis vector */
	for ( j=0; j<QR->m ; j++ )
	    tmp1->ve[j].re = tmp1->ve[j].im = 0.0;
	tmp1->ve[i].re = 1.0;
	
	/* apply H/h transforms in reverse order */
	for ( j=limit-1; j>=0; j-- )
	{
	    zget_col(QR,j,tmp2);
	    r_ii = zabs(tmp2->ve[j]);
	    tmp2->ve[j] = diag->ve[j];
	    tmp_val = (r_ii*zabs(diag->ve[j]));
	    beta = ( tmp_val == 0.0 ) ? 0.0 : 1.0/tmp_val;
	    /* hhtrvec(tmp2,beta->ve[j],j,tmp1,tmp1); */
	    zhhtrvec(tmp2,beta,j,tmp1,tmp1);
	}
	
	/* insert into Q */
	zset_col(Qout,i,tmp1);
    }

#ifdef	THREADSAFE
    ZV_FREE(tmp1);	ZV_FREE(tmp2);
#endif

    return (Qout);
}
Esempio n. 4
0
ZVEC	*pxinv_zvec(PERM *px, ZVEC *x, ZVEC *out)
#endif
{
    unsigned int	i, size;
    
    if ( ! px || ! x )
	error(E_NULL,"pxinv_zvec");
    if ( px->size > x->dim )
	error(E_SIZES,"pxinv_zvec");
    if ( ! out || out->dim < x->dim )
	out = zv_resize(out,x->dim);
    
    size = px->size;
    if ( size == 0 )
	return zv_copy(x,out);
    if ( out != x )
    {
	for ( i=0; i<size; i++ )
	    if ( px->pe[i] >= size )
		error(E_BOUNDS,"pxinv_vec");
	    else
		out->ve[px->pe[i]] = x->ve[i];
    }
    else
    {	/* in situ algorithm --- cheat's way out */
	px_inv(px,px);
	px_zvec(px,x,out);
	px_inv(px,px);
    }
    
    
    return out;
}
Esempio n. 5
0
ZVEC	*zv_slash(const ZVEC *x1, const ZVEC *x2, ZVEC *out)
#endif
{
    int		i;
    Real	r2, t_re, t_im;
    complex	tmp;

    if ( ! x1 || ! x2 )
	error(E_NULL,"zv_slash");
    if ( x1->dim != x2->dim )
	error(E_SIZES,"zv_slash");
    out = zv_resize(out,x1->dim);

    for ( i = 0; i < x1->dim; i++ )
    {
	r2 = x1->ve[i].re*x1->ve[i].re + x1->ve[i].im*x1->ve[i].im;
	if ( r2 == 0.0 )
	    error(E_SING,"zv_slash");
	tmp.re =   x1->ve[i].re / r2;
	tmp.im = - x1->ve[i].im / r2;
	t_re = tmp.re*x2->ve[i].re - tmp.im*x2->ve[i].im;
	t_im = tmp.re*x2->ve[i].im + tmp.im*x2->ve[i].re;
	out->ve[i].re = t_re;
	out->ve[i].im = t_im;
    }

    return out;
}
Esempio n. 6
0
/* zQRAsolve -- solves the system (Q.R)*.x = b
	-- Q & R are stored in compact form
	-- returns x, which is created if necessary */
ZVEC	*zQRAsolve(ZMAT *QR, ZVEC *diag, ZVEC *b, ZVEC *x)
{
    int		j, limit;
    Real	beta, r_ii, tmp_val;
    STATIC	ZVEC	*tmp = ZVNULL;
    
    if ( ! QR || ! diag || ! b )
	error(E_NULL,"zQRAsolve");
    limit = min(QR->m,QR->n);
    if ( diag->dim < limit || b->dim != QR->n )
	error(E_SIZES,"zQRAsolve");

    x = zv_resize(x,QR->m);
    x = zUAsolve(QR,b,x,0.0);
    x = zv_resize(x,QR->m);

    tmp = zv_resize(tmp,x->dim);
    MEM_STAT_REG(tmp,TYPE_ZVEC);
    /*  printf("zQRAsolve: tmp->dim = %d, x->dim = %d\n", tmp->dim, x->dim); */
    
    /* apply H/h transforms in reverse order */
    for ( j=limit-1; j>=0; j-- )
    {
	zget_col(QR,j,tmp);
	tmp = zv_resize(tmp,QR->m);
	r_ii = zabs(tmp->ve[j]);
	tmp->ve[j] = diag->ve[j];
	tmp_val = (r_ii*zabs(diag->ve[j]));
	beta = ( tmp_val == 0.0 ) ? 0.0 : 1.0/tmp_val;
	zhhtrvec(tmp,beta,j,x,x);
    }

#ifdef	THREADSAFE
    ZV_FREE(tmp);
#endif

    return x;
}
Esempio n. 7
0
int zv_resize_vars(int new_dim, ...) {
    va_list ap;
    int i = 0;
    ZVEC **par;

    va_start(ap, new_dim);
    while ((par = va_arg(ap, ZVEC **))) { /* NULL ends the list*/
        *par = zv_resize(*par, new_dim);
        i++;
    }

    va_end(ap);
    return i;
}
Esempio n. 8
0
/* zQRsolve -- solves the system Q.R.x=b where Q & R are stored in compact form
   -- returns x, which is created if necessary */
ZVEC	*zQRsolve(ZMAT *QR, ZVEC *diag, ZVEC *b, ZVEC *x)
{
    int	limit;
    STATIC	ZVEC	*tmp = ZVNULL;
    
    if ( ! QR || ! diag || ! b )
	error(E_NULL,"zQRsolve");
    limit = min(QR->m,QR->n);
    if ( diag->dim < limit || b->dim != QR->m )
	error(E_SIZES,"zQRsolve");
    tmp = zv_resize(tmp,limit);
    MEM_STAT_REG(tmp,TYPE_ZVEC);

    x = zv_resize(x,QR->n);
    _zQsolve(QR,diag,b,x,tmp);
    x = zUsolve(QR,x,x,0.0);
    x = zv_resize(x,QR->n);

#ifdef	THREADSAFE
    ZV_FREE(tmp);
#endif

    return x;
}
Esempio n. 9
0
ZVEC	*zv_add(const ZVEC *vec1, const ZVEC *vec2, ZVEC *out)
#endif
{
	unsigned int	dim;

	if ( vec1==ZVNULL || vec2==ZVNULL )
		error(E_NULL,"zv_add");
	if ( vec1->dim != vec2->dim )
		error(E_SIZES,"zv_add");
	if ( out==ZVNULL || out->dim != vec1->dim )
		out = zv_resize(out,vec1->dim);
	dim = vec1->dim;
	__zadd__(vec1->ve,vec2->ve,out->ve,(int)dim);

	return (out);
}
Esempio n. 10
0
/* zUmlt -- compute out = upper_triang(U).x
	-- may be in situ */
ZVEC	*zUmlt(ZMAT *U, ZVEC* x, ZVEC *out)
{
    int		i, limit;

    if ( U == ZMNULL || x == ZVNULL )
	error(E_NULL,"zUmlt");
    limit = min(U->m,U->n);
    if ( limit != x->dim )
	error(E_SIZES,"zUmlt");
    if ( out == ZVNULL || out->dim < limit )
	out = zv_resize(out,limit);

    for ( i = 0; i < limit; i++ )
	out->ve[i] = __zip__(&(x->ve[i]),&(U->me[i][i]),limit - i,Z_NOCONJ);
    return out;
}
Esempio n. 11
0
ZVEC	*zv_map(complex (*f)(complex), const ZVEC *x, ZVEC *out)
#endif
{
	complex	*x_ve, *out_ve;
	int	i, dim;

	if ( ! x || ! f )
		error(E_NULL,"zv_map");
	if ( ! out || out->dim != x->dim )
		out = zv_resize(out,x->dim);

	dim = x->dim;	x_ve = x->ve;	out_ve = out->ve;
	for ( i = 0; i < dim; i++ )
		out_ve[i] = (*f)(x_ve[i]);

	return out;
}
Esempio n. 12
0
ZVEC	*zv_sub(const ZVEC *vec1, const ZVEC *vec2, ZVEC *out)
#endif
{
	/* unsigned int	i, dim; */
	/* complex	*out_ve, *vec1_ve, *vec2_ve; */

	if ( vec1==ZVNULL || vec2==ZVNULL )
		error(E_NULL,"zv_sub");
	if ( vec1->dim != vec2->dim )
		error(E_SIZES,"zv_sub");
	if ( out==ZVNULL || out->dim != vec1->dim )
		out = zv_resize(out,vec1->dim);

	__zsub__(vec1->ve,vec2->ve,out->ve,(int)(vec1->dim));

	return (out);
}
Esempio n. 13
0
ZVEC	*zv_mlt(complex scalar, const ZVEC *vector, ZVEC *out)
#endif
{
	/* unsigned int	dim, i; */
	/* complex	*out_ve, *vec_ve; */

	if ( vector==ZVNULL )
		error(E_NULL,"zv_mlt");
	if ( out==ZVNULL || out->dim != vector->dim )
		out = zv_resize(out,vector->dim);
	if ( scalar.re == 0.0 && scalar.im == 0.0 )
		return zv_zero(out);
	if ( scalar.re == 1.0 && scalar.im == 0.0 )
		return zv_copy(vector,out);

	__zmlt__(vector->ve,scalar,out->ve,(int)(vector->dim));

	return (out);
}
Esempio n. 14
0
/* zUAmlt -- returns out = upper_triang(U)^T.x */
ZVEC	*zUAmlt(ZMAT *U, ZVEC *x, ZVEC *out)
{
    /* complex	sum; */
    complex	tmp;
    int		i, limit;

    if ( U == ZMNULL || x == ZVNULL )
	error(E_NULL,"zUAmlt");
    limit = min(U->m,U->n);
    if ( out == ZVNULL || out->dim < limit )
	out = zv_resize(out,limit);

    for ( i = limit-1; i >= 0; i-- )
    {
	tmp = x->ve[i];
	out->ve[i].re = out->ve[i].im = 0.0;
	__zmltadd__(&(out->ve[i]),&(U->me[i][i]),tmp,limit-i-1,Z_CONJ);
    }

    return out;
}
Esempio n. 15
0
ZVEC	*zv_star(const ZVEC *x1, const ZVEC *x2, ZVEC *out)
#endif
{
    int		i;
    Real	t_re, t_im;

    if ( ! x1 || ! x2 )
	error(E_NULL,"zv_star");
    if ( x1->dim != x2->dim )
	error(E_SIZES,"zv_star");
    out = zv_resize(out,x1->dim);

    for ( i = 0; i < x1->dim; i++ )
    {
	/* out->ve[i] = x1->ve[i] * x2->ve[i]; */
	t_re = x1->ve[i].re*x2->ve[i].re - x1->ve[i].im*x2->ve[i].im;
	t_im = x1->ve[i].re*x2->ve[i].im + x1->ve[i].im*x2->ve[i].re;
	out->ve[i].re = t_re;
	out->ve[i].im = t_im;
    }

    return out;
}
Esempio n. 16
0
ZVEC	*px_zvec(PERM *px, ZVEC *vector, ZVEC *out)
#endif
{
    unsigned int	old_i, i, size, start;
    complex	tmp;
    
    if ( px==PNULL || vector==ZVNULL )
	error(E_NULL,"px_zvec");
    if ( px->size > vector->dim )
	error(E_SIZES,"px_zvec");
    if ( out==ZVNULL || out->dim < vector->dim )
	out = zv_resize(out,vector->dim);
    
    size = px->size;
    if ( size == 0 )
	return zv_copy(vector,out);
    
    if ( out != vector )
    {
	for ( i=0; i<size; i++ )
	    if ( px->pe[i] >= size )
		error(E_BOUNDS,"px_vec");
	    else
		out->ve[i] = vector->ve[px->pe[i]];
    }
    else
    {	/* in situ algorithm */
	start = 0;
	while ( start < size )
	{
	    old_i = start;
	    i = px->pe[old_i];
	    if ( i >= size )
	    {
		start++;
		continue;
	    }
	    tmp = vector->ve[start];
	    while ( TRUE )
	    {
		vector->ve[old_i] = vector->ve[i];
		px->pe[old_i] = i+size;
		old_i = i;
		i = px->pe[old_i];
		if ( i >= size )
		    break;
		if ( i == start )
		{
		    vector->ve[old_i] = tmp;
		    px->pe[old_i] = i+size;
		    break;
		}
	    }
	    start++;
	}
	
	for ( i = 0; i < size; i++ )
	    if ( px->pe[i] < size )
		error(E_BOUNDS,"px_vec");
	    else
		px->pe[i] = px->pe[i]-size;
    }
    
    return out;
}
Esempio n. 17
0
/* zQRCPfactor -- forms the QR factorisation of A with column pivoting
   -- factorisation stored in compact form as described above
   ( not quite standard format )				*/
ZMAT	*zQRCPfactor(ZMAT *A, ZVEC* diag, PERM *px)
{
    unsigned int	i, i_max, j, k, limit;
    STATIC	ZVEC	*tmp1=ZVNULL, *tmp2=ZVNULL, *w=ZVNULL;
    STATIC	VEC	*gamma=VNULL;
    Real 	beta;
    Real	maxgamma, sum, tmp;
    complex	ztmp;
    
    if ( ! A || ! diag || ! px )
	error(E_NULL,"QRCPfactor");
    limit = min(A->m,A->n);
    if ( diag->dim < limit || px->size != A->n )
	error(E_SIZES,"QRCPfactor");
    
    tmp1 = zv_resize(tmp1,A->m);
    tmp2 = zv_resize(tmp2,A->m);
    gamma = v_resize(gamma,A->n);
    w    = zv_resize(w,A->n);
    MEM_STAT_REG(tmp1,TYPE_ZVEC);
    MEM_STAT_REG(tmp2,TYPE_ZVEC);
    MEM_STAT_REG(gamma,TYPE_VEC);
    MEM_STAT_REG(w,   TYPE_ZVEC);
    
    /* initialise gamma and px */
    for ( j=0; j<A->n; j++ )
    {
	px->pe[j] = j;
	sum = 0.0;
	for ( i=0; i<A->m; i++ )
	    sum += square(A->me[i][j].re) + square(A->me[i][j].im);
	gamma->ve[j] = sum;
    }
    
    for ( k=0; k<limit; k++ )
    {
	/* find "best" column to use */
	i_max = k;	maxgamma = gamma->ve[k];
	for ( i=k+1; i<A->n; i++ )
	    /* Loop invariant:maxgamma=gamma[i_max]
	       >=gamma[l];l=k,...,i-1 */
	    if ( gamma->ve[i] > maxgamma )
	    {	maxgamma = gamma->ve[i]; i_max = i;	}
	
	/* swap columns if necessary */
	if ( i_max != k )
	{
	    /* swap gamma values */
	    tmp = gamma->ve[k];
	    gamma->ve[k] = gamma->ve[i_max];
	    gamma->ve[i_max] = tmp;
	    
	    /* update column permutation */
	    px_transp(px,k,i_max);
	    
	    /* swap columns of A */
	    for ( i=0; i<A->m; i++ )
	    {
		ztmp = A->me[i][k];
		A->me[i][k] = A->me[i][i_max];
		A->me[i][i_max] = ztmp;
	    }
	}
	
	/* get H/holder vector for the k-th column */
	zget_col(A,k,tmp1);
	/* hhvec(tmp1,k,&beta->ve[k],tmp1,&A->me[k][k]); */
	zhhvec(tmp1,k,&beta,tmp1,&A->me[k][k]);
	diag->ve[k] = tmp1->ve[k];
	
	/* apply H/holder vector to remaining columns */
	_zhhtrcols(A,k,k+1,tmp1,beta,w);
	
	/* update gamma values */
	for ( j=k+1; j<A->n; j++ )
	    gamma->ve[j] -= square(A->me[k][j].re)+square(A->me[k][j].im);
    }

#ifdef	THREADSAFE
    ZV_FREE(tmp1);	ZV_FREE(tmp2);	V_FREE(gamma);	ZV_FREE(w);
#endif
    return (A);
}
Esempio n. 18
0
/* zQRcondest -- returns an estimate of the 2-norm condition number of the
		matrix factorised by QRfactor() or QRCPfactor()
	-- note that as Q does not affect the 2-norm condition number,
		it is not necessary to pass the diag, beta (or pivot) vectors
	-- generates a lower bound on the true condition number
	-- if the matrix is exactly singular, HUGE_VAL is returned
	-- note that QRcondest() is likely to be more reliable for
		matrices factored using QRCPfactor() */
double	zQRcondest(ZMAT *QR)
{
    STATIC	ZVEC	*y=ZVNULL;
    Real	norm, norm1, norm2, tmp1, tmp2;
    complex	sum, tmp;
    int		i, j, limit;

    if ( QR == ZMNULL )
	error(E_NULL,"zQRcondest");

    limit = min(QR->m,QR->n);
    for ( i = 0; i < limit; i++ )
	/* if ( QR->me[i][i] == 0.0 ) */
	if ( is_zero(QR->me[i][i]) )
	    return HUGE_VAL;

    y = zv_resize(y,limit);
    MEM_STAT_REG(y,TYPE_ZVEC);
    /* use the trick for getting a unit vector y with ||R.y||_inf small
       from the LU condition estimator */
    for ( i = 0; i < limit; i++ )
    {
	sum.re = sum.im = 0.0;
	for ( j = 0; j < i; j++ )
	    /* sum -= QR->me[j][i]*y->ve[j]; */
	    sum = zsub(sum,zmlt(QR->me[j][i],y->ve[j]));
	/* sum -= (sum < 0.0) ? 1.0 : -1.0; */
	norm1 = zabs(sum);
	if ( norm1 == 0.0 )
	    sum.re = 1.0;
	else
	{
	    sum.re += sum.re / norm1;
	    sum.im += sum.im / norm1;
	}
	/* y->ve[i] = sum / QR->me[i][i]; */
	y->ve[i] = zdiv(sum,QR->me[i][i]);
    }
    zUAmlt(QR,y,y);

    /* now apply inverse power method to R*.R */
    for ( i = 0; i < 3; i++ )
    {
	tmp1 = zv_norm2(y);
	zv_mlt(zmake(1.0/tmp1,0.0),y,y);
	zUAsolve(QR,y,y,0.0);
	tmp2 = zv_norm2(y);
	zv_mlt(zmake(1.0/tmp2,0.0),y,y);
	zUsolve(QR,y,y,0.0);
    }
    /* now compute approximation for ||R^{-1}||_2 */
    norm1 = sqrt(tmp1)*sqrt(tmp2);

    /* now use complementary approach to compute approximation to ||R||_2 */
    for ( i = limit-1; i >= 0; i-- )
    {
	sum.re = sum.im = 0.0;
	for ( j = i+1; j < limit; j++ )
	    sum = zadd(sum,zmlt(QR->me[i][j],y->ve[j]));
	if ( is_zero(QR->me[i][i]) )
	    return HUGE_VAL;
	tmp = zdiv(sum,QR->me[i][i]);
	if ( is_zero(tmp) )
	{
	    y->ve[i].re = 1.0;
	    y->ve[i].im = 0.0;
	}
	else
	{
	    norm = zabs(tmp);
	    y->ve[i].re = sum.re / norm;
	    y->ve[i].im = sum.im / norm;
	}
	/* y->ve[i] = (sum >= 0.0) ? 1.0 : -1.0; */
	/* y->ve[i] = (QR->me[i][i] >= 0.0) ? y->ve[i] : - y->ve[i]; */
    }

    /* now apply power method to R*.R */
    for ( i = 0; i < 3; i++ )
    {
	tmp1 = zv_norm2(y);
	zv_mlt(zmake(1.0/tmp1,0.0),y,y);
	zUmlt(QR,y,y);
	tmp2 = zv_norm2(y);
	zv_mlt(zmake(1.0/tmp2,0.0),y,y);
	zUAmlt(QR,y,y);
    }
    norm2 = sqrt(tmp1)*sqrt(tmp2);

    /* printf("QRcondest: norm1 = %g, norm2 = %g\n",norm1,norm2); */

#ifdef	THREADSAFE
    ZV_FREE(y);
#endif

    return norm1*norm2;
}