mirror of
https://github.com/apache/commons-math.git
synced 2025-02-07 18:49:40 +00:00
Moved math 2.0 branch to trunk.
git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@722335 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
commit
d9df34360f
59
NOTICE.txt
59
NOTICE.txt
@ -8,6 +8,21 @@ The Apache Software Foundation (http://www.apache.org/).
|
||||
This product includes software translated from the lmder, lmpar
|
||||
and qrsolv Fortran routines from the Minpack package and
|
||||
distributed under the following disclaimer:
|
||||
http://www.netlib.org/minpack/disclaimer
|
||||
|
||||
This product includes software translated from the odex Fortran routine
|
||||
developed by E. Hairer and G. Wanner and distributed under the following
|
||||
license:
|
||||
http://www.unige.ch/~hairer/prog/licence.txt
|
||||
|
||||
This product includes software translated from some LAPACK Fortran routines
|
||||
and distributed under the following license:
|
||||
http://www.netlib.org/lapack/LICENSE
|
||||
|
||||
For convenience, the text of these licenses and disclaimers as available at
|
||||
time of code inclusion are provided below.
|
||||
|
||||
|
||||
|
||||
---------- http://www.netlib.org/minpack/disclaimer ----------
|
||||
Minpack Copyright Notice (1999) University of Chicago. All rights reserved
|
||||
@ -65,10 +80,6 @@ POSSIBILITY OF SUCH LOSS OR DAMAGES.
|
||||
|
||||
|
||||
|
||||
This product includes software translated from the odex Fortran routine
|
||||
developed by E. Hairer and G. Wanner and distributed under the following
|
||||
license:
|
||||
|
||||
---------- http://www.unige.ch/~hairer/prog/licence.txt ----------
|
||||
Copyright (c) 2004, Ernst Hairer
|
||||
|
||||
@ -95,3 +106,43 @@ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
---------- http://www.unige.ch/~hairer/prog/licence.txt ----------
|
||||
|
||||
|
||||
|
||||
---------- http://www.netlib.org/lapack/LICENSE ----------
|
||||
Copyright (c) 1992-2008 The University of Tennessee. All rights reserved.
|
||||
|
||||
$COPYRIGHT$
|
||||
|
||||
Additional copyrights may follow
|
||||
|
||||
$HEADER$
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer listed
|
||||
in this license in the documentation and/or other materials
|
||||
provided with the distribution.
|
||||
|
||||
- Neither the name of the copyright holders nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
---------- http://www.netlib.org/lapack/LICENSE ----------
|
||||
|
106
build.xml
106
build.xml
@ -1,46 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<!--build.xml generated by maven from project.xml version 1.2-SNAPSHOT
|
||||
on date December 22 2005, time 1344-->
|
||||
<!--build.xml generated by maven from project.xml version 1.2-RC2
|
||||
on date April 24 2008, time 1634-->
|
||||
|
||||
<project default="jar" name="commons-math" basedir=".">
|
||||
<!--Load local and user build preferences-->
|
||||
|
||||
<property file="build.properties">
|
||||
<property name="defaulttargetdir" value="target">
|
||||
</property>
|
||||
<property file="${user.home}/build.properties">
|
||||
<property name="libdir" value="target/lib">
|
||||
</property>
|
||||
<!--Build properties-->
|
||||
|
||||
<property name="defaulttargetdir" value="${basedir}/target">
|
||||
<property name="classesdir" value="target/classes">
|
||||
</property>
|
||||
<property name="libdir" value="${user.home}/.maven/repository">
|
||||
<property name="testclassesdir" value="target/test-classes">
|
||||
</property>
|
||||
<property name="classesdir" value="${basedir}/target/classes">
|
||||
<property name="testclassesdir" value="target/test-classes">
|
||||
</property>
|
||||
<property name="testclassesdir" value="${basedir}/target/test-classes">
|
||||
<property name="testreportdir" value="target/test-reports">
|
||||
</property>
|
||||
<property name="testreportdir" value="${basedir}/target/test-reports">
|
||||
<property name="distdir" value="dist">
|
||||
</property>
|
||||
<property name="distdir" value="${basedir}/dist">
|
||||
<property name="javadocdir" value="dist/docs/api">
|
||||
</property>
|
||||
<property name="javadocdir" value="${basedir}/dist/docs/api">
|
||||
</property>
|
||||
<property name="final.name" value="commons-math-1.2">
|
||||
</property>
|
||||
<property name="proxy.host" value="">
|
||||
</property>
|
||||
<property name="proxy.port" value="">
|
||||
</property>
|
||||
<property name="proxy.username" value="">
|
||||
</property>
|
||||
<property name="proxy.password" value="">
|
||||
<property name="final.name" value="commons-math-1.2-RC2">
|
||||
</property>
|
||||
<path id="build.classpath">
|
||||
<pathelement location="${libdir}/commons-logging/jars/commons-logging-1.0.3.jar">
|
||||
</pathelement>
|
||||
<pathelement location="${libdir}/commons-discovery/jars/commons-discovery-0.2.jar">
|
||||
</pathelement>
|
||||
<fileset dir="${libdir}">
|
||||
<include name="**/*.jar">
|
||||
</include>
|
||||
</fileset>
|
||||
</path>
|
||||
<target name="init" description="o Initializes some properties">
|
||||
<mkdir dir="${libdir}">
|
||||
@ -53,25 +39,13 @@
|
||||
|
||||
<available property="Junit.present" classname="junit.framework.Test">
|
||||
</available>
|
||||
<!--Test if user defined a proxy-->
|
||||
|
||||
<condition property="useProxy">
|
||||
<and>
|
||||
<isset property="proxy.host">
|
||||
</isset>
|
||||
<not>
|
||||
<equals trim="true" arg2="" arg1="${proxy.host}">
|
||||
</equals>
|
||||
</not>
|
||||
</and>
|
||||
</condition>
|
||||
</target>
|
||||
<target name="compile" description="o Compile the code" depends="get-deps">
|
||||
<mkdir dir="${classesdir}">
|
||||
</mkdir>
|
||||
<javac destdir="${classesdir}" deprecation="true" debug="true" optimize="false" excludes="**/package.html">
|
||||
<src>
|
||||
<pathelement location="${basedir}/src/java">
|
||||
<pathelement location="src/java">
|
||||
</pathelement>
|
||||
</src>
|
||||
<classpath refid="build.classpath">
|
||||
@ -80,11 +54,9 @@
|
||||
<mkdir dir="${classesdir}/META-INF">
|
||||
</mkdir>
|
||||
<copy todir="${classesdir}/META-INF">
|
||||
<fileset dir="${basedir}/.">
|
||||
<fileset dir=".">
|
||||
<include name="NOTICE.txt">
|
||||
</include>
|
||||
<include name="LICENSE.txt">
|
||||
</include>
|
||||
</fileset>
|
||||
</copy>
|
||||
</target>
|
||||
@ -115,7 +87,7 @@
|
||||
<target name="internal-test" if="Junit.present" depends="junit-present,compile-tests">
|
||||
<mkdir dir="${testreportdir}">
|
||||
</mkdir>
|
||||
<junit dir="${basedir}" failureproperty="test.failure" printSummary="yes" fork="true" haltonerror="true">
|
||||
<junit dir="./" failureproperty="test.failure" printSummary="yes" fork="true" haltonerror="true">
|
||||
<sysproperty key="basedir" value=".">
|
||||
</sysproperty>
|
||||
<formatter type="xml">
|
||||
@ -131,7 +103,7 @@
|
||||
</pathelement>
|
||||
</classpath>
|
||||
<batchtest todir="${testreportdir}">
|
||||
<fileset dir="${basedir}/src/test">
|
||||
<fileset dir="src/test">
|
||||
<include name="**/*Test.java">
|
||||
</include>
|
||||
<exclude name="**/*AbstractTest.java">
|
||||
@ -150,7 +122,7 @@
|
||||
</mkdir>
|
||||
<javac destdir="${testclassesdir}" deprecation="true" debug="true" optimize="false" excludes="**/package.html">
|
||||
<src>
|
||||
<pathelement location="${basedir}/src/test">
|
||||
<pathelement location="src/test">
|
||||
</pathelement>
|
||||
</src>
|
||||
<classpath>
|
||||
@ -161,7 +133,7 @@
|
||||
</classpath>
|
||||
</javac>
|
||||
<copy todir="${testclassesdir}">
|
||||
<fileset dir="${basedir}/src/test">
|
||||
<fileset dir="src/test">
|
||||
<include name="**/*.xml">
|
||||
</include>
|
||||
<include name="**/*.txt">
|
||||
@ -178,42 +150,16 @@
|
||||
</tstamp>
|
||||
<property name="copyright" value="Copyright &copy; The Apache Software Foundation. All Rights Reserved.">
|
||||
</property>
|
||||
<property name="title" value="Math 1.2-SNAPSHOT API">
|
||||
<property name="title" value="Math 1.2-RC2 API">
|
||||
</property>
|
||||
<javadoc use="true" private="true" destdir="${javadocdir}" author="true" version="true" sourcepath="${basedir}/src/java" packagenames="org.apache.commons.math.*">
|
||||
<javadoc use="true" private="true" destdir="${javadocdir}" author="true" version="true" sourcepath="src/java" packagenames="org.apache.commons.math.*">
|
||||
<classpath>
|
||||
<path refid="build.classpath">
|
||||
</path>
|
||||
</classpath>
|
||||
</javadoc>
|
||||
</target>
|
||||
<target name="get-dep-commons-logging.jar" description="o Download the dependency : commons-logging.jar" unless="commons-logging.jar" depends="init,setProxy,noProxy,get-custom-dep-commons-logging.jar">
|
||||
<mkdir dir="${libdir}/commons-logging/jars/">
|
||||
</mkdir>
|
||||
<get dest="${libdir}/commons-logging/jars/commons-logging-1.0.4.jar" usetimestamp="true" ignoreerrors="true" src="http://www.ibiblio.org/maven/commons-logging/jars/commons-logging-1.0.4.jar">
|
||||
</get>
|
||||
</target>
|
||||
<target name="get-custom-dep-commons-logging.jar" if="commons-logging.jar" depends="init,setProxy,noProxy">
|
||||
<mkdir dir="${libdir}/commons-logging/jars/">
|
||||
</mkdir>
|
||||
<get dest="${libdir}/commons-logging/jars/commons-logging-1.0.4.jar" usetimestamp="true" ignoreerrors="true" src="${commons-logging.jar}">
|
||||
</get>
|
||||
</target>
|
||||
<target name="get-dep-commons-discovery.jar" description="o Download the dependency : commons-discovery.jar" unless="commons-discovery.jar" depends="init,setProxy,noProxy,get-custom-dep-commons-discovery.jar">
|
||||
<mkdir dir="${libdir}/commons-discovery/jars/">
|
||||
</mkdir>
|
||||
<get dest="${libdir}/commons-discovery/jars/commons-discovery-0.2.jar" usetimestamp="true" ignoreerrors="true" src="http://www.ibiblio.org/maven/commons-discovery/jars/commons-discovery-0.2.jar">
|
||||
</get>
|
||||
</target>
|
||||
<target name="get-custom-dep-commons-discovery.jar" if="commons-discovery.jar" depends="init,setProxy,noProxy">
|
||||
<mkdir dir="${libdir}/commons-discovery/jars/">
|
||||
</mkdir>
|
||||
<get dest="${libdir}/commons-discovery/jars/commons-discovery-0.2.jar" usetimestamp="true" ignoreerrors="true" src="${commons-discovery.jar}">
|
||||
</get>
|
||||
</target>
|
||||
<target name="get-deps" unless="noget" depends="get-dep-commons-logging.jar,get-dep-commons-discovery.jar">
|
||||
</target>
|
||||
<target name="setProxy" if="useProxy" depends="init">
|
||||
<target name="get-deps" unless="noget" depends="init">
|
||||
<!--Proxy settings works only with a JDK 1.2 and higher.-->
|
||||
|
||||
<echo>Proxy used :</echo>
|
||||
@ -222,6 +168,10 @@
|
||||
<echo>Proxy user [${proxy.username}]</echo>
|
||||
<setproxy proxyuser="${proxy.username}" proxyport="${proxy.port}" proxypassword="${proxy.password}" proxyhost="${proxy.host}">
|
||||
</setproxy>
|
||||
<get dest="${libdir}/maven-cobertura-plugin-1.1.1.jar" usetimestamp="true" ignoreerrors="true" src="http://repo1.maven.org/maven/maven-plugins/plugins/maven-cobertura-plugin-1.1.1.jar">
|
||||
</get>
|
||||
<get dest="${libdir}/maven-xdoc-plugin-1.9.2.jar" usetimestamp="true" ignoreerrors="true" src="http://repo1.maven.org/maven/maven/plugins/maven-xdoc-plugin-1.9.2.jar">
|
||||
</get>
|
||||
</target>
|
||||
<target name="noProxy" unless="useProxy" depends="init">
|
||||
<echo>Proxy not used.</echo>
|
||||
|
@ -66,9 +66,21 @@
|
||||
<module name="IllegalInstantiation">
|
||||
<property name="classes" value="java.lang.Boolean, java.lang.String"/>
|
||||
</module>
|
||||
|
||||
<!-- Required for SuppressionCommentFilter below -->
|
||||
<module name="FileContentsHolder"/>
|
||||
|
||||
</module>
|
||||
|
||||
<!-- Require package javadoc -->
|
||||
<module name="PackageHtml"/>
|
||||
|
||||
<!-- Setup special comments to suppress specific checks from source files -->
|
||||
<module name="SuppressionCommentFilter">
|
||||
<property name="offCommentFormat" value="CHECKSTYLE\: stop JavadocMethodCheck"/>
|
||||
<property name="onCommentFormat" value="CHECKSTYLE\: resume JavadocMethodCheck"/>
|
||||
<property name="checkFormat" value="JavadocMethodCheck"/>
|
||||
</module>
|
||||
|
||||
</module>
|
||||
|
||||
|
@ -49,11 +49,29 @@
|
||||
|
||||
|
||||
<!-- the following expositions of internal representation are intentional and documented -->
|
||||
<Match>
|
||||
<Class name="org.apache.commons.math.ode.sampling.AbstractStepInterpolator"/>
|
||||
<Or>
|
||||
<Method name="getInterpolatedState" params="" returns="double[]" />
|
||||
<Method name="getInterpolatedDerivatives" params="" returns="double[]" />
|
||||
</Or>
|
||||
<Bug pattern="EI_EXPOSE_REP" />
|
||||
</Match>
|
||||
<Match>
|
||||
<Class name="org.apache.commons.math.linear.BigMatrixImpl"/>
|
||||
<Method name="<init>" params="java.math.BigDecimal[][],boolean" returns="void" />
|
||||
<Bug pattern="EI_EXPOSE_REP2" />
|
||||
</Match>
|
||||
<Match>
|
||||
<Class name="org.apache.commons.math.linear.BigMatrixImpl"/>
|
||||
<Method name="getDataRef" params="" returns="java.math.BigDecimal[][]" />
|
||||
<Bug pattern="EI_EXPOSE_REP" />
|
||||
</Match>
|
||||
<Match>
|
||||
<Class name="org.apache.commons.math.linear.RealMatrixImpl"/>
|
||||
<Method name="<init>" params="double[][],boolean" returns="void" />
|
||||
<Bug pattern="EI_EXPOSE_REP2" />
|
||||
</Match>
|
||||
<Match>
|
||||
<Class name="org.apache.commons.math.linear.RealMatrixImpl"/>
|
||||
<Method name="getDataRef" params="" returns="double[][]" />
|
||||
@ -64,6 +82,11 @@
|
||||
<Method name="getValues" params="" returns="double[]" />
|
||||
<Bug pattern="EI_EXPOSE_REP" />
|
||||
</Match>
|
||||
<Match>
|
||||
<Class name="org.apache.commons.math.linear.RealVectorImpl"/>
|
||||
<Method name="getDataRef" params="" returns="double[]" />
|
||||
<Bug pattern="EI_EXPOSE_REP" />
|
||||
</Match>
|
||||
|
||||
<!-- The following cases are intentional unit tests for null parameters -->
|
||||
<Match>
|
||||
|
@ -51,12 +51,6 @@
|
||||
</preGoal>
|
||||
-->
|
||||
|
||||
<!-- Uncomment to include compile time dependent jars (discovery, logging)
|
||||
<preGoal name="dist:build-bin">
|
||||
<deploy:copy-deps todir="${maven.build.dir}/${maven.final.name}/bin/${maven.final.name}" />
|
||||
</preGoal>
|
||||
-->
|
||||
|
||||
<!-- Limit maven resources included in site generation -->
|
||||
<postGoal name="xdoc:copy-resources">
|
||||
<copy todir="${maven.docs.dest}/images">
|
||||
|
60
pom.xml
60
pom.xml
@ -15,19 +15,16 @@
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<project
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<parent>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-parent</artifactId>
|
||||
<version>11</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>commons-math</groupId>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-math</artifactId>
|
||||
<version>1.3-SNAPSHOT</version>
|
||||
<version>2.0-SNAPSHOT</version>
|
||||
<name>Commons Math</name>
|
||||
|
||||
<inceptionYear>2003</inceptionYear>
|
||||
@ -41,9 +38,11 @@
|
||||
</issueManagement>
|
||||
|
||||
<scm>
|
||||
<connection>scm:svn:http://svn.apache.org/repos/asf/commons/proper/math/trunk</connection>
|
||||
<developerConnection>scm:svn:https://svn.apache.org/repos/asf/commons/proper/math/trunk</developerConnection>
|
||||
<url>http://svn.apache.org/viewvc/commons/proper/math/trunk</url>
|
||||
<!-- WARNING! -->
|
||||
<!-- this should be set back to trunk when the branch will be merged back -->
|
||||
<connection>scm:svn:http://svn.apache.org/repos/asf/commons/proper/math/branches/MATH_2_0</connection>
|
||||
<developerConnection>scm:svn:https://svn.apache.org/repos/asf/commons/proper/math/branches/MATH_2_0</developerConnection>
|
||||
<url>http://svn.apache.org/viewvc/commons/proper/math/branches/MATH_2_0</url>
|
||||
</scm>
|
||||
|
||||
<distributionManagement>
|
||||
@ -106,6 +105,9 @@
|
||||
<contributor>
|
||||
<name>Hasan Diwan</name>
|
||||
</contributor>
|
||||
<contributor>
|
||||
<name>Ted Dunning</name>
|
||||
</contributor>
|
||||
<contributor>
|
||||
<name>Ken Geis</name>
|
||||
</contributor>
|
||||
@ -127,6 +129,9 @@
|
||||
<contributor>
|
||||
<name>Todd C. Parnell</name>
|
||||
</contributor>
|
||||
<contributor>
|
||||
<name>Andreas Rieger</name>
|
||||
</contributor>
|
||||
<contributor>
|
||||
<name>Joni Salonen</name>
|
||||
</contributor>
|
||||
@ -151,38 +156,10 @@
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>3.8.2</version>
|
||||
<version>4.4</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-logging</groupId>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
<version>1.0.4</version>
|
||||
<!--
|
||||
<properties>
|
||||
<comment>
|
||||
Only required when commons-discovery is used for class factory
|
||||
configuration. No hard compile or runtime dependency.
|
||||
</comment>
|
||||
</properties>
|
||||
-->
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-discovery</groupId>
|
||||
<artifactId>commons-discovery</artifactId>
|
||||
<version>0.2</version>
|
||||
<!--
|
||||
<properties>
|
||||
<comment>
|
||||
Only required when commons-discovery is used for class
|
||||
factory configuration. No hard compile or runtime dependency.
|
||||
</comment>
|
||||
</properties>
|
||||
-->
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<commons.componentid>math</commons.componentid>
|
||||
@ -190,6 +167,8 @@
|
||||
<commons.binary.suffix></commons.binary.suffix>
|
||||
<commons.jira.id>MATH</commons.jira.id>
|
||||
<commons.jira.pid>12310485</commons.jira.pid>
|
||||
<maven.compile.source>1.5</maven.compile.source>
|
||||
<maven.compile.target>1.5</maven.compile.target>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
@ -308,6 +287,8 @@
|
||||
<rulesets>
|
||||
<ruleset>checkstyle.xml</ruleset>
|
||||
</rulesets>
|
||||
<linkXref>true</linkXref>
|
||||
<targetJdk>1.5</targetJdk>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
@ -321,3 +302,4 @@
|
||||
</plugins>
|
||||
</reporting>
|
||||
</project>
|
||||
|
||||
|
@ -45,8 +45,7 @@ maven.docs.dest=${maven.build.dir}/site
|
||||
maven.docs.src=${basedir}/src/site/xdoc
|
||||
|
||||
maven.javadoc.links = http://java.sun.com/j2se/1.4.2/docs/api/,\
|
||||
http://commons.apache.org/collections/api/,\
|
||||
http://commons.apache.org/discovery/apidocs/
|
||||
http://commons.apache.org/collections/api/
|
||||
|
||||
maven.changes.issue.template=http://issues.apache.org/jira/browse/%ISSUE%
|
||||
|
||||
|
26
project.xml
26
project.xml
@ -23,7 +23,7 @@
|
||||
<name>Math</name>
|
||||
<groupId>commons-math</groupId>
|
||||
<artifactId>commons-math</artifactId>
|
||||
<currentVersion>1.2-RC2</currentVersion>
|
||||
<currentVersion>2.0-SNAPSHOT</currentVersion>
|
||||
<inceptionYear>2003</inceptionYear>
|
||||
<shortDescription>Commons Math</shortDescription>
|
||||
<description>The Math project is a library of lightweight, self-contained mathematics and statistics components addressing the most common practical problems not immediately available in the Java programming language or commons-lang.</description>
|
||||
@ -202,30 +202,6 @@
|
||||
</contributor>
|
||||
</contributors>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>commons-logging</groupId>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
<version>1.0.4</version>
|
||||
<url>http://commons.apache.org/logging</url>
|
||||
<properties>
|
||||
<comment>
|
||||
Only required when commons-discovery is used for class factory
|
||||
configuration. No hard compile or runtime dependency.
|
||||
</comment>
|
||||
</properties>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-discovery</groupId>
|
||||
<artifactId>commons-discovery</artifactId>
|
||||
<version>0.2</version>
|
||||
<url>http://commons.apache.org/discovery</url>
|
||||
<properties>
|
||||
<comment>
|
||||
Only required when commons-discovery is used for class
|
||||
factory configuration. No hard compile or runtime dependency.
|
||||
</comment>
|
||||
</properties>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>maven-plugins</groupId>
|
||||
<artifactId>maven-cobertura-plugin</artifactId>
|
||||
|
@ -145,19 +145,19 @@ public class DefaultContext implements EvaluationContext {
|
||||
}
|
||||
|
||||
DefaultValue(double d) {
|
||||
value = new Double(d);
|
||||
value = Double.valueOf(d);
|
||||
}
|
||||
|
||||
DefaultValue(float f) {
|
||||
value = new Float(f);
|
||||
value = Float.valueOf(f);
|
||||
}
|
||||
|
||||
DefaultValue(int i) {
|
||||
value = new Integer(i);
|
||||
value = Integer.valueOf(i);
|
||||
}
|
||||
|
||||
DefaultValue(long l) {
|
||||
value = new Long(l);
|
||||
value = Long.valueOf(l);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
@ -134,7 +134,7 @@ public class BeanListUnivariateImpl extends ListUnivariateImpl implements Serial
|
||||
} catch (Exception ex) { // InstantiationException, IllegalAccessException
|
||||
throw new RuntimeException(ex); // should never happen
|
||||
}
|
||||
dynaBean.set(propertyName, new Double(v));
|
||||
dynaBean.set(propertyName, Double.valueOf(v));
|
||||
addObject(dynaBean);
|
||||
}
|
||||
|
||||
|
@ -60,21 +60,21 @@ public final class BeanListUnivariateImplTest extends TestCase {
|
||||
patientList = new ArrayList();
|
||||
|
||||
// Create and add patient bean 1
|
||||
VitalStats vs1 = new VitalStats( new Double(120.0),
|
||||
new Double(96.4) );
|
||||
Patient p1 = new Patient( vs1, new Integer( 35 ) );
|
||||
VitalStats vs1 = new VitalStats( Double.valueOf(120.0),
|
||||
Double.valueOf(96.4) );
|
||||
Patient p1 = new Patient( vs1, Integer.valueOf( 35 ) );
|
||||
patientList.add( p1 );
|
||||
|
||||
// Create and add patient bean 2
|
||||
VitalStats vs2 = new VitalStats( new Double(70.0),
|
||||
new Double(97.4) );
|
||||
Patient p2 = new Patient( vs2, new Integer( 23 ) );
|
||||
VitalStats vs2 = new VitalStats( Double.valueOf(70.0),
|
||||
Double.valueOf(97.4) );
|
||||
Patient p2 = new Patient( vs2, Integer.valueOf( 23 ) );
|
||||
patientList.add( p2 );
|
||||
|
||||
// Create and add patient bean 3
|
||||
VitalStats vs3 = new VitalStats( new Double(90.0),
|
||||
new Double(98.6) );
|
||||
Patient p3 = new Patient( vs3, new Integer( 42 ) );
|
||||
VitalStats vs3 = new VitalStats( Double.valueOf(90.0),
|
||||
Double.valueOf(98.6) );
|
||||
Patient p3 = new Patient( vs3, Integer.valueOf( 42 ) );
|
||||
patientList.add( p3 );
|
||||
}
|
||||
|
||||
|
@ -38,7 +38,7 @@ public class ArgumentOutsideDomainException extends FunctionEvaluationException
|
||||
public ArgumentOutsideDomainException(double argument, double lower, double upper) {
|
||||
super(argument,
|
||||
"Argument {0} outside domain [{1} ; {2}]",
|
||||
new Object[] { new Double(argument), new Double(lower), new Double(upper) });
|
||||
new Object[] { Double.valueOf(argument), Double.valueOf(lower), Double.valueOf(upper) });
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ public class ConvergenceException extends MathException {
|
||||
* Default constructor.
|
||||
*/
|
||||
public ConvergenceException() {
|
||||
super("Convergence failed", new Object[0]);
|
||||
super("Convergence failed", null);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -65,30 +65,4 @@ public class ConvergenceException extends MathException {
|
||||
super(pattern, arguments, cause);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new <code>ConvergenceException</code> with specified
|
||||
* detail message and nested <code>Throwable</code> root cause.
|
||||
*
|
||||
* @param msg the error message.
|
||||
* @param rootCause the exception or error that caused this exception
|
||||
* to be thrown.
|
||||
* @deprecated as of 1.2, replaced by
|
||||
* {@link #ConvergenceException(String, Object[], Throwable)}
|
||||
*/
|
||||
public ConvergenceException(String msg, Throwable rootCause) {
|
||||
super(msg, rootCause);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new <code>ConvergenceException</code> with specified
|
||||
* detail message.
|
||||
*
|
||||
* @param msg the error message.
|
||||
* @deprecated as of 1.2, replaced by
|
||||
* {@link #ConvergenceException(String, Object[])}
|
||||
*/
|
||||
public ConvergenceException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ public class DimensionMismatchException extends MathException {
|
||||
public DimensionMismatchException(int dimension1, int dimension2) {
|
||||
super("dimension mismatch {0} != {1}",
|
||||
new Object[] {
|
||||
new Integer(dimension1), new Integer(dimension2)
|
||||
Integer.valueOf(dimension1), Integer.valueOf(dimension2)
|
||||
});
|
||||
this.dimension1 = dimension1;
|
||||
this.dimension2 = dimension2;
|
||||
|
@ -35,7 +35,7 @@ public class DuplicateSampleAbscissaException extends MathException {
|
||||
*/
|
||||
public DuplicateSampleAbscissaException(double abscissa, int i1, int i2) {
|
||||
super("Abscissa {0} is duplicated at both indices {1} and {2}",
|
||||
new Object[] { new Double(abscissa), new Integer(i1), new Integer(i2) });
|
||||
new Object[] { Double.valueOf(abscissa), Integer.valueOf(i1), Integer.valueOf(i2) });
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -27,7 +27,7 @@ package org.apache.commons.math;
|
||||
public class FunctionEvaluationException extends MathException {
|
||||
|
||||
/** Serializable version identifier. */
|
||||
private static final long serialVersionUID = -7619974756160279127L;
|
||||
private static final long serialVersionUID = -2193260774031645876L;
|
||||
|
||||
/** Argument causing function evaluation failure */
|
||||
private double argument = Double.NaN;
|
||||
@ -40,23 +40,10 @@ public class FunctionEvaluationException extends MathException {
|
||||
*/
|
||||
public FunctionEvaluationException(double argument) {
|
||||
super("Evaluation failed for argument = {0}",
|
||||
new Object[] { new Double(argument) });
|
||||
new Object[] { Double.valueOf(argument) });
|
||||
this.argument = argument;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an exception using the given argument and message
|
||||
* text.
|
||||
*
|
||||
* @param argument the failing function argument
|
||||
* @param message the exception message text
|
||||
* @deprecated as of 1.2, replaced by {@link #FunctionEvaluationException(double, String, Object[])}
|
||||
*/
|
||||
public FunctionEvaluationException(double argument, String message) {
|
||||
super(message);
|
||||
this.argument = argument;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an exception with specified formatted detail message.
|
||||
* Message formatting is delegated to {@link java.text.MessageFormat}.
|
||||
@ -71,20 +58,6 @@ public class FunctionEvaluationException extends MathException {
|
||||
this.argument = argument;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an exception with the given argument, message and root cause.
|
||||
*
|
||||
* @param argument the failing function argument
|
||||
* @param message descriptive error message
|
||||
* @param cause root cause.
|
||||
* @deprecated as of 1.2, replaced by {@link #FunctionEvaluationException(double, String, Object[], Throwable)}
|
||||
*/
|
||||
public FunctionEvaluationException(double argument,
|
||||
String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
this.argument = argument;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an exception with specified root cause.
|
||||
* Message formatting is delegated to {@link java.text.MessageFormat}.
|
||||
|
@ -25,7 +25,8 @@ import java.io.Serializable;
|
||||
public class MathConfigurationException extends MathException implements Serializable{
|
||||
|
||||
/** Serializable version identifier */
|
||||
private static final long serialVersionUID = -4056541384141349722L;
|
||||
private static final long serialVersionUID = 5261476508226103366L;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
@ -33,15 +34,6 @@ public class MathConfigurationException extends MathException implements Seriali
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an exception with the given message.
|
||||
* @param message descriptive error message
|
||||
* @deprecated as of 1.2, replaced by {@link #MathConfigurationException(String, Object[])}
|
||||
*/
|
||||
public MathConfigurationException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an exception with specified formatted detail message.
|
||||
* Message formatting is delegated to {@link java.text.MessageFormat}.
|
||||
@ -53,16 +45,6 @@ public class MathConfigurationException extends MathException implements Seriali
|
||||
super(pattern, arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an exception with the given message and root cause.
|
||||
* @param message descriptive error message
|
||||
* @param cause the exception or error that caused this exception to be thrown
|
||||
* @deprecated as of 1.2, replaced by {@link #MathConfigurationException(String, Object[], Throwable)}
|
||||
*/
|
||||
public MathConfigurationException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an exception with a given root cause.
|
||||
* @param cause the exception or error that caused this exception to be thrown
|
||||
|
@ -35,24 +35,8 @@ import java.util.ResourceBundle;
|
||||
*/
|
||||
public class MathException extends Exception {
|
||||
|
||||
/** Serializable version identifier */
|
||||
private static final long serialVersionUID = -8602234299177097102L;
|
||||
|
||||
/**
|
||||
* Does JDK support nested exceptions?
|
||||
*/
|
||||
private static final boolean JDK_SUPPORTS_NESTED;
|
||||
|
||||
static {
|
||||
boolean flag = false;
|
||||
try {
|
||||
Throwable.class.getDeclaredMethod("getCause", new Class[0]);
|
||||
flag = true;
|
||||
} catch (NoSuchMethodException ex) {
|
||||
flag = false;
|
||||
}
|
||||
JDK_SUPPORTS_NESTED = flag;
|
||||
}
|
||||
/** Serializable version identifier. */
|
||||
private static final long serialVersionUID = 5924076008552401454L;
|
||||
|
||||
/** Cache for resources bundle. */
|
||||
private static ResourceBundle cachedResources = null;
|
||||
@ -67,11 +51,6 @@ public class MathException extends Exception {
|
||||
*/
|
||||
private final Object[] arguments;
|
||||
|
||||
/**
|
||||
* Root cause of the exception
|
||||
*/
|
||||
private final Throwable rootCause;
|
||||
|
||||
/**
|
||||
* Translate a string to a given locale.
|
||||
* @param s string to translate
|
||||
@ -110,10 +89,7 @@ public class MathException extends Exception {
|
||||
* @return a message string
|
||||
*/
|
||||
private static String buildMessage(String pattern, Object[] arguments, Locale locale) {
|
||||
// do it the hard way, for Java 1.3. compatibility
|
||||
MessageFormat mf = new MessageFormat(translate(pattern, locale));
|
||||
mf.setLocale(locale);
|
||||
return mf.format(arguments);
|
||||
return (pattern == null) ? "" : new MessageFormat(translate(pattern, locale), locale).format(arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -124,23 +100,8 @@ public class MathException extends Exception {
|
||||
super();
|
||||
this.pattern = null;
|
||||
this.arguments = new Object[0];
|
||||
this.rootCause = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new <code>MathException</code> with specified
|
||||
* detail message.
|
||||
*
|
||||
* @param msg the error message.
|
||||
* @deprecated as of 1.2, replaced by {@link #MathException(String, Object[])}
|
||||
*/
|
||||
public MathException(String msg) {
|
||||
super(msg);
|
||||
this.pattern = msg;
|
||||
this.arguments = new Object[0];
|
||||
this.rootCause = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new <code>MathException</code> with specified
|
||||
* formatted detail message.
|
||||
@ -151,8 +112,7 @@ public class MathException extends Exception {
|
||||
public MathException(String pattern, Object[] arguments) {
|
||||
super(buildMessage(pattern, arguments, Locale.US));
|
||||
this.pattern = pattern;
|
||||
this.arguments = (Object[]) arguments.clone();
|
||||
this.rootCause = null;
|
||||
this.arguments = (arguments == null) ? new Object[0] : arguments.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -163,28 +123,11 @@ public class MathException extends Exception {
|
||||
* to be thrown.
|
||||
*/
|
||||
public MathException(Throwable rootCause) {
|
||||
super((rootCause == null ? null : rootCause.getMessage()));
|
||||
super(rootCause);
|
||||
this.pattern = getMessage();
|
||||
this.arguments = new Object[0];
|
||||
this.rootCause = rootCause;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new <code>MathException</code> with specified
|
||||
* detail message and nested <code>Throwable</code> root cause.
|
||||
*
|
||||
* @param msg the error message.
|
||||
* @param rootCause the exception or error that caused this exception
|
||||
* to be thrown.
|
||||
* @deprecated as of 1.2, replaced by {@link #MathException(String, Object[], Throwable)}
|
||||
*/
|
||||
public MathException(String msg, Throwable rootCause) {
|
||||
super(msg);
|
||||
this.pattern = msg;
|
||||
this.arguments = new Object[0];
|
||||
this.rootCause = rootCause;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new <code>MathException</code> with specified
|
||||
* formatted detail message and nested <code>Throwable</code> root cause.
|
||||
@ -196,10 +139,9 @@ public class MathException extends Exception {
|
||||
* @since 1.2
|
||||
*/
|
||||
public MathException(String pattern, Object[] arguments, Throwable rootCause) {
|
||||
super(buildMessage(pattern, arguments, Locale.US));
|
||||
super(buildMessage(pattern, arguments, Locale.US), rootCause);
|
||||
this.pattern = pattern;
|
||||
this.arguments = (Object[]) arguments.clone();
|
||||
this.rootCause = rootCause;
|
||||
this.arguments = (arguments == null) ? new Object[0] : arguments.clone();
|
||||
}
|
||||
|
||||
/** Gets the pattern used to build the message of this throwable.
|
||||
@ -217,7 +159,7 @@ public class MathException extends Exception {
|
||||
* @since 1.2
|
||||
*/
|
||||
public Object[] getArguments() {
|
||||
return (Object[]) arguments.clone();
|
||||
return arguments.clone();
|
||||
}
|
||||
|
||||
/** Gets the message in a specified locale.
|
||||
@ -228,18 +170,14 @@ public class MathException extends Exception {
|
||||
* @since 1.2
|
||||
*/
|
||||
public String getMessage(Locale locale) {
|
||||
return (pattern == null) ? null : buildMessage(pattern, arguments, locale);
|
||||
return buildMessage(pattern, arguments, locale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the cause of this throwable.
|
||||
*
|
||||
* @return the cause of this throwable, or <code>null</code>
|
||||
*/
|
||||
public Throwable getCause() {
|
||||
return rootCause;
|
||||
/** {@inheritDoc} */
|
||||
public String getLocalizedMessage() {
|
||||
return getMessage(Locale.getDefault());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Prints the stack trace of this exception to the standard error stream.
|
||||
*/
|
||||
@ -260,20 +198,5 @@ public class MathException extends Exception {
|
||||
pw.flush();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the stack trace of this exception to the specified writer.
|
||||
*
|
||||
* @param out the <code>PrintWriter</code> to use for output
|
||||
*/
|
||||
public void printStackTrace(PrintWriter out) {
|
||||
synchronized (out) {
|
||||
super.printStackTrace(out);
|
||||
if (rootCause != null && JDK_SUPPORTS_NESTED == false) {
|
||||
out.print("Caused by: ");
|
||||
rootCause.printStackTrace(out);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
334
src/java/org/apache/commons/math/MathRuntimeException.java
Normal file
334
src/java/org/apache/commons/math/MathRuntimeException.java
Normal file
@ -0,0 +1,334 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.commons.math;
|
||||
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.text.MessageFormat;
|
||||
import java.text.ParseException;
|
||||
import java.util.Locale;
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
/**
|
||||
* Base class for commons-math unchecked exceptions.
|
||||
*
|
||||
* @version $Revision$ $Date$
|
||||
* @since 2.0
|
||||
*/
|
||||
public class MathRuntimeException extends RuntimeException {
|
||||
|
||||
/** Serializable version identifier. */
|
||||
private static final long serialVersionUID = 8560172512507661982L;
|
||||
|
||||
/** Cache for resources bundle. */
|
||||
private static ResourceBundle cachedResources = null;
|
||||
|
||||
/**
|
||||
* Pattern used to build the message.
|
||||
*/
|
||||
private final String pattern;
|
||||
|
||||
/**
|
||||
* Arguments used to build the message.
|
||||
*/
|
||||
private final Object[] arguments;
|
||||
|
||||
/**
|
||||
* Translate a string to a given locale.
|
||||
* @param s string to translate
|
||||
* @param locale locale into which to translate the string
|
||||
* @return translated string or original string
|
||||
* for unsupported locales or unknown strings
|
||||
*/
|
||||
private static String translate(final String s, final Locale locale) {
|
||||
try {
|
||||
if ((cachedResources == null) || (! cachedResources.getLocale().equals(locale))) {
|
||||
// caching the resource bundle
|
||||
cachedResources =
|
||||
ResourceBundle.getBundle("org.apache.commons.math.MessagesResources", locale);
|
||||
}
|
||||
|
||||
if (cachedResources.getLocale().getLanguage().equals(locale.getLanguage())) {
|
||||
// the value of the resource is the translated string
|
||||
return cachedResources.getString(s);
|
||||
}
|
||||
|
||||
} catch (MissingResourceException mre) {
|
||||
// do nothing here
|
||||
}
|
||||
|
||||
// the locale is not supported or the resource is unknown
|
||||
// don't translate and fall back to using the string as is
|
||||
return s;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a message string by from a pattern and its arguments.
|
||||
* @param pattern format specifier
|
||||
* @param arguments format arguments
|
||||
* @param locale Locale in which the message should be translated
|
||||
* @return a message string
|
||||
*/
|
||||
private static String buildMessage(final String pattern, final Object[] arguments,
|
||||
final Locale locale) {
|
||||
return (pattern == null) ? "" : new MessageFormat(translate(pattern, locale), locale).format(arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new <code>MathRuntimeException</code> with specified
|
||||
* formatted detail message.
|
||||
* Message formatting is delegated to {@link java.text.MessageFormat}.
|
||||
* @param pattern format specifier
|
||||
* @param arguments format arguments
|
||||
*/
|
||||
public MathRuntimeException(final String pattern, final Object[] arguments) {
|
||||
super(buildMessage(pattern, arguments, Locale.US));
|
||||
this.pattern = pattern;
|
||||
this.arguments = (arguments == null) ? new Object[0] : arguments.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new <code>MathRuntimeException</code> with specified
|
||||
* nested <code>Throwable</code> root cause.
|
||||
*
|
||||
* @param rootCause the exception or error that caused this exception
|
||||
* to be thrown.
|
||||
*/
|
||||
public MathRuntimeException(final Throwable rootCause) {
|
||||
super(rootCause);
|
||||
this.pattern = getMessage();
|
||||
this.arguments = new Object[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new <code>MathRuntimeException</code> with specified
|
||||
* formatted detail message and nested <code>Throwable</code> root cause.
|
||||
* Message formatting is delegated to {@link java.text.MessageFormat}.
|
||||
* @param pattern format specifier
|
||||
* @param arguments format arguments
|
||||
* @param rootCause the exception or error that caused this exception
|
||||
* to be thrown.
|
||||
*/
|
||||
public MathRuntimeException(final String pattern, final Object[] arguments,
|
||||
final Throwable rootCause) {
|
||||
super(buildMessage(pattern, arguments, Locale.US), rootCause);
|
||||
this.pattern = pattern;
|
||||
this.arguments = (arguments == null) ? new Object[0] : arguments.clone();
|
||||
}
|
||||
|
||||
/** Gets the pattern used to build the message of this throwable.
|
||||
*
|
||||
* @return the pattern used to build the message of this throwable
|
||||
*/
|
||||
public String getPattern() {
|
||||
return pattern;
|
||||
}
|
||||
|
||||
/** Gets the arguments used to build the message of this throwable.
|
||||
*
|
||||
* @return the arguments used to build the message of this throwable
|
||||
*/
|
||||
public Object[] getArguments() {
|
||||
return arguments.clone();
|
||||
}
|
||||
|
||||
/** Gets the message in a specified locale.
|
||||
*
|
||||
* @param locale Locale in which the message should be translated
|
||||
*
|
||||
* @return localized message
|
||||
*/
|
||||
public String getMessage(final Locale locale) {
|
||||
return buildMessage(pattern, arguments, locale);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public String getLocalizedMessage() {
|
||||
return getMessage(Locale.getDefault());
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the stack trace of this exception to the standard error stream.
|
||||
*/
|
||||
public void printStackTrace() {
|
||||
printStackTrace(System.err);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the stack trace of this exception to the specified stream.
|
||||
*
|
||||
* @param out the <code>PrintStream</code> to use for output
|
||||
*/
|
||||
public void printStackTrace(final PrintStream out) {
|
||||
synchronized (out) {
|
||||
PrintWriter pw = new PrintWriter(out, false);
|
||||
printStackTrace(pw);
|
||||
// Flush the PrintWriter before it's GC'ed.
|
||||
pw.flush();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new <code>ArithmeticException</code> with specified formatted detail message.
|
||||
* Message formatting is delegated to {@link java.text.MessageFormat}.
|
||||
* @param pattern format specifier
|
||||
* @param arguments format arguments
|
||||
*/
|
||||
public static ArithmeticException createArithmeticException(final String pattern,
|
||||
final Object[] arguments) {
|
||||
return new ArithmeticException(buildMessage(pattern, arguments, Locale.US)) {
|
||||
|
||||
/** Serializable version identifier. */
|
||||
private static final long serialVersionUID = 7705628723242533939L;
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public String getLocalizedMessage() {
|
||||
return buildMessage(pattern, arguments, Locale.getDefault());
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new <code>ArrayIndexOutOfBoundsException</code> with specified formatted detail message.
|
||||
* Message formatting is delegated to {@link java.text.MessageFormat}.
|
||||
* @param pattern format specifier
|
||||
* @param arguments format arguments
|
||||
*/
|
||||
public static ArrayIndexOutOfBoundsException createArrayIndexOutOfBoundsException(final String pattern,
|
||||
final Object[] arguments) {
|
||||
return new ArrayIndexOutOfBoundsException(buildMessage(pattern, arguments, Locale.US)) {
|
||||
|
||||
/** Serializable version identifier. */
|
||||
private static final long serialVersionUID = 8077627622976962141L;
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public String getLocalizedMessage() {
|
||||
return buildMessage(pattern, arguments, Locale.getDefault());
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new <code>EOFException</code> with specified formatted detail message.
|
||||
* Message formatting is delegated to {@link java.text.MessageFormat}.
|
||||
* @param pattern format specifier
|
||||
* @param arguments format arguments
|
||||
*/
|
||||
public static EOFException createEOFException(final String pattern,
|
||||
final Object[] arguments) {
|
||||
return new EOFException(buildMessage(pattern, arguments, Locale.US)) {
|
||||
|
||||
/** Serializable version identifier. */
|
||||
private static final long serialVersionUID = 279461544586092584L;
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public String getLocalizedMessage() {
|
||||
return buildMessage(pattern, arguments, Locale.getDefault());
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new <code>IOException</code> with specified nested
|
||||
* <code>Throwable</code> root cause.
|
||||
* <p>This factory method allows chaining of other exceptions within an
|
||||
* <code>IOException</code> even for Java 5. The constructor for
|
||||
* <code>IOException</code> with a cause parameter was introduced only
|
||||
* with Java 6.</p>
|
||||
* @param rootCause the exception or error that caused this exception
|
||||
* to be thrown.
|
||||
*/
|
||||
public static IOException createIOException(final Throwable rootCause) {
|
||||
IOException ioe = new IOException(rootCause.getLocalizedMessage());
|
||||
ioe.initCause(rootCause);
|
||||
return ioe;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new <code>IllegalArgumentException</code> with specified formatted detail message.
|
||||
* Message formatting is delegated to {@link java.text.MessageFormat}.
|
||||
* @param pattern format specifier
|
||||
* @param arguments format arguments
|
||||
*/
|
||||
public static IllegalArgumentException createIllegalArgumentException(final String pattern,
|
||||
final Object[] arguments) {
|
||||
return new IllegalArgumentException(buildMessage(pattern, arguments, Locale.US)) {
|
||||
|
||||
/** Serializable version identifier. */
|
||||
private static final long serialVersionUID = -7537852425838457684L;
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public String getLocalizedMessage() {
|
||||
return buildMessage(pattern, arguments, Locale.getDefault());
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new <code>IllegalStateException</code> with specified formatted detail message.
|
||||
* Message formatting is delegated to {@link java.text.MessageFormat}.
|
||||
* @param pattern format specifier
|
||||
* @param arguments format arguments
|
||||
*/
|
||||
public static IllegalStateException createIllegalStateException(final String pattern,
|
||||
final Object[] arguments) {
|
||||
return new IllegalStateException(buildMessage(pattern, arguments, Locale.US)) {
|
||||
|
||||
/** Serializable version identifier. */
|
||||
private static final long serialVersionUID = 5173599768297434381L;
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public String getLocalizedMessage() {
|
||||
return buildMessage(pattern, arguments, Locale.getDefault());
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new <code>ParseException</code> with specified
|
||||
* formatted detail message.
|
||||
* Message formatting is delegated to {@link java.text.MessageFormat}.
|
||||
* @param pattern format specifier
|
||||
* @param arguments format arguments
|
||||
* @param offset offset at which error occurred
|
||||
*/
|
||||
public static ParseException createParseException(final String pattern,
|
||||
final Object[] arguments,
|
||||
final int offset) {
|
||||
return new ParseException(buildMessage(pattern, arguments, Locale.US), offset) {
|
||||
|
||||
/** Serializable version identifier. */
|
||||
private static final long serialVersionUID = -1103502177342465975L;
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public String getLocalizedMessage() {
|
||||
return buildMessage(pattern, arguments, Locale.getDefault());
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
}
|
@ -41,7 +41,7 @@ public class MaxIterationsExceededException extends ConvergenceException {
|
||||
*/
|
||||
public MaxIterationsExceededException(int maxIterations) {
|
||||
super("Maximal number of iterations ({0}) exceeded",
|
||||
new Object[] { new Integer(maxIterations) });
|
||||
new Object[] { Integer.valueOf(maxIterations) });
|
||||
this.maxIterations = maxIterations;
|
||||
}
|
||||
|
||||
|
@ -133,7 +133,7 @@ public class MessagesResources_fr
|
||||
{ "unable to orthogonalize matrix in {0} iterations",
|
||||
"impossible de rendre la matrice orthogonale en {0} it\u00e9rations" },
|
||||
|
||||
// org.apache.commons.math.ode.AdaptiveStepsizeIntegrator
|
||||
// org.apache.commons.math.ode.nonstiff.AdaptiveStepsizeIntegrator
|
||||
{ "minimal step size ({0}) reached, integration needs {1}",
|
||||
"pas minimal ({0}) atteint, l''int\u00e9gration n\u00e9cessite {1}" },
|
||||
{ "dimensions mismatch: state vector has dimension {0}," +
|
||||
@ -145,8 +145,8 @@ public class MessagesResources_fr
|
||||
"incompatibilit\u00e9 de dimensions entre le vecteur d''\u00e9tat ({0})," +
|
||||
" et le vecteur de tol\u00e9rance relative ({1})" },
|
||||
|
||||
// org.apache.commons.math.ode.AdaptiveStepsizeIntegrator,
|
||||
// org.apache.commons.math.ode.RungeKuttaIntegrator
|
||||
// org.apache.commons.math.ode.nonstiff.AdaptiveStepsizeIntegrator,
|
||||
// org.apache.commons.math.ode.nonstiff.RungeKuttaIntegrator
|
||||
{ "dimensions mismatch: ODE problem has dimension {0}," +
|
||||
" initial state vector has dimension {1}",
|
||||
"incompatibilit\u00e9 de dimensions entre le probl\u00e8me ODE ({0})," +
|
||||
@ -158,9 +158,153 @@ public class MessagesResources_fr
|
||||
{ "too small integration interval: length = {0}",
|
||||
"intervalle d''int\u00e9gration trop petit : {0}" },
|
||||
|
||||
// org.apache.commons.math.ode.ContinuousOutputModel
|
||||
// org.apache.commons.math.optimization.DirectSearchOptimizer
|
||||
{ "unexpected exception caught",
|
||||
"exception inattendue lev\u00e9e" },
|
||||
|
||||
// org.apache.commons.math.optimization.DirectSearchOptimizer
|
||||
{ "none of the {0} start points lead to convergence",
|
||||
"aucun des {0} points de d\u00e9part n''aboutit \u00e0 une convergence" }
|
||||
"aucun des {0} points de d\u00e9part n''aboutit \u00e0 une convergence" },
|
||||
|
||||
// org.apache.commons.math.random.EmpiricalDistributionImpl
|
||||
{ "no bin selected",
|
||||
"aucun compartiment s\u00e9lectionn\u00e9" },
|
||||
|
||||
// org.apache.commons.math.linear.EigenDecompositionImpl
|
||||
{ "cannot solve degree {0} equation",
|
||||
"impossible de r\u00e9soudre une \u00e9quation de degr\u00e9 {0}" },
|
||||
{ "negative element on decomposed tridiagonal of {0}x{1} matrix",
|
||||
"\u00e9l\u00e9ment n\u00e9gatif dans la d\u00e9composition tri-diagonale d''une matrice {0}x{1}" },
|
||||
|
||||
// org.apache.commons.math.linear.NonSquareMatrixException
|
||||
{ "a {0}x{1} matrix was provided instead of a square matrix",
|
||||
"une matrice {0}x{1} a \u00e9t\u00e9 fournie \u00e0 la place d''une matrice carr\u00e9e" },
|
||||
|
||||
// org.apache.commons.math.linear.SingularMatrixException
|
||||
{ "matrix is singular",
|
||||
"matrice singuli\u00e8re" },
|
||||
|
||||
// org.apache.commons.math.linear.RankDeficientMatrixException
|
||||
{ "matrix is rank-deficient",
|
||||
"le rang de la matrice est inf\u00e9rieur \u00e0 sa dimension" },
|
||||
|
||||
// org.apache.commons.math.linear.RealVectorImpl
|
||||
{ "index {0} out of allowed range [{1}, {2}]",
|
||||
"index {0} hors de la plage autoris\u00e9e [{1}, {2}]" },
|
||||
|
||||
// org.apache.commons.math.linear.BigMatrixImpl
|
||||
// org.apache.commons.math.linear.RealMatrixImpl
|
||||
{ "row index {0} out of allowed range [{1}, {2}]",
|
||||
"index de ligne {0} hors de la plage autoris\u00e9e [{1}, {2}]" },
|
||||
{ "column index {0} out of allowed range [{1}, {2}]",
|
||||
"index de colonne {0} hors de la plage autoris\u00e9e [{1}, {2}]" },
|
||||
{ "no entry at indices ({0}, {1}) in a {2}x{3} matrix",
|
||||
"pas d''entr\u00e9e aux indices ({0}, {1}) dans une matrice {2}x{3}" },
|
||||
{ "initial row {0} after final row {1}",
|
||||
"ligne initiale {0} apr\u00e8s la ligne finale {1}" },
|
||||
{ "initial column {0} after final column {1}",
|
||||
"colonne initiale {0} apr\u00e8s la colonne finale {1}" },
|
||||
{ "empty selected row index array",
|
||||
"tableau des indices de lignes s\u00e9lectionn\u00e9es vide" },
|
||||
{ "empty selected column index array",
|
||||
"tableau des indices de colonnes s\u00e9lectionn\u00e9es vide" },
|
||||
|
||||
// org.apache.commons.math.random.EmpiricalDistributionImpl
|
||||
// org.apache.commons.math.random.ValueServer
|
||||
{ "URL {0} contains no data",
|
||||
"l''adresse {0} ne contient aucune donn\u00e9e" },
|
||||
|
||||
// org.apache.commons.math.complex.ComplexFormat
|
||||
{ "unparseable complex number: \"{0}\"",
|
||||
"\u00e9chec d''analyse du nombre complexe \"{0}\"" },
|
||||
|
||||
// org.apache.commons.math.fraction.FractionFormat
|
||||
{ "unparseable fraction number: \"{0}\"",
|
||||
"\u00e9chec d''analyse du nombre rationnel \"{0}\"" },
|
||||
|
||||
// org.apache.commons.math.geometry.Vector3DFormat
|
||||
{ "unparseable 3D vector: \"{0}\"",
|
||||
"\u00e9chec d''analyse du vecteur de dimension 3 \"{0}\"" },
|
||||
|
||||
// org.apache.commons.math.linear.RealVectorFormat
|
||||
{ "unparseable real vector: \"{0}\"",
|
||||
"\u00e9chec d''analyse du vecteur r\u00e9el \"{0}\"" },
|
||||
|
||||
// org.apache.commons.math.util.ResizableDoubleArray
|
||||
{ "the index specified: {0} is larger than the current maximal index {1}",
|
||||
"l''index sp\u00e9cifi\u00e9 ({0}) d\u00e9passe l''index maximal courant ({1})" },
|
||||
{ "elements cannot be retrieved from a negative array index {0}",
|
||||
"impossible d''extraire un \u00e9l\u00e9ment \u00e0 un index n\u00e9gatif ({0})" },
|
||||
{ "cannot set an element at a negative index {0}",
|
||||
"impossible de mettre un \u00e9l\u00e9ment \u00e0 un index n\u00e9gatif ({0})" },
|
||||
{ "cannot substitute an element from an empty array",
|
||||
"impossible de substituer un \u00e9l\u00e9ment dans un tableau vide" },
|
||||
|
||||
// org.apache.commons.math.analysis.PolynomialFunctionLagrangeForm
|
||||
{ "identical abscissas x[{0}] == x[{1}] == {2} cause division by zero",
|
||||
"division par z\u00e9ro caus\u00e9e par les abscisses identiques x[{0}] == x[{1}] == {2}" },
|
||||
|
||||
// org.apache.commons.math.fraction.Fraction
|
||||
{ "zero denominator in fraction {0}/{1}",
|
||||
"d\u00e9nominateur null dans le nombre rationnel {0}/{1}" },
|
||||
{ "overflow in fraction {0}/{1}, cannot negate",
|
||||
"d\u00e9passement de capacit\u00e9 pour la fraction {0}/{1}, son signe ne peut \u00eatre chang\u00e9" },
|
||||
{ "overflow, numerator too large after multiply: {0}",
|
||||
"d\u00e9passement de capacit\u00e9 pour le num\u00e9rateur apr\u00e8s multiplication : {0}" },
|
||||
{ "the fraction to divide by must not be zero: {0}/{1}",
|
||||
"division par un nombre rationnel nul : {0}/{1}" },
|
||||
|
||||
// org.apache.commons.math.geometry.Rotation
|
||||
{ "zero norm for rotation axis",
|
||||
"norme nulle pour un axe de rotation" },
|
||||
|
||||
// org.apache.commons.math.geometry.Vector3D
|
||||
// org.apache.commons.math.linear.RealVectorImpl
|
||||
{ "cannot normalize a zero norm vector",
|
||||
"impossible de normer un vecteur de norme nulle" },
|
||||
{ "zero norm",
|
||||
"norme nulle" },
|
||||
|
||||
// org.apache.commons.math.analysis.UnivariateRealIntegratorImpl
|
||||
// org.apache.commons.math.analysis.UnivariateRealSolverImpl
|
||||
{ "no result available",
|
||||
"aucun r\u00e9sultat n''est disponible" },
|
||||
|
||||
// org.apache.commons.math.linear.BigMatrixImpl
|
||||
{ "first {0} rows are not initialized yet",
|
||||
"les {0} premi\u00e8res lignes ne sont pas encore initialis\u00e9es" },
|
||||
{ "first {0} columns are not initialized yet",
|
||||
"les {0} premi\u00e8res colonnes ne sont pas encore initialis\u00e9es" },
|
||||
|
||||
// org.apache.commons.math.linear.EigenDecompositionImpl
|
||||
// org.apache.commons.math.linear.LUDecompositionImpl
|
||||
// org.apache.commons.math.linear.QRDecompositionImpl
|
||||
// org.apache.commons.math.linear.SingularValueDecompositionImpl
|
||||
{ "no matrix have been decomposed yet",
|
||||
"aucune matrice n''a encore \u00e9t\u00e9 d\u00e9compos\u00e9e" },
|
||||
|
||||
// org.apache.commons.math.random.EmpiricalDistributionImpl
|
||||
{ "distribution not loaded",
|
||||
"aucune distribution n''a \u00e9t\u00e9 charg\u00e9e" },
|
||||
|
||||
// org.apache.commons.math.random.ValueServer
|
||||
{ "unknown mode {0}, known modes: {1} ({2}), {3} ({4}), {5} ({6}), {7} ({8}), {9} ({10}) and {11} ({12})",
|
||||
"mode {0} inconnu, modes connus : {1} ({2}), {3} ({4}), {5} ({6}), {7} ({8}), {9} ({10}) et {11} ({12})" },
|
||||
{ "digest not initialized",
|
||||
"mod\u00e8le empirique non initialis\u00e9" },
|
||||
|
||||
// org.apache.commons.math.stat.descriptive.moment.GeometricMean
|
||||
// org.apache.commons.math.stat.descriptive.MultivariateSummaryStatistics
|
||||
// org.apache.commons.math.stat.descriptive.SummaryStatistics
|
||||
{ "{0} values have been added before statistic is configured",
|
||||
"{0} valeurs ont \u00e9t\u00e9 ajout\u00e9es avant que la statistique ne soit configur\u00e9e" },
|
||||
|
||||
// org.apache.commons.math.stat.descriptive.moment.Kurtosis
|
||||
{ "statistics constructed from external moments cannot be incremented",
|
||||
"les statistiques bas\u00e9es sur des moments externes ne peuvent pas \u00eatre incr\u00e9ment\u00e9es" },
|
||||
{ "statistics constructed from external moments cannot be cleared",
|
||||
"les statistiques bas\u00e9es sur des moments externes ne peuvent pas \u00eatre remises \u00e0 z\u00e9ro" }
|
||||
|
||||
};
|
||||
|
||||
|
@ -26,7 +26,7 @@ import org.apache.commons.math.MaxIterationsExceededException;
|
||||
* <p>
|
||||
* The function should be continuous but not necessarily smooth.</p>
|
||||
*
|
||||
* @version $Revision$ $Date$
|
||||
* @version $Revision:670469 $ $Date:2008-06-23 10:01:38 +0200 (lun., 23 juin 2008) $
|
||||
*/
|
||||
public class BrentSolver extends UnivariateRealSolverImpl {
|
||||
|
||||
|
@ -27,7 +27,7 @@ import org.apache.commons.math.DuplicateSampleAbscissaException;
|
||||
* functions. For reference, see <b>Introduction to Numerical Analysis</b>,
|
||||
* ISBN 038795452X, chapter 2.
|
||||
* <p>
|
||||
* The actual code of Neville's evalution is in PolynomialFunctionLagrangeForm,
|
||||
* The actual code of Neville's evaluation is in PolynomialFunctionLagrangeForm,
|
||||
* this class provides an easy-to-use interface to it.</p>
|
||||
*
|
||||
* @version $Revision$ $Date$
|
||||
|
@ -20,6 +20,7 @@ import java.io.Serializable;
|
||||
|
||||
import org.apache.commons.math.DuplicateSampleAbscissaException;
|
||||
import org.apache.commons.math.FunctionEvaluationException;
|
||||
import org.apache.commons.math.MathRuntimeException;
|
||||
|
||||
/**
|
||||
* Implements the representation of a real polynomial function in
|
||||
@ -253,8 +254,14 @@ public class PolynomialFunctionLagrangeForm implements UnivariateRealFunction,
|
||||
}
|
||||
if (d == 0.0) {
|
||||
// This happens only when two abscissas are identical.
|
||||
throw new ArithmeticException
|
||||
("Identical abscissas cause division by zero.");
|
||||
for (int k = 0; k < n; ++k) {
|
||||
if ((i != k) && (x[i] == x[k])) {
|
||||
throw MathRuntimeException.createArithmeticException("identical abscissas x[{0}] == x[{1}] == {2} cause division by zero",
|
||||
new Object[] {
|
||||
i, k, x[i]
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
t = y[i] / d;
|
||||
// Lagrange polynomial is the sum of n terms, each of which is a
|
||||
|
@ -18,6 +18,8 @@ package org.apache.commons.math.analysis;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.apache.commons.math.MathRuntimeException;
|
||||
|
||||
/**
|
||||
* Provide a default implementation for several generic functions.
|
||||
*
|
||||
@ -99,7 +101,7 @@ public abstract class UnivariateRealIntegratorImpl implements
|
||||
if (resultComputed) {
|
||||
return result;
|
||||
} else {
|
||||
throw new IllegalStateException("No result available.");
|
||||
throw MathRuntimeException.createIllegalStateException("no result available", null);
|
||||
}
|
||||
}
|
||||
|
||||
@ -113,7 +115,7 @@ public abstract class UnivariateRealIntegratorImpl implements
|
||||
if (resultComputed) {
|
||||
return iterationCount;
|
||||
} else {
|
||||
throw new IllegalStateException("No result available.");
|
||||
throw MathRuntimeException.createIllegalStateException("no result available", null);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,8 +16,6 @@
|
||||
*/
|
||||
package org.apache.commons.math.analysis;
|
||||
|
||||
import org.apache.commons.discovery.tools.DiscoverClass;
|
||||
|
||||
/**
|
||||
* Abstract factory class used to create {@link UnivariateRealSolver} instances.
|
||||
* <p>
|
||||
@ -37,11 +35,6 @@ import org.apache.commons.discovery.tools.DiscoverClass;
|
||||
* BrentSolver solver = factory.newBrentSolver(f);
|
||||
* </pre>
|
||||
*
|
||||
* <a href="http://commons.apache.org/discovery/">Apache Commons Discovery</a>
|
||||
* is used to determine the concrete factory returned by
|
||||
* <code>UnivariateRealSolverFactory.newInstance().</code> The default is
|
||||
* {@link UnivariateRealSolverFactoryImpl}.
|
||||
*
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
public abstract class UnivariateRealSolverFactory {
|
||||
@ -56,16 +49,7 @@ public abstract class UnivariateRealSolverFactory {
|
||||
* @return a new factory.
|
||||
*/
|
||||
public static UnivariateRealSolverFactory newInstance() {
|
||||
UnivariateRealSolverFactory factory = null;
|
||||
try {
|
||||
DiscoverClass dc = new DiscoverClass();
|
||||
factory = (UnivariateRealSolverFactory) dc.newInstance(
|
||||
UnivariateRealSolverFactory.class,
|
||||
"org.apache.commons.math.analysis.UnivariateRealSolverFactoryImpl");
|
||||
} catch(Throwable t) {
|
||||
return new UnivariateRealSolverFactoryImpl();
|
||||
}
|
||||
return factory;
|
||||
return new UnivariateRealSolverFactoryImpl();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -20,6 +20,7 @@ package org.apache.commons.math.analysis;
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.apache.commons.math.FunctionEvaluationException;
|
||||
import org.apache.commons.math.MathRuntimeException;
|
||||
|
||||
/**
|
||||
* Provide a default implementation for several functions useful to generic
|
||||
@ -111,7 +112,7 @@ public abstract class UnivariateRealSolverImpl implements UnivariateRealSolver,
|
||||
if (resultComputed) {
|
||||
return result;
|
||||
} else {
|
||||
throw new IllegalStateException("No result available");
|
||||
throw MathRuntimeException.createIllegalStateException("no result available", null);
|
||||
}
|
||||
}
|
||||
|
||||
@ -126,7 +127,7 @@ public abstract class UnivariateRealSolverImpl implements UnivariateRealSolver,
|
||||
if (resultComputed) {
|
||||
return iterationCount;
|
||||
} else {
|
||||
throw new IllegalStateException("No result available");
|
||||
throw MathRuntimeException.createIllegalStateException("no result available", null);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -199,9 +199,9 @@ public class UnivariateRealSolverUtils {
|
||||
if (fa * fb >= 0.0 ) {
|
||||
throw new ConvergenceException
|
||||
("Number of iterations={0}, maximum iterations={1}, initial={2}, lower bound={3}, upper bound={4}, final a value={5}, final b value={6}, f(a)={7}, f(b)={8}",
|
||||
new Object[] { new Integer(numIterations), new Integer(maximumIterations),
|
||||
new Double(initial), new Double(lowerBound), new Double(upperBound),
|
||||
new Double(a), new Double(b), new Double(fa), new Double(fb) });
|
||||
new Object[] { Integer.valueOf(numIterations), Integer.valueOf(maximumIterations),
|
||||
Double.valueOf(initial), Double.valueOf(lowerBound), Double.valueOf(upperBound),
|
||||
Double.valueOf(a), Double.valueOf(b), Double.valueOf(fa), Double.valueOf(fb) });
|
||||
}
|
||||
|
||||
return new double[]{a, b};
|
||||
|
@ -58,15 +58,13 @@ public class Complex implements Serializable {
|
||||
|
||||
/**
|
||||
* The imaginary part
|
||||
* @deprecated to be made final and private in 2.0
|
||||
*/
|
||||
protected double imaginary;
|
||||
private final double imaginary;
|
||||
|
||||
/**
|
||||
* The real part
|
||||
* @deprecated to be made final and private in 2.0
|
||||
*/
|
||||
protected double real;
|
||||
private final double real;
|
||||
|
||||
/**
|
||||
* Create a complex number given the real and imaginary parts.
|
||||
@ -257,10 +255,7 @@ public class Complex implements Serializable {
|
||||
if (rhs.isNaN()) {
|
||||
ret = this.isNaN();
|
||||
} else {
|
||||
ret = (Double.doubleToRawLongBits(real) ==
|
||||
Double.doubleToRawLongBits(rhs.getReal())) &&
|
||||
(Double.doubleToRawLongBits(imaginary) ==
|
||||
Double.doubleToRawLongBits(rhs.getImaginary()));
|
||||
ret = (real == rhs.real) && (imaginary == rhs.imaginary);
|
||||
}
|
||||
} catch (ClassCastException ex) {
|
||||
// ignore exception
|
||||
|
@ -17,28 +17,29 @@
|
||||
|
||||
package org.apache.commons.math.complex;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.text.FieldPosition;
|
||||
import java.text.Format;
|
||||
import java.text.NumberFormat;
|
||||
import java.text.ParseException;
|
||||
import java.text.ParsePosition;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.apache.commons.math.MathRuntimeException;
|
||||
import org.apache.commons.math.util.CompositeFormat;
|
||||
|
||||
/**
|
||||
* Formats a Complex number in cartesian format "Re(c) + Im(c)i". 'i' can
|
||||
* be replaced with 'j', and the number format for both real and imaginary parts
|
||||
* can be configured.
|
||||
* be replaced with 'j' (or anything else), and the number format for both real
|
||||
* and imaginary parts can be configured.
|
||||
*
|
||||
* @author Apache Software Foundation
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
public class ComplexFormat extends Format implements Serializable {
|
||||
public class ComplexFormat extends CompositeFormat {
|
||||
|
||||
/** Serializable version identifier */
|
||||
private static final long serialVersionUID = -6337346779577272306L;
|
||||
|
||||
/** The default imaginary character. */
|
||||
private static final long serialVersionUID = -3343698360149467646L;
|
||||
|
||||
/** The default imaginary character. */
|
||||
private static final String DEFAULT_IMAGINARY_CHARACTER = "i";
|
||||
|
||||
/** The notation used to signify the imaginary part of the complex number. */
|
||||
@ -73,8 +74,7 @@ public class ComplexFormat extends Format implements Serializable {
|
||||
* @param realFormat the custom format for the real part.
|
||||
* @param imaginaryFormat the custom format for the imaginary part.
|
||||
*/
|
||||
public ComplexFormat(NumberFormat realFormat,
|
||||
NumberFormat imaginaryFormat) {
|
||||
public ComplexFormat(NumberFormat realFormat, NumberFormat imaginaryFormat) {
|
||||
this(DEFAULT_IMAGINARY_CHARACTER, realFormat, imaginaryFormat);
|
||||
}
|
||||
|
||||
@ -114,14 +114,23 @@ public class ComplexFormat extends Format implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* This static method calls formatComplex() on a default instance of
|
||||
* Get the set of locales for which complex formats are available.
|
||||
* <p>This is the same set as the {@link NumberFormat} set.</p>
|
||||
* @return available complex format locales.
|
||||
*/
|
||||
public static Locale[] getAvailableLocales() {
|
||||
return NumberFormat.getAvailableLocales();
|
||||
}
|
||||
|
||||
/**
|
||||
* This static method calls {@link #format(Object)} on a default instance of
|
||||
* ComplexFormat.
|
||||
*
|
||||
* @param c Complex object to format
|
||||
* @return A formatted number in the form "Re(c) + Im(c)i"
|
||||
*/
|
||||
public static String formatComplex( Complex c ) {
|
||||
return getInstance().format( c );
|
||||
public static String formatComplex(Complex c) {
|
||||
return getInstance().format(c);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -182,74 +191,12 @@ public class ComplexFormat extends Format implements Serializable {
|
||||
ret = format( new Complex(((Number)obj).doubleValue(), 0.0),
|
||||
toAppendTo, pos);
|
||||
} else {
|
||||
throw new IllegalArgumentException(
|
||||
"Cannot format given Object as a Date");
|
||||
throw new IllegalArgumentException("Cannot format given Object as a Complex");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a double value to produce a string. In general, the value is
|
||||
* formatted using the formatting rules of <code>format</code>. There are
|
||||
* three exceptions to this:
|
||||
* <ol>
|
||||
* <li>NaN is formatted as '(NaN)'</li>
|
||||
* <li>Positive infinity is formatted as '(Infinity)'</li>
|
||||
* <li>Negative infinity is formatted as '(-Infinity)'</li>
|
||||
* </ol>
|
||||
*
|
||||
* @param value the double to format.
|
||||
* @param format the format used.
|
||||
* @param toAppendTo where the text is to be appended
|
||||
* @param pos On input: an alignment field, if desired. On output: the
|
||||
* offsets of the alignment field
|
||||
* @return the value passed in as toAppendTo.
|
||||
*/
|
||||
private StringBuffer formatDouble(double value, NumberFormat format,
|
||||
StringBuffer toAppendTo, FieldPosition pos) {
|
||||
if( Double.isNaN(value) || Double.isInfinite(value) ) {
|
||||
toAppendTo.append('(');
|
||||
toAppendTo.append(value);
|
||||
toAppendTo.append(')');
|
||||
} else {
|
||||
format.format(value, toAppendTo, pos);
|
||||
}
|
||||
return toAppendTo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the set of locales for which complex formats are available. This
|
||||
* is the same set as the {@link NumberFormat} set.
|
||||
* @return available complex format locales.
|
||||
*/
|
||||
public static Locale[] getAvailableLocales() {
|
||||
return NumberFormat.getAvailableLocales();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a default number format. The default number format is based on
|
||||
* {@link NumberFormat#getInstance()} with the only customizing is the
|
||||
* maximum number of fraction digits, which is set to 2.
|
||||
* @return the default number format.
|
||||
*/
|
||||
private static NumberFormat getDefaultNumberFormat() {
|
||||
return getDefaultNumberFormat(Locale.getDefault());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a default number format. The default number format is based on
|
||||
* {@link NumberFormat#getInstance(java.util.Locale)} with the only
|
||||
* customizing is the maximum number of fraction digits, which is set to 2.
|
||||
* @param locale the specific locale used by the format.
|
||||
* @return the default number format specific to the given locale.
|
||||
*/
|
||||
private static NumberFormat getDefaultNumberFormat(Locale locale) {
|
||||
NumberFormat nf = NumberFormat.getInstance(locale);
|
||||
nf.setMaximumFractionDigits(2);
|
||||
return nf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Access the imaginaryCharacter.
|
||||
* @return the imaginaryCharacter.
|
||||
@ -304,8 +251,9 @@ public class ComplexFormat extends Format implements Serializable {
|
||||
ParsePosition parsePosition = new ParsePosition(0);
|
||||
Complex result = parse(source, parsePosition);
|
||||
if (parsePosition.getIndex() == 0) {
|
||||
throw new ParseException("Unparseable complex number: \"" + source +
|
||||
"\"", parsePosition.getErrorIndex());
|
||||
throw MathRuntimeException.createParseException("unparseable complex number: \"{0}\"",
|
||||
new Object[] { source },
|
||||
parsePosition.getErrorIndex());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -328,7 +276,6 @@ public class ComplexFormat extends Format implements Serializable {
|
||||
if (re == null) {
|
||||
// invalid real number
|
||||
// set index back to initial, error index should already be set
|
||||
// character examined.
|
||||
pos.setIndex(initialIndex);
|
||||
return null;
|
||||
}
|
||||
@ -365,129 +312,19 @@ public class ComplexFormat extends Format implements Serializable {
|
||||
if (im == null) {
|
||||
// invalid imaginary number
|
||||
// set index back to initial, error index should already be set
|
||||
// character examined.
|
||||
pos.setIndex(initialIndex);
|
||||
return null;
|
||||
}
|
||||
|
||||
// parse imaginary character
|
||||
int n = getImaginaryCharacter().length();
|
||||
startIndex = pos.getIndex();
|
||||
int endIndex = startIndex + n;
|
||||
if ((startIndex >= source.length()) ||
|
||||
(endIndex > source.length()) ||
|
||||
source.substring(startIndex, endIndex).compareTo(
|
||||
getImaginaryCharacter()) != 0) {
|
||||
// set index back to initial, error index should be the start index
|
||||
// character examined.
|
||||
pos.setIndex(initialIndex);
|
||||
pos.setErrorIndex(startIndex);
|
||||
if (!parseFixedstring(source, getImaginaryCharacter(), pos)) {
|
||||
return null;
|
||||
}
|
||||
pos.setIndex(endIndex);
|
||||
|
||||
return new Complex(re.doubleValue(), im.doubleValue() * sign);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses <code>source</code> until a non-whitespace character is found.
|
||||
*
|
||||
* @param source the string to parse
|
||||
* @param pos input/ouput parsing parameter. On output, <code>pos</code>
|
||||
* holds the index of the next non-whitespace character.
|
||||
*/
|
||||
private void parseAndIgnoreWhitespace(String source, ParsePosition pos) {
|
||||
parseNextCharacter(source, pos);
|
||||
pos.setIndex(pos.getIndex() - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses <code>source</code> until a non-whitespace character is found.
|
||||
*
|
||||
* @param source the string to parse
|
||||
* @param pos input/ouput parsing parameter.
|
||||
* @return the first non-whitespace character.
|
||||
*/
|
||||
private char parseNextCharacter(String source, ParsePosition pos) {
|
||||
int index = pos.getIndex();
|
||||
int n = source.length();
|
||||
char ret = 0;
|
||||
|
||||
if (index < n) {
|
||||
char c;
|
||||
do {
|
||||
c = source.charAt(index++);
|
||||
} while (Character.isWhitespace(c) && index < n);
|
||||
pos.setIndex(index);
|
||||
|
||||
if (index < n) {
|
||||
ret = c;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses <code>source</code> for a special double values. These values
|
||||
* include Double.NaN, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY.
|
||||
*
|
||||
* @param source the string to parse
|
||||
* @param value the special value to parse.
|
||||
* @param pos input/ouput parsing parameter.
|
||||
* @return the special number.
|
||||
*/
|
||||
private Number parseNumber(String source, double value, ParsePosition pos) {
|
||||
Number ret = null;
|
||||
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append('(');
|
||||
sb.append(value);
|
||||
sb.append(')');
|
||||
|
||||
int n = sb.length();
|
||||
int startIndex = pos.getIndex();
|
||||
int endIndex = startIndex + n;
|
||||
if (endIndex < source.length()) {
|
||||
if (source.substring(startIndex, endIndex).compareTo(sb.toString()) == 0) {
|
||||
ret = new Double(value);
|
||||
pos.setIndex(endIndex);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses <code>source</code> for a number. This method can parse normal,
|
||||
* numeric values as well as special values. These special values include
|
||||
* Double.NaN, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY.
|
||||
*
|
||||
* @param source the string to parse
|
||||
* @param format the number format used to parse normal, numeric values.
|
||||
* @param pos input/ouput parsing parameter.
|
||||
* @return the parsed number.
|
||||
*/
|
||||
private Number parseNumber(String source, NumberFormat format, ParsePosition pos) {
|
||||
int startIndex = pos.getIndex();
|
||||
Number number = format.parse(source, pos);
|
||||
int endIndex = pos.getIndex();
|
||||
|
||||
// check for error parsing number
|
||||
if (startIndex == endIndex) {
|
||||
// try parsing special numbers
|
||||
double[] special = {Double.NaN, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY};
|
||||
for (int i = 0; i < special.length; ++i) {
|
||||
number = parseNumber(source, special[i], pos);
|
||||
if (number != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a string to produce a object.
|
||||
*
|
||||
@ -499,6 +336,7 @@ public class ComplexFormat extends Format implements Serializable {
|
||||
public Object parseObject(String source, ParsePosition pos) {
|
||||
return parse(source, pos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Modify the imaginaryCharacter.
|
||||
* @param imaginaryCharacter The new imaginaryCharacter value.
|
||||
@ -540,4 +378,5 @@ public class ComplexFormat extends Format implements Serializable {
|
||||
}
|
||||
this.realFormat = realFormat;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -17,23 +17,9 @@
|
||||
|
||||
package org.apache.commons.math.complex;
|
||||
|
||||
import org.apache.commons.math.util.MathUtils;
|
||||
|
||||
/**
|
||||
* Static implementations of common
|
||||
* {@link org.apache.commons.math.complex.Complex}-valued functions. Included
|
||||
* are trigonometric, exponential, log, power and square root functions.
|
||||
*<p>
|
||||
* Reference:
|
||||
* <ul>
|
||||
* <li><a href="http://myweb.lmu.edu/dmsmith/ZMLIB.pdf">
|
||||
* Multiple Precision Complex Arithmetic and Functions</a></li>
|
||||
* </ul>
|
||||
* See individual method javadocs for the computational formulas used.
|
||||
* In general, NaN values in either real or imaginary parts of input arguments
|
||||
* result in {@link Complex#NaN} returned. Otherwise, infinite or NaN values
|
||||
* are returned as they arise in computing the real functions specified in the
|
||||
* computational formulas. Null arguments result in NullPointerExceptions.
|
||||
* {@link org.apache.commons.math.complex.Complex} utilities functions.
|
||||
*
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
@ -46,198 +32,6 @@ public class ComplexUtils {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the
|
||||
* <a href="http://mathworld.wolfram.com/InverseCosine.html" TARGET="_top">
|
||||
* inverse cosine</a> for the given complex argument.
|
||||
* <p>
|
||||
* Implements the formula: <pre>
|
||||
* <code> acos(z) = -i (log(z + i (sqrt(1 - z<sup>2</sup>))))</code></pre>
|
||||
* <p>
|
||||
* Returns {@link Complex#NaN} if either real or imaginary part of the
|
||||
* input argument is <code>NaN</code> or infinite.
|
||||
*
|
||||
* @param z the value whose inverse cosine is to be returned
|
||||
* @return the inverse cosine of <code>z</code>
|
||||
* @throws NullPointerException if <code>z</code> is null
|
||||
* @deprecated use Complex.acos()
|
||||
*/
|
||||
public static Complex acos(Complex z) {
|
||||
return z.acos();
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the
|
||||
* <a href="http://mathworld.wolfram.com/InverseSine.html" TARGET="_top">
|
||||
* inverse sine</a> for the given complex argument.
|
||||
* <p>
|
||||
* Implements the formula: <pre>
|
||||
* <code> asin(z) = -i (log(sqrt(1 - z<sup>2</sup>) + iz)) </code></pre>
|
||||
* <p>
|
||||
* Returns {@link Complex#NaN} if either real or imaginary part of the
|
||||
* input argument is <code>NaN</code> or infinite.
|
||||
*
|
||||
* @param z the value whose inverse sine is to be returned.
|
||||
* @return the inverse sine of <code>z</code>.
|
||||
* @throws NullPointerException if <code>z</code> is null
|
||||
* @deprecated use Complex.asin()
|
||||
*/
|
||||
public static Complex asin(Complex z) {
|
||||
return z.asin();
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the
|
||||
* <a href="http://mathworld.wolfram.com/InverseTangent.html" TARGET="_top">
|
||||
* inverse tangent</a> for the given complex argument.
|
||||
* <p>
|
||||
* Implements the formula: <pre>
|
||||
* <code> atan(z) = (i/2) log((i + z)/(i - z)) </code></pre>
|
||||
* <p>
|
||||
* Returns {@link Complex#NaN} if either real or imaginary part of the
|
||||
* input argument is <code>NaN</code> or infinite.
|
||||
*
|
||||
* @param z the value whose inverse tangent is to be returned
|
||||
* @return the inverse tangent of <code>z</code>
|
||||
* @throws NullPointerException if <code>z</code> is null
|
||||
* @deprecated use Complex.atan()
|
||||
*/
|
||||
public static Complex atan(Complex z) {
|
||||
return z.atan();
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the
|
||||
* <a href="http://mathworld.wolfram.com/Cosine.html" TARGET="_top">
|
||||
* cosine</a>
|
||||
* for the given complex argument.
|
||||
* <p>
|
||||
* Implements the formula: <pre>
|
||||
* <code> cos(a + bi) = cos(a)cosh(b) - sin(a)sinh(b)i</code></pre>
|
||||
* where the (real) functions on the right-hand side are
|
||||
* {@link java.lang.Math#sin}, {@link java.lang.Math#cos},
|
||||
* {@link MathUtils#cosh} and {@link MathUtils#sinh}.
|
||||
* <p>
|
||||
* Returns {@link Complex#NaN} if either real or imaginary part of the
|
||||
* input argument is <code>NaN</code>.
|
||||
* <p>
|
||||
* Infinite values in real or imaginary parts of the input may result in
|
||||
* infinite or NaN values returned in parts of the result.<pre>
|
||||
* Examples:
|
||||
* <code>
|
||||
* cos(1 ± INFINITY i) = 1 ∓ INFINITY i
|
||||
* cos(±INFINITY + i) = NaN + NaN i
|
||||
* cos(±INFINITY ± INFINITY i) = NaN + NaN i</code></pre>
|
||||
*
|
||||
* @param z the value whose cosine is to be returned
|
||||
* @return the cosine of <code>z</code>
|
||||
* @throws NullPointerException if <code>z</code> is null
|
||||
* @deprecated use Complex.cos()
|
||||
*/
|
||||
public static Complex cos(Complex z) {
|
||||
return z.cos();
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the
|
||||
* <a href="http://mathworld.wolfram.com/HyperbolicCosine.html" TARGET="_top">
|
||||
* hyperbolic cosine</a> for the given complex argument.
|
||||
* <p>
|
||||
* Implements the formula: <pre>
|
||||
* <code> cosh(a + bi) = cosh(a)cos(b) + sinh(a)sin(b)i</code></pre>
|
||||
* where the (real) functions on the right-hand side are
|
||||
* {@link java.lang.Math#sin}, {@link java.lang.Math#cos},
|
||||
* {@link MathUtils#cosh} and {@link MathUtils#sinh}.
|
||||
* <p>
|
||||
* Returns {@link Complex#NaN} if either real or imaginary part of the
|
||||
* input argument is <code>NaN</code>.
|
||||
* <p>
|
||||
* Infinite values in real or imaginary parts of the input may result in
|
||||
* infinite or NaN values returned in parts of the result.<pre>
|
||||
* Examples:
|
||||
* <code>
|
||||
* cosh(1 ± INFINITY i) = NaN + NaN i
|
||||
* cosh(±INFINITY + i) = INFINITY ± INFINITY i
|
||||
* cosh(±INFINITY ± INFINITY i) = NaN + NaN i</code></pre>
|
||||
* <p>
|
||||
* Throws <code>NullPointerException</code> if z is null.
|
||||
*
|
||||
* @param z the value whose hyperbolic cosine is to be returned.
|
||||
* @return the hyperbolic cosine of <code>z</code>.
|
||||
* @deprecated use Complex.cosh()
|
||||
*/
|
||||
public static Complex cosh(Complex z) {
|
||||
return z.cosh();
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the
|
||||
* <a href="http://mathworld.wolfram.com/ExponentialFunction.html" TARGET="_top">
|
||||
* exponential function</a> for the given complex argument.
|
||||
* <p>
|
||||
* Implements the formula: <pre>
|
||||
* <code> exp(a + bi) = exp(a)cos(b) + exp(a)sin(b)i</code></pre>
|
||||
* where the (real) functions on the right-hand side are
|
||||
* {@link java.lang.Math#exp}, {@link java.lang.Math#cos}, and
|
||||
* {@link java.lang.Math#sin}.
|
||||
* <p>
|
||||
* Returns {@link Complex#NaN} if either real or imaginary part of the
|
||||
* input argument is <code>NaN</code>.
|
||||
* <p>
|
||||
* Infinite values in real or imaginary parts of the input may result in
|
||||
* infinite or NaN values returned in parts of the result.<pre>
|
||||
* Examples:
|
||||
* <code>
|
||||
* exp(1 ± INFINITY i) = NaN + NaN i
|
||||
* exp(INFINITY + i) = INFINITY + INFINITY i
|
||||
* exp(-INFINITY + i) = 0 + 0i
|
||||
* exp(±INFINITY ± INFINITY i) = NaN + NaN i</code></pre>
|
||||
* <p>
|
||||
* Throws <code>NullPointerException</code> if z is null.
|
||||
*
|
||||
* @param z the value
|
||||
* @return <i>e</i><sup><code>z</code></sup>
|
||||
* @deprecated use Complex.exp()
|
||||
*/
|
||||
public static Complex exp(Complex z) {
|
||||
return z.exp();
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the
|
||||
* <a href="http://mathworld.wolfram.com/NaturalLogarithm.html" TARGET="_top">
|
||||
* natural logarithm</a> for the given complex argument.
|
||||
* <p>
|
||||
* Implements the formula: <pre>
|
||||
* <code> log(a + bi) = ln(|a + bi|) + arg(a + bi)i</code></pre>
|
||||
* where ln on the right hand side is {@link java.lang.Math#log},
|
||||
* <code>|a + bi|</code> is the modulus, {@link Complex#abs}, and
|
||||
* <code>arg(a + bi) = {@link java.lang.Math#atan2}(b, a)</code>
|
||||
* <p>
|
||||
* Returns {@link Complex#NaN} if either real or imaginary part of the
|
||||
* input argument is <code>NaN</code>.
|
||||
* <p>
|
||||
* Infinite (or critical) values in real or imaginary parts of the input may
|
||||
* result in infinite or NaN values returned in parts of the result.<pre>
|
||||
* Examples:
|
||||
* <code>
|
||||
* log(1 ± INFINITY i) = INFINITY ± (π/2)i
|
||||
* log(INFINITY + i) = INFINITY + 0i
|
||||
* log(-INFINITY + i) = INFINITY + πi
|
||||
* log(INFINITY ± INFINITY i) = INFINITY ± (π/4)i
|
||||
* log(-INFINITY ± INFINITY i) = INFINITY ± (3π/4)i
|
||||
* log(0 + 0i) = -INFINITY + 0i
|
||||
* </code></pre>
|
||||
* Throws <code>NullPointerException</code> if z is null.
|
||||
*
|
||||
* @param z the value.
|
||||
* @return ln <code>z</code>.
|
||||
* @deprecated use Complex.log()
|
||||
*/
|
||||
public static Complex log(Complex z) {
|
||||
return z.log();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a complex number from the given polar representation.
|
||||
* <p>
|
||||
@ -271,216 +65,4 @@ public class ComplexUtils {
|
||||
return new Complex(r * Math.cos(theta), r * Math.sin(theta));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns of value of <code>y</code> raised to the power of <code>x</code>.
|
||||
* <p>
|
||||
* Implements the formula: <pre>
|
||||
* <code> y<sup>x</sup> = exp(x·log(y))</code></pre>
|
||||
* where <code>exp</code> and <code>log</code> are {@link #exp} and
|
||||
* {@link #log}, respectively.
|
||||
* <p>
|
||||
* Returns {@link Complex#NaN} if either real or imaginary part of the
|
||||
* input argument is <code>NaN</code> or infinite, or if <code>y</code>
|
||||
* equals {@link Complex#ZERO}.
|
||||
*
|
||||
* @param y the base.
|
||||
* @param x the exponent.
|
||||
* @return <code>y</code><sup><code>x</code></sup>
|
||||
* @throws NullPointerException if either x or y is null
|
||||
* @deprecated use Complex.pow(x)
|
||||
*/
|
||||
public static Complex pow(Complex y, Complex x) {
|
||||
return y.pow(x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the
|
||||
* <a href="http://mathworld.wolfram.com/Sine.html" TARGET="_top">
|
||||
* sine</a>
|
||||
* for the given complex argument.
|
||||
* <p>
|
||||
* Implements the formula: <pre>
|
||||
* <code> sin(a + bi) = sin(a)cosh(b) - cos(a)sinh(b)i</code></pre>
|
||||
* where the (real) functions on the right-hand side are
|
||||
* {@link java.lang.Math#sin}, {@link java.lang.Math#cos},
|
||||
* {@link MathUtils#cosh} and {@link MathUtils#sinh}.
|
||||
* <p>
|
||||
* Returns {@link Complex#NaN} if either real or imaginary part of the
|
||||
* input argument is <code>NaN</code>.
|
||||
* <p>
|
||||
* Infinite values in real or imaginary parts of the input may result in
|
||||
* infinite or NaN values returned in parts of the result.<pre>
|
||||
* Examples:
|
||||
* <code>
|
||||
* sin(1 ± INFINITY i) = 1 ± INFINITY i
|
||||
* sin(±INFINITY + i) = NaN + NaN i
|
||||
* sin(±INFINITY ± INFINITY i) = NaN + NaN i</code></pre>
|
||||
*
|
||||
* Throws <code>NullPointerException</code> if z is null.
|
||||
*
|
||||
* @param z the value whose sine is to be returned.
|
||||
* @return the sine of <code>z</code>.
|
||||
* @deprecated use Complex.sin()
|
||||
*/
|
||||
public static Complex sin(Complex z) {
|
||||
return z.sin();
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the
|
||||
* <a href="http://mathworld.wolfram.com/HyperbolicSine.html" TARGET="_top">
|
||||
* hyperbolic sine</a> for the given complex argument.
|
||||
* <p>
|
||||
* Implements the formula: <pre>
|
||||
* <code> sinh(a + bi) = sinh(a)cos(b)) + cosh(a)sin(b)i</code></pre>
|
||||
* where the (real) functions on the right-hand side are
|
||||
* {@link java.lang.Math#sin}, {@link java.lang.Math#cos},
|
||||
* {@link MathUtils#cosh} and {@link MathUtils#sinh}.
|
||||
* <p>
|
||||
* Returns {@link Complex#NaN} if either real or imaginary part of the
|
||||
* input argument is <code>NaN</code>.
|
||||
* <p>
|
||||
* Infinite values in real or imaginary parts of the input may result in
|
||||
* infinite or NaN values returned in parts of the result.<pre>
|
||||
* Examples:
|
||||
* <code>
|
||||
* sinh(1 ± INFINITY i) = NaN + NaN i
|
||||
* sinh(±INFINITY + i) = ± INFINITY + INFINITY i
|
||||
* sinh(±INFINITY ± INFINITY i) = NaN + NaN i</code></pre
|
||||
*
|
||||
* @param z the value whose hyperbolic sine is to be returned
|
||||
* @return the hyperbolic sine of <code>z</code>
|
||||
* @throws NullPointerException if <code>z</code> is null
|
||||
* @deprecated use Complex.sinh()
|
||||
*/
|
||||
public static Complex sinh(Complex z) {
|
||||
return z.sinh();
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the
|
||||
* <a href="http://mathworld.wolfram.com/SquareRoot.html" TARGET="_top">
|
||||
* square root</a> for the given complex argument.
|
||||
* <p>
|
||||
* Implements the following algorithm to compute <code>sqrt(a + bi)</code>:
|
||||
* <ol><li>Let <code>t = sqrt((|a| + |a + bi|) / 2)</code></li>
|
||||
* <li><pre>if <code> a ≥ 0</code> return <code>t + (b/2t)i</code>
|
||||
* else return <code>|b|/2t + sign(b)t i </code></pre></li>
|
||||
* </ol>
|
||||
* where <ul>
|
||||
* <li><code>|a| = {@link Math#abs}(a)</code></li>
|
||||
* <li><code>|a + bi| = {@link Complex#abs}(a + bi) </code></li>
|
||||
* <li><code>sign(b) = {@link MathUtils#indicator}(b) </code>
|
||||
* </ul>
|
||||
* <p>
|
||||
* Returns {@link Complex#NaN} if either real or imaginary part of the
|
||||
* input argument is <code>NaN</code>.
|
||||
* <p>
|
||||
* Infinite values in real or imaginary parts of the input may result in
|
||||
* infinite or NaN values returned in parts of the result.<pre>
|
||||
* Examples:
|
||||
* <code>
|
||||
* sqrt(1 ± INFINITY i) = INFINITY + NaN i
|
||||
* sqrt(INFINITY + i) = INFINITY + 0i
|
||||
* sqrt(-INFINITY + i) = 0 + INFINITY i
|
||||
* sqrt(INFINITY ± INFINITY i) = INFINITY + NaN i
|
||||
* sqrt(-INFINITY ± INFINITY i) = NaN ± INFINITY i
|
||||
* </code></pre>
|
||||
*
|
||||
* @param z the value whose square root is to be returned
|
||||
* @return the square root of <code>z</code>
|
||||
* @throws NullPointerException if <code>z</code> is null
|
||||
* @deprecated use Complex.sqrt()
|
||||
*/
|
||||
public static Complex sqrt(Complex z) {
|
||||
return z.sqrt();
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the
|
||||
* <a href="http://mathworld.wolfram.com/SquareRoot.html" TARGET="_top">
|
||||
* square root</a> of 1 - <code>z</code><sup>2</sup> for the given complex
|
||||
* argument.
|
||||
* <p>
|
||||
* Computes the result directly as
|
||||
* <code>sqrt(Complex.ONE.subtract(z.multiply(z)))</code>.
|
||||
* <p>
|
||||
* Returns {@link Complex#NaN} if either real or imaginary part of the
|
||||
* input argument is <code>NaN</code>.
|
||||
* <p>
|
||||
* Infinite values in real or imaginary parts of the input may result in
|
||||
* infinite or NaN values returned in parts of the result.
|
||||
*
|
||||
* @param z the value
|
||||
* @return the square root of 1 - <code>z</code><sup>2</sup>
|
||||
* @throws NullPointerException if <code>z</code> is null
|
||||
* @deprecated use Complex.sqrt1z()
|
||||
*/
|
||||
public static Complex sqrt1z(Complex z) {
|
||||
return z.sqrt1z();
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the
|
||||
* <a href="http://mathworld.wolfram.com/Tangent.html" TARGET="_top">
|
||||
* tangent</a> for the given complex argument.
|
||||
* <p>
|
||||
* Implements the formula: <pre>
|
||||
* <code>tan(a + bi) = sin(2a)/(cos(2a)+cosh(2b)) + [sinh(2b)/(cos(2a)+cosh(2b))]i</code></pre>
|
||||
* where the (real) functions on the right-hand side are
|
||||
* {@link java.lang.Math#sin}, {@link java.lang.Math#cos},
|
||||
* {@link MathUtils#cosh} and {@link MathUtils#sinh}.
|
||||
* <p>
|
||||
* Returns {@link Complex#NaN} if either real or imaginary part of the
|
||||
* input argument is <code>NaN</code>.
|
||||
* <p>
|
||||
* Infinite (or critical) values in real or imaginary parts of the input may
|
||||
* result in infinite or NaN values returned in parts of the result.<pre>
|
||||
* Examples:
|
||||
* <code>
|
||||
* tan(1 ± INFINITY i) = 0 + NaN i
|
||||
* tan(±INFINITY + i) = NaN + NaN i
|
||||
* tan(±INFINITY ± INFINITY i) = NaN + NaN i
|
||||
* tan(±π/2 + 0 i) = ±INFINITY + NaN i</code></pre>
|
||||
*
|
||||
* @param z the value whose tangent is to be returned
|
||||
* @return the tangent of <code>z</code>
|
||||
* @throws NullPointerException if <code>z</code> is null
|
||||
* @deprecated use Complex.tan()
|
||||
*/
|
||||
public static Complex tan(Complex z) {
|
||||
return z.tan();
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the
|
||||
* <a href="http://mathworld.wolfram.com/HyperbolicTangent.html" TARGET="_top">
|
||||
* hyperbolic tangent</a> for the given complex argument.
|
||||
* <p>
|
||||
* Implements the formula: <pre>
|
||||
* <code>tan(a + bi) = sinh(2a)/(cosh(2a)+cos(2b)) + [sin(2b)/(cosh(2a)+cos(2b))]i</code></pre>
|
||||
* where the (real) functions on the right-hand side are
|
||||
* {@link java.lang.Math#sin}, {@link java.lang.Math#cos},
|
||||
* {@link MathUtils#cosh} and {@link MathUtils#sinh}.
|
||||
* <p>
|
||||
* Returns {@link Complex#NaN} if either real or imaginary part of the
|
||||
* input argument is <code>NaN</code>.
|
||||
* <p>
|
||||
* Infinite values in real or imaginary parts of the input may result in
|
||||
* infinite or NaN values returned in parts of the result.<pre>
|
||||
* Examples:
|
||||
* <code>
|
||||
* tanh(1 ± INFINITY i) = NaN + NaN i
|
||||
* tanh(±INFINITY + i) = NaN + 0 i
|
||||
* tanh(±INFINITY ± INFINITY i) = NaN + NaN i
|
||||
* tanh(0 + (π/2)i) = NaN + INFINITY i</code></pre>
|
||||
*
|
||||
* @param z the value whose hyperbolic tangent is to be returned
|
||||
* @return the hyperbolic tangent of <code>z</code>
|
||||
* @throws NullPointerException if <code>z</code> is null
|
||||
* @deprecated use Complex.tanh()
|
||||
*/
|
||||
public static Complex tanh(Complex z) {
|
||||
return z.tanh();
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.commons.math.distribution;
|
||||
|
||||
import org.apache.commons.math.MathException;
|
||||
|
||||
/**
|
||||
* Computes the cumulative, inverse cumulative and density functions for the beta distribuiton.
|
||||
*
|
||||
* @see <a href="http://en.wikipedia.org/wiki/Beta_distribution">Beta_distribution</a>
|
||||
* @version $Revision$ $Date$
|
||||
* @since 2.0
|
||||
*/
|
||||
public interface BetaDistribution extends ContinuousDistribution, HasDensity<Double> {
|
||||
/**
|
||||
* Modify the shape parameter, alpha.
|
||||
* @param alpha the new shape parameter.
|
||||
*/
|
||||
void setAlpha(double alpha);
|
||||
|
||||
/**
|
||||
* Access the shape parameter, alpha
|
||||
* @return alpha.
|
||||
*/
|
||||
double getAlpha();
|
||||
|
||||
/**
|
||||
* Modify the shape parameter, beta.
|
||||
* @param beta the new scale parameter.
|
||||
*/
|
||||
void setBeta(double beta);
|
||||
|
||||
/**
|
||||
* Access the shape parameter, beta
|
||||
* @return beta.
|
||||
*/
|
||||
double getBeta();
|
||||
|
||||
/**
|
||||
* Return the probability density for a particular point.
|
||||
* @param x The point at which the density should be computed.
|
||||
* @return The pdf at point x.
|
||||
* @exception MathException if probability density cannot be computed
|
||||
*/
|
||||
double density(Double x) throws MathException;
|
||||
|
||||
}
|
@ -0,0 +1,157 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.commons.math.distribution;
|
||||
|
||||
import org.apache.commons.math.MathException;
|
||||
import org.apache.commons.math.special.Gamma;
|
||||
import org.apache.commons.math.special.Beta;
|
||||
|
||||
/**
|
||||
* Implements the Beta distribution.
|
||||
* <p>
|
||||
* References:
|
||||
* <ul>
|
||||
* <li><a href="http://en.wikipedia.org/wiki/Beta_distribution">
|
||||
* Beta distribution</a></li>
|
||||
* </ul>
|
||||
* </p>
|
||||
* @version $Revision$ $Date$
|
||||
* @since 2.0
|
||||
*/
|
||||
public class BetaDistributionImpl
|
||||
extends AbstractContinuousDistribution implements BetaDistribution {
|
||||
|
||||
/** Serializable version identifier. */
|
||||
private static final long serialVersionUID = -1221965979403477668L;
|
||||
|
||||
/** First shape parameter. */
|
||||
private double alpha;
|
||||
|
||||
/** Second shape parameter. */
|
||||
private double beta;
|
||||
|
||||
/** Normalizing factor used in density computations.
|
||||
* updated whenever alpha or beta are changed.
|
||||
*/
|
||||
private double z;
|
||||
|
||||
/**
|
||||
* Build a new instance.
|
||||
* @param alpha first shape parameter (must be positive)
|
||||
* @param beta second shape parameter (must be positive)
|
||||
*/
|
||||
public BetaDistributionImpl(double alpha, double beta) {
|
||||
this.alpha = alpha;
|
||||
this.beta = beta;
|
||||
z = Double.NaN;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public void setAlpha(double alpha) {
|
||||
this.alpha = alpha;
|
||||
z = Double.NaN;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public double getAlpha() {
|
||||
return alpha;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public void setBeta(double beta) {
|
||||
this.beta = beta;
|
||||
z = Double.NaN;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public double getBeta() {
|
||||
return beta;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recompute the normalization factor.
|
||||
*/
|
||||
private void recomputeZ() {
|
||||
if (Double.isNaN(z)) {
|
||||
z = Gamma.logGamma(alpha) + Gamma.logGamma(beta) - Gamma.logGamma(alpha + beta);
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public double density(Double x) throws MathException {
|
||||
recomputeZ();
|
||||
if (x < 0 || x > 1) {
|
||||
return 0;
|
||||
} else if (x == 0) {
|
||||
if (alpha < 1) {
|
||||
throw new MathException("Cannot compute beta density at 0 when alpha = {0,number}", new Double[]{alpha});
|
||||
}
|
||||
return 0;
|
||||
} else if (x == 1) {
|
||||
if (beta < 1) {
|
||||
throw new MathException("Cannot compute beta density at 1 when beta = %.3g", new Double[]{beta});
|
||||
}
|
||||
return 0;
|
||||
} else {
|
||||
double logX = Math.log(x);
|
||||
double log1mX = Math.log1p(-x);
|
||||
return Math.exp((alpha - 1) * logX + (beta - 1) * log1mX - z);
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public double inverseCumulativeProbability(double p) throws MathException {
|
||||
if (p == 0) {
|
||||
return 0;
|
||||
} else if (p == 1) {
|
||||
return 1;
|
||||
} else {
|
||||
return super.inverseCumulativeProbability(p);
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
protected double getInitialDomain(double p) {
|
||||
return p;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
protected double getDomainLowerBound(double p) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
protected double getDomainUpperBound(double p) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public double cumulativeProbability(double x) throws MathException {
|
||||
if (x <= 0) {
|
||||
return 0;
|
||||
} else if (x >= 1) {
|
||||
return 1;
|
||||
} else {
|
||||
return Beta.regularizedBeta(x, alpha, beta);
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public double cumulativeProbability(double x0, double x1) throws MathException {
|
||||
return cumulativeProbability(x1) - cumulativeProbability(x0);
|
||||
}
|
||||
}
|
@ -29,7 +29,7 @@ package org.apache.commons.math.distribution;
|
||||
*
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
public interface ChiSquaredDistribution extends ContinuousDistribution {
|
||||
public interface ChiSquaredDistribution extends ContinuousDistribution, HasDensity<Double> {
|
||||
/**
|
||||
* Modify the degrees of freedom.
|
||||
* @param degreesOfFreedom the new degrees of freedom.
|
||||
@ -41,4 +41,11 @@ public interface ChiSquaredDistribution extends ContinuousDistribution {
|
||||
* @return the degrees of freedom.
|
||||
*/
|
||||
double getDegreesOfFreedom();
|
||||
|
||||
/**
|
||||
* Return the probability density for a particular point.
|
||||
* @param x The point at which the density should be computed.
|
||||
* @return The pdf at point x.
|
||||
*/
|
||||
double density(Double x);
|
||||
}
|
@ -70,7 +70,17 @@ public class ChiSquaredDistributionImpl
|
||||
public double getDegreesOfFreedom() {
|
||||
return getGamma().getAlpha() * 2.0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the probability density for a particular point.
|
||||
*
|
||||
* @param x The point at which the density should be computed.
|
||||
* @return The pdf at point x.
|
||||
*/
|
||||
public double density(Double x) {
|
||||
return gamma.density(x);
|
||||
}
|
||||
|
||||
/**
|
||||
* For this distribution, X, this method returns P(X < x).
|
||||
* @param x the value at which the CDF is evaluated.
|
||||
|
@ -1,206 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.commons.math.distribution;
|
||||
|
||||
/**
|
||||
* This factory provids the means to create common statistical distributions.
|
||||
* The following distributions are supported:
|
||||
* <ul>
|
||||
* <li>Binomial</li>
|
||||
* <li>Cauchy</li>
|
||||
* <li>Chi-Squared</li>
|
||||
* <li>Exponential</li>
|
||||
* <li>F</li>
|
||||
* <li>Gamma</li>
|
||||
* <li>HyperGeometric</li>
|
||||
* <li>Poisson</li>
|
||||
* <li>Normal</li>
|
||||
* <li>Student's t</li>
|
||||
* <li>Weibull</li>
|
||||
* <li>Pascal</li>
|
||||
* </ul>
|
||||
*
|
||||
* Common usage:<pre>
|
||||
* DistributionFactory factory = DistributionFactory.newInstance();
|
||||
*
|
||||
* // create a Chi-Square distribution with 5 degrees of freedom.
|
||||
* ChiSquaredDistribution chi = factory.createChiSquareDistribution(5.0);
|
||||
* </pre>
|
||||
*
|
||||
* @version $Revision$ $Date$
|
||||
* @deprecated pluggability of distribution instances is now provided through
|
||||
* constructors and setters.
|
||||
*/
|
||||
public abstract class DistributionFactory {
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
protected DistributionFactory() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of a <code>DistributionFactory</code>
|
||||
* @return a new factory.
|
||||
*/
|
||||
public static DistributionFactory newInstance() {
|
||||
return new DistributionFactoryImpl();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a binomial distribution with the given number of trials and
|
||||
* probability of success.
|
||||
*
|
||||
* @param numberOfTrials the number of trials.
|
||||
* @param probabilityOfSuccess the probability of success
|
||||
* @return a new binomial distribution
|
||||
*/
|
||||
public abstract BinomialDistribution createBinomialDistribution(
|
||||
int numberOfTrials, double probabilityOfSuccess);
|
||||
|
||||
/**
|
||||
* Create a Pascal distribution with the given number of successes and
|
||||
* probability of success.
|
||||
*
|
||||
* @param numberOfSuccesses the number of successes.
|
||||
* @param probabilityOfSuccess the probability of success
|
||||
* @return a new Pascal distribution
|
||||
* @since 1.2
|
||||
*/
|
||||
public PascalDistribution createPascalDistribution(
|
||||
int numberOfSuccesses, double probabilityOfSuccess) {
|
||||
return new PascalDistributionImpl(numberOfSuccesses, probabilityOfSuccess);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new cauchy distribution with the given median and scale.
|
||||
* @param median the median of the distribution
|
||||
* @param scale the scale
|
||||
* @return a new cauchy distribution
|
||||
* @since 1.1
|
||||
*/
|
||||
public CauchyDistribution createCauchyDistribution(
|
||||
double median, double scale)
|
||||
{
|
||||
return new CauchyDistributionImpl(median, scale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new chi-square distribution with the given degrees of freedom.
|
||||
*
|
||||
* @param degreesOfFreedom degrees of freedom
|
||||
* @return a new chi-square distribution
|
||||
*/
|
||||
public abstract ChiSquaredDistribution createChiSquareDistribution(
|
||||
double degreesOfFreedom);
|
||||
|
||||
/**
|
||||
* Create a new exponential distribution with the given degrees of freedom.
|
||||
*
|
||||
* @param mean mean
|
||||
* @return a new exponential distribution
|
||||
*/
|
||||
public abstract ExponentialDistribution createExponentialDistribution(
|
||||
double mean);
|
||||
|
||||
/**
|
||||
* Create a new F-distribution with the given degrees of freedom.
|
||||
*
|
||||
* @param numeratorDegreesOfFreedom numerator degrees of freedom
|
||||
* @param denominatorDegreesOfFreedom denominator degrees of freedom
|
||||
* @return a new F-distribution
|
||||
*/
|
||||
public abstract FDistribution createFDistribution(
|
||||
double numeratorDegreesOfFreedom, double denominatorDegreesOfFreedom);
|
||||
|
||||
/**
|
||||
* Create a new gamma distribution with the given shape and scale
|
||||
* parameters.
|
||||
*
|
||||
* @param alpha the shape parameter
|
||||
* @param beta the scale parameter
|
||||
*
|
||||
* @return a new gamma distribution
|
||||
*/
|
||||
public abstract GammaDistribution createGammaDistribution(
|
||||
double alpha, double beta);
|
||||
|
||||
/**
|
||||
* Create a new t distribution with the given degrees of freedom.
|
||||
*
|
||||
* @param degreesOfFreedom degrees of freedom
|
||||
* @return a new t distribution
|
||||
*/
|
||||
public abstract TDistribution createTDistribution(double degreesOfFreedom);
|
||||
|
||||
/**
|
||||
* Create a new hypergeometric distribution with the given the population
|
||||
* size, the number of successes in the population, and the sample size.
|
||||
*
|
||||
* @param populationSize the population size
|
||||
* @param numberOfSuccesses number of successes in the population
|
||||
* @param sampleSize the sample size
|
||||
* @return a new hypergeometric desitribution
|
||||
*/
|
||||
public abstract HypergeometricDistribution
|
||||
createHypergeometricDistribution(int populationSize,
|
||||
int numberOfSuccesses, int sampleSize);
|
||||
|
||||
/**
|
||||
* Create a new normal distribution with the given mean and standard
|
||||
* deviation.
|
||||
*
|
||||
* @param mean the mean of the distribution
|
||||
* @param sd standard deviation
|
||||
* @return a new normal distribution
|
||||
*/
|
||||
public abstract NormalDistribution
|
||||
createNormalDistribution(double mean, double sd);
|
||||
|
||||
/**
|
||||
* Create a new normal distribution with mean zero and standard
|
||||
* deviation one.
|
||||
*
|
||||
* @return a new normal distribution.
|
||||
*/
|
||||
public abstract NormalDistribution createNormalDistribution();
|
||||
|
||||
/**
|
||||
* Create a new Poisson distribution with poisson parameter lambda.
|
||||
*
|
||||
* @param lambda poisson parameter
|
||||
* @return a new poisson distribution.
|
||||
*/
|
||||
public abstract PoissonDistribution
|
||||
createPoissonDistribution(double lambda);
|
||||
|
||||
/**
|
||||
* Create a new Weibull distribution with the given shape and scale
|
||||
* parameters.
|
||||
*
|
||||
* @param alpha the shape parameter.
|
||||
* @param beta the scale parameter.
|
||||
* @return a new Weibull distribution.
|
||||
* @since 1.1
|
||||
*/
|
||||
public WeibullDistribution createWeibullDistribution(
|
||||
double alpha, double beta)
|
||||
{
|
||||
return new WeibullDistributionImpl(alpha, beta);
|
||||
}
|
||||
}
|
@ -1,159 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.commons.math.distribution;
|
||||
|
||||
/**
|
||||
* A concrete distribution factory. This is the default factory used by
|
||||
* Commons-Math.
|
||||
*
|
||||
* @version $Revision$ $Date$
|
||||
* @deprecated pluggability of distribution instances is now provided through
|
||||
* constructors and setters.
|
||||
*/
|
||||
public class DistributionFactoryImpl extends DistributionFactory {
|
||||
|
||||
/**
|
||||
* Default constructor. Package scope to prevent unwanted instantiation.
|
||||
*/
|
||||
public DistributionFactoryImpl() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new chi-square distribution with the given degrees of freedom.
|
||||
*
|
||||
* @param degreesOfFreedom degrees of freedom
|
||||
* @return a new chi-square distribution
|
||||
*/
|
||||
public ChiSquaredDistribution createChiSquareDistribution(
|
||||
final double degreesOfFreedom) {
|
||||
|
||||
return new ChiSquaredDistributionImpl(degreesOfFreedom);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new gamma distribution the given shape and scale parameters.
|
||||
*
|
||||
* @param alpha the shape parameter
|
||||
* @param beta the scale parameter
|
||||
* @return a new gamma distribution
|
||||
*/
|
||||
public GammaDistribution createGammaDistribution(
|
||||
double alpha, double beta) {
|
||||
|
||||
return new GammaDistributionImpl(alpha, beta);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new t distribution with the given degrees of freedom.
|
||||
*
|
||||
* @param degreesOfFreedom degrees of freedom
|
||||
* @return a new t distribution.
|
||||
*/
|
||||
public TDistribution createTDistribution(double degreesOfFreedom) {
|
||||
return new TDistributionImpl(degreesOfFreedom);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new F-distribution with the given degrees of freedom.
|
||||
*
|
||||
* @param numeratorDegreesOfFreedom numerator degrees of freedom
|
||||
* @param denominatorDegreesOfFreedom denominator degrees of freedom
|
||||
* @return a new F-distribution
|
||||
*/
|
||||
public FDistribution createFDistribution(
|
||||
double numeratorDegreesOfFreedom,
|
||||
double denominatorDegreesOfFreedom) {
|
||||
return new FDistributionImpl(numeratorDegreesOfFreedom,
|
||||
denominatorDegreesOfFreedom);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new exponential distribution with the given degrees of freedom.
|
||||
*
|
||||
* @param mean mean
|
||||
* @return a new exponential distribution
|
||||
*/
|
||||
public ExponentialDistribution createExponentialDistribution(double mean) {
|
||||
return new ExponentialDistributionImpl(mean);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a binomial distribution with the given number of trials and
|
||||
* probability of success.
|
||||
*
|
||||
* @param numberOfTrials the number of trials
|
||||
* @param probabilityOfSuccess the probability of success
|
||||
* @return a new binomial distribution
|
||||
*/
|
||||
public BinomialDistribution createBinomialDistribution(
|
||||
int numberOfTrials, double probabilityOfSuccess) {
|
||||
return new BinomialDistributionImpl(numberOfTrials,
|
||||
probabilityOfSuccess);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new hypergeometric distribution with the given the population
|
||||
* size, the number of successes in the population, and the sample size.
|
||||
*
|
||||
* @param populationSize the population size
|
||||
* @param numberOfSuccesses number of successes in the population
|
||||
* @param sampleSize the sample size
|
||||
* @return a new hypergeometric desitribution
|
||||
*/
|
||||
public HypergeometricDistribution createHypergeometricDistribution(
|
||||
int populationSize, int numberOfSuccesses, int sampleSize) {
|
||||
return new HypergeometricDistributionImpl(populationSize,
|
||||
numberOfSuccesses, sampleSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new normal distribution with the given mean and standard
|
||||
* deviation.
|
||||
*
|
||||
* @param mean the mean of the distribution
|
||||
* @param sd standard deviation
|
||||
* @return a new normal distribution
|
||||
*/
|
||||
public NormalDistribution createNormalDistribution(double mean, double sd) {
|
||||
return new NormalDistributionImpl(mean, sd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new normal distribution with the mean zero and standard
|
||||
* deviation one.
|
||||
*
|
||||
* @return a new normal distribution
|
||||
*/
|
||||
public NormalDistribution createNormalDistribution() {
|
||||
return new NormalDistributionImpl();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Poisson distribution with poisson parameter lambda.
|
||||
* <p>
|
||||
* lambda must be postive; otherwise an
|
||||
* <code>IllegalArgumentException</code> is thrown.
|
||||
*
|
||||
* @param lambda poisson parameter
|
||||
* @return a new Poisson distribution
|
||||
* @throws IllegalArgumentException if lambda ≤ 0
|
||||
*/
|
||||
public PoissonDistribution createPoissonDistribution(double lambda) {
|
||||
return new PoissonDistributionImpl(lambda);
|
||||
}
|
||||
}
|
@ -29,7 +29,7 @@ package org.apache.commons.math.distribution;
|
||||
*
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
public interface ExponentialDistribution extends ContinuousDistribution {
|
||||
public interface ExponentialDistribution extends ContinuousDistribution, HasDensity<Double> {
|
||||
/**
|
||||
* Modify the mean.
|
||||
* @param mean the new mean.
|
||||
@ -41,4 +41,11 @@ public interface ExponentialDistribution extends ContinuousDistribution {
|
||||
* @return the mean.
|
||||
*/
|
||||
double getMean();
|
||||
|
||||
/**
|
||||
* Return the probability density for a particular point.
|
||||
* @param x The point at which the density should be computed.
|
||||
* @return The pdf at point x.
|
||||
*/
|
||||
double density(Double x);
|
||||
}
|
@ -63,6 +63,19 @@ public class ExponentialDistributionImpl extends AbstractContinuousDistribution
|
||||
return mean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the probability density for a particular point.
|
||||
*
|
||||
* @param x The point at which the density should be computed.
|
||||
* @return The pdf at point x.
|
||||
*/
|
||||
public double density(Double x) {
|
||||
if (x < 0) {
|
||||
return 0;
|
||||
}
|
||||
return Math.exp(-x / getMean()) / getMean();
|
||||
}
|
||||
|
||||
/**
|
||||
* For this distribution, X, this method returns P(X < x).
|
||||
*
|
||||
@ -157,6 +170,8 @@ public class ExponentialDistributionImpl extends AbstractContinuousDistribution
|
||||
*/
|
||||
protected double getInitialDomain(double p) {
|
||||
// TODO: try to improve on this estimate
|
||||
// TODO: what should really happen here is not derive from AbstractContinuousDistribution
|
||||
// TODO: because the inverse cumulative distribution is simple.
|
||||
// Exponential is skewed to the left, therefore, P(X < μ) > .5
|
||||
if (p < .5) {
|
||||
// use 1/2 mean
|
||||
|
@ -24,188 +24,173 @@ import org.apache.commons.math.special.Beta;
|
||||
/**
|
||||
* Default implementation of
|
||||
* {@link org.apache.commons.math.distribution.FDistribution}.
|
||||
*
|
||||
* @version $Revision$ $Date: 2008-02-08 09:44:11 -0600 (Fri, 08 Feb
|
||||
* 2008) $
|
||||
*
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
public class FDistributionImpl extends AbstractContinuousDistribution implements
|
||||
FDistribution, Serializable {
|
||||
public class FDistributionImpl
|
||||
extends AbstractContinuousDistribution
|
||||
implements FDistribution, Serializable {
|
||||
|
||||
/** Serializable version identifier */
|
||||
private static final long serialVersionUID = -8516354193418641566L;
|
||||
/** Serializable version identifier */
|
||||
private static final long serialVersionUID = -8516354193418641566L;
|
||||
|
||||
/** The numerator degrees of freedom */
|
||||
private double numeratorDegreesOfFreedom;
|
||||
/** The numerator degrees of freedom*/
|
||||
private double numeratorDegreesOfFreedom;
|
||||
|
||||
/** The numerator degrees of freedom */
|
||||
private double denominatorDegreesOfFreedom;
|
||||
/** The numerator degrees of freedom*/
|
||||
private double denominatorDegreesOfFreedom;
|
||||
|
||||
/**
|
||||
* Create a F distribution using the given degrees of freedom.
|
||||
* @param numeratorDegreesOfFreedom the numerator degrees of freedom.
|
||||
* @param denominatorDegreesOfFreedom the denominator degrees of freedom.
|
||||
*/
|
||||
public FDistributionImpl(double numeratorDegreesOfFreedom,
|
||||
double denominatorDegreesOfFreedom) {
|
||||
super();
|
||||
setNumeratorDegreesOfFreedom(numeratorDegreesOfFreedom);
|
||||
setDenominatorDegreesOfFreedom(denominatorDegreesOfFreedom);
|
||||
}
|
||||
|
||||
/**
|
||||
* For this distribution, X, this method returns P(X < x).
|
||||
*
|
||||
* The implementation of this method is based on:
|
||||
* <ul>
|
||||
* <li>
|
||||
* <a href="http://mathworld.wolfram.com/F-Distribution.html">
|
||||
* F-Distribution</a>, equation (4).</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param x the value at which the CDF is evaluated.
|
||||
* @return CDF for this distribution.
|
||||
* @throws MathException if the cumulative probability can not be
|
||||
* computed due to convergence or other numerical errors.
|
||||
*/
|
||||
public double cumulativeProbability(double x) throws MathException {
|
||||
double ret;
|
||||
if (x <= 0.0) {
|
||||
ret = 0.0;
|
||||
} else {
|
||||
double n = getNumeratorDegreesOfFreedom();
|
||||
double m = getDenominatorDegreesOfFreedom();
|
||||
|
||||
ret = Beta.regularizedBeta((n * x) / (m + n * x),
|
||||
0.5 * n,
|
||||
0.5 * m);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* For this distribution, X, this method returns the critical point x, such
|
||||
* that P(X < x) = <code>p</code>.
|
||||
* <p>
|
||||
* Returns 0 for p=0 and <code>Double.POSITIVE_INFINITY</code> for p=1.</p>
|
||||
*
|
||||
* @param p the desired probability
|
||||
* @return x, such that P(X < x) = <code>p</code>
|
||||
* @throws MathException if the inverse cumulative probability can not be
|
||||
* computed due to convergence or other numerical errors.
|
||||
* @throws IllegalArgumentException if <code>p</code> is not a valid
|
||||
* probability.
|
||||
*/
|
||||
public double inverseCumulativeProbability(final double p)
|
||||
throws MathException {
|
||||
if (p == 0) {
|
||||
return 0d;
|
||||
}
|
||||
if (p == 1) {
|
||||
return Double.POSITIVE_INFINITY;
|
||||
}
|
||||
return super.inverseCumulativeProbability(p);
|
||||
}
|
||||
|
||||
/**
|
||||
* Access the domain value lower bound, based on <code>p</code>, used to
|
||||
* bracket a CDF root. This method is used by
|
||||
* {@link #inverseCumulativeProbability(double)} to find critical values.
|
||||
*
|
||||
* @param p the desired probability for the critical value
|
||||
* @return domain value lower bound, i.e.
|
||||
* P(X < <i>lower bound</i>) < <code>p</code>
|
||||
*/
|
||||
protected double getDomainLowerBound(double p) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a F distribution using the given degrees of freedom.
|
||||
*
|
||||
* @param numeratorDegreesOfFreedom
|
||||
* the numerator degrees of freedom.
|
||||
* @param denominatorDegreesOfFreedom
|
||||
* the denominator degrees of freedom.
|
||||
*/
|
||||
public FDistributionImpl(double numeratorDegreesOfFreedom,
|
||||
double denominatorDegreesOfFreedom) {
|
||||
super();
|
||||
setNumeratorDegreesOfFreedom(numeratorDegreesOfFreedom);
|
||||
setDenominatorDegreesOfFreedom(denominatorDegreesOfFreedom);
|
||||
}
|
||||
/**
|
||||
* Access the domain value upper bound, based on <code>p</code>, used to
|
||||
* bracket a CDF root. This method is used by
|
||||
* {@link #inverseCumulativeProbability(double)} to find critical values.
|
||||
*
|
||||
* @param p the desired probability for the critical value
|
||||
* @return domain value upper bound, i.e.
|
||||
* P(X < <i>upper bound</i>) > <code>p</code>
|
||||
*/
|
||||
protected double getDomainUpperBound(double p) {
|
||||
return Double.MAX_VALUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* For this distribution, X, this method returns P(X < x).
|
||||
*
|
||||
* The implementation of this method is based on:
|
||||
* <ul>
|
||||
* <li>
|
||||
* <a href="http://mathworld.wolfram.com/F-Distribution.html">
|
||||
* F-Distribution</a>, equation (4).</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param x
|
||||
* the value at which the CDF is evaluated.
|
||||
* @return CDF for this distribution.
|
||||
* @throws MathException
|
||||
* if the cumulative probability can not be computed due to
|
||||
* convergence or other numerical errors.
|
||||
*/
|
||||
public double cumulativeProbability(double x) throws MathException {
|
||||
double ret;
|
||||
if (x <= 0.0) {
|
||||
ret = 0.0;
|
||||
} else {
|
||||
double n = getNumeratorDegreesOfFreedom();
|
||||
double m = getDenominatorDegreesOfFreedom();
|
||||
|
||||
ret = Beta.regularizedBeta((n * x) / (m + n * x), 0.5 * n, 0.5 * m);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* For this distribution, X, this method returns the critical point x, such
|
||||
* that P(X < x) = <code>p</code>.
|
||||
* <p>
|
||||
* Returns 0 for p=0 and <code>Double.POSITIVE_INFINITY</code> for p=1.
|
||||
* </p>
|
||||
*
|
||||
* @param p
|
||||
* the desired probability
|
||||
* @return x, such that P(X < x) = <code>p</code>
|
||||
* @throws MathException
|
||||
* if the inverse cumulative probability can not be computed due
|
||||
* to convergence or other numerical errors.
|
||||
* @throws IllegalArgumentException
|
||||
* if <code>p</code> is not a valid probability.
|
||||
*/
|
||||
public double inverseCumulativeProbability(final double p)
|
||||
throws MathException {
|
||||
if (p == 0) {
|
||||
return 0d;
|
||||
}
|
||||
if (p == 1) {
|
||||
return Double.POSITIVE_INFINITY;
|
||||
}
|
||||
return super.inverseCumulativeProbability(p);
|
||||
}
|
||||
|
||||
/**
|
||||
* Access the domain value lower bound, based on <code>p</code>, used to
|
||||
* bracket a CDF root. This method is used by
|
||||
* {@link #inverseCumulativeProbability(double)} to find critical values.
|
||||
*
|
||||
* @param p
|
||||
* the desired probability for the critical value
|
||||
* @return domain value lower bound, i.e. P(X < <i>lower bound</i>) <
|
||||
* <code>p</code>
|
||||
*/
|
||||
protected double getDomainLowerBound(double p) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Access the domain value upper bound, based on <code>p</code>, used to
|
||||
* bracket a CDF root. This method is used by
|
||||
* {@link #inverseCumulativeProbability(double)} to find critical values.
|
||||
*
|
||||
* @param p
|
||||
* the desired probability for the critical value
|
||||
* @return domain value upper bound, i.e. P(X < <i>upper bound</i>) >
|
||||
* <code>p</code>
|
||||
*/
|
||||
protected double getDomainUpperBound(double p) {
|
||||
return Double.MAX_VALUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Access the initial domain value, based on <code>p</code>, used to bracket
|
||||
* a CDF root. This method is used by
|
||||
* {@link #inverseCumulativeProbability(double)} to find critical values.
|
||||
*
|
||||
* @param p
|
||||
* the desired probability for the critical value
|
||||
* @return initial domain value
|
||||
*/
|
||||
protected double getInitialDomain(double p) {
|
||||
double ret = 1.0;
|
||||
double d = getDenominatorDegreesOfFreedom();
|
||||
if (d > 2.0) {
|
||||
// use mean
|
||||
ret = d / (d - 2.0);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Modify the numerator degrees of freedom.
|
||||
*
|
||||
* @param degreesOfFreedom
|
||||
* the new numerator degrees of freedom.
|
||||
* @throws IllegalArgumentException
|
||||
* if <code>degreesOfFreedom</code> is not positive.
|
||||
*/
|
||||
public void setNumeratorDegreesOfFreedom(double degreesOfFreedom) {
|
||||
if (degreesOfFreedom <= 0.0) {
|
||||
throw new IllegalArgumentException(
|
||||
"degrees of freedom must be positive.");
|
||||
}
|
||||
this.numeratorDegreesOfFreedom = degreesOfFreedom;
|
||||
}
|
||||
|
||||
/**
|
||||
* Access the numerator degrees of freedom.
|
||||
*
|
||||
* @return the numerator degrees of freedom.
|
||||
*/
|
||||
public double getNumeratorDegreesOfFreedom() {
|
||||
return numeratorDegreesOfFreedom;
|
||||
}
|
||||
|
||||
/**
|
||||
* Modify the denominator degrees of freedom.
|
||||
*
|
||||
* @param degreesOfFreedom
|
||||
* the new denominator degrees of freedom.
|
||||
* @throws IllegalArgumentException
|
||||
* if <code>degreesOfFreedom</code> is not positive.
|
||||
*/
|
||||
public void setDenominatorDegreesOfFreedom(double degreesOfFreedom) {
|
||||
if (degreesOfFreedom <= 0.0) {
|
||||
throw new IllegalArgumentException(
|
||||
"degrees of freedom must be positive.");
|
||||
}
|
||||
this.denominatorDegreesOfFreedom = degreesOfFreedom;
|
||||
}
|
||||
|
||||
/**
|
||||
* Access the denominator degrees of freedom.
|
||||
*
|
||||
* @return the denominator degrees of freedom.
|
||||
*/
|
||||
public double getDenominatorDegreesOfFreedom() {
|
||||
return denominatorDegreesOfFreedom;
|
||||
}
|
||||
/**
|
||||
* Access the initial domain value, based on <code>p</code>, used to
|
||||
* bracket a CDF root. This method is used by
|
||||
* {@link #inverseCumulativeProbability(double)} to find critical values.
|
||||
*
|
||||
* @param p the desired probability for the critical value
|
||||
* @return initial domain value
|
||||
*/
|
||||
protected double getInitialDomain(double p) {
|
||||
double ret = 1.0;
|
||||
double d = getDenominatorDegreesOfFreedom();
|
||||
if (d > 2.0) {
|
||||
// use mean
|
||||
ret = d / (d - 2.0);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Modify the numerator degrees of freedom.
|
||||
* @param degreesOfFreedom the new numerator degrees of freedom.
|
||||
* @throws IllegalArgumentException if <code>degreesOfFreedom</code> is not
|
||||
* positive.
|
||||
*/
|
||||
public void setNumeratorDegreesOfFreedom(double degreesOfFreedom) {
|
||||
if (degreesOfFreedom <= 0.0) {
|
||||
throw new IllegalArgumentException(
|
||||
"degrees of freedom must be positive.");
|
||||
}
|
||||
this.numeratorDegreesOfFreedom = degreesOfFreedom;
|
||||
}
|
||||
|
||||
/**
|
||||
* Access the numerator degrees of freedom.
|
||||
* @return the numerator degrees of freedom.
|
||||
*/
|
||||
public double getNumeratorDegreesOfFreedom() {
|
||||
return numeratorDegreesOfFreedom;
|
||||
}
|
||||
|
||||
/**
|
||||
* Modify the denominator degrees of freedom.
|
||||
* @param degreesOfFreedom the new denominator degrees of freedom.
|
||||
* @throws IllegalArgumentException if <code>degreesOfFreedom</code> is not
|
||||
* positive.
|
||||
*/
|
||||
public void setDenominatorDegreesOfFreedom(double degreesOfFreedom) {
|
||||
if (degreesOfFreedom <= 0.0) {
|
||||
throw new IllegalArgumentException(
|
||||
"degrees of freedom must be positive.");
|
||||
}
|
||||
this.denominatorDegreesOfFreedom = degreesOfFreedom;
|
||||
}
|
||||
|
||||
/**
|
||||
* Access the denominator degrees of freedom.
|
||||
* @return the denominator degrees of freedom.
|
||||
*/
|
||||
public double getDenominatorDegreesOfFreedom() {
|
||||
return denominatorDegreesOfFreedom;
|
||||
}
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ package org.apache.commons.math.distribution;
|
||||
*
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
public interface GammaDistribution extends ContinuousDistribution {
|
||||
public interface GammaDistribution extends ContinuousDistribution, HasDensity<Double> {
|
||||
/**
|
||||
* Modify the shape parameter, alpha.
|
||||
* @param alpha the new shape parameter.
|
||||
@ -53,4 +53,11 @@ public interface GammaDistribution extends ContinuousDistribution {
|
||||
* @return beta.
|
||||
*/
|
||||
double getBeta();
|
||||
|
||||
/**
|
||||
* Return the probability density for a particular point.
|
||||
* @param x The point at which the density should be computed.
|
||||
* @return The pdf at point x.
|
||||
*/
|
||||
double density(Double x);
|
||||
}
|
||||
|
@ -141,7 +141,18 @@ public class GammaDistributionImpl extends AbstractContinuousDistribution
|
||||
public double getBeta() {
|
||||
return beta;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the probability density for a particular point.
|
||||
*
|
||||
* @param x The point at which the density should be computed.
|
||||
* @return The pdf at point x.
|
||||
*/
|
||||
public double density(Double x) {
|
||||
if (x < 0) return 0;
|
||||
return Math.pow(x / getBeta(), getAlpha() - 1) / getBeta() * Math.exp(-x / getBeta()) / Math.exp(Gamma.logGamma(getAlpha()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Access the domain value lower bound, based on <code>p</code>, used to
|
||||
* bracket a CDF root. This method is used by
|
||||
|
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.commons.math.distribution;
|
||||
|
||||
import org.apache.commons.math.MathException;
|
||||
|
||||
/**
|
||||
* Interface that signals that a distribution can compute the probability density function
|
||||
* for a particular point.
|
||||
* @param <P> the type of the point at which density is to be computed, this
|
||||
* may be for example <code>Double</code>
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
public interface HasDensity<P> {
|
||||
|
||||
/**
|
||||
* Compute the probability density function.
|
||||
* @param x point for which the probability density is requested
|
||||
* @return probability density at point x
|
||||
* @throws MathException if probability density cannot be computed at specifed point
|
||||
*/
|
||||
double density(P x) throws MathException;
|
||||
|
||||
}
|
@ -30,7 +30,7 @@ package org.apache.commons.math.distribution;
|
||||
*
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
public interface NormalDistribution extends ContinuousDistribution {
|
||||
public interface NormalDistribution extends ContinuousDistribution, HasDensity<Double> {
|
||||
/**
|
||||
* Access the mean.
|
||||
* @return mean for this distribution
|
||||
@ -51,4 +51,11 @@ public interface NormalDistribution extends ContinuousDistribution {
|
||||
* @param sd standard deviation for this distribution
|
||||
*/
|
||||
void setStandardDeviation(double sd);
|
||||
|
||||
/**
|
||||
* Return the probability density for a particular point.
|
||||
* @param x The point at which the density should be computed.
|
||||
* @return The pdf at point x.
|
||||
*/
|
||||
double density(Double x);
|
||||
}
|
||||
|
@ -35,12 +35,15 @@ public class NormalDistributionImpl extends AbstractContinuousDistribution
|
||||
/** Serializable version identifier */
|
||||
private static final long serialVersionUID = 8589540077390120676L;
|
||||
|
||||
/** &sqrt;(2 π) */
|
||||
private static final double SQRT2PI = Math.sqrt(2 * Math.PI);
|
||||
|
||||
/** The mean of this distribution. */
|
||||
private double mean = 0;
|
||||
|
||||
/** The standard deviation of this distribution. */
|
||||
private double standardDeviation = 1;
|
||||
|
||||
|
||||
/**
|
||||
* Create a normal distribution using the given mean and standard deviation.
|
||||
* @param mean mean for this distribution
|
||||
@ -97,6 +100,17 @@ public class NormalDistributionImpl extends AbstractContinuousDistribution
|
||||
standardDeviation = sd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the probability density for a particular point.
|
||||
*
|
||||
* @param x The point at which the density should be computed.
|
||||
* @return The pdf at point x.
|
||||
*/
|
||||
public double density(Double x) {
|
||||
double x0 = x - getMean();
|
||||
return Math.exp(-x0 * x0 / (2 * getStandardDeviation() * getStandardDeviation())) / (getStandardDeviation() * SQRT2PI);
|
||||
}
|
||||
|
||||
/**
|
||||
* For this distribution, X, this method returns P(X < <code>x</code>).
|
||||
* @param x the value at which the CDF is evaluated.
|
||||
|
@ -98,7 +98,7 @@ public abstract class AbstractEstimator implements Estimator {
|
||||
|
||||
if (++costEvaluations > maxCostEval) {
|
||||
throw new EstimationException("maximal number of evaluations exceeded ({0})",
|
||||
new Object[] { new Integer(maxCostEval) });
|
||||
new Object[] { Integer.valueOf(maxCostEval) });
|
||||
}
|
||||
|
||||
cost = 0;
|
||||
@ -179,10 +179,10 @@ public abstract class AbstractEstimator implements Estimator {
|
||||
|
||||
try {
|
||||
// compute the covariances matrix
|
||||
return new RealMatrixImpl(jTj).inverse().getData();
|
||||
return ((RealMatrixImpl) new RealMatrixImpl(jTj, false).inverse()).getDataRef();
|
||||
} catch (InvalidMatrixException ime) {
|
||||
throw new EstimationException("unable to compute covariances: singular problem",
|
||||
new Object[0]);
|
||||
null);
|
||||
}
|
||||
|
||||
}
|
||||
@ -202,7 +202,7 @@ public abstract class AbstractEstimator implements Estimator {
|
||||
int p = problem.getUnboundParameters().length;
|
||||
if (m <= p) {
|
||||
throw new EstimationException("no degrees of freedom ({0} measurements, {1} parameters)",
|
||||
new Object[] { new Integer(m), new Integer(p)});
|
||||
new Object[] { Integer.valueOf(m), Integer.valueOf(p)});
|
||||
}
|
||||
double[] errors = new double[problem.getUnboundParameters().length];
|
||||
final double c = Math.sqrt(getChiSquare(problem) / (m - p));
|
||||
|
@ -20,8 +20,11 @@ package org.apache.commons.math.estimation;
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.apache.commons.math.linear.InvalidMatrixException;
|
||||
import org.apache.commons.math.linear.LUDecompositionImpl;
|
||||
import org.apache.commons.math.linear.RealMatrix;
|
||||
import org.apache.commons.math.linear.RealMatrixImpl;
|
||||
import org.apache.commons.math.linear.RealVector;
|
||||
import org.apache.commons.math.linear.RealVectorImpl;
|
||||
|
||||
/**
|
||||
* This class implements a solver for estimation problems.
|
||||
@ -106,8 +109,8 @@ public class GaussNewtonEstimator extends AbstractEstimator implements Serializa
|
||||
|
||||
// work matrices
|
||||
double[] grad = new double[parameters.length];
|
||||
RealMatrixImpl bDecrement = new RealMatrixImpl(parameters.length, 1);
|
||||
double[][] bDecrementData = bDecrement.getDataRef();
|
||||
RealVectorImpl bDecrement = new RealVectorImpl(parameters.length);
|
||||
double[] bDecrementData = bDecrement.getDataRef();
|
||||
RealMatrixImpl wGradGradT = new RealMatrixImpl(parameters.length, parameters.length);
|
||||
double[][] wggData = wGradGradT.getDataRef();
|
||||
|
||||
@ -117,7 +120,7 @@ public class GaussNewtonEstimator extends AbstractEstimator implements Serializa
|
||||
|
||||
// build the linear problem
|
||||
incrementJacobianEvaluationsCounter();
|
||||
RealMatrix b = new RealMatrixImpl(parameters.length, 1);
|
||||
RealVector b = new RealVectorImpl(parameters.length);
|
||||
RealMatrix a = new RealMatrixImpl(parameters.length, parameters.length);
|
||||
for (int i = 0; i < measurements.length; ++i) {
|
||||
if (! measurements [i].isIgnored()) {
|
||||
@ -128,7 +131,7 @@ public class GaussNewtonEstimator extends AbstractEstimator implements Serializa
|
||||
// compute the normal equation
|
||||
for (int j = 0; j < parameters.length; ++j) {
|
||||
grad[j] = measurements[i].getPartial(parameters[j]);
|
||||
bDecrementData[j][0] = weight * residual * grad[j];
|
||||
bDecrementData[j] = weight * residual * grad[j];
|
||||
}
|
||||
|
||||
// build the contribution matrix for measurement i
|
||||
@ -150,15 +153,15 @@ public class GaussNewtonEstimator extends AbstractEstimator implements Serializa
|
||||
try {
|
||||
|
||||
// solve the linearized least squares problem
|
||||
RealMatrix dX = a.solve(b);
|
||||
RealVector dX = new LUDecompositionImpl(a).solve(b);
|
||||
|
||||
// update the estimated parameters
|
||||
for (int i = 0; i < parameters.length; ++i) {
|
||||
parameters[i].setEstimate(parameters[i].getEstimate() + dX.getEntry(i, 0));
|
||||
parameters[i].setEstimate(parameters[i].getEstimate() + dX.getEntry(i));
|
||||
}
|
||||
|
||||
} catch(InvalidMatrixException e) {
|
||||
throw new EstimationException("unable to solve: singular problem", new Object[0]);
|
||||
throw new EstimationException("unable to solve: singular problem", null);
|
||||
}
|
||||
|
||||
|
||||
|
@ -401,16 +401,16 @@ public class LevenbergMarquardtEstimator extends AbstractEstimator implements Se
|
||||
throw new EstimationException("cost relative tolerance is too small ({0})," +
|
||||
" no further reduction in the" +
|
||||
" sum of squares is possible",
|
||||
new Object[] { new Double(costRelativeTolerance) });
|
||||
new Object[] { Double.valueOf(costRelativeTolerance) });
|
||||
} else if (delta <= 2.2204e-16 * xNorm) {
|
||||
throw new EstimationException("parameters relative tolerance is too small" +
|
||||
" ({0}), no further improvement in" +
|
||||
" the approximate solution is possible",
|
||||
new Object[] { new Double(parRelativeTolerance) });
|
||||
new Object[] { Double.valueOf(parRelativeTolerance) });
|
||||
} else if (maxCosine <= 2.2204e-16) {
|
||||
throw new EstimationException("orthogonality tolerance is too small ({0})," +
|
||||
" solution is orthogonal to the jacobian",
|
||||
new Object[] { new Double(orthoTolerance) });
|
||||
new Object[] { Double.valueOf(orthoTolerance) });
|
||||
}
|
||||
|
||||
}
|
||||
@ -763,7 +763,7 @@ public class LevenbergMarquardtEstimator extends AbstractEstimator implements Se
|
||||
}
|
||||
if (Double.isInfinite(norm2) || Double.isNaN(norm2)) {
|
||||
throw new EstimationException("unable to perform Q.R decomposition on the {0}x{1} jacobian matrix",
|
||||
new Object[] { new Integer(rows), new Integer(cols) });
|
||||
new Object[] { Integer.valueOf(rows), Integer.valueOf(cols) });
|
||||
}
|
||||
if (norm2 > ak2) {
|
||||
nextColumn = i;
|
||||
|
@ -18,7 +18,6 @@
|
||||
package org.apache.commons.math.estimation;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@ -46,8 +45,8 @@ public class SimpleEstimationProblem implements EstimationProblem {
|
||||
* Build an empty instance without parameters nor measurements.
|
||||
*/
|
||||
public SimpleEstimationProblem() {
|
||||
parameters = new ArrayList();
|
||||
measurements = new ArrayList();
|
||||
parameters = new ArrayList<EstimatedParameter>();
|
||||
measurements = new ArrayList<WeightedMeasurement>();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -65,9 +64,8 @@ public class SimpleEstimationProblem implements EstimationProblem {
|
||||
public EstimatedParameter[] getUnboundParameters() {
|
||||
|
||||
// filter the unbound parameters
|
||||
List unbound = new ArrayList(parameters.size());
|
||||
for (Iterator iterator = parameters.iterator(); iterator.hasNext();) {
|
||||
EstimatedParameter p = (EstimatedParameter) iterator.next();
|
||||
List<EstimatedParameter> unbound = new ArrayList<EstimatedParameter>(parameters.size());
|
||||
for (EstimatedParameter p : parameters) {
|
||||
if (! p.isBound()) {
|
||||
unbound.add(p);
|
||||
}
|
||||
@ -102,9 +100,9 @@ public class SimpleEstimationProblem implements EstimationProblem {
|
||||
}
|
||||
|
||||
/** Estimated parameters. */
|
||||
private final List parameters;
|
||||
private final List<EstimatedParameter> parameters;
|
||||
|
||||
/** Measurements. */
|
||||
private final List measurements;
|
||||
private final List<WeightedMeasurement> measurements;
|
||||
|
||||
}
|
||||
|
@ -51,7 +51,10 @@ import java.io.Serializable;
|
||||
|
||||
public abstract class WeightedMeasurement implements Serializable {
|
||||
|
||||
/**
|
||||
/** Serializable version identifier. */
|
||||
private static final long serialVersionUID = 4360046376796901941L;
|
||||
|
||||
/**
|
||||
* Simple constructor.
|
||||
* Build a measurement with the given parameters, and set its ignore
|
||||
* flag to false.
|
||||
|
@ -17,6 +17,8 @@
|
||||
package org.apache.commons.math.fraction;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
import org.apache.commons.math.MathRuntimeException;
|
||||
import org.apache.commons.math.util.MathUtils;
|
||||
|
||||
/**
|
||||
@ -25,7 +27,7 @@ import org.apache.commons.math.util.MathUtils;
|
||||
* @since 1.1
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
public class Fraction extends Number implements Comparable {
|
||||
public class Fraction extends Number implements Comparable<Fraction> {
|
||||
|
||||
/** A fraction representing "1 / 1". */
|
||||
public static final Fraction ONE = new Fraction(1, 1);
|
||||
@ -34,7 +36,7 @@ public class Fraction extends Number implements Comparable {
|
||||
public static final Fraction ZERO = new Fraction(0, 1);
|
||||
|
||||
/** Serializable version identifier */
|
||||
private static final long serialVersionUID = -8958519416450949235L;
|
||||
private static final long serialVersionUID = -5731055832688548463L;
|
||||
|
||||
/** The denominator. */
|
||||
private final int denominator;
|
||||
@ -200,12 +202,13 @@ public class Fraction extends Number implements Comparable {
|
||||
public Fraction(int num, int den) {
|
||||
super();
|
||||
if (den == 0) {
|
||||
throw new ArithmeticException("The denominator must not be zero");
|
||||
throw MathRuntimeException.createArithmeticException("zero denominator in fraction {0}/{1}",
|
||||
new Object[] { num, den});
|
||||
}
|
||||
if (den < 0) {
|
||||
if (num == Integer.MIN_VALUE ||
|
||||
den == Integer.MIN_VALUE) {
|
||||
throw new ArithmeticException("overflow: can't negate");
|
||||
if (num == Integer.MIN_VALUE || den == Integer.MIN_VALUE) {
|
||||
throw MathRuntimeException.createArithmeticException("overflow in fraction {0}/{1}, cannot negate",
|
||||
new Object[] { num, den});
|
||||
}
|
||||
num = -num;
|
||||
den = -den;
|
||||
@ -246,13 +249,12 @@ public class Fraction extends Number implements Comparable {
|
||||
* @return -1 if this is less than <tt>object</tt>, +1 if this is greater
|
||||
* than <tt>object</tt>, 0 if they are equal.
|
||||
*/
|
||||
public int compareTo(Object object) {
|
||||
public int compareTo(Fraction object) {
|
||||
int ret = 0;
|
||||
|
||||
if (this != object) {
|
||||
Fraction other = (Fraction)object;
|
||||
double first = doubleValue();
|
||||
double second = other.doubleValue();
|
||||
double second = object.doubleValue();
|
||||
|
||||
if (first < second) {
|
||||
ret = -1;
|
||||
@ -362,7 +364,8 @@ public class Fraction extends Number implements Comparable {
|
||||
*/
|
||||
public Fraction negate() {
|
||||
if (numerator==Integer.MIN_VALUE) {
|
||||
throw new ArithmeticException("overflow: too large to negate");
|
||||
throw MathRuntimeException.createArithmeticException("overflow in fraction {0}/{1}, cannot negate",
|
||||
new Object[] { numerator, denominator});
|
||||
}
|
||||
return new Fraction(-numerator, denominator);
|
||||
}
|
||||
@ -452,8 +455,8 @@ public class Fraction extends Number implements Comparable {
|
||||
// result is (t/d2) / (u'/d1)(v'/d2)
|
||||
BigInteger w = t.divide(BigInteger.valueOf(d2));
|
||||
if (w.bitLength() > 31) {
|
||||
throw new ArithmeticException
|
||||
("overflow: numerator too large after multiply");
|
||||
throw MathRuntimeException.createArithmeticException("overflow, numerator too large after multiply: {0}",
|
||||
new Object[] { w });
|
||||
}
|
||||
return new Fraction (w.intValue(),
|
||||
MathUtils.mulAndCheck(denominator/d1,
|
||||
@ -501,7 +504,8 @@ public class Fraction extends Number implements Comparable {
|
||||
throw new IllegalArgumentException("The fraction must not be null");
|
||||
}
|
||||
if (fraction.numerator == 0) {
|
||||
throw new ArithmeticException("The fraction to divide by must not be zero");
|
||||
throw MathRuntimeException.createArithmeticException("the fraction to divide by must not be zero: {0}/{1}",
|
||||
new Object[] { fraction.numerator, fraction.denominator });
|
||||
}
|
||||
return multiply(fraction.reciprocal());
|
||||
}
|
||||
@ -519,7 +523,8 @@ public class Fraction extends Number implements Comparable {
|
||||
*/
|
||||
public static Fraction getReducedFraction(int numerator, int denominator) {
|
||||
if (denominator == 0) {
|
||||
throw new ArithmeticException("The denominator must not be zero");
|
||||
throw MathRuntimeException.createArithmeticException("zero denominator in fraction {0}/{1}",
|
||||
new Object[] { numerator, denominator});
|
||||
}
|
||||
if (numerator==0) {
|
||||
return ZERO; // normalize zero.
|
||||
@ -531,7 +536,8 @@ public class Fraction extends Number implements Comparable {
|
||||
if (denominator < 0) {
|
||||
if (numerator==Integer.MIN_VALUE ||
|
||||
denominator==Integer.MIN_VALUE) {
|
||||
throw new ArithmeticException("overflow: can't negate");
|
||||
throw MathRuntimeException.createArithmeticException("overflow in fraction {0}/{1}, cannot negate",
|
||||
new Object[] { numerator, denominator});
|
||||
}
|
||||
numerator = -numerator;
|
||||
denominator = -denominator;
|
||||
|
@ -39,7 +39,7 @@ public class FractionConversionException extends ConvergenceException {
|
||||
*/
|
||||
public FractionConversionException(double value, int maxIterations) {
|
||||
super("Unable to convert {0} to fraction after {1} iterations",
|
||||
new Object[] { new Double(value), new Integer(maxIterations) });
|
||||
new Object[] { Double.valueOf(value), Integer.valueOf(maxIterations) });
|
||||
}
|
||||
|
||||
/**
|
||||
@ -51,7 +51,7 @@ public class FractionConversionException extends ConvergenceException {
|
||||
*/
|
||||
public FractionConversionException(double value, long p, long q) {
|
||||
super("Overflow trying to convert {0} to fraction ({1}/{2})",
|
||||
new Object[] { new Double(value), new Long(p), new Long(q) });
|
||||
new Object[] { Double.valueOf(value), Long.valueOf(p), Long.valueOf(q) });
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ import java.text.ParsePosition;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.apache.commons.math.ConvergenceException;
|
||||
import org.apache.commons.math.MathRuntimeException;
|
||||
|
||||
/**
|
||||
* Formats a Fraction number in proper format or improper format. The number
|
||||
@ -244,8 +245,9 @@ public class FractionFormat extends Format implements Serializable {
|
||||
ParsePosition parsePosition = new ParsePosition(0);
|
||||
Fraction result = parse(source, parsePosition);
|
||||
if (parsePosition.getIndex() == 0) {
|
||||
throw new ParseException("Unparseable fraction number: \"" +
|
||||
source + "\"", parsePosition.getErrorIndex());
|
||||
throw MathRuntimeException.createParseException("unparseable fraction number: \"{0}\"",
|
||||
new Object[] { source },
|
||||
parsePosition.getErrorIndex());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ package org.apache.commons.math.genetics;
|
||||
|
||||
/**
|
||||
* Individual in a population. Chromosomes are compared based on their fitness.
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
public interface Chromosome {
|
||||
/**
|
||||
|
@ -18,6 +18,7 @@ package org.apache.commons.math.genetics;
|
||||
|
||||
/**
|
||||
* A pair of {@link Chromosome} objects.
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
public class ChromosomePair {
|
||||
/** the first chromosome in the pair. */
|
||||
|
@ -19,6 +19,7 @@ package org.apache.commons.math.genetics;
|
||||
/**
|
||||
* Policy used to create a pair of new chromosomes by performing a crossover
|
||||
* operation on a source pair of chromosomes.
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
public interface CrossoverPolicy {
|
||||
/**
|
||||
|
@ -19,6 +19,8 @@ package org.apache.commons.math.genetics;
|
||||
/**
|
||||
* Implementation of a genetic algorithm. All factors that govern the operation
|
||||
* of the algorithm can be configured for a specific problem.
|
||||
*
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
public class GeneticAlgorithm {
|
||||
/** the crossover policy used by the algorithm. */
|
||||
@ -98,7 +100,24 @@ public class GeneticAlgorithm {
|
||||
}
|
||||
|
||||
/**
|
||||
* Evolve the given population into the next generation.
|
||||
* <p>Evolve the given population into the next generation.</p>
|
||||
* <p><ol>
|
||||
* <li>Get nextGeneration polulation to fill from <code>current</code>
|
||||
* generation, using its nextGeneration method</li>
|
||||
* <li>Loop until new generation is filled:</li>
|
||||
* <ul><li>Apply configured SelectionPolicy to select a pair of parents
|
||||
* from <code>current</code></li>
|
||||
* <li>With probability = {@link #getCrossoverRate()}, apply
|
||||
* configured {@link CrossoverPolicy} to parents</li>
|
||||
* <li>With probability = {@link #getMutationRate()}, apply
|
||||
* configured {@link MutationPolicy} to each of the offspring</li>
|
||||
* <li>Add offspring individually to nextGeneration,
|
||||
* space permitting</li>
|
||||
* </ul>
|
||||
* <li>Return nextGeneration</li>
|
||||
* </ol>
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* @param current the current population.
|
||||
* @return the population for the next generation.
|
||||
@ -111,23 +130,29 @@ public class GeneticAlgorithm {
|
||||
// select parent chromosomes
|
||||
ChromosomePair pair = getSelectionPolicy().select(current);
|
||||
|
||||
// apply crossover policy to create two offspring
|
||||
// crossover?
|
||||
if (Math.random() < getCrossoverRate()) {
|
||||
// apply crossover policy to create two offspring
|
||||
pair = getCrossoverPolicy().crossover(pair.getFirst(),
|
||||
pair.getSecond());
|
||||
}
|
||||
|
||||
// apply mutation policy to first offspring
|
||||
// mutation?
|
||||
if (Math.random() < getMutationRate()) {
|
||||
nextGeneration.addChromosome(getMutationPolicy().mutate(
|
||||
pair.getFirst()));
|
||||
// apply mutation policy to the chromosomes
|
||||
pair = new ChromosomePair(
|
||||
getMutationPolicy().mutate(pair.getFirst()),
|
||||
getMutationPolicy().mutate(pair.getSecond())
|
||||
);
|
||||
}
|
||||
|
||||
if (nextGeneration.getPopulationSize() < nextGeneration
|
||||
.getPopulationLimit()) {
|
||||
// apply mutation policy to second offspring
|
||||
nextGeneration.addChromosome(getMutationPolicy().mutate(
|
||||
pair.getSecond()));
|
||||
}
|
||||
// add the first chromosome to the population
|
||||
nextGeneration.addChromosome(pair.getFirst());
|
||||
// is there still a place for the second chromosome?
|
||||
if (nextGeneration.getPopulationSize() < nextGeneration
|
||||
.getPopulationLimit()) {
|
||||
// add the second chromosome to the population
|
||||
nextGeneration.addChromosome(pair.getSecond());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,7 @@ package org.apache.commons.math.genetics;
|
||||
|
||||
/**
|
||||
* Algorithm used to mutate a chrommosome.
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
public interface MutationPolicy {
|
||||
|
||||
|
@ -18,6 +18,7 @@ package org.apache.commons.math.genetics;
|
||||
|
||||
/**
|
||||
* A collection of chromosomes that facilitates generational evolution.
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
public interface Population {
|
||||
/**
|
||||
|
@ -18,6 +18,7 @@ package org.apache.commons.math.genetics;
|
||||
|
||||
/**
|
||||
* Algorithm used to select a chromosome pair from a population.
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
public interface SelectionPolicy {
|
||||
/**
|
||||
|
@ -18,6 +18,7 @@ package org.apache.commons.math.genetics;
|
||||
|
||||
/**
|
||||
* Algorithm used to determine when to stop evolution.
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
public interface StoppingCondition {
|
||||
/**
|
||||
|
@ -35,7 +35,7 @@ public class CardanEulerSingularityException
|
||||
* if false it is related to EulerAngles
|
||||
*/
|
||||
public CardanEulerSingularityException(boolean isCardan) {
|
||||
super(isCardan ? "Cardan angles singularity" : "Euler angles singularity", new Object[0]);
|
||||
super(isCardan ? "Cardan angles singularity" : "Euler angles singularity", null);
|
||||
}
|
||||
|
||||
/** Serializable version identifier */
|
||||
|
@ -19,6 +19,8 @@ package org.apache.commons.math.geometry;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.apache.commons.math.MathRuntimeException;
|
||||
|
||||
/**
|
||||
* This class implements rotations in a three-dimensional space.
|
||||
*
|
||||
@ -88,14 +90,23 @@ import java.io.Serializable;
|
||||
|
||||
public class Rotation implements Serializable {
|
||||
|
||||
/** Build the identity rotation.
|
||||
*/
|
||||
public Rotation() {
|
||||
q0 = 1;
|
||||
q1 = 0;
|
||||
q2 = 0;
|
||||
q3 = 0;
|
||||
}
|
||||
/** Identity rotation. */
|
||||
public static final Rotation IDENTITY = new Rotation(1.0, 0.0, 0.0, 0.0, false);
|
||||
|
||||
/** Serializable version identifier */
|
||||
private static final long serialVersionUID = -2153622329907944313L;
|
||||
|
||||
/** Scalar coordinate of the quaternion. */
|
||||
private final double q0;
|
||||
|
||||
/** First coordinate of the vectorial part of the quaternion. */
|
||||
private final double q1;
|
||||
|
||||
/** Second coordinate of the vectorial part of the quaternion. */
|
||||
private final double q2;
|
||||
|
||||
/** Third coordinate of the vectorial part of the quaternion. */
|
||||
private final double q3;
|
||||
|
||||
/** Build a rotation from the quaternion coordinates.
|
||||
* <p>A rotation can be built from a <em>normalized</em> quaternion,
|
||||
@ -145,7 +156,8 @@ public class Rotation implements Serializable {
|
||||
|
||||
double norm = axis.getNorm();
|
||||
if (norm == 0) {
|
||||
throw new ArithmeticException("zero norm for rotation axis");
|
||||
throw MathRuntimeException.createArithmeticException("zero norm for rotation axis",
|
||||
null);
|
||||
}
|
||||
|
||||
double halfAngle = -0.5 * angle;
|
||||
@ -453,10 +465,10 @@ public class Rotation implements Serializable {
|
||||
/** Build a rotation from three Cardan or Euler elementary rotations.
|
||||
|
||||
* <p>Cardan rotations are three successive rotations around the
|
||||
* canonical axes X, Y and Z, each axis beeing used once. There are
|
||||
* canonical axes X, Y and Z, each axis being used once. There are
|
||||
* 6 such sets of rotations (XYZ, XZY, YXZ, YZX, ZXY and ZYX). Euler
|
||||
* rotations are three successive rotations around the canonical
|
||||
* axes X, Y and Z, the first and last rotations beeing around the
|
||||
* axes X, Y and Z, the first and last rotations being around the
|
||||
* same axis. There are 6 such sets of rotations (XYX, XZX, YXY,
|
||||
* YZY, ZXZ and ZYZ), the most popular one being ZXZ.</p>
|
||||
* <p>Beware that many people routinely use the term Euler angles even
|
||||
@ -592,8 +604,8 @@ public class Rotation implements Serializable {
|
||||
// (-r) (Vector3D.plusI) coordinates are :
|
||||
// cos (psi) cos (theta), -sin (psi) cos (theta), sin (theta)
|
||||
// and we can choose to have theta in the interval [-PI/2 ; +PI/2]
|
||||
Vector3D v1 = applyTo(Vector3D.plusK);
|
||||
Vector3D v2 = applyInverseTo(Vector3D.plusI);
|
||||
Vector3D v1 = applyTo(Vector3D.PLUS_K);
|
||||
Vector3D v2 = applyInverseTo(Vector3D.PLUS_I);
|
||||
if ((v2.getZ() < -0.9999999999) || (v2.getZ() > 0.9999999999)) {
|
||||
throw new CardanEulerSingularityException(true);
|
||||
}
|
||||
@ -610,8 +622,8 @@ public class Rotation implements Serializable {
|
||||
// (-r) (Vector3D.plusI) coordinates are :
|
||||
// cos (theta) cos (psi), -sin (psi), sin (theta) cos (psi)
|
||||
// and we can choose to have psi in the interval [-PI/2 ; +PI/2]
|
||||
Vector3D v1 = applyTo(Vector3D.plusJ);
|
||||
Vector3D v2 = applyInverseTo(Vector3D.plusI);
|
||||
Vector3D v1 = applyTo(Vector3D.PLUS_J);
|
||||
Vector3D v2 = applyInverseTo(Vector3D.PLUS_I);
|
||||
if ((v2.getY() < -0.9999999999) || (v2.getY() > 0.9999999999)) {
|
||||
throw new CardanEulerSingularityException(true);
|
||||
}
|
||||
@ -628,8 +640,8 @@ public class Rotation implements Serializable {
|
||||
// (-r) (Vector3D.plusJ) coordinates are :
|
||||
// sin (psi) cos (phi), cos (psi) cos (phi), -sin (phi)
|
||||
// and we can choose to have phi in the interval [-PI/2 ; +PI/2]
|
||||
Vector3D v1 = applyTo(Vector3D.plusK);
|
||||
Vector3D v2 = applyInverseTo(Vector3D.plusJ);
|
||||
Vector3D v1 = applyTo(Vector3D.PLUS_K);
|
||||
Vector3D v2 = applyInverseTo(Vector3D.PLUS_J);
|
||||
if ((v2.getZ() < -0.9999999999) || (v2.getZ() > 0.9999999999)) {
|
||||
throw new CardanEulerSingularityException(true);
|
||||
}
|
||||
@ -646,8 +658,8 @@ public class Rotation implements Serializable {
|
||||
// (-r) (Vector3D.plusJ) coordinates are :
|
||||
// sin (psi), cos (phi) cos (psi), -sin (phi) cos (psi)
|
||||
// and we can choose to have psi in the interval [-PI/2 ; +PI/2]
|
||||
Vector3D v1 = applyTo(Vector3D.plusI);
|
||||
Vector3D v2 = applyInverseTo(Vector3D.plusJ);
|
||||
Vector3D v1 = applyTo(Vector3D.PLUS_I);
|
||||
Vector3D v2 = applyInverseTo(Vector3D.PLUS_J);
|
||||
if ((v2.getX() < -0.9999999999) || (v2.getX() > 0.9999999999)) {
|
||||
throw new CardanEulerSingularityException(true);
|
||||
}
|
||||
@ -664,8 +676,8 @@ public class Rotation implements Serializable {
|
||||
// (-r) (Vector3D.plusK) coordinates are :
|
||||
// -sin (theta) cos (phi), sin (phi), cos (theta) cos (phi)
|
||||
// and we can choose to have phi in the interval [-PI/2 ; +PI/2]
|
||||
Vector3D v1 = applyTo(Vector3D.plusJ);
|
||||
Vector3D v2 = applyInverseTo(Vector3D.plusK);
|
||||
Vector3D v1 = applyTo(Vector3D.PLUS_J);
|
||||
Vector3D v2 = applyInverseTo(Vector3D.PLUS_K);
|
||||
if ((v2.getY() < -0.9999999999) || (v2.getY() > 0.9999999999)) {
|
||||
throw new CardanEulerSingularityException(true);
|
||||
}
|
||||
@ -682,8 +694,8 @@ public class Rotation implements Serializable {
|
||||
// (-r) (Vector3D.plusK) coordinates are :
|
||||
// -sin (theta), sin (phi) cos (theta), cos (phi) cos (theta)
|
||||
// and we can choose to have theta in the interval [-PI/2 ; +PI/2]
|
||||
Vector3D v1 = applyTo(Vector3D.plusI);
|
||||
Vector3D v2 = applyInverseTo(Vector3D.plusK);
|
||||
Vector3D v1 = applyTo(Vector3D.PLUS_I);
|
||||
Vector3D v2 = applyInverseTo(Vector3D.PLUS_K);
|
||||
if ((v2.getX() < -0.9999999999) || (v2.getX() > 0.9999999999)) {
|
||||
throw new CardanEulerSingularityException(true);
|
||||
}
|
||||
@ -700,8 +712,8 @@ public class Rotation implements Serializable {
|
||||
// (-r) (Vector3D.plusI) coordinates are :
|
||||
// cos (theta), sin (theta) sin (phi2), sin (theta) cos (phi2)
|
||||
// and we can choose to have theta in the interval [0 ; PI]
|
||||
Vector3D v1 = applyTo(Vector3D.plusI);
|
||||
Vector3D v2 = applyInverseTo(Vector3D.plusI);
|
||||
Vector3D v1 = applyTo(Vector3D.PLUS_I);
|
||||
Vector3D v2 = applyInverseTo(Vector3D.PLUS_I);
|
||||
if ((v2.getX() < -0.9999999999) || (v2.getX() > 0.9999999999)) {
|
||||
throw new CardanEulerSingularityException(false);
|
||||
}
|
||||
@ -718,8 +730,8 @@ public class Rotation implements Serializable {
|
||||
// (-r) (Vector3D.plusI) coordinates are :
|
||||
// cos (psi), -sin (psi) cos (phi2), sin (psi) sin (phi2)
|
||||
// and we can choose to have psi in the interval [0 ; PI]
|
||||
Vector3D v1 = applyTo(Vector3D.plusI);
|
||||
Vector3D v2 = applyInverseTo(Vector3D.plusI);
|
||||
Vector3D v1 = applyTo(Vector3D.PLUS_I);
|
||||
Vector3D v2 = applyInverseTo(Vector3D.PLUS_I);
|
||||
if ((v2.getX() < -0.9999999999) || (v2.getX() > 0.9999999999)) {
|
||||
throw new CardanEulerSingularityException(false);
|
||||
}
|
||||
@ -736,8 +748,8 @@ public class Rotation implements Serializable {
|
||||
// (-r) (Vector3D.plusJ) coordinates are :
|
||||
// sin (phi) sin (theta2), cos (phi), -sin (phi) cos (theta2)
|
||||
// and we can choose to have phi in the interval [0 ; PI]
|
||||
Vector3D v1 = applyTo(Vector3D.plusJ);
|
||||
Vector3D v2 = applyInverseTo(Vector3D.plusJ);
|
||||
Vector3D v1 = applyTo(Vector3D.PLUS_J);
|
||||
Vector3D v2 = applyInverseTo(Vector3D.PLUS_J);
|
||||
if ((v2.getY() < -0.9999999999) || (v2.getY() > 0.9999999999)) {
|
||||
throw new CardanEulerSingularityException(false);
|
||||
}
|
||||
@ -754,8 +766,8 @@ public class Rotation implements Serializable {
|
||||
// (-r) (Vector3D.plusJ) coordinates are :
|
||||
// sin (psi) cos (theta2), cos (psi), sin (psi) sin (theta2)
|
||||
// and we can choose to have psi in the interval [0 ; PI]
|
||||
Vector3D v1 = applyTo(Vector3D.plusJ);
|
||||
Vector3D v2 = applyInverseTo(Vector3D.plusJ);
|
||||
Vector3D v1 = applyTo(Vector3D.PLUS_J);
|
||||
Vector3D v2 = applyInverseTo(Vector3D.PLUS_J);
|
||||
if ((v2.getY() < -0.9999999999) || (v2.getY() > 0.9999999999)) {
|
||||
throw new CardanEulerSingularityException(false);
|
||||
}
|
||||
@ -772,8 +784,8 @@ public class Rotation implements Serializable {
|
||||
// (-r) (Vector3D.plusK) coordinates are :
|
||||
// sin (phi) sin (psi2), sin (phi) cos (psi2), cos (phi)
|
||||
// and we can choose to have phi in the interval [0 ; PI]
|
||||
Vector3D v1 = applyTo(Vector3D.plusK);
|
||||
Vector3D v2 = applyInverseTo(Vector3D.plusK);
|
||||
Vector3D v1 = applyTo(Vector3D.PLUS_K);
|
||||
Vector3D v2 = applyInverseTo(Vector3D.PLUS_K);
|
||||
if ((v2.getZ() < -0.9999999999) || (v2.getZ() > 0.9999999999)) {
|
||||
throw new CardanEulerSingularityException(false);
|
||||
}
|
||||
@ -790,8 +802,8 @@ public class Rotation implements Serializable {
|
||||
// (-r) (Vector3D.plusK) coordinates are :
|
||||
// -sin (theta) cos (psi2), sin (theta) sin (psi2), cos (theta)
|
||||
// and we can choose to have theta in the interval [0 ; PI]
|
||||
Vector3D v1 = applyTo(Vector3D.plusK);
|
||||
Vector3D v2 = applyInverseTo(Vector3D.plusK);
|
||||
Vector3D v1 = applyTo(Vector3D.PLUS_K);
|
||||
Vector3D v2 = applyInverseTo(Vector3D.PLUS_K);
|
||||
if ((v2.getZ() < -0.9999999999) || (v2.getZ() > 0.9999999999)) {
|
||||
throw new CardanEulerSingularityException(false);
|
||||
}
|
||||
@ -1017,19 +1029,32 @@ public class Rotation implements Serializable {
|
||||
});
|
||||
}
|
||||
|
||||
/** Scalar coordinate of the quaternion. */
|
||||
private final double q0;
|
||||
|
||||
/** First coordinate of the vectorial part of the quaternion. */
|
||||
private final double q1;
|
||||
|
||||
/** Second coordinate of the vectorial part of the quaternion. */
|
||||
private final double q2;
|
||||
|
||||
/** Third coordinate of the vectorial part of the quaternion. */
|
||||
private final double q3;
|
||||
|
||||
/** Serializable version identifier */
|
||||
private static final long serialVersionUID = 8225864499430109352L;
|
||||
/** Compute the <i>distance</i> between two rotations.
|
||||
* <p>The <i>distance</i> is intended here as a way to check if two
|
||||
* rotations are almost similar (i.e. they transform vectors the same way)
|
||||
* or very different. It is mathematically defined as the angle of
|
||||
* the rotation r that prepended to one of the rotations gives the other
|
||||
* one:</p>
|
||||
* <pre>
|
||||
* r<sub>1</sub>(r) = r<sub>2</sub>
|
||||
* </pre>
|
||||
* <p>This distance is an angle between 0 and π. Its value is the smallest
|
||||
* possible upper bound of the angle in radians between r<sub>1</sub>(v)
|
||||
* and r<sub>2</sub>(v) for all possible vectors v. This upper bound is
|
||||
* reached for some v. The distance is equal to 0 if and only if the two
|
||||
* rotations are identical.</p>
|
||||
* <p>Comparing two rotations should always be done using this value rather
|
||||
* than for example comparing the components of the quaternions. It is much
|
||||
* more stable, and has a geometric meaning. Also comparing quaternions
|
||||
* components is error prone since for example quaternions (0.36, 0.48, -0.48, -0.64)
|
||||
* and (-0.36, -0.48, 0.48, 0.64) represent exactly the same rotation despite
|
||||
* their components are different (they are exact opposites).</p>
|
||||
* @param r1 first rotation
|
||||
* @param r2 second rotation
|
||||
* @return <i>distance</i> between r1 and r2
|
||||
*/
|
||||
public static double distance(Rotation r1, Rotation r2) {
|
||||
return r1.applyInverseTo(r2).getAngle();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -80,84 +80,84 @@ public final class RotationOrder {
|
||||
* around Z
|
||||
*/
|
||||
public static final RotationOrder XYZ =
|
||||
new RotationOrder("XYZ", Vector3D.plusI, Vector3D.plusJ, Vector3D.plusK);
|
||||
new RotationOrder("XYZ", Vector3D.PLUS_I, Vector3D.PLUS_J, Vector3D.PLUS_K);
|
||||
|
||||
/** Set of Cardan angles.
|
||||
* this ordered set of rotations is around X, then around Z, then
|
||||
* around Y
|
||||
*/
|
||||
public static final RotationOrder XZY =
|
||||
new RotationOrder("XZY", Vector3D.plusI, Vector3D.plusK, Vector3D.plusJ);
|
||||
new RotationOrder("XZY", Vector3D.PLUS_I, Vector3D.PLUS_K, Vector3D.PLUS_J);
|
||||
|
||||
/** Set of Cardan angles.
|
||||
* this ordered set of rotations is around Y, then around X, then
|
||||
* around Z
|
||||
*/
|
||||
public static final RotationOrder YXZ =
|
||||
new RotationOrder("YXZ", Vector3D.plusJ, Vector3D.plusI, Vector3D.plusK);
|
||||
new RotationOrder("YXZ", Vector3D.PLUS_J, Vector3D.PLUS_I, Vector3D.PLUS_K);
|
||||
|
||||
/** Set of Cardan angles.
|
||||
* this ordered set of rotations is around Y, then around Z, then
|
||||
* around X
|
||||
*/
|
||||
public static final RotationOrder YZX =
|
||||
new RotationOrder("YZX", Vector3D.plusJ, Vector3D.plusK, Vector3D.plusI);
|
||||
new RotationOrder("YZX", Vector3D.PLUS_J, Vector3D.PLUS_K, Vector3D.PLUS_I);
|
||||
|
||||
/** Set of Cardan angles.
|
||||
* this ordered set of rotations is around Z, then around X, then
|
||||
* around Y
|
||||
*/
|
||||
public static final RotationOrder ZXY =
|
||||
new RotationOrder("ZXY", Vector3D.plusK, Vector3D.plusI, Vector3D.plusJ);
|
||||
new RotationOrder("ZXY", Vector3D.PLUS_K, Vector3D.PLUS_I, Vector3D.PLUS_J);
|
||||
|
||||
/** Set of Cardan angles.
|
||||
* this ordered set of rotations is around Z, then around Y, then
|
||||
* around X
|
||||
*/
|
||||
public static final RotationOrder ZYX =
|
||||
new RotationOrder("ZYX", Vector3D.plusK, Vector3D.plusJ, Vector3D.plusI);
|
||||
new RotationOrder("ZYX", Vector3D.PLUS_K, Vector3D.PLUS_J, Vector3D.PLUS_I);
|
||||
|
||||
/** Set of Euler angles.
|
||||
* this ordered set of rotations is around X, then around Y, then
|
||||
* around X
|
||||
*/
|
||||
public static final RotationOrder XYX =
|
||||
new RotationOrder("XYX", Vector3D.plusI, Vector3D.plusJ, Vector3D.plusI);
|
||||
new RotationOrder("XYX", Vector3D.PLUS_I, Vector3D.PLUS_J, Vector3D.PLUS_I);
|
||||
|
||||
/** Set of Euler angles.
|
||||
* this ordered set of rotations is around X, then around Z, then
|
||||
* around X
|
||||
*/
|
||||
public static final RotationOrder XZX =
|
||||
new RotationOrder("XZX", Vector3D.plusI, Vector3D.plusK, Vector3D.plusI);
|
||||
new RotationOrder("XZX", Vector3D.PLUS_I, Vector3D.PLUS_K, Vector3D.PLUS_I);
|
||||
|
||||
/** Set of Euler angles.
|
||||
* this ordered set of rotations is around Y, then around X, then
|
||||
* around Y
|
||||
*/
|
||||
public static final RotationOrder YXY =
|
||||
new RotationOrder("YXY", Vector3D.plusJ, Vector3D.plusI, Vector3D.plusJ);
|
||||
new RotationOrder("YXY", Vector3D.PLUS_J, Vector3D.PLUS_I, Vector3D.PLUS_J);
|
||||
|
||||
/** Set of Euler angles.
|
||||
* this ordered set of rotations is around Y, then around Z, then
|
||||
* around Y
|
||||
*/
|
||||
public static final RotationOrder YZY =
|
||||
new RotationOrder("YZY", Vector3D.plusJ, Vector3D.plusK, Vector3D.plusJ);
|
||||
new RotationOrder("YZY", Vector3D.PLUS_J, Vector3D.PLUS_K, Vector3D.PLUS_J);
|
||||
|
||||
/** Set of Euler angles.
|
||||
* this ordered set of rotations is around Z, then around X, then
|
||||
* around Z
|
||||
*/
|
||||
public static final RotationOrder ZXZ =
|
||||
new RotationOrder("ZXZ", Vector3D.plusK, Vector3D.plusI, Vector3D.plusK);
|
||||
new RotationOrder("ZXZ", Vector3D.PLUS_K, Vector3D.PLUS_I, Vector3D.PLUS_K);
|
||||
|
||||
/** Set of Euler angles.
|
||||
* this ordered set of rotations is around Z, then around Y, then
|
||||
* around Z
|
||||
*/
|
||||
public static final RotationOrder ZYZ =
|
||||
new RotationOrder("ZYZ", Vector3D.plusK, Vector3D.plusJ, Vector3D.plusK);
|
||||
new RotationOrder("ZYZ", Vector3D.PLUS_K, Vector3D.PLUS_J, Vector3D.PLUS_K);
|
||||
|
||||
/** Name of the rotations order. */
|
||||
private final String name;
|
||||
|
@ -19,6 +19,9 @@ package org.apache.commons.math.geometry;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.apache.commons.math.MathRuntimeException;
|
||||
import org.apache.commons.math.util.MathUtils;
|
||||
|
||||
/**
|
||||
* This class implements vectors in a three-dimensional space.
|
||||
* <p>Instance of this class are guaranteed to be immutable.</p>
|
||||
@ -29,35 +32,53 @@ import java.io.Serializable;
|
||||
public class Vector3D
|
||||
implements Serializable {
|
||||
|
||||
/** Null vector (coordinates: 0, 0, 0). */
|
||||
public static final Vector3D ZERO = new Vector3D(0, 0, 0);
|
||||
|
||||
/** First canonical vector (coordinates: 1, 0, 0). */
|
||||
public static final Vector3D plusI = new Vector3D(1, 0, 0);
|
||||
public static final Vector3D PLUS_I = new Vector3D(1, 0, 0);
|
||||
|
||||
/** Opposite of the first canonical vector (coordinates: -1, 0, 0). */
|
||||
public static final Vector3D minusI = new Vector3D(-1, 0, 0);
|
||||
public static final Vector3D MINUS_I = new Vector3D(-1, 0, 0);
|
||||
|
||||
/** Second canonical vector (coordinates: 0, 1, 0). */
|
||||
public static final Vector3D plusJ = new Vector3D(0, 1, 0);
|
||||
public static final Vector3D PLUS_J = new Vector3D(0, 1, 0);
|
||||
|
||||
/** Opposite of the second canonical vector (coordinates: 0, -1, 0). */
|
||||
public static final Vector3D minusJ = new Vector3D(0, -1, 0);
|
||||
public static final Vector3D MINUS_J = new Vector3D(0, -1, 0);
|
||||
|
||||
/** Third canonical vector (coordinates: 0, 0, 1). */
|
||||
public static final Vector3D plusK = new Vector3D(0, 0, 1);
|
||||
public static final Vector3D PLUS_K = new Vector3D(0, 0, 1);
|
||||
|
||||
/** Opposite of the third canonical vector (coordinates: 0, 0, -1). */
|
||||
public static final Vector3D minusK = new Vector3D(0, 0, -1);
|
||||
public static final Vector3D MINUS_K = new Vector3D(0, 0, -1);
|
||||
|
||||
/** Null vector (coordinates: 0, 0, 0). */
|
||||
public static final Vector3D zero = new Vector3D(0, 0, 0);
|
||||
/** A vector with all coordinates set to NaN. */
|
||||
public static final Vector3D NaN = new Vector3D(Double.NaN, Double.NaN, Double.NaN);
|
||||
|
||||
/** Simple constructor.
|
||||
* Build a null vector.
|
||||
*/
|
||||
public Vector3D() {
|
||||
x = 0;
|
||||
y = 0;
|
||||
z = 0;
|
||||
}
|
||||
/** A vector with all coordinates set to positive infinity. */
|
||||
public static final Vector3D POSITIVE_INFINITY =
|
||||
new Vector3D(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY);
|
||||
|
||||
/** A vector with all coordinates set to negative infinity. */
|
||||
public static final Vector3D NEGATIVE_INFINITY =
|
||||
new Vector3D(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY);
|
||||
|
||||
/** Default format. */
|
||||
private static final Vector3DFormat DEFAULT_FORMAT =
|
||||
Vector3DFormat.getInstance();
|
||||
|
||||
/** Serializable version identifier. */
|
||||
private static final long serialVersionUID = 5133268763396045979L;
|
||||
|
||||
/** Abscissa. */
|
||||
private final double x;
|
||||
|
||||
/** Ordinate. */
|
||||
private final double y;
|
||||
|
||||
/** Height. */
|
||||
private final double z;
|
||||
|
||||
/** Simple constructor.
|
||||
* Build a vector from its coordinates
|
||||
@ -182,6 +203,13 @@ public class Vector3D
|
||||
return Math.sqrt (x * x + y * y + z * z);
|
||||
}
|
||||
|
||||
/** Get the square of the norm for the vector.
|
||||
* @return square of the euclidian norm for the vector
|
||||
*/
|
||||
public double getNormSq() {
|
||||
return x * x + y * y + z * z;
|
||||
}
|
||||
|
||||
/** Get the azimuth of the vector.
|
||||
* @return azimuth (α) of the vector, between -π and +π
|
||||
* @see #Vector3D(double, double)
|
||||
@ -239,7 +267,8 @@ public class Vector3D
|
||||
public Vector3D normalize() {
|
||||
double s = getNorm();
|
||||
if (s == 0) {
|
||||
throw new ArithmeticException("cannot normalize a zero norm vector");
|
||||
throw MathRuntimeException.createArithmeticException("cannot normalize a zero norm vector",
|
||||
null);
|
||||
}
|
||||
return scalarMultiply(1 / s);
|
||||
}
|
||||
@ -263,7 +292,7 @@ public class Vector3D
|
||||
|
||||
double threshold = 0.6 * getNorm();
|
||||
if (threshold == 0) {
|
||||
throw new ArithmeticException("null norm");
|
||||
throw MathRuntimeException.createArithmeticException("zero norm", null);
|
||||
}
|
||||
|
||||
if ((x >= -threshold) && (x <= threshold)) {
|
||||
@ -293,7 +322,7 @@ public class Vector3D
|
||||
|
||||
double normProduct = v1.getNorm() * v2.getNorm();
|
||||
if (normProduct == 0) {
|
||||
throw new ArithmeticException("null norm");
|
||||
throw MathRuntimeException.createArithmeticException("zero norm", null);
|
||||
}
|
||||
|
||||
double dot = dotProduct(v1, v2);
|
||||
@ -327,6 +356,83 @@ public class Vector3D
|
||||
return new Vector3D(a * x, a * y, a * z);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if any coordinate of this vector is NaN; false otherwise
|
||||
* @return true if any coordinate of this vector is NaN; false otherwise
|
||||
*/
|
||||
public boolean isNaN() {
|
||||
return Double.isNaN(x) || Double.isNaN(y) || Double.isNaN(z);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if any coordinate of this vector is infinite and none are NaN;
|
||||
* false otherwise
|
||||
* @return true if any coordinate of this vector is infinite and none are NaN;
|
||||
* false otherwise
|
||||
*/
|
||||
public boolean isInfinite() {
|
||||
return !isNaN() && (Double.isInfinite(x) || Double.isInfinite(y) || Double.isInfinite(z));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for the equality of two 3D vectors.
|
||||
* <p>
|
||||
* If all coordinates of two 3D vectors are exactly the same, and none are
|
||||
* <code>Double.NaN</code>, the two 3D vectors are considered to be equal.
|
||||
* </p>
|
||||
* <p>
|
||||
* <code>NaN</code> coordinates are considered to affect globally the vector
|
||||
* and be equals to each other - i.e, if either (or all) coordinates of the
|
||||
* 3D vector are equal to <code>Double.NaN</code>, the 3D vector is equal to
|
||||
* {@link #NaN}.
|
||||
* </p>
|
||||
*
|
||||
* @param other Object to test for equality to this
|
||||
* @return true if two 3D vector objects are equal, false if
|
||||
* object is null, not an instance of Vector3D, or
|
||||
* not equal to this Vector3D instance
|
||||
*
|
||||
*/
|
||||
public boolean equals(Object other) {
|
||||
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (other == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
final Vector3D rhs = (Vector3D)other;
|
||||
if (rhs.isNaN()) {
|
||||
return this.isNaN();
|
||||
}
|
||||
|
||||
return (x == rhs.x) && (y == rhs.y) && (z == rhs.z);
|
||||
|
||||
} catch (ClassCastException ex) {
|
||||
// ignore exception
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a hashCode for the 3D vector.
|
||||
* <p>
|
||||
* All NaN values have the same hash code.</p>
|
||||
*
|
||||
* @return a hash code value for this object
|
||||
*/
|
||||
public int hashCode() {
|
||||
if (isNaN()) {
|
||||
return 8;
|
||||
}
|
||||
return 31 * (23 * MathUtils.hash(x) + 19 * MathUtils.hash(y) + MathUtils.hash(z));
|
||||
}
|
||||
|
||||
/** Compute the dot-product of two vectors.
|
||||
* @param v1 first vector
|
||||
* @param v2 second vector
|
||||
@ -347,17 +453,41 @@ public class Vector3D
|
||||
v1.x * v2.y - v1.y * v2.x);
|
||||
}
|
||||
|
||||
/** Abscissa. */
|
||||
private final double x;
|
||||
/** Compute the distance between two vectors.
|
||||
* <p>Calling this method is equivalent to calling:
|
||||
* <code>v1.subtract(v2).getNorm()</code> except that no intermediate
|
||||
* vector is built</p>
|
||||
* @param v1 first vector
|
||||
* @param v2 second vector
|
||||
* @return the distance between v1 and v2
|
||||
*/
|
||||
public static double distance(Vector3D v1, Vector3D v2) {
|
||||
final double dx = v2.x - v1.x;
|
||||
final double dy = v2.y - v1.y;
|
||||
final double dz = v2.z - v1.z;
|
||||
return Math.sqrt(dx * dx + dy * dy + dz * dz);
|
||||
}
|
||||
|
||||
/** Ordinate. */
|
||||
private final double y;
|
||||
|
||||
/** Height. */
|
||||
private final double z;
|
||||
|
||||
/** Serializable version identifier */
|
||||
private static final long serialVersionUID = -5721105387745193385L;
|
||||
/** Compute the square of the distance between two vectors.
|
||||
* <p>Calling this method is equivalent to calling:
|
||||
* <code>v1.subtract(v2).getNormSq()</code> except that no intermediate
|
||||
* vector is built</p>
|
||||
* @param v1 first vector
|
||||
* @param v2 second vector
|
||||
* @return the square of the distance between v1 and v2
|
||||
*/
|
||||
public static double distanceSq(Vector3D v1, Vector3D v2) {
|
||||
final double dx = v2.x - v1.x;
|
||||
final double dy = v2.y - v1.y;
|
||||
final double dz = v2.z - v1.z;
|
||||
return dx * dx + dy * dy + dz * dz;
|
||||
}
|
||||
|
||||
/** Get a string representation of this vector.
|
||||
* @return a string representation of this vector
|
||||
*/
|
||||
public String toString() {
|
||||
return DEFAULT_FORMAT.format(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
339
src/java/org/apache/commons/math/geometry/Vector3DFormat.java
Normal file
339
src/java/org/apache/commons/math/geometry/Vector3DFormat.java
Normal file
@ -0,0 +1,339 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.commons.math.geometry;
|
||||
|
||||
import java.text.FieldPosition;
|
||||
import java.text.NumberFormat;
|
||||
import java.text.ParseException;
|
||||
import java.text.ParsePosition;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.apache.commons.math.MathRuntimeException;
|
||||
import org.apache.commons.math.util.CompositeFormat;
|
||||
|
||||
/**
|
||||
* Formats a 3D vector in components list format "{x; y; z}".
|
||||
* <p>The prefix and suffix "{" and "}" and the separator "; " can be replaced by
|
||||
* any user-defined strings. The number format for components can be configured.</p>
|
||||
* <p>White space is ignored at parse time, even if it is in the prefix, suffix
|
||||
* or separator specifications. So even if the default separator does include a space
|
||||
* character that is used at format time, both input string "{1;1;1}" and
|
||||
* " { 1 ; 1 ; 1 } " will be parsed without error and the same vector will be
|
||||
* returned. In the second case, however, the parse position after parsing will be
|
||||
* just after the closing curly brace, i.e. just before the trailing space.</p>
|
||||
*
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
public class Vector3DFormat extends CompositeFormat {
|
||||
|
||||
/** Serializable version identifier */
|
||||
private static final long serialVersionUID = -5447606608652576301L;
|
||||
|
||||
/** The default prefix: "{". */
|
||||
private static final String DEFAULT_PREFIX = "{";
|
||||
|
||||
/** The default suffix: "}". */
|
||||
private static final String DEFAULT_SUFFIX = "}";
|
||||
|
||||
/** The default separator: ", ". */
|
||||
private static final String DEFAULT_SEPARATOR = "; ";
|
||||
|
||||
/** Prefix. */
|
||||
private final String prefix;
|
||||
|
||||
/** Suffix. */
|
||||
private final String suffix;
|
||||
|
||||
/** Separator. */
|
||||
private final String separator;
|
||||
|
||||
/** Trimmed prefix. */
|
||||
private final String trimmedPrefix;
|
||||
|
||||
/** Trimmed suffix. */
|
||||
private final String trimmedSuffix;
|
||||
|
||||
/** Trimmed separator. */
|
||||
private final String trimmedSeparator;
|
||||
|
||||
/** The format used for components. */
|
||||
private NumberFormat format;
|
||||
|
||||
/**
|
||||
* Create an instance with default settings.
|
||||
* <p>The instance uses the default prefix, suffix and separator:
|
||||
* "{", "}", and "; " and the default number format for components.</p>
|
||||
*/
|
||||
public Vector3DFormat() {
|
||||
this(DEFAULT_PREFIX, DEFAULT_SUFFIX, DEFAULT_SEPARATOR, getDefaultNumberFormat());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance with a custom number format for components.
|
||||
* @param format the custom format for components.
|
||||
*/
|
||||
public Vector3DFormat(final NumberFormat format) {
|
||||
this(DEFAULT_PREFIX, DEFAULT_SUFFIX, DEFAULT_SEPARATOR, format);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance with custom prefix, suffix and separator.
|
||||
* @param prefix prefix to use instead of the default "{"
|
||||
* @param suffix suffix to use instead of the default "}"
|
||||
* @param separator separator to use instead of the default "; "
|
||||
*/
|
||||
public Vector3DFormat(final String prefix, final String suffix,
|
||||
final String separator) {
|
||||
this(prefix, suffix, separator, getDefaultNumberFormat());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance with custom prefix, suffix, separator and format
|
||||
* for components.
|
||||
* @param prefix prefix to use instead of the default "{"
|
||||
* @param suffix suffix to use instead of the default "}"
|
||||
* @param separator separator to use instead of the default "; "
|
||||
* @param format the custom format for components.
|
||||
*/
|
||||
public Vector3DFormat(final String prefix, final String suffix,
|
||||
final String separator, final NumberFormat format) {
|
||||
this.prefix = prefix;
|
||||
this.suffix = suffix;
|
||||
this.separator = separator;
|
||||
trimmedPrefix = prefix.trim();
|
||||
trimmedSuffix = suffix.trim();
|
||||
trimmedSeparator = separator.trim();
|
||||
this.format = format;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the set of locales for which 3D vectors formats are available.
|
||||
* <p>This is the same set as the {@link NumberFormat} set.</p>
|
||||
* @return available 3D vector format locales.
|
||||
*/
|
||||
public static Locale[] getAvailableLocales() {
|
||||
return NumberFormat.getAvailableLocales();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the format prefix.
|
||||
* @return format prefix.
|
||||
*/
|
||||
public String getPrefix() {
|
||||
return prefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the format suffix.
|
||||
* @return format suffix.
|
||||
*/
|
||||
public String getSuffix() {
|
||||
return suffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the format separator between components.
|
||||
* @return format separator.
|
||||
*/
|
||||
public String getSeparator() {
|
||||
return separator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the components format.
|
||||
* @return components format.
|
||||
*/
|
||||
public NumberFormat getFormat() {
|
||||
return format;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default 3D vector format for the current locale.
|
||||
* @return the default 3D vector format.
|
||||
*/
|
||||
public static Vector3DFormat getInstance() {
|
||||
return getInstance(Locale.getDefault());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default 3D vector format for the given locale.
|
||||
* @param locale the specific locale used by the format.
|
||||
* @return the 3D vector format specific to the given locale.
|
||||
*/
|
||||
public static Vector3DFormat getInstance(final Locale locale) {
|
||||
return new Vector3DFormat(getDefaultNumberFormat(locale));
|
||||
}
|
||||
|
||||
/**
|
||||
* This static method calls {@link #format(Object)} on a default instance of
|
||||
* Vector3DFormat.
|
||||
*
|
||||
* @param v Vector3D object to format
|
||||
* @return A formatted vector
|
||||
*/
|
||||
public static String formatVector3D(Vector3D v) {
|
||||
return getInstance().format(v);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a {@link Vector3D} object to produce a string.
|
||||
* @param vector the object to format.
|
||||
* @param toAppendTo where the text is to be appended
|
||||
* @param pos On input: an alignment field, if desired. On output: the
|
||||
* offsets of the alignment field
|
||||
* @return the value passed in as toAppendTo.
|
||||
*/
|
||||
public StringBuffer format(Vector3D vector, StringBuffer toAppendTo,
|
||||
FieldPosition pos) {
|
||||
|
||||
pos.setBeginIndex(0);
|
||||
pos.setEndIndex(0);
|
||||
|
||||
// format prefix
|
||||
toAppendTo.append(prefix);
|
||||
|
||||
// format components
|
||||
formatDouble(vector.getX(), format, toAppendTo, pos);
|
||||
toAppendTo.append(separator);
|
||||
formatDouble(vector.getY(), format, toAppendTo, pos);
|
||||
toAppendTo.append(separator);
|
||||
formatDouble(vector.getZ(), format, toAppendTo, pos);
|
||||
|
||||
// format suffix
|
||||
toAppendTo.append(suffix);
|
||||
|
||||
return toAppendTo;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a object to produce a string.
|
||||
* <p><code>obj</code> must be a {@link Vector3D} object. Any other type of
|
||||
* object will result in an {@link IllegalArgumentException} being thrown.</p>
|
||||
* @param obj the object to format.
|
||||
* @param toAppendTo where the text is to be appended
|
||||
* @param pos On input: an alignment field, if desired. On output: the
|
||||
* offsets of the alignment field
|
||||
* @return the value passed in as toAppendTo.
|
||||
* @see java.text.Format#format(java.lang.Object, java.lang.StringBuffer, java.text.FieldPosition)
|
||||
* @throws IllegalArgumentException is <code>obj</code> is not a valid type.
|
||||
*/
|
||||
public StringBuffer format(Object obj, StringBuffer toAppendTo,
|
||||
FieldPosition pos) {
|
||||
|
||||
if (obj instanceof Vector3D) {
|
||||
return format( (Vector3D)obj, toAppendTo, pos);
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Cannot format given Object as a Vector3D");
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a string to produce a {@link Vector3D} object.
|
||||
* @param source the string to parse
|
||||
* @return the parsed {@link Vector3D} object.
|
||||
* @exception ParseException if the beginning of the specified string
|
||||
* cannot be parsed.
|
||||
*/
|
||||
public Vector3D parse(String source) throws ParseException {
|
||||
ParsePosition parsePosition = new ParsePosition(0);
|
||||
Vector3D result = parse(source, parsePosition);
|
||||
if (parsePosition.getIndex() == 0) {
|
||||
throw MathRuntimeException.createParseException("unparseable 3D vector: \"{0}\"",
|
||||
new Object[] { source },
|
||||
parsePosition.getErrorIndex());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a string to produce a {@link Vector3D} object.
|
||||
* @param source the string to parse
|
||||
* @param pos input/ouput parsing parameter.
|
||||
* @return the parsed {@link Vector3D} object.
|
||||
*/
|
||||
public Vector3D parse(String source, ParsePosition pos) {
|
||||
int initialIndex = pos.getIndex();
|
||||
|
||||
// parse prefix
|
||||
parseAndIgnoreWhitespace(source, pos);
|
||||
if (!parseFixedstring(source, trimmedPrefix, pos)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// parse X component
|
||||
parseAndIgnoreWhitespace(source, pos);
|
||||
Number x = parseNumber(source, format, pos);
|
||||
if (x == null) {
|
||||
// invalid abscissa
|
||||
// set index back to initial, error index should already be set
|
||||
pos.setIndex(initialIndex);
|
||||
return null;
|
||||
}
|
||||
|
||||
// parse Y component
|
||||
parseAndIgnoreWhitespace(source, pos);
|
||||
if (!parseFixedstring(source, trimmedSeparator, pos)) {
|
||||
return null;
|
||||
}
|
||||
parseAndIgnoreWhitespace(source, pos);
|
||||
Number y = parseNumber(source, format, pos);
|
||||
if (y == null) {
|
||||
// invalid ordinate
|
||||
// set index back to initial, error index should already be set
|
||||
pos.setIndex(initialIndex);
|
||||
return null;
|
||||
}
|
||||
|
||||
// parse Z component
|
||||
parseAndIgnoreWhitespace(source, pos);
|
||||
if (!parseFixedstring(source, trimmedSeparator, pos)) {
|
||||
return null;
|
||||
}
|
||||
parseAndIgnoreWhitespace(source, pos);
|
||||
Number z = parseNumber(source, format, pos);
|
||||
if (z == null) {
|
||||
// invalid height
|
||||
// set index back to initial, error index should already be set
|
||||
pos.setIndex(initialIndex);
|
||||
return null;
|
||||
}
|
||||
|
||||
// parse suffix
|
||||
parseAndIgnoreWhitespace(source, pos);
|
||||
if (!parseFixedstring(source, trimmedSuffix, pos)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new Vector3D(x.doubleValue(), y.doubleValue(), z.doubleValue());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a string to produce a object.
|
||||
* @param source the string to parse
|
||||
* @param pos input/ouput parsing parameter.
|
||||
* @return the parsed object.
|
||||
* @see java.text.Format#parseObject(java.lang.String, java.text.ParsePosition)
|
||||
*/
|
||||
public Object parseObject(String source, ParsePosition pos) {
|
||||
return parse(source, pos);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,393 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.commons.math.linear;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Class transforming any matrix to bi-diagonal shape.
|
||||
* <p>Any m × n matrix A can be written as the product of three matrices:
|
||||
* A = U × B × V<sup>T</sup> with U an m × m orthogonal matrix,
|
||||
* B an m × n bi-diagonal matrix (lower diagonal if m < n, upper diagonal
|
||||
* otherwise), and V an n × n orthogonal matrix.</p>
|
||||
* <p>Transformation to bi-diagonal shape is often not a goal by itself, but it is
|
||||
* an intermediate step in more general decomposition algorithms like {@link
|
||||
* SingularValueDecomposition Singular Value Decomposition}. This class is therefore
|
||||
* intended for internal use by the library and is not public. As a consequence of
|
||||
* this explicitly limited scope, many methods directly returns references to
|
||||
* internal arrays, not copies.</p>
|
||||
* @version $Revision$ $Date$
|
||||
* @since 2.0
|
||||
*/
|
||||
class BiDiagonalTransformer implements Serializable {
|
||||
|
||||
/** Serializable version identifier. */
|
||||
private static final long serialVersionUID = 8935390784125343332L;
|
||||
|
||||
/** Householder vectors. */
|
||||
private final double householderVectors[][];
|
||||
|
||||
/** Main diagonal. */
|
||||
private final double[] main;
|
||||
|
||||
/** Secondary diagonal. */
|
||||
private final double[] secondary;
|
||||
|
||||
/** Cached value of U. */
|
||||
private RealMatrix cachedU;
|
||||
|
||||
/** Cached value of B. */
|
||||
private RealMatrix cachedB;
|
||||
|
||||
/** Cached value of V. */
|
||||
private RealMatrix cachedV;
|
||||
|
||||
/**
|
||||
* Build the transformation to bi-diagonal shape of a matrix.
|
||||
* @param matrix the matrix to transform.
|
||||
*/
|
||||
public BiDiagonalTransformer(RealMatrix matrix) {
|
||||
|
||||
final int m = matrix.getRowDimension();
|
||||
final int n = matrix.getColumnDimension();
|
||||
final int p = Math.min(m, n);
|
||||
householderVectors = matrix.getData();
|
||||
main = new double[p];
|
||||
secondary = new double[p - 1];
|
||||
cachedU = null;
|
||||
cachedB = null;
|
||||
cachedV = null;
|
||||
|
||||
// transform matrix
|
||||
if (m >= n) {
|
||||
transformToUpperBiDiagonal();
|
||||
} else {
|
||||
transformToLowerBiDiagonal();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the matrix U of the transform.
|
||||
* <p>U is an orthogonal matrix, i.e. its transpose is also its inverse.</p>
|
||||
* @return the U matrix
|
||||
*/
|
||||
public RealMatrix getU() {
|
||||
|
||||
if (cachedU == null) {
|
||||
|
||||
final int m = householderVectors.length;
|
||||
final int n = householderVectors[0].length;
|
||||
final int p = main.length;
|
||||
final int diagOffset = (m >= n) ? 0 : 1;
|
||||
final double[] diagonal = (m >= n) ? main : secondary;
|
||||
final double[][] uData = new double[m][m];
|
||||
|
||||
// fill up the part of the matrix not affected by Householder transforms
|
||||
for (int k = m - 1; k >= p; --k) {
|
||||
uData[k][k] = 1;
|
||||
}
|
||||
|
||||
// build up first part of the matrix by applying Householder transforms
|
||||
for (int k = p - 1; k >= diagOffset; --k) {
|
||||
final double[] hK = householderVectors[k];
|
||||
uData[k][k] = 1;
|
||||
if (hK[k - diagOffset] != 0.0) {
|
||||
for (int j = k; j < m; ++j) {
|
||||
double alpha = 0;
|
||||
for (int i = k; i < m; ++i) {
|
||||
alpha -= uData[i][j] * householderVectors[i][k - diagOffset];
|
||||
}
|
||||
alpha /= diagonal[k - diagOffset] * hK[k - diagOffset];
|
||||
|
||||
for (int i = k; i < m; ++i) {
|
||||
uData[i][j] -= alpha * householderVectors[i][k - diagOffset];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (diagOffset > 0) {
|
||||
uData[0][0] = 1;
|
||||
}
|
||||
|
||||
// cache the matrix for subsequent calls
|
||||
cachedU = new RealMatrixImpl(uData, false);
|
||||
|
||||
}
|
||||
|
||||
// return the cached matrix
|
||||
return cachedU;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the bi-diagonal matrix B of the transform.
|
||||
* @return the B matrix
|
||||
*/
|
||||
public RealMatrix getB() {
|
||||
|
||||
if (cachedB == null) {
|
||||
|
||||
final int m = householderVectors.length;
|
||||
final int n = householderVectors[0].length;
|
||||
double[][] bData = new double[m][n];
|
||||
for (int i = 0; i < main.length; ++i) {
|
||||
double[] bDataI = bData[i];
|
||||
bDataI[i] = main[i];
|
||||
if (m < n) {
|
||||
if (i > 0) {
|
||||
bDataI[i - 1] = secondary[i - 1];
|
||||
}
|
||||
} else {
|
||||
if (i < main.length - 1) {
|
||||
bDataI[i + 1] = secondary[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// cache the matrix for subsequent calls
|
||||
cachedB = new RealMatrixImpl(bData, false);
|
||||
|
||||
}
|
||||
|
||||
// return the cached matrix
|
||||
return cachedB;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the matrix V of the transform.
|
||||
* <p>V is an orthogonal matrix, i.e. its transpose is also its inverse.</p>
|
||||
* @return the V matrix
|
||||
*/
|
||||
public RealMatrix getV() {
|
||||
|
||||
if (cachedV == null) {
|
||||
|
||||
final int m = householderVectors.length;
|
||||
final int n = householderVectors[0].length;
|
||||
final int p = main.length;
|
||||
final int diagOffset = (m >= n) ? 1 : 0;
|
||||
final double[] diagonal = (m >= n) ? secondary : main;
|
||||
final double[][] vData = new double[n][n];
|
||||
|
||||
// fill up the part of the matrix not affected by Householder transforms
|
||||
for (int k = n - 1; k >= p; --k) {
|
||||
vData[k][k] = 1;
|
||||
}
|
||||
|
||||
// build up first part of the matrix by applying Householder transforms
|
||||
for (int k = p - 1; k >= diagOffset; --k) {
|
||||
final double[] hK = householderVectors[k - diagOffset];
|
||||
vData[k][k] = 1;
|
||||
if (hK[k] != 0.0) {
|
||||
for (int j = k; j < n; ++j) {
|
||||
double beta = 0;
|
||||
for (int i = k; i < n; ++i) {
|
||||
beta -= vData[i][j] * hK[i];
|
||||
}
|
||||
beta /= diagonal[k - diagOffset] * hK[k];
|
||||
|
||||
for (int i = k; i < n; ++i) {
|
||||
vData[i][j] -= beta * hK[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (diagOffset > 0) {
|
||||
vData[0][0] = 1;
|
||||
}
|
||||
|
||||
// cache the matrix for subsequent calls
|
||||
cachedV = new RealMatrixImpl(vData, false);
|
||||
|
||||
}
|
||||
|
||||
// return the cached matrix
|
||||
return cachedV;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Householder vectors of the transform.
|
||||
* <p>Note that since this class is only intended for internal use,
|
||||
* it returns directly a reference to its internal arrays, not a copy.</p>
|
||||
* @return the main diagonal elements of the B matrix
|
||||
*/
|
||||
double[][] getHouseholderVectorsRef() {
|
||||
return householderVectors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the main diagonal elements of the matrix B of the transform.
|
||||
* <p>Note that since this class is only intended for internal use,
|
||||
* it returns directly a reference to its internal arrays, not a copy.</p>
|
||||
* @return the main diagonal elements of the B matrix
|
||||
*/
|
||||
double[] getMainDiagonalRef() {
|
||||
return main;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the secondary diagonal elements of the matrix B of the transform.
|
||||
* <p>Note that since this class is only intended for internal use,
|
||||
* it returns directly a reference to its internal arrays, not a copy.</p>
|
||||
* @return the secondary diagonal elements of the B matrix
|
||||
*/
|
||||
double[] getSecondaryDiagonalRef() {
|
||||
return secondary;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the matrix is transformed to upper bi-diagonal.
|
||||
* @return true if the matrix is transformed to upper bi-diagonal
|
||||
*/
|
||||
boolean isUpperBiDiagonal() {
|
||||
return householderVectors.length >= householderVectors[0].length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform original matrix to upper bi-diagonal form.
|
||||
* <p>Transformation is done using alternate Householder transforms
|
||||
* on columns and rows.</p>
|
||||
*/
|
||||
private void transformToUpperBiDiagonal() {
|
||||
|
||||
final int m = householderVectors.length;
|
||||
final int n = householderVectors[0].length;
|
||||
for (int k = 0; k < n; k++) {
|
||||
|
||||
//zero-out a column
|
||||
double xNormSqr = 0;
|
||||
for (int i = k; i < m; ++i) {
|
||||
final double c = householderVectors[i][k];
|
||||
xNormSqr += c * c;
|
||||
}
|
||||
final double[] hK = householderVectors[k];
|
||||
final double a = (hK[k] > 0) ? -Math.sqrt(xNormSqr) : Math.sqrt(xNormSqr);
|
||||
main[k] = a;
|
||||
if (a != 0.0) {
|
||||
hK[k] -= a;
|
||||
for (int j = k + 1; j < n; ++j) {
|
||||
double alpha = 0;
|
||||
for (int i = k; i < m; ++i) {
|
||||
final double[] hI = householderVectors[i];
|
||||
alpha -= hI[j] * hI[k];
|
||||
}
|
||||
alpha /= a * householderVectors[k][k];
|
||||
for (int i = k; i < m; ++i) {
|
||||
final double[] hI = householderVectors[i];
|
||||
hI[j] -= alpha * hI[k];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (k < n - 1) {
|
||||
//zero-out a row
|
||||
xNormSqr = 0;
|
||||
for (int j = k + 1; j < n; ++j) {
|
||||
final double c = hK[j];
|
||||
xNormSqr += c * c;
|
||||
}
|
||||
final double b = (hK[k + 1] > 0) ? -Math.sqrt(xNormSqr) : Math.sqrt(xNormSqr);
|
||||
secondary[k] = b;
|
||||
if (b != 0.0) {
|
||||
hK[k + 1] -= b;
|
||||
for (int i = k + 1; i < m; ++i) {
|
||||
final double[] hI = householderVectors[i];
|
||||
double beta = 0;
|
||||
for (int j = k + 1; j < n; ++j) {
|
||||
beta -= hI[j] * hK[j];
|
||||
}
|
||||
beta /= b * hK[k + 1];
|
||||
for (int j = k + 1; j < n; ++j) {
|
||||
hI[j] -= beta * hK[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform original matrix to lower bi-diagonal form.
|
||||
* <p>Transformation is done using alternate Householder transforms
|
||||
* on rows and columns.</p>
|
||||
*/
|
||||
private void transformToLowerBiDiagonal() {
|
||||
|
||||
final int m = householderVectors.length;
|
||||
final int n = householderVectors[0].length;
|
||||
for (int k = 0; k < m; k++) {
|
||||
|
||||
//zero-out a row
|
||||
final double[] hK = householderVectors[k];
|
||||
double xNormSqr = 0;
|
||||
for (int j = k; j < n; ++j) {
|
||||
final double c = hK[j];
|
||||
xNormSqr += c * c;
|
||||
}
|
||||
final double a = (hK[k] > 0) ? -Math.sqrt(xNormSqr) : Math.sqrt(xNormSqr);
|
||||
main[k] = a;
|
||||
if (a != 0.0) {
|
||||
hK[k] -= a;
|
||||
for (int i = k + 1; i < m; ++i) {
|
||||
final double[] hI = householderVectors[i];
|
||||
double alpha = 0;
|
||||
for (int j = k; j < n; ++j) {
|
||||
alpha -= hI[j] * hK[j];
|
||||
}
|
||||
alpha /= a * householderVectors[k][k];
|
||||
for (int j = k; j < n; ++j) {
|
||||
hI[j] -= alpha * hK[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (k < m - 1) {
|
||||
//zero-out a column
|
||||
final double[] hKp1 = householderVectors[k + 1];
|
||||
xNormSqr = 0;
|
||||
for (int i = k + 1; i < m; ++i) {
|
||||
final double c = householderVectors[i][k];
|
||||
xNormSqr += c * c;
|
||||
}
|
||||
final double b = (hKp1[k] > 0) ? -Math.sqrt(xNormSqr) : Math.sqrt(xNormSqr);
|
||||
secondary[k] = b;
|
||||
if (b != 0.0) {
|
||||
hKp1[k] -= b;
|
||||
for (int j = k + 1; j < n; ++j) {
|
||||
double beta = 0;
|
||||
for (int i = k + 1; i < m; ++i) {
|
||||
final double[] hI = householderVectors[i];
|
||||
beta -= hI[j] * hI[k];
|
||||
}
|
||||
beta /= b * hKp1[k];
|
||||
for (int i = k + 1; i < m; ++i) {
|
||||
final double[] hI = householderVectors[i];
|
||||
hI[j] -= beta * hI[k];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load Diff
107
src/java/org/apache/commons/math/linear/DecompositionSolver.java
Normal file
107
src/java/org/apache/commons/math/linear/DecompositionSolver.java
Normal file
@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.commons.math.linear;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* A base interface to decomposition algorithms that can solve A × X = B.
|
||||
* <p>This interface is the common base of decomposition algorithms like
|
||||
* {@link QRDecomposition}, {@link LUDecomposition}, {@link
|
||||
* SingularValueDecomposition} or {@link EigenDecomposition}. All these
|
||||
* algorithms decompose an A matrix has a product of several specific matrices
|
||||
* from which they can solve A × X = B in least squares sense: they find X
|
||||
* such that ||A × X - B|| is minimal.</p>
|
||||
* <p>Some solvers like {@link LUDecomposition} can only find the solution for
|
||||
* square matrices and when the solution is an exact linear solution, i.e. when
|
||||
* ||A × X - B|| is exactly 0. Other solvers can also find solutions
|
||||
* with non-square matrix A and with non-null minimal norm. If an exact linear
|
||||
* solution exists it is also the minimal norm solution.</p>
|
||||
*
|
||||
* @version $Revision$ $Date$
|
||||
* @since 2.0
|
||||
*/
|
||||
public interface DecompositionSolver extends Serializable {
|
||||
|
||||
/**
|
||||
* Decompose a matrix.
|
||||
* @param matrix matrix to decompose
|
||||
* @exception InvalidMatrixException if matrix does not fulfill
|
||||
* the decomposition requirements (for example non-square matrix
|
||||
* for {@link LUDecomposition})
|
||||
*/
|
||||
void decompose(RealMatrix matrix)
|
||||
throws InvalidMatrixException;
|
||||
|
||||
/** Solve the linear equation A × X = B.
|
||||
* <p>The A matrix is implicit here. It <strong>must</strong> have
|
||||
* already been provided by a previous call to {@link #decompose(RealMatrix)}.</p>
|
||||
* @param b right-hand side of the equation A × X = B
|
||||
* @return a vector X that minimizes the two norm of A × X - B
|
||||
* @exception IllegalStateException if {@link #decompose(RealMatrix) decompose}
|
||||
* has not been called
|
||||
* @exception IllegalArgumentException if matrices dimensions don't match
|
||||
* @exception InvalidMatrixException if decomposed matrix is singular
|
||||
*/
|
||||
double[] solve(double[] b)
|
||||
throws IllegalStateException, IllegalArgumentException, InvalidMatrixException;
|
||||
|
||||
/** Solve the linear equation A × X = B.
|
||||
* <p>The A matrix is implicit here. It <strong>must</strong> have
|
||||
* already been provided by a previous call to {@link #decompose(RealMatrix)}.</p>
|
||||
* @param b right-hand side of the equation A × X = B
|
||||
* @return a vector X that minimizes the two norm of A × X - B
|
||||
* @exception IllegalStateException if {@link #decompose(RealMatrix) decompose}
|
||||
* has not been called
|
||||
* @exception IllegalArgumentException if matrices dimensions don't match
|
||||
* @exception InvalidMatrixException if decomposed matrix is singular
|
||||
*/
|
||||
RealVector solve(RealVector b)
|
||||
throws IllegalStateException, IllegalArgumentException, InvalidMatrixException;
|
||||
|
||||
/** Solve the linear equation A × X = B.
|
||||
* <p>The A matrix is implicit here. It <strong>must</strong> have
|
||||
* already been provided by a previous call to {@link #decompose(RealMatrix)}.</p>
|
||||
* @param b right-hand side of the equation A × X = B
|
||||
* @return a matrix X that minimizes the two norm of A × X - B
|
||||
* @exception IllegalStateException if {@link #decompose(RealMatrix) decompose}
|
||||
* has not been called
|
||||
* @exception IllegalArgumentException if matrices dimensions don't match
|
||||
* @exception InvalidMatrixException if decomposed matrix is singular
|
||||
*/
|
||||
RealMatrix solve(RealMatrix b)
|
||||
throws IllegalStateException, IllegalArgumentException, InvalidMatrixException;
|
||||
|
||||
/**
|
||||
* Check if the decomposed matrix is non-singular.
|
||||
* @return true if the decomposed matrix is non-singular
|
||||
* @exception IllegalStateException if {@link
|
||||
* DecompositionSolver#decompose(RealMatrix) decompose} has not been called
|
||||
*/
|
||||
boolean isNonSingular() throws IllegalStateException;
|
||||
|
||||
/** Get the inverse of the decomposed matrix.
|
||||
* @return inverse matrix
|
||||
* @exception IllegalStateException if {@link #decompose(RealMatrix) decompose}
|
||||
* has not been called
|
||||
* @throws InvalidMatrixException if decomposed matrix is singular
|
||||
*/
|
||||
RealMatrix getInverse()
|
||||
throws IllegalStateException, InvalidMatrixException;
|
||||
|
||||
}
|
123
src/java/org/apache/commons/math/linear/EigenDecomposition.java
Normal file
123
src/java/org/apache/commons/math/linear/EigenDecomposition.java
Normal file
@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.commons.math.linear;
|
||||
|
||||
/**
|
||||
* An interface to classes that implement an algorithm to calculate the
|
||||
* eigen decomposition of a real symmetric matrix.
|
||||
* <p>The eigen decomposition of matrix A is a set of two matrices:
|
||||
* V and D such that A = V × D × V<sup>T</sup>.
|
||||
* A, V and D are all m × m matrices.</p>
|
||||
* <p>This interface is similar in spirit to the <code>EigenvalueDecomposition</code>
|
||||
* class from the now defunct <a href="http://math.nist.gov/javanumerics/jama/">JAMA</a>
|
||||
* library, with the following changes:</p>
|
||||
* <ul>
|
||||
* <li><code>solve</code> methods have been added (in the superinterface),</li>
|
||||
* <li>a {@link DecompositionSolver#decompose(RealMatrix) decompose(RealMatrix)}
|
||||
* method has been added (in the superinterface),</li>
|
||||
* <li>a {@link DecompositionSolver#isNonSingular() isNonSingular} method has
|
||||
* been added (in the superinterface),</li>
|
||||
* <li>a {@link DecompositionSolver#getInverse() getInverse} method has been
|
||||
* added (in the superinterface),</li>
|
||||
* <li>a {@link #getVT() getVt} method has been added,</li>
|
||||
* <li>a {@link #getEigenvalue(int) getEigenvalue} method to pick up a single
|
||||
* eigenvalue has been added,</li>
|
||||
* <li>a {@link #getEigenvector(int) getEigenvector} method to pick up a single
|
||||
* eigenvector has been added,</li>
|
||||
* <li>the <code>getRealEigenvalues</code> method has been renamed as {@link
|
||||
* #getEigenValues() getEigenValues},</li>
|
||||
* <li>the <code>getImagEigenvalues</code> method has been removed</li>
|
||||
* </ul>
|
||||
* @see <a href="http://mathworld.wolfram.com/EigenDecomposition.html">MathWorld</a>
|
||||
* @see <a href="http://en.wikipedia.org/wiki/Eigendecomposition_of_a_matrix">Wikipedia</a>
|
||||
* @version $Revision$ $Date$
|
||||
* @since 2.0
|
||||
*/
|
||||
public interface EigenDecomposition extends DecompositionSolver {
|
||||
|
||||
/**
|
||||
* Returns the matrix V of the decomposition.
|
||||
* <p>V is an orthogonal matrix, i.e. its transpose is also its inverse.</p>
|
||||
* <p>The columns of V are the eigenvectors of the original matrix.</p>
|
||||
* @return the V matrix
|
||||
* @exception IllegalStateException if {@link
|
||||
* DecompositionSolver#decompose(RealMatrix) decompose} has not been called
|
||||
*/
|
||||
RealMatrix getV() throws IllegalStateException;
|
||||
|
||||
/**
|
||||
* Returns the diagonal matrix D of the decomposition.
|
||||
* <p>D is a diagonal matrix.</p>
|
||||
* <p>The values on the diagonal are the eigenvalues of the original matrix.</p>
|
||||
* @return the D matrix
|
||||
* @exception IllegalStateException if {@link
|
||||
* DecompositionSolver#decompose(RealMatrix) decompose} has not been called
|
||||
* @see #getEigenValues()
|
||||
*/
|
||||
RealMatrix getD() throws IllegalStateException;
|
||||
|
||||
/**
|
||||
* Returns the transpose of the matrix V of the decomposition.
|
||||
* <p>V is an orthogonal matrix, i.e. its transpose is also its inverse.</p>
|
||||
* <p>The columns of V are the eigenvectors of the original matrix.</p>
|
||||
* @return the transpose of the V matrix
|
||||
* @exception IllegalStateException if {@link
|
||||
* DecompositionSolver#decompose(RealMatrix) decompose} has not been called
|
||||
*/
|
||||
RealMatrix getVT() throws IllegalStateException;
|
||||
|
||||
/**
|
||||
* Returns a copy of the eigenvalues of the original matrix.
|
||||
* @return a copy of the eigenvalues of the original matrix
|
||||
* @exception IllegalStateException if {@link
|
||||
* DecompositionSolver#decompose(RealMatrix) decompose} has not been called
|
||||
* @see #getD()
|
||||
*/
|
||||
double[] getEigenvalues() throws IllegalStateException;
|
||||
|
||||
/**
|
||||
* Returns the i<sup>th</sup> eigenvalue of the original matrix.
|
||||
* @param i index of the eigenvalue (counting from 0)
|
||||
* @return i<sup>th</sup> eigenvalue of the original matrix
|
||||
* @exception IllegalStateException if {@link
|
||||
* DecompositionSolver#decompose(RealMatrix) decompose} has not been called
|
||||
* @exception ArrayIndexOutOfBoundsException if i is not
|
||||
* @see #getD()
|
||||
*/
|
||||
double getEigenvalue(int i) throws IllegalStateException;
|
||||
|
||||
/**
|
||||
* Returns a copy of the i<sup>th</sup> eigenvector of the original matrix.
|
||||
* @param i index of the eigenvector (counting from 0)
|
||||
* @return copy of the i<sup>th</sup> eigenvector of the original matrix
|
||||
* @exception IllegalStateException if {@link
|
||||
* DecompositionSolver#decompose(RealMatrix) decompose} has not been called
|
||||
* @see #getD()
|
||||
*/
|
||||
RealVector getEigenvector(int i) throws IllegalStateException;
|
||||
|
||||
/**
|
||||
* Return the determinant of the matrix
|
||||
* @return determinant of the matrix
|
||||
* @exception IllegalStateException if {@link
|
||||
* DecompositionSolver#decompose(RealMatrix) decompose} has not been called
|
||||
* @see #isNonSingular()
|
||||
*/
|
||||
double getDeterminant() throws IllegalStateException;
|
||||
|
||||
}
|
1804
src/java/org/apache/commons/math/linear/EigenDecompositionImpl.java
Normal file
1804
src/java/org/apache/commons/math/linear/EigenDecompositionImpl.java
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.commons.math.linear;
|
||||
|
||||
/** Class representing a union of Gershgorin circles.
|
||||
* <p>Gershgorin circles are bounding areas where eigenvalues must lie.
|
||||
* They are used as starting values for eigen decomposition algorithms.
|
||||
* In the real case, Gershgorin circles are simple intervals.</p>
|
||||
* @see EigenDecompositionImpl
|
||||
* @version $Revision$ $Date$
|
||||
* @since 2.0
|
||||
*/
|
||||
class GershgorinCirclesUnion implements Comparable<GershgorinCirclesUnion> {
|
||||
|
||||
/** Lower bound of the interval. */
|
||||
private double low;
|
||||
|
||||
/** Higher bound of the interval. */
|
||||
private double high;
|
||||
|
||||
/** Create a simple Gershgorin circle.
|
||||
* @param d diagonal element of the current row
|
||||
* @param sum sum of the absolute values of the off-diagonal elements
|
||||
* of the current row
|
||||
*/
|
||||
public GershgorinCirclesUnion(final double d, final double sum) {
|
||||
low = d - sum;
|
||||
high = d + sum;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the lower bound of the interval.
|
||||
* @return lower bound of the interval
|
||||
*/
|
||||
public double getLow() {
|
||||
return low;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the higher bound of the interval.
|
||||
* @return higher bound of the interval
|
||||
*/
|
||||
public double getHigh() {
|
||||
return high;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a Gershgorin circles union intersects instance.
|
||||
* @param other Gershgorin circles union to test against instance
|
||||
* @return true if the other Gershgorin circles union intersects instance
|
||||
*/
|
||||
public boolean intersects(final GershgorinCirclesUnion other) {
|
||||
return (other.low <= this.high) && (other.high >= this.low);
|
||||
}
|
||||
|
||||
/**
|
||||
* Swallow another Gershgorin circles union.
|
||||
* <p>Swallowing another Gershgorin circles union changes the
|
||||
* instance such that it contains everything that was formerly in
|
||||
* either circles union. It is mainly intended for circles unions
|
||||
* that {@link #intersects(GershgorinCirclesUnion) intersect}
|
||||
* each other beforehand.</p>
|
||||
* @param other Gershgorin circles union to swallow
|
||||
*/
|
||||
public void swallow(final GershgorinCirclesUnion other) {
|
||||
low = Math.min(low, other.low);
|
||||
high = Math.max(high, other.high);
|
||||
}
|
||||
|
||||
/** Compare another Gershgorin circles union in interval start order.
|
||||
* @param other Gershgorin circles union to compare to instance
|
||||
* @return a negative, zero or positive value depending on the other
|
||||
* union starting before, at same location or after instance
|
||||
*/
|
||||
public int compareTo(GershgorinCirclesUnion other) {
|
||||
return Double.compare(low, other.low);
|
||||
}
|
||||
|
||||
}
|
@ -17,30 +17,37 @@
|
||||
|
||||
package org.apache.commons.math.linear;
|
||||
|
||||
import org.apache.commons.math.MathRuntimeException;
|
||||
|
||||
/**
|
||||
* Thrown when a system attempts an operation on a matrix, and
|
||||
* that matrix does not satisfy the preconditions for the
|
||||
* aforementioned operation.
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
public class InvalidMatrixException extends RuntimeException {
|
||||
public class InvalidMatrixException extends MathRuntimeException {
|
||||
|
||||
/** Serializable version identifier */
|
||||
private static final long serialVersionUID = 5318837237354354107L;
|
||||
/** Serializable version identifier. */
|
||||
private static final long serialVersionUID = 1135533765052675495L;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
* Construct an exception with the given message.
|
||||
* @param pattern format specifier
|
||||
* @param arguments format arguments
|
||||
* @since 2.0
|
||||
*/
|
||||
public InvalidMatrixException() {
|
||||
this(null);
|
||||
public InvalidMatrixException(final String pattern, final Object[] arguments) {
|
||||
super(pattern, arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an exception with the given message.
|
||||
* @param message descriptive error message.
|
||||
* @param cause the exception or error that caused this exception
|
||||
* to be thrown.
|
||||
* @since 2.0
|
||||
*/
|
||||
public InvalidMatrixException(String message) {
|
||||
super(message);
|
||||
public InvalidMatrixException(final Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
}
|
||||
|
113
src/java/org/apache/commons/math/linear/LUDecomposition.java
Normal file
113
src/java/org/apache/commons/math/linear/LUDecomposition.java
Normal file
@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.commons.math.linear;
|
||||
|
||||
/**
|
||||
* An interface to classes that implement an algorithm to calculate the
|
||||
* LU-decomposition of a real matrix.
|
||||
* <p>The LU-decomposition of matrix A is a set of three matrices: P, L and U
|
||||
* such that P×A = L×U. P is a rows permutation matrix that is used
|
||||
* to rearrange the rows of A before so that it can be decomposed. L is a lower
|
||||
* triangular matrix with unit diagonal terms and U is an upper triangular matrix.</p>
|
||||
* <p>This interface is based on the class with similar name from the now defunct
|
||||
* <a href="http://math.nist.gov/javanumerics/jama/">JAMA</a> library, with the
|
||||
* following changes:</p>
|
||||
* <ul>
|
||||
* <li>several signatures have been added for the <code>solve</code> methods
|
||||
* (in the superinterface),</li>
|
||||
* <li>a {@link DecompositionSolver#decompose(RealMatrix) decompose(RealMatrix)}
|
||||
* method has been added (in the superinterface),</li>
|
||||
* <li>a {@link DecompositionSolver#isNonSingular() isNonSingular} method has
|
||||
* been added (in the superinterface),</li>
|
||||
* <li>a {@link DecompositionSolver#getInverse() getInverse} method has been
|
||||
* added (in the superinterface),</li>
|
||||
* <li>the <code>det</code> method has been renamed as {@link #getDeterminant() getDeterminant}.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @see <a href="http://mathworld.wolfram.com/LUDecomposition.html">MathWorld</a>
|
||||
* @see <a href="http://en.wikipedia.org/wiki/LU_decomposition">Wikipedia</a>
|
||||
* @version $Revision$ $Date$
|
||||
* @since 2.0
|
||||
*/
|
||||
public interface LUDecomposition extends DecompositionSolver {
|
||||
|
||||
/**
|
||||
* Computes a new
|
||||
* <a href="http://www.math.gatech.edu/~bourbaki/math2601/Web-notes/2num.pdf">
|
||||
* LU decomposition</a> for this matrix, storing the result for use by other methods.
|
||||
* <p>
|
||||
* <strong>Implementation Note</strong>:<br>
|
||||
* Uses <a href="http://www.damtp.cam.ac.uk/user/fdl/people/sd/lectures/nummeth98/linear.htm">
|
||||
* Crout's algorithm</a>, with partial pivoting.</p>
|
||||
* @param matrix The matrix to decompose.
|
||||
* @param singularityThreshold threshold (based on partial row norm)
|
||||
* under which a matrix is considered singular
|
||||
* @exception InvalidMatrixException if matrix is not square
|
||||
*/
|
||||
void decompose(RealMatrix matrix, double singularityThreshold);
|
||||
|
||||
/**
|
||||
* Returns the matrix L of the decomposition.
|
||||
* <p>L is an lower-triangular matrix</p>
|
||||
* @return the L matrix (or null if decomposed matrix is singular)
|
||||
* @exception IllegalStateException if {@link
|
||||
* DecompositionSolver#decompose(RealMatrix) decompose} has not been called
|
||||
*/
|
||||
RealMatrix getL() throws IllegalStateException;
|
||||
|
||||
/**
|
||||
* Returns the matrix U of the decomposition.
|
||||
* <p>U is an upper-triangular matrix</p>
|
||||
* @return the U matrix (or null if decomposed matrix is singular)
|
||||
* @exception IllegalStateException if {@link
|
||||
* DecompositionSolver#decompose(RealMatrix) decompose} has not been called
|
||||
*/
|
||||
RealMatrix getU() throws IllegalStateException;
|
||||
|
||||
/**
|
||||
* Returns the P rows permutation matrix.
|
||||
* <p>P is a sparse matrix with exactly one element set to 1.0 in
|
||||
* each row and each column, all other elements being set to 0.0.</p>
|
||||
* <p>The positions of the 1 elements are given by the {@link #getPivot()
|
||||
* pivot permutation vector}.</p>
|
||||
* @return the P rows permutation matrix (or null if decomposed matrix is singular)
|
||||
* @exception IllegalStateException if {@link
|
||||
* DecompositionSolver#decompose(RealMatrix) decompose} has not been called
|
||||
* @see #getPivot()
|
||||
*/
|
||||
RealMatrix getP() throws IllegalStateException;
|
||||
|
||||
/**
|
||||
* Returns the pivot permutation vector.
|
||||
* @return the pivot permutation vector
|
||||
* @exception IllegalStateException if {@link
|
||||
* DecompositionSolver#decompose(RealMatrix) decompose} has not been called
|
||||
* @see #getPermutation()
|
||||
*/
|
||||
int[] getPivot() throws IllegalStateException;
|
||||
|
||||
/**
|
||||
* Return the determinant of the matrix
|
||||
* @return determinant of the matrix
|
||||
* @exception IllegalStateException if {@link
|
||||
* DecompositionSolver#decompose(RealMatrix) decompose} has not been called
|
||||
* @see #isNonSingular()
|
||||
*/
|
||||
double getDeterminant() throws IllegalStateException;
|
||||
|
||||
}
|
440
src/java/org/apache/commons/math/linear/LUDecompositionImpl.java
Normal file
440
src/java/org/apache/commons/math/linear/LUDecompositionImpl.java
Normal file
@ -0,0 +1,440 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.commons.math.linear;
|
||||
|
||||
import org.apache.commons.math.MathRuntimeException;
|
||||
|
||||
/**
|
||||
* Calculates the LUP-decomposition of a square matrix.
|
||||
* <p>The LUP-decomposition of a matrix A consists of three matrices
|
||||
* L, U and P that satisfy: A = LUP, L is lower triangular, and U is
|
||||
* upper triangular and P is a permutation matrix. All matrices are
|
||||
* m×m.</p>
|
||||
* <p>As shown by the presence of the P matrix, this decomposition is
|
||||
* implemented using partial pivoting.</p>
|
||||
*
|
||||
* @version $Revision$ $Date$
|
||||
* @since 2.0
|
||||
*/
|
||||
public class LUDecompositionImpl implements LUDecomposition {
|
||||
|
||||
/** Serializable version identifier. */
|
||||
private static final long serialVersionUID = 3446121671437672843L;
|
||||
|
||||
/** Entries of LU decomposition. */
|
||||
private double lu[][];
|
||||
|
||||
/** Pivot permutation associated with LU decomposition */
|
||||
private int[] pivot;
|
||||
|
||||
/** Parity of the permutation associated with the LU decomposition */
|
||||
private int parity;
|
||||
|
||||
/** Singularity indicator. */
|
||||
private boolean singular;
|
||||
|
||||
/** Cached value of L. */
|
||||
private RealMatrix cachedL;
|
||||
|
||||
/** Cached value of U. */
|
||||
private RealMatrix cachedU;
|
||||
|
||||
/** Cached value of P. */
|
||||
private RealMatrix cachedP;
|
||||
|
||||
/** Default bound to determine effective singularity in LU decomposition */
|
||||
private static final double DEFAULT_TOO_SMALL = 10E-12;
|
||||
|
||||
/**
|
||||
* Build a new instance.
|
||||
* <p>Note that either {@link #decompose(RealMatrix)} or
|
||||
* {@link #decompose(RealMatrix, double)} <strong>must</strong> be called
|
||||
* before any of the {@link #getP()}, {@link #getPivot()}, {@link #getL()},
|
||||
* {@link #getU()}, {@link #getDeterminant()}, {@link #isNonSingular()},
|
||||
* {@link #solve(double[])}, {@link #solve(RealMatrix)}, {@link #solve(RealVector)}
|
||||
* or {@link #solve(RealVectorImpl)} methods can be called.</p>
|
||||
* @see #decompose(RealMatrix)
|
||||
* @see #decompose(RealMatrix, double)
|
||||
*/
|
||||
public LUDecompositionImpl() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the LU-decomposition of the given matrix.
|
||||
* <p>Calling this constructor is equivalent to first call the no-arguments
|
||||
* constructor and then call {@link #decompose(RealMatrix)}.</p>
|
||||
* @param matrix The matrix to decompose.
|
||||
* @exception InvalidMatrixException if matrix is not square
|
||||
*/
|
||||
public LUDecompositionImpl(RealMatrix matrix)
|
||||
throws InvalidMatrixException {
|
||||
decompose(matrix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the LU-decomposition of the given matrix.
|
||||
* <p>Calling this constructor is equivalent to first call the no-arguments
|
||||
* constructor and then call {@link #decompose(RealMatrix, double)}.</p>
|
||||
* @param matrix The matrix to decompose.
|
||||
* @param singularityThreshold threshold (based on partial row norm)
|
||||
* under which a matrix is considered singular
|
||||
* @exception InvalidMatrixException if matrix is not square
|
||||
*/
|
||||
public LUDecompositionImpl(RealMatrix matrix, double singularityThreshold)
|
||||
throws InvalidMatrixException {
|
||||
decompose(matrix, singularityThreshold);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public void decompose(RealMatrix matrix)
|
||||
throws InvalidMatrixException {
|
||||
decompose(matrix, DEFAULT_TOO_SMALL);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public void decompose(RealMatrix matrix, double singularityThreshold)
|
||||
throws InvalidMatrixException {
|
||||
if (!matrix.isSquare()) {
|
||||
throw new NonSquareMatrixException(matrix.getRowDimension(), matrix.getColumnDimension());
|
||||
}
|
||||
final int m = matrix.getColumnDimension();
|
||||
lu = matrix.getData();
|
||||
pivot = new int[m];
|
||||
cachedL = null;
|
||||
cachedU = null;
|
||||
cachedP = null;
|
||||
|
||||
// Initialize permutation array and parity
|
||||
for (int row = 0; row < m; row++) {
|
||||
pivot[row] = row;
|
||||
}
|
||||
parity = 1;
|
||||
singular = false;
|
||||
|
||||
// Loop over columns
|
||||
for (int col = 0; col < m; col++) {
|
||||
|
||||
double sum = 0;
|
||||
|
||||
// upper
|
||||
for (int row = 0; row < col; row++) {
|
||||
final double[] luRow = lu[row];
|
||||
sum = luRow[col];
|
||||
for (int i = 0; i < row; i++) {
|
||||
sum -= luRow[i] * lu[i][col];
|
||||
}
|
||||
luRow[col] = sum;
|
||||
}
|
||||
|
||||
// lower
|
||||
int max = col; // permutation row
|
||||
double largest = Double.NEGATIVE_INFINITY;
|
||||
for (int row = col; row < m; row++) {
|
||||
final double[] luRow = lu[row];
|
||||
sum = luRow[col];
|
||||
for (int i = 0; i < col; i++) {
|
||||
sum -= luRow[i] * lu[i][col];
|
||||
}
|
||||
luRow[col] = sum;
|
||||
|
||||
// maintain best permutation choice
|
||||
if (Math.abs(sum) > largest) {
|
||||
largest = Math.abs(sum);
|
||||
max = row;
|
||||
}
|
||||
}
|
||||
|
||||
// Singularity check
|
||||
if (Math.abs(lu[max][col]) < singularityThreshold) {
|
||||
singular = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// Pivot if necessary
|
||||
if (max != col) {
|
||||
double tmp = 0;
|
||||
for (int i = 0; i < m; i++) {
|
||||
tmp = lu[max][i];
|
||||
lu[max][i] = lu[col][i];
|
||||
lu[col][i] = tmp;
|
||||
}
|
||||
int temp = pivot[max];
|
||||
pivot[max] = pivot[col];
|
||||
pivot[col] = temp;
|
||||
parity = -parity;
|
||||
}
|
||||
|
||||
// Divide the lower elements by the "winning" diagonal elt.
|
||||
final double luDiag = lu[col][col];
|
||||
for (int row = col + 1; row < m; row++) {
|
||||
lu[row][col] /= luDiag;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public RealMatrix getL()
|
||||
throws IllegalStateException {
|
||||
checkDecomposed();
|
||||
if ((cachedL == null) && !singular) {
|
||||
final int m = pivot.length;
|
||||
final double[][] lData = new double[m][m];
|
||||
for (int i = 0; i < m; ++i) {
|
||||
System.arraycopy(lu[i], 0, lData[i], 0, i);
|
||||
lData[i][i] = 1.0;
|
||||
}
|
||||
cachedL = new RealMatrixImpl(lData, false);
|
||||
}
|
||||
return cachedL;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public RealMatrix getU()
|
||||
throws IllegalStateException {
|
||||
checkDecomposed();
|
||||
if ((cachedU == null) && !singular) {
|
||||
final int m = pivot.length;
|
||||
final double[][] uData = new double[m][m];
|
||||
for (int i = 0; i < m; ++i) {
|
||||
System.arraycopy(lu[i], i, uData[i], i, m - i);
|
||||
}
|
||||
cachedU = new RealMatrixImpl(uData, false);
|
||||
}
|
||||
return cachedU;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public RealMatrix getP()
|
||||
throws IllegalStateException {
|
||||
checkDecomposed();
|
||||
if ((cachedP == null) && !singular) {
|
||||
final int m = pivot.length;
|
||||
final double[][] pData = new double[m][m];
|
||||
for (int i = 0; i < m; ++i) {
|
||||
pData[i][pivot[i]] = 1.0;
|
||||
}
|
||||
cachedP = new RealMatrixImpl(pData, false);
|
||||
}
|
||||
return cachedP;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public int[] getPivot()
|
||||
throws IllegalStateException {
|
||||
checkDecomposed();
|
||||
return pivot.clone();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public boolean isNonSingular()
|
||||
throws IllegalStateException {
|
||||
checkDecomposed();
|
||||
return !singular;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public double getDeterminant()
|
||||
throws IllegalStateException {
|
||||
checkDecomposed();
|
||||
if (singular) {
|
||||
return 0;
|
||||
} else {
|
||||
final int m = pivot.length;
|
||||
double determinant = parity;
|
||||
for (int i = 0; i < m; i++) {
|
||||
determinant *= lu[i][i];
|
||||
}
|
||||
return determinant;
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public double[] solve(double[] b)
|
||||
throws IllegalStateException, IllegalArgumentException, InvalidMatrixException {
|
||||
|
||||
checkDecomposed();
|
||||
final int m = pivot.length;
|
||||
if (b.length != m) {
|
||||
throw new IllegalArgumentException("constant vector has wrong length");
|
||||
}
|
||||
if (singular) {
|
||||
throw new SingularMatrixException();
|
||||
}
|
||||
|
||||
final double[] bp = new double[m];
|
||||
|
||||
// Apply permutations to b
|
||||
for (int row = 0; row < m; row++) {
|
||||
bp[row] = b[pivot[row]];
|
||||
}
|
||||
|
||||
// Solve LY = b
|
||||
for (int col = 0; col < m; col++) {
|
||||
for (int i = col + 1; i < m; i++) {
|
||||
bp[i] -= bp[col] * lu[i][col];
|
||||
}
|
||||
}
|
||||
|
||||
// Solve UX = Y
|
||||
for (int col = m - 1; col >= 0; col--) {
|
||||
bp[col] /= lu[col][col];
|
||||
for (int i = 0; i < col; i++) {
|
||||
bp[i] -= bp[col] * lu[i][col];
|
||||
}
|
||||
}
|
||||
|
||||
return bp;
|
||||
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public RealVector solve(RealVector b)
|
||||
throws IllegalStateException, IllegalArgumentException, InvalidMatrixException {
|
||||
try {
|
||||
return solve((RealVectorImpl) b);
|
||||
} catch (ClassCastException cce) {
|
||||
|
||||
checkDecomposed();
|
||||
final int m = pivot.length;
|
||||
if (b.getDimension() != m) {
|
||||
throw new IllegalArgumentException("constant vector has wrong length");
|
||||
}
|
||||
if (singular) {
|
||||
throw new SingularMatrixException();
|
||||
}
|
||||
|
||||
final double[] bp = new double[m];
|
||||
|
||||
// Apply permutations to b
|
||||
for (int row = 0; row < m; row++) {
|
||||
bp[row] = b.getEntry(pivot[row]);
|
||||
}
|
||||
|
||||
// Solve LY = b
|
||||
for (int col = 0; col < m; col++) {
|
||||
for (int i = col + 1; i < m; i++) {
|
||||
bp[i] -= bp[col] * lu[i][col];
|
||||
}
|
||||
}
|
||||
|
||||
// Solve UX = Y
|
||||
for (int col = m - 1; col >= 0; col--) {
|
||||
bp[col] /= lu[col][col];
|
||||
for (int i = 0; i < col; i++) {
|
||||
bp[i] -= bp[col] * lu[i][col];
|
||||
}
|
||||
}
|
||||
|
||||
return new RealVectorImpl(bp, false);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/** Solve the linear equation A × X = B.
|
||||
* <p>The A matrix is implicit here. It is </p>
|
||||
* @param b right-hand side of the equation A × X = B
|
||||
* @return a vector X such that A × X = B
|
||||
* @exception IllegalStateException if {@link #decompose(RealMatrix) decompose}
|
||||
* has not been called
|
||||
* @exception IllegalArgumentException if matrices dimensions don't match
|
||||
* @exception InvalidMatrixException if decomposed matrix is singular
|
||||
*/
|
||||
public RealVectorImpl solve(RealVectorImpl b)
|
||||
throws IllegalStateException, IllegalArgumentException, InvalidMatrixException {
|
||||
return new RealVectorImpl(solve(b.getDataRef()), false);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public RealMatrix solve(RealMatrix b)
|
||||
throws IllegalStateException, IllegalArgumentException, InvalidMatrixException {
|
||||
|
||||
checkDecomposed();
|
||||
final int m = pivot.length;
|
||||
if (b.getRowDimension() != m) {
|
||||
throw new IllegalArgumentException("Incorrect row dimension");
|
||||
}
|
||||
if (singular) {
|
||||
throw new SingularMatrixException();
|
||||
}
|
||||
|
||||
final int nColB = b.getColumnDimension();
|
||||
|
||||
// Apply permutations to b
|
||||
final double[][] bp = new double[m][nColB];
|
||||
for (int row = 0; row < m; row++) {
|
||||
final double[] bpRow = bp[row];
|
||||
final int pRow = pivot[row];
|
||||
for (int col = 0; col < nColB; col++) {
|
||||
bpRow[col] = b.getEntry(pRow, col);
|
||||
}
|
||||
}
|
||||
|
||||
// Solve LY = b
|
||||
for (int col = 0; col < m; col++) {
|
||||
final double[] bpCol = bp[col];
|
||||
for (int i = col + 1; i < m; i++) {
|
||||
final double[] bpI = bp[i];
|
||||
final double luICol = lu[i][col];
|
||||
for (int j = 0; j < nColB; j++) {
|
||||
bpI[j] -= bpCol[j] * luICol;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Solve UX = Y
|
||||
for (int col = m - 1; col >= 0; col--) {
|
||||
final double[] bpCol = bp[col];
|
||||
final double luDiag = lu[col][col];
|
||||
for (int j = 0; j < nColB; j++) {
|
||||
bpCol[j] /= luDiag;
|
||||
}
|
||||
for (int i = 0; i < col; i++) {
|
||||
final double[] bpI = bp[i];
|
||||
final double luICol = lu[i][col];
|
||||
for (int j = 0; j < nColB; j++) {
|
||||
bpI[j] -= bpCol[j] * luICol;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new RealMatrixImpl(bp, false);
|
||||
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public RealMatrix getInverse()
|
||||
throws IllegalStateException, InvalidMatrixException {
|
||||
checkDecomposed();
|
||||
return solve(MatrixUtils.createRealIdentityMatrix(pivot.length));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if either {@link #decompose(RealMatrix)} or {@link
|
||||
* #decompose(RealMatrix, double) has been called.
|
||||
* @exception IllegalStateException if {@link #decompose(RealMatrix) decompose}
|
||||
* has not been called
|
||||
*/
|
||||
private void checkDecomposed()
|
||||
throws IllegalStateException {
|
||||
if (lu == null) {
|
||||
throw MathRuntimeException.createIllegalStateException("no matrix have been decomposed yet", null);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -17,30 +17,25 @@
|
||||
|
||||
package org.apache.commons.math.linear;
|
||||
|
||||
import org.apache.commons.math.MathRuntimeException;
|
||||
|
||||
/**
|
||||
* Thrown when an operation addresses a matrix coordinate (row,col)
|
||||
* Thrown when an operation addresses a matrix coordinate (row, col)
|
||||
* which is outside of the dimensions of a matrix.
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
public class MatrixIndexException extends RuntimeException {
|
||||
public class MatrixIndexException extends MathRuntimeException {
|
||||
|
||||
/** Serializable version identifier */
|
||||
private static final long serialVersionUID = -1341109412864309526L;
|
||||
private static final long serialVersionUID = -2382324504109300625L;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
* @deprecated as of 1.2 replaced by #MatrixIndexException(String)
|
||||
* Constructs a new instance with specified formatted detail message.
|
||||
* @param pattern format specifier
|
||||
* @param arguments format arguments
|
||||
*/
|
||||
public MatrixIndexException() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an exception with the given message and root cause.
|
||||
* @param message descriptive error message.
|
||||
*/
|
||||
public MatrixIndexException(String message) {
|
||||
super(message);
|
||||
public MatrixIndexException(final String pattern, final Object[] arguments) {
|
||||
super(pattern, arguments);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -18,6 +18,7 @@
|
||||
package org.apache.commons.math.linear;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* A collection of static methods that operate on or return matrices.
|
||||
@ -41,12 +42,33 @@ public class MatrixUtils {
|
||||
* @return RealMatrix containing the values of the array
|
||||
* @throws IllegalArgumentException if <code>data</code> is not rectangular
|
||||
* (not all rows have the same length) or empty
|
||||
* @throws NullPointerException if data is null
|
||||
* @throws NullPointerException if <code>data</code> is null
|
||||
* @see #createRealMatrix(double[][], boolean)
|
||||
*/
|
||||
public static RealMatrix createRealMatrix(double[][] data) {
|
||||
return new RealMatrixImpl(data);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a {@link RealMatrix} whose entries are the the values in the
|
||||
* the input array.
|
||||
* <p>If an array is built specially in order to be embedded in a
|
||||
* RealMatrix and not used directly, the <code>copyArray</code> may be
|
||||
* set to <code>false</code. This will prevent the copying and improve
|
||||
* performance as no new array will be built and no data will be copied.</p>
|
||||
* @param data data for new matrix
|
||||
* @param copyArray if true, the input array will be copied, otherwise
|
||||
* it will be referenced
|
||||
* @return RealMatrix containing the values of the array
|
||||
* @throws IllegalArgumentException if <code>data</code> is not rectangular
|
||||
* (not all rows have the same length) or empty
|
||||
* @throws NullPointerException if <code>data</code> is null
|
||||
* @see #createRealMatrix(double[][])
|
||||
*/
|
||||
public static RealMatrix createRealMatrix(double[][] data, boolean copyArray) {
|
||||
return new RealMatrixImpl(data, copyArray);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>dimension x dimension</code> identity matrix.
|
||||
*
|
||||
@ -56,14 +78,11 @@ public class MatrixUtils {
|
||||
* @since 1.1
|
||||
*/
|
||||
public static RealMatrix createRealIdentityMatrix(int dimension) {
|
||||
RealMatrixImpl out = new RealMatrixImpl(dimension, dimension);
|
||||
double[][] d = out.getDataRef();
|
||||
double[][] d = new double[dimension][dimension];
|
||||
for (int row = 0; row < dimension; row++) {
|
||||
for (int col = 0; col < dimension; col++) {
|
||||
d[row][col] = row == col ? 1d : 0d;
|
||||
}
|
||||
d[row][row] = 1d;
|
||||
}
|
||||
return out;
|
||||
return new RealMatrixImpl(d, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -93,7 +112,27 @@ public class MatrixUtils {
|
||||
public static BigMatrix createBigMatrix(BigDecimal[][] data) {
|
||||
return new BigMatrixImpl(data);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a {@link BigMatrix} whose entries are the the values in the
|
||||
* the input array.
|
||||
* <p>If an array is built specially in order to be embedded in a
|
||||
* BigMatrix and not used directly, the <code>copyArray</code> may be
|
||||
* set to <code>false</code. This will prevent the copying and improve
|
||||
* performance as no new array will be built and no data will be copied.</p>
|
||||
* @param data data for new matrix
|
||||
* @param copyArray if true, the input array will be copied, otherwise
|
||||
* it will be referenced
|
||||
* @return BigMatrix containing the values of the array
|
||||
* @throws IllegalArgumentException if <code>data</code> is not rectangular
|
||||
* (not all rows have the same length) or empty
|
||||
* @throws NullPointerException if <code>data</code> is null
|
||||
* @see #createRealMatrix(double[][])
|
||||
*/
|
||||
public static BigMatrix createBigMatrix(BigDecimal[][] data, boolean copyArray) {
|
||||
return new BigMatrixImpl(data, copyArray);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link BigMatrix} whose entries are the the values in the
|
||||
* the input array. The input array is copied, not referenced.
|
||||
@ -108,6 +147,18 @@ public class MatrixUtils {
|
||||
return new BigMatrixImpl(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link RealVector} using the data from the input array.
|
||||
*
|
||||
* @param data the input data
|
||||
* @return a data.length RealVector
|
||||
* @throws IllegalArgumentException if <code>data</code> is empty
|
||||
* @throws NullPointerException if <code>data</code>is null
|
||||
*/
|
||||
public static RealVector createRealVector(double[] data) {
|
||||
return new RealVectorImpl(data, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a row {@link RealMatrix} using the data from the input
|
||||
* array.
|
||||
@ -118,10 +169,10 @@ public class MatrixUtils {
|
||||
* @throws NullPointerException if <code>rowData</code>is null
|
||||
*/
|
||||
public static RealMatrix createRowRealMatrix(double[] rowData) {
|
||||
int nCols = rowData.length;
|
||||
double[][] data = new double[1][nCols];
|
||||
final int nCols = rowData.length;
|
||||
final double[][] data = new double[1][nCols];
|
||||
System.arraycopy(rowData, 0, data[0], 0, nCols);
|
||||
return new RealMatrixImpl(data);
|
||||
return new RealMatrixImpl(data, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -134,10 +185,12 @@ public class MatrixUtils {
|
||||
* @throws NullPointerException if <code>rowData</code>is null
|
||||
*/
|
||||
public static BigMatrix createRowBigMatrix(double[] rowData) {
|
||||
int nCols = rowData.length;
|
||||
double[][] data = new double[1][nCols];
|
||||
System.arraycopy(rowData, 0, data[0], 0, nCols);
|
||||
return new BigMatrixImpl(data);
|
||||
final int nCols = rowData.length;
|
||||
final BigDecimal[][] data = new BigDecimal[1][nCols];
|
||||
for (int i = 0; i < nCols; ++i) {
|
||||
data[0][i] = new BigDecimal(rowData[i]);
|
||||
}
|
||||
return new BigMatrixImpl(data, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -150,10 +203,10 @@ public class MatrixUtils {
|
||||
* @throws NullPointerException if <code>rowData</code>is null
|
||||
*/
|
||||
public static BigMatrix createRowBigMatrix(BigDecimal[] rowData) {
|
||||
int nCols = rowData.length;
|
||||
BigDecimal[][] data = new BigDecimal[1][nCols];
|
||||
final int nCols = rowData.length;
|
||||
final BigDecimal[][] data = new BigDecimal[1][nCols];
|
||||
System.arraycopy(rowData, 0, data[0], 0, nCols);
|
||||
return new BigMatrixImpl(data);
|
||||
return new BigMatrixImpl(data, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -166,10 +219,12 @@ public class MatrixUtils {
|
||||
* @throws NullPointerException if <code>rowData</code>is null
|
||||
*/
|
||||
public static BigMatrix createRowBigMatrix(String[] rowData) {
|
||||
int nCols = rowData.length;
|
||||
String[][] data = new String[1][nCols];
|
||||
System.arraycopy(rowData, 0, data[0], 0, nCols);
|
||||
return new BigMatrixImpl(data);
|
||||
final int nCols = rowData.length;
|
||||
final BigDecimal[][] data = new BigDecimal[1][nCols];
|
||||
for (int i = 0; i < nCols; ++i) {
|
||||
data[0][i] = new BigDecimal(rowData[i]);
|
||||
}
|
||||
return new BigMatrixImpl(data, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -182,12 +237,12 @@ public class MatrixUtils {
|
||||
* @throws NullPointerException if <code>columnData</code>is null
|
||||
*/
|
||||
public static RealMatrix createColumnRealMatrix(double[] columnData) {
|
||||
int nRows = columnData.length;
|
||||
double[][] data = new double[nRows][1];
|
||||
final int nRows = columnData.length;
|
||||
final double[][] data = new double[nRows][1];
|
||||
for (int row = 0; row < nRows; row++) {
|
||||
data[row][0] = columnData[row];
|
||||
}
|
||||
return new RealMatrixImpl(data);
|
||||
return new RealMatrixImpl(data, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -200,12 +255,12 @@ public class MatrixUtils {
|
||||
* @throws NullPointerException if <code>columnData</code>is null
|
||||
*/
|
||||
public static BigMatrix createColumnBigMatrix(double[] columnData) {
|
||||
int nRows = columnData.length;
|
||||
double[][] data = new double[nRows][1];
|
||||
final int nRows = columnData.length;
|
||||
final BigDecimal[][] data = new BigDecimal[nRows][1];
|
||||
for (int row = 0; row < nRows; row++) {
|
||||
data[row][0] = columnData[row];
|
||||
data[row][0] = new BigDecimal(columnData[row]);
|
||||
}
|
||||
return new BigMatrixImpl(data);
|
||||
return new BigMatrixImpl(data, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -218,12 +273,12 @@ public class MatrixUtils {
|
||||
* @throws NullPointerException if <code>columnData</code>is null
|
||||
*/
|
||||
public static BigMatrix createColumnBigMatrix(BigDecimal[] columnData) {
|
||||
int nRows = columnData.length;
|
||||
BigDecimal[][] data = new BigDecimal[nRows][1];
|
||||
final int nRows = columnData.length;
|
||||
final BigDecimal[][] data = new BigDecimal[nRows][1];
|
||||
for (int row = 0; row < nRows; row++) {
|
||||
data[row][0] = columnData[row];
|
||||
}
|
||||
return new BigMatrixImpl(data);
|
||||
return new BigMatrixImpl(data, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -237,11 +292,11 @@ public class MatrixUtils {
|
||||
*/
|
||||
public static BigMatrix createColumnBigMatrix(String[] columnData) {
|
||||
int nRows = columnData.length;
|
||||
String[][] data = new String[nRows][1];
|
||||
final BigDecimal[][] data = new BigDecimal[nRows][1];
|
||||
for (int row = 0; row < nRows; row++) {
|
||||
data[row][0] = columnData[row];
|
||||
data[row][0] = new BigDecimal(columnData[row]);
|
||||
}
|
||||
return new BigMatrixImpl(data);
|
||||
return new BigMatrixImpl(data, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -253,14 +308,13 @@ public class MatrixUtils {
|
||||
* @since 1.1
|
||||
*/
|
||||
public static BigMatrix createBigIdentityMatrix(int dimension) {
|
||||
BigMatrixImpl out = new BigMatrixImpl(dimension, dimension);
|
||||
BigDecimal[][] d = out.getDataRef();
|
||||
final BigDecimal[][] d = new BigDecimal[dimension][dimension];
|
||||
for (int row = 0; row < dimension; row++) {
|
||||
for (int col = 0; col < dimension; col++) {
|
||||
d[row][col] = row == col ? BigMatrixImpl.ONE : BigMatrixImpl.ZERO;
|
||||
}
|
||||
final BigDecimal[] dRow = d[row];
|
||||
Arrays.fill(dRow, BigMatrixImpl.ZERO);
|
||||
dRow[row] = BigMatrixImpl.ONE;
|
||||
}
|
||||
return out;
|
||||
return new BigMatrixImpl(d, false);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -14,42 +14,27 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.commons.math.stat.inference;
|
||||
|
||||
package org.apache.commons.math.linear;
|
||||
|
||||
/**
|
||||
* A concrete inference test factory. This is the default factory used by
|
||||
* Commons-Math.
|
||||
*
|
||||
* @deprecated as of 1.2, pluggability of test instances is now provided through
|
||||
* constructors and setters.
|
||||
* @since 1.1
|
||||
* Thrown when an operation defined only for square matrices is applied to non-square ones.
|
||||
* @version $Revision$ $Date$
|
||||
* @since 2.0
|
||||
*/
|
||||
public class TestFactoryImpl extends TestFactory {
|
||||
public class NonSquareMatrixException extends InvalidMatrixException {
|
||||
|
||||
/** Serializable version identifier. */
|
||||
private static final long serialVersionUID = 8996207526636673730L;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
* Construct an exception with the given message.
|
||||
* @param rows number of rows of the faulty matrix
|
||||
* @param columns number of columns of the faulty matrix
|
||||
*/
|
||||
public TestFactoryImpl() {
|
||||
super();
|
||||
public NonSquareMatrixException(final int rows, final int columns) {
|
||||
super("a {0}x{1} matrix was provided instead of a square matrix",
|
||||
new Object[] { rows, columns });
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a TTest instance.
|
||||
*
|
||||
* @return a new TTest instance
|
||||
*/
|
||||
public TTest createTTest() {
|
||||
return new TTestImpl();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a ChiSquareTest instance.
|
||||
*
|
||||
* @return a new ChiSquareTest instance
|
||||
*/
|
||||
public ChiSquareTest createChiSquareTest() {
|
||||
return new ChiSquareTestImpl();
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -18,27 +18,65 @@
|
||||
package org.apache.commons.math.linear;
|
||||
|
||||
/**
|
||||
* An interface to classes that implement a algorithm to calculate the
|
||||
* An interface to classes that implement an algorithm to calculate the
|
||||
* QR-decomposition of a real matrix.
|
||||
* <p>This interface is based on the class with similar name from the now defunct
|
||||
* <a href="http://math.nist.gov/javanumerics/jama/">JAMA</a> library, with the
|
||||
* following changes:</p>
|
||||
* <ul>
|
||||
* <li>several signatures have been added for the <code>solve</code> methods
|
||||
* (in the superinterface),</li>
|
||||
* <li>a {@link DecompositionSolver#decompose(RealMatrix) decompose(RealMatrix)}
|
||||
* method has been added (in the superinterface),</li>
|
||||
* <li>a {@link DecompositionSolver#getInverse() getInverse} method has been
|
||||
* added (in the superinterface),</li>
|
||||
* <li>the <code>isFullRank</code> method has been replaced by the {@link
|
||||
* DecompositionSolver#isNonSingular() isNonSingular} method in the superinterface.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @see <a href="http://mathworld.wolfram.com/QRDecomposition.html">MathWorld</a>
|
||||
* @see <a href="http://en.wikipedia.org/wiki/QR_decomposition">Wikipedia</a>
|
||||
* @version $Revision$ $Date$
|
||||
* @since 1.2
|
||||
*/
|
||||
public interface QRDecomposition {
|
||||
public interface QRDecomposition extends DecompositionSolver {
|
||||
|
||||
/**
|
||||
* Returns the matrix R of the decomposition.
|
||||
*
|
||||
* <p>R is an upper-triangular matrix</p>
|
||||
* @return the R matrix
|
||||
* @exception IllegalStateException if {@link
|
||||
* DecompositionSolver#decompose(RealMatrix) decompose} has not been called
|
||||
*/
|
||||
public abstract RealMatrix getR();
|
||||
RealMatrix getR() throws IllegalStateException;
|
||||
|
||||
/**
|
||||
* Returns the matrix Q of the decomposition.
|
||||
*
|
||||
* <p>Q is an orthogonal matrix</p>
|
||||
* @return the Q matrix
|
||||
* @exception IllegalStateException if {@link
|
||||
* DecompositionSolver#decompose(RealMatrix) decompose} has not been called
|
||||
*/
|
||||
public abstract RealMatrix getQ();
|
||||
RealMatrix getQ() throws IllegalStateException;
|
||||
|
||||
/**
|
||||
* Returns the transpose of the matrix Q of the decomposition.
|
||||
* <p>Q is an orthogonal matrix</p>
|
||||
* @return the Q matrix
|
||||
* @exception IllegalStateException if {@link
|
||||
* DecompositionSolver#decompose(RealMatrix) decompose} has not been called
|
||||
*/
|
||||
RealMatrix getQT() throws IllegalStateException;
|
||||
|
||||
/**
|
||||
* Returns the Householder reflector vectors.
|
||||
* <p>H is a lower trapezoidal matrix whose columns represent
|
||||
* each successive Householder reflector vector. This matrix is used
|
||||
* to compute Q.</p>
|
||||
* @return a matrix containing the Householder reflector vectors
|
||||
* @exception IllegalStateException if {@link
|
||||
* DecompositionSolver#decompose(RealMatrix) decompose} has not been called
|
||||
*/
|
||||
RealMatrix getH() throws IllegalStateException;
|
||||
|
||||
}
|
||||
|
@ -17,56 +17,85 @@
|
||||
|
||||
package org.apache.commons.math.linear;
|
||||
|
||||
import org.apache.commons.math.MathRuntimeException;
|
||||
|
||||
/**
|
||||
* Calculates the QR-decomposition of a matrix. In the QR-decomposition of
|
||||
* a matrix A consists of two matrices Q and R that satisfy: A = QR, Q is
|
||||
* orthogonal (Q<sup>T</sup>Q = I), and R is upper triangular. If A is
|
||||
* m×n, Q is m×m and R m×n.
|
||||
* <p>
|
||||
* Implemented using Householder reflectors.</p>
|
||||
* Calculates the QR-decomposition of a matrix.
|
||||
* <p>The QR-decomposition of a matrix A consists of two matrices Q and R
|
||||
* that satisfy: A = QR, Q is orthogonal (Q<sup>T</sup>Q = I), and R is
|
||||
* upper triangular. If A is m×n, Q is m×m and R m×n.</p>
|
||||
* <p>This class compute the decomposition using Householder reflectors.</p>
|
||||
* <p>For efficiency purposes, the decomposition in packed form is transposed.
|
||||
* This allows inner loop to iterate inside rows, which is much more cache-efficient
|
||||
* in Java.</p>
|
||||
*
|
||||
* @see <a href="http://mathworld.wolfram.com/QRDecomposition.html">MathWorld</a>
|
||||
* @see <a href="http://en.wikipedia.org/wiki/QR_decomposition">Wikipedia</a>
|
||||
*
|
||||
*
|
||||
* @version $Revision$ $Date$
|
||||
* @since 1.2
|
||||
*/
|
||||
public class QRDecompositionImpl implements QRDecomposition {
|
||||
|
||||
/**
|
||||
* A packed representation of the QR decomposition. The elements above the
|
||||
* diagonal are the elements of R, and the columns of the lower triangle
|
||||
* are the Householder reflector vectors of which an explicit form of Q can
|
||||
* be calculated.
|
||||
*/
|
||||
private double[][] qr;
|
||||
/** Serializable version identifier. */
|
||||
private static final long serialVersionUID = -5179446891802932307L;
|
||||
|
||||
/**
|
||||
* The diagonal elements of R.
|
||||
* A packed TRANSPOSED representation of the QR decomposition.
|
||||
* <p>The elements BELOW the diagonal are the elements of the UPPER triangular
|
||||
* matrix R, and the rows ABOVE the diagonal are the Householder reflector vectors
|
||||
* from which an explicit form of Q can be recomputed if desired.</p>
|
||||
*/
|
||||
private double[][] qrt;
|
||||
|
||||
/** The diagonal elements of R. */
|
||||
private double[] rDiag;
|
||||
|
||||
/**
|
||||
* The row dimension of the given matrix. The size of Q will be m x m, the
|
||||
* size of R will be m x n.
|
||||
*/
|
||||
private int m;
|
||||
/** Cached value of Q. */
|
||||
private RealMatrix cachedQ;
|
||||
|
||||
/** Cached value of QT. */
|
||||
private RealMatrix cachedQT;
|
||||
|
||||
/** Cached value of R. */
|
||||
private RealMatrix cachedR;
|
||||
|
||||
/** Cached value of H. */
|
||||
private RealMatrix cachedH;
|
||||
|
||||
/**
|
||||
* The column dimension of the given matrix. The size of R will be m x n.
|
||||
* Build a new instance.
|
||||
* <p>Note that {@link #decompose(RealMatrix)} <strong>must</strong> be called
|
||||
* before any of the {@link #getQ()}, {@link #getR()}, {@link #getH()},
|
||||
* {@link #isFullRank()}, {@link #solve(double[])}, {@link #solve(RealMatrix)},
|
||||
* {@link #solve(RealVector)} or {@link #solve(RealVectorImpl)} methods can be
|
||||
* called.</p>
|
||||
* @see #decompose(RealMatrix)
|
||||
*/
|
||||
private int n;
|
||||
public QRDecompositionImpl() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the QR decomposition of the given matrix.
|
||||
*
|
||||
* Calculates the QR-decomposition of the given matrix.
|
||||
* <p>Calling this constructor is equivalent to first call the no-arguments
|
||||
* constructor and then call {@link #decompose(RealMatrix)}.</p>
|
||||
* @param matrix The matrix to decompose.
|
||||
*/
|
||||
public QRDecompositionImpl(RealMatrix matrix) {
|
||||
m = matrix.getRowDimension();
|
||||
n = matrix.getColumnDimension();
|
||||
qr = matrix.getData();
|
||||
decompose(matrix);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public void decompose(RealMatrix matrix) {
|
||||
|
||||
final int m = matrix.getRowDimension();
|
||||
final int n = matrix.getColumnDimension();
|
||||
qrt = matrix.transpose().getData();
|
||||
rDiag = new double[n];
|
||||
cachedQ = null;
|
||||
cachedQT = null;
|
||||
cachedR = null;
|
||||
cachedH = null;
|
||||
|
||||
/*
|
||||
* The QR decomposition of a matrix A is calculated using Householder
|
||||
@ -74,6 +103,9 @@ public class QRDecompositionImpl implements QRDecomposition {
|
||||
* A(minor,minor) of A:
|
||||
*/
|
||||
for (int minor = 0; minor < Math.min(m, n); minor++) {
|
||||
|
||||
final double[] qrtMinor = qrt[minor];
|
||||
|
||||
/*
|
||||
* Let x be the first column of the minor, and a^2 = |x|^2.
|
||||
* x will be in the positions qr[minor][minor] through qr[m][minor].
|
||||
@ -83,10 +115,10 @@ public class QRDecompositionImpl implements QRDecomposition {
|
||||
*/
|
||||
double xNormSqr = 0;
|
||||
for (int row = minor; row < m; row++) {
|
||||
xNormSqr += qr[row][minor]*qr[row][minor];
|
||||
final double c = qrtMinor[row];
|
||||
xNormSqr += c * c;
|
||||
}
|
||||
double a = Math.sqrt(xNormSqr);
|
||||
if (qr[minor][minor] > 0) a = -a;
|
||||
final double a = (qrtMinor[minor] > 0) ? -Math.sqrt(xNormSqr) : Math.sqrt(xNormSqr);
|
||||
rDiag[minor] = a;
|
||||
|
||||
if (a != 0.0) {
|
||||
@ -99,7 +131,7 @@ public class QRDecompositionImpl implements QRDecomposition {
|
||||
* Here <x, e> is now qr[minor][minor].
|
||||
* v = x-ae is stored in the column at qr:
|
||||
*/
|
||||
qr[minor][minor] -= a; // now |v|^2 = -2a*(qr[minor][minor])
|
||||
qrtMinor[minor] -= a; // now |v|^2 = -2a*(qr[minor][minor])
|
||||
|
||||
/*
|
||||
* Transform the rest of the columns of the minor:
|
||||
@ -108,85 +140,313 @@ public class QRDecompositionImpl implements QRDecomposition {
|
||||
* Hx = (I-2vv'/|v|^2)x = x-2vv'x/|v|^2 = x - 2<x,v>/|v|^2 v.
|
||||
* Therefore the transformation is easily calculated by
|
||||
* subtracting the column vector (2<x,v>/|v|^2)v from x.
|
||||
*
|
||||
*
|
||||
* Let 2<x,v>/|v|^2 = alpha. From above we have
|
||||
* |v|^2 = -2a*(qr[minor][minor]), so
|
||||
* alpha = -<x,v>/(a*qr[minor][minor])
|
||||
*/
|
||||
for (int col = minor+1; col < n; col++) {
|
||||
final double[] qrtCol = qrt[col];
|
||||
double alpha = 0;
|
||||
for (int row = minor; row < m; row++) {
|
||||
alpha -= qr[row][col]*qr[row][minor];
|
||||
alpha -= qrtCol[row] * qrtMinor[row];
|
||||
}
|
||||
alpha /= a*qr[minor][minor];
|
||||
alpha /= a * qrtMinor[minor];
|
||||
|
||||
// Subtract the column vector alpha*v from x.
|
||||
for (int row = minor; row < m; row++) {
|
||||
qr[row][col] -= alpha*qr[row][minor];
|
||||
qrtCol[row] -= alpha * qrtMinor[row];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the matrix R of the QR-decomposition.
|
||||
*
|
||||
* @return the R matrix
|
||||
*/
|
||||
/** {@inheritDoc} */
|
||||
public RealMatrix getR()
|
||||
{
|
||||
// R is supposed to be m x n
|
||||
RealMatrixImpl ret = new RealMatrixImpl(m,n);
|
||||
double[][] r = ret.getDataRef();
|
||||
throws IllegalStateException {
|
||||
|
||||
// copy the diagonal from rDiag and the upper triangle of qr
|
||||
for (int row = Math.min(m,n)-1; row >= 0; row--) {
|
||||
r[row][row] = rDiag[row];
|
||||
for (int col = row+1; col < n; col++) {
|
||||
r[row][col] = qr[row][col];
|
||||
if (cachedR == null) {
|
||||
|
||||
checkDecomposed();
|
||||
|
||||
// R is supposed to be m x n
|
||||
final int n = qrt.length;
|
||||
final int m = qrt[0].length;
|
||||
double[][] r = new double[m][n];
|
||||
|
||||
// copy the diagonal from rDiag and the upper triangle of qr
|
||||
for (int row = Math.min(m, n) - 1; row >= 0; row--) {
|
||||
double[] rRow = r[row];
|
||||
rRow[row] = rDiag[row];
|
||||
for (int col = row + 1; col < n; col++) {
|
||||
rRow[col] = qrt[col][row];
|
||||
}
|
||||
}
|
||||
|
||||
// cache the matrix for subsequent calls
|
||||
cachedR = new RealMatrixImpl(r, false);
|
||||
|
||||
}
|
||||
return ret;
|
||||
|
||||
// return the cached matrix
|
||||
return cachedR;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the matrix Q of the QR-decomposition.
|
||||
*
|
||||
* @return the Q matrix
|
||||
*/
|
||||
/** {@inheritDoc} */
|
||||
public RealMatrix getQ()
|
||||
{
|
||||
// Q is supposed to be m x m
|
||||
RealMatrixImpl ret = new RealMatrixImpl(m,m);
|
||||
double[][] Q = ret.getDataRef();
|
||||
|
||||
/*
|
||||
* Q = Q1 Q2 ... Q_m, so Q is formed by first constructing Q_m and then
|
||||
* applying the Householder transformations Q_(m-1),Q_(m-2),...,Q1 in
|
||||
* succession to the result
|
||||
*/
|
||||
for (int minor = m-1; minor >= Math.min(m,n); minor--) {
|
||||
Q[minor][minor]=1;
|
||||
throws IllegalStateException {
|
||||
if (cachedQ == null) {
|
||||
cachedQ = getQT().transpose();
|
||||
}
|
||||
return cachedQ;
|
||||
}
|
||||
|
||||
for (int minor = Math.min(m,n)-1; minor >= 0; minor--){
|
||||
Q[minor][minor] = 1;
|
||||
if (qr[minor][minor] != 0.0) {
|
||||
for (int col = minor; col < m; col++) {
|
||||
double alpha = 0;
|
||||
for (int row = minor; row < m; row++) {
|
||||
alpha -= Q[row][col] * qr[row][minor];
|
||||
}
|
||||
alpha /= rDiag[minor]*qr[minor][minor];
|
||||
/** {@inheritDoc} */
|
||||
public RealMatrix getQT()
|
||||
throws IllegalStateException {
|
||||
|
||||
for (int row = minor; row < m; row++) {
|
||||
Q[row][col] -= alpha*qr[row][minor];
|
||||
if (cachedQT == null) {
|
||||
|
||||
checkDecomposed();
|
||||
|
||||
// QT is supposed to be m x m
|
||||
final int n = qrt.length;
|
||||
final int m = qrt[0].length;
|
||||
double[][] qT = new double[m][m];
|
||||
|
||||
/*
|
||||
* Q = Q1 Q2 ... Q_m, so Q is formed by first constructing Q_m and then
|
||||
* applying the Householder transformations Q_(m-1),Q_(m-2),...,Q1 in
|
||||
* succession to the result
|
||||
*/
|
||||
for (int minor = m - 1; minor >= Math.min(m, n); minor--) {
|
||||
qT[minor][minor]=1;
|
||||
}
|
||||
|
||||
for (int minor = Math.min(m,n)-1; minor >= 0; minor--){
|
||||
final double[] qrtMinor = qrt[minor];
|
||||
qT[minor][minor] = 1;
|
||||
if (qrtMinor[minor] != 0.0) {
|
||||
for (int col = minor; col < m; col++) {
|
||||
final double[] qTCol = qT[col];
|
||||
double alpha = 0;
|
||||
for (int row = minor; row < m; row++) {
|
||||
alpha -= qTCol[row] * qrtMinor[row];
|
||||
}
|
||||
alpha /= rDiag[minor] * qrtMinor[minor];
|
||||
|
||||
for (int row = minor; row < m; row++) {
|
||||
qTCol[row] -= alpha * qrtMinor[row];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// cache the matrix for subsequent calls
|
||||
cachedQT = new RealMatrixImpl(qT, false);
|
||||
|
||||
}
|
||||
|
||||
return ret;
|
||||
// return the cached matrix
|
||||
return cachedQT;
|
||||
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public RealMatrix getH()
|
||||
throws IllegalStateException {
|
||||
|
||||
if (cachedH == null) {
|
||||
|
||||
checkDecomposed();
|
||||
|
||||
final int n = qrt.length;
|
||||
final int m = qrt[0].length;
|
||||
double[][] hData = new double[m][n];
|
||||
for (int i = 0; i < m; ++i) {
|
||||
final double[] hDataI = hData[i];
|
||||
for (int j = 0; j < Math.min(i + 1, n); ++j) {
|
||||
hDataI[j] = qrt[j][i] / -rDiag[j];
|
||||
}
|
||||
}
|
||||
|
||||
// cache the matrix for subsequent calls
|
||||
cachedH = new RealMatrixImpl(hData, false);
|
||||
|
||||
}
|
||||
|
||||
// return the cached matrix
|
||||
return cachedH;
|
||||
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public boolean isNonSingular()
|
||||
throws IllegalStateException {
|
||||
|
||||
checkDecomposed();
|
||||
|
||||
for (double diag : rDiag) {
|
||||
if (diag == 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public double[] solve(double[] b)
|
||||
throws IllegalStateException, IllegalArgumentException, InvalidMatrixException {
|
||||
|
||||
checkDecomposed();
|
||||
|
||||
final int n = qrt.length;
|
||||
final int m = qrt[0].length;
|
||||
if (b.length != m) {
|
||||
throw new IllegalArgumentException("Incorrect row dimension");
|
||||
}
|
||||
if (!isNonSingular()) {
|
||||
throw new RankDeficientMatrixException();
|
||||
}
|
||||
|
||||
final double[] x = new double[n];
|
||||
final double[] y = b.clone();
|
||||
|
||||
// apply Householder transforms to solve Q.y = b
|
||||
for (int minor = 0; minor < Math.min(m, n); minor++) {
|
||||
|
||||
final double[] qrtMinor = qrt[minor];
|
||||
double dotProduct = 0;
|
||||
for (int row = minor; row < m; row++) {
|
||||
dotProduct += y[row] * qrtMinor[row];
|
||||
}
|
||||
dotProduct /= rDiag[minor] * qrtMinor[minor];
|
||||
|
||||
for (int row = minor; row < m; row++) {
|
||||
y[row] += dotProduct * qrtMinor[row];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// solve triangular system R.x = y
|
||||
for (int row = n - 1; row >= 0; --row) {
|
||||
y[row] /= rDiag[row];
|
||||
final double yRow = y[row];
|
||||
final double[] qrtRow = qrt[row];
|
||||
x[row] = yRow;
|
||||
for (int i = 0; i < row; i++) {
|
||||
y[i] -= yRow * qrtRow[i];
|
||||
}
|
||||
}
|
||||
|
||||
return x;
|
||||
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public RealVector solve(RealVector b)
|
||||
throws IllegalStateException, IllegalArgumentException, InvalidMatrixException {
|
||||
try {
|
||||
return solve((RealVectorImpl) b);
|
||||
} catch (ClassCastException cce) {
|
||||
checkDecomposed();
|
||||
return new RealVectorImpl(solve(b.getData()), false);
|
||||
}
|
||||
}
|
||||
|
||||
/** Solve the linear equation A × X = B.
|
||||
* <p>The A matrix is implicit here. It is </p>
|
||||
* @param b right-hand side of the equation A × X = B
|
||||
* @return a vector X that minimizes the two norm of A × X - B
|
||||
* @exception IllegalStateException if {@link #decompose(RealMatrix) decompose}
|
||||
* has not been called
|
||||
* @throws IllegalArgumentException if matrices dimensions don't match
|
||||
* @throws InvalidMatrixException if decomposed matrix is singular
|
||||
*/
|
||||
public RealVectorImpl solve(RealVectorImpl b)
|
||||
throws IllegalStateException, IllegalArgumentException, InvalidMatrixException {
|
||||
return new RealVectorImpl(solve(b.getDataRef()), false);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public RealMatrix solve(RealMatrix b)
|
||||
throws IllegalStateException, IllegalArgumentException, InvalidMatrixException {
|
||||
|
||||
checkDecomposed();
|
||||
|
||||
final int n = qrt.length;
|
||||
final int m = qrt[0].length;
|
||||
if (b.getRowDimension() != m) {
|
||||
throw new IllegalArgumentException("Incorrect row dimension");
|
||||
}
|
||||
if (!isNonSingular()) {
|
||||
throw new RankDeficientMatrixException();
|
||||
}
|
||||
|
||||
final int cols = b.getColumnDimension();
|
||||
final double[][] xData = new double[n][cols];
|
||||
final double[] y = new double[b.getRowDimension()];
|
||||
|
||||
for (int k = 0; k < cols; ++k) {
|
||||
|
||||
// get the right hand side vector
|
||||
for (int j = 0; j < y.length; ++j) {
|
||||
y[j] = b.getEntry(j, k);
|
||||
}
|
||||
|
||||
// apply Householder transforms to solve Q.y = b
|
||||
for (int minor = 0; minor < Math.min(m, n); minor++) {
|
||||
|
||||
final double[] qrtMinor = qrt[minor];
|
||||
double dotProduct = 0;
|
||||
for (int row = minor; row < m; row++) {
|
||||
dotProduct += y[row] * qrtMinor[row];
|
||||
}
|
||||
dotProduct /= rDiag[minor] * qrtMinor[minor];
|
||||
|
||||
for (int row = minor; row < m; row++) {
|
||||
y[row] += dotProduct * qrtMinor[row];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// solve triangular system R.x = y
|
||||
for (int row = n - 1; row >= 0; --row) {
|
||||
y[row] /= rDiag[row];
|
||||
final double yRow = y[row];
|
||||
final double[] qrtRow = qrt[row];
|
||||
xData[row][k] = yRow;
|
||||
for (int i = 0; i < row; i++) {
|
||||
y[i] -= yRow * qrtRow[i];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return new RealMatrixImpl(xData, false);
|
||||
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public RealMatrix getInverse()
|
||||
throws IllegalStateException, InvalidMatrixException {
|
||||
checkDecomposed();
|
||||
return solve(MatrixUtils.createRealIdentityMatrix(rDiag.length));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if {@link #decompose(RealMatrix)} has been called.
|
||||
* @exception IllegalStateException if {@link #decompose(RealMatrix) decompose}
|
||||
* has not been called
|
||||
*/
|
||||
private void checkDecomposed()
|
||||
throws IllegalStateException {
|
||||
if (qrt == null) {
|
||||
throw MathRuntimeException.createIllegalStateException("no matrix have been decomposed yet", null);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -14,31 +14,24 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.commons.math.stat.descriptive;
|
||||
|
||||
import java.io.Serializable;
|
||||
package org.apache.commons.math.linear;
|
||||
|
||||
/**
|
||||
* Provides a default {@link SummaryStatistics} implementation.
|
||||
*
|
||||
* @deprecated to be removed in commons math 2.0. Use {@link SummaryStatistics}.
|
||||
* @version $Revision$ $Date$
|
||||
* Thrown when a matrix is singular.
|
||||
* @version $Revision$ $Date$
|
||||
* @since 2.0
|
||||
*/
|
||||
public class SummaryStatisticsImpl extends SummaryStatistics implements Serializable {
|
||||
public class RankDeficientMatrixException extends InvalidMatrixException {
|
||||
|
||||
/** Serializable version identifier */
|
||||
private static final long serialVersionUID = 8528794411480425963L;
|
||||
/** Serializable version identifier. */
|
||||
private static final long serialVersionUID = 7051890448195709736L;
|
||||
|
||||
/**
|
||||
* Construct a SummaryStatistics
|
||||
* Construct an exception with a default message.
|
||||
*/
|
||||
public SummaryStatisticsImpl() {
|
||||
super();
|
||||
public RankDeficientMatrixException() {
|
||||
super("matrix is rank-deficient", null);
|
||||
}
|
||||
|
||||
/** Resets all statistics and storage. */
|
||||
public void clear() {
|
||||
super.clear();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -148,6 +148,26 @@ public interface RealMatrix {
|
||||
* @throws MatrixIndexException if the specified column index is invalid
|
||||
*/
|
||||
RealMatrix getColumnMatrix(int column) throws MatrixIndexException;
|
||||
|
||||
/**
|
||||
* Returns the entries in row number <code>row</code>
|
||||
* as a vector. Row indices start at 0.
|
||||
*
|
||||
* @param row the row to be fetched
|
||||
* @return row vector
|
||||
* @throws MatrixIndexException if the specified row index is invalid
|
||||
*/
|
||||
RealVector getRowVector(int row) throws MatrixIndexException;
|
||||
|
||||
/**
|
||||
* Returns the entries in column number <code>column</code>
|
||||
* as a column vector. Column indices start at 0.
|
||||
*
|
||||
* @param column the column to be fetched
|
||||
* @return column vector
|
||||
* @throws MatrixIndexException if the specified column index is invalid
|
||||
*/
|
||||
RealVector getColumnVector(int column) throws MatrixIndexException;
|
||||
|
||||
/**
|
||||
* Returns the entries in row number <code>row</code> as an array.
|
||||
@ -202,14 +222,18 @@ public interface RealMatrix {
|
||||
*
|
||||
* @return inverse matrix
|
||||
* @throws InvalidMatrixException if this is not invertible
|
||||
* @deprecated as of release 2.0, replaced by {@link DecompositionSolver#getInverse()}
|
||||
*/
|
||||
@Deprecated
|
||||
RealMatrix inverse() throws InvalidMatrixException;
|
||||
|
||||
/**
|
||||
* Returns the determinant of this matrix.
|
||||
*
|
||||
* @return determinant
|
||||
* @deprecated as of release 2.0, replaced by {@link LUDecomposition#getDeterminant()}
|
||||
*/
|
||||
@Deprecated
|
||||
double getDeterminant();
|
||||
|
||||
/**
|
||||
@ -221,7 +245,10 @@ public interface RealMatrix {
|
||||
/**
|
||||
* Is this a singular matrix?
|
||||
* @return true if the matrix is singular
|
||||
* @deprecated as of release 2.0, replaced by the boolean negation of
|
||||
* {@link DecompositionSolver#isNonSingular()}
|
||||
*/
|
||||
@Deprecated
|
||||
boolean isSingular();
|
||||
|
||||
/**
|
||||
@ -255,6 +282,15 @@ public interface RealMatrix {
|
||||
*/
|
||||
double[] operate(double[] v) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Returns the result of multiplying this by the vector <code>v</code>.
|
||||
*
|
||||
* @param v the vector to operate on
|
||||
* @return this*v
|
||||
* @throws IllegalArgumentException if columnDimension != v.size()
|
||||
*/
|
||||
RealVector operate(RealVector v) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Returns the (row) vector result of premultiplying this by the vector <code>v</code>.
|
||||
*
|
||||
@ -264,6 +300,15 @@ public interface RealMatrix {
|
||||
*/
|
||||
double[] preMultiply(double[] v) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Returns the (row) vector result of premultiplying this by the vector <code>v</code>.
|
||||
*
|
||||
* @param v the row vector to premultiply by
|
||||
* @return v*this
|
||||
* @throws IllegalArgumentException if rowDimension != v.size()
|
||||
*/
|
||||
RealVector preMultiply(RealVector v) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Returns the solution vector for a linear system with coefficient
|
||||
* matrix = this and constant vector = <code>b</code>.
|
||||
@ -272,7 +317,9 @@ public interface RealMatrix {
|
||||
* @return vector of solution values to AX = b, where A is *this
|
||||
* @throws IllegalArgumentException if this.rowDimension != b.length
|
||||
* @throws InvalidMatrixException if this matrix is not square or is singular
|
||||
* @deprecated as of release 2.0, replaced by {@link DecompositionSolver#solve(double[])}
|
||||
*/
|
||||
@Deprecated
|
||||
double[] solve(double[] b) throws IllegalArgumentException, InvalidMatrixException;
|
||||
|
||||
/**
|
||||
@ -285,7 +332,9 @@ public interface RealMatrix {
|
||||
* @return matrix of solution vectors
|
||||
* @throws IllegalArgumentException if this.rowDimension != row dimension
|
||||
* @throws InvalidMatrixException if this matrix is not square or is singular
|
||||
* @deprecated as of release 2.0, replaced by {@link DecompositionSolver#solve(RealMatrix)}
|
||||
*/
|
||||
@Deprecated
|
||||
RealMatrix solve(RealMatrix b) throws IllegalArgumentException, InvalidMatrixException;
|
||||
}
|
||||
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
799
src/java/org/apache/commons/math/linear/RealVector.java
Normal file
799
src/java/org/apache/commons/math/linear/RealVector.java
Normal file
@ -0,0 +1,799 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.commons.math.linear;
|
||||
|
||||
/**
|
||||
* Interface defining a real-valued vector with basic algebraic operations.
|
||||
* <p>
|
||||
* vector element indexing is 0-based -- e.g., <code>getEntry(0)</code>
|
||||
* returns the first element of the vector.
|
||||
* </p>
|
||||
* <p>
|
||||
* The various <code>mapXxx</code> and <code>mapXxxToSelf</code> methods operate
|
||||
* on vectors element-wise, i.e. they perform the same operation (adding a scalar,
|
||||
* applying a function ...) on each element in turn. The <code>mapXxx</code>
|
||||
* versions create a new vector to hold the result and do not change the instance.
|
||||
* The <code>mapXxxToSelf</code> versions use the instance itself to store the
|
||||
* results, so the instance is changed by these methods. In both cases, the result
|
||||
* vector is returned by the methods, this allows to use the <i>fluent API</i>
|
||||
* style, like this:
|
||||
* </p>
|
||||
* <pre>
|
||||
* RealVector result = v.mapAddToSelf(3.0).mapTanToSelf().mapSquareToSelf();
|
||||
* </pre>
|
||||
*
|
||||
* @version $Revision$ $Date$
|
||||
* @since 2.0
|
||||
*/
|
||||
public interface RealVector {
|
||||
|
||||
/**
|
||||
* Returns a (deep) copy of this.
|
||||
* @return vector copy
|
||||
*/
|
||||
RealVector copy();
|
||||
|
||||
/**
|
||||
* Compute the sum of this and v.
|
||||
* @param v vector to be added
|
||||
* @return this + v
|
||||
* @throws IllegalArgumentException if v is not the same size as this
|
||||
*/
|
||||
RealVector add(RealVector v)
|
||||
throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Compute the sum of this and v.
|
||||
* @param v vector to be added
|
||||
* @return this + v
|
||||
* @throws IllegalArgumentException if v is not the same size as this
|
||||
*/
|
||||
RealVector add(double[] v)
|
||||
throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Compute this minus v.
|
||||
* @param v vector to be subtracted
|
||||
* @return this + v
|
||||
* @throws IllegalArgumentException if v is not the same size as this
|
||||
*/
|
||||
RealVector subtract(RealVector v)
|
||||
throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Compute this minus v.
|
||||
* @param v vector to be subtracted
|
||||
* @return this + v
|
||||
* @throws IllegalArgumentException if v is not the same size as this
|
||||
*/
|
||||
RealVector subtract(double[] v)
|
||||
throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Map an addition operation to each entry.
|
||||
* @param d value to be added to each entry
|
||||
* @return this + d
|
||||
*/
|
||||
RealVector mapAdd(double d);
|
||||
|
||||
/**
|
||||
* Map an addition operation to each entry.
|
||||
* <p>The instance <strong>is</strong> changed by this method.</p>
|
||||
* @param d value to be added to each entry
|
||||
* @return for convenience, return this
|
||||
*/
|
||||
RealVector mapAddToSelf(double d);
|
||||
|
||||
/**
|
||||
* Map a subtraction operation to each entry.
|
||||
* @param d value to be subtracted to each entry
|
||||
* @return this - d
|
||||
*/
|
||||
RealVector mapSubtract(double d);
|
||||
|
||||
/**
|
||||
* Map a subtraction operation to each entry.
|
||||
* <p>The instance <strong>is</strong> changed by this method.</p>
|
||||
* @param d value to be subtracted to each entry
|
||||
* @return for convenience, return this
|
||||
*/
|
||||
RealVector mapSubtractToSelf(double d);
|
||||
|
||||
/**
|
||||
* Map a multiplication operation to each entry.
|
||||
* @param d value to multiply all entries by
|
||||
* @return this * d
|
||||
*/
|
||||
RealVector mapMultiply(double d);
|
||||
|
||||
/**
|
||||
* Map a multiplication operation to each entry.
|
||||
* <p>The instance <strong>is</strong> changed by this method.</p>
|
||||
* @param d value to multiply all entries by
|
||||
* @return for convenience, return this
|
||||
*/
|
||||
RealVector mapMultiplyToSelf(double d);
|
||||
|
||||
/**
|
||||
* Map a division operation to each entry.
|
||||
* @param d value to divide all entries by
|
||||
* @return this / d
|
||||
*/
|
||||
RealVector mapDivide(double d);
|
||||
|
||||
/**
|
||||
* Map a division operation to each entry.
|
||||
* <p>The instance <strong>is</strong> changed by this method.</p>
|
||||
* @param d value to divide all entries by
|
||||
* @return for convenience, return this
|
||||
*/
|
||||
RealVector mapDivideToSelf(double d);
|
||||
|
||||
/**
|
||||
* Map a power operation to each entry.
|
||||
* @param d value to raise all entries to
|
||||
* @return this ^ d
|
||||
*/
|
||||
RealVector mapPow(double d);
|
||||
|
||||
/**
|
||||
* Map a power operation to each entry.
|
||||
* <p>The instance <strong>is</strong> changed by this method.</p>
|
||||
* @param d value to raise all entries to
|
||||
* @return for convenience, return this
|
||||
*/
|
||||
RealVector mapPowToSelf(double d);
|
||||
|
||||
/**
|
||||
* Map the {@link Math#exp(double)} function to each entry.
|
||||
* @return a vector containing the result of applying the function to each entry
|
||||
*/
|
||||
RealVector mapExp();
|
||||
|
||||
/**
|
||||
* Map the {@link Math#exp(double)} function to each entry.
|
||||
* <p>The instance <strong>is</strong> changed by this method.</p>
|
||||
* @return for convenience, return this
|
||||
*/
|
||||
RealVector mapExpToSelf();
|
||||
|
||||
/**
|
||||
* Map the {@link Math#expm1(double)} function to each entry.
|
||||
* @return a vector containing the result of applying the function to each entry
|
||||
*/
|
||||
RealVector mapExpm1();
|
||||
|
||||
/**
|
||||
* Map the {@link Math#expm1(double)} function to each entry.
|
||||
* <p>The instance <strong>is</strong> changed by this method.</p>
|
||||
* @return for convenience, return this
|
||||
*/
|
||||
RealVector mapExpm1ToSelf();
|
||||
|
||||
/**
|
||||
* Map the {@link Math#log(double)} function to each entry.
|
||||
* @return a vector containing the result of applying the function to each entry
|
||||
*/
|
||||
RealVector mapLog();
|
||||
|
||||
/**
|
||||
* Map the {@link Math#log(double)} function to each entry.
|
||||
* <p>The instance <strong>is</strong> changed by this method.</p>
|
||||
* @return for convenience, return this
|
||||
*/
|
||||
RealVector mapLogToSelf();
|
||||
|
||||
/**
|
||||
* Map the {@link Math#log10(double)} function to each entry.
|
||||
* @return a vector containing the result of applying the function to each entry
|
||||
*/
|
||||
RealVector mapLog10();
|
||||
|
||||
/**
|
||||
* Map the {@link Math#log10(double)} function to each entry.
|
||||
* <p>The instance <strong>is</strong> changed by this method.</p>
|
||||
* @return for convenience, return this
|
||||
*/
|
||||
RealVector mapLog10ToSelf();
|
||||
|
||||
/**
|
||||
* Map the {@link Math#log1p(double)} function to each entry.
|
||||
* @return a vector containing the result of applying the function to each entry
|
||||
*/
|
||||
RealVector mapLog1p();
|
||||
|
||||
/**
|
||||
* Map the {@link Math#log1p(double)} function to each entry.
|
||||
* <p>The instance <strong>is</strong> changed by this method.</p>
|
||||
* @return for convenience, return this
|
||||
*/
|
||||
RealVector mapLog1pToSelf();
|
||||
|
||||
/**
|
||||
* Map the {@link Math#cosh(double)} function to each entry.
|
||||
* @return a vector containing the result of applying the function to each entry
|
||||
*/
|
||||
RealVector mapCosh();
|
||||
|
||||
/**
|
||||
* Map the {@link Math#cosh(double)} function to each entry.
|
||||
* <p>The instance <strong>is</strong> changed by this method.</p>
|
||||
* @return for convenience, return this
|
||||
*/
|
||||
RealVector mapCoshToSelf();
|
||||
|
||||
/**
|
||||
* Map the {@link Math#sinh(double)} function to each entry.
|
||||
* @return a vector containing the result of applying the function to each entry
|
||||
*/
|
||||
RealVector mapSinh();
|
||||
|
||||
/**
|
||||
* Map the {@link Math#sinh(double)} function to each entry.
|
||||
* <p>The instance <strong>is</strong> changed by this method.</p>
|
||||
* @return for convenience, return this
|
||||
*/
|
||||
RealVector mapSinhToSelf();
|
||||
|
||||
/**
|
||||
* Map the {@link Math#tanh(double)} function to each entry.
|
||||
* @return a vector containing the result of applying the function to each entry
|
||||
*/
|
||||
RealVector mapTanh();
|
||||
|
||||
/**
|
||||
* Map the {@link Math#tanh(double)} function to each entry.
|
||||
* <p>The instance <strong>is</strong> changed by this method.</p>
|
||||
* @return for convenience, return this
|
||||
*/
|
||||
RealVector mapTanhToSelf();
|
||||
|
||||
/**
|
||||
* Map the {@link Math#cos(double)} function to each entry.
|
||||
* @return a vector containing the result of applying the function to each entry
|
||||
*/
|
||||
RealVector mapCos();
|
||||
|
||||
/**
|
||||
* Map the {@link Math#cos(double)} function to each entry.
|
||||
* <p>The instance <strong>is</strong> changed by this method.</p>
|
||||
* @return for convenience, return this
|
||||
*/
|
||||
RealVector mapCosToSelf();
|
||||
|
||||
/**
|
||||
* Map the {@link Math#sin(double)} function to each entry.
|
||||
* @return a vector containing the result of applying the function to each entry
|
||||
*/
|
||||
RealVector mapSin();
|
||||
|
||||
/**
|
||||
* Map the {@link Math#sin(double)} function to each entry.
|
||||
* <p>The instance <strong>is</strong> changed by this method.</p>
|
||||
* @return for convenience, return this
|
||||
*/
|
||||
RealVector mapSinToSelf();
|
||||
|
||||
/**
|
||||
* Map the {@link Math#tan(double)} function to each entry.
|
||||
* @return a vector containing the result of applying the function to each entry
|
||||
*/
|
||||
RealVector mapTan();
|
||||
|
||||
/**
|
||||
* Map the {@link Math#tan(double)} function to each entry.
|
||||
* <p>The instance <strong>is</strong> changed by this method.</p>
|
||||
* @return for convenience, return this
|
||||
*/
|
||||
RealVector mapTanToSelf();
|
||||
|
||||
/**
|
||||
* Map the {@link Math#acos(double)} function to each entry.
|
||||
* @return a vector containing the result of applying the function to each entry
|
||||
*/
|
||||
RealVector mapAcos();
|
||||
|
||||
/**
|
||||
* Map the {@link Math#acos(double)} function to each entry.
|
||||
* <p>The instance <strong>is</strong> changed by this method.</p>
|
||||
* @return for convenience, return this
|
||||
*/
|
||||
RealVector mapAcosToSelf();
|
||||
|
||||
/**
|
||||
* Map the {@link Math#asin(double)} function to each entry.
|
||||
* @return a vector containing the result of applying the function to each entry
|
||||
*/
|
||||
RealVector mapAsin();
|
||||
|
||||
/**
|
||||
* Map the {@link Math#asin(double)} function to each entry.
|
||||
* <p>The instance <strong>is</strong> changed by this method.</p>
|
||||
* @return for convenience, return this
|
||||
*/
|
||||
RealVector mapAsinToSelf();
|
||||
|
||||
/**
|
||||
* Map the {@link Math#atan(double)} function to each entry.
|
||||
* @return a vector containing the result of applying the function to each entry
|
||||
*/
|
||||
RealVector mapAtan();
|
||||
|
||||
/**
|
||||
* Map the {@link Math#atan(double)} function to each entry.
|
||||
* <p>The instance <strong>is</strong> changed by this method.</p>
|
||||
* @return for convenience, return this
|
||||
*/
|
||||
RealVector mapAtanToSelf();
|
||||
|
||||
/**
|
||||
* Map the 1/x function to each entry.
|
||||
* @return a vector containing the result of applying the function to each entry
|
||||
*/
|
||||
RealVector mapInv();
|
||||
|
||||
/**
|
||||
* Map the 1/x function to each entry.
|
||||
* <p>The instance <strong>is</strong> changed by this method.</p>
|
||||
* @return for convenience, return this
|
||||
*/
|
||||
RealVector mapInvToSelf();
|
||||
|
||||
/**
|
||||
* Map the {@link Math#abs(double)} function to each entry.
|
||||
* @return a vector containing the result of applying the function to each entry
|
||||
*/
|
||||
RealVector mapAbs();
|
||||
|
||||
/**
|
||||
* Map the {@link Math#abs(double)} function to each entry.
|
||||
* <p>The instance <strong>is</strong> changed by this method.</p>
|
||||
* @return for convenience, return this
|
||||
*/
|
||||
RealVector mapAbsToSelf();
|
||||
|
||||
/**
|
||||
* Map the {@link Math#sqrt(double)} function to each entry.
|
||||
* @return a vector containing the result of applying the function to each entry
|
||||
*/
|
||||
RealVector mapSqrt();
|
||||
|
||||
/**
|
||||
* Map the {@link Math#sqrt(double)} function to each entry.
|
||||
* <p>The instance <strong>is</strong> changed by this method.</p>
|
||||
* @return for convenience, return this
|
||||
*/
|
||||
RealVector mapSqrtToSelf();
|
||||
|
||||
/**
|
||||
* Map the {@link Math#cbrt(double)} function to each entry.
|
||||
* @return a vector containing the result of applying the function to each entry
|
||||
*/
|
||||
RealVector mapCbrt();
|
||||
|
||||
/**
|
||||
* Map the {@link Math#cbrt(double)} function to each entry.
|
||||
* <p>The instance <strong>is</strong> changed by this method.</p>
|
||||
* @return for convenience, return this
|
||||
*/
|
||||
RealVector mapCbrtToSelf();
|
||||
|
||||
/**
|
||||
* Map the {@link Math#ceil(double)} function to each entry.
|
||||
* @return a vector containing the result of applying the function to each entry
|
||||
*/
|
||||
RealVector mapCeil();
|
||||
|
||||
/**
|
||||
* Map the {@link Math#ceil(double)} function to each entry.
|
||||
* <p>The instance <strong>is</strong> changed by this method.</p>
|
||||
* @return for convenience, return this
|
||||
*/
|
||||
RealVector mapCeilToSelf();
|
||||
|
||||
/**
|
||||
* Map the {@link Math#floor(double)} function to each entry.
|
||||
* @return a vector containing the result of applying the function to each entry
|
||||
*/
|
||||
RealVector mapFloor();
|
||||
|
||||
/**
|
||||
* Map the {@link Math#floor(double)} function to each entry.
|
||||
* <p>The instance <strong>is</strong> changed by this method.</p>
|
||||
* @return for convenience, return this
|
||||
*/
|
||||
RealVector mapFloorToSelf();
|
||||
|
||||
/**
|
||||
* Map the {@link Math#rint(double)} function to each entry.
|
||||
* @return a vector containing the result of applying the function to each entry
|
||||
*/
|
||||
RealVector mapRint();
|
||||
|
||||
/**
|
||||
* Map the {@link Math#rint(double)} function to each entry.
|
||||
* <p>The instance <strong>is</strong> changed by this method.</p>
|
||||
* @return for convenience, return this
|
||||
*/
|
||||
RealVector mapRintToSelf();
|
||||
|
||||
/**
|
||||
* Map the {@link Math#signum(double)} function to each entry.
|
||||
* @return a vector containing the result of applying the function to each entry
|
||||
*/
|
||||
RealVector mapSignum();
|
||||
|
||||
/**
|
||||
* Map the {@link Math#signum(double)} function to each entry.
|
||||
* <p>The instance <strong>is</strong> changed by this method.</p>
|
||||
* @return for convenience, return this
|
||||
*/
|
||||
RealVector mapSignumToSelf();
|
||||
|
||||
/**
|
||||
* Map the {@link Math#ulp(double)} function to each entry.
|
||||
* @return a vector containing the result of applying the function to each entry
|
||||
*/
|
||||
RealVector mapUlp();
|
||||
|
||||
/**
|
||||
* Map the {@link Math#ulp(double)} function to each entry.
|
||||
* <p>The instance <strong>is</strong> changed by this method.</p>
|
||||
* @return for convenience, return this
|
||||
*/
|
||||
RealVector mapUlpToSelf();
|
||||
|
||||
/**
|
||||
* Element-by-element multiplication.
|
||||
* @param v vector by which instance elements must be multiplied
|
||||
* @return a vector containing this[i] * v[i] for all i
|
||||
* @throws IllegalArgumentException if v is not the same size as this
|
||||
*/
|
||||
public RealVector ebeMultiply(RealVector v)
|
||||
throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Element-by-element multiplication.
|
||||
* @param v vector by which instance elements must be multiplied
|
||||
* @return a vector containing this[i] * v[i] for all i
|
||||
* @throws IllegalArgumentException if v is not the same size as this
|
||||
*/
|
||||
public RealVector ebeMultiply(double[] v)
|
||||
throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Element-by-element division.
|
||||
* @param v vector by which instance elements must be divided
|
||||
* @return a vector containing this[i] / v[i] for all i
|
||||
* @throws IllegalArgumentException if v is not the same size as this
|
||||
*/
|
||||
public RealVector ebeDivide(RealVector v)
|
||||
throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Element-by-element division.
|
||||
* @param v vector by which instance elements must be divided
|
||||
* @return a vector containing this[i] / v[i] for all i
|
||||
* @throws IllegalArgumentException if v is not the same size as this
|
||||
*/
|
||||
public RealVector ebeDivide(double[] v)
|
||||
throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Returns vector entries as a double array.
|
||||
* @return double array of entries
|
||||
*/
|
||||
double[] getData();
|
||||
|
||||
/**
|
||||
* Compute the dot product.
|
||||
* @param v vector with which dot product should be computed
|
||||
* @return the scalar dot product between instance and v
|
||||
* @exception IllegalArgumentException if v is not the same size as this
|
||||
*/
|
||||
double dotProduct(RealVector v)
|
||||
throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Compute the dot product.
|
||||
* @param v vector with which dot product should be computed
|
||||
* @return the scalar dot product between instance and v
|
||||
* @exception IllegalArgumentException if v is not the same size as this
|
||||
*/
|
||||
double dotProduct(double[] v)
|
||||
throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Returns the L<sub>2</sub> norm of the vector.
|
||||
* <p>The L<sub>2</sub> norm is the root of the sum of
|
||||
* the squared elements.</p>
|
||||
* @return norm
|
||||
* @see #getL1Norm()
|
||||
* @see #getLInfNorm()
|
||||
* @see #getDistance(RealVector)
|
||||
*/
|
||||
double getNorm();
|
||||
|
||||
/**
|
||||
* Returns the L<sub>1</sub> norm of the vector.
|
||||
* <p>The L<sub>1</sub> norm is the sum of the absolute
|
||||
* values of elements.</p>
|
||||
* @return norm
|
||||
* @see #getNorm()
|
||||
* @see #getLInfNorm()
|
||||
* @see #getL1Distance(RealVector)
|
||||
*/
|
||||
double getL1Norm();
|
||||
|
||||
/**
|
||||
* Returns the L<sub>&infty;</sub> norm of the vector.
|
||||
* <p>The L<sub>&infty;</sub> norm is the max of the absolute
|
||||
* values of elements.</p>
|
||||
* @return norm
|
||||
* @see #getNorm()
|
||||
* @see #getL1Norm()
|
||||
* @see #getLInfDistance(RealVector)
|
||||
*/
|
||||
double getLInfNorm();
|
||||
|
||||
/**
|
||||
* Distance between two vectors.
|
||||
* <p>This method computes the distance consistent with the
|
||||
* L<sub>2</sub> norm, i.e. the square root of the sum of
|
||||
* elements differences, or euclidian distance.</p>
|
||||
* @param v vector to which distance is requested
|
||||
* @return distance between two vectors.
|
||||
* @exception IllegalArgumentException if v is not the same size as this
|
||||
* @see #getL1Distance(RealVector)
|
||||
* @see #getLInfDistance(RealVector)
|
||||
* @see #getNorm()
|
||||
*/
|
||||
double getDistance(RealVector v)
|
||||
throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Distance between two vectors.
|
||||
* <p>This method computes the distance consistent with the
|
||||
* L<sub>2</sub> norm, i.e. the square root of the sum of
|
||||
* elements differences, or euclidian distance.</p>
|
||||
* @param v vector to which distance is requested
|
||||
* @return distance between two vectors.
|
||||
* @exception IllegalArgumentException if v is not the same size as this
|
||||
* @see #getL1Distance(double[])
|
||||
* @see #getLInfDistance(double[])
|
||||
* @see #getNorm()
|
||||
*/
|
||||
double getDistance(double[] v)
|
||||
throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Distance between two vectors.
|
||||
* <p>This method computes the distance consistent with
|
||||
* L<sub>1</sub> norm, i.e. the sum of the absolute values of
|
||||
* elements differences.</p>
|
||||
* @param v vector to which distance is requested
|
||||
* @return distance between two vectors.
|
||||
* @exception IllegalArgumentException if v is not the same size as this
|
||||
* @see #getDistance(RealVector)
|
||||
* @see #getLInfDistance(RealVector)
|
||||
* @see #getL1Norm()
|
||||
*/
|
||||
double getL1Distance(RealVector v)
|
||||
throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Distance between two vectors.
|
||||
* <p>This method computes the distance consistent with
|
||||
* L<sub>1</sub> norm, i.e. the sum of the absolute values of
|
||||
* elements differences.</p>
|
||||
* @param v vector to which distance is requested
|
||||
* @return distance between two vectors.
|
||||
* @exception IllegalArgumentException if v is not the same size as this
|
||||
* @see #getDistance(double[])
|
||||
* @see #getLInfDistance(double[])
|
||||
* @see #getL1Norm()
|
||||
*/
|
||||
double getL1Distance(double[] v)
|
||||
throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Distance between two vectors.
|
||||
* <p>This method computes the distance consistent with
|
||||
* L<sub>&infty;</sub> norm, i.e. the max of the absolute values of
|
||||
* elements differences.</p>
|
||||
* @param v vector to which distance is requested
|
||||
* @return distance between two vectors.
|
||||
* @exception IllegalArgumentException if v is not the same size as this
|
||||
* @see #getDistance(RealVector)
|
||||
* @see #getL1Distance(RealVector)
|
||||
* @see #getLInfNorm()
|
||||
*/
|
||||
double getLInfDistance(RealVector v)
|
||||
throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Distance between two vectors.
|
||||
* <p>This method computes the distance consistent with
|
||||
* L<sub>&infty;</sub> norm, i.e. the max of the absolute values of
|
||||
* elements differences.</p>
|
||||
* @param v vector to which distance is requested
|
||||
* @return distance between two vectors.
|
||||
* @exception IllegalArgumentException if v is not the same size as this
|
||||
* @see #getDistance(double[])
|
||||
* @see #getL1Distance(double[])
|
||||
* @see #getLInfNorm()
|
||||
*/
|
||||
double getLInfDistance(double[] v)
|
||||
throws IllegalArgumentException;
|
||||
|
||||
/** Creates a unit vector pointing in the direction of this vector.
|
||||
* <p>The instance is not changed by this method.</p>
|
||||
* @return a unit vector pointing in direction of this vector
|
||||
* @exception ArithmeticException if the norm is null
|
||||
*/
|
||||
RealVector unitVector();
|
||||
|
||||
/** Converts this vector into a unit vector.
|
||||
* <p>The instance itself is changed by this method.</p>
|
||||
* @exception ArithmeticException if the norm is null
|
||||
*/
|
||||
void unitize();
|
||||
|
||||
/** Find the orthogonal projection of this vector onto another vector.
|
||||
* @param v vector onto which instance must be projected
|
||||
* @return projection of the instance onto v
|
||||
* @throws IllegalArgumentException if v is not the same size as this
|
||||
*/
|
||||
RealVector projection(RealVector v)
|
||||
throws IllegalArgumentException;
|
||||
|
||||
/** Find the orthogonal projection of this vector onto another vector.
|
||||
* @param v vector onto which instance must be projected
|
||||
* @return projection of the instance onto v
|
||||
* @throws IllegalArgumentException if v is not the same size as this
|
||||
*/
|
||||
RealVector projection(double[] v)
|
||||
throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Compute the outer product.
|
||||
* @param v vector with which outer product should be computed
|
||||
* @return the square matrix outer product between instance and v
|
||||
* @exception IllegalArgumentException if v is not the same size as this
|
||||
*/
|
||||
RealMatrix outerProduct(RealVector v)
|
||||
throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Compute the outer product.
|
||||
* @param v vector with which outer product should be computed
|
||||
* @return the square matrix outer product between instance and v
|
||||
* @exception IllegalArgumentException if v is not the same size as this
|
||||
*/
|
||||
RealMatrix outerProduct(double[] v)
|
||||
throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Returns the entry in the specified index.
|
||||
* <p>
|
||||
* The index start at 0 and must be lesser than the size,
|
||||
* otherwise a {@link MatrixIndexException} is thrown.
|
||||
* </p>
|
||||
* @param index index location of entry to be fetched
|
||||
* @return vector entry at index
|
||||
* @throws MatrixIndexException if the index is not valid
|
||||
*/
|
||||
double getEntry(int index)
|
||||
throws MatrixIndexException;
|
||||
|
||||
/**
|
||||
* Returns the size of the vector.
|
||||
* @return size
|
||||
*/
|
||||
int getDimension();
|
||||
|
||||
/**
|
||||
* Construct a vector by appending a vector to this vector.
|
||||
* @param v vector to append to this one.
|
||||
* @return a new vector
|
||||
*/
|
||||
RealVector append(RealVector v);
|
||||
|
||||
/**
|
||||
* Construct a vector by appending a double to this vector.
|
||||
* @param d double to append.
|
||||
* @return a new vector
|
||||
*/
|
||||
RealVector append(double d);
|
||||
|
||||
/**
|
||||
* Construct a vector by appending a double array to this vector.
|
||||
* @param a double array to append.
|
||||
* @return a new vector
|
||||
*/
|
||||
RealVector append(double[] a);
|
||||
|
||||
/**
|
||||
* Get a subvector from consecutive elements.
|
||||
* @param index index of first element.
|
||||
* @param n number of elements to be retrieved.
|
||||
* @return a vector containing n elements.
|
||||
* @exception MatrixIndexException if the index is
|
||||
* inconsistent with vector size
|
||||
*/
|
||||
RealVector get(int index, int n)
|
||||
throws MatrixIndexException;
|
||||
|
||||
/**
|
||||
* Set a single element.
|
||||
* @param index element index.
|
||||
* @param value new value for the element.
|
||||
* @exception MatrixIndexException if the index is
|
||||
* inconsistent with vector size
|
||||
*/
|
||||
void set(int index, double value)
|
||||
throws MatrixIndexException;
|
||||
|
||||
/**
|
||||
* Set a set of consecutive elements.
|
||||
* @param index index of first element to be set.
|
||||
* @param v vector containing the values to set.
|
||||
* @exception MatrixIndexException if the index is
|
||||
* inconsistent with vector size
|
||||
*/
|
||||
void set(int index, RealVector v)
|
||||
throws MatrixIndexException;
|
||||
|
||||
/**
|
||||
* Set a set of consecutive elements.
|
||||
* @param index index of first element to be set.
|
||||
* @param v vector containing the values to set.
|
||||
* @exception MatrixIndexException if the index is
|
||||
* inconsistent with vector size
|
||||
*/
|
||||
void set(int index, double[] v)
|
||||
throws MatrixIndexException;
|
||||
|
||||
/**
|
||||
* Set all elements to a single value.
|
||||
* @param value single value to set for all elements
|
||||
*/
|
||||
void set(double value);
|
||||
|
||||
/**
|
||||
* Convert the vector to a double array.
|
||||
* <p>The array is independent from vector data, it's elements
|
||||
* are copied.</p>
|
||||
* @return array containing a copy of vector elements
|
||||
*/
|
||||
double[] toArray();
|
||||
|
||||
/**
|
||||
* Returns true if any coordinate of this vector is NaN; false otherwise
|
||||
* @return true if any coordinate of this vector is NaN; false otherwise
|
||||
*/
|
||||
public boolean isNaN();
|
||||
|
||||
/**
|
||||
* Returns true if any coordinate of this vector is infinite and none are NaN;
|
||||
* false otherwise
|
||||
* @return true if any coordinate of this vector is infinite and none are NaN;
|
||||
* false otherwise
|
||||
*/
|
||||
public boolean isInfinite();
|
||||
|
||||
}
|
336
src/java/org/apache/commons/math/linear/RealVectorFormat.java
Normal file
336
src/java/org/apache/commons/math/linear/RealVectorFormat.java
Normal file
@ -0,0 +1,336 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.commons.math.linear;
|
||||
|
||||
import java.text.FieldPosition;
|
||||
import java.text.NumberFormat;
|
||||
import java.text.ParseException;
|
||||
import java.text.ParsePosition;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.apache.commons.math.MathRuntimeException;
|
||||
import org.apache.commons.math.util.CompositeFormat;
|
||||
|
||||
/**
|
||||
* Formats a vector in components list format "{v0; v1; ...; vk-1}".
|
||||
* <p>The prefix and suffix "{" and "}" and the separator "; " can be replaced by
|
||||
* any user-defined strings. The number format for components can be configured.</p>
|
||||
* <p>White space is ignored at parse time, even if it is in the prefix, suffix
|
||||
* or separator specifications. So even if the default separator does include a space
|
||||
* character that is used at format time, both input string "{1;1;1}" and
|
||||
* " { 1 ; 1 ; 1 } " will be parsed without error and the same vector will be
|
||||
* returned. In the second case, however, the parse position after parsing will be
|
||||
* just after the closing curly brace, i.e. just before the trailing space.</p>
|
||||
*
|
||||
* @version $Revision$ $Date$
|
||||
* @since 2.0
|
||||
*/
|
||||
public class RealVectorFormat extends CompositeFormat {
|
||||
|
||||
/** Serializable version identifier */
|
||||
private static final long serialVersionUID = -708767813036157690L;
|
||||
|
||||
/** The default prefix: "{". */
|
||||
private static final String DEFAULT_PREFIX = "{";
|
||||
|
||||
/** The default suffix: "}". */
|
||||
private static final String DEFAULT_SUFFIX = "}";
|
||||
|
||||
/** The default separator: ", ". */
|
||||
private static final String DEFAULT_SEPARATOR = "; ";
|
||||
|
||||
/** Prefix. */
|
||||
private final String prefix;
|
||||
|
||||
/** Suffix. */
|
||||
private final String suffix;
|
||||
|
||||
/** Separator. */
|
||||
private final String separator;
|
||||
|
||||
/** Trimmed prefix. */
|
||||
private final String trimmedPrefix;
|
||||
|
||||
/** Trimmed suffix. */
|
||||
private final String trimmedSuffix;
|
||||
|
||||
/** Trimmed separator. */
|
||||
private final String trimmedSeparator;
|
||||
|
||||
/** The format used for components. */
|
||||
private NumberFormat format;
|
||||
|
||||
/**
|
||||
* Create an instance with default settings.
|
||||
* <p>The instance uses the default prefix, suffix and separator:
|
||||
* "{", "}", and "; " and the default number format for components.</p>
|
||||
*/
|
||||
public RealVectorFormat() {
|
||||
this(DEFAULT_PREFIX, DEFAULT_SUFFIX, DEFAULT_SEPARATOR, getDefaultNumberFormat());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance with a custom number format for components.
|
||||
* @param format the custom format for components.
|
||||
*/
|
||||
public RealVectorFormat(final NumberFormat format) {
|
||||
this(DEFAULT_PREFIX, DEFAULT_SUFFIX, DEFAULT_SEPARATOR, format);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance with custom prefix, suffix and separator.
|
||||
* @param prefix prefix to use instead of the default "{"
|
||||
* @param suffix suffix to use instead of the default "}"
|
||||
* @param separator separator to use instead of the default "; "
|
||||
*/
|
||||
public RealVectorFormat(final String prefix, final String suffix,
|
||||
final String separator) {
|
||||
this(prefix, suffix, separator, getDefaultNumberFormat());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance with custom prefix, suffix, separator and format
|
||||
* for components.
|
||||
* @param prefix prefix to use instead of the default "{"
|
||||
* @param suffix suffix to use instead of the default "}"
|
||||
* @param separator separator to use instead of the default "; "
|
||||
* @param format the custom format for components.
|
||||
*/
|
||||
public RealVectorFormat(final String prefix, final String suffix,
|
||||
final String separator, final NumberFormat format) {
|
||||
this.prefix = prefix;
|
||||
this.suffix = suffix;
|
||||
this.separator = separator;
|
||||
trimmedPrefix = prefix.trim();
|
||||
trimmedSuffix = suffix.trim();
|
||||
trimmedSeparator = separator.trim();
|
||||
this.format = format;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the set of locales for which real vectors formats are available.
|
||||
* <p>This is the same set as the {@link NumberFormat} set.</p>
|
||||
* @return available real vector format locales.
|
||||
*/
|
||||
public static Locale[] getAvailableLocales() {
|
||||
return NumberFormat.getAvailableLocales();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the format prefix.
|
||||
* @return format prefix.
|
||||
*/
|
||||
public String getPrefix() {
|
||||
return prefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the format suffix.
|
||||
* @return format suffix.
|
||||
*/
|
||||
public String getSuffix() {
|
||||
return suffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the format separator between components.
|
||||
* @return format separator.
|
||||
*/
|
||||
public String getSeparator() {
|
||||
return separator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the components format.
|
||||
* @return components format.
|
||||
*/
|
||||
public NumberFormat getFormat() {
|
||||
return format;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default real vector format for the current locale.
|
||||
* @return the default real vector format.
|
||||
*/
|
||||
public static RealVectorFormat getInstance() {
|
||||
return getInstance(Locale.getDefault());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default real vector format for the given locale.
|
||||
* @param locale the specific locale used by the format.
|
||||
* @return the real vector format specific to the given locale.
|
||||
*/
|
||||
public static RealVectorFormat getInstance(final Locale locale) {
|
||||
return new RealVectorFormat(getDefaultNumberFormat(locale));
|
||||
}
|
||||
|
||||
/**
|
||||
* This static method calls {@link #format(Object)} on a default instance of
|
||||
* RealVectorFormat.
|
||||
*
|
||||
* @param v RealVector object to format
|
||||
* @return A formatted vector
|
||||
*/
|
||||
public static String formatRealVector(RealVector v) {
|
||||
return getInstance().format(v);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a {@link RealVector} object to produce a string.
|
||||
* @param vector the object to format.
|
||||
* @param toAppendTo where the text is to be appended
|
||||
* @param pos On input: an alignment field, if desired. On output: the
|
||||
* offsets of the alignment field
|
||||
* @return the value passed in as toAppendTo.
|
||||
*/
|
||||
public StringBuffer format(RealVector vector, StringBuffer toAppendTo,
|
||||
FieldPosition pos) {
|
||||
|
||||
pos.setBeginIndex(0);
|
||||
pos.setEndIndex(0);
|
||||
|
||||
// format prefix
|
||||
toAppendTo.append(prefix);
|
||||
|
||||
// format components
|
||||
for (int i = 0; i < vector.getDimension(); ++i) {
|
||||
if (i > 0) {
|
||||
toAppendTo.append(separator);
|
||||
}
|
||||
formatDouble(vector.getEntry(i), format, toAppendTo, pos);
|
||||
}
|
||||
|
||||
// format suffix
|
||||
toAppendTo.append(suffix);
|
||||
|
||||
return toAppendTo;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a object to produce a string.
|
||||
* <p><code>obj</code> must be a {@link RealVector} object. Any other type of
|
||||
* object will result in an {@link IllegalArgumentException} being thrown.</p>
|
||||
* @param obj the object to format.
|
||||
* @param toAppendTo where the text is to be appended
|
||||
* @param pos On input: an alignment field, if desired. On output: the
|
||||
* offsets of the alignment field
|
||||
* @return the value passed in as toAppendTo.
|
||||
* @see java.text.Format#format(java.lang.Object, java.lang.StringBuffer, java.text.FieldPosition)
|
||||
* @throws IllegalArgumentException is <code>obj</code> is not a valid type.
|
||||
*/
|
||||
public StringBuffer format(Object obj, StringBuffer toAppendTo,
|
||||
FieldPosition pos) {
|
||||
|
||||
if (obj instanceof RealVector) {
|
||||
return format( (RealVector)obj, toAppendTo, pos);
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Cannot format given Object as a RealVector");
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a string to produce a {@link RealVector} object.
|
||||
* @param source the string to parse
|
||||
* @return the parsed {@link RealVector} object.
|
||||
* @exception ParseException if the beginning of the specified string
|
||||
* cannot be parsed.
|
||||
*/
|
||||
public RealVectorImpl parse(String source) throws ParseException {
|
||||
ParsePosition parsePosition = new ParsePosition(0);
|
||||
RealVectorImpl result = parse(source, parsePosition);
|
||||
if (parsePosition.getIndex() == 0) {
|
||||
throw MathRuntimeException.createParseException("unparseable real vector: \"{0}\"",
|
||||
new Object[] { source },
|
||||
parsePosition.getErrorIndex());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a string to produce a {@link RealVector} object.
|
||||
* @param source the string to parse
|
||||
* @param pos input/ouput parsing parameter.
|
||||
* @return the parsed {@link RealVector} object.
|
||||
*/
|
||||
public RealVectorImpl parse(String source, ParsePosition pos) {
|
||||
int initialIndex = pos.getIndex();
|
||||
|
||||
// parse prefix
|
||||
parseAndIgnoreWhitespace(source, pos);
|
||||
if (!parseFixedstring(source, trimmedPrefix, pos)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// parse components
|
||||
List<Number> components = new ArrayList<Number>();
|
||||
for (boolean loop = true; loop;){
|
||||
|
||||
if (!components.isEmpty()) {
|
||||
parseAndIgnoreWhitespace(source, pos);
|
||||
if (!parseFixedstring(source, trimmedSeparator, pos)) {
|
||||
loop = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (loop) {
|
||||
parseAndIgnoreWhitespace(source, pos);
|
||||
Number component = parseNumber(source, format, pos);
|
||||
if (component != null) {
|
||||
components.add(component);
|
||||
} else {
|
||||
// invalid component
|
||||
// set index back to initial, error index should already be set
|
||||
pos.setIndex(initialIndex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// parse suffix
|
||||
parseAndIgnoreWhitespace(source, pos);
|
||||
if (!parseFixedstring(source, trimmedSuffix, pos)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// build vector
|
||||
double[] data = new double[components.size()];
|
||||
for (int i = 0; i < data.length; ++i) {
|
||||
data[i] = components.get(i).doubleValue();
|
||||
}
|
||||
return new RealVectorImpl(data, false);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a string to produce a object.
|
||||
* @param source the string to parse
|
||||
* @param pos input/ouput parsing parameter.
|
||||
* @return the parsed object.
|
||||
* @see java.text.Format#parseObject(java.lang.String, java.text.ParsePosition)
|
||||
*/
|
||||
public Object parseObject(String source, ParsePosition pos) {
|
||||
return parse(source, pos);
|
||||
}
|
||||
|
||||
}
|
1405
src/java/org/apache/commons/math/linear/RealVectorImpl.java
Normal file
1405
src/java/org/apache/commons/math/linear/RealVectorImpl.java
Normal file
File diff suppressed because it is too large
Load Diff
@ -5,39 +5,33 @@
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.commons.math.stat.descriptive;
|
||||
|
||||
package org.apache.commons.math.linear;
|
||||
|
||||
import junit.framework.Test;
|
||||
import junit.framework.TestSuite;
|
||||
/**
|
||||
* Test cases for the {@link SummaryStatisticsImpl} class.
|
||||
* @deprecated - to be removed in 2.0 with SummaryStatisticsImpl
|
||||
* Thrown when a matrix is singular.
|
||||
* @version $Revision$ $Date$
|
||||
* @since 2.0
|
||||
*/
|
||||
public class SingularMatrixException extends InvalidMatrixException {
|
||||
|
||||
public final class SummaryStatisticsImplTest extends SummaryStatisticsAbstractTest {
|
||||
/** Serializable version identifier. */
|
||||
private static final long serialVersionUID = -7379143356784298432L;
|
||||
|
||||
public SummaryStatisticsImplTest(String name) {
|
||||
super(name);
|
||||
/**
|
||||
* Construct an exception with a default message.
|
||||
*/
|
||||
public SingularMatrixException() {
|
||||
super("matrix is singular", null);
|
||||
}
|
||||
|
||||
public static Test suite() {
|
||||
TestSuite suite = new TestSuite(SummaryStatisticsImplTest.class);
|
||||
suite.setName("SummaryStatisticsImpl Tests");
|
||||
return suite;
|
||||
}
|
||||
|
||||
protected SummaryStatistics createSummaryStatistics() {
|
||||
return new SummaryStatisticsImpl();
|
||||
}
|
||||
}
|
@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.commons.math.linear;
|
||||
|
||||
import org.apache.commons.math.ConvergenceException;
|
||||
|
||||
/**
|
||||
* An interface to classes that implement an algorithm to calculate the
|
||||
* Singular Value Decomposition of a real matrix.
|
||||
* <p>The Singular Value Decomposition of matrix A is a set of three matrices:
|
||||
* U, Σ and V such that A = U × Σ × V<sup>T</sup>.
|
||||
* Let A be an m × n matrix, then U is an m × m orthogonal matrix,
|
||||
* Σ is a m × n diagonal matrix with positive diagonal elements,
|
||||
* and V is an n × n orthogonal matrix.</p>
|
||||
* <p>This interface is similar to the class with similar name from the now defunct
|
||||
* <a href="http://math.nist.gov/javanumerics/jama/">JAMA</a> library, with the
|
||||
* following changes:</p>
|
||||
* <ul>
|
||||
* <li><code>solve</code> methods have been added (in the superinterface),</li>
|
||||
* <li>a {@link DecompositionSolver#decompose(RealMatrix) decompose(RealMatrix)}
|
||||
* method has been added (in the superinterface),</li>
|
||||
* <li>a {@link #decompose(RealMatrix, int) decompose(RealMatrix), int)} method
|
||||
* has been added,</li>
|
||||
* <li>a {@link DecompositionSolver#isNonSingular() isNonSingular} method has
|
||||
* been added (in the superinterface),</li>
|
||||
* <li>a {@link DecompositionSolver#getInverse() getInverse} method has been
|
||||
* added (in the superinterface),</li>
|
||||
* <li>the <code>norm2</code> method which has been renamed as {@link #getNorm()
|
||||
* getNorm},</li>
|
||||
* <li>the <code>cond</code> method which has been renamed as {@link
|
||||
* #getConditionNumber() getConditionNumber},</li>
|
||||
* <li>the <code>rank</code> method which has been renamed as {@link #getRank()
|
||||
* getRank}</li>
|
||||
* </ul>
|
||||
* @see <a href="http://mathworld.wolfram.com/SingularValueDecomposition.html">MathWorld</a>
|
||||
* @see <a href="http://en.wikipedia.org/wiki/Singular_value_decomposition">Wikipedia</a>
|
||||
* @version $Revision$ $Date$
|
||||
* @since 2.0
|
||||
*/
|
||||
public interface SingularValueDecomposition extends DecompositionSolver {
|
||||
|
||||
/**
|
||||
* Decompose a matrix to find its largest singular values.
|
||||
* @param matrix matrix to decompose
|
||||
* @param maxSingularValues maximal number of singular values to compute
|
||||
* @exception InvalidMatrixException (wrapping a {@link ConvergenceException}
|
||||
* if algorithm fails to converge
|
||||
*/
|
||||
void decompose(RealMatrix matrix, int maxSingularValues)
|
||||
throws InvalidMatrixException;
|
||||
|
||||
/**
|
||||
* Returns the matrix U of the decomposition.
|
||||
* <p>U is an orthogonal matrix, i.e. its transpose is also its inverse.</p>
|
||||
* @return the U matrix
|
||||
* @exception IllegalStateException if neither {@link
|
||||
* DecompositionSolver#decompose(RealMatrix) decompose} nor {@link
|
||||
* #decompose(RealMatrix, int)} have not been called
|
||||
*/
|
||||
RealMatrix getU() throws IllegalStateException;
|
||||
|
||||
/**
|
||||
* Returns the diagonal matrix Σ of the decomposition.
|
||||
* <p>Σ is a diagonal matrix.</p>
|
||||
* @return the Σ matrix
|
||||
* @exception IllegalStateException if neither {@link
|
||||
* DecompositionSolver#decompose(RealMatrix) decompose} nor {@link
|
||||
* #decompose(RealMatrix, int)} have not been called
|
||||
*/
|
||||
RealMatrix getS() throws IllegalStateException;
|
||||
|
||||
/**
|
||||
* Returns the diagonal elements of the matrix Σ of the decomposition.
|
||||
* @return the diagonal elements of the Σ matrix
|
||||
* @exception IllegalStateException if neither {@link
|
||||
* DecompositionSolver#decompose(RealMatrix) decompose} nor {@link
|
||||
* #decompose(RealMatrix, int)} have not been called
|
||||
*/
|
||||
double[] getSingularValues() throws IllegalStateException;
|
||||
|
||||
/**
|
||||
* Returns the matrix V of the decomposition.
|
||||
* <p>V is an orthogonal matrix, i.e. its transpose is also its inverse.</p>
|
||||
* @return the V matrix (or null if decomposed matrix is singular)
|
||||
* @exception IllegalStateException if neither {@link
|
||||
* DecompositionSolver#decompose(RealMatrix) decompose} nor {@link
|
||||
* #decompose(RealMatrix, int)} have not been called
|
||||
*/
|
||||
RealMatrix getV() throws IllegalStateException;
|
||||
|
||||
/**
|
||||
* Returns the L<sub>2</sub> norm of the matrix.
|
||||
* <p>The L<sub>2</sub> norm is max(|A × u|<sub>2</sub> /
|
||||
* |u|<sub>2</sub>), where |.|<sub>2</sub> denotes the vectorial 2-norm
|
||||
* (i.e. the traditional euclidian norm).</p>
|
||||
* @return norm
|
||||
* @exception IllegalStateException if neither {@link
|
||||
* DecompositionSolver#decompose(RealMatrix) decompose} nor {@link
|
||||
* #decompose(RealMatrix, int)} have not been called
|
||||
*/
|
||||
double getNorm() throws IllegalStateException;
|
||||
|
||||
/**
|
||||
* Return the condition number of the matrix.
|
||||
* @return condition number of the matrix
|
||||
* @exception IllegalStateException if neither {@link
|
||||
* DecompositionSolver#decompose(RealMatrix) decompose} nor {@link
|
||||
* #decompose(RealMatrix, int)} have not been called
|
||||
*/
|
||||
double getConditionNumber() throws IllegalStateException;
|
||||
|
||||
/**
|
||||
* Return the effective numerical matrix rank.
|
||||
* <p>The effective numerical rank is the number of non-negligible
|
||||
* singular values. The threshold used to identify non-negligible
|
||||
* terms is max(m,n) × ulp(s<sub>1</sub>) where ulp(s<sub>1</sub>)
|
||||
* is the least significant bit of the largest singular value.</p>
|
||||
* @return effective numerical matrix rank
|
||||
* @exception IllegalStateException if neither {@link
|
||||
* DecompositionSolver#decompose(RealMatrix) decompose} nor {@link
|
||||
* #decompose(RealMatrix, int)} have not been called
|
||||
*/
|
||||
int getRank() throws IllegalStateException;
|
||||
|
||||
}
|
@ -0,0 +1,280 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.commons.math.linear;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Class transforming a symmetrical matrix to tridiagonal shape.
|
||||
* <p>A symmetrical m × m matrix A can be written as the product of three matrices:
|
||||
* A = Q × T × Q<sup>T</sup> with Q an orthogonal matrix and T a symmetrical
|
||||
* tridiagonal matrix. Both Q and T are m × m matrices.</p>
|
||||
* <p>This implementation only uses the upper part of the matrix, the part below the
|
||||
* diagonal is not accessed at all.</p>
|
||||
* <p>Transformation to tridiagonal shape is often not a goal by itself, but it is
|
||||
* an intermediate step in more general decomposition algorithms like {@link
|
||||
* EigenDecomposition eigen decomposition}. This class is therefore intended for internal
|
||||
* use by the library and is not public. As a consequence of this explicitly limited scope,
|
||||
* many methods directly returns references to internal arrays, not copies.</p>
|
||||
* @version $Revision$ $Date$
|
||||
* @since 2.0
|
||||
*/
|
||||
class TriDiagonalTransformer implements Serializable {
|
||||
|
||||
/** Serializable version identifier. */
|
||||
private static final long serialVersionUID = 8935390784125343332L;
|
||||
|
||||
/** Householder vectors. */
|
||||
private final double householderVectors[][];
|
||||
|
||||
/** Main diagonal. */
|
||||
private final double[] main;
|
||||
|
||||
/** Secondary diagonal. */
|
||||
private final double[] secondary;
|
||||
|
||||
/** Cached value of Q. */
|
||||
private RealMatrix cachedQ;
|
||||
|
||||
/** Cached value of Qt. */
|
||||
private RealMatrix cachedQt;
|
||||
|
||||
/** Cached value of T. */
|
||||
private RealMatrix cachedT;
|
||||
|
||||
/**
|
||||
* Build the transformation to tridiagonal shape of a symmetrical matrix.
|
||||
* <p>The specified matrix is assumed to be symmetrical without any check.
|
||||
* Only the upper triangular part of the matrix is used.</p>
|
||||
* @param matrix the symmetrical matrix to transform.
|
||||
* @exception InvalidMatrixException if matrix is not square
|
||||
*/
|
||||
public TriDiagonalTransformer(RealMatrix matrix)
|
||||
throws InvalidMatrixException {
|
||||
if (!matrix.isSquare()) {
|
||||
throw new NonSquareMatrixException(matrix.getRowDimension(), matrix.getColumnDimension());
|
||||
}
|
||||
|
||||
final int m = matrix.getRowDimension();
|
||||
householderVectors = matrix.getData();
|
||||
main = new double[m];
|
||||
secondary = new double[m - 1];
|
||||
cachedQ = null;
|
||||
cachedQt = null;
|
||||
cachedT = null;
|
||||
|
||||
// transform matrix
|
||||
transform();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the matrix Q of the transform.
|
||||
* <p>Q is an orthogonal matrix, i.e. its transpose is also its inverse.</p>
|
||||
* @return the Q matrix
|
||||
*/
|
||||
public RealMatrix getQ() {
|
||||
if (cachedQ == null) {
|
||||
cachedQ = getQT().transpose();
|
||||
}
|
||||
return cachedQ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the transpose of the matrix Q of the transform.
|
||||
* <p>Q is an orthogonal matrix, i.e. its transpose is also its inverse.</p>
|
||||
* @return the Q matrix
|
||||
*/
|
||||
public RealMatrix getQT() {
|
||||
|
||||
if (cachedQt == null) {
|
||||
|
||||
final int m = householderVectors.length;
|
||||
final double[][] qtData = new double[m][m];
|
||||
|
||||
// build up first part of the matrix by applying Householder transforms
|
||||
for (int k = m - 1; k >= 1; --k) {
|
||||
final double[] hK = householderVectors[k - 1];
|
||||
final double inv = 1.0 / (secondary[k - 1] * hK[k]);
|
||||
qtData[k][k] = 1;
|
||||
if (hK[k] != 0.0) {
|
||||
final double[] qtK = qtData[k];
|
||||
double beta = 1.0 / secondary[k - 1];
|
||||
qtK[k] = 1 + beta * hK[k];
|
||||
for (int i = k + 1; i < m; ++i) {
|
||||
qtK[i] = beta * hK[i];
|
||||
}
|
||||
for (int j = k + 1; j < m; ++j) {
|
||||
final double[] qtJ = qtData[j];
|
||||
beta = 0;
|
||||
for (int i = k + 1; i < m; ++i) {
|
||||
beta += qtJ[i] * hK[i];
|
||||
}
|
||||
beta *= inv;
|
||||
qtJ[k] = beta * hK[k];
|
||||
for (int i = k + 1; i < m; ++i) {
|
||||
qtJ[i] += beta * hK[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
qtData[0][0] = 1;
|
||||
|
||||
// cache the matrix for subsequent calls
|
||||
cachedQt = new RealMatrixImpl(qtData, false);
|
||||
|
||||
}
|
||||
|
||||
// return the cached matrix
|
||||
return cachedQt;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the tridiagonal matrix T of the transform.
|
||||
* @return the T matrix
|
||||
*/
|
||||
public RealMatrix getT() {
|
||||
|
||||
if (cachedT == null) {
|
||||
|
||||
final int m = main.length;
|
||||
double[][] tData = new double[m][m];
|
||||
for (int i = 0; i < m; ++i) {
|
||||
double[] tDataI = tData[i];
|
||||
tDataI[i] = main[i];
|
||||
if (i > 0) {
|
||||
tDataI[i - 1] = secondary[i - 1];
|
||||
}
|
||||
if (i < main.length - 1) {
|
||||
tDataI[i + 1] = secondary[i];
|
||||
}
|
||||
}
|
||||
|
||||
// cache the matrix for subsequent calls
|
||||
cachedT = new RealMatrixImpl(tData, false);
|
||||
|
||||
}
|
||||
|
||||
// return the cached matrix
|
||||
return cachedT;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Householder vectors of the transform.
|
||||
* <p>Note that since this class is only intended for internal use,
|
||||
* it returns directly a reference to its internal arrays, not a copy.</p>
|
||||
* @return the main diagonal elements of the B matrix
|
||||
*/
|
||||
double[][] getHouseholderVectorsRef() {
|
||||
return householderVectors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the main diagonal elements of the matrix T of the transform.
|
||||
* <p>Note that since this class is only intended for internal use,
|
||||
* it returns directly a reference to its internal arrays, not a copy.</p>
|
||||
* @return the main diagonal elements of the T matrix
|
||||
*/
|
||||
double[] getMainDiagonalRef() {
|
||||
return main;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the secondary diagonal elements of the matrix T of the transform.
|
||||
* <p>Note that since this class is only intended for internal use,
|
||||
* it returns directly a reference to its internal arrays, not a copy.</p>
|
||||
* @return the secondary diagonal elements of the T matrix
|
||||
*/
|
||||
double[] getSecondaryDiagonalRef() {
|
||||
return secondary;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform original matrix to tridiagonal form.
|
||||
* <p>Transformation is done using Householder transforms.</p>
|
||||
*/
|
||||
private void transform() {
|
||||
|
||||
final int m = householderVectors.length;
|
||||
final double[] z = new double[m];
|
||||
for (int k = 0; k < m - 1; k++) {
|
||||
|
||||
//zero-out a row and a column simultaneously
|
||||
final double[] hK = householderVectors[k];
|
||||
main[k] = hK[k];
|
||||
double xNormSqr = 0;
|
||||
for (int j = k + 1; j < m; ++j) {
|
||||
final double c = hK[j];
|
||||
xNormSqr += c * c;
|
||||
}
|
||||
final double a = (hK[k + 1] > 0) ? -Math.sqrt(xNormSqr) : Math.sqrt(xNormSqr);
|
||||
secondary[k] = a;
|
||||
if (a != 0.0) {
|
||||
// apply Householder transform from left and right simultaneously
|
||||
|
||||
hK[k + 1] -= a;
|
||||
final double beta = -1 / (a * hK[k + 1]);
|
||||
|
||||
// compute a = beta A v, where v is the Householder vector
|
||||
// this loop is written in such a way
|
||||
// 1) only the upper triangular part of the matrix is accessed
|
||||
// 2) access is cache-friendly for a matrix stored in rows
|
||||
Arrays.fill(z, k + 1, m, 0);
|
||||
for (int i = k + 1; i < m; ++i) {
|
||||
final double[] hI = householderVectors[i];
|
||||
final double hKI = hK[i];
|
||||
double zI = hI[i] * hKI;
|
||||
for (int j = i + 1; j < m; ++j) {
|
||||
final double hIJ = hI[j];
|
||||
zI += hIJ * hK[j];
|
||||
z[j] += hIJ * hKI;
|
||||
}
|
||||
z[i] = beta * (z[i] + zI);
|
||||
}
|
||||
|
||||
// compute gamma = beta vT z / 2
|
||||
double gamma = 0;
|
||||
for (int i = k + 1; i < m; ++i) {
|
||||
gamma += z[i] * hK[i];
|
||||
}
|
||||
gamma *= beta / 2;
|
||||
|
||||
// compute z = z - gamma v
|
||||
for (int i = k + 1; i < m; ++i) {
|
||||
z[i] -= gamma * hK[i];
|
||||
}
|
||||
|
||||
// update matrix: A = A - v zT - z vT
|
||||
// only the upper triangular part of the matrix is updated
|
||||
for (int i = k + 1; i < m; ++i) {
|
||||
final double[] hI = householderVectors[i];
|
||||
for (int j = i; j < m; ++j) {
|
||||
hI[j] -= hK[i] * z[j] + z[i] * hK[j];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
main[m - 1] = householderVectors[m - 1][m - 1];
|
||||
}
|
||||
|
||||
}
|
225
src/java/org/apache/commons/math/ode/AbstractIntegrator.java
Normal file
225
src/java/org/apache/commons/math/ode/AbstractIntegrator.java
Normal file
@ -0,0 +1,225 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.commons.math.ode;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.apache.commons.math.ode.events.CombinedEventsManager;
|
||||
import org.apache.commons.math.ode.events.EventHandler;
|
||||
import org.apache.commons.math.ode.events.EventState;
|
||||
import org.apache.commons.math.ode.sampling.StepHandler;
|
||||
|
||||
/**
|
||||
* Base class managing common boilerplate for all integrators.
|
||||
* @version $Revision$ $Date$
|
||||
* @since 2.0
|
||||
*/
|
||||
public abstract class AbstractIntegrator implements FirstOrderIntegrator {
|
||||
|
||||
/** Serializable version identifier. */
|
||||
private static final long serialVersionUID = 5771479854166853494L;
|
||||
|
||||
/** Name of the method. */
|
||||
private final String name;
|
||||
|
||||
/** Step handler. */
|
||||
protected Collection<StepHandler> stepHandlers;
|
||||
|
||||
/** Current step start time. */
|
||||
protected double stepStart;
|
||||
|
||||
/** Current stepsize. */
|
||||
protected double stepSize;
|
||||
|
||||
/** Events handlers manager. */
|
||||
protected CombinedEventsManager eventsHandlersManager;
|
||||
|
||||
/** Build an instance.
|
||||
* @param name name of the method
|
||||
*/
|
||||
public AbstractIntegrator(final String name) {
|
||||
this.name = name;
|
||||
stepHandlers = new ArrayList<StepHandler>();
|
||||
stepStart = Double.NaN;
|
||||
stepSize = Double.NaN;
|
||||
eventsHandlersManager = new CombinedEventsManager();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public void addStepHandler(final StepHandler handler) {
|
||||
stepHandlers.add(handler);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public Collection<StepHandler> getStepHandlers() {
|
||||
return Collections.unmodifiableCollection(stepHandlers);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public void clearStepHandlers() {
|
||||
stepHandlers.clear();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public void addEventHandler(final EventHandler function,
|
||||
final double maxCheckInterval,
|
||||
final double convergence,
|
||||
final int maxIterationCount) {
|
||||
eventsHandlersManager.addEventHandler(function, maxCheckInterval,
|
||||
convergence, maxIterationCount);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public Collection<EventHandler> getEventHandlers() {
|
||||
return eventsHandlersManager.getEventsHandlers();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public void clearEventHandlers() {
|
||||
eventsHandlersManager.clearEventsHandlers();
|
||||
}
|
||||
|
||||
/** Check if one of the step handlers requires dense output.
|
||||
* @return true if one of the step handlers requires dense output
|
||||
*/
|
||||
protected boolean requiresDenseOutput() {
|
||||
for (StepHandler handler : stepHandlers) {
|
||||
if (handler.requiresDenseOutput()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public double getCurrentStepStart() {
|
||||
return stepStart;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public double getCurrentSignedStepsize() {
|
||||
return stepSize;
|
||||
}
|
||||
|
||||
/** Perform some sanity checks on the integration parameters.
|
||||
* @param equations differential equations set
|
||||
* @param t0 start time
|
||||
* @param y0 state vector at t0
|
||||
* @param t target time for the integration
|
||||
* @param y placeholder where to put the state vector
|
||||
* @exception IntegratorException if some inconsistency is detected
|
||||
*/
|
||||
protected void sanityChecks(final FirstOrderDifferentialEquations equations,
|
||||
final double t0, final double[] y0,
|
||||
final double t, final double[] y)
|
||||
throws IntegratorException {
|
||||
|
||||
if (equations.getDimension() != y0.length) {
|
||||
throw new IntegratorException("dimensions mismatch: ODE problem has dimension {0}," +
|
||||
" initial state vector has dimension {1}",
|
||||
new Object[] {
|
||||
Integer.valueOf(equations.getDimension()),
|
||||
Integer.valueOf(y0.length)
|
||||
});
|
||||
}
|
||||
|
||||
if (equations.getDimension() != y.length) {
|
||||
throw new IntegratorException("dimensions mismatch: ODE problem has dimension {0}," +
|
||||
" final state vector has dimension {1}",
|
||||
new Object[] {
|
||||
Integer.valueOf(equations.getDimension()),
|
||||
Integer.valueOf(y.length)
|
||||
});
|
||||
}
|
||||
|
||||
if (Math.abs(t - t0) <= 1.0e-12 * Math.max(Math.abs(t0), Math.abs(t))) {
|
||||
throw new IntegratorException("too small integration interval: length = {0}",
|
||||
new Object[] {
|
||||
Double.valueOf(Math.abs(t - t0))
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** Add an event handler for end time checking.
|
||||
* <p>This method can be used to simplify handling of integration end time.
|
||||
* It leverages the nominal stop condition with the exceptional stop
|
||||
* conditions.</p>
|
||||
* @param startTime integration start time
|
||||
* @param endTime desired end time
|
||||
* @param manager manager containing the user-defined handlers
|
||||
* @return a new manager containing all the user-defined handlers plus a
|
||||
* dedicated manager triggering a stop event at entTime
|
||||
*/
|
||||
protected CombinedEventsManager addEndTimeChecker(final double startTime,
|
||||
final double endTime,
|
||||
final CombinedEventsManager manager) {
|
||||
CombinedEventsManager newManager = new CombinedEventsManager();
|
||||
for (final EventState state : manager.getEventsStates()) {
|
||||
newManager.addEventHandler(state.getEventHandler(),
|
||||
state.getMaxCheckInterval(),
|
||||
state.getConvergence(),
|
||||
state.getMaxIterationCount());
|
||||
}
|
||||
newManager.addEventHandler(new EndTimeChecker(endTime),
|
||||
Double.POSITIVE_INFINITY,
|
||||
Math.ulp(Math.max(Math.abs(startTime), Math.abs(endTime))),
|
||||
100);
|
||||
return newManager;
|
||||
}
|
||||
|
||||
/** Specialized event handler to stop integration. */
|
||||
private static class EndTimeChecker implements EventHandler {
|
||||
|
||||
/** Serializable version identifier. */
|
||||
private static final long serialVersionUID = -5211782540446301964L;
|
||||
|
||||
/** DEsiredt end time. */
|
||||
private final double endTime;
|
||||
|
||||
/** Build an instance.
|
||||
* @param endTime desired time
|
||||
*/
|
||||
public EndTimeChecker(final double endTime) {
|
||||
this.endTime = endTime;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public int eventOccurred(double t, double[] y) {
|
||||
return STOP;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public double g(double t, double[] y) {
|
||||
return t - endTime;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public void resetState(double t, double[] y) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,109 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.commons.math.ode;
|
||||
|
||||
/**
|
||||
* This class implements a step interpolator for the classical fourth
|
||||
* order Runge-Kutta integrator.
|
||||
*
|
||||
* <p>This interpolator allows to compute dense output inside the last
|
||||
* step computed. The interpolation equation is consistent with the
|
||||
* integration scheme :
|
||||
|
||||
* <pre>
|
||||
* y(t_n + theta h) = y (t_n + h)
|
||||
* + (1 - theta) (h/6) [ (-4 theta^2 + 5 theta - 1) y'_1
|
||||
* +(4 theta^2 - 2 theta - 2) (y'_2 + y'_3)
|
||||
* -(4 theta^2 + theta + 1) y'_4
|
||||
* ]
|
||||
* </pre>
|
||||
*
|
||||
* where theta belongs to [0 ; 1] and where y'_1 to y'_4 are the four
|
||||
* evaluations of the derivatives already computed during the
|
||||
* step.</p>
|
||||
*
|
||||
* @see ClassicalRungeKuttaIntegrator
|
||||
* @version $Revision$ $Date$
|
||||
* @since 1.2
|
||||
*/
|
||||
|
||||
class ClassicalRungeKuttaStepInterpolator
|
||||
extends RungeKuttaStepInterpolator {
|
||||
|
||||
/** Simple constructor.
|
||||
* This constructor builds an instance that is not usable yet, the
|
||||
* {@link RungeKuttaStepInterpolator#reinitialize} method should be
|
||||
* called before using the instance in order to initialize the
|
||||
* internal arrays. This constructor is used only in order to delay
|
||||
* the initialization in some cases. The {@link RungeKuttaIntegrator}
|
||||
* class uses the prototyping design pattern to create the step
|
||||
* interpolators by cloning an uninitialized model and latter initializing
|
||||
* the copy.
|
||||
*/
|
||||
public ClassicalRungeKuttaStepInterpolator() {
|
||||
}
|
||||
|
||||
/** Copy constructor.
|
||||
* @param interpolator interpolator to copy from. The copy is a deep
|
||||
* copy: its arrays are separated from the original arrays of the
|
||||
* instance
|
||||
*/
|
||||
public ClassicalRungeKuttaStepInterpolator(ClassicalRungeKuttaStepInterpolator interpolator) {
|
||||
super(interpolator);
|
||||
}
|
||||
|
||||
/** Really copy the finalized instance.
|
||||
* @return a copy of the finalized instance
|
||||
*/
|
||||
protected StepInterpolator doCopy() {
|
||||
return new ClassicalRungeKuttaStepInterpolator(this);
|
||||
}
|
||||
|
||||
/** Compute the state at the interpolated time.
|
||||
* This is the main processing method that should be implemented by
|
||||
* the derived classes to perform the interpolation.
|
||||
* @param theta normalized interpolation abscissa within the step
|
||||
* (theta is zero at the previous time step and one at the current time step)
|
||||
* @param oneMinusThetaH time gap between the interpolated time and
|
||||
* the current time
|
||||
* @throws DerivativeException this exception is propagated to the caller if the
|
||||
* underlying user function triggers one
|
||||
*/
|
||||
protected void computeInterpolatedState(double theta,
|
||||
double oneMinusThetaH)
|
||||
throws DerivativeException {
|
||||
|
||||
double fourTheta = 4 * theta;
|
||||
double s = oneMinusThetaH / 6.0;
|
||||
double coeff1 = s * ((-fourTheta + 5) * theta - 1);
|
||||
double coeff23 = s * (( fourTheta - 2) * theta - 2);
|
||||
double coeff4 = s * ((-fourTheta - 1) * theta - 1);
|
||||
|
||||
for (int i = 0; i < interpolatedState.length; ++i) {
|
||||
interpolatedState[i] = currentState[i] +
|
||||
coeff1 * yDotK[0][i] +
|
||||
coeff23 * (yDotK[1][i] + yDotK[2][i]) +
|
||||
coeff4 * yDotK[3][i];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** Serializable version identifier */
|
||||
private static final long serialVersionUID = -6576285612589783992L;
|
||||
|
||||
}
|
@ -18,10 +18,14 @@
|
||||
package org.apache.commons.math.ode;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.apache.commons.math.MathRuntimeException;
|
||||
import org.apache.commons.math.ode.nonstiff.AdaptiveStepsizeIntegrator;
|
||||
import org.apache.commons.math.ode.sampling.StepHandler;
|
||||
import org.apache.commons.math.ode.sampling.StepInterpolator;
|
||||
|
||||
/**
|
||||
* This class stores all information provided by an ODE integrator
|
||||
* during the integration process and build a continuous model of the
|
||||
@ -45,14 +49,14 @@ import java.io.Serializable;
|
||||
* get the model value at any time or to navigate through the
|
||||
* data).</p>
|
||||
*
|
||||
* <p>If problem modelization is done with several separate
|
||||
* <p>If problem modeling is done with several separate
|
||||
* integration phases for contiguous intervals, the same
|
||||
* ContinuousOutputModel can be used as step handler for all
|
||||
* integration phases as long as they are performed in order and in
|
||||
* the same direction. As an example, one can extrapolate the
|
||||
* trajectory of a satellite with one model (i.e. one set of
|
||||
* differential equations) up to the beginning of a maneuver, use
|
||||
* another more complex model including thrusters modelization and
|
||||
* another more complex model including thrusters modeling and
|
||||
* accurate attitude control during the maneuver, and revert to the
|
||||
* first model after the end of the maneuver. If the same continuous
|
||||
* output model handles the steps of all integration phases, the user
|
||||
@ -86,7 +90,7 @@ public class ContinuousOutputModel
|
||||
* Build an empty continuous output model.
|
||||
*/
|
||||
public ContinuousOutputModel() {
|
||||
steps = new ArrayList();
|
||||
steps = new ArrayList<StepInterpolator>();
|
||||
reset();
|
||||
}
|
||||
|
||||
@ -98,7 +102,7 @@ public class ContinuousOutputModel
|
||||
* compatible with the instance (dimension of the state vector,
|
||||
* propagation direction, hole between the dates)
|
||||
*/
|
||||
public void append(ContinuousOutputModel model)
|
||||
public void append(final ContinuousOutputModel model)
|
||||
throws DerivativeException {
|
||||
|
||||
if (model.steps.size() == 0) {
|
||||
@ -118,19 +122,19 @@ public class ContinuousOutputModel
|
||||
throw new IllegalArgumentException("propagation direction mismatch");
|
||||
}
|
||||
|
||||
StepInterpolator lastInterpolator = (StepInterpolator) steps.get(index);
|
||||
double current = lastInterpolator.getCurrentTime();
|
||||
double previous = lastInterpolator.getPreviousTime();
|
||||
double step = current - previous;
|
||||
double gap = model.getInitialTime() - current;
|
||||
final StepInterpolator lastInterpolator = (StepInterpolator) steps.get(index);
|
||||
final double current = lastInterpolator.getCurrentTime();
|
||||
final double previous = lastInterpolator.getPreviousTime();
|
||||
final double step = current - previous;
|
||||
final double gap = model.getInitialTime() - current;
|
||||
if (Math.abs(gap) > 1.0e-3 * Math.abs(step)) {
|
||||
throw new IllegalArgumentException("hole between time ranges");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (Iterator iter = model.steps.iterator(); iter.hasNext(); ) {
|
||||
steps.add(((AbstractStepInterpolator) iter.next()).copy());
|
||||
for (StepInterpolator interpolator : model.steps) {
|
||||
steps.add(interpolator.copy());
|
||||
}
|
||||
|
||||
index = steps.size() - 1;
|
||||
@ -168,20 +172,18 @@ public class ContinuousOutputModel
|
||||
* @throws DerivativeException this exception is propagated to the
|
||||
* caller if the underlying user function triggers one
|
||||
*/
|
||||
public void handleStep(StepInterpolator interpolator, boolean isLast)
|
||||
public void handleStep(final StepInterpolator interpolator, final boolean isLast)
|
||||
throws DerivativeException {
|
||||
|
||||
AbstractStepInterpolator ai = (AbstractStepInterpolator) interpolator;
|
||||
|
||||
if (steps.size() == 0) {
|
||||
initialTime = interpolator.getPreviousTime();
|
||||
forward = interpolator.isForward();
|
||||
}
|
||||
|
||||
steps.add(ai.copy());
|
||||
steps.add(interpolator.copy());
|
||||
|
||||
if (isLast) {
|
||||
finalTime = ai.getCurrentTime();
|
||||
finalTime = interpolator.getCurrentTime();
|
||||
index = steps.size() - 1;
|
||||
}
|
||||
|
||||
@ -210,7 +212,7 @@ public class ContinuousOutputModel
|
||||
* @return interpolation point time
|
||||
*/
|
||||
public double getInterpolatedTime() {
|
||||
return ((StepInterpolator) steps.get(index)).getInterpolatedTime();
|
||||
return steps.get(index).getInterpolatedTime();
|
||||
}
|
||||
|
||||
/** Set the time of the interpolated point.
|
||||
@ -225,16 +227,16 @@ public class ContinuousOutputModel
|
||||
* near the interval endpoints.</p>
|
||||
* @param time time of the interpolated point
|
||||
*/
|
||||
public void setInterpolatedTime(double time) {
|
||||
public void setInterpolatedTime(final double time) {
|
||||
|
||||
try {
|
||||
// initialize the search with the complete steps table
|
||||
int iMin = 0;
|
||||
StepInterpolator sMin = (StepInterpolator) steps.get(iMin);
|
||||
final StepInterpolator sMin = steps.get(iMin);
|
||||
double tMin = 0.5 * (sMin.getPreviousTime() + sMin.getCurrentTime());
|
||||
|
||||
int iMax = steps.size() - 1;
|
||||
StepInterpolator sMax = (StepInterpolator) steps.get(iMax);
|
||||
final StepInterpolator sMax = steps.get(iMax);
|
||||
double tMax = 0.5 * (sMax.getPreviousTime() + sMax.getCurrentTime());
|
||||
|
||||
// handle points outside of the integration interval
|
||||
@ -254,8 +256,8 @@ public class ContinuousOutputModel
|
||||
while (iMax - iMin > 5) {
|
||||
|
||||
// use the last estimated index as the splitting index
|
||||
StepInterpolator si = (StepInterpolator) steps.get(index);
|
||||
int location = locatePoint(time, si);
|
||||
final StepInterpolator si = steps.get(index);
|
||||
final int location = locatePoint(time, si);
|
||||
if (location < 0) {
|
||||
iMax = index;
|
||||
tMax = 0.5 * (si.getPreviousTime() + si.getCurrentTime());
|
||||
@ -269,9 +271,9 @@ public class ContinuousOutputModel
|
||||
}
|
||||
|
||||
// compute a new estimate of the index in the reduced table slice
|
||||
int iMed = (iMin + iMax) / 2;
|
||||
StepInterpolator sMed = (StepInterpolator) steps.get(iMed);
|
||||
double tMed = 0.5 * (sMed.getPreviousTime() + sMed.getCurrentTime());
|
||||
final int iMed = (iMin + iMax) / 2;
|
||||
final StepInterpolator sMed = steps.get(iMed);
|
||||
final double tMed = 0.5 * (sMed.getPreviousTime() + sMed.getCurrentTime());
|
||||
|
||||
if ((Math.abs(tMed - tMin) < 1e-6) || (Math.abs(tMax - tMed) < 1e-6)) {
|
||||
// too close to the bounds, we estimate using a simple dichotomy
|
||||
@ -280,22 +282,22 @@ public class ContinuousOutputModel
|
||||
// estimate the index using a reverse quadratic polynom
|
||||
// (reverse means we have i = P(t), thus allowing to simply
|
||||
// compute index = P(time) rather than solving a quadratic equation)
|
||||
double d12 = tMax - tMed;
|
||||
double d23 = tMed - tMin;
|
||||
double d13 = tMax - tMin;
|
||||
double dt1 = time - tMax;
|
||||
double dt2 = time - tMed;
|
||||
double dt3 = time - tMin;
|
||||
double iLagrange = ((dt2 * dt3 * d23) * iMax -
|
||||
(dt1 * dt3 * d13) * iMed +
|
||||
(dt1 * dt2 * d12) * iMin) /
|
||||
(d12 * d23 * d13);
|
||||
final double d12 = tMax - tMed;
|
||||
final double d23 = tMed - tMin;
|
||||
final double d13 = tMax - tMin;
|
||||
final double dt1 = time - tMax;
|
||||
final double dt2 = time - tMed;
|
||||
final double dt3 = time - tMin;
|
||||
final double iLagrange = ((dt2 * dt3 * d23) * iMax -
|
||||
(dt1 * dt3 * d13) * iMed +
|
||||
(dt1 * dt2 * d12) * iMin) /
|
||||
(d12 * d23 * d13);
|
||||
index = (int) Math.rint(iLagrange);
|
||||
}
|
||||
|
||||
// force the next size reduction to be at least one tenth
|
||||
int low = Math.max(iMin + 1, (9 * iMin + iMax) / 10);
|
||||
int high = Math.min(iMax - 1, (iMin + 9 * iMax) / 10);
|
||||
final int low = Math.max(iMin + 1, (9 * iMin + iMax) / 10);
|
||||
final int high = Math.min(iMax - 1, (iMin + 9 * iMax) / 10);
|
||||
if (index < low) {
|
||||
index = low;
|
||||
} else if (index > high) {
|
||||
@ -306,18 +308,14 @@ public class ContinuousOutputModel
|
||||
|
||||
// now the table slice is very small, we perform an iterative search
|
||||
index = iMin;
|
||||
while ((index <= iMax) &&
|
||||
(locatePoint(time, (StepInterpolator) steps.get(index)) > 0)) {
|
||||
while ((index <= iMax) && (locatePoint(time, steps.get(index)) > 0)) {
|
||||
++index;
|
||||
}
|
||||
|
||||
StepInterpolator si = (StepInterpolator) steps.get(index);
|
||||
|
||||
si.setInterpolatedTime(time);
|
||||
steps.get(index).setInterpolatedTime(time);
|
||||
|
||||
} catch (DerivativeException de) {
|
||||
throw new RuntimeException("unexpected DerivativeException caught: " +
|
||||
de.getMessage());
|
||||
throw new MathRuntimeException("unexpected exception caught", null, de);
|
||||
}
|
||||
|
||||
}
|
||||
@ -327,7 +325,7 @@ public class ContinuousOutputModel
|
||||
* @return state vector at time {@link #getInterpolatedTime}
|
||||
*/
|
||||
public double[] getInterpolatedState() {
|
||||
return ((StepInterpolator) steps.get(index)).getInterpolatedState();
|
||||
return steps.get(index).getInterpolatedState();
|
||||
}
|
||||
|
||||
/** Compare a step interval and a double.
|
||||
@ -337,7 +335,7 @@ public class ContinuousOutputModel
|
||||
* the interval, and +1 if it is after the interval, according to
|
||||
* the interval direction
|
||||
*/
|
||||
private int locatePoint(double time, StepInterpolator interval) {
|
||||
private int locatePoint(final double time, final StepInterpolator interval) {
|
||||
if (forward) {
|
||||
if (time < interval.getPreviousTime()) {
|
||||
return -1;
|
||||
@ -369,9 +367,9 @@ public class ContinuousOutputModel
|
||||
private int index;
|
||||
|
||||
/** Steps table. */
|
||||
private List steps;
|
||||
private List<StepInterpolator> steps;
|
||||
|
||||
/** Serializable version identifier */
|
||||
private static final long serialVersionUID = 2259286184268533249L;
|
||||
private static final long serialVersionUID = -1417964919405031606L;
|
||||
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ import org.apache.commons.math.MathException;
|
||||
|
||||
/**
|
||||
* This exception is made available to users to report
|
||||
* the error conditions that are trigegred while computing
|
||||
* the error conditions that are triggered while computing
|
||||
* the differential equations.
|
||||
* @version $Revision$ $Date$
|
||||
* @since 1.2
|
||||
@ -34,14 +34,14 @@ public class DerivativeException
|
||||
* @param specifier format specifier (to be translated)
|
||||
* @param parts to insert in the format (no translation)
|
||||
*/
|
||||
public DerivativeException(String specifier, String[] parts) {
|
||||
public DerivativeException(final String specifier, final Object[] parts) {
|
||||
super(specifier, parts);
|
||||
}
|
||||
|
||||
/** Build an instance from an underlying cause.
|
||||
* @param cause cause for the exception
|
||||
*/
|
||||
public DerivativeException(Throwable cause) {
|
||||
public DerivativeException(final Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
|
@ -56,11 +56,14 @@ package org.apache.commons.math.ode;
|
||||
public class FirstOrderConverter
|
||||
implements FirstOrderDifferentialEquations {
|
||||
|
||||
/** Serializable version identifier. */
|
||||
private static final long serialVersionUID = -8233657110042144146L;
|
||||
|
||||
/** Simple constructor.
|
||||
* Build a converter around a second order equations set.
|
||||
* @param equations second order equations set to convert
|
||||
*/
|
||||
public FirstOrderConverter (SecondOrderDifferentialEquations equations) {
|
||||
public FirstOrderConverter (final SecondOrderDifferentialEquations equations) {
|
||||
this.equations = equations;
|
||||
dimension = equations.getDimension();
|
||||
z = new double[dimension];
|
||||
@ -84,8 +87,8 @@ public class FirstOrderConverter
|
||||
* @throws DerivativeException this exception is propagated to the caller if the
|
||||
* underlying user function triggers one
|
||||
*/
|
||||
public void computeDerivatives(double t, double[] y, double[] yDot)
|
||||
throws DerivativeException {
|
||||
public void computeDerivatives(final double t, final double[] y, final double[] yDot)
|
||||
throws DerivativeException {
|
||||
|
||||
// split the state vector in two
|
||||
System.arraycopy(y, 0, z, 0, dimension);
|
||||
|
@ -17,6 +17,8 @@
|
||||
|
||||
package org.apache.commons.math.ode;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/** This interface represents a first order differential equations set.
|
||||
*
|
||||
* <p>This interface should be implemented by all real first order
|
||||
@ -44,7 +46,7 @@ package org.apache.commons.math.ode;
|
||||
* @since 1.2
|
||||
*/
|
||||
|
||||
public interface FirstOrderDifferentialEquations {
|
||||
public interface FirstOrderDifferentialEquations extends Serializable {
|
||||
|
||||
/** Get the dimension of the problem.
|
||||
* @return dimension of the problem
|
||||
|
@ -17,6 +17,9 @@
|
||||
|
||||
package org.apache.commons.math.ode;
|
||||
|
||||
import org.apache.commons.math.ode.events.EventHandler;
|
||||
import org.apache.commons.math.ode.sampling.StepHandler;
|
||||
|
||||
/** This interface represents a first order integrator for
|
||||
* differential equations.
|
||||
|
||||
@ -27,43 +30,12 @@ package org.apache.commons.math.ode;
|
||||
*
|
||||
* @see FirstOrderDifferentialEquations
|
||||
* @see StepHandler
|
||||
* @see SwitchingFunction
|
||||
* @see EventHandler
|
||||
* @version $Revision$ $Date$
|
||||
* @since 1.2
|
||||
*/
|
||||
|
||||
public interface FirstOrderIntegrator {
|
||||
|
||||
/** Get the name of the method.
|
||||
* @return name of the method
|
||||
*/
|
||||
public String getName();
|
||||
|
||||
/** Set the step handler for this integrator.
|
||||
* The handler will be called by the integrator for each accepted
|
||||
* step.
|
||||
* @param handler handler for the accepted steps
|
||||
*/
|
||||
public void setStepHandler (StepHandler handler);
|
||||
|
||||
/** Get the step handler for this integrator.
|
||||
* @return the step handler for this integrator
|
||||
*/
|
||||
public StepHandler getStepHandler();
|
||||
|
||||
/** Add a switching function to the integrator.
|
||||
* @param function switching function
|
||||
* @param maxCheckInterval maximal time interval between switching
|
||||
* function checks (this interval prevents missing sign changes in
|
||||
* case the integration steps becomes very large)
|
||||
* @param convergence convergence threshold in the event time search
|
||||
* @param maxIterationCount upper limit of the iteration count in
|
||||
* the event time search
|
||||
*/
|
||||
public void addSwitchingFunction(SwitchingFunction function,
|
||||
double maxCheckInterval,
|
||||
double convergence,
|
||||
int maxIterationCount);
|
||||
public interface FirstOrderIntegrator extends ODEIntegrator {
|
||||
|
||||
/** Integrate the differential equations up to the given time.
|
||||
* <p>This method solves an Initial Value Problem (IVP).</p>
|
||||
@ -77,35 +49,15 @@ public interface FirstOrderIntegrator {
|
||||
* (can be set to a value smaller than <code>t0</code> for backward integration)
|
||||
* @param y placeholder where to put the state vector at each successful
|
||||
* step (and hence at the end of integration), can be the same object as y0
|
||||
* @return stop time, will be the same as target time if integration reached its
|
||||
* target, but may be different if some {@link EventHandler} stops it at some point.
|
||||
* @throws IntegratorException if the integrator cannot perform integration
|
||||
* @throws DerivativeException this exception is propagated to the caller if
|
||||
* the underlying user function triggers one
|
||||
*/
|
||||
public void integrate (FirstOrderDifferentialEquations equations,
|
||||
double t0, double[] y0,
|
||||
double t, double[] y)
|
||||
public double integrate (FirstOrderDifferentialEquations equations,
|
||||
double t0, double[] y0,
|
||||
double t, double[] y)
|
||||
throws DerivativeException, IntegratorException;
|
||||
|
||||
/** Get the current value of the step start time t<sub>i</sub>.
|
||||
* <p>This method can be called during integration (typically by
|
||||
* the object implementing the {@link FirstOrderDifferentialEquations
|
||||
* differential equations} problem) if the value of the current step that
|
||||
* is attempted is needed.</p>
|
||||
* <p>The result is undefined if the method is called outside of
|
||||
* calls to {@link #integrate}</p>
|
||||
* @return current value of the step start time t<sub>i</sub>
|
||||
*/
|
||||
public double getCurrentStepStart();
|
||||
|
||||
/** Get the current signed value of the integration stepsize.
|
||||
* <p>This method can be called during integration (typically by
|
||||
* the object implementing the {@link FirstOrderDifferentialEquations
|
||||
* differential equations} problem) if the signed value of the current stepsize
|
||||
* that is tried is needed.</p>
|
||||
* <p>The result is undefined if the method is called outside of
|
||||
* calls to {@link #integrate}</p>
|
||||
* @return current signed value of the stepsize
|
||||
*/
|
||||
public double getCurrentSignedStepsize();
|
||||
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ public class IntegratorException
|
||||
* @param specifier format specifier (to be translated)
|
||||
* @param parts to insert in the format (no translation)
|
||||
*/
|
||||
public IntegratorException(String specifier, Object[] parts) {
|
||||
public IntegratorException(final String specifier, final Object[] parts) {
|
||||
super(specifier, parts);
|
||||
}
|
||||
|
||||
@ -41,7 +41,7 @@ public class IntegratorException
|
||||
* Create an exception with a given root cause.
|
||||
* @param cause the exception or error that caused this exception to be thrown
|
||||
*/
|
||||
public IntegratorException(Throwable cause) {
|
||||
public IntegratorException(final Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
|
117
src/java/org/apache/commons/math/ode/ODEIntegrator.java
Normal file
117
src/java/org/apache/commons/math/ode/ODEIntegrator.java
Normal file
@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.commons.math.ode;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.apache.commons.math.ode.events.EventHandler;
|
||||
import org.apache.commons.math.ode.sampling.StepHandler;
|
||||
|
||||
/**
|
||||
* This interface defines the common parts shared by integrators
|
||||
* for first and second order differential equations.
|
||||
* @see FirstOrderIntegrator
|
||||
* @see SecondOrderIntegrator
|
||||
* @version $Revision$ $Date$
|
||||
* @since 2.0
|
||||
*/
|
||||
public interface ODEIntegrator extends Serializable {
|
||||
|
||||
/** Get the name of the method.
|
||||
* @return name of the method
|
||||
*/
|
||||
String getName();
|
||||
|
||||
/** Add a step handler to this integrator.
|
||||
* <p>The handler will be called by the integrator for each accepted
|
||||
* step.</p>
|
||||
* @param handler handler for the accepted steps
|
||||
* @see #getStepHandlers()
|
||||
* @see #clearStepHandlers()
|
||||
* @since 2.0
|
||||
*/
|
||||
void addStepHandler(StepHandler handler);
|
||||
|
||||
/** Get all the step handlers that have been added to the integrator.
|
||||
* @return an unmodifiable collection of the added events handlers
|
||||
* @see #addStepHandler(StepHandler)
|
||||
* @see #clearStepHandlers()
|
||||
* @since 2.0
|
||||
*/
|
||||
Collection<StepHandler> getStepHandlers();
|
||||
|
||||
/** Remove all the step handlers that have been added to the integrator.
|
||||
* @see #addStepHandler(StepHandler)
|
||||
* @see #getStepHandlers()
|
||||
* @since 2.0
|
||||
*/
|
||||
void clearStepHandlers();
|
||||
|
||||
/** Add an event handler to the integrator.
|
||||
* @param handler event handler
|
||||
* @param maxCheckInterval maximal time interval between switching
|
||||
* function checks (this interval prevents missing sign changes in
|
||||
* case the integration steps becomes very large)
|
||||
* @param convergence convergence threshold in the event time search
|
||||
* @param maxIterationCount upper limit of the iteration count in
|
||||
* the event time search
|
||||
* @see #getEventHandlers()
|
||||
* @see #clearEventHandlers()
|
||||
*/
|
||||
void addEventHandler(EventHandler handler,
|
||||
double maxCheckInterval,
|
||||
double convergence,
|
||||
int maxIterationCount);
|
||||
|
||||
/** Get all the event handlers that have been added to the integrator.
|
||||
* @return an unmodifiable collection of the added events handlers
|
||||
* @see #addEventHandler(EventHandler, double, double, int)
|
||||
* @see #clearEventHandlers()
|
||||
*/
|
||||
Collection<EventHandler> getEventHandlers();
|
||||
|
||||
/** Remove all the event handlers that have been added to the integrator.
|
||||
* @see #addEventHandler(EventHandler, double, double, int)
|
||||
* @see #getEventHandlers()
|
||||
*/
|
||||
void clearEventHandlers();
|
||||
|
||||
/** Get the current value of the step start time t<sub>i</sub>.
|
||||
* <p>This method can be called during integration (typically by
|
||||
* the object implementing the {@link FirstOrderDifferentialEquations
|
||||
* differential equations} problem) if the value of the current step that
|
||||
* is attempted is needed.</p>
|
||||
* <p>The result is undefined if the method is called outside of
|
||||
* calls to {@link #integrate}</p>
|
||||
* @return current value of the step start time t<sub>i</sub>
|
||||
*/
|
||||
double getCurrentStepStart();
|
||||
|
||||
/** Get the current signed value of the integration stepsize.
|
||||
* <p>This method can be called during integration (typically by
|
||||
* the object implementing the {@link FirstOrderDifferentialEquations
|
||||
* differential equations} problem) if the signed value of the current stepsize
|
||||
* that is tried is needed.</p>
|
||||
* <p>The result is undefined if the method is called outside of
|
||||
* calls to {@link #integrate}</p>
|
||||
* @return current signed value of the stepsize
|
||||
*/
|
||||
double getCurrentSignedStepsize();
|
||||
|
||||
}
|
@ -1,331 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.commons.math.ode;
|
||||
|
||||
/**
|
||||
* This class implements the common part of all fixed step Runge-Kutta
|
||||
* integrators for Ordinary Differential Equations.
|
||||
*
|
||||
* <p>These methods are explicit Runge-Kutta methods, their Butcher
|
||||
* arrays are as follows :
|
||||
* <pre>
|
||||
* 0 |
|
||||
* c2 | a21
|
||||
* c3 | a31 a32
|
||||
* ... | ...
|
||||
* cs | as1 as2 ... ass-1
|
||||
* |--------------------------
|
||||
* | b1 b2 ... bs-1 bs
|
||||
* </pre>
|
||||
* </p>
|
||||
*
|
||||
* @see EulerIntegrator
|
||||
* @see ClassicalRungeKuttaIntegrator
|
||||
* @see GillIntegrator
|
||||
* @see MidpointIntegrator
|
||||
* @version $Revision$ $Date$
|
||||
* @since 1.2
|
||||
*/
|
||||
|
||||
public abstract class RungeKuttaIntegrator
|
||||
implements FirstOrderIntegrator {
|
||||
|
||||
/** Simple constructor.
|
||||
* Build a Runge-Kutta integrator with the given
|
||||
* step. The default step handler does nothing.
|
||||
* @param c time steps from Butcher array (without the first zero)
|
||||
* @param a internal weights from Butcher array (without the first empty row)
|
||||
* @param b propagation weights for the high order method from Butcher array
|
||||
* @param prototype prototype of the step interpolator to use
|
||||
* @param step integration step
|
||||
*/
|
||||
protected RungeKuttaIntegrator(double[] c, double[][] a, double[] b,
|
||||
RungeKuttaStepInterpolator prototype,
|
||||
double step) {
|
||||
this.c = c;
|
||||
this.a = a;
|
||||
this.b = b;
|
||||
this.prototype = prototype;
|
||||
this.step = step;
|
||||
handler = DummyStepHandler.getInstance();
|
||||
switchesHandler = new SwitchingFunctionsHandler();
|
||||
resetInternalState();
|
||||
}
|
||||
|
||||
/** Get the name of the method.
|
||||
* @return name of the method
|
||||
*/
|
||||
public abstract String getName();
|
||||
|
||||
/** Set the step handler for this integrator.
|
||||
* The handler will be called by the integrator for each accepted
|
||||
* step.
|
||||
* @param handler handler for the accepted steps
|
||||
*/
|
||||
public void setStepHandler (StepHandler handler) {
|
||||
this.handler = handler;
|
||||
}
|
||||
|
||||
/** Get the step handler for this integrator.
|
||||
* @return the step handler for this integrator
|
||||
*/
|
||||
public StepHandler getStepHandler() {
|
||||
return handler;
|
||||
}
|
||||
|
||||
/** Add a switching function to the integrator.
|
||||
* @param function switching function
|
||||
* @param maxCheckInterval maximal time interval between switching
|
||||
* function checks (this interval prevents missing sign changes in
|
||||
* case the integration steps becomes very large)
|
||||
* @param convergence convergence threshold in the event time search
|
||||
* @param maxIterationCount upper limit of the iteration count in
|
||||
* the event time search
|
||||
*/
|
||||
public void addSwitchingFunction(SwitchingFunction function,
|
||||
double maxCheckInterval,
|
||||
double convergence,
|
||||
int maxIterationCount) {
|
||||
switchesHandler.add(function, maxCheckInterval, convergence, maxIterationCount);
|
||||
}
|
||||
|
||||
/** Perform some sanity checks on the integration parameters.
|
||||
* @param equations differential equations set
|
||||
* @param t0 start time
|
||||
* @param y0 state vector at t0
|
||||
* @param t target time for the integration
|
||||
* @param y placeholder where to put the state vector
|
||||
* @exception IntegratorException if some inconsistency is detected
|
||||
*/
|
||||
private void sanityChecks(FirstOrderDifferentialEquations equations,
|
||||
double t0, double[] y0, double t, double[] y)
|
||||
throws IntegratorException {
|
||||
if (equations.getDimension() != y0.length) {
|
||||
throw new IntegratorException("dimensions mismatch: ODE problem has dimension {0}," +
|
||||
" initial state vector has dimension {1}",
|
||||
new Object[] {
|
||||
new Integer(equations.getDimension()),
|
||||
new Integer(y0.length)
|
||||
});
|
||||
}
|
||||
if (equations.getDimension() != y.length) {
|
||||
throw new IntegratorException("dimensions mismatch: ODE problem has dimension {0}," +
|
||||
" final state vector has dimension {1}",
|
||||
new Object[] {
|
||||
new Integer(equations.getDimension()),
|
||||
new Integer(y.length)
|
||||
});
|
||||
}
|
||||
if (Math.abs(t - t0) <= 1.0e-12 * Math.max(Math.abs(t0), Math.abs(t))) {
|
||||
throw new IntegratorException("too small integration interval: length = {0}",
|
||||
new Object[] { new Double(Math.abs(t - t0)) });
|
||||
}
|
||||
}
|
||||
|
||||
/** Integrate the differential equations up to the given time.
|
||||
* <p>This method solves an Initial Value Problem (IVP).</p>
|
||||
* <p>Since this method stores some internal state variables made
|
||||
* available in its public interface during integration ({@link
|
||||
* #getCurrentSignedStepsize()}), it is <em>not</em> thread-safe.</p>
|
||||
* @param equations differential equations to integrate
|
||||
* @param t0 initial time
|
||||
* @param y0 initial value of the state vector at t0
|
||||
* @param t target time for the integration
|
||||
* (can be set to a value smaller than <code>t0</code> for backward integration)
|
||||
* @param y placeholder where to put the state vector at each successful
|
||||
* step (and hence at the end of integration), can be the same object as y0
|
||||
* @throws IntegratorException if the integrator cannot perform integration
|
||||
* @throws DerivativeException this exception is propagated to the caller if
|
||||
* the underlying user function triggers one
|
||||
*/
|
||||
public void integrate(FirstOrderDifferentialEquations equations,
|
||||
double t0, double[] y0,
|
||||
double t, double[] y)
|
||||
throws DerivativeException, IntegratorException {
|
||||
|
||||
sanityChecks(equations, t0, y0, t, y);
|
||||
boolean forward = (t > t0);
|
||||
|
||||
// create some internal working arrays
|
||||
int stages = c.length + 1;
|
||||
if (y != y0) {
|
||||
System.arraycopy(y0, 0, y, 0, y0.length);
|
||||
}
|
||||
double[][] yDotK = new double[stages][];
|
||||
for (int i = 0; i < stages; ++i) {
|
||||
yDotK [i] = new double[y0.length];
|
||||
}
|
||||
double[] yTmp = new double[y0.length];
|
||||
|
||||
// set up an interpolator sharing the integrator arrays
|
||||
AbstractStepInterpolator interpolator;
|
||||
if (handler.requiresDenseOutput() || (! switchesHandler.isEmpty())) {
|
||||
RungeKuttaStepInterpolator rki = (RungeKuttaStepInterpolator) prototype.copy();
|
||||
rki.reinitialize(equations, yTmp, yDotK, forward);
|
||||
interpolator = rki;
|
||||
} else {
|
||||
interpolator = new DummyStepInterpolator(yTmp, forward);
|
||||
}
|
||||
interpolator.storeTime(t0);
|
||||
|
||||
// recompute the step
|
||||
long nbStep = Math.max(1l, Math.abs(Math.round((t - t0) / step)));
|
||||
boolean lastStep = false;
|
||||
stepStart = t0;
|
||||
stepSize = (t - t0) / nbStep;
|
||||
handler.reset();
|
||||
for (long i = 0; ! lastStep; ++i) {
|
||||
|
||||
interpolator.shift();
|
||||
|
||||
boolean needUpdate = false;
|
||||
for (boolean loop = true; loop;) {
|
||||
|
||||
// first stage
|
||||
equations.computeDerivatives(stepStart, y, yDotK[0]);
|
||||
|
||||
// next stages
|
||||
for (int k = 1; k < stages; ++k) {
|
||||
|
||||
for (int j = 0; j < y0.length; ++j) {
|
||||
double sum = a[k-1][0] * yDotK[0][j];
|
||||
for (int l = 1; l < k; ++l) {
|
||||
sum += a[k-1][l] * yDotK[l][j];
|
||||
}
|
||||
yTmp[j] = y[j] + stepSize * sum;
|
||||
}
|
||||
|
||||
equations.computeDerivatives(stepStart + c[k-1] * stepSize, yTmp, yDotK[k]);
|
||||
|
||||
}
|
||||
|
||||
// estimate the state at the end of the step
|
||||
for (int j = 0; j < y0.length; ++j) {
|
||||
double sum = b[0] * yDotK[0][j];
|
||||
for (int l = 1; l < stages; ++l) {
|
||||
sum += b[l] * yDotK[l][j];
|
||||
}
|
||||
yTmp[j] = y[j] + stepSize * sum;
|
||||
}
|
||||
|
||||
// Switching functions handling
|
||||
interpolator.storeTime(stepStart + stepSize);
|
||||
if (switchesHandler.evaluateStep(interpolator)) {
|
||||
needUpdate = true;
|
||||
stepSize = switchesHandler.getEventTime() - stepStart;
|
||||
} else {
|
||||
loop = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// the step has been accepted
|
||||
double nextStep = stepStart + stepSize;
|
||||
System.arraycopy(yTmp, 0, y, 0, y0.length);
|
||||
switchesHandler.stepAccepted(nextStep, y);
|
||||
if (switchesHandler.stop()) {
|
||||
lastStep = true;
|
||||
} else {
|
||||
lastStep = (i == (nbStep - 1));
|
||||
}
|
||||
|
||||
// provide the step data to the step handler
|
||||
interpolator.storeTime(nextStep);
|
||||
handler.handleStep(interpolator, lastStep);
|
||||
stepStart = nextStep;
|
||||
|
||||
if (switchesHandler.reset(stepStart, y) && ! lastStep) {
|
||||
// some switching function has triggered changes that
|
||||
// invalidate the derivatives, we need to recompute them
|
||||
equations.computeDerivatives(stepStart, y, yDotK[0]);
|
||||
}
|
||||
|
||||
if (needUpdate) {
|
||||
// a switching function has changed the step
|
||||
// we need to recompute stepsize
|
||||
nbStep = Math.max(1l, Math.abs(Math.round((t - stepStart) / step)));
|
||||
stepSize = (t - stepStart) / nbStep;
|
||||
i = -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
resetInternalState();
|
||||
|
||||
}
|
||||
|
||||
/** Get the current value of the step start time t<sub>i</sub>.
|
||||
* <p>This method can be called during integration (typically by
|
||||
* the object implementing the {@link FirstOrderDifferentialEquations
|
||||
* differential equations} problem) if the value of the current step that
|
||||
* is attempted is needed.</p>
|
||||
* <p>The result is undefined if the method is called outside of
|
||||
* calls to {@link #integrate}</p>
|
||||
* @return current value of the step start time t<sub>i</sub>
|
||||
*/
|
||||
public double getCurrentStepStart() {
|
||||
return stepStart;
|
||||
}
|
||||
|
||||
/** Get the current signed value of the integration stepsize.
|
||||
* <p>This method can be called during integration (typically by
|
||||
* the object implementing the {@link FirstOrderDifferentialEquations
|
||||
* differential equations} problem) if the signed value of the current stepsize
|
||||
* that is tried is needed.</p>
|
||||
* <p>The result is undefined if the method is called outside of
|
||||
* calls to {@link #integrate}</p>
|
||||
* @return current signed value of the stepsize
|
||||
*/
|
||||
public double getCurrentSignedStepsize() {
|
||||
return stepSize;
|
||||
}
|
||||
|
||||
/** Reset internal state to dummy values. */
|
||||
private void resetInternalState() {
|
||||
stepStart = Double.NaN;
|
||||
stepSize = Double.NaN;
|
||||
}
|
||||
|
||||
/** Time steps from Butcher array (without the first zero). */
|
||||
private double[] c;
|
||||
|
||||
/** Internal weights from Butcher array (without the first empty row). */
|
||||
private double[][] a;
|
||||
|
||||
/** External weights for the high order method from Butcher array. */
|
||||
private double[] b;
|
||||
|
||||
/** Prototype of the step interpolator. */
|
||||
private RungeKuttaStepInterpolator prototype;
|
||||
|
||||
/** Integration step. */
|
||||
private double step;
|
||||
|
||||
/** Step handler. */
|
||||
private StepHandler handler;
|
||||
|
||||
/** Switching functions handler. */
|
||||
protected SwitchingFunctionsHandler switchesHandler;
|
||||
|
||||
/** Current step start time. */
|
||||
private double stepStart;
|
||||
|
||||
/** Current stepsize. */
|
||||
private double stepSize;
|
||||
|
||||
}
|
@ -17,6 +17,7 @@
|
||||
|
||||
package org.apache.commons.math.ode;
|
||||
|
||||
|
||||
/** This interface represents a second order integrator for
|
||||
* differential equations.
|
||||
*
|
||||
@ -30,24 +31,7 @@ package org.apache.commons.math.ode;
|
||||
* @since 1.2
|
||||
*/
|
||||
|
||||
public interface SecondOrderIntegrator {
|
||||
|
||||
/** Get the name of the method.
|
||||
* @return name of the method
|
||||
*/
|
||||
public String getName();
|
||||
|
||||
/** Set the step handler for this integrator.
|
||||
* The handler will be called by the integrator for each accepted
|
||||
* step.
|
||||
* @param handler handler for the accepted steps
|
||||
*/
|
||||
public void setStepHandler (StepHandler handler);
|
||||
|
||||
/** Get the step handler for this integrator.
|
||||
* @return the step handler for this integrator
|
||||
*/
|
||||
public StepHandler getStepHandler();
|
||||
public interface SecondOrderIntegrator extends ODEIntegrator {
|
||||
|
||||
/** Integrate the differential equations up to the given time
|
||||
* @param equations differential equations to integrate
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user