⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 spscale.c

📁 经济学专业代码
💻 C
📖 第 1 页 / 共 3 页
字号:
   WORK
     fwork  - 2 * n^2 vector.
   RETURNS zjc0_NEW
   ************************************************************ */
int sprealutxu(double *z, const int *zir, const int zjc0, const int zjc1,
               const double *u, const int *invperm, const double *x,
               const int first, const int n, double *fwork)
{
  int inz, i, irow, j, icol, jcol, jfirst, jlast, m;
  double *xu;
  const double *uj, *xuj;
/* ------------------------------------------------------------
   Partition 2*n^2 WORKING array fwork into [fwork(n^2), xu(n^2)].
   ------------------------------------------------------------ */
  xu = fwork + SQR(n);
/* ------------------------------------------------------------
   Let fwork = X in full symmetric storage
   ------------------------------------------------------------ */
  memcpy(fwork, x, SQR(n) * sizeof(double));
  triu2sym(fwork,n);
/* ------------------------------------------------------------
   Compute xu = triu(fwork'*U):   1^2 + 2^2 + ... + (n-1)^2 + n^2 mults.
   For each j, let uj point to u(0,j); m is
   remaining length of column j, i.e. m=j.      (SEE realutxu.)
   ------------------------------------------------------------ */
  inz = 0; jcol = 0;
  for(j = 0, m = n; j < n; j++, jcol += n){
    for(i = 0, icol = 0; i <= j; i++, icol += n)
      xu[inz++] = realdot(fwork+icol,u+jcol,j+1);  /* x(:,i)'*u(0:j,j) */
    inz += --m;                                    /* skip tril */
  }
/* ------------------------------------------------------------
   For all target subscripts (i,j), let
   zij = (U'*XU)_ij [ = (U'*XU)_ji ]
   ------------------------------------------------------------ */
  jlast = 0;                  /* index right after last activated column */
  for(inz = zjc0; inz < zjc1; inz++){
    if((i = zir[inz]) >= jlast){      /* move to new z-column */
      j = (i-first) / n;              /* col j = floor( (i-first)/n ) */
      if(j >= n)
        break;                        /* finished all columns of Z */
      jfirst = first + n * j;
      jlast = jfirst + n;
      j = invperm[j];                 /* change to U- and X-index */
      jcol = n * j;
      uj = u + jcol;
      xuj = xu + jcol;
    }
    irow = invperm[i - jfirst];       /* U- and X-index */
    if(irow <= j)            /* zij = u(0:i,i)' * xu(0:i,j) IF i<=j */
      z[i] = realdot(u + irow * n, xuj, irow + 1);
    else{                    /* zij = u(0:j,j)' * xu(0:j,i) IF i>j */
      z[i] = realdot(uj, xu + irow * n, j + 1);
    }
  }
/* ------------------------------------------------------------
   RETURN inz, next position in zir (after range first:first+n^2-1).
   ------------------------------------------------------------ */
  return inz;
}

/* ************************************************************
   PROCEDURE spcpxutxu - Computes Z(perm,perm) = U' * X * U.
        Z has pre-chosen sparsity structure zir
	(typically subset of tril-entries [or of triu-entries]).
        U,X and Z are complex matrices, stored as [vec(RE); vec(IM)].
   INPUT
     zir, zjc0, zjc1 - Target sparsity structure. We compute z(i) only for
       i in zir(zjc0:zjc1-1) with i < first + 2*n^2.
       zjc0 such that zir(zjc0) >= first.
     u      - full 2*(n x n) matrix, triu(u) = U.
     invperm - length n array, invperm(perm)=0:n-1. Used to translate Z-index
       to u- and x-index.
     x - 2*(n x n) full symmetric matrix containing triu(X).
     first  - Subscript of X(1,1) and Z(1,1), i.e.
       x(first:first+n^2-1) = vec(RE X), x(first+n^2:end) = vec(IM(X))..
     n      - order of U, X.
   OUTPUT
     Z - lenfull vector. Only z(first:first+2n^2-1) is affected, and from this
       only the indices listed in zir. (Other entries unaffected.)
   WORK
     fwork  - 4 * n^2 vector.
   RETURNS zjc0_NEW
   ************************************************************ */
int spcpxutxu(double *z, const int *zir, const int zjc0, const int zjc1,
              const double *u, const int *invperm, const double *x,
              const int first, const int n, double *fwork)
{
  int inz, i, irow, j, icol, jcol, jfirst, jlast, m, nsqr, imgfirst;
  double *xu, *xupi, *fworkpi;
  const double *uj, *ujpi, *xuj, *xujpi, *upi;
/* ------------------------------------------------------------
   Partition 4*n^2 WORKING array fwork into [fwork(2*n^2), xu(2*n^2)].
   ------------------------------------------------------------ */
  nsqr = SQR(n);
  upi = u + nsqr;
  fworkpi = fwork + nsqr;
  xu = fworkpi + nsqr;
  xupi = xu + nsqr;
/* ------------------------------------------------------------
   Let fwork = X in full hermitian storage
   ------------------------------------------------------------ */
  memcpy(fwork, x, 2*nsqr * sizeof(double));
  triu2herm(fwork,fworkpi,n);
/* ------------------------------------------------------------
   Compute xu = triu(fwork'*U)   ( =triu(XU), since X is Hermitian.)   
   For each j, let uj point to u(0,j); m is
   remaining length of column j, i.e. m=j.      (SEE prpiutxu.)
   ------------------------------------------------------------ */
  inz = 0; jcol = 0;
  for(j = 0, m = n; j < n; j++, jcol += n){
    for(i = 0, icol = 0; i <= j; i++, icol += n){
/* xu(i,j) = x(:,i)'*u(0:j,j), assume IM u(j,j) == 0 */
      xu[inz] = realdot(fwork+icol,u+jcol,j+1) +
        realdot(fworkpi+icol,upi+jcol,j);
      xupi[inz] = realdot(fwork+icol,upi+jcol,j) -
        realdot(fworkpi+icol,u+jcol,j+1);
      inz++;
    }
    inz += --m;                                /* skip tril */
  }
/* ------------------------------------------------------------
   For all target subscripts (i,j) in RE Z, let
   zij = RE (U'*XU)_ij [ = RE (U'*XU)_ji ]
   ------------------------------------------------------------ */
  jlast = 0;                  /* index right after last activated column */
  for(inz = zjc0; inz < zjc1; inz++){
    if((i = zir[inz]) >= jlast){      /* move to new z-column */
      j = (i-first) / n;              /* col j = floor( (i-first)/n ) */
      if(j >= n)
        break;                        /* finished all columns of RE Z */
      jfirst = first + n * j;
      jlast = jfirst + n;
      j = invperm[j];                 /* change to U- and X-index */
      jcol = n * j;
      uj = u + jcol;
      ujpi = uj + nsqr;
      xuj = xu + jcol;
      xujpi = xuj + nsqr;
    }
    irow = invperm[i - jfirst];       /* U- and X-index */
    icol = irow * n;
    if(irow <= j)            /* zij = RE u(0:i,i)' * xu(0:i,j) IF i<=j */
      z[i] = realdot(u+icol, xuj, irow+1) + realdot(upi+icol, xujpi, irow);
    else{                    /* zij = RE u(0:j,j)' * xu(0:j,i) IF i>j */
      z[i] = realdot(uj, xu+icol, j+1) + realdot(ujpi, xupi+icol, j);
    }
  }
/* ------------------------------------------------------------
   Remains target subscripts (i,j) in IM Z. Let
   zij = IM (U'*XU)_ij [ = -IM (U'*XU)_ji ]
   ------------------------------------------------------------ */
  imgfirst = first + nsqr;
  for(; inz < zjc1; inz++){
    if((i = zir[inz]) >= jlast){      /* move to new z-column */
      j = (i-imgfirst) / n;              /* col j = floor( (i-first)/n ) */
      if(j >= n)
        break;                        /* finished all columns of IM Z */
      jfirst = imgfirst + n * j;
      jlast = jfirst + n;
      j = invperm[j];                 /* change to U- and X-index */
      jcol = n * j;
      uj = u + jcol;
      ujpi = uj + nsqr;
      xuj = xu + jcol;
      xujpi = xuj + nsqr;
    }
    irow = invperm[i - jfirst];       /* U- and X-index */
    icol = irow * n;
    if(irow <= j)            /* zij = IM u(0:i,i)' * xu(0:i,j) IF i<=j */
      z[i] = realdot(u+icol, xujpi, irow+1) - realdot(upi+icol, xuj, irow);
    else                     /* zij = -IM u(0:j,j)' * xu(0:j,i) IF i>j */
      z[i] = realdot(ujpi, xu+icol, j) - realdot(uj, xupi+icol, j+1);
  }
/* ------------------------------------------------------------
   RETURN inz, next position in zir (after range first:first+2*n^2-1).
   ------------------------------------------------------------ */
  return inz;
}

/* ************************************************************
   PROCEDURE blkpsdscale - Computes z = D(d)x = U'*X*U for PSD-part.
     Typically, X = D(d)aj = vec(triu(U*Aj*U')).
   INPUT
     zir, zjc1 - Target sparsity structure. We compute z(i) only for
       i in zir(0:zjc1-1).
     u      - lenud vector containing full n x n matrices Uk
     invperm - lenpsd array, containing inverse perm for Uk for each psd-block
     x      - vector of full blocks, viz. those listed in xblk.
     xblk, blkjc0, blkjc1 - the psd-blocks stored in x.
     blkstart  - length psdN+1 array such that
       z(blkstart[k]:blkstart[k+1]) = vec(Zk) for all PSD blocks k.
     psdNL     - length psdN array, is K.s.
     cumpsdNL  - cumsum([0, psdNL]), i.e. start of block k in invperm.
     rpsdN     - number of real symmetric PSD blocks.
   OUTPUT (PRE-INITIALIZED)
     z - lenfull vector. Only indices listed in zir are affected.
       Other entries are unaffected (not even set to 0).
   WORK
     fwork  - 2 * (rMaxn^2 + 2*hMaxn^2) vector.  (<= 4*max(K.s)^2)
   RETURNS zjc0_NEW (should be zjc1)
   ************************************************************ */
int blkpsdscale(double *z, const int *zir, const int zjc1,
		const double *u, const int *invperm, const double *x,
		const int *xblk, const int blkjc0, const int blkjc1,
		const int *blkstart, const int *psdNL, const int *cumpsdNL,
		const int rpsdN, double *fwork)
{
  int inz, knz, k, nk, lastzsub;

  inz = 0;                 /* points into zir */
  if(inz >= zjc1)
    return inz;            /* return if no target subscripts */
  lastzsub = zir[zjc1-1];
  u -= blkstart[0];        /* Now, u + blkstart[k] gives Uk */
  for(knz = blkjc0; knz < blkjc1; knz++){
/* ------------------------------------------------------------
   For each nonzero block xblk[k] in x, Let zk = vec(tril(Dk * Xk * Dk)).
   ------------------------------------------------------------ */
    k = xblk[knz];
    if(k >= rpsdN)
      break;                                /* 1st nz Hermitian PSD block */
    if(lastzsub < blkstart[k])
      break;                                /* already beyond last target i*/
    nk = psdNL[k];
    while(zir[inz] < blkstart[k])           /* move to block k, viz. */
      z[zir[inz++]] = 0.0;                  /* all-0 where x is all-0 */
    inz = sprealutxu(z, zir, inz, zjc1, u + blkstart[k], invperm+cumpsdNL[k],
		     x, blkstart[k], nk, fwork);
    x += SQR(nk);                           /* point to next nonzero block */
  }
/* ------------------------------------------------------------
   Hermitian PSD blocks
   ------------------------------------------------------------ */
  for(; knz < blkjc1; knz++){
    k = xblk[knz];
    if(lastzsub < blkstart[k])
      break;                                /* already beyond last target i*/
    nk = psdNL[k];
    while(zir[inz] < blkstart[k])           /* move to block k, viz. */
      z[zir[inz++]] = 0.0;                  /* all-0 where x is all-0 */
    inz = spcpxutxu(z, zir, inz, zjc1, u + blkstart[k], invperm+cumpsdNL[k],
                    x, blkstart[k], nk, fwork);
    x += 2*SQR(nk);                         /* point to next nonzero block */
  }
/* ------------------------------------------------------------
   No remaining x blocks ==> remaining z-entries all-0.
   ------------------------------------------------------------ */
  for(; inz < zjc1; inz++)
    z[zir[inz]] = 0.0;                  /* all-0 where x is all-0 */
/* ------------------------------------------------------------
   RETURN next zir-position (should be zjc1)
   ------------------------------------------------------------ */
  return inz;       /* arrived at end of z-vector */
}
#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -