]> gerrit.simantics Code Review - simantics/3d.git/commitdiff
Included old javax.vecmath 1.5.2 to org.simantics.g3d.feature release/1.33.0 release/1.34.0 release/1.34.1 release/1.34.2
authorTuukka Lehtonen <tuukka.lehtonen@semantum.fi>
Wed, 14 Feb 2018 22:36:53 +0000 (00:36 +0200)
committerTuukka Lehtonen <tuukka.lehtonen@semantum.fi>
Wed, 14 Feb 2018 22:36:53 +0000 (00:36 +0200)
The library is used as is without modifications under the
terms of the "CLASSPATH" EXCEPTION TO THE GPL so it is OK
to include it here in this otherwise EPL'ed software.

61 files changed:
javax.vecmath/.classpath [new file with mode: 0644]
javax.vecmath/.project [new file with mode: 0644]
javax.vecmath/.settings/org.eclipse.jdt.core.prefs [new file with mode: 0644]
javax.vecmath/.settings/org.eclipse.pde.core.prefs [new file with mode: 0644]
javax.vecmath/COPYRIGHT.txt [new file with mode: 0644]
javax.vecmath/LICENSE-SPEC.html [new file with mode: 0644]
javax.vecmath/LICENSE.txt [new file with mode: 0644]
javax.vecmath/META-INF/MANIFEST.MF [new file with mode: 0644]
javax.vecmath/README.txt [new file with mode: 0644]
javax.vecmath/build.properties [new file with mode: 0644]
javax.vecmath/pom.xml [new file with mode: 0644]
javax.vecmath/src/javax/vecmath/AxisAngle4d.java [new file with mode: 0644]
javax.vecmath/src/javax/vecmath/AxisAngle4f.java [new file with mode: 0644]
javax.vecmath/src/javax/vecmath/Color3b.java [new file with mode: 0644]
javax.vecmath/src/javax/vecmath/Color3f.java [new file with mode: 0644]
javax.vecmath/src/javax/vecmath/Color4b.java [new file with mode: 0644]
javax.vecmath/src/javax/vecmath/Color4f.java [new file with mode: 0644]
javax.vecmath/src/javax/vecmath/ExceptionStrings.properties [new file with mode: 0644]
javax.vecmath/src/javax/vecmath/GMatrix.java [new file with mode: 0644]
javax.vecmath/src/javax/vecmath/GVector.java [new file with mode: 0644]
javax.vecmath/src/javax/vecmath/Matrix3d.java [new file with mode: 0644]
javax.vecmath/src/javax/vecmath/Matrix3f.java [new file with mode: 0644]
javax.vecmath/src/javax/vecmath/Matrix4d.java [new file with mode: 0644]
javax.vecmath/src/javax/vecmath/Matrix4f.java [new file with mode: 0644]
javax.vecmath/src/javax/vecmath/MismatchedSizeException.java [new file with mode: 0644]
javax.vecmath/src/javax/vecmath/Point2d.java [new file with mode: 0644]
javax.vecmath/src/javax/vecmath/Point2f.java [new file with mode: 0644]
javax.vecmath/src/javax/vecmath/Point2i.java [new file with mode: 0644]
javax.vecmath/src/javax/vecmath/Point3d.java [new file with mode: 0644]
javax.vecmath/src/javax/vecmath/Point3f.java [new file with mode: 0644]
javax.vecmath/src/javax/vecmath/Point3i.java [new file with mode: 0644]
javax.vecmath/src/javax/vecmath/Point4d.java [new file with mode: 0644]
javax.vecmath/src/javax/vecmath/Point4f.java [new file with mode: 0644]
javax.vecmath/src/javax/vecmath/Point4i.java [new file with mode: 0644]
javax.vecmath/src/javax/vecmath/Quat4d.java [new file with mode: 0644]
javax.vecmath/src/javax/vecmath/Quat4f.java [new file with mode: 0644]
javax.vecmath/src/javax/vecmath/SingularMatrixException.java [new file with mode: 0644]
javax.vecmath/src/javax/vecmath/TexCoord2f.java [new file with mode: 0644]
javax.vecmath/src/javax/vecmath/TexCoord3f.java [new file with mode: 0644]
javax.vecmath/src/javax/vecmath/TexCoord4f.java [new file with mode: 0644]
javax.vecmath/src/javax/vecmath/Tuple2d.java [new file with mode: 0644]
javax.vecmath/src/javax/vecmath/Tuple2f.java [new file with mode: 0644]
javax.vecmath/src/javax/vecmath/Tuple2i.java [new file with mode: 0644]
javax.vecmath/src/javax/vecmath/Tuple3b.java [new file with mode: 0644]
javax.vecmath/src/javax/vecmath/Tuple3d.java [new file with mode: 0644]
javax.vecmath/src/javax/vecmath/Tuple3f.java [new file with mode: 0644]
javax.vecmath/src/javax/vecmath/Tuple3i.java [new file with mode: 0644]
javax.vecmath/src/javax/vecmath/Tuple4b.java [new file with mode: 0644]
javax.vecmath/src/javax/vecmath/Tuple4d.java [new file with mode: 0644]
javax.vecmath/src/javax/vecmath/Tuple4f.java [new file with mode: 0644]
javax.vecmath/src/javax/vecmath/Tuple4i.java [new file with mode: 0644]
javax.vecmath/src/javax/vecmath/VecMathI18N.java [new file with mode: 0644]
javax.vecmath/src/javax/vecmath/VecMathUtil.java [new file with mode: 0644]
javax.vecmath/src/javax/vecmath/Vector2d.java [new file with mode: 0644]
javax.vecmath/src/javax/vecmath/Vector2f.java [new file with mode: 0644]
javax.vecmath/src/javax/vecmath/Vector3d.java [new file with mode: 0644]
javax.vecmath/src/javax/vecmath/Vector3f.java [new file with mode: 0644]
javax.vecmath/src/javax/vecmath/Vector4d.java [new file with mode: 0644]
javax.vecmath/src/javax/vecmath/Vector4f.java [new file with mode: 0644]
org.simantics.g3d.feature/feature.xml
pom.xml

diff --git a/javax.vecmath/.classpath b/javax.vecmath/.classpath
new file mode 100644 (file)
index 0000000..8a8f166
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<classpath>\r
+       <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>\r
+       <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>\r
+       <classpathentry kind="src" path="src"/>\r
+       <classpathentry kind="output" path="bin"/>\r
+</classpath>\r
diff --git a/javax.vecmath/.project b/javax.vecmath/.project
new file mode 100644 (file)
index 0000000..6e28f64
--- /dev/null
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<projectDescription>\r
+       <name>javax.vecmath</name>\r
+       <comment></comment>\r
+       <projects>\r
+       </projects>\r
+       <buildSpec>\r
+               <buildCommand>\r
+                       <name>org.eclipse.jdt.core.javabuilder</name>\r
+                       <arguments>\r
+                       </arguments>\r
+               </buildCommand>\r
+               <buildCommand>\r
+                       <name>org.eclipse.pde.ManifestBuilder</name>\r
+                       <arguments>\r
+                       </arguments>\r
+               </buildCommand>\r
+               <buildCommand>\r
+                       <name>org.eclipse.pde.SchemaBuilder</name>\r
+                       <arguments>\r
+                       </arguments>\r
+               </buildCommand>\r
+       </buildSpec>\r
+       <natures>\r
+               <nature>org.eclipse.pde.PluginNature</nature>\r
+               <nature>org.eclipse.jdt.core.javanature</nature>\r
+       </natures>\r
+</projectDescription>\r
diff --git a/javax.vecmath/.settings/org.eclipse.jdt.core.prefs b/javax.vecmath/.settings/org.eclipse.jdt.core.prefs
new file mode 100644 (file)
index 0000000..e2df0ba
--- /dev/null
@@ -0,0 +1,8 @@
+#Fri Apr 01 11:08:58 EEST 2011\r
+eclipse.preferences.version=1\r
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled\r
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6\r
+org.eclipse.jdt.core.compiler.compliance=1.6\r
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error\r
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error\r
+org.eclipse.jdt.core.compiler.source=1.6\r
diff --git a/javax.vecmath/.settings/org.eclipse.pde.core.prefs b/javax.vecmath/.settings/org.eclipse.pde.core.prefs
new file mode 100644 (file)
index 0000000..21af2df
--- /dev/null
@@ -0,0 +1,5 @@
+#Fri Apr 01 11:08:58 EEST 2011\r
+eclipse.preferences.version=1\r
+pluginProject.equinox=false\r
+pluginProject.extensions=false\r
+resolve.requirebundle=false\r
diff --git a/javax.vecmath/COPYRIGHT.txt b/javax.vecmath/COPYRIGHT.txt
new file mode 100644 (file)
index 0000000..dd7d0ec
--- /dev/null
@@ -0,0 +1,77 @@
+Copyright 1996-2008 Sun Microsystems, Inc., 4150 Network Circle, Santa
+Clara, California 95054, U.S.A. All rights reserved.
+
+Sun Microsystems, Inc. has intellectual property rights relating to
+technology embodied in the product that is described in this
+document. In particular, and without limitation, these intellectual
+property rights may include one or more of the U.S. patents listed at
+http://www.sun.com/patents and one or more additional patents or
+pending patent applications in the U.S. and in other countries.
+
+U.S. Government Rights - Commercial software. Government users are
+subject to the Sun Microsystems, Inc. standard license agreement and
+applicable provisions of the FAR and its supplements.
+
+Use is subject to license terms.
+
+This distribution may include materials developed by third parties.
+
+Parts of the product may be derived from Berkeley BSD systems,
+licensed from the University of California. UNIX is a registered
+trademark in the U.S. and in other countries, exclusively licensed
+through X/Open Company, Ltd.
+
+Sun, Sun Microsystems, the Sun logo, Java, Solaris, Java 3D, the 100%
+Pure Java logo, the Duke logo and the Java Coffee Cup logo are
+trademarks or registered trademarks of Sun Microsystems, Inc. in the
+U.S. and other countries.
+
+This product is covered and controlled by U.S. Export Control laws and
+may be subject to the export or import laws in other countries.
+Nuclear, missile, chemical biological weapons or nuclear maritime end
+uses or end users, whether direct or indirect, are strictly
+prohibited. Export or reexport to countries subject to U.S. embargo or
+to entities identified on U.S. export exclusion lists, including, but
+not limited to, the denied persons and specially designated nationals
+lists is strictly prohibited.
+
+Copyright 1996-2008 Sun Microsystems, Inc., 4150 Network Circle, Santa
+Clara, California 95054, Etats-Unis. Tous droits réservés.
+
+Sun Microsystems, Inc. détient les droits de propriété intellectuels
+relatifs à la technologie incorporée dans le produit qui est décrit
+dans ce document. En particulier, et ce sans limitation, ces droits de
+propriété intellectuelle peuvent inclure un ou plus des brevets
+américains listés à l'adresse http://www.sun.com/patents et un ou les
+brevets supplémentaires ou les applications de brevet en attente aux
+Etats - Unis et dans les autres pays.
+
+L'utilisation est soumise aux termes de la Licence.
+
+Cette distribution peut comprendre des composants développés par des
+tierces parties.
+
+Des parties de ce produit pourront être dérivées des systèmes Berkeley
+BSD licenciés par l'Université de Californie. UNIX est une marque
+déposée aux Etats-Unis et dans d'autres pays et licenciée
+exclusivement par X/Open Company, Ltd.
+
+Sun, Sun Microsystems, le logo Sun, Java, Solaris, Java 3D, le logo
+100% Pure Java, le logo Duke et le logo Java Coffee Cup sont des
+marques de fabrique ou des marques déposées de Sun Microsystems,
+Inc. aux Etats-Unis et dans d'autres pays.
+
+Ce produit est soumis à la législation américaine en matière de
+contrôle des exportations et peut être soumis à la règlementation en
+vigueur dans d'autres pays dans le domaine des exportations et
+importations. Les utilisations, ou utilisateurs finaux, pour des armes
+nucléaires,des missiles, des armes biologiques et chimiques ou du
+nucléaire maritime, directement ou indirectement, sont strictement
+interdites. Les exportations ou réexportations vers les pays sous
+embargo américain, ou vers des entités figurant sur les listes
+d'exclusion d'exportation américaines, y compris, mais de manière non
+exhaustive, la liste de personnes qui font objet d'un ordre de ne pas
+participer, d'une façon directe ou indirecte, aux exportations des
+produits ou des services qui sont régis par la législation américaine
+en matière de contrôle des exportations et la liste de ressortissants
+spécifiquement désignés, sont rigoureusement interdites.
diff --git a/javax.vecmath/LICENSE-SPEC.html b/javax.vecmath/LICENSE-SPEC.html
new file mode 100644 (file)
index 0000000..4b12f55
--- /dev/null
@@ -0,0 +1,220 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+  <meta content="text/html; charset=ISO-8859-1"
+ http-equiv="content-type">
+  <title>Java 3D API Specification</title>
+</head>
+<body>
+<p>
+Specification: JSR-000926 Java 3D<sup><font size="-2">TM</font></sup> API ("Specification")
+</p>
+<p>
+Version: 1.5<br>
+Status: Maintenance Release 2<br>
+Release: 21 December 2006
+</p>
+<p>
+Copyright 2006-2008 SUN MICROSYSTEMS, INC.<br>
+4150 Network Circle, Santa Clara, California 95054, U.S.A<br>
+All rights reserved.
+</p>
+<p>
+LIMITED LICENSE GRANTS
+</p>
+<p>
+1. License for Evaluation Purposes. Sun hereby grants you a
+fully-paid, non-exclusive, non-transferable, worldwide, limited license
+(without the right to sublicense), under Sun's applicable intellectual
+property rights to view, download, use and reproduce the Specification
+only for the purpose of internal evaluation. This includes (i)
+developing applications intended to run on an implementation of the
+Specification, provided that such applications do not themselves
+implement any portion(s) of the Specification, and (ii) discussing the
+Specification with any third party; and (iii) excerpting brief portions
+of the Specification in oral or written communications which discuss the
+Specification provided that such excerpts do not in the aggregate
+constitute a significant portion of the Specification.
+</p>
+<p>
+2. License for the Distribution of Compliant Implementations. Sun also
+grants you a perpetual, non-exclusive, non-transferable, worldwide,
+fully paid-up, royalty free, limited license (without the right to
+sublicense) under any applicable copyrights or, subject to the
+provisions of subsection 4 below, patent rights it may have covering the
+Specification to create and/or distribute an Independent Implementation
+of the Specification that: (a) fully implements the Specification
+including all its required interfaces and functionality; (b) does not
+modify, subset, superset or otherwise extend the Licensor Name Space, or
+include any public or protected packages, classes, Java interfaces,
+fields or methods within the Licensor Name Space other than those
+required/authorized by the Specification or Specifications being
+implemented; and (c) passes the Technology Compatibility Kit (including
+satisfying the requirements of the applicable TCK Users Guide) for such
+Specification ("Compliant Implementation"). In addition, the foregoing
+license is expressly conditioned on your not acting outside its scope.
+No license is granted hereunder for any other purpose (including, for
+example, modifying the Specification, other than to the extent of your
+fair use rights, or distributing the Specification to third parties).
+Also, no right, title, or interest in or to any trademarks, service
+marks, or trade names of Sun or Sun's licensors is granted hereunder.
+Java, and Java-related logos, marks and names are trademarks or
+registered trademarks of Sun Microsystems, Inc. in the U.S. and other
+countries.
+</p>
+<p>
+3. Pass-through Conditions. You need not include limitations (a)-(c)
+from the previous paragraph or any other particular "pass through"
+requirements in any license You grant concerning the use of your
+Independent Implementation or products derived from it. However, except
+with respect to Independent Implementations (and products derived from
+them) that satisfy limitations (a)-(c) from the previous paragraph, You
+may neither: (a) grant or otherwise pass through to your licensees any
+licenses under Sun's applicable intellectual property rights; nor (b)
+authorize your licensees to make any claims concerning their
+implementation's compliance with the Specification in question.
+</p>
+<p>
+4. Reciprocity Concerning Patent Licenses.
+</p>
+<p>
+a. With respect to any patent claims covered by the license granted
+under subparagraph 2 above that would be infringed by all technically
+feasible implementations of the Specification, such license is
+conditioned upon your offering on fair, reasonable and
+non-discriminatory terms, to any party seeking it from You, a perpetual,
+non-exclusive, non-transferable, worldwide license under Your patent
+rights which are or would be infringed by all technically feasible
+implementations of the Specification to develop, distribute and use a
+Compliant Implementation.
+</p>
+<p>
+b With respect to any patent claims owned by Sun and covered by the
+license granted under subparagraph 2, whether or not their infringement
+can be avoided in a technically feasible manner when implementing the
+Specification, such license shall terminate with respect to such claims
+if You initiate a claim against Sun that it has, in the course of
+performing its responsibilities as the Specification Lead, induced any
+other entity to infringe Your patent rights.
+</p>
+<p>
+c Also with respect to any patent claims owned by Sun and covered by the
+license granted under subparagraph 2 above, where the infringement of
+such claims can be avoided in a technically feasible manner when
+implementing the Specification such license, with respect to such
+claims, shall terminate if You initiate a claim against Sun that its
+making, having made, using, offering to sell, selling or importing a
+Compliant Implementation infringes Your patent rights.
+</p>
+<p>
+5. Definitions. For the purposes of this Agreement: "Independent
+Implementation" shall mean an implementation of the Specification that
+neither derives from any of Sun's source code or binary code materials
+nor, except with an appropriate and separate license from Sun, includes
+any of Sun's source code or binary code materials; "Licensor Name Space"
+shall mean the public class or interface declarations whose names begin
+with "java", "javax", "com.sun" or their equivalents in any subsequent
+naming convention adopted by Sun through the Java Community Process, or
+any recognized successors or replacements thereof; and "Technology
+Compatibility Kit" or "TCK" shall mean the test suite and accompanying
+TCK User's Guide provided by Sun which corresponds to the Specification
+and that was available either (i) from Sun's 120 days before the first
+release of Your Independent Implementation that allows its use for
+commercial purposes, or (ii) more recently than 120 days from such
+release but against which You elect to test Your implementation of the
+Specification.
+</p>
+<p>
+This Agreement will terminate immediately without notice from Sun if you
+breach the Agreement or act outside the scope of the licenses granted above.
+</p>
+<p>
+DISCLAIMER OF WARRANTIES
+</p>
+<p>
+THE SPECIFICATION IS PROVIDED "AS IS". SUN MAKES NO REPRESENTATIONS OR
+WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO,
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
+NON-INFRINGEMENT (INCLUDING AS A CONSEQUENCE OF ANY PRACTICE OR
+IMPLEMENTATION OF THE SPECIFICATION), OR THAT THE CONTENTS OF THE
+SPECIFICATION ARE SUITABLE FOR ANY PURPOSE. This document does not
+represent any commitment to release or implement any portion of the
+Specification in any product. In addition, the Specification could
+include technical inaccuracies or typographical errors.
+</p>
+<p>
+LIMITATION OF LIABILITY
+</p>
+<p>
+TO THE EXTENT NOT PROHIBITED BY LAW, IN NO EVENT WILL SUN OR ITS
+LICENSORS BE LIABLE FOR ANY DAMAGES, INCLUDING WITHOUT LIMITATION, LOST
+REVENUE, PROFITS OR DATA, OR FOR SPECIAL, INDIRECT, CONSEQUENTIAL,
+INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE
+THEORY OF LIABILITY, ARISING OUT OF OR RELATED IN ANY WAY TO YOUR
+HAVING, IMPLEMENTING OR OTHERWISE USING THE SPECIFICATION, EVEN
+IF SUN AND/OR ITS LICENSORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+You will indemnify, hold harmless, and defend Sun and its licensors from
+any claims arising or resulting from: (i) your use of the Specification;
+(ii) the use or distribution of your Java application, applet and/or
+implementation; and/or (iii) any claims that later versions or releases
+of any Specification furnished to you are incompatible with the
+Specification provided to you under this license.
+</p>
+<p>
+RESTRICTED RIGHTS LEGEND
+</p>
+<p>
+U.S. Government: If this Specification is being acquired by or on behalf
+of the U.S. Government or by a U.S. Government prime contractor or
+subcontractor (at any tier), then the Government's rights in the
+Software and accompanying documentation shall be only as set forth in
+this license; this is in accordance with 48 C.F.R. 227.7201 through
+227.7202-4 (for Department of Defense (DoD) acquisitions) and with 48
+C.F.R. 2.101 and 12.212 (for non-DoD acquisitions).
+</p>
+<p>
+REPORT
+</p>
+<p>
+If you provide Sun with any comments or suggestions concerning the
+Specification ("Feedback"), you hereby: (i) agree that such Feedback is
+provided on a non-proprietary and non-confidential basis, and (ii) grant
+Sun a perpetual, non-exclusive, worldwide, fully paid-up, irrevocable
+license, with the right to sublicense through multiple levels of
+sublicensees, to incorporate, disclose, and use without limitation the
+Feedback for any purpose.
+</p>
+<p>
+GENERAL TERMS
+</p>
+<p>
+Any action related to this Agreement will be governed by California law
+and controlling U.S. federal law. The U.N. Convention for the
+International Sale of Goods and the choice of law rules of any
+jurisdiction will not apply.
+</p>
+<p>
+The Specification is subject to U.S. export control laws and may be
+subject to export or import regulations in other countries. Licensee
+agrees to comply strictly with all such laws and regulations and
+acknowledges that it has the responsibility to obtain such licenses to
+export, re-export or import as may be required after delivery to Licensee.
+</p>
+<p>
+This Agreement is the parties' entire agreement relating to its subject
+matter. It supersedes all prior or contemporaneous oral or written
+communications, proposals, conditions, representations and warranties
+and prevails over any conflicting or additional terms of any quote,
+order, acknowledgment, or other communication between the parties
+relating to its subject matter during the term of this Agreement. No
+modification to this Agreement will be binding, unless in writing and
+signed by an authorized representative of each party.
+</p>
+<p>
+Rev. April, 2006<br>
+Sun/Final/Full
+</p>
+</body>
+</html>
diff --git a/javax.vecmath/LICENSE.txt b/javax.vecmath/LICENSE.txt
new file mode 100644 (file)
index 0000000..eeab58c
--- /dev/null
@@ -0,0 +1,347 @@
+The GNU General Public License (GPL)
+
+Version 2, June 1991
+
+Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+Everyone is permitted to copy and distribute verbatim copies of this license
+document, but changing it is not allowed.
+
+Preamble
+
+The licenses for most software are designed to take away your freedom to share
+and change it.  By contrast, the GNU General Public License is intended to
+guarantee your freedom to share and change free software--to make sure the
+software is free for all its users.  This General Public License applies to
+most of the Free Software Foundation's software and to any other program whose
+authors commit to using it.  (Some other Free Software Foundation software is
+covered by the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+When we speak of free software, we are referring to freedom, not price.  Our
+General Public Licenses are designed to make sure that you have the freedom to
+distribute copies of free software (and charge for this service if you wish),
+that you receive source code or can get it if you want it, that you can change
+the software or use pieces of it in new free programs; and that you know you
+can do these things.
+
+To protect your rights, we need to make restrictions that forbid anyone to deny
+you these rights or to ask you to surrender the rights.  These restrictions
+translate to certain responsibilities for you if you distribute copies of the
+software, or if you modify it.
+
+For example, if you distribute copies of such a program, whether gratis or for
+a fee, you must give the recipients all the rights that you have.  You must
+make sure that they, too, receive or can get the source code.  And you must
+show them these terms so they know their rights.
+
+We protect your rights with two steps: (1) copyright the software, and (2)
+offer you this license which gives you legal permission to copy, distribute
+and/or modify the software.
+
+Also, for each author's protection and ours, we want to make certain that
+everyone understands that there is no warranty for this free software.  If the
+software is modified by someone else and passed on, we want its recipients to
+know that what they have is not the original, so that any problems introduced
+by others will not reflect on the original authors' reputations.
+
+Finally, any free program is threatened constantly by software patents.  We
+wish to avoid the danger that redistributors of a free program will
+individually obtain patent licenses, in effect making the program proprietary.
+To prevent this, we have made it clear that any patent must be licensed for
+everyone's free use or not licensed at all.
+
+The precise terms and conditions for copying, distribution and modification
+follow.
+
+TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+0. This License applies to any program or other work which contains a notice
+placed by the copyright holder saying it may be distributed under the terms of
+this General Public License.  The "Program", below, refers to any such program
+or work, and a "work based on the Program" means either the Program or any
+derivative work under copyright law: that is to say, a work containing the
+Program or a portion of it, either verbatim or with modifications and/or
+translated into another language.  (Hereinafter, translation is included
+without limitation in the term "modification".) Each licensee is addressed as
+"you".
+
+Activities other than copying, distribution and modification are not covered by
+this License; they are outside its scope.  The act of running the Program is
+not restricted, and the output from the Program is covered only if its contents
+constitute a work based on the Program (independent of having been made by
+running the Program).  Whether that is true depends on what the Program does.
+
+1. You may copy and distribute verbatim copies of the Program's source code as
+you receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice and
+disclaimer of warranty; keep intact all the notices that refer to this License
+and to the absence of any warranty; and give any other recipients of the
+Program a copy of this License along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and you may
+at your option offer warranty protection in exchange for a fee.
+
+2. You may modify your copy or copies of the Program or any portion of it, thus
+forming a work based on the Program, and copy and distribute such modifications
+or work under the terms of Section 1 above, provided that you also meet all of
+these conditions:
+
+    a) You must cause the modified files to carry prominent notices stating
+    that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in whole or
+    in part contains or is derived from the Program or any part thereof, to be
+    licensed as a whole at no charge to all third parties under the terms of
+    this License.
+
+    c) If the modified program normally reads commands interactively when run,
+    you must cause it, when started running for such interactive use in the
+    most ordinary way, to print or display an announcement including an
+    appropriate copyright notice and a notice that there is no warranty (or
+    else, saying that you provide a warranty) and that users may redistribute
+    the program under these conditions, and telling the user how to view a copy
+    of this License.  (Exception: if the Program itself is interactive but does
+    not normally print such an announcement, your work based on the Program is
+    not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If identifiable
+sections of that work are not derived from the Program, and can be reasonably
+considered independent and separate works in themselves, then this License, and
+its terms, do not apply to those sections when you distribute them as separate
+works.  But when you distribute the same sections as part of a whole which is a
+work based on the Program, the distribution of the whole must be on the terms
+of this License, whose permissions for other licensees extend to the entire
+whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest your
+rights to work written entirely by you; rather, the intent is to exercise the
+right to control the distribution of derivative or collective works based on
+the Program.
+
+In addition, mere aggregation of another work not based on the Program with the
+Program (or with a work based on the Program) on a volume of a storage or
+distribution medium does not bring the other work under the scope of this
+License.
+
+3. You may copy and distribute the Program (or a work based on it, under
+Section 2) in object code or executable form under the terms of Sections 1 and
+2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable source
+    code, which must be distributed under the terms of Sections 1 and 2 above
+    on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three years, to
+    give any third party, for a charge no more than your cost of physically
+    performing source distribution, a complete machine-readable copy of the
+    corresponding source code, to be distributed under the terms of Sections 1
+    and 2 above on a medium customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer to
+    distribute corresponding source code.  (This alternative is allowed only
+    for noncommercial distribution and only if you received the program in
+    object code or executable form with such an offer, in accord with
+    Subsection b above.)
+
+The source code for a work means the preferred form of the work for making
+modifications to it.  For an executable work, complete source code means all
+the source code for all modules it contains, plus any associated interface
+definition files, plus the scripts used to control compilation and installation
+of the executable.  However, as a special exception, the source code
+distributed need not include anything that is normally distributed (in either
+source or binary form) with the major components (compiler, kernel, and so on)
+of the operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the source
+code from the same place counts as distribution of the source code, even though
+third parties are not compelled to copy the source along with the object code.
+
+4. You may not copy, modify, sublicense, or distribute the Program except as
+expressly provided under this License.  Any attempt otherwise to copy, modify,
+sublicense or distribute the Program is void, and will automatically terminate
+your rights under this License.  However, parties who have received copies, or
+rights, from you under this License will not have their licenses terminated so
+long as such parties remain in full compliance.
+
+5. You are not required to accept this License, since you have not signed it.
+However, nothing else grants you permission to modify or distribute the Program
+or its derivative works.  These actions are prohibited by law if you do not
+accept this License.  Therefore, by modifying or distributing the Program (or
+any work based on the Program), you indicate your acceptance of this License to
+do so, and all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+6. Each time you redistribute the Program (or any work based on the Program),
+the recipient automatically receives a license from the original licensor to
+copy, distribute or modify the Program subject to these terms and conditions.
+You may not impose any further restrictions on the recipients' exercise of the
+rights granted herein.  You are not responsible for enforcing compliance by
+third parties to this License.
+
+7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues), conditions
+are imposed on you (whether by court order, agreement or otherwise) that
+contradict the conditions of this License, they do not excuse you from the
+conditions of this License.  If you cannot distribute so as to satisfy
+simultaneously your obligations under this License and any other pertinent
+obligations, then as a consequence you may not distribute the Program at all.
+For example, if a patent license would not permit royalty-free redistribution
+of the Program by all those who receive copies directly or indirectly through
+you, then the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply and
+the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any patents or
+other property right claims or to contest validity of any such claims; this
+section has the sole purpose of protecting the integrity of the free software
+distribution system, which is implemented by public license practices.  Many
+people have made generous contributions to the wide range of software
+distributed through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing to
+distribute software through any other system and a licensee cannot impose that
+choice.
+
+This section is intended to make thoroughly clear what is believed to be a
+consequence of the rest of this License.
+
+8. If the distribution and/or use of the Program is restricted in certain
+countries either by patents or by copyrighted interfaces, the original
+copyright holder who places the Program under this License may add an explicit
+geographical distribution limitation excluding those countries, so that
+distribution is permitted only in or among countries not thus excluded.  In
+such case, this License incorporates the limitation as if written in the body
+of this License.
+
+9. The Free Software Foundation may publish revised and/or new versions of the
+General Public License from time to time.  Such new versions will be similar in
+spirit to the present version, but may differ in detail to address new problems
+or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any later
+version", you have the option of following the terms and conditions either of
+that version or of any later version published by the Free Software Foundation.
+If the Program does not specify a version number of this License, you may
+choose any version ever published by the Free Software Foundation.
+
+10. If you wish to incorporate parts of the Program into other free programs
+whose distribution conditions are different, write to the author to ask for
+permission.  For software which is copyrighted by the Free Software Foundation,
+write to the Free Software Foundation; we sometimes make exceptions for this.
+Our decision will be guided by the two goals of preserving the free status of
+all derivatives of our free software and of promoting the sharing and reuse of
+software generally.
+
+NO WARRANTY
+
+11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR
+THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN OTHERWISE
+STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE
+PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND
+PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE,
+YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL
+ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE
+PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR
+INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA
+BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER
+OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+END OF TERMS AND CONDITIONS
+
+How to Apply These Terms to Your New Programs
+
+If you develop a new program, and you want it to be of the greatest possible
+use to the public, the best way to achieve this is to make it free software
+which everyone can redistribute and change under these terms.
+
+To do so, attach the following notices to the program.  It is safest to attach
+them to the start of each source file to most effectively convey the exclusion
+of warranty; and each file should have at least the "copyright" line and a
+pointer to where the full notice is found.
+
+    One line to give the program's name and a brief idea of what it does.
+
+    Copyright (C) <year> <name of author>
+
+    This program is free software; you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by the Free
+    Software Foundation; either version 2 of the License, or (at your option)
+    any later version.
+
+    This program is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc., 59
+    Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this when it
+starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author Gnomovision comes
+    with ABSOLUTELY NO WARRANTY; for details type 'show w'.  This is free
+    software, and you are welcome to redistribute it under certain conditions;
+    type 'show c' for details.
+
+The hypothetical commands 'show w' and 'show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may be
+called something other than 'show w' and 'show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.  Here
+is a sample; alter the names:
+
+    Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+    'Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+    signature of Ty Coon, 1 April 1989
+
+    Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General Public
+License instead of this License.
+
+
+"CLASSPATH" EXCEPTION TO THE GPL
+
+Certain source files distributed by Sun Microsystems, Inc.  are subject to
+the following clarification and special exception to the GPL, but only where
+Sun has expressly included in the particular source file's header the words
+"Sun designates this particular file as subject to the "Classpath" exception
+as provided by Sun in the LICENSE file that accompanied this code."
+
+    Linking this library statically or dynamically with other modules is making
+    a combined work based on this library.  Thus, the terms and conditions of
+    the GNU General Public License cover the whole combination.
+
+    As a special exception, the copyright holders of this library give you
+    permission to link this library with independent modules to produce an
+    executable, regardless of the license terms of these independent modules,
+    and to copy and distribute the resulting executable under terms of your
+    choice, provided that you also meet, for each linked independent module,
+    the terms and conditions of the license of that module.  An independent
+    module is a module which is not derived from or based on this library.  If
+    you modify this library, you may extend this exception to your version of
+    the library, but you are not obligated to do so.  If you do not wish to do
+    so, delete this exception statement from your version.
diff --git a/javax.vecmath/META-INF/MANIFEST.MF b/javax.vecmath/META-INF/MANIFEST.MF
new file mode 100644 (file)
index 0000000..a486382
--- /dev/null
@@ -0,0 +1,8 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Vecmath
+Bundle-SymbolicName: javax.vecmath
+Bundle-Version: 1.5.2
+Bundle-Vendor: VTT Technical Research Centre of Finland
+Bundle-RequiredExecutionEnvironment: JavaSE-1.6
+Export-Package: javax.vecmath
diff --git a/javax.vecmath/README.txt b/javax.vecmath/README.txt
new file mode 100644 (file)
index 0000000..542597b
--- /dev/null
@@ -0,0 +1,23 @@
+This is the vanilla javax.vecmath version 1.5.2 source originally
+downloaded from the dev.java.net site that has since been closed.
+
+Note that we do not extend the code in this library, we only use
+the library as is. Therefore we are using it according to the
+"CLASSPATH" EXCEPTION TO THE GPL as stated in LICENSE.txt meaning
+the code using this library does not have to be GPLv2 licensed.
+
+----
+
+The source code in this directory is copyrighted code that is licensed
+to individuals or companies who download or otherwise access the code.
+
+The copyright notice for the vecmath source code is in the
+COPYRIGHT.txt file.
+
+The license for the vecmath source code is in the LICENSE.txt
+file.
+
+Note that the source files in this directory are not sufficient to
+build vecmath. If you want to build vecmath, you can use CVS to get a
+complete source tree.  See
+https://vecmath.dev.java.net/build-instr.html for more information.
diff --git a/javax.vecmath/build.properties b/javax.vecmath/build.properties
new file mode 100644 (file)
index 0000000..3e1218d
--- /dev/null
@@ -0,0 +1,8 @@
+source.. = src/\r
+output.. = bin/\r
+bin.includes = .,\\r
+               COPYRIGHT.txt,\\r
+               LICENSE-SPEC.html,\\r
+               LICENSE.txt,\\r
+               META-INF/,\\r
+               README.txt\r
diff --git a/javax.vecmath/pom.xml b/javax.vecmath/pom.xml
new file mode 100644 (file)
index 0000000..9c5d2e4
--- /dev/null
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
+       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
+       xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+       <modelVersion>4.0.0</modelVersion>
+
+       <parent>
+               <groupId>org.simantics.g3d</groupId>
+               <artifactId>org.simantics.g3d.root</artifactId>
+               <version>1.0.0-SNAPSHOT</version>
+       </parent>
+
+       <artifactId>javax.vecmath</artifactId>
+       <packaging>eclipse-plugin</packaging>
+       <version>1.5.2</version>
+
+</project>
diff --git a/javax.vecmath/src/javax/vecmath/AxisAngle4d.java b/javax.vecmath/src/javax/vecmath/AxisAngle4d.java
new file mode 100644 (file)
index 0000000..7c38e97
--- /dev/null
@@ -0,0 +1,652 @@
+/*
+ * $RCSfile: AxisAngle4d.java,v $
+ *
+ * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ * $Revision: 1.9 $
+ * $Date: 2008/02/28 20:18:50 $
+ * $State: Exp $
+ */
+
+package javax.vecmath;
+
+/**
+ * A four-element axis angle represented by double-precision floating point 
+ * x,y,z,angle components.  An axis angle is a rotation of angle (radians)
+ * about the vector (x,y,z).
+ *
+ */
+public class AxisAngle4d implements java.io.Serializable, Cloneable {
+
+
+    // Compatible with 1.1
+    static final long serialVersionUID = 3644296204459140589L;
+
+    /**
+     * The x coordinate.
+     */
+    public     double  x;
+
+    /**
+     * The y coordinate.
+     */
+    public     double  y;
+
+    /**
+     * The z coordinate.
+     */
+    public     double  z;
+
+    /**
+     * The angle of rotation in radians.
+     */
+    public     double  angle;
+
+    // Fixed to issue 538
+    final static double EPS = 1.0e-12;
+    
+    /**
+     * Constructs and initializes an AxisAngle4d from the specified 
+     * x, y, z, and angle.
+     * @param x the x coordinate
+     * @param y the y coordinate
+     * @param z the z coordinate
+     * @param angle the angle of rotation in radians
+     */
+    public AxisAngle4d(double x, double y, double z, double angle)
+    {
+       this.x = x;
+       this.y = y;
+       this.z = z;
+       this.angle = angle;
+    }
+
+
+    /**
+     * Constructs and initializes an AxisAngle4d from the components
+     * contained in the array.  
+     * @param a  the array of length 4 containing x,y,z,angle in order 
+     */ 
+        public AxisAngle4d(double[] a) 
+     { 
+         this.x = a[0]; 
+         this.y = a[1]; 
+         this.z = a[2]; 
+         this.angle = a[3]; 
+     }
+    /**
+     * Constructs and initializes an AxisAngle4d from the specified AxisAngle4d.
+     * @param a1 the AxisAngle4d containing the initialization x y z angle data
+     */
+    public AxisAngle4d(AxisAngle4d a1)
+    {
+       this.x = a1.x;
+       this.y = a1.y;
+       this.z = a1.z;
+       this.angle = a1.angle;
+    }
+
+
+    /**
+     * Constructs and initializes an AxisAngle4d from the specified 
+     * AxisAngle4f.
+     * @param a1 the AxisAngle4f containing the initialization x y z angle data
+     */
+    public AxisAngle4d(AxisAngle4f a1)
+    {
+       this.x = a1.x;
+       this.y = a1.y;
+       this.z = a1.z;
+       this.angle = a1.angle;
+    }
+
+
+    /**
+     * Constructs and initializes an AxisAngle4d from the specified 
+     * axis and angle.
+     * @param axis the axis
+     * @param angle the angle of rotation in radian
+     *
+     * @since vecmath 1.2
+     */
+    public AxisAngle4d(Vector3d axis, double angle) {
+       this.x = axis.x;
+       this.y = axis.y;
+       this.z = axis.z;
+       this.angle = angle;
+    }
+
+
+    /**
+     * Constructs and initializes an AxisAngle4d to (0,0,1,0).
+     */
+    public AxisAngle4d()
+    {
+       this.x = 0.0;
+       this.y = 0.0;
+       this.z = 1.0;
+       this.angle = 0.0;
+    }
+
+
+    /**
+     * Sets the value of this axis angle to the specified x,y,z,angle.
+     * @param x the x coordinate
+     * @param y the y coordinate
+     * @param z the z coordinate
+     * @param angle  the angle of rotation in radians
+     */
+    public final void set(double x, double y, double z, double angle)
+    {
+       this.x = x;
+       this.y = y;
+       this.z = z;
+       this.angle = angle;
+    }
+
+
+    /**
+     * Sets the value of this axis angle to the specified x,y,z,angle.
+     * @param a  the array of length 4 containing x,y,z,angle in order
+     */
+    public final void set(double[] a)
+    {
+       this.x = a[0];
+       this.y = a[1];
+       this.z = a[2];
+       this.angle = a[3];
+    }
+
+
+    /**
+     * Sets the value of this axis angle to the value of axis angle a1.
+     * @param a1 the axis angle to be copied
+     */
+    public final void set(AxisAngle4d a1)
+    {
+       this.x = a1.x;
+       this.y = a1.y;
+       this.z = a1.z;
+       this.angle = a1.angle;
+    }
+
+
+    /**
+     * Sets the value of this axis angle to the value of axis angle a1.
+     * @param a1 the axis angle to be copied
+     */
+    public final void set(AxisAngle4f a1)
+    {
+       this.x = a1.x;
+       this.y = a1.y;
+       this.z = a1.z;
+       this.angle = a1.angle;
+    }
+
+
+    /**
+     * Sets the value of this AxisAngle4d to the specified 
+     * axis and angle.
+     * @param axis the axis
+     * @param angle the angle of rotation in radians
+     *
+     * @since vecmath 1.2
+     */
+    public final void set(Vector3d axis, double angle) {
+       this.x = axis.x;
+       this.y = axis.y;
+       this.z = axis.z;
+       this.angle = angle;
+    }
+
+
+    /**
+     * Gets the value of this axis angle and places it into the array a of
+     * length four in x,y,z,angle order.
+     * @param a  the array of length four
+     */
+    public final void get(double[] a)
+    {
+        a[0] = this.x;
+        a[1] = this.y;
+        a[2] = this.z;
+        a[3] = this.angle;
+    }
+
+
+    /**
+     * Sets the value of this axis-angle to the rotational component of
+     * the passed matrix.
+     * If the specified matrix has no rotational component, the value
+     * of this AxisAngle4d is set to an angle of 0 about an axis of (0,1,0).
+     *
+     * @param m1 the matrix4f
+     */
+    public final void set(Matrix4f m1)
+    {
+        Matrix3d m3d = new Matrix3d();
+
+        m1.get(m3d);
+
+        x = (float)(m3d.m21 - m3d.m12);
+        y = (float)(m3d.m02 - m3d.m20);
+        z = (float)(m3d.m10 - m3d.m01);
+        double mag = x*x + y*y + z*z;
+
+       if (mag > EPS ) {
+           mag = Math.sqrt(mag);
+           double sin = 0.5*mag;
+           double cos = 0.5*(m3d.m00 + m3d.m11 + m3d.m22 - 1.0);
+           
+           angle = (float)Math.atan2(sin, cos);
+           
+           double invMag = 1.0/mag;
+           x = x*invMag;
+           y = y*invMag;
+           z = z*invMag;
+       } else {
+           x = 0.0f;
+           y = 1.0f;
+           z = 0.0f;
+           angle = 0.0f;
+       }
+    }
+
+
+    /**
+     * Sets the value of this axis-angle to the rotational component of
+     * the passed matrix.
+     * If the specified matrix has no rotational component, the value
+     * of this AxisAngle4d is set to an angle of 0 about an axis of (0,1,0).
+     *
+     * @param m1 the matrix4d
+     */
+    public final void set(Matrix4d m1)
+    {
+        Matrix3d m3d = new Matrix3d();
+
+        m1.get(m3d);
+
+        x = (float)(m3d.m21 - m3d.m12);
+        y = (float)(m3d.m02 - m3d.m20);
+        z = (float)(m3d.m10 - m3d.m01);
+
+        double mag = x*x + y*y + z*z;
+
+       if (mag > EPS ) {
+           mag = Math.sqrt(mag);
+
+           double sin = 0.5*mag;
+           double cos = 0.5*(m3d.m00 + m3d.m11 + m3d.m22 - 1.0);
+           angle = (float)Math.atan2(sin, cos);
+
+           double invMag = 1.0/mag;
+           x = x*invMag;
+           y = y*invMag;
+           z = z*invMag;
+       } else {
+           x = 0.0f;
+           y = 1.0f;
+           z = 0.0f;
+           angle = 0.0f;
+       }
+    }
+
+
+    /**
+     * Sets the value of this axis-angle to the rotational component of
+     * the passed matrix.
+     * If the specified matrix has no rotational component, the value
+     * of this AxisAngle4d is set to an angle of 0 about an axis of (0,1,0).
+     * @param m1 the matrix3f
+     */
+    public final void set(Matrix3f m1)
+    {
+        x = (float)(m1.m21 - m1.m12);
+        y = (float)(m1.m02 - m1.m20);
+        z = (float)(m1.m10 - m1.m01);
+        double mag = x*x + y*y + z*z;
+
+       if (mag > EPS ) {
+           mag = Math.sqrt(mag);
+
+           double sin = 0.5*mag;
+           double cos = 0.5*(m1.m00 + m1.m11 + m1.m22 - 1.0);
+           angle = (float)Math.atan2(sin, cos);
+
+           double invMag = 1.0/mag;
+           x = x*invMag;
+           y = y*invMag;
+           z = z*invMag;
+       } else {
+           x = 0.0f;
+           y = 1.0f;
+           z = 0.0f;
+           angle = 0.0f;
+       }
+    }
+
+
+    /**
+     * Sets the value of this axis-angle to the rotational component of
+     * the passed matrix.
+     * If the specified matrix has no rotational component, the value
+     * of this AxisAngle4d is set to an angle of 0 about an axis of (0,1,0).
+     * @param m1 the matrix3d
+     */
+    public final void set(Matrix3d m1)
+    {
+        x = (float)(m1.m21 - m1.m12);
+        y = (float)(m1.m02 - m1.m20);
+        z = (float)(m1.m10 - m1.m01);
+
+        double mag = x*x + y*y + z*z;
+
+       if (mag > EPS ) {
+           mag = Math.sqrt(mag);
+           
+           double sin = 0.5*mag;
+           double cos = 0.5*(m1.m00 + m1.m11 + m1.m22 - 1.0);
+           
+           angle = (float)Math.atan2(sin, cos);
+
+           double invMag = 1.0/mag;
+           x = x*invMag;
+           y = y*invMag;
+           z = z*invMag;
+       } else {
+           x = 0.0f;
+           y = 1.0f;
+           z = 0.0f;
+           angle = 0.0f;
+       }
+
+    }
+
+
+
+    /**
+      * Sets the value of this axis-angle to the rotational equivalent
+      * of the passed quaternion.
+      * If the specified quaternion has no rotational component, the value
+      * of this AxisAngle4d is set to an angle of 0 about an axis of (0,1,0).
+      * @param q1  the Quat4f
+      */
+    public final void set(Quat4f q1)
+    {
+        double mag = q1.x*q1.x + q1.y*q1.y + q1.z*q1.z;  
+
+        if( mag > EPS ) {
+           mag = Math.sqrt(mag);
+           double invMag = 1.0/mag;
+
+           x = q1.x*invMag;
+           y = q1.y*invMag;
+           z = q1.z*invMag;
+           angle = 2.0*Math.atan2(mag, q1.w); 
+       } else {
+           x = 0.0f;
+           y = 1.0f;
+           z = 0.0f;
+          angle = 0.0f;
+        } 
+  }
+
+
+    /**
+      * Sets the value of this axis-angle to the rotational equivalent
+      * of the passed quaternion.
+      * If the specified quaternion has no rotational component, the value
+      * of this AxisAngle4d is set to an angle of 0 about an axis of (0,1,0).
+      * @param q1  the Quat4d
+      */
+    public final void set(Quat4d q1)
+    {
+       double mag = q1.x*q1.x + q1.y*q1.y + q1.z*q1.z;  
+       
+       if ( mag > EPS ) {
+           mag = Math.sqrt(mag);
+           double invMag = 1.0/mag;
+           
+           x = q1.x*invMag;
+           y = q1.y*invMag;
+           z = q1.z*invMag;
+           angle = 2.0*Math.atan2(mag, q1.w); 
+        } else {
+           x = 0.0f;
+           y = 1.0f;
+           z = 0.0f;
+           angle = 0f;
+       }
+    }
+
+
+   /**
+     * Returns a string that contains the values of this AxisAngle4d.
+     * The form is (x,y,z,angle).
+     * @return the String representation
+     */  
+    public String toString() {
+       return "(" + this.x + ", " + this.y + ", " + this.z + ", " + this.angle + ")";
+    }
+
+
+   /**
+     * Returns true if all of the data members of AxisAngle4d a1 are
+     * equal to the corresponding data members in this AxisAngle4d.
+     * @param a1  the axis-angle with which the comparison is made
+     * @return  true or false
+     */  
+    public boolean equals(AxisAngle4d a1)
+    {
+        try {
+           return(this.x == a1.x && this.y == a1.y && this.z == a1.z
+            && this.angle == a1.angle);
+        }
+        catch (NullPointerException e2) {return false;}
+
+    }
+    /**
+     * Returns true if the Object o1 is of type AxisAngle4d and all of the
+     * data members of o1 are equal to the corresponding data members in
+     * this AxisAngle4d.
+     * @param o1  the object with which the comparison is made
+     * @return  true or false
+      */  
+    public boolean equals(Object o1)
+    {
+        try {
+           AxisAngle4d a2 = (AxisAngle4d) o1;
+           return(this.x == a2.x && this.y == a2.y && this.z == a2.z
+            && this.angle == a2.angle);
+        }
+        catch (NullPointerException e2) {return false;}
+        catch (ClassCastException   e1) {return false;}
+
+    }
+
+
+   /**
+     * Returns true if the L-infinite distance between this axis-angle
+     * and axis-angle a1 is less than or equal to the epsilon parameter, 
+     * otherwise returns false.  The L-infinite
+     * distance is equal to 
+     * MAX[abs(x1-x2), abs(y1-y2), abs(z1-z2), abs(angle1-angle2)].
+     * @param a1  the axis-angle to be compared to this axis-angle 
+     * @param epsilon  the threshold value  
+     */
+    public boolean epsilonEquals(AxisAngle4d a1, double epsilon)
+    {
+       double diff;
+
+       diff = x - a1.x;
+       if((diff<0?-diff:diff) > epsilon) return false;
+
+       diff = y - a1.y;
+       if((diff<0?-diff:diff) > epsilon) return false;
+
+       diff = z - a1.z;
+       if((diff<0?-diff:diff) > epsilon) return false;
+
+       diff = angle - a1.angle;
+       if((diff<0?-diff:diff) > epsilon) return false;
+
+       return true;
+    }
+
+
+    /**
+     * Returns a hash code value based on the data values in this
+     * object.  Two different AxisAngle4d objects with identical data values
+     * (i.e., AxisAngle4d.equals returns true) will return the same hash
+     * code value.  Two objects with different data members may return the
+     * same hash value, although this is not likely.
+     * @return the integer hash code value
+     */  
+    public int hashCode() {
+       long bits = 1L;
+       bits = 31L * bits + VecMathUtil.doubleToLongBits(x);
+       bits = 31L * bits + VecMathUtil.doubleToLongBits(y);
+       bits = 31L * bits + VecMathUtil.doubleToLongBits(z);
+       bits = 31L * bits + VecMathUtil.doubleToLongBits(angle);
+       return (int) (bits ^ (bits >> 32));
+    }
+
+    /**
+     * Creates a new object of the same class as this object.
+     *
+     * @return a clone of this instance.
+     * @exception OutOfMemoryError if there is not enough memory.
+     * @see java.lang.Cloneable
+     * @since vecmath 1.3
+     */
+    public Object clone() {
+       // Since there are no arrays we can just use Object.clone()
+       try {
+           return super.clone();
+       } catch (CloneNotSupportedException e) {
+           // this shouldn't happen, since we are Cloneable
+           throw new InternalError();
+       }
+    }
+
+
+       /**
+        * Get the axis angle, in radians.<br>
+        * An axis angle is a rotation angle about the vector (x,y,z).
+     * 
+        * @return the angle, in radians.
+        * 
+        * @since vecmath 1.5
+        */
+       public final double getAngle() {
+               return angle;
+       }
+
+
+       /**
+        * Set the axis angle, in radians.<br>
+        * An axis angle is a rotation angle about the vector (x,y,z).
+        * 
+        * @param angle The angle to set, in radians.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setAngle(double angle) {
+               this.angle = angle;
+       }
+
+
+       /**
+        * Get value of <i>x</i> coordinate. 
+        * 
+        * @return the <i>x</i> coordinate.
+        * 
+        * @since vecmath 1.5
+        */
+       public double getX() {
+               return x;
+       }
+
+
+       /**
+        * Set a new value for <i>x</i> coordinate.
+        * 
+        * @param x the <i>x</i> coordinate.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setX(double x) {
+               this.x = x;
+       }
+
+
+       /**
+        * Get value of <i>y</i> coordinate.
+        * 
+        * @return the <i>y</i> coordinate. 
+        * 
+        * @since vecmath 1.5
+        */
+       public  final double getY() {
+               return y;
+       }
+
+
+       /**
+        * Set a new value for <i>y</i> coordinate.
+        * 
+        * @param y the <i>y</i> coordinate.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setY(double y) {
+               this.y = y;
+       }
+
+
+       /**
+        * Get  value of <i>z</i> coordinate.
+        * 
+        * @return  the <i>z</i> coordinate.
+        * 
+        * @since vecmath 1.5
+        */
+       public double getZ() {
+               return z;
+       }
+
+
+       /**
+        * Set a new value for <i>z</i> coordinate.
+        * 
+        * @param z the <i>z</i> coordinate.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setZ(double z) {
+               this.z = z;
+       }
+
+}
diff --git a/javax.vecmath/src/javax/vecmath/AxisAngle4f.java b/javax.vecmath/src/javax/vecmath/AxisAngle4f.java
new file mode 100644 (file)
index 0000000..a7956da
--- /dev/null
@@ -0,0 +1,649 @@
+/*
+ * $RCSfile: AxisAngle4f.java,v $
+ *
+ * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ * $Revision: 1.8 $
+ * $Date: 2008/02/28 20:18:50 $
+ * $State: Exp $
+ */
+
+package javax.vecmath;
+
+import java.lang.Math;
+
+/**
+ * A four-element axis angle represented by single-precision floating point 
+ * x,y,z,angle components.  An axis angle is a rotation of angle (radians)
+ * about the vector (x,y,z).
+ *
+ */
+public class AxisAngle4f implements java.io.Serializable, Cloneable {
+
+  // Compatible with 1.1
+  static final long serialVersionUID = -163246355858070601L;
+
+  /**
+   * The x coordinate.
+   */
+  public       float   x;
+
+  /**
+   * The y coordinate.
+   */
+  public       float   y;
+
+  /**
+   * The z coordinate.
+   */
+  public       float   z;
+
+  /**
+   * The angle of rotation in radians.
+   */
+  public       float   angle;
+
+  final static double EPS = 0.000001;
+
+  /**
+   * Constructs and initializes a AxisAngle4f from the specified xyzw coordinates.
+   * @param x the x coordinate
+   * @param y the y coordinate
+   * @param z the z coordinate
+   * @param angle  the angle of rotation in radians
+   */
+  public AxisAngle4f(float x, float y, float z, float angle)
+  {
+    this.x = x;
+    this.y = y;
+    this.z = z;
+    this.angle = angle;
+  }
+
+
+  /**
+   * Constructs and initializes an AxisAngle4f from the array of length 4. 
+   * @param a the array of length 4 containing x,y,z,angle in order
+   */
+  public AxisAngle4f(float[] a)
+  {
+    this.x = a[0];
+    this.y = a[1];
+    this.z = a[2];
+    this.angle = a[3];
+  }
+
+
+  /**
+   * Constructs and initializes an AxisAngle4f from the specified 
+   * AxisAngle4f.
+   * @param a1 the AxisAngle4f containing the initialization x y z angle data
+   */
+  public AxisAngle4f(AxisAngle4f a1)
+  {
+    this.x = a1.x;
+    this.y = a1.y;
+    this.z = a1.z;
+    this.angle = a1.angle;
+  }
+
+
+  /**
+   * Constructs and initializes an AxisAngle4f from the specified AxisAngle4d.
+   * @param a1 the AxisAngle4d containing the initialization x y z angle data
+   */
+  public AxisAngle4f(AxisAngle4d a1)
+  {
+    this.x = (float) a1.x;
+    this.y = (float) a1.y;
+    this.z = (float) a1.z;
+    this.angle = (float) a1.angle;
+  }
+
+
+    /**
+     * Constructs and initializes an AxisAngle4f from the specified 
+     * axis and angle.
+     * @param axis the axis
+     * @param angle the angle of rotation in radians
+     *
+     * @since vecmath 1.2
+     */
+    public AxisAngle4f(Vector3f axis, float angle) {
+       this.x = axis.x;
+       this.y = axis.y;
+       this.z = axis.z;
+       this.angle = angle;
+    }
+
+
+  /**
+   * Constructs and initializes an AxisAngle4f to (0,0,1,0).
+   */
+  public AxisAngle4f()
+  {
+    this.x = 0.0f;
+    this.y = 0.0f;
+    this.z = 1.0f;
+    this.angle = 0.0f;
+  }
+
+
+    /**
+     * Sets the value of this axis-angle to the specified x,y,z,angle. 
+     * @param x the x coordinate
+     * @param y the y coordinate
+     * @param z the z coordinate
+     * @param angle  the angle of rotation in radians
+     */
+    public final void set(float x, float y, float z, float angle)
+    {
+       this.x = x;
+       this.y = y;
+       this.z = z;
+       this.angle = angle;
+    }
+
+
+    /**
+     * Sets the value of this axis-angle to the specified values in the
+     * array of length 4.
+     * @param a the array of length 4 containing x,y,z,angle in order
+     */
+    public final void set(float[] a)
+    {
+       this.x = a[0];
+       this.y = a[1];
+       this.z = a[2];
+       this.angle = a[3];
+    }
+
+
+    /**
+     * Sets the value of this axis-angle to the value of axis-angle a1.
+     * @param a1 the axis-angle to be copied
+     */
+    public final void set(AxisAngle4f a1)
+    {
+       this.x = a1.x;
+       this.y = a1.y;
+       this.z = a1.z;
+       this.angle = a1.angle;
+    }
+
+
+    /**
+     * Sets the value of this axis-angle to the value of axis-angle a1.
+     * @param a1 the axis-angle to be copied
+     */
+    public final void set(AxisAngle4d a1)
+    {
+       this.x = (float) a1.x;
+       this.y = (float) a1.y;
+       this.z = (float) a1.z;
+       this.angle = (float) a1.angle;
+    }
+
+
+    /**
+     * Sets the value of this AxisAngle4f to the specified 
+     * axis and angle.
+     * @param axis the axis
+     * @param angle the angle of rotation in radians
+     *
+     * @since vecmath 1.2
+     */
+    public final void set(Vector3f axis, float angle) {
+       this.x = axis.x;
+       this.y = axis.y;
+       this.z = axis.z;
+       this.angle = angle;
+    }
+
+
+    /**
+     * Copies the value of this axis-angle into the array a.
+     * @param a the array 
+     */
+   public final void get(float[] a)
+   {
+      a[0] = this.x;
+      a[1] = this.y;
+      a[2] = this.z;
+      a[3] = this.angle;
+   } 
+
+
+    /**
+      * Sets the value of this axis-angle to the rotational equivalent
+      * of the passed quaternion.
+      * If the specified quaternion has no rotational component, the value
+      * of this AxisAngle4f is set to an angle of 0 about an axis of (0,1,0).
+      * @param q1  the Quat4f
+      */
+    public final void set(Quat4f q1)
+    {
+       double mag = q1.x*q1.x + q1.y*q1.y + q1.z*q1.z;  
+
+       if ( mag > EPS ) {
+           mag = Math.sqrt(mag);
+           double invMag = 1.0/mag;
+           
+           x = (float)(q1.x*invMag);
+           y = (float)(q1.y*invMag);
+           z = (float)(q1.z*invMag);
+           angle = (float)(2.0*Math.atan2(mag, q1.w)); 
+        } else {
+           x = 0.0f;
+           y = 1.0f;
+           z = 0.0f;
+           angle = 0.0f;
+       }
+    }
+
+
+    /**
+      * Sets the value of this axis-angle to the rotational equivalent
+      * of the passed quaternion.
+      * If the specified quaternion has no rotational component, the value
+      * of this AxisAngle4f is set to an angle of 0 about an axis of (0,1,0).
+      * @param q1  the Quat4d
+      */
+    public final void set(Quat4d q1)
+    {
+        double mag = q1.x*q1.x + q1.y*q1.y + q1.z*q1.z;  
+
+        if (mag > EPS) {
+           mag = Math.sqrt(mag);
+           double invMag = 1.0/mag;
+
+           x = (float)(q1.x*invMag);
+           y = (float)(q1.y*invMag);
+           z = (float)(q1.z*invMag);
+           angle = (float)(2.0*Math.atan2(mag, q1.w)); 
+        } else {
+           x = 0.0f;
+           y = 1.0f;
+           z = 0.0f;
+           angle = 0.0f;
+       }
+    }
+
+
+  /**
+   * Sets the value of this axis-angle to the rotational component of
+   * the passed matrix.
+   * If the specified matrix has no rotational component, the value
+   * of this AxisAngle4f is set to an angle of 0 about an axis of (0,1,0).
+   * @param m1 the matrix4f
+   */
+  public final void set(Matrix4f m1)
+  {
+        Matrix3f m3f = new Matrix3f();
+
+        m1.get(m3f);
+
+        x = m3f.m21 - m3f.m12;
+        y = m3f.m02 - m3f.m20;
+        z = m3f.m10 - m3f.m01;
+        double mag = x*x + y*y + z*z;
+
+       if (mag > EPS) {
+           mag = Math.sqrt(mag);
+           double sin = 0.5*mag;
+           double cos = 0.5*(m3f.m00 + m3f.m11 + m3f.m22 - 1.0);
+
+           angle = (float)Math.atan2(sin, cos);
+           double invMag = 1.0/mag;
+           x = (float)(x*invMag);
+           y = (float)(y*invMag);
+           z = (float)(z*invMag);
+       } else {
+           x = 0.0f;
+           y = 1.0f;
+           z = 0.0f;
+           angle = 0.0f;
+       }
+
+
+  }
+
+
+  /**
+   * Sets the value of this axis-angle to the rotational component of
+   * the passed matrix.
+   * If the specified matrix has no rotational component, the value
+   * of this AxisAngle4f is set to an angle of 0 about an axis of (0,1,0).
+   * @param m1 the matrix4d
+   */
+  public final void set(Matrix4d m1)
+  {
+        Matrix3d m3d = new Matrix3d();
+
+        m1.get(m3d);
+
+
+        x = (float)(m3d.m21 - m3d.m12);
+        y = (float)(m3d.m02 - m3d.m20);
+        z = (float)(m3d.m10 - m3d.m01);
+        double mag = x*x + y*y + z*z;
+
+       if (mag > EPS) {
+           mag = Math.sqrt(mag);
+           double sin = 0.5*mag;
+           double cos = 0.5*(m3d.m00 + m3d.m11 + m3d.m22 - 1.0);
+           angle = (float)Math.atan2(sin, cos);
+           
+           double invMag = 1.0/mag;
+           x = (float)(x*invMag);
+           y = (float)(y*invMag);
+           z = (float)(z*invMag);
+       } else {
+           x = 0.0f;
+           y = 1.0f;
+           z = 0.0f;
+           angle = 0.0f;           
+       }
+
+  }
+
+
+  /**
+   * Sets the value of this axis-angle to the rotational component of
+   * the passed matrix.
+   * If the specified matrix has no rotational component, the value
+   * of this AxisAngle4f is set to an angle of 0 about an axis of (0,1,0).
+   * @param m1 the matrix3f
+   */
+  public final void set(Matrix3f m1)
+  {
+        x = (float)(m1.m21 - m1.m12);
+        y = (float)(m1.m02 - m1.m20);
+        z = (float)(m1.m10 - m1.m01);
+        double mag = x*x + y*y + z*z;
+       if (mag > EPS) {
+           mag = Math.sqrt(mag);
+           double sin = 0.5*mag;
+           double cos = 0.5*(m1.m00 + m1.m11 + m1.m22 - 1.0);
+           
+           angle = (float)Math.atan2(sin, cos);
+           
+           double invMag = 1.0/mag;
+           x = (float)(x*invMag);
+           y = (float)(y*invMag);
+           z = (float)(z*invMag);
+       } else {
+           x = 0.0f;
+           y = 1.0f;
+           z = 0.0f;
+           angle = 0.0f;           
+       }
+
+  }
+
+
+  /**
+   * Sets the value of this axis-angle to the rotational component of
+   * the passed matrix.
+   * If the specified matrix has no rotational component, the value
+   * of this AxisAngle4f is set to an angle of 0 about an axis of (0,1,0).
+   * @param m1 the matrix3d
+   */
+  public final void set(Matrix3d m1)
+  {
+
+        x = (float)(m1.m21 - m1.m12);
+        y = (float)(m1.m02 - m1.m20);
+        z = (float)(m1.m10 - m1.m01);
+        double mag = x*x + y*y + z*z;
+
+       if (mag > EPS) {
+           mag = Math.sqrt(mag);
+           double sin = 0.5*mag;
+           double cos = 0.5*(m1.m00 + m1.m11 + m1.m22 - 1.0);
+           
+           angle = (float)Math.atan2(sin, cos);
+           
+           double invMag = 1.0/mag;
+           x = (float)(x*invMag);
+           y = (float)(y*invMag);
+           z = (float)(z*invMag);
+       } else {
+           x = 0.0f;
+           y = 1.0f;
+           z = 0.0f;
+           angle = 0.0f;           
+       }
+  }
+
+
+   /**
+     * Returns a string that contains the values of this AxisAngle4f.
+     * The form is (x,y,z,angle).
+     * @return the String representation
+     */  
+    public String toString() {
+       return "(" + this.x + ", " + this.y + ", " + this.z + ", " + this.angle + ")";
+    }
+
+
+   /**
+     * Returns true if all of the data members of AxisAngle4f a1 are
+     * equal to the corresponding data members in this AxisAngle4f.
+     * @param a1  the axis-angle with which the comparison is made
+     * @return  true or false
+     */  
+    public boolean equals(AxisAngle4f a1)
+    {
+        try {
+            return(this.x == a1.x && this.y == a1.y && this.z == a1.z
+            && this.angle == a1.angle);
+        }
+        catch (NullPointerException e2) {return false;}
+
+    }
+
+    /**
+     * Returns true if the Object o1 is of type AxisAngle4f and all of the
+     * data members of o1 are equal to the corresponding data members in
+     * this AxisAngle4f.
+     * @param o1  the object with which the comparison is made
+     * @return  true or false
+      */  
+    public boolean equals(Object o1)
+    {
+        try {
+           AxisAngle4f a2 = (AxisAngle4f) o1;
+           return(this.x == a2.x && this.y == a2.y && this.z == a2.z
+            && this.angle == a2.angle);
+        }
+        catch (NullPointerException e2) {return false;}
+        catch (ClassCastException   e1) {return false;}
+
+    }
+
+   /**
+     * Returns true if the L-infinite distance between this axis-angle
+     * and axis-angle a1 is less than or equal to the epsilon parameter, 
+     * otherwise returns false.  The L-infinite
+     * distance is equal to 
+     * MAX[abs(x1-x2), abs(y1-y2), abs(z1-z2), abs(angle1-angle2)].
+     * @param a1  the axis-angle to be compared to this axis-angle 
+     * @param epsilon  the threshold value  
+     */
+    public boolean epsilonEquals(AxisAngle4f a1, float epsilon)
+    {
+       float diff;
+
+       diff = x - a1.x;
+       if((diff<0?-diff:diff) > epsilon) return false;
+
+       diff = y - a1.y;
+       if((diff<0?-diff:diff) > epsilon) return false;
+
+       diff = z - a1.z;
+       if((diff<0?-diff:diff) > epsilon) return false;
+
+       diff = angle - a1.angle;
+       if((diff<0?-diff:diff) > epsilon) return false;
+
+       return true;
+
+    }
+
+
+    /**
+     * Returns a hash code value based on the data values in this
+     * object.  Two different AxisAngle4f objects with identical data values
+     * (i.e., AxisAngle4f.equals returns true) will return the same hash
+     * code value.  Two objects with different data members may return the
+     * same hash value, although this is not likely.
+     * @return the integer hash code value
+     */  
+    public int hashCode() {
+       long bits = 1L;
+       bits = 31L * bits + (long)VecMathUtil.floatToIntBits(x);
+       bits = 31L * bits + (long)VecMathUtil.floatToIntBits(y);
+       bits = 31L * bits + (long)VecMathUtil.floatToIntBits(z);
+       bits = 31L * bits + (long)VecMathUtil.floatToIntBits(angle);
+       return (int) (bits ^ (bits >> 32));
+    }
+
+    /**
+     * Creates a new object of the same class as this object.
+     *
+     * @return a clone of this instance.
+     * @exception OutOfMemoryError if there is not enough memory.
+     * @see java.lang.Cloneable
+     * @since vecmath 1.3
+     */
+    public Object clone() {
+       // Since there are no arrays we can just use Object.clone()
+       try {
+           return super.clone();
+       } catch (CloneNotSupportedException e) {
+           // this shouldn't happen, since we are Cloneable
+           throw new InternalError();
+       }
+    }
+
+
+    /**
+        * Get the axis angle, in radians.<br>
+        * An axis angle is a rotation angle about the vector (x,y,z). 
+        * 
+        * @return Returns the angle, in radians.
+        * 
+        * @since vecmath 1.5
+        */
+       public final float getAngle() {
+               return angle;
+       }
+
+
+       /**
+        * Set the axis angle, in radians.<br>
+        * An axis angle is a rotation angle about the vector (x,y,z). 
+        * 
+        * @param angle The angle to set, in radians.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setAngle(float angle) {
+               this.angle = angle;
+       }
+
+
+       /**
+        * Get value of <i>x</i> coordinate.  
+        * 
+        * @return the <i>x</i> coordinate.
+        * 
+        * @since vecmath 1.5
+        */
+       public final float getX() {
+               return x;
+       }
+
+
+       /**
+        * Set a new value for <i>x</i> coordinate.
+        * 
+        * @param x the <i>x</i> coordinate.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setX(float x) {
+               this.x = x;
+       }
+
+
+       /**
+        * Get value of <i>y</i> coordinate.
+        * 
+        * @return the <i>y</i> coordinate 
+        * 
+        * @since vecmath 1.5
+        */
+       public final float getY() {
+               return y;
+       }
+
+
+       /**
+        * Set a new value for <i>y</i> coordinate.
+        * 
+        * @param y the <i>y</i> coordinate.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setY(float y) {
+               this.y = y;
+       }
+
+
+       /**
+        * Get  value of <i>z</i> coordinate.
+        * 
+        * @return the <i>z</i> coordinate.
+        * 
+        * @since vecmath 1.5
+        */
+       public final float getZ() {
+               return z;
+       }
+
+
+       /**
+        * Set a new value for <i>z</i> coordinate.
+        * 
+        * @param z the <i>z</i> coordinate.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setZ(float z) {
+               this.z = z;
+       }
+
+}
diff --git a/javax.vecmath/src/javax/vecmath/Color3b.java b/javax.vecmath/src/javax/vecmath/Color3b.java
new file mode 100644 (file)
index 0000000..a159b3d
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * $RCSfile: Color3b.java,v $
+ *
+ * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ * $Revision: 1.6 $
+ * $Date: 2008/02/28 20:18:50 $
+ * $State: Exp $
+ */
+
+package javax.vecmath;
+
+import java.awt.Color;
+
+
+/**
+ * A three-byte color value represented by byte x, y, and z values. The
+ * x, y, and z values represent the red, green, and blue values,
+ * respectively.
+ * <p>
+ * Note that Java defines a byte as a signed integer in the range
+ * [-128, 127]. However, colors are more typically represented by values 
+ * in the range [0, 255]. Java 3D recognizes this and for color
+ * treats the bytes as if the range were [0, 255]---in other words, as
+ * if the bytes were unsigned.
+ * <p>
+ * Java 3D assumes that a linear (gamma-corrected) visual is used for
+ * all colors.
+ *
+ */
+public class Color3b extends Tuple3b implements java.io.Serializable {
+
+    // Compatible with 1.1
+    static final long serialVersionUID = 6632576088353444794L;
+
+    /**
+     * Constructs and initializes a Color3b from the specified three values.
+     * @param c1 the red color value
+     * @param c2 the green color value
+     * @param c3 the blue color value
+     */
+    public Color3b(byte c1, byte c2, byte c3) {
+       super(c1,c2,c3);
+    }
+
+
+    /**
+     * Constructs and initializes a Color3b from input array of length 3.
+     * @param c the array of length 3 containing the r,g,b data in order
+     */
+    public Color3b(byte[] c) {
+       super(c);
+    }
+
+
+    /**
+     * Constructs and initializes a Color3b from the specified Color3b.
+     * @param c1 the Color3b containing the initialization r,g,b data
+     */
+    public Color3b(Color3b c1) {
+       super(c1);
+    }
+
+
+    /**
+     * Constructs and initializes a Color3b from the specified Tuple3b.
+     * @param t1 the Tuple3b containing the initialization r,g,b data
+     */
+    public Color3b(Tuple3b t1) {
+       super(t1);
+    }
+
+
+    /**
+     * Constructs and initializes a Color3b from the specified AWT
+     * Color object.  The alpha value of the AWT color is ignored.
+     * No conversion is done on the color to compensate for
+     * gamma correction.
+     *
+     * @param color the AWT color with which to initialize this
+     * Color3b object
+     *
+     * @since vecmath 1.2
+     */
+    public Color3b(Color color) {
+       super((byte)color.getRed(),
+             (byte)color.getGreen(),
+             (byte)color.getBlue());
+    }
+
+
+    /**
+     * Constructs and initializes a Color3b to (0,0,0).
+     */
+    public Color3b() {
+       super();
+    }
+
+
+    /**
+     * Sets the r,g,b values of this Color3b object to those of the
+     * specified AWT Color object.
+     * No conversion is done on the color to compensate for
+     * gamma correction.
+     *
+     * @param color the AWT color to copy into this Color3b object
+     *
+     * @since vecmath 1.2
+     */
+    public final void set(Color color) {
+       x = (byte)color.getRed();
+       y = (byte)color.getGreen();
+       z = (byte)color.getBlue();
+    }
+
+
+    /**
+     * Returns a new AWT color object initialized with the r,g,b
+     * values of this Color3b object.
+     *
+     * @return a new AWT Color object
+     *
+     * @since vecmath 1.2
+     */
+    public final Color get() {
+       int r = (int)x & 0xff;
+       int g = (int)y & 0xff;
+       int b = (int)z & 0xff;
+
+       return new Color(r, g, b);
+    }
+
+}
diff --git a/javax.vecmath/src/javax/vecmath/Color3f.java b/javax.vecmath/src/javax/vecmath/Color3f.java
new file mode 100644 (file)
index 0000000..864dcd0
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * $RCSfile: Color3f.java,v $
+ *
+ * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ * $Revision: 1.6 $
+ * $Date: 2008/02/28 20:18:50 $
+ * $State: Exp $
+ */
+
+package javax.vecmath;
+
+import java.awt.Color;
+
+
+/**
+ * A three-element color value represented by single precision floating 
+ * point x,y,z values.  The x,y,z values represent the red, green, and 
+ * blue color values, respectively. Color components should be in the 
+ * range of [0.0, 1.0].
+ * <p>
+ * Java 3D assumes that a linear (gamma-corrected) visual is used for
+ * all colors.
+ *
+ */
+public class Color3f extends Tuple3f implements java.io.Serializable {
+
+    // Compatible with 1.1
+    static final long serialVersionUID = -1861792981817493659L;
+
+    /**
+     * Constructs and initializes a Color3f from the three xyz values.
+     * @param x the red color value
+     * @param y the green color value
+     * @param z the blue color value
+     */
+    public Color3f(float x, float y, float z) {
+        super(x,y,z);
+    }
+
+
+    /**
+     * Constructs and initializes a Color3f from the array of length 3.
+     * @param v the array of length 3 containing xyz in order
+     */
+    public Color3f(float[] v) {
+       super(v);
+    }
+
+
+    /**
+     * Constructs and initializes a Color3f from the specified Color3f.
+     * @param v1 the Color3f containing the initialization x y z data
+     */
+    public Color3f(Color3f v1) {
+       super(v1);
+    }
+
+
+    /**
+     * Constructs and initializes a Color3f from the specified Tuple3f.
+     * @param t1 the Tuple3f containing the initialization x y z data
+     */
+    public Color3f(Tuple3f t1) {
+       super(t1);
+    }
+
+
+    /**
+     * Constructs and initializes a Color3f from the specified Tuple3d.
+     * @param t1 the Tuple3d containing the initialization x y z data
+     */
+    public Color3f(Tuple3d t1) {
+       super(t1);
+    }
+
+
+    /**
+     * Constructs and initializes a Color3f from the specified AWT
+     * Color object.  The alpha value of the AWT color is ignored.
+     * No conversion is done on the color to compensate for
+     * gamma correction.
+     *
+     * @param color the AWT color with which to initialize this
+     * Color3f object
+     *
+     * @since vecmath 1.2
+     */
+    public Color3f(Color color) {
+       super((float)color.getRed() / 255.0f,
+             (float)color.getGreen() / 255.0f,
+             (float)color.getBlue() / 255.0f);
+    }
+
+
+    /**
+     * Constructs and initializes a Color3f to (0.0, 0.0, 0.0).
+     */
+    public Color3f() {
+        super();
+    }
+
+
+    /**
+     * Sets the r,g,b values of this Color3f object to those of the
+     * specified AWT Color object.
+     * No conversion is done on the color to compensate for
+     * gamma correction.
+     *
+     * @param color the AWT color to copy into this Color3f object
+     *
+     * @since vecmath 1.2
+     */
+    public final void set(Color color) {
+       x = (float)color.getRed() / 255.0f;
+       y = (float)color.getGreen() / 255.0f;
+       z = (float)color.getBlue() / 255.0f;
+    }
+
+
+    /**
+     * Returns a new AWT color object initialized with the r,g,b
+     * values of this Color3f object.
+     *
+     * @return a new AWT Color object
+     *
+     * @since vecmath 1.2
+     */
+    public final Color get() {
+       int r = Math.round(x * 255.0f);
+       int g = Math.round(y * 255.0f);
+       int b = Math.round(z * 255.0f);
+
+       return new Color(r, g, b);
+    }
+
+}
diff --git a/javax.vecmath/src/javax/vecmath/Color4b.java b/javax.vecmath/src/javax/vecmath/Color4b.java
new file mode 100644 (file)
index 0000000..2cbdacd
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+ * $RCSfile: Color4b.java,v $
+ *
+ * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ * $Revision: 1.6 $
+ * $Date: 2008/02/28 20:18:50 $
+ * $State: Exp $
+ */
+
+package javax.vecmath;
+
+import java.awt.Color;
+
+
+/**
+ * A four-byte color value represented by byte x, y, z, and w values. 
+ * The x, y, z, and w values represent the red, green, blue, and alpha
+ * values, respectively.
+ * <p>
+ * Note that Java defines a byte as a signed integer in the range
+ * [-128, 127]. However, colors are more typically represented by values
+ * in the range [0, 255]. Java 3D recognizes this and for color
+ * treats the bytes as if the range were [0, 255]---in other words, as
+ * if the bytes were unsigned.
+ * <p>
+ * Java 3D assumes that a linear (gamma-corrected) visual is used for
+ * all colors.
+ *
+ */
+public class Color4b extends Tuple4b implements java.io.Serializable {
+
+    // Compatible with 1.1
+    static final long serialVersionUID = -105080578052502155L;
+
+    /**
+     * Constructs and initializes a Color4b from the four specified values.
+     * @param b1 the red color value
+     * @param b2 the green color value
+     * @param b3 the blue color value
+     * @param b4 the alpha value
+     */
+    public Color4b(byte b1, byte b2, byte b3, byte b4) {
+       super(b1,b2,b3,b4);
+    }
+
+
+    /**
+     * Constructs and initializes a Color4b from the array of length 4.
+     * @param c the array of length 4 containing r, g, b, and alpha in order
+     */
+    public Color4b(byte[] c) {
+       super(c);
+    }
+
+
+    /**
+     * Constructs and initializes a Color4b from the specified Color4b.
+     * @param c1 the Color4b containing the initialization r,g,b,a
+     * data
+     */
+    public Color4b(Color4b c1) {
+        super(c1);
+    }
+
+
+    /**
+     * Constructs and initializes a Color4b from the specified Tuple4b.
+     * @param t1 the Tuple4b containing the initialization r,g,b,a
+     * data
+     */
+    public Color4b(Tuple4b t1) {
+       super(t1);
+    }
+
+
+    /**
+     * Constructs and initializes a Color4b from the specified AWT
+     * Color object.
+     * No conversion is done on the color to compensate for
+     * gamma correction.
+     *
+     * @param color the AWT color with which to initialize this
+     * Color4b object
+     *
+     * @since vecmath 1.2
+     */
+    public Color4b(Color color) {
+       super((byte)color.getRed(),
+             (byte)color.getGreen(),
+             (byte)color.getBlue(),
+             (byte)color.getAlpha());
+    }
+
+
+    /**
+     * Constructs and initializes a Color4b to (0,0,0,0).
+     */
+    public Color4b() {
+        super();
+    }
+
+
+    /**
+     * Sets the r,g,b,a values of this Color4b object to those of the
+     * specified AWT Color object.
+     * No conversion is done on the color to compensate for
+     * gamma correction.
+     *
+     * @param color the AWT color to copy into this Color4b object
+     *
+     * @since vecmath 1.2
+     */
+    public final void set(Color color) {
+       x = (byte)color.getRed();
+       y = (byte)color.getGreen();
+       z = (byte)color.getBlue();
+       w = (byte)color.getAlpha();
+    }
+
+
+    /**
+     * Returns a new AWT color object initialized with the r,g,b,a
+     * values of this Color4b object.
+     *
+     * @return a new AWT Color object
+     *
+     * @since vecmath 1.2
+     */
+    public final Color get() {
+       int r = (int)x & 0xff;
+       int g = (int)y & 0xff;
+       int b = (int)z & 0xff;
+       int a = (int)w & 0xff;
+
+       return new Color(r, g, b, a);
+    }
+
+}
diff --git a/javax.vecmath/src/javax/vecmath/Color4f.java b/javax.vecmath/src/javax/vecmath/Color4f.java
new file mode 100644 (file)
index 0000000..f2651ba
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ * $RCSfile: Color4f.java,v $
+ *
+ * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ * $Revision: 1.6 $
+ * $Date: 2008/02/28 20:18:50 $
+ * $State: Exp $
+ */
+
+package javax.vecmath;
+
+import java.awt.Color;
+
+
+/**
+ * A four-element color represented by single precision floating point 
+ * x, y, z, and w values.  The x, y, z, and w values represent the red,
+ * blue, green, and alpha color values, respectively. Color and alpha 
+ * components should be in the range [0.0, 1.0].
+ * <p>
+ * Java 3D assumes that a linear (gamma-corrected) visual is used for
+ * all colors.
+ *
+ */
+public class Color4f extends Tuple4f implements java.io.Serializable {
+
+    // Compatible with 1.1
+    static final long serialVersionUID = 8577680141580006740L;
+
+    /**
+     * Constructs and initializes a Color4f from the specified xyzw
+     * coordinates.
+     * @param x the red color value
+     * @param y the green color value
+     * @param z the blue color value
+     * @param w the alpha value
+     */
+    public Color4f(float x, float y, float z, float w) {
+       super(x,y,z,w);
+    }
+
+
+    /**
+     * Constructs and initializes a Color4f from the array of length 4.
+     * @param c the array of length 4 containing r,g,b,a in order
+     */
+    public Color4f(float[] c) {
+       super(c);
+    }
+
+
+    /**
+     * Constructs and initializes a Color4f from the specified Color4f.
+     * @param c1 the Color4f containing the initialization r,g,b,a data
+     */
+    public Color4f(Color4f c1) {
+       super(c1);
+    }
+
+
+    /**
+     * Constructs and initializes a Color4f from the specified Tuple4f.
+     * @param t1 the Tuple4f containing the initialization r,g,b,a data
+     */
+    public Color4f(Tuple4f t1) {
+       super(t1);
+    }
+
+
+    /**
+     * Constructs and initializes a Color4f from the specified Tuple4d.
+     * @param t1 the Tuple4d containing the initialization r,g,b,a data
+     */
+    public Color4f(Tuple4d t1) {
+       super(t1);
+    }
+
+
+    /**
+     * Constructs and initializes a Color4f from the specified AWT
+     * Color object.
+     * No conversion is done on the color to compensate for
+     * gamma correction.
+     *
+     * @param color the AWT color with which to initialize this
+     * Color4f object
+     *
+     * @since vecmath 1.2
+     */
+    public Color4f(Color color) {
+       super((float)color.getRed() / 255.0f,
+             (float)color.getGreen() / 255.0f,
+             (float)color.getBlue() / 255.0f,
+             (float)color.getAlpha() / 255.0f);
+    }
+
+
+    /**
+     * Constructs and initializes a Color4f to (0.0, 0.0, 0.0, 0.0).
+     */
+    public Color4f() {
+       super();
+    }
+
+
+    /**
+     * Sets the r,g,b,a values of this Color4f object to those of the
+     * specified AWT Color object.
+     * No conversion is done on the color to compensate for
+     * gamma correction.
+     *
+     * @param color the AWT color to copy into this Color4f object
+     *
+     * @since vecmath 1.2
+     */
+    public final void set(Color color) {
+       x = (float)color.getRed() / 255.0f;
+       y = (float)color.getGreen() / 255.0f;
+       z = (float)color.getBlue() / 255.0f;
+       w = (float)color.getAlpha() / 255.0f;
+    }
+
+
+    /**
+     * Returns a new AWT color object initialized with the r,g,b,a
+     * values of this Color4f object.
+     *
+     * @return a new AWT Color object
+     *
+     * @since vecmath 1.2
+     */
+    public final Color get() {
+       int r = Math.round(x * 255.0f);
+       int g = Math.round(y * 255.0f);
+       int b = Math.round(z * 255.0f);
+       int a = Math.round(w * 255.0f);
+
+       return new Color(r, g, b, a);
+    }
+
+}
diff --git a/javax.vecmath/src/javax/vecmath/ExceptionStrings.properties b/javax.vecmath/src/javax/vecmath/ExceptionStrings.properties
new file mode 100644 (file)
index 0000000..ca56746
--- /dev/null
@@ -0,0 +1,86 @@
+Matrix3d0=Matrix3d setElement
+Matrix3d1=Matrix3d getElement
+Matrix3d2=Matrix3d getRow
+Matrix3d4=Matrix3d getColumn
+Matrix3d6=Matrix3d setRow
+Matrix3d9=Matrix3d setColumn
+Matrix3d12=cannot invert matrix
+Matrix3d13=Logic error: imax < 0
+Matrix3f0=Matrix3f setElement
+Matrix3f1=Matrix3d getRow
+Matrix3f3=Matrix3d getColumn
+Matrix3f5=Matrix3f getElement
+Matrix3f6=Matrix3f setRow
+Matrix3f9=Matrix3f setColumn
+Matrix3f12=cannot invert matrix
+Matrix3f13=Logic error: imax < 0
+Matrix4d0=Matrix4d setElement
+Matrix4d1=Matrix4d getElement
+Matrix4d2=Matrix4d getRow
+Matrix4d3=Matrix4d getColumn
+Matrix4d4=Matrix4d setRow
+Matrix4d7=Matrix4d setColumn
+Matrix4d10=cannot invert matrix
+Matrix4d11=Logic error: imax < 0
+Matrix4f0=Matrix4f setElement
+Matrix4f1=Matrix4f getElement
+Matrix4f2=Matrix4f getRow
+Matrix4f4=Matrix4f getColumn
+Matrix4f6=Matrix4f setRow
+Matrix4f9=Matrix4f setColumn
+Matrix4f12=cannot invert matrix
+Matrix4f13=Logic error: imax < 0
+GMatrix0=GMatrix.mul:array dimension mismatch 
+GMatrix1=GMatrix.mul(GMatrix, GMatrix) dimension mismatch 
+GMatrix2=GMatrix.mul(GVector, GVector): matrix does not have enough rows 
+GMatrix3=GMatrix.mul(GVector, GVector): matrix does not have enough columns 
+GMatrix4=GMatrix.add(GMatrix): row dimension mismatch 
+GMatrix5=GMatrix.add(GMatrix): column dimension mismatch 
+GMatrix6=GMatrix.add(GMatrix, GMatrix): row dimension mismatch 
+GMatrix7=GMatrix.add(GMatrix, GMatrix): column dimension mismatch 
+GMatrix8=GMatrix.add(GMatrix): input matrices dimensions do not match this matrix dimensions
+GMatrix9=GMatrix.sub(GMatrix): row dimension mismatch 
+GMatrix10=GMatrix.sub(GMatrix, GMatrix): row dimension mismatch 
+GMatrix11=GMatrix.sub(GMatrix, GMatrix): column dimension mismatch 
+GMatrix12=GMatrix.sub(GMatrix, GMatrix): input matrix dimensions do not match dimensions for this matrix 
+GMatrix13=GMatrix.negate(GMatrix, GMatrix): input matrix dimensions do not match dimensions for this matrix 
+GMatrix14=GMatrix.mulTransposeBoth matrix dimension mismatch
+GMatrix15=GMatrix.mulTransposeRight matrix dimension mismatch
+GMatrix16=GMatrix.mulTransposeLeft matrix dimension mismatch
+GMatrix17=GMatrix.transpose(GMatrix) mismatch in matrix dimensions
+GMatrix18=GMatrix.SVD: dimension mismatch with V matrix
+GMatrix19=cannot perform LU decomposition on a non square matrix
+GMatrix20=row permutation must be same dimension as matrix
+GMatrix21=cannot invert matrix
+GMatrix22=cannot invert non square matrix
+GMatrix24=Logic error: imax < 0
+GMatrix25=GMatrix.SVD: dimension mismatch with U matrix
+GMatrix26=GMatrix.SVD: dimension mismatch with W matrix
+GMatrix27=LU must have same dimensions as this matrix
+GMatrix28=GMatrix.sub(GMatrix): column dimension mismatch
+GVector0=GVector.normalize( GVector) input vector and this vector lengths not matched
+GVector1=GVector.scale(double,  GVector) input vector and this vector lengths not matched
+GVector2=GVector.scaleAdd(GVector, GVector) input vector dimensions not matched
+GVector3=GVector.scaleAdd(GVector, GVector) input vectors and  this vector dimensions not matched
+GVector4=GVector.add(GVector) input vectors and  this vector dimensions not matched
+GVector5=GVector.add(GVector, GVector) input vector dimensions not matched
+GVector6=GVector.add(GVector, GVector) input vectors and  this vector dimensions not matched
+GVector7=GVector.sub(GVector) input vector and  this vector dimensions not matched
+GVector8=GVector.sub(GVector,  GVector) input vector dimensions not matched
+GVector9=GVector.sub(GMatrix,  GVector) input vectors and this vector dimensions not matched
+GVector10=GVector.mul(GMatrix,  GVector) matrix and vector dimensions not matched
+GVector11=GVector.mul(GMatrix,  GVector) matrix this vector dimensions not matched
+GVector12=GVector.mul(GVector, GMatrix) matrix and vector dimensions not matched
+GVector13=GVector.mul(GVector, GMatrix) matrix this vector dimensions not matched
+GVector14=GVector.dot(GVector) input vector and this vector have different sizes
+GVector15=matrix dimensions are not compatible 
+GVector16=b vector does not match matrix dimension 
+GVector17=GVector.interpolate(GVector, GVector, float) input vectors have different lengths 
+GVector18=GVector.interpolate(GVector, GVector, float) input vectors and this vector have different lengths
+GVector19=GVector.interpolate(GVector, float) input vector and this vector have different lengths
+GVector20=GVector.interpolate(GVector, GVector, double) input vectors have different lengths 
+GVector21=GVector.interpolate(GVector, GVector, double) input vectors and this vector have different lengths
+GVector22=GVector.interpolate(GVector,  double) input vectors and this vector have different lengths
+GVector23=matrix dimensions are not compatible
+GVector24=permutation vector does not match matrix dimension
+GVector25=LUDBackSolve non square matrix
diff --git a/javax.vecmath/src/javax/vecmath/GMatrix.java b/javax.vecmath/src/javax/vecmath/GMatrix.java
new file mode 100644 (file)
index 0000000..8674a57
--- /dev/null
@@ -0,0 +1,3008 @@
+/*
+ * $RCSfile: GMatrix.java,v $
+ *
+ * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ * $Revision: 1.7 $
+ * $Date: 2008/02/28 20:18:50 $
+ * $State: Exp $
+ */
+
+package javax.vecmath;
+
+import java.lang.Math;
+
+/**
+ * A double precision, general, dynamically-resizable,
+ * two-dimensional matrix class.  Row and column numbering begins with
+ * zero.  The representation is row major.
+ */
+
+public class GMatrix implements java.io.Serializable, Cloneable {
+
+    // Compatible with 1.1
+    static final long serialVersionUID = 2777097312029690941L;
+    private static final boolean debug = false;
+
+    int nRow;
+    int nCol;
+
+    // double dereference is slow 
+    double[][] values;
+
+    private static final double EPS = 1.0E-10;
+
+    /**
+     * Constructs an nRow by NCol identity matrix. 
+     * Note that because row and column numbering begins with
+     * zero, nRow and nCol will be one larger than the maximum
+     * possible matrix index values.
+     * @param nRow  number of rows in this matrix.
+     * @param nCol  number of columns in this matrix.
+     */
+    public GMatrix(int nRow, int nCol)
+    {
+        values = new double[nRow][nCol];
+       this.nRow = nRow;
+       this.nCol = nCol;
+
+       int i, j;
+       for (i = 0; i < nRow; i++) {
+           for (j = 0; j < nCol; j++) {
+               values[i][j] = 0.0;
+           }
+       }
+
+       int l;
+       if (nRow < nCol)
+           l = nRow;
+        else
+           l = nCol;
+
+       for (i = 0; i < l; i++) {
+           values[i][i] = 1.0;
+       }
+    }
+
+    /** 
+     * Constructs an nRow by nCol matrix initialized to the values 
+     * in the matrix array.  The array values are copied in one row at
+     * a time in row major fashion.  The array should be at least 
+     * nRow*nCol in length.
+     * Note that because row and column numbering begins with 
+     * zero, nRow and nCol will be one larger than the maximum
+     * possible matrix index values.
+     * @param nRow  number of rows in this matrix. 
+     * @param nCol  number of columns in this matrix. 
+     * @param matrix  a 1D array that specifies a matrix in row major fashion
+     */ 
+    public GMatrix(int nRow, int nCol, double[] matrix)
+    {
+        values = new double[nRow][nCol];
+       this.nRow = nRow;
+       this.nCol = nCol;
+
+       int i, j;
+       for (i = 0; i < nRow; i++) {
+           for (j = 0; j < nCol; j++) {
+               values[i][j] = matrix[i*nCol+j];
+           }
+       }
+    }
+
+    /** 
+     * Constructs a new GMatrix and copies the initial values
+     * from the parameter matrix.
+     * @param matrix  the source of the initial values of the new GMatrix
+     */ 
+    public GMatrix(GMatrix matrix)
+    {
+        nRow = matrix.nRow;
+       nCol = matrix.nCol;
+        values = new double[nRow][nCol];
+
+       int i, j;
+       for (i = 0; i < nRow; i++) {
+           for (j = 0; j < nCol; j++) {
+               values[i][j] = matrix.values[i][j];
+           }
+       }
+    }
+
+    /**
+     * Sets the value of this matrix to the result of multiplying itself
+     * with matrix m1 (this = this * m1).  
+     * @param m1 the other matrix
+     */  
+    public final void mul(GMatrix m1)
+    {
+       int i, j, k;
+
+       if (nCol != m1.nRow ||  nCol != m1.nCol)
+           throw new MismatchedSizeException
+               (VecMathI18N.getString("GMatrix0"));
+
+       double [][] tmp = new double[nRow][nCol];
+
+       for (i = 0; i < nRow; i++) {
+           for (j = 0; j < nCol; j++) {
+               tmp[i][j] = 0.0;
+               for (k = 0; k < nCol; k++) {
+                   tmp[i][j] += values[i][k]*m1.values[k][j];  
+               }
+           }
+       }
+       
+       values = tmp;
+    }
+
+    /**
+     * Sets the value of this matrix to the result of multiplying
+     * the two argument matrices together (this = m1 * m2).
+     * @param m1 the first matrix
+     * @param m2 the second matrix
+     */
+    public final void mul(GMatrix m1, GMatrix m2)
+    {
+       int i, j, k;
+
+       if (m1.nCol != m2.nRow || nRow != m1.nRow || nCol != m2.nCol)
+           throw new MismatchedSizeException
+               (VecMathI18N.getString("GMatrix1"));
+
+       double[][] tmp = new double[nRow][nCol];
+
+       for (i = 0; i < m1.nRow; i++) {
+           for (j = 0; j < m2.nCol; j++) {
+               tmp[i][j] = 0.0;
+               for (k = 0; k < m1.nCol; k++) {
+                   tmp[i][j] += m1.values[i][k]*m2.values[k][j];       
+               }
+           }
+       }
+       
+       values = tmp;
+    }
+
+    /**
+     * Computes the outer product of the two vectors; multiplies the
+     * the first vector by the transpose of the second vector and places
+     * the matrix result into this matrix.  This matrix must be
+     * be as big or bigger than getSize(v1)xgetSize(v2).
+     * @param v1 the first vector, treated as a row vector
+     * @param v2 the second vector, treated as a column vector
+     */
+    public final void mul(GVector v1, GVector v2)
+    {
+       int i, j;
+
+       if (nRow < v1.getSize())
+           throw new MismatchedSizeException
+               (VecMathI18N.getString("GMatrix2"));
+
+       if (nCol < v2.getSize())
+           throw new MismatchedSizeException
+               (VecMathI18N.getString("GMatrix3"));
+
+       for (i = 0; i < v1.getSize(); i++ ) {
+           for (j = 0; j < v2.getSize(); j++ ) {
+               values[i][j] = v1.values[i]*v2.values[j];
+           }
+       }
+    }
+
+    /**
+     * Sets the value of this matrix to sum of itself and matrix m1.
+     * @param m1 the other matrix
+     */  
+    public final void add(GMatrix m1)
+    {
+       int i, j;
+
+       if (nRow != m1.nRow) 
+           throw new MismatchedSizeException
+               (VecMathI18N.getString("GMatrix4"));
+
+       if (nCol != m1.nCol) 
+           throw new MismatchedSizeException
+               (VecMathI18N.getString("GMatrix5"));
+
+       for (i = 0; i < nRow; i++) {
+           for (j = 0; j < nCol; j++) {
+               values[i][j] = values[i][j] + m1.values[i][j];
+           }
+       }
+    }
+
+    /**
+     * Sets the value of this matrix to the matrix sum of matrices m1 and m2.
+     * @param m1 the first matrix
+     * @param m2 the second matrix
+     */  
+    public final void add(GMatrix m1, GMatrix m2)
+    {
+       int i, j;
+
+       if (m2.nRow != m1.nRow) 
+           throw new MismatchedSizeException
+               (VecMathI18N.getString("GMatrix6"));
+
+       if (m2.nCol != m1.nCol) 
+           throw new MismatchedSizeException
+               (VecMathI18N.getString("GMatrix7"));
+
+       if (nCol != m1.nCol  || nRow != m1.nRow) 
+           throw new MismatchedSizeException
+               (VecMathI18N.getString("GMatrix8"));
+
+       for (i = 0; i < nRow; i++) {
+           for (j = 0; j < nCol; j++) {
+               values[i][j] = m1.values[i][j] + m2.values[i][j];
+           }
+       }
+    }
+
+    /**
+     * Sets the value of this matrix to the matrix difference of itself
+     * and matrix m1 (this = this - m1).
+     * @param m1 the other matrix
+     */  
+    public final void sub(GMatrix m1) 
+    { 
+       int i, j; 
+       if (nRow != m1.nRow)  
+           throw new MismatchedSizeException
+               (VecMathI18N.getString("GMatrix9")); 
+       if (nCol != m1.nCol) 
+           throw new MismatchedSizeException
+               (VecMathI18N.getString("GMatrix28")); 
+       for (i = 0; i < nRow; i++) { 
+           for (j = 0; j < nCol; j++) { 
+               values[i][j] = values[i][j] - m1.values[i][j];
+           } 
+       } 
+    } 
+
+    /**
+     * Sets the value of this matrix to the matrix difference
+     * of matrices m1 and m2 (this = m1 - m2).
+     * @param m1 the first matrix
+     * @param m2 the second matrix
+     */  
+    public final void sub(GMatrix m1, GMatrix m2) 
+    {
+       int i, j;
+       if (m2.nRow != m1.nRow) 
+           throw new MismatchedSizeException
+               (VecMathI18N.getString("GMatrix10"));
+
+       if (m2.nCol != m1.nCol) 
+           throw new MismatchedSizeException
+               (VecMathI18N.getString("GMatrix11"));
+
+       if (nRow !=  m1.nRow || nCol != m1.nCol) 
+           throw new MismatchedSizeException
+               (VecMathI18N.getString("GMatrix12"));
+         
+       for (i = 0; i < nRow; i++) {
+           for (j = 0; j < nCol; j++) {
+               values[i][j] = m1.values[i][j] - m2.values[i][j];
+           }
+       }
+    }
+
+    /** 
+     * Negates the value of this matrix: this = -this.
+     */
+    public final void negate()
+    {
+       int i, j;
+       for (i = 0; i < nRow; i++) {
+           for (j = 0;j < nCol; j++) {
+               values[i][j] = -values[i][j];
+           }
+       }
+    }
+
+    /**
+     *  Sets the value of this matrix equal to the negation of
+     *  of the GMatrix parameter.
+     *  @param m1  The source matrix
+     */  
+    public final void negate(GMatrix m1)
+    {
+       int i, j;
+       if (nRow != m1.nRow  || nCol != m1.nCol)
+           throw new MismatchedSizeException
+               (VecMathI18N.getString("GMatrix13"));
+
+       for (i = 0; i < nRow; i++) {
+           for (j = 0; j < nCol; j++) {
+               values[i][j] =  -m1.values[i][j];
+           }
+       }
+    }
+
+    /**
+     * Sets this GMatrix to the identity matrix.
+     */
+    public final void setIdentity()
+    {
+        int i, j;
+        for (i = 0; i < nRow; i++) {
+           for (j = 0; j < nCol; j++) {
+               values[i][j] = 0.0;
+           }
+        }
+
+        int l;
+        if (nRow < nCol)
+           l = nRow;
+        else
+           l = nCol;
+
+        for (i = 0; i < l; i++) {
+           values[i][i] = 1.0;
+        }
+    }
+
+    /**
+     * Sets all the values in this matrix to zero.
+     */
+    public final void setZero()
+    {
+       int i, j;
+       for (i = 0; i < nRow; i++) {
+           for (j = 0; j < nCol; j++) {
+               values[i][j] = 0.0; 
+           }
+       }   
+    }
+
+    /**
+     * Subtracts this matrix from the identity matrix and puts the values
+     * back into this (this = I - this).
+     */
+    public final void identityMinus()
+    {
+       int i, j;
+       for(i = 0; i < nRow; i++) {
+           for(j = 0; j < nCol; j++) { 
+               values[i][j] = -values[i][j]; 
+           } 
+       }    
+
+        int l; 
+        if( nRow < nCol) 
+           l = nRow; 
+        else 
+           l = nCol;
+        for(i = 0; i < l; i++) { 
+           values[i][i] += 1.0; 
+        } 
+    }
+
+   
+    /**
+     * Inverts this matrix in place.
+     */
+    public final void invert()
+    {
+       invertGeneral(this);
+    }
+
+    /**
+     * Inverts matrix m1 and places the new values into this matrix.  Matrix
+     * m1 is not modified.
+     * @param m1   the matrix to be inverted 
+     */ 
+    public final void invert(GMatrix m1)
+    {
+       invertGeneral(m1);
+    }
+
+    /**
+     * Copies a sub-matrix derived from this matrix into the target matrix.
+     * The upper left of the sub-matrix is located at (rowSource, colSource);
+     * the lower right of the sub-matrix is located at 
+     * (lastRowSource,lastColSource).  The sub-matrix is copied into the
+     * the target matrix starting at (rowDest, colDest).
+     * @param rowSource   the top-most row of the sub-matrix 
+     * @param colSource   the left-most column of the sub-matrix 
+     * @param numRow   the number of rows in the sub-matrix
+     * @param numCol  the number of columns in the sub-matrix
+     * @param rowDest  the top-most row of the position of the copied
+     *                 sub-matrix within the target matrix
+     * @param colDest  the left-most column of the position of the copied
+     *                 sub-matrix within the target matrix
+     * @param target  the matrix into which the sub-matrix will be copied
+     */
+    public final void copySubMatrix(int rowSource, int colSource, 
+                                   int numRow, int numCol, int rowDest,
+                                   int colDest, GMatrix target) 
+    {
+        int i, j;
+
+       if (this != target) {
+           for (i = 0; i < numRow; i++) {
+               for (j = 0; j < numCol; j++) {
+                   target.values[rowDest+i][colDest+j] =
+                       values[rowSource+i][colSource+j];
+               }
+           }
+       } else {
+           double[][] tmp = new double[numRow][numCol];
+           for (i = 0; i < numRow; i++) {
+               for (j = 0; j < numCol; j++) {
+                   tmp[i][j] = values[rowSource+i][colSource+j];
+               }
+           }
+           for (i = 0; i < numRow; i++) {
+               for (j = 0; j < numCol; j++) {
+                   target.values[rowDest+i][colDest+j] = tmp[i][j];
+               }
+           }
+       }
+    }
+
+    /**
+     * Changes the size of this matrix dynamically.  If the size is increased
+     * no data values will be lost.  If the size is decreased, only those data
+     * values whose matrix positions were eliminated will be lost.
+     * @param nRow  number of desired rows in this matrix
+     * @param nCol  number of desired columns in this matrix
+     */
+    public final void setSize(int nRow, int nCol)
+    {
+       double[][] tmp = new double[nRow][nCol];
+       int i, j, maxRow, maxCol;
+
+       if (this.nRow < nRow)
+           maxRow = this.nRow;
+       else
+           maxRow = nRow;
+
+       if (this.nCol < nCol)
+           maxCol = this.nCol;
+       else
+           maxCol = nCol;
+
+       for (i = 0; i < maxRow; i++) {
+           for (j = 0; j < maxCol; j++) {
+               tmp[i][j] = values[i][j];
+           }
+       }
+
+       this.nRow = nRow;
+       this.nCol = nCol;
+
+       values = tmp;
+    }
+
+    /**
+     * Sets the value of this matrix to the values found in the array parameter.
+     * The values are copied in one row at a time, in row major 
+     * fashion.  The array should be at least equal in length to
+     * the number of matrix rows times the number of matrix columns
+     * in this matrix.
+     * @param matrix  the row major source array
+     */  
+    public final void set(double[] matrix)
+    {
+       int i, j;
+        
+       for (i = 0; i < nRow; i++) { 
+           for (j = 0; j < nCol; j++) {
+               values[i][j] = matrix[nCol*i+j];
+           } 
+       }  
+    }
+
+    /**
+     * Sets the value of this matrix to that of the Matrix3f provided.
+     * @param m1 the matrix
+     */  
+    public final void set(Matrix3f m1)
+    {
+       int i, j;
+
+       if (nCol < 3 || nRow < 3) { // expand matrix if too small 
+           nCol = 3;
+           nRow = 3;
+           values = new double[nRow][nCol];
+        }
+
+        values[0][0] = m1.m00;
+        values[0][1] = m1.m01;
+        values[0][2] = m1.m02;
+
+        values[1][0] = m1.m10;
+        values[1][1] = m1.m11;
+        values[1][2] = m1.m12;
+
+        values[2][0] = m1.m20;
+        values[2][1] = m1.m21;
+        values[2][2] = m1.m22;
+
+        for (i = 3; i < nRow; i++) {   // pad rest or matrix with zeros 
+           for (j = 3; j < nCol; j++) {
+               values[i][j] = 0.0;
+           }
+        }
+    }
+
+    /**
+     * Sets the value of this matrix to that of the Matrix3d provided.
+     * @param m1 the matrix
+     */  
+    public final void set(Matrix3d m1)
+    {
+       if (nRow < 3 || nCol < 3) {
+           values = new double[3][3];
+           nRow = 3;
+           nCol = 3;
+       }
+
+        values[0][0] = m1.m00;
+        values[0][1] = m1.m01;
+        values[0][2] = m1.m02;
+
+        values[1][0] = m1.m10;
+        values[1][1] = m1.m11;
+        values[1][2] = m1.m12;
+
+        values[2][0] = m1.m20;
+        values[2][1] = m1.m21;
+        values[2][2] = m1.m22;
+
+        for (int i = 3; i < nRow; i++) {   // pad rest or matrix with zeros 
+           for(int j = 3; j < nCol; j++) {
+               values[i][j] = 0.0;
+           }
+        }
+
+    }
+
+    /**  
+     * Sets the value of this matrix to that of the Matrix4f provided.
+     * @param m1 the matrix
+     */  
+    public final void set(Matrix4f m1)
+    {
+       if (nRow < 4 || nCol < 4) {
+           values = new double[4][4];
+           nRow = 4;
+           nCol = 4;
+       }
+
+        values[0][0] = m1.m00;
+        values[0][1] = m1.m01;
+        values[0][2] = m1.m02;
+        values[0][3] = m1.m03;
+
+        values[1][0] = m1.m10;
+        values[1][1] = m1.m11;
+        values[1][2] = m1.m12;
+        values[1][3] = m1.m13;
+
+        values[2][0] = m1.m20;
+        values[2][1] = m1.m21;
+        values[2][2] = m1.m22;
+        values[2][3] = m1.m23;
+
+        values[3][0] = m1.m30;
+        values[3][1] = m1.m31;
+        values[3][2] = m1.m32;
+        values[3][3] = m1.m33;
+
+        for (int i = 4 ; i < nRow; i++) {   // pad rest or matrix with zeros 
+           for (int j = 4; j < nCol; j++) {
+               values[i][j] = 0.0;
+           }
+        }
+    }
+
+    /**   
+     * Sets the value of this matrix to that of the Matrix4d provided. 
+     * @param m1 the matrix 
+     */   
+    public final void set(Matrix4d m1) 
+    { 
+       if (nRow < 4 || nCol < 4) {
+           values = new double[4][4];
+           nRow = 4;
+           nCol = 4;
+       }
+
+        values[0][0] = m1.m00;
+        values[0][1] = m1.m01;
+        values[0][2] = m1.m02;
+        values[0][3] = m1.m03;
+
+        values[1][0] = m1.m10;
+        values[1][1] = m1.m11;
+        values[1][2] = m1.m12;
+        values[1][3] = m1.m13;
+
+        values[2][0] = m1.m20;
+        values[2][1] = m1.m21;
+        values[2][2] = m1.m22;
+        values[2][3] = m1.m23;
+
+        values[3][0] = m1.m30;
+        values[3][1] = m1.m31;
+        values[3][2] = m1.m32;
+        values[3][3] = m1.m33;
+
+        for (int i = 4; i < nRow; i++) {   // pad rest or matrix with zeros 
+           for (int j = 4; j < nCol; j++) {
+               values[i][j] = 0.0;
+           }
+        }
+    } 
+
+    /**
+     * Sets the value of this matrix to the values found in matrix m1.
+     * @param m1  the source matrix
+     */
+    public final void set(GMatrix m1)
+    {
+       int i, j;
+
+       if (nRow < m1.nRow || nCol < m1.nCol) {
+           nRow = m1.nRow;
+           nCol = m1.nCol;
+           values = new double[nRow][nCol];
+       }
+
+       for (i = 0; i < Math.min(nRow, m1.nRow); i++) {
+           for (j = 0; j < Math.min(nCol, m1.nCol); j++) {
+               values[i][j] = m1.values[i][j];
+           }
+       }
+
+        for (i = m1.nRow; i < nRow; i++) {   // pad rest or matrix with zeros 
+           for (j = m1.nCol; j < nCol; j++) {
+               values[i][j] = 0.0;
+           }
+        }
+    }
+
+    /**
+     * Returns the number of rows in this matrix.
+     * @return  number of rows in this matrix
+     */
+    public final int getNumRow()
+    {
+        return(nRow);
+    }
+
+    /**
+     * Returns the number of colmuns in this matrix.
+     * @return  number of columns in this matrix
+     */
+    public final int getNumCol()
+    {
+       return(nCol);
+    }
+
+    /**
+     * Retrieves the value at the specified row and column of this matrix.
+     * @param row the row number to be retrieved (zero indexed)
+     * @param column the column number to be retrieved (zero indexed)
+     * @return the value at the indexed element
+     */  
+    public final double getElement(int row, int column)
+    {
+        return(values[row][column]);
+    }
+
+    /**  
+     * Modifies the value at the specified row and column of this matrix.
+     * @param row  the row number to be modified (zero indexed) 
+     * @param column  the column number to be modified (zero indexed) 
+     * @param value  the new matrix element value
+     */   
+    public final void setElement(int row, int column, double value)
+    {
+       values[row][column] = value;
+    }
+
+    /**
+     * Places the values of the specified row into the array parameter.
+     * @param row  the target row number
+     * @param array  the array into which the row values will be placed
+     */
+    public final void getRow(int row, double[] array)
+    {
+       for (int i = 0; i < nCol; i++) {
+            array[i] = values[row][i];
+       }
+    }
+
+    /**
+     * Places the values of the specified row into the vector parameter.
+     * @param row  the target row number
+     * @param vector  the vector into which the row values will be placed
+     */  
+    public final void getRow(int row, GVector vector)
+    {
+       if (vector.getSize() < nCol)
+           vector.setSize(nCol);
+        
+       for (int i = 0; i < nCol; i++) {
+            vector.values[i] = values[row][i];
+       }
+    }
+
+    /**
+     * Places the values of the specified column into the array parameter.
+     * @param col  the target column number
+     * @param array  the array into which the column values will be placed
+     */
+    public final void getColumn(int col, double[] array)
+    {
+       for (int i = 0; i < nRow; i++) {
+            array[i] = values[i][col];
+       }
+
+    }
+
+    /**
+     * Places the values of the specified column into the vector parameter.
+     * @param col  the target column number
+     * @param vector  the vector into which the column values will be placed
+     */  
+    public final void getColumn(int col, GVector vector)
+    {
+       if (vector.getSize() < nRow)
+           vector.setSize(nRow);
+                  
+       for (int i = 0; i < nRow; i++) { 
+            vector.values[i] = values[i][col];   
+       } 
+    }
+
+    /**
+     * Places the values in the upper 3x3 of this GMatrix into
+     * the matrix m1.
+     * @param m1  The matrix that will hold the new values
+     */  
+    public final void get(Matrix3d m1)
+    {
+       if (nRow < 3 || nCol < 3) {
+           m1.setZero();
+           if (nCol > 0) {
+               if (nRow > 0){ 
+                   m1.m00 = values[0][0];
+                   if (nRow > 1){ 
+                       m1.m10 = values[1][0];
+                       if( nRow > 2 ){ 
+                           m1.m20= values[2][0];
+                       }
+                   }
+               }
+               if (nCol > 1) {
+                   if (nRow > 0) { 
+                       m1.m01 = values[0][1];
+                       if (nRow > 1){ 
+                           m1.m11 = values[1][1];
+                           if (nRow >  2){ 
+                               m1.m21 = values[2][1];
+                           }
+                       }
+                   }
+                   if (nCol > 2) {
+                       if (nRow > 0) { 
+                           m1.m02 = values[0][2];
+                           if (nRow > 1) {
+                               m1.m12 = values[1][2];
+                               if (nRow > 2) { 
+                                   m1.m22 = values[2][2];
+                               }
+                           }
+                       }
+                   }
+               }
+           }
+       } else {
+           m1.m00 = values[0][0];
+           m1.m01 = values[0][1];
+           m1.m02 = values[0][2];
+
+           m1.m10 = values[1][0];
+           m1.m11 = values[1][1];
+           m1.m12 = values[1][2];
+
+           m1.m20 = values[2][0];
+           m1.m21 = values[2][1];
+           m1.m22 = values[2][2];
+       }
+    }
+
+    /**
+     * Places the values in the upper 3x3 of this GMatrix into 
+     * the matrix m1. 
+     * @param m1  The matrix that will hold the new values
+     */  
+    public final void get(Matrix3f m1) 
+    { 
+
+       if (nRow < 3 || nCol < 3) {
+           m1.setZero();
+           if (nCol > 0) {
+               if (nRow > 0) { 
+                   m1.m00 = (float)values[0][0];
+                   if (nRow > 1) { 
+                       m1.m10 = (float)values[1][0];
+                       if (nRow > 2) { 
+                           m1.m20 = (float)values[2][0];
+                       }
+                   }
+               }
+               if (nCol > 1) {
+                   if (nRow > 0) { 
+                       m1.m01 = (float)values[0][1];
+                       if (nRow >  1){ 
+                           m1.m11 = (float)values[1][1];
+                           if (nRow >  2){ 
+                               m1.m21 = (float)values[2][1];
+                           }
+                       }
+                   }
+                   if (nCol > 2) {
+                       if (nRow > 0) { 
+                           m1.m02 = (float)values[0][2];
+                           if (nRow > 1) {
+                               m1.m12 = (float)values[1][2];
+                               if (nRow > 2) { 
+                                   m1.m22 = (float)values[2][2];
+                               }
+                           }
+                       }
+                   }
+               }
+           }
+        } else {
+           m1.m00 = (float)values[0][0];
+           m1.m01 = (float)values[0][1];
+           m1.m02 = (float)values[0][2];
+
+           m1.m10 = (float)values[1][0];
+           m1.m11 = (float)values[1][1];
+           m1.m12 = (float)values[1][2];
+
+           m1.m20 = (float)values[2][0];
+           m1.m21 = (float)values[2][1];
+           m1.m22 = (float)values[2][2];
+       }
+    } 
+
+    /**
+     * Places the values in the upper 4x4 of this GMatrix into 
+     * the matrix m1. 
+     * @param m1  The matrix that will hold the new values
+     */  
+    public final void get(Matrix4d m1) 
+    { 
+       if (nRow < 4 || nCol < 4) {
+           m1.setZero();
+           if (nCol > 0) {
+               if (nRow > 0) { 
+                   m1.m00 = values[0][0];
+                   if (nRow > 1) { 
+                       m1.m10 = values[1][0];
+                       if (nRow > 2) { 
+                           m1.m20 = values[2][0];
+                           if (nRow > 3) { 
+                               m1.m30 = values[3][0];
+                           }
+                       }
+                   }
+               }
+               if (nCol > 1) {
+                   if (nRow > 0) { 
+                       m1.m01 = values[0][1];
+                       if (nRow > 1) { 
+                           m1.m11 = values[1][1];
+                           if (nRow > 2) { 
+                               m1.m21 = values[2][1];
+                               if (nRow > 3) { 
+                                   m1.m31 = values[3][1];
+                               }
+                           }
+                       }
+                   }
+                   if (nCol > 2) {
+                       if (nRow > 0) { 
+                           m1.m02 = values[0][2];
+                           if (nRow > 1) {
+                               m1.m12 = values[1][2];
+                               if (nRow > 2) { 
+                                   m1.m22 = values[2][2];
+                                   if (nRow > 3) { 
+                                       m1.m32 = values[3][2];
+                                   }
+                               }
+                           }
+                       }
+                       if (nCol > 3) {
+                           if (nRow > 0) { 
+                               m1.m03 = values[0][3];
+                               if (nRow > 1) {
+                                   m1.m13 = values[1][3];
+                                   if (nRow > 2) { 
+                                       m1.m23 = values[2][3];
+                                       if (nRow > 3) { 
+                                           m1.m33 = values[3][3];
+                                       }
+                                   }
+                               }
+                           }
+                       }
+                   }
+               }
+           }
+        } else {
+           m1.m00 = values[0][0];
+           m1.m01 = values[0][1];
+           m1.m02 = values[0][2];
+           m1.m03 = values[0][3];
+
+           m1.m10 = values[1][0];
+           m1.m11 = values[1][1];
+           m1.m12 = values[1][2];
+           m1.m13 = values[1][3];
+
+           m1.m20 = values[2][0];
+           m1.m21 = values[2][1];
+           m1.m22 = values[2][2];
+           m1.m23 = values[2][3];
+
+           m1.m30 = values[3][0];
+           m1.m31 = values[3][1];
+           m1.m32 = values[3][2];
+           m1.m33 = values[3][3];
+       }
+
+    } 
+
+    /**
+     * Places the values in the upper 4x4 of this GMatrix into 
+     * the matrix m1. 
+     * @param m1  The matrix that will hold the new values
+     */  
+    public final void get(Matrix4f m1) 
+    { 
+
+       if (nRow < 4 || nCol < 4) {
+           m1.setZero();
+           if (nCol > 0) {
+               if (nRow > 0) {
+                   m1.m00 = (float)values[0][0];
+                   if (nRow > 1) {
+                       m1.m10 = (float)values[1][0];
+                       if (nRow > 2) {
+                           m1.m20 = (float)values[2][0];
+                           if (nRow > 3) {
+                               m1.m30 = (float)values[3][0];
+                           }  
+                       }
+                   }
+               }   
+               if (nCol > 1) {
+                   if (nRow > 0) {
+                       m1.m01 = (float)values[0][1];
+                       if (nRow > 1) {
+                           m1.m11 = (float)values[1][1];
+                           if (nRow > 2) {
+                               m1.m21 = (float)values[2][1];
+                               if (nRow > 3) {
+                                   m1.m31 = (float)values[3][1];
+                               }
+                           }   
+                       }   
+                   }
+                   if (nCol > 2) {
+                       if (nRow > 0) {
+                           m1.m02 = (float)values[0][2];
+                           if (nRow > 1) {
+                               m1.m12 = (float)values[1][2];
+                               if (nRow > 2) {
+                                   m1.m22 = (float)values[2][2];
+                                   if (nRow > 3) {
+                                       m1.m32 = (float)values[3][2];
+                                   }
+                               }   
+                           }   
+                       }   
+                       if (nCol > 3) {
+                           if (nRow > 0) {
+                               m1.m03 = (float)values[0][3];
+                               if (nRow > 1) {
+                                   m1.m13 = (float)values[1][3];
+                                   if (nRow > 2) {
+                                       m1.m23 = (float)values[2][3];
+                                       if (nRow > 3) {
+                                           m1.m33 = (float)values[3][3];
+                                       }
+                                   }   
+                               }   
+                           }   
+                       }  
+                   }  
+               }   
+           }   
+        } else {
+           m1.m00 = (float)values[0][0];
+           m1.m01 = (float)values[0][1];
+           m1.m02 = (float)values[0][2];
+           m1.m03 = (float)values[0][3];
+
+           m1.m10 = (float)values[1][0];
+           m1.m11 = (float)values[1][1];
+           m1.m12 = (float)values[1][2];
+           m1.m13 = (float)values[1][3];
+
+           m1.m20 = (float)values[2][0];
+           m1.m21 = (float)values[2][1];
+           m1.m22 = (float)values[2][2];
+           m1.m23 = (float)values[2][3];
+
+           m1.m30 = (float)values[3][0];
+           m1.m31 = (float)values[3][1];
+           m1.m32 = (float)values[3][2];
+           m1.m33 = (float)values[3][3];
+       }
+    } 
+
+    /**
+     * Places the values in the this GMatrix into the matrix m1;
+     * m1 should be at least as large as this GMatrix.
+     * @param m1  The matrix that will hold the new values
+     */  
+    public final void get(GMatrix m1) 
+    { 
+       int i, j, nc, nr;
+
+       if (nCol < m1.nCol)
+           nc = nCol;
+       else
+           nc = m1.nCol;
+
+       if (nRow < m1.nRow)
+           nr = nRow;
+       else
+           nr = m1.nRow;
+
+       for (i = 0; i < nr; i++) {
+           for (j = 0; j < nc; j++) {
+               m1.values[i][j] = values[i][j];
+           }
+       }
+       for (i = nr; i < m1.nRow; i++) {
+           for (j = 0; j < m1.nCol; j++) {
+               m1.values[i][j] = 0.0;
+           }
+       }
+       for (j = nc; j < m1.nCol; j++) {
+           for (i = 0; i < nr; i++) {
+               m1.values[i][j] = 0.0;
+           }
+       }
+    } 
+
+    /**
+     * Copy the values from the array into the specified row of this
+     * matrix.  
+     * @param row  the row of this matrix into which the array values 
+     *             will be copied.
+     * @param array  the source array
+     */
+    public final void setRow(int row, double[] array)
+    {
+       for (int i = 0; i < nCol; i++) {
+            values[row][i] = array[i];
+       }
+    }
+
+    /**
+     * Copy the values from the vector into the specified row of this
+     * matrix.
+     * @param row  the row of this matrix into which the array values
+     *             will be copied
+     * @param vector  the source vector
+     */  
+    public final void setRow(int row, GVector vector)
+    {
+       for(int i = 0; i < nCol; i++) {
+            values[row][i] = vector.values[i];
+       }
+    }
+
+    /**
+     * Copy the values from the array into the specified column of this
+     * matrix.   
+     * @param col  the column of this matrix into which the array values 
+     *             will be copied
+     * @param array  the source array
+     */ 
+    public final void setColumn(int col, double[] array)
+    {
+       for(int i = 0; i < nRow; i++) {
+            values[i][col] = array[i];
+       }
+    }
+
+    /**
+     * Copy the values from the vector into the specified column of this
+     * matrix.
+     * @param col  the column of this matrix into which the array values
+     *             will be copied
+     * @param vector  the source vector
+     */  
+    public final void setColumn(int col, GVector vector)
+    {
+       for(int i = 0; i < nRow; i++) {
+            values[i][col] = vector.values[i];
+       }
+
+    }
+
+    /**
+     *  Multiplies the transpose of matrix m1 times the transpose of matrix
+     *  m2, and places the result into this.
+     *  @param m1  The matrix on the left hand side of the multiplication
+     *  @param m2  The matrix on the right hand side of the multiplication
+     */  
+    public final void mulTransposeBoth(GMatrix m1, GMatrix m2)
+    {    
+       int i, j, k;
+
+       if (m1.nRow != m2.nCol || nRow != m1.nCol || nCol != m2.nRow)
+           throw new MismatchedSizeException
+               (VecMathI18N.getString("GMatrix14"));
+
+       if (m1 == this || m2 == this) {
+           double[][] tmp = new double[nRow][nCol];
+           for (i = 0; i < nRow; i++) { 
+               for (j = 0; j < nCol; j++) {
+                   tmp[i][j] = 0.0; 
+                   for (k = 0; k < m1.nRow; k++) {
+                       tmp[i][j] += m1.values[k][i]*m2.values[j][k]; 
+                   }
+               }  
+           }
+           values = tmp;
+       } else {
+           for (i = 0; i < nRow; i++) { 
+               for (j = 0; j < nCol; j++) {
+                   values[i][j] = 0.0; 
+                   for (k = 0; k < m1.nRow; k++) {
+                       values[i][j] += m1.values[k][i]*m2.values[j][k]; 
+                   }
+               }  
+           }  
+       }
+    }    
+
+    /**   
+     *  Multiplies matrix m1 times the transpose of matrix m2, and
+     *  places the result into this.
+     *  @param m1  The matrix on the left hand side of the multiplication
+     *  @param m2  The matrix on the right hand side of the multiplication
+     */  
+    public final void mulTransposeRight(GMatrix m1, GMatrix m2)
+    {    
+       int i, j, k;
+
+       if (m1.nCol != m2.nCol || nCol != m2.nRow || nRow != m1.nRow)
+           throw new MismatchedSizeException
+               (VecMathI18N.getString("GMatrix15"));
+
+       if (m1 == this || m2 == this) {
+           double[][] tmp = new double[nRow][nCol];
+           for (i = 0; i < nRow; i++) { 
+               for (j = 0; j < nCol; j++) {
+                   tmp[i][j] = 0.0; 
+                   for (k = 0; k < m1.nCol; k++) {
+                       tmp[i][j] += m1.values[i][k]*m2.values[j][k]; 
+                   }
+               }  
+           }
+           values = tmp;
+       } else {
+           for (i = 0; i < nRow; i++) { 
+               for (j = 0;j < nCol; j++) {
+                   values[i][j] = 0.0; 
+                   for (k = 0; k < m1.nCol; k++) {
+                       values[i][j] += m1.values[i][k]*m2.values[j][k]; 
+                   }
+               }  
+           }  
+       }
+
+    }    
+
+    /**   
+     *  Multiplies the transpose of matrix m1 times matrix m2, and
+     *  places the result into this.
+     *  @param m1  The matrix on the left hand side of the multiplication
+     *  @param m2  The matrix on the right hand side of the multiplication
+     */  
+    public final void mulTransposeLeft(GMatrix m1, GMatrix m2)
+    {
+       int i, j, k;
+
+       if (m1.nRow != m2.nRow || nCol != m2.nCol || nRow != m1.nCol)
+           throw new MismatchedSizeException
+               (VecMathI18N.getString("GMatrix16"));
+
+       if (m1 == this || m2 == this) {
+           double[][] tmp = new double[nRow][nCol];
+           for (i = 0; i < nRow; i++) { 
+               for (j = 0; j < nCol; j++) {
+                   tmp[i][j] = 0.0; 
+                   for (k = 0; k < m1.nRow; k++) {
+                       tmp[i][j] += m1.values[k][i]*m2.values[k][j]; 
+                   }
+               }  
+           }
+           values = tmp;
+       } else {
+           for (i = 0; i < nRow; i++) { 
+               for (j = 0; j < nCol; j++) {
+                   values[i][j] = 0.0; 
+                   for (k = 0; k < m1.nRow; k++) {
+                       values[i][j] += m1.values[k][i]*m2.values[k][j]; 
+                   }
+               }  
+           }  
+       }
+    }
+   
+
+    /**
+     * Transposes this matrix in place.
+     */
+    public final void transpose()
+    {
+        int i, j;
+
+        if (nRow != nCol) {
+           double[][] tmp;
+           i=nRow;
+           nRow = nCol;
+           nCol = i;
+           tmp = new double[nRow][nCol];
+           for (i = 0; i < nRow; i++) { 
+               for (j = 0; j < nCol; j++) {
+                   tmp[i][j] = values[j][i]; 
+               }  
+           }  
+           values = tmp;
+        } else {
+           double swap;
+           for (i = 0; i < nRow; i++) { 
+               for (j = 0; j < i; j++) {
+                   swap = values[i][j];
+                   values[i][j] = values[j][i];
+                   values[j][i] = swap;
+               }  
+           }  
+       }
+    }
+
+    /**
+     * Places the matrix values of the transpose of matrix m1 into this matrix.
+     * @param m1  the matrix to be transposed (but not modified)
+     */
+    public final void transpose(GMatrix m1)
+    {
+        int i, j;
+
+        if (nRow != m1.nCol || nCol != m1.nRow)
+           throw new MismatchedSizeException
+               (VecMathI18N.getString("GMatrix17"));
+
+        if (m1 != this) {
+           for (i = 0; i < nRow; i++) {
+               for (j = 0;j < nCol; j++) {
+                   values[i][j] = m1.values[j][i];
+               }
+           }
+       } else {
+           transpose();
+        }
+    }
+
+    /**
+     * Returns a string that contains the values of this GMatrix.
+     * @return the String representation
+     */  
+    public String toString() 
+    {
+       StringBuffer buffer = new StringBuffer(nRow*nCol*8);
+
+       int i, j;
+
+       for (i = 0; i < nRow; i++) {
+           for (j = 0; j < nCol; j++) {
+               buffer.append(values[i][j]).append(" ");
+           }
+           buffer.append("\n");
+       }
+
+       return buffer.toString();
+    }
+
+    private static void checkMatrix( GMatrix m) 
+    {
+       int i, j;
+
+       for (i = 0; i < m.nRow; i++) {
+           for (j = 0; j < m.nCol; j++) {
+               if (Math.abs(m.values[i][j]) < 0.0000000001) {
+                   System.out.print(" 0.0     ");
+               } else {
+                   System.out.print(" " + m.values[i][j]);
+               }
+           }
+           System.out.print("\n");
+       }
+    }
+
+
+    /**
+     * Returns a hash code value based on the data values in this
+     * object.  Two different GMatrix objects with identical data
+     * values (i.e., GMatrix.equals returns true) will return the
+     * same hash number.  Two GMatrix objects with different data
+     * members may return the same hash value, although this is not
+     * likely.
+     * @return the integer hash code value
+     */
+    public int hashCode() {
+       long bits = 1L;
+
+       bits = 31L * bits + (long)nRow;
+       bits = 31L * bits + (long)nCol;
+
+       for (int i = 0; i < nRow; i++) {
+           for (int j = 0; j < nCol; j++) {
+               bits = 31L * bits + VecMathUtil.doubleToLongBits(values[i][j]);
+           }
+       }
+
+       return (int) (bits ^ (bits >> 32));
+    } 
+
+
+    /**
+     * Returns true if all of the data members of GMatrix m1 are
+     * equal to the corresponding data members in this GMatrix.
+     * @param m1  The matrix with which the comparison is made.
+     * @return  true or false
+     */  
+    public boolean equals(GMatrix m1)
+    {
+       try { 
+           int i, j;
+
+           if (nRow != m1.nRow || nCol != m1.nCol)
+               return false;
+
+           for (i = 0;i < nRow; i++) {
+               for (j = 0; j < nCol; j++) {
+                   if (values[i][j] != m1.values[i][j])
+                       return false;
+               }
+           }
+           return true;
+       }  
+       catch (NullPointerException e2) {
+           return false;
+       }
+    }
+
+    /**
+     * Returns true if the Object o1 is of type GMatrix and all of the
+     * data members of o1 are equal to the corresponding data members in
+     * this GMatrix.
+     * @param o1  The object with which the comparison is made.
+     * @return  true or false
+     */  
+    public boolean equals(Object o1)
+    {
+        try { 
+           GMatrix m2 = (GMatrix) o1;
+           int i, j;
+           if (nRow != m2.nRow || nCol != m2.nCol)
+               return false;
+
+           for (i = 0; i < nRow; i++) {
+                for (j = 0; j < nCol; j++) {
+                   if (values[i][j] != m2.values[i][j])
+                       return false;
+                }
+           }
+           return true;
+        }
+        catch (ClassCastException e1) {
+           return false;
+       }
+        catch (NullPointerException e2) {
+           return false;
+       }
+    }
+
+    /**
+     * @deprecated Use epsilonEquals(GMatrix, double) instead
+     */
+    public boolean epsilonEquals(GMatrix m1, float epsilon) {
+       return epsilonEquals(m1, (double)epsilon);
+    }
+
+    /**
+     * Returns true if the L-infinite distance between this matrix
+     * and matrix m1 is less than or equal to the epsilon parameter,
+     * otherwise returns false.  The L-infinite
+     * distance is equal to
+     * MAX[i=0,1,2, . . .n ; j=0,1,2, . . .n ; abs(this.m(i,j) - m1.m(i,j)]
+     * @param m1  The matrix to be compared to this matrix
+     * @param epsilon  the threshold value
+     */  
+    public boolean epsilonEquals(GMatrix m1, double epsilon)
+    {
+       int i, j;
+       double diff;
+       if (nRow != m1.nRow || nCol != m1.nCol)
+           return false;
+
+        for (i = 0; i < nRow; i++) {
+           for (j = 0; j < nCol; j++) {
+               diff = values[i][j] - m1.values[i][j];
+               if ((diff < 0 ? -diff : diff) > epsilon)
+                   return false;
+           }
+        }
+        return true;
+    }
+
+    /**
+     * Returns the trace of this matrix.
+     * @return  the trace of this matrix
+     */
+    public final double trace()
+    {
+       int i, l;
+       double t;
+
+       if (nRow < nCol) 
+           l = nRow;
+       else 
+           l = nCol;
+
+       t = 0.0;
+       for (i = 0; i < l; i++) {
+           t += values[i][i];
+       }
+       return t;
+    }
+
+    /**
+     *  Finds the singular value decomposition (SVD) of this matrix 
+     *  such that this = U*W*transpose(V); and returns the rank of
+     *  this matrix; the values of U,W,V are all overwritten.  Note 
+     *  that the matrix V is output as V, and
+     *  not transpose(V).  If this matrix is mxn, then U is mxm, W 
+     *  is a diagonal matrix that is mxn, and V is nxn.  Using the
+     *  notation W = diag(w), then the inverse of this matrix is:
+     *  inverse(this) = V*diag(1/w)*tranpose(U), where diag(1/w)
+     *  is the same matrix as W except that the reciprocal of each 
+     *  of the diagonal components is used.
+     *  @param U  The computed U matrix in the equation this = U*W*transpose(V)
+     *  @param W  The computed W matrix in the equation this = U*W*transpose(V)
+     *  @param V  The computed V matrix in the equation this = U*W*transpose(V)
+     *  @return  The rank of this matrix.
+     */
+    public final int SVD(GMatrix U, GMatrix W, GMatrix V)
+    {
+       // check for consistancy in dimensions 
+       if (nCol != V.nCol || nCol != V.nRow) {
+           throw new MismatchedSizeException
+               (VecMathI18N.getString("GMatrix18"));
+       }
+
+       if (nRow != U.nRow || nRow != U.nCol) {
+           throw new MismatchedSizeException
+               (VecMathI18N.getString("GMatrix25"));
+       }
+
+       if (nRow != W.nRow || nCol != W.nCol) {
+           throw new MismatchedSizeException
+               (VecMathI18N.getString("GMatrix26"));
+       }
+
+       // Fix ArrayIndexOutOfBounds for 2x2 matrices, which partially
+       // addresses bug 4348562 for J3D 1.2.1.
+       //
+       // Does *not* fix the following problems reported in 4348562,
+       // which will wait for J3D 1.3:
+       //
+       //   1) no output of W
+       //   2) wrong transposition of U
+       //   3) wrong results for 4x4 matrices
+       //   4) slow performance
+       if (nRow == 2 && nCol == 2) {
+           if (values[1][0] == 0.0) {
+               U.setIdentity();
+               V.setIdentity();
+
+               if (values[0][1] == 0.0) {
+                   return 2;
+               }
+
+               double[] sinl = new double[1];
+               double[] sinr = new double[1];
+               double[] cosl = new double[1];
+               double[] cosr = new double[1];
+               double[] single_values = new double[2];
+
+               single_values[0] = values[0][0];
+               single_values[1] = values[1][1];
+
+               compute_2X2(values[0][0], values[0][1], values[1][1],
+                           single_values, sinl, cosl, sinr, cosr, 0);
+
+               update_u(0, U, cosl, sinl);
+               update_v(0, V, cosr, sinr);
+
+               return 2;
+           }
+           // else call computeSVD() and check for 2x2 there
+       }
+
+       return computeSVD(this, U, W, V);
+    }
+
+    /**
+     * LU Decomposition: this matrix must be a square matrix and the
+     * LU GMatrix parameter must be the same size as this matrix. 
+     * The matrix LU will be overwritten as the combination of a 
+     * lower diagonal and upper diagonal matrix decompostion of this
+     * matrix; the diagonal 
+     * elements of L (unity) are not stored.  The GVector parameter
+     * records the row permutation effected by the partial pivoting,
+     * and is used as a parameter to the GVector method LUDBackSolve
+     * to solve sets of linear equations.
+     * This method returns +/- 1 depending on whether the number
+     * of row interchanges was even or odd, respectively.
+     * @param LU  The matrix into which the lower and upper decompositions
+     * will be placed.
+     * @param permutation  The row permutation effected by the partial
+     * pivoting
+     * @return  +-1 depending on whether the number of row interchanges
+     * was even or odd respectively
+     */
+    public final int LUD(GMatrix LU, GVector permutation)
+    {
+        int size = LU.nRow*LU.nCol;
+        double[] temp = new double[size];
+       int[] even_row_exchange = new int[1];
+       int[] row_perm = new int[LU.nRow];
+       int i, j;
+
+        if (nRow != nCol) {
+           throw new MismatchedSizeException
+               (VecMathI18N.getString("GMatrix19"));
+        }
+
+        if (nRow != LU.nRow) {
+           throw new MismatchedSizeException
+               (VecMathI18N.getString("GMatrix27"));
+        }
+
+        if (nCol != LU.nCol) {
+           throw new MismatchedSizeException
+               (VecMathI18N.getString("GMatrix27"));
+        }
+
+        if (LU.nRow != permutation.getSize()) {
+           throw new MismatchedSizeException
+               (VecMathI18N.getString("GMatrix20"));
+        }
+
+       for (i = 0; i < nRow; i++) {
+           for (j = 0; j < nCol; j++) {
+               temp[i*nCol+j] = values[i][j];
+           }
+        }
+
+        // Calculate LU decomposition: Is the matrix singular? 
+        if (!luDecomposition(LU.nRow, temp, row_perm, even_row_exchange)) {
+            // Matrix has no inverse 
+            throw new SingularMatrixException
+               (VecMathI18N.getString("GMatrix21"));
+        }
+
+       for (i = 0; i < nRow; i++) {
+           for (j = 0; j < nCol; j++) {
+               LU.values[i][j] = temp[i*nCol+j];
+           }
+        }
+
+       for (i = 0; i < LU.nRow; i++){
+           permutation.values[i] = (double)row_perm[i];
+        }
+
+        return even_row_exchange[0];
+    }
+
+    /** 
+     *  Sets this matrix to a uniform scale matrix; all of the  
+     *  values are reset. 
+     *  @param scale  The new scale value 
+     */   
+    public final void setScale(double scale) 
+    { 
+       int i, j, l;
+
+       if (nRow < nCol) 
+           l = nRow;
+       else 
+           l = nCol;
+
+       for (i = 0; i < nRow; i++) {
+           for (j = 0; j < nCol; j++) {
+               values[i][j] = 0.0;
+           }
+       }
+
+       for (i = 0; i < l; i++) {
+           values[i][i] = scale;
+       }
+    } 
+
+    /**
+     * General invert routine.  Inverts m1 and places the result in "this".
+     * Note that this routine handles both the "this" version and the
+     * non-"this" version.
+     *
+     * Also note that since this routine is slow anyway, we won't worry
+     * about allocating a little bit of garbage.
+     */
+    final void invertGeneral(GMatrix  m1) {
+        int size = m1.nRow*m1.nCol;
+       double temp[] = new double[size];
+       double result[] = new double[size];
+       int row_perm[] = new int[m1.nRow];
+       int[] even_row_exchange = new int[1];
+       int i, j;
+
+       // Use LU decomposition and backsubstitution code specifically
+       // for floating-point nxn matrices.
+       if (m1.nRow != m1.nCol) {
+           // Matrix is either under or over determined 
+           throw new MismatchedSizeException
+               (VecMathI18N.getString("GMatrix22"));
+       }
+
+       // Copy source matrix to temp 
+       for (i = 0; i < nRow; i++) {
+           for (j = 0; j < nCol; j++) {
+               temp[i*nCol+j] = m1.values[i][j];
+           }
+       }
+
+       // Calculate LU decomposition: Is the matrix singular? 
+       if (!luDecomposition(m1.nRow, temp, row_perm, even_row_exchange)) {
+           // Matrix has no inverse 
+           throw new SingularMatrixException
+               (VecMathI18N.getString("GMatrix21"));
+       }
+
+       // Perform back substitution on the identity matrix 
+        for (i = 0; i < size; i++)
+           result[i] = 0.0;
+
+        for (i = 0; i < nCol; i++)
+           result[i+i*nCol] = 1.0;
+
+       luBacksubstitution(m1.nRow, temp, row_perm, result);
+
+       for (i = 0; i < nRow; i++) {
+           for (j = 0; j < nCol; j++) {
+               values[i][j] =  result[i*nCol+j];
+           }
+        }
+    }
+
+    /**
+     * Given a nxn array "matrix0", this function replaces it with the 
+     * LU decomposition of a row-wise permutation of itself.  The input 
+     * parameters are "matrix0" and "dim".  The array "matrix0" is also 
+     * an output parameter.  The vector "row_perm[]" is an output 
+     * parameter that contains the row permutations resulting from partial 
+     * pivoting.  The output parameter "even_row_xchg" is 1 when the 
+     * number of row exchanges is even, or -1 otherwise.  Assumes data 
+     * type is always double.
+     *
+     * @return true if the matrix is nonsingular, or false otherwise.
+     */
+    //
+    // Reference: Press, Flannery, Teukolsky, Vetterling, 
+    //       _Numerical_Recipes_in_C_, Cambridge University Press, 
+    //       1988, pp 40-45.
+    //
+    static boolean luDecomposition(int dim, double[] matrix0,
+                                  int[] row_perm, int[] even_row_xchg) {
+
+       double row_scale[] = new double[dim];
+
+       // Determine implicit scaling information by looping over rows 
+       int i, j;
+       int ptr, rs, mtx;
+       double big, temp;
+
+       ptr = 0;
+       rs = 0;
+       even_row_xchg[0] = 1;
+
+       // For each row ... 
+       i = dim;
+       while (i-- != 0) {
+           big = 0.0;
+
+           // For each column, find the largest element in the row 
+           j = dim;
+           while (j-- != 0) {
+               temp = matrix0[ptr++];
+               temp = Math.abs(temp);
+               if (temp > big) {
+                   big = temp;
+               }
+           }
+
+           // Is the matrix singular? 
+           if (big == 0.0) {
+               return false;
+           }
+           row_scale[rs++] = 1.0 / big;
+       }
+
+       // For all columns, execute Crout's method 
+       mtx = 0;
+       for (j = 0; j < dim; j++) {
+           int imax, k;
+           int target, p1, p2;
+           double sum;
+
+           // Determine elements of upper diagonal matrix U 
+           for (i = 0; i < j; i++) {
+               target = mtx + (dim*i) + j;
+               sum = matrix0[target];
+               k = i;
+               p1 = mtx + (dim*i);
+               p2 = mtx + j;
+               while (k-- != 0) {
+                   sum -= matrix0[p1] * matrix0[p2];
+                   p1++;
+                   p2 += dim;
+               }
+               matrix0[target] = sum;
+           }
+
+           // Search for largest pivot element and calculate
+           // intermediate elements of lower diagonal matrix L.
+           big = 0.0;
+           imax = -1;
+           for (i = j; i < dim; i++) {
+               target = mtx + (dim*i) + j;
+               sum = matrix0[target];
+               k = j;
+               p1 = mtx + (dim*i);
+               p2 = mtx + j;
+               while (k-- != 0) {
+                   sum -= matrix0[p1] * matrix0[p2];
+                   p1++;
+                   p2 += dim;
+               }
+               matrix0[target] = sum;
+
+               // Is this the best pivot so far? 
+               if ((temp = row_scale[i] * Math.abs(sum)) >= big) {
+                   big = temp;
+                   imax = i;
+               }
+           }
+
+           if (imax < 0) {
+               throw new RuntimeException(VecMathI18N.getString("GMatrix24"));
+           }
+
+           // Is a row exchange necessary? 
+           if (j != imax) {
+               // Yes: exchange rows 
+               k = dim;
+               p1 = mtx + (dim*imax);
+               p2 = mtx + (dim*j);
+               while (k-- != 0) {
+                   temp = matrix0[p1];
+                   matrix0[p1++] = matrix0[p2];
+                   matrix0[p2++] = temp;
+               }
+
+               // Record change in scale factor 
+               row_scale[imax] = row_scale[j];
+               even_row_xchg[0] = -even_row_xchg[0]; // change exchange parity
+           }
+
+           // Record row permutation 
+           row_perm[j] = imax;
+
+           // Is the matrix singular 
+           if (matrix0[(mtx + (dim*j) + j)] == 0.0) {
+               return false;
+           }
+
+           // Divide elements of lower diagonal matrix L by pivot 
+           if (j != (dim-1)) {
+               temp = 1.0 / (matrix0[(mtx + (dim*j) + j)]);
+               target = mtx + (dim*(j+1)) + j;
+               i = (dim-1) - j;
+               while (i-- != 0) {
+                   matrix0[target] *= temp;
+                   target += dim;
+               }
+           }
+
+       }
+
+       return true;
+    }
+
+    /**
+     * Solves a set of linear equations.  The input parameters "matrix1",
+     * and "row_perm" come from luDecompostion and do not change
+     * here.  The parameter "matrix2" is a set of column vectors assembled
+     * into a nxn matrix of floating-point values.  The procedure takes each
+     * column of "matrix2" in turn and treats it as the right-hand side of the
+     * matrix equation Ax = LUx = b.  The solution vector replaces the
+     * original column of the matrix.
+     *
+     * If "matrix2" is the identity matrix, the procedure replaces its contents
+     * with the inverse of the matrix from which "matrix1" was originally
+     * derived.
+     */
+    //
+    // Reference: Press, Flannery, Teukolsky, Vetterling, 
+    //       _Numerical_Recipes_in_C_, Cambridge University Press, 
+    //       1988, pp 44-45.
+    //
+    static void luBacksubstitution(int dim, double[] matrix1,
+                                  int[] row_perm,
+                                  double[] matrix2) {
+
+       int i, ii, ip, j, k;
+       int rp;
+       int cv, rv, ri;
+       double tt;
+       
+       // rp = row_perm;
+       rp = 0;
+
+       // For each column vector of matrix2 ... 
+       for (k = 0; k < dim; k++) {
+           // cv = &(matrix2[0][k]);
+           cv = k;
+           ii = -1;
+
+           // Forward substitution 
+           for (i = 0; i < dim; i++) {
+               double sum;
+
+               ip = row_perm[rp+i];
+               sum = matrix2[cv+dim*ip];
+               matrix2[cv+dim*ip] = matrix2[cv+dim*i];
+               if (ii >= 0) {
+                   // rv = &(matrix1[i][0]);
+                   rv = i*dim;
+                   for (j = ii; j <= i-1; j++) {
+                       sum -= matrix1[rv+j] * matrix2[cv+dim*j];
+                   }
+               }
+               else if (sum != 0.0) {
+                   ii = i;
+               }
+               matrix2[cv+dim*i] = sum;
+           }
+
+           // Backsubstitution 
+           for (i = 0; i < dim; i++) {
+               ri = (dim-1-i);
+               rv = dim*(ri);
+               tt = 0.0;
+               for(j=1;j<=i;j++) {
+                   tt += matrix1[rv+dim-j] * matrix2[cv+dim*(dim-j)];    
+               }
+               matrix2[cv+dim*ri]= (matrix2[cv+dim*ri] - tt) / matrix1[rv+ri];
+            }
+       }
+    }
+
+    static int computeSVD(GMatrix mat, GMatrix U, GMatrix W, GMatrix V) {
+       int i, j, k;
+       int nr, nc, si;
+
+       int converged, rank;
+       double cs, sn, r, mag,scale, t;
+       int eLength, sLength, vecLength;
+
+       GMatrix tmp = new GMatrix(mat.nRow, mat.nCol);
+       GMatrix u = new GMatrix(mat.nRow, mat.nCol);
+       GMatrix v = new GMatrix(mat.nRow, mat.nCol);
+       GMatrix m = new GMatrix(mat);
+
+       // compute the number of singular values
+       if (m.nRow >= m.nCol) {
+           sLength = m.nCol;
+           eLength = m.nCol-1;
+       }else {
+           sLength = m.nRow;
+           eLength = m.nRow;
+       }
+
+       if (m.nRow > m.nCol) 
+           vecLength = m.nRow;
+       else
+           vecLength = m.nCol;
+
+       double[] vec = new double[vecLength];
+       double[] single_values = new double[sLength];
+       double[] e = new double[eLength];
+
+       if(debug) {
+           System.out.println("input to compute_svd = \n"+m.toString());
+       }
+
+       rank = 0;
+
+       U.setIdentity();
+       V.setIdentity();
+
+       nr = m.nRow;
+       nc = m.nCol;
+
+       // householder reduction 
+       for (si = 0; si < sLength; si++) {
+           // for each singular value
+
+           if (nr > 1) {
+               // zero out column
+               if (debug)
+                   System.out.println
+                       ("*********************** U ***********************\n");
+
+               // compute reflector
+               mag = 0.0;
+               for (i = 0; i < nr; i++) {
+                   mag += m.values[i+si][si] * m.values[i+si][si];
+                   if (debug)
+                       System.out.println
+                           ("mag = " + mag + " matrix.dot = " +
+                            m.values[i+si][si] * m.values[i+si][si]);
+               }
+
+               mag = Math.sqrt(mag);
+               if (m.values[si][si] == 0.0) {
+                   vec[0] = mag;
+               } else {
+                   vec[0] = m.values[si][si] + d_sign(mag, m.values[si][si]);
+               }
+
+               for (i = 1; i < nr; i++) {
+                   vec[i] =  m.values[si+i][si];
+               }
+
+               scale = 0.0;
+               for (i = 0; i < nr; i++) {
+                   if (debug)
+                       System.out.println("vec["+i+"]="+vec[i]);
+
+                   scale += vec[i]*vec[i];
+               }
+
+               scale = 2.0/scale;
+               if (debug)
+                   System.out.println("scale = "+scale);
+
+               for (j = si; j < m.nRow; j++) {
+                   for (k = si; k < m.nRow; k++) {
+                       u.values[j][k] = -scale * vec[j-si]*vec[k-si];
+                   }
+               }
+
+               for (i = si; i < m.nRow; i++){
+                   u.values[i][i] +=  1.0;
+               }
+
+               // compute s
+               t = 0.0;
+               for (i = si; i < m.nRow; i++){
+                   t += u.values[si][i] * m.values[i][si];
+               }
+               m.values[si][si] = t;
+
+               // apply reflector
+               for (j = si; j < m.nRow; j++) {
+                   for (k = si+1; k < m.nCol; k++) {
+                       tmp.values[j][k] = 0.0;
+                       for (i = si; i < m.nCol; i++) {
+                           tmp.values[j][k] += u.values[j][i] * m.values[i][k];
+                       }
+                   }
+               }
+
+               for (j = si; j < m.nRow; j++) {
+                   for (k = si+1; k < m.nCol; k++) {
+                       m.values[j][k] = tmp.values[j][k];
+                   }
+               }
+
+               if (debug) {
+                   System.out.println("U =\n" + U.toString());
+                   System.out.println("u =\n" + u.toString());
+               }
+
+               // update U matrix
+               for (j = si; j < m.nRow; j++) {
+                   for (k = 0; k < m.nCol; k++) {
+                       tmp.values[j][k] = 0.0; 
+                       for (i = si; i < m.nCol; i++) {
+                           tmp.values[j][k] += u.values[j][i] * U.values[i][k];
+                       }
+                   }
+               }
+
+               for (j = si; j < m.nRow; j++) {
+                   for (k = 0; k < m.nCol; k++) {
+                       U.values[j][k] = tmp.values[j][k];
+                   }
+               }
+
+               if (debug) {
+                   System.out.println("single_values["+si+"] =\n" +
+                                      single_values[si]);
+                   System.out.println("m =\n" + m.toString());
+                   System.out.println("U =\n" + U.toString());
+               }
+
+               nr--;
+           }
+
+           if( nc > 2 ) {
+               // zero out row
+               if (debug)
+                   System.out.println
+                       ("*********************** V ***********************\n");
+
+               mag = 0.0;
+               for (i = 1; i < nc; i++){
+                   mag += m.values[si][si+i] * m.values[si][si+i];
+               }
+
+               if (debug)
+                   System.out.println("mag = " + mag);
+
+               // generate the reflection vector, compute the first entry and
+               // copy the rest from the row to be zeroed
+               mag = Math.sqrt(mag);
+               if (m.values[si][si+1] == 0.0) {
+                   vec[0] = mag;
+               } else {
+                   vec[0] = m.values[si][si+1] +
+                       d_sign(mag, m.values[si][si+1]);
+               }
+
+               for (i = 1; i < nc - 1; i++){
+                   vec[i] =  m.values[si][si+i+1];
+               }
+
+               // use reflection vector to compute v matrix
+               scale = 0.0;
+               for (i = 0; i < nc - 1; i++){
+                   if( debug )System.out.println("vec["+i+"]="+vec[i]);
+                   scale += vec[i]*vec[i];
+               }
+
+               scale = 2.0/scale;
+               if (debug)
+                   System.out.println("scale = "+scale);
+
+               for (j = si + 1; j < nc; j++) {
+                   for (k = si+1; k < m.nCol; k++) {
+                       v.values[j][k] = -scale * vec[j-si-1]*vec[k-si-1];
+                   }
+               }
+
+               for (i = si + 1; i < m.nCol; i++){
+                   v.values[i][i] +=  1.0;
+               }
+
+               t=0.0;
+               for (i = si; i < m.nCol; i++){
+                   t += v.values[i][si+1] * m.values[si][i];
+               }
+               m.values[si][si+1]=t;
+
+               // apply reflector
+               for (j = si + 1; j < m.nRow; j++) {
+                   for (k = si + 1; k < m.nCol; k++) {
+                       tmp.values[j][k] = 0.0;
+                       for (i = si + 1; i < m.nCol; i++) {
+                           tmp.values[j][k] += v.values[i][k] * m.values[j][i];
+                       }
+                   }
+               }
+
+               for (j = si + 1; j < m.nRow; j++) {
+                   for (k = si + 1; k < m.nCol; k++) {
+                       m.values[j][k] = tmp.values[j][k];
+                   }
+               }
+
+               if (debug) {
+                   System.out.println("V =\n" + V.toString());
+                   System.out.println("v =\n" + v.toString());
+                   System.out.println("tmp =\n" + tmp.toString());
+               }
+
+               // update V matrix
+               for (j = 0; j < m.nRow; j++) {
+                   for (k = si + 1; k < m.nCol; k++) {
+                       tmp.values[j][k] = 0.0; 
+                       for (i = si + 1; i < m.nCol; i++) {
+                           tmp.values[j][k] += v.values[i][k] * V.values[j][i];
+                       }
+                   }
+               }
+
+               if (debug)
+                   System.out.println("tmp =\n" + tmp.toString());
+
+               for (j = 0;j < m.nRow; j++) {
+                   for (k = si + 1; k < m.nCol; k++) {
+                       V.values[j][k] = tmp.values[j][k];
+                   }
+               }
+
+               if (debug) {
+                   System.out.println("m =\n" + m.toString());
+                   System.out.println("V =\n" + V.toString());
+               }
+
+               nc--;
+           }
+       }
+
+       for (i = 0; i < sLength; i++){
+           single_values[i] = m.values[i][i];
+       }
+
+       for (i = 0; i < eLength; i++){
+           e[i] = m.values[i][i+1];
+       }
+
+       // Fix ArrayIndexOutOfBounds for 2x2 matrices, which partially
+       // addresses bug 4348562 for J3D 1.2.1.
+       //
+       // Does *not* fix the following problems reported in 4348562,
+       // which will wait for J3D 1.3:
+       //
+       //   1) no output of W
+       //   2) wrong transposition of U
+       //   3) wrong results for 4x4 matrices
+       //   4) slow performance
+       if (m.nRow == 2 && m.nCol == 2) {
+           double[] cosl = new double[1];
+           double[] cosr = new double[1];
+           double[] sinl = new double[1];
+           double[] sinr = new double[1];
+
+           compute_2X2(single_values[0], e[0], single_values[1],
+                       single_values, sinl, cosl, sinr, cosr, 0);
+
+           update_u(0, U, cosl, sinl);
+           update_v(0, V, cosr, sinr);
+
+           return 2;
+       }
+
+       // compute_qr causes ArrayIndexOutOfBounds for 2x2 matrices
+       compute_qr (0, e.length-1, single_values, e, U, V); 
+
+       // compute rank = number of non zero singular values
+       rank = single_values.length;
+  
+       // sort by order of size of single values
+       // and check for zero's
+       return rank;
+    }
+
+    static void compute_qr(int start, int end, double[] s, double[] e,
+                          GMatrix u, GMatrix v) {
+
+       int i, j, k, n, sl;
+       boolean converged;
+       double shift, r, utemp, vtemp, f, g;
+       double[] cosl = new double[1];
+       double[] cosr = new double[1];
+       double[] sinl = new double[1];
+       double[] sinr = new double[1];
+       GMatrix m = new GMatrix(u.nCol, v.nRow);
+       final int MAX_INTERATIONS = 2;
+       final double CONVERGE_TOL = 4.89E-15;
+
+       if (debug) {
+           System.out.println("start =" + start);
+           System.out.println("s =\n");
+           for(i=0;i<s.length;i++) {
+               System.out.println(s[i]);
+           }
+
+           System.out.println("\nes =\n");
+           for (i = 0; i < e.length; i++) {
+               System.out.println(e[i]);
+           }
+
+           for (i = 0; i < s.length; i++) {
+               m.values[i][i] = s[i];
+           }
+
+           for (i = 0; i < e.length; i++) {
+               m.values[i][i+1] = e[i];
+           }
+           System.out.println("\nm =\n" + m.toString());
+       }
+
+       double c_b48 =  1.0;
+       double c_b71 = -1.0;
+       converged = false;
+
+       if (debug)
+           print_svd(s, e, u, v);
+
+       f = 0.0;
+       g = 0.0;
+   
+       for (k = 0; k < MAX_INTERATIONS && !converged;k++) {
+           for (i = start; i <= end; i++) {
+
+               // if at start of iterfaction compute shift 
+               if (i == start) { 
+                   if (e.length == s.length)
+                       sl = end;
+                   else
+                       sl = end + 1;
+
+                   shift = compute_shift(s[sl-1], e[end], s[sl]);
+
+                   f = (Math.abs(s[i]) - shift) *
+                       (d_sign(c_b48, s[i]) + shift/s[i]);
+                   g = e[i];
+               } 
+
+               r = compute_rot(f, g, sinr, cosr);
+               if (i != start)
+                   e[i-1] = r;
+
+               f = cosr[0] * s[i] + sinr[0] * e[i];
+               e[i] = cosr[0] * e[i] - sinr[0] * s[i];
+               g = sinr[0] * s[i+1];
+               s[i+1] = cosr[0] * s[i+1];
+
+               // if (debug) print_se(s,e);
+               update_v (i, v, cosr, sinr);
+               if (debug)
+                   print_m(m,u,v);
+
+               r = compute_rot(f, g, sinl, cosl);
+               s[i] = r;
+               f = cosl[0] * e[i] + sinl[0] * s[i+1];
+               s[i+1] = cosl[0] * s[i+1] - sinl[0] * e[i];
+
+               if( i < end) {
+                   // if not last
+                   g = sinl[0] * e[i+1];
+                   e[i+1] =  cosl[0] * e[i+1];
+               }
+               //if (debug) print_se(s,e);
+
+               update_u(i, u, cosl, sinl);
+               if (debug)
+                   print_m(m,u,v);
+           }
+
+           // if extra off diagonal perform one more right side rotation
+           if (s.length == e.length) {
+               r = compute_rot(f, g, sinr, cosr);
+               f = cosr[0] * s[i] + sinr[0] * e[i];
+               e[i] = cosr[0] * e[i] - sinr[0] * s[i];
+               s[i+1] = cosr[0] * s[i+1];
+
+               update_v(i, v, cosr, sinr);
+               if (debug)
+                   print_m(m,u,v);
+           } 
+
+           if (debug) {
+               System.out.println
+                   ("\n*********************** iteration #" + k +
+                    " ***********************\n");
+               print_svd(s, e, u, v);
+           }
+
+           // check for convergence on off diagonals and reduce 
+           while ((end-start > 1) && (Math.abs(e[end]) < CONVERGE_TOL)) { 
+               end--;
+           }
+
+           // check if need to split
+           for (n = end - 2; n > start; n--) {
+               if (Math.abs(e[n]) < CONVERGE_TOL) {     // split
+                   compute_qr(n + 1, end, s, e, u, v);  // do lower matrix
+                   end = n - 1;                         // do upper matrix
+
+                   // check for convergence on off diagonals and reduce 
+                   while ((end - start > 1) &&
+                          (Math.abs(e[end]) < CONVERGE_TOL)) { 
+                       end--;
+                   }
+               }
+           }
+
+           if (debug)
+               System.out.println("start = " + start);
+
+           if ((end - start <= 1) && (Math.abs(e[start+1]) < CONVERGE_TOL)) {
+               converged = true;
+           } else {
+               // check if zero on the diagonal
+           }
+
+       }
+
+       if (debug)
+           System.out.println("\n****call compute_2X2 ********************\n");
+
+       if (Math.abs(e[1]) < CONVERGE_TOL) {
+           compute_2X2(s[start], e[start], s[start+1], s,
+                       sinl, cosl, sinr, cosr, 0);
+           e[start] = 0.0;
+           e[start+1] = 0.0;
+       } else {
+       }
+
+       i = start;
+       update_u(i, u, cosl, sinl);
+       update_v(i, v, cosr, sinr);
+
+       if(debug) {
+           System.out.println
+               ("\n*******after call compute_2X2 **********************\n");
+           print_svd(s, e, u, v);
+       }
+
+       return;
+    }
+
+    private static void print_se(double[] s, double[] e) {
+       System.out.println("\ns =" + s[0] + " " + s[1] + " " + s[2]);
+       System.out.println("e =" + e[0] + " " + e[1]);
+    }
+
+    private static void update_v(int index, GMatrix v,
+                                double[] cosr, double[] sinr) {
+       int j;
+       double vtemp;
+
+       for (j = 0; j < v.nRow; j++) {
+           vtemp = v.values[j][index];
+           v.values[j][index] =
+               cosr[0]*vtemp + sinr[0]*v.values[j][index+1];
+           v.values[j][index+1] =
+              -sinr[0]*vtemp + cosr[0]*v.values[j][index+1];
+       }
+    }
+
+    private static void chase_up(double[] s, double[] e, int k, GMatrix v) {
+       double f, g, r;
+       double[] cosr = new double[1];
+       double[] sinr = new double[1];
+       int i;
+       GMatrix t = new GMatrix(v.nRow, v.nCol);
+       GMatrix m = new GMatrix(v.nRow, v.nCol);
+
+       if (debug) {
+           m.setIdentity();
+           for (i = 0; i < s.length; i++) {
+               m.values[i][i] = s[i];
+           }
+           for (i = 0; i < e.length; i++) {
+               m.values[i][i+1] = e[i];
+           }
+       }
+
+       f = e[k];
+       g = s[k];
+
+       for (i = k; i > 0; i--) {
+           r = compute_rot(f, g, sinr, cosr);
+           f = -e[i-1] * sinr[0];
+           g = s[i-1];
+           s[i] = r;
+           e[i-1] = e[i-1] * cosr[0];
+           update_v_split(i, k+1, v, cosr, sinr, t, m);
+       }
+
+       s[i+1] = compute_rot(f, g, sinr, cosr);
+       update_v_split(i, k+1, v, cosr, sinr, t, m);
+    }
+    
+    private static void chase_across(double[] s, double[] e, int k, GMatrix u) {
+       double f, g, r;
+       double[] cosl = new double[1];
+       double[] sinl = new double[1];
+       int i;
+       GMatrix t = new GMatrix(u.nRow, u.nCol);
+       GMatrix m = new GMatrix(u.nRow, u.nCol);
+
+       if (debug) {
+           m.setIdentity();
+           for (i = 0; i < s.length; i++) {
+               m.values[i][i] = s[i];
+           }
+           for (i = 0; i < e.length; i++) {
+               m.values[i][i+1] = e[i];
+           }
+       }
+
+       g = e[k];
+       f = s[k+1];
+
+       for (i = k; i < u.nCol-2; i++){
+           r = compute_rot(f, g, sinl, cosl);
+           g = -e[i+1] * sinl[0];
+           f = s[i+2];
+           s[i+1] = r;
+           e[i+1] = e[i+1] * cosl[0];
+           update_u_split(k, i + 1, u, cosl, sinl, t, m);
+       }
+
+       s[i+1] = compute_rot(f, g, sinl, cosl);
+       update_u_split(k, i + 1, u, cosl, sinl, t, m);
+    }
+
+    private static void update_v_split(int topr, int bottomr, GMatrix v,
+                                      double[] cosr, double[] sinr,
+                                      GMatrix t, GMatrix m) {
+       int j;
+       double vtemp;
+
+       for (j = 0; j < v.nRow; j++) {
+           vtemp = v.values[j][topr];
+           v.values[j][topr] = cosr[0]*vtemp - sinr[0]*v.values[j][bottomr];
+           v.values[j][bottomr] = sinr[0]*vtemp + cosr[0]*v.values[j][bottomr];
+       }
+
+       if (debug) {
+           t.setIdentity();
+           for (j = 0; j < v.nRow; j++) {
+               vtemp = t.values[j][topr];
+               t.values[j][topr] =
+                   cosr[0]*vtemp - sinr[0]*t.values[j][bottomr];
+               t.values[j][bottomr] =
+                   sinr[0]*vtemp + cosr[0]*t.values[j][bottomr];
+           }
+       }
+
+       System.out.println("topr    =" + topr);
+       System.out.println("bottomr =" + bottomr);
+       System.out.println("cosr =" + cosr[0]);
+       System.out.println("sinr =" + sinr[0]);
+       System.out.println("\nm =");
+       checkMatrix(m);
+       System.out.println("\nv =");
+       checkMatrix(t);
+       m.mul(m,t);
+       System.out.println("\nt*m =");
+       checkMatrix(m);
+    }
+
+    private static void update_u_split(int topr, int bottomr, GMatrix u,
+                                      double[] cosl, double[] sinl,
+                                      GMatrix t, GMatrix m) {
+       int j;
+       double utemp;
+
+       for (j = 0; j < u.nCol; j++) {
+           utemp = u.values[topr][j];
+           u.values[topr][j]    = cosl[0]*utemp - sinl[0]*u.values[bottomr][j];
+           u.values[bottomr][j] = sinl[0]*utemp + cosl[0]*u.values[bottomr][j];
+       }
+
+       if(debug) {
+           t.setIdentity();
+           for (j = 0;j < u.nCol; j++) {
+               utemp = t.values[topr][j];
+               t.values[topr][j] =
+                   cosl[0]*utemp - sinl[0]*t.values[bottomr][j];
+               t.values[bottomr][j] =
+                   sinl[0]*utemp + cosl[0]*t.values[bottomr][j];
+           }
+       }
+       System.out.println("\nm=");
+       checkMatrix(m);
+       System.out.println("\nu=");
+       checkMatrix(t);
+       m.mul(t,m);
+       System.out.println("\nt*m=");
+       checkMatrix(m);
+    }
+
+    private static void update_u(int index, GMatrix u,
+                                double[] cosl, double[] sinl) {
+       int j;
+       double utemp;
+
+       for (j = 0; j < u.nCol; j++) {
+           utemp = u.values[index][j];
+           u.values[index][j] =
+               cosl[0]*utemp + sinl[0]*u.values[index+1][j];
+           u.values[index+1][j] =
+              -sinl[0]*utemp + cosl[0]*u.values[index+1][j];
+       }
+    }
+
+    private static void print_m(GMatrix m, GMatrix u, GMatrix v) {
+       GMatrix mtmp = new GMatrix(m.nCol, m.nRow);
+
+       mtmp.mul(u, mtmp);
+       mtmp.mul(mtmp, v);
+       System.out.println("\n m = \n" + mtmp.toString(mtmp));
+            
+    }
+
+    private static String toString(GMatrix m) 
+    {
+       StringBuffer buffer = new StringBuffer(m.nRow * m.nCol * 8);
+       int i, j;
+
+       for (i = 0; i < m.nRow; i++) {
+           for(j = 0; j < m.nCol; j++) {
+               if (Math.abs(m.values[i][j]) < .000000001) {
+                   buffer.append("0.0000 ");
+               } else {
+                   buffer.append(m.values[i][j]).append(" ");
+               }
+           }
+           buffer.append("\n");
+       }
+       return buffer.toString();
+    }
+
+    private static void print_svd(double[] s, double[] e,
+                                 GMatrix u, GMatrix v) {
+       int i;
+       GMatrix mtmp = new GMatrix(u.nCol, v.nRow);
+
+       System.out.println(" \ns = ");
+       for (i = 0; i < s.length; i++) {
+           System.out.println(" " + s[i]);     
+       }
+
+       System.out.println(" \ne = ");
+       for (i = 0; i < e.length; i++) {
+           System.out.println(" " + e[i]);     
+       }
+
+       System.out.println(" \nu  = \n" + u.toString());
+       System.out.println(" \nv  = \n" + v.toString());
+
+       mtmp.setIdentity();
+       for (i = 0; i < s.length; i++) {
+           mtmp.values[i][i] = s[i];
+       }
+       for (i = 0; i < e.length; i++) {
+           mtmp.values[i][i+1] = e[i];
+       }
+       System.out.println(" \nm  = \n"+mtmp.toString());
+
+       mtmp.mulTransposeLeft(u, mtmp);
+       mtmp.mulTransposeRight(mtmp, v);
+
+       System.out.println(" \n u.transpose*m*v.transpose  = \n" +
+                          mtmp.toString());
+    }
+
+    static double max(double a, double b) {
+       if (a > b) 
+           return a;
+       else
+           return b;
+    }
+
+    static double min(double a, double b) {
+       if (a < b) 
+           return a;
+       else
+           return b;
+    }
+
+    static double compute_shift(double f, double g, double h) {
+       double d__1, d__2;
+       double fhmn, fhmx, c, fa, ga, ha, as, at, au;
+       double ssmin;
+       fa = Math.abs(f);
+       ga = Math.abs(g);
+       ha = Math.abs(h);
+       fhmn = min(fa,ha);
+       fhmx = max(fa,ha);
+
+       if (fhmn == 0.0) {
+           ssmin = 0.0;
+           if (fhmx == 0.0) {
+           } else {
+               d__1 = min(fhmx,ga) / max(fhmx,ga);
+           }
+       } else {
+           if (ga < fhmx) {
+               as = fhmn / fhmx + 1.0;
+               at = (fhmx - fhmn) / fhmx;
+               d__1 = ga / fhmx;
+               au = d__1 * d__1;
+               c = 2.0 / (Math.sqrt(as * as + au) + Math.sqrt(at * at + au));
+               ssmin = fhmn * c;
+           } else {
+               au = fhmx / ga;
+               if (au == 0.0) {
+                   ssmin = fhmn * fhmx / ga;
+               } else {
+                   as = fhmn / fhmx + 1.0;
+                   at = (fhmx - fhmn) / fhmx;
+                   d__1 = as * au;
+                   d__2 = at * au;
+                   c = 1.0 / (Math.sqrt(d__1 * d__1 + 1.0) +
+                              Math.sqrt(d__2 * d__2 + 1.0));
+                   ssmin = fhmn * c * au;
+                   ssmin += ssmin;
+               }
+           }
+       }    
+
+       return ssmin;
+    }
+
+    static int compute_2X2(double f, double g, double h,
+                          double[] single_values, double[] snl, double[] csl,
+                          double[] snr, double[] csr, int index) {
+
+       double c_b3 = 2.0;
+       double c_b4 = 1.0;
+       double d__1;
+       int pmax;
+       double temp;
+       boolean swap;
+       double a, d, l, m, r, s, t, tsign, fa, ga, ha;
+       double ft, gt, ht, mm;
+       boolean gasmal;
+       double tt, clt, crt, slt, srt;
+       double ssmin,ssmax;
+       ssmax = single_values[0];
+       ssmin = single_values[1];
+       clt = 0.0;
+       crt = 0.0;
+       slt = 0.0;
+       srt = 0.0;
+       tsign = 0.0;
+
+       ft = f;
+       fa = Math.abs(ft);
+       ht = h;
+       ha = Math.abs(h);
+       pmax = 1;
+       if (ha > fa) 
+           swap = true;
+       else 
+           swap = false;
+
+       if (swap) {
+           pmax = 3;
+           temp = ft;
+           ft = ht;
+           ht = temp;
+           temp = fa;
+           fa = ha;
+           ha = temp;
+       }
+
+       gt = g;
+       ga = Math.abs(gt);
+       if (ga == 0.0) {
+           single_values[1] = ha;
+           single_values[0] = fa;
+           clt = 1.0;
+           crt = 1.0;
+           slt = 0.0;
+           srt = 0.0;
+       } else {
+           gasmal = true;
+           if (ga > fa) {
+               pmax = 2;
+               if (fa / ga < EPS) {
+                   gasmal = false;
+                   ssmax = ga;
+
+                   if (ha > 1.0) {
+                       ssmin = fa / (ga / ha);
+                   } else {
+                       ssmin = fa / ga * ha;
+                   }
+                   clt = 1.0;
+                   slt = ht / gt;
+                   srt = 1.0;
+                   crt = ft / gt;
+               }
+           }
+           if (gasmal) {
+               d = fa - ha;
+               if (d == fa) {
+                   l = 1.0;
+               } else {
+                   l = d / fa;
+               }
+               m = gt / ft;
+               t = 2.0 - l;
+               mm = m * m;
+               tt = t * t;
+               s = Math.sqrt(tt + mm);
+               if (l == 0.0) {
+                   r = Math.abs(m);
+               } else {
+                   r = Math.sqrt(l * l + mm);
+               }
+               a = (s + r) * 0.5;
+               if (ga > fa) {
+                   pmax = 2;
+                   if (fa / ga < EPS) {
+                       gasmal = false;
+                       ssmax = ga;
+                       if (ha > 1.0) {
+                           ssmin = fa / (ga / ha);
+                       } else {
+                           ssmin = fa / ga * ha;
+                       }
+                       clt = 1.0;
+                       slt = ht / gt;
+                       srt = 1.0;
+                       crt = ft / gt;
+                   }
+               }
+               if (gasmal) {
+                   d = fa - ha;
+                   if (d == fa) {
+                       l = 1.0;
+                   } else {
+                       l = d / fa;
+                   }
+                   m = gt / ft;
+                   t = 2.0 - l;
+                   mm = m * m;
+                   tt = t * t;
+                   s = Math.sqrt(tt + mm);
+                   if (l == 0.) {
+                       r = Math.abs(m);
+                   } else {
+                       r = Math.sqrt(l * l + mm);
+                   }
+                   a = (s + r) * 0.5;
+                   ssmin = ha / a;
+                   ssmax = fa * a;
+
+                   if (mm == 0.0) {
+                       if (l == 0.0) {
+                           t = d_sign(c_b3, ft) * d_sign(c_b4, gt);
+                       } else {
+                           t = gt / d_sign(d, ft) + m / t;
+                       }
+                   } else {
+                       t = (m / (s + t) + m / (r + l)) * (a + 1.0);
+                   }
+
+                   l = Math.sqrt(t * t + 4.0);
+                   crt = 2.0 / l;
+                   srt = t / l;
+                   clt = (crt + srt * m) / a;
+                   slt = ht / ft * srt / a;
+               }
+           }
+           if (swap) {
+               csl[0] = srt;
+               snl[0] = crt;
+               csr[0] = slt;
+               snr[0] = clt;
+           } else {
+               csl[0] = clt;
+               snl[0] = slt;
+               csr[0] = crt;
+               snr[0] = srt;
+           }
+       
+           if (pmax == 1) {
+               tsign = d_sign(c_b4, csr[0]) *
+                   d_sign(c_b4, csl[0]) * d_sign(c_b4, f);
+           }
+           if (pmax == 2) {
+               tsign = d_sign(c_b4, snr[0]) *
+                   d_sign(c_b4, csl[0]) * d_sign(c_b4, g);
+           }
+           if (pmax == 3) {
+               tsign = d_sign(c_b4, snr[0]) *
+                   d_sign(c_b4, snl[0]) * d_sign(c_b4, h);
+           }
+
+           single_values[index] = d_sign(ssmax, tsign);
+           d__1 = tsign * d_sign(c_b4, f) * d_sign(c_b4, h);
+           single_values[index+1] = d_sign(ssmin, d__1);
+       }  
+
+       return 0;
+    }
+
+    static double compute_rot(double f, double g, double[] sin, double[] cos) {
+       int i__1;
+       double d__1, d__2;
+       double cs, sn;
+       int i;
+       double scale;
+       int count;
+       double f1, g1;
+       double r;
+       final double safmn2 = 2.002083095183101E-146;
+       final double safmx2 = 4.994797680505588E+145;
+       if (g == 0.0) {
+           cs = 1.0;
+           sn = 0.0;
+           r = f;
+       } else if (f == 0.0) {
+           cs = 0.0;
+           sn = 1.0;
+           r = g;
+       } else {
+           f1 = f;
+           g1 = g;
+           scale = max(Math.abs(f1),Math.abs(g1));
+           if (scale >= safmx2) {
+               count = 0;
+               while(scale >= safmx2) {
+                   ++count;
+                   f1 *= safmn2;
+                   g1 *= safmn2;
+                   scale = max(Math.abs(f1), Math.abs(g1));
+               }
+               r = Math.sqrt(f1*f1 + g1*g1);
+               cs = f1 / r;
+               sn = g1 / r;
+               i__1 = count;
+               for (i = 1; i <= count; ++i) {
+                   r *= safmx2;
+               }
+           } else if (scale <= safmn2) {
+               count = 0;
+               while(scale <= safmn2) {
+                   ++count;
+                   f1 *= safmx2;
+                   g1 *= safmx2;
+                   scale = max(Math.abs(f1), Math.abs(g1));
+               }
+               r = Math.sqrt(f1*f1 + g1*g1);
+               cs = f1 / r;
+               sn = g1 / r;
+               i__1 = count;
+               for (i = 1; i <= count; ++i) {
+                   r *= safmn2;
+               }
+           } else {
+               r = Math.sqrt(f1*f1 + g1*g1);
+               cs = f1 / r;
+               sn = g1 / r;
+           }
+           if (Math.abs(f) > Math.abs(g) && cs < 0.0) {
+               cs = -cs;
+               sn = -sn;
+               r = -r;
+           }
+       }    
+       sin[0] = sn;
+       cos[0] = cs;
+       return r;
+    }
+
+    static double d_sign(double a, double b) {
+       double x;
+       x = (a >= 0 ? a : - a);
+       return (b >= 0 ? x : -x);
+    }
+
+    /**
+     * Creates a new object of the same class as this object.
+     *
+     * @return a clone of this instance.
+     * @exception OutOfMemoryError if there is not enough memory.
+     * @see java.lang.Cloneable
+     * @since vecmath 1.3
+     */
+    public Object clone() {
+       GMatrix m1 = null;
+       try {
+           m1 = (GMatrix)super.clone();
+       } catch (CloneNotSupportedException e) {
+           // this shouldn't happen, since we are Cloneable
+           throw new InternalError();
+       }
+
+       // Also need to clone array of values
+        m1.values = new double[nRow][nCol];
+       for (int i = 0; i < nRow; i++) {
+          for(int j = 0; j < nCol; j++) {
+              m1.values[i][j] = values[i][j];
+          }
+       }
+
+       return m1;
+    }
+
+}
diff --git a/javax.vecmath/src/javax/vecmath/GVector.java b/javax.vecmath/src/javax/vecmath/GVector.java
new file mode 100644 (file)
index 0000000..c7b8719
--- /dev/null
@@ -0,0 +1,933 @@
+/*
+ * $RCSfile: GVector.java,v $
+ *
+ * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ * $Revision: 1.7 $
+ * $Date: 2008/02/28 20:18:50 $
+ * $State: Exp $
+ */
+
+package javax.vecmath;
+
+import java.lang.Math;
+
+/**
+ * A double precision, general, dynamically-resizable,
+ * one-dimensional vector class.  Index numbering begins with zero.
+ */
+
+public class GVector implements java.io.Serializable, Cloneable {
+
+    private int length;
+    double[] values;
+
+    // Compatible with 1.1
+    static final long serialVersionUID = 1398850036893875112L;
+
+    /**
+     * Constructs a new GVector of the specified
+     * length with all vector elements initialized to 0.
+     * @param length the number of elements in this GVector.
+     */
+    public GVector(int length)
+       {
+           int i;
+            
+            this.length = length;          
+           values = new double[length];
+           for(i = 0; i < length; i++) values[i] = 0.0;
+       }
+    
+    /**
+     * Constructs a new GVector from the specified array elements.
+     * The length of this GVector is set to the length of the
+     * specified array.  The array elements are copied into this new
+     * GVector.
+     * @param vector the values for the new GVector.
+     */
+    public GVector(double[] vector)
+       {
+           int i;
+           
+            length = vector.length;        
+           values = new double[vector.length];
+           for(i = 0; i < length; i++) values[i] = vector[i];
+       }
+                                                         
+    /**
+     * Constructs a new GVector from the specified vector.
+     * The vector elements are copied into this new GVector.
+     * @param vector the source GVector for this new GVector.
+     */
+    public GVector(GVector vector)
+       {
+           int i;
+       
+           values = new double[vector.length];
+           length = vector.length;
+           for(i = 0; i < length; i++) values[i] = vector.values[i];
+       }
+
+    /**
+      * Constructs a new GVector and copies the initial values
+      * from the specified tuple.
+      * @param tuple the source for the new GVector's initial values
+      */
+    public GVector(Tuple2f tuple)
+        {
+            values = new double[2];
+            values[0] = (double)tuple.x;
+            values[1] = (double)tuple.y;
+           length = 2;
+        }
+
+    /** 
+      * Constructs a new GVector and copies the initial values
+      * from the specified tuple.
+      * @param tuple the source for the new GVector's initial values
+      */ 
+    public GVector(Tuple3f tuple)
+       {
+           values = new double[3];
+           values[0] = (double)tuple.x;
+           values[1] = (double)tuple.y;
+           values[2] = (double)tuple.z;
+           length = 3;
+       }
+
+    /** 
+      * Constructs a new GVector and copies the initial values
+      * from the specified tuple.
+      * @param tuple the source for the new GVector's initial values
+      */ 
+    public GVector(Tuple3d tuple)
+       {
+           values = new double[3];
+           values[0] = tuple.x;
+           values[1] = tuple.y;
+           values[2] = tuple.z;
+           length = 3;
+       }
+
+    /** 
+      * Constructs a new GVector and copies the initial values
+      * from the specified tuple.
+      * @param tuple the source for the new GVector's initial values
+      */ 
+    public GVector(Tuple4f tuple)
+       {
+           values = new double[4];
+           values[0] = (double)tuple.x;
+           values[1] = (double)tuple.y;
+           values[2] = (double)tuple.z;
+           values[3] = (double)tuple.w;
+           length = 4;
+       }
+
+    /** 
+      * Constructs a new GVector and copies the initial values
+      * from the specified tuple.
+      * @param tuple the source for the new GVector's initial values
+      */ 
+    public GVector(Tuple4d tuple)
+       {
+           values = new double[4];
+           values[0] = tuple.x;
+           values[1] = tuple.y;
+           values[2] = tuple.z;
+           values[3] = tuple.w;
+           length = 4;
+       }
+
+    /**
+     * Constructs a new GVector of the specified length and
+     * initializes it by copying the specified number of elements from
+     * the specified array.  The array must contain at least
+     * <code>length</code> elements (i.e., <code>vector.length</code> >=
+     * <code>length</code>.  The length of this new GVector is set to
+     * the specified length.
+     * @param  vector   The array from which the values will be copied.
+     * @param  length   The number of values copied from the array.
+     */
+    public GVector(double vector[], int length) {
+       int i;
+
+        this.length = length;
+       values = new double [length];
+       for(i=0;i<length;i++) {
+           values[i] = vector[i];
+        }
+    }
+
+    /**
+      * Returns the square root of the sum of the squares of this
+      * vector (its length in n-dimensional space).
+      * @return  length of this vector
+      */ 
+    public final double norm()
+    {
+      double sq = 0.0;
+      int i;
+
+       for(i=0;i<length;i++) {
+           sq += values[i]*values[i];
+        }           
+
+       return(Math.sqrt(sq));
+
+    }
+
+    /** 
+      * Returns the sum of the squares of this   
+      * vector (its length squared in n-dimensional space). 
+      * @return  length squared of this vector 
+      */
+    public final double normSquared() 
+    { 
+        double sq = 0.0;
+        int i;
+
+       for(i=0;i<length;i++) {
+           sq += values[i]*values[i];
+        }           
+
+       return(sq);
+    }
+
+    /**
+     * Sets the value of this vector to the normalization of vector v1.
+     * @param v1 the un-normalized vector
+     */  
+    public final void normalize(GVector v1)
+    {
+      double sq = 0.0;
+      int i;
+
+      if( length != v1.length)
+          throw new MismatchedSizeException(VecMathI18N.getString("GVector0"));
+
+       for(i=0;i<length;i++) {
+           sq += v1.values[i]*v1.values[i];
+       }            
+
+       double invMag;
+       invMag = 1.0/Math.sqrt(sq);
+
+       for(i=0;i<length;i++) {
+          values[i] = v1.values[i]*invMag;
+       }
+    }
+
+    /**
+     * Normalizes this vector in place. 
+     */  
+    public final void normalize() 
+    { 
+      double sq = 0.0;
+      int i;
+
+        for(i=0;i<length;i++) {
+            sq += values[i]*values[i];
+        }        
+
+        double invMag;
+       invMag = 1.0/Math.sqrt(sq);
+
+        for(i=0;i<length;i++) {
+            values[i] = values[i]*invMag;
+        }
+
+    } 
+
+    /**
+     * Sets the value of this vector to the scalar multiplication
+     * of the scale factor with the vector v1.
+     * @param s the scalar value
+     * @param v1 the source vector 
+     */  
+    public final void scale(double s, GVector v1)
+    {
+        int i;
+       if( length != v1.length)
+          throw new MismatchedSizeException(VecMathI18N.getString("GVector1"));
+
+        for(i=0;i<length;i++) {
+            values[i] = v1.values[i]*s;
+        }
+    }
+
+    /** 
+     * Scales this vector by the scale factor s. 
+     * @param s the scalar value 
+     */   
+    public final void scale(double s) 
+    { 
+      int i;
+
+        for(i=0;i<length;i++) {
+            values[i] = values[i]*s;
+        }
+    } 
+
+    /**
+     * Sets the value of this vector to the scalar multiplication by s
+     * of vector v1 plus vector v2 (this = s*v1 + v2).
+     * @param s the scalar value
+     * @param v1 the vector to be multiplied
+     * @param v2 the vector to be added
+     */
+    public final void scaleAdd(double s, GVector v1, GVector v2)
+    {
+
+      int i;
+
+      if( v2.length != v1.length ) 
+        throw new MismatchedSizeException(VecMathI18N.getString("GVector2"));
+
+       if( length  != v1.length )
+         throw new MismatchedSizeException(VecMathI18N.getString("GVector3"));
+
+        for(i=0;i<length;i++) {
+            values[i] = v1.values[i]*s + v2.values[i];
+        }
+    }
+
+    /**
+      * Sets the value of this vector to sum of itself and the specified
+      * vector
+      * @param vector the second vector
+      */  
+    public final void add(GVector vector)
+       {
+           int i;
+           
+          if( length  != vector.length )
+            throw new MismatchedSizeException(VecMathI18N.getString("GVector4"));
+
+          for(i = 0; i < length; i++) {
+               this.values[i] += vector.values[i];
+          }
+       }
+
+    /**
+      * Sets the value of this vector to the vector sum of vectors vector1
+      * and vector2.
+      * @param vector1 the first vector
+      * @param vector2 the second vector
+      */  
+    public final void add(GVector vector1, GVector vector2)
+       {
+         int i;
+
+         if( vector1.length != vector2.length ) 
+          throw new MismatchedSizeException(VecMathI18N.getString("GVector5"));
+
+       if( length  != vector1.length )
+         throw new MismatchedSizeException(VecMathI18N.getString("GVector6"));
+           
+           for(i = 0; i < length; i++)
+               this.values[i] = vector1.values[i] + vector2.values[i];
+       }
+
+    /**
+      * Sets the value of this vector to the vector difference of itself
+      * and vector (this = this - vector).
+      * @param vector the other vector
+      */  
+    public final void sub(GVector vector) 
+       { 
+           int i;
+           
+           if( length  != vector.length )
+               throw new MismatchedSizeException(VecMathI18N.getString("GVector7"));
+
+           for(i = 0; i < length; i++) {
+               this.values[i] -= vector.values[i];
+           }
+       } 
+
+    /**
+      * Sets the value of this vector to the vector difference
+      * of vectors vector1 and vector2 (this = vector1 - vector2).
+      * @param vector1 the first vector
+      * @param vector2 the second vector
+      */  
+    public final void sub(GVector vector1, GVector vector2) 
+       {
+           int i,l;
+           
+
+       if( vector1.length != vector2.length ) 
+         throw new MismatchedSizeException(VecMathI18N.getString("GVector8"));
+
+       if( length  != vector1.length )
+         throw new MismatchedSizeException(VecMathI18N.getString("GVector9"));
+
+           for(i = 0; i < length; i++)
+               this.values[i] = vector1.values[i] - vector2.values[i];
+       }
+
+    /**
+      * Multiplies matrix m1 times Vector v1 and places the result
+      * into this vector (this = m1*v1).  
+      * @param m1  The matrix in the multiplication
+      * @param v1  The vector that is multiplied
+      */
+    public final void mul(GMatrix m1, GVector v1) {
+       if (m1.getNumCol() != v1.length) 
+         throw new MismatchedSizeException(VecMathI18N.getString("GVector10"));
+
+       if (length  != m1.getNumRow())
+         throw new MismatchedSizeException(VecMathI18N.getString("GVector11"));
+
+       double v[];
+       if (v1 != this) {
+          v = v1.values;
+       } else {
+          v = (double []) values.clone();
+       }
+
+       for(int j=length-1; j>=0; j--){
+         values[j] = 0.0;
+         for(int i=v1.length-1;i>=0; i--){
+           values[j] += m1.values[j][i] * v[i];
+         }
+       }
+     }
+
+    /** 
+      * Multiplies the transpose of vector v1 (ie, v1 becomes a row
+      * vector with respect to the multiplication) times matrix m1 
+      * and places the result into this vector 
+      * (this = transpose(v1)*m1).  The result is technically a 
+      * row vector, but the GVector class only knows about column
+      * vectors, and so the result is stored as a column vector.
+      * @param m1  The matrix in the multiplication
+      * @param v1  The vector that is temporarily transposed
+      */ 
+    public final void mul(GVector v1, GMatrix m1) {   
+       if (m1.getNumRow() != v1.length) 
+         throw new MismatchedSizeException(VecMathI18N.getString("GVector12"));
+
+       if (length  != m1.getNumCol())
+         throw new MismatchedSizeException(VecMathI18N.getString("GVector13"));
+
+       double v[];
+       if (v1 != this) {
+          v = v1.values;
+       } else {
+          v = (double []) values.clone();
+       }
+
+       for (int j=length-1; j>=0; j--){
+         values[j] = 0.0;
+         for(int i=v1.length-1; i>=0; i--){
+            values[j] += m1.values[i][j] * v[i];
+         }
+       }
+     }   
+
+    /** 
+      * Negates the value of this vector: this = -this.
+      */
+    public final void negate() {
+       for(int i=length-1; i>=0; i--) {
+           this.values[i] *= -1.0;
+       }
+    }
+
+    /**
+      * Sets all the values in this vector to zero.
+      */
+    public final void zero() {
+       for (int i=0; i < this.length; i++) {
+           this.values[i] = 0.0;
+       }
+    }
+
+    /**
+      * Changes the size of this vector dynamically.  If the size is increased
+      * no data values will be lost.  If the size is decreased, only those data
+      * values whose vector positions were eliminated will be lost.
+      * @param length  number of desired elements in this vector
+      */
+    public final void setSize(int length) {
+          double[] tmp = new double[length];
+          int i,max;
+
+           if( this.length < length)
+             max = this.length;
+           else
+              max = length;
+
+          for(i=0;i<max;i++) {
+             tmp[i] = values[i];
+           }
+          this.length = length;
+
+          values = tmp;
+
+       }
+
+    /**
+      * Sets the value of this vector to the values found in the array 
+      * parameter. The array should be at least equal in length to
+      * the number of elements in the vector.
+      * @param vector  the source array
+      */  
+    public final void set(double[] vector) {
+       for(int i = length-1; i >=0; i--) 
+           values[i] = vector[i];
+    }
+
+    /**
+      * Sets the value of this vector to the values found in vector vector.
+      * @param vector  the source vector
+      */
+    public final void set(GVector vector) {
+       int i;
+       
+       if (length < vector.length) {
+           length = vector.length;
+           values = new double[length];
+           for(i = 0; i < length; i++) 
+               values[i] = vector.values[i];
+       }else {
+           for(i = 0; i < vector.length; i++)
+               values[i] = vector.values[i];
+           for(i = vector.length; i < length; i++)
+               values[i] = 0.0;
+       }
+    }
+
+    /**
+      * Sets the value of this vector to the values in tuple
+      * @param tuple the source for the new GVector's new values
+      */ 
+    public final void set(Tuple2f tuple)
+        {
+            if (length < 2) {
+              length = 2;
+              values = new double[2];
+           }
+            values[0] = (double)tuple.x;
+            values[1] = (double)tuple.y;
+           for(int i = 2; i < length; i++) values[i] = 0.0;
+
+        }
+
+    /** 
+      * Sets the value of this vector to the values in tuple
+      * @param tuple the source for the new GVector's new values
+      */ 
+    public final void set(Tuple3f tuple)
+       {
+            if (length < 3) {
+              length = 3;
+              values = new double[3];
+           }
+            values[0] = (double)tuple.x;
+            values[1] = (double)tuple.y;
+           values[2] = (double)tuple.z;
+           for(int i = 3; i < length; i++) values[i] = 0.0;
+       }
+
+    /** 
+      * Sets the value of this vector to the values in tuple
+      * @param tuple the source for the new GVector's new values
+      */ 
+    public final void set(Tuple3d tuple)
+       {
+            if (length < 3) {
+              length = 3;
+              values = new double[3];
+           }
+            values[0] = tuple.x;
+            values[1] = tuple.y;
+           values[2] = tuple.z;
+           for(int i = 3; i < length; i++) values[i] = 0.0;
+       }
+
+    /** 
+      * Sets the value of this vector to the values in tuple
+      * @param tuple the source for the new GVector's new values
+      */ 
+    public final void set(Tuple4f tuple)
+       {
+            if (length < 4) {
+              length = 4;
+              values = new double[4];
+           }
+            values[0] = (double)tuple.x;
+            values[1] = (double)tuple.y;
+           values[2] = (double)tuple.z;
+           values[3] = (double)tuple.w;
+           for(int i = 4; i < length; i++) values[i] = 0.0;
+       }
+
+    /** 
+      * Sets the value of this vector to the values in tuple
+      * @param tuple the source for the new GVector's new values
+      */ 
+    public final void set(Tuple4d tuple)
+       {
+            if (length < 4) {
+              length = 4;
+              values = new double[4];
+           }
+            values[0] = tuple.x;
+            values[1] = tuple.y;
+           values[2] = tuple.z;
+           values[3] = tuple.w;
+           for(int i = 4; i < length; i++) values[i] = 0.0;
+       }
+
+    /**
+      * Returns the number of elements in this vector.
+      * @return  number of elements in this vector
+      */
+    public final int getSize()
+       {
+           return values.length;
+       }
+
+    /**
+      * Retrieves the value at the specified index value of this vector.
+      * @param index the index of the element to retrieve (zero indexed)
+      * @return the value at the indexed element
+      */  
+    public final double getElement(int index)
+       {
+           return values[index];
+       }
+
+    /**  
+      * Modifies the value at the specified index of this vector.
+      * @param index  the index if the element to modify (zero indexed) 
+      * @param value  the new vector element value
+      */   
+    public final void setElement(int index, double value)
+       {
+           values[index] = value;
+       }
+
+    /**
+      * Returns a string that contains the values of this GVector.
+      * @return the String representation
+      */  
+    public String toString() {
+      StringBuffer buffer = new StringBuffer(length*8);
+
+      int i;
+
+      for(i=0;i<length;i++) {
+           buffer.append(values[i]).append(" ");
+      }
+
+      return buffer.toString();
+
+    }
+
+
+    /**
+     * Returns a hash code value based on the data values in this
+     * object.  Two different GVector objects with identical data
+     * values (i.e., GVector.equals returns true) will return the
+     * same hash number.  Two GVector objects with different data
+     * members may return the same hash value, although this is not
+     * likely.
+     * @return the integer hash code value
+     */
+    public int hashCode() {
+       long bits = 1L;
+
+       for (int i = 0; i < length; i++) {
+           bits = 31L * bits + VecMathUtil.doubleToLongBits(values[i]);
+       }
+
+       return (int) (bits ^ (bits >> 32));
+    } 
+
+
+    /**
+      * Returns true if all of the data members of GVector vector1 are
+      * equal to the corresponding data members in this GVector.
+      * @param vector1  The vector with which the comparison is made.
+      * @return  true or false
+      */  
+    public boolean equals(GVector vector1)
+       {
+        try { 
+           if( length != vector1.length)   return false;
+
+            for(int i = 0;i<length;i++) {
+             if( values[i] != vector1.values[i]) return false;
+            }
+
+           return true;
+        }
+        catch (NullPointerException e2) { return false; }
+
+         }
+    /**
+     * Returns true if the Object o1 is of type GMatrix and all of the
+     * data members of o1 are equal to the corresponding data members in
+     * this GMatrix.
+     * @param o1  The object with which the comparison is made.
+     * @return  true or false
+     */  
+    public boolean equals(Object o1)
+    {
+        try {   
+            GVector v2 = (GVector) o1;
+
+           if( length != v2.length)   return false;
+
+            for(int i = 0;i<length;i++) {
+             if( values[i] != v2.values[i]) return false;
+            }
+           return true;
+        }
+        catch (ClassCastException   e1) { return false; }
+        catch (NullPointerException e2) { return false; }
+
+    }
+
+   /**
+     * Returns true if the L-infinite distance between this vector
+     * and vector v1 is less than or equal to the epsilon parameter, 
+     * otherwise returns false.  The L-infinite
+     * distance is equal to 
+     * MAX[abs(x1-x2), abs(y1-y2), . . .  ].
+     * @param v1  The vector to be compared to this vector
+     * @param epsilon  the threshold value  
+     */
+    public boolean epsilonEquals(GVector v1, double epsilon)
+    {
+       double diff;
+
+           if( length != v1.length)   return false;
+
+            for(int i = 0;i<length;i++) {
+               diff = values[i] - v1.values[i];
+                if( (diff<0?-diff:diff) > epsilon) return false;
+            }
+           return true;
+    }
+
+  /**
+    * Returns the dot product of this vector and vector v1.
+    * @param v1 the other vector
+    * @return the dot product of this and v1
+    */
+   public final double dot(GVector v1)
+     {
+       if( length != v1.length)  
+              throw new MismatchedSizeException(VecMathI18N.getString("GVector14"));
+
+       double result = 0.0;
+       for(int i = 0;i<length;i++) {
+         result += values[i] * v1.values[i];
+       }
+       return result;
+     }
+  /**
+    *  Solves for x in Ax = b, where x is this vector (nx1), A is mxn,
+    *  b is mx1, and A = U*W*transpose(V); U,W,V must
+    *  be precomputed and can be found by taking the singular value 
+    *  decomposition (SVD) of A using the method SVD found in the 
+    *  GMatrix class.
+    *  @param U  The U matrix produced by the GMatrix method SVD
+    *  @param W  The W matrix produced by the GMatrix method SVD
+    *  @param V  The V matrix produced by the GMatrix method SVD
+    *  @param b  The b vector in the linear equation Ax = b
+    */
+   public final void SVDBackSolve(GMatrix U, GMatrix W, GMatrix V, GVector b)
+    {
+       if( !(U.nRow == b.getSize() &&
+            U.nRow == U.nCol      &&
+            U.nRow == W.nRow  ) ) {
+            throw new MismatchedSizeException(VecMathI18N.getString("GVector15"));
+       }
+
+       if( !(W.nCol == values.length &&
+            W.nCol == V.nCol        &&
+            W.nCol == V.nRow  ) ) {
+            throw new MismatchedSizeException(VecMathI18N.getString("GVector23"));
+       }
+
+       GMatrix tmp = new GMatrix( U.nRow, W.nCol);
+       tmp.mul( U, V);
+       tmp.mulTransposeRight( U, W);
+       tmp.invert();
+       mul(tmp, b);
+
+    }
+
+   /**
+     * LU Decomposition Back Solve; this method takes the LU matrix
+     * and the permutation vector produced by the GMatrix method LUD
+     * and solves the equation (LU)*x = b by placing the solution vector
+     * x into this vector.  This vector should be the same length or 
+     * longer than b.  
+     * @param LU  The matrix into which the lower and upper decompostions
+     * have been placed
+     * @param b  The b vector in the equation (LU)*x = b
+     * @param permutation  The row permuations that were necessary to 
+     * produce the LU matrix parameter
+     */ 
+   public final void LUDBackSolve(GMatrix LU, GVector b, GVector permutation)
+   {
+       int size = LU.nRow*LU.nCol;
+
+       double[] temp = new double[size];
+       double[] result = new double[size];
+       int[] row_perm = new int[b.getSize()]; 
+       int i,j;
+
+       if( LU.nRow != b.getSize() ) {
+            throw new MismatchedSizeException(VecMathI18N.getString("GVector16"));
+       }
+
+       if( LU.nRow != permutation.getSize() ) {
+            throw new MismatchedSizeException(VecMathI18N.getString("GVector24"));
+       }
+
+       if (LU.nRow != LU.nCol) {
+            throw new MismatchedSizeException(VecMathI18N.getString("GVector25"));
+       }
+
+        for(i=0;i<LU.nRow;i++) {
+           for(j=0;j<LU.nCol;j++) {
+               temp[i*LU.nCol+j] = LU.values[i][j];
+           }
+        }
+
+       for(i=0;i<size;i++) result[i] = 0.0; 
+       for(i=0;i<LU.nRow;i++) result[i*LU.nCol] = b.values[i]; 
+       for(i=0;i<LU.nCol;i++) row_perm[i] = (int)permutation.values[i]; 
+
+       GMatrix.luBacksubstitution(LU.nRow, temp, row_perm, result);
+
+       for(i=0;i<LU.nRow;i++) this.values[i] = result[i*LU.nCol]; 
+   }
+
+  /**
+    *   Returns the (n-space) angle in radians between this vector and
+    *   the vector parameter; the return value is constrained to the
+    *   range [0,PI].
+    *   @param v1    The other vector
+    *   @return   The angle in radians in the range [0,PI]
+    */
+   public final double angle(GVector v1)
+   {
+   return( Math.acos( this.dot(v1) / ( this.norm()*v1.norm() ) ) );
+   }
+
+
+    /**
+     * @deprecated Use interpolate(GVector, GVector, double) instead
+     */
+    public final void interpolate(GVector v1, GVector v2, float alpha) {
+       interpolate(v1, v2, (double)alpha);
+    }
+
+
+    /**
+     * @deprecated Use interpolate(GVector, double) instead
+     */
+    public final void interpolate(GVector v1, float alpha) {
+       interpolate(v1, (double)alpha);
+    }
+
+
+  /**
+    *  Linearly interpolates between vectors v1 and v2 and places the
+    *  result into this tuple:  this = (1-alpha)*v1 + alpha*v2.
+    *  @param v1  the first vector
+    *  @param v2  the second vector
+    *  @param alpha  the alpha interpolation parameter   
+    */   
+  public final void interpolate(GVector v1, GVector v2, double alpha)
+  {
+       if( v2.length != v1.length ) 
+         throw new MismatchedSizeException(VecMathI18N.getString("GVector20"));
+
+       if( length  != v1.length )
+         throw new MismatchedSizeException(VecMathI18N.getString("GVector21"));
+
+       for(int i=0;i<length;i++) {
+         values[i] = (1-alpha)*v1.values[i] + alpha*v2.values[i];
+       }
+  }
+
+  /**    
+    *  Linearly interpolates between this vector and vector v1 and 
+    *  places the result into this tuple:  this = (1-alpha)*this + alpha*v1.
+    *  @param v1  the first vector 
+    *  @param alpha  the alpha interpolation parameter   
+    */
+  public final void interpolate(GVector v1, double alpha)
+  {
+       if( v1.length != length )
+         throw new MismatchedSizeException(VecMathI18N.getString("GVector22"));
+
+       for(int i=0;i<length;i++) {
+         values[i] = (1-alpha)*values[i] + alpha*v1.values[i];
+       }
+  }
+    /**
+     * Creates a new object of the same class as this object.
+     *
+     * @return a clone of this instance.
+     * @exception OutOfMemoryError if there is not enough memory.
+     * @see java.lang.Cloneable
+     * @since vecmath 1.3
+     */
+    public Object clone() {
+       GVector v1 = null;
+       try {
+           v1 = (GVector)super.clone();
+       } catch (CloneNotSupportedException e) {
+           // this shouldn't happen, since we are Cloneable
+           throw new InternalError();
+       }
+
+       // Also need to clone array of values
+       v1.values = new double[length];
+       for (int i = 0; i < length; i++) {
+           v1.values[i] = values[i];
+       }
+
+       return v1;
+    }
+
+}
diff --git a/javax.vecmath/src/javax/vecmath/Matrix3d.java b/javax.vecmath/src/javax/vecmath/Matrix3d.java
new file mode 100644 (file)
index 0000000..c073e8b
--- /dev/null
@@ -0,0 +1,3321 @@
+/*
+ * $RCSfile: Matrix3d.java,v $
+ *
+ * Copyright 1996-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ * $Revision: 1.8 $
+ * $Date: 2008/02/28 20:18:50 $
+ * $State: Exp $
+ */
+
+package javax.vecmath;
+
+import java.lang.Math;
+
+/**
+ * A double precision floating point 3 by 3 matrix.
+ * Primarily to support 3D rotations.
+ *
+ */
+public class Matrix3d implements java.io.Serializable, Cloneable {
+
+    // Compatible with 1.1
+    static final long serialVersionUID = 6837536777072402710L;
+
+    /**
+     * The first matrix element in the first row.
+     */
+    public     double  m00;
+
+    /**
+     * The second matrix element in the first row.
+     */
+    public     double  m01;
+
+    /**
+     * The third matrix element in the first row.
+     */
+    public     double  m02;
+
+    /**
+     * The first matrix element in the second row.
+     */
+    public     double  m10;
+
+    /**
+     * The second matrix element in the second row.
+     */
+    public     double  m11;
+
+    /**
+     * The third matrix element in the second row.
+     */
+    public     double  m12;
+
+    /**
+     * The first matrix element in the third row.
+     */
+    public     double  m20;
+
+    /**
+     * The second matrix element in the third row.
+     */
+    public     double  m21;
+
+    /**
+     * The third matrix element in the third row.
+     */
+    public     double  m22;
+
+    //double[]    tmp = new double[9];  // scratch matrix
+    //double[]    tmp_rot = new double[9];  // scratch matrix
+    //double[]    tmp_scale = new double[3];  // scratch matrix
+    private static final double EPS = 1.110223024E-16;
+    private static final double ERR_EPS = 1.0E-8;
+    private static double xin,yin,zin,xout,yout,zout;
+
+    /**
+     * Constructs and initializes a Matrix3d from the specified nine values.
+     * @param m00 the [0][0] element
+     * @param m01 the [0][1] element
+     * @param m02 the [0][2] element
+     * @param m10 the [1][0] element
+     * @param m11 the [1][1] element
+     * @param m12 the [1][2] element
+     * @param m20 the [2][0] element
+     * @param m21 the [2][1] element
+     * @param m22 the [2][2] element
+     */
+    public Matrix3d(double m00, double m01, double m02,
+                   double m10, double m11, double m12,
+                   double m20, double m21, double m22)
+    {
+       this.m00 = m00;
+       this.m01 = m01;
+       this.m02 = m02;
+
+       this.m10 = m10;
+       this.m11 = m11;
+       this.m12 = m12;
+
+       this.m20 = m20;
+       this.m21 = m21;
+       this.m22 = m22;
+
+    }
+
+    /**
+     * Constructs and initializes a Matrix3d from the specified nine-
+     * element array.
+     * @param v the array of length 9 containing in order
+     */
+    public Matrix3d(double[] v)
+    {
+       this.m00 = v[0];
+       this.m01 = v[1];
+       this.m02 = v[2];
+
+       this.m10 = v[3];
+       this.m11 = v[4];
+       this.m12 = v[5];
+
+       this.m20 = v[6];
+       this.m21 = v[7];
+       this.m22 = v[8];
+
+    }
+
+   /**
+     *  Constructs a new matrix with the same values as the
+     *  Matrix3d parameter.
+     *  @param m1  the source matrix
+     */
+   public Matrix3d(Matrix3d m1)
+   {
+        this.m00 = m1.m00;
+        this.m01 = m1.m01;
+        this.m02 = m1.m02;
+
+        this.m10 = m1.m10;
+        this.m11 = m1.m11;
+        this.m12 = m1.m12;
+
+        this.m20 = m1.m20;
+        this.m21 = m1.m21;
+        this.m22 = m1.m22;
+
+   }
+
+   /**
+     *  Constructs a new matrix with the same values as the
+     *  Matrix3f parameter.
+     *  @param m1  the source matrix
+     */
+   public Matrix3d(Matrix3f m1)
+   {
+        this.m00 = m1.m00;
+        this.m01 = m1.m01;
+        this.m02 = m1.m02;
+
+        this.m10 = m1.m10;
+        this.m11 = m1.m11;
+        this.m12 = m1.m12;
+
+        this.m20 = m1.m20;
+        this.m21 = m1.m21;
+        this.m22 = m1.m22;
+
+   }
+
+    /**
+     * Constructs and initializes a Matrix3d to all zeros.
+     */
+    public Matrix3d()
+    {
+       this.m00 = 0.0;
+       this.m01 = 0.0;
+       this.m02 = 0.0;
+
+       this.m10 = 0.0;
+       this.m11 = 0.0;
+       this.m12 = 0.0;
+
+       this.m20 = 0.0;
+       this.m21 = 0.0;
+       this.m22 = 0.0;
+
+    }
+
+   /**
+     * Returns a string that contains the values of this Matrix3d.
+     * @return the String representation
+     */
+    public String toString() {
+      return
+       this.m00 + ", " + this.m01 + ", " + this.m02 + "\n" +
+       this.m10 + ", " + this.m11 + ", " + this.m12 + "\n" +
+       this.m20 + ", " + this.m21 + ", " + this.m22 + "\n";
+    }
+
+    /**
+     * Sets this Matrix3d to identity.
+     */
+    public final void setIdentity()
+    {
+       this.m00 = 1.0;
+       this.m01 = 0.0;
+       this.m02 = 0.0;
+
+       this.m10 = 0.0;
+       this.m11 = 1.0;
+       this.m12 = 0.0;
+
+       this.m20 = 0.0;
+       this.m21 = 0.0;
+       this.m22 = 1.0;
+    }
+
+   /**
+     * Sets the scale component of the current matrix by factoring
+     * out the current scale (by doing an SVD) and multiplying by
+     * the new scale.
+     * @param scale  the new scale amount
+     */
+    public final void setScale(double scale)
+    {
+
+       double[]    tmp_rot = new double[9];  // scratch matrix
+       double[]    tmp_scale = new double[3];  // scratch matrix
+
+       getScaleRotate(tmp_scale, tmp_rot);
+
+       this.m00 = tmp_rot[0] * scale;
+       this.m01 = tmp_rot[1] * scale;
+       this.m02 = tmp_rot[2] * scale;
+
+       this.m10 = tmp_rot[3] * scale;
+       this.m11 = tmp_rot[4] * scale;
+       this.m12 = tmp_rot[5] * scale;
+
+       this.m20 = tmp_rot[6] * scale;
+       this.m21 = tmp_rot[7] * scale;
+       this.m22 = tmp_rot[8] * scale;
+    }
+
+    /**
+     * Sets the specified element of this matrix3f to the value provided.
+     * @param row the row number to be modified (zero indexed)
+     * @param column the column number to be modified (zero indexed)
+     * @param value the new value
+     */
+    public final void setElement(int row, int column, double value)
+    {
+       switch (row)
+         {
+         case 0:
+           switch(column)
+             {
+             case 0:
+               this.m00 = value;
+               break;
+             case 1:
+               this.m01 = value;
+               break;
+             case 2:
+               this.m02 = value;
+               break;
+             default:
+               throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3d0"));
+             }
+           break;
+
+         case 1:
+           switch(column)
+             {
+             case 0:
+               this.m10 = value;
+               break;
+             case 1:
+               this.m11 = value;
+               break;
+             case 2:
+               this.m12 = value;
+               break;
+             default:
+               throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3d0"));
+             }
+           break;
+
+
+         case 2:
+           switch(column)
+             {
+             case 0:
+               this.m20 = value;
+               break;
+             case 1:
+               this.m21 = value;
+               break;
+             case 2:
+               this.m22 = value;
+               break;
+             default:
+               throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3d0"));
+             }
+           break;
+
+         default:
+               throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3d0"));
+         }
+    }
+
+    /**
+     * Retrieves the value at the specified row and column of the specified
+     * matrix.
+     * @param row the row number to be retrieved (zero indexed)
+     * @param column the column number to be retrieved (zero indexed)
+     * @return the value at the indexed element.
+     */
+    public final double getElement(int row, int column)
+    {
+       switch (row)
+         {
+         case 0:
+           switch(column)
+             {
+             case 0:
+               return(this.m00);
+             case 1:
+               return(this.m01);
+             case 2:
+               return(this.m02);
+             default:
+               break;
+             }
+           break;
+         case 1:
+           switch(column)
+             {
+             case 0:
+               return(this.m10);
+             case 1:
+               return(this.m11);
+             case 2:
+               return(this.m12);
+             default:
+               break;
+             }
+           break;
+
+         case 2:
+           switch(column)
+             {
+             case 0:
+               return(this.m20);
+             case 1:
+               return(this.m21);
+             case 2:
+               return(this.m22);
+             default:
+               break;
+             }
+           break;
+
+         default:
+           break;
+         }
+
+       throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3d1"));
+    }
+
+    /**
+     * Copies the matrix values in the specified row into the vector parameter.
+     * @param row  the matrix row
+     * @param v    the vector into which the matrix row values will be copied
+     */
+    public final void getRow(int row, Vector3d v) {
+        if( row == 0 ) {
+           v.x = m00;
+           v.y = m01;
+           v.z = m02;
+        } else if(row == 1) {
+           v.x = m10;
+           v.y = m11;
+           v.z = m12;
+        } else if(row == 2) {
+           v.x = m20;
+           v.y = m21;
+           v.z = m22;
+        } else {
+          throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3d2"));
+        }
+
+    }
+
+    /**
+     * Copies the matrix values in the specified row into the array parameter.
+     * @param row  the matrix row
+     * @param v    the array into which the matrix row values will be copied
+     */
+    public final void getRow(int row, double v[]) {
+        if( row == 0 ) {
+           v[0] = m00;
+           v[1] = m01;
+           v[2] = m02;
+        } else if(row == 1) {
+           v[0] = m10;
+           v[1] = m11;
+           v[2] = m12;
+        } else if(row == 2) {
+           v[0] = m20;
+           v[1] = m21;
+           v[2] = m22;
+        } else {
+          throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3d2"));
+        }
+
+    }
+
+    /**
+     * Copies the matrix values in the specified column into the vector
+     * parameter.
+     * @param column  the matrix column
+     * @param v    the vector into which the matrix row values will be copied
+     */
+    public final void getColumn(int column, Vector3d v) {
+        if( column == 0 ) {
+           v.x = m00;
+           v.y = m10;
+           v.z = m20;
+        } else if(column == 1) {
+           v.x = m01;
+           v.y = m11;
+           v.z = m21;
+        }else if(column == 2){
+           v.x = m02;
+           v.y = m12;
+           v.z = m22;
+        } else {
+           throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3d4"));
+        }
+
+    }
+
+    /**
+     * Copies the matrix values in the specified column into the array
+     * parameter.
+     * @param column  the matrix column
+     * @param v    the array into which the matrix row values will be copied
+     */
+    public final void getColumn(int column, double v[]) {
+        if( column == 0 ) {
+           v[0] = m00;
+           v[1] = m10;
+           v[2] = m20;
+        } else if(column == 1) {
+           v[0] = m01;
+           v[1] = m11;
+           v[2] = m21;
+        }else if(column == 2) {
+           v[0] = m02;
+           v[1] = m12;
+           v[2] = m22;
+        }else {
+          throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3d4"));
+        }
+
+    }
+
+
+    /**
+     * Sets the specified row of this matrix3d to the 4 values provided.
+     * @param row the row number to be modified (zero indexed)
+     * @param x the first column element
+     * @param y the second column element
+     * @param z the third column element
+     */
+    public final void setRow(int row, double x, double y, double z)
+    {
+       switch (row) {
+       case 0:
+           this.m00 = x;
+           this.m01 = y;
+           this.m02 = z;
+           break;
+
+       case 1:
+           this.m10 = x;
+           this.m11 = y;
+           this.m12 = z;
+           break;
+
+       case 2:
+           this.m20 = x;
+           this.m21 = y;
+           this.m22 = z;
+           break;
+
+       default:
+         throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3d6"));
+       }
+    }
+
+    /**
+     * Sets the specified row of this matrix3d to the Vector provided.
+     * @param row the row number to be modified (zero indexed)
+     * @param v the replacement row
+     */
+    public final void setRow(int row, Vector3d v)
+    {
+       switch (row) {
+       case 0:
+           this.m00 = v.x;
+           this.m01 = v.y;
+           this.m02 = v.z;
+           break;
+
+       case 1:
+           this.m10 = v.x;
+           this.m11 = v.y;
+           this.m12 = v.z;
+           break;
+
+       case 2:
+           this.m20 = v.x;
+           this.m21 = v.y;
+           this.m22 = v.z;
+           break;
+
+       default:
+            throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3d6"));
+       }
+    }
+
+    /**
+     * Sets the specified row of this matrix3d to the three values provided.
+     * @param row the row number to be modified (zero indexed)
+     * @param v the replacement row
+     */
+    public final void setRow(int row, double v[])
+    {
+       switch (row) {
+       case 0:
+           this.m00 = v[0];
+           this.m01 = v[1];
+           this.m02 = v[2];
+           break;
+
+       case 1:
+           this.m10 = v[0];
+           this.m11 = v[1];
+           this.m12 = v[2];
+           break;
+
+       case 2:
+           this.m20 = v[0];
+           this.m21 = v[1];
+           this.m22 = v[2];
+           break;
+
+       default:
+            throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3d6"));
+       }
+    }
+
+    /**
+     * Sets the specified column of this matrix3d to the three values provided.
+     * @param column the column number to be modified (zero indexed)
+     * @param x the first row element
+     * @param y the second row element
+     * @param z the third row element
+     */
+    public final void setColumn(int column, double x, double y, double z)
+    {
+       switch (column) {
+       case 0:
+           this.m00 = x;
+           this.m10 = y;
+           this.m20 = z;
+           break;
+
+       case 1:
+           this.m01 = x;
+           this.m11 = y;
+           this.m21 = z;
+           break;
+
+       case 2:
+           this.m02 = x;
+           this.m12 = y;
+           this.m22 = z;
+           break;
+
+       default:
+            throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3d9"));
+       }
+    }
+
+    /**
+     * Sets the specified column of this matrix3d to the vector provided.
+     * @param column the column number to be modified (zero indexed)
+     * @param v the replacement column
+     */
+    public final void setColumn(int column, Vector3d v)
+    {
+       switch (column) {
+       case 0:
+           this.m00 = v.x;
+           this.m10 = v.y;
+           this.m20 = v.z;
+           break;
+
+       case 1:
+           this.m01 = v.x;
+           this.m11 = v.y;
+           this.m21 = v.z;
+           break;
+
+       case 2:
+           this.m02 = v.x;
+           this.m12 = v.y;
+           this.m22 = v.z;
+           break;
+
+       default:
+            throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3d9"));
+       }
+    }
+
+    /**
+     * Sets the specified column of this matrix3d to the three values provided.
+     * @param column the column number to be modified (zero indexed)
+     * @param v the replacement column
+     */
+    public final void setColumn(int column, double v[])
+    {
+       switch (column) {
+       case 0:
+           this.m00 = v[0];
+           this.m10 = v[1];
+           this.m20 = v[2];
+           break;
+
+       case 1:
+           this.m01 = v[0];
+           this.m11 = v[1];
+           this.m21 = v[2];
+           break;
+
+       case 2:
+           this.m02 = v[0];
+           this.m12 = v[1];
+           this.m22 = v[2];
+           break;
+
+       default:
+            throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3d9"));
+       }
+    }
+
+   /**
+     * Performs an SVD normalization of this matrix to calculate
+     * and return the uniform scale factor. If the matrix has non-uniform
+     * scale factors, the largest of the x, y, and z scale factors will
+     * be returned. This matrix is not modified.
+     * @return  the scale factor of this matrix
+     */
+    public final double getScale()
+    {
+
+       double[]    tmp_scale = new double[3];  // scratch matrix
+       double[]    tmp_rot = new double[9];  // scratch matrix
+       getScaleRotate(tmp_scale, tmp_rot);
+
+        return( max3(tmp_scale) );
+
+    }
+
+   /**
+     *  Adds a scalar to each component of this matrix.
+     *  @param scalar  the scalar adder
+     */
+    public final void add(double scalar)
+    {
+        m00 += scalar;
+        m01 += scalar;
+        m02 += scalar;
+
+        m10 += scalar;
+        m11 += scalar;
+        m12 += scalar;
+
+        m20 += scalar;
+        m21 += scalar;
+        m22 += scalar;
+
+    }
+
+   /**
+     *  Adds a scalar to each component of the matrix m1 and places
+     *  the result into this.  Matrix m1 is not modified.
+     *  @param scalar  the scalar adder
+     *  @param m1  the original matrix values
+     */
+    public final void add(double scalar, Matrix3d m1)
+    {
+       this.m00 = m1.m00 + scalar;
+       this.m01 = m1.m01 + scalar;
+       this.m02 = m1.m02 + scalar;
+
+       this.m10 = m1.m10 + scalar;
+       this.m11 = m1.m11 + scalar;
+       this.m12 = m1.m12 + scalar;
+
+       this.m20 = m1.m20 + scalar;
+       this.m21 = m1.m21 + scalar;
+       this.m22 = m1.m22 + scalar;
+    }
+
+    /**
+     * Sets the value of this matrix to the matrix sum of matrices m1 and m2.
+     * @param m1 the first matrix
+     * @param m2 the second matrix
+     */
+    public final void add(Matrix3d m1, Matrix3d m2)
+    {
+       this.m00 = m1.m00 + m2.m00;
+       this.m01 = m1.m01 + m2.m01;
+       this.m02 = m1.m02 + m2.m02;
+
+       this.m10 = m1.m10 + m2.m10;
+       this.m11 = m1.m11 + m2.m11;
+       this.m12 = m1.m12 + m2.m12;
+
+       this.m20 = m1.m20 + m2.m20;
+       this.m21 = m1.m21 + m2.m21;
+       this.m22 = m1.m22 + m2.m22;
+    }
+
+    /**
+     * Sets the value of this matrix to the sum of itself and matrix m1.
+     * @param m1 the other matrix
+     */
+    public final void add(Matrix3d m1)
+    {
+        this.m00 += m1.m00;
+        this.m01 += m1.m01;
+        this.m02 += m1.m02;
+
+        this.m10 += m1.m10;
+        this.m11 += m1.m11;
+        this.m12 += m1.m12;
+
+        this.m20 += m1.m20;
+        this.m21 += m1.m21;
+        this.m22 += m1.m22;
+    }
+
+    /**
+     * Sets the value of this matrix to the matrix difference
+     * of matrices m1 and m2.
+     * @param m1 the first matrix
+     * @param m2 the second matrix
+     */
+    public final void sub(Matrix3d m1, Matrix3d m2)
+    {
+       this.m00 = m1.m00 - m2.m00;
+       this.m01 = m1.m01 - m2.m01;
+       this.m02 = m1.m02 - m2.m02;
+
+       this.m10 = m1.m10 - m2.m10;
+       this.m11 = m1.m11 - m2.m11;
+       this.m12 = m1.m12 - m2.m12;
+
+       this.m20 = m1.m20 - m2.m20;
+       this.m21 = m1.m21 - m2.m21;
+       this.m22 = m1.m22 - m2.m22;
+    }
+
+    /**
+     * Sets the value of this matrix to the matrix difference of itself and
+     * matrix m1 (this = this - m1).
+     * @param m1 the other matrix
+     */
+    public final void sub(Matrix3d m1)
+    {
+        this.m00 -= m1.m00;
+        this.m01 -= m1.m01;
+        this.m02 -= m1.m02;
+
+        this.m10 -= m1.m10;
+        this.m11 -= m1.m11;
+        this.m12 -= m1.m12;
+
+        this.m20 -= m1.m20;
+        this.m21 -= m1.m21;
+        this.m22 -= m1.m22;
+    }
+
+    /**
+     * Sets the value of this matrix to its transpose.
+     */
+    public final void transpose()
+    {
+       double temp;
+
+       temp = this.m10;
+       this.m10 = this.m01;
+       this.m01 = temp;
+
+       temp = this.m20;
+       this.m20 = this.m02;
+       this.m02 = temp;
+
+       temp = this.m21;
+       this.m21 = this.m12;
+       this.m12 = temp;
+    }
+
+    /**
+     * Sets the value of this matrix to the transpose of the argument matrix.
+     * @param m1 the matrix to be transposed
+     */
+    public final void transpose(Matrix3d m1)
+    {
+       if (this != m1) {
+           this.m00 = m1.m00;
+           this.m01 = m1.m10;
+           this.m02 = m1.m20;
+
+           this.m10 = m1.m01;
+           this.m11 = m1.m11;
+           this.m12 = m1.m21;
+
+           this.m20 = m1.m02;
+           this.m21 = m1.m12;
+           this.m22 = m1.m22;
+       } else
+           this.transpose();
+    }
+
+    /**
+     * Sets the value of this matrix to the matrix conversion of the
+     * double precision quaternion argument.
+     * @param q1 the quaternion to be converted
+     */
+    public final void set(Quat4d q1)
+    {
+       this.m00 = (1.0 - 2.0*q1.y*q1.y - 2.0*q1.z*q1.z);
+       this.m10 = (2.0*(q1.x*q1.y + q1.w*q1.z));
+       this.m20 = (2.0*(q1.x*q1.z - q1.w*q1.y));
+
+       this.m01 = (2.0*(q1.x*q1.y - q1.w*q1.z));
+       this.m11 = (1.0 - 2.0*q1.x*q1.x - 2.0*q1.z*q1.z);
+       this.m21 = (2.0*(q1.y*q1.z + q1.w*q1.x));
+
+       this.m02 = (2.0*(q1.x*q1.z + q1.w*q1.y));
+       this.m12 = (2.0*(q1.y*q1.z - q1.w*q1.x));
+       this.m22 = (1.0 - 2.0*q1.x*q1.x - 2.0*q1.y*q1.y);
+    }
+
+    /**
+     * Sets the value of this matrix to the matrix conversion of the
+     * double precision axis and angle argument.
+     * @param a1 the axis and angle to be converted
+     */
+    public final void set(AxisAngle4d a1)
+    {
+      double mag = Math.sqrt( a1.x*a1.x + a1.y*a1.y + a1.z*a1.z);
+
+      if( mag < EPS ) {
+       m00 = 1.0;
+       m01 = 0.0;
+       m02 = 0.0;
+
+       m10 = 0.0;
+       m11 = 1.0;
+       m12 = 0.0;
+
+       m20 = 0.0;
+       m21 = 0.0;
+       m22 = 1.0;
+      } else {
+       mag = 1.0/mag;
+        double ax = a1.x*mag;
+        double ay = a1.y*mag;
+        double az = a1.z*mag;
+
+        double sinTheta = Math.sin(a1.angle);
+        double cosTheta = Math.cos(a1.angle);
+        double t = 1.0 - cosTheta;
+
+        double xz = ax * az;
+        double xy = ax * ay;
+        double yz = ay * az;
+
+        m00 = t * ax * ax + cosTheta;
+        m01 = t * xy - sinTheta * az;
+        m02 = t * xz + sinTheta * ay;
+
+        m10 = t * xy + sinTheta * az;
+        m11 = t * ay * ay + cosTheta;
+        m12 = t * yz - sinTheta * ax;
+
+        m20 = t * xz - sinTheta * ay;
+        m21 = t * yz + sinTheta * ax;
+        m22 = t * az * az + cosTheta;
+      }
+    }
+
+    /**
+     * Sets the value of this matrix to the matrix conversion of the
+     * single precision quaternion argument.
+     * @param q1 the quaternion to be converted
+     */
+    public final void set(Quat4f q1)
+    {
+       this.m00 = (1.0 - 2.0*q1.y*q1.y - 2.0*q1.z*q1.z);
+       this.m10 = (2.0*(q1.x*q1.y + q1.w*q1.z));
+       this.m20 = (2.0*(q1.x*q1.z - q1.w*q1.y));
+
+       this.m01 = (2.0*(q1.x*q1.y - q1.w*q1.z));
+       this.m11 = (1.0 - 2.0*q1.x*q1.x - 2.0*q1.z*q1.z);
+       this.m21 = (2.0*(q1.y*q1.z + q1.w*q1.x));
+
+       this.m02 = (2.0*(q1.x*q1.z + q1.w*q1.y));
+       this.m12 = (2.0*(q1.y*q1.z - q1.w*q1.x));
+       this.m22 = (1.0 - 2.0*q1.x*q1.x - 2.0*q1.y*q1.y);
+    }
+
+    /**
+     * Sets the value of this matrix to the matrix conversion of the
+     * single precision axis and angle argument.
+     * @param a1 the axis and angle to be converted
+     */
+    public final void set(AxisAngle4f a1)
+    {
+      double mag = Math.sqrt( a1.x*a1.x + a1.y*a1.y + a1.z*a1.z);
+      if( mag < EPS ) {
+       m00 = 1.0;
+       m01 = 0.0;
+       m02 = 0.0;
+
+       m10 = 0.0;
+       m11 = 1.0;
+       m12 = 0.0;
+
+       m20 = 0.0;
+       m21 = 0.0;
+       m22 = 1.0;
+      } else {
+       mag = 1.0/mag;
+        double ax = a1.x*mag;
+        double ay = a1.y*mag;
+        double az = a1.z*mag;
+        double sinTheta = Math.sin(a1.angle);
+        double cosTheta = Math.cos(a1.angle);
+        double t = 1.0 - cosTheta;
+
+        double xz = ax * az;
+        double xy = ax * ay;
+        double yz = ay * az;
+
+        m00 = t * ax * ax + cosTheta;
+        m01 = t * xy - sinTheta * az;
+        m02 = t * xz + sinTheta * ay;
+
+        m10 = t * xy + sinTheta * az;
+        m11 = t * ay * ay + cosTheta;
+        m12 = t * yz - sinTheta * ax;
+
+        m20 = t * xz - sinTheta * ay;
+        m21 = t * yz + sinTheta * ax;
+        m22 = t * az * az + cosTheta;
+      }
+    }
+
+    /**
+     * Sets the value of this matrix to the double value of the Matrix3f
+     * argument.
+     * @param m1 the matrix3d to be converted to double
+     */
+    public final void set(Matrix3f m1)
+    {
+       this.m00 = m1.m00;
+       this.m01 = m1.m01;
+       this.m02 = m1.m02;
+
+       this.m10 = m1.m10;
+       this.m11 = m1.m11;
+       this.m12 = m1.m12;
+
+       this.m20 = m1.m20;
+       this.m21 = m1.m21;
+       this.m22 = m1.m22;
+    }
+
+    /**
+     * Sets the value of this matrix to the value of the Matrix3d
+     * argument.
+     * @param m1 the source matrix3d
+     */
+    public final void set(Matrix3d m1)
+    {
+        this.m00 = m1.m00;
+        this.m01 = m1.m01;
+        this.m02 = m1.m02;
+
+        this.m10 = m1.m10;
+        this.m11 = m1.m11;
+        this.m12 = m1.m12;
+
+        this.m20 = m1.m20;
+        this.m21 = m1.m21;
+        this.m22 = m1.m22;
+    }
+
+    /**
+     *  Sets the values in this Matrix3d equal to the row-major
+     *  array parameter (ie, the first three elements of the
+     *  array will be copied into the first row of this matrix, etc.).
+     *  @param m  the double precision array of length 9
+     */
+    public final void set(double[] m)
+    {
+       m00 = m[0];
+       m01 = m[1];
+       m02 = m[2];
+
+       m10 = m[3];
+       m11 = m[4];
+       m12 = m[5];
+
+       m20 = m[6];
+       m21 = m[7];
+       m22 = m[8];
+
+    }
+
+    /**
+     * Sets the value of this matrix to the matrix inverse
+     * of the passed matrix m1.
+     * @param m1 the matrix to be inverted
+     */
+    public final void invert(Matrix3d m1)
+    {
+         invertGeneral( m1 );
+    }
+
+    /**
+     * Inverts this matrix in place.
+     */
+    public final void invert()
+    {
+         invertGeneral( this );
+    }
+
+    /**
+     * General invert routine.  Inverts m1 and places the result in "this".
+     * Note that this routine handles both the "this" version and the
+     * non-"this" version.
+     *
+     * Also note that since this routine is slow anyway, we won't worry
+     * about allocating a little bit of garbage.
+     */
+    private final void invertGeneral(Matrix3d  m1) {
+       double result[] = new double[9];
+       int row_perm[] = new int[3];
+       int i, r, c;
+       double[]    tmp = new double[9];  // scratch matrix
+
+       // Use LU decomposition and backsubstitution code specifically
+       // for floating-point 3x3 matrices.
+
+       // Copy source matrix to t1tmp
+        tmp[0] = m1.m00;
+        tmp[1] = m1.m01;
+        tmp[2] = m1.m02;
+
+        tmp[3] = m1.m10;
+        tmp[4] = m1.m11;
+        tmp[5] = m1.m12;
+
+        tmp[6] = m1.m20;
+        tmp[7] = m1.m21;
+        tmp[8] = m1.m22;
+
+
+       // Calculate LU decomposition: Is the matrix singular?
+       if (!luDecomposition(tmp, row_perm)) {
+           // Matrix has no inverse
+           throw new SingularMatrixException(VecMathI18N.getString("Matrix3d12"));
+       }
+
+       // Perform back substitution on the identity matrix
+        for(i=0;i<9;i++) result[i] = 0.0;
+        result[0] = 1.0; result[4] = 1.0; result[8] = 1.0;
+       luBacksubstitution(tmp, row_perm, result);
+
+        this.m00 = result[0];
+        this.m01 = result[1];
+        this.m02 = result[2];
+
+        this.m10 = result[3];
+        this.m11 = result[4];
+        this.m12 = result[5];
+
+        this.m20 = result[6];
+        this.m21 = result[7];
+        this.m22 = result[8];
+
+    }
+
+    /**
+     * Given a 3x3 array "matrix0", this function replaces it with the
+     * LU decomposition of a row-wise permutation of itself.  The input
+     * parameters are "matrix0" and "dimen".  The array "matrix0" is also
+     * an output parameter.  The vector "row_perm[3]" is an output
+     * parameter that contains the row permutations resulting from partial
+     * pivoting.  The output parameter "even_row_xchg" is 1 when the
+     * number of row exchanges is even, or -1 otherwise.  Assumes data
+     * type is always double.
+     *
+     * This function is similar to luDecomposition, except that it
+     * is tuned specifically for 3x3 matrices.
+     *
+     * @return true if the matrix is nonsingular, or false otherwise.
+     */
+    //
+    // Reference: Press, Flannery, Teukolsky, Vetterling,
+    //       _Numerical_Recipes_in_C_, Cambridge University Press,
+    //       1988, pp 40-45.
+    //
+    static boolean luDecomposition(double[] matrix0,
+                                  int[] row_perm) {
+
+       double row_scale[] = new double[3];
+
+       // Determine implicit scaling information by looping over rows
+       {
+           int i, j;
+           int ptr, rs;
+           double big, temp;
+
+           ptr = 0;
+           rs = 0;
+
+           // For each row ...
+           i = 3;
+           while (i-- != 0) {
+               big = 0.0;
+
+               // For each column, find the largest element in the row
+               j = 3;
+               while (j-- != 0) {
+                   temp = matrix0[ptr++];
+                   temp = Math.abs(temp);
+                   if (temp > big) {
+                       big = temp;
+                   }
+               }
+
+               // Is the matrix singular?
+               if (big == 0.0) {
+                   return false;
+               }
+               row_scale[rs++] = 1.0 / big;
+           }
+       }
+
+       {
+           int j;
+           int mtx;
+
+           mtx = 0;
+
+           // For all columns, execute Crout's method
+           for (j = 0; j < 3; j++) {
+               int i, imax, k;
+               int target, p1, p2;
+               double sum, big, temp;
+
+               // Determine elements of upper diagonal matrix U
+               for (i = 0; i < j; i++) {
+                   target = mtx + (3*i) + j;
+                   sum = matrix0[target];
+                   k = i;
+                   p1 = mtx + (3*i);
+                   p2 = mtx + j;
+                   while (k-- != 0) {
+                       sum -= matrix0[p1] * matrix0[p2];
+                       p1++;
+                       p2 += 3;
+                   }
+                   matrix0[target] = sum;
+               }
+
+               // Search for largest pivot element and calculate
+               // intermediate elements of lower diagonal matrix L.
+               big = 0.0;
+               imax = -1;
+               for (i = j; i < 3; i++) {
+                   target = mtx + (3*i) + j;
+                   sum = matrix0[target];
+                   k = j;
+                   p1 = mtx + (3*i);
+                   p2 = mtx + j;
+                   while (k-- != 0) {
+                       sum -= matrix0[p1] * matrix0[p2];
+                       p1++;
+                       p2 += 3;
+                   }
+                   matrix0[target] = sum;
+
+                   // Is this the best pivot so far?
+                   if ((temp = row_scale[i] * Math.abs(sum)) >= big) {
+                       big = temp;
+                       imax = i;
+                   }
+               }
+
+               if (imax < 0) {
+                   throw new RuntimeException(VecMathI18N.getString("Matrix3d13"));
+               }
+
+               // Is a row exchange necessary?
+               if (j != imax) {
+                   // Yes: exchange rows
+                   k = 3;
+                   p1 = mtx + (3*imax);
+                   p2 = mtx + (3*j);
+                   while (k-- != 0) {
+                       temp = matrix0[p1];
+                       matrix0[p1++] = matrix0[p2];
+                       matrix0[p2++] = temp;
+                   }
+
+                   // Record change in scale factor
+                   row_scale[imax] = row_scale[j];
+               }
+
+               // Record row permutation
+               row_perm[j] = imax;
+
+               // Is the matrix singular
+               if (matrix0[(mtx + (3*j) + j)] == 0.0) {
+                   return false;
+               }
+
+               // Divide elements of lower diagonal matrix L by pivot
+               if (j != (3-1)) {
+                   temp = 1.0 / (matrix0[(mtx + (3*j) + j)]);
+                   target = mtx + (3*(j+1)) + j;
+                   i = 2 - j;
+                   while (i-- != 0) {
+                       matrix0[target] *= temp;
+                       target += 3;
+                   }
+               }
+           }
+       }
+
+       return true;
+    }
+
+    /**
+     * Solves a set of linear equations.  The input parameters "matrix1",
+     * and "row_perm" come from luDecompostionD3x3 and do not change
+     * here.  The parameter "matrix2" is a set of column vectors assembled
+     * into a 3x3 matrix of floating-point values.  The procedure takes each
+     * column of "matrix2" in turn and treats it as the right-hand side of the
+     * matrix equation Ax = LUx = b.  The solution vector replaces the
+     * original column of the matrix.
+     *
+     * If "matrix2" is the identity matrix, the procedure replaces its contents
+     * with the inverse of the matrix from which "matrix1" was originally
+     * derived.
+     */
+    //
+    // Reference: Press, Flannery, Teukolsky, Vetterling,
+    //       _Numerical_Recipes_in_C_, Cambridge University Press,
+    //       1988, pp 44-45.
+    //
+    static void luBacksubstitution(double[] matrix1,
+                                  int[] row_perm,
+                                  double[] matrix2) {
+
+       int i, ii, ip, j, k;
+       int rp;
+       int cv, rv;
+
+       //      rp = row_perm;
+       rp = 0;
+
+       // For each column vector of matrix2 ...
+       for (k = 0; k < 3; k++) {
+           //      cv = &(matrix2[0][k]);
+           cv = k;
+           ii = -1;
+
+           // Forward substitution
+           for (i = 0; i < 3; i++) {
+               double sum;
+
+               ip = row_perm[rp+i];
+               sum = matrix2[cv+3*ip];
+               matrix2[cv+3*ip] = matrix2[cv+3*i];
+               if (ii >= 0) {
+                   //              rv = &(matrix1[i][0]);
+                   rv = i*3;
+                   for (j = ii; j <= i-1; j++) {
+                       sum -= matrix1[rv+j] * matrix2[cv+3*j];
+                   }
+               }
+               else if (sum != 0.0) {
+                   ii = i;
+               }
+               matrix2[cv+3*i] = sum;
+           }
+
+           // Backsubstitution
+           //      rv = &(matrix1[3][0]);
+           rv = 2*3;
+           matrix2[cv+3*2] /= matrix1[rv+2];
+
+           rv -= 3;
+           matrix2[cv+3*1] = (matrix2[cv+3*1] -
+                           matrix1[rv+2] * matrix2[cv+3*2]) / matrix1[rv+1];
+
+           rv -= 3;
+           matrix2[cv+4*0] = (matrix2[cv+3*0] -
+                           matrix1[rv+1] * matrix2[cv+3*1] -
+                           matrix1[rv+2] * matrix2[cv+3*2]) / matrix1[rv+0];
+
+       }
+    }
+
+    /**
+     * Computes the determinant of this matrix.
+     * @return the determinant of the matrix
+     */
+    public final double determinant()
+    {
+       double total;
+
+       total =  this.m00*(this.m11*this.m22 - this.m12*this.m21)
+              + this.m01*(this.m12*this.m20 - this.m10*this.m22)
+              + this.m02*(this.m10*this.m21 - this.m11*this.m20);
+       return total;
+    }
+
+    /**
+     * Sets the value of this matrix to a scale matrix with
+     * the passed scale amount.
+     * @param scale the scale factor for the matrix
+     */
+    public final void set(double scale)
+    {
+       this.m00 = scale;
+       this.m01 = 0.0;
+       this.m02 = 0.0;
+
+       this.m10 = 0.0;
+       this.m11 = scale;
+       this.m12 = 0.0;
+
+       this.m20 = 0.0;
+       this.m21 = 0.0;
+       this.m22 = scale;
+    }
+
+    /**
+     * Sets the value of this matrix to a counter clockwise rotation
+     * about the x axis.
+     * @param angle the angle to rotate about the X axis in radians
+     */
+    public final void rotX(double angle)
+    {
+       double  sinAngle, cosAngle;
+
+       sinAngle = Math.sin(angle);
+       cosAngle = Math.cos(angle);
+
+       this.m00 = 1.0;
+       this.m01 = 0.0;
+       this.m02 = 0.0;
+
+       this.m10 = 0.0;
+       this.m11 = cosAngle;
+       this.m12 = -sinAngle;
+
+       this.m20 = 0.0;
+       this.m21 = sinAngle;
+       this.m22 = cosAngle;
+    }
+
+    /**
+     * Sets the value of this matrix to a counter clockwise rotation
+     * about the y axis.
+     * @param angle the angle to rotate about the Y axis in radians
+     */
+    public final void rotY(double angle)
+    {
+       double  sinAngle, cosAngle;
+
+       sinAngle = Math.sin(angle);
+       cosAngle = Math.cos(angle);
+
+       this.m00 = cosAngle;
+       this.m01 = 0.0;
+       this.m02 = sinAngle;
+
+       this.m10 = 0.0;
+       this.m11 = 1.0;
+       this.m12 = 0.0;
+
+       this.m20 = -sinAngle;
+       this.m21 = 0.0;
+       this.m22 = cosAngle;
+    }
+
+    /**
+     * Sets the value of this matrix to a counter clockwise rotation
+     * about the z axis.
+     * @param angle the angle to rotate about the Z axis in radians
+     */
+    public final void rotZ(double angle)
+    {
+       double  sinAngle, cosAngle;
+
+       sinAngle = Math.sin(angle);
+       cosAngle = Math.cos(angle);
+
+       this.m00 = cosAngle;
+       this.m01 = -sinAngle;
+       this.m02 = 0.0;
+
+       this.m10 = sinAngle;
+       this.m11 = cosAngle;
+       this.m12 = 0.0;
+
+       this.m20 = 0.0;
+       this.m21 = 0.0;
+       this.m22 = 1.0;
+    }
+
+   /**
+     * Multiplies each element of this matrix by a scalar.
+     * @param scalar  The scalar multiplier.
+     */
+    public final void mul(double scalar)
+    {
+       m00 *= scalar;
+       m01 *= scalar;
+       m02 *= scalar;
+
+       m10 *= scalar;
+       m11 *= scalar;
+       m12 *= scalar;
+
+       m20 *= scalar;
+       m21 *= scalar;
+       m22 *= scalar;
+
+    }
+
+   /**
+     * Multiplies each element of matrix m1 by a scalar and places
+     * the result into this.  Matrix m1 is not modified.
+     * @param scalar  the scalar multiplier
+     * @param m1  the original matrix
+     */
+    public final void mul(double scalar, Matrix3d m1)
+    {
+        this.m00 = scalar * m1.m00;
+        this.m01 = scalar * m1.m01;
+        this.m02 = scalar * m1.m02;
+
+        this.m10 = scalar * m1.m10;
+        this.m11 = scalar * m1.m11;
+        this.m12 = scalar * m1.m12;
+
+        this.m20 = scalar * m1.m20;
+        this.m21 = scalar * m1.m21;
+        this.m22 = scalar * m1.m22;
+
+    }
+
+   /**
+     * Sets the value of this matrix to the result of multiplying itself
+     * with matrix m1.
+     * @param m1 the other matrix
+     */
+    public final void mul(Matrix3d m1)
+    {
+            double      m00, m01, m02,
+                        m10, m11, m12,
+                        m20, m21, m22;
+
+            m00 = this.m00*m1.m00 + this.m01*m1.m10 + this.m02*m1.m20;
+            m01 = this.m00*m1.m01 + this.m01*m1.m11 + this.m02*m1.m21;
+            m02 = this.m00*m1.m02 + this.m01*m1.m12 + this.m02*m1.m22;
+
+            m10 = this.m10*m1.m00 + this.m11*m1.m10 + this.m12*m1.m20;
+            m11 = this.m10*m1.m01 + this.m11*m1.m11 + this.m12*m1.m21;
+            m12 = this.m10*m1.m02 + this.m11*m1.m12 + this.m12*m1.m22;
+
+            m20 = this.m20*m1.m00 + this.m21*m1.m10 + this.m22*m1.m20;
+            m21 = this.m20*m1.m01 + this.m21*m1.m11 + this.m22*m1.m21;
+            m22 = this.m20*m1.m02 + this.m21*m1.m12 + this.m22*m1.m22;
+
+            this.m00 = m00; this.m01 = m01; this.m02 = m02;
+            this.m10 = m10; this.m11 = m11; this.m12 = m12;
+            this.m20 = m20; this.m21 = m21; this.m22 = m22;
+    }
+
+    /**
+     * Sets the value of this matrix to the result of multiplying
+     * the two argument matrices together.
+     * @param m1 the first matrix
+     * @param m2 the second matrix
+     */
+    public final void mul(Matrix3d m1, Matrix3d m2)
+    {
+       if (this != m1 && this != m2) {
+            this.m00 = m1.m00*m2.m00 + m1.m01*m2.m10 + m1.m02*m2.m20;
+            this.m01 = m1.m00*m2.m01 + m1.m01*m2.m11 + m1.m02*m2.m21;
+            this.m02 = m1.m00*m2.m02 + m1.m01*m2.m12 + m1.m02*m2.m22;
+
+            this.m10 = m1.m10*m2.m00 + m1.m11*m2.m10 + m1.m12*m2.m20;
+            this.m11 = m1.m10*m2.m01 + m1.m11*m2.m11 + m1.m12*m2.m21;
+            this.m12 = m1.m10*m2.m02 + m1.m11*m2.m12 + m1.m12*m2.m22;
+
+            this.m20 = m1.m20*m2.m00 + m1.m21*m2.m10 + m1.m22*m2.m20;
+            this.m21 = m1.m20*m2.m01 + m1.m21*m2.m11 + m1.m22*m2.m21;
+            this.m22 = m1.m20*m2.m02 + m1.m21*m2.m12 + m1.m22*m2.m22;
+       } else {
+           double      m00, m01, m02,
+                       m10, m11, m12,
+               m20, m21, m22;  // vars for temp result matrix
+
+            m00 = m1.m00*m2.m00 + m1.m01*m2.m10 + m1.m02*m2.m20;
+            m01 = m1.m00*m2.m01 + m1.m01*m2.m11 + m1.m02*m2.m21;
+            m02 = m1.m00*m2.m02 + m1.m01*m2.m12 + m1.m02*m2.m22;
+
+            m10 = m1.m10*m2.m00 + m1.m11*m2.m10 + m1.m12*m2.m20;
+            m11 = m1.m10*m2.m01 + m1.m11*m2.m11 + m1.m12*m2.m21;
+            m12 = m1.m10*m2.m02 + m1.m11*m2.m12 + m1.m12*m2.m22;
+
+            m20 = m1.m20*m2.m00 + m1.m21*m2.m10 + m1.m22*m2.m20;
+            m21 = m1.m20*m2.m01 + m1.m21*m2.m11 + m1.m22*m2.m21;
+            m22 = m1.m20*m2.m02 + m1.m21*m2.m12 + m1.m22*m2.m22;
+
+            this.m00 = m00; this.m01 = m01; this.m02 = m02;
+            this.m10 = m10; this.m11 = m11; this.m12 = m12;
+            this.m20 = m20; this.m21 = m21; this.m22 = m22;
+       }
+    }
+
+   /**
+     *  Multiplies this matrix by matrix m1, does an SVD normalization
+     *  of the result, and places the result back into this matrix
+     *  this = SVDnorm(this*m1).
+     *  @param  m1   the matrix on the right hand side of the multiplication
+     */
+    public final void mulNormalize(Matrix3d m1){
+
+       double[]    tmp = new double[9];  // scratch matrix
+       double[]    tmp_rot = new double[9];  // scratch matrix
+       double[]    tmp_scale = new double[3];  // scratch matrix
+
+       tmp[0] = this.m00*m1.m00 + this.m01*m1.m10 + this.m02*m1.m20;
+       tmp[1] = this.m00*m1.m01 + this.m01*m1.m11 + this.m02*m1.m21;
+       tmp[2] = this.m00*m1.m02 + this.m01*m1.m12 + this.m02*m1.m22;
+
+       tmp[3] = this.m10*m1.m00 + this.m11*m1.m10 + this.m12*m1.m20;
+       tmp[4] = this.m10*m1.m01 + this.m11*m1.m11 + this.m12*m1.m21;
+       tmp[5] = this.m10*m1.m02 + this.m11*m1.m12 + this.m12*m1.m22;
+
+       tmp[6] = this.m20*m1.m00 + this.m21*m1.m10 + this.m22*m1.m20;
+       tmp[7] = this.m20*m1.m01 + this.m21*m1.m11 + this.m22*m1.m21;
+       tmp[8] = this.m20*m1.m02 + this.m21*m1.m12 + this.m22*m1.m22;
+
+       compute_svd( tmp, tmp_scale, tmp_rot);
+
+       this.m00 = tmp_rot[0];
+       this.m01 = tmp_rot[1];
+       this.m02 = tmp_rot[2];
+
+       this.m10 = tmp_rot[3];
+       this.m11 = tmp_rot[4];
+       this.m12 = tmp_rot[5];
+
+       this.m20 = tmp_rot[6];
+       this.m21 = tmp_rot[7];
+       this.m22 = tmp_rot[8];
+
+    }
+
+
+   /**
+     *  Multiplies matrix m1 by matrix m2, does an SVD normalization
+     *  of the result, and places the result into this matrix
+     *  this = SVDnorm(m1*m2).
+     *  @param  m1  the matrix on the left hand side of the multiplication
+     *  @param  m2  the matrix on the right hand side of the multiplication
+     */
+    public final void mulNormalize(Matrix3d m1, Matrix3d m2){
+
+       double[]    tmp = new double[9];  // scratch matrix
+       double[]    tmp_rot = new double[9];  // scratch matrix
+       double[]    tmp_scale = new double[3];  // scratch matrix
+
+       tmp[0] = m1.m00*m2.m00 + m1.m01*m2.m10 + m1.m02*m2.m20;
+       tmp[1] = m1.m00*m2.m01 + m1.m01*m2.m11 + m1.m02*m2.m21;
+       tmp[2] = m1.m00*m2.m02 + m1.m01*m2.m12 + m1.m02*m2.m22;
+
+       tmp[3] = m1.m10*m2.m00 + m1.m11*m2.m10 + m1.m12*m2.m20;
+       tmp[4] = m1.m10*m2.m01 + m1.m11*m2.m11 + m1.m12*m2.m21;
+       tmp[5] = m1.m10*m2.m02 + m1.m11*m2.m12 + m1.m12*m2.m22;
+
+       tmp[6] = m1.m20*m2.m00 + m1.m21*m2.m10 + m1.m22*m2.m20;
+       tmp[7] = m1.m20*m2.m01 + m1.m21*m2.m11 + m1.m22*m2.m21;
+       tmp[8] = m1.m20*m2.m02 + m1.m21*m2.m12 + m1.m22*m2.m22;
+
+       compute_svd( tmp, tmp_scale, tmp_rot);
+
+       this.m00 = tmp_rot[0];
+       this.m01 = tmp_rot[1];
+       this.m02 = tmp_rot[2];
+
+       this.m10 = tmp_rot[3];
+       this.m11 = tmp_rot[4];
+       this.m12 = tmp_rot[5];
+
+       this.m20 = tmp_rot[6];
+       this.m21 = tmp_rot[7];
+       this.m22 = tmp_rot[8];
+
+    }
+
+   /**
+     *  Multiplies the transpose of matrix m1 times the transpose of matrix
+     *  m2, and places the result into this.
+     *  @param m1  the matrix on the left hand side of the multiplication
+     *  @param m2  the matrix on the right hand side of the multiplication
+     */
+    public final void mulTransposeBoth(Matrix3d m1, Matrix3d m2)
+    {
+        if (this != m1 && this != m2) {
+            this.m00 = m1.m00*m2.m00 + m1.m10*m2.m01 + m1.m20*m2.m02;
+            this.m01 = m1.m00*m2.m10 + m1.m10*m2.m11 + m1.m20*m2.m12;
+            this.m02 = m1.m00*m2.m20 + m1.m10*m2.m21 + m1.m20*m2.m22;
+
+            this.m10 = m1.m01*m2.m00 + m1.m11*m2.m01 + m1.m21*m2.m02;
+            this.m11 = m1.m01*m2.m10 + m1.m11*m2.m11 + m1.m21*m2.m12;
+            this.m12 = m1.m01*m2.m20 + m1.m11*m2.m21 + m1.m21*m2.m22;
+
+            this.m20 = m1.m02*m2.m00 + m1.m12*m2.m01 + m1.m22*m2.m02;
+            this.m21 = m1.m02*m2.m10 + m1.m12*m2.m11 + m1.m22*m2.m12;
+            this.m22 = m1.m02*m2.m20 + m1.m12*m2.m21 + m1.m22*m2.m22;
+        } else {
+            double      m00, m01, m02,
+                        m10, m11, m12,
+               m20, m21, m22;  // vars for temp result matrix
+
+            m00 = m1.m00*m2.m00 + m1.m10*m2.m01 + m1.m20*m2.m02;
+            m01 = m1.m00*m2.m10 + m1.m10*m2.m11 + m1.m20*m2.m12;
+            m02 = m1.m00*m2.m20 + m1.m10*m2.m21 + m1.m20*m2.m22;
+
+            m10 = m1.m01*m2.m00 + m1.m11*m2.m01 + m1.m21*m2.m02;
+            m11 = m1.m01*m2.m10 + m1.m11*m2.m11 + m1.m21*m2.m12;
+            m12 = m1.m01*m2.m20 + m1.m11*m2.m21 + m1.m21*m2.m22;
+
+            m20 = m1.m02*m2.m00 + m1.m12*m2.m01 + m1.m22*m2.m02;
+            m21 = m1.m02*m2.m10 + m1.m12*m2.m11 + m1.m22*m2.m12;
+            m22 = m1.m02*m2.m20 + m1.m12*m2.m21 + m1.m22*m2.m22;
+
+            this.m00 = m00; this.m01 = m01; this.m02 = m02;
+            this.m10 = m10; this.m11 = m11; this.m12 = m12;
+            this.m20 = m20; this.m21 = m21; this.m22 = m22;
+        }
+
+    }
+
+   /**
+     *  Multiplies matrix m1 times the transpose of matrix m2, and
+     *  places the result into this.
+     *  @param m1  the matrix on the left hand side of the multiplication
+     *  @param m2  the matrix on the right hand side of the multiplication
+     */
+    public final void mulTransposeRight(Matrix3d m1, Matrix3d m2)
+  {
+    if (this != m1 && this != m2) {
+      this.m00 = m1.m00*m2.m00 + m1.m01*m2.m01 + m1.m02*m2.m02;
+      this.m01 = m1.m00*m2.m10 + m1.m01*m2.m11 + m1.m02*m2.m12;
+      this.m02 = m1.m00*m2.m20 + m1.m01*m2.m21 + m1.m02*m2.m22;
+
+      this.m10 = m1.m10*m2.m00 + m1.m11*m2.m01 + m1.m12*m2.m02;
+      this.m11 = m1.m10*m2.m10 + m1.m11*m2.m11 + m1.m12*m2.m12;
+      this.m12 = m1.m10*m2.m20 + m1.m11*m2.m21 + m1.m12*m2.m22;
+
+      this.m20 = m1.m20*m2.m00 + m1.m21*m2.m01 + m1.m22*m2.m02;
+      this.m21 = m1.m20*m2.m10 + m1.m21*m2.m11 + m1.m22*m2.m12;
+      this.m22 = m1.m20*m2.m20 + m1.m21*m2.m21 + m1.m22*m2.m22;
+    } else {
+      double   m00, m01, m02,
+       m10, m11, m12,
+         m20, m21, m22;  // vars for temp result matrix
+
+      m00 = m1.m00*m2.m00 + m1.m01*m2.m01 + m1.m02*m2.m02;
+      m01 = m1.m00*m2.m10 + m1.m01*m2.m11 + m1.m02*m2.m12;
+      m02 = m1.m00*m2.m20 + m1.m01*m2.m21 + m1.m02*m2.m22;
+
+      m10 = m1.m10*m2.m00 + m1.m11*m2.m01 + m1.m12*m2.m02;
+      m11 = m1.m10*m2.m10 + m1.m11*m2.m11 + m1.m12*m2.m12;
+      m12 = m1.m10*m2.m20 + m1.m11*m2.m21 + m1.m12*m2.m22;
+
+      m20 = m1.m20*m2.m00 + m1.m21*m2.m01 + m1.m22*m2.m02;
+      m21 = m1.m20*m2.m10 + m1.m21*m2.m11 + m1.m22*m2.m12;
+      m22 = m1.m20*m2.m20 + m1.m21*m2.m21 + m1.m22*m2.m22;
+
+      this.m00 = m00; this.m01 = m01; this.m02 = m02;
+      this.m10 = m10; this.m11 = m11; this.m12 = m12;
+      this.m20 = m20; this.m21 = m21; this.m22 = m22;
+    }
+  }
+
+
+   /**
+     *  Multiplies the transpose of matrix m1 times matrix m2, and
+     *  places the result into this.
+     *  @param m1  the matrix on the left hand side of the multiplication
+     *  @param m2  the matrix on the right hand side of the multiplication
+     */
+    public final void mulTransposeLeft(Matrix3d m1, Matrix3d m2) {
+       if (this != m1 && this != m2) {
+            this.m00 = m1.m00*m2.m00 + m1.m10*m2.m10 + m1.m20*m2.m20;
+            this.m01 = m1.m00*m2.m01 + m1.m10*m2.m11 + m1.m20*m2.m21;
+            this.m02 = m1.m00*m2.m02 + m1.m10*m2.m12 + m1.m20*m2.m22;
+
+            this.m10 = m1.m01*m2.m00 + m1.m11*m2.m10 + m1.m21*m2.m20;
+            this.m11 = m1.m01*m2.m01 + m1.m11*m2.m11 + m1.m21*m2.m21;
+            this.m12 = m1.m01*m2.m02 + m1.m11*m2.m12 + m1.m21*m2.m22;
+
+            this.m20 = m1.m02*m2.m00 + m1.m12*m2.m10 + m1.m22*m2.m20;
+            this.m21 = m1.m02*m2.m01 + m1.m12*m2.m11 + m1.m22*m2.m21;
+            this.m22 = m1.m02*m2.m02 + m1.m12*m2.m12 + m1.m22*m2.m22;
+       } else {
+           double      m00, m01, m02,
+                       m10, m11, m12,
+               m20, m21, m22;  // vars for temp result matrix
+
+            m00 = m1.m00*m2.m00 + m1.m10*m2.m10 + m1.m20*m2.m20;
+            m01 = m1.m00*m2.m01 + m1.m10*m2.m11 + m1.m20*m2.m21;
+            m02 = m1.m00*m2.m02 + m1.m10*m2.m12 + m1.m20*m2.m22;
+
+            m10 = m1.m01*m2.m00 + m1.m11*m2.m10 + m1.m21*m2.m20;
+            m11 = m1.m01*m2.m01 + m1.m11*m2.m11 + m1.m21*m2.m21;
+            m12 = m1.m01*m2.m02 + m1.m11*m2.m12 + m1.m21*m2.m22;
+
+            m20 = m1.m02*m2.m00 + m1.m12*m2.m10 + m1.m22*m2.m20;
+            m21 = m1.m02*m2.m01 + m1.m12*m2.m11 + m1.m22*m2.m21;
+            m22 = m1.m02*m2.m02 + m1.m12*m2.m12 + m1.m22*m2.m22;
+
+            this.m00 = m00; this.m01 = m01; this.m02 = m02;
+            this.m10 = m10; this.m11 = m11; this.m12 = m12;
+            this.m20 = m20; this.m21 = m21; this.m22 = m22;
+       }
+    }
+
+
+
+   /**
+     * Performs singular value decomposition normalization of this matrix.
+     */
+    public final void normalize(){
+       double[]    tmp_rot = new double[9];  // scratch matrix
+       double[]    tmp_scale = new double[3];  // scratch matrix
+
+       getScaleRotate( tmp_scale, tmp_rot );
+
+       this.m00 = tmp_rot[0];
+       this.m01 = tmp_rot[1];
+       this.m02 = tmp_rot[2];
+
+       this.m10 = tmp_rot[3];
+       this.m11 = tmp_rot[4];
+       this.m12 = tmp_rot[5];
+
+       this.m20 = tmp_rot[6];
+       this.m21 = tmp_rot[7];
+       this.m22 = tmp_rot[8];
+
+    }
+
+
+   /**
+     * Perform singular value decomposition normalization of matrix m1 and
+     * place the normalized values into this.
+     * @param m1  Provides the matrix values to be normalized
+     */
+    public final void normalize(Matrix3d m1){
+
+       double[]    tmp = new double[9];  // scratch matrix
+       double[]    tmp_rot = new double[9];  // scratch matrix
+       double[]    tmp_scale = new double[3];  // scratch matrix
+
+       tmp[0] = m1.m00;
+       tmp[1] = m1.m01;
+       tmp[2] = m1.m02;
+
+       tmp[3] = m1.m10;
+       tmp[4] = m1.m11;
+       tmp[5] = m1.m12;
+
+       tmp[6] = m1.m20;
+       tmp[7] = m1.m21;
+       tmp[8] = m1.m22;
+
+       compute_svd( tmp, tmp_scale, tmp_rot);
+
+       this.m00 = tmp_rot[0];
+       this.m01 = tmp_rot[1];
+       this.m02 = tmp_rot[2];
+
+       this.m10 = tmp_rot[3];
+       this.m11 = tmp_rot[4];
+       this.m12 = tmp_rot[5];
+
+       this.m20 = tmp_rot[6];
+       this.m21 = tmp_rot[7];
+       this.m22 = tmp_rot[8];
+    }
+
+
+   /**
+     * Perform cross product normalization of this matrix.
+     */
+
+    public final void normalizeCP()
+    {
+       double mag = 1.0/Math.sqrt(m00*m00 + m10*m10 + m20*m20);
+       m00 = m00*mag;
+       m10 = m10*mag;
+       m20 = m20*mag;
+
+       mag = 1.0/Math.sqrt(m01*m01 + m11*m11 + m21*m21);
+       m01 = m01*mag;
+       m11 = m11*mag;
+       m21 = m21*mag;
+
+       m02 = m10*m21 - m11*m20;
+       m12 = m01*m20 - m00*m21;
+       m22 = m00*m11 - m01*m10;
+    }
+
+
+   /**
+     * Perform cross product normalization of matrix m1 and place the
+     * normalized values into this.
+     * @param m1  Provides the matrix values to be normalized
+     */
+    public final void normalizeCP(Matrix3d m1)
+    {
+       double mag = 1.0/Math.sqrt(m1.m00*m1.m00 + m1.m10*m1.m10 + m1.m20*m1.m20);
+       m00 = m1.m00*mag;
+       m10 = m1.m10*mag;
+       m20 = m1.m20*mag;
+
+       mag = 1.0/Math.sqrt(m1.m01*m1.m01 + m1.m11*m1.m11 + m1.m21*m1.m21);
+       m01 = m1.m01*mag;
+       m11 = m1.m11*mag;
+       m21 = m1.m21*mag;
+
+       m02 = m10*m21 - m11*m20;
+       m12 = m01*m20 - m00*m21;
+       m22 = m00*m11 - m01*m10;
+    }
+
+   /**
+     * Returns true if all of the data members of Matrix3d m1 are
+     * equal to the corresponding data members in this Matrix3d.
+     * @param m1  the matrix with which the comparison is made
+     * @return  true or false
+     */
+    public boolean equals(Matrix3d m1)
+    {
+      try {
+         return(this.m00 == m1.m00 && this.m01 == m1.m01 && this.m02 == m1.m02
+            && this.m10 == m1.m10 && this.m11 == m1.m11 && this.m12 == m1.m12
+            && this.m20 == m1.m20 && this.m21 == m1.m21 && this.m22 == m1.m22);
+      }
+      catch (NullPointerException e2) { return false; }
+
+    }
+
+   /**
+     * Returns true if the Object t1 is of type Matrix3d and all of the
+     * data members of t1 are equal to the corresponding data members in
+     * this Matrix3d.
+     * @param t1  the matrix with which the comparison is made
+     * @return  true or false
+     */
+    public boolean equals(Object t1)
+    {
+        try {
+           Matrix3d m2 = (Matrix3d) t1;
+           return(this.m00 == m2.m00 && this.m01 == m2.m01 && this.m02 == m2.m02
+             && this.m10 == m2.m10 && this.m11 == m2.m11 && this.m12 == m2.m12
+             && this.m20 == m2.m20 && this.m21 == m2.m21 && this.m22 == m2.m22);
+        }
+        catch (ClassCastException   e1) { return false; }
+        catch (NullPointerException e2) { return false; }
+
+    }
+
+   /**
+     * Returns true if the L-infinite distance between this matrix
+     * and matrix m1 is less than or equal to the epsilon parameter,
+     * otherwise returns false.  The L-infinite
+     * distance is equal to
+     * MAX[i=0,1,2 ; j=0,1,2 ; abs(this.m(i,j) - m1.m(i,j)]
+     * @param m1  the matrix to be compared to this matrix
+     * @param epsilon  the threshold value
+     */
+    public boolean epsilonEquals(Matrix3d m1, double epsilon)
+    {
+       double diff;
+
+       diff = m00 - m1.m00;
+       if((diff<0?-diff:diff) > epsilon) return false;
+
+       diff = m01 - m1.m01;
+       if((diff<0?-diff:diff) > epsilon) return false;
+
+       diff = m02 - m1.m02;
+       if((diff<0?-diff:diff) > epsilon) return false;
+
+       diff = m10 - m1.m10;
+       if((diff<0?-diff:diff) > epsilon) return false;
+
+       diff = m11 - m1.m11;
+       if((diff<0?-diff:diff) > epsilon) return false;
+
+       diff = m12 - m1.m12;
+       if((diff<0?-diff:diff) > epsilon) return false;
+
+       diff = m20 - m1.m20;
+       if((diff<0?-diff:diff) > epsilon) return false;
+
+       diff = m21 - m1.m21;
+       if((diff<0?-diff:diff) > epsilon) return false;
+
+       diff = m22 - m1.m22;
+       if((diff<0?-diff:diff) > epsilon) return false;
+
+       return true;
+    }
+
+
+    /**
+     * Returns a hash code value based on the data values in this
+     * object.  Two different Matrix3d objects with identical data values
+     * (i.e., Matrix3d.equals returns true) will return the same hash
+     * code value.  Two objects with different data members may return the
+     * same hash value, although this is not likely.
+     * @return the integer hash code value
+     */
+    public int hashCode() {
+       long bits = 1L;
+       bits = 31L * bits + VecMathUtil.doubleToLongBits(m00);
+       bits = 31L * bits + VecMathUtil.doubleToLongBits(m01);
+       bits = 31L * bits + VecMathUtil.doubleToLongBits(m02);
+       bits = 31L * bits + VecMathUtil.doubleToLongBits(m10);
+       bits = 31L * bits + VecMathUtil.doubleToLongBits(m11);
+       bits = 31L * bits + VecMathUtil.doubleToLongBits(m12);
+       bits = 31L * bits + VecMathUtil.doubleToLongBits(m20);
+       bits = 31L * bits + VecMathUtil.doubleToLongBits(m21);
+       bits = 31L * bits + VecMathUtil.doubleToLongBits(m22);
+       return (int) (bits ^ (bits >> 32));
+    }
+
+
+  /**
+    *  Sets this matrix to all zeros.
+    */
+   public final void setZero()
+   {
+        m00 = 0.0;
+        m01 = 0.0;
+        m02 = 0.0;
+
+        m10 = 0.0;
+        m11 = 0.0;
+        m12 = 0.0;
+
+        m20 = 0.0;
+        m21 = 0.0;
+        m22 = 0.0;
+
+   }
+
+   /**
+     * Negates the value of this matrix: this = -this.
+     */
+    public final void negate()
+    {
+        this.m00 = -this.m00;
+        this.m01 = -this.m01;
+        this.m02 = -this.m02;
+
+        this.m10 = -this.m10;
+        this.m11 = -this.m11;
+        this.m12 = -this.m12;
+
+        this.m20 = -this.m20;
+        this.m21 = -this.m21;
+        this.m22 = -this.m22;
+
+    }
+
+   /**
+     *  Sets the value of this matrix equal to the negation of
+     *  of the Matrix3d parameter.
+     *  @param m1  the source matrix
+     */
+    public final void negate(Matrix3d m1)
+    {
+        this.m00 = -m1.m00;
+        this.m01 = -m1.m01;
+        this.m02 = -m1.m02;
+
+        this.m10 = -m1.m10;
+        this.m11 = -m1.m11;
+        this.m12 = -m1.m12;
+
+        this.m20 = -m1.m20;
+        this.m21 = -m1.m21;
+        this.m22 = -m1.m22;
+
+    }
+
+   /**
+     * Multiply this matrix by the tuple t and place the result
+     * back into the tuple (t = this*t).
+     * @param t  the tuple to be multiplied by this matrix and then replaced
+     */
+    public final void transform(Tuple3d t) {
+     double x,y,z;
+     x = m00* t.x + m01*t.y + m02*t.z;
+     y = m10* t.x + m11*t.y + m12*t.z;
+     z = m20* t.x + m21*t.y + m22*t.z;
+     t.set(x,y,z);
+    }
+
+   /**
+     * Multiply this matrix by the tuple t and and place the result
+     * into the tuple "result" (result = this*t).
+     * @param t  the tuple to be multiplied by this matrix
+     * @param result  the tuple into which the product is placed
+     */
+    public final void transform(Tuple3d t, Tuple3d result) {
+     double x,y,z;
+        x = m00* t.x + m01*t.y + m02*t.z;
+        y = m10* t.x + m11*t.y + m12*t.z;
+        result.z = m20* t.x + m21*t.y + m22*t.z;
+        result.x = x;
+        result.y = y;
+    }
+
+    /**
+     * perform SVD (if necessary to get rotational component
+     */
+    final void getScaleRotate(double scales[], double rots[]) {
+
+       double[]    tmp = new double[9];  // scratch matrix
+
+       tmp[0] = m00;
+       tmp[1] = m01;
+       tmp[2] = m02;
+
+       tmp[3] = m10;
+       tmp[4] = m11;
+       tmp[5] = m12;
+
+       tmp[6] = m20;
+       tmp[7] = m21;
+       tmp[8] = m22;
+       compute_svd( tmp, scales, rots);
+
+       return;
+    }
+
+    static void compute_svd( double[] m, double[] outScale, double[] outRot) {
+       int i,j;
+       double g,scale;
+       double[] u1 = new double[9];
+       double[] v1 = new double[9];
+       double[] t1 = new double[9];
+       double[] t2 = new double[9];
+
+       double[] tmp = t1;
+       double[] single_values = t2;
+
+       double[] rot = new double[9];
+       double[] e = new double[3];
+       double[] scales = new double[3];
+
+       int converged, negCnt=0;
+       double cs,sn;
+       double c1,c2,c3,c4;
+       double s1,s2,s3,s4;
+       double cl1,cl2,cl3;
+
+
+       for(i=0; i<9; i++)
+           rot[i] = m[i];
+
+       // u1
+
+       if( m[3]*m[3] < EPS ) {
+           u1[0] = 1.0; u1[1] = 0.0; u1[2] = 0.0;
+           u1[3] = 0.0; u1[4] = 1.0; u1[5] = 0.0;
+           u1[6] = 0.0; u1[7] = 0.0; u1[8] = 1.0;
+       } else if( m[0]*m[0] < EPS ) {
+           tmp[0] = m[0];
+           tmp[1] = m[1];
+           tmp[2] = m[2];
+           m[0] = m[3];
+           m[1] = m[4];
+           m[2] = m[5];
+
+           m[3] = -tmp[0]; // zero
+           m[4] = -tmp[1];
+           m[5] = -tmp[2];
+
+           u1[0] =  0.0; u1[1] = 1.0;  u1[2] = 0.0;
+           u1[3] = -1.0; u1[4] = 0.0;  u1[5] = 0.0;
+           u1[6] =  0.0; u1[7] = 0.0;  u1[8] = 1.0;
+       } else {
+           g = 1.0/Math.sqrt(m[0]*m[0] + m[3]*m[3]);
+           c1 = m[0]*g;
+           s1 = m[3]*g;
+           tmp[0] = c1*m[0] + s1*m[3];
+           tmp[1] = c1*m[1] + s1*m[4];
+           tmp[2] = c1*m[2] + s1*m[5];
+
+           m[3] = -s1*m[0] + c1*m[3]; // zero
+           m[4] = -s1*m[1] + c1*m[4];
+           m[5] = -s1*m[2] + c1*m[5];
+
+           m[0] = tmp[0];
+           m[1] = tmp[1];
+           m[2] = tmp[2];
+           u1[0] = c1;  u1[1] = s1;  u1[2] = 0.0;
+           u1[3] = -s1; u1[4] = c1;  u1[5] = 0.0;
+           u1[6] = 0.0; u1[7] = 0.0; u1[8] = 1.0;
+       }
+
+       // u2
+
+       if( m[6]*m[6] < EPS  ) {
+       } else if( m[0]*m[0] < EPS ){
+           tmp[0] = m[0];
+           tmp[1] = m[1];
+           tmp[2] = m[2];
+           m[0] = m[6];
+           m[1] = m[7];
+           m[2] = m[8];
+
+           m[6] = -tmp[0]; // zero
+           m[7] = -tmp[1];
+           m[8] = -tmp[2];
+
+           tmp[0] = u1[0];
+           tmp[1] = u1[1];
+           tmp[2] = u1[2];
+           u1[0] = u1[6];
+           u1[1] = u1[7];
+           u1[2] = u1[8];
+
+           u1[6] = -tmp[0]; // zero
+           u1[7] = -tmp[1];
+           u1[8] = -tmp[2];
+       } else {
+           g = 1.0/Math.sqrt(m[0]*m[0] + m[6]*m[6]);
+           c2 = m[0]*g;
+           s2 = m[6]*g;
+           tmp[0] = c2*m[0] + s2*m[6];
+           tmp[1] = c2*m[1] + s2*m[7];
+           tmp[2] = c2*m[2] + s2*m[8];
+
+           m[6] = -s2*m[0] + c2*m[6];
+           m[7] = -s2*m[1] + c2*m[7];
+           m[8] = -s2*m[2] + c2*m[8];
+           m[0] = tmp[0];
+           m[1] = tmp[1];
+           m[2] = tmp[2];
+
+           tmp[0] = c2*u1[0];
+           tmp[1] = c2*u1[1];
+           u1[2]  = s2;
+
+           tmp[6] = -u1[0]*s2;
+           tmp[7] = -u1[1]*s2;
+           u1[8] = c2;
+           u1[0] = tmp[0];
+           u1[1] = tmp[1];
+           u1[6] = tmp[6];
+           u1[7] = tmp[7];
+       }
+
+       // v1
+
+       if( m[2]*m[2] < EPS ) {
+           v1[0] = 1.0; v1[1] = 0.0; v1[2] = 0.0;
+           v1[3] = 0.0; v1[4] = 1.0; v1[5] = 0.0;
+           v1[6] = 0.0; v1[7] = 0.0; v1[8] = 1.0;
+       } else if( m[1]*m[1] < EPS ) {
+           tmp[2] = m[2];
+           tmp[5] = m[5];
+           tmp[8] = m[8];
+           m[2] = -m[1];
+           m[5] = -m[4];
+           m[8] = -m[7];
+
+           m[1] = tmp[2]; // zero
+           m[4] = tmp[5];
+           m[7] = tmp[8];
+
+           v1[0] =  1.0; v1[1] = 0.0;  v1[2] = 0.0;
+           v1[3] =  0.0; v1[4] = 0.0;  v1[5] =-1.0;
+           v1[6] =  0.0; v1[7] = 1.0;  v1[8] = 0.0;
+       } else {
+           g = 1.0/Math.sqrt(m[1]*m[1] + m[2]*m[2]);
+           c3 = m[1]*g;
+           s3 = m[2]*g;
+           tmp[1] = c3*m[1] + s3*m[2];  // can assign to m[1]?
+           m[2] =-s3*m[1] + c3*m[2];  // zero
+           m[1] = tmp[1];
+
+           tmp[4] = c3*m[4] + s3*m[5];
+           m[5] =-s3*m[4] + c3*m[5];
+           m[4] = tmp[4];
+
+           tmp[7] = c3*m[7] + s3*m[8];
+           m[8] =-s3*m[7] + c3*m[8];
+           m[7] = tmp[7];
+
+           v1[0] = 1.0; v1[1] = 0.0; v1[2] = 0.0;
+           v1[3] = 0.0; v1[4] =  c3; v1[5] = -s3;
+           v1[6] = 0.0; v1[7] =  s3; v1[8] =  c3;
+       }
+
+       // u3
+
+       if( m[7]*m[7] < EPS ) {
+       } else if( m[4]*m[4] < EPS ) {
+           tmp[3] = m[3];
+           tmp[4] = m[4];
+           tmp[5] = m[5];
+           m[3] = m[6];   // zero
+           m[4] = m[7];
+           m[5] = m[8];
+
+           m[6] = -tmp[3]; // zero
+           m[7] = -tmp[4]; // zero
+           m[8] = -tmp[5];
+
+           tmp[3] = u1[3];
+           tmp[4] = u1[4];
+           tmp[5] = u1[5];
+           u1[3] = u1[6];
+           u1[4] = u1[7];
+           u1[5] = u1[8];
+
+           u1[6] = -tmp[3]; // zero
+           u1[7] = -tmp[4];
+           u1[8] = -tmp[5];
+
+       } else {
+           g = 1.0/Math.sqrt(m[4]*m[4] + m[7]*m[7]);
+           c4 = m[4]*g;
+           s4 = m[7]*g;
+           tmp[3] = c4*m[3] + s4*m[6];
+           m[6] =-s4*m[3] + c4*m[6];  // zero
+           m[3] = tmp[3];
+
+           tmp[4] = c4*m[4] + s4*m[7];
+           m[7] =-s4*m[4] + c4*m[7];
+           m[4] = tmp[4];
+
+           tmp[5] = c4*m[5] + s4*m[8];
+           m[8] =-s4*m[5] + c4*m[8];
+           m[5] = tmp[5];
+
+           tmp[3] = c4*u1[3] + s4*u1[6];
+           u1[6] =-s4*u1[3] + c4*u1[6];
+           u1[3] = tmp[3];
+
+           tmp[4] = c4*u1[4] + s4*u1[7];
+           u1[7] =-s4*u1[4] + c4*u1[7];
+           u1[4] = tmp[4];
+
+           tmp[5] = c4*u1[5] + s4*u1[8];
+           u1[8] =-s4*u1[5] + c4*u1[8];
+           u1[5] = tmp[5];
+       }
+
+       single_values[0] = m[0];
+       single_values[1] = m[4];
+       single_values[2] = m[8];
+       e[0] = m[1];
+       e[1] = m[5];
+
+       if( e[0]*e[0]<EPS  && e[1]*e[1]<EPS ) {
+
+       } else {
+           compute_qr( single_values, e, u1, v1);
+       }
+
+       scales[0] = single_values[0];
+       scales[1] = single_values[1];
+       scales[2] = single_values[2];
+
+
+       // Do some optimization here. If scale is unity, simply return the rotation matric.
+       if(almostEqual(Math.abs(scales[0]), 1.0) &&
+          almostEqual(Math.abs(scales[1]), 1.0) &&
+          almostEqual(Math.abs(scales[2]), 1.0)) {
+           //  System.out.println("Scale components almost to 1.0");
+
+           for(i=0;i<3;i++)
+               if(scales[i]<0.0)
+                   negCnt++;
+
+           if((negCnt==0)||(negCnt==2)) {
+               //System.out.println("Optimize!!");
+               outScale[0] = outScale[1] = outScale[2] = 1.0;
+               for(i=0;i<9;i++)
+                   outRot[i] = rot[i];
+
+               return;
+           }
+       }
+
+
+       transpose_mat(u1, t1);
+       transpose_mat(v1, t2);
+
+       /*
+         System.out.println("t1 is \n" + t1);
+         System.out.println("t1="+t1[0]+" "+t1[1]+" "+t1[2]);
+         System.out.println("t1="+t1[3]+" "+t1[4]+" "+t1[5]);
+         System.out.println("t1="+t1[6]+" "+t1[7]+" "+t1[8]);
+
+         System.out.println("t2 is \n" + t2);
+         System.out.println("t2="+t2[0]+" "+t2[1]+" "+t2[2]);
+         System.out.println("t2="+t2[3]+" "+t2[4]+" "+t2[5]);
+         System.out.println("t2="+t2[6]+" "+t2[7]+" "+t2[8]);
+         */
+
+       svdReorder( m, t1, t2, scales, outRot, outScale);
+
+    }
+
+    static void svdReorder( double[] m, double[] t1, double[] t2, double[] scales,
+                           double[] outRot, double[] outScale) {
+
+       int[] out = new int[3];
+       int[] in = new int[3];
+       int in0, in1, in2, index, i;
+       double[] mag = new double[3];
+       double[] rot = new double[9];
+
+
+       // check for rotation information in the scales
+       if(scales[0] < 0.0 ) {   // move the rotation info to rotation matrix
+           scales[0] = -scales[0];
+           t2[0] = -t2[0];
+           t2[1] = -t2[1];
+           t2[2] = -t2[2];
+       }
+       if(scales[1] < 0.0 ) {   // move the rotation info to rotation matrix
+           scales[1] = -scales[1];
+           t2[3] = -t2[3];
+           t2[4] = -t2[4];
+           t2[5] = -t2[5];
+       }
+       if(scales[2] < 0.0 ) {   // move the rotation info to rotation matrix
+           scales[2] = -scales[2];
+           t2[6] = -t2[6];
+           t2[7] = -t2[7];
+           t2[8] = -t2[8];
+       }
+
+       mat_mul(t1,t2,rot);
+
+       // check for equal scales case  and do not reorder
+       if(almostEqual(Math.abs(scales[0]), Math.abs(scales[1])) &&
+          almostEqual(Math.abs(scales[1]), Math.abs(scales[2]))   ){
+           for(i=0;i<9;i++){
+               outRot[i] = rot[i];
+           }
+           for(i=0;i<3;i++){
+               outScale[i] = scales[i];
+           }
+
+       }else {
+
+           // sort the order of the results of SVD
+           if( scales[0] > scales[1]) {
+               if( scales[0] > scales[2] ) {
+                   if( scales[2] > scales[1] ) {
+                       out[0] = 0; out[1] = 2; out[2] = 1; // xzy
+                   } else {
+                       out[0] = 0; out[1] = 1; out[2] = 2; // xyz
+                   }
+               } else {
+                   out[0] = 2; out[1] = 0; out[2] = 1; // zxy
+               }
+           } else {  // y > x
+               if( scales[1] > scales[2] ) {
+                   if( scales[2] > scales[0] ) {
+                       out[0] = 1; out[1] = 2; out[2] = 0; // yzx
+                   } else {
+                       out[0] = 1; out[1] = 0; out[2] = 2; // yxz
+                   }
+               } else  {
+                   out[0] = 2; out[1] = 1; out[2] = 0; // zyx
+               }
+           }
+
+           /*
+               System.out.println("\nscales="+scales[0]+" "+scales[1]+" "+scales[2]);
+               System.out.println("\nrot="+rot[0]+" "+rot[1]+" "+rot[2]);
+               System.out.println("rot="+rot[3]+" "+rot[4]+" "+rot[5]);
+               System.out.println("rot="+rot[6]+" "+rot[7]+" "+rot[8]);
+               */
+
+           // sort the order of the input matrix
+           mag[0] = (m[0]*m[0] + m[1]*m[1] + m[2]*m[2]);
+           mag[1] = (m[3]*m[3] + m[4]*m[4] + m[5]*m[5]);
+           mag[2] = (m[6]*m[6] + m[7]*m[7] + m[8]*m[8]);
+
+           if( mag[0] > mag[1]) {
+               if( mag[0] > mag[2] ) {
+                   if( mag[2] > mag[1] )  {
+                       // 0 - 2 - 1
+                       in0 = 0; in2 = 1; in1 = 2;// xzy
+                   } else {
+                       // 0 - 1 - 2
+                       in0 = 0; in1 = 1; in2 = 2; // xyz
+                   }
+               } else {
+                   // 2 - 0 - 1
+                   in2 = 0; in0 = 1; in1 = 2;  // zxy
+               }
+           } else {  // y > x   1>0
+               if( mag[1] > mag[2] ) {
+                   if( mag[2] > mag[0] )  {
+                       // 1 - 2 - 0
+                       in1 = 0; in2 = 1; in0 = 2; // yzx
+                   } else {
+                       // 1 - 0 - 2
+                       in1 = 0; in0 = 1; in2 = 2; // yxz
+                   }
+               } else  {
+                   // 2 - 1 - 0
+                   in2 = 0; in1 = 1; in0 = 2; // zyx
+               }
+           }
+
+
+           index = out[in0];
+           outScale[0] = scales[index];
+
+           index = out[in1];
+           outScale[1] = scales[index];
+
+           index = out[in2];
+           outScale[2] = scales[index];
+
+
+           index = out[in0];
+           outRot[0] = rot[index];
+
+           index = out[in0]+3;
+           outRot[0+3] = rot[index];
+
+           index = out[in0]+6;
+           outRot[0+6] = rot[index];
+
+           index = out[in1];
+           outRot[1] = rot[index];
+
+           index = out[in1]+3;
+           outRot[1+3] = rot[index];
+
+           index = out[in1]+6;
+           outRot[1+6] = rot[index];
+
+           index = out[in2];
+           outRot[2] = rot[index];
+
+           index = out[in2]+3;
+           outRot[2+3] = rot[index];
+
+           index = out[in2]+6;
+           outRot[2+6] = rot[index];
+       }
+    }
+
+    static  int compute_qr( double[] s, double[] e, double[] u, double[] v) {
+
+       int i,j,k;
+       boolean converged;
+       double shift,ssmin,ssmax,r;
+       double[]   cosl  = new double[2];
+       double[]   cosr  = new double[2];
+       double[]   sinl  = new double[2];
+       double[]   sinr  = new double[2];
+       double[]   m = new double[9];
+
+       double utemp,vtemp;
+       double f,g;
+
+       final int MAX_INTERATIONS = 10;
+       final double CONVERGE_TOL = 4.89E-15;
+
+       double c_b48 = 1.;
+       double c_b71 = -1.;
+       int first;
+       converged = false;
+
+
+       first = 1;
+
+       if( Math.abs(e[1]) < CONVERGE_TOL || Math.abs(e[0]) < CONVERGE_TOL) converged = true;
+
+       for(k=0;k<MAX_INTERATIONS && !converged;k++) {
+           shift = compute_shift( s[1], e[1], s[2]);
+            f = (Math.abs(s[0]) - shift) * (d_sign(c_b48, s[0]) + shift/s[0]);
+            g = e[0];
+            r = compute_rot(f, g, sinr, cosr,  0, first);
+            f = cosr[0] * s[0] + sinr[0] * e[0];
+            e[0] = cosr[0] * e[0] - sinr[0] * s[0];
+            g = sinr[0] * s[1];
+            s[1] = cosr[0] * s[1];
+
+            r = compute_rot(f, g, sinl, cosl, 0, first);
+            first = 0;
+            s[0] = r;
+            f = cosl[0] * e[0] + sinl[0] * s[1];
+            s[1] = cosl[0] * s[1] - sinl[0] * e[0];
+            g = sinl[0] * e[1];
+            e[1] =  cosl[0] * e[1];
+
+            r = compute_rot(f, g, sinr, cosr, 1, first);
+            e[0] = r;
+            f = cosr[1] * s[1] + sinr[1] * e[1];
+            e[1] = cosr[1] * e[1] - sinr[1] * s[1];
+            g = sinr[1] * s[2];
+            s[2] = cosr[1] * s[2];
+
+            r = compute_rot(f, g, sinl, cosl, 1, first);
+            s[1] = r;
+            f = cosl[1] * e[1] + sinl[1] * s[2];
+            s[2] = cosl[1] * s[2] - sinl[1] * e[1];
+            e[1] = f;
+
+           // update u  matrices
+            utemp = u[0];
+            u[0] = cosl[0]*utemp + sinl[0]*u[3];
+            u[3] = -sinl[0]*utemp + cosl[0]*u[3];
+            utemp = u[1];
+            u[1] = cosl[0]*utemp + sinl[0]*u[4];
+            u[4] = -sinl[0]*utemp + cosl[0]*u[4];
+            utemp = u[2];
+            u[2] = cosl[0]*utemp + sinl[0]*u[5];
+            u[5] = -sinl[0]*utemp + cosl[0]*u[5];
+
+            utemp = u[3];
+            u[3] = cosl[1]*utemp + sinl[1]*u[6];
+            u[6] = -sinl[1]*utemp + cosl[1]*u[6];
+            utemp = u[4];
+            u[4] = cosl[1]*utemp + sinl[1]*u[7];
+            u[7] = -sinl[1]*utemp + cosl[1]*u[7];
+            utemp = u[5];
+            u[5] = cosl[1]*utemp + sinl[1]*u[8];
+            u[8] = -sinl[1]*utemp + cosl[1]*u[8];
+
+           // update v  matrices
+
+            vtemp = v[0];
+            v[0] = cosr[0]*vtemp + sinr[0]*v[1];
+            v[1] = -sinr[0]*vtemp + cosr[0]*v[1];
+            vtemp = v[3];
+            v[3] = cosr[0]*vtemp + sinr[0]*v[4];
+            v[4] = -sinr[0]*vtemp + cosr[0]*v[4];
+            vtemp = v[6];
+            v[6] = cosr[0]*vtemp + sinr[0]*v[7];
+            v[7] = -sinr[0]*vtemp + cosr[0]*v[7];
+
+            vtemp = v[1];
+            v[1] = cosr[1]*vtemp + sinr[1]*v[2];
+            v[2] = -sinr[1]*vtemp + cosr[1]*v[2];
+            vtemp = v[4];
+            v[4] = cosr[1]*vtemp + sinr[1]*v[5];
+            v[5] = -sinr[1]*vtemp + cosr[1]*v[5];
+            vtemp = v[7];
+            v[7] = cosr[1]*vtemp + sinr[1]*v[8];
+            v[8] = -sinr[1]*vtemp + cosr[1]*v[8];
+
+
+   m[0] = s[0];  m[1] = e[0]; m[2] = 0.0;
+   m[3] =  0.0;  m[4] = s[1]; m[5] =e[1];
+   m[6] =  0.0;  m[7] =  0.0; m[8] =s[2];
+
+      if( Math.abs(e[1]) < CONVERGE_TOL || Math.abs(e[0]) < CONVERGE_TOL) converged = true;
+   }
+
+   if( Math.abs(e[1]) < CONVERGE_TOL ) {
+       compute_2X2( s[0],e[0],s[1],s,sinl,cosl,sinr,cosr, 0);
+
+       utemp = u[0];
+       u[0] = cosl[0]*utemp + sinl[0]*u[3];
+       u[3] = -sinl[0]*utemp + cosl[0]*u[3];
+       utemp = u[1];
+       u[1] = cosl[0]*utemp + sinl[0]*u[4];
+       u[4] = -sinl[0]*utemp + cosl[0]*u[4];
+       utemp = u[2];
+       u[2] = cosl[0]*utemp + sinl[0]*u[5];
+       u[5] = -sinl[0]*utemp + cosl[0]*u[5];
+
+       // update v  matrices
+
+       vtemp = v[0];
+       v[0] = cosr[0]*vtemp + sinr[0]*v[1];
+       v[1] = -sinr[0]*vtemp + cosr[0]*v[1];
+       vtemp = v[3];
+       v[3] = cosr[0]*vtemp + sinr[0]*v[4];
+       v[4] = -sinr[0]*vtemp + cosr[0]*v[4];
+       vtemp = v[6];
+       v[6] = cosr[0]*vtemp + sinr[0]*v[7];
+       v[7] = -sinr[0]*vtemp + cosr[0]*v[7];
+   } else {
+       compute_2X2( s[1],e[1],s[2],s,sinl,cosl,sinr,cosr,1);
+
+       utemp = u[3];
+       u[3] = cosl[0]*utemp + sinl[0]*u[6];
+       u[6] = -sinl[0]*utemp + cosl[0]*u[6];
+       utemp = u[4];
+       u[4] = cosl[0]*utemp + sinl[0]*u[7];
+       u[7] = -sinl[0]*utemp + cosl[0]*u[7];
+       utemp = u[5];
+       u[5] = cosl[0]*utemp + sinl[0]*u[8];
+       u[8] = -sinl[0]*utemp + cosl[0]*u[8];
+
+       // update v  matrices
+
+       vtemp = v[1];
+       v[1] = cosr[0]*vtemp + sinr[0]*v[2];
+       v[2] = -sinr[0]*vtemp + cosr[0]*v[2];
+       vtemp = v[4];
+       v[4] = cosr[0]*vtemp + sinr[0]*v[5];
+       v[5] = -sinr[0]*vtemp + cosr[0]*v[5];
+       vtemp = v[7];
+       v[7] = cosr[0]*vtemp + sinr[0]*v[8];
+       v[8] = -sinr[0]*vtemp + cosr[0]*v[8];
+   }
+
+       return(0);
+}
+static double max( double a, double b) {
+    if( a > b)
+      return( a);
+    else
+      return( b);
+}
+static double min( double a, double b) {
+    if( a < b)
+      return( a);
+    else
+      return( b);
+}
+static double d_sign(double a, double b) {
+double x;
+x = (a >= 0 ? a : - a);
+return( b >= 0 ? x : -x);
+}
+
+static double compute_shift( double f, double g, double h) {
+    double d__1, d__2;
+    double fhmn, fhmx, c, fa, ga, ha, as, at, au;
+    double ssmin;
+
+    fa = Math.abs(f);
+    ga = Math.abs(g);
+    ha = Math.abs(h);
+    fhmn = min(fa,ha);
+    fhmx = max(fa,ha);
+    if (fhmn == 0.) {
+        ssmin = 0.;
+        if (fhmx == 0.) {
+        } else {
+            d__1 = min(fhmx,ga) / max(fhmx,ga);
+        }
+    } else {
+        if (ga < fhmx) {
+            as = fhmn / fhmx + 1.;
+            at = (fhmx - fhmn) / fhmx;
+            d__1 = ga / fhmx;
+            au = d__1 * d__1;
+            c = 2. / (Math.sqrt(as * as + au) + Math.sqrt(at * at + au));
+            ssmin = fhmn * c;
+        } else {
+            au = fhmx / ga;
+            if (au == 0.) {
+                ssmin = fhmn * fhmx / ga;
+            } else {
+                as = fhmn / fhmx + 1.;
+                at = (fhmx - fhmn) / fhmx;
+                d__1 = as * au;
+                d__2 = at * au;
+                c = 1. / (Math.sqrt(d__1 * d__1 + 1.) + Math.sqrt(d__2 * d__2 + 1.));
+                ssmin = fhmn * c * au;
+                ssmin += ssmin;
+            }
+        }
+    }
+
+    return(ssmin);
+}
+static int compute_2X2( double f, double g, double h, double[] single_values,
+                double[] snl, double[] csl, double[] snr, double[] csr, int index)  {
+
+    double c_b3 = 2.;
+    double c_b4 = 1.;
+
+    double d__1;
+    int pmax;
+    double temp;
+    boolean swap;
+    double a, d, l, m, r, s, t, tsign, fa, ga, ha;
+    double ft, gt, ht, mm;
+    boolean gasmal;
+    double tt, clt, crt, slt, srt;
+    double ssmin,ssmax;
+
+    ssmax = single_values[0];
+    ssmin = single_values[1];
+    clt = 0.0;
+    crt = 0.0;
+    slt = 0.0;
+    srt = 0.0;
+    tsign = 0.0;
+
+    ft = f;
+    fa = Math.abs(ft);
+    ht = h;
+    ha = Math.abs(h);
+
+    pmax = 1;
+    if( ha > fa)
+       swap = true;
+    else
+       swap = false;
+
+    if (swap) {
+        pmax = 3;
+        temp = ft;
+        ft = ht;
+        ht = temp;
+        temp = fa;
+        fa = ha;
+        ha = temp;
+
+    }
+    gt = g;
+    ga = Math.abs(gt);
+    if (ga == 0.) {
+
+        single_values[1] = ha;
+        single_values[0] = fa;
+        clt = 1.;
+        crt = 1.;
+        slt = 0.;
+        srt = 0.;
+    } else {
+        gasmal = true;
+
+       if (ga > fa) {
+            pmax = 2;
+            if (fa / ga < EPS) {
+
+                gasmal = false;
+                ssmax = ga;
+                if (ha > 1.) {
+                    ssmin = fa / (ga / ha);
+                } else {
+                    ssmin = fa / ga * ha;
+                }
+                clt = 1.;
+                slt = ht / gt;
+                srt = 1.;
+                crt = ft / gt;
+            }
+        }
+        if (gasmal) {
+
+            d = fa - ha;
+            if (d == fa) {
+
+                l = 1.;
+            } else {
+                l = d / fa;
+            }
+
+            m = gt / ft;
+
+            t = 2. - l;
+
+            mm = m * m;
+            tt = t * t;
+            s = Math.sqrt(tt + mm);
+
+            if (l == 0.) {
+                r = Math.abs(m);
+            } else {
+                r = Math.sqrt(l * l + mm);
+            }
+
+            a = (s + r) * .5;
+
+       if (ga > fa) {
+            pmax = 2;
+            if (fa / ga < EPS) {
+
+                gasmal = false;
+                ssmax = ga;
+                if (ha > 1.) {
+                    ssmin = fa / (ga / ha);
+                } else {
+                    ssmin = fa / ga * ha;
+                }
+                clt = 1.;
+                slt = ht / gt;
+                srt = 1.;
+                crt = ft / gt;
+            }
+        }
+        if (gasmal) {
+
+            d = fa - ha;
+            if (d == fa) {
+
+                l = 1.;
+            } else {
+                l = d / fa;
+            }
+
+            m = gt / ft;
+
+            t = 2. - l;
+
+            mm = m * m;
+            tt = t * t;
+            s = Math.sqrt(tt + mm);
+
+            if (l == 0.) {
+                r = Math.abs(m);
+            } else {
+                r = Math.sqrt(l * l + mm);
+            }
+
+            a = (s + r) * .5;
+
+
+            ssmin = ha / a;
+            ssmax = fa * a;
+            if (mm == 0.) {
+
+                if (l == 0.) {
+                    t = d_sign(c_b3, ft) * d_sign(c_b4, gt);
+                } else {
+                    t = gt / d_sign(d, ft) + m / t;
+                }
+            } else {
+                t = (m / (s + t) + m / (r + l)) * (a + 1.);
+            }
+            l = Math.sqrt(t * t + 4.);
+            crt = 2. / l;
+            srt = t / l;
+            clt = (crt + srt * m) / a;
+            slt = ht / ft * srt / a;
+        }
+    }
+    if (swap) {
+        csl[0] = srt;
+        snl[0] = crt;
+        csr[0] = slt;
+        snr[0] = clt;
+    } else {
+        csl[0] = clt;
+        snl[0] = slt;
+        csr[0] = crt;
+        snr[0] = srt;
+    }
+
+    if (pmax == 1) {
+        tsign = d_sign(c_b4, csr[0]) * d_sign(c_b4, csl[0]) * d_sign(c_b4, f);
+    }
+    if (pmax == 2) {
+        tsign = d_sign(c_b4, snr[0]) * d_sign(c_b4, csl[0]) * d_sign(c_b4, g);
+    }
+    if (pmax == 3) {
+        tsign = d_sign(c_b4, snr[0]) * d_sign(c_b4, snl[0]) * d_sign(c_b4, h);
+    }
+    single_values[index] = d_sign(ssmax, tsign);
+    d__1 = tsign * d_sign(c_b4, f) * d_sign(c_b4, h);
+    single_values[index+1] = d_sign(ssmin, d__1);
+
+
+   }
+    return 0;
+ }
+  static double compute_rot( double f, double g, double[] sin, double[] cos, int index, int first) {
+    int i__1;
+    double d__1, d__2;
+    double cs,sn;
+    int i;
+    double scale;
+    int count;
+    double f1, g1;
+    double r;
+    final double safmn2 = 2.002083095183101E-146;
+    final double safmx2 = 4.994797680505588E+145;
+
+    if (g == 0.) {
+        cs = 1.;
+        sn = 0.;
+        r = f;
+    } else if (f == 0.) {
+        cs = 0.;
+        sn = 1.;
+        r = g;
+    } else {
+        f1 = f;
+        g1 = g;
+        scale = max(Math.abs(f1),Math.abs(g1));
+        if (scale >= safmx2) {
+            count = 0;
+            while(scale >= safmx2) {
+               ++count;
+               f1 *= safmn2;
+               g1 *= safmn2;
+               scale = max(Math.abs(f1),Math.abs(g1));
+            }
+            r = Math.sqrt(f1*f1 + g1*g1);
+            cs = f1 / r;
+            sn = g1 / r;
+            i__1 = count;
+            for (i = 1; i <= count; ++i) {
+                r *= safmx2;
+            }
+        } else if (scale <= safmn2) {
+            count = 0;
+            while(scale <= safmn2) {
+               ++count;
+               f1 *= safmx2;
+               g1 *= safmx2;
+               scale = max(Math.abs(f1),Math.abs(g1));
+            }
+            r = Math.sqrt(f1*f1 + g1*g1);
+            cs = f1 / r;
+            sn = g1 / r;
+            i__1 = count;
+            for (i = 1; i <= count; ++i) {
+                r *= safmn2;
+            }
+        } else {
+            r = Math.sqrt(f1*f1 + g1*g1);
+            cs = f1 / r;
+            sn = g1 / r;
+        }
+        if (Math.abs(f) > Math.abs(g) && cs < 0.) {
+            cs = -cs;
+            sn = -sn;
+            r = -r;
+        }
+    }
+    sin[index] = sn;
+    cos[index] = cs;
+    return r;
+
+  }
+static void print_mat( double[]  mat) {
+int i;
+  for(i=0;i<3;i++){
+    System.out.println(mat[i*3+0]+" "+mat[i*3+1]+" "+mat[i*3+2]+"\n");
+  }
+
+}
+static void print_det( double[] mat) {
+double det;
+
+  det = mat[0]*mat[4]*mat[8] +
+        mat[1]*mat[5]*mat[6] +
+        mat[2]*mat[3]*mat[7] -
+        mat[2]*mat[4]*mat[6] -
+        mat[0]*mat[5]*mat[7] -
+        mat[1]*mat[3]*mat[8];
+  System.out.println("det= "+det);
+}
+static void  mat_mul(double[] m1, double[] m2, double[] m3) {
+  int i;
+  double[] tmp = new double[9];
+
+    tmp[0] =  m1[0]*m2[0] + m1[1]*m2[3] + m1[2]*m2[6];
+    tmp[1] =  m1[0]*m2[1] + m1[1]*m2[4] + m1[2]*m2[7];
+    tmp[2] =  m1[0]*m2[2] + m1[1]*m2[5] + m1[2]*m2[8];
+
+    tmp[3] =  m1[3]*m2[0] + m1[4]*m2[3] + m1[5]*m2[6];
+    tmp[4] =  m1[3]*m2[1] + m1[4]*m2[4] + m1[5]*m2[7];
+    tmp[5] =  m1[3]*m2[2] + m1[4]*m2[5] + m1[5]*m2[8];
+
+    tmp[6] =  m1[6]*m2[0] + m1[7]*m2[3] + m1[8]*m2[6];
+    tmp[7] =  m1[6]*m2[1] + m1[7]*m2[4] + m1[8]*m2[7];
+    tmp[8] =  m1[6]*m2[2] + m1[7]*m2[5] + m1[8]*m2[8];
+
+    for(i=0;i<9;i++) {
+       m3[i] = tmp[i];
+    }
+}
+static void  transpose_mat(double[] in, double[] out) {
+       out[0] = in[0];
+       out[1] = in[3];
+       out[2] = in[6];
+
+       out[3] = in[1];
+       out[4] = in[4];
+       out[5] = in[7];
+
+       out[6] = in[2];
+       out[7] = in[5];
+       out[8] = in[8];
+}
+static  double max3( double[] values) {
+     if( values[0] > values[1] ) {
+        if( values[0] > values[2] )
+           return(values[0]);
+        else
+           return(values[2]);
+     } else {
+        if( values[1] > values[2] )
+           return(values[1]);
+        else
+           return(values[2]);
+     }
+  }
+
+    private static final boolean almostEqual(double a, double b) {
+        if (a == b)
+            return true;
+
+        final double EPSILON_ABSOLUTE = 1.0e-6;
+        final double EPSILON_RELATIVE = 1.0e-4;
+        double diff = Math.abs(a-b);
+        double absA = Math.abs(a);
+        double absB = Math.abs(b);
+        double max = (absA >= absB) ? absA : absB;
+
+        if (diff < EPSILON_ABSOLUTE)
+            return true;
+
+        if ((diff / max) < EPSILON_RELATIVE)
+            return true;
+
+        return false;
+    }
+
+    /**
+     * Creates a new object of the same class as this object.
+     *
+     * @return a clone of this instance.
+     * @exception OutOfMemoryError if there is not enough memory.
+     * @see java.lang.Cloneable
+     * @since vecmath 1.3
+     */
+    public Object clone() {
+       Matrix3d m1 = null;
+       try {
+           m1 = (Matrix3d)super.clone();
+       } catch (CloneNotSupportedException e) {
+           // this shouldn't happen, since we are Cloneable
+           throw new InternalError();
+       }
+
+       // Also need to create new tmp arrays (no need to actually clone them)
+       return m1;
+    }
+
+       /**
+        * Get the first matrix element in the first row.
+        * @return Returns the m00.
+        * @since vecmath 1.5
+        */
+       public final  double getM00() {
+               return m00;
+       }
+
+       /**
+        * Set the first matrix element in the first row.
+        * 
+        * @param m00 The m00 to set.
+        * 
+        * @since vecmath 1.5
+        */
+       public final  void setM00(double m00) {
+               this.m00 = m00;
+       }
+
+       /**
+        * Get the second matrix element in the first row.
+        * 
+        * @return Returns the m01.
+        * 
+        * @since vecmath 1.5
+        */
+       public final  double getM01() {
+               return m01;
+       }
+
+       /**
+        * Set the second matrix element in the first row.
+        * 
+        * @param m01 The m01 to set.
+        * 
+        * @since vecmath 1.5
+        */
+       public  final void setM01(double m01) {
+               this.m01 = m01;
+       }
+
+       /**
+        * Get the third matrix element in the first row.
+        * 
+        * @return Returns the m02.
+        * 
+        * @since vecmath 1.5
+        */
+       public final double getM02() {
+               return m02;
+       }
+
+       /**
+        * Set the third matrix element in the first row.
+        * 
+        * @param m02 The m02 to set.
+        * 
+        * @since vecmath 1.5
+        */
+       public final  void setM02(double m02) {
+               this.m02 = m02;
+       }
+
+       /**
+        * Get first matrix element in the second row.
+        * 
+        * @return Returns the m10.
+        * 
+        * @since vecmath 1.5
+        */
+       public final  double getM10() {
+               return m10;
+       }
+
+       /**
+        * Set first matrix element in the second row.
+        * 
+        * @param m10 The m10 to set.
+        * 
+        * @since vecmath 1.5
+        */
+       public final  void setM10(double m10) {
+               this.m10 = m10;
+       }
+
+       /**
+        * Get second matrix element in the second row.
+        * 
+        * @return Returns the m11.
+        * 
+        * @since vecmath 1.5
+        */
+       public final  double getM11() {
+               return m11;
+       }
+
+       /**
+        * Set the second matrix element in the second row.
+        * 
+        * @param m11 The m11 to set.
+        * 
+        * @since vecmath 1.5
+        */
+       public final  void setM11(double m11) {
+               this.m11 = m11;
+       }
+
+       /**
+        * Get the third matrix element in the second row.
+        * 
+        * @return Returns the m12.
+        * 
+        * @since vecmath 1.5
+        */
+       public final  double getM12() {
+               return m12;
+       }
+
+       /**
+        * Set the third matrix element in the second row.
+        * 
+        * @param m12 The m12 to set.
+        * 
+        * @since vecmath 1.5
+        */
+       public final  void setM12(double m12) {
+               this.m12 = m12;
+       }
+
+       /**
+        * Get the first matrix element in the third row.
+        * 
+        * @return Returns the m20.
+        * 
+        * @since vecmath 1.5
+        */
+       public final  double getM20() {
+               return m20;
+       }
+
+       /**
+        * Set the first matrix element in the third row.
+        * 
+        * @param m20 The m20 to set.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setM20(double m20) {
+               this.m20 = m20;
+       }
+
+       /**
+        * Get the second matrix element in the third row.
+        * 
+        * @return Returns the m21.
+        * 
+        * @since vecmath 1.5
+        */
+       public final double getM21() {
+               return m21;
+       }
+
+       /**
+        * Set the second matrix element in the third row.
+        * 
+        * @param m21 The m21 to set.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setM21(double m21) {
+               this.m21 = m21;
+       }
+
+       /**
+        * Get the third matrix element in the third row .
+        * 
+        * @return Returns the m22.
+        * 
+        * @since vecmath 1.5
+        */
+       public final double getM22() {
+               return m22;
+       }
+
+       /**
+        * Set the third matrix element in the third row.
+        * 
+        * @param m22 The m22 to set.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setM22(double m22) {
+               this.m22 = m22;
+       }
+
+}
diff --git a/javax.vecmath/src/javax/vecmath/Matrix3f.java b/javax.vecmath/src/javax/vecmath/Matrix3f.java
new file mode 100644 (file)
index 0000000..f02cb47
--- /dev/null
@@ -0,0 +1,2313 @@
+/*
+ * $RCSfile: Matrix3f.java,v $
+ *
+ * Copyright 1996-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ * $Revision: 1.8 $
+ * $Date: 2008/02/28 20:18:50 $
+ * $State: Exp $
+ */
+
+package javax.vecmath;
+
+import java.lang.Math;
+
+/**
+ * A single precision floating point 3 by 3 matrix.
+ * Primarily to support 3D rotations.
+ *
+ */
+public class Matrix3f implements java.io.Serializable, Cloneable {
+
+  // Compatible with 1.1
+  static final long serialVersionUID = 329697160112089834L;
+
+  /** 
+    * The first matrix element in the first row.
+    */
+    public     float   m00;
+
+  /** 
+    * The second matrix element in the first row.
+    */
+    public     float   m01;
+
+  /** 
+    * The third matrix element in the first row.
+    */
+    public     float   m02;
+
+  /** 
+    * The first matrix element in the second row.
+    */
+    public     float   m10;
+
+  /** 
+    * The second matrix element in the second row.
+    */
+    public     float   m11;
+
+  /** 
+    * The third matrix element in the second row.
+    */
+    public     float   m12;
+
+  /** 
+    * The first matrix element in the third row.
+    */
+    public     float   m20;
+
+  /** 
+    * The second matrix element in the third row.
+    */
+    public     float   m21;
+
+  /** 
+    * The third matrix element in the third row.
+    */
+    public     float   m22;
+    /*
+    double[]    tmp       = new double[9];  // scratch matrix
+    double[]    tmp_rot   = new double[9];  // scratch matrix
+    double[]    tmp_scale = new double[3];  // scratch matrix
+    */
+    private static final double EPS = 1.0E-8;
+
+  
+
+    /**
+     * Constructs and initializes a Matrix3f from the specified nine values.
+     * @param m00 the [0][0] element
+     * @param m01 the [0][1] element
+     * @param m02 the [0][2] element
+     * @param m10 the [1][0] element
+     * @param m11 the [1][1] element
+     * @param m12 the [1][2] element
+     * @param m20 the [2][0] element
+     * @param m21 the [2][1] element
+     * @param m22 the [2][2] element
+     */
+    public Matrix3f(float m00, float m01, float m02,
+                   float m10, float m11, float m12,
+                   float m20, float m21, float m22)
+    {
+       this.m00 = m00;
+       this.m01 = m01;
+       this.m02 = m02;
+
+       this.m10 = m10;
+       this.m11 = m11;
+       this.m12 = m12;
+
+       this.m20 = m20;
+       this.m21 = m21;
+       this.m22 = m22;
+
+    }
+
+    /**
+     * Constructs and initializes a Matrix3f from the specified 
+     * nine-element array.   this.m00 =v[0], this.m01=v[1], etc.
+     * @param v the array of length 9 containing in order
+     */
+    public Matrix3f(float[] v)
+    {
+       this.m00 = v[ 0];
+       this.m01 = v[ 1];
+       this.m02 = v[ 2];
+
+       this.m10 = v[ 3];
+       this.m11 = v[ 4];
+       this.m12 = v[ 5];
+
+       this.m20 = v[ 6];
+       this.m21 = v[ 7];
+       this.m22 = v[ 8];
+
+    }
+
+   /**   
+     *  Constructs a new matrix with the same values as the 
+     *  Matrix3d parameter.
+     *  @param m1  the source matrix
+     */  
+   public Matrix3f(Matrix3d m1) 
+   { 
+        this.m00 = (float)m1.m00;
+        this.m01 = (float)m1.m01;
+        this.m02 = (float)m1.m02;
+        this.m10 = (float)m1.m10;
+        this.m11 = (float)m1.m11;
+        this.m12 = (float)m1.m12;
+        this.m20 = (float)m1.m20;
+        this.m21 = (float)m1.m21;
+        this.m22 = (float)m1.m22;
+
+   } 
+   /**
+     *  Constructs a new matrix with the same values as the
+     *  Matrix3f parameter.
+     *  @param m1  the source matrix
+     */  
+   public Matrix3f(Matrix3f m1)
+   {
+        this.m00 = m1.m00;
+        this.m01 = m1.m01;
+        this.m02 = m1.m02;
+        this.m10 = m1.m10;
+        this.m11 = m1.m11;
+        this.m12 = m1.m12;
+        this.m20 = m1.m20;
+        this.m21 = m1.m21;
+        this.m22 = m1.m22;
+
+   }
+
+    /**
+     * Constructs and initializes a Matrix3f to all zeros.
+     */
+    public Matrix3f()
+    {
+       this.m00 = (float) 0.0;
+       this.m01 = (float) 0.0;
+       this.m02 = (float) 0.0;
+
+       this.m10 = (float) 0.0;
+       this.m11 = (float) 0.0;
+       this.m12 = (float) 0.0;
+
+       this.m20 = (float) 0.0;
+       this.m21 = (float) 0.0;
+       this.m22 = (float) 0.0;
+
+    }
+
+   /**
+     * Returns a string that contains the values of this Matrix3f.
+     * @return the String representation
+     */
+    public String toString() {
+      return
+       this.m00 + ", " + this.m01 + ", " + this.m02 + "\n" +
+       this.m10 + ", " + this.m11 + ", " + this.m12 + "\n" +
+       this.m20 + ", " + this.m21 + ", " + this.m22 + "\n";
+    }
+
+    /**
+     * Sets this Matrix3f to identity.
+     */
+    public final void setIdentity()
+    {
+       this.m00 = (float) 1.0;
+       this.m01 = (float) 0.0;
+       this.m02 = (float) 0.0;
+
+       this.m10 = (float) 0.0;
+       this.m11 = (float) 1.0;
+       this.m12 = (float) 0.0;
+
+       this.m20 = (float) 0.0;
+       this.m21 = (float) 0.0;
+       this.m22 = (float) 1.0;
+    }
+
+   /**
+     * Sets the scale component of the current matrix by factoring
+     * out the current scale (by doing an SVD) and multiplying by 
+     * the new scale.
+     * @param scale  the new scale amount
+     */
+    public final void setScale(float scale)
+    {
+       double[]    tmp_rot = new double[9];  // scratch matrix
+       double[]    tmp_scale = new double[3];  // scratch matrix
+       
+       getScaleRotate( tmp_scale, tmp_rot );
+        this.m00 = (float)(tmp_rot[0] * scale);
+        this.m01 = (float)(tmp_rot[1] * scale);
+        this.m02 = (float)(tmp_rot[2] * scale);
+        this.m10 = (float)(tmp_rot[3] * scale);
+        this.m11 = (float)(tmp_rot[4] * scale);
+        this.m12 = (float)(tmp_rot[5] * scale);
+        this.m20 = (float)(tmp_rot[6] * scale);
+        this.m21 = (float)(tmp_rot[7] * scale);
+        this.m22 = (float)(tmp_rot[8] * scale);
+
+    }
+
+    /**
+     * Sets the specified element of this matrix3f to the value provided.
+     * @param row the row number to be modified (zero indexed)
+     * @param column the column number to be modified (zero indexed)
+     * @param value the new value
+     */
+    public final void setElement(int row, int column, float value)
+    {
+       switch (row) 
+         {
+         case 0:
+           switch(column)
+             {
+             case 0:
+               this.m00 = value;
+               break;
+             case 1:
+               this.m01 = value;
+               break;
+             case 2:
+               this.m02 = value;
+               break;
+             default:
+               throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3f0"));
+             }
+           break;
+
+         case 1:
+           switch(column) 
+             {
+             case 0:
+               this.m10 = value;
+               break;
+             case 1:
+               this.m11 = value;
+               break;
+             case 2:
+               this.m12 = value;
+               break;
+             default:
+               throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3f0"));
+             }
+           break;
+         
+         case 2:
+           switch(column) 
+             {
+             case 0:
+               this.m20 = value;
+               break;
+             case 1:
+               this.m21 = value;
+               break;
+             case 2:
+               this.m22 = value;
+               break;
+             default:
+
+               throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3f0"));
+             }
+           break;
+
+         default:
+               throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3f0"));
+         }
+    }
+
+    /**
+     * Copies the matrix values in the specified row into the vector parameter. 
+     * @param row  the matrix row
+     * @param v    the vector into which the matrix row values will be copied
+     */
+    public final void getRow(int row, Vector3f v) {
+         if( row == 0 ) {
+           v.x = m00;
+           v.y = m01;
+           v.z = m02;
+        } else if(row == 1) {
+           v.x = m10;
+           v.y = m11;
+           v.z = m12;
+        } else if(row == 2) {
+           v.x = m20;
+           v.y = m21;
+           v.z = m22;
+        } else {
+          throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3f1"));
+        }
+
+    }
+
+    /**
+     * Copies the matrix values in the specified row into the array parameter. 
+     * @param row  the matrix row
+     * @param v    the array into which the matrix row values will be copied 
+     */  
+    public final void getRow(int row, float v[]) {
+        if( row == 0 ) {
+           v[0] = m00; 
+           v[1] = m01;
+           v[2] = m02;
+        } else if(row == 1) {
+           v[0] = m10;
+           v[1] = m11;
+           v[2] = m12;
+        } else if(row == 2) {
+           v[0] = m20;
+           v[1] = m21;
+           v[2] = m22;
+        } else {
+          throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3f1"));
+        }
+
+    }
+
+    /**
+     * Copies the matrix values in the specified column into the vector 
+     * parameter.
+     * @param column  the matrix column
+     * @param v    the vector into which the matrix row values will be copied
+     */  
+    public final void getColumn(int column, Vector3f v) {
+        if( column == 0 ) {
+           v.x = m00;
+           v.y = m10;
+           v.z = m20;
+        } else if(column == 1) {
+           v.x = m01;
+           v.y = m11;
+           v.z = m21;
+        }else if(column == 2){
+           v.x = m02;
+           v.y = m12;
+           v.z = m22;
+        } else {
+           throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3f3"));
+        }
+
+    }
+
+    /**  
+     * Copies the matrix values in the specified column into the array 
+     * parameter.
+     * @param column  the matrix column
+     * @param v    the array into which the matrix row values will be copied
+     */  
+    public final void getColumn(int column, float v[]) {
+        if( column == 0 ) {
+           v[0] = m00;
+           v[1] = m10;
+           v[2] = m20;
+        } else if(column == 1) {
+           v[0] = m01;
+           v[1] = m11;
+           v[2] = m21;
+        }else if(column == 2) {
+           v[0] = m02;
+           v[1] = m12;
+           v[2] = m22;
+        }else {
+          throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3f3"));
+        }
+    }
+
+    /**
+     * Retrieves the value at the specified row and column of this
+     * matrix.
+     * @param row the row number to be retrieved (zero indexed)
+     * @param column the column number to be retrieved (zero indexed)
+     * @return the value at the indexed element.
+     */
+    public final float getElement(int row, int column)
+    {
+       switch (row) 
+         {
+         case 0:
+           switch(column)
+             {
+             case 0:
+               return(this.m00);
+             case 1:
+               return(this.m01);
+             case 2:
+               return(this.m02);
+             default:
+                break;
+             }
+           break;
+         case 1:
+           switch(column) 
+             {
+             case 0:
+               return(this.m10);
+             case 1:
+               return(this.m11);
+             case 2:
+               return(this.m12);
+             default:
+                break;
+             }
+           break;
+         
+         case 2:
+           switch(column) 
+             {
+             case 0:
+               return(this.m20);
+             case 1:
+               return(this.m21);
+             case 2:
+               return(this.m22);
+             default:
+                break;
+             }
+           break;
+           
+         default:
+            break;
+         }
+       throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3f5"));
+    }
+
+    /**
+     * Sets the specified row of this matrix3f to the three values provided.
+     * @param row the row number to be modified (zero indexed)
+     * @param x the first column element
+     * @param y the second column element
+     * @param z the third column element
+     */
+    public final void setRow(int row, float x, float y, float z)
+    {
+       switch (row) {
+       case 0:
+           this.m00 = x;
+           this.m01 = y;
+           this.m02 = z;
+           break;
+
+       case 1:
+           this.m10 = x;
+           this.m11 = y;
+           this.m12 = z;
+           break;
+
+       case 2:
+           this.m20 = x;
+           this.m21 = y;
+           this.m22 = z;
+           break;
+
+       default:
+         throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3f6"));
+       }
+    }
+
+    /**
+     * Sets the specified row of this matrix3f to the Vector provided.
+     * @param row the row number to be modified (zero indexed)
+     * @param v the replacement row
+     */
+    public final void setRow(int row, Vector3f v)
+    {
+       switch (row) {
+       case 0:
+           this.m00 = v.x;
+           this.m01 = v.y;
+           this.m02 = v.z;
+           break;
+
+       case 1:
+           this.m10 = v.x;
+           this.m11 = v.y;
+           this.m12 = v.z;
+           break;
+
+       case 2:
+           this.m20 = v.x;
+           this.m21 = v.y;
+           this.m22 = v.z;
+           break;
+
+       default:
+         throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3f6"));
+       }
+    }
+
+    /**
+     * Sets the specified row of this matrix3f to the three values provided.
+     * @param row the row number to be modified (zero indexed)
+     * @param v the replacement row
+     */
+    public final void setRow(int row, float v[])
+    {
+       switch (row) {
+       case 0:
+           this.m00 = v[0];
+           this.m01 = v[1];
+           this.m02 = v[2];
+           break;
+
+       case 1:
+           this.m10 = v[0];
+           this.m11 = v[1];
+           this.m12 = v[2];
+           break;
+
+       case 2:
+           this.m20 = v[0];
+           this.m21 = v[1];
+           this.m22 = v[2];
+           break;
+
+       default:
+           throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3f6"));
+       }
+    }
+
+    /**
+     * Sets the specified column of this matrix3f to the three values provided.
+     * @param column the column number to be modified (zero indexed)
+     * @param x the first row element
+     * @param y the second row element
+     * @param z the third row element
+     */
+    public final void setColumn(int column, float x, float y, float z)
+    {
+       switch (column) {
+       case 0:
+           this.m00 = x;
+           this.m10 = y;
+           this.m20 = z;
+           break;
+
+       case 1:
+           this.m01 = x;
+           this.m11 = y;
+           this.m21 = z;
+           break;
+
+       case 2:
+           this.m02 = x;
+           this.m12 = y;
+           this.m22 = z;
+           break;
+
+       default:
+           throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3f9"));
+       }
+    }
+
+    /**
+     * Sets the specified column of this matrix3f to the vector provided.
+     * @param column the column number to be modified (zero indexed)
+     * @param v the replacement column
+     */
+    public final void setColumn(int column, Vector3f v)
+    {
+       switch (column) {
+       case 0:
+           this.m00 = v.x;
+           this.m10 = v.y;
+           this.m20 = v.z;
+           break;
+
+       case 1:
+           this.m01 = v.x;
+           this.m11 = v.y;
+           this.m21 = v.z;
+           break;
+
+       case 2:
+           this.m02 = v.x;
+           this.m12 = v.y;
+           this.m22 = v.z;
+           break;
+
+       default:
+           throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3f9"));
+       }
+    }
+
+    /**
+     * Sets the specified column of this matrix3f to the three values provided.
+     * @param column the column number to be modified (zero indexed)
+     * @param v the replacement column
+     */
+    public final void setColumn(int column, float v[])
+    {
+       switch (column) {
+       case 0:
+           this.m00 = v[0];
+           this.m10 = v[1];
+           this.m20 = v[2];
+           break;
+
+       case 1:
+           this.m01 = v[0];
+           this.m11 = v[1];
+           this.m21 = v[2];
+           break;
+
+       case 2:
+           this.m02 = v[0];
+           this.m12 = v[1];
+           this.m22 = v[2];
+           break;
+
+       default:
+           throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3f9"));
+       }
+    }
+
+   /**
+     * Performs an SVD normalization of this matrix to calculate
+     * and return the uniform scale factor. If the matrix has non-uniform 
+     * scale factors, the largest of the x, y, and z scale factors will 
+     * be returned. This matrix is not modified.
+     * @return  the scale factor of this matrix
+     */  
+    public final float getScale()
+    {
+       
+       double[]    tmp_rot = new double[9];  // scratch matrix
+       double[]    tmp_scale = new double[3];  // scratch matrix
+       getScaleRotate(tmp_scale, tmp_rot);
+
+        return( (float)Matrix3d.max3(tmp_scale ));
+
+    } 
+
+   /**
+     *  Adds a scalar to each component of this matrix.
+     *  @param scalar  the scalar adder
+     */
+    public final void add(float scalar)
+    {
+        m00 += scalar;
+        m01 += scalar;
+        m02 += scalar;
+        m10 += scalar;
+        m11 += scalar;
+        m12 += scalar;
+        m20 += scalar;
+        m21 += scalar;
+        m22 += scalar;
+    }
+
+   /** 
+     *  Adds a scalar to each component of the matrix m1 and places
+     *  the result into this.  Matrix m1 is not modified.
+     *  @param scalar  the scalar adder.
+     *  @param m1  the original matrix values
+     */   
+    public final void add(float scalar, Matrix3f m1) 
+    {
+        this.m00 = m1.m00 +  scalar;
+        this.m01 = m1.m01 +  scalar;
+        this.m02 = m1.m02 +  scalar;
+        this.m10 = m1.m10 +  scalar;
+        this.m11 = m1.m11 +  scalar;
+        this.m12 = m1.m12 +  scalar;
+        this.m20 = m1.m20 +  scalar;
+        this.m21 = m1.m21 +  scalar;
+        this.m22 = m1.m22 +  scalar;
+    } 
+
+    /**
+     * Sets the value of this matrix to the matrix sum of matrices m1 and m2.
+     * @param m1 the first matrix
+     * @param m2 the second matrix
+     */
+    public final void add(Matrix3f m1, Matrix3f m2)
+    {
+       this.m00 = m1.m00 + m2.m00;
+       this.m01 = m1.m01 + m2.m01;
+       this.m02 = m1.m02 + m2.m02;
+
+       this.m10 = m1.m10 + m2.m10;
+       this.m11 = m1.m11 + m2.m11;
+       this.m12 = m1.m12 + m2.m12;
+
+       this.m20 = m1.m20 + m2.m20;
+       this.m21 = m1.m21 + m2.m21;
+       this.m22 = m1.m22 + m2.m22;
+    }
+
+    /**
+     * Sets the value of this matrix to the matrix sum of itself and 
+     * matrix m1.
+     * @param m1 the other matrix
+     */
+    public final void add(Matrix3f m1)
+    {  
+        this.m00 += m1.m00;
+        this.m01 += m1.m01;
+        this.m02 += m1.m02;
+        this.m10 += m1.m10;
+        this.m11 += m1.m11;
+        this.m12 += m1.m12;
+        this.m20 += m1.m20;
+        this.m21 += m1.m21;
+        this.m22 += m1.m22;
+    }  
+
+    /**
+     * Sets the value of this matrix to the matrix difference
+     * of matrices m1 and m2.
+     * @param m1 the first matrix
+     * @param m2 the second matrix
+     */
+    public final void sub(Matrix3f m1, Matrix3f m2)
+    {
+       this.m00 = m1.m00 - m2.m00;
+       this.m01 = m1.m01 - m2.m01;
+       this.m02 = m1.m02 - m2.m02;
+
+       this.m10 = m1.m10 - m2.m10;
+       this.m11 = m1.m11 - m2.m11;
+       this.m12 = m1.m12 - m2.m12;
+
+       this.m20 = m1.m20 - m2.m20;
+       this.m21 = m1.m21 - m2.m21;
+       this.m22 = m1.m22 - m2.m22;
+    }
+
+    /**  
+     * Sets the value of this matrix to the matrix difference
+     * of itself and matrix m1 (this = this - m1).
+     * @param m1 the other matrix
+     */  
+    public final void sub(Matrix3f m1)
+    {  
+        this.m00 -= m1.m00;
+        this.m01 -= m1.m01;
+        this.m02 -= m1.m02;
+        this.m10 -= m1.m10;
+        this.m11 -= m1.m11;
+        this.m12 -= m1.m12;
+        this.m20 -= m1.m20;
+        this.m21 -= m1.m21;
+        this.m22 -= m1.m22;
+    }
+
+    /**
+     * Sets the value of this matrix to its transpose.
+     */
+    public final void transpose()
+    {
+       float temp;
+
+       temp = this.m10;
+       this.m10 = this.m01;
+       this.m01 = temp;
+
+       temp = this.m20;
+       this.m20 = this.m02;
+       this.m02 = temp;
+
+       temp = this.m21;
+       this.m21 = this.m12;
+       this.m12 = temp;
+    }
+
+    /**
+     * Sets the value of this matrix to the transpose of the argument matrix.
+     * @param m1 the matrix to be transposed
+     */
+    public final void transpose(Matrix3f m1)
+    {
+       if (this != m1) {
+           this.m00 = m1.m00;
+           this.m01 = m1.m10;
+           this.m02 = m1.m20;
+
+           this.m10 = m1.m01;
+           this.m11 = m1.m11;
+           this.m12 = m1.m21;
+
+           this.m20 = m1.m02;
+           this.m21 = m1.m12;
+           this.m22 = m1.m22;
+       } else
+           this.transpose();
+    }
+
+    /**
+     * Sets the value of this matrix to the matrix conversion of the
+     * (single precision) quaternion argument.
+     * @param q1 the quaternion to be converted
+     */
+    public final void set(Quat4f q1)
+    {
+       this.m00 = 1.0f - 2.0f*q1.y*q1.y - 2.0f*q1.z*q1.z;
+       this.m10 = 2.0f*(q1.x*q1.y + q1.w*q1.z);
+       this.m20 = 2.0f*(q1.x*q1.z - q1.w*q1.y);
+
+       this.m01 = 2.0f*(q1.x*q1.y - q1.w*q1.z);
+       this.m11 = 1.0f - 2.0f*q1.x*q1.x - 2.0f*q1.z*q1.z;
+       this.m21 = 2.0f*(q1.y*q1.z + q1.w*q1.x);
+
+       this.m02 = 2.0f*(q1.x*q1.z + q1.w*q1.y);
+       this.m12 = 2.0f*(q1.y*q1.z - q1.w*q1.x);
+       this.m22 = 1.0f - 2.0f*q1.x*q1.x - 2.0f*q1.y*q1.y;
+    }
+
+    /**
+     * Sets the value of this matrix to the matrix conversion of the
+     * (single precision) axis and angle argument.
+     * @param a1 the axis and angle to be converted
+     */
+    public final void set(AxisAngle4f a1)
+    {
+      float mag = (float)Math.sqrt( a1.x*a1.x + a1.y*a1.y + a1.z*a1.z);
+      if( mag < EPS ) {
+        m00 = 1.0f;
+        m01 = 0.0f;
+        m02 = 0.0f;
+
+        m10 = 0.0f;
+        m11 = 1.0f;
+        m12 = 0.0f;
+
+        m20 = 0.0f;
+        m21 = 0.0f;
+        m22 = 1.0f;
+      } else {
+        mag = 1.0f/mag;
+         float ax = a1.x*mag;
+         float ay = a1.y*mag;
+         float az = a1.z*mag;
+
+         float sinTheta = (float)Math.sin((float)a1.angle);
+         float cosTheta = (float)Math.cos((float)a1.angle);
+         float t = (float)1.0 - cosTheta;
+
+         float xz = ax * az;    
+         float xy = ax * ay;
+         float yz = ay * az;
+
+         m00 = t * ax * ax + cosTheta;
+         m01 = t * xy - sinTheta * az;
+         m02 = t * xz + sinTheta * ay;
+    
+         m10 = t * xy + sinTheta * az;
+         m11 = t * ay * ay + cosTheta;
+         m12 = t * yz - sinTheta * ax;
+    
+         m20 = t * xz - sinTheta * ay;
+         m21 = t * yz + sinTheta * ax;
+         m22 = t * az * az + cosTheta;
+      }
+
+    }
+
+    /**
+     * Sets the value of this matrix to the matrix conversion of the
+     * (double precision) axis and angle argument.
+     * @param a1 the axis and angle to be converted
+     */
+    public final void set(AxisAngle4d a1)
+    {
+      double mag = Math.sqrt( a1.x*a1.x + a1.y*a1.y + a1.z*a1.z);
+      if( mag < EPS ) {
+        m00 = 1.0f;
+        m01 = 0.0f;
+        m02 = 0.0f;
+
+        m10 = 0.0f;
+        m11 = 1.0f;
+        m12 = 0.0f;
+
+        m20 = 0.0f;
+        m21 = 0.0f;
+        m22 = 1.0f;
+      } else {
+        mag = 1.0/mag;
+         double ax = a1.x*mag;
+         double ay = a1.y*mag;
+         double az = a1.z*mag;
+
+         double sinTheta = Math.sin(a1.angle);
+         double cosTheta = Math.cos(a1.angle);
+         double t = 1.0 - cosTheta;
+
+         double xz = ax * az;    
+         double xy = ax * ay;
+         double yz = ay * az;
+
+         m00 = (float)(t * ax * ax + cosTheta);
+         m01 = (float)(t * xy - sinTheta * az);
+         m02 = (float)(t * xz + sinTheta * ay);
+    
+         m10 = (float)(t * xy + sinTheta * az);
+         m11 = (float)(t * ay * ay + cosTheta);
+         m12 = (float)(t * yz - sinTheta * ax);
+    
+         m20 = (float)(t * xz - sinTheta * ay);
+         m21 = (float)(t * yz + sinTheta * ax);
+         m22 = (float)(t * az * az + cosTheta);
+      }
+
+    }
+
+    /**
+     * Sets the value of this matrix to the matrix conversion of the
+     * (single precision) quaternion argument.
+     * @param q1 the quaternion to be converted
+     */
+    public final void set(Quat4d q1)
+    {
+       this.m00 = (float) (1.0 - 2.0*q1.y*q1.y - 2.0*q1.z*q1.z);
+       this.m10 = (float) (2.0*(q1.x*q1.y + q1.w*q1.z));
+       this.m20 = (float) (2.0*(q1.x*q1.z - q1.w*q1.y));
+
+       this.m01 = (float) (2.0*(q1.x*q1.y - q1.w*q1.z));
+       this.m11 = (float) (1.0 - 2.0*q1.x*q1.x - 2.0*q1.z*q1.z);
+       this.m21 = (float) (2.0*(q1.y*q1.z + q1.w*q1.x));
+
+       this.m02 = (float) (2.0*(q1.x*q1.z + q1.w*q1.y));
+       this.m12 = (float) (2.0*(q1.y*q1.z - q1.w*q1.x));
+       this.m22 = (float) (1.0 - 2.0*q1.x*q1.x - 2.0*q1.y*q1.y);
+    }
+
+    /** 
+     *  Sets the values in this Matrix3f equal to the row-major 
+     *  array parameter (ie, the first three elements of the 
+     *  array will be copied into the first row of this matrix, etc.). 
+     *  @param m  the single precision array of length 9 
+     */   
+    public final void set(float[] m) 
+    {
+       m00 = m[0];
+       m01 = m[1];
+       m02 = m[2];
+       m10 = m[3];
+       m11 = m[4];
+       m12 = m[5];
+       m20 = m[6];
+       m21 = m[7];
+       m22 = m[8];
+
+       
+    } 
+
+    /**
+     * Sets the value of this matrix to the value of the Matrix3f 
+     * argument. 
+     * @param m1 the source matrix3f 
+     */  
+    public final void set(Matrix3f m1) {
+
+        this.m00 = m1.m00;
+        this.m01 = m1.m01;
+        this.m02 = m1.m02;
+
+        this.m10 = m1.m10;
+        this.m11 = m1.m11;
+        this.m12 = m1.m12;
+
+        this.m20 = m1.m20;
+        this.m21 = m1.m21;
+        this.m22 = m1.m22;
+
+    }
+
+    /**
+     * Sets the value of this matrix to the float value of the Matrix3d 
+     * argument. 
+     * @param m1 the source matrix3d 
+     */  
+    public final void set(Matrix3d m1) { 
+        this.m00 = (float)m1.m00; 
+        this.m01 = (float)m1.m01; 
+        this.m02 = (float)m1.m02; 
+        this.m10 = (float)m1.m10; 
+        this.m11 = (float)m1.m11;
+        this.m12 = (float)m1.m12;
+        this.m20 = (float)m1.m20;
+        this.m21 = (float)m1.m21; 
+        this.m22 = (float)m1.m22;
+    }
+
+    /**
+     * Sets the value of this matrix to the matrix inverse
+     * of the passed matrix m1.
+     * @param m1 the matrix to be inverted
+     */
+    public final void invert(Matrix3f m1)
+    {
+        invertGeneral( m1);
+    }
+
+    /**
+     * Inverts this matrix in place.
+     */
+    public final void invert()
+    {
+       invertGeneral( this );
+    }
+
+    /**
+     * General invert routine.  Inverts m1 and places the result in "this".
+     * Note that this routine handles both the "this" version and the
+     * non-"this" version.
+     *
+     * Also note that since this routine is slow anyway, we won't worry
+     * about allocating a little bit of garbage.
+     */
+    private final void invertGeneral(Matrix3f  m1) {
+       double temp[] = new double[9];
+       double result[] = new double[9];
+       int row_perm[] = new int[3];
+       int i, r, c;
+
+       // Use LU decomposition and backsubstitution code specifically
+       // for floating-point 3x3 matrices.
+
+       // Copy source matrix to t1tmp 
+        temp[0] = (double)m1.m00;
+        temp[1] = (double)m1.m01;
+        temp[2] = (double)m1.m02;
+        temp[3] = (double)m1.m10;
+        temp[4] = (double)m1.m11;
+        temp[5] = (double)m1.m12;
+        temp[6] = (double)m1.m20;
+        temp[7] = (double)m1.m21;
+        temp[8] = (double)m1.m22;
+
+       // Calculate LU decomposition: Is the matrix singular? 
+       if (!luDecomposition(temp, row_perm)) {
+           // Matrix has no inverse 
+           throw new SingularMatrixException(VecMathI18N.getString("Matrix3f12"));
+       }
+
+       // Perform back substitution on the identity matrix 
+        for(i=0;i<9;i++) result[i] = 0.0;
+        result[0] = 1.0; result[4] = 1.0; result[8] = 1.0;
+       luBacksubstitution(temp, row_perm, result);
+
+        this.m00 = (float)result[0];
+        this.m01 = (float)result[1];
+        this.m02 = (float)result[2];
+
+        this.m10 = (float)result[3];
+        this.m11 = (float)result[4];
+        this.m12 = (float)result[5];
+        this.m20 = (float)result[6];
+        this.m21 = (float)result[7];
+        this.m22 = (float)result[8];
+
+    }
+
+    /**
+     * Given a 3x3 array "matrix0", this function replaces it with the 
+     * LU decomposition of a row-wise permutation of itself.  The input 
+     * parameters are "matrix0" and "dimen".  The array "matrix0" is also 
+     * an output parameter.  The vector "row_perm[3]" is an output 
+     * parameter that contains the row permutations resulting from partial 
+     * pivoting.  The output parameter "even_row_xchg" is 1 when the 
+     * number of row exchanges is even, or -1 otherwise.  Assumes data 
+     * type is always double.
+     *
+     * This function is similar to luDecomposition, except that it
+     * is tuned specifically for 3x3 matrices.
+     *
+     * @return true if the matrix is nonsingular, or false otherwise.
+     */
+    //
+    // Reference: Press, Flannery, Teukolsky, Vetterling, 
+    //       _Numerical_Recipes_in_C_, Cambridge University Press, 
+    //       1988, pp 40-45.
+    //
+    static boolean luDecomposition(double[] matrix0,
+                                  int[] row_perm) {
+
+       double row_scale[] = new double[3];
+
+       // Determine implicit scaling information by looping over rows 
+       {
+           int i, j;
+           int ptr, rs;
+           double big, temp;
+
+           ptr = 0;
+           rs = 0;
+
+           // For each row ... 
+           i = 3;
+           while (i-- != 0) {
+               big = 0.0;
+
+               // For each column, find the largest element in the row 
+               j = 3;
+               while (j-- != 0) {
+                   temp = matrix0[ptr++];
+                   temp = Math.abs(temp);
+                   if (temp > big) {
+                       big = temp;
+                   }
+               }
+
+               // Is the matrix singular? 
+               if (big == 0.0) {
+                   return false;
+               }
+               row_scale[rs++] = 1.0 / big;
+           }
+       }
+
+       {
+           int j;
+           int mtx;
+
+           mtx = 0;
+
+           // For all columns, execute Crout's method 
+           for (j = 0; j < 3; j++) {
+               int i, imax, k;
+               int target, p1, p2;
+               double sum, big, temp;
+
+               // Determine elements of upper diagonal matrix U 
+               for (i = 0; i < j; i++) {
+                   target = mtx + (3*i) + j;
+                   sum = matrix0[target];
+                   k = i;
+                   p1 = mtx + (3*i);
+                   p2 = mtx + j;
+                   while (k-- != 0) {
+                       sum -= matrix0[p1] * matrix0[p2];
+                       p1++;
+                       p2 += 3;
+                   }
+                   matrix0[target] = sum;
+               }
+
+               // Search for largest pivot element and calculate
+               // intermediate elements of lower diagonal matrix L.
+               big = 0.0;
+               imax = -1;
+               for (i = j; i < 3; i++) {
+                   target = mtx + (3*i) + j;
+                   sum = matrix0[target];
+                   k = j;
+                   p1 = mtx + (3*i);
+                   p2 = mtx + j;
+                   while (k-- != 0) {
+                       sum -= matrix0[p1] * matrix0[p2];
+                       p1++;
+                       p2 += 3;
+                   }
+                   matrix0[target] = sum;
+
+                   // Is this the best pivot so far? 
+                   if ((temp = row_scale[i] * Math.abs(sum)) >= big) {
+                       big = temp;
+                       imax = i;
+                   }
+               }
+
+               if (imax < 0) {
+                   throw new RuntimeException(VecMathI18N.getString("Matrix3f13"));
+               }
+
+               // Is a row exchange necessary? 
+               if (j != imax) {
+                   // Yes: exchange rows 
+                   k = 3;
+                   p1 = mtx + (3*imax);
+                   p2 = mtx + (3*j);
+                   while (k-- != 0) {
+                       temp = matrix0[p1];
+                       matrix0[p1++] = matrix0[p2];
+                       matrix0[p2++] = temp;
+                   }
+
+                   // Record change in scale factor 
+                   row_scale[imax] = row_scale[j];
+               }
+
+               // Record row permutation 
+               row_perm[j] = imax;
+
+               // Is the matrix singular 
+               if (matrix0[(mtx + (3*j) + j)] == 0.0) {
+                   return false;
+               }
+
+               // Divide elements of lower diagonal matrix L by pivot 
+               if (j != (3-1)) {
+                   temp = 1.0 / (matrix0[(mtx + (3*j) + j)]);
+                   target = mtx + (3*(j+1)) + j;
+                   i = 2 - j;
+                   while (i-- != 0) {
+                       matrix0[target] *= temp;
+                       target += 3;
+                   }
+               }
+           }
+       }
+
+       return true;
+    }
+
+    /**
+     * Solves a set of linear equations.  The input parameters "matrix1",
+     * and "row_perm" come from luDecompostionD3x3 and do not change
+     * here.  The parameter "matrix2" is a set of column vectors assembled
+     * into a 3x3 matrix of floating-point values.  The procedure takes each
+     * column of "matrix2" in turn and treats it as the right-hand side of the
+     * matrix equation Ax = LUx = b.  The solution vector replaces the
+     * original column of the matrix.
+     *
+     * If "matrix2" is the identity matrix, the procedure replaces its contents
+     * with the inverse of the matrix from which "matrix1" was originally
+     * derived.
+     */
+    //
+    // Reference: Press, Flannery, Teukolsky, Vetterling, 
+    //       _Numerical_Recipes_in_C_, Cambridge University Press, 
+    //       1988, pp 44-45.
+    //
+    static void luBacksubstitution(double[] matrix1,
+                                  int[] row_perm,
+                                  double[] matrix2) {
+
+       int i, ii, ip, j, k;
+       int rp;
+       int cv, rv;
+       
+       //      rp = row_perm;
+       rp = 0;
+
+       // For each column vector of matrix2 ... 
+       for (k = 0; k < 3; k++) {
+           //      cv = &(matrix2[0][k]);
+           cv = k;
+           ii = -1;
+
+           // Forward substitution 
+           for (i = 0; i < 3; i++) {
+               double sum;
+
+               ip = row_perm[rp+i];
+               sum = matrix2[cv+3*ip];
+               matrix2[cv+3*ip] = matrix2[cv+3*i];
+               if (ii >= 0) {
+                   //              rv = &(matrix1[i][0]);
+                   rv = i*3;
+                   for (j = ii; j <= i-1; j++) {
+                       sum -= matrix1[rv+j] * matrix2[cv+3*j];
+                   }
+               }
+               else if (sum != 0.0) {
+                   ii = i;
+               }
+               matrix2[cv+3*i] = sum;
+           }
+
+           // Backsubstitution 
+           //      rv = &(matrix1[3][0]);
+           rv = 2*3;
+           matrix2[cv+3*2] /= matrix1[rv+2];
+
+           rv -= 3;
+           matrix2[cv+3*1] = (matrix2[cv+3*1] -
+                           matrix1[rv+2] * matrix2[cv+3*2]) / matrix1[rv+1];
+
+           rv -= 3;
+           matrix2[cv+4*0] = (matrix2[cv+3*0] -
+                           matrix1[rv+1] * matrix2[cv+3*1] -
+                           matrix1[rv+2] * matrix2[cv+3*2]) / matrix1[rv+0];
+
+       }
+    }
+   /**
+     * Computes the determinant of this matrix.
+     * @return the determinant of this matrix
+     */
+    public final float determinant()
+    {
+       float total;
+       total =  this.m00*(this.m11*this.m22 - this.m12*this.m21)
+              + this.m01*(this.m12*this.m20 - this.m10*this.m22)
+              + this.m02*(this.m10*this.m21 - this.m11*this.m20); 
+       return total;
+    }
+
+    /**
+     * Sets the value of this matrix to a scale matrix with
+     * the passed scale amount.
+     * @param scale the scale factor for the matrix
+     */
+    public final void set(float scale)
+    {
+       this.m00 = scale;
+       this.m01 = (float) 0.0;
+       this.m02 = (float) 0.0;
+
+       this.m10 = (float) 0.0;
+       this.m11 = scale;
+       this.m12 = (float) 0.0;
+
+       this.m20 = (float) 0.0;
+       this.m21 = (float) 0.0;
+       this.m22 = scale;
+    }
+
+    /**
+     * Sets the value of this matrix to a counter clockwise rotation 
+     * about the x axis.
+     * @param angle the angle to rotate about the X axis in radians
+     */
+    public final void rotX(float angle)
+    {
+       float   sinAngle, cosAngle;
+
+       sinAngle = (float) Math.sin((double) angle);
+       cosAngle = (float) Math.cos((double) angle);
+
+       this.m00 = (float) 1.0;
+       this.m01 = (float) 0.0;
+       this.m02 = (float) 0.0;
+
+       this.m10 = (float) 0.0;
+       this.m11 = cosAngle;
+       this.m12 = -sinAngle;
+
+       this.m20 = (float) 0.0;
+       this.m21 = sinAngle;
+       this.m22 = cosAngle;
+    }
+
+    /**
+     * Sets the value of this matrix to a counter clockwise rotation 
+     * about the y axis.
+     * @param angle the angle to rotate about the Y axis in radians
+     */
+    public final void rotY(float angle)
+    {
+       float   sinAngle, cosAngle;
+
+       sinAngle = (float) Math.sin((double) angle);
+       cosAngle = (float) Math.cos((double) angle);
+
+       this.m00 = cosAngle;
+       this.m01 = (float) 0.0;
+       this.m02 = sinAngle;
+
+       this.m10 = (float) 0.0;
+       this.m11 = (float) 1.0;
+       this.m12 = (float) 0.0;
+
+       this.m20 = -sinAngle;
+       this.m21 = (float) 0.0;
+       this.m22 = cosAngle;
+    }
+
+    /**
+     * Sets the value of this matrix to a counter clockwise rotation 
+     * about the z axis.
+     * @param angle the angle to rotate about the Z axis in radians
+     */
+    public final void rotZ(float angle)
+    {
+       float   sinAngle, cosAngle;
+
+       sinAngle = (float) Math.sin((double) angle);
+       cosAngle = (float) Math.cos((double) angle);
+
+       this.m00 = cosAngle;
+       this.m01 = -sinAngle;
+       this.m02 = (float) 0.0;
+
+       this.m10 = sinAngle;
+       this.m11 = cosAngle;
+       this.m12 = (float) 0.0;
+
+       this.m20 = (float) 0.0;
+       this.m21 = (float) 0.0;
+       this.m22 = (float) 1.0;
+    }
+
+   /**
+     * Multiplies each element of this matrix by a scalar.
+     * @param scalar  the scalar multiplier
+     */
+    public final void mul(float scalar)
+    {
+       m00 *= scalar;
+       m01 *= scalar;
+       m02 *= scalar;
+
+       m10 *= scalar;
+       m11 *= scalar;
+       m12 *= scalar;
+
+       m20 *= scalar;
+       m21 *= scalar;
+       m22 *= scalar;
+    }
+
+   /**   
+     * Multiplies each element of matrix m1 by a scalar and places
+     * the result into this.  Matrix m1 is not modified.
+     * @param scalar  the scalar multiplier
+     * @param m1  the original matrix
+     */   
+    public final void mul(float scalar, Matrix3f m1)
+    { 
+        this.m00 = scalar * m1.m00;
+        this.m01 = scalar * m1.m01;
+        this.m02 = scalar * m1.m02;
+        this.m10 = scalar * m1.m10;
+        this.m11 = scalar * m1.m11;
+        this.m12 = scalar * m1.m12;
+        this.m20 = scalar * m1.m20;
+        this.m21 = scalar * m1.m21;
+        this.m22 = scalar * m1.m22;
+
+    } 
+
+   /**
+     * Sets the value of this matrix to the result of multiplying itself
+     * with matrix m1.
+     * @param m1 the other matrix
+     */  
+    public final void mul(Matrix3f m1)
+    {
+          float       m00, m01, m02,
+                      m10, m11, m12,
+                      m20, m21, m22;
+
+            m00 = this.m00*m1.m00 + this.m01*m1.m10 + this.m02*m1.m20;
+            m01 = this.m00*m1.m01 + this.m01*m1.m11 + this.m02*m1.m21;
+            m02 = this.m00*m1.m02 + this.m01*m1.m12 + this.m02*m1.m22;
+            m10 = this.m10*m1.m00 + this.m11*m1.m10 + this.m12*m1.m20;
+            m11 = this.m10*m1.m01 + this.m11*m1.m11 + this.m12*m1.m21;
+            m12 = this.m10*m1.m02 + this.m11*m1.m12 + this.m12*m1.m22;
+            m20 = this.m20*m1.m00 + this.m21*m1.m10 + this.m22*m1.m20;
+            m21 = this.m20*m1.m01 + this.m21*m1.m11 + this.m22*m1.m21;
+            m22 = this.m20*m1.m02 + this.m21*m1.m12 + this.m22*m1.m22;
+            this.m00 = m00; this.m01 = m01; this.m02 = m02;
+            this.m10 = m10; this.m11 = m11; this.m12 = m12;
+            this.m20 = m20; this.m21 = m21; this.m22 = m22;
+    }
+
+    /**
+     * Sets the value of this matrix to the result of multiplying
+     * the two argument matrices together.
+     * @param m1 the first matrix
+     * @param m2 the second matrix
+     */
+    public final void mul(Matrix3f m1, Matrix3f m2)
+    {
+       if (this != m1 && this != m2) {
+            this.m00 = m1.m00*m2.m00 + m1.m01*m2.m10 + m1.m02*m2.m20;
+            this.m01 = m1.m00*m2.m01 + m1.m01*m2.m11 + m1.m02*m2.m21;
+            this.m02 = m1.m00*m2.m02 + m1.m01*m2.m12 + m1.m02*m2.m22;
+
+            this.m10 = m1.m10*m2.m00 + m1.m11*m2.m10 + m1.m12*m2.m20;
+            this.m11 = m1.m10*m2.m01 + m1.m11*m2.m11 + m1.m12*m2.m21;
+            this.m12 = m1.m10*m2.m02 + m1.m11*m2.m12 + m1.m12*m2.m22;
+
+            this.m20 = m1.m20*m2.m00 + m1.m21*m2.m10 + m1.m22*m2.m20;
+            this.m21 = m1.m20*m2.m01 + m1.m21*m2.m11 + m1.m22*m2.m21;
+            this.m22 = m1.m20*m2.m02 + m1.m21*m2.m12 + m1.m22*m2.m22;
+       } else {
+           float       m00, m01, m02,
+                       m10, m11, m12,
+                       m20, m21, m22;
+
+            m00 = m1.m00*m2.m00 + m1.m01*m2.m10 + m1.m02*m2.m20; 
+            m01 = m1.m00*m2.m01 + m1.m01*m2.m11 + m1.m02*m2.m21; 
+            m02 = m1.m00*m2.m02 + m1.m01*m2.m12 + m1.m02*m2.m22; 
+            m10 = m1.m10*m2.m00 + m1.m11*m2.m10 + m1.m12*m2.m20; 
+            m11 = m1.m10*m2.m01 + m1.m11*m2.m11 + m1.m12*m2.m21; 
+            m12 = m1.m10*m2.m02 + m1.m11*m2.m12 + m1.m12*m2.m22; 
+            m20 = m1.m20*m2.m00 + m1.m21*m2.m10 + m1.m22*m2.m20; 
+            m21 = m1.m20*m2.m01 + m1.m21*m2.m11 + m1.m22*m2.m21; 
+            m22 = m1.m20*m2.m02 + m1.m21*m2.m12 + m1.m22*m2.m22; 
+
+            this.m00 = m00; this.m01 = m01; this.m02 = m02;
+            this.m10 = m10; this.m11 = m11; this.m12 = m12;
+            this.m20 = m20; this.m21 = m21; this.m22 = m22;
+       }
+    }
+
+   /**
+     *  Multiplies this matrix by matrix m1, does an SVD normalization 
+     *  of the result, and places the result back into this matrix.
+     *  this = SVDnorm(this*m1).
+     *  @param  m1 the matrix on the right hand side of the multiplication
+     */
+    public final void mulNormalize(Matrix3f m1){
+       
+       double[]    tmp = new double[9];  // scratch matrix
+       double[]    tmp_rot = new double[9];  // scratch matrix
+       double[]    tmp_scale = new double[3];  // scratch matrix
+
+       tmp[0] = this.m00*m1.m00 + this.m01*m1.m10 + this.m02*m1.m20;
+       tmp[1] = this.m00*m1.m01 + this.m01*m1.m11 + this.m02*m1.m21;
+       tmp[2] = this.m00*m1.m02 + this.m01*m1.m12 + this.m02*m1.m22;
+
+       tmp[3] = this.m10*m1.m00 + this.m11*m1.m10 + this.m12*m1.m20;
+       tmp[4] = this.m10*m1.m01 + this.m11*m1.m11 + this.m12*m1.m21;
+       tmp[5] = this.m10*m1.m02 + this.m11*m1.m12 + this.m12*m1.m22;
+
+       tmp[6] = this.m20*m1.m00 + this.m21*m1.m10 + this.m22*m1.m20;
+       tmp[7] = this.m20*m1.m01 + this.m21*m1.m11 + this.m22*m1.m21;
+       tmp[8] = this.m20*m1.m02 + this.m21*m1.m12 + this.m22*m1.m22;
+
+       Matrix3d.compute_svd( tmp, tmp_scale, tmp_rot);
+
+       this.m00 = (float)(tmp_rot[0]);
+       this.m01 = (float)(tmp_rot[1]);
+       this.m02 = (float)(tmp_rot[2]);
+
+       this.m10 = (float)(tmp_rot[3]);
+       this.m11 = (float)(tmp_rot[4]);
+       this.m12 = (float)(tmp_rot[5]);
+
+       this.m20 = (float)(tmp_rot[6]);
+       this.m21 = (float)(tmp_rot[7]);
+       this.m22 = (float)(tmp_rot[8]);
+
+    }
+
+   /**
+     *  Multiplies matrix m1 by matrix m2, does an SVD normalization 
+     *  of the result, and places the result into this matrix.
+     *  this = SVDnorm(m1*m2).
+     *  @param m1  the matrix on the left hand side of the multiplication
+     *  @param m2  the matrix on the right hand side of the multiplication
+     */  
+    public final void mulNormalize(Matrix3f m1, Matrix3f m2){
+       
+       double[]    tmp = new double[9];  // scratch matrix
+       double[]    tmp_rot = new double[9];  // scratch matrix
+       double[]    tmp_scale = new double[3];  // scratch matrix
+
+       
+       tmp[0] = m1.m00*m2.m00 + m1.m01*m2.m10 + m1.m02*m2.m20;
+       tmp[1] = m1.m00*m2.m01 + m1.m01*m2.m11 + m1.m02*m2.m21;
+       tmp[2] = m1.m00*m2.m02 + m1.m01*m2.m12 + m1.m02*m2.m22;
+       tmp[3] = m1.m10*m2.m00 + m1.m11*m2.m10 + m1.m12*m2.m20;
+       tmp[4] = m1.m10*m2.m01 + m1.m11*m2.m11 + m1.m12*m2.m21; 
+       tmp[5] = m1.m10*m2.m02 + m1.m11*m2.m12 + m1.m12*m2.m22; 
+       tmp[6] = m1.m20*m2.m00 + m1.m21*m2.m10 + m1.m22*m2.m20;
+       tmp[7] = m1.m20*m2.m01 + m1.m21*m2.m11 + m1.m22*m2.m21; 
+       tmp[8] = m1.m20*m2.m02 + m1.m21*m2.m12 + m1.m22*m2.m22; 
+       Matrix3d.compute_svd( tmp, tmp_scale, tmp_rot);
+       this.m00 = (float)(tmp_rot[0]);
+       this.m01 = (float)(tmp_rot[1]);
+       this.m02 = (float)(tmp_rot[2]);
+       this.m10 = (float)(tmp_rot[3]);
+       this.m11 = (float)(tmp_rot[4]);
+       this.m12 = (float)(tmp_rot[5]);
+       this.m20 = (float)(tmp_rot[6]);
+       this.m21 = (float)(tmp_rot[7]);
+       this.m22 = (float)(tmp_rot[8]);
+    }
+
+   /**
+     *  Multiplies the transpose of matrix m1 times the transpose of matrix
+     *  m2, and places the result into this.
+     *  @param m1  the matrix on the left hand side of the multiplication
+     *  @param m2  the matrix on the right hand side of the multiplication
+     */
+    public final void mulTransposeBoth(Matrix3f m1, Matrix3f m2)
+    {
+        if (this != m1 && this != m2) {
+            this.m00 = m1.m00*m2.m00 + m1.m10*m2.m01 + m1.m20*m2.m02;
+            this.m01 = m1.m00*m2.m10 + m1.m10*m2.m11 + m1.m20*m2.m12;
+            this.m02 = m1.m00*m2.m20 + m1.m10*m2.m21 + m1.m20*m2.m22;
+
+            this.m10 = m1.m01*m2.m00 + m1.m11*m2.m01 + m1.m21*m2.m02;
+            this.m11 = m1.m01*m2.m10 + m1.m11*m2.m11 + m1.m21*m2.m12;
+            this.m12 = m1.m01*m2.m20 + m1.m11*m2.m21 + m1.m21*m2.m22;
+
+            this.m20 = m1.m02*m2.m00 + m1.m12*m2.m01 + m1.m22*m2.m02;
+            this.m21 = m1.m02*m2.m10 + m1.m12*m2.m11 + m1.m22*m2.m12;
+            this.m22 = m1.m02*m2.m20 + m1.m12*m2.m21 + m1.m22*m2.m22;
+        } else {
+            float       m00, m01, m02,
+                        m10, m11, m12,
+               m20, m21, m22;  // vars for temp result matrix 
+
+            m00 = m1.m00*m2.m00 + m1.m10*m2.m01 + m1.m20*m2.m02;
+            m01 = m1.m00*m2.m10 + m1.m10*m2.m11 + m1.m20*m2.m12;
+            m02 = m1.m00*m2.m20 + m1.m10*m2.m21 + m1.m20*m2.m22;
+
+            m10 = m1.m01*m2.m00 + m1.m11*m2.m01 + m1.m21*m2.m02;
+            m11 = m1.m01*m2.m10 + m1.m11*m2.m11 + m1.m21*m2.m12;
+            m12 = m1.m01*m2.m20 + m1.m11*m2.m21 + m1.m21*m2.m22;
+
+            m20 = m1.m02*m2.m00 + m1.m12*m2.m01 + m1.m22*m2.m02;
+            m21 = m1.m02*m2.m10 + m1.m12*m2.m11 + m1.m22*m2.m12;
+            m22 = m1.m02*m2.m20 + m1.m12*m2.m21 + m1.m22*m2.m22;
+
+            this.m00 = m00; this.m01 = m01; this.m02 = m02;
+            this.m10 = m10; this.m11 = m11; this.m12 = m12;
+            this.m20 = m20; this.m21 = m21; this.m22 = m22;
+        }
+
+    }
+
+   /**   
+     *  Multiplies matrix m1 times the transpose of matrix m2, and
+     *  places the result into this.
+     *  @param m1  the matrix on the left hand side of the multiplication 
+     *  @param m2  the matrix on the right hand side of the multiplication
+     */  
+    public final void mulTransposeRight(Matrix3f m1, Matrix3f m2) 
+  { 
+    if (this != m1 && this != m2) {
+      this.m00 = m1.m00*m2.m00 + m1.m01*m2.m01 + m1.m02*m2.m02;
+      this.m01 = m1.m00*m2.m10 + m1.m01*m2.m11 + m1.m02*m2.m12;
+      this.m02 = m1.m00*m2.m20 + m1.m01*m2.m21 + m1.m02*m2.m22;
+       
+      this.m10 = m1.m10*m2.m00 + m1.m11*m2.m01 + m1.m12*m2.m02;
+      this.m11 = m1.m10*m2.m10 + m1.m11*m2.m11 + m1.m12*m2.m12;
+      this.m12 = m1.m10*m2.m20 + m1.m11*m2.m21 + m1.m12*m2.m22;
+       
+      this.m20 = m1.m20*m2.m00 + m1.m21*m2.m01 + m1.m22*m2.m02;
+      this.m21 = m1.m20*m2.m10 + m1.m21*m2.m11 + m1.m22*m2.m12;
+      this.m22 = m1.m20*m2.m20 + m1.m21*m2.m21 + m1.m22*m2.m22;
+    } else {
+      float    m00, m01, m02,
+       m10, m11, m12,
+         m20, m21, m22;  // vars for temp result matrix 
+
+      m00 = m1.m00*m2.m00 + m1.m01*m2.m01 + m1.m02*m2.m02;
+      m01 = m1.m00*m2.m10 + m1.m01*m2.m11 + m1.m02*m2.m12;
+      m02 = m1.m00*m2.m20 + m1.m01*m2.m21 + m1.m02*m2.m22;
+
+      m10 = m1.m10*m2.m00 + m1.m11*m2.m01 + m1.m12*m2.m02; 
+      m11 = m1.m10*m2.m10 + m1.m11*m2.m11 + m1.m12*m2.m12;
+      m12 = m1.m10*m2.m20 + m1.m11*m2.m21 + m1.m12*m2.m22;
+
+      m20 = m1.m20*m2.m00 + m1.m21*m2.m01 + m1.m22*m2.m02; 
+      m21 = m1.m20*m2.m10 + m1.m21*m2.m11 + m1.m22*m2.m12;
+      m22 = m1.m20*m2.m20 + m1.m21*m2.m21 + m1.m22*m2.m22;
+      this.m00 = m00; this.m01 = m01; this.m02 = m02;
+      this.m10 = m10; this.m11 = m11; this.m12 = m12;
+      this.m20 = m20; this.m21 = m21; this.m22 = m22;
+    }
+  } 
+
+   /**   
+     *  Multiplies the transpose of matrix m1 times matrix m2, and 
+     *  places the result into this.  
+     *  @param m1  the matrix on the left hand side of the multiplication  
+     *  @param m2  the matrix on the right hand side of the multiplication 
+     */   
+    public final void mulTransposeLeft(Matrix3f m1, Matrix3f m2)  
+    {    
+      if (this != m1 && this != m2) {
+       this.m00 = m1.m00*m2.m00 + m1.m10*m2.m10 + m1.m20*m2.m20;
+       this.m01 = m1.m00*m2.m01 + m1.m10*m2.m11 + m1.m20*m2.m21;
+       this.m02 = m1.m00*m2.m02 + m1.m10*m2.m12 + m1.m20*m2.m22;
+       this.m10 = m1.m01*m2.m00 + m1.m11*m2.m10 + m1.m21*m2.m20;
+       this.m11 = m1.m01*m2.m01 + m1.m11*m2.m11 + m1.m21*m2.m21;
+       this.m12 = m1.m01*m2.m02 + m1.m11*m2.m12 + m1.m21*m2.m22;
+       this.m20 = m1.m02*m2.m00 + m1.m12*m2.m10 + m1.m22*m2.m20;
+       this.m21 = m1.m02*m2.m01 + m1.m12*m2.m11 + m1.m22*m2.m21;
+       this.m22 = m1.m02*m2.m02 + m1.m12*m2.m12 + m1.m22*m2.m22;
+      } else {
+       float   m00, m01, m02,
+         m10, m11, m12,
+           m20, m21, m22;  // vars for temp result matrix 
+
+       m00 = m1.m00*m2.m00 + m1.m10*m2.m10 + m1.m20*m2.m20;
+       m01 = m1.m00*m2.m01 + m1.m10*m2.m11 + m1.m20*m2.m21;
+       m02 = m1.m00*m2.m02 + m1.m10*m2.m12 + m1.m20*m2.m22;
+
+       m10 = m1.m01*m2.m00 + m1.m11*m2.m10 + m1.m21*m2.m20; 
+       m11 = m1.m01*m2.m01 + m1.m11*m2.m11 + m1.m21*m2.m21;
+       m12 = m1.m01*m2.m02 + m1.m11*m2.m12 + m1.m21*m2.m22;
+
+       m20 = m1.m02*m2.m00 + m1.m12*m2.m10 + m1.m22*m2.m20; 
+       m21 = m1.m02*m2.m01 + m1.m12*m2.m11 + m1.m22*m2.m21;
+       m22 = m1.m02*m2.m02 + m1.m12*m2.m12 + m1.m22*m2.m22;
+       this.m00 = m00; this.m01 = m01; this.m02 = m02;
+       this.m10 = m10; this.m11 = m11; this.m12 = m12;
+       this.m20 = m20; this.m21 = m21; this.m22 = m22;
+      }  
+    }
+
+   /**
+     * Performs singular value decomposition normalization of this matrix.   
+     */
+    public final void normalize(){
+       
+       double[]    tmp_rot = new double[9];  // scratch matrix
+       double[]    tmp_scale = new double[3];  // scratch matrix
+       getScaleRotate( tmp_scale, tmp_rot );
+
+       this.m00 = (float)tmp_rot[0];
+       this.m01 = (float)tmp_rot[1];
+       this.m02 = (float)tmp_rot[2];
+
+       this.m10 = (float)tmp_rot[3];
+       this.m11 = (float)tmp_rot[4];
+       this.m12 = (float)tmp_rot[5];
+
+       this.m20 = (float)tmp_rot[6];
+       this.m21 = (float)tmp_rot[7];
+       this.m22 = (float)tmp_rot[8];
+
+    }
+
+   /**   
+     * Perform singular value decomposition normalization of matrix m1 
+     * and place the normalized values into this.   
+     * @param m1  the matrix values to be normalized
+     */ 
+    public final void normalize(Matrix3f m1){
+       double[]    tmp = new double[9];  // scratch matrix
+       double[]    tmp_rot = new double[9];  // scratch matrix
+       double[]    tmp_scale = new double[3];  // scratch matrix
+
+       tmp[0] = m1.m00;
+       tmp[1] = m1.m01;
+       tmp[2] = m1.m02;
+       tmp[3] = m1.m10;
+       tmp[4] = m1.m11;
+       tmp[5] = m1.m12;
+       tmp[6] = m1.m20;
+       tmp[7] = m1.m21;
+       tmp[8] = m1.m22;
+       Matrix3d.compute_svd( tmp, tmp_scale, tmp_rot );
+       this.m00 = (float)(tmp_rot[0]);
+       this.m01 = (float)(tmp_rot[1]);
+       this.m02 = (float)(tmp_rot[2]);
+       this.m10 = (float)(tmp_rot[3]);
+       this.m11 = (float)(tmp_rot[4]);
+       this.m12 = (float)(tmp_rot[5]);
+       this.m20 = (float)(tmp_rot[6]);
+       this.m21 = (float)(tmp_rot[7]);
+       this.m22 = (float)(tmp_rot[8]);
+
+    }
+
+   /**
+     * Perform cross product normalization of this matrix.   
+     */
+    public final void normalizeCP()
+    {
+       float mag = 1.0f/(float)Math.sqrt(m00*m00 + m10*m10 + m20*m20);
+       m00 = m00*mag;
+       m10 = m10*mag;
+       m20 = m20*mag;
+
+       mag = 1.0f/(float)Math.sqrt(m01*m01 + m11*m11 + m21*m21);
+       m01 = m01*mag;
+       m11 = m11*mag;
+       m21 = m21*mag;
+
+       m02 = m10*m21 - m11*m20;
+       m12 = m01*m20 - m00*m21;
+       m22 = m00*m11 - m01*m10;
+
+    }
+
+   /**
+     * Perform cross product normalization of matrix m1 and place the 
+     * normalized values into this.   
+     * @param m1  Provides the matrix values to be normalized
+     */
+    public final void normalizeCP(Matrix3f m1)
+    {
+       float mag = 1.0f/(float)Math.sqrt(m1.m00*m1.m00 + m1.m10*m1.m10 + m1.m20*m1.m20);
+       m00 = m1.m00*mag;
+       m10 = m1.m10*mag;
+       m20 = m1.m20*mag;
+
+       mag = 1.0f/(float)Math.sqrt(m1.m01*m1.m01 + m1.m11*m1.m11 + m1.m21*m1.m21);
+       m01 = m1.m01*mag;
+       m11 = m1.m11*mag;
+       m21 = m1.m21*mag;
+
+       m02 = m10*m21 - m11*m20;
+       m12 = m01*m20 - m00*m21;
+       m22 = m00*m11 - m01*m10;
+
+    }
+
+   /**
+     * Returns true if all of the data members of Matrix3f m1 are
+     * equal to the corresponding data members in this Matrix3f.
+     * @param m1  the matrix with which the comparison is made
+     * @return  true or false
+     */  
+    public boolean equals(Matrix3f m1)
+    {
+      try {
+
+        return(this.m00 == m1.m00 && this.m01 == m1.m01 && this.m02 == m1.m02
+            && this.m10 == m1.m10 && this.m11 == m1.m11 && this.m12 == m1.m12
+            && this.m20 == m1.m20 && this.m21 == m1.m21 && this.m22 == m1.m22);
+      }  
+      catch (NullPointerException e2) { return false; }
+
+    }
+
+   /**
+     * Returns true if the Object o1 is of type Matrix3f and all of the
+     * data members of o1 are equal to the corresponding data members in
+     * this Matrix3f.
+     * @param o1  the object with which the comparison is made
+     * @return  true or false
+     */  
+    public boolean equals(Object o1)
+    {
+      try { 
+
+           Matrix3f m2 = (Matrix3f) o1;
+           return(this.m00 == m2.m00 && this.m01 == m2.m01 && this.m02 == m2.m02
+             && this.m10 == m2.m10 && this.m11 == m2.m11 && this.m12 == m2.m12
+             && this.m20 == m2.m20 && this.m21 == m2.m21 && this.m22 == m2.m22);
+        }
+        catch (ClassCastException   e1) { return false; } 
+        catch (NullPointerException e2) { return false; }
+    }
+
+   /**
+     * Returns true if the L-infinite distance between this matrix 
+     * and matrix m1 is less than or equal to the epsilon parameter, 
+     * otherwise returns false.  The L-infinite
+     * distance is equal to 
+     * MAX[i=0,1,2 ; j=0,1,2 ; abs(this.m(i,j) - m1.m(i,j)]
+     * @param m1  the matrix to be compared to this matrix
+     * @param epsilon  the threshold value  
+     */
+    public boolean epsilonEquals(Matrix3f m1, float epsilon)
+    {
+        boolean status = true;
+
+        if( Math.abs( this.m00 - m1.m00) > epsilon) status = false;
+        if( Math.abs( this.m01 - m1.m01) > epsilon) status = false;
+        if( Math.abs( this.m02 - m1.m02) > epsilon) status = false;
+
+        if( Math.abs( this.m10 - m1.m10) > epsilon) status = false;
+        if( Math.abs( this.m11 - m1.m11) > epsilon) status = false;
+        if( Math.abs( this.m12 - m1.m12) > epsilon) status = false;
+
+        if( Math.abs( this.m20 - m1.m20) > epsilon) status = false;
+        if( Math.abs( this.m21 - m1.m21) > epsilon) status = false;
+        if( Math.abs( this.m22 - m1.m22) > epsilon) status = false;
+
+        return( status );
+
+    }
+
+
+    /**
+     * Returns a hash code value based on the data values in this
+     * object.  Two different Matrix3f objects with identical data values
+     * (i.e., Matrix3f.equals returns true) will return the same hash
+     * code value.  Two objects with different data members may return the
+     * same hash value, although this is not likely.
+     * @return the integer hash code value
+     */  
+    public int hashCode() {
+       long bits = 1L;
+       bits = 31L * bits + (long)VecMathUtil.floatToIntBits(m00);
+       bits = 31L * bits + (long)VecMathUtil.floatToIntBits(m01);
+       bits = 31L * bits + (long)VecMathUtil.floatToIntBits(m02);
+       bits = 31L * bits + (long)VecMathUtil.floatToIntBits(m10);
+       bits = 31L * bits + (long)VecMathUtil.floatToIntBits(m11);
+       bits = 31L * bits + (long)VecMathUtil.floatToIntBits(m12);
+       bits = 31L * bits + (long)VecMathUtil.floatToIntBits(m20);
+       bits = 31L * bits + (long)VecMathUtil.floatToIntBits(m21);
+       bits = 31L * bits + (long)VecMathUtil.floatToIntBits(m22);
+       return (int) (bits ^ (bits >> 32));
+    }
+
+
+  /**
+    *  Sets this matrix to all zeros.
+    */
+   public final void setZero()
+   {
+        m00 = 0.0f;
+        m01 = 0.0f;
+        m02 = 0.0f;
+        m10 = 0.0f;
+        m11 = 0.0f;
+        m12 = 0.0f;
+        m20 = 0.0f;
+        m21 = 0.0f;
+        m22 = 0.0f;
+
+   }
+
+   /**
+     * Negates the value of this matrix: this = -this.
+     */  
+    public final void negate()
+    {
+        this.m00 = -this.m00;
+        this.m01 = -this.m01;
+        this.m02 = -this.m02;
+        this.m10 = -this.m10;
+        this.m11 = -this.m11;
+        this.m12 = -this.m12;
+        this.m20 = -this.m20;
+        this.m21 = -this.m21;
+        this.m22 = -this.m22;
+
+    }
+
+   /**
+     *  Sets the value of this matrix equal to the negation of
+     *  of the Matrix3f parameter.
+     *  @param m1  the source matrix
+     */  
+    public final void negate(Matrix3f m1)
+    {
+        this.m00 = -m1.m00;
+        this.m01 = -m1.m01;
+        this.m02 = -m1.m02;
+        this.m10 = -m1.m10;
+        this.m11 = -m1.m11;
+        this.m12 = -m1.m12;
+        this.m20 = -m1.m20;
+        this.m21 = -m1.m21;
+        this.m22 = -m1.m22;
+
+    }
+
+   /**
+    * Multiply this matrix by the tuple t and place the result
+    * back into the tuple (t = this*t).
+    * @param t  the tuple to be multiplied by this matrix and then replaced
+    */
+    public final void transform(Tuple3f t) {
+     float x,y,z;
+     x = m00* t.x + m01*t.y + m02*t.z; 
+     y = m10* t.x + m11*t.y + m12*t.z; 
+     z = m20* t.x + m21*t.y + m22*t.z; 
+     t.set(x,y,z);
+    }
+
+   /**
+    * Multiply this matrix by the tuple t and and place the result 
+    * into the tuple "result" (result = this*t).
+    * @param t  the tuple to be multiplied by this matrix
+    * @param result  the tuple into which the product is placed
+    */
+    public final void transform(Tuple3f t, Tuple3f result) { 
+     float x,y,z;
+     x = m00* t.x + m01*t.y + m02*t.z; 
+     y = m10* t.x + m11*t.y + m12*t.z;
+     result.z = m20* t.x + m21*t.y + m22*t.z; 
+     result.x = x;
+     result.y = y;
+    }   
+
+    /**
+     * perform SVD (if necessary to get rotational component 
+     */
+    void  getScaleRotate( double[] scales, double[] rot ) {
+       
+       double[]    tmp = new double[9];  // scratch matrix
+        tmp[0] = m00;
+        tmp[1] = m01;
+        tmp[2] = m02;
+        tmp[3] = m10;
+        tmp[4] = m11;
+        tmp[5] = m12;
+        tmp[6] = m20;
+        tmp[7] = m21;
+        tmp[8] = m22;
+        Matrix3d.compute_svd(tmp, scales, rot);
+
+        return;
+       
+    }
+
+    /**
+     * Creates a new object of the same class as this object.
+     *
+     * @return a clone of this instance.
+     * @exception OutOfMemoryError if there is not enough memory.
+     * @see java.lang.Cloneable
+     * @since vecmath 1.3
+     */
+    public Object clone() {
+       Matrix3f m1 = null;
+       try {
+           m1 = (Matrix3f)super.clone();
+       } catch (CloneNotSupportedException e) {
+           // this shouldn't happen, since we are Cloneable
+           throw new InternalError();
+       }
+       return m1;
+    }
+
+    
+    /**
+        * Get the first matrix element in the first row.
+        * 
+        * @return Returns the m00.
+        * 
+        * @since vecmath 1.5
+        */
+       public final  float getM00() {
+               return m00;
+       }
+
+       /**
+        * Set the first matrix element in the first row.
+        * 
+        * @param m00 The m00 to set.
+        * 
+        * @since vecmath 1.5
+        */
+       public final  void setM00(float m00) {
+               this.m00 = m00;
+       }
+
+       /**
+        * Get the second matrix element in the first row.
+        * 
+        * @return Returns the m01.
+        * 
+        * 
+        * @since vecmath 1.5
+        */
+       public final  float getM01() {
+               return m01;
+       }
+
+       /**
+        * Set the second matrix element in the first row.
+        * 
+        * @param m01 The m01 to set.
+        * 
+        * @since vecmath 1.5
+        */
+       public  final void setM01(float m01) {
+               this.m01 = m01;
+       }
+
+       /**
+        * Get the third matrix element in the first row.
+        * 
+        * @return Returns the m02.
+        * 
+        * @since vecmath 1.5
+        */
+       public final float getM02() {
+               return m02;
+       }
+
+       /**
+        * Set the third matrix element in the first row.
+        * 
+        * @param m02 The m02 to set.
+        * 
+        * @since vecmath 1.5
+        */
+       public final  void setM02(float m02) {
+               this.m02 = m02;
+       }
+
+       /**
+        * Get first matrix element in the second row.
+        * 
+        * @return Returns the m10.
+        * 
+        * @since vecmath 1.5
+        */
+       public final  float getM10() {
+               return m10;
+       }
+
+       /**
+        * Set first matrix element in the second row.
+        * 
+        * @param m10 The m10 to set.
+        * 
+        * @since vecmath 1.5
+        */
+       public final  void setM10(float m10) {
+               this.m10 = m10;
+       }
+
+       /**
+        * Get second matrix element in the second row.
+        * 
+        * @return Returns the m11.
+        * 
+        * @since vecmath 1.5
+        */
+       public final  float getM11() {
+               return m11;
+       }
+
+       /**
+        * Set the second matrix element in the second row.
+        * 
+        * @param m11 The m11 to set.
+        * 
+        * @since vecmath 1.5
+        */
+       public final  void setM11(float m11) {
+               this.m11 = m11;
+       }
+
+       /**
+        * Get the third matrix element in the second row.
+        * 
+        * @return Returns the m12.
+        * 
+        * @since vecmath 1.5
+        */
+       public final  float getM12() {
+               return m12;
+       }
+
+       /**
+        * Set the third matrix element in the second row.
+        * @param m12 The m12 to set.
+        * @since vecmath 1.5
+        */
+       public final  void setM12(float m12) {
+               this.m12 = m12;
+       }
+
+       /**
+        * Get the first matrix element in the third row.
+        * 
+        * @return Returns the m20.
+        * 
+        * @since vecmath 1.5
+        */
+       public final  float getM20() {
+               return m20;
+       }
+
+       /**
+        * Set the first matrix element in the third row.
+        * 
+        * @param m20 The m20 to set.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setM20(float m20) {
+               this.m20 = m20;
+       }
+
+       /**
+        * Get the second matrix element in the third row.
+        * 
+        * @return Returns the m21.
+        * 
+        * @since vecmath 1.5
+        */
+       public final float getM21() {
+               return m21;
+       }
+
+       /**
+        * Set the second matrix element in the third row.
+        * 
+        * @param m21 The m21 to set.
+        * 
+        * @since vecmath 1.5 
+        */
+       public final void setM21(float m21) {
+               this.m21 = m21;
+       }
+
+       /**
+        * Get the third matrix element in the third row .
+        * 
+        * @return Returns the m22.
+        * 
+        * @since vecmath 1.5
+        */
+       public final float getM22() {
+               return m22;
+       }
+
+       /**
+        * Set the third matrix element in the third row.
+        * 
+        * @param m22 The m22 to set.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setM22(float m22) {
+               this.m22 = m22;
+       }
+
+}
diff --git a/javax.vecmath/src/javax/vecmath/Matrix4d.java b/javax.vecmath/src/javax/vecmath/Matrix4d.java
new file mode 100644 (file)
index 0000000..12d3ac0
--- /dev/null
@@ -0,0 +1,3958 @@
+/*
+ * $RCSfile: Matrix4d.java,v $
+ *
+ * Copyright 1996-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ * $Revision: 1.8 $
+ * $Date: 2008/02/28 20:18:50 $
+ * $State: Exp $
+ */
+
+package javax.vecmath;
+
+import java.lang.Math;
+
+/**
+ * A double precision floating point 4 by 4 matrix.
+ * Primarily to support 3D rotations.
+ *
+ */
+public class Matrix4d implements java.io.Serializable, Cloneable {
+
+    // Compatible with 1.1
+    static final long serialVersionUID = 8223903484171633710L;
+
+    /**
+     *  The first element of the first row.
+     */
+    public     double  m00;
+
+    /**
+     *  The second element of the first row.
+     */
+    public     double  m01;
+
+    /**
+     *  The third element of the first row.
+     */
+    public     double  m02;
+
+    /**
+     *  The fourth element of the first row.
+     */
+    public     double  m03;
+
+    /**
+     *  The first element of the second row.
+     */
+    public     double  m10;
+
+    /**
+     *  The second element of the second row.
+     */
+    public     double  m11;
+
+    /**
+     *  The third element of the second row.
+     */
+    public     double  m12;
+
+    /**
+     *  The fourth element of the second row.
+     */
+    public     double  m13;
+
+    /**
+     *  The first element of the third row.
+     */
+    public     double  m20;
+
+    /**
+     *  The second element of the third row.
+     */
+    public     double  m21;
+
+    /**
+     *  The third element of the third row.
+     */
+    public     double  m22;
+
+    /**
+     *  The fourth element of the third row.
+     */
+    public     double  m23;
+
+    /**
+     *  The first element of the fourth row.
+     */
+    public     double  m30;
+
+    /**
+     *  The second element of the fourth row.
+     */
+    public     double  m31;
+
+    /**
+     *  The third element of the fourth row.
+     */
+    public     double  m32;
+
+    /**
+     *  The fourth element of the fourth row.
+     */
+    public     double  m33;
+    /*
+    double[] tmp = new double[16];
+    double[] tmp_rot = new double[9];  // scratch matrix
+    double[] tmp_scale = new double[3];  // scratch matrix
+    */
+    private static final double EPS = 1.0E-10;
+
+    /**
+     * Constructs and initializes a Matrix4d from the specified 16 values.
+     * @param m00 the [0][0] element
+     * @param m01 the [0][1] element
+     * @param m02 the [0][2] element
+     * @param m03 the [0][3] element
+     * @param m10 the [1][0] element
+     * @param m11 the [1][1] element
+     * @param m12 the [1][2] element
+     * @param m13 the [1][3] element
+     * @param m20 the [2][0] element
+     * @param m21 the [2][1] element
+     * @param m22 the [2][2] element
+     * @param m23 the [2][3] element
+     * @param m30 the [3][0] element
+     * @param m31 the [3][1] element
+     * @param m32 the [3][2] element
+     * @param m33 the [3][3] element
+     */
+    public Matrix4d(double m00, double m01, double m02, double m03,
+                   double m10, double m11, double m12, double m13,
+                   double m20, double m21, double m22, double m23,
+                   double m30, double m31, double m32, double m33)
+    {
+       this.m00 = m00;
+       this.m01 = m01;
+       this.m02 = m02;
+       this.m03 = m03;
+
+       this.m10 = m10;
+       this.m11 = m11;
+       this.m12 = m12;
+       this.m13 = m13;
+
+       this.m20 = m20;
+       this.m21 = m21;
+       this.m22 = m22;
+       this.m23 = m23;
+
+       this.m30 = m30;
+       this.m31 = m31;
+       this.m32 = m32;
+       this.m33 = m33;
+
+    }
+
+    /**
+     * Constructs and initializes a Matrix4d from the specified 16
+     * element array.  this.m00 =v[0], this.m01=v[1], etc.
+     * @param v the array of length 16 containing in order
+     */
+    public Matrix4d(double[] v)
+    {
+       this.m00 = v[ 0];
+       this.m01 = v[ 1];
+       this.m02 = v[ 2];
+       this.m03 = v[ 3];
+
+       this.m10 = v[ 4];
+       this.m11 = v[ 5];
+       this.m12 = v[ 6];
+       this.m13 = v[ 7];
+
+       this.m20 = v[ 8];
+       this.m21 = v[ 9];
+       this.m22 = v[10];
+       this.m23 = v[11];
+
+       this.m30 = v[12];
+       this.m31 = v[13];
+       this.m32 = v[14];
+       this.m33 = v[15];
+
+    }
+
+   /**
+     * Constructs and initializes a Matrix4d from the quaternion,
+     * translation, and scale values; the scale is applied only to the
+     * rotational components of the matrix (upper 3x3) and not to the
+     * translational components.
+     * @param q1  the quaternion value representing the rotational component
+     * @param t1  the translational component of the matrix
+     * @param s   the scale value applied to the rotational components
+     */
+    public Matrix4d(Quat4d q1, Vector3d t1, double s)
+    {  
+        m00 = s*(1.0 - 2.0*q1.y*q1.y - 2.0*q1.z*q1.z);
+        m10 = s*(2.0*(q1.x*q1.y + q1.w*q1.z));
+        m20 = s*(2.0*(q1.x*q1.z - q1.w*q1.y));
+
+        m01 = s*(2.0*(q1.x*q1.y - q1.w*q1.z));
+        m11 = s*(1.0 - 2.0*q1.x*q1.x - 2.0*q1.z*q1.z);
+        m21 = s*(2.0*(q1.y*q1.z + q1.w*q1.x));
+
+        m02 = s*(2.0*(q1.x*q1.z + q1.w*q1.y));
+        m12 = s*(2.0*(q1.y*q1.z - q1.w*q1.x));
+        m22 = s*(1.0 - 2.0*q1.x*q1.x - 2.0*q1.y*q1.y);
+
+        m03 = t1.x;
+        m13 = t1.y;
+        m23 = t1.z;
+
+        m30 = 0.0;
+        m31 = 0.0;
+        m32 = 0.0;
+        m33 = 1.0;
+
+    }
+
+   /** 
+     * Constructs and initializes a Matrix4d from the quaternion,
+     * translation, and scale values; the scale is applied only to the 
+     * rotational components of the matrix (upper 3x3) and not to the 
+     * translational components. 
+     * @param q1  the quaternion value representing the rotational component 
+     * @param t1  the translational component of the matrix 
+     * @param s   the scale value applied to the rotational components 
+     */  
+    public Matrix4d(Quat4f q1, Vector3d t1, double s)
+    {
+        m00 = s*(1.0 - 2.0*q1.y*q1.y - 2.0*q1.z*q1.z);
+        m10 = s*(2.0*(q1.x*q1.y + q1.w*q1.z));
+        m20 = s*(2.0*(q1.x*q1.z - q1.w*q1.y));
+
+        m01 = s*(2.0*(q1.x*q1.y - q1.w*q1.z));
+        m11 = s*(1.0 - 2.0*q1.x*q1.x - 2.0*q1.z*q1.z);
+        m21 = s*(2.0*(q1.y*q1.z + q1.w*q1.x));
+
+        m02 = s*(2.0*(q1.x*q1.z + q1.w*q1.y));
+        m12 = s*(2.0*(q1.y*q1.z - q1.w*q1.x));
+        m22 = s*(1.0 - 2.0*q1.x*q1.x - 2.0*q1.y*q1.y);
+
+        m03 = t1.x;
+        m13 = t1.y;
+        m23 = t1.z;
+
+        m30 = 0.0;
+        m31 = 0.0;
+        m32 = 0.0;
+        m33 = 1.0;
+
+    }
+
+   /**
+     *  Constructs a new matrix with the same values as the 
+     *  Matrix4d parameter.
+     *  @param m1  the source matrix
+     */
+   public Matrix4d(Matrix4d m1)
+   {
+        this.m00 = m1.m00;
+        this.m01 = m1.m01;
+        this.m02 = m1.m02;
+        this.m03 = m1.m03;
+
+        this.m10 = m1.m10;
+        this.m11 = m1.m11;
+        this.m12 = m1.m12;
+        this.m13 = m1.m13;
+
+        this.m20 = m1.m20;
+        this.m21 = m1.m21;
+        this.m22 = m1.m22;
+        this.m23 = m1.m23;
+
+        this.m30 = m1.m30;
+        this.m31 = m1.m31;
+        this.m32 = m1.m32;
+        this.m33 = m1.m33;
+
+   }
+
+   /**
+     *  Constructs a new matrix with the same values as the 
+     *  Matrix4f parameter.
+     *  @param m1  the source matrix
+     */
+   public Matrix4d(Matrix4f m1)
+   {
+        this.m00 = m1.m00; 
+        this.m01 = m1.m01; 
+        this.m02 = m1.m02; 
+        this.m03 = m1.m03; 
+        this.m10 = m1.m10;
+        this.m11 = m1.m11; 
+        this.m12 = m1.m12; 
+        this.m13 = m1.m13; 
+        this.m20 = m1.m20; 
+        this.m21 = m1.m21; 
+        this.m22 = m1.m22; 
+        this.m23 = m1.m23; 
+        this.m30 = m1.m30; 
+        this.m31 = m1.m31; 
+        this.m32 = m1.m32; 
+        this.m33 = m1.m33; 
+
+   }
+
+   /**
+     * Constructs and initializes a Matrix4d from the rotation matrix,
+     * translation, and scale values; the scale is applied only to the
+     * rotational components of the matrix (upper 3x3) and not to the
+     * translational components of the matrix.
+     * @param m1  the rotation matrix representing the rotational components
+     * @param t1  the translational components of the matrix
+     * @param s   the scale value applied to the rotational components
+     */
+    public Matrix4d(Matrix3f m1, Vector3d t1, double s)
+    {
+        this.m00 = m1.m00*s; 
+        this.m01 = m1.m01*s; 
+        this.m02 = m1.m02*s; 
+        this.m03 = t1.x; 
+  
+        this.m10 = m1.m10*s; 
+        this.m11 = m1.m11*s;  
+        this.m12 = m1.m12*s;  
+        this.m13 = t1.y;  
+  
+        this.m20 = m1.m20*s;  
+        this.m21 = m1.m21*s;  
+        this.m22 = m1.m22*s;  
+        this.m23 = t1.z;  
+  
+        this.m30 = 0.0;  
+        this.m31 = 0.0;  
+        this.m32 = 0.0;  
+        this.m33 = 1.0;  
+
+    }
+
+   /**   
+     * Constructs and initializes a Matrix4f from the rotation matrix,
+     * translation, and scale values; the scale is applied only to the
+     * rotational components of the matrix (upper 3x3) and not to the
+     * translational components of the matrix.
+     * @param m1  the rotation matrix representing the rotational components
+     * @param t1  the translational components of the matrix
+     * @param s   the scale value applied to the rotational components
+     */  
+    public Matrix4d(Matrix3d m1, Vector3d t1, double s)
+    {
+        this.m00 = m1.m00*s;  
+        this.m01 = m1.m01*s;  
+        this.m02 = m1.m02*s;  
+        this.m03 = t1.x; 
+  
+        this.m10 = m1.m10*s;  
+        this.m11 = m1.m11*s;   
+        this.m12 = m1.m12*s;   
+        this.m13 = t1.y;   
+   
+        this.m20 = m1.m20*s;   
+        this.m21 = m1.m21*s;   
+        this.m22 = m1.m22*s;   
+        this.m23 = t1.z;   
+   
+        this.m30 = 0.0;   
+        this.m31 = 0.0;   
+        this.m32 = 0.0;   
+        this.m33 = 1.0;  
+
+    }
+
+    /**
+     * Constructs and initializes a Matrix4d to all zeros.
+     */
+    public Matrix4d()
+    {
+       this.m00 = 0.0;
+       this.m01 = 0.0;
+       this.m02 = 0.0;
+       this.m03 = 0.0;
+
+       this.m10 = 0.0;
+       this.m11 = 0.0;
+       this.m12 = 0.0;
+       this.m13 = 0.0;
+
+       this.m20 = 0.0;
+       this.m21 = 0.0;
+       this.m22 = 0.0;
+       this.m23 = 0.0;
+
+       this.m30 = 0.0;
+       this.m31 = 0.0;
+       this.m32 = 0.0;
+       this.m33 = 0.0;
+
+    }
+
+   /**
+     * Returns a string that contains the values of this Matrix4d.
+     * @return the String representation
+     */ 
+    public String toString() {
+      return
+       this.m00 + ", " + this.m01 + ", " + this.m02 + ", " + this.m03 + "\n" +
+       this.m10 + ", " + this.m11 + ", " + this.m12 + ", " + this.m13 + "\n" +
+       this.m20 + ", " + this.m21 + ", " + this.m22 + ", " + this.m23 + "\n" +
+       this.m30 + ", " + this.m31 + ", " + this.m32 + ", " + this.m33 + "\n";
+    }
+
+    /**
+     * Sets this Matrix4d to identity.
+     */
+    public final void setIdentity()
+    {
+       this.m00 = 1.0;
+       this.m01 = 0.0;
+       this.m02 = 0.0;
+       this.m03 = 0.0;
+
+       this.m10 = 0.0;
+       this.m11 = 1.0;
+       this.m12 = 0.0;
+       this.m13 = 0.0;
+
+       this.m20 = 0.0;
+       this.m21 = 0.0;
+       this.m22 = 1.0;
+       this.m23 = 0.0;
+
+       this.m30 = 0.0;
+       this.m31 = 0.0;
+       this.m32 = 0.0;
+       this.m33 = 1.0;
+    }
+
+    /**
+     * Sets the specified element of this matrix4f to the value provided.
+     * @param row the row number to be modified (zero indexed)
+     * @param column the column number to be modified (zero indexed)
+     * @param value the new value
+     */
+    public final void setElement(int row, int column, double value)
+    {
+       switch (row) 
+         {
+         case 0:
+           switch(column)
+             {
+             case 0:
+               this.m00 = value;
+               break;
+             case 1:
+               this.m01 = value;
+               break;
+             case 2:
+               this.m02 = value;
+               break;
+             case 3:
+               this.m03 = value;
+               break;
+             default:
+               throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4d0"));
+             }
+           break;
+
+         case 1:
+           switch(column) 
+             {
+             case 0:
+               this.m10 = value;
+               break;
+             case 1:
+               this.m11 = value;
+               break;
+             case 2:
+               this.m12 = value;
+               break;
+             case 3:
+               this.m13 = value;
+               break;
+             default:
+               throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4d0"));
+             }
+           break;
+
+         case 2:
+           switch(column) 
+             {
+             case 0:
+               this.m20 = value;
+               break;
+             case 1:
+               this.m21 = value;
+               break;
+             case 2:
+               this.m22 = value;
+               break;
+             case 3:
+               this.m23 = value;
+               break;
+             default:
+               throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4d0"));
+             }
+           break;
+
+         case 3:
+           switch(column) 
+             {
+             case 0:
+               this.m30 = value;
+               break;
+             case 1:
+               this.m31 = value;
+               break;
+             case 2:
+               this.m32 = value;
+               break;
+             case 3:
+               this.m33 = value;
+               break;
+             default:
+               throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4d0"));
+             }
+           break;
+
+         default:
+               throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4d0"));
+         }
+    }
+
+    /**
+     * Retrieves the value at the specified row and column of this matrix.
+     * @param row the row number to be retrieved (zero indexed)
+     * @param column the column number to be retrieved (zero indexed)
+     * @return the value at the indexed element
+     */
+    public final double getElement(int row, int column)
+    {
+       switch (row) 
+         {
+         case 0:
+           switch(column)
+             {
+             case 0:
+               return(this.m00);
+             case 1:
+               return(this.m01);
+             case 2:
+               return(this.m02);
+             case 3:
+               return(this.m03);
+             default:
+               break;
+             }
+           break;
+         case 1:
+           switch(column) 
+             {
+             case 0:
+               return(this.m10);
+             case 1:
+               return(this.m11);
+             case 2:
+               return(this.m12);
+             case 3:
+               return(this.m13);
+             default:
+               break;
+             }
+           break;
+         
+         case 2:
+           switch(column) 
+             {
+             case 0:
+               return(this.m20);
+             case 1:
+               return(this.m21);
+             case 2:
+               return(this.m22);
+             case 3:
+               return(this.m23);
+             default:
+               break;
+             }
+           break;
+           
+         case 3:
+           switch(column) 
+             {
+             case 0:
+               return(this.m30);
+             case 1:
+               return(this.m31);
+             case 2:
+               return(this.m32);
+             case 3:
+               return(this.m33);
+             default:
+               break;
+             }
+           break;
+           
+         default:
+           break;
+         }
+       throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4d1"));
+    }
+
+    /** 
+     * Copies the matrix values in the specified row into the vector parameter. 
+     * @param row  the matrix row 
+     * @param v    the vector into which the matrix row values will be copied 
+     */   
+    public final void getRow(int row, Vector4d v) {
+        if( row == 0 ) {
+           v.x = m00;  
+           v.y = m01;
+           v.z = m02;
+           v.w = m03;
+        } else if(row == 1) {
+           v.x = m10;
+           v.y = m11;
+           v.z = m12;
+           v.w = m13;
+        } else if(row == 2) {
+           v.x = m20;
+           v.y = m21;
+           v.z = m22;
+           v.w = m23;
+        } else if(row == 3) {
+           v.x = m30;
+           v.y = m31;
+           v.z = m32;
+           v.w = m33;
+        } else {
+          throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4d2"));
+        }
+    } 
+    /**   
+     * Copies the matrix values in the specified row into the array parameter.
+     * @param row  the matrix row 
+     * @param v    the array into which the matrix row values will be copied 
+     */   
+    public final void getRow(int row, double v[]) { 
+        if( row == 0 ) {
+               v[0] = m00;
+               v[1] = m01;
+               v[2] = m02;
+               v[3] = m03;
+        } else if(row == 1) {
+               v[0] = m10;
+               v[1] = m11;
+               v[2] = m12;
+               v[3] = m13;
+        } else if(row == 2) {
+               v[0] = m20;
+               v[1] = m21;
+               v[2] = m22;
+               v[3] = m23;
+        } else if(row == 3) {
+               v[0] = m30;
+               v[1] = m31;
+               v[2] = m32;
+               v[3] = m33;
+        } else {
+
+          throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4d2"));
+        }
+    }
+    /**   
+     * Copies the matrix values in the specified column into the vector 
+     * parameter.
+     * @param column  the matrix column
+     * @param v    the vector into which the matrix column values will be copied 
+     */   
+    public final void getColumn(int column, Vector4d v) { 
+        if( column == 0 ) {
+           v.x = m00; 
+           v.y = m10;
+           v.z = m20;
+           v.w = m30;
+        } else if(column == 1) {
+           v.x = m01; 
+           v.y = m11;
+           v.z = m21;
+           v.w = m31;
+        } else if(column == 2) {
+           v.x = m02; 
+           v.y = m12;
+           v.z = m22;
+           v.w = m32;
+        } else if(column == 3) {
+           v.x = m03; 
+           v.y = m13;
+           v.z = m23;
+           v.w = m33;
+        } else {
+          throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4d3"));
+
+        }
+
+    } 
+    /**   
+     * Copies the matrix values in the specified column into the array 
+     * parameter. 
+     * @param column the matrix column
+     * @param v    the array into which the matrix column values will be copied 
+     */  
+    public final void getColumn(int column, double v[]) {
+        if( column == 0 ) {
+           v[0] = m00;
+           v[1] = m10;
+           v[2] = m20;
+           v[3] = m30;
+        } else if(column == 1) {
+           v[0] = m01;
+           v[1] = m11;
+           v[2] = m21;
+           v[3] = m31;
+        } else if(column == 2) {
+           v[0] = m02;
+           v[1] = m12;
+           v[2] = m22;
+           v[3] = m32;
+        } else if(column == 3) {
+           v[0] = m03;
+           v[1] = m13;
+           v[2] = m23;
+           v[3] = m33;
+        } else {
+          throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4d3"));
+
+        }
+
+    } 
+
+    /**  
+     * Performs an SVD normalization of this matrix in order to acquire
+     * the normalized rotational component; the values are placed into
+     * the Matrix3d parameter.
+     * @param m1 the matrix into which the rotational component is placed
+     */  
+    public final void get(Matrix3d m1)
+    {
+       double[]    tmp_rot = new double[9];  // scratch matrix
+       double[]    tmp_scale = new double[3];  // scratch matrix
+       getScaleRotate( tmp_scale, tmp_rot );
+
+        m1.m00 = tmp_rot[0];
+        m1.m01 = tmp_rot[1];
+        m1.m02 = tmp_rot[2];
+
+        m1.m10 = tmp_rot[3];
+        m1.m11 = tmp_rot[4];
+        m1.m12 = tmp_rot[5];
+
+        m1.m20 = tmp_rot[6];
+        m1.m21 = tmp_rot[7];
+        m1.m22 = tmp_rot[8];
+    }
+
+    /**   
+     * Performs an SVD normalization of this matrix in order to acquire 
+     * the normalized rotational component; the values are placed into 
+     * the Matrix3f parameter. 
+     * @param m1 the matrix into which the rotational component is placed 
+     */   
+    public final void get(Matrix3f m1) 
+    {
+       double[]    tmp_rot = new double[9];  // scratch matrix
+       double[]    tmp_scale = new double[3];  // scratch matrix
+       
+       getScaleRotate( tmp_scale, tmp_rot );
+
+        m1.m00 = (float)tmp_rot[0];
+        m1.m01 = (float)tmp_rot[1];
+        m1.m02 = (float)tmp_rot[2];
+
+        m1.m10 = (float)tmp_rot[3];
+        m1.m11 = (float)tmp_rot[4];
+        m1.m12 = (float)tmp_rot[5];
+
+        m1.m20 = (float)tmp_rot[6];
+        m1.m21 = (float)tmp_rot[7];
+        m1.m22 = (float)tmp_rot[8];
+    } 
+
+   /**
+     * Performs an SVD normalization of this matrix to calculate
+     * the rotation as a 3x3 matrix, the translation, and the scale.
+     * None of the matrix values are modified.
+     * @param m1  the normalized matrix representing the rotation
+     * @param t1  the translation component
+     * @return  the scale component of this transform
+     */  
+    public final double get(Matrix3d m1, Vector3d t1)
+    {    
+       
+       double[]    tmp_rot = new double[9];  // scratch matrix
+       double[]    tmp_scale = new double[3];  // scratch matrix
+       getScaleRotate( tmp_scale, tmp_rot );
+
+        m1.m00 = tmp_rot[0];
+        m1.m01 = tmp_rot[1];
+        m1.m02 = tmp_rot[2];
+
+        m1.m10 = tmp_rot[3];
+        m1.m11 = tmp_rot[4];
+        m1.m12 = tmp_rot[5];
+
+        m1.m20 = tmp_rot[6];
+        m1.m21 = tmp_rot[7];
+        m1.m22 = tmp_rot[8];
+
+        t1.x = m03;
+        t1.y = m13;
+        t1.z = m23;
+
+        return( Matrix3d.max3( tmp_scale ));
+       
+    }
+
+   /**   
+     * Performs an SVD normalization of this matrix to calculate
+     * the rotation as a 3x3 matrix, the translation, and the scale.
+     * None of the matrix values are modified.
+     * @param m1  the normalized matrix representing the rotation
+     * @param t1  the translation component
+     * @return  the scale component of this transform
+     */  
+    public final double get(Matrix3f m1, Vector3d t1){
+       
+       double[]    tmp_rot = new double[9];  // scratch matrix
+       double[]    tmp_scale = new double[3];  // scratch matrix
+        getScaleRotate( tmp_scale, tmp_rot );
+
+        m1.m00 = (float)tmp_rot[0];
+        m1.m01 = (float)tmp_rot[1];
+        m1.m02 = (float)tmp_rot[2];
+
+        m1.m10 = (float)tmp_rot[3];
+        m1.m11 = (float)tmp_rot[4];
+        m1.m12 = (float)tmp_rot[5];
+
+        m1.m20 = (float)tmp_rot[6];
+        m1.m21 = (float)tmp_rot[7];
+        m1.m22 = (float)tmp_rot[8];
+
+        t1.x = m03;
+        t1.y = m13;
+        t1.z = m23;
+
+        return( Matrix3d.max3( tmp_scale ));
+       
+    }    
+
+    /**
+     * Performs an SVD normalization of this matrix in order to acquire
+     * the normalized rotational component; the values are placed into
+     * the Quat4f parameter.
+     * @param q1  quaternion into which the rotation component is placed
+     */  
+    public final void get(Quat4f q1)
+    {
+
+       double[]    tmp_rot = new double[9];  // scratch matrix
+       double[]    tmp_scale = new double[3];  // scratch matrix
+        getScaleRotate( tmp_scale, tmp_rot );
+
+        double ww;   
+
+        ww = 0.25*(1.0 + tmp_rot[0] + tmp_rot[4] + tmp_rot[8]);
+        if(!((ww<0?-ww:ww) < 1.0e-30)) {
+          q1.w = (float)Math.sqrt(ww);
+          ww = 0.25/q1.w; 
+          q1.x = (float)((tmp_rot[7] - tmp_rot[5])*ww);
+          q1.y = (float)((tmp_rot[2] - tmp_rot[6])*ww);
+          q1.z = (float)((tmp_rot[3] - tmp_rot[1])*ww);
+          return;
+        }
+
+        q1.w = 0.0f;
+        ww = -0.5*(tmp_rot[4] + tmp_rot[8]);
+        if(!((ww<0?-ww:ww) < 1.0e-30)) {
+          q1.x =  (float)Math.sqrt(ww);
+          ww = 0.5/q1.x;  
+          q1.y = (float)(tmp_rot[3]*ww);
+          q1.z = (float)(tmp_rot[6]*ww);
+          return;
+        }
+
+        q1.x = 0.0f;
+        ww = 0.5*(1.0 - tmp_rot[8]);
+        if(!((ww<0?-ww:ww) < 1.0e-30)) {
+          q1.y =  (float)(Math.sqrt(ww));
+          q1.z = (float)(tmp_rot[7]/(2.0*q1.y));
+          return;
+        }
+     
+        q1.y = 0.0f;
+        q1.z = 1.0f;
+
+    }
+
+    /** 
+     * Performs an SVD normalization of q1 matrix in order to acquire 
+     * the normalized rotational component; the values are placed into 
+     * the Quat4d parameter. 
+     * @param q1  the quaternion into which the rotation component is placed 
+     */   
+    public final void get(Quat4d q1) 
+    { 
+       double[]    tmp_rot = new double[9];  // scratch matrix
+       double[]    tmp_scale = new double[3];  // scratch matrix
+       
+       getScaleRotate( tmp_scale, tmp_rot );
+
+        double ww;   
+
+        ww = 0.25*(1.0 + tmp_rot[0] + tmp_rot[4] + tmp_rot[8]);
+        if(!((ww<0?-ww:ww) < 1.0e-30)) {
+          q1.w = Math.sqrt(ww);
+          ww = 0.25/q1.w; 
+          q1.x = (tmp_rot[7] - tmp_rot[5])*ww;
+          q1.y = (tmp_rot[2] - tmp_rot[6])*ww;
+          q1.z = (tmp_rot[3] - tmp_rot[1])*ww;
+          return;
+        }
+
+        q1.w = 0.0f;
+        ww = -0.5*(tmp_rot[4] + tmp_rot[8]);
+        if(!((ww<0?-ww:ww) < 1.0e-30)) {
+          q1.x =  Math.sqrt(ww);
+          ww = 0.5/q1.x;  
+          q1.y = tmp_rot[3]*ww;
+          q1.z = tmp_rot[6]*ww;
+          return;
+        }
+
+        q1.x = 0.0;
+        ww = 0.5*(1.0 - tmp_rot[8]);
+        if(!((ww<0?-ww:ww) < 1.0e-30)) {
+          q1.y =  Math.sqrt(ww);
+          q1.z = tmp_rot[7]/(2.0*q1.y);
+          return;
+        }
+     
+        q1.y = 0.0;
+        q1.z = 1.0;
+    } 
+
+   /**
+     * Retrieves the translational components of this matrix.
+     * @param trans  the vector that will receive the translational component
+     */  
+    public final void get(Vector3d trans)
+    {
+        trans.x = m03;
+        trans.y = m13;
+        trans.z = m23;
+    }
+
+  /**
+    * Gets the upper 3x3 values of this matrix and places them into
+    * the matrix m1.
+    * @param m1  the matrix that will hold the values
+    */
+    public final void getRotationScale(Matrix3f m1)
+    {
+      m1.m00 = (float)m00; m1.m01 = (float)m01; m1.m02 = (float)m02;
+      m1.m10 = (float)m10; m1.m11 = (float)m11; m1.m12 = (float)m12;
+      m1.m20 = (float)m20; m1.m21 = (float)m21; m1.m22 = (float)m22;
+    }
+
+  /** 
+    * Gets the upper 3x3 values of this matrix and places them into 
+    * the matrix m1. 
+    * @param m1  the matrix that will hold the values 
+    */
+    public final void getRotationScale(Matrix3d m1)
+    { 
+      m1.m00 = m00; m1.m01 = m01; m1.m02 = m02; 
+      m1.m10 = m10; m1.m11 = m11; m1.m12 = m12; 
+      m1.m20 = m20; m1.m21 = m21; m1.m22 = m22; 
+    } 
+
+   /**
+     * Performs an SVD normalization of this matrix to calculate
+     * and return the uniform scale factor. If the matrix has non-uniform 
+     * scale factors, the largest of the x, y, and z scale factors will 
+     * be returned. This matrix is not modified.
+     * @return  the scale factor of this matrix
+     */  
+    public final double getScale()
+    {
+       
+       double[]    tmp_rot = new double[9];  // scratch matrix
+       double[]    tmp_scale = new double[3];  // scratch matrix
+       getScaleRotate( tmp_scale, tmp_rot );
+
+        return( Matrix3d.max3( tmp_scale ));
+
+    }
+
+  /**
+   * Replaces the upper 3x3 matrix values of this matrix with the
+   * values in the matrix m1.
+   * @param m1  the matrix that will be the new upper 3x3
+   */
+    public final void setRotationScale(Matrix3d m1)
+    {
+      m00 = m1.m00; m01 = m1.m01; m02 = m1.m02;
+      m10 = m1.m10; m11 = m1.m11; m12 = m1.m12;
+      m20 = m1.m20; m21 = m1.m21; m22 = m1.m22;
+    }
+
+  /** 
+   * Replaces the upper 3x3 matrix values of this matrix with the 
+   * values in the matrix m1. 
+   * @param m1  the matrix that will be the new upper 3x3 
+   */ 
+    public final void setRotationScale(Matrix3f m1) 
+    { 
+      m00 = m1.m00; m01 = m1.m01; m02 = m1.m02; 
+      m10 = m1.m10; m11 = m1.m11; m12 = m1.m12; 
+      m20 = m1.m20; m21 = m1.m21; m22 = m1.m22; 
+    } 
+
+   /**
+     * Sets the scale component of the current matrix by factoring
+     * out the current scale (by doing an SVD) from the rotational
+     * component and multiplying by the new scale.
+     * @param scale  the new scale amount
+     */
+    public final void setScale(double scale)
+    {
+       double[]    tmp_rot = new double[9];  // scratch matrix
+       double[]    tmp_scale = new double[3];  // scratch matrix
+       
+       getScaleRotate( tmp_scale, tmp_rot );
+
+        m00 = tmp_rot[0]*scale;
+        m01 = tmp_rot[1]*scale;
+        m02 = tmp_rot[2]*scale;
+
+        m10 = tmp_rot[3]*scale;
+        m11 = tmp_rot[4]*scale;
+        m12 = tmp_rot[5]*scale;
+
+        m20 = tmp_rot[6]*scale;
+        m21 = tmp_rot[7]*scale;
+        m22 = tmp_rot[8]*scale;
+
+    }
+
+    /**
+     * Sets the specified row of this matrix4d to the four values provided.
+     * @param row the row number to be modified (zero indexed)
+     * @param x the first column element
+     * @param y the second column element
+     * @param z the third column element
+     * @param w the fourth column element
+     */
+    public final void setRow(int row, double x, double y, double z, double w)
+    {
+       switch (row) {
+       case 0:
+           this.m00 = x;
+           this.m01 = y;
+           this.m02 = z;
+           this.m03 = w;
+           break;
+
+       case 1:
+           this.m10 = x;
+           this.m11 = y;
+           this.m12 = z;
+           this.m13 = w;
+           break;
+
+       case 2:
+           this.m20 = x;
+           this.m21 = y;
+           this.m22 = z;
+           this.m23 = w;
+           break;
+
+       case 3:
+           this.m30 = x;
+           this.m31 = y;
+           this.m32 = z;
+           this.m33 = w;
+           break;
+
+       default: 
+            throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4d4"));
+
+       }
+    }
+
+    /**
+     * Sets the specified row of this matrix4d to the Vector provided.
+     * @param row the row number to be modified (zero indexed)
+     * @param v the replacement row
+     */
+    public final void setRow(int row, Vector4d v)
+    {
+       switch (row) {
+       case 0:
+           this.m00 = v.x;
+           this.m01 = v.y;
+           this.m02 = v.z;
+           this.m03 = v.w;
+           break;
+
+       case 1:
+           this.m10 = v.x;
+           this.m11 = v.y;
+           this.m12 = v.z;
+           this.m13 = v.w;
+           break;
+
+       case 2:
+           this.m20 = v.x;
+           this.m21 = v.y;
+           this.m22 = v.z;
+           this.m23 = v.w;
+           break;
+
+       case 3:
+           this.m30 = v.x;
+           this.m31 = v.y;
+           this.m32 = v.z;
+           this.m33 = v.w;
+           break;
+
+       default:
+            throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4d4"));
+       }
+    }
+
+    /**
+     * Sets the specified row of this matrix4d to the four values provided.
+     * @param row the row number to be modified (zero indexed)
+     * @param v the replacement row
+     */
+    public final void setRow(int row, double v[])
+    {
+       switch (row) {
+       case 0:
+           this.m00 = v[0];
+           this.m01 = v[1];
+           this.m02 = v[2];
+           this.m03 = v[3];
+           break;
+
+       case 1:
+           this.m10 = v[0];
+           this.m11 = v[1];
+           this.m12 = v[2];
+           this.m13 = v[3];
+           break;
+
+       case 2:
+           this.m20 = v[0];
+           this.m21 = v[1];
+           this.m22 = v[2];
+           this.m23 = v[3];
+           break;
+
+       case 3:
+           this.m30 = v[0];
+           this.m31 = v[1];
+           this.m32 = v[2];
+           this.m33 = v[3];
+           break;
+
+       default:
+            throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4d4"));
+       }
+    }
+
+    /**
+     * Sets the specified column of this matrix4d to the four values provided.
+     * @param column the column number to be modified (zero indexed)
+     * @param x the first row element
+     * @param y the second row element
+     * @param z the third row element
+     * @param w the fourth row element
+     */
+    public final void setColumn(int column, double x, double y, double z, double w)
+    {
+       switch (column) {
+       case 0:
+           this.m00 = x;
+           this.m10 = y;
+           this.m20 = z;
+           this.m30 = w;
+           break;
+
+       case 1:
+           this.m01 = x;
+           this.m11 = y;
+           this.m21 = z;
+           this.m31 = w;
+           break;
+
+       case 2:
+           this.m02 = x;
+           this.m12 = y;
+           this.m22 = z;
+           this.m32 = w;
+           break;
+
+       case 3:
+           this.m03 = x;
+           this.m13 = y;
+           this.m23 = z;
+           this.m33 = w;
+           break;
+
+       default:
+            throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4d7"));
+       }
+    }
+
+    /**
+     * Sets the specified column of this matrix4d to the vector provided.
+     * @param column the column number to be modified (zero indexed)
+     * @param v the replacement column
+     */
+    public final void setColumn(int column, Vector4d v)
+    {
+       switch (column) {
+       case 0:
+           this.m00 = v.x;
+           this.m10 = v.y;
+           this.m20 = v.z;
+           this.m30 = v.w;
+           break;
+
+       case 1:
+           this.m01 = v.x;
+           this.m11 = v.y;
+           this.m21 = v.z;
+           this.m31 = v.w;
+           break;
+
+       case 2:
+           this.m02 = v.x;
+           this.m12 = v.y;
+           this.m22 = v.z;
+           this.m32 = v.w;
+           break;
+
+       case 3:
+           this.m03 = v.x;
+           this.m13 = v.y;
+           this.m23 = v.z;
+           this.m33 = v.w;
+           break;
+
+       default:
+            throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4d7"));
+       }
+    }
+
+    /**
+     * Sets the specified column of this matrix4d to the four values provided.
+     * @param column the column number to be modified (zero indexed)
+     * @param v the replacement column
+     */
+    public final void setColumn(int column, double v[])
+    {
+       switch (column) {
+       case 0:
+           this.m00 = v[0];
+           this.m10 = v[1];
+           this.m20 = v[2];
+           this.m30 = v[3];
+           break;
+
+       case 1:
+           this.m01 = v[0];
+           this.m11 = v[1];
+           this.m21 = v[2];
+           this.m31 = v[3];
+           break;
+
+       case 2:
+           this.m02 = v[0];
+           this.m12 = v[1];
+           this.m22 = v[2];
+           this.m32 = v[3];
+           break;
+
+       case 3:
+           this.m03 = v[0];
+           this.m13 = v[1];
+           this.m23 = v[2];
+           this.m33 = v[3];
+           break;
+
+       default:
+            throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4d7"));
+       }
+    }
+
+   /**
+     *  Adds a scalar to each component of this matrix.
+     *  @param scalar  the scalar adder
+     */  
+    public final void add(double scalar)
+    {
+        m00 += scalar;
+        m01 += scalar;
+        m02 += scalar;
+        m03 += scalar;
+        m10 += scalar;
+        m11 += scalar;
+        m12 += scalar;
+        m13 += scalar;
+        m20 += scalar;
+        m21 += scalar;
+        m22 += scalar;
+        m23 += scalar;
+        m30 += scalar;
+        m31 += scalar;
+        m32 += scalar;
+        m33 += scalar;
+    }
+
+   /**
+     *  Adds a scalar to each component of the matrix m1 and places
+     *  the result into this.  Matrix m1 is not modified.
+     *  @param scalar  the scalar adder
+     *  @param m1  the original matrix values
+     */  
+    public final void add(double scalar, Matrix4d m1)
+    {
+        this.m00 = m1.m00 +  scalar; 
+        this.m01 = m1.m01 +  scalar; 
+        this.m02 = m1.m02 +  scalar; 
+        this.m03 = m1.m03 +  scalar; 
+        this.m10 = m1.m10 +  scalar; 
+        this.m11 = m1.m11 +  scalar; 
+        this.m12 = m1.m12 +  scalar; 
+        this.m13 = m1.m13 +  scalar; 
+        this.m20 = m1.m20 +  scalar; 
+        this.m21 = m1.m21 +  scalar; 
+        this.m22 = m1.m22 +  scalar; 
+        this.m23 = m1.m23 +  scalar; 
+        this.m30 = m1.m30 +  scalar; 
+        this.m31 = m1.m31 +  scalar; 
+        this.m32 = m1.m32 +  scalar; 
+        this.m33 = m1.m33 +  scalar; 
+    }
+
+    /**
+     * Sets the value of this matrix to the matrix sum of matrices m1 and m2.
+     * @param m1 the first matrix
+     * @param m2 the second matrix
+     */
+    public final void add(Matrix4d m1, Matrix4d m2)
+    {
+       this.m00 = m1.m00 + m2.m00;
+       this.m01 = m1.m01 + m2.m01;
+       this.m02 = m1.m02 + m2.m02;
+       this.m03 = m1.m03 + m2.m03;
+
+       this.m10 = m1.m10 + m2.m10;
+       this.m11 = m1.m11 + m2.m11;
+       this.m12 = m1.m12 + m2.m12;
+       this.m13 = m1.m13 + m2.m13;
+
+       this.m20 = m1.m20 + m2.m20;
+       this.m21 = m1.m21 + m2.m21;
+       this.m22 = m1.m22 + m2.m22;
+       this.m23 = m1.m23 + m2.m23;
+
+       this.m30 = m1.m30 + m2.m30;
+       this.m31 = m1.m31 + m2.m31;
+       this.m32 = m1.m32 + m2.m32;
+       this.m33 = m1.m33 + m2.m33;
+    }
+
+    /**
+     * Sets the value of this matrix to sum of itself and matrix m1.
+     * @param m1 the other matrix
+     */
+    public final void add(Matrix4d m1)
+    {  
+        this.m00 += m1.m00;
+        this.m01 += m1.m01;
+        this.m02 += m1.m02;
+        this.m03 += m1.m03;
+        this.m10 += m1.m10;
+        this.m11 += m1.m11;
+        this.m12 += m1.m12;
+        this.m13 += m1.m13;
+        this.m20 += m1.m20;
+        this.m21 += m1.m21;
+        this.m22 += m1.m22;
+        this.m23 += m1.m23;
+        this.m30 += m1.m30;
+        this.m31 += m1.m31;
+        this.m32 += m1.m32;
+        this.m33 += m1.m33;
+    }  
+
+    /**
+     * Sets the value of this matrix to the matrix difference
+     * of matrices m1 and m2.
+     * @param m1 the first matrix
+     * @param m2 the second matrix
+     */
+    public final void sub(Matrix4d m1, Matrix4d m2)
+    {
+       this.m00 = m1.m00 - m2.m00;
+       this.m01 = m1.m01 - m2.m01;
+       this.m02 = m1.m02 - m2.m02;
+       this.m03 = m1.m03 - m2.m03;
+
+       this.m10 = m1.m10 - m2.m10;
+       this.m11 = m1.m11 - m2.m11;
+       this.m12 = m1.m12 - m2.m12;
+       this.m13 = m1.m13 - m2.m13;
+
+       this.m20 = m1.m20 - m2.m20;
+       this.m21 = m1.m21 - m2.m21;
+       this.m22 = m1.m22 - m2.m22;
+       this.m23 = m1.m23 - m2.m23;
+
+       this.m30 = m1.m30 - m2.m30;
+       this.m31 = m1.m31 - m2.m31;
+       this.m32 = m1.m32 - m2.m32;
+       this.m33 = m1.m33 - m2.m33;
+    }
+
+    /**
+     * Sets the value of this matrix to the matrix difference of itself
+     * and matrix m1 (this = this - m1).
+     * @param m1 the other matrix
+     */
+    public final void sub(Matrix4d m1)
+    {  
+        this.m00 -= m1.m00;
+        this.m01 -= m1.m01;
+        this.m02 -= m1.m02;
+        this.m03 -= m1.m03;
+        this.m10 -= m1.m10;
+        this.m11 -= m1.m11;
+        this.m12 -= m1.m12;
+        this.m13 -= m1.m13;
+        this.m20 -= m1.m20;
+        this.m21 -= m1.m21;
+        this.m22 -= m1.m22;
+        this.m23 -= m1.m23;
+        this.m30 -= m1.m30;
+        this.m31 -= m1.m31;
+        this.m32 -= m1.m32;
+        this.m33 -= m1.m33;
+    }  
+
+    /**
+     * Sets the value of this matrix to its transpose.
+     */
+    public final void transpose()
+    {
+       double temp;
+
+       temp = this.m10;
+       this.m10 = this.m01;
+       this.m01 = temp;
+
+       temp = this.m20;
+       this.m20 = this.m02;
+       this.m02 = temp;
+
+       temp = this.m30;
+       this.m30 = this.m03;
+       this.m03 = temp;
+
+       temp = this.m21;
+       this.m21 = this.m12;
+       this.m12 = temp;
+
+       temp = this.m31;
+       this.m31 = this.m13;
+       this.m13 = temp;
+
+       temp = this.m32;
+       this.m32 = this.m23;
+       this.m23 = temp;
+    }
+
+    /**
+     * Sets the value of this matrix to the transpose of the argument matrix
+     * @param m1 the matrix to be transposed
+     */
+    public final void transpose(Matrix4d m1)
+    {
+       if (this != m1) {
+           this.m00 = m1.m00;
+           this.m01 = m1.m10;
+           this.m02 = m1.m20;
+           this.m03 = m1.m30;
+
+           this.m10 = m1.m01;
+           this.m11 = m1.m11;
+           this.m12 = m1.m21;
+           this.m13 = m1.m31;
+
+           this.m20 = m1.m02;
+           this.m21 = m1.m12;
+           this.m22 = m1.m22;
+           this.m23 = m1.m32;
+
+           this.m30 = m1.m03;
+           this.m31 = m1.m13;
+           this.m32 = m1.m23;
+           this.m33 = m1.m33;
+       } else
+           this.transpose();
+    }
+
+    /**
+     *  Sets the values in this Matrix4d equal to the row-major
+     *  array parameter (ie, the first four elements of the
+     *  array will be copied into the first row of this matrix, etc.).
+     *  @param m  the double precision array of length 16
+     */
+    public final void set(double[] m)
+    {
+          m00 = m[0];
+          m01 = m[1];
+          m02 = m[2];
+          m03 = m[3];
+          m10 = m[4];
+          m11 = m[5];
+          m12 = m[6];
+          m13 = m[7];
+          m20 = m[8];
+          m21 = m[9];
+          m22 = m[10];
+          m23 = m[11];
+          m30 = m[12];
+          m31 = m[13];
+          m32 = m[14];
+          m33 = m[15];
+    }
+
+    /**  
+     * Sets the rotational component (upper 3x3) of this matrix to the
+     * matrix values in the single precision Matrix3f argument; the other
+     * elements of this matrix are initialized as if this were an identity
+     * matrix (i.e., affine matrix with no translational component).
+     * @param m1   the double precision 3x3 matrix
+     */  
+    public final void set(Matrix3f m1)
+    {
+       m00 = m1.m00; m01 = m1.m01; m02 = m1.m02; m03 = 0.0;
+       m10 = m1.m10; m11 = m1.m11; m12 = m1.m12; m13 = 0.0;
+       m20 = m1.m20; m21 = m1.m21; m22 = m1.m22; m23 = 0.0;
+       m30 = 0.0;    m31 = 0.0   ; m32 = 0.0   ; m33 = 1.0;
+    }
+
+    /**  
+     * Sets the rotational component (upper 3x3) of this matrix to the 
+     * matrix values in the double precision Matrix3d argument; the other 
+     * elements of this matrix are initialized as if this were an identity 
+     * matrix (i.e., affine matrix with no translational component).
+     * @param m1   the double precision 3x3 matrix 
+     */   
+    public final void set(Matrix3d m1)   
+    {
+       m00 = m1.m00; m01 = m1.m01; m02 = m1.m02; m03 = 0.0;
+       m10 = m1.m10; m11 = m1.m11; m12 = m1.m12; m13 = 0.0;
+       m20 = m1.m20; m21 = m1.m21; m22 = m1.m22; m23 = 0.0;
+       m30 = 0.0;    m31 = 0.0   ; m32 = 0.0   ; m33 = 1.0;
+    } 
+
+    /**
+     * Sets the value of this matrix to the matrix conversion of the
+     * (double precision) quaternion argument.
+     * @param q1 the quaternion to be converted
+     */
+    public final void set(Quat4d q1)
+    {
+       this.m00 = (1.0 - 2.0*q1.y*q1.y - 2.0*q1.z*q1.z);
+       this.m10 = (2.0*(q1.x*q1.y + q1.w*q1.z));
+       this.m20 = (2.0*(q1.x*q1.z - q1.w*q1.y));
+
+       this.m01 = (2.0*(q1.x*q1.y - q1.w*q1.z));
+       this.m11 = (1.0 - 2.0*q1.x*q1.x - 2.0*q1.z*q1.z);
+       this.m21 = (2.0*(q1.y*q1.z + q1.w*q1.x));
+
+       this.m02 = (2.0*(q1.x*q1.z + q1.w*q1.y));
+       this.m12 = (2.0*(q1.y*q1.z - q1.w*q1.x));
+       this.m22 = (1.0 - 2.0*q1.x*q1.x - 2.0*q1.y*q1.y);
+
+       this.m03 = 0.0;
+       this.m13 = 0.0;
+       this.m23 = 0.0;
+
+       this.m30 = 0.0;
+       this.m31 = 0.0;
+       this.m32 = 0.0;
+       this.m33 = 1.0;
+    }
+
+    /**
+     * Sets the value of this matrix to the matrix conversion of the
+     * double precision axis and angle argument.
+     * @param a1 the axis and angle to be converted
+     */
+    public final void set(AxisAngle4d a1)
+    {
+      double mag = Math.sqrt( a1.x*a1.x + a1.y*a1.y + a1.z*a1.z);
+
+      if( mag < EPS ) {
+        m00 = 1.0;
+        m01 = 0.0;
+        m02 = 0.0;
+
+        m10 = 0.0;
+        m11 = 1.0;
+        m12 = 0.0;
+
+        m20 = 0.0;
+        m21 = 0.0;
+        m22 = 1.0;
+      } else {
+        mag = 1.0/mag;
+         double ax = a1.x*mag;
+         double ay = a1.y*mag;
+         double az = a1.z*mag;
+
+         double sinTheta = Math.sin(a1.angle);
+         double cosTheta = Math.cos(a1.angle);
+         double t = 1.0 - cosTheta;
+         
+         double xz = ax * az;
+         double xy = ax * ay;
+         double yz = ay * az;
+         
+         m00 = t * ax * ax + cosTheta;
+         m01 = t * xy - sinTheta * az;
+         m02 = t * xz + sinTheta * ay;
+
+         m10 = t * xy + sinTheta * az;
+         m11 = t * ay * ay + cosTheta;
+         m12 = t * yz - sinTheta * ax;
+
+         m20 = t * xz - sinTheta * ay;
+         m21 = t * yz + sinTheta * ax;
+         m22 = t * az * az + cosTheta;
+      }
+
+      m03 = 0.0;
+      m13 = 0.0;
+      m23 = 0.0;
+
+      m30 = 0.0;
+      m31 = 0.0;
+      m32 = 0.0;
+      m33 = 1.0;
+    }
+
+    /**
+     * Sets the value of this matrix to the matrix conversion of the
+     * single precision quaternion argument.
+     * @param q1 the quaternion to be converted
+     */
+    public final void set(Quat4f q1)
+    {
+       this.m00 = (1.0 - 2.0*q1.y*q1.y - 2.0*q1.z*q1.z);
+       this.m10 = (2.0*(q1.x*q1.y + q1.w*q1.z));
+       this.m20 = (2.0*(q1.x*q1.z - q1.w*q1.y));
+
+       this.m01 = (2.0*(q1.x*q1.y - q1.w*q1.z));
+       this.m11 = (1.0 - 2.0*q1.x*q1.x - 2.0*q1.z*q1.z);
+       this.m21 = (2.0*(q1.y*q1.z + q1.w*q1.x));
+
+       this.m02 = (2.0*(q1.x*q1.z + q1.w*q1.y));
+       this.m12 = (2.0*(q1.y*q1.z - q1.w*q1.x));
+       this.m22 = (1.0 - 2.0*q1.x*q1.x - 2.0*q1.y*q1.y);
+
+       this.m03 = 0.0;
+       this.m13 = 0.0;
+       this.m23 = 0.0;
+
+       this.m30 = 0.0;
+       this.m31 = 0.0;
+       this.m32 = 0.0;
+       this.m33 = 1.0;
+    }
+
+    /**
+     * Sets the value of this matrix to the matrix conversion of the
+     * single precision axis and angle argument.
+     * @param a1 the axis and angle to be converted
+     */
+    public final void set(AxisAngle4f a1)
+    {
+      double mag = Math.sqrt( a1.x*a1.x + a1.y*a1.y + a1.z*a1.z);
+
+      if( mag < EPS ) {
+        m00 = 1.0;
+        m01 = 0.0;
+        m02 = 0.0;
+
+        m10 = 0.0;
+        m11 = 1.0;
+        m12 = 0.0;
+
+        m20 = 0.0;
+        m21 = 0.0;
+        m22 = 1.0;
+      } else {
+        mag = 1.0/mag;
+         double ax = a1.x*mag;
+         double ay = a1.y*mag;
+         double az = a1.z*mag;
+
+         double sinTheta = Math.sin((double)a1.angle);
+         double cosTheta = Math.cos((double)a1.angle);
+         double t = 1.0 - cosTheta;
+
+         double xz = ax * az;
+         double xy = ax * ay;
+         double yz = ay * az;
+
+         m00 = t * ax * ax + cosTheta;
+         m01 = t * xy - sinTheta * az;
+         m02 = t * xz + sinTheta * ay;
+
+         m10 = t * xy + sinTheta * az;
+         m11 = t * ay * ay + cosTheta;
+         m12 = t * yz - sinTheta * ax;
+
+         m20 = t * xz - sinTheta * ay;
+         m21 = t * yz + sinTheta * ax;
+         m22 = t * az * az + cosTheta;
+      }
+      m03 = 0.0;
+      m13 = 0.0;
+      m23 = 0.0;
+
+      m30 = 0.0;
+      m31 = 0.0;
+      m32 = 0.0;
+      m33 = 1.0;
+    }
+
+    /**  
+     * Sets the value of this matrix from the rotation expressed
+     * by the quaternion q1, the translation t1, and the scale s.
+     * @param q1 the rotation expressed as a quaternion
+     * @param t1 the translation
+     * @param s the scale value
+     */
+    public final void set(Quat4d q1, Vector3d t1, double s)
+    {  
+        this.m00 = s*(1.0 - 2.0*q1.y*q1.y - 2.0*q1.z*q1.z);
+        this.m10 = s*(2.0*(q1.x*q1.y + q1.w*q1.z));
+        this.m20 = s*(2.0*(q1.x*q1.z - q1.w*q1.y));
+        this.m01 = s*(2.0*(q1.x*q1.y - q1.w*q1.z));
+        this.m11 = s*(1.0 - 2.0*q1.x*q1.x - 2.0*q1.z*q1.z);
+        this.m21 = s*(2.0*(q1.y*q1.z + q1.w*q1.x));
+        this.m02 = s*(2.0*(q1.x*q1.z + q1.w*q1.y));
+        this.m12 = s*(2.0*(q1.y*q1.z - q1.w*q1.x));
+        this.m22 = s*(1.0 - 2.0*q1.x*q1.x - 2.0*q1.y*q1.y);
+        this.m03 = t1.x;
+        this.m13 = t1.y;
+        this.m23 = t1.z;
+        this.m30 = 0.0;
+        this.m31 = 0.0;
+        this.m32 = 0.0;
+        this.m33 = 1.0;
+    }
+
+    /**
+     * Sets the value of this matrix from the rotation expressed
+     * by the quaternion q1, the translation t1, and the scale s.
+     * @param q1 the rotation expressed as a quaternion
+     * @param t1 the translation
+     * @param s the scale value
+     */  
+    public final void set(Quat4f q1, Vector3d t1, double s)
+    {
+       this.m00 = s*(1.0 - 2.0*q1.y*q1.y - 2.0*q1.z*q1.z);
+       this.m10 = s*(2.0*(q1.x*q1.y + q1.w*q1.z));
+       this.m20 = s*(2.0*(q1.x*q1.z - q1.w*q1.y));
+
+       this.m01 = s*(2.0*(q1.x*q1.y - q1.w*q1.z));
+       this.m11 = s*(1.0 - 2.0*q1.x*q1.x - 2.0*q1.z*q1.z);
+       this.m21 = s*(2.0*(q1.y*q1.z + q1.w*q1.x));
+
+       this.m02 = s*(2.0*(q1.x*q1.z + q1.w*q1.y));
+       this.m12 = s*(2.0*(q1.y*q1.z - q1.w*q1.x));
+       this.m22 = s*(1.0 - 2.0*q1.x*q1.x - 2.0*q1.y*q1.y);
+
+       this.m03 = t1.x;
+       this.m13 = t1.y;
+       this.m23 = t1.z;
+
+       this.m30 = 0.0;
+       this.m31 = 0.0;
+       this.m32 = 0.0;
+       this.m33 = 1.0;
+    }
+
+    /**
+     * Sets the value of this matrix from the rotation expressed
+     * by the quaternion q1, the translation t1, and the scale s.
+     * @param q1 the rotation expressed as a quaternion
+     * @param t1 the translation
+     * @param s the scale value
+     */  
+    public final void set(Quat4f q1, Vector3f t1, float s)
+   {
+       this.m00 = s*(1.0 - 2.0*q1.y*q1.y - 2.0*q1.z*q1.z);
+       this.m10 = s*(2.0*(q1.x*q1.y + q1.w*q1.z));
+       this.m20 = s*(2.0*(q1.x*q1.z - q1.w*q1.y));
+
+       this.m01 = s*(2.0*(q1.x*q1.y - q1.w*q1.z));
+       this.m11 = s*(1.0 - 2.0*q1.x*q1.x - 2.0*q1.z*q1.z);
+       this.m21 = s*(2.0*(q1.y*q1.z + q1.w*q1.x));
+
+       this.m02 = s*(2.0*(q1.x*q1.z + q1.w*q1.y));
+        this.m12 = s*(2.0*(q1.y*q1.z - q1.w*q1.x));
+       this.m22 = s*(1.0 - 2.0*q1.x*q1.x - 2.0*q1.y*q1.y);
+
+       this.m03 = t1.x;
+       this.m13 = t1.y;
+       this.m23 = t1.z;
+
+       this.m30 = 0.0;
+       this.m31 = 0.0;
+       this.m32 = 0.0;
+       this.m33 = 1.0;
+   }
+
+    /**
+     * Sets the value of this matrix to a copy of the
+     * passed matrix m1.
+     * @param m1 the matrix4f 
+     */
+    public final void set(Matrix4f m1)
+    {
+       this.m00 = m1.m00;
+       this.m01 = m1.m01;
+       this.m02 = m1.m02;
+       this.m03 = m1.m03;
+
+       this.m10 = m1.m10;
+       this.m11 = m1.m11;
+       this.m12 = m1.m12;
+       this.m13 = m1.m13;
+
+       this.m20 = m1.m20;
+       this.m21 = m1.m21;
+       this.m22 = m1.m22;
+       this.m23 = m1.m23;
+
+       this.m30 = m1.m30;
+       this.m31 = m1.m31;
+       this.m32 = m1.m32;
+       this.m33 = m1.m33;
+    }
+
+    /**
+     * Sets the value of this matrix to a copy of the
+     * passed matrix m1.
+     * @param m1 the matrix to be copied
+     */
+    public final void set(Matrix4d m1)
+    {
+       this.m00 = m1.m00;
+       this.m01 = m1.m01;
+       this.m02 = m1.m02;
+       this.m03 = m1.m03;
+
+       this.m10 = m1.m10;
+       this.m11 = m1.m11;
+       this.m12 = m1.m12;
+       this.m13 = m1.m13;
+
+       this.m20 = m1.m20;
+       this.m21 = m1.m21;
+       this.m22 = m1.m22;
+       this.m23 = m1.m23;
+
+       this.m30 = m1.m30;
+       this.m31 = m1.m31;
+       this.m32 = m1.m32;
+       this.m33 = m1.m33;
+    }
+
+  /**
+   * Sets the value of this matrix to the matrix inverse
+   * of the passed (user declared) matrix m1.
+   * @param m1 the matrix to be inverted
+   */
+  public final void invert(Matrix4d m1)
+  {
+
+     invertGeneral( m1);    
+  }
+
+  /**
+   * Inverts this matrix in place.
+   */
+  public final void invert()
+  {
+     invertGeneral( this );    
+  }
+
+    /**
+     * General invert routine.  Inverts m1 and places the result in "this".
+     * Note that this routine handles both the "this" version and the
+     * non-"this" version.
+     *
+     * Also note that since this routine is slow anyway, we won't worry
+     * about allocating a little bit of garbage.
+     */
+    final void invertGeneral(Matrix4d  m1) {
+       double result[] = new double[16];
+       int row_perm[] = new int[4];
+       int i, r, c;
+
+       // Use LU decomposition and backsubstitution code specifically
+       // for floating-point 4x4 matrices.
+       double[]    tmp = new double[16];  // scratch matrix
+       // Copy source matrix to t1tmp 
+        tmp[0] = m1.m00;
+        tmp[1] = m1.m01;
+        tmp[2] = m1.m02;
+        tmp[3] = m1.m03;
+        tmp[4] = m1.m10;
+        tmp[5] = m1.m11;
+        tmp[6] = m1.m12;
+        tmp[7] = m1.m13;
+        tmp[8] = m1.m20;
+        tmp[9] = m1.m21;
+        tmp[10] = m1.m22;
+        tmp[11] = m1.m23;
+        tmp[12] = m1.m30;
+        tmp[13] = m1.m31;
+        tmp[14] = m1.m32;
+        tmp[15] = m1.m33;
+
+       // Calculate LU decomposition: Is the matrix singular? 
+       if (!luDecomposition(tmp, row_perm)) {
+           // Matrix has no inverse 
+           throw new SingularMatrixException(VecMathI18N.getString("Matrix4d10"));
+       }
+
+       // Perform back substitution on the identity matrix 
+        for(i=0;i<16;i++) result[i] = 0.0;
+        result[0] = 1.0; result[5] = 1.0; result[10] = 1.0; result[15] = 1.0;
+       luBacksubstitution(tmp, row_perm, result);
+
+        this.m00 = result[0];
+        this.m01 = result[1];
+        this.m02 = result[2];
+        this.m03 = result[3];
+
+        this.m10 = result[4];
+        this.m11 = result[5];
+        this.m12 = result[6];
+        this.m13 = result[7];
+        this.m20 = result[8];
+        this.m21 = result[9];
+        this.m22 = result[10];
+        this.m23 = result[11];
+        this.m30 = result[12];
+        this.m31 = result[13];
+        this.m32 = result[14];
+        this.m33 = result[15];
+
+    }
+
+    /**
+     * Given a 4x4 array "matrix0", this function replaces it with the 
+     * LU decomposition of a row-wise permutation of itself.  The input 
+     * parameters are "matrix0" and "dimen".  The array "matrix0" is also 
+     * an output parameter.  The vector "row_perm[4]" is an output 
+     * parameter that contains the row permutations resulting from partial 
+     * pivoting.  The output parameter "even_row_xchg" is 1 when the 
+     * number of row exchanges is even, or -1 otherwise.  Assumes data 
+     * type is always double.
+     *
+     * This function is similar to luDecomposition, except that it
+     * is tuned specifically for 4x4 matrices.
+     *
+     * @return true if the matrix is nonsingular, or false otherwise.
+     */
+    //
+    // Reference: Press, Flannery, Teukolsky, Vetterling, 
+    //       _Numerical_Recipes_in_C_, Cambridge University Press, 
+    //       1988, pp 40-45.
+    //
+    static boolean luDecomposition(double[] matrix0,
+                                  int[] row_perm) {
+
+       double row_scale[] = new double[4];
+
+       // Determine implicit scaling information by looping over rows 
+       {
+           int i, j;
+           int ptr, rs;
+           double big, temp;
+
+           ptr = 0;
+           rs = 0;
+
+           // For each row ... 
+           i = 4;
+           while (i-- != 0) {
+               big = 0.0;
+
+               // For each column, find the largest element in the row 
+               j = 4;
+               while (j-- != 0) {
+                   temp = matrix0[ptr++];
+                   temp = Math.abs(temp);
+                   if (temp > big) {
+                       big = temp;
+                   }
+               }
+
+               // Is the matrix singular? 
+               if (big == 0.0) {
+                   return false;
+               }
+               row_scale[rs++] = 1.0 / big;
+           }
+       }
+
+       {
+           int j;
+           int mtx;
+
+           mtx = 0;
+
+           // For all columns, execute Crout's method 
+           for (j = 0; j < 4; j++) {
+               int i, imax, k;
+               int target, p1, p2;
+               double sum, big, temp;
+
+               // Determine elements of upper diagonal matrix U 
+               for (i = 0; i < j; i++) {
+                   target = mtx + (4*i) + j;
+                   sum = matrix0[target];
+                   k = i;
+                   p1 = mtx + (4*i);
+                   p2 = mtx + j;
+                   while (k-- != 0) {
+                       sum -= matrix0[p1] * matrix0[p2];
+                       p1++;
+                       p2 += 4;
+                   }
+                   matrix0[target] = sum;
+               }
+
+               // Search for largest pivot element and calculate
+               // intermediate elements of lower diagonal matrix L.
+               big = 0.0;
+               imax = -1;
+               for (i = j; i < 4; i++) {
+                   target = mtx + (4*i) + j;
+                   sum = matrix0[target];
+                   k = j;
+                   p1 = mtx + (4*i);
+                   p2 = mtx + j;
+                   while (k-- != 0) {
+                       sum -= matrix0[p1] * matrix0[p2];
+                       p1++;
+                       p2 += 4;
+                   }
+                   matrix0[target] = sum;
+
+                   // Is this the best pivot so far? 
+                   if ((temp = row_scale[i] * Math.abs(sum)) >= big) {
+                       big = temp;
+                       imax = i;
+                   }
+               }
+
+               if (imax < 0) {
+                   throw new RuntimeException(VecMathI18N.getString("Matrix4d11"));
+               }
+
+               // Is a row exchange necessary? 
+               if (j != imax) {
+                   // Yes: exchange rows 
+                   k = 4;
+                   p1 = mtx + (4*imax);
+                   p2 = mtx + (4*j);
+                   while (k-- != 0) {
+                       temp = matrix0[p1];
+                       matrix0[p1++] = matrix0[p2];
+                       matrix0[p2++] = temp;
+                   }
+
+                   // Record change in scale factor 
+                   row_scale[imax] = row_scale[j];
+               }
+
+               // Record row permutation 
+               row_perm[j] = imax;
+
+               // Is the matrix singular 
+               if (matrix0[(mtx + (4*j) + j)] == 0.0) {
+                   return false;
+               }
+
+               // Divide elements of lower diagonal matrix L by pivot 
+               if (j != (4-1)) {
+                   temp = 1.0 / (matrix0[(mtx + (4*j) + j)]);
+                   target = mtx + (4*(j+1)) + j;
+                   i = 3 - j;
+                   while (i-- != 0) {
+                       matrix0[target] *= temp;
+                       target += 4;
+                   }
+               }
+           }
+       }
+
+       return true;
+    }
+
+    /**
+     * Solves a set of linear equations.  The input parameters "matrix1",
+     * and "row_perm" come from luDecompostionD4x4 and do not change
+     * here.  The parameter "matrix2" is a set of column vectors assembled
+     * into a 4x4 matrix of floating-point values.  The procedure takes each
+     * column of "matrix2" in turn and treats it as the right-hand side of the
+     * matrix equation Ax = LUx = b.  The solution vector replaces the
+     * original column of the matrix.
+     *
+     * If "matrix2" is the identity matrix, the procedure replaces its contents
+     * with the inverse of the matrix from which "matrix1" was originally
+     * derived.
+     */
+    //
+    // Reference: Press, Flannery, Teukolsky, Vetterling, 
+    //       _Numerical_Recipes_in_C_, Cambridge University Press, 
+    //       1988, pp 44-45.
+    //
+    static void luBacksubstitution(double[] matrix1,
+                                  int[] row_perm,
+                                  double[] matrix2) {
+
+       int i, ii, ip, j, k;
+       int rp;
+       int cv, rv;
+       
+       //      rp = row_perm;
+       rp = 0;
+
+       // For each column vector of matrix2 ... 
+       for (k = 0; k < 4; k++) {
+           //      cv = &(matrix2[0][k]);
+           cv = k;
+           ii = -1;
+
+           // Forward substitution 
+           for (i = 0; i < 4; i++) {
+               double sum;
+
+               ip = row_perm[rp+i];
+               sum = matrix2[cv+4*ip];
+               matrix2[cv+4*ip] = matrix2[cv+4*i];
+               if (ii >= 0) {
+                   //              rv = &(matrix1[i][0]);
+                   rv = i*4;
+                   for (j = ii; j <= i-1; j++) {
+                       sum -= matrix1[rv+j] * matrix2[cv+4*j];
+                   }
+               }
+               else if (sum != 0.0) {
+                   ii = i;
+               }
+               matrix2[cv+4*i] = sum;
+           }
+
+           // Backsubstitution 
+           //      rv = &(matrix1[3][0]);
+           rv = 3*4;
+           matrix2[cv+4*3] /= matrix1[rv+3];
+
+           rv -= 4;
+           matrix2[cv+4*2] = (matrix2[cv+4*2] -
+                           matrix1[rv+3] * matrix2[cv+4*3]) / matrix1[rv+2];
+
+           rv -= 4;
+           matrix2[cv+4*1] = (matrix2[cv+4*1] -
+                           matrix1[rv+2] * matrix2[cv+4*2] -
+                           matrix1[rv+3] * matrix2[cv+4*3]) / matrix1[rv+1];
+
+           rv -= 4;
+           matrix2[cv+4*0] = (matrix2[cv+4*0] -
+                           matrix1[rv+1] * matrix2[cv+4*1] -
+                           matrix1[rv+2] * matrix2[cv+4*2] -
+                           matrix1[rv+3] * matrix2[cv+4*3]) / matrix1[rv+0];
+       }
+    }
+
+    /**
+     * Computes the determinant of this matrix.
+     * @return the determinant of the matrix 
+     */
+    public final double determinant()
+    {
+       double det;
+
+       // cofactor exapainsion along first row 
+
+       det = m00*(m11*m22*m33+ m12*m23*m31 + m13*m21*m32 
+                - m13*m22*m31 -m11*m23*m32 - m12*m21*m33);
+       det -= m01*(m10*m22*m33+ m12*m23*m30 + m13*m20*m32 
+                 - m13*m22*m30 -m10*m23*m32 - m12*m20*m33);
+       det += m02*(m10*m21*m33+ m11*m23*m30 + m13*m20*m31 
+                 - m13*m21*m30 -m10*m23*m31 - m11*m20*m33);
+       det -= m03*(m10*m21*m32+ m11*m22*m30 + m12*m20*m31 
+                 - m12*m21*m30 -m10*m22*m31 - m11*m20*m32);
+
+        return( det );
+    }
+
+    /**
+     * Sets the value of this matrix to a scale matrix with the
+     * passed scale amount.
+     * @param scale the scale factor for the matrix
+     */
+    public final void set(double scale)
+    {
+       this.m00 = scale;
+       this.m01 = 0.0;
+       this.m02 = 0.0;
+       this.m03 = 0.0;
+
+       this.m10 = 0.0;
+       this.m11 = scale;
+       this.m12 = 0.0;
+       this.m13 = 0.0;
+
+       this.m20 = 0.0;
+       this.m21 = 0.0;
+       this.m22 = scale;
+       this.m23 = 0.0;
+
+       this.m30 = 0.0;
+       this.m31 = 0.0;
+       this.m32 = 0.0;
+       this.m33 = 1.0;
+    }
+
+    /**
+     * Sets the value of this matrix to a translate matrix by the
+     * passed translation value.
+     * @param v1 the translation amount
+     */
+    public final void set(Vector3d v1)
+    {
+       this.m00 = 1.0;
+       this.m01 = 0.0;
+       this.m02 = 0.0;
+       this.m03 = v1.x;
+
+       this.m10 = 0.0;
+       this.m11 = 1.0;
+       this.m12 = 0.0;
+       this.m13 = v1.y;
+
+       this.m20 = 0.0;
+       this.m21 = 0.0;
+       this.m22 = 1.0;
+       this.m23 = v1.z;
+
+       this.m30 = 0.0;
+       this.m31 = 0.0;
+       this.m32 = 0.0;
+       this.m33 = 1.0;
+    }
+
+    /**
+     * Sets the value of this transform to a scale and translation matrix;
+     * the scale is not applied to the translation and all of the matrix
+     * values are modified.
+     * @param scale the scale factor for the matrix
+     * @param v1 the translation amount
+     */
+    public final void set(double scale, Vector3d v1)
+    {
+       this.m00 = scale;
+       this.m01 = 0.0;
+       this.m02 = 0.0;
+       this.m03 = v1.x;
+
+       this.m10 = 0.0;
+       this.m11 = scale;
+       this.m12 = 0.0;
+       this.m13 = v1.y;
+
+       this.m20 = 0.0;
+       this.m21 = 0.0;
+       this.m22 = scale;
+       this.m23 = v1.z;
+
+       this.m30 = 0.0;
+       this.m31 = 0.0;
+       this.m32 = 0.0;
+       this.m33 = 1.0;
+    }
+
+   /**
+     * Sets the value of this transform to a scale and translation matrix;
+     * the translation is scaled by the scale factor and all of the matrix
+     * values are modified.
+     * @param v1 the translation amount
+     * @param scale the scale factor for the matrix
+     */
+    public final void set(Vector3d v1, double scale)
+    {
+       this.m00 = scale;
+       this.m01 = 0.0;
+       this.m02 = 0.0;
+       this.m03 = scale*v1.x;
+
+       this.m10 = 0.0;
+       this.m11 = scale;
+       this.m12 = 0.0;
+       this.m13 = scale*v1.y;
+
+       this.m20 = 0.0;
+       this.m21 = 0.0;
+       this.m22 = scale;
+       this.m23 = scale*v1.z;
+
+       this.m30 = 0.0;
+       this.m31 = 0.0;
+       this.m32 = 0.0;
+       this.m33 = 1.0;
+    }
+
+   /**
+     * Sets the value of this matrix from the rotation expressed by
+     * the rotation matrix m1, the translation t1, and the scale factor.
+     * The translation is not modified by the scale.
+     * @param m1  the rotation component
+     * @param t1  the translation component
+     * @param scale  the scale component
+     */
+    public final void set(Matrix3f m1, Vector3f t1, float scale)
+    { 
+        this.m00 = m1.m00*scale;
+        this.m01 = m1.m01*scale;
+        this.m02 = m1.m02*scale;
+        this.m03 = t1.x;
+
+        this.m10 = m1.m10*scale;
+        this.m11 = m1.m11*scale;
+        this.m12 = m1.m12*scale;
+        this.m13 = t1.y;
+
+        this.m20 = m1.m20*scale;
+        this.m21 = m1.m21*scale;
+        this.m22 = m1.m22*scale;
+        this.m23 = t1.z;
+
+        this.m30 = 0.0;
+        this.m31 = 0.0;
+        this.m32 = 0.0;
+        this.m33 = 1.0;
+    }
+
+   /**
+     * Sets the value of this matrix from the rotation expressed by 
+     * the rotation matrix m1, the translation t1, and the scale factor.
+     * The translation is not modified by the scale. 
+     * @param m1  the rotation component 
+     * @param t1  the translation component
+     * @param scale  the scale component 
+     */ 
+    public final void set(Matrix3d m1, Vector3d t1, double scale) 
+    {  
+        this.m00 = m1.m00*scale;
+        this.m01 = m1.m01*scale;
+        this.m02 = m1.m02*scale;
+        this.m03 = t1.x;
+
+        this.m10 = m1.m10*scale;
+        this.m11 = m1.m11*scale;
+        this.m12 = m1.m12*scale;
+        this.m13 = t1.y;
+
+        this.m20 = m1.m20*scale;
+        this.m21 = m1.m21*scale;
+        this.m22 = m1.m22*scale;
+        this.m23 = t1.z;
+
+        this.m30 = 0.0;
+        this.m31 = 0.0;
+        this.m32 = 0.0;
+        this.m33 = 1.0;
+    } 
+
+   /** 
+     * Modifies the translational components of this matrix to the values 
+     * of the Vector3d argument; the other values of this matrix are not 
+     * modified. 
+     * @param trans  the translational component
+     */   
+    public final void setTranslation(Vector3d trans) 
+    { 
+       m03 = trans.x;  
+       m13 = trans.y;
+       m23 = trans.z; 
+    } 
+
+    /**
+     * Sets the value of this matrix to a counter-clockwise rotation 
+     * about the x axis.
+     * @param angle the angle to rotate about the X axis in radians
+     */
+    public final void rotX(double angle)
+    {
+       double  sinAngle, cosAngle;
+
+       sinAngle = Math.sin(angle);
+       cosAngle = Math.cos(angle);
+
+       this.m00 = 1.0;
+       this.m01 = 0.0;
+       this.m02 = 0.0;
+       this.m03 = 0.0;
+
+       this.m10 = 0.0;
+       this.m11 = cosAngle;
+       this.m12 = -sinAngle;
+       this.m13 = 0.0;
+
+       this.m20 = 0.0;
+       this.m21 = sinAngle;
+       this.m22 = cosAngle;
+       this.m23 = 0.0;
+
+       this.m30 = 0.0;
+       this.m31 = 0.0;
+       this.m32 = 0.0;
+       this.m33 = 1.0;
+    }
+
+    /**
+     * Sets the value of this matrix to a counter-clockwise rotation 
+     * about the y axis.
+     * @param angle the angle to rotate about the Y axis in radians
+     */
+    public final void rotY(double angle)
+    {
+       double  sinAngle, cosAngle;
+
+       sinAngle = Math.sin(angle);
+       cosAngle = Math.cos(angle);
+
+       this.m00 = cosAngle;
+       this.m01 = 0.0;
+       this.m02 = sinAngle;
+       this.m03 = 0.0;
+
+       this.m10 = 0.0;
+       this.m11 = 1.0;
+       this.m12 = 0.0;
+       this.m13 = 0.0;
+
+       this.m20 = -sinAngle;
+       this.m21 = 0.0;
+       this.m22 = cosAngle;
+       this.m23 = 0.0;
+
+       this.m30 = 0.0;
+       this.m31 = 0.0;
+       this.m32 = 0.0;
+       this.m33 = 1.0;
+    }
+
+    /**
+     * Sets the value of this matrix to a counter-clockwise rotation 
+     * about the z axis.
+     * @param angle the angle to rotate about the Z axis in radians
+     */
+    public final void rotZ(double angle)
+    {
+       double  sinAngle, cosAngle;
+
+       sinAngle = Math.sin(angle);
+       cosAngle = Math.cos(angle);
+
+       this.m00 = cosAngle;
+       this.m01 = -sinAngle;
+       this.m02 = 0.0;
+       this.m03 = 0.0;
+
+       this.m10 = sinAngle;
+       this.m11 = cosAngle;
+       this.m12 = 0.0;
+       this.m13 = 0.0;
+
+       this.m20 = 0.0;
+       this.m21 = 0.0;
+       this.m22 = 1.0;
+       this.m23 = 0.0;
+
+       this.m30 = 0.0;
+       this.m31 = 0.0;
+       this.m32 = 0.0;
+       this.m33 = 1.0;
+    }
+
+   /**
+     * Multiplies each element of this matrix by a scalar.
+     * @param scalar  the scalar multiplier.
+     */
+    public final void mul(double scalar)
+    {
+      m00 *= scalar;
+      m01 *= scalar;
+      m02 *= scalar;
+      m03 *= scalar;
+      m10 *= scalar;
+      m11 *= scalar;
+      m12 *= scalar;
+      m13 *= scalar;
+      m20 *= scalar;
+      m21 *= scalar;
+      m22 *= scalar;
+      m23 *= scalar;
+      m30 *= scalar;
+      m31 *= scalar;
+      m32 *= scalar;
+      m33 *= scalar;
+    }
+
+   /**
+     * Multiplies each element of matrix m1 by a scalar and places
+     * the result into this.  Matrix m1 is not modified.
+     * @param scalar  the scalar multiplier
+     * @param m1  the original matrix
+     */  
+    public final void mul(double scalar, Matrix4d m1)
+    {
+      this.m00 = m1.m00 * scalar;
+      this.m01 = m1.m01 * scalar;
+      this.m02 = m1.m02 * scalar;
+      this.m03 = m1.m03 * scalar;
+      this.m10 = m1.m10 * scalar;
+      this.m11 = m1.m11 * scalar;
+      this.m12 = m1.m12 * scalar;
+      this.m13 = m1.m13 * scalar;
+      this.m20 = m1.m20 * scalar;
+      this.m21 = m1.m21 * scalar;
+      this.m22 = m1.m22 * scalar;
+      this.m23 = m1.m23 * scalar;
+      this.m30 = m1.m30 * scalar;
+      this.m31 = m1.m31 * scalar;
+      this.m32 = m1.m32 * scalar;
+      this.m33 = m1.m33 * scalar;
+    }
+
+    /**
+     * Sets the value of this matrix to the result of multiplying itself
+     * with matrix m1.
+     * @param m1 the other matrix
+     */
+    public final void mul(Matrix4d m1) 
+    {
+            double      m00, m01, m02, m03,
+                        m10, m11, m12, m13,
+                        m20, m21, m22, m23,
+                       m30, m31, m32, m33;  // vars for temp result matrix 
+
+        m00 = this.m00*m1.m00 + this.m01*m1.m10 + 
+              this.m02*m1.m20 + this.m03*m1.m30;
+        m01 = this.m00*m1.m01 + this.m01*m1.m11 + 
+              this.m02*m1.m21 + this.m03*m1.m31;
+        m02 = this.m00*m1.m02 + this.m01*m1.m12 + 
+              this.m02*m1.m22 + this.m03*m1.m32;
+        m03 = this.m00*m1.m03 + this.m01*m1.m13 + 
+              this.m02*m1.m23 + this.m03*m1.m33;
+
+        m10 = this.m10*m1.m00 + this.m11*m1.m10 + 
+              this.m12*m1.m20 + this.m13*m1.m30;
+        m11 = this.m10*m1.m01 + this.m11*m1.m11 + 
+              this.m12*m1.m21 + this.m13*m1.m31;
+        m12 = this.m10*m1.m02 + this.m11*m1.m12 + 
+              this.m12*m1.m22 + this.m13*m1.m32;
+        m13 = this.m10*m1.m03 + this.m11*m1.m13 + 
+              this.m12*m1.m23 + this.m13*m1.m33;
+
+        m20 = this.m20*m1.m00 + this.m21*m1.m10 + 
+              this.m22*m1.m20 + this.m23*m1.m30;
+        m21 = this.m20*m1.m01 + this.m21*m1.m11 + 
+              this.m22*m1.m21 + this.m23*m1.m31;
+        m22 = this.m20*m1.m02 + this.m21*m1.m12 + 
+              this.m22*m1.m22 + this.m23*m1.m32;
+        m23 = this.m20*m1.m03 + this.m21*m1.m13 + 
+              this.m22*m1.m23 + this.m23*m1.m33;
+
+        m30 = this.m30*m1.m00 + this.m31*m1.m10 + 
+              this.m32*m1.m20 + this.m33*m1.m30;
+        m31 = this.m30*m1.m01 + this.m31*m1.m11 + 
+              this.m32*m1.m21 + this.m33*m1.m31;
+        m32 = this.m30*m1.m02 + this.m31*m1.m12 + 
+              this.m32*m1.m22 + this.m33*m1.m32;
+        m33 = this.m30*m1.m03 + this.m31*m1.m13 + 
+              this.m32*m1.m23 + this.m33*m1.m33;
+
+        this.m00 = m00; this.m01 = m01; this.m02 = m02; this.m03 = m03;
+        this.m10 = m10; this.m11 = m11; this.m12 = m12; this.m13 = m13;
+        this.m20 = m20; this.m21 = m21; this.m22 = m22; this.m23 = m23;
+        this.m30 = m30; this.m31 = m31; this.m32 = m32; this.m33 = m33;
+    }
+
+    /**
+     * Sets the value of this matrix to the result of multiplying
+     * the two argument matrices together.
+     * @param m1 the first matrix
+     * @param m2 the second matrix
+     */
+    public final void mul(Matrix4d m1, Matrix4d m2)
+    {
+       if (this != m1 && this != m2) {
+           // code for mat mul 
+           this.m00 = m1.m00*m2.m00 + m1.m01*m2.m10 + 
+                       m1.m02*m2.m20 + m1.m03*m2.m30;
+           this.m01 = m1.m00*m2.m01 + m1.m01*m2.m11 + 
+                       m1.m02*m2.m21 + m1.m03*m2.m31;
+           this.m02 = m1.m00*m2.m02 + m1.m01*m2.m12 + 
+                       m1.m02*m2.m22 + m1.m03*m2.m32;
+           this.m03 = m1.m00*m2.m03 + m1.m01*m2.m13 + 
+                       m1.m02*m2.m23 + m1.m03*m2.m33;
+
+           this.m10 = m1.m10*m2.m00 + m1.m11*m2.m10 + 
+                       m1.m12*m2.m20 + m1.m13*m2.m30;
+           this.m11 = m1.m10*m2.m01 + m1.m11*m2.m11 + 
+                       m1.m12*m2.m21 + m1.m13*m2.m31;
+           this.m12 = m1.m10*m2.m02 + m1.m11*m2.m12 + 
+                       m1.m12*m2.m22 + m1.m13*m2.m32;
+           this.m13 = m1.m10*m2.m03 + m1.m11*m2.m13 + 
+                       m1.m12*m2.m23 + m1.m13*m2.m33;
+
+           this.m20 = m1.m20*m2.m00 + m1.m21*m2.m10 + 
+                       m1.m22*m2.m20 + m1.m23*m2.m30;
+           this.m21 = m1.m20*m2.m01 + m1.m21*m2.m11 + 
+                       m1.m22*m2.m21 + m1.m23*m2.m31;
+           this.m22 = m1.m20*m2.m02 + m1.m21*m2.m12 + 
+                       m1.m22*m2.m22 + m1.m23*m2.m32;
+           this.m23 = m1.m20*m2.m03 + m1.m21*m2.m13 + 
+                       m1.m22*m2.m23 + m1.m23*m2.m33;
+
+           this.m30 = m1.m30*m2.m00 + m1.m31*m2.m10 + 
+                       m1.m32*m2.m20 + m1.m33*m2.m30;
+           this.m31 = m1.m30*m2.m01 + m1.m31*m2.m11 + 
+                       m1.m32*m2.m21 + m1.m33*m2.m31;
+           this.m32 = m1.m30*m2.m02 + m1.m31*m2.m12 + 
+                       m1.m32*m2.m22 + m1.m33*m2.m32;
+           this.m33 = m1.m30*m2.m03 + m1.m31*m2.m13 + 
+                       m1.m32*m2.m23 + m1.m33*m2.m33;
+       } else {
+           double      m00, m01, m02, m03,
+                       m10, m11, m12, m13,
+                       m20, m21, m22, m23,
+                       m30, m31, m32, m33;  // vars for temp result matrix 
+
+           // code for mat mul 
+           m00 = m1.m00*m2.m00 + m1.m01*m2.m10 + m1.m02*m2.m20 + m1.m03*m2.m30;
+           m01 = m1.m00*m2.m01 + m1.m01*m2.m11 + m1.m02*m2.m21 + m1.m03*m2.m31;
+           m02 = m1.m00*m2.m02 + m1.m01*m2.m12 + m1.m02*m2.m22 + m1.m03*m2.m32;
+           m03 = m1.m00*m2.m03 + m1.m01*m2.m13 + m1.m02*m2.m23 + m1.m03*m2.m33;
+
+           m10 = m1.m10*m2.m00 + m1.m11*m2.m10 + m1.m12*m2.m20 + m1.m13*m2.m30;
+           m11 = m1.m10*m2.m01 + m1.m11*m2.m11 + m1.m12*m2.m21 + m1.m13*m2.m31;
+           m12 = m1.m10*m2.m02 + m1.m11*m2.m12 + m1.m12*m2.m22 + m1.m13*m2.m32;
+           m13 = m1.m10*m2.m03 + m1.m11*m2.m13 + m1.m12*m2.m23 + m1.m13*m2.m33;
+
+           m20 = m1.m20*m2.m00 + m1.m21*m2.m10 + m1.m22*m2.m20 + m1.m23*m2.m30;
+           m21 = m1.m20*m2.m01 + m1.m21*m2.m11 + m1.m22*m2.m21 + m1.m23*m2.m31;
+           m22 = m1.m20*m2.m02 + m1.m21*m2.m12 + m1.m22*m2.m22 + m1.m23*m2.m32;
+           m23 = m1.m20*m2.m03 + m1.m21*m2.m13 + m1.m22*m2.m23 + m1.m23*m2.m33;
+
+           m30 = m1.m30*m2.m00 + m1.m31*m2.m10 + m1.m32*m2.m20 + m1.m33*m2.m30;
+           m31 = m1.m30*m2.m01 + m1.m31*m2.m11 + m1.m32*m2.m21 + m1.m33*m2.m31;
+           m32 = m1.m30*m2.m02 + m1.m31*m2.m12 + m1.m32*m2.m22 + m1.m33*m2.m32;
+           m33 = m1.m30*m2.m03 + m1.m31*m2.m13 + m1.m32*m2.m23 + m1.m33*m2.m33;
+
+           this.m00 = m00; this.m01 = m01; this.m02 = m02; this.m03 = m03;
+           this.m10 = m10; this.m11 = m11; this.m12 = m12; this.m13 = m13;
+           this.m20 = m20; this.m21 = m21; this.m22 = m22; this.m23 = m23;
+           this.m30 = m30; this.m31 = m31; this.m32 = m32; this.m33 = m33;
+
+       }
+    }
+
+   /**
+     *  Multiplies the transpose of matrix m1 times the transpose of matrix
+     *  m2, and places the result into this.
+     *  @param m1  the matrix on the left hand side of the multiplication 
+     *  @param m2  the matrix on the right hand side of the multiplication
+     */  
+    public final void mulTransposeBoth(Matrix4d m1, Matrix4d m2) 
+    { 
+       if (this != m1 && this != m2) {
+            this.m00 = m1.m00*m2.m00 + m1.m10*m2.m01 + m1.m20*m2.m02 + m1.m30*m2.m03;
+            this.m01 = m1.m00*m2.m10 + m1.m10*m2.m11 + m1.m20*m2.m12 + m1.m30*m2.m13;
+            this.m02 = m1.m00*m2.m20 + m1.m10*m2.m21 + m1.m20*m2.m22 + m1.m30*m2.m23;
+            this.m03 = m1.m00*m2.m30 + m1.m10*m2.m31 + m1.m20*m2.m32 + m1.m30*m2.m33;
+
+            this.m10 = m1.m01*m2.m00 + m1.m11*m2.m01 + m1.m21*m2.m02 + m1.m31*m2.m03;
+            this.m11 = m1.m01*m2.m10 + m1.m11*m2.m11 + m1.m21*m2.m12 + m1.m31*m2.m13;
+            this.m12 = m1.m01*m2.m20 + m1.m11*m2.m21 + m1.m21*m2.m22 + m1.m31*m2.m23;
+            this.m13 = m1.m01*m2.m30 + m1.m11*m2.m31 + m1.m21*m2.m32 + m1.m31*m2.m33;
+
+            this.m20 = m1.m02*m2.m00 + m1.m12*m2.m01 + m1.m22*m2.m02 + m1.m32*m2.m03;
+            this.m21 = m1.m02*m2.m10 + m1.m12*m2.m11 + m1.m22*m2.m12 + m1.m32*m2.m13;
+            this.m22 = m1.m02*m2.m20 + m1.m12*m2.m21 + m1.m22*m2.m22 + m1.m32*m2.m23;
+            this.m23 = m1.m02*m2.m30 + m1.m12*m2.m31 + m1.m22*m2.m32 + m1.m32*m2.m33;
+
+            this.m30 = m1.m03*m2.m00 + m1.m13*m2.m01 + m1.m23*m2.m02 + m1.m33*m2.m03;
+            this.m31 = m1.m03*m2.m10 + m1.m13*m2.m11 + m1.m23*m2.m12 + m1.m33*m2.m13;
+            this.m32 = m1.m03*m2.m20 + m1.m13*m2.m21 + m1.m23*m2.m22 + m1.m33*m2.m23;
+            this.m33 = m1.m03*m2.m30 + m1.m13*m2.m31 + m1.m23*m2.m32 + m1.m33*m2.m33;
+        } else {
+            double      m00, m01, m02, m03,
+                        m10, m11, m12, m13,
+                       m20, m21, m22, m23,  // vars for temp result matrix 
+                        m30, m31, m32, m33;
+         
+            m00 = m1.m00*m2.m00 + m1.m10*m2.m01 + m1.m20*m2.m02 + m1.m30*m2.m03;
+            m01 = m1.m00*m2.m10 + m1.m10*m2.m11 + m1.m20*m2.m12 + m1.m30*m2.m13;
+            m02 = m1.m00*m2.m20 + m1.m10*m2.m21 + m1.m20*m2.m22 + m1.m30*m2.m23;
+            m03 = m1.m00*m2.m30 + m1.m10*m2.m31 + m1.m20*m2.m32 + m1.m30*m2.m33;
+            m10 = m1.m01*m2.m00 + m1.m11*m2.m01 + m1.m21*m2.m02 + m1.m31*m2.m03;
+            m11 = m1.m01*m2.m10 + m1.m11*m2.m11 + m1.m21*m2.m12 + m1.m31*m2.m13;
+            m12 = m1.m01*m2.m20 + m1.m11*m2.m21 + m1.m21*m2.m22 + m1.m31*m2.m23;
+            m13 = m1.m01*m2.m30 + m1.m11*m2.m31 + m1.m21*m2.m32 + m1.m31*m2.m33;
+            m20 = m1.m02*m2.m00 + m1.m12*m2.m01 + m1.m22*m2.m02 + m1.m32*m2.m03;
+            m21 = m1.m02*m2.m10 + m1.m12*m2.m11 + m1.m22*m2.m12 + m1.m32*m2.m13;
+            m22 = m1.m02*m2.m20 + m1.m12*m2.m21 + m1.m22*m2.m22 + m1.m32*m2.m23;
+            m23 = m1.m02*m2.m30 + m1.m12*m2.m31 + m1.m22*m2.m32 + m1.m32*m2.m33;
+            m30 = m1.m03*m2.m00 + m1.m13*m2.m01 + m1.m23*m2.m02 + m1.m33*m2.m03;
+            m31 = m1.m03*m2.m10 + m1.m13*m2.m11 + m1.m23*m2.m12 + m1.m33*m2.m13;
+            m32 = m1.m03*m2.m20 + m1.m13*m2.m21 + m1.m23*m2.m22 + m1.m33*m2.m23;
+            m33 = m1.m03*m2.m30 + m1.m13*m2.m31 + m1.m23*m2.m32 + m1.m33*m2.m33;
+            this.m00 = m00; this.m01 = m01; this.m02 = m02; this.m03 = m03;
+            this.m10 = m10; this.m11 = m11; this.m12 = m12; this.m13 = m13;
+            this.m20 = m20; this.m21 = m21; this.m22 = m22; this.m23 = m23;
+            this.m30 = m30; this.m31 = m31; this.m32 = m32; this.m33 = m33;
+        }
+    }
+
+   /**   
+     *  Multiplies matrix m1 times the transpose of matrix m2, and 
+     *  places the result into this. 
+     *  @param m1  the matrix on the left hand side of the multiplication 
+     *  @param m2  the matrix on the right hand side of the multiplication 
+     */  
+    public final void mulTransposeRight(Matrix4d m1, Matrix4d m2) 
+    {    
+    if (this != m1 && this != m2) {
+      this.m00 = m1.m00*m2.m00 + m1.m01*m2.m01 + m1.m02*m2.m02 + m1.m03*m2.m03;
+      this.m01 = m1.m00*m2.m10 + m1.m01*m2.m11 + m1.m02*m2.m12 + m1.m03*m2.m13;
+      this.m02 = m1.m00*m2.m20 + m1.m01*m2.m21 + m1.m02*m2.m22 + m1.m03*m2.m23;
+      this.m03 = m1.m00*m2.m30 + m1.m01*m2.m31 + m1.m02*m2.m32 + m1.m03*m2.m33;
+         
+      this.m10 = m1.m10*m2.m00 + m1.m11*m2.m01 + m1.m12*m2.m02 + m1.m13*m2.m03;
+      this.m11 = m1.m10*m2.m10 + m1.m11*m2.m11 + m1.m12*m2.m12 + m1.m13*m2.m13;
+      this.m12 = m1.m10*m2.m20 + m1.m11*m2.m21 + m1.m12*m2.m22 + m1.m13*m2.m23;
+      this.m13 = m1.m10*m2.m30 + m1.m11*m2.m31 + m1.m12*m2.m32 + m1.m13*m2.m33;
+
+      this.m20 = m1.m20*m2.m00 + m1.m21*m2.m01 + m1.m22*m2.m02 + m1.m23*m2.m03;
+      this.m21 = m1.m20*m2.m10 + m1.m21*m2.m11 + m1.m22*m2.m12 + m1.m23*m2.m13;
+      this.m22 = m1.m20*m2.m20 + m1.m21*m2.m21 + m1.m22*m2.m22 + m1.m23*m2.m23;
+      this.m23 = m1.m20*m2.m30 + m1.m21*m2.m31 + m1.m22*m2.m32 + m1.m23*m2.m33;
+
+      this.m30 = m1.m30*m2.m00 + m1.m31*m2.m01 + m1.m32*m2.m02 + m1.m33*m2.m03;
+      this.m31 = m1.m30*m2.m10 + m1.m31*m2.m11 + m1.m32*m2.m12 + m1.m33*m2.m13;
+      this.m32 = m1.m30*m2.m20 + m1.m31*m2.m21 + m1.m32*m2.m22 + m1.m33*m2.m23;
+      this.m33 = m1.m30*m2.m30 + m1.m31*m2.m31 + m1.m32*m2.m32 + m1.m33*m2.m33;
+    } else {
+            double      m00, m01, m02, m03,
+                        m10, m11, m12, m13,
+                       m20, m21, m22, m23,  // vars for temp result matrix
+                        m30, m31, m32, m33;
+
+      m00 = m1.m00*m2.m00 + m1.m01*m2.m01 + m1.m02*m2.m02 + m1.m03*m2.m03;
+      m01 = m1.m00*m2.m10 + m1.m01*m2.m11 + m1.m02*m2.m12 + m1.m03*m2.m13;
+      m02 = m1.m00*m2.m20 + m1.m01*m2.m21 + m1.m02*m2.m22 + m1.m03*m2.m23;
+      m03 = m1.m00*m2.m30 + m1.m01*m2.m31 + m1.m02*m2.m32 + m1.m03*m2.m33;
+
+      m10 = m1.m10*m2.m00 + m1.m11*m2.m01 + m1.m12*m2.m02 + m1.m13*m2.m03;
+      m11 = m1.m10*m2.m10 + m1.m11*m2.m11 + m1.m12*m2.m12 + m1.m13*m2.m13;
+      m12 = m1.m10*m2.m20 + m1.m11*m2.m21 + m1.m12*m2.m22 + m1.m13*m2.m23;
+      m13 = m1.m10*m2.m30 + m1.m11*m2.m31 + m1.m12*m2.m32 + m1.m13*m2.m33;
+
+      m20 = m1.m20*m2.m00 + m1.m21*m2.m01 + m1.m22*m2.m02 + m1.m23*m2.m03;
+      m21 = m1.m20*m2.m10 + m1.m21*m2.m11 + m1.m22*m2.m12 + m1.m23*m2.m13;
+      m22 = m1.m20*m2.m20 + m1.m21*m2.m21 + m1.m22*m2.m22 + m1.m23*m2.m23;
+      m23 = m1.m20*m2.m30 + m1.m21*m2.m31 + m1.m22*m2.m32 + m1.m23*m2.m33;
+
+      m30 = m1.m30*m2.m00 + m1.m31*m2.m01 + m1.m32*m2.m02 + m1.m33*m2.m03;
+      m31 = m1.m30*m2.m10 + m1.m31*m2.m11 + m1.m32*m2.m12 + m1.m33*m2.m13;
+      m32 = m1.m30*m2.m20 + m1.m31*m2.m21 + m1.m32*m2.m22 + m1.m33*m2.m23;
+      m33 = m1.m30*m2.m30 + m1.m31*m2.m31 + m1.m32*m2.m32 + m1.m33*m2.m33;
+
+      this.m00 = m00; this.m01 = m01; this.m02 = m02; this.m03 = m03;
+      this.m10 = m10; this.m11 = m11; this.m12 = m12; this.m13 = m13;
+      this.m20 = m20; this.m21 = m21; this.m22 = m22; this.m23 = m23;
+      this.m30 = m30; this.m31 = m31; this.m32 = m32; this.m33 = m33;
+    }
+}
+  
+  
+   /**    
+     *  Multiplies the transpose of matrix m1 times matrix m2, and 
+     *  places the result into this. 
+     *  @param m1  the matrix on the left hand side of the multiplication 
+     *  @param m2  the matrix on the right hand side of the multiplication 
+     */  
+    public final void mulTransposeLeft(Matrix4d m1, Matrix4d m2) 
+    {
+    if (this != m1 && this != m2) {
+      this.m00 = m1.m00*m2.m00 + m1.m10*m2.m10 + m1.m20*m2.m20 + m1.m30*m2.m30;
+      this.m01 = m1.m00*m2.m01 + m1.m10*m2.m11 + m1.m20*m2.m21 + m1.m30*m2.m31;
+      this.m02 = m1.m00*m2.m02 + m1.m10*m2.m12 + m1.m20*m2.m22 + m1.m30*m2.m32;
+      this.m03 = m1.m00*m2.m03 + m1.m10*m2.m13 + m1.m20*m2.m23 + m1.m30*m2.m33;
+                  
+      this.m10 = m1.m01*m2.m00 + m1.m11*m2.m10 + m1.m21*m2.m20 + m1.m31*m2.m30;
+      this.m11 = m1.m01*m2.m01 + m1.m11*m2.m11 + m1.m21*m2.m21 + m1.m31*m2.m31;
+      this.m12 = m1.m01*m2.m02 + m1.m11*m2.m12 + m1.m21*m2.m22 + m1.m31*m2.m32;
+      this.m13 = m1.m01*m2.m03 + m1.m11*m2.m13 + m1.m21*m2.m23 + m1.m31*m2.m33;
+                  
+      this.m20 = m1.m02*m2.m00 + m1.m12*m2.m10 + m1.m22*m2.m20 + m1.m32*m2.m30;
+      this.m21 = m1.m02*m2.m01 + m1.m12*m2.m11 + m1.m22*m2.m21 + m1.m32*m2.m31;
+      this.m22 = m1.m02*m2.m02 + m1.m12*m2.m12 + m1.m22*m2.m22 + m1.m32*m2.m32;
+      this.m23 = m1.m02*m2.m03 + m1.m12*m2.m13 + m1.m22*m2.m23 + m1.m32*m2.m33;
+                  
+      this.m30 = m1.m03*m2.m00 + m1.m13*m2.m10 + m1.m23*m2.m20 + m1.m33*m2.m30;
+      this.m31 = m1.m03*m2.m01 + m1.m13*m2.m11 + m1.m23*m2.m21 + m1.m33*m2.m31;
+      this.m32 = m1.m03*m2.m02 + m1.m13*m2.m12 + m1.m23*m2.m22 + m1.m33*m2.m32;
+      this.m33 = m1.m03*m2.m03 + m1.m13*m2.m13 + m1.m23*m2.m23 + m1.m33*m2.m33;
+    } else {
+            double      m00, m01, m02, m03,
+                        m10, m11, m12, m13,
+                       m20, m21, m22, m23,  // vars for temp result matrix
+                        m30, m31, m32, m33;
+              
+
+      m00 = m1.m00*m2.m00 + m1.m10*m2.m10 + m1.m20*m2.m20 + m1.m30*m2.m30;
+      m01 = m1.m00*m2.m01 + m1.m10*m2.m11 + m1.m20*m2.m21 + m1.m30*m2.m31;
+      m02 = m1.m00*m2.m02 + m1.m10*m2.m12 + m1.m20*m2.m22 + m1.m30*m2.m32;
+      m03 = m1.m00*m2.m03 + m1.m10*m2.m13 + m1.m20*m2.m23 + m1.m30*m2.m33;
+               
+      m10 = m1.m01*m2.m00 + m1.m11*m2.m10 + m1.m21*m2.m20 + m1.m31*m2.m30;
+      m11 = m1.m01*m2.m01 + m1.m11*m2.m11 + m1.m21*m2.m21 + m1.m31*m2.m31;
+      m12 = m1.m01*m2.m02 + m1.m11*m2.m12 + m1.m21*m2.m22 + m1.m31*m2.m32;
+      m13 = m1.m01*m2.m03 + m1.m11*m2.m13 + m1.m21*m2.m23 + m1.m31*m2.m33;
+               
+      m20 = m1.m02*m2.m00 + m1.m12*m2.m10 + m1.m22*m2.m20 + m1.m32*m2.m30;
+      m21 = m1.m02*m2.m01 + m1.m12*m2.m11 + m1.m22*m2.m21 + m1.m32*m2.m31;
+      m22 = m1.m02*m2.m02 + m1.m12*m2.m12 + m1.m22*m2.m22 + m1.m32*m2.m32;
+      m23 = m1.m02*m2.m03 + m1.m12*m2.m13 + m1.m22*m2.m23 + m1.m32*m2.m33;
+               
+      m30 = m1.m03*m2.m00 + m1.m13*m2.m10 + m1.m23*m2.m20 + m1.m33*m2.m30;
+      m31 = m1.m03*m2.m01 + m1.m13*m2.m11 + m1.m23*m2.m21 + m1.m33*m2.m31;
+      m32 = m1.m03*m2.m02 + m1.m13*m2.m12 + m1.m23*m2.m22 + m1.m33*m2.m32;
+      m33 = m1.m03*m2.m03 + m1.m13*m2.m13 + m1.m23*m2.m23 + m1.m33*m2.m33;
+
+      this.m00 = m00; this.m01 = m01; this.m02 = m02; this.m03 = m03;
+      this.m10 = m10; this.m11 = m11; this.m12 = m12; this.m13 = m13;
+      this.m20 = m20; this.m21 = m21; this.m22 = m22; this.m23 = m23;
+      this.m30 = m30; this.m31 = m31; this.m32 = m32; this.m33 = m33;
+    }
+
+    }
+    
+  
+   /**
+     * Returns true if all of the data members of Matrix4d m1 are
+     * equal to the corresponding data members in this Matrix4d.
+     * @param m1  the matrix with which the comparison is made
+     * @return  true or false
+     */
+    public boolean equals(Matrix4d m1)
+    {
+      try {
+        return(this.m00 == m1.m00 && this.m01 == m1.m01 && this.m02 == m1.m02
+            && this.m03 == m1.m03 && this.m10 == m1.m10 && this.m11 == m1.m11
+            && this.m12 == m1.m12 && this.m13 == m1.m13 && this.m20 == m1.m20
+            && this.m21 == m1.m21 && this.m22 == m1.m22 && this.m23 == m1.m23
+            && this.m30 == m1.m30 && this.m31 == m1.m31 && this.m32 == m1.m32
+            && this.m33 == m1.m33);
+      }  
+      catch (NullPointerException e2) { return false; }
+
+    }
+
+   /**
+     * Returns true if the Object t1 is of type Matrix4d and all of the
+     * data members of t1 are equal to the corresponding data members in
+     * this Matrix4d.
+     * @param t1  the matrix with which the comparison is made
+     * @return  true or false
+     */  
+    public boolean equals(Object t1)
+    {
+        try {    
+           Matrix4d m2 = (Matrix4d) t1;
+           return(this.m00 == m2.m00 && this.m01 == m2.m01 && this.m02 == m2.m02
+             && this.m03 == m2.m03 && this.m10 == m2.m10 && this.m11 == m2.m11
+             && this.m12 == m2.m12 && this.m13 == m2.m13 && this.m20 == m2.m20
+             && this.m21 == m2.m21 && this.m22 == m2.m22 && this.m23 == m2.m23
+             && this.m30 == m2.m30 && this.m31 == m2.m31 && this.m32 == m2.m32
+             && this.m33 == m2.m33);
+        }
+        catch (ClassCastException   e1) { return false; } 
+        catch (NullPointerException e2) { return false; }
+    }
+
+    /**   
+     * @deprecated Use epsilonEquals(Matrix4d,double) instead
+     */   
+    public boolean epsilonEquals(Matrix4d m1, float epsilon) {
+       return epsilonEquals(m1, (double)epsilon);
+    }
+
+    /**   
+     * Returns true if the L-infinite distance between this matrix 
+     * and matrix m1 is less than or equal to the epsilon parameter, 
+     * otherwise returns false.  The L-infinite 
+     * distance is equal to  
+     * MAX[i=0,1,2,3 ; j=0,1,2,3 ; abs(this.m(i,j) - m1.m(i,j)] 
+     * @param m1  the matrix to be compared to this matrix 
+     * @param epsilon  the threshold value   
+     */   
+    public boolean epsilonEquals(Matrix4d m1, double epsilon) { 
+       double diff;
+
+       diff = m00 - m1.m00;
+       if((diff<0?-diff:diff) > epsilon) return false;
+
+       diff = m01 - m1.m01;
+       if((diff<0?-diff:diff) > epsilon) return false;
+
+       diff = m02 - m1.m02;
+       if((diff<0?-diff:diff) > epsilon) return false;
+
+       diff = m03 - m1.m03;
+       if((diff<0?-diff:diff) > epsilon) return false;
+
+       diff = m10 - m1.m10;
+       if((diff<0?-diff:diff) > epsilon) return false;
+
+       diff = m11 - m1.m11;
+       if((diff<0?-diff:diff) > epsilon) return false;
+
+       diff = m12 - m1.m12;
+       if((diff<0?-diff:diff) > epsilon) return false;
+
+       diff = m13 - m1.m13;
+       if((diff<0?-diff:diff) > epsilon) return false;
+
+       diff = m20 - m1.m20;
+       if((diff<0?-diff:diff) > epsilon) return false;
+
+       diff = m21 - m1.m21;
+       if((diff<0?-diff:diff) > epsilon) return false;
+
+       diff = m22 - m1.m22;
+       if((diff<0?-diff:diff) > epsilon) return false;
+
+       diff = m23 - m1.m23;
+       if((diff<0?-diff:diff) > epsilon) return false;
+
+       diff = m30 - m1.m30;
+       if((diff<0?-diff:diff) > epsilon) return false;
+
+       diff = m31 - m1.m31;
+       if((diff<0?-diff:diff) > epsilon) return false;
+
+       diff = m32 - m1.m32;
+       if((diff<0?-diff:diff) > epsilon) return false;
+
+       diff = m33 - m1.m33;
+       if((diff<0?-diff:diff) > epsilon) return false;
+
+       return true;
+    } 
+
+    /**
+     * Returns a hash code value based on the data values in this
+     * object.  Two different Matrix4d objects with identical data values
+     * (i.e., Matrix4d.equals returns true) will return the same hash
+     * code value.  Two objects with different data members may return the
+     * same hash value, although this is not likely.
+     * @return the integer hash code value
+     */  
+    public int hashCode() {
+       long bits = 1L;
+       bits = 31L * bits + VecMathUtil.doubleToLongBits(m00);
+       bits = 31L * bits + VecMathUtil.doubleToLongBits(m01);
+       bits = 31L * bits + VecMathUtil.doubleToLongBits(m02);
+       bits = 31L * bits + VecMathUtil.doubleToLongBits(m03);
+       bits = 31L * bits + VecMathUtil.doubleToLongBits(m10);
+       bits = 31L * bits + VecMathUtil.doubleToLongBits(m11);
+       bits = 31L * bits + VecMathUtil.doubleToLongBits(m12);
+       bits = 31L * bits + VecMathUtil.doubleToLongBits(m13);
+       bits = 31L * bits + VecMathUtil.doubleToLongBits(m20);
+       bits = 31L * bits + VecMathUtil.doubleToLongBits(m21);
+       bits = 31L * bits + VecMathUtil.doubleToLongBits(m22);
+       bits = 31L * bits + VecMathUtil.doubleToLongBits(m23);
+       bits = 31L * bits + VecMathUtil.doubleToLongBits(m30);
+       bits = 31L * bits + VecMathUtil.doubleToLongBits(m31);
+       bits = 31L * bits + VecMathUtil.doubleToLongBits(m32);
+       bits = 31L * bits + VecMathUtil.doubleToLongBits(m33);
+       return (int) (bits ^ (bits >> 32));
+    }
+
+
+  /**
+   * Transform the vector vec using this Matrix4d and place the
+   * result into vecOut.
+   * @param vec  the double precision vector to be transformed
+   * @param vecOut  the vector into which the transformed values are placed
+   */
+    public final void transform(Tuple4d vec, Tuple4d vecOut)
+    {
+           double x,y,z,w;
+           x = (m00*vec.x + m01*vec.y
+                  + m02*vec.z + m03*vec.w);
+           y = (m10*vec.x + m11*vec.y
+                   + m12*vec.z + m13*vec.w);
+           z = (m20*vec.x + m21*vec.y
+                     + m22*vec.z + m23*vec.w);
+           vecOut.w = (m30*vec.x + m31*vec.y
+                      + m32*vec.z + m33*vec.w);
+           vecOut.x = x;
+           vecOut.y = y;
+           vecOut.z = z;
+    }
+
+  /**
+   * Transform the vector vec using this Matrix4d and place the
+   * result back into vec.
+   * @param vec  the double precision vector to be transformed
+   */
+    public final void transform(Tuple4d vec)
+    {
+         double x,y,z;
+
+           x = (m00*vec.x + m01*vec.y
+                     + m02*vec.z + m03*vec.w);
+           y = (m10*vec.x + m11*vec.y
+                     + m12*vec.z + m13*vec.w);
+           z = (m20*vec.x + m21*vec.y
+                     + m22*vec.z + m23*vec.w);
+           vec.w = (m30*vec.x + m31*vec.y
+                      + m32*vec.z + m33*vec.w);
+           vec.x = x;
+           vec.y = y;
+           vec.z = z;
+    }
+
+  /**
+   * Transform the vector vec using this Matrix4d and place the
+   * result into vecOut.
+   * @param vec  the single precision vector to be transformed
+   * @param vecOut  the vector into which the transformed values are placed
+   */
+    public final void transform(Tuple4f vec, Tuple4f vecOut)
+    {
+        float x,y,z;
+           x = (float) (m00*vec.x + m01*vec.y
+                     + m02*vec.z + m03*vec.w);
+           y = (float) (m10*vec.x + m11*vec.y
+                     + m12*vec.z + m13*vec.w);
+           z = (float) (m20*vec.x + m21*vec.y
+                     + m22*vec.z + m23*vec.w);
+           vecOut.w = (float) (m30*vec.x + m31*vec.y
+                      + m32*vec.z + m33*vec.w);
+           vecOut.x = x;
+           vecOut.y = y;
+           vecOut.z = z;
+    }
+
+  /**
+   * Transform the vector vec using this Transform and place the
+   * result back into vec.
+   * @param vec  the single precision vector to be transformed
+   */
+    public final void transform(Tuple4f vec)
+    {
+         float x,y,z;
+
+           x = (float) (m00*vec.x + m01*vec.y
+                     + m02*vec.z + m03*vec.w);
+           y = (float) (m10*vec.x + m11*vec.y
+                     + m12*vec.z + m13*vec.w);
+           z = (float) (m20*vec.x + m21*vec.y
+                     + m22*vec.z + m23*vec.w);
+           vec.w = (float) (m30*vec.x + m31*vec.y
+                      + m32*vec.z + m33*vec.w);
+           vec.x = x;
+           vec.y = y;
+           vec.z = z;
+    }
+
+  /**
+   * Transforms the point parameter with this Matrix4d and
+   * places the result into pointOut.  The fourth element of the
+   * point input parameter is assumed to be one.
+   * @param point  the input point to be transformed.
+   * @param pointOut  the transformed point
+   */
+    public final void transform(Point3d point, Point3d pointOut)
+    {
+        double x,y;
+        x = m00*point.x + m01*point.y + m02*point.z + m03;
+        y = m10*point.x + m11*point.y + m12*point.z + m13;
+        pointOut.z = m20*point.x + m21*point.y + m22*point.z + m23;
+        pointOut.x = x;
+        pointOut.y = y;
+
+    }
+  /**
+   * Transforms the point parameter with this Matrix4d and
+   * places the result back into point.  The fourth element of the
+   * point input parameter is assumed to be one.
+   * @param point  the input point to be transformed.
+   */
+    public final void transform(Point3d point)
+    {
+        double x, y;
+        x = m00*point.x + m01*point.y + m02*point.z + m03;
+        y = m10*point.x + m11*point.y + m12*point.z + m13;
+        point.z =  m20*point.x + m21*point.y + m22*point.z + m23;
+        point.x = x;
+        point.y = y;
+    }
+
+  /**
+   * Transforms the point parameter with this Matrix4d and
+   * places the result into pointOut.  The fourth element of the
+   * point input parameter is assumed to be one.
+   * @param point  the input point to be transformed.
+   * @param pointOut  the transformed point
+   */
+    public final void transform(Point3f point, Point3f pointOut)
+    {
+        float x,y;
+
+        x = (float) (m00*point.x + m01*point.y + m02*point.z + m03);
+        y = (float) (m10*point.x + m11*point.y + m12*point.z + m13);
+        pointOut.z = (float) (m20*point.x + m21*point.y + m22*point.z + m23);
+        pointOut.x = x;
+        pointOut.y = y;
+    }
+  /**
+   * Transforms the point parameter with this Matrix4d and
+   * places the result back into point.  The fourth element of the
+   * point input parameter is assumed to be one.
+   * @param point  the input point to be transformed.
+   */
+    public final void transform(Point3f point)
+    {
+        float  x, y;
+        x = (float) (m00*point.x + m01*point.y + m02*point.z + m03);
+        y = (float) (m10*point.x + m11*point.y + m12*point.z + m13);
+        point.z =  (float) (m20*point.x + m21*point.y + m22*point.z + m23);
+        point.x = x;
+        point.y = y;
+    }
+
+  /**
+   * Transforms the normal parameter by this Matrix4d and places the value
+   * into normalOut.  The fourth element of the normal is assumed to be zero.
+   * @param normal   the input normal to be transformed.
+   * @param normalOut  the transformed normal
+   */
+    public final void transform(Vector3d normal, Vector3d normalOut)
+    {
+        double x,y;
+        x =  m00*normal.x + m01*normal.y + m02*normal.z;
+        y =  m10*normal.x + m11*normal.y + m12*normal.z;
+        normalOut.z =  m20*normal.x + m21*normal.y + m22*normal.z;
+        normalOut.x = x;
+        normalOut.y = y;
+    }
+  /**
+   * Transforms the normal parameter by this transform and places the value
+   * back into normal.  The fourth element of the normal is assumed to be zero.
+   * @param normal   the input normal to be transformed.
+   */
+    public final void transform(Vector3d normal)
+    {
+        double x, y;
+
+        x =  m00*normal.x + m01*normal.y + m02*normal.z;
+        y =  m10*normal.x + m11*normal.y + m12*normal.z;
+        normal.z =  m20*normal.x + m21*normal.y + m22*normal.z;
+        normal.x = x;
+        normal.y = y;
+    }
+
+  /**
+   * Transforms the normal parameter by this Matrix4d and places the value
+   * into normalOut.  The fourth element of the normal is assumed to be zero.
+   * @param normal   the input normal to be transformed.
+   * @param normalOut  the transformed normal
+   */
+    public final void transform(Vector3f normal, Vector3f normalOut)
+    {
+        float x,y;
+        x =  (float) (m00*normal.x + m01*normal.y + m02*normal.z);
+        y =  (float) (m10*normal.x + m11*normal.y + m12*normal.z);
+        normalOut.z =  (float) (m20*normal.x + m21*normal.y + m22*normal.z);
+        normalOut.x = x;
+        normalOut.y = y;
+    }
+      
+  /**
+   * Transforms the normal parameter by this transform and places the value
+   * back into normal.  The fourth element of the normal is assumed to be zero.
+   * @param normal   the input normal to be transformed.
+   */
+    public final void transform(Vector3f normal)
+    {
+        float x, y;
+        x =  (float) (m00*normal.x + m01*normal.y + m02*normal.z);
+        y =  (float) (m10*normal.x + m11*normal.y + m12*normal.z);
+        normal.z =  (float) (m20*normal.x + m21*normal.y + m22*normal.z);
+        normal.x = x;
+        normal.y = y;
+    }
+
+   /**
+     * Sets the rotational component (upper 3x3) of this matrix to the
+     * matrix values in the double precision Matrix3d argument; the other
+     * elements of this matrix are unchanged; a singular value
+     * decomposition is performed on this object's upper 3x3 matrix to
+     * factor out the scale, then this object's upper 3x3 matrix components
+     * are replaced by the passed rotation components,
+     * and then the scale is reapplied to the rotational components.
+     * @param m1   double precision 3x3 matrix
+     */  
+    public final void setRotation( Matrix3d m1){ 
+       double[]    tmp_rot = new double[9];  // scratch matrix
+       double[]    tmp_scale = new double[3];  // scratch matrix
+  
+       getScaleRotate( tmp_scale, tmp_rot );
+
+       m00 = m1.m00*tmp_scale[0];
+       m01 = m1.m01*tmp_scale[1];
+       m02 = m1.m02*tmp_scale[2];
+
+       m10 = m1.m10*tmp_scale[0];
+       m11 = m1.m11*tmp_scale[1];
+       m12 = m1.m12*tmp_scale[2];
+
+       m20 = m1.m20*tmp_scale[0];
+       m21 = m1.m21*tmp_scale[1];
+       m22 = m1.m22*tmp_scale[2];
+
+    } 
+   /**
+     * Sets the rotational component (upper 3x3) of this matrix to the
+     * matrix values in the single precision Matrix3f argument; the other
+     * elements of this matrix are unchanged; a singular value
+     * decomposition is performed on this object's upper 3x3 matrix to
+     * factor out the scale, then this object's upper 3x3 matrix components
+     * are replaced by the passed rotation components,
+     * and then the scale is reapplied to the rotational components.
+     * @param m1   single precision 3x3 matrix
+     */  
+   public final void setRotation( Matrix3f m1)  
+   {  
+
+       double[]    tmp_rot = new double[9];  // scratch matrix
+       double[]    tmp_scale = new double[3];  // scratch matrix
+       getScaleRotate( tmp_scale, tmp_rot );
+
+        m00 = m1.m00*tmp_scale[0];
+        m01 = m1.m01*tmp_scale[1];
+        m02 = m1.m02*tmp_scale[2];
+
+        m10 = m1.m10*tmp_scale[0];
+        m11 = m1.m11*tmp_scale[1];
+        m12 = m1.m12*tmp_scale[2];
+
+        m20 = m1.m20*tmp_scale[0];
+        m21 = m1.m21*tmp_scale[1];
+        m22 = m1.m22*tmp_scale[2];
+   }  
+
+   /**
+     * Sets the rotational component (upper 3x3) of this matrix to the
+     * matrix equivalent values of the quaternion argument; the other
+     * elements of this matrix are unchanged; a singular value
+     * decomposition is performed on this object's upper 3x3 matrix to
+     * factor out the scale, then this object's upper 3x3 matrix components
+     * are replaced by the matrix equivalent of the quaternion,
+     * and then the scale is reapplied to the rotational components.
+     * @param q1    the quaternion that specifies the rotation
+     */  
+   public final void setRotation(Quat4f q1){
+       double[]    tmp_rot = new double[9];  // scratch matrix
+       double[]    tmp_scale = new double[3];  // scratch matrix
+       getScaleRotate( tmp_scale, tmp_rot );
+        m00 = (1.0 - 2.0f*q1.y*q1.y - 2.0f*q1.z*q1.z)*tmp_scale[0];
+        m10 = (2.0*(q1.x*q1.y + q1.w*q1.z))*tmp_scale[0]; 
+        m20 = (2.0*(q1.x*q1.z - q1.w*q1.y))*tmp_scale[0]; 
+  
+        m01 = (2.0*(q1.x*q1.y - q1.w*q1.z))*tmp_scale[1];
+        m11 = (1.0 - 2.0f*q1.x*q1.x - 2.0f*q1.z*q1.z)*tmp_scale[1]; 
+        m21 = (2.0*(q1.y*q1.z + q1.w*q1.x))*tmp_scale[1]; 
+        m02 = (2.0*(q1.x*q1.z + q1.w*q1.y))*tmp_scale[2];
+        m12 = (2.0*(q1.y*q1.z - q1.w*q1.x))*tmp_scale[2]; 
+        m22 = (1.0 - 2.0f*q1.x*q1.x - 2.0f*q1.y*q1.y)*tmp_scale[2]; 
+
+      }
+
+   /** 
+     * Sets the rotational component (upper 3x3) of this matrix to the 
+     * matrix equivalent values of the quaternion argument; the other 
+     * elements of this matrix are unchanged; a singular value 
+     * decomposition is performed on this object's upper 3x3 matrix to 
+     * factor out the scale, then this object's upper 3x3 matrix components
+     * are replaced by the matrix equivalent of the quaternion,
+     * and then the scale is reapplied to the rotational components. 
+     * @param q1    the quaternion that specifies the rotation 
+     */   
+   public final void setRotation(Quat4d q1){
+       
+       double[]    tmp_rot = new double[9];  // scratch matrix
+       double[]    tmp_scale = new double[3];  // scratch matrix
+       getScaleRotate( tmp_scale, tmp_rot );
+
+        m00 = (1.0 - 2.0f*q1.y*q1.y - 2.0f*q1.z*q1.z)*tmp_scale[0];
+        m10 = (2.0*(q1.x*q1.y + q1.w*q1.z))*tmp_scale[0];
+        m20 = (2.0*(q1.x*q1.z - q1.w*q1.y))*tmp_scale[0];
+        m01 = (2.0*(q1.x*q1.y - q1.w*q1.z))*tmp_scale[1];
+        m11 = (1.0 - 2.0f*q1.x*q1.x - 2.0f*q1.z*q1.z)*tmp_scale[1];
+        m21 = (2.0*(q1.y*q1.z + q1.w*q1.x))*tmp_scale[1];
+        m02 = (2.0*(q1.x*q1.z + q1.w*q1.y))*tmp_scale[2];
+        m12 = (2.0*(q1.y*q1.z - q1.w*q1.x))*tmp_scale[2];
+        m22 = (1.0 - 2.0f*q1.x*q1.x - 2.0f*q1.y*q1.y)*tmp_scale[2];
+      }
+
+   /**   
+     * Sets the rotational component (upper 3x3) of this matrix to the
+     * matrix equivalent values of the axis-angle argument; the other
+     * elements of this matrix are unchanged; a singular value
+     * decomposition is performed on this object's upper 3x3 matrix to
+     * factor out the scale, then this object's upper 3x3 matrix components
+     * are replaced by the matrix equivalent of the axis-angle,
+     * and then the scale is reapplied to the rotational components.
+     * @param a1 the axis-angle to be converted (x, y, z, angle)
+     */
+    public final void setRotation(AxisAngle4d a1)
+    {  
+       double[]    tmp_rot = new double[9];  // scratch matrix
+       double[]    tmp_scale = new double[3];  // scratch matrix
+       
+       getScaleRotate( tmp_scale, tmp_rot );
+
+        double mag = 1.0/Math.sqrt( a1.x*a1.x + a1.y*a1.y + a1.z*a1.z);
+        double ax = a1.x*mag;
+        double ay = a1.y*mag;
+        double az = a1.z*mag;
+
+        double sinTheta = Math.sin(a1.angle);
+        double cosTheta = Math.cos(a1.angle);
+        double t = 1.0 - cosTheta;
+
+        double xz = a1.x * a1.z;
+        double xy = a1.x * a1.y;
+        double yz = a1.y * a1.z;
+
+        m00 = (t * ax * ax + cosTheta)*tmp_scale[0];
+        m01 = (t * xy - sinTheta * az)*tmp_scale[1];
+        m02 = (t * xz + sinTheta * ay)*tmp_scale[2];
+
+        m10 = (t * xy + sinTheta * az)*tmp_scale[0];
+        m11 = (t * ay * ay + cosTheta)*tmp_scale[1];
+        m12 = (t * yz - sinTheta * ax)*tmp_scale[2];
+        m20 = (t * xz - sinTheta * ay)*tmp_scale[0];
+        m21 = (t * yz + sinTheta * ax)*tmp_scale[1];
+        m22 = (t * az * az + cosTheta)*tmp_scale[2];
+
+    }
+
+  /**
+    *  Sets this matrix to all zeros.
+    */
+   public final void setZero()
+   {
+        m00 = 0.0;
+        m01 = 0.0;
+        m02 = 0.0;
+        m03 = 0.0;
+        m10 = 0.0;
+        m11 = 0.0;
+        m12 = 0.0;
+        m13 = 0.0;
+        m20 = 0.0;
+        m21 = 0.0;
+        m22 = 0.0;
+        m23 = 0.0;
+        m30 = 0.0;
+        m31 = 0.0;
+        m32 = 0.0;
+        m33 = 0.0;
+   }
+
+   /**
+     * Negates the value of this matrix: this = -this.
+     */  
+    public final void negate()
+    {
+        m00 = -m00;
+        m01 = -m01;
+        m02 = -m02;
+        m03 = -m03;
+        m10 = -m10;
+        m11 = -m11;
+        m12 = -m12;
+        m13 = -m13;
+        m20 = -m20;
+        m21 = -m21;
+        m22 = -m22;
+        m23 = -m23;
+        m30 = -m30;
+        m31 = -m31;
+        m32 = -m32;
+        m33 = -m33;
+    }
+
+   /**
+     *  Sets the value of this matrix equal to the negation of
+     *  of the Matrix4d parameter.
+     *  @param m1  the source matrix
+     */  
+    public final void negate(Matrix4d m1)
+    {
+        this.m00 = -m1.m00; 
+        this.m01 = -m1.m01;
+        this.m02 = -m1.m02;
+        this.m03 = -m1.m03;
+        this.m10 = -m1.m10;
+        this.m11 = -m1.m11;
+        this.m12 = -m1.m12;
+        this.m13 = -m1.m13;
+        this.m20 = -m1.m20;
+        this.m21 = -m1.m21;
+        this.m22 = -m1.m22;
+        this.m23 = -m1.m23;
+        this.m30 = -m1.m30;
+        this.m31 = -m1.m31;
+        this.m32 = -m1.m32;
+        this.m33 = -m1.m33;
+    }
+    private final void getScaleRotate(double scales[], double rots[]) {
+       double[]    tmp = new double[9];  // scratch matrix
+       tmp[0] = m00;
+       tmp[1] = m01;
+       tmp[2] = m02;
+
+       tmp[3] = m10;
+       tmp[4] = m11;
+       tmp[5] = m12;
+
+       tmp[6] = m20;
+       tmp[7] = m21;
+       tmp[8] = m22;
+
+       Matrix3d.compute_svd( tmp, scales, rots);
+
+       return;
+    }
+
+    /**
+     * Creates a new object of the same class as this object.
+     *
+     * @return a clone of this instance.
+     * @exception OutOfMemoryError if there is not enough memory.
+     * @see java.lang.Cloneable
+     * @since vecmath 1.3
+     */
+    public Object clone() {
+       Matrix4d m1 = null;
+       try {
+           m1 = (Matrix4d)super.clone();
+       } catch (CloneNotSupportedException e) {
+           // this shouldn't happen, since we are Cloneable
+           throw new InternalError();
+       }
+
+       return m1;
+    }
+
+    /**
+        * Get the first matrix element in the first row.
+        * 
+        * @return Returns the m00.
+        * 
+        * @since vecmath 1.5
+        */
+       public final  double getM00() {
+               return m00;
+       }
+
+       /**
+        * Set the first matrix element in the first row.
+        * 
+        * @param m00 The m00 to set.
+        * 
+        * 
+        * @since vecmath 1.5
+        */
+       public final  void setM00(double m00) {
+               this.m00 = m00;
+       }
+
+       /**
+        * Get the second matrix element in the first row.
+        * 
+        * @return Returns the m01.
+        * 
+        * @since vecmath 1.5
+        */
+       public final  double getM01() {
+               return m01;
+       }
+
+       /**
+        * Set the second matrix element in the first row.
+        * 
+        * @param m01 The m01 to set.
+        * 
+        * @since vecmath 1.5
+        */
+       public  final void setM01(double m01) {
+               this.m01 = m01;
+       }
+
+       /**
+        * Get the third matrix element in the first row.
+        * 
+        * @return Returns the m02.
+        * 
+        * @since vecmath 1.5
+        */
+       public final double getM02() {
+               return m02;
+       }
+
+       /**
+        * Set the third matrix element in the first row.
+        * 
+        * @param m02 The m02 to set.
+        * 
+        * @since vecmath 1.5
+        */
+       public final  void setM02(double m02) {
+               this.m02 = m02;
+       }
+
+       /**
+        * Get first matrix element in the second row.
+        * 
+        * @return Returns the m10.
+        * 
+        * @since vecmath 1.5
+        */
+       public final  double getM10() {
+               return m10;
+       }
+
+       /**
+        * Set first matrix element in the second row.
+        * 
+        * @param m10 The m10 to set.
+        * 
+        * @since vecmath 1.5
+        */
+       public final  void setM10(double m10) {
+               this.m10 = m10;
+       }
+
+       /**
+        * Get second matrix element in the second row.
+        * 
+        * @return Returns the m11.
+        * 
+        * @since vecmath 1.5
+        */
+       public final  double getM11() {
+               return m11;
+       }
+
+       /**
+        * Set the second matrix element in the second row.
+        * 
+        * @param m11 The m11 to set.
+        * 
+        * @since vecmath 1.5
+        */
+       public final  void setM11(double m11) {
+               this.m11 = m11;
+       }
+
+       /**
+        * Get the third matrix element in the second row.
+        * 
+        * @return Returns the m12.
+        * 
+        * @since vecmath 1.5
+        */
+       public final  double getM12() {
+               return m12;
+       }
+
+       /**
+        * Set the third matrix element in the second row.
+        * 
+        * @param m12 The m12 to set.
+        * 
+        * 
+        * @since vecmath 1.5
+        */
+       public final  void setM12(double m12) {
+               this.m12 = m12;
+       }
+
+       /**
+        * Get the first matrix element in the third row.
+        * 
+        * @return Returns the m20.
+        * 
+        * @since vecmath 1.5
+        */
+       public final  double getM20() {
+               return m20;
+       }
+
+       /**
+        * Set the first matrix element in the third row.
+        * 
+        * @param m20 The m20 to set.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setM20(double m20) {
+               this.m20 = m20;
+       }
+
+       /**
+        * Get the second matrix element in the third row.
+        * 
+        * @return Returns the m21.
+        * 
+        * @since vecmath 1.5
+        */
+       public final double getM21() {
+               return m21;
+       }
+
+       /**
+        * Set the second matrix element in the third row.
+        * 
+        * @param m21 The m21 to set.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setM21(double m21) {
+               this.m21 = m21;
+       }
+
+       /**
+        * Get the third matrix element in the third row.
+        * 
+        * @return Returns the m22.
+        * 
+        * @since vecmath 1.5
+        */
+       public final double getM22() {
+               return m22;
+       }
+
+       /**
+        * Set the third matrix element in the third row.
+        * 
+        * @param m22 The m22 to set.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setM22(double m22) {
+               this.m22 = m22;
+       }
+
+       /**
+        * Get the fourth element of the first row.
+        * 
+        * @return Returns the m03.
+        * 
+        * @since vecmath 1.5
+        */
+       public final double getM03() {
+               return m03;
+       }
+
+       /**
+        * Set the fourth element of the first row.
+        * 
+        * @param m03 The m03 to set.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setM03(double m03) {
+               this.m03 = m03;
+       }
+
+       /**
+        * Get the fourth element of the second row.
+        * 
+        * @return Returns the m13.
+        * 
+        * @since vecmath 1.5
+        */
+       public final double getM13() {
+               return m13;
+       }
+
+       /**
+        * Set the fourth element of the second row.
+        * 
+        * @param m13 The m13 to set.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setM13(double m13) {
+               this.m13 = m13;
+       }
+
+       /**
+        * Get the fourth element of the third row.
+        * 
+        * @return Returns the m23.
+        * 
+        * @since vecmath 1.5
+        */
+       public final double getM23() {
+               return m23;
+       }
+
+       /**
+        * Set the fourth element of the third row.
+        * 
+        * @param m23 The m23 to set.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setM23(double m23) {
+               this.m23 = m23;
+       }
+
+       /**
+        * Get the first element of the fourth row.
+        * 
+        * @return Returns the m30.
+        * 
+        * @since vecmath 1.5
+        */
+       public final double getM30() {
+               return m30;
+       }
+
+       /**
+        * Set the first element of the fourth row.
+        * 
+        * @param m30 The m30 to set.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setM30(double m30) {
+               this.m30 = m30;
+       }
+
+       /**
+        * Get the second element of the fourth row.
+        * 
+        * @return Returns the m31.
+        * 
+        * @since vecmath 1.5
+        */
+       public final double getM31() {
+               return m31;
+       }
+
+       /**
+        * Set the second element of the fourth row.
+        * 
+        * @param m31 The m31 to set.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setM31(double m31) {
+               this.m31 = m31;
+       }
+
+       /**
+        * Get the third element of the fourth row.
+        *  
+        * @return Returns the m32.
+        * 
+        * 
+        * @since vecmath 1.5
+        */
+       public final double getM32() {
+               return m32;
+       }
+
+       /**
+        * Set the third element of the fourth row.
+        * 
+        * @param m32 The m32 to set.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setM32(double m32) {
+               this.m32 = m32;
+       }
+
+       /**
+        * Get the fourth element of the fourth row.
+        * 
+        * @return Returns the m33.
+        * 
+        * @since vecmath 1.5
+        */
+       public final double getM33() {
+               return m33;
+       }
+
+       /**
+        * Set the fourth element of the fourth row.
+        * 
+        * @param m33 The m33 to set.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setM33(double m33) {
+               this.m33 = m33;
+       }
+}
diff --git a/javax.vecmath/src/javax/vecmath/Matrix4f.java b/javax.vecmath/src/javax/vecmath/Matrix4f.java
new file mode 100644 (file)
index 0000000..0ba9952
--- /dev/null
@@ -0,0 +1,3617 @@
+/*
+ * $RCSfile: Matrix4f.java,v $
+ *
+ * Copyright 1996-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ * $Revision: 1.8 $
+ * $Date: 2008/02/28 20:18:50 $
+ * $State: Exp $
+ */
+
+package javax.vecmath;
+
+import java.lang.Math;
+
+/**
+ * A single precision floating point 4 by 4 matrix.
+ * Primarily to support 3D rotations.
+ *
+ */
+public class Matrix4f implements java.io.Serializable, Cloneable {
+
+    // Compatible with 1.1
+    static final long serialVersionUID = -8405036035410109353L;
+    /**
+     *  The first element of the first row.
+     */
+    public     float   m00;
+
+    /**
+     *  The second element of the first row.
+     */
+    public     float   m01;
+
+    /**
+     *  The third element of the first row.
+     */
+    public     float   m02;
+
+    /**
+     *  The fourth element of the first row.
+     */
+    public     float   m03;
+
+    /**
+     *  The first element of the second row.
+     */
+    public     float   m10;
+
+    /**
+     *  The second element of the second row.
+     */
+    public     float   m11;
+
+    /**
+     *  The third element of the second row.
+     */
+    public     float   m12;
+
+    /**
+     *  The fourth element of the second row.
+     */
+    public     float   m13;
+
+    /**
+     *  The first element of the third row.
+     */
+    public     float   m20;
+
+    /**
+     *  The second element of the third row.
+     */
+    public     float   m21;
+
+    /**
+     * The third element of the third row.
+     */
+    public     float   m22;
+
+    /**
+     * The fourth element of the third row.
+     */
+    public     float   m23;
+
+    /**
+     * The first element of the fourth row.
+     */
+    public     float   m30;
+
+    /**
+     * The second element of the fourth row.
+     */
+    public     float   m31;
+
+    /**
+     * The third element of the fourth row.
+     */
+    public     float   m32;
+
+    /**
+     * The fourth element of the fourth row.
+     */
+    public     float   m33;
+    /*
+    double[] tmp = new double[9];
+    double[] tmp_scale = new double[3];
+    double[] tmp_rot = new double[9];
+    */
+    private static final double EPS = 1.0E-8;
+
+    /**
+     * Constructs and initializes a Matrix4f from the specified 16 values.
+     * @param m00 the [0][0] element
+     * @param m01 the [0][1] element
+     * @param m02 the [0][2] element
+     * @param m03 the [0][3] element
+     * @param m10 the [1][0] element
+     * @param m11 the [1][1] element
+     * @param m12 the [1][2] element
+     * @param m13 the [1][3] element
+     * @param m20 the [2][0] element
+     * @param m21 the [2][1] element
+     * @param m22 the [2][2] element
+     * @param m23 the [2][3] element
+     * @param m30 the [3][0] element
+     * @param m31 the [3][1] element
+     * @param m32 the [3][2] element
+     * @param m33 the [3][3] element
+     */
+    public Matrix4f(float m00, float m01, float m02, float m03,
+                   float m10, float m11, float m12, float m13,
+                   float m20, float m21, float m22, float m23,
+                   float m30, float m31, float m32, float m33)
+    {
+       this.m00 = m00;
+       this.m01 = m01;
+       this.m02 = m02;
+       this.m03 = m03;
+
+       this.m10 = m10;
+       this.m11 = m11;
+       this.m12 = m12;
+       this.m13 = m13;
+
+       this.m20 = m20;
+       this.m21 = m21;
+       this.m22 = m22;
+       this.m23 = m23;
+
+       this.m30 = m30;
+       this.m31 = m31;
+       this.m32 = m32;
+       this.m33 = m33;
+        
+    }
+
+    /**
+     * Constructs and initializes a Matrix4f from the specified 16
+     * element array.  this.m00 =v[0], this.m01=v[1], etc.
+     * @param v the array of length 16 containing in order
+     */
+    public Matrix4f(float[] v)
+    {
+       this.m00 = v[ 0];
+       this.m01 = v[ 1];
+       this.m02 = v[ 2];
+       this.m03 = v[ 3];
+
+       this.m10 = v[ 4];
+       this.m11 = v[ 5];
+       this.m12 = v[ 6];
+       this.m13 = v[ 7];
+
+       this.m20 = v[ 8];
+       this.m21 = v[ 9];
+       this.m22 = v[10];
+       this.m23 = v[11];
+
+       this.m30 = v[12];
+       this.m31 = v[13];
+       this.m32 = v[14];
+       this.m33 = v[15];
+        
+    }
+
+   /**
+     * Constructs and initializes a Matrix4f from the quaternion,
+     * translation, and scale values; the scale is applied only to the
+     * rotational components of the matrix (upper 3x3) and not to the
+     * translational components.
+     * @param q1  the quaternion value representing the rotational component
+     * @param t1  the translational component of the matrix
+     * @param s   the scale value applied to the rotational components
+     */  
+    public Matrix4f(Quat4f q1, Vector3f t1, float s)
+    {
+        m00 = (float)(s*(1.0 - 2.0*q1.y*q1.y - 2.0*q1.z*q1.z));
+        m10 = (float)(s*(2.0*(q1.x*q1.y + q1.w*q1.z)));
+        m20 = (float)(s*(2.0*(q1.x*q1.z - q1.w*q1.y)));
+
+        m01 = (float)(s*(2.0*(q1.x*q1.y - q1.w*q1.z)));
+        m11 = (float)(s*(1.0 - 2.0*q1.x*q1.x - 2.0*q1.z*q1.z));
+        m21 = (float)(s*(2.0*(q1.y*q1.z + q1.w*q1.x)));
+
+        m02 = (float)(s*(2.0*(q1.x*q1.z + q1.w*q1.y)));
+        m12 = (float)(s*(2.0*(q1.y*q1.z - q1.w*q1.x)));
+        m22 = (float)(s*(1.0 - 2.0*q1.x*q1.x - 2.0*q1.y*q1.y));
+
+        m03 = t1.x;
+        m13 = t1.y;
+        m23 = t1.z;
+
+        m30 = 0.0f;
+        m31 = 0.0f;
+        m32 = 0.0f;
+        m33 = 1.0f;
+
+    }
+
+   /**
+     *  Constructs a new matrix with the same values as the 
+     *  Matrix4d parameter.
+     *  @param m1  the source matrix
+     */
+   public Matrix4f(Matrix4d m1)
+   {
+        this.m00 = (float)m1.m00;
+        this.m01 = (float)m1.m01;
+        this.m02 = (float)m1.m02;
+        this.m03 = (float)m1.m03;
+
+        this.m10 = (float)m1.m10;
+        this.m11 = (float)m1.m11;
+        this.m12 = (float)m1.m12;
+        this.m13 = (float)m1.m13;
+
+        this.m20 = (float)m1.m20;
+        this.m21 = (float)m1.m21;
+        this.m22 = (float)m1.m22;
+        this.m23 = (float)m1.m23;
+
+        this.m30 = (float)m1.m30;
+        this.m31 = (float)m1.m31;
+        this.m32 = (float)m1.m32;
+        this.m33 = (float)m1.m33;
+        
+   }
+   /**
+     *  Constructs a new matrix with the same values as the
+     *  Matrix4f parameter.
+     *  @param m1  the source matrix
+     */
+   public Matrix4f(Matrix4f m1)
+   {
+        this.m00 = m1.m00;
+        this.m01 = m1.m01;
+        this.m02 = m1.m02;
+        this.m03 = m1.m03;
+
+        this.m10 = m1.m10;
+        this.m11 = m1.m11;
+        this.m12 = m1.m12;
+        this.m13 = m1.m13;
+
+        this.m20 = m1.m20;
+        this.m21 = m1.m21;
+        this.m22 = m1.m22;
+        this.m23 = m1.m23;
+
+        this.m30 = m1.m30;
+        this.m31 = m1.m31;
+        this.m32 = m1.m32;
+        this.m33 = m1.m33;
+        
+   }
+
+   /**
+     * Constructs and initializes a Matrix4f from the rotation matrix,
+     * translation, and scale values; the scale is applied only to the
+     * rotational components of the matrix (upper 3x3) and not to the
+     * translational components of the matrix.
+     * @param m1  the rotation matrix representing the rotational components
+     * @param t1  the translational components of the matrix
+     * @param s   the scale value applied to the rotational components
+     */
+    public Matrix4f(Matrix3f m1, Vector3f t1, float s)
+    {
+        this.m00 = m1.m00*s;
+        this.m01 = m1.m01*s;
+        this.m02 = m1.m02*s;
+        this.m03 = t1.x;
+
+        this.m10 = m1.m10*s;
+        this.m11 = m1.m11*s;
+        this.m12 = m1.m12*s;
+        this.m13 = t1.y;
+
+        this.m20 = m1.m20*s;
+        this.m21 = m1.m21*s;
+        this.m22 = m1.m22*s;
+        this.m23 = t1.z;
+
+        this.m30 = 0.0f;
+        this.m31 = 0.0f;
+        this.m32 = 0.0f;
+        this.m33 = 1.0f;
+        
+    }
+    /**
+     * Constructs and initializes a Matrix4f to all zeros.
+     */
+    public Matrix4f()
+    {
+       this.m00 = (float) 0.0;
+       this.m01 = (float) 0.0;
+       this.m02 = (float) 0.0;
+       this.m03 = (float) 0.0;
+
+       this.m10 = (float) 0.0;
+       this.m11 = (float) 0.0;
+       this.m12 = (float) 0.0;
+       this.m13 = (float) 0.0;
+
+       this.m20 = (float) 0.0;
+       this.m21 = (float) 0.0;
+       this.m22 = (float) 0.0;
+       this.m23 = (float) 0.0;
+
+       this.m30 = (float) 0.0;
+       this.m31 = (float) 0.0;
+       this.m32 = (float) 0.0;
+       this.m33 = (float) 0.0;
+        
+    }
+
+   /**  
+     * Returns a string that contains the values of this Matrix4f.
+     * @return the String representation
+     */  
+    public String toString() {
+      return
+       this.m00 + ", " + this.m01 + ", " + this.m02 + ", " + this.m03 + "\n" +
+       this.m10 + ", " + this.m11 + ", " + this.m12 + ", " + this.m13 + "\n" +
+       this.m20 + ", " + this.m21 + ", " + this.m22 + ", " + this.m23 + "\n" +
+       this.m30 + ", " + this.m31 + ", " + this.m32 + ", " + this.m33 + "\n";
+    }
+
+    /**
+     * Sets this Matrix4f to identity.
+     */
+    public final void setIdentity()
+    {
+       this.m00 = (float) 1.0;
+       this.m01 = (float) 0.0;
+       this.m02 = (float) 0.0;
+       this.m03 = (float) 0.0;
+
+       this.m10 = (float) 0.0;
+       this.m11 = (float) 1.0;
+       this.m12 = (float) 0.0;
+       this.m13 = (float) 0.0;
+
+       this.m20 = (float) 0.0;
+       this.m21 = (float) 0.0;
+       this.m22 = (float) 1.0;
+       this.m23 = (float) 0.0;
+
+       this.m30 = (float) 0.0;
+       this.m31 = (float) 0.0;
+       this.m32 = (float) 0.0;
+       this.m33 = (float) 1.0;
+    }
+
+    /**
+     * Sets the specified element of this matrix4f to the value provided.
+     * @param row the row number to be modified (zero indexed)
+     * @param column the column number to be modified (zero indexed)
+     * @param value the new value
+     */
+    public final void setElement(int row, int column, float value)
+    {
+       switch (row) 
+         {
+         case 0:
+           switch(column)
+             {
+             case 0:
+               this.m00 = value;
+               break;
+             case 1:
+               this.m01 = value;
+               break;
+             case 2:
+               this.m02 = value;
+               break;
+             case 3:
+               this.m03 = value;
+               break;
+             default:
+               throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4f0"));
+             }
+           break;
+
+         case 1:
+           switch(column) 
+             {
+             case 0:
+               this.m10 = value;
+               break;
+             case 1:
+               this.m11 = value;
+               break;
+             case 2:
+               this.m12 = value;
+               break;
+             case 3:
+               this.m13 = value;
+               break;
+             default:
+               throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4f0"));
+             }
+           break;
+
+         case 2:
+           switch(column) 
+             {
+             case 0:
+               this.m20 = value;
+               break;
+             case 1:
+               this.m21 = value;
+               break;
+             case 2:
+               this.m22 = value;
+               break;
+             case 3:
+               this.m23 = value;
+               break;
+             default:
+               throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4f0"));
+             }
+           break;
+
+         case 3:
+           switch(column) 
+             {
+             case 0:
+               this.m30 = value;
+               break;
+             case 1:
+               this.m31 = value;
+               break;
+             case 2:
+               this.m32 = value;
+               break;
+             case 3:
+               this.m33 = value;
+               break;
+             default:
+               throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4f0"));
+             }
+           break;
+
+         default:
+               throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4f0"));
+         }
+    }
+
+    /**
+     * Retrieves the value at the specified row and column of this matrix.
+     * @param row the row number to be retrieved (zero indexed)
+     * @param column the column number to be retrieved (zero indexed)
+     * @return the value at the indexed element
+     */
+    public final float getElement(int row, int column)
+    {
+       switch (row) 
+         {
+         case 0:
+           switch(column)
+             {
+             case 0:
+               return(this.m00);
+             case 1:
+               return(this.m01);
+             case 2:
+               return(this.m02);
+             case 3:
+               return(this.m03);
+             default:
+               break;
+             }
+           break;
+         case 1:
+           switch(column) 
+             {
+             case 0:
+               return(this.m10);
+             case 1:
+               return(this.m11);
+             case 2:
+               return(this.m12);
+             case 3:
+               return(this.m13);
+             default:
+               break;
+             }
+           break;
+         
+         case 2:
+           switch(column) 
+             {
+             case 0:
+               return(this.m20);
+             case 1:
+               return(this.m21);
+             case 2:
+               return(this.m22);
+             case 3:
+               return(this.m23);
+             default:
+               break;
+             }
+           break;
+           
+         case 3:
+           switch(column) 
+             {
+             case 0:
+               return(this.m30);
+             case 1:
+               return(this.m31);
+             case 2:
+               return(this.m32);
+             case 3:
+               return(this.m33);
+             default:
+               break;
+             }
+           break;
+           
+         default:
+           break;
+         }
+       throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4f1"));
+    }
+
+    /**
+     * Copies the matrix values in the specified row into the vector parameter.
+     * @param row  the matrix row
+     * @param v    the vector into which the matrix row values will be copied
+     */  
+    public final void getRow(int row, Vector4f v) {
+        if( row == 0 ) {
+           v.x = m00;
+           v.y = m01;
+           v.z = m02;
+           v.w = m03;
+        } else if(row == 1) {
+           v.x = m10;
+           v.y = m11;
+           v.z = m12;
+           v.w = m13;
+        } else if(row == 2) {
+           v.x = m20;
+           v.y = m21;
+           v.z = m22;
+           v.w = m23;
+        } else if(row == 3) {
+           v.x = m30;
+           v.y = m31;
+           v.z = m32;
+           v.w = m33;
+        } else {
+          throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4f2"));
+        }
+
+    }
+
+    /**  
+     * Copies the matrix values in the specified row into the array parameter.
+     * @param row  the matrix row
+     * @param v    the array into which the matrix row values will be copied
+     */  
+    public final void getRow(int row, float v[]) {
+        if( row == 0 ) {
+           v[0] = m00;
+           v[1] = m01;
+           v[2] = m02;
+           v[3] = m03;
+        } else if(row == 1) {
+           v[0] = m10;
+           v[1] = m11;
+           v[2] = m12;
+           v[3] = m13;
+        } else if(row == 2) {
+           v[0] = m20;
+           v[1] = m21;
+           v[2] = m22;
+           v[3] = m23;
+        } else if(row == 3) {
+           v[0] = m30;
+           v[1] = m31;
+           v[2] = m32;
+           v[3] = m33;
+        } else {
+          throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4f2"));
+        }
+
+    }
+
+    /**  
+     * Copies the matrix values in the specified column into the vector
+     * parameter.
+     * @param column the matrix column
+     * @param v    the vector into which the matrix row values will be copied
+     */  
+    public final void getColumn(int column, Vector4f v) {
+        if( column == 0 ) {
+           v.x = m00;
+           v.y = m10;
+           v.z = m20;
+           v.w = m30;
+        } else if(column == 1) {
+           v.x = m01;
+           v.y = m11;
+           v.z = m21;
+           v.w = m31;
+        } else if(column == 2) {
+           v.x = m02;
+           v.y = m12;
+           v.z = m22;
+           v.w = m32;
+        } else if(column == 3) {
+           v.x = m03;
+           v.y = m13;
+           v.z = m23;
+           v.w = m33;
+        } else {
+          throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4f4"));
+        }
+
+    }
+
+    /**  
+     * Copies the matrix values in the specified column into the array
+     * parameter.
+     * @param column the matrix column
+     * @param v    the array into which the matrix row values will be copied
+     */ 
+    public final void getColumn(int column, float v[]) {
+        if( column == 0 ) {
+           v[0] = m00;
+           v[1] = m10;
+           v[2] = m20;
+           v[3] = m30;
+        } else if(column == 1) {
+           v[0] = m01;
+           v[1] = m11;
+           v[2] = m21;
+           v[3] = m31;
+        } else if(column == 2) {
+           v[0] = m02;
+           v[1] = m12;
+           v[2] = m22;
+           v[3] = m32;
+        } else if(column == 3) {
+           v[0] = m03;
+           v[1] = m13;
+           v[2] = m23;
+           v[3] = m33;
+        } else {
+          throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4f4"));
+        }
+
+    }
+
+   /** 
+     * Sets the scale component of the current matrix by factoring 
+     * out the current scale (by doing an SVD) from the rotational 
+     * component and multiplying by the new scale. 
+     * @param scale  the new scale amount 
+     */
+    public final void setScale(float scale){
+       
+       double[]    tmp_rot = new double[9];  // scratch matrix
+       double[]    tmp_scale = new double[3];  // scratch matrix
+       getScaleRotate( tmp_scale, tmp_rot );
+
+        m00 = (float)(tmp_rot[0]*scale);
+        m01 = (float)(tmp_rot[1]*scale);
+        m02 = (float)(tmp_rot[2]*scale);
+
+        m10 = (float)(tmp_rot[3]*scale);
+        m11 = (float)(tmp_rot[4]*scale);
+        m12 = (float)(tmp_rot[5]*scale);
+
+        m20 = (float)(tmp_rot[6]*scale);
+        m21 = (float)(tmp_rot[7]*scale);
+        m22 = (float)(tmp_rot[8]*scale);
+
+    }
+
+    /**
+     * Performs an SVD normalization of this matrix in order to acquire
+     * the normalized rotational component; the values are placed into
+     * the Matrix3d parameter.
+     * @param m1 matrix into which the rotational component is placed
+     */  
+    public final void get(Matrix3d m1){
+
+       double[]    tmp_rot = new double[9];  // scratch matrix
+       double[]    tmp_scale = new double[3];  // scratch matrix
+       
+        getScaleRotate( tmp_scale, tmp_rot );
+
+        m1.m00 = tmp_rot[0];
+        m1.m01 = tmp_rot[1];
+        m1.m02 = tmp_rot[2];
+
+        m1.m10 = tmp_rot[3];
+        m1.m11 = tmp_rot[4];
+        m1.m12 = tmp_rot[5];
+
+        m1.m20 = tmp_rot[6];
+        m1.m21 = tmp_rot[7];
+        m1.m22 = tmp_rot[8];
+
+    }
+
+    /**
+     * Performs an SVD normalization of this matrix in order to acquire
+     * the normalized rotational component; the values are placed into
+     * the Matrix3f parameter.
+     * @param m1 matrix into which the rotational component is placed
+     */  
+    public final void get(Matrix3f m1)
+    {
+       double[]    tmp_rot = new double[9];  // scratch matrix
+       double[]    tmp_scale = new double[3];  // scratch matrix
+       
+       getScaleRotate( tmp_scale, tmp_rot );
+
+        m1.m00 = (float)tmp_rot[0];
+        m1.m01 = (float)tmp_rot[1];
+        m1.m02 = (float)tmp_rot[2];
+        m1.m10 = (float)tmp_rot[3];
+        m1.m11 = (float)tmp_rot[4];
+        m1.m12 = (float)tmp_rot[5];
+        m1.m20 = (float)tmp_rot[6];
+        m1.m21 = (float)tmp_rot[7];
+        m1.m22 = (float)tmp_rot[8];
+
+    }
+
+   /**
+     * Performs an SVD normalization of this matrix to calculate 
+     * the rotation as a 3x3 matrix, the translation, and the scale. 
+     * None of the matrix values are modified. 
+     * @param m1  the normalized matrix representing the rotation 
+     * @param t1  the translation component    
+     * @return  the scale component of this transform 
+     */   
+    public final float get(Matrix3f m1, Vector3f t1) 
+    {     
+       double[]    tmp_rot = new double[9];  // scratch matrix
+       double[]    tmp_scale = new double[3];  // scratch matrix
+       
+       getScaleRotate( tmp_scale, tmp_rot );
+        m1.m00 = (float)tmp_rot[0];
+        m1.m01 = (float)tmp_rot[1];
+        m1.m02 = (float)tmp_rot[2];
+        m1.m10 = (float)tmp_rot[3];
+        m1.m11 = (float)tmp_rot[4];
+        m1.m12 = (float)tmp_rot[5];
+        m1.m20 = (float)tmp_rot[6];
+        m1.m21 = (float)tmp_rot[7];
+        m1.m22 = (float)tmp_rot[8];
+        t1.x = m03;
+        t1.y = m13;
+        t1.z = m23;
+        return( (float)Matrix3d.max3( tmp_scale ));
+
+    } 
+    /** 
+     * Performs an SVD normalization of this matrix in order to acquire 
+     * the normalized rotational component; the values are placed into 
+     * the Quat4f parameter. 
+     * @param q1  quaternion into which the rotation component is placed 
+     */
+    public final void get(Quat4f q1){
+       double[]    tmp_rot = new double[9];  // scratch matrix
+       double[]    tmp_scale = new double[3];  // scratch matrix
+       getScaleRotate( tmp_scale, tmp_rot );
+
+        double ww;
+
+        ww = 0.25*(1.0 + tmp_rot[0] + tmp_rot[4] + tmp_rot[8]);
+        if(!((ww<0?-ww:ww) < 1.0e-30)) {
+          q1.w = (float)Math.sqrt(ww);
+          ww = 0.25/q1.w;
+          q1.x = (float)((tmp_rot[7] - tmp_rot[5])*ww);
+          q1.y = (float)((tmp_rot[2] - tmp_rot[6])*ww);
+          q1.z = (float)((tmp_rot[3] - tmp_rot[1])*ww);
+          return;
+        }
+
+        q1.w = 0.0f;
+        ww = -0.5*(tmp_rot[4] + tmp_rot[8]);
+        if(!((ww<0?-ww:ww) < 1.0e-30)) {
+          q1.x =  (float)Math.sqrt(ww);
+          ww = 0.5/q1.x;
+          q1.y = (float)(tmp_rot[3]*ww);
+          q1.z = (float)(tmp_rot[6]*ww);
+          return;
+        }
+
+        q1.x = 0.0f;
+        ww = 0.5*(1.0 - tmp_rot[8]);
+        if(!((ww<0?-ww:ww) < 1.0e-30)) {
+          q1.y =  (float)(Math.sqrt(ww));
+          q1.z = (float)(tmp_rot[7]/(2.0*q1.y));
+          return;
+        }  
+     
+        q1.y = 0.0f;
+        q1.z = 1.0f;
+
+    }
+   /**
+     * Retrieves the translational components of this matrix.
+     * @param trans  the vector that will receive the translational component
+     */
+    public final void get(Vector3f trans)
+    {  
+        trans.x = m03;
+        trans.y = m13;
+        trans.z = m23;
+    }
+
+  /**  
+    * Gets the upper 3x3 values of this matrix and places them into  
+    * the matrix m1.  
+    * @param m1  the matrix that will hold the values 
+    */
+    public final void getRotationScale(Matrix3f m1) 
+    {    
+      m1.m00 = m00; m1.m01 = m01; m1.m02 = m02; 
+      m1.m10 = m10; m1.m11 = m11; m1.m12 = m12; 
+      m1.m20 = m20; m1.m21 = m21; m1.m22 = m22; 
+    }  
+
+   /**
+     * Performs an SVD normalization of this matrix to calculate
+     * and return the uniform scale factor. If the matrix has non-uniform 
+     * scale factors, the largest of the x, y, and z scale factors will 
+     * be returned. This matrix is not modified.
+     * @return  the scale factor of this matrix
+     */  
+    public final float getScale() 
+    {
+       double[]    tmp_rot = new double[9];  // scratch matrix
+       double[]    tmp_scale = new double[3];  // scratch matrix
+       
+       getScaleRotate( tmp_scale, tmp_rot );
+
+        return( (float)Matrix3d.max3( tmp_scale ));
+
+    } 
+
+  /**  
+   * Replaces the upper 3x3 matrix values of this matrix with the  
+   * values in the matrix m1.  
+   * @param m1  the matrix that will be the new upper 3x3  
+   */  
+    public final void setRotationScale(Matrix3f m1)  
+    {    
+      m00 = m1.m00; m01 = m1.m01; m02 = m1.m02;
+      m10 = m1.m10; m11 = m1.m11; m12 = m1.m12;
+      m20 = m1.m20; m21 = m1.m21; m22 = m1.m22;
+    }    
+    /**
+     * Sets the specified row of this matrix4f to the four values provided.
+     * @param row the row number to be modified (zero indexed)
+     * @param x the first column element
+     * @param y the second column element
+     * @param z the third column element
+     * @param w the fourth column element
+     */
+    public final void setRow(int row, float x, float y, float z, float w)
+    {
+       switch (row) {
+       case 0:
+           this.m00 = x;
+           this.m01 = y;
+           this.m02 = z;
+           this.m03 = w;
+           break;
+
+       case 1:
+           this.m10 = x;
+           this.m11 = y;
+           this.m12 = z;
+           this.m13 = w;
+           break;
+
+       case 2:
+           this.m20 = x;
+           this.m21 = y;
+           this.m22 = z;
+           this.m23 = w;
+           break;
+
+       case 3:
+           this.m30 = x;
+           this.m31 = y;
+           this.m32 = z;
+           this.m33 = w;
+           break;
+
+       default:
+            throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4f6"));
+       }
+    }
+
+    /**
+     * Sets the specified row of this matrix4f to the Vector provided.
+     * @param row the row number to be modified (zero indexed)
+     * @param v the replacement row
+     */
+    public final void setRow(int row, Vector4f v)
+    {
+       switch (row) {
+       case 0:
+           this.m00 = v.x;
+           this.m01 = v.y;
+           this.m02 = v.z;
+           this.m03 = v.w;
+           break;
+
+       case 1:
+           this.m10 = v.x;
+           this.m11 = v.y;
+           this.m12 = v.z;
+           this.m13 = v.w;
+           break;
+
+       case 2:
+           this.m20 = v.x;
+           this.m21 = v.y;
+           this.m22 = v.z;
+           this.m23 = v.w;
+           break;
+
+       case 3:
+           this.m30 = v.x;
+           this.m31 = v.y;
+           this.m32 = v.z;
+           this.m33 = v.w;
+           break;
+
+       default:
+            throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4f6"));
+       }
+    }
+
+    /**
+     * Sets the specified row of this matrix4f to the four values provided
+     * in the passed array.
+     * @param row the row number to be modified (zero indexed)
+     * @param v the replacement row
+     */
+    public final void setRow(int row, float v[])
+    {
+       switch (row) {
+       case 0:
+           this.m00 = v[0];
+           this.m01 = v[1];
+           this.m02 = v[2];
+           this.m03 = v[3];
+           break;
+
+       case 1:
+           this.m10 = v[0];
+           this.m11 = v[1];
+           this.m12 = v[2];
+           this.m13 = v[3];
+           break;
+
+       case 2:
+           this.m20 = v[0];
+           this.m21 = v[1];
+           this.m22 = v[2];
+           this.m23 = v[3];
+           break;
+
+       case 3:
+           this.m30 = v[0];
+           this.m31 = v[1];
+           this.m32 = v[2];
+           this.m33 = v[3];
+           break;
+
+       default:
+            throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4f6"));
+       }
+    }
+
+    /**
+     * Sets the specified column of this matrix4f to the four values provided.
+     * @param column the column number to be modified (zero indexed)
+     * @param x the first row element
+     * @param y the second row element
+     * @param z the third row element
+     * @param w the fourth row element
+     */
+    public final void setColumn(int column, float x, float y, float z, float w)
+    {
+       switch (column) {
+       case 0:
+           this.m00 = x;
+           this.m10 = y;
+           this.m20 = z;
+           this.m30 = w;
+           break;
+
+       case 1:
+           this.m01 = x;
+           this.m11 = y;
+           this.m21 = z;
+           this.m31 = w;
+           break;
+
+       case 2:
+           this.m02 = x;
+           this.m12 = y;
+           this.m22 = z;
+           this.m32 = w;
+           break;
+
+       case 3:
+           this.m03 = x;
+           this.m13 = y;
+           this.m23 = z;
+           this.m33 = w;
+           break;
+
+       default:
+            throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4f9"));
+       }
+    }
+
+    /**
+     * Sets the specified column of this matrix4f to the vector provided.
+     * @param column the column number to be modified (zero indexed)
+     * @param v the replacement column
+     */
+    public final void setColumn(int column, Vector4f v)
+    {
+       switch (column) {
+       case 0:
+           this.m00 = v.x;
+           this.m10 = v.y;
+           this.m20 = v.z;
+           this.m30 = v.w;
+           break;
+
+       case 1:
+           this.m01 = v.x;
+           this.m11 = v.y;
+           this.m21 = v.z;
+           this.m31 = v.w;
+           break;
+
+       case 2:
+           this.m02 = v.x;
+           this.m12 = v.y;
+           this.m22 = v.z;
+           this.m32 = v.w;
+           break;
+
+       case 3:
+           this.m03 = v.x;
+           this.m13 = v.y;
+           this.m23 = v.z;
+           this.m33 = v.w;
+           break;
+
+       default:
+            throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4f9"));
+       }
+    }
+
+    /**
+     * Sets the specified column of this matrix4f to the four values provided.
+     * @param column the column number to be modified (zero indexed)
+     * @param v the replacement column
+     */
+    public final void setColumn(int column, float v[])
+    {
+       switch (column) {
+       case 0:
+           this.m00 = v[0];
+           this.m10 = v[1];
+           this.m20 = v[2];
+           this.m30 = v[3];
+           break;
+
+       case 1:
+           this.m01 = v[0];
+           this.m11 = v[1];
+           this.m21 = v[2];
+           this.m31 = v[3];
+           break;
+
+       case 2:
+           this.m02 = v[0];
+           this.m12 = v[1];
+           this.m22 = v[2];
+           this.m32 = v[3];
+           break;
+
+       case 3:
+           this.m03 = v[0];
+           this.m13 = v[1];
+           this.m23 = v[2];
+           this.m33 = v[3];
+           break;
+
+       default:
+            throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4f9"));
+       }
+    }
+
+   /**
+     *  Adds a scalar to each component of this matrix.
+     *  @param scalar  the scalar adder
+     */
+    public final void add(float scalar)
+    {
+        m00 += scalar;
+        m01 += scalar;
+        m02 += scalar;
+        m03 += scalar;
+        m10 += scalar;
+        m11 += scalar;
+        m12 += scalar;
+        m13 += scalar;
+        m20 += scalar;
+        m21 += scalar;
+        m22 += scalar;
+        m23 += scalar;
+        m30 += scalar;
+        m31 += scalar;
+        m32 += scalar;
+        m33 += scalar;
+    }
+
+   /**
+     *  Adds a scalar to each component of the matrix m1 and places
+     *  the result into this.  Matrix m1 is not modified.
+     *  @param scalar  the scalar adder
+     *  @param m1  the original matrix values
+     */  
+    public final void add(float scalar, Matrix4f m1)
+    {
+        this.m00 = m1.m00 +  scalar;
+        this.m01 = m1.m01 +  scalar;
+        this.m02 = m1.m02 +  scalar;
+        this.m03 = m1.m03 +  scalar;
+        this.m10 = m1.m10 +  scalar;
+        this.m11 = m1.m11 +  scalar;
+        this.m12 = m1.m12 +  scalar;
+        this.m13 = m1.m13 +  scalar;
+        this.m20 = m1.m20 +  scalar;
+        this.m21 = m1.m21 +  scalar;
+        this.m22 = m1.m22 +  scalar;
+        this.m23 = m1.m23 +  scalar;
+        this.m30 = m1.m30 +  scalar;
+        this.m31 = m1.m31 +  scalar;
+        this.m32 = m1.m32 +  scalar;
+        this.m33 = m1.m33 +  scalar;
+    }
+
+    /**
+     * Sets the value of this matrix to the matrix sum of matrices m1 and m2.
+     * @param m1 the first matrix
+     * @param m2 the second matrix
+     */
+    public final void add(Matrix4f m1, Matrix4f m2)
+    {
+       this.m00 = m1.m00 + m2.m00;
+       this.m01 = m1.m01 + m2.m01;
+       this.m02 = m1.m02 + m2.m02;
+       this.m03 = m1.m03 + m2.m03;
+
+       this.m10 = m1.m10 + m2.m10;
+       this.m11 = m1.m11 + m2.m11;
+       this.m12 = m1.m12 + m2.m12;
+       this.m13 = m1.m13 + m2.m13;
+
+       this.m20 = m1.m20 + m2.m20;
+       this.m21 = m1.m21 + m2.m21;
+       this.m22 = m1.m22 + m2.m22;
+       this.m23 = m1.m23 + m2.m23;
+
+       this.m30 = m1.m30 + m2.m30;
+       this.m31 = m1.m31 + m2.m31;
+       this.m32 = m1.m32 + m2.m32;
+       this.m33 = m1.m33 + m2.m33;
+    }
+
+    /**  
+     * Sets the value of this matrix to the sum of itself and matrix m1.
+     * @param m1 the other matrix
+     */
+    public final void add(Matrix4f m1)
+    { 
+        this.m00 += m1.m00;
+        this.m01 += m1.m01;
+        this.m02 += m1.m02;
+        this.m03 += m1.m03;
+        this.m10 += m1.m10;
+        this.m11 += m1.m11;
+        this.m12 += m1.m12;
+        this.m13 += m1.m13;
+        this.m20 += m1.m20;
+        this.m21 += m1.m21;
+        this.m22 += m1.m22;
+        this.m23 += m1.m23;
+        this.m30 += m1.m30;
+        this.m31 += m1.m31;
+        this.m32 += m1.m32;
+        this.m33 += m1.m33;
+    }  
+
+    /**
+     * Performs an element-by-element subtraction of matrix m2 from
+     * matrix m1 and places the result into matrix this (this =
+     * m2 - m1).
+     * @param m1 the first matrix
+     * @param m2 the second matrix
+     */
+    public final void sub(Matrix4f m1, Matrix4f m2)
+    {
+       this.m00 = m1.m00 - m2.m00;
+       this.m01 = m1.m01 - m2.m01;
+       this.m02 = m1.m02 - m2.m02;
+       this.m03 = m1.m03 - m2.m03;
+
+       this.m10 = m1.m10 - m2.m10;
+       this.m11 = m1.m11 - m2.m11;
+       this.m12 = m1.m12 - m2.m12;
+       this.m13 = m1.m13 - m2.m13;
+
+       this.m20 = m1.m20 - m2.m20;
+       this.m21 = m1.m21 - m2.m21;
+       this.m22 = m1.m22 - m2.m22;
+       this.m23 = m1.m23 - m2.m23;
+
+       this.m30 = m1.m30 - m2.m30;
+       this.m31 = m1.m31 - m2.m31;
+       this.m32 = m1.m32 - m2.m32;
+       this.m33 = m1.m33 - m2.m33;
+    }
+
+   /**
+     * Sets this matrix to the matrix difference of itself and 
+     * matrix m1 (this = this - m1).
+     * @param m1 the other matrix
+     */
+    public final void sub(Matrix4f m1)
+    {
+        this.m00 -= m1.m00;
+        this.m01 -= m1.m01;
+        this.m02 -= m1.m02;
+        this.m03 -= m1.m03;
+        this.m10 -= m1.m10;
+        this.m11 -= m1.m11;
+        this.m12 -= m1.m12;
+        this.m13 -= m1.m13;
+        this.m20 -= m1.m20;
+        this.m21 -= m1.m21;
+        this.m22 -= m1.m22;
+        this.m23 -= m1.m23;
+        this.m30 -= m1.m30;
+        this.m31 -= m1.m31;
+        this.m32 -= m1.m32;
+        this.m33 -= m1.m33;
+    }   
+
+    /**
+     * Sets the value of this matrix to its transpose in place.
+     */
+    public final void transpose()
+    {
+       float temp;
+
+       temp = this.m10;
+       this.m10 = this.m01;
+       this.m01 = temp;
+
+       temp = this.m20;
+       this.m20 = this.m02;
+       this.m02 = temp;
+
+       temp = this.m30;
+       this.m30 = this.m03;
+       this.m03 = temp;
+
+       temp = this.m21;
+       this.m21 = this.m12;
+       this.m12 = temp;
+
+       temp = this.m31;
+       this.m31 = this.m13;
+       this.m13 = temp;
+
+       temp = this.m32;
+       this.m32 = this.m23;
+       this.m23 = temp;
+    }
+
+    /**
+     * Sets the value of this matrix to the transpose of the argument matrix.
+     * @param m1 the matrix to be transposed
+     */
+    public final void transpose(Matrix4f m1)
+    {
+       if (this != m1) {
+           this.m00 = m1.m00;
+           this.m01 = m1.m10;
+           this.m02 = m1.m20;
+           this.m03 = m1.m30;
+
+           this.m10 = m1.m01;
+           this.m11 = m1.m11;
+           this.m12 = m1.m21;
+           this.m13 = m1.m31;
+
+           this.m20 = m1.m02;
+           this.m21 = m1.m12;
+           this.m22 = m1.m22;
+           this.m23 = m1.m32;
+
+           this.m30 = m1.m03;
+           this.m31 = m1.m13;
+           this.m32 = m1.m23;
+           this.m33 = m1.m33;
+       } else
+           this.transpose();
+    }
+
+    /**
+     * Sets the value of this matrix to the matrix conversion of the
+     * single precision quaternion argument.
+     * @param q1 the quaternion to be converted
+     */
+    public final void set(Quat4f q1)
+    {
+        this.m00 = (1.0f - 2.0f*q1.y*q1.y - 2.0f*q1.z*q1.z);
+        this.m10 = (2.0f*(q1.x*q1.y + q1.w*q1.z));
+        this.m20 = (2.0f*(q1.x*q1.z - q1.w*q1.y));
+
+        this.m01 = (2.0f*(q1.x*q1.y - q1.w*q1.z));
+        this.m11 = (1.0f - 2.0f*q1.x*q1.x - 2.0f*q1.z*q1.z);
+        this.m21 = (2.0f*(q1.y*q1.z + q1.w*q1.x));
+
+        this.m02 = (2.0f*(q1.x*q1.z + q1.w*q1.y));
+        this.m12 = (2.0f*(q1.y*q1.z - q1.w*q1.x));
+        this.m22 = (1.0f - 2.0f*q1.x*q1.x - 2.0f*q1.y*q1.y);
+
+        this.m03 = (float) 0.0;
+        this.m13 = (float) 0.0;
+        this.m23 = (float) 0.0;
+
+        this.m30 = (float) 0.0;
+        this.m31 = (float) 0.0;
+        this.m32 = (float) 0.0;
+        this.m33 = (float) 1.0;
+    }
+
+    /**
+     * Sets the value of this matrix to the matrix conversion of the
+     * (single precision) axis and angle argument.
+     * @param a1 the axis and angle to be converted
+     */
+    public final void set(AxisAngle4f a1)
+    {
+      float mag = (float)Math.sqrt( a1.x*a1.x + a1.y*a1.y + a1.z*a1.z);
+      if( mag < EPS ) {
+        m00 = 1.0f;
+        m01 = 0.0f;
+        m02 = 0.0f;
+
+        m10 = 0.0f;
+        m11 = 1.0f;
+        m12 = 0.0f;
+
+        m20 = 0.0f;
+        m21 = 0.0f;
+        m22 = 1.0f;
+      } else {
+        mag = 1.0f/mag;
+         float ax = a1.x*mag;
+         float ay = a1.y*mag;
+         float az = a1.z*mag;
+
+         float sinTheta = (float)Math.sin((double)a1.angle);
+         float cosTheta = (float)Math.cos((double)a1.angle);
+         float t = 1.0f - cosTheta;
+         
+         float xz = ax * az;
+         float xy = ax * ay;
+         float yz = ay * az;
+         
+         m00 = t * ax * ax + cosTheta;
+         m01 = t * xy - sinTheta * az;
+         m02 = t * xz + sinTheta * ay;
+
+         m10 = t * xy + sinTheta * az;
+         m11 = t * ay * ay + cosTheta;
+         m12 = t * yz - sinTheta * ax;
+
+         m20 = t * xz - sinTheta * ay;
+         m21 = t * yz + sinTheta * ax;
+         m22 = t * az * az + cosTheta;
+      }
+      m03 = 0.0f;
+      m13 = 0.0f;
+      m23 = 0.0f;
+
+      m30 = 0.0f;
+      m31 = 0.0f;
+      m32 = 0.0f;
+      m33 = 1.0f;
+    }
+
+    /**
+     * Sets the value of this matrix to the matrix conversion of the
+     * double precision quaternion argument.
+     * @param q1 the quaternion to be converted
+     */
+    public final void set(Quat4d q1)
+    {
+       this.m00 = (float) (1.0 - 2.0*q1.y*q1.y - 2.0*q1.z*q1.z);
+       this.m10 = (float) (2.0*(q1.x*q1.y + q1.w*q1.z));
+       this.m20 = (float) (2.0*(q1.x*q1.z - q1.w*q1.y));
+
+       this.m01 = (float) (2.0*(q1.x*q1.y - q1.w*q1.z));
+       this.m11 = (float) (1.0 - 2.0*q1.x*q1.x - 2.0*q1.z*q1.z);
+       this.m21 = (float) (2.0*(q1.y*q1.z + q1.w*q1.x));
+
+       this.m02 = (float) (2.0*(q1.x*q1.z + q1.w*q1.y));
+       this.m12 = (float) (2.0*(q1.y*q1.z - q1.w*q1.x));
+       this.m22 = (float) (1.0 - 2.0*q1.x*q1.x - 2.0*q1.y*q1.y);
+
+       this.m03 = (float) 0.0;
+       this.m13 = (float) 0.0;
+       this.m23 = (float) 0.0;
+
+       this.m30 = (float) 0.0;
+       this.m31 = (float) 0.0;
+       this.m32 = (float) 0.0;
+       this.m33 = (float) 1.0;
+    }
+
+    /**
+     * Sets the value of this matrix to the matrix conversion of the
+     * double precision axis and angle argument.
+     * @param a1 the axis and angle to be converted
+     */
+    public final void set(AxisAngle4d a1)
+    {
+      double mag = Math.sqrt( a1.x*a1.x + a1.y*a1.y + a1.z*a1.z);
+
+      if( mag < EPS ) {
+        m00 = 1.0f;
+        m01 = 0.0f;
+        m02 = 0.0f;
+
+        m10 = 0.0f;
+        m11 = 1.0f;
+        m12 = 0.0f;
+
+        m20 = 0.0f;
+        m21 = 0.0f;
+        m22 = 1.0f;
+      } else {
+        mag = 1.0/mag;
+         double ax = a1.x*mag;
+         double ay = a1.y*mag;
+         double az = a1.z*mag;
+
+         float sinTheta = (float) Math.sin(a1.angle);
+         float cosTheta = (float) Math.cos(a1.angle);
+         float t = 1.0f - cosTheta;
+
+         float xz = (float) (ax * az);
+         float xy = (float) (ax * ay);
+         float yz = (float) (ay * az);
+
+         this.m00 = t * (float)(ax * ax) + cosTheta;
+         this.m01 = t * xy - sinTheta * (float)az;
+         this.m02 = t * xz + sinTheta * (float)ay;
+
+         this.m10 = t * xy + sinTheta * (float)az;
+         this.m11 = t * (float)(ay * ay) + cosTheta;
+         this.m12 = t * yz - sinTheta * (float)ax;
+
+         this.m20 = t * xz - sinTheta * (float)ay;
+         this.m21 = t * yz + sinTheta * (float)ax;
+         this.m22 = t * (float)(az * az) + cosTheta;
+      }
+      this.m03 = 0.0f;
+      this.m13 = 0.0f;
+      this.m23 = 0.0f;
+
+      this.m30 = 0.0f;
+      this.m31 = 0.0f;
+      this.m32 = 0.0f;
+      this.m33 = 1.0f;
+    }
+
+    /**
+     * Sets the value of this matrix from the rotation expressed
+     * by the quaternion q1, the translation t1, and the scale s.
+     * @param q1 the rotation expressed as a quaternion
+     * @param t1 the translation
+     * @param s the scale value
+     */
+    public final void set(Quat4d q1, Vector3d t1, double s)
+    {
+       this.m00 = (float) (s*(1.0 - 2.0*q1.y*q1.y -2.0*q1.z*q1.z));
+       this.m10 = (float) (s*(2.0*(q1.x*q1.y + q1.w*q1.z)));
+       this.m20 = (float) (s*(2.0*(q1.x*q1.z - q1.w*q1.y)));
+
+       this.m01 = (float) (s*(2.0*(q1.x*q1.y - q1.w*q1.z)));
+       this.m11 = (float) (s*(1.0 - 2.0*q1.x*q1.x -2.0*q1.z*q1.z));
+       this.m21 = (float) (s*(2.0*(q1.y*q1.z + q1.w*q1.x)));
+
+       this.m02 = (float) (s*(2.0*(q1.x*q1.z + q1.w*q1.y)));
+       this.m12 = (float) (s*(2.0*(q1.y*q1.z - q1.w*q1.x)));
+       this.m22 = (float) (s*(1.0 - 2.0*q1.x*q1.x -2.0*q1.y*q1.y));
+
+       this.m03 = (float) t1.x;
+       this.m13 = (float) t1.y;
+       this.m23 = (float) t1.z;
+
+       this.m30 = (float) 0.0;
+       this.m31 = (float) 0.0;
+       this.m32 = (float) 0.0;
+       this.m33 = (float) 1.0;
+    }
+
+    /**
+     * Sets the value of this matrix from the rotation expressed
+     * by the quaternion q1, the translation t1, and the scale s.
+     * @param q1 the rotation expressed as a quaternion
+     * @param t1 the translation
+     * @param s the scale value
+     */
+    public final void set(Quat4f q1, Vector3f t1, float s)
+    {
+       this.m00 =  (s*(1.0f - 2.0f*q1.y*q1.y -2.0f*q1.z*q1.z));
+       this.m10 =  (s*(2.0f*(q1.x*q1.y + q1.w*q1.z)));
+       this.m20 =  (s*(2.0f*(q1.x*q1.z - q1.w*q1.y)));
+
+       this.m01 =  (s*(2.0f*(q1.x*q1.y - q1.w*q1.z)));
+       this.m11 =  (s*(1.0f - 2.0f*q1.x*q1.x -2.0f*q1.z*q1.z));
+       this.m21 =  (s*(2.0f*(q1.y*q1.z + q1.w*q1.x)));
+
+       this.m02 =  (s*(2.0f*(q1.x*q1.z + q1.w*q1.y)));
+       this.m12 =  (s*(2.0f*(q1.y*q1.z - q1.w*q1.x)));
+       this.m22 =  (s*(1.0f - 2.0f*q1.x*q1.x - 2.0f*q1.y*q1.y));
+
+       this.m03 =  t1.x;
+       this.m13 =  t1.y;
+       this.m23 =  t1.z;
+
+       this.m30 = (float) 0.0;
+       this.m31 = (float) 0.0;
+       this.m32 = (float) 0.0;
+       this.m33 = (float) 1.0;
+    }
+
+    /**
+     * Sets the value of this matrix to the float value of the
+     * passed matrix4d m1.
+     * @param m1 the matrix4d to be converted to float
+     */
+    public final void set(Matrix4d m1)
+    {
+       this.m00 = (float) m1.m00;
+       this.m01 = (float) m1.m01;
+       this.m02 = (float) m1.m02;
+       this.m03 = (float) m1.m03;
+
+       this.m10 = (float) m1.m10;
+       this.m11 = (float) m1.m11;
+       this.m12 = (float) m1.m12;
+       this.m13 = (float) m1.m13;
+
+       this.m20 = (float) m1.m20;
+       this.m21 = (float) m1.m21;
+       this.m22 = (float) m1.m22;
+       this.m23 = (float) m1.m23;
+
+       this.m30 = (float) m1.m30;
+       this.m31 = (float) m1.m31;
+       this.m32 = (float) m1.m32;
+       this.m33 = (float) m1.m33;
+    }
+
+    /**
+     * Sets the value of this matrix to a copy of the
+     * passed matrix m1.
+     * @param m1 the matrix to be copied
+     */
+    public final void set(Matrix4f m1)
+    {
+       this.m00 = m1.m00;
+       this.m01 = m1.m01;
+       this.m02 = m1.m02;
+       this.m03 = m1.m03;
+
+       this.m10 = m1.m10;
+       this.m11 = m1.m11;
+       this.m12 = m1.m12;
+       this.m13 = m1.m13;
+
+       this.m20 = m1.m20;
+       this.m21 = m1.m21;
+       this.m22 = m1.m22;
+       this.m23 = m1.m23;
+
+       this.m30 = m1.m30;
+       this.m31 = m1.m31;
+       this.m32 = m1.m32;
+       this.m33 = m1.m33;
+    }
+
+  /**
+   * Sets the value of this matrix to the matrix inverse
+   * of the passed (user declared) matrix m1.
+   * @param m1 the matrix to be inverted
+   */
+  public final void invert(Matrix4f m1)
+  {
+
+     invertGeneral( m1);    
+  }
+
+  /**
+   * Inverts this matrix in place.
+   */
+  public final void invert()
+  {
+     invertGeneral( this );    
+  }
+
+    /**
+     * General invert routine.  Inverts m1 and places the result in "this".
+     * Note that this routine handles both the "this" version and the
+     * non-"this" version.
+     *
+     * Also note that since this routine is slow anyway, we won't worry
+     * about allocating a little bit of garbage.
+     */
+    final void invertGeneral(Matrix4f  m1) {
+       double temp[] = new double[16];
+       double result[] = new double[16];
+       int row_perm[] = new int[4];
+       int i, r, c;
+
+       // Use LU decomposition and backsubstitution code specifically
+       // for floating-point 4x4 matrices.
+
+       // Copy source matrix to t1tmp 
+        temp[0] = m1.m00;
+        temp[1] = m1.m01;
+        temp[2] = m1.m02;
+        temp[3] = m1.m03;
+        temp[4] = m1.m10;
+        temp[5] = m1.m11;
+        temp[6] = m1.m12;
+        temp[7] = m1.m13;
+        temp[8] = m1.m20;
+        temp[9] = m1.m21;
+        temp[10] = m1.m22;
+        temp[11] = m1.m23;
+        temp[12] = m1.m30;
+        temp[13] = m1.m31;
+        temp[14] = m1.m32;
+        temp[15] = m1.m33;
+
+       // Calculate LU decomposition: Is the matrix singular? 
+       if (!luDecomposition(temp, row_perm)) {
+           // Matrix has no inverse 
+           throw new SingularMatrixException(VecMathI18N.getString("Matrix4f12"));
+       }
+
+       // Perform back substitution on the identity matrix 
+        for(i=0;i<16;i++) result[i] = 0.0;
+        result[0] = 1.0; result[5] = 1.0; result[10] = 1.0; result[15] = 1.0;
+       luBacksubstitution(temp, row_perm, result);
+
+        this.m00 = (float)result[0];
+        this.m01 = (float)result[1];
+        this.m02 = (float)result[2];
+        this.m03 = (float)result[3];
+
+        this.m10 = (float)result[4];
+        this.m11 = (float)result[5];
+        this.m12 = (float)result[6];
+        this.m13 = (float)result[7];
+        this.m20 = (float)result[8];
+        this.m21 = (float)result[9];
+        this.m22 = (float)result[10];
+        this.m23 = (float)result[11];
+        this.m30 = (float)result[12];
+        this.m31 = (float)result[13];
+        this.m32 = (float)result[14];
+        this.m33 = (float)result[15];
+
+    }
+
+    /**
+     * Given a 4x4 array "matrix0", this function replaces it with the 
+     * LU decomposition of a row-wise permutation of itself.  The input 
+     * parameters are "matrix0" and "dimen".  The array "matrix0" is also 
+     * an output parameter.  The vector "row_perm[4]" is an output 
+     * parameter that contains the row permutations resulting from partial 
+     * pivoting.  The output parameter "even_row_xchg" is 1 when the 
+     * number of row exchanges is even, or -1 otherwise.  Assumes data 
+     * type is always double.
+     *
+     * This function is similar to luDecomposition, except that it
+     * is tuned specifically for 4x4 matrices.
+     *
+     * @return true if the matrix is nonsingular, or false otherwise.
+     */
+    //
+    // Reference: Press, Flannery, Teukolsky, Vetterling, 
+    //       _Numerical_Recipes_in_C_, Cambridge University Press, 
+    //       1988, pp 40-45.
+    //
+    static boolean luDecomposition(double[] matrix0,
+                                  int[] row_perm) {
+
+       double row_scale[] = new double[4];
+
+       // Determine implicit scaling information by looping over rows 
+       {
+           int i, j;
+           int ptr, rs;
+           double big, temp;
+
+           ptr = 0;
+           rs = 0;
+
+           // For each row ... 
+           i = 4;
+           while (i-- != 0) {
+               big = 0.0;
+
+               // For each column, find the largest element in the row 
+               j = 4;
+               while (j-- != 0) {
+                   temp = matrix0[ptr++];
+                   temp = Math.abs(temp);
+                   if (temp > big) {
+                       big = temp;
+                   }
+               }
+
+               // Is the matrix singular? 
+               if (big == 0.0) {
+                   return false;
+               }
+               row_scale[rs++] = 1.0 / big;
+           }
+       }
+
+       {
+           int j;
+           int mtx;
+
+           mtx = 0;
+
+           // For all columns, execute Crout's method 
+           for (j = 0; j < 4; j++) {
+               int i, imax, k;
+               int target, p1, p2;
+               double sum, big, temp;
+
+               // Determine elements of upper diagonal matrix U 
+               for (i = 0; i < j; i++) {
+                   target = mtx + (4*i) + j;
+                   sum = matrix0[target];
+                   k = i;
+                   p1 = mtx + (4*i);
+                   p2 = mtx + j;
+                   while (k-- != 0) {
+                       sum -= matrix0[p1] * matrix0[p2];
+                       p1++;
+                       p2 += 4;
+                   }
+                   matrix0[target] = sum;
+               }
+
+               // Search for largest pivot element and calculate
+               // intermediate elements of lower diagonal matrix L.
+               big = 0.0;
+               imax = -1;
+               for (i = j; i < 4; i++) {
+                   target = mtx + (4*i) + j;
+                   sum = matrix0[target];
+                   k = j;
+                   p1 = mtx + (4*i);
+                   p2 = mtx + j;
+                   while (k-- != 0) {
+                       sum -= matrix0[p1] * matrix0[p2];
+                       p1++;
+                       p2 += 4;
+                   }
+                   matrix0[target] = sum;
+
+                   // Is this the best pivot so far? 
+                   if ((temp = row_scale[i] * Math.abs(sum)) >= big) {
+                       big = temp;
+                       imax = i;
+                   }
+               }
+
+               if (imax < 0) {
+                   throw new RuntimeException(VecMathI18N.getString("Matrix4f13"));
+               }
+
+               // Is a row exchange necessary? 
+               if (j != imax) {
+                   // Yes: exchange rows 
+                   k = 4;
+                   p1 = mtx + (4*imax);
+                   p2 = mtx + (4*j);
+                   while (k-- != 0) {
+                       temp = matrix0[p1];
+                       matrix0[p1++] = matrix0[p2];
+                       matrix0[p2++] = temp;
+                   }
+
+                   // Record change in scale factor 
+                   row_scale[imax] = row_scale[j];
+               }
+
+               // Record row permutation 
+               row_perm[j] = imax;
+
+               // Is the matrix singular 
+               if (matrix0[(mtx + (4*j) + j)] == 0.0) {
+                   return false;
+               }
+
+               // Divide elements of lower diagonal matrix L by pivot 
+               if (j != (4-1)) {
+                   temp = 1.0 / (matrix0[(mtx + (4*j) + j)]);
+                   target = mtx + (4*(j+1)) + j;
+                   i = 3 - j;
+                   while (i-- != 0) {
+                       matrix0[target] *= temp;
+                       target += 4;
+                   }
+               }
+           }
+       }
+
+       return true;
+    }
+
+    /**
+     * Solves a set of linear equations.  The input parameters "matrix1",
+     * and "row_perm" come from luDecompostionD4x4 and do not change
+     * here.  The parameter "matrix2" is a set of column vectors assembled
+     * into a 4x4 matrix of floating-point values.  The procedure takes each
+     * column of "matrix2" in turn and treats it as the right-hand side of the
+     * matrix equation Ax = LUx = b.  The solution vector replaces the
+     * original column of the matrix.
+     *
+     * If "matrix2" is the identity matrix, the procedure replaces its contents
+     * with the inverse of the matrix from which "matrix1" was originally
+     * derived.
+     */
+    //
+    // Reference: Press, Flannery, Teukolsky, Vetterling, 
+    //       _Numerical_Recipes_in_C_, Cambridge University Press, 
+    //       1988, pp 44-45.
+    //
+    static void luBacksubstitution(double[] matrix1,
+                                  int[] row_perm,
+                                  double[] matrix2) {
+
+       int i, ii, ip, j, k;
+       int rp;
+       int cv, rv;
+       
+       //      rp = row_perm;
+       rp = 0;
+
+       // For each column vector of matrix2 ... 
+       for (k = 0; k < 4; k++) {
+           //      cv = &(matrix2[0][k]);
+           cv = k;
+           ii = -1;
+
+           // Forward substitution 
+           for (i = 0; i < 4; i++) {
+               double sum;
+
+               ip = row_perm[rp+i];
+               sum = matrix2[cv+4*ip];
+               matrix2[cv+4*ip] = matrix2[cv+4*i];
+               if (ii >= 0) {
+                   //              rv = &(matrix1[i][0]);
+                   rv = i*4;
+                   for (j = ii; j <= i-1; j++) {
+                       sum -= matrix1[rv+j] * matrix2[cv+4*j];
+                   }
+               }
+               else if (sum != 0.0) {
+                   ii = i;
+               }
+               matrix2[cv+4*i] = sum;
+           }
+
+           // Backsubstitution 
+           //      rv = &(matrix1[3][0]);
+           rv = 3*4;
+           matrix2[cv+4*3] /= matrix1[rv+3];
+
+           rv -= 4;
+           matrix2[cv+4*2] = (matrix2[cv+4*2] -
+                           matrix1[rv+3] * matrix2[cv+4*3]) / matrix1[rv+2];
+
+           rv -= 4;
+           matrix2[cv+4*1] = (matrix2[cv+4*1] -
+                           matrix1[rv+2] * matrix2[cv+4*2] -
+                           matrix1[rv+3] * matrix2[cv+4*3]) / matrix1[rv+1];
+
+           rv -= 4;
+           matrix2[cv+4*0] = (matrix2[cv+4*0] -
+                           matrix1[rv+1] * matrix2[cv+4*1] -
+                           matrix1[rv+2] * matrix2[cv+4*2] -
+                           matrix1[rv+3] * matrix2[cv+4*3]) / matrix1[rv+0];
+       }
+    }
+
+    /**
+     * Computes the determinate of this matrix.
+     * @return the determinate of the matrix
+     */
+    public final float determinant()
+    {
+       float det;
+
+       // cofactor exapainsion along first row 
+
+        det = m00*(m11*m22*m33+ m12*m23*m31 + m13*m21*m32 
+                 - m13*m22*m31 -m11*m23*m32 - m12*m21*m33);
+        det -= m01*(m10*m22*m33+ m12*m23*m30 + m13*m20*m32 
+                  - m13*m22*m30 -m10*m23*m32 - m12*m20*m33);
+        det += m02*(m10*m21*m33+ m11*m23*m30 + m13*m20*m31 
+                  - m13*m21*m30 -m10*m23*m31 - m11*m20*m33);
+        det -= m03*(m10*m21*m32+ m11*m22*m30 + m12*m20*m31 
+                  - m12*m21*m30 -m10*m22*m31 - m11*m20*m32);
+
+        return( det );
+    }
+
+    /**
+     * Sets the rotational component (upper 3x3) of this matrix to the
+     * matrix values in the single precision Matrix3f argument; the other
+     * elements of this matrix are initialized as if this were an identity
+     * matrix (i.e., affine matrix with no translational component).
+     * @param m1   the single-precision 3x3 matrix
+     */  
+    public final void set(Matrix3f m1)
+    {
+       m00 = m1.m00; m01 = m1.m01; m02 = m1.m02; m03 = 0.0f;
+       m10 = m1.m10; m11 = m1.m11; m12 = m1.m12; m13 = 0.0f;
+       m20 = m1.m20; m21 = m1.m21; m22 = m1.m22; m23 = 0.0f;
+       m30 = 0.0f;   m31 = 0.0f  ; m32 = 0.0f  ; m33 = 1.0f;
+    }
+
+    /**
+     * Sets the rotational component (upper 3x3) of this matrix to the
+     * matrix values in the double precision Matrix3d argument; the other
+     * elements of this matrix are initialized as if this were an identity
+     * matrix (i.e., affine matrix with no translational component).
+     * @param m1   the double-precision 3x3 matrix
+     */  
+    public final void set(Matrix3d m1)
+    {
+       m00 = (float)m1.m00; m01 = (float)m1.m01; m02 = (float)m1.m02; m03 = 0.0f;
+       m10 = (float)m1.m10; m11 = (float)m1.m11; m12 = (float)m1.m12; m13 = 0.0f;
+       m20 = (float)m1.m20; m21 = (float)m1.m21; m22 = (float)m1.m22; m23 = 0.0f;
+       m30 = 0.0f;   m31 = 0.0f  ; m32 = 0.0f  ; m33 = 1.0f;
+    }
+
+    /**
+     * Sets the value of this matrix to a scale matrix with the
+     * the passed scale amount.
+     * @param scale the scale factor for the matrix
+     */
+    public final void set(float scale)
+    {
+       this.m00 = scale;
+       this.m01 = (float) 0.0;
+       this.m02 = (float) 0.0;
+       this.m03 = (float) 0.0;
+
+       this.m10 = (float) 0.0;
+       this.m11 = scale;
+       this.m12 = (float) 0.0;
+       this.m13 = (float) 0.0;
+
+       this.m20 = (float) 0.0;
+       this.m21 = (float) 0.0;
+       this.m22 = scale;
+       this.m23 = (float) 0.0;
+
+       this.m30 = (float) 0.0;
+       this.m31 = (float) 0.0;
+       this.m32 = (float) 0.0;
+       this.m33 = (float) 1.0;
+    }
+
+    /**
+     *  Sets the values in this Matrix4f equal to the row-major
+     *  array parameter (ie, the first four elements of the
+     *  array will be copied into the first row of this matrix, etc.).
+     *  @param m  the single precision array of length 16
+     */  
+    public final void set(float[] m)
+    {
+          m00 = m[0];
+          m01 = m[1];
+          m02 = m[2];
+          m03 = m[3];
+          m10 = m[4];
+          m11 = m[5];
+          m12 = m[6];
+          m13 = m[7];
+          m20 = m[8];
+          m21 = m[9];
+          m22 = m[10];
+          m23 = m[11];
+          m30 = m[12];
+          m31 = m[13];
+          m32 = m[14];
+          m33 = m[15];
+    }
+
+    /**
+     * Sets the value of this matrix to a translate matrix with
+     * the passed translation value.
+     * @param v1 the translation amount
+     */
+    public final void set(Vector3f v1)
+    {
+       this.m00 = (float) 1.0;
+       this.m01 = (float) 0.0;
+       this.m02 = (float) 0.0;
+       this.m03 = v1.x; 
+
+       this.m10 = (float) 0.0;
+       this.m11 = (float) 1.0;
+       this.m12 = (float) 0.0;
+       this.m13 = v1.y;
+
+       this.m20 = (float) 0.0;
+       this.m21 = (float) 0.0;
+       this.m22 = (float) 1.0;
+       this.m23 = v1.z;
+
+       this.m30 = (float) 0.0;
+       this.m31 = (float) 0.0;
+       this.m32 = (float) 0.0;
+       this.m33 = (float) 1.0;
+    }
+
+   /**
+     * Sets the value of this transform to a scale and translation matrix; 
+     * the scale is not applied to the translation and all of the matrix 
+     * values are modified. 
+     * @param scale the scale factor for the matrix
+     * @param t1 the translation amount
+     */
+    public final void set(float scale, Vector3f t1)
+    {
+       this.m00 = scale;
+       this.m01 = (float) 0.0;
+       this.m02 = (float) 0.0;
+       this.m03 = t1.x;
+
+       this.m10 = (float) 0.0;
+       this.m11 = scale;
+       this.m12 = (float) 0.0;
+       this.m13 = t1.y;
+
+       this.m20 = (float) 0.0;
+       this.m21 = (float) 0.0;
+       this.m22 = scale;
+       this.m23 = t1.z;
+
+       this.m30 = (float) 0.0;
+       this.m31 = (float) 0.0;
+       this.m32 = (float) 0.0;
+       this.m33 = (float) 1.0;
+    }
+
+    /**
+      * Sets the value of this transform to a scale and translation matrix; 
+      * the translation is scaled by the scale factor and all of the matrix 
+      * values are modified. 
+      * @param t1 the translation amount
+      * @param scale the scale factor for the matrix
+      */
+    public final void set(Vector3f t1, float scale)
+    {
+       this.m00 = scale;
+       this.m01 = (float) 0.0;
+       this.m02 = (float) 0.0;
+       this.m03 = scale*t1.x;
+
+       this.m10 = (float) 0.0;
+       this.m11 = scale;
+       this.m12 = (float) 0.0;
+       this.m13 = scale*t1.y;
+
+       this.m20 = (float) 0.0;
+       this.m21 = (float) 0.0;
+       this.m22 = scale;
+       this.m23 = scale*t1.z;
+
+       this.m30 = (float) 0.0;
+       this.m31 = (float) 0.0;
+       this.m32 = (float) 0.0;
+       this.m33 = (float) 1.0;
+    }
+
+   /**
+     * Sets the value of this matrix from the rotation expressed by 
+     * the rotation matrix m1, the translation t1, and the scale factor.
+     * The translation is not modified by the scale.
+     * @param m1  the rotation component
+     * @param t1  the translation component
+     * @param scale  the scale component
+     */
+    public final void set(Matrix3f m1, Vector3f t1, float scale)
+    {
+        this.m00 = m1.m00*scale;
+        this.m01 = m1.m01*scale;
+        this.m02 = m1.m02*scale;
+        this.m03 = t1.x;
+
+        this.m10 = m1.m10*scale;
+        this.m11 = m1.m11*scale;
+        this.m12 = m1.m12*scale;
+        this.m13 = t1.y;
+
+        this.m20 = m1.m20*scale;
+        this.m21 = m1.m21*scale;
+        this.m22 = m1.m22*scale;
+        this.m23 = t1.z;
+
+        this.m30 = 0.0f;
+        this.m31 = 0.0f;
+        this.m32 = 0.0f;
+        this.m33 = 1.0f;
+    }
+
+   /**
+     * Sets the value of this matrix from the rotation expressed by
+     * the rotation matrix m1, the translation t1, and the scale factor.
+     * The translation is not modified by the scale.
+     * @param m1  the rotation component
+     * @param t1  the translation component
+     * @param scale  the scale factor
+     */
+    public final void set(Matrix3d m1, Vector3d t1, double scale)
+    {
+        this.m00 = (float)(m1.m00*scale);
+        this.m01 = (float)(m1.m01*scale);
+        this.m02 = (float)(m1.m02*scale);
+        this.m03 = (float)t1.x;
+
+        this.m10 = (float)(m1.m10*scale);
+        this.m11 = (float)(m1.m11*scale);
+        this.m12 = (float)(m1.m12*scale);
+        this.m13 = (float)t1.y;
+
+        this.m20 = (float)(m1.m20*scale);
+        this.m21 = (float)(m1.m21*scale);
+        this.m22 = (float)(m1.m22*scale);
+        this.m23 = (float)t1.z;
+
+        this.m30 = 0.0f;
+        this.m31 = 0.0f;
+        this.m32 = 0.0f;
+        this.m33 = 1.0f;
+    }
+
+   /**
+     * Modifies the translational components of this matrix to the values
+     * of the Vector3f argument; the other values of this matrix are not
+     * modified.
+     * @param trans  the translational component
+     */  
+    public final void setTranslation(Vector3f trans)
+    {
+       m03 = trans.x; 
+       m13 = trans.y;
+       m23 = trans.z;
+    }
+
+    /**
+     * Sets the value of this matrix to a counter clockwise rotation 
+     * about the x axis.
+     * @param angle the angle to rotate about the X axis in radians
+     */
+    public final void rotX(float angle)
+    {
+       float   sinAngle, cosAngle;
+
+       sinAngle = (float) Math.sin((double) angle);
+       cosAngle = (float) Math.cos((double) angle);
+
+       this.m00 = (float) 1.0;
+       this.m01 = (float) 0.0;
+       this.m02 = (float) 0.0;
+       this.m03 = (float) 0.0;
+
+       this.m10 = (float) 0.0;
+       this.m11 = cosAngle;
+       this.m12 = -sinAngle;
+       this.m13 = (float) 0.0;
+
+       this.m20 = (float) 0.0;
+       this.m21 = sinAngle;
+       this.m22 = cosAngle;
+       this.m23 = (float) 0.0;
+
+       this.m30 = (float) 0.0;
+       this.m31 = (float) 0.0;
+       this.m32 = (float) 0.0;
+       this.m33 = (float) 1.0;
+    }
+
+    /**
+     * Sets the value of this matrix to a counter clockwise rotation 
+     * about the y axis.
+     * @param angle the angle to rotate about the Y axis in radians
+     */
+    public final void rotY(float angle)
+    {
+       float   sinAngle, cosAngle;
+
+       sinAngle = (float) Math.sin((double) angle);
+       cosAngle = (float) Math.cos((double) angle);
+
+       this.m00 = cosAngle;
+       this.m01 = (float) 0.0;
+       this.m02 = sinAngle;
+       this.m03 = (float) 0.0;
+
+       this.m10 = (float) 0.0;
+       this.m11 = (float) 1.0;
+       this.m12 = (float) 0.0;
+       this.m13 = (float) 0.0;
+
+       this.m20 = -sinAngle;
+       this.m21 = (float) 0.0;
+       this.m22 = cosAngle;
+       this.m23 = (float) 0.0;
+
+       this.m30 = (float) 0.0;
+       this.m31 = (float) 0.0;
+       this.m32 = (float) 0.0;
+       this.m33 = (float) 1.0;
+    }
+
+    /**
+     * Sets the value of this matrix to a counter clockwise rotation 
+     * about the z axis.
+     * @param angle the angle to rotate about the Z axis in radians
+     */
+    public final void rotZ(float angle)
+    {
+       float   sinAngle, cosAngle;
+
+       sinAngle = (float) Math.sin((double) angle);
+       cosAngle = (float) Math.cos((double) angle);
+
+       this.m00 = cosAngle;
+       this.m01 = -sinAngle;
+       this.m02 = (float) 0.0;
+       this.m03 = (float) 0.0;
+
+       this.m10 = sinAngle;
+       this.m11 = cosAngle;
+       this.m12 = (float) 0.0;
+       this.m13 = (float) 0.0;
+
+       this.m20 = (float) 0.0;
+       this.m21 = (float) 0.0;
+       this.m22 = (float) 1.0;
+       this.m23 = (float) 0.0;
+
+       this.m30 = (float) 0.0;
+       this.m31 = (float) 0.0;
+       this.m32 = (float) 0.0;
+       this.m33 = (float) 1.0;
+    }
+
+   /**
+     * Multiplies each element of this matrix by a scalar.
+     * @param scalar  the scalar multiplier.
+     */
+    public final void mul(float scalar) 
+    { 
+      m00 *= scalar;
+      m01 *= scalar;
+      m02 *= scalar;
+      m03 *= scalar;
+      m10 *= scalar;
+      m11 *= scalar;
+      m12 *= scalar;
+      m13 *= scalar;
+      m20 *= scalar;
+      m21 *= scalar;
+      m22 *= scalar;
+      m23 *= scalar;
+      m30 *= scalar;
+      m31 *= scalar;
+      m32 *= scalar;
+      m33 *= scalar;
+    }
+
+   /**   
+     * Multiplies each element of matrix m1 by a scalar and places
+     * the result into this.  Matrix m1 is not modified.
+     * @param scalar  the scalar multiplier. 
+     * @param m1  the original matrix. 
+     */   
+    public final void mul(float scalar, Matrix4f m1)
+    {
+      this.m00 = m1.m00 * scalar;
+      this.m01 = m1.m01 * scalar;
+      this.m02 = m1.m02 * scalar;
+      this.m03 = m1.m03 * scalar;
+      this.m10 = m1.m10 * scalar;
+      this.m11 = m1.m11 * scalar;
+      this.m12 = m1.m12 * scalar;
+      this.m13 = m1.m13 * scalar;
+      this.m20 = m1.m20 * scalar;
+      this.m21 = m1.m21 * scalar;
+      this.m22 = m1.m22 * scalar;
+      this.m23 = m1.m23 * scalar;
+      this.m30 = m1.m30 * scalar;
+      this.m31 = m1.m31 * scalar;
+      this.m32 = m1.m32 * scalar;
+      this.m33 = m1.m33 * scalar;
+    } 
+
+    /**
+     * Sets the value of this matrix to the result of multiplying itself
+     * with matrix m1.
+     * @param m1 the other matrix
+     */
+    public final void mul(Matrix4f m1) 
+    {
+        float       m00, m01, m02, m03,
+                    m10, m11, m12, m13,
+                    m20, m21, m22, m23,
+                    m30, m31, m32, m33;  // vars for temp result matrix
+
+        m00 = this.m00*m1.m00 + this.m01*m1.m10 + 
+              this.m02*m1.m20 + this.m03*m1.m30;
+        m01 = this.m00*m1.m01 + this.m01*m1.m11 + 
+              this.m02*m1.m21 + this.m03*m1.m31;
+        m02 = this.m00*m1.m02 + this.m01*m1.m12 + 
+              this.m02*m1.m22 + this.m03*m1.m32;
+        m03 = this.m00*m1.m03 + this.m01*m1.m13 + 
+              this.m02*m1.m23 + this.m03*m1.m33;
+
+        m10 = this.m10*m1.m00 + this.m11*m1.m10 + 
+              this.m12*m1.m20 + this.m13*m1.m30; 
+        m11 = this.m10*m1.m01 + this.m11*m1.m11 + 
+              this.m12*m1.m21 + this.m13*m1.m31;
+        m12 = this.m10*m1.m02 + this.m11*m1.m12 + 
+              this.m12*m1.m22 + this.m13*m1.m32;
+        m13 = this.m10*m1.m03 + this.m11*m1.m13 + 
+              this.m12*m1.m23 + this.m13*m1.m33;
+
+        m20 = this.m20*m1.m00 + this.m21*m1.m10 + 
+              this.m22*m1.m20 + this.m23*m1.m30; 
+        m21 = this.m20*m1.m01 + this.m21*m1.m11 + 
+              this.m22*m1.m21 + this.m23*m1.m31;
+        m22 = this.m20*m1.m02 + this.m21*m1.m12 + 
+              this.m22*m1.m22 + this.m23*m1.m32;
+        m23 = this.m20*m1.m03 + this.m21*m1.m13 + 
+              this.m22*m1.m23 + this.m23*m1.m33;
+
+        m30 = this.m30*m1.m00 + this.m31*m1.m10 + 
+              this.m32*m1.m20 + this.m33*m1.m30; 
+        m31 = this.m30*m1.m01 + this.m31*m1.m11 + 
+              this.m32*m1.m21 + this.m33*m1.m31;
+        m32 = this.m30*m1.m02 + this.m31*m1.m12 + 
+              this.m32*m1.m22 + this.m33*m1.m32;
+        m33 = this.m30*m1.m03 + this.m31*m1.m13 + 
+              this.m32*m1.m23 + this.m33*m1.m33;
+        this.m00 = m00; this.m01 = m01; this.m02 = m02; this.m03 = m03;
+        this.m10 = m10; this.m11 = m11; this.m12 = m12; this.m13 = m13;
+        this.m20 = m20; this.m21 = m21; this.m22 = m22; this.m23 = m23;
+        this.m30 = m30; this.m31 = m31; this.m32 = m32; this.m33 = m33;
+    }
+
+    /**
+     * Sets the value of this matrix to the result of multiplying
+     * the two argument matrices together.
+     * @param m1 the first matrix
+     * @param m2 the second matrix
+     */
+    public final void mul(Matrix4f m1, Matrix4f m2)
+    {
+       if (this != m1 && this != m2) {
+
+            this.m00 = m1.m00*m2.m00 + m1.m01*m2.m10 + 
+                       m1.m02*m2.m20 + m1.m03*m2.m30;
+            this.m01 = m1.m00*m2.m01 + m1.m01*m2.m11 + 
+                       m1.m02*m2.m21 + m1.m03*m2.m31;
+            this.m02 = m1.m00*m2.m02 + m1.m01*m2.m12 + 
+                       m1.m02*m2.m22 + m1.m03*m2.m32;
+            this.m03 = m1.m00*m2.m03 + m1.m01*m2.m13 + 
+                       m1.m02*m2.m23 + m1.m03*m2.m33;
+
+            this.m10 = m1.m10*m2.m00 + m1.m11*m2.m10 + 
+                       m1.m12*m2.m20 + m1.m13*m2.m30;
+            this.m11 = m1.m10*m2.m01 + m1.m11*m2.m11 + 
+                       m1.m12*m2.m21 + m1.m13*m2.m31;
+            this.m12 = m1.m10*m2.m02 + m1.m11*m2.m12 + 
+                       m1.m12*m2.m22 + m1.m13*m2.m32;
+            this.m13 = m1.m10*m2.m03 + m1.m11*m2.m13 + 
+                       m1.m12*m2.m23 + m1.m13*m2.m33;
+
+            this.m20 = m1.m20*m2.m00 + m1.m21*m2.m10 + 
+                       m1.m22*m2.m20 + m1.m23*m2.m30;
+            this.m21 = m1.m20*m2.m01 + m1.m21*m2.m11 + 
+                       m1.m22*m2.m21 + m1.m23*m2.m31;
+            this.m22 = m1.m20*m2.m02 + m1.m21*m2.m12 + 
+                       m1.m22*m2.m22 + m1.m23*m2.m32;
+            this.m23 = m1.m20*m2.m03 + m1.m21*m2.m13 + 
+                       m1.m22*m2.m23 + m1.m23*m2.m33;
+
+            this.m30 = m1.m30*m2.m00 + m1.m31*m2.m10 + 
+                       m1.m32*m2.m20 + m1.m33*m2.m30;
+            this.m31 = m1.m30*m2.m01 + m1.m31*m2.m11 + 
+                       m1.m32*m2.m21 + m1.m33*m2.m31;
+            this.m32 = m1.m30*m2.m02 + m1.m31*m2.m12 + 
+                       m1.m32*m2.m22 + m1.m33*m2.m32;
+            this.m33 = m1.m30*m2.m03 + m1.m31*m2.m13 + 
+                       m1.m32*m2.m23 + m1.m33*m2.m33;
+       } else {
+           float       m00, m01, m02, m03,
+                       m10, m11, m12, m13,
+                       m20, m21, m22, m23,
+                       m30, m31, m32, m33;  // vars for temp result matrix
+            m00 = m1.m00*m2.m00 + m1.m01*m2.m10 + m1.m02*m2.m20 + m1.m03*m2.m30;
+            m01 = m1.m00*m2.m01 + m1.m01*m2.m11 + m1.m02*m2.m21 + m1.m03*m2.m31;
+            m02 = m1.m00*m2.m02 + m1.m01*m2.m12 + m1.m02*m2.m22 + m1.m03*m2.m32;
+            m03 = m1.m00*m2.m03 + m1.m01*m2.m13 + m1.m02*m2.m23 + m1.m03*m2.m33;
+            m10 = m1.m10*m2.m00 + m1.m11*m2.m10 + m1.m12*m2.m20 + m1.m13*m2.m30;
+            m11 = m1.m10*m2.m01 + m1.m11*m2.m11 + m1.m12*m2.m21 + m1.m13*m2.m31;
+            m12 = m1.m10*m2.m02 + m1.m11*m2.m12 + m1.m12*m2.m22 + m1.m13*m2.m32;
+            m13 = m1.m10*m2.m03 + m1.m11*m2.m13 + m1.m12*m2.m23 + m1.m13*m2.m33;
+            m20 = m1.m20*m2.m00 + m1.m21*m2.m10 + m1.m22*m2.m20 + m1.m23*m2.m30;
+            m21 = m1.m20*m2.m01 + m1.m21*m2.m11 + m1.m22*m2.m21 + m1.m23*m2.m31;
+            m22 = m1.m20*m2.m02 + m1.m21*m2.m12 + m1.m22*m2.m22 + m1.m23*m2.m32;
+            m23 = m1.m20*m2.m03 + m1.m21*m2.m13 + m1.m22*m2.m23 + m1.m23*m2.m33;
+            m30 = m1.m30*m2.m00 + m1.m31*m2.m10 + m1.m32*m2.m20 + m1.m33*m2.m30;
+            m31 = m1.m30*m2.m01 + m1.m31*m2.m11 + m1.m32*m2.m21 + m1.m33*m2.m31;
+            m32 = m1.m30*m2.m02 + m1.m31*m2.m12 + m1.m32*m2.m22 + m1.m33*m2.m32;
+            m33 = m1.m30*m2.m03 + m1.m31*m2.m13 + m1.m32*m2.m23 + m1.m33*m2.m33;
+
+            this.m00 = m00; this.m01 = m01; this.m02 = m02; this.m03 = m03;
+            this.m10 = m10; this.m11 = m11; this.m12 = m12; this.m13 = m13;
+            this.m20 = m20; this.m21 = m21; this.m22 = m22; this.m23 = m23;
+            this.m30 = m30; this.m31 = m31; this.m32 = m32; this.m33 = m33;
+       }
+    }
+
+   /**
+     *  Multiplies the transpose of matrix m1 times the transpose of matrix
+     *  m2, and places the result into this.
+     *  @param m1  the matrix on the left hand side of the multiplication
+     *  @param m2  the matrix on the right hand side of the multiplication
+     */  
+    public final void mulTransposeBoth(Matrix4f m1, Matrix4f m2)
+    {
+        if (this != m1 && this != m2) {
+            this.m00 = m1.m00*m2.m00 + m1.m10*m2.m01 + m1.m20*m2.m02 + m1.m30*m2.m03;
+            this.m01 = m1.m00*m2.m10 + m1.m10*m2.m11 + m1.m20*m2.m12 + m1.m30*m2.m13;
+            this.m02 = m1.m00*m2.m20 + m1.m10*m2.m21 + m1.m20*m2.m22 + m1.m30*m2.m23;
+            this.m03 = m1.m00*m2.m30 + m1.m10*m2.m31 + m1.m20*m2.m32 + m1.m30*m2.m33;
+
+            this.m10 = m1.m01*m2.m00 + m1.m11*m2.m01 + m1.m21*m2.m02 + m1.m31*m2.m03;
+            this.m11 = m1.m01*m2.m10 + m1.m11*m2.m11 + m1.m21*m2.m12 + m1.m31*m2.m13;
+            this.m12 = m1.m01*m2.m20 + m1.m11*m2.m21 + m1.m21*m2.m22 + m1.m31*m2.m23;
+            this.m13 = m1.m01*m2.m30 + m1.m11*m2.m31 + m1.m21*m2.m32 + m1.m31*m2.m33;
+
+            this.m20 = m1.m02*m2.m00 + m1.m12*m2.m01 + m1.m22*m2.m02 + m1.m32*m2.m03;
+            this.m21 = m1.m02*m2.m10 + m1.m12*m2.m11 + m1.m22*m2.m12 + m1.m32*m2.m13;
+            this.m22 = m1.m02*m2.m20 + m1.m12*m2.m21 + m1.m22*m2.m22 + m1.m32*m2.m23;
+            this.m23 = m1.m02*m2.m30 + m1.m12*m2.m31 + m1.m22*m2.m32 + m1.m32*m2.m33;
+
+            this.m30 = m1.m03*m2.m00 + m1.m13*m2.m01 + m1.m23*m2.m02 + m1.m33*m2.m03;
+            this.m31 = m1.m03*m2.m10 + m1.m13*m2.m11 + m1.m23*m2.m12 + m1.m33*m2.m13;
+            this.m32 = m1.m03*m2.m20 + m1.m13*m2.m21 + m1.m23*m2.m22 + m1.m33*m2.m23;
+            this.m33 = m1.m03*m2.m30 + m1.m13*m2.m31 + m1.m23*m2.m32 + m1.m33*m2.m33;
+        } else {
+            float       m00, m01, m02, m03,
+                        m10, m11, m12, m13,
+                        m20, m21, m22, m23,  // vars for temp result matrix
+                        m30, m31, m32, m33;
+         
+            m00 = m1.m00*m2.m00 + m1.m10*m2.m01 + m1.m20*m2.m02 + m1.m30*m2.m03;
+            m01 = m1.m00*m2.m10 + m1.m10*m2.m11 + m1.m20*m2.m12 + m1.m30*m2.m13;
+            m02 = m1.m00*m2.m20 + m1.m10*m2.m21 + m1.m20*m2.m22 + m1.m30*m2.m23;
+            m03 = m1.m00*m2.m30 + m1.m10*m2.m31 + m1.m20*m2.m32 + m1.m30*m2.m33;
+            m10 = m1.m01*m2.m00 + m1.m11*m2.m01 + m1.m21*m2.m02 + m1.m31*m2.m03;
+            m11 = m1.m01*m2.m10 + m1.m11*m2.m11 + m1.m21*m2.m12 + m1.m31*m2.m13;
+            m12 = m1.m01*m2.m20 + m1.m11*m2.m21 + m1.m21*m2.m22 + m1.m31*m2.m23;
+            m13 = m1.m01*m2.m30 + m1.m11*m2.m31 + m1.m21*m2.m32 + m1.m31*m2.m33;
+            m20 = m1.m02*m2.m00 + m1.m12*m2.m01 + m1.m22*m2.m02 + m1.m32*m2.m03;
+            m21 = m1.m02*m2.m10 + m1.m12*m2.m11 + m1.m22*m2.m12 + m1.m32*m2.m13;
+            m22 = m1.m02*m2.m20 + m1.m12*m2.m21 + m1.m22*m2.m22 + m1.m32*m2.m23;
+            m23 = m1.m02*m2.m30 + m1.m12*m2.m31 + m1.m22*m2.m32 + m1.m32*m2.m33;
+            m30 = m1.m03*m2.m00 + m1.m13*m2.m01 + m1.m23*m2.m02 + m1.m33*m2.m03;
+            m31 = m1.m03*m2.m10 + m1.m13*m2.m11 + m1.m23*m2.m12 + m1.m33*m2.m13;
+            m32 = m1.m03*m2.m20 + m1.m13*m2.m21 + m1.m23*m2.m22 + m1.m33*m2.m23;
+            m33 = m1.m03*m2.m30 + m1.m13*m2.m31 + m1.m23*m2.m32 + m1.m33*m2.m33;
+            this.m00 = m00; this.m01 = m01; this.m02 = m02; this.m03 = m03;
+            this.m10 = m10; this.m11 = m11; this.m12 = m12; this.m13 = m13;
+            this.m20 = m20; this.m21 = m21; this.m22 = m22; this.m23 = m23;
+            this.m30 = m30; this.m31 = m31; this.m32 = m32; this.m33 = m33;
+        }
+
+    }
+
+   /**
+     *  Multiplies matrix m1 times the transpose of matrix m2, and
+     *  places the result into this.
+     *  @param m1  the matrix on the left hand side of the multiplication
+     *  @param m2  the matrix on the right hand side of the multiplication
+     */
+    public final void mulTransposeRight(Matrix4f m1, Matrix4f m2)
+    {  
+    if (this != m1 && this != m2) {
+      this.m00 = m1.m00*m2.m00 + m1.m01*m2.m01 + m1.m02*m2.m02 + m1.m03*m2.m03;
+      this.m01 = m1.m00*m2.m10 + m1.m01*m2.m11 + m1.m02*m2.m12 + m1.m03*m2.m13;
+      this.m02 = m1.m00*m2.m20 + m1.m01*m2.m21 + m1.m02*m2.m22 + m1.m03*m2.m23;
+      this.m03 = m1.m00*m2.m30 + m1.m01*m2.m31 + m1.m02*m2.m32 + m1.m03*m2.m33;
+         
+      this.m10 = m1.m10*m2.m00 + m1.m11*m2.m01 + m1.m12*m2.m02 + m1.m13*m2.m03;
+      this.m11 = m1.m10*m2.m10 + m1.m11*m2.m11 + m1.m12*m2.m12 + m1.m13*m2.m13;
+      this.m12 = m1.m10*m2.m20 + m1.m11*m2.m21 + m1.m12*m2.m22 + m1.m13*m2.m23;
+      this.m13 = m1.m10*m2.m30 + m1.m11*m2.m31 + m1.m12*m2.m32 + m1.m13*m2.m33;
+         
+      this.m20 = m1.m20*m2.m00 + m1.m21*m2.m01 + m1.m22*m2.m02 + m1.m23*m2.m03;
+      this.m21 = m1.m20*m2.m10 + m1.m21*m2.m11 + m1.m22*m2.m12 + m1.m23*m2.m13;
+      this.m22 = m1.m20*m2.m20 + m1.m21*m2.m21 + m1.m22*m2.m22 + m1.m23*m2.m23;
+      this.m23 = m1.m20*m2.m30 + m1.m21*m2.m31 + m1.m22*m2.m32 + m1.m23*m2.m33;
+         
+      this.m30 = m1.m30*m2.m00 + m1.m31*m2.m01 + m1.m32*m2.m02 + m1.m33*m2.m03;
+      this.m31 = m1.m30*m2.m10 + m1.m31*m2.m11 + m1.m32*m2.m12 + m1.m33*m2.m13;
+      this.m32 = m1.m30*m2.m20 + m1.m31*m2.m21 + m1.m32*m2.m22 + m1.m33*m2.m23;
+      this.m33 = m1.m30*m2.m30 + m1.m31*m2.m31 + m1.m32*m2.m32 + m1.m33*m2.m33;
+    } else {
+            float       m00, m01, m02, m03,
+                        m10, m11, m12, m13,
+                        m20, m21, m22, m23,  // vars for temp result matrix
+                        m30, m31, m32, m33;
+      m00 = m1.m00*m2.m00 + m1.m01*m2.m01 + m1.m02*m2.m02 + m1.m03*m2.m03;
+      m01 = m1.m00*m2.m10 + m1.m01*m2.m11 + m1.m02*m2.m12 + m1.m03*m2.m13;
+      m02 = m1.m00*m2.m20 + m1.m01*m2.m21 + m1.m02*m2.m22 + m1.m03*m2.m23;
+      m03 = m1.m00*m2.m30 + m1.m01*m2.m31 + m1.m02*m2.m32 + m1.m03*m2.m33;
+         
+      m10 = m1.m10*m2.m00 + m1.m11*m2.m01 + m1.m12*m2.m02 + m1.m13*m2.m03;
+      m11 = m1.m10*m2.m10 + m1.m11*m2.m11 + m1.m12*m2.m12 + m1.m13*m2.m13;
+      m12 = m1.m10*m2.m20 + m1.m11*m2.m21 + m1.m12*m2.m22 + m1.m13*m2.m23;
+      m13 = m1.m10*m2.m30 + m1.m11*m2.m31 + m1.m12*m2.m32 + m1.m13*m2.m33;
+         
+      m20 = m1.m20*m2.m00 + m1.m21*m2.m01 + m1.m22*m2.m02 + m1.m23*m2.m03;
+      m21 = m1.m20*m2.m10 + m1.m21*m2.m11 + m1.m22*m2.m12 + m1.m23*m2.m13;
+      m22 = m1.m20*m2.m20 + m1.m21*m2.m21 + m1.m22*m2.m22 + m1.m23*m2.m23;
+      m23 = m1.m20*m2.m30 + m1.m21*m2.m31 + m1.m22*m2.m32 + m1.m23*m2.m33;
+      m30 = m1.m30*m2.m00 + m1.m31*m2.m01 + m1.m32*m2.m02 + m1.m33*m2.m03;
+      m31 = m1.m30*m2.m10 + m1.m31*m2.m11 + m1.m32*m2.m12 + m1.m33*m2.m13;
+      m32 = m1.m30*m2.m20 + m1.m31*m2.m21 + m1.m32*m2.m22 + m1.m33*m2.m23;
+      m33 = m1.m30*m2.m30 + m1.m31*m2.m31 + m1.m32*m2.m32 + m1.m33*m2.m33;
+         
+      this.m00 = m00; this.m01 = m01; this.m02 = m02; this.m03 = m03;
+      this.m10 = m10; this.m11 = m11; this.m12 = m12; this.m13 = m13;
+      this.m20 = m20; this.m21 = m21; this.m22 = m22; this.m23 = m23;
+      this.m30 = m30; this.m31 = m31; this.m32 = m32; this.m33 = m33;
+    }
+
+    }
+   /**   
+     *  Multiplies the transpose of matrix m1 times matrix m2, and
+     *  places the result into this.
+     *  @param m1  the matrix on the left hand side of the multiplication
+     *  @param m2  the matrix on the right hand side of the multiplication
+     */
+    public final void mulTransposeLeft(Matrix4f m1, Matrix4f m2)
+    {  
+    if (this != m1 && this != m2) {
+      this.m00 = m1.m00*m2.m00 + m1.m10*m2.m10 + m1.m20*m2.m20 + m1.m30*m2.m30;
+      this.m01 = m1.m00*m2.m01 + m1.m10*m2.m11 + m1.m20*m2.m21 + m1.m30*m2.m31;
+      this.m02 = m1.m00*m2.m02 + m1.m10*m2.m12 + m1.m20*m2.m22 + m1.m30*m2.m32;
+      this.m03 = m1.m00*m2.m03 + m1.m10*m2.m13 + m1.m20*m2.m23 + m1.m30*m2.m33;
+                 
+      this.m10 = m1.m01*m2.m00 + m1.m11*m2.m10 + m1.m21*m2.m20 + m1.m31*m2.m30;
+      this.m11 = m1.m01*m2.m01 + m1.m11*m2.m11 + m1.m21*m2.m21 + m1.m31*m2.m31;
+      this.m12 = m1.m01*m2.m02 + m1.m11*m2.m12 + m1.m21*m2.m22 + m1.m31*m2.m32;
+      this.m13 = m1.m01*m2.m03 + m1.m11*m2.m13 + m1.m21*m2.m23 + m1.m31*m2.m33;
+                 
+      this.m20 = m1.m02*m2.m00 + m1.m12*m2.m10 + m1.m22*m2.m20 + m1.m32*m2.m30;
+      this.m21 = m1.m02*m2.m01 + m1.m12*m2.m11 + m1.m22*m2.m21 + m1.m32*m2.m31;
+      this.m22 = m1.m02*m2.m02 + m1.m12*m2.m12 + m1.m22*m2.m22 + m1.m32*m2.m32;
+      this.m23 = m1.m02*m2.m03 + m1.m12*m2.m13 + m1.m22*m2.m23 + m1.m32*m2.m33;
+                 
+      this.m30 = m1.m03*m2.m00 + m1.m13*m2.m10 + m1.m23*m2.m20 + m1.m33*m2.m30;
+      this.m31 = m1.m03*m2.m01 + m1.m13*m2.m11 + m1.m23*m2.m21 + m1.m33*m2.m31;
+      this.m32 = m1.m03*m2.m02 + m1.m13*m2.m12 + m1.m23*m2.m22 + m1.m33*m2.m32;
+      this.m33 = m1.m03*m2.m03 + m1.m13*m2.m13 + m1.m23*m2.m23 + m1.m33*m2.m33;
+    } else {
+            float       m00, m01, m02, m03,
+                        m10, m11, m12, m13,
+                        m20, m21, m22, m23,  // vars for temp result matrix
+                        m30, m31, m32, m33;
+      
+
+      m00 = m1.m00*m2.m00 + m1.m10*m2.m10 + m1.m20*m2.m20 + m1.m30*m2.m30;
+      m01 = m1.m00*m2.m01 + m1.m10*m2.m11 + m1.m20*m2.m21 + m1.m30*m2.m31;
+      m02 = m1.m00*m2.m02 + m1.m10*m2.m12 + m1.m20*m2.m22 + m1.m30*m2.m32;
+      m03 = m1.m00*m2.m03 + m1.m10*m2.m13 + m1.m20*m2.m23 + m1.m30*m2.m33;
+                 
+      m10 = m1.m01*m2.m00 + m1.m11*m2.m10 + m1.m21*m2.m20 + m1.m31*m2.m30;
+      m11 = m1.m01*m2.m01 + m1.m11*m2.m11 + m1.m21*m2.m21 + m1.m31*m2.m31;
+      m12 = m1.m01*m2.m02 + m1.m11*m2.m12 + m1.m21*m2.m22 + m1.m31*m2.m32;
+      m13 = m1.m01*m2.m03 + m1.m11*m2.m13 + m1.m21*m2.m23 + m1.m31*m2.m33;
+                 
+      m20 = m1.m02*m2.m00 + m1.m12*m2.m10 + m1.m22*m2.m20 + m1.m32*m2.m30;
+      m21 = m1.m02*m2.m01 + m1.m12*m2.m11 + m1.m22*m2.m21 + m1.m32*m2.m31;
+      m22 = m1.m02*m2.m02 + m1.m12*m2.m12 + m1.m22*m2.m22 + m1.m32*m2.m32;
+      m23 = m1.m02*m2.m03 + m1.m12*m2.m13 + m1.m22*m2.m23 + m1.m32*m2.m33;
+                 
+      m30 = m1.m03*m2.m00 + m1.m13*m2.m10 + m1.m23*m2.m20 + m1.m33*m2.m30;
+      m31 = m1.m03*m2.m01 + m1.m13*m2.m11 + m1.m23*m2.m21 + m1.m33*m2.m31;
+      m32 = m1.m03*m2.m02 + m1.m13*m2.m12 + m1.m23*m2.m22 + m1.m33*m2.m32;
+      m33 = m1.m03*m2.m03 + m1.m13*m2.m13 + m1.m23*m2.m23 + m1.m33*m2.m33;
+
+      this.m00 = m00; this.m01 = m01; this.m02 = m02; this.m03 = m03;
+      this.m10 = m10; this.m11 = m11; this.m12 = m12; this.m13 = m13;
+      this.m20 = m20; this.m21 = m21; this.m22 = m22; this.m23 = m23;
+      this.m30 = m30; this.m31 = m31; this.m32 = m32; this.m33 = m33;
+    }
+
+    }
+
+   /**
+     * Returns true if all of the data members of Matrix4f m1 are
+     * equal to the corresponding data members in this Matrix4f.
+     * @param m1  the matrix with which the comparison is made.
+     * @return  true or false
+     */  
+    public boolean equals(Matrix4f m1)
+    {
+      try {
+        return(this.m00 == m1.m00 && this.m01 == m1.m01 && this.m02 == m1.m02
+            && this.m03 == m1.m03 && this.m10 == m1.m10 && this.m11 == m1.m11 
+            && this.m12 == m1.m12 && this.m13 == m1.m13 && this.m20 == m1.m20 
+            && this.m21 == m1.m21 && this.m22 == m1.m22 && this.m23 == m1.m23
+            && this.m30 == m1.m30 && this.m31 == m1.m31 && this.m32 == m1.m32
+            && this.m33 == m1.m33);
+      }  
+      catch (NullPointerException e2) { return false; }
+
+    }
+
+   /**   
+     * Returns true if the Object t1 is of type Matrix4f and all of the
+     * data members of t1 are equal to the corresponding data members in
+     * this Matrix4f.
+     * @param t1  the matrix with which the comparison is made.
+     * @return  true or false
+     */  
+    public boolean equals(Object t1)
+    {
+        try {    
+           Matrix4f m2 = (Matrix4f) t1;
+           return(this.m00 == m2.m00 && this.m01 == m2.m01 && this.m02 == m2.m02
+             && this.m03 == m2.m03 && this.m10 == m2.m10 && this.m11 == m2.m11
+             && this.m12 == m2.m12 && this.m13 == m2.m13 && this.m20 == m2.m20
+             && this.m21 == m2.m21 && this.m22 == m2.m22 && this.m23 == m2.m23
+             && this.m30 == m2.m30 && this.m31 == m2.m31 && this.m32 == m2.m32
+             && this.m33 == m2.m33);
+        }
+        catch (ClassCastException   e1) { return false; }
+        catch (NullPointerException e2) { return false; }
+    }
+
+   /**   
+     * Returns true if the L-infinite distance between this matrix
+     * and matrix m1 is less than or equal to the epsilon parameter,
+     * otherwise returns false.  The L-infinite
+     * distance is equal to 
+     * MAX[i=0,1,2,3 ; j=0,1,2,3 ; abs(this.m(i,j) - m1.m(i,j)]
+     * @param m1  the matrix to be compared to this matrix
+     * @param epsilon  the threshold value  
+     */  
+    public boolean epsilonEquals(Matrix4f m1, float epsilon)
+    {
+
+        boolean status = true;
+
+        if( Math.abs( this.m00 - m1.m00) > epsilon) status = false;
+        if( Math.abs( this.m01 - m1.m01) > epsilon) status = false;
+        if( Math.abs( this.m02 - m1.m02) > epsilon) status = false;
+        if( Math.abs( this.m03 - m1.m03) > epsilon) status = false;
+
+        if( Math.abs( this.m10 - m1.m10) > epsilon) status = false;
+        if( Math.abs( this.m11 - m1.m11) > epsilon) status = false;
+        if( Math.abs( this.m12 - m1.m12) > epsilon) status = false;
+        if( Math.abs( this.m13 - m1.m13) > epsilon) status = false;
+
+        if( Math.abs( this.m20 - m1.m20) > epsilon) status = false;
+        if( Math.abs( this.m21 - m1.m21) > epsilon) status = false;
+        if( Math.abs( this.m22 - m1.m22) > epsilon) status = false;
+        if( Math.abs( this.m23 - m1.m23) > epsilon) status = false;
+
+        if( Math.abs( this.m30 - m1.m30) > epsilon) status = false;
+        if( Math.abs( this.m31 - m1.m31) > epsilon) status = false;
+        if( Math.abs( this.m32 - m1.m32) > epsilon) status = false;
+        if( Math.abs( this.m33 - m1.m33) > epsilon) status = false;
+
+        return( status );
+
+    }
+
+
+    /**
+     * Returns a hash code value based on the data values in this
+     * object.  Two different Matrix4f objects with identical data values
+     * (i.e., Matrix4f.equals returns true) will return the same hash
+     * code value.  Two objects with different data members may return the
+     * same hash value, although this is not likely.
+     * @return the integer hash code value
+     */  
+    public int hashCode() {
+       long bits = 1L;
+       bits = 31L * bits + (long)VecMathUtil.floatToIntBits(m00);
+       bits = 31L * bits + (long)VecMathUtil.floatToIntBits(m01);
+       bits = 31L * bits + (long)VecMathUtil.floatToIntBits(m02);
+       bits = 31L * bits + (long)VecMathUtil.floatToIntBits(m03);
+       bits = 31L * bits + (long)VecMathUtil.floatToIntBits(m10);
+       bits = 31L * bits + (long)VecMathUtil.floatToIntBits(m11);
+       bits = 31L * bits + (long)VecMathUtil.floatToIntBits(m12);
+       bits = 31L * bits + (long)VecMathUtil.floatToIntBits(m13);
+       bits = 31L * bits + (long)VecMathUtil.floatToIntBits(m20);
+       bits = 31L * bits + (long)VecMathUtil.floatToIntBits(m21);
+       bits = 31L * bits + (long)VecMathUtil.floatToIntBits(m22);
+       bits = 31L * bits + (long)VecMathUtil.floatToIntBits(m23);
+       bits = 31L * bits + (long)VecMathUtil.floatToIntBits(m30);
+       bits = 31L * bits + (long)VecMathUtil.floatToIntBits(m31);
+       bits = 31L * bits + (long)VecMathUtil.floatToIntBits(m32);
+       bits = 31L * bits + (long)VecMathUtil.floatToIntBits(m33);
+       return (int) (bits ^ (bits >> 32));
+    }
+
+
+  /**
+   * Transform the vector vec using this Matrix4f and place the
+   * result into vecOut.
+   * @param vec  the single precision vector to be transformed
+   * @param vecOut  the vector into which the transformed values are placed
+   */
+    public final void transform(Tuple4f vec, Tuple4f vecOut)
+    {
+           float x,y,z;
+           x = m00*vec.x + m01*vec.y
+                     + m02*vec.z + m03*vec.w;
+           y = m10*vec.x + m11*vec.y
+                     + m12*vec.z + m13*vec.w;
+           z = m20*vec.x + m21*vec.y
+                     + m22*vec.z + m23*vec.w;
+           vecOut.w = m30*vec.x + m31*vec.y
+                      + m32*vec.z + m33*vec.w;
+           vecOut.x = x;
+           vecOut.y = y;
+           vecOut.z = z;
+    }
+  /**
+   * Transform the vector vec using this Transform and place the
+   * result back into vec.
+   * @param vec  the single precision vector to be transformed
+   */
+    public final void transform(Tuple4f vec)
+    {
+         float x,y,z;
+           x = m00*vec.x + m01*vec.y
+                   + m02*vec.z + m03*vec.w;
+           y = m10*vec.x + m11*vec.y
+                     + m12*vec.z + m13*vec.w;
+           z = m20*vec.x + m21*vec.y
+                     + m22*vec.z + m23*vec.w;
+           vec.w = m30*vec.x + m31*vec.y
+                      + m32*vec.z + m33*vec.w;
+           vec.x = x;
+           vec.y = y;
+           vec.z = z;
+    }
+
+  /**
+   * Transforms the point parameter with this Matrix4f and
+   * places the result into pointOut.  The fourth element of the
+   * point input paramter is assumed to be one.
+   * @param point  the input point to be transformed.
+   * @param pointOut  the transformed point
+   */
+    public final void transform(Point3f point, Point3f pointOut)
+    {
+        float x,y;
+        x = m00*point.x + m01*point.y + m02*point.z + m03;
+        y = m10*point.x + m11*point.y + m12*point.z + m13;
+        pointOut.z = m20*point.x + m21*point.y + m22*point.z + m23;
+        pointOut.x = x;
+        pointOut.y = y;
+    }
+      
+  /**
+   * Transforms the point parameter with this Matrix4f and
+   * places the result back into point.  The fourth element of the
+   * point input paramter is assumed to be one.
+   * @param point  the input point to be transformed.
+   */
+    public final void transform(Point3f point)
+    {
+        float  x, y;
+        x = m00*point.x + m01*point.y + m02*point.z + m03;
+        y = m10*point.x + m11*point.y + m12*point.z + m13;
+        point.z =  m20*point.x + m21*point.y + m22*point.z + m23;
+        point.x = x;
+        point.y = y;
+    }
+
+  /**
+   * Transforms the normal parameter by this Matrix4f and places the value
+   * into normalOut.  The fourth element of the normal is assumed to be zero.
+   * @param normal   the input normal to be transformed.
+   * @param normalOut  the transformed normal
+   */
+    public final void transform(Vector3f normal, Vector3f normalOut)
+    {
+        float x,y;
+        x =  m00*normal.x + m01*normal.y + m02*normal.z;
+        y =  m10*normal.x + m11*normal.y + m12*normal.z;
+        normalOut.z =  m20*normal.x + m21*normal.y + m22*normal.z;
+        normalOut.x = x;
+        normalOut.y = y;
+    }
+
+      
+  /**
+   * Transforms the normal parameter by this transform and places the value
+   * back into normal.  The fourth element of the normal is assumed to be zero.
+   * @param normal   the input normal to be transformed.
+   */
+    public final void transform(Vector3f normal)
+    {
+        float x, y;
+
+        x =  m00*normal.x + m01*normal.y + m02*normal.z;
+        y =  m10*normal.x + m11*normal.y + m12*normal.z;
+        normal.z =  m20*normal.x + m21*normal.y + m22*normal.z;
+        normal.x = x;
+        normal.y = y;
+    }
+
+  
+   /**
+     * Sets the rotational component (upper 3x3) of this matrix to the
+     * matrix values in the double precision Matrix3d argument; the other
+     * elements of this matrix are unchanged; a singular value   
+     * decomposition is performed on this object's upper 3x3 matrix to 
+     * factor out the scale, then this object's upper 3x3 matrix components
+     * are replaced by the passed rotation components,   
+     * and then the scale is reapplied to the rotational components. 
+     * @param m1   double precision 3x3 matrix
+     */  
+   public final void setRotation( Matrix3d m1)
+   {
+       double[]    tmp_rot = new double[9];  // scratch matrix
+       double[]    tmp_scale = new double[3];  // scratch matrix
+       getScaleRotate( tmp_scale, tmp_rot );
+
+        m00 = (float)(m1.m00*tmp_scale[0]);
+        m01 = (float)(m1.m01*tmp_scale[1]);
+        m02 = (float)(m1.m02*tmp_scale[2]);
+
+        m10 = (float)(m1.m10*tmp_scale[0]);
+        m11 = (float)(m1.m11*tmp_scale[1]);
+        m12 = (float)(m1.m12*tmp_scale[2]);
+
+        m20 = (float)(m1.m20*tmp_scale[0]);
+        m21 = (float)(m1.m21*tmp_scale[1]);
+        m22 = (float)(m1.m22*tmp_scale[2]);
+
+   }
+
+   /**
+     * Sets the rotational component (upper 3x3) of this matrix to the
+     * matrix values in the single precision Matrix3f argument; the other
+     * elements of this matrix are unchanged; a singular value
+     * decomposition is performed on this object's upper 3x3 matrix to
+     * factor out the scale, then this object's upper 3x3 matrix components
+     * are replaced by the passed rotation components,  
+     * and then the scale is reapplied to the rotational components.
+     * @param m1   single precision 3x3 matrix
+     */  
+   public final void setRotation( Matrix3f m1){
+       double[]    tmp_rot = new double[9];  // scratch matrix
+       double[]    tmp_scale = new double[3];  // scratch matrix
+     
+       getScaleRotate( tmp_scale, tmp_rot );
+
+        m00 = (float)(m1.m00*tmp_scale[0]);
+        m01 = (float)(m1.m01*tmp_scale[1]);
+        m02 = (float)(m1.m02*tmp_scale[2]);
+
+        m10 = (float)(m1.m10*tmp_scale[0]);
+        m11 = (float)(m1.m11*tmp_scale[1]);
+        m12 = (float)(m1.m12*tmp_scale[2]);
+
+        m20 = (float)(m1.m20*tmp_scale[0]);
+        m21 = (float)(m1.m21*tmp_scale[1]);
+        m22 = (float)(m1.m22*tmp_scale[2]);
+   } 
+
+   /**
+     * Sets the rotational component (upper 3x3) of this matrix to the
+     * matrix equivalent values of the quaternion argument; the other
+     * elements of this matrix are unchanged; a singular value
+     * decomposition is performed on this object's upper 3x3 matrix to
+     * factor out the scale, then this object's upper 3x3 matrix components
+     * are replaced by the matrix equivalent of the quaternion,  
+     * and then the scale is reapplied to the rotational components.
+     * @param q1    the quaternion that specifies the rotation
+     */  
+    public final void setRotation(Quat4f q1){  
+       double[]    tmp_rot = new double[9];  // scratch matrix
+       double[]    tmp_scale = new double[3];  // scratch matrix
+        getScaleRotate( tmp_scale, tmp_rot );
+        m00 = (float)((1.0f - 2.0f*q1.y*q1.y - 2.0f*q1.z*q1.z)*tmp_scale[0]);
+        m10 = (float)((2.0f*(q1.x*q1.y + q1.w*q1.z))*tmp_scale[0]);
+        m20 = (float)((2.0f*(q1.x*q1.z - q1.w*q1.y))*tmp_scale[0]);
+        m01 = (float)((2.0f*(q1.x*q1.y - q1.w*q1.z))*tmp_scale[1]);
+        m11 = (float)((1.0f - 2.0f*q1.x*q1.x - 2.0f*q1.z*q1.z)*tmp_scale[1]);
+        m21 = (float)((2.0f*(q1.y*q1.z + q1.w*q1.x))*tmp_scale[1]);
+        m02 = (float)((2.0f*(q1.x*q1.z + q1.w*q1.y))*tmp_scale[2]);
+        m12 = (float)((2.0f*(q1.y*q1.z - q1.w*q1.x))*tmp_scale[2]);
+        m22 = (float)((1.0f - 2.0f*q1.x*q1.x - 2.0f*q1.y*q1.y)*tmp_scale[2]);
+    }  
+   /** 
+     * Sets the rotational component (upper 3x3) of this matrix to the
+     * matrix equivalent values of the quaternion argument; the other
+     * elements of this matrix are unchanged; a singular value 
+     * decomposition is performed on this object's upper 3x3 matrix to
+     * factor out the scale, then this object's upper 3x3 matrix components 
+     * are replaced by the matrix equivalent of the quaternion,       
+     * and then the scale is reapplied to the rotational components. 
+     * @param q1   the quaternion that specifies the rotation
+     */   
+    public final void setRotation(Quat4d q1){  
+       double[]    tmp_rot = new double[9];  // scratch matrix
+       double[]    tmp_scale = new double[3];  // scratch matrix
+       
+       getScaleRotate( tmp_scale, tmp_rot );
+        m00 = (float)((1.0f - 2.0f*q1.y*q1.y - 2.0f*q1.z*q1.z)*tmp_scale[0]);
+        m10 = (float)((2.0f*(q1.x*q1.y + q1.w*q1.z))*tmp_scale[0]);
+        m20 = (float)((2.0f*(q1.x*q1.z - q1.w*q1.y))*tmp_scale[0]);
+        m01 = (float)((2.0f*(q1.x*q1.y - q1.w*q1.z))*tmp_scale[1]);
+        m11 = (float)((1.0f - 2.0f*q1.x*q1.x - 2.0f*q1.z*q1.z)*tmp_scale[1]);
+        m21 = (float)((2.0f*(q1.y*q1.z + q1.w*q1.x))*tmp_scale[1]);
+        m02 = (float)((2.0f*(q1.x*q1.z + q1.w*q1.y))*tmp_scale[2]);
+        m12 = (float)((2.0f*(q1.y*q1.z - q1.w*q1.x))*tmp_scale[2]);
+        m22 = (float)((1.0f - 2.0f*q1.x*q1.x - 2.0f*q1.y*q1.y)*tmp_scale[2]);
+    }  
+
+   /** 
+     * Sets the rotational component (upper 3x3) of this matrix to the
+     * matrix equivalent values of the axis-angle argument; the other
+     * elements of this matrix are unchanged; a singular value 
+     * decomposition is performed on this object's upper 3x3 matrix to
+     * factor out the scale, then this object's upper 3x3 matrix components 
+     * are replaced by the matrix equivalent of the axis-angle,
+     * and then the scale is reapplied to the rotational components.
+     * @param a1 the axis-angle to be converted (x, y, z, angle)
+     */   
+    public final void setRotation(AxisAngle4f a1){   
+       double[]    tmp_rot = new double[9];  // scratch matrix
+       double[]    tmp_scale = new double[3];  // scratch matrix
+
+       getScaleRotate( tmp_scale, tmp_rot );
+
+       double mag = Math.sqrt( a1.x*a1.x + a1.y*a1.y + a1.z*a1.z);
+       if( mag < EPS ) {
+           m00 = 1.0f;
+           m01 = 0.0f;
+           m02 = 0.0f;
+
+           m10 = 0.0f;
+           m11 = 1.0f;
+           m12 = 0.0f;
+
+           m20 = 0.0f;
+           m21 = 0.0f;
+           m22 = 1.0f;
+       } else {
+           mag = 1.0/mag;
+           double ax = a1.x*mag;
+           double ay = a1.y*mag;
+           double az = a1.z*mag;
+  
+           double sinTheta = Math.sin(a1.angle);
+           double cosTheta = Math.cos(a1.angle);
+           double t = 1.0 - cosTheta;
+  
+           double xz = a1.x * a1.z;
+           double xy = a1.x * a1.y;
+           double yz = a1.y * a1.z;
+  
+           m00 = (float)((t * ax * ax + cosTheta)*tmp_scale[0]);
+           m01 = (float)((t * xy - sinTheta * az)*tmp_scale[1]);
+           m02 = (float)((t * xz + sinTheta * ay)*tmp_scale[2]);
+  
+           m10 = (float)((t * xy + sinTheta * az)*tmp_scale[0]);
+           m11 = (float)((t * ay * ay + cosTheta)*tmp_scale[1]);
+           m12 = (float)((t * yz - sinTheta * ax)*tmp_scale[2]);
+
+           m20 = (float)((t * xz - sinTheta * ay)*tmp_scale[0]);
+           m21 = (float)((t * yz + sinTheta * ax)*tmp_scale[1]);
+           m22 = (float)((t * az * az + cosTheta)*tmp_scale[2]);
+       }
+
+    }                                       
+
+  /**
+    *  Sets this matrix to all zeros.
+    */
+   public final void setZero()
+   {
+        m00 = 0.0f;
+        m01 = 0.0f;
+        m02 = 0.0f;
+        m03 = 0.0f;
+        m10 = 0.0f;
+        m11 = 0.0f;
+        m12 = 0.0f;
+        m13 = 0.0f;
+        m20 = 0.0f;
+        m21 = 0.0f;
+        m22 = 0.0f;
+        m23 = 0.0f;
+        m30 = 0.0f;
+        m31 = 0.0f;
+        m32 = 0.0f;
+        m33 = 0.0f;
+   }
+
+   /**
+     * Negates the value of this matrix: this = -this.
+     */  
+    public final void negate()
+    {
+        m00 = -m00;
+        m01 = -m01;
+        m02 = -m02;
+        m03 = -m03;
+        m10 = -m10;
+        m11 = -m11;
+        m12 = -m12;
+        m13 = -m13;
+        m20 = -m20;
+        m21 = -m21;
+        m22 = -m22;
+        m23 = -m23;
+        m30 = -m30;
+        m31 = -m31;
+        m32 = -m32;
+        m33 = -m33;
+    }
+
+   /**
+     *  Sets the value of this matrix equal to the negation of
+     *  of the Matrix4f parameter.
+     *  @param m1  the source matrix
+     */  
+    public final void negate(Matrix4f m1)
+    {
+        this.m00 = -m1.m00;
+        this.m01 = -m1.m01;
+        this.m02 = -m1.m02;
+        this.m03 = -m1.m03;
+        this.m10 = -m1.m10;
+        this.m11 = -m1.m11;
+        this.m12 = -m1.m12;
+        this.m13 = -m1.m13;
+        this.m20 = -m1.m20;
+        this.m21 = -m1.m21;
+        this.m22 = -m1.m22;
+        this.m23 = -m1.m23;
+        this.m30 = -m1.m30;
+        this.m31 = -m1.m31;
+        this.m32 = -m1.m32;
+        this.m33 = -m1.m33;
+    }
+    private final void getScaleRotate(double scales[], double rots[]) {
+       double[]    tmp = new double[9];  // scratch matrix
+       tmp[0] = m00;
+       tmp[1] = m01;
+       tmp[2] = m02;
+       tmp[3] = m10;
+       tmp[4] = m11;
+       tmp[5] = m12;
+       tmp[6] = m20;
+       tmp[7] = m21;
+       tmp[8] = m22;
+       Matrix3d.compute_svd( tmp, scales, rots);
+       return;
+    }
+
+    /**
+     * Creates a new object of the same class as this object.
+     *
+     * @return a clone of this instance.
+     * @exception OutOfMemoryError if there is not enough memory.
+     * @see java.lang.Cloneable
+     * @since vecmath 1.3
+     */
+    public Object clone() {
+       Matrix4f m1 = null;
+       try {
+           m1 = (Matrix4f)super.clone();
+       } catch (CloneNotSupportedException e) {
+           // this shouldn't happen, since we are Cloneable
+           throw new InternalError();
+       }
+
+       return m1;
+    }
+
+    /**
+        * Get the first matrix element in the first row.
+        * 
+        * @return Returns the m00.
+        * 
+        * @since vecmath 1.5
+        */
+       public final  float getM00() {
+               return m00;
+       }
+
+       /**
+        * Set the first matrix element in the first row.
+        * 
+        * @param m00 The m00 to set.
+        * 
+        * @since vecmath 1.5
+        */
+       public final  void setM00(float m00) {
+               this.m00 = m00;
+       }
+
+       /**
+        * Get the second matrix element in the first row.
+        * 
+        * @return Returns the m01.
+        * 
+        * @since vecmath 1.5
+        */
+       public final  float getM01() {
+               return m01;
+       }
+
+       /**
+        * Set the second matrix element in the first row.
+        * 
+        * @param m01 The m01 to set.
+        * 
+        * @since vecmath 1.5
+        */
+       public  final void setM01(float m01) {
+               this.m01 = m01;
+       }
+
+       /**
+        * Get the third matrix element in the first row.
+        * 
+        * @return Returns the m02.
+        * 
+        * @since vecmath 1.5
+        */
+       public final float getM02() {
+               return m02;
+       }
+
+       /**
+        * Set the third matrix element in the first row.
+        * 
+        * @param m02 The m02 to set.
+        * 
+        * @since vecmath 1.5
+        */
+       public final  void setM02(float m02) {
+               this.m02 = m02;
+       }
+
+       /**
+        * Get first matrix element in the second row.
+        * 
+        * @return Returns the m10.
+        * 
+        * @since vecmath 1.5
+        */
+       public final  float getM10() {
+               return m10;
+       }
+
+       /**
+        * Set first matrix element in the second row.
+        * 
+        * @param m10 The m10 to set.
+        * 
+        * @since vecmath 1.5
+        */
+       public final  void setM10(float m10) {
+               this.m10 = m10;
+       }
+
+       /**
+        * Get second matrix element in the second row.
+        * 
+        * @return Returns the m11.
+        * 
+        * @since vecmath 1.5
+        */
+       public final  float getM11() {
+               return m11;
+       }
+
+       /**
+        * Set the second matrix element in the second row.
+        * 
+        * @param m11 The m11 to set.
+        * 
+        * @since vecmath 1.5
+        */
+       public final  void setM11(float m11) {
+               this.m11 = m11;
+       }
+
+       /**
+        * Get the third matrix element in the second row.
+        * 
+        * @return Returns the m12.
+        * 
+        * @since vecmath 1.5
+        */
+       public final  float getM12() {
+               return m12;
+       }
+
+       /**
+        * Set the third matrix element in the second row.
+        * 
+        * @param m12 The m12 to set.
+        * 
+        * @since vecmath 1.5
+        */
+       public final  void setM12(float m12) {
+               this.m12 = m12;
+       }
+
+       /**
+        * Get the first matrix element in the third row.
+        * 
+        * @return Returns the m20.
+        * 
+        * @since vecmath 1.5
+        */
+       public final  float getM20() {
+               return m20;
+       }
+
+       /**
+        * Set the first matrix element in the third row.
+        * 
+        * @param m20 The m20 to set.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setM20(float m20) {
+               this.m20 = m20;
+       }
+
+       /**
+        * Get the second matrix element in the third row.
+        * 
+        * @return Returns the m21.
+        * 
+        * @since vecmath 1.5
+        */
+       public final float getM21() {
+               return m21;
+       }
+
+       /**
+        * Set the second matrix element in the third row.
+        * 
+        * @param m21 The m21 to set.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setM21(float m21) {
+               this.m21 = m21;
+       }
+
+       /**
+        * Get the third matrix element in the third row.
+        * 
+        * @return Returns the m22.
+        * 
+        * @since vecmath 1.5
+        */
+       public final float getM22() {
+               return m22;
+       }
+
+       /**
+        * Set the third matrix element in the third row.
+        * 
+        * @param m22 The m22 to set.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setM22(float m22) {
+               this.m22 = m22;
+       }
+
+       /**
+        * Get the fourth element of the first row.
+        * 
+        * @return Returns the m03.
+        * 
+        * @since vecmath 1.5
+        */
+       public final float getM03() {
+               return m03;
+       }
+
+       /**
+        * Set the fourth element of the first row.
+        * 
+        * @param m03 The m03 to set.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setM03(float m03) {
+               this.m03 = m03;
+       }
+
+       /**
+        * Get the fourth element of the second row.
+        * 
+        * @return Returns the m13.
+        * 
+        * @since vecmath 1.5
+        */
+       public final float getM13() {
+               return m13;
+       }
+
+       /**
+        * Set the fourth element of the second row.
+        * 
+        * @param m13 The m13 to set.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setM13(float m13) {
+               this.m13 = m13;
+       }
+
+       /**
+        * Get the fourth element of the third row.
+        * 
+        * @return Returns the m23.
+        * 
+        * @since vecmath 1.5
+        */
+       public final float getM23() {
+               return m23;
+       }
+
+       /**
+        * Set the fourth element of the third row.
+        * 
+        * @param m23 The m23 to set.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setM23(float m23) {
+               this.m23 = m23;
+       }
+
+       /**
+        * Get the first element of the fourth row.
+        * 
+        * @return Returns the m30.
+        * 
+        * @since vecmath 1.5
+        */
+       public final float getM30() {
+               return m30;
+       }
+
+       /**
+        * Set the first element of the fourth row.
+        * 
+        * @param m30 The m30 to set.
+        * 
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setM30(float m30) {
+               this.m30 = m30;
+       }
+
+       /**
+        * Get the second element of the fourth row.
+        * 
+        * @return Returns the m31.
+        * 
+        * @since vecmath 1.5
+        */
+       public final float getM31() {
+               return m31;
+       }
+
+       /**
+        * Set the second element of the fourth row.
+        * 
+        * @param m31 The m31 to set.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setM31(float m31) {
+               this.m31 = m31;
+       }
+
+       /**
+        * Get the third element of the fourth row. 
+        * 
+        * @return Returns the m32.
+        * 
+        * @since vecmath 1.5
+        */
+       public final float getM32() {
+               return m32;
+       }
+
+       /**
+        * Set the third element of the fourth row.
+        * 
+        * @param m32 The m32 to set.
+        * 
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setM32(float m32) {
+               this.m32 = m32;
+       }
+
+       /**
+        * Get the fourth element of the fourth row.
+        * 
+        * @return Returns the m33.
+        * 
+        * @since vecmath 1.5
+        */
+       public final float getM33() {
+               return m33;
+       }
+
+       /**
+        * Set the fourth element of the fourth row.
+        * 
+        * @param m33 The m33 to set.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setM33(float m33) {
+               this.m33 = m33;
+       }
+}
diff --git a/javax.vecmath/src/javax/vecmath/MismatchedSizeException.java b/javax.vecmath/src/javax/vecmath/MismatchedSizeException.java
new file mode 100644 (file)
index 0000000..8ac0133
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * $RCSfile: MismatchedSizeException.java,v $
+ *
+ * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ * $Revision: 1.5 $
+ * $Date: 2008/02/28 20:18:50 $
+ * $State: Exp $
+ */
+
+package javax.vecmath;
+
+/**
+ * Indicates that an operation cannot be completed properly because
+ * of a mismatch in the sizes of object attributes.
+ */
+public class MismatchedSizeException extends RuntimeException{
+
+
+/**
+ * Create the exception object with default values.
+ */
+  public MismatchedSizeException(){
+  }
+
+/**
+ * Create the exception object that outputs a message.
+ * @param str the message string to be output.
+ */
+  public MismatchedSizeException(String str){
+
+    super(str);
+  }
+
+}
+
diff --git a/javax.vecmath/src/javax/vecmath/Point2d.java b/javax.vecmath/src/javax/vecmath/Point2d.java
new file mode 100644 (file)
index 0000000..2d8dea6
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ * $RCSfile: Point2d.java,v $
+ *
+ * Copyright 1998-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ * $Revision: 1.5 $
+ * $Date: 2008/02/28 20:18:50 $
+ * $State: Exp $
+ */
+
+package javax.vecmath;
+
+import java.lang.Math;
+
+/**
+ * A 2 element point that is represented by double precision floating 
+ * point x,y coordinates.
+ *
+ */
+public class Point2d extends Tuple2d implements java.io.Serializable {
+
+    // Compatible with 1.1
+    static final long serialVersionUID = 1133748791492571954L;
+
+    /**
+     * Constructs and initializes a Point2d from the specified xy coordinates.
+     * @param x the x coordinate
+     * @param y the y coordinate
+     */
+    public Point2d(double x, double y)
+    {
+         super(x,y);
+    }
+
+
+    /**
+     * Constructs and initializes a Point2d from the specified array.
+     * @param p the array of length 2 containing xy in order
+     */
+    public Point2d(double[] p)
+    {
+         super(p);
+    }
+
+
+    /**
+     * Constructs and initializes a Point2d from the specified Point2d.
+     * @param p1 the Point2d containing the initialization x y data
+     */
+    public Point2d(Point2d p1)
+    {
+        super(p1);
+    }
+
+
+    /**
+     * Constructs and initializes a Point2d from the specified Point2f.
+     * @param p1 the Point2f containing the initialization x y data
+     */
+    public Point2d(Point2f p1)
+    {
+        super(p1);
+    }
+
+
+    /**
+     * Constructs and initializes a Point2d from the specified Tuple2d.
+     * @param t1 the Tuple2d containing the initialization x y data
+     */ 
+    public Point2d(Tuple2d t1) 
+    {
+       super(t1);
+    }
+
+
+    /**
+     * Constructs and initializes a Point2d from the specified Tuple2f.
+     * @param t1 the Tuple2f containing the initialization x y data
+     */ 
+    public Point2d(Tuple2f t1) 
+    {
+       super(t1);
+    }
+
+
+    /**
+     * Constructs and initializes a Point2d to (0,0).
+     */
+    public Point2d()
+    {
+       super();
+    }
+
+  /**
+   * Computes the square of the distance between this point and point p1.
+   * @param p1 the other point
+   */
+  public final double distanceSquared(Point2d p1)
+    {
+      double dx, dy;
+
+      dx = this.x-p1.x;  
+      dy = this.y-p1.y;
+      return dx*dx+dy*dy;
+    }
+
+  /**
+   * Computes the distance between this point and point p1.
+   * @param p1 the other point 
+   */    
+  public final double distance(Point2d p1)
+    {
+      double  dx, dy;
+
+      dx = this.x-p1.x;  
+      dy = this.y-p1.y;
+      return Math.sqrt(dx*dx+dy*dy);
+    }
+
+
+  /**
+    * Computes the L-1 (Manhattan) distance between this point and
+    * point p1.  The L-1 distance is equal to abs(x1-x2) + abs(y1-y2).
+    * @param p1 the other point
+    */
+  public final double distanceL1(Point2d p1)
+    {
+      return( Math.abs(this.x-p1.x) + Math.abs(this.y-p1.y));
+    }
+
+  /**
+    * Computes the L-infinite distance between this point and
+    * point p1.  The L-infinite distance is equal to 
+    * MAX[abs(x1-x2), abs(y1-y2)]. 
+    * @param p1 the other point
+    */
+  public final double distanceLinf(Point2d p1)
+    {
+      return(Math.max( Math.abs(this.x-p1.x), Math.abs(this.y-p1.y)));
+    }
+
+}
diff --git a/javax.vecmath/src/javax/vecmath/Point2f.java b/javax.vecmath/src/javax/vecmath/Point2f.java
new file mode 100644 (file)
index 0000000..40cbc9d
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ * $RCSfile: Point2f.java,v $
+ *
+ * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ * $Revision: 1.5 $
+ * $Date: 2008/02/28 20:18:50 $
+ * $State: Exp $
+ */
+
+package javax.vecmath;
+
+import java.lang.Math;
+
+/**
+ * A 2 element point that is represented by single precision floating 
+ * point x,y coordinates.
+ *
+ */
+public class Point2f extends Tuple2f implements java.io.Serializable {
+
+    // Compatible with 1.1
+    static final long serialVersionUID = -4801347926528714435L;
+
+    /**
+     * Constructs and initializes a Point2f from the specified xy coordinates.
+     * @param x the x coordinate
+     * @param y the y coordinate
+     */
+    public Point2f(float x, float y)
+    {
+         super(x,y);
+    }
+
+
+    /**
+     * Constructs and initializes a Point2f from the specified array.
+     * @param p the array of length 2 containing xy in order
+     */
+    public Point2f(float[] p)
+    {
+         super(p);
+    }
+
+
+    /**
+     * Constructs and initializes a Point2f from the specified Point2f.
+     * @param p1 the Point2f containing the initialization x y data
+     */
+    public Point2f(Point2f p1)
+    {
+        super(p1);
+    }
+
+    /**
+     * Constructs and initializes a Point2f from the specified Point2d.
+     * @param p1 the Point2d containing the initialization x y z data
+     */
+    public Point2f(Point2d p1)
+    {
+       super(p1);
+    }
+
+
+
+    /**
+     * Constructs and initializes a Point2f from the specified Tuple2d.
+     * @param t1 the Tuple2d containing the initialization x y z data
+     */ 
+    public Point2f(Tuple2d t1) 
+    {
+       super(t1);
+    }
+
+
+
+    /**
+     * Constructs and initializes a Point2f from the specified Tuple2f.
+     * @param t1 the Tuple2f containing the initialization x y data
+     */ 
+    public Point2f(Tuple2f t1) 
+    {
+       super(t1);
+    }
+
+
+    /**
+     * Constructs and initializes a Point2f to (0,0).
+     */
+    public Point2f()
+    {
+       super();
+    }
+
+  /**
+   * Computes the square of the distance between this point and point p1.
+   * @param p1 the other point
+   */
+  public final float distanceSquared(Point2f p1)
+    {
+      float dx, dy;
+
+      dx = this.x-p1.x;  
+      dy = this.y-p1.y;
+      return dx*dx+dy*dy;
+    }
+
+  /**
+   * Computes the distance between this point and point p1.
+   * @param p1 the other point 
+   */    
+  public final float distance(Point2f p1)
+    {
+      float  dx, dy;
+
+      dx = this.x-p1.x;  
+      dy = this.y-p1.y;
+      return (float) Math.sqrt(dx*dx+dy*dy);
+    }
+
+
+  /**
+    * Computes the L-1 (Manhattan) distance between this point and
+    * point p1.  The L-1 distance is equal to abs(x1-x2) + abs(y1-y2).
+    * @param p1 the other point
+    */
+  public final float distanceL1(Point2f p1)
+    {
+      return( Math.abs(this.x-p1.x) + Math.abs(this.y-p1.y));
+    }
+
+  /**
+    * Computes the L-infinite distance between this point and
+    * point p1.  The L-infinite distance is equal to 
+    * MAX[abs(x1-x2), abs(y1-y2)]. 
+    * @param p1 the other point
+    */
+  public final float distanceLinf(Point2f p1)
+    {
+      return(Math.max( Math.abs(this.x-p1.x), Math.abs(this.y-p1.y)));
+    }
+
+}
diff --git a/javax.vecmath/src/javax/vecmath/Point2i.java b/javax.vecmath/src/javax/vecmath/Point2i.java
new file mode 100644 (file)
index 0000000..5c2105e
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * $RCSfile: Point2i.java,v $
+ *
+ * Copyright 2005-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ * $Revision: 1.5 $
+ * $Date: 2008/02/28 20:18:50 $
+ * $State: Exp $
+ */
+
+package javax.vecmath;
+
+import java.lang.Math;
+
+/**
+ * A 2-element point represented by signed integer x,y
+ * coordinates.
+ *
+ * @since vecmath 1.4
+ */
+public class Point2i extends Tuple2i implements java.io.Serializable {
+
+    static final long serialVersionUID = 9208072376494084954L;
+
+    /**
+     * Constructs and initializes a Point2i from the specified
+     * x and y coordinates.
+     * @param x the x coordinate
+     * @param y the y coordinate
+     */
+    public Point2i(int x, int y) {
+       super(x, y);
+    }
+
+
+    /**
+     * Constructs and initializes a Point2i from the array of length 2.
+     * @param t the array of length 2 containing x and y in order.
+     */
+    public Point2i(int[] t) {
+       super(t);
+    }
+
+
+    /**
+     * Constructs and initializes a Point2i from the specified Tuple2i.
+     * @param t1 the Tuple2i containing the initialization x and y
+     * data.
+     */
+    public Point2i(Tuple2i t1) {
+       super(t1);
+    }
+
+
+    /**
+     * Constructs and initializes a Point2i to (0,0).
+     */
+    public Point2i() {
+       super();
+    }
+
+}
diff --git a/javax.vecmath/src/javax/vecmath/Point3d.java b/javax.vecmath/src/javax/vecmath/Point3d.java
new file mode 100644 (file)
index 0000000..74dd431
--- /dev/null
@@ -0,0 +1,194 @@
+/*
+ * $RCSfile: Point3d.java,v $
+ *
+ * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ * $Revision: 1.5 $
+ * $Date: 2008/02/28 20:18:50 $
+ * $State: Exp $
+ */
+
+package javax.vecmath;
+
+import java.lang.Math;
+
+/**
+ * A 3 element point that is represented by double precision floating point 
+ * x,y,z coordinates.
+ *
+ */
+public class Point3d extends Tuple3d implements java.io.Serializable {
+
+    // Compatible with 1.1
+    static final long serialVersionUID = 5718062286069042927L;
+
+    /**
+     * Constructs and initializes a Point3d from the specified xyz coordinates.
+     * @param x the x coordinate
+     * @param y the y coordinate
+     * @param z the z coordinate
+     */
+    public Point3d(double x, double y, double z)
+    {
+        super(x,y,z);
+    }
+
+
+    /**
+     * Constructs and initializes a Point3d from the array of length 3.
+     * @param p the array of length 3 containing xyz in order
+     */
+    public Point3d(double[] p)
+    {
+       super(p);
+    }
+
+
+    /**
+     * Constructs and initializes a Point3d from the specified Point3d.
+     * @param p1 the Point3d containing the initialization x y z data
+     */
+    public Point3d(Point3d p1)
+    {
+         super(p1);
+    }
+
+
+    /**
+     * Constructs and initializes a Point3d from the specified Point3f.
+     * @param p1 the Point3f containing the initialization x y z data
+     */
+    public Point3d(Point3f p1)
+    {
+       super(p1);
+    }
+
+
+    /** 
+     * Constructs and initializes a Point3d from the specified Tuple3f. 
+     * @param t1 the Tuple3f containing the initialization x y z data 
+     */  
+    public Point3d(Tuple3f t1)  
+    { 
+       super(t1); 
+    }
+    /** 
+     * Constructs and initializes a Point3d from the specified Tuple3d.  
+     * @param t1 the Tuple3d containing the initialization x y z data 
+     */  
+    public Point3d(Tuple3d t1)
+    {
+       super(t1);
+    }
+
+
+    /**
+     * Constructs and initializes a Point3d to (0,0,0).
+     */
+    public Point3d()
+    {
+       super();
+    }
+
+
+  /**
+   * Returns the square of the distance between this point and point p1.
+   * @param p1 the other point 
+   * @return the square of the distance
+   */
+  public final double distanceSquared(Point3d p1)
+    {
+      double dx, dy, dz;
+
+      dx = this.x-p1.x;
+      dy = this.y-p1.y;
+      dz = this.z-p1.z;
+      return (dx*dx+dy*dy+dz*dz);
+    }
+
+
+  /**
+   * Returns the distance between this point and point p1.
+   * @param p1 the other point
+   * @return the distance 
+   */
+  public final double distance(Point3d p1)
+    {
+      double dx, dy, dz;
+
+      dx = this.x-p1.x;
+      dy = this.y-p1.y;
+      dz = this.z-p1.z;
+      return Math.sqrt(dx*dx+dy*dy+dz*dz);
+    }
+
+
+    /**
+     * Computes the L-1 (Manhattan) distance between this point and
+     * point p1.  The L-1 distance is equal to:
+     *  abs(x1-x2) + abs(y1-y2) + abs(z1-z2).
+     * @param p1 the other point
+     * @return  the L-1 distance
+     */
+    public final double distanceL1(Point3d p1) {
+       return Math.abs(this.x-p1.x) + Math.abs(this.y-p1.y) +
+           Math.abs(this.z-p1.z);
+    }
+
+
+    /**
+     * Computes the L-infinite distance between this point and
+     * point p1.  The L-infinite distance is equal to
+     * MAX[abs(x1-x2), abs(y1-y2), abs(z1-z2)].
+     * @param p1 the other point
+     * @return  the L-infinite distance
+     */
+    public final double distanceLinf(Point3d p1) {
+       double tmp;
+       tmp = Math.max( Math.abs(this.x-p1.x), Math.abs(this.y-p1.y));
+
+       return Math.max(tmp,Math.abs(this.z-p1.z));
+    }
+
+
+  /**
+    *  Multiplies each of the x,y,z components of the Point4d parameter 
+    *  by 1/w and places the projected values into this point. 
+    *  @param  p1  the source Point4d, which is not modified 
+    */   
+   public final void project(Point4d p1)
+   { 
+     double oneOw;
+
+     oneOw = 1/p1.w;
+     x = p1.x*oneOw;
+     y = p1.y*oneOw;
+     z = p1.z*oneOw;
+
+   } 
+
+
+}
diff --git a/javax.vecmath/src/javax/vecmath/Point3f.java b/javax.vecmath/src/javax/vecmath/Point3f.java
new file mode 100644 (file)
index 0000000..716ae30
--- /dev/null
@@ -0,0 +1,197 @@
+/*
+ * $RCSfile: Point3f.java,v $
+ *
+ * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ * $Revision: 1.5 $
+ * $Date: 2008/02/28 20:18:50 $
+ * $State: Exp $
+ */
+
+package javax.vecmath;
+
+import java.lang.Math;
+
+/**
+ * A 3 element point that is represented by single precision floating point 
+ * x,y,z coordinates.
+ *
+ */
+public class Point3f extends Tuple3f implements java.io.Serializable {
+
+
+    // Compatible with 1.1
+    static final long serialVersionUID = -8689337816398030143L;
+
+    /**
+     * Constructs and initializes a Point3f from the specified xyz coordinates.
+     * @param x the x coordinate
+     * @param y the y coordinate
+     * @param z the z coordinate
+     */
+    public Point3f(float x, float y, float z)
+    {
+        super(x,y,z);
+    }
+
+
+    /**
+     * Constructs and initializes a Point3f from the array of length 3.
+     * @param p the array of length 3 containing xyz in order
+     */
+    public Point3f(float[] p)
+    {
+       super(p);
+    }
+
+
+    /**
+     * Constructs and initializes a Point3f from the specified Point3f.
+     * @param p1 the Point3f containing the initialization x y z data
+     */
+    public Point3f(Point3f p1)
+    {
+       super(p1);
+    }
+
+
+    /**
+     * Constructs and initializes a Point3f from the specified Point3d.
+     * @param p1 the Point3d containing the initialization x y z data
+     */
+    public Point3f(Point3d p1)
+    {
+       super(p1);
+    }
+
+
+    /**
+     * Constructs and initializes a Point3f from the specified Tuple3f.
+     * @param t1 the Tuple3f containing the initialization x y z data
+     */ 
+    public Point3f(Tuple3f t1) 
+    {
+       super(t1);
+    }
+
+
+    /**
+     * Constructs and initializes a Point3f from the specified Tuple3d.
+     * @param t1 the Tuple3d containing the initialization x y z data
+     */ 
+    public Point3f(Tuple3d t1) 
+    {
+       super(t1);
+    }
+
+
+    /**
+     * Constructs and initializes a Point3f to (0,0,0).
+     */
+    public Point3f()
+    {
+        super();
+    }
+
+
+ /**
+   * Computes the square of the distance between this point and 
+   * point p1.
+   * @param p1 the other point
+   * @return  the square of the distance
+   */
+  public final float distanceSquared(Point3f p1)
+    {
+      float dx, dy, dz;
+
+      dx = this.x-p1.x;
+      dy = this.y-p1.y;
+      dz = this.z-p1.z;
+      return dx*dx+dy*dy+dz*dz;
+    }
+
+
+  /**
+   * Computes the distance between this point and point p1.
+   * @param p1 the other point
+   * @return the distance
+   */
+  public final float distance(Point3f p1)
+    {
+      float  dx, dy, dz;
+
+      dx = this.x-p1.x;
+      dy = this.y-p1.y;
+      dz = this.z-p1.z;
+      return (float) Math.sqrt(dx*dx+dy*dy+dz*dz);
+    }
+
+
+  /**
+    * Computes the L-1 (Manhattan) distance between this point and
+    * point p1.  The L-1 distance is equal to:
+    *  abs(x1-x2) + abs(y1-y2) + abs(z1-z2).
+    * @param p1 the other point
+    * @return  the L-1 distance
+    */
+  public final float distanceL1(Point3f p1)
+    {
+       return( Math.abs(this.x-p1.x) + Math.abs(this.y-p1.y) + Math.abs(this.z-p1.z));
+    }
+
+
+  /**
+    * Computes the L-infinite distance between this point and
+    * point p1.  The L-infinite distance is equal to 
+    * MAX[abs(x1-x2), abs(y1-y2), abs(z1-z2)]. 
+    * @param p1 the other point
+    * @return  the L-infinite distance
+    */
+  public final float distanceLinf(Point3f p1)
+    {
+       float tmp;
+       tmp = Math.max( Math.abs(this.x-p1.x), Math.abs(this.y-p1.y));
+       return(Math.max(tmp,Math.abs(this.z-p1.z)));
+
+    }
+
+
+  /**
+    *  Multiplies each of the x,y,z components of the Point4f parameter
+    *  by 1/w and places the projected values into this point.
+    *  @param  p1  the source Point4f, which is not modified
+    */
+   public final void project(Point4f p1)
+   {
+     float oneOw;
+
+     oneOw = 1/p1.w;
+     x = p1.x*oneOw;
+     y = p1.y*oneOw;
+     z = p1.z*oneOw;
+
+   }
+
+
+}
diff --git a/javax.vecmath/src/javax/vecmath/Point3i.java b/javax.vecmath/src/javax/vecmath/Point3i.java
new file mode 100644 (file)
index 0000000..6cba0e8
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * $RCSfile: Point3i.java,v $
+ *
+ * Copyright 1999-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ * $Revision: 1.6 $
+ * $Date: 2008/02/28 20:18:50 $
+ * $State: Exp $
+ */
+
+package javax.vecmath;
+
+import java.lang.Math;
+
+/**
+ * A 3 element point represented by signed integer x,y,z
+ * coordinates.
+ *
+ * @since vecmath 1.2
+ */
+public class Point3i extends Tuple3i implements java.io.Serializable {
+
+    // Compatible with 1.2
+    static final long serialVersionUID = 6149289077348153921L;
+
+    /**
+     * Constructs and initializes a Point3i from the specified
+     * x, y, and z coordinates.
+     * @param x the x coordinate
+     * @param y the y coordinate
+     * @param z the z coordinate
+     */
+    public Point3i(int x, int y, int z) {
+       super(x, y, z);
+    }
+
+
+    /**
+     * Constructs and initializes a Point3i from the array of length 3.
+     * @param t the array of length 3 containing x, y, and z in order.
+     */
+    public Point3i(int[] t) {
+       super(t);
+    }
+
+
+    /**
+     * Constructs and initializes a Point3i from the specified Tuple3i.
+     * @param t1 the Tuple3i containing the initialization x, y, and z
+     * data.
+     */
+    public Point3i(Tuple3i t1) {
+       super(t1);
+    }
+
+
+    /**
+     * Constructs and initializes a Point3i to (0,0,0).
+     */
+    public Point3i() {
+       super();
+    }
+
+}
diff --git a/javax.vecmath/src/javax/vecmath/Point4d.java b/javax.vecmath/src/javax/vecmath/Point4d.java
new file mode 100644 (file)
index 0000000..c01aaa3
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ * $RCSfile: Point4d.java,v $
+ *
+ * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ * $Revision: 1.6 $
+ * $Date: 2008/02/28 20:18:50 $
+ * $State: Exp $
+ */
+
+package javax.vecmath;
+
+import java.lang.Math;
+
+/**
+ * A 4 element vector represented by double precision floating point 
+ * x,y,z,w coordinates.
+ *
+ */
+public class Point4d extends Tuple4d implements java.io.Serializable {
+
+    // Compatible with 1.1
+    static final long serialVersionUID = 1733471895962736949L;
+
+
+    /**
+     * Constructs and initializes a Point4d from the specified xyzw coordinates.
+     * @param x the x coordinate
+     * @param y the y coordinate
+     * @param z the z coordinate
+     * @param w the w coordinate
+     */
+    public Point4d(double x, double y, double z, double w)
+    {
+        super(x,y,z,w);
+    }
+
+    /**
+     * Constructs and initializes a Point4d from the coordinates contained
+     * in the array.
+     * @param p the array of length 4 containing xyzw in order
+     */
+    public Point4d(double[] p)
+    {
+        super(p);
+    }
+
+
+    /**
+     * Constructs and initializes a Point4d from the specified Point4d.
+     * @param p1 the Point4d containing the initialization x y z w data
+     */
+    public Point4d(Point4d p1)
+    {
+         super(p1);
+    }
+
+
+    /**
+     * Constructs and initializes a Point4d from the specified Point4f.
+     * @param p1 the Point4f containing the initialization x y z w data
+     */
+    public Point4d(Point4f p1)
+    {
+       super(p1);
+    }
+
+
+    /**  
+     * Constructs and initializes a Point4d from the specified Tuple4f.  
+     * @param t1 the Tuple4f containing the initialization x y z w data  
+     */  
+    public Point4d(Tuple4f t1)  
+    {    
+       super(t1);  
+    } 
+  
+  
+    /**  
+     * Constructs and initializes a Point4d from the specified Tuple4d.  
+     * @param t1 the Tuple4d containing the initialization x y z w data  
+     */   
+    public Point4d(Tuple4d t1) 
+    { 
+       super(t1); 
+    } 
+  
+
+    /**
+     * Constructs and initializes a Point4d from the specified Tuple3d.
+     * The x,y,z components of this point are set to the corresponding
+     * components of tuple t1.  The w component of this point
+     * is set to 1.
+     * @param t1 the tuple to be copied
+     *
+     * @since vecmath 1.2
+     */
+    public Point4d(Tuple3d t1) {
+       super(t1.x, t1.y, t1.z, 1.0);
+    }
+
+
+    /**
+     * Constructs and initializes a Point4d to (0,0,0,0).
+     */
+    public Point4d()
+    {
+       super();
+    }
+
+
+    /**
+     * Sets the x,y,z components of this point to the corresponding
+     * components of tuple t1.  The w component of this point
+     * is set to 1.
+     * @param t1 the tuple to be copied
+     *
+     * @since vecmath 1.2
+     */
+    public final void set(Tuple3d t1) {
+       this.x = t1.x;
+       this.y = t1.y;
+       this.z = t1.z;
+       this.w = 1.0;
+    }
+
+
+ /**
+   * Returns the square of the distance between this point and point p1.
+   * @param p1 the first point
+   * @return the square of distance between this point and point p1
+   */
+    public final double distanceSquared(Point4d p1)
+    {
+      double dx, dy, dz, dw;
+
+      dx = this.x-p1.x;
+      dy = this.y-p1.y;
+      dz = this.z-p1.z;
+      dw = this.w-p1.w;
+      return (dx*dx+dy*dy+dz*dz+dw*dw);
+    }
+
+
+  /**
+   * Returns the distance between this point and point p1.
+   * @param p1 the first point
+   * @return the distance between these this point and point p1.
+   */
+    public final double distance(Point4d p1)
+    {
+      double dx, dy, dz, dw;
+
+      dx = this.x-p1.x;
+      dy = this.y-p1.y;
+      dz = this.z-p1.z;
+      dw = this.w-p1.w;
+      return Math.sqrt(dx*dx+dy*dy+dz*dz+dw*dw);
+    }
+
+
+  /**
+    * Computes the L-1 (Manhattan) distance between this point and
+    * point p1.  The L-1 distance is equal to:
+    *  abs(x1-x2) + abs(y1-y2) + abs(z1-z2) + abs(w1-w2).
+    * @param p1 the other point
+    * @return  the L-1 distance
+    */
+    public final double distanceL1(Point4d p1) {
+       return Math.abs(this.x-p1.x) + Math.abs(this.y-p1.y) +
+           Math.abs(this.z-p1.z) + Math.abs(this.w-p1.w);
+    }
+
+    /**
+     * Computes the L-infinite distance between this point and
+     * point p1.  The L-infinite distance is equal to
+     * MAX[abs(x1-x2), abs(y1-y2), abs(z1-z2), abs(w1-w2)].
+     * @param p1 the other point
+     * @return  the L-infinite distance
+     */
+    public final double distanceLinf(Point4d p1) {
+       double t1, t2;
+       t1 = Math.max( Math.abs(this.x-p1.x), Math.abs(this.y-p1.y));
+       t2 = Math.max( Math.abs(this.z-p1.z), Math.abs(this.w-p1.w));
+       return Math.max(t1,t2);
+    }
+
+  /**
+    *  Multiplies each of the x,y,z components of the Point4d parameter 
+    *  by 1/w, places the projected values into this point, and places
+    *  a 1 as the w parameter of this point. 
+    *  @param  p1  the source Point4d, which is not modified 
+    */   
+   public final void project(Point4d p1)
+   { 
+     double oneOw;
+
+     oneOw = 1/p1.w;
+     x = p1.x*oneOw;
+     y = p1.y*oneOw;
+     z = p1.z*oneOw;
+     w = 1.0;
+
+   } 
+
+
+}
diff --git a/javax.vecmath/src/javax/vecmath/Point4f.java b/javax.vecmath/src/javax/vecmath/Point4f.java
new file mode 100644 (file)
index 0000000..c299fca
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+ * $RCSfile: Point4f.java,v $
+ *
+ * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ * $Revision: 1.6 $
+ * $Date: 2008/02/28 20:18:50 $
+ * $State: Exp $
+ */
+
+package javax.vecmath;
+
+import java.lang.Math;
+
+/**
+ * A 4 element point represented by single precision floating point x,y,z,w 
+ * coordinates.
+ *
+ */
+public class Point4f extends Tuple4f implements java.io.Serializable {
+
+
+    // Compatible with 1.1
+    static final long serialVersionUID = 4643134103185764459L;
+
+  /**
+   * Constructs and initializes a Point4f from the specified xyzw coordinates.
+   * @param x the x coordinate
+   * @param y the y coordinate
+   * @param z the z coordinate
+   * @param w the w coordinate
+   */
+  public Point4f(float x, float y, float z, float w)
+  {
+       super(x,y,z,w);
+  }
+
+
+  /**
+   * Constructs and initializes a Point4f from the array of length 4. 
+   * @param p the array of length 4 containing xyzw in order
+   */
+  public Point4f(float[] p)
+  {
+     super(p);
+  }
+
+
+  /**
+   * Constructs and initializes a Point4f from the specified Point4f.
+   * @param p1 the Point4f containing the initialization x y z w data
+   */
+  public Point4f(Point4f p1)
+  {
+      super(p1);
+  }
+
+
+  /**
+   * Constructs and initializes a Point4f from the specified Point4d.
+   * @param p1 the Point4d containing the initialization x y z w data
+   */
+  public Point4f(Point4d p1)
+  {
+      super(p1);
+  }
+
+
+    /** 
+     * Constructs and initializes a Point4f from the specified Tuple4f. 
+     * @param t1 the Tuple4f containing the initialization x y z w data 
+     */  
+    public Point4f(Tuple4f t1)  
+    { 
+       super(t1); 
+    }
+    /** 
+     * Constructs and initializes a Point4f from the specified Tuple4d.  
+     * @param t1 the Tuple4d containing the initialization x y z w data 
+     */  
+    public Point4f(Tuple4d t1)
+    {
+       super(t1);
+    }
+
+    /**
+     * Constructs and initializes a Point4f from the specified Tuple3f.
+     * The x,y,z components of this point are set to the corresponding
+     * components of tuple t1.  The w component of this point
+     * is set to 1.
+     * @param t1 the tuple to be copied
+     *
+     * @since vecmath 1.2
+     */
+    public Point4f(Tuple3f t1) {
+       super(t1.x, t1.y, t1.z, 1.0f);
+    }
+
+
+  /**
+   * Constructs and initializes a Point4f to (0,0,0,0).
+   */
+  public Point4f()
+  {
+      super();
+  }
+
+
+    /**
+     * Sets the x,y,z components of this point to the corresponding
+     * components of tuple t1.  The w component of this point
+     * is set to 1.
+     * @param t1 the tuple to be copied
+     *
+     * @since vecmath 1.2
+     */
+    public final void set(Tuple3f t1) {
+       this.x = t1.x;
+       this.y = t1.y;
+       this.z = t1.z;
+       this.w = 1.0f;
+    }
+
+
+ /**
+   * Computes the square of the distance between this point and point p1.
+   * @param p1 the other point
+   * @return the square of distance between these two points as a float
+   */
+  public final float distanceSquared(Point4f p1)
+    {
+      float dx, dy, dz, dw;
+
+      dx = this.x-p1.x;
+      dy = this.y-p1.y;
+      dz = this.z-p1.z;
+      dw = this.w-p1.w;
+      return (dx*dx+dy*dy+dz*dz+dw*dw);
+    }
+
+
+  /**
+   * Computes the distance between this point and point p1.
+   * @param p1 the other point
+   * @return the distance between the two points
+   */
+  public final float distance(Point4f p1)
+    {
+      float dx, dy, dz, dw;
+
+      dx = this.x-p1.x;
+      dy = this.y-p1.y;
+      dz = this.z-p1.z;
+      dw = this.w-p1.w;
+      return (float) Math.sqrt(dx*dx+dy*dy+dz*dz+dw*dw);
+    }
+
+
+  /**
+    * Computes the L-1 (Manhattan) distance between this point and
+    * point p1.  The L-1 distance is equal to:
+    *  abs(x1-x2) + abs(y1-y2) + abs(z1-z2) + abs(w1-w2).
+    * @param p1 the other point
+    * @return  the L-1 distance
+    */
+  public final float distanceL1(Point4f p1)
+    {
+       return( Math.abs(this.x-p1.x) + Math.abs(this.y-p1.y) + Math.abs(this.z-p1.z) + Math.abs(this.w-p1.w));
+    }
+
+
+  /**
+    * Computes the L-infinite distance between this point and
+    * point p1.  The L-infinite distance is equal to
+    * MAX[abs(x1-x2), abs(y1-y2), abs(z1-z2), abs(w1-w2)].
+    * @param p1 the other point
+    * @return  the L-infinite distance
+    */
+  public final float distanceLinf(Point4f p1)
+    {
+       float t1, t2;
+       t1 = Math.max( Math.abs(this.x-p1.x), Math.abs(this.y-p1.y));
+       t2 = Math.max( Math.abs(this.z-p1.z), Math.abs(this.w-p1.w));
+       return(Math.max(t1,t2));
+
+    }
+
+  /**
+    *  Multiplies each of the x,y,z components of the Point4f parameter 
+    *  by 1/w, places the projected values into this point, and places
+    *  a 1 as the w parameter of this point. 
+    *  @param  p1  the source Point4f, which is not modified 
+    */   
+   public final void project(Point4f p1)
+   { 
+     float oneOw;
+
+     oneOw = 1/p1.w;
+     x = p1.x*oneOw;
+     y = p1.y*oneOw;
+     z = p1.z*oneOw;
+     w = 1.0f;
+
+   } 
+
+}
diff --git a/javax.vecmath/src/javax/vecmath/Point4i.java b/javax.vecmath/src/javax/vecmath/Point4i.java
new file mode 100644 (file)
index 0000000..f7a8462
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * $RCSfile: Point4i.java,v $
+ *
+ * Copyright 1999-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ * $Revision: 1.6 $
+ * $Date: 2008/02/28 20:18:50 $
+ * $State: Exp $
+ */
+
+package javax.vecmath;
+
+import java.lang.Math;
+
+/**
+ * A 4 element point represented by signed integer x,y,z,w
+ * coordinates.
+ *
+ * @since vecmath 1.2
+ */
+public class Point4i extends Tuple4i implements java.io.Serializable {
+
+    // Combatible with 1.2
+    static final long serialVersionUID = 620124780244617983L;
+
+    /**
+     * Constructs and initializes a Point4i from the specified
+     * x, y, z, and w coordinates.
+     * @param x the x coordinate
+     * @param y the y coordinate
+     * @param z the z coordinate
+     * @param w the w coordinate
+     */
+    public Point4i(int x, int y, int z, int w) {
+       super(x, y, z, w);
+    }
+
+
+    /**
+     * Constructs and initializes a Point4i from the array of length 4.
+     * @param t the array of length 4 containing x, y, z, and w in order.
+     */
+    public Point4i(int[] t) {
+       super(t);
+    }
+
+
+    /**
+     * Constructs and initializes a Point4i from the specified Tuple4i.
+     * @param t1 the Tuple4i containing the initialization x, y, z,
+     * and w data.
+     */
+    public Point4i(Tuple4i t1) {
+       super(t1);
+    }
+
+
+    /**
+     * Constructs and initializes a Point4i to (0,0,0,0).
+     */
+    public Point4i() {
+       super();
+    }
+
+}
diff --git a/javax.vecmath/src/javax/vecmath/Quat4d.java b/javax.vecmath/src/javax/vecmath/Quat4d.java
new file mode 100644 (file)
index 0000000..0116ad8
--- /dev/null
@@ -0,0 +1,682 @@
+/*
+ * $RCSfile: Quat4d.java,v $
+ *
+ * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ * $Revision: 1.7 $
+ * $Date: 2008/02/28 20:18:50 $
+ * $State: Exp $
+ */
+
+package javax.vecmath;
+
+/**
+ * A 4-element quaternion represented by double precision floating 
+ * point x,y,z,w coordinates.  The quaternion is always normalized.
+ *
+ */
+public class Quat4d extends Tuple4d implements java.io.Serializable {
+
+  // Combatible with 1.1
+  static final long serialVersionUID = 7577479888820201099L;
+
+  // Fixed to issue 538
+  final static double EPS = 1.0e-12;
+  final static double EPS2 = 1.0e-30;
+  final static double PIO2 = 1.57079632679;
+
+  /**
+   * Constructs and initializes a Quat4d from the specified xyzw coordinates.
+   * @param x the x coordinate
+   * @param y the y coordinate
+   * @param z the z coordinate
+   * @param w the w scalar component
+   */
+  public Quat4d(double x, double y, double z, double w)
+  {
+      double mag;
+      mag = 1.0/Math.sqrt( x*x + y*y + z*z + w*w );
+      this.x =  x*mag;
+      this.y =  y*mag;
+      this.z =  z*mag;
+      this.w =  w*mag;
+
+  }
+
+  /**
+   * Constructs and initializes a Quat4d from the array of length 4. 
+   * @param q the array of length 4 containing xyzw in order
+   */
+  public Quat4d(double[] q)
+  {
+      double mag; 
+      mag = 1.0/Math.sqrt( q[0]*q[0] + q[1]*q[1] + q[2]*q[2] + q[3]*q[3] );
+      x =  q[0]*mag;
+      y =  q[1]*mag;
+      z =  q[2]*mag;
+      w =  q[3]*mag;
+
+  }
+
+  /**
+   * Constructs and initializes a Quat4d from the specified Quat4d.
+   * @param q1 the Quat4d containing the initialization x y z w data
+   */
+  public Quat4d(Quat4d q1)
+  {
+       super(q1);
+  }
+
+  /**
+   * Constructs and initializes a Quat4d from the specified Quat4f.
+   * @param q1 the Quat4f containing the initialization x y z w data
+   */
+  public Quat4d(Quat4f q1)
+  {
+     super(q1);
+  }
+
+
+    /** 
+     * Constructs and initializes a Quat4d from the specified Tuple4f. 
+     * @param t1 the Tuple4f containing the initialization x y z w data 
+     */  
+    public Quat4d(Tuple4f t1)  
+    { 
+      double mag;
+      mag = 1.0/Math.sqrt( t1.x*t1.x + t1.y*t1.y + t1.z*t1.z + t1.w*t1.w );
+      x =  t1.x*mag;
+      y =  t1.y*mag;
+      z =  t1.z*mag;
+      w =  t1.w*mag;
+
+    }
+    /** 
+     * Constructs and initializes a Quat4d from the specified Tuple4d.  
+     * @param t1 the Tuple4d containing the initialization x y z w data 
+     */  
+    public Quat4d(Tuple4d t1)
+    {
+      double mag;
+      mag = 1.0/Math.sqrt( t1.x*t1.x + t1.y*t1.y + t1.z*t1.z + t1.w*t1.w );
+      x =  t1.x*mag;
+      y =  t1.y*mag;
+      z =  t1.z*mag;
+      w =  t1.w*mag;
+    }
+
+
+  /**
+   * Constructs and initializes a Quat4d to (0,0,0,0).
+   */
+  public Quat4d()
+  {
+     super();
+  }
+
+
+  /**
+   * Sets the value of this quaternion to the conjugate of quaternion q1.
+   * @param q1 the source vector
+   */
+  public final void conjugate(Quat4d q1)
+  {
+    this.x = -q1.x;
+    this.y = -q1.y;
+    this.z = -q1.z;
+    this.w = q1.w;
+  }
+
+
+  /**
+   * Negate the value of of each of this quaternion's x,y,z coordinates 
+   *  in place.
+   */
+  public final void conjugate()
+  {
+    this.x = -this.x;
+    this.y = -this.y;
+    this.z = -this.z;
+  }
+
+
+  /**
+   * Sets the value of this quaternion to the quaternion product of
+   * quaternions q1 and q2 (this = q1 * q2).  
+   * Note that this is safe for aliasing (e.g. this can be q1 or q2).
+   * @param q1 the first quaternion
+   * @param q2 the second quaternion
+   */
+  public final void mul(Quat4d q1, Quat4d q2)
+  {
+    if (this != q1 && this != q2) {
+      this.w = q1.w*q2.w - q1.x*q2.x - q1.y*q2.y - q1.z*q2.z;
+      this.x = q1.w*q2.x + q2.w*q1.x + q1.y*q2.z - q1.z*q2.y;
+      this.y = q1.w*q2.y + q2.w*q1.y - q1.x*q2.z + q1.z*q2.x;
+      this.z = q1.w*q2.z + q2.w*q1.z + q1.x*q2.y - q1.y*q2.x;
+    } else {
+      double   x, y, w;
+
+      w = q1.w*q2.w - q1.x*q2.x - q1.y*q2.y - q1.z*q2.z;
+      x = q1.w*q2.x + q2.w*q1.x + q1.y*q2.z - q1.z*q2.y;
+      y = q1.w*q2.y + q2.w*q1.y - q1.x*q2.z + q1.z*q2.x;
+      this.z = q1.w*q2.z + q2.w*q1.z + q1.x*q2.y - q1.y*q2.x;
+      this.w = w;
+      this.x = x;
+      this.y = y;
+    }
+  }
+
+
+ /**
+   * Sets the value of this quaternion to the quaternion product of
+   * itself and q1 (this = this * q1).  
+   * @param q1 the other quaternion
+   */
+  public final void mul(Quat4d q1)
+  {
+      double     x, y, w; 
+
+       w = this.w*q1.w - this.x*q1.x - this.y*q1.y - this.z*q1.z;
+       x = this.w*q1.x + q1.w*this.x + this.y*q1.z - this.z*q1.y;
+       y = this.w*q1.y + q1.w*this.y - this.x*q1.z + this.z*q1.x;
+       this.z = this.w*q1.z + q1.w*this.z + this.x*q1.y - this.y*q1.x;
+       this.w = w;
+       this.x = x;
+       this.y = y;
+  } 
+
+
+ /** 
+   * Multiplies quaternion q1 by the inverse of quaternion q2 and places
+   * the value into this quaternion.  The value of both argument quaternions 
+   * is preservered (this = q1 * q2^-1).
+   * @param q1 the first quaternion 
+   * @param q2 the second quaternion
+   */ 
+  public final void mulInverse(Quat4d q1, Quat4d q2) 
+  {   
+      Quat4d  tempQuat = new Quat4d(q2);  
+      tempQuat.inverse(); 
+      this.mul(q1, tempQuat); 
+  }
+
+
+ /**
+   * Multiplies this quaternion by the inverse of quaternion q1 and places
+   * the value into this quaternion.  The value of the argument quaternion
+   * is preserved (this = this * q^-1).
+   * @param q1 the other quaternion
+   */
+  public final void mulInverse(Quat4d q1)
+  {  
+      Quat4d  tempQuat = new Quat4d(q1);
+
+      tempQuat.inverse();
+      this.mul(tempQuat);
+  }
+
+
+  /**
+   * Sets the value of this quaternion to quaternion inverse of quaternion q1.
+   * @param q1 the quaternion to be inverted
+   */
+  public final void inverse(Quat4d q1)
+  {
+    double norm;
+
+    norm = 1.0/(q1.w*q1.w + q1.x*q1.x + q1.y*q1.y + q1.z*q1.z);
+    this.w =  norm*q1.w;
+    this.x = -norm*q1.x;
+    this.y = -norm*q1.y;
+    this.z = -norm*q1.z;
+  }
+
+
+  /**
+   * Sets the value of this quaternion to the quaternion inverse of itself.
+   */
+  public final void inverse()
+  {
+    double norm;  
+    norm = 1.0/(this.w*this.w + this.x*this.x + this.y*this.y + this.z*this.z);
+    this.w *=  norm;
+    this.x *= -norm;
+    this.y *= -norm;
+    this.z *= -norm;
+  }
+
+
+  /**
+   * Sets the value of this quaternion to the normalized value
+   * of quaternion q1.
+   * @param q1 the quaternion to be normalized.
+   */
+  public final void normalize(Quat4d q1)
+  {
+    double norm;
+
+    norm = (q1.x*q1.x + q1.y*q1.y + q1.z*q1.z + q1.w*q1.w);
+
+    if (norm > 0.0) {
+      norm = 1.0/Math.sqrt(norm);
+      this.x = norm*q1.x;
+      this.y = norm*q1.y;
+      this.z = norm*q1.z;
+      this.w = norm*q1.w;
+    } else {
+      this.x =  0.0;
+      this.y =  0.0;
+      this.z =  0.0;
+      this.w =  0.0;
+    }
+  }
+
+
+  /**
+   * Normalizes the value of this quaternion in place.
+   */
+  public final void normalize()
+  {
+    double norm;
+
+    norm = (this.x*this.x + this.y*this.y + this.z*this.z + this.w*this.w);
+
+    if (norm > 0.0) {
+      norm = 1.0 / Math.sqrt(norm);
+      this.x *= norm;
+      this.y *= norm;
+      this.z *= norm;
+      this.w *= norm;
+    } else {
+      this.x =  0.0;
+      this.y =  0.0;
+      this.z =  0.0;
+      this.w =  0.0;
+    }
+  }
+
+
+    /**
+     * Sets the value of this quaternion to the rotational component of
+     * the passed matrix.
+     * @param m1 the matrix4f
+     */
+    public final void set(Matrix4f m1) 
+    {
+       double ww = 0.25*(m1.m00 + m1.m11 + m1.m22 + m1.m33);
+
+       if (ww >= 0) {
+           if (ww >= EPS2) {
+               this.w = Math.sqrt(ww);
+               ww =  0.25/this.w;
+               this.x =  ((m1.m21 - m1.m12)*ww);
+               this.y =  ((m1.m02 - m1.m20)*ww);
+               this.z =  ((m1.m10 - m1.m01)*ww);
+               return;
+           }
+       } else {
+           this.w = 0;
+           this.x = 0;
+           this.y = 0;
+           this.z = 1;
+           return;
+       }
+
+       this.w = 0;
+       ww = -0.5*(m1.m11 + m1.m22);
+       if (ww >= 0) {
+           if (ww >= EPS2) {
+               this.x =  Math.sqrt(ww);
+               ww = 1.0/(2.0*this.x);
+               this.y = (m1.m10*ww);
+               this.z = (m1.m20*ww);
+               return;
+           }
+       } else {
+           this.x = 0;
+           this.y = 0;
+           this.z = 1;
+           return;
+       }
+     
+       this.x = 0;
+       ww = 0.5*(1.0 - m1.m22);
+       if (ww >= EPS2) {
+           this.y = Math.sqrt(ww);
+           this.z = (m1.m21)/(2.0*this.y);
+           return;
+       }
+
+       this.y = 0;
+       this.z = 1;
+    }
+
+
+    /**
+     * Sets the value of this quaternion to the rotational component of
+     * the passed matrix.
+     * @param m1 the matrix4d
+     */
+    public final void set(Matrix4d m1)
+    {
+       double ww = 0.25*(m1.m00 + m1.m11 + m1.m22 + m1.m33);
+
+       if (ww >= 0) {
+           if (ww >= EPS2) {
+               this.w = Math.sqrt(ww);
+               ww = 0.25/this.w;
+               this.x = (m1.m21 - m1.m12)*ww;
+               this.y = (m1.m02 - m1.m20)*ww;
+               this.z = (m1.m10 - m1.m01)*ww;
+               return;
+           }
+       } else {
+           this.w = 0;
+           this.x = 0;
+           this.y = 0;
+           this.z = 1;
+           return;
+       }
+
+       this.w = 0;
+       ww = -0.5*(m1.m11 + m1.m22);
+       if (ww >= 0) {
+           if (ww >= EPS2){
+               this.x =  Math.sqrt(ww);
+               ww = 0.5/this.x;
+               this.y = m1.m10*ww;
+               this.z = m1.m20*ww;
+               return;
+           }
+       } else {
+           this.x = 0;
+           this.y = 0;
+           this.z = 1;
+           return;
+       }
+     
+       this.x = 0.0;
+       ww = 0.5*(1.0 - m1.m22);
+       if (ww >= EPS2) {
+           this.y =  Math.sqrt(ww);
+           this.z = m1.m21/(2.0*this.y);
+           return;
+       }
+       
+       this.y =  0;
+       this.z =  1;
+    }
+
+
+    /**
+     * Sets the value of this quaternion to the rotational component of
+     * the passed matrix.
+     * @param m1 the matrix3f
+     */
+    public final void set(Matrix3f m1)
+    {
+       double ww = 0.25*(m1.m00 + m1.m11 + m1.m22 + 1.0);
+
+       if (ww >= 0) {
+           if (ww >= EPS2) {
+               this.w = Math.sqrt(ww);
+               ww = 0.25/this.w;
+               this.x = ((m1.m21 - m1.m12)*ww);
+               this.y = ((m1.m02 - m1.m20)*ww);
+               this.z = ((m1.m10 - m1.m01)*ww);
+               return;
+           }
+       } else {
+           this.w = 0;
+           this.x = 0;
+           this.y = 0;
+           this.z = 1;
+           return;
+       }
+
+       this.w = 0;
+       ww = -0.5*(m1.m11 + m1.m22);
+       if (ww >= 0) {
+           if (ww >= EPS2) {
+               this.x = Math.sqrt(ww);
+               ww = 0.5/this.x;
+               this.y = (m1.m10*ww);
+               this.z = (m1.m20*ww);
+               return;
+           }
+       } else {
+           this.x = 0;
+           this.y = 0;
+           this.z = 1;
+           return;
+       }
+     
+       this.x = 0;
+       ww =  0.5*(1.0 - m1.m22);
+       if (ww >= EPS2) {
+           this.y = Math.sqrt(ww);
+           this.z = (m1.m21/(2.0*this.y));
+       }
+     
+       this.y =  0;
+       this.z =  1;
+    }
+
+    
+    /**
+     * Sets the value of this quaternion to the rotational component of
+     * the passed matrix.
+     * @param m1 the matrix3d
+     */
+    public final void set(Matrix3d m1)
+    {
+       double ww = 0.25*(m1.m00 + m1.m11 + m1.m22 + 1.0);
+
+       if (ww >= 0) {
+           if (ww >= EPS2) {
+               this.w = Math.sqrt(ww);
+               ww = 0.25/this.w;
+               this.x = (m1.m21 - m1.m12)*ww;
+               this.y = (m1.m02 - m1.m20)*ww;
+               this.z = (m1.m10 - m1.m01)*ww;
+               return;
+           }
+       } else {
+           this.w = 0;
+           this.x = 0;
+           this.y = 0;
+           this.z = 1;
+           return;
+       }
+
+       this.w = 0;
+       ww = -0.5*(m1.m11 + m1.m22);
+       if (ww >= 0) {
+           if (ww >= EPS2) {
+               this.x =  Math.sqrt(ww);
+               ww = 0.5/this.x;
+               this.y = m1.m10*ww;
+               this.z = m1.m20*ww;
+               return;
+           }
+       } else {
+           this.x = 0;
+           this.y = 0;
+           this.z = 1;         
+           return;
+       }
+     
+       this.x = 0;
+       ww = 0.5*(1.0 - m1.m22);
+       if (ww >= EPS2) {
+           this.y =  Math.sqrt(ww);
+           this.z = m1.m21/(2.0*this.y);
+           return;
+       }
+     
+       this.y = 0;
+       this.z = 1;
+    }
+
+    
+    /**
+     * Sets the value of this quaternion to the equivalent rotation
+     * of the AxisAngle argument.
+     * @param a  the AxisAngle to be emulated
+     */
+    public final void set(AxisAngle4f a)
+    {
+       double mag,amag;
+       // Quat = cos(theta/2) + sin(theta/2)(roation_axis) 
+
+       amag = Math.sqrt( a.x*a.x + a.y*a.y + a.z*a.z);
+       if( amag < EPS ) {
+           w = 0.0;
+           x = 0.0;
+           y = 0.0;
+           z = 0.0;
+       } else {
+           mag = Math.sin(a.angle/2.0);
+           amag = 1.0/amag;
+           w = Math.cos(a.angle/2.0);
+           x = a.x*amag*mag;
+           y = a.y*amag*mag;
+           z = a.z*amag*mag;
+       }
+       
+    }
+
+    /**
+     * Sets the value of this quaternion to the equivalent rotation
+     * of the AxisAngle argument.
+     * @param a  the AxisAngle to be emulated
+     */
+    public final void set(AxisAngle4d a)
+    {
+       double mag,amag;
+       // Quat = cos(theta/2) + sin(theta/2)(roation_axis) 
+       
+       amag = Math.sqrt( a.x*a.x + a.y*a.y + a.z*a.z);
+       if( amag < EPS ) {
+           w = 0.0;
+           x = 0.0;
+           y = 0.0;
+           z = 0.0;
+       } else {  
+           amag = 1.0/amag; 
+           mag = Math.sin(a.angle/2.0);
+           w = Math.cos(a.angle/2.0);
+       x = a.x*amag*mag;
+       y = a.y*amag*mag;
+       z = a.z*amag*mag;
+       }
+       
+    }
+    
+ /**
+   *  Performs a great circle interpolation between this quaternion
+   *  and the quaternion parameter and places the result into this
+   *  quaternion.
+   *  @param q1  the other quaternion
+   *  @param alpha  the alpha interpolation parameter
+   */
+  public final void interpolate(Quat4d q1, double alpha) {
+      // From "Advanced Animation and Rendering Techniques"
+      // by Watt and Watt pg. 364, function as implemented appeared to be
+      // incorrect.  Fails to choose the same quaternion for the double
+      // covering. Resulting in change of direction for rotations.
+      // Fixed function to negate the first quaternion in the case that the
+      // dot product of q1 and this is negative. Second case was not needed.
+      double dot,s1,s2,om,sinom;
+
+      dot = x*q1.x + y*q1.y + z*q1.z + w*q1.w;
+
+      if ( dot < 0 ) {
+        // negate quaternion
+        q1.x = -q1.x;  q1.y = -q1.y;  q1.z = -q1.z;  q1.w = -q1.w;
+        dot = -dot;
+      }
+
+      if ( (1.0 - dot) > EPS ) {
+        om = Math.acos(dot);
+        sinom = Math.sin(om);
+        s1 = Math.sin((1.0-alpha)*om)/sinom;
+        s2 = Math.sin( alpha*om)/sinom;
+      } else{
+        s1 = 1.0 - alpha;
+        s2 = alpha;
+      }
+
+      w = s1*w + s2*q1.w;
+      x = s1*x + s2*q1.x;
+      y = s1*y + s2*q1.y;
+      z = s1*z + s2*q1.z;
+    }
+
+/**
+   *  Performs a great circle interpolation between quaternion q1
+   *  and quaternion q2 and places the result into this quaternion.
+   *  @param q1  the first quaternion
+   *  @param q2  the second quaternion
+   *  @param alpha  the alpha interpolation parameter
+   */
+  public final void interpolate(Quat4d q1, Quat4d q2, double alpha) {
+      // From "Advanced Animation and Rendering Techniques"
+      // by Watt and Watt pg. 364, function as implemented appeared to be
+      // incorrect.  Fails to choose the same quaternion for the double
+      // covering. Resulting in change of direction for rotations.
+      // Fixed function to negate the first quaternion in the case that the
+      // dot product of q1 and this is negative. Second case was not needed.
+      double dot,s1,s2,om,sinom;
+
+      dot = q2.x*q1.x + q2.y*q1.y + q2.z*q1.z + q2.w*q1.w;
+
+      if ( dot < 0 ) {
+        // negate quaternion
+        q1.x = -q1.x;  q1.y = -q1.y;  q1.z = -q1.z;  q1.w = -q1.w;
+        dot = -dot;
+      }
+
+      if ( (1.0 - dot) > EPS ) {
+        om = Math.acos(dot);
+        sinom = Math.sin(om);
+        s1 = Math.sin((1.0-alpha)*om)/sinom;
+        s2 = Math.sin( alpha*om)/sinom;
+      } else{
+        s1 = 1.0 - alpha;
+        s2 = alpha;
+      }
+      w = s1*q1.w + s2*q2.w;
+      x = s1*q1.x + s2*q2.x;
+      y = s1*q1.y + s2*q2.y;
+      z = s1*q1.z + s2*q2.z;
+    }
+
+}
diff --git a/javax.vecmath/src/javax/vecmath/Quat4f.java b/javax.vecmath/src/javax/vecmath/Quat4f.java
new file mode 100644 (file)
index 0000000..d29e1d2
--- /dev/null
@@ -0,0 +1,695 @@
+/*
+ * $RCSfile: Quat4f.java,v $
+ *
+ * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ * $Revision: 1.6 $
+ * $Date: 2008/02/28 20:18:50 $
+ * $State: Exp $
+ */
+
+package javax.vecmath;
+
+import java.lang.Math;
+
+/**
+ * A 4 element unit quaternion represented by single precision floating 
+ * point x,y,z,w coordinates.  The quaternion is always normalized.
+ *
+ */
+public class Quat4f extends Tuple4f implements java.io.Serializable {
+
+  // Combatible with 1.1
+  static final long serialVersionUID = 2675933778405442383L;
+
+  final static double EPS = 0.000001;
+  final static double EPS2 = 1.0e-30;
+  final static double PIO2 = 1.57079632679;
+
+  /**
+   * Constructs and initializes a Quat4f from the specified xyzw coordinates.
+   * @param x the x coordinate
+   * @param y the y coordinate
+   * @param z the z coordinate
+   * @param w the w scalar component
+   */
+  public Quat4f(float x, float y, float z, float w)
+  {
+      float mag;
+      mag = (float)(1.0/Math.sqrt( x*x + y*y + z*z + w*w ));
+      this.x =  x*mag;
+      this.y =  y*mag;
+      this.z =  z*mag;
+      this.w =  w*mag;
+
+  }
+
+  /**
+   * Constructs and initializes a Quat4f from the array of length 4. 
+   * @param q the array of length 4 containing xyzw in order
+   */
+  public Quat4f(float[] q)
+  {
+      float mag;
+      mag = (float)(1.0/Math.sqrt( q[0]*q[0] + q[1]*q[1] + q[2]*q[2] + q[3]*q[3] ));
+      x =  q[0]*mag;
+      y =  q[1]*mag;
+      z =  q[2]*mag;
+      w =  q[3]*mag;
+
+  }
+
+
+  /**
+   * Constructs and initializes a Quat4f from the specified Quat4f.
+   * @param q1 the Quat4f containing the initialization x y z w data
+   */
+  public Quat4f(Quat4f q1)
+  {
+       super(q1);
+  }
+
+  /**
+   * Constructs and initializes a Quat4f from the specified Quat4d.
+   * @param q1 the Quat4d containing the initialization x y z w data
+   */
+  public Quat4f(Quat4d q1)
+  {
+      super(q1);
+  }
+
+
+    /** 
+     * Constructs and initializes a Quat4f from the specified Tuple4f. 
+     * @param t1 the Tuple4f containing the initialization x y z w data 
+     */  
+    public Quat4f(Tuple4f t1)  
+    { 
+      float mag;
+      mag = (float)(1.0/Math.sqrt( t1.x*t1.x + t1.y*t1.y + t1.z*t1.z + t1.w*t1.w ));
+      x =  t1.x*mag;
+      y =  t1.y*mag;
+      z =  t1.z*mag;
+      w =  t1.w*mag;
+
+    }
+    /** 
+     * Constructs and initializes a Quat4f from the specified Tuple4d.  
+     * @param t1 the Tuple4d containing the initialization x y z w data 
+     */  
+    public Quat4f(Tuple4d t1)
+    {
+      double mag;
+      mag = 1.0/Math.sqrt( t1.x*t1.x + t1.y*t1.y + t1.z*t1.z + t1.w*t1.w );
+      x =  (float)(t1.x*mag);
+      y =  (float)(t1.y*mag);
+      z =  (float)(t1.z*mag);
+      w =  (float)(t1.w*mag);
+    }
+
+
+  /**
+   * Constructs and initializes a Quat4f to (0.0,0.0,0.0,0.0).
+   */
+  public Quat4f()
+  {
+      super();
+  }
+
+
+  /**
+   * Sets the value of this quaternion to the conjugate of quaternion q1.
+   * @param q1 the source vector
+   */
+  public final void conjugate(Quat4f q1)
+  {
+    this.x = -q1.x;
+    this.y = -q1.y;
+    this.z = -q1.z;
+    this.w = q1.w;
+  }
+
+  /**
+   * Sets the value of this quaternion to the conjugate of itself.
+   */
+  public final void conjugate()
+  {
+    this.x = -this.x;
+    this.y = -this.y;
+    this.z = -this.z;
+  }
+
+
+  /**
+   * Sets the value of this quaternion to the quaternion product of
+   * quaternions q1 and q2 (this = q1 * q2).  
+   * Note that this is safe for aliasing (e.g. this can be q1 or q2).
+   * @param q1 the first quaternion
+   * @param q2 the second quaternion
+   */
+  public final void mul(Quat4f q1, Quat4f q2)
+  {
+    if (this != q1 && this != q2) {
+      this.w = q1.w*q2.w - q1.x*q2.x - q1.y*q2.y - q1.z*q2.z;
+      this.x = q1.w*q2.x + q2.w*q1.x + q1.y*q2.z - q1.z*q2.y;
+      this.y = q1.w*q2.y + q2.w*q1.y - q1.x*q2.z + q1.z*q2.x;
+      this.z = q1.w*q2.z + q2.w*q1.z + q1.x*q2.y - q1.y*q2.x;
+    } else {
+      float    x, y, w;
+
+      w = q1.w*q2.w - q1.x*q2.x - q1.y*q2.y - q1.z*q2.z;
+      x = q1.w*q2.x + q2.w*q1.x + q1.y*q2.z - q1.z*q2.y;
+      y = q1.w*q2.y + q2.w*q1.y - q1.x*q2.z + q1.z*q2.x;
+      this.z = q1.w*q2.z + q2.w*q1.z + q1.x*q2.y - q1.y*q2.x;
+      this.w = w;
+      this.x = x;
+      this.y = y;
+    }
+  }
+
+
+ /**
+   * Sets the value of this quaternion to the quaternion product of
+   * itself and q1 (this = this * q1).  
+   * @param q1 the other quaternion
+   */
+  public final void mul(Quat4f q1)
+  {
+      float     x, y, w; 
+
+       w = this.w*q1.w - this.x*q1.x - this.y*q1.y - this.z*q1.z;
+       x = this.w*q1.x + q1.w*this.x + this.y*q1.z - this.z*q1.y;
+       y = this.w*q1.y + q1.w*this.y - this.x*q1.z + this.z*q1.x;
+       this.z = this.w*q1.z + q1.w*this.z + this.x*q1.y - this.y*q1.x;
+       this.w = w;
+       this.x = x;
+       this.y = y;
+  } 
+
+
+ /** 
+   * Multiplies quaternion q1 by the inverse of quaternion q2 and places
+   * the value into this quaternion.  The value of both argument quaternions 
+   * is preservered (this = q1 * q2^-1).
+   * @param q1 the first quaternion
+   * @param q2 the second quaternion
+   */ 
+  public final void mulInverse(Quat4f q1, Quat4f q2) 
+  {   
+      Quat4f  tempQuat = new Quat4f(q2);  
+      tempQuat.inverse(); 
+      this.mul(q1, tempQuat); 
+  }
+
+
+ /**
+   * Multiplies this quaternion by the inverse of quaternion q1 and places
+   * the value into this quaternion.  The value of the argument quaternion
+   * is preserved (this = this * q^-1).
+   * @param q1 the other quaternion
+   */
+  public final void mulInverse(Quat4f q1)
+  {  
+      Quat4f  tempQuat = new Quat4f(q1);
+
+      tempQuat.inverse();
+      this.mul(tempQuat);
+  }
+
+
+
+  /**
+   * Sets the value of this quaternion to quaternion inverse of quaternion q1.
+   * @param q1 the quaternion to be inverted
+   */
+  public final void inverse(Quat4f q1)
+  {
+    float norm;
+
+    norm = 1.0f/(q1.w*q1.w + q1.x*q1.x + q1.y*q1.y + q1.z*q1.z);
+    this.w =  norm*q1.w;
+    this.x = -norm*q1.x;
+    this.y = -norm*q1.y;
+    this.z = -norm*q1.z;
+  }
+
+
+  /**
+   * Sets the value of this quaternion to the quaternion inverse of itself.
+   */
+  public final void inverse()
+  {
+    float norm;  
+    norm = 1.0f/(this.w*this.w + this.x*this.x + this.y*this.y + this.z*this.z);
+    this.w *=  norm;
+    this.x *= -norm;
+    this.y *= -norm;
+    this.z *= -norm;
+  }
+
+
+  /**
+   * Sets the value of this quaternion to the normalized value
+   * of quaternion q1.
+   * @param q1 the quaternion to be normalized.
+   */
+  public final void normalize(Quat4f q1)
+  {
+    float norm;
+
+    norm = (q1.x*q1.x + q1.y*q1.y + q1.z*q1.z + q1.w*q1.w);
+
+    if (norm > 0.0f) {
+      norm = 1.0f/(float)Math.sqrt(norm);
+      this.x = norm*q1.x;
+      this.y = norm*q1.y;
+      this.z = norm*q1.z;
+      this.w = norm*q1.w;
+    } else {
+      this.x = (float) 0.0;
+      this.y = (float) 0.0;
+      this.z = (float) 0.0;
+      this.w = (float) 0.0;
+    }
+  }
+
+
+  /**
+   * Normalizes the value of this quaternion in place.
+   */
+  public final void normalize()
+  {
+    float norm;
+
+    norm = (this.x*this.x + this.y*this.y + this.z*this.z + this.w*this.w);
+
+    if (norm > 0.0f) {
+      norm = 1.0f / (float)Math.sqrt(norm);
+      this.x *= norm;
+      this.y *= norm;
+      this.z *= norm;
+      this.w *= norm;
+    } else {
+      this.x = (float) 0.0;
+      this.y = (float) 0.0;
+      this.z = (float) 0.0;
+      this.w = (float) 0.0;
+    }
+  }
+
+
+  /**
+   * Sets the value of this quaternion to the rotational component of
+   * the passed matrix.
+   * @param m1 the Matrix4f
+   */
+   public final void set(Matrix4f m1) 
+   {
+       float ww = 0.25f*(m1.m00 + m1.m11 + m1.m22 + m1.m33);
+
+       if (ww >= 0) {
+          if (ww >= EPS2) {
+              this.w = (float) Math.sqrt((double)ww);
+              ww =  0.25f/this.w;
+              this.x = (m1.m21 - m1.m12)*ww;
+              this.y = (m1.m02 - m1.m20)*ww;
+              this.z = (m1.m10 - m1.m01)*ww;
+              return;
+          } 
+       } else {
+          this.w = 0;
+          this.x = 0;
+          this.y = 0;
+          this.z = 1;
+          return;
+       }
+
+       this.w = 0;
+       ww = -0.5f*(m1.m11 + m1.m22);
+       
+       if (ww >= 0) {
+          if (ww >= EPS2) {
+              this.x = (float) Math.sqrt((double) ww);
+              ww = 1.0f/(2.0f*this.x);
+              this.y = m1.m10*ww;
+              this.z = m1.m20*ww;
+              return;
+          }
+       } else {
+          this.x = 0;
+          this.y = 0;
+          this.z = 1;
+          return;
+       }
+     
+       this.x = 0;
+       ww = 0.5f*(1.0f - m1.m22);
+
+       if (ww >= EPS2) {
+          this.y = (float) Math.sqrt((double) ww);
+          this.z = m1.m21/(2.0f*this.y);
+          return;
+       }
+     
+       this.y = 0;
+       this.z = 1;
+   }
+
+
+    /**
+     * Sets the value of this quaternion to the rotational component of
+     * the passed matrix.
+     * @param m1 the Matrix4d
+     */
+    public final void set(Matrix4d m1)
+    {
+       double ww = 0.25*(m1.m00 + m1.m11 + m1.m22 + m1.m33);
+
+       if (ww >= 0) {
+           if (ww >= EPS2) {
+               this.w = (float) Math.sqrt(ww);
+               ww = 0.25/this.w;
+               this.x = (float) ((m1.m21 - m1.m12)*ww);
+               this.y = (float) ((m1.m02 - m1.m20)*ww);
+               this.z = (float) ((m1.m10 - m1.m01)*ww);
+               return;
+           }
+       } else {
+           this.w = 0;
+           this.x = 0;
+           this.y = 0;
+           this.z = 1;
+           return;
+       }
+
+       this.w = 0;
+       ww = -0.5*(m1.m11 + m1.m22);
+       if (ww >= 0) {
+           if (ww >= EPS2) {
+               this.x = (float) Math.sqrt(ww);
+               ww = 0.5/this.x;
+               this.y = (float)(m1.m10*ww);
+               this.z = (float)(m1.m20*ww);
+               return;
+           } 
+       } else {
+           this.x = 0;
+           this.y = 0;
+           this.z = 1;
+           return;
+       }
+     
+       this.x = 0;
+       ww = 0.5*(1.0 - m1.m22);
+       if (ww >= EPS2) {
+           this.y = (float) Math.sqrt(ww);
+           this.z = (float) (m1.m21/(2.0*(double)(this.y)));
+           return;
+       }
+     
+       this.y = 0;
+       this.z = 1;
+    }
+
+
+    /**
+     * Sets the value of this quaternion to the rotational component of
+     * the passed matrix.
+     * @param m1 the Matrix3f
+     */
+    public final void set(Matrix3f m1)
+    {
+       float ww = 0.25f*(m1.m00 + m1.m11 + m1.m22 + 1.0f);
+
+       if (ww >= 0) {
+           if (ww >= EPS2) {
+               this.w = (float) Math.sqrt((double) ww);
+               ww = 0.25f/this.w;
+               this.x = (m1.m21 - m1.m12)*ww;
+               this.y = (m1.m02 - m1.m20)*ww;
+               this.z = (m1.m10 - m1.m01)*ww;
+               return;
+           }
+       } else {
+           this.w = 0;
+           this.x = 0;
+           this.y = 0;
+           this.z = 1;
+           return;
+       }
+
+       this.w = 0;
+       ww = -0.5f*(m1.m11 + m1.m22);
+       if (ww >= 0) {
+           if (ww >= EPS2) {
+               this.x = (float) Math.sqrt((double) ww);
+               ww = 0.5f/this.x;
+               this.y = m1.m10*ww;
+               this.z = m1.m20*ww;
+               return;
+           }
+       } else {
+           this.x = 0;
+           this.y = 0;
+           this.z = 1;
+           return;
+       }
+
+       this.x = 0;
+       ww =  0.5f*(1.0f - m1.m22);
+       if (ww >= EPS2) {
+           this.y = (float) Math.sqrt((double) ww);
+           this.z = m1.m21/(2.0f*this.y);
+           return;
+       }
+     
+       this.y = 0;
+       this.z = 1;
+    }
+
+
+    /**
+     * Sets the value of this quaternion to the rotational component of
+     * the passed matrix.
+     * @param m1 the Matrix3d
+     */
+    public final void set(Matrix3d m1)
+    {
+       double ww = 0.25*(m1.m00 + m1.m11 + m1.m22 + 1.0f);
+
+       if (ww >= 0) {
+           if (ww >= EPS2) {
+               this.w = (float) Math.sqrt(ww);
+               ww = 0.25/this.w;
+               this.x = (float) ((m1.m21 - m1.m12)*ww);
+               this.y = (float) ((m1.m02 - m1.m20)*ww);
+               this.z = (float) ((m1.m10 - m1.m01)*ww);
+               return;
+           }
+       } else {
+           this.w = 0;
+           this.x = 0;
+           this.y = 0;
+           this.z = 1;
+           return;
+       }
+
+       this.w = 0;
+       ww = -0.5*(m1.m11 + m1.m22);
+       if (ww >= 0) {
+           if (ww >= EPS2) {
+               this.x = (float) Math.sqrt(ww);
+               ww = 0.5/this.x;
+               this.y = (float) (m1.m10*ww);
+               this.z = (float) (m1.m20*ww);
+               return;
+           }
+       } else {
+           this.x = 0;
+           this.y = 0;
+           this.z = 1;
+           return;
+       }
+     
+       this.x = 0;
+       ww = 0.5*(1.0 - m1.m22);
+       if (ww >= EPS2) {
+           this.y = (float) Math.sqrt(ww);
+           this.z = (float) (m1.m21/(2.0*(double)(this.y)));
+           return;
+       }
+     
+       this.y = 0;
+       this.z = 1;
+    }
+
+
+    /**
+     * Sets the value of this quaternion to the equivalent rotation
+     * of the AxisAngle argument.
+     * @param a  the AxisAngle to be emulated
+     */
+    public final void set(AxisAngle4f a)
+    {
+       float mag,amag;
+       // Quat = cos(theta/2) + sin(theta/2)(roation_axis) 
+       amag = (float)Math.sqrt( a.x*a.x + a.y*a.y + a.z*a.z);
+       if (amag < EPS ) {
+           w = 0.0f;
+           x = 0.0f;
+           y = 0.0f;
+           z = 0.0f;
+       } else {  
+           amag = 1.0f/amag; 
+           mag = (float)Math.sin(a.angle/2.0);
+           w = (float)Math.cos(a.angle/2.0);
+           x = a.x*amag*mag;
+           y = a.y*amag*mag;
+           z = a.z*amag*mag;
+       }
+    }
+
+
+    /**
+     * Sets the value of this quaternion to the equivalent rotation
+     * of the AxisAngle argument.
+     * @param a  the AxisAngle to be emulated
+     */
+    public final void set(AxisAngle4d a)
+    {
+       float mag,amag;
+       // Quat = cos(theta/2) + sin(theta/2)(roation_axis) 
+       
+       amag = (float)(1.0/Math.sqrt( a.x*a.x + a.y*a.y + a.z*a.z));
+       
+       if (amag < EPS ) {
+           w = 0.0f;
+           x = 0.0f;
+           y = 0.0f;
+           z = 0.0f;
+       } else {  
+           amag = 1.0f/amag; 
+           mag = (float)Math.sin(a.angle/2.0);
+           w = (float)Math.cos(a.angle/2.0);
+           x = (float)a.x*amag*mag;
+           y = (float)a.y*amag*mag;
+           z = (float)a.z*amag*mag;
+       }
+       
+    }
+    
+
+    /**
+     *  Performs a great circle interpolation between this quaternion
+     *  and the quaternion parameter and places the result into this
+     *  quaternion.
+     *  @param q1  the other quaternion
+     *  @param alpha  the alpha interpolation parameter
+     */
+    public final void interpolate(Quat4f q1, float alpha) {
+       // From "Advanced Animation and Rendering Techniques"
+       // by Watt and Watt pg. 364, function as implemented appeared to be 
+       // incorrect.  Fails to choose the same quaternion for the double
+       // covering. Resulting in change of direction for rotations.
+       // Fixed function to negate the first quaternion in the case that the
+       // dot product of q1 and this is negative. Second case was not needed. 
+    
+     double dot,s1,s2,om,sinom;
+
+     dot = x*q1.x + y*q1.y + z*q1.z + w*q1.w;
+
+     if ( dot < 0 ) {
+        // negate quaternion
+       q1.x = -q1.x;  q1.y = -q1.y;  q1.z = -q1.z;  q1.w = -q1.w;
+       dot = -dot;
+     }
+
+     if ( (1.0 - dot) > EPS ) {
+       om = Math.acos(dot);
+       sinom = Math.sin(om);
+       s1 = Math.sin((1.0-alpha)*om)/sinom;
+       s2 = Math.sin( alpha*om)/sinom;
+     } else{
+       s1 = 1.0 - alpha;
+       s2 = alpha;
+     }
+
+     w = (float)(s1*w + s2*q1.w);
+     x = (float)(s1*x + s2*q1.x);
+     y = (float)(s1*y + s2*q1.y);
+     z = (float)(s1*z + s2*q1.z);
+  }
+
+
+
+  /** 
+    *  Performs a great circle interpolation between quaternion q1
+    *  and quaternion q2 and places the result into this quaternion. 
+    *  @param q1  the first quaternion
+    *  @param q2  the second quaternion
+    *  @param alpha  the alpha interpolation parameter 
+    */   
+    public final void interpolate(Quat4f q1, Quat4f q2, float alpha) { 
+       // From "Advanced Animation and Rendering Techniques"
+       // by Watt and Watt pg. 364, function as implemented appeared to be 
+       // incorrect.  Fails to choose the same quaternion for the double
+       // covering. Resulting in change of direction for rotations.
+       // Fixed function to negate the first quaternion in the case that the
+       // dot product of q1 and this is negative. Second case was not needed. 
+
+     double dot,s1,s2,om,sinom;
+
+     dot = q2.x*q1.x + q2.y*q1.y + q2.z*q1.z + q2.w*q1.w;
+     
+     if ( dot < 0 ) {
+        // negate quaternion
+       q1.x = -q1.x;  q1.y = -q1.y;  q1.z = -q1.z;  q1.w = -q1.w;
+       dot = -dot;
+     }
+
+     if ( (1.0 - dot) > EPS ) {
+       om = Math.acos(dot);
+       sinom = Math.sin(om);
+       s1 = Math.sin((1.0-alpha)*om)/sinom;
+       s2 = Math.sin( alpha*om)/sinom;
+     } else{
+       s1 = 1.0 - alpha;
+       s2 = alpha;
+     }
+     w = (float)(s1*q1.w + s2*q2.w);
+     x = (float)(s1*q1.x + s2*q2.x);
+     y = (float)(s1*q1.y + s2*q2.y);
+     z = (float)(s1*q1.z + s2*q2.z);
+  }
+
+}
+
+
+
+
diff --git a/javax.vecmath/src/javax/vecmath/SingularMatrixException.java b/javax.vecmath/src/javax/vecmath/SingularMatrixException.java
new file mode 100644 (file)
index 0000000..eccc318
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * $RCSfile: SingularMatrixException.java,v $
+ *
+ * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ * $Revision: 1.5 $
+ * $Date: 2008/02/28 20:18:50 $
+ * $State: Exp $
+ */
+
+package javax.vecmath;
+
+/**
+ * Indicates that inverse of a matrix can not be computed.
+ */
+public class SingularMatrixException extends RuntimeException{
+
+/**
+ * Create the exception object with default values.
+ */
+  public SingularMatrixException(){
+  }
+
+/**
+ * Create the exception object that outputs message.
+ * @param str the message string to be output.
+ */
+  public SingularMatrixException(String str){
+
+    super(str);
+  }
+
+}
diff --git a/javax.vecmath/src/javax/vecmath/TexCoord2f.java b/javax.vecmath/src/javax/vecmath/TexCoord2f.java
new file mode 100644 (file)
index 0000000..10a9b32
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * $RCSfile: TexCoord2f.java,v $
+ *
+ * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ * $Revision: 1.5 $
+ * $Date: 2008/02/28 20:18:50 $
+ * $State: Exp $
+ */
+
+package javax.vecmath;
+
+import java.lang.Math;
+
+/**
+ * A 2-element vector that is represented by single-precision floating 
+ * point x,y coordinates.
+ *
+ */
+public class TexCoord2f extends Tuple2f implements java.io.Serializable {
+
+    // Combatible with 1.1
+    static final long serialVersionUID = 7998248474800032487L;
+
+    /**
+     * Constructs and initializes a TexCoord2f from the specified xy coordinates.
+     * @param x the x coordinate
+     * @param y the y coordinate
+     */
+    public TexCoord2f(float x, float y)
+    {
+         super(x,y);
+    }
+
+
+    /**
+     * Constructs and initializes a TexCoord2f from the specified array.
+     * @param v the array of length 2 containing xy in order
+     */
+    public TexCoord2f(float[] v)
+    {
+         super(v);
+    }
+
+
+    /**
+     * Constructs and initializes a TexCoord2f from the specified TexCoord2f.
+     * @param v1 the TexCoord2f containing the initialization x y data
+     */
+    public TexCoord2f(TexCoord2f v1)
+    {
+        super(v1);
+    }
+
+
+    /**
+     * Constructs and initializes a TexCoord2f from the specified Tuple2f.
+     * @param t1 the Tuple2f containing the initialization x y data
+     */ 
+    public TexCoord2f(Tuple2f t1) 
+    {
+       super(t1);
+    }
+
+
+    /**
+     * Constructs and initializes a TexCoord2f to (0,0).
+     */
+    public TexCoord2f()
+    {
+       super();
+    }
+
+
+}
diff --git a/javax.vecmath/src/javax/vecmath/TexCoord3f.java b/javax.vecmath/src/javax/vecmath/TexCoord3f.java
new file mode 100644 (file)
index 0000000..ec6499a
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * $RCSfile: TexCoord3f.java,v $
+ *
+ * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ * $Revision: 1.5 $
+ * $Date: 2008/02/28 20:18:50 $
+ * $State: Exp $
+ */
+
+package javax.vecmath;
+
+import java.lang.Math;
+
+/**
+ * A 3 element texture coordinate that is represented by single precision 
+ * floating point x,y,z coordinates.
+ *
+ */
+public class TexCoord3f extends Tuple3f implements java.io.Serializable {
+
+    // Combatible with 1.1
+    static final long serialVersionUID = -3517736544731446513L;
+
+    /**
+     * Constructs and initializes a TexCoord3f from the specified xyz
+     * coordinates.
+     * @param x the x coordinate
+     * @param y the y coordinate
+     * @param z the z coordinate
+     */
+    public TexCoord3f(float x, float y, float z)
+    {
+        super(x,y,z);
+    }
+
+
+    /**
+     * Constructs and initializes a TexCoord3f from the array of length 3.
+     * @param v the array of length 3 containing xyz in order
+     */
+    public TexCoord3f(float[] v)
+    {
+       super(v);
+    }
+
+
+    /**
+     * Constructs and initializes a TexCoord3f from the specified TexCoord3f.
+     * @param v1 the TexCoord3f containing the initialization x y z data
+     */
+    public TexCoord3f(TexCoord3f v1)
+    {
+       super(v1);
+    }
+
+
+    /**
+     * Constructs and initializes a TexCoord3f from the specified Tuple3f.
+     * @param t1 the Tuple3f containing the initialization x y z data
+     */ 
+    public TexCoord3f(Tuple3f t1) 
+    {
+       super(t1);
+    }
+
+
+    /**
+     * Constructs and initializes a TexCoord3f from the specified Tuple3d.
+     * @param t1 the Tuple3d containing the initialization x y z data
+     */ 
+    public TexCoord3f(Tuple3d t1) 
+    {
+       super(t1);
+    }
+
+
+    /**
+     * Constructs and initializes a TexCoord3f to (0,0,0).
+     */
+    public TexCoord3f()
+    {
+        super();
+    }
+
+}
diff --git a/javax.vecmath/src/javax/vecmath/TexCoord4f.java b/javax.vecmath/src/javax/vecmath/TexCoord4f.java
new file mode 100644 (file)
index 0000000..d7000c4
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * $RCSfile: TexCoord4f.java,v $
+ *
+ * Copyright 2001-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ * $Revision: 1.6 $
+ * $Date: 2008/02/28 20:18:50 $
+ * $State: Exp $
+ */
+
+package javax.vecmath;
+
+import java.lang.Math;
+
+/**
+ * A 4 element texture coordinate that is represented by single precision 
+ * floating point x,y,z,w coordinates.
+ *
+ * @since vecmath 1.3
+ */
+public class TexCoord4f extends Tuple4f implements java.io.Serializable {
+
+    // Combatible with 1.1
+    static final long serialVersionUID = -3517736544731446513L;
+
+    /**
+     * Constructs and initializes a TexCoord4f from the specified xyzw
+     * coordinates.
+     * @param x the x coordinate
+     * @param y the y coordinate
+     * @param z the z coordinate
+     * @param w the w coordinate
+     */
+    public TexCoord4f(float x, float y, float z, float w)
+    {
+        super(x,y,z,w);
+    }
+
+
+    /**
+     * Constructs and initializes a TexCoord4f from the array of length 4.
+     * @param v the array of length w containing xyzw in order
+     */
+    public TexCoord4f(float[] v)
+    {
+       super(v);
+    }
+
+
+    /**
+     * Constructs and initializes a TexCoord4f from the specified TexCoord4f.
+     * @param v1 the TexCoord4f containing the initialization x y z w data
+     */
+    public TexCoord4f(TexCoord4f v1)
+    {
+       super(v1);
+    }
+
+
+    /**
+     * Constructs and initializes a TexCoord4f from the specified Tuple4f.
+     * @param t1 the Tuple4f containing the initialization x y z w data
+     */ 
+    public TexCoord4f(Tuple4f t1) 
+    {
+       super(t1);
+    }
+
+
+    /**
+     * Constructs and initializes a TexCoord4f from the specified Tuple4d.
+     * @param t1 the Tuple4d containing the initialization x y z w data
+     */ 
+    public TexCoord4f(Tuple4d t1) 
+    {
+       super(t1);
+    }
+
+
+    /**
+     * Constructs and initializes a TexCoord4f to (0,0,0,0).
+     */
+    public TexCoord4f()
+    {
+        super();
+    }
+
+}
diff --git a/javax.vecmath/src/javax/vecmath/Tuple2d.java b/javax.vecmath/src/javax/vecmath/Tuple2d.java
new file mode 100644 (file)
index 0000000..c721c5c
--- /dev/null
@@ -0,0 +1,606 @@
+/*
+ * $RCSfile: Tuple2d.java,v $
+ *
+ * Copyright 1998-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ * $Revision: 1.8 $
+ * $Date: 2008/02/28 20:18:50 $
+ * $State: Exp $
+ */
+
+package javax.vecmath;
+
+import java.lang.Math;
+
+/**
+ * A generic 2-element tuple that is represented by double-precision  
+ * floating point x,y coordinates.
+ *
+ */
+public abstract class Tuple2d implements java.io.Serializable, Cloneable {
+
+    static final long serialVersionUID = 6205762482756093838L;
+
+    /**
+     * The x coordinate.
+     */
+    public     double  x;
+
+    /**
+     * The y coordinate.
+     */
+    public     double  y;
+
+
+    /**
+     * Constructs and initializes a Tuple2d from the specified xy coordinates.
+     * @param x the x coordinate
+     * @param y the y coordinate
+     */
+    public Tuple2d(double x, double y)
+    {
+       this.x = x;
+       this.y = y;
+    }
+
+
+    /**
+     * Constructs and initializes a Tuple2d from the specified array.
+     * @param t the array of length 2 containing xy in order
+     */
+    public Tuple2d(double[] t)
+    {
+       this.x = t[0];
+       this.y = t[1];
+    }
+
+
+    /**
+     * Constructs and initializes a Tuple2d from the specified Tuple2d.
+     * @param t1 the Tuple2d containing the initialization x y data
+     */
+    public Tuple2d(Tuple2d t1)
+    {
+       this.x = t1.x;
+       this.y = t1.y;
+    }
+
+
+    /**
+     * Constructs and initializes a Tuple2d from the specified Tuple2f.
+     * @param t1 the Tuple2f containing the initialization x y data
+     */
+    public Tuple2d(Tuple2f t1)
+    {
+       this.x = (double) t1.x;
+       this.y = (double) t1.y;
+    }
+
+    /**
+     * Constructs and initializes a Tuple2d to (0,0).
+     */
+    public Tuple2d()
+    {
+       this.x = 0.0;
+       this.y = 0.0;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the specified xy coordinates.
+     * @param x the x coordinate
+     * @param y the y coordinate
+     */
+    public final void set(double x, double y)
+    {
+       this.x = x;
+       this.y = y;
+    }
+
+
+    /**
+     * Sets the value of this tuple from the 2 values specified in 
+     * the array.
+     * @param t the array of length 2 containing xy in order
+     */
+    public final void set(double[] t)
+    {
+       this.x = t[0];
+       this.y = t[1];
+    }
+
+
+    /**
+     * Sets the value of this tuple to the value of the Tuple2d argument.
+     * @param t1 the tuple to be copied
+     */
+    public final void set(Tuple2d t1)
+    {
+       this.x = t1.x;
+       this.y = t1.y;
+    }
+
+    /**
+     * Sets the value of this tuple to the value of Tuple2f t1.
+     * @param t1 the tuple to be copied
+     */
+    public final void set(Tuple2f t1)
+    {
+       this.x = (double) t1.x;
+       this.y = (double) t1.y;
+    }
+
+   /**
+    *  Copies the value of the elements of this tuple into the array t.
+    *  @param t the array that will contain the values of the vector
+    */
+   public final void get(double[] t)
+    {
+        t[0] = this.x;
+        t[1] = this.y;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the vector sum of tuples t1 and t2.
+     * @param t1 the first tuple
+     * @param t2 the second tuple
+     */
+    public final void add(Tuple2d t1, Tuple2d t2)
+    {
+       this.x = t1.x + t2.x;
+       this.y = t1.y + t2.y;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the vector sum of itself and tuple t1.
+     * @param t1 the other tuple
+     */  
+    public final void add(Tuple2d t1)
+    {
+        this.x += t1.x;
+        this.y += t1.y;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the vector difference of 
+     * tuple t1 and t2 (this = t1 - t2).    
+     * @param t1 the first tuple
+     * @param t2 the second tuple
+     */  
+    public final void sub(Tuple2d t1, Tuple2d t2)
+    {
+        this.x = t1.x - t2.x;
+        this.y = t1.y - t2.y;
+    }  
+
+
+    /**
+     * Sets the value of this tuple to the vector difference of
+     * itself and tuple t1 (this = this - t1).
+     * @param t1 the other vector
+     */  
+    public final void sub(Tuple2d t1)
+    {
+        this.x -= t1.x;
+        this.y -= t1.y;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the negation of tuple t1.
+     * @param t1 the source vector
+     */
+    public final void negate(Tuple2d t1)
+    {
+       this.x = -t1.x;
+       this.y = -t1.y;
+    }
+
+
+    /**
+     * Negates the value of this vector in place.
+     */
+    public final void negate()
+    {
+       this.x = -this.x;
+       this.y = -this.y;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the scalar multiplication
+     * of tuple t1.
+     * @param s the scalar value
+     * @param t1 the source tuple
+     */
+    public final void scale(double s, Tuple2d t1)
+    {
+       this.x = s*t1.x;
+       this.y = s*t1.y;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the scalar multiplication
+     * of itself.
+     * @param s the scalar value
+     */
+    public final void scale(double s)
+    {
+       this.x *= s;
+       this.y *= s;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the scalar multiplication
+     * of tuple t1 and then adds tuple t2 (this = s*t1 + t2).
+     * @param s the scalar value
+     * @param t1 the tuple to be multipled
+     * @param t2 the tuple to be added
+     */  
+    public final void scaleAdd(double s, Tuple2d t1, Tuple2d t2)
+    {
+        this.x = s*t1.x + t2.x; 
+        this.y = s*t1.y + t2.y; 
+    } 
+
+    /**
+     * Sets the value of this tuple to the scalar multiplication
+     * of itself and then adds tuple t1 (this = s*this + t1).
+     * @param s the scalar value
+     * @param t1 the tuple to be added
+     */
+    public final void scaleAdd(double s, Tuple2d t1)
+    {
+        this.x = s*this.x + t1.x;
+        this.y = s*this.y + t1.y;
+    }
+
+
+
+    /**
+     * Returns a hash code value based on the data values in this
+     * object.  Two different Tuple2d objects with identical data values
+     * (i.e., Tuple2d.equals returns true) will return the same hash
+     * code value.  Two objects with different data members may return the
+     * same hash value, although this is not likely.
+     * @return the integer hash code value
+     */  
+    public int hashCode() {
+       long bits = 1L;
+       bits = 31L * bits + VecMathUtil.doubleToLongBits(x);
+       bits = 31L * bits + VecMathUtil.doubleToLongBits(y);
+       return (int) (bits ^ (bits >> 32));
+    }
+
+
+   /**   
+     * Returns true if all of the data members of Tuple2d t1 are
+     * equal to the corresponding data members in this Tuple2d.
+     * @param t1  the vector with which the comparison is made
+     * @return  true or false
+     */  
+    public boolean equals(Tuple2d t1)
+    {
+        try {
+           return(this.x == t1.x && this.y == t1.y);
+        }
+        catch (NullPointerException e2) {return false;}
+
+    }
+
+   /**   
+     * Returns true if the Object t1 is of type Tuple2d and all of the
+     * data members of t1 are equal to the corresponding data members in
+     * this Tuple2d.
+     * @param t1  the object with which the comparison is made
+     * @return  true or false
+     */  
+    public boolean equals(Object t1)
+    {
+        try {
+           Tuple2d t2 = (Tuple2d) t1;
+           return(this.x == t2.x && this.y == t2.y);
+        }
+        catch (NullPointerException e2) {return false;}
+        catch (ClassCastException   e1) {return false;}
+
+    }
+
+   /**
+     * Returns true if the L-infinite distance between this tuple
+     * and tuple t1 is less than or equal to the epsilon parameter, 
+     * otherwise returns false.  The L-infinite
+     * distance is equal to MAX[abs(x1-x2), abs(y1-y2)]. 
+     * @param t1  the tuple to be compared to this tuple
+     * @param epsilon  the threshold value  
+     * @return  true or false
+     */
+    public boolean epsilonEquals(Tuple2d t1, double epsilon)
+    {
+       double diff;
+
+       diff = x - t1.x;
+       if(Double.isNaN(diff)) return false;
+       if((diff<0?-diff:diff) > epsilon) return false;
+
+       diff = y - t1.y;
+       if(Double.isNaN(diff)) return false;
+       if((diff<0?-diff:diff) > epsilon) return false;
+
+       return true;
+    }
+
+   /**
+     * Returns a string that contains the values of this Tuple2d.
+     * The form is (x,y).
+     * @return the String representation
+     */  
+   public String toString()
+   {
+        return("(" + this.x + ", " + this.y + ")");
+   }
+
+
+  /**
+    *  Clamps the tuple parameter to the range [low, high] and 
+    *  places the values into this tuple.  
+    *  @param min   the lowest value in the tuple after clamping
+    *  @param max  the highest value in the tuple after clamping 
+    *  @param t   the source tuple, which will not be modified
+    */
+   public final void clamp(double min, double max, Tuple2d t)
+   {
+        if( t.x > max ) { 
+          x = max;
+        } else if( t.x < min ){
+          x = min;
+        } else {
+          x = t.x;
+        }
+
+        if( t.y > max ) { 
+          y = max;
+        } else if( t.y < min ){
+          y = min;
+        } else {
+          y = t.y;
+        }
+
+   }
+
+
+  /** 
+    *  Clamps the minimum value of the tuple parameter to the min 
+    *  parameter and places the values into this tuple.
+    *  @param min   the lowest value in the tuple after clamping 
+    *  @param t   the source tuple, which will not be modified
+    */   
+   public final void clampMin(double min, Tuple2d t) 
+   { 
+        if( t.x < min ) { 
+          x = min;
+        } else {
+          x = t.x;
+        }
+
+        if( t.y < min ) { 
+          y = min;
+        } else {
+          y = t.y;
+        }
+
+   } 
+
+
+  /**  
+    *  Clamps the maximum value of the tuple parameter to the max 
+    *  parameter and places the values into this tuple.
+    *  @param max   the highest value in the tuple after clamping  
+    *  @param t   the source tuple, which will not be modified
+    */    
+   public final void clampMax(double max, Tuple2d t)  
+   {  
+        if( t.x > max ) { 
+          x = max;
+        } else { 
+          x = t.x;
+        }
+        if( t.y > max ) {
+          y = max;
+        } else {
+          y = t.y;
+        }
+
+   } 
+
+
+  /**  
+    *  Sets each component of the tuple parameter to its absolute 
+    *  value and places the modified values into this tuple.
+    *  @param t   the source tuple, which will not be modified
+    */    
+  public final void absolute(Tuple2d t)
+  {
+       x = Math.abs(t.x);
+       y = Math.abs(t.y);
+  } 
+
+
+
+  /**
+    *  Clamps this tuple to the range [low, high].
+    *  @param min  the lowest value in this tuple after clamping
+    *  @param max  the highest value in this tuple after clamping
+    */
+   public final void clamp(double min, double max)
+   {
+        if( x > max ) {
+          x = max;
+        } else if( x < min ){
+          x = min;
+        }
+        if( y > max ) {
+          y = max;
+        } else if( y < min ){
+          y = min;
+        }
+
+   }
+
+  /**
+    *  Clamps the minimum value of this tuple to the min parameter.
+    *  @param min   the lowest value in this tuple after clamping
+    */
+   public final void clampMin(double min)
+   { 
+      if( x < min ) x=min;
+      if( y < min ) y=min;
+   } 
+  /**
+    *  Clamps the maximum value of this tuple to the max parameter.
+    *  @param max   the highest value in the tuple after clamping
+    */
+   public final void clampMax(double max)
+   { 
+      if( x > max ) x=max;
+      if( y > max ) y=max;
+   }
+
+
+  /**
+    *  Sets each component of this tuple to its absolute value.
+    */
+  public final void absolute()
+  {
+     x = Math.abs(x);
+     y = Math.abs(y);
+  }
+
+
+  /** 
+    *  Linearly interpolates between tuples t1 and t2 and places the 
+    *  result into this tuple:  this = (1-alpha)*t1 + alpha*t2.
+    *  @param t1  the first tuple
+    *  @param t2  the second tuple
+    *  @param alpha  the alpha interpolation parameter
+    */
+  public final void interpolate(Tuple2d t1, Tuple2d t2, double alpha)
+  {
+       this.x = (1-alpha)*t1.x + alpha*t2.x;
+       this.y = (1-alpha)*t1.y + alpha*t2.y;
+  }
+
+
+  /**  
+    *  Linearly interpolates between this tuple and tuple t1 and 
+    *  places the result into this tuple:  this = (1-alpha)*this + alpha*t1.
+    *  @param t1  the first tuple
+    *  @param alpha  the alpha interpolation parameter  
+    */   
+  public final void interpolate(Tuple2d t1, double alpha) 
+  { 
+       this.x = (1-alpha)*this.x + alpha*t1.x;
+       this.y = (1-alpha)*this.y + alpha*t1.y;
+
+  } 
+
+    /**
+     * Creates a new object of the same class as this object.
+     *
+     * @return a clone of this instance.
+     * @exception OutOfMemoryError if there is not enough memory.
+     * @see java.lang.Cloneable
+     * @since vecmath 1.3
+     */
+    public Object clone() {
+       // Since there are no arrays we can just use Object.clone()
+       try {
+           return super.clone();
+       } catch (CloneNotSupportedException e) {
+           // this shouldn't happen, since we are Cloneable
+           throw new InternalError();
+       }
+    }
+
+
+       /**
+        * Get the <i>x</i> coordinate.
+        * 
+        * @return the <i>x</i> coordinate.
+        * 
+        * @since vecmath 1.5
+        */
+       public final double getX() {
+               return x;
+       }
+
+
+       /**
+        * Set the <i>x</i> coordinate.
+        * 
+        * @param x  value to <i>x</i> coordinate.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setX(double x) {
+               this.x = x;
+       }
+
+
+       /**
+        * Get the <i>y</i> coordinate.
+        * 
+        * @return the <i>y</i> coordinate.
+        * 
+        * @since vecmath 1.5
+        */
+       public final double getY() {
+               return y;
+       }
+
+
+       /**
+        * Set the <i>y</i> coordinate.
+        * 
+        * @param y value to <i>y</i> coordinate.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setY(double y) {
+               this.y = y;
+       }
+
+}
diff --git a/javax.vecmath/src/javax/vecmath/Tuple2f.java b/javax.vecmath/src/javax/vecmath/Tuple2f.java
new file mode 100644 (file)
index 0000000..5aad511
--- /dev/null
@@ -0,0 +1,609 @@
+/*
+ * $RCSfile: Tuple2f.java,v $
+ *
+ * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ * $Revision: 1.8 $
+ * $Date: 2008/02/28 20:18:51 $
+ * $State: Exp $
+ */
+
+package javax.vecmath;
+
+import java.lang.Math;
+
+/**
+ * A generic 2-element tuple that is represented by single-precision  
+ * floating point x,y coordinates.
+ *
+ */
+public abstract class Tuple2f implements java.io.Serializable, Cloneable {
+
+    static final long serialVersionUID = 9011180388985266884L;
+
+    /**
+     * The x coordinate.
+     */
+    public     float   x;
+
+    /**
+     * The y coordinate.
+     */
+    public     float   y;
+
+
+    /**
+     * Constructs and initializes a Tuple2f from the specified xy coordinates.
+     * @param x the x coordinate
+     * @param y the y coordinate
+     */
+    public Tuple2f(float x, float y)
+    {
+       this.x = x;
+       this.y = y;
+    }
+
+
+    /**
+     * Constructs and initializes a Tuple2f from the specified array.
+     * @param t the array of length 2 containing xy in order
+     */
+    public Tuple2f(float[] t)
+    {
+       this.x = t[0];
+       this.y = t[1];
+    }
+
+
+    /**
+     * Constructs and initializes a Tuple2f from the specified Tuple2f.
+     * @param t1 the Tuple2f containing the initialization x y data
+     */
+    public Tuple2f(Tuple2f t1)
+    {
+       this.x = t1.x;
+       this.y = t1.y;
+    }
+
+
+    /**
+     * Constructs and initializes a Tuple2f from the specified Tuple2d.
+     * @param t1 the Tuple2d containing the initialization x y data
+     */
+    public Tuple2f(Tuple2d t1)
+    {
+       this.x = (float) t1.x;
+       this.y = (float) t1.y;
+    }
+
+
+    /**
+     * Constructs and initializes a Tuple2f to (0,0).
+     */
+    public Tuple2f()
+    {
+       this.x = (float) 0.0;
+       this.y = (float) 0.0;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the specified xy coordinates.
+     * @param x the x coordinate
+     * @param y the y coordinate
+     */
+    public final void set(float x, float y)
+    {
+       this.x = x;
+       this.y = y;
+    }
+
+
+    /**
+     * Sets the value of this tuple from the 2 values specified in 
+     * the array.
+     * @param t the array of length 2 containing xy in order
+     */
+    public final void set(float[] t)
+    {
+       this.x = t[0];
+       this.y = t[1];
+    }
+
+
+    /**
+     * Sets the value of this tuple to the value of the Tuple2f argument.
+     * @param t1 the tuple to be copied
+     */
+    public final void set(Tuple2f t1)
+    {
+       this.x = t1.x;
+       this.y = t1.y;
+    }
+
+    /**
+     * Sets the value of this tuple to the value of the Tuple2d argument.
+     * @param t1 the tuple to be copied
+     */
+    public final void set(Tuple2d t1)
+    {
+       this.x = (float) t1.x;
+       this.y = (float) t1.y;
+    }
+
+
+   /**
+    *  Copies the value of the elements of this tuple into the array t.
+    *  @param t the array that will contain the values of the vector
+    */
+   public final void get(float[] t)
+    {
+        t[0] = this.x;
+        t[1] = this.y;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the vector sum of tuples t1 and t2.
+     * @param t1 the first tuple
+     * @param t2 the second tuple
+     */
+    public final void add(Tuple2f t1, Tuple2f t2)
+    {
+       this.x = t1.x + t2.x;
+       this.y = t1.y + t2.y;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the vector sum of itself and tuple t1.
+     * @param t1 the other tuple
+     */  
+    public final void add(Tuple2f t1)
+    {
+        this.x += t1.x;
+        this.y += t1.y;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the vector difference of 
+     * tuple t1 and t2 (this = t1 - t2).    
+     * @param t1 the first tuple
+     * @param t2 the second tuple
+     */  
+    public final void sub(Tuple2f t1, Tuple2f t2)
+    {
+        this.x = t1.x - t2.x;
+        this.y = t1.y - t2.y;
+    }  
+
+
+    /**
+     * Sets the value of this tuple to the vector difference of
+     * itself and tuple t1 (this = this - t1).
+     * @param t1 the other tuple
+     */  
+    public final void sub(Tuple2f t1)
+    {
+        this.x -= t1.x;
+        this.y -= t1.y;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the negation of tuple t1.
+     * @param t1 the source tuple
+     */
+    public final void negate(Tuple2f t1)
+    {
+       this.x = -t1.x;
+       this.y = -t1.y;
+    }
+
+
+    /**
+     * Negates the value of this vector in place.
+     */
+    public final void negate()
+    {
+       this.x = -this.x;
+       this.y = -this.y;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the scalar multiplication
+     * of tuple t1.
+     * @param s the scalar value
+     * @param t1 the source tuple
+     */
+    public final void scale(float s, Tuple2f t1)
+    {
+       this.x = s*t1.x;
+       this.y = s*t1.y;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the scalar multiplication
+     * of itself.
+     * @param s the scalar value
+     */
+    public final void scale(float s)
+    {
+       this.x *= s;
+       this.y *= s;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the scalar multiplication
+     * of tuple t1 and then adds tuple t2 (this = s*t1 + t2).
+     * @param s the scalar value
+     * @param t1 the tuple to be multipled
+     * @param t2 the tuple to be added
+     */  
+    public final void scaleAdd(float s, Tuple2f t1, Tuple2f t2)
+    {
+        this.x = s*t1.x + t2.x; 
+        this.y = s*t1.y + t2.y; 
+    } 
+
+    /**
+     * Sets the value of this tuple to the scalar multiplication
+     * of itself and then adds tuple t1 (this = s*this + t1).
+     * @param s the scalar value
+     * @param t1 the tuple to be added
+     */
+    public final void scaleAdd(float s, Tuple2f t1)
+    {
+        this.x = s*this.x + t1.x;
+        this.y = s*this.y + t1.y;
+    }
+
+
+
+    /**
+     * Returns a hash code value based on the data values in this
+     * object.  Two different Tuple2f objects with identical data values
+     * (i.e., Tuple2f.equals returns true) will return the same hash
+     * code value.  Two objects with different data members may return the
+     * same hash value, although this is not likely.
+     * @return the integer hash code value
+     */  
+    public int hashCode() {
+       long bits = 1L;
+       bits = 31L * bits + (long)VecMathUtil.floatToIntBits(x);
+       bits = 31L * bits + (long)VecMathUtil.floatToIntBits(y);
+       return (int) (bits ^ (bits >> 32));
+    }
+
+
+   /**   
+     * Returns true if all of the data members of Tuple2f t1 are
+     * equal to the corresponding data members in this Tuple2f.
+     * @param t1  the vector with which the comparison is made
+     * @return  true or false
+     */  
+    public boolean equals(Tuple2f t1)
+    {
+        try {
+           return(this.x == t1.x && this.y == t1.y);
+        }
+        catch (NullPointerException e2) {return false;}
+
+    }
+
+   /**   
+     * Returns true if the Object t1 is of type Tuple2f and all of the
+     * data members of t1 are equal to the corresponding data members in
+     * this Tuple2f.
+     * @param t1  the object with which the comparison is made
+     * @return  true or false
+     */  
+    public boolean equals(Object t1)
+    {
+        try {
+           Tuple2f t2 = (Tuple2f) t1;
+           return(this.x == t2.x && this.y == t2.y);
+        }
+        catch (NullPointerException e2) {return false;}
+        catch (ClassCastException   e1) {return false;}
+
+    }
+
+   /**
+     * Returns true if the L-infinite distance between this tuple
+     * and tuple t1 is less than or equal to the epsilon parameter, 
+     * otherwise returns false.  The L-infinite
+     * distance is equal to MAX[abs(x1-x2), abs(y1-y2)]. 
+     * @param t1  the tuple to be compared to this tuple
+     * @param epsilon  the threshold value  
+     * @return  true or false
+     */
+    public boolean epsilonEquals(Tuple2f t1, float epsilon)
+    {
+       float diff;
+
+       diff = x - t1.x;
+       if(Float.isNaN(diff)) return false;
+       if((diff<0?-diff:diff) > epsilon) return false;
+
+       diff = y - t1.y;
+       if(Float.isNaN(diff)) return false;
+       if((diff<0?-diff:diff) > epsilon) return false;
+
+       return true;
+    }
+
+   /**
+     * Returns a string that contains the values of this Tuple2f.
+     * The form is (x,y).
+     * @return the String representation
+     */  
+   public String toString()
+   {
+        return("(" + this.x + ", " + this.y + ")");
+   }
+
+
+  /**
+    *  Clamps the tuple parameter to the range [low, high] and 
+    *  places the values into this tuple.  
+    *  @param min   the lowest value in the tuple after clamping
+    *  @param max  the highest value in the tuple after clamping 
+    *  @param t   the source tuple, which will not be modified
+    */
+   public final void clamp(float min, float max, Tuple2f t)
+   {
+        if( t.x > max ) { 
+          x = max;
+        } else if( t.x < min ){
+          x = min;
+        } else {
+          x = t.x;
+        }
+
+        if( t.y > max ) { 
+          y = max;
+        } else if( t.y < min ){
+          y = min;
+        } else {
+          y = t.y;
+        }
+
+   }
+
+
+  /** 
+    *  Clamps the minimum value of the tuple parameter to the min 
+    *  parameter and places the values into this tuple.
+    *  @param min   the lowest value in the tuple after clamping 
+    *  @param t   the source tuple, which will not be modified
+    */   
+   public final void clampMin(float min, Tuple2f t) 
+   { 
+        if( t.x < min ) { 
+          x = min;
+        } else {
+          x = t.x;
+        }
+
+        if( t.y < min ) { 
+          y = min;
+        } else {
+          y = t.y;
+        }
+
+   } 
+
+
+  /**  
+    *  Clamps the maximum value of the tuple parameter to the max 
+    *  parameter and places the values into this tuple.
+    *  @param max   the highest value in the tuple after clamping  
+    *  @param t   the source tuple, which will not be modified
+    */    
+   public final void clampMax(float max, Tuple2f t)  
+   {  
+        if( t.x > max ) { 
+          x = max;
+        } else { 
+          x = t.x;
+        }
+        if( t.y > max ) {
+          y = max;
+        } else {
+          y = t.y;
+        }
+
+   } 
+
+
+  /**  
+    *  Sets each component of the tuple parameter to its absolute 
+    *  value and places the modified values into this tuple.
+    *  @param t   the source tuple, which will not be modified
+    */    
+  public final void absolute(Tuple2f t)
+  {
+       x = Math.abs(t.x);
+       y = Math.abs(t.y);
+  } 
+
+
+
+  /**
+    *  Clamps this tuple to the range [low, high].
+    *  @param min  the lowest value in this tuple after clamping
+    *  @param max  the highest value in this tuple after clamping
+    */
+   public final void clamp(float min, float max)
+   {
+        if( x > max ) {
+          x = max;
+        } else if( x < min ){
+          x = min;
+        }
+        if( y > max ) {
+          y = max;
+        } else if( y < min ){
+          y = min;
+        }
+
+   }
+
+  /**
+    *  Clamps the minimum value of this tuple to the min parameter.
+    *  @param min   the lowest value in this tuple after clamping
+    */
+   public final void clampMin(float min)
+   { 
+      if( x < min ) x=min;
+      if( y < min ) y=min;
+   } 
+  /**
+    *  Clamps the maximum value of this tuple to the max parameter.
+    *  @param max   the highest value in the tuple after clamping
+    */
+   public final void clampMax(float max)
+   { 
+      if( x > max ) x=max;
+      if( y > max ) y=max;
+   }
+
+
+  /**
+    *  Sets each component of this tuple to its absolute value.
+    */
+  public final void absolute()
+  {
+     x = Math.abs(x);
+     y = Math.abs(y);
+  }
+
+
+  /** 
+    *  Linearly interpolates between tuples t1 and t2 and places the 
+    *  result into this tuple:  this = (1-alpha)*t1 + alpha*t2.
+    *  @param t1  the first tuple
+    *  @param t2  the second tuple
+    *  @param alpha  the alpha interpolation parameter
+    */
+  public final void interpolate(Tuple2f t1, Tuple2f t2, float alpha)
+  {
+           this.x = (1-alpha)*t1.x + alpha*t2.x;
+           this.y = (1-alpha)*t1.y + alpha*t2.y;
+  }
+
+
+  /**  
+    *  Linearly interpolates between this tuple and tuple t1 and 
+    *  places the result into this tuple:  this = (1-alpha)*this + alpha*t1.
+    *  @param t1  the first tuple
+    *  @param alpha  the alpha interpolation parameter  
+    */   
+  public final void interpolate(Tuple2f t1, float alpha) 
+  { 
+
+     this.x = (1-alpha)*this.x + alpha*t1.x;
+     this.y = (1-alpha)*this.y + alpha*t1.y;
+
+  } 
+
+    /**
+     * Creates a new object of the same class as this object.
+     *
+     * @return a clone of this instance.
+     * @exception OutOfMemoryError if there is not enough memory.
+     * @see java.lang.Cloneable
+     * @since vecmath 1.3
+     */
+    public Object clone() {
+       // Since there are no arrays we can just use Object.clone()
+       try {
+           return super.clone();
+       } catch (CloneNotSupportedException e) {
+           // this shouldn't happen, since we are Cloneable
+           throw new InternalError();
+       }
+    }
+
+
+    /**
+        * Get the <i>x</i> coordinate.
+        * 
+        * @return  the <i>x</i> coordinate.
+        * 
+        * @since vecmath 1.5
+        */
+       public final float getX() {
+               return x;
+       }
+
+
+       /**
+        * Set the <i>x</i> coordinate.
+        * 
+        * @param x  value to <i>x</i> coordinate.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setX(float x) {
+               this.x = x;
+       }
+
+
+       /**
+        * Get the <i>y</i> coordinate.
+        * 
+        * @return  the <i>y</i> coordinate.
+        * 
+        * @since vecmath 1.5
+        */
+       public final float getY() {
+               return y;
+       }
+
+
+       /**
+        * Set the <i>y</i> coordinate.
+        * 
+        * @param y value to <i>y</i> coordinate.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setY(float y) {
+               this.y = y;
+       }
+}
diff --git a/javax.vecmath/src/javax/vecmath/Tuple2i.java b/javax.vecmath/src/javax/vecmath/Tuple2i.java
new file mode 100644 (file)
index 0000000..797f6a8
--- /dev/null
@@ -0,0 +1,506 @@
+/*
+ * $RCSfile: Tuple2i.java,v $
+ *
+ * Copyright 2005-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ * $Revision: 1.6 $
+ * $Date: 2008/02/28 20:18:51 $
+ * $State: Exp $
+ */
+
+package javax.vecmath;
+
+import java.lang.Math;
+
+/**
+ * A 2-element tuple represented by signed integer x,y
+ * coordinates.
+ *
+ * @since vecmath 1.4
+ */
+public abstract class Tuple2i implements java.io.Serializable, Cloneable {
+
+    static final long serialVersionUID = -3555701650170169638L;
+
+    /**
+     * The x coordinate.
+     */
+    public int x;
+
+    /**
+     * The y coordinate.
+     */
+    public int y;
+
+
+    /**
+     * Constructs and initializes a Tuple2i from the specified
+     * x and y coordinates.
+     * @param x the x coordinate
+     * @param y the y coordinate
+     */
+    public Tuple2i(int x, int y) {
+       this.x = x;
+       this.y = y;
+    }
+
+
+    /**
+     * Constructs and initializes a Tuple2i from the array of length 2.
+     * @param t the array of length 2 containing x and y in order.
+     */
+    public Tuple2i(int[] t) {
+       this.x = t[0];
+       this.y = t[1];
+    }
+
+
+    /**
+     * Constructs and initializes a Tuple2i from the specified Tuple2i.
+     * @param t1 the Tuple2i containing the initialization x and y
+     * data.
+     */
+    public Tuple2i(Tuple2i t1) {
+       this.x = t1.x;
+       this.y = t1.y;
+    }
+
+
+    /**
+     * Constructs and initializes a Tuple2i to (0,0).
+     */
+    public Tuple2i() {
+       this.x = 0;
+       this.y = 0;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the specified x and y
+     * coordinates.
+     * @param x the x coordinate
+     * @param y the y coordinate
+     */
+    public final void set(int x, int y) {
+       this.x = x;
+       this.y = y;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the specified coordinates in the
+     * array of length 2.
+     * @param t the array of length 2 containing x and y in order.
+     */
+    public final void set(int[] t) {
+       this.x = t[0];
+       this.y = t[1];
+    }
+
+
+    /**
+     * Sets the value of this tuple to the value of tuple t1.
+     * @param t1 the tuple to be copied
+     */
+    public final void set(Tuple2i t1) {
+       this.x = t1.x;
+       this.y = t1.y;
+    }
+
+
+    /**
+     * Copies the values of this tuple into the array t.
+     * @param t is the array
+     */
+    public final void get(int[] t) {
+       t[0] = this.x;
+       t[1] = this.y;
+    }
+
+
+    /**
+     * Copies the values of this tuple into the tuple t.
+     * @param t is the target tuple
+     */
+    public final void get(Tuple2i t) {
+       t.x = this.x;
+       t.y = this.y;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the sum of tuples t1 and t2.
+     * @param t1 the first tuple
+     * @param t2 the second tuple
+     */
+    public final void add(Tuple2i t1, Tuple2i t2) {
+       this.x = t1.x + t2.x;
+       this.y = t1.y + t2.y;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the sum of itself and t1.
+     * @param t1 the other tuple
+     */
+    public final void add(Tuple2i t1) {
+       this.x += t1.x;
+       this.y += t1.y;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the difference
+     * of tuples t1 and t2 (this = t1 - t2).
+     * @param t1 the first tuple
+     * @param t2 the second tuple
+     */
+    public final void sub(Tuple2i t1, Tuple2i t2) {
+       this.x = t1.x - t2.x;
+       this.y = t1.y - t2.y;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the difference
+     * of itself and t1 (this = this - t1).
+     * @param t1 the other tuple
+     */
+    public final void sub(Tuple2i t1) {
+       this.x -= t1.x;
+       this.y -= t1.y;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the negation of tuple t1.
+     * @param t1 the source tuple
+     */
+    public final void negate(Tuple2i t1) {
+       this.x = -t1.x;
+       this.y = -t1.y;
+    }
+
+
+    /**
+     * Negates the value of this tuple in place.
+     */
+    public final void negate() {
+       this.x = -this.x;
+       this.y = -this.y;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the scalar multiplication
+     * of tuple t1.
+     * @param s the scalar value
+     * @param t1 the source tuple
+     */
+    public final void scale(int s, Tuple2i t1) {
+       this.x = s*t1.x;
+       this.y = s*t1.y;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the scalar multiplication
+     * of the scale factor with this.
+     * @param s the scalar value
+     */
+    public final void scale(int s) {
+       this.x *= s;
+       this.y *= s;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the scalar multiplication
+     * of tuple t1 plus tuple t2 (this = s*t1 + t2).
+     * @param s the scalar value
+     * @param t1 the tuple to be multipled
+     * @param t2 the tuple to be added
+     */
+    public final void scaleAdd(int s, Tuple2i t1, Tuple2i t2) {
+       this.x = s*t1.x + t2.x;
+       this.y = s*t1.y + t2.y;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the scalar multiplication
+     * of itself and then adds tuple t1 (this = s*this + t1).
+     * @param s the scalar value
+     * @param t1 the tuple to be added
+     */
+    public final void scaleAdd(int s, Tuple2i t1) {
+        this.x = s*this.x + t1.x;
+        this.y = s*this.y + t1.y;
+    }
+
+
+    /**
+     * Returns a string that contains the values of this Tuple2i.
+     * The form is (x,y).
+     * @return the String representation
+     */
+    public String toString() {
+        return "(" + this.x + ", " + this.y + ")";
+    }
+
+
+    /**
+     * Returns true if the Object t1 is of type Tuple2i and all of the
+     * data members of t1 are equal to the corresponding data members in
+     * this Tuple2i.
+     * @param t1  the object with which the comparison is made
+     */
+    public boolean equals(Object t1) {
+        try {
+           Tuple2i t2 = (Tuple2i) t1;
+           return(this.x == t2.x && this.y == t2.y);
+        }
+        catch (NullPointerException e2) {
+           return false;
+       }
+        catch (ClassCastException e1) {
+           return false;
+       }
+    }
+
+
+    /**
+     * Returns a hash code value based on the data values in this
+     * object.  Two different Tuple2i objects with identical data values
+     * (i.e., Tuple2i.equals returns true) will return the same hash
+     * code value.  Two objects with different data members may return the
+     * same hash value, although this is not likely.
+     * @return the integer hash code value
+     */
+    public int hashCode() {
+       long bits = 1L;
+       bits = 31L * bits + (long)x;
+       bits = 31L * bits + (long)y;
+       return (int) (bits ^ (bits >> 32));
+    }
+
+
+    /**
+     *  Clamps the tuple parameter to the range [low, high] and
+     *  places the values into this tuple.
+     *  @param min   the lowest value in the tuple after clamping
+     *  @param max  the highest value in the tuple after clamping
+     *  @param t   the source tuple, which will not be modified
+     */
+    public final void clamp(int min, int max, Tuple2i t) {
+        if( t.x > max ) {
+           x = max;
+        } else if( t.x < min ) {
+           x = min;
+        } else {
+           x = t.x;
+        }
+
+        if( t.y > max ) {
+           y = max;
+        } else if( t.y < min ) {
+           y = min;
+        } else {
+           y = t.y;
+        }
+    }
+
+
+    /**
+     *  Clamps the minimum value of the tuple parameter to the min
+     *  parameter and places the values into this tuple.
+     *  @param min   the lowest value in the tuple after clamping
+     *  @param t   the source tuple, which will not be modified
+     */
+    public final void clampMin(int min, Tuple2i t) {
+        if( t.x < min ) {
+           x = min;
+        } else {
+           x = t.x;
+        }
+
+        if( t.y < min ) {
+           y = min;
+        } else {
+           y = t.y;
+        }
+    }
+
+
+    /**
+     *  Clamps the maximum value of the tuple parameter to the max
+     *  parameter and places the values into this tuple.
+     *  @param max   the highest value in the tuple after clamping
+     *  @param t   the source tuple, which will not be modified
+     */
+    public final void clampMax(int max, Tuple2i t) {
+        if( t.x > max ) {
+           x = max;
+        } else {
+           x = t.x;
+        }
+
+        if( t.y > max ) {
+           y = max;
+        } else {
+           y = t.y;
+        }
+    }
+
+
+    /**
+     *  Sets each component of the tuple parameter to its absolute
+     *  value and places the modified values into this tuple.
+     *  @param t   the source tuple, which will not be modified
+     */
+    public final void absolute(Tuple2i t) {
+       x = Math.abs(t.x);
+       y = Math.abs(t.y);
+    }
+
+
+    /**
+     *  Clamps this tuple to the range [low, high].
+     *  @param min  the lowest value in this tuple after clamping
+     *  @param max  the highest value in this tuple after clamping
+     */
+    public final void clamp(int min, int max) {
+       if( x > max ) {
+           x = max;
+        } else if( x < min ) {
+           x = min;
+        }
+
+        if( y > max ) {
+           y = max;
+        } else if( y < min ) {
+           y = min;
+        }
+    }
+
+
+    /**
+     *  Clamps the minimum value of this tuple to the min parameter.
+     *  @param min   the lowest value in this tuple after clamping
+     */
+    public final void clampMin(int min) {
+       if (x < min)
+           x=min;
+
+       if (y < min)
+           y = min;
+    }
+
+
+    /**
+     *  Clamps the maximum value of this tuple to the max parameter.
+     *  @param max   the highest value in the tuple after clamping
+     */
+    public final void clampMax(int max) {
+       if (x > max)
+           x = max;
+
+       if (y > max)
+           y = max;
+    }
+
+
+    /**
+     *  Sets each component of this tuple to its absolute value.
+     */
+    public final void absolute() {
+       x = Math.abs(x);
+       y = Math.abs(y);
+    }
+
+    /**
+     * Creates a new object of the same class as this object.
+     *
+     * @return a clone of this instance.
+     * @exception OutOfMemoryError if there is not enough memory.
+     * @see java.lang.Cloneable
+     */
+    public Object clone() {
+       // Since there are no arrays we can just use Object.clone()
+       try {
+           return super.clone();
+       } catch (CloneNotSupportedException e) {
+           // this shouldn't happen, since we are Cloneable
+           throw new InternalError();
+       }
+    }
+
+
+    /**
+        * Get the <i>x</i> coordinate.
+        * 
+        * @return the x coordinate.
+        * 
+        * @since vecmath 1.5
+        */
+       public final int getX() {
+               return x;
+       }
+
+
+       /**
+        * Set the <i>x</i> coordinate.
+        * 
+        * @param x  value to <i>x</i> coordinate.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setX(int x) {
+               this.x = x;
+       }
+
+
+       /**
+        * Get the <i>y</i> coordinate.
+        * 
+        * @return  the <i>y</i> coordinate.
+        * 
+        * @since vecmath 1.5
+        */
+       public final int getY() {
+               return y;
+       }
+
+
+       /**
+        * Set the <i>y</i> coordinate.
+        * 
+        * @param y value to <i>y</i> coordinate.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setY(int y) {
+               this.y = y;
+       }
+}
diff --git a/javax.vecmath/src/javax/vecmath/Tuple3b.java b/javax.vecmath/src/javax/vecmath/Tuple3b.java
new file mode 100644 (file)
index 0000000..93bc772
--- /dev/null
@@ -0,0 +1,319 @@
+/*
+ * $RCSfile: Tuple3b.java,v $
+ *
+ * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ * $Revision: 1.7 $
+ * $Date: 2008/02/28 20:18:51 $
+ * $State: Exp $
+ */
+
+package javax.vecmath;
+
+import java.lang.Math;
+
+/**
+ * A three byte tuple.  Note that Java defines a byte as a signed integer
+ * in the range [-128, 127]. However, colors are more typically
+ * represented by values in the range [0, 255]. Java 3D recognizes this
+ * and, in those cases where Tuple3b is used to represent color, treats
+ * the bytes as if the range were [0, 255]---in other words, as if the
+ * bytes were unsigned.
+ * Values greater than 127 can be assigned to a byte variable using a
+ * type cast.  For example:
+ * <ul>byteVariable = (byte) intValue; // intValue can be > 127</ul>
+ * If intValue is greater than 127, then byteVariable will be negative.  The
+ * correct value will be extracted when it is used (by masking off the upper
+ * bits).
+ */
+public abstract class Tuple3b implements java.io.Serializable, Cloneable {
+
+    static final long serialVersionUID = -483782685323607044L;
+
+    /**
+     * The first value.
+     */
+    public     byte    x;
+
+    /**
+     * The second value.
+     */
+    public     byte    y;
+
+    /**
+     * The third value.
+     */
+    public     byte    z;
+
+
+    /**
+     * Constructs and initializes a Tuple3b from the specified three values.
+     * @param b1 the first value
+     * @param b2 the second value
+     * @param b3 the third value
+     */
+    public Tuple3b(byte b1, byte b2, byte b3)
+    {
+       this.x = b1;
+       this.y = b2;
+       this.z = b3;
+    }
+
+
+    /**
+     * Constructs and initializes a Tuple3b from input array of length 3.
+     * @param t the array of length 3 containing b1 b2 b3 in order
+     */
+    public Tuple3b(byte[] t)
+    {
+       this.x = t[0];
+       this.y = t[1];
+       this.z = t[2];
+    }
+
+
+    /**
+     * Constructs and initializes a Tuple3b from the specified Tuple3b.
+     * @param t1  the Tuple3b containing the initialization x y z data
+     */
+    public Tuple3b(Tuple3b t1)
+    {
+       this.x = t1.x;
+       this.y = t1.y;
+       this.z = t1.z;
+    }
+
+
+    /**
+     * Constructs and initializes a Tuple3b to (0,0,0).
+     */
+    public Tuple3b()
+    {
+       this.x = (byte) 0;
+       this.y = (byte) 0;
+       this.z = (byte) 0;
+    }
+
+
+   /**
+     * Returns a string that contains the values of this Tuple3b.
+     * @return a String with the values
+     */
+    public String toString()
+    {   
+        return("("  + ((int)this.x & 0xff) +
+              ", " + ((int)this.y & 0xff) +
+              ", " + ((int)this.z & 0xff) + ")");
+    }   
+
+   /**   
+     * Places the value of the x,y,z components of this Tuple3b
+     * into the array of length 3.
+     * @param t array of length 3 into which the component values are copied
+     */ 
+    public final void get(byte[] t)
+    {   
+        t[0] = this.x;
+        t[1] = this.y;
+        t[2] = this.z;
+    }   
+
+
+   /**
+     * Places the value of the x,y,z components of this tuple into 
+     * the tuple t1.
+     * @param t1  the tuple into which the values are placed
+     */
+    public final void get(Tuple3b t1)
+    {
+       t1.x = this.x;
+       t1.y = this.y;
+       t1.z = this.z;
+    }
+
+
+   /**
+     * Sets the value of the data members of this tuple to the value 
+     * of the argument tuple t1.
+     * @param t1  the source tuple for the memberwise copy
+     */ 
+    public final void set(Tuple3b t1)
+    {   
+        this.x = t1.x;
+        this.y = t1.y;
+        this.z = t1.z;
+    }   
+
+   /**
+     * Sets the value of the x,y,z, data members of this tuple to the 
+     * values in the array t of length 3.
+     * @param t  array of length 3 which is the source for the memberwise copy
+     */ 
+    public final void set(byte[] t)
+    {   
+        this.x = t[0];
+        this.y = t[1];
+        this.z = t[2];
+    }   
+
+   /**
+     * Returns true if all of the data members of tuple t1 are equal to
+     * the corresponding data members in this tuple. 
+     * @param t1  the tuple with which the comparison is made
+     * @return  true or false
+     */ 
+    public boolean equals(Tuple3b t1)
+    {
+        try {
+        return(this.x == t1.x && this.y == t1.y && this.z == t1.z);
+        }
+        catch (NullPointerException e2) {return false;}
+
+    }
+
+   /**
+     * Returns true if the Object t1 is of type Tuple3b and all of the
+     * data members of t1 are equal to the corresponding data members in
+     * this Tuple3b.
+     * @param t1  the object with which the comparison is made
+     */ 
+    public boolean equals(Object t1)
+    {
+        try {
+           Tuple3b t2 = (Tuple3b) t1;
+           return(this.x == t2.x && this.y == t2.y && this.z == t2.z);
+        }
+        catch (NullPointerException e2) {return false;}
+        catch (ClassCastException   e1) {return false;}
+
+    }
+
+    /**
+     * Returns a hash code value based on the data values in this
+     * object.  Two different Tuple3b objects with identical data values
+     * (i.e., Tuple3b.equals returns true) will return the same hash
+     * code value.  Two objects with different data members may return the
+     * same hash value, although this is not likely.
+     * @return the integer hash code value
+     */  
+    public int hashCode() {
+       return ((((int)x & 0xff) <<  0) |
+               (((int)y & 0xff) <<  8) |
+               (((int)z & 0xff) << 16));
+    }
+   
+    /**
+     * Creates a new object of the same class as this object.
+     *
+     * @return a clone of this instance.
+     * @exception OutOfMemoryError if there is not enough memory.
+     * @see java.lang.Cloneable
+     * @since vecmath 1.3
+     */
+    public Object clone() {
+       // Since there are no arrays we can just use Object.clone()
+       try {
+           return super.clone();
+       } catch (CloneNotSupportedException e) {
+           // this shouldn't happen, since we are Cloneable
+           throw new InternalError();
+       }
+    }
+
+
+    /**
+        * Get <i>x</i>, the  first value.
+        * 
+        * @return the first value.
+        * 
+        * @since vecmath 1.5
+        */
+       public final byte getX() {
+               return x;
+       }
+
+
+       /**
+        * Set <i>x</i>, the first value.
+        * 
+        * @param x the first value to set. 
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setX(byte x) {
+               this.x = x;
+       }
+
+
+       /**
+        * Get <i>y</i>, the second value.
+        * 
+        * @return the second value. 
+        * 
+        * @since vecmath 1.5
+        */
+       public final byte getY() {
+               return y;
+       }
+
+
+       /**
+        * Set <i>y</i>, the second value.
+        * 
+        * @param y the second value to set.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setY(byte y) {
+               this.y = y;
+       }
+
+       /**
+        * Get <i>z</i>, the third value.
+        * 
+        * @return the third value. 
+        * 
+        * @since vecmath 1.5
+        */
+       public final byte getZ() {
+               return z;
+       }
+
+
+       /**
+        * Set <i>z</i>, the third value.
+        * 
+        * @param z the third value to set.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setZ(byte z) {
+               this.z = z;
+       }
+
+}
diff --git a/javax.vecmath/src/javax/vecmath/Tuple3d.java b/javax.vecmath/src/javax/vecmath/Tuple3d.java
new file mode 100644 (file)
index 0000000..e9cff82
--- /dev/null
@@ -0,0 +1,758 @@
+/*
+ * $RCSfile: Tuple3d.java,v $
+ *
+ * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ * $Revision: 1.8 $
+ * $Date: 2008/02/28 20:18:51 $
+ * $State: Exp $
+ */
+
+package javax.vecmath;
+
+import java.lang.Math;
+
+/**
+ * A generic 3-element tuple that is represented by double-precision 
+ * floating point x,y,z coordinates.
+ *
+ */
+public abstract class Tuple3d implements java.io.Serializable, Cloneable {
+
+    static final long serialVersionUID = 5542096614926168415L;
+
+    /**
+     * The x coordinate.
+     */
+    public     double  x;
+
+    /**
+     * The y coordinate.
+     */
+    public     double  y;
+
+    /**
+     * The z coordinate.
+     */
+    public     double  z;
+
+
+    /**
+     * Constructs and initializes a Tuple3d from the specified xyz coordinates.
+     * @param x the x coordinate
+     * @param y the y coordinate
+     * @param z the z coordinate
+     */
+    public Tuple3d(double x, double y, double z)
+    {
+       this.x = x;
+       this.y = y;
+       this.z = z;
+    }
+
+    /**
+     * Constructs and initializes a Tuple3d from the array of length 3.
+     * @param t the array of length 3 containing xyz in order
+     */
+    public Tuple3d(double[] t)
+    {
+       this.x = t[0];
+       this.y = t[1];
+       this.z = t[2];
+    }
+
+    /**
+     * Constructs and initializes a Tuple3d from the specified Tuple3d.
+     * @param t1 the Tuple3d containing the initialization x y z data
+     */
+    public Tuple3d(Tuple3d t1)
+    {
+       this.x = t1.x;
+       this.y = t1.y;
+       this.z = t1.z;
+    }
+
+    /**
+     * Constructs and initializes a Tuple3d from the specified Tuple3f.
+     * @param t1 the Tuple3f containing the initialization x y z data
+     */
+    public Tuple3d(Tuple3f t1)
+    {
+       this.x = (double) t1.x;
+       this.y = (double) t1.y;
+       this.z = (double) t1.z;
+    }
+
+    /**
+     * Constructs and initializes a Tuple3d to (0,0,0).
+     */
+    public Tuple3d()
+    {
+       this.x = (double) 0.0;
+       this.y = (double) 0.0;
+       this.z = (double) 0.0;
+    }
+
+    /**
+     * Sets the value of this tuple to the specified xyz coordinates.
+     * @param x the x coordinate
+     * @param y the y coordinate
+     * @param z the z coordinate
+     */
+    public final void set(double x, double y, double z)
+    {
+       this.x = x;
+       this.y = y;
+       this.z = z;
+    }
+
+    /**
+     * Sets the value of this tuple to the value of the xyz coordinates
+     * located in the array of length 3.
+     * @param t the array of length 3 containing xyz in order
+     */
+    public final void set(double[] t)
+    {
+       this.x = t[0];
+       this.y = t[1];
+       this.z = t[2];
+    }
+
+    /**
+     * Sets the value of this tuple to the value of tuple t1.
+     * @param t1 the tuple to be copied
+     */
+    public final void set(Tuple3d t1)
+    {
+       this.x = t1.x;
+       this.y = t1.y;
+       this.z = t1.z;
+    }
+
+    /**
+     * Sets the value of this tuple to the value of tuple t1.
+     * @param t1 the tuple to be copied
+     */
+    public final void set(Tuple3f t1)
+    {
+       this.x = (double) t1.x;
+       this.y = (double) t1.y;
+       this.z = (double) t1.z;
+    }
+
+   /**
+     * Copies the x,y,z coordinates of this tuple into the array t
+     * of length 3.
+     * @param t  the target array 
+     */
+    public final void get(double[] t)
+    {
+        t[0] = this.x;
+        t[1] = this.y;
+        t[2] = this.z;
+    }
+
+
+   /**
+     * Copies the x,y,z coordinates of this tuple into the tuple t.
+     * @param t  the Tuple3d object into which the values of this object are copied
+     */
+    public final void get(Tuple3d t)
+    {
+        t.x = this.x;
+        t.y = this.y;
+        t.z = this.z;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the sum of tuples t1 and t2.
+     * @param t1 the first tuple
+     * @param t2 the second tuple
+     */
+    public final void add(Tuple3d t1, Tuple3d t2)
+    {
+       this.x = t1.x + t2.x;
+       this.y = t1.y + t2.y;
+       this.z = t1.z + t2.z;
+    }
+
+
+    /**  
+     * Sets the value of this tuple to the sum of itself and t1.
+     * @param t1 the other tuple
+     */  
+    public final void add(Tuple3d t1)
+    { 
+        this.x += t1.x;
+        this.y += t1.y;
+        this.z += t1.z;
+    }
+
+    /**
+     * Sets the value of this tuple to the difference of tuples
+     * t1 and t2 (this = t1 - t2).
+     * @param t1 the first tuple
+     * @param t2 the second tuple
+     */
+    public final void sub(Tuple3d t1, Tuple3d t2)
+    {
+       this.x = t1.x - t2.x;
+       this.y = t1.y - t2.y;
+       this.z = t1.z - t2.z;
+    }
+    /**  
+     * Sets the value of this tuple to the difference
+     * of itself and t1 (this = this - t1).
+     * @param t1 the other tuple
+     */  
+    public final void sub(Tuple3d t1)
+    { 
+        this.x -= t1.x;
+        this.y -= t1.y;
+        this.z -= t1.z;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the negation of tuple t1.
+     * @param t1 the source tuple
+     */
+    public final void negate(Tuple3d t1)
+    {
+       this.x = -t1.x;
+       this.y = -t1.y;
+       this.z = -t1.z;
+    }
+
+
+    /**
+     * Negates the value of this tuple in place.
+     */
+    public final void negate()
+    {
+       this.x = -this.x;
+       this.y = -this.y;
+       this.z = -this.z;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the scalar multiplication
+     * of tuple t1.
+     * @param s the scalar value
+     * @param t1 the source tuple
+     */
+    public final void scale(double s, Tuple3d t1)
+    {
+       this.x = s*t1.x;
+       this.y = s*t1.y;
+       this.z = s*t1.z;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the scalar multiplication
+     * of itself.
+     * @param s the scalar value
+     */
+    public final void scale(double s)
+    {
+        this.x *= s;
+        this.y *= s;
+        this.z *= s;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the scalar multiplication
+     * of tuple t1 and then adds tuple t2 (this = s*t1 + t2).
+     * @param s the scalar value
+     * @param t1 the tuple to be multipled
+     * @param t2 the tuple to be added
+     */
+    public final void scaleAdd(double s, Tuple3d t1, Tuple3d t2)
+    {
+       this.x = s*t1.x + t2.x;
+       this.y = s*t1.y + t2.y;
+       this.z = s*t1.z + t2.z;
+    }
+
+
+    /**
+     * @deprecated Use scaleAdd(double,Tuple3d) instead
+     */  
+    public final void scaleAdd(double s, Tuple3f t1) {
+       scaleAdd(s, new Point3d(t1));
+    }
+
+
+    /**
+     * Sets the value of this tuple to the scalar multiplication
+     * of itself and then adds tuple t1 (this = s*this + t1).
+     * @param s the scalar value
+     * @param t1 the tuple to be added
+     */  
+    public final void scaleAdd(double s, Tuple3d t1) {
+        this.x = s*this.x + t1.x;
+        this.y = s*this.y + t1.y;
+        this.z = s*this.z + t1.z;
+    }
+
+
+
+   /**
+     * Returns a string that contains the values of this Tuple3d.
+     * The form is (x,y,z).
+     * @return the String representation
+     */  
+    public String toString() {
+        return "(" + this.x + ", " + this.y + ", " + this.z + ")";
+    }
+
+
+    /**
+     * Returns a hash code value based on the data values in this
+     * object.  Two different Tuple3d objects with identical data values
+     * (i.e., Tuple3d.equals returns true) will return the same hash
+     * code value.  Two objects with different data members may return the
+     * same hash value, although this is not likely.
+     * @return the integer hash code value
+     */  
+    public int hashCode() {
+       long bits = 1L;
+       bits = 31L * bits + VecMathUtil.doubleToLongBits(x);
+       bits = 31L * bits + VecMathUtil.doubleToLongBits(y);
+       bits = 31L * bits + VecMathUtil.doubleToLongBits(z);
+       return (int) (bits ^ (bits >> 32));
+    }
+
+
+   /**
+     * Returns true if all of the data members of Tuple3d t1 are
+     * equal to the corresponding data members in this Tuple3d.
+     * @param t1  the tuple with which the comparison is made
+     * @return  true or false
+     */  
+    public boolean equals(Tuple3d t1)
+    {
+      try {
+        return(this.x == t1.x && this.y == t1.y && this.z == t1.z);
+      }
+      catch (NullPointerException e2) {return false;}
+    }
+
+   /**
+     * Returns true if the Object t1 is of type Tuple3d and all of the
+     * data members of t1 are equal to the corresponding data members in
+     * this Tuple3d.
+     * @param t1  the Object with which the comparison is made
+     * @return  true or false
+     */  
+    public boolean equals(Object t1)
+    {
+      try {
+           Tuple3d t2 = (Tuple3d) t1;
+           return(this.x == t2.x && this.y == t2.y && this.z == t2.z);
+      }
+      catch (ClassCastException   e1) {return false;}
+      catch (NullPointerException e2) {return false;}
+
+    }
+
+   /**
+     * Returns true if the L-infinite distance between this tuple
+     * and tuple t1 is less than or equal to the epsilon parameter, 
+     * otherwise returns false.  The L-infinite
+     * distance is equal to MAX[abs(x1-x2), abs(y1-y2), abs(z1-z2)].
+     * @param t1  the tuple to be compared to this tuple
+     * @param epsilon  the threshold value  
+     * @return  true or false
+     */
+    public boolean epsilonEquals(Tuple3d t1, double epsilon)
+    {
+       double diff;
+
+       diff = x - t1.x;
+       if(Double.isNaN(diff)) return false;
+       if((diff<0?-diff:diff) > epsilon) return false;
+
+       diff = y - t1.y;
+       if(Double.isNaN(diff)) return false;
+       if((diff<0?-diff:diff) > epsilon) return false;
+
+       diff = z - t1.z;
+       if(Double.isNaN(diff)) return false;
+       if((diff<0?-diff:diff) > epsilon) return false;
+
+       return true;
+
+    }
+
+
+    /**
+     * @deprecated Use clamp(double,double,Tuple3d) instead
+     */
+    public final void clamp(float min, float max, Tuple3d t) {
+       clamp((double)min, (double)max, t);
+    }
+
+
+    /**
+     *  Clamps the tuple parameter to the range [low, high] and 
+     *  places the values into this tuple.  
+     *  @param min   the lowest value in the tuple after clamping
+     *  @param max  the highest value in the tuple after clamping 
+     *  @param t   the source tuple, which will not be modified
+     */
+    public final void clamp(double min, double max, Tuple3d t) {
+        if( t.x > max ) {
+          x = max;
+        } else if( t.x < min ){
+          x = min;
+        } else {
+          x = t.x;
+        }
+        if( t.y > max ) {
+          y = max;
+        } else if( t.y < min ){
+          y = min;
+        } else {
+          y = t.y;
+        }
+        if( t.z > max ) {
+          z = max;
+        } else if( t.z < min ){
+          z = min;
+        } else {
+          z = t.z;
+        }
+
+   }
+
+
+    /** 
+     * @deprecated Use clampMin(double,Tuple3d) instead
+     */   
+    public final void clampMin(float min, Tuple3d t) {
+       clampMin((double)min, t);
+    }
+
+
+    /** 
+     *  Clamps the minimum value of the tuple parameter to the min 
+     *  parameter and places the values into this tuple.
+     *  @param min   the lowest value in the tuple after clamping 
+     *  @param t   the source tuple, which will not be modified
+     */   
+    public final void clampMin(double min, Tuple3d t) { 
+        if( t.x < min ) {
+          x = min;
+        } else {
+          x = t.x;
+        }
+        if( t.y < min ) {
+          y = min;
+        } else {
+          y = t.y;
+        }
+        if( t.z < min ) {
+          z = min;
+        } else {
+          z = t.z;
+        }
+
+   } 
+
+
+    /** 
+     * @deprecated Use clampMax(double,Tuple3d) instead
+     */   
+    public final void clampMax(float max, Tuple3d t) {
+       clampMax((double)max, t);
+    }
+
+
+    /**  
+     *  Clamps the maximum value of the tuple parameter to the max 
+     *  parameter and places the values into this tuple.
+     *  @param max the highest value in the tuple after clamping  
+     *  @param t   the source tuple, which will not be modified
+     */    
+    public final void clampMax(double max, Tuple3d t) {  
+        if( t.x > max ) {
+          x = max;
+        } else {
+          x = t.x;
+        }
+        if( t.y > max ) {
+          y = max;
+        } else {
+          y = t.y;
+        }
+        if( t.z > max ) {
+          z = max;
+        } else {
+          z = t.z;
+        }
+
+   } 
+
+
+  /**  
+    *  Sets each component of the tuple parameter to its absolute 
+    *  value and places the modified values into this tuple.
+    *  @param t   the source tuple, which will not be modified
+    */    
+  public final void absolute(Tuple3d t)
+  {
+       x = Math.abs(t.x);
+       y = Math.abs(t.y);
+       z = Math.abs(t.z);
+
+  } 
+
+
+    /**
+     * @deprecated Use clamp(double,double) instead
+     */
+    public final void clamp(float min, float max) {
+       clamp((double)min, (double)max);
+    }
+
+
+    /**
+     *  Clamps this tuple to the range [low, high].
+     *  @param min  the lowest value in this tuple after clamping
+     *  @param max  the highest value in this tuple after clamping
+     */
+    public final void clamp(double min, double max) {
+        if( x > max ) {
+          x = max;
+        } else if( x < min ){
+          x = min;
+        }
+        if( y > max ) {
+          y = max;
+        } else if( y < min ){
+          y = min;
+        }
+        if( z > max ) {
+          z = max;
+        } else if( z < min ){
+          z = min;
+        }
+
+   }
+
+    /** 
+     * @deprecated Use clampMin(double) instead
+     */   
+    public final void clampMin(float min) {
+       clampMin((double)min);
+    }
+
+
+    /**
+     *  Clamps the minimum value of this tuple to the min parameter.
+     *  @param min   the lowest value in this tuple after clamping
+     */
+    public final void clampMin(double min) { 
+      if( x < min ) x=min;
+      if( y < min ) y=min;
+      if( z < min ) z=min;
+
+   } 
+    /** 
+     * @deprecated Use clampMax(double) instead
+     */   
+    public final void clampMax(float max) {
+       clampMax((double)max);
+    }
+
+
+    /**
+     *  Clamps the maximum value of this tuple to the max parameter.
+     *  @param max   the highest value in the tuple after clamping
+     */
+    public final void clampMax(double max) { 
+      if( x > max ) x=max;
+      if( y > max ) y=max;
+      if( z > max ) z=max;
+   }
+
+
+  /**
+    *  Sets each component of this tuple to its absolute value.
+    */
+  public final void absolute()
+  {
+     x = Math.abs(x);
+     y = Math.abs(y);
+     z = Math.abs(z);
+  }
+
+
+    /**
+     * @deprecated Use interpolate(Tuple3d,Tuple3d,double) instead
+     */
+    public final void interpolate(Tuple3d t1, Tuple3d t2, float alpha) {
+       interpolate(t1, t2, (double)alpha);
+    }
+
+
+    /**
+     *  Linearly interpolates between tuples t1 and t2 and places the 
+     *  result into this tuple:  this = (1-alpha)*t1 + alpha*t2.
+     *  @param t1  the first tuple
+     *  @param t2  the second tuple  
+     *  @param alpha  the alpha interpolation parameter  
+     */   
+    public final void interpolate(Tuple3d t1, Tuple3d t2, double alpha) {
+       this.x = (1-alpha)*t1.x + alpha*t2.x;
+       this.y = (1-alpha)*t1.y + alpha*t2.y;
+       this.z = (1-alpha)*t1.z + alpha*t2.z;
+    }
+    /**
+     * @deprecated Use interpolate(Tuple3d,double) instead
+     */
+    public final void interpolate(Tuple3d t1, float alpha) {
+       interpolate(t1, (double)alpha);
+    }
+
+
+    /**   
+    *  Linearly interpolates between this tuple and tuple t1 and 
+    *  places the result into this tuple:  this = (1-alpha)*this + alpha*t1. 
+    *  @param t1  the first tuple 
+    *  @param alpha  the alpha interpolation parameter   
+    */    
+    public final void interpolate(Tuple3d t1, double alpha) {
+       this.x = (1-alpha)*this.x + alpha*t1.x;
+       this.y = (1-alpha)*this.y + alpha*t1.y;
+       this.z = (1-alpha)*this.z + alpha*t1.z;
+    }  
+    /**
+     * Creates a new object of the same class as this object.
+     *
+     * @return a clone of this instance.
+     * @exception OutOfMemoryError if there is not enough memory.
+     * @see java.lang.Cloneable
+     * @since vecmath 1.3
+     */
+    public Object clone() {
+       // Since there are no arrays we can just use Object.clone()
+       try {
+           return super.clone();
+       } catch (CloneNotSupportedException e) {
+           // this shouldn't happen, since we are Cloneable
+           throw new InternalError();
+       }
+    }
+
+    /**
+        * Get the <i>x</i> coordinate.
+        * 
+        * @return  the <i>x</i> coordinate.
+        * 
+        * @since vecmath 1.5
+        */
+       public final double getX() {
+               return x;
+       }
+
+
+       /**
+        * Set the <i>x</i> coordinate.
+        * 
+        * @param x  value to <i>x</i> coordinate.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setX(double x) {
+               this.x = x;
+       }
+
+
+       /**
+        * Get the <i>y</i> coordinate.
+        * 
+        * @return the <i>y</i> coordinate.
+        * 
+        * @since vecmath 1.5
+        */
+       public final double getY() {
+               return y;
+       }
+
+
+       /**
+        * Set the <i>y</i> coordinate.
+        * 
+        * @param y value to <i>y</i> coordinate.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setY(double y) {
+               this.y = y;
+       }
+
+       /**
+        * Get the <i>z</i> coordinate.
+        * 
+        * @return the <i>z</i> coordinate.
+        * 
+        * @since vecmath 1.5
+        */
+       public final double getZ() {
+               return z;
+       }
+
+
+       /**
+        * Set the <i>z</i> coordinate.
+        * 
+        * @param z value to <i>z</i> coordinate.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setZ(double z) {
+               this.z = z;
+       }
+}
diff --git a/javax.vecmath/src/javax/vecmath/Tuple3f.java b/javax.vecmath/src/javax/vecmath/Tuple3f.java
new file mode 100644 (file)
index 0000000..c55f7b4
--- /dev/null
@@ -0,0 +1,713 @@
+/*
+ * $RCSfile: Tuple3f.java,v $
+ *
+ * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ * $Revision: 1.8 $
+ * $Date: 2008/02/28 20:18:51 $
+ * $State: Exp $
+ */
+
+package javax.vecmath;
+
+import java.lang.Math;
+
+/**
+ * A generic 3-element tuple that is represented by single precision-floating  
+ * point x,y,z coordinates.
+ *
+ */
+public abstract class Tuple3f implements java.io.Serializable, Cloneable {
+
+    static final long serialVersionUID=5019834619484343712L;
+
+    /**
+     * The x coordinate.
+     */
+    public     float   x;
+
+    /**
+     * The y coordinate.
+     */
+    public     float   y;
+
+    /**
+     * The z coordinate.
+     */
+    public     float   z;
+
+
+    /**
+     * Constructs and initializes a Tuple3f from the specified xyz coordinates.
+     * @param x the x coordinate
+     * @param y the y coordinate
+     * @param z the z coordinate
+     */
+    public Tuple3f(float x, float y, float z)
+    {
+       this.x = x;
+       this.y = y;
+       this.z = z;
+    }
+
+
+    /**
+     * Constructs and initializes a Tuple3f from the array of length 3.
+     * @param t the array of length 3 containing xyz in order
+     */
+    public Tuple3f(float[] t)
+    {
+       this.x = t[0];
+       this.y = t[1];
+       this.z = t[2];
+    }
+
+
+    /**
+     * Constructs and initializes a Tuple3f from the specified Tuple3f.
+     * @param t1 the Tuple3f containing the initialization x y z data
+     */
+    public Tuple3f(Tuple3f t1)
+    {
+       this.x = t1.x;
+       this.y = t1.y;
+       this.z = t1.z;
+    }
+
+
+    /**
+     * Constructs and initializes a Tuple3f from the specified Tuple3d.
+     * @param t1 the Tuple3d containing the initialization x y z data
+     */
+    public Tuple3f(Tuple3d t1)
+    {
+       this.x = (float) t1.x;
+       this.y = (float) t1.y;
+       this.z = (float) t1.z;
+    }
+
+
+    /**
+     * Constructs and initializes a Tuple3f to (0,0,0).
+     */
+    public Tuple3f()
+    {
+       this.x = 0.0f;
+       this.y = 0.0f;
+       this.z = 0.0f;
+    }
+
+
+   /**
+     * Returns a string that contains the values of this Tuple3f.
+     * The form is (x,y,z).
+     * @return the String representation
+     */  
+    public String toString() {
+       return "(" + this.x + ", " + this.y + ", " + this.z + ")";
+    }
+
+
+    /**
+     * Sets the value of this tuple to the specified xyz coordinates.
+     * @param x the x coordinate
+     * @param y the y coordinate
+     * @param z the z coordinate
+     */
+    public final void set(float x, float y, float z)
+    {
+       this.x = x;
+       this.y = y;
+       this.z = z;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the xyz coordinates specified in
+     * the array of length 3.
+     * @param t the array of length 3 containing xyz in order
+     */
+    public final void set(float[] t)
+    {
+       this.x = t[0];
+       this.y = t[1];
+       this.z = t[2];
+    }
+
+
+    /**
+     * Sets the value of this tuple to the value of tuple t1.
+     * @param t1 the tuple to be copied
+     */
+    public final void set(Tuple3f t1)
+    {
+       this.x = t1.x;
+       this.y = t1.y;
+       this.z = t1.z;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the value of tuple t1.
+     * @param t1 the tuple to be copied
+     */
+    public final void set(Tuple3d t1)
+    {
+       this.x = (float) t1.x;
+       this.y = (float) t1.y;
+       this.z = (float) t1.z;
+    }
+
+
+   /** 
+     * Gets the value of this tuple and copies the values into t.
+     * @param t  the array of length 3 into which the values are copied 
+     */
+    public final void get(float[] t)
+    {
+       t[0] = this.x;
+       t[1] = this.y;
+       t[2] = this.z;
+    }
+
+
+   /**
+     * Gets the value of this tuple and copies the values into t.
+     * @param t  the Tuple3f object into which the values of this object are copied
+     */
+    public final void get(Tuple3f t)
+    {  
+       t.x = this.x;
+       t.y = this.y;
+       t.z = this.z;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the vector sum of tuples t1 and t2.
+     * @param t1 the first tuple
+     * @param t2 the second tuple
+     */
+    public final void add(Tuple3f t1, Tuple3f t2)
+    {
+       this.x = t1.x + t2.x;
+       this.y = t1.y + t2.y;
+       this.z = t1.z + t2.z;
+    }
+
+
+    /**  
+     * Sets the value of this tuple to the vector sum of itself and tuple t1.
+     * @param t1 the other tuple
+     */  
+    public final void add(Tuple3f t1)
+    {
+        this.x += t1.x;
+        this.y += t1.y;
+        this.z += t1.z;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the vector difference
+     * of tuples t1 and t2 (this = t1 - t2).
+     * @param t1 the first tuple
+     * @param t2 the second tuple
+     */
+    public final void sub(Tuple3f t1, Tuple3f t2)
+    {
+       this.x = t1.x - t2.x;
+       this.y = t1.y - t2.y;
+       this.z = t1.z - t2.z;
+    }
+
+
+   /**  
+     * Sets the value of this tuple to the vector difference of
+     * itself and tuple t1 (this = this - t1) .
+     * @param t1 the other tuple
+     */  
+    public final void sub(Tuple3f t1)
+    { 
+        this.x -= t1.x;
+        this.y -= t1.y;
+        this.z -= t1.z;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the negation of tuple t1.
+     * @param t1 the source tuple
+     */
+    public final void negate(Tuple3f t1)
+    {
+       this.x = -t1.x;
+       this.y = -t1.y;
+       this.z = -t1.z;
+    }
+
+
+    /**
+     * Negates the value of this tuple in place.
+     */
+    public final void negate()
+    {
+       this.x = -this.x;
+       this.y = -this.y;
+       this.z = -this.z;
+    }
+
+
+    /**
+     * Sets the value of this vector to the scalar multiplication
+     * of tuple t1.
+     * @param s the scalar value
+     * @param t1 the source tuple
+     */
+    public final void scale(float s, Tuple3f t1)
+    {
+       this.x = s*t1.x;
+       this.y = s*t1.y;
+       this.z = s*t1.z;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the scalar multiplication
+     * of the scale factor with this.
+     * @param s the scalar value
+     */
+    public final void scale(float s)
+    {
+       this.x *= s;
+       this.y *= s;
+       this.z *= s;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the scalar multiplication
+     * of tuple t1 and then adds tuple t2 (this = s*t1 + t2).
+     * @param s the scalar value
+     * @param t1 the tuple to be scaled and added
+     * @param t2 the tuple to be added without a scale
+     */
+    public final void scaleAdd(float s, Tuple3f t1, Tuple3f t2)
+    {
+       this.x = s*t1.x + t2.x;
+       this.y = s*t1.y + t2.y;
+       this.z = s*t1.z + t2.z;
+    }
+
+
+
+    /**
+     * Sets the value of this tuple to the scalar multiplication
+     * of itself and then adds tuple t1 (this = s*this + t1).
+     * @param s the scalar value
+     * @param t1 the tuple to be added
+     */
+    public final void scaleAdd(float s, Tuple3f t1)
+    {
+        this.x = s*this.x + t1.x;
+        this.y = s*this.y + t1.y;
+        this.z = s*this.z + t1.z;
+    }
+
+
+   /**
+     * Returns true if the Object t1 is of type Tuple3f and all of the
+     * data members of t1 are equal to the corresponding data members in
+     * this Tuple3f.
+     * @param t1  the vector with which the comparison is made
+     * @return  true or false
+     */ 
+    public boolean equals(Tuple3f t1)
+    {
+        try {
+           return(this.x == t1.x && this.y == t1.y && this.z == t1.z);
+        }
+        catch (NullPointerException e2) {return false;}
+    }
+   /**
+     * Returns true if the Object t1 is of type Tuple3f and all of the
+     * data members of t1 are equal to the corresponding data members in
+     * this Tuple3f.
+     * @param t1  the Object with which the comparison is made
+     * @return  true or false
+     */ 
+    public boolean equals(Object t1)
+    {
+        try {
+           Tuple3f t2 = (Tuple3f) t1;
+           return(this.x == t2.x && this.y == t2.y && this.z == t2.z);
+        }
+        catch (NullPointerException e2) {return false;}
+        catch (ClassCastException   e1) {return false;}
+    }
+
+
+   /**
+     * Returns true if the L-infinite distance between this tuple
+     * and tuple t1 is less than or equal to the epsilon parameter, 
+     * otherwise returns false.  The L-infinite
+     * distance is equal to MAX[abs(x1-x2), abs(y1-y2), abs(z1-z2)].
+     * @param t1  the tuple to be compared to this tuple
+     * @param epsilon  the threshold value  
+     * @return  true or false
+     */
+    public boolean epsilonEquals(Tuple3f t1, float epsilon)
+    {
+       float diff;
+
+       diff = x - t1.x;
+       if(Float.isNaN(diff)) return false;
+       if((diff<0?-diff:diff) > epsilon) return false;
+
+       diff = y - t1.y;
+       if(Float.isNaN(diff)) return false;
+       if((diff<0?-diff:diff) > epsilon) return false;
+
+       diff = z - t1.z;
+       if(Float.isNaN(diff)) return false;
+       if((diff<0?-diff:diff) > epsilon) return false;
+
+       return true;
+
+    }
+
+
+    /**
+     * Returns a hash code value based on the data values in this
+     * object.  Two different Tuple3f objects with identical data values
+     * (i.e., Tuple3f.equals returns true) will return the same hash
+     * code value.  Two objects with different data members may return the
+     * same hash value, although this is not likely.
+     * @return the integer hash code value
+     */  
+    public int hashCode() {
+       long bits = 1L;
+       bits = 31L * bits + (long)VecMathUtil.floatToIntBits(x);
+       bits = 31L * bits + (long)VecMathUtil.floatToIntBits(y);
+       bits = 31L * bits + (long)VecMathUtil.floatToIntBits(z);
+       return (int) (bits ^ (bits >> 32));
+    }
+
+
+  /** 
+    *  Clamps the tuple parameter to the range [low, high] and 
+    *  places the values into this tuple.  
+    *  @param min   the lowest value in the tuple after clamping 
+    *  @param max  the highest value in the tuple after clamping  
+    *  @param t   the source tuple, which will not be modified
+    */   
+   public final void clamp(float min, float max, Tuple3f t)  
+   { 
+        if( t.x > max ) {
+          x = max;
+        } else if( t.x < min ){
+          x = min;
+        } else {
+          x = t.x;
+        }
+        if( t.y > max ) {
+          y = max;
+        } else if( t.y < min ){
+          y = min;
+        } else {
+          y = t.y;
+        }
+
+        if( t.z > max ) {
+          z = max;
+        } else if( t.z < min ){
+          z = min;
+        } else {
+          z = t.z;
+        }
+
+   } 
+  /**    
+    *  Clamps the minimum value of the tuple parameter to the min 
+    *  parameter and places the values into this tuple.   
+    *  @param min   the lowest value in the tuple after clamping  
+    *  @param t   the source tuple, which will not be modified
+    */    
+   public final void clampMin(float min, Tuple3f t)  
+   {  
+        if( t.x < min ) {
+          x = min;
+        } else {
+          x = t.x;
+        }
+        if( t.y < min ) {
+          y = min;
+        } else {
+          y = t.y;
+        }
+        if( t.z < min ) {
+          z = min;
+        } else {
+          z = t.z;
+        }
+
+   }  
+  /**    
+    *  Clamps the maximum value of the tuple parameter to the max 
+    *  parameter and places the values into this tuple.   
+    *  @param max   the highest value in the tuple after clamping   
+    *  @param t   the source tuple, which will not be modified
+    */     
+   public final void clampMax(float max, Tuple3f t)   
+   { 
+        if( t.x > max ) {
+          x = max;
+        } else {
+          x = t.x;
+        }
+        if( t.y > max ) {
+          y = max;
+        } else {
+          y = t.y;
+        }
+        if( t.z > max ) {
+          z = max;
+        } else {
+          z = t.z;
+        }
+
+   } 
+  /** 
+    *  Sets each component of the tuple parameter to its absolute
+    *  value and places the modified values into this tuple.
+    *  @param t   the source tuple, which will not be modified
+    */   
+  public final void absolute(Tuple3f t)
+  {
+       x = Math.abs(t.x);
+       y = Math.abs(t.y);
+       z = Math.abs(t.z);
+  }
+
+
+
+  /**
+    *  Clamps this tuple to the range [low, high].
+    *  @param min  the lowest value in this tuple after clamping
+    *  @param max  the highest value in this tuple after clamping
+    */
+   public final void clamp(float min, float max)
+   {
+        if( x > max ) {
+          x = max;
+        } else if( x < min ){
+          x = min;
+        }
+        if( y > max ) {
+          y = max;
+        } else if( y < min ){
+          y = min;
+        }
+        if( z > max ) {
+          z = max;
+        } else if( z < min ){
+          z = min;
+        }
+
+   }
+
+  /**
+    *  Clamps the minimum value of this tuple to the min parameter.
+    *  @param min   the lowest value in this tuple after clamping
+    */
+   public final void clampMin(float min)
+   { 
+      if( x < min ) x=min;
+      if( y < min ) y=min;
+      if( z < min ) z=min;
+
+   } 
+  /**
+    *  Clamps the maximum value of this tuple to the max parameter.
+    *  @param max   the highest value in the tuple after clamping
+    */
+   public final void clampMax(float max)
+   { 
+      if( x > max ) x=max;
+      if( y > max ) y=max;
+      if( z > max ) z=max;
+
+   }
+
+
+  /**
+    *  Sets each component of this tuple to its absolute value.
+    */
+  public final void absolute()
+  {
+     x = Math.abs(x);
+     y = Math.abs(y);
+     z = Math.abs(z);
+
+  }
+
+
+  /**  
+    *  Linearly interpolates between tuples t1 and t2 and places the 
+    *  result into this tuple:  this = (1-alpha)*t1 + alpha*t2.
+    *  @param t1  the first tuple
+    *  @param t2  the second tuple  
+    *  @param alpha  the alpha interpolation parameter  
+    */   
+  public final void interpolate(Tuple3f t1, Tuple3f t2, float alpha) 
+  { 
+           this.x = (1-alpha)*t1.x + alpha*t2.x;
+           this.y = (1-alpha)*t1.y + alpha*t2.y;
+           this.z = (1-alpha)*t1.z + alpha*t2.z;
+        
+
+  } 
+  /**   
+    *  Linearly interpolates between this tuple and tuple t1 and 
+    *  places the result into this tuple:  this = (1-alpha)*this + alpha*t1. 
+    *  @param t1  the first tuple 
+    *  @param alpha  the alpha interpolation parameter   
+    */    
+  public final void interpolate(Tuple3f t1, float alpha)  
+  {  
+     this.x = (1-alpha)*this.x + alpha*t1.x;
+     this.y = (1-alpha)*this.y + alpha*t1.y;
+     this.z = (1-alpha)*this.z + alpha*t1.z;
+
+
+  }  
+    /**
+     * Creates a new object of the same class as this object.
+     *
+     * @return a clone of this instance.
+     * @exception OutOfMemoryError if there is not enough memory.
+     * @see java.lang.Cloneable
+     * @since vecmath 1.3
+     */
+    public Object clone() {
+       // Since there are no arrays we can just use Object.clone()
+       try {
+           return super.clone();
+       } catch (CloneNotSupportedException e) {
+           // this shouldn't happen, since we are Cloneable
+           throw new InternalError();
+       }
+    }
+
+
+    /**
+        * Get the <i>x</i> coordinate.
+        * 
+        * @return the  <i>x</i> coordinate.
+        * 
+        * @since vecmath 1.5
+        */
+       public final float getX() {
+               return x;
+       }
+
+
+       /**
+        * Set the <i>x</i> coordinate.
+        * 
+        * @param x  value to <i>x</i> coordinate.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setX(float x) {
+               this.x = x;
+       }
+
+
+       /**
+        * Get the <i>y</i> coordinate.
+        * 
+        * @return the <i>y</i> coordinate.
+        * 
+        * @since vecmath 1.5
+        */
+       public final float getY() {
+               return y;
+       }
+
+
+       /**
+        * Set the <i>y</i> coordinate.
+        * 
+        * @param y value to <i>y</i> coordinate.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setY(float y) {
+               this.y = y;
+       }
+
+       /**
+        * Get the <i>z</i> coordinate.
+        * 
+        * @return the <i>z</i> coordinate
+        * 
+        * @since vecmath 1.5
+        */
+       public final float getZ() {
+               return z;
+       }
+
+
+       /**
+        * Set the <i>Z</i> coordinate.
+        * 
+        * @param z value to <i>z</i> coordinate.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setZ(float z) {
+               this.z = z;
+       }
+}
diff --git a/javax.vecmath/src/javax/vecmath/Tuple3i.java b/javax.vecmath/src/javax/vecmath/Tuple3i.java
new file mode 100644 (file)
index 0000000..7fb2aea
--- /dev/null
@@ -0,0 +1,590 @@
+/*
+ * $RCSfile: Tuple3i.java,v $
+ *
+ * Copyright 1999-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ * $Revision: 1.7 $
+ * $Date: 2008/02/28 20:18:51 $
+ * $State: Exp $
+ */
+
+package javax.vecmath;
+
+import java.lang.Math;
+
+/**
+ * A 3-element tuple represented by signed integer x,y,z
+ * coordinates.
+ *
+ * @since vecmath 1.2
+ */
+public abstract class Tuple3i implements java.io.Serializable, Cloneable {
+
+    static final long serialVersionUID = -732740491767276200L;
+
+    /**
+     * The x coordinate.
+     */
+    public int x;
+
+    /**
+     * The y coordinate.
+     */
+    public int y;
+
+    /**
+     * The z coordinate.
+     */
+    public int z;
+
+
+    /**
+     * Constructs and initializes a Tuple3i from the specified
+     * x, y, and z coordinates.
+     * @param x the x coordinate
+     * @param y the y coordinate
+     * @param z the z coordinate
+     */
+    public Tuple3i(int x, int y, int z) {
+       this.x = x;
+       this.y = y;
+       this.z = z;
+    }
+
+
+    /**
+     * Constructs and initializes a Tuple3i from the array of length 3.
+     * @param t the array of length 3 containing x, y, and z in order.
+     */
+    public Tuple3i(int[] t) {
+       this.x = t[0];
+       this.y = t[1];
+       this.z = t[2];
+    }
+
+
+    /**
+     * Constructs and initializes a Tuple3i from the specified Tuple3i.
+     * @param t1 the Tuple3i containing the initialization x, y, and z
+     * data.
+     */
+    public Tuple3i(Tuple3i t1) {
+       this.x = t1.x;
+       this.y = t1.y;
+       this.z = t1.z;
+    }
+
+
+    /**
+     * Constructs and initializes a Tuple3i to (0,0,0).
+     */
+    public Tuple3i() {
+       this.x = 0;
+       this.y = 0;
+       this.z = 0;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the specified x, y, and z
+     * coordinates.
+     * @param x the x coordinate
+     * @param y the y coordinate
+     * @param z the z coordinate
+     */
+    public final void set(int x, int y, int z) {
+       this.x = x;
+       this.y = y;
+       this.z = z;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the specified coordinates in the
+     * array of length 3.
+     * @param t the array of length 3 containing x, y, and z in order.
+     */
+    public final void set(int[] t) {
+       this.x = t[0];
+       this.y = t[1];
+       this.z = t[2];
+    }
+
+
+    /**
+     * Sets the value of this tuple to the value of tuple t1.
+     * @param t1 the tuple to be copied
+     */
+    public final void set(Tuple3i t1) {
+       this.x = t1.x;
+       this.y = t1.y;
+       this.z = t1.z;
+    }
+
+
+    /**
+     * Copies the values of this tuple into the array t.
+     * @param t is the array
+     */
+    public final void get(int[] t) {
+       t[0] = this.x;
+       t[1] = this.y;
+       t[2] = this.z;
+    }
+
+
+    /**
+     * Copies the values of this tuple into the tuple t.
+     * @param t is the target tuple
+     */
+    public final void get(Tuple3i t) {
+       t.x = this.x;
+       t.y = this.y;
+       t.z = this.z;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the sum of tuples t1 and t2.
+     * @param t1 the first tuple
+     * @param t2 the second tuple
+     */
+    public final void add(Tuple3i t1, Tuple3i t2) {
+       this.x = t1.x + t2.x;
+       this.y = t1.y + t2.y;
+       this.z = t1.z + t2.z;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the sum of itself and t1.
+     * @param t1 the other tuple
+     */
+    public final void add(Tuple3i t1) {
+       this.x += t1.x;
+       this.y += t1.y;
+       this.z += t1.z;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the difference
+     * of tuples t1 and t2 (this = t1 - t2).
+     * @param t1 the first tuple
+     * @param t2 the second tuple
+     */
+    public final void sub(Tuple3i t1, Tuple3i t2) {
+       this.x = t1.x - t2.x;
+       this.y = t1.y - t2.y;
+       this.z = t1.z - t2.z;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the difference
+     * of itself and t1 (this = this - t1).
+     * @param t1 the other tuple
+     */
+    public final void sub(Tuple3i t1) {
+       this.x -= t1.x;
+       this.y -= t1.y;
+       this.z -= t1.z;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the negation of tuple t1.
+     * @param t1 the source tuple
+     */
+    public final void negate(Tuple3i t1) {
+       this.x = -t1.x;
+       this.y = -t1.y;
+       this.z = -t1.z;
+    }
+
+
+    /**
+     * Negates the value of this tuple in place.
+     */
+    public final void negate() {
+       this.x = -this.x;
+       this.y = -this.y;
+       this.z = -this.z;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the scalar multiplication
+     * of tuple t1.
+     * @param s the scalar value
+     * @param t1 the source tuple
+     */
+    public final void scale(int s, Tuple3i t1) {
+       this.x = s*t1.x;
+       this.y = s*t1.y;
+       this.z = s*t1.z;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the scalar multiplication
+     * of the scale factor with this.
+     * @param s the scalar value
+     */
+    public final void scale(int s) {
+       this.x *= s;
+       this.y *= s;
+       this.z *= s;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the scalar multiplication
+     * of tuple t1 plus tuple t2 (this = s*t1 + t2).
+     * @param s the scalar value
+     * @param t1 the tuple to be multipled
+     * @param t2 the tuple to be added
+     */
+    public final void scaleAdd(int s, Tuple3i t1, Tuple3i t2) {
+       this.x = s*t1.x + t2.x;
+       this.y = s*t1.y + t2.y;
+       this.z = s*t1.z + t2.z;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the scalar multiplication
+     * of itself and then adds tuple t1 (this = s*this + t1).
+     * @param s the scalar value
+     * @param t1 the tuple to be added
+     */
+    public final void scaleAdd(int s, Tuple3i t1) {
+        this.x = s*this.x + t1.x;
+        this.y = s*this.y + t1.y;
+        this.z = s*this.z + t1.z;
+    }
+
+
+    /**
+     * Returns a string that contains the values of this Tuple3i.
+     * The form is (x,y,z).
+     * @return the String representation
+     */
+    public String toString() {
+        return "(" + this.x + ", " + this.y + ", " + this.z + ")";
+    }
+
+
+    /**
+     * Returns true if the Object t1 is of type Tuple3i and all of the
+     * data members of t1 are equal to the corresponding data members in
+     * this Tuple3i.
+     * @param t1  the object with which the comparison is made
+     */
+    public boolean equals(Object t1) {
+        try {
+           Tuple3i t2 = (Tuple3i) t1;
+           return(this.x == t2.x && this.y == t2.y && this.z == t2.z);
+        }
+        catch (NullPointerException e2) {
+           return false;
+       }
+        catch (ClassCastException e1) {
+           return false;
+       }
+    }
+
+
+    /**
+     * Returns a hash code value based on the data values in this
+     * object.  Two different Tuple3i objects with identical data values
+     * (i.e., Tuple3i.equals returns true) will return the same hash
+     * code value.  Two objects with different data members may return the
+     * same hash value, although this is not likely.
+     * @return the integer hash code value
+     */
+    public int hashCode() {
+       long bits = 1L;
+       bits = 31L * bits + (long)x;
+       bits = 31L * bits + (long)y;
+       bits = 31L * bits + (long)z;
+       return (int) (bits ^ (bits >> 32));
+    }
+
+
+    /**
+     *  Clamps the tuple parameter to the range [low, high] and
+     *  places the values into this tuple.
+     *  @param min   the lowest value in the tuple after clamping
+     *  @param max  the highest value in the tuple after clamping
+     *  @param t   the source tuple, which will not be modified
+     */
+    public final void clamp(int min, int max, Tuple3i t) {
+        if( t.x > max ) {
+           x = max;
+        } else if( t.x < min ) {
+           x = min;
+        } else {
+           x = t.x;
+        }
+
+        if( t.y > max ) {
+           y = max;
+        } else if( t.y < min ) {
+           y = min;
+        } else {
+           y = t.y;
+        }
+
+        if( t.z > max ) {
+           z = max;
+        } else if( t.z < min ) {
+           z = min;
+        } else {
+           z = t.z;
+        }
+    }
+
+
+    /**
+     *  Clamps the minimum value of the tuple parameter to the min
+     *  parameter and places the values into this tuple.
+     *  @param min   the lowest value in the tuple after clamping
+     *  @param t   the source tuple, which will not be modified
+     */
+    public final void clampMin(int min, Tuple3i t) {
+        if( t.x < min ) {
+           x = min;
+        } else {
+           x = t.x;
+        }
+
+        if( t.y < min ) {
+           y = min;
+        } else {
+           y = t.y;
+        }
+
+        if( t.z < min ) {
+           z = min;
+        } else {
+           z = t.z;
+        }
+    }
+
+
+    /**
+     *  Clamps the maximum value of the tuple parameter to the max
+     *  parameter and places the values into this tuple.
+     *  @param max   the highest value in the tuple after clamping
+     *  @param t   the source tuple, which will not be modified
+     */
+    public final void clampMax(int max, Tuple3i t) {
+        if( t.x > max ) {
+           x = max;
+        } else {
+           x = t.x;
+        }
+
+        if( t.y > max ) {
+           y = max;
+        } else {
+           y = t.y;
+        }
+
+        if( t.z > max ) {
+           z = max;
+        } else {
+           z = t.z;
+        }
+    }
+
+
+    /**
+     *  Sets each component of the tuple parameter to its absolute
+     *  value and places the modified values into this tuple.
+     *  @param t   the source tuple, which will not be modified
+     */
+    public final void absolute(Tuple3i t) {
+       x = Math.abs(t.x);
+       y = Math.abs(t.y);
+       z = Math.abs(t.z);
+    }
+
+
+    /**
+     *  Clamps this tuple to the range [low, high].
+     *  @param min  the lowest value in this tuple after clamping
+     *  @param max  the highest value in this tuple after clamping
+     */
+    public final void clamp(int min, int max) {
+       if( x > max ) {
+           x = max;
+        } else if( x < min ) {
+           x = min;
+        }
+
+        if( y > max ) {
+           y = max;
+        } else if( y < min ) {
+           y = min;
+        }
+
+        if( z > max ) {
+           z = max;
+        } else if( z < min ) {
+           z = min;
+        }
+    }
+
+
+    /**
+     *  Clamps the minimum value of this tuple to the min parameter.
+     *  @param min   the lowest value in this tuple after clamping
+     */
+    public final void clampMin(int min) {
+       if (x < min)
+           x=min;
+
+       if (y < min)
+           y = min;
+
+       if (z < min)
+           z = min;
+    }
+
+
+    /**
+     *  Clamps the maximum value of this tuple to the max parameter.
+     *  @param max   the highest value in the tuple after clamping
+     */
+    public final void clampMax(int max) {
+       if (x > max)
+           x = max;
+
+       if (y > max)
+           y = max;
+
+       if (z > max)
+           z = max;
+    }
+
+
+    /**
+     *  Sets each component of this tuple to its absolute value.
+     */
+    public final void absolute() {
+       x = Math.abs(x);
+       y = Math.abs(y);
+       z = Math.abs(z);
+    }
+
+    /**
+     * Creates a new object of the same class as this object.
+     *
+     * @return a clone of this instance.
+     * @exception OutOfMemoryError if there is not enough memory.
+     * @see java.lang.Cloneable
+     * @since vecmath 1.3
+     */
+    public Object clone() {
+       // Since there are no arrays we can just use Object.clone()
+       try {
+           return super.clone();
+       } catch (CloneNotSupportedException e) {
+           // this shouldn't happen, since we are Cloneable
+           throw new InternalError();
+       }
+    }
+
+
+    /**
+        * Get the <i>x</i> coordinate.
+        * 
+        * @return  the <i>x</i> coordinate.
+        * 
+        * @since vecmath 1.5
+        */
+       public final int getX() {
+               return x;
+       }
+
+
+       /**
+        * Set the <i>x</i> coordinate.
+        * 
+        * @param x  value to <i>x</i> coordinate.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setX(int x) {
+               this.x = x;
+       }
+
+
+       /**
+        * Get the <i>y</i> coordinate.
+        * 
+        * @return  the <i>y</i> coordinate.
+        * 
+        * @since vecmath 1.5
+        */
+       public final int getY() {
+               return y;
+       }
+
+
+       /**
+        * Set the <i>y</i> coordinate.
+        * 
+        * @param y value to <i>y</i> coordinate.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setY(int y) {
+               this.y = y;
+       }
+
+       /**
+        * Get the <i>z</i> coordinate.
+        * 
+        * @return the <i>z</i> coordinate.
+        * @since vecmath 1.5
+        */
+       public final int getZ() {
+               return z;
+       }
+
+
+       /**
+        * Set the <i>z</i> coordinate.
+        * 
+        * @param z value to <i>z</i> coordinate.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setZ(int z) {
+               this.z = z;
+       }
+}
diff --git a/javax.vecmath/src/javax/vecmath/Tuple4b.java b/javax.vecmath/src/javax/vecmath/Tuple4b.java
new file mode 100644 (file)
index 0000000..ea40ff3
--- /dev/null
@@ -0,0 +1,359 @@
+/*
+ * $RCSfile: Tuple4b.java,v $
+ *
+ * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ * $Revision: 1.7 $
+ * $Date: 2008/02/28 20:18:51 $
+ * $State: Exp $
+ */
+
+package javax.vecmath;
+
+import java.lang.Math;
+
+/**
+ * A four byte tuple.  Note that Java defines a byte as a signed integer
+ * in the range [-128, 127]. However, colors are more typically
+ * represented by values in the range [0, 255]. Java 3D recognizes this
+ * and, in those cases where Tuple4b is used to represent color, treats
+ * the bytes as if the range were [0, 255]---in other words, as if the
+ * bytes were unsigned.
+ * Values greater than 127 can be assigned to a byte variable using a
+ * type cast.  For example:
+ * <ul>byteVariable = (byte) intValue; // intValue can be > 127</ul>
+ * If intValue is greater than 127, then byteVariable will be negative.  The
+ * correct value will be extracted when it is used (by masking off the upper
+ * bits).
+ */
+public abstract class Tuple4b implements java.io.Serializable, Cloneable {
+
+    static final long serialVersionUID = -8226727741811898211L;
+
+    /**
+     * The first value.
+     */
+    public     byte    x;
+
+    /**
+     * The second value.
+     */
+    public     byte    y;
+
+    /**
+     * The third value.
+     */
+    public     byte    z;
+
+    /**
+     * The fourth value.
+     */
+    public     byte    w;
+
+
+    /**
+     * Constructs and initializes a Tuple4b from the specified four values.
+     * @param b1 the first value
+     * @param b2 the second value
+     * @param b3 the third value
+     * @param b4 the fourth value
+     */
+    public Tuple4b(byte b1, byte b2, byte b3, byte b4)
+    {
+       this.x = b1;
+       this.y = b2;
+       this.z = b3;
+       this.w = b4;
+    }
+
+
+    /**
+     * Constructs and initializes a Tuple4b from the array of length 4.
+     * @param t the array of length 4 containing b1 b2 b3 b4 in order
+     */
+    public Tuple4b(byte[] t)
+    {
+       this.x = t[0];
+       this.y = t[1];
+       this.z = t[2];
+       this.w = t[3];
+    }
+
+
+    /**
+     * Constructs and initializes a Tuple4b from the specified Tuple4b.
+     * @param t1 the Tuple4b containing the initialization x y z w data
+     */
+    public Tuple4b(Tuple4b t1)
+    {
+       this.x = t1.x;
+       this.y = t1.y;
+       this.z = t1.z;
+       this.w = t1.w;
+    }
+
+
+    /**
+     * Constructs and initializes a Tuple4b to (0,0,0,0).
+     */
+    public Tuple4b()
+    {
+       this.x = (byte) 0;
+       this.y = (byte) 0;
+       this.z = (byte) 0;
+       this.w = (byte) 0;
+    }
+
+
+   /**
+     * Returns a string that contains the values of this Tuple4b.
+     * @return the String representation
+     */  
+    public String toString()
+    {
+        return("("  + ((int)this.x & 0xff) +
+              ", " + ((int)this.y & 0xff) +
+              ", " + ((int)this.z & 0xff) +
+              ", " + ((int)this.w & 0xff) + ")");
+    }
+
+
+   /**
+     * Places the value of the x,y,z,w components of this Tuple4b
+     * into the array of length 4.
+     * @param b   array of length 4 into which the values are placed
+     */
+    public final void get(byte[] b)
+    {
+        b[0] = this.x;
+        b[1] = this.y;
+        b[2] = this.z;
+        b[3] = this.w;
+    }
+
+
+   /**   
+     * Places the value of the x,y,z,w components of this
+     * Tuple4b into the tuple t1.
+     * @param t1   tuple into which the values are placed
+     */
+    public final void get(Tuple4b t1)
+    {
+       t1.x = this.x;
+       t1.y = this.y;
+       t1.z = this.z;
+       t1.w = this.w;
+   }
+
+
+   /**
+     * Sets the value of the data members of this tuple to the value
+     * of the argument tuple t1.
+     * @param t1  the source tuple
+     */
+    public final void set(Tuple4b t1)
+    {
+        this.x = t1.x;
+        this.y = t1.y;
+        this.z = t1.z;
+        this.w = t1.w;
+    }
+
+
+   /**
+     * Sets the value of the data members of this tuple to the value
+     * of the array b of length 4.
+     * @param b   the source array of length 4
+     */
+    public final void set(byte[] b)
+    {
+        this.x = b[0];
+        this.y = b[1];
+        this.z = b[2];
+        this.w = b[3];
+    }
+
+   /**
+     * Returns true if all of the data members of tuple t1 are equal to
+     * the corresponding data members in this tuple.
+     * @param t1  the tuple with which the comparison is made
+     */
+    public boolean equals(Tuple4b t1)
+    {
+        try {
+           return(this.x == t1.x && this.y == t1.y && 
+                  this.z == t1.z && this.w == t1.w);
+        }
+        catch (NullPointerException e2) {return false;}
+
+    }
+
+   /**
+     * Returns true if the Object t1 is of type Tuple4b and all of the
+     * data members of t1 are equal to the corresponding data members in
+     * this Tuple4b.
+     * @param t1  the object with which the comparison is made
+     */
+    public boolean equals(Object t1)
+    {
+        try {
+           Tuple4b t2 = (Tuple4b) t1;
+           return(this.x == t2.x && this.y == t2.y && 
+                  this.z == t2.z && this.w == t2.w);
+        }
+        catch (NullPointerException e2) {return false;}
+        catch (ClassCastException   e1) {return false;}
+
+    }
+
+
+    /**
+     * Returns a hash code value based on the data values in this
+     * object.  Two different Tuple4b objects with identical data values
+     * (i.e., Tuple4b.equals returns true) will return the same hash
+     * code value.  Two objects with different data members may return the
+     * same hash value, although this is not likely.
+     * @return the integer hash code value
+     */  
+    public int hashCode() {
+       return ((((int)x & 0xff) <<  0) |
+               (((int)y & 0xff) <<  8) |
+               (((int)z & 0xff) << 16) |
+               (((int)w & 0xff) << 24));
+    }
+
+    /**
+     * Creates a new object of the same class as this object.
+     *
+     * @return a clone of this instance.
+     * @exception OutOfMemoryError if there is not enough memory.
+     * @see java.lang.Cloneable
+     * @since vecmath 1.3
+     */
+    public Object clone() {
+       // Since there are no arrays we can just use Object.clone()
+       try {
+           return super.clone();
+       } catch (CloneNotSupportedException e) {
+           // this shouldn't happen, since we are Cloneable
+           throw new InternalError();
+       }
+    }
+
+
+    /**
+        * Get <i>x</i>, the first value.
+        * 
+        * @return Returns <i>x</i>, the first value.
+        * 
+        * @since vecmath 1.5
+        */
+       public final byte getX() {
+               return x;
+       }
+
+
+       /**
+        * Set <i>x</i>,  the first value.
+        * 
+        * @param x the first value.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setX(byte x) {
+               this.x = x;
+       }
+
+
+       /**
+        * Get <i>y</i>, the second value.
+        * 
+        * @return Returns <i>y</i>, the second value.
+        * 
+        * @since vecmath 1.5
+        */
+       public final byte getY() {
+               return y;
+       }
+
+
+       /**
+        * Set <i>y</i>, the second value.
+        * 
+        * @param y the second value.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setY(byte y) {
+               this.y = y;
+       }
+
+       /**
+        * Get <i>z</i>, the third value.
+        * 
+        *  @return Returns <i>z</i>, the third value.  
+        *   
+        * @since vecmath 1.5
+        */
+       public final byte getZ() {
+               return z;
+       }
+
+
+       /**
+        * Set <i>z</i>,  the third value.
+        * 
+        * @param z  the third value.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setZ(byte z) {
+               this.z = z;
+       }
+
+
+       /**
+        * Get <i>w</i>, the fourth value.
+        * 
+        * @return Returns <i>w</i> - the fourth value.
+        * 
+        * @since vecmath 1.5
+        */
+       public final byte getW() {
+               return w;
+       }
+
+
+       /**
+        * Set <i>w</i>, the fourth value.
+        * 
+        * @param w the fourth value.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setW(byte w) {
+               this.w = w;
+       }
+}
diff --git a/javax.vecmath/src/javax/vecmath/Tuple4d.java b/javax.vecmath/src/javax/vecmath/Tuple4d.java
new file mode 100644 (file)
index 0000000..20bffeb
--- /dev/null
@@ -0,0 +1,867 @@
+/*
+ * $RCSfile: Tuple4d.java,v $
+ *
+ * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ * $Revision: 1.8 $
+ * $Date: 2008/02/28 20:18:51 $
+ * $State: Exp $
+ */
+
+package javax.vecmath;
+
+import java.lang.Math;
+
+/**
+ * A 4 element tuple represented by double precision floating point 
+ * x,y,z,w coordinates.
+ *
+ */
+public abstract class Tuple4d implements java.io.Serializable, Cloneable {
+
+    static final long serialVersionUID = -4748953690425311052L;
+
+    /**
+     * The x coordinate.
+     */
+    public     double  x;
+
+    /**
+     * The y coordinate.
+     */
+    public     double  y;
+
+    /**
+     * The z coordinate.
+     */
+    public     double  z;
+
+    /**
+     * The w coordinate.
+     */
+    public     double  w;
+
+
+    /**
+     * Constructs and initializes a Tuple4d from the specified xyzw coordinates.
+     * @param x the x coordinate
+     * @param y the y coordinate
+     * @param z the z coordinate
+     * @param w the w coordinate
+     */
+    public Tuple4d(double x, double y, double z, double w)
+    {
+       this.x = x;
+       this.y = y;
+       this.z = z;
+       this.w = w;
+    }
+
+
+    /**
+     * Constructs and initializes a Tuple4d from the coordinates contained
+     * in the array.
+     * @param t the array of length 4 containing xyzw in order
+     */
+    public Tuple4d(double[] t)
+    {
+       this.x = t[0];
+       this.y = t[1];
+       this.z = t[2];
+       this.w = t[3];
+    }
+
+
+    /**
+     * Constructs and initializes a Tuple4d from the specified Tuple4d.
+     * @param t1 the Tuple4d containing the initialization x y z w data
+     */
+    public Tuple4d(Tuple4d t1)
+    {
+       this.x = t1.x;
+       this.y = t1.y;
+       this.z = t1.z;
+       this.w = t1.w;
+    }
+
+
+    /**
+     * Constructs and initializes a Tuple4d from the specified Tuple4f.
+     * @param t1 the Tuple4f containing the initialization x y z w data
+     */
+    public Tuple4d(Tuple4f t1)
+    {
+       this.x = t1.x;
+       this.y = t1.y;
+       this.z = t1.z;
+       this.w = t1.w;
+    }
+
+
+    /**
+     * Constructs and initializes a Tuple4d to (0,0,0,0).
+     */
+    public Tuple4d()
+    {
+       this.x = 0.0;
+       this.y = 0.0;
+       this.z = 0.0;
+       this.w = 0.0;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the specified xyzw coordinates.
+     * @param x the x coordinate
+     * @param y the y coordinate
+     * @param z the z coordinate
+     * @param w the w coordinate
+     */
+    public final void set(double x, double y, double z, double w)
+    {
+       this.x = x;
+       this.y = y;
+       this.z = z;
+       this.w = w;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the specified xyzw coordinates.
+     * @param t the array of length 4 containing xyzw in order
+     */
+    public final void set(double[] t)
+    {
+       this.x = t[0];
+       this.y = t[1];
+       this.z = t[2];
+       this.w = t[3];
+    }
+
+
+    /**
+     * Sets the value of this tuple to the value of tuple t1.
+     * @param t1 the tuple to be copied
+     */
+    public final void set(Tuple4d t1)
+    {
+       this.x = t1.x;
+       this.y = t1.y;
+       this.z = t1.z;
+       this.w = t1.w;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the value of tuple t1.
+     * @param t1 the tuple to be copied
+     */
+    public final void set(Tuple4f t1)
+    {
+       this.x = t1.x;
+       this.y = t1.y;
+       this.z = t1.z;
+       this.w = t1.w;
+    }
+
+
+    /**
+     * Gets the value of this tuple and places it into the array t of
+     * length four in x,y,z,w order.
+     * @param t  the array of length four
+     */
+    public final void get(double[] t)
+    {
+        t[0] = this.x;
+        t[1] = this.y;
+        t[2] = this.z;
+        t[3] = this.w;
+    }
+
+
+    /**
+     * Gets the value of this tuple and places it into the Tuple4d
+     * argument of
+     * length four in x,y,z,w order.
+     * @param t  the Tuple into which the values will be copied
+     */
+    public final void get(Tuple4d t)
+    {
+        t.x = this.x;
+        t.y = this.y;
+        t.z = this.z;
+        t.w = this.w;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the tuple sum of tuples t1 and t2.
+     * @param t1 the first tuple
+     * @param t2 the second tuple
+     */
+    public final void add(Tuple4d t1, Tuple4d t2)
+    {
+       this.x = t1.x + t2.x;
+       this.y = t1.y + t2.y;
+       this.z = t1.z + t2.z;
+       this.w = t1.w + t2.w;
+    }
+
+
+    /**  
+     * Sets the value of this tuple to the sum of itself and tuple t1.
+     * @param t1 the other tuple
+     */
+    public final void add(Tuple4d t1)
+    {
+        this.x += t1.x;
+        this.y += t1.y;
+        this.z += t1.z;
+        this.w += t1.w;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the difference
+     * of tuples t1 and t2 (this = t1 - t2).
+     * @param t1 the first tuple
+     * @param t2 the second tuple
+     */
+    public final void sub(Tuple4d t1, Tuple4d t2)
+    {
+       this.x = t1.x - t2.x;
+       this.y = t1.y - t2.y;
+       this.z = t1.z - t2.z;
+       this.w = t1.w - t2.w;
+    }
+
+
+    /**  
+     * Sets the value of this tuple to the difference of itself
+     * and tuple t1 (this = this - t1).
+     * @param t1 the other tuple
+     */
+   public final void sub(Tuple4d t1)
+    { 
+        this.x -= t1.x;
+        this.y -= t1.y;
+        this.z -= t1.z;
+        this.w -= t1.w;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the negation of tuple t1.
+     * @param t1 the source tuple
+     */
+    public final void negate(Tuple4d t1)
+    {
+       this.x = -t1.x;
+       this.y = -t1.y;
+       this.z = -t1.z;
+       this.w = -t1.w;
+    }
+
+
+    /**
+     * Negates the value of this tuple in place.
+     */
+    public final void negate()
+    {
+       this.x = -this.x;
+       this.y = -this.y;
+       this.z = -this.z;
+       this.w = -this.w;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the scalar multiplication
+     * of the scale factor with the tuple t1.
+     * @param s the scalar value
+     * @param t1 the source tuple
+     */
+    public final void scale(double s, Tuple4d t1)
+    {
+       this.x = s*t1.x;
+       this.y = s*t1.y;
+       this.z = s*t1.z;
+       this.w = s*t1.w;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the scalar multiplication
+     * of the scale factor with this.
+     * @param s the scalar value
+     */
+    public final void scale(double s)
+    {
+       this.x *= s;
+       this.y *= s;
+       this.z *= s;
+       this.w *= s;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the scalar multiplication by s
+     * of tuple t1 plus tuple t2 (this = s*t1 + t2).
+     * @param s the scalar value
+     * @param t1 the tuple to be multipled
+     * @param t2 the tuple to be added
+     */
+    public final void scaleAdd(double s, Tuple4d t1, Tuple4d t2)
+    {
+       this.x = s*t1.x + t2.x;
+       this.y = s*t1.y + t2.y;
+       this.z = s*t1.z + t2.z;
+       this.w = s*t1.w + t2.w;
+    }
+
+
+    /**
+     * @deprecated Use scaleAdd(double,Tuple4d) instead
+     */  
+    public final void scaleAdd(float s, Tuple4d t1) {
+       scaleAdd((double)s, t1);
+    }
+
+
+    /** 
+     * Sets the value of this tuple to the scalar multiplication
+     * of itself and then adds tuple t1 (this = s*this + t1).
+     * @param s the scalar value 
+     * @param t1 the tuple to be added 
+     */   
+    public final void scaleAdd(double s, Tuple4d t1) {
+        this.x = s*this.x + t1.x; 
+        this.y = s*this.y + t1.y; 
+        this.z = s*this.z + t1.z; 
+        this.w = s*this.w + t1.w;
+    } 
+
+
+   /**
+     * Returns a string that contains the values of this Tuple4d.
+     * The form is (x,y,z,w).
+     * @return the String representation
+     */  
+    public String toString() {
+        return "(" + this.x + ", " + this.y + ", " + this.z + ", " + this.w + ")";
+    }
+
+
+   /**
+     * Returns true if all of the data members of Tuple4d t1 are
+     * equal to the corresponding data members in this Tuple4d.
+     * @param t1  the tuple with which the comparison is made
+     * @return  true or false
+     */  
+    public boolean equals(Tuple4d t1)
+    {
+        try {
+        return(this.x == t1.x && this.y == t1.y && this.z == t1.z
+            && this.w == t1.w);
+        }
+        catch (NullPointerException e2) {return false;}
+    }
+
+   /**
+     * Returns true if the Object t1 is of type Tuple4d and all of the
+     * data members of t1 are equal to the corresponding data members in
+     * this Tuple4d.
+     * @param t1  the object with which the comparison is made
+     * @return  true or false
+     */
+    public boolean equals(Object t1)
+    {
+        try {
+
+           Tuple4d t2 = (Tuple4d) t1;
+           return(this.x == t2.x && this.y == t2.y && 
+                  this.z == t2.z && this.w == t2.w);
+        }
+        catch (NullPointerException e2) {return false;}
+        catch (ClassCastException   e1) {return false;}
+    }
+
+
+   /**
+     * Returns true if the L-infinite distance between this tuple
+     * and tuple t1 is less than or equal to the epsilon parameter, 
+     * otherwise returns false.  The L-infinite
+     * distance is equal to 
+     * MAX[abs(x1-x2), abs(y1-y2), abs(z1-z2), abs(w1-w2)].
+     * @param t1  the tuple to be compared to this tuple
+     * @param epsilon  the threshold value  
+     * @return  true or false
+     */
+    public boolean epsilonEquals(Tuple4d t1, double epsilon)
+    {
+       double diff;
+
+       diff = x - t1.x;
+       if(Double.isNaN(diff)) return false;
+       if((diff<0?-diff:diff) > epsilon) return false;
+
+       diff = y - t1.y;
+       if(Double.isNaN(diff)) return false;
+       if((diff<0?-diff:diff) > epsilon) return false;
+
+       diff = z - t1.z;
+       if(Double.isNaN(diff)) return false;
+       if((diff<0?-diff:diff) > epsilon) return false;
+
+       diff = w - t1.w;
+       if(Double.isNaN(diff)) return false;
+       if((diff<0?-diff:diff) > epsilon) return false;
+
+       return true;
+
+    }
+
+
+    /**
+     * Returns a hash code value based on the data values in this
+     * object.  Two different Tuple4d objects with identical data values
+     * (i.e., Tuple4d.equals returns true) will return the same hash
+     * code value.  Two objects with different data members may return the
+     * same hash value, although this is not likely.
+     * @return the integer hash code value
+     */  
+    public int hashCode() {
+       long bits = 1L;
+       bits = 31L * bits + VecMathUtil.doubleToLongBits(x);
+       bits = 31L * bits + VecMathUtil.doubleToLongBits(y);
+       bits = 31L * bits + VecMathUtil.doubleToLongBits(z);
+       bits = 31L * bits + VecMathUtil.doubleToLongBits(w);
+       return (int) (bits ^ (bits >> 32));
+    }
+
+
+    /**
+     * @deprecated Use clamp(double,double,Tuple4d) instead
+     */
+    public final void clamp(float min, float max, Tuple4d t) {
+       clamp((double)min, (double)max, t);
+    }
+
+
+    /**
+     *  Clamps the tuple parameter to the range [low, high] and 
+     *  places the values into this tuple.  
+     *  @param min   the lowest value in the tuple after clamping
+     *  @param max  the highest value in the tuple after clamping 
+     *  @param t   the source tuple, which will not be modified
+     */
+    public final void clamp(double min, double max, Tuple4d t) {
+        if( t.x > max ) {
+          x = max;
+        } else if( t.x < min ){
+          x = min;
+        } else { 
+          x = t.x;
+        }
+        if( t.y > max ) {
+          y = max;
+        } else if( t.y < min ){
+          y = min;
+        } else {
+          y = t.y;
+        }
+        if( t.z > max ) {
+          z = max;
+        } else if( t.z < min ){
+          z = min;
+        } else {
+          z = t.z;
+        }
+
+        if( t.w > max ) {
+          w = max;
+        } else if( t.w < min ){
+          w = min;
+        } else {
+          w = t.w;
+        }
+
+   }
+
+
+    /**
+     * @deprecated Use clampMin(double,Tuple4d) instead
+     */
+    public final void clampMin(float min, Tuple4d t) {
+       clampMin((double)min, t);
+    }
+
+
+    /** 
+     *  Clamps the minimum value of the tuple parameter to the min 
+     *  parameter and places the values into this tuple.
+     *  @param min   the lowest value in the tuple after clamping 
+     *  @param t   the source tuple, which will not be modified
+     */   
+    public final void clampMin(double min, Tuple4d t) { 
+        if( t.x < min ) {
+          x = min;
+        } else {
+          x = t.x;
+        }
+        if( t.y < min ) {
+          y = min;
+        } else {
+          y = t.y;
+        }
+        if( t.z < min ) {
+          z = min;
+        } else {
+          z = t.z;
+        }
+        if( t.w < min ) {
+          w = min;
+        } else {
+          w = t.w;
+        }
+
+   } 
+
+
+    /**
+     * @deprecated Use clampMax(double,Tuple4d) instead
+     */
+    public final void clampMax(float max, Tuple4d t) {
+       clampMax((double)max, t);
+    }
+
+
+    /**  
+     *  Clamps the maximum value of the tuple parameter to the max 
+     *  parameter and places the values into this tuple.
+     *  @param max   the highest value in the tuple after clamping  
+     *  @param t   the source tuple, which will not be modified
+     */    
+    public final void clampMax(double max, Tuple4d t) {  
+        if( t.x > max ) {
+          x = max;
+        } else {
+          x = t.x;
+        }
+        if( t.y > max ) {
+          y = max;
+        } else {
+          y = t.y;
+        }
+        if( t.z > max ) {
+          z = max;
+        } else {
+          z = t.z;
+        }
+        if( t.w > max ) {
+          w = max;
+        } else {
+          w = t.z;
+        }
+
+   } 
+
+
+  /**  
+    *  Sets each component of the tuple parameter to its absolute 
+    *  value and places the modified values into this tuple.
+    *  @param t   the source tuple, which will not be modified
+    */    
+  public final void absolute(Tuple4d t)
+  {
+       x = Math.abs(t.x);
+       y = Math.abs(t.y);
+       z = Math.abs(t.z);
+       w = Math.abs(t.w);
+
+  } 
+
+
+
+    /**
+     * @deprecated Use clamp(double,double) instead
+     */
+    public final void clamp(float min, float max) {
+       clamp((double)min, (double)max);
+    }
+
+
+    /**
+     *  Clamps this tuple to the range [low, high].
+     *  @param min  the lowest value in this tuple after clamping
+     *  @param max  the highest value in this tuple after clamping
+     */
+    public final void clamp(double min, double max) {
+        if( x > max ) {
+          x = max;
+        } else if( x < min ){
+          x = min;
+        }
+        if( y > max ) {
+          y = max;
+        } else if( y < min ){
+          y = min;
+        }
+        if( z > max ) {
+          z = max;
+        } else if( z < min ){
+          z = min;
+        }
+        if( w > max ) {
+          w = max;
+        } else if( w < min ){
+          w = min;
+        }
+
+   }
+
+    /**
+     * @deprecated Use clampMin(double) instead
+     */
+    public final void clampMin(float min) {
+       clampMin((double)min);
+    }
+
+
+    /**
+     *  Clamps the minimum value of this tuple to the min parameter.
+     *  @param min   the lowest value in this tuple after clamping
+     */
+    public final void clampMin(double min) { 
+      if( x < min ) x=min;
+      if( y < min ) y=min;
+      if( z < min ) z=min;
+      if( w < min ) w=min;
+   } 
+    /**
+     * @deprecated Use clampMax(double) instead
+     */
+    public final void clampMax(float max) {
+       clampMax((double)max);
+    }
+
+
+    /**
+     *  Clamps the maximum value of this tuple to the max parameter.
+     *  @param max   the highest value in the tuple after clamping
+     */
+    public final void clampMax(double max) { 
+      if( x > max ) x=max;
+      if( y > max ) y=max;
+      if( z > max ) z=max;
+      if( w > max ) w=max;
+
+   }
+
+
+  /**
+    *  Sets each component of this tuple to its absolute value.
+    */
+  public final void absolute()
+  {
+     x = Math.abs(x);
+     y = Math.abs(y);
+     z = Math.abs(z);
+     w = Math.abs(w);
+
+  }
+
+
+    /**
+     * @deprecated Use interpolate(Tuple4d,Tuple4d,double) instead
+     */
+    public void interpolate(Tuple4d t1, Tuple4d t2, float alpha) {
+       interpolate(t1, t2, (double)alpha);
+    }
+
+
+    /**
+     *  Linearly interpolates between tuples t1 and t2 and places the 
+     *  result into this tuple:  this = (1-alpha)*t1 + alpha*t2.
+     *  @param t1  the first tuple
+     *  @param t2  the second tuple  
+     *  @param alpha  the alpha interpolation parameter  
+     */   
+    public void interpolate(Tuple4d t1, Tuple4d t2, double alpha) {
+       this.x = (1-alpha)*t1.x + alpha*t2.x;
+       this.y = (1-alpha)*t1.y + alpha*t2.y;
+       this.z = (1-alpha)*t1.z + alpha*t2.z;
+       this.w = (1-alpha)*t1.w + alpha*t2.w;
+    } 
+    /**
+     * @deprecated Use interpolate(Tuple4d,double) instead
+     */
+    public void interpolate(Tuple4d t1, float alpha) {
+       interpolate(t1, (double)alpha);
+    }
+
+
+    /**
+     *  Linearly interpolates between this tuple and tuple t1 and 
+     *  places the result into this tuple: this = (1-alpha)*this + alpha*t1. 
+     *  @param t1  the first tuple 
+     *  @param alpha  the alpha interpolation parameter   
+     */    
+    public void interpolate(Tuple4d t1, double alpha) {
+       this.x = (1-alpha)*this.x + alpha*t1.x;
+       this.y = (1-alpha)*this.y + alpha*t1.y;
+       this.z = (1-alpha)*this.z + alpha*t1.z;
+       this.w = (1-alpha)*this.w + alpha*t1.w;
+    }
+
+    /**
+     * Creates a new object of the same class as this object.
+     *
+     * @return a clone of this instance.
+     * @exception OutOfMemoryError if there is not enough memory.
+     * @see java.lang.Cloneable
+     * @since vecmath 1.3
+     */
+    public Object clone() {
+       // Since there are no arrays we can just use Object.clone()
+       try {
+           return super.clone();
+       } catch (CloneNotSupportedException e) {
+           // this shouldn't happen, since we are Cloneable
+           throw new InternalError();
+       }
+    }
+
+    /**
+        * Get the <i>x</i> coordinate.
+        * 
+        * @return the x coordinate.
+        * 
+        * @since vecmath 1.5
+        */
+       public final double getX() {
+               return x;
+       }
+
+
+       /**
+        * Set the <i>x</i> coordinate.
+        * 
+        * @param x  value to <i>x</i> coordinate.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setX(double x) {
+               this.x = x;
+       }
+
+
+       /**
+        * Get the <i>y</i> coordinate.
+        * 
+        * @return  the <i>y</i> coordinate.
+        * 
+        * @since vecmath 1.5
+        */
+       public final double getY() {
+               return y;
+       }
+
+
+       /**
+        * Set the <i>y</i> coordinate.
+        * 
+        * @param y value to <i>y</i> coordinate.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setY(double y) {
+               this.y = y;
+       }
+
+       /**
+        * Get the <i>z</i> coordinate.
+        * 
+        * @return the <i>z</i> coordinate.
+        * 
+        * @since vecmath 1.5
+        */
+       public final double getZ() {
+               return z;
+       }
+
+
+       /**
+        * Set the <i>z</i> coordinate.
+        * 
+        * @param z value to <i>z</i> coordinate.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setZ(double z) {
+               this.z = z;
+       }
+
+
+       /**
+        * Get the <i>w</i> coordinate.
+        * 
+        * @return the <i>w</i> coordinate.
+        * 
+        * @since vecmath 1.5
+        */
+       public final double getW() {
+               return w;
+       }
+
+
+       /**
+        * Set the <i>w</i> coordinate.
+        * 
+        * @param w value to <i>w</i> coordinate.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setW(double w) {
+               this.w = w;
+       }
+}
diff --git a/javax.vecmath/src/javax/vecmath/Tuple4f.java b/javax.vecmath/src/javax/vecmath/Tuple4f.java
new file mode 100644 (file)
index 0000000..5a7fee3
--- /dev/null
@@ -0,0 +1,798 @@
+/*
+ * $RCSfile: Tuple4f.java,v $
+ *
+ * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ * $Revision: 1.8 $
+ * $Date: 2008/02/28 20:18:51 $
+ * $State: Exp $
+ */
+
+package javax.vecmath;
+
+import java.lang.Math;
+
+/**
+ * A 4-element tuple represented by single-precision floating point x,y,z,w 
+ * coordinates.
+ *
+ */
+public abstract class Tuple4f implements java.io.Serializable, Cloneable {
+
+  static final long serialVersionUID =  7068460319248845763L;
+
+  /**
+   * The x coordinate.
+   */
+  public       float   x;
+
+  /**
+   * The y coordinate.
+   */
+  public       float   y;
+
+  /**
+   * The z coordinate.
+   */
+  public       float   z;
+
+  /**
+   * The w coordinate.
+   */
+  public       float   w;
+
+
+  /**
+   * Constructs and initializes a Tuple4f from the specified xyzw coordinates.
+   * @param x the x coordinate
+   * @param y the y coordinate
+   * @param z the z coordinate
+   * @param w the w coordinate
+   */
+  public Tuple4f(float x, float y, float z, float w)
+  {
+    this.x = x;
+    this.y = y;
+    this.z = z;
+    this.w = w;
+  }
+
+
+  /**
+   * Constructs and initializes a Tuple4f from the array of length 4. 
+   * @param t the array of length 4 containing xyzw in order
+   */
+  public Tuple4f(float[] t)
+  {
+    this.x = t[0];
+    this.y = t[1];
+    this.z = t[2];
+    this.w = t[3];
+  }
+
+
+  /**
+   * Constructs and initializes a Tuple4f from the specified Tuple4f.
+   * @param t1 the Tuple4f containing the initialization x y z w data
+   */
+  public Tuple4f(Tuple4f t1)
+  {
+    this.x = t1.x;
+    this.y = t1.y;
+    this.z = t1.z;
+    this.w = t1.w;
+  }
+
+
+  /**
+   * Constructs and initializes a Tuple4f from the specified Tuple4d.
+   * @param t1 the Tuple4d containing the initialization x y z w data
+   */
+  public Tuple4f(Tuple4d t1)
+  {
+    this.x = (float) t1.x;
+    this.y = (float) t1.y;
+    this.z = (float) t1.z;
+    this.w = (float) t1.w;
+  }
+
+
+  /**
+   * Constructs and initializes a Tuple4f to (0,0,0,0).
+   */
+  public Tuple4f()
+  {
+    this.x = 0.0f;
+    this.y = 0.0f;
+    this.z = 0.0f;
+    this.w = 0.0f;
+  }
+
+
+    /**
+     * Sets the value of this tuple to the specified xyzw coordinates.
+     * @param x the x coordinate
+     * @param y the y coordinate
+     * @param z the z coordinate
+     * @param w the w coordinate
+     */
+    public final void set(float x, float y, float z, float w)
+    {
+       this.x = x;
+       this.y = y;
+       this.z = z;
+       this.w = w;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the specified coordinates in the
+     * array of length 4.
+     * @param t the array of length 4 containing xyzw in order
+     */
+    public final void set(float[] t)
+    {
+       this.x = t[0];
+       this.y = t[1];
+       this.z = t[2];
+       this.w = t[3];
+    }
+
+
+    /**
+     * Sets the value of this tuple to the value of tuple t1.
+     * @param t1 the tuple to be copied
+     */
+    public final void set(Tuple4f t1)
+    {
+       this.x = t1.x;
+       this.y = t1.y;
+       this.z = t1.z;
+       this.w = t1.w;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the value of tuple t1.
+     * @param t1 the tuple to be copied
+     */
+    public final void set(Tuple4d t1)
+    {
+       this.x = (float) t1.x;
+       this.y = (float) t1.y;
+       this.z = (float) t1.z;
+       this.w = (float) t1.w;
+    }
+
+
+    /**
+     * Copies the values of this tuple into the array t.
+     * @param t the array 
+     */
+   public final void get(float[] t)
+   {
+      t[0] = this.x;
+      t[1] = this.y;
+      t[2] = this.z;
+      t[3] = this.w;
+   } 
+
+    /**  
+     * Copies the values of this tuple into the tuple t.
+     * @param t the target tuple
+     */ 
+   public final void get(Tuple4f t)
+   {
+      t.x = this.x;
+      t.y = this.y;
+      t.z = this.z;
+      t.w = this.w;
+   }
+
+
+  /**
+   * Sets the value of this tuple to the sum of tuples t1 and t2.
+   * @param t1 the first tuple
+   * @param t2 the second tuple
+   */
+  public final void add(Tuple4f t1, Tuple4f t2)
+  {
+    this.x = t1.x + t2.x;
+    this.y = t1.y + t2.y;
+    this.z = t1.z + t2.z;
+    this.w = t1.w + t2.w;
+  }
+
+
+  /**
+   * Sets the value of this tuple to the sum of itself and t1.
+   * @param t1 the other tuple
+   */
+  public final void add(Tuple4f t1)
+  { 
+    this.x += t1.x;
+    this.y += t1.y;
+    this.z += t1.z;
+    this.w += t1.w;
+  }
+
+
+  /**
+   * Sets the value of this tuple to the difference
+   * of tuples t1 and t2 (this = t1 - t2).
+   * @param t1 the first tuple
+   * @param t2 the second tuple
+   */
+  public final void sub(Tuple4f t1, Tuple4f t2)
+  {
+    this.x = t1.x - t2.x;
+    this.y = t1.y - t2.y;
+    this.z = t1.z - t2.z;
+    this.w = t1.w - t2.w;
+  }
+
+
+  /**
+   * Sets the value of this tuple to the difference
+   * of itself and t1 (this = this - t1).
+   * @param t1 the other tuple 
+   */
+  public final void sub(Tuple4f t1)
+  { 
+    this.x -= t1.x;
+    this.y -= t1.y;
+    this.z -= t1.z;
+    this.w -= t1.w;
+  }
+
+
+  /**
+   * Sets the value of this tuple to the negation of tuple t1.
+   * @param t1 the source tuple
+   */
+  public final void negate(Tuple4f t1)
+  {
+    this.x = -t1.x;
+    this.y = -t1.y;
+    this.z = -t1.z;
+    this.w = -t1.w;
+  }
+
+
+  /**
+   * Negates the value of this tuple in place.
+   */
+  public final void negate()
+  {
+    this.x = -this.x;
+    this.y = -this.y;
+    this.z = -this.z;
+    this.w = -this.w;
+  }
+
+
+  /**
+   * Sets the value of this tuple to the scalar multiplication
+   * of tuple t1.
+   * @param s the scalar value
+   * @param t1 the source tuple
+   */
+  public final void scale(float s, Tuple4f t1)
+  {
+    this.x = s*t1.x;
+    this.y = s*t1.y;
+    this.z = s*t1.z;
+    this.w = s*t1.w;
+  }
+
+
+  /**
+   * Sets the value of this tuple to the scalar multiplication
+   * of the scale factor with this.
+   * @param s the scalar value
+   */
+  public final void scale(float s)
+  {
+    this.x *= s;
+    this.y *= s;
+    this.z *= s;
+    this.w *= s;
+  }
+
+
+  /**
+   * Sets the value of this tuple to the scalar multiplication
+   * of tuple t1 plus tuple t2 (this = s*t1 + t2).
+   * @param s the scalar value
+   * @param t1 the tuple to be multipled
+   * @param t2 the tuple to be added
+   */
+  public final void scaleAdd(float s, Tuple4f t1, Tuple4f t2)
+  {
+    this.x = s*t1.x + t2.x;
+    this.y = s*t1.y + t2.y;
+    this.z = s*t1.z + t2.z;
+    this.w = s*t1.w + t2.w;
+  }
+
+
+    /**
+     * Sets the value of this tuple to the scalar multiplication
+     * of itself and then adds tuple t1 (this = s*this + t1).
+     * @param s the scalar value
+     * @param t1 the tuple to be added
+     */  
+    public final void scaleAdd(float s, Tuple4f t1)
+    {
+        this.x = s*this.x + t1.x;
+        this.y = s*this.y + t1.y;
+        this.z = s*this.z + t1.z;
+        this.w = s*this.w + t1.w;
+    }
+
+
+
+   /**
+     * Returns a string that contains the values of this Tuple4f.
+     * The form is (x,y,z,w).
+     * @return the String representation
+     */  
+    public String toString() {
+        return "(" + this.x + ", " + this.y + ", " + this.z + ", " + this.w + ")";
+    }
+
+   /**
+     * Returns true if all of the data members of Tuple4f t1 are
+     * equal to the corresponding data members in this Tuple4f.
+     * @param t1  the vector with which the comparison is made
+     * @return  true or false
+     */  
+    public boolean equals(Tuple4f t1)
+    {
+        try {
+        return(this.x == t1.x && this.y == t1.y && this.z == t1.z
+            && this.w == t1.w);
+        }
+        catch (NullPointerException e2) {return false;}
+    }
+
+   /**
+     * Returns true if the Object t1 is of type Tuple4f and all of the
+     * data members of t1 are equal to the corresponding data members in
+     * this Tuple4f.
+     * @param t1  the object with which the comparison is made
+     * @return  true or false
+     */
+    public boolean equals(Object t1)
+    {
+        try {
+           Tuple4f t2 = (Tuple4f) t1;
+           return(this.x == t2.x && this.y == t2.y && 
+                  this.z == t2.z && this.w == t2.w);
+        }
+        catch (NullPointerException e2) {return false;}
+        catch (ClassCastException   e1) {return false;}
+    }
+
+
+   /**
+     * Returns true if the L-infinite distance between this tuple
+     * and tuple t1 is less than or equal to the epsilon parameter, 
+     * otherwise returns false.  The L-infinite
+     * distance is equal to 
+     * MAX[abs(x1-x2), abs(y1-y2), abs(z1-z2), abs(w1-w2)].
+     * @param t1  the tuple to be compared to this tuple
+     * @param epsilon  the threshold value  
+     * @return  true or false
+     */
+    public boolean epsilonEquals(Tuple4f t1, float epsilon)
+    {
+       float diff;
+
+       diff = x - t1.x;
+       if(Float.isNaN(diff)) return false;
+       if((diff<0?-diff:diff) > epsilon) return false;
+
+       diff = y - t1.y;
+       if(Float.isNaN(diff)) return false;
+       if((diff<0?-diff:diff) > epsilon) return false;
+
+       diff = z - t1.z;
+       if(Float.isNaN(diff)) return false;
+       if((diff<0?-diff:diff) > epsilon) return false;
+
+       diff = w - t1.w;
+       if(Float.isNaN(diff)) return false;
+       if((diff<0?-diff:diff) > epsilon) return false;
+
+       return true;
+    }
+
+
+    /**
+     * Returns a hash code value based on the data values in this
+     * object.  Two different Tuple4f objects with identical data values
+     * (i.e., Tuple4f.equals returns true) will return the same hash
+     * code value.  Two objects with different data members may return the
+     * same hash value, although this is not likely.
+     * @return the integer hash code value
+     */  
+    public int hashCode() {
+       long bits = 1L;
+       bits = 31L * bits + (long)VecMathUtil.floatToIntBits(x);
+       bits = 31L * bits + (long)VecMathUtil.floatToIntBits(y);
+       bits = 31L * bits + (long)VecMathUtil.floatToIntBits(z);
+       bits = 31L * bits + (long)VecMathUtil.floatToIntBits(w);
+       return (int) (bits ^ (bits >> 32));
+    }
+
+
+  /**
+    *  Clamps the tuple parameter to the range [low, high] and 
+    *  places the values into this tuple.  
+    *  @param min   the lowest value in the tuple after clamping
+    *  @param max  the highest value in the tuple after clamping 
+    *  @param t   the source tuple, which will not be modified
+    */
+   public final void clamp(float min, float max, Tuple4f t)
+   {
+        if( t.x > max ) {
+          x = max;
+        } else if( t.x < min ){
+          x = min;
+        } else { 
+          x = t.x;
+        }
+        if( t.y > max ) {
+          y = max;
+        } else if( t.y < min ){
+          y = min;
+        } else {
+          y = t.y;
+        }
+        if( t.z > max ) {
+          z = max;
+        } else if( t.z < min ){
+          z = min;
+        } else {
+          z = t.z;
+        }
+
+        if( t.w > max ) {
+          w = max;
+        } else if( t.w < min ){
+          w = min;
+        } else {
+          w = t.w;
+        }
+
+   }
+
+
+  /** 
+    *  Clamps the minimum value of the tuple parameter to the min 
+    *  parameter and places the values into this tuple.
+    *  @param min   the lowest value in the tuple after clamping 
+    *  @param t   the source tuple, which will not be modified
+    */   
+   public final void clampMin(float min, Tuple4f t) 
+   { 
+        if( t.x < min ) {
+          x = min;
+        } else {
+          x = t.x;
+        }
+        if( t.y < min ) {
+          y = min;
+        } else {
+          y = t.y;
+        }
+        if( t.z < min ) {
+          z = min;
+        } else {
+          z = t.z;
+        }
+        if( t.w < min ) {
+          w = min;
+        } else {
+          w = t.w;
+        }
+
+   } 
+
+
+  /**  
+    *  Clamps the maximum value of the tuple parameter to the max 
+    *  parameter and places the values into this tuple.
+    *  @param max   the highest value in the tuple after clamping  
+    *  @param t   the source tuple, which will not be modified
+    */    
+   public final void clampMax(float max, Tuple4f t)  
+   {  
+        if( t.x > max ) {
+          x = max;
+        } else {
+          x = t.x;
+        }
+        if( t.y > max ) {
+          y = max;
+        } else {
+          y = t.y;
+        }
+        if( t.z > max ) {
+          z = max;
+        } else {
+          z = t.z;
+        }
+        if( t.w > max ) {
+          w = max;
+        } else {
+          w = t.z;
+        }
+
+   } 
+
+
+  /**  
+    *  Sets each component of the tuple parameter to its absolute 
+    *  value and places the modified values into this tuple.
+    *  @param t   the source tuple, which will not be modified
+    */    
+  public final void absolute(Tuple4f t)
+  {
+       x = Math.abs(t.x);
+       y = Math.abs(t.y);
+       z = Math.abs(t.z);
+       w = Math.abs(t.w);
+  } 
+
+
+  /**
+    *  Clamps this tuple to the range [low, high].
+    *  @param min  the lowest value in this tuple after clamping
+    *  @param max  the highest value in this tuple after clamping
+    */
+   public final void clamp(float min, float max)
+   {
+       if( x > max ) {
+          x = max;
+        } else if( x < min ){
+          x = min;
+        }
+        if( y > max ) {
+          y = max;
+        } else if( y < min ){
+          y = min;
+        }
+        if( z > max ) {
+          z = max;
+        } else if( z < min ){
+          z = min;
+        }
+        if( w > max ) {
+          w = max;
+        } else if( w < min ){
+          w = min;
+        }
+
+   }
+
+  /**
+    *  Clamps the minimum value of this tuple to the min parameter.
+    *  @param min   the lowest value in this tuple after clamping
+    */
+   public final void clampMin(float min)
+   { 
+      if( x < min ) x=min;
+      if( y < min ) y=min;
+      if( z < min ) z=min;
+      if( w < min ) w=min;
+
+   } 
+  /**
+    *  Clamps the maximum value of this tuple to the max parameter.
+    *  @param max   the highest value in the tuple after clamping
+    */
+   public final void clampMax(float max)
+   { 
+      if( x > max ) x=max;
+      if( y > max ) y=max;
+      if( z > max ) z=max;
+      if( w > max ) w=max;
+
+   }
+
+
+  /**
+    *  Sets each component of this tuple to its absolute value.
+    */
+  public final void absolute()
+  {
+     x = Math.abs(x);
+     y = Math.abs(y);
+     z = Math.abs(z);
+     w = Math.abs(w);
+  }
+
+
+  /**  
+    *  Linearly interpolates between tuples t1 and t2 and places the 
+    *  result into this tuple:  this = (1-alpha)*t1 + alpha*t2.
+    *  @param t1  the first tuple
+    *  @param t2  the second tuple  
+    *  @param alpha  the alpha interpolation parameter  
+    */   
+  public void interpolate(Tuple4f t1, Tuple4f t2, float alpha) 
+  { 
+           this.x = (1-alpha)*t1.x + alpha*t2.x;
+           this.y = (1-alpha)*t1.y + alpha*t2.y;
+           this.z = (1-alpha)*t1.z + alpha*t2.z;
+           this.w = (1-alpha)*t1.w + alpha*t2.w;
+
+  } 
+  /**   
+    *  Linearly interpolates between this tuple and tuple t1 and 
+    *  places the result into this tuple:  this = (1-alpha)*this + alpha*t1. 
+    *  @param t1  the first tuple 
+    *  @param alpha  the alpha interpolation parameter   
+    */    
+  public void interpolate(Tuple4f t1, float alpha)  
+  {  
+     this.x = (1-alpha)*this.x + alpha*t1.x;
+     this.y = (1-alpha)*this.y + alpha*t1.y;
+     this.z = (1-alpha)*this.z + alpha*t1.z;
+     this.w = (1-alpha)*this.w + alpha*t1.w;
+
+  }  
+    /**
+     * Creates a new object of the same class as this object.
+     *
+     * @return a clone of this instance.
+     * @exception OutOfMemoryError if there is not enough memory.
+     * @see java.lang.Cloneable
+     * @since vecmath 1.3
+     */
+    public Object clone() {
+       // Since there are no arrays we can just use Object.clone()
+       try {
+           return super.clone();
+       } catch (CloneNotSupportedException e) {
+           // this shouldn't happen, since we are Cloneable
+           throw new InternalError();
+       }
+    }
+
+    /**
+        * Get the <i>x</i> coordinate.
+        * 
+        * @return the <i>x</i> coordinate.
+        * 
+        * @since vecmath 1.5
+        */
+       public final float getX() {
+               return x;
+       }
+
+
+       /**
+        * Set the <i>x</i> coordinate.
+        * 
+        * @param x  value to <i>x</i> coordinate.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setX(float x) {
+               this.x = x;
+       }
+
+
+       /**
+        * Get the <i>y</i> coordinate.
+        * 
+        * @return the <i>y</i> coordinate.
+        * 
+        * @since vecmath 1.5
+        */
+       public final float getY() {
+               return y;
+       }
+
+
+       /**
+        * Set the <i>y</i> coordinate.
+        * 
+        * @param y value to <i>y</i> coordinate.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setY(float y) {
+               this.y = y;
+       }
+
+       /**
+        * Get the <i>z</i> coordinate.
+        * 
+        * @return the <i>z</i> coordinate.
+        * 
+        * @since vecmath 1.5
+        */
+       public final float getZ() {
+               return z;
+       }
+
+
+       /**
+        * Set the <i>z</i> coordinate.
+        * 
+        * @param z value to <i>z</i> coordinate.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setZ(float z) {
+               this.z = z;
+       }
+
+
+       /**
+        * Get the <i>w</i> coordinate.
+        * 
+        * @return the <i>w</i> coordinate.
+        * 
+        * @since vecmath 1.5
+        */
+       public final float getW() {
+               return w;
+       }
+
+
+       /**
+        * Set the <i>w</i> coordinate.
+        * 
+        * @param w value to <i>w</i> coordinate.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setW(float w) {
+               this.w = w;
+       }
+}
diff --git a/javax.vecmath/src/javax/vecmath/Tuple4i.java b/javax.vecmath/src/javax/vecmath/Tuple4i.java
new file mode 100644 (file)
index 0000000..0a0f947
--- /dev/null
@@ -0,0 +1,680 @@
+/*
+ * $RCSfile: Tuple4i.java,v $
+ *
+ * Copyright 1999-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ * $Revision: 1.7 $
+ * $Date: 2008/02/28 20:18:51 $
+ * $State: Exp $
+ */
+
+package javax.vecmath;
+
+import java.lang.Math;
+
+/**
+ * A 4-element tuple represented by signed integer x,y,z,w
+ * coordinates.
+ *
+ * @since vecmath 1.2
+ */
+public abstract class Tuple4i implements java.io.Serializable, Cloneable {
+
+    static final long serialVersionUID = 8064614250942616720L;
+
+    /**
+     * The x coordinate.
+     */
+    public int x;
+
+    /**
+     * The y coordinate.
+     */
+    public int y;
+
+    /**
+     * The z coordinate.
+     */
+    public int z;
+
+    /**
+     * The w coordinate.
+     */
+    public int w;
+
+
+    /**
+     * Constructs and initializes a Tuple4i from the specified
+     * x, y, z, and w coordinates.
+     * @param x the x coordinate
+     * @param y the y coordinate
+     * @param z the z coordinate
+     * @param w the w coordinate
+     */
+    public Tuple4i(int x, int y, int z, int w) {
+       this.x = x;
+       this.y = y;
+       this.z = z;
+       this.w = w;
+    }
+
+
+    /**
+     * Constructs and initializes a Tuple4i from the array of length 4.
+     * @param t the array of length 4 containing x, y, z, and w in order.
+     */
+    public Tuple4i(int[] t) {
+       this.x = t[0];
+       this.y = t[1];
+       this.z = t[2];
+       this.w = t[3];
+    }
+
+
+    /**
+     * Constructs and initializes a Tuple4i from the specified Tuple4i.
+     * @param t1 the Tuple4i containing the initialization x, y, z,
+     * and w data.
+     */
+    public Tuple4i(Tuple4i t1) {
+       this.x = t1.x;
+       this.y = t1.y;
+       this.z = t1.z;
+       this.w = t1.w;
+    }
+
+
+    /**
+     * Constructs and initializes a Tuple4i to (0,0,0,0).
+     */
+    public Tuple4i() {
+       this.x = 0;
+       this.y = 0;
+       this.z = 0;
+       this.w = 0;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the specified x, y, z, and w
+     * coordinates.
+     * @param x the x coordinate
+     * @param y the y coordinate
+     * @param z the z coordinate
+     * @param w the w coordinate
+     */
+    public final void set(int x, int y, int z, int w) {
+       this.x = x;
+       this.y = y;
+       this.z = z;
+       this.w = w;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the specified coordinates in the
+     * array of length 4.
+     * @param t the array of length 4 containing x, y, z, and w in order.
+     */
+    public final void set(int[] t) {
+       this.x = t[0];
+       this.y = t[1];
+       this.z = t[2];
+       this.w = t[3];
+    }
+
+
+    /**
+     * Sets the value of this tuple to the value of tuple t1.
+     * @param t1 the tuple to be copied
+     */
+    public final void set(Tuple4i t1) {
+       this.x = t1.x;
+       this.y = t1.y;
+       this.z = t1.z;
+       this.w = t1.w;
+    }
+
+
+    /**
+     * Copies the values of this tuple into the array t.
+     * @param t the array
+     */
+    public final void get(int[] t) {
+       t[0] = this.x;
+       t[1] = this.y;
+       t[2] = this.z;
+       t[3] = this.w;
+    }
+
+
+    /**
+     * Copies the values of this tuple into the tuple t.
+     * @param t the target tuple
+     */
+    public final void get(Tuple4i t) {
+       t.x = this.x;
+       t.y = this.y;
+       t.z = this.z;
+       t.w = this.w;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the sum of tuples t1 and t2.
+     * @param t1 the first tuple
+     * @param t2 the second tuple
+     */
+    public final void add(Tuple4i t1, Tuple4i t2) {
+       this.x = t1.x + t2.x;
+       this.y = t1.y + t2.y;
+       this.z = t1.z + t2.z;
+       this.w = t1.w + t2.w;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the sum of itself and t1.
+     * @param t1 the other tuple
+     */
+    public final void add(Tuple4i t1) {
+       this.x += t1.x;
+       this.y += t1.y;
+       this.z += t1.z;
+       this.w += t1.w;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the difference
+     * of tuples t1 and t2 (this = t1 - t2).
+     * @param t1 the first tuple
+     * @param t2 the second tuple
+     */
+    public final void sub(Tuple4i t1, Tuple4i t2) {
+       this.x = t1.x - t2.x;
+       this.y = t1.y - t2.y;
+       this.z = t1.z - t2.z;
+       this.w = t1.w - t2.w;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the difference
+     * of itself and t1 (this = this - t1).
+     * @param t1 the other tuple
+     */
+    public final void sub(Tuple4i t1) {
+       this.x -= t1.x;
+       this.y -= t1.y;
+       this.z -= t1.z;
+       this.w -= t1.w;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the negation of tuple t1.
+     * @param t1 the source tuple
+     */
+    public final void negate(Tuple4i t1) {
+       this.x = -t1.x;
+       this.y = -t1.y;
+       this.z = -t1.z;
+       this.w = -t1.w;
+    }
+
+
+    /**
+     * Negates the value of this tuple in place.
+     */
+    public final void negate() {
+       this.x = -this.x;
+       this.y = -this.y;
+       this.z = -this.z;
+       this.w = -this.w;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the scalar multiplication
+     * of tuple t1.
+     * @param s the scalar value
+     * @param t1 the source tuple
+     */
+    public final void scale(int s, Tuple4i t1) {
+       this.x = s*t1.x;
+       this.y = s*t1.y;
+       this.z = s*t1.z;
+       this.w = s*t1.w;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the scalar multiplication
+     * of the scale factor with this.
+     * @param s the scalar value
+     */
+    public final void scale(int s) {
+       this.x *= s;
+       this.y *= s;
+       this.z *= s;
+       this.w *= s;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the scalar multiplication
+     * of tuple t1 plus tuple t2 (this = s*t1 + t2).
+     * @param s the scalar value
+     * @param t1 the tuple to be multipled
+     * @param t2 the tuple to be added
+     */
+    public final void scaleAdd(int s, Tuple4i t1, Tuple4i t2) {
+       this.x = s*t1.x + t2.x;
+       this.y = s*t1.y + t2.y;
+       this.z = s*t1.z + t2.z;
+       this.w = s*t1.w + t2.w;
+    }
+
+
+    /**
+     * Sets the value of this tuple to the scalar multiplication
+     * of itself and then adds tuple t1 (this = s*this + t1).
+     * @param s the scalar value
+     * @param t1 the tuple to be added
+     */
+    public final void scaleAdd(int s, Tuple4i t1) {
+        this.x = s*this.x + t1.x;
+        this.y = s*this.y + t1.y;
+        this.z = s*this.z + t1.z;
+        this.w = s*this.w + t1.w;
+    }
+
+
+    /**
+     * Returns a string that contains the values of this Tuple4i.
+     * The form is (x,y,z,w).
+     * @return the String representation
+     */
+    public String toString() {
+        return "(" + this.x + ", " + this.y + ", " + this.z + ", " + this.w + ")";
+    }
+
+
+    /**
+     * Returns true if the Object t1 is of type Tuple4i and all of the
+     * data members of t1 are equal to the corresponding data members in
+     * this Tuple4i.
+     * @param t1  the object with which the comparison is made
+     * @return  true or false
+     */
+    public boolean equals(Object t1) {
+        try {
+           Tuple4i t2 = (Tuple4i) t1;
+           return(this.x == t2.x && this.y == t2.y &&
+                  this.z == t2.z && this.w == t2.w);
+        }
+        catch (NullPointerException e2) {
+           return false;
+       }
+        catch (ClassCastException e1) {
+           return false;
+       }
+    }
+
+
+    /**
+     * Returns a hash code value based on the data values in this
+     * object.  Two different Tuple4i objects with identical data values
+     * (i.e., Tuple4i.equals returns true) will return the same hash
+     * code value.  Two objects with different data members may return the
+     * same hash value, although this is not likely.
+     * @return the integer hash code value
+     */
+    public int hashCode() {
+       long bits = 1L;
+       bits = 31L * bits + (long)x;
+       bits = 31L * bits + (long)y;
+       bits = 31L * bits + (long)z;
+       bits = 31L * bits + (long)w;
+       return (int) (bits ^ (bits >> 32));
+    }
+
+
+    /**
+     *  Clamps the tuple parameter to the range [low, high] and
+     *  places the values into this tuple.
+     *  @param min   the lowest value in the tuple after clamping
+     *  @param max  the highest value in the tuple after clamping
+     *  @param t   the source tuple, which will not be modified
+     */
+    public final void clamp(int min, int max, Tuple4i t) {
+        if( t.x > max ) {
+           x = max;
+        } else if( t.x < min ) {
+           x = min;
+        } else {
+           x = t.x;
+        }
+
+        if( t.y > max ) {
+           y = max;
+        } else if( t.y < min ) {
+           y = min;
+        } else {
+           y = t.y;
+        }
+
+        if( t.z > max ) {
+           z = max;
+        } else if( t.z < min ) {
+           z = min;
+        } else {
+           z = t.z;
+        }
+
+        if( t.w > max ) {
+           w = max;
+        } else if( t.w < min ) {
+           w = min;
+        } else {
+           w = t.w;
+        }
+    }
+
+
+    /**
+     *  Clamps the minimum value of the tuple parameter to the min
+     *  parameter and places the values into this tuple.
+     *  @param min   the lowest value in the tuple after clamping
+     *  @param t   the source tuple, which will not be modified
+     */
+    public final void clampMin(int min, Tuple4i t) {
+        if( t.x < min ) {
+           x = min;
+        } else {
+           x = t.x;
+        }
+
+        if( t.y < min ) {
+           y = min;
+        } else {
+           y = t.y;
+        }
+
+        if( t.z < min ) {
+           z = min;
+        } else {
+           z = t.z;
+        }
+
+        if( t.w < min ) {
+           w = min;
+        } else {
+           w = t.w;
+        }
+
+
+    }
+
+
+    /**
+     *  Clamps the maximum value of the tuple parameter to the max
+     *  parameter and places the values into this tuple.
+     *  @param max   the highest value in the tuple after clamping
+     *  @param t   the source tuple, which will not be modified
+     */
+    public final void clampMax(int max, Tuple4i t) {
+        if( t.x > max ) {
+           x = max;
+        } else {
+           x = t.x;
+        }
+
+        if( t.y > max ) {
+           y = max;
+        } else {
+           y = t.y;
+        }
+
+        if( t.z > max ) {
+           z = max;
+        } else {
+           z = t.z;
+        }
+
+        if( t.w > max ) {
+           w = max;
+        } else {
+           w = t.z;
+        }
+    }
+
+
+    /**
+     *  Sets each component of the tuple parameter to its absolute
+     *  value and places the modified values into this tuple.
+     *  @param t   the source tuple, which will not be modified
+     */
+    public final void absolute(Tuple4i t) {
+       x = Math.abs(t.x);
+       y = Math.abs(t.y);
+       z = Math.abs(t.z);
+       w = Math.abs(t.w);
+    }
+
+
+    /**
+     *  Clamps this tuple to the range [low, high].
+     *  @param min  the lowest value in this tuple after clamping
+     *  @param max  the highest value in this tuple after clamping
+     */
+    public final void clamp(int min, int max) {
+       if( x > max ) {
+           x = max;
+        } else if( x < min ) {
+           x = min;
+        }
+
+        if( y > max ) {
+           y = max;
+        } else if( y < min ) {
+           y = min;
+        }
+
+        if( z > max ) {
+           z = max;
+        } else if( z < min ) {
+           z = min;
+        }
+
+        if( w > max ) {
+           w = max;
+        } else if( w < min ) {
+           w = min;
+        }
+    }
+
+
+    /**
+     *  Clamps the minimum value of this tuple to the min parameter.
+     *  @param min   the lowest value in this tuple after clamping
+     */
+    public final void clampMin(int min) {
+       if (x < min)
+           x=min;
+
+       if (y < min)
+           y = min;
+
+       if (z < min)
+           z = min;
+
+       if (w < min)
+           w = min;
+    }
+
+
+    /**
+     *  Clamps the maximum value of this tuple to the max parameter.
+     *  @param max   the highest value in the tuple after clamping
+     */
+    public final void clampMax(int max) {
+       if (x > max)
+           x = max;
+
+       if (y > max)
+           y = max;
+
+       if (z > max)
+           z = max;
+
+       if (w > max)
+           w = max;
+    }
+
+
+    /**
+     *  Sets each component of this tuple to its absolute value.
+     */
+    public final void absolute() {
+       x = Math.abs(x);
+       y = Math.abs(y);
+       z = Math.abs(z);
+       w = Math.abs(w);
+    }
+
+    /**
+     * Creates a new object of the same class as this object.
+     *
+     * @return a clone of this instance.
+     * @exception OutOfMemoryError if there is not enough memory.
+     * @see java.lang.Cloneable
+     * @since vecmath 1.3
+     */
+    public Object clone() {
+       // Since there are no arrays we can just use Object.clone()
+       try {
+           return super.clone();
+       } catch (CloneNotSupportedException e) {
+           // this shouldn't happen, since we are Cloneable
+           throw new InternalError();
+       }
+    }
+
+
+
+    /**
+        * Get the <i>x</i> coordinate.
+        * 
+        * @return the <i>x</i> coordinate.
+        * 
+        * @since vecmath 1.5
+        */
+       public final int getX() {
+               return x;
+       }
+
+
+       /**
+        * Set the <i>x</i> coordinate.
+        * 
+        * @param x  value to <i>x</i> coordinate.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setX(int x) {
+               this.x = x;
+       }
+
+
+       /**
+        * Get the <i>y</i> coordinate.
+        * 
+        * @return  the <i>y</i> coordinate.
+        * 
+        * @since vecmath 1.5
+        */
+       public final int getY() {
+               return y;
+       }
+
+
+       /**
+        * Set the <i>y</i> coordinate.
+        * 
+        * @param y value to <i>y</i> coordinate.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setY(int y) {
+               this.y = y;
+       }
+
+       /**
+        * Get the <i>z</i> coordinate.
+        * 
+        * @return the <i>z</i> coordinate.
+        * 
+        * @since vecmath 1.5
+        */
+       public final int getZ() {
+               return z;
+       }
+
+
+       /**
+        * Set the <i>z</i> coordinate.
+        * 
+        * @param z value to <i>z</i> coordinate.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setZ(int z) {
+               this.z = z;
+       }
+
+
+       /**
+        * Get the <i>w</i> coordinate.
+        * @return the  <i>w</i> coordinate.
+        * @since vecmath 1.5
+        */
+       public final int getW() {
+               return w;
+       }
+
+
+       /**
+        * Set the <i>w</i> coordinate.
+        * 
+        * @param w value to <i>w</i> coordinate.
+        * 
+        * @since vecmath 1.5
+        */
+       public final void setW(int w) {
+               this.w = w;
+       }
+
+}
diff --git a/javax.vecmath/src/javax/vecmath/VecMathI18N.java b/javax.vecmath/src/javax/vecmath/VecMathI18N.java
new file mode 100644 (file)
index 0000000..2a9f199
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * $RCSfile: VecMathI18N.java,v $
+ *
+ * Copyright 1998-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ * $Revision: 1.5 $
+ * $Date: 2008/02/28 20:18:51 $
+ * $State: Exp $
+ */
+
+package javax.vecmath;
+
+import java.io.*;
+import java.util.*;
+
+
+class VecMathI18N {
+    static String getString(String key) {
+       String s;
+       try {
+           s = (String) ResourceBundle.getBundle("javax.vecmath.ExceptionStrings").getString(key);
+       }
+       catch (MissingResourceException e) {
+           System.err.println("VecMathI18N: Error looking up: " + key);
+           s = key;
+       }
+       return s;
+    }
+}
diff --git a/javax.vecmath/src/javax/vecmath/VecMathUtil.java b/javax.vecmath/src/javax/vecmath/VecMathUtil.java
new file mode 100644 (file)
index 0000000..1afcfe6
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * $RCSfile: VecMathUtil.java,v $
+ *
+ * Copyright 2004-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ * $Revision: 1.5 $
+ * $Date: 2008/02/28 20:18:51 $
+ * $State: Exp $
+ */
+
+package javax.vecmath;
+
+/**
+ * Utility vecmath class used when computing the hash code for vecmath
+ * objects containing float or double values. This fixes Issue 36.
+ */
+class VecMathUtil {
+    /**
+     * Returns the representation of the specified floating-point
+     * value according to the IEEE 754 floating-point "single format"
+     * bit layout, after first mapping -0.0 to 0.0. This method is
+     * identical to Float.floatToIntBits(float) except that an integer
+     * value of 0 is returned for a floating-point value of
+     * -0.0f. This is done for the purpose of computing a hash code
+     * that satisfies the contract of hashCode() and equals(). The
+     * equals() method in each vecmath class does a pair-wise "=="
+     * test on each floating-point field in the class (e.g., x, y, and
+     * z for a Tuple3f). Since 0.0f&nbsp;==&nbsp;-0.0f returns true,
+     * we must also return the same hash code for two objects, one of
+     * which has a field with a value of -0.0f and the other of which
+     * has a cooresponding field with a value of 0.0f.
+     *
+     * @param f an input floating-point number
+     * @return the integer bits representing that floating-point
+     * number, after first mapping -0.0f to 0.0f
+     */
+    static int floatToIntBits(float f) {
+       // Check for +0 or -0
+       if (f == 0.0f) {
+           return 0;
+       }
+       else {
+           return Float.floatToIntBits(f);
+       }
+    }
+
+    /**
+     * Returns the representation of the specified floating-point
+     * value according to the IEEE 754 floating-point "double format"
+     * bit layout, after first mapping -0.0 to 0.0. This method is
+     * identical to Double.doubleToLongBits(double) except that an
+     * integer value of 0L is returned for a floating-point value of
+     * -0.0. This is done for the purpose of computing a hash code
+     * that satisfies the contract of hashCode() and equals(). The
+     * equals() method in each vecmath class does a pair-wise "=="
+     * test on each floating-point field in the class (e.g., x, y, and
+     * z for a Tuple3d). Since 0.0&nbsp;==&nbsp;-0.0 returns true, we
+     * must also return the same hash code for two objects, one of
+     * which has a field with a value of -0.0 and the other of which
+     * has a cooresponding field with a value of 0.0.
+     *
+     * @param d an input double precision floating-point number
+     * @return the integer bits representing that floating-point
+     * number, after first mapping -0.0f to 0.0f
+     */
+    static long doubleToLongBits(double d) {
+       // Check for +0 or -0
+       if (d == 0.0) {
+           return 0L;
+       }
+       else {
+           return Double.doubleToLongBits(d);
+       }
+    }
+
+
+    /**
+     * Do not construct an instance of this class.
+     */
+    private VecMathUtil() {
+    }
+}
diff --git a/javax.vecmath/src/javax/vecmath/Vector2d.java b/javax.vecmath/src/javax/vecmath/Vector2d.java
new file mode 100644 (file)
index 0000000..be196c8
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ * $RCSfile: Vector2d.java,v $
+ *
+ * Copyright 1998-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ * $Revision: 1.5 $
+ * $Date: 2008/02/28 20:18:51 $
+ * $State: Exp $
+ */
+
+package javax.vecmath;
+
+import java.lang.Math;
+
+/**
+ * A 2-element vector that is represented by double-precision floating 
+ * point x,y coordinates.
+ *
+ */
+public class Vector2d extends Tuple2d implements java.io.Serializable {
+
+    // Combatible with 1.1
+    static final long serialVersionUID = 8572646365302599857L;
+
+    /**
+     * Constructs and initializes a Vector2d from the specified xy coordinates.
+     * @param x the x coordinate
+     * @param y the y coordinate
+     */
+    public Vector2d(double x, double y)
+    {
+      super(x,y);
+    }
+
+
+    /**
+     * Constructs and initializes a Vector2d from the specified array.
+     * @param v the array of length 2 containing xy in order
+     */
+    public Vector2d(double[] v)
+    {
+      super(v);
+    }
+
+
+    /**
+     * Constructs and initializes a Vector2d from the specified Vector2d.
+     * @param v1 the Vector2d containing the initialization x y data
+     */
+    public Vector2d(Vector2d v1)
+    {
+       super(v1);
+    }
+
+
+    /**
+     * Constructs and initializes a Vector2d from the specified Vector2f.
+     * @param v1 the Vector2f containing the initialization x y data
+     */
+    public Vector2d(Vector2f v1)
+    {
+       super(v1);
+    }
+
+
+    /**
+     * Constructs and initializes a Vector2d from the specified Tuple2d.
+     * @param t1 the Tuple2d containing the initialization x y data
+     */  
+    public Vector2d(Tuple2d t1)
+    {
+       super(t1);
+    }
+
+
+    /**
+     * Constructs and initializes a Vector2d from the specified Tuple2f.
+     * @param t1 the Tuple2f containing the initialization x y data
+     */  
+    public Vector2d(Tuple2f t1)
+    {
+       super(t1);
+    }
+
+
+    /**
+     * Constructs and initializes a Vector2d to (0,0).
+     */
+    public Vector2d()
+    {
+        super();
+    }
+
+
+  /**
+   * Computes the dot product of the this vector and vector v1.
+   * @param v1 the other vector
+   */
+  public final double dot(Vector2d v1)
+    {
+      return (this.x*v1.x + this.y*v1.y);
+    }
+
+
+    /**  
+     * Returns the length of this vector.
+     * @return the length of this vector
+     */  
+    public final double length()
+    {
+        return (double) Math.sqrt(this.x*this.x + this.y*this.y);
+    }
+
+    /**  
+     * Returns the squared length of this vector.
+     * @return the squared length of this vector
+     */  
+    public final double lengthSquared()
+    {
+        return (this.x*this.x + this.y*this.y);
+    }
+
+    /**
+     * Sets the value of this vector to the normalization of vector v1.
+     * @param v1 the un-normalized vector
+     */  
+    public final void normalize(Vector2d v1)
+    {
+        double norm;
+
+        norm = (double) (1.0/Math.sqrt(v1.x*v1.x + v1.y*v1.y));
+        this.x = v1.x*norm;
+        this.y = v1.y*norm;
+    }
+
+    /**
+     * Normalizes this vector in place.
+     */  
+    public final void normalize()
+    {
+        double norm;
+
+        norm = (double)
+               (1.0/Math.sqrt(this.x*this.x + this.y*this.y));
+        this.x *= norm;
+        this.y *= norm;
+    }
+
+
+  /**
+    *   Returns the angle in radians between this vector and the vector
+    *   parameter; the return value is constrained to the range [0,PI].
+    *   @param v1    the other vector
+    *   @return   the angle in radians in the range [0,PI]
+    */
+   public final double angle(Vector2d v1)
+   {
+      double vDot = this.dot(v1) / ( this.length()*v1.length() );
+      if( vDot < -1.0) vDot = -1.0;
+      if( vDot >  1.0) vDot =  1.0;
+      return((double) (Math.acos( vDot )));
+
+   }
+
+
+}
diff --git a/javax.vecmath/src/javax/vecmath/Vector2f.java b/javax.vecmath/src/javax/vecmath/Vector2f.java
new file mode 100644 (file)
index 0000000..ac5ae45
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ * $RCSfile: Vector2f.java,v $
+ *
+ * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ * $Revision: 1.5 $
+ * $Date: 2008/02/28 20:18:51 $
+ * $State: Exp $
+ */
+
+package javax.vecmath;
+
+import java.lang.Math;
+
+/**
+ * A 2-element vector that is represented by single-precision floating 
+ * point x,y coordinates.
+ *
+ */
+public class Vector2f extends Tuple2f implements java.io.Serializable {
+
+    // Combatible with 1.1
+    static final long serialVersionUID = -2168194326883512320L;
+
+    /**
+     * Constructs and initializes a Vector2f from the specified xy coordinates.
+     * @param x the x coordinate
+     * @param y the y coordinate
+     */
+    public Vector2f(float x, float y)
+    {
+      super(x,y);
+    }
+
+
+    /**
+     * Constructs and initializes a Vector2f from the specified array.
+     * @param v the array of length 2 containing xy in order
+     */
+    public Vector2f(float[] v)
+    {
+      super(v);
+    }
+
+
+    /**
+     * Constructs and initializes a Vector2f from the specified Vector2f.
+     * @param v1 the Vector2f containing the initialization x y data
+     */
+    public Vector2f(Vector2f v1)
+    {
+       super(v1);
+    }
+
+
+    /**
+     * Constructs and initializes a Vector2f from the specified Vector2d.
+     * @param v1 the Vector2d containing the initialization x y data
+     */
+    public Vector2f(Vector2d v1)
+    {
+       super(v1);
+    }
+
+
+    /**
+     * Constructs and initializes a Vector2f from the specified Tuple2f.
+     * @param t1 the Tuple2f containing the initialization x y data
+     */  
+    public Vector2f(Tuple2f t1)
+    {
+       super(t1);
+    }
+
+
+    /**
+     * Constructs and initializes a Vector2f from the specified Tuple2d.
+     * @param t1 the Tuple2d containing the initialization x y data
+     */  
+    public Vector2f(Tuple2d t1)
+    {
+       super(t1);
+    }
+
+
+
+    /**
+     * Constructs and initializes a Vector2f to (0,0).
+     */
+    public Vector2f()
+    {
+        super();
+    }
+
+
+  /**
+   * Computes the dot product of the this vector and vector v1.
+   * @param v1 the other vector
+   */
+  public final float dot(Vector2f v1)
+    {
+      return (this.x*v1.x + this.y*v1.y);
+    }
+
+
+    /**  
+     * Returns the length of this vector.
+     * @return the length of this vector
+     */  
+    public final float length()
+    {
+        return (float) Math.sqrt(this.x*this.x + this.y*this.y);
+    }
+
+    /**  
+     * Returns the squared length of this vector.
+     * @return the squared length of this vector
+     */  
+    public final float lengthSquared()
+    {
+        return (this.x*this.x + this.y*this.y);
+    }
+
+    /**
+     * Sets the value of this vector to the normalization of vector v1.
+     * @param v1 the un-normalized vector
+     */  
+    public final void normalize(Vector2f v1)
+    {
+        float norm;
+
+        norm = (float) (1.0/Math.sqrt(v1.x*v1.x + v1.y*v1.y));
+        this.x = v1.x*norm;
+        this.y = v1.y*norm;
+    }
+
+    /**
+     * Normalizes this vector in place.
+     */  
+    public final void normalize()
+    {
+        float norm;
+
+        norm = (float)
+               (1.0/Math.sqrt(this.x*this.x + this.y*this.y));
+        this.x *= norm;
+        this.y *= norm;
+    }
+
+
+  /**
+    *   Returns the angle in radians between this vector and the vector
+    *   parameter; the return value is constrained to the range [0,PI].
+    *   @param v1    the other vector
+    *   @return   the angle in radians in the range [0,PI]
+    */
+   public final float angle(Vector2f v1)
+   {
+      double vDot = this.dot(v1) / ( this.length()*v1.length() );
+      if( vDot < -1.0) vDot = -1.0;
+      if( vDot >  1.0) vDot =  1.0;
+      return((float) (Math.acos( vDot )));
+   }
+
+
+}
diff --git a/javax.vecmath/src/javax/vecmath/Vector3d.java b/javax.vecmath/src/javax/vecmath/Vector3d.java
new file mode 100644 (file)
index 0000000..3eae6dc
--- /dev/null
@@ -0,0 +1,210 @@
+/*
+ * $RCSfile: Vector3d.java,v $
+ *
+ * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ * $Revision: 1.5 $
+ * $Date: 2008/02/28 20:18:51 $
+ * $State: Exp $
+ */
+
+package javax.vecmath;
+
+import java.lang.Math;
+
+/**
+ * A 3-element vector that is represented by double-precision floating point 
+ * x,y,z coordinates.  If this value represents a normal, then it should
+ * be normalized.
+ *
+ */
+public class Vector3d extends Tuple3d implements java.io.Serializable {
+
+    // Combatible with 1.1
+    static final long serialVersionUID = 3761969948420550442L;
+
+    /**
+     * Constructs and initializes a Vector3d from the specified xyz coordinates.
+     * @param x the x coordinate
+     * @param y the y coordinate
+     * @param z the z coordinate
+     */
+    public Vector3d(double x, double y, double z)
+    {
+        super(x,y,z);
+    }
+
+
+    /**
+     * Constructs and initializes a Vector3d from the array of length 3.
+     * @param v the array of length 3 containing xyz in order
+     */
+    public Vector3d(double[] v)
+    {
+       super(v);
+    }
+
+
+    /**
+     * Constructs and initializes a Vector3d from the specified Vector3d.
+     * @param v1 the Vector3d containing the initialization x y z data
+     */
+    public Vector3d(Vector3d v1)
+    {
+         super(v1);
+    }
+
+
+    /**
+     * Constructs and initializes a Vector3d from the specified Vector3f.
+     * @param v1 the Vector3f containing the initialization x y z data
+     */
+    public Vector3d(Vector3f v1)
+    {
+       super(v1);
+    }
+
+
+    /**
+     * Constructs and initializes a Vector3d from the specified Tuple3f.
+     * @param t1 the Tuple3f containing the initialization x y z data
+     */  
+    public Vector3d(Tuple3f t1) 
+    {
+       super(t1);
+    }
+
+
+    /**
+     * Constructs and initializes a Vector3d from the specified Tuple3d.
+     * @param t1 the Tuple3d containing the initialization x y z data 
+     */  
+    public Vector3d(Tuple3d t1) 
+    {
+       super(t1); 
+    }
+
+
+    /**
+     * Constructs and initializes a Vector3d to (0,0,0).
+     */
+    public Vector3d()
+    {
+       super();
+    }
+
+
+   /**
+     * Sets this vector to the vector cross product of vectors v1 and v2.
+     * @param v1 the first vector
+     * @param v2 the second vector
+     */
+    public final void cross(Vector3d v1, Vector3d v2)
+    { 
+        double x,y;
+
+        x = v1.y*v2.z - v1.z*v2.y;
+        y = v2.x*v1.z - v2.z*v1.x;
+        this.z = v1.x*v2.y - v1.y*v2.x;
+        this.x = x;
+        this.y = y;
+    }
+
+
+    /**
+     * Sets the value of this vector to the normalization of vector v1.
+     * @param v1 the un-normalized vector
+     */
+    public final void normalize(Vector3d v1)
+    {
+        double norm;
+
+        norm = 1.0/Math.sqrt(v1.x*v1.x + v1.y*v1.y + v1.z*v1.z);
+        this.x = v1.x*norm;
+        this.y = v1.y*norm;
+        this.z = v1.z*norm;
+    }
+
+
+    /**
+     * Normalizes this vector in place.
+     */
+    public final void normalize()
+    {
+        double norm;
+
+        norm = 1.0/Math.sqrt(this.x*this.x + this.y*this.y + this.z*this.z);
+        this.x *= norm;
+        this.y *= norm;
+        this.z *= norm;
+    }
+
+
+  /**
+   * Returns the dot product of this vector and vector v1.
+   * @param v1 the other vector
+   * @return the dot product of this and v1
+   */
+  public final double dot(Vector3d v1)
+    {
+      return (this.x*v1.x + this.y*v1.y + this.z*v1.z);
+    }
+
+
+    /**
+     * Returns the squared length of this vector.
+     * @return the squared length of this vector
+     */
+    public final double lengthSquared()
+    {
+        return (this.x*this.x + this.y*this.y + this.z*this.z);
+    }
+
+
+    /**
+     * Returns the length of this vector.
+     * @return the length of this vector
+     */
+    public final double length()
+    {
+        return Math.sqrt(this.x*this.x + this.y*this.y + this.z*this.z);
+    }
+
+
+  /** 
+    *   Returns the angle in radians between this vector and the vector
+    *   parameter; the return value is constrained to the range [0,PI]. 
+    *   @param v1    the other vector 
+    *   @return   the angle in radians in the range [0,PI] 
+    */   
+   public final double angle(Vector3d v1) 
+   { 
+      double vDot = this.dot(v1) / ( this.length()*v1.length() );
+      if( vDot < -1.0) vDot = -1.0;
+      if( vDot >  1.0) vDot =  1.0;
+      return((double) (Math.acos( vDot )));
+   } 
+
+}
diff --git a/javax.vecmath/src/javax/vecmath/Vector3f.java b/javax.vecmath/src/javax/vecmath/Vector3f.java
new file mode 100644 (file)
index 0000000..f21cf92
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+ * $RCSfile: Vector3f.java,v $
+ *
+ * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ * $Revision: 1.5 $
+ * $Date: 2008/02/28 20:18:51 $
+ * $State: Exp $
+ */
+
+package javax.vecmath;
+
+import java.lang.Math;
+
+/**
+ * A 3-element vector that is represented by single-precision floating point 
+ * x,y,z coordinates.  If this value represents a normal, then it should
+ * be normalized.
+ *
+ */
+public class Vector3f extends Tuple3f implements java.io.Serializable {
+
+    // Combatible with 1.1
+    static final long serialVersionUID = -7031930069184524614L;
+
+    /**
+     * Constructs and initializes a Vector3f from the specified xyz coordinates.
+     * @param x the x coordinate
+     * @param y the y coordinate
+     * @param z the z coordinate
+     */
+    public Vector3f(float x, float y, float z)
+    {
+        super(x,y,z);
+    }
+
+
+    /**
+     * Constructs and initializes a Vector3f from the array of length 3.
+     * @param v the array of length 3 containing xyz in order
+     */
+    public Vector3f(float[] v)
+    {
+       super(v);
+    }
+
+
+    /**
+     * Constructs and initializes a Vector3f from the specified Vector3f.
+     * @param v1 the Vector3f containing the initialization x y z data
+     */
+    public Vector3f(Vector3f v1)
+    {
+       super(v1);
+    }
+
+
+    /**
+     * Constructs and initializes a Vector3f from the specified Vector3d.
+     * @param v1 the Vector3d containing the initialization x y z data
+     */
+    public Vector3f(Vector3d v1)
+    {
+       super(v1);
+    }
+
+
+    /**
+     * Constructs and initializes a Vector3f from the specified Tuple3f.
+     * @param t1 the Tuple3f containing the initialization x y z data
+     */  
+    public Vector3f(Tuple3f t1) {
+       super(t1);
+    }
+
+
+    /**
+     * Constructs and initializes a Vector3f from the specified Tuple3d.
+     * @param t1 the Tuple3d containing the initialization x y z data
+     */  
+    public Vector3f(Tuple3d t1) {
+       super(t1);
+    }
+
+
+    /**
+     * Constructs and initializes a Vector3f to (0,0,0).
+     */
+    public Vector3f()
+    {
+        super();
+    }
+
+
+   /**
+     * Returns the squared length of this vector.
+     * @return the squared length of this vector
+     */
+    public final float lengthSquared()
+    {
+        return (this.x*this.x + this.y*this.y + this.z*this.z);
+    }
+
+    /**
+     * Returns the length of this vector.
+     * @return the length of this vector
+     */
+    public final float length()
+    {
+        return (float)
+             Math.sqrt(this.x*this.x + this.y*this.y + this.z*this.z);
+    }
+
+
+  /**
+     * Sets this vector to be the vector cross product of vectors v1 and v2.
+     * @param v1 the first vector
+     * @param v2 the second vector
+     */
+    public final void cross(Vector3f v1, Vector3f v2)
+    {
+        float x,y;
+
+        x = v1.y*v2.z - v1.z*v2.y;
+        y = v2.x*v1.z - v2.z*v1.x;
+        this.z = v1.x*v2.y - v1.y*v2.x;
+        this.x = x;
+        this.y = y;
+    }
+
+ /**
+   * Computes the dot product of this vector and vector v1.
+   * @param v1 the other vector
+   * @return the dot product of this vector and v1
+   */
+  public final float dot(Vector3f v1)
+    {
+      return (this.x*v1.x + this.y*v1.y + this.z*v1.z);
+    }
+
+   /**
+     * Sets the value of this vector to the normalization of vector v1.
+     * @param v1 the un-normalized vector
+     */
+    public final void normalize(Vector3f v1)
+    {
+        float norm;
+
+        norm = (float) (1.0/Math.sqrt(v1.x*v1.x + v1.y*v1.y + v1.z*v1.z));
+        this.x = v1.x*norm;
+        this.y = v1.y*norm;
+        this.z = v1.z*norm;
+    }
+
+    /**
+     * Normalizes this vector in place.
+     */
+    public final void normalize()
+    {
+        float norm;
+
+        norm = (float)
+               (1.0/Math.sqrt(this.x*this.x + this.y*this.y + this.z*this.z));
+        this.x *= norm;
+        this.y *= norm;
+        this.z *= norm;
+    }
+
+
+  /** 
+    *   Returns the angle in radians between this vector and the vector
+    *   parameter; the return value is constrained to the range [0,PI]. 
+    *   @param v1    the other vector 
+    *   @return   the angle in radians in the range [0,PI] 
+    */   
+   public final float angle(Vector3f v1) 
+   { 
+      double vDot = this.dot(v1) / ( this.length()*v1.length() );
+      if( vDot < -1.0) vDot = -1.0;
+      if( vDot >  1.0) vDot =  1.0;
+      return((float) (Math.acos( vDot )));
+   } 
+
+}
diff --git a/javax.vecmath/src/javax/vecmath/Vector4d.java b/javax.vecmath/src/javax/vecmath/Vector4d.java
new file mode 100644 (file)
index 0000000..c15a7f8
--- /dev/null
@@ -0,0 +1,224 @@
+/*
+ * $RCSfile: Vector4d.java,v $
+ *
+ * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ * $Revision: 1.6 $
+ * $Date: 2008/02/28 20:18:51 $
+ * $State: Exp $
+ */
+
+package javax.vecmath;
+
+import java.lang.Math;
+
+/**
+ * A 4-element vector represented by double-precision floating point 
+ * x,y,z,w coordinates.
+ *
+ */
+public class Vector4d extends Tuple4d implements java.io.Serializable {
+
+    // Compatible with 1.1
+    static final long serialVersionUID = 3938123424117448700L;
+
+    /**
+     * Constructs and initializes a Vector4d from the specified xyzw coordinates.
+     * @param x the x coordinate
+     * @param y the y coordinate
+     * @param z the z coordinate
+     * @param w the w coordinate
+     */
+    public Vector4d(double x, double y, double z, double w)
+    {
+        super(x,y,z,w);
+    }
+
+    /**
+     * Constructs and initializes a Vector4d from the coordinates contained
+     * in the array.
+     * @param v the array of length 4 containing xyzw in order
+     */
+    public Vector4d(double[] v)
+    {
+        super(v);
+    }
+
+    /**
+     * Constructs and initializes a Vector4d from the specified Vector4d.
+     * @param v1 the Vector4d containing the initialization x y z w data
+     */
+    public Vector4d(Vector4d v1)
+    {
+         super(v1);
+    }
+
+    /**
+     * Constructs and initializes a Vector4d from the specified Vector4f.
+     * @param v1 the Vector4f containing the initialization x y z w data
+     */
+    public Vector4d(Vector4f v1)
+    {
+       super(v1);
+    }
+
+    /**
+     * Constructs and initializes a Vector4d from the specified Tuple4f.
+     * @param t1 the Tuple4f containing the initialization x y z w data
+     */  
+    public Vector4d(Tuple4f t1) 
+    {
+       super(t1);
+    }
+
+    /**
+     * Constructs and initializes a Vector4d from the specified Tuple4d.
+     * @param t1 the Tuple4d containing the initialization x y z w data 
+     */  
+    public Vector4d(Tuple4d t1) 
+    {
+       super(t1); 
+    }
+
+
+    /**
+     * Constructs and initializes a Vector4d from the specified Tuple3d.
+     * The x,y,z components of this vector are set to the corresponding
+     * components of tuple t1.  The w component of this vector
+     * is set to 0.
+     * @param t1 the tuple to be copied
+     *
+     * @since vecmath 1.2
+     */
+    public Vector4d(Tuple3d t1) {
+       super(t1.x, t1.y, t1.z, 0.0);
+    }
+
+
+    /**
+     * Constructs and initializes a Vector4d to (0,0,0,0).
+     */
+    public Vector4d()
+    {
+       super();
+    }
+
+   
+    /**
+     * Sets the x,y,z components of this vector to the corresponding
+     * components of tuple t1.  The w component of this vector
+     * is set to 0.
+     * @param t1 the tuple to be copied
+     *
+     * @since vecmath 1.2
+     */
+    public final void set(Tuple3d t1) {
+       this.x = t1.x;
+       this.y = t1.y;
+       this.z = t1.z;
+       this.w = 0.0;
+    }
+
+
+    /**
+     * Returns the length of this vector.
+     * @return the length of this vector
+     */
+    public final double length()
+    {
+        return Math.sqrt(this.x*this.x + this.y*this.y +
+                              this.z*this.z + this.w*this.w);
+    }
+
+
+    /**
+     * Returns the squared length of this vector.
+     * @return the squared length of this vector
+     */
+    public final double lengthSquared()
+    {
+        return (this.x*this.x + this.y*this.y +
+                this.z*this.z + this.w*this.w);
+    }
+
+
+  /**
+   * Returns the dot product of this vector and vector v1.
+   * @param v1 the other vector
+   * @return the dot product of this vector and vector v1
+   */
+    public final double dot(Vector4d v1)
+    {
+      return (this.x*v1.x + this.y*v1.y + this.z*v1.z + this.w*v1.w);
+    }
+
+
+   /**
+     * Sets the value of this vector to the normalization of vector v1.
+     * @param v1 the un-normalized vector
+     */
+    public final void normalize(Vector4d v1)
+    {
+        double norm;
+
+        norm = 1.0/Math.sqrt(v1.x*v1.x + v1.y*v1.y + v1.z*v1.z + v1.w*v1.w);
+        this.x = v1.x*norm;
+        this.y = v1.y*norm;
+        this.z = v1.z*norm;
+        this.w = v1.w*norm;
+    }
+
+
+    /**
+     * Normalizes this vector in place.
+     */
+    public final void normalize()
+    {
+        double norm;
+
+        norm = 1.0/Math.sqrt(this.x*this.x + this.y*this.y +
+                              this.z*this.z + this.w*this.w);
+        this.x *= norm;
+        this.y *= norm;
+        this.z *= norm;
+        this.w *= norm;
+    }
+
+
+  /** 
+    *   Returns the (4-space) angle in radians between this vector and 
+    *   the vector parameter; the return value is constrained to the 
+    *   range [0,PI]. 
+    *   @param v1    the other vector 
+    *   @return   the angle in radians in the range [0,PI] 
+    */   
+   public final double angle(Vector4d v1) 
+   { 
+      double vDot = this.dot(v1) / ( this.length()*v1.length() );
+      if( vDot < -1.0) vDot = -1.0;
+      if( vDot >  1.0) vDot =  1.0;
+      return((double) (Math.acos( vDot )));
+   } 
+
+}
diff --git a/javax.vecmath/src/javax/vecmath/Vector4f.java b/javax.vecmath/src/javax/vecmath/Vector4f.java
new file mode 100644 (file)
index 0000000..e407ddb
--- /dev/null
@@ -0,0 +1,228 @@
+/*
+ * $RCSfile: Vector4f.java,v $
+ *
+ * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ * $Revision: 1.6 $
+ * $Date: 2008/02/28 20:18:51 $
+ * $State: Exp $
+ */
+
+package javax.vecmath;
+
+import java.lang.Math;
+
+/**
+ * A 4-element vector represented by single-precision floating point x,y,z,w 
+ * coordinates.
+ *
+ */
+public class Vector4f extends Tuple4f implements java.io.Serializable {
+
+  // Compatible with 1.1
+  static final long serialVersionUID = 8749319902347760659L;
+
+  /**
+   * Constructs and initializes a Vector4f from the specified xyzw coordinates.
+   * @param x the x coordinate
+   * @param y the y coordinate
+   * @param z the z coordinate
+   * @param w the w coordinate
+   */
+  public Vector4f(float x, float y, float z, float w)
+  {
+       super(x,y,z,w);
+  }
+
+
+  /**
+   * Constructs and initializes a Vector4f from the array of length 4. 
+   * @param v the array of length 4 containing xyzw in order
+   */
+  public Vector4f(float[] v)
+  {
+     super(v);
+  }
+
+
+  /**
+   * Constructs and initializes a Vector4f from the specified Vector4f.
+   * @param v1 the Vector4f containing the initialization x y z w data
+   */
+  public Vector4f(Vector4f v1)
+  {
+      super(v1);
+  }
+
+
+  /**
+   * Constructs and initializes a Vector4f from the specified Vector4d.
+   * @param v1 the Vector4d containing the initialization x y z w data
+   */
+  public Vector4f(Vector4d v1)
+  {
+      super(v1);
+  }
+
+
+    /**
+     * Constructs and initializes a Vector4f from the specified Tuple4f.
+     * @param t1 the Tuple4f containing the initialization x y z w data
+     */  
+    public Vector4f(Tuple4f t1) 
+    {
+       super(t1);
+    }
+
+
+    /**
+     * Constructs and initializes a Vector4f from the specified Tuple4d.
+     * @param t1 the Tuple4d containing the initialization x y z w data 
+     */  
+    public Vector4f(Tuple4d t1) 
+    {
+       super(t1); 
+    }
+
+
+    /**
+     * Constructs and initializes a Vector4f from the specified Tuple3f.
+     * The x,y,z components of this vector are set to the corresponding
+     * components of tuple t1.  The w component of this vector
+     * is set to 0.
+     * @param t1 the tuple to be copied
+     *
+     * @since vecmath 1.2
+     */
+    public Vector4f(Tuple3f t1) {
+       super(t1.x, t1.y, t1.z, 0.0f);
+    }
+
+
+  /**
+   * Constructs and initializes a Vector4f to (0,0,0,0).
+   */
+  public Vector4f()
+  {
+      super();
+  }
+
+
+    /**
+     * Sets the x,y,z components of this vector to the corresponding
+     * components of tuple t1.  The w component of this vector
+     * is set to 0.
+     * @param t1 the tuple to be copied
+     *
+     * @since vecmath 1.2
+     */
+    public final void set(Tuple3f t1) {
+       this.x = t1.x;
+       this.y = t1.y;
+       this.z = t1.z;
+       this.w = 0.0f;
+    }
+
+
+ /**
+   * Returns the length of this vector.
+   * @return the length of this vector as a float
+   */
+  public final float length()
+  {
+    return
+      (float) Math.sqrt(this.x*this.x + this.y*this.y +
+                        this.z*this.z + this.w*this.w);
+  }
+
+  /**
+   * Returns the squared length of this vector
+   * @return the squared length of this vector as a float
+   */
+  public final float lengthSquared()
+  {
+    return (this.x*this.x + this.y*this.y +
+            this.z*this.z + this.w*this.w);
+  }
+
+  /**
+   * returns the dot product of this vector and v1
+   * @param v1 the other vector
+   * @return the dot product of this vector and v1
+   */
+  public final float dot(Vector4f v1)
+    {
+      return (this.x*v1.x + this.y*v1.y + this.z*v1.z + this.w*v1.w);
+    }
+
+
+ /**
+   * Sets the value of this vector to the normalization of vector v1.
+   * @param v1 the un-normalized vector
+   */
+  public final void normalize(Vector4f v1)
+  {
+    float norm;
+
+    norm = (float) (1.0/Math.sqrt(v1.x*v1.x + v1.y*v1.y +
+                                  v1.z*v1.z + v1.w*v1.w));
+    this.x = v1.x*norm;
+    this.y = v1.y*norm;
+    this.z = v1.z*norm;
+    this.w = v1.w*norm;
+  }
+
+
+  /**
+   * Normalizes this vector in place.
+   */
+  public final void normalize()
+  {
+    float norm;
+
+    norm = (float) (1.0/Math.sqrt(this.x*this.x + this.y*this.y +
+                                  this.z*this.z + this.w*this.w));
+    this.x *= norm;
+    this.y *= norm;
+    this.z *= norm;
+    this.w *= norm;
+  }
+
+
+  /** 
+    *   Returns the (4-space) angle in radians between this vector and 
+    *   the vector parameter; the return value is constrained to the 
+    *   range [0,PI]. 
+    *   @param v1    the other vector 
+    *   @return   the angle in radians in the range [0,PI] 
+    */   
+   public final float angle(Vector4f v1) 
+   { 
+      double vDot = this.dot(v1) / ( this.length()*v1.length() );
+      if( vDot < -1.0) vDot = -1.0;
+      if( vDot >  1.0) vDot =  1.0;
+      return((float) (Math.acos( vDot )));
+   } 
+
+}
index ce52b6233176014e01d0039146ea31313570f902..5989d5d28599b29c88389cf8446154c278763b08 100644 (file)
          id="vtk.lib"
          version="0.0.0"/>
 
+   <plugin
+         id="javax.vecmath"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
    <plugin
          id="org.simantics.g3d"
          download-size="0"
diff --git a/pom.xml b/pom.xml
index 4d4a832df590fa1d14f13b85132bfa24b85ffe8f..a406b5a706aed23b3ec8ba9905a2caf4ab329145 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -11,6 +11,7 @@
                <branch-spec>master</branch-spec>
                <simantics-download-site>http://www.simantics.org/download</simantics-download-site>
                <tycho-version>1.0.0</tycho-version>
+               <tycho-extras-version>1.0.0</tycho-extras-version>
        </properties>
 
        <repositories>
@@ -48,6 +49,7 @@
                                <artifactId>target-platform-configuration</artifactId>
                                <version>${tycho-version}</version>
                                <configuration>
+                                       <includePackedArtifacts>true</includePackedArtifacts>
                                        <ignoreTychoRepositories>true</ignoreTychoRepositories>
                                        <resolver>p2</resolver>
                                        <environments>
                                        </environments>
                                </configuration>
                        </plugin>
+                       <plugin>
+                               <groupId>org.eclipse.tycho.extras</groupId>
+                               <artifactId>tycho-pack200b-plugin</artifactId>
+                               <version>${tycho-extras-version}</version>
+                               <executions>
+                                       <execution>
+                                               <id>pack200-pack</id>
+                                               <goals>
+                                                       <goal>pack</goal>
+                                               </goals>
+                                       </execution>
+                               </executions>
+                       </plugin>
+                       <plugin>
+                               <groupId>org.eclipse.tycho</groupId>
+                               <artifactId>tycho-p2-plugin</artifactId>
+                               <version>${tycho-version}</version>
+                               <executions>
+                                       <execution>
+                                               <id>attach-p2-metadata</id>
+                                               <phase>package</phase>
+                                               <goals>
+                                                       <goal>p2-metadata</goal>
+                                               </goals>
+                                       </execution>
+                               </executions>
+                               <configuration>
+                                       <defaultP2Metadata>false</defaultP2Metadata>
+                               </configuration>
+                       </plugin>
 
                </plugins>
        </build>