예제 #1
0
		///<summary>Computes the algorithm.</summary>
		protected override void InternalCompute()
		{
			rows = matrix.RowLength;
			cols = matrix.ColumnLength;
			int mm = System.Math.Min(rows + 1, cols);
			s = new FloatVector(mm); // singular values

#if MANAGED
			// Derived from LINPACK code.
			// Initialize.

			u = new FloatMatrix(rows, rows); // left vectors
			v = new FloatMatrix(cols, cols); // right vectors
			FloatVector e = new FloatVector(cols);
			FloatVector work = new FloatVector(rows);

			int i, iter, j, k, kase, l, lp1, ls = 0, lu, m, nct, nctp1, ncu, nrt, nrtp1;
			float b, c, cs = 0.0f, el, emm1, f, g, scale, shift, sl,
				sm, sn = 0.0f, smm1, t1, test, ztest, xnorm, enorm;
			float t, r;

			ncu = rows;

			//   reduce matrix to bidiagonal form, storing the diagonal elements
			//   in s and the super-diagonal elements in e.
			int info = 0;
			nct = System.Math.Min(rows - 1, cols);
			nrt = System.Math.Max(0, System.Math.Min(cols - 2, rows));
			lu = System.Math.Max(nct, nrt);

			for (l = 0; l < lu; l++)
			{
				lp1 = l + 1;
				if (l < nct)
				{
					// compute the transformation for the l-th column and
					// place the l-th diagonal in s[l].
					xnorm = dnrm2Column(matrix, l, l);
					s[l] = xnorm;
					if (s[l] != 0.0f)
					{
						if (matrix[l, l] != 0.0f)
						{
							s[l] = dsign(s[l], matrix[l, l]);
						}
						dscalColumn(matrix, l, l, 1.0f / s[l]);
						matrix[l, l] = 1.0f + matrix[l, l];
					}

					s[l] = -s[l];
				}

				for (j = lp1; j < cols; j++)
				{
					if (l < nct)
					{
						if (s[l] != 0.0f)
						{
							// apply the transformation.
							t = -ddot(matrix, l, j, l) / matrix[l, l];
							for (int ii = l; ii < matrix.RowLength; ii++)
							{
								matrix[ii, j] += t * matrix[ii, l];
							}
						}
					}

					//place the l-th row of matrix into  e for the
					//subsequent calculation of the row transformation.
					e[j] = matrix[l, j];
				}

				if (computeVectors && l < nct)
				{
					// place the transformation in u for subsequent back multiplication.
					for (i = l; i < rows; i++)
					{
						u[i, l] = matrix[i, l];
					}
				}

				if (l < nrt)
				{
					// compute the l-th row transformation and place the l-th super-diagonal in e(l).
					enorm = dnrm2Vector(e, lp1);
					e[l] = enorm;
					if (e[l] != 0.0f)
					{
						if (e[lp1] != 0.0f)
						{
							e[l] = dsign(e[l], e[lp1]);
						}
						dscalVector(e, lp1, 1.0f / e[l]);
						e[lp1] = 1.0f + e[lp1];
					}
					e[l] = -e[l];

					if (lp1 < rows && e[l] != 0.0f)
					{
						// apply the transformation.
						for (i = lp1; i < rows; i++)
						{
							work[i] = 0.0f;
						}

						for (j = lp1; j < cols; j++)
						{
							for (int ii = lp1; ii < matrix.RowLength; ii++)
							{
								work[ii] += e[j] * matrix[ii, j];
							}
						}

						for (j = lp1; j < cols; j++)
						{
							float ww = -e[j] / e[lp1];
							for (int ii = lp1; ii < matrix.RowLength; ii++)
							{
								matrix[ii, j] += ww * work[ii];
							}
						}
					}

					if (computeVectors)
					{
						// place the transformation in v for subsequent back multiplication.
						for (i = lp1; i < cols; i++)
						{
							v[i, l] = e[i];
						}
					}
				}
			}

			//   set up the final bidiagonal matrix or order m.
			m = System.Math.Min(cols, rows + 1);
			nctp1 = nct + 1;
			nrtp1 = nrt + 1;
			if (nct < cols)
			{
				s[nctp1 - 1] = matrix[nctp1 - 1, nctp1 - 1];
			}
			if (rows < m)
			{
				s[m - 1] = 0.0f;
			}
			if (nrtp1 < m)
			{
				e[nrtp1 - 1] = matrix[nrtp1 - 1, m - 1];
			}
			e[m - 1] = 0.0f;

			//   if required, generate u.
			if (computeVectors)
			{
				for (j = nctp1 - 1; j < ncu; j++)
				{
					for (i = 0; i < rows; i++)
					{
						u[i, j] = 0.0f;
					}
					u[j, j] = 1.0f;
				}

				for (l = nct - 1; l >= 0; l--)
				{
					if (s[l] != 0.0f)
					{
						for (j = l + 1; j < ncu; j++)
						{
							t = -ddot(u, l, j, l) / u[l, l];
							for (int ii = l; ii < u.RowLength; ii++)
							{
								u[ii, j] += t * u[ii, l];
							}
						}
						dscalColumn(u, l, l, -1.0f);
						u[l, l] = 1.0f + u[l, l];
						for (i = 0; i < l; i++)
						{
							u[i, l] = 0.0f;
						}
					}
					else
					{
						for (i = 0; i < rows; i++)
						{
							u[i, l] = 0.0f;
						}
						u[l, l] = 1.0f;
					}
				}
			}

			//   if it is required, generate v.
			if (computeVectors)
			{
				for (l = cols - 1; l >= 0; l--)
				{
					lp1 = l + 1;
					if (l < nrt)
					{
						if (e[l] != 0.0f)
						{
							for (j = lp1; j < cols; j++)
							{
								t = -ddot(v, l, j, lp1) / v[lp1, l];
								for (int ii = l; ii < v.RowLength; ii++)
								{
									v[ii, j] += t * v[ii, l];
								}
							}
						}
					}
					for (i = 0; i < cols; i++)
					{
						v[i, l] = 0.0f;
					}
					v[l, l] = 1.0f;
				}
			}

			//   transform s and e so that they are  float .
			for (i = 0; i < m; i++)
			{
				if (s[i] != 0.0f)
				{
					t = s[i];
					r = s[i] / t;
					s[i] = t;
					if (i < m - 1)
					{
						e[i] = e[i] / r;
					}
					if (computeVectors)
					{
						dscalColumn(u, i, 0, r);
					}
				}
				//   ...exit
				if (i == m - 1)
				{
					break;
				}
				if (e[i] != 0.0)
				{
					t = e[i];
					r = t / e[i];
					e[i] = t;
					s[i + 1] = s[i + 1] * r;
					if (computeVectors)
					{
						dscalColumn(v, i + 1, 0, r);
					}
				}
			}

			//   main iteration loop for the singular values.
			mm = m;
			iter = 0;

			while (m > 0)
			{ // quit if all the singular values have been found.
				// if too many iterations have been performed, set
				//      flag and return.
				if (iter >= MAXITER)
				{
					info = m;
					//   ......exit
					break;
				}

				//      this section of the program inspects for
				//      negligible elements in the s and e arrays.  on
				//      completion the variables kase and l are set as follows.

				//         kase = 1     if s[m] and e[l-1] are negligible and l < m
				//         kase = 2     if s[l] is negligible and l < m
				//         kase = 3     if e[l-1] is negligible, l < m, and
				//                      s[l, ..., s[m] are not negligible (qr step).
				//         kase = 4     if e[m-1] is negligible (convergence).

				for (l = m - 2; l >= 0; l--)
				{
					test = ComplexMath.Absolute(s[l]) + ComplexMath.Absolute(s[l + 1]);
					ztest = test + ComplexMath.Absolute(e[l]);
					if (ztest == test)
					{
						e[l] = 0.0f;
						break;
					}
				}

				if (l == m - 2)
				{
					kase = 4;
				}
				else
				{
					for (ls = m - 1; ls > l; ls--)
					{
						test = 0.0f;
						if (ls != m - 1)
						{
							test = test + ComplexMath.Absolute(e[ls]);
						}
						if (ls != l + 1)
						{
							test = test + ComplexMath.Absolute(e[ls - 1]);
						}
						ztest = test + ComplexMath.Absolute(s[ls]);
						if (ztest == test)
						{
							s[ls] = 0.0f;
							break;
						}
					}

					if (ls == l)
					{
						kase = 3;
					}
					else if (ls == m - 1)
					{
						kase = 1;
					}
					else
					{
						kase = 2;
						l = ls;
					}
				}

				l = l + 1;

				//      perform the task indicated by kase.
				switch (kase)
				{
					// deflate negligible s[m].
					case 1:
						f = e[m - 2];
						e[m - 2] = 0.0f;
						for (k = m - 2; k >= 0; k--)
						{
							t1 = s[k];
							drotg(ref t1, ref f, ref cs, ref sn);
							s[k] = t1;
							if (k != l)
							{
								f = -sn * e[k - 1];
								e[k - 1] = cs * e[k - 1];
							}
							if (computeVectors)
							{
								drot(v, k, m - 1, cs, sn);
							}
						}
						break;

					// split at negligible s[l].
					case 2:
						f = e[l - 1];
						e[l - 1] = 0.0f;
						for (k = l; k < m; k++)
						{
							t1 = s[k];
							drotg(ref t1, ref f, ref cs, ref sn);
							s[k] = t1;
							f = -sn * e[k];
							e[k] = cs * e[k];
							if (computeVectors)
							{
								drot(u, k, l - 1, cs, sn);
							}
						}
						break;

					// perform one qr step.
					case 3:
						// calculate the shift.
						scale = 0.0f;
						scale = System.Math.Max(scale, ComplexMath.Absolute(s[m - 1]));
						scale = System.Math.Max(scale, ComplexMath.Absolute(s[m - 2]));
						scale = System.Math.Max(scale, ComplexMath.Absolute(e[m - 2]));
						scale = System.Math.Max(scale, ComplexMath.Absolute(s[l]));
						scale = System.Math.Max(scale, ComplexMath.Absolute(e[l]));
						sm = s[m - 1] / scale;
						smm1 = s[m - 2] / scale;
						emm1 = e[m - 2] / scale;
						sl = s[l] / scale;
						el = e[l] / scale;
						b = ((smm1 + sm) * (smm1 - sm) + emm1 * emm1) / 2.0f;
						c = (sm * emm1) * (sm * emm1);
						shift = 0.0f;
						if (b != 0.0f || c != 0.0f)
						{
							shift = (float)System.Math.Sqrt(b * b + c);
							if (b < 0.0f)
							{
								shift = -shift;
							}
							shift = c / (b + shift);
						}
						f = (sl + sm) * (sl - sm) + shift;
						g = sl * el;

						// chase zeros.
						for (k = l; k < m - 1; k++)
						{
							drotg(ref f, ref g, ref cs, ref sn);
							if (k != l) e[k - 1] = f;
							f = cs * s[k] + sn * e[k];
							e[k] = cs * e[k] - sn * s[k];
							g = sn * s[k + 1];
							s[k + 1] = cs * s[k + 1];
							if (computeVectors)
							{
								drot(v, k, k + 1, cs, sn);
							}
							drotg(ref f, ref g, ref cs, ref sn);
							s[k] = f;
							f = cs * e[k] + sn * s[k + 1];
							s[k + 1] = -sn * e[k] + cs * s[k + 1];
							g = sn * e[k + 1];
							e[k + 1] = cs * e[k + 1];
							if (computeVectors && k < rows)
							{
								drot(u, k, k + 1, cs, sn);
							}
						}
						e[m - 2] = f;
						iter = iter + 1;
						break;

					// convergence.
					case 4:
						// make the singular value  positive
						if (s[l] < 0.0f)
						{
							s[l] = -s[l];
							if (computeVectors)
							{
								dscalColumn(v, l, 0, -1.0f);
							}
						}

						// order the singular value.
						while (l != mm - 1)
						{
							if (s[l] >= s[l + 1])
							{
								break;
							}
							t = s[l];
							s[l] = s[l + 1];
							s[l + 1] = t;
							if (computeVectors && l < cols)
							{
								dswap(v, l, l + 1);
							}
							if (computeVectors && l < rows)
							{
								dswap(u, l, l + 1);
							}
							l = l + 1;
						}
						iter = 0;
						m = m - 1;
						break;
				}
			}

			// make matrix w from vector s
			// there is no constructor, creating diagonal matrix from vector
			// doing it ourselves
			mm = System.Math.Min(matrix.RowLength, matrix.ColumnLength);
#else
      u = new FloatMatrix(rows);
      v = new FloatMatrix(cols);
      float[] a = new float[matrix.data.Length];
      Array.Copy(matrix.data, a, matrix.data.Length);
      Lapack.Gesvd.Compute(rows, cols, a, s.data, u.data, v.data );
      v.Transpose();
#endif
			w = new FloatMatrix(matrix.RowLength, matrix.ColumnLength);
			for (int ii = 0; ii < matrix.RowLength; ii++)
			{
				for (int jj = 0; jj < matrix.ColumnLength; jj++)
				{
					if (ii == jj)
					{
						w[ii, ii] = s[ii];
					}
				}
			}

			float eps = (float)System.Math.Pow(2.0, -52.0);
			float tol = (float)System.Math.Max(matrix.RowLength, matrix.ColumnLength) * s[0] * eps;
			rank = 0;

			for (int h = 0; h < mm; h++)
			{
				if (s[h] > tol)
				{
					rank++;
				}
			}

			if (!computeVectors)
			{
				u = null;
				v = null;
			}
			matrix = null;
		}
예제 #2
0
		public void TransposeLong()
		{
			FloatMatrix a = new FloatMatrix(3, 2);
			a[0, 0] = 1;
			a[0, 1] = 2;
			a[1, 0] = 3;
			a[1, 1] = 4;
			a[2, 0] = 5;
			a[2, 1] = 6;
			a.Transpose();
			Assert.AreEqual(a[0, 0], 1);
			Assert.AreEqual(a[0, 1], 3);
			Assert.AreEqual(a[0, 2], 5);
			Assert.AreEqual(a[1, 0], 2);
			Assert.AreEqual(a[1, 1], 4);
			Assert.AreEqual(a[1, 2], 6);
			Assert.AreEqual(a.RowLength, 2);
			Assert.AreEqual(a.ColumnLength, 3);
		}
예제 #3
0
        ///<summary>Computes the algorithm.</summary>
        protected override void InternalCompute()
        {
            rows = matrix.RowLength;
            cols = matrix.ColumnLength;
            int mm = System.Math.Min(rows + 1, cols);

            s = new FloatVector(mm); // singular values

#if MANAGED
            // Derived from LINPACK code.
            // Initialize.

            u = new FloatMatrix(rows, rows); // left vectors
            v = new FloatMatrix(cols, cols); // right vectors
            var e    = new FloatVector(cols);
            var work = new FloatVector(rows);

            int   i, iter, j, k, kase, l, lp1, ls = 0, lu, m, nct, nctp1, ncu, nrt, nrtp1;
            float b, c, cs = 0.0f, el, emm1, f, g, scale, shift, sl,
                  sm, sn = 0.0f, smm1, t1, test, ztest, xnorm, enorm;
            float t, r;

            ncu = rows;

            //   reduce matrix to bidiagonal form, storing the diagonal elements
            //   in s and the super-diagonal elements in e.
            int info = 0;
            nct = System.Math.Min(rows - 1, cols);
            nrt = System.Math.Max(0, System.Math.Min(cols - 2, rows));
            lu  = System.Math.Max(nct, nrt);

            for (l = 0; l < lu; l++)
            {
                lp1 = l + 1;
                if (l < nct)
                {
                    // compute the transformation for the l-th column and
                    // place the l-th diagonal in s[l].
                    xnorm = dnrm2Column(matrix, l, l);
                    s[l]  = xnorm;
                    if (s[l] != 0.0f)
                    {
                        if (matrix[l, l] != 0.0f)
                        {
                            s[l] = dsign(s[l], matrix[l, l]);
                        }
                        dscalColumn(matrix, l, l, 1.0f / s[l]);
                        matrix[l, l] = 1.0f + matrix[l, l];
                    }

                    s[l] = -s[l];
                }

                for (j = lp1; j < cols; j++)
                {
                    if (l < nct)
                    {
                        if (s[l] != 0.0f)
                        {
                            // apply the transformation.
                            t = -ddot(matrix, l, j, l) / matrix[l, l];
                            for (int ii = l; ii < matrix.RowLength; ii++)
                            {
                                matrix[ii, j] += t * matrix[ii, l];
                            }
                        }
                    }

                    //place the l-th row of matrix into  e for the
                    //subsequent calculation of the row transformation.
                    e[j] = matrix[l, j];
                }

                if (computeVectors && l < nct)
                {
                    // place the transformation in u for subsequent back multiplication.
                    for (i = l; i < rows; i++)
                    {
                        u[i, l] = matrix[i, l];
                    }
                }

                if (l < nrt)
                {
                    // compute the l-th row transformation and place the l-th super-diagonal in e(l).
                    enorm = dnrm2Vector(e, lp1);
                    e[l]  = enorm;
                    if (e[l] != 0.0f)
                    {
                        if (e[lp1] != 0.0f)
                        {
                            e[l] = dsign(e[l], e[lp1]);
                        }
                        dscalVector(e, lp1, 1.0f / e[l]);
                        e[lp1] = 1.0f + e[lp1];
                    }
                    e[l] = -e[l];

                    if (lp1 < rows && e[l] != 0.0f)
                    {
                        // apply the transformation.
                        for (i = lp1; i < rows; i++)
                        {
                            work[i] = 0.0f;
                        }

                        for (j = lp1; j < cols; j++)
                        {
                            for (int ii = lp1; ii < matrix.RowLength; ii++)
                            {
                                work[ii] += e[j] * matrix[ii, j];
                            }
                        }

                        for (j = lp1; j < cols; j++)
                        {
                            float ww = -e[j] / e[lp1];
                            for (int ii = lp1; ii < matrix.RowLength; ii++)
                            {
                                matrix[ii, j] += ww * work[ii];
                            }
                        }
                    }

                    if (computeVectors)
                    {
                        // place the transformation in v for subsequent back multiplication.
                        for (i = lp1; i < cols; i++)
                        {
                            v[i, l] = e[i];
                        }
                    }
                }
            }

            //   set up the final bidiagonal matrix or order m.
            m     = System.Math.Min(cols, rows + 1);
            nctp1 = nct + 1;
            nrtp1 = nrt + 1;
            if (nct < cols)
            {
                s[nctp1 - 1] = matrix[nctp1 - 1, nctp1 - 1];
            }
            if (rows < m)
            {
                s[m - 1] = 0.0f;
            }
            if (nrtp1 < m)
            {
                e[nrtp1 - 1] = matrix[nrtp1 - 1, m - 1];
            }
            e[m - 1] = 0.0f;

            //   if required, generate u.
            if (computeVectors)
            {
                for (j = nctp1 - 1; j < ncu; j++)
                {
                    for (i = 0; i < rows; i++)
                    {
                        u[i, j] = 0.0f;
                    }
                    u[j, j] = 1.0f;
                }

                for (l = nct - 1; l >= 0; l--)
                {
                    if (s[l] != 0.0f)
                    {
                        for (j = l + 1; j < ncu; j++)
                        {
                            t = -ddot(u, l, j, l) / u[l, l];
                            for (int ii = l; ii < u.RowLength; ii++)
                            {
                                u[ii, j] += t * u[ii, l];
                            }
                        }
                        dscalColumn(u, l, l, -1.0f);
                        u[l, l] = 1.0f + u[l, l];
                        for (i = 0; i < l; i++)
                        {
                            u[i, l] = 0.0f;
                        }
                    }
                    else
                    {
                        for (i = 0; i < rows; i++)
                        {
                            u[i, l] = 0.0f;
                        }
                        u[l, l] = 1.0f;
                    }
                }
            }

            //   if it is required, generate v.
            if (computeVectors)
            {
                for (l = cols - 1; l >= 0; l--)
                {
                    lp1 = l + 1;
                    if (l < nrt)
                    {
                        if (e[l] != 0.0f)
                        {
                            for (j = lp1; j < cols; j++)
                            {
                                t = -ddot(v, l, j, lp1) / v[lp1, l];
                                for (int ii = l; ii < v.RowLength; ii++)
                                {
                                    v[ii, j] += t * v[ii, l];
                                }
                            }
                        }
                    }
                    for (i = 0; i < cols; i++)
                    {
                        v[i, l] = 0.0f;
                    }
                    v[l, l] = 1.0f;
                }
            }

            //   transform s and e so that they are  float .
            for (i = 0; i < m; i++)
            {
                if (s[i] != 0.0f)
                {
                    t    = s[i];
                    r    = s[i] / t;
                    s[i] = t;
                    if (i < m - 1)
                    {
                        e[i] = e[i] / r;
                    }
                    if (computeVectors)
                    {
                        dscalColumn(u, i, 0, r);
                    }
                }
                //   ...exit
                if (i == m - 1)
                {
                    break;
                }
                if (e[i] != 0.0)
                {
                    t        = e[i];
                    r        = t / e[i];
                    e[i]     = t;
                    s[i + 1] = s[i + 1] * r;
                    if (computeVectors)
                    {
                        dscalColumn(v, i + 1, 0, r);
                    }
                }
            }

            //   main iteration loop for the singular values.
            mm   = m;
            iter = 0;

            while (m > 0)
            { // quit if all the singular values have been found.
              // if too many iterations have been performed, set
              //      flag and return.
                if (iter >= MAXITER)
                {
                    info = m;
                    //   ......exit
                    break;
                }

                //      this section of the program inspects for
                //      negligible elements in the s and e arrays.  on
                //      completion the variables kase and l are set as follows.

                //         kase = 1     if s[m] and e[l-1] are negligible and l < m
                //         kase = 2     if s[l] is negligible and l < m
                //         kase = 3     if e[l-1] is negligible, l < m, and
                //                      s[l, ..., s[m] are not negligible (qr step).
                //         kase = 4     if e[m-1] is negligible (convergence).

                for (l = m - 2; l >= 0; l--)
                {
                    test  = ComplexMath.Absolute(s[l]) + ComplexMath.Absolute(s[l + 1]);
                    ztest = test + ComplexMath.Absolute(e[l]);
                    if (ztest == test)
                    {
                        e[l] = 0.0f;
                        break;
                    }
                }

                if (l == m - 2)
                {
                    kase = 4;
                }
                else
                {
                    for (ls = m - 1; ls > l; ls--)
                    {
                        test = 0.0f;
                        if (ls != m - 1)
                        {
                            test = test + ComplexMath.Absolute(e[ls]);
                        }
                        if (ls != l + 1)
                        {
                            test = test + ComplexMath.Absolute(e[ls - 1]);
                        }
                        ztest = test + ComplexMath.Absolute(s[ls]);
                        if (ztest == test)
                        {
                            s[ls] = 0.0f;
                            break;
                        }
                    }

                    if (ls == l)
                    {
                        kase = 3;
                    }
                    else if (ls == m - 1)
                    {
                        kase = 1;
                    }
                    else
                    {
                        kase = 2;
                        l    = ls;
                    }
                }

                l = l + 1;

                //      perform the task indicated by kase.
                switch (kase)
                {
                // deflate negligible s[m].
                case 1:
                    f        = e[m - 2];
                    e[m - 2] = 0.0f;
                    for (k = m - 2; k >= 0; k--)
                    {
                        t1 = s[k];
                        drotg(ref t1, ref f, ref cs, ref sn);
                        s[k] = t1;
                        if (k != l)
                        {
                            f        = -sn * e[k - 1];
                            e[k - 1] = cs * e[k - 1];
                        }
                        if (computeVectors)
                        {
                            drot(v, k, m - 1, cs, sn);
                        }
                    }
                    break;

                // split at negligible s[l].
                case 2:
                    f        = e[l - 1];
                    e[l - 1] = 0.0f;
                    for (k = l; k < m; k++)
                    {
                        t1 = s[k];
                        drotg(ref t1, ref f, ref cs, ref sn);
                        s[k] = t1;
                        f    = -sn * e[k];
                        e[k] = cs * e[k];
                        if (computeVectors)
                        {
                            drot(u, k, l - 1, cs, sn);
                        }
                    }
                    break;

                // perform one qr step.
                case 3:
                    // calculate the shift.
                    scale = 0.0f;
                    scale = System.Math.Max(scale, ComplexMath.Absolute(s[m - 1]));
                    scale = System.Math.Max(scale, ComplexMath.Absolute(s[m - 2]));
                    scale = System.Math.Max(scale, ComplexMath.Absolute(e[m - 2]));
                    scale = System.Math.Max(scale, ComplexMath.Absolute(s[l]));
                    scale = System.Math.Max(scale, ComplexMath.Absolute(e[l]));
                    sm    = s[m - 1] / scale;
                    smm1  = s[m - 2] / scale;
                    emm1  = e[m - 2] / scale;
                    sl    = s[l] / scale;
                    el    = e[l] / scale;
                    b     = ((smm1 + sm) * (smm1 - sm) + emm1 * emm1) / 2.0f;
                    c     = (sm * emm1) * (sm * emm1);
                    shift = 0.0f;
                    if (b != 0.0f || c != 0.0f)
                    {
                        shift = (float)System.Math.Sqrt(b * b + c);
                        if (b < 0.0f)
                        {
                            shift = -shift;
                        }
                        shift = c / (b + shift);
                    }
                    f = (sl + sm) * (sl - sm) + shift;
                    g = sl * el;

                    // chase zeros.
                    for (k = l; k < m - 1; k++)
                    {
                        drotg(ref f, ref g, ref cs, ref sn);
                        if (k != l)
                        {
                            e[k - 1] = f;
                        }
                        f        = cs * s[k] + sn * e[k];
                        e[k]     = cs * e[k] - sn * s[k];
                        g        = sn * s[k + 1];
                        s[k + 1] = cs * s[k + 1];
                        if (computeVectors)
                        {
                            drot(v, k, k + 1, cs, sn);
                        }
                        drotg(ref f, ref g, ref cs, ref sn);
                        s[k]     = f;
                        f        = cs * e[k] + sn * s[k + 1];
                        s[k + 1] = -sn * e[k] + cs * s[k + 1];
                        g        = sn * e[k + 1];
                        e[k + 1] = cs * e[k + 1];
                        if (computeVectors && k < rows)
                        {
                            drot(u, k, k + 1, cs, sn);
                        }
                    }
                    e[m - 2] = f;
                    iter     = iter + 1;
                    break;

                // convergence.
                case 4:
                    // make the singular value  positive
                    if (s[l] < 0.0f)
                    {
                        s[l] = -s[l];
                        if (computeVectors)
                        {
                            dscalColumn(v, l, 0, -1.0f);
                        }
                    }

                    // order the singular value.
                    while (l != mm - 1)
                    {
                        if (s[l] >= s[l + 1])
                        {
                            break;
                        }
                        t        = s[l];
                        s[l]     = s[l + 1];
                        s[l + 1] = t;
                        if (computeVectors && l < cols)
                        {
                            dswap(v, l, l + 1);
                        }
                        if (computeVectors && l < rows)
                        {
                            dswap(u, l, l + 1);
                        }
                        l = l + 1;
                    }
                    iter = 0;
                    m    = m - 1;
                    break;
                }
            }

            // make matrix w from vector s
            // there is no constructor, creating diagonal matrix from vector
            // doing it ourselves
            mm = System.Math.Min(matrix.RowLength, matrix.ColumnLength);
#else
            u = new FloatMatrix(rows);
            v = new FloatMatrix(cols);
            float[] a = new float[matrix.data.Length];
            Array.Copy(matrix.data, a, matrix.data.Length);
            Lapack.Gesvd.Compute(rows, cols, a, s.data, u.data, v.data);
            v.Transpose();
#endif
            w = new FloatMatrix(matrix.RowLength, matrix.ColumnLength);
            for (int ii = 0; ii < matrix.RowLength; ii++)
            {
                for (int jj = 0; jj < matrix.ColumnLength; jj++)
                {
                    if (ii == jj)
                    {
                        w[ii, ii] = s[ii];
                    }
                }
            }

            float eps = (float)System.Math.Pow(2.0, -52.0);
            float tol = System.Math.Max(matrix.RowLength, matrix.ColumnLength) * s[0] * eps;
            rank = 0;

            for (int h = 0; h < mm; h++)
            {
                if (s[h] > tol)
                {
                    rank++;
                }
            }

            if (!computeVectors)
            {
                u = null;
                v = null;
            }
            matrix = null;
        }
예제 #4
0
		public void TransposeSquare()
		{
			FloatMatrix a = new FloatMatrix(2, 2);
			a[0, 0] = 1;
			a[0, 1] = 2;
			a[1, 0] = 3;
			a[1, 1] = 4;
			a.Transpose();
			Assert.AreEqual(a[0, 0], 1);
			Assert.AreEqual(a[0, 1], 3);
			Assert.AreEqual(a[1, 0], 2);
			Assert.AreEqual(a[1, 1], 4);
		}