Пример #1
0
TEST(generateExpression, index_op) {
  static const bool user_facing = true;
  std::stringstream msgs;

  // expr:  row_vector
  stan::lang::double_literal dblLit(5.1);
  dblLit.string_ = "5.1";
  stan::lang::expression e1 = dblLit;
  std::vector<stan::lang::expression> elements;
  elements.push_back(e1);
  elements.push_back(e1);
  stan::lang::row_vector_expr rv1(elements);
  stan::lang::expression e2 = rv1;

  // dimensions:  vector of vector of dimensions
  std::vector<std::vector<stan::lang::expression> > dimss;
  std::vector<stan::lang::expression> dim;
  dim.push_back(stan::lang::int_literal(1));
  dimss.push_back(dim);
  stan::lang::index_op i_op(e2, dimss);
  stan::lang::expression e3 = i_op;

  // result is index into row_vector
  generate_expression(e3, user_facing, msgs);
  EXPECT_NE(msgs.str().find("stan::math::to_row_vector"), std::string::npos);
  EXPECT_NE(msgs.str().find("stan::math::array_builder<double"), std::string::npos);
  EXPECT_NE(msgs.str().find("add(5.1).array()"), std::string::npos);
  EXPECT_NE(msgs.str().find("[1]"), std::string::npos);
}
Пример #2
0
TEST(generateExpression, row_vector_expr) {
  static const bool user_facing = true;
  std::stringstream msgs;

  stan::lang::double_literal dblLit(5.1);
  dblLit.string_ = "5.1";
  stan::lang::expression e1 = dblLit;
  std::vector<stan::lang::expression> elements;
  elements.push_back(e1);
  elements.push_back(e1);
  stan::lang::row_vector_expr rv1(elements);
  stan::lang::expression e2 = rv1;

  generate_expression(e2, user_facing, msgs);
  EXPECT_NE(msgs.str().find("stan::math::to_row_vector"), std::string::npos);
  EXPECT_NE(msgs.str().find("stan::math::array_builder<double"), std::string::npos);
  EXPECT_NE(msgs.str().find("add(5.1).array()"), std::string::npos);
}
Пример #3
0
Foam::SVD::SVD(const scalarRectangularMatrix& A, const scalar minCondition)
:
    U_(A),
    V_(A.m(), A.m()),
    S_(A.m()),
    VSinvUt_(A.m(), A.n()),
    nZeros_(0)
{
    // SVDcomp to find U_, V_ and S_ - the singular values

    const label Um = U_.m();
    const label Un = U_.n();

    scalarList rv1(Um);
    scalar g = 0;
    scalar scale = 0;
    scalar s = 0;
    scalar anorm = 0;
    label l = 0;

    for (label i = 0; i < Um; i++)
    {
        l = i+2;
        rv1[i] = scale*g;
        g = s = scale = 0;

        if (i < Un)
        {
            for (label k = i; k < Un; k++)
            {
                scale += mag(U_[k][i]);
            }

            if (scale != 0)
            {
                for (label k = i; k < Un; k++)
                {
                    U_[k][i] /= scale;
                    s += U_[k][i]*U_[k][i];
                }

                scalar f = U_[i][i];
                g = -sign(Foam::sqrt(s), f);
                scalar h = f*g - s;
                U_[i][i] = f - g;

                for (label j = l-1; j < Um; j++)
                {
                    s = 0;
                    for (label k = i; k < Un; k++)
                    {
                        s += U_[k][i]*U_[k][j];
                    }

                    f = s/h;
                    for (label k = i; k < A.n(); k++)
                    {
                        U_[k][j] += f*U_[k][i];
                    }
                }

                for (label k = i; k < Un; k++)
                {
                    U_[k][i] *= scale;
                }
            }
        }

        S_[i] = scale*g;

        g = s = scale = 0;

        if (i+1 <= Un && i != Um)
        {
            for (label k = l-1; k < Um; k++)
            {
                scale += mag(U_[i][k]);
            }

            if (scale != 0)
            {
                for (label k=l-1; k < Um; k++)
                {
                    U_[i][k] /= scale;
                    s += U_[i][k]*U_[i][k];
                }

                scalar f = U_[i][l-1];
                g = -sign(Foam::sqrt(s),f);
                scalar h = f*g - s;
                U_[i][l-1] = f - g;

                for (label k = l-1; k < Um; k++)
                {
                    rv1[k] = U_[i][k]/h;
                }

                for (label j = l-1; j < Un; j++)
                {
                    s = 0;
                    for (label k = l-1; k < Um; k++)
                    {
                        s += U_[j][k]*U_[i][k];
                    }

                    for (label k = l-1; k < Um; k++)
                    {
                        U_[j][k] += s*rv1[k];
                    }
                }
                for (label k = l-1; k < Um; k++)
                {
                    U_[i][k] *= scale;
                }
            }
        }

        anorm = max(anorm, mag(S_[i]) + mag(rv1[i]));
    }

    for (label i = Um-1; i >= 0; i--)
    {
        if (i < Um-1)
        {
            if (g != 0)
            {
                for (label j = l; j < Um; j++)
                {
                    V_[j][i] = (U_[i][j]/U_[i][l])/g;
                }

                for (label j=l; j < Um; j++)
                {
                    s = 0;
                    for (label k = l; k < Um; k++)
                    {
                        s += U_[i][k]*V_[k][j];
                    }

                    for (label k = l; k < Um; k++)
                    {
                        V_[k][j] += s*V_[k][i];
                    }
                }
            }

            for (label j = l; j < Um;j++)
            {
                V_[i][j] = V_[j][i] = 0.0;
            }
        }

        V_[i][i] = 1;
        g = rv1[i];
        l = i;
    }

    for (label i = min(Um, Un) - 1; i >= 0; i--)
    {
        l = i+1;
        g = S_[i];

        for (label j = l; j < Um; j++)
        {
            U_[i][j] = 0.0;
        }

        if (g != 0)
        {
            g = 1.0/g;

            for (label j = l; j < Um; j++)
            {
                s = 0;
                for (label k = l; k < Un; k++)
                {
                    s += U_[k][i]*U_[k][j];
                }

                scalar f = (s/U_[i][i])*g;

                for (label k = i; k < Un; k++)
                {
                    U_[k][j] += f*U_[k][i];
                }
            }

            for (label j = i; j < Un; j++)
            {
                U_[j][i] *= g;
            }
        }
        else
        {
            for (label j = i; j < Un; j++)
            {
                U_[j][i] = 0.0;
            }
        }

        ++U_[i][i];
    }

    for (label k = Um-1; k >= 0; k--)
    {
        for (label its = 0; its < 35; its++)
        {
            bool flag = true;

            label nm;
            for (l = k; l >= 0; l--)
            {
                nm = l-1;
                if (mag(rv1[l]) + anorm == anorm)
                {
                    flag = false;
                    break;
                }
                if (mag(S_[nm]) + anorm == anorm) break;
            }

            if (flag)
            {
                scalar c = 0.0;
                s = 1.0;
                for (label i = l-1; i < k+1; i++)
                {
                    scalar f = s*rv1[i];
                    rv1[i] = c*rv1[i];

                    if (mag(f) + anorm == anorm) break;

                    g = S_[i];
                    scalar h = sqrtSumSqr(f, g);
                    S_[i] = h;
                    h = 1.0/h;
                    c = g*h;
                    s = -f*h;

                    for (label j = 0; j < Un; j++)
                    {
                        scalar y = U_[j][nm];
                        scalar z = U_[j][i];
                        U_[j][nm] = y*c + z*s;
                        U_[j][i] = z*c - y*s;
                    }
                }
            }

            scalar z = S_[k];

            if (l == k)
            {
                if (z < 0.0)
                {
                    S_[k] = -z;

                    for (label j = 0; j < Um; j++) V_[j][k] = -V_[j][k];
                }
                break;
            }
            if (its == 34)
            {
                WarningIn
                (
                    "SVD::SVD"
                    "(scalarRectangularMatrix& A, const scalar minCondition)"
                )   << "no convergence in 35 SVD iterations"
                    << endl;
            }

            scalar x = S_[l];
            nm = k-1;
            scalar y = S_[nm];
            g = rv1[nm];
            scalar h = rv1[k];
            scalar f = ((y - z)*(y + z) + (g - h)*(g + h))/(2.0*h*y);
            g = sqrtSumSqr(f, scalar(1));
            f = ((x - z)*(x + z) + h*((y/(f + sign(g, f))) - h))/x;
            scalar c = 1.0;
            s = 1.0;

            for (label j = l; j <= nm; j++)
            {
                label i = j + 1;
                g = rv1[i];
                y = S_[i];
                h = s*g;
                g = c*g;
                scalar z = sqrtSumSqr(f, h);
                rv1[j] = z;
                c = f/z;
                s = h/z;
                f = x*c + g*s;
                g = g*c - x*s;
                h = y*s;
                y *= c;

                for (label jj = 0; jj < Um; jj++)
                {
                    x = V_[jj][j];
                    z = V_[jj][i];
                    V_[jj][j] = x*c + z*s;
                    V_[jj][i] = z*c - x*s;
                }

                z = sqrtSumSqr(f, h);
                S_[j] = z;
                if (z)
                {
                    z = 1.0/z;
                    c = f*z;
                    s = h*z;
                }
                f = c*g + s*y;
                x = c*y - s*g;

                for (label jj=0; jj < Un; jj++)
                {
                    y = U_[jj][j];
                    z = U_[jj][i];
                    U_[jj][j] = y*c + z*s;
                    U_[jj][i] = z*c - y*s;
                }
            }
            rv1[l] = 0.0;
            rv1[k] = f;
            S_[k] = x;
        }
    }

    // zero singular values that are less than minCondition*maxS
    const scalar minS = minCondition*S_[findMax(S_)];
    forAll(S_, i)
    {
        if (S_[i] <= minS)
        {
            //Info<< "Removing " << S_[i] << " < " << minS << endl;
            S_[i] = 0;
            nZeros_++;
        }
    }

    // now multiply out to find the pseudo inverse of A, VSinvUt_
    multiply(VSinvUt_, V_, inv(S_), U_.T());

    // test SVD
    /*scalarRectangularMatrix SVDA(A.n(), A.m());
    multiply(SVDA, U_, S_, transpose(V_));
    scalar maxDiff = 0;
    scalar diff = 0;
    for (label i = 0; i < A.n(); i++)
    {
        for (label j = 0; j < A.m(); j++)
        {
            diff = mag(A[i][j] - SVDA[i][j]);
            if (diff > maxDiff) maxDiff = diff;
        }
    }
    Info<< "Maximum discrepancy between A and svd(A) = " << maxDiff << endl;

    if (maxDiff > 4)
    {
        Info<< "singular values " << S_ << endl;
    }
    */
}
Пример #4
0
void SVD::decompose() {
	bool flag;
	Int i,its,j,jj,k,l,nm;
	Doub anorm,c,f,g,h,s,scale,x,y,z;
	VecDoub rv1(n);
	g = scale = anorm = 0.0;
	for (i=0;i<n;i++) {
		l=i+2;
		rv1[i]=scale*g;
		g=s=scale=0.0;
		if (i < m) {
			for (k=i;k<m;k++) scale += abs(u[k][i]);
			if (scale != 0.0) {
				for (k=i;k<m;k++) {
					u[k][i] /= scale;
					s += u[k][i]*u[k][i];
				}
				f=u[i][i];
				g = -SIGN(sqrt(s),f);
				h=f*g-s;
				u[i][i]=f-g;
				for (j=l-1;j<n;j++) {
					for (s=0.0,k=i;k<m;k++) s += u[k][i]*u[k][j];
					f=s/h;
					for (k=i;k<m;k++) u[k][j] += f*u[k][i];
				}
				for (k=i;k<m;k++) u[k][i] *= scale;
			}
		}
		w[i]=scale *g;
		g=s=scale=0.0;
		if (i+1 <= m && i+1 != n) {
			for (k=l-1;k<n;k++) scale += abs(u[i][k]);
			if (scale != 0.0) {
				for (k=l-1;k<n;k++) {
					u[i][k] /= scale;
					s += u[i][k]*u[i][k];
				}
				f=u[i][l-1];
				g = -SIGN(sqrt(s),f);
				h=f*g-s;
				u[i][l-1]=f-g;
				for (k=l-1;k<n;k++) rv1[k]=u[i][k]/h;
				for (j=l-1;j<m;j++) {
					for (s=0.0,k=l-1;k<n;k++) s += u[j][k]*u[i][k];
					for (k=l-1;k<n;k++) u[j][k] += s*rv1[k];
				}
				for (k=l-1;k<n;k++) u[i][k] *= scale;
			}
		}
		anorm=MAX(anorm,(abs(w[i])+abs(rv1[i])));
	}
	for (i=n-1;i>=0;i--) {
		if (i < n-1) {
			if (g != 0.0) {
				for (j=l;j<n;j++)
					v[j][i]=(u[i][j]/u[i][l])/g;
				for (j=l;j<n;j++) {
					for (s=0.0,k=l;k<n;k++) s += u[i][k]*v[k][j];
					for (k=l;k<n;k++) v[k][j] += s*v[k][i];
				}
			}
			for (j=l;j<n;j++) v[i][j]=v[j][i]=0.0;
		}
		v[i][i]=1.0;
		g=rv1[i];
		l=i;
	}
	for (i=MIN(m,n)-1;i>=0;i--) {
		l=i+1;
		g=w[i];
		for (j=l;j<n;j++) u[i][j]=0.0;
		if (g != 0.0) {
			g=1.0/g;
			for (j=l;j<n;j++) {
				for (s=0.0,k=l;k<m;k++) s += u[k][i]*u[k][j];
				f=(s/u[i][i])*g;
				for (k=i;k<m;k++) u[k][j] += f*u[k][i];
			}
			for (j=i;j<m;j++) u[j][i] *= g;
		} else for (j=i;j<m;j++) u[j][i]=0.0;
		++u[i][i];
	}
	for (k=n-1;k>=0;k--) {
		for (its=0;its<30;its++) {
			flag=true;
			for (l=k;l>=0;l--) {
				nm=l-1;
				if (l == 0 || abs(rv1[l]) <= eps*anorm) {
					flag=false;
					break;
				}
				if (abs(w[nm]) <= eps*anorm) break;
			}
			if (flag) {
				c=0.0;
				s=1.0;
				for (i=l;i<k+1;i++) {
					f=s*rv1[i];
					rv1[i]=c*rv1[i];
					if (abs(f) <= eps*anorm) break;
					g=w[i];
					h=pythag(f,g);
					w[i]=h;
					h=1.0/h;
					c=g*h;
					s = -f*h;
					for (j=0;j<m;j++) {
						y=u[j][nm];
						z=u[j][i];
						u[j][nm]=y*c+z*s;
						u[j][i]=z*c-y*s;
					}
				}
			}
			z=w[k];
			if (l == k) {
				if (z < 0.0) {
					w[k] = -z;
					for (j=0;j<n;j++) v[j][k] = -v[j][k];
				}
				break;
			}
			if (its == 29) throw("no convergence in 30 svdcmp iterations");
			x=w[l];
			nm=k-1;
			y=w[nm];
			g=rv1[nm];
			h=rv1[k];
			f=((y-z)*(y+z)+(g-h)*(g+h))/(2.0*h*y);
			g=pythag(f,1.0);
			f=((x-z)*(x+z)+h*((y/(f+SIGN(g,f)))-h))/x;
			c=s=1.0;
			for (j=l;j<=nm;j++) {
				i=j+1;
				g=rv1[i];
				y=w[i];
				h=s*g;
				g=c*g;
				z=pythag(f,h);
				rv1[j]=z;
				c=f/z;
				s=h/z;
				f=x*c+g*s;
				g=g*c-x*s;
				h=y*s;
				y *= c;
				for (jj=0;jj<n;jj++) {
					x=v[jj][j];
					z=v[jj][i];
					v[jj][j]=x*c+z*s;
					v[jj][i]=z*c-x*s;
				}
				z=pythag(f,h);
				w[j]=z;
				if (z) {
					z=1.0/z;
					c=f*z;
					s=h*z;
				}
				f=c*g+s*y;
				x=c*y-s*g;
				for (jj=0;jj<m;jj++) {
					y=u[jj][j];
					z=u[jj][i];
					u[jj][j]=y*c+z*s;
					u[jj][i]=z*c-y*s;
				}
			}
			rv1[l]=0.0;
			rv1[k]=f;
			w[k]=x;
		}
	}
}
Пример #5
0
bool
svdCoreT(AddressableMatrix<R> & U, long rows, long cols, S * D, AddressableMatrix<T> & V)
{
  static int const MAX_ITERATIONS = 30;

  if (rows == 0 && cols == 0)
    return true;

  debugAssertM(rows >= cols, "SVD: Matrix must have more rows than columns");

  long i, j, jj, k, l = 0, nm = 0;
  int flag, its;
  double c, f, h, s, x, y, z;
  double anorm = 0.0, g = 0.0, scale = 0.0;

  // Temp row vector
  TheaArray<double> rv1((array_size_t)cols);

  // Householder reduction to bidiagonal form
  for (i = 0; i < cols; ++i)
  {
    // Left-hand reduction
    l = i + 1;
    rv1[i] = scale * g;
    g = s = scale = 0.0;

    if (i < rows)
    {

      for (k = i; k < rows; ++k)
      {
        scale += std::fabs((double)U.get(k, i));
      }

      if (scale)
      {
        for (k = i; k < rows; ++k)
        {
          double x = (double)U.get(k, i) / scale;
          U.set(k, i, x);
          s += (x * x);
        }

        f = (double)U.get(i, i);

        g = -SVD_SIGN(std::sqrt(s), f);
        h = f * g - s;
        U.set(i, i, (R)(f - g));

        if (i != cols - 1)
        {
          for (j = l; j < cols; j++)
          {
            for (s = 0.0, k = i; k < rows; ++k)
            {
              s += ((double)U.get(k, i) * (double)U.get(k, j));
            }

            f = s / h;
            for (k = i; k < rows; ++k)
            {
              U.getMutable(k, j) += (R)(f * (double)U.get(k, i));
            }
          }
        }
        for (k = i; k < rows; ++k)
        {
          U.getMutable(k, i) *= (R)scale;
        }
      }
    }
    D[i] = (S)(scale * g);

    // right-hand reduction
    g = s = scale = 0.0;
    if (i < rows && i != cols - 1)
    {
      for (k = l; k < cols; ++k)
      {
        scale += std::fabs((double)U.get(i, k));
      }

      if (scale)
      {
        for (k = l; k < cols; ++k)
        {
          double x = (double)U.get(i, k) / scale;
          U.set(i, k, (R)x);
          s += (x * x);
        }

        f = (double)U.get(i, l);
        g = -SVD_SIGN(std::sqrt(s), f);
        h = f * g - s;
        U.set(i, l, (R)(f - g));

        for (k = l; k < cols; ++k)
        {
          rv1[k] = (double)U.get(i, k) / h;
        }

        if (i != rows - 1)
        {
          for (j = l; j < rows; ++j)
          {
            for (s = 0.0, k = l; k < cols; ++k)
            {
              s += ((double)U.get(j, k) * (double)U.get(i, k));
            }

            for (k = l; k < cols; ++k)
            {
              U.getMutable(j, k) += (R)(s * rv1[k]);
            }
          }
        }

        for (k = l; k < cols; ++k)
        {
          U.getMutable(i, k) *= (R)scale;
        }
      }
    }

    anorm = std::max(anorm, std::fabs((double)D[i]) + std::fabs(rv1[i]));
  }

  // accumulate the right-hand transformation
  for (i = cols - 1; i >= 0; --i)
  {
    if (i < cols - 1)
    {
      if (g != 0.0)
      {
        for (j = l; j < cols; j++)
        {
          V.set(j, i, (T)(((double)U.get(i, j) / (double)U.get(i, l)) / g));
        }

        // double division to avoid underflow
        for (j = l; j < cols; ++j)
        {
          for (s = 0.0, k = l; k < cols; k++) {
            s += ((double)U.get(i, k) * (double)V.get(k, j));
          }

          for (k = l; k < cols; ++k)
          {
            V.getMutable(k, j) += (T)(s * (double)V.get(k, i));
          }
        }
      }

      for (j = l; j < cols; ++j)
      {
        V.set(i, j, 0.0);
        V.set(j, i, 0.0);
      }
    }

    V.set(i, i, 1.0);
    g = rv1[i];
    l = i;
  }

  // accumulate the left-hand transformation
  for (i = cols - 1; i >= 0; --i)
  {
    l = i + 1;
    g = (double)D[i];
    if (i < cols - 1)
    {
      for (j = l; j < cols; ++j)
      {
        U.set(i, j, 0.0);
      }
    }

    if (g)
    {
      g = 1.0 / g;
      if (i != cols - 1)
      {
        for (j = l; j < cols; ++j)
        {
          for (s = 0.0, k = l; k < rows; ++k)
          {
            s += ((double)U.get(k, i) * (double)U.get(k, j));
          }

          f = (s / (double)U.get(i, i)) * g;

          for (k = i; k < rows; ++k)
          {
            U.getMutable(k, j) += (R)(f * (double)U.get(k, i));
          }
        }
      }

      for (j = i; j < rows; ++j)
      {
        U.getMutable(j, i) *= (R)g;
      }
    }
    else
    {
      for (j = i; j < rows; ++j)
      {
        U.set(j, i, 0.0);
      }
    }
    U.getMutable(i, i)++;
  }

  // diagonalize the bidiagonal form
  for (k = cols - 1; k >= 0; --k)
  {
    // loop over singular values
    for (its = 0; its < MAX_ITERATIONS; ++its)
    {
      // loop over allowed iterations
      flag = 1;

      for (l = k; l >= 0; --l)
      {
        // test for splitting
        nm = l - 1;
        if (std::fabs(rv1[l]) + anorm == anorm)
        {
          flag = 0;
          break;
        }

        if (std::fabs((double)D[nm]) + anorm == anorm)
        {
          break;
        }
      }

      if (flag)
      {
        c = 0.0;
        s = 1.0;
        for (i = l; i <= k; ++i)
        {
          f = s * rv1[i];
          if (std::fabs(f) + anorm != anorm)
          {
            g = (double)D[i];
            h = pythag(f, g);
            D[i] = (S)h;
            h = 1.0 / h;
            c = g * h;
            s = (- f * h);
            for (j = 0; j < rows; ++j)
            {
              y = (double)U.get(j, nm);
              z = (double)U.get(j, i);
              U.set(j, nm, (R)(y * c + z * s));
              U.set(j, i, (R)(z * c - y * s));
            }
          }
        }
      }

      z = (double)D[k];
      if (l == k)
      {
        // convergence
        if (z < 0.0)
        {
          // make singular value nonnegative
          D[k] = (S)(-z);

          for (j = 0; j < cols; ++j)
          {
            V.set(j, k, -V.get(j, k));
          }
        }
        break;
      }

      if (its >= MAX_ITERATIONS)
      {
        THEA_DEBUG << "SVD: Failed to converge";
        return false;
      }

      // shift from bottom 2 x 2 minor
      x = (double)D[l];
      nm = k - 1;
      y = (double)D[nm];
      g = rv1[nm];
      h = rv1[k];
      f = ((y - z) * (y + z) + (g - h) * (g + h)) / (2.0 * h * y);
      g = pythag(f, 1.0);
      f = ((x - z) * (x + z) + h * ((y / (f + SVD_SIGN(g, f))) - h)) / x;

      // next QR transformation
      c = s = 1.0;
      for (j = l; j <= nm; ++j)
      {
        i = j + 1;
        g = rv1[i];
        y = (double)D[i];
        h = s * g;
        g = c * g;
        z = pythag(f, h);
        rv1[j] = z;
        c = f / z;
        s = h / z;
        f = x * c + g * s;
        g = g * c - x * s;
        h = y * s;
        y = y * c;

        for (jj = 0; jj < cols; ++jj)
        {
          x = (double)V.get(jj, j);
          z = (double)V.get(jj, i);
          V.set(jj, j, (T)(x * c + z * s));
          V.set(jj, i, (T)(z * c - x * s));
        }
        z = pythag(f, h);
        D[j] = (S)z;
        if (z)
        {
          z = 1.0 / z;
          c = f * z;
          s = h * z;
        }
        f = (c * g) + (s * y);
        x = (c * y) - (s * g);
        for (jj = 0; jj < rows; jj++)
        {
          y = (double)U.get(jj, j);
          z = (double)U.get(jj, i);
          U.set(jj, j, (R)(y * c + z * s));
          U.set(jj, i, (R)(z * c - y * s));
        }
      }
      rv1[l] = 0.0;
      rv1[k] = f;
      D[k] = (S)x;
    }
  }

  // So far V actually contains V^T, so we transpose V in-place
  for (i = 0; i < rows; ++i)
    for (j = i + 1; j < cols; ++j)
      std::swap(V.getMutable(i, j), V.getMutable(j, i));

  return true;
}
bool obsoletesvddecomposition(ap::real_2d_array& a,
     int m,
     int n,
     ap::real_1d_array& w,
     ap::real_2d_array& v)
{
    bool result;
    int nm;
    int minmn;
    int l;
    int k;
    int j;
    int jj;
    int its;
    int i;
    double z;
    double y;
    double x;
    double vscale;
    double s;
    double h;
    double g;
    double f;
    double c;
    double anorm;
    ap::real_1d_array rv1;
    bool flag;

    rv1.setbounds(1, n);
    w.setbounds(1, n);
    v.setbounds(1, n, 1, n);
    result = true;
    if( m<n )
    {
        minmn = m;
    }
    else
    {
        minmn = n;
    }
    g = 0.0;
    vscale = 0.0;
    anorm = 0.0;
    for(i = 1; i <= n; i++)
    {
        l = i+1;
        rv1(i) = vscale*g;
        g = 0;
        s = 0;
        vscale = 0;
        if( i<=m )
        {
            for(k = i; k <= m; k++)
            {
                vscale = vscale+fabs(a(k,i));
            }
            if( ap::fp_neq(vscale,0.0) )
            {
                for(k = i; k <= m; k++)
                {
                    a(k,i) = a(k,i)/vscale;
                    s = s+a(k,i)*a(k,i);
                }
                f = a(i,i);
                g = -extsign(sqrt(s), f);
                h = f*g-s;
                a(i,i) = f-g;
                if( i!=n )
                {
                    for(j = l; j <= n; j++)
                    {
                        s = 0.0;
                        for(k = i; k <= m; k++)
                        {
                            s = s+a(k,i)*a(k,j);
                        }
                        f = s/h;
                        for(k = i; k <= m; k++)
                        {
                            a(k,j) = a(k,j)+f*a(k,i);
                        }
                    }
                }
                for(k = i; k <= m; k++)
                {
                    a(k,i) = vscale*a(k,i);
                }
            }
        }
        w(i) = vscale*g;
        g = 0.0;
        s = 0.0;
        vscale = 0.0;
        if( i<=m&&i!=n )
        {
            for(k = l; k <= n; k++)
            {
                vscale = vscale+fabs(a(i,k));
            }
            if( ap::fp_neq(vscale,0.0) )
            {
                for(k = l; k <= n; k++)
                {
                    a(i,k) = a(i,k)/vscale;
                    s = s+a(i,k)*a(i,k);
                }
                f = a(i,l);
                g = -extsign(sqrt(s), f);
                h = f*g-s;
                a(i,l) = f-g;
                for(k = l; k <= n; k++)
                {
                    rv1(k) = a(i,k)/h;
                }
                if( i!=m )
                {
                    for(j = l; j <= m; j++)
                    {
                        s = 0.0;
                        for(k = l; k <= n; k++)
                        {
                            s = s+a(j,k)*a(i,k);
                        }
                        for(k = l; k <= n; k++)
                        {
                            a(j,k) = a(j,k)+s*rv1(k);
                        }
                    }
                }
                for(k = l; k <= n; k++)
                {
                    a(i,k) = vscale*a(i,k);
                }
            }
        }
        anorm = mymax(anorm, fabs(w(i))+fabs(rv1(i)));
    }
    for(i = n; i >= 1; i--)
    {
        if( i<n )
        {
            if( ap::fp_neq(g,0.0) )
            {
                for(j = l; j <= n; j++)
                {
                    v(j,i) = a(i,j)/a(i,l)/g;
                }
                for(j = l; j <= n; j++)
                {
                    s = 0.0;
                    for(k = l; k <= n; k++)
                    {
                        s = s+a(i,k)*v(k,j);
                    }
                    for(k = l; k <= n; k++)
                    {
                        v(k,j) = v(k,j)+s*v(k,i);
                    }
                }
            }
            for(j = l; j <= n; j++)
            {
                v(i,j) = 0.0;
                v(j,i) = 0.0;
            }
        }
        v(i,i) = 1.0;
        g = rv1(i);
        l = i;
    }
    for(i = minmn; i >= 1; i--)
    {
        l = i+1;
        g = w(i);
        if( i<n )
        {
            for(j = l; j <= n; j++)
            {
                a(i,j) = 0.0;
            }
        }
        if( ap::fp_neq(g,0.0) )
        {
            g = 1.0/g;
            if( i!=n )
            {
                for(j = l; j <= n; j++)
                {
                    s = 0.0;
                    for(k = l; k <= m; k++)
                    {
                        s = s+a(k,i)*a(k,j);
                    }
                    f = s/a(i,i)*g;
                    for(k = i; k <= m; k++)
                    {
                        a(k,j) = a(k,j)+f*a(k,i);
                    }
                }
            }
            for(j = i; j <= m; j++)
            {
                a(j,i) = a(j,i)*g;
            }
        }
        else
        {
            for(j = i; j <= m; j++)
            {
                a(j,i) = 0.0;
            }
        }
        a(i,i) = a(i,i)+1.0;
    }
    for(k = n; k >= 1; k--)
    {
        for(its = 1; its <= maxsvditerations; its++)
        {
            flag = true;
            for(l = k; l >= 1; l--)
            {
                nm = l-1;
                if( ap::fp_eq(fabs(rv1(l))+anorm,anorm) )
                {
                    flag = false;
                    break;
                }
                if( ap::fp_eq(fabs(w(nm))+anorm,anorm) )
                {
                    break;
                }
            }
            if( flag )
            {
                c = 0.0;
                s = 1.0;
                for(i = l; i <= k; i++)
                {
                    f = s*rv1(i);
                    if( ap::fp_neq(fabs(f)+anorm,anorm) )
                    {
                        g = w(i);
                        h = pythag(f, g);
                        w(i) = h;
                        h = 1.0/h;
                        c = g*h;
                        s = -f*h;
                        for(j = 1; j <= m; j++)
                        {
                            y = a(j,nm);
                            z = a(j,i);
                            a(j,nm) = y*c+z*s;
                            a(j,i) = -y*s+z*c;
                        }
                    }
                }
            }
            z = w(k);
            if( l==k )
            {
                if( ap::fp_less(z,0.0) )
                {
                    w(k) = -z;
                    for(j = 1; j <= n; j++)
                    {
                        v(j,k) = -v(j,k);
                    }
                }
                break;
            }
            if( its==maxsvditerations )
            {
                result = false;
                return result;
            }
            x = w(l);
            nm = k-1;
            y = w(nm);
            g = rv1(nm);
            h = rv1(k);
            f = ((y-z)*(y+z)+(g-h)*(g+h))/(2.0*h*y);
            g = pythag(f, double(1));
            f = ((x-z)*(x+z)+h*(y/(f+extsign(g, f))-h))/x;
            c = 1.0;
            s = 1.0;
            for(j = l; j <= nm; j++)
            {
                i = j+1;
                g = rv1(i);
                y = w(i);
                h = s*g;
                g = c*g;
                z = pythag(f, h);
                rv1(j) = z;
                c = f/z;
                s = h/z;
                f = x*c+g*s;
                g = -x*s+g*c;
                h = y*s;
                y = y*c;
                for(jj = 1; jj <= n; jj++)
                {
                    x = v(jj,j);
                    z = v(jj,i);
                    v(jj,j) = x*c+z*s;
                    v(jj,i) = -x*s+z*c;
                }
                z = pythag(f, h);
                w(j) = z;
                if( ap::fp_neq(z,0.0) )
                {
                    z = 1.0/z;
                    c = f*z;
                    s = h*z;
                }
                f = c*g+s*y;
                x = -s*g+c*y;
                for(jj = 1; jj <= m; jj++)
                {
                    y = a(jj,j);
                    z = a(jj,i);
                    a(jj,j) = y*c+z*s;
                    a(jj,i) = -y*s+z*c;
                }
            }
            rv1(l) = 0.0;
            rv1(k) = f;
            w(k) = x;
        }
    }
    return result;
}