home *** CD-ROM | disk | FTP | other *** search
-
- /**************************************************************************
- **
- ** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved.
- **
- ** Meschach Library
- **
- ** This Meschach Library is provided "as is" without any express
- ** or implied warranty of any kind with respect to this software.
- ** In particular the authors shall not be liable for any direct,
- ** indirect, special, incidental or consequential damages arising
- ** in any way from use of the software.
- **
- ** Everyone is granted permission to copy, modify and redistribute this
- ** Meschach Library, provided:
- ** 1. All copies contain this copyright notice.
- ** 2. All modified copies shall carry a notice stating who
- ** made the last modification and the date of such modification.
- ** 3. No charge is made for this software or works derived from it.
- ** This clause shall not be construed as constraining other software
- ** distributed on the same medium as this software, nor is a
- ** distribution fee considered a charge.
- **
- ***************************************************************************/
-
-
- /* iter0.c 14/09/93 */
-
- /* ITERATIVE METHODS - service functions */
-
- /* functions for creating and releasing ITER structures;
- for memory information;
- for getting some values from an ITER variable;
- for changing values in an ITER variable;
- see also iter.c
- */
-
- #include <stdio.h>
- #include <math.h>
- #include "iter.h"
-
-
- static char rcsid[] = "$Id: iter0.c,v 1.2 1994/06/20 05:22:10 des Exp $";
-
-
- /* standard functions */
-
- /* standard information */
- void iter_std_info(ip,nres,res,Bres)
- ITER *ip;
- double nres;
- VEC *res, *Bres;
- {
- if (nres >= 0.0)
- printf(" %d. residual = %g\n",ip->steps,nres);
- else
- printf(" %d. residual = %g (WARNING !!! should be >= 0) \n",
- ip->steps,nres);
- }
-
- /* standard stopping criterion */
- int iter_std_stop_crit(ip, nres, res, Bres)
- ITER *ip;
- double nres;
- VEC *res, *Bres;
- {
- /* save initial value of the residual in init_res */
- if (ip->steps == 0)
- ip->init_res = fabs(nres);
-
- /* standard stopping criterium */
- if (nres <= ip->init_res*ip->eps) return TRUE;
- return FALSE;
- }
-
-
- /* iter_get - create a new structure pointing to ITER */
-
- ITER *iter_get(lenb, lenx)
- int lenb, lenx;
- {
- ITER *ip;
-
- if ((ip = NEW(ITER)) == (ITER *) NULL)
- error(E_MEM,"iter_get");
- else if (mem_info_is_on()) {
- mem_bytes(TYPE_ITER,0,sizeof(ITER));
- mem_numvar(TYPE_ITER,1);
- }
-
- /* default values */
-
- ip->shared_x = FALSE;
- ip->shared_b = FALSE;
- ip->k = 0;
- ip->limit = ITER_LIMIT_DEF;
- ip->eps = ITER_EPS_DEF;
- ip->steps = 0;
-
- if (lenb > 0) ip->b = v_get(lenb);
- else ip->b = (VEC *)NULL;
-
- if (lenx > 0) ip->x = v_get(lenx);
- else ip->x = (VEC *)NULL;
-
- ip->Ax = ip->ATx = ip->Bx = NULL;
- ip->A_par = ip->AT_par = ip->B_par = NULL;
- ip->info = iter_std_info;
- ip->stop_crit = iter_std_stop_crit;
- ip->init_res = 0.0;
-
- return ip;
- }
-
-
- /* iter_free - release memory */
- int iter_free(ip)
- ITER *ip;
- {
- if (ip == (ITER *)NULL) return -1;
-
- if (mem_info_is_on()) {
- mem_bytes(TYPE_ITER,sizeof(ITER),0);
- mem_numvar(TYPE_ITER,-1);
- }
-
- if ( !ip->shared_x && ip->x != NULL ) v_free(ip->x);
- if ( !ip->shared_b && ip->b != NULL ) v_free(ip->b);
-
- free((char *)ip);
-
- return 0;
- }
-
- ITER *iter_resize(ip,new_lenb,new_lenx)
- ITER *ip;
- int new_lenb, new_lenx;
- {
- int old;
-
- if ( ip == (ITER *) NULL)
- error(E_NULL,"iter_resize");
-
- if (new_lenx <= 0) ip->x = VNULL;
- else {
- old = ip->x->dim;
- ip->x = v_resize(ip->x,new_lenx);
- if ( ip->shared_x && old != new_lenx)
- warning(WARN_SHARED_VEC,"iter_resize");
- }
-
- if (new_lenb <= 0) ip->b = VNULL;
- else {
- old = ip->b->dim;
- ip->b = v_resize(ip->b,new_lenb);
- if ( ip->shared_b && old != new_lenb)
- warning(WARN_SHARED_VEC,"iter_resize");
- }
-
- return ip;
- }
-
-
-
- /* print out ip structure - for diagnostic purposes mainly */
- void iter_dump(fp,ip)
- ITER *ip;
- FILE *fp;
- {
- if (ip == NULL) {
- fprintf(fp," ITER structure: NULL\n");
- return;
- }
-
- fprintf(fp,"\n ITER structure:\n");
- fprintf(fp," ip->shared_x = %s, ip->shared_b = %s\n",
- (ip->shared_x ? "TRUE" : "FALSE"),
- (ip->shared_b ? "TRUE" : "FALSE") );
- fprintf(fp," ip->k = %d, ip->limit = %d, ip->steps = %d, ip->eps = %g\n",
- ip->k,ip->limit,ip->steps,ip->eps);
- fprintf(fp," ip->x = 0x%p, ip->b = 0x%p\n",ip->x,ip->b);
- fprintf(fp," ip->Ax = 0x%p, ip->A_par = 0x%p\n",ip->Ax,ip->A_par);
- fprintf(fp," ip->ATx = 0x%p, ip->AT_par = 0x%p\n",ip->ATx,ip->AT_par);
- fprintf(fp," ip->Bx = 0x%p, ip->B_par = 0x%p\n",ip->Bx,ip->B_par);
- fprintf(fp," ip->info = 0x%p, ip->stop_crit = 0x%p, ip->init_res = %g\n",
- ip->info,ip->stop_crit,ip->init_res);
- fprintf(fp,"\n");
-
- }
-
-
- /* copy the structure ip1 to ip2 preserving vectors x and b of ip2
- (vectors x and b in ip2 are the same before and after iter_copy2)
- if ip2 == NULL then a new structure is created with x and b being NULL
- and other members are taken from ip1
- */
- ITER *iter_copy2(ip1,ip2)
- ITER *ip1, *ip2;
- {
- VEC *x, *b;
- int shx, shb;
-
- if (ip1 == (ITER *)NULL)
- error(E_NULL,"iter_copy2");
-
- if (ip2 == (ITER *)NULL) {
- if ((ip2 = NEW(ITER)) == (ITER *) NULL)
- error(E_MEM,"iter_copy2");
- else if (mem_info_is_on()) {
- mem_bytes(TYPE_ITER,0,sizeof(ITER));
- mem_numvar(TYPE_ITER,1);
- }
- ip2->x = ip2->b = NULL;
- ip2->shared_x = ip2->shared_x = FALSE;
- }
-
- x = ip2->x;
- b = ip2->b;
- shb = ip2->shared_b;
- shx = ip2->shared_x;
- MEM_COPY(ip1,ip2,sizeof(ITER));
- ip2->x = x;
- ip2->b = b;
- ip2->shared_x = shx;
- ip2->shared_b = shb;
-
- return ip2;
- }
-
-
- /* copy the structure ip1 to ip2 copying also the vectors x and b */
- ITER *iter_copy(ip1,ip2)
- ITER *ip1, *ip2;
- {
- VEC *x, *b;
-
- if (ip1 == (ITER *)NULL)
- error(E_NULL,"iter_copy");
-
- if (ip2 == (ITER *)NULL) {
- if ((ip2 = NEW(ITER)) == (ITER *) NULL)
- error(E_MEM,"iter_copy2");
- else if (mem_info_is_on()) {
- mem_bytes(TYPE_ITER,0,sizeof(ITER));
- mem_numvar(TYPE_ITER,1);
- }
- }
-
- x = ip2->x;
- b = ip2->b;
-
- MEM_COPY(ip1,ip2,sizeof(ITER));
- if (ip1->x)
- ip2->x = v_copy(ip1->x,x);
- if (ip1->b)
- ip2->b = v_copy(ip1->b,b);
-
- ip2->shared_x = ip2->shared_b = FALSE;
-
- return ip2;
- }
-
-
- /*** functions to generate sparse matrices with random entries ***/
-
-
- /* iter_gen_sym -- generate symmetric positive definite
- n x n matrix,
- nrow - number of nonzero entries in a row
- */
- SPMAT *iter_gen_sym(n,nrow)
- int n, nrow;
- {
- SPMAT *A;
- VEC *u;
- Real s1;
- int i, j, k, k_max;
-
- if (nrow <= 1) nrow = 2;
- /* nrow should be even */
- if ((nrow & 1)) nrow -= 1;
- A = sp_get(n,n,nrow);
- u = v_get(A->m);
- v_zero(u);
- for ( i = 0; i < A->m; i++ )
- {
- k_max = ((rand() >> 8) % (nrow/2));
- for ( k = 0; k <= k_max; k++ )
- {
- j = (rand() >> 8) % A->n;
- s1 = mrand();
- sp_set_val(A,i,j,s1);
- sp_set_val(A,j,i,s1);
- u->ve[i] += fabs(s1);
- u->ve[j] += fabs(s1);
- }
- }
- /* ensure that A is positive definite */
- for ( i = 0; i < A->m; i++ )
- sp_set_val(A,i,i,u->ve[i] + 1.0);
-
- V_FREE(u);
- return A;
- }
-
-
- /* iter_gen_nonsym -- generate non-symmetric m x n sparse matrix, m >= n
- nrow - number of entries in a row;
- diag - number which is put in diagonal entries and then permuted
- (if diag is zero then 1.0 is there)
- */
- SPMAT *iter_gen_nonsym(m,n,nrow,diag)
- int m, n, nrow;
- double diag;
- {
- SPMAT *A;
- PERM *px;
- int i, j, k, k_max;
- Real s1;
-
- if (nrow <= 1) nrow = 2;
- if (diag == 0.0) diag = 1.0;
- A = sp_get(m,n,nrow);
- px = px_get(n);
- for ( i = 0; i < A->m; i++ )
- {
- k_max = (rand() >> 8) % (nrow-1);
- for ( k = 0; k <= k_max; k++ )
- {
- j = (rand() >> 8) % A->n;
- s1 = mrand();
- sp_set_val(A,i,j,-s1);
- }
- }
- /* to make it likely that A is nonsingular, use pivot... */
- for ( i = 0; i < 2*A->n; i++ )
- {
- j = (rand() >> 8) % A->n;
- k = (rand() >> 8) % A->n;
- px_transp(px,j,k);
- }
- for ( i = 0; i < A->n; i++ )
- sp_set_val(A,i,px->pe[i],diag);
-
- PX_FREE(px);
- return A;
- }
-
-
- /* iter_gen_nonsym -- generate non-symmetric positive definite
- n x n sparse matrix;
- nrow - number of entries in a row
- */
- SPMAT *iter_gen_nonsym_posdef(n,nrow)
- int n, nrow;
- {
- SPMAT *A;
- PERM *px;
- VEC *u;
- int i, j, k, k_max;
- Real s1;
-
- if (nrow <= 1) nrow = 2;
- A = sp_get(n,n,nrow);
- px = px_get(n);
- u = v_get(A->m);
- v_zero(u);
- for ( i = 0; i < A->m; i++ )
- {
- k_max = (rand() >> 8) % (nrow-1);
- for ( k = 0; k <= k_max; k++ )
- {
- j = (rand() >> 8) % A->n;
- s1 = mrand();
- sp_set_val(A,i,j,-s1);
- u->ve[i] += fabs(s1);
- }
- }
- /* ensure that A is positive definite */
- for ( i = 0; i < A->m; i++ )
- sp_set_val(A,i,i,u->ve[i] + 1.0);
-
- PX_FREE(px);
- V_FREE(u);
- return A;
- }
-
-
-