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; }
VEC *pxinv_vec(PERM *px, const VEC *x, VEC *out) { unsigned int i, size; if ( ! px || ! x ) error(E_NULL,"pxinv_vec"); if ( px->size > x->dim ) error(E_SIZES,"pxinv_vec"); if ( ! out || out->dim < x->dim ) out = v_resize(out,x->dim); size = px->size; if ( size == 0 ) return v_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 { px_inv(px,px); px_vec(px,x,out); px_inv(px,px); } return out; }
VEC *bdLUsolve(const BAND *bA, PERM *pivot, const VEC *b, VEC *x) #endif { int i,j,l,n,n1,pi,lb,ub,jmin, maxj; Real c; Real **bA_v; if ( bA==(BAND *)NULL || b==(VEC *)NULL || pivot==(PERM *)NULL ) error(E_NULL,"bdLUsolve"); if ( bA->mat->n != b->dim || bA->mat->n != pivot->size) error(E_SIZES,"bdLUsolve"); lb = bA->lb; ub = bA->ub; n = b->dim; n1 = n-1; bA_v = bA->mat->me; x = v_resize(x,b->dim); px_vec(pivot,b,x); /* solve Lx = b; implicit diagonal = 1 L is not permuted, therefore it must be permuted now */ px_inv(pivot,pivot); for (j=0; j < n; j++) { jmin = j+1; c = x->ve[j]; maxj = max(0,j+lb-n1); for (i=jmin,l=lb-1; l >= maxj; i++,l--) { if ( (pi = pivot->pe[i]) < jmin) pi = pivot->pe[i] = pivot->pe[pi]; x->ve[pi] -= bA_v[l][j]*c; } } /* solve Ux = b; explicit diagonal */ x->ve[n1] /= bA_v[lb][n1]; for (i=n-2; i >= 0; i--) { c = x->ve[i]; for (j=min(n1,i+ub), l=lb+j-i; j > i; j--,l--) c -= bA_v[l][j]*x->ve[j]; x->ve[i] = c/bA_v[lb][i]; } return (x); }
//-------------------------------------------------------------------------- void Hqp_IpRedSpBKP::init(const Hqp_Program *qp) { IVEC *degree, *neigh_start, *neighs; SPMAT *QCTC; SPROW *r1, *r2; int i, j; int len, dim; Real sum; _n = qp->c->dim; _me = qp->b->dim; _m = qp->d->dim; dim = _n + _me; // reallocations _pivot = px_resize(_pivot, dim); _blocks = px_resize(_blocks, dim); _zw = v_resize(_zw, _m); _scale = v_resize(_scale, _n); _r12 = v_resize(_r12, dim); _xy = v_resize(_xy, dim); // store C' for further computations // analyze structure of C'*C _CT = sp_transp(qp->C, _CT); sp_ones(_CT); v_ones(_zw); QCTC = sp_get(_n, _n, 10); r1 = _CT->row; for (i=0; i<_n; i++, r1++) { r2 = r1; for (j=i; j<_n; j++, r2++) { sum = sprow_inprod(r1, _zw, r2); if (sum != 0.0) { sp_set_val(QCTC, i, j, sum); if (i != j) sp_set_val(QCTC, j, i, sum); } } } _CTC_degree = iv_resize(_CTC_degree, _n); _CTC_neigh_start = iv_resize(_CTC_neigh_start, _n + 1); _CTC_neighs = sp_rcm_scan(QCTC, SMNULL, SMNULL, _CTC_degree, _CTC_neigh_start, _CTC_neighs); // initialize structure of reduced qp QCTC = sp_add(qp->Q, QCTC, QCTC); // determine RCM ordering degree = iv_get(dim); neigh_start = iv_get(dim + 1); neighs = sp_rcm_scan(QCTC, qp->A, SMNULL, degree, neigh_start, IVNULL); _QP2J = sp_rcm_order(degree, neigh_start, neighs, _QP2J); _sbw = sp_rcm_sbw(neigh_start, neighs, _QP2J); _J2QP = px_inv(_QP2J, _J2QP); iv_free(degree); iv_free(neigh_start); iv_free(neighs); len = 1 + (int)(log((double)dim) / log(2.0)); sp_free(_J); sp_free(_J_raw); _J_raw = sp_get(dim, dim, len); _J = SMNULL; // fill up data (to allocate _J_raw) sp_into_symsp(QCTC, -1.0, _J_raw, _QP2J, 0, 0); spT_into_symsp(qp->A, 1.0, _J_raw, _QP2J, 0, _n); sp_into_symsp(qp->A, 1.0, _J_raw, _QP2J, _n, 0); sp_free(QCTC); // prepare iterations update(qp); }