Kelvin and Josh,

I believe there is a problem with the SVD implementation in javax.vecmath.
The following code demonstrates that the vecmath decomposition U W V is not
the correct decomposition of the original matrix. (after having problems
with the GMatrix implementation, I just switched to using the JNL package)

Mark

--------------------------------------------------------------------------

package svdTest;

import javax.vecmath.GMatrix;

import VisualNumerics.math.DoubleSVD;

public class SVDtest {

  //Main method
  public static void main(String[] args) {
    final int N=3;
    // generate NxN array of random values
    double[][] rv2 = new double[N][N];
    for (int i=0; i<N; i++)
      for (int j=0; j<N; j++)
        rv2[i][j] = Math.random();

    // construct a GMatrix from the NxN array
    GMatrix Q = new GMatrix(N, N);
    for (int i=0; i<N; i++) Q.setRow(i, rv2[i]);

    // invoke the JNL SVD routine
    final int M = 10000;
    DoubleSVD[] qsvda = new DoubleSVD[M];
    long startTime = System.currentTimeMillis();
    for (int i=0; i<M; i++) qsvda[i] = new DoubleSVD(rv2);
    long duration = System.currentTimeMillis() - startTime;
    double interval = (double)duration / M;
    System.out.println("JNL SVD computation time: " + interval + " msec");
    DoubleSVD qsvd = qsvda[0];
    try {
      System.out.println("JNL rank: " + qsvd.rank());
      } catch (Exception e) {e.printStackTrace();};

      // construct result matrices for SVD
      GMatrix U = new GMatrix(N, N);
      GMatrix S = new GMatrix(N, N);
      GMatrix V = new GMatrix(N, N);

      // test results by computing  X = U*S*transpose(V)
      for (int i=0; i<N; i++) U.setRow(i, qsvd.U()[i]);
      for (int i=0; i<N; i++) S.setElement(i, i, qsvd.S()[i]);
      for (int i=0; i<N; i++) V.setRow(i, qsvd.V()[i]);

      GMatrix X = new GMatrix(U);
      X.mul(S);
      V.transpose();
      X.mul(V);

      // test X = Q
      X.sub(Q);
      double ssq = 0;
      for (int i=0; i<N; i++) {
        for (int j=0; j<N; j++) {
          ssq += Math.pow(X.getElement(i,j), 2);
        }
      }
      System.out.println("JNL error \n" + X);
      System.out.println("sum of squared errors: " + ssq);


      // repeat test using GMatrix SVD routine
      int rank = 0;
      startTime = System.currentTimeMillis();
      for (int i=0; i<M; i++) rank = Q.SVD(U, S, V);
      duration = System.currentTimeMillis() - startTime;
      interval = (double)duration / M;
      System.out.println("GMatrix rank: " + rank);
      System.out.println("vecmath SVD computation time: " + interval + "
msec");

      X = new GMatrix(U);
      X.mul(S);
      V.transpose();
      X.mul(V);
      X.sub(Q);
      ssq = 0;
      for (int i=0; i<N; i++) {
        for (int j=0; j<N; j++) {
          ssq += Math.pow(X.getElement(i,j), 2);
        }
      }
      System.out.println("GMatrix error \n" + X);
      System.out.println("sum of squared errors: " + ssq);
  }
}

----------------------------------------------------------------------------


C:\j2sdk1.4.0-rc\bin\javaw svdTest.SVDtest
JNL SVD computation time: 0.0844 msec

JNL rank: 3

JNL error
2.0816681711721685E-16 9.992007221626409E-16 2.220446049250313E-16
3.3306690738754696E-16 1.8041124150158794E-16 3.3306690738754696E-16
1.6653345369377348E-16 5.551115123125783E-16 -2.914335439641036E-16


sum of squared errors: 1.766270351997534E-30

GMatrix rank: 3

vecmath SVD computation time: 0.0313 msec

GMatrix error
-0.004779392884258549 -0.5042163801665813 0.5760133790720257
-0.7285576864679053 -0.6700460809138684 -1.0894544843687317
-0.2314124499011076 0.08774924790691563 -0.7340488647018298


sum of squared errors: 3.3527969283127526


----------------------------------------------------------------------------

----- Original Message -----
From: "Kelvin Chung" <
[EMAIL PROTECTED]>
To: <
[EMAIL PROTECTED]>
Sent: Thursday, September 19, 2002 12:18 PM
Subject: Re: [JAVA3D] Matrix4d bug!


> Josh Richmond wrote:
> > Hi everyone,
> >
> > Either I misunderstand the definition of Matrix4d.get(Matrix3d) or I've
discovered a surprising bug.
> >
> > Run the attached program to see, but it looks like (at least using my
initial values), the 3x3 matrix returned is not the 3x3 rotation matrix of
the 4x4 matrix, even with no affine transformation.
> >
> > E:\temp>java -cp . MatrixTest
> > 4x4:
> > 0.996823, 0.036243, 0.070927, -0.245034
> > -0.036412, 0.997481, 0.001096, 0.034035
> > -0.07084, -0.003675, 0.999336, 0.036529
> > 0.0, 0.0, 0.0, 1.0
> >
> >
> > 3x3:
> > 0.03627668530489642, 0.9968262981253496, 0.07086136795886099
> > 0.9993350269113018, -0.03644589019989963, 0.0010959360038394175
> > -0.0036750634657327997, -0.0707744901306144, 0.997485571552428
> >
> > As you can see it is vastly re-arranged. Am I misinterpreting the
definition of the method? Is the problem with my values? They're practically
identity.
> >
> > josh
> >
>
>
> I don't see a problem here, if you pass the m3 matrix to Transform3D and
> get its type :
>
>         Transform3D t = new Transform3D();
>         t.set(m3);
>         int type = t.getType();
>
>          if ((type & Transform3D.ZERO)                 > 0 )
> System.out.print(" ZERO");
>         if ((type & Transform3D.IDENTITY)             > 0 )
System.out.print("
> IDENTITY");
>         if ((type & Transform3D.SCALE)                > 0 )
System.out.print("
> SCALE");
>         if ((type & Transform3D.TRANSLATION)          > 0 )
System.out.print("
> TRANSLATION");
>         if ((type & Transform3D.ORTHOGONAL)           > 0 )
System.out.print("
> ORTHOGONAL");
>         if ((type & Transform3D.RIGID)                > 0 )
System.out.print("
> RIGID");
>         if ((type & Transform3D.CONGRUENT)            > 0 )
System.out.print("
> CONGRUENT");
>         if ((type & Transform3D.AFFINE)               > 0 )
System.out.print("
> AFFINE");
>         if ((type & Transform3D.NEGATIVE_DETERMINANT) > 0 )
System.out.print("
> NEGATIVE_DETERMINANT");
>
>
>
> The output is :
>
> ORTHOGONAL RIGID CONGRUENT AFFINE NEGATIVE_DETERMINANT4x4
>
>
> - Kelvin
>
>
===========================================================================
> To unsubscribe, send email to
[EMAIL PROTECTED] and include in the
body
> of the message "signoff JAVA3D-INTEREST".  For general help, send email to
>
[EMAIL PROTECTED] and include in the body of the message "help".
>

Reply via email to