toxiclibs 0.2-java → 0.5.0-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (383) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +16 -0
  3. data/CHANGELOG.md +4 -0
  4. data/LICENSE +675 -0
  5. data/README.md +12 -5
  6. data/Rakefile +25 -82
  7. data/examples/attract_repel/attract_repel.rb +30 -0
  8. data/examples/attract_repel/attractor.rb +23 -0
  9. data/examples/attract_repel/particle.rb +27 -0
  10. data/examples/data/ti_yong.png +0 -0
  11. data/examples/force_directed/cluster.rb +76 -0
  12. data/examples/force_directed/force_directed_graph.rb +92 -0
  13. data/examples/force_directed/node.rb +26 -0
  14. data/examples/gray_scott_image.rb +75 -0
  15. data/examples/gray_scott_tone_map.rb +77 -0
  16. data/examples/implicit.rb +139 -0
  17. data/examples/inflate_mesh.rb +89 -0
  18. data/examples/model_align.rb +44 -0
  19. data/examples/povmesh/ftest.rb +46 -0
  20. data/examples/povmesh/tentacle.rb +73 -0
  21. data/examples/simple_cluster/cluster.rb +47 -0
  22. data/examples/simple_cluster/node.rb +27 -0
  23. data/examples/simple_cluster/simple_cluster.rb +60 -0
  24. data/examples/soft_body/blanket.rb +45 -0
  25. data/examples/soft_body/connection.rb +16 -0
  26. data/examples/soft_body/particle.rb +22 -0
  27. data/examples/soft_body/soft_body_square_adapted.rb +55 -0
  28. data/lib/toxiclibs.jar +0 -0
  29. data/lib/toxiclibs.rb +91 -32
  30. data/lib/toxiclibs/version.rb +1 -1
  31. data/pom.xml +122 -0
  32. data/src/com/toxi/net/ClientListener.java +41 -0
  33. data/src/com/toxi/net/ServerListener.java +70 -0
  34. data/src/com/toxi/net/ServerListenerAdapter.java +47 -0
  35. data/src/com/toxi/net/ServerState.java +18 -0
  36. data/src/com/toxi/net/UDPConnection.java +66 -0
  37. data/src/com/toxi/net/UDPSyncClient.java +81 -0
  38. data/src/com/toxi/net/UDPSyncServer.java +450 -0
  39. data/src/com/toxi/nio/UDPClient.java +121 -0
  40. data/src/com/toxi/nio/UDPClientState.java +32 -0
  41. data/src/com/toxi/nio/UDPServer.java +129 -0
  42. data/src/toxi/color/AccessCriteria.java +114 -0
  43. data/src/toxi/color/AlphaAccessor.java +67 -0
  44. data/src/toxi/color/CMYKAccessor.java +122 -0
  45. data/src/toxi/color/CMYKDistanceProxy.java +40 -0
  46. data/src/toxi/color/ColorGradient.java +260 -0
  47. data/src/toxi/color/ColorList.java +699 -0
  48. data/src/toxi/color/ColorRange.java +671 -0
  49. data/src/toxi/color/ColorTheme.java +163 -0
  50. data/src/toxi/color/DistanceProxy.java +44 -0
  51. data/src/toxi/color/HSVAccessor.java +113 -0
  52. data/src/toxi/color/HSVDistanceProxy.java +40 -0
  53. data/src/toxi/color/HistEntry.java +85 -0
  54. data/src/toxi/color/Histogram.java +185 -0
  55. data/src/toxi/color/Hue.java +249 -0
  56. data/src/toxi/color/LuminanceAccessor.java +78 -0
  57. data/src/toxi/color/NamedColor.java +935 -0
  58. data/src/toxi/color/ProximityComparator.java +70 -0
  59. data/src/toxi/color/RGBAccessor.java +113 -0
  60. data/src/toxi/color/RGBDistanceProxy.java +41 -0
  61. data/src/toxi/color/ReadonlyTColor.java +296 -0
  62. data/src/toxi/color/TColor.java +1677 -0
  63. data/src/toxi/color/TColorAdapter.java +68 -0
  64. data/src/toxi/color/ToneMap.java +218 -0
  65. data/src/toxi/color/theory/AnalogousStrategy.java +140 -0
  66. data/src/toxi/color/theory/ColorTheoryRegistry.java +139 -0
  67. data/src/toxi/color/theory/ColorTheoryStrategy.java +56 -0
  68. data/src/toxi/color/theory/ComplementaryStrategy.java +111 -0
  69. data/src/toxi/color/theory/CompoundTheoryStrategy.java +143 -0
  70. data/src/toxi/color/theory/LeftSplitComplementaryStrategy.java +82 -0
  71. data/src/toxi/color/theory/MonochromeTheoryStrategy.java +103 -0
  72. data/src/toxi/color/theory/RightSplitComplementaryStrategy.java +82 -0
  73. data/src/toxi/color/theory/SingleComplementStrategy.java +76 -0
  74. data/src/toxi/color/theory/SplitComplementaryStrategy.java +77 -0
  75. data/src/toxi/color/theory/TetradTheoryStrategy.java +114 -0
  76. data/src/toxi/color/theory/TriadTheoryStrategy.java +77 -0
  77. data/src/toxi/data/csv/CSVAdapter.java +74 -0
  78. data/src/toxi/data/csv/CSVFieldMapper.java +212 -0
  79. data/src/toxi/data/csv/CSVListener.java +61 -0
  80. data/src/toxi/data/csv/CSVParser.java +202 -0
  81. data/src/toxi/data/feeds/AtomAuthor.java +49 -0
  82. data/src/toxi/data/feeds/AtomContent.java +50 -0
  83. data/src/toxi/data/feeds/AtomEntry.java +111 -0
  84. data/src/toxi/data/feeds/AtomFeed.java +129 -0
  85. data/src/toxi/data/feeds/AtomLink.java +62 -0
  86. data/src/toxi/data/feeds/RSSChannel.java +88 -0
  87. data/src/toxi/data/feeds/RSSEnclosure.java +60 -0
  88. data/src/toxi/data/feeds/RSSFeed.java +99 -0
  89. data/src/toxi/data/feeds/RSSItem.java +104 -0
  90. data/src/toxi/data/feeds/util/EntityStripper.java +2480 -0
  91. data/src/toxi/data/feeds/util/Iso8601DateAdapter.java +101 -0
  92. data/src/toxi/data/feeds/util/Rfc822DateAdapter.java +93 -0
  93. data/src/toxi/geom/AABB.java +658 -0
  94. data/src/toxi/geom/Axis3D.java +116 -0
  95. data/src/toxi/geom/AxisAlignedCylinder.java +163 -0
  96. data/src/toxi/geom/BernsteinPolynomial.java +94 -0
  97. data/src/toxi/geom/BezierCurve2D.java +159 -0
  98. data/src/toxi/geom/BezierCurve3D.java +148 -0
  99. data/src/toxi/geom/BooleanShapeBuilder.java +185 -0
  100. data/src/toxi/geom/BoxIntersector.java +52 -0
  101. data/src/toxi/geom/Circle.java +230 -0
  102. data/src/toxi/geom/CircleIntersector.java +85 -0
  103. data/src/toxi/geom/Cone.java +150 -0
  104. data/src/toxi/geom/ConvexPolygonClipper.java +136 -0
  105. data/src/toxi/geom/CoordinateExtractor.java +16 -0
  106. data/src/toxi/geom/Ellipse.java +250 -0
  107. data/src/toxi/geom/GMatrix.java +2599 -0
  108. data/src/toxi/geom/GVector.java +833 -0
  109. data/src/toxi/geom/GlobalGridTesselator.java +54 -0
  110. data/src/toxi/geom/GridTesselator.java +108 -0
  111. data/src/toxi/geom/Intersector2D.java +49 -0
  112. data/src/toxi/geom/Intersector3D.java +51 -0
  113. data/src/toxi/geom/IsectData2D.java +103 -0
  114. data/src/toxi/geom/IsectData3D.java +103 -0
  115. data/src/toxi/geom/Line2D.java +534 -0
  116. data/src/toxi/geom/Line3D.java +471 -0
  117. data/src/toxi/geom/LineStrip2D.java +430 -0
  118. data/src/toxi/geom/LineStrip3D.java +230 -0
  119. data/src/toxi/geom/LocalGridTesselator.java +57 -0
  120. data/src/toxi/geom/Matrix3d.java +3048 -0
  121. data/src/toxi/geom/Matrix4f.java +3446 -0
  122. data/src/toxi/geom/Matrix4x4.java +1076 -0
  123. data/src/toxi/geom/MatrixSizeException.java +58 -0
  124. data/src/toxi/geom/OctreeVisitor.java +44 -0
  125. data/src/toxi/geom/Origin3D.java +148 -0
  126. data/src/toxi/geom/Plane.java +293 -0
  127. data/src/toxi/geom/PlaneIntersector.java +57 -0
  128. data/src/toxi/geom/PointCloud3D.java +253 -0
  129. data/src/toxi/geom/PointOctree.java +502 -0
  130. data/src/toxi/geom/PointQuadtree.java +375 -0
  131. data/src/toxi/geom/Polygon2D.java +1038 -0
  132. data/src/toxi/geom/PolygonClipper2D.java +45 -0
  133. data/src/toxi/geom/PolygonTesselator.java +20 -0
  134. data/src/toxi/geom/QuadtreeVisitor.java +44 -0
  135. data/src/toxi/geom/Quaternion.java +641 -0
  136. data/src/toxi/geom/Ray2D.java +146 -0
  137. data/src/toxi/geom/Ray3D.java +150 -0
  138. data/src/toxi/geom/Ray3DIntersector.java +75 -0
  139. data/src/toxi/geom/ReadonlyVec2D.java +575 -0
  140. data/src/toxi/geom/ReadonlyVec3D.java +628 -0
  141. data/src/toxi/geom/ReadonlyVec4D.java +431 -0
  142. data/src/toxi/geom/Rect.java +720 -0
  143. data/src/toxi/geom/Reflector3D.java +58 -0
  144. data/src/toxi/geom/Shape2D.java +94 -0
  145. data/src/toxi/geom/Shape3D.java +42 -0
  146. data/src/toxi/geom/SingularMatrixException.java +57 -0
  147. data/src/toxi/geom/SpatialBins.java +182 -0
  148. data/src/toxi/geom/SpatialIndex.java +61 -0
  149. data/src/toxi/geom/Sphere.java +224 -0
  150. data/src/toxi/geom/SphereIntersectorReflector.java +196 -0
  151. data/src/toxi/geom/Spline2D.java +349 -0
  152. data/src/toxi/geom/Spline3D.java +351 -0
  153. data/src/toxi/geom/SutherlandHodgemanClipper.java +151 -0
  154. data/src/toxi/geom/Triangle2D.java +422 -0
  155. data/src/toxi/geom/Triangle3D.java +456 -0
  156. data/src/toxi/geom/TriangleIntersector.java +105 -0
  157. data/src/toxi/geom/Vec2D.java +1328 -0
  158. data/src/toxi/geom/Vec3D.java +1832 -0
  159. data/src/toxi/geom/Vec4D.java +985 -0
  160. data/src/toxi/geom/VecMathUtil.java +100 -0
  161. data/src/toxi/geom/XAxisCylinder.java +64 -0
  162. data/src/toxi/geom/YAxisCylinder.java +65 -0
  163. data/src/toxi/geom/ZAxisCylinder.java +64 -0
  164. data/src/toxi/geom/mesh/BezierPatch.java +200 -0
  165. data/src/toxi/geom/mesh/BoxSelector.java +62 -0
  166. data/src/toxi/geom/mesh/DefaultSTLColorModel.java +67 -0
  167. data/src/toxi/geom/mesh/DefaultSelector.java +50 -0
  168. data/src/toxi/geom/mesh/Face.java +176 -0
  169. data/src/toxi/geom/mesh/LaplacianSmooth.java +80 -0
  170. data/src/toxi/geom/mesh/MaterialiseSTLColorModel.java +150 -0
  171. data/src/toxi/geom/mesh/Mesh3D.java +224 -0
  172. data/src/toxi/geom/mesh/MeshIntersector.java +91 -0
  173. data/src/toxi/geom/mesh/OBJWriter.java +194 -0
  174. data/src/toxi/geom/mesh/PLYWriter.java +167 -0
  175. data/src/toxi/geom/mesh/PlaneSelector.java +90 -0
  176. data/src/toxi/geom/mesh/STLColorModel.java +54 -0
  177. data/src/toxi/geom/mesh/STLReader.java +185 -0
  178. data/src/toxi/geom/mesh/STLWriter.java +323 -0
  179. data/src/toxi/geom/mesh/SphereFunction.java +156 -0
  180. data/src/toxi/geom/mesh/SphericalHarmonics.java +110 -0
  181. data/src/toxi/geom/mesh/SuperEllipsoid.java +110 -0
  182. data/src/toxi/geom/mesh/SurfaceFunction.java +75 -0
  183. data/src/toxi/geom/mesh/SurfaceMeshBuilder.java +149 -0
  184. data/src/toxi/geom/mesh/Terrain.java +451 -0
  185. data/src/toxi/geom/mesh/TriangleMesh.java +1201 -0
  186. data/src/toxi/geom/mesh/Vertex.java +78 -0
  187. data/src/toxi/geom/mesh/VertexSelector.java +193 -0
  188. data/src/toxi/geom/mesh/WEFace.java +100 -0
  189. data/src/toxi/geom/mesh/WEMeshFilterStrategy.java +51 -0
  190. data/src/toxi/geom/mesh/WETriangleMesh.java +761 -0
  191. data/src/toxi/geom/mesh/WEVertex.java +134 -0
  192. data/src/toxi/geom/mesh/WingedEdge.java +115 -0
  193. data/src/toxi/geom/mesh/subdiv/CentroidSubdiv.java +37 -0
  194. data/src/toxi/geom/mesh/subdiv/DisplacementSubdivision.java +85 -0
  195. data/src/toxi/geom/mesh/subdiv/DualDisplacementSubdivision.java +94 -0
  196. data/src/toxi/geom/mesh/subdiv/DualSubdivision.java +49 -0
  197. data/src/toxi/geom/mesh/subdiv/EdgeLengthComparator.java +50 -0
  198. data/src/toxi/geom/mesh/subdiv/FaceCountComparator.java +51 -0
  199. data/src/toxi/geom/mesh/subdiv/MidpointDisplacementSubdivision.java +80 -0
  200. data/src/toxi/geom/mesh/subdiv/MidpointSubdiv.java +42 -0
  201. data/src/toxi/geom/mesh/subdiv/MidpointSubdivision.java +48 -0
  202. data/src/toxi/geom/mesh/subdiv/NewSubdivStrategy.java +23 -0
  203. data/src/toxi/geom/mesh/subdiv/NormalDisplacementSubdivision.java +74 -0
  204. data/src/toxi/geom/mesh/subdiv/SubdivisionStrategy.java +83 -0
  205. data/src/toxi/geom/mesh/subdiv/TriSubdivision.java +51 -0
  206. data/src/toxi/geom/mesh2d/DelaunayTriangle.java +222 -0
  207. data/src/toxi/geom/mesh2d/DelaunayTriangulation.java +327 -0
  208. data/src/toxi/geom/mesh2d/DelaunayVertex.java +560 -0
  209. data/src/toxi/geom/mesh2d/Voronoi.java +149 -0
  210. data/src/toxi/geom/nurbs/BasicNurbsCurve.java +210 -0
  211. data/src/toxi/geom/nurbs/BasicNurbsSurface.java +233 -0
  212. data/src/toxi/geom/nurbs/ControlNet.java +148 -0
  213. data/src/toxi/geom/nurbs/CurveCreator.java +112 -0
  214. data/src/toxi/geom/nurbs/CurveUtils.java +259 -0
  215. data/src/toxi/geom/nurbs/InterpolationException.java +65 -0
  216. data/src/toxi/geom/nurbs/KnotVector.java +333 -0
  217. data/src/toxi/geom/nurbs/NurbsCreator.java +815 -0
  218. data/src/toxi/geom/nurbs/NurbsCurve.java +120 -0
  219. data/src/toxi/geom/nurbs/NurbsMeshCreator.java +145 -0
  220. data/src/toxi/geom/nurbs/NurbsSurface.java +147 -0
  221. data/src/toxi/image/util/Filter8bit.java +331 -0
  222. data/src/toxi/image/util/TiledFrameExporter.java +162 -0
  223. data/src/toxi/math/BezierInterpolation.java +102 -0
  224. data/src/toxi/math/CircularInterpolation.java +88 -0
  225. data/src/toxi/math/CosineInterpolation.java +51 -0
  226. data/src/toxi/math/DecimatedInterpolation.java +77 -0
  227. data/src/toxi/math/ExponentialInterpolation.java +68 -0
  228. data/src/toxi/math/InterpolateStrategy.java +60 -0
  229. data/src/toxi/math/Interpolation2D.java +93 -0
  230. data/src/toxi/math/LinearInterpolation.java +46 -0
  231. data/src/toxi/math/MathUtils.java +990 -0
  232. data/src/toxi/math/NonLinearScaleMap.java +101 -0
  233. data/src/toxi/math/ScaleMap.java +183 -0
  234. data/src/toxi/math/SigmoidInterpolation.java +78 -0
  235. data/src/toxi/math/SinCosLUT.java +141 -0
  236. data/src/toxi/math/ThresholdInterpolation.java +58 -0
  237. data/src/toxi/math/ZoomLensInterpolation.java +126 -0
  238. data/src/toxi/math/conversion/UnitTranslator.java +161 -0
  239. data/src/toxi/math/noise/PerlinNoise.java +281 -0
  240. data/src/toxi/math/noise/SimplexNoise.java +542 -0
  241. data/src/toxi/math/waves/AMFMSineWave.java +143 -0
  242. data/src/toxi/math/waves/AbstractWave.java +248 -0
  243. data/src/toxi/math/waves/ConstantWave.java +48 -0
  244. data/src/toxi/math/waves/FMHarmonicSquareWave.java +155 -0
  245. data/src/toxi/math/waves/FMSawtoothWave.java +144 -0
  246. data/src/toxi/math/waves/FMSineWave.java +142 -0
  247. data/src/toxi/math/waves/FMSquareWave.java +143 -0
  248. data/src/toxi/math/waves/FMTriangleWave.java +126 -0
  249. data/src/toxi/math/waves/SineWave.java +81 -0
  250. data/src/toxi/math/waves/Wave2D.java +68 -0
  251. data/src/toxi/math/waves/WaveState.java +69 -0
  252. data/src/toxi/music/scale/AbstractScale.java +117 -0
  253. data/src/toxi/music/scale/GenericScale.java +66 -0
  254. data/src/toxi/music/scale/MajorScale.java +41 -0
  255. data/src/toxi/newmesh/AttributedEdge.java +106 -0
  256. data/src/toxi/newmesh/AttributedFace.java +63 -0
  257. data/src/toxi/newmesh/IndexedTriangleMesh.java +809 -0
  258. data/src/toxi/newmesh/MeshAttributeCompiler.java +45 -0
  259. data/src/toxi/newmesh/MeshFaceNormalCompiler.java +52 -0
  260. data/src/toxi/newmesh/MeshUVCompiler.java +52 -0
  261. data/src/toxi/newmesh/MeshVertexColorCompiler.java +49 -0
  262. data/src/toxi/newmesh/MeshVertexCompiler.java +54 -0
  263. data/src/toxi/newmesh/MeshVertexNormalCompiler.java +55 -0
  264. data/src/toxi/newmesh/SpatialIndex.java +78 -0
  265. data/src/toxi/physics2d/ParticlePath2D.java +100 -0
  266. data/src/toxi/physics2d/ParticleString2D.java +184 -0
  267. data/src/toxi/physics2d/PullBackSpring2D.java +51 -0
  268. data/src/toxi/physics2d/VerletConstrainedSpring2D.java +89 -0
  269. data/src/toxi/physics2d/VerletMinDistanceSpring2D.java +57 -0
  270. data/src/toxi/physics2d/VerletParticle2D.java +457 -0
  271. data/src/toxi/physics2d/VerletPhysics2D.java +448 -0
  272. data/src/toxi/physics2d/VerletSpring2D.java +181 -0
  273. data/src/toxi/physics2d/behaviors/AttractionBehavior2D.java +212 -0
  274. data/src/toxi/physics2d/behaviors/ConstantForceBehavior2D.java +112 -0
  275. data/src/toxi/physics2d/behaviors/GravityBehavior2D.java +61 -0
  276. data/src/toxi/physics2d/behaviors/ParticleBehavior2D.java +66 -0
  277. data/src/toxi/physics2d/constraints/AngularConstraint.java +83 -0
  278. data/src/toxi/physics2d/constraints/AxisConstraint.java +71 -0
  279. data/src/toxi/physics2d/constraints/CircularConstraint.java +69 -0
  280. data/src/toxi/physics2d/constraints/MaxConstraint.java +66 -0
  281. data/src/toxi/physics2d/constraints/MinConstraint.java +66 -0
  282. data/src/toxi/physics2d/constraints/ParticleConstraint2D.java +47 -0
  283. data/src/toxi/physics2d/constraints/PolygonConstraint.java +93 -0
  284. data/src/toxi/physics2d/constraints/RectConstraint.java +114 -0
  285. data/src/toxi/physics3d/ParticlePath3D.java +100 -0
  286. data/src/toxi/physics3d/ParticleString3D.java +184 -0
  287. data/src/toxi/physics3d/PullBackSpring3D.java +50 -0
  288. data/src/toxi/physics3d/VerletConstrainedSpring3D.java +88 -0
  289. data/src/toxi/physics3d/VerletMinDistanceSpring3D.java +56 -0
  290. data/src/toxi/physics3d/VerletParticle3D.java +385 -0
  291. data/src/toxi/physics3d/VerletPhysics3D.java +417 -0
  292. data/src/toxi/physics3d/VerletSpring3D.java +180 -0
  293. data/src/toxi/physics3d/behaviors/AttractionBehavior3D.java +182 -0
  294. data/src/toxi/physics3d/behaviors/ConstantForceBehavior3D.java +92 -0
  295. data/src/toxi/physics3d/behaviors/GravityBehavior3D.java +61 -0
  296. data/src/toxi/physics3d/behaviors/ParticleBehavior3D.java +52 -0
  297. data/src/toxi/physics3d/constraints/AxisConstraint.java +68 -0
  298. data/src/toxi/physics3d/constraints/BoxConstraint.java +121 -0
  299. data/src/toxi/physics3d/constraints/CylinderConstraint.java +87 -0
  300. data/src/toxi/physics3d/constraints/MaxConstraint.java +65 -0
  301. data/src/toxi/physics3d/constraints/MinConstraint.java +65 -0
  302. data/src/toxi/physics3d/constraints/ParticleConstraint3D.java +49 -0
  303. data/src/toxi/physics3d/constraints/PlaneConstraint.java +78 -0
  304. data/src/toxi/physics3d/constraints/SoftBoxConstraint.java +87 -0
  305. data/src/toxi/physics3d/constraints/SphereConstraint.java +108 -0
  306. data/src/toxi/processing/ArrowModifier.java +116 -0
  307. data/src/toxi/processing/DashedLineModifier.java +48 -0
  308. data/src/toxi/processing/DeltaOrientationMapper.java +57 -0
  309. data/src/toxi/processing/Line2DRenderModifier.java +18 -0
  310. data/src/toxi/processing/MeshToVBO.java +94 -0
  311. data/src/toxi/processing/NormalMapper.java +18 -0
  312. data/src/toxi/processing/POVInterface.java +121 -0
  313. data/src/toxi/processing/POVMesh.java +219 -0
  314. data/src/toxi/processing/POVWriter.java +460 -0
  315. data/src/toxi/processing/RCOpaque.java +77 -0
  316. data/src/toxi/processing/RCTransp.java +78 -0
  317. data/src/toxi/processing/TextureBuilder.java +232 -0
  318. data/src/toxi/processing/Textures.java +110 -0
  319. data/src/toxi/processing/ToxiclibsSupport.java +1239 -0
  320. data/src/toxi/processing/Tracing.java +25 -0
  321. data/src/toxi/processing/XYZNormalMapper.java +30 -0
  322. data/src/toxi/sim/automata/CAMatrix.java +297 -0
  323. data/src/toxi/sim/automata/CARule.java +76 -0
  324. data/src/toxi/sim/automata/CARule2D.java +354 -0
  325. data/src/toxi/sim/automata/CAWolfram1D.java +309 -0
  326. data/src/toxi/sim/automata/EvolvableMatrix.java +61 -0
  327. data/src/toxi/sim/automata/MatrixEvolver.java +42 -0
  328. data/src/toxi/sim/dla/BottomUpOrder.java +76 -0
  329. data/src/toxi/sim/dla/DLA.java +497 -0
  330. data/src/toxi/sim/dla/DLAConfiguration.java +364 -0
  331. data/src/toxi/sim/dla/DLAEventAdapter.java +64 -0
  332. data/src/toxi/sim/dla/DLAEventListener.java +57 -0
  333. data/src/toxi/sim/dla/DLAGuideLines.java +219 -0
  334. data/src/toxi/sim/dla/DLAParticle.java +102 -0
  335. data/src/toxi/sim/dla/DLASegment.java +88 -0
  336. data/src/toxi/sim/dla/PipelineOrder.java +50 -0
  337. data/src/toxi/sim/dla/RadialDistanceOrder.java +92 -0
  338. data/src/toxi/sim/erosion/ErosionFunction.java +122 -0
  339. data/src/toxi/sim/erosion/TalusAngleErosion.java +145 -0
  340. data/src/toxi/sim/erosion/ThermalErosion.java +75 -0
  341. data/src/toxi/sim/fluids/FluidSolver2D.java +762 -0
  342. data/src/toxi/sim/fluids/FluidSolver3D.java +326 -0
  343. data/src/toxi/sim/grayscott/GrayScott.java +469 -0
  344. data/src/toxi/util/DateUtils.java +141 -0
  345. data/src/toxi/util/FileSequenceDescriptor.java +181 -0
  346. data/src/toxi/util/FileUtils.java +467 -0
  347. data/src/toxi/util/datatypes/ArraySet.java +128 -0
  348. data/src/toxi/util/datatypes/ArrayUtil.java +404 -0
  349. data/src/toxi/util/datatypes/BiasedDoubleRange.java +141 -0
  350. data/src/toxi/util/datatypes/BiasedFloatRange.java +141 -0
  351. data/src/toxi/util/datatypes/BiasedIntegerRange.java +141 -0
  352. data/src/toxi/util/datatypes/DoubleRange.java +251 -0
  353. data/src/toxi/util/datatypes/FloatRange.java +251 -0
  354. data/src/toxi/util/datatypes/GenericSet.java +215 -0
  355. data/src/toxi/util/datatypes/IntegerRange.java +247 -0
  356. data/src/toxi/util/datatypes/IntegerSet.java +149 -0
  357. data/src/toxi/util/datatypes/ItemIndex.java +72 -0
  358. data/src/toxi/util/datatypes/SingletonRegistry.java +91 -0
  359. data/src/toxi/util/datatypes/TypedProperties.java +291 -0
  360. data/src/toxi/util/datatypes/UndirectedGraph.java +134 -0
  361. data/src/toxi/util/datatypes/UniqueItemIndex.java +223 -0
  362. data/src/toxi/util/datatypes/WeightedRandomEntry.java +76 -0
  363. data/src/toxi/util/datatypes/WeightedRandomSet.java +125 -0
  364. data/src/toxi/util/events/EventDispatcher.java +86 -0
  365. data/src/toxi/volume/AdditiveBrush.java +19 -0
  366. data/src/toxi/volume/ArrayIsoSurface.java +297 -0
  367. data/src/toxi/volume/BoxBrush.java +100 -0
  368. data/src/toxi/volume/BrushMode.java +16 -0
  369. data/src/toxi/volume/HashIsoSurface.java +354 -0
  370. data/src/toxi/volume/IsoSurface.java +59 -0
  371. data/src/toxi/volume/MarchingCubesIndex.java +312 -0
  372. data/src/toxi/volume/MeshLatticeBuilder.java +358 -0
  373. data/src/toxi/volume/MeshVoxelizer.java +216 -0
  374. data/src/toxi/volume/MultiplyBrush.java +20 -0
  375. data/src/toxi/volume/PeakBrush.java +21 -0
  376. data/src/toxi/volume/ReplaceBrush.java +19 -0
  377. data/src/toxi/volume/RoundBrush.java +113 -0
  378. data/src/toxi/volume/VolumetricBrush.java +160 -0
  379. data/src/toxi/volume/VolumetricHashMap.java +179 -0
  380. data/src/toxi/volume/VolumetricSpace.java +195 -0
  381. data/src/toxi/volume/VolumetricSpaceArray.java +214 -0
  382. data/toxiclibs.gemspec +34 -0
  383. metadata +424 -27
@@ -0,0 +1,2599 @@
1
+ /*
2
+ * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
3
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
+ *
5
+ * This code is free software; you can redistribute it and/or modify it
6
+ * under the terms of the GNU General Public License version 2 only, as
7
+ * published by the Free Software Foundation. Sun designates this
8
+ * particular file as subject to the "Classpath" exception as provided
9
+ * by Sun in the LICENSE file that accompanied this code.
10
+ *
11
+ * This code is distributed in the hope that it will be useful, but WITHOUT
12
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
+ * version 2 for more details (a copy is included in the LICENSE file that
15
+ * accompanied this code).
16
+ *
17
+ * You should have received a copy of the GNU General Public License version
18
+ * 2 along with this work; if not, write to the Free Software Foundation,
19
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
+ *
21
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22
+ * CA 95054 USA or visit www.sun.com if you need additional information or
23
+ * have any questions.
24
+ */
25
+ package toxi.geom;
26
+
27
+ import java.util.Arrays;
28
+ import toxi.math.MathUtils;
29
+
30
+ /**
31
+ * A double precision, row major, general and dynamically-resizable,
32
+ * two-dimensional matrix class. Row and column numbering begins with zero.
33
+ */
34
+ public class GMatrix implements java.io.Serializable, Cloneable {
35
+
36
+ static final long serialVersionUID = 1L;
37
+
38
+ /**
39
+ * Solves a set of linear equations. The input parameters "matrix1", and
40
+ * "row_perm" come from luDecompostion and do not change here. The parameter
41
+ * "matrix2" is a set of column vectors assembled into a nxn matrix of
42
+ * floating-point values. The procedure takes each column of "matrix2" in
43
+ * turn and treats it as the right-hand side of the matrix equation Ax = LUx
44
+ * = b. The solution vector replaces the original column of the matrix.
45
+ *
46
+ * If "matrix2" is the identity matrix, the procedure replaces its contents
47
+ * with the inverse of the matrix from which "matrix1" was originally
48
+ * derived.
49
+ *
50
+ * @param dim
51
+ * @param matrix1
52
+ * @param row_perm
53
+ * @param matrix2
54
+ */
55
+ //
56
+ // Reference: Press, Flannery, Teukolsky, Vetterling,
57
+ // _Numerical_Recipes_in_C_, Cambridge University Press,
58
+ // 1988, pp 44-45.
59
+ //
60
+ public static void backSubstituteLU(int dim, double[] matrix1,
61
+ int[] row_perm, double[] matrix2) {
62
+
63
+ int i, ii, ip, j, k;
64
+ int rp;
65
+ int cv, rv, ri;
66
+ double tt;
67
+
68
+ // rp = row_perm;
69
+ rp = 0;
70
+
71
+ // For each column vector of matrix2 ...
72
+ for (k = 0; k < dim; k++) {
73
+ // cv = &(matrix2[0][k]);
74
+ cv = k;
75
+ ii = -1;
76
+
77
+ // Forward substitution
78
+ for (i = 0; i < dim; i++) {
79
+ double sum;
80
+
81
+ ip = row_perm[rp + i];
82
+ sum = matrix2[cv + dim * ip];
83
+ matrix2[cv + dim * ip] = matrix2[cv + dim * i];
84
+ if (ii >= 0) {
85
+ // rv = &(matrix1[i][0]);
86
+ rv = i * dim;
87
+ for (j = ii; j <= i - 1; j++) {
88
+ sum -= matrix1[rv + j] * matrix2[cv + dim * j];
89
+ }
90
+ } else if (sum != 0.0) {
91
+ ii = i;
92
+ }
93
+ matrix2[cv + dim * i] = sum;
94
+ }
95
+
96
+ // Backsubstitution
97
+ for (i = 0; i < dim; i++) {
98
+ ri = (dim - 1 - i);
99
+ rv = dim * (ri);
100
+ tt = 0.0;
101
+ for (j = 1; j <= i; j++) {
102
+ tt += matrix1[rv + dim - j] * matrix2[cv + dim * (dim - j)];
103
+ }
104
+ matrix2[cv + dim * ri] = (matrix2[cv + dim * ri] - tt)
105
+ / matrix1[rv + ri];
106
+ }
107
+ }
108
+ }
109
+
110
+ private static void chase_across(double[] s, double[] e, int k, GMatrix u) {
111
+ double f, g, r;
112
+ double[] cosl = new double[1];
113
+ double[] sinl = new double[1];
114
+ int i;
115
+ GMatrix t = new GMatrix(u.nRow, u.nCol);
116
+ GMatrix m = new GMatrix(u.nRow, u.nCol);
117
+
118
+ g = e[k];
119
+ f = s[k + 1];
120
+
121
+ for (i = k; i < u.nCol - 2; i++) {
122
+ r = compute_rot(f, g, sinl, cosl);
123
+ g = -e[i + 1] * sinl[0];
124
+ f = s[i + 2];
125
+ s[i + 1] = r;
126
+ e[i + 1] = e[i + 1] * cosl[0];
127
+ update_u_split(k, i + 1, u, cosl, sinl, t, m);
128
+ }
129
+
130
+ s[i + 1] = compute_rot(f, g, sinl, cosl);
131
+ update_u_split(k, i + 1, u, cosl, sinl, t, m);
132
+ }
133
+
134
+ private static void chase_up(double[] s, double[] e, int k, GMatrix v) {
135
+ double f, g, r;
136
+ double[] cosr = new double[1];
137
+ double[] sinr = new double[1];
138
+ int i;
139
+ GMatrix t = new GMatrix(v.nRow, v.nCol);
140
+ GMatrix m = new GMatrix(v.nRow, v.nCol);
141
+
142
+ f = e[k];
143
+ g = s[k];
144
+
145
+ for (i = k; i > 0; i--) {
146
+ r = compute_rot(f, g, sinr, cosr);
147
+ f = -e[i - 1] * sinr[0];
148
+ g = s[i - 1];
149
+ s[i] = r;
150
+ e[i - 1] = e[i - 1] * cosr[0];
151
+ update_v_split(i, k + 1, v, cosr, sinr, t, m);
152
+ }
153
+
154
+ s[i + 1] = compute_rot(f, g, sinr, cosr);
155
+ update_v_split(i, k + 1, v, cosr, sinr, t, m);
156
+ }
157
+
158
+ private static void checkMatrix(GMatrix m) {
159
+ int i, j;
160
+
161
+ for (i = 0; i < m.nRow; i++) {
162
+ for (j = 0; j < m.nCol; j++) {
163
+ if (MathUtils.abs(m.values[i][j]) < 0.0000000001) {
164
+ System.out.print(" 0.0 ");
165
+ } else {
166
+ System.out.print(" " + m.values[i][j]);
167
+ }
168
+ }
169
+ System.out.print("\n");
170
+ }
171
+ }
172
+
173
+ private static int compute_2X2(double f, double g, double h,
174
+ double[] single_values, double[] snl, double[] csl, double[] snr,
175
+ double[] csr, int index) {
176
+
177
+ double c_b3 = 2.0;
178
+ double c_b4 = 1.0;
179
+
180
+ double d__1;
181
+ int pmax;
182
+ double temp;
183
+ boolean swap;
184
+ double a, d, l, m, r, s, t, tsign, fa, ga, ha;
185
+ double ft, gt, ht, mm;
186
+ boolean gasmal;
187
+ double tt, clt, crt, slt, srt;
188
+ double ssmin, ssmax;
189
+
190
+ ssmax = single_values[0];
191
+ ssmin = single_values[1];
192
+ clt = 0.0;
193
+ crt = 0.0;
194
+ slt = 0.0;
195
+ srt = 0.0;
196
+ tsign = 0.0;
197
+
198
+ ft = f;
199
+ fa = MathUtils.abs(ft);
200
+ ht = h;
201
+ ha = MathUtils.abs(h);
202
+
203
+ pmax = 1;
204
+ swap = ha > fa;
205
+
206
+ if (swap) {
207
+ pmax = 3;
208
+ temp = ft;
209
+ ft = ht;
210
+ ht = temp;
211
+ temp = fa;
212
+ fa = ha;
213
+ ha = temp;
214
+
215
+ }
216
+
217
+ gt = g;
218
+ ga = MathUtils.abs(gt);
219
+ if (ga == 0.0) {
220
+ single_values[1] = ha;
221
+ single_values[0] = fa;
222
+ clt = 1.0;
223
+ crt = 1.0;
224
+ slt = 0.0;
225
+ srt = 0.0;
226
+ } else {
227
+ gasmal = true;
228
+ if (ga > fa) {
229
+ pmax = 2;
230
+ if (fa / ga < EPS) {
231
+ gasmal = false;
232
+ ssmax = ga;
233
+
234
+ if (ha > 1.0) {
235
+ ssmin = fa / (ga / ha);
236
+ } else {
237
+ ssmin = fa / ga * ha;
238
+ }
239
+ clt = 1.0;
240
+ slt = ht / gt;
241
+ srt = 1.0;
242
+ crt = ft / gt;
243
+ }
244
+ }
245
+ if (gasmal) {
246
+ d = fa - ha;
247
+ if (d == fa) {
248
+
249
+ l = 1.0;
250
+ } else {
251
+ l = d / fa;
252
+ }
253
+
254
+ m = gt / ft;
255
+ t = 2.0 - l;
256
+ mm = m * m;
257
+ tt = t * t;
258
+ s = Math.sqrt(tt + mm);
259
+
260
+ if (l == 0.0) {
261
+ r = MathUtils.abs(m);
262
+ } else {
263
+ r = Math.sqrt(l * l + mm);
264
+ }
265
+
266
+ a = (s + r) * 0.5;
267
+ if (ga > fa) {
268
+ pmax = 2;
269
+ if (fa / ga < EPS) {
270
+ gasmal = false;
271
+ ssmax = ga;
272
+ if (ha > 1.0) {
273
+ ssmin = fa / (ga / ha);
274
+ } else {
275
+ ssmin = fa / ga * ha;
276
+ }
277
+ clt = 1.0;
278
+ slt = ht / gt;
279
+ srt = 1.0;
280
+ crt = ft / gt;
281
+ }
282
+ }
283
+ if (gasmal) {
284
+ d = fa - ha;
285
+ if (d == fa) {
286
+ l = 1.0;
287
+ } else {
288
+ l = d / fa;
289
+ }
290
+
291
+ m = gt / ft;
292
+ t = 2.0 - l;
293
+
294
+ mm = m * m;
295
+ tt = t * t;
296
+ s = Math.sqrt(tt + mm);
297
+
298
+ if (l == 0.) {
299
+ r = MathUtils.abs(m);
300
+ } else {
301
+ r = Math.sqrt(l * l + mm);
302
+ }
303
+
304
+ a = (s + r) * 0.5;
305
+ ssmin = ha / a;
306
+ ssmax = fa * a;
307
+
308
+ if (mm == 0.0) {
309
+ if (l == 0.0) {
310
+ t = MathUtils.dualSign(c_b3, ft)
311
+ * MathUtils.dualSign(c_b4, gt);
312
+ } else {
313
+ t = gt / MathUtils.dualSign(d, ft) + m / t;
314
+ }
315
+ } else {
316
+ t = (m / (s + t) + m / (r + l)) * (a + 1.0);
317
+ }
318
+
319
+ l = Math.sqrt(t * t + 4.0);
320
+ crt = 2.0 / l;
321
+ srt = t / l;
322
+ clt = (crt + srt * m) / a;
323
+ slt = ht / ft * srt / a;
324
+ }
325
+ }
326
+ if (swap) {
327
+ csl[0] = srt;
328
+ snl[0] = crt;
329
+ csr[0] = slt;
330
+ snr[0] = clt;
331
+ } else {
332
+ csl[0] = clt;
333
+ snl[0] = slt;
334
+ csr[0] = crt;
335
+ snr[0] = srt;
336
+ }
337
+
338
+ if (pmax == 1) {
339
+ tsign = MathUtils.dualSign(c_b4, csr[0])
340
+ * MathUtils.dualSign(c_b4, csl[0])
341
+ * MathUtils.dualSign(c_b4, f);
342
+ }
343
+ if (pmax == 2) {
344
+ tsign = MathUtils.dualSign(c_b4, snr[0])
345
+ * MathUtils.dualSign(c_b4, csl[0])
346
+ * MathUtils.dualSign(c_b4, g);
347
+ }
348
+ if (pmax == 3) {
349
+ tsign = MathUtils.dualSign(c_b4, snr[0])
350
+ * MathUtils.dualSign(c_b4, snl[0])
351
+ * MathUtils.dualSign(c_b4, h);
352
+ }
353
+
354
+ single_values[index] = MathUtils.dualSign(ssmax, tsign);
355
+ d__1 = tsign * MathUtils.dualSign(c_b4, f)
356
+ * MathUtils.dualSign(c_b4, h);
357
+ single_values[index + 1] = MathUtils.dualSign(ssmin, d__1);
358
+ }
359
+
360
+ return 0;
361
+ }
362
+
363
+ private static double compute_rot(double f, double g, double[] sin,
364
+ double[] cos) {
365
+ double cs, sn;
366
+ int i;
367
+ double scale;
368
+ int count;
369
+ double f1, g1;
370
+ double r;
371
+ final double safmn2 = 2.002083095183101E-146;
372
+ final double safmx2 = 4.994797680505588E+145;
373
+
374
+ if (g == 0.0) {
375
+ cs = 1.0;
376
+ sn = 0.0;
377
+ r = f;
378
+ } else if (f == 0.0) {
379
+ cs = 0.0;
380
+ sn = 1.0;
381
+ r = g;
382
+ } else {
383
+ f1 = f;
384
+ g1 = g;
385
+ scale = MathUtils.max(MathUtils.abs(f1), MathUtils.abs(g1));
386
+ if (scale >= safmx2) {
387
+ count = 0;
388
+ while (scale >= safmx2) {
389
+ ++count;
390
+ f1 *= safmn2;
391
+ g1 *= safmn2;
392
+ scale = MathUtils.max(MathUtils.abs(f1), MathUtils.abs(g1));
393
+ }
394
+ r = Math.sqrt(f1 * f1 + g1 * g1);
395
+ cs = f1 / r;
396
+ sn = g1 / r;
397
+ for (i = 1; i <= count; ++i) {
398
+ r *= safmx2;
399
+ }
400
+ } else if (scale <= safmn2) {
401
+ count = 0;
402
+ while (scale <= safmn2) {
403
+ ++count;
404
+ f1 *= safmx2;
405
+ g1 *= safmx2;
406
+ scale = MathUtils.max(MathUtils.abs(f1), MathUtils.abs(g1));
407
+ }
408
+ r = Math.sqrt(f1 * f1 + g1 * g1);
409
+ cs = f1 / r;
410
+ sn = g1 / r;
411
+ for (i = 1; i <= count; ++i) {
412
+ r *= safmn2;
413
+ }
414
+ } else {
415
+ r = Math.sqrt(f1 * f1 + g1 * g1);
416
+ cs = f1 / r;
417
+ sn = g1 / r;
418
+ }
419
+ if (MathUtils.abs(f) > MathUtils.abs(g) && cs < 0.0) {
420
+ cs = -cs;
421
+ sn = -sn;
422
+ r = -r;
423
+ }
424
+ }
425
+ sin[0] = sn;
426
+ cos[0] = cs;
427
+ return r;
428
+ }
429
+
430
+ private static double compute_shift(double f, double g, double h) {
431
+ double d__1, d__2;
432
+ double fhmn, fhmx, c, fa, ga, ha, as, at, au;
433
+ double ssmin;
434
+
435
+ fa = MathUtils.abs(f);
436
+ ga = MathUtils.abs(g);
437
+ ha = MathUtils.abs(h);
438
+ fhmn = MathUtils.min(fa, ha);
439
+ fhmx = MathUtils.max(fa, ha);
440
+
441
+ if (fhmn == 0.0) {
442
+ ssmin = 0.0;
443
+ if (fhmx == 0.0) {
444
+ } else {
445
+ d__1 = MathUtils.min(fhmx, ga) / MathUtils.max(fhmx, ga);
446
+ }
447
+ } else {
448
+ if (ga < fhmx) {
449
+ as = fhmn / fhmx + 1.0;
450
+ at = (fhmx - fhmn) / fhmx;
451
+ d__1 = ga / fhmx;
452
+ au = d__1 * d__1;
453
+ c = 2.0 / (Math.sqrt(as * as + au) + Math.sqrt(at * at + au));
454
+ ssmin = fhmn * c;
455
+ } else {
456
+ au = fhmx / ga;
457
+ if (au == 0.0) {
458
+ ssmin = fhmn * fhmx / ga;
459
+ } else {
460
+ as = fhmn / fhmx + 1.0;
461
+ at = (fhmx - fhmn) / fhmx;
462
+ d__1 = as * au;
463
+ d__2 = at * au;
464
+ c = 1.0 / (Math.sqrt(d__1 * d__1 + 1.0) + Math.sqrt(d__2
465
+ * d__2 + 1.0));
466
+ ssmin = fhmn * c * au;
467
+ ssmin += ssmin;
468
+ }
469
+ }
470
+ }
471
+
472
+ return ssmin;
473
+ }
474
+
475
+ /**
476
+ *
477
+ * @param start
478
+ * @param end
479
+ * @param s
480
+ * @param e
481
+ * @param u
482
+ * @param v
483
+ */
484
+ public static void computeQR(int start, int end, double[] s, double[] e,
485
+ GMatrix u, GMatrix v) {
486
+
487
+ int i, k, n, sl;
488
+ double shift, r, f, g;
489
+ double[] cosl = new double[1];
490
+ double[] cosr = new double[1];
491
+ double[] sinl = new double[1];
492
+ double[] sinr = new double[1];
493
+
494
+ final int MAX_INTERATIONS = 2;
495
+ final double CONVERGE_TOL = 4.89E-15;
496
+
497
+ boolean converged = false;
498
+
499
+ f = 0.0;
500
+ g = 0.0;
501
+
502
+ for (k = 0; k < MAX_INTERATIONS && !converged; k++) {
503
+ for (i = start; i <= end; i++) {
504
+
505
+ // if at start of iterfaction compute shift
506
+ if (i == start) {
507
+ if (e.length == s.length) {
508
+ sl = end;
509
+ } else {
510
+ sl = end + 1;
511
+ }
512
+
513
+ shift = compute_shift(s[sl - 1], e[end], s[sl]);
514
+
515
+ f = (MathUtils.abs(s[i]) - shift)
516
+ * (MathUtils.dualSign(1.0, s[i]) + shift / s[i]);
517
+ g = e[i];
518
+ }
519
+
520
+ r = compute_rot(f, g, sinr, cosr);
521
+ if (i != start) {
522
+ e[i - 1] = r;
523
+ }
524
+
525
+ f = cosr[0] * s[i] + sinr[0] * e[i];
526
+ e[i] = cosr[0] * e[i] - sinr[0] * s[i];
527
+ g = sinr[0] * s[i + 1];
528
+ s[i + 1] = cosr[0] * s[i + 1];
529
+
530
+ update_v(i, v, cosr, sinr);
531
+
532
+ r = compute_rot(f, g, sinl, cosl);
533
+ s[i] = r;
534
+ f = cosl[0] * e[i] + sinl[0] * s[i + 1];
535
+ s[i + 1] = cosl[0] * s[i + 1] - sinl[0] * e[i];
536
+
537
+ if (i < end) {
538
+ // if not last
539
+ g = sinl[0] * e[i + 1];
540
+ e[i + 1] = cosl[0] * e[i + 1];
541
+ }
542
+ update_u(i, u, cosl, sinl);
543
+ }
544
+
545
+ // if extra off diagonal perform one more right side rotation
546
+ if (s.length == e.length) {
547
+ r = compute_rot(f, g, sinr, cosr);
548
+ f = cosr[0] * s[i] + sinr[0] * e[i];
549
+ e[i] = cosr[0] * e[i] - sinr[0] * s[i];
550
+ s[i + 1] = cosr[0] * s[i + 1];
551
+
552
+ update_v(i, v, cosr, sinr);
553
+ }
554
+
555
+ // check for convergence on off diagonals and reduce
556
+ while ((end - start > 1) && (MathUtils.abs(e[end]) < CONVERGE_TOL)) {
557
+ end--;
558
+ }
559
+
560
+ // check if need to split
561
+ for (n = end - 2; n > start; n--) {
562
+ if (MathUtils.abs(e[n]) < CONVERGE_TOL) { // split
563
+ computeQR(n + 1, end, s, e, u, v); // do lower matrix
564
+ end = n - 1; // do upper matrix
565
+
566
+ // check for convergence on off diagonals and reduce
567
+ while ((end - start > 1)
568
+ && (MathUtils.abs(e[end]) < CONVERGE_TOL)) {
569
+ end--;
570
+ }
571
+ }
572
+ }
573
+
574
+ if ((end - start <= 1)
575
+ && (MathUtils.abs(e[start + 1]) < CONVERGE_TOL)) {
576
+ converged = true;
577
+ } else {
578
+ // check if zero on the diagonal
579
+ }
580
+
581
+ }
582
+
583
+ if (MathUtils.abs(e[1]) < CONVERGE_TOL) {
584
+ compute_2X2(s[start], e[start], s[start + 1], s, sinl, cosl, sinr,
585
+ cosr, 0);
586
+ e[start] = 0.0;
587
+ e[start + 1] = 0.0;
588
+ }
589
+
590
+ i = start;
591
+ update_u(i, u, cosl, sinl);
592
+ update_v(i, v, cosr, sinr);
593
+ }
594
+
595
+ /**
596
+ *
597
+ * @param mat
598
+ * @param U
599
+ * @param W
600
+ * @param V
601
+ * @return
602
+ */
603
+ public static int computeSVD(GMatrix mat, GMatrix U, GMatrix W, GMatrix V) {
604
+ int i, j, k;
605
+ int nr, nc, si;
606
+
607
+ int rank;
608
+ double mag, scale, t;
609
+ int eLength, sLength, vecLength;
610
+
611
+ GMatrix tmp = new GMatrix(mat.nRow, mat.nCol);
612
+ GMatrix u = new GMatrix(mat.nRow, mat.nCol);
613
+ GMatrix v = new GMatrix(mat.nRow, mat.nCol);
614
+ GMatrix m = new GMatrix(mat);
615
+
616
+ // compute the number of singular values
617
+ if (m.nRow >= m.nCol) {
618
+ sLength = m.nCol;
619
+ eLength = m.nCol - 1;
620
+ } else {
621
+ sLength = m.nRow;
622
+ eLength = m.nRow;
623
+ }
624
+
625
+ if (m.nRow > m.nCol) {
626
+ vecLength = m.nRow;
627
+ } else {
628
+ vecLength = m.nCol;
629
+ }
630
+
631
+ double[] vec = new double[vecLength];
632
+ double[] single_values = new double[sLength];
633
+ double[] e = new double[eLength];
634
+
635
+ rank = 0;
636
+
637
+ U.identity();
638
+ V.identity();
639
+
640
+ nr = m.nRow;
641
+ nc = m.nCol;
642
+
643
+ // householder reduction
644
+ for (si = 0; si < sLength; si++) {
645
+ // for each singular value
646
+
647
+ if (nr > 1) {
648
+ // compute reflector
649
+ mag = 0.0;
650
+ for (i = 0; i < nr; i++) {
651
+ mag += m.values[i + si][si] * m.values[i + si][si];
652
+ }
653
+
654
+ mag = Math.sqrt(mag);
655
+ if (m.values[si][si] == 0.0) {
656
+ vec[0] = mag;
657
+ } else {
658
+ vec[0] = m.values[si][si]
659
+ + MathUtils.dualSign(mag, m.values[si][si]);
660
+ }
661
+
662
+ for (i = 1; i < nr; i++) {
663
+ vec[i] = m.values[si + i][si];
664
+ }
665
+
666
+ scale = 0.0;
667
+ for (i = 0; i < nr; i++) {
668
+ scale += vec[i] * vec[i];
669
+ }
670
+
671
+ scale = 2.0 / scale;
672
+ for (j = si; j < m.nRow; j++) {
673
+ for (k = si; k < m.nRow; k++) {
674
+ u.values[j][k] = -scale * vec[j - si] * vec[k - si];
675
+ }
676
+ }
677
+
678
+ for (i = si; i < m.nRow; i++) {
679
+ u.values[i][i] += 1.0;
680
+ }
681
+
682
+ // compute s
683
+ t = 0.0;
684
+ for (i = si; i < m.nRow; i++) {
685
+ t += u.values[si][i] * m.values[i][si];
686
+ }
687
+ m.values[si][si] = t;
688
+
689
+ // apply reflector
690
+ for (j = si; j < m.nRow; j++) {
691
+ for (k = si + 1; k < m.nCol; k++) {
692
+ tmp.values[j][k] = 0.0;
693
+ for (i = si; i < m.nCol; i++) {
694
+ tmp.values[j][k] += u.values[j][i] * m.values[i][k];
695
+ }
696
+ }
697
+ }
698
+
699
+ for (j = si; j < m.nRow; j++) {
700
+ for (k = si + 1; k < m.nCol; k++) {
701
+ m.values[j][k] = tmp.values[j][k];
702
+ }
703
+ }
704
+
705
+ // update U matrix
706
+ for (j = si; j < m.nRow; j++) {
707
+ for (k = 0; k < m.nCol; k++) {
708
+ tmp.values[j][k] = 0.0;
709
+ for (i = si; i < m.nCol; i++) {
710
+ tmp.values[j][k] += u.values[j][i] * U.values[i][k];
711
+ }
712
+ }
713
+ }
714
+
715
+ for (j = si; j < m.nRow; j++) {
716
+ for (k = 0; k < m.nCol; k++) {
717
+ U.values[j][k] = tmp.values[j][k];
718
+ }
719
+ }
720
+ nr--;
721
+ }
722
+
723
+ if (nc > 2) {
724
+ mag = 0.0;
725
+ for (i = 1; i < nc; i++) {
726
+ mag += m.values[si][si + i] * m.values[si][si + i];
727
+ }
728
+ // generate the reflection vector, compute the first entry and
729
+ // copy the rest from the row to be zeroed
730
+ mag = Math.sqrt(mag);
731
+ if (m.values[si][si + 1] == 0.0) {
732
+ vec[0] = mag;
733
+ } else {
734
+ vec[0] = m.values[si][si + 1]
735
+ + MathUtils.dualSign(mag, m.values[si][si + 1]);
736
+ }
737
+
738
+ for (i = 1; i < nc - 1; i++) {
739
+ vec[i] = m.values[si][si + i + 1];
740
+ }
741
+
742
+ // use reflection vector to compute v matrix
743
+ scale = 0.0;
744
+ for (i = 0; i < nc - 1; i++) {
745
+ scale += vec[i] * vec[i];
746
+ }
747
+
748
+ scale = 2.0 / scale;
749
+ for (j = si + 1; j < nc; j++) {
750
+ for (k = si + 1; k < m.nCol; k++) {
751
+ v.values[j][k] = -scale * vec[j - si - 1]
752
+ * vec[k - si - 1];
753
+ }
754
+ }
755
+
756
+ for (i = si + 1; i < m.nCol; i++) {
757
+ v.values[i][i] += 1.0;
758
+ }
759
+
760
+ t = 0.0;
761
+ for (i = si; i < m.nCol; i++) {
762
+ t += v.values[i][si + 1] * m.values[si][i];
763
+ }
764
+ m.values[si][si + 1] = t;
765
+
766
+ // apply reflector
767
+ for (j = si + 1; j < m.nRow; j++) {
768
+ for (k = si + 1; k < m.nCol; k++) {
769
+ tmp.values[j][k] = 0.0;
770
+ for (i = si + 1; i < m.nCol; i++) {
771
+ tmp.values[j][k] += v.values[i][k] * m.values[j][i];
772
+ }
773
+ }
774
+ }
775
+
776
+ for (j = si + 1; j < m.nRow; j++) {
777
+ for (k = si + 1; k < m.nCol; k++) {
778
+ m.values[j][k] = tmp.values[j][k];
779
+ }
780
+ }
781
+
782
+ // update V matrix
783
+ for (j = 0; j < m.nRow; j++) {
784
+ for (k = si + 1; k < m.nCol; k++) {
785
+ tmp.values[j][k] = 0.0;
786
+ for (i = si + 1; i < m.nCol; i++) {
787
+ tmp.values[j][k] += v.values[i][k] * V.values[j][i];
788
+ }
789
+ }
790
+ }
791
+
792
+ for (j = 0; j < m.nRow; j++) {
793
+ for (k = si + 1; k < m.nCol; k++) {
794
+ V.values[j][k] = tmp.values[j][k];
795
+ }
796
+ }
797
+ nc--;
798
+ }
799
+ }
800
+
801
+ for (i = 0; i < sLength; i++) {
802
+ single_values[i] = m.values[i][i];
803
+ }
804
+
805
+ for (i = 0; i < eLength; i++) {
806
+ e[i] = m.values[i][i + 1];
807
+ }
808
+
809
+ // Fix ArrayIndexOutOfBounds for 2x2 matrices, which partially
810
+ // addresses bug 4348562 for J3D 1.2.1.
811
+ //
812
+ // Does *not* fix the following problems reported in 4348562,
813
+ // which will wait for J3D 1.3:
814
+ //
815
+ // 1) no output of W
816
+ // 2) wrong transposition of U
817
+ // 3) wrong results for 4x4 matrices
818
+ // 4) slow performance
819
+ if (m.nRow == 2 && m.nCol == 2) {
820
+ double[] cosl = new double[1];
821
+ double[] cosr = new double[1];
822
+ double[] sinl = new double[1];
823
+ double[] sinr = new double[1];
824
+
825
+ compute_2X2(single_values[0], e[0], single_values[1],
826
+ single_values, sinl, cosl, sinr, cosr, 0);
827
+
828
+ update_u(0, U, cosl, sinl);
829
+ update_v(0, V, cosr, sinr);
830
+ return 2;
831
+ }
832
+
833
+ // compute_qr causes ArrayIndexOutOfBounds for 2x2 matrices
834
+ computeQR(0, e.length - 1, single_values, e, U, V);
835
+
836
+ // compute rank = number of non zero singular values
837
+ rank = single_values.length;
838
+
839
+ // sort by order of size of single values
840
+ // and check for zero's
841
+ return rank;
842
+ }
843
+
844
+ /**
845
+ * Given a nxn array "matrix0", this function replaces it with the LU
846
+ * decomposition of a row-wise permutation of itself. The input parameters
847
+ * are "matrix0" and "dim". The array "matrix0" is also an output parameter.
848
+ * The vector "row_perm[]" is an output parameter that contains the row
849
+ * permutations resulting from partial pivoting. The output parameter
850
+ * "even_row_xchg" is 1 when the number of row exchanges is even, or -1
851
+ * otherwise. Assumes data type is always double.
852
+ *
853
+ * @param dim
854
+ * @param matrix0
855
+ * @param row_perm
856
+ * @param even_row_xchg
857
+ * @return true if the matrix is nonsingular, or false otherwise.
858
+ */
859
+ //
860
+ // Reference: Press, Flannery, Teukolsky, Vetterling,
861
+ // _Numerical_Recipes_in_C_, Cambridge University Press,
862
+ // 1988, pp 40-45.
863
+ //
864
+ public static boolean decomposeLU(int dim, double[] matrix0,
865
+ int[] row_perm, int[] even_row_xchg) {
866
+
867
+ double row_scale[] = new double[dim];
868
+
869
+ // Determine implicit scaling information by looping over rows
870
+ int i, j;
871
+ int ptr, rs, mtx;
872
+ double big, temp;
873
+
874
+ ptr = 0;
875
+ rs = 0;
876
+ even_row_xchg[0] = 1;
877
+
878
+ // For each row ...
879
+ i = dim;
880
+ while (i-- != 0) {
881
+ big = 0.0;
882
+
883
+ // For each column, find the largest element in the row
884
+ j = dim;
885
+ while (j-- != 0) {
886
+ temp = matrix0[ptr++];
887
+ temp = MathUtils.abs(temp);
888
+ if (temp > big) {
889
+ big = temp;
890
+ }
891
+ }
892
+
893
+ // Is the matrix singular?
894
+ if (big == 0.0) {
895
+ return false;
896
+ }
897
+ row_scale[rs++] = 1.0 / big;
898
+ }
899
+
900
+ // For all columns, execute Crout's method
901
+ mtx = 0;
902
+ for (j = 0; j < dim; j++) {
903
+ int imax, k;
904
+ int target, p1, p2;
905
+ double sum;
906
+
907
+ // Determine elements of upper diagonal matrix U
908
+ for (i = 0; i < j; i++) {
909
+ target = mtx + (dim * i) + j;
910
+ sum = matrix0[target];
911
+ k = i;
912
+ p1 = mtx + (dim * i);
913
+ p2 = mtx + j;
914
+ while (k-- != 0) {
915
+ sum -= matrix0[p1] * matrix0[p2];
916
+ p1++;
917
+ p2 += dim;
918
+ }
919
+ matrix0[target] = sum;
920
+ }
921
+
922
+ // Search for largest pivot element and calculate
923
+ // intermediate elements of lower diagonal matrix L.
924
+ big = 0.0;
925
+ imax = -1;
926
+ for (i = j; i < dim; i++) {
927
+ target = mtx + (dim * i) + j;
928
+ sum = matrix0[target];
929
+ k = j;
930
+ p1 = mtx + (dim * i);
931
+ p2 = mtx + j;
932
+ while (k-- != 0) {
933
+ sum -= matrix0[p1] * matrix0[p2];
934
+ p1++;
935
+ p2 += dim;
936
+ }
937
+ matrix0[target] = sum;
938
+
939
+ // Is this the best pivot so far?
940
+ if ((temp = row_scale[i] * MathUtils.abs(sum)) >= big) {
941
+ big = temp;
942
+ imax = i;
943
+ }
944
+ }
945
+
946
+ if (imax < 0) {
947
+ throw new RuntimeException();
948
+ }
949
+
950
+ // Is a row exchange necessary?
951
+ if (j != imax) {
952
+ // Yes: exchange rows
953
+ k = dim;
954
+ p1 = mtx + (dim * imax);
955
+ p2 = mtx + (dim * j);
956
+ while (k-- != 0) {
957
+ temp = matrix0[p1];
958
+ matrix0[p1++] = matrix0[p2];
959
+ matrix0[p2++] = temp;
960
+ }
961
+
962
+ // Record change in scale factor
963
+ row_scale[imax] = row_scale[j];
964
+ even_row_xchg[0] = -even_row_xchg[0]; // change exchange parity
965
+ }
966
+
967
+ // Record row permutation
968
+ row_perm[j] = imax;
969
+
970
+ // Is the matrix singular
971
+ if (matrix0[(mtx + (dim * j) + j)] == 0.0) {
972
+ return false;
973
+ }
974
+
975
+ // Divide elements of lower diagonal matrix L by pivot
976
+ if (j != (dim - 1)) {
977
+ temp = 1.0 / (matrix0[(mtx + (dim * j) + j)]);
978
+ target = mtx + (dim * (j + 1)) + j;
979
+ i = (dim - 1) - j;
980
+ while (i-- != 0) {
981
+ matrix0[target] *= temp;
982
+ target += dim;
983
+ }
984
+ }
985
+
986
+ }
987
+
988
+ return true;
989
+ }
990
+
991
+ private static void print_m(GMatrix m, GMatrix u, GMatrix v) {
992
+ GMatrix mtmp = new GMatrix(m.nCol, m.nRow);
993
+
994
+ mtmp.mul(u, mtmp);
995
+ mtmp.mul(mtmp, v);
996
+ System.out.println("\n m = \n" + GMatrix.toString(mtmp));
997
+
998
+ }
999
+
1000
+ private static void print_se(double[] s, double[] e) {
1001
+ System.out.println("\ns =" + s[0] + " " + s[1] + " " + s[2]);
1002
+ System.out.println("e =" + e[0] + " " + e[1]);
1003
+ }
1004
+
1005
+ private static void print_svd(double[] s, double[] e, GMatrix u, GMatrix v) {
1006
+ int i;
1007
+ GMatrix mtmp = new GMatrix(u.nCol, v.nRow);
1008
+
1009
+ System.out.println(" \ns = ");
1010
+ for (i = 0; i < s.length; i++) {
1011
+ System.out.println(" " + s[i]);
1012
+ }
1013
+
1014
+ System.out.println(" \ne = ");
1015
+ for (i = 0; i < e.length; i++) {
1016
+ System.out.println(" " + e[i]);
1017
+ }
1018
+
1019
+ System.out.println(" \nu = \n" + u.toString());
1020
+ System.out.println(" \nv = \n" + v.toString());
1021
+
1022
+ mtmp.identity();
1023
+ for (i = 0; i < s.length; i++) {
1024
+ mtmp.values[i][i] = s[i];
1025
+ }
1026
+ for (i = 0; i < e.length; i++) {
1027
+ mtmp.values[i][i + 1] = e[i];
1028
+ }
1029
+ System.out.println(" \nm = \n" + mtmp.toString());
1030
+
1031
+ mtmp.mulTransposeLeft(u, mtmp);
1032
+ mtmp.mulTransposeRight(mtmp, v);
1033
+
1034
+ System.out.println(" \n u.transpose*m*v.transpose = \n"
1035
+ + mtmp.toString());
1036
+ }
1037
+
1038
+ private static String toString(GMatrix m) {
1039
+ StringBuilder buffer = new StringBuilder(m.nRow * m.nCol * 8);
1040
+ int i, j;
1041
+
1042
+ for (i = 0; i < m.nRow; i++) {
1043
+ for (j = 0; j < m.nCol; j++) {
1044
+ if (MathUtils.abs(m.values[i][j]) < MathUtils.EPS) {
1045
+ buffer.append("0.0000 ");
1046
+ } else {
1047
+ buffer.append(m.values[i][j]).append(" ");
1048
+ }
1049
+ }
1050
+ buffer.append("\n");
1051
+ }
1052
+ return buffer.toString();
1053
+ }
1054
+
1055
+ private static void update_u(int index, GMatrix u, double[] cosl,
1056
+ double[] sinl) {
1057
+ int j;
1058
+ double utemp;
1059
+
1060
+ for (j = 0; j < u.nCol; j++) {
1061
+ utemp = u.values[index][j];
1062
+ u.values[index][j] = cosl[0] * utemp + sinl[0]
1063
+ * u.values[index + 1][j];
1064
+ u.values[index + 1][j] = -sinl[0] * utemp + cosl[0]
1065
+ * u.values[index + 1][j];
1066
+ }
1067
+ }
1068
+
1069
+ private static void update_u_split(int topr, int bottomr, GMatrix u,
1070
+ double[] cosl, double[] sinl, GMatrix t, GMatrix m) {
1071
+ int j;
1072
+ double utemp;
1073
+
1074
+ for (j = 0; j < u.nCol; j++) {
1075
+ utemp = u.values[topr][j];
1076
+ u.values[topr][j] = cosl[0] * utemp - sinl[0]
1077
+ * u.values[bottomr][j];
1078
+ u.values[bottomr][j] = sinl[0] * utemp + cosl[0]
1079
+ * u.values[bottomr][j];
1080
+ }
1081
+
1082
+ checkMatrix(m);
1083
+ checkMatrix(t);
1084
+ m.mul(t, m);
1085
+ checkMatrix(m);
1086
+ }
1087
+
1088
+ private static void update_v(int index, GMatrix v, double[] cosr,
1089
+ double[] sinr) {
1090
+ int j;
1091
+ double vtemp;
1092
+
1093
+ for (j = 0; j < v.nRow; j++) {
1094
+ vtemp = v.values[j][index];
1095
+ v.values[j][index] = cosr[0] * vtemp + sinr[0]
1096
+ * v.values[j][index + 1];
1097
+ v.values[j][index + 1] = -sinr[0] * vtemp + cosr[0]
1098
+ * v.values[j][index + 1];
1099
+ }
1100
+ }
1101
+
1102
+ private static void update_v_split(int topr, int bottomr, GMatrix v,
1103
+ double[] cosr, double[] sinr, GMatrix t, GMatrix m) {
1104
+ int j;
1105
+ double vtemp;
1106
+
1107
+ for (j = 0; j < v.nRow; j++) {
1108
+ vtemp = v.values[j][topr];
1109
+ v.values[j][topr] = cosr[0] * vtemp - sinr[0]
1110
+ * v.values[j][bottomr];
1111
+ v.values[j][bottomr] = sinr[0] * vtemp + cosr[0]
1112
+ * v.values[j][bottomr];
1113
+ }
1114
+
1115
+ checkMatrix(m);
1116
+ checkMatrix(t);
1117
+ m.mul(m, t);
1118
+ checkMatrix(m);
1119
+ }
1120
+
1121
+ int nRow;
1122
+
1123
+ int nCol;
1124
+
1125
+ // double dereference is slow
1126
+ double[][] values;
1127
+
1128
+ private static final double EPS = 1.0E-10;
1129
+
1130
+ /**
1131
+ * Constructs a new GMatrix and copies the initial values from the parameter
1132
+ * matrix.
1133
+ *
1134
+ * @param matrix the source of the initial values of the new GMatrix
1135
+ */
1136
+ public GMatrix(GMatrix matrix) {
1137
+ nRow = matrix.nRow;
1138
+ nCol = matrix.nCol;
1139
+ values = new double[nRow][nCol];
1140
+
1141
+ int i, j;
1142
+ for (i = 0; i < nRow; i++) {
1143
+ for (j = 0; j < nCol; j++) {
1144
+ values[i][j] = matrix.values[i][j];
1145
+ }
1146
+ }
1147
+ }
1148
+
1149
+ /**
1150
+ * Constructs an nRow by NCol identity matrix. Note that because row and
1151
+ * column numbering begins with zero, nRow and nCol will be one larger than
1152
+ * the maximum possible matrix index values.
1153
+ *
1154
+ * @param nRow number of rows in this matrix.
1155
+ * @param nCol number of columns in this matrix.
1156
+ */
1157
+ public GMatrix(int nRow, int nCol) {
1158
+ values = new double[nRow][nCol];
1159
+ this.nRow = nRow;
1160
+ this.nCol = nCol;
1161
+
1162
+ int i, j;
1163
+ for (i = 0; i < nRow; i++) {
1164
+ for (j = 0; j < nCol; j++) {
1165
+ values[i][j] = 0.0;
1166
+ }
1167
+ }
1168
+
1169
+ int l;
1170
+ if (nRow < nCol) {
1171
+ l = nRow;
1172
+ } else {
1173
+ l = nCol;
1174
+ }
1175
+
1176
+ for (i = 0; i < l; i++) {
1177
+ values[i][i] = 1.0;
1178
+ }
1179
+ }
1180
+
1181
+ /**
1182
+ * Constructs an nRow by nCol matrix initialized to the values in the matrix
1183
+ * array. The array values are copied in one row at a time in row major
1184
+ * fashion. The array should be at least nRow*nCol in length. Note that
1185
+ * because row and column numbering begins with zero, nRow and nCol will be
1186
+ * one larger than the maximum possible matrix index values.
1187
+ *
1188
+ * @param nRow number of rows in this matrix.
1189
+ * @param nCol number of columns in this matrix.
1190
+ * @param matrix a 1D array that specifies a matrix in row major fashion
1191
+ */
1192
+ public GMatrix(int nRow, int nCol, double[] matrix) {
1193
+ values = new double[nRow][nCol];
1194
+ this.nRow = nRow;
1195
+ this.nCol = nCol;
1196
+
1197
+ int i, j;
1198
+ for (i = 0; i < nRow; i++) {
1199
+ for (j = 0; j < nCol; j++) {
1200
+ values[i][j] = matrix[i * nCol + j];
1201
+ }
1202
+ }
1203
+ }
1204
+
1205
+ /**
1206
+ * Sets the value of this matrix to sum of itself and matrix m1.
1207
+ *
1208
+ * @param m1 the other matrix
1209
+ */
1210
+ public final void add(GMatrix m1) {
1211
+ int i, j;
1212
+
1213
+ if (nRow != m1.nRow) {
1214
+ throw new MatrixSizeException();
1215
+ }
1216
+
1217
+ if (nCol != m1.nCol) {
1218
+ throw new MatrixSizeException();
1219
+ }
1220
+
1221
+ for (i = 0; i < nRow; i++) {
1222
+ for (j = 0; j < nCol; j++) {
1223
+ values[i][j] = values[i][j] + m1.values[i][j];
1224
+ }
1225
+ }
1226
+ }
1227
+
1228
+ /**
1229
+ * Sets the value of this matrix to the matrix sum of matrices m1 and m2.
1230
+ *
1231
+ * @param m1 the first matrix
1232
+ * @param m2 the second matrix
1233
+ */
1234
+ public final void add(GMatrix m1, GMatrix m2) {
1235
+ int i, j;
1236
+
1237
+ if (m2.nRow != m1.nRow) {
1238
+ throw new MatrixSizeException();
1239
+ }
1240
+
1241
+ if (m2.nCol != m1.nCol) {
1242
+ throw new MatrixSizeException();
1243
+ }
1244
+
1245
+ if (nCol != m1.nCol || nRow != m1.nRow) {
1246
+ throw new MatrixSizeException();
1247
+ }
1248
+
1249
+ for (i = 0; i < nRow; i++) {
1250
+ for (j = 0; j < nCol; j++) {
1251
+ values[i][j] = m1.values[i][j] + m2.values[i][j];
1252
+ }
1253
+ }
1254
+ }
1255
+
1256
+ /**
1257
+ * Creates a new object of the same class as this object.
1258
+ *
1259
+ * @return a clone of this instance.
1260
+ * @exception OutOfMemoryError if there is not enough memory.
1261
+ * @see java.lang.Cloneable
1262
+ * @since vecmath 1.3
1263
+ */
1264
+ // @Override
1265
+ // public Object clone() throws CloneNotSupportedException {
1266
+ // GMatrix m1 = null;
1267
+ // try {
1268
+ // m1 = (GMatrix) super.clone();
1269
+ // } catch (CloneNotSupportedException e) {
1270
+ // // this shouldn't happen, since we are Cloneable
1271
+ // throw new InternalError();
1272
+ // }
1273
+ //
1274
+ // // Also need to clone array of values
1275
+ // m1.values = new double[nRow][nCol];
1276
+ // for (int i = 0; i < nRow; i++) {
1277
+ // System.arraycopy(values[i], 0, m1.values[i], 0, nCol);
1278
+ // }
1279
+ //
1280
+ // return m1;
1281
+ // }
1282
+
1283
+ /**
1284
+ * LU Decomposition: this matrix must be a square matrix and the LU GMatrix
1285
+ * parameter must be the same size as this matrix. The matrix LU will be
1286
+ * overwritten as the combination of a lower diagonal and upper diagonal
1287
+ * matrix decompostion of this matrix; the diagonal elements of L (unity)
1288
+ * are not stored. The GVector parameter records the row permutation
1289
+ * effected by the partial pivoting, and is used as a parameter to the
1290
+ * GVector method LUDBackSolve to solve sets of linear equations. This
1291
+ * method returns +/- 1 depending on whether the number of row interchanges
1292
+ * was even or odd, respectively.
1293
+ *
1294
+ * @param LU The matrix into which the lower and upper decompositions will
1295
+ * be placed.
1296
+ * @param permutation The row permutation effected by the partial pivoting
1297
+ * @return +-1 depending on whether the number of row interchanges was even
1298
+ * or odd respectively
1299
+ */
1300
+ public final int computeLUD(GMatrix LU, GVector permutation) {
1301
+ int size = LU.nRow * LU.nCol;
1302
+ double[] temp = new double[size];
1303
+ int[] even_row_exchange = new int[1];
1304
+ int[] row_perm = new int[LU.nRow];
1305
+ int i, j;
1306
+
1307
+ if (nRow != nCol) {
1308
+ throw new MatrixSizeException();
1309
+ }
1310
+
1311
+ if (nRow != LU.nRow) {
1312
+ throw new MatrixSizeException();
1313
+ }
1314
+
1315
+ if (nCol != LU.nCol) {
1316
+ throw new MatrixSizeException();
1317
+ }
1318
+
1319
+ if (LU.nRow != permutation.size()) {
1320
+ throw new MatrixSizeException();
1321
+ }
1322
+
1323
+ for (i = 0; i < nRow; i++) {
1324
+ for (j = 0; j < nCol; j++) {
1325
+ temp[i * nCol + j] = values[i][j];
1326
+ }
1327
+ }
1328
+
1329
+ // Calculate LU decomposition: Is the matrix singular?
1330
+ if (!decomposeLU(LU.nRow, temp, row_perm, even_row_exchange)) {
1331
+ // Matrix has no inverse
1332
+ throw new SingularMatrixException();
1333
+ }
1334
+
1335
+ for (i = 0; i < nRow; i++) {
1336
+ for (j = 0; j < nCol; j++) {
1337
+ LU.values[i][j] = temp[i * nCol + j];
1338
+ }
1339
+ }
1340
+
1341
+ for (i = 0; i < LU.nRow; i++) {
1342
+ permutation.values[i] = row_perm[i];
1343
+ }
1344
+
1345
+ return even_row_exchange[0];
1346
+ }
1347
+
1348
+ /**
1349
+ * Finds the singular value decomposition (SVD) of this matrix such that
1350
+ * this = U*W*transpose(V); and returns the rank of this matrix; the values
1351
+ * of U,W,V are all overwritten. Note that the matrix V is output as V, and
1352
+ * not transpose(V). If this matrix is mxn, then U is mxm, W is a diagonal
1353
+ * matrix that is mxn, and V is nxn. Using the notation W = diag(w), then
1354
+ * the inverse of this matrix is: inverse(this) = V*diag(1/w)*tranpose(U),
1355
+ * where diag(1/w) is the same matrix as W except that the reciprocal of
1356
+ * each of the diagonal components is used.
1357
+ *
1358
+ * @param U The computed U matrix in the equation this = U*W*transpose(V)
1359
+ * @param W The computed W matrix in the equation this = U*W*transpose(V)
1360
+ * @param V The computed V matrix in the equation this = U*W*transpose(V)
1361
+ * @return The rank of this matrix.
1362
+ */
1363
+ public final int computeSVD(GMatrix U, GMatrix W, GMatrix V) {
1364
+ // check for consistancy in dimensions
1365
+ if (nCol != V.nCol || nCol != V.nRow) {
1366
+ throw new MatrixSizeException();
1367
+ }
1368
+
1369
+ if (nRow != U.nRow || nRow != U.nCol) {
1370
+ throw new MatrixSizeException();
1371
+ }
1372
+
1373
+ if (nRow != W.nRow || nCol != W.nCol) {
1374
+ throw new MatrixSizeException();
1375
+ }
1376
+
1377
+ // Fix ArrayIndexOutOfBounds for 2x2 matrices, which partially
1378
+ // addresses bug 4348562 for J3D 1.2.1.
1379
+ //
1380
+ // Does *not* fix the following problems reported in 4348562,
1381
+ // which will wait for J3D 1.3:
1382
+ //
1383
+ // 1) no output of W
1384
+ // 2) wrong transposition of U
1385
+ // 3) wrong results for 4x4 matrices
1386
+ // 4) slow performance
1387
+ if (nRow == 2 && nCol == 2) {
1388
+ if (values[1][0] == 0.0) {
1389
+ U.identity();
1390
+ V.identity();
1391
+
1392
+ if (values[0][1] == 0.0) {
1393
+ return 2;
1394
+ }
1395
+
1396
+ double[] sinl = new double[1];
1397
+ double[] sinr = new double[1];
1398
+ double[] cosl = new double[1];
1399
+ double[] cosr = new double[1];
1400
+ double[] single_values = new double[2];
1401
+
1402
+ single_values[0] = values[0][0];
1403
+ single_values[1] = values[1][1];
1404
+
1405
+ compute_2X2(values[0][0], values[0][1], values[1][1],
1406
+ single_values, sinl, cosl, sinr, cosr, 0);
1407
+
1408
+ update_u(0, U, cosl, sinl);
1409
+ update_v(0, V, cosr, sinr);
1410
+
1411
+ return 2;
1412
+ }
1413
+ // else call computeSVD() and check for 2x2 there
1414
+ }
1415
+
1416
+ return computeSVD(this, U, W, V);
1417
+ }
1418
+
1419
+ /**
1420
+ * Copies a sub-matrix derived from this matrix into the target matrix. The
1421
+ * upper left of the sub-matrix is located at (rowSource, colSource); the
1422
+ * lower right of the sub-matrix is located at
1423
+ * (lastRowSource,lastColSource). The sub-matrix is copied into the the
1424
+ * target matrix starting at (rowDest, colDest).
1425
+ *
1426
+ * @param rowSource the top-most row of the sub-matrix
1427
+ * @param colSource the left-most column of the sub-matrix
1428
+ * @param numRow the number of rows in the sub-matrix
1429
+ * @param numCol the number of columns in the sub-matrix
1430
+ * @param rowDest the top-most row of the position of the copied sub-matrix
1431
+ * within the target matrix
1432
+ * @param colDest the left-most column of the position of the copied
1433
+ * sub-matrix within the target matrix
1434
+ * @param target the matrix into which the sub-matrix will be copied
1435
+ */
1436
+ public final void copySubMatrix(int rowSource, int colSource, int numRow,
1437
+ int numCol, int rowDest, int colDest, GMatrix target) {
1438
+ int i, j;
1439
+
1440
+ if (this != target) {
1441
+ for (i = 0; i < numRow; i++) {
1442
+ for (j = 0; j < numCol; j++) {
1443
+ target.values[rowDest + i][colDest + j] = values[rowSource
1444
+ + i][colSource + j];
1445
+ }
1446
+ }
1447
+ } else {
1448
+ double[][] tmp = new double[numRow][numCol];
1449
+ for (i = 0; i < numRow; i++) {
1450
+ for (j = 0; j < numCol; j++) {
1451
+ tmp[i][j] = values[rowSource + i][colSource + j];
1452
+ }
1453
+ }
1454
+ for (i = 0; i < numRow; i++) {
1455
+ for (j = 0; j < numCol; j++) {
1456
+ target.values[rowDest + i][colDest + j] = tmp[i][j];
1457
+ }
1458
+ }
1459
+ }
1460
+ }
1461
+
1462
+ /**
1463
+ * Returns true if the L-infinite distance between this matrix and matrix m1
1464
+ * is less than or equal to the epsilon parameter, otherwise returns false.
1465
+ * The L-infinite distance is equal to MAX[i=0,1,2, . . .n ; j=0,1,2, . . .n
1466
+ * ; abs(this.m(i,j) - m1.m(i,j)]
1467
+ *
1468
+ * @param m1 The matrix to be compared to this matrix
1469
+ * @param epsilon the threshold value
1470
+ * @return
1471
+ */
1472
+ public boolean epsilonEquals(GMatrix m1, double epsilon) {
1473
+ int i, j;
1474
+ double diff;
1475
+ if (nRow != m1.nRow || nCol != m1.nCol) {
1476
+ return false;
1477
+ }
1478
+
1479
+ for (i = 0; i < nRow; i++) {
1480
+ for (j = 0; j < nCol; j++) {
1481
+ diff = values[i][j] - m1.values[i][j];
1482
+ if ((diff < 0 ? -diff : diff) > epsilon) {
1483
+ return false;
1484
+ }
1485
+ }
1486
+ }
1487
+ return true;
1488
+ }
1489
+
1490
+ /**
1491
+ * @param m1
1492
+ * @param epsilon
1493
+ * @return
1494
+ * @deprecated Use epsilonEquals(GMatrix, double) instead
1495
+ */
1496
+ @Deprecated
1497
+ public boolean epsilonEquals(GMatrix m1, float epsilon) {
1498
+ return epsilonEquals(m1, (double) epsilon);
1499
+ }
1500
+
1501
+ /**
1502
+ * Returns true if all of the data members of GMatrix m1 are equal to the
1503
+ * corresponding data members in this GMatrix.
1504
+ *
1505
+ * @param m1 The matrix with which the comparison is made.
1506
+ * @return true or false
1507
+ */
1508
+ public boolean equals(GMatrix m1) {
1509
+ try {
1510
+ int i, j;
1511
+
1512
+ if (nRow != m1.nRow || nCol != m1.nCol) {
1513
+ return false;
1514
+ }
1515
+
1516
+ for (i = 0; i < nRow; i++) {
1517
+ for (j = 0; j < nCol; j++) {
1518
+ if (values[i][j] != m1.values[i][j]) {
1519
+ return false;
1520
+ }
1521
+ }
1522
+ }
1523
+ return true;
1524
+ } catch (NullPointerException e2) {
1525
+ return false;
1526
+ }
1527
+ }
1528
+
1529
+ /**
1530
+ * Returns true if the Object o1 is of type GMatrix and all of the data
1531
+ * members of o1 are equal to the corresponding data members in this
1532
+ * GMatrix.
1533
+ *
1534
+ * @param o1 The object with which the comparison is made.
1535
+ * @return true or false
1536
+ */
1537
+ @Override
1538
+ public boolean equals(Object o1) {
1539
+ if (o1 instanceof GMatrix) {
1540
+ GMatrix m2 = (GMatrix) o1;
1541
+ int i, j;
1542
+ if (nRow != m2.nRow || nCol != m2.nCol) {
1543
+ return false;
1544
+ }
1545
+
1546
+ for (i = 0; i < nRow; i++) {
1547
+ for (j = 0; j < nCol; j++) {
1548
+ if (values[i][j] != m2.values[i][j]) {
1549
+ return false;
1550
+ }
1551
+ }
1552
+
1553
+ }
1554
+ return true;
1555
+ }
1556
+ return false;
1557
+ }
1558
+
1559
+ /**
1560
+ *
1561
+ * @return
1562
+ */
1563
+ @Override
1564
+ public int hashCode() {
1565
+ int hash = 7;
1566
+ hash = 67 * hash + this.nRow;
1567
+ hash = 67 * hash + this.nCol;
1568
+ hash = 67 * hash + Arrays.deepHashCode(this.values);
1569
+ return hash;
1570
+ }
1571
+ /**
1572
+ * Places the values in the this GMatrix into the matrix m1; m1 should
1573
+ * be at least as large as this GMatrix.
1574
+ *
1575
+ * @param m1 The matrix that will hold the new values
1576
+ */
1577
+ public final void get(GMatrix m1) {
1578
+ int i, j, nc, nr;
1579
+
1580
+ if (nCol < m1.nCol) {
1581
+ nc = nCol;
1582
+ } else {
1583
+ nc = m1.nCol;
1584
+ }
1585
+
1586
+ if (nRow < m1.nRow) {
1587
+ nr = nRow;
1588
+ } else {
1589
+ nr = m1.nRow;
1590
+ }
1591
+
1592
+ for (i = 0; i < nr; i++) {
1593
+ for (j = 0; j < nc; j++) {
1594
+ m1.values[i][j] = values[i][j];
1595
+ }
1596
+ }
1597
+ for (i = nr; i < m1.nRow; i++) {
1598
+ for (j = 0; j < m1.nCol; j++) {
1599
+ m1.values[i][j] = 0.0;
1600
+ }
1601
+ }
1602
+ for (j = nc; j < m1.nCol; j++) {
1603
+ for (i = 0; i < nr; i++) {
1604
+ m1.values[i][j] = 0.0;
1605
+ }
1606
+ }
1607
+ }
1608
+
1609
+ /**
1610
+ * Places the values in the upper 3x3 of this GMatrix into the matrix m1.
1611
+ *
1612
+ * @param m1 The matrix that will hold the new values
1613
+ */
1614
+ public final void get(Matrix3d m1) {
1615
+ if (nRow < 3 || nCol < 3) {
1616
+ m1.setZero();
1617
+ if (nCol > 0) {
1618
+ if (nRow > 0) {
1619
+ m1.m00 = values[0][0];
1620
+ if (nRow > 1) {
1621
+ m1.m10 = values[1][0];
1622
+ if (nRow > 2) {
1623
+ m1.m20 = values[2][0];
1624
+ }
1625
+ }
1626
+ }
1627
+ if (nCol > 1) {
1628
+ if (nRow > 0) {
1629
+ m1.m01 = values[0][1];
1630
+ if (nRow > 1) {
1631
+ m1.m11 = values[1][1];
1632
+ if (nRow > 2) {
1633
+ m1.m21 = values[2][1];
1634
+ }
1635
+ }
1636
+ }
1637
+ if (nCol > 2) {
1638
+ if (nRow > 0) {
1639
+ m1.m02 = values[0][2];
1640
+ if (nRow > 1) {
1641
+ m1.m12 = values[1][2];
1642
+ if (nRow > 2) {
1643
+ m1.m22 = values[2][2];
1644
+ }
1645
+ }
1646
+ }
1647
+ }
1648
+ }
1649
+ }
1650
+ } else {
1651
+ m1.m00 = values[0][0];
1652
+ m1.m01 = values[0][1];
1653
+ m1.m02 = values[0][2];
1654
+
1655
+ m1.m10 = values[1][0];
1656
+ m1.m11 = values[1][1];
1657
+ m1.m12 = values[1][2];
1658
+
1659
+ m1.m20 = values[2][0];
1660
+ m1.m21 = values[2][1];
1661
+ m1.m22 = values[2][2];
1662
+ }
1663
+ }
1664
+
1665
+ /**
1666
+ * Places the values in the upper 4x4 of this GMatrix into the matrix m1.
1667
+ *
1668
+ * @param m1 The matrix that will hold the new values
1669
+ */
1670
+ public final void get(Matrix4f m1) {
1671
+
1672
+ if (nRow < 4 || nCol < 4) {
1673
+ m1.setZero();
1674
+ if (nCol > 0) {
1675
+ if (nRow > 0) {
1676
+ m1.m00 = (float) values[0][0];
1677
+ if (nRow > 1) {
1678
+ m1.m10 = (float) values[1][0];
1679
+ if (nRow > 2) {
1680
+ m1.m20 = (float) values[2][0];
1681
+ if (nRow > 3) {
1682
+ m1.m30 = (float) values[3][0];
1683
+ }
1684
+ }
1685
+ }
1686
+ }
1687
+ if (nCol > 1) {
1688
+ if (nRow > 0) {
1689
+ m1.m01 = (float) values[0][1];
1690
+ if (nRow > 1) {
1691
+ m1.m11 = (float) values[1][1];
1692
+ if (nRow > 2) {
1693
+ m1.m21 = (float) values[2][1];
1694
+ if (nRow > 3) {
1695
+ m1.m31 = (float) values[3][1];
1696
+ }
1697
+ }
1698
+ }
1699
+ }
1700
+ if (nCol > 2) {
1701
+ if (nRow > 0) {
1702
+ m1.m02 = (float) values[0][2];
1703
+ if (nRow > 1) {
1704
+ m1.m12 = (float) values[1][2];
1705
+ if (nRow > 2) {
1706
+ m1.m22 = (float) values[2][2];
1707
+ if (nRow > 3) {
1708
+ m1.m32 = (float) values[3][2];
1709
+ }
1710
+ }
1711
+ }
1712
+ }
1713
+ if (nCol > 3) {
1714
+ if (nRow > 0) {
1715
+ m1.m03 = (float) values[0][3];
1716
+ if (nRow > 1) {
1717
+ m1.m13 = (float) values[1][3];
1718
+ if (nRow > 2) {
1719
+ m1.m23 = (float) values[2][3];
1720
+ if (nRow > 3) {
1721
+ m1.m33 = (float) values[3][3];
1722
+ }
1723
+ }
1724
+ }
1725
+ }
1726
+ }
1727
+ }
1728
+ }
1729
+ }
1730
+ } else {
1731
+ m1.m00 = (float) values[0][0];
1732
+ m1.m01 = (float) values[0][1];
1733
+ m1.m02 = (float) values[0][2];
1734
+ m1.m03 = (float) values[0][3];
1735
+
1736
+ m1.m10 = (float) values[1][0];
1737
+ m1.m11 = (float) values[1][1];
1738
+ m1.m12 = (float) values[1][2];
1739
+ m1.m13 = (float) values[1][3];
1740
+
1741
+ m1.m20 = (float) values[2][0];
1742
+ m1.m21 = (float) values[2][1];
1743
+ m1.m22 = (float) values[2][2];
1744
+ m1.m23 = (float) values[2][3];
1745
+
1746
+ m1.m30 = (float) values[3][0];
1747
+ m1.m31 = (float) values[3][1];
1748
+ m1.m32 = (float) values[3][2];
1749
+ m1.m33 = (float) values[3][3];
1750
+ }
1751
+ }
1752
+
1753
+ /**
1754
+ * Places the values of the specified column into the array parameter.
1755
+ *
1756
+ * @param col the target column number
1757
+ * @param array the array into which the column values will be placed
1758
+ */
1759
+ public final void getColumn(int col, double[] array) {
1760
+ for (int i = 0; i < nRow; i++) {
1761
+ array[i] = values[i][col];
1762
+ }
1763
+
1764
+ }
1765
+
1766
+ /**
1767
+ * Places the values of the specified column into the vector parameter.
1768
+ *
1769
+ * @param col the target column number
1770
+ * @param vector the vector into which the column values will be placed
1771
+ */
1772
+ public final void getColumn(int col, GVector vector) {
1773
+ if (vector.size() < nRow) {
1774
+ vector.setSize(nRow);
1775
+ }
1776
+
1777
+ for (int i = 0; i < nRow; i++) {
1778
+ vector.values[i] = values[i][col];
1779
+ }
1780
+ }
1781
+
1782
+ /**
1783
+ * Retrieves the value at the specified row and column of this matrix.
1784
+ *
1785
+ * @param row the row number to be retrieved (zero indexed)
1786
+ * @param column the column number to be retrieved (zero indexed)
1787
+ * @return the value at the indexed element
1788
+ */
1789
+ public final double getElement(int row, int column) {
1790
+ return (values[row][column]);
1791
+ }
1792
+
1793
+ /**
1794
+ * Returns the number of colmuns in this matrix.
1795
+ *
1796
+ * @return number of columns in this matrix
1797
+ */
1798
+ public final int getNumCol() {
1799
+ return (nCol);
1800
+ }
1801
+
1802
+ /**
1803
+ * Returns the number of rows in this matrix.
1804
+ *
1805
+ * @return number of rows in this matrix
1806
+ */
1807
+ public final int getNumRow() {
1808
+ return (nRow);
1809
+ }
1810
+
1811
+ /**
1812
+ * Places the values of the specified row into the array parameter.
1813
+ *
1814
+ * @param row the target row number
1815
+ * @param array the array into which the row values will be placed
1816
+ */
1817
+ public final void getRow(int row, double[] array) {
1818
+ System.arraycopy(values[row], 0, array, 0, nCol);
1819
+ }
1820
+
1821
+ /**
1822
+ * Places the values of the specified row into the vector parameter.
1823
+ *
1824
+ * @param row the target row number
1825
+ * @param vector the vector into which the row values will be placed
1826
+ */
1827
+ public final void getRow(int row, GVector vector) {
1828
+ if (vector.size() < nCol) {
1829
+ vector.setSize(nCol);
1830
+ }
1831
+ System.arraycopy(values[row], 0, vector.values, 0, nCol);
1832
+ }
1833
+
1834
+ /**
1835
+ * Returns a hash code value based on the data values in this object. Two
1836
+ * different GMatrix objects with identical data values (i.e.,
1837
+ * GMatrix.equals returns true) will return the same hash number. Two
1838
+ * GMatrix objects with different data members may return the same hash
1839
+ * value, although this is not likely.
1840
+ *
1841
+ * @return the integer hash code value
1842
+ */
1843
+ // @Override
1844
+ // public int hashCode() {
1845
+ // long bits = 1L;
1846
+ //
1847
+ // bits = 31L * bits + nRow;
1848
+ // bits = 31L * bits + nCol;
1849
+ //
1850
+ // for (int i = 0; i < nRow; i++) {
1851
+ // for (int j = 0; j < nCol; j++) {
1852
+ // bits = 31L * bits + VecMathUtil.doubleToLongBits(values[i][j]);
1853
+ // }
1854
+ // }
1855
+ //
1856
+ // return (int) (bits ^ (bits >> 32));
1857
+ // }
1858
+
1859
+ /**
1860
+ * Sets this GMatrix to the identity matrix.
1861
+ */
1862
+ public final void identity() {
1863
+ int i, j;
1864
+ for (i = 0; i < nRow; i++) {
1865
+ for (j = 0; j < nCol; j++) {
1866
+ values[i][j] = 0.0;
1867
+ }
1868
+ }
1869
+
1870
+ int l;
1871
+ if (nRow < nCol) {
1872
+ l = nRow;
1873
+ } else {
1874
+ l = nCol;
1875
+ }
1876
+
1877
+ for (i = 0; i < l; i++) {
1878
+ values[i][i] = 1.0;
1879
+ }
1880
+ }
1881
+
1882
+ /**
1883
+ * Subtracts this matrix from the identity matrix and puts the values back
1884
+ * into this (this = I - this).
1885
+ */
1886
+ public final void identityMinus() {
1887
+ int i, j;
1888
+
1889
+ for (i = 0; i < nRow; i++) {
1890
+ for (j = 0; j < nCol; j++) {
1891
+ values[i][j] = -values[i][j];
1892
+ }
1893
+ }
1894
+
1895
+ int l;
1896
+ if (nRow < nCol) {
1897
+ l = nRow;
1898
+ } else {
1899
+ l = nCol;
1900
+ }
1901
+
1902
+ for (i = 0; i < l; i++) {
1903
+ values[i][i] += 1.0;
1904
+ }
1905
+ }
1906
+
1907
+ /**
1908
+ * Inverts this matrix in place.
1909
+ */
1910
+ public final void invert() {
1911
+ invertGeneral(this);
1912
+ }
1913
+
1914
+ /**
1915
+ * Inverts matrix m1 and places the new values into this matrix. Matrix m1
1916
+ * is not modified.
1917
+ *
1918
+ * @param m1 the matrix to be inverted
1919
+ */
1920
+ public final void invert(GMatrix m1) {
1921
+ invertGeneral(m1);
1922
+ }
1923
+
1924
+ /**
1925
+ * General invert routine. Inverts m1 and places the result in "this". Note
1926
+ * that this routine handles both the "this" version and the non-"this"
1927
+ * version.
1928
+ *
1929
+ * Also note that since this routine is slow anyway, we won't worry about
1930
+ * allocating a little bit of garbage.
1931
+ */
1932
+ final void invertGeneral(GMatrix m1) {
1933
+ int size = m1.nRow * m1.nCol;
1934
+ double temp[] = new double[size];
1935
+ double result[] = new double[size];
1936
+ int row_perm[] = new int[m1.nRow];
1937
+ int[] even_row_exchange = new int[1];
1938
+ int i, j;
1939
+
1940
+ // Use LU decomposition and backsubstitution code specifically
1941
+ // for floating-point nxn matrices.
1942
+ if (m1.nRow != m1.nCol) {
1943
+ // Matrix is either under or over determined
1944
+ throw new MatrixSizeException();
1945
+ }
1946
+
1947
+ // Copy source matrix to temp
1948
+ for (i = 0; i < nRow; i++) {
1949
+ for (j = 0; j < nCol; j++) {
1950
+ temp[i * nCol + j] = m1.values[i][j];
1951
+ }
1952
+ }
1953
+
1954
+ // Calculate LU decomposition: Is the matrix singular?
1955
+ if (!decomposeLU(m1.nRow, temp, row_perm, even_row_exchange)) {
1956
+ // Matrix has no inverse
1957
+ throw new SingularMatrixException();
1958
+ }
1959
+
1960
+ // Perform back substitution on the identity matrix
1961
+ for (i = 0; i < size; i++) {
1962
+ result[i] = 0.0;
1963
+ }
1964
+
1965
+ for (i = 0; i < nCol; i++) {
1966
+ result[i + i * nCol] = 1.0;
1967
+ }
1968
+
1969
+ backSubstituteLU(m1.nRow, temp, row_perm, result);
1970
+
1971
+ for (i = 0; i < nRow; i++) {
1972
+ for (j = 0; j < nCol; j++) {
1973
+ values[i][j] = result[i * nCol + j];
1974
+ }
1975
+ }
1976
+ }
1977
+
1978
+ /**
1979
+ * Sets the value of this matrix to the result of multiplying itself with
1980
+ * matrix m1 (this = this * m1).
1981
+ *
1982
+ * @param m1 the other matrix
1983
+ */
1984
+ public final void mul(GMatrix m1) {
1985
+ int i, j, k;
1986
+
1987
+ if (nCol != m1.nRow || nCol != m1.nCol) {
1988
+ throw new MatrixSizeException();
1989
+ }
1990
+
1991
+ double[][] tmp = new double[nRow][nCol];
1992
+
1993
+ for (i = 0; i < nRow; i++) {
1994
+ for (j = 0; j < nCol; j++) {
1995
+ tmp[i][j] = 0.0;
1996
+ for (k = 0; k < nCol; k++) {
1997
+ tmp[i][j] += values[i][k] * m1.values[k][j];
1998
+ }
1999
+ }
2000
+ }
2001
+
2002
+ values = tmp;
2003
+ }
2004
+
2005
+ /**
2006
+ * Sets the value of this matrix to the result of multiplying the two
2007
+ * argument matrices together (this = m1 * m2).
2008
+ *
2009
+ * @param m1 the first matrix
2010
+ * @param m2 the second matrix
2011
+ */
2012
+ public final void mul(GMatrix m1, GMatrix m2) {
2013
+ int i, j, k;
2014
+
2015
+ if (m1.nCol != m2.nRow || nRow != m1.nRow || nCol != m2.nCol) {
2016
+ throw new MatrixSizeException();
2017
+ }
2018
+
2019
+ double[][] tmp = new double[nRow][nCol];
2020
+
2021
+ for (i = 0; i < m1.nRow; i++) {
2022
+ for (j = 0; j < m2.nCol; j++) {
2023
+ tmp[i][j] = 0.0;
2024
+ for (k = 0; k < m1.nCol; k++) {
2025
+ tmp[i][j] += m1.values[i][k] * m2.values[k][j];
2026
+ }
2027
+ }
2028
+ }
2029
+
2030
+ values = tmp;
2031
+ }
2032
+
2033
+ /**
2034
+ * Computes the outer product of the two vectors; multiplies the the first
2035
+ * vector by the transpose of the second vector and places the matrix result
2036
+ * into this matrix. This matrix must be be as big or bigger than
2037
+ * getSize(v1)xgetSize(v2).
2038
+ *
2039
+ * @param v1 the first vector, treated as a row vector
2040
+ * @param v2 the second vector, treated as a column vector
2041
+ */
2042
+ public final void mul(GVector v1, GVector v2) {
2043
+ int i, j;
2044
+
2045
+ if (nRow < v1.size()) {
2046
+ throw new MatrixSizeException();
2047
+ }
2048
+
2049
+ if (nCol < v2.size()) {
2050
+ throw new MatrixSizeException();
2051
+ }
2052
+
2053
+ for (i = 0; i < v1.size(); i++) {
2054
+ for (j = 0; j < v2.size(); j++) {
2055
+ values[i][j] = v1.values[i] * v2.values[j];
2056
+ }
2057
+ }
2058
+ }
2059
+
2060
+ /**
2061
+ * Multiplies the transpose of matrix m1 times the transpose of matrix m2,
2062
+ * and places the result into this.
2063
+ *
2064
+ * @param m1 The matrix on the left hand side of the multiplication
2065
+ * @param m2 The matrix on the right hand side of the multiplication
2066
+ */
2067
+ public final void mulTransposeBoth(GMatrix m1, GMatrix m2) {
2068
+ int i, j, k;
2069
+
2070
+ if (m1.nRow != m2.nCol || nRow != m1.nCol || nCol != m2.nRow) {
2071
+ throw new MatrixSizeException();
2072
+ }
2073
+
2074
+ if (m1 == this || m2 == this) {
2075
+ double[][] tmp = new double[nRow][nCol];
2076
+ for (i = 0; i < nRow; i++) {
2077
+ for (j = 0; j < nCol; j++) {
2078
+ tmp[i][j] = 0.0;
2079
+ for (k = 0; k < m1.nRow; k++) {
2080
+ tmp[i][j] += m1.values[k][i] * m2.values[j][k];
2081
+ }
2082
+ }
2083
+ }
2084
+ values = tmp;
2085
+ } else {
2086
+ for (i = 0; i < nRow; i++) {
2087
+ for (j = 0; j < nCol; j++) {
2088
+ values[i][j] = 0.0;
2089
+ for (k = 0; k < m1.nRow; k++) {
2090
+ values[i][j] += m1.values[k][i] * m2.values[j][k];
2091
+ }
2092
+ }
2093
+ }
2094
+ }
2095
+ }
2096
+
2097
+ /**
2098
+ * Multiplies the transpose of matrix m1 times matrix m2, and places the
2099
+ * result into this.
2100
+ *
2101
+ * @param m1 The matrix on the left hand side of the multiplication
2102
+ * @param m2 The matrix on the right hand side of the multiplication
2103
+ */
2104
+ public final void mulTransposeLeft(GMatrix m1, GMatrix m2) {
2105
+ int i, j, k;
2106
+
2107
+ if (m1.nRow != m2.nRow || nCol != m2.nCol || nRow != m1.nCol) {
2108
+ throw new MatrixSizeException();
2109
+ }
2110
+
2111
+ if (m1 == this || m2 == this) {
2112
+ double[][] tmp = new double[nRow][nCol];
2113
+ for (i = 0; i < nRow; i++) {
2114
+ for (j = 0; j < nCol; j++) {
2115
+ tmp[i][j] = 0.0;
2116
+ for (k = 0; k < m1.nRow; k++) {
2117
+ tmp[i][j] += m1.values[k][i] * m2.values[k][j];
2118
+ }
2119
+ }
2120
+ }
2121
+ values = tmp;
2122
+ } else {
2123
+ for (i = 0; i < nRow; i++) {
2124
+ for (j = 0; j < nCol; j++) {
2125
+ values[i][j] = 0.0;
2126
+ for (k = 0; k < m1.nRow; k++) {
2127
+ values[i][j] += m1.values[k][i] * m2.values[k][j];
2128
+ }
2129
+ }
2130
+ }
2131
+ }
2132
+ }
2133
+
2134
+ /**
2135
+ * Multiplies matrix m1 times the transpose of matrix m2, and places the
2136
+ * result into this.
2137
+ *
2138
+ * @param m1 The matrix on the left hand side of the multiplication
2139
+ * @param m2 The matrix on the right hand side of the multiplication
2140
+ */
2141
+ public final void mulTransposeRight(GMatrix m1, GMatrix m2) {
2142
+ int i, j, k;
2143
+
2144
+ if (m1.nCol != m2.nCol || nCol != m2.nRow || nRow != m1.nRow) {
2145
+ throw new MatrixSizeException();
2146
+ }
2147
+
2148
+ if (m1 == this || m2 == this) {
2149
+ double[][] tmp = new double[nRow][nCol];
2150
+ for (i = 0; i < nRow; i++) {
2151
+ for (j = 0; j < nCol; j++) {
2152
+ tmp[i][j] = 0.0;
2153
+ for (k = 0; k < m1.nCol; k++) {
2154
+ tmp[i][j] += m1.values[i][k] * m2.values[j][k];
2155
+ }
2156
+ }
2157
+ }
2158
+ values = tmp;
2159
+ } else {
2160
+ for (i = 0; i < nRow; i++) {
2161
+ for (j = 0; j < nCol; j++) {
2162
+ values[i][j] = 0.0;
2163
+ for (k = 0; k < m1.nCol; k++) {
2164
+ values[i][j] += m1.values[i][k] * m2.values[j][k];
2165
+ }
2166
+ }
2167
+ }
2168
+ }
2169
+
2170
+ }
2171
+
2172
+ /**
2173
+ * Negates the value of this matrix: this = -this.
2174
+ */
2175
+ public final void negate() {
2176
+ int i, j;
2177
+ for (i = 0; i < nRow; i++) {
2178
+ for (j = 0; j < nCol; j++) {
2179
+ values[i][j] = -values[i][j];
2180
+ }
2181
+ }
2182
+ }
2183
+
2184
+ /**
2185
+ * Sets the value of this matrix equal to the negation of of the GMatrix
2186
+ * parameter.
2187
+ *
2188
+ * @param m1 The source matrix
2189
+ */
2190
+ public final void negate(GMatrix m1) {
2191
+ int i, j;
2192
+ if (nRow != m1.nRow || nCol != m1.nCol) {
2193
+ throw new MatrixSizeException();
2194
+ }
2195
+
2196
+ for (i = 0; i < nRow; i++) {
2197
+ for (j = 0; j < nCol; j++) {
2198
+ values[i][j] = -m1.values[i][j];
2199
+ }
2200
+ }
2201
+ }
2202
+
2203
+ /**
2204
+ * Sets the value of this matrix to the values found in the array parameter.
2205
+ * The values are copied in one row at a time, in row major fashion. The
2206
+ * array should be at least equal in length to the number of matrix rows
2207
+ * times the number of matrix columns in this matrix.
2208
+ *
2209
+ * @param matrix the row major source array
2210
+ */
2211
+ public final void set(double[] matrix) {
2212
+ int i, j;
2213
+
2214
+ for (i = 0; i < nRow; i++) {
2215
+ for (j = 0; j < nCol; j++) {
2216
+ values[i][j] = matrix[nCol * i + j];
2217
+ }
2218
+ }
2219
+ }
2220
+
2221
+ /**
2222
+ * Sets the value of this matrix to the values found in matrix m1.
2223
+ *
2224
+ * @param m1 the source matrix
2225
+ */
2226
+ public final void set(GMatrix m1) {
2227
+ int i, j;
2228
+
2229
+ if (nRow < m1.nRow || nCol < m1.nCol) {
2230
+ nRow = m1.nRow;
2231
+ nCol = m1.nCol;
2232
+ values = new double[nRow][nCol];
2233
+ }
2234
+
2235
+ for (i = 0; i < Math.min(nRow, m1.nRow); i++) {
2236
+ for (j = 0; j < Math.min(nCol, m1.nCol); j++) {
2237
+ values[i][j] = m1.values[i][j];
2238
+ }
2239
+ }
2240
+
2241
+ for (i = m1.nRow; i < nRow; i++) { // pad rest or matrix with zeros
2242
+ for (j = m1.nCol; j < nCol; j++) {
2243
+ values[i][j] = 0.0;
2244
+ }
2245
+ }
2246
+ }
2247
+
2248
+ /**
2249
+ * Sets the value of this matrix to that of the Matrix3d provided.
2250
+ *
2251
+ * @param m1 the matrix
2252
+ */
2253
+ public final void set(Matrix3d m1) {
2254
+ if (nRow < 3 || nCol < 3) {
2255
+ values = new double[3][3];
2256
+ nRow = 3;
2257
+ nCol = 3;
2258
+ }
2259
+
2260
+ values[0][0] = m1.m00;
2261
+ values[0][1] = m1.m01;
2262
+ values[0][2] = m1.m02;
2263
+
2264
+ values[1][0] = m1.m10;
2265
+ values[1][1] = m1.m11;
2266
+ values[1][2] = m1.m12;
2267
+
2268
+ values[2][0] = m1.m20;
2269
+ values[2][1] = m1.m21;
2270
+ values[2][2] = m1.m22;
2271
+
2272
+ for (int i = 3; i < nRow; i++) { // pad rest or matrix with zeros
2273
+ for (int j = 3; j < nCol; j++) {
2274
+ values[i][j] = 0.0;
2275
+ }
2276
+ }
2277
+
2278
+ }
2279
+
2280
+ /**
2281
+ * Sets the value of this matrix to that of the Matrix4f provided.
2282
+ *
2283
+ * @param m1 the matrix
2284
+ */
2285
+ public final void set(Matrix4f m1) {
2286
+ if (nRow < 4 || nCol < 4) {
2287
+ values = new double[4][4];
2288
+ nRow = 4;
2289
+ nCol = 4;
2290
+ }
2291
+
2292
+ values[0][0] = m1.m00;
2293
+ values[0][1] = m1.m01;
2294
+ values[0][2] = m1.m02;
2295
+ values[0][3] = m1.m03;
2296
+
2297
+ values[1][0] = m1.m10;
2298
+ values[1][1] = m1.m11;
2299
+ values[1][2] = m1.m12;
2300
+ values[1][3] = m1.m13;
2301
+
2302
+ values[2][0] = m1.m20;
2303
+ values[2][1] = m1.m21;
2304
+ values[2][2] = m1.m22;
2305
+ values[2][3] = m1.m23;
2306
+
2307
+ values[3][0] = m1.m30;
2308
+ values[3][1] = m1.m31;
2309
+ values[3][2] = m1.m32;
2310
+ values[3][3] = m1.m33;
2311
+
2312
+ for (int i = 4; i < nRow; i++) { // pad rest or matrix with zeros
2313
+ for (int j = 4; j < nCol; j++) {
2314
+ values[i][j] = 0.0;
2315
+ }
2316
+ }
2317
+ }
2318
+
2319
+ /**
2320
+ * Copy the values from the array into the specified column of this matrix.
2321
+ *
2322
+ * @param col the column of this matrix into which the array values will be
2323
+ * copied
2324
+ * @param array the source array
2325
+ */
2326
+ public final void setColumn(int col, double[] array) {
2327
+ for (int i = 0; i < nRow; i++) {
2328
+ values[i][col] = array[i];
2329
+ }
2330
+ }
2331
+
2332
+ /**
2333
+ * Copy the values from the vector into the specified column of this matrix.
2334
+ *
2335
+ * @param col the column of this matrix into which the array values will be
2336
+ * copied
2337
+ * @param vector the source vector
2338
+ */
2339
+ public final void setColumn(int col, GVector vector) {
2340
+ for (int i = 0; i < nRow; i++) {
2341
+ values[i][col] = vector.values[i];
2342
+ }
2343
+
2344
+ }
2345
+
2346
+ /**
2347
+ * Modifies the value at the specified row and column of this matrix.
2348
+ *
2349
+ * @param row the row number to be modified (zero indexed)
2350
+ * @param column the column number to be modified (zero indexed)
2351
+ * @param value the new matrix element value
2352
+ */
2353
+ public final void setElement(int row, int column, double value) {
2354
+ values[row][column] = value;
2355
+ }
2356
+
2357
+ /**
2358
+ * Copy the values from the array into the specified row of this matrix.
2359
+ *
2360
+ * @param row the row of this matrix into which the array values will be
2361
+ * copied.
2362
+ * @param array the source array
2363
+ */
2364
+ public final void setRow(int row, double[] array) {
2365
+ System.arraycopy(array, 0, values[row], 0, nCol);
2366
+ }
2367
+
2368
+ /**
2369
+ * Copy the values from the vector into the specified row of this matrix.
2370
+ *
2371
+ * @param row the row of this matrix into which the array values will be
2372
+ * copied
2373
+ * @param vector the source vector
2374
+ */
2375
+ public final void setRow(int row, GVector vector) {
2376
+ System.arraycopy(vector.values, 0, values[row], 0, nCol);
2377
+ }
2378
+
2379
+ /**
2380
+ * Sets this matrix to a uniform scale matrix; all of the values are reset.
2381
+ *
2382
+ * @param scale The new scale value
2383
+ */
2384
+ public final void setScale(double scale) {
2385
+ int i, j, l;
2386
+
2387
+ if (nRow < nCol) {
2388
+ l = nRow;
2389
+ } else {
2390
+ l = nCol;
2391
+ }
2392
+
2393
+ for (i = 0; i < nRow; i++) {
2394
+ for (j = 0; j < nCol; j++) {
2395
+ values[i][j] = 0.0;
2396
+ }
2397
+ }
2398
+
2399
+ for (i = 0; i < l; i++) {
2400
+ values[i][i] = scale;
2401
+ }
2402
+ }
2403
+
2404
+ /**
2405
+ * Changes the size of this matrix dynamically. If the size is increased no
2406
+ * data values will be lost. If the size is decreased, only those data
2407
+ * values whose matrix positions were eliminated will be lost.
2408
+ *
2409
+ * @param nRow number of desired rows in this matrix
2410
+ * @param nCol number of desired columns in this matrix
2411
+ */
2412
+ public final void setSize(int nRow, int nCol) {
2413
+ double[][] tmp = new double[nRow][nCol];
2414
+ int i, j, maxRow, maxCol;
2415
+
2416
+ if (this.nRow < nRow) {
2417
+ maxRow = this.nRow;
2418
+ } else {
2419
+ maxRow = nRow;
2420
+ }
2421
+
2422
+ if (this.nCol < nCol) {
2423
+ maxCol = this.nCol;
2424
+ } else {
2425
+ maxCol = nCol;
2426
+ }
2427
+
2428
+ for (i = 0; i < maxRow; i++) {
2429
+ for (j = 0; j < maxCol; j++) {
2430
+ tmp[i][j] = values[i][j];
2431
+ }
2432
+ }
2433
+
2434
+ this.nRow = nRow;
2435
+ this.nCol = nCol;
2436
+
2437
+ values = tmp;
2438
+ }
2439
+
2440
+ /**
2441
+ * Sets all the values in this matrix to zero.
2442
+ */
2443
+ public final void setZero() {
2444
+ int i, j;
2445
+ for (i = 0; i < nRow; i++) {
2446
+ for (j = 0; j < nCol; j++) {
2447
+ values[i][j] = 0.0;
2448
+ }
2449
+ }
2450
+ }
2451
+
2452
+ /**
2453
+ * Sets the value of this matrix to the matrix difference of itself and
2454
+ * matrix m1 (this = this - m1).
2455
+ *
2456
+ * @param m1 the other matrix
2457
+ */
2458
+ public final void sub(GMatrix m1) {
2459
+ int i, j;
2460
+ if (nRow != m1.nRow) {
2461
+ throw new MatrixSizeException();
2462
+ }
2463
+
2464
+ if (nCol != m1.nCol) {
2465
+ throw new MatrixSizeException();
2466
+ }
2467
+
2468
+ for (i = 0; i < nRow; i++) {
2469
+ for (j = 0; j < nCol; j++) {
2470
+ values[i][j] = values[i][j] - m1.values[i][j];
2471
+ }
2472
+ }
2473
+ }
2474
+
2475
+ /**
2476
+ * Sets the value of this matrix to the matrix difference of matrices m1 and
2477
+ * m2 (this = m1 - m2).
2478
+ *
2479
+ * @param m1 the first matrix
2480
+ * @param m2 the second matrix
2481
+ */
2482
+ public final void sub(GMatrix m1, GMatrix m2) {
2483
+ int i, j;
2484
+ if (m2.nRow != m1.nRow) {
2485
+ throw new MatrixSizeException();
2486
+ }
2487
+
2488
+ if (m2.nCol != m1.nCol) {
2489
+ throw new MatrixSizeException();
2490
+ }
2491
+
2492
+ if (nRow != m1.nRow || nCol != m1.nCol) {
2493
+ throw new MatrixSizeException();
2494
+ }
2495
+
2496
+ for (i = 0; i < nRow; i++) {
2497
+ for (j = 0; j < nCol; j++) {
2498
+ values[i][j] = m1.values[i][j] - m2.values[i][j];
2499
+ }
2500
+ }
2501
+ }
2502
+
2503
+ /**
2504
+ * Returns a string that contains the values of this GMatrix.
2505
+ *
2506
+ * @return the String representation
2507
+ */
2508
+ @Override
2509
+ public String toString() {
2510
+ StringBuilder buffer = new StringBuilder(nRow * nCol * 8);
2511
+
2512
+ int i, j;
2513
+
2514
+ for (i = 0; i < nRow; i++) {
2515
+ for (j = 0; j < nCol; j++) {
2516
+ buffer.append(values[i][j]).append(" ");
2517
+ }
2518
+ buffer.append("\n");
2519
+ }
2520
+
2521
+ return buffer.toString();
2522
+ }
2523
+
2524
+ /**
2525
+ * Returns the trace of this matrix.
2526
+ *
2527
+ * @return the trace of this matrix
2528
+ */
2529
+ public final double trace() {
2530
+ int i, l;
2531
+ double t;
2532
+
2533
+ if (nRow < nCol) {
2534
+ l = nRow;
2535
+ } else {
2536
+ l = nCol;
2537
+ }
2538
+
2539
+ t = 0.0;
2540
+ for (i = 0; i < l; i++) {
2541
+ t += values[i][i];
2542
+ }
2543
+ return t;
2544
+ }
2545
+
2546
+ /**
2547
+ * Transposes this matrix in place.
2548
+ */
2549
+ public final void transpose() {
2550
+ int i, j;
2551
+
2552
+ if (nRow != nCol) {
2553
+ double[][] tmp;
2554
+ i = nRow;
2555
+ nRow = nCol;
2556
+ nCol = i;
2557
+ tmp = new double[nRow][nCol];
2558
+ for (i = 0; i < nRow; i++) {
2559
+ for (j = 0; j < nCol; j++) {
2560
+ tmp[i][j] = values[j][i];
2561
+ }
2562
+ }
2563
+ values = tmp;
2564
+ } else {
2565
+ double swap;
2566
+ for (i = 0; i < nRow; i++) {
2567
+ for (j = 0; j < i; j++) {
2568
+ swap = values[i][j];
2569
+ values[i][j] = values[j][i];
2570
+ values[j][i] = swap;
2571
+ }
2572
+ }
2573
+ }
2574
+ }
2575
+
2576
+ /**
2577
+ * Places the matrix values of the transpose of matrix m1 into this matrix.
2578
+ *
2579
+ * @param m1 the matrix to be transposed (but not modified)
2580
+ */
2581
+ public final void transpose(GMatrix m1) {
2582
+ int i, j;
2583
+
2584
+ if (nRow != m1.nCol || nCol != m1.nRow) {
2585
+ throw new MatrixSizeException();
2586
+ }
2587
+
2588
+ if (m1 != this) {
2589
+ for (i = 0; i < nRow; i++) {
2590
+ for (j = 0; j < nCol; j++) {
2591
+ values[i][j] = m1.values[j][i];
2592
+ }
2593
+ }
2594
+ } else {
2595
+ transpose();
2596
+ }
2597
+ }
2598
+
2599
+ }