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:
Phil Steitz 2008-12-02 02:21:22 +00:00
commit d9df34360f
405 changed files with 23475 additions and 7893 deletions

View File

@ -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
View File

@ -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 &amp;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>

View File

@ -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>

View File

@ -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="&lt;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="&lt;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>

View File

@ -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
View File

@ -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>

View File

@ -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%

View File

@ -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>

View File

@ -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)

View File

@ -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);
}

View File

@ -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 );
}

View File

@ -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) });
}
}

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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) });
}
/**

View File

@ -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}.

View File

@ -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

View File

@ -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);
}
}
}
}

View 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());
}
};
}
}

View File

@ -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;
}

View File

@ -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" }
};

View File

@ -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 {

View File

@ -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$

View File

@ -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

View File

@ -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);
}
}

View File

@ -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();
}
/**

View File

@ -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);
}
}

View File

@ -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};

View File

@ -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

View File

@ -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;
}
}

View File

@ -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 &plusmn; INFINITY i) = 1 &#x2213; INFINITY i
* cos(&plusmn;INFINITY + i) = NaN + NaN i
* cos(&plusmn;INFINITY &plusmn; 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 &plusmn; INFINITY i) = NaN + NaN i
* cosh(&plusmn;INFINITY + i) = INFINITY &plusmn; INFINITY i
* cosh(&plusmn;INFINITY &plusmn; 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 &plusmn; INFINITY i) = NaN + NaN i
* exp(INFINITY + i) = INFINITY + INFINITY i
* exp(-INFINITY + i) = 0 + 0i
* exp(&plusmn;INFINITY &plusmn; 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 &plusmn; INFINITY i) = INFINITY &plusmn; (&pi;/2)i
* log(INFINITY + i) = INFINITY + 0i
* log(-INFINITY + i) = INFINITY + &pi;i
* log(INFINITY &plusmn; INFINITY i) = INFINITY &plusmn; (&pi;/4)i
* log(-INFINITY &plusmn; INFINITY i) = INFINITY &plusmn; (3&pi;/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&middot;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 &plusmn; INFINITY i) = 1 &plusmn; INFINITY i
* sin(&plusmn;INFINITY + i) = NaN + NaN i
* sin(&plusmn;INFINITY &plusmn; 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 &plusmn; INFINITY i) = NaN + NaN i
* sinh(&plusmn;INFINITY + i) = &plusmn; INFINITY + INFINITY i
* sinh(&plusmn;INFINITY &plusmn; 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 &#8805; 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 &plusmn; INFINITY i) = INFINITY + NaN i
* sqrt(INFINITY + i) = INFINITY + 0i
* sqrt(-INFINITY + i) = 0 + INFINITY i
* sqrt(INFINITY &plusmn; INFINITY i) = INFINITY + NaN i
* sqrt(-INFINITY &plusmn; INFINITY i) = NaN &plusmn; 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 &plusmn; INFINITY i) = 0 + NaN i
* tan(&plusmn;INFINITY + i) = NaN + NaN i
* tan(&plusmn;INFINITY &plusmn; INFINITY i) = NaN + NaN i
* tan(&plusmn;&pi;/2 + 0 i) = &plusmn;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 &plusmn; INFINITY i) = NaN + NaN i
* tanh(&plusmn;INFINITY + i) = NaN + 0 i
* tanh(&plusmn;INFINITY &plusmn; INFINITY i) = NaN + NaN i
* tanh(0 + (&pi;/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();
}
}

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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 &lt; x).
* @param x the value at which the CDF is evaluated.

View File

@ -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);
}
}

View File

@ -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 &le; 0
*/
public PoissonDistribution createPoissonDistribution(double lambda) {
return new PoissonDistributionImpl(lambda);
}
}

View File

@ -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);
}

View File

@ -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 &lt; 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 < &mu;) > .5
if (p < .5) {
// use 1/2 mean

View File

@ -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 &lt; 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 &lt; 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 &lt; 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 &lt; <i>lower bound</i>) &lt; <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 &lt; <i>upper bound</i>) &gt; <code>p</code>
*/
protected double getDomainUpperBound(double p) {
return Double.MAX_VALUE;
}
/**
* For this distribution, X, this method returns P(X &lt; 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 &lt; 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 &lt; 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 &lt; <i>lower bound</i>) &lt;
* <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 &lt; <i>upper bound</i>) &gt;
* <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;
}
}

View File

@ -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);
}

View File

@ -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

View File

@ -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;
}

View File

@ -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);
}

View File

@ -35,12 +35,15 @@ public class NormalDistributionImpl extends AbstractContinuousDistribution
/** Serializable version identifier */
private static final long serialVersionUID = 8589540077390120676L;
/** &sqrt;(2 &pi;) */
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 &lt; <code>x</code>).
* @param x the value at which the CDF is evaluated.

View File

@ -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));

View File

@ -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);
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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.

View File

@ -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;

View File

@ -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) });
}
}

View File

@ -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;
}

View File

@ -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 {
/**

View File

@ -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. */

View File

@ -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 {
/**

View File

@ -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());
}
}

View File

@ -18,6 +18,7 @@ package org.apache.commons.math.genetics;
/**
* Algorithm used to mutate a chrommosome.
* @version $Revision$ $Date$
*/
public interface MutationPolicy {

View File

@ -18,6 +18,7 @@ package org.apache.commons.math.genetics;
/**
* A collection of chromosomes that facilitates generational evolution.
* @version $Revision$ $Date$
*/
public interface Population {
/**

View File

@ -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 {
/**

View File

@ -18,6 +18,7 @@ package org.apache.commons.math.genetics;
/**
* Algorithm used to determine when to stop evolution.
* @version $Revision$ $Date$
*/
public interface StoppingCondition {
/**

View File

@ -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 */

View File

@ -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 &pi;. 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();
}
}

View File

@ -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;

View File

@ -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 (&alpha;) of the vector, between -&pi; and +&pi;
* @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);
}
}

View 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);
}
}

View File

@ -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 &times; n matrix A can be written as the product of three matrices:
* A = U &times; B &times; V<sup>T</sup> with U an m &times; m orthogonal matrix,
* B an m &times; n bi-diagonal matrix (lower diagonal if m &lt; n, upper diagonal
* otherwise), and V an n &times; 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

View 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 &times; 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 &times; X = B in least squares sense: they find X
* such that ||A &times; 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 &times; 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 &times; 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 &times; X = B
* @return a vector X that minimizes the two norm of A &times; 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 &times; 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 &times; X = B
* @return a vector X that minimizes the two norm of A &times; 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 &times; 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 &times; X = B
* @return a matrix X that minimizes the two norm of A &times; 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;
}

View 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 &times; D &times; V<sup>T</sup>.
* A, V and D are all m &times; 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;
}

File diff suppressed because it is too large Load Diff

View File

@ -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);
}
}

View File

@ -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);
}
}

View 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&times;A = L&times;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;
}

View 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&times;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 &times; X = B.
* <p>The A matrix is implicit here. It is </p>
* @param b right-hand side of the equation A &times; X = B
* @return a vector X such that A &times; 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);
}
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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();
}
}

View File

@ -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;
}

View File

@ -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&times;n, Q is m&times;m and R m&times;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&times;n, Q is m&times;m and R m&times;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 &times; X = B.
* <p>The A matrix is implicit here. It is </p>
* @param b right-hand side of the equation A &times; X = B
* @return a vector X that minimizes the two norm of A &times; 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);
}
}
}

View File

@ -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();
}
}
}

View File

@ -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

View 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();
}

View 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);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -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();
}
}

View File

@ -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, &Sigma; and V such that A = U &times; &Sigma; &times; V<sup>T</sup>.
* Let A be an m &times; n matrix, then U is an m &times; m orthogonal matrix,
* &Sigma; is a m &times; n diagonal matrix with positive diagonal elements,
* and V is an n &times; 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 &Sigma; of the decomposition.
* <p>&Sigma; is a diagonal matrix.</p>
* @return the &Sigma; 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 &Sigma; of the decomposition.
* @return the diagonal elements of the &Sigma; 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 &times; 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) &times; 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;
}

View File

@ -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 &times; m matrix A can be written as the product of three matrices:
* A = Q &times; T &times; Q<sup>T</sup> with Q an orthogonal matrix and T a symmetrical
* tridiagonal matrix. Both Q and T are m &times; 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];
}
}

View 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) {
}
}
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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);

View File

@ -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

View File

@ -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();
}

View File

@ -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);
}

View 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();
}

View File

@ -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;
}

View File

@ -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