예제 #1
0
static double	sprow_ip(const SPROW *row1, const SPROW *row2, int lim)
#endif
{
	int			idx1, idx2, len1, len2, tmp;
	register row_elt	*elts1, *elts2;
	register Real		sum;

	elts1 = row1->elt;	elts2 = row2->elt;
	len1 = row1->len;	len2 = row2->len;

	sum = 0.0;

	if ( len1 <= 0 || len2 <= 0 )
		return 0.0;
	if ( elts1->col >= lim || elts2->col >= lim )
		return 0.0;

	/* use sprow_idx() to speed up inner product where one row is
		much longer than the other */
	idx1 = idx2 = 0;
	if ( len1 > 2*len2 )
	{
		idx1 = sprow_idx(row1,elts2->col);
		idx1 = (idx1 < 0) ? -(idx1+2) : idx1;
		if ( idx1 < 0 )
			error(E_UNKNOWN,"sprow_ip");
		len1 -= idx1;
	}
	else if ( len2 > 2*len1 )
	{
		idx2 = sprow_idx(row2,elts1->col);
		idx2 = (idx2 < 0) ? -(idx2+2) : idx2;
		if ( idx2 < 0 )
			error(E_UNKNOWN,"sprow_ip");
		len2 -= idx2;
	}
	if ( len1 <= 0 || len2 <= 0 )
		return 0.0;

	elts1 = &(elts1[idx1]);		elts2 = &(elts2[idx2]);


	for ( ; ; )	/* forever do... */
	{
		if ( (tmp=elts1->col-elts2->col) < 0 )
		{
		    len1--;		elts1++;
		    if ( ! len1 || elts1->col >= lim )
			break;
		}
		else if ( tmp > 0 )
		{
		    len2--;		elts2++;
		    if ( ! len2 || elts2->col >= lim )
			break;
		}
		else
		{
		    sum += elts1->val * elts2->val;
		    len1--;		elts1++;
		    len2--;		elts2++;
		    if ( ! len1 || ! len2 ||
				elts1->col >= lim || elts2->col >= lim )
			break;
		}
	}

	return sum;
}
예제 #2
0
파일: splufctr.c 프로젝트: Rainwin2015/C
SPMAT	*spLUfactor(SPMAT *A, PERM *px, double alpha)
#endif
{
	int	i, best_i, k, idx, len, best_len, m, n;
	SPROW	*r, *r_piv, tmp_row;
	STATIC	SPROW	*merge = (SPROW *)NULL;
	Real	max_val, tmp;
	STATIC VEC	*col_vals=VNULL;

	if ( ! A || ! px )
		error(E_NULL,"spLUfctr");
	if ( alpha <= 0.0 || alpha > 1.0 )
		error(E_RANGE,"alpha in spLUfctr");
	if ( px->size <= A->m )
		px = px_resize(px,A->m);
	px_ident(px);
	col_vals = v_resize(col_vals,A->m);
	MEM_STAT_REG(col_vals,TYPE_VEC);

	m = A->m;	n = A->n;
	if ( ! A->flag_col )
		sp_col_access(A);
	if ( ! A->flag_diag )
		sp_diag_access(A);
	A->flag_col = A->flag_diag = FALSE;
	if ( ! merge ) {
	   merge = sprow_get(20);
	   MEM_STAT_REG(merge,TYPE_SPROW);
	}

	for ( k = 0; k < n; k++ )
	{
	    /* find pivot row/element for partial pivoting */

	    /* get first row with a non-zero entry in the k-th column */
	    max_val = 0.0;
	    for ( i = k; i < m; i++ )
	    {
		r = &(A->row[i]);
		idx = sprow_idx(r,k);
		if ( idx < 0 )
		    tmp = 0.0;
		else
		    tmp = r->elt[idx].val;
		if ( fabs(tmp) > max_val )
		    max_val = fabs(tmp);
		col_vals->ve[i] = tmp;
	    }

	    if ( max_val == 0.0 )
		continue;

	    best_len = n+1;	/* only if no possibilities */
	    best_i = -1;
	    for ( i = k; i < m; i++ )
	    {
		tmp = fabs(col_vals->ve[i]);
		if ( tmp == 0.0 )
		    continue;
		if ( tmp >= alpha*max_val )
		{
		    r = &(A->row[i]);
		    idx = sprow_idx(r,k);
		    len = (r->len) - idx;
		    if ( len < best_len )
		    {
			best_len = len;
			best_i = i;
		    }
		}
	    }

	    /* swap row #best_i with row #k */
	    MEM_COPY(&(A->row[best_i]),&tmp_row,sizeof(SPROW));
	    MEM_COPY(&(A->row[k]),&(A->row[best_i]),sizeof(SPROW));
	    MEM_COPY(&tmp_row,&(A->row[k]),sizeof(SPROW));
	    /* swap col_vals entries */
	    tmp = col_vals->ve[best_i];
	    col_vals->ve[best_i] = col_vals->ve[k];
	    col_vals->ve[k] = tmp;
	    px_transp(px,k,best_i);

	    r_piv = &(A->row[k]);
	    for ( i = k+1; i < n; i++ )
	    {
		/* compute and set multiplier */
		tmp = col_vals->ve[i]/col_vals->ve[k];
		if ( tmp != 0.0 )
		    sp_set_val(A,i,k,tmp);
		else
		    continue;

		/* perform row operations */
		merge->len = 0;
		r = &(A->row[i]);
		sprow_mltadd(r,r_piv,-tmp,k+1,merge,TYPE_SPROW);
		idx = sprow_idx(r,k+1);
		if ( idx < 0 )
		    idx = -(idx+2);
		/* see if r needs expanding */
		if ( r->maxlen < idx + merge->len )
		    sprow_xpd(r,idx+merge->len,TYPE_SPMAT);
		r->len = idx+merge->len;
		MEM_COPY((char *)(merge->elt),(char *)&(r->elt[idx]),
			merge->len*sizeof(row_elt));
	    }
	}
#ifdef	THREADSAFE
	sprow_free(merge);	V_FREE(col_vals);
#endif

	return A;
}
예제 #3
0
//--------------------------------------------------------------------------
SPMAT *Hqp_IpRedSpBKP::sub_CTC(const PERM *px, SPMAT *Q)
// return Q - _CT * diag(_zw) * _CT'
// read:  _CT, _zw
// write: _scale
{
  int i, j, j_idx, j_end;
  int qi, qj, qj_idx;
  SPROW *crow, *qrow;
  Real sum, val;
  IVEC neigh_header;
  IVEC *neigh = &neigh_header;

  assert(Q->n == Q->m);
  assert((int)px->size == Q->m && Q->m >= _n);

  if (!Q->flag_diag)
    sp_diag_access(Q);

  neigh_header.max_dim = 0;

  crow = _CT->row;
  for (i=0; i<_n; i++, crow++) {

    qrow = Q->row + px->pe[i];
    if (crow->len <= 0) {
      val = qrow->elt[qrow->diag].val;
      _scale->ve[i] = min(1.0, sqrt(-1.0 / val));
    }
    else {

      // calculate diagonal entry
      sum = sprow_inprod(crow, _zw, crow);
      j_idx = qrow->diag;
      val = qrow->elt[j_idx].val -= sum;
      _scale->ve[i] = min(1.0, sqrt(-1.0 / val));

      // calculate resting entries
      neigh->ive = _CTC_neighs->ive + _CTC_neigh_start->ive[i];
      neigh->dim = _CTC_neigh_start->ive[i + 1] - _CTC_neigh_start->ive[i];
      j_end = neigh->dim;
      for (j_idx = 0; j_idx < j_end; j_idx++) {
	j = neigh->ive[j_idx];
	if (j < i) {
	  sum = sprow_inprod(crow, _zw, _CT->row + j);
	  qi = px->pe[i];
	  qj = px->pe[j];

	  // substract sum from Qij or Qji (entry from upper part only)

	  if (qi < qj) {
	    qrow = Q->row + qi;
	    qj_idx = sprow_idx(qrow, qj);
	    if (qj_idx < 0) {
	      // the structure must already have been allocated in init()
	      m_error(E_INTERN, "Hqp_IpRedSpBKP");
	    }
	    else {
	      qrow->elt[qj_idx].val -= sum;
	    }
	  }
	  else {
	    qrow = Q->row + qj;
	    qj_idx = sprow_idx(qrow, qi);
	    if (qj_idx < 0) {
	      // the structure must already have been allocated in init()
	      m_error(E_INTERN, "Hqp_IpRedSpBKP");
	    }
	    else {
	      qrow->elt[qj_idx].val -= sum;
	    }
	  }
	}
      }
    }
  }

  return Q;  
}
예제 #4
0
파일: splufctr.c 프로젝트: Rainwin2015/C
SPMAT	*spILUfactor(SPMAT *A, double alpha)
#endif
{
    int		i, k, idx, idx_piv, m, n, old_idx, old_idx_piv;
    SPROW	*r, *r_piv;
    Real	piv_val, tmp;
    
    /* printf("spILUfactor: entered\n"); */
    if ( ! A )
	error(E_NULL,"spILUfactor");
    if ( alpha < 0.0 )
	error(E_RANGE,"[alpha] in spILUfactor");
    
    m = A->m;	n = A->n;
    sp_diag_access(A);
    sp_col_access(A);
    
    for ( k = 0; k < n; k++ )
    {
	/* printf("spILUfactor(l.%d): checkpoint A: k = %d\n",__LINE__,k); */
	/* printf("spILUfactor(l.%d): A =\n", __LINE__); */
	/* sp_output(A); */
	r_piv = &(A->row[k]);
	idx_piv = r_piv->diag;
	if ( idx_piv < 0 )
	{
	    sprow_set_val(r_piv,k,alpha);
	    idx_piv = sprow_idx(r_piv,k);
	}
	/* printf("spILUfactor: checkpoint B\n"); */
	if ( idx_piv < 0 )
	    error(E_BOUNDS,"spILUfactor");
	old_idx_piv = idx_piv;
	piv_val = r_piv->elt[idx_piv].val;
	/* printf("spILUfactor: checkpoint C\n"); */
	if ( fabs(piv_val) < alpha )
	    piv_val = ( piv_val < 0.0 ) ? -alpha : alpha;
	if ( piv_val == 0.0 )	/* alpha == 0.0 too! */
	    error(E_SING,"spILUfactor");

	/* go to next row with a non-zero in this column */
	i = r_piv->elt[idx_piv].nxt_row;
	old_idx = idx = r_piv->elt[idx_piv].nxt_idx;
	while ( i >= k )
	{
	    /* printf("spILUfactor: checkpoint D: i = %d\n",i); */
	    /* perform row operations */
	    r = &(A->row[i]);
	    /* idx = sprow_idx(r,k); */
	    /* printf("spLUfactor(l.%d) i = %d, idx = %d\n",
		   __LINE__, i, idx); */
	    if ( idx < 0 )
	    {
		idx = r->elt[old_idx].nxt_idx;
		i = r->elt[old_idx].nxt_row;
		continue;
	    }
	    /* printf("spILUfactor: checkpoint E\n"); */
	    /* compute and set multiplier */
	    r->elt[idx].val = tmp = r->elt[idx].val/piv_val;
	    /* printf("spILUfactor: piv_val = %g, multiplier = %g\n",
		   piv_val, tmp); */
	    /* printf("spLUfactor(l.%d) multiplier = %g\n", __LINE__, tmp); */
	    if ( tmp == 0.0 )
	    {
		idx = r->elt[old_idx].nxt_idx;
		i = r->elt[old_idx].nxt_row;
		continue;
	    }
	    /* idx = sprow_idx(r,k+1); */
	    /* if ( idx < 0 )
		idx = -(idx+2); */
	    idx_piv++;	idx++;	/* now look beyond the multiplier entry */
	    /* printf("spILUfactor: checkpoint F: idx = %d, idx_piv = %d\n",
		   idx, idx_piv); */
	    while ( idx_piv < r_piv->len && idx < r->len )
	    {
		/* printf("spILUfactor: checkpoint G: idx = %d, idx_piv = %d\n",
		       idx, idx_piv); */
		if ( r_piv->elt[idx_piv].col < r->elt[idx].col )
		    idx_piv++;
		else if ( r_piv->elt[idx_piv].col > r->elt[idx].col )
		    idx++;
		else /* column numbers match */
		{
		    /* printf("spILUfactor(l.%d) subtract %g times the ",
			   __LINE__, tmp); */
		    /* printf("(%d,%d) entry to the (%d,%d) entry\n",
			   k, r_piv->elt[idx_piv].col,
			   i, r->elt[idx].col); */
		    r->elt[idx].val -= tmp*r_piv->elt[idx_piv].val;
		    idx++;	idx_piv++;
		}
	    }

	    /* bump to next row with a non-zero in column k */
	    /* printf("spILUfactor(l.%d) column = %d, row[%d] =\n",
		   __LINE__, r->elt[old_idx].col, i); */
	    /* sprow_foutput(stdout,r); */
	    i = r->elt[old_idx].nxt_row;
	    old_idx = idx = r->elt[old_idx].nxt_idx;
	    /* printf("spILUfactor(l.%d) i = %d, idx = %d\n", __LINE__, i, idx); */
	    /* and restore idx_piv to index of pivot entry */
	    idx_piv = old_idx_piv;
	}
    }
    /* printf("spILUfactor: exiting\n"); */
    return A;
}