wwmm-euclid-87e8f785a814/.hg_archival.txt0000644000000000000000000000020011607017524016220 0ustar 00000000000000repo: 507c169bff6f232737cc0eb015b1272e7926f1d3 node: 87e8f785a814807290d9294a4a00ec6492eb6185 branch: default tag: euclid-1.0.1 wwmm-euclid-87e8f785a814/.hgignore0000644000000000000000000000011111607017524014736 0ustar 00000000000000foo ^.project$ ^.settings/ ^.classpath$ ^.hgignore~$ ^target/.* /target/ wwmm-euclid-87e8f785a814/.hgtags0000644000000000000000000000005611607017524014421 0ustar 00000000000000691e6cd96e4097b1ab6e90977a78c08c64637467 v1.0 wwmm-euclid-87e8f785a814/pom.xml0000644000000000000000000001411211607017524014456 0ustar 00000000000000 4.0.0 uk.ac.cam.ch.wwmm wwmm-parent 4 org.xml-cml euclid 1.0.1 jar CML Euclid A Java library for 2D and 3D geometric calculations http://bitbucket.org/wwmm/euclid Apache License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0.txt repo https://bitbucket.org/wwmm/euclid/src scm:hg:http://bitbucket.org/wwmm/euclid scm:hg:https://bitbucket.org/wwmm/euclid pm286 Peter Murray-Rust 1994 cml-discuss https://lists.sourceforge.net/lists/listinfo/cml-discuss https://lists.sourceforge.net/lists/listinfo/cml-discuss http://sourceforge.net/mailarchive/forum.php?forum_name=cml-discuss hudson https://hudson.ch.cam.ac.uk/job/euclid Peter Murray-Rust http://wwmm.ch.cam.ac.uk/blogs/murrayrust/ maven-source-plugin jar org.codehaus.mojo cobertura-maven-plugin false org.xmlcml.* 80 80 org/xmlcml/**/*.class clean pre-site clean instrument site instrument cobertura check com.mycila.maven-license-plugin maven-license-plugin
src/main/resources/header.txt
junit junit 4.8.2 test org.xml-cml euclid-testutil 1.0.1 test commons-io commons-io 2.0.1 log4j log4j 1.2.16 org.apache.commons commons-math 2.2 joda-time joda-time 1.6.2 release maven-assembly-plugin src org.apache.maven.plugins maven-project-info-reports-plugin index summary dependencies project-team license cim scm org.apache.maven.plugins maven-javadoc-plugin org.apache.maven.plugins maven-surefire-report-plugin org.apache.maven.plugins maven-jxr-plugin org.apache.maven.plugins maven-pmd-plugin 1.5 true org.apache.maven.plugins maven-checkstyle-plugin src/test/resources/checkstyle.xml org.codehaus.mojo cobertura-maven-plugin org.codehaus.mojo apt-maven-plugin
wwmm-euclid-87e8f785a814/src/main/java/org/xmlcml/euclid/Angle.java0000644000000000000000000002071311607017524023022 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid; /** * Angle object * * Angle represents an angle The reason for the class is to help remember about * radian/degree problems, to keep the angle in the right range (0, 2*PI) or * (-PI, PI) as required, and to format output. *

* To construct an angle the user must consciously use RADIANS *

* The angle returned is always in RADIANS (except if getDegrees() is used) *

*
* If SIGNED is used, the angle is in the range -180 to 180 (-pi to pi)
* If UNSIGNED is used, the angle is in the range 0 to 360 (0 to 2*pi)
* Default is SIGNED *

* Default value of Angle is 0.0; Constructions of invalid angles should throw * exceptions rather than try to make invalid angles. * * @author (C) P. Murray-Rust, 1996 */ public class Angle { /** units */ public enum Units { /** */ DEGREES, /** */ RADIANS; } /** range */ public enum Range { /** * any value. */ UNLIMITED, /** * 0 to 2*PI. */ UNSIGNED, /** * -PI to PI. */ SIGNED; } /** * default is UNLIMITED */ Range range = Range.UNLIMITED; /** * default is RADIANS */ Units type = Units.RADIANS; /** */ public final static double DEGREES_IN_RADIAN = 180.0 / Math.PI; /** * ALWAYS held as radians internally */ double angle = 0.0; /** * create default Angle default is (0.0) */ public Angle() { } /** * create an angle IN RADIANS * * @param a */ public Angle(double a) { angle = a; } /** * construct using degrees or radians * * @param a * @param units */ public Angle(double a, Units units) { angle = (units == Units.RADIANS) ? a : a / DEGREES_IN_RADIAN; } /** * from X and Y components (uses atan2) * * @param x * @param y */ public Angle(double y, double x) { angle = Math.atan2(y, x); } /** * copy constructor * * @param a */ public Angle(Angle a) { angle = a.angle; range = a.range; type = a.type; } /** * shallowCopy * * @param a */ public void shallowCopy(Angle a) { range = a.range; type = a.type; angle = a.angle; } /** * add two angles * * @param a2 * @return new angle */ public Angle plus(Angle a2) { Angle temp = new Angle(angle + a2.angle); return temp; } /** * subtract two angles * * @param a2 * @return new angle */ public Angle subtract(Angle a2) { Angle temp = new Angle(angle - a2.angle); return temp; } /** * multiply an angle by a scalar * * @param f * @return new angle */ public Angle multiplyBy(double f) { Angle temp = new Angle(angle * f); return temp; } /** * trigonometric functions * * @return cosine of angle */ public double cos() { return Math.cos(angle); } /** * sin of angle * * @return sine */ public double sin() { return Math.sin(angle); } /** * tan. * * @return the tan */ public double tan() { return Math.tan(angle); } /** * normalise angle. to range 0 -> 2*PI * * @param angle * @return normalised angle */ public static double normalise(double angle) { while (angle > 2 * Math.PI) { angle -= 2 * Math.PI; } while (angle < 0.0) { angle += 2 * Math.PI; } return angle; } /** * relational operators normalise the angles internally before comparison */ /** * are two normalised angles equal. * * @param a * @return boolean * */ public boolean isEqualTo(double a) { return Real.isEqual(Angle.normalise(angle), Angle.normalise(a)); } /** * is one angle greater than another (after normalisation) * * @param a * @return greater than */ public boolean greaterThan(double a) { return Angle.normalise(angle) > Angle.normalise(a); } /** * is one angle greater than or equal to another (after normalisation) * * @param a * @return greater than or equals */ public boolean greaterThanOrEquals(double a) { return Angle.normalise(angle) >= Angle.normalise(a); } /** * is one angle less than another (after normalisation) * * @param a * @return < */ public boolean lessThan(double a) { return Angle.normalise(angle) < Angle.normalise(a); } /** * is one angle less than or equal to another (after normalisation) * * @param a * @return <= */ public boolean lessThanOrEquals(double a) { return Angle.normalise(angle) <= Angle.normalise(a); } /** * are two angles equal * * @param a * @return == */ public boolean isEqualTo(Angle a) { return isEqualTo(a.angle); } /** * is one angle greater than another (after normalisation) * * @param a * @return > */ public boolean greaterThan(Angle a) { return greaterThan(a.angle); } /** * is one angle greater than or equal to another (after normalisation) * * @param a * @return >= */ public boolean greaterThanOrEquals(Angle a) { return greaterThanOrEquals(a.angle); } /** * is one angle less than another (after normalisation) * * @param a * @return < */ public boolean lessThan(Angle a) { return lessThan(a.angle); } /** * is one angle less than or equal to another (after normalisation) * * @param a * @return <= */ public boolean lessThanOrEquals(Angle a) { return lessThanOrEquals(a.angle); } /** * get angle in radians * * @return anngle */ public double getAngle() { return adjust(angle); } /** * get angle in radians * * @return angle */ public double getRadian() { return adjust(angle); } /** * get angle in degrees * * @return angle */ public double getDegrees() { return adjust(angle) * DEGREES_IN_RADIAN; } /** * input angle in degrees * * @param a */ public void putDegrees(double a) { angle = a / DEGREES_IN_RADIAN; } /** * set type of range * * @param range */ public void setRange(Range range) { this.range = range; } /** * set angle to correct range */ private double adjust(double a) { if (range == Range.UNLIMITED) return a; double temp = normalise(a); if (range == Range.UNSIGNED) { return temp; } if (temp > Math.PI) { temp -= 2 * Math.PI; } else if (temp < -Math.PI) { temp += 2 * Math.PI; } return temp; } /** * to string. * * @return string */ public String toString() { StringBuffer s = new StringBuffer(); double temp = adjust(angle); if (type == Units.DEGREES) { s.append(temp).append(" degrees"); } else { s.append(temp); } return s.toString(); } } wwmm-euclid-87e8f785a814/src/main/java/org/xmlcml/euclid/ArrayBase.java0000644000000000000000000000222011607017524023636 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid; import org.apache.log4j.Logger; /** * super class of array methods * * @author (C) P. Murray-Rust, 1996 */ public abstract class ArrayBase implements EuclidConstants { final static Logger logger = Logger.getLogger(ArrayBase.class.getName()); /** */ public enum Trim { /** */ ABOVE(1), /** */ BELOW(2); /** */ public int trim; private Trim(int t) { this.trim = t; } } } wwmm-euclid-87e8f785a814/src/main/java/org/xmlcml/euclid/Axis.java0000644000000000000000000000443511607017524022703 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid; /** * enums to represent 2- or 3-D axes * * @author (C) P. Murray-Rust, 2005 */ public class Axis { /** enum for x y z axes */ public enum Axis2 { /** * x axis. value is 0 for indexing arrays. */ X("x", 0), /** * y axis. value is 1 for indexing arrays. */ Y("y", 1); /** string value */ public final String axis; /** integer value */ public final int value; /** * constructor. * * @param axis * label for the axis * @param value * serial number (starts at 0) */ private Axis2(String axis, int value) { this.axis = axis; this.value = value; } } /** 3d axes */ public enum Axis3 { /** * x axis. value is 0 for indexing arrays. */ X("x", 0), /** * y axis. value is 1 for indexing arrays. */ Y("y", 1), /** * z axis. value is 2 for indexing arrays. */ Z("z", 2); /** string value */ public final String axis; /** int value */ public final int value; /** * constructor. * * @param axis * label for the axis * @param value * serial number (starts at 0) */ private Axis3(String axis, int value) { this.axis = axis; this.value = value; } } } wwmm-euclid-87e8f785a814/src/main/java/org/xmlcml/euclid/Complex.java0000644000000000000000000001051711607017524023404 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid; /** * A complex number derived from Real2 * * Complex represents a complex number A reasonable number of arithmetic * operations are included DeMoivre's theorem is used for some of them so there * may be quicker implementations elsewhere. * * @author (C) P. Murray-Rust, 1996 */ public class Complex extends Real2 { /** * constructor. */ public Complex() { super(); } /** * real component only * * @param a */ public Complex(double a) { super(a, 0.0); } /** * from components * * @param a * @param b */ public Complex(double a, double b) { super(a, b); } /** * from base class * * @param a */ public Complex(Real2 a) { this.x = a.x; this.y = a.y; } /** * in polar coords * * @param r * @param th */ public Complex(double r, Angle th) { Polar p = new Polar(r, th); x = p.getX(); y = p.getY(); } /** * construct from polar * * @param p */ public Complex(Polar p) { x = p.getX(); y = p.getY(); } /** * copy constructor * * @param a */ public Complex(Complex a) { this.x = a.x; this.y = a.y; } /** * gets real part. * * @return real part */ public double getReal() { return x; } /** * gets imaginary part. * * @return imaginary * */ public double getImaginary() { return y; } /** * unary minus MODIFIES object */ public void negative() { this.x = -this.x; this.y = -this.y; } /** * multiply a complex by a complex. * * @param f * @return complex */ public Complex multiply(Complex f) { Complex temp = new Complex(this); temp.x = x * f.x - y * f.y; temp.y = x * f.y + y * f.x; return temp; } /** * divide a complex by a complex. * * @param f * @return complex * @throws EuclidRuntimeException */ public Complex divideBy(Complex f) throws EuclidRuntimeException { double denom = f.x * f.x + f.y * f.y; if (Real.isZero(denom, Real.getEpsilon())) { throw new EuclidRuntimeException("cannot divide by zero"); } Complex temp = new Complex(f.x, -f.y); temp = new Complex((temp.multiply(this)).multiplyBy(1 / denom)); return temp; } /** * get as polar coords. * * @return radius */ public double getR() { double t = Math.sqrt(x * x + y * y); // double t = x * x + y * y; return t; } /** * angle. * * @return the angle */ public Angle getTheta() { return new Angle(y, x); } /** * polar object. * * @return polar object */ public Polar getPolar() { return new Polar(getR(), getTheta()); } /** * complex square root. * * @param a * @return complex sqrt */ public static Complex sqrt(Complex a) { Polar temp = new Polar(a); temp.r = Math.sqrt(temp.r); temp.theta *= 0.5; return new Complex(temp); } /** * to string. * * @return string */ public String toString() { StringBuffer sb = new StringBuffer(); sb.append(x + EC.S_COMMA + y); return sb.toString(); } } wwmm-euclid-87e8f785a814/src/main/java/org/xmlcml/euclid/DoubleTool.java0000644000000000000000000000351711607017524024047 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid; /** * *

* Tool providing methods for working with doubles. *

* * @author Sam Adams * */ public class DoubleTool { /** * tests equality of doubles. * * @param a * @param b * @param eps * margin of identity * @return true if a == b within eps */ public static boolean equals(double a, double b, double eps) { return (Math.abs(a - b) < Math.abs(eps)); } /** * tests equality of double arrays. arrays must be of same length * * @param a * first array * @param b * second array * @param eps * margin of identity * @return array elements equal within eps */ public static boolean equals(double[] a, double[] b, double eps) { boolean result = false; if (a.length == b.length) { result = true; for (int i = 0; i < a.length; i++) { if (Math.abs(a[i] - b[i]) > Math.abs(eps)) { result = false; break; } } } return result; } } wwmm-euclid-87e8f785a814/src/main/java/org/xmlcml/euclid/EC.java0000644000000000000000000000142311607017524022260 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid; /** alias for brevity. * * @author pm286 * */ public interface EC extends EuclidConstants { } wwmm-euclid-87e8f785a814/src/main/java/org/xmlcml/euclid/Euclid.java0000644000000000000000000000261011607017524023175 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid; /** * These routines have evolved over >10 years and have now settled down to * primitive dataTypes to support CML. In general a CML data element (scalar, * array, matrix) * (double, int, String) will have a euclid primitive unless it * is already provided by Java or not useful. Almost all double types are * supported but some int and String types (e.g. IntSquareMatrix, StringArray, * etc.) are missing. The emphasis is on algebrra and geometry. * * In some CML routines (e.g. atom.geXYZ() a Point3 is returned, but in others * the wrapped type (e.g. CMLArray) is used. Please let us know if this design * works satisfactorily. * * @author pmr 2005 * */ public @interface Euclid { } wwmm-euclid-87e8f785a814/src/main/java/org/xmlcml/euclid/EuclidConstants.java0000644000000000000000000001513011607017524025073 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid; import java.io.File; /** * *

* Constants *

* * @author Peter Murray-Rust * @version 5.0 * */ public interface EuclidConstants { char C_DEL = (char) 127; char C_BACKSPACE = (char) 8; /** constant */ char C_COLON = ':'; /** constant */ char C_SPACE = ' '; /** constant */ char C_NL = '\n'; /** constant */ char C_NBSP = (char) 160; /** constant */ char C_QUOT = '"'; /** constant */ char C_SLASH = '/'; /** constant */ char C_TAB = '\t'; /** constant */ char C_RETURN = '\r'; /** constant */ char C_NEWLINE = '\n'; /** constant */ char C_FORMFEED = '\f'; /** constant */ char C_LBRAK = '('; /** constant */ char C_RBRAK = ')'; /** constant */ char C_SHRIEK = '!'; /** constant */ char C_POUND = '£'; /** constant */ char C_DOLLAR = '$'; /** constant */ char C_PERCENT = '%'; /** constant */ char C_CARET = '^'; /** constant */ char C_AMP = '&'; /** constant */ char C_STAR = '*'; /** constant */ char C_UNDER = '_'; /** constant */ char C_MINUS = '-'; /** constant */ char C_PLUS = '+'; /** constant */ char C_EQUALS = '='; /** constant */ char C_LCURLY = '{'; /** constant */ char C_RCURLY = '}'; /** constant */ char C_LSQUARE = '['; /** constant */ char C_RSQUARE = ']'; /** constant */ char C_TILDE = '~'; /** constant */ char C_HASH = '#'; /** constant */ char C_SEMICOLON = ';'; /** constant */ char C_ATSIGN = '@'; /** constant */ char C_APOS = '\''; /** constant */ char C_COMMA = ','; /** constant */ // char C_CUBED = (char); /** constant */ char C_PERIOD = '.'; /** constant */ char C_QUERY = '?'; /** constant */ char C_LANGLE = '<'; /** constant */ char C_RANGLE = '>'; /** constant */ char C_PIPE = '|'; /** constant */ char C_BACKSLASH = '\\'; /** constant */ String S_BACKSLASH = "\\"; /** constant */ String S_COLON = ":"; /** constant */ String S_EMPTY = ""; /** constant */ String S_SPACE = " "; /** constant */ String S_NL = "\n"; /** constant */ String S_QUOT = "\""; /** constant */ String S_SLASH = "/"; /** constant */ String S_WHITEREGEX = S_BACKSLASH+"s+"; // java regex for any whitespace /** constant */ String S_TAB = "\t"; /** constant */ String S_RETURN = "\r"; /** constant */ String S_NEWLINE = "\n"; /** constant */ String S_FORMFEED = "\f"; /** constant */ String WHITESPACE = S_SPACE + S_TAB + S_RETURN + S_NEWLINE + S_FORMFEED; /** constant */ String S_LBRAK = "("; /** constant */ String S_RBRAK = ")"; /** constant */ String S_SHRIEK = "!"; /** constant */ String S_POUND = "£"; /** constant */ String S_DOLLAR = "$"; /** constant */ String S_PERCENT = "%"; /** constant */ String S_CARET = "^"; /** constant */ String S_AMP = "&"; /** constant */ String S_STAR = "*"; /** constant */ String S_UNDER = "_"; /** constant */ String S_MINUS = "-"; /** constant */ String S_PLUS = "+"; /** constant */ String S_EQUALS = "="; /** constant */ String S_LCURLY = "{"; /** constant */ String S_RCURLY = "}"; /** constant */ String S_LSQUARE = "["; /** constant */ String S_RSQUARE = "]"; /** constant */ String S_TILDE = "~"; /** constant */ String S_HASH = "#"; /** constant */ String S_SEMICOLON = ";"; /** constant */ String S_ATSIGN = "@"; /** constant */ String S_APOS = "'"; /** constant */ String S_COMMA = ","; /** constant */ String S_PERIOD = "."; /** constant */ String S_QUERY = "?"; /** constant */ String S_LANGLE = "<"; /** constant */ String S_RANGLE = ">"; /** constant */ String S_PIPE = "|"; /** punctuation without _.- and whitespace */ String NONWHITEPUNC0 = S_LBRAK + S_RBRAK + S_SHRIEK + S_QUOT + S_POUND + S_DOLLAR + S_PERCENT + S_CARET + S_AMP + S_STAR + S_PLUS + S_EQUALS + S_LCURLY + S_RCURLY + S_LSQUARE + S_RSQUARE + S_TILDE + S_HASH + S_COLON + S_SEMICOLON + S_ATSIGN + S_APOS + S_COMMA + S_SLASH + S_QUERY + S_LANGLE + S_RANGLE + S_PIPE + S_BACKSLASH; /** punctuation without _.- and whitespace */ String NONWHITEPUNC0REGEX = S_BACKSLASH+S_LBRAK + S_BACKSLASH+S_RBRAK + S_BACKSLASH+S_SHRIEK + S_BACKSLASH+S_QUOT + S_BACKSLASH+S_POUND + S_BACKSLASH+S_DOLLAR + S_BACKSLASH+S_PERCENT + S_BACKSLASH+S_CARET + S_BACKSLASH+S_AMP + S_BACKSLASH+S_STAR + S_BACKSLASH+S_PLUS + S_BACKSLASH+S_EQUALS + S_BACKSLASH+S_LCURLY + S_BACKSLASH+S_RCURLY + S_BACKSLASH+S_LSQUARE + S_BACKSLASH+S_RSQUARE + S_BACKSLASH+S_TILDE + S_BACKSLASH+S_HASH + S_BACKSLASH+S_COLON + S_BACKSLASH+S_SEMICOLON + S_BACKSLASH+S_ATSIGN + S_BACKSLASH+S_APOS + S_BACKSLASH+S_COMMA + S_BACKSLASH+S_SLASH + S_BACKSLASH+S_QUERY + S_BACKSLASH+S_LANGLE + S_BACKSLASH+S_RANGLE + S_BACKSLASH+S_PIPE + S_BACKSLASH+S_BACKSLASH; /** all punctuation without whitespace */ String NONWHITEPUNC = NONWHITEPUNC0 + S_UNDER + S_MINUS+ S_PERIOD ; /** all punctuation */ String PUNC = WHITESPACE + NONWHITEPUNC; /** convenience */ String F_S = File.separator; /** URL separator */ String U_S = S_SLASH; /** */ double EPS = 1.0E-14; /** */ double ONE_THIRD = 1.0/3.0; /** */ double TWO_THIRDS = 2.0/3.0; }wwmm-euclid-87e8f785a814/src/main/java/org/xmlcml/euclid/EuclidException.java0000644000000000000000000000240311607017524025054 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid; /** * replaces all Exceptions in jumbo.euclid with a single Exception. The old * Exceptions were too numerous and confused signatures * * @author (C) P. Murray-Rust, 1996 */ public class EuclidException extends Exception { /** * Comment for serialVersionUID */ private static final long serialVersionUID = 3617576011412288051L; /** * constructor. */ public EuclidException() { super(); } /** * constructor. * * @param s */ public EuclidException(String s) { super(s); } } wwmm-euclid-87e8f785a814/src/main/java/org/xmlcml/euclid/EuclidRuntimeException.java0000644000000000000000000000313211607017524026420 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid; /** * *

* runtime exception for Euclid *

* * @author Joe Townsend * @version 5.0 * */ public class EuclidRuntimeException extends RuntimeException implements EuclidConstants { /** constructor * * @param message * @param cause */ public EuclidRuntimeException(String message, Throwable cause) { super(message, cause); } /** * */ private static final long serialVersionUID = 3618697517584169017L; protected EuclidRuntimeException() { super(); } /** * creates EuclidRuntime with message. * * @param msg */ public EuclidRuntimeException(String msg) { super(msg); } /** * creates EuclidRuntime from EuclidException. * * @param exception */ public EuclidRuntimeException(EuclidException exception) { this(S_EMPTY + exception); } } wwmm-euclid-87e8f785a814/src/main/java/org/xmlcml/euclid/EuclidTestUtils.java0000644000000000000000000001232711607017524025064 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid; /** * contains tests for equality, etc. but not not use Assert. * Can therefore be used in tests without worrying about inclusion of * Junit, etc. * @author pm286 * */ public class EuclidTestUtils { /** * returns a message if arrays differ. * * @param a * array to compare * @param b * array to compare * @param eps * tolerance * @return null if arrays are equal else indicative message */ public static String testEquals(double[] a, double[] b, double eps) { String s = null; if (a == null) { s = "a is null"; } else if (b == null) { s = "b is null"; } else if (a.length != b.length) { s = "unequal arrays: " + a.length + EC.S_SLASH + b.length; } else { for (int i = 0; i < a.length; i++) { if (!Real.isEqual(a[i], b[i], eps)) { s = "unequal element at (" + i + "), " + a[i] + " != " + b[i]; break; } } } return s; } /** * returns a message if arrays differ. * @param msg to prepend * @param a array to compare * @param b array to compare * @param eps tolerance * @return null if arrays are equal else indicative message */ public static String testEquals(String msg, double[] a, double[] b, double eps) { String s = testEquals(a, b, eps); if (s != null) { s = msg+": "+s; } return s; } /** * returns a message if arrays of arrays differ. * * @param a * array to compare * @param b * array to compare * @param eps * tolerance * @return null if array are equal else indicative message */ static String testEquals(double[][] a, double[][] b, double eps) { String s = null; if (a == null) { s = "a is null"; } else if (b == null) { s = "b is null"; } else if (a.length != b.length) { s = "unequal arrays: " + a.length + EC.S_SLASH + b.length; } else { for (int i = 0; i < a.length; i++) { if (a[i].length != b[i].length) { s = "row (" + i + ") has unequal lengths: " + a[i].length + EC.S_SLASH + b[i].length; break; } for (int j = 0; j < a[i].length; j++) { if (!Real.isEqual(a[i][j], b[i][j], eps)) { s = "unequal element at (" + i + ", " + j + "), (" + a[i][j] + " != " + b[i][j] + EC.S_RBRAK; break; } } } } return s; } /** * returns a message if arrays differ. * @param msg to prepend * @param a array to compare * @param b array to compare * @param eps tolerance * @return null if arrays are equal else indicative message */ public static String testEquals(String msg, double[][] a, double[][] b, double eps) { String s = testEquals(a, b, eps); if (s != null) { s = msg+": "+s; } return s; } // Real2 /** * returns a message if arrays differ. * * @param a * array to compare * @param b * array to compare * @param eps * tolerance * @return null if arrays are equal else indicative message */ public static String testEquals(Real2 a, Real2 b, double eps) { String s = null; if (a == null) { s = "a is null"; } else if (b == null) { s = "b is null"; } else { if (!Real.isEqual(a.x, b.x, eps) || !Real.isEqual(a.y, b.y, eps)) { s = ""+a+" != "+b; } } return s; } // Plane3 /** * equality test. true if both args not null and equal within epsilon * * @param msg * message * @param test * @param expected * @param epsilon */ public static String testEquals(String msg, Plane3 expected, Plane3 test, double epsilon) { String s = null; if (test == null) { s = msg+": null test"; } else if (expected == null) { s = msg+": null expected"; } else { s = testEquals(msg, expected.getArray(), test, epsilon); } return s; } /** * equality test. true if both args not null and equal within epsilon * * @param msg * message * @param test * array must be of length 4 * @param expected * @param epsilon */ public static String testEquals(String msg, double[] expected, Plane3 test, double epsilon) { String s = null; if (expected == null) { s = msg+": expected should not be null"; } else if (expected.length != 4) { s = msg+": expected must be of length 4; was "+expected.length; } else if (test == null) { s = msg+": test should not be null"; } else { s = testEquals(msg, expected, test.getArray(), epsilon); } return s; } } wwmm-euclid-87e8f785a814/src/main/java/org/xmlcml/euclid/Int.java0000644000000000000000000000705211607017524022527 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid; import org.apache.log4j.Logger; /** * Int supports various utilities for integers Use Integer where you want a * first-class Java object * * @author (C) P. Murray-Rust, 1996 */ public abstract class Int implements EuclidConstants { final static Logger logger = Logger.getLogger(Int.class); /** * set an array to zero * * @param nelem * @param arr */ public static void zeroArray(int nelem, int[] arr) { for (int i = 0; i < nelem; i++) { arr[i] = 0; } } /** * set an array to given value * * @param nelem * @param arr * @param f */ public static void initArray(int nelem, int[] arr, int f) { for (int i = 0; i < nelem; i++) { arr[i] = f; } } /** * print a int[] * * @param a * */ public static void printArray(int[] a) { for (int i = 0; i < a.length; i++) { logger.info(a[i] + EC.S_SPACE); } logger.info(""); } /** * tests equality of int arrays. arrays must be of same length * * @param a * first array * @param b * second array * @return array elements equal */ public static boolean equals(int[] a, int[] b) { boolean result = false; if (a.length == b.length) { result = true; for (int i = 0; i < a.length; i++) { if (a[i] != b[i]) { result = false; break; } } } return result; } /** * compare integer arrays. * * @param a * @param b * @return message or null */ public static String testEquals(int[] a, int[] b) { String s = null; if (a == null) { s = "a is null"; } else if (b == null) { s = "b is null"; } else if (a.length != b.length) { s = "unequal arrays: " + a.length + S_SLASH + b.length; } else { for (int i = 0; i < a.length; i++) { if (a[i] != b[i]) { s = "unequal element (" + i + "), " + a[i] + " != " + b[i]; break; } } } return s; } /** * compare arrays. * * @param a * @param b * @return message or null if equal */ public static String testEquals(int[][] a, int[][] b) { String s = null; if (a == null) { s = "a is null"; } else if (b == null) { s = "b is null"; } else if (a.length != b.length) { s = "unequal arrays: " + a.length + S_SLASH + b.length; } else { for (int i = 0; i < a.length; i++) { if (a[i].length != b[i].length) { s = "row (" + i + ") has unequal lengths: " + a[i].length + S_SLASH + b[i].length; break; } for (int j = 0; j < a[i].length; j++) { if (a[i][j] != b[i][j]) { s = "unequal element at (" + i + ", " + j + "), (" + a[i][j] + " != " + b[i][j] + S_RBRAK; break; } } } } return s; } } wwmm-euclid-87e8f785a814/src/main/java/org/xmlcml/euclid/Int2.java0000644000000000000000000001664511607017524022621 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid; import java.util.Arrays; /** * A pair of integers with no other assumptions Contains two ints. * * The default value is 0, 0. * * @author (C) P. Murray-Rust, 1996 */ public class Int2 implements EuclidConstants { /** the first integer value */ int x; /** the second integer value */ int y; /** * constructor. */ public Int2() { x = 0; y = 0; } /** * constructor. * * @param x * @param y */ public Int2(int x, int y) { this.x = x; this.y = y; } /** * copy constructor * * @param r */ public Int2(Int2 r) { this.x = r.x; this.y = r.y; } /** * swaps the x and y values */ public void swap() { int t = x; x = y; y = t; } /** * sorts x and y so that x <= y */ public void sortAscending() { if (x > y) this.swap(); } /** * sorts x and y so that x >= y */ public void sortDescending() { if (x < y) this.swap(); } /** * set to 0, 0 */ public void clear() { x = y = 0; } /** * set x. * * @param xx */ public void setX(int xx) { x = xx; } /** * set y. * * @param yy */ public void setY(int yy) { y = yy; } /** * is equal to. * * @param r * @return true if equal */ public boolean isEqualTo(Int2 r) { return (x == r.x && y == r.y); } /** * add two points to give vector sum * * @param r2 * @return new point */ public Int2 plus(Int2 r2) { return new Int2(x + r2.x, y + r2.y); } /** * subtract two points to give vector difference * * @param r2 * @return point */ public Int2 subtract(Int2 r2) { return new Int2(x - r2.x, y - r2.y); } /** * multiply both components by minus one MODIFIES 'this' */ public void negative() { this.x = -this.x; this.y = -this.y; } /** * multiply a point by a scalar * * @param f * @return point */ public Int2 multiplyBy(int f) { return new Int2(x * f, y * f); } /** * get X value * * @return value */ public int getX() { return x; } /** * get Y value * * @return value */ public int getY() { return y; } /** * get either value; counts from ZERO * * @param elem * @return element * @throws EuclidRuntimeException */ public int elementAt(int elem) throws EuclidRuntimeException { if (elem == 0) { return x; } else if (elem == 1) { return y; } throw new EuclidRuntimeException("bad index " + elem); } /** * point midway between 'this' and 'p' * * @param p * @return midpoint */ public Int2 getMidPoint(Int2 p) { return new Int2((this.x + p.x) / 2, (this.y + p.y) / 2); } /** * get dot product * * @param r * @return dot */ public int dotProduct(Int2 r) { return (this.x * r.x + this.y * r.y); } /** * to string. * * @return string */ public String toString() { return EC.S_LBRAK + x + EC.S_COMMA + y + EC.S_RBRAK; } } /** * Int2Array is NOT a Vector of Int2s, but a container for a 2-D array with a * variety of ways of managing the data including IntArrays for the x and y * arrays, and also an array of Int2s The latter is only stored if required, and * then is cached. */ class Int2Array { // store in both ways... (wasteful but convenient) IntArray xarr; IntArray yarr; Int2[] xy; int nelem = 0; private boolean expanded = false; /** * default constructor gives an array of 0 points */ public Int2Array() { } /** * get max and min value of Int2_Array * * @return range */ public Int2Range getRange2() { Int2Range temp = new Int2Range(); expand(); for (int i = 0; i < nelem; i++) { temp.add(elementAt(i)); } return temp; } /** * make an Int2Array from 2 IntArrays. copies each. * * @param x * @param y * @exception EuclidRuntimeException unequal sized arrays */ public Int2Array(IntArray x, IntArray y) throws EuclidRuntimeException { if (x.size() != y.size()) { throw new EuclidRuntimeException("arrays of different sizes"); } nelem = x.size(); xarr = (IntArray) x.clone(); yarr = (IntArray) y.clone(); expanded = false; } private void expand() { if (expanded) return; expanded = true; xy = new Int2[nelem]; try { for (int i = 0; i < nelem; i++) { xy[i] = new Int2(xarr.elementAt(i), yarr.elementAt(i)); } } catch (Exception e) { Util.BUG(e); } } /** * size of array * * @return size */ public int size() { return nelem; } /** * get element. * * @param elem * @return element */ public Int2 elementAt(int elem) { expand(); return xy[elem]; } /** hash code. * @return hash code */ @Override public int hashCode() { final int PRIME = 31; int result = 1; result = PRIME * result + ((xarr == null) ? 0 : xarr.hashCode()); result = PRIME * result + Arrays.hashCode(xy); result = PRIME * result + ((yarr == null) ? 0 : yarr.hashCode()); return result; } /** equals. * @param obj * @return equality */ @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; final Int2Array other = (Int2Array) obj; if (xarr == null) { if (other.xarr != null) return false; } else if (!xarr.equals(other.xarr)) return false; if (!Arrays.equals(xy, other.xy)) return false; if (yarr == null) { if (other.yarr != null) return false; } else if (!yarr.equals(other.yarr)) return false; return true; } } wwmm-euclid-87e8f785a814/src/main/java/org/xmlcml/euclid/Int2Range.java0000644000000000000000000001152611607017524023567 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid; /** * * 2-D int limits * * Contains two IntRanges. Can therefore be used to describe 2-dimensional * limits (for example axes of graphs, rectangles in graphics, limits of a * molecule, etc.) *

* Default is two default/invalid IntRange components. Adding points will create * valid ranges. * * @author (C) P. Murray-Rust, 1996 */ public class Int2Range implements EuclidConstants { /** * X-range */ IntRange xrange; /** * Y-range */ IntRange yrange; /** * creates zero range. * * */ public Int2Range() { xrange = new IntRange(); yrange = new IntRange(); } /** * initialise with min and max values; * * @param xr * @param yr */ public Int2Range(IntRange xr, IntRange yr) { if (xr.isValid() && yr.isValid()) { xrange = xr; yrange = yr; } } /** * copy constructor * * @param r */ public Int2Range(Int2Range r) { if (r.isValid()) { xrange = new IntRange(r.xrange); yrange = new IntRange(r.yrange); } } /** * a Int2Range is valid if both its constituent ranges are * * @return valid */ public boolean isValid() { return (xrange != null && yrange != null && xrange.isValid() && yrange .isValid()); } /** * is equal to. * * @param r2 * @return true if equal */ public boolean isEqualTo(Int2Range r2) { if (isValid() && r2 != null && r2.isValid()) { return (xrange.isEqualTo(r2.xrange) && yrange.isEqualTo(r2.yrange)); } else { return false; } } /** * merge two ranges and take the maximum extents * * @param r2 * @return range */ public Int2Range plus(Int2Range r2) { if (!isValid()) { if (r2 == null || !r2.isValid()) { return new Int2Range(); } else { return new Int2Range(r2); } } if (r2 == null || !r2.isValid()) { return new Int2Range(this); } return new Int2Range(xrange.plus(r2.xrange), yrange.plus(r2.yrange)); } /** * intersect two ranges and take the range common to both; return invalid * range if no overlap or either is null/invalid * * @param r2 * @return range * */ public Int2Range intersectionWith(Int2Range r2) { if (!isValid() || r2 == null || !r2.isValid()) { return new Int2Range(); } IntRange xr = this.getXRange().intersectionWith(r2.getXRange()); IntRange yr = this.getYRange().intersectionWith(r2.getYRange()); return new Int2Range(xr, yr); } /** * get xrange * * @return range */ public IntRange getXRange() { return xrange; } /** * get yrange * * @return range */ public IntRange getYRange() { return yrange; } /** * is an Int2 within a Int2Range * * @param p * @return includes */ public boolean includes(Int2 p) { if (!isValid()) { return false; } return (xrange.includes(p.getX()) && yrange.includes(p.getY())); } /** * is one Int2Range completely within another * * @param r * @return includes */ public boolean includes(Int2Range r) { if (!isValid() || r == null || !r.isValid()) { return false; } IntRange xr = r.getXRange(); IntRange yr = r.getYRange(); return (xrange.includes(xr) && yrange.includes(yr)); } /** * add a Int2 to a range * * @param p */ public void add(Int2 p) { xrange.add(p.getX()); yrange.add(p.getY()); } /** * to string. * * @return string */ public String toString() { return EC.S_LBRAK + xrange.toString() + EC.S_COMMA + yrange.toString() + EC.S_RBRAK; } }wwmm-euclid-87e8f785a814/src/main/java/org/xmlcml/euclid/IntArray.java0000644000000000000000000011473011607017524023530 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid; import org.apache.log4j.Logger; /** * array of ints * * IntArray represents a 1-dimensional vector or array of ints and is basically * a wrapper for int[] in Java There are a lot of useful member functions * (sorting, ranges, parallel operations The default is an array with zero * points All arrays are valid objects. Attempting to create an array with < 0 * points creates a default array (zero points). Since int[] knows its length * (unlike C), there are many cases where int[] can be safely used. However it * is not a first-class object and IntArray supplies this feature int[] is * referenceable through getArray() note that the length of the internal array * may not be a useful guide to the number of elements * * @author (C) P. Murray-Rust, 1996 */ public class IntArray extends ArrayBase { final static Logger logger = Logger.getLogger(IntArray.class.getName()); /** * maximum number of elements (for bound checking) * * resettable */ private int maxelem = 10000; /** * actual number of elements */ int nelem; /** * the array of ints */ int[] array; int bufsize = 5; /** * create default Array. default is an array of zero points */ public IntArray() { nelem = 0; bufsize = 5; array = new int[bufsize]; } /** * checks potential size of array. if n < 0, set to 0, otherwise adjust * bufsize to be consistent * * @param n * size of array * @return false if negative */ private boolean checkSize(int n) { if (n < 0) { n = 0; return false; } else { nelem = n; if (nelem > maxelem) maxelem = nelem; if (bufsize < nelem) bufsize = nelem; return true; } } // expands buffer if necessary and copies array into it private void makeSpace(int newCount) { if (newCount > bufsize) { while (newCount > bufsize) { bufsize *= 2; } int[] array1 = new int[bufsize]; System.arraycopy(array, 0, array1, 0, nelem); array = array1; } } /** * creates n-element array. initialised to 0 * * @param n * size of array */ public IntArray(int n) { this(n, 0); } /** * create n-element array initialised linearly. values are elem1+(i-1)*delta * * @param n * size of array * @param elem1 * starting value * @param delta * setpsize */ public IntArray(int n, int elem1, int delta) { if (!checkSize(n)) return; array = new int[n]; bufsize = n; int ff = elem1; for (int i = 0; i < n; i++) { array[i] = ff; ff += delta; } } /** * create Array initialized to constant value. all elements of the array are * set to a given value * * @param n * size of array * @param elem1 * value to set */ public IntArray(int n, int elem1) { if (!checkSize(n)) return; array = new int[n]; bufsize = n; for (int i = 0; i < n; i++) { array[i] = elem1; } } /** * create Array from part of java array. use first n elements of array. * * @param n * number of elements to use * @param arr * array to read from * @throws EuclidRuntimeException * n larger than arraysize */ public IntArray(int n, int[] arr) throws EuclidRuntimeException { if (!checkSize(n)) throw new EuclidRuntimeException("Cannot have negative array length"); if (n > arr.length) { throw new EuclidRuntimeException("Array would overflow"); } array = new int[n]; bufsize = n; System.arraycopy(arr, 0, array, 0, n); } /** * create Array from java array. * * @param arr * array to read from */ public IntArray(int[] arr) { nelem = arr.length; array = new int[nelem]; bufsize = nelem; System.arraycopy(arr, 0, array, 0, nelem); } /** * create from subarray of another Array. * * @param m * array to slice * @param low * inclusive start index of array * @param high * inclusive end index of array * @throws EuclidRuntimeException * low > high or negative indices or outside size of m */ public IntArray(IntArray m, int low, int high) throws EuclidRuntimeException { if (low < 0 || low > high || high >= m.size()) { throw new EuclidRuntimeException("index out of range: " + low + EC.S_SLASH + high); } nelem = high - low + 1; checkSize(nelem); array = new int[nelem]; bufsize = nelem; System.arraycopy(m.array, low, array, 0, nelem); } /** * create mixed sliced array. use another IntArray to subscript this one * where I(this) = I(ref) subscripted by I(sub); Result has dimension of * I(sub). caller is responsible for making sure elements of sub are unique * * @param ref * matrix to slice * @param sub * subscripts. * @throws EuclidRuntimeException * if any of I(sub) lies outside 0...refmax-1 */ public IntArray(IntArray ref, IntArray sub) throws EuclidRuntimeException { this(sub.size()); for (int i = 0; i < sub.size(); i++) { int j = sub.elementAt(i); if (j < 0 || j >= ref.size()) { throw new EuclidRuntimeException(); } this.setElementAt(i, ref.elementAt(j)); } } /** * clone. * * @return the clone */ public Object clone() { IntArray temp = new IntArray(nelem); temp.nelem = nelem; temp.maxelem = maxelem; System.arraycopy(array, 0, temp.array, 0, nelem); temp.bufsize = nelem; return (Object) temp; } /** * copy constructor. * * @param m * array to copy */ public IntArray(IntArray m) { this.shallowCopy(m); System.arraycopy(m.array, 0, array, 0, nelem); } /** * Create customized array. create a given 'shape' of array for data * filtering An intended use is with IntArray.arrayFilter(). The shapes * (before scaling by maxval) are: *

* step is maxval / nn * * @param nn * number of elements * @param shape * TRIANGLE or ZIGZAG * @param maxval * used to compute step */ public IntArray(int nn, String shape, int maxval) { if (shape.toUpperCase().equals("TRIANGLE")) { nelem = nn * 2 - 1; if (!checkSize(nelem)) return; array = new int[nelem]; int delta = maxval / ((int) nn); for (int i = 0; i < nn; i++) { array[i] = (i + 1) * delta; array[nelem - i - 1] = array[i]; } } else if (shape.toUpperCase().equals("ZIGZAG")) { nelem = nn * 4 - 1; if (!checkSize(nelem)) return; array = new int[nelem]; int delta = maxval / ((int) nn); for (int i = 0; i < nn; i++) { array[i] = (i + 1) * delta; array[2 * nn - i - 2] = array[i]; array[2 * nn + i] = -array[i]; array[nelem - i - 1] = -array[i]; } array[2 * nn - 1] = 0; } } /** * construct from an array of Strings. must represent integers * * @param strings values as Strings * @exception NumberFormatException * a string could not be interpreted as integer */ public IntArray(String[] strings) throws NumberFormatException { this(strings.length); for (int i = 0; i < strings.length; i++) { array[i] = (Integer.valueOf(strings[i])).intValue(); } } /** * create from a space-separated string of integers. * * @param string * of form "1 3 56 2..." * @exception NumberFormatException * a substring could not be interpreted as integer */ public IntArray(String string) throws NumberFormatException { this(string.split(S_WHITEREGEX)); } /** * contracts internal array to be of same length as number of elements. * * should be used if the array will be used elsewhere with a fixed length. * */ public void contractArray() { int[] array1 = new int[nelem]; System.arraycopy(array, 0, array1, 0, nelem); array = array1; } /** * shallowCopy * * @param m */ public void shallowCopy(IntArray m) { nelem = m.nelem; bufsize = m.bufsize; maxelem = m.maxelem; array = m.array; } /** * get element by index. * * @param elem * the index * @exception ArrayIndexOutOfBoundsException * elem >= size of this * @return element value */ public int elementAt(int elem) throws ArrayIndexOutOfBoundsException { return array[elem]; } /** * get actual number of elements. * * @return number of elements */ public int size() { return nelem; } /** * get java array. * * @return the array */ public int[] getArray() { if (nelem != array.length) { int[] temp = new int[nelem]; System.arraycopy(array, 0, temp, 0, nelem); array = temp; } return array; } /** * are two arrays equal. * * @param f * array to compare * @return true if arrays are of same size and elements are equal) */ public boolean equals(IntArray f) { boolean equal = false; try { checkConformable(f); equal = true; for (int i = 0; i < nelem; i++) { if (array[i] != f.array[i]) { equal = false; break; } } } catch (Exception e) { equal = false; } return equal; } /** * clear all elements of array. sets value to 0 */ public void clearArray() { for (int i = 0; i < size(); i++) { array[i] = 0; } } /** * get java array in reverse order. * * @return array */ public int[] getReverseArray() { int count = size(); int[] temp = new int[count]; for (int i = 0; i < size(); i++) { temp[i] = this.array[--count]; } return temp; } /** * reset the maximum index (for when poking elements) (no other effect) */ /*-- public void setMaxIndex(int max) { maxelem = max; } --*/ private void checkConformable(IntArray m) throws EuclidRuntimeException { if (nelem != m.nelem) { throw new EuclidRuntimeException(); } } /** * are two arrays equal. * * @param f * array to compare * @return true if arrays are of same size and this(i) = f(i) */ public boolean isEqualTo(IntArray f) { boolean equal = false; try { checkConformable(f); equal = true; for (int i = 0; i < nelem; i++) { if (array[i] != f.array[i]) { equal = false; break; } } } catch (Exception e) { equal = false; } return equal; } /** * adds arrays. does not modify this * * @param f * array to add * @exception EuclidRuntimeException * f is different size from this * @return new array as this + f */ public IntArray plus(IntArray f) throws EuclidRuntimeException { checkConformable(f); IntArray m = (IntArray) this.clone(); for (int i = 0; i < nelem; i++) { m.array[i] = f.array[i] + array[i]; } return m; } /** * subtracts arrays. does not modify this * * @param f * array to substract * @exception EuclidRuntimeException * f is different size from this * @return new array as this - f */ public IntArray subtract(IntArray f) throws EuclidRuntimeException { checkConformable(f); IntArray m = (IntArray) this.clone(); for (int i = 0; i < nelem; i++) { m.array[i] = array[i] - f.array[i]; } return m; } /** * array subtraction. modifies this -= f * * @param f * array to subtract * @exception EuclidRuntimeException * f is different size from this */ public void subtractEquals(IntArray f) throws EuclidRuntimeException { checkConformable(f); for (int i = 0; i < nelem; i++) { array[i] -= f.array[i]; } } /** * change the sign of all elements. MODIFIES this */ public void negative() { for (int i = 0; i < size(); i++) { array[i] = -array[i]; } } /** * add a scalar to all elements. creates new array; does NOT modify 'this'; * for subtraction use negative scalar * * @param f * to add * @return new array */ /*-- public RealArray addScalar(int f) { RealArray m = (RealArray) this.clone(); for(int i = 0; i < nelem; i++) { m.array[i] += f; } return m; } --*/ /** * array multiplication by a scalar. creates new array; does NOT modify * 'this' * * @param f * multiplier * @return the new array */ public IntArray multiplyBy(int f) { IntArray m = (IntArray) this.clone(); for (int i = 0; i < nelem; i++) { m.array[i] *= f; } return m; } /** * set element value. * * @param elem * index * @param f * value * @exception ArrayIndexOutOfBoundsException * elem >= size of this */ public void setElementAt(int elem, int f) throws ArrayIndexOutOfBoundsException { array[elem] = f; } /** * get array slice. creates new array; does not modify this * * @param start * index inclusive * @param end * index inclusive * @return new array */ public IntArray getSubArray(int start, int end) { int nel = end - start + 1; IntArray f = new IntArray(nel, 0); System.arraycopy(array, start, f.array, 0, nel); return f; } /** * set array slice. copy whole array into the array. * * @param start * index in this * @param a * array to copy * @throws ArrayIndexOutOfBoundsException * start < 0 or start+a.length > this.size() */ public void setElements(int start, int[] a) { if (start < 0 || start + a.length > nelem) { throw new ArrayIndexOutOfBoundsException(); } System.arraycopy(a, 0, this.array, start, a.length); } /** * is the array filled with zeros. * * @return true if this(i) = 0 */ public boolean isClear() { for (int i = 0; i < nelem; i++) { if (array[i] != 0) return false; } return true; } /** * initialise array to given value. this(i) = f * * @param f * value to set */ public void setAllElements(int f) { Int.initArray(nelem, array, f); } /** * sum all elements. * * @return sigma(this(i)) */ public int sumAllElements() { int sum = 0; for (int i = 0; i < nelem; i++) { sum += array[i]; } return sum; } /** * sum of all absolute element values. * * @return sigma(abs(this(i))) */ public int absSumAllElements() { int sum = 0; for (int i = 0; i < nelem; i++) { sum += Math.abs(array[i]); } return sum; } /** * inner product. dotProduct(this) * * @return sigma(this(i)**2) */ public int innerProduct() { int result = Integer.MIN_VALUE; try { result = this.dotProduct(this); } catch (EuclidRuntimeException x) { throw new EuclidRuntimeException("bug " + x); } return result; } /** * dot product of two arrays. sigma(this(i)*(f(i)); * * @param f * array to multiply * @exception EuclidRuntimeException * f is different size from this * @return dot */ public int dotProduct(IntArray f) throws EuclidRuntimeException { checkConformable(f); int sum = 0; for (int i = 0; i < nelem; i++) { sum += array[i] * f.array[i]; } return sum; } /** * cumulative sum of array. create new array as elem[i] = sum(k = 0 to i) * f[k] does not modify 'this' * * @return each element is cumulative sum to that point */ public IntArray cumulativeSum() { IntArray temp = new IntArray(nelem); int sum = 0; for (int i = 0; i < nelem; i++) { sum += array[i]; temp.array[i] = sum; } return temp; } /** * apply filter. convolute array with another array. This is 1-D image * processing. If filter has <= 1 element, return this * unchanged. filter should have an odd number of elements. The * filter can be created with a IntArray constructor filter is moved along * stepwise *

* * @param filter * to apply normally smaller than this * @return filtered array */ public IntArray applyFilter(IntArray filter) { if (nelem == 0 || filter == null || filter.nelem <= 1) { return this; } int nfilter = filter.size(); int midfilter = (nfilter - 1) / 2; IntArray temp = new IntArray(nelem); int wt = 0; int sum = 0; for (int j = 0; j < midfilter; j++) { // get weight wt = 0; sum = 0; int l = 0; for (int k = midfilter - j; k < nfilter; k++) { wt += Math.abs(filter.array[k]); sum += filter.array[k] * this.array[l++]; } temp.array[j] = sum / wt; } wt = filter.absSumAllElements(); for (int j = midfilter; j < nelem - midfilter; j++) { sum = 0; int l = j - midfilter; for (int k = 0; k < nfilter; k++) { sum += filter.array[k] * this.array[l++]; } temp.array[j] = sum / wt; } for (int j = nelem - midfilter; j < nelem; j++) { // get weight wt = 0; sum = 0; int l = j - midfilter; for (int k = 0; k < midfilter + nelem - j; k++) { wt += Math.abs(filter.array[k]); sum += filter.array[k] * this.array[l++]; } temp.array[j] = sum / wt; } return temp; } /** * trims array to lie within limit. * * if flag == BELOW values below limit are set to limit. if flag == ABOVE * values above limit are set to limit. by repeated use of trim() values can * be constrained to lie within or outside a window does not modify this. * * @param flag * BELOW or ABOVE * @param limit * value to constrain * @return new array */ public IntArray trim(Trim flag, int limit) { IntArray temp = new IntArray(nelem); for (int i = 0; i < nelem; i++) { int v = array[i]; if ((flag == Trim.BELOW && v < limit) || (flag == Trim.ABOVE && v > limit)) v = limit; temp.array[i] = v; } return temp; } /** * index of largest element. * * @throws ArrayIndexOutOfBoundsException * array is zero length * @return index */ public int indexOfLargestElement() throws ArrayIndexOutOfBoundsException { if (nelem == 0) { throw new ArrayIndexOutOfBoundsException(); } int index = -1; int value = Integer.MIN_VALUE; for (int i = 0; i < nelem; i++) { if (array[i] > value) { value = array[i]; index = i; } } return index; } /** * index of smallest element. * * @throws ArrayIndexOutOfBoundsException * array is zero length * @return index */ public int indexOfSmallestElement() throws ArrayIndexOutOfBoundsException { if (nelem == 0) { throw new ArrayIndexOutOfBoundsException(); } int index = -1; int value = Integer.MAX_VALUE; for (int i = 0; i < nelem; i++) { if (array[i] < value) { value = array[i]; index = i; } } return index; } /** * value of largest element. * * @throws ArrayIndexOutOfBoundsException * array is zero length * @return value */ public int largestElement() throws ArrayIndexOutOfBoundsException { return array[indexOfLargestElement()]; } /** * value of largest element. synonym for largestElement(); * * @throws ArrayIndexOutOfBoundsException * array is zero length * @return value */ public int getMax() throws ArrayIndexOutOfBoundsException { return array[indexOfLargestElement()]; } /** * value of smallest element. * * @throws ArrayIndexOutOfBoundsException * array is zero length * @return index */ public int smallestElement() throws ArrayIndexOutOfBoundsException { return array[indexOfSmallestElement()]; } /** * value of smallest element. synonym for smallestElement(); * * @throws ArrayIndexOutOfBoundsException * array is zero length * @return value */ public int getMin() throws ArrayIndexOutOfBoundsException { return array[indexOfSmallestElement()]; } /** * range of array. * * @throws ArrayIndexOutOfBoundsException * array is zero length * @return (minValue, maxValue) */ public IntRange getRange() throws ArrayIndexOutOfBoundsException { if (nelem == 0) { throw new ArrayIndexOutOfBoundsException(); } IntRange r = new IntRange(); for (int i = 0; i < nelem; i++) { r.add(array[i]); } return r; } /** * as above (deprecated) */ /*-- public RealRange range() {return this.getRange();} --*/ /** * delete element and close up. modifies this. * * @param elem * to delete * @throws ArrayIndexOutOfBoundsException * elem out of range */ public void deleteElement(int elem) throws ArrayIndexOutOfBoundsException { if (elem < 0 || elem >= nelem) { throw new ArrayIndexOutOfBoundsException(); } nelem--; if (bufsize > nelem * 2) { bufsize /= 2; } int[] temp = new int[bufsize]; System.arraycopy(array, 0, temp, 0, elem); System.arraycopy(array, elem + 1, temp, elem, nelem - elem); array = temp; } /** * delete elements and close up. modifies this. * * @param low * lowest index inclusive * @param high * highest index inclusive * @throws ArrayIndexOutOfBoundsException * low or high out of range or low > high */ /** * delete elements and close up. modifies this. * * @param low * lowest index inclusive * @param high * highest index inclusive * @throws ArrayIndexOutOfBoundsException * low or high out of range or low > high */ public void deleteElements(int low, int high) throws ArrayIndexOutOfBoundsException { if (low < 0 || low > high || high >= nelem) { throw new ArrayIndexOutOfBoundsException(); } int ndeleted = high - low + 1; int[] temp = new int[nelem - ndeleted]; System.arraycopy(array, 0, temp, 0, low); System.arraycopy(array, high + 1, temp, low, nelem - low - ndeleted); array = temp; nelem -= ndeleted; bufsize = nelem; int[] array = new int[nelem]; System.arraycopy(temp, 0, array, 0, nelem); } /** * insert element and expand. modifies this. * * @param elem * index of element to insert * @param f * value of element * @throws ArrayIndexOutOfBoundsException * elem out of range */ public void insertElementAt(int elem, int f) throws ArrayIndexOutOfBoundsException { if (elem < 0 || elem > nelem) { throw new ArrayIndexOutOfBoundsException(); } int[] array1 = new int[nelem + 1]; System.arraycopy(array, 0, array1, 0, elem); array1[elem] = f; System.arraycopy(array, elem, array1, elem + 1, nelem - elem); nelem++; array = array1; } /** * insert an array and expand. modifies this. * * @param elem * index of element to insert * @param f * value of element * @throws ArrayIndexOutOfBoundsException * elem out of range */ public void insertArray(int elem, IntArray f) throws ArrayIndexOutOfBoundsException { int n = f.size(); if (elem < 0 || elem >= nelem || n < 1) { throw new ArrayIndexOutOfBoundsException(); } nelem += n; int[] array1 = new int[nelem]; System.arraycopy(array, 0, array1, 0, elem); System.arraycopy(f.getArray(), 0, array1, elem, n); System.arraycopy(array, elem, array1, n + elem, nelem - elem - n); array = array1; } /** * append element. modifies this. * * @param f * element to append */ public void addElement(int f) { makeSpace(nelem + 1); array[nelem++] = f; } /** * append elements. modifies this. * * @param f * elements to append */ public void addArray(IntArray f) { makeSpace(nelem + f.nelem); System.arraycopy(f.array, 0, array, nelem, f.nelem); nelem += f.nelem; } /** * get reordered Array. reorder by index in IntSet new(i) = this(idx(i)) * does NOT modify array * * @param idx * array of indexes * @exception EuclidRuntimeException * an element of idx is outside range of this * @return array */ public IntArray getReorderedArray(IntSet idx) throws EuclidRuntimeException { IntArray temp = new IntArray(nelem); for (int i = 0; i < nelem; i++) { int index = idx.elementAt(i); if (index > nelem) { throw new EuclidRuntimeException(); } temp.array[i] = array[index]; } return temp; } /** * get elements within a range. * * @param r * within which element values must lie * @return indexes of conforming elements */ public IntSet inRange(IntRange r) { int n = size(); IntSet temp = new IntSet(); for (int i = 0; i < n; i++) { if (r.isValid() && r.includes(array[i])) { temp.addElement(i); } } return temp; } /** * get elements outside a range. * * @param r * outside which element values must lie * @return indexes of conforming elements */ public IntSet outOfRange(IntRange r) { int n = size(); IntSet temp = new IntSet(); for (int i = 0; i < n; i++) { if (r.isValid() && !r.includes(array[i])) { temp.addElement(i); } } return temp; } /** * returns values as strings. * * @return string values of elements */ public String[] getStringValues() { String[] temp = new String[nelem]; for (int i = 0; i < nelem; i++) { temp[i] = Integer.toString(array[i]); } return temp; } /** * gets values as string. * * @return element values seperated with spaces */ public String toString() { // don't change this routine!!! StringBuffer s = new StringBuffer(); s.append(S_LBRAK); for (int i = 0; i < nelem; i++) { if (i > 0) { s.append(S_COMMA); } s.append(array[i]); } s.append(S_RBRAK); return s.toString(); } /** * delete elements. utility routine. delete elements from java routine and * close up * * @param low * index inclusive * @param hi * index inclusive if hi >= float.length hi is reset to * float.length-1. */ static int[] deleteElements(int[] f, int low, int hi) { if (hi >= f.length) hi = f.length - 1; if (low < 0) low = 0; int ndel = hi - low + 1; if (ndel <= 0) return f; int[] temp = new int[f.length - ndel]; System.arraycopy(f, 0, temp, 0, low); System.arraycopy(f, hi + 1, temp, low, f.length - hi - 1); return temp; } /** * copy java array utility routine */ static int[] copy(int[] f) { int temp[] = new int[f.length]; System.arraycopy(f, 0, temp, 0, f.length); return temp; } /** * quick sort - modified from p96 - 97 (Hansen - C++ answer book) * * Scalar sort refers to sorting IntArray and IntArray (and similar classes) * where the objects themeselves are sorted. * * Index sort refers to sorting indexes (held as IntSet's) to the object and * getting the sorted object(s) with reorderBy(IntSet idx); * */ void xfswap(int[] x, int a, int b) { int tmp = x[a]; x[a] = x[b]; x[b] = tmp; } // scalar sort routines (internal) static final int CUTOFF = 16; private void inssort(int left, int right) { int k; for (int i = left + 1; i <= right; i++) { int v = array[i]; int j; for (j = i, k = j - 1; j > 0 && array[k] > v; j--, k--) { array[j] = array[k]; } array[j] = v; } } private int partition(int left, int right) { int mid = (left + right) / 2; if (array[left] > array[mid]) xfswap(array, left, mid); if (array[left] > array[right]) xfswap(array, left, right); if (array[mid] > array[right]) xfswap(array, mid, right); int j = right - 1; xfswap(array, mid, j); int i = left; int v = array[j]; do { do { i++; } while (array[i] < v); do { j--; } while (array[j] > v); xfswap(array, i, j); } while (i < j); xfswap(array, j, i); xfswap(array, i, right - 1); return i; } private void iqsort(int left, int right) { while (right - left > CUTOFF) { int i = partition(left, right); if (i - left > right - i) { iqsort(i + 1, right); right = i - 1; } else { iqsort(left, i - 1); left = i + 1; } } } /** * sorts array into ascending order. MODIFIES this */ public void sortAscending() { if (nelem <= 0) return; iqsort(0, nelem - 1); inssort(0, nelem - 1); } /** * sorts array into descending order. MODIFIES this */ public void sortDescending() { sortAscending(); reverse(); } /** * puts array into reverse order. MODIFIES this */ public void reverse() { int i = 0, j = nelem - 1; while (i < j) { xfswap(array, i, j); i++; j--; } } private static final int XXCUTOFF = 16; /** * get indexes of ascending sorted array. this array NOT MODIFIED * * @return indexes idx so that element(idx(0)) is lowest */ public IntSet indexSortAscending() { if (nelem <= 0) { return new IntSet(); } IntSet idx = new IntSet(nelem); IntArray iarray = new IntArray(idx.getElements()); xxiqsort(iarray, array, 0, nelem - 1); xxinssort(iarray, array, 0, nelem - 1); try { idx = new IntSet(iarray.getArray()); } catch (Exception e) { throw new EuclidRuntimeException(e.toString()); } return idx; } /** * get indexes of descending sorted array. this array NOT MODIFIED * * @return indexes idx so that element(idx(0)) is highest */ public IntSet indexSortDescending() { IntSet idx; idx = indexSortAscending(); int[] temp = new IntArray(idx.getElements()).getReverseArray(); try { idx = new IntSet(temp); } catch (Exception e) { throw new EuclidRuntimeException(e.toString()); } return idx; } private void xxinssort(IntArray iarr, int[] pfl, int left, int right) { int j, k; for (int i = left + 1; i <= right; i++) { int v = iarr.elementAt(i); for (j = i, k = j - 1; j > 0 && pfl[iarr.elementAt(k)] > pfl[v]; j--, k--) { iarr.setElementAt(j, iarr.elementAt(k)); } iarr.setElementAt(j, v); } } private int xxpartition(IntArray iarr, int[] pfl, int left, int right) { int mid = (left + right) / 2; if (pfl[iarr.elementAt(left)] > pfl[iarr.elementAt(mid)]) xxfswap(iarr, left, mid); if (pfl[iarr.elementAt(left)] > pfl[iarr.elementAt(right)]) xxfswap(iarr, left, right); if (pfl[iarr.elementAt(mid)] > pfl[iarr.elementAt(right)]) xxfswap(iarr, mid, right); int j = right - 1; xxfswap(iarr, mid, j); int i = left; int v = pfl[iarr.elementAt(j)]; do { do { i++; } while (pfl[iarr.elementAt(i)] < v); do { j--; } while (pfl[iarr.elementAt(j)] > v); xxfswap(iarr, i, j); } while (i < j); xxfswap(iarr, j, i); xxfswap(iarr, i, right - 1); return i; } private void xxiqsort(IntArray iarr, int[] pfl, int left, int right) { while (right - left > XXCUTOFF) { int i = xxpartition(iarr, pfl, left, right); if (i - left > right - i) { xxiqsort(iarr, pfl, i + 1, right); right = i - 1; } else { xxiqsort(iarr, pfl, left, i - 1); left = i + 1; } } } private void xxfswap(IntArray iarr, int a, int b) { int t = iarr.elementAt(a); iarr.setElementAt(a, iarr.elementAt(b)); iarr.setElementAt(b, t); } /** * parse string as integerArray. * * @param s * @param delimiterRegex * @return true if can be parsed. */ public static boolean isIntArray(String s, String delimiterRegex) { boolean couldBeIntArray = true; String[] ss = s.split(delimiterRegex); try { new IntArray(ss); } catch (NumberFormatException e) { couldBeIntArray = false; } return couldBeIntArray; } } wwmm-euclid-87e8f785a814/src/main/java/org/xmlcml/euclid/IntMatrix.java0000644000000000000000000013753711607017524023730 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid; import java.io.IOException; import java.io.Writer; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.List; import org.apache.log4j.Logger; /** * rectangular real number matrix class IntMatrix represents a rectangular m-x-n * matrix. The basic matrix algebra for non-square matrices is represented here * and this class is also a base for square matrices. *

* Read the signature of each member function carefully as some MODIFY the * object and some CREATE A NEW ONE. Among the reasons for this is that * subclassing (e.g to IntSquareMatrix) is easier with one of these forms in * certain cases. Note that if you modify an object, then all references to it * will refer to the changed object * * @author (C) P. Murray-Rust, 1996 */ public class IntMatrix implements EuclidConstants { final static Logger logger = Logger.getLogger(IntMatrix.class.getName()); /** * number of rows */ protected int rows = 0; /** * number of columns */ protected int cols = 0; /** * the matrix */ protected int[][] flmat = new int[0][0]; DecimalFormat format = null; /** * construct default matrix. cols = rows = 0 */ public IntMatrix() { } /** * Create matrix with given rows and columns. A rows*cols matrix values set * to 0 (rows or cols < 0 defaults to 0) * * @param r * number of rows * @param c * number of columns */ public IntMatrix(int r, int c) { if (r < 0) r = 0; if (c < 0) c = 0; rows = r; cols = c; flmat = new int[r][c]; } /** * Create from 1-D array. Formed by feeding in an existing 1-D array to a * rowsXcols matrix THE COLUMN IS THE FASTEST MOVING INDEX, that is the * matrix is filled as flmat(0,0), flmat(0,1) ... C-LIKE. COPIES the array * * @param rows * @param cols * @param array * @exception EuclidRuntimeException * size of array is not rows*cols */ public IntMatrix(int rows, int cols, int[] array) throws EuclidRuntimeException { this(rows, cols); check(rows, cols, array); this.rows = rows; this.cols = cols; int count = 0; for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { flmat[i][j] = array[count++]; } } } /** * creates matrix with initialised values. * * @param r * rows * @param c * columns * @param f * value to initialize with */ public IntMatrix(int r, int c, int f) { this(r, c); for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { flmat[i][j] = f; } } } /** * create from submatrix of another matrix. fails if lowrow > hirow, lowrow < * 0, etc * * COPIES the parts of m * * @param m * the matrix to slice * @param lowcol * lowest column index * @param hicol * highest column index * @param lowrow * lowest row index * @param hirow * highest row index * @exception EuclidRuntimeException * impossible value of hirow, hicol, lowrow, lowcol */ public IntMatrix(IntMatrix m, int lowrow, int hirow, int lowcol, int hicol) throws EuclidRuntimeException { this(hirow - lowrow + 1, hicol - lowcol + 1); if (hirow >= m.getRows() || lowrow < 0) { throw new EuclidRuntimeException("bad row index: " + lowrow + S_SLASH + hirow + " outside 0/" + m.getRows()); } if (hicol >= m.getCols() || lowcol < 0) { throw new EuclidRuntimeException("bad col index: " + lowcol + S_SLASH + hicol + " outside 0/" + m.getCols()); } for (int i = 0, mrow = lowrow; i < rows; i++, mrow++) { for (int j = 0, mcol = lowcol; j < cols; j++, mcol++) { flmat[i][j] = m.flmat[mrow][mcol]; } } } /** * copy constructor. copies matrix including values * * @param m * matrix to copy */ public IntMatrix(IntMatrix m) { this(m.rows, m.cols); for (int i = 0; i < rows; i++) { System.arraycopy(m.flmat[i], 0, flmat[i], 0, cols); } } /** * shallow copy constructor. copies references (uses same internal array) * * @param m * matrix to copy */ public void shallowCopy(IntMatrix m) { this.rows = m.rows; this.cols = m.cols; this.flmat = m.flmat; } /** * constructs an IntMatrix. intm(i,j) = (int) this(i,j), i.e.gets nearest * integers as matrix. * * @return the nearest IntMatrix */ public IntMatrix getIntMatrix() { IntMatrix im = new IntMatrix(rows, cols); int[][] matrix = im.getMatrix(); for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { matrix[i][j] = (int) flmat[i][j]; } } return im; } /** * create from a java matrix. must be rectangular copies matrix values (i.e. * m can be discarded) * * @param m * natrix to copy from * @exception EuclidRuntimeException * m has rows of different lengths */ public IntMatrix(int[][] m) throws EuclidRuntimeException { this(m.length, m[0].length); for (int i = 0; i < rows; i++) { if (m[i].length != cols) { throw new EuclidRuntimeException("non-rectangular matrix cols: " + cols + " row: " + i + " length: " + m[i].length); } for (int j = 0; j < cols; j++) { flmat[i][j] = m[i][j]; } } } /** * set output format. * * @param f * the format */ public void setFormat(DecimalFormat f) { format = f; } /** * get output format. * * @return the format */ public DecimalFormat getFormat() { return format; } /** * get number of rows. * * @return number of rows */ public int getRows() { return rows; } /** * get number of columns. * * @return number of columns */ public int getCols() { return cols; } /** * get matrix as java matrix. shallow copy - any alterations to java matrix * will alter this and vice versa. * * @return matrix as java matrix */ public int[][] getMatrix() { return flmat; } /** * get matrix as array. * * @return matrix as 1-D array in C order: (m(0,0), m(0,1) ...) */ public int[] getMatrixAsArray() { int[] temp = new int[rows * cols]; int count = 0; for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { temp[count++] = flmat[i][j]; } } return temp; } /** * tests matrices for equality. * * uses Int.isEqual(int) for tests * * @param m * @return true if all corresponding elements are equal */ public boolean isEqualTo(IntMatrix m) { boolean ok = true; try { checkConformable(m); for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { if (flmat[i][j] != m.flmat[i][j]) { ok = false; break; } } } } catch (EuclidRuntimeException e) { ok = false; } return ok; } // check that plus, subtract is possible private void checkConformable(IntMatrix m) throws EuclidRuntimeException { if (rows != m.rows || cols != m.cols) { throw new EuclidRuntimeException("unequal matrices"); } } // check that multiply is possible private void checkConformable2(IntMatrix m) throws EuclidRuntimeException { if (m.rows != this.cols) { throw new EuclidRuntimeException("unequal matrices (" + this.cols + ", " + m.rows + S_RBRAK); } } private void check(int rows, int cols, int[] array) throws EuclidRuntimeException { if (array == null) { throw new EuclidRuntimeException("IntMatrix(null)"); } if (array.length != rows * cols) { throw new EuclidRuntimeException("rows * cols (" + rows + S_STAR + cols + ") != array (" + array.length + S_RBRAK); } } /** * matrix addition. adds conformable matrices giving NEW matrix. this is * unaltered * * @param m2 matrix * @exception EuclidRuntimeException * m and this are different sizes * @return new matrix */ public IntMatrix plus(IntMatrix m2) throws EuclidRuntimeException { IntMatrix m = new IntMatrix(m2.rows, m2.cols); checkConformable(m2); for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { m.flmat[i][j] = flmat[i][j] + m2.flmat[i][j]; } } return m; } /** * matrix subtraction. subtracts conformable matrices giving NEW matrix this * is unaltered * * @param m2 * @exception EuclidRuntimeException * m and this are different sizes * @return new matrix */ public IntMatrix subtract(IntMatrix m2) throws EuclidRuntimeException { IntMatrix m = new IntMatrix(m2.rows, m2.cols); checkConformable(m2); for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { m.flmat[i][j] = flmat[i][j] - m2.flmat[i][j]; } } return m; } /** * unary minus. negate all elements of matrix; MODIFIES matrix */ public void negative() { for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { flmat[i][j] = -flmat[i][j]; } } } /** * matrix multiplication. * * multiplies conformable matrices to give NEW matrix. this is unaltered * result = 'this' * m; (order matters) * * @param m * @exception EuclidRuntimeException * m and this are different sizes * @return new matrix */ public IntMatrix multiply(IntMatrix m) throws EuclidRuntimeException { checkConformable2(m); IntMatrix m1 = new IntMatrix(rows, m.cols); for (int i = 0; i < rows; i++) { for (int j = 0; j < m.cols; j++) { m1.flmat[i][j] = 0; for (int k = 0; k < cols; k++) { m1.flmat[i][j] += flmat[i][k] * m.flmat[k][j]; } } } return m1; } /** * matrix multiplication by a scalar. creates this(i,j) = f*this(i,j) * MODIFIES matrix * * @param f * scalar */ public void multiplyBy(int f) { for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { flmat[i][j] *= f; } } } /** * matrix multiplication. multiplies conformable matrices and stores result * in this matrix. this = 'this' * m; * * @param m * matrix to multiply by * @exception EuclidRuntimeException * m and this are different sizes */ public void multiplyEquals(IntMatrix m) throws EuclidRuntimeException { IntMatrix mm = this.multiply(m); this.rows = mm.rows; this.cols = mm.cols; this.flmat = new int[this.rows][]; for (int i = 0; i < rows; i++) { this.flmat[i] = new int[this.cols]; System.arraycopy(mm.flmat[i], 0, this.flmat[i], 0, this.cols); } } /** * subtract value from each row. this[i,j] = this[i,j] - d[j] modifies this * * @param d * array of ints to subtract */ /*-- public void translateByRow(int[] d) { checkColumns(d); for (int i = rows - 1; i >= 0; -- i) { for (int j = cols - 1; j >= 0; -- j) { flmat [i] [j] -= d [j]; } } } --*/ /** * check. * * @param d * @throws EuclidRuntimeException */ /* private */void checkColumns(int[] d) throws EuclidRuntimeException { if (d.length != cols) { throw new EuclidRuntimeException("array size " + d.length + "!= cols length " + cols); } } private void checkRows(int[] d) throws EuclidRuntimeException { if (d.length != rows) { throw new EuclidRuntimeException("array size " + d.length + "!= rows length " + rows); } } /** * subtract value from each colum. this[i,j] = this[i,j] - d[i] modifies * this * * @param d * array of ints to subtract * @throws EuclidRuntimeException */ public void translateByColumn(int[] d) throws EuclidRuntimeException { checkRows(d); for (int i = cols - 1; i >= 0; --i) { for (int j = rows - 1; j >= 0; --j) { flmat[j][i] -= d[j]; } } } /** * matrix multiplication of a COLUMN vector. creates new vector * * @param f * vector to multiply * @exception EuclidRuntimeException * f.size() differs from cols * @return transformed array */ public IntArray multiply(IntArray f) throws EuclidRuntimeException { if (f.size() != this.cols) { throw new EuclidRuntimeException("unequal matrices"); } int[] temp = new int[rows]; int[] farray = f.getArray(); for (int i = 0; i < rows; i++) { temp[i] = 0; for (int j = 0; j < cols; j++) { temp[i] += this.flmat[i][j] * farray[j]; } } IntArray ff = new IntArray(temp); return ff; } /** * divide each column of a matrix by a vector of scalars (that is mat[i][j] = * mat[i][j] / vect[i] - MODIFIES matrix * * @param f * array to divide by * @exception EuclidRuntimeException * f.size() and rows differ */ public void columnwiseDivide(IntArray f) throws EuclidRuntimeException { if (this.cols != f.size()) { throw new EuclidRuntimeException("unequal matrices " + this.cols + S_SLASH + f.size()); } for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { this.flmat[i][j] /= f.elementAt(j); } } } /** * extracts a given element. * * @param row * @param col * @throws EuclidRuntimeException * bad value of row or column * @return the element at row,col */ public int elementAt(int row, int col) throws EuclidRuntimeException { checkRow(row); checkColumn(col); return flmat[row][col]; } /** * checks a row is in range. * * @throws EuclidRuntimeException * if it isn't */ private void checkRow(int row) throws EuclidRuntimeException { if (row < 0 || row >= rows) throw new EuclidRuntimeException("Bad value of row: " + row + S_SLASH + rows); } /** * checks a col is in range. * * @throws EuclidRuntimeException * if it isn't */ private void checkColumn(int col) throws EuclidRuntimeException { if (col < 0 || col >= cols) throw new EuclidRuntimeException("Bad value of col: " + col + S_SLASH + cols); } /** * extracts a given element. * * @param rowcol * represents row,col * @return the element at row,col * @throws EuclidRuntimeException */ public int elementAt(Int2 rowcol) throws EuclidRuntimeException { return elementAt(rowcol.elementAt(0), rowcol.elementAt(1)); } /** * sets a given element MODIFIES matrix * * @param row * @param col * @param f * @throws EuclidRuntimeException */ public void setElementAt(int row, int col, int f) throws EuclidRuntimeException { checkRow(row); checkColumn(col); flmat[row][col] = f; } /** * get value of largest element. * * @return value of largest element */ public int largestElement() { Int2 temp = indexOfLargestElement(); if (temp == null) { throw new EuclidRuntimeException("bug; null index for largest element"); } int d = this.elementAt(temp); return d; } /** * get index of largest element. * * @return (row, col) */ public Int2 indexOfLargestElement() { Int2 int2 = null; if (cols != 0 && rows != 0) { int f = Integer.MIN_VALUE; int im = 0; int jm = 0; for (int irow = 0; irow < rows; irow++) { for (int jcol = 0; jcol < cols; jcol++) { if (f < flmat[irow][jcol]) { f = flmat[irow][jcol]; im = irow; jm = jcol; } } } int2 = new Int2(im, jm); } return int2; } /** * get value of largest element in a column * * @param jcol * @throws EuclidRuntimeException * @return the value */ public int largestElementInColumn(int jcol) throws EuclidRuntimeException { return this.elementAt(indexOfLargestElementInColumn(jcol), jcol); } /** * get index of largest element in column. * * @param jcol * index * @return index (-1 if empty matrix) * @throws EuclidRuntimeException * bad value of jcol */ public int indexOfLargestElementInColumn(int jcol) throws EuclidRuntimeException { checkColumn(jcol); int imax = -1; int max = Integer.MIN_VALUE; for (int irow = 0; irow < rows; irow++) { if (max < flmat[irow][jcol]) { max = flmat[irow][jcol]; imax = irow; } } return imax; } /** * get index of largest element in row. * * @param irow * index * @return index (-1 if empty matrix) * @throws EuclidRuntimeException * bad value of irow */ public int indexOfLargestElementInRow(int irow) throws EuclidRuntimeException { checkRow(irow); int imax = -1; int max = Integer.MIN_VALUE; for (int jcol = 0; jcol < cols; jcol++) { if (max < flmat[irow][jcol]) { max = flmat[irow][jcol]; imax = jcol; } } return imax; } /** * get index of smallest element in column. * * @param jcol * index * @return index (-1 if empty matrix) * @throws EuclidRuntimeException * bad value of jcol */ public int indexOfSmallestElementInColumn(int jcol) throws EuclidRuntimeException { checkColumn(jcol); int imin = -1; int min = Integer.MAX_VALUE; for (int irow = 0; irow < rows; irow++) { if (min > flmat[irow][jcol]) { min = flmat[irow][jcol]; imin = irow; } } return imin; } protected boolean checkNonEmptyMatrix() { return (cols > 0 && rows > 0); } /** * get value of largest element in a row. * * @param irow * @return value (0 if no columns) * @throws EuclidRuntimeException */ public int largestElementInRow(int irow) throws EuclidRuntimeException { int idx = indexOfLargestElementInRow(irow); if (idx < 0) { throw new EuclidRuntimeException("empty matrix"); } return this.elementAt(irow, idx); } /** * get index of smallest element in row. * * @param irow * index * @return index (-1 if empty matrix) * @throws EuclidRuntimeException * bad value of irow */ public int indexOfSmallestElementInRow(int irow) throws EuclidRuntimeException { checkRow(irow); int imin = -1; int min = Integer.MAX_VALUE; for (int jcol = 0; jcol < cols; jcol++) { if (min > flmat[irow][jcol]) { min = flmat[irow][jcol]; imin = jcol; } } return imin; } /** * get value of smallest element. * * @return value * @throws EuclidRuntimeException */ public int smallestElement() throws EuclidRuntimeException { Int2 temp = indexOfSmallestElement(); return this.elementAt(temp); } /** * get index of smallest element. * * @return (row,col) or null for empty matrix */ public Int2 indexOfSmallestElement() { int f = Integer.MAX_VALUE; int im = -1; int jm = -1; for (int irow = 0; irow < rows; irow++) { for (int jcol = 0; jcol < cols; jcol++) { if (f > flmat[irow][jcol]) { f = flmat[irow][jcol]; im = irow; jm = jcol; } } } return (im >= 0) ? new Int2(im, jm) : null; } /** * get smallest element in a column. * * @param jcol * @return smallest value * @exception EuclidRuntimeException * bad value of jcol */ public int smallestElementInColumn(int jcol) throws EuclidRuntimeException { int idx = indexOfSmallestElementInColumn(jcol); if (idx < 0) { throw new EuclidRuntimeException("empty matrix"); } return this.elementAt(idx, jcol); } /** * get smallest element in a row. * * @param irow * @return smallest value * @exception EuclidRuntimeException * bad value of irow */ public int smallestElementInRow(int irow) throws EuclidRuntimeException { int idx = indexOfSmallestElementInRow(irow); if (idx < 0) { throw new EuclidRuntimeException("empty matrix"); } return this.elementAt(irow, idx); } /** * is matrix Orthogonal row-wise. * * that is row(i) * row(j) = 0 if i not equals j. * * @return true if orthogonal */ public boolean isOrthogonal() { for (int i = 1; i < rows; i++) { IntArray rowi = extractRowData(i); int dot = 0; for (int j = i + 1; j < rows; j++) { IntArray rowj = extractRowData(j); dot = rowi.dotProduct(rowj); if (dot != 0) return false; } } return true; } /** * get column data from matrix. * * @param col * the column * @return the column data (or length rows) * @throws EuclidRuntimeException */ public IntArray extractColumnData(int col) throws EuclidRuntimeException { checkColumn(col); IntArray fa = new IntArray(rows); for (int i = 0; i < rows; i++) { fa.setElementAt(i, this.flmat[i][col]); } return fa; } /** * get row data from matrix. * * @param row * the column * @return the column data (of length cols) */ public IntArray extractRowData(int row) { return new IntArray(flmat[row]); } /** * clear matrix. */ public void clearMatrix() { for (int irow = 0; irow < rows; irow++) { for (int jcol = 0; jcol < cols; jcol++) { flmat[irow][jcol] = 0; } } } /** * initialise matrix to given int. * * @param f */ public void setAllElements(int f) { for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { flmat[i][j] = f; } } } /** * transpose matrix - creates new Matrix * * @return transpose */ public IntMatrix getTranspose() { int[][] m = new int[cols][rows]; for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { m[j][i] = this.flmat[i][j]; } } return new IntMatrix(m); } /** * is the matrix square * * @return is square */ public boolean isSquare() { return (cols == rows && cols > 0); } /** * delete column from matrix and close up. no-op if impermissible value of * col * * @param col * the column */ public void deleteColumn(int col) { if (col >= 0 && col < cols) { int[][] temp = new int[rows][cols - 1]; for (int i = 0; i < rows; i++) { for (int j = 0; j < col; j++) { temp[i][j] = flmat[i][j]; } for (int j = col + 1; j < cols; j++) { temp[i][j - 1] = flmat[i][j]; } } cols--; flmat = temp; } } /** * delete 2 or more adjacent columns (inclusive) from matrix and close up. * no action if impermissible value of low and high * * @param low * start column * @param high * end column */ public void deleteColumns(int low, int high) { high = (high > cols - 1) ? cols - 1 : high; low = (low < 0) ? 0 : low; for (int i = 0; i < rows; i++) { this.flmat[i] = IntArray.deleteElements(this.flmat[i], low, high); } this.cols -= (high - low + 1); } /** * delete row from matrix and close up. * * @param row */ public void deleteRow(int row) { deleteRows(row, row); } /** * delete 2 or more adjacent rows (inclusive) from matrix and close up. if * (high > rows-1 high -> rows-1; or low < 0, low -> 0 * * @param low * start row * @param high * end row */ public void deleteRows(int low, int high) { high = (high >= rows) ? rows - 1 : high; low = (low < 0) ? 0 : low; if (low > high) return; int newrows = rows + high - low - 1; int temp[][] = new int[newrows][cols]; int oldrow = 0; int newrow = 0; while (oldrow < rows) { if (oldrow < low || oldrow > high) { temp[newrow++] = flmat[oldrow]; } oldrow++; } this.rows = newrows; flmat = temp; } /** * replace data in a single column. * * @param column * @param f * data must be of length rows * @throws EuclidRuntimeException */ public void replaceColumnData(int column, IntArray f) throws EuclidRuntimeException { checkRows(f); checkColumn(column); int[] temp = f.getArray(); for (int i = 0; i < rows; i++) { flmat[i][column] = temp[i]; } } private void checkRows(IntArray f) throws EuclidRuntimeException { if (f == null || f.size() != rows) { throw new EuclidRuntimeException("incompatible value of array size: " + f.size() + S_SLASH + rows); } } private void checkColumns(IntArray f) throws EuclidRuntimeException { if (f == null || f.size() != cols) { throw new EuclidRuntimeException("incompatible value of array size: " + f.size() + S_SLASH + cols); } } private void checkColumns(IntSet is) throws EuclidRuntimeException { if (is == null || is.size() != cols) { throw new EuclidRuntimeException("incompatible value of IntSet size: " + is.size() + S_SLASH + cols); } } private void checkColumns(IntMatrix m) throws EuclidRuntimeException { if (m == null || m.getCols() != cols) { throw new EuclidRuntimeException("incompatible value of matrix size: " + m.getCols() + S_SLASH + cols); } } private void checkRows(IntMatrix m) throws EuclidRuntimeException { if (m == null || m.getRows() != rows) { throw new EuclidRuntimeException("incompatible value of matrix size: " + m.getRows() + S_SLASH + rows); } } /** * replace data in a single column. * * @param starting_col * @param f * data must be of length rows * @throws EuclidRuntimeException */ public void replaceColumnData(int starting_col, int[] f) throws EuclidRuntimeException { replaceColumnData(starting_col, new IntArray(rows, f)); } /** * replace data in a block of columns. * * @param start_column * (gets overwritten) * @param m * must have same row count and fit into gap * @throws EuclidRuntimeException */ public void replaceColumnData(int start_column, IntMatrix m) throws EuclidRuntimeException { // must trap copying a matrix into itself! if (this == m) { return; } cols = this.getCols(); int mcols = m.getCols(); checkRows(m); if (start_column < 0) { throw new EuclidRuntimeException("cannot start at negative column: " + start_column); } int end_column = start_column + mcols; if (end_column > cols) { throw new EuclidRuntimeException("too many columns to copy: " + start_column + "|" + mcols + S_SLASH + cols); } copyColumns(m.flmat, start_column, mcols); } private void copyColumns(int[][] mat, int start_column, int nToCopy) { for (int j = 0; j < nToCopy; j++) { for (int i = 0; i < rows; i++) { this.flmat[i][start_column + j] = mat[i][j]; } } } /** * insert a hole into the matrix and expand. result is blank space in matrix * * @param after_col * @param delta_cols */ public void makeSpaceForNewColumns(int after_col, int delta_cols) { if (after_col >= 0 && after_col <= cols && delta_cols > 0) { int newcols = delta_cols + cols; IntMatrix temp = new IntMatrix(rows, newcols); for (int irow = 0; irow < rows; irow++) { for (int jcol = 0; jcol < after_col; jcol++) { temp.flmat[irow][jcol] = this.flmat[irow][jcol]; } for (int jcol = after_col; jcol < cols; jcol++) { temp.flmat[irow][jcol + delta_cols] = this.flmat[irow][jcol]; } } shallowCopy(temp); } } /** * add data as column or column block into matrix and expand. column is * inserted after given column * * @param after_col * -1 to cols-1 * @param f * @throws EuclidRuntimeException */ public void insertColumnData(int after_col, IntArray f) throws EuclidRuntimeException { checkRows(f); if (cols == 0) { rows = f.size(); flmat = new int[rows][1]; int[] arr = f.getArray(); cols = 1; for (int i = 0; i < rows; i++) { flmat[i][0] = arr[i]; } } else { if (f.size() == rows) { makeSpaceForNewColumns(after_col + 1, 1); replaceColumnData(after_col + 1, f); } } } /** * add data as column or column block into matrix and expand. * * @param afterCol * -1 to cols-1 * @param m * @throws EuclidRuntimeException */ public void insertColumnData(int afterCol, IntMatrix m) throws EuclidRuntimeException { // must trap copying a matrix into itself! if (this == m) { return; } checkRows(m); int mcols = m.getCols(); cols = this.getCols(); if (afterCol < -1 || afterCol >= cols) { throw new EuclidRuntimeException("afterCol must be >= -1 or < cols: " + afterCol); } makeSpaceForNewColumns(afterCol + 1, mcols); replaceColumnData(afterCol + 1, m); } /** * make space for new rows in matrix and expand. * * @param after_row * -1 to rows-1 * @param delta_rows * size of space */ public void insertRows(int after_row, int delta_rows) { if (after_row >= 0 && after_row <= cols && delta_rows > 0) { int newrows = delta_rows + rows; IntMatrix temp = new IntMatrix(newrows, cols); for (int jcol = 0; jcol < cols; jcol++) { for (int irow = 0; irow < after_row; irow++) { temp.flmat[irow][jcol] = this.flmat[irow][jcol]; } for (int irow = after_row; irow < rows; irow++) { temp.flmat[irow + delta_rows][jcol] = this.flmat[irow][jcol]; } } shallowCopy(temp); } } /** * overwrite existing row of data. * * @param row * to replace * @param f * row to use * @exception EuclidRuntimeException * f.size() and cols differ */ public void replaceRowData(int row, IntArray f) throws EuclidRuntimeException { checkColumns(f); int mcols = f.size(); System.arraycopy(f.getArray(), 0, flmat[row], 0, mcols); } /** * overwrite existing row of data. * * @param row * to replace * @param f * row to use * @exception EuclidRuntimeException * f.length and cols differ */ public void replaceRowData(int row, int[] f) throws EuclidRuntimeException { IntArray temp = new IntArray(cols, f); replaceRowData(row, temp); } /** * overwrite existing block of rows; if too big, copying is truncated * * @param afterRow * from -1 to rows-1 * @param m * data to replace with * @exception EuclidRuntimeException * m.rows and this.rows differ */ public void replaceRowData(int afterRow, IntMatrix m) throws EuclidRuntimeException { // must trap copying a matrix into itself! if (this == m) return; checkColumns(m); if (afterRow < -1) { throw new EuclidRuntimeException("afterRow must be >= -1 :" + afterRow); } if (!(afterRow <= (rows - m.rows))) { throw new EuclidRuntimeException("afterRow (" + afterRow + ")must be <= rows (" + rows + ") - m.rows (" + m.rows + S_RBRAK); } copyRowData(m.flmat, afterRow + 1, m.rows); } /** * insert 2 or more adjacent rows of data into matrix and expand * * @param afterRow * from -1 to rows-1 * @param m * data to insert * @exception EuclidRuntimeException * m.cols and this.colsdiffer */ public void insertRowData(int afterRow, IntMatrix m) throws EuclidRuntimeException { // must trap copying a matrix into itself! if (this == m) { return; } rows = this.getRows(); int mrows = m.getRows(); checkColumns(m); if (afterRow < -1) { throw new EuclidRuntimeException("must insert after -1 or higher"); } if (afterRow >= rows) { throw new EuclidRuntimeException("must insert after nrows-1 or lower"); } insertRows(afterRow + 1, mrows); copyRowData(m.flmat, afterRow + 1, mrows); } private void copyRowData(int[][] mat, int afterRow, int nrows) { for (int i = 0; i < nrows; i++) { for (int j = 0; j < cols; j++) { this.flmat[afterRow + i][j] = mat[i][j]; } } } /** * insert row of data into matrix and expand. * * @param after_row * from -1 to rows-1 * @param f * data to insert * @exception EuclidRuntimeException * f.size() and this.cols differ */ public void insertRowData(int after_row, IntArray f) throws EuclidRuntimeException { checkColumns(f); int mcols = f.size(); if (after_row >= -1 && after_row <= rows && mcols == cols) { insertRows(after_row + 1, 1); replaceRowData(after_row + 1, f); } else { throw new EuclidRuntimeException("Cannot add array after row" + after_row + S_SLASH + rows + "==" + mcols + S_SLASH + cols); } } /** * append data to matrix columnwise. * * @param f * data to append * @exception EuclidRuntimeException * f.size() and this.rows differ */ public void appendColumnData(IntArray f) throws EuclidRuntimeException { if (cols == 0) { rows = f.size(); } insertColumnData(cols - 1, f); } /** * append data to matrix columnwise. * * @param m data to append * @exception EuclidRuntimeException m.rows and this.rows differ */ public void appendColumnData(IntMatrix m) throws EuclidRuntimeException { if (cols == 0) { rows = m.getRows(); } insertColumnData(cols - 1, m); } /** * append data to matrix rowwise. * * @param f * data to append * @exception EuclidRuntimeException * m.cols and this.cols differ */ public void appendRowData(IntArray f) throws EuclidRuntimeException { if (rows == 0) { cols = f.size(); } insertRowData(rows - 1, f); } /** * append data to matrix rowwise. * * @param m * data to append * @exception EuclidRuntimeException * m.cols and this.cols differ */ public void appendRowData(IntMatrix m) throws EuclidRuntimeException { if (rows == 0) { cols = m.getCols(); } insertRowData(rows - 1, m); } /** * replaces the data in a submatrix. starts at (low_row, low_col) and * extends by the dimensions for the matrix m * * @param low_row * starting row * @param low_col * starting col * @param m * data to append */ public void replaceSubMatrixData(int low_row, int low_col, IntMatrix m) { if (this == m) return; if (low_row > 0 && low_col > 0) { int mrows = m.getRows(); int mcols = m.getCols(); if (low_row + mrows - 1 < rows && low_col + mcols - 1 < cols) { for (int i = 0; i < mrows; i++) { for (int j = 0; j < mcols; j++) { flmat[i + low_row - 1][j] = m.flmat[i][j]; } } } } } /** * reorder the columns of a matrix. * * @param is * indexes to reorder by * @exception EuclidRuntimeException * is.size() and this.cols differ * @return new matrix */ public IntMatrix reorderColumnsBy(IntSet is) throws EuclidRuntimeException { checkColumns(is); IntMatrix temp = new IntMatrix(rows, is.size()); for (int i = 0; i < is.size(); i++) { int icol = is.elementAt(i); if (icol >= cols || icol < 0) { throw new ArrayIndexOutOfBoundsException(); } IntArray coldat = this.extractColumnData(icol); temp.replaceColumnData(i, coldat); } return temp; } /** * reorder the rows of a matrix Deleting rows is allowed * * @param is * indexes to reprder by * @exception EuclidRuntimeException * is.size() and this.rows differ * @return matrix */ public IntMatrix reorderRowsBy(IntSet is) throws EuclidRuntimeException { if (is.size() != rows) { throw new EuclidRuntimeException("unequal matrices"); } IntMatrix temp = new IntMatrix(is.size(), cols); for (int i = 0; i < is.size(); i++) { int irow = is.elementAt(i); if (irow >= rows || irow < 0) { throw new EuclidRuntimeException("irow: " + irow); } IntArray rowdat = this.extractRowData(irow); temp.replaceRowData(i, rowdat); } return temp; } /** * extract a IntMatrix submatrix from a IntMatrix * * @param low_row * starting row * @param high_row * end row * @param low_col * starting col * @param high_col * end col * @exception EuclidRuntimeException * low/high_row/col are outside range of this * @return matrix */ public IntMatrix extractSubMatrixData(int low_row, int high_row, int low_col, int high_col) throws EuclidRuntimeException { return new IntMatrix(this, low_row, high_row, low_col, high_col); } /** * make an Int2_Array from columns. * * @param col1 * @param col2 * @throws EuclidRuntimeException * bad values of columns * @return 2*rows data */ public Int2Array extractColumns(int col1, int col2) throws EuclidRuntimeException { IntArray x = this.extractColumnData(col1); IntArray y = this.extractColumnData(col2); return new Int2Array(x, y); } /** * make an Int2_Array from rows. * * @param row1 * @param row2 * @throws EuclidRuntimeException * bad values of rows * @return 2*cols data */ public Int2Array extractRows(int row1, int row2) throws EuclidRuntimeException { IntArray x = this.extractRowData(row1); IntArray y = this.extractRowData(row2); return new Int2Array(x, y); } /** * produce a mask of those elements which fall in a range. result is matrix * with (1) else (0) * * @param r * the range * @throws EuclidRuntimeException * bad values of rows * @return matrix with 1s where data is in range else 0 */ public IntMatrix elementsInRange(IntRange r) throws EuclidRuntimeException { IntMatrix m = new IntMatrix(rows, cols); for (int irow = 0; irow < rows; irow++) { for (int jcol = 0; jcol < cols; jcol++) { int elem = 0; if (r.includes(elementAt(irow, jcol))) { elem = 1; } m.setElementAt(irow, jcol, elem); } } return m; } /** * output matrix - very crude * * @return the string */ public String toString() { StringBuffer sb = new StringBuffer(); // rows and cols if (rows > 0 && cols > 0) { sb.append(S_LCURLY); sb.append(rows); sb.append(S_COMMA); sb.append(cols); sb.append(S_RCURLY); } else { sb.append(S_LBRAK); } for (int i = 0; i < rows; i++) { sb.append(S_NEWLINE); sb.append(S_LBRAK); for (int j = 0; j < cols; j++) { if (j > 0) { sb.append(S_COMMA); } if (format == null) { sb.append(flmat[i][j]); } else { sb.append(format.format(flmat[i][j])); } } sb.append(S_RBRAK); } if (rows == 0 || cols == 0) { sb.append(S_RBRAK); } return sb.toString(); } /** * output xml as a CML matrix. * * @param w * the writer * @exception IOException */ public void writeXML(Writer w) throws IOException { StringBuffer sb = new StringBuffer(); sb.append(""); for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { if (i != 0 || j != 0) sb.append(S_SPACE); if (format == null) { sb.append(flmat[i][j]); } else { sb.append(format.format(flmat[i][j])); } } } sb.append(""); w.write(sb.toString()); } /** * should really be in IntMatrix */ public static List findLargestUniqueElementsInRowColumn(IntMatrix intMatrix) { List intList = new ArrayList(); for (int jcol = 0, max = intMatrix.getCols(); jcol < max; jcol++) { int irow = intMatrix.indexOfLargestElementInColumn(jcol); int maxval = intMatrix.elementAt(irow, jcol); if (maxval == -1) { irow = -1; } else { for (int ii = irow + 1, maxrow = intMatrix.getRows(); ii < maxrow; ii++) { int val = intMatrix.elementAt(ii, jcol); if (val >= maxval) { irow = -1; break; } } } intList.add(irow); } return intList; } } wwmm-euclid-87e8f785a814/src/main/java/org/xmlcml/euclid/IntRange.java0000644000000000000000000001175511607017524023511 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid; /** * maximum and minimum values * * Contains two ints representing the minimum and maximum of an allowed or * observed range. *

* Default is range with low > high; this can be regarded as the uninitialised * state. If points are added to a default IntRange it becomes initialised. * * @author (C) P. Murray-Rust, 1996 */ public class IntRange implements EuclidConstants { /** * maximum of range */ protected int maxval; /** * minimum of range */ protected int minval; /** * creates invalid range from MAX_VALUE to MIN_VALUE */ public IntRange() { minval = Integer.MAX_VALUE; maxval = Integer.MIN_VALUE; } /** * initialise with min and max values; if minv > maxv create inValid * IntRange * * @param minv * @param maxv */ public IntRange(int minv, int maxv) { maxval = maxv; minval = minv; if (minval > maxval) { minval = Integer.MAX_VALUE; maxval = Integer.MIN_VALUE; } } /** * copy constructor * * @param r */ public IntRange(IntRange r) { minval = r.minval; maxval = r.maxval; } /** * a Range is only valid if its maxval is not less than its minval; this * tests for uninitialised ranges * * @return valid */ public boolean isValid() { return (minval <= maxval); } /** * invalid ranges return false * * @param r * @return equals * */ public boolean isEqualTo(IntRange r) { return (r != null && minval == r.minval && maxval == r.maxval && minval <= maxval); } /** * combine two ranges if both valid; takes greatest limits of both, else * returns InValid * * @param r2 * @return range */ public IntRange plus(IntRange r2) { if (!this.isValid()) { if (r2 == null || !r2.isValid()) { return new IntRange(); } return new IntRange(r2); } IntRange temp = new IntRange(); temp = new IntRange(Math.min(minval, r2.minval), Math.max(maxval, r2.maxval)); return temp; } /** * intersect two ranges and take the range common to both; return invalid * range if no overlap * * @param r2 * @return range */ public IntRange intersectionWith(IntRange r2) { if (!isValid() || r2 == null || !r2.isValid()) { return new IntRange(); } int minv = Math.max(minval, r2.minval); int maxv = Math.min(maxval, r2.maxval); return new IntRange(minv, maxv); } /** * get minimum value (MAX_VALUE if inValid) * * @return min */ public int getMin() { return minval; } /** * get maximum value (MIN_VALUE if inValid) * * @return max * */ public int getMax() { return maxval; } /** * get range (MIN_VALUE if invalid) * * @return range */ public int getRange() { if (!isValid()) return Integer.MIN_VALUE; return maxval - minval; } /** * does one range include another * * @param r2 * @return includes */ public boolean includes(IntRange r2) { return (r2 != null && r2.isValid() && this.includes(r2.getMin()) && this .includes(r2.getMax())); } /** * is a int within a IntRange * * @param f * @return includes If inValid, return false */ public boolean includes(int f) { return f >= minval && f <= maxval; } /** * synonym for includes() * * @param f * @return includes */ public boolean contains(int f) { return includes(f); } /** * add a value to a range * * @param x */ public void add(int x) { maxval = Math.max(maxval, x); minval = Math.min(minval, x); } /** * to string * * @return string */ public String toString() { return (minval > maxval) ? "NULL" : S_LBRAK + minval + S_COMMA + maxval + S_RBRAK; } } wwmm-euclid-87e8f785a814/src/main/java/org/xmlcml/euclid/IntSet.java0000644000000000000000000003320511607017524023202 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.log4j.Logger; /** * public class IntSet * * Stores a unique set of ints (that is cannot contain duplicate ints. The * limits can be set with setMin and setMax. There are operations for combining * sets (for example NOT, OR) and sets can be built up incrementally. *

* Inverse mapping. IntSets can be used to map one set of indexed data to * another, for example *

* RealArray x = someFunction();
* InstSet idx = x.indexSortAscending();
* for (int i = 0; i < x.size(); i++) {
* y[i] = x[idx[i]];
}
*
To map the other way, x[i] = y[inv[i]]; the inverse IntSet * can be used * * @author (C) P. Murray-Rust, 1996 */ public class IntSet implements EuclidConstants { final static Logger logger = Logger.getLogger(IntSet.class.getName()); private int array[]; private int nelem = 0; private int min = Integer.MIN_VALUE; private int max = Integer.MAX_VALUE; Set set; /** gets all permutations of integers from 0 to n-1. * crude * @param number * @return list of all permutations (no special order) */ public static Map>> integerMap = new HashMap>>(); /** * constructor. */ public IntSet() { initialise(0, 0, true); } /** * creates an IntSet with the integers 0...nelem-1 * * @param nelem */ public IntSet(int nelem) { nelem = (nelem < 0) ? 0 : nelem; this.nelem = nelem; initialise(0, nelem, true); } /** * creates an IntSet with the integers start...end (if start <= end) * * @param start * @param end * */ public IntSet(int start, int end) { nelem = end - start + 1; if (nelem <= 0) { nelem = 0; } initialise(start, nelem, true); } /** * copy constructor * * @param is */ public IntSet(IntSet is) { if (is != null) { array = is.array; System.arraycopy(is.array, 0, array, 0, nelem); nelem = is.nelem; min = is.min; max = is.max; this.set = new HashSet(); for (Integer ii : is.set) { this.set.add(ii); } } } /** * make from an int[] - all values must be distinct; * * @param is * @exception EuclidRuntimeException * values were not distinct */ public IntSet(int[] is) throws EuclidRuntimeException { nelem = is.length; initialise(0, nelem, false); int i = 0; for (int ii : is) { if (this.contains(ii)) { throw new EuclidRuntimeException("Duplicate value: " + i); } array[i++] = ii; set.add(new Integer(ii)); } } /** * use another IntSet to subscript this one that is I(new) = I(this) * subscripted by I(sub); Result has dimension of I(sub). If any of I(sub) * lies outside 0...this.size()-1, throw an error * * @param sub * @return the matrix * * @throws EuclidRuntimeException */ public IntSet getSubscriptedIntSet(IntSet sub) throws EuclidRuntimeException { IntSet is = new IntSet(sub.size()); for (int i = 0; i < sub.size(); i++) { int j = sub.elementAt(i); if (j < 0 || j >= this.nelem) { throw new EuclidRuntimeException("sub index (" + j + ") too large for " + this.toString()); } is.setElementAt(i, this.array[j]); } return is; } private void initialise(int start, int nelem, boolean addSet) { array = new int[nelem]; set = new HashSet(); int nToAdd = nelem /* - start */; for (int i = 0; i < nToAdd; i++) { array[i] = start + i; if (addSet) { set.add(new Integer(array[i])); } } } /** * element-by-element comparison of sets * * @param is * @return equal */ public boolean isEqualTo(IntSet is) { for (int i = 0; i < nelem; i++) { if (array[i] != is.array[i]) return false; } return true; } /** * get elements. * * @return elements as array */ public int[] getElements() { // since the array may have spare space, contract if (nelem != array.length) { int[] temp = new int[nelem]; System.arraycopy(array, 0, temp, 0, nelem); array = temp; } return array; } /** * set maximum allowed value. if current set has elements greater than max * throws exception. * * @param max * @exception EuclidRuntimeException */ public void setMax(int max) throws EuclidRuntimeException { for (int i = 0; i < nelem; i++) { if (array[i] > max) { throw new EuclidRuntimeException("element in set (" + array[i] + ") greater than new max (" + max + S_RBRAK); } } this.max = max; } /** * set minimum allowed value. if current set has elements less than min * throws exception. * * @param min * @exception EuclidRuntimeException */ public void setMin(int min) { for (int i = 0; i < nelem; i++) { if (array[i] < min) { throw new EuclidRuntimeException("element in set (" + array[i] + ") less than new max (" + max + S_RBRAK); } } this.min = min; } /** * size of array. * * @return size */ public int size() { return nelem; } /** * add integer Fails if it is outside limits or already exists in set * * @param value * @return if successful * * @throws EuclidRuntimeException */ public boolean addElement(int value) throws EuclidRuntimeException { if (value < min || value > max) { throw new EuclidRuntimeException("value (" + value + ")outside range (" + min + "..." + max + S_RBRAK); } if (set.contains(value)) { throw new EuclidRuntimeException("value already in set: " + value); } if (nelem >= array.length) { int nbuff = (array.length == 0) ? 1 : array.length; while (nelem >= nbuff) { nbuff *= 2; } int temp[] = new int[nbuff]; for (int i = 0; i < nelem; i++) { temp[i] = array[i]; } array = temp; } array[nelem++] = value; set.add(new Integer(value)); return true; } /** * does set contain value. * * @param value * @return tur if contains */ public boolean contains(int value) { return set.contains(new Integer(value)); } /** * get element. * * @param i * @return element * @throws ArrayIndexOutOfBoundsException */ public int elementAt(int i) throws ArrayIndexOutOfBoundsException { if (i < 0 || i >= nelem) { throw new ArrayIndexOutOfBoundsException(); } return array[i]; } /** * gets the ints as an IntArray. * * @see #getElements() * @return the array */ public IntArray getIntArray() { int[] temp = new int[nelem]; System.arraycopy(array, 0, temp, 0, nelem); return new IntArray(temp); } /** * sort the IntSet; MODIFIES 'this' */ public void sortAscending() { IntArray temp = this.getIntArray(); temp.sortAscending(); for (int i = 0; i < nelem; i++) { array[i] = temp.array[i]; } } /** * concatenate sets. * * @param is * set to append * @throws EuclidRuntimeException * if there are elements in common or exceed max/min */ public void addSet(IntSet is) throws EuclidRuntimeException { for (int i = 0; i < is.nelem; i++) { int ii = is.elementAt(i); if (this.contains(ii)) { throw new EuclidRuntimeException("duplicate element " + ii); } this.addElement(ii); } } /** * intersect two sets (that is elements common to both) * * @param is * @return set * */ public IntSet intersectionWith(IntSet is) { IntSet ix = new IntSet(); for (int i = 0; i < is.nelem; i++) { int ii = is.elementAt(i); if (this.contains(ii)) { ix.addElement(ii); } } return ix; } /** * elements only in first set * * @param is * @return set */ public IntSet notIn(IntSet is) { IntSet ix = new IntSet(); for (int i = 0; i < this.nelem; i++) { int ii = this.elementAt(i); if (!is.contains(ii)) { ix.addElement(ii); } } return ix; } /** * add all values from an IntRange if range is 2,5 adds 2,3,4,5 * * @param ir */ public void addRange(IntRange ir) { if (ir == null) return; for (int i = ir.getMin(); i <= ir.getMax(); i++) { this.addElement(i); } } /** * Inverse mapping - see introduction if y[i] = x[this.elementAt(i)]; * then the result supports x[i] = y[inv.elementAt(i)]; * * @exception ArrayIndexOutOfBoundsException * the set must contain the integers 0...nelem-1 * @return inverse map */ public IntSet inverseMap() throws ArrayIndexOutOfBoundsException { IntSet temp = new IntSet(this.size()); for (int i = 0; i < size(); i++) { temp.setElementAt(this.elementAt(i), i); } return temp; } /** * private routine to set elements; check is made on the index, but not on * duplicate values */ void setElementAt(int i, int value) throws ArrayIndexOutOfBoundsException { if (i >= size()) { throw new ArrayIndexOutOfBoundsException(); } array[i] = value; } /** * debug. */ public void debug() { for (int i = 0; i < nelem; i++) { Util.print(S_SPACE + array[i]); } Util.println(); } /** * to string. * * @return string */ public String toString() { StringBuffer s = new StringBuffer(); s.append(S_LBRAK); for (int i = 0; i < nelem; i++) { if (i > 0) { s.append(S_COMMA); } s.append(array[i]); } s.append(S_RBRAK); return s.toString(); } private static List copy(List list) { List newList = new ArrayList(); for (Integer ii : list) { newList.add(ii); } return newList; } /** create all permutations of an integer. * runs from 0,1,... number-1 * @param number * @return */ public static List getPermutations(Integer number) { List intArrayList = new ArrayList(); List> intListList = IntSet.getPermutations0(number); for (List intList : intListList) { int size = intList.size(); int[] ints = new int[size]; for (int i = 0; i < size; i++) { ints[i] = intList.get(i).intValue(); } intArrayList.add(ints); } return intArrayList; } /** create all permutations of an integer. * runs from 0,1,... number-1 * @param number * @return */ private static List> getPermutations0(Integer number) { List> listList = IntSet.integerMap.get(number); if (listList == null) { listList = new ArrayList>(); if (number.equals(0)) { listList.add(new ArrayList()); } else { List> listListMinus = IntSet.getPermutations0(new Integer(number - 1)); for (List listMinus : listListMinus) { for (Integer ii = 0; ii < number; ii++) { List copyList = IntSet.copy(listMinus); copyList.add(ii.intValue(), number); listList.add(copyList); } } } IntSet.integerMap.put(number, listList); } return listList; } } wwmm-euclid-87e8f785a814/src/main/java/org/xmlcml/euclid/IntSquareMatrix.java0000644000000000000000000002733211607017524025100 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid; import org.apache.log4j.Logger; /** * square matrix class * * IntSquareMatrix represents a square m-x-m matrix. The basic matrix algebra * for square matrices is represented here Check out the exciting member * functions, which are supported by Exceptions where appropriate. (NB. No * attempt has been made to provide numerical robustness and inversion, * diagonalisation, etc are as you find them.) *

* * @author (C) P. Murray-Rust, 1996 */ public class IntSquareMatrix extends IntMatrix { /** * helper class to provide types of matrix. */ /** type */ public enum Type { /** */ UPPER_TRIANGLE(1), /** */ LOWER_TRIANGLE(2), /** */ SYMMETRIC(3), /** */ DIAGONAL(4), /** */ OUTER_PRODUCT(5), /** */ UNKNOWN(6); /** integer value */ public int i; private Type(int i) { this.i = i; } } final static Logger logger = Logger.getLogger(IntSquareMatrix.class .getName()); /** * Constructor. This gives a default matrix with cols = rows = 0. */ public IntSquareMatrix() { super(); } /** * Constructor. * * @param rows * number of rows and columns values are set to zero */ public IntSquareMatrix(int rows) { super(rows, rows); } /** * Creates square matrix from real matrix. * * @param f * real array (length rows) multiplied to give outer product * @return square matrix of size rows * rows */ public static IntSquareMatrix outerProduct(IntArray f) { int rows = f.size(); IntSquareMatrix temp = new IntSquareMatrix(rows); for (int i = 0; i < rows; i++) { for (int j = 0; j < rows; j++) { temp.flmat[i][j] = f.elementAt(i) * f.elementAt(j); } } return temp; } /** * create diagonal matrix from real matrix. * * @param f * real array (length rows) * @return square matrix with elem (i, i) = f(i), else 0 */ public static IntSquareMatrix diagonal(IntArray f) { int rows = f.size(); IntSquareMatrix temp = new IntSquareMatrix(rows); for (int i = 0; i < rows; i++) { temp.flmat[i][i] = f.elementAt(i); } return temp; } /** * Creates real square matrix from array THE COLUMN IS THE FASTEST MOVING * INDEX, that is the matrix is filled as mat(0,0), mat(0,1) ... C-LIKE * * @param rows * the final rows and cols of real square matrix * @param array * of size (rows * rows) * @exception EuclidRuntimeException * array size must be multiple of rows */ public IntSquareMatrix(int rows, int[] array) { super(rows, rows, array); } /** * Creates real square matrix with all elements initialized to int value. * * @param rows * size of square matrix * @param f * value of all elements */ public IntSquareMatrix(int rows, int f) { super(rows, rows, f); } /** * Constructor for submatrix of another matrix. * * @param m * matrix to slice (need not be square) * @param lowrow * the start row inclusive (count from 0) * @param lowcol * the start column inclusive (count from 0) * @param rows * size of final matrix * @throws EuclidRuntimeException */ public IntSquareMatrix(IntMatrix m, int lowrow, int lowcol, int rows) throws EuclidRuntimeException { super(m, lowrow, lowrow + rows - 1, lowcol, lowcol + rows - 1); } /** * copy constructor. * * @param m * matrix to copy */ public IntSquareMatrix(IntSquareMatrix m) { super(m); } /** * shallow copy from IntMatrix * * the array values are not copied (only the reference) * * @param m * matrix to copy reference from * * @exception EuclidRuntimeException * m must be square (that is cols = rows) */ public IntSquareMatrix(IntMatrix m) throws EuclidRuntimeException { super(m.rows, m.cols); if (m.cols != m.rows) { throw new EuclidRuntimeException("non square matrix"); } this.flmat = m.flmat; } /** * constructor from array. * * form from a Java 2-D array (it holds row and column count) * * @param matrix * to copy * @exception EuclidRuntimeException * matrix is not square (might even not be * rectangular!) */ public IntSquareMatrix(int[][] matrix) throws EuclidRuntimeException { super(matrix); if (cols != rows) { throw new EuclidRuntimeException("non square matrix"); } } /** * shallowCopy an existing square matrix. * * @param m * matrix to shallow copy * @exception EuclidRuntimeException * m must have the same number of rows and cols as * this */ public void shallowCopy(IntSquareMatrix m) throws EuclidRuntimeException { super.shallowCopy((IntMatrix) m); } /** * are two matrices identical * * @param r * matrix to compare * @return true if equal (see IntMatrix.equals for details) */ public boolean isEqualTo(IntSquareMatrix r) { return super.isEqualTo((IntMatrix) r); } /** * matrix addition. adds conformable matrices. Does NOT alter this. * * @param m * matrix to add * @exception EuclidRuntimeException * m must have the same number of rows and cols as * this * @return resultant matrix */ public IntSquareMatrix plus(IntSquareMatrix m) throws EuclidRuntimeException { IntMatrix temp = super.plus((IntMatrix) m); IntSquareMatrix sqm = new IntSquareMatrix(temp); return sqm; } /** * matrix subtraction. subtracts conformable matrices. Does NOT alter this. * * @param m * matrix to subtract from this * @exception EuclidRuntimeException * m must have the same number of rows and cols as * this * @return resultant matrix */ public IntSquareMatrix subtract(IntSquareMatrix m) throws EuclidRuntimeException { IntMatrix temp = super.subtract((IntMatrix) m); IntSquareMatrix sqm = new IntSquareMatrix(temp); return sqm; } /** * matrix multiplication. * * multiplies conformable matrices; result is this*m * * @param m * matrix to multiply by * @exception EuclidRuntimeException * m must have the same number of rows as this * has cols * @return new matrix */ public IntSquareMatrix multiply(IntSquareMatrix m) throws EuclidRuntimeException { IntMatrix temp = super.multiply((IntMatrix) m); IntSquareMatrix sqm = new IntSquareMatrix(temp); return sqm; } /** * trace. * * @return the trace */ public int trace() { int trace = 0; for (int i = 0; i < rows; i++) { trace += flmat[i][i]; } return trace; } /** * is it a unit matrix. * * @return are all diagonals 1 and off-diagonal zero (within Int.isEqual()) */ public boolean isUnit() { for (int i = 0; i < rows; i++) { for (int j = 0; j < rows; j++) { int f = flmat[i][j]; if ((f != 0 && (i != j)) || (f != 1 && (i == j))) { return false; } } } return true; } /** * is matrix symmetric. * * @return is Int.isEqual(elem(i,j), elem(j,i)) */ public boolean isSymmetric() { for (int i = 0; i < rows - 1; i++) { for (int j = i + 1; j < rows; j++) { if (flmat[i][j] != flmat[j][i]) { return false; } } } return true; } /** * is matrix UpperTriangular. * * @return true if all bottom triangle excluding diagona Int.isZero() */ public boolean isUpperTriangular() { for (int i = 1; i < rows; i++) { for (int j = 0; j < i; j++) { if (flmat[i][j] != 0) return false; } } return true; } /** * is matrix LowerTriangular. diagonal must also be zero * * @return true if all bottom triangle Int.isZero() */ public boolean isLowerTriangular() { for (int i = 0; i < rows - 1; i++) { for (int j = i + 1; j < rows; j++) { if (flmat[i][j] != 0) return false; } } return true; } /** * copy upper triangle into lower triangle. alters this to make it symmetric * * @return this as new square matrix */ public IntSquareMatrix copyUpperToLower() { for (int i = 0; i < cols - 1; i++) { for (int j = i + 1; j < cols; j++) { flmat[j][i] = flmat[i][j]; } } return this; } /** * copy lower triangle into upper triangle. alters this to make it symmetric * * @return this as new square matrix */ public IntSquareMatrix copyLowerToUpper() { for (int i = 0; i < cols - 1; i++) { for (int j = i + 1; j < cols; j++) { flmat[i][j] = flmat[j][i]; } } return this; } /** * copy lower triangle into linear array; order: 0,0; 1,0; 1,1; 2,0 * * @return linear array of size rows * (rows+1) / 2 */ public IntArray lowerTriangle() { int n = rows; IntArray triangle = new IntArray((n * (n + 1)) / 2); int count = 0; for (int i = 0; i < rows; i++) { for (int j = 0; j <= i; j++) { triangle.setElementAt(count++, flmat[i][j]); } } return triangle; } /** * transpose. MODIFIES this */ public void transpose() { for (int i = 0; i < rows; i++) { for (int j = 0; j < i; j++) { int t = flmat[i][j]; flmat[i][j] = flmat[j][i]; flmat[j][i] = t; } } } } wwmm-euclid-87e8f785a814/src/main/java/org/xmlcml/euclid/JodaDate.java0000644000000000000000000001654611607017524023460 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid; import java.util.Date; import org.joda.time.DateTime; import org.joda.time.DateTimeZone; import org.joda.time.MutableDateTime; import org.joda.time.format.DateTimeFormat; import org.joda.time.format.DateTimeFormatter; import org.joda.time.format.ISODateTimeFormat; /** * really just to remember at this stage * @author pm286 * The pattern syntax is mostly compatible with java.text.SimpleDateFormat - time zone names cannot be parsed and a few more symbols are supported. All ASCII letters are reserved as pattern letters, which are defined as follows: Symbol Meaning Presentation Examples ------ ------- ------------ ------- G era text AD C century of era (>=0) number 20 Y year of era (>=0) year 1996 x weekyear year 1996 w week of weekyear number 27 e day of week number 2 E day of week text Tuesday; Tue y year year 1996 D day of year number 189 M month of year month July; Jul; 07 d day of month number 10 a halfday of day text PM K hour of halfday (0~11) number 0 h clockhour of halfday (1~12) number 12 H hour of day (0~23) number 0 k clockhour of day (1~24) number 24 m minute of hour number 30 s second of minute number 55 S fraction of second number 978 z time zone text Pacific Standard Time; PST Z time zone offset/id zone -0800; -08:00; America/Los_Angeles ' escape for text delimiter '' single quote literal ' The count of pattern letters determine the format. Text: If the number of pattern letters is 4 or more, the full form is used; otherwise a short or abbreviated form is used if available. Number: The minimum number of digits. Shorter numbers are zero-padded to this amount. Year: Numeric presentation for year and weekyear fields are handled specially. For example, if the count of 'y' is 2, the year will be displayed as the zero-based year of the century, which is two digits. Month: 3 or over, use text, otherwise use number. Zone: 'Z' outputs offset without a colon, 'ZZ' outputs the offset with a colon, 'ZZZ' or more outputs the zone id. Zone names: Time zone names ('z') cannot be parsed. Any characters in the pattern that are not in the ranges of ['a'..'z'] and ['A'..'Z'] will be treated as quoted text. For instance, characters like ':', '.', ' ', '#' and '?' will appear in the resulting time text even they are not embraced within single quotes. DateTimeFormat is thread-safe and immutable, and the formatters it returns are as well. * */ public class JodaDate { // from W3C 2000-01-12T12:13:14Z // Wed Jul 8 10:53:24 PDT 1998 private static final String ALPHA_ZONE_PATTERN = "EEE MMM d HH:mm:ss ZZZ yyyy"; private static final DateTimeFormatter ALPHA_ZONE_FORMATTER = DateTimeFormat.forPattern(ALPHA_ZONE_PATTERN); // Wed Jul 8 10:53:24 1998 private static final String ALPHA_PATTERN1 = "EEE MMM d HH:mm:ss yyyy"; private static final String ALPHA_PATTERN2 = "EEE MMM dd HH:mm:ss yyyy"; private static final DateTimeFormatter ALPHA_FORMATTER1 = DateTimeFormat.forPattern(ALPHA_PATTERN1); private static final DateTimeFormatter ALPHA_FORMATTER2 = DateTimeFormat.forPattern(ALPHA_PATTERN2); private static final String DATETIME_PATTERN = "yyyy-MM-dd'T'HH:mm:ssZZ"; private static final DateTimeFormatter DATETIME_FORMATTER = DateTimeFormat.forPattern(DATETIME_PATTERN); private static final String ZULU_DATETIME_PATTERN = "yyyy-MM-dd'T'HH:mm:ss'Z"; private static final DateTimeFormatter ZULU_FORMATTER = DateTimeFormat.forPattern(ZULU_DATETIME_PATTERN); public static String formatDate(DateTime datetime) { if (DateTimeZone.UTC.equals(datetime.getZone())) { return ZULU_FORMATTER.print(datetime); } else { return DATETIME_FORMATTER.print(datetime); } } public static String formatIsoDate(DateTime datetime) { return ISODateTimeFormat.dateTime().print(datetime); } public static DateTime parseDate(String s) { if (s.endsWith("Z")) { MutableDateTime dateTime = ZULU_FORMATTER.parseMutableDateTime(s); dateTime.setZone(DateTimeZone.UTC); return dateTime.toDateTime(); } else if (Character.isLetter(s.charAt(0))){ DateTime dateTime = JodaDate.parseQuietly(ALPHA_FORMATTER2, s); if (dateTime == null) { dateTime = JodaDate.parseQuietly(ALPHA_FORMATTER1, s); } return dateTime; } else { return DATETIME_FORMATTER.parseDateTime(s); } } /** return null if fails * * @param formatter * @param s * @return */ public static DateTime parseQuietly(DateTimeFormatter formatter, String s) { DateTime dateTime = null; if (formatter != null) { try { dateTime = formatter.parseDateTime(s); } catch (Exception e) { // } } return dateTime; } public static DateTime parseDate(String date, String format) { DateTimeFormatter dateTimeFormatter = DateTimeFormat.forPattern(format); if (format.endsWith("Z")) { } else { dateTimeFormatter = dateTimeFormatter.withZone(DateTimeZone.forID("UTC")); } DateTime dateTime = dateTimeFormatter.parseDateTime(date); return dateTime.withZone(DateTimeZone.forID("UTC")); } public static DateTime parseJavaDate(Date javaDate) { long seconds = javaDate.getTime(); return new DateTime(seconds); } @SuppressWarnings("deprecation") public static Date parseJodaDate(DateTime jodaDate) { int year = jodaDate.getYear(); int month = jodaDate.getMonthOfYear(); int day = jodaDate.getDayOfMonth(); int hour = jodaDate.getHourOfDay(); int min = jodaDate.getMinuteOfDay(); int sec = jodaDate.getSecondOfMinute(); // arghh Date date = new Date(year-1900, month, day, hour, min, sec); return date; } } wwmm-euclid-87e8f785a814/src/main/java/org/xmlcml/euclid/Line2.java0000644000000000000000000001725011607017524022747 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid; import org.apache.log4j.Logger; /** line * determined by one point (R) and a vector (V) * this gives L = R + nV * can assume that R and R+V are the two "ends of the line" * the semantics of this are application-dependent * @author pm286 * */ public class Line2 implements EuclidConstants { private static Logger LOG = Logger.getLogger(Line2.class); private Real2 from; private Real2 to; private Vector2 vector; private Vector2 unitVector = null; // lazy evaluation private double slope = Double.NaN; private double c = Double.NaN; private double xint = Double.NaN; /** * generates vector * @param from * @param to */ public Line2(Real2 from, Real2 to) { vector = new Vector2(to.subtract(from)); if (vector.getLength() < Real.EPS) { LOG.warn("line has coincident points: "+from+" ... "+to); } this.from = new Real2(from); this.to = new Real2(to); init(); } private void init() { slope = Double.NaN; c = Double.NaN; xint = Double.NaN; } /** * generates to * @param from * @param v */ public Line2(Real2 from, Vector2 v) { if (v.getLength() < Real.EPS) { throw new EuclidRuntimeException("Cannot form line from coincident points"); } this.from = new Real2(from); this.vector = new Vector2(v); to = from.plus(v); } /** get slope. * "m" in y=m*x+c * if x component is zero returns Double.*_INFINITY; * @return slope, Double.POSITIVE_INFINITY or Double.NEGATIVE_INFINITY; */ public double getSlope() { if (Double.isNaN(slope)) { try { slope = vector.getY() / vector.getX(); } catch (ArithmeticException ae) { slope = (vector.getY() > 0) ? Double.POSITIVE_INFINITY : Double.NEGATIVE_INFINITY; } } return slope; } /** * * "c" in y=m*x+c * @return intercept or Double.NaN if slope is infinite */ public double getYIntercept() { if (Double.isNaN(c)) { getSlope(); if (!Double.isNaN(slope) && slope < Double.POSITIVE_INFINITY && slope > Double.NEGATIVE_INFINITY ) { c = from.getY() - from.getX() * slope; } } return c; } /** * "c" in y=m*x+c * @return intercept or Double.NaN if slope is infinite */ public double getXIntercept() { if (Double.isNaN(xint)) { getYIntercept(); if (Double.isNaN(slope) || Double.compare(slope, Double.NEGATIVE_INFINITY) == 0 || Double.compare(slope, Double.POSITIVE_INFINITY) == 0 ) { xint = from.getX(); } else if(Math.abs(slope) > Real.EPS) { xint = - c / slope; } } return xint; } /** get intersection of two lines * see softSurfer algorithm * @param line1 * @return null if parallel or antiparallel */ public Real2 getIntersection(Line2 line1) { Real2 inter = null; if (this.from.getDistance(line1.from) < Real.EPS) { inter = this.from; } else { double perpv = this.vector.getPerpProduct(line1.vector); Vector2 w = new Vector2(this.from.subtract(line1.from)); double perpw = line1.vector.getPerpProduct(w); // this = point + lambda * vector; double lambda = perpw / perpv; Real2 vv = vector.multiplyBy(lambda); inter = this.from.plus(vv); } return inter; } /** does a line contain a point. * line is of zero thickness * * @param point * @param eps distance within which point muct approach line * @param allowExtension if true allow point to be "outside" line * segment * @return true if within eps of line */ public boolean contains(Real2 point, double eps, boolean allowExtension) { boolean contains = false; if (point != null) { double dist = Math.abs(this.getDistanceFromPoint(point)); if (dist < eps) { double length = this.getLength() + eps; contains = allowExtension || (point.getDistance(from) < length && point.getDistance(to) < length); } } return contains; } /** swaps to and from coordinates. * */ public void flipCoordinates() { Real2 temp = from; from = to; to = temp; } /** * get unit vector convenience * @return vector */ public Vector2 getUnitVector() { if (unitVector == null) { unitVector = new Vector2(vector.getUnitVector()); } return unitVector; } /** perpendiculat distance from point to infinite line. * @param point * @return distance */ public double getDistanceFromPoint(Real2 point) { getUnitVector(); // LOG.debug(unitVector); Vector2 w = new Vector2(point.subtract(from)); // LOG.debug(w); return unitVector.getPerpProduct(w); } /** perpendiculat distance from point to infinite line. * @param point * @return distance */ public Real2 getNearestPointOnLine(Real2 point) { getUnitVector(); Vector2 lp = new Vector2(point.subtract(this.from)); // Vector2 ulp = new Vector2(lp.getUnitVector()); double lambda = unitVector.dotProduct(lp); Real2 vv = unitVector.multiplyBy(lambda); return from.plus(vv); } /** convenience method. * gets angle formed between lines using * Vector2.getAngleMadeWith(Vector2) * @param line * @return angle or null */ public Angle getAngleMadeWith(Line2 line) { Angle angle = null; if (line != null) { angle = this.getVector().getAngleMadeWith(line.getVector()); } return angle; } /** gets multiplier of point from "from" * finds nearest point (pp) on line (so avoids rounding errors) * then finds pp = from + vector * lambda * if pp is within segment , lambda is 0, 1 * @param p * @return lambda */ public double getLambda(Real2 p) { Real2 near = this.getNearestPointOnLine(p); Real2 delta = near.subtract(from); double lambda = (Math.abs(vector.getX()) > Math.abs(vector.getY())) ? delta.getX() / vector.getX() : delta.getY() / vector.getY(); return lambda; } /** get mid point * @return mid point */ public Real2 getMidPoint() { Real2 mm = this.from.plus(this.to); return mm.multiplyBy(0.5); } /** get length * @return length */ public double getLength() { return vector.getLength(); } /** * @return the from */ public Real2 getFrom() { return from; } /** * @return the to */ public Real2 getTo() { return to; } /** get point at either end. * * @param i (0/from or 1/to) * @return */ public Real2 getXY(int i) { Real2 xy = null; if (i == 0) { xy = from; } else if (i == 1) { xy = to; } else { throw new EuclidRuntimeException("Bad point in Line2 "+i); } return xy; } /** set point at either end. * * @param i (0/from or 1/to) * @return */ public void setXY(Real2 xy, int i) { if (i == 0) { from = new Real2(xy); } else if (i == 1) { to = new Real2(xy); } else { throw new EuclidRuntimeException("Bad point in Line2 "+i); } } /** * @return the vector */ public Vector2 getVector() { return vector; } /** * @return string */ public String toString() { return "line: from("+from+") to("+to+") v("+vector+")"; } } wwmm-euclid-87e8f785a814/src/main/java/org/xmlcml/euclid/Line3.java0000644000000000000000000001677311607017524022761 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid; /** * 3-dimensional line class * * Line3 represents a 3-dimensional line It is one of a set of primitives which * can be combined to create and manipulate complex 3-dimensional objects. Lines * can be transformed with rotation matrices or rotation-translation matrices * (Transform3), can be calculated from other primitives or can be used to * generate other primitives. * * * A line is a vector which is located in space. It is described by a unit * vector (vector) and a point (p) on the line. Any point on the line can be used for * p, and p could change during the existence of a calculation without affecting * the integrity of the line, for example p = {1,1,1}, vector = {1,0,0} is the same * line as p = {2,1,1}, vector = {1,0,0}. However the absolute direction of vector IS * important, giving the line a direction. * * Default is a default Point3 (0.0, 0.0, 0.0) and default Vector3 (0.0, 0.0, * 0.0). Operations on this line may lead to Exceptions such as * ZeroLengthVector. * * @author (C) P. Murray-Rust, 1996 */ public class Line3 implements EuclidConstants { /** * the (normalised) vector for the line */ Vector3 vect = new Vector3(); /** * any point on the line */ Point3 point = new Point3(); /** * contents as array */ // double[] array = new double[6]; /** * default consstructor. no vector and point set * */ public Line3() { } /** * construct from point and vector. the line will not necessarily retain the * exact point and the vector need not be normalized p and vector are copied * * @param p * a point on the line * @param v * non-zero vector through the point */ public Line3(Point3 p, Vector3 v) { vect = new Vector3(v); point = new Point3(p); if (!vect.isZero()) { // normalise vector vect.normalize(); } } /** * construct from array. dangerous as it is easy to muddle point and vector * * @param array * of length 6. first 3 are VECTOR, next are POINT */ /*-- public Line3(double[] array) throws EuclidRuntimeException { Util.check(array, 6); vect = new Vector3(); System.arraycopy(array, 0, vect.flarray, 0, 3); vect.normalize(); point = new Point3(); System.arraycopy(array, 3, point.flarray, 0, 3); System.arraycopy(array, 0, this.array, 0, 6); } --*/ /** * construct a line from two Point3s. the line will not necessarily retain * the exact points * * @param p1 * a point on the line * @param p2 * another point on the line */ public Line3(Point3 p1, Point3 p2) { this(p1, p2.subtract(p1)); } /** * copy constructor. * * @param l * Line3 to copy */ public Line3(Line3 l) { vect = new Vector3(l.vect); point = new Point3(l.point); } /** * are two lines identical. must be coincident and parallel uses * vect.equals() and containsPoint * * @param l2 * Line3 to compare * @return equals */ public boolean isEqualTo(Line3 l2) { if (!vect.isEqualTo(l2.vect)) { return false; } else { return containsPoint(l2.point); } } /** * form coincident antiparallel line. * * @return antiparallel line */ public Line3 negative() { Line3 l = new Line3(point, vect.negative()); return l; } /** * get return contents as an array. * * @return the array (v0, v1, v2, p0, p1, p2) */ /*-- public double[] getArray() { System.arraycopy(vect.flarray, 0, array, 0, 3); System.arraycopy(point.flarray, 0, array, 3, 3); return array; } --*/ /** * get vector from line. * * @return the vector (need not be normalized) */ public Vector3 getVector() { return vect; } /** * get point from line. * * @return any point on line */ public Point3 getPoint() { return point; } /** * get transformed line. does not alter this * * @param t * transform * @return transformed line */ public Line3 transform(Transform3 t) { Line3 lout = new Line3(); lout.point = point.transform(t); lout.vect = vect.transform(t); return lout; } /** * are two lines parallel. (not antiparallel) does not test coincidence * * @param l2 * line to compare * @return true if parallel */ public boolean isParallelTo(Line3 l2) { return vect.isIdenticalTo(l2.vect); } /** * are two lines antiparallel. (not parallel) does not test coincidence * * @param l2 * line to compare * @return true if antiparallel */ public boolean isAntiparallelTo(Line3 l2) { Vector3 v = new Vector3(l2.vect); return vect.isIdenticalTo(v.negative()); } /** * is a point on a line. tests for Real.isZero() distance from line * * @param p * point * @return true if within Real.isZero() */ public boolean containsPoint(Point3 p) { return Real.isZero(getDistanceFromPoint(p), Real.getEpsilon()); } /** * point on line closest to another point. * * @param p2 * reference point * @return point on line closest to p2 */ public Point3 getClosestPointTo(Point3 p2) { Point3 p1 = new Point3(); Vector3 v2 = new Vector3(p2); Vector3 v1 = new Vector3(point); p1 = point.plus(vect.multiplyBy((v2.subtract(v1)).dot(vect))); return p1; } /** * distance of a point from a line * * @param p * reference point * @return distance from line */ public double getDistanceFromPoint(Point3 p) { Point3 p0 = getClosestPointTo(p); Vector3 v = new Vector3(p.subtract(p0)); return v.getLength(); } /** * point of intersection of line and plane calls * Plane3.getIntersectionWith(Point3) * * @param pl * plane intersecting line * @return point (null if line parallel to plane) */ public Point3 getIntersectionWith(Plane3 pl) { return pl.getIntersectionWith(this); } /** * get string representation. * * @return string */ public String toString() { return S_LBRAK + vect + S_COMMA + point + S_RBRAK; } } wwmm-euclid-87e8f785a814/src/main/java/org/xmlcml/euclid/Plane3.java0000644000000000000000000002472211607017524023122 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid; import org.apache.log4j.Logger; /** * 3-dimensional plane class * * Plane3 represents a 3-dimensional plane. It is one of a set of primitives * which can be combined to create and manipulate complex 3-dimensional objects. * Planes can be transformed with rotation matrices or rotation-translation * matrices (Transform3), can be calculated from other primitives or can be used * to generate other primitives. *

* A plane is described by a unit vector (vector) and the perpendicular distance * (dist) of the plane from the origin. The absolute direction of the plane * (vector) IS important, giving the plane a direction (back and front faces). *

* The default plane is a Vector of (0.0, 0.0, 0.0) and a distance of 0.0. * Operations on this default may lead to Exceptions such as ZeroLengthvector. * * @author (C) P. Murray-Rust, 1996 */ public class Plane3 implements EuclidConstants { final static Logger logger = Logger.getLogger(Plane3.class.getName()); /** * vector of plane (normalised) */ protected Vector3 vect; /** * distance of plane from origin */ protected double dist; /** * status (OK or not) */ /** * 4-component array representing contents of vector and distance */ double[] array = new double[4]; /** * default constructor. uses default vector3 */ public Plane3() { vect = new Vector3(); dist = 0.0; } /** * formed from components. vector is normalised * * @param l * component * @param m * component * @param n * component * @param d * distance * @throws EuclidRuntimeException */ public Plane3(double l, double m, double n, double d) throws EuclidRuntimeException { vect = new Vector3(l, m, n); if (vect.isZero()) { throw new EuclidRuntimeException("zero length normal"); } dist = d; // normalise vector vect.normalize(); } /** * formed from components. vector is normalised * * @param lmn * component * @param d * distance * @throws EuclidRuntimeException */ public Plane3(double[] lmn, double d) throws EuclidRuntimeException { Util.check(lmn, 3); vect = new Vector3(lmn); dist = d; // normalise vector vect.normalize(); } /** * construct from array. * * @param array * 4-components * @throws EuclidRuntimeException */ public Plane3(double[] array) throws EuclidRuntimeException { Util.check(array, 4); vect = new Vector3(); System.arraycopy(array, 0, vect.flarray, 0, 3); dist = array[3]; System.arraycopy(array, 0, this.array, 0, 4); } /** * formed from plane and distance. vector is copied and normalised * * @param v * vector * @param d * distance * @throws EuclidRuntimeException */ public Plane3(Vector3 v, double d) throws EuclidRuntimeException { if (v.isZero()) { throw new EuclidRuntimeException("zero length normal"); } vect = new Vector3(v); dist = d; vect.normalize(); } /** * copy constructor: * * @param pl * place */ public Plane3(Plane3 pl) { vect = new Vector3(pl.vect); dist = pl.dist; } /** * make a plane from three points. * * @param p1 * point * @param p2 * point * @param p3 * point * @throws EuclidRuntimeException */ public Plane3(Point3 p1, Point3 p2, Point3 p3) throws EuclidRuntimeException { vect = new Vector3(); dist = 0.0; vect = (p2.subtract(p1)).cross(p3.subtract(p2)); if (vect.isZero()) { throw new EuclidRuntimeException("zero length normal"); } vect.normalize(); Vector3 vp1 = new Vector3(p1); dist = vp1.dot(vect); } /** * make a plane from a line and a point not on the line. * * @param l * point * @param p * point * @throws EuclidRuntimeException */ public Plane3(Line3 l, Point3 p) throws EuclidRuntimeException { // oKness dealt with by previous constructor this(l.getPoint(), (Point3) (l.getPoint().plus(l.getVector())), p); } /** * get return contents as an array. * * @return the array (l,m,n,d) */ public double[] getArray() { System.arraycopy(vect.flarray, 0, array, 0, 3); array[3] = dist; return array; } /** * get vector. * * @return the vector */ public Vector3 getVector() { return vect; } /** * get distance from origin. * * @return the distance */ public double getDistance() { return dist; } /** * reverse direction of plane. */ public void negative() { vect.negativeEquals(); } /** * are two planes coincident and parallel. * * @param pl2 * plane to compare * @return true if equal within Real.isEqual() */ public boolean isEqualTo(Plane3 pl2) { if (!vect.isEqualTo(pl2.vect)) return false; return Real.isEqual(pl2.dist, dist); } /** * form coincident antiparallel plane. * * @return antiparallel plane */ public Plane3 subtract() { Plane3 pl = this; pl.vect = pl.vect.negative(); return pl; } /** * distance of point from plane. will be a signed quantity * * @param p * the point * @return the distance */ public double getDistanceFromPoint(Point3 p) { Vector3 v = new Vector3(p); return (v.dot(vect) - dist); } /** * are two planes parallel. not antiparallel * * @param pl2 * the plane * @return true if parallel within Real.isEqual() */ public boolean isParallelTo(Plane3 pl2) { return vect.isIdenticalTo(pl2.vect); } /** * are two planes antiparallel. not parallel * * @param pl2 * the plane * @return true if antiparallel within Real.isEqual() */ public boolean isAntiparallelTo(Plane3 pl2) { Vector3 v = new Vector3(pl2.vect); return vect.isIdenticalTo(v.negative()); } /** * is a point on the plane. * * @param p * the point * @return true if within Real.isEqual() */ public boolean containsPoint(Point3 p) { return Real.isZero(this.getDistanceFromPoint(p), Real.getEpsilon()); } /** * point on plane closest to another point. if p2 is on plane then result * will coincide * * @param p2 * other point * @return the closest point */ public Point3 getClosestPointTo(Point3 p2) { Point3 p1 = new Point3(); double d = getDistanceFromPoint(p2); Vector3 v = new Vector3(vect.multiplyBy(d)); Vector3 vv = new Vector3(p2); p1 = new Point3(vv.subtract(v)); return p1; } /** * point of intersection of plane and line. * * @param l * line * @return intersection point (null if line parallel to plane) */ public Point3 getIntersectionWith(Line3 l) { Point3 p = null; double lambda; Vector3 v = new Vector3(l.getPoint()); Vector3 lvect = new Vector3(l.getVector()); double numer = dist - vect.dot(v); double denom = vect.dot(lvect); // check for line and plane parallel if (!Real.isZero(denom, Real.getEpsilon())) { lambda = numer / denom; p = l.getPoint().plus(lvect.multiplyBy(lambda)); } return p; } /** * get line as intersection of two planes. * * @param pl2 * plane * @return intersection line (null if parallel) */ public Line3 getIntersectionWith(Plane3 pl2) { Vector3 v3 = vect.cross(pl2.vect); v3.normalize(); // point on p1 nearest origin Point3 p = new Point3(vect.multiplyBy(dist)); Vector3 v1a = vect.cross(v3); Line3 l1 = new Line3(p, v1a); Point3 p2 = pl2.getIntersectionWith(l1); // this should take care of null vector (that is parallel planes) return (p2 == null) ? null : new Line3(p2, v3); } /** * point where three planes intersect * * @param pl2 * plane * @param pl3 * plane * @return intersection point (null if any planes parallel) */ public Point3 getIntersectionWith(Plane3 pl2, Plane3 pl3) { Point3 p = new Point3(); Line3 l = pl2.getIntersectionWith(pl3); p = getIntersectionWith(l); return p; } /** * the angle between 2 planes. * * @param pl2 * plane * @return the angle (unsigned) */ public Angle getAngleMadeWith(Plane3 pl2) { return this.getVector().getAngleMadeWith(pl2.getVector()); } /** * string representation. * * @return the string */ public String toString() { return EuclidConstants.S_LBRAK + vect + EuclidConstants.S_COMMA + dist + EuclidConstants.S_RBRAK; } } wwmm-euclid-87e8f785a814/src/main/java/org/xmlcml/euclid/Point2.java0000644000000000000000000000366711607017524023160 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid; /** * 2-dimensional point class * PROBABLY OBSOLETE - WE USE Real2 instead * * Point2 represents a 2-dimensional point. It is one of a set of primitives * which can be combined to create and manipulate complex 2-dimensional objects. * Points can be transformed with rotation matrices or rotation-translation * matrices (Transform2), can be calculated from other primitives or can be used * to generate other primitives. * * Default point is 0.0, 0.0 * * @author Peter Murray-Rust * * @author (C) P. Murray-Rust, 1996 */ public class Point2 extends Real2 { /** * the coordinates of the point */ // protected double[] p2_array; /** * constructor. */ public Point2() { super(); } /** * formed from point components * * @param x * @param y */ public Point2(double x, double y) { super(x, y); } /** * copy constructor * * @param p */ public Point2(Point2 p) { super(p); } /** * constructor from a double[] (or a RealArray) * * @param f */ public Point2(double[] f) { super(f); } } wwmm-euclid-87e8f785a814/src/main/java/org/xmlcml/euclid/Point3.java0000644000000000000000000004440411607017524023153 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid; import org.apache.log4j.Logger; /** * 3-dimensional point class * * * Point3 represents a 3-dimensional point. It is one of a set of primitives * which can be combined to create and manipulate complex 3-dimensional objects. * Points can be transformed with rotation matrices or rotation-translation * matrices (Transform3), can be calculated from other primitives or can be used * to generate other primitives. * * Default point is 0.0, 0.0, 0.0 * * @author Peter Murray-Rust * @see Vector3 * @see Line3 * @see Point3Vector * @see Plane3 * * @author (C) P. Murray-Rust, 1996 */ public class Point3 implements EuclidConstants { final static Logger logger = Logger.getLogger(Point3.class.getName()); /** * tolerance between crystal fractional coordinates. allows for 1/3 being * represented as 0.3333 which will not fit normal equality */ public final static double CRYSTALFRACTEPSILON = 0.001; /** * the coordinates of the point */ protected double[] flarray = new double[3]; /** * constructor. */ public Point3() { } /** * formed from point components * * @param x * @param y * @param z */ public Point3(double x, double y, double z) { flarray[0] = x; flarray[1] = y; flarray[2] = z; } /** * copy constructor * * @param p */ public Point3(Point3 p) { System.arraycopy(p.flarray, 0, flarray, 0, 3); } /** * constructor from a double[] (or a RealArray). * * @param f * @throws EuclidRuntimeException */ public Point3(double[] f) throws EuclidRuntimeException { Util.check(f, 3); System.arraycopy(f, 0, flarray, 0, 3); } /** * make a point from a vector creates the point at head of vector rooted at * the origin * * @param v */ public Point3(Vector3 v) { System.arraycopy(v.flarray, 0, flarray, 0, 3); } /** * get components as double[] * * @return the array */ public double[] getArray() { return flarray; } /** * sets the point to the origin */ public void clear() { flarray[0] = flarray[1] = flarray[2] = 0.0; } /** * are two points identical. compares content of points with Real.isEqual() * * @param p * point to compare * @return equal if coordinates are equal within Real.epsilon */ public boolean isEqualTo(Point3 p) { return Real.isEqual(flarray, p.flarray, Real.getEpsilon()); } /** * are two points identical. compares x, y, z coordinates of points * * @param p * point to compare * @param eps * the tolerance * @return equal if coordinates are equal within Real.epsilon */ public boolean isEqualTo(Point3 p, double eps) { return Real.isEqual(flarray, p.flarray, eps); } /** * are two crystallographic points identical. shifts x, y, z by +-1.0 if * necessary compares content of crystallographically normalised points with * Real.isEqual() * * @param p * point to compare * @return equal if coordinates are equal within CRYSTALFRACTEPSILON */ public boolean equalsCrystallographically(Point3 p) { Point3 crystal = new Point3(this); crystal.normaliseCrystallographically(); Point3 crystalP = new Point3(p); crystalP.normaliseCrystallographically(); return Real.isEqual(crystalP.flarray, crystal.flarray, Point3.CRYSTALFRACTEPSILON); } /** * normalise crystallographically. shifts x, y, z so that values lie between * 0.0 (inclusive) and 1.0 (exclusive) modifies this * * @return Vector3 corresponding to the translation vector to crystallographically normalise Point3 */ public Vector3 normaliseCrystallographically() { double[] arr = new double[3]; for (int i = 0; i < 3; i++) { double start = flarray[i]; flarray[i] = normaliseCrystallographically(flarray[i]); arr[i] = Math.round(flarray[i] - start); } return new Vector3(arr); } private static double normaliseCrystallographically(double d) { while (d >= 1.0) { d -= 1.0; } while (d < 0.0) { d += 1.0; } return d; } /** * is point invariant wrt symmetry operation. * * tolerance is decided by Real.isEqual() * * @param t3 * the transformation * @param translate * allow crystallographic translations (+-1) * @return true if t3 transforms this onto itself */ public boolean isInvariant(Transform3 t3, boolean translate) { Point3 pNew = this.transform(t3); return (translate) ? pNew.equalsCrystallographically(this) : pNew .isEqualTo(this); } /** * vector between two points. result is vector FROM p2 TO this this -= p2 * alters this * * @param p2 * point to subtract * @return vector */ public Vector3 subtract(Point3 p2) { Vector3 v1 = new Vector3(this); for (int i = 0; i < 3; i++) { v1.flarray[i] -= p2.flarray[i]; } return v1; } /** * New point by adding points as vectors. used for finding centroids, etc. * does NOT alter this * * @param p * to add * @return NEW point */ public Point3 plus(Point3 p) { Point3 p1 = new Point3(); for (int i = 0; i < 3; i++) { p1.flarray[i] = flarray[i] + p.flarray[i]; } return p1; } /** * Move this Point3. alters this * * @param pt * point to shift by */ public void plusEquals(final Point3 pt) { for (int i = 0; i < 3; i++) { flarray[i] += pt.flarray[i]; } } /** * New point from point+vector does NOT alter this * * @param v * to add * @return NEW point */ public Point3 plus(Vector3 v) { Point3 p1 = new Point3(); for (int i = 0; i < 3; i++) { p1.flarray[i] = flarray[i] + v.flarray[i]; } return p1; } /** * point from point and vector. alter this * * @param v * to add */ public void plusEquals(Vector3 v) { for (int i = 0; i < 3; i++) { flarray[i] += v.flarray[i]; } } /** * New point from point minus vector. does NOT alter this * * @param v * to subtract * @return NEW point */ public Point3 subtract(Vector3 v) { Point3 p1 = new Point3(); for (int i = 0; i < 3; i++) { p1.flarray[i] = flarray[i] - v.flarray[i]; } return p1; } /** * Shift point from point. does alter this * * @param pt * the Point3 to subtract from this */ public void subtractEquals(final Point3 pt) { for (int i = 0; i < 3; i++) { flarray[i] -= pt.flarray[i]; } } /** * Shift point from vector3. does alter this * * @param vec3 * the Vector3 to subtract from this */ public void subtractEquals(final Vector3 vec3) { for (int i = 0; i < 3; i++) { flarray[i] -= vec3.flarray[i]; } } /** * scale point. does NOT alter this * * @param f * factor to multiply by * @return NEW point */ public Point3 multiplyBy(double f) { Point3 p1 = new Point3(); for (int i = 0; i < 3; i++) { p1.flarray[i] = flarray[i] * f; } return p1; } /** * scale point. alters this * * @param f * factor to multiply by */ public void multiplyEquals(final double f) { for (int i = 2; i >= 0; --i) { flarray[i] *= f; } } /** * create inverse point. alters this = -this */ public void reflect() { flarray[0] = -flarray[0]; flarray[1] = -flarray[1]; flarray[2] = -flarray[2]; } /** * scale point does NOT alter this * * @param f * factor to divide by * @return NEW point */ public Point3 divideBy(double f) { Point3 p1 = new Point3(); for (int i = 0; i < 3; i++) { p1.flarray[i] = flarray[i] / f; } return p1; } /** * scale point. alters this * * @param f * factor to divide by */ public void divideEquals(final double f) { final double f1 = 1.0 / f; for (int i = 2; i >= 0; --i) { flarray[i] *= f1; } } /** * subscript operator. * * @param n * the index * @throws EuclidRuntimeException * @return the element */ public double elementAt(int n) throws EuclidRuntimeException { Util.check(n, 0, 2); return flarray[n]; } /** * sets element. * * @param n * the index * @param d * the value * @throws EuclidRuntimeException */ public void setElementAt(int n, double d) throws EuclidRuntimeException { Util.check(n, 0, 2); flarray[n] = d; } /** * get transformed point. does NOT modify 'this' * * @param t * the transform * @return new point */ public Point3 transform(Transform3 t) { RealArray col3 = new RealArray(4, 1.0); // set the translation in col 3 col3.setElements(0, this.flarray); RealArray result = t.multiply(col3); Point3 pout = new Point3(result.getSubArray(0, 2).getArray()); return pout; } /** * get transformed point. does modify 'this' * * @param t * the transform */ public void transformEquals(Transform3 t) { RealArray col3 = new RealArray(4, 1.0); // set the translation in col 3 col3.setElements(0, this.flarray); RealArray result = t.multiply(col3); System.arraycopy(result.getSubArray(0, 2).getArray(), 0, flarray, 0, 3); } /** * distance of point from origin. * * @return distance */ public double getDistanceFromOrigin() { Vector3 v = new Vector3(this); return v.getLength(); } /** * Gets the squared Distance between this point and another * * @param p2 * the other point to get the distance from * @return the squared distance */ public double getSquaredDistanceFromPoint(final Point3 p2) { double d = flarray[0] - p2.flarray[0]; double sqdDist = d * d; d = flarray[1] - p2.flarray[1]; sqdDist += (d * d); d = flarray[2] - p2.flarray[2]; sqdDist += (d * d); return sqdDist; } /** * distance of point from another point * * @param p2 * the other point to get the distance from * @return the distance */ public double getDistanceFromPoint(Point3 p2) { Vector3 v = new Vector3(p2.subtract(this)); return v.getLength(); } /** * distance from plane * * @param pl * @return distance */ public double distanceFromPlane(Plane3 pl) { return pl.getDistanceFromPoint(this); } /** * get closest point on line. * * @param l * the line * @return the point where distance is shortest */ public Point3 getClosestPointOnLine(Line3 l) { return l.getClosestPointTo(this); } /** * is point on line. * * @param l * the line * @return true if within Real.isEqual() of line */ public boolean isOnLine(Line3 l) { // TODO add epsilon return l.containsPoint(this); } /** * is point on plane. * * @param pl * the plane * @return true if within Real.isEqual() of plane */ public boolean isOnPlane(Plane3 pl) { return pl.containsPoint(this); } /** * distance from line. * * @param l * the line * @return the distance */ public double distanceFromLine(Line3 l) { return l.getDistanceFromPoint(this); } /** * mid-point of two points. * * @param p2 * the other point * @return the midPoint */ public Point3 getMidPoint(Point3 p2) { Point3 p = new Point3(); { for (int i = 0; i < 3; i++) { p.flarray[i] = (this.flarray[i] + p2.flarray[i]) / 2.0; } } return p; } /** * get angle. p1-p2-p3 * * @param p1 * the start point * @param p2 * the vertex point * @param p3 * the remote point * @return angle null if coincient points */ public static Angle getAngle(Point3 p1, Point3 p2, Point3 p3) { Vector3 v1 = p1.subtract(p2); return (v1.isZero()) ? null : v1.getAngleMadeWith(p3.subtract(p2)); } /** * torsion angle. p1-p2-p3-p4 * * @param p1 * @param p2 * @param p3 * @param p4 * @return angle unsigned radians or null (null args, or colinearity) */ public static Angle getTorsion(Point3 p1, Point3 p2, Point3 p3, Point3 p4) { Angle angle = null; Vector3 v23 = p3.subtract(p2); Vector3 v13a = p2.subtract(p1); Vector3 v13 = v13a.cross(v23); Vector3 v24 = v23.cross(p4.subtract(p3)); v13.normalize(); v24.normalize(); double ang = v13.getAngleMadeWith(v24).getAngle(); if (v13.getScalarTripleProduct(v24, v23) < 0.0) { ang = -ang; } angle = new Angle(ang); return angle; } /** * add point using internal coordinates. used for z-matrix like building * p1-p2-p3-newPoint * * @param p1 * existing point * @param p2 * existing point * @param p3 * existing point * @param length * p3-p4 * @param angle * p2-p3-p4 * @param torsion * this-p2-p3-p4 * @exception EuclidRuntimeException * two points are coincident or 3 colinear * @return new point; null if two points are coincident or three points are * colinear */ public static Point3 calculateFromInternalCoordinates(Point3 p1, Point3 p2, Point3 p3, double length, Angle angle, Angle torsion) throws EuclidRuntimeException { Vector3 v32 = p2.subtract(p3); Vector3 v12 = p2.subtract(p1); // perp to p1-2-3 Vector3 v13a = v12.cross(v32); Vector3 v13n = v13a.normalize(); // in plane Vector3 v32n = v32.normalize(); Vector3 v34 = v32n.multiplyBy(length); Transform3 t = new Transform3(v13n, angle); v34 = v34.transform(t); v32n = v32n.negative(); Transform3 t1 = new Transform3(v32n, torsion); v34 = v34.transform(t1); Point3 p4 = p3.plus(v34); return p4; } /** * is a point at Origin * * @return is this within Real.isEqual() of origin */ public boolean isOrigin() { for (int i = 0; i < 3; i++) { if (!Real.isZero(flarray[i], Real.getEpsilon())) return false; } return true; } /** * string representation. * * @return the string */ public String toString() { return EC.S_LBRAK + flarray[0] + EC.S_COMMA + EC.S_SPACE + flarray[1] + EC.S_COMMA + EC.S_SPACE + flarray[2] + EC.S_RBRAK; } /** equals. * @param that * @return is equal */ public boolean equals(Object that) { if (this == that) return true; if (!(that instanceof Point3)) return false; Point3 p3 = (Point3) that; return Real.isEqual(this.getArray(), p3.getArray(), Point3.CRYSTALFRACTEPSILON); } /** hash code. * @return coe */ public int hashCode() { int result = 17; int c = 1; long x = Double.doubleToLongBits(flarray[0]); c = c * (int)(x^(x>>>32)); long y = Double.doubleToLongBits(flarray[1]); c = c * (int)(y^(x>>>32)); long z = Double.doubleToLongBits(flarray[2]); c = c * (int)(z^(x>>>32)); return 37*result+c; } /** main. * * @param args */ public static void main(String[] args) { Point3 one = new Point3(0.1, 0.2, 0.3); Point3 two = new Point3(0.1, 0.2, 0.5); if (one.equals(two)) { Util.println("are equal in state"); } if (one == two) { Util.println("same object"); } } } wwmm-euclid-87e8f785a814/src/main/java/org/xmlcml/euclid/Point3Vector.java0000644000000000000000000012550611607017524024341 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid; import java.util.ArrayList; import java.util.List; import org.apache.log4j.Logger; import org.xmlcml.euclid.Axis.Axis3; /** * a (Java) Vector of Point3s (Note that 'Vector' is used by Java to describe an * array of objects - there is no relationship to geometrical vectors in this * package.) *

* There are a large number of routines for manipulating 3-D coordinates. * Examples are distance, torsion, angle, planes, fitting, etc. The routines * have NOT been optimised. In the previous incarnation (C++) all coordinates * were handled by Point3s, etc because pointers are fragile. In Java, however, * a lot more intermediate information could be passed through double[] arrays * and this will be gradually converted. *

* All the routines compile and give answers. The answers were right in the C++ * version. Most seem to be right here, but the FITTING ROUTINES ARE CURRENTLY * NOT WORKING PROPERLY. This will be fixed... *

* Default is an empty (Java) Vector; * * @author (C) P. Murray-Rust, 1996 */ public class Point3Vector implements EuclidConstants { final static Logger logger = Logger.getLogger(Point3Vector.class.getName()); protected List vector; /** * Comment for serialVersionUID */ private static final long serialVersionUID = 3258126964282635312L; /** * constructor. */ public Point3Vector() { vector = new ArrayList(); } /** * Formed by feeding in an existing array to a 3xn matrix flarray is in form * (x, y, z, x, y, z ...) * * @param flarray * @exception EuclidException * size of flarray must be multiple of 3 */ /** * constructor. * * @param flarray * @exception EuclidRuntimeException */ public Point3Vector(double[] flarray) throws EuclidRuntimeException { this(); if (flarray == null) { throw new EuclidRuntimeException("null array"); } int count = 0; int n = flarray.length / 3; if (flarray.length != 3 * n) { throw new EuclidRuntimeException("array length must be multiple of 3"); } for (int i = 0; i < n; i++) { Point3 p = new Point3(flarray[count++], flarray[count++], flarray[count++]); vector.add(p); } } /** * from three parallel arrays of x, y and z - by REFERENCE * * @param n * @param x * @param y * @param z * @throws EuclidRuntimeException * */ public Point3Vector(int n, double[] x, double[] y, double[] z) throws EuclidRuntimeException { this(); Util.check(x, n); Util.check(y, n); Util.check(z, n); for (int i = 0; i < n; i++) { vector.add(new Point3(x[i], y[i], z[i])); } } /** * constructor from RealArray - by REFERENCE * * @param m * @exception EuclidRuntimeException * size of flarray must be multiple of 3 */ public Point3Vector(RealArray m) throws EuclidRuntimeException { this(); double[] marray = m.getArray(); int count = marray.length / 3; if (marray == null || marray.length != count * 3) { throw new EuclidRuntimeException("null array or count not divisible by 3"); } int j = 0; for (int i = 0; i < count; i++) { vector.add(new Point3(marray[j++], marray[j++], marray[j++])); } } /** * copy constructor from Point3Vector COPIES pv * * @param pv */ public Point3Vector(Point3Vector pv) { this(); for (int i = 0; i < pv.size(); i++) { Point3 point = (Point3) pv.elementAt(i); if (point != null) { point = new Point3(point); } this.addElement(point); } } /** * size of vector. * * @return the size */ public int size() { return vector.size(); } /** * get points as list. * * @return list */ public List getPoint3List() { return vector; } /** * is equal. * * @param p * @return true if equals */ public boolean isEqualTo(Point3Vector p) { boolean ok = true; if (p == null || this.size() != p.size()) { ok = false; } else { int i = 0; for (Point3 pp : p.vector) { Point3 thisP = this.vector.get(i++); if (!thisP.isEqualTo(pp)) { ok = false; break; } } } return ok; } /** * get array. * * @return array */ public double[] getArray() { double[] array = new double[3 * vector.size()]; int i = 0; for (Point3 p : vector) { array[i++] = p.flarray[0]; array[i++] = p.flarray[1]; array[i++] = p.flarray[2]; } return array; } /** * add point. * * @param p * the point */ public void add(Point3 p) { vector.add(p); } /** * insert point. * * @param p * point to insert * @param i * position to insert at */ public void setElementAt(Point3 p, int i) { vector.set(i, p); } /** * get Point3 element. * * @param i * serial of the element to get * @return the element */ public Point3 elementAt(int i) { return vector.get(i); } /** * get Point3 element. * * @param i * serial of the element to get * @return the element */ public Point3 get(int i) { return (Point3) vector.get(i); } private void checkConformable(Point3Vector v) throws EuclidRuntimeException { if (size() != v.size()) { throw new EuclidRuntimeException("incompatible Point3Vector sizes: " + size() + EC.S_SLASH + v.size()); } } /** * add point. * * @param p */ public void addElement(Point3 p) { vector.add(p); } /** * sets a given coordinate (i) to vector * * @param v * @param i * @exception EuclidRuntimeException * i is >= number of current points (cann use this to * increase size of Point3Vector) */ public void setElementAt(Vector3 v, int i) throws EuclidRuntimeException { vector.set(i, new Point3(v)); } /** * get range of one coordinate * * @param ax * @return range */ public RealRange getRange(Axis3 ax) { RealArray temp = new RealArray(vector.size()); double[] dd = temp.getArray(); int i = 0; for (Point3 p : vector) { dd[i++] = p.getArray()[ax.value]; } RealRange range = new RealRange(); if (size() > 0) { range.add(temp.smallestElement()); range.add(temp.largestElement()); } return range; } /** * get range of all 3 coordinates * * @return range */ public Real3Range getRange3() { Axis3 axes[] = Axis3.values(); Real3Range range = new Real3Range(); for (Axis3 ax : axes) { range.add(ax, getRange(ax)); } return range; } /** * gets sums of squared distances between points. * * result = sigma[i = 1, npoints] (this.point(i)getDistanceFrom(vector.point(i)) ** * 2 * * @param v * the other vector * @throws EuclidRuntimeException * vectors not of same length * @return the sums of squared distances */ public double getSigmaDeltaSquared(Point3Vector v) throws EuclidRuntimeException { int np = size(); if (v.size() != np) { throw new EuclidRuntimeException("Vectors of different lengths"); } double d = 0.0; for (int i = 0; i < np; i++) { Point3 thisP = vector.get(i); Point3 vP = v.vector.get(i); double dist = thisP.getDistanceFromPoint(vP); d += dist * dist; } return d; } /** * create a NEW subset of the points; points are COPIED * * @param is * @return vector * @exception EuclidRuntimeException * an element of is is outside range of this */ public Point3Vector subArray(IntSet is) throws EuclidRuntimeException { Point3Vector sub = new Point3Vector(); for (int i = 0; i < is.size(); i++) { int ix = is.elementAt(i); if (ix < 0 || ix >= this.size()) { throw new EuclidRuntimeException("element out of range: "+ix); } sub.addElement(new Point3(this.getPoint3(ix))); } return sub; } /** * multiply all coords. does not alter this. * * @param scale * @return the scaled vector */ public Point3Vector multiplyBy(double scale) { Point3Vector p3v = new Point3Vector(this); p3v.multiplyByEquals(scale); return p3v; } /** * multiply all coords - alters this. * * @param scale * @return the scaled vector */ public void multiplyByEquals(double scale) { for (int i = 0; i < this.size(); i++) { this.getPoint3(i).multiplyEquals(scale); } } /** * form the point+point sum for two vectors of points * * @param pv2 * @exception EuclidRuntimeException * pv2 is different size from this * @return vector */ public Point3Vector plus(Point3Vector pv2) throws EuclidRuntimeException { checkConformable(pv2); Point3Vector pv1 = new Point3Vector(); for (int i = 0; i < this.size(); i++) { Point3 temp = (getPoint3(i)).plus(pv2.getPoint3(i)); pv1.addElement(temp); } return pv1; } /** * form the point+point difference for two vectors of points * * @param pv2 * @return vector * @exception EuclidRuntimeException * pv2 is different size from this */ public Point3Vector subtract(Point3Vector pv2) throws EuclidRuntimeException { checkConformable(pv2); Point3Vector pv1 = new Point3Vector(); for (int i = 0; i < size(); i++) { Vector3 v = (getPoint3(i)).subtract(pv2.getPoint3(i)); Point3 temp = new Point3(v.getArray()); pv1.addElement(temp); } return pv1; } /** * get the line between two points * * @param i1 * @param i2 * @return line */ public Line3 getLine(int i1, int i2) { Line3 temp = new Line3(); if (i1 >= 0 && i1 < size() && i2 >= 0 && i2 < size()) { temp = new Line3(getPoint3(i1), getPoint3(i2)); } return temp; } /** * get centroid of all points * * @return point */ synchronized public Point3 getCentroid() { final int size = size(); if (size < 1) { return null; } Point3 p = new Point3(); for (int j = size - 1; j >= 0; --j) { p = p.plus(getPoint3(j)); } double scale = 1.0 / ((double) size); p = p.multiplyBy(scale); return p; } /** * translate by a vector - do NOT modify this * * @param v * @return vector */ public Point3Vector plus(Vector3 v) { Point3Vector temp = new Point3Vector(); for (int i = 0; i < size(); i++) { Point3 p = getPoint3(i).plus(v); temp.addElement(p); } return temp; } /** * translate by a vector - modify this * * @param v */ public void plusEquals(Vector3 v) { for (int i = 0; i < size(); i++) { getPoint3(i).plusEquals(v); } } /** * translate negatively. does NOT modify this * * @param v vector to subtract * @return the NEW translated p3v */ public Point3Vector subtract(Vector3 v) { Vector3 v1 = v.negative(); Point3Vector temp = this.plus(v1); return temp; } /** * centre molecule on origin. translate to centroid MODIFIES PV */ public void moveToCentroid() { Point3 temp = this.getCentroid(); temp = temp.multiplyBy(-1.); this.plusEquals(new Vector3(temp)); } /** removes null values if both vectors have them at same position. * else throws exception * @param a * @param b */ public static void removeNullValues(Point3Vector a, Point3Vector b) { int n = a.size(); if (b.size() != n) { throw new EuclidRuntimeException("vectors of different sizes"); } for (int i = n-1; i >= 0; i--) { Point3 pa = a.elementAt(i); Point3 pb = b.elementAt(i); if (pa != null && pb != null) { } else if (pa == null && pb == null) { a.vector.remove(i); b.vector.remove(i); } else { throw new EuclidRuntimeException("unmatched null values at: "+i); } } } /** * get inertial tensor. (second moments) * * @return the inertial tensor */ public RealSquareMatrix calculateNonMassWeightedInertialTensorOld() { RealSquareMatrix tensor = new RealSquareMatrix(3); Point3 centre = this.getCentroid(); // subtract centroid from each coord and sum outerproduct of result for (int i = 0; i < size(); i++) { Point3 temp = new Point3(this.getPoint3(i).subtract(centre)); RealArray delta = new RealArray(3, temp.getArray()); RealSquareMatrix op = RealSquareMatrix.outerProduct(delta); tensor = tensor.plus(op); } return tensor; } public RealSquareMatrix calculateRotationToInertialAxes() { RealSquareMatrix inertialTensor = calculateNonMassWeightedInertialTensor(); RealSquareMatrix eigenvectors = inertialTensor.calculateEigenvectors(); if (eigenvectors != null) { // make sure axes are right-handed double determinant = eigenvectors.determinant(); if (determinant < 0.1) { RealSquareMatrix flip = new RealSquareMatrix( new double[][] { new double[] {1.0, 0.0, 0.0}, new double[] {0.0, -1.0, 0.0}, new double[] {0.0, 0.0, 1.0}, } ); eigenvectors = eigenvectors.multiply(flip); } eigenvectors = new RealSquareMatrix(eigenvectors.getTranspose()); } return eigenvectors; } /** * transform all coordinates. MODIFIES p3Vector * * @param t */ public void transform(Transform3 t) { for (int i = 0; i < size(); i++) { Point3 p = new Point3(getPoint3(i)); vector.set(i, p.transform(t)); } } /** * transform subset of coordinates - MODIFIES Vector * * @param t * @param is */ public void transform(Transform3 t, IntSet is) { int nis = is.size(); for (int j = 0; j < nis; j++) { int i = is.elementAt(j); if (i >= 0 && i < size()) { Point3 p = new Point3(getPoint3(i)); vector.set(i, p.transform(t)); } } } /** * get distance between 2 points. * * @param i1 * index of first point * @param i2 * index of second point * @return distance */ public double distance(int i1, int i2) { Vector3 v1 = getPoint3(i1).subtract(getPoint3(i2)); return v1.getLength(); } /** * get distance between 2 points. * * @param is * of exactly 2 integers * @exception EuclidRuntimeException * is must have exactly 2 points * @return distance */ public double distance(IntSet is) throws EuclidRuntimeException { if (is.size() != 2) { throw new EuclidRuntimeException("int set must have exactly 2 points"); } return distance(is.elementAt(0), is.elementAt(1)); } /** * get angle between 3 points. * * @param i1 * serial of first point * @param i2 * serial of second point * @param i3 * serial of third point * @exception EuclidRuntimeException * two points are coincident or identical * @return the angle */ public Angle angle(int i1, int i2, int i3) throws EuclidRuntimeException { Angle a; a = Point3.getAngle(getPoint3(i1), getPoint3(i2), getPoint3(i3)); return a; } /** * get angle between 3 points * * @param is * of exactly 3 integers * @exception EuclidRuntimeException * is must have exactly 3 points * @exception EuclidRuntimeException * two points are coincident or identical * @return the angle */ public Angle angle(IntSet is) throws EuclidRuntimeException { if (is.size() != 3) { throw new EuclidRuntimeException("size must be 3"); } return angle(is.elementAt(0), is.elementAt(1), is.elementAt(2)); } /** * get torsion angle between 4 points. * * @param i1 * serial of first point * @param i2 * serial of second point * @param i3 * serial of third point * @param i4 * serial of fourth point * @exception EuclidRuntimeException * either 2 points are identical or coincident or 3 * successive points are colinear * @return the angle */ public Angle torsion(int i1, int i2, int i3, int i4) throws EuclidRuntimeException { return Point3.getTorsion(getPoint3(i1), getPoint3(i2), getPoint3(i3), getPoint3(i4)); } /** * get torsion angle between 4 points. * * @param is * of exactly 3 integers * @exception EuclidRuntimeException * is must have exactly 4 points * @exception EuclidRuntimeException * either 2 points are identical or coincident or 3 * successive points are colinear * @return the angle */ public Angle torsion(IntSet is) throws EuclidRuntimeException { if (is.size() != 4) { throw new EuclidRuntimeException("size must be 4"); } return torsion(is.elementAt(0), is.elementAt(1), is.elementAt(2), is .elementAt(3)); } /** * distance matrix * * @return matrix */ public RealSquareMatrix getDistanceMatrix() { int size = this.size(); RealSquareMatrix distances = new RealSquareMatrix(size); double zero = 0.0; double[][] distanceMatrix = distances.getMatrix(); for (int i = 0; i < size; i++) { distanceMatrix[i][i] = zero; for (int j = i + 1; j < size; j++) { double distance = this.getPoint3(i).getDistanceFromPoint( this.getPoint3(j)); distanceMatrix[i][j] = distance; distanceMatrix[j][i] = distance; } } return distances; } public RealSquareMatrix calculateNonMassWeightedInertialTensor() { RealSquareMatrix rsm = new RealSquareMatrix(3); for (int i = 0; i < this.size(); i++) { Point3 p = this.get(i); double x = p.getArray()[0]; double y = p.getArray()[1]; double z = p.getArray()[2]; rsm.flmat[0][0] += y*y + z*z; rsm.flmat[1][1] += x*x + z*z; rsm.flmat[2][2] += y*y + x*x; rsm.flmat[0][1] += -x*y; rsm.flmat[0][2] += -x*z; rsm.flmat[1][2] += -y*z; rsm.flmat[1][0] = rsm.flmat[0][1]; rsm.flmat[2][0] = rsm.flmat[0][2]; rsm.flmat[2][1] = rsm.flmat[1][2]; } return rsm; } /** * get Inertial axes; do not throw exception for pathological cases, but * return it. Axes (lengths and unit vectors) are returned through the * arguments eigval and eigvect. OBSOLETE * NYI * @param eigval * @param eigvect * @param illCond * @exception EuclidRuntimeException * must have at least 3 points * @deprecated (doesn't work) */ public void inertialAxes(RealArray eigval, RealSquareMatrix eigvect, EuclidRuntimeException illCond) throws EuclidRuntimeException { RealArray val = new RealArray(3); RealSquareMatrix vect = new RealSquareMatrix(3); illCond = null; eigval.shallowCopy(val); eigvect.shallowCopy(vect); } /** * get best plane * * @return plane * * @exception EuclidRuntimeException * must have at least 3 points * @deprecated doesn't work */ public Plane3 bestPlane() throws EuclidRuntimeException { RealSquareMatrix eigvect = new RealSquareMatrix(3); RealArray eigval = new RealArray(3); EuclidRuntimeException illCond = null; inertialAxes(eigval, eigvect, illCond); // smallest eigenvalue RealArray temp = eigvect.extractRowData(2); Vector3 v = new Vector3(temp); // construct plane double dist = v.dot(getCentroid().getArray()); Plane3 p = new Plane3(v, dist); return p; } /** * get deviations of coordinates from plane * * @param p * @return deviations * */ public RealArray deviationsFromPlane(Plane3 p) { double[] farray = new double[size()]; for (int i = 0; i < size(); i++) { double dist = p.getVector().dot(getPoint3(i).getArray()); dist = dist - p.getDistance(); farray[i] = dist; } return new RealArray(farray); } /** * fit two coordinates of same length and alignment - quaternions */ // Transform3 newfitTo(Point3Vector c) { // // Uses Quaternions (method developed by Alan L. MacKay); // // // number of points must be the same // /* // if(size() != c.size()) { // Transform3 t; // return t; // } // Point3Vector c1 = c; // reference // Point3Vector pv2 = this; // moving molecule // c1.moveToCentroid(); // pv2.moveToCentroid(); // Point3Vector csum(count); // csum = c1 + pv2; // Point3Vector cdiff(count); // cdiff = c1 - pv2; // */ // // /** now set up the matrix elements*/ // /* // double mat[] = {0.,0.,0.,0., 0.,0.,0.,0., 0.,0.,0.,0., 0.,0.,0.,0.,}; // double[] psum = csum.flarray; // double[] pdiff = cdiff.flarray; // for (int i = 0; i < count; i++) { // double xp = *(psum); // double yp = *(psum + 1); // double zp = *(psum + 2); // // double xm = *(pdiff); // double ym = *(pdiff + 1); // double zm = *(pdiff + 2); // // mat[0] += xm*xm + ym*ym + zm*zm; // mat[1] += yp*zm - ym*zp; // mat[2] += xm*zp - xp*zm; // mat[3] += xp*ym - xm*yp; // // mat[5] += yp*yp + zp*zp + xm*xm; // mat[6] += xm*ym - xp*yp; // mat[7] += xm*zm - xp*zp; // // mat[10] += xp*xp + zp*zp + ym*ym; // mat[11] += ym*zm - yp*zp; // // mat[15] += xp*xp + yp*yp + zm*zm; // // psum++; pdiff++; // } // RealSquareMatrix s(4, mat); // // symmetrize matrix: upper to lower // // s.copyUpperToLower(); // // diagonalise // RealSquareMatrix evect(4); // RealArray eval(4); // s.diagonalise(eval, evect); // */ // // /*jacobi(mat,4,eval,evec,&nrot);*/ // // /*eigsrt(eval,evec,4);*/ // /* // return evect; // */ // return new Transform3(); // } /** * get a single point by REFERENCE * * @param i * @return point */ public Point3 getPoint3(int i) { return vector.get(i); } /** * get the coordinate coordinate array as doubles x,y,z,x,y,z, * * @return array */ public RealArray getXYZ() { double[] f = new double[3 * size()]; int count = 0; for (int i = 0; i < size(); i++) { double[] p = getPoint3(i).flarray; f[count++] = p[0]; f[count++] = p[1]; f[count++] = p[2]; } return new RealArray(f); } /** * get a single coordinate value * * @param i * @param j * @return coordinate */ public double getCoordinate(int i, Axis3 j) { return getPoint3(i).flarray[j.value]; } /** * get a single coordinate value; as above but not public */ double getCoordinate(int i, int j) { return getPoint3(i).flarray[j]; } /** * get a single coordinate array for example all x-coordinates * * @param axis * @return array */ public RealArray getXYZ(Axis3 axis) { double[] f = new double[size()]; for (int i = 0; i < size(); i++) { f[i] = getPoint3(i).flarray[axis.value]; } return new RealArray(f); } /** * rms between two molecules - per atom * * @param c * @return rms */ public double rms(Point3Vector c) { RealArray tt = getXYZ(); RealArray cc = c.getXYZ(); tt = tt.subtract(cc); return Math.sqrt(tt.innerProduct()) / (new Double(size())).doubleValue(); } /** * get point furthest from another. useful for alignments * * @param p * point to avoid (need not be in this) * @return the serial of the furthest point */ public int getFurthestPointFrom(Point3 p) { double d = -0.1; int serial = -1; for (int i = 0; i < this.size(); i++) { Point3 pp = vector.get(i); double dd = p.getDistanceFromPoint(pp); if (dd > d) { d = dd; serial = i; } } return serial; } /** * get point making smallest angle with two others. useful for alignments * * @param p1 * point to avoid (need not be in this) * @param p2 * point to avoid (need not be in this) * @return the serial of the point making smallest angle */ public int getPointMakingSmallestAngle(Point3 p1, Point3 p2) { double a = 999.; int serial = -1; for (int i = 0; i < this.size(); i++) { Point3 pp = vector.get(i); if (pp.isEqualTo(p1) || pp.isEqualTo(p2)) { continue; } try { Angle ang = Point3.getAngle(p1, pp, p2); double aa = ang.getAngle(); if (aa < a) { a = aa; serial = i; } } catch (Exception e) { ; } } return serial; } /** * fit two coordinates of same length and alignment. very approximate uses * get3SeparatedPoints() and then three find point1 furthest from centroid * find point2 furthest from point1 find point3 making smallest angle with * point1 and point2 m1 is moving molecule, m2 is fixed translate centroids * to match then rotate so that m1-point1 coincides with m2-point1 then * rotate so that m1-point2 coincides with m2-point2 This is rough, but will * be a good starting point for most molecules. *

* * @param ref * @return transformation * @exception EuclidRuntimeException * some unusual geometry (for example one coordinate set is * linear, has coincident points, etc.) */ public Transform3 alignUsing3Points(Point3Vector ref) throws EuclidRuntimeException { if (this.size() != ref.size()) { throw new EuclidRuntimeException("this and ref must be same size"); } if (this.size() < 3) { throw new EuclidRuntimeException("Need at least 3 points"); } int[] serial = get3SeparatedPoints(); Point3Vector thisVector = new Point3Vector(); Point3Vector refVector = new Point3Vector(); for (int i = 0; i < serial.length; i++) { thisVector.add(this.getPoint3(serial[i])); refVector.add(ref.getPoint3(serial[i])); } return thisVector.align3PointVectors(refVector); /*-- RealSquareMatrix unit = new RealSquareMatrix(3, new double[]{1., 0., 0., 0., 1., 0., 0., 0., 1.} ); Point3Vector moving = new Point3Vector(this); Point3 c1 = moving.getCentroid(); Point3 rc1 = ref.getCentroid(); Vector3 v12 = rc1.subtract(c1); Transform3 tr = new Transform3(unit, v12); moving.transform(tr); int i1 = moving.getFurthestPointFrom(c1); Point3 p1 = (Point3) moving.elementAt(i1); int i2 = moving.getFurthestPointFrom(p1); Point3 p2 = (Point3) moving.elementAt(i2); Point3 r1 = (Point3) ref.elementAt(i1); Point3 r2 = (Point3) ref.elementAt(i2); Vector3 p12 = p1.subtract(c1); Vector3 r12 = r1.subtract(rc1); Transform3 rot = new Transform3(p12, r12); moving.transform(rot); p1 = (Point3) moving.elementAt(i1); p2 = (Point3) moving.elementAt(i2); tr = rot.concatenate(tr); p12 = p1.subtract(p2); int i3 = moving.getPointMakingSmallestAngle(p1, p2); Point3 p3 = (Point3) moving.elementAt(i3); Point3 r3 = (Point3) ref.elementAt(i3); Vector3 p13 = p3.subtract(c1); Vector3 r13 = r3.subtract(rc1); Vector3 px = p12.cross(p13); px = px.normalize(); Vector3 rx = r12.cross(r13); rx = rx.normalize(); Transform3 rotx = new Transform3(px, rx); tr = rotx.concatenate(tr); return tr; --*/ } /** * get three widely separated points. useful for initial alignments p1 is * furthest from centroid p2 is furthest from p1 p3 is the point making * smallest value of p1-p3-p2 * * @return array with serial numbers of points * @exception EuclidRuntimeException * this or ref do not have 3 points or one has colinear or * coincident points */ public int[] get3SeparatedPoints() throws EuclidRuntimeException { int[] serial = new int[3]; Point3 c1 = this.getCentroid(); serial[0] = this.getFurthestPointFrom(c1); Point3 p1 = this.getPoint3(serial[0]); serial[1] = this.getFurthestPointFrom(p1); Point3 p2 = this.getPoint3(serial[1]); if (p1.isEqualTo(p2)) { throw new EuclidRuntimeException("Cannot find 3 separated points"); } serial[2] = this.getPointMakingSmallestAngle(p1, p2); Point3 p3 = this.getPoint3(serial[2]); if (p1.isEqualTo(p3) || p2.isEqualTo(p3)) { throw new EuclidRuntimeException("Cannot find 3 separated points"); } if ((p3.subtract(p1)).cross(p3.subtract(p2)).isZero()) { throw new EuclidRuntimeException("Cannot find 3 non-colinear points"); } return serial; } /** * fit two sets of three points. simple method. this and ref must each have * 3 points rotates p1-p2 vector in each to be parallel then rotates * p1-p2-p3 plane to be parallel This is rough, but will be a good starting * point for many systems, especially if get3SeparatedPoints is used * * no translation this is not changed * * @param ref * reference points * @return transform such that ttansform * this = ref * @exception EuclidRuntimeException * this or ref do not have 3 points or one has colinear or * coincident points */ public Transform3 align3PointVectors(Point3Vector ref) throws EuclidRuntimeException { if (this.size() != 3) { throw new EuclidRuntimeException("this requires 3 points"); } if (ref.size() != 3) { throw new EuclidRuntimeException("ref requires 3 points"); } RealSquareMatrix unit = new RealSquareMatrix(3, new double[] { 1., 0., 0., 0., 1., 0., 0., 0., 1. }); Transform3 overallTransform = new Transform3(unit); // copy this Point3Vector moving = new Point3Vector(this); Point3 thisCentroid = moving.getCentroid(); Point3 refCentroid = ref.getCentroid(); Point3 p1 = moving.getPoint3(0); Point3 p2 = moving.getPoint3(1); Point3 r1 = ref.getPoint3(0); Vector3 p12 = p1.subtract(thisCentroid); Vector3 r12 = r1.subtract(refCentroid); // align p1-p2 vectors Transform3 rot = new Transform3(p12, r12); moving.transform(rot); p1 = moving.getPoint3(0); p2 = moving.getPoint3(1); overallTransform = rot.concatenate(overallTransform); p12 = p1.subtract(p2); Point3 p3 = moving.getPoint3(2); Point3 r3 = ref.getPoint3(2); Vector3 p13 = p3.subtract(thisCentroid); Vector3 r13 = r3.subtract(refCentroid); // get normals Vector3 px = p12.cross(p13); px = px.normalize(); Vector3 rx = r12.cross(r13); rx = rx.normalize(); // and align Transform3 rotx = new Transform3(px, rx); overallTransform = rotx.concatenate(overallTransform); return overallTransform; } /** * fit two coordinates of same length and alignment. * * rough method . * fit 'this' to ref ('this' is moving molecule, ref is fixed) * take copies and refer each to their centroid as origin. * pick three points in ref which are well separated * Find the plane of these three and use the normal, * together with the vector to one of the points, to define two coordinate axes. * Calculate the third axis as right-handed orthogonal (check). * This gives a pure rotation matrix (Tref) * using the corresponding points in 'this' repeat to give Tthis * Tranformation matrix is then * Tthis(T). Tref. * Defining the intercentroid vector as Tthis2ref = centRef - centThis * we have * Tfinal = Tthis2Ref . Tthis(T) . Tref . (-Tthis2Ref) * This is rough, but will be a good starting point for many systems. * * @param ref * @return transformation * @exception EuclidRuntimeException * some unusual geometry (for example one coordinate set is * linear, has coincident points, etc.) */ public Transform3 roughAlign(Point3Vector ref) throws EuclidRuntimeException { // int[] points; int nn = ref.size(); if (nn != size()) { throw new EuclidRuntimeException("arrays of different lengths: "+this.size()+"/"+nn); } if (nn < 3) { throw new EuclidRuntimeException("must have 3 points to align: "+this.size()+"/"+nn); } Point3 centThis = this.getCentroid(); Point3 centRef = ref.getCentroid(); Transform3 r = fit3Points(ref); return translateRotateRetranslate(centThis, centRef, r); } private Transform3 fit3Points(Point3Vector ref) { int[] points; Point3Vector pvThis = new Point3Vector(this); pvThis.moveToCentroid(); Point3Vector pvRef = new Point3Vector(ref); pvRef.moveToCentroid(); points = this.get3SeparatedPoints(); Transform3 tThis = getTransformOfPlane(points, pvThis); Transform3 tRef = getTransformOfPlane(points, pvRef); tRef.transpose(); Transform3 r = tRef.concatenate(tThis); return r; } private Transform3 translateRotateRetranslate(Point3 centThis, Point3 centRef, Transform3 rotate) { Vector3 this2Origv = new Vector3(centThis.multiplyBy(-1.0)); Transform3 trans2Orig = new Transform3(this2Origv); Transform3 trans1 = rotate.concatenate(trans2Orig); Vector3 orig2Refv = new Vector3(centRef); Transform3 orig2Ref = new Transform3(orig2Refv); Transform3 finalT = orig2Ref.concatenate(trans1); return finalT; } private Transform3 getTransformOfPlane(int[] ii, Point3Vector pv) { Plane3 p = new Plane3(pv.getPoint3(ii[0]), pv.getPoint3(ii[1]), pv .getPoint3(ii[2])); // get reference point in each plane Vector3 v = new Vector3(pv.getPoint3(ii[0])).normalize(); // and form axes: Vector3 w = p.getVector().cross(v).normalize(); // form the two sets of axes Vector3 vv = v.cross(w); Transform3 t = new Transform3(vv, v, w); return t; } // private void eigenvectorFit(Point3Vector pv2) { // RealSquareMatrix eigvec = new RealSquareMatrix(4); // RealArray eigval = new RealArray(4); // EuclidRuntimeException illCond = null; // pv2.inertialAxes(eigval, eigvec, illCond); // LOG.debug("EIG "+eigval+"/"+eigvec); // if (illCond != null) { // throw illCond; // } // Transform3 axes = new Transform3(eigvec); // LOG.debug("AX "+axes); // axes.transpose(); // Point3Vector pv22 = new Point3Vector(pv2); // LOG.debug("PVV "+pv22); // pv22.transform(axes); // LOG.debug("PVVZZ "+pv22); // } /** * fit two coordinates of same length and alignment * * CURRENTLY NOT VALIDATED * * @param ref * @return transformation * @exception EuclidRuntimeException * some unusual geometry (for example one coordinate set is * linear, has coincident points, etc.) */ public Transform3 fitTo(Point3Vector ref) throws EuclidRuntimeException { // these should be set as parameters? double damp = 1.0; double converge = 0.0002; Point3 thisCent = this.getCentroid(); Point3 refCent = ref.getCentroid(); /** * make copies of each molecule and translate to centroid */ Point3Vector thistmp = new Point3Vector(this); Point3Vector reftmp = new Point3Vector(ref); thistmp.moveToCentroid(); reftmp.moveToCentroid(); /** * roughly rotate moving molecule onto reference one */ Transform3 t = thistmp.roughAlign(reftmp); thistmp.transform(t); RealArray shift = new RealArray(3); int NCYC = 20; for (int icyc = 0; icyc < NCYC; icyc++) { double maxshift = 0.0; /** * loop through x,y,z */ for (int jax0 = 0; jax0 < 3; jax0++) { int jax1 = (jax0 + 1) % 3; int jax2 = (jax1 + 1) % 3; double rh = 0.0; double lh = 0.0; for (int ipt = 0; ipt < size(); ipt++) { double refj1 = reftmp.getCoordinate(ipt, jax1); double refj2 = reftmp.getCoordinate(ipt, jax2); double movj1 = thistmp.getCoordinate(ipt, jax1); double movj2 = thistmp.getCoordinate(ipt, jax2); lh += refj1 * refj1 + refj2 * refj2; rh += refj1 * (refj2 - movj2) - refj2 * (refj1 - movj1); } /** * get shifts */ double sft = -(damp * (rh / lh)); maxshift = Math.max(maxshift, Math.abs(sft)); shift.setElementAt(jax0, sft); } /** * break out if converged */ if (maxshift < converge) { // LOG.debug("CONVERGED"); break; } else if (maxshift < 0.1) { // not yet used damp = 1.0; } else if (maxshift > 0.1) { // not yet used damp = 1.0; } // LOG.debug("CYCLE"); /** * make transformation matrix by rotations about 3 axes */ Transform3 t1 = new Transform3( new Angle(shift.elementAt(0)), new Angle(shift.elementAt(1)), new Angle(shift.elementAt(2))); thistmp.transform(t1); /** * concatenate transformations */ t = new Transform3(t1.concatenate(t)); } Transform3 tt = translateRotateRetranslate(thisCent, refCent, t); return tt; } /** * to string. * * @return string */ public String toString() { StringBuffer sb = new StringBuffer(); sb.append(S_LBRAK); for (int i = 0; i < size(); i++) { sb.append(get(i).toString()); sb.append(S_NEWLINE); } sb.append(S_RBRAK); return sb.toString(); } public RealArray extractRealArray() { return new RealArray(getArray()); } public Double innerProduct() { return extractRealArray().innerProduct(); } } wwmm-euclid-87e8f785a814/src/main/java/org/xmlcml/euclid/Polar.java0000644000000000000000000001107611607017524023053 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid; /** * Polar coordinates (r, theta) * * @author (C) P. Murray-Rust, 1996 */ public class Polar implements EuclidConstants { /** * the radius from the origin */ double r = 0.0; /** * the angle with the X-axis (anticlockwise) */ double theta = 0.0; /** * constructor. */ public Polar() { super(); } /** * constructor. * * @param x * @param y */ public Polar(double x, double y) { super(); r = Math.sqrt(x * x + y * y); theta = Math.atan2(y, x); } /** * constructor. * * @param a * @param b */ public Polar(double a, Angle b) { r = a; theta = b.getAngle(); } /** * constructor. * * @param c */ public Polar(Complex c) { r = c.getR(); theta = c.getTheta().getAngle(); } /** * constructor. * * @param a */ public Polar(Polar a) { r = a.r; theta = a.theta; } /** * gets radial part * * @return radius */ public double getR() { return r; } /** * gets angular part * * @return angle */ public Angle getTheta() { return new Angle(theta); } /** * add two polars * * @param a2 * @return new polar */ public Polar plus(Polar a2) { Complex tmp = new Complex(getX() + a2.getX(), getY() + a2.getY()); Polar temp = new Polar(tmp); return temp; } /** * subtract two polars * * @param a2 * @return new polar */ public Polar subtract(Polar a2) { Complex tmp = new Complex(getX() - a2.getX(), getY() - a2.getY()); Polar temp = new Polar(tmp); return temp; } /** * unary minus */ public void subtract() { theta = theta + Math.PI; } /** * multiply a polar by a polar * * @param f * @return new polar */ public Polar multiplyBy(Polar f) { Polar temp = new Polar(this); temp.r = r * f.r; temp.theta = theta + f.theta; return temp; } /** * multiply a polar by a scalar * * @param f * @return new polar */ public Polar multiplyBy(double f) { Polar temp = new Polar(this); temp.r *= f; return temp; } /** * divide a polar by a polar * * @param f * @return polar * @throws EuclidRuntimeException */ public Polar divideBy(Polar f) throws EuclidRuntimeException { Polar temp = new Polar(this); if (Real.isZero(f.r, Real.getEpsilon())) { throw new EuclidRuntimeException(); } temp.r = r / f.r; temp.theta = theta - f.theta; return temp; } /** * are two polar equal * * @param a * @return equals */ public boolean isEqualTo(Polar a) { return Real.isEqual(r, a.r) && Real.isEqual(theta, a.theta); } /** * get X, Y and XY coords * * @return coord */ public double getX() { double temp = r * Math.cos(theta); return temp; } /** * get y. * * @return coord */ public double getY() { double temp = r * Math.sin(theta); return temp; } /** * get coordinates. * * @return coordinates */ public Real2 getXY() { return new Real2(r * Math.cos(theta), r * Math.sin(theta)); } /** * to string. * * @return string */ public String toString() { StringBuffer sb = new StringBuffer(); sb.append("Polar: " + r + EC.S_COMMA + theta); return sb.toString(); } } wwmm-euclid-87e8f785a814/src/main/java/org/xmlcml/euclid/RandomNumberGenerator.java0000644000000000000000000002432011607017524026232 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid; /** * @(#)RandomNumberGenerator.java * * Copyright (c) 2000 by Sundar Dorai-Raj * * @author Sundar Dorai-Raj * * Email: sdoraira@vt.edu * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License * * as published by the Free Software Foundation; either version 2 * * of the License, or (at your option) any later version, * * provided that any use properly credits the author. * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details at http://www.gnu.org * * */ import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; /* * Reference. * M. Matsumoto and T. Nishimura, * "Mersenne Twister: A 623-Dimensionally Equidistributed Uniform * Pseudo-Random Number Generator", * ACM Transactions on Modeling and Computer Simulation, * Vol. 8, No. 1, January 1998, pp 3--30. */ public class RandomNumberGenerator implements java.io.Serializable { static final long serialVersionUID = 3905348978240129619L; // Period parameters private static final int N = 624; private static final int M = 397; private static final int MATRIX_A = 0x9908b0df; private static final int UPPER_MASK = 0x80000000; private static final int LOWER_MASK = 0x7fffffff; // Tempering parameters private static final int TEMPERING_MASK_B = 0x9d2c5680; private static final int TEMPERING_MASK_C = 0xefc60000; private int mt[]; // the array for the state vector private int mti; // mti==N+1 means mt[N] is not initialized private int mag01[]; // a good initial seed (of int size, though stored in a long) @SuppressWarnings("unused") private static final long GOOD_SEED = 4357; private synchronized void writeObject(ObjectOutputStream out) throws IOException { // just so we're synchronized. out.defaultWriteObject(); } private synchronized void readObject (ObjectInputStream in) throws IOException, ClassNotFoundException { // just so we're synchronized. in.defaultReadObject(); } protected synchronized void setSeed(long seed) { haveNextGaussian = false; mt = new int[N]; // setting initial seeds to mt[N] using // the generator Line 25 of Table 1 in // [KNUTH 1981, The Art of Computer Programming // Vol. 2 (2nd Ed.), pp102] // the 0xffffffff is commented out because in Java // ints are always 32 bits; hence i & 0xffffffff == i mt[0]= ((int)seed); // & 0xffffffff; for(mti = 1; mti < N; mti++) mt[mti] = (69069 * mt[mti-1]); // mag01[x] = x * MATRIX_A for x=0,1 mag01 = new int[2]; mag01[0] = 0x0; mag01[1] = MATRIX_A; } protected synchronized int next(int bits) { int y; if(mti >= N) { int kk; for(kk = 0; kk < N - M; kk++) { y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); mt[kk] = mt[kk+M] ^ (y >>> 1) ^ mag01[y & 0x1]; } for(; kk < N-1; kk++) { y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); mt[kk] = mt[kk+(M-N)] ^ (y >>> 1) ^ mag01[y & 0x1]; } y = (mt[N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK); mt[N-1] = mt[M-1] ^ (y >>> 1) ^ mag01[y & 0x1]; mti = 0; } y = mt[mti++]; y ^= y >>> 11; y ^= (y << 7) & TEMPERING_MASK_B; y ^= (y << 15) & TEMPERING_MASK_C; y ^= (y >>> 18); return y >>> (32 - bits); } public RandomNumberGenerator() { this(System.currentTimeMillis()); } public RandomNumberGenerator(long seed) { setSeed(seed); } // generate integers between 0 and 2^32 public synchronized int nextInt() { return next(32); } // generate integers between 0 and n-1 (inclusive) public synchronized int nextInt(int n) { if (n <= 0) throw new IllegalArgumentException( "n must be positive" ); if ((n & -n) == n) { // i.e., n is a power of 2 return (int)((n * (long)next(31)) >> 31); } int bits, val; do { bits = next(31); val = bits % n; } while(bits - val + (n-1) < 0); return val; } // generate Poisson(lambda) // E(X)=lambda ; Var(X)=lambda public synchronized int nextPoisson(double lambda) { int v=-1; double l=Math.exp(-lambda),p; p=1.0; while (p>=l) { p*=nextUniform(); v++; } return v; } // generate Poisson(1) // E(X)=1 ; Var(X)=1 public synchronized int nextPoisson() { return nextPoisson(1); } // generate random boolean variables public synchronized boolean nextBoolean() { return (next(32) & 1 << 15) != 0; } // generates true with probability p public synchronized boolean nextBoolean(double p) { double u=nextUniform(); if(u < p) return true; return false; } // generate U(0,1) // E(X)=1/2 ; Var(X)=1/12 public synchronized double nextUniform() { long l = ((long)(next(26)) << 27) + next(27); return l / (double)(1L << 53); } // generate U(a,b) // E(X)=(b-a)/2 ; Var(X)=(b-a)^2/12 public synchronized double nextUniform(double a,double b) { return a + (b-a)*nextUniform(); } private double nextGaussian; private boolean haveNextGaussian = false; // generate N(0,1) // E(X)=1 ; Var(X)=1 public synchronized double nextGaussian() { if (!haveNextGaussian) { double v1=nextUniform(),v2=nextUniform(); double x1,x2; x1=Math.sqrt(-2*Math.log(v1))*Math.cos(2*Math.PI*v2); x2=Math.sqrt(-2*Math.log(v1))*Math.sin(2*Math.PI*v2); nextGaussian=x2; haveNextGaussian=true; return x1; } else { haveNextGaussian=false; return nextGaussian; } } // generate N(m,s2) // E(X)=m ; Var(X)=s2 public synchronized double nextGaussian(double m,double s2) { return nextGaussian()*Math.sqrt(s2)+m; } // generate Gamma(1,1) // E(X)=1 ; Var(X)=1 public synchronized double nextGamma() { return nextGamma(1,1,0); } // generate Gamma(alpha,beta) // E(X)=alpha*beta ; Var(X)=alpha*beta^2 public synchronized double nextGamma(double alpha,double beta) { return nextGamma(alpha,beta,0); } // generate shifted-Gamma(alpha,beta) // E(X)=alpha*beta+lambda ; Var(X)=alpha*beta^2 public synchronized double nextGamma(double alpha,double beta,double lambda) { double gamma=0; if(alpha <= 0 || beta <= 0) throw new IllegalArgumentException("alpha and beta must be strictly positive."); if (alpha < 1) { double b,p; boolean flag=false; b=1+alpha*Math.exp(-1); while(!flag) { p=b*nextUniform(); if (p>1) { gamma=-Math.log((b-p)/alpha); if (nextUniform()<=Math.pow(gamma,alpha-1)) flag=true; } else { gamma=Math.pow(p,1/alpha); if (nextUniform()<=Math.exp(-gamma)) flag=true; } } } else if (alpha == 1) gamma=-Math.log(nextUniform()); else { double y=-Math.log(nextUniform()); while (nextUniform()>Math.pow(y*Math.exp(1-y),alpha-1)) y=-Math.log(nextUniform()); gamma=alpha*y; } return beta*gamma+lambda; } // generate Exp(1) // E(X)=1 ; Var(X)=1 public synchronized double nextExp() { return nextGamma(1,1,0); } // generate Exp(beta) // E(X)=beta ; Var(X)=beta^2 public synchronized double nextExp(double beta) { return nextGamma(1,beta,0); } // generate shifted-Exp(beta) // E(X)=beta+lambda ; Var(X)=beta^2 public synchronized double nextExp(double beta,double lambda) { return nextGamma(1,beta,lambda); } // generate ChiSq(1) // E(X)=1 ; Var(X)=2 public synchronized double nextChiSq() { return nextGamma(0.5,2,0); } // generate ChiSq(df) // E(X)=df ; Var(X)=2*df public synchronized double nextChiSq(int df) { return nextGamma(0.5*(double)df,2,0); } // generate shifted-ChiSq(df) // E(X)=df+lambda ; Var(X)=2*df public synchronized double nextChiSq(int df,double lambda) { return nextGamma(0.5*(double)df,2,lambda); } // generate Beta(alpha,beta) // E(X)=a/(a+b) ; Var(X)=ab/[(a+b+1)(a+b)^2] public synchronized double nextBeta(double alpha,double beta) { if(alpha <= 0 || beta <=0) throw new IllegalArgumentException("alpha and beta must be strictly positive."); if (alpha == 1 && beta == 1) return nextUniform(); else if (alpha >= 1 && beta >=1) { double A=alpha-1, B=beta-1, C=A+B, L=C*Math.log(C), mu=A/C, sigma=0.5/Math.sqrt(C); double y=nextGaussian(),x=sigma*y+mu; while (x < 0 || x > 1) { y=nextGaussian(); x=sigma*y+mu; } double u=nextUniform(); while (Math.log(u) >= A*Math.log(x/A)+B*Math.log((1-x)/B)+L+0.5*y*y) { y=nextGaussian(); x=sigma*y+mu; while (x < 0 || x > 1) { y=nextGaussian(); x=sigma*y+mu; } u=nextUniform(); } return x; } else { double v1=Math.pow(nextUniform(),1/alpha), v2=Math.pow(nextUniform(),1/beta); while (v1+v2>1) { v1=Math.pow(nextUniform(),1/alpha); v2=Math.pow(nextUniform(),1/beta); } return v1/(v1+v2); } } } wwmm-euclid-87e8f785a814/src/main/java/org/xmlcml/euclid/Real.java0000644000000000000000000002110511607017524022653 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid; import java.util.regex.Pattern; import org.apache.log4j.Logger; /** * Real supports various utilities for real numbers Use Double where you want a * first-class Java object * * @author (C) P. Murray-Rust, 1996 */ public abstract class Real implements EuclidConstants { final static Logger logger = Logger.getLogger(Real.class.getName()); /** standard for equality of numbers */ static double epsx = 0.0000000001; /** * get current version of epsilon. * * @return maximum difference between numbers */ public static double getEpsilon() { return epsx; } /** * set current version of epsilon. * * @param epsilon * will be used in any implicit comparison until reset * */ public static void setEpsilon(double epsilon) { epsx = epsilon; } /** truncate to given number of decimals. * forms nint(d * 10^ndec)/10^ndec * @param d to truncate * @param ndec * @return */ public static double normalize(double d, int ndec) { int dd = 1; for (int i = 0; i < ndec; i++) { dd *= 10; } return ((double) Math.round(d * (double)dd)) / (double) dd; } /** * are two numbers equal within epsx. * * @param a * number * @param b * number * @return true if a equals b within epsilon * */ public static boolean isEqual(double a, double b) { return Math.abs(a - b) < epsx; } /** * is a number zero within epsx * * @param a * number * @return true if a is zero within epsilon * * @deprecated use epsilon method */ public static boolean isZero(double a) { return Real.isZero(a, epsx); } /** * are all members of an array equal within epsilon. * * @param n * length of array * @param a * first array * @param b * first array * @param epsilon * difference * @return true is all arrays are of equals lengths and members are equal * within epsilon * * @deprecated omit n */ public static boolean isEqual(int n, double[] a, double[] b, double epsilon) { if (a.length != b.length) { return false; } for (int i = 0; i < n; i++) { if (!Real.isEqual(a[i], b[i], epsilon)) return false; } return true; } /** * are all members of an array equal within epsilon. * * @param a first array * @param b first array * @param epsilon difference * @return true is all arrays are of equals lengths and members are equal * within epsilon * */ public static boolean isEqual(double[] a, double[] b, double epsilon) { if (a == null || b == null || a.length != b.length) { return false; } for (int i = 0; i < a.length; i++) { if (!Real.isEqual(a[i], b[i], epsilon)) return false; } return true; } /** * are all members of an array equal within epsx * * @param n length of array * @param a first array * @param b first array * @return true is all arrays are of equals lengths and members are equal * within epsilon * @deprecated use epsilon method */ public static boolean isEqual(int n, double[] a, double b[]) { return isEqual(n, a, b, epsx); } /** * are two numbers equal within epsilon * * @param a * number * @param b * number * @param epsilon * difference * @return true if a equals b within epsilon */ public static boolean isEqual(double a, double b, double epsilon) { return Math.abs(a - b) < epsilon; } /** * is a number zero within epsilon * * @param a * number * * @param epsilon * difference * * @return true if a is zero within epsilon * */ /** * A regular expression match a number pattern. */ public static final String SCIENTIFIC_PARSE = "(?:[+-]?(?:(?:\\d*(?:\\.?\\d+)?)|(?:\\d+(?:\\.?\\d*)?))(?:[EeDdGgHh][+-]?\\d+[dDfF]?)?)"; // sign? | number | exponent? | precision? /** * A compiled Pattern object which matches a number pattern. */ public static final Pattern SCIENTIFIC_PATTERN = Pattern.compile(SCIENTIFIC_PARSE); /** * Parse a string to double value, similar to Double.parseDouble function, but * also try to parse against FORTRAN number, e.g. 12.3D-05. * *

If the return value is Double.NaN, a RuntimeException is thrown. * This should not happen anyway. * * @author (C) Weerapong Phadungsukanan, 2009 * @param db String of number value * @return double value of the given String * @throws NullPointerException if db is null. * @throws NumberFormatException if db is not a number. */ public static double parseDouble(String db) { double d = Double.NaN; db = db.trim(); // Try to parse string using java routine first. If it does not match // the string could be number in FORTRAN format, [DdGgHh] as exponential // notation. So we replace the first exponential notation by E and then // try to parse again with java routine. The two steps are necessary and // cannot be removed otherwise the number such as 12.0d will not be parsed. try { d = Double.parseDouble(db); } catch (NumberFormatException nfe) { d = Double.parseDouble(db.replaceFirst("[DdGgHh]", "E")); } if (d == Double.NaN) throw new RuntimeException("Cannot parse {" + db + "} as double and cannot throw NumberFormatException. This is a program bug."); return d; } public static boolean isZero(double a, double epsilon) { return Math.abs(a) < epsilon; } /** * is a less than epsx less than b * * @param a * number * * @param b * number * * @return true if a < b within epsx * */ public static boolean isLessThan(double a, double b) { return ((b - a) > epsx); } /** * is a more than epsx greater than b * * @param a * number * * @param b * number * * @return true if a > b within epsx * */ public static boolean isGreaterThan(double a, double b) { return ((a - b) > epsx); } /** * set an array to zero * * @param nelem * length of array * * @param arr * array * */ public static void zeroArray(int nelem, double[] arr) { for (int i = 0; i < nelem; i++) { arr[i] = 0.0; } } /** * set an array to given value * * @param nelem * length of array * * @param arr * array * * @param f * the value * */ public static void initArray(int nelem, double[] arr, double f) { for (int i = 0; i < nelem; i++) { arr[i] = f; } } /** * print a double[] * * @param a * array * */ public static void printArray(double[] a) { for (int i = 0; i < a.length; i++) { logger.info(a[i] + S_SPACE); } logger.info(""); } } wwmm-euclid-87e8f785a814/src/main/java/org/xmlcml/euclid/Real2.java0000644000000000000000000004000211607017524022732 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid; import java.util.List; import org.apache.log4j.Logger; /** * A pair of FPt numbers with no other assumptions * * Contains two doubles Can be used as it is, but there are some specialised * derived classes (for example Complex (a complex number), Point2 (x,y coords), * etc), The default value is 0.0, 0.0. * * @author (C) P. Murray-Rust, 1996 */ public class Real2 implements EuclidConstants { private static Logger LOG = Logger.getLogger(Real2.class); /** the first floating point value */ public double x; /** the second floating point value */ public double y; /** * constructor. */ public Real2() { x = 0.0; y = 0.0; } /** * constructor. * * @param x * @param y */ public Real2(double x, double y) { this.x = x; this.y = y; } /** * constructor. * * @param dd * @throws RuntimeException null or not length=2 */ /** * two integers separated by whitespace * @param s */ public Real2(String s) { this(Util.splitToDoubleArray(s, S_SPACE)); } /** * two integers separated by delimiter * @param s */ public Real2(String s, String delimiter) { this(Util.splitToDoubleArray(s, delimiter)); } /** * constructor. * * @param x the two components */ public Real2(double[] x) { if (x == null) { throw new EuclidRuntimeException("requires non-null array"); } if (x.length != 2) { throw new EuclidRuntimeException("requires array of length 2; found: "+x.length); } this.x = x[0]; this.y = x[1]; } /** * copy constructor * * @param r */ public Real2(Real2 r) { this.x = r.x; this.y = r.y; } /** * swaps the x and y values */ public void swap() { double t = x; x = y; y = t; } /** * sorts x and y so that x <= y */ public void sortAscending() { if (x > y) this.swap(); } /** * sorts x and y so that x >= y */ public void sortDescending() { if (x < y) this.swap(); } /** * set to 0 0 */ public void clear() { x = y = 0.0; } /** * set x. * * @param xx */ public void setX(double xx) { x = xx; } /** * set y. * * @param yy */ public void setY(double yy) { y = yy; } /** * equality. * * @param r to test * @return equals * @deprecated */ public boolean isEqualTo(Real2 r) { return (Real.isEqual(x, r.x) && Real.isEqual(y, r.y)); } /** * equality. * * @param r to test * @param eps tolerance * @return equals */ public boolean isEqualTo(Real2 r, double eps) { return (Real.isEqual(x, r.x, eps) && Real.isEqual(y, r.y, eps)); } /** * is the point the origin. * * @return true if origin * @deprecated USE epsilon method */ public boolean isOrigin() { return Real.isZero(x, Real.getEpsilon()) && Real.isZero(y, Real.getEpsilon()); } /** * is the point the origin. * @param epsilon * @return true if origin */ public boolean isOrigin(double epsilon) { return Real.isZero(x, epsilon) && Real.isZero(y, epsilon); } /** * add two points to give vector sum * * @param r2 * @return point * */ public Real2 plus(Real2 r2) { return new Real2(x + r2.x, y + r2.y); } /** * add two points to give vector sum * * @param r2 * */ public void plusEquals(Real2 r2) { this.x = x + r2.x; this.y = y + r2.y; } /** * subtract two points to give vector difference * * @param r2 * @return point * */ public Real2 subtract(Real2 r2) { return new Real2(x - r2.x, y - r2.y); } /** * multiply both components by minus one MODIFIES 'this' */ public void negative() { this.x = -this.x; this.y = -this.y; } /** * retuen multiplication of a point by a scalar * does not alter this * @param f * @return point */ public Real2 multiplyBy(double f) { return new Real2(x * f, y * f); } /** * multiply a point by a scalar * alters this * @param f */ public void multiplyEquals(double f) { this.x = x * f; this.y = y * f; } /** * get X value * * @return x value */ public double getX() { return x; } /** * get Y value * * @return y value */ public double getY() { return y; } /** * get either value counts from ZERO * * @param elem * @return value * @throws EuclidRuntimeException */ public double elementAt(int elem) throws EuclidRuntimeException { if (elem == 0) { return x; } else if (elem == 1) { return y; } throw new EuclidRuntimeException("bad index " + elem); } /** * get length of Real2 if centered on origin * * @return length */ public double getLength() { return Math.sqrt(x * x + y * y); } /** * get distance to another Real2 * * @param r * @return distance */ public double getDistance(Real2 r) { return (r == null) ? Double.NaN : Math.sqrt((x - r.x) * (x - r.x) + (y - r.y) * (y - r.y)); } /** * get squared distance to another Real2 * * @param r * @return dist2 */ public double getSquaredDistance(Real2 r) { return (r == null) ? Double.NaN : (x - r.x) * (x - r.x) + (y - r.y) * (y - r.y); } /** * point midway between 'this' and 'p' * * @param p * @return midpoint */ public Real2 getMidPoint(Real2 p) { return new Real2((this.x + p.x) / 2.0, (this.y + p.y) / 2.0); } /** * get unit vector * * @return unit vector * @exception EuclidRuntimeException * this was of zero length */ public Real2 getUnitVector() { double length = this.getLength(); if (Real.isZero(length, Real.getEpsilon())) { throw new EuclidRuntimeException("zero length vector"); } Real2 temp = new Real2(this.x, this.y); temp = temp.multiplyBy(1.0 / length); return temp; } /** * get dot product * * @param r * @return dot */ public double dotProduct(Real2 r) { return (this.x * r.x + this.y * r.y); } /** * get angle between 3 Real2s (the second is in the centre) * * @param p1 * @param p2 * @param p3 * @return angle is CLOCKWISE from p1 to p3 */ public static Angle getAngle(Real2 p1, Real2 p2, Real2 p3) { if (p1 == null || p2 == null || p3 == null) { throw new RuntimeException("null coordinates"); } double x1 = p1.x - p2.x; double y1 = p1.y - p2.y; double x3 = p3.x - p2.x; double y3 = p3.y - p2.y; double angle1 = Math.atan2(x1, y1); double angle3 = Math.atan2(x3, y3); double angle13 = angle1 - angle3; Angle angle123 = new Angle(angle13, Angle.Units.RADIANS); double d12 = p1.getDistance(p2); double d13 = p1.getDistance(p3); double d23 = p2.getDistance(p3); double cost = (-d13*d13 + d12*d12 + d23*d23)/(2*d12*d23); double anglex = Math.acos(cost); LOG.trace("AAA "+anglex+"/"+angle13+"//"+p1+"/"+p2+"/"+p3); return angle123; } /** * transforms the point by a rot-trans matrix MODIFIES 'this' Note the next * routinie is often better * * @param t * */ public void transformBy(Transform2 t) { double xx = t.flmat[0][0] * this.x + t.flmat[0][1] * this.y + t.flmat[0][2]; double yy = t.flmat[1][0] * this.x + t.flmat[1][1] * this.y + t.flmat[1][2]; this.x = xx; this.y = yy; } /** * gets a point transformed by a rot-trans matrix does NOT MODIFY 'this' * * @param t * @return point */ public Real2 getTransformed(Transform2 t) { Real2 p = new Real2(this); p.transformBy(t); return p; } /** * creates a polygon * * returns a point array from two points Serial numbers of points are 0 and * end that is point1 is points[0] and point2 is points[end] if end == 0, * end=>1 * * @param point1 * @param nPoints * @param point2 * @param end * @param repelPoint * @return points * */ public static Real2[] addPolygonOnLine(Real2 point1, Real2 point2, int nPoints, int end, Real2 repelPoint) { if (end < 1) end = 1; Real2[] newPoints = new Real2[nPoints]; Real2 mid = point1.getMidPoint(point2); double dTheta = Math.PI * 2.0 / (double) nPoints; double lineTheta = (point1.subtract(point2)).getAngle(); double line2 = (point1.subtract(mid)).getLength(); // this accounts for number of points skipped double halfTheta = 0.5 * (dTheta * (double) end); // find centre double dist = line2 / Math.tan(halfTheta); // as far as possible from repelPoint double angle = lineTheta - 0.5 * Math.PI; Real2 center0 = mid.makePoint(dist, angle); Real2 center = center0; // this mess takes care of direction double theta0 = -halfTheta + angle + Math.PI; double theta = theta0; if (repelPoint != null) { double tempDist = (center.subtract(repelPoint)).getLength(); Real2 center1 = mid.makePoint(dist, angle + Math.PI); // swap it, change direction of traverse if ((center1.subtract(repelPoint)).getLength() > tempDist) { center = center1; dTheta = -dTheta; theta = +halfTheta + angle; } } // radius of polygon double rad = line2 / Math.sin(halfTheta); // now add points newPoints = makePoints(center, nPoints, rad, theta, dTheta); // for even-number polygons exactly bisected the repel cannot work on // centers so // also required for centroids on re-entrant nuclei // we examine the newly created points if (repelPoint != null /* && 2*end == nPoints */) { double dista = newPoints[1].subtract(repelPoint).getLength(); double distb = newPoints[nPoints - 2].subtract(repelPoint) .getLength(); // LOG.debug(""+dista+S_SLASH+distb+"/"+repelPoint+"/"+newPoints[1]+"/"+newPoints[nPoints-2]); if (dista > distb) { // logger.info("SWAP"); center = center0; dTheta = -dTheta; theta = theta0; newPoints = makePoints(center, nPoints, rad, theta, dTheta); } else { // LOG.debug("NOSWAP"); } } return newPoints; } private static Real2[] makePoints(Real2 center, int nPoints, double rad, double theta, double dTheta) { Real2[] points = new Real2[nPoints]; for (int i = 0; i < nPoints; i++) { points[i] = center.makePoint(rad, theta); theta += dTheta; } return points; } /** * get angle between origin and this point (i.e polar coords) - uses atan2 * (that is anticlockwise from X axis); if x == y == 0.0 presumably returns * NaN * * @return angle * */ public double getAngle() { return Math.atan2(y, x); } /** * make a new point at (dist, theta) from this * * @param rad * the distance to new point * @param theta * the angle to new point (anticlockwise from X axis), that is * theta=0 gives (rad, 0), theta=PI/2 gives (0, rad) * @return Real2 new point */ public Real2 makePoint(double rad, double theta) { Real2 point = new Real2(); point.x = this.x + rad * Math.cos(theta); point.y = this.y + rad * Math.sin(theta); return point; } /** * get centroid of all points. does not modify this * * @param p2Vector * @return the centroid */ public static Real2 getCentroid(List p2Vector) { if (p2Vector.size() < 1) return null; Real2 p = new Real2(); for (int j = 0; j < p2Vector.size(); j++) { p = p.plus(p2Vector.get(j)); } double scale = 1.0 / (new Double(p2Vector.size()).doubleValue()); p = p.multiplyBy(scale); return p; } /** * get serialNumber of nearest point * * @param p2v * @param point * @return serial */ public static int getSerialOfNearestPoint(List p2v, Real2 point) { double dist = Double.MAX_VALUE; int serial = -1; for (int j = 0; j < p2v.size(); j++) { double d = p2v.get(j).subtract(point).getLength(); if (d < dist) { serial = j; dist = d; } } return serial; } /** * get rectangular distance matrix. * * matrix need not be square or symmetric unless coords == coords2 d(ij) is * distance between coord(i) and coords2(j). * * @param coords1 * @param coords2 * @return distance matrix */ public static RealMatrix getDistanceMatrix(List coords1, List coords2) { int size = coords1.size(); int size2 = coords2.size(); RealMatrix distMatrix = new RealMatrix(size, size2); double[][] distMatrixMat = distMatrix.getMatrix(); for (int i = 0; i < size; i++) { Real2 ri = coords1.get(i); for (int j = 0; j < size2; j++) { Real2 rj = coords2.get(j); double dij = ri.getDistance(rj); distMatrixMat[i][j] = dij; } } return distMatrix; } /** * to string. * * @return string */ public String toString() { return S_LBRAK + x + S_COMMA + y + S_RBRAK; } /** * get x y as array. * * @return array of length 2 */ public double[] getXY() { double[] dd = new double[2]; dd[0] = x; dd[1] = y; return dd; } /** round to decimal places. * * @param places * @return this */ public Real2 format(int places) { x = Util.format(x, places); y = Util.format(y, places); return this; } } wwmm-euclid-87e8f785a814/src/main/java/org/xmlcml/euclid/Real2Array.java0000644000000000000000000002013011607017524023731 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid; import org.apache.log4j.Logger; /** * Real2Array is NOT a Vector of Real2s but a container for a 2 * n matrix * * with a variety of ways of managing the data including RealArrays for the x * and y arrays, and also an array of Real2s The latter is only stored if * required, and then is cached. * * Note that we also have Real2Vector which acts like a List. We may * therefore obsolete the Real2Array at some time - it is not used in Jumbo * elsewhere although it might be useful for spectra. * * NOTE: I think it's used quite a lot in fact... * * @author P.Murray-Rust, Copyright 1997 */ public class Real2Array implements EuclidConstants { @SuppressWarnings("unused") private static Logger LOG = Logger.getLogger(Real2Array.class); RealArray xarr; RealArray yarr; int nelem = 0; /** * default constructor gives an array of 0 points */ public Real2Array() { } /** * get max and min value of Real2_Array * * @return range */ public Real2Range getRange2() { Real2Range range = new Real2Range(); for (int i = 0; i < nelem; i++) { Real2 r2 = new Real2(xarr.elementAt(i), yarr.elementAt(i)); range.add(r2); } return range; } /** copy * * @param r2a */ public Real2Array(Real2Array r2a) { if (r2a != null && !r2a.equals(this)) { xarr = new RealArray(r2a.getXArray()); yarr = new RealArray(r2a.getYArray()); this.nelem = r2a.nelem; } } /** * make an Real2_Array from 2 RealVec's; takes a copy * * @param x * @param y * @exception EuclidRuntimeException * x and x must have number of elements */ public Real2Array(RealArray x, RealArray y) throws EuclidRuntimeException { if (x.size() != y.size()) { throw new EuclidRuntimeException("incompatible array sizes "+x.size()+"/"+y.size()); } nelem = x.size(); xarr = (RealArray) x.clone(); yarr = (RealArray) y.clone(); } /** * @param r2 */ public void add(Real2 r2) { if (nelem == 0 || xarr == null || yarr == null) { xarr = new RealArray(); yarr = new RealArray(); } xarr.addElement(r2.getX()); yarr.addElement(r2.getY()); nelem++; } /** * @param real2Array */ public void add(Real2Array real2Array) { if (real2Array != null) { if (nelem == 0 || xarr == null || yarr == null) { xarr = new RealArray(); yarr = new RealArray(); } xarr.addArray(real2Array.xarr); yarr.addArray(real2Array.yarr); nelem += real2Array.size(); } } /** * make an Real2_Array from pairs of numbers separated by delimiter * * @param s * @param delimiter (might be a regex e.g. ",| " (comma or space)) * @exception EuclidRuntimeException * x and x must have number of elements */ public static Real2Array createFromPairs(String sss, String delimiter) { Real2Array real2Array = null; if (sss != null) { String[] ss = sss.split(delimiter); if (ss.length % 2 == 0) { RealArray realArray = new RealArray(ss); real2Array = Real2Array.createFromPairs(realArray); } } return real2Array; } /** * make an Real2_Array from pairs of numbers x1,y1 .. x2,y2 .. etc * * @param s * @param delimiter * @exception EuclidRuntimeException * x and x must have number of elements */ public static Real2Array createFromPairs(RealArray ra) { if (ra == null) { throw new RuntimeException("Null RealArray"); } if (ra.size() % 2 != 0) { throw new RuntimeException("Must have even number of points"); } Real2Array real2Array = new Real2Array(); real2Array.xarr = new RealArray(); real2Array.yarr = new RealArray(); for (int i = 0; i < ra.size(); ) { real2Array.xarr.addElement(ra.elementAt(i++)); real2Array.yarr.addElement(ra.elementAt(i++)); real2Array.nelem++; } return real2Array; } /** * extract X array. * * @return array */ public RealArray getXArray() { return xarr; } /** * extract Y array. * * @return array */ public RealArray getYArray() { return yarr; } /** * size of array. * * @return size */ public int size() { return nelem; } /** * get element. * * @param elem * @return element */ public Real2 elementAt(int elem) { return new Real2(xarr.elementAt(elem), yarr.elementAt(elem)); } /** * get element. * * @param elem * @return element */ public Real2 get(int elem) { return new Real2(xarr.elementAt(elem), yarr.elementAt(elem)); } /** * get element. * * @param elem * @return element */ public void setElement(int elem, Real2 r2) { xarr.setElementAt(elem, r2.getX()); yarr.setElementAt(elem, r2.getY()); } /** delete element. * * @param i */ public void deleteElement(int i) { if (i >= 0 && i < nelem) { xarr.deleteElement(i); yarr.deleteElement(i); nelem--; } else { throw new EuclidRuntimeException("Cannt delete element at: "+i); } } public void transformBy(Transform2 t2) { for (int i = 0; i < nelem; i++) { Real2 xy = this.get(i); xy.transformBy(t2); this.setElement(i, xy); } } /** round to decimal places. * * @param places * @return this */ public Real2Array format(int places) { double[] xarray = xarr.getArray(); double[] yarray = yarr.getArray(); for (int i = 0; i < nelem; i++) { xarray[i] = Util.format(xarray[i], places); yarray[i] = Util.format(yarray[i], places); } return this; } /** * to space-separated string. * * @return string */ public String getStringArray() { // don't change this routine!!! StringBuffer s = new StringBuffer(); double[] xarray = (xarr == null) ? null : xarr.getArray(); double[] yarray = (yarr == null) ? null : yarr.getArray(); for (int i = 0; i < nelem; i++) { if (i > 0) { s.append(S_SPACE); } s.append(xarray[i]); s.append(S_SPACE); s.append(yarray[i]); } return s.toString(); } /** * to string. * * @return string */ public String toString() { // don't change this routine!!! StringBuffer s = new StringBuffer(); double[] xarray = (xarr == null) ? null : xarr.getArray(); double[] yarray = (yarr == null) ? null : yarr.getArray(); s.append(S_LBRAK); for (int i = 0; i < nelem; i++) { s.append(S_LBRAK); s.append(xarray[i]); s.append(S_COMMA); s.append(yarray[i]); s.append(S_RBRAK); } s.append(S_RBRAK); return s.toString(); } } wwmm-euclid-87e8f785a814/src/main/java/org/xmlcml/euclid/Real2Interval.java0000644000000000000000000001061511607017524024446 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid; /** a two dimensional area. * may have negative ranges * @author pm286 * */ public class Real2Interval implements EuclidConstants { RealInterval xInterval; RealInterval yInterval; /** constructor. * defaults to 0,1 0,1 * */ public Real2Interval() { this(new RealInterval(), new RealInterval()); } /** constructor from 1-D intervals. * * @param xInterval * @param yInterval */ public Real2Interval(RealInterval xInterval, RealInterval yInterval) { this.xInterval = new RealInterval(xInterval); this.yInterval = new RealInterval(yInterval); } /** copy constructor. * * @param xyInterval */ public Real2Interval(Real2Interval xyInterval) { this(xyInterval.xInterval, xyInterval.yInterval); } /** constructor from range. * interval direction is therefore always positive * @param range2 */ public Real2Interval(Real2Range range2) { this(new RealInterval(range2.getXRange()), new RealInterval(range2.getYRange())); } /** get x and y scales to other interval2. * exact scaling * @param interval2 * @return scales never null but component(s) may be NaN */ public double[] scalesTo(Real2Interval interval2) { double[] scales = new double[2]; scales[0] = xInterval.scaleTo(interval2.xInterval); scales[1] = yInterval.scaleTo(interval2.yInterval); return scales; } /** get isotropic scale to other interval2. * takes minimum value of x and y scales * @param interval2 * @return scale may be NaN */ public double scaleTo(Real2Interval interval2) { double scale = Double.NaN; double[] scales = scalesTo(interval2); if (Double.isNaN(scales[0])) { scale = scales[1]; } else if (Double.isNaN(scales[1])) { scale = scales[0]; } else { scale = Math.min(scales[0], scales[0]); } return scale; } /** offsets to overlap origins in each * scales these by scales and then calculates offsets to overlap midpoints * @param interval2 * @param scales (some might be NaN) * @return offsets (components might be NaN. */ public double[] offsetsTo(Real2Interval interval2, double[] scales) { double[] offsets = new double[2]; offsets[0] = xInterval.offsetTo(interval2.xInterval, scales[0]); offsets[1] = yInterval.offsetTo(interval2.yInterval, scales[1]); return offsets; } /** offsets to overlap origins in each * isotropic scales * scales these by scale * @param interval2 * @param scale * @return offsets (components might be NaN. */ public double[] offsetsTo(Real2Interval interval2, double scale) { return offsetsTo(interval2, new double[]{scale, scale}); } /** offset to map one interval onto another. * exact mapping in both directions * @param interval2 * @return offset applied after scaling */ public double[] offsetsTo(Real2Interval interval2) { double[] offsets = new double[2]; offsets[0] = xInterval.offsetTo(interval2.xInterval); offsets[1] = yInterval.offsetTo(interval2.yInterval); return offsets; } /** gets midpoint. * * @return midpoint of both axes */ public Real2 midPoint() { return new Real2(xInterval.midPoint(), yInterval.midPoint()); } // /** offsets to overlap given points in each // * scales these by scales and then calculates offsets to overlap midpoints // * @param interval2 // * @param scales (some might be NaN) // * @return offsets (components might be NaN. // */ // public double[] offsetsTo(Real2Interval interval2, double scale, Real2 xyThis, Real2 xy2) { // double[] offsets = new double[2]; // offsets[0] = xInterval.offsetTo(interval2.xInterval, scales[0]); // offsets[1] = yInterval.offsetTo(interval2.yInterval, scales[1]); // return offsets; // } } wwmm-euclid-87e8f785a814/src/main/java/org/xmlcml/euclid/Real2Range.java0000644000000000000000000001674611607017524023731 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid; import org.xmlcml.euclid.Axis.Axis2; /** * 2-D double limits Contains two RealRanges. Can therefore be used to describe * 2-dimensional limits (for example axes of graphs, rectangles in graphics, * limits of a molecule, etc.) *

* Default is two default/invalid RealRange components. Adding points will * create valid ranges. * * @author (C) P. Murray-Rust, 1996 */ public class Real2Range implements EuclidConstants { /** * X-range */ RealRange xrange; /** * Y-range */ RealRange yrange; /** * constructor. */ public Real2Range() { } /** * initialise with min and max values; * * @param xr * @param yr */ public Real2Range(RealRange xr, RealRange yr) { if (xr.isValid() && yr.isValid()) { xrange = xr; yrange = yr; } } public Real2Range(Real2 r2a, Real2 r2b) { double x0 = r2a.getX(); double x1 = r2b.getX(); xrange = new RealRange(Math.min(x0, x1), Math.max(x0, x1)); double y0 = r2a.getY(); double y1 = r2b.getY(); yrange = new RealRange(Math.min(y0, y1), Math.max(y0, y1)); } /** * copy constructor * * @param r */ public Real2Range(Real2Range r) { if (r.isValid()) { xrange = new RealRange(r.xrange); yrange = new RealRange(r.yrange); } } /** * a Real2Range is valid if both its constituent ranges are * * @return valid */ public boolean isValid() { return (xrange != null && yrange != null && xrange.isValid() && yrange .isValid()); } /** * is equals to. * * @param r2 * @return tru if equal */ @Deprecated public boolean isEqualTo(Real2Range r2) { if (isValid() && r2 != null && r2.isValid()) { return (xrange.isEqualTo(r2.xrange) && yrange.isEqualTo(r2.yrange)); } else { return false; } } /** * is equals to. * * @param r2 * @return tru if equal */ public boolean isEqualTo(Real2Range r2, double eps) { if (isValid() && r2 != null && r2.isValid()) { return (xrange.isEqualTo(r2.xrange, eps) && yrange.isEqualTo(r2.yrange, eps)); } else { return false; } } /** * merge two ranges and take the maximum extents * * @param r2 * @return range */ public Real2Range plus(Real2Range r2) { if (!isValid()) { if (r2 == null || !r2.isValid()) { return new Real2Range(); } else { return new Real2Range(r2); } } if (r2 == null || !r2.isValid()) { return new Real2Range(this); } return new Real2Range(xrange.plus(r2.xrange), yrange.plus(r2.yrange)); } /** * intersect two ranges and take the range common to both; return invalid * range if no overlap or either is null/invalid * * @param r2 * @return range * */ public Real2Range intersectionWith(Real2Range r2) { if (!isValid() || r2 == null || !r2.isValid()) { return new Real2Range(); } RealRange xr = this.getXRange().intersectionWith(r2.getXRange()); RealRange yr = this.getYRange().intersectionWith(r2.getYRange()); return (xr == null || yr == null) ? null : new Real2Range(xr, yr); } /** * get xrange * * @return range */ public RealRange getXRange() { return xrange; } /** * get yrange * * @return range */ public RealRange getYRange() { return yrange; } /** * get yrange * * @return range */ public Real2 getCentroid() { return new Real2(xrange.getMidPoint(), yrange.getMidPoint()); } /** gets lower left and upper right. * @return minx,miny ... maxx, maxy */ public Real2[] getCorners() { Real2[] rr = new Real2[2]; rr[0] = new Real2(xrange.getMin(), yrange.getMin()); rr[1] = new Real2(xrange.getMax(), yrange.getMax()); return rr; } /** * is an Real2 within a Real2Range * * @param p * @return includes */ public boolean includes(Real2 p) { if (!isValid()) { return false; } return (xrange.includes(p.getX()) && yrange.includes(p.getY())); } /** * is one Real2Range completely within another * * @param r * @return includes */ public boolean includes(Real2Range r) { if (!isValid() || r == null || !r.isValid()) { return false; } RealRange xr = r.getXRange(); RealRange yr = r.getYRange(); return (xrange.includes(xr) && yrange.includes(yr)); } /** * add a Real2 to a range * * @param p */ public void add(Real2 p) { if (p == null) return; if (xrange == null) xrange = new RealRange(); if (yrange == null) yrange = new RealRange(); xrange.add(p.getX()); yrange.add(p.getY()); } /** * merge range for given axis. * * @param ax * axis * @param range */ public void add(Axis2 ax, RealRange range) { if (range == null) return; if (ax.equals(Axis2.X)) { if (xrange == null) { xrange = new RealRange(); } xrange = xrange.plus(range); } if (ax.equals(Axis2.Y)) { if (yrange == null) { yrange = new RealRange(); } yrange = yrange.plus(range); } } /** gets minimum X and Y translations required to move point into range * uses RealRange.distanceOutside() - see this * @param p * @return null if p == null or has bad coordinates; Real2(0,0) if in or on range, else translations to touch range */ public Real2 distanceOutside(Real2 p) { Real2 r2 = null; if (p != null) { double dx = xrange.distanceOutside(p.getX()); double dy = yrange.distanceOutside(p.getY()); if (!Double.isNaN(dx) && !Double.isNaN(dy)) { r2 = new Real2(dx, dy); } } return r2; } /** * to string. * * @return string */ public String toString() { String xx = (xrange == null) ? "NULL" : xrange.toString(); String yy = (yrange == null) ? "NULL" : yrange.toString(); return EC.S_LBRAK + xx + EC.S_COMMA + yy + EC.S_RBRAK; } } wwmm-euclid-87e8f785a814/src/main/java/org/xmlcml/euclid/Real2Vector.java0000644000000000000000000005630611607017524024133 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid; import java.util.ArrayList; import java.util.List; import org.xmlcml.euclid.Axis.Axis2; /** * a (Java) Vector of Real2s (Note that 'Vector' is used by Java to describe an * array of objects - there is no relationship to geometrical vectors in this * package.) *

* Support is also given for the two component arrays as RealArrays *

* Default is an empty (Java) Vector; * * @author (C) P. Murray-Rust, 1996 */ public class Real2Vector implements EuclidConstants { List vector; /** * Comment for serialVersionUID */ private static final long serialVersionUID = 3834026952770990647L; /** * constructor. */ public Real2Vector() { vector = new ArrayList(); } /** * Formed by feeding in an existing array to a 2xn matrix THE COLUMN IS THE * FASTEST MOVING INDEX, that is the matrix is filled as flarray(0,0, * flarray(0,1). Primarily for compatibility with other apps * * @param flarray * @exception EuclidRuntimeException * array must have even number of elements * */ public Real2Vector(double[] flarray) throws EuclidRuntimeException { this(); int count = 0; int n = flarray.length / 2; if (flarray.length != 2 * n) { throw new EuclidRuntimeException("size must be multiple of 2"); } for (int i = 0; i < n; i++) { Real2 p = new Real2(flarray[count++], flarray[count++]); vector.add(p); } } /** * from two parallel arrays of x, y - by REFERENCE. * * @param n * @param x * @param y * @throws EuclidRuntimeException * */ public Real2Vector(int n, double[] x, double[] y) throws EuclidRuntimeException { this(); Util.check(x, n); Util.check(y, n); for (int i = 0; i < n; i++) { vector.add(new Real2(x[i], y[i])); } } /** conversion routine. * * @param r2a */ public Real2Vector(Real2Array r2a) { this(r2a.size(), r2a.getXArray().getArray(), r2a.getYArray().getArray()); } /** * constructor from RealArray - by REFERENCE * * @param m * @exception EuclidRuntimeException * array must have even number of elements */ public Real2Vector(RealArray m) throws EuclidRuntimeException { this(); int count = m.size() / 2; if (m.size() != count * 2) { throw new EuclidRuntimeException("size must be multiple of 2"); } double[] marray = m.getArray(); int j = 0; for (int i = 0; i < count; i++) { vector.add(new Real2(marray[j++], marray[j++])); } } /** * copy constructor from Real2Vector COPIES pv * * @param pv */ public Real2Vector(Real2Vector pv) { this(); for (int i = 0; i < pv.size(); i++) { vector.add(new Real2(pv.get(i))); } } /** * construct from list of Real2. * * @param rList * list */ public Real2Vector(List rList) { this(); for (Real2 r : rList) { add(r); } } /** * appens a Real2. * * @param p * to append */ public void add(Real2 p) { vector.add(p); } /** * gets Real2 element. * * @param i * the position * @return the Real2 or null if outside range */ public Real2 get(int i) { return (Real2) vector.get(i); } /** * @param i * @param v * @exception EuclidRuntimeException * vector does not have an i'th element */ public void set(int i, Real2 v) throws EuclidRuntimeException { vector.set(i, v); } /** * size of vector. * * @return the size */ public int size() { return vector.size(); } /** access the vector. * this is the only storage so should be safe * @return vector */ public List getVector() { return vector; } /** * get range of one coordinate * * @param ax * @return range */ public RealRange getRange(Axis2 ax) { RealArray temp = new RealArray(vector.size()); double[] dd = temp.getArray(); int i = 0; for (Real2 p : vector) { dd[i++] = (ax.equals(Axis2.X)) ? p.getX() : p.getY(); } RealRange range = new RealRange(); if (size() > 0) { range.add(temp.smallestElement()); range.add(temp.largestElement()); } return range; } /** * get range of both coordinates * * @return range */ public Real2Range getRange2() { Axis2 axes[] = Axis2.values(); Real2Range range2 = new Real2Range(); for (Axis2 ax : axes) { RealRange range = getRange(ax); range2.add(ax, range); } return range2; } /** * create a NEW subset of the points; points are COPIED * * @param is * @return sub array * @exception EuclidRuntimeException * an element of is is out of range of this */ public Real2Vector subArray(IntSet is) throws EuclidRuntimeException { Real2Vector sub = new Real2Vector(); for (int i = 0; i < is.size(); i++) { int ix = is.elementAt(i); if (ix < 0 || ix >= vector.size()) { throw new EuclidRuntimeException("index out of range " + ix); } sub.add(new Real2(this.getReal2(ix))); } return sub; } /** * create a subset of the points within a box * * @param r * @return sub set */ public IntSet subSet(Real2Range r) { IntSet is = new IntSet(); for (int i = 0; i < size(); i++) { Real2 point = (Real2) vector.get(i); if (r.includes(point)) { is.addElement(i); } } return is; } /** * get the closest point (both ranges are assumed to have the same scales * * @param p * @return index of point */ public int getClosestPoint(Real2 p) { double dist2 = Double.POSITIVE_INFINITY; int ipoint = -1; for (int i = 0; i < size(); i++) { Real2 point = this.get(i); double dx = p.x - point.x; double dy = p.y - point.y; double d2 = dx * dx + dy * dy; if (d2 < dist2) { dist2 = d2; ipoint = i; } } return ipoint; } /** * get the index of the first point within a box centered on p (that is p+- * width/2, height/2) or -1 if none * * @param p * @param width * @param height * @return index of point * */ public int getPoint(Real2 p, double width, double height) { double hwidth = width / 2.0; double hheight = height / 2.0; for (int i = 0; i < size(); i++) { Real2 point = this.get(i); if (Math.abs(p.x - point.x) <= hwidth && Math.abs(p.y - point.y) <= hheight) return i; } return -1; } /** * translate by a vector, synonym for plus. MODIFIES 'this' * * @param v */ public void translateBy(Real2 v) { for (int i = 0; i < size(); i++) { Real2 p = getReal2(i).plus(v); vector.set(i, p); } } /** * add a Real2 to all elements of this. MODIFIES 'this' * * @param p */ public void plus(Real2 p) { this.translateBy(p); } /** * translate negatively; MODIFIES 'this' * * @param v */ public void subtract(Real2 v) { Real2 v1 = new Real2(v); v1.negative(); this.plus(v1); } /** * multiply all coordinates be a given scalar (that is expands scale) * * @param f */ public void multiplyBy(double f) { for (int i = 0; i < size(); i++) { Real2 p = getReal2(i).multiplyBy(f); vector.set(i, p); } } /** * get distance between 2 points * * @param i1 * @param i2 * @return distance */ public double distance(int i1, int i2) { Real2 v1 = getReal2(i1).subtract(getReal2(i2)); return v1.getLength(); } /** * get distance between 2 points * * @param is * @return distance * @exception EuclidRuntimeException * a value in IntSet is not in the range 0 ... nelem-1 */ public double distance(IntSet is) throws EuclidRuntimeException { if (is.size() != 2) { throw new EuclidRuntimeException("index must be multiple of 2"); } return distance(is.elementAt(0), is.elementAt(1)); } /** * get angle between 3 points * * @param i1 * @param i2 * @param i3 * @return angle * @exception EuclidRuntimeException * two points are coincident */ public Angle angle(int i1, int i2, int i3) throws EuclidRuntimeException { return Real2.getAngle(getReal2(i1), getReal2(i2), getReal2(i3)); } /** * get angle between 3 points * * @param is * @return angle * @exception EuclidRuntimeException * a value in IntSet is not in the range 0 ... nelem-1 */ public Angle angle(IntSet is) throws EuclidRuntimeException { if (is.size() != 3) { throw new EuclidRuntimeException("index must be multiple of 3"); } return angle(is.elementAt(0), is.elementAt(1), is.elementAt(2)); } /** * get the i'th Real2 * * @param i * @return element */ public Real2 getReal2(int i) { return (Real2) get(i); } /** get List of Real2s. * * @return the list */ public List getReal2List() { return vector; } /** * get the coordinate coordinate array as doubles x,y,x,y, * * @return array */ public RealArray getXY() { double[] f = new double[2 * size()]; int count = 0; for (int i = 0; i < size(); i++) { Real2 p = getReal2(i); f[count++] = p.getX(); f[count++] = p.getY(); } return new RealArray(f); } /** * get the X coordinate array * * @return array */ public RealArray getXArray() { double[] f = new double[size()]; int count = 0; for (int i = 0; i < size(); i++) { Real2 p = getReal2(i); f[count++] = p.getX(); } return new RealArray(f); } /** * get the Y coordinate array * * @return array */ public RealArray getYArray() { double[] f = new double[size()]; int count = 0; for (int i = 0; i < size(); i++) { Real2 p = getReal2(i); f[count++] = p.getY(); } return new RealArray(f); } /** convenience * * @return real2Array */ public Real2Array getReal2Array() { return new Real2Array(getXArray(), getYArray()); } /** * get a single coordinate value * * @param i * @param j * @return coord */ public double getCoordinate(int i, Axis2 j) { return (j.value == 0) ? getReal2(i).getX() : getReal2(i).getY(); } /** * get a single coordinate array - for example all x-coordinates * * @param axis * @return array */ public RealArray getXorY(Axis2 axis) { double[] f = new double[size()]; for (int i = 0; i < size(); i++) { f[i] = (axis.value == 0) ? getReal2(i).getX() : getReal2(i).getY(); } return new RealArray(f); } /** * swap all X and Y coordinates; MODIFIES array */ public void swapXY() { for (int i = 0; i < size(); i++) { Real2 temp = (Real2) vector.get(i); temp.swap(); vector.set(i, temp); } } /** * sort ARRAY on X or Y coordinate; returns new array * * @param ax * @return vector */ public Real2Vector sortAscending(Axis2 ax) { IntSet is = getXorY(ax).indexSortAscending(); Real2Vector temp = new Real2Vector(); for (int i = 0; i < size(); i++) { temp.add(this.get(is.elementAt(i))); } return temp; } /** * sort ARRAY on X or Y coordinate; returns new array * * @param ax * @return vector * */ public Real2Vector sortDescending(Axis2 ax) { IntSet is = getXorY(ax).indexSortDescending(); Real2Vector temp = new Real2Vector(); for (int i = 0; i < size(); i++) { temp.add(this.get(is.elementAt(i))); } return temp; } /** * transforms 'this' by rotation-translation matrix; MODIFIES 'this' * * @param t */ public void transformBy(Transform2 t) { for (int i = 0; i < size(); i++) { Real2 point = (Real2) vector.get(i); point.transformBy(t); vector.set(i, point); } } /** * squared difference between corresponding points in 2 real2Vectors. must * be of same length else returns Double.NaN * * @param r2v * vector to compare * @return sum ((x1-x2)**2 + (y1-y2)**2) */ public double getSquaredDifference(Real2Vector r2v) { double sum = Double.NaN; if (r2v.size() == 0 || vector.size() == 0 || r2v.size() != vector.size()) { } else { sum = 0.0; for (int i = 0; i < size(); i++) { Real2 xy1 = this.get(i); Real2 xy2 = r2v.get(i); double d2 = xy1.getSquaredDistance(xy2); sum += d2; } } return sum; } /** * gets array of squared distances between corresponding points. * * array of d(this(i)-r2v(i))^2; returns null if Real2Vectors are different * lengths * * @param r2v * other vector * @return array of squares distances else null */ public double[] getSquaredDistances(Real2Vector r2v) { double dist2[] = null; if (r2v.size() == vector.size()) { dist2 = new double[vector.size()]; for (int i = 0; i < size(); i++) { Real2 xy1 = this.get(i); Real2 xy2 = r2v.get(i); dist2[i] = xy1.getSquaredDistance(xy2); } } return dist2; } /** * rotate about centroid by given angle; MODIFIES 'this' * * @param a */ public void rotateAboutCentroid(Angle a) { Real2 temp = this.getCentroid(); Transform2 t2 = new Transform2(a); t2 = new Transform2(t2, temp); this.transformBy(t2); } /** creates mirror image * changes sign of x-coords */ public void flipX() { for (Real2 r2 : vector) { r2.setX(-r2.getX()); } } /** creates mirror image * changes sign of y-coords */ public void flipY() { for (Real2 r2 : vector) { r2.setY(-r2.getY()); } } /** * create regular polygon. * centre is at 0.0, first point at * (rad*cos(angle+dangle), rad*sin(angle+dangle)) * points go anticlockwise * * @param nsides * @param rad the radius * @param angle offset to vertical (radians) * (point 0 is at rad*cos(angle), rad*sin(angle)) * @return array of points */ public static Real2Vector regularPolygon(int nsides, double rad, double angle) { Real2Vector temp = new Real2Vector(); double dangle = 2 * Math.PI / (new Integer(nsides).doubleValue()); for (int i = 0; i < nsides; i++) { Real2 p = new Real2(rad * Math.sin(angle), rad * Math.cos(angle)); temp.add(p); angle += dangle; } return temp; } /** * create part of regular polygon. * centre is at 0.0, last point at (rad, 0) * points go anticlockwise * produces points pointn, pointn+1, ... nsides-1, 0 * if npoint is 1 we get full polygon * if npoint >= nsides returns null * @param nsides * @param pointn * @param dist0n between point0 and npoint * @return array of points */ public static Real2Vector partOfRegularPolygon(int nsides, int pointn, double dist0n) { Real2Vector temp = new Real2Vector(); double dangle = 2 * Math.PI / (new Integer(nsides).doubleValue()); double sinAngle2 = Math.sin((double) pointn * dangle / 2.); double rad = 0.5 * dist0n / sinAngle2; double angle = dangle; for (int i = pointn; i <= nsides; i++) { Real2 p = new Real2(rad * Math.sin(angle), rad * Math.cos(angle)); temp.add(p); angle += dangle; } return temp; } /** * create regular polygon. * centre is at 0.0, first point at (0, rad) * points go anticlockwise (rad*cos, -rad*sin) * * @param nsides * @param rad the radius * @return array of points */ public static Real2Vector regularPolygon(int nsides, double rad) { return regularPolygon(nsides, rad, 0.0); } /** create regular polygon. * goes through points p1, p2 * if m = (p1 +p2)/2 * and c is centre of circle * and pp = p2 - p1 * and d = c-m * then signed angle(pp, d) is 90 * * points go clockwise * to make the polygon go the other way reverse p1 and p2 * @param nsides * @param p1 first point * @param p2 second point * @param flip use mirror image * @return array of points */ public static Real2Vector regularPolygon(int nsides, Real2 p1, Real2 p2, boolean flip) { double halfAngle = Math.PI / (double) nsides; Vector2 p1top2 = new Vector2(p2.subtract(p1)); double halfSidelength = p1top2.getLength() / 2.0; double rad = halfSidelength / Math.sin(halfAngle); Real2Vector temp = regularPolygon(nsides, rad); if (flip) { temp.flipY(); } // deviation between p1p2 and the y-axis Angle rot = null; rot = p1top2.getAngleMadeWith(new Vector2(0.0, 1.0)); rot = new Vector2(1.0, 0.0).getAngleMadeWith(p1top2); temp.transformBy(new Transform2(rot)); temp.transformBy(new Transform2(new Angle(-halfAngle))); Real2 shift = p1.subtract(new Vector2(temp.get(0))); temp.transformBy(new Transform2(new Vector2(shift))); return temp; } /** * get centroid of all points. does not modify this * * @return the centroid */ public Real2 getCentroid() { if (vector.size() < 1) return null; Real2 p = new Real2(); for (int j = 0; j < vector.size(); j++) { Real2 pp = (Real2) vector.get(j); p = p.plus(pp); } double scale = 1.0 / (new Double(vector.size()).doubleValue()); p = p.multiplyBy(scale); return p; } /** * get serialNumber of nearest point. * * @param point * @return serial of point */ public int getSerialOfNearestPoint(Real2 point) { double dist = Double.MAX_VALUE; int serial = -1; for (int j = 0; j < vector.size(); j++) { double d = this.get(j).subtract(point).getLength(); if (d < dist) { serial = j; dist = d; } } return serial; } /** * get rectangular distance matrix. * * matrix need not be square or symmetric unless coords == coords2 d(ij) is * distance between coord(i) and coords2(j). * * @param coords2 * @return distance matrix */ public RealMatrix getDistanceMatrix(List coords2) { int size = vector.size(); int size2 = coords2.size(); RealMatrix distMatrix = new RealMatrix(size, size2); double[][] mat = distMatrix.getMatrix(); for (int i = 0; i < size; i++) { Real2 ri = this.get(i); for (int j = 0; j < size2; j++) { Real2 rj = coords2.get(j); double dij = ri.getDistance(rj); mat[i][j] = dij; } } return distMatrix; } /** * if real2Vector is treated as a polygon, determines whether point * is inside it // The function will return true if the point x,y is inside the polygon, or // false if it is not. If the point is exactly on the edge of the polygon, // then the function may return YES or NO. */ public boolean encloses(Real2 point) { int nvect = vector.size(); int j = nvect - 1; boolean oddNodes = false; double x = point.getX(); double y = point.getY(); for (int i=0; i < nvect; i++) { double xi = vector.get(i).getX(); double yi = vector.get(i).getY(); double xj = vector.get(j).getX(); double yj = vector.get(j).getY(); if (yi < y && yj >= y || yj < y && yi >= y) { if (xi + (y - yi) / (yj - yi) * (xj - xi) < x) { oddNodes = !oddNodes; } } j = i; } return oddNodes; } /** * to string. * * @return string */ public String toString() { StringBuffer sb = new StringBuffer(); sb.append(S_LBRAK); for (int i = 0; i < size(); i++) { sb.append(getReal2(i)); if (i < (size() - 1)) { sb.append(S_NEWLINE); } } sb.append(S_RBRAK); return sb.toString(); } } wwmm-euclid-87e8f785a814/src/main/java/org/xmlcml/euclid/Real3Range.java0000644000000000000000000001377411607017524023730 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid; import org.xmlcml.euclid.Axis.Axis3; /** * 3-D double limits * * Contains 3 RealRanges. Can therefore be used to describe 3-dimensional limits * (for example axes of 3-D graphs, boxes in graphics, limits of a molecule, * etc.) *

* Default is three invalid RealRange components. * * @author (C) P. Murray-Rust, 1996 */ public class Real3Range implements EuclidConstants { private RealRange[] xyzrange = new RealRange[3]; /** * default is three default RealRanges */ public Real3Range() { for (int i = 0; i < 3; i++) { xyzrange[i] = new RealRange(); } } /** * initialise with min and max values; takes COPIES * * @param xr * @param yr * @param zr */ public Real3Range(RealRange xr, RealRange yr, RealRange zr) { setRanges(xr, yr, zr); } /** reset ranges. * clears any existing content * @param xr * @param yr * @param zr */ public void setRanges(RealRange xr, RealRange yr, RealRange zr) { xyzrange[0] = new RealRange(xr); xyzrange[1] = new RealRange(yr); xyzrange[2] = new RealRange(zr); } /** * copy constructor * * @param r */ public Real3Range(Real3Range r) { for (int i = 0; i < 3; i++) { xyzrange[i] = new RealRange(r.xyzrange[i]); } } /** * is equal to. * * @param r3 * @return tru if equals */ public boolean isEqualTo(Real3Range r3, double eps) { return (xyzrange[0].isEqualTo(r3.xyzrange[0], eps) && xyzrange[1].isEqualTo(r3.xyzrange[1], eps) && xyzrange[2] .isEqualTo(r3.xyzrange[2], eps)); } /** * is equal to. * * @param r3 * @return tru if equals */ @Deprecated public boolean isEqualTo(Real3Range r3) { return (xyzrange[0].isEqualTo(r3.xyzrange[0]) && xyzrange[1].isEqualTo(r3.xyzrange[1]) && xyzrange[2] .isEqualTo(r3.xyzrange[2])); } /** * add two ranges. applies plus to each of x, y, z. creates minima and * maxima of this, r3 * * @param r3 * @return new range */ public Real3Range plus(Real3Range r3) { return new Real3Range(xyzrange[0].plus(r3.xyzrange[0]), xyzrange[1] .plus(r3.xyzrange[1]), xyzrange[2].plus(r3.xyzrange[2])); } /** * get xrange * * @return range */ public RealRange getXRange() { return xyzrange[0]; } /** * get yrange * * @return range */ public RealRange getYRange() { return xyzrange[1]; } /** * get zrange * * @return range */ public RealRange getZRange() { return xyzrange[2]; } /** * add a single value * * @param ax * @param value */ public void add(Axis3 ax, double value) { xyzrange[ax.value].add(value); } /** * add a single value * * @param ax * @param range */ public void add(Axis3 ax, RealRange range) { xyzrange[ax.value] = range; } /** * add a single value - not for general use * * @param axis * @param value */ protected void add(int axis, double value) { xyzrange[axis].add(value); } /** * is a Point3 within a Real3Range * * @param p * @return includes */ public boolean includes(Point3 p) { double[] coords = p.getArray(); return (xyzrange[0].includes(coords[0]) && xyzrange[1].includes(coords[1]) && xyzrange[2] .includes(coords[2])); } /** * add a Point3 to a range * * @param p */ public void add(Point3 p) { double[] coords = p.getArray(); xyzrange[0].add(coords[0]); xyzrange[1].add(coords[1]); xyzrange[2].add(coords[2]); } /** get point with min x, y, z. * * @return the point. */ public Point3 getMinPoint3() { return new Point3( xyzrange[0].getMin(), xyzrange[1].getMin(), xyzrange[2].getMin()); } /** get point with max x, y, z. * * @return the point. */ public Point3 getMaxPoint3() { return new Point3( xyzrange[0].getMax(), xyzrange[1].getMax(), xyzrange[2].getMax()); } /** transforms range. * modifies this * @param transform */ public void transformEquals(Transform3 transform) { Point3 minxyz = getMinPoint3(); Point3 maxxyz = getMaxPoint3(); minxyz.transformEquals(transform); maxxyz.transformEquals(transform); Real3Range newRange3 = new Real3Range(); newRange3.add(minxyz); newRange3.add(maxxyz); int i = 0; for (RealRange xyzr : newRange3.xyzrange) { this.xyzrange[i++] = new RealRange(xyzr); } } /** * to string. * * @return string */ public String toString() { return EC.S_LBRAK + xyzrange[0] + EC.S_COMMA + xyzrange[1] + EC.S_COMMA + xyzrange[2] + EC.S_RBRAK; } } wwmm-euclid-87e8f785a814/src/main/java/org/xmlcml/euclid/RealArray.java0000644000000000000000000015313211607017524023660 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid; import java.text.DecimalFormat; import org.apache.log4j.Logger; /** * array of doubles * * RealArray represents a 1-dimensional array of doubles and is basically a * wrapper for double[] in Java There are a lot of useful member functions * (sorting, ranges, parallel operations * * The default is an array with zero points All arrays are valid objects. * * Attempting to create an array with < 0 points creates a default array (zero * points). * * Since double[] knows its length (unlike C), there are many cases where * double[] can be safely used. However it is not a first-class object and * RealArray supplies this feature. double[] is referenceable through getArray() * * note that the length of the internal array may not be a useful guide to the * number of elements. Use contractArray() to adjust arraySize to number of * elements (useful after adding elements). * * * @author (C) P. Murray-Rust, 1996 */ public class RealArray extends ArrayBase { final static Logger LOG = Logger.getLogger(RealArray.class); /** filter */ public enum Filter { /** */ GAUSSIAN("Gaussian"), /** */ GAUSSIAN_FIRST_DERIVATIVE("Gaussian First Derivative"), /** */ GAUSSIAN_SECOND_DERIVATIVE("Gaussian Second Derivative"); /** string value */ public String string; private Filter(String s) { this.string = s; } } public enum Monotonicity { INCREASING, DECREASING } /** * maximum number of elements (for bound checking) - resettable */ private int maxelem = 10000; /** * actual number of elements */ private int nelem; /** * the array of doubles */ private double[] array; private int bufsize = 5; private DecimalFormat format = null; /** * create default Array. default is an array of zero points */ public RealArray() { nelem = 0; bufsize = 5; array = new double[bufsize]; } /** * checks potential size of array. if n < 0, set to 0, otherwise adjust * bufsize to be consistent * * @param n * size of array * @return false if negative */ private boolean checkSize(int n) { if (n < 0) { n = 0; return false; } else { nelem = n; if (nelem > maxelem) maxelem = nelem; if (bufsize < nelem) bufsize = nelem; return true; } } // expands buffer if necessary and copies array into it private void makeSpace(int newCount) { if (bufsize < 5) { bufsize = 5; } if (newCount >= bufsize || array.length < newCount) { while (newCount >= bufsize) { bufsize *= 2; } double[] array1 = new double[bufsize]; System.arraycopy(array, 0, array1, 0, nelem); array = array1; } } /** * creates n-element array. initialised to 0 * * @param n * size of array */ public RealArray(int n) { this(n, 0.0); } /** * create n-element array initialised linearly. values are elem1+(i-1)*delta * * @param n * size of array * @param elem1 * starting value * @param delta * setpsize */ public RealArray(int n, double elem1, double delta) { if (!checkSize(n)) return; array = new double[n]; bufsize = n; double ff = elem1; for (int i = 0; i < n; i++) { array[i] = ff; ff += delta; } } /** * create Array initialized to constant value. all elements of the array are * set to a given value * * @param n * size of array * @param elem1 * value to set */ public RealArray(int n, double elem1) { if (!checkSize(n)) return; array = new double[n]; bufsize = n; for (int i = 0; i < n; i++) { array[i] = elem1; } } /** * create Array from part of java array. use first n elements of array. * * @param n * number of elements to use * @param arr * array to read from * @throws EuclidRuntimeException * n larger than arraysize */ public RealArray(int n, double[] arr) throws EuclidRuntimeException { if (!checkSize(n)) throw new EuclidRuntimeException("Cannot have negative array length"); if (n > arr.length) { throw new EuclidRuntimeException("Array size too small"); } array = new double[n]; bufsize = n; System.arraycopy(arr, 0, array, 0, n); } /** * create Array from java array. * * @param arr * array to read from */ public RealArray(double[] arr) { setElements(arr); } /** * create from IntArray. * * @param ia * IntArray to copy from */ public RealArray(IntArray ia) { if (!checkSize(ia.size())) return; array = new double[nelem]; bufsize = nelem; for (int i = 0; i < nelem; i++) { array[i] = (new Double(ia.elementAt(i))).doubleValue(); } } /** * create from subarray of another Array. * * @param m * array to slice * @param low * inclusive start index of array * @param high * inclusive end index of array * @throws EuclidRuntimeException * low > high or negative indices or outside size of m */ public RealArray(RealArray m, int low, int high) throws EuclidRuntimeException { if (low < 0 || low > high || high >= m.size()) { throw new EuclidRuntimeException("index out of range " + low + EC.S_SLASH + high); } nelem = high - low + 1; checkSize(nelem); array = new double[nelem]; bufsize = nelem; System.arraycopy(m.array, low, array, 0, nelem); } /** * create mixed sliced array. use another IntArray to subscript this one * where I(this) = I(ref) subscripted by I(sub); Result has dimension of * I(sub). caller is responsible for making sure elements of sub are unique * * @param ref * matrix to slice * @param sub * subscripts. * @throws EuclidRuntimeException * if any of I(sub) lies outside 0...refmax-1 */ public RealArray(RealArray ref, IntArray sub) throws EuclidRuntimeException { this(sub.size()); for (int i = 0; i < sub.size(); i++) { int j = sub.elementAt(i); if (j < 0 || j >= ref.size()) { throw new EuclidRuntimeException("index out of range " + j); } this.setElementAt(i, ref.elementAt(j)); } } /** gets range distributed about a midpoint. * * array is from n steps from mid-halfrange to mid to mid+halfrange * @param mid midpoint of range * @param nsteps odd number of steps * @param halfrange * @return array */ public static RealArray getSymmetricalArray( double mid, int nsteps, double halfrange) { if (nsteps < 3 || nsteps % 2 != 1) { throw new EuclidRuntimeException( "Number of steps must be positive odd number; was: "+nsteps); } int nhalfsteps = (nsteps - 1) / 2; double step = halfrange / nhalfsteps; RealArray realArray = new RealArray(nsteps, mid - halfrange, step); return realArray; } /** * clone. * * @return the clone */ public Object clone() { RealArray temp = new RealArray(nelem); temp.nelem = nelem; temp.maxelem = maxelem; System.arraycopy(array, 0, temp.array, 0, nelem); temp.bufsize = nelem; return (Object) temp; } /** * copy constructor. * * @param m * array to copy */ public RealArray(RealArray m) { this.shallowCopy(m); System.arraycopy(m.array, 0, array, 0, nelem); } /** * Create customized array. create a given 'shape' of array for data * filtering An intended use is with RealArray.arrayFilter(). The shapes * (before scaling by maxval) are: *

* step is maxval / nn * * @param nn * number of elements * @param shape * TRIANGLE or ZIGZAG * @param maxval * used to compute step */ public RealArray(int nn, String shape, double maxval) { if (shape.toUpperCase().equals("TRIANGLE")) { nelem = nn * 2 - 1; if (!checkSize(nelem)) return; array = new double[nelem]; double delta = maxval / ((double) nn); for (int i = 0; i < nn; i++) { array[i] = (i + 1) * delta; array[nelem - i - 1] = array[i]; } } else if (shape.toUpperCase().equals("ZIGZAG")) { nelem = nn * 4 - 1; if (!checkSize(nelem)) return; array = new double[nelem]; double delta = maxval / ((double) nn); for (int i = 0; i < nn; i++) { array[i] = (i + 1) * delta; array[2 * nn - i - 2] = array[i]; array[2 * nn + i] = -array[i]; array[nelem - i - 1] = -array[i]; } array[2 * nn - 1] = 0.0; } } /** * construct from an array of Strings. must represent doubles * * @param strings * values as Strings * @exception EuclidRuntimeException * a string could not be interpreted as doubles */ public RealArray(String[] strings) throws EuclidRuntimeException { this(strings.length); for (int i = 0; i < strings.length; i++) { try { array[i] = Real.parseDouble(strings[i]); } catch (Exception e) { throw new EuclidRuntimeException("Bad array element at ("+i+") :"+strings[i]+":"); } } } /** * create from a space-separated string of doubles. * * @param string * of form "1.1 -3.2 0.56E-04 2..." * @exception NumberFormatException * a substring could not be interpreted as double */ public RealArray(String string) throws NumberFormatException { this(string.split(S_WHITEREGEX)); } /** * set output format. doesn't yet do anything! * * @param f */ public void setFormat(DecimalFormat f) { format = f; } /** * get output format. * * @return format */ public DecimalFormat getFormat() { return format; } /** * replace all values of NaN with given value. use with care as there is * probably something wrong * * @param d * default value */ public void replaceNaN(double d) { for (int i = 0; i < nelem; i++) { if (Double.isNaN(array[i])) array[i] = d; } } /** * contracts internal array to be of same length as number of elements. * should be used if the array will be used elsewhere with a fixed length. * called by getArray() */ private void contractArray() { double[] array1 = new double[nelem]; System.arraycopy(array, 0, array1, 0, nelem); array = array1; } /** * shallowCopy. * * @param m * array to copy */ void shallowCopy(RealArray m) { nelem = m.nelem; bufsize = m.bufsize; maxelem = m.maxelem; array = m.array; } /** * creates a filter based on Gaussian and derivatives. Scaled so that * approximately 2.5 sigma is included (that is value at edge is ca 0.01 of * centre * * @param halfWidth * @param function * @return array */ public static RealArray getFilter(int halfWidth, Filter function) { if (!function.equals(Filter.GAUSSIAN) && !function.equals(Filter.GAUSSIAN_FIRST_DERIVATIVE) && !function.equals(Filter.GAUSSIAN_SECOND_DERIVATIVE)) return null; if (halfWidth < 1) halfWidth = 1; double xar[] = new double[2 * halfWidth + 1]; double limit = 7.0; // ymin ca 0.01 double sum = 0; double x = 0.0; double y = 1.0; // double dHalf = Math.sqrt(0.693); double dHalf = limit * 0.693 * 0.693 / (double) halfWidth; for (int i = 0; i <= halfWidth; i++) { if (function.equals(Filter.GAUSSIAN)) { y = Math.exp(-x * x); } if (function.equals(Filter.GAUSSIAN_FIRST_DERIVATIVE)) { y = -2 * x * Math.exp(-x * x); } if (function.equals(Filter.GAUSSIAN_SECOND_DERIVATIVE)) { y = (4 * (x * x) - 2.0) * Math.exp(-x * x); } xar[halfWidth + i] = (function .equals(Filter.GAUSSIAN_FIRST_DERIVATIVE)) ? -y : y; xar[halfWidth - i] = y; sum += (i == 0) ? y : 2 * y; x += dHalf; } // normalise for Gaussian (only = the others are meaningless) if (function.equals(Filter.GAUSSIAN)) { for (int i = 0; i < 2 * halfWidth + 1; i++) { xar[i] /= sum; } } RealArray r = new RealArray(xar); return r; } /** creates a normal distribution about a mean. * returns N*(exp((x-mean)^2/(2*sigma^2)) * where N = 1/sigma*Math.sqrt(2*PI) * * The distribution is scaled to unit area over -INF to +INF * so a smaller selection will not be precisely normalised * however -5 sigma to + 5 sigma should be fine * * the x range is nsteps from maen-range to mean+range. This should be * prepared using * RealArray xvalues = RealArray.getSymmetricalArray(mean, nsteps, halfrange); * RealArray normalDist = xvalues.getNormalDistribution(sigma); * nsteps should be an odd positive integer * halfrange is the range either side of the mean * * @param sigma standard deviation * @return array */ public RealArray getNormalDistribution(double sigma) { int nsteps = this.size(); double norm = 1.0/(sigma*Math.sqrt(2*Math.PI)); double scale = 1.0/(2*sigma*sigma); RealArray normal = new RealArray(this.size()); double[] array = this.getArray(); double mean = (array[0] + array[nsteps-1])/2.0; for (int i = 0; i < nsteps; i++) { double delta = array[i] - mean; normal.array[i] = norm * Math.exp(-delta * delta * scale); } return normal; } /** gets a variate from a distribution. * 'this' is normally a regularly spaced RealArray x (e.g. * with values x[i] = x0, x0+dx, x0+2*dx, etc. * * distribution is a set of frequencies of occurrence of the values * x[0], x[1]..., i.e. f[0], f[1]... * * The method uses a cumulative dictribution with a uniformaly * distributed variable (e.g. math.random() to read off the interpolated * value of x. * * the cumulativeSum is normally used as a cache, e.g. * RealArray x = new RealArray(11, 20., 1.) // gives 20, 21 ...30 * RealArray freq = new RealArray(new double[] {23., 3., 45....) * RealArray cumulativeSum = new RealArray(); * * for (int i = 0, i < npoints; i++) { * double random = x.getRandomVariate(freq, sumulativeSum); * } * * the size of this and freq must be identical * @param distribution * @param cumulativeDistribution initially clea, then used as cache * @return a random variate */ public double getRandomVariate( RealArray distribution, RealArray cumulativeDistribution) { if (cumulativeDistribution.size() == 0) { RealArray cumul = distribution.cumulativeSum(); cumulativeDistribution.setElements(cumul.getArray()); } double[] cArray = cumulativeDistribution.getArray(); double range = cArray[cArray.length-1] - cArray[0]; double probe = cArray[0] + Math.random()* range; return lineSearch(probe, cumulativeDistribution); } /** binary search on monotonic increasing distribution. * 'this' must be regular array of values (x0, x0+dx, x0+2dx...) * @param probe * @param distribution * @return interpolated point in this */ public double lineSearch(double probe, RealArray distribution) { if (this.size() <= 1) { throw new EuclidRuntimeException("unfilled arrays in line search"); } if (this.size() != distribution.size()) { throw new EuclidRuntimeException("unequal arrays in line search"); } double[] distArray = distribution.getArray(); // binary chop int top = distArray.length-1; int bottom = 0; boolean change = true; while (change) { if (top - bottom <= 1) { break; } change = false; int mid = (top + bottom) / 2; if (distArray[mid] < probe) { bottom = mid; change = true; } else if (distArray[mid] > probe) { top = mid; change = true; } } double ratio = (probe - distArray[bottom]) / (distArray[top] - distArray[bottom]); double step = array[1] - array[0]; return this.array[bottom] + step * ratio; } /** get element by index. * * @param elem the index * @exception ArrayIndexOutOfBoundsException * elem >= size of this * @return element value */ public double elementAt(int elem) throws ArrayIndexOutOfBoundsException { return array[elem]; } /** get element by index. * * @param elem the index * @exception ArrayIndexOutOfBoundsException * elem >= size of this * @return element value */ public double get(int elem) throws ArrayIndexOutOfBoundsException { return array[elem]; } /** * get actual number of elements. * * @return number of elements */ public int size() { return nelem; } /** * get java array. always adjusted to be same length as element count * * @return the array */ public double[] getArray() { if (nelem != array.length) { contractArray(); } return array; } /** * clear all elements of array. sets value to 0.0 */ public void clearArray() { for (int i = 0; i < size(); i++) { array[i] = 0.0; } } /** * get java array in reverse order. * * @return array */ public double[] getReverseArray() { int count = size(); double[] temp = new double[count]; for (int i = 0; i < size(); i++) { temp[i] = this.array[--count]; } return temp; } private void checkConformable(RealArray m) throws EuclidRuntimeException { if (nelem != m.nelem) { throw new EuclidRuntimeException(); } } /** * are two arrays equal. * * @param f * array to compare * @return true if arrays are of same size and this(i) = f(i) */ public boolean isEqualTo(RealArray f) { return equals(f, Real.getEpsilon()); } /** * are two arrays equal. * * @param f * array to compare * @param epsilon * tolerance * @return true if arrays are of same size and Real.isEqual(array[i], * f.array[i], epsilon) */ public boolean equals(RealArray f, double epsilon) { boolean equal = false; try { checkConformable(f); equal = true; for (int i = 0; i < nelem; i++) { if (!Real.isEqual(array[i], f.array[i], epsilon)) { equal = false; break; } } } catch (Exception e) { equal = false; } return equal; } /** * adds arrays. does not modify this * * @param f * array to add * @exception EuclidRuntimeException * f is different size from this * @return new array as this + f */ public RealArray plus(RealArray f) throws EuclidRuntimeException { checkConformable(f); RealArray m = (RealArray) this.clone(); for (int i = 0; i < nelem; i++) { m.array[i] = f.array[i] + array[i]; } return m; } /** * adds arrays. modifies this += f * * @param f * array to add * @exception EuclidRuntimeException * f is different size from this */ public void plusEquals(RealArray f) throws EuclidRuntimeException { checkConformable(f); for (int i = nelem - 1; i >= 0; --i) { array[i] += f.array[i]; } } /** * subtracts arrays. does not modify this * * @param f * array to substract * @exception EuclidRuntimeException * f is different size from this * @return new array as this - f */ public RealArray subtract(RealArray f) throws EuclidRuntimeException { checkConformable(f); RealArray m = (RealArray) this.clone(); for (int i = 0; i < nelem; i++) { m.array[i] = array[i] - f.array[i]; } return m; } /** * array subtraction. modifies this -= f * * @param f * array to subtract * @exception EuclidRuntimeException * f is different size from this */ public void subtractEquals(RealArray f) throws EuclidRuntimeException { checkConformable(f); for (int i = nelem - 1; i >= 0; --i) { array[i] -= f.array[i]; } } /** * change the sign of all elements. MODIFIES this */ public void negative() { for (int i = 0; i < size(); i++) { array[i] = -array[i]; } } /** * add a scalar to all elements. creates new array; does NOT modify 'this'; * for subtraction use negative scalar * * @param f * to add * @return new array */ public RealArray addScalar(double f) { RealArray m = (RealArray) this.clone(); for (int i = 0; i < nelem; i++) { m.array[i] += f; } return m; } /** * array multiplication by a scalar. creates new array; does NOT modify * 'this' * * @param f * multiplier * @return the new array */ public RealArray multiplyBy(double f) { RealArray m = (RealArray) this.clone(); for (int i = 0; i < nelem; i++) { m.array[i] *= f; } return m; } /** * set element value. * * @param elem * index * @param f * value * @exception ArrayIndexOutOfBoundsException * elem >= size of this */ public void setElementAt(int elem, double f) throws ArrayIndexOutOfBoundsException { array[elem] = f; } /** * get array slice. creates new array; does not modify this * * @param start * index inclusive * @param end * index inclusive * @return new array */ public RealArray getSubArray(int start, int end) { int nel = end - start + 1; RealArray f = new RealArray(nel, 0); System.arraycopy(array, start, f.array, 0, nel); return f; } /** * set array slice. copy whole array into the array. * * @param start * index in this * @param a * array to copy * @throws ArrayIndexOutOfBoundsException * start < 0 or start+a.length > this.size() */ public void setElements(int start, double[] a) { if (start < 0 || start + a.length > nelem) { throw new ArrayIndexOutOfBoundsException("was "+start+" in 0-"+a.length); } System.arraycopy(a, 0, this.array, start, a.length); } /** set array. * clears any existing arrays * @param a * array to copy */ public void setElements(double[] a) { nelem = a.length; array = new double[nelem]; bufsize = nelem; System.arraycopy(a, 0, array, 0, nelem); } /** * is the array filled with zeros. * * @return true if this(i) = 0 */ public boolean isClear() { for (int i = 0; i < nelem; i++) { if (!Real.isZero(array[i], Real.getEpsilon())) return false; } return true; } /** * initialise array to given value. this(i) = f * * @param f * value to set */ public void setAllElements(double f) { Real.initArray(nelem, array, f); } /** * sum all elements. * * @return sigma(this(i)) */ public double sumAllElements() { double sum = 0.0; for (int i = 0; i < nelem; i++) { sum += array[i]; } return sum; } /** * sum of all absolute element values. * * @return sigma(abs(this(i))) */ public double absSumAllElements() { double sum = 0.0; for (int i = 0; i < nelem; i++) { sum += Math.abs(array[i]); } return sum; } /** * inner product. dotProduct(this) * * @return sigma(this(i)**2) */ public double innerProduct() { return this.dotProduct(this); } /** * dot product of two arrays. sigma(this(i)*(f(i)); * * @param f * array to multiply * @exception EuclidRuntimeException * f is different size from this * @return dot product */ public double dotProduct(RealArray f) throws EuclidRuntimeException { checkConformable(f); double sum = 0.0; for (int i = 0; i < nelem; i++) { sum += array[i] * f.array[i]; } return sum; } /** * Euclidean length of vector * * @return length */ public double euclideanLength() { return Math.sqrt(innerProduct()); } /** * root mean square sqrt(sigma(x(i)**2)/n) * * @exception EuclidRuntimeException * must have at least 1 point * @return rms */ public double rms() throws EuclidRuntimeException { if (nelem == 0) { throw new EuclidRuntimeException("must have at least one point"); } return euclideanLength() / Math.sqrt((double) nelem); } /** * get unit vector * * @exception EuclidRuntimeException * elements of this are all zero * @return the unit vector */ public RealArray unitVector() throws EuclidRuntimeException { double l = euclideanLength(); if (Real.isZero(l, Real.getEpsilon())) { throw new EuclidRuntimeException("zero length vector"); } double scale = 1.0 / l; RealArray f = new RealArray(nelem); f = this.multiplyBy(scale); return f; } /** * cumulative sum of array. create new array as elem[i] = sum(k = 0 to i) * f[k] does not modify 'this' * * @return each element is cumulative sum to that point */ public RealArray cumulativeSum() { RealArray temp = new RealArray(nelem); double sum = 0.0; for (int i = 0; i < nelem; i++) { sum += array[i]; temp.array[i] = sum; } return temp; } /** * apply filter. convolute array with another array. This is 1-D image * processing. If filter has <= 1 element, return this * unchanged. filter should have an odd number of elements. The * filter can be created with a IntArray constructor filter is moved along * stepwise *

* * @param filter * to apply normally smaller than this * @return filtered array */ public RealArray applyFilter(RealArray filter) { if (nelem == 0 || filter == null || filter.nelem <= 1) { return this; } int nfilter = filter.size(); int midfilter = (nfilter - 1) / 2; RealArray temp = new RealArray(nelem); double wt = 0; double sum = 0; for (int j = 0; j < midfilter; j++) { // get weight wt = 0.0; sum = 0.0; int l = 0; for (int k = midfilter - j; k < nfilter; k++) { wt += Math.abs(filter.array[k]); sum += filter.array[k] * this.array[l++]; } temp.array[j] = sum / wt; } wt = filter.absSumAllElements(); for (int j = midfilter; j < nelem - midfilter; j++) { sum = 0.0; int l = j - midfilter; for (int k = 0; k < nfilter; k++) { sum += filter.array[k] * this.array[l++]; } temp.array[j] = sum / wt; } for (int j = nelem - midfilter; j < nelem; j++) { // get weight wt = 0.0; sum = 0.0; int l = j - midfilter; for (int k = 0; k < midfilter + nelem - j; k++) { wt += Math.abs(filter.array[k]); sum += filter.array[k] * this.array[l++]; } temp.array[j] = sum / wt; } return temp; } /** * trims array to lie within limit. * * if flag == BELOW values below limit are set to limit. if flag == ABOVE * values above limit are set to limit. by repeated use of trim() values can * be constrained to lie within or outside a window does not modify this. * * @param flag * BELOW or ABOVE * @param limit * value to constrain * @return new array */ public RealArray trim(Trim flag, double limit) { RealArray temp = new RealArray(nelem); for (int i = 0; i < nelem; i++) { double v = array[i]; if ((flag == Trim.BELOW && v < limit) || (flag == Trim.ABOVE && v > limit)) v = limit; temp.array[i] = v; } return temp; } /** * index of largest element. * * @throws ArrayIndexOutOfBoundsException * array is zero length * @return index */ public int indexOfLargestElement() { if (nelem == 0) { throw new ArrayIndexOutOfBoundsException(); } int index = -1; double value = Double.NEGATIVE_INFINITY; for (int i = 0; i < nelem; i++) { if (array[i] > value) { value = array[i]; index = i; } } return index; } /** * index of smallest element. * * @throws ArrayIndexOutOfBoundsException * array is zero length * @return index */ public int indexOfSmallestElement() { if (nelem == 0) { throw new ArrayIndexOutOfBoundsException(); } int index = -1; double value = Double.POSITIVE_INFINITY; for (int i = 0; i < nelem; i++) { if (array[i] < value) { value = array[i]; index = i; } } return index; } /** * value of largest element. * * @throws ArrayIndexOutOfBoundsException * array is zero length * @return value */ public double largestElement() throws ArrayIndexOutOfBoundsException { return array[indexOfLargestElement()]; } /** * value of largest element. synonym for largestElement(); * * @throws ArrayIndexOutOfBoundsException * array is zero length * @return value */ public double getMax() throws ArrayIndexOutOfBoundsException { return array[indexOfLargestElement()]; } /** * value of smallest element. * * @throws ArrayIndexOutOfBoundsException * array is zero length * @return index */ public double smallestElement() throws ArrayIndexOutOfBoundsException { return array[indexOfSmallestElement()]; } /** * value of smallest element. synonym for smallestElement(); * * @throws ArrayIndexOutOfBoundsException * array is zero length * @return value */ public double getMin() throws ArrayIndexOutOfBoundsException { return array[indexOfSmallestElement()]; } /** * range of array. * * @throws ArrayIndexOutOfBoundsException * array is zero length * @return (minValue, maxValue) */ public RealRange getRange() throws ArrayIndexOutOfBoundsException { if (nelem == 0) { throw new ArrayIndexOutOfBoundsException(); } RealRange r = new RealRange(); for (int i = 0; i < nelem; i++) { r.add(array[i]); } return r; } /** * delete element and close up. modifies this. * * @param elem * to delete * @throws ArrayIndexOutOfBoundsException * elem out of range */ public void deleteElement(int elem) throws ArrayIndexOutOfBoundsException { if (elem < 0 || elem >= nelem) { throw new ArrayIndexOutOfBoundsException(); } nelem--; if (bufsize > nelem * 2) { bufsize /= 2; } double[] temp = new double[bufsize]; System.arraycopy(array, 0, temp, 0, elem); System.arraycopy(array, elem + 1, temp, elem, nelem - elem); array = temp; } /** * delete elements and close up. modifies this. * * @param low * lowest index inclusive * @param high * highest index inclusive * @throws ArrayIndexOutOfBoundsException * low or high out of range or low > high */ public void deleteElements(int low, int high) throws ArrayIndexOutOfBoundsException { if (low < 0 || low > high || high >= nelem) { throw new ArrayIndexOutOfBoundsException(); } int ndeleted = high - low + 1; double[] temp = new double[nelem - ndeleted]; System.arraycopy(array, 0, temp, 0, low); System.arraycopy(array, high + 1, temp, low, nelem - low - ndeleted); array = temp; nelem -= ndeleted; bufsize = nelem; double[] array = new double[nelem]; System.arraycopy(temp, 0, array, 0, nelem); } /** * insert element and expand. modifies this. * * @param elem * index of element to insert * @param f * value of element * @throws ArrayIndexOutOfBoundsException * elem out of range */ public void insertElementAt(int elem, double f) throws ArrayIndexOutOfBoundsException { if (elem < 0 || elem > nelem) { throw new ArrayIndexOutOfBoundsException(); } double[] array1 = new double[nelem + 1]; System.arraycopy(array, 0, array1, 0, elem); array1[elem] = f; System.arraycopy(array, elem, array1, elem + 1, nelem - elem); nelem++; array = array1; } /** * insert an array and expand. modifies this. * * @param elem * index of element to insert * @param f * value of element * @throws ArrayIndexOutOfBoundsException * elem out of range */ public void insertArray(int elem, RealArray f) throws ArrayIndexOutOfBoundsException { int n = f.size(); if (elem < 0 || elem >= nelem || n < 1) { throw new ArrayIndexOutOfBoundsException(); } nelem += n; double[] array1 = new double[nelem]; System.arraycopy(array, 0, array1, 0, elem); System.arraycopy(f.getArray(), 0, array1, elem, n); System.arraycopy(array, elem, array1, n + elem, nelem - elem - n); array = array1; } /** * append element. modifies this. * * @param f * element to append */ public void addElement(double f) { makeSpace(nelem + 1); array[nelem++] = f; } /** * append elements. modifies this. * * @param f * elements to append */ public void addArray(RealArray f) { LOG.trace("COPY0 "+array.length+"//"+nelem+"/"+f.nelem+"/"+array.length); makeSpace(nelem + f.nelem); LOG.trace("COPY1 "+array.length+"//"+nelem+"/"+f.nelem+"/"+array.length); System.arraycopy(f.array, 0, array, nelem, f.nelem); nelem += f.nelem; } /** * get reordered Array. reorder by index in IntSet new(i) = this(idx(i)) * does NOT modify array * * @param idx * array of indexes * @exception EuclidRuntimeException * an element of idx is outside range of this * @return array * */ public RealArray getReorderedArray(IntSet idx) throws EuclidRuntimeException { RealArray temp = new RealArray(nelem); for (int i = 0; i < nelem; i++) { int index = idx.elementAt(i); if (index > nelem) { throw new EuclidRuntimeException("index out of range " + index); } temp.array[i] = array[index]; } return temp; } /** normalize to given number of places * replaces each element by (nint(elem*10^ndec))/10^ndec * @param dd array * @param ndec number of places */ public static void round(double[] dd, int ndec) { for (int i = 0; i < dd.length; i++) { dd[i] = Real.normalize(dd[i], ndec); } } /** * get elements within a range. * * @param r * within which element values must lie * @return indexes of conforming elements */ public IntSet inRange(RealRange r) { int n = size(); IntSet temp = new IntSet(); for (int i = 0; i < n; i++) { if (r.isValid() && r.includes(array[i])) { temp.addElement(i); } } return temp; } /** * get elements outside a range. * * @param r * outside which element values must lie * @return indexes of conforming elements */ public IntSet outOfRange(RealRange r) { int n = size(); IntSet temp = new IntSet(); for (int i = 0; i < n; i++) { if (r.isValid() && !r.includes(array[i])) { temp.addElement(i); } } return temp; } /** * returns values as strings. * * @return string values of elements */ public String[] getStringValues() { String[] temp = new String[nelem]; for (int i = 0; i < nelem; i++) { temp[i] = Double.toString(array[i]); } return temp; } public String getStringArray() { StringBuffer s = new StringBuffer(); for (int i = 0; i < nelem; i++) { if (i > 0) { s.append(S_COMMA); } s.append(array[i]); } return s.toString(); } /** * gets values as string. * within brackets and including commas * @return element values separated with spaces */ public String toString() { // don't change this routine!!! StringBuffer s = new StringBuffer(); s.append(S_LBRAK); for (int i = 0; i < nelem; i++) { if (i > 0) { s.append(S_COMMA); } s.append(array[i]); } s.append(S_RBRAK); return s.toString(); } /** * some operations on float[] (static) */ /** * delete elements (lo - > hi inclusive) in a float[] and close up; if hi >= * float.length hi is reset to float.length-1. * * @param f * @param hi * @param low * @return new array */ public static double[] deleteElements(double[] f, int low, int hi) { if (hi >= f.length) hi = f.length - 1; if (low < 0) low = 0; int ndel = hi - low + 1; if (ndel <= 0) return f; double[] temp = new double[f.length - ndel]; System.arraycopy(f, 0, temp, 0, low); System.arraycopy(f, hi + 1, temp, low, f.length - hi - 1); return temp; } /** if RA is an autocorrelation array find first maximum after origin. * rather hairy so not generally recommended * runs through array till value below cutoff * then runs till value above cutoff * then aggregates values until drops below cutoff * @param cutoff * @return the maximum element (may be non-integral) */ public double findFirstLocalMaximumafter(int start, double cutoff) { double index = Double.NaN; boolean hitmin = false; boolean hitmax = false; double sigyx = 0.0; double sigy = 0.0; for (int i = start; i < nelem; i++) { double d = array[i]; if (!hitmin && !hitmax) { if (d < cutoff) { hitmin = true; } } else if (hitmin && !hitmax) { if (d > cutoff) { hitmax = true; hitmin = false; } } else if (hitmax) { if (d < cutoff) { hitmin = true; break; } sigyx += d*i; sigy += d; } } if (hitmin && hitmax) { index = sigyx / sigy; } return index; } /** find baseline. * experimental approach to finding baseline and adjusting to it. * Finds peak of distribution * read source code if you need to use this * @throws JumboException (many) * @return base offset */ public double getBaseLine() { double baseOffset; Univariate univariate = new Univariate(this); int binCount = 100; univariate.setBinCount(binCount); double step = this.getRange().getRange()/(double)binCount; double min = this.getMin(); int[] bins = univariate.getHistogramCounts(); int ibMax = -1; int binMax = -1; for (int i = 0; i < bins.length; i++) { if (bins[i] > binMax) { binMax = bins[i]; ibMax = i; } } int iMin = -1; for (int i = ibMax; i >= 0; i--) { if (bins[i] < binMax/2) { iMin = i; break; } } iMin = (iMin > 0) ? iMin : 0; int iMax = -1; for (int i = ibMax; i < binCount; i++) { if (bins[i] < binMax/2) { iMax = i; break; } } iMax = (iMax > 0) ? iMax : binCount-1; if (iMin == ibMax || ibMax == binCount-1) { baseOffset = 0.0; } else { double weight = 0.0; double sum = 0.0; for (int i = iMin; i <= iMax; i++) { double w = (double) bins[i]; weight += w; sum += w*i; } double deltaB = sum/weight; baseOffset = step*(deltaB)+min; } return baseOffset; } /** round to decimal places. * * @param places * @return this */ public RealArray format(int places) { for (int i = 0; i < nelem; i++) { array[i] = Util.format(array[i], places); } return this; } /** * copy a double[] into a new one */ /*-- private static double[] copy(double[] f) { double temp[] = new double[f.length]; System.arraycopy(f, 0, temp, 0, f.length); return temp; } --*/ /** * quick sort - modified from p96 - 97 (Hansen - C++ answer book) * * Scalar sort refers to sorting IntArray and RealArray (and similar * classes) where the objects themeselves are sorted. * * Index sort refers to sorting indexes (held as IntSet's) to the object and * getting the sorted object(s) with reorderBy(IntSet idx); * */ private void xfswap(double[] x, int a, int b) { double tmp = x[a]; x[a] = x[b]; x[b] = tmp; } // scalar sort routines (internal) private static final int CUTOFF = 16; private void inssort(int left, int right) { int k; for (int i = left + 1; i <= right; i++) { double v = array[i]; int j; for (j = i, k = j - 1; j > 0 && array[k] > v; j--, k--) { array[j] = array[k]; } array[j] = v; } } private int partition(int left, int right) { int mid = (left + right) / 2; if (array[left] > array[mid]) xfswap(array, left, mid); if (array[left] > array[right]) xfswap(array, left, right); if (array[mid] > array[right]) xfswap(array, mid, right); int j = right - 1; xfswap(array, mid, j); int i = left; double v = array[j]; do { do { i++; } while (array[i] < v); do { j--; } while (array[j] > v); xfswap(array, i, j); } while (i < j); xfswap(array, j, i); xfswap(array, i, right - 1); return i; } private void iqsort(int left, int right) { while (right - left > CUTOFF) { int i = partition(left, right); if (i - left > right - i) { iqsort(i + 1, right); right = i - 1; } else { iqsort(left, i - 1); left = i + 1; } } } /** * sorts array into ascending order. MODIFIES this */ public void sortAscending() { if (nelem <= 0) return; iqsort(0, nelem - 1); inssort(0, nelem - 1); } /** * sorts array into descending order. MODIFIES this */ public void sortDescending() { sortAscending(); reverse(); } /** * puts array into reverse order. MODIFIES this */ public void reverse() { int i = 0, j = nelem - 1; while (i < j) { xfswap(array, i, j); i++; j--; } } private static final int XXCUTOFF = 16; /** * get indexes of ascending sorted array. this array NOT MODIFIED * * @return indexes idx so that element(idx(0)) is lowest */ public IntSet indexSortAscending() { if (nelem <= 0) { return new IntSet(); } IntSet idx = new IntSet(nelem); IntArray iarray = new IntArray(idx.getElements()); xxiqsort(iarray, array, 0, nelem - 1); xxinssort(iarray, array, 0, nelem - 1); try { idx = new IntSet(iarray.getArray()); } catch (Exception e) { throw new EuclidRuntimeException(e.toString()); } return idx; } /** * get indexes of descending sorted array. this array NOT MODIFIED * * @return indexes idx so that element(idx(0)) is lowest */ public IntSet indexSortDescending() { IntSet idx; idx = indexSortAscending(); int[] temp = new IntArray(idx.getElements()).getReverseArray(); try { idx = new IntSet(temp); } catch (Exception e) { throw new EuclidRuntimeException(e.toString()); } return idx; } private void xxinssort(IntArray iarr, double[] pfl, int left, int right) { int j, k; for (int i = left + 1; i <= right; i++) { int v = iarr.elementAt(i); for (j = i, k = j - 1; j > 0 && pfl[iarr.elementAt(k)] > pfl[v]; j--, k--) { iarr.setElementAt(j, iarr.elementAt(k)); } iarr.setElementAt(j, v); } } private int xxpartition(IntArray iarr, double[] pfl, int left, int right) { int mid = (left + right) / 2; if (pfl[iarr.elementAt(left)] > pfl[iarr.elementAt(mid)]) xxfswap(iarr, left, mid); if (pfl[iarr.elementAt(left)] > pfl[iarr.elementAt(right)]) xxfswap(iarr, left, right); if (pfl[iarr.elementAt(mid)] > pfl[iarr.elementAt(right)]) xxfswap(iarr, mid, right); int j = right - 1; xxfswap(iarr, mid, j); int i = left; double v = pfl[iarr.elementAt(j)]; do { do { i++; } while (pfl[iarr.elementAt(i)] < v); do { j--; } while (pfl[iarr.elementAt(j)] > v); xxfswap(iarr, i, j); } while (i < j); xxfswap(iarr, j, i); xxfswap(iarr, i, right - 1); return i; } private void xxiqsort(IntArray iarr, double[] pfl, int left, int right) { while (right - left > XXCUTOFF) { int i = xxpartition(iarr, pfl, left, right); if (i - left > right - i) { xxiqsort(iarr, pfl, i + 1, right); right = i - 1; } else { xxiqsort(iarr, pfl, left, i - 1); left = i + 1; } } } private void xxfswap(IntArray iarr, int a, int b) { int t = iarr.elementAt(a); iarr.setElementAt(a, iarr.elementAt(b)); iarr.setElementAt(b, t); } /** * @param monotonicity * @return */ public Monotonicity getMonotonicity() { Monotonicity monotonicity = null; if (size() > 1) { double last = get(0); for (int i = 1; i < size(); i++) { double current = get(i); // equality with last Monotonicity m = null; if (current < last) { m = Monotonicity.DECREASING; } else if (current > last) { m = Monotonicity.INCREASING; } // compare with last monotonocity if (m != null) { if (monotonicity == null) { monotonicity = m; } else if (monotonicity != m) { monotonicity = null; break; } } last = current; } } return monotonicity; } /** * checks RealArray is not null and is of given size. * * @param array * to check * @param size * required size * @throws EuclidRuntimeException * if null or wrong size */ public static void check(RealArray array, int size) throws EuclidRuntimeException { if (array == null) { throw new EuclidRuntimeException("null array"); } else if (array.size() != size) { throw new EuclidRuntimeException("array size required (" + size + ") found " + array.size()); } } /** * parse string as realArray. * * @param s * @param delimiterRegex * @return true if can be parsed. */ public static boolean isFloatArray(String s, String delimiterRegex) { boolean couldBeFloatArray = true; String[] ss = s.split(delimiterRegex); try { new RealArray(ss); } catch (Exception e) { couldBeFloatArray = false; } return couldBeFloatArray; } } wwmm-euclid-87e8f785a814/src/main/java/org/xmlcml/euclid/RealInterval.java0000644000000000000000000000566411607017524024374 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid; /** an interval on the real line. * may be negative * it is allowed for the interval to be of zero length * @author pm286 * */ public class RealInterval implements EuclidConstants { double x1; double x2; /** constructor. * defaults to 0,1 * */ public RealInterval() { this(0., 1.0); } /** construct from Real2. * * @param x1 * @param x2 */ public RealInterval(double x1, double x2) { this.x1 = x1; this.x2 = x2; } /** copy constructor. * * @param interval */ public RealInterval(RealInterval interval) { this.x1 = interval.x1; this.x2 = interval.x2; } /** get length. * could be negative * @return length */ public double getLength() { return x2 - x1; } /** constructor from range. * interval direction is therefore always positive * @param range */ public RealInterval(RealRange range) { this(range.getMin(), range.getMax()); } /** get scale to other interval. * scale is interval.length / this.length * @param interval * @return scale may be NaN */ public double scaleTo(RealInterval interval) { double scale = Double.NaN; try { scale = interval.getLength() / this.getLength(); } catch (Throwable t) { // } return scale; } /** offset to translate xthis to xthat after scaling. * X = (x - xthis)*scale + Xthat * X = offset + scale*xthis * so offset = xthat - scale*xthis * @param scale * @param xthis * @param xthat * @return offset */ static double offsetTo(double scale, double xthis, double xthat) { return (xthat - xthis * scale); } /** offset to map one interval onto another. * precise mapping * @param interval * @return offset applied after scaling */ public double offsetTo(RealInterval interval) { return this.offsetTo(interval, this.scaleTo(interval)); } /** offset to map one interval onto another. * maps x1 of each onto eachg other * @param interval to map to * @param scale * @return offset applied after scaling */ public double offsetTo(RealInterval interval, double scale) { return interval.x1 - scale * this.x1; } /** gets midpoint. * * @return midpoint */ public double midPoint() { return (x1 + x2) / 2.0; } } wwmm-euclid-87e8f785a814/src/main/java/org/xmlcml/euclid/RealMatrix.java0000644000000000000000000014611511607017524024051 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid; import java.io.IOException; import java.io.Writer; import java.text.DecimalFormat; import org.apache.log4j.Logger; /** * rectangular real number matrix class RealMatrix represents a rectangular * m-x-n matrix. The basic matrix algebra for non-square matrices is represented * here and this class is also a base for square matrices. *

* Read the signature of each member function carefully as some MODIFY the * object and some CREATE A NEW ONE. Among the reasons for this is that * subclassing (e.g to RealSquareMatrix) is easier with one of these forms in * certain cases. Note that if you modify an object, then all references to it * will refer to the changed object * * @author (C) P. Murray-Rust, 1996 */ public class RealMatrix implements EuclidConstants { final static Logger logger = Logger.getLogger(RealMatrix.class.getName()); /** * number of rows */ protected int rows = 0; /** * number of columns */ protected int cols = 0; /** * the matrix */ protected double[][] flmat = new double[0][0]; DecimalFormat format = null; /** * construct default matrix. cols = rows = 0 */ public RealMatrix() { } /** * Create matrix with given rows and columns. A rows*cols matrix values set * to 0 (rows or cols < 0 defaults to 0) * * @param r * number of rows * @param c * number of columns */ public RealMatrix(int r, int c) { if (r < 0) r = 0; if (c < 0) c = 0; rows = r; cols = c; flmat = new double[r][c]; } /** * Create from 1-D array. Formed by feeding in an existing 1-D array to a * rowsXcols matrix THE COLUMN IS THE FASTEST MOVING INDEX, that is the * matrix is filled as flmat(0,0), flmat(0,1) ... C-LIKE. COPIES the array * * @param rows * @param cols * @param array * @exception EuclidRuntimeException * size of array is not rows*cols */ public RealMatrix(int rows, int cols, double[] array) throws EuclidRuntimeException { this(rows, cols); check(rows, cols, array); this.rows = rows; this.cols = cols; int count = 0; for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { flmat[i][j] = array[count++]; } } } /** * creates matrix with initialised values. * * @param r * rows * @param c * columns * @param f * value to initialize with */ public RealMatrix(int r, int c, double f) { this(r, c); for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { flmat[i][j] = f; } } } /** * create from submatrix of another matrix. fails if lowrow > hirow, lowrow < * 0, etc * * COPIES the parts of m * * @param m * the matrix to slice * @param lowcol * lowest column index * @param hicol * highest column index * @param lowrow * lowest row index * @param hirow * highest row index * @exception EuclidRuntimeException * impossible value of hirow, hicol, lowrow, lowcol */ public RealMatrix(RealMatrix m, int lowrow, int hirow, int lowcol, int hicol) throws EuclidRuntimeException { this(hirow - lowrow + 1, hicol - lowcol + 1); if (hirow >= m.getRows() || lowrow < 0) { throw new EuclidRuntimeException("bad row index: " + lowrow + S_SLASH + hirow + " outside 0/" + m.getRows()); } if (hicol >= m.getCols() || lowcol < 0) { throw new EuclidRuntimeException("bad col index: " + lowcol + S_SLASH + hicol + " outside 0/" + m.getCols()); } for (int i = 0, mrow = lowrow; i < rows; i++, mrow++) { for (int j = 0, mcol = lowcol; j < cols; j++, mcol++) { flmat[i][j] = m.flmat[mrow][mcol]; } } } /** * copy constructor. copies matrix including values * * @param m * matrix to copy */ public RealMatrix(RealMatrix m) { this(m.rows, m.cols); for (int i = 0; i < rows; i++) { System.arraycopy(m.flmat[i], 0, flmat[i], 0, cols); } } /** * shallow copy constructor. copies references (uses same internal array) * * @param m * matrix to copy */ public void shallowCopy(RealMatrix m) { this.rows = m.rows; this.cols = m.cols; this.flmat = m.flmat; } /** * construct from a IntMatrix. * * @param m * matrix to copy (this(i,j) = m(i,j)) */ public RealMatrix(IntMatrix m) { this(m.rows, m.cols); for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { flmat[i][j] = new Double(m.flmat[i][j]).doubleValue(); } } } /** * constructs an IntMatrix. intm(i,j) = (int) this(i,j), i.e.gets nearest * integers as matrix. * * @return the nearest IntMatrix */ public IntMatrix getIntMatrix() { IntMatrix im = new IntMatrix(rows, cols); int[][] matrix = im.getMatrix(); for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { matrix[i][j] = (int) flmat[i][j]; } } return im; } /** * create from a java matrix. must be rectangular copies matrix values (i.e. * m can be discarded) * * @param m * natrix to copy from * @exception EuclidRuntimeException * m has rows of different lengths */ public RealMatrix(double[][] m) throws EuclidRuntimeException { this(m.length, m[0].length); for (int i = 0; i < rows; i++) { if (m[i].length != cols) { throw new EuclidRuntimeException("non-rectangular matrix cols: " + cols + " row: " + i + " length: " + m[i].length); } for (int j = 0; j < cols; j++) { flmat[i][j] = m[i][j]; } } } /** * set output format. * * @param f * the format */ public void setFormat(DecimalFormat f) { format = f; } /** * get output format. * * @return the format */ public DecimalFormat getFormat() { return format; } /** * get number of rows. * * @return number of rows */ public int getRows() { return rows; } /** * get number of columns. * * @return number of columns */ public int getCols() { return cols; } /** * get matrix as java matrix. shallow copy - any alterations to java matrix * will alter this and vice versa. * * @return matrix as java matrix */ public double[][] getMatrix() { return flmat; } /** * get matrix as array. * * @return matrix as 1-D array in C order: (m(0,0), m(0,1) ...) */ public double[] getMatrixAsArray() { double[] temp = new double[rows * cols]; int count = 0; for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { temp[count++] = flmat[i][j]; } } return temp; } /** * tests matrices for equality. * * uses Real.isEqual(double) for tests * * @param m * @return true if all corresponding elements are equal */ public boolean isEqualTo(RealMatrix m) { boolean ok = true; try { checkConformable(m); for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { if (!Real.isEqual(flmat[i][j], m.flmat[i][j])) { ok = false; break; } } } } catch (EuclidRuntimeException e) { ok = false; } return ok; } // check that plus, subtract is possible private void checkConformable(RealMatrix m) throws EuclidRuntimeException { if (rows != m.rows || cols != m.cols) { throw new EuclidRuntimeException("unequal matrices"); } } // check that multiply is possible private void checkConformable2(RealMatrix m) throws EuclidRuntimeException { if (m.rows != this.cols) { throw new EuclidRuntimeException("unequal matrices (" + this.cols + ", " + m.rows + S_RBRAK); } } private void check(int rows, int cols, double[] array) throws EuclidRuntimeException { if (array == null) { throw new EuclidRuntimeException("RealMatrix(null)"); } if (array.length != rows * cols) { throw new EuclidRuntimeException("rows * cols (" + rows + S_STAR + cols + ") != array (" + array.length + S_RBRAK); } } /** * matrix addition. adds conformable matrices giving NEW matrix. this is * unaltered * * @param m2 * @exception EuclidRuntimeException * m and this are different sizes * @return new matrix */ public RealMatrix plus(RealMatrix m2) throws EuclidRuntimeException { RealMatrix m = new RealMatrix(m2.rows, m2.cols); checkConformable(m2); for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { m.flmat[i][j] = flmat[i][j] + m2.flmat[i][j]; } } return m; } /** * matrix subtraction. subtracts conformable matrices giving NEW matrix this * is unaltered * * @param m2 * @exception EuclidRuntimeException * m and this are different sizes * @return new matrix */ public RealMatrix subtract(RealMatrix m2) throws EuclidRuntimeException { RealMatrix m = new RealMatrix(m2.rows, m2.cols); checkConformable(m2); for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { m.flmat[i][j] = flmat[i][j] - m2.flmat[i][j]; } } return m; } /** * unary minus. negate all elements of matrix; MODIFIES matrix */ public void negative() { for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { flmat[i][j] = -flmat[i][j]; } } } /** * matrix multiplication. * * multiplies conformable matrices to give NEW matrix. this is unaltered * result = 'this' * m; (order matters) * * @param m * @exception EuclidRuntimeException * m and this are different sizes * @return new matrix */ public RealMatrix multiply(RealMatrix m) throws EuclidRuntimeException { checkConformable2(m); RealMatrix m1 = new RealMatrix(rows, m.cols); for (int i = 0; i < rows; i++) { for (int j = 0; j < m.cols; j++) { m1.flmat[i][j] = 0.0; for (int k = 0; k < cols; k++) { m1.flmat[i][j] += flmat[i][k] * m.flmat[k][j]; } } } return m1; } /** * matrix multiplication by a scalar. creates this(i,j) = f*this(i,j) * MODIFIES matrix * * @param f * scalar */ public void multiplyBy(double f) { for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { flmat[i][j] *= f; } } } /** * matrix multiplication. multiplies conformable matrices and stores result * in this matrix. this = 'this' * m; * * @param m * matrix to multiply by * @exception EuclidRuntimeException * m and this are different sizes */ public void multiplyEquals(RealMatrix m) throws EuclidRuntimeException { RealMatrix mm = this.multiply(m); this.rows = mm.rows; this.cols = mm.cols; this.flmat = new double[this.rows][]; for (int i = 0; i < rows; i++) { this.flmat[i] = new double[this.cols]; System.arraycopy(mm.flmat[i], 0, this.flmat[i], 0, this.cols); } } /** * subtract value from each row. this[i,j] = this[i,j] - d[j] modifies this * @param d * array of doubles to subtract * @throws EuclidRuntimeException */ /*-- public void translateByRow(double[] d) { checkColumns(d); for (int i = rows - 1; i >= 0; -- i) { for (int j = cols - 1; j >= 0; -- j) { flmat [i] [j] -= d [j]; } } } --*/ void checkColumns(double[] d) throws EuclidRuntimeException { if (d.length != cols) { throw new EuclidRuntimeException("array size " + d.length + "!= cols length " + cols); } } private void checkRows(double[] d) throws EuclidRuntimeException { if (d.length != rows) { throw new EuclidRuntimeException("array size " + d.length + "!= rows length " + rows); } } /** * subtract value from each colum. this[i,j] = this[i,j] - d[i] modifies * this * * @param d * array of doubles to subtract * @throws EuclidRuntimeException */ public void translateByColumn(double[] d) throws EuclidRuntimeException { checkRows(d); for (int i = cols - 1; i >= 0; --i) { for (int j = rows - 1; j >= 0; --j) { flmat[j][i] -= d[j]; } } } /** * matrix multiplication of a COLUMN vector. creates new vector * * @param f * vector to multiply * @exception EuclidRuntimeException * f.size() differs from cols * @return transformed array */ public RealArray multiply(RealArray f) throws EuclidRuntimeException { if (f.size() != this.cols) { throw new EuclidRuntimeException("unequal matrices"); } double[] temp = new double[rows]; double[] farray = f.getArray(); for (int i = 0; i < rows; i++) { temp[i] = 0.0; for (int j = 0; j < cols; j++) { temp[i] += this.flmat[i][j] * farray[j]; } } RealArray ff = new RealArray(temp); return ff; } /** * divide each column of a matrix by a vector of scalars (that is mat[i][j] = * mat[i][j] / vect[i] - MODIFIES matrix * * @param f * array to divide by * @exception EuclidRuntimeException * f.size() and rows differ */ public void columnwiseDivide(RealArray f) throws EuclidRuntimeException { if (this.cols != f.size()) { throw new EuclidRuntimeException("unequal matrices " + this.cols + S_SLASH + f.size()); } for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { this.flmat[i][j] /= f.elementAt(j); } } } /** * extracts a given element. * * @param row * @param col * @throws EuclidRuntimeException * bad value of row or column * @return the element at row,col */ public double elementAt(int row, int col) throws EuclidRuntimeException { checkRow(row); checkColumn(col); return flmat[row][col]; } /** * checks a row is in range. * * @throws EuclidRuntimeException * if it isn't */ private void checkRow(int row) throws EuclidRuntimeException { if (row < 0 || row >= rows) throw new EuclidRuntimeException("Bad value of row: " + row + S_SLASH + rows); } /** * checks a col is in range. * * @throws EuclidRuntimeException * if it isn't */ private void checkColumn(int col) throws EuclidRuntimeException { if (col < 0 || col >= cols) throw new EuclidRuntimeException("Bad value of col: " + col + S_SLASH + cols); } /** * extracts a given element. * * @param rowcol * represents row,col * @return the element at row,col * @throws EuclidRuntimeException */ public double elementAt(Int2 rowcol) throws EuclidRuntimeException { return elementAt(rowcol.elementAt(0), rowcol.elementAt(1)); } /** * sets a given element MODIFIES matrix * * @param row * @param col * @param f * @throws EuclidRuntimeException */ public void setElementAt(int row, int col, double f) throws EuclidRuntimeException { checkRow(row); checkColumn(col); flmat[row][col] = f; } /** * get value of largest element. * * @return value of largest element */ public double largestElement() { Int2 temp = indexOfLargestElement(); if (temp == null) { throw new EuclidRuntimeException("bug; null index for largest element"); } return this.elementAt(temp); } /** * get index of largest element. * * @return (row, col) */ public Int2 indexOfLargestElement() { Int2 int2 = null; if (cols != 0 && rows != 0) { double f = Double.NEGATIVE_INFINITY; int im = 0; int jm = 0; for (int irow = 0; irow < rows; irow++) { for (int jcol = 0; jcol < cols; jcol++) { if (f < flmat[irow][jcol]) { f = flmat[irow][jcol]; im = irow; jm = jcol; } } } int2 = new Int2(im, jm); } return int2; } /** * get value of largest element in a column * * @param jcol * @return the value * @throws EuclidRuntimeException */ public double largestElementInColumn(int jcol) throws EuclidRuntimeException { return this.elementAt(indexOfLargestElementInColumn(jcol), jcol); } /** * get index of largest element in column. * * @param jcol * index * @return index (-1 if empty matrix) * @throws EuclidRuntimeException * bad value of jcol */ public int indexOfLargestElementInColumn(int jcol) throws EuclidRuntimeException { checkColumn(jcol); int imax = -1; double max = Double.NEGATIVE_INFINITY; for (int irow = 0; irow < rows; irow++) { if (max < flmat[irow][jcol]) { max = flmat[irow][jcol]; imax = irow; } } return imax; } /** * get index of largest element in row. * * @param irow * index * @return index (-1 if empty matrix) * @throws EuclidRuntimeException * bad value of irow */ public int indexOfLargestElementInRow(int irow) throws EuclidRuntimeException { checkRow(irow); int imax = -1; double max = Double.NEGATIVE_INFINITY; for (int jcol = 0; jcol < cols; jcol++) { if (max < flmat[irow][jcol]) { max = flmat[irow][jcol]; imax = jcol; } } return imax; } /** * get index of smallest element in column. * * @param jcol * index * @return index (-1 if empty matrix) * @throws EuclidRuntimeException * bad value of jcol */ public int indexOfSmallestElementInColumn(int jcol) throws EuclidRuntimeException { checkColumn(jcol); int imin = -1; double min = Double.POSITIVE_INFINITY; for (int irow = 0; irow < rows; irow++) { if (min > flmat[irow][jcol]) { min = flmat[irow][jcol]; imin = irow; } } return imin; } protected boolean checkNonEmptyMatrix() { return (cols > 0 && rows > 0); } /** * get value of largest element in a row. * * @param irow * @return value (0 if no columns) * @throws EuclidRuntimeException */ public double largestElementInRow(int irow) throws EuclidRuntimeException { int idx = indexOfLargestElementInRow(irow); if (idx < 0) { throw new EuclidRuntimeException("empty matrix"); } return this.elementAt(irow, idx); } /** * get index of smallest element in row. * * @param irow * index * @return index (-1 if empty matrix) * @throws EuclidRuntimeException * bad value of irow */ public int indexOfSmallestElementInRow(int irow) throws EuclidRuntimeException { checkRow(irow); int imin = -1; double min = Double.POSITIVE_INFINITY; for (int jcol = 0; jcol < cols; jcol++) { if (min > flmat[irow][jcol]) { min = flmat[irow][jcol]; imin = jcol; } } return imin; } /** * get value of smallest element. * * @return value * @throws EuclidRuntimeException */ public double smallestElement() throws EuclidRuntimeException { Int2 temp = indexOfSmallestElement(); return this.elementAt(temp); } /** * get index of smallest element. * * @return (row,col) or null for empty matrix */ public Int2 indexOfSmallestElement() { double f = Double.POSITIVE_INFINITY; int im = -1; int jm = -1; for (int irow = 0; irow < rows; irow++) { for (int jcol = 0; jcol < cols; jcol++) { if (f > flmat[irow][jcol]) { f = flmat[irow][jcol]; im = irow; jm = jcol; } } } return (im >= 0) ? new Int2(im, jm) : null; } /** * get smallest element in a column. * * @param jcol * @return smallest value * @exception EuclidRuntimeException * bad value of jcol */ public double smallestElementInColumn(int jcol) throws EuclidRuntimeException { int idx = indexOfSmallestElementInColumn(jcol); if (idx < 0) { throw new EuclidRuntimeException("empty matrix"); } return this.elementAt(idx, jcol); } /** * get smallest element in a row. * * @param irow * @return smallest value * @exception EuclidRuntimeException * bad value of irow */ public double smallestElementInRow(int irow) throws EuclidRuntimeException { int idx = indexOfSmallestElementInRow(irow); if (idx < 0) { throw new EuclidRuntimeException("empty matrix"); } return this.elementAt(irow, idx); } /** * get index of smallest element in row. * * @param irow * @return index of smallest value */ /*-- public int indexOfSmallestElementInRow(int irow) { double f = Double.POSITIVE_INFINITY; int imax = 0; for(int jcol = 0; jcol < cols; jcol++) { if(f > flmat[irow][jcol]) { f = flmat[irow][jcol]; imax = jcol; } } return imax; } -*/ /** * is matrix Orthogonal row-wise. * * that is row(i) * row(j) = 0 if i not equals j. * * @return true if orthogonal */ public boolean isOrthogonal() { for (int i = 1; i < rows; i++) { RealArray rowi = extractRowData(i); double dot = 0.0; for (int j = i + 1; j < rows; j++) { RealArray rowj = extractRowData(j); dot = rowi.dotProduct(rowj); if (!Real.isZero(dot, Real.getEpsilon())) return false; } } return true; } /** * get Euclidean length of row. * * @param i * the row * @return length of row * @throws EuclidRuntimeException * bad row number */ public double euclideanRowLength(int i) throws EuclidRuntimeException { checkRow(i); RealArray f = extractRowData(i); return f.euclideanLength(); } /** * get array of Euclidean row lengths. * * @return the array (of dimension cols) */ public RealArray euclideanRowLengths() { RealArray fa = new RealArray(rows); for (int i = 0; i < rows; i++) { fa.setElementAt(i, this.euclideanRowLength(i)); } return fa; } /** * get Euclidean length of column. * * @param jcol * the column * @return the length * @throws EuclidRuntimeException */ public double euclideanColumnLength(int jcol) throws EuclidRuntimeException { RealArray f = extractColumnData(jcol); return f.euclideanLength(); } /** * get array of Euclidean column lengths * * @return the array (of dimension rows) */ public RealArray euclideanColumnLengths() { RealArray fa = new RealArray(cols); for (int i = 0; i < cols; i++) { try { fa.setElementAt(i, this.euclideanColumnLength(i)); } catch (Exception e) { e.printStackTrace(); throw new EuclidRuntimeException("BUG " + e); } } return fa; } /** * get column data from matrix. * * @param col * the column * @return the column data (or length rows) * @throws EuclidRuntimeException * bad index */ public RealArray extractColumnData(int col) throws EuclidRuntimeException { checkColumn(col); RealArray fa = new RealArray(rows); for (int i = 0; i < rows; i++) { fa.setElementAt(i, this.flmat[i][col]); } return fa; } /** * get row data from matrix. * * @param row * the column * @return the row data (of length cols) * @throws EuclidRuntimeException * bad index */ public RealArray extractRowData(int row) throws EuclidRuntimeException { checkRow(row); return new RealArray(flmat[row]); } /** * clear matrix. */ public void clearMatrix() { for (int irow = 0; irow < rows; irow++) { for (int jcol = 0; jcol < cols; jcol++) { flmat[irow][jcol] = 0.0; } } } /** * initialise matrix to given double. * * @param f */ public void setAllElements(double f) { for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { flmat[i][j] = f; } } } /** * normalise matrix rows to length of unity */ public void normaliseByRows() { RealArray rowlen = new RealArray(cols); rowlen = euclideanRowLengths(); for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { this.flmat[i][j] /= rowlen.elementAt(i); } } } /** * normalise matrix columns to length of unity */ public void normaliseByColumns() { RealArray ra = euclideanColumnLengths(); this.columnwiseDivide(ra); } /** * transpose matrix - creates new Matrix * * @return transpoe */ public RealMatrix getTranspose() { double[][] m = new double[cols][rows]; for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { m[j][i] = this.flmat[i][j]; } } RealMatrix mm = new RealMatrix(m); return mm; } /** * is the matrix square * * @return is square */ public boolean isSquare() { return (cols == rows && cols > 0); } /** are all elements of matrix zero? * * @param eps tolerance * @return true if all elements zero */ public boolean isZero(double eps) { boolean zero = true; for (int irow = 0; irow < rows; irow++) { for (int icol = 0; icol < cols; icol++) { if (!Real.isZero(flmat[irow][icol], eps)) { zero = false; break; } } } return zero; } /** * delete column from matrix and close up. no-op if impermissible value of * col * * @param col * the column */ public void deleteColumn(int col) { if (col >= 0 && col < cols) { double[][] temp = new double[rows][cols - 1]; for (int i = 0; i < rows; i++) { for (int j = 0; j < col; j++) { temp[i][j] = flmat[i][j]; } for (int j = col + 1; j < cols; j++) { temp[i][j - 1] = flmat[i][j]; } } cols--; flmat = temp; } } /** * delete 2 or more adjacent columns (inclusive) from matrix and close up. * no action if impermissible value of low and high * * @param low * start column * @param high * end column */ public void deleteColumns(int low, int high) { high = (high > cols - 1) ? cols - 1 : high; low = (low < 0) ? 0 : low; for (int i = 0; i < rows; i++) { this.flmat[i] = RealArray.deleteElements(this.flmat[i], low, high); } this.cols -= (high - low + 1); } /** * delete row from matrix and close up. * * @param row */ public void deleteRow(int row) { deleteRows(row, row); } /** * delete 2 or more adjacent rows (inclusive) from matrix and close up. if * (high > rows-1 high -> rows-1; or low < 0, low -> 0 * * @param low * start row * @param high * end row */ public void deleteRows(int low, int high) { high = (high >= rows) ? rows - 1 : high; low = (low < 0) ? 0 : low; if (low > high) return; int newrows = rows + high - low - 1; double temp[][] = new double[newrows][cols]; int oldrow = 0; int newrow = 0; while (oldrow < rows) { if (oldrow < low || oldrow > high) { temp[newrow++] = flmat[oldrow]; } oldrow++; } this.rows = newrows; flmat = temp; } /** * replace data in a single column. * * @param column * @param f * data must be of length rows * @throws EuclidRuntimeException */ public void replaceColumnData(int column, RealArray f) throws EuclidRuntimeException { checkRows(f); checkColumn(column); double[] temp = f.getArray(); for (int i = 0; i < rows; i++) { flmat[i][column] = temp[i]; } } private void checkRows(RealArray f) throws EuclidRuntimeException { if (f == null || f.size() != rows) { throw new EuclidRuntimeException("incompatible value of array size: " + f.size() + S_SLASH + rows); } } private void checkColumns(RealArray f) throws EuclidRuntimeException { if (f == null || f.size() != cols) { throw new EuclidRuntimeException("incompatible value of array size: " + f.size() + S_SLASH + cols); } } private void checkColumns(IntSet is) throws EuclidRuntimeException { if (is == null || is.size() != cols) { throw new EuclidRuntimeException("incompatible value of IntSet size: " + is.size() + S_SLASH + cols); } } private void checkColumns(RealMatrix m) throws EuclidRuntimeException { if (m == null || m.getCols() != cols) { throw new EuclidRuntimeException("incompatible value of matrix size: " + m.getCols() + S_SLASH + cols); } } private void checkRows(RealMatrix m) throws EuclidRuntimeException { if (m == null || m.getRows() != rows) { throw new EuclidRuntimeException("incompatible value of matrix size: " + m.getRows() + S_SLASH + rows); } } /** * replace data in a single column. * * @param starting_col * @param f * data must be of length rows * @throws EuclidRuntimeException */ public void replaceColumnData(int starting_col, double[] f) throws EuclidRuntimeException { replaceColumnData(starting_col, new RealArray(rows, f)); } /** * replace data in a block of columns. * * @param start_column * (gets overwritten) * @param m * must have same row count and fit into gap * @throws EuclidRuntimeException */ public void replaceColumnData(int start_column, RealMatrix m) throws EuclidRuntimeException { // must trap copying a matrix into itself! if (this == m) { return; } cols = this.getCols(); int mcols = m.getCols(); checkRows(m); if (start_column < 0) { throw new EuclidRuntimeException("cannot start at negative column: " + start_column); } int end_column = start_column + mcols; if (end_column > cols) { throw new EuclidRuntimeException("too many columns to copy: " + start_column + "|" + mcols + S_SLASH + cols); } copyColumns(m.flmat, start_column, mcols); } private void copyColumns(double[][] mat, int start_column, int nToCopy) { for (int j = 0; j < nToCopy; j++) { for (int i = 0; i < rows; i++) { this.flmat[i][start_column + j] = mat[i][j]; } } } /** * insert a hole into the matrix and expand. result is blank space in matrix * * @param after_col * @param delta_cols */ public void makeSpaceForNewColumns(int after_col, int delta_cols) { if (after_col >= 0 && after_col <= cols && delta_cols > 0) { int newcols = delta_cols + cols; RealMatrix temp = new RealMatrix(rows, newcols); for (int irow = 0; irow < rows; irow++) { for (int jcol = 0; jcol < after_col; jcol++) { temp.flmat[irow][jcol] = this.flmat[irow][jcol]; } for (int jcol = after_col; jcol < cols; jcol++) { temp.flmat[irow][jcol + delta_cols] = this.flmat[irow][jcol]; } } shallowCopy(temp); } } /** * add data as column or column block into matrix and expand. column is * inserted after given column * * @param after_col * -1 to cols-1 * @param f * @throws EuclidRuntimeException */ public void insertColumnData(int after_col, RealArray f) throws EuclidRuntimeException { checkRows(f); if (cols == 0) { rows = f.size(); flmat = new double[rows][1]; double[] arr = f.getArray(); cols = 1; for (int i = 0; i < rows; i++) { flmat[i][0] = arr[i]; } } else { if (f.size() == rows) { makeSpaceForNewColumns(after_col + 1, 1); replaceColumnData(after_col + 1, f); } } } /** * add data as column or column block into matrix and expand. * * @param afterCol * -1 to cols-1 * @param m * @throws EuclidRuntimeException */ public void insertColumnData(int afterCol, RealMatrix m) throws EuclidRuntimeException { // must trap copying a matrix into itself! if (this == m) { return; } checkRows(m); int mcols = m.getCols(); cols = this.getCols(); if (afterCol < -1 || afterCol >= cols) { throw new EuclidRuntimeException("afterCol must be >= -1 or < cols: " + afterCol); } makeSpaceForNewColumns(afterCol + 1, mcols); replaceColumnData(afterCol + 1, m); } /** * make space for new rows in matrix and expand. * * @param after_row * -1 to rows-1 * @param delta_rows * size of space */ public void insertRows(int after_row, int delta_rows) { if (after_row >= 0 && after_row <= cols && delta_rows > 0) { int newrows = delta_rows + rows; RealMatrix temp = new RealMatrix(newrows, cols); for (int jcol = 0; jcol < cols; jcol++) { for (int irow = 0; irow < after_row; irow++) { temp.flmat[irow][jcol] = this.flmat[irow][jcol]; } for (int irow = after_row; irow < rows; irow++) { temp.flmat[irow + delta_rows][jcol] = this.flmat[irow][jcol]; } } shallowCopy(temp); } } /** * overwrite existing row of data. * * @param row * to replace * @param f * row to use * @exception EuclidRuntimeException * f.size() and cols differ */ public void replaceRowData(int row, RealArray f) throws EuclidRuntimeException{ checkColumns(f); int mcols = f.size(); System.arraycopy(f.getArray(), 0, flmat[row], 0, mcols); } /** * overwrite existing row of data. * * @param row * to replace * @param f * row to use * @exception EuclidRuntimeException * f.length and cols differ */ public void replaceRowData(int row, double[] f) throws EuclidRuntimeException { RealArray temp = new RealArray(cols, f); replaceRowData(row, temp); } /** * overwrite existing block of rows; if too big, copying is truncated * * @param afterRow * from -1 to rows-1 * @param m * data to replace with * @exception EuclidRuntimeException * m.rows and this.rows differ */ public void replaceRowData(int afterRow, RealMatrix m) throws EuclidRuntimeException { // must trap copying a matrix into itself! if (this == m) return; checkColumns(m); if (afterRow < -1) { throw new EuclidRuntimeException("afterRow must be >= -1 :" + afterRow); } if (!(afterRow <= (rows - m.rows))) { throw new EuclidRuntimeException("afterRow (" + afterRow + ")must be <= rows (" + rows + ") - m.rows (" + m.rows + S_RBRAK); } copyRowData(m.flmat, afterRow + 1, m.rows); } /** * insert 2 or more adjacent rows of data into matrix and expand * * @param afterRow * from -1 to rows-1 * @param m * data to insert * @exception EuclidRuntimeException * m.cols and this.colsdiffer */ public void insertRowData(int afterRow, RealMatrix m) throws EuclidRuntimeException { // must trap copying a matrix into itself! if (this == m) { return; } rows = this.getRows(); int mrows = m.getRows(); checkColumns(m); if (afterRow < -1) { throw new EuclidRuntimeException("must insert after -1 or higher"); } if (afterRow >= rows) { throw new EuclidRuntimeException("must insert after nrows-1 or lower"); } insertRows(afterRow + 1, mrows); copyRowData(m.flmat, afterRow + 1, mrows); } private void copyRowData(double[][] mat, int afterRow, int nrows) { for (int i = 0; i < nrows; i++) { for (int j = 0; j < cols; j++) { this.flmat[afterRow + i][j] = mat[i][j]; } } } /** * insert row of data into matrix and expand. * * @param after_row * from -1 to rows-1 * @param f * data to insert * @exception EuclidRuntimeException * f.size() and this.cols differ */ public void insertRowData(int after_row, RealArray f) throws EuclidRuntimeException { checkColumns(f); int mcols = f.size(); if (after_row >= -1 && after_row <= rows && mcols == cols) { insertRows(after_row + 1, 1); replaceRowData(after_row + 1, f); } else { throw new EuclidRuntimeException("Cannot add array after row" + after_row + S_SLASH + rows + "==" + mcols + S_SLASH + cols); } } /** * append data to matrix columnwise. * * @param f * data to append * @exception EuclidRuntimeException * f.size() and this.rows differ */ public void appendColumnData(RealArray f) throws EuclidRuntimeException { if (cols == 0) { rows = f.size(); } insertColumnData(cols - 1, f); } /** * append data to matrix columnwise. * * @param m * data to append * @exception EuclidRuntimeException * m.rows and this.rows differ */ public void appendColumnData(RealMatrix m) throws EuclidRuntimeException { if (cols == 0) { rows = m.getRows(); } insertColumnData(cols - 1, m); } /** * append data to matrix rowwise. * * @param f * data to append * @exception EuclidRuntimeException * m.cols and this.cols differ */ public void appendRowData(RealArray f) throws EuclidRuntimeException { if (rows == 0) { cols = f.size(); } insertRowData(rows - 1, f); } /** * append data to matrix rowwise. * * @param m * data to append * @exception EuclidRuntimeException * m.cols and this.cols differ */ public void appendRowData(RealMatrix m) throws EuclidRuntimeException { if (rows == 0) { cols = m.getCols(); } insertRowData(rows - 1, m); } /** * replaces the data in a submatrix. starts at (low_row, low_col) and * extends by the dimensions for the matrix m * * @param low_row * starting row * @param low_col * starting col * @param m * data to append */ public void replaceSubMatrixData(int low_row, int low_col, RealMatrix m) { if (this == m) return; if (low_row > 0 && low_col > 0) { int mrows = m.getRows(); int mcols = m.getCols(); if (low_row + mrows - 1 < rows && low_col + mcols - 1 < cols) { for (int i = 0; i < mrows; i++) { for (int j = 0; j < mcols; j++) { flmat[i + low_row - 1][j] = m.flmat[i][j]; } } } } } /** * reorder the columns of a matrix. * * @param is * indexes to reorder by * @exception EuclidRuntimeException * is.size() and this.cols differ * @return matrix */ public RealMatrix reorderColumnsBy(IntSet is) throws EuclidRuntimeException { checkColumns(is); RealMatrix temp = new RealMatrix(rows, is.size()); for (int i = 0; i < is.size(); i++) { int icol = is.elementAt(i); if (icol >= cols || icol < 0) { throw new EuclidRuntimeException("bad value of column "+icol); } RealArray coldat = this.extractColumnData(icol); temp.replaceColumnData(i, coldat); } return temp; } /** * reorder the rows of a matrix Deleting rows is allowed * * @param is * indexes to reprder by * @exception EuclidRuntimeException * is.size() and this.rows differ * @return matrix */ public RealMatrix reorderRowsBy(IntSet is) throws EuclidRuntimeException { if (is.size() != rows) { throw new EuclidRuntimeException("unequal matrices"); } RealMatrix temp = new RealMatrix(is.size(), cols); for (int i = 0; i < is.size(); i++) { int irow = is.elementAt(i); if (irow >= rows || irow < 0) { throw new ArrayIndexOutOfBoundsException("irow: " + irow); } RealArray rowdat = this.extractRowData(irow); temp.replaceRowData(i, rowdat); } return temp; } /** * extract a RealMatrix submatrix from a RealMatrix * * @param low_row * starting row * @param high_row * end row * @param low_col * starting col * @param high_col * end col * @exception EuclidRuntimeException * low/high_row/col are outside range of this * @return matrix */ public RealMatrix extractSubMatrixData(int low_row, int high_row, int low_col, int high_col) throws EuclidRuntimeException { return new RealMatrix(this, low_row, high_row, low_col, high_col); } /** * make an Real2_Array from columns. * * @param col1 * @param col2 * @throws EuclidRuntimeException * bad values of columns * @return 2*rows data */ public Real2Array extractColumns(int col1, int col2) throws EuclidRuntimeException { RealArray x = this.extractColumnData(col1); RealArray y = this.extractColumnData(col2); return new Real2Array(x, y); } /** * make an Real2_Array from rows. * * @param row1 * @param row2 * @throws EuclidRuntimeException * bad values of rows * @return 2*cols data */ public Real2Array extractRows(int row1, int row2) throws EuclidRuntimeException { RealArray x = this.extractRowData(row1); RealArray y = this.extractRowData(row2); return new Real2Array(x, y); } /** * produce a mask of those elements which fall in a range. result is matrix * with (1) else (0) * * @param r * the range * @throws EuclidRuntimeException * bad values of rows * @return matrix with 1s where data is in range else 0 */ public IntMatrix elementsInRange(RealRange r) throws EuclidRuntimeException { IntMatrix m = new IntMatrix(rows, cols); for (int irow = 0; irow < rows; irow++) { for (int jcol = 0; jcol < cols; jcol++) { int elem = 0; if (r.includes(elementAt(irow, jcol))) { elem = 1; } m.setElementAt(irow, jcol, elem); } } return m; } /** * output matrix - very crude * * @return the string */ public String toString() { StringBuffer sb = new StringBuffer(); // rows and cols if (rows > 0 && cols > 0) { sb.append(S_LCURLY); sb.append(rows); sb.append(S_COMMA); sb.append(cols); sb.append(S_RCURLY); } else { sb.append(S_LBRAK); } for (int i = 0; i < rows; i++) { sb.append(S_NEWLINE); sb.append(S_LBRAK); for (int j = 0; j < cols; j++) { if (j > 0) { sb.append(S_COMMA); } if (format == null) { sb.append(flmat[i][j]); } else { sb.append(format.format(flmat[i][j])); } } sb.append(S_RBRAK); } if (rows == 0 || cols == 0) { sb.append(S_RBRAK); } return sb.toString(); } /** * output xml as a CML matrix. * * @param w * the writer * @throws IOException */ public void writeXML(Writer w) throws IOException { StringBuffer sb = new StringBuffer(); sb.append(""); for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { if (i != 0 || j != 0) sb.append(S_SPACE); if (format == null) { sb.append(flmat[i][j]); } else { sb.append(format.format(flmat[i][j])); } } } sb.append(""); w.write(sb.toString()); } } wwmm-euclid-87e8f785a814/src/main/java/org/xmlcml/euclid/RealRange.java0000644000000000000000000001777511607017524023652 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid; /** * maximum and minimum values * * Contains two doubles representing the minimum and maximum of an allowed or * observed range. *

* Default is range with low > high; this can be regarded as the uninitialised * state. If points are added to a default RealRange it becomes initialised. * * @author (C) P. Murray-Rust, 1996 */ public class RealRange implements EuclidConstants { /** * maximum of range */ protected double maxval; /** * minimum of range */ protected double minval; /** * creates invalid range from POSITIVE_INFINITY to NEGATIVE_INFINITY */ public RealRange() { minval = Double.POSITIVE_INFINITY; maxval = Double.NEGATIVE_INFINITY; } /** * initialise with min and max values; if minv > maxv create inValid * RealRange * * @param minv * @param maxv */ public RealRange(double minv, double maxv) { setRange(minv, maxv); } /** * initialise with min and max values; if minv > maxv create inValid * RealRange * * @param minv * @param maxv * @param normalize swap params if min > max */ public RealRange(double minv, double maxv, boolean normalize) { if (minv > maxv) { double temp = minv; minv = maxv; maxv = temp; } setRange(minv, maxv); } /** sets range. * overwrites any previous info * @param minv * @param maxv */ public void setRange(double minv, double maxv) { maxval = maxv; minval = minv; if (minval > maxval) { minval = Double.POSITIVE_INFINITY; maxval = Double.NEGATIVE_INFINITY; } } /** * copy constructor * * @param r */ public RealRange(RealRange r) { minval = r.minval; maxval = r.maxval; } /** * from an IntRange * * @param ir */ public RealRange(IntRange ir) { minval = (double) ir.minval; maxval = (double) ir.maxval; } public static RealRange getRange(String s) { RealRange rr = null; RealArray ra = new RealArray(s); if (ra.size() == 2) { rr = new RealRange(ra.get(0), ra.get(1)); } return rr; } /** * a Range is only valid if its maxval is not less than its minval; this * tests for uninitialised ranges * * @return valid */ public boolean isValid() { return (minval <= maxval); } /** * invalid ranges return false * * @param r * @return equal */ @Deprecated public boolean isEqualTo(RealRange r) { return (r != null && Real.isEqual(minval, r.minval) && Real.isEqual(maxval, r.maxval) && minval <= maxval); } /** * invalid ranges return false * * @param r * @return equal */ public boolean isEqualTo(RealRange r, double eps) { return (r != null && Real.isEqual(minval, r.minval, eps) && Real.isEqual(maxval, r.maxval, eps) && minval <= maxval); } /** * combine two ranges if both valid; takes greatest limits of both, else * returns InValid * * @param r2 * @return range */ public RealRange plus(RealRange r2) { if (!this.isValid()) { if (r2 == null || !r2.isValid()) { return new RealRange(); } return new RealRange(r2); } RealRange temp = new RealRange( Math.min(minval, r2.minval), Math.max(maxval, r2.maxval)); return temp; } /** * intersect two ranges and take the range common to both; * return null if no overlap * * @param r2 * @return range */ public RealRange intersectionWith(RealRange r2) { RealRange inter = null; if (isValid() && r2 != null && r2.isValid()) { double minv = Math.max(minval, r2.minval); double maxv = Math.min(maxval, r2.maxval); if (minv <= maxv) { inter = new RealRange(minv, maxv); } } return inter; } /** * get minimum value (POSITIVE_INFINITY if inValid) * * @return min */ public double getMin() { return minval; } /** * get maximum value (NEGATIVE_INFINITY if inValid) * * @return max */ public double getMax() { return maxval; } /** * get centroid value (NEGATIVE_INFINITY if inValid) * * @return centroid */ public double getMidPoint() { return (minval + maxval) * 0.5; } /** * get range (NaN if invalid) * * @return range */ public double getRange() { if (!isValid()) return Double.NaN; return maxval - minval; } /** * does one range include another * * @param r2 * @return includes */ public boolean includes(RealRange r2) { return (r2 != null && r2.isValid() && this.includes(r2.getMin()) && this .includes(r2.getMax())); } /** * is a double within a RealRange * * If inValid, return false * * @param f * @return includes */ public boolean includes(double f) { return f >= minval && f <= maxval; } /** * synonym for includes() * * @param f * @return includes */ public boolean contains(double f) { return includes(f); } /** * add a value to a range * * @param x */ public void add(double x) { maxval = Math.max(maxval, x); minval = Math.min(minval, x); } /** return a number uniformaly distributed within the range. * * @return number. */ public double getRandomVariate() { double range = maxval - minval; return minval + Math.random() * range; } /** get scale to convert this range to same extent as other. * * @param range to scale to * @return scale or Double.NaN */ public double getScaleTo(RealRange range) { double scale = Double.NaN; return scale; } /** * if min > max swap them */ public void normalize() { if (minval > maxval) { double temp = minval; minval = maxval; maxval = temp; } } /** gets minimum signed translation required to move point into range * If range=(-1, 10) * -3 returns 2 * -1 returns 0 * 3 returns 0 * 10 returns 0 * 12 returns -2 * @param p null returns Double.NaN * @return 0 if in or on range */ public double distanceOutside(double d) { double dd = Double.NaN; if (!Double.isNaN(d)) { dd = 0.0; if (d < minval) { dd = d - minval; } else if (d > maxval) { dd = maxval - d; } } return dd; } /** * to string. format: "NULL" or EC.S_LBRAK+minval+S_COMMA+maxval+S_RBRAK; * * @return string */ public String toString() { return (minval > maxval) ? "NULL" : EC.S_LBRAK + minval + EC.S_COMMA + maxval + EC.S_RBRAK; } } wwmm-euclid-87e8f785a814/src/main/java/org/xmlcml/euclid/RealSquareMatrix.java0000644000000000000000000012154611607017524025233 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid; import org.apache.log4j.Logger; import org.apache.commons.math.linear.EigenDecompositionImpl; import org.apache.commons.math.linear.Array2DRowRealMatrix; import org.apache.commons.math.linear.InvalidMatrixException; /** * square matrix class * * RealSquareMatrix represents a square m-x-m matrix. The basic matrix algebra * for square matrices is represented here Check out the exciting member * functions, which are supported by Exceptions where appropriate. (NB. No * attempt has been made to provide numerical robustness and inversion, * diagonalisation, etc are as you find them.) *

* * @author (C) P. Murray-Rust, 1996 */ public class RealSquareMatrix extends RealMatrix { /** * helper class to provide types of matrix. */ /** type */ public enum Type { /** */ UPPER_TRIANGLE(1), /** */ LOWER_TRIANGLE(2), /** */ SYMMETRIC(3), /** */ DIAGONAL(4), /** */ OUTER_PRODUCT(5), /** */ UNKNOWN(6); /** integer value */ public int i; private Type(int i) { this.i = i; } } final static Logger logger = Logger.getLogger(RealSquareMatrix.class); private EigenDecompositionImpl eigenDecompositionImpl; private RealSquareMatrix inverse; private RealArray eigenvalues; private RealSquareMatrix eigenvectors; /** * Constructor. This gives a default matrix with cols = rows = 0. */ public RealSquareMatrix() { super(); } /** * Constructor. * * @param rows * number of rows and columns values are set to zero */ public RealSquareMatrix(int rows) { super(rows, rows); } /** * Creates square matrix from real matrix. * * @param f * real array (length rows) multiplied to give outer product * @return square matrix of size rows * rows */ public static RealSquareMatrix outerProduct(RealArray f) { int rows = f.size(); RealSquareMatrix temp = new RealSquareMatrix(rows); for (int i = 0; i < rows; i++) { for (int j = 0; j < rows; j++) { temp.flmat[i][j] = f.elementAt(i) * f.elementAt(j); } } return temp; } /** * create diagonal matrix from real matrix. * * @param f * real array (length rows) * @return square matrix with elem (i, i) = f(i), else 0.0 */ public static RealSquareMatrix diagonal(RealArray f) { int rows = f.size(); RealSquareMatrix temp = new RealSquareMatrix(rows); for (int i = 0; i < rows; i++) { temp.flmat[i][i] = f.elementAt(i); } return temp; } /** * Creates real square matrix from array * THE COLUMN IS THE FASTEST MOVING * INDEX, that is the matrix is filled as mat(0,0), mat(0,1) ... C-LIKE * * @param rows * the final rows and cols of real square matrix * @param array * of size (rows * rows) * @exception EuclidRuntimeException * array size must be multiple of rows */ public RealSquareMatrix(int rows, double[] array) throws EuclidRuntimeException { super(rows, rows, array); } /** * Creates real square matrix with all elements initialized to double value. * * @param rows * size of square matrix * @param f * value of all elements */ public RealSquareMatrix(int rows, double f) { super(rows, rows, f); } /** * Constructor for submatrix of another matrix. * * @param m * matrix to slice (need not be square) * @param lowrow * the start row inclusive (count from 0) * @param lowcol * the start column inclusive (count from 0) * @param rows * size of final matrix * @exception EuclidRuntimeException * lowrow, lowcol or rows are not consistent with size of * m */ public RealSquareMatrix(RealMatrix m, int lowrow, int lowcol, int rows) throws EuclidRuntimeException { super(m, lowrow, lowrow + rows - 1, lowcol, lowcol + rows - 1); } /** * copy constructor. * * @param m * matrix to copy */ public RealSquareMatrix(RealSquareMatrix m) { super(m); } /** * shallow copy from RealMatrix * * the array values are not copied (only the reference) * * @param m * matrix to copy reference from * * @exception EuclidRuntimeException * m must be square (that is cols = rows) */ public RealSquareMatrix(RealMatrix m) throws EuclidRuntimeException { super(m.rows, m.cols); if (m.cols != m.rows) { throw new EuclidRuntimeException("non square matrix"); } this.flmat = m.flmat; } /** * constructor from array. * * form from a Java 2-D array (it holds row and column count) * * @param matrix * to copy * @exception EuclidRuntimeException * matrix is not square (might even not be * rectangular!) */ public RealSquareMatrix(double[][] matrix) throws EuclidRuntimeException { super(matrix); if (cols != rows) { throw new EuclidRuntimeException("non square matrix"); } } /** * shallowCopy an existing square matrix. * * @param m * matrix to shallow copy * @exception EuclidRuntimeException * m must have the same number of rows and cols as * this */ public void shallowCopy(RealSquareMatrix m) throws EuclidRuntimeException { super.shallowCopy((RealMatrix) m); } /** create square matrix from lower triangle values * upper triangle is filled with zeros * @param f real array (length rows * (rows+1) / 2) * @return square matrix with elem (i, j) = f(k++), else 0.0 */ public static RealSquareMatrix fromLowerTriangle(RealArray f) { int n = f.size(); int rows = (int) Math.round((Math.sqrt(8*n+1) - 1 + 0.001) / 2.); if ((rows * (rows + 1))/2 != n) { throw new RuntimeException("band number of values ("+n+") for lower Triangle"); } RealSquareMatrix temp = new RealSquareMatrix(rows); int count = 0; for (int i = 0; i < rows; i++) { for (int j = 0; j <= i; j++) { temp.flmat[i][j] = f.elementAt(count); if (i != j) { temp.flmat[j][i] = 0.0; } count++; } } return temp; } /** create square matrix from lower triangle * lower triangle is filled with zeros * @param f real array (length rows * (rows+1) / 2) * @return square matrix with elem (i, j) = f(k++), else 0.0 */ public static RealSquareMatrix fromUpperTriangle(RealArray f) { int n = f.size(); int rows = (int) Math.round((Math.sqrt(8*n+1) - 1 + 0.001) / 2.); if ((rows * (rows + 1))/2 != n) { throw new RuntimeException("band number of values ("+n+") for lower Triangle"); } RealSquareMatrix temp = new RealSquareMatrix(rows); int count = 0; for (int i = 0; i < rows; i++) { for (int j = i; j < rows; j++) { temp.flmat[i][j] = f.elementAt(count); if (i != j) { temp.flmat[j][i] = 0.0; } count++; } } return temp; } /** * are two matrices identical * * @param r * matrix to compare * @return true if equal (see RealMatrix.equals for details) */ public boolean isEqualTo(RealSquareMatrix r) { return super.isEqualTo((RealMatrix) r); } /** * matrix addition. adds conformable matrices. Does NOT alter this. * * @param m * matrix to add * @exception EuclidRuntimeException * m must have the same number of rows and cols as * this * @return resultant matrix */ public RealSquareMatrix plus(RealSquareMatrix m) throws EuclidRuntimeException { RealMatrix temp = super.plus((RealMatrix) m); RealSquareMatrix sqm = new RealSquareMatrix(temp); return sqm; } /** * matrix subtraction. subtracts conformable matrices. Does NOT alter this. * * @param m * matrix to subtract from this * @exception EuclidRuntimeException * m must have the same number of rows and cols as * this * @return resultant matrix */ public RealSquareMatrix subtract(RealSquareMatrix m) throws EuclidRuntimeException { RealMatrix temp = super.subtract((RealMatrix) m); RealSquareMatrix sqm = new RealSquareMatrix(temp); return sqm; } /** * matrix multiplication. * * multiplies conformable matrices; result is this*m * * @param m * matrix to multiply by * @exception EuclidRuntimeException * m must have the same number of rows as this * has cols * @return new matrix */ public RealSquareMatrix multiply(RealSquareMatrix m) throws EuclidRuntimeException { RealMatrix temp = super.multiply((RealMatrix) m); RealSquareMatrix sqm = new RealSquareMatrix(temp); return sqm; } /** * determinant. hardcoded up to order 3 at present; rest is VERY slow :-( * calls determinant recursively for order > 3 * * @return the determinant */ public double determinant() { double det = 0.0; if (rows == 1) { det = flmat[0][0]; } else if (rows == 2) { det = flmat[0][0] * flmat[1][1] - flmat[1][0] * flmat[0][1]; } else if (rows == 3) { det = flmat[0][0] * (flmat[1][1] * flmat[2][2] - flmat[1][2] * flmat[2][1]) + flmat[0][1] * (flmat[1][2] * flmat[2][0] - flmat[1][0] * flmat[2][2]) + flmat[0][2] * (flmat[1][0] * flmat[2][1] - flmat[1][1] * flmat[2][0]); } else { int sign = 1; for (int j = 0; j < cols; j++) { det += sign * flmat[0][j] * minorDet(j); sign = -sign; } } return det; } private double minorDet(int ii) { int r = rows - 1; double array[] = new double[r * r]; int countN = 0; for (int i = 1; i < rows; i++) { for (int j = 0; j < cols; j++) { if (j != ii) { array[countN++] = flmat[i][j]; } } } RealSquareMatrix mm = null; try { mm = new RealSquareMatrix(r, array); } catch (Exception e) { throw new EuclidRuntimeException(e.toString()); } double d = mm.determinant(); return d; } /** * trace. * * @return the trace */ public double trace() { double trace = 0.0; for (int i = 0; i < rows; i++) { trace += flmat[i][i]; } return trace; } /** * is it a unit matrix. * * @return are all diagonals 1 and off-diagonal zero (within Real.isEqual()) */ public boolean isUnit() { for (int i = 0; i < rows; i++) { for (int j = 0; j < rows; j++) { double f = flmat[i][j]; if ((!Real.isZero(f, Real.getEpsilon()) && (i != j)) || (!Real.isEqual(f, 1.0, Real.getEpsilon()) && (i == j))) { return false; } } } return true; } /** * is matrix symmetric. * * @return is Real.isEqual(elem(i,j), elem(j,i)) */ public boolean isSymmetric() { for (int i = 0; i < rows - 1; i++) { for (int j = i + 1; j < rows; j++) { if (!Real.isEqual(flmat[i][j], flmat[j][i])) { return false; } } } return true; } /** * orthonormalise matrix. crude (only works for 1, 2x2, 3x3 at present) - * use jama? * * @exception EuclidRuntimeException * I have only written this for this.rows up to 3. * If anyone can find a routine, this will disappear ... -( * @return the orthonormalized matrix */ public RealSquareMatrix orthonormalize() { if (cols == 1) { flmat[0][0] = 1.; } else if (cols == 2) { Vector3 v1 = new Vector3(flmat[0][0], flmat[0][1], 0.); v1 = v1.normalize(); Vector3 v2 = new Vector3(flmat[1][0], flmat[1][1], 0.); v2 = v2.normalize(); Vector3 v3 = v1.cross(v2); v2 = v3.cross(v1); v2 = v2.normalize(); flmat[0][0] = v1.flarray[0]; flmat[0][1] = v1.flarray[1]; flmat[1][0] = v2.flarray[0]; flmat[1][1] = v2.flarray[1]; } else if (cols == 3) { Vector3 v0 = new Vector3(extractRowData(0)); Vector3 v1 = new Vector3(extractRowData(1)); Vector3 v2 = new Vector3(extractRowData(2)); // check handedness double det = v0.getScalarTripleProduct(v1, v2); v0.normalize(); v2 = v0.cross(v1); v2.normalize(); v1 = v2.cross(v0); if (det < 0.0) { v2.negative(); } replaceRowData(0, v0.getArray()); replaceRowData(1, v1.getArray()); replaceRowData(2, v2.getArray()); } else { throw new EuclidRuntimeException( "Sorry: orthonormalise only up to 3x3 matrices: had " + cols + " columns"); } return this; } /** * is matrix unitary. i.e is it orthonormal? * * (synonym for isUnitary()) * * @return true if is Unitary */ public boolean isOrthonormal() { return isUnitary(); } /** * is matrix UpperTriangular. * * @return true if all bottom triangle excluding diagona Real.isZero() */ public boolean isUpperTriangular() { for (int i = 1; i < rows; i++) { for (int j = 0; j < i; j++) { if (!Real.isZero(flmat[i][j], Real.getEpsilon())) return false; } } return true; } /** * is matrix LowerTriangular. diagonal must also be zero * * @return true if all bottom triangle Real.isZero() */ public boolean isLowerTriangular() { for (int i = 0; i < rows - 1; i++) { for (int j = i + 1; j < rows; j++) { if (!Real.isZero(flmat[i][j], Real.getEpsilon())) return false; } } return true; } double rowDotproduct(int row1, int row2) { double sum = 0.0; for (int i = 0; i < cols; i++) { sum += flmat[row1][i] * flmat[row2][i]; } return sum; } /** * is matrix orthogonal. * * checks if Real.isZero(dotProduct) (rowwise calculation) * * @return true if orthogonal */ public boolean isOrthogonal() { for (int i = 0; i < rows - 1; i++) { for (int j = i + 1; j < rows; j++) { double dp = rowDotproduct(i, j); if (!Real.isZero(dp, Real.getEpsilon())) { return false; } } } return true; } /** * is matrix an improper rotation. * * @return true if determinant is -1.0 and isOrthogonal * */ public boolean isImproperRotation() { double f = determinant(); return (Real.isEqual(f, -1.0) && isOrthogonal()); } /** * is matrix unitary. i.e is it orthonormal? * * (synonym for isUnitary()) * * @return true if is Unitary */ public boolean isUnitary() { double f = determinant(); double fa = Math.abs(f); return (Real.isEqual(fa, 1.0) && isOrthogonal()); } /** * copy upper triangle into lower triangle. alters this to make it symmetric * * @return this as new square matrix */ public RealSquareMatrix copyUpperToLower() { for (int i = 0; i < cols - 1; i++) { for (int j = i + 1; j < cols; j++) { flmat[j][i] = flmat[i][j]; } } return this; } /** * copy lower triangle into upper triangle. alters this to make it symmetric * * @return this as new square matrix */ public RealSquareMatrix copyLowerToUpper() { for (int i = 0; i < cols - 1; i++) { for (int j = i + 1; j < cols; j++) { flmat[i][j] = flmat[j][i]; } } return this; } /** * copy lower triangle into linear array; order: 0,0; 1,0; 1,1; 2,0 * * @return linear array of size rows * (rows+1) / 2 */ public RealArray lowerTriangle() { int n = rows; RealArray triangle = new RealArray((n * (n + 1)) / 2); int count = 0; for (int i = 0; i < rows; i++) { for (int j = 0; j <= i; j++) { triangle.setElementAt(count++, flmat[i][j]); } } return triangle; } /** * transpose. MODIFIES this */ public void transpose() { for (int i = 0; i < rows; i++) { for (int j = 0; j < i; j++) { double t = flmat[i][j]; flmat[i][j] = flmat[j][i]; flmat[j][i] = t; } } } /** * diagonalisation returns eigenvalues and vectors as MODIFIED arguments; * 'this' is NOT affected USE JAMA INSTEAD Note that IllCondMatrixException * is RETURNED and not thrown * * @param eigenvalues * @param eigenvectors * @param illCond * @exception EuclidRuntimeException * must have at least order 2 * @return flag */ public int diagonaliseAndReturnRank(RealArray eigenvalues, RealSquareMatrix eigenvectors, EuclidRuntimeException illCond) throws EuclidRuntimeException { // because this was translated from FORTRAN there are some offsets // store current matrix as 1-D array lower Triangle RealArray lowert = this.lowerTriangle(); // f77 offset double[] lower77 = new double[lowert.size() + 1]; System.arraycopy(lowert.getArray(), 0, lower77, 1, lowert.size()); int order = rows; // size must be at least 2! if (rows < 2) { throw new EuclidRuntimeException("need at least 2 rows"); } double[] eigenval77 = new double[rows + 1]; double[] eigenvect77 = new double[rows * rows + 1]; illCond = null; int rank = Diagonalise.vneigl(order, lower77, eigenval77, eigenvect77, illCond); // unoffset the f77 double[] eigenval = new double[rows]; System.arraycopy(eigenval77, 1, eigenval, 0, rows); double[] eigenvect = new double[rows * rows]; System.arraycopy(eigenvect77, 1, eigenvect, 0, rows * rows); eigenvalues.shallowCopy(new RealArray(eigenval)); eigenvectors.shallowCopy(new RealSquareMatrix(rows, eigenvect)); return rank; } /** * orthogonalise matrix. (only works for 3x3 at present); MODIFIES this * * @exception EuclidRuntimeException * I have only written this for this.rows up to 3. * If anyone can find a routine, this will disappear ... -( */ public void orthogonalise() throws EuclidRuntimeException { if (cols == 3) { Vector3 v0 = new Vector3(extractRowData(0)); Vector3 v1 = new Vector3(extractRowData(1)); Vector3 v2 = new Vector3(extractRowData(2)); double l0 = v0.getLength(); double l1 = v1.getLength(); double l2 = v2.getLength(); /** * check handedness */ double det = v0.getScalarTripleProduct(v1, v2); v0.normalize(); v2 = v0.cross(v1); v2.normalize(); v1 = v2.cross(v0); if (det < 0.0) { v2 = v2.negative(); } v0 = v0.multiplyBy(l0); v1 = v1.multiplyBy(l1); v2 = v2.multiplyBy(l2); replaceRowData(0, v0.getArray()); replaceRowData(1, v1.getArray()); replaceRowData(2, v2.getArray()); } else { throw new EuclidRuntimeException( "Sorry: orthogonalise only up to 3x3 matrices"); } } public RealArray calculateEigenvalues() { solveDecomposition(); return eigenvalues; } public RealSquareMatrix calculateInverse() { solveDecomposition(); return inverse; } private void solveDecomposition() { if (eigenDecompositionImpl == null) { Array2DRowRealMatrix realMatrix = new Array2DRowRealMatrix(this.getMatrix()); try { eigenDecompositionImpl = new EigenDecompositionImpl(realMatrix, 0.0); inverse = new RealSquareMatrix(eigenDecompositionImpl.getSolver().getInverse().getData()); eigenvalues = new RealArray(eigenDecompositionImpl.getRealEigenvalues()); eigenvectors = new RealSquareMatrix(eigenDecompositionImpl.getV().getData()); } catch (InvalidMatrixException ime) { inverse = null; eigenvalues = null; eigenvectors = null; } } } /** V is an orthogonal matrix, i.e. its transpose is also its inverse. The columns of V are the eigenvectors of the original matrix. uses apachae.commons.math * @return */ public RealSquareMatrix calculateEigenvectors() { solveDecomposition(); return eigenvectors; } public void resetEigenDecomposition() { eigenDecompositionImpl = null; inverse = null; } /** * create orthogonlisation matrix from cell lengths and angles. Rollett * "Computing Methods in Crystallography" Pergamon 1965 p.23 * * @param celleng * 3 lengths * @param angle * 3 angles in degrees * @return matrix */ public static RealSquareMatrix getCrystallographicOrthogonalisation( double[] celleng, double[] angle) { RealSquareMatrix orthMat = new RealSquareMatrix(3); double dtor = Math.PI / 180.0; double sina = Math.sin(dtor * angle[0]); double cosa = Math.cos(dtor * angle[0]); double sinb = Math.sin(dtor * angle[1]); double cosb = Math.cos(dtor * angle[1]); double cosg = Math.cos(dtor * angle[2]); double cosgstar = (cosa * cosb - cosg) / (sina * sinb); double singstar = Math.sqrt(1.0 - cosgstar * cosgstar); double[][] omat = orthMat.getMatrix(); omat[0][0] = celleng[0] * sinb * singstar; omat[0][1] = 0.0; omat[0][2] = 0.0; omat[1][0] = -celleng[0] * sinb * cosgstar; omat[1][1] = celleng[1] * sina; omat[1][2] = 0.0; omat[2][0] = celleng[0] * cosb; omat[2][1] = celleng[1] * cosa; omat[2][2] = celleng[2]; return orthMat; } /** * inversion of matrix. creates NEW matrix * Hard-coded up to 3x3, if matrix is larger uses JAMA * * @exception EuclidRuntimeException * singular matrix (or worse!) * @return inverse matrix */ public RealSquareMatrix getInverse() throws EuclidRuntimeException { double[][] inv = new double[rows][rows]; double[][] temp = getMatrix(); double det = this.determinant(); if (det == 0) { throw new EuclidRuntimeException("Cannot invert matrix: determinant=0"); } double detr = 1 / det; if (this.rows == 1) { // 1x1 Matrix inv[0][0] = detr; } else if (this.rows == 2) { // 2x2 Matrix inv[0][0] = detr * temp[1][1]; inv[1][0] = 0 - (detr * temp[0][1]); inv[0][1] = 0 - (detr * temp[1][0]); inv[1][1] = detr * temp[0][0]; } else if (this.rows == 3) { // 3x3 Matrix inv[0][0] = detr * (temp[1][1] * temp[2][2] - temp[1][2] * temp[2][1]); inv[0][1] = detr * (temp[0][2] * temp[2][1] - temp[0][1] * temp[2][2]); inv[0][2] = detr * (temp[0][1] * temp[1][2] - temp[0][2] * temp[1][1]); inv[1][0] = detr * (temp[1][2] * temp[2][0] - temp[1][0] * temp[2][2]); inv[1][1] = detr * (temp[0][0] * temp[2][2] - temp[0][2] * temp[2][0]); inv[1][2] = detr * (temp[0][2] * temp[1][0] - temp[0][0] * temp[1][2]); inv[2][0] = detr * (temp[1][0] * temp[2][1] - temp[1][1] * temp[2][0]); inv[2][1] = detr * (temp[0][1] * temp[2][0] - temp[0][0] * temp[2][1]); inv[2][2] = detr * (temp[0][0] * temp[1][1] - temp[0][1] * temp[1][0]); } else { throw new EuclidRuntimeException("Inverse of larger than 3x3 matricies: NYI"); } RealSquareMatrix imat = new RealSquareMatrix(inv); return imat; } /** * invert a square matrix from Hansen (The C++ answer Book - pp 114-5) */ private boolean dopivot(double[][] A, double[][] I, int diag, int nelem) { if (A[diag][diag] != 0.0) return true; int i; for (i = diag + 1; i < nelem; i++) { if (A[i][diag] != 0.0) { double[] t; t = A[diag]; A[diag] = A[i]; A[i] = t; t = I[diag]; I[diag] = I[i]; I[i] = t; break; } } return i < nelem; } @SuppressWarnings("unused") private void matinv(double[][] A, double[][] I, int nelem) throws EuclidRuntimeException { // identity for (int i = 0; i < nelem; i++) { for (int j = 0; j < nelem; j++) { I[i][j] = 0.0; } I[i][i] = 1.0; } for (int diag = 0; diag < nelem; diag++) { if (!dopivot(A, I, diag, nelem)) { throw new EuclidRuntimeException("singular matrix"); } double div = A[diag][diag]; if (div != 1.0) { A[diag][diag] = 1.0; for (int j = diag + 1; j < nelem; j++) A[diag][j] /= div; for (int j = 0; j < nelem; j++) I[diag][j] /= div; } for (int i = 0; i < nelem; i++) { if (i == diag) continue; double sub = A[i][diag]; if (sub != 0.0) { A[i][diag] = 0.0; for (int j = diag + 1; j < nelem; j++) A[i][j] -= sub * A[diag][j]; for (int j = 0; j < nelem; j++) I[i][j] -= sub * I[diag][j]; } } } } } /* in separate class because jvc bombs on compiling this */ class Diagonalise implements EuclidConstants { final static double ZERO = 0.0; final static double ONE = 1.0; final static double TWO = 2.0; final static double SQRT2 = Math.sqrt(TWO); /** * diagonalisation routine * * @param order * @param a * matrix as 1d array * @param eigval * eigenvalues * @param eigvec * egenvectors as 1d array * @param illCond * @throws EuclidRuntimeException * contains reason for failure (probably illconditioned) * @exception EuclidRuntimeException * order < 2 * @return flag */ public static int vneigl(int order, double[] a, double[] eigval, double[] eigvec, EuclidRuntimeException illCond) throws EuclidRuntimeException { /*********************************************************************** * // translated from FORTRAN * * * BECAUSE THIS HAS BEEN TRANSLATED, THERE IS AN OFFSET OF 1 IN THE * ARRAY ADDRESSES * * YOU SHOULD NEVER CALL THIS DIRECTLY, BUT USE THE WRAPPER * (diagonalise). Category: Eigenvectors and Inversion Function: * Destructive diagonalisation of symmetric matrix Mnemonic: Vector * N-dimensional : EIGenvectors/values of Lower triangle * * * Inputs: long int order : order of matrix * * Input And Outputs: double a[] : lower triangular matrix (DESTROYED) * * Outputs: double eigval[] : returned eigenvalues double eigvec[] : * returned eigenvectors * * Syntax: call VNEIGL(order,a,eigval,eigvec) * * Other Information: I think this takes a lower triangle A, * destructively diagonalises it * * into A with eigenvectors in R. Eigenvalues are left down diagonal of * A. The method is (I think) Householder and others. N is order of * matrix The eigenvectors, although declared in routine as * 1-dimensional, can be taken as eigvec(N,N) * * ******************************************************************* * * Local variables: */ double cosx, sinx, xxyy, cosx2, sinx2 = 0.0; int i, j, k, l, m = 0; double x, y, range, anorm, sincs, anrmx = 0.0; int ia, ij, /* il, *//* im, */ll, lm, iq, mm, jq, lq, mq, ind, ilq, imq, ilr, imr = 0; double thr = 0.0; /* -------------------------------------------------------------------- */ /* Conversion from F77 */ // int /*ivar1, ivar2,*/ ivar3 = 0; // double rvar1 = 0.0; cosx = 0.0; sinx = 0.0; xxyy = 0.0; cosx2 = 0.0; sinx2 = 0.0; i = 0; j = 0; k = 0; l = 0; m = 0; x = 0.0; y = 0.0; range = 0.0; anorm = 0.0; sincs = 0.0; anrmx = 0.0; ia = 0; ij = 0; // il = 0; // im = 0; ll = 0; lm = 0; iq = 0; mm = 0; jq = 0; lq = 0; mq = 0; ind = 0; ilq = 0; imq = 0; ilr = 0; imr = 0; thr = 0.0; // ivar3 = 0; // rvar1 = 0.0; /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ RealSquareMatrix.logger.info("O..." + order); /* Function Body */ if (order < 2) { throw new EuclidRuntimeException("order too small"); } /* generate identity matrix */ range = 1e-6f; iq = -(order); /* ivar1 = order; */ for (j = 1; j <= /* ivar1 */order; ++j) { iq += order; /* ivar2 = order; */ for (i = 1; i <= /* ivar2 */order; ++i) { ij = iq + i; eigvec[ij] = ZERO; if (i - j == 0) { eigvec[ij] = ONE; } } } RealSquareMatrix.logger.info("O " + order); /*----------------------------------------------------------------------- */ /* compute initial and final norms (anorm and anormx) */ anorm = ZERO; /* ivar2 = order; */ for (i = 1; i <= /* ivar2 */order; ++i) { /* ivar1 = order; */ for (j = i; j <= /* ivar1 */order; ++j) { if (i - j != 0) { ia = i + (j * j - j) / 2; anorm += a[ia] * a[ia]; } } } if (anorm > ZERO) { anorm = Math.sqrt(anorm) * SQRT2; anrmx = anorm * range / (new Double(order).doubleValue()); /* initialize indicators and compute threshold, thr */ ind = 0; thr = anorm; // L80: while (true) { thr /= new Double(order).doubleValue(); // L90: while (true) { l = 1; while (true) { // L100: m = l + 1; /* compute sin and cos */ // L110: while (true) { mq = (m * m - m) / 2; lq = (l * l - l) / 2; lm = l + mq; if (Math.abs(a[lm]) - thr >= ZERO) { // if (Math.abs(a[lm]) - thr > ZERO) { ind = 1; ll = l + lq; mm = m + mq; x = (a[ll] - a[mm]) * .5f; y = -a[lm] / Math.sqrt(a[lm] * a[lm] + x * x); if (x < ZERO) { y = -y; } /* check to avoid rounding errors */ // L140: xxyy = ONE - y * y; if (xxyy < ZERO) { xxyy = ZERO; } sinx = y / Math.sqrt((Math.sqrt(xxyy) + ONE) * TWO); sinx2 = sinx * sinx; cosx = Math.sqrt(ONE - sinx2); cosx2 = cosx * cosx; sincs = sinx * cosx; /* rotate l and m columns */ ilq = order * (l - 1); imq = order * (m - 1); Diagonalise.subroutine(order, a, ilq, imq, l, m, lq, mq, ll, lm, mm, sinx, cosx, eigval, eigvec, sincs, sinx2, cosx2); } // L250 if (m == order) { break; } // goto L110; // L260 ++m; } /* test for l = second from last column */ // L270 if (l == (order - 1)) { RealSquareMatrix.logger.info(S_LSQUARE + l + EC.S_SLASH + order + EC.S_RSQUARE); break; } // goto L100; // L280 ++l; } // L290 RealSquareMatrix.logger.info(S_PLUS + l + EC.S_SLASH + ind); if (ind != 1) { break; } // L300 ind = 0; // goto L90; } RealSquareMatrix.logger.info("====================broke"); /* compare threshold with final norm */ // L310: if (thr - anrmx <= ZERO) { break; // goto L320; } // goto L80; } } /* sort eigenvalues and eigenvectors */ // L320: iq = -(order); /* ivar1 = order; */ for (i = 1; i <= /* ivar1 */order; ++i) { iq += order; ll = i + (i * i - i) / 2; jq = order * (i - 2); /* ivar2 = order; */ for (j = i; j <= /* ivar2 */order; ++j) { jq += order; mm = j + (j * j - j) / 2; if (a[ll] - a[mm] >= ZERO) { continue; } x = a[ll]; a[ll] = a[mm]; a[mm] = x; /* ivar3 = order; */ for (k = 1; k <= /* ivar3 */order; ++k) { ilr = iq + k; imr = jq + k; x = eigvec[ilr]; eigvec[ilr] = eigvec[imr]; eigvec[imr] = x; } } } return Diagonalise.eigtest(order, a, eigval, range); } private static int eigtest(int order, double[] a, double[] eigval, double range) { /* get eigenvalues and test for singularity */ int rank = 0; for (int i = order; i >= 1; --i) { eigval[i] = a[(i * i + i) / 2]; if (eigval[i] < ZERO) { // illCond = new NPDMatrixException(); break; } else if (eigval[i] < range) { RealSquareMatrix.logger.info("SING"); // illCond = new SingMatrixException(); break; } else { ++rank; } } return rank; } static void subroutine(int order, double[] a, int ilq, int imq, int l, int m, int lq, int mq, int ll, int lm, int mm, double sinx, double cosx, double[] eigval, double[] eigvec, double sincs, double sinx2, double cosx2) { double x, y; /* ivar1 = order; */ for (int i = 1; i <= /* ivar1 */order; ++i) { int iq = (i * i - i) / 2; if (i != l) { // L150: int im, il; int ivar2 = i - m; if (ivar2 != 0) { if (ivar2 < 0) { // L160: im = i + mq; } else { // L170: im = m + iq; } // L180: if (i >= l) { // L200: il = l + iq; } else { // L190: il = i + lq; } // L210: x = a[il] * cosx - a[im] * sinx; a[im] = a[il] * sinx + a[im] * cosx; a[il] = x; } // L220: int ilr = ilq + i; int imr = imq + i; x = eigvec[ilr] * cosx - eigvec[imr] * sinx; eigvec[imr] = eigvec[ilr] * sinx + eigvec[imr] * cosx; eigvec[ilr] = x; } x = a[lm] * 2.f * sincs; y = a[ll] * cosx2 + a[mm] * sinx2 - x; x = a[ll] * sinx2 + a[mm] * cosx2 + x; a[lm] = (a[ll] - a[mm]) * sincs + a[lm] * (cosx2 - sinx2); a[ll] = y; a[mm] = x; /* * tests for completion test for m = last column */ } } } wwmm-euclid-87e8f785a814/src/main/java/org/xmlcml/euclid/Transform2.java0000644000000000000000000004770011607017524024036 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid; import org.apache.log4j.Logger; /** * 2-D transformation matrix class * * Transform2 represents a transformation matrix for 2-D objects. Its actual * form may be implementation-dependent, but we have started with 3x3 matrices. * The following transformations will be supported as the class is developed: * * * * TRFORM2_NULL no transformation allowed
* ROT_ORIG rotation about the origin
* ROT_TRANS rotation and translation
* ROT_TRANS_SCALE rotation, translation and single scale factor
* ROT_TRANS_AXIAL_SCALE rotation, translation + 3 axial scale factors
* ROT_TRANS_SCALE_PERSP rotation, translation, scale, perspective
* TRFORM3_ANY any matrix at all - user beware! *

* * The basic stuff is all there - the user will do best to look at examples. * * * NOTE; this has been hacked in a hurry from Transform3. Many of the internal * routines are grossly overcomplicated. I'll clean it up some time. * * @author (C) P. Murray-Rust, 1996 * @author PMR 20 August 2003 */ public class Transform2 extends RealSquareMatrix { final static Logger logger = Logger.getLogger(Transform2.class.getName()); /** type */ public enum Type { /** */ NULL(1, "none"), /** */ ROT_ORIG(2, "rotation about origin"), /** */ ROT_TRANS(3, "rotation translation"), /** */ ROT_TRANS_SCALE(4, "rotation translation scale"), /** */ ROT_TRANS_AXIAL_SCALE(5, "rotation translation axial scale"), /** */ ROT_TRANS_SCALE_PERSP(6, "perspective"), /** */ ANY(7, "any"); /** integer value */ public int i; /** String value */ public String s; private Type(int i, String s) { this.i = i; this.s = s; } }; /** * Transform2 inherits all public or protected members of RealSquareMatrix * and its ancestors */ Type trnsfrm; /** * default is a unit matrix */ public Transform2() { super(3); for (int i = 0; i < 3; i++) { flmat[i][i] = 1.0; } trnsfrm = Type.ANY; } /** * This gives a default unit matrix of type t (default ROT_ORIG) * * @param t * Description of the Parameter */ public Transform2(Type t) { this(); trnsfrm = t; } /** identity matrix with translation component * * @param v amount to translate by */ public Transform2(Vector2 v) { this(); trnsfrm = Type.ROT_TRANS; flmat[0][2] = v.x; flmat[1][2] = v.y; } /** clockwise rotation about z- axis * * @param zrot radians clockwise rotation */ public Transform2(Angle zrot) { this(); double cosx = zrot.cos(); double sinx = zrot.sin(); this.flmat[0][0] = cosx; this.flmat[0][1] = sinx; this.flmat[1][0] = -sinx; this.flmat[1][1] = cosx; this.flmat[2][2] = 1.0; this.trnsfrm = Type.ROT_ORIG; } /** * from rotation about a point, given a matrix NOT CHECKED * * @param t * Description of the Parameter * @param p * Description of the Parameter */ public Transform2(Transform2 t, Real2 p) { super(3); // translation = -M*r + r flmat[0][2] = -t.flmat[0][0] * p.x - t.flmat[0][1] * p.y + p.x; flmat[1][2] = -t.flmat[1][0] * p.x - t.flmat[1][1] * p.y + p.y; this.flmat[0][0] = t.flmat[0][0]; this.flmat[0][1] = t.flmat[0][1]; this.flmat[1][0] = t.flmat[1][0]; this.flmat[1][1] = t.flmat[1][1]; trnsfrm = Type.ROT_TRANS; } /** * rotation of one vector onto another * * @param v1 * Description of the Parameter * @param v2 * Description of the Parameter * @exception EuclidRuntimeException * v1 or v2 is zero length */ public Transform2(Vector2 v1, Vector2 v2) throws EuclidRuntimeException { super(3); Angle a = v1.getAngleMadeWith(v2); Transform2 temp = new Transform2(a); this.flmat = temp.flmat; this.trnsfrm = temp.trnsfrm; } /** * from 2 vector components - NOT checked for validity * * @param v1 * Description of the Parameter * @param v2 * Description of the Parameter */ public Transform2(Real2 v1, Real2 v2) { super(3); for (int i = 0; i < 2; i++) { flmat[0][0] = v1.x; flmat[1][0] = v2.x; flmat[0][1] = v1.y; flmat[1][1] = v2.y; flmat[2][i] = 0.0; flmat[i][2] = 0.0; } flmat[2][2] = 1.0; trnsfrm = Type.ROT_ORIG; } /** * construct from an array. Formed by feeding in an existing array. to a * cols*cols matrix array is of type m00, m01, m02, m10 ... * * @param array * to create the Transform from * @exception EuclidRuntimeException * array must have 9 elements */ public Transform2(double[] array) throws EuclidRuntimeException { super(3, array); trnsfrm = calculateMatrixType(); } /** * copy constructors - assumed to be an OK matrix. * * @param m * the transform to copy */ public Transform2(Transform2 m) { super(m); trnsfrm = m.trnsfrm; } /** * from a 2x2 or 3x3 matrix * * @param m * Description of the Parameter * @exception EuclidRuntimeException * m must be 2*2 or 3*3 */ public Transform2(RealSquareMatrix m) throws EuclidRuntimeException { this(); // 2x2 matrix. convert to 3x3 if (m.getCols() == 2) { // convert to 3x3 for (int i = 0; i < 2; i++) { for (int j = 0; j < 2; j++) { flmat[i][j] = m.flmat[i][j]; } } } else if (m.getCols() != 3) { throw new EuclidRuntimeException("bad size for transform "+m.getCols()); } else { this.flmat = m.flmat; } this.trnsfrm = calculateMatrixType(); } /** * from a 2x2 rotation matrix and a translation vector * * @param m * Description of the Parameter * @param v * Description of the Parameter * @exception EuclidRuntimeException * m must be 2*2 */ public Transform2(RealSquareMatrix m, Vector2 v) throws EuclidRuntimeException { this(m); // 2x2 matrix. convert to 3x3 if (m.getCols() == 2) { // convert to 3x3 flmat[0][2] = v.x; flmat[1][2] = v.y; } else { throw new EuclidRuntimeException("must have 2*2 rotation matrix"); } } /** * clone * * @param m * Description of the Parameter * @return Description of the Return Value */ public Transform2 clone(Transform2 m) { // delete existing matrix in this Transform2 temp = new Transform2((RealSquareMatrix) m); temp.trnsfrm = m.trnsfrm; return temp; } /** * Carries out graphics transform * * transforms between rectangular coordinates. * Example: *

     * Real2 inputDim = new Real2(2.7, 20000);
     * Real2 outputDim = new Real2(-300, 300);
     * 
* *@param in Description of the Parameter *@param out Description of the Parameter *@param keepAspectRatio Description of the Parameter *@exception ArithmeticException Description of the Exception *@throws zero-sized dimensions */ public Transform2(Window2 in, Window2 out, boolean keepAspectRatio) throws ArithmeticException { this(in.origin, in.dim, out.origin, out.dim, keepAspectRatio); } /** * graphics transform (transforms between rectangular coordinates * ("windows") originIn maps onto originOut and dimensionIn (width, height) * onto dimensionOut. If keepAspectRatio id true, scales will be isotropic. * Note that ranges can be inverted by using negative coordinates in * dimensions. Example:
     *Real2 inputDim = new Real2(2.7, 20000);
     *Real2 outputDim = new Real2(-300, 300);
     *
* *@param originIn Description of the Parameter *@param dimensionIn Description of the Parameter *@param originOut Description of the Parameter *@param dimensionOut Description of the Parameter *@param keepAspectRatio Description of the Parameter *@exception ArithmeticException Description of the Exception *@throws zero-sized dimensions */ public Transform2(Real2 originIn, Real2 dimensionIn, Real2 originOut, Real2 dimensionOut, boolean keepAspectRatio) throws ArithmeticException { this(); double scaleX; double scaleY; scaleX = dimensionOut.getX() / dimensionIn.getX(); scaleY = dimensionOut.getY() / dimensionIn.getY(); if (keepAspectRatio) { if (Math.abs(scaleX) < Math.abs(scaleY)) { scaleY = scaleX * (scaleY / Math.abs(scaleY)); } if (Math.abs(scaleY) < Math.abs(scaleX)) { scaleX = scaleY * (scaleX / Math.abs(scaleX)); } } flmat[0][0] = scaleX; flmat[1][1] = scaleY; flmat[0][2] = originOut.getX() - scaleX * originIn.getX(); flmat[1][2] = originOut.getY() - scaleY * originIn.getY(); } /** * seem to require this one * * @param m * Description of the Parameter * @return Description of the Return Value */ Transform2 clone(RealSquareMatrix m) { Transform2 temp = new Transform2(m); temp.trnsfrm = calculateMatrixType(); return temp; } /** * Description of the Method * * @param m * Description of the Parameter * @return Description of the Return Value */ public boolean isEqualTo(Transform2 m) { return super.isEqualTo((RealSquareMatrix) m) && trnsfrm == m.trnsfrm; } /** rotate about a point. * * @param angle * @param point * @return tramsformation */ public static Transform2 getRotationAboutPoint(Angle angle, Real2 point) { Transform2 t3 = new Transform2(new Vector2(point)); Transform2 t2 = new Transform2(angle); Transform2 t1 = new Transform2(new Vector2(point.multiplyBy(-1.0))); return t3.concatenate(t2).concatenate(t1); } /** * apply scales to each axis * @param scaleX * @param scaleY * @return transform */ public static Transform2 applyScales(double scaleX, double scaleY) { return new Transform2( new double[] { scaleX, 0.0, 0.0, 0.0, scaleY, 0.0, 0.0, 0.0, 1.0 }); } /** * apply scale to each axis * @param scale * @return transform */ public static Transform2 applyScale(double scale) { return Transform2.applyScales(scale, scale); } public void applyScalesToThis(double scaleX, double scaleY) { Transform2 t2 = Transform2.applyScales(scaleX, scaleY); t2 = this.concatenate(t2); this.flmat = t2.flmat; } /** * concatenate * * @param m2 postmultiplies this * @return Description of the Return Value */ public Transform2 concatenate(Transform2 m2) { RealSquareMatrix temp = new RealSquareMatrix(((RealSquareMatrix) this) .multiply((RealSquareMatrix) m2)); // maximum value is matrix of greatest generality (horrible) Transform2 temp1 = new Transform2(temp); temp1.trnsfrm = (trnsfrm.i > m2.trnsfrm.i) ? trnsfrm : m2.trnsfrm; return temp1; } /** * set transformation type may attempt to orthonomalise if type includes a * rotation * * @param option * The new transformationType value * @return Description of the Return Value */ public int setTransformationType(Type option) { RealSquareMatrix s3 = new RealSquareMatrix(); if (option == Type.ROT_ORIG) { s3 = new RealSquareMatrix(this.extractSubMatrixData(0, 1, 0, 1)); s3.orthonormalize(); this.replaceSubMatrixData(0, 0, s3); } else if (option == Type.ROT_TRANS) { s3 = new RealSquareMatrix(this.extractSubMatrixData(0, 1, 0, 1)); s3.orthonormalize(); this.replaceSubMatrixData(0, 0, s3); } else if (option == Type.ROT_TRANS_SCALE) { s3 = new RealSquareMatrix(this.extractSubMatrixData(0, 1, 0, 1)); double[] scale = s3.euclideanColumnLengths().getArray(); double scale3 = Math.exp(Math.log(scale[0] * scale[1]) / 2.0); s3.orthonormalize(); RealArray sc1 = new RealArray(3, scale3); RealSquareMatrix s = RealSquareMatrix.diagonal(sc1); s3 = s.multiply(s3); replaceSubMatrixData(0, 0, s3); } else if (option == Type.ROT_TRANS_SCALE_PERSP) { } else if (option == Type.ROT_TRANS_AXIAL_SCALE) { s3 = new RealSquareMatrix(this.extractSubMatrixData(0, 1, 0, 1)); RealArray scale = s3.euclideanColumnLengths(); s3.orthonormalize(); RealSquareMatrix s = RealSquareMatrix.diagonal(scale); s3 = s.multiply(s3); replaceSubMatrixData(0, 0, s3); } else if (option == Type.ANY) { } else if (option == Type.NULL) { } else { return 1; } trnsfrm = option; return 0; } /** * get transformation type * * @return The transformationType value */ public Type getTransformationType() { return trnsfrm; } /** * get new matrix type * * @return Description of the Return Value */ public Type calculateMatrixType() { RealSquareMatrix s3 = new RealSquareMatrix(extractSubMatrixData(0, 1, 0, 1)); RealArray c3 = extractColumnData(2); if (c3 != null) { if (Real.isZero(c3.elementAt(0), Real.getEpsilon()) && Real.isZero(c3.elementAt(1), Real.getEpsilon())) { return Type.NULL; } } { if (s3.isUnit()) { return Type.NULL; } // unit matrix if (s3.isUnitary()) { return Type.ROT_ORIG; } // unitary matrix } if (s3.isUnitary()) { return Type.ROT_TRANS; } // rot + trans; no scale if (s3.isOrthogonal()) { double[] scale = s3.euclideanColumnLengths().getArray(); if (Real.isEqual(scale[0], scale[1])) { return Type.ROT_TRANS_SCALE; } return Type.ROT_TRANS_AXIAL_SCALE; } return Type.ANY; } /** * interpret current matrix as rotation about axis NOT YET CHECKED; only * worsk for orthornormal matrices * * @return The angleOfRotation value */ public Angle getAngleOfRotation() { return new Angle(Math.atan2(flmat[0][1], flmat[0][0])); } /** * get Transformation to mirror ('flip') across an axis NOT YET CHECKED * * @param r * Description of the Parameter * @return Description of the Return Value * @exception EuclidRuntimeException * r is zero length */ public static Transform2 flipAboutVector(Real2 r) throws EuclidRuntimeException { r = r.getUnitVector(); double cost = r.x; double sint = r.y; Transform2 temp = new Transform2(); temp.flmat[0][0] = cost * cost - sint * sint; temp.flmat[1][1] = -temp.flmat[0][0]; temp.flmat[0][1] = temp.flmat[1][0] = 2 * cost * sint; return temp; } /** * get translation component only * * @return The translation value */ public Real2 getTranslation() { return new Real2(flmat[0][2], flmat[1][2]); } /** * get translation component only * * @return The translation value */ public void setTranslation(Real2 xy) { flmat[0][2] = xy.x; flmat[1][2] = xy.y; } /** * get scales (as a 2-element RealArray) * * @return The scales value */ RealArray getScales() { RealArray scales; RealSquareMatrix s3 = new RealSquareMatrix(extractSubMatrixData(0, 1, 0, 1)); scales = s3.euclideanColumnLengths(); return scales; } /** * get Unitary matrix (that is eliminate scales and translation) * * @return The rotationMatrix value */ public RealSquareMatrix getRotationMatrix() { RealSquareMatrix s; RealSquareMatrix s3 = new RealSquareMatrix(extractSubMatrixData(0, 1, 0, 1)); s3.normaliseByColumns(); s = s3; return s; } /** * transform describing the rotation and stretching of a line. * used in bondTool.getTranformToRotateAndStretchBond(movingAtom, targetPoint); * Transform2 t = this.getTranformToRotateAndStretchLine(movingAtom, targetPoint) { * @param pivotPoint * @param movingPoint * @param targetPoint point to translate movingAtom to * @return */ public static Transform2 getTransformToRotateAndStretchLine( Real2 pivotPoint, Real2 movingPoint, Real2 targetPoint) { Vector2 pivotVector = new Vector2(movingPoint.subtract(pivotPoint)); Vector2 targetVector = new Vector2(targetPoint.subtract(pivotPoint)); Angle angle = pivotVector.getAngleMadeWith(targetVector); Transform2 rotate = new Transform2(angle); Transform2 rotateAboutOtherPoint = new Transform2(rotate, pivotPoint); Vector2 deltaVector = new Vector2(targetVector.subtract(pivotVector)); Vector2 stretchVector = deltaVector.projectOnto(pivotVector); Transform2 stretch = new Transform2(stretchVector); Transform2 finalTransform = rotateAboutOtherPoint.concatenate(stretch); return finalTransform; } /** * Description of the Method * * @return Description of the Return Value */ public String toString() { String s = EC.S_LBRAK; for (int i = 0; i < this.flmat.length; i++) { for (int j = 0; j < this.flmat[i].length; j++) { s += flmat[i][j]; s += EC.S_COMMA; } if (i < flmat.length - 1) { s += EC.S_NEWLINE; } } s += EC.S_RBRAK; return s; } } wwmm-euclid-87e8f785a814/src/main/java/org/xmlcml/euclid/Transform3.java0000644000000000000000000006635411607017524024045 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid; import java.util.StringTokenizer; import org.apache.log4j.Logger; import org.xmlcml.euclid.Axis.Axis3; /** * 3-D transformation matrix class Transform3 represents a transformation matrix * for 3-D objects. Its actual form may be implementation-dependent, but we have * started with 4x4 matrices. The following transformations will be supported as * the class is developed: *

*
* TRFORM3_NULL no transformation allowed
* ROT_ORIG rotation about the origin
* ROT_TRANS rotation and translation
* ROT_TRANS_SCALE rotation, translation and single scale factor
* ROT_TRANS_AXIAL_SCALE rotation, translation + 3 axial scale factors
* ROT_TRANS_SCALE_PERSP rotation, translation, scale, perspective
* TRFORM3_ANY any matrix at all - user beware! *

* The basic stuff is all there - the user will do best to look at examples. * * @author (C) P. Murray-Rust, 1996 */ public class Transform3 extends RealSquareMatrix { final static Logger logger = Logger.getLogger(Transform3.class.getName()); /** type */ public enum Type { /** */ NULL(1, "none"), /** */ ROT_ORIG(2, "rotation about origin"), /** */ ROT_TRANS(3, "rotation translation"), /** */ ROT_TRANS_SCALE(4, "rotation translation scale"), /** */ ROT_TRANS_AXIAL_SCALE(5, "rotation translation axial scale"), /** */ ROT_TRANS_SCALE_PERSP(6, "perspective"), /** */ ANY(7, "any"); /** integer value */ public int i; /** String value */ public String s; private Type(int i, String s) { this.i = i; this.s = s; } }; /** * Transform3 inherits all public/protected members of RealSquareMatrix and * its ancestors */ /** * type of transformation ( see above) */ Type trnsfrm = Type.ANY; /** * construct unit matrix T = I */ public Transform3() { super(4); createIdentityTransform(); } private void createIdentityTransform() { for (int i = 0; i < 4; i++) { flmat[i][i] = 1.0; } } /** * This gives a default unit matrix of type t. * * @param t type */ public Transform3(Type t) { this(); trnsfrm = t; } /** * identity matrix with translation component. T = I|vector * * @param v translation vector */ public Transform3(Vector3 v) { this(); trnsfrm = Type.ROT_TRANS; for (int i = 0; i < 3; i++) { flmat[i][3] = v.flarray[i]; } } /** * from rotation about an axis. (use (Choice3.X), etc * * @param axis Choice.X, etc * @param rot angle to rotate by */ public Transform3(Axis3 axis, Angle rot) { this(); trnsfrm = Type.ROT_ORIG; // unit matrix RealSquareMatrix t1 = new RealSquareMatrix(4); double cosx = rot.cos(); double sinx = rot.sin(); // X-axis if (axis == Axis3.X) { t1.flmat[0][0] = 1.0; t1.flmat[1][1] = cosx; t1.flmat[1][2] = sinx; t1.flmat[2][1] = -sinx; t1.flmat[2][2] = cosx; t1.flmat[3][3] = 1.0; } // Y-axis else if (axis == Axis3.Y) { t1.flmat[0][0] = cosx; t1.flmat[0][2] = -sinx; t1.flmat[1][1] = 1.0; t1.flmat[2][0] = sinx; t1.flmat[2][2] = cosx; t1.flmat[3][3] = 1.0; } // Z-axis else if (axis == Axis3.Z) { t1.flmat[0][0] = cosx; t1.flmat[0][1] = sinx; t1.flmat[1][0] = -sinx; t1.flmat[1][1] = cosx; t1.flmat[2][2] = 1.0; t1.flmat[3][3] = 1.0; } this.flmat = t1.flmat; this.trnsfrm = Type.ROT_ORIG; } /** * from rotation about the three orthogonal axes. rotX then rotY then rotZ * * @param xrot * @param yrot * @param zrot */ public Transform3(Angle xrot, Angle yrot, Angle zrot) { super(4); double cosx = 0.0; double sinx = 0.0; trnsfrm = Type.ROT_ORIG; // X-axis int mat = 0; RealSquareMatrix t1 = new RealSquareMatrix(4); //must have non=zero matrix even for zero angle cosx = xrot.cos(); sinx = xrot.sin(); t1.flmat[0][0] = 1.0; t1.flmat[1][1] = cosx; t1.flmat[1][2] = sinx; t1.flmat[2][1] = -sinx; t1.flmat[2][2] = cosx; t1.flmat[3][3] = 1.0; mat = 1; // Y-axis if (!yrot.isEqualTo(0.0)) { cosx = yrot.cos(); sinx = yrot.sin(); // unit matrix RealSquareMatrix t2 = new RealSquareMatrix(4); t2.flmat[0][0] = cosx; t2.flmat[1][1] = 1.0; t2.flmat[0][2] = -sinx; t2.flmat[2][0] = sinx; t2.flmat[2][2] = cosx; t2.flmat[3][3] = 1.0; if (mat == 1) { t1 = t2.multiply(t1); } else { t1 = t2; } mat = 1; } // Z-axis if (!zrot.isEqualTo(0.0)) { cosx = zrot.cos(); sinx = zrot.sin(); // unit matrix RealSquareMatrix t2 = new RealSquareMatrix(4); t2.flmat[0][0] = cosx; t2.flmat[0][1] = sinx; t2.flmat[1][0] = -sinx; t2.flmat[1][1] = cosx; t2.flmat[2][2] = 1.0; t2.flmat[3][3] = 1.0; if (mat == 1) { t1 = t2.multiply(t1); } else { t1 = t2; } } this.flmat = t1.flmat; this.trnsfrm = Type.ROT_ORIG; } /** * from rotation about a point. * * @param t * rotation matrix * @param p * point to rotate about */ public Transform3(Transform3 t, Point3 p) { super(4); double f1[] = { 0.0, 0.0, 0.0, 1.0 }; trnsfrm = Type.ROT_TRANS; Vector3 tvect = new Vector3(p); // translation only matrices Transform3 trans1 = new Transform3(tvect.negative()); Transform3 trans2 = new Transform3(tvect); // remove existing translation RealArray f0 = new RealArray(f1); Transform3 temp = t; temp.replaceColumnData(3, f0); // concatenate Transform3 temp3 = trans2.concatenate(temp.concatenate(trans1)); this.flmat = temp3.flmat; this.trnsfrm = temp3.trnsfrm; } /** * from rotation about a vector. * * @param v * vector to rotate about * @param a * angle to rotate by */ public Transform3(Vector3 v, Angle a) { super(4); trnsfrm = Type.ROT_ORIG; Vector3 v2 = v; v2.normalize(); double cosa = a.cos(); // make a diagonal with identical elements (cos(a)) RealArray tempf = new RealArray(3, cosa); RealSquareMatrix m3 = RealSquareMatrix.diagonal(tempf); // outer product of axial components RealArray temp1 = new RealArray(v2.getArray()); RealSquareMatrix m2 = RealSquareMatrix.outerProduct(temp1); m2.multiplyBy(1.0 - cosa); m2 = m2.plus(m3); // final matrix is (0, -v3, v2; v3, 0, -v1; -v2, v1, 0) * sin(a) // I expect the coding could be more elegant! double sina = a.sin(); m3.clearMatrix(); double f = sina * v2.flarray[2]; m3.flmat[0][1] = -f; m3.flmat[1][0] = f; f = sina * v2.flarray[1]; m3.flmat[0][2] = f; m3.flmat[2][0] = -f; f = sina * v2.flarray[0]; m3.flmat[1][2] = -f; m3.flmat[2][1] = f; m2 = m2.plus(m3); // transfer to main matrix for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { flmat[i][j] = m2.flmat[i][j]; } } flmat[3][3] = 1.0; } /** * Rotation about a line. chooses any point on line as centre of rotation * * @param l * line to rotate about * @param a * angle to rotate by */ public Transform3(Line3 l, Angle a) { super(4); trnsfrm = Type.ROT_TRANS; Vector3 v = l.getVector(); Point3 p = l.getPoint(); Transform3 temp = new Transform3(v, a); Vector3 orig = new Vector3(p); Transform3 trans1 = new Transform3(orig.negative()); // translate to // origin orig = new Vector3(p); Transform3 trans2 = new Transform3(orig); // translate back Transform3 temp2 = new Transform3(); temp2 = new Transform3(trans2.concatenate(temp.concatenate(trans1))); // concatenate // copy back to present one this.flmat = temp2.flmat; } /** * rotation of one vector onto another. this documentation has not been * checked * * @param v1 vector to rotate * @param v2 vector to rotate v1 onto */ public Transform3(Vector3 v1, Vector3 v2) { super(4); Vector3 v12 = v1.cross(v2); // if parallel return unit matrix /* * 06/03/08 * I've changed the code so there is a difference between parallel and * anti-parallel vectors. This is important for the polymer builder, but * may break other applications. Contact me if this is a problem - dmj30@cam */ if (v12.isZero()) { double unit = 1.0; if(v1.dot(v2) < 0) unit = -1.0; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { flmat[i][j] = 0.0; } flmat[i][i] = unit; } } else { Angle a = v1.getAngleMadeWith(v2); Transform3 temp = new Transform3(v12, a); this.flmat = temp.flmat; this.trnsfrm = temp.trnsfrm; } } /** * from 3 vector components. NOT checked fills rows of T with v1, v2, v3 * * @param v1 * first row of T * @param v2 * second row of T * @param v3 * third row of T */ public Transform3(Vector3 v1, Vector3 v2, Vector3 v3) { super(4); for (int i = 0; i < 3; i++) { flmat[0][i] = v1.flarray[i]; flmat[1][i] = v2.flarray[i]; flmat[2][i] = v3.flarray[i]; flmat[3][i] = 0.0; flmat[i][3] = 0.0; } flmat[3][3] = 1.0; trnsfrm = Type.ROT_ORIG; } /** * apply scales to each axis * @param scaleX * @param scaleY * @param scaleZ * @return transform */ public static Transform3 applyScales(double scaleX, double scaleY, double scaleZ) { return new Transform3( new double[] { scaleX, 0.0, 0.0, 0.0, 0.0, scaleY, 0.0, 0.0, 0.0, 0.0, scaleZ, 0.0, 0.0, 0.0, 0.0, 1.0 }); } /** * apply scale to each axis * @param scale * @return transform */ public static Transform3 applyScale(double scale) { return Transform3.applyScales(scale, scale, scale); } /** * From array. * * @param array * copied to m00, m01, m02, m03, m10 ... * @exception EuclidRuntimeException * array must have 16 elements */ public Transform3(double[] array) throws EuclidRuntimeException { super(4, array); trnsfrm = checkMatrix(); } /** * copy constructor. * * @param m * transform to copy */ public Transform3(Transform3 m) { super(m); trnsfrm = m.trnsfrm; } /** * from a matrix. * * @param m * 3x3 or 4x4 matrix * @exception EuclidRuntimeException * m must be 3*3 or 4*4 */ public Transform3(RealSquareMatrix m) throws EuclidRuntimeException { this(); // 3x3 matrix. convert to 4x4 if (m.getCols() == 3) { // convert to 4x4 for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { flmat[i][j] = m.flmat[i][j]; } } } else if (m.getCols() != 4) { throw new EuclidRuntimeException("must have 3 or 4 cols"); } else { this.flmat = m.flmat; } this.trnsfrm = checkMatrix(); } /** * from a matrix and vector. * * @param m * 3x3 rotation matrix * @param v * translation vector * @exception EuclidRuntimeException * m must be 3*3 */ public Transform3(RealSquareMatrix m, Vector3 v) throws EuclidRuntimeException { this(m); // 3x3 matrix. convert to 4x4 if (m.getCols() == 3) { // convert to 4x4 for (int i = 0; i < 3; i++) { flmat[i][3] = v.flarray[i]; } } else { throw new EuclidRuntimeException("must have 3 columns"); } } /** * from a crystallographic operator. * * @param opString * for example 1/2-x,1/2+y,-z * @throws EuclidRuntimeException * corrupt/invalid string */ public Transform3(String opString) throws EuclidRuntimeException { super(4); StringTokenizer st = new StringTokenizer(opString, EuclidConstants.S_COMMA); if (st.countTokens() != 3) { throw new EuclidRuntimeException("Must have 3 operators"); } for (int i = 0; i < 3; i++) { String s = st.nextToken(); s = s.trim(); StringTokenizer sst = new StringTokenizer(s, "+-", true); int ntok = sst.countTokens(); double sign = 1; for (int j = 0; j < ntok; j++) { String ss = sst.nextToken().trim(); int idx = ss.indexOf(S_SLASH); if (idx != -1) { final String numerator = ss.substring(0, idx).trim(); final String denominator = ss.substring(idx + 1).trim(); flmat[i][3] = sign * (double) Integer.parseInt(numerator) / (double) Integer.parseInt(denominator); } else if (ss.equalsIgnoreCase("x")) { flmat[i][0] = sign; } else if (ss.equalsIgnoreCase("y")) { flmat[i][1] = sign; } else if (ss.equalsIgnoreCase("z")) { flmat[i][2] = sign; } else if (ss.equals(S_MINUS)) { sign = -1; } else if (ss.equals(S_PLUS)) { sign = 1; } else if (ss.trim().equals("")) { // unusual, but some people put "y+1" } else { try { flmat[i][3] = sign * (double) Integer.parseInt(ss); } catch (NumberFormatException nfe) { System.out.flush(); throw new EuclidRuntimeException("Bad string in symmetry: " + ss + " in " + opString); } } } } } /** * clone. * * @param m * @return transform */ public Transform3 clone(Transform3 m) { // delete existing matrix in this Transform3 temp = new Transform3((RealSquareMatrix) m); temp.trnsfrm = m.trnsfrm; return temp; } /** * seem to require this one */ Transform3 clone(RealSquareMatrix m) { Transform3 temp = new Transform3(m); temp.trnsfrm = checkMatrix(); return temp; } /** * equality of two transforms. based on equality of RealSquareMatrix * * @param m * transform to compare * @return true if equal within Real.isEqual() */ public boolean isEqualTo(Transform3 m) { return super.isEqualTo((RealSquareMatrix) m) && trnsfrm == m.trnsfrm; } /** * concatenate. (I think this is right...) result = this * m2 i.e. if x' = * m2 * x and x'' = this * x'' then x'' = result * x; * * @param m2 * transform to be concatenated * @return result of applying this to m2 */ public Transform3 concatenate(Transform3 m2) { RealSquareMatrix temp = new RealSquareMatrix(((RealSquareMatrix) this) .multiply((RealSquareMatrix) m2)); // maximum value is matrix of greatest generality (horrible) Transform3 temp1 = new Transform3(temp); temp1.trnsfrm = (trnsfrm.i > m2.trnsfrm.i) ? trnsfrm : m2.trnsfrm; return temp1; } /** * set transformation type. * * @param option * the type * @return 0 if ok else 1 */ public int setTransformationType(Type option) { RealSquareMatrix s3 = new RealSquareMatrix(); if (option == Type.ROT_ORIG) /** orthonormalise and set trans vector to zero */ { s3 = new RealSquareMatrix(this.extractSubMatrixData(0, 2, 0, 2)); s3.orthonormalize(); this.replaceSubMatrixData(0, 0, s3); } else if (option == Type.ROT_TRANS) /** orthonormalise */ { s3 = new RealSquareMatrix(this.extractSubMatrixData(0, 2, 0, 2)); s3.orthonormalize(); this.replaceSubMatrixData(0, 0, s3); } else if (option == Type.ROT_TRANS_SCALE) /** * orthogonalise and take geometric mean of the three diagonal scale * elements */ { s3 = new RealSquareMatrix(this.extractSubMatrixData(0, 2, 0, 2)); double[] scale = s3.euclideanColumnLengths().getArray(); double scale3 = Math .exp(Math.log(scale[0] * scale[1] * scale[2]) / 3.0); s3.orthonormalize(); /** * diagonal scale matrix */ RealArray sc1 = new RealArray(3, scale3); RealSquareMatrix s = RealSquareMatrix.diagonal(sc1); s3 = s.multiply(s3); replaceSubMatrixData(0, 0, s3); } else if (option == Type.ROT_TRANS_SCALE_PERSP) { } else if (option == Type.ROT_TRANS_AXIAL_SCALE) { s3 = new RealSquareMatrix(this.extractSubMatrixData(0, 2, 0, 2)); RealArray scale = s3.euclideanColumnLengths(); s3.orthonormalize(); /** * diagonal scale matrix */ RealSquareMatrix s = RealSquareMatrix.diagonal(scale); s3 = s.multiply(s3); replaceSubMatrixData(0, 0, s3); } else if (option == Type.ANY) { /** * anything goes! */ } else if (option == Type.NULL) { } else { return 1; } trnsfrm = option; return 0; } /** * get transformation type. * * @return the type */ public Type getTransformationType() { return trnsfrm; } /** * get new matrix type. not sure what this is! * * @return the type */ public Type checkMatrix() { /** * get Top LHS (3x3 matrix) */ RealSquareMatrix s3 = new RealSquareMatrix(extractSubMatrixData(0, 2, 0, 2)); /** * and Column3 (translation) */ RealArray c3 = extractColumnData(3); if (c3 != null) { if (Real.isZero(c3.elementAt(0), Real.getEpsilon()) && Real.isZero(c3.elementAt(1), Real.getEpsilon()) && Real.isZero(c3.elementAt(2), Real.getEpsilon())) return Type.NULL; } /** no translation term */ { if (s3.isUnit()) return Type.NULL; // unit matrix if (s3.isUnitary()) return Type.ROT_ORIG; // unitary matrix } /** * translation term */ if (s3.isUnitary()) return Type.ROT_TRANS; // rot + trans; no scale /** * pure scale, no perspective */ if (s3.isOrthogonal()) { double[] scale = s3.euclideanColumnLengths().getArray(); if (Real.isEqual(scale[0], scale[1]) && Real.isEqual(scale[1], scale[2])) { return Type.ROT_TRANS_SCALE; } return Type.ROT_TRANS_AXIAL_SCALE; } return Type.ANY; } /** * interpret current matrix as rotation about general axis. user must supply * an empty axis and an empty angle, which will be filled by the routine. * will do better to create AxisAndAngle class * * @param axis * (holds return values) * @param ang * angle (holds return value) * @return flag */ public int getAxisAndAngle(Vector3 axis, Angle ang) { RealSquareMatrix s3 = new RealSquareMatrix(this.extractSubMatrixData(0, 2, 0, 2)); s3.orthonormalize(); int chirality = 1; /** * invert improper rotations */ if ((double) s3.determinant() < 0.0) { s3.negative(); chirality = -1; } double theta = Math.acos(((double) s3.trace() - 1.0) * 0.5); double[][] mat = s3.getMatrix(); double[] lmn = new double[3]; /** * theta might be exactly pi or zero */ if (Real.isEqual(theta, Math.PI) || Real.isEqual(theta, 0.0)) { lmn[0] = Math.sqrt((1.0 + mat[0][0]) * 0.5); if (Real.isZero(lmn[0], Real.getEpsilon())) { lmn[1] = mat[0][1] * 0.5 / lmn[0]; lmn[2] = mat[0][2] * 0.5 / lmn[0]; } else { lmn[1] = Math.sqrt((1.0 + mat[1][1]) * 0.5); lmn[2] = mat[1][2] / (2.0 * lmn[1]); } } else { double c = 1.0 / (2.0 * Math.sin(theta)); lmn[0] = (mat[2][1] - mat[1][2]) * c; lmn[1] = (mat[0][2] - mat[2][0]) * c; lmn[2] = (mat[1][0] - mat[0][1]) * c; } /** * stuff into angle and axis */ ang.shallowCopy(new Angle(theta)); System.arraycopy(lmn, 0, axis.getArray(), 0, 3); return chirality; } /** * get translation component. * * @return the translation */ public Vector3 getTranslation() { return new Vector3(flmat[0][3], flmat[1][3], flmat[2][3]); } /** increment translation component. * add vector to current translation * @param dt translation increment */ public void incrementTranslation(Vector3 dt) { flmat[0][3] += dt.flarray[0]; flmat[1][3] += dt.flarray[1]; flmat[2][3] += dt.flarray[2]; } /** set translation component. * * @param t translation vector */ public void setTranslation(Vector3 t) { flmat[0][3] = t.flarray[0]; flmat[1][3] = t.flarray[1]; flmat[2][3] = t.flarray[2]; } /** * get centre of rotation. if R is rotation and t is translation compute p = * ~(I - R) . t * * @return the centre */ public Point3 getCentreOfRotation() { Point3 p = new Point3(); RealSquareMatrix unit = new RealSquareMatrix(3); RealSquareMatrix temp = new RealSquareMatrix(this.extractSubMatrixData(0, 2, 0, 2)); unit = unit.subtract(temp); // (I - Rmat) unit.transpose(); RealArray t = new RealArray(getTranslation().getArray()); p = new Point3(unit.multiply(t).getArray()); // p = ~(I - R) . t return p; } /** * get scales. * * @return 3-element RealArray) */ public RealArray getScales() { RealArray scales; RealSquareMatrix s3 = new RealSquareMatrix(extractSubMatrixData(0, 2, 0, 2)); scales = s3.euclideanColumnLengths(); return scales; } /** * get Unitary matrix. eliminate scales and translation and normalize * * @return unitary 3X3 matrix */ public RealSquareMatrix getRotationMatrix() { RealSquareMatrix s; RealSquareMatrix s3 = new RealSquareMatrix(extractSubMatrixData(0, 2, 0, 2)); s3.normaliseByColumns(); s = s3; return s; } final static String[] oper = {"x", "y", "z"}; /** return operator in crystallographic form; * * @return string of type "x,-y,1/2+z" */ public String getCrystallographicString() { String s = ""; for (int irow = 0; irow < 3; irow++) { s += trans(flmat[irow][3]); for (int jcol = 0; jcol < 3; jcol++) { double f = flmat[irow][jcol]; if (f > 0.1) { s += EuclidConstants.S_PLUS+oper[jcol]; } else if (f < -0.1) { s += EuclidConstants.S_MINUS+oper[jcol]; } } if (irow < 2) { s += EuclidConstants.S_COMMA; } } return s; } private String trans(double dd) { int n = (int) Math.round(dd * 12); int d = 12; if (n % 2 == 0) { n /= 2; d /= 2; } if (n % 2 == 0) { n /= 2; d /= 2; } if (n % 3 == 0) { n /= 3; d /= 3; } String s = EuclidConstants.S_EMPTY; if (n != 0) { if (d == 1) { s = EuclidConstants.S_EMPTY+n; } else { s += EuclidConstants.S_EMPTY+n+S_SLASH+d; } } return s; } /** * check not null * * @param t transform3 */ public static void checkNotNull(Transform3 t) { if (t == null) { throw new EuclidRuntimeException("null transform"); } } } wwmm-euclid-87e8f785a814/src/main/java/org/xmlcml/euclid/Univariate.java0000644000000000000000000005604511607017524024112 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid; /** * Univariate stats. * @author (C) P. Murray-Rust, 2001, 2004 */ public class Univariate { RealArray realArray; double[] array; int count; double mean = Double.NaN; double sum = Double.NaN; double median = Double.NaN; double variance = Double.NaN; double xMax = Double.NaN; double xMin = Double.NaN; double range = Double.NaN; double stdev = Double.NaN; RealArray deviateArray = null; RealArray zValueArray = null; boolean gotMean = false; boolean gotVariance = false; boolean gotStandardDeviation = false; boolean isSorted = false; int binCount; int[] bins; // count of each bin int[] binStart; // start index of each bin double deltaX = Double.NaN; // bin step RealArray binArray = null; // lower bin values /** default constructor. */ public Univariate() { init(); realArray = new RealArray(); } /** creates from data array. * copies realArray * @param realArray the data */ public Univariate(RealArray realArray) { init(); setArray(realArray); } void init() { setBinCount(10); } /** sets data * copies realArray * @param realArray the data */ public void setArray(RealArray realArray) { this.realArray = new RealArray(realArray); getCount(); } /** set bin count. * @param binCount the number of bins */ public void setBinCount(int binCount) { this.binCount = binCount; } /** get bin count. * @return binCount (default 10) */ public int getBinCount() { return binCount; } /** get number of data points. * @return count */ public int getCount() { count = realArray.size(); return count; } /** get minimum value. * @return minimum value */ public double getMin() { xMin = realArray.smallestElement(); return xMin; } /** get maximum value. * @return maximum value */ public double getMax() { xMax = realArray.largestElement(); return xMax; } /** get mean value. * @ not enough points * @return mean value */ public double getMean() { if (!gotMean || mean == Double.NaN) { count = realArray.size(); if (count == 0) { throw new RuntimeException("No points"); } sum = realArray.sumAllElements(); mean = sum / (double) count; gotMean = true; } return mean; } /** get variance. * @ not enough points * @return variance */ public double getVariance() { if (!gotVariance) { getCount(); if (count < 2) { throw new RuntimeException("Only one point"); } getMean(); double sumx2 = 0.0; getDeviateValues(); double x[] = deviateArray.getArray(); for(int i = 0; i < count; i++) { sumx2 += x[i] * x[i]; } // variance = (sumx2 - count * mean * mean) / (double) (count - 1); variance = (sumx2) / (double) (count - 1); gotVariance = true; } return variance; } /** get standard deviation. * @ not enough points * @return standard deviation */ public double getStandardDeviation() { getVariance(); stdev = Math.sqrt(variance); return stdev; } /** get standard error. * @ not enough points * @return standard error */ public double getStandardError() { getVariance(); return(Math.sqrt(variance / (double) count)); } /** get data points. * @return the points */ public double[] getArray() { array = realArray.getArray(); return array; } /** get sorted data points. * modifies this * @return the points */ public double [] getSortedArray() { if (!isSorted) { realArray.sortAscending(); getArray(); isSorted = true; } return array; } /** get normalized values. * array transformed by subtrating mean and dividing by standard deviation. * result (the "z"-values") therefore have mean of zero and stdev of 1.0. * does not modify this. * * @ arrays too small * @return the normalized values */ public RealArray getNormalizedValues() { double[] array = realArray.getArray(); getMean(); getDeviateValues(); double[] dvArray = deviateArray.getArray(); getStandardDeviation(); double[] normArray = new double[array.length]; for (int i = 0; i < array.length; i++) { normArray[i] = (dvArray[i]) / stdev; } zValueArray = new RealArray(normArray); return zValueArray; } /** get deviate values. * array transformed by subtrating mean. * result therefore has mean of zero. * does not modify this. * * @ arrays too small * @return the deviate values */ public RealArray getDeviateValues() { double[] array = realArray.getArray(); getMean(); double[] dvArray = new double[array.length]; for (int i = 0; i < array.length; i++) { dvArray[i] = (array[i] - mean); } deviateArray = new RealArray(dvArray); return deviateArray; } /** get quantile. * @param q the value of the quantile (0 =< q =< 1.0) * @ not enough points * @return quantile */ public double getQuantile(double q) { double quantile = Double.NaN; if (q > 1.0 || q < 0.0) { throw new RuntimeException("Quantile value out of range: "+q); } getSortedArray(); // count of quantile element double dindex = (count + 1) * q; int index = (int) dindex; int flindex = (int) Math.floor(dindex); int cindex = (int) Math.ceil(dindex); // exact match if ((dindex - index) == 0) { quantile = array[index - 1]; } else { quantile = q * array[flindex - 1] + (1 - q) * array[cindex - 1]; } return quantile; } /** get median. * @ not enough points * @return median */ public double getMedian() { median = getQuantile(0.50); return median; } void calculateSummaryStats() { getMin(); getMax(); getMean(); getVariance(); getStandardDeviation(); } public RealArray getXValues() { range = realArray.getRange().getRange() + Real.getEpsilon(); deltaX = range / binCount; getMin(); binArray = new RealArray(binCount, xMin, deltaX); return binArray; } /** return bins for Histogram. * @ not enough points * @return the counts in each bin */ public int[] getHistogramCounts() { if (realArray.size() < 2) { throw new RuntimeException("Too few points"); } calculateSummaryStats(); getXValues(); getSortedArray(); bins = new int[binCount]; binStart = new int[binCount]; int lastBin = -1; for (int i = 0; i < count; i++) { double x = realArray.getArray()[i]; double diff = x - xMin; int bin = (int) (diff/deltaX); if (bin < 0) bin = 0; if (bin >= binCount) bin = binCount - 1; if (bin > lastBin) { binStart[bin] = i; lastBin = bin; } bins[bin]++; } return bins; } /** get normal parameters * * I think... * variate should be normally distributed about 1.0 with sd = 1.0 * @param count number of points * @return the normal distribution */ public static Univariate getNormalParams(int count) { double a = (count <= 10) ? 0.375 : 0.500; double[] z=new double[count]; for(int i = 0; i < count; i++) { z[i] = Univariate.qnorm((i + 1 - a)/(count + 1 - 2*a)); } return(new Univariate(new RealArray(z))); } /** percentage points of normal distribution. * upper is true. * @param p (0 <= p <= 1) * @return the percentage point (?) */ public static double qnorm(double p) { return qnorm(p, true); } /** percentage points of normal distribution. * J. D. Beasley and S. G. Springer * Algorithm AS 111: "The Percentage Points of the Normal Distribution" * Applied Statistics * @param p (0 <= p <= 1) * @param upper if true use upper half (??) * @return the percentage point (?) */ public static double qnorm(double p,boolean upper) { if(p<0 || p>1) { throw new IllegalArgumentException("Illegal argument "+p+" for qnorm(p)."); } double split=0.42, a0= 2.50662823884, a1=-18.61500062529, a2= 41.39119773534, a3=-25.44106049637, b1= -8.47351093090, b2= 23.08336743743, b3=-21.06224101826, b4= 3.13082909833, c0= -2.78718931138, c1= -2.29796479134, c2= 4.85014127135, c3= 2.32121276858, d1= 3.54388924762, d2= 1.63706781897, q=p-0.5; double r,ppnd; if(Math.abs(q)<=split) { r=q*q; ppnd=q*(((a3*r+a2)*r+a1)*r+a0)/((((b4*r+b3)*r+b2)*r+b1)*r+1); } else { r=p; if(q>0) r=1-p; if(r>0) { r=Math.sqrt(-Math.log(r)); ppnd=(((c3*r+c2)*r+c1)*r+c0)/((d2*r+d1)*r+1); if(q<0) ppnd=-ppnd; } else { ppnd=0; } } if(upper) ppnd=1-ppnd; return(ppnd); } /** percentage points of normal distribution. * J. D. Beasley and S. G. Springer * Algorithm AS 111: "The Percentage Points of the Normal Distribution" * Applied Statistics * @param p (0 <= p <= 1) * @param upper if true use upper half (??) * @param mu mean * @param sigma2 the variance(?) * @return the percentage point (?) */ public static double qnorm(double p,boolean upper,double mu,double sigma2) { return(qnorm(p,upper)*Math.sqrt(sigma2)+mu); } /** normal integral. * I. D. Hill * Algorithm AS 66: "The Normal Integral" * Applied Statistics * @param z * @param upper if true use upper half (??) * @return the integral (?) */ public static double pnorm(double z,boolean upper) { /* Reference: */ double ltone=7.0, utzero=18.66, con=1.28, a1 = 0.398942280444, a2 = 0.399903438504, a3 = 5.75885480458, a4 =29.8213557808, a5 = 2.62433121679, a6 =48.6959930692, a7 = 5.92885724438, b1 = 0.398942280385, b2 = 3.8052e-8, b3 = 1.00000615302, b4 = 3.98064794e-4, b5 = 1.986153813664, b6 = 0.151679116635, b7 = 5.29330324926, b8 = 4.8385912808, b9 =15.1508972451, b10= 0.742380924027, b11=30.789933034, b12= 3.99019417011; double y,alnorm; if(z<0) { upper=!upper; z=-z; } if(z<=ltone || upper && z<=utzero) { y=0.5*z*z; if(z>con) { alnorm=b1*Math.exp(-y)/(z-b2+b3/(z+b4+b5/(z-b6+b7/(z+b8-b9/(z+b10+b11/(z+b12)))))); } else { alnorm=0.5-z*(a1-a2*y/(y+a3-a4/(y+a5+a6/(y+a7)))); } } else { alnorm=0; } if(!upper) { alnorm=1-alnorm; } return(alnorm); } /** normal integral. * I. D. Hill * Algorithm AS 66: "The Normal Integral" * Applied Statistics * @param x * @param upper if true use upper half (??) * @param mu mean * @param sigma2 the variance(?) * @return the integral (?) */ public static double pnorm(double x,boolean upper,double mu,double sigma2) { return(pnorm((x-mu)/Math.sqrt(sigma2),upper)); } /** Student's t-quantiles. * Algorithm 396: Student's t-quantiles by * G.W. Hill CACM 13(10), 619-620, October 1970 * @param p (0 <= p <= 1) * @param ndf degrees of freedom >= 1 * @param lower_tail * @return the integral (?) */ public static double qt(double p, double ndf, boolean lower_tail) { if(p<=0 || p>=1 || ndf<1) { throw new IllegalArgumentException("Invalid p or df in call to qt(double,double,boolean)."); } double eps=1e-12; double M_PI_2=1.570796326794896619231321691640; // pi/2 boolean neg; double P,q,prob,a,b,c,d,y,x; if((lower_tail && p > 0.5) || (!lower_tail && p < 0.5)) { neg = false; P = 2 * (lower_tail ? (1 - p) : p); } else { neg = true; P = 2 * (lower_tail ? p : (1 - p)); } if(Math.abs(ndf - 2) < eps) { /* df ~= 2 */ q = Math.sqrt(2 / (P * (2 - P)) - 2); } else if (ndf < 1 + eps) { /* df ~= 1 */ prob = P * M_PI_2; q = Math.cos(prob)/Math.sin(prob); } else { /*-- usual case; including, e.g., df = 1.1 */ a = 1 / (ndf - 0.5); b = 48 / (a * a); c = ((20700 * a / b - 98) * a - 16) * a + 96.36; d = ((94.5 / (b + c) - 3) / b + 1) * Math.sqrt(a * M_PI_2) * ndf; y = Math.pow(d * P, 2 / ndf); if (y > 0.05 + a) { /* Asymptotic inverse expansion about normal */ x = qnorm(0.5 * P,false); y = x * x; if (ndf < 5) { c += 0.3 * (ndf - 4.5) * (x + 0.6); } c = (((0.05 * d * x - 5) * x - 7) * x - 2) * x + b + c; y = (((((0.4 * y + 6.3) * y + 36) * y + 94.5) / c - y - 3) / b + 1) * x; y = a * y * y; if (y > 0.002) {/* FIXME: This cutoff is machine-precision dependent*/ y = Math.exp(y) - 1; } else { /* Taylor of e^y -1 : */ y = (0.5 * y + 1) * y; } } else { y = ((1 / (((ndf + 6) / (ndf * y) - 0.089 * d - 0.822) * (ndf + 2) * 3) + 0.5 / (ndf + 4)) * y - 1) * (ndf + 1) / (ndf + 2) + 1 / y; } q = Math.sqrt(ndf * y); } if(neg) { q = -q; } return q; } /** T-test. * ALGORITHM AS 3 APPL. STATIST. (1968) VOL.17, P.189 * Computes P(T < t) * @param t * @param df degrees of freedom * @return probability (?) */ public static double pt(double t,double df) { double a,b,idf,im2,ioe,s,c,ks,fk,k; double g1=0.3183098862;// =1/pi; if(df<1) { throw new IllegalArgumentException("Illegal argument df for pt(t,df)."); } idf=df; a=t/Math.sqrt(idf); b=idf/(idf+t*t); im2=df-2; ioe=idf%2; s=1; c=1; idf=1; ks=2+ioe; fk=ks; if(im2>=2) { for(k=ks;k<=im2;k+=2) { c=c*b*(fk-1)/fk; s+=c; if(s!=idf) { idf=s; fk+=2; } } } if(ioe!=1) { return 0.5+0.5*a*Math.sqrt(b)*s; } if(df==1) { s=0; } return 0.5+(a*b*s+Math.atan(a))*g1; } /** chiSquared. * Posten, H. (1989) American Statistician 43 p. 261-265 * @param q * @param df degrees of freedom * @return chisq (?) */ public double pchisq(double q,double df) { double df2=df*.5; double q2=q*.5; int n=5,k; double tk,CFL,CFU,prob; if(q<=0 || df<=0) { throw new IllegalArgumentException("Illegal argument "+q+" or "+df+" for qnorm(p)."); } if(q1;k--) { tk=q2*(1-k-df2)/(df2+2*k-1+k*q2/(df2+2*k+tk)); } CFL=1-q2/(df2+1+q2/(df2+2+tk)); prob=Math.exp(df2*Math.log(q2)-q2-lnfgamma(df2+1)-Math.log(CFL)); } else { tk=(n-df2)/(q2+n); for(k=n-1;k>1;k--) { tk=(k-df2)/(q2+k/(1+tk)); } CFU=1+(1-df2)/(q2+1/(1+tk)); prob=1-Math.exp((df2-1)*Math.log(q2)-q2-lnfgamma(df2)-Math.log(CFU)); } return prob; } /** betainv * ALGORITHM AS 63 APPL. STATIST. VOL.32, NO.1 * Computes P(Beta>x) * @param x * @param p * @param q * @return betainv (?) */ public static double betainv(double x,double p,double q) { double beta=lnfbeta(p,q),acu=1E-14; double cx,psq,pp,qq,x2,term,ai,betain,ns,rx,temp; boolean indx; if(p<=0 || q<=0) { return(-1.0); } if(x<=0 || x>=1) { return(-1.0); } psq=p+q; cx=1-x; if(pacu && temp>acu*betain) { term=term*temp*rx/(pp+ai); betain=betain+term; temp=Math.abs(term); if(temp>acu && temp>acu*betain) { ai++; ns--; if(ns>=0) { temp=qq-ai; if(ns==0) rx=x2; } else { temp=psq; psq+=1; } } } betain*=Math.exp(pp*Math.log(x2)+(qq-1)*Math.log(cx)-beta)/pp; if(indx) betain=1-betain; return(betain); } /** betainv * ALGORITHM AS 63 APPL. STATIST. VOL.32, NO.1 * Computes P(F>x) * @param x * @param df1 * @param df2 * @return (?) */ public static double pf(double x,double df1,double df2) { return(betainv(df1*x/(df1*x+df2),0.5*df1,0.5*df2)); } public static void test() { Util.println( "--------------Testing Univariate--------------\n"); RandomNumberGenerator rng = new RandomNumberGenerator(); int npoints1 = 1000; double[] data1 = new double[npoints1]; for (int i = 0; i < npoints1; i++) { data1[i] = rng.nextGaussian(); } RealArray dataArray1 = new RealArray(data1); Univariate univ1 = new Univariate(dataArray1); Util.println("mean: "+univ1.getMean()); Util.println("sdev: "+univ1.getStandardDeviation()); int npoints2 = 300; double[] data2 = new double[npoints2]; for (int i = 0; i < npoints2; i++) { data2[i] = rng.nextGaussian()*0.5 + 5.0; } RealArray dataArray2 = new RealArray(data2); Univariate univ2 = new Univariate(dataArray2); Util.println("mean: "+univ2.getMean()); Util.println("sdev: "+univ2.getStandardDeviation()); dataArray1.addArray(dataArray2); Univariate univ3 = new Univariate(dataArray1); Util.println("mean: "+univ3.getMean()); Util.println("sdev: "+univ3.getStandardDeviation()); Util.println("min: "+univ3.getMin()); Util.println("q1: "+univ3.getQuantile(0.25)); Util.println("median: "+univ3.getMedian()); Util.println("q3: "+univ3.getQuantile(0.75)); Util.println("max: "+univ3.getMax()); univ3.setBinCount(30); int[] bins = univ3.getHistogramCounts(); for (int i = 0; i < bins.length; i++) { Util.println("bin: "+bins[i]); } Univariate norm = Univariate.getNormalParams(1000); Util.println("mean: "+norm.getMean()); Util.println("sdev: "+norm.getStandardDeviation()); Util.println("min: "+norm.getMin()); Util.println("q1: "+norm.getQuantile(0.25)); Util.println("median: "+norm.getMedian()); Util.println("q3: "+norm.getQuantile(0.75)); Util.println("max: "+norm.getMax()); } public static double lnfgamma(double c) { int j; double x,y,tmp,ser; double [] cof = { 76.18009172947146 ,-86.50532032941677 , 24.01409824083091 ,-1.231739572450155 , 0.1208650973866179e-2,-0.5395239384953e-5}; y = x = c; tmp = x + 5.5 - (x + 0.5) * Math.log(x + 5.5); ser = 1.000000000190015; for (j=0; j<=5; j++) { ser += (cof[j] / ++y); } return(Math.log(2.5066282746310005 * ser / x) - tmp); } public static double lnfbeta(double a,double b) { return(lnfgamma(a)+lnfgamma(b)-lnfgamma(a+b)); } public static double fbeta(double a,double b) { return Math.exp(lnfbeta(a,b)); } public static double fgamma(double c) { return Math.exp(lnfgamma(c)); } public static double fact (int n) { return Math.exp(lnfgamma(n+1)); } public static double lnfact(int n) { return lnfgamma(n+1); } public static double nCr(int n,int r) { return Math.exp(lnfact(n)-lnfact(r)-lnfact(n-r)); } public static double nPr(int n,int r) { return Math.exp(lnfact(n)-lnfact(r)); } public static void main(String[] args) { test(); } } wwmm-euclid-87e8f785a814/src/main/java/org/xmlcml/euclid/Util.java0000644000000000000000000023104311607017524022711 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.DataInputStream; import java.io.EOFException; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URISyntaxException; import java.net.URL; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.text.NumberFormat; import java.text.ParseException; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Enumeration; import java.util.HashMap; import java.util.Hashtable; import java.util.List; import java.util.Map; import java.util.StringTokenizer; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.commons.io.IOUtils; import org.apache.log4j.Logger; /** * A number of miscellaneous tools. Originally devised for jumbo.sgml, now * rewritten for jumbo.xml. Use these at your peril - some will be phased out * * @author (C) P. Murray-Rust, 1998 * @author 20 August 2003 */ public class Util implements EuclidConstants { /** messages */ public enum Message { /** not yet implemented */ NYI("not yet implemented"), ; /** value */ public String value; private Message(String v) { value = v; } } final static Logger logger = Logger.getLogger(Util.class.getName()); public final static String[] LOWER_ROMAN_NUMERAL = { "i", "ii", "iii", "iv", "v", "vi", "vii", "viii", "ix", "x", "xi", "xii", "xiii", "xiv", "xv", "xvi", "xvii", "xviii", "xix", "xx", "xxi", "xxii", "xxiii", "xxiv", "xxv", "xxvi", "xxvii", "xxviii", "xxix", "xxx", "xxxi", "xxxii", "xxxiii", "xxxiv", "xxxv", "xxxvi", "xxxvii", "xxxviii", "xxxix", "xl", "xli", "xlii", "xliii", "xliv", "xlv", "xlvi", "xlvii", "xlviii", "xlix", "l", }; /** * regex matching roman numbers up to m ("[ivxlcdm]+"). */ public final static String LOWER_ROMAN_REGEX = "[ivxlcdm]+"; /** * regex matching roman numbers up to M ("[IVXLCDM]+"). */ public final static String UPPER_ROMAN_REGEX = "[IVXLCDM]+"; private final static File TEMP_DIRECTORY = new File("target" + File.separator + "test-outputs"); /** * get temporary directory - mainly for testing methods with outputs. calls * mkdirs() if does not exist * * @return temporary directory. */ public static File getTEMP_DIRECTORY() { if (!TEMP_DIRECTORY.exists()) { boolean ok = TEMP_DIRECTORY.mkdirs(); if (!ok) { throw new RuntimeException( "Cannot create temporary directory : " + TEMP_DIRECTORY.getAbsolutePath()); } } return TEMP_DIRECTORY; } /** * get class-specific temporary directory - mainly for testing methods with * ouputs. calls mkdirs() if does not exist * * @param classx * @return temporary directory. */ public static File getTestOutputDirectory(Class classx) { File tempDir = getTEMP_DIRECTORY(); String dirs = classx.getName().replace(S_PERIOD, File.separator); File testDir = new File(tempDir, dirs); if (!testDir.exists()) { boolean ok = testDir.mkdirs(); if (!ok) { throw new RuntimeException( "Cannot create temporary class directory : " + testDir.getAbsolutePath()); } } return testDir; } /** * convenience method to extend array of Strings. * * @param array * to extend * @param s * element to add * @return extended array */ public final static String[] addElementToStringArray(String[] array, String s) { int l = array.length; String[] array1 = new String[l + 1]; for (int i = 0; i < l; i++) { array1[i] = array[i]; } array1[l] = s; return array1; } /** * convenience method to remove element from array of Strings. * * Removes ALL occurrences of string * * @param array * to edit * @param s * element to remove * @return depleted array */ public final static String[] removeElementFromStringArray(String[] array, String s) { List sList = new ArrayList(); for (int i = 0; i < array.length; i++) { if (!array[i].equals(s)) { sList.add(array[i]); } } return (String[]) sList.toArray(new String[0]); } /** * traps a bug. use for programming errors where this could can "never be * reached" concatenates msg with "BUG" and throws {@link RuntimeException} * * @param msg * @param e */ public static void BUG(String msg, Exception e) { msg = (msg == null || msg.trim().length() == 0) ? EC.S_EMPTY : EC.S_LBRAK + msg + EC.S_RBRAK; throw new RuntimeException("BUG: " + msg + "should never throw: " + e, e); } /** * traps a bug. empty message. * * @see #BUG(String, Throwable) * @param e */ public static void BUG(Exception e) { BUG(S_EMPTY, e); } /** * convenience method for "not yet implemented". deliberately deprecated so * that it requires deprecated on all modules containing NYI * * @deprecated * @throws RuntimeException */ public static void throwNYI() { throw new RuntimeException(Message.NYI.value); } /** * traps a bug. * * @see #BUG(String, Throwable) * @param msg */ public static void BUG(String msg) { BUG(msg, new RuntimeException()); } /** * convenience method to get input stream from resource. the resource is * packaged with the classes for distribution. typical filename is * org/xmlcml/molutil/elementdata.xml for file elementdata.xml in class * hierarchy org.xmlcml.molutil * * @param filename * relative to current class hierarchy. * @return input stream * @throws IOException */ public static InputStream getInputStreamFromResource(String filename) throws IOException { return getResource(filename).openStream(); } /** * creates directories and files if they don't exist. creates dir/filename * * @param dir * @param filename * @throws IOException */ public static void createFile(File dir, String filename) throws IOException { File file = new File(dir + File.separator + filename); if (!dir.exists()) { boolean ok = dir.mkdirs(); if (!ok) { throw new IOException("cannot make dictories: " + dir + EC.S_SPACE + filename); } } if (!file.exists()) { file.createNewFile(); } } /** * creates resource from filename. uses ClassLoader.getResource() * * @param filename * name relative to classroot * @return url or null */ public static URL getResource(String filename) { URL url = null; if (filename != null) { ClassLoader l = Util.class.getClassLoader(); url = l.getResource(filename); if (url == null) { throw new RuntimeException("No resource with name " + filename); } } return url; } public static InputStream getResourceUsingContextClassLoader(String name, Class clazz) throws FileNotFoundException { ClassLoader cl = Thread.currentThread().getContextClassLoader(); if (cl == null) { cl = clazz.getClassLoader(); } InputStream is = cl.getResourceAsStream(name); if (is == null) { throw new FileNotFoundException("Resource not found: "+name); } return is; } /** * gets file from build path components. pm286 is not quite sure how it does * this... * * @author ojd20@cam.ac.uk * @param path * @return file or null * @throws URISyntaxException */ public static File getResourceFile(String... path) throws URISyntaxException { File f = new File(Util.class.getClassLoader().getResource( buildPath(path)).toURI()); return f; } /** * gets build path from its components. * * @param parts * @return build path concatenated with File.separatorChar */ public static String buildPath(String... parts) { StringBuilder sb = new StringBuilder(parts.length * 20); for (String part : parts) { sb.append(part).append(File.separatorChar); } sb.deleteCharAt(sb.length() - 1); return sb.toString(); } /** * delete a file If directory==true then file will be recursively deleted * * @param file * Description of the Parameter * @param deleteDirectory * Description of the Parameter * @return Description of the Return Value */ public static boolean deleteFile(File file, boolean deleteDirectory) { if (file.exists()) { if (file.isDirectory() && deleteDirectory) { String[] filenames = file.list(); for (int i = 0; i < filenames.length; i++) { File childFile = new File(file.toString() + File.separator + filenames[i]); deleteFile(childFile, deleteDirectory); } } return file.delete(); } else { return false; } } /** * copy one file to another (I suspect there is a better way * * @param inFile * Description of the Parameter * @param outFile * Description of the Parameter * @exception FileNotFoundException * Description of the Exception * @exception IOException * Description of the Exception */ public static void copyFile(File inFile, File outFile) throws FileNotFoundException, IOException { BufferedInputStream bis = new BufferedInputStream(new FileInputStream( inFile)); BufferedOutputStream bos = new BufferedOutputStream( new FileOutputStream(outFile)); byte[] buffer = new byte[10000]; while (true) { int b = bis.read(buffer); if (b == -1) { break; } bos.write(buffer, 0, b); } bis.close(); bos.close(); } /** * reads a stream from url and outputs it as integer values of the * characters and as strings. Emulates UNIX od(). * * @param url * Description of the Parameter * @return String tabular version of input (in 10-column chunks) * @exception Exception * Description of the Exception */ public static String dump(URL url) throws Exception { BufferedReader br = new BufferedReader(new InputStreamReader(url .openStream())); int count = 0; StringBuffer sb = new StringBuffer(); String s0 = "\n"; String s1 = EC.S_EMPTY; while (true) { int i = br.read(); if (i == -1) { break; } String s = " " + i; while (s.length() > 4) { s = s.substring(1); } s0 += s; if (i >= 32 && i < 128) { s1 += (char) i; } else { s1 += EC.S_SPACE; } if (++count % 10 == 0) { sb.append(s0 + " " + s1); s1 = EC.S_EMPTY; s0 = "\n"; } } if (count != 0) { sb.append(s0 + " " + s1); } return sb.toString(); } /** * make a String of a given number of spaces * * @param nspace * Description of the Parameter * @return Description of the Return Value */ public static String spaces(int nspace) { if (nspace <= 0) { return EC.S_EMPTY; } else { StringBuffer sb = new StringBuffer(); for (int i = 0; i < nspace; i++) { sb.append(S_SPACE); } return sb.toString(); } } /** * * gets suffix from filename * * * * @param filename * Description of the Parameter * * @return The suffix value * */ public static String getSuffix(String filename) { int idx = filename.lastIndexOf(Util.S_PERIOD); if (idx == -1) { return null; } return filename.substring(idx + 1, filename.length()); } /** * return the first n characters of a string and add ellipses if truncated * * @param s * @param maxlength * @return String the (possibly) truncated string */ public static String truncateAndAddEllipsis(String s, int maxlength) { if (s != null) { int l = s.length(); s = (l <= maxlength) ? s : s.substring(0, maxlength) + " ... "; } return s; } /** * return the first n characters of a string and add ellipses if truncated * * @param s * @param maxlength * @return String the (possibly) truncated string */ public static String truncateAndAddNewlinesAndEllipsis(String s, int maxlength) { return (s == null) ? null : truncateAndAddEllipsis(s.replace(S_NEWLINE, "\\n"), maxlength); } /** * remove balanced quotes from ends of (trimmed) string, else no action * * @param s * Description of the Parameter * @return Description of the Return Value */ public static String deQuote(String s) { if (s == null) { return null; } String ss = s.trim(); if (ss.equals(S_EMPTY)) { return ss; } char c = ss.charAt(0); if (c == '"' || c == '\'') { int l = ss.length(); if (ss.charAt(l - 1) == c) { return ss.substring(1, l - 1); } } return s; } /** * remove trailing blanks * * @param s * Description of the Parameter * @return Description of the Return Value */ public static String rightTrim(String s) { if (s == null) { return null; } if (s.trim().equals(S_EMPTY)) { return EC.S_EMPTY; } int l = s.length(); while (l >= 0) { if (!Character.isWhitespace(s.charAt(--l))) { l++; break; } } return s.substring(0, l); } /** * remove leading blanks * * @param s * Description of the Parameter * @return Description of the Return Value */ public static String leftTrim(String s) { if (s == null) { return null; } if (s.trim().equals(S_EMPTY)) { return EC.S_EMPTY; } int l = s.length(); for (int i = 0; i < l; i++) { if (s.charAt(i) != ' ') { return s.substring(i); } } return s; } /** * return index of balanced bracket. String MUST start with a generic LH * bracket (e.g. '{', '<', '(' '[') * * @param lbrack * starting character * @param s * string to search * @return index of bracket or -1 if none */ public static int indexOfBalancedBracket(char lbrack, String s) { if (s == null) { return -1; } if (s.charAt(0) != lbrack) { return -1; } char rbrack = ' '; if (lbrack == '(') { rbrack = ')'; } else if (lbrack == '<') { rbrack = '>'; } else if (lbrack == '[') { rbrack = ']'; } else if (lbrack == '{') { rbrack = '}'; } int l = s.length(); int i = 0; int level = 0; while (i < l) { if (s.charAt(i) == lbrack) { level++; } else if (s.charAt(i) == rbrack) { level--; if (level == 0) { return i; } } i++; } return -1; } /** * parse comma-separated Strings Note fields can be EC.S_EMPTY (as in ,,,) and * fields can be quoted "...". If so, embedded quotes are represented as * EC.S_EMPTY, for example A," this is a EC.S_EMPTYBS_EMPTY character",C. An * unbalanced quote returns a mess * * @param s * Description of the Parameter * @return List the vector of Strings - any error returns null * @exception RuntimeException * missing quote */ public static List getCommaSeparatedStrings(String s) throws RuntimeException { if (s == null) { return null; } String s0 = s; s = s.trim(); List v = new ArrayList(); while (!s.equals(S_EMPTY)) { if (s.startsWith(S_QUOT)) { String temp = EC.S_EMPTY; s = s.substring(1); while (true) { int idx = s.indexOf(S_QUOT); if (idx == -1) { throw new RuntimeException("Missing Quote:" + s0 + EC.S_COLON); } int idx2 = s.indexOf(S_QUOT + EC.S_QUOT); // next quote is actually EC.S_EMPTY if (idx2 == idx) { temp += s.substring(0, idx) + EC.S_QUOT; s = s.substring(idx + 2); // single quote } else { temp += s.substring(0, idx); s = s.substring(idx + 1); break; } } v.add(temp); if (s.startsWith(S_COMMA)) { s = s.substring(1); } else if (s.equals(S_EMPTY)) { } else { throw new RuntimeException("Unbalanced Quotes:" + s0 + EC.S_COLON); } } else { int idx = s.indexOf(S_COMMA); // end? if (idx == -1) { v.add(s); break; } else { // another comma String temp = s.substring(0, idx); v.add(temp); s = s.substring(idx + 1); if (s.equals(S_EMPTY)) { v.add(s); break; } } } } return v; } /** * create comma-separated Strings fields include a comma or a " they are * wrapped with quotes ("). Note fields can be EC.S_EMPTY (as in ,,,) and * fields can be quoted "...". If so, embedded quotes are represented as * EC.S_EMPTY, for example A," this is a EC.S_EMPTYBS_EMPTY character",C. * * @param v * vector of strings to be concatenated (null returns null) * @return String the concatenated string - any error returns null */ public static String createCommaSeparatedStrings(List v) { if (v == null) { return null; } StringBuffer sb = new StringBuffer(); for (int i = 0; i < v.size(); i++) { String s = v.get(i).toString(); s = Util.substituteStrings(s, new String[] { EC.S_QUOT }, new String[] { EC.S_QUOT + EC.S_QUOT }); // wrap in quotes to escape comma or other quotes if (s.indexOf(S_COMMA) != -1 || s.indexOf(S_QUOT) != -1) { s = EC.S_QUOT + s + EC.S_QUOT; } if (i > 0) { sb.append(S_COMMA); } sb.append(s); } return sb.toString(); } /** * concatenate strings into quote-separated string * * @param s * Description of the Parameter * @return String concatenated string */ public static String quoteConcatenate(String[] s) { StringBuffer sb = new StringBuffer(); for (int i = 0; i < s.length; i++) { if (i > 0) { sb.append(S_SPACE); } boolean quote = false; if (s[i].indexOf(S_SPACE) != -1) { sb.append(S_QUOT); quote = true; } sb.append(s[i]); if (quote) { sb.append(S_QUOT); } } return sb.toString(); } /** * get the index of a String in an array * * @param string * Description of the Parameter * @param strings * Description of the Parameter * @param ignoreCase * ignore case * @return index of string else -1 if not found */ public static int indexOf(String string, String[] strings, boolean ignoreCase) { if (string == null || strings == null) { return -1; } for (int i = 0; i < strings.length; i++) { if (ignoreCase) { if (string.equalsIgnoreCase(strings[i])) { return i; } } else { if (string.equals(strings[i])) { return i; } } } return -1; } /** * remove balanced (well-formed) markup from a string. Crude (that is not * fully XML-compliant);
Example: "This is <A * HREF="foo">bar</A> and </BR> a break" goes to "This is bar * and a break" * * @param s * Description of the Parameter * @return Description of the Return Value */ public static String removeHTML(String s) { StringBuilder sb = new StringBuilder(); while (true) { int idx = s.indexOf("<"); if (idx == -1) { sb.append(s); break; } else { sb.append(s.substring(0, idx)); s = s.substring(idx); idx = s.indexOf('>'); if (idx == -1) { throw new RuntimeException("missing >"); } else { s = s.substring(idx + 1); } } } return sb.toString(); } /** * * Warning message - nothing fancy at present * * * * @param s * Description of the Parameter * */ public static void warning(String s) { logger.info("WARNING: " + s); } /** * * message - nothing fancy at present * * * * @param s * Description of the Parameter * */ public static void message(String s) { logger.info(s); } // static jumbo.xml.gui.XText errorText; /** * * Error message - nothing fancy at present. Display in Text frame * * * * @param s * Description of the Parameter * */ public static void error(String s) { // if (errorText == null) { // errorText = new jumbo.xml.gui.XText(); // errorText.displayInFrame(); // } logger.info("ERROR: " + s); // errorText.addText(s); } /** * * record that we have hit a program bug!!! * * * * @param s * Description of the Parameter * */ // public static void bug(String s) { // bug(new Exception(s)); // } /** * traps a bug. use for programming errors where this could can "never be * reached" concatenates msg with "BUG" and throws {@link RuntimeException} * * @param msg * @param t */ public static void BUG(String msg, Throwable t) { msg = (msg == null || msg.trim().length() == 0) ? EC.S_EMPTY : EC.S_LBRAK + msg + EC.S_RBRAK; throw new RuntimeException("BUG: " + msg + "should never throw", t); } /** * traps a bug. empty message. * * @see #BUG(String, Throwable) * @param t */ public static void BUG(Throwable t) { BUG(S_EMPTY, t); } /** file separator. */ final static String FS = System.getProperty("file.separator"); /** * * create new file, including making directory if required This seems to be * * a mess - f.createNewFile() doesn't seem to work A directory should have * * a trailing file.separator * * * * @param fileName * Description of the Parameter * * @return Description of the Return Value * * @exception IOException * Description of the Exception * */ // public static File createNewFile(String fileName) throws IOException { // File f = null; // String path = null; // int idx = fileName.lastIndexOf(FS); // if (idx != -1) { // path = fileName.substring(0, idx); // // fileN = fileName.substring(idx+1); // } // // try { // if (path != null) { // f = new File(path); // f.mkdirs(); // } // if (!fileName.endsWith(FS)) { // f = new File(fileName); // } // // } catch (IOException e) { // // logger.info("Failed to create: "+fileName+S_LBRAK+e+S_RBRAK); // // } // return f; // } /** * get current directory * * @return The pWDName value */ public static String getPWDName() { File f = new File(S_PERIOD); return new File(f.getAbsolutePath()).getParent(); } /** * create new file, including making directory if required This seems to be * a mess - f.createNewFile() doesn't seem to work A directory should have a * trailing file.separator * * @param fileName * @return file * * @exception IOException */ public static File createNewFile(String fileName) throws IOException { File f = null; String path = null; int idx = fileName.lastIndexOf(FS); if (idx != -1) { path = fileName.substring(0, idx); } if (path != null) { f = new File(path); f.mkdirs(); } if (!fileName.endsWith(FS)) { f = new File(fileName); } return f; } /** * * make substitutions in a string. If oldSubtrings = "A" and newSubstrings = * "aa" then count occurrences of "A" in s are replaced with "aa", etc. * * "AAA" count=2 would be replaced by "aaaaA" * * @param s * @param oldSubstring * @param newSubstring * @param count * @return new string * */ public static String substituteString(String s, String oldSubstring, String newSubstring, int count) { if (count <= 0) { count = Integer.MAX_VALUE; } StringBuffer sb = new StringBuffer(); int lo = oldSubstring.length(); for (int i = 0; i < count; i++) { int idx = s.indexOf(oldSubstring); if (idx == -1) { break; } sb.append(s.substring(0, idx)); sb.append(newSubstring); s = s.substring(idx + lo); } sb.append(s); return sb.toString(); } /** * make substitutions in a string. If oldSubtrings = {"A", "BB", "C"} and * newSubstrings = {"aa", "b", "zz"} then every occurrence of "A" in s is * * replaced with "aa", etc. "BBB" would be replaced by "bB" * * @param s * @param oldSubstrings * @param newSubstrings * * @return Description of the Return Value * @throws RuntimeException */ public static String substituteStrings(String s, String[] oldSubstrings, String[] newSubstrings) { int ol = oldSubstrings.length; int nl = newSubstrings.length; if (ol != nl) { throw new RuntimeException( "Util.substituteStrings arguments of different lengths: " + ol + EC.S_SLASH + nl); } for (int i = 0; i < ol; i++) { String oldS = oldSubstrings[i]; String newS = newSubstrings[i]; int lo = oldS.length(); if (s.indexOf(oldS) == -1) { continue; } String ss = EC.S_EMPTY; while (true) { int idx = s.indexOf(oldS); if (idx == -1) { ss += s; break; } ss += s.substring(0, idx) + newS; s = s.substring(idx + lo); } s = ss; } return s; } /** * * substitute characters with =Hex values. Thus "=2E" is translated to * * char(46); A trailing EQUALS (continuation line is not affected, nor is * * any non-hex value * * * */ static String[] dosEquivalents = { EC.S_EMPTY + (char) 12, // ?? S_EMPTY + (char) 127, // ?? S_EMPTY + (char) 128, // Ccedil S_EMPTY + (char) 129, // uuml S_EMPTY + (char) 130, // eacute S_EMPTY + (char) 131, // acirc S_EMPTY + (char) 132, // auml S_EMPTY + (char) 133, // agrave S_EMPTY + (char) 134, // aring S_EMPTY + (char) 135, // ccedil S_EMPTY + (char) 136, // ecirc S_EMPTY + (char) 137, // euml S_EMPTY + (char) 138, // egrave S_EMPTY + (char) 139, // iuml S_EMPTY + (char) 140, // icirc S_EMPTY + (char) 141, // igrave S_EMPTY + (char) 142, // Auml S_EMPTY + (char) 143, // Aring S_EMPTY + (char) 144, // Eacute S_EMPTY + (char) 145, // aelig S_EMPTY + (char) 146, // ff? S_EMPTY + (char) 147, // ocirc S_EMPTY + (char) 148, // ouml S_EMPTY + (char) 149, // ograve S_EMPTY + (char) 150, // ucirc S_EMPTY + (char) 151, // ugrave S_EMPTY + (char) 152, // yuml S_EMPTY + (char) 153, // Ouml S_EMPTY + (char) 154, // Uuml S_EMPTY + (char) 155, // ?? S_EMPTY + (char) 156, // ?? S_EMPTY + (char) 157, // ?? S_EMPTY + (char) 158, // ?? S_EMPTY + (char) 159, // ?? S_EMPTY + (char) 160, // aacute S_EMPTY + (char) 161, // iacute S_EMPTY + (char) 162, // oacute S_EMPTY + (char) 163, // uacute S_EMPTY + (char) 164, // nwave? S_EMPTY + (char) 165, // Nwave? S_EMPTY + (char) 166, // ?? S_EMPTY + (char) 167, // ?? S_EMPTY + (char) 168, // ?? S_EMPTY + (char) 169, // ?? S_EMPTY + (char) 170, // 170 S_EMPTY + (char) 171, // ?? S_EMPTY + (char) 172, // ?? S_EMPTY + (char) 173, // ?? S_EMPTY + (char) 174, // ?? S_EMPTY + (char) 175, // ?? S_EMPTY + (char) 176, // ?? S_EMPTY + (char) 177, // ?? S_EMPTY + (char) 178, // ?? S_EMPTY + (char) 179, // ?? S_EMPTY + (char) 180, // 180 // S_EMPTY + (char) 192, // eacute S_EMPTY + (char) 248, // degrees S_EMPTY + (char) 352, // egrave S_EMPTY + (char) 402, // acirc S_EMPTY + (char) 710, // ecirc S_EMPTY + (char) 8218, // eacute S_EMPTY + (char) 8221, // ouml S_EMPTY + (char) 8222, // auml S_EMPTY + (char) 8225, // ccedil S_EMPTY + (char) 8230, // agrave S_EMPTY + (char) 8240, // euml S_EMPTY + (char) 65533, // uuml }; static String[] asciiEquivalents = { EC.S_EMPTY, // ?? S_EMPTY + (char) 0, // ?? S_EMPTY + (char) 199, // Ccedil S_EMPTY + (char) 252, // uuml S_EMPTY + (char) 233, // eacute S_EMPTY + (char) 226, // acirc S_EMPTY + (char) 228, // auml S_EMPTY + (char) 224, // agrave S_EMPTY + (char) 229, // aring S_EMPTY + (char) 231, // ccedil S_EMPTY + (char) 234, // ecirc S_EMPTY + (char) 235, // euml S_EMPTY + (char) 232, // egrave S_EMPTY + (char) 239, // iuml S_EMPTY + (char) 238, // icirc S_EMPTY + (char) 236, // igrave S_EMPTY + (char) 196, // Auml S_EMPTY + (char) 197, // Aring S_EMPTY + (char) 201, // Eacute S_EMPTY + (char) 230, // aelig S_EMPTY + (char) 0, // ff? S_EMPTY + (char) 244, // ocirc S_EMPTY + (char) 246, // ouml S_EMPTY + (char) 242, // ograve S_EMPTY + (char) 251, // ucirc S_EMPTY + (char) 249, // ugrave S_EMPTY + (char) 255, // yuml S_EMPTY + (char) 214, // Ouml S_EMPTY + (char) 220, // Uuml S_EMPTY + (char) 0, // ff? S_EMPTY + (char) 0, // ff? S_EMPTY + (char) 0, // ff? S_EMPTY + (char) 0, // ff? S_EMPTY + (char) 0, // ff? S_EMPTY + (char) 225, // aacute S_EMPTY + (char) 237, // iacute S_EMPTY + (char) 243, // oacute S_EMPTY + (char) 250, // uacute S_EMPTY + (char) 241, // nwave? S_EMPTY + (char) 209, // Nwave? S_EMPTY + (char) 0, // ?? S_EMPTY + (char) 0, // ?? S_EMPTY + (char) 0, // ?? S_EMPTY + (char) 0, // ?? S_EMPTY + (char) 0, // 170 S_EMPTY + (char) 0, // ?? S_EMPTY + (char) 0, // ?? S_EMPTY + (char) 0, // ?? S_EMPTY + (char) 0, // ?? S_EMPTY + (char) 0, // ?? S_EMPTY + (char) 0, // ?? S_EMPTY + (char) 0, // ?? S_EMPTY + (char) 0, // ?? S_EMPTY + (char) 0, // ?? S_EMPTY + (char) 0, // 180 // S_EMPTY + (char) 233, // eacute "[degrees]", // degrees S_EMPTY + (char) 232, // egrave S_EMPTY + (char) 226, // acirc S_EMPTY + (char) 234, // ecirc S_EMPTY + (char) 233, // eacute S_EMPTY + (char) 246, // ouml S_EMPTY + (char) 228, // auml S_EMPTY + (char) 231, // ccedil S_EMPTY + (char) 224, // agrave S_EMPTY + (char) 235, // euml S_EMPTY + (char) 252, // uuml }; /** * isolatin entities */ public final static String[] ISOLATIN_ENTITIES = new String[256]; /** */ public final static int ISOLATIN_LO = 160; /** */ public final static int ISOLATIN_HI = 255; static { // ones before 160 are null ISOLATIN_ENTITIES[160] = "_nbsp_"; ISOLATIN_ENTITIES[161] = "_iexcl_"; ISOLATIN_ENTITIES[162] = "_cent_"; ISOLATIN_ENTITIES[163] = "_pound_"; ISOLATIN_ENTITIES[164] = "_curren_"; ISOLATIN_ENTITIES[165] = "_yen_"; ISOLATIN_ENTITIES[166] = "_brvbar_"; ISOLATIN_ENTITIES[167] = "_sect_"; ISOLATIN_ENTITIES[168] = "_uml_"; ISOLATIN_ENTITIES[169] = "_copy_"; ISOLATIN_ENTITIES[170] = "_ordf_"; ISOLATIN_ENTITIES[171] = "_laquo_"; ISOLATIN_ENTITIES[172] = "_not_"; ISOLATIN_ENTITIES[173] = "_shy_"; ISOLATIN_ENTITIES[174] = "_reg_"; ISOLATIN_ENTITIES[175] = "_macr_"; ISOLATIN_ENTITIES[176] = "_deg_"; ISOLATIN_ENTITIES[177] = "_plusmn_"; ISOLATIN_ENTITIES[178] = "_sup2_"; ISOLATIN_ENTITIES[179] = "_sup3_"; ISOLATIN_ENTITIES[180] = "_acute_"; ISOLATIN_ENTITIES[181] = "_micro_"; ISOLATIN_ENTITIES[182] = "_para_"; ISOLATIN_ENTITIES[183] = "_middot_"; ISOLATIN_ENTITIES[184] = "_cedil_"; ISOLATIN_ENTITIES[185] = "_sup1_"; ISOLATIN_ENTITIES[186] = "_ordm_"; ISOLATIN_ENTITIES[187] = "_raquo_"; ISOLATIN_ENTITIES[188] = "_frac14_"; ISOLATIN_ENTITIES[189] = "_frac12_"; ISOLATIN_ENTITIES[190] = "_frac34_"; ISOLATIN_ENTITIES[191] = "_iquest_"; ISOLATIN_ENTITIES[192] = "_Agrave_"; ISOLATIN_ENTITIES[193] = "_Aacute_"; ISOLATIN_ENTITIES[194] = "_Acirc_"; ISOLATIN_ENTITIES[195] = "_Atilde_"; ISOLATIN_ENTITIES[196] = "_Auml_"; ISOLATIN_ENTITIES[197] = "_Aring_"; ISOLATIN_ENTITIES[198] = "_AElig_"; ISOLATIN_ENTITIES[199] = "_Ccedil_"; ISOLATIN_ENTITIES[200] = "_Egrave_"; ISOLATIN_ENTITIES[201] = "_Eacute_"; ISOLATIN_ENTITIES[202] = "_Ecirc_"; ISOLATIN_ENTITIES[203] = "_Euml_"; ISOLATIN_ENTITIES[204] = "_Igrave_"; ISOLATIN_ENTITIES[205] = "_Iacute_"; ISOLATIN_ENTITIES[206] = "_Icirc_"; ISOLATIN_ENTITIES[207] = "_Iuml_"; ISOLATIN_ENTITIES[208] = "_ETH_"; ISOLATIN_ENTITIES[209] = "_Ntilde_"; ISOLATIN_ENTITIES[210] = "_Ograve_"; ISOLATIN_ENTITIES[211] = "_Oacute_"; ISOLATIN_ENTITIES[212] = "_Ocirc_"; ISOLATIN_ENTITIES[213] = "_Otilde_"; ISOLATIN_ENTITIES[214] = "_Ouml_"; ISOLATIN_ENTITIES[215] = "_times_"; ISOLATIN_ENTITIES[216] = "_Oslash_"; ISOLATIN_ENTITIES[217] = "_Ugrave_"; ISOLATIN_ENTITIES[218] = "_Uacute_"; ISOLATIN_ENTITIES[219] = "_Ucirc_"; ISOLATIN_ENTITIES[220] = "_Uuml_"; ISOLATIN_ENTITIES[221] = "_Yacute_"; ISOLATIN_ENTITIES[222] = "_THORN_"; ISOLATIN_ENTITIES[223] = "_szlig_"; ISOLATIN_ENTITIES[224] = "_agrave_"; ISOLATIN_ENTITIES[225] = "_aacute_"; ISOLATIN_ENTITIES[226] = "_acirc_"; ISOLATIN_ENTITIES[227] = "_atilde_"; ISOLATIN_ENTITIES[228] = "_auml_"; ISOLATIN_ENTITIES[229] = "_aring_"; ISOLATIN_ENTITIES[230] = "_aelig_"; ISOLATIN_ENTITIES[231] = "_ccedil_"; ISOLATIN_ENTITIES[232] = "_egrave_"; ISOLATIN_ENTITIES[233] = "_eacute_"; ISOLATIN_ENTITIES[234] = "_ecirc_"; ISOLATIN_ENTITIES[235] = "_euml_"; ISOLATIN_ENTITIES[236] = "_igrave_"; ISOLATIN_ENTITIES[237] = "_iacute_"; ISOLATIN_ENTITIES[238] = "_icirc_"; ISOLATIN_ENTITIES[239] = "_iuml_"; ISOLATIN_ENTITIES[240] = "_eth_"; ISOLATIN_ENTITIES[241] = "_ntilde_"; ISOLATIN_ENTITIES[242] = "_ograve_"; ISOLATIN_ENTITIES[243] = "_oacute_"; ISOLATIN_ENTITIES[244] = "_ocirc_"; ISOLATIN_ENTITIES[245] = "_otilde_"; ISOLATIN_ENTITIES[246] = "_ouml_"; ISOLATIN_ENTITIES[247] = "_divide_"; ISOLATIN_ENTITIES[248] = "_oslash_"; ISOLATIN_ENTITIES[249] = "_ugrave_"; ISOLATIN_ENTITIES[250] = "_uacute_"; ISOLATIN_ENTITIES[251] = "_ucirc_"; ISOLATIN_ENTITIES[252] = "_uuml_"; ISOLATIN_ENTITIES[253] = "_yacute_"; ISOLATIN_ENTITIES[254] = "_thorn_"; ISOLATIN_ENTITIES[255] = "_yuml_"; } /** * replaces entities in string by ISOLatin mnemonics e.g. replaces ± by * _plusmn_ sometimes find strings of form ± which actually mean * ± the leading string ent should be of form Â&#, etc. &# will do * simple entities * * @param s * to be edited * @param ent * leading string before numeric * @param lo * lowest index allowed * @param hi * highest index allowed * @param chars * list of characters * @return edited string * @throws RuntimeException */ private static String replaceNumericEntityByMnemonic(String s, String ent, int lo, int hi, String[] chars) throws RuntimeException { if (ent == null || !ent.endsWith(S_AMP + EC.S_HASH)) { throw new RuntimeException("bad entity: " + ent); } int idx = s.indexOf(ent); if (idx != -1) { // String sub = ""; while (true) { idx = s.indexOf(ent); if (idx == -1) { break; } String ss = s.substring(idx + ent.length()); int ii = ss.indexOf(S_SEMICOLON); if (ii == -1) { throw new RuntimeException("Bad entity after (" + ent + "): " + s); } String alpha = "_unk_"; String sss = ss.substring(0, ii); try { int ia = Integer.parseInt(sss); // ascii if (ia >= 32 && ia <= 127) { alpha = EC.S_EMPTY + (char) ia; } else if (ia < lo || ia > hi) { alpha = EC.S_UNDER + "ent" + ia + EC.S_UNDER; } else { alpha = EC.S_UNDER + chars[ia] + EC.S_UNDER; } } catch (NumberFormatException e) { throw new RuntimeException("Bad numeric entity: " + sss); } s = s.replace(ent + sss + EC.S_SEMICOLON, alpha); } } return s; } /** * @param s * string to be edited * @param ent * leading entity * @return edited string */ public static String replaceNumericEntityByISOLatinString(String s, String ent) { return replaceNumericEntityByMnemonic(s, ent, 160, 255, ISOLATIN_ENTITIES); } /** greek entities */ public final static String[] GREEK_ENTITIES = new String[200]; static { GREEK_ENTITIES[145] = "Alpha"; GREEK_ENTITIES[146] = "Beta"; GREEK_ENTITIES[147] = "Gamma"; GREEK_ENTITIES[148] = "Delta"; GREEK_ENTITIES[149] = "Epsilon"; GREEK_ENTITIES[150] = "Zeta"; GREEK_ENTITIES[151] = "Eta"; GREEK_ENTITIES[152] = "Theta"; GREEK_ENTITIES[153] = "Iota"; GREEK_ENTITIES[154] = "Kappa"; GREEK_ENTITIES[155] = "Lambda"; GREEK_ENTITIES[156] = "Mu"; GREEK_ENTITIES[157] = "Nu"; GREEK_ENTITIES[158] = "Omicron"; GREEK_ENTITIES[159] = "Pi"; GREEK_ENTITIES[160] = "Rho"; GREEK_ENTITIES[161] = "Sigma"; GREEK_ENTITIES[162] = "Tau"; GREEK_ENTITIES[163] = "Upsilon"; GREEK_ENTITIES[164] = "Phi"; GREEK_ENTITIES[165] = "Phi"; GREEK_ENTITIES[166] = "Psi"; GREEK_ENTITIES[167] = "Omega"; GREEK_ENTITIES[177] = "alpha"; GREEK_ENTITIES[178] = "beta"; GREEK_ENTITIES[179] = "gamma"; GREEK_ENTITIES[180] = "delta"; GREEK_ENTITIES[181] = "epsilon"; GREEK_ENTITIES[182] = "zeta"; GREEK_ENTITIES[183] = "eta"; GREEK_ENTITIES[184] = "theta"; GREEK_ENTITIES[185] = "iota"; GREEK_ENTITIES[186] = "kappa"; GREEK_ENTITIES[187] = "lambda"; GREEK_ENTITIES[188] = "mu"; GREEK_ENTITIES[189] = "nu"; GREEK_ENTITIES[190] = "omicron"; GREEK_ENTITIES[191] = "pi"; GREEK_ENTITIES[192] = "rho"; GREEK_ENTITIES[193] = "sigma"; GREEK_ENTITIES[194] = "tau"; GREEK_ENTITIES[195] = "upsilon"; GREEK_ENTITIES[196] = "phi"; GREEK_ENTITIES[197] = "chi"; GREEK_ENTITIES[198] = "psi"; GREEK_ENTITIES[199] = "omega"; }; /** UPPER_GREEK entities */ public final static String[] UPPER_GREEK_ENTITIES = new String[968]; public final static Map GREEK2CHARACTER_MAP; static { UPPER_GREEK_ENTITIES[912] = "Alpha"; UPPER_GREEK_ENTITIES[914] = "Beta"; UPPER_GREEK_ENTITIES[915] = "Gamma"; UPPER_GREEK_ENTITIES[916] = "Delta"; UPPER_GREEK_ENTITIES[917] = "Epsilon"; UPPER_GREEK_ENTITIES[918] = "Zeta"; UPPER_GREEK_ENTITIES[919] = "Eta"; UPPER_GREEK_ENTITIES[920] = "Theta"; UPPER_GREEK_ENTITIES[921] = "Iota"; UPPER_GREEK_ENTITIES[922] = "Kappa"; UPPER_GREEK_ENTITIES[923] = "Lambda"; UPPER_GREEK_ENTITIES[924] = "Mu"; UPPER_GREEK_ENTITIES[925] = "Nu"; UPPER_GREEK_ENTITIES[926] = "Omicron"; UPPER_GREEK_ENTITIES[927] = "Pi"; UPPER_GREEK_ENTITIES[928] = "Rho"; UPPER_GREEK_ENTITIES[929] = "Sigma"; UPPER_GREEK_ENTITIES[930] = "Tau"; UPPER_GREEK_ENTITIES[931] = "Upsilon"; UPPER_GREEK_ENTITIES[932] = "Phi"; UPPER_GREEK_ENTITIES[933] = "Phi"; UPPER_GREEK_ENTITIES[934] = "Psi"; UPPER_GREEK_ENTITIES[935] = "Omega"; UPPER_GREEK_ENTITIES[945] = "alpha"; UPPER_GREEK_ENTITIES[946] = "beta"; UPPER_GREEK_ENTITIES[947] = "gamma"; UPPER_GREEK_ENTITIES[948] = "delta"; UPPER_GREEK_ENTITIES[949] = "epsilon"; UPPER_GREEK_ENTITIES[950] = "zeta"; UPPER_GREEK_ENTITIES[951] = "eta"; UPPER_GREEK_ENTITIES[952] = "theta"; UPPER_GREEK_ENTITIES[953] = "iota"; UPPER_GREEK_ENTITIES[954] = "kappa"; UPPER_GREEK_ENTITIES[955] = "lambda"; UPPER_GREEK_ENTITIES[956] = "mu"; UPPER_GREEK_ENTITIES[957] = "nu"; UPPER_GREEK_ENTITIES[958] = "omicron"; UPPER_GREEK_ENTITIES[959] = "pi"; UPPER_GREEK_ENTITIES[960] = "rho"; UPPER_GREEK_ENTITIES[961] = "sigma"; UPPER_GREEK_ENTITIES[962] = "tau"; UPPER_GREEK_ENTITIES[963] = "upsilon"; UPPER_GREEK_ENTITIES[964] = "phi"; UPPER_GREEK_ENTITIES[965] = "chi"; UPPER_GREEK_ENTITIES[966] = "psi"; UPPER_GREEK_ENTITIES[967] = "omega"; GREEK2CHARACTER_MAP = new HashMap(); GREEK2CHARACTER_MAP.put("Alpha", (char)912); GREEK2CHARACTER_MAP.put("Beta", (char)914); GREEK2CHARACTER_MAP.put("Gamma", (char)915); GREEK2CHARACTER_MAP.put("Delta", (char)916); GREEK2CHARACTER_MAP.put("Epsilon", (char)917); GREEK2CHARACTER_MAP.put("Zeta", (char)918); GREEK2CHARACTER_MAP.put("Eta", (char)919); GREEK2CHARACTER_MAP.put("Theta", (char)920); GREEK2CHARACTER_MAP.put("Iota", (char)921); GREEK2CHARACTER_MAP.put("Kappa", (char)922); GREEK2CHARACTER_MAP.put("Lambda", (char)923); GREEK2CHARACTER_MAP.put("Mu", (char)924); GREEK2CHARACTER_MAP.put("Nu", (char)925); GREEK2CHARACTER_MAP.put("Omicron", (char)926); GREEK2CHARACTER_MAP.put("Pi", (char)927); GREEK2CHARACTER_MAP.put("Rho", (char)928); GREEK2CHARACTER_MAP.put("Sigma", (char)929); GREEK2CHARACTER_MAP.put("Tau", (char)930); GREEK2CHARACTER_MAP.put("Upsilon", (char)931); GREEK2CHARACTER_MAP.put("Phi", (char)932); GREEK2CHARACTER_MAP.put("Phi", (char)933); GREEK2CHARACTER_MAP.put("Psi", (char)934); GREEK2CHARACTER_MAP.put("Omega", (char)935); GREEK2CHARACTER_MAP.put("alpha", (char)945); GREEK2CHARACTER_MAP.put("beta", (char)946); GREEK2CHARACTER_MAP.put("gamma", (char)947); GREEK2CHARACTER_MAP.put("delta", (char)948); GREEK2CHARACTER_MAP.put("epsilon", (char)949); GREEK2CHARACTER_MAP.put("zeta", (char)950); GREEK2CHARACTER_MAP.put("eta", (char)951); GREEK2CHARACTER_MAP.put("theta", (char)952); GREEK2CHARACTER_MAP.put("iota", (char)953); GREEK2CHARACTER_MAP.put("kappa", (char)954); GREEK2CHARACTER_MAP.put("lambda", (char)955); GREEK2CHARACTER_MAP.put("mu", (char)956); GREEK2CHARACTER_MAP.put("nu", (char)957); GREEK2CHARACTER_MAP.put("omicron", (char)958); GREEK2CHARACTER_MAP.put("pi", (char)959); GREEK2CHARACTER_MAP.put("rho", (char)960); GREEK2CHARACTER_MAP.put("sigma", (char)961); GREEK2CHARACTER_MAP.put("tau", (char)962); GREEK2CHARACTER_MAP.put("upsilon", (char)963); GREEK2CHARACTER_MAP.put("phi", (char)964); GREEK2CHARACTER_MAP.put("chi", (char)965); GREEK2CHARACTER_MAP.put("psi", (char)966); GREEK2CHARACTER_MAP.put("omega", (char)967); }; /** * remove all control (non-printing) characters * * @param s * Description of the Parameter * @return Description of the Return Value */ public static String replaceISOControlsByMnemonic(String s) { if (s == null) { return null; } StringBuffer sb = new StringBuffer(); int l = s.length(); for (int i = 0; i < l; i++) { char ch = s.charAt(i); if (Character.isISOControl(ch)) { sb.append(translateToMnemonic(ch)); } else { sb.append(ch); } } return sb.toString(); } /** * translate non-printing character to ISO mnemonic. e.g. 1 => SOH * * @param ch * [0 - 31] or 127 * @return translation or empty string if out of range */ public static String translateToMnemonic(char ch) { switch (ch) { case 0: return "NUL"; case 1: return "SOH"; case 2: return "STX"; case 3: return "ETX"; case 4: return "EOT"; case 5: return "ENQ"; case 6: return "ACK"; case 7: return "BEL"; case 8: return "BS"; case 9: return "HT"; case 10: return "LF"; case 11: return "VT"; case 12: return "FF"; case 13: return "CR"; case 14: return "SO"; case 15: return "SI"; case 16: return "DLE"; case 17: return "DC1"; case 18: return "DC2"; case 19: return "DC3"; case 20: return "DC4"; case 21: return "NAK"; case 22: return "SYN"; case 23: return "ETB"; case 24: return "CAN"; case 25: return "EM"; case 26: return "SUB"; case 27: return "ESC"; case 28: return "FS"; case 29: return "GS"; case 30: return "RS"; case 31: return "US"; case 127: return "DEL"; default: return ""; } } /** * convert 2 UTF8 characters to single IsoLatin1 character. quick and dirty * UTF8 C2 80 => 80 (etc) UTF8 C3 80 => C0 (i.e. add x40) user has * responsibility for selecting characters * * @param a * leading character (ignored if not C2 and not C3) * @param b * range 80-bf * @return Isolatin equiv or 0 if a,b ignored or bad range */ public static char convertUTF8ToLatin1(char a, char b) { char c = 0; if (b >= 128 && b < 192) { if (a == (char) 194) { c = b; } else if (a == (char) 195) { c = (char) ((int) b + 64); } } return c; } /** * convert single IsoLatin1 character to 2 UTF8 characters . quick and dirty * user has responsibility for selecting characters a >= x80 && a <= xBF ==> * xC2 a a >= xC0 && a <= xFF ==> xC3 a - x40 * * @param a * char to be converted (a >= x80 && a = 128 && a < 192) { c = new char[2]; c[0] = (char) 194; c[1] = a; } else if (a >= 192 && a < 256) { c = new char[2]; c[0] = (char) 195; c[1] = (char) (a - 64); } return c; } /** * @param s * string to be edited * @param ent * leading entity * @return edited string */ public static String replaceNumericEntityByGreekMnemonics(String s, String ent) { return replaceNumericEntityByMnemonic(s, ent, 145, 199, GREEK_ENTITIES); } /** * substitute certain DOS-compatible diacriticals by the Unicode value. Not * guaranteed to be correct. Example 130 is e-acute (== * * @param s * Description of the Parameter * @return Description of the Return Value */ public static String substituteDOSbyAscii(String s) { // check for untranslated chars for (int i = 0; i < s.length(); i++) { int jj = (int) s.charAt(i); if (jj > 180) { boolean ok = false; for (int j = 0; j < dosEquivalents.length; j++) { if (dosEquivalents[j].equals(S_EMPTY + s.charAt(i))) { ok = true; break; } } if (!ok) { logger.error("==Unknown DOS character==" + jj + "//" + s); } } } String s1 = substituteStrings(s, dosEquivalents, asciiEquivalents); return s1; } public static String substituteNonASCIIChars(String s, char replacement) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < s.length(); i++) { int c = s.charAt(i); c = (c > 256) ? (int) replacement : c; sb.append((char)c); } return sb.toString(); } /* ‌ ‌ Zero Width Non Joiner ‍ ‍ Zero Width Joiner ‎ ‎ Left-Right Mark ‏ ‏ Right-Left Mark – – en dash — — em dash ‘ ‘ left single quotation mark ’ ’ right single quotation mark “ “ left double quotation mark ” ” right double quotation mark */ public static String substituteSmartCharacters(String s) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < s.length(); i++) { int c = s.charAt(i); if (c == 8204 || c == 160) { c = ' '; } else if (c == 8205) { c = -1; } else if (c == 8211 || c == 8212) { c = '-'; } else if (c == 8216 || c == 8217) { c = '\''; } else if (c == 8220 || c == 8221) { c = '"'; } else if (c > 127) { c = '?'; } if (c > 0) { sb.append((char)c); } } return sb.toString(); } /** * replace tabs with spaces while trying to preserve the formatting * @param s * @param width * @return */ public static String replaceTabs(String s, int width) { StringBuilder sb = new StringBuilder(); int in = 0; int out = 0; for (; in < s.length(); in++) { char c = s.charAt(in); if (c == EuclidConstants.C_TAB) { int mod = width - (out % width); for (int i = 0; i < mod; i++) { sb.append(EuclidConstants.C_SPACE); out++; } } else { sb.append(c); out++; } } return sb.toString(); } /** * substitute hex representation of character, for example =2E by char(46). * If line ends with =, ignore that character. * * @param s * Description of the Parameter * @return String result */ public static String substituteEquals(String s) { if (s == null) { return null; } int len = s.length(); StringBuffer sb = new StringBuffer(S_EMPTY); while (true) { int idx = s.indexOf(S_EQUALS); if (idx == -1) { sb.append(s); return sb.toString(); } // remove EQUALS sb.append(s.substring(0, idx)); s = s.substring(idx + 1); len -= idx + 1; // not enough chars if (len <= 1) { sb.append(S_EQUALS); sb.append(s); return sb.toString(); } int hex = getIntFromHex(s.substring(0, 2)); // wasn't a hexchar if (hex < 0) { sb.append(S_EQUALS); } else { sb.append((char) hex); s = s.substring(2); len -= 2; } } } /** * * Translates a Hex number to its int equivalent. Thus "FE" translates to * * 254. Horrid, but I couldn't find if Java reads hex. All results are >= * * 0. Errors return -1 * * * * @param hex * Description of the Parameter * * @return The intFromHex value * */ public static int getIntFromHex(String hex) { hex = hex.toUpperCase(); if (hex.startsWith("0X")) { hex = hex.substring(2); } else if (hex.charAt(0) == 'X') { hex = hex.substring(1); } int result = 0; for (int i = 0; i < hex.length(); i++) { char c = hex.charAt(i); if (Character.isDigit(c)) { c -= '0'; } else if (c < 'A' || c > 'F') { return -1; } else { c -= 'A'; c += (char) 10; } result = 16 * result + c; } return result; } /** * capitalise a String (whatever the starting case) * * @param s * Description of the Parameter * @return Description of the Return Value */ public static String capitalise(String s) { if (s.equals(S_EMPTY)) { return EC.S_EMPTY; } if (s.length() == 1) { return s.toUpperCase(); } else { return s.substring(0, 1).toUpperCase() + s.substring(1).toLowerCase(); } } /** * Description of the Method * * @param s * Description of the Parameter * @return Description of the Return Value */ public static String toCamelCase(String s) { StringTokenizer st = new StringTokenizer(s, " \n\r\t"); String out = EC.S_EMPTY; while (st.hasMoreTokens()) { s = st.nextToken(); if (out != EC.S_EMPTY) { s = capitalise(s); } out += s; } return out; } /** * reads a byte array from file, *including* line feeds * * @param filename * Description of the Parameter * @return Description of the Return Value * @exception FileNotFoundException * Description of the Exception * @exception IOException * Description of the Exception */ public static byte[] readByteArray(String filename) throws FileNotFoundException, IOException { DataInputStream dis = new DataInputStream(new FileInputStream(filename)); return Util.readByteArray(dis); } /** * reads a byte array from DataInputStream, *including* line feeds * * @param d * Description of the Parameter * @return Description of the Return Value * @exception IOException * Description of the Exception */ public static byte[] readByteArray(DataInputStream d) throws IOException { int len = 100; int count = 0; byte[] src = new byte[len]; byte b; while (true) { try { b = d.readByte(); } catch (EOFException e) { break; } src[count] = b; if (++count >= len) { len *= 2; byte[] temp = new byte[len]; System.arraycopy(src, 0, temp, 0, count); src = temp; } } len = count; byte[] temp = new byte[len]; System.arraycopy(src, 0, temp, 0, count); return temp; } /** * remove all control (non-printing) characters * * @param s * Description of the Parameter * @return Description of the Return Value */ public static String stripISOControls(String s) { if (s == null) { return null; } StringBuffer sb = new StringBuffer(); int l = s.length(); for (int i = 0; i < l; i++) { char ch = s.charAt(i); if (!Character.isISOControl(ch)) { sb.append(ch); } } return sb.toString(); } /** * normalise whitespace in a String (all whitespace is transformed to single * spaces and the string is NOT trimmed * * @param s * Description of the Parameter * @return Description of the Return Value */ public static String normaliseWhitespace(String s) { if (s == null || s.equals(S_EMPTY)) { return s; } StringTokenizer st = new StringTokenizer(s, Util.WHITESPACE); int l = s.length(); String ss = EC.S_EMPTY; if (Character.isWhitespace(s.charAt(0))) { ss = EC.S_SPACE; } String end = EC.S_EMPTY; if (Character.isWhitespace(s.charAt(l - 1))) { end = EC.S_SPACE; } boolean start = true; while (st.hasMoreTokens()) { if (start) { ss += st.nextToken(); start = false; } else { ss += EC.S_SPACE + st.nextToken(); } } return ss + end; } /** * strip linefeeds from a byte array * * @param b * Description of the Parameter * @return Description of the Return Value */ public static byte[] stripNewlines(byte[] b) { int l = b.length; byte[] bb = new byte[l]; int j = 0; for (int i = 0; i < l; i++) { if (b[i] != '\n') { bb[j++] = b[i]; } } byte[] bbb = new byte[j]; System.arraycopy(bb, 0, bbb, 0, j); return bbb; } /** * get an OutputStream from a file or URL. Required (I think) because * strings of the sort "file:/C:\foo\bat.txt" crash FileOutputStream, so * this strips off the file:/ stuff for Windows-like stuff * * @param fileName * Description of the Parameter * @return FileOutputStream a new (opened) FileOutputStream * @exception java.io.FileNotFoundException * Description of the Exception */ public static FileOutputStream getFileOutputStream(String fileName) throws java.io.FileNotFoundException { if (fileName == null) { return null; } // W-like syntax if (fileName.startsWith("file:") && fileName.substring(5).indexOf(S_COLON) != -1) { fileName = fileName.substring(5); if (fileName.startsWith(S_SLASH) || fileName.startsWith(S_BACKSLASH)) { fileName = fileName.substring(1); } } return new FileOutputStream(fileName); } // cache the formats static Hashtable formTable = new Hashtable(); /** * format for example f8.3 this is a mess; if cannot fit, then either * right-truncates or when that doesn't work, returns **** * * @param nPlaces * Description of the Parameter * @param nDec * Description of the Parameter * @param value * Description of the Parameter * @return Description of the Return Value * @exception EuclidRuntimeException * Description of the Exception */ public static String outputFloat(int nPlaces, int nDec, double value) throws EuclidRuntimeException { String f = "f" + nPlaces + EC.S_PERIOD + nDec; DecimalFormat form = formTable.get(f); if (form == null) { String pattern = EC.S_EMPTY; for (int i = 0; i < nPlaces - nDec - 2; i++) { pattern += "#"; } pattern += "0."; for (int i = nPlaces - nDec; i < nPlaces; i++) { pattern += "0"; } form = (DecimalFormat) NumberFormat.getInstance(); DecimalFormatSymbols symbols = form.getDecimalFormatSymbols(); symbols.setDecimalSeparator('.'); form.setDecimalFormatSymbols(symbols); form.setMaximumIntegerDigits(nPlaces - nDec - 1); // form.applyLocalizedPattern(pattern); form.applyPattern(pattern); formTable.put(f, form); } String result = form.format(value).trim(); boolean negative = false; if (result.charAt(0) == '-') { result = result.substring(1); negative = true; } if (negative) { result = EC.S_MINUS + result; } StringBuffer sb = new StringBuffer(); int l = result.length(); for (int i = 0; i < nPlaces - l; i++) { sb.append(S_SPACE); } String s = sb.append(result).toString(); if (l > nPlaces) { s = s.substring(0, nPlaces); // decimal point got truncated? if (s.indexOf(S_PERIOD) == -1) { s = EC.S_EMPTY; for (int i = 0; i < nPlaces; i++) { s += EC.S_STAR; } } } return s; } /** * as above, but trims trailing zeros * * @param nPlaces * Description of the Parameter * @param nDec * Description of the Parameter * @param c * Description of the Parameter * @return Description of the Return Value */ public static String outputNumber(int nPlaces, int nDec, double c) { String s = Util.outputFloat(nPlaces, nDec, c).trim(); if (s.indexOf(S_PERIOD) != -1) { while (s.endsWith("0")) { s = s.substring(0, s.length() - 1); } if (s.endsWith(S_PERIOD)) { s = s.substring(0, s.length() - 1); } } return s; } /** * invert a Hashtable by interchanging keys and values. This assumes a 1;1 * mapping - if not the result is probably garbage. * * @param table * Description of the Parameter * @return Description of the Return Value */ public static Hashtable invert( Hashtable table) { if (table == null) { return null; } Hashtable newTable = new Hashtable(); for (Enumeration e = table.keys(); e.hasMoreElements();) { Object key = e.nextElement(); Object value = table.get(key); newTable.put(value, key); } return newTable; } /** * checks array is not null and is of given size. * * @param array * to check * @param size * required size * @throws EuclidRuntimeException * if null or wrong size */ public static void check(double[] array, int size) throws EuclidRuntimeException { if (array == null) { throw new EuclidRuntimeException("null array"); } else if (array.length != size) { throw new EuclidRuntimeException("array size required (" + size + ") found " + array.length); } } /** * checks that an in is in the range low to high. * * @param n * to check * @param low * inclusive lower * @param high * inclusive higher * @throws EuclidRuntimeException * if out of range */ public static void check(int n, int low, int high) throws EuclidRuntimeException { if (n < low || n > high) { throw new EuclidRuntimeException("index (" + n + ")out of range: " + low + EC.S_SLASH + high); } } /** * compare two arrays of doubles. * * @param a * first array * @param b * second array * @param eps * maximum allowed difference * @return true if arrays non-null and if arrays are equal length and * corresonding elements agree within eps. */ public static boolean isEqual(double[] a, double[] b, double eps) { boolean equal = (a != null && b != null && a.length == b.length); if (equal) { for (int i = 0; i < a.length; i++) { if (Math.abs(a[i] - b[i]) >= eps) { equal = false; break; } } } return equal; } /** * compare two arrays of ints. * * @param a * first array * @param b * second array * @param eps * maximum allowed difference * @return true if arrays non-null and if arrays are equal length and * corresonding elements agree within eps. */ public static boolean isEqual(int[] a, int[] b, int eps) { boolean equal = (a != null && b != null && a.length == b.length); if (equal) { for (int i = 0; i < a.length; i++) { if (Math.abs(a[i] - b[i]) >= eps) { equal = false; break; } } } return equal; } /** * concatenates array of booleans. * * @param bb * the values * @param separator * @return the String */ public final static String concatenate(boolean[] bb, String separator) { StringBuffer sb = new StringBuffer(); for (int i = 0; i < bb.length; i++) { if (i > 0) { sb.append(separator); } sb.append(bb[i]); } return sb.toString(); } /** * concatenates array of doubles. * * @param ss * the values * @param separator * @return the String */ public final static String concatenate(double[] ss, String separator) { StringBuffer sb = new StringBuffer(); for (int i = 0; i < ss.length; i++) { if (i > 0) { sb.append(separator); } if (Double.isInfinite(ss[i])) { if (ss[i] < 0) { sb.append("-"); } sb.append("INF"); } else if (Double.isNaN(ss[i])) { sb.append("NaN"); } else { sb.append(ss[i]); } } return sb.toString(); } /** * concatenates array of array of doubles. * * @param ss * the values * @param separator * @return the String */ public final static String concatenate(double[][] ss, String separator) { StringBuffer sb = new StringBuffer(); for (int i = 0; i < ss.length; i++) { if (i > 0) { sb.append(separator); } sb.append(Util.concatenate(ss[i], separator)); } return sb.toString(); } /** * splits string into ints. * * @param s * the string * @param delim * @return array * @throws EuclidRuntimeException * cannot parse as ints */ public final static int[] splitToIntArray(String s, String delim) throws EuclidRuntimeException { String[] ss = s.split(delim); int[] ii = new int[ss.length]; for (int i = 0; i < ss.length; i++) { try { ii[i] = Integer.parseInt(ss[i]); } catch (NumberFormatException nfe) { throw new EuclidRuntimeException(S_EMPTY + nfe); } } return ii; } /** * splits string into doubles. assumes single space delimiters * * @param s * the string * @return array * @throws EuclidRuntimeException * cannot parse as ints */ public final static double[] splitToDoubleArray(String s) { return splitToDoubleArray(s, EC.S_SPACE); } /** * Parses double, taking account of lexical forms of special cases allowed * by the XSD spec: INF, -INF and NaN. * * @param value * @return * @throws ParseException */ public static double parseFlexibleDouble(String value) throws ParseException { //LOG.debug("Parsing "+ value); if (value != null) { // 0, -0, INF, -INF and NaN : Special cases from the XSD spec. if ("INF".equals(value)) { return Double.POSITIVE_INFINITY; } else if ("-INF".equals(value)) { return Double.NEGATIVE_INFINITY; } else if ("NaN".equals(value)) { return Double.NaN; } else { try { return Double.valueOf(value); } catch (NumberFormatException e) { throw new ParseException(e.toString(), 0); } } } else { throw new IllegalArgumentException("Null double string not allowed"); } } /** * splits string into doubles. * * @param s * the string * @param delim * @return array * @throws EuclidRuntimeException * cannot parse as ints */ public final static double[] splitToDoubleArray(String s, String delim) throws EuclidRuntimeException { if (s == null) { throw new RuntimeException("null argument"); } String[] ss = s.trim().split(delim); double[] dd = new double[ss.length]; for (int i = 0; i < ss.length; i++) { try { dd[i] = parseFlexibleDouble(ss[i]); } catch (NumberFormatException nfe) { throw new EuclidRuntimeException(S_EMPTY + nfe.getMessage(), nfe); } catch (ParseException e) { throw new EuclidRuntimeException("Bad double in (" + s + ") : " + ss[i] + "at position " + i, e); } } return dd; } /** * concatenates array of ints. * * @param ss * the values * @param separator * @return the String */ public final static String concatenate(int[] ss, String separator) { StringBuffer sb = new StringBuffer(); for (int i = 0; i < ss.length; i++) { if (i > 0) { sb.append(separator); } sb.append(ss[i]); } return sb.toString(); } /** * concatenates array of Strings. * * @param ss * the values * @param separator * @return the String */ public final static String concatenate(String[] ss, String separator) { StringBuffer sb = new StringBuffer(); for (int i = 0; i < ss.length; i++) { if (i > 0) { sb.append(separator); } sb.append(ss[i]); } String s = sb.toString(); if (separator.trim().equals(S_EMPTY)) { s = s.trim(); } return s; } /** * does an array of Strings contain a String. * * @param strings * @param s * string to search for * @return true if any ss[i] == s */ public final static boolean containsString(String[] strings, String s) { boolean b = false; if (s != null) { for (int i = 0; i < strings.length; i++) { if (s.equals(strings[i])) { b = true; break; } } } return b; } /** * format trailing decimals * * @param d * value to be formatted * @param ndec * max number of decimals (3 = ****.ddd * @return the formatted number */ public static double format(double d, int ndec) { int pow = 1; for (int i = 0; i < ndec; i++) { pow *= 10; } return (double) Math.round(d * (double) pow) / (double) pow; } /** * trim trailing zeroes and trailing decimal point. * * @param d * @return trimmed string */ public static String trim(double d) { String s = EC.S_EMPTY + d; int idx = s.lastIndexOf(S_PERIOD); if (idx > 0) { int l = s.length() - 1; while (l > idx) { if (s.charAt(l) != '0') { break; } l--; } if (l == idx) { l--; } l++; s = s.substring(0, l); } return s; } /** * translate array of Strings to a List. * * @param ss * strings (can include null) * @return the list */ public static List createList(String[] ss) { List list = new ArrayList(); for (String s : ss) { list.add(s); } return list; } private static List primeList; /** * get i'th prime. calculates it on demand if not already present and caches * result. * * @param i * @return the primt (starts at 2) */ public static int getPrime(int i) { if (primeList == null) { primeList = new ArrayList(); primeList.add(new Integer(2)); primeList.add(new Integer(3)); primeList.add(new Integer(5)); primeList.add(new Integer(7)); primeList.add(new Integer(11)); } int np = primeList.size(); int p = primeList.get(np - 1).intValue(); while (np <= i) { p = nextPrime(p); primeList.add(new Integer(p)); np++; } return primeList.get(i).intValue(); } private static int nextPrime(int pp) { int p = pp; for (;;) { p = p + 2; if (isPrime(p)) { break; } } return p; } private static boolean isPrime(int p) { boolean prime = true; int sp = (int) Math.sqrt(p) + 1; for (int i = 1; i < primeList.size(); i++) { int pp = primeList.get(i).intValue(); if (p % pp == 0) { prime = false; break; } if (pp > sp) { break; } } return prime; } /** * parse string as integer. * * @param s * @return true if can be parsed. */ public static boolean isInt(String s) { boolean couldBeInt = true; try { new Integer(s); } catch (NumberFormatException e) { couldBeInt = false; } return couldBeInt; } /** * parse string as integerArray. * * @param s * @param delimiterRegex * @return true if can be parsed. */ public static boolean isIntArray(String s, String delimiterRegex) { boolean couldBeIntArray = true; String[] ss = s.split(delimiterRegex); try { new IntArray(ss); } catch (NumberFormatException e) { couldBeIntArray = false; } return couldBeIntArray; } /** * parse string as realArray. * * @param s * @param delimiterRegex * @return true if can be parsed. */ public static boolean isFloatArray(String s, String delimiterRegex) { boolean couldBeFloatArray = true; String[] ss = s.split(delimiterRegex); try { new RealArray(ss); } catch (Exception e) { couldBeFloatArray = false; } return couldBeFloatArray; } /** * parse string as float. * * @param s * @return true if can be parsed. */ public static boolean isFloat(String s) { boolean couldBeFloat = true; try { new Double(s); } catch (NumberFormatException e) { couldBeFloat = false; } return couldBeFloat; } /** * date of form 21-jan-1965. */ public final static String DATE_REGEX1 = "([0-3][0-9])\\-(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\\-(\\d\\d\\d\\d)"; /** * date of form 1965-01-25. */ public final static String DATE_REGEX2 = "\\d\\d\\d\\d\\-[0-1][0-9]\\-[0-3][0-9]"; /** * month data . */ public final static String[] months = { "jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec" }; /** * parse string as date. tries several formats (case insensitive) can be * used to test whether string is parsable as date * * @param s * @return ISO 8601 format if can be parsed or null */ public static String getCanonicalDate(String s) { String dateS = null; Pattern pattern = Pattern .compile(DATE_REGEX1, Pattern.CASE_INSENSITIVE); Matcher matcher = pattern.matcher(s.toLowerCase()); if (matcher.matches()) { int day = Integer.parseInt(matcher.group(1)); String month = matcher.group(2).toLowerCase(); boolean ignoreCase = true; int imonth = Util.indexOf(month, months, ignoreCase); int year = Integer.parseInt(matcher.group(3)); dateS = "" + year + EC.S_MINUS + imonth + EC.S_MINUS + day; } else { pattern = Pattern.compile(DATE_REGEX2, Pattern.CASE_INSENSITIVE); matcher = pattern.matcher(s.toLowerCase()); if (matcher.matches()) { dateS = s; } } return dateS; } public static double getDouble(String s) { double d = Double.NaN; try { d = new Double(s).doubleValue(); } catch (NumberFormatException nfe) { throw new RuntimeException("Bad double: " + s); } return d; } /** * rounds to decimal place. * * @param dd * number to be rounded * @param ndec * number of places * @return float */ public static double trimFloat(double dd, int ndec) { int trim = 1; ndec = Math.min(ndec, 10); // to avoid problems for (int i = 0; i < ndec; i++) { trim *= 10; } return ((int) (trim * dd)) / (double) trim; } /** * sorts a list of string on integers within them. normal lexical sort will * often produce file1, file10, file11, file2, etc. this will order them by * integers int their * * @param list */ public static void sortByEmbeddedInteger(List list) { StringIntegerComparator fic = new StringIntegerComparator(); Collections.sort(list, fic); } /** outputs to sysout. * primarily to allow trapping and tracing of sysout calls * which we try to avoid anyway * @param s */ public static void print(String s) { System.out.print(s); } /** outputs to sysout. * primarily to allow trapping and tracing of sysout calls * which we try to avoid anyway * @param s */ public static void println(String s) { System.out.println(s); } /** outputs to sysout. * primarily to allow trapping and tracing of sysout calls * which we try to avoid anyway * @param s */ public static void println() { System.out.println(); } public static List getRESTQueryAsLines(String s, String u, String mediaType) throws IOException { byte[] content = Util.getRESTQuery(s, u, mediaType); BufferedReader br = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(content))); List lines = new ArrayList(); String line; while ((line = br.readLine()) != null) { lines.add(line); } return lines; } public static byte[] getRESTQuery(String serviceUrl, String urlString, String mediaType) throws IOException { URL url = new URL(urlString+serviceUrl); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.addRequestProperty("accept", mediaType); conn.connect(); InputStream is = conn.getInputStream(); byte[] bytes = IOUtils.toByteArray(is); conn.disconnect(); return bytes; } /** * borrowed from somewhere. * @param s * @return */ public static String calculateMD5(String s) { String md5String = null; if (s != null && s.trim().length() > 0) { StringBuffer hexString = new StringBuffer(); try{ MessageDigest algorithm = MessageDigest.getInstance("MD5"); algorithm.reset(); algorithm.update(s.getBytes()); byte messageDigest[] = algorithm.digest(); for (int i=0; i < messageDigest.length; i++) { hexString.append(Integer.toHexString(0xFF & messageDigest[i])); } } catch(NoSuchAlgorithmException nsae) { } md5String = hexString.toString(); } return md5String; } /** * avoids the checked exception * @param file * @return */ public static String getCanonicalPath(File file) { String path = null; try { File absoluteFile = file.getAbsoluteFile(); path = absoluteFile.getCanonicalPath(); } catch (IOException e) { throw new RuntimeException("cannot canonicalize "+file+" ... "+e.getMessage(), e); } return path; } /** path to create file2 from file1 *@param file1 *@param file2 *@param newSeparator if not null, use as new separator */ public static String getRelativeFilename(File file1, File file2, String newSeparator) { if (newSeparator == null) { newSeparator = File.separator; } String regex = (File.separator.equals("\\")) ? "\\\\" : File.separator; String path = null; try { String path1 = file1.getCanonicalPath(); String path2 = file2.getCanonicalPath(); String[] pathComponent1 = path1.split(regex); String[] pathComponent2 = path2.split(regex); //int minComponents = Math.min(pathComponent1.length, pathComponent2.length); int i = 0; for (; i < pathComponent1.length; i++) { if (!pathComponent2[i].equals(pathComponent1[i])) { break; } } path = ""; for (int j = i; j < pathComponent1.length; j++) { path += ".."+newSeparator; } for (int j = i; j < pathComponent2.length-1; j++) { path += pathComponent2[j]+newSeparator; } path += pathComponent2[pathComponent2.length-1]; } catch (Exception e) { throw new RuntimeException("bad names/BUG", e); // return null } return path; } } class StringIntegerComparator implements Comparator { public int compare(Object o1, Object o2) { Integer i1 = strip(o1.toString()); Integer i2 = strip(o2.toString()); return i1.compareTo(i2); } private static Integer strip(String s) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < s.length(); i++) { char ch = s.charAt(i); if (ch >= '0' && ch <= '9') { sb.append(ch); } } String ss = sb.toString(); if (ss.length() == 0) { ss = "0"; } return new Integer(ss); } } wwmm-euclid-87e8f785a814/src/main/java/org/xmlcml/euclid/Vector2.java0000644000000000000000000000627611607017524023330 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid; /** * a 2-D vector relationship with Complex and Polar not fully worked out. It may * simply be a matter of style which is used. * * @author (C) P. Murray-Rust, 1996 */ public class Vector2 extends Real2 { /** * constructor. * * @param r * coordinates */ public Vector2(Real2 r) { super(r); } /** * constructor. * * @param x * @param y */ public Vector2(double x, double y) { this(new Real2(x, y)); } /** * I *think* I have written this so that the angle is positive as this * rotates anticlockwise to vector. * * @param v * @return angle or null */ public Angle getAngleMadeWith(Vector2 v) { Angle angle = null; if (v != null) { double theta0 = Math.atan2(v.x, v.y); double theta1 = Math.atan2(this.x, this.y); angle = new Angle(theta0 - theta1); } return angle; } /** is vector parallel to another * calculates angle between vectors * @param v * @param eps tolerance in radians (should be non-negative) * @return true if abs(angle) (rad) < eps */ public boolean isParallelTo(Vector2 v, double eps) { Angle a = this.getAngleMadeWith(v); return Math.abs(a.getRadian()) < eps; } /** is vector antiparallel to another * calculates angle between vectors * @param v * @param eps tolerance in radians (should be non-negative) * @return true if abs(angle) (rad) < eps */ public boolean isAntiParallelTo(Vector2 v, double eps) { Angle a = this.getAngleMadeWith(v); return Math.abs(Math.abs(a.getRadian())-Math.PI) < eps; } /** perp product (Hill). * this.getX() * vector.getY() - this.getY() * vector.getX(); * @param v * @return product */ public double getPerpProduct(Vector2 v) { return this.getX() * v.getY() - this.getY() * v.getX(); } /** * projection of this onto vector. does not alter this. result = vector.norm() * * (this.norm() dot vector.norm()) * * @param v vector to project onto * @return projected vector */ public Vector2 projectOnto(Vector2 v2) { Real2 unit2 = v2.getUnitVector(); Real2 unit = this.getUnitVector(); double dot = unit2.dotProduct(unit); Vector2 projection = new Vector2(unit2.multiplyBy(this.getLength() * dot)); return projection; } } wwmm-euclid-87e8f785a814/src/main/java/org/xmlcml/euclid/Vector3.java0000644000000000000000000004062411607017524023324 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid; import org.xmlcml.euclid.Axis.Axis3; /** * 3-dimensional vector * * A vector has thre components giving it a length and a direction (whose sign * is important),but no position. Vectors are often normalised to unit length. *

* Vectors and points are very closely related and some people use them * interchangeably. A Point3 has a position and cannot be normalised. In * very many routines, however, Vectors and Points can either be used * interchangeably, or there are equivalent routines or they can be converted * using cross-constructors. (They cannot be interconverted through casts). *

* The default vector is 0.0, 0.0, 0.0. Some operations on this will result in * ZerolengthVector Exceptions. * * @author (C) P. Murray-Rust, 1996 */ public class Vector3 implements EuclidConstants { /** * length of vector is zero */ final static int ZERO_VECT = 0; /** * length of vector is unknown */ final static int UNK_VECT = 1; /** * length is unit vector */ final static int UNIT_VECT = 2; /** * length of vector not zero or unity */ final static int OK_VECT = 3; /** * zero-length vector */ public final static Vector3 ZEROV = new Vector3(0.0, 0.0, 0.0); /** * X axis */ public final static Vector3 XV = new Vector3(1.0, 0.0, 0.0); /** * Y axis */ public final static Vector3 YV = new Vector3(0.0, 1.0, 0.0); /** * Z axis */ public final static Vector3 ZV = new Vector3(0.0, 0.0, 1.0); /** * Vector3 includes protected members which keep track of the sort of vector * At present these can be: null vector, unit vector and unknown. These * serve to reduce repetition in normalising already normalised vectors */ /** * vector status */ // int vecstatus = UNK_VECT; /** * vector length IF status not UNK_VECT, else -1 */ // double veclength; /** * vector components */ double[] flarray = new double[3]; /** * null constructor */ public Vector3() { } /** * construct from vector components. * * @param x * component * @param y * component * @param z * component */ public Vector3(double x, double y, double z) { this(); flarray[0] = x; flarray[1] = y; flarray[2] = z; } /** * construct from vector components. * * @param array * components * @throws EuclidRuntimeException */ public Vector3(double[] array) throws EuclidRuntimeException { this(); Util.check(array, 3); System.arraycopy(array, 0, flarray, 0, 3); } /** * axial unit vector constructor. unit vectors along X, Y, Z axes * * @param axis * to use */ public Vector3(Axis3 axis) { this(); Real.zeroArray(3, flarray); flarray[axis.value] = 1.0; } /** * copy constructor: * * @param v * vector to copy */ public Vector3(Vector3 v) { this(); System.arraycopy(v.flarray, 0, flarray, 0, 3); } /** * copy constructor from RealArray. * * @param f the array (of length 3) * @throws EuclidRuntimeException */ public Vector3(RealArray f) throws EuclidRuntimeException { this(); RealArray.check(f, 3); System.arraycopy(f.getArray(), 0, flarray, 0, 3); } /** * make a vector from a point vector is from origin to point * * @param p * the point */ public Vector3(Point3 p) { this(); System.arraycopy(p.flarray, 0, flarray, 0, 3); } /** * copy constructor: synonym for copy constructor * * @param v * vector to copy * @return vector */ public Vector3 clone(Vector3 v) { System.arraycopy(v.flarray, 0, flarray, 0, 3); return this; } /** * from Point3 vector is from origin to point * * @param p * the point * @return vector */ public Vector3 clone(Point3 p) { System.arraycopy(p.flarray, 0, flarray, 0, 3); return this; } /** * get the vector components * * @return vector of length 3 */ public double[] getArray() { return flarray; } /** * are two vectors equal lengths. uses Real.isEqual * * @param v * @return equal if length difference is within tolerance */ public boolean isEqualTo(Vector3 v) { return Real.isEqual(getLength(), v.getLength()); } /** * vector length > vector length * * @param v * vector to compare * @return true if this > vector */ public boolean longerThan(Vector3 v) { return (getLength() > v.getLength()); } /** * scalar multiplication. create new vector vector = this*f does not alter this * * @param f * multiplier for all components * @return scaled vector */ public Vector3 multiplyBy(double f) { Vector3 v1 = new Vector3(this); for (int i = 0; i < 3; i++) { v1.flarray[i] *= f; } return v1; } /** * scalar multiplication. sets equal to this*f alters this * * @param f * multiplier for all components */ public void multiplyEquals(double f) { for (int i = 2; i >= 0; --i) { flarray[i] *= f; } } /** * vector addition. create new vector result = this + v3 does not alter this * * @param v3 * vector to add * @return resultant vector */ public Vector3 plus(Vector3 v3) { Vector3 v1 = new Vector3(); v1 = this; for (int i = 0; i < 3; i++) { v1.flarray[i] += v3.flarray[i]; } return v1; } /** * vector addition. sets equal to this + v3 alters this * * @param v3 vector to subtract */ public void plusEquals(Vector3 v3) { for (int i = 2; i >= 0; --i) { flarray[i] += v3.flarray[i]; } } /** * vector subtraction. create new vector result = this - v3 does not alter * this * * @param v3 * vector to subtract * @return resultant vector */ public Vector3 subtract(Vector3 v3) { Vector3 v1 = new Vector3(); v1 = this; for (int i = 0; i < 3; i++) { v1.flarray[i] -= v3.flarray[i]; } return v1; } /** * vector subtraction. sets equal to this - v3 alters this * * @param v3 vector to subtract */ public void subtractEquals(Vector3 v3) { for (int i = 2; i >= 0; --i) { flarray[i] -= v3.flarray[i]; } } /** * negative of vector. result = -this does not alter this * * @return resultant vector */ public Vector3 negative() { Vector3 v1 = new Vector3(this); for (int i = 0; i < 3; i++) { v1.flarray[i] = -flarray[i]; } return v1; } /** * negative of vector. result = - DOES alter this * * @return resultant vector */ public Vector3 negativeEquals() { for (int i = 0; i < 3; i++) { flarray[i] = -flarray[i]; } return this; } /** * get component. use raw array if you are sure checking is not required * * @param n * the zero-based index * @return the n'th component * @throws EuclidRuntimeException */ public double elementAt(int n) throws EuclidRuntimeException { Util.check(n, 0, 2); return flarray[n]; } /** * set component. * * @param n * the zero-based index * @param f * component value * @throws EuclidRuntimeException */ public void setElementAt(int n, double f) throws EuclidRuntimeException { Util.check(n, 0, 2); flarray[n] = f; } /** * are two vectors equal in all components. uses Real.isEqual * * @param v * @return equal if components equal within tolerance */ public boolean isIdenticalTo(Vector3 v) { return Real.isEqual(flarray, v.flarray, Real.getEpsilon()); } /** * is vector of zero length. uses Real.isEqual * * @return if zero within tolerance */ public boolean isZero() { boolean b = Real.isZero(getLength(), Real.getEpsilon()); return b; } /** * create transformed vector. does not alter this. * * @param t * transform * @return tranformed vector */ public Vector3 transform(Transform3 t) { Transform3.checkNotNull(t); Vector3 vout = new Vector3(); double[] pv = vout.flarray; double[][] pt = t.getMatrix(); // just use the 3x3 submatrix and ignore translation for (int i = 0; i < 3; i++) { double[] p = this.flarray; for (int j = 0; j < 3; j++) { pv[i] += pt[i][j] * p[j]; } } return vout; } /** * create cross product. result = this x v3 does not alter this. * * @param v3 * vector to multiply * @return cross product */ public Vector3 cross(Vector3 v3) { Vector3 v1 = new Vector3(); int i, j, k; for (i = 0, j = 1, k = 2; i < 3; i++) { v1.flarray[i] = flarray[j] * v3.flarray[k] - flarray[k] * v3.flarray[j]; j = (j + 1) % 3; k = (k + 1) % 3; } return v1; } /** sets vector components to nearest integer value. * useful for crystallography and other grids * uses Math.round(); * ALTERS THIS * @return vector with integer components */ public Vector3 round() { for (int i = 0; i < 3; i++) { flarray[i] = Math.round(flarray[i]); } return this; } /** normalize vector. * alters this * this = this.normalize() * if zero vector takes no action (maybe this is bad...) * * @return vector of unit length */ public Vector3 normalize() { double veclength = this.getLength(); if (veclength < EPS) { throw new EuclidRuntimeException("cannot normalize zero-length vector"); } for (int i = 0; i < 3; i++) { flarray[i] /= veclength; } return this; } /** normalize vector. alters this this = this.normalize() if zero vector * takes no action (maybe this is bad...) * @deprecated (use normalize()) * @return vector of unit length */ public Vector3 normalise() { return this.normalize(); } /** * get normalized vector. * does not alter this * result = this.normalize() * if zero vector takes no action (maybe this is bad...) * * @return vector of unit length */ public Vector3 getUnitVector() { Vector3 v = new Vector3(this); v.normalize(); return v; } /** * return vector length. does not alter this result = this.length() * * @return vector length */ public double getLength() { double sum = 0.0; for (int i = 0; i < 3; i++) { sum += flarray[i] * flarray[i]; } return Math.sqrt(sum); } /** * create dot product. result = this . v3 does not alter this. * * @param v3 * vector to multiply * @return dot product */ public double dot(Vector3 v3) { double sum = 0.0; for (int i = 0; i < 3; i++) { sum += this.flarray[i] * v3.flarray[i]; } return sum; } /** * dot product - protected * * @param v3 * @return the dotproduct */ protected double dot(double[] v3) { double sum = 0.0; for (int i = 0; i < 3; i++) { sum += this.flarray[i] * v3[i]; } return sum; } /** * calculate unsigned angle between vectors result = angle between this and * v2 uses acos(this.dot.v2) so angle is unsigned does not alter this. * * @param v2 * vector to multiply * @return angle (null if vectors zero length */ public Angle getAngleMadeWith(Vector3 v2) { Angle a = null; if (!this.isZero() && !v2.isZero()) { Vector3 v1a = getUnitVector(); Vector3 v2a = v2.getUnitVector(); double tmp = v1a.dot(v2a); if (tmp < -1.0) { tmp = -1.0; } else if (tmp > 1.0) { tmp = 1.0; } a = new Angle(Math.acos(tmp)); } return a; } /** * calculate scalar triple product between vectors. result = this.(v2 x v3) * does not alter this. * * @param v2 * vector to multiply * @param v3 * vector to multiply * @return stp */ public double getScalarTripleProduct(Vector3 v2, Vector3 v3) { return this.dot(v2.cross(v3)); } /** * projection of this onto vector. does not alter this. result = vector.norm() * * (this.norm() dot vector.norm()) * * @param v * vector to project onto * @exception EuclidRuntimeException * vector or this is zero length * @return projected vector */ public Vector3 projectOnto(Vector3 v) throws EuclidRuntimeException { if (this.isZero() || v.isZero()) { throw new EuclidRuntimeException("zero length vector"); } Vector3 projection = new Vector3(); Vector3 unit3 = v.getUnitVector(); Vector3 unit2 = getUnitVector(); double dot = unit2.dot(unit3); projection = unit3.multiplyBy(getLength() * dot); return projection; } /** * are two vectors colinear. also returns true if one or more vectors are * zero * * @param v * vector to test with this * @return true if cross product isZero() */ public boolean isColinearVector(Vector3 v) { return this.cross(v).isZero(); } /** * get any vector not colinear with this. returns any axis which is not * colinear with this * * @return either XV or YV (even if this is zero) */ public Vector3 getNonColinearVector() { return isColinearVector(XV) ? YV : XV; } /** * get any vector perpendicular to this. useful for creating cartesian axes * containing this * * @return vector perpendicular to this (zero if this is zero) */ public Vector3 getPerpendicularVector() { return this.isZero() ? ZEROV : this.getNonColinearVector().cross(this); } /** * get string representation. * * @return string representation */ public String toString() { return EuclidConstants.S_LBRAK + flarray[0] + EuclidConstants.S_COMMA + flarray[1] + EuclidConstants.S_COMMA + flarray[2] + EuclidConstants.S_RBRAK; } } wwmm-euclid-87e8f785a814/src/main/java/org/xmlcml/euclid/Window2.java0000644000000000000000000000512611607017524023326 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid; /** a 2D window * (bounding box, viewport, etc) * Used with Transform2 @author (C) P. Murray-Rust, 2001 */ public class Window2 { public final static int X = 0; public final static int Y = 1; Real2 origin; Real2 farPoint; Real2 dim; public Window2(Real2 origin, Real2 farPoint) { this.origin = new Real2(origin); this.farPoint = new Real2(farPoint); getDim(); } public Real2 getDim() { this.dim = new Real2(farPoint.getX() - origin.getX(), farPoint.getY() - origin.getY()); return this.dim; } public Real2 getOrigin() {return origin;} public Real2 getFarPoint() {return farPoint;} /** get extent of a given axis (X or Y); */ public Real2 getExtent(int axis) { if (axis == X) return new Real2(origin.getX(), farPoint.getX()); if (axis == Y) return new Real2(origin.getY(), farPoint.getY()); return null; } /** convenience because negative lengths not allowed in awt */ public void drawRect(java.awt.Graphics g) { int x1 = (int) origin.getX(); int x2 = (int) farPoint.getX(); int y1 = (int) origin.getY(); int y2 = (int) farPoint.getY(); if (x1 > x2) {int t = x2; x2 = x1; x1 = t;} if (y1 > y2) {int t = y2; y2 = y1; y1 = t;} g.drawRect(x1, y1, x2-x1, y2-y1); } /** convenience because negative lengths not allowed in awt */ public void fillRect(java.awt.Graphics g) { int x1 = (int) origin.getX(); int x2 = (int) farPoint.getX(); int y1 = (int) origin.getY(); int y2 = (int) farPoint.getY(); if (x1 > x2) {int t = x2; x2 = x1; x1 = t;} if (y1 > y2) {int t = y2; y2 = y1; y1 = t;} g.fillRect(x1, y1, x2-x1, y2-y1); } public void transformBy(Transform2 tr) { origin.transformBy(tr); farPoint.transformBy(tr); getDim(); } public String toString() { return "Window2: "+origin+"/"+farPoint+"("+dim+")"; } } wwmm-euclid-87e8f785a814/src/main/resources/header.txt0000644000000000000000000000112711607017524020661 0ustar 00000000000000 Copyright 2011 Peter Murray-Rust Licensed 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.wwmm-euclid-87e8f785a814/src/test/java/org/xmlcml/euclid/test/AngleTest.java0000644000000000000000000002177711607017524024707 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid.test; import static org.xmlcml.euclid.EC.EPS; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.xmlcml.euclid.Angle; import org.xmlcml.euclid.Angle.Units; /** * test Angle. * * @author pmr * */ public class AngleTest { Angle zero; Angle pi4; Angle pi2; Angle pi; /** * setup. * * @throws Exception */ @Before public void setUp() throws Exception { zero = new Angle(0.); pi4 = new Angle(Math.PI / 4.); pi2 = new Angle(Math.PI / 2.); pi = new Angle(Math.PI); } /** * Test method for 'org.xmlcml.euclid.Angle.Angle(double)' */ @Test public void testAngleDouble() { Assert.assertEquals("pi/4", 45., pi4.getDegrees(), EPS); } /** * Test method for 'org.xmlcml.euclid.Angle.Angle(double, AngleType)' */ @Test public void testAngleDoubleAngleType() { Angle a1 = new Angle(1., Angle.Units.DEGREES); Assert.assertEquals("degrees ", Math.PI / 180., a1.getRadian(), EPS); a1 = new Angle(1., Angle.Units.RADIANS); Assert.assertEquals("degrees ", 1., a1.getRadian(), EPS); } /** * Test method for 'org.xmlcml.euclid.Angle.Angle(double, double)' */ @Test public void testAngleDoubleDouble() { Angle a1 = new Angle(1., 0.); Assert.assertEquals("degrees ", Math.PI / 2., a1.getRadian(), EPS); a1 = new Angle(1., 1.); Assert.assertEquals("degrees ", Math.PI / 4., a1.getRadian(), EPS); a1 = new Angle(0., 1.); Assert.assertEquals("degrees ", 0., a1.getRadian(), EPS); a1 = new Angle(0., -1.); Assert.assertEquals("degrees ", Math.PI, a1.getRadian(), EPS); a1 = new Angle(-1., -1.); Assert.assertEquals("degrees ", -3 * Math.PI / 4, a1.getRadian(), EPS); } /** * Test method for 'org.xmlcml.euclid.Angle.Angle(Angle)' */ @Test public void testAngleAngle() { Angle a1 = new Angle(pi2); Assert.assertEquals("degrees ", Math.PI / 2., a1.getRadian(), EPS); } /** * Test method for 'org.xmlcml.euclid.Angle.plus(Angle)' */ @Test public void testPlus() { Angle a1 = pi2.plus(pi4); Assert.assertEquals("degrees ", 3 * Math.PI / 4., a1.getRadian(), EPS); } /** * Test method for 'org.xmlcml.euclid.Angle.subtract(Angle)' */ @Test public void testSubtract() { Angle a1 = pi.subtract(pi4); Assert.assertEquals("degrees ", 3 * Math.PI / 4., a1.getRadian(), EPS); } /** * Test method for 'org.xmlcml.euclid.Angle.multiplyBy(double)' */ @Test public void testMultiplyBy() { Angle a1 = pi4.multiplyBy(3.); Assert.assertEquals("degrees ", 3 * Math.PI / 4., a1.getRadian(), EPS); } /** * Test method for 'org.xmlcml.euclid.Angle.cos()' */ @Test public void testCos() { double c = pi4.cos(); Assert.assertEquals("cos ", Math.sqrt(1. / 2.), c, EPS); } /** * Test method for 'org.xmlcml.euclid.Angle.sin()' */ @Test public void testSin() { double s = pi4.sin(); Assert.assertEquals("sin ", Math.sqrt(1. / 2.), s, 1.0E-08); } /** * Test method for 'org.xmlcml.euclid.Angle.tan()' */ @Test public void testTan() { double t = pi4.tan(); Assert.assertEquals("tan ", 1., t, 1.0E-08); } /** * Test method for 'org.xmlcml.euclid.Angle.normalise(double)' */ @Test public void testNormalise() { double a = Angle.normalise(3 * Math.PI); Assert.assertEquals("degrees ", Math.PI, a, EPS); } /** * Test method for 'org.xmlcml.euclid.Angle.isEqualTo(double)' */ @Test public void testIsEqualToDouble() { Assert.assertTrue("is equal", pi.isEqualTo(Math.PI)); Assert.assertFalse("is equal", pi.isEqualTo(Math.PI / 2)); } /** * Test method for 'org.xmlcml.euclid.Angle.greaterThan(double)' */ @Test public void testGreaterThanDouble() { Assert.assertTrue("GreaterThan", pi.greaterThan(Math.PI / 2)); Assert.assertFalse("GreaterThan", pi2.greaterThan(Math.PI)); Assert.assertFalse("GreaterThan", pi.greaterThan(Math.PI)); } /** * Test method for 'org.xmlcml.euclid.Angle.greaterThanOrEquals(double)' */ @Test public void testGreaterThanOrEqualsDouble() { Assert.assertTrue("GreaterThanOrEquals", pi .greaterThanOrEquals(Math.PI / 2)); Assert.assertFalse("GreaterThanOrEquals", pi2 .greaterThanOrEquals(Math.PI)); Assert.assertTrue("GreaterThanOrEquals", pi .greaterThanOrEquals(Math.PI)); } /** * Test method for 'org.xmlcml.euclid.Angle.lessThan(double)' */ @Test public void testLessThanDouble() { Assert.assertFalse("LessThan", pi.lessThan(Math.PI / 2)); Assert.assertTrue("LessThan", pi2.lessThan(Math.PI)); Assert.assertFalse("LessThan", pi.lessThan(Math.PI)); } /** * Test method for 'org.xmlcml.euclid.Angle.lessThanOrEquals(double)' */ @Test public void testLessThanOrEqualsDouble() { Assert .assertFalse("LessThanOrEquals", pi .lessThanOrEquals(Math.PI / 2)); Assert.assertTrue("LessThanOrEquals", pi2.lessThanOrEquals(Math.PI)); Assert.assertTrue("LessThanOrEquals", pi.lessThanOrEquals(Math.PI)); } /** * Test method for 'org.xmlcml.euclid.Angle.isEqualTo(Angle)' */ @Test public void testIsEqualToAngle() { Assert.assertTrue("is equal", pi.isEqualTo(pi)); Assert.assertFalse("is equal", pi.isEqualTo(pi2)); } /** * Test method for 'org.xmlcml.euclid.Angle.greaterThan(Angle)' */ @Test public void testGreaterThanAngle() { Assert.assertTrue("GreaterThan", pi.greaterThan(pi2)); Assert.assertFalse("GreaterThan", pi2.greaterThan(pi)); Assert.assertFalse("GreaterThan", pi.greaterThan(pi)); } /** * Test method for 'org.xmlcml.euclid.Angle.greaterThanOrEquals(Angle)' */ @Test public void testGreaterThanOrEqualsAngle() { Assert.assertTrue("GreaterThanOrEquals", pi.greaterThanOrEquals(pi2)); Assert.assertFalse("GreaterThanOrEquals", pi2.greaterThanOrEquals(pi)); Assert.assertTrue("GreaterThanOrEquals", pi.greaterThanOrEquals(pi)); } /** * Test method for 'org.xmlcml.euclid.Angle.lessThan(Angle)' */ @Test public void testLessThanAngle() { Assert.assertFalse("LessThan", pi.lessThan(pi2)); Assert.assertTrue("LessThan", pi2.lessThan(pi)); Assert.assertFalse("LessThan", pi.lessThan(pi)); } /** * Test method for 'org.xmlcml.euclid.Angle.lessThanOrEquals(Angle)' */ @Test public void testLessThanOrEqualsAngle() { Assert.assertFalse("LessThanOrEquals", pi.lessThanOrEquals(pi2)); Assert.assertTrue("LessThanOrEquals", pi2.lessThanOrEquals(pi)); Assert.assertTrue("LessThanOrEquals", pi.lessThanOrEquals(pi)); } /** * Test method for 'org.xmlcml.euclid.Angle.getAngle()' */ @Test public void testGetAngle() { double a = pi2.getAngle(); Assert.assertEquals("get angle", Math.PI / 2, a, EPS); } /** * Test method for 'org.xmlcml.euclid.Angle.getRadian()' */ @Test public void testGetRadian() { double a = pi2.getRadian(); Assert.assertEquals("get radian", Math.PI / 2, a, EPS); } /** * Test method for 'org.xmlcml.euclid.Angle.getDegrees()' */ @Test public void testGetDegrees() { double a = pi2.getDegrees(); Assert.assertEquals("get degrees", 90., a, EPS); } /** * Test method for 'org.xmlcml.euclid.Angle.putDegrees(double)' */ @Test public void testPutDegrees() { pi2.putDegrees(60.); Assert.assertEquals("put degrees", 60., pi2.getDegrees(), 1.0E-08); Assert.assertEquals("put degrees", Math.PI / 3., pi2.getRadian(), EPS); } /** * Test method for 'org.xmlcml.euclid.Angle.setRange(AngleRange)' */ @Test public void testSetRange() { pi2.putDegrees(-60.); pi2.setRange(Angle.Range.UNSIGNED); Assert.assertEquals("put degrees", 300., pi2.getDegrees(), 1.0E-08); Assert.assertEquals("put degrees", 5. * Math.PI / 3., pi2.getRadian(), EPS); } /** * Test method for 'org.xmlcml.euclid.Angle.Angle(double, Units)' */ @Test public void testAngleDoubleUnits() { Angle a = new Angle(90, Units.DEGREES); Assert.assertEquals("degrees", 90, a.getDegrees(), EPS); Assert.assertEquals("radians", 90 * Math.PI / 180., a.getRadian(), EPS); a = new Angle(1, Units.RADIANS); Assert.assertEquals("degrees", 180. / Math.PI, a.getDegrees(), EPS); Assert.assertEquals("radians", 1., a.getRadian(), EPS); a = new Angle(10, Units.RADIANS); Assert.assertEquals("degrees", 10. * 180. / Math.PI, a.getDegrees(), EPS); Assert.assertEquals("radians", 10., a.getRadian(), EPS); } } wwmm-euclid-87e8f785a814/src/test/java/org/xmlcml/euclid/test/ComplexTest.java0000644000000000000000000001303011607017524025247 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid.test; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.xmlcml.euclid.Angle; import org.xmlcml.euclid.Complex; import org.xmlcml.euclid.Polar; import org.xmlcml.euclid.Real2; /** * test Complex. * * @author pmr * */ public class ComplexTest { private static final double EPS = 1E-14; Complex c0; Complex c1; Complex c2; /** * setup. * * @throws Exception */ @Before public void setUp() throws Exception { c0 = new Complex(); c1 = new Complex(1, 0); c2 = new Complex(1, 2); } /** * Test method for 'org.xmlcml.euclid.Complex.negative()' */ @Test public void testNegative() { c2.negative(); Assert.assertEquals("negative", -1., c2.getReal(),EPS); Assert.assertEquals("negative", -2., c2.getImaginary(),EPS); } /** * Test method for 'org.xmlcml.euclid.Complex.toString()' */ @Test public void testToString() { String s = c2.toString(); Assert.assertEquals("to string", "1.0,2.0", s); } /** * Test method for 'org.xmlcml.euclid.Complex.Complex()' */ @Test public void testComplex() { String s = c0.toString(); Assert.assertEquals("to string", "0.0,0.0", s); Assert.assertEquals("empty ", 0., c0.getReal(),EPS); Assert.assertEquals("empty", 0., c0.getImaginary(),EPS); } /** * Test method for 'org.xmlcml.euclid.Complex.Complex(double)' */ @Test public void testComplexDouble() { Complex c = new Complex(3.); Assert.assertEquals("to string", "3.0,0.0", c.toString()); } /** * Test method for 'org.xmlcml.euclid.Complex.Complex(double, double)' */ @Test public void testComplexDoubleDouble() { Complex c = new Complex(3., 2.); Assert.assertEquals("to string", "3.0,2.0", c.toString()); } /** * Test method for 'org.xmlcml.euclid.Complex.Complex(Real2)' */ @Test public void testComplexReal2() { Complex c = new Complex(new Real2(3., 2.)); Assert.assertEquals("real 2", "3.0,2.0", c.toString()); } /** * Test method for 'org.xmlcml.euclid.Complex.Complex(double, Angle)' */ @Test public void testComplexDoubleAngle() { Angle a = new Angle(60., Angle.Units.DEGREES); Complex c = new Complex(1., a); Assert.assertEquals("length angle", 1. / 2., c.getReal(), 1.0E-08); Assert.assertEquals("length angle", Math.sqrt(3.) / 2., c .getImaginary(), 1.0E-08); } /** * Test method for 'org.xmlcml.euclid.Complex.Complex(Polar)' */ @Test public void testComplexPolar() { Polar p = new Polar(1., 2.); Complex c = new Complex(p); Assert.assertEquals("polar", 1., c.getReal(), 1.0E-08); Assert.assertEquals("polar", 2., c.getImaginary(), 1.0E-08); } /** * Test method for 'org.xmlcml.euclid.Complex.Complex(Complex)' */ @Test public void testComplexComplex() { Complex c = new Complex(c2); Assert.assertEquals("complex", 1., c.getReal(), 1.0E-08); Assert.assertEquals("complex", 2., c.getImaginary(), 1.0E-08); } /** * Test method for 'org.xmlcml.euclid.Complex.getReal()' */ @Test public void testGetReal() { Assert.assertEquals("real", 1., c2.getReal(), 1.0E-08); } /** * Test method for 'org.xmlcml.euclid.Complex.getImaginary()' */ @Test public void testGetImaginary() { Assert.assertEquals("imaginary", 2., c2.getImaginary(), 1.0E-08); } /** * Test method for 'org.xmlcml.euclid.Complex.multiply(Complex)' */ @Test public void testMultiply() { Complex c = c2.multiply(c2); Assert.assertEquals("multiply", -3., c.getReal(), 1.0E-08); Assert.assertEquals("multiply", 4., c.getImaginary(), 1.0E-08); } /** * Test method for 'org.xmlcml.euclid.Complex.divideBy(Complex)' */ @Test public void testDivideBy() { Complex c = c1.divideBy(c2); Assert.assertEquals("divide", 0.2, c.getReal(), 1.0E-08); Assert.assertEquals("divide", -0.4, c.getImaginary(), 1.0E-08); } /** * Test method for 'org.xmlcml.euclid.Complex.getR()' */ @Test public void testGetR() { double r = c2.getR(); Assert.assertEquals("R", Math.sqrt(5.), r, 1.0E-08); } /** * Test method for 'org.xmlcml.euclid.Complex.getTheta()' */ @Test public void testGetTheta() { Angle a = c2.getTheta(); Assert.assertEquals("theta", Math.atan2(2., 1.), a.getAngle(), 1.0E-08); } /** * Test method for 'org.xmlcml.euclid.Complex.getPolar()' */ @Test public void testGetPolar() { Polar p = c2.getPolar(); Angle a = p.getTheta(); Assert.assertEquals("R", Math.sqrt(5.), p.getR(), 1.0E-08); Assert.assertEquals("theta", Math.atan2(2., 1.), a.getAngle(), 1.0E-08); } /** * Test method for 'org.xmlcml.euclid.Complex.sqrt(Complex)' */ @Test public void testSqrt() { Complex c = Complex.sqrt(c2); Assert.assertEquals("sqrt x", 1.2720196, c.getReal(), 0.000001); Assert.assertEquals("sqrt y", 0.786151, c.getImaginary(), 0.000001); } } wwmm-euclid-87e8f785a814/src/test/java/org/xmlcml/euclid/test/EuclidTestUtils.java0000644000000000000000000000160511607017524026073 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid.test; import org.apache.log4j.Logger; public class EuclidTestUtils { /** logger */ public final static Logger logger = Logger.getLogger(EuclidTestUtils.class.getName()); public final static String BASE_RESOURCE = "org/xmlcml/euclid"; } wwmm-euclid-87e8f785a814/src/test/java/org/xmlcml/euclid/test/GeomTest.java0000644000000000000000000000550411607017524024536 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid.test; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.xmlcml.euclid.Line3; import org.xmlcml.euclid.Plane3; import org.xmlcml.euclid.Point3; import org.xmlcml.euclid.Transform3; import org.xmlcml.euclid.Vector3; /** * parent class for geom tests. * * @author pmr * */ public class GeomTest { Line3 l0; Line3 l100000; Line3 l123456; Plane3 pl0; Plane3 pl1000; Plane3 pl0100; Plane3 pl0010; Plane3 pl1234; Plane3 pl1111; Point3 p0; Point3 p000; Point3 p100; Point3 p010; Point3 p001; Point3 p111; Point3 p123; Point3 p321; Transform3 tr0; Transform3 tr1; Transform3 tr2; Vector3 v0; Vector3 v000; Vector3 v100; Vector3 v010; Vector3 v001; Vector3 v123; Vector3 v321; final static double s14 = Math.sqrt(14.); final static double s3 = Math.sqrt(3.); final static double s2 = Math.sqrt(2.); /** * setup. * * @throws Exception */ @Before public void setUp() throws Exception { l0 = new Line3(); l100000 = new Line3(new Point3(0., 0., 0.), new Vector3(1., 0., 0.)); l123456 = new Line3(new Point3(4., 5., 6.), new Vector3(1., 2., 3.)); pl0 = new Plane3(); pl1000 = new Plane3(1., 0., 0., 0); pl0100 = new Plane3(0., 1., 0., 0.); pl0010 = new Plane3(new double[] { 0., 0., 1., 0. }); pl1234 = new Plane3(new double[] { 1., 2., 3. }, 4.); pl1111 = new Plane3(new Vector3(1., 1., 1.), 1.); p0 = new Point3(); p000 = new Point3(0., 0., 0.); p100 = new Point3(1., 0., 0.); p010 = new Point3(0., 1., 0.); p001 = new Point3(0., 0., 1.); p111 = new Point3(1., 1., 1.); p123 = new Point3(1., 2., 3.); p321 = new Point3(3., 2., 1.); tr0 = new Transform3(); tr1 = new Transform3("x, -y, z"); tr2 = new Transform3("-x, -y, z"); v0 = new Vector3(); v000 = new Vector3(0., 0., 0.); v100 = new Vector3(1., 0., 0.); v010 = new Vector3(0., 1., 0.); v001 = new Vector3(0., 0., 1.); v123 = new Vector3(1., 2., 3.); v321 = new Vector3(3., 2., 1.); } /** test */ @Test public void testDummy() { Assert.assertNotNull(p0); } } wwmm-euclid-87e8f785a814/src/test/java/org/xmlcml/euclid/test/Int2RangeTest.java0000644000000000000000000001402311607017524025434 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid.test; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.xmlcml.euclid.Int2; import org.xmlcml.euclid.Int2Range; import org.xmlcml.euclid.IntRange; /** * test Int2Range * * @author pmr * */ public class Int2RangeTest { Int2Range i2r0; Int2Range i2r1; Int2Range i2r2; /** * main * * @param args */ public static void main(String[] args) { } /** * setup. * * @throws Exception */ @Before public void setUp() throws Exception { i2r0 = new Int2Range(); i2r1 = new Int2Range(new IntRange(1, 2), new IntRange(1, 2)); i2r2 = new Int2Range(new IntRange(1, 2), new IntRange(3, 4)); } /** * Test method for 'org.xmlcml.euclid.Int2Range.Int2Range()' */ @Test public void testInt2Range() { Assert.assertEquals("empty", "(NULL,NULL)", i2r0.toString()); } /** * Test method for 'org.xmlcml.euclid.Int2Range.Int2Range(IntRange, * IntRange)' */ @Test public void testInt2RangeIntRangeIntRange() { Assert.assertEquals("empty", "((1,2),(3,4))", i2r2.toString()); } /** * Test method for 'org.xmlcml.euclid.Int2Range.Int2Range(Int2Range)' */ @Test public void testInt2RangeInt2Range() { Int2Range ii = new Int2Range(i2r2); Assert.assertEquals("empty", "((1,2),(3,4))", ii.toString()); } /** * Test method for 'org.xmlcml.euclid.Int2Range.isValid()' */ @Test public void testIsValid() { Assert.assertTrue("valid", i2r2.isValid()); Assert.assertFalse("invalid", i2r0.isValid()); } /** * Test method for 'org.xmlcml.euclid.Int2Range.isEqualTo(Int2Range)' */ @Test public void testIsEqualTo() { Assert.assertTrue("isEqual", i2r2.isEqualTo(i2r2)); Assert.assertFalse("isEqual", i2r2.isEqualTo(i2r1)); Assert.assertFalse("isEqual", i2r0.isEqualTo(i2r0)); } /** * Test method for 'org.xmlcml.euclid.Int2Range.plus(Int2Range)' */ @Test public void testPlus() { Int2Range ix = new Int2Range(new IntRange(1, 4), new IntRange(11, 14)); Int2Range iy = new Int2Range(new IntRange(2, 5), new IntRange(12, 15)); Int2Range ii = ix.plus(iy); Assert.assertEquals("plus", "((1,5),(11,15))", ii.toString()); iy = new Int2Range(new IntRange(2, 3), new IntRange(12, 13)); ii = ix.plus(iy); Assert.assertEquals("plus", "((1,4),(11,14))", ii.toString()); iy = new Int2Range(new IntRange(0, 8), new IntRange(10, 18)); ii = ix.plus(iy); Assert.assertEquals("plus", "((0,8),(10,18))", ii.toString()); } /** * Test method for 'org.xmlcml.euclid.Int2Range.intersectionWith(Int2Range)' */ @Test public void testIntersectionWith() { Int2Range ix = new Int2Range(new IntRange(1, 4), new IntRange(11, 14)); Int2Range iy = new Int2Range(new IntRange(2, 5), new IntRange(12, 15)); Int2Range ii = ix.intersectionWith(iy); Assert.assertEquals("plus", "((2,4),(12,14))", ii.toString()); iy = new Int2Range(new IntRange(2, 3), new IntRange(12, 13)); ii = ix.intersectionWith(iy); Assert.assertEquals("plus", "((2,3),(12,13))", ii.toString()); iy = new Int2Range(new IntRange(0, 8), new IntRange(10, 18)); ii = ix.intersectionWith(iy); Assert.assertEquals("plus", "((1,4),(11,14))", ii.toString()); } /** * Test method for 'org.xmlcml.euclid.Int2Range.getXRange()' */ @Test public void testGetXRange() { Assert.assertEquals("getXRange", "NULL", i2r0.getXRange().toString()); Assert.assertEquals("getXRange", "(1,2)", i2r2.getXRange().toString()); } /** * Test method for 'org.xmlcml.euclid.Int2Range.getYRange()' */ @Test public void testGetYRange() { Assert.assertEquals("getXRange", "NULL", i2r0.getYRange().toString()); Assert.assertEquals("getXRange", "(3,4)", i2r2.getYRange().toString()); } /** * Test method for 'org.xmlcml.euclid.Int2Range.includes(Int2)' */ @Test public void testIncludesInt2() { Int2Range ix = new Int2Range(new IntRange(1, 4), new IntRange(11, 14)); Assert.assertTrue("include", ix.includes(new Int2(2, 12))); Assert.assertTrue("include", ix.includes(new Int2(1, 11))); Assert.assertTrue("include", ix.includes(new Int2(4, 14))); Assert.assertFalse("include", ix.includes(new Int2(1, 15))); } /** * Test method for 'org.xmlcml.euclid.Int2Range.includes(Int2Range)' */ @Test public void testIncludesInt2Range() { Int2Range ix = new Int2Range(new IntRange(1, 4), new IntRange(11, 14)); Assert.assertTrue("include", ix.includes(new Int2Range(new IntRange(2, 3), new IntRange(12, 13)))); Assert.assertTrue("include", ix.includes(new Int2Range(new IntRange(1, 4), new IntRange(11, 14)))); Assert.assertFalse("include", ix.includes(new Int2Range(new IntRange(0, 4), new IntRange(10, 14)))); Assert.assertFalse("include", ix.includes(new Int2Range(new IntRange(2, 5), new IntRange(12, 15)))); } /** * Test method for 'org.xmlcml.euclid.Int2Range.add(Int2)' */ @Test public void testAdd() { Int2Range ii = new Int2Range(new IntRange(1, 4), new IntRange(11, 14)); Assert.assertEquals("plus", "((1,4),(11,14))", ii.toString()); Int2 i2 = new Int2(2, 12); ii.add(i2); Assert.assertEquals("plus", "((1,4),(11,14))", ii.toString()); i2 = new Int2(0, 15); ii.add(i2); Assert.assertEquals("plus", "((0,4),(11,15))", ii.toString()); i2 = new Int2(8, 7); ii.add(i2); Assert.assertEquals("plus", "((0,8),(7,15))", ii.toString()); } } wwmm-euclid-87e8f785a814/src/test/java/org/xmlcml/euclid/test/Int2Test.java0000644000000000000000000001153211607017524024461 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid.test; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.xmlcml.euclid.Int2; /** * test Int2 * * @author pmr * */ public class Int2Test { Int2 i0; Int2 i11; Int2 i12; /** * setup. * * @throws Exception */ @Before public void setUp() throws Exception { i0 = new Int2(); i11 = new Int2(1, 1); i12 = new Int2(1, 2); } /** * Test method for 'org.xmlcml.euclid.Int2.Int2()' */ @Test public void testInt2() { Assert.assertEquals("int2", "(0,0)", i0.toString()); } /** * Test method for 'org.xmlcml.euclid.Int2.Int2(int, int)' */ @Test public void testInt2IntInt() { Assert.assertEquals("int2", "(1,2)", i12.toString()); } /** * Test method for 'org.xmlcml.euclid.Int2.Int2(Int2)' */ @Test public void testInt2Int2() { Int2 ii = new Int2(i12); Assert.assertEquals("int2", "(1,2)", ii.toString()); } /** * Test method for 'org.xmlcml.euclid.Int2.swap()' */ @Test public void testSwap() { i12.swap(); Assert.assertEquals("int2", "(2,1)", i12.toString()); } /** * Test method for 'org.xmlcml.euclid.Int2.sortAscending()' */ @Test public void testSortAscending() { i12.sortAscending(); Assert.assertEquals("int2", "(1,2)", i12.toString()); } /** * Test method for 'org.xmlcml.euclid.Int2.sortDescending()' */ @Test public void testSortDescending() { i12.sortDescending(); Assert.assertEquals("int2", "(2,1)", i12.toString()); } /** * Test method for 'org.xmlcml.euclid.Int2.clear()' */ @Test public void testClear() { i12.clear(); Assert.assertEquals("int2", "(0,0)", i12.toString()); } /** * Test method for 'org.xmlcml.euclid.Int2.setX(int)' */ @Test public void testSetX() { i12.setX(3); Assert.assertEquals("int2", "(3,2)", i12.toString()); } /** * Test method for 'org.xmlcml.euclid.Int2.setY(int)' */ @Test public void testSetY() { i12.setY(3); Assert.assertEquals("int2", "(1,3)", i12.toString()); } /** * Test method for 'org.xmlcml.euclid.Int2.isEqualTo(Int2)' */ @Test public void testIsEqualTo() { Assert.assertTrue("equals", i12.isEqualTo(i12)); Assert.assertFalse("equals", i11.isEqualTo(i12)); } /** * Test method for 'org.xmlcml.euclid.Int2.plus(Int2)' */ @Test public void testPlus() { Int2 ii = i12.plus(i11); Assert.assertEquals("plus", "(2,3)", ii.toString()); } /** * Test method for 'org.xmlcml.euclid.Int2.subtract(Int2)' */ @Test public void testSubtract() { Int2 ii = i12.subtract(i11); Assert.assertEquals("subtract", "(0,1)", ii.toString()); } /** * Test method for 'org.xmlcml.euclid.Int2.negative()' */ @Test public void testNegative() { i12.negative(); Assert.assertEquals("negative", "(-1,-2)", i12.toString()); } /** * Test method for 'org.xmlcml.euclid.Int2.multiplyBy(int)' */ @Test public void testMultiplyBy() { Int2 ii = i12.multiplyBy(3); Assert.assertEquals("multiply", "(3,6)", ii.toString()); } /** * Test method for 'org.xmlcml.euclid.Int2.getX()' */ @Test public void testGetX() { Assert.assertEquals("getX", 1, i12.getX()); } /** * Test method for 'org.xmlcml.euclid.Int2.getY()' */ @Test public void testGetY() { Assert.assertEquals("getY", 2, i12.getY()); } /** * Test method for 'org.xmlcml.euclid.Int2.elementAt(int)' */ @Test public void testElementAt() { Assert.assertEquals("elementAt", 1, i12.elementAt(0)); Assert.assertEquals("elementAt", 2, i12.elementAt(1)); } /** * Test method for 'org.xmlcml.euclid.Int2.getMidPoint(Int2)' */ @Test public void testGetMidPoint() { Int2 m = i12.getMidPoint(new Int2(3, 4)); Assert.assertEquals("mid point", "(2,3)", m.toString()); } /** * Test method for 'org.xmlcml.euclid.Int2.dotProduct(Int2)' */ @Test public void testDotProduct() { int i = i12.dotProduct(new Int2(3, 4)); Assert.assertEquals("dor", 11, i); } /** * Test method for 'org.xmlcml.euclid.Int2.toString()' */ @Test public void testToString() { Assert.assertEquals("toString", "(1,2)", i12.toString()); } } wwmm-euclid-87e8f785a814/src/test/java/org/xmlcml/euclid/test/IntArrayTest.java0000644000000000000000000004672011607017524025405 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid.test; import static org.xmlcml.euclid.EC.S_EMPTY; import static org.xmlcml.euclid.EC.S_RBRAK; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.xmlcml.euclid.EuclidRuntimeException; import org.xmlcml.euclid.Int; import org.xmlcml.euclid.IntArray; import org.xmlcml.euclid.IntRange; import org.xmlcml.euclid.IntSet; import org.xmlcml.euclid.ArrayBase.Trim; /** * test IntArray * * @author pmr * */ public class IntArrayTest { IntArray a0; IntArray a1; /** * setup. * * @throws Exception */ @Before public void setUp() throws Exception { a0 = new IntArray(); a1 = new IntArray(new int[] { 1, 2, 4, 6 }); } /** * equality test. true if both args not null and equal * * @param msg * message * @param test * @param expected */ public static void assertEquals(String msg, IntArray test, IntArray expected) { Assert.assertNotNull("test should not be null (" + msg + S_RBRAK, test); Assert.assertNotNull("expected should not be null (" + msg + S_RBRAK, expected); String s = Int.testEquals(test.getArray(), expected.getArray()); if (s != null) { Assert.fail(msg + "; " + s); } } /** * equality test. true if both args not null and equal * * @param msg * message * @param test * @param expected */ public static void assertEquals(String msg, int[] test, IntArray expected) { Assert.assertNotNull("test should not be null (" + msg + S_RBRAK, test); Assert.assertNotNull("expected should not be null (" + msg + S_RBRAK, expected); Assert.assertEquals("must be of equal length ", test.length, expected .getArray().length); String s = Int.testEquals(test, expected.getArray()); if (s != null) { Assert.fail(msg + "; " + s); } } /** * Test method for 'org.xmlcml.euclid.IntArray.IntArray()' */ @Test public void testIntArray() { Assert.assertEquals("empty", 0, a0.size()); Assert.assertEquals("empty", "()", a0.toString()); } /** * Test method for 'org.xmlcml.euclid.IntArray.IntArray(int)' */ @Test public void testIntArrayInt() { IntArray r = new IntArray(4); Assert.assertEquals("r", 4, r.size()); IntArrayTest.assertEquals("r", new int[] { 0, 0, 0, 0 }, r); } /** * Test method for 'org.xmlcml.euclid.IntArray.IntArray(int, int, int)' */ @Test public void testIntArrayIntDoubleDouble() { IntArray r = new IntArray(4, 1, 2); Assert.assertEquals("r", 4, r.size()); IntArrayTest.assertEquals("r", new int[] { 1, 3, 5, 7 }, r); } /** * Test method for 'org.xmlcml.euclid.IntArray.IntArray(int, int)' */ @Test public void testIntArrayIntDouble() { IntArray r = new IntArray(4, 2); Assert.assertEquals("r", 4, r.size()); IntArrayTest.assertEquals("r", new int[] { 2, 2, 2, 2 }, r); } /** * Test method for 'org.xmlcml.euclid.IntArray.IntArray(int, int[])' */ @Test public void testIntArrayIntDoubleArray() { int[] d = { 1, 2, 3, 4 }; IntArray r = new IntArray(3, d); Assert.assertEquals("r", 3, r.size()); IntArrayTest.assertEquals("r", new int[] { 1, 2, 3 }, r); try { r = new IntArray(5, d); Assert.fail("should always throw " + "Array size too small"); } catch (EuclidRuntimeException e) { Assert .assertEquals("int[]", "Array would overflow", e .getMessage()); } } /** * Test method for 'org.xmlcml.euclid.IntArray.IntArray(int[])' */ @Test public void testIntArrayDoubleArray() { int[] d = { 1, 2, 3, 4 }; IntArray r = new IntArray(d); Assert.assertEquals("r", 4, r.size()); IntArrayTest.assertEquals("r", new int[] { 1, 2, 3, 4 }, r); } /** * Test method for 'org.xmlcml.euclid.IntArray.IntArray(IntArray, int, int)' */ @Test public void testIntArrayIntArrayIntInt() { IntArray r = new IntArray(a1, 1, 2); Assert.assertEquals("r", 2, r.size()); IntArrayTest.assertEquals("r", new int[] { 2, 4 }, r); try { r = new IntArray(a1, 0, 5); } catch (EuclidRuntimeException e) { Assert.assertEquals("int array", "index out of range: 0/5", e .getMessage()); } } /** * Test method for 'org.xmlcml.euclid.IntArray.IntArray(IntArray, IntArray)' */ @Test public void testIntArrayIntArrayIntArray() { IntArray r = new IntArray(a1, new IntArray(new int[] { 3, 1, 2 })); Assert.assertEquals("r", 3, r.size()); IntArrayTest.assertEquals("r", new int[] { 6, 2, 4 }, r); } /** * Test method for 'org.xmlcml.euclid.IntArray.IntArray(IntArray)' */ @Test public void testIntArrayIntArray() { IntArray r = new IntArray(a1); Assert.assertEquals("r", 4, r.size()); IntArrayTest.assertEquals("r", new int[] { 1, 2, 4, 6 }, r); } /** * Test method for 'org.xmlcml.euclid.IntArray.IntArray(String[])' */ @Test public void testIntArrayStringArray() { IntArray r = new IntArray(new String[] { "1", "2", "4", "6" }); IntArrayTest.assertEquals("string array", a1, r); } /** * Test method for 'org.xmlcml.euclid.IntArray.IntArray(String)' */ @Test public void testIntArrayString() { IntArray r = new IntArray("1 2 4 6"); IntArrayTest.assertEquals("string array", a1, r); } /** * Test method for 'org.xmlcml.euclid.IntArray.elementAt(int)' */ @Test public void testElementAt() { Assert.assertEquals("element at", 4, a1.elementAt(2)); try { Assert.assertEquals("element at", 4, a1.elementAt(5)); Assert.fail("should always throw " + "ArrayIndexOutOfBoundsException"); } catch (ArrayIndexOutOfBoundsException e) { Assert.assertEquals("ArrayIndexOutOfBoundsException", "5", e .getMessage()); } } /** * Test method for 'org.xmlcml.euclid.IntArray.size()' */ @Test public void testSize() { Assert.assertEquals("size", 0, a0.size()); Assert.assertEquals("size", 4, a1.size()); } /** * Test method for 'org.xmlcml.euclid.IntArray.getArray()' */ @Test public void testGetArray() { String s = Int.testEquals((new int[] {}), a0.getArray()); if (s != null) { Assert.fail("array" + "; " + s); } s = Int.testEquals((new int[] { 1, 2, 4, 6 }), a1.getArray()); if (s != null) { Assert.fail("array" + "; " + s); } } /** * Test method for 'org.xmlcml.euclid.IntArray.clearArray()' */ @Test public void testClearArray() { a1.clearArray(); IntArrayTest.assertEquals("clear", new int[] { 0, 0, 0, 0 }, a1); } /** * Test method for 'org.xmlcml.euclid.IntArray.getReverseArray()' */ @Test public void testGetReverseArray() { int[] d = a1.getReverseArray(); String s = Int.testEquals((new int[] { 6, 4, 2, 1 }), d); if (s != null) { Assert.fail("clear" + "; " + s); } } /** * Test method for 'org.xmlcml.euclid.IntArray.isEqualTo(IntArray)' */ @Test public void testIsEqualTo() { IntArray a = new IntArray("1 2 4 6"); Assert.assertTrue("isEqualTo", a1.isEqualTo(a)); a = new IntArray("1 2 4"); Assert.assertFalse("isEqualTo", a1.isEqualTo(a)); } /** * Test method for 'org.xmlcml.euclid.IntArray.equals(IntArray, int)' */ @Test public void testEqualsIntArrayDouble() { IntArray a = new IntArray("1 2 4 6"); Assert.assertTrue("isEqualTo", a1.equals(a)); a = new IntArray("1 2 4 7"); Assert.assertFalse("isEqualTo", a1.equals(a)); a = new IntArray("1 2 4"); Assert.assertFalse("isEqualTo", a1.equals(a)); } /** * Test method for 'org.xmlcml.euclid.IntArray.plus(IntArray)' */ @Test public void testPlus() { IntArray a2 = a1.plus(new IntArray("10 20 30 40")); IntArrayTest.assertEquals("plus", new int[] { 11, 22, 34, 46 }, a2); } /** * Test method for 'org.xmlcml.euclid.IntArray.subtract(IntArray)' */ @Test public void testSubtract() { IntArray a2 = a1.subtract(new IntArray("10 20 30 40")); IntArrayTest.assertEquals("subtract", new int[] { -9, -18, -26, -34 }, a2); } /** * Test method for 'org.xmlcml.euclid.IntArray.subtractEquals(IntArray)' */ @Test public void testSubtractEquals() { IntArray ia = new IntArray("10 20 30 40"); a1.subtractEquals(ia); IntArrayTest.assertEquals("subtract", new int[] { -9, -18, -26, -34 }, a1); } /** * Test method for 'org.xmlcml.euclid.IntArray.negative()' */ @Test public void testNegative() { a1.negative(); IntArrayTest.assertEquals("negative", new int[] { -1, -2, -4, -6 }, a1); } /** * Test method for 'org.xmlcml.euclid.IntArray.multiplyBy(int)' */ @Test public void testMultiplyBy() { IntArray a = a1.multiplyBy(2); IntArrayTest.assertEquals("multiplyBy", new int[] { 2, 4, 8, 12 }, a); } /** * Test method for 'org.xmlcml.euclid.IntArray.setElementAt(int, int)' */ @Test public void testSetElementAt() { a1.setElementAt(2, 10); IntArrayTest.assertEquals("setElement", new int[] { 1, 2, 10, 6 }, a1); } /** * Test method for 'org.xmlcml.euclid.IntArray.getSubArray(int, int)' */ @Test public void testGetSubArray() { IntArray a = a1.getSubArray(2, 3); IntArrayTest.assertEquals("subArray", new int[] { 4, 6 }, a); a = a1.getSubArray(2, 2); IntArrayTest.assertEquals("subArray", new int[] { 4 }, a); a = a1.getSubArray(0, 3); IntArrayTest.assertEquals("subArray", new int[] { 1, 2, 4, 6 }, a); try { a = a1.getSubArray(0, 5); Assert.fail("should always throw " + "ArrayIndexOutOfBoundsException"); } catch (ArrayIndexOutOfBoundsException e) { Assert.assertEquals("subArray ArrayIndexOutOfBoundsException", "java.lang.ArrayIndexOutOfBoundsException", S_EMPTY + e); } } /** * Test method for 'org.xmlcml.euclid.IntArray.setElements(int, int[])' */ @Test public void testSetElements() { a1.setElements(1, new int[] { 10, 20 }); IntArrayTest.assertEquals("setElement", new int[] { 1, 10, 20, 6 }, a1); try { a1.setElements(1, new int[] { 10, 20, 30, 40 }); Assert.fail("should always throw " + "ArrayIndexOutOfBoundsException"); } catch (ArrayIndexOutOfBoundsException e) { Assert.assertEquals("subArray ArrayIndexOutOfBoundsException", "java.lang.ArrayIndexOutOfBoundsException", S_EMPTY + e); } } /** * Test method for 'org.xmlcml.euclid.IntArray.isClear()' */ @Test public void testIsClear() { Assert.assertFalse("isClear", a1.isClear()); a1.clearArray(); Assert.assertTrue("isClear", a1.isClear()); } /** * Test method for 'org.xmlcml.euclid.IntArray.setAllElements(int)' */ @Test public void testSetAllElements() { a1.setAllElements(10); IntArrayTest.assertEquals("setElement", new int[] { 10, 10, 10, 10 }, a1); } /** * Test method for 'org.xmlcml.euclid.IntArray.sumAllElements()' */ @Test public void testSumAllElements() { Assert.assertEquals("sum", 13, a1.sumAllElements()); } /** * Test method for 'org.xmlcml.euclid.IntArray.absSumAllElements()' */ @Test public void testAbsSumAllElements() { IntArray a = new IntArray("-1 3 -11 14"); Assert.assertEquals("sum", 5, a.sumAllElements()); Assert.assertEquals("absSum", 29, a.absSumAllElements()); } /** * Test method for 'org.xmlcml.euclid.IntArray.innerProduct()' */ @Test public void testInnerProduct() { Assert.assertEquals("inner", 57, a1.innerProduct()); } /** * Test method for 'org.xmlcml.euclid.IntArray.dotProduct(IntArray)' */ @Test public void testDotProduct() { IntArray a = new IntArray("1 2 3 4"); int d = a1.dotProduct(a); Assert.assertEquals("dot", 41, d); a = new IntArray("1 2 3"); try { a1.dotProduct(a); Assert.fail("should always throw " + "ArrayIndexOutOfBoundsException"); } catch (EuclidRuntimeException e) { Assert.assertEquals("dot", "org.xmlcml.euclid.EuclidRuntimeException", S_EMPTY + e); } } /** * Test method for 'org.xmlcml.euclid.IntArray.cumulativeSum()' */ @Test public void testCumulativeSum() { IntArray a = a1.cumulativeSum(); IntArrayTest.assertEquals("cumulative", new int[] { 1, 3, 7, 13 }, a); } /** * Test method for 'org.xmlcml.euclid.IntArray.trim(int, int)' */ @Test public void testTrim() { IntArray a = new IntArray("1 2 3 4 1 3 5 1 3"); IntArray b = a.trim(Trim.ABOVE, 2); int[] d = { 1, 2, 2, 2, 1, 2, 2, 1, 2 }; IntArrayTest.assertEquals("trim", d, b); b = a.trim(Trim.BELOW, 2); int[] dd = { 2, 2, 3, 4, 2, 3, 5, 2, 3 }; IntArrayTest.assertEquals("trim", dd, b); } /** * Test method for 'org.xmlcml.euclid.IntArray.indexOfLargestElement()' */ @Test public void testIndexOfLargestElement() { Assert.assertEquals("largest", 3, a1.indexOfLargestElement()); } /** * Test method for 'org.xmlcml.euclid.IntArray.indexOfSmallestElement()' */ @Test public void testIndexOfSmallestElement() { Assert.assertEquals("smallest", 0, a1.indexOfSmallestElement()); } /** * Test method for 'org.xmlcml.euclid.IntArray.largestElement()' */ @Test public void testLargestElement() { Assert.assertEquals("largest", 6, a1.largestElement()); } /** * Test method for 'org.xmlcml.euclid.IntArray.getMax()' */ @Test public void testGetMax() { Assert.assertEquals("max", 6, a1.getMax()); } /** * Test method for 'org.xmlcml.euclid.IntArray.smallestElement()' */ @Test public void testSmallestElement() { Assert.assertEquals("smallest", 1, a1.smallestElement()); } /** * Test method for 'org.xmlcml.euclid.IntArray.getMin()' */ @Test public void testGetMin() { Assert.assertEquals("max", 1, a1.getMin()); } /** * Test method for 'org.xmlcml.euclid.IntArray.getRange()' */ @Test public void testGetRange() { IntRange range = a1.getRange(); Assert.assertEquals("range", 1, range.getMin()); Assert.assertEquals("range", 6, range.getMax()); } /** * Test method for 'org.xmlcml.euclid.IntArray.deleteElement(int)' */ @Test public void testDeleteElement() { a1.deleteElement(2); IntArrayTest.assertEquals("delete", new int[] { 1, 2, 6 }, a1); } /** * Test method for 'org.xmlcml.euclid.IntArray.deleteElements(int, int)' */ @Test public void testDeleteElementsIntInt() { IntArray a = new IntArray(a1); a.deleteElements(1, 2); IntArrayTest.assertEquals("delete", new int[] { 1, 6 }, a); a = new IntArray(a1); a.deleteElements(0, 3); IntArrayTest.assertEquals("delete", new int[] {}, a); a = new IntArray(a1); a.deleteElements(2, 2); IntArrayTest.assertEquals("delete", new int[] { 1, 2, 6 }, a); } /** * Test method for 'org.xmlcml.euclid.IntArray.insertElementAt(int, int)' */ @Test public void testInsertElementAt() { IntArray a = new IntArray(a1); a.insertElementAt(1, 30); IntArrayTest.assertEquals("insert", new int[] { 1, 30, 2, 4, 6 }, a); a.insertElementAt(0, 20); IntArrayTest .assertEquals("insert", new int[] { 20, 1, 30, 2, 4, 6 }, a); a.insertElementAt(6, 10); IntArrayTest.assertEquals("insert", new int[] { 20, 1, 30, 2, 4, 6, 10 }, a); } /** * Test method for 'org.xmlcml.euclid.IntArray.insertArray(int, IntArray)' */ @Test public void testInsertArray() { a1.insertArray(1, new IntArray("44 55")); IntArrayTest.assertEquals("insert", new int[] { 1, 44, 55, 2, 4, 6 }, a1); } /** * Test method for 'org.xmlcml.euclid.IntArray.addElement(int)' */ @Test public void testAddElement() { a1.addElement(30); IntArrayTest.assertEquals("insert", new int[] { 1, 2, 4, 6, 30 }, a1); } /** * Test method for 'org.xmlcml.euclid.IntArray.addArray(IntArray)' */ @Test public void testAddArray() { a1.addArray(new IntArray("5 16 7")); IntArrayTest.assertEquals("insert", new int[] { 1, 2, 4, 6, 5, 16, 7 }, a1); } /** * Test method for 'org.xmlcml.euclid.IntArray.getReorderedArray(IntSet)' */ @Test public void testGetReorderedArray() { IntSet intSet = new IntSet(new int[] { 3, 1, 0, 2 }); IntArray a = a1.getReorderedArray(intSet); IntArrayTest.assertEquals("insert", new int[] { 6, 2, 1, 4 }, a); } /** * Test method for 'org.xmlcml.euclid.IntArray.inRange(IntRange)' */ @Test public void testInRange() { IntRange range = new IntRange(1, 5); IntSet intSet = a1.inRange(range); IntArray intArray = intSet.getIntArray(); IntArrayTest.assertEquals("inrange", new int[] { 0, 1, 2 }, intArray); intSet = a1.inRange(new IntRange(-3, 7)); IntArrayTest.assertEquals("inrange", new int[] { 0, 1, 2, 3 }, intSet .getIntArray()); intSet = a1.inRange(new IntRange(5, 5)); IntArrayTest .assertEquals("inrange", new int[] {}, intSet.getIntArray()); } /** * Test method for 'org.xmlcml.euclid.IntArray.outOfRange(IntRange)' */ @Test public void testOutOfRange() { IntRange range = new IntRange(1, 5); IntSet intSet = a1.outOfRange(range); IntArray intArray = intSet.getIntArray(); IntArrayTest.assertEquals("inrange", new int[] { 3 }, intArray); intSet = a1.outOfRange(new IntRange(-3, 7)); IntArrayTest .assertEquals("inrange", new int[] {}, intSet.getIntArray()); intSet = a1.outOfRange(new IntRange(4, 6)); IntArrayTest.assertEquals("inrange", new int[] { 0, 1 }, intSet .getIntArray()); } /** * Test method for 'org.xmlcml.euclid.IntArray.getStringValues()' */ @Test public void testGetStringValues() { String[] ss = a1.getStringValues(); StringTestBase.assertEquals("string values", new String[] { "1", "2", "4", "6" }, ss); } /** * Test method for 'org.xmlcml.euclid.IntArray.sortAscending()' */ @Test public void testSortAscending() { IntArray ra = new IntArray("1 6 3 9 2 0"); ra.sortAscending(); IntArrayTest.assertEquals("sortAscending", new int[] { 0, 1, 2, 3, 6, 9 }, ra); } /** * Test method for 'org.xmlcml.euclid.IntArray.sortDescending()' */ @Test public void testSortDescending() { IntArray ra = new IntArray("1 6 3 9 2 0"); ra.sortDescending(); IntArrayTest.assertEquals("sortDescending", new int[] { 9, 6, 3, 2, 1, 0 }, ra); } /** * Test method for 'org.xmlcml.euclid.IntArray.reverse()' */ @Test public void testReverse() { IntArray ra = new IntArray("1 6 3 9 2 0"); ra.reverse(); IntArrayTest .assertEquals("reverse", new int[] { 0, 2, 9, 3, 6, 1 }, ra); } /** * Test method for 'org.xmlcml.euclid.IntArray.indexSortAscending()' */ @Test public void testIndexSortAscending() { IntArray ra = new IntArray("1 6 3 9 2 0"); IntSet intSet = ra.indexSortAscending(); IntArrayTest.assertEquals("sortAscending", new int[] { 5, 0, 4, 2, 1, 3 }, intSet.getIntArray()); } /** * Test method for 'org.xmlcml.euclid.IntArray.indexSortDescending()' */ @Test public void testIndexSortDescending() { IntArray ra = new IntArray("1 6 3 9 2 0"); IntSet intSet = ra.indexSortDescending(); IntArrayTest.assertEquals("sortDescending", new int[] { 3, 1, 2, 4, 0, 5 }, intSet.getIntArray()); } } wwmm-euclid-87e8f785a814/src/test/java/org/xmlcml/euclid/test/IntMatrixTest.java0000644000000000000000000006646211607017524025600 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid.test; import static org.xmlcml.euclid.EC.S_RBRAK; import java.io.IOException; import java.io.StringWriter; import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.xmlcml.euclid.EuclidRuntimeException; import org.xmlcml.euclid.Int; import org.xmlcml.euclid.Int2; import org.xmlcml.euclid.IntArray; import org.xmlcml.euclid.IntMatrix; import org.xmlcml.euclid.IntRange; import org.xmlcml.euclid.IntSet; /** * test IntMatrix * * @author pmr * */ public class IntMatrixTest { final static Logger logger = Logger.getLogger(IntMatrixTest.class); IntMatrix m0; IntMatrix m1; IntMatrix m2; /** * setup. * * @throws Exception */ @Before public void setUp() throws Exception { logger.setLevel(Level.WARN); m0 = new IntMatrix(); m1 = new IntMatrix(3, 4); m2 = new IntMatrix(3, 4, new int[] { 11, 12, 13, 14, 21, 22, 23, 24, 31, 32, 33, 34, }); } /** * equality test. true if both args not null and equal within epsilon and * rows are present and equals and columns are present and equals * * @param msg * message * @param test * @param expected */ public static void assertEquals(String msg, IntMatrix test, IntMatrix expected) { Assert.assertNotNull("test should not be null (" + msg + S_RBRAK, test); Assert.assertNotNull("expected should not be null (" + msg + S_RBRAK, expected); Assert.assertNotNull("expected should have columns (" + msg + S_RBRAK, expected.getCols()); Assert.assertNotNull("expected should have rows (" + msg + S_RBRAK, expected.getRows()); Assert.assertNotNull("test should have columns (" + msg + S_RBRAK, test .getCols()); Assert.assertNotNull("test should have rows (" + msg + S_RBRAK, test .getRows()); Assert.assertEquals("rows should be equal (" + msg + S_RBRAK, test .getRows(), expected.getRows()); Assert.assertEquals("columns should be equal (" + msg + S_RBRAK, test .getCols(), expected.getCols()); String s = Int.testEquals(test.getMatrixAsArray(), expected .getMatrixAsArray()); if (s != null) { Assert.fail(msg + "; " + s); } } /** * equality test. true if both args not null and equal within epsilon * * @param msg * message * @param rows * @param cols * @param test * @param expected */ public static void assertEquals(String msg, int rows, int cols, int[] test, IntMatrix expected) { Assert.assertNotNull("test should not be null (" + msg + S_RBRAK, test); Assert.assertNotNull("ref should not be null (" + msg + S_RBRAK, expected); Assert.assertEquals("rows should be equal (" + msg + S_RBRAK, rows, expected.getRows()); Assert.assertEquals("columns should be equal (" + msg + S_RBRAK, cols, expected.getCols()); String s = Int.testEquals(test, expected.getMatrixAsArray()); if (s != null) { Assert.fail(msg + "; " + s); } } /** * Test method for 'org.xmlcml.euclid.IntMatrix.IntMatrix()' */ @Test public void testIntMatrix() { Assert.assertEquals("empty", "()", m0.toString()); } /** * Test method for 'org.xmlcml.euclid.IntMatrix.IntMatrix(int, int)' */ @Test public void testIntMatrixIntInt() { Assert.assertEquals("int int", "{3,4}" + "\n(0,0,0,0)" + "\n(0,0,0,0)" + "\n(0,0,0,0)", m1.toString()); Assert.assertEquals("int int rows", 3, m1.getRows()); Assert.assertEquals("int int cols", 4, m1.getCols()); } /** * Test method for 'org.xmlcml.euclid.IntMatrix.IntMatrix(int, int, int[])' */ @Test public void testIntMatrixIntIntIntegerArray() { Assert.assertEquals("int int int[]", "{3,4}" + "\n(11,12,13,14)" + "\n(21,22,23,24)" + "\n(31,32,33,34)", m2.toString()); Assert.assertEquals("int int int[] rows", 3, m2.getRows()); Assert.assertEquals("int int int[] cols", 4, m2.getCols()); } /** * Test method for 'org.xmlcml.euclid.IntMatrix.IntMatrix(int, int, int)' */ @Test public void testIntMatrixIntIntInteger() { IntMatrix m = new IntMatrix(3, 4, 10); Assert.assertEquals("int int int[]", "{3,4}" + "\n(10,10,10,10)" + "\n(10,10,10,10)" + "\n(10,10,10,10)", m.toString()); Assert.assertEquals("int int int[] rows", 3, m.getRows()); Assert.assertEquals("int int int[] cols", 4, m.getCols()); } /** * Test method for 'org.xmlcml.euclid.IntMatrix.IntMatrix(IntMatrix, int, * int, int, int)' */ @Test public void testIntMatrixIntMatrixIntIntIntInt() { IntMatrix m = new IntMatrix(m2, 1, 2, 1, 3); Assert.assertEquals("int int int[]", "{2,3}" + "\n(22,23,24)" + "\n(32,33,34)", m.toString()); Assert.assertEquals("int int int[] rows", 2, m.getRows()); Assert.assertEquals("int int int[] cols", 3, m.getCols()); } /** * Test method for 'org.xmlcml.euclid.IntMatrix.IntMatrix(IntMatrix)' */ @Test public void testIntMatrixIntMatrix() { IntMatrix m = new IntMatrix(m2); Assert.assertEquals("int int int[]", "{3,4}" + "\n(11,12,13,14)" + "\n(21,22,23,24)" + "\n(31,32,33,34)", m.toString()); Assert.assertEquals("int int int[] rows", 3, m.getRows()); Assert.assertEquals("int int int[] cols", 4, m.getCols()); } /** * Test method for 'org.xmlcml.euclid.IntMatrix.getIntMatrix()' */ @Test public void testGetIntMatrix() { IntMatrix mm2 = new IntMatrix(3, 4, new int[] { 11, 12, 13, 14, 21, 22, 23, 24, 31, 32, 33, 34, }); IntMatrix m = mm2.getIntMatrix(); Assert.assertEquals("int int int[]", "{3,4}" + "\n(11,12,13,14)" + "\n(21,22,23,24)" + "\n(31,32,33,34)", m.toString()); Assert.assertEquals("int int int[] rows", 3, m.getRows()); Assert.assertEquals("int int int[] cols", 4, m.getCols()); } /** * Test method for 'org.xmlcml.euclid.IntMatrix.IntMatrix(int[][])' */ @Test public void testIntMatrixIntegerArrayArray() { IntMatrix mm2 = new IntMatrix(new int[][] { new int[] { 11, 12, 13, 14 }, new int[] { 21, 22, 23, 24 }, new int[] { 31, 32, 33, 34 } }); IntMatrix m = mm2.getIntMatrix(); Assert.assertEquals("int int int[]", "{3,4}" + "\n(11,12,13,14)" + "\n(21,22,23,24)" + "\n(31,32,33,34)", m.toString()); Assert.assertEquals("int int int[] rows", 3, m.getRows()); Assert.assertEquals("int int int[] cols", 4, m.getCols()); } /** * Test method for 'org.xmlcml.euclid.IntMatrix.setFormat(DecimalFormat)' */ @Test public void testSetFormat() { } /** * Test method for 'org.xmlcml.euclid.IntMatrix.getFormat()' */ @Test public void testGetFormat() { } /** * Test method for 'org.xmlcml.euclid.IntMatrix.getRows()' */ @Test public void testGetRowsCols() { IntMatrix m = new IntMatrix(new int[][] { new int[] { 11, 12, 13, 14 }, new int[] { 21, 22, 23, 24 }, new int[] { 31, 32, 33, 34 } }); Assert.assertEquals("int int int[] rows", 3, m.getRows()); Assert.assertEquals("int int int[] cols", 4, m.getCols()); } /** * Test method for 'org.xmlcml.euclid.IntMatrix.getMatrix()' */ @Test public void testGetMatrix() { int[][] matrix = m1.getMatrix(); Assert.assertEquals("getMatrix", 3, matrix.length); Assert.assertEquals("getMatrix", 4, matrix[0].length); } /** * Test method for 'org.xmlcml.euclid.IntMatrix.getMatrixAsArray()' */ @Test public void testGetMatrixAsArray() { int[] array = m2.getMatrixAsArray(); String s = Int.testEquals((new int[] { 11, 12, 13, 14, 21, 22, 23, 24, 31, 32, 33, 34 }), array); if (s != null) { Assert.fail("matrix as array" + "; " + s); } } /** * Test method for 'org.xmlcml.euclid.IntMatrix.isEqualTo(IntMatrix)' */ @Test public void testIsEqualTo() { Assert.assertTrue("isEqualTo", m2.isEqualTo(m2)); } /** * Test method for 'org.xmlcml.euclid.IntMatrix.plus(IntMatrix)' */ @Test public void testPlus() { IntMatrix m = m2.plus(m2); IntMatrixTest.assertEquals("matrix as array", 3, 4, new int[] { 22, 24, 26, 28, 42, 44, 46, 48, 62, 64, 66, 68 }, m); } /** * Test method for 'org.xmlcml.euclid.IntMatrix.subtract(IntMatrix)' */ @Test public void testSubtract() { IntMatrix m = new IntMatrix(new int[][] { new int[] { 11, 12, 13, 14 }, new int[] { 21, 22, 23, 24 }, new int[] { 31, 32, 33, 34 } }); IntMatrix mm = m2.subtract(m); IntMatrixTest.assertEquals("matrix as array", 3, 4, new int[] { -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, }, mm); } /** * Test method for 'org.xmlcml.euclid.IntMatrix.negative()' */ @Test public void testNegative() { m2.negative(); IntMatrixTest.assertEquals("matrix as array", 3, 4, new int[] { -11, -12, -13, -14, -21, -22, -23, -24, -31, -32, -33, -34 }, m2); } /** * Test method for 'org.xmlcml.euclid.IntMatrix.multiply(IntMatrix)' */ @Test public void testMultiplyIntMatrix() { IntMatrix m = new IntMatrix(new int[][] { new int[] { 10, 20, 30 }, new int[] { 40, 50, 60 }, }); IntMatrix mm = m.multiply(m2); IntMatrixTest.assertEquals("matrix as array", 2, 4, new int[] { 1460, 1520, 1580, 1640, 3350, 3500, 3650, 3800, }, mm); } /** * Test method for 'org.xmlcml.euclid.IntMatrix.multiplyBy(int)' */ @Test public void testMultiplyBy() { m2.multiplyBy(10); IntMatrixTest.assertEquals("matrix as array", 3, 4, new int[] { 110, 120, 130, 140, 210, 220, 230, 240, 310, 320, 330, 340, }, m2); } /** * Test method for 'org.xmlcml.euclid.IntMatrix.multiplyEquals(IntMatrix)' */ @Test public void testMultiplyEquals() { IntMatrix m = new IntMatrix(new int[][] { new int[] { 10, 20, 30 }, new int[] { 40, 50, 60 }, }); try { m2.multiplyEquals(m); Assert.fail("should always throw " + "non-conformable matrices"); } catch (EuclidRuntimeException e) { Assert.assertEquals("multiplyEquals", "unequal matrices (4, 2)", e .getMessage()); } m.multiplyEquals(m2); IntMatrixTest.assertEquals("matrix as array", 2, 4, new int[] { 1460, 1520, 1580, 1640, 3350, 3500, 3650, 3800, }, m); } /** * Test method for 'org.xmlcml.euclid.IntMatrix.multiply(IntArray)' */ @Test public void testMultiplyIntArray() { IntArray ra = new IntArray(new int[] { 1, 2, 3, 4 }); IntArray raa = m2.multiply(ra); IntArrayTest.assertEquals("array", new int[] { 130, 230, 330 }, raa); } /** * Test method for 'org.xmlcml.euclid.IntMatrix.columnwiseDivide(IntArray)' */ @Test public void testColumnwiseDivide() { IntArray ra = new IntArray(new int[] { 1, 2, 3, 4 }); m2.columnwiseDivide(ra); IntMatrixTest.assertEquals("array", 3, 4, new int[] { 11, 6, 4, 3, 21, 11, 7, 6, 31, 16, 11, 8, }, m2); } /** * Test method for 'org.xmlcml.euclid.IntMatrix.elementAt(int, int)' */ @Test public void testElementAtIntInt() { Assert.assertEquals("elementAt ", 32, m2.elementAt(2, 1)); try { m2.elementAt(5, 5); } catch (EuclidRuntimeException e) { Assert.assertEquals("elementAt", "Bad value of row: 5/3", e .getMessage()); } } /** * Test method for 'org.xmlcml.euclid.IntMatrix.elementAt(Int2)' */ @Test public void testElementAtInt2() { Assert.assertEquals("elementAt ", 32, m2.elementAt(new Int2(2, 1))); try { m2.elementAt(new Int2(5, 5)); } catch (EuclidRuntimeException e) { Assert.assertEquals("elementAt", "Bad value of row: 5/3", e .getMessage()); } } /** * Test method for 'org.xmlcml.euclid.IntMatrix.setElementAt(int, int, int)' */ @Test public void testSetElementAt() { m2.setElementAt(1, 2, 15); IntMatrixTest.assertEquals("matrix as array", 3, 4, new int[] { 11, 12, 13, 14, 21, 22, 15, 24, 31, 32, 33, 34, }, m2); } /** * Test method for 'org.xmlcml.euclid.IntMatrix.largestElement()' */ @Test public void testLargestElement() { int d = m2.largestElement(); Assert.assertEquals("largestElement", 34, d); } /** * Test method for 'org.xmlcml.euclid.IntMatrix.indexOfLargestElement()' */ @Test public void testIndexOfLargestElement() { Int2 ii = m2.indexOfLargestElement(); Assert.assertEquals("indexOfLargestElement", 2, ii.getX()); Assert.assertEquals("indexOfLargestElement", 3, ii.getY()); } /** * Test method for 'org.xmlcml.euclid.IntMatrix.largestElementInColumn(int)' */ @Test public void testLargestElementInColumn() { int d = m2.largestElementInColumn(1); Assert.assertEquals("largestElement", 32, d); } /** * Test method for * 'org.xmlcml.euclid.IntMatrix.indexOfLargestElementInColumn(int)' */ @Test public void testIndexOfLargestElementInColumn() { int i = m2.indexOfLargestElementInColumn(1); Assert.assertEquals("largestElement", 2, i); } /** * Test method for 'org.xmlcml.euclid.IntMatrix.largestElementInRow(int)' */ @Test public void testLargestElementInRow() { int d = m2.largestElementInRow(1); Assert.assertEquals("largestElement", 24, d); } /** * Test method for * 'org.xmlcml.euclid.IntMatrix.indexOfLargestElementInRow(int)' */ @Test public void testIndexOfLargestElementInRow() { int i = m2.indexOfLargestElementInRow(1); Assert.assertEquals("largestElement", 3, i); } /** * Test method for 'org.xmlcml.euclid.IntMatrix.smallestElement()' */ @Test public void testSmallestElement() { int d = m2.smallestElement(); Assert.assertEquals("smallestElement", 11, d); } /** * Test method for 'org.xmlcml.euclid.IntMatrix.indexOfSmallestElement()' */ @Test public void testIndexOfSmallestElement() { Int2 ii = m2.indexOfSmallestElement(); Assert.assertEquals("indexOfSmallestElement", 0, ii.getX()); Assert.assertEquals("indexOfSmallestElement", 0, ii.getY()); } /** * Test method for * 'org.xmlcml.euclid.IntMatrix.smallestElementInColumn(int)' */ @Test public void testSmallestElementInColumn() { int d = m2.smallestElementInColumn(1); Assert.assertEquals("smallestElement", 12, d); } /** * Test method for * 'org.xmlcml.euclid.IntMatrix.indexOfSmallestElementInColumn(int)' */ @Test public void testIndexOfSmallestElementInColumn() { int i = m2.indexOfSmallestElementInColumn(1); Assert.assertEquals("largestElement", 0, i); } /** * Test method for 'org.xmlcml.euclid.IntMatrix.smallestElementInRow(int)' */ @Test public void testSmallestElementInRow() { int d = m2.smallestElementInRow(1); Assert.assertEquals("smallestElement", 21, d); } /** * Test method for * 'org.xmlcml.euclid.IntMatrix.indexOfSmallestElementInRow(int)' */ @Test public void testIndexOfSmallestElementInRow() { int i = m2.indexOfSmallestElementInRow(1); Assert.assertEquals("largestElement", 0, i); } /** * Test method for 'org.xmlcml.euclid.IntMatrix.extractColumnData(int)' */ @Test public void testExtractColumnData() { IntArray ra = m2.extractColumnData(1); IntArrayTest.assertEquals("euclidean column lengths", new int[] { 12, 22, 32 }, ra); } /** * Test method for 'org.xmlcml.euclid.IntMatrix.extractRowData(int)' */ @Test public void testExtractRowData() { IntArray ra = m2.extractRowData(1); IntArrayTest.assertEquals("euclidean column lengths", new int[] { 21, 22, 23, 24 }, ra); } /** * Test method for 'org.xmlcml.euclid.IntMatrix.clearMatrix()' */ @Test public void testClearMatrix() { m2.clearMatrix(); IntMatrixTest.assertEquals("matrix as array", 3, 4, new int[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, m2); } /** * Test method for 'org.xmlcml.euclid.IntMatrix.setAllElements(int)' */ @Test public void testSetAllElements() { m2.setAllElements(23); IntMatrixTest.assertEquals("matrix as array", 3, 4, new int[] { 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, }, m2); } /** * Test method for 'org.xmlcml.euclid.IntMatrix.getTranspose()' */ @Test public void testGetTranspose() { IntMatrix m = m2.getTranspose(); IntMatrixTest.assertEquals("transpose", 4, 3, new int[] { 11, 21, 31, 12, 22, 32, 13, 23, 33, 14, 24, 34, }, m); } /** * Test method for 'org.xmlcml.euclid.IntMatrix.isSquare()' */ @Test public void testIsSquare() { Assert.assertFalse("isSquare", m2.isSquare()); Assert.assertTrue("isSquare", new IntMatrix(2, 2, new int[] { 11, 12, 21, 22 }).isSquare()); } /** * Test method for 'org.xmlcml.euclid.IntMatrix.deleteColumn(int)' */ @Test public void testDeleteColumn() { m2.deleteColumn(1); IntMatrixTest.assertEquals("matrix as array", 3, 3, new int[] { 11, 13, 14, 21, 23, 24, 31, 33, 34, }, m2); } /** * Test method for 'org.xmlcml.euclid.IntMatrix.deleteColumns(int, int)' */ @Test public void testDeleteColumns() { m2.deleteColumns(1, 2); IntMatrixTest.assertEquals("matrix as array", 3, 2, new int[] { 11, 14, 21, 24, 31, 34, }, m2); } /** * Test method for 'org.xmlcml.euclid.IntMatrix.deleteRow(int)' */ @Test public void testDeleteRow() { m2.deleteRow(1); IntMatrixTest.assertEquals("matrix as array", 2, 4, new int[] { 11, 12, 13, 14, 31, 32, 33, 34, }, m2); } /** * Test method for 'org.xmlcml.euclid.IntMatrix.deleteRows(int, int)' */ @Test public void testDeleteRows() { // FIXME does not work for high = nrows m2.deleteRows(1, 1); IntMatrixTest.assertEquals("matrix as array", 2, 4, new int[] { 11, 12, 13, 14, 31, 32, 33, 34, }, m2); } /** * Test method for 'org.xmlcml.euclid.IntMatrix.replaceColumnData(int, * IntArray)' */ @Test public void testReplaceColumnDataIntIntArray() { m2.replaceColumnData(1, new IntArray(new int[] { 19, 29, 39 })); IntMatrixTest.assertEquals("matrix as array", 3, 4, new int[] { 11, 19, 13, 14, 21, 29, 23, 24, 31, 39, 33, 34, }, m2); } /** * Test method for 'org.xmlcml.euclid.IntMatrix.replaceColumnData(int, * int[])' */ @Test public void testReplaceColumnDataIntIntegerArray() { m2.replaceColumnData(1, new int[] { 19, 29, 39 }); IntMatrixTest.assertEquals("matrix as array", 3, 4, new int[] { 11, 19, 13, 14, 21, 29, 23, 24, 31, 39, 33, 34, }, m2); } /** * Test method for 'org.xmlcml.euclid.IntMatrix.replaceColumnData(int, * IntMatrix)' */ @Test public void testReplaceColumnDataIntIntMatrix() { IntMatrix expect = null; IntMatrix m = new IntMatrix(3, 2, new int[] { 72, 73, 82, 83, 92, 93 }); m2.replaceColumnData(1, m); expect = new IntMatrix(3, 4, new int[] { 11, 72, 73, 14, 21, 82, 83, 24, 31, 92, 93, 34, }); IntMatrixTest.assertEquals("matrix as array", m2, expect); } /** * Test method for 'org.xmlcml.euclid.IntMatrix.insertColumns(int, int)' */ @Test public void testInsertColumns() { // inserts 3 empty columns m2.makeSpaceForNewColumns(1, 3); IntMatrix expect = new IntMatrix(3, 7, new int[] { 11, 0, 0, 0, 12, 13, 14, 21, 0, 0, 0, 22, 23, 24, 31, 0, 0, 0, 32, 33, 34, }); IntMatrixTest.assertEquals("matrix as array", m2, expect); } /** * Test method for 'org.xmlcml.euclid.IntMatrix.insertColumnData(int, * IntArray)' */ @Test public void testInsertColumnDataIntIntArray() { // inserts a column m2.insertColumnData(1, new IntArray(new int[] { 91, 92, 93 })); IntMatrix expect = new IntMatrix(3, 5, new int[] { 11, 12, 91, 13, 14, 21, 22, 92, 23, 24, 31, 32, 93, 33, 34, }); IntMatrixTest.assertEquals("matrix as array", m2, expect); } /** * Test method for 'org.xmlcml.euclid.IntMatrix.insertColumnData(int, * IntMatrix)' */ @Test public void testInsertColumnDataIntIntMatrix() { logger.info("+++insertColumnData>>>"); IntMatrix insert = new IntMatrix(3, 2, new int[] { 72, 73, 82, 83, 92, 93, }); m2.insertColumnData(1, insert); IntMatrix expect = new IntMatrix(3, 6, new int[] { 11, 12, 72, 73, 13, 14, 21, 22, 82, 83, 23, 24, 31, 32, 92, 93, 33, 34, }); IntMatrixTest.assertEquals("matrix as array", m2, expect); } /** * Test method for 'org.xmlcml.euclid.IntMatrix.insertRows(int, int)' */ @Test public void testInsertRows() { m2.insertRows(1, 2); int[] array = m2.getMatrixAsArray(); String s = Int.testEquals((new int[] { 11, 12, 13, 14, 0, 0, 0, 0, 0, 0, 0, 0, 21, 22, 23, 24, 31, 32, 33, 34, }), array); if (s != null) { Assert.fail("matrix as array" + "; " + s); } } /** * Test method for 'org.xmlcml.euclid.IntMatrix.replaceRowData(int, * IntArray)' */ @Test public void testReplaceRowDataIntIntArray() { m2.replaceRowData(1, new IntArray(new int[] { 71, 72, 73, 74 })); int[] array = m2.getMatrixAsArray(); String s = Int.testEquals((new int[] { 11, 12, 13, 14, 71, 72, 73, 74, 31, 32, 33, 34, }), array); if (s != null) { Assert.fail("matrix as array" + "; " + s); } } /** * Test method for 'org.xmlcml.euclid.IntMatrix.replaceRowData(int, int[])' */ @Test public void testReplaceRowDataIntIntegerArray() { m2.replaceRowData(1, new int[] { 71, 72, 73, 74 }); int[] array = m2.getMatrixAsArray(); String s = Int.testEquals((new int[] { 11, 12, 13, 14, 71, 72, 73, 74, 31, 32, 33, 34, }), array); if (s != null) { Assert.fail("matrix as array" + "; " + s); } } /** * Test method for 'org.xmlcml.euclid.IntMatrix.replaceRowData(int, * IntMatrix)' */ @Test public void testReplaceRowDataIntIntMatrix() { logger.info("+++replaceRowData>>>"); // FIXME IntMatrix insert = new IntMatrix(new IntMatrix(2, 4, new int[] { 71, 72, 73, 74, 81, 82, 83, 84, })); m2.replaceRowData(0, insert); IntMatrix expect = new IntMatrix(3, 4, new int[] { 11, 12, 13, 14, 71, 72, 73, 74, 81, 82, 83, 84, }); // rows 2 and 3 are not filled IntMatrixTest.assertEquals("matrix as array", m2, expect); } /** * Test method for 'org.xmlcml.euclid.IntMatrix.insertRowData(int, * IntMatrix)' */ @Test public void testInsertRowDataIntIntMatrix() { // FIXME m2.insertRowData(1, new IntMatrix(2, 4, new int[] { 71, 72, 73, 74, 81, 82, 83, 84, })); IntMatrix expect = new IntMatrix(5, 4, new int[] { 11, 12, 13, 14, 21, 22, 23, 24, 71, 72, 73, 74, 81, 82, 83, 84, 31, 32, 33, 34, }); String s = Int.testEquals(expect.getMatrixAsArray(), m2 .getMatrixAsArray()); if (s != null) { Assert.fail("matrix as array" + "; " + s); } } /** * Test method for 'org.xmlcml.euclid.IntMatrix.insertRowData(int, * IntArray)' */ @Test public void testInsertRowDataIntIntArray() { IntMatrixTest.assertEquals("matrix as array", 3, 4, new int[] { 11, 12, 13, 14, 21, 22, 23, 24, 31, 32, 33, 34, }, m2); m2.insertRowData(1, new IntArray(new int[] { 71, 72, 73, 74, })); IntMatrixTest.assertEquals("matrix as array", 4, 4, new int[] { 11, 12, 13, 14, 21, 22, 23, 24, 71, 72, 73, 74, 31, 32, 33, 34, }, m2); } /** * Test method for 'org.xmlcml.euclid.IntMatrix.appendColumnData(IntArray)' */ @Test public void testAppendColumnDataIntArray() { m2.appendColumnData(new IntArray(new int[] { 17, 27, 37, })); int[] array = m2.getMatrixAsArray(); String s = Int.testEquals((new int[] { 11, 12, 13, 14, 17, 21, 22, 23, 24, 27, 31, 32, 33, 34, 37 }), array); if (s != null) { Assert.fail("matrix as array" + "; " + s); } } /** * Test method for 'org.xmlcml.euclid.IntMatrix.appendColumnData(IntMatrix)' */ @Test public void testAppendColumnDataIntMatrix() { // logger.info("+++appendColumnData>>>"); IntMatrix rm = new IntMatrix(3, 2, new int[] { 17, 18, 27, 28, 37, 38 }); m2.appendColumnData(rm); IntMatrix expect = new IntMatrix(3, 6, new int[] { 11, 12, 13, 14, 17, 18, 21, 22, 23, 24, 27, 28, 31, 32, 33, 34, 37, 38 }); IntMatrixTest.assertEquals("matrix as array", m2, expect); } /** * Test method for 'org.xmlcml.euclid.IntMatrix.appendRowData(IntArray)' */ @Test public void testAppendRowDataIntArray() { IntArray ra = new IntArray(new int[] { 41, 42, 43, 44 }); m2.appendRowData(ra); // fails to insert data IntMatrixTest.assertEquals("matrix as array", 4, 4, new int[] { 11, 12, 13, 14, 21, 22, 23, 24, 31, 32, 33, 34, 41, 42, 43, 44 }, m2); } /** * Test method for 'org.xmlcml.euclid.IntMatrix.appendRowData(IntMatrix)' */ @Test public void testAppendRowDataIntMatrix() { logger.info("+++appendRowData>>>"); // FIXME IntMatrix rm = new IntMatrix(2, 4, new int[] { 41, 42, 43, 44, 51, 52, 53, 54 }); m2.appendRowData(rm); IntMatrix expect = new IntMatrix(5, 4, new int[] { 11, 12, 13, 14, 21, 22, 23, 24, 31, 32, 33, 34, 41, 42, 43, 44, 51, 52, 53, 54 }); IntMatrixTest.assertEquals("matrix as array", m2, expect); } /** * Test method for 'org.xmlcml.euclid.IntMatrix.replaceSubMatrixData(int, * int, IntMatrix)' */ @Test public void testReplaceSubMatrixData() { IntMatrix rm = new IntMatrix(2, 2, new int[] { 71, 72, 81, 82 }); m2.replaceSubMatrixData(1, 1, rm); // fails to insert data IntMatrixTest.assertEquals("matrix as array", 3, 4, new int[] { 71, 72, 13, 14, 81, 82, 23, 24, 31, 32, 33, 34, }, m2); } /** * Test method for 'org.xmlcml.euclid.IntMatrix.reorderColumnsBy(IntSet)' */ @Test public void testReorderColumnsBy() { IntMatrix mm = m2 .reorderColumnsBy(new IntSet(new int[] { 3, 1, 2, 0 })); // fails to insert data IntMatrixTest.assertEquals("matrix as array", 3, 4, new int[] { 14, 12, 13, 11, 24, 22, 23, 21, 34, 32, 33, 31 }, mm); } /** * Test method for 'org.xmlcml.euclid.IntMatrix.reorderRowsBy(IntSet)' */ @Test public void testReorderRowsBy() { IntMatrix mm = m2.reorderRowsBy(new IntSet(new int[] { 1, 2, 0 })); // fails to insert data IntMatrixTest.assertEquals("matrix as array", 3, 4, new int[] { 21, 22, 23, 24, 31, 32, 33, 34, 11, 12, 13, 14, }, mm); } /** * Test method for 'org.xmlcml.euclid.IntMatrix.extractSubMatrixData(int, * int, int, int)' */ @Test public void testExtractSubMatrixData() { IntMatrix mm = m2.extractSubMatrixData(1, 2, 2, 3); IntMatrixTest.assertEquals("sub matrix", 2, 2, new int[] { 23, 24, 33, 34 }, mm); } /** * Test method for 'org.xmlcml.euclid.IntMatrix.elementsInRange(IntRange)' */ @Test public void testElementsInRange() { IntMatrix im = m2.elementsInRange(new IntRange(13, 31)); IntMatrixTest.assertEquals("sub matrix", 3, 4, new int[] { 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 }, im); } /** * Test method for 'org.xmlcml.euclid.IntMatrix.writeXML(Writer)' */ @Test public void testWriteXML() { StringWriter w = new StringWriter(); try { m2.writeXML(w); w.close(); } catch (IOException e) { throw new EuclidRuntimeException("should never throw " + e); } Assert .assertEquals( "writeXML", "11 12 13 14 21 22 23 24 31 32 33 34", w.toString()); } } wwmm-euclid-87e8f785a814/src/test/java/org/xmlcml/euclid/test/IntRangeTest.java0000644000000000000000000001175511607017524025363 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid.test; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.xmlcml.euclid.IntRange; /** * test IntRange * * @author pmr * */ public class IntRangeTest { IntRange i0; IntRange i1; IntRange i2; /** * main * * @param args */ public static void main(String[] args) { } /** * setup. * * @throws Exception */ @Before public void setUp() throws Exception { i0 = new IntRange(); i1 = new IntRange(1, 1); i2 = new IntRange(1, 3); } /** * Test method for 'org.xmlcml.euclid.IntRange.IntRange()' */ @Test public void testIntRange() { Assert.assertEquals("empty", "NULL", i0.toString()); } /** * Test method for 'org.xmlcml.euclid.IntRange.IntRange(int, int)' */ @Test public void testIntRangeIntInt() { Assert.assertEquals("i1", "(1,1)", i1.toString()); Assert.assertEquals("i2", "(1,3)", i2.toString()); } /** * Test method for 'org.xmlcml.euclid.IntRange.IntRange(IntRange)' */ @Test public void testIntRangeIntRange() { IntRange ii = new IntRange(i2); Assert.assertEquals("ii", "(1,3)", ii.toString()); } /** * Test method for 'org.xmlcml.euclid.IntRange.isValid()' */ @Test public void testIsValid() { Assert.assertTrue("valid", i2.isValid()); Assert.assertFalse("invalid", i0.isValid()); } /** * Test method for 'org.xmlcml.euclid.IntRange.isEqualTo(IntRange)' */ @Test public void testIsEqualTo() { Assert.assertTrue("equal", i2.isEqualTo(i2)); Assert.assertFalse("equal", i2.isEqualTo(i0)); Assert.assertFalse("equal", i0.isEqualTo(i0)); } /** * Test method for 'org.xmlcml.euclid.IntRange.plus(IntRange)' */ @Test public void testPlus() { IntRange ix = new IntRange(1, 4); IntRange iy = new IntRange(2, 3); IntRange ii = ix.plus(iy); Assert.assertEquals("ii", "(1,4)", ii.toString()); iy = new IntRange(0, 2); ii = ix.plus(iy); Assert.assertEquals("ii", "(0,4)", ii.toString()); iy = new IntRange(2, 6); ii = ix.plus(iy); Assert.assertEquals("ii", "(1,6)", ii.toString()); iy = new IntRange(); ii = ix.plus(iy); Assert.assertEquals("ii", "(1,4)", ii.toString()); } /** * Test method for 'org.xmlcml.euclid.IntRange.intersectionWith(IntRange)' */ @Test public void testIntersectionWith() { IntRange ix = new IntRange(1, 4); IntRange iy = new IntRange(2, 3); IntRange ii = ix.intersectionWith(iy); Assert.assertEquals("ii", "(2,3)", ii.toString()); iy = new IntRange(0, 2); ii = ix.intersectionWith(iy); Assert.assertEquals("ii", "(1,2)", ii.toString()); iy = new IntRange(2, 6); ii = ix.intersectionWith(iy); Assert.assertEquals("ii", "(2,4)", ii.toString()); iy = new IntRange(); ii = ix.intersectionWith(iy); Assert.assertEquals("ii", "NULL", ii.toString()); } /** * Test method for 'org.xmlcml.euclid.IntRange.getMin()' */ @Test public void testGetMin() { Assert.assertEquals("min", 1, i2.getMin()); } /** * Test method for 'org.xmlcml.euclid.IntRange.getMax()' */ @Test public void testGetMax() { Assert.assertEquals("max", 3, i2.getMax()); } /** * Test method for 'org.xmlcml.euclid.IntRange.getRange()' */ @Test public void testGetRange() { Assert.assertEquals("range", 2, i2.getRange()); } /** * Test method for 'org.xmlcml.euclid.IntRange.includes(IntRange)' */ @Test public void testIncludesIntRange() { Assert.assertTrue("includes", i2.includes(new IntRange(2, 3))); Assert.assertFalse("includes", i2.includes(new IntRange(0, 3))); } /** * Test method for 'org.xmlcml.euclid.IntRange.includes(int)' */ @Test public void testIncludesInt() { Assert.assertTrue("includes", i2.includes(1)); Assert.assertFalse("includes", i2.includes(0)); } /** * Test method for 'org.xmlcml.euclid.IntRange.contains(int)' */ @Test public void testContains() { Assert.assertTrue("contains", i2.contains(1)); Assert.assertFalse("contains", i2.contains(0)); } /** * Test method for 'org.xmlcml.euclid.IntRange.add(int)' */ @Test public void testAdd() { i2.add(2); Assert.assertEquals("ii", "(1,3)", i2.toString()); i2.add(0); Assert.assertEquals("ii", "(0,3)", i2.toString()); i2.add(9); Assert.assertEquals("ii", "(0,9)", i2.toString()); } } wwmm-euclid-87e8f785a814/src/test/java/org/xmlcml/euclid/test/IntSetTest.java0000644000000000000000000002714411607017524025061 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid.test; import static org.xmlcml.euclid.EC.S_EMPTY; import java.util.List; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.xmlcml.euclid.EC; import org.xmlcml.euclid.EuclidRuntimeException; import org.xmlcml.euclid.Int; import org.xmlcml.euclid.IntRange; import org.xmlcml.euclid.IntSet; /** * test IntSet. * * @author pmr * */ public class IntSetTest { IntSet i0; IntSet i1; IntSet i2; IntSet i3; /** * setup. * * @throws Exception */ @Before public void setUp() throws Exception { i0 = new IntSet(); i1 = new IntSet(new int[] { 3, 4, 1, 2 }); i2 = new IntSet(4); i3 = new IntSet(2, 5); } /** * equality test. true if both args not null and equal * * @param msg * message * @param test * @param expected */ public static void assertEquals(String msg, IntSet test, IntSet expected) { Assert.assertNotNull("test should not be null (" + msg + EC.S_RBRAK, test); Assert.assertNotNull("expected should not be null (" + msg + EC.S_RBRAK, expected); String s = Int.testEquals(test.getElements(), expected.getElements()); if (s != null) { Assert.fail(msg + "; " + s); } } /** * equality test. true if both args not null and equal * * @param msg * message * @param test * @param expected */ public static void assertEquals(String msg, int[] test, IntSet expected) { Assert.assertNotNull("test should not be null (" + msg + EC.S_RBRAK, test); Assert.assertNotNull("expected should not be null (" + msg + EC.S_RBRAK, expected); Assert.assertEquals("must be of equal length ", test.length, expected .getElements().length); String s = Int.testEquals(test, expected.getElements()); if (s != null) { Assert.fail(msg + "; " + s); } } /** * Test method for 'org.xmlcml.euclid.IntSet.IntSet()' */ @Test public void testIntSet() { Assert.assertEquals("empty", "()", i0.toString()); Assert.assertFalse("int, int ", i0.contains(0)); Assert.assertFalse("int, int ", i0.contains(1)); } /** * Test method for 'org.xmlcml.euclid.IntSet.IntSet(int)' */ @Test public void testIntSetInt() { Assert.assertEquals("int[]", "(3,4,1,2)", i1.toString()); Assert.assertFalse("int, int ", i1.contains(0)); Assert.assertTrue("int, int ", i1.contains(1)); Assert.assertTrue("int, int ", i1.contains(2)); Assert.assertTrue("int, int ", i1.contains(3)); Assert.assertTrue("int, int ", i1.contains(4)); Assert.assertFalse("int, int ", i1.contains(5)); } /** * Test method for 'org.xmlcml.euclid.IntSet.IntSet(int, int)' */ @Test public void testIntSetIntInt() { Assert.assertEquals("int", "(2,3,4,5)", i3.toString()); Assert.assertFalse("int, int ", i3.contains(0)); Assert.assertFalse("int, int ", i3.contains(1)); Assert.assertTrue("int, int ", i3.contains(2)); Assert.assertTrue("int, int ", i3.contains(3)); Assert.assertTrue("int, int ", i3.contains(4)); Assert.assertTrue("int, int ", i3.contains(5)); Assert.assertFalse("int, int ", i3.contains(6)); } /** * Test method for 'org.xmlcml.euclid.IntSet.IntSet(IntSet)' */ @Test public void testIntSetIntSet() { IntSet ii = new IntSet(i1); Assert.assertEquals("copy", "(3,4,1,2)", ii.toString()); Assert.assertFalse("int, int ", ii.contains(0)); Assert.assertTrue("int, int ", ii.contains(1)); Assert.assertTrue("int, int ", ii.contains(2)); Assert.assertTrue("int, int ", ii.contains(3)); Assert.assertTrue("int, int ", ii.contains(4)); Assert.assertFalse("int, int ", ii.contains(5)); } /** * Test method for 'org.xmlcml.euclid.IntSet.IntSet(int[])' */ @Test public void testIntSetIntArray() { IntSetTest.assertEquals("int", new int[] { 0, 1, 2, 3 }, i2); } /** * Test method for * 'org.xmlcml.euclid.IntSet.IntSet.getSubcriptedIntSet(IntSet)' */ @Test public void testIntSetIntSetIntSet() { IntSet is0 = new IntSet(new int[] { 0, 1, 2, 3 }); IntSet is = i1.getSubscriptedIntSet(is0); IntSetTest.assertEquals("copy", new int[] { 3, 4, 1, 2 }, is); } /** * Test method for 'org.xmlcml.euclid.IntSet.isEqualTo(IntSet)' */ @Test public void testIsEqualTo() { Assert.assertTrue("isEqualsTo", i1.isEqualTo(i1)); Assert.assertFalse("isEqualsTo", i1.isEqualTo(i2)); } /** * Test method for 'org.xmlcml.euclid.IntSet.getElements()' */ @Test public void testGetElements() { String s = Int.testEquals((new int[] {}), i0.getElements()); if (s != null) { Assert.fail("getElements" + "; " + s); } s = Int.testEquals((new int[] { 3, 4, 1, 2 }), i1 .getElements()); if (s != null) { Assert.fail("getElements" + "; " + s); } } /** * Test method for 'org.xmlcml.euclid.IntSet.setMax(int)' */ @Test public void testSetMax() { i1.setMax(7); i1.addElement(6); IntSetTest.assertEquals("getElements", new int[] { 3, 4, 1, 2, 6 }, i1); i1.addElement(7); String s = Int.testEquals((new int[] { 3, 4, 1, 2, 6, 7 }), i1 .getElements()); if (s != null) { Assert.fail("getElements" + "; " + s); } try { i1.addElement(8); } catch (EuclidRuntimeException e) { Assert .assertEquals( "addElement", "org.xmlcml.euclid.EuclidRuntimeException: value (8)outside range (-2147483648...7)", S_EMPTY + e); } } /** * Test method for 'org.xmlcml.euclid.IntSet.setMin(int)' */ @Test public void testSetMin() { i1.setMin(-3); i1.addElement(-2); IntSetTest .assertEquals("getElements", new int[] { 3, 4, 1, 2, -2 }, i1); i1.addElement(-3); IntSetTest.assertEquals("getElements", new int[] { 3, 4, 1, 2, -2, -3 }, i1); try { i1.addElement(-4); } catch (EuclidRuntimeException e) { Assert .assertEquals( "addElement", "org.xmlcml.euclid.EuclidRuntimeException: value (-4)outside range (-3...2147483647)", S_EMPTY + e); } } /** * Test method for 'org.xmlcml.euclid.IntSet.size()' */ @Test public void testSize() { Assert.assertEquals("size", 4, i1.size()); } /** * Test method for 'org.xmlcml.euclid.IntSet.addElement(int)' */ @Test public void testAddElement() { i1.addElement(6); IntSetTest.assertEquals("addElement", new int[] { 3, 4, 1, 2, 6 }, i1); try { i1.addElement(4); } catch (EuclidRuntimeException e) { Assert .assertEquals( "addElement", "org.xmlcml.euclid.EuclidRuntimeException: value already in set: 4", S_EMPTY + e); } IntSetTest.assertEquals("addElement", new int[] { 3, 4, 1, 2, 6 }, i1); } /** * Test method for 'org.xmlcml.euclid.IntSet.contains(int)' */ @Test public void testContains() { Assert.assertTrue("contains", i1.contains(4)); Assert.assertFalse("contains", i1.contains(5)); } /** * Test method for 'org.xmlcml.euclid.IntSet.elementAt(int)' */ @Test public void testElementAt() { Assert.assertEquals("elementAt", 4, i1.elementAt(1)); } /** * Test method for 'org.xmlcml.euclid.IntSet.getIntArray()' */ @Test public void testGetIntArray() { String s = Int.testEquals((new int[] { 3, 4, 1, 2 }), i1 .getIntArray().getArray()); if (s != null) { Assert.fail("getIntArray" + "; " + s); } s = Int.testEquals((new int[] {}), i0.getIntArray() .getArray()); if (s != null) { Assert.fail("getIntArray" + "; " + s); } } /** * Test method for 'org.xmlcml.euclid.IntSet.sortAscending()' */ @Test public void testSortAscending() { i1.sortAscending(); IntSetTest.assertEquals("sort ascending", new int[] { 1, 2, 3, 4 }, i1); i0.sortAscending(); IntSetTest.assertEquals("sort ascending", new int[] {}, i0); } /** * Test method for 'org.xmlcml.euclid.IntSet.addSet(IntSet)' */ @Test public void testAddSet() { i1.addSet(new IntSet(new int[] { 5, 19, 8, 33 })); IntSetTest.assertEquals("addSet", new int[] { 3, 4, 1, 2, 5, 19, 8, 33 }, i1); IntSetTest.assertEquals("addSet", new int[] { 0, 1, 2, 3 }, i2); IntSet newIs = null; newIs = new IntSet(new int[] { 3, 4, 5, 6 }); try { i2.addSet(newIs); } catch (EuclidRuntimeException e) { Assert .assertEquals( "addSet", "org.xmlcml.euclid.EuclidRuntimeException: duplicate element 3", S_EMPTY + e); } IntSetTest.assertEquals("addSet", new int[] { 0, 1, 2, 3 }, i2); } /** * Test method for 'org.xmlcml.euclid.IntSet.intersectionWith(IntSet)' */ @Test public void testIntersectionWith() { IntSet is1 = null; IntSet is2 = null; is1 = new IntSet(new int[] { 1, 2, 3, 4, 5 }); is2 = new IntSet(new int[] { 4, 5, 6, 7, 3 }); IntSet is = is1.intersectionWith((is2)); IntSetTest.assertEquals("intersection", new int[] { 4, 5, 3 }, is); } /** * Test method for 'org.xmlcml.euclid.IntSet.notIn(IntSet)' */ @Test public void testNotIn() { IntSet is1 = null; IntSet is2 = null; is1 = new IntSet(new int[] { 1, 2, 3, 4, 5 }); is2 = new IntSet(new int[] { 4, 5, 6, 7, 3 }); IntSet is = is1.notIn(is2); IntSetTest.assertEquals("notIn", new int[] { 1, 2 }, is); } /** * Test method for 'org.xmlcml.euclid.IntSet.addRange(IntRange)' */ @Test public void testAddRange() { IntSet is1 = new IntSet(new int[] { 1, 2, 3, 4, 5 }); is1.addRange(new IntRange(-2, 0)); IntSetTest.assertEquals("addRange", new int[] { 1, 2, 3, 4, 5, -2, -1, 0 }, is1); } /** * Test method for 'org.xmlcml.euclid.IntSet.inverseMap()' */ @Test public void testInverseMap() { IntSet is1 = new IntSet(new int[] { 4, 0, 1, 3, 2 }); IntSet is = is1.inverseMap(); IntSetTest.assertEquals("inverse", new int[] { 1, 2, 4, 3, 0 }, is); } @Test public final void testGetSubscriptedIntSet() { IntSet is1 = new IntSet(new int[] { 4, 0, 1, 3, 2 }); IntSet is2 = new IntSet(new int[] { 14, 10, 11, 13, 12 }); IntSet is3 = is2.getSubscriptedIntSet(is1); IntSetTest.assertEquals("subscripts", new IntSet(new int[] { 12, 14, 10, 13, 11 }), is3); is1 = new IntSet(new int[] { 4, 0, 5, 3, 2 }); try { is3 = is2.getSubscriptedIntSet(is1); Assert.fail("Should throw exception"); } catch (EuclidRuntimeException e) { ;// expected } is1 = new IntSet(new int[] { 4, 0, 1, 3 }); is3 = is2.getSubscriptedIntSet(is1); IntSetTest.assertEquals("subscripts", new IntSet(new int[] { 12, 14, 10, 13 }), is3); } @Test public final void testGetPermutations() { List perm3 = IntSet.getPermutations(new Integer(3)); String s = Int.testEquals((new int[] { 3, 2, 1 }), perm3 .get(0)); if (s != null) { Assert.fail("permutation" + "; " + s); } s = Int.testEquals((new int[] { 2, 3, 1 }), perm3 .get(1)); if (s != null) { Assert.fail("permutation" + "; " + s); } s = Int.testEquals((new int[] { 1, 2, 3 }), perm3 .get(5)); if (s != null) { Assert.fail("permutation" + "; " + s); } } } wwmm-euclid-87e8f785a814/src/test/java/org/xmlcml/euclid/test/IntSquareMatrixTest.java0000644000000000000000000002636711607017524026761 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid.test; import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.xmlcml.euclid.Int; import org.xmlcml.euclid.IntArray; import org.xmlcml.euclid.IntMatrix; import org.xmlcml.euclid.IntSquareMatrix; /** * test IntSquareMatrix. * * @author pmr * */ public class IntSquareMatrixTest extends MatrixTest { static Logger logger = Logger .getLogger(IntSquareMatrixTest.class.getName()); IntSquareMatrix m0; IntSquareMatrix m1; IntSquareMatrix m2; /** * setup. * * @throws Exception */ @Before public void setUp() throws Exception { super.setUp(); logger.setLevel(Level.WARN); m0 = new IntSquareMatrix(); m1 = new IntSquareMatrix(3); m2 = new IntSquareMatrix(3, new int[] { 11, 12, 13, 21, 22, 23, 31, 32, 33, }); } /** * Test method for 'org.xmlcml.euclid.IntSquareMatrix.isOrthogonal()' */ @Test public void testIsOrthogonal() { Assert.assertFalse("isOrthogonal", m2.isOrthogonal()); IntSquareMatrix m = new IntSquareMatrix(3, new int[] { 0, 1, 0, -1, 0, 0, 0, 0, 1, }); Assert.assertTrue("isOrthogonal", m.isOrthogonal()); } /** * Test method for 'org.xmlcml.euclid.IntSquareMatrix.IntSquareMatrix()' */ @Test public void testIntSquareMatrix() { Assert.assertEquals("real square matrix", 0, m0.getRows()); Assert.assertEquals("real square matrix", 0, m0.getCols()); } /** * Test method for 'org.xmlcml.euclid.IntSquareMatrix.IntSquareMatrix(int)' */ @Test public void testIntSquareMatrixInt() { Assert.assertEquals("real square matrix", 3, m1.getRows()); Assert.assertEquals("real square matrix", 3, m1.getCols()); } /** * Test method for * 'org.xmlcml.euclid.IntSquareMatrix.outerProduct(IntArray)' */ @Test public void testOuterProduct() { IntArray ra = new IntArray(3, new int[] { 1, 2, 3 }); IntSquareMatrix rsm = IntSquareMatrix.outerProduct(ra); IntMatrix rm = new IntMatrix(3, 3, new int[] { 1, 2, 3, 2, 4, 6, 3, 6, 9, }); MatrixTest.assertEquals("outer product", rm, (IntMatrix) rsm); } /** * Test method for 'org.xmlcml.euclid.IntSquareMatrix.diagonal(IntArray)' */ @Test public void testDiagonal() { IntArray ra = new IntArray(3, new int[] { 1, 2, 3 }); IntMatrix rsm = IntSquareMatrix.diagonal(ra); IntMatrix rm = new IntMatrix(3, 3, new int[] { 1, 0, 0, 0, 2, 0, 0, 0, 3, }); MatrixTest.assertEquals("diagonal", rm, (IntMatrix) rsm); } /** * Test method for 'org.xmlcml.euclid.IntSquareMatrix.IntSquareMatrix(int, * int[])' */ @Test public void testIntSquareMatrixIntIntegerArray() { IntMatrix rm = new IntMatrix(3, 3, new int[] { 1, 2, 3, 2, 4, 6, 3, 6, 9, }); IntSquareMatrix rsm = new IntSquareMatrix(3, new int[] { 1, 2, 3, 2, 4, 6, 3, 6, 9, }); MatrixTest.assertEquals("int int[]", rm, (IntMatrix) rsm); } /** * Test method for 'org.xmlcml.euclid.IntSquareMatrix.IntSquareMatrix(int, * int)' */ @Test public void testIntSquareMatrixIntInteger() { IntMatrix rm = new IntMatrix(3, 3, 10); IntSquareMatrix rsm = new IntSquareMatrix(3, 10); MatrixTest.assertEquals("int int", rm, (IntMatrix) rsm); } /** * Test method for * 'org.xmlcml.euclid.IntSquareMatrix.IntSquareMatrix(IntMatrix, int, int, * int)' */ @Test public void testIntSquareMatrixIntMatrixIntIntInt() { IntMatrix rm = new IntMatrix(3, 4, new int[] { 11, 12, 13, 14, 21, 22, 23, 24, 31, 32, 33, 34 }); IntSquareMatrix rsm = new IntSquareMatrix(rm, 1, 1, 2); IntMatrix rm1 = new IntMatrix(2, 2, new int[] { 22, 23, 32, 33, }); MatrixTest.assertEquals("rsm int int int", rm1, (IntMatrix) rsm); } /** * Test method for * 'org.xmlcml.euclid.IntSquareMatrix.IntSquareMatrix(IntSquareMatrix)' */ @Test public void testIntSquareMatrixIntSquareMatrix() { IntSquareMatrix rsm = new IntSquareMatrix(m2); MatrixTest.assertEquals("copy", m2, rsm); } /** * Test method for * 'org.xmlcml.euclid.IntSquareMatrix.IntSquareMatrix(IntMatrix)' */ @Test public void testIntSquareMatrixIntMatrix() { IntMatrix rm = new IntMatrix(2, 2, new int[] { 22, 23, 32, 33, }); IntSquareMatrix rsm = new IntSquareMatrix(rm); MatrixTest.assertEquals("real matrix", rm, rsm); } /** * Test method for * 'org.xmlcml.euclid.IntSquareMatrix.IntSquareMatrix(int[][])' */ @Test public void testIntSquareMatrixIntegerArrayArray() { int[][] mat = new int[][] { new int[] { 11, 12, 13 }, new int[] { 21, 22, 23 }, new int[] { 31, 32, 33 }, }; IntSquareMatrix rsm = new IntSquareMatrix(mat); IntMatrix rm = new IntMatrix(3, 3, new int[] { 11, 12, 13, 21, 22, 23, 31, 32, 33, }); MatrixTest.assertEquals("real matrix", rm, rsm); } /** * Test method for * 'org.xmlcml.euclid.IntSquareMatrix.isEqualTo(IntSquareMatrix)' */ @Test public void testIsEqualToIntSquareMatrix() { IntSquareMatrix rsm = new IntSquareMatrix(m2); Assert.assertTrue("isEqualTo", m2.isEqualTo(rsm)); } /** * Test method for 'org.xmlcml.euclid.IntSquareMatrix.plus(IntSquareMatrix)' */ @Test public void testPlusIntSquareMatrix() { IntSquareMatrix rsm = m2.plus(m2); IntMatrix rm = new IntMatrix(3, 3, new int[] { 22, 24, 26, 42, 44, 46, 62, 64, 66, }); MatrixTest.assertEquals("real matrix", rm, rsm); } /** * Test method for * 'org.xmlcml.euclid.IntSquareMatrix.subtract(IntSquareMatrix)' */ @Test public void testSubtractIntSquareMatrix() { IntSquareMatrix rsm = m2.plus(m2); IntSquareMatrix rsm1 = m2.subtract(rsm); IntMatrix rm = new IntMatrix(3, 3, new int[] { -11, -12, -13, -21, -22, -23, -31, -32, -33, }); MatrixTest.assertEquals("real matrix", rm, rsm1); } /** * Test method for * 'org.xmlcml.euclid.IntSquareMatrix.multiply(IntSquareMatrix)' */ @Test public void testMultiplyIntSquareMatrix() { IntSquareMatrix rsm = m2.multiply(m2); IntMatrix rm = new IntMatrix(3, 3, new int[] { 776, 812, 848, 1406, 1472, 1538, 2036, 2132, 2228, }); MatrixTest.assertEquals("real matrix", rm, rsm); } /** * Test method for 'org.xmlcml.euclid.IntSquareMatrix.isUnit()' */ @Test public void testIsUnit() { IntSquareMatrix m = new IntSquareMatrix(3, new int[] { 1, 0, 0, 0, 1, 0, 0, 0, 1 }); Assert.assertTrue("unit", m.isUnit()); m = new IntSquareMatrix(3, new int[] { 1, 1, 1, 2, 3, 4, 3, 4, 7 }); Assert.assertFalse("unit", m.isUnit()); } /** * Test method for 'org.xmlcml.euclid.IntSquareMatrix.isSymmetric()' */ @Test public void testIsSymmetric() { IntSquareMatrix m = new IntSquareMatrix(3, new int[] { 1, 0, 3, 0, 1, 0, 3, 0, 1 }); Assert.assertTrue("unit", m.isSymmetric()); m = new IntSquareMatrix(3, new int[] { 1, 1, 1, 2, 3, 4, 3, 4, 7 }); Assert.assertFalse("unit", m.isSymmetric()); } /** * Test method for 'org.xmlcml.euclid.IntSquareMatrix.isUpperTriangular()' */ @Test public void testIsUpperTriangular() { IntSquareMatrix m = new IntSquareMatrix(3, new int[] { 0, 2, 3, 0, 0, 2, 0, 0, 0 }); Assert.assertTrue("upper triangular", m.isUpperTriangular()); m = new IntSquareMatrix(3, new int[] { 1, 2, 3, 0, 1, 2, 0, 0, 1 }); Assert.assertTrue("upper triangular", m.isUpperTriangular()); m = new IntSquareMatrix(3, new int[] { 1, 1, 1, 2, 3, 4, 3, 4, 7 }); Assert.assertFalse("upper triangular false", m.isUpperTriangular()); } /** * Test method for 'org.xmlcml.euclid.IntSquareMatrix.isLowerTriangular()' */ @Test public void testIsLowerTriangular() { IntSquareMatrix m = new IntSquareMatrix(3, new int[] { 0, 0, 0, 2, 0, 0, 3, 2, 0 }); Assert.assertTrue("lower triangular", m.isLowerTriangular()); m = new IntSquareMatrix(3, new int[] { 1, 0, 0, 2, 1, 0, 3, 2, 1 }); Assert.assertTrue("lower triangular", m.isLowerTriangular()); m = new IntSquareMatrix(3, new int[] { 1, 1, 1, 2, 3, 4, 3, 4, 7 }); Assert.assertFalse("lower triangular false", m.isLowerTriangular()); } /** * Test method for 'org.xmlcml.euclid.IntSquareMatrix.copyUpperToLower()' */ @Test public void testCopyUpperToLower() { IntSquareMatrix m = new IntSquareMatrix(3, new int[] { 6, 7, 8, 2, 5, 4, 3, 2, 9 }); m.copyUpperToLower(); IntSquareMatrix mm = new IntSquareMatrix(3, new int[] { 6, 7, 8, 7, 5, 4, 8, 4, 9 }); MatrixTest.assertEquals("copy upper", mm, m); } /** * Test method for 'org.xmlcml.euclid.IntSquareMatrix.copyLowerToUpper()' */ @Test public void testCopyLowerToUpper() { IntSquareMatrix m = new IntSquareMatrix(3, new int[] { 6, 7, 8, 2, 5, 4, 3, 2, 9 }); m.copyLowerToUpper(); IntSquareMatrix mm = new IntSquareMatrix(3, new int[] { 6, 2, 3, 2, 5, 2, 3, 2, 9 }); MatrixTest.assertEquals("copy upper", mm, m); } /** * Test method for 'org.xmlcml.euclid.IntSquareMatrix.lowerTriangle()' */ @Test public void testLowerTriangle() { IntSquareMatrix m = new IntSquareMatrix(3, new int[] { 6, 7, 8, 2, 5, 4, 3, 2, 9 }); IntArray ra = m.lowerTriangle(); String s = Int.testEquals((new int[] { 6, 2, 5, 3, 2, 9 }), ra.getArray()); if (s != null) { Assert.fail("lower triangle" + "; " + s); } } /** * Test method for 'org.xmlcml.euclid.IntSquareMatrix.transpose()' */ @Test public void testTranspose() { IntSquareMatrix m = new IntSquareMatrix(3, new int[] { 6, 7, 8, 2, 5, 4, 3, 1, 9 }); m.transpose(); IntSquareMatrix mm = new IntSquareMatrix(3, new int[] { 6, 2, 3, 7, 5, 1, 8, 4, 9 }); MatrixTest.assertEquals("transpose", mm, m); } } wwmm-euclid-87e8f785a814/src/test/java/org/xmlcml/euclid/test/IntTest.java0000644000000000000000000000266611607017524024407 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid.test; import org.junit.Assert; import org.junit.Test; import org.xmlcml.euclid.Int; /** * test Int. * * @author pmr * */ public class IntTest { /** * Test method for 'org.xmlcml.euclid.Int.zeroArray(int, int[])' */ @Test public void testZeroArray() { int[] ii = new int[5]; Int.zeroArray(5, ii); String s = Int.testEquals((new int[] { 0, 0, 0, 0, 0 }), ii); if (s != null) { Assert.fail("int[] " + "; " + s); } } /** * Test method for 'org.xmlcml.euclid.Int.initArray(int, int[], int)' */ @Test public void testInitArray() { int[] ii = new int[5]; Int.initArray(5, ii, 3); String s = Int.testEquals((new int[] { 3, 3, 3, 3, 3 }), ii); if (s != null) { Assert.fail("int[] " + "; " + s); } } } wwmm-euclid-87e8f785a814/src/test/java/org/xmlcml/euclid/test/JodaDateTest.java0000644000000000000000000000456111607017524025324 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid.test; import java.util.Date; import junit.framework.Assert; import org.joda.time.DateTime; import org.joda.time.DateTimeZone; import org.junit.Test; import org.xmlcml.euclid.JodaDate; public class JodaDateTest { @Test public void testFormatDate() { DateTime datetime = new DateTime(1288135627973L); datetime = datetime.withZone(DateTimeZone.forID("UTC")); String dateTimeString = JodaDate.formatIsoDate(datetime); Assert.assertEquals("date string", "2010-10-26T23:27:07.973Z", dateTimeString); } @Test public void testParseDate() { DateTime dateTime = JodaDate.parseDate("2010-10-27T00:27:07+01:00"); Assert.assertEquals("date millis", 1288135627000L, dateTime.getMillis()); } @Test public void testParseDate1() { DateTime dateTime = JodaDate.parseDate("25/12/1984", "dd/mm/yyyy"); Assert.assertEquals("date format", 443837520000L, dateTime.getMillis()); } @SuppressWarnings("deprecation") @Test public void testParseJavaDate() { Date date = new Date(2001-1900, 12, 25, 10, 20, 30); Assert.assertNotNull(date); DateTime dateTime = JodaDate.parseJavaDate(date); Assert.assertNotNull(dateTime); Assert.assertEquals("date to datetime", 1011954030000L, dateTime.getMillis()); } @Test public void testParseJodaDate() { DateTime dateTime = new DateTime(1288135627000L).withZone(DateTimeZone.forID("UTC")); Date date = JodaDate.parseJodaDate(dateTime); // I can't hack this at present // Assert.assertEquals("datetime to date", "Sat Nov 27 22:27:07 GMT 2010", date.toString()); Assert.assertTrue("datetime to date", date.toString().indexOf("Nov 27") != -1); } } wwmm-euclid-87e8f785a814/src/test/java/org/xmlcml/euclid/test/Line2Test.java0000644000000000000000000001404411607017524024617 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid.test; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.xmlcml.euclid.Line2; import org.xmlcml.euclid.Real; import org.xmlcml.euclid.Real2; import org.xmlcml.euclid.Vector2; /** * test for Line2 * * @author pm286 * */ public class Line2Test { static double sqrt2 = Math.sqrt(2.); static double sqrt5 = Math.sqrt(5.); Real2 p00 = new Real2(0., 0.); Real2 p02 = new Real2(0., 2.); Real2 p20 = new Real2(2., 0.); Real2 p12 = new Real2(1., 2.); Real2 p21 = new Real2(2., 1.); Real2 p11 = new Real2(1., 1.); Vector2 v12 = new Vector2(1., 2.); Line2 l0002; Line2 l0200; Line2 l0020; Line2 l1221; Line2 l1112; /** * @throws Exception * */ @Before public void setUp() throws Exception { l0002 = new Line2(p00, p02); l0200 = new Line2(p02, p00); l0020 = new Line2(p00, p20); l1221 = new Line2(p12, p21); l1112 = new Line2(p11, v12); } /** dewisott */ @Test public final void testLine2Real2Real2() { Assert.assertNotNull("l0002", l0002); Vector2 v = l0002.getVector(); Real2Test.assertEquals("vector", new Vector2(0., 2.), v, Real.EPS); Real2 p = l0002.getFrom(); Real2Test.assertEquals("from", new Real2(0., 0.), p, Real.EPS); p = l0002.getTo(); Real2Test.assertEquals("to", new Real2(0., 2.), p, Real.EPS); Assert.assertNotNull("l1221", l1221); v = l1221.getVector(); Real2Test.assertEquals("vector", new Vector2(1., -1.), v, Real.EPS); p = l1221.getFrom(); Real2Test.assertEquals("from", new Real2(1., 2.), p, Real.EPS); p = l1221.getTo(); Real2Test.assertEquals("to", new Real2(2., 1.), p, Real.EPS); } /** dewisott */ @Test public final void testLine2Real2Vector2() { Assert.assertNotNull("l1112", l1112); Vector2 v = l1112.getVector(); Real2Test.assertEquals("vector", new Vector2(1., 2.), v, Real.EPS); Real2 p = l1112.getFrom(); Real2Test.assertEquals("from", new Real2(1., 1.), p, Real.EPS); p = l1112.getTo(); Real2Test.assertEquals("to", new Real2(2., 3.), p, Real.EPS); } /** dewisott */ @Test public final void testGetSlope() { double slope = l0002.getSlope(); Assert.assertEquals("slope", Double.POSITIVE_INFINITY, slope, Real.EPS); slope = l0200.getSlope(); Assert.assertEquals("slope", Double.NEGATIVE_INFINITY, slope, Real.EPS); slope = l0020.getSlope(); Assert.assertEquals("slope", 0.0, slope, Real.EPS); slope = l1221.getSlope(); Assert.assertEquals("slope", -1.0, slope, Real.EPS); slope = l1112.getSlope(); Assert.assertEquals("slope", 2.0, slope, Real.EPS); } /** dewisott */ @Test public final void testGetYIntercept() { double yint = l1221.getYIntercept(); Assert.assertEquals("yint", 3.0, yint, Real.EPS); yint = l1112.getYIntercept(); Assert.assertEquals("yint", -1.0, yint, Real.EPS); Line2 ll = new Line2(new Real2(1., 1.), new Vector2(0., 1.)); yint = ll.getYIntercept(); Assert.assertEquals("yint", Double.NaN, yint, Real.EPS); ll = new Line2(new Real2(1., 1.), new Vector2(1., 0.)); yint = ll.getYIntercept(); Assert.assertEquals("yint", 1.0, yint, Real.EPS); } /** dewisott */ @Test public final void testGetXIntercept() { double xint = l1221.getXIntercept(); Assert.assertEquals("xint", 3.0, xint, Real.EPS); xint = l1112.getXIntercept(); Assert.assertEquals("xint", 0.5, xint, Real.EPS); Line2 ll = new Line2(new Real2(1., 1.), new Vector2(0., 1.)); xint = ll.getXIntercept(); Assert.assertEquals("xint", 1.0, xint, Real.EPS); ll = new Line2(new Real2(1., 1.), new Vector2(1., 0.)); xint = ll.getXIntercept(); Assert.assertEquals("xint", Double.NaN, xint, Real.EPS); } /** dewisott */ @Test public final void testGetIntersection() { Real2 p = l0002.getIntersection(l0020); Real2Test.assertEquals("intersect", new Real2(0., 0.), p, Real.EPS); p = l0002.getIntersection(l1112); Real2Test.assertEquals("intersect", new Real2(0.0, -1.0), p, Real.EPS); p = l1221.getIntersection(l1112); Real2Test.assertEquals("intersect", new Real2(4. / 3., 5. / 3.), p, Real.EPS); } /** dewisott */ @Test public final void testGetUnitVector() { Vector2 v = l1112.getUnitVector(); Real2Test.assertEquals("unitv", new Real2(1. / sqrt5, 2. / sqrt5), v, Real.EPS); } /** dewisott */ @Test public final void testGetDistanceFromPoint() { double d = l1112.getDistanceFromPoint(new Real2(0., 0.)); Assert.assertEquals("distance", 1. / sqrt5, d, Real.EPS); } /** dewisott */ @Test public final void testGetNearestPointOnLine() { Real2 p = l1112.getNearestPointOnLine(new Real2(0., 0.)); Real2Test.assertEquals("point", new Real2(0.4, -0.2), p, 0.0000001); } /** dewisott */ @Test public final void testGetLambda() { Real2 p = new Real2(0.4, -0.2); double lambda = l1112.getLambda(p); Assert.assertEquals("lambda", -0.6, lambda, Real.EPS); p = new Real2(0.0, -1.0); lambda = l1112.getLambda(p); Assert.assertEquals("lambda", -1.0, lambda, Real.EPS); lambda = l1112.getLambda(l1112.getTo()); Assert.assertEquals("lambda", 1.0, lambda, Real.EPS); } /** dewisott */ @Test public final void testGetLength() { Assert.assertEquals("length", sqrt2, l1221.getLength(), Real.EPS); } /** dewisott */ @Test public final void testGetMidPoint() { Real2Test.assertEquals("mid point", new Real2(1.5, 2), l1112 .getMidPoint(), Real.EPS); } } wwmm-euclid-87e8f785a814/src/test/java/org/xmlcml/euclid/test/Line3Test.java0000644000000000000000000001653111607017524024623 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid.test; import static org.xmlcml.euclid.EC.EPS; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.xmlcml.euclid.Angle; import org.xmlcml.euclid.EC; import org.xmlcml.euclid.Line3; import org.xmlcml.euclid.Point3; import org.xmlcml.euclid.Vector3; /** * test Line3 * * @author pmr * */ public class Line3Test extends GeomTest { /** * set up. * */ /** * setup. * * @throws Exception */ @Before public void setUp() throws Exception { super.setUp(); } /** * equality test. true if both args not null and equal within epsilon * * @param msg * message * @param test * @param expected * @param epsilon */ public static void assertEquals(String msg, Line3 test, Line3 expected, double epsilon) { Assert.assertNotNull("test should not be null (" + msg + EC.S_RBRAK, test); Assert.assertNotNull("ref should not be null (" + msg + EC.S_RBRAK, expected); Point3Test.assertEquals(msg, test.getPoint(), expected.getPoint(), epsilon); Vector3Test.assertEquals(msg, test.getVector(), expected.getVector(), epsilon); } /** * equality test. true if both args not null and equal within epsilon * * @param msg * message * @param testPoint * @param testVector * @param expected * @param epsilon */ public static void assertEquals(String msg, Point3 testPoint, Vector3 testVector, Line3 expected, double epsilon) { Assert.assertNotNull("testPoint should not be null (" + msg + EC.S_RBRAK, testPoint); Assert.assertNotNull("testVector should not be null (" + msg + EC.S_RBRAK, testVector); Assert.assertNotNull("expected should not be null (" + msg + EC.S_RBRAK, expected); Point3Test.assertEquals(msg, testPoint, expected.getPoint(), epsilon); Vector3Test .assertEquals(msg, testVector, expected.getVector(), epsilon); } /** * Test method for 'org.xmlcml.euclid.Line3.Line3()' */ @Test public void testLine3() { Assert.assertNotNull("line", l0); } /** * Test method for 'org.xmlcml.euclid.Line3.Line3(Point3, Vector3)' */ @Test public void testLine3Point3Vector3() { Assert.assertNotNull("line", l123456); Point3 p = l123456.getPoint(); Vector3 v = l123456.getVector(); Point3Test.assertEquals("line", new double[] { 4., 5., 6. }, p, EPS); Vector3Test.assertEquals("line", new double[] { 1. / s14, 2. / s14, 3. / s14 }, v, EPS); } /** * Test method for 'org.xmlcml.euclid.Line3.Line3(Point3, Point3)' */ @Test public void testLine3Point3Point3() { Line3 l = new Line3(p100, p001); Assert.assertNotNull("line", l); Point3 p = l.getPoint(); Vector3 v = l.getVector(); Point3Test.assertEquals("line", new double[] { 1., 0., 0. }, p, EPS); Vector3Test.assertEquals("line", new double[] { -1. / s2, 0., 1. / s2 }, v, EPS); } /** * Test method for 'org.xmlcml.euclid.Line3.Line3(Line3)' */ @Test public void testLine3Line3() { Line3 l = new Line3(l123456); Assert.assertNotNull("line", l); Point3 p = l.getPoint(); Vector3 v = l.getVector(); Point3Test.assertEquals("line", new double[] { 4., 5., 6. }, p, EPS); Vector3Test.assertEquals("line", new double[] { 1. / s14, 2. / s14, 3. / s14 }, v, EPS); } /** * Test method for 'org.xmlcml.euclid.Line3.isEqualTo(Line3)' */ @Test public void testIsEqualTo() { Line3 l = new Line3(l123456); Assert.assertTrue("isEqualTo", l.isEqualTo(l123456)); } /** * Test method for 'org.xmlcml.euclid.Line3.negative()' */ @Test public void testNegative() { Line3 l = new Line3(l123456); l = l.negative(); Vector3Test.assertEquals("negative", new double[] { -1. / s14, -2. / s14, -3. / s14 }, l.getVector(), EPS); Point3Test.assertEquals("negative", new double[] { 4., 5., 6. }, l .getPoint(), EPS); } /** * Test method for 'org.xmlcml.euclid.Line3.transform(Transform3)' */ @Test public void testTransform() { Line3 l = l123456.transform(tr1); Vector3Test.assertEquals("transform", new double[] { 1. / s14, -2. / s14, 3. / s14 }, l.getVector(), EPS); Point3Test.assertEquals("transform", new double[] { 4., -5., 6. }, l .getPoint(), EPS); } /** * Test method for 'org.xmlcml.euclid.Line3.isParallelTo(Line3)' */ @Test public void testIsParallelTo() { Line3 l = new Line3(l123456); Assert.assertTrue("isParallel", l.isParallelTo(l123456)); l = l.negative(); Assert.assertFalse("isParallel", l.isParallelTo(l123456)); } /** * Test method for 'org.xmlcml.euclid.Line3.isAntiparallelTo(Line3)' */ @Test public void testIsAntiparallelTo() { Line3 l = new Line3(l123456); Assert.assertFalse("isAntiParallel", l.isAntiparallelTo(l123456)); l = l.negative(); Assert.assertTrue("isAntiParallel", l.isAntiparallelTo(l123456)); } /** * Test method for 'org.xmlcml.euclid.Line3.containsPoint(Point3)' */ @Test public void testContainsPoint() { Assert.assertTrue("contains", l123456.containsPoint(new Point3(4., 5., 6.))); Assert.assertTrue("contains", l123456.containsPoint(new Point3(3., 3., 3.))); Assert.assertTrue("contains", l123456.containsPoint(new Point3(2., 1., 0.))); Assert.assertFalse("contains", l123456.containsPoint(new Point3(3., 5., 6.))); } /** * Test method for 'org.xmlcml.euclid.Line3.getClosestPointTo(Point3)' */ @Test public void testGetClosestPointTo() { Point3 p = l123456.getClosestPointTo(p100); Assert.assertTrue("contains", l123456.containsPoint(p)); Assert.assertFalse("contains", l123456.containsPoint(p100)); } /** * Test method for 'org.xmlcml.euclid.Line3.getDistanceFromPoint(Point3)' */ @Test public void testGetDistanceFromPoint() { double d = l123456.getDistanceFromPoint(p100); Assert.assertEquals("distance from", 1.1649647450214353, d, EPS); Point3 p = l123456.getClosestPointTo(p100); double dd = p.getDistanceFromPoint(p100); Assert.assertEquals("distance from", 1.1649647450214353, dd, EPS); Vector3 v = p.subtract(p100); Angle a = v.getAngleMadeWith(l123456.getVector()); Assert.assertNotNull("angle ", a); Assert.assertEquals("check angle", Math.PI / 2., a.getRadian(), EPS); } /** * Test method for 'org.xmlcml.euclid.Line3.getIntersectionWith(Plane3)' */ @Test public void testGetIntersectionWith() { Point3 p = l123456.getIntersectionWith(pl1111); Point3Test.assertEquals("intersection", new double[] { 1.788675134594813, 0.5773502691896262, -0.6339745962155607 }, p, EPS); Assert.assertTrue("contains", l123456.containsPoint(p)); Assert.assertTrue("contains", pl1111.containsPoint(p)); } } wwmm-euclid-87e8f785a814/src/test/java/org/xmlcml/euclid/test/MatrixTest.java0000644000000000000000000001035511607017524025113 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid.test; import static org.xmlcml.euclid.EC.EPS; import static org.xmlcml.euclid.EC.S_EMPTY; import static org.xmlcml.euclid.EC.S_RBRAK; import static org.xmlcml.euclid.test.EuclidTestBase.getAssertFormat; import junit.framework.Assert; import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.junit.Before; import org.junit.Test; import org.xmlcml.euclid.Int; import org.xmlcml.euclid.IntMatrix; import org.xmlcml.euclid.Real; import org.xmlcml.euclid.RealMatrix; /** * test Matrix stuff. * * @author pmr * */ public class MatrixTest { static Logger logger = Logger.getLogger(MatrixTest.class.getName()); /** * setup. * * @throws Exception */ @Before public void setUp() throws Exception { logger.setLevel(Level.WARN); } /** * Asserts equality of RealMatrix. * * checks for non-null, then equality of length, then individual elements * * @param message * @param a * expected array * @param b * actual array * @param eps * tolerance for agreement */ public static void assertEquals(String message, RealMatrix a, RealMatrix b, double eps) { if (a == null || b == null) { Assert.fail(getAssertFormat(message, "double[]", "null")); } int aRows = a.getRows(); int bRows = b.getRows(); int aCols = a.getCols(); int bCols = b.getCols(); if (aRows != bRows) { Assert.fail(getAssertFormat(message + "; unequal rows in matrices", S_EMPTY + aRows, S_EMPTY + bRows)); } if (aCols != bCols) { Assert.fail(getAssertFormat(message + "; unequal cols in matrices", S_EMPTY + aCols, S_EMPTY + bCols)); } double[][] aMat = a.getMatrix(); double[][] bMat = b.getMatrix(); for (int i = 0; i < aRows; i++) { for (int j = 0; j < aCols; j++) { if (!Real.isEqual(aMat[i][j], bMat[i][j], eps)) { Assert.fail(getAssertFormat(message + "; unequal element (" + i + ", " + j + S_RBRAK, S_EMPTY + aMat[i][j], S_EMPTY + bMat[i][j])); } } } } /** * Asserts equality of RealMatrix. * * checks for non-null, then equality of length, then individual elements * * @param message * @param a * expected array * @param b * actual array */ public static void assertEquals(String message, IntMatrix a, IntMatrix b) { if (a == null || b == null) { Assert.fail(getAssertFormat(message, "IntMatrix", "null")); } int aRows = a.getRows(); int bRows = b.getRows(); int aCols = a.getCols(); int bCols = b.getCols(); if (aRows != bRows) { Assert.fail(getAssertFormat(message + "; unequal rows in matrices", S_EMPTY + aRows, S_EMPTY + bRows)); } if (aCols != bCols) { Assert.fail(getAssertFormat(message + "; unequal cols in matrices", S_EMPTY + aCols, S_EMPTY + bCols)); } String s = Int.testEquals(a.getMatrix(), b.getMatrix()); if (s != null) { Assert.fail(message + "; " + s); } } /** test */ @Test public void testRealMatrix() { RealMatrix a = new RealMatrix(2, 3, new double[] { 11.0, 12.0, 13.0, 21.0, 22.0, 23.0 }); RealMatrix b = new RealMatrix(2, 3, new double[] { 11.0, 12.0, 13.0, 21.0, 28.0, 23.0 }); MatrixTest.assertEquals("MatrixTest", a, a, EPS); Assert.assertNotNull(b); } /** test */ @Test public void testIntMatrix() { IntMatrix a = new IntMatrix(2, 3, new int[] { 11, 12, 13, 21, 22, 23 }); IntMatrix b = new IntMatrix(2, 3, new int[] { 11, 12, 13, 21, 28, 23 }); Assert.assertNotNull(b); Assert.assertEquals("MatrixTest", a, a); } } wwmm-euclid-87e8f785a814/src/test/java/org/xmlcml/euclid/test/Plane3Test.java0000644000000000000000000002355511607017524024777 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid.test; import static org.xmlcml.euclid.EC.EPS; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.xmlcml.euclid.Angle; import org.xmlcml.euclid.EC; import org.xmlcml.euclid.EuclidRuntimeException; import org.xmlcml.euclid.Line3; import org.xmlcml.euclid.Plane3; import org.xmlcml.euclid.Point3; import org.xmlcml.euclid.Vector3; /** * test Plane3 * * @author pmr * */ public class Plane3Test extends GeomTest { /** * setup. * * @throws Exception */ @Before public void setUp() throws Exception { super.setUp(); } /** * equality test. true if both args not null and equal within epsilon * * @param msg * message * @param test * @param expected * @param epsilon */ public static void assertEquals(String msg, Plane3 test, Plane3 expected, double epsilon) { Assert.assertNotNull("test should not be null (" + msg + EC.S_RBRAK, test); Assert.assertNotNull("ref should not be null (" + msg + EC.S_RBRAK, expected); DoubleTestBase.assertEquals(msg, test.getArray(), expected.getArray(), epsilon); } /** * equality test. true if both args not null and equal within epsilon * * @param msg * message * @param test * array must be of length 4 * @param expected * @param epsilon */ public static void assertEquals(String msg, double[] test, Plane3 expected, double epsilon) { Assert.assertNotNull("test should not be null (" + msg + EC.S_RBRAK, test); Assert.assertEquals("must be of length 4", 4, test.length); Assert.assertNotNull("ref should not be null (" + msg + EC.S_RBRAK, expected); DoubleTestBase.assertEquals(msg, test, expected.getArray(), epsilon); } /** * Test method for 'org.xmlcml.euclid.Plane3.Plane3()' */ @Test public void testPlane3() { Assert.assertNotNull("plane", pl0); Plane3Test.assertEquals("plane", new double[] { 0., 0., 0., 0. }, pl0, EPS); } /** * Test method for 'org.xmlcml.euclid.Plane3.Plane3(double, double, double, * double)' */ @Test public void testPlane3DoubleDoubleDoubleDouble() { Plane3Test.assertEquals("plane", new double[] { 1., 0., 0., 0. }, pl1000, EPS); } /** * Test method for 'org.xmlcml.euclid.Plane3.Plane3(double[], double)' */ @Test public void testPlane3DoubleArrayDouble() { Plane3Test.assertEquals("plane", new double[] { 1. / s14, 2. / s14, 3. / s14, 4. }, pl1234, EPS); } /** * Test method for 'org.xmlcml.euclid.Plane3.Plane3(double[])' */ @Test public void testPlane3DoubleArray() { Plane3Test.assertEquals("plane", new double[] { 0., 0., 1., 0. }, pl0010, EPS); } /** * Test method for 'org.xmlcml.euclid.Plane3.Plane3(Vector3, double)' */ @Test public void testPlane3Vector3Double() { Plane3Test.assertEquals("plane", new double[] { 1. / s3, 1. / s3, 1. / s3, 1. }, pl1111, EPS); } /** * Test method for 'org.xmlcml.euclid.Plane3.Plane3(Plane3)' */ @Test public void testPlane3Plane3() { Plane3 pl = new Plane3(pl1234); Plane3Test.assertEquals("plane", new double[] { 1. / s14, 2. / s14, 3. / s14, 4. }, pl, EPS); } /** * Test method for 'org.xmlcml.euclid.Plane3.Plane3(Point3, Point3, Point3)' */ @Test public void testPlane3Point3Point3Point3() { Plane3 pl = new Plane3(p100, p010, p001); Plane3Test.assertEquals("plane", new double[] { 1. / s3, 1. / s3, 1. / s3, 1. / s3 }, pl, EPS); try { pl = new Plane3(p100, p010, p100); Assert.fail("should always throw " + "zero normal"); } catch (EuclidRuntimeException e) { Assert.assertEquals("plane", "zero length normal", e.getMessage()); } } /** * Test method for 'org.xmlcml.euclid.Plane3.Plane3(Line3, Point3)' */ @Test public void testPlane3Line3Point3() { Plane3 pl = new Plane3(l100000, p001); Plane3Test.assertEquals("plane", new double[] { 0., -1., 0., 0. }, pl, EPS); pl = new Plane3(l123456, p321); Assert.assertNotNull("plane", pl); Plane3Test.assertEquals("plane", new double[] { -0.40824829046386013, 0.816496580927727, -0.4082482904638642, 9.325873406851315E-15 }, pl, EPS); } /** * Test method for 'org.xmlcml.euclid.Plane3.getVector()' */ @Test public void testGetVector() { Plane3 pl = new Plane3(p100, p010, p001); Vector3 v = pl.getVector(); Vector3Test.assertEquals("vector", new double[] { 1. / s3, 1. / s3, 1. / s3 }, v, EPS); } /** * Test method for 'org.xmlcml.euclid.Plane3.getDistance()' */ @Test public void testGetDistance() { Plane3 pl = new Plane3(p100, p010, p001); Assert.assertEquals("distance", 1. / s3, pl.getDistance(), EPS); } /** * Test method for 'org.xmlcml.euclid.Plane3.negative()' */ @Test public void testNegative() { Plane3 pl = new Plane3(p100, p010, p001); Plane3Test.assertEquals("negative", new double[] { 1. / s3, 1. / s3, 1. / s3, 1. / s3 }, pl, EPS); pl.negative(); Plane3Test.assertEquals("negative", new double[] { -1. / s3, -1. / s3, -1. / s3, 1. / s3 }, pl, EPS); } /** * Test method for 'org.xmlcml.euclid.Plane3.isEqualTo(Plane3)' */ @Test public void testIsEqualTo() { Plane3 pl = new Plane3(pl1234); Assert.assertTrue("equals", pl.isEqualTo(pl1234)); } /** * Test method for 'org.xmlcml.euclid.Plane3.subtract()' */ @Test public void testSubtract() { Plane3Test.assertEquals("equals", new double[] { 1. / s14, 2. / s14, 3. / s14, 4. }, pl1234, EPS); Plane3 pl = pl1234.subtract(); Plane3Test.assertEquals("equals", new double[] { -1. / s14, -2. / s14, -3. / s14, 4. }, pl, EPS); } /** * Test method for 'org.xmlcml.euclid.Plane3.getDistanceFromPoint(Point3)' */ @Test public void testGetDistanceFromPoint() { double d = pl1111.getDistanceFromPoint(p000); Assert.assertEquals("equals", -1., d, EPS); Plane3 pl = pl1111.subtract(); Assert.assertEquals("equals", -1., pl.getDistanceFromPoint(p000), EPS); } /** * Test method for 'org.xmlcml.euclid.Plane3.isParallelTo(Plane3)' */ @Test public void testIsParallelTo() { Plane3 pl = new Plane3(pl1234); Assert.assertTrue("parallel", pl.isParallelTo(pl1234)); pl.subtract(); Assert.assertFalse("parallel", pl.isParallelTo(pl1234)); } /** * Test method for 'org.xmlcml.euclid.Plane3.isAntiparallelTo(Plane3)' */ @Test public void testIsAntiparallelTo() { Plane3 pl = new Plane3(pl1234); Assert.assertFalse("antiparallel", pl.isAntiparallelTo(pl1234)); pl = pl.subtract(); Assert.assertTrue("isAntiparallelTo", pl.isAntiparallelTo(pl1234)); } /** * Test method for 'org.xmlcml.euclid.Plane3.containsPoint(Point3)' */ @Test public void testContainsPoint() { Assert.assertFalse("contains", pl1111.containsPoint(p111)); Assert.assertTrue("contains", pl1111.containsPoint(new Point3(1. / s3, 1. / s3, 1. / s3))); } /** * Test method for 'org.xmlcml.euclid.Plane3.getClosestPointTo(Point3)' */ @Test public void testGetClosestPointTo() { Point3 p = pl1111.getClosestPointTo(p000); Point3Test.assertEquals("equals", new double[] { 1. / s3, 1. / s3, 1. / s3 }, p, EPS); } /** * Test method for 'org.xmlcml.euclid.Plane3.getIntersectionWith(Line3)' */ @Test public void testGetIntersectionWithLine3() { Point3 p = pl1111.getIntersectionWith(l123456); Point3Test.assertEquals("equals", new double[] { 1.788675134594813, 0.5773502691896262, -0.6339745962155607 }, p, EPS); double d = pl1111.getDistanceFromPoint(p); Assert.assertEquals("intersection", 0.0, d, EPS); d = l123456.getDistanceFromPoint(p); Assert.assertEquals("intersection", 0.0, d, EPS); } /** * Test method for 'org.xmlcml.euclid.Plane3.getIntersectionWith(Plane3)' */ @Test public void testGetIntersectionWithPlane3() { Line3 l = pl1111.getIntersectionWith(pl1234); Vector3Test.assertEquals("plane line", new double[] { 0.4082482904638631, -0.8164965809277261, 0.4082482904638631, }, l.getVector(), EPS); Point3Test.assertEquals("plane line", new double[] { -5.17391369678938, 0.5773502691896258, 6.328614235168632 }, l.getPoint(), EPS); Point3 p = l.getPoint(); double d = pl1111.getDistanceFromPoint(p); Assert.assertEquals("intersection", 0.0, d, EPS); Point3 p1 = p.plus(l.getVector()); d = pl1234.getDistanceFromPoint(p1); Assert.assertEquals("intersection", 0.0, d, EPS); } /** * Test method for 'org.xmlcml.euclid.Plane3.getIntersectionWith(Plane3, * Plane3)' */ @Test public void testGetIntersectionWithPlane3Plane3() { Point3 p = pl1111.getIntersectionWith(pl1234, pl1000); Point3Test.assertEquals("intersection", new double[] { 0.0, -9.770477124389135, 11.502527931958012 }, p, EPS); // check double d = pl1111.getDistanceFromPoint(p); Assert.assertEquals("intersection", 0.0, d, EPS); d = pl1234.getDistanceFromPoint(p); Assert.assertEquals("intersection", 0.0, d, EPS); } /** * Test method for 'org.xmlcml.euclid.Plane3.getAngleMadeWith(Plane3)' */ @Test public void testGetAngleMadeWith() { Angle a = pl1111.getAngleMadeWith(pl1234); Assert.assertEquals("angle", 0.38759668665518016, a.getRadian(), EPS); } } wwmm-euclid-87e8f785a814/src/test/java/org/xmlcml/euclid/test/Point3Test.java0000644000000000000000000003645011607017524025027 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid.test; import static org.xmlcml.euclid.EC.EPS; import static org.xmlcml.euclid.EC.S_RBRAK; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.xmlcml.euclid.Angle; import org.xmlcml.euclid.EuclidRuntimeException; import org.xmlcml.euclid.Line3; import org.xmlcml.euclid.Plane3; import org.xmlcml.euclid.Point3; import org.xmlcml.euclid.Util; import org.xmlcml.euclid.Vector3; /** * test Point3 * * @author pmr * */ public class Point3Test extends GeomTest { /** * setup. */ /** * setup. * * @throws Exception */ @Before public void setUp() throws Exception { super.setUp(); } /** * equality test. true if both args not null and equal within epsilon * * @param msg * message * @param test * @param expected * @param epsilon */ public static void assertEquals(String msg, Point3 test, Point3 expected, double epsilon) { Assert.assertNotNull("test should not be null (" + msg + S_RBRAK, test); Assert.assertNotNull("ref should not be null (" + msg + S_RBRAK, expected); DoubleTestBase.assertEquals(msg, test.getArray(), expected.getArray(), epsilon); } /** * equality test. true if both args not null and equal within epsilon * * @param msg * message * @param test * array must be of length 3 * @param expected * @param epsilon */ public static void assertEquals(String msg, double[] test, Point3 expected, double epsilon) { Assert.assertNotNull("test should not be null (" + msg + S_RBRAK, test); Assert.assertEquals("must be of length 3", 3, test.length); Assert.assertNotNull("ref should not be null (" + msg + S_RBRAK, expected); DoubleTestBase.assertEquals(msg, test, expected.getArray(), epsilon); } /** * Test method for 'org.xmlcml.euclid.Point3.Point3()' */ @Test public void testPoint3() { Assert.assertNotNull("point", p0); Point3Test .assertEquals("point 0", new double[] { 0., 0., 0. }, p0, EPS); } /** * Test method for 'org.xmlcml.euclid.Point3.Point3(double, double, double)' */ @Test public void testPoint3DoubleDoubleDouble() { Assert.assertNotNull("point", p123); Point3Test.assertEquals("point 123", new double[] { 1., 2., 3. }, p123, EPS); } /** * Test method for 'org.xmlcml.euclid.Point3.Point3(Point3)' */ @Test public void testPoint3Point3() { Point3 pp = new Point3(p123); Assert.assertNotNull("point", pp); Point3Test.assertEquals("point copy", new double[] { 1., 2., 3. }, pp, EPS); } /** * Test method for 'org.xmlcml.euclid.Point3.Point3(double[])' */ @Test public void testPoint3DoubleArray() { Point3 pp = new Point3(new double[] { 1., 3., 5. }); Assert.assertNotNull("point", pp); Point3Test.assertEquals("point copy", new double[] { 1., 3., 5. }, pp, EPS); try { pp = new Point3(new double[] { 1., 3. }); Assert.fail("should always throw " + "must have 3 coordinates"); } catch (EuclidRuntimeException e) { Assert.assertEquals("bad coordinates", "array size required (3) found 2", e.getMessage()); } } /** * Test method for 'org.xmlcml.euclid.Point3.Point3(Vector3)' */ @Test public void testPoint3Vector3() { Point3 pp = new Point3(v123); Assert.assertNotNull("point", pp); Point3Test.assertEquals("point copy", new double[] { 1., 2., 3. }, pp, EPS); } /** * Test method for 'org.xmlcml.euclid.Point3.getArray()' */ @Test public void testGetArray() { Point3Test.assertEquals("point array", new double[] { 1., 2., 3. }, p123, EPS); } /** * Test method for 'org.xmlcml.euclid.Point3.clear()' */ @Test public void testClear() { p123.clear(); Point3Test.assertEquals("point array", new double[] { 0., 0., 0. }, p123, EPS); } /** * Test method for 'org.xmlcml.euclid.Point3.isEqualTo(Point3)' */ @Test public void testIsEqualToPoint3() { Point3 pp = new Point3(p123); Assert.assertTrue("point isEqualTo", p123.isEqualTo(pp)); } /** * Test method for 'org.xmlcml.euclid.Point3.isEqualTo(Point3, double)' */ @Test public void testIsEqualToPoint3Double() { Point3 pp = new Point3(p123); Assert.assertTrue("point isEqualTo", p123.isEqualTo(pp, EPS)); } /** * Test method for * 'org.xmlcml.euclid.Point3.equalsCrystallographically(Point3)' */ @Test public void testEqualsCrystallographically() { Assert.assertTrue("point isEqualToCrystallographically", p123 .equalsCrystallographically(p000)); Assert.assertFalse("point isEqualToCrystallographically", p123 .equalsCrystallographically(new Point3(0.1, 0.2, 0.3))); } /** * Test method for * 'org.xmlcml.euclid.Point3.normaliseCrystallographically()' */ @Test public void testNormaliseCrystallographically() { Point3 p = new Point3(1.1, 2.2, -0.7); p.normaliseCrystallographically(); Point3Test.assertEquals("normalise", new double[] { 0.1, 0.2, 0.3 }, p, EPS); } /** * Test method for 'org.xmlcml.euclid.Point3.isInvariant(Transform3, * boolean)' */ @Test public void testIsInvariant() { boolean allowTranslate = false; Assert.assertTrue("invariant", p123.isInvariant(tr0, allowTranslate)); allowTranslate = true; Assert.assertTrue("invariant", p123.isInvariant(tr0, allowTranslate)); allowTranslate = false; Assert.assertFalse("invariant", p123.isInvariant(tr1, allowTranslate)); allowTranslate = true; Assert.assertTrue("invariant", p123.isInvariant(tr0, allowTranslate)); } /** * Test method for 'org.xmlcml.euclid.Point3.subtract(Point3)' */ @Test public void testSubtractPoint3() { Vector3 v = p123.subtract(p321); Vector3Test.assertEquals("subtract", new double[] { -2, 0, 2 }, v, EPS); } /** * Test method for 'org.xmlcml.euclid.Point3.plus(Point3)' */ @Test public void testPlusPoint3() { Point3 pp = p123.plus(p321); Point3Test.assertEquals("subtract", new double[] { 4., 4., 4. }, pp, EPS); } /** * Test method for 'org.xmlcml.euclid.Point3.plusEquals(Point3)' */ @Test public void testPlusEqualsPoint3() { p123.plusEquals(p321); Point3Test.assertEquals("plusEquals", new double[] { 4., 4., 4. }, p123, EPS); } /** * Test method for 'org.xmlcml.euclid.Point3.plus(Vector3)' */ @Test public void testPlusVector3() { Point3 pp = p123.plus(v321); Point3Test.assertEquals("plus", new double[] { 4., 4., 4. }, pp, EPS); } /** * Test method for 'org.xmlcml.euclid.Point3.plusEquals(Vector3)' */ @Test public void testPlusEqualsVector3() { p123.plusEquals(v321); Point3Test.assertEquals("plusEquals", new double[] { 4., 4., 4. }, p123, EPS); } /** * Test method for 'org.xmlcml.euclid.Point3.subtract(Vector3)' */ @Test public void testSubtractVector3() { Point3 pp = p123.subtract(v321); Point3Test.assertEquals("subtract", new double[] { -2., 0., 2. }, pp, EPS); } /** * Test method for 'org.xmlcml.euclid.Point3.subtractEquals(Point3)' */ @Test public void testSubtractEqualsPoint3() { p123.subtractEquals(p321); Point3Test.assertEquals("subtractEquals", new double[] { -2., 0., 2. }, p123, EPS); } /** * Test method for 'org.xmlcml.euclid.Point3.subtractEquals(Vector3)' */ @Test public void testSubtractEqualsVector3() { p123.subtractEquals(v321); Point3Test.assertEquals("subtractEquals", new double[] { -2., 0., 2. }, p123, EPS); } /** * Test method for 'org.xmlcml.euclid.Point3.multiplyBy(double)' */ @Test public void testMultiplyBy() { Point3 p = p123.multiplyBy(10.); Point3Test.assertEquals("multiply", new double[] { 10., 20., 30. }, p, EPS); } /** * Test method for 'org.xmlcml.euclid.Point3.multiplyEquals(double)' */ @Test public void testMultiplyEquals() { p123.multiplyEquals(10.); Point3Test.assertEquals("multiplyEquals", new double[] { 10., 20., 30. }, p123, EPS); } /** * Test method for 'org.xmlcml.euclid.Point3.reflect()' */ @Test public void testReflect() { p123.reflect(); Point3Test.assertEquals("reflect", new double[] { -1., -2., -3. }, p123, EPS); } /** * Test method for 'org.xmlcml.euclid.Point3.divideBy(double)' */ @Test public void testDivideBy() { Point3 p = p123.divideBy(10.); Point3Test.assertEquals("divideBy", new double[] { 0.1, 0.2, 0.3 }, p, EPS); } /** * Test method for 'org.xmlcml.euclid.Point3.divideEquals(double)' */ @Test public void testDivideEquals() { p123.divideEquals(10.); Point3Test.assertEquals("divideEquals", new double[] { 0.1, 0.2, 0.3 }, p123, EPS); } /** * Test method for 'org.xmlcml.euclid.Point3.elementAt(int)' */ @Test public void testElementAt() { double d = p123.elementAt(1); Assert.assertEquals("element at", 2., d, EPS); try { d = p123.elementAt(3); } catch (EuclidRuntimeException e) { Assert.assertEquals("element at", "index (3)out of range: 0/2", e .getMessage()); } } /** * Test method for 'org.xmlcml.euclid.Point3.setElementAt(int, double)' */ @Test public void testSetElementAt() { p123.setElementAt(1, 10.); Point3Test.assertEquals("set element at", new double[] { 1., 10., 3. }, p123, EPS); try { p123.setElementAt(3, 10.); } catch (EuclidRuntimeException e) { Assert.assertEquals("element at", "index (3)out of range: 0/2", e .getMessage()); } } /** * Test method for 'org.xmlcml.euclid.Point3.transform(Transform3)' */ @Test public void testTransform() { Point3 p = p123.transform(tr1); Point3Test.assertEquals("transform", new double[] { 1., -2., 3. }, p, EPS); } /** * Test method for 'org.xmlcml.euclid.Point3.transformEquals(Transform3)' */ @Test public void testTransformEquals() { p123.transformEquals(tr1); Point3Test.assertEquals("transform", new double[] { 1., -2., 3. }, p123, EPS); } /** * Test method for 'org.xmlcml.euclid.Point3.getDistanceFromOrigin()' */ @Test public void testGetDistanceFromOrigin() { double d = p123.getDistanceFromOrigin(); Assert.assertEquals("distance from origin", Math.sqrt(14.), d, EPS); } /** * Test method for * 'org.xmlcml.euclid.Point3.getSquaredDistanceFromPoint(Point3)' */ @Test public void testGetSquaredDistanceFromPoint() { double d = p123.getSquaredDistanceFromPoint(p321); Assert.assertEquals("distance from origin", 8., d, EPS); } /** * Test method for 'org.xmlcml.euclid.Point3.getDistanceFromPoint(Point3)' */ @Test public void testGetDistanceFromPoint() { double d = p123.getDistanceFromPoint(p321); Assert.assertEquals("distance from origin", Math.sqrt(8.), d, EPS); } /** * Test method for 'org.xmlcml.euclid.Point3.distanceFromPlane(Plane3)' */ @Test public void testDistanceFromPlane() { Point3 p = new Point3(0., 0., 0.); Plane3 pl = null; try { pl = new Plane3(new Vector3(1., 1., 1.), 1.0); } catch (Exception e) { Util.BUG(e); } double d = p.distanceFromPlane(pl); Assert.assertEquals("distance ", -1.0, d, EPS); p = new Point3(1., 1., 1.); d = p.distanceFromPlane(pl); Assert.assertEquals("distance ", Math.sqrt(3.) - 1., d, EPS); } /** * Test method for 'org.xmlcml.euclid.Point3.getClosestPointOnLine(Line3)' */ @Test public void testGetClosestPointOnLine() { Vector3 vv = new Vector3(1., 1., 1.); Point3 pp = new Point3(1., 2., 3.); Line3 ll = new Line3(pp, vv); Assert.assertTrue("on line", pp.isOnLine(ll)); double d = pp.distanceFromLine(ll); Point3 p0 = new Point3(0., 0., 0.); Assert.assertFalse("on line", p0.isOnLine(ll)); Point3 pClose = p0.getClosestPointOnLine(ll); Point3Test.assertEquals("nearest point", new double[] { -1, 0., 1. }, pClose, EPS); d = pClose.distanceFromLine(ll); Assert.assertEquals("distance", 0.0, d, EPS); Vector3 v = pClose.subtract(p0); Angle a = null; a = v.getAngleMadeWith(vv); Assert.assertEquals("angle ", Math.PI / 2., a.getRadian(), EPS); } /** * Test method for 'org.xmlcml.euclid.Point3.isOnLine(Line3)' */ @Test public void testIsOnLine() { Vector3 vv = new Vector3(1., 1., 1.); Point3 p = new Point3(1., 2., 3.); Line3 l3 = new Line3(p, vv); Assert.assertTrue("on line", p.isOnLine(l3)); } /** * Test method for 'org.xmlcml.euclid.Point3.distanceFromLine(Line3)' */ @Test public void testDistanceFromLine() { Point3 pp = new Point3(4., 5., 6.); Vector3 vv = new Vector3(1., 2., 3.); Line3 ll = new Line3(pp, vv); double d = pp.distanceFromLine(ll); Assert.assertEquals("distance from line", 0.0, d,EPS); Point3 p0 = new Point3(0., 0., 0.); d = p0.distanceFromLine(ll); Assert.assertEquals("distance", 1.9639610121239313, d, EPS); } /** * Test method for 'org.xmlcml.euclid.Point3.getMidPoint(Point3)' */ @Test public void testGetMidPoint() { Point3 p = p123.getMidPoint(p321); Point3Test.assertEquals("mid point", new double[] { 2., 2., 2. }, p, EPS); } /** * Test method for 'org.xmlcml.euclid.Point3.getAngle(Point3, Point3, * Point3)' */ @Test public void testGetAngle() { Point3 p444 = new Point3(4., 4., 4.); Angle p = Point3.getAngle(p123, p444, p321); Assert.assertNotNull("angle ", p); Assert.assertEquals("angle", 0.7751933733103613, p.getRadian(), EPS); p = Point3 .getAngle(new Point3(1., 0., 0), p000, new Point3(0., 1., 0.)); Assert.assertNotNull("angle ", p); Assert.assertEquals("angle", Math.PI / 2., p.getRadian(), EPS); } /** * Test method for 'org.xmlcml.euclid.Point3.getTorsion(Point3, Point3, * Point3, Point3)' */ @Test public void testGetTorsion() { Angle p = null; p = Point3.getTorsion(new Point3(1., 0., 0), p000, new Point3(0., 1., 0.), new Point3(0., 1., 1.)); Assert.assertEquals("angle", -Math.PI / 2., p.getRadian(), EPS); } /** * Test method for * 'org.xmlcml.euclid.Point3.calculateFromInternalCoordinates(Point3, * Point3, Point3, double, Angle, Angle)' */ @Test public void testCalculateFromInternalCoordinates() { Point3 p0 = new Point3(1., 0., 0.); Point3 p1 = new Point3(0., 0., 0.); Point3 p2 = new Point3(0., 1., 0.); Point3 p = Point3.calculateFromInternalCoordinates(p0, p1, p2, 2.0, new Angle(Math.PI / 2), new Angle(Math.PI / 2)); Point3Test.assertEquals("internals", new double[] { 0.0, 1.0, -2.0 }, p, EPS); } /** * Test method for 'org.xmlcml.euclid.Point3.isOrigin()' */ @Test public void testIsOrigin() { Assert.assertTrue("origin", p000.isOrigin()); Assert.assertFalse("origin", p123.isOrigin()); } } wwmm-euclid-87e8f785a814/src/test/java/org/xmlcml/euclid/test/Point3VectorTest.java0000644000000000000000000005527411607017524026217 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid.test; import static org.xmlcml.euclid.EuclidConstants.EPS; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.xmlcml.euclid.Angle; import org.xmlcml.euclid.Axis.Axis3; import org.xmlcml.euclid.EC; import org.xmlcml.euclid.EuclidRuntimeException; import org.xmlcml.euclid.Int; import org.xmlcml.euclid.IntSet; import org.xmlcml.euclid.Line3; import org.xmlcml.euclid.Plane3; import org.xmlcml.euclid.Point3; import org.xmlcml.euclid.Point3Vector; import org.xmlcml.euclid.Real3Range; import org.xmlcml.euclid.RealArray; import org.xmlcml.euclid.RealMatrix; import org.xmlcml.euclid.RealRange; import org.xmlcml.euclid.RealSquareMatrix; import org.xmlcml.euclid.Transform3; import org.xmlcml.euclid.Vector3; /** * test Point3Vector. * * @author pmr * */ public class Point3VectorTest { Point3Vector p0; Point3Vector p1; Point3Vector p2; final static double s2 = Math.sqrt(2.); final static double s3 = Math.sqrt(3.); /** * setup. * * @throws Exception */ @Before public void setUp() throws Exception { p0 = new Point3Vector(); p1 = new Point3Vector(new double[] { 11., 21., 31., 12., 22., 32., 13., 23., 33., 14., 24., 34. }); p2 = new Point3Vector(new double[] { 1., 0., 0., 0., 0., 0., 0., 1., 0., 0., 1., 1. }); } /** * equality test. true if both args not null and equal within epsilon * * @param msg * message * @param test * @param expected * @param epsilon */ public static void assertEquals(String msg, Point3Vector test, Point3Vector expected, double epsilon) { Assert.assertNotNull("test should not be null (" + msg + EC.S_RBRAK, test); Assert.assertNotNull("expected should not be null (" + msg + EC.S_RBRAK, expected); DoubleTestBase.assertEquals(msg, test.getArray(), expected.getArray(), epsilon); } /** * equality test. true if both args not null and equal within epsilon * * @param msg * message * @param test * array must be of length 3 * @param expected * @param epsilon */ public static void assertEquals(String msg, double[] test, Point3Vector expected, double epsilon) { Assert.assertNotNull("test should not be null (" + msg + EC.S_RBRAK, test); Assert.assertNotNull("expected should not be null (" + msg + EC.S_RBRAK, expected); Assert.assertEquals("must be of equal length ", test.length, expected .getArray().length); DoubleTestBase.assertEquals(msg, test, expected.getArray(), epsilon); } /** * Test method for 'org.xmlcml.euclid.Point3Vector.Point3Vector()' */ @Test public void testPoint3Vector() { Assert.assertNotNull("p3v", p0); Assert.assertEquals("p3v", 0, p0.size()); } /** * Test method for 'org.xmlcml.euclid.Point3Vector.Point3Vector(double[])' */ @Test public void testPoint3VectorDoubleArray() { Assert.assertNotNull("p3v", p1); Assert.assertEquals("p3v", 4, p1.size()); try { new Point3Vector(new double[] { 1., 2., 3., 4. }); } catch (EuclidRuntimeException e) { Assert.assertEquals("bad array", "array length must be multiple of 3", e.getMessage()); } } /** * Test method for 'org.xmlcml.euclid.Point3Vector.Point3Vector(int, * double[], double[], double[])' */ @Test public void testPoint3VectorIntDoubleArrayDoubleArrayDoubleArray() { new Point3Vector(3, new double[] { 11., 12., 13., }, new double[] { 21., 22., 23., }, new double[] { 31., 32., 33., }); try { new Point3Vector(3, new double[] { 11., 12., 13., }, new double[] { 21., 22., 23., }, new double[] { 31., 32., }); } catch (EuclidRuntimeException e) { Assert.assertEquals("bad array", "array size required (3) found 2", e.getMessage()); } } /** * Test method for 'org.xmlcml.euclid.Point3Vector.Point3Vector(RealArray)' */ @Test public void testPoint3VectorRealArray() { Point3Vector p3v = new Point3Vector(new RealArray(new double[] { 11., 12., 13., 21., 22., 23., 31., 32., 33., 41., 42., 43., })); Assert.assertEquals("p3v", 4, p3v.size()); } /** * Test method for * 'org.xmlcml.euclid.Point3Vector.Point3Vector(Point3Vector)' */ @Test public void testPoint3VectorPoint3Vector() { Point3Vector p = new Point3Vector(p1); Assert.assertTrue("copy", p.isEqualTo(p1)); } /** * Test method for 'org.xmlcml.euclid.Point3Vector.size()' */ @Test public void testSize() { Assert.assertEquals("size", 4, p1.size()); } /** * Test method for 'org.xmlcml.euclid.Point3Vector.add(Point3)' */ @Test public void testAdd() { Point3 p = new Point3(10., 11., 12.); Point3Test.assertEquals("add", new double[] { 14., 24., 34. }, p1 .get(3), EPS); Assert.assertEquals("add", 4, p1.size()); p1.add(p); Assert.assertEquals("add", 5, p1.size()); Point3Test.assertEquals("add", p, p1.get(4), EPS); } /** * Test method for 'org.xmlcml.euclid.Point3Vector.setElementAt(Point3, * int)' */ @Test public void testSetElementAtPoint3Int() { Point3 p = new Point3(51., 52., 53.); p1.setElementAt(p, 2); Point3VectorTest.assertEquals("set", new double[] { 11., 21., 31., 12., 22., 32., 51., 52., 53., 14., 24., 34., }, p1, EPS); } /** * Test method for 'org.xmlcml.euclid.Point3Vector.elementAt(int)' */ @Test public void testElementAt() { Point3 p = p1.elementAt(2); Point3Test.assertEquals("get", new double[] { 13., 23., 33. }, p, EPS); } /** * Test method for 'org.xmlcml.euclid.Point3Vector.get(int)' */ @Test public void testGet() { Point3 p = p1.get(2); Point3Test.assertEquals("get", new double[] { 13., 23., 33. }, p, EPS); } /** * Test method for 'org.xmlcml.euclid.Point3Vector.addElement(Point3)' */ @Test public void testAddElement() { Point3 p = new Point3(51., 52., 53.); p1.addElement(p); Point3VectorTest.assertEquals("set", new double[] { 11., 21., 31., 12., 22., 32., 13., 23., 33., 14., 24., 34., 51., 52., 53., }, p1, EPS); } /** * Test method for 'org.xmlcml.euclid.Point3Vector.setElementAt(Vector3, * int)' */ @Test public void testSetElementAtVector3Int() { Vector3 p = new Vector3(51., 52., 53.); p1.setElementAt(p, 2); Point3VectorTest.assertEquals("set", new double[] { 11., 21., 31., 12., 22., 32., 51., 52., 53., 14., 24., 34., }, p1, EPS); } /** * Test method for 'org.xmlcml.euclid.Point3Vector.getRange(Axis3)' */ @Test public void testGetRange() { RealRange r = p1.getRange(Axis3.X); Assert.assertEquals("range", 11., r.getMin(), EPS); Assert.assertEquals("range", 14., r.getMax(), EPS); r = p1.getRange(Axis3.Y); Assert.assertEquals("range", 21., r.getMin(), EPS); Assert.assertEquals("range", 24., r.getMax(), EPS); r = p1.getRange(Axis3.Z); Assert.assertEquals("range", 31., r.getMin(), EPS); Assert.assertEquals("range", 34., r.getMax(), EPS); Point3 p = new Point3(51., 52., 53.); p1.addElement(p); r = p1.getRange(Axis3.X); Assert.assertEquals("range", 11., r.getMin(), EPS); Assert.assertEquals("range", 51., r.getMax(), EPS); r = p1.getRange(Axis3.Y); Assert.assertEquals("range", 21., r.getMin(), EPS); Assert.assertEquals("range", 52., r.getMax(), EPS); r = p1.getRange(Axis3.Z); Assert.assertEquals("range", 31., r.getMin(), EPS); Assert.assertEquals("range", 53., r.getMax(), EPS); } /** * Test method for 'org.xmlcml.euclid.Point3Vector.getRange3()' */ @Test public void testGetRange3() { Real3Range rr = p1.getRange3(); RealRange r = rr.getXRange(); Assert.assertEquals("range", 11., r.getMin(), EPS); Assert.assertEquals("range", 14., r.getMax(), EPS); r = rr.getYRange(); Assert.assertEquals("range", 21., r.getMin(), EPS); Assert.assertEquals("range", 24., r.getMax(), EPS); r = rr.getZRange(); Assert.assertEquals("range", 31., r.getMin(), EPS); Assert.assertEquals("range", 34., r.getMax(), EPS); } /** * Test method for * 'org.xmlcml.euclid.Point3Vector.getSigmaDeltaSquared(Point3Vector)' */ @Test public void testGetSigmaDeltaSquared() { Point3Vector p = new Point3Vector(p1); double d = p1.getSigmaDeltaSquared(p); Assert.assertEquals("sigma", 0.0, d, EPS); for (Point3 pp : p.getPoint3List()) { pp.plusEquals(new Vector3(0.1, 0.2, 0.3)); } d = p1.getSigmaDeltaSquared(p); Assert.assertEquals("sigma", 0.56, d, EPS); } /** * Test method for 'org.xmlcml.euclid.Point3Vector.subArray(IntSet)' */ @Test public void testSubArray() { Point3Vector sub = p1.subArray(new IntSet(new int[] { 3, 1, 2 })); Point3VectorTest.assertEquals("set", new double[] { 14.0, 24.0, 34.0, 12.0, 22.0, 32.0, 13.0, 23.0, 33.0 }, sub, EPS); } /** * Test method for 'org.xmlcml.euclid.Point3Vector.plus(Point3Vector)' */ @Test public void testPlusPoint3Vector() { Point3Vector p = new Point3Vector(new double[] { 61., 62., 63., 71., 72., 73. }); try { p1.plus(p); Assert.fail("should always throw " + "incompatible sizes"); } catch (EuclidRuntimeException e) { Assert.assertEquals("plus", "incompatible Point3Vector sizes: 4/2", e.getMessage()); } p = new Point3Vector(new double[] { 61., 62., 63., 71., 72., 73., 81., 82., 83., 91., 92., 93. }); p1 = p1.plus(p); Point3VectorTest.assertEquals("plus", new double[] { 72.0, 83.0, 94.0, 83.0, 94.0, 105.0, 94.0, 105.0, 116.0, 105.0, 116.0, 127.0 }, p1, EPS); } /** * Test method for 'org.xmlcml.euclid.Point3Vector.subtract(Point3Vector)' */ @Test public void testSubtractPoint3Vector() { Point3Vector p = new Point3Vector(new double[] { 61., 62., 63., 71., 72., 73. }); try { p1.subtract(p); Assert.fail("should always throw " + "incompatible sizes"); } catch (EuclidRuntimeException e) { Assert.assertEquals("plus", "incompatible Point3Vector sizes: 4/2", e.getMessage()); } p = new Point3Vector(new double[] { 61., 62., 63., 71., 72., 73., 81., 82., 83., 91., 92., 93. }); p1 = p.subtract(p1); Point3VectorTest .assertEquals("plus", new double[] { 50.0, 41.0, 32.0, 59.0, 50.0, 41.0, 68.0, 59.0, 50.0, 77.0, 68.0, 59.0 }, p1, EPS); } /** * Test method for 'org.xmlcml.euclid.Point3Vector.getLine(int, int)' */ @Test public void testGetLine() { Line3 l = p1.getLine(1, 2); Vector3Test.assertEquals("line", new double[] { 0.5773502691896258, 0.5773502691896258, 0.5773502691896258 }, l.getVector(), EPS); Point3Test.assertEquals("line", new double[] { 12.0, 22.0, 32.0 }, l .getPoint(), EPS); } /** * Test method for 'org.xmlcml.euclid.Point3Vector.getCentroid()' */ @Test public void testGetCentroid() { Point3 p = p1.getCentroid(); Point3Test.assertEquals("centroid", new double[] { 12.5, 22.5, 32.5 }, p, EPS); } /** * Test method for 'org.xmlcml.euclid.Point3Vector.plus(Vector3)' */ @Test public void testPlusVector3() { Point3Vector p = p1.plus(new Vector3(10., 20., 30.)); Point3VectorTest.assertEquals("plus vector", new double[] { 21.0, 41.0, 61.0, 22.0, 42.0, 62.0, 23.0, 43.0, 63.0, 24.0, 44.0, 64.0 }, p, EPS); } /** * Test method for 'org.xmlcml.euclid.Point3Vector.subtract(Vector3)' */ @Test public void testSubtractVector3() { Point3Vector p = p1.subtract(new Vector3(10., 20., 30.)); Point3VectorTest .assertEquals("subtract vector", new double[] { 1.0, 1.0, 1.0, 2.0, 2.0, 2.0, 3.0, 3.0, 3.0, 4.0, 4.0, 4.0 }, p, EPS); } /** * Test method for 'org.xmlcml.euclid.Point3Vector.moveToCentroid()' */ @Test public void testMoveToCentroid() { p1.moveToCentroid(); Point3VectorTest.assertEquals("move to centroid", new double[] { -1.5, -1.5, -1.5, -0.5, -0.5, -0.5, 0.5, 0.5, 0.5, 1.5, 1.5, 1.5 }, p1, EPS); } /** * Test method for 'org.xmlcml.euclid.Point3Vector.inertialTensor()' */ @Test public void testInertialTensor() { Point3Vector p = new Point3Vector(new double[] { 1., 2., 3., 2., 4., 6., 3., 6., 9., 4., 1., 0., 3., 6., 1. }); RealMatrix m = p.calculateNonMassWeightedInertialTensorOld(); RealMatrixTest.assertEquals("move to centroid", 3, 3, new double[] { 5.2, 0.6, -4.4, 0.6, 20.8, 17.8, -4.4, 17.8, 54.8 }, m, EPS); } /** * Test method for 'org.xmlcml.euclid.Point3Vector.transform(Transform3)' */ @Test public void testTransformTransform3() { Transform3 t = new Transform3("y, -x, z"); p1.transform(t); Point3VectorTest.assertEquals("transform", new double[] { 21.0, -11.0, 31.0, 22.0, -12.0, 32.0, 23.0, -13.0, 33.0, 24.0, -14.0, 34.0 }, p1, EPS); } /** * Test method for 'org.xmlcml.euclid.Point3Vector.transform(Transform3, * IntSet)' */ @Test public void testTransformTransform3IntSet() { Transform3 t = new Transform3("y, -x, z"); p1.transform(t, new IntSet(new int[] { 3, 1, 2 })); Point3VectorTest.assertEquals("transform", new double[] { 11.0, 21.0, 31.0, 22.0, -12.0, 32.0, 23.0, -13.0, 33.0, 24.0, -14.0, 34.0 }, p1, EPS); } /** * Test method for 'org.xmlcml.euclid.Point3Vector.distance(int, int)' */ @Test public void testDistanceIntInt() { double d = p1.distance(1, 3); Assert.assertEquals("distance", 3.464101, d, 0.00001); } /** * Test method for 'org.xmlcml.euclid.Point3Vector.distance(IntSet)' */ @Test public void testDistanceIntSet() { double d = 0; try { d = p1.distance(new IntSet(new int[] { 3, 1, 2 })); } catch (EuclidRuntimeException e) { Assert.assertEquals("distance", "int set must have exactly 2 points", e.getMessage()); } d = p1.distance(new IntSet(new int[] { 3, 1 })); Assert.assertEquals("distance", 3.464101, d, 0.00001); } /** * Test method for 'org.xmlcml.euclid.Point3Vector.angle(int, int, int)' */ @Test public void testAngleIntIntInt() { Angle a = p2.angle(1, 2, 3); Assert.assertEquals("angle", Math.PI / 2., a.getRadian(), EPS); a = p2.angle(3, 1, 2); Assert.assertEquals("angle", Math.PI / 4., a.getRadian(), EPS); } /** * Test method for 'org.xmlcml.euclid.Point3Vector.angle(IntSet)' */ @Test public void testAngleIntSet() { Angle a = p2.angle(new IntSet(new int[] { 1, 2, 3 })); Assert.assertEquals("angle", Math.PI / 2., a.getRadian(), EPS); a = p2.angle(new IntSet(new int[] { 2, 0, 1 })); Assert.assertEquals("angle", Math.PI / 4., a.getRadian(), EPS); } /** * Test method for 'org.xmlcml.euclid.Point3Vector.torsion(int, int, int, * int)' */ @Test public void testTorsionIntIntIntInt() { Angle t = p2.torsion(0, 1, 2, 3); Assert.assertEquals("torsion", -Math.PI / 2., t.getRadian(), EPS); } /** * Test method for 'org.xmlcml.euclid.Point3Vector.torsion(IntSet)' */ @Test public void testTorsionIntSet() { Angle t = p2.torsion(new IntSet(new int[] { 0, 1, 2, 3 })); Assert.assertEquals("torsion", -Math.PI / 2., t.getRadian(), EPS); } /** * Test method for 'org.xmlcml.euclid.Point3Vector.getDistanceMatrix()' */ @Test public void testGetDistanceMatrix() { RealSquareMatrix rsm = p2.getDistanceMatrix(); RealSquareMatrixTest.assertEquals("distance matrix", 4, new double[] { 0., 1., s2, s3, 1., 0., 1., s2, s2, 1., 0., 1., s3, s2, 1., 0. }, rsm, EPS); } /** * Test method for * 'org.xmlcml.euclid.Point3Vector.deviationsFromPlane(Plane3)' */ @Test public void testDeviationsFromPlane() { Plane3 pl = new Plane3(1., 0., 0., 0.5); RealArray ra = p2.deviationsFromPlane(pl); RealArrayTest.assertEquals("deviations", new double[] { 0.5, -0.5, -0.5, -0.5 }, ra, EPS); } /** * Test method for 'org.xmlcml.euclid.Point3Vector.getPoint3(int)' */ @Test public void testGetPoint3() { Point3 p = p1.getPoint3(1); Point3Test.assertEquals("get point", new double[] { 12., 22., 32. }, p, EPS); } /** * Test method for 'org.xmlcml.euclid.Point3Vector.getXYZ()' */ @Test public void testGetXYZ() { RealArray ra = p1.getXYZ(); RealArrayTest.assertEquals("get point", new double[] { 11.0, 21.0, 31.0, 12.0, 22.0, 32.0, 13.0, 23.0, 33.0, 14.0, 24.0, 34.0 }, ra, EPS); } /** * Test method for 'org.xmlcml.euclid.Point3Vector.getCoordinate(int, * Axis3)' */ @Test public void testGetCoordinateIntAxis3() { double d = p1.getCoordinate(3, Axis3.Y); Assert.assertEquals("get coord", 24., d, EPS); } /** * Test method for 'org.xmlcml.euclid.Point3Vector.getXYZ(Axis3)' */ @Test public void testGetXYZAxis3() { RealArray ra = p1.getXYZ(Axis3.Y); RealArrayTest.assertEquals("get XYZ", new double[] { 21., 22., 23., 24. }, ra, EPS); } /** * Test method for 'org.xmlcml.euclid.Point3Vector.rms(Point3Vector)' */ @Test public void testRms() { p1.moveToCentroid(); p2.moveToCentroid(); double d = p1.rms(p2); Assert.assertEquals("rms", 0.9185586535436918, d, EPS); } /** * Test method for * 'org.xmlcml.euclid.Point3Vector.getFurthestPointFrom(Point3)' */ @Test public void testGetFurthestPointFrom() { int idx = p1.getFurthestPointFrom(new Point3(0., 0., 0.)); Assert.assertEquals("furthest point", 3, idx); } /** * Test method for * 'org.xmlcml.euclid.Point3Vector.getPointMakingSmallestAngle(Point3, * Point3)' */ @Test public void testGetPointMakingSmallestAngle() { int idx = p1.getPointMakingSmallestAngle(new Point3(0., 0., 0.), new Point3(20., 15., 10.)); Assert.assertEquals("smallest angle point", 3, idx); } /** * Test method for * 'org.xmlcml.euclid.Point3Vector.alignUsing3Points(Point3Vector)' */ @Test public void testAlignUsing3Points() { p1.add(new Point3(20., 10., 0.)); p2.add(new Point3(5., 10., 5.)); Transform3 t = p1.alignUsing3Points(p2); Transform3Test.assertEquals("align", new double[] { 0.11432809806666633, 0.8588003169190181, -0.4993907304428592, 0.0, 0.6186208633307761, -0.45487483749749846, -0.6406224392444506, 0.0, -0.7773270312065208, -0.2356923797483021, -0.5832767685106605, 0.0, 0.0, 0.0, 0.0, 1.0 }, t, EPS); } /** * Test method for 'org.xmlcml.euclid.Point3Vector.get3SeparatedPoints()' */ @Test public void testGet3SeparatedPoints() { p1.add(new Point3(20., 10., 0.)); int[] idx = p1.get3SeparatedPoints(); String s = Int.testEquals((new int[] { 4, 3, 0 }), idx); if (s != null) { Assert.fail("separated points" + "; " + s); } } /** * Test method for * 'org.xmlcml.euclid.Point3Vector.align3PointVectors(Point3Vector)' */ @Test public void testAlign3PointVectors() { Transform3 t = null; try { t = p1.align3PointVectors(p2); } catch (EuclidRuntimeException e) { Assert.assertEquals("align", "this requires 3 points", e .getMessage()); } Point3Vector pa = new Point3Vector(new double[] { 1., 0., 0., 0., 1., 0., 0., 0., 1. }); Point3Vector pb = new Point3Vector(new double[] { 0., 1., 0., 1., 0., 0., 0., 0., 1. }); t = pa.align3PointVectors(pb); Transform3Test.assertEquals("align", new double[] { 0.0, 0.0, -1.0, 0.0, -1.0, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0, 0.0, 0.0, 0.0, -1.0 }, t, EPS); } /** * Test method for 'org.xmlcml.euclid.Point3Vector.roughAlign(Point3Vector)' */ @Test public void testRoughAlign() { Transform3 t = null; Point3Vector pthis = new Point3Vector(new double[] { 1., -1., 0., 0., 1., -1., -1., 0., 1. }); Point3Vector pref = new Point3Vector(new double[] { 0., 1., -1., 1., -1., 0., -1., 0., 1. }); t = pthis.roughAlign(pref); pthis.transform(t); Point3VectorTest.assertEquals("transformed pthis", pref, pthis, 0.000001); pref = new Point3Vector(new double[] { 12., 0., 1., 11., 2., 0., 10., 1., 2. }); t = pthis.roughAlign(pref); pthis.transform(t); // LOG.debug("PA "+pthis+"\n"+t); RealArray.round(pthis.getArray(), 6); Point3VectorTest.assertEquals("transformed pthis", pref, pthis, 0.000001); } /** * Test method for 'org.xmlcml.euclid.Point3Vector.fitTo(Point3Vector)' */ @Test public void testFitTo() { Transform3 t = null; Point3Vector pa = new Point3Vector(new double[] { 1., 0., 0., 0., 1., 0., 0., 0., 1. }); Point3Vector pb = new Point3Vector(new double[] { 0., 1., 0., 0., 0., 1., 1., 0., 0. }); t = pa.fitTo(pb); pa.transform(t); double rms = pa.rms(pb); Assert.assertEquals("rms", 0.0, rms, 0.000000001); DoubleTestBase.assertEquals("align", new double[] { 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0 }, t .getMatrixAsArray(), EPS); pb = new Point3Vector(new double[] { 10., 1.1, 0., 10., 0., 0.9, 11.1, 0., 0. }); t = pa.fitTo(pb); pa.transform(t); rms = pa.rms(pb); Assert.assertEquals("rms", 0.03470386605101721, rms, 0.0001); } @Test public void calculateInertialTensor() { Point3Vector p3v = new Point3Vector( new double[] { 3., 0., 0., 0., 2., 0., 0., 0., 1., -3., 0., 0., 0., -2., 0., 0., 0., -1.} ); RealSquareMatrix rsm = p3v.calculateNonMassWeightedInertialTensor(); RealSquareMatrixTest.assertEquals("rsm", 3, new double[]{ 10.0, 0.0, 0.0, 0.0, 20.0, 0.0, 0.0, 0.0, 26.0, }, rsm, 0.000001); RealArray realArray = rsm.calculateEigenvalues(); RealArrayTest.assertEquals("eigval ", new double[]{26.0, 20.0, 10.0}, realArray, 0.000001); } @Test public void calculateRotationToInertialAxes() { Point3Vector p3v = new Point3Vector( new double[] { 3., 0., 0., 0., 2., 0., 0., 0., 1., -3., 0., 0., 0., -2., 0., 0., 0., -1.} ); // arbitrary transform Transform3 t = new Transform3(new Angle(0.1), new Angle(0.2), new Angle(0.3)); p3v.transform(t); RealSquareMatrix eigvec = p3v.calculateRotationToInertialAxes(); Transform3 tt = new Transform3(eigvec); p3v.transform(tt); Point3VectorTest.assertEquals("transform to axes ", new double[]{ 0.0, 0.0, 3.0, 0.0, 2.0, 0.0, -1.0, 0.0, 0.0, 0.0, 0.0, -3.0, 0.0, -2.0, 0.0, 1.0, 0.0, 0.0, }, p3v, 0.000001); } } wwmm-euclid-87e8f785a814/src/test/java/org/xmlcml/euclid/test/PolarTest.java0000644000000000000000000001465511607017524024733 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid.test; import static org.xmlcml.euclid.EC.EPS; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.xmlcml.euclid.Angle; import org.xmlcml.euclid.Complex; import org.xmlcml.euclid.Polar; import org.xmlcml.euclid.Real2; /** * test Polar. * * @author pmr * */ public class PolarTest { Polar p0; Polar p1; Polar p2; /** * setup. * * @throws Exception */ @Before public void setUp() throws Exception { p0 = new Polar(); p1 = new Polar(1, 2); p2 = new Polar(10, new Angle(Math.PI / 3)); } /** * Test method for 'org.xmlcml.euclid.Polar.Polar()' */ @Test public void testPolar() { Assert.assertEquals("polar", 0.0, p0.getTheta().getRadian(), EPS); Assert.assertEquals("polar", 0.0, p0.getR(), EPS); } /** * Test method for 'org.xmlcml.euclid.Polar.Polar(double, double)' */ @Test public void testPolarDoubleDouble() { Assert.assertEquals("polar", Math.atan(2. / 1.), p1.getTheta() .getRadian(), EPS); Assert.assertEquals("polar", Math.sqrt(5.), p1.getR(), EPS); Assert.assertEquals("polar", 1., p1.getX(), EPS); Assert.assertEquals("polar", 2., p1.getY(), EPS); } /** * Test method for 'org.xmlcml.euclid.Polar.Polar(double, Angle)' */ @Test public void testPolarDoubleAngle() { Assert.assertEquals("polar", Math.PI / 3., p2.getTheta().getRadian(), EPS); Assert.assertEquals("polar", 10., p2.getR(), EPS); } /** * Test method for 'org.xmlcml.euclid.Polar.Polar(Complex)' */ @Test public void testPolarComplex() { Polar c = new Polar(new Complex(1., 2.)); Assert.assertEquals("polar", Math.atan(2. / 1.), c.getTheta() .getRadian(), EPS); Assert.assertEquals("polar", Math.sqrt(5.), c.getR(), EPS); } /** * Test method for 'org.xmlcml.euclid.Polar.Polar(Polar)' */ @Test public void testPolarPolar() { Polar p = new Polar(p1); Assert.assertEquals("polar", Math.atan(2. / 1.), p.getTheta() .getRadian(), EPS); Assert.assertEquals("polar", Math.sqrt(5.), p.getR(), EPS); } /** * Test method for 'org.xmlcml.euclid.Polar.getR()' */ @Test public void testGetR() { Assert.assertEquals("polar", Math.sqrt(5.), p1.getR(), EPS); } /** * Test method for 'org.xmlcml.euclid.Polar.getTheta()' */ @Test public void testGetTheta() { Assert.assertEquals("polar", Math.atan(2. / 1.), p1.getTheta() .getRadian(), EPS); } /** * Test method for 'org.xmlcml.euclid.Polar.plus(Polar)' */ @Test public void testPlus() { Polar pa = new Polar(10., 20.); Assert.assertEquals("polar", 10., pa.getX(), EPS); Assert.assertEquals("polar", 20., pa.getY(), EPS); Polar pb = new Polar(30., 40.); Assert.assertEquals("polar", 30., pb.getX(), EPS); Assert.assertEquals("polar", 40., pb.getY(), EPS); Polar pc = pa.plus(pb); Assert.assertEquals("polar", 40., pc.getX(), EPS); Assert.assertEquals("polar", 60., pc.getY(), EPS); } /** * Test method for 'org.xmlcml.euclid.Polar.subtract(Polar)' */ @Test public void testSubtractPolar() { Polar pa = new Polar(10., 20.); Polar pb = new Polar(30., 50.); Polar pc = pa.subtract(pb); Assert.assertEquals("polar", -20., pc.getX(), EPS); Assert.assertEquals("polar", -30., pc.getY(), EPS); } /** * Test method for 'org.xmlcml.euclid.Polar.subtract()' */ @Test public void testSubtract() { Polar pa = new Polar(10., 20.); pa.subtract(); Assert.assertEquals("polar", -10., pa.getX(), EPS); Assert.assertEquals("polar", -20., pa.getY(), EPS); } /** * Test method for 'org.xmlcml.euclid.Polar.multiplyBy(Polar)' */ @Test public void testMultiplyByPolar() { Polar pa = new Polar(10., new Angle(Math.PI / 4.)); Polar pb = new Polar(20., new Angle(Math.PI / 3.)); Polar pc = pa.multiplyBy(pb); Assert.assertEquals("polar", 200., pc.getR(), 1.0E-08); Assert.assertEquals("polar", Math.PI / 4. + Math.PI / 3., pc.getTheta() .getRadian(), 1.0E-08); } /** * Test method for 'org.xmlcml.euclid.Polar.multiplyBy(double)' */ @Test public void testMultiplyByDouble() { Polar pa = new Polar(10., 20.); Polar pb = pa.multiplyBy(3.); Assert.assertEquals("polar", 30., pb.getX(), 1.0E-08); Assert.assertEquals("polar", 60., pb.getY(), 1.0E-08); } /** * Test method for 'org.xmlcml.euclid.Polar.divideBy(Polar)' */ @Test public void testDivideBy() { Polar pa = new Polar(10., new Angle(Math.PI / 4.)); Polar pb = new Polar(20., new Angle(Math.PI / 3.)); Polar pc = pa.divideBy(pb); Assert.assertEquals("polar", 0.5, pc.getR(), 1.0E-08); Assert.assertEquals("polar", Math.PI / 4. - Math.PI / 3., pc.getTheta() .getRadian(), 1.0E-08); } /** * Test method for 'org.xmlcml.euclid.Polar.isEqualTo(Polar)' */ @Test public void testIsEqualTo() { Assert.assertTrue("isEqualTo", p1.isEqualTo(p1)); Assert.assertFalse("isEqualTo", p1.isEqualTo(p2)); } /** * Test method for 'org.xmlcml.euclid.Polar.getX()' */ @Test public void testGetX() { Polar pb = new Polar(20., new Angle(Math.PI / 3.)); Assert.assertEquals("polar", 20 * Math.cos(Math.PI / 3.), pb.getX(), 1.0E-08); } /** * Test method for 'org.xmlcml.euclid.Polar.getY()' */ @Test public void testGetY() { Polar pb = new Polar(20., new Angle(Math.PI / 3.)); Assert.assertEquals("polar", 20 * Math.sin(Math.PI / 3.), pb.getY(), 1.0E-08); } /** * Test method for 'org.xmlcml.euclid.Polar.getXY()' */ @Test public void testGetXY() { Polar pb = new Polar(20., new Angle(Math.PI / 3.)); Real2 r = pb.getXY(); Assert.assertEquals("polar", 20 * Math.cos(Math.PI / 3.), r.getX(), 1.0E-08); Assert.assertEquals("polar", 20 * Math.sin(Math.PI / 3.), r.getY(), 1.0E-08); } } wwmm-euclid-87e8f785a814/src/test/java/org/xmlcml/euclid/test/Real2ArrayTest.java0000644000000000000000000000740211607017524025612 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid.test; import static org.xmlcml.euclid.EC.EPS; import static org.xmlcml.euclid.EC.S_PIPE; import static org.xmlcml.euclid.EC.S_SPACE; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.xmlcml.euclid.EC; import org.xmlcml.euclid.Real2; import org.xmlcml.euclid.Real2Array; import org.xmlcml.euclid.Real2Range; import org.xmlcml.euclid.RealArray; import org.xmlcml.euclid.RealRange; /** * test Real2Array * * @author pmr * */ public class Real2ArrayTest { Real2Array ra0; Real2Array ra1; /** * setup. * * @throws Exception */ @Before public void setUp() throws Exception { ra0 = new Real2Array(); ra1 = new Real2Array(new RealArray(new double[] { 1, 2, 3, 4, 5, 6 }), new RealArray(new double[] { 11, 12, 13, 14, 15, 16 })); } /** * Test method for 'org.xmlcml.euclid.Real2Array.Real2Array()' */ @Test public void testReal2Array() { Assert.assertEquals("empty", "()", ra0.toString()); } /** * Test method for 'org.xmlcml.euclid.Real2Array.getRange2()' */ @Test public void testGetRange2() { Real2Range real2Range = ra1.getRange2(); Assert.assertTrue("range2", real2Range.isEqualTo(new Real2Range( new RealRange(1, 6), new RealRange(11, 16)), 0.001)); } /** * Test method for 'org.xmlcml.euclid.Real2Array.Real2Array(RealArray, * RealArray)' */ @Test public void testReal2ArrayRealArrayRealArray() { Assert.assertEquals("realArrays", EC.S_LBRAK + "(1.0,11.0)" + "(2.0,12.0)" + "(3.0,13.0)" + "(4.0,14.0)" + "(5.0,15.0)" + "(6.0,16.0)" + EC.S_RBRAK, ra1.toString()); } /** * Test method for 'org.xmlcml.euclid.Real2Array.getXArray()' */ @Test public void testGetXArray() { RealArray xarr = ra1.getXArray(); Assert.assertTrue("getXArray", xarr.isEqualTo(new RealArray( new double[] { 1., 2., 3., 4., 5., 6. }))); } /** * Test method for 'org.xmlcml.euclid.Real2Array.getYArray()' */ @Test public void testGetYArray() { RealArray yarr = ra1.getYArray(); Assert.assertTrue("getYArray", yarr.isEqualTo(new RealArray( new double[] { 11., 12., 13., 14., 15., 16. }))); } /** * Test method for 'org.xmlcml.euclid.Real2Array.size()' */ @Test public void testSize() { Assert.assertEquals("size", 6, ra1.size()); } @Test public void testCreateFromPairs() { String s = "1,2 3,4 5,6 7,8"; Real2Array real2Array = Real2Array.createFromPairs(s, EC.S_COMMA+S_PIPE+S_SPACE); Assert.assertEquals("size", 4, real2Array.size()); RealArray xarr = real2Array.getXArray(); Assert.assertTrue("getXArray", xarr.isEqualTo(new RealArray( new double[] { 1., 3., 5., 7. }))); RealArray yarr = real2Array.getYArray(); Assert.assertTrue("getYArray", yarr.isEqualTo(new RealArray( new double[] { 2., 4., 6., 8. }))); } /** * Test method for 'org.xmlcml.euclid.Real2Array.elementAt(int)' */ @Test public void testElementAt() { Real2 real2 = ra1.elementAt(4); Assert.assertEquals("elementAt", 5., real2.getX(), EPS); Assert.assertEquals("elementAt", 15., real2.getY(), EPS); } } wwmm-euclid-87e8f785a814/src/test/java/org/xmlcml/euclid/test/Real2RangeTest.java0000644000000000000000000001455111607017524025573 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid.test; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.xmlcml.euclid.Real2; import org.xmlcml.euclid.Real2Range; import org.xmlcml.euclid.RealRange; /** * test Real2Range. * * @author pmr * */ public class Real2RangeTest { Real2Range i2r0; Real2Range i2r1; Real2Range i2r2; /** * setup. * * @throws Exception */ @Before public void setUp() throws Exception { i2r0 = new Real2Range(); i2r1 = new Real2Range(new RealRange(1.0, 2.0), new RealRange(1.0, 2.0)); i2r2 = new Real2Range(new RealRange(1.0, 2.0), new RealRange(3.0, 4.0)); } /** * Test method for 'org.xmlcml.euclid.Real2Range.Real2Range()' */ @Test public void testReal2Range() { Assert.assertEquals("empty", "(NULL,NULL)", i2r0.toString()); } /** * Test method for 'org.xmlcml.euclid.Real2Range.Real2Range(RealRange, * RealRange)' */ @Test public void testReal2RangeRealRangeRealRange() { Assert.assertEquals("real range", "((1.0,2.0),(3.0,4.0))", i2r2 .toString()); } /** * Test method for 'org.xmlcml.euclid.Real2Range.Real2Range(Real2Range)' */ @Test public void testReal2RangeReal2Range() { Real2Range ii = new Real2Range(i2r2); Assert.assertEquals("empty", "((1.0,2.0),(3.0,4.0))", ii.toString()); } /** * Test method for 'org.xmlcml.euclid.Real2Range.isValid()' */ @Test public void testIsValid() { Assert.assertTrue("valid", i2r2.isValid()); Assert.assertFalse("invalid", i2r0.isValid()); } /** * Test method for 'org.xmlcml.euclid.Real2Range.isEqualTo(Real2Range)' */ @Test public void testIsEqualTo() { Assert.assertTrue("isEqual", i2r2.isEqualTo(i2r2, 0.001)); Assert.assertFalse("isEqual", i2r2.isEqualTo(i2r1, 0.001)); Assert.assertFalse("isEqual", i2r0.isEqualTo(i2r0, 0.001)); } /** * Test method for 'org.xmlcml.euclid.Real2Range.plus(Real2Range)' */ @Test public void testPlus() { Real2Range ix = new Real2Range(new RealRange(1.0, 4.0), new RealRange( 11.0, 14.0)); Real2Range iy = new Real2Range(new RealRange(2.0, 5.0), new RealRange( 12.0, 15.0)); Real2Range ii = ix.plus(iy); Assert.assertEquals("plus", "((1.0,5.0),(11.0,15.0))", ii.toString()); iy = new Real2Range(new RealRange(2.0, 3.0), new RealRange(12.0, 13.0)); ii = ix.plus(iy); Assert.assertEquals("plus", "((1.0,4.0),(11.0,14.0))", ii.toString()); iy = new Real2Range(new RealRange(0.0, 8.0), new RealRange(10.0, 18.0)); ii = ix.plus(iy); Assert.assertEquals("plus", "((0.0,8.0),(10.0,18.0))", ii.toString()); } /** * Test method for * 'org.xmlcml.euclid.Real2Range.doubleersectionWith(Real2Range)' */ @Test public void testIntersectionWith() { Real2Range ix = new Real2Range(new RealRange(1.0, 4.0), new RealRange( 11.0, 14.0)); Real2Range iy = new Real2Range(new RealRange(2.0, 5.0), new RealRange( 12.0, 15.0)); Real2Range ii = ix.intersectionWith(iy); Assert.assertEquals("plus", "((2.0,4.0),(12.0,14.0))", ii.toString()); iy = new Real2Range(new RealRange(2.0, 3.0), new RealRange(12.0, 13.0)); ii = ix.intersectionWith(iy); Assert.assertEquals("plus", "((2.0,3.0),(12.0,13.0))", ii.toString()); iy = new Real2Range(new RealRange(0.0, 8.0), new RealRange(10.0, 18.0)); ii = ix.intersectionWith(iy); Assert.assertEquals("plus", "((1.0,4.0),(11.0,14.0))", ii.toString()); } /** * Test method for 'org.xmlcml.euclid.Real2Range.getXRange()' */ @Test public void testGetXRange() { Assert.assertNull("getXRange", i2r0.getXRange()); Assert.assertEquals("getXRange", "(1.0,2.0)", i2r2.getXRange() .toString()); } /** * Test method for 'org.xmlcml.euclid.Real2Range.getYRange()' */ @Test public void testGetYRange() { Assert.assertNull("getXRange", i2r0.getYRange()); Assert.assertEquals("getXRange", "(3.0,4.0)", i2r2.getYRange() .toString()); } /** * Test method for 'org.xmlcml.euclid.Real2Range.includes(Real2)' */ @Test public void testIncludesReal2() { Real2Range ix = new Real2Range(new RealRange(1.0, 4.0), new RealRange( 11.0, 14.0)); Assert.assertTrue("include", ix.includes(new Real2(2.0, 12.0))); Assert.assertTrue("include", ix.includes(new Real2(1.0, 11.0))); Assert.assertTrue("include", ix.includes(new Real2(4.0, 14.0))); Assert.assertFalse("include", ix.includes(new Real2(1.0, 15.0))); } /** * Test method for 'org.xmlcml.euclid.Real2Range.includes(Real2Range)' */ @Test public void testIncludesReal2Range() { Real2Range ix = new Real2Range(new RealRange(1.0, 4.0), new RealRange( 11.0, 14.0)); Assert.assertTrue("include", ix.includes(new Real2Range(new RealRange( 2.0, 3.0), new RealRange(12.0, 13.0)))); Assert.assertTrue("include", ix.includes(new Real2Range(new RealRange( 1.0, 4.0), new RealRange(11.0, 14.0)))); Assert.assertFalse("include", ix.includes(new Real2Range(new RealRange( 0.0, 4.0), new RealRange(10.0, 14.0)))); Assert.assertFalse("include", ix.includes(new Real2Range(new RealRange( 2.0, 5.0), new RealRange(12.0, 15.0)))); } /** * Test method for 'org.xmlcml.euclid.Real2Range.add(Real2)' */ @Test public void testAdd() { Real2Range ii = new Real2Range(new RealRange(1.0, 4.0), new RealRange( 11.0, 14.0)); Assert.assertEquals("plus", "((1.0,4.0),(11.0,14.0))", ii.toString()); Real2 i2 = new Real2(2.0, 12.0); ii.add(i2); Assert.assertEquals("plus", "((1.0,4.0),(11.0,14.0))", ii.toString()); i2 = new Real2(0.0, 15.0); ii.add(i2); Assert.assertEquals("plus", "((0.0,4.0),(11.0,15.0))", ii.toString()); i2 = new Real2(8.0, 7.0); ii.add(i2); Assert.assertEquals("plus", "((0.0,8.0),(7.0,15.0))", ii.toString()); } } wwmm-euclid-87e8f785a814/src/test/java/org/xmlcml/euclid/test/Real2Test.java0000644000000000000000000002766411607017524024627 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid.test; import static org.xmlcml.euclid.EC.EPS; import static org.xmlcml.euclid.EC.S_RBRAK; import java.util.ArrayList; import java.util.List; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.xmlcml.euclid.Angle; import org.xmlcml.euclid.Real2; import org.xmlcml.euclid.RealMatrix; import org.xmlcml.euclid.Transform2; /** * tests real2 * * @author pmr * */ public class Real2Test { Real2 r0; Real2 r11; Real2 r12; List real2List; /** * setup. * * @throws Exception */ @Before public void setUp() throws Exception { r0 = new Real2(); r11 = new Real2(1.0, 1.0); r12 = new Real2(1.0, 2.0); } /** * equality test. true if both args not null and equal within epsilon * * @param msg * message * @param test * @param expected * @param epsilon */ public static void assertEquals(String msg, Real2 test, Real2 expected, double epsilon) { Assert.assertNotNull("test should not be null (" + msg + S_RBRAK, test); Assert.assertNotNull("expected should not be null (" + msg + S_RBRAK, expected); DoubleTestBase.assertEquals(msg, test.getXY(), expected.getXY(), epsilon); } /** * equality test. true if both args not null and equal within epsilon * * @param msg * message * @param test * array must be of length 2 * @param expected * @param epsilon */ public static void assertEquals(String msg, double[] test, Real2 expected, double epsilon) { Assert.assertNotNull("test should not be null (" + msg + S_RBRAK, test); Assert.assertEquals("must be of length 2", 2, test.length); Assert.assertNotNull("ref should not be null (" + msg + S_RBRAK, expected); DoubleTestBase.assertEquals(msg, test, expected.getXY(), epsilon); } /** * Test method for 'org.xmlcml.euclid.Real2.Real2()' */ @Test public void testReal2() { Assert.assertEquals("double2", "(0.0,0.0)", r0.toString()); } /** * Test method for 'org.xmlcml.euclid.Real2.Real2(double, double)' */ @Test public void testReal2RealReal() { Assert.assertEquals("double2", "(1.0,2.0)", r12.toString()); } /** * Test method for 'org.xmlcml.euclid.Real2.Real2(Real2)' */ @Test public void testReal2Real2() { Real2 ii = new Real2(r12); Assert.assertEquals("double2", "(1.0,2.0)", ii.toString()); } /** * Test method for 'org.xmlcml.euclid.Real2.swap()' */ @Test public void testSwap() { r12.swap(); Assert.assertEquals("double2", "(2.0,1.0)", r12.toString()); } /** * Test method for 'org.xmlcml.euclid.Real2.sortAscending()' */ @Test public void testSortAscending() { r12.sortAscending(); Assert.assertEquals("double2", "(1.0,2.0)", r12.toString()); } /** * Test method for 'org.xmlcml.euclid.Real2.sortDescending()' */ @Test public void testSortDescending() { r12.sortDescending(); Assert.assertEquals("double2", "(2.0,1.0)", r12.toString()); } /** * Test method for 'org.xmlcml.euclid.Real2.clear()' */ @Test public void testClear() { r12.clear(); Assert.assertEquals("double2", "(0.0,0.0)", r12.toString()); } /** * Test method for 'org.xmlcml.euclid.Real2.setX(double)' */ @Test public void testSetX() { r12.setX(3); Assert.assertEquals("double2", "(3.0,2.0)", r12.toString()); } /** * Test method for 'org.xmlcml.euclid.Real2.setY(double)' */ @Test public void testSetY() { r12.setY(3); Assert.assertEquals("double2", "(1.0,3.0)", r12.toString()); } // /** // * Test method for 'org.xmlcml.euclid.Real2.isEqualTo(Real2)' // */ // @Test // public void testIsEqualTo() { // Assert.assertTrue("equals", r12.isEqualTo(r12)); // Assert.assertFalse("equals", r11.isEqualTo(r12)); // } /** * Test method for 'org.xmlcml.euclid.Real2.plus(Real2)' */ @Test public void testPlus() { Real2 ii = r12.plus(r11); Assert.assertEquals("plus", "(2.0,3.0)", ii.toString()); } /** * Test method for 'org.xmlcml.euclid.Real2.subtract(Real2)' */ @Test public void testSubtract() { Real2 ii = r12.subtract(r11); Assert.assertEquals("subtract", "(0.0,1.0)", ii.toString()); } /** * Test method for 'org.xmlcml.euclid.Real2.negative()' */ @Test public void testNegative() { r12.negative(); Assert.assertEquals("negative", "(-1.0,-2.0)", r12.toString()); } /** * Test method for 'org.xmlcml.euclid.Real2.multiplyBy(double)' */ @Test public void testMultiplyBy() { Real2 ii = r12.multiplyBy(3); Assert.assertEquals("multiply", "(3.0,6.0)", ii.toString()); } /** * Test method for 'org.xmlcml.euclid.Real2.getX()' */ @Test public void testGetX() { Assert.assertEquals("getX", 1.0, r12.getX(), EPS); } /** * Test method for 'org.xmlcml.euclid.Real2.getY()' */ @Test public void testGetY() { Assert.assertEquals("getY", 2.0, r12.getY(), EPS); } /** * Test method for 'org.xmlcml.euclid.Real2.elementAt(double)' */ @Test public void testElementAt() { Assert.assertEquals("elementAt", 1.0, r12.elementAt(0), EPS); Assert.assertEquals("elementAt", 2.0, r12.elementAt(1), EPS); } /** * Test method for 'org.xmlcml.euclid.Real2.getMidPodouble(Real2)' */ @Test public void testGetMidPoint() { Real2 m = r12.getMidPoint(new Real2(3.0, 4.0)); Assert.assertEquals("mid point", "(2.0,3.0)", m.toString()); } /** * Test method for 'org.xmlcml.euclid.Real2.dotProduct(Real2)' */ @Test public void testDotProduct() { double i = r12.dotProduct(new Real2(3.0, 4.0)); Assert.assertEquals("dot", 11, i, EPS); } /** * Test method for 'org.xmlcml.euclid.Real2.toString()' */ @Test public void testToString() { Assert.assertEquals("toString", "(1.0,2.0)", r12.toString()); } /** * Test method for 'org.xmlcml.euclid.Real2.getLength()' */ @Test public void testGetLength() { Assert.assertEquals("length", Math.sqrt(5.), r12.getLength(), EPS); } /** * Test method for 'org.xmlcml.euclid.Real2.getDistance(Real2)' */ @Test public void testGetDistance() { Assert.assertEquals("distance", Math.sqrt(1.), r12.getDistance(r11), EPS); } /** * Test method for 'org.xmlcml.euclid.Real2.getSquaredDistance(Real2)' */ @Test public void testGetSquaredDistance() { Assert.assertEquals("squared distance", Math.sqrt(1.), r12 .getSquaredDistance(r11), EPS); } /** * Test method for 'org.xmlcml.euclid.Real2.getUnitVector()' */ @Test public void testGetUnitVector() { Real2 unit = r12.getUnitVector(); Assert.assertEquals("vector", Math.sqrt(1. / 5.), unit.getX(), EPS); Assert.assertEquals("vector", Math.sqrt(4. / 5.), unit.getY(), EPS); } /** * Test method for 'org.xmlcml.euclid.Real2.getAngle(Real2, Real2, Real2)' */ @Test public void testGetAngleReal2Real2Real2() { Real2 p1 = new Real2(1. + Math.cos(Math.PI / 3), 2. - Math .sin(Math.PI / 3)); Real2 p2 = new Real2(1., 2.); Real2 p3 = new Real2(1. + Math.cos(Math.PI / 3), 2. + Math .sin(Math.PI / 3)); Angle a = Real2.getAngle(p1, p2, p3); Assert.assertEquals("angle", 2. * Math.PI / 3, a.getAngle(), EPS); p1 = new Real2(0., 1.); p3 = new Real2(1., 0.); p2 = new Real2(0., 0.); a = Real2.getAngle(p1, p2, p3); Assert.assertEquals("angle", - Math.PI / 2., a.getAngle(), EPS); p1 = new Real2(0., 1.); p3 = new Real2(1., 1.); p2 = new Real2(0., 0.); a = Real2.getAngle(p1, p2, p3); Assert.assertEquals("angle", - Math.PI / 4., a.getAngle(), EPS); p1 = new Real2(0., 1.); p3 = new Real2(Math.sqrt(3.)/2., 0.5); p2 = new Real2(0., 0.); a = Real2.getAngle(p1, p2, p3); Assert.assertEquals("angle", - Math.PI / 3., a.getAngle(), EPS); p1 = new Real2(0., 1.); p3 = new Real2(0.5, Math.sqrt(3.)/2.); p2 = new Real2(0., 0.); a = Real2.getAngle(p1, p2, p3); Assert.assertEquals("angle", - Math.PI / 6., a.getAngle(), EPS); } /** * Test method for 'org.xmlcml.euclid.Real2.transformBy(Transform2)' */ @Test public void testTransformBy() { Transform2 t2 = new Transform2(new Angle(Math.PI / 2)); r12.transformBy(t2); Assert.assertEquals("transform", 2.0, r12.getX(), EPS); Assert.assertEquals("transform", -1.0, r12.getY(), EPS); } /** * Test method for 'org.xmlcml.euclid.Real2.getTransformed(Transform2)' */ @Test public void testGetTransformed() { Transform2 t2 = new Transform2(new Angle(Math.PI / 2)); Real2 r2 = r12.getTransformed(t2); Assert.assertEquals("transform", 2.0, r2.getX(), EPS); Assert.assertEquals("transform", -1.0, r2.getY(), EPS); } /** * Test method for 'org.xmlcml.euclid.Real2.addPolygonOnLine(Real2, Real2, * int, int, Real2)' */ // not worth developing // @Test // public void testAddPolygonOnLine() { // //T O D O // // } /** * Test method for 'org.xmlcml.euclid.Real2.getAngle()' */ @Test public void testGetAngle() { double d = r12.getAngle(); Assert.assertEquals("angle", Math.atan2(2., 1.), d, EPS); } /** * Test method for 'org.xmlcml.euclid.Real2.makePoint(double, double)' */ @Test public void testMakePoint() { Real2 real = r12.makePoint(10., Math.PI / 3); Assert.assertEquals("make point", 1. + 10 * Math.cos(Math.PI / 3), real .getX(), EPS); Assert.assertEquals("make point", 2. + 10 * Math.sin(Math.PI / 3), real .getY(), EPS); } /** * Test method for 'org.xmlcml.euclid.Real2.getCentroid(List)' */ @Test public void testGetCentroid() { real2List = new ArrayList(); real2List.add(new Real2(1.0, 2.0)); real2List.add(new Real2(-2.0, 1.0)); real2List.add(new Real2(4.0, 3.0)); Real2 c = Real2.getCentroid(real2List); Assert.assertEquals("centroid", 1., c.getX(), EPS); Assert.assertEquals("centroid", 2., c.getY(), EPS); } /** * Test method for * 'org.xmlcml.euclid.Real2.getSerialOfNearestPoint(List, Real2)' */ @Test public void testGetSerialOfNearestPoint() { real2List = new ArrayList(); real2List.add(new Real2(1.0, 2.0)); real2List.add(new Real2(-2.0, 1.0)); real2List.add(new Real2(4.0, 3.0)); Real2 p = new Real2(-1.6, 0.8); int i = Real2.getSerialOfNearestPoint(real2List, p); Assert.assertEquals("nearest", 1, i); // equidistant from 0 and 2, will choose the first p = new Real2(2.5, 2.5); i = Real2.getSerialOfNearestPoint(real2List, p); Assert.assertEquals("nearest", 0, i); // now choose the nearest p = new Real2(2.5, 2.50001); i = Real2.getSerialOfNearestPoint(real2List, p); Assert.assertEquals("nearest", 2, i); } /** * Test method for 'org.xmlcml.euclid.Real2.getDistanceMatrix(List, * List)' */ @Test public void testGetDistanceMatrix() { real2List = new ArrayList(); real2List.add(new Real2(1.0, 2.0)); real2List.add(new Real2(-2.0, 1.0)); real2List.add(new Real2(4.0, 4.0)); RealMatrix m = Real2.getDistanceMatrix(real2List, real2List); double[] d = new double[9]; d[0] = 0.0; d[1] = Math.sqrt(10.); d[2] = Math.sqrt(13.); d[3] = Math.sqrt(10.); d[4] = 0.0; d[5] = Math.sqrt(45.); d[6] = Math.sqrt(13.); d[7] = Math.sqrt(45.); d[8] = 0.0; RealMatrixTest.assertEquals("distance matrix", 3, 3, d, m, EPS); } } wwmm-euclid-87e8f785a814/src/test/java/org/xmlcml/euclid/test/Real2VectorTest.java0000644000000000000000000005151411607017524026001 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid.test; import static org.xmlcml.euclid.EuclidConstants.EPS; import java.util.ArrayList; import java.util.List; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.xmlcml.euclid.Angle; import org.xmlcml.euclid.EC; import org.xmlcml.euclid.EuclidRuntimeException; import org.xmlcml.euclid.IntSet; import org.xmlcml.euclid.Real2; import org.xmlcml.euclid.Real2Range; import org.xmlcml.euclid.Real2Vector; import org.xmlcml.euclid.RealArray; import org.xmlcml.euclid.RealMatrix; import org.xmlcml.euclid.RealRange; import org.xmlcml.euclid.Transform2; import org.xmlcml.euclid.Axis.Axis2; /** * tests real2Vector. * * @author pmr * */ public class Real2VectorTest { Real2Vector r0; Real2Vector r1; Real2Vector r2; /** * setup. * * @throws Exception */ @Before public void setUp() throws Exception { r0 = new Real2Vector(); r1 = new Real2Vector(new double[] { 1., 2., 3., 4., 5., 6., }); r2 = new Real2Vector(new double[] { 1., 2., 3., 4., 5., 6., 7., 8., 9., 10. }); } /** * equality test. true if both args not null and equal within epsilon * * @param msg * message * @param test * @param expected * @param epsilon */ public static void assertEquals(String msg, Real2Vector expected, Real2Vector test, double epsilon) { Assert.assertNotNull("test should not be null (" + msg + EC.S_RBRAK, test); Assert.assertNotNull("expected should not be null (" + msg + EC.S_RBRAK, expected); DoubleTestBase.assertEquals(msg, expected.getXY().getArray(), test .getXY().getArray(), epsilon); } /** * equality test. true if both args not null and equal within epsilon * * @param msg * message * @param test * array must be of length 3 * @param expected * @param epsilon */ public static void assertEquals(String msg, double[] test, Real2Vector expected, double epsilon) { Assert.assertNotNull("test should not be null (" + msg + EC.S_RBRAK, test); Assert.assertNotNull("expected should not be null (" + msg + EC.S_RBRAK, expected); Assert.assertEquals("must be of equal length ", test.length, expected .getXY().getArray().length); DoubleTestBase.assertEquals(msg, test, expected.getXY().getArray(), epsilon); } /** * Test method for 'org.xmlcml.euclid.Real2Vector.Real2Vector()' */ @Test public void testReal2Vector() { Assert.assertEquals("r2v", 0, r0.size()); } /** * Test method for 'org.xmlcml.euclid.Real2Vector.Real2Vector(double[])' */ @Test public void testReal2VectorDoubleArray() { Real2Vector r = new Real2Vector(new double[] { 1., 2., 3., 4., 5., 6. }); Assert.assertEquals("r2v", 3, r.size()); try { r = new Real2Vector(new double[] { 1., 2., 3., 4., 5. }); } catch (EuclidRuntimeException e) { Assert.assertEquals("r2v", "size must be multiple of 2", e .getMessage()); } } /** * Test method for 'org.xmlcml.euclid.Real2Vector.Real2Vector(int, double[], * double[])' */ @Test public void testReal2VectorIntDoubleArrayDoubleArray() { Real2Vector r = new Real2Vector(3, new double[] { 1., 2., 3. }, new double[] { 4., 5., 6. }); Assert.assertEquals("r2v", 3, r.size()); try { r = new Real2Vector(3, new double[] { 1., 2., 3. }, new double[] { 4., 5. }); } catch (EuclidRuntimeException e) { Assert.assertEquals("r2v", "array size required (3) found 2", e .getMessage()); } } /** * Test method for 'org.xmlcml.euclid.Real2Vector.Real2Vector(RealArray)' */ @Test public void testReal2VectorRealArray() { Real2Vector r = new Real2Vector(new RealArray(new double[] { 1., 2., 3., 4., 5., 6. })); Assert.assertEquals("r2v", 3, r.size()); try { r = new Real2Vector(new RealArray( new double[] { 1., 2., 3., 4., 5. })); } catch (EuclidRuntimeException e) { Assert.assertEquals("r2v", "size must be multiple of 2", e .getMessage()); } } /** * Test method for 'org.xmlcml.euclid.Real2Vector.Real2Vector(Real2Vector)' */ @Test public void testReal2VectorReal2Vector() { Real2Vector r = new Real2Vector(r1); Assert.assertEquals("r2v", 3, r.size()); } /** * Test method for 'org.xmlcml.euclid.Real2Vector.add(Real2)' */ @Test public void testAdd() { r1.add(new Real2(7., 8.)); Assert.assertEquals("add", 4, r1.size()); Assert.assertEquals("add", 7., r1.get(3).getX(),EPS); Assert.assertEquals("add", 8., r1.get(3).getY(),EPS); } /** * Test method for 'org.xmlcml.euclid.Real2Vector.set(int, Real2)' */ @Test public void testSet() { r1.set(1, new Real2(9., 8.)); Assert.assertEquals("set", 9., r1.get(1).getX(),EPS); Assert.assertEquals("set", 8., r1.get(1).getY(),EPS); Assert.assertEquals("add", 3, r1.size()); } /** * Test method for 'org.xmlcml.euclid.Real2Vector.getRange(Axis2)' */ @Test public void testGetRange() { RealRange r = r1.getRange(Axis2.X); Assert.assertEquals("range", 1., r.getMin(),EPS); Assert.assertEquals("range", 5., r.getMax(),EPS); r1.set(0, new Real2(-9., 8.)); r1.set(1, new Real2(9., 8.)); r = r1.getRange(Axis2.X); Assert.assertEquals("range", -9., r.getMin(),EPS); Assert.assertEquals("range", 9., r.getMax(),EPS); r = r1.getRange(Axis2.Y); Assert.assertEquals("range", 6., r.getMin(),EPS); Assert.assertEquals("range", 8., r.getMax(),EPS); r1.set(0, new Real2(-9., 8.)); r1.set(1, new Real2(9., 8.)); r = r1.getRange(Axis2.Y); Assert.assertEquals("range", 6., r.getMin(),EPS); Assert.assertEquals("range", 8., r.getMax(),EPS); } /** * Test method for 'org.xmlcml.euclid.Real2Vector.getRange2()' */ @Test public void testGetRange2() { Real2Range r2 = r1.getRange2(); RealRange xr = r2.getXRange(); RealRange yr = r2.getYRange(); Assert.assertEquals("range", 1., xr.getMin(),EPS); Assert.assertEquals("range", 5., xr.getMax(),EPS); Assert.assertEquals("range", 2., yr.getMin(),EPS); Assert.assertEquals("range", 6., yr.getMax(),EPS); r1.set(0, new Real2(-9., 8.)); r1.set(1, new Real2(9., 8.)); r2 = r1.getRange2(); xr = r2.getXRange(); yr = r2.getYRange(); Assert.assertEquals("range", -9., xr.getMin(),EPS); Assert.assertEquals("range", 9., xr.getMax(),EPS); Assert.assertEquals("range", 6., yr.getMin(),EPS); Assert.assertEquals("range", 8., yr.getMax(),EPS); } /** * Test method for 'org.xmlcml.euclid.Real2Vector.subArray(IntSet)' */ @Test public void testSubArray() { Real2Vector sub = r2.subArray(new IntSet(new int[] { 3, 1, 2 })); Real2VectorTest.assertEquals("sub", new double[] { 7., 8., 3., 4., 5., 6. }, sub, EPS); } /** * Test method for 'org.xmlcml.euclid.Real2Vector.subSet(Real2Range)' */ @Test public void testSubSet() { Real2Range rr = new Real2Range(new RealRange(2.5, 7.5), new RealRange( 2.5, 7.5)); IntSet is = null; is = r2.subSet(rr); IntSetTest.assertEquals("sub", new int[] { 1, 2 }, is); } /** * Test method for 'org.xmlcml.euclid.Real2Vector.getClosestPoint(Real2)' */ @Test public void testGetClosestPoint() { int ip = r2.getClosestPoint(new Real2(3.5, 6.7)); Assert.assertEquals("closest", 2, ip); } /** * Test method for 'org.xmlcml.euclid.Real2Vector.getPoint(Real2, double, * double)' */ @Test public void testGetPoint() { int ip = r2.getPoint(new Real2(4., 5.), 0.5, 0.5); Assert.assertEquals("closest", -1, ip); ip = r2.getPoint(new Real2(4., 5.), 2.0, 2.0); Assert.assertEquals("closest", 1, ip); } /** * Test method for 'org.xmlcml.euclid.Real2Vector.translateBy(Real2)' */ @Test public void testTranslateBy() { r2.translateBy(new Real2(2., 3.)); Real2VectorTest.assertEquals("translate", new double[] { 3., 5., 5., 7., 7., 9., 9., 11., 11., 13. }, r2, EPS); } /** * Test method for 'org.xmlcml.euclid.Real2Vector.plus(Real2)' */ @Test public void testPlus() { r2.plus(new Real2(2., 3.)); Real2VectorTest.assertEquals("plus", new double[] { 3., 5., 5., 7., 7., 9., 9., 11., 11., 13. }, r2, EPS); } /** * Test method for 'org.xmlcml.euclid.Real2Vector.subtract(Real2)' */ @Test public void testSubtract() { r2.subtract(new Real2(2., 3.)); Real2VectorTest.assertEquals("subtract", new double[] { -1., -1., 1., 1., 3., 3., 5., 5., 7., 7. }, r2, EPS); } /** * Test method for 'org.xmlcml.euclid.Real2Vector.multiplyBy(double)' */ @Test public void testMultiplyBy() { r2.multiplyBy(2.); Real2VectorTest.assertEquals("subtract", new double[] { 2., 4., 6., 8., 10., 12., 14., 16., 18., 20. }, r2, EPS); } /** * Test method for 'org.xmlcml.euclid.Real2Vector.distance(int, int)' */ @Test public void testDistanceIntInt() { double d = r2.distance(2, 3); Assert.assertEquals("distance", Math.sqrt(8.), d, EPS); } /** * Test method for 'org.xmlcml.euclid.Real2Vector.distance(IntSet)' */ @Test public void testDistanceIntSet() { double d = r2.distance(new IntSet(new int[] { 2, 3 })); Assert.assertEquals("distance", Math.sqrt(8.), d, EPS); } /** * Test method for 'org.xmlcml.euclid.Real2Vector.angle(int, int, int)' */ @Test public void testAngleIntIntInt() { Angle a = r2.angle(1, 2, 3); Assert.assertEquals("angle", -Math.PI, a.getRadian(), EPS); } /** * Test method for 'org.xmlcml.euclid.Real2Vector.angle(IntSet)' */ @Test public void testAngleIntSet() { Angle a = r2.angle(new IntSet(new int[] { 1, 2, 3 })); Assert.assertEquals("angle", -Math.PI, a.getRadian(), EPS); } /** * Test method for 'org.xmlcml.euclid.Real2Vector.getReal2(int)' */ @Test public void testGetReal2() { Real2 r = r2.getReal2(1); Assert.assertEquals("angle", 3., r.getX(), EPS); Assert.assertEquals("angle", 4., r.getY(), EPS); } /** * Test method for 'org.xmlcml.euclid.Real2Vector.getXY()' */ @Test public void testGetXY() { RealArray ra = r2.getXY(); RealArrayTest.assertEquals("getXY", new double[] { 1., 2., 3., 4., 5., 6., 7., 8., 9., 10. }, ra, EPS); } /** * Test method for 'org.xmlcml.euclid.Real2Vector.getCoordinate(int, Axis2)' */ @Test public void testGetCoordinate() { double d = r2.getCoordinate(2, Axis2.X); Assert.assertEquals("coord", 5., d, EPS); d = r2.getCoordinate(3, Axis2.Y); Assert.assertEquals("coord", 8., d, EPS); } /** * Test method for 'org.xmlcml.euclid.Real2Vector.getXorY(Axis2)' */ @Test public void testGetXorY() { RealArray ra = r2.getXorY(Axis2.X); RealArrayTest.assertEquals("Xarray", new double[] { 1., 3., 5., 7., 9. }, ra, EPS); ra = r2.getXorY(Axis2.Y); RealArrayTest.assertEquals("Yarray", new double[] { 2., 4., 6., 8., 10. }, ra, EPS); } /** * Test method for 'org.xmlcml.euclid.Real2Vector.swapXY()' */ @Test public void testSwapXY() { r2.swapXY(); Real2VectorTest.assertEquals("getXY", new double[] { 2., 1., 4., 3., 6., 5., 8., 7., 10., 9. }, r2, EPS); } /** * Test method for 'org.xmlcml.euclid.Real2Vector.sortAscending(Axis2)' */ @Test public void testSortAscending() { Real2Vector r2v = new Real2Vector(new double[] { 1., 3., 5., 2., 7., 1., 2., 6. }); r2v = r2v.sortAscending(Axis2.X); Real2VectorTest.assertEquals("sortAsc", new double[] { 1.0, 3.0, 2.0, 6.0, 5.0, 2.0, 7.0, 1.0 }, r2v, EPS); r2v = r2v.sortAscending(Axis2.Y); Real2VectorTest.assertEquals("sortAsc", new double[] { 7.0, 1.0, 5.0, 2.0, 1.0, 3.0, 2.0, 6.0 }, r2v, EPS); r2v = r2v.sortDescending(Axis2.X); Real2VectorTest.assertEquals("sortAsc", new double[] { 7.0, 1.0, 5.0, 2.0, 2.0, 6.0, 1.0, 3.0 }, r2v, EPS); r2v = r2v.sortDescending(Axis2.Y); Real2VectorTest.assertEquals("sortAsc", new double[] { 2.0, 6.0, 1.0, 3.0, 5.0, 2.0, 7.0, 1.0 }, r2v, EPS); } /** * Test method for 'org.xmlcml.euclid.Real2Vector.transformBy(Transform2)' */ @Test public void testTransformBy() { Transform2 t = new Transform2(new Angle(Math.PI / 2.)); r1.transformBy(t); Real2VectorTest.assertEquals("transform", new double[] { 2.0, -1.0, 4.0, -3.0, 6.0, -5.0 }, r1, EPS); } /** * Test method for * 'org.xmlcml.euclid.Real2Vector.getSquaredDifference(Real2Vector)' */ @Test public void testGetSquaredDifference() { Real2Vector r = new Real2Vector(new double[] { 1.1, 2.2, 3.3, 4.4, 5.5, 6.6 }); double d = r1.getSquaredDifference(r); Assert.assertEquals("squared difference", 0.91, d, EPS); } /** * Test method for * 'org.xmlcml.euclid.Real2Vector.getSquaredDistances(Real2Vector)' */ @Test public void testGetSquaredDistances() { Real2Vector r = new Real2Vector(new double[] { 1.1, 2.2, 3.3, 4.4, 5.5, 6.6 }); double[] d = r1.getSquaredDistances(r); DoubleTestBase.assertEquals("squared distances", new double[] { 0.05, 0.25, 0.61 }, d, EPS); } /** * Test method for * 'org.xmlcml.euclid.Real2Vector.rotateAboutCentroid(Angle)' */ @Test public void testRotateAboutCentroid() { Real2VectorTest.assertEquals("transform", new double[] { 1., 2., 3., 4., 5., 6., }, r1, EPS); r1.rotateAboutCentroid(new Angle(Math.PI / 4.)); Real2VectorTest.assertEquals("transform", new double[] { 3. - Math.sqrt(8.), 4.0, 3.0, 4.0, 3. + Math.sqrt(8.), 4.0 }, r1, EPS); } /** * Test method for 'org.xmlcml.euclid.Real2Vector.regularPolygon(int, * double)' */ @Test public void testRegularPolygon() { Real2Vector p = Real2Vector.regularPolygon(3, 1.0); Real2VectorTest.assertEquals("polygon", new double[] { 0.0, 1.0, 0.8660254037844387, -0.5, -0.8660254037844385, -0.5 }, p, EPS); } /** * Test method for 'org.xmlcml.euclid.Real2Vector.getCentroid()' */ @Test public void testGetCentroid() { Real2Vector r = new Real2Vector(new double[] { 1.1, 2.2, 3.3, 4.4, 5.5, 6.6 }); Real2 c = r.getCentroid(); Assert.assertEquals("centroid", 3.3, c.getX(), EPS); Assert.assertEquals("centroid", 4.4, c.getY(), EPS); } /** * Test method for * 'org.xmlcml.euclid.Real2Vector.getSerialOfNearestPoint(Real2)' */ @Test public void testGetSerialOfNearestPoint() { Real2Vector r = new Real2Vector(new double[] { 1.1, 2.2, 3.3, 4.4, 5.5, 6.6 }); int idx = r.getSerialOfNearestPoint(new Real2(3., 4.)); Assert.assertEquals("nearest point", 1, idx); } /** * Test method for * 'org.xmlcml.euclid.Real2Vector.getDistanceMatrix(List)' */ @Test public void testGetDistanceMatrix() { List pointList = new ArrayList(); pointList.add(new Real2(1.1, 2.2)); pointList.add(new Real2(3.3, 4.4)); RealMatrix rsm = r1.getDistanceMatrix(pointList); DoubleTestBase.assertEquals("distance matrix", new double[] { 0.22360679774997916, 3.3241540277189325, 2.6172504656604803, 0.5000000000000001, 5.445181356024793, 2.33452350598575 }, rsm .getMatrixAsArray(), EPS); } /** * Test method for * {@link org.xmlcml.euclid.Real2Vector#Real2Vector(java.util.List)}. */ @Test public final void testReal2VectorListOfReal2() { List lr2 = new ArrayList(); lr2.add(new Real2(1., 2.)); lr2.add(new Real2(3., 4.)); Real2Vector r2v = new Real2Vector(lr2); Real2VectorTest.assertEquals("copy", new Real2Vector(new double[] { 1., 2., 3., 4. }), r2v, EPS); } /** * Test method for {@link org.xmlcml.euclid.Real2Vector#get(int)}. */ @Test public final void testGet() { Real2Test.assertEquals("real list", new Real2(3., 4.), r2.get(1), EPS); } /** * Test method for {@link org.xmlcml.euclid.Real2Vector#size()}. */ @Test public final void testSize() { Assert.assertEquals("real list", 5, r2.size()); } /** * Test method for {@link org.xmlcml.euclid.Real2Vector#getReal2List()}. */ @Test public final void testGetReal2List() { List r2l = r2.getReal2List(); Assert.assertEquals("real list", 5, r2l.size()); } /** * Test method for * {@link org.xmlcml.euclid.Real2Vector#sortDescending(org.xmlcml.euclid.Axis.Axis2)} * . */ @Test public final void testSortDescending() { List lr = new ArrayList(); lr.add(new Real2(3., 5.)); lr.add(new Real2(1., 2.)); lr.add(new Real2(7., 1.)); lr.add(new Real2(5., 4.)); Real2Vector r2v = new Real2Vector(lr); r2v = r2v.sortDescending(Axis2.X); Real2VectorTest.assertEquals("sort", new double[] { 7.0, 1.0, 5.0, 4.0, 3.0, 5.0, 1.0, 2.0, }, r2v, EPS); r2v = r2v.sortDescending(Axis2.Y); Real2VectorTest.assertEquals("sort", new double[] { 3.0, 5.0, 5.0, 4.0, 1.0, 2.0, 7.0, 1.0, }, r2v, EPS); } /** * Test method for * {@link org.xmlcml.euclid.Real2Vector#regularPolygon(int, double)}. */ @Test public final void testRegularPolygonIntDouble() { Real2Vector v = Real2Vector.regularPolygon(4, 1.0); Real2VectorTest.assertEquals("polygon", new Real2Vector( new Real2Vector(new double[] { 0.0, 1.0, 1.0, 0.0, 0.0, -1.0, -1.0, 0.0 })), v, EPS); v = Real2Vector.regularPolygon(6, 1.0); } /** * Test method for * {@link org.xmlcml.euclid.Real2Vector#regularPolygon(int, double, double)} * . */ @Test public final void testRegularPolygonIntDoubleDouble() { Real2Vector v = Real2Vector.regularPolygon(4, 1, 0.1); Real2VectorTest.assertEquals("polygon", new Real2Vector( new Real2Vector(new double[] { 0.09983341664682815, 0.9950041652780258, 0.9950041652780257, -0.09983341664682818, -0.09983341664682811, -0.9950041652780258, -0.9950041652780258, 0.09983341664682761, })), v, EPS); } /** * Test method for * {@link org.xmlcml.euclid.Real2Vector#regularPolygon(int, org.xmlcml.euclid.Real2, org.xmlcml.euclid.Real2, boolean)} * . */ @Test public final void testRegularPolygonIntReal2Real2Boolean() { Real2Vector v = null; v = Real2Vector.regularPolygon(5, new Real2(0.0, 0.0), new Real2(1.0, 0.0), false); Real2VectorTest.assertEquals("polygon", new Real2Vector( new Real2Vector(new double[] { 0.0, 0.0, 1.0, 0.0, 1.3090169943749475, -0.9510565162951536, 0.5, -1.5388417685876266, -0.30901699437494745, -0.9510565162951539 })), v, EPS); v = Real2Vector.regularPolygon(4, new Real2(0.0, 0.0), new Real2(3.0, 5.0), false); Real2VectorTest.assertEquals("polygon", new Real2Vector( new Real2Vector(new double[] { 0.0, 0.0, 3.0, 5.0, 8.0, 2.0, 5.0, -3.0, })), v, EPS); v = Real2Vector.regularPolygon(4, new Real2(1.0, 2.0), new Real2(3.0, 5.0), false); Real2VectorTest.assertEquals("polygon", new Real2Vector( new Real2Vector(new double[] { 1.0, 2.0, 3.0, 5.0, 6.0, 3.0, 4.0, 0.0, })), v, EPS); v = Real2Vector.regularPolygon(4, new Real2(3.0, 5.0), new Real2(1.0, 2.0), false); Real2VectorTest.assertEquals("polygon", new Real2Vector( new Real2Vector(new double[] { 3.0, 5.0, 1.0, 2.0, -2.0, 4.0, 0.0, 7.0 })), v, EPS); v = Real2Vector.regularPolygon(4, new Real2(3.0, 5.0), new Real2(1.0, 2.0), true); Real2VectorTest.assertEquals("polygon", new Real2Vector( new Real2Vector(new double[] { 3.0, 5.0, 6.0, 3.0, 8.0, 6.0, 5.0, 8.0 })), v, EPS); } /** * */ @Test public final void testGetXArrayYArray() { Real2Vector r2v = new Real2Vector(); r2v.add(new Real2(1., 11.)); r2v.add(new Real2(2., 12.)); r2v.add(new Real2(3., 13.)); r2v.add(new Real2(4., 14.)); r2v.add(new Real2(5., 15.)); RealArray xx = r2v.getXArray(); RealArrayTest.assertEquals("x", new double[] { 1., 2., 3., 4., 5. }, xx, 0.00001); RealArray yy = r2v.getYArray(); RealArrayTest.assertEquals("y", new double[] { 11., 12., 13., 14., 15. }, yy, 0.00001); } /** * */ @Test public final void testIsInside() { Real2Vector r2v = new Real2Vector(); r2v.add(new Real2(0., 0.)); r2v.add(new Real2(0., 10.)); r2v.add(new Real2(10., 10.)); r2v.add(new Real2(10., 0.)); Real2 point = new Real2(5., 3.); // simple box Assert.assertTrue("inside", r2v.encloses(point)); // make concave r2v.add(new Real2(5., 5.)); Assert.assertFalse("inside", r2v.encloses(point)); // avoid point r2v.add(new Real2(6., 0.)); Assert.assertTrue("inside", r2v.encloses(point)); } } wwmm-euclid-87e8f785a814/src/test/java/org/xmlcml/euclid/test/Real3RangeTest.java0000644000000000000000000001275011607017524025573 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid.test; import static org.xmlcml.euclid.EC.EPS; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.xmlcml.euclid.Point3; import org.xmlcml.euclid.Real3Range; import org.xmlcml.euclid.RealRange; import org.xmlcml.euclid.Transform3; import org.xmlcml.euclid.Axis.Axis3; /** * test Real3Range. * * @author pmr * */ public class Real3RangeTest { Real3Range r0 = null; Real3Range r1 = null; /** * setup. * * @throws Exception */ @Before public void setUp() throws Exception { r0 = new Real3Range(); r1 = new Real3Range(new RealRange(1., 2.), new RealRange(3., 4.), new RealRange(5., 6.)); } /** * Test method for 'org.xmlcml.euclid.Real3Range.Real3Range()' */ @Test public void testReal3Range() { Assert.assertEquals("real3", "(NULL,NULL,NULL)", r0.toString()); } /** * Test method for 'org.xmlcml.euclid.Real3Range.Real3Range(RealRange, * RealRange, RealRange)' */ @Test public void testReal3RangeRealRangeRealRangeRealRange() { Assert.assertEquals("real3", "((1.0,2.0),(3.0,4.0),(5.0,6.0))", r1 .toString()); } /** * Test method for 'org.xmlcml.euclid.Real3Range.Real3Range(Real3Range)' */ @Test public void testReal3RangeReal3Range() { Real3Range rr = new Real3Range(r1); Assert.assertEquals("real3", "((1.0,2.0),(3.0,4.0),(5.0,6.0))", rr .toString()); } /** * test ranges for equality. * * @param msg * @param r3ref * @param r3 * @param epsilon */ public static void assertEquals(String msg, Real3Range r3ref, Real3Range r3, double epsilon) { RealRangeTest.assertEquals("xRange", r3.getXRange(), r3ref.getXRange(), epsilon); RealRangeTest.assertEquals("yRange", r3.getYRange(), r3ref.getYRange(), epsilon); RealRangeTest.assertEquals("zRange", r3.getZRange(), r3ref.getZRange(), epsilon); } /** * Test method for 'org.xmlcml.euclid.Real3Range.isEqualTo(Real3Range)' */ @Test public void testIsEqualTo() { Real3Range rr = new Real3Range(r1); Assert.assertTrue("real3", rr.isEqualTo(r1, 0.001)); } /** * Test method for 'org.xmlcml.euclid.Real3Range.plus(Real3Range)' */ @Test public void testPlus() { Real3Range r = new Real3Range(new RealRange(1., 3.), new RealRange(2., 7.), new RealRange(2., 3.)); Real3Range rr = r.plus(r1); Assert.assertEquals("real3", "((1.0,3.0),(2.0,7.0),(2.0,6.0))", rr .toString()); } /** * Test method for 'org.xmlcml.euclid.Real3Range.getXRange()' */ @Test public void testGetXYZRange() { RealRange x = r1.getXRange(); Assert.assertEquals("realx", "(1.0,2.0)", x.toString()); RealRange y = r1.getYRange(); Assert.assertEquals("realy", "(3.0,4.0)", y.toString()); RealRange z = r1.getZRange(); Assert.assertEquals("realz", "(5.0,6.0)", z.toString()); } /** * Test method for 'org.xmlcml.euclid.Real3Range.add(Axis3, double)' */ @Test public void testAddAxis3Double() { r1.add(Axis3.X, 10.); Assert.assertEquals("add", "((1.0,10.0),(3.0,4.0),(5.0,6.0))", r1 .toString()); r1.add(Axis3.X, -1.); Assert.assertEquals("add", "((-1.0,10.0),(3.0,4.0),(5.0,6.0))", r1 .toString()); } /** * Test method for 'org.xmlcml.euclid.Real3Range.includes(Point3)' */ @Test public void testIncludes() { Assert.assertTrue("includes", r1.includes(new Point3(1.1, 3.3, 5.5))); Assert.assertFalse("includes", r1.includes(new Point3(0.9, 3.3, 5.5))); } /** * Test method for 'org.xmlcml.euclid.Real3Range.add(Point3)' */ @Test public void testAddPoint3() { r1.add(new Point3(1.1, 1.2, 10.8)); Assert.assertEquals("add", "((1.0,2.0),(1.2,4.0),(5.0,10.8))", r1 .toString()); } /** * test get point with max x, y, z. */ @Test public void testGetMaxPoint3() { Point3 maxp = r1.getMaxPoint3(); Point3Test.assertEquals("max point", new Point3(2., 4., 6.), maxp, EPS); } /** * test get point with min x, y, z. */ @Test public void testGetMinPoint3() { Point3 minp = r1.getMinPoint3(); Point3Test.assertEquals("min point", new Point3(1., 3., 5.), minp, EPS); } /** * test transforms range. */ @Test public void testTransformEquals() { Transform3 tr = new Transform3("y, -z, -x"); r1.transformEquals(tr); Assert.assertEquals("transformed x range min", 3., r1.getXRange() .getMin(), EPS); Assert.assertEquals("transformed x range max", 4., r1.getXRange() .getMax(), EPS); Assert.assertEquals("transformed y range min", -6., r1.getYRange() .getMin(), EPS); Assert.assertEquals("transformed y range max", -5., r1.getYRange() .getMax(), EPS); Assert.assertEquals("transformed z range min", -2., r1.getZRange() .getMin(), EPS); Assert.assertEquals("transformed z range max", -1., r1.getZRange() .getMax(), EPS); } } wwmm-euclid-87e8f785a814/src/test/java/org/xmlcml/euclid/test/RealArrayTest.java0000644000000000000000000007065411607017524025541 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid.test; import static org.xmlcml.euclid.EuclidConstants.EPS; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.xmlcml.euclid.EuclidConstants; import org.xmlcml.euclid.EuclidRuntimeException; import org.xmlcml.euclid.IntArray; import org.xmlcml.euclid.IntSet; import org.xmlcml.euclid.RealArray; import org.xmlcml.euclid.RealRange; import org.xmlcml.euclid.ArrayBase.Trim; import org.xmlcml.euclid.RealArray.Filter; import org.xmlcml.euclid.RealArray.Monotonicity; /** * test RealArray. * * @author pmr * */ public class RealArrayTest { RealArray a0; RealArray a1; /** * main * * @param args */ public static void main(String[] args) { } /** * setup. * * @throws Exception */ @Before public void setUp() throws Exception { a0 = new RealArray(); a1 = new RealArray(new double[] { 1.0, 2.0, 4.0, 6.0 }); } /** * equality test. true if both args not null and equal within epsilon * * @param msg * message * @param test * @param expected * @param epsilon */ public static void assertEquals(String msg, RealArray test, RealArray expected, double epsilon) { Assert.assertNotNull("test should not be null (" + msg + EuclidConstants.S_RBRAK, test); Assert.assertNotNull("expected should not be null (" + msg + EuclidConstants.S_RBRAK, expected); DoubleTestBase.assertEquals(msg, test.getArray(), expected.getArray(), epsilon); } /** * equality test. true if both args not null and equal within epsilon * * @param msg * message * @param test * array must be of length 3 * @param expected * @param epsilon */ public static void assertEquals(String msg, double[] test, RealArray expected, double epsilon) { Assert.assertNotNull("test should not be null (" + msg + EuclidConstants.S_RBRAK, test); Assert.assertNotNull("expected should not be null (" + msg + EuclidConstants.S_RBRAK, expected); Assert.assertEquals("must be of equal length ", test.length, expected .getArray().length); DoubleTestBase.assertEquals(msg, test, expected.getArray(), epsilon); } /** * Test method for 'org.xmlcml.euclid.RealArray.RealArray()' */ @Test public void testRealArray() { Assert.assertEquals("empty", 0, a0.size()); Assert.assertEquals("empty", "()", a0.toString()); } /** * Test method for 'org.xmlcml.euclid.RealArray.RealArray(int)' */ @Test public void testRealArrayInt() { RealArray r = new RealArray(4); Assert.assertEquals("r", 4, r.size()); RealArrayTest.assertEquals("r", new double[] { 0.0, 0.0, 0.0, 0.0 }, r, EPS); } /** * Test method for 'org.xmlcml.euclid.RealArray.RealArray(int, double, * double)' */ @Test public void testRealArrayIntDoubleDouble() { RealArray r = new RealArray(4, 1.0, 2.0); Assert.assertEquals("r", 4, r.size()); RealArrayTest.assertEquals("r", new double[] { 1.0, 3.0, 5.0, 7.0 }, r, EPS); } /** * Test method for 'org.xmlcml.euclid.RealArray.RealArray(int, double)' */ @Test public void testRealArrayIntDouble() { RealArray r = new RealArray(4, 2.0); Assert.assertEquals("r", 4, r.size()); RealArrayTest.assertEquals("r", new double[] { 2.0, 2.0, 2.0, 2.0 }, r, EPS); } /** * Test method for 'org.xmlcml.euclid.RealArray.RealArray(int, double[])' */ @Test public void testRealArrayIntDoubleArray() { double[] d = { 1.0, 2.0, 3.0, 4.0 }; RealArray r = new RealArray(3, d); Assert.assertEquals("r", 3, r.size()); RealArrayTest.assertEquals("r", new double[] { 1.0, 2.0, 3.0 }, r, EPS); try { r = new RealArray(5, d); Assert.fail("should always throw " + "Array size too small"); } catch (EuclidRuntimeException e) { Assert.assertEquals("double[]", "Array size too small", e .getMessage()); } } /** * Test method for 'org.xmlcml.euclid.RealArray.RealArray(double[])' */ @Test public void testRealArrayDoubleArray() { double[] d = { 1.0, 2.0, 3.0, 4.0 }; RealArray r = new RealArray(d); Assert.assertEquals("r", 4, r.size()); RealArrayTest.assertEquals("r", new double[] { 1.0, 2.0, 3.0, 4.0 }, r, EPS); } /** * Test method for 'org.xmlcml.euclid.RealArray.RealArray(IntArray)' */ @Test public void testRealArrayIntArray() { IntArray i = new IntArray(new int[] { 1, 2, 3, 4 }); RealArray r = new RealArray(i); Assert.assertEquals("r", 4, r.size()); RealArrayTest.assertEquals("r", new double[] { 1.0, 2.0, 3.0, 4.0 }, r, EPS); } /** * Test method for 'org.xmlcml.euclid.RealArray.RealArray(RealArray, int, * int)' */ @Test public void testRealArrayRealArrayIntInt() { RealArray r = new RealArray(a1, 1, 2); Assert.assertEquals("r", 2, r.size()); RealArrayTest.assertEquals("r", new double[] { 2.0, 4.0 }, r, EPS); try { r = new RealArray(a1, 0, 5); } catch (EuclidRuntimeException e) { Assert.assertEquals("real array", "index out of range 0/5", e .getMessage()); } } /** * Test method for 'org.xmlcml.euclid.RealArray.RealArray(RealArray, * IntArray)' */ @Test public void testRealArrayRealArrayIntArray() { RealArray r = new RealArray(a1, new IntArray(new int[] { 3, 1, 2 })); Assert.assertEquals("r", 3, r.size()); RealArrayTest.assertEquals("r", new double[] { 6.0, 2.0, 4.0 }, r, EPS); } /** * Test method for 'org.xmlcml.euclid.RealArray.RealArray(RealArray)' */ @Test public void testRealArrayRealArray() { RealArray r = new RealArray(a1); Assert.assertEquals("r", 4, r.size()); RealArrayTest.assertEquals("r", new double[] { 1.0, 2.0, 4.0, 6.0 }, r, EPS); } /** * Test method for 'org.xmlcml.euclid.RealArray.RealArray(int, String, * double)' */ @Test public void testRealArrayIntStringDouble() { RealArray r = new RealArray(3, "TRIANGLE", 2.0); Assert.assertEquals("r", 5, r.size()); RealArrayTest.assertEquals("r", new double[] { 2. / 3., 4. / 3., 2., 4. / 3., 2. / 3. }, r, EPS); } /** * Test method for 'org.xmlcml.euclid.RealArray.RealArray(String[])' */ @Test public void testRealArrayStringArray() { RealArray r = new RealArray(new String[] { "1.0", "2.0", "4.0", "6.0" }); RealArrayTest.assertEquals("string array", a1, r, EPS); } /** * Test method for 'org.xmlcml.euclid.RealArray.RealArray(String)' */ @Test public void testRealArrayString() { RealArray r = new RealArray("1.0 2.0 4.0 6.0"); RealArrayTest.assertEquals("string array", a1, r, EPS); } /** * Test method for 'org.xmlcml.euclid.RealArray.getFilter(int, String)' */ @Test public void testGetFilter() { RealArray filter = RealArray.getFilter(3, Filter.GAUSSIAN); double[] f = new double[] { 0.00000780609891336, 0.00416059856172973, 0.17996534087165197, 0.6317325089354098, 0.17996534087165197, 0.00416059856172973, 0.00000780609891336 }; RealArrayTest.assertEquals("filter", f, filter, 1.0E-16); filter = RealArray.getFilter(2, Filter.GAUSSIAN_FIRST_DERIVATIVE); f = new double[] { -8.307977825463781E-5, -0.19931487665039388, -0.0, 0.19931487665039388, 8.307977825463781E-5 }; RealArrayTest.assertEquals("filter", f, filter, 1.0E-16); filter = RealArray.getFilter(3, Filter.GAUSSIAN_SECOND_DERIVATIVE); f = new double[] { 5.338724215243003E-4, 0.119149066997191, 0.8611247708322933, -2.0, 0.8611247708322933, 0.119149066997191, 5.338724215243003E-4 }; RealArrayTest.assertEquals("filter", f, filter, 1.0E-16); } /** * test getSymmetricalArray() */ @Test public void testGetSymmetricalArray() { RealArray realArray = RealArray.getSymmetricalArray(10., 11, 1.0); Assert.assertEquals("range min", 9.0, realArray.getArray()[0], EPS); Assert.assertEquals("range min+1", 9.2, realArray.getArray()[1], EPS); Assert.assertEquals("range max", 11.0, realArray.getArray()[10], EPS); Assert.assertEquals("range mid", 10.0, realArray.getArray()[5], EPS); } @Test public void testGetMonotonicity() { RealArray realArray = new RealArray(new double[]{ 1., 2., 3., 4., 4., 5. }); Monotonicity m = realArray.getMonotonicity(); Assert.assertEquals("monotonicity", Monotonicity.INCREASING, m); realArray = new RealArray(new double[]{ 1., 2., }); m = realArray.getMonotonicity(); Assert.assertEquals("monotonicity", Monotonicity.INCREASING, m); realArray = new RealArray(new double[]{ 1., 1., }); m = realArray.getMonotonicity(); Assert.assertNull("monotonicity", m); realArray = new RealArray(new double[]{ 1., }); m = realArray.getMonotonicity(); Assert.assertNull("monotonicity", m); realArray = new RealArray(new double[]{ 5., 4., 3., 2., 2., 1. }); m = realArray.getMonotonicity(); Assert.assertEquals("monotonicity", Monotonicity.DECREASING, m); realArray = new RealArray(new double[]{ 5., 4., 1., 2., 2., 1. }); m = realArray.getMonotonicity(); Assert.assertNull("monotonicity", m); } /** * test getNormalDistribution() */ @Test public void testGetNormalDistribution() { double mean = 10.; double halfrange = 5.0; int nsteps = 101; double sigma = 1.0; RealArray realArray = RealArray.getSymmetricalArray(mean, nsteps, halfrange); RealArray normalDist = realArray.getNormalDistribution(sigma); Assert.assertEquals("range min", 1.486e-06, normalDist.getArray()[0], 1E-06); Assert.assertEquals("range mid", 0.398942, normalDist.getArray()[50], 1E-06); Assert.assertEquals("range max", 1.486e-06, normalDist.getArray()[100], 1E-06); RealArray cumulativeSum = normalDist.cumulativeSum(); Assert.assertEquals("range min", 1.5e-06, cumulativeSum.getArray()[0], 1E-06); Assert.assertEquals("range mid", 5.199469, cumulativeSum.getArray()[50], 1E-06); Assert.assertEquals("range max", 9.999996, cumulativeSum.getArray()[100], 1E-06); for (int i = 0; i < 100; i++) { /* double d = mean - halfrange + halfrange */Math.random(); // Util.sysout(d); } } /** * test lineSearch. */ @Test public void testLineSearch() { RealArray x = new RealArray(11, 0., 1.0); RealArray cumulative = new RealArray(new double[] { 0., 4., 5., 20., 23., 26., 33., 40., 41., 44., 50. }); double d = -1.; double probe = 22.; d = x.lineSearch(probe, cumulative); Assert.assertEquals("search ", 11. / 3., d, EPS); probe = 2.; d = x.lineSearch(probe, cumulative); Assert.assertEquals("search ", 0.5, d, EPS); probe = 1.; d = x.lineSearch(probe, cumulative); Assert.assertEquals("search ", 0.25, d, EPS); probe = 4.5; d = x.lineSearch(probe, cumulative); Assert.assertEquals("search ", 1.5, d, EPS); probe = 50; d = x.lineSearch(probe, cumulative); Assert.assertEquals("search ", 10., d, EPS); probe = 0; d = x.lineSearch(probe, cumulative); Assert.assertEquals("search ", 0., d, EPS); } /** * test getRandomVariate. * */ @Test @SuppressWarnings("unused") public void testGetRandomVariate() { RealArray x = new RealArray(11, 20., 1.); // gives 20, 21 ...30 RealArray freq = new RealArray(new double[] { 5., 10., 10., 1., 0., 2., 10., 15., 10., 3., 1. }); RealArray cumulativeSum = new RealArray(); for (int i = 0; i < 50; i++) { double random = x.getRandomVariate(freq, cumulativeSum); // Util.sysout(cumulativeSum); // Util.sysout(random); } } /** * Test method for 'org.xmlcml.euclid.RealArray.elementAt(int)' */ @Test public void testElementAt() { Assert.assertEquals("element at", 4.0, a1.elementAt(2),EPS); try { Assert.assertEquals("element at", 4.0, a1.elementAt(5),EPS); Assert.fail("should always throw " + "ArrayIndexOutOfBoundsException"); } catch (ArrayIndexOutOfBoundsException e) { Assert.assertEquals("ArrayIndexOutOfBoundsException", "5", e .getMessage()); } } /** * Test method for 'org.xmlcml.euclid.RealArray.size()' */ @Test public void testSize() { Assert.assertEquals("size", 0, a0.size()); Assert.assertEquals("size", 4, a1.size()); } /** * Test method for 'org.xmlcml.euclid.RealArray' */ @Test public void testGetArray() { RealArrayTest.assertEquals("array", new double[] {}, a0, EPS); RealArrayTest.assertEquals("array", new double[] { 1., 2., 4., 6. }, a1, EPS); } /** * Test method for 'org.xmlcml.euclid.RealArray.clearArray()' */ @Test public void testClearArray() { a1.clearArray(); RealArrayTest.assertEquals("clear", new double[] { 0., 0., 0., 0. }, a1, EPS); } /** * Test method for 'org.xmlcml.euclid.RealArray.getReverseArray()' */ @Test public void testGetReverseArray() { double[] d = a1.getReverseArray(); DoubleTestBase.assertEquals("clear", new double[] { 6., 4., 2., 1. }, d, EPS); } /** * Test method for 'org.xmlcml.euclid.RealArray.isEqualTo(RealArray)' */ @Test public void testIsEqualTo() { RealArray a = new RealArray("1 2 4 6"); Assert.assertTrue("isEqualTo", a1.isEqualTo(a)); a = new RealArray("1 2 4 6.1"); Assert.assertFalse("isEqualTo", a1.isEqualTo(a)); a = new RealArray("1 2 4"); Assert.assertFalse("isEqualTo", a1.isEqualTo(a)); } /** * Test method for 'org.xmlcml.euclid.RealArray.equals(RealArray, double)' */ @Test public void testEqualsRealArrayDouble() { RealArray a = new RealArray("1 2 4 6"); Assert.assertTrue("isEqualTo", a1.equals(a, EPS)); a = new RealArray("1 2 4 6.1"); Assert.assertFalse("isEqualTo", a1.equals(a, EPS)); a = new RealArray("1.00002 1.99999 4.0000007 6.0001"); Assert.assertTrue("isEqualTo", a1.equals(a, .001)); a = new RealArray("1 2 4"); Assert.assertFalse("isEqualTo", a1.equals(a, EPS)); } /** * Test method for 'org.xmlcml.euclid.RealArray.plus(RealArray)' */ @Test public void testPlus() { RealArray a2 = a1.plus(new RealArray("10 20 30 40")); RealArrayTest.assertEquals("plus", new double[] { 11.0, 22.0, 34.0, 46.0 }, a2, EPS); } /** * Test method for 'org.xmlcml.euclid.RealArray.plusEquals(RealArray)' */ @Test public void testPlusEquals() { a1.plusEquals(new RealArray("10 20 30 40")); RealArrayTest.assertEquals("plus", new double[] { 11.0, 22.0, 34.0, 46.0 }, a1, EPS); } /** * Test method for 'org.xmlcml.euclid.RealArray.subtract(RealArray)' */ @Test public void testSubtract() { RealArray a2 = a1.subtract(new RealArray("10 20 30 40")); RealArrayTest.assertEquals("subtract", new double[] { -9.0, -18.0, -26.0, -34.0 }, a2, EPS); } /** * Test method for 'org.xmlcml.euclid.RealArray.subtractEquals(RealArray)' */ @Test public void testSubtractEquals() { a1.subtractEquals(new RealArray("10 20 30 40")); RealArrayTest.assertEquals("subtract", new double[] { -9.0, -18.0, -26.0, -34.0 }, a1, EPS); } /** * Test method for 'org.xmlcml.euclid.RealArray.negative()' */ @Test public void testNegative() { a1.negative(); RealArrayTest.assertEquals("negative", new double[] { -1, -2, -4, -6 }, a1, EPS); } /** * Test method for 'org.xmlcml.euclid.RealArray.addScalar(double)' */ @Test public void testAddScalar() { RealArray a = a1.addScalar(3.3); RealArrayTest.assertEquals("addScalar", new double[] { 4.3, 5.3, 7.3, 9.3 }, a, EPS); } /** * Test method for 'org.xmlcml.euclid.RealArray.multiplyBy(double)' */ @Test public void testMultiplyBy() { RealArray a = a1.multiplyBy(1.1); RealArrayTest.assertEquals("multiplyBy", new double[] { 1.1, 2.2, 4.4, 6.6 }, a, EPS); } /** * Test method for 'org.xmlcml.euclid.RealArray.setElementAt(int, double)' */ @Test public void testSetElementAt() { a1.setElementAt(2, 10.); RealArrayTest.assertEquals("setElement", new double[] { 1., 2., 10., 6. }, a1, EPS); } /** * Test method for 'org.xmlcml.euclid.RealArray.getSubArray(int, int)' */ @Test public void testGetSubArray() { RealArray a = a1.getSubArray(2, 3); RealArrayTest.assertEquals("subArray", new double[] { 4., 6. }, a, EPS); a = a1.getSubArray(2, 2); RealArrayTest.assertEquals("subArray", new double[] { 4. }, a, EPS); a = a1.getSubArray(0, 3); RealArrayTest.assertEquals("subArray", new double[] { 1., 2., 4., 6. }, a, EPS); try { a = a1.getSubArray(0, 5); Assert.fail("should always throw " + "ArrayIndexOutOfBoundsException"); } catch (ArrayIndexOutOfBoundsException e) { Assert.assertEquals("subArray ArrayIndexOutOfBoundsException", "java.lang.ArrayIndexOutOfBoundsException", "" + e); } } /** * Test method for 'org.xmlcml.euclid.RealArray.setElements(int, double[])' */ @Test public void testSetElements() { a1.setElements(1, new double[] { 10., 20. }); RealArrayTest.assertEquals("setElement", new double[] { 1., 10., 20., 6. }, a1, EPS); try { a1.setElements(1, new double[] { 10., 20., 30., 40. }); Assert.fail("should always throw " + "ArrayIndexOutOfBoundsException"); } catch (ArrayIndexOutOfBoundsException e) { Assert.assertEquals("subArray ArrayIndexOutOfBoundsException", "java.lang.ArrayIndexOutOfBoundsException: was 1 in 0-4", "" + e); } } /** * Test method for 'org.xmlcml.euclid.RealArray.isClear()' */ @Test public void testIsClear() { Assert.assertFalse("isClear", a1.isClear()); a1.clearArray(); Assert.assertTrue("isClear", a1.isClear()); } /** * Test method for 'org.xmlcml.euclid.RealArray.setAllElements(double)' */ @Test public void testSetAllElements() { a1.setAllElements(10.); RealArrayTest.assertEquals("setElement", new double[] { 10., 10., 10., 10. }, a1, EPS); } /** * Test method for 'org.xmlcml.euclid.RealArray.sumAllElements()' */ @Test public void testSumAllElements() { Assert.assertEquals("sum", 13., a1.sumAllElements(), EPS); } /** * Test method for 'org.xmlcml.euclid.RealArray.absSumAllElements()' */ @Test public void testAbsSumAllElements() { RealArray a = new RealArray("-1 3 -11 14"); Assert.assertEquals("sum", 5., a.sumAllElements(), EPS); Assert.assertEquals("absSum", 29., a.absSumAllElements(), EPS); } /** * Test method for 'org.xmlcml.euclid.RealArray.innerProduct()' */ @Test public void testInnerProduct() { Assert.assertEquals("inner", 57., a1.innerProduct(), EPS); } /** * Test method for 'org.xmlcml.euclid.RealArray.dotProduct(RealArray)' */ @Test public void testDotProduct() { RealArray a = new RealArray("1 2 3 4"); double d = a1.dotProduct(a); Assert.assertEquals("dot", 41., d, EPS); a = new RealArray("1 2 3"); try { a1.dotProduct(a); Assert.fail("should always throw " + "ArrayIndexOutOfBoundsException"); } catch (EuclidRuntimeException e) { Assert.assertEquals("dot", "org.xmlcml.euclid.EuclidRuntimeException", "" + e); } } /** * Test method for 'org.xmlcml.euclid.RealArray.euclideanLength()' */ @Test public void testEuclideanLength() { double d = 0.0; d = a1.euclideanLength(); Assert.assertEquals("dot", Math.sqrt(57.), d, EPS); } /** * Test method for 'org.xmlcml.euclid.RealArray.rms()' */ @Test public void testRms() { double d = a1.rms(); Assert.assertEquals("rms", 3.7749172176, d, 1.0E-06); } /** * Test method for 'org.xmlcml.euclid.RealArray.unitVector()' */ @Test public void testUnitVector() { RealArray v = a1.unitVector(); RealArrayTest.assertEquals("unit vector", new double[] { 0.13245323570650439, 0.26490647141300877, 0.5298129428260175, 0.7947194142390264 }, v, 1.0E-10); } /** * Test method for 'org.xmlcml.euclid.RealArray.cumulativeSum()' */ @Test public void testCumulativeSum() { RealArray a = a1.cumulativeSum(); RealArrayTest.assertEquals("cumulative", new double[] { 1., 3., 7., 13. }, a, EPS); } /** * Test method for 'org.xmlcml.euclid.RealArray.applyFilter(RealArray)' */ @Test public void testApplyFilter() { RealArray gaussian = RealArray.getFilter(3, Filter.GAUSSIAN); RealArray raw = new RealArray(new double[] { 1., 2., 1., 2., 1., 5., 7., 9., 3., 2., 3., 1., 1. }); RealArray filtered = raw.applyFilter(gaussian); double[] d = { 1.2205914829606295, 1.6385548625623205, 1.3599647160591364, 1.6525823383375386, 1.9248605506188587, 4.644183080224947, 6.958315953393569, 7.51440140346297, 3.916469098605179, 2.384925497509336, 2.4518253377494292, 1.3656309904274337, 1.010208785051181 }; RealArrayTest.assertEquals("filtered", d, filtered, EPS); } /** * Test method for 'org.xmlcml.euclid.RealArray.trim(int, double)' */ @Test public void testTrim() { RealArray a = new RealArray("1.1 2.1 3 4 1.2 3.2 5 1 3"); RealArray b = a.trim(Trim.ABOVE, 2.0); double[] d = { 1.1, 2.0, 2.0, 2.0, 1.2, 2.0, 2.0, 1.0, 2.0 }; RealArrayTest.assertEquals("trim", d, b, EPS); b = a.trim(Trim.BELOW, 2.0); double[] dd = { 2.0, 2.1, 3.0, 4.0, 2.0, 3.2, 5.0, 2.0, 3.0 }; RealArrayTest.assertEquals("trim", dd, b, EPS); } /** * Test method for 'org.xmlcml.euclid.RealArray.indexOfLargestElement()' */ @Test public void testIndexOfLargestElement() { Assert.assertEquals("largest", 3, a1.indexOfLargestElement()); } /** * Test method for 'org.xmlcml.euclid.RealArray.indexOfSmallestElement()' */ @Test public void testIndexOfSmallestElement() { Assert.assertEquals("smallest", 0, a1.indexOfSmallestElement()); } /** * Test method for 'org.xmlcml.euclid.RealArray.largestElement()' */ @Test public void testLargestElement() { Assert.assertEquals("largest", 6., a1.largestElement(),EPS); } /** * Test method for 'org.xmlcml.euclid.RealArray.getMax()' */ @Test public void testGetMax() { Assert.assertEquals("max", 6., a1.getMax(), EPS); } /** * Test method for 'org.xmlcml.euclid.RealArray.smallestElement()' */ @Test public void testSmallestElement() { Assert.assertEquals("smallest", 1., a1.smallestElement(),EPS); } /** * Test method for 'org.xmlcml.euclid.RealArray.getMin()' */ @Test public void testGetMin() { Assert.assertEquals("max", 1., a1.getMin(), EPS); } /** * Test method for 'org.xmlcml.euclid.RealArray.getRange()' */ @Test public void testGetRange() { RealRange range = a1.getRange(); Assert.assertEquals("range", 1., range.getMin(), EPS); Assert.assertEquals("range", 6., range.getMax(), EPS); } /** * Test method for 'org.xmlcml.euclid.RealArray.deleteElement(int)' */ @Test public void testDeleteElement() { a1.deleteElement(2); RealArrayTest.assertEquals("delete", new double[] { 1., 2., 6. }, a1, EPS); } /** * Test method for 'org.xmlcml.euclid.RealArray.deleteElements(int, int)' */ @Test public void testDeleteElementsIntInt() { RealArray a = new RealArray(a1); a.deleteElements(1, 2); RealArrayTest.assertEquals("delete", new double[] { 1., 6. }, a, EPS); a = new RealArray(a1); a.deleteElements(0, 3); RealArrayTest.assertEquals("delete", new double[] {}, a, EPS); a = new RealArray(a1); a.deleteElements(2, 2); RealArrayTest.assertEquals("delete", new double[] { 1., 2., 6. }, a, EPS); } /** * Test method for 'org.xmlcml.euclid.RealArray.insertElementAt(int, * double)' */ @Test public void testInsertElementAt() { RealArray a = new RealArray(a1); a.insertElementAt(1, 30.); RealArrayTest.assertEquals("insert", new double[] { 1., 30., 2., 4., 6. }, a, EPS); a.insertElementAt(0, 20.); RealArrayTest.assertEquals("insert", new double[] { 20., 1., 30., 2., 4., 6. }, a, EPS); a.insertElementAt(6, 10.); RealArrayTest.assertEquals("insert", new double[] { 20., 1., 30., 2., 4., 6., 10. }, a, EPS); } /** * Test method for 'org.xmlcml.euclid.RealArray.insertArray(int, RealArray)' */ @Test public void testInsertArray() { a1.insertArray(1, new RealArray("44 55")); RealArrayTest.assertEquals("insert", new double[] { 1., 44., 55., 2., 4., 6. }, a1, EPS); } /** * Test method for 'org.xmlcml.euclid.RealArray.addElement(double)' */ @Test public void testAddElement() { a1.addElement(30.); RealArrayTest.assertEquals("insert", new double[] { 1., 2., 4., 6., 30. }, a1, EPS); } /** * Test method for 'org.xmlcml.euclid.RealArray.addArray(RealArray)' */ @Test public void testAddArray() { a1.addArray(new RealArray("5 16 7")); RealArrayTest.assertEquals("insert", new double[] { 1., 2., 4., 6., 5., 16., 7. }, a1, EPS); } /** * Test method for 'org.xmlcml.euclid.RealArray.getReorderedArray(IntSet)' */ @Test public void testGetReorderedArray() { IntSet intSet = new IntSet(new int[] { 3, 1, 0, 2 }); RealArray a = null; a = a1.getReorderedArray(intSet); RealArrayTest.assertEquals("insert", new double[] { 6., 2., 1., 4. }, a, EPS); } /** * Test method for 'org.xmlcml.euclid.RealArray.inRange(RealRange)' */ @Test public void testInRange() { RealRange range = new RealRange(1.3, 5.); IntSet intSet = a1.inRange(range); IntArray intArray = intSet.getIntArray(); IntArrayTest.assertEquals("inrange", new int[] { 1, 2 }, intArray); intSet = a1.inRange(new RealRange(-3., 7.)); IntArrayTest.assertEquals("inrange", new int[] { 0, 1, 2, 3 }, intSet .getIntArray()); intSet = a1.inRange(new RealRange(4.5, 4.6)); IntArrayTest .assertEquals("inrange", new int[] {}, intSet.getIntArray()); } /** * Test method for 'org.xmlcml.euclid.RealArray.outOfRange(RealRange)' */ @Test public void testOutOfRange() { RealRange range = new RealRange(1.3, 5.); IntSet intSet = a1.outOfRange(range); IntArray intArray = intSet.getIntArray(); IntArrayTest.assertEquals("inrange", new int[] { 0, 3 }, intArray); intSet = a1.outOfRange(new RealRange(-3., 7.)); IntArrayTest .assertEquals("inrange", new int[] {}, intSet.getIntArray()); intSet = a1.outOfRange(new RealRange(4.5, 4.6)); IntArrayTest.assertEquals("inrange", new int[] { 0, 1, 2, 3 }, intSet .getIntArray()); } /** * Test method for 'org.xmlcml.euclid.RealArray.getStringValues()' */ @Test public void testGetStringValues() { String[] ss = a1.getStringValues(); StringTestBase.assertEquals("string values", new String[] { "1.0", "2.0", "4.0", "6.0" }, ss); } /** * Test method for 'org.xmlcml.euclid.RealArray.sortAscending()' */ @Test public void testSortAscending() { RealArray ra = new RealArray("1 6 3 9 2 0"); ra.sortAscending(); RealArrayTest.assertEquals("sortAscending", new double[] { 0., 1., 2., 3., 6., 9. }, ra, EPS); } /** * Test method for 'org.xmlcml.euclid.RealArray.sortDescending()' */ @Test public void testSortDescending() { RealArray ra = new RealArray("1 6 3 9 2 0"); ra.sortDescending(); RealArrayTest.assertEquals("sortDescending", new double[] { 9., 6., 3., 2., 1., 0 }, ra, EPS); } /** * Test method for 'org.xmlcml.euclid.RealArray.reverse()' */ @Test public void testReverse() { RealArray ra = new RealArray("1 6 3 9 2 0"); ra.reverse(); RealArrayTest.assertEquals("reverse", new double[] { 0., 2., 9., 3., 6., 1. }, ra, EPS); } /** * Test method for 'org.xmlcml.euclid.RealArray.indexSortAscending()' */ @Test public void testIndexSortAscending() { RealArray ra = new RealArray("1 6 3 9 2 0"); IntSet intSet = ra.indexSortAscending(); IntArrayTest.assertEquals("sortAscending", new int[] { 5, 0, 4, 2, 1, 3 }, intSet.getIntArray()); } /** * Test method for 'org.xmlcml.euclid.RealArray.indexSortDescending()' */ @Test public void testIndexSortDescending() { RealArray ra = new RealArray("1 6 3 9 2 0"); IntSet intSet = ra.indexSortDescending(); IntArrayTest.assertEquals("sortDescending", new int[] { 3, 1, 2, 4, 0, 5 }, intSet.getIntArray()); } } wwmm-euclid-87e8f785a814/src/test/java/org/xmlcml/euclid/test/RealMatrixTest.java0000644000000000000000000012107311607017524025717 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid.test; import java.io.IOException; import java.io.StringWriter; import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.xmlcml.euclid.EC; import org.xmlcml.euclid.EuclidRuntimeException; import org.xmlcml.euclid.Int; import org.xmlcml.euclid.Int2; import org.xmlcml.euclid.IntMatrix; import org.xmlcml.euclid.IntSet; import org.xmlcml.euclid.Real2Array; import org.xmlcml.euclid.RealArray; import org.xmlcml.euclid.RealMatrix; import org.xmlcml.euclid.RealRange; /** * test RealMatrix * * @author pmr * */ public class RealMatrixTest{ static Logger logger = Logger.getLogger(RealMatrixTest.class.getName()); RealMatrix m0; RealMatrix m1; RealMatrix m2; /** * setup. * * @throws Exception */ @Before public void setUp() throws Exception { logger.setLevel(Level.WARN); m0 = new RealMatrix(); m1 = new RealMatrix(3, 4); m2 = new RealMatrix(3, 4, new double[] { 11., 12., 13., 14., 21., 22., 23., 24., 31., 32., 33., 34., }); } /** * equality test. true if both args not null and equal within epsilon and * rows are present and equals and columns are present and equals * * @param msg * message * @param test * @param expected * @param epsilon */ public static void assertEquals(String msg, RealMatrix test, RealMatrix expected, double epsilon) { Assert.assertNotNull("test should not be null (" + msg + EC.S_RBRAK, test); Assert.assertNotNull("expected should not be null (" + msg + EC.S_RBRAK, expected); Assert.assertNotNull("expected should have columns (" + msg + EC.S_RBRAK, expected.getCols()); Assert.assertNotNull("expected should have rows (" + msg + EC.S_RBRAK, expected.getRows()); Assert.assertNotNull("test should have columns (" + msg + EC.S_RBRAK, test .getCols()); Assert.assertNotNull("test should have rows (" + msg + EC.S_RBRAK, test .getRows()); Assert.assertEquals("rows should be equal (" + msg + EC.S_RBRAK, test .getRows(), expected.getRows()); Assert.assertEquals("columns should be equal (" + msg + EC.S_RBRAK, test .getCols(), expected.getCols()); DoubleTestBase.assertEquals(msg, test.getMatrixAsArray(), expected .getMatrixAsArray(), epsilon); } /** * equality test. true if both args not null and equal within epsilon * * @param msg * message * @param rows * @param cols * @param test * @param expected * @param epsilon */ public static void assertEquals(String msg, int rows, int cols, double[] test, RealMatrix expected, double epsilon) { Assert.assertNotNull("test should not be null (" + msg + EC.S_RBRAK, test); Assert.assertNotNull("ref should not be null (" + msg + EC.S_RBRAK, expected); Assert.assertEquals("rows should be equal (" + msg + EC.S_RBRAK, rows, expected.getRows()); Assert.assertEquals("columns should be equal (" + msg + EC.S_RBRAK, cols, expected.getCols()); DoubleTestBase.assertEquals(msg, test, expected.getMatrixAsArray(), epsilon); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.RealMatrix()' */ @Test public void testRealMatrix() { Assert.assertEquals("empty", "()", m0.toString()); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.RealMatrix(int, int)' */ @Test public void testRealMatrixIntInt() { Assert.assertEquals("int int", "{3,4}" + "\n(0.0,0.0,0.0,0.0)" + "\n(0.0,0.0,0.0,0.0)" + "\n(0.0,0.0,0.0,0.0)", m1.toString()); Assert.assertEquals("int int rows", 3, m1.getRows()); Assert.assertEquals("int int cols", 4, m1.getCols()); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.RealMatrix(int, int, * double[])' */ @Test public void testRealMatrixIntIntDoubleArray() { Assert.assertEquals("int int double[]", "{3,4}" + "\n(11.0,12.0,13.0,14.0)" + "\n(21.0,22.0,23.0,24.0)" + "\n(31.0,32.0,33.0,34.0)", m2.toString()); Assert.assertEquals("int int double[] rows", 3, m2.getRows()); Assert.assertEquals("int int double[] cols", 4, m2.getCols()); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.RealMatrix(int, int, * double)' */ @Test public void testRealMatrixIntIntDouble() { RealMatrix m = new RealMatrix(3, 4, 10.); Assert.assertEquals("int int double[]", "{3,4}" + "\n(10.0,10.0,10.0,10.0)" + "\n(10.0,10.0,10.0,10.0)" + "\n(10.0,10.0,10.0,10.0)", m.toString()); Assert.assertEquals("int int double[] rows", 3, m.getRows()); Assert.assertEquals("int int double[] cols", 4, m.getCols()); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.RealMatrix(RealMatrix, int, * int, int, int)' */ @Test public void testRealMatrixRealMatrixIntIntIntInt() { RealMatrix m = new RealMatrix(m2, 1, 2, 1, 3); Assert.assertEquals("int int double[]", "{2,3}" + "\n(22.0,23.0,24.0)" + "\n(32.0,33.0,34.0)", m.toString()); Assert.assertEquals("int int double[] rows", 2, m.getRows()); Assert.assertEquals("int int double[] cols", 3, m.getCols()); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.RealMatrix(RealMatrix)' */ @Test public void testRealMatrixRealMatrix() { RealMatrix m = new RealMatrix(m2); Assert.assertEquals("int int double[]", "{3,4}" + "\n(11.0,12.0,13.0,14.0)" + "\n(21.0,22.0,23.0,24.0)" + "\n(31.0,32.0,33.0,34.0)", m.toString()); Assert.assertEquals("int int double[] rows", 3, m.getRows()); Assert.assertEquals("int int double[] cols", 4, m.getCols()); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.RealMatrix(IntMatrix)' */ @Test public void testRealMatrixIntMatrix() { IntMatrix i2 = new IntMatrix(3, 4, new int[] { 11, 12, 13, 14, 21, 22, 23, 24, 31, 32, 33, 34, }); RealMatrix m = new RealMatrix(i2); Assert.assertEquals("int int double[]", "{3,4}" + "\n(11.0,12.0,13.0,14.0)" + "\n(21.0,22.0,23.0,24.0)" + "\n(31.0,32.0,33.0,34.0)", m.toString()); Assert.assertEquals("int int double[] rows", 3, m.getRows()); Assert.assertEquals("int int double[] cols", 4, m.getCols()); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.getIntMatrix()' */ @Test public void testGetIntMatrix() { RealMatrix mm2 = new RealMatrix(3, 4, new double[] { 11.1, 12.1, 13.1, 14.1, 21.1, 22.1, 23.1, 24.1, 31.1, 32.1, 33.1, 34.1, }); IntMatrix m = mm2.getIntMatrix(); Assert.assertEquals("int int double[]", "{3,4}" + "\n(11,12,13,14)" + "\n(21,22,23,24)" + "\n(31,32,33,34)", m.toString()); Assert.assertEquals("int int double[] rows", 3, m.getRows()); Assert.assertEquals("int int double[] cols", 4, m.getCols()); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.RealMatrix(double[][])' */ @Test public void testRealMatrixDoubleArrayArray() { RealMatrix mm2 = new RealMatrix(new double[][] { new double[] { 11.1, 12.1, 13.1, 14.1 }, new double[] { 21.1, 22.1, 23.1, 24.1 }, new double[] { 31.1, 32.1, 33.1, 34.1 } }); IntMatrix m = mm2.getIntMatrix(); Assert.assertEquals("int int double[]", "{3,4}" + "\n(11,12,13,14)" + "\n(21,22,23,24)" + "\n(31,32,33,34)", m.toString()); Assert.assertEquals("int int double[] rows", 3, m.getRows()); Assert.assertEquals("int int double[] cols", 4, m.getCols()); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.setFormat(DecimalFormat)' */ @Test public void testSetFormat() { } /** * Test method for 'org.xmlcml.euclid.RealMatrix.getFormat()' */ @Test public void testGetFormat() { } /** * Test method for 'org.xmlcml.euclid.RealMatrix.getRows()' */ @Test public void testGetRowsCols() { RealMatrix m = new RealMatrix(new double[][] { new double[] { 11.1, 12.1, 13.1, 14.1 }, new double[] { 21.1, 22.1, 23.1, 24.1 }, new double[] { 31.1, 32.1, 33.1, 34.1 } }); Assert.assertEquals("int int double[] rows", 3, m.getRows()); Assert.assertEquals("int int double[] cols", 4, m.getCols()); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.getMatrix()' */ @Test public void testGetMatrix() { double[][] matrix = m1.getMatrix(); Assert.assertEquals("getMatrix", 3, matrix.length); Assert.assertEquals("getMatrix", 4, matrix[0].length); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.getMatrixAsArray()' */ @Test public void testGetMatrixAsArray() { double[] array = m2.getMatrixAsArray(); DoubleTestBase.assertEquals("matrix as array", new double[] { 11.0, 12.0, 13.0, 14.0, 21.0, 22.0, 23.0, 24.0, 31.0, 32.0, 33.0, 34.0 }, array, EC.EPS); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.isEqualTo(RealMatrix)' */ @Test public void testIsEqualTo() { Assert.assertTrue("isEqualTo", m2.isEqualTo(m2)); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.plus(RealMatrix)' */ @Test public void testPlus() { RealMatrix m = m2.plus(m2); RealMatrixTest.assertEquals("matrix as array", 3, 4, new double[] { 22.0, 24.0, 26.0, 28.0, 42.0, 44.0, 46.0, 48.0, 62.0, 64.0, 66.0, 68.0 }, m, EC.EPS); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.subtract(RealMatrix)' */ @Test public void testSubtract() { RealMatrix m = new RealMatrix(new double[][] { new double[] { 11.1, 12.1, 13.1, 14.1 }, new double[] { 21.1, 22.1, 23.1, 24.1 }, new double[] { 31.1, 32.1, 33.1, 34.1 } }); RealMatrix mm = m2.subtract(m); RealMatrixTest.assertEquals("matrix as array", 3, 4, new double[] { -0.1, -0.1, -0.1, -0.1, -0.1, -0.1, -0.1, -0.1, -0.1, -0.1, -0.1, -0.1, }, mm, EC.EPS); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.negative()' */ @Test public void testNegative() { m2.negative(); RealMatrixTest.assertEquals("matrix as array", 3, 4, new double[] { -11.0, -12.0, -13.0, -14.0, -21.0, -22.0, -23.0, -24.0, -31.0, -32.0, -33.0, -34.0 }, m2, EC.EPS); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.multiply(RealMatrix)' */ @Test public void testMultiplyRealMatrix() { RealMatrix m = new RealMatrix(new double[][] { new double[] { 10, 20, 30 }, new double[] { 40, 50, 60 }, }); RealMatrix mm = m.multiply(m2); RealMatrixTest.assertEquals("matrix as array", 2, 4, new double[] { 1460.0, 1520.0, 1580.0, 1640.0, 3350.0, 3500.0, 3650.0, 3800.0, }, mm, EC.EPS); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.multiplyBy(double)' */ @Test public void testMultiplyBy() { m2.multiplyBy(10.); RealMatrixTest.assertEquals("matrix as array", 3, 4, new double[] { 110.0, 120.0, 130.0, 140.0, 210.0, 220.0, 230.0, 240.0, 310.0, 320.0, 330.0, 340.0, }, m2, EC.EPS); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.multiplyEquals(RealMatrix)' */ @Test public void testMultiplyEquals() { RealMatrix m = new RealMatrix(new double[][] { new double[] { 10, 20, 30 }, new double[] { 40, 50, 60 }, }); try { m2.multiplyEquals(m); Assert.fail("non-conformable matrices"); } catch (EuclidRuntimeException e) { Assert.assertEquals("multiplyEquals", "unequal matrices (4, 2)", e .getMessage()); } m.multiplyEquals(m2); RealMatrixTest.assertEquals("matrix as array", 2, 4, new double[] { 1460.0, 1520.0, 1580.0, 1640.0, 3350.0, 3500.0, 3650.0, 3800.0, }, m, EC.EPS); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.multiply(RealArray)' */ @Test public void testMultiplyRealArray() { RealArray ra = new RealArray(new double[] { 1., 2., 3., 4. }); RealArray raa = m2.multiply(ra); RealArrayTest.assertEquals("array", new double[] { 130.0, 230.0, 330.0 }, raa, EC.EPS); } /** * Test method for * 'org.xmlcml.euclid.RealMatrix.columnwiseDivide(RealArray)' */ @Test public void testColumnwiseDivide() { RealArray ra = new RealArray(new double[] { 1., 2., 3., 4. }); m2.columnwiseDivide(ra); RealMatrixTest.assertEquals("array", 3, 4, new double[] { 11.0, 6.0, 4.333333, 3.5, 21.0, 11.0, 7.66666666, 6.0, 31.0, 16.0, 11.0, 8.5, }, m2, 0.00001); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.elementAt(int, int)' */ @Test public void testElementAtIntInt() { Assert.assertEquals("elementAt ", 32.0, m2.elementAt(2, 1), EC.EPS); try { m2.elementAt(5, 5); } catch (EuclidRuntimeException e) { Assert.assertEquals("elementAt", "Bad value of row: 5/3", e .getMessage()); } } /** * Test method for 'org.xmlcml.euclid.RealMatrix.elementAt(Int2)' */ @Test public void testElementAtInt2() { Assert.assertEquals("elementAt ", 32.0, m2.elementAt(new Int2(2, 1)), EC.EPS); try { m2.elementAt(new Int2(5, 5)); } catch (EuclidRuntimeException e) { Assert.assertEquals("elementAt", "Bad value of row: 5/3", e .getMessage()); } } /** * Test method for 'org.xmlcml.euclid.RealMatrix.setElementAt(int, int, * double)' */ @Test public void testSetElementAt() { m2.setElementAt(1, 2, 15.); RealMatrixTest.assertEquals("matrix as array", 3, 4, new double[] { 11.0, 12.0, 13.0, 14.0, 21.0, 22.0, 15.0, 24.0, 31.0, 32.0, 33.0, 34.0, }, m2, EC.EPS); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.largestElement()' */ @Test public void testLargestElement() { double d = m2.largestElement(); Assert.assertEquals("largestElement", 34., d, EC.EPS); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.indexOfLargestElement()' */ @Test public void testIndexOfLargestElement() { Int2 ii = m2.indexOfLargestElement(); Assert.assertEquals("indexOfLargestElement", 2, ii.getX()); Assert.assertEquals("indexOfLargestElement", 3, ii.getY()); } /** * Test method for * 'org.xmlcml.euclid.RealMatrix.largestElementInColumn(int)' */ @Test public void testLargestElementInColumn() { double d = m2.largestElementInColumn(1); Assert.assertEquals("largestElement", 32., d, EC.EPS); } /** * Test method for * 'org.xmlcml.euclid.RealMatrix.indexOfLargestElementInColumn(int)' */ @Test public void testIndexOfLargestElementInColumn() { int i = m2.indexOfLargestElementInColumn(1); Assert.assertEquals("largestElement", 2, i); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.largestElementInRow(int)' */ @Test public void testLargestElementInRow() { double d = m2.largestElementInRow(1); Assert.assertEquals("largestElement", 24., d, EC.EPS); } /** * Test method for * 'org.xmlcml.euclid.RealMatrix.indexOfLargestElementInRow(int)' */ @Test public void testIndexOfLargestElementInRow() { int i = m2.indexOfLargestElementInRow(1); Assert.assertEquals("largestElement", 3, i); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.smallestElement()' */ @Test public void testSmallestElement() { double d = m2.smallestElement(); Assert.assertEquals("smallestElement", 11., d, EC.EPS); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.indexOfSmallestElement()' */ @Test public void testIndexOfSmallestElement() { Int2 ii = m2.indexOfSmallestElement(); Assert.assertEquals("indexOfSmallestElement", 0, ii.getX()); Assert.assertEquals("indexOfSmallestElement", 0, ii.getY()); } /** * Test method for * 'org.xmlcml.euclid.RealMatrix.smallestElementInColumn(int)' */ @Test public void testSmallestElementInColumn() { double d = m2.smallestElementInColumn(1); Assert.assertEquals("smallestElement", 12., d, EC.EPS); } /** * Test method for * 'org.xmlcml.euclid.RealMatrix.indexOfSmallestElementInColumn(int)' */ @Test public void testIndexOfSmallestElementInColumn() { int i = m2.indexOfSmallestElementInColumn(1); Assert.assertEquals("largestElement", 0, i); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.smallestElementInRow(int)' */ @Test public void testSmallestElementInRow() { double d = m2.smallestElementInRow(1); Assert.assertEquals("smallestElement", 21., d, EC.EPS); } /** * Test method for * 'org.xmlcml.euclid.RealMatrix.indexOfSmallestElementInRow(int)' */ @Test public void testIndexOfSmallestElementInRow() { int i = m2.indexOfSmallestElementInRow(1); Assert.assertEquals("largestElement", 0, i); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.isOrthogonal()' */ @Test public void testIsOrthogonal() { Assert.assertFalse("orthogonal", m2.isOrthogonal()); RealMatrix m = new RealMatrix(2, 2, new double[] { 1., 0., 0., 1. }); Assert.assertTrue("orthogonal", m.isOrthogonal()); m = new RealMatrix(2, 2, new double[] { Math.cos(Math.PI / 3.), Math.sin(Math.PI / 3.), -Math.sin(Math.PI / 3.), Math.cos(Math.PI / 3.) }); Assert.assertTrue("orthogonal", m.isOrthogonal()); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.euclideanRowLength(int)' */ @Test public void testEuclideanRowLength() { double d = m2.euclideanRowLength(1); Assert.assertEquals("euclidean row length", 45.05552130427524, d, EC.EPS); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.euclideanRowLengths()' */ @Test public void testEuclideanRowLengths() { RealArray ra = m2.euclideanRowLengths(); RealArrayTest.assertEquals("euclidean row lengths", new double[] { 25.099800796022265, 45.05552130427524, 65.0384501660364 }, ra, EC.EPS); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.euclideanColumnLength(int)' */ @Test public void testEuclideanColumnLength() { double d = m2.euclideanColumnLength(1); Assert.assertEquals("euclidean row length", 40.64480286580315, d, EC.EPS); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.euclideanColumnLengths()' */ @Test public void testEuclideanColumnLengths() { RealArray ra = m2.euclideanColumnLengths(); RealArrayTest.assertEquals("euclidean column lengths", new double[] { 39.02563260217571, 40.64480286580315, 42.2729227756965, 43.9089968002003 }, ra, EC.EPS); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.extractColumnData(int)' */ @Test public void testExtractColumnData() { RealArray ra = m2.extractColumnData(1); RealArrayTest.assertEquals("euclidean column lengths", new double[] { 12., 22., 32. }, ra, EC.EPS); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.extractRowData(int)' */ @Test public void testExtractRowData() { RealArray ra = m2.extractRowData(1); RealArrayTest.assertEquals("euclidean column lengths", new double[] { 21., 22., 23., 24. }, ra, EC.EPS); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.clearMatrix()' */ @Test public void testClearMatrix() { m2.clearMatrix(); RealMatrixTest.assertEquals("matrix as array", 3, 4, new double[] { 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., }, m2, EC.EPS); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.setAllElements(double)' */ @Test public void testSetAllElements() { m2.setAllElements(23.); RealMatrixTest.assertEquals("matrix as array", 3, 4, new double[] { 23., 23., 23., 23., 23., 23., 23., 23., 23., 23., 23., 23., }, m2, EC.EPS); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.normaliseByRows()' */ @Test public void testNormaliseByRows() { m2.normaliseByRows(); RealMatrixTest.assertEquals("matrix as array", 3, 4, new double[] { 0.4382504900892777, 0.4780914437337575, 0.5179323973782373, 0.5577733510227171, 0.46609159969939906, 0.4882864377803228, 0.5104812758612466, 0.5326761139421703, 0.47664112414825727, 0.49201664428207204, 0.5073921644158867, 0.5227676845497016, }, m2, EC.EPS); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.normaliseByColumns()' */ @Test public void testNormaliseByColumns() { m2.normaliseByColumns(); RealMatrixTest.assertEquals("matrix as array", 3, 4, new double[] { 0.2818660266736263, 0.29524069878307374, 0.30752545947624765, 0.31884126307199384, 0.5381078691041957, 0.5412746144356352, 0.5440835052272074, 0.5465850224091323, 0.7943497115347651, 0.7873085300881967, 0.7806415509781671, 0.7743287817462708, }, m2, EC.EPS); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.getTranspose()' */ @Test public void testGetTranspose() { RealMatrix m = m2.getTranspose(); RealMatrixTest.assertEquals("transpose", 4, 3, new double[] { 11.0, 21.0, 31.0, 12.0, 22.0, 32.0, 13.0, 23.0, 33.0, 14.0, 24.0, 34.0, }, m, EC.EPS); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.isSquare()' */ @Test public void testIsSquare() { Assert.assertFalse("isSquare", m2.isSquare()); Assert.assertTrue("isSquare", new RealMatrix(2, 2, new double[] { 11., 12., 21., 22. }).isSquare()); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.deleteColumn(int)' */ @Test public void testDeleteColumn() { m2.deleteColumn(1); RealMatrixTest.assertEquals("matrix as array", 3, 3, new double[] { 11.0, 13.0, 14.0, 21.0, 23.0, 24.0, 31.0, 33.0, 34.0, }, m2, EC.EPS); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.deleteColumns(int, int)' */ @Test public void testDeleteColumns() { m2.deleteColumns(1, 2); RealMatrixTest.assertEquals("matrix as array", 3, 2, new double[] { 11.0, 14.0, 21.0, 24.0, 31.0, 34.0, }, m2, EC.EPS); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.deleteRow(int)' */ @Test public void testDeleteRow() { m2.deleteRow(1); RealMatrixTest.assertEquals("matrix as array", 2, 4, new double[] { 11.0, 12.0, 13.0, 14.0, 31.0, 32.0, 33.0, 34.0, }, m2, EC.EPS); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.deleteRows(int, int)' */ @Test public void testDeleteRows() { // FIXME does not work for high = nrows m2.deleteRows(1, 1); RealMatrixTest.assertEquals("matrix as array", 2, 4, new double[] { 11.0, 12., 13., 14.0, 31.0, 32., 33., 34.0, }, m2, EC.EPS); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.replaceColumnData(int, * RealArray)' */ @Test public void testReplaceColumnDataIntRealArray() { m2.replaceColumnData(1, new RealArray(new double[] { 19., 29., 39. })); RealMatrixTest.assertEquals("matrix as array", 3, 4, new double[] { 11.0, 19., 13., 14.0, 21.0, 29., 23., 24.0, 31.0, 39., 33., 34.0, }, m2, EC.EPS); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.replaceColumnData(int, * double[])' */ @Test public void testReplaceColumnDataIntDoubleArray() { m2.replaceColumnData(1, new double[] { 19., 29., 39. }); RealMatrixTest.assertEquals("matrix as array", 3, 4, new double[] { 11.0, 19., 13., 14.0, 21.0, 29., 23., 24.0, 31.0, 39., 33., 34.0, }, m2, EC.EPS); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.replaceColumnData(int, * RealMatrix)' */ @Test public void testReplaceColumnDataIntRealMatrix() { RealMatrix m = new RealMatrix(3, 2, new double[] { 72., 73., 82., 83., 92., 93. }); logger.info("\n--OK replace-- 1 " + m + "\n----"); m2.replaceColumnData(1, m); RealMatrix expect = new RealMatrix(3, 4, new double[] { 11.0, 72.0, 73.0, 14.0, 21.0, 82.0, 83.0, 24.0, 31.0, 92.0, 93.0, 34.0, }); Assert.assertNotNull("test should not be null (" + "matrix as array" + EC.S_RBRAK, m2); Assert.assertNotNull("expected should not be null (" + "matrix as array" + EC.S_RBRAK, expect); Assert.assertNotNull("expected should have columns (" + "matrix as array" + EC.S_RBRAK, expect.getCols()); Assert.assertNotNull("expected should have rows (" + "matrix as array" + EC.S_RBRAK, expect.getRows()); Assert.assertNotNull("test should have columns (" + "matrix as array" + EC.S_RBRAK, m2 .getCols()); Assert.assertNotNull("test should have rows (" + "matrix as array" + EC.S_RBRAK, m2 .getRows()); Assert.assertEquals("rows should be equal (" + "matrix as array" + EC.S_RBRAK, m2 .getRows(), expect.getRows()); Assert.assertEquals("columns should be equal (" + "matrix as array" + EC.S_RBRAK, m2 .getCols(), expect.getCols()); DoubleTestBase.assertEquals("matrix as array", m2.getMatrixAsArray(), expect .getMatrixAsArray(), EC.EPS); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.insertColumns(int, int)' */ @Test public void testInsertColumns() { // inserts 3 empty columns m2.makeSpaceForNewColumns(1, 3); RealMatrix expect = new RealMatrix(3, 7, new double[] { 11.0, 0.0, 0.0, 0.0, 12.0, 13.0, 14.0, 21.0, 0.0, 0.0, 0.0, 22.0, 23.0, 24.0, 31.0, 0.0, 0.0, 0.0, 32.0, 33.0, 34.0, }); Assert.assertNotNull("test should not be null (" + "matrix as array" + EC.S_RBRAK, m2); Assert.assertNotNull("expected should not be null (" + "matrix as array" + EC.S_RBRAK, expect); Assert.assertNotNull("expected should have columns (" + "matrix as array" + EC.S_RBRAK, expect.getCols()); Assert.assertNotNull("expected should have rows (" + "matrix as array" + EC.S_RBRAK, expect.getRows()); Assert.assertNotNull("test should have columns (" + "matrix as array" + EC.S_RBRAK, m2 .getCols()); Assert.assertNotNull("test should have rows (" + "matrix as array" + EC.S_RBRAK, m2 .getRows()); Assert.assertEquals("rows should be equal (" + "matrix as array" + EC.S_RBRAK, m2 .getRows(), expect.getRows()); Assert.assertEquals("columns should be equal (" + "matrix as array" + EC.S_RBRAK, m2 .getCols(), expect.getCols()); DoubleTestBase.assertEquals("matrix as array", m2.getMatrixAsArray(), expect .getMatrixAsArray(), EC.EPS); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.insertColumnData(int, * RealArray)' */ @Test public void testInsertColumnDataIntRealArray() { // inserts a column m2.insertColumnData(1, new RealArray(new double[] { 91., 92., 93. })); RealMatrix expect = new RealMatrix(3, 5, new double[] { 11.0, 12.0, 91.0, 13.0, 14.0, 21.0, 22.0, 92.0, 23.0, 24.0, 31.0, 32.0, 93.0, 33.0, 34.0, }); Assert.assertNotNull("test should not be null (" + "matrix as array" + EC.S_RBRAK, m2); Assert.assertNotNull("expected should not be null (" + "matrix as array" + EC.S_RBRAK, expect); Assert.assertNotNull("expected should have columns (" + "matrix as array" + EC.S_RBRAK, expect.getCols()); Assert.assertNotNull("expected should have rows (" + "matrix as array" + EC.S_RBRAK, expect.getRows()); Assert.assertNotNull("test should have columns (" + "matrix as array" + EC.S_RBRAK, m2 .getCols()); Assert.assertNotNull("test should have rows (" + "matrix as array" + EC.S_RBRAK, m2 .getRows()); Assert.assertEquals("rows should be equal (" + "matrix as array" + EC.S_RBRAK, m2 .getRows(), expect.getRows()); Assert.assertEquals("columns should be equal (" + "matrix as array" + EC.S_RBRAK, m2 .getCols(), expect.getCols()); DoubleTestBase.assertEquals("matrix as array", m2.getMatrixAsArray(), expect .getMatrixAsArray(), EC.EPS); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.insertColumnData(int, * RealMatrix)' */ @Test public void testInsertColumnDataIntRealMatrix() { logger.info("+++insertColumnData>>>"); RealMatrix insert = new RealMatrix(3, 2, new double[] { 72., 73., 82., 83., 92., 93., }); m2.insertColumnData(1, insert); RealMatrix expect = new RealMatrix(3, 6, new double[] { 11.0, 12.0, 72.0, 73.0, 13.0, 14.0, 21.0, 22.0, 82.0, 83.0, 23.0, 24.0, 31.0, 32.0, 92.0, 93.0, 33.0, 34.0, }); Assert.assertNotNull("test should not be null (" + "matrix as array" + EC.S_RBRAK, m2); Assert.assertNotNull("expected should not be null (" + "matrix as array" + EC.S_RBRAK, expect); Assert.assertNotNull("expected should have columns (" + "matrix as array" + EC.S_RBRAK, expect.getCols()); Assert.assertNotNull("expected should have rows (" + "matrix as array" + EC.S_RBRAK, expect.getRows()); Assert.assertNotNull("test should have columns (" + "matrix as array" + EC.S_RBRAK, m2 .getCols()); Assert.assertNotNull("test should have rows (" + "matrix as array" + EC.S_RBRAK, m2 .getRows()); Assert.assertEquals("rows should be equal (" + "matrix as array" + EC.S_RBRAK, m2 .getRows(), expect.getRows()); Assert.assertEquals("columns should be equal (" + "matrix as array" + EC.S_RBRAK, m2 .getCols(), expect.getCols()); DoubleTestBase.assertEquals("matrix as array", m2.getMatrixAsArray(), expect .getMatrixAsArray(), EC.EPS); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.insertRows(int, int)' */ @Test public void testInsertRows() { m2.insertRows(1, 2); RealMatrixTest.assertEquals("matrix as array", 5, 4, new double[] { 11.0, 12.0, 13.0, 14.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 21.0, 22.0, 23.0, 24.0, 31.0, 32.0, 33.0, 34.0, }, m2, EC.EPS); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.replaceRowData(int, * RealArray)' */ @Test public void testReplaceRowDataIntRealArray() { m2.replaceRowData(1, new RealArray(new double[] { 71.0, 72., 73., 74. })); RealMatrixTest.assertEquals("matrix as array", 3, 4, new double[] { 11.0, 12.0, 13.0, 14.0, 71.0, 72.0, 73.0, 74.0, 31.0, 32.0, 33.0, 34.0, }, m2, EC.EPS); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.replaceRowData(int, * double[])' */ @Test public void testReplaceRowDataIntDoubleArray() { m2.replaceRowData(1, new double[] { 71.0, 72., 73., 74. }); RealMatrixTest.assertEquals("matrix as array", 3, 4, new double[] { 11.0, 12.0, 13.0, 14.0, 71.0, 72.0, 73.0, 74.0, 31.0, 32.0, 33.0, 34.0, }, m2, EC.EPS); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.replaceRowData(int, * RealMatrix)' */ @Test public void testReplaceRowDataIntRealMatrix() { logger.info("+++replaceRowData>>>"); // FIXME RealMatrix insert = new RealMatrix(new RealMatrix(2, 4, new double[] { 71.0, 72.0, 73.0, 74.0, 81.0, 82.0, 83.0, 84.0, })); m2.replaceRowData(0, insert); RealMatrix expect = new RealMatrix(3, 4, new double[] { 11.0, 12.0, 13.0, 14.0, 71.0, 72.0, 73.0, 74.0, 81.0, 82.0, 83.0, 84.0, }); // rows 2 and 3 are not filled Assert.assertNotNull("test should not be null (" + "matrix as array" + EC.S_RBRAK, m2); Assert.assertNotNull("expected should not be null (" + "matrix as array" + EC.S_RBRAK, expect); Assert.assertNotNull("expected should have columns (" + "matrix as array" + EC.S_RBRAK, expect.getCols()); Assert.assertNotNull("expected should have rows (" + "matrix as array" + EC.S_RBRAK, expect.getRows()); Assert.assertNotNull("test should have columns (" + "matrix as array" + EC.S_RBRAK, m2 .getCols()); Assert.assertNotNull("test should have rows (" + "matrix as array" + EC.S_RBRAK, m2 .getRows()); Assert.assertEquals("rows should be equal (" + "matrix as array" + EC.S_RBRAK, m2 .getRows(), expect.getRows()); Assert.assertEquals("columns should be equal (" + "matrix as array" + EC.S_RBRAK, m2 .getCols(), expect.getCols()); DoubleTestBase.assertEquals("matrix as array", m2.getMatrixAsArray(), expect .getMatrixAsArray(), EC.EPS); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.insertRowData(int, * RealMatrix)' */ @Test public void testInsertRowDataIntRealMatrix() { // FIXME m2.insertRowData(1, new RealMatrix(2, 4, new double[] { 71.0, 72., 73., 74., 81.0, 82., 83., 84., })); RealMatrix expect = new RealMatrix(5, 4, new double[] { 11.0, 12.0, 13.0, 14.0, 21.0, 22.0, 23.0, 24.0, 71.0, 72.0, 73.0, 74.0, 81.0, 82.0, 83.0, 84.0, 31.0, 32.0, 33.0, 34.0, }); Assert.assertNotNull("test should not be null (" + "matrix as array" + EC.S_RBRAK, m2); Assert.assertNotNull("expected should not be null (" + "matrix as array" + EC.S_RBRAK, expect); Assert.assertNotNull("expected should have columns (" + "matrix as array" + EC.S_RBRAK, expect.getCols()); Assert.assertNotNull("expected should have rows (" + "matrix as array" + EC.S_RBRAK, expect.getRows()); Assert.assertNotNull("test should have columns (" + "matrix as array" + EC.S_RBRAK, m2 .getCols()); Assert.assertNotNull("test should have rows (" + "matrix as array" + EC.S_RBRAK, m2 .getRows()); Assert.assertEquals("rows should be equal (" + "matrix as array" + EC.S_RBRAK, m2 .getRows(), expect.getRows()); Assert.assertEquals("columns should be equal (" + "matrix as array" + EC.S_RBRAK, m2 .getCols(), expect.getCols()); DoubleTestBase.assertEquals("matrix as array", m2.getMatrixAsArray(), expect .getMatrixAsArray(), EC.EPS); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.insertRowData(int, * RealArray)' */ @Test public void testInsertRowDataIntRealArray() { m2.insertRowData(1, new RealArray(new double[] { 71.0, 72., 73., 74., })); RealMatrixTest.assertEquals("matrix as array", 4, 4, new double[] { 11.0, 12.0, 13.0, 14.0, 21.0, 22.0, 23.0, 24.0, 71.0, 72.0, 73.0, 74.0, 31.0, 32.0, 33.0, 34.0, }, m2, EC.EPS); } /** * Test method for * 'org.xmlcml.euclid.RealMatrix.appendColumnData(RealArray)' */ @Test public void testAppendColumnDataRealArray() { m2.appendColumnData(new RealArray(new double[] { 17., 27., 37., })); RealMatrixTest.assertEquals("matrix as array", 3, 5, new double[] { 11.0, 12.0, 13.0, 14.0, 17.0, 21.0, 22.0, 23.0, 24.0, 27.0, 31.0, 32.0, 33.0, 34.0, 37.0 }, m2, EC.EPS); } /** * Test method for * 'org.xmlcml.euclid.RealMatrix.appendColumnData(RealMatrix)' */ @Test public void testAppendColumnDataRealMatrix() { // logger.info("+++appendColumnData>>>"); RealMatrix rm = new RealMatrix(3, 2, new double[] { 17., 18., 27., 28., 37., 38. }); m2.appendColumnData(rm); RealMatrix expect = new RealMatrix(3, 6, new double[] { 11.0, 12.0, 13.0, 14.0, 17.0, 18.0, 21.0, 22.0, 23.0, 24.0, 27.0, 28.0, 31.0, 32.0, 33.0, 34.0, 37.0, 38.0 }); Assert.assertNotNull("test should not be null (" + "matrix as array" + EC.S_RBRAK, m2); Assert.assertNotNull("expected should not be null (" + "matrix as array" + EC.S_RBRAK, expect); Assert.assertNotNull("expected should have columns (" + "matrix as array" + EC.S_RBRAK, expect.getCols()); Assert.assertNotNull("expected should have rows (" + "matrix as array" + EC.S_RBRAK, expect.getRows()); Assert.assertNotNull("test should have columns (" + "matrix as array" + EC.S_RBRAK, m2 .getCols()); Assert.assertNotNull("test should have rows (" + "matrix as array" + EC.S_RBRAK, m2 .getRows()); Assert.assertEquals("rows should be equal (" + "matrix as array" + EC.S_RBRAK, m2 .getRows(), expect.getRows()); Assert.assertEquals("columns should be equal (" + "matrix as array" + EC.S_RBRAK, m2 .getCols(), expect.getCols()); DoubleTestBase.assertEquals("matrix as array", m2.getMatrixAsArray(), expect .getMatrixAsArray(), EC.EPS); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.appendRowData(RealArray)' */ @Test public void testAppendRowDataRealArray() { RealArray ra = new RealArray(new double[] { 41., 42., 43., 44. }); m2.appendRowData(ra); // fails to insert data RealMatrixTest.assertEquals("matrix as array", 4, 4, new double[] { 11.0, 12.0, 13.0, 14.0, 21.0, 22.0, 23.0, 24.0, 31.0, 32.0, 33.0, 34.0, 41.0, 42.0, 43.0, 44.0 }, m2, EC.EPS); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.appendRowData(RealMatrix)' */ @Test public void testAppendRowDataRealMatrix() { logger.info("+++appendRowData>>>"); // FIXME RealMatrix rm = new RealMatrix(2, 4, new double[] { 41., 42., 43., 44., 51., 52., 53., 54. }); m2.appendRowData(rm); RealMatrix expect = new RealMatrix(5, 4, new double[] { 11.0, 12.0, 13.0, 14.0, 21.0, 22.0, 23.0, 24.0, 31.0, 32.0, 33.0, 34.0, 41.0, 42.0, 43.0, 44.0, 51.0, 52.0, 53.0, 54.0 }); Assert.assertNotNull("test should not be null (" + "matrix as array" + EC.S_RBRAK, m2); Assert.assertNotNull("expected should not be null (" + "matrix as array" + EC.S_RBRAK, expect); Assert.assertNotNull("expected should have columns (" + "matrix as array" + EC.S_RBRAK, expect.getCols()); Assert.assertNotNull("expected should have rows (" + "matrix as array" + EC.S_RBRAK, expect.getRows()); Assert.assertNotNull("test should have columns (" + "matrix as array" + EC.S_RBRAK, m2 .getCols()); Assert.assertNotNull("test should have rows (" + "matrix as array" + EC.S_RBRAK, m2 .getRows()); Assert.assertEquals("rows should be equal (" + "matrix as array" + EC.S_RBRAK, m2 .getRows(), expect.getRows()); Assert.assertEquals("columns should be equal (" + "matrix as array" + EC.S_RBRAK, m2 .getCols(), expect.getCols()); DoubleTestBase.assertEquals("matrix as array", m2.getMatrixAsArray(), expect .getMatrixAsArray(), EC.EPS); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.replaceSubMatrixData(int, * int, RealMatrix)' */ @Test public void testReplaceSubMatrixData() { RealMatrix rm = new RealMatrix(2, 2, new double[] { 71., 72., 81., 82. }); m2.replaceSubMatrixData(1, 1, rm); // fails to insert data RealMatrixTest.assertEquals("matrix as array", 3, 4, new double[] { 71.0, 72.0, 13.0, 14.0, 81.0, 82.0, 23.0, 24.0, 31.0, 32.0, 33.0, 34.0, }, m2, EC.EPS); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.reorderColumnsBy(IntSet)' */ @Test public void testReorderColumnsBy() { RealMatrix mm = m2 .reorderColumnsBy(new IntSet(new int[] { 3, 1, 2, 0 })); // fails to insert data RealMatrixTest.assertEquals("matrix as array", 3, 4, new double[] { 14.0, 12.0, 13.0, 11.0, 24.0, 22.0, 23.0, 21.0, 34.0, 32.0, 33.0, 31.0 }, mm, EC.EPS); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.reorderRowsBy(IntSet)' */ @Test public void testReorderRowsBy() { RealMatrix mm = m2.reorderRowsBy(new IntSet(new int[] { 1, 2, 0 })); // fails to insert data RealMatrixTest.assertEquals("matrix as array", 3, 4, new double[] { 21.0, 22.0, 23.0, 24.0, 31.0, 32.0, 33.0, 34.0, 11.0, 12.0, 13.0, 14.0, }, mm, EC.EPS); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.extractSubMatrixData(int, * int, int, int)' */ @Test public void testExtractSubMatrixData() { RealMatrix mm = m2.extractSubMatrixData(1, 2, 2, 3); RealMatrixTest.assertEquals("sub matrix", 2, 2, new double[] { 23.0, 24.0, 33.0, 34.0 }, mm, EC.EPS); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.extractColumns(int, int)' */ @Test public void testExtractColumns() { Real2Array mm = m2.extractColumns(1, 3); RealArrayTest.assertEquals("extract columns", new double[] { 12.0, 22.0, 32.0 }, mm.getXArray(), EC.EPS); RealArrayTest.assertEquals("extract columns", new double[] { 14.0, 24.0, 34.0 }, mm.getYArray(), EC.EPS); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.extractRows(int, int)' */ @Test public void testExtractRows() { Real2Array mm = m2.extractRows(2, 0); RealArrayTest.assertEquals("extract rows", new double[] { 31.0, 32.0, 33.0, 34.0 }, mm.getXArray(), EC.EPS); RealArrayTest.assertEquals("extract rows", new double[] { 11.0, 12.0, 13.0, 14.0 }, mm.getYArray(), EC.EPS); } /** * Test method for 'org.xmlcml.euclid.RealMatrix.elementsInRange(RealRange)' */ @Test public void testElementsInRange() { IntMatrix im = m2.elementsInRange(new RealRange(13.1, 31.1)); String s = Int.testEquals((new int[] { 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0 }), im.getMatrixAsArray()); if (s != null) { Assert.fail("sub matrix" + "; " + s); } } /** * Test method for 'org.xmlcml.euclid.RealMatrix.writeXML(Writer)' */ @Test public void testWriteXML() { StringWriter w = new StringWriter(); try { m2.writeXML(w); w.close(); } catch (IOException e) { throw new EuclidRuntimeException("should never throw " + e); } Assert .assertEquals( "writeXML", "11.0 12.0 13.0 14.0 21.0 22.0 23.0 24.0 31.0 32.0 33.0 34.0", w.toString()); } } wwmm-euclid-87e8f785a814/src/test/java/org/xmlcml/euclid/test/RealRangeTest.java0000644000000000000000000001556611607017524025520 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid.test; import static org.xmlcml.euclid.EC.EPS; import org.apache.log4j.Logger; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.xmlcml.euclid.IntRange; import org.xmlcml.euclid.RealRange; /** * tests RealRange. * * @author pmr * */ public class RealRangeTest { @SuppressWarnings("unused") private static Logger LOG = Logger.getLogger(RealRangeTest.class); RealRange r0; RealRange r1; RealRange r2; /** * tests equality of ranges. * * @param msg * message * @param ref * @param r * @param epsilon */ public static void assertEquals(String msg, RealRange ref, RealRange r, double epsilon) { Assert.assertEquals(msg + " min", r.getMin(), ref.getMin(), epsilon); Assert.assertEquals(msg + " max", r.getMax(), ref.getMax(), epsilon); } /** * setup. * * @throws Exception */ @Before public void setUp() throws Exception { r0 = new RealRange(); r1 = new RealRange(1.0, 1.0); r2 = new RealRange(1.0, 3.0); } /** * Test method for 'org.xmlcml.euclid.RealRange.RealRange()' */ @Test public void testRealRange() { Assert.assertEquals("empty", "NULL", r0.toString()); } /** * Test method for 'org.xmlcml.euclid.RealRange.RealRange(double, double)' */ @Test public void testRealRangeRealReal() { Assert.assertEquals("i1", "(1.0,1.0)", r1.toString()); Assert.assertEquals("i2", "(1.0,3.0)", r2.toString()); } /** * Test method for 'org.xmlcml.euclid.RealRange.RealRange(RealRange)' */ @Test public void testRealRangeRealRange() { RealRange ii = new RealRange(r2); Assert.assertEquals("ii", "(1.0,3.0)", ii.toString()); } /** * Test method for 'org.xmlcml.euclid.RealRange.isValid()' */ @Test public void testIsValid() { Assert.assertTrue("valid", r2.isValid()); Assert.assertFalse("invalid", r0.isValid()); } /** * Test method for 'org.xmlcml.euclid.RealRange.isEqualTo(RealRange)' */ @Test public void testIsEqualTo() { Assert.assertTrue("equal", r2.isEqualTo(r2, 0.001)); Assert.assertFalse("equal", r2.isEqualTo(r0, 0.001)); Assert.assertFalse("equal", r0.isEqualTo(r0, 0.001)); } /** * Test method for 'org.xmlcml.euclid.RealRange.plus(RealRange)' */ @Test public void testPlus() { RealRange ix = new RealRange(1.0, 4.0); RealRange iy = new RealRange(2.0, 3.0); RealRange ii = ix.plus(iy); Assert.assertEquals("ii", "(1.0,4.0)", ii.toString()); iy = new RealRange(0, 2); ii = ix.plus(iy); Assert.assertEquals("ii", "(0.0,4.0)", ii.toString()); iy = new RealRange(2.0, 6.0); ii = ix.plus(iy); Assert.assertEquals("ii", "(1.0,6.0)", ii.toString()); iy = new RealRange(); ii = ix.plus(iy); Assert.assertEquals("ii", "(1.0,4.0)", ii.toString()); // RealRange r1 = new RealRange(-1,2); RealRange r2 = new RealRange(-3,-4); // invalid RealRange r = r1.plus(r2); Assert.assertTrue("r1+r2", r.isEqualTo(new RealRange(-1, 2), 0.0001)); r1 = new RealRange(-1,2); r2 = new RealRange(-4,-3); // invalid r = r1.plus(r2); Assert.assertTrue("r1+r2", r.isEqualTo(new RealRange(-4, 2), 0.0001)); r1 = new RealRange(-1,2); r2 = new RealRange(-4,3); // invalid r = r1.plus(r2); Assert.assertTrue("r1+r2", r.isEqualTo(new RealRange(-4, 3), 0.0001)); } /** * Test method for * 'org.xmlcml.euclid.RealRange.doubleersectionWith(RealRange)' */ @Test public void testIntsectionWith() { RealRange ix = new RealRange(1.0, 4.0); RealRange iy = new RealRange(2.0, 3.0); RealRange ii = ix.intersectionWith(iy); Assert.assertEquals("ii", "(2.0,3.0)", ii.toString()); iy = new RealRange(0.0, 2.0); ii = ix.intersectionWith(iy); Assert.assertEquals("ii", "(1.0,2.0)", ii.toString()); iy = new RealRange(2.0, 6.0); ii = ix.intersectionWith(iy); Assert.assertEquals("ii", "(2.0,4.0)", ii.toString()); iy = new RealRange(); ii = ix.intersectionWith(iy); Assert.assertNull("ii", ii); } /** * Test method for 'org.xmlcml.euclid.RealRange.getMin()' */ @Test public void testGetMin() { Assert.assertEquals("min", 1.0, r2.getMin(), EPS); } /** * Test method for 'org.xmlcml.euclid.RealRange.getMax()' */ @Test public void testGetMax() { Assert.assertEquals("max", 3.0, r2.getMax(), EPS); } /** * Test method for 'org.xmlcml.euclid.RealRange.getRange()' */ @Test public void testGetRange() { Assert.assertEquals("range", 2.0, r2.getRange(), EPS); } /** * Test method for 'org.xmlcml.euclid.RealRange.includes(RealRange)' */ @Test public void testIncludesRealRange() { Assert.assertTrue("includes", r2.includes(new RealRange(2.0, 3.0))); Assert.assertFalse("includes", r2.includes(new RealRange(0.0, 3.0))); } /** * Test method for 'org.xmlcml.euclid.RealRange.includes(double)' */ @Test public void testIncludesReal() { Assert.assertTrue("includes", r2.includes(1.0)); Assert.assertFalse("includes", r2.includes(0.0)); } /** * Test method for 'org.xmlcml.euclid.RealRange.contains(double)' */ @Test public void testContains() { Assert.assertTrue("contains", r2.contains(1.0)); Assert.assertFalse("contains", r2.contains(0.0)); } /** * Test method for 'org.xmlcml.euclid.RealRange.add(double)' */ @Test public void testAdd() { r2.add(2); Assert.assertEquals("ii", "(1.0,3.0)", r2.toString()); r2.add(0); Assert.assertEquals("ii", "(0.0,3.0)", r2.toString()); r2.add(9); Assert.assertEquals("ii", "(0.0,9.0)", r2.toString()); } /** * test getting a random variate. tests limits only */ @Test public void testGetRandomVariate() { RealRange range = new RealRange(10, 20); double sum = 0.0; for (int i = 0; i < 100; i++) { double d = range.getRandomVariate(); Assert.assertTrue("limit: ", d >= 10. && d <= 20.); sum += d; } // LOG.debug(sum); // crude check Assert.assertTrue("distribution", sum > 1400 && sum < 1600); } /** * Test method for 'org.xmlcml.euclid.RealRange.RealRange(IntRange)' */ @Test public void testRealRangeIntRange() { RealRange r = new RealRange(new IntRange(1, 2)); Assert.assertEquals("int", "(1.0,2.0)", r.toString()); } } wwmm-euclid-87e8f785a814/src/test/java/org/xmlcml/euclid/test/RealSquareMatrixTest.java0000644000000000000000000004361111607017524027101 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid.test; import static org.xmlcml.euclid.EC.EPS; import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.xmlcml.euclid.EC; import org.xmlcml.euclid.EuclidTestUtils; import org.xmlcml.euclid.RealArray; import org.xmlcml.euclid.RealMatrix; import org.xmlcml.euclid.RealSquareMatrix; /** * tests RealSquareMatrix. * * @author pmr * */ public class RealSquareMatrixTest extends MatrixTest { static Logger logger = Logger.getLogger(RealSquareMatrixTest.class); RealSquareMatrix m0; RealSquareMatrix m1; RealSquareMatrix m2; /** * setup. * * @throws Exception */ @Before public void setUp() throws Exception { super.setUp(); logger.setLevel(Level.WARN); m0 = new RealSquareMatrix(); m1 = new RealSquareMatrix(3); m2 = new RealSquareMatrix(3, new double[] { 11., 12., 13., 21., 22., 23., 31., 32., 33., }); } /** * equality test. true if both args not null and equal within epsilon and * rows are present and equals and columns are present and equals * * @param msg * message * @param test * @param expected * @param epsilon */ public static void assertEquals(String msg, RealSquareMatrix test, RealSquareMatrix expected, double epsilon) { Assert.assertNotNull("test should not be null (" + msg + EC.S_RBRAK, test); Assert.assertNotNull("expected should not be null (" + msg + EC.S_RBRAK, expected); Assert.assertNotNull("expected should have columns (" + msg + EC.S_RBRAK, expected.getCols()); Assert.assertNotNull("expected should have rows (" + msg + EC.S_RBRAK, expected.getRows()); Assert.assertNotNull("test should have columns (" + msg + EC.S_RBRAK, test .getCols()); Assert.assertNotNull("test should have rows (" + msg + EC.S_RBRAK, test .getRows()); Assert.assertEquals("rows should be equal (" + msg + EC.S_RBRAK, test .getRows(), expected.getRows()); Assert.assertEquals("columns should be equal (" + msg + EC.S_RBRAK, test .getCols(), expected.getCols()); DoubleTestBase.assertEquals(msg, test.getMatrixAsArray(), expected .getMatrixAsArray(), epsilon); } /** * equality test. true if both args not null and equal within epsilon * * @param msg * message * @param rows * @param test * @param expected * @param epsilon */ public static void assertEquals(String msg, int rows, double[] test, RealSquareMatrix expected, double epsilon) { Assert.assertNotNull("test should not be null (" + msg + EC.S_RBRAK, test); Assert.assertNotNull("ref should not be null (" + msg + EC.S_RBRAK, expected); Assert.assertEquals("rows should be equal (" + msg + EC.S_RBRAK, rows, expected.getRows()); DoubleTestBase.assertEquals(msg, test, expected.getMatrixAsArray(), epsilon); } /** * Test method for 'org.xmlcml.euclid.RealSquareMatrix.isOrthogonal()' */ @Test public void testIsOrthogonal() { Assert.assertFalse("isOrthogonal", m2.isOrthogonal()); RealSquareMatrix m = new RealSquareMatrix(3, new double[] { 0, 1, 0, -1, 0, 0, 0, 0, 1, }); Assert.assertTrue("isOrthogonal", m.isOrthogonal()); } /** * Test method for 'org.xmlcml.euclid.RealSquareMatrix.RealSquareMatrix()' */ @Test public void testRealSquareMatrix() { Assert.assertEquals("real square matrix", 0, m0.getRows()); Assert.assertEquals("real square matrix", 0, m0.getCols()); } /** * Test method for * 'org.xmlcml.euclid.RealSquareMatrix.RealSquareMatrix(int)' */ @Test public void testRealSquareMatrixInt() { Assert.assertEquals("real square matrix", 3, m1.getRows()); Assert.assertEquals("real square matrix", 3, m1.getCols()); } /** * Test method for * 'org.xmlcml.euclid.RealSquareMatrix.outerProduct(RealArray)' */ @Test public void testOuterProduct() { RealArray ra = new RealArray(3, new double[] { 1, 2, 3 }); RealSquareMatrix rsm = RealSquareMatrix.outerProduct(ra); RealMatrix rm = null; rm = new RealMatrix(3, 3, new double[] { 1.0, 2.0, 3.0, 2.0, 4.0, 6.0, 3.0, 6.0, 9.0, }); MatrixTest.assertEquals("outer product", rm, (RealMatrix) rsm, EPS); } /** * Test method for 'org.xmlcml.euclid.RealSquareMatrix.diagonal(RealArray)' */ @Test public void testDiagonal() { RealArray ra = new RealArray(3, new double[] { 1, 2, 3 }); RealMatrix rsm = RealSquareMatrix.diagonal(ra); RealMatrix rm = null; rm = new RealMatrix(3, 3, new double[] { 1, 0, 0, 0, 2, 0, 0, 0, 3, }); MatrixTest.assertEquals("diagonal", rm, (RealMatrix) rsm, EPS); } /** * Test method for 'org.xmlcml.euclid.RealSquareMatrix.RealSquareMatrix(int, * double[])' */ @Test public void testRealSquareMatrixIntDoubleArray() { RealMatrix rm = new RealMatrix(3, 3, new double[] { 1.0, 2.0, 3.0, 2.0, 4.0, 6.0, 3.0, 6.0, 9.0, }); RealSquareMatrix rsm = new RealSquareMatrix(3, new double[] { 1.0, 2.0, 3.0, 2.0, 4.0, 6.0, 3.0, 6.0, 9.0, }); MatrixTest.assertEquals("int double[]", rm, (RealMatrix) rsm, EPS); } /** * Test method for 'org.xmlcml.euclid.RealSquareMatrix.RealSquareMatrix(int, * double)' */ @Test public void testRealSquareMatrixIntDouble() { RealMatrix rm = new RealMatrix(3, 3, 10.); RealSquareMatrix rsm = new RealSquareMatrix(3, 10.); MatrixTest.assertEquals("int double", rm, (RealMatrix) rsm, EPS); } /** * Test method for * 'org.xmlcml.euclid.RealSquareMatrix.RealSquareMatrix(RealMatrix, int, * int, int)' */ @Test public void testRealSquareMatrixRealMatrixIntIntInt() { RealMatrix rm = new RealMatrix(3, 4, new double[] { 11., 12., 13., 14., 21., 22., 23., 24., 31., 32., 33., 34. }); RealSquareMatrix rsm = new RealSquareMatrix(rm, 1, 1, 2); RealMatrix rm1 = new RealMatrix(2, 2, new double[] { 22., 23., 32., 33., }); MatrixTest.assertEquals("rsm int int int", rm1, (RealMatrix) rsm, EPS); } /** * Test method for * 'org.xmlcml.euclid.RealSquareMatrix.RealSquareMatrix(RealSquareMatrix)' */ @Test public void testRealSquareMatrixRealSquareMatrix() { RealSquareMatrix rsm = new RealSquareMatrix(m2); MatrixTest.assertEquals("copy", m2, rsm, EPS); } /** * Test method for * 'org.xmlcml.euclid.RealSquareMatrix.RealSquareMatrix(RealMatrix)' */ @Test public void testRealSquareMatrixRealMatrix() { RealMatrix rm = new RealMatrix(2, 2, new double[] { 22., 23., 32., 33., }); RealSquareMatrix rsm = new RealSquareMatrix(rm); MatrixTest.assertEquals("real matrix", rm, rsm, EPS); } /** * Test method for * 'org.xmlcml.euclid.RealSquareMatrix.isEqualTo(RealSquareMatrix)' */ @Test public void testIsEqualToRealSquareMatrix() { RealSquareMatrix rsm = new RealSquareMatrix(m2); Assert.assertTrue("isEqualTo", m2.isEqualTo(rsm)); } /** * Test method for * 'org.xmlcml.euclid.RealSquareMatrix.RealSquareMatrix(double[][])' */ @Test public void testRealSquareMatrixDoubleArrayArray() { double[][] mat = new double[][] { new double[] { 11., 12., 13. }, new double[] { 21., 22., 23. }, new double[] { 31., 32., 33. }, }; RealSquareMatrix rsm = new RealSquareMatrix(mat); RealMatrix rm = new RealMatrix(3, 3, new double[] { 11., 12., 13., 21., 22., 23., 31., 32., 33., }); MatrixTest.assertEquals("real matrix", rm, rsm, EPS); } /** * Test method for * 'org.xmlcml.euclid.RealSquareMatrix.plus(RealSquareMatrix)' */ @Test public void testPlusRealSquareMatrix() { RealSquareMatrix rsm = m2.plus(m2); RealMatrix rm = new RealMatrix(3, 3, new double[] { 22., 24., 26., 42., 44., 46., 62., 64., 66., }); MatrixTest.assertEquals("real matrix", rm, rsm, EPS); } /** * Test method for * 'org.xmlcml.euclid.RealSquareMatrix.subtract(RealSquareMatrix)' */ @Test public void testSubtractRealSquareMatrix() { RealSquareMatrix rsm = m2.plus(m2); RealSquareMatrix rsm1 = m2.subtract(rsm); RealMatrix rm = new RealMatrix(3, 3, new double[] { -11., -12., -13., -21., -22., -23., -31., -32., -33., }); MatrixTest.assertEquals("real matrix", rm, rsm1, EPS); } /** * Test method for * 'org.xmlcml.euclid.RealSquareMatrix.multiply(RealSquareMatrix)' */ @Test public void testMultiplyRealSquareMatrix() { RealSquareMatrix rsm = m2.multiply(m2); RealMatrix rm = new RealMatrix(3, 3, new double[] { 776.0, 812.0, 848.0, 1406.0, 1472.0, 1538.0, 2036.0, 2132.0, 2228.0, }); MatrixTest.assertEquals("real matrix", rm, rsm, EPS); } /** * Test method for 'org.xmlcml.euclid.RealSquareMatrix.determinant()' */ @Test public void testDeterminant() { RealSquareMatrix m = new RealSquareMatrix(3, new double[] { 1., 1., 1., 2., 3., 4., 3., 4., 7. }); double d = m.determinant(); Assert.assertEquals("determinant", 2., d, EPS); } /** * Test method for 'org.xmlcml.euclid.RealSquareMatrix.trace()' */ @Test public void testTrace() { RealSquareMatrix m = new RealSquareMatrix(3, new double[] { 1., 1., 1., 2., 3., 4., 3., 4., 7. }); double d = m.trace(); Assert.assertEquals("trace", 11., d, EPS); } /** * Test method for 'org.xmlcml.euclid.RealSquareMatrix.isUnit()' */ @Test public void testIsUnit() { RealSquareMatrix m = new RealSquareMatrix(3, new double[] { 1., 0., 0., 0., 1., 0., 0., 0., 1. }); Assert.assertTrue("unit", m.isUnit()); m = new RealSquareMatrix(3, new double[] { 1., 1., 1., 2., 3., 4., 3., 4., 7. }); Assert.assertFalse("unit", m.isUnit()); } /** * Test method for 'org.xmlcml.euclid.RealSquareMatrix.isSymmetric()' */ @Test public void testIsSymmetric() { RealSquareMatrix m = new RealSquareMatrix(3, new double[] { 1., 0., 3., 0., 1., 0., 3., 0., 1. }); Assert.assertTrue("unit", m.isSymmetric()); m = new RealSquareMatrix(3, new double[] { 1., 1., 1., 2., 3., 4., 3., 4., 7. }); Assert.assertFalse("unit", m.isSymmetric()); } /** * Test method for 'org.xmlcml.euclid.RealSquareMatrix.orthonormalize()' */ @Test public void testOrthonormalize() { RealSquareMatrix m = new RealSquareMatrix(3, new double[] { 1., 1., 1., 2., 3., 4., 3., 4., 7. }); Assert.assertFalse("orthonormal", m.isOrthonormal()); m.orthonormalize(); Assert.assertTrue("orthonormal", m.isOrthonormal()); RealSquareMatrix mm = new RealSquareMatrix(3, new double[] { 0.5773502691896258, 0.5773502691896258, 0.5773502691896258, -0.7071067811865477, 0.0, 0.7071067811865476, 0.40824829046386296, -0.816496580927726, 0.40824829046386313, }); MatrixTest.assertEquals("orthonormal", mm, m, EPS); } /** * Test method for 'org.xmlcml.euclid.RealSquareMatrix.isUpperTriangular()' */ @Test public void testIsUpperTriangular() { RealSquareMatrix m = new RealSquareMatrix(3, new double[] { 0., 2., 3., 0., 0., 2., 0., 0., 0. }); Assert.assertTrue("upper triangular", m.isUpperTriangular()); m = new RealSquareMatrix(3, new double[] { 1., 2., 3., 0., 1., 2., 0., 0., 1. }); Assert.assertTrue("upper triangular", m.isUpperTriangular()); m = new RealSquareMatrix(3, new double[] { 1., 1., 1., 2., 3., 4., 3., 4., 7. }); Assert.assertFalse("upper triangular false", m.isUpperTriangular()); } /** * Test method for 'org.xmlcml.euclid.RealSquareMatrix.isLowerTriangular()' */ @Test public void testIsLowerTriangular() { RealSquareMatrix m = new RealSquareMatrix(3, new double[] { 0., 0., 0., 2., 0., 0., 3., 2., 0. }); Assert.assertTrue("lower triangular", m.isLowerTriangular()); m = new RealSquareMatrix(3, new double[] { 1., 0., 0., 2., 1., 0., 3., 2., 1. }); Assert.assertTrue("lower triangular", m.isLowerTriangular()); m = new RealSquareMatrix(3, new double[] { 1., 1., 1., 2., 3., 4., 3., 4., 7. }); Assert.assertFalse("lower triangular false", m.isLowerTriangular()); } /** * Test method for 'org.xmlcml.euclid.RealSquareMatrix.isImproperRotation()' */ @Test public void testIsImproperRotation() { RealSquareMatrix m = new RealSquareMatrix(3, new double[] { 1., 0., 0., 0., 1., 0., 0., 0., -1. }); Assert.assertTrue("isImproper", m.isImproperRotation()); m = new RealSquareMatrix(3, new double[] { 1., 0., 0., 0., -1., 0., 0., 0., -1. }); Assert.assertFalse("isImproper", m.isImproperRotation()); } /** * Test method for 'org.xmlcml.euclid.RealSquareMatrix.isUnitary()' */ @Test public void testIsUnitary() { RealSquareMatrix m = new RealSquareMatrix(3, new double[] { 1., 0., 0., 0., 1., 0., 0., 0., -1. }); Assert.assertTrue("isUnitary", m.isUnitary()); m = new RealSquareMatrix(3, new double[] { 1., 0., 0., 0., -1., 0., 0., 0., -1. }); Assert.assertTrue("isUnitary", m.isUnitary()); m = new RealSquareMatrix(3, new double[] { 1., 0., 1., 0., -1., 0., 0., 0., -1. }); Assert.assertFalse("isUnitary", m.isUnitary()); } /** * Test method for 'org.xmlcml.euclid.RealSquareMatrix.copyUpperToLower()' */ @Test public void testCopyUpperToLower() { RealSquareMatrix m = new RealSquareMatrix(3, new double[] { 6., 7., 8., 2., 5., 4., 3., 2., 9. }); m.copyUpperToLower(); RealSquareMatrix mm = new RealSquareMatrix(3, new double[] { 6., 7., 8., 7., 5., 4., 8., 4., 9. }); MatrixTest.assertEquals("copy upper", mm, m, EPS); } /** * Test method for 'org.xmlcml.euclid.RealSquareMatrix.copyLowerToUpper()' */ @Test public void testCopyLowerToUpper() { RealSquareMatrix m = new RealSquareMatrix(3, new double[] { 6., 7., 8., 2., 5., 4., 3., 2., 9. }); m.copyLowerToUpper(); RealSquareMatrix mm = new RealSquareMatrix(3, new double[] { 6., 2., 3., 2., 5., 2., 3., 2., 9. }); MatrixTest.assertEquals("copy upper", mm, m, EPS); } /** * Test method for 'org.xmlcml.euclid.RealSquareMatrix.lowerTriangle()' */ @Test public void testLowerTriangle() { RealSquareMatrix m = new RealSquareMatrix(3, new double[] { 6., 7., 8., 2., 5., 4., 3., 2., 9. }); RealArray ra = m.lowerTriangle(); RealArrayTest.assertEquals("lower triangle", new double[] { 6.0, 2.0, 5.0, 3.0, 2.0, 9.0 }, ra, EPS); } /** * Test method for 'org.xmlcml.euclid.RealSquareMatrix.transpose()' */ @Test public void testTranspose() { RealSquareMatrix m = new RealSquareMatrix(3, new double[] { 6., 7., 8., 2., 5., 4., 3., 1., 9. }); m.transpose(); RealSquareMatrix mm = new RealSquareMatrix(3, new double[] { 6., 2., 3., 7., 5., 1., 8., 4., 9. }); MatrixTest.assertEquals("transpose", mm, m, EPS); } /** * Test method for 'org.xmlcml.euclid.RealSquareMatrix.orthogonalise()' */ @Test public void testOrthogonalise() { RealSquareMatrix m = new RealSquareMatrix(3, new double[] { 6., 7., 8., 7., 5., 4., 8., 4., 9. }); m.orthogonalise(); Assert.assertTrue("orthogonalise", m.isOrthogonal()); RealSquareMatrix mm = new RealSquareMatrix(3, new double[] { 6.0, 7.0, 8.0, 7.7316819236624434, -0.35776420212319654, -5.485717765889034, 3.8939506336049337, -10.383868356279821, 6.1654218365411415, }); MatrixTest.assertEquals("orthogonalise", mm, m, 0.000000000001); } /** * Test method for * 'org.xmlcml.euclid.RealSquareMatrix.getCrystallographicOrthogonalisation(double[ * ] , double[])' */ @Test public void testGetCrystallographicOrthogonalisation() { double[] len = { 10., 11., 12. }; double[] ang = { 80., 90., 100. }; // degrees! RealSquareMatrix m = RealSquareMatrix .getCrystallographicOrthogonalisation(len, ang); RealSquareMatrix mm = new RealSquareMatrix(3, new double[] { 9.843316493307713, 0.0, 0.0, -1.7632698070846495, 10.832885283134289, 0.0, 0.0, 1.9101299543362344, 12.0 }); MatrixTest.assertEquals("orthogonalise", mm, m, 0.000000000001); } /** * Test method for 'org.xmlcml.euclid.RealSquareMatrix.getInverse()' */ @Test public void testGetInverse() { RealSquareMatrix m = new RealSquareMatrix(3, new double[] { 6., 7., 8., 2., 5., 4., 1., 3., 9. }); RealSquareMatrix inv = m.getInverse(); RealSquareMatrix mm = new RealSquareMatrix(3, new double[] { 0.3055555555555556, -0.36111111111111116, -0.11111111111111108, -0.12962962962962962, 0.42592592592592593, -0.07407407407407408, 0.009259259259259259, -0.10185185185185185, 0.14814814814814814, }); MatrixTest.assertEquals("inverse", mm, inv, 0.000000000001); } @Test public void calculateEigenvalues() { RealSquareMatrix m = new RealSquareMatrix(3, new double[] { 1., 2., 3., 2., 1., 8., 3., 8., 7. }); RealArray realArray = m.calculateEigenvalues(); double[] expected = new double[]{13.57729611363183,-0.03241110263496161,-4.54488501099687}; EuclidTestUtils.testEquals("inverse", expected, realArray.getArray(), 0.0000001); } @Test public void calculateInverse() { RealSquareMatrix m = new RealSquareMatrix(3, new double[] { 1., 2., 3., 2., 1., 8., 3., 8., 7. }); RealSquareMatrix expected = new RealSquareMatrix(3, new double[] { -28.5, 5.0, 6.5, 5.0, -1.0, -1.0, 6.5, -1.0, -1.5 }); RealSquareMatrix rsm = m.calculateInverse(); EuclidTestUtils.testEquals("inverse", expected.getMatrix(), rsm.getMatrix(), 0.0000001); RealSquareMatrix one = m.multiply(rsm); Assert.assertNotNull(one); } } wwmm-euclid-87e8f785a814/src/test/java/org/xmlcml/euclid/test/RealTest.java0000644000000000000000000000267211607017524024535 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid.test; import static org.xmlcml.euclid.EC.EPS; import org.junit.Test; import org.xmlcml.euclid.Real; /** * test Real. * * @author pmr * */ public class RealTest { /** * Test method for 'org.xmlcml.euclid.Real.zeroArray(double, double[])' */ @Test public void testZeroArray() { double[] rr = new double[5]; Real.zeroArray(5, rr); DoubleTestBase.assertEquals("double[] ", new double[] { 0.0, 0.0, 0.0, 0.0, 0.0 }, rr, EPS); } /** * Test method for 'org.xmlcml.euclid.Real.initArray(double, double[], * double)' */ @Test public void testInitArray() { double[] rr = new double[5]; Real.initArray(5, rr, 3.0); DoubleTestBase.assertEquals("double[] ", new double[] { 3.0, 3.0, 3.0, 3.0, 3.0 }, rr, EPS); } } wwmm-euclid-87e8f785a814/src/test/java/org/xmlcml/euclid/test/Transform2Test.java0000644000000000000000000002625011607017524025705 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid.test; import static org.xmlcml.euclid.EC.EPS; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.xmlcml.euclid.Angle; import org.xmlcml.euclid.EC; import org.xmlcml.euclid.EuclidRuntimeException; import org.xmlcml.euclid.Real2; import org.xmlcml.euclid.RealSquareMatrix; import org.xmlcml.euclid.Transform2; import org.xmlcml.euclid.Vector2; import org.xmlcml.euclid.Transform2.Type; /** * test Transform2. * * @author pmr * */ public class Transform2Test { Transform2 t0; Transform2 t1; Transform2 t2; /** * setup. * * @throws Exception */ @Before public void setUp() throws Exception { t0 = new Transform2(); t1 = new Transform2( new double[] { 0., 1., 0., -1., 0., 0., 0., 0., 1. }); t2 = new Transform2(new double[] { 1., 0., 0.7, 0., -1., 0.5, 0., 0., 1. }); } /** * equality test. true if both args not null and equal within epsilon * * @param msg * message * @param test * @param expected * @param epsilon */ public static void assertEquals(String msg, Transform2 test, Transform2 expected, double epsilon) { Assert.assertNotNull("test should not be null (" + msg + EC.S_RBRAK, test); Assert.assertNotNull("expected should not be null (" + msg + EC.S_RBRAK, expected); DoubleTestBase.assertEquals(msg, test.getMatrixAsArray(), expected .getMatrixAsArray(), epsilon); } /** * equality test. true if both args not null and equal within epsilon * * @param msg * message * @param test * 16 values * @param expected * @param epsilon */ public static void assertEquals(String msg, double[] test, Transform2 expected, double epsilon) { Assert.assertNotNull("test should not be null (" + msg + EC.S_RBRAK, test); Assert.assertEquals("test should have 16 elements (" + msg + EC.S_RBRAK, 9, test.length); Assert.assertNotNull("ref should not be null (" + msg + EC.S_RBRAK, expected); DoubleTestBase.assertEquals(msg, test, expected.getMatrixAsArray(), epsilon); } /** * Test method for 'org.xmlcml.euclid.Transform2.Transform2()' */ @Test public void testTransform2() { Assert.assertNotNull("transform2", t0); Transform2Test.assertEquals("transform2", new double[] { 1., 0., 0., 0., 1., 0., 0., 0., 1. }, t0, EPS); Assert.assertTrue("transform2", t0.getTransformationType() == Type.ANY); } /** * Test method for 'org.xmlcml.euclid.Transform2.Transform2(Vector2)' */ @Test public void testTransform2Vector2() { Vector2 v = new Vector2(1., 2.); Transform2 t = new Transform2(v); Real2 vv = t.getTranslation(); Assert.assertEquals("vector", 1., vv.getX(), EPS); Assert.assertEquals("vector", 2., vv.getY(), EPS); Assert.assertEquals("transform2", Type.ROT_TRANS.s, t .getTransformationType().s); } /** * Test method for 'org.xmlcml.euclid.Transform2.Transform2(Angle)' */ @Test public void testTransform2Angle() { Transform2 ta = new Transform2(new Angle(Math.PI / 3.)); Angle aa = ta.getAngleOfRotation(); Assert.assertEquals("transform angle", Math.PI / 3., aa.getRadian(), EPS); ta = new Transform2(new Angle(1.)); aa = ta.getAngleOfRotation(); Assert.assertEquals("transform angle", 1., aa.getRadian(), EPS); Assert.assertEquals("transform2", Type.ROT_ORIG.s, ta .getTransformationType().s); } /** * Test method for 'org.xmlcml.euclid.Transform2.Transform2(Transform2, * Real2)' */ @Test public void testTransform2Transform2Real2() { Transform2 ta = new Transform2(new Angle(Math.PI / 3.)); Transform2 tb = new Transform2(ta, new Real2(3., 4.)); // haven't checked this is right Real2 tr = tb.getTranslation(); Assert.assertEquals("vector", -1.9641016151377553, tr.getX(), EPS); Assert.assertEquals("vector", 4.598076211353316, tr.getY(), EPS); Angle aa = ta.getAngleOfRotation(); Assert.assertEquals("transform angle", Math.PI / 3., aa.getRadian(), EPS); Assert.assertEquals("transform2", Type.ROT_TRANS.s, tb .getTransformationType().s); } /** * Test method for 'org.xmlcml.euclid.Transform2.Transform2(Vector2, * Vector2)' */ @Test public void testTransform2Vector2Vector2() { Transform2 ta = new Transform2(new Vector2(1., 2.), new Vector2(3., 4.)); Transform2Test.assertEquals("transform2", new double[] { 0.9838699100999074, 0.17888543819998318, 0.0, -0.17888543819998318, 0.9838699100999074, 0.0, 0.0, 0.0, 1.0, }, ta, EPS); Assert.assertEquals("transform2", Type.ROT_ORIG.s, ta .getTransformationType().s); } /** * Test method for 'org.xmlcml.euclid.Transform2.Transform2(Real2, Real2)' */ @Test public void testTransform2Real2Real2() { Transform2 ta = null; ta = new Transform2(new Real2(1., 2.), new Real2(3., 4.)); Transform2Test.assertEquals("transform2", new double[] { 1.0, 2.0, 0.0, 3.0, 4.0, 0.0, 0.0, 0.0, 1.0, }, ta, EPS); Assert.assertEquals("transform2", Type.ROT_ORIG.s, ta .getTransformationType().s); } /** * Test method for 'org.xmlcml.euclid.Transform2.Transform2(double[])' */ @Test public void testTransform2DoubleArray() { Transform2 ta = new Transform2(new double[] { 1., 0., 1., 0., -1., 2., 0., 0., 1. }); Transform2Test.assertEquals("transform2", new double[] { 1., 0., 1., 0., -1., 2., 0., 0., 1. }, ta, EPS); Assert.assertEquals("transform2", Type.ROT_ORIG.s, ta .getTransformationType().s); } /** * Test method for 'org.xmlcml.euclid.Transform2.Transform2(Transform2)' */ @Test public void testTransform2Transform2() { Transform2 t = new Transform2(t1); Assert.assertTrue("transform", t.isEqualTo(t1)); } /** * Test method for * 'org.xmlcml.euclid.Transform2.Transform2(RealSquareMatrix)' */ @Test public void testTransform2RealSquareMatrix() { RealSquareMatrix rsm = new RealSquareMatrix(3, new double[] { 1., 0., 2., 0., 1., 3., 0., 0., 1. }); Transform2 t = new Transform2(rsm); DoubleTestBase.assertEquals("rsm", new double[] { 1., 0., 2., 0., 1., 3., 0., 0., 1. }, t.getMatrixAsArray(), EPS); Assert.assertEquals("transform2", Type.NULL.s, t .getTransformationType().s); } /** * Test method for * 'org.xmlcml.euclid.Transform2.Transform2(RealSquareMatrix, Vector2)' */ @Test public void testTransform2RealSquareMatrixVector2() { RealSquareMatrix rsm = new RealSquareMatrix(2, new double[] { 1., 0., 0., 1., }); Transform2 t = new Transform2(rsm, new Vector2(2., 3.)); Transform2Test.assertEquals("rsm", new double[] { 1., 0., 2., 0., 1., 3., 0., 0., 1. }, t, EPS); Assert.assertEquals("transform2", Type.NULL.s, t .getTransformationType().s); rsm = new RealSquareMatrix(3, new double[] { 1., 0., 2., 0., 1., 3., 0., 0., 1. }); try { t = new Transform2(rsm, new Vector2(2., 3.)); Assert.fail("should always throw " + "must have 2*2 rotation matrix"); } catch (EuclidRuntimeException e) { Assert.assertEquals("matrix vector", "must have 2*2 rotation matrix", e.getMessage()); } } /** * Test method for 'org.xmlcml.euclid.Transform2.isEqualTo(Transform2)' */ @Test public void testIsEqualToTransform2() { Transform2 t = new Transform2(t1); Assert.assertTrue("isEqualsTo", t.isEqualTo(t1)); } /** * Test method for 'org.xmlcml.euclid.Transform2.concatenate(Transform2)' */ @Test public void testConcatenate() { Transform2 t = t1.concatenate(t2); Transform2Test.assertEquals("concatenate", new double[] { 0.0, -1.0, 0.5, -1.0, 0.0, -0.7, 0.0, 0.0, 1.0, }, t, EPS); Assert.assertEquals("concatenate", Type.ROT_ORIG.s, t .getTransformationType().s); } /** * Test method for 'org.xmlcml.euclid.Transform2.setTransformationType(int)' */ @Test public void testSetTransformationType() { Transform2 t = t1.concatenate(t2); t.setTransformationType(Type.ROT_TRANS); Assert.assertEquals("setType", Type.ROT_TRANS.s, t .getTransformationType().s); } /** * Test method for 'org.xmlcml.euclid.Transform2.checkMatrix()' */ @Test public void testCheckMatrix() { // not sure this works Transform2 t = new Transform2(new double[] { 0., 1., 0., -1., 0., 0., 0., 0., 1. }); Assert .assertEquals("getType", Type.NULL.s, t.getTransformationType().s); t = new Transform2(new double[] { 1., 0., 0., 0., 1., 0., 0., 0., 1. }); Assert .assertEquals("getType", Type.NULL.s, t.getTransformationType().s); t = new Transform2(new double[] { 1., 0., 2., 0., 1., 3., 0., 0., 1. }); Assert .assertEquals("getType", Type.NULL.s, t.getTransformationType().s); } /** * Test method for 'org.xmlcml.euclid.Transform2.getAngleOfRotation()' */ @Test public void testGetAngleOfRotation() { Transform2 t = new Transform2(new double[] { 0., 1., 0., -1., 0., 0., 0., 0., 1. }); Angle a = t.getAngleOfRotation(); Assert.assertEquals("getAngle", Math.PI / 2., a.getRadian(), EPS); } /** * Test method for 'org.xmlcml.euclid.Transform2.flipAboutVector(Real2)' */ @Test public void testFlipAboutVector() { Transform2 t = Transform2.flipAboutVector(new Vector2(1., 1.)); DoubleTestBase.assertEquals("flip", new double[] { 0.0, 1., 0.0, 1., 0.0, 0.0, 0.0, 0.0, 1.0, }, t.getMatrixAsArray(), 0.0000000001); } /** * Test method for 'org.xmlcml.euclid.Transform2.getTranslation()' */ @Test public void testGetTranslation() { Real2 v = t2.getTranslation(); Assert.assertEquals("translation", 0.7, v.getX(), EPS); Assert.assertEquals("translation", 0.5, v.getY(), EPS); } /** * Test method for 'org.xmlcml.euclid.Transform2.getCentreOfRotation()' */ /** * -- not yet written * * @Test public void testGetCentreOfRotation() { Transform2 t = null; try { * t = new Transform2(new double[]{ 0., 1., 2., -1., 0., 3., 0., 0., * 1. }); } catch (EuclidException e) { neverFail(e); } Real2 r = * t.getCentreOfRotation(); Angle a = t.getAngleOfRotation(); * Assert.assertEquals("getAngle", Math.PI/2., a.getRadian(), EPS); } * -- */ /** * Test method for 'org.xmlcml.euclid.Transform2.getRotationMatrix()' */ @Test public void testGetRotationMatrix() { Transform2 t = new Transform2(new double[] { 0., 1., 2., -1., 0., 3., 0., 0., 1. }); RealSquareMatrix rsm = t.getRotationMatrix(); DoubleTestBase.assertEquals("getRotationMatrix", new double[] { 0.0, 1.0, -1.0, 0.0, }, rsm.getMatrixAsArray(), EPS); } } wwmm-euclid-87e8f785a814/src/test/java/org/xmlcml/euclid/test/Transform3Test.java0000644000000000000000000003036011607017524025703 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid.test; import static org.xmlcml.euclid.EC.EPS; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.xmlcml.euclid.Angle; import org.xmlcml.euclid.EC; import org.xmlcml.euclid.Point3; import org.xmlcml.euclid.RealArray; import org.xmlcml.euclid.RealSquareMatrix; import org.xmlcml.euclid.Transform3; import org.xmlcml.euclid.Vector3; import org.xmlcml.euclid.Axis.Axis3; import org.xmlcml.euclid.Transform3.Type; /** * test Transform3. * * @author pmr * */ public class Transform3Test extends GeomTest { /** * setup. * * @throws Exception */ @Before public void setUp() throws Exception { super.setUp(); } /** * equality test. true if both args not null and equal within epsilon * * @param msg * message * @param test * @param expected * @param epsilon */ public static void assertEquals(String msg, Transform3 test, Transform3 expected, double epsilon) { Assert.assertNotNull("test should not be null (" + msg + EC.S_RBRAK, test); Assert.assertNotNull("expected should not be null (" + msg + EC.S_RBRAK, expected); DoubleTestBase.assertEquals(msg, test.getMatrixAsArray(), expected .getMatrixAsArray(), epsilon); } /** * equality test. true if both args not null and equal within epsilon * * @param msg * message * @param test * 16 values * @param expected * @param epsilon */ public static void assertEquals(String msg, double[] test, Transform3 expected, double epsilon) { Assert.assertNotNull("test should not be null (" + msg + EC.S_RBRAK, test); Assert.assertEquals("test should have 16 elements (" + msg + EC.S_RBRAK, 16, test.length); Assert.assertNotNull("ref should not be null (" + msg + EC.S_RBRAK, expected); DoubleTestBase.assertEquals(msg, test, expected.getMatrixAsArray(), epsilon); } /** * Test method for 'org.xmlcml.euclid.Transform3.Transform3()' */ @Test public void testTransform3() { Assert.assertNotNull("transform3", tr0); } /** * Test method for 'org.xmlcml.euclid.Transform3.Transform3(int)' */ @Test public void testTransform3Int() { Transform3 t = new Transform3(Type.ANY); Assert.assertNotNull("transform3", t); Transform3Test.assertEquals("transform3", new double[] { 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, }, t, EPS); } /** * Test method for 'org.xmlcml.euclid.Transform3.Transform3(Vector3)' */ @Test public void testTransform3Vector3() { Transform3 t = new Transform3(new Vector3(1., 2., 3.)); Transform3Test.assertEquals("transform3 vector", new double[] { 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 2.0, 0.0, 0.0, 1.0, 3.0, 0.0, 0.0, 0.0, 1.0, }, t, EPS); } /** * Test method for 'org.xmlcml.euclid.Transform3.Transform3(Axis3, Angle)' */ @Test public void testTransform3Axis3Angle() { Transform3 t = new Transform3(Axis3.X, new Angle(Math.PI / 3.)); // not sure if this is right Transform3Test.assertEquals("transform3 vector", new double[] { 1.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.8660254037844386, 0.0, 0.0, -0.8660254037844386, 0.5, 0.0, 0.0, 0.0, 0.0, 1.0 }, t, EPS); } /** * Test method for 'org.xmlcml.euclid.Transform3.Transform3(Angle, Angle, * Angle)' */ @Test public void testTransform3AngleAngleAngle() { Transform3 t = new Transform3(new Angle(Math.PI / 2.), new Angle( Math.PI / 2.), new Angle(Math.PI / 2.)); // not sure if this is right Transform3Test.assertEquals("transform3 vector", new double[] { 0., 0., 1., 0., 0., -1., 0., 0., 1., 0., 0., 0., 0., 0., 0., 1. }, t, EPS); } /** * Test method for 'org.xmlcml.euclid.Transform3.Transform3(Transform3, * Point3)' */ @Test public void testTransform3Transform3Point3() { Transform3 t = new Transform3(tr0, new Point3(1., 2., 3.)); // tr0 is rotation 0 degrees, so should give identity matrix Transform3Test.assertEquals("transform3 vector", new double[] { 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 }, t, EPS); } /** * Test method for 'org.xmlcml.euclid.Transform3.Transform3(Vector3, Angle)' */ @Test public void testTransform3Vector3Angle() { Transform3 t = new Transform3(new Vector3(1. / s3, 1. / s3, 1. / s3), new Angle(Math.PI / 3.)); // not sure if this is right Transform3Test.assertEquals("transform3 vector angle", new double[] { 0.6666666666666667, -0.3333333333333333, 0.6666666666666667, 0.0, 0.6666666666666667, 0.6666666666666667, -0.3333333333333333, 0.0, -0.3333333333333333, 0.6666666666666667, 0.6666666666666667, 0.0, 0.0, 0.0, 0.0, 1.0 }, t, EPS); } /** * Test method for 'org.xmlcml.euclid.Transform3.Transform3(Line3, Angle)' */ @Test public void testTransform3Line3Angle() { Transform3 t = new Transform3(l123456, new Angle(Math.PI / 3.)); // not sure if this is right Transform3Test.assertEquals("transform3 line3 angle", new double[] { 0.5357142857142858, -0.6229365034008422, 0.5700529070291328, 1.5515079319722704, 0.765793646257985, 0.642857142857143, -0.01716931065742361, -1.174444435373113, -0.3557671927434186, 0.4457407392288521, 0.8214285714285715, 0.2657936462579853, 0.0, 0.0, 0.0, 1.0 }, t, EPS); } /** * Test method for 'org.xmlcml.euclid.Transform3.Transform3(Vector3, * Vector3)' */ @Test public void testTransform3Vector3Vector3() { Transform3 t = new Transform3(v123, v321); // not sure if this is right Transform3Test.assertEquals("transform3 vector vector", new double[] { 0.761904761904762, 0.1904761904761905, 0.6190476190476192, 0.0, -0.38095238095238104, 0.9047619047619049, 0.1904761904761905, 0.0, -0.5238095238095238, -0.38095238095238104, 0.761904761904762, 0.0, 0.0, 0.0, 0.0, 1.0 }, t, EPS); } /** * Test method for 'org.xmlcml.euclid.Transform3.Transform3(Vector3, * Vector3, Vector3)' */ @Test public void testTransform3Vector3Vector3Vector3() { Transform3 t = null; t = new Transform3(v123, v321, v100); Transform3Test.assertEquals("transform3 vector vector vector", new double[] { 1.0, 2.0, 3.0, 0.0, 3.0, 2.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0 }, t, EPS); } /** * Test method for 'org.xmlcml.euclid.Transform3.Transform3(double[])' */ @Test public void testTransform3DoubleArray() { Transform3 t = new Transform3(new double[] { 0., 0., 1., 4., 0., 1., 0., 8., -1., 0., 0., 9., 0., 0., 0., 1. }); Transform3Test.assertEquals("transform3 double[]", new double[] { 0., 0., 1., 4., 0., 1., 0., 8., -1., 0., 0., 9., 0., 0., 0., 1. }, t, EPS); } /** * Test method for 'org.xmlcml.euclid.Transform3.Transform3(Transform3)' */ @Test public void testTransform3Transform3() { Transform3 t = new Transform3(tr1); Transform3Test.assertEquals("copy", t, tr1, EPS); } /** * Test method for * 'org.xmlcml.euclid.Transform3.Transform3(RealSquareMatrix)' */ @Test public void testTransform3RealSquareMatrix() { Transform3 t = new Transform3(new RealSquareMatrix(4, new double[] { 0., 0., 1., 4., 0., 1., 0., 8., -1., 0., 0., 9., 0., 0., 0., 1. })); Transform3Test.assertEquals("transform3 rsm", new double[] { 0., 0., 1., 4., 0., 1., 0., 8., -1., 0., 0., 9., 0., 0., 0., 1. }, t, EPS); } /** * Test method for * 'org.xmlcml.euclid.Transform3.Transform3(RealSquareMatrix, Vector3)' */ @Test public void testTransform3RealSquareMatrixVector3() { Transform3 t = new Transform3(new RealSquareMatrix(3, new double[] { 0., 0., 1., 0., 1., 0., -1., 0., 0., }), new Vector3(4., 8., 9.)); Transform3Test.assertEquals("transform3 rsm vector", new double[] { 0., 0., 1., 4., 0., 1., 0., 8., -1., 0., 0., 9., 0., 0., 0., 1. }, t, EPS); } /** * Test method for 'org.xmlcml.euclid.Transform3.Transform3(String)' */ @Test public void testTransform3String() { Transform3 t = new Transform3("x, -y, 1/2+z"); Transform3Test.assertEquals("transform3 string", new double[] { 1.0, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.5, 0.0, 0.0, 0.0, 0.0 }, t, EPS); } /** * Test method for 'org.xmlcml.euclid.Transform3.concatenate(Transform3)' */ @Test public void testConcatenate() { Transform3 t1 = new Transform3("x, -y, z"); Transform3 t2 = new Transform3("-x, -y, -z"); Transform3 t = t1.concatenate(t2); Transform3Test.assertEquals("transform3 concatenate", new double[] { -1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0, 0.0, 0.0, 0.0 }, t, EPS); } /** * Test method for 'org.xmlcml.euclid.Transform3.getAxisAndAngle(Vector3, * Angle)' */ @Test public void testGetAxisAndAngle() { Transform3 t = new Transform3(new Vector3(1. / s3, 1. / s3, 1. / s3), new Angle(Math.PI / 3.)); Vector3 v = new Vector3(); Angle a = new Angle(); t.getAxisAndAngle(v, a); // not sure if this is right Vector3Test.assertEquals("vector angle", new Vector3(1. / s3, 1. / s3, 1. / s3), v, EPS); Assert.assertEquals("vector angle", Math.PI / 3., a.getRadian(), EPS); t = new Transform3("y, -x, z"); t.getAxisAndAngle(v, a); // not sure if this is right Vector3Test.assertEquals("vector angle", new double[] { 0., 0., -1. }, v, EPS); Assert.assertEquals("vector angle", Math.PI / 2., a.getRadian(), EPS); } /** * Test method for 'org.xmlcml.euclid.Transform3.getTranslation()' */ @Test public void testGetTranslation() { Transform3 t = new Transform3("x+1/2, y+1/4, z+1/6"); Vector3Test.assertEquals("transform3 translation", new double[] { 0.5, 0.25, 1. / 6. }, t.getTranslation(), EPS); } /** * Test method for 'org.xmlcml.euclid.Transform3.setTranslation()' */ @Test public void testSetTranslation() { Transform3 t = new Transform3("x+1/2, y+1/4, z+1/6"); t.incrementTranslation(new Vector3(0.6, 0.7, 0.8)); Vector3Test.assertEquals("transform3 increment translation", new double[] { 1.1, 0.95, 0.8 + (1. / 6.) }, t.getTranslation(), EPS); } /** * Test method for 'org.xmlcml.euclid.Transform3.getCentreOfRotation()' */ @Test public void testGetCentreOfRotation() { Transform3 t = new Transform3("-x+1/2, -y+1/2, z"); Transform3Test.assertEquals("transform3 translation", new double[] { -1.0, 0.0, 0.0, 0.5, 0.0, -1.0, 0.0, 0.5, 0.0, 0.0, 1.0, 0., 0.0, 0.0, 0.0, 0.0 }, t, EPS); // not sure if this is right Point3 p = t.getCentreOfRotation(); Point3Test.assertEquals("transform3 centre", new double[] { 0.5, 0.5, 0.0 }, p, EPS); } /** * Test method for 'org.xmlcml.euclid.Transform3.getScales()' */ @Test public void testGetScales() { Transform3 t = new Transform3(new double[] { 10., 0., 0., 0., 0., 20., 0., 0., 0., 0., 30., 0., 0., 0., 0., 1. }); RealArray scales = t.getScales(); RealArrayTest.assertEquals("scales", new double[] { 10., 20., 30. }, scales, EPS); } /** * Test method for 'org.xmlcml.euclid.Transform3.getRotationMatrix()' */ @Test public void testGetRotationMatrix() { Transform3 t = new Transform3(new Angle(Math.PI / 2.), new Angle( Math.PI / 2.), new Angle(Math.PI / 2.)); // not sure if this is right Transform3Test.assertEquals("transform3 vector", new double[] { 0., 0., 1., 0., 0., -1., 0., 0., 1., 0., 0., 0., 0., 0., 0., 1. }, t, EPS); RealMatrixTest.assertEquals("rotation matrix", 3, 3, new double[] { 0., 0., 1., 0., -1., 0., 1., 0., 0. }, t.getRotationMatrix(), EPS); } } wwmm-euclid-87e8f785a814/src/test/java/org/xmlcml/euclid/test/UtilTest.java0000644000000000000000000005577711607017524024605 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid.test; import static org.xmlcml.euclid.EuclidConstants.EPS; import static org.xmlcml.euclid.EuclidConstants.F_S; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.net.URLEncoder; import java.util.ArrayList; import java.util.List; import org.junit.Assert; import org.junit.Ignore; import org.junit.Test; import org.xmlcml.euclid.EuclidConstants; import org.xmlcml.euclid.EuclidRuntimeException; import org.xmlcml.euclid.Int; import org.xmlcml.euclid.Util; /** * @author pm286 * */ public class UtilTest { /** * Test method for 'org.xmlcml.cml.base.CMLUtil.addElement(String[], * String)' */ @Test public final void testAddElementToStringArray() { String[] array = new String[] { "a", "b" }; String[] array1 = Util.addElementToStringArray(array, "c"); Assert.assertEquals("array", 3, array1.length); StringTestBase.assertEquals("array", new String[] { "a", "b", "c" }, array1); } /** * Test method for 'org.xmlcml.cml.base.CMLUtil.removeElement(String[], * String)' */ @Test public final void testRemoveElement() { String[] array = new String[] { "a", "b", "c" }; String[] array1 = Util.removeElementFromStringArray(array, "b"); Assert.assertEquals("array", 2, array1.length); StringTestBase.assertEquals("array", new String[] { "a", "c" }, array1); } /** * Test method for 'org.xmlcml.cml.base.CMLUtil.createFile(File, String)' */ @Test public final void testCreateFile() { File dir = null; try { dir = Util.getResourceFile(EuclidTestUtils.BASE_RESOURCE); } catch (Exception e1) { throw new EuclidRuntimeException("should never throw " + e1); } File junk = new File(dir, "junk"); if (junk.exists()) { junk.delete(); } Assert.assertTrue("create", !junk.exists()); try { Util.createFile(dir, "junk"); } catch (Exception e) { e.printStackTrace(); throw new EuclidRuntimeException("should never throw " + e); } Assert.assertTrue("should exist: " + junk.toString(), junk.exists()); } @Test public void testGetRelativeFilename() { String S = File.separator; File file1 = new File("a"+S+"b"+S+"c"+S+"d"); File file2 = new File("a"+S+"b"+S+"e"); String relative = Util.getRelativeFilename(file1, file2, "/"); // this failed on other machines // Assert.assertEquals("relative", "../../e", relative); try { File file3 = new File(file1, relative); Assert.assertEquals("canonical", file2.getCanonicalPath(), file3.getCanonicalPath()); } catch (IOException e) { e.printStackTrace(); } } /** * Test method for org.xmlcml.euclid.Util.BUG(java.lang.String, * java.lang.Exception)}. */ @Test public final void testBUGStringException() { try { Util.BUG("foo", new Exception("bar")); Assert.fail("should throw exception"); } catch (RuntimeException e) { Assert.assertEquals("bug", "BUG: (foo)should never throw: java.lang.Exception: bar", e .getMessage()); } catch (Exception e) { throw new EuclidRuntimeException("should never throw " + e); } } /** * Test method for {org.xmlcml.euclid.Util.BUG(java.lang.Exception)}. */ @Test public final void testBUGException() { try { Util.BUG(new Exception("bar")); Assert.fail("should throw exception"); } catch (RuntimeException e) { Assert.assertEquals("bug", "BUG: should never throw: java.lang.Exception: bar", e .getMessage()); } catch (Exception e) { throw new EuclidRuntimeException("should never throw " + e); } } /** * @deprecated Test method for {@link org.xmlcml.euclid.Util#throwNYI()}. */ @Test public final void testNYI() { try { Util.throwNYI(); Assert.fail("should throw exception"); } catch (RuntimeException e) { Assert.assertEquals("NYI", "not yet implemented", e.getMessage()); } catch (Exception e) { throw new EuclidRuntimeException("should never throw " + e); } } /** * Test method for {org.xmlcml.euclid.Util.BUG(java.lang.String)}. */ @Test public final void testBUGString() { try { Util.BUG("foo"); Assert.fail("should throw exception"); } catch (RuntimeException e) { Assert.assertEquals("bug", "BUG: (foo)should never throw: java.lang.RuntimeException", e.getMessage()); } catch (Exception e) { throw new EuclidRuntimeException("should never throw " + e); } } /** * Test method for * {@link org.xmlcml.euclid.Util#getInputStreamFromResource(java.lang.String)} * . */ @Test public final void testGetInputStreamFromResource() { String filename = EuclidTestUtils.BASE_RESOURCE +EuclidConstants.U_S + "cml0.xml"; InputStream is = null; try { is = Util.getInputStreamFromResource(filename); } catch (Exception e) { throw new EuclidRuntimeException("should never throw " + e); } try { int read=is.read(); Assert.assertTrue(read!=-1); } catch (Exception e) { throw new EuclidRuntimeException("should never throw " + e); } } /** * Test method for * {@link org.xmlcml.euclid.Util#getResource(java.lang.String)}. */ @Test public final void testGetResource() { String filename = EuclidTestUtils.BASE_RESOURCE +EuclidConstants.U_S + "cml0.xml"; URL url = Util.getResource(filename); Assert.assertNotNull("url", url); Assert.assertTrue("target", url.toString().endsWith( "/org/xmlcml/euclid/cml0.xml")); } /** * Test method for * {@link org.xmlcml.euclid.Util#getResourceFile(java.lang.String[])}. */ @Test public final void testGetResourceFile() { String filename = EuclidTestUtils.BASE_RESOURCE +EuclidConstants.U_S + "cml0.xml"; File file = null; try { file = Util.getResourceFile(filename); } catch (Exception e) { Assert.fail("should never throw " + e); } Assert.assertNotNull("url", file); Assert.assertTrue("target", file.toString().endsWith( "" + F_S + "org" + F_S + "xmlcml" + F_S + "euclid" + F_S+ "cml0.xml")); Assert.assertTrue("file", file.exists()); } /** * Test method for {at link * org.xmlcml.cml.base.CMLUtil#buildPath(java.lang.String...)}. */ @Test public final void testBuildPath() { String s = Util.buildPath("foo", "bar", "plugh"); Assert.assertEquals("build", "foo" + F_S + "bar" + F_S + "plugh", s); } /** * Test method for * {@link org.xmlcml.euclid.Util#deleteFile(java.io.File, boolean)}. */ @Test public final void testDeleteFile() { File dir = Util.getTEMP_DIRECTORY(); try { Util.createFile(dir, "grot"); } catch (IOException e) { Assert.fail("IOException " + e); } File file = new File(dir, "grot"); Assert.assertTrue("exists", file.exists()); boolean deleteDirectory = false; Util.deleteFile(file, deleteDirectory); Assert.assertFalse("exists", file.exists()); } /** * Test method for * {@link org.xmlcml.euclid.Util#copyFile(java.io.File, java.io.File)}. */ @Test public final void testCopyFile() { try { File dir = Util.getTEMP_DIRECTORY(); File file = new File(dir, "grot.txt"); FileWriter fw = new FileWriter(file); fw.write("this is a line\n"); fw.write("and another\n"); fw.close(); File outFile = new File(dir, "grotOut.txt"); Util.copyFile(file, outFile); Assert.assertTrue("exists", outFile.exists()); } catch (IOException e) { Assert.fail("IOException " + e); } } /** * Test method for {@link org.xmlcml.euclid.Util#dump(java.net.URL)}. */ @Test public final void testDump() { try { File dir = Util.getTEMP_DIRECTORY(); File file = new File(dir, "grot.txt"); FileWriter fw = new FileWriter(file); fw.write("this is a line\n"); fw.write("and another\n"); fw.close(); URL url = file.toURI().toURL(); String s = Util.dump(url); String exp = "\n" + " 116 104 105 115 32 105 115 32 97 32 this is a \n" + " 108 105 110 101 10 97 110 100 32 97 line and a\n" + " 110 111 116 104 101 114 10 nother "; Assert.assertEquals("dump", exp, s); } catch (Exception e) { Assert.fail("IOException " + e); } } /** * Test method for {@link org.xmlcml.euclid.Util#spaces(int)}. */ @Test public final void testSpaces() { Assert.assertEquals("spaces", " ", Util.spaces(5)); } /** * Test method for * {@link org.xmlcml.euclid.Util#getSuffix(java.lang.String)}. */ @Test public final void testGetSuffix() { Assert.assertEquals("suffix", "txt", Util.getSuffix("foo.bar.txt")); } /** * Test method for * {@link org.xmlcml.euclid.Util#truncateAndAddEllipsis(java.lang.String, int)} * . */ @Test public final void testTruncateAndAddEllipsis() { Assert.assertEquals("suffix", "qwert ... ", Util .truncateAndAddEllipsis("qwertyuiop", 5)); } /** * Test method for {@link org.xmlcml.euclid.Util#deQuote(java.lang.String)}. */ @Test public final void testDeQuote() { Assert.assertEquals("deQuote", "This is a string", Util .deQuote("'This is a string'")); Assert.assertEquals("deQuote", "This is a string", Util .deQuote("\"This is a string\"")); } /** * Test method for * {@link org.xmlcml.euclid.Util#rightTrim(java.lang.String)}. */ @Test public final void testRightTrim() { Assert.assertEquals("deQuote", " This is a string", Util .rightTrim(" This is a string ")); } /** * Test method for {@link org.xmlcml.euclid.Util#leftTrim(java.lang.String)} * . */ @Test public final void testLeftTrim() { Assert.assertEquals("deQuote", "This is a string ", Util .leftTrim(" This is a string ")); } /** * Test method for * {@link org.xmlcml.euclid.Util#indexOfBalancedBracket(char, java.lang.String)} * . */ @Test public final void testIndexOfBalancedBracket() { String s = "(foo(bar)junk)grot"; Assert .assertEquals("balanced", 13, Util.indexOfBalancedBracket('(', s)); } /** * Test method for * {@link org.xmlcml.euclid.Util#getCommaSeparatedStrings(java.lang.String)} * . */ @Test public final void testGetCommaSeparatedStrings() { List ss = Util .getCommaSeparatedStrings("aa, bb, \"cc dd\", ee "); Assert.assertEquals("list", 4, ss.size()); Assert.assertEquals("s0", "aa", ss.get(0)); Assert.assertEquals("s1", " bb", ss.get(1)); Assert.assertEquals("s2", " \"cc dd\"", ss.get(2)); Assert.assertEquals("s3", " ee", ss.get(3)); } /** * Test method for * {@link org.xmlcml.euclid.Util#createCommaSeparatedStrings(java.util.List)} * . */ @Test public final void testCreateCommaSeparatedStrings() { List ss = new ArrayList(); ss.add("aa"); ss.add("bb"); ss.add("cc \"B\" dd"); ss.add("ee"); String s = Util.createCommaSeparatedStrings(ss); Assert.assertEquals("comma", "aa,bb,\"cc \"\"B\"\" dd\",ee", s); } /** * Test method for * {@link org.xmlcml.euclid.Util#quoteConcatenate(java.lang.String[])}. */ @Test public final void testQuoteConcatenate() { String[] ss = new String[4]; ss[0] = "aa"; ss[1] = "bb"; ss[2] = "cc \"B\" dd"; ss[3] = "ee"; String s = Util.quoteConcatenate(ss); Assert.assertEquals("quote", "aa bb \"cc \"B\" dd\" ee", s); } /** * Test method for * {@link org.xmlcml.euclid.Util#indexOf(java.lang.String, java.lang.String[], boolean)} * . */ @Test public final void testIndexOf() { String[] ss = new String[4]; ss[0] = "aa"; ss[1] = "bb"; ss[2] = "cc \"B\" dd"; ss[3] = "ee"; boolean ignoreCase = false; Assert.assertEquals("index", 1, Util.indexOf("bb", ss, ignoreCase)); Assert.assertEquals("index", -1, Util.indexOf("BB", ss, ignoreCase)); ignoreCase = true; Assert.assertEquals("index", 1, Util.indexOf("BB", ss, ignoreCase)); Assert.assertEquals("index", -1, Util.indexOf("XX", ss, ignoreCase)); } /** * Test method for * {@link org.xmlcml.euclid.Util#removeHTML(java.lang.String)}. */ @Test public final void testRemoveHTML() { String s = "

This is a para

"; String ss = Util.removeHTML(s); Assert.assertEquals("html", "This is a para", ss); } /** * Test method for {@link org.xmlcml.euclid.Util#warning(java.lang.String)}. */ @Test public final void testWarning() { // no useful method } /** * Test method for {@link org.xmlcml.euclid.Util#message(java.lang.String)}. */ @Test public final void testMessage() { // no useful method } /** * Test method for {@link org.xmlcml.euclid.Util#error(java.lang.String)}. */ @Test public final void testError() { // no useful method } /** * Test method for * {@link org.xmlcml.euclid.Util#BUG(java.lang.String, java.lang.Throwable)} * . */ @Test public final void testBUGStringThrowable() { // no useful method } /** * Test method for {@link org.xmlcml.euclid.Util#BUG(java.lang.Throwable)}. */ @Test public final void testBUGThrowable() { // no useful method } /** * Test method for {@link org.xmlcml.euclid.Util#getPWDName()}. */ @Test public final void testGetPWDName() { // no useful method } /** * Test method for * {@link org.xmlcml.euclid.Util#substituteString(java.lang.String, java.lang.String, java.lang.String, int)} * . */ @Test public final void testSubstituteString() { String s = "AAA"; String oldSubstring = "A"; String newSubstring = "aa"; String ss = Util.substituteString(s, oldSubstring, newSubstring, 2); Assert.assertEquals("substitute", "aaaaA", ss); } /** * Test method for * {@link org.xmlcml.euclid.Util#substituteStrings(java.lang.String, java.lang.String[], java.lang.String[])} * . */ @Test public final void testSubstituteStrings() { String s = "AAABBBCCCAAADDDSS"; String[] oldSubstring = new String[] { "AA", "CC", "D" }; String[] newSubstring = new String[] { "aa", "cc", "d" }; String ss = Util.substituteStrings(s, oldSubstring, newSubstring); Assert.assertEquals("substitute", "aaABBBccCaaAdddSS", ss); } /** * Test method for * {@link org.xmlcml.euclid.Util#substituteDOSbyAscii(java.lang.String)}. */ @Test public final void testSubstituteDOSbyAscii() { String ss = Util.substituteDOSbyAscii("" + (char) 161); Assert.assertEquals("char", 237, (int) ss.charAt(0)); } /** * Test method for * {@link org.xmlcml.euclid.Util#substituteEquals(java.lang.String)}. */ @Test public final void testSubstituteEquals() { String ss = Util.substituteEquals("=20"); Assert.assertEquals("equals", EuclidConstants.S_SPACE, ss); } /** * Test method for * {@link org.xmlcml.euclid.Util#getIntFromHex(java.lang.String)}. */ @Test public final void testGetIntFromHex() { Assert.assertEquals("hex", 2707, Util.getIntFromHex("A93")); } /** * Test method for * {@link org.xmlcml.euclid.Util#capitalise(java.lang.String)}. */ @Test public final void testCapitalise() { Assert.assertEquals("capital", "This is fred", Util .capitalise("this is fred")); } /** * Test method for * {@link org.xmlcml.euclid.Util#toCamelCase(java.lang.String)}. */ @Test public final void testToCamelCase() { Assert.assertEquals("capital", "thisIsFred", Util .toCamelCase("this is fred")); } /** * Test method for * {@link org.xmlcml.euclid.Util#readByteArray(java.lang.String)}. */ @Test public final void testReadByteArrayString() { // String filename; // byte[] bb = Util.readByteArray(filename); } /** * Test method for * {@link org.xmlcml.euclid.Util#readByteArray(java.io.DataInputStream)}. */ @Test public final void testReadByteArrayDataInputStream() { // not yet tested } /** * Test method for * {@link org.xmlcml.euclid.Util#stripISOControls(java.lang.String)}. */ @Test public final void testStripISOControls() { // not yet tested } /** * Test method for * {@link org.xmlcml.euclid.Util#normaliseWhitespace(java.lang.String)}. */ @Test public final void testNormaliseWhitespace() { Assert.assertEquals("capital", "this is fred", Util .normaliseWhitespace("this is fred")); } /** * Test method for {@link org.xmlcml.euclid.Util#stripNewlines(byte[])}. */ @Test public final void testStripNewlines() { Assert.assertEquals("capital", "this is fred", Util .normaliseWhitespace("this\nis\nfred")); } /** * Test method for * {@link org.xmlcml.euclid.Util#getFileOutputStream(java.lang.String)}. */ @Test public final void testGetFileOutputStream() { // not yet implemented } /** * Test method for * {@link org.xmlcml.euclid.Util#outputFloat(int, int, double)}. */ @Test public final void testOutputFloat() { // fail("Not yet implemented"); // TODO } /** * Test method for * {@link org.xmlcml.euclid.Util#outputNumber(int, int, double)}. */ @Test public final void testOutputNumber() { // fail("Not yet implemented"); // TODO } /** * Test method for * {@link org.xmlcml.euclid.Util#invert(java.util.Hashtable)}. */ @Test public final void testInvert() { // fail("Not yet implemented"); // TODO } /** * Test method for * {@link org.xmlcml.euclid.Util#concatenate(double[], java.lang.String)}. */ @Test public final void testConcatenateDoubleArrayString() { double[] ss = new double[] { 1.2, 3.4, 5.6 }; String s = Util.concatenate(ss, EuclidConstants.S_SPACE); Assert.assertEquals("Concat", "1.2 3.4 5.6", s); s = Util.concatenate(ss, EuclidConstants.S_COMMA); Assert.assertEquals("Concat", "1.2,3.4,5.6", s); } @Test public void testConcatenateInfinityAndBeyond() { double[] ss = new double[] { Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.NaN }; Assert.assertEquals("Concat infinities according to XSD", "INF -INF NaN", Util.concatenate(ss, EuclidConstants.S_SPACE)); } /** * Test method for * {@link org.xmlcml.euclid.Util#concatenate(double[][], java.lang.String)}. */ @Test public final void testConcatenateDoubleArrayArrayString() { double[][] ss = new double[][] { new double[] { 1.2, 3.4, 5.6 }, new double[] { 1.1, 2.2, 3.3, 4.4 } }; String s = Util.concatenate(ss, EuclidConstants.S_SPACE); Assert.assertEquals("Concat", "1.2 3.4 5.6 1.1 2.2 3.3 4.4", s); s = Util.concatenate(ss, EuclidConstants.S_COMMA); Assert.assertEquals("Concat", "1.2,3.4,5.6,1.1,2.2,3.3,4.4", s); } /** * Test method for * {@link org.xmlcml.euclid.Util#splitToIntArray(java.lang.String, java.lang.String)} * . */ @Test public final void testSplitToIntArray() { int[] ii = Util.splitToIntArray("1 2 3 4", EuclidConstants.S_SPACE); String s = Int.testEquals((new int[] { 1, 2, 3, 4 }), ii); if (s != null) { Assert.fail("int split" + "; " + s); } ii = Util.splitToIntArray("1,2,3,4", EuclidConstants.S_COMMA); s = Int.testEquals((new int[] { 1, 2, 3, 4 }), ii); if (s != null) { Assert.fail("int split" + "; " + s); } } /** * Test method for * {@link org.xmlcml.euclid.Util#splitToDoubleArray(java.lang.String, java.lang.String)} * . */ @Test public final void testSplitToDoubleArray() { double[] dd = Util.splitToDoubleArray("1.1 2.2 3.3 4.4", EuclidConstants.S_SPACE); DoubleTestBase.assertEquals("double split", new double[] { 1.1, 2.2, 3.3, 4.4 }, dd, EPS); dd = Util.splitToDoubleArray("1.1,2.2,3.3,4.4", EuclidConstants.S_COMMA); DoubleTestBase.assertEquals("double split", new double[] { 1.1, 2.2, 3.3, 4.4 }, dd, EPS); } /** * Test method for * {@link org.xmlcml.euclid.Util#concatenate(int[], java.lang.String)}. */ @Test public final void testConcatenateIntArrayString() { int[] ii = new int[] { 1, 2, 3, 4 }; String s = Util.concatenate(ii, EuclidConstants.S_SPACE); Assert.assertEquals("int split", "1 2 3 4", s); ii = new int[] { 1, 2, 3, 4 }; s = Util.concatenate(ii, EuclidConstants.S_COMMA); Assert.assertEquals("int split", "1,2,3,4", s); } /** * Test method for * {@link org.xmlcml.euclid.Util#concatenate(java.lang.String[], java.lang.String)} * . */ @Test public final void testConcatenateStringArrayString() { String[] ii = new String[] { "a", "b", "c", "d" }; String s = Util.concatenate(ii, EuclidConstants.S_SPACE); Assert.assertEquals("int split", "a b c d", s); ii = new String[] { "a", "b", "c", "d" }; s = Util.concatenate(ii, EuclidConstants.S_COMMA); Assert.assertEquals("int split", "a,b,c,d", s); } /** * Test method for * {@link org.xmlcml.euclid.Util#containsString(java.lang.String[], java.lang.String)} * . */ @Test public final void testContainsString() { Assert.assertTrue("contains", Util.containsString(new String[] { "aa", "bb", "cc" }, "bb")); Assert.assertFalse("contains", Util.containsString(new String[] { "aa", "bb", "cc" }, "xx")); } /** * Test method for {@link org.xmlcml.euclid.Util#getPrime(int)}. */ @Test public final void testGetPrime() { int i = Util.getPrime(0); Assert.assertEquals("0", 2, i); i = Util.getPrime(1); Assert.assertEquals("1", 3, i); i = Util.getPrime(4); Assert.assertEquals("4", 11, i); i = Util.getPrime(10); Assert.assertEquals("10", 31, i); i = Util.getPrime(100); Assert.assertEquals("100", 547, i); i = Util.getPrime(1000); Assert.assertEquals("1000", 7927, i); i = Util.getPrime(100); Assert.assertEquals("100", 547, i); } @Test public final void testSortByEmbeddedInteger() { String[] ss = { "a123", "b213", "aa1", "ac9", "ax22", }; List ssList = new ArrayList(); for (String s : ss) { ssList.add(s); } Util.sortByEmbeddedInteger(ssList); Assert.assertEquals("0", "aa1", ssList.get(0)); Assert.assertEquals("1", "ac9", ssList.get(1)); Assert.assertEquals("2", "ax22", ssList.get(2)); Assert.assertEquals("3", "a123", ssList.get(3)); Assert.assertEquals("4", "b213", ssList.get(4)); } @Test @Ignore ("switch off if server is down") public void testHTTP() throws IOException { // will fail if server is down String s = "Isopropyl 3-(hydroxymethyl)pyridine-2-carboxylate"; String u = "http://opsin.ch.cam.ac.uk/opsin/"; s = URLEncoder.encode(s, "UTF-8"); String mediaType = "chemical/x-cml"; List lines = Util.getRESTQueryAsLines(s, u, mediaType); Assert.assertEquals("lines", 88, lines.size()); } } wwmm-euclid-87e8f785a814/src/test/java/org/xmlcml/euclid/test/Vector2Test.java0000644000000000000000000000530211607017524025167 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid.test; import static org.xmlcml.euclid.EC.EPS; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.xmlcml.euclid.Angle; import org.xmlcml.euclid.EC; import org.xmlcml.euclid.Real2; import org.xmlcml.euclid.Vector2; /** * tests for Vector2. * * @author pmr * */ public class Vector2Test { Vector2 v0; Vector2 v1; /** * setup. * * @throws Exception */ @Before public void setUp() throws Exception { v0 = new Vector2(new Real2(3., 4.)); v1 = new Vector2(1., 2.); } /** * equality test. true if both args not null and equal within epsilon * * @param msg * message * @param test * @param expected * @param epsilon */ public static void assertEquals(String msg, Vector2 test, Vector2 expected, double epsilon) { Assert.assertNotNull("test should not be null (" + msg + EC.S_RBRAK, test); Assert.assertNotNull("expected should not be null (" + msg + EC.S_RBRAK, expected); DoubleTestBase.assertEquals(msg, test.getXY(), expected.getXY(), epsilon); } /** * Test method for 'org.xmlcml.euclid.Vector2.Vector2(Real2)' */ @Test public void testVector2Real2() { Assert.assertEquals("vector2 real2", 3., v0.getX(),EPS); Assert.assertEquals("vector2 real2", 4., v0.getY(),EPS); } /** * Test method for 'org.xmlcml.euclid.Vector2.Vector2(double, double)' */ @Test public void testVector2DoubleDouble() { Assert.assertEquals("vector2 real2", 1., v1.getX(),EPS); Assert.assertEquals("vector2 real2", 2., v1.getY(),EPS); } /** * Test method for 'org.xmlcml.euclid.Vector2.getAngleMadeWith(Vector2)' */ @Test public void testGetAngleMadeWith() { Vector2 v1 = new Vector2(Math.sqrt(3.) / 2., 1. / 2.); Vector2 v2 = new Vector2(1. / 2., Math.sqrt(3.) / 2.); Angle a = v1.getAngleMadeWith(v2); Assert.assertEquals("angle", -Math.PI / 6., a.getRadian(), EPS); a = v2.getAngleMadeWith(v1); Assert.assertEquals("angle", Math.PI / 6., a.getRadian(), EPS); } } wwmm-euclid-87e8f785a814/src/test/java/org/xmlcml/euclid/test/Vector3Test.java0000644000000000000000000003010511607017524025167 0ustar 00000000000000/** * Copyright 2011 Peter Murray-Rust * * Licensed 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.xmlcml.euclid.test; import static org.xmlcml.euclid.EC.EPS; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.xmlcml.euclid.Angle; import org.xmlcml.euclid.EuclidConstants; import org.xmlcml.euclid.EuclidRuntimeException; import org.xmlcml.euclid.Vector3; import org.xmlcml.euclid.Axis.Axis3; /** * tests for Vector3. * * @author pmr * */ public class Vector3Test extends GeomTest { /** * setup. * * @throws Exception */ @Before public void setUp() throws Exception { super.setUp(); } /** * equality test. true if both args not null and equal within epsilon * * @param msg * message * @param test * @param expected * @param epsilon */ public static void assertEquals(String msg, Vector3 test, Vector3 expected, double epsilon) { Assert.assertNotNull("test should not be null (" + msg + EuclidConstants.S_RBRAK, test); Assert.assertNotNull("expected should not be null (" + msg + EuclidConstants.S_RBRAK, expected); DoubleTestBase.assertEquals(msg, test.getArray(), expected.getArray(), epsilon); } /** * equality test. true if both args not null and equal within epsilon * * @param msg * message * @param test * array must be of length 3 * @param expected * @param epsilon */ public static void assertEquals(String msg, double[] test, Vector3 expected, double epsilon) { Assert.assertNotNull("test should not be null (" + msg + EuclidConstants.S_RBRAK, test); Assert.assertEquals("must be of length 3", 3, test.length); Assert.assertNotNull("expected should not be null (" + msg + EuclidConstants.S_RBRAK, expected); DoubleTestBase.assertEquals(msg, test, expected.getArray(), epsilon); } /** * Test method for 'org.xmlcml.euclid.Vector3.Vector3()' */ @Test public void testVector3() { Vector3Test .assertEquals("vector", new double[] { 0., 0., 0. }, v0, EPS); } /** * Test method for 'org.xmlcml.euclid.Vector3.Vector3(double, double, * double)' */ @Test public void testVector3DoubleDoubleDouble() { Vector3Test.assertEquals("vector", new double[] { 1., 2., 3. }, v123, EPS); } /** * Test method for 'org.xmlcml.euclid.Vector3.Vector3(double[])' */ @Test public void testVector3DoubleArray() { Vector3 v = new Vector3(new double[] { 4., 5., 6. }); Vector3Test.assertEquals("vector", new double[] { 4., 5., 6. }, v, EPS); } /** * Test method for 'org.xmlcml.euclid.Vector3.Vector3(Axis3)' */ @Test public void testVector3Axis3() { Vector3 v = new Vector3(Axis3.X); Vector3Test.assertEquals("vector", new double[] { 1., 0., 0. }, v, EPS); v = new Vector3(Axis3.Y); Vector3Test.assertEquals("vector", new double[] { 0., 1., 0. }, v, EPS); v = new Vector3(Axis3.Z); Vector3Test.assertEquals("vector", new double[] { 0., 0., 1. }, v, EPS); } /** * Test method for 'org.xmlcml.euclid.Vector3.Vector3(Vector3)' */ @Test public void testVector3Vector3() { Vector3 v = new Vector3(v123); Vector3Test.assertEquals("vector", new double[] { 1., 2., 3. }, v, EPS); } /** * Test method for 'org.xmlcml.euclid.Vector3.Vector3(RealArray)' */ @Test public void testVector3RealArray() { Vector3 v = new Vector3(new double[] { 1., 2., 3. }); Vector3Test.assertEquals("vector", new double[] { 1., 2., 3. }, v, EPS); } /** * Test method for 'org.xmlcml.euclid.Vector3.Vector3(Point3)' */ @Test public void testVector3Point3() { Vector3 v = new Vector3(p123); Vector3Test.assertEquals("vector", new double[] { 1., 2., 3. }, v, EPS); } /** * Test method for 'org.xmlcml.euclid.Vector3.getArray()' */ @Test public void testGetArray() { DoubleTestBase.assertEquals("array", new double[] { 1., 2., 3. }, v123 .getArray(), EPS); } /** * Test method for 'org.xmlcml.euclid.Vector3.isEqualTo(Vector3)' */ @Test public void testIsEqualTo() { Vector3 v = new Vector3(v123); Assert.assertTrue("isEqualTo", v.isEqualTo(v)); } /** * Test method for 'org.xmlcml.euclid.Vector3.longerThan(Vector3)' */ @Test public void testLongerThan() { Vector3 v = new Vector3(v123).plus(v100); Assert.assertTrue("isLongerThan", v.longerThan(v123)); } /** * Test method for 'org.xmlcml.euclid.Vector3.multiplyBy(double)' */ @Test public void testMultiplyBy() { Vector3 v = v123.multiplyBy(10.); Vector3Test.assertEquals("multiply", new double[] { 10., 20., 30. }, v, EPS); } /** * Test method for 'org.xmlcml.euclid.Vector3.multiplyEquals(double)' */ @Test public void testMultiplyEquals() { v123.multiplyEquals(10.); Vector3Test.assertEquals("multiply", new double[] { 10., 20., 30. }, v123, EPS); } /** * Test method for 'org.xmlcml.euclid.Vector3.plus(Vector3)' */ @Test public void testPlus() { Vector3 v = v123.plus(v100); Vector3Test.assertEquals("plus", new double[] { 2., 2., 3. }, v, EPS); } /** * Test method for 'org.xmlcml.euclid.Vector3.subtract(Vector3)' */ @Test public void testSubtract() { Vector3 v = v123.subtract(v100); Vector3Test.assertEquals("subtract", new double[] { 0., 2., 3. }, v, EPS); } /** * Test method for 'org.xmlcml.euclid.Vector3.negative()' */ @Test public void testNegative() { Vector3 v = v123.negative(); Vector3Test.assertEquals("negative", new double[] { -1., -2., -3. }, v, EPS); } /** * Test method for 'org.xmlcml.euclid.Vector3.elementAt(int)' */ @Test public void testElementAt() { double d = v123.elementAt(0); Assert.assertEquals("elementAt", 1., d, EPS); d = v123.elementAt(1); Assert.assertEquals("elementAt", 2., d, EPS); d = v123.elementAt(2); Assert.assertEquals("elementAt", 3., d, EPS); try { v123.elementAt(-1); } catch (EuclidRuntimeException e) { Assert.assertEquals("elementAt", "index (-1)out of range: 0/2", e .getMessage()); } try { v123.elementAt(3); } catch (EuclidRuntimeException e) { Assert.assertEquals("elementAt", "index (3)out of range: 0/2", e .getMessage()); } } /** * Test method for 'org.xmlcml.euclid.Vector3.setElementAt(int, double)' */ @Test public void testSetElementAt() { v123.setElementAt(0, 10.); Vector3Test.assertEquals("elementAt", new double[] { 10., 2., 3. }, v123, EPS); v123.setElementAt(1, 20.); Vector3Test.assertEquals("elementAt", new double[] { 10., 20., 3. }, v123, EPS); v123.setElementAt(2, 30.); Vector3Test.assertEquals("elementAt", new double[] { 10., 20., 30. }, v123, EPS); try { v123.elementAt(-1); } catch (EuclidRuntimeException e) { Assert.assertEquals("elementAt", "index (-1)out of range: 0/2", e .getMessage()); } try { v123.elementAt(3); } catch (EuclidRuntimeException e) { Assert.assertEquals("elementAt", "index (3)out of range: 0/2", e .getMessage()); } } /** * Test method for 'org.xmlcml.euclid.Vector3.isIdenticalTo(Vector3)' */ @Test public void testIsIdenticalTo() { Vector3 v = new Vector3(v123); Assert.assertTrue("identical to", v123.isIdenticalTo(v)); Assert.assertFalse("identical to", v123.isIdenticalTo(v100)); } /** * Test method for 'org.xmlcml.euclid.Vector3.isZero()' */ @Test public void testIsZero() { Assert.assertTrue("isZero", v000.isZero()); Assert.assertFalse("isZero", v123.isZero()); } /** * Test method for 'org.xmlcml.euclid.Vector3.transform(Transform3)' */ @Test public void testTransform() { Vector3 v = v123.transform(tr2); Vector3Test.assertEquals("transform", new double[] { 1., 2., 3. }, v123, EPS); Vector3Test.assertEquals("transform", new double[] { -1., -2., 3. }, v, EPS); } /** * Test method for 'org.xmlcml.euclid.Vector3.cross(Vector3)' */ @Test public void testCross() { Vector3 v = v100.cross(v010); Vector3Test.assertEquals("cross", new double[] { 0., 0., 1. }, v, EPS); v = v100.cross(v100); Vector3Test.assertEquals("cross", new double[] { 0., 0., 0. }, v, EPS); } /** * Test method for 'org.xmlcml.euclid.Vector3.normalize()' */ @Test public void testNormalise() { v123.normalize(); double d = Math.sqrt(14.); Vector3Test.assertEquals("normalise", new double[] { 1. / d, 2. / d, 3. / d }, v123, EPS); } /** * Test method for 'org.xmlcml.euclid.Vector3.round()' */ @Test public void testRound() { Vector3 v = new Vector3(0.8, -0.1, -1.2); v.round(); Vector3Test.assertEquals("round", new double[] { 1.0, 0.0, -1.0 }, v, EPS); } /** * Test method for 'org.xmlcml.euclid.Vector3.getUnitVector()' */ @Test public void testGetUnitVector() { Vector3 v = v123.getUnitVector(); double d = Math.sqrt(14.); Vector3Test.assertEquals("unit vector", new double[] { 1. / d, 2. / d, 3. / d }, v, EPS); } /** * Test method for 'org.xmlcml.euclid.Vector3.getLength()' */ @Test public void testGetLength() { Assert.assertEquals("length", Math.sqrt(14.), v123.getLength(), EPS); Assert.assertEquals("length", Math.sqrt(0.), v000.getLength(), EPS); } /** * Test method for 'org.xmlcml.euclid.Vector3.dot(Vector3)' */ @Test public void testDotVector3() { Assert.assertEquals("dot", 3., v001.dot(v123),EPS); Assert.assertEquals("dot", 0., v100.dot(v001),EPS); } /** * Test method for 'org.xmlcml.euclid.Vector3.getAngleMadeWith(Vector3)' */ @Test public void testGetAngleMadeWith() { Angle a = null; a = v001.getAngleMadeWith(v100); Assert.assertNotNull("angle", a); Assert.assertEquals("angle", Math.PI / 2., a.getRadian(), EPS); a = v001.getAngleMadeWith(v001); Assert.assertNotNull("angle", a); Assert.assertEquals("angle", 0., a.getRadian(), EPS); a = v001.getAngleMadeWith(v000); Assert.assertNull("angle zero length", a); } /** * Test method for * 'org.xmlcml.euclid.Vector3.getScalarTripleProduct(Vector3, Vector3)' */ @Test public void testGetScalarTripleProduct() { Assert.assertEquals("stp", 0., v001.getScalarTripleProduct(v001, v010), EPS); Assert.assertEquals("stp", -1., v001.getScalarTripleProduct(v010, v100), EPS); Assert.assertEquals("stp", 1., v001.getScalarTripleProduct(v100, v010), EPS); } /** * Test method for 'org.xmlcml.euclid.Vector3.projectOnto(Vector3)' */ @Test public void testProjectOnto() { Vector3 v = v123.projectOnto(v100); Vector3Test .assertEquals("project", new double[] { 1., 0., 0. }, v, EPS); v = v123.projectOnto(v001); Vector3Test .assertEquals("project", new double[] { 0., 0., 3. }, v, EPS); } /** * Test method for 'org.xmlcml.euclid.Vector3.isColinearVector(Vector3)' */ @Test public void testIsColinearVector() { Assert.assertTrue("colinear", v123.isColinearVector(v123)); } /** * Test method for 'org.xmlcml.euclid.Vector3.getNonColinearVector()' */ @Test public void testGetNonColinearVector() { Vector3 v = v123.getNonColinearVector(); Assert.assertFalse("colinear", v123.isColinearVector(v)); } /** * Test method for 'org.xmlcml.euclid.Vector3.getPerpendicularVector()' */ @Test public void testGetPerpendicularVector() { Vector3 v = v123.getPerpendicularVector(); Angle a = v.getAngleMadeWith(v123); Assert.assertNotNull("perpendicular vector", a); Assert.assertEquals("perpendicular", Math.PI / 2., a.getRadian(), EPS); } } wwmm-euclid-87e8f785a814/src/test/resources/org/xmlcml/euclid/cml0.xml0000644000000000000000000000162011607017524023626 0ustar 00000000000000 wwmm-euclid-87e8f785a814/src/test/resources/org/xmlcml/euclid/junk0000644000000000000000000000000011607017524023132 0ustar 00000000000000wwmm-euclid-87e8f785a814/src/test/resources/org/xmlcml/euclid/temp/cml0.xsd0000644000000000000000000000266611607017524024604 0ustar 00000000000000 wwmm-euclid-87e8f785a814/src/test/resources/org/xmlcml/euclid/temp/noSchema.xml0000644000000000000000000000134311607017524025477 0ustar 00000000000000