BAND *bd_resize(BAND *A, int new_lb, int new_ub, int new_n) #endif { int lb,ub,i,j,l,shift,umin; Real **Av; if (new_lb < 0 || new_ub < 0 || new_n <= 0) error(E_NEG,"bd_resize"); if ( ! A ) return bd_get(new_lb,new_ub,new_n); if ( A->lb+A->ub+1 > A->mat->m ) error(E_INTERN,"bd_resize"); if ( A->lb == new_lb && A->ub == new_ub && A->mat->n == new_n ) return A; lb = A->lb; ub = A->ub; Av = A->mat->me; umin = min(ub,new_ub); /* ensure that unused triangles at edges are zero'd */ for ( i = 0; i < lb; i++ ) for ( j = A->mat->n - lb + i; j < A->mat->n; j++ ) Av[i][j] = 0.0; for ( i = lb+1,l=1; l <= umin; i++,l++ ) for ( j = 0; j < l; j++ ) Av[i][j] = 0.0; new_lb = A->lb = min(new_lb,new_n-1); new_ub = A->ub = min(new_ub,new_n-1); A->mat = m_resize(A->mat,new_lb+new_ub+1,new_n); Av = A->mat->me; /* if new_lb != lb then move the rows to get the main diag in the new_lb row */ if (new_lb > lb) { shift = new_lb-lb; for (i=lb+umin, l=i+shift; i >= 0; i--,l--) MEM_COPY(Av[i],Av[l],new_n*sizeof(Real)); for (l=shift-1; l >= 0; l--) __zero__(Av[l],new_n); } else if (new_lb < lb) { shift = lb - new_lb; for (i=shift, l=0; i <= lb+umin; i++,l++) MEM_COPY(Av[i],Av[l],new_n*sizeof(Real)); for (i=lb+umin+1; i <= new_lb+new_ub; i++) __zero__(Av[i],new_n); } return A; }
/* v_resize -- returns the vector x with dim new_dim -- x is set to the zero vector */ extern VEC *v_resize(VEC *x, int new_dim) { if (new_dim < 0) error(E_NEG,"v_resize"); if ( ! x ) return v_get(new_dim); /* nothing is changed */ if (new_dim == x->dim) return x; if ( x->max_dim == 0 ) /* assume that it's from sub_vec */ return v_get(new_dim); if ( new_dim > x->max_dim ) { if (mem_info_is_on()) { mem_bytes(TYPE_VEC,x->max_dim*sizeof(Real), new_dim*sizeof(Real)); } x->ve = RENEW(x->ve,new_dim,Real); if ( ! x->ve ) error(E_MEM,"v_resize"); x->max_dim = new_dim; } if ( new_dim > x->dim ) __zero__(&(x->ve[x->dim]),new_dim - x->dim); x->dim = new_dim; return x; }
/* v_zero -- zero the vector x */ VEC *v_zero(VEC *x) { if ( x == VNULL ) error(E_NULL,"v_zero"); __zero__(x->ve,x->dim); /* for ( i = 0; i < x->dim; i++ ) x->ve[i] = 0.0; */ return x; }
VEC *LTsolve(const MAT *L, const VEC *b, VEC *out, double diag) { unsigned int dim; int i, i_lim; MatrixReal **L_me, *b_ve, *out_ve, tmp, invdiag, tiny; if ( ! L || ! b ) error(E_NULL,"LTsolve"); dim = mat_min(L->m,L->n); if ( b->dim < dim ) error(E_SIZES,"LTsolve"); out = v_resize(out,L->n); L_me = L->me; b_ve = b->ve; out_ve = out->ve; tiny = (10.0/HUGE_VAL); for ( i=dim-1; i>=0; i-- ) if ( b_ve[i] != 0.0 ) break; i_lim = i; if ( b != out ) { __zero__(out_ve,out->dim); MEM_COPY(b_ve,out_ve,(i_lim+1)*sizeof(MatrixReal)); } if ( diag == 0.0 ) { for ( ; i>=0; i-- ) { tmp = L_me[i][i]; if ( fabs(tmp) <= tiny*fabs(out_ve[i]) ) error(E_SING,"LTsolve"); out_ve[i] /= tmp; __mltadd__(out_ve,L_me[i],-out_ve[i],i); } } else { invdiag = 1.0/diag; for ( ; i>=0; i-- ) { out_ve[i] *= invdiag; __mltadd__(out_ve,L_me[i],-out_ve[i],i); } } return (out); }
VEC *UTsolve(const MAT *U, const VEC *b, VEC *out, double diag) { unsigned int dim, i, i_lim; MatrixReal **U_me, *b_ve, *out_ve, tmp, invdiag, tiny; if ( ! U || ! b ) error(E_NULL,"UTsolve"); dim = mat_min(U->m,U->n); if ( b->dim < dim ) error(E_SIZES,"UTsolve"); out = v_resize(out,U->n); U_me = U->me; b_ve = b->ve; out_ve = out->ve; tiny = (10.0/HUGE_VAL); for ( i=0; i<dim; i++ ) if ( b_ve[i] != 0.0 ) break; else out_ve[i] = 0.0; i_lim = i; if ( b != out ) { __zero__(out_ve,out->dim); MEM_COPY(&(b_ve[i_lim]),&(out_ve[i_lim]),(dim-i_lim)*sizeof(MatrixReal)); } if ( diag == 0.0 ) { for ( ; i<dim; i++ ) { tmp = U_me[i][i]; if ( fabs(tmp) <= tiny*fabs(out_ve[i]) ) error(E_SING,"UTsolve"); out_ve[i] /= tmp; __mltadd__(&(out_ve[i+1]),&(U_me[i][i+1]),-out_ve[i],dim-i-1); } } else { invdiag = 1.0/diag; for ( ; i<dim; i++ ) { out_ve[i] *= invdiag; __mltadd__(&(out_ve[i+1]),&(U_me[i][i+1]),-out_ve[i],dim-i-1); } } return (out); }
/* m_zero -- zero the matrix A */ MAT *m_zero(MAT *A) { int i, A_m, A_n; Real **A_me; if ( A == MNULL ) error(E_NULL,"m_zero"); A_m = A->m; A_n = A->n; A_me = A->me; for ( i = 0; i < A_m; i++ ) __zero__(A_me[i],A_n); /* for ( j = 0; j < A_n; j++ ) A_me[i][j] = 0.0; */ return A; }
/* m_resize -- returns the matrix A of size new_m x new_n; A is zeroed -- if A == NULL on entry then the effect is equivalent to m_get() */ extern MAT *m_resize(MAT *A, int new_m, int new_n) { int i; int new_max_m, new_max_n, new_size, old_m, old_n; if (new_m < 0 || new_n < 0) error(E_NEG,"m_resize"); if ( ! A ) return m_get(new_m,new_n); /* nothing was changed */ if (new_m == A->m && new_n == A->n) return A; old_m = A->m; old_n = A->n; if ( new_m > A->max_m ) { /* re-allocate A->me */ if (mem_info_is_on()) { mem_bytes(TYPE_MAT,A->max_m*sizeof(Real *), new_m*sizeof(Real *)); } A->me = RENEW(A->me,new_m,Real *); if ( ! A->me ) error(E_MEM,"m_resize"); } new_max_m = max(new_m,A->max_m); new_max_n = max(new_n,A->max_n); #ifndef SEGMENTED new_size = new_max_m*new_max_n; if ( new_size > A->max_size ) { /* re-allocate A->base */ if (mem_info_is_on()) { mem_bytes(TYPE_MAT,A->max_m*A->max_n*sizeof(Real), new_size*sizeof(Real)); } A->base = RENEW(A->base,new_size,Real); if ( ! A->base ) error(E_MEM,"m_resize"); A->max_size = new_size; } /* now set up A->me[i] */ for ( i = 0; i < new_m; i++ ) A->me[i] = &(A->base[i*new_n]); /* now shift data in matrix */ if ( old_n > new_n ) { for ( i = 1; i < min(old_m,new_m); i++ ) MEM_COPY((char *)&(A->base[i*old_n]), (char *)&(A->base[i*new_n]), sizeof(Real)*new_n); } else if ( old_n < new_n ) { for ( i = (int)(min(old_m,new_m))-1; i > 0; i-- ) { /* copy & then zero extra space */ MEM_COPY((char *)&(A->base[i*old_n]), (char *)&(A->base[i*new_n]), sizeof(Real)*old_n); __zero__(&(A->base[i*new_n+old_n]),(new_n-old_n)); } __zero__(&(A->base[old_n]),(new_n-old_n)); A->max_n = new_n; } /* zero out the new rows.. */ for ( i = old_m; i < new_m; i++ ) __zero__(&(A->base[i*new_n]),new_n); #else if ( A->max_n < new_n ) { Real *tmp; for ( i = 0; i < A->max_m; i++ ) { if (mem_info_is_on()) { mem_bytes(TYPE_MAT,A->max_n*sizeof(Real), new_max_n*sizeof(Real)); } if ( (tmp = RENEW(A->me[i],new_max_n,Real)) == NULL ) error(E_MEM,"m_resize"); else { A->me[i] = tmp; } } for ( i = A->max_m; i < new_max_m; i++ ) { if ( (tmp = NEW_A(new_max_n,Real)) == NULL ) error(E_MEM,"m_resize"); else { A->me[i] = tmp; if (mem_info_is_on()) { mem_bytes(TYPE_MAT,0,new_max_n*sizeof(Real)); } } } } else if ( A->max_m < new_m ) { for ( i = A->max_m; i < new_m; i++ ) if ( (A->me[i] = NEW_A(new_max_n,Real)) == NULL ) error(E_MEM,"m_resize"); else if (mem_info_is_on()) { mem_bytes(TYPE_MAT,0,new_max_n*sizeof(Real)); } } if ( old_n < new_n ) { for ( i = 0; i < old_m; i++ ) __zero__(&(A->me[i][old_n]),new_n-old_n); } /* zero out the new rows.. */ for ( i = old_m; i < new_m; i++ ) __zero__(A->me[i],new_n); #endif A->max_m = new_max_m; A->max_n = new_max_n; A->max_size = A->max_m*A->max_n; A->m = new_m; A->n = new_n; return A; }