brentworden 2004/06/01 06:47:17
Modified: math/src/test/org/apache/commons/math/complex
ComplexFormatTest.java
math/src/java/org/apache/commons/math/complex
ComplexFormat.java
math/xdocs/userguide complex.xml index.xml
Log:
PR: 29000
Made ComplexFormat extend java.text.Format providing complex object formatting and
parsing.
Revision Changes Path
1.5 +257 -14
jakarta-commons/math/src/test/org/apache/commons/math/complex/ComplexFormatTest.java
Index: ComplexFormatTest.java
===================================================================
RCS file:
/home/cvs/jakarta-commons/math/src/test/org/apache/commons/math/complex/ComplexFormatTest.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- ComplexFormatTest.java 23 May 2004 00:52:32 -0000 1.4
+++ ComplexFormatTest.java 1 Jun 2004 13:47:17 -0000 1.5
@@ -16,6 +16,9 @@
package org.apache.commons.math.complex;
+import java.text.NumberFormat;
+import java.text.ParseException;
+
import junit.framework.TestCase;
public class ComplexFormatTest extends TestCase {
@@ -34,67 +37,307 @@
public void testSimpleNoDecimals() {
Complex c = new Complex(1, 1);
- assertEquals( complexFormat.format( c ), "1 + 1i" );
+ String expected = "1 + 1i";
+ String actual = complexFormat.format(c);
+ assertEquals(expected, actual);
}
public void testSimpleWithDecimals() {
Complex c = new Complex(1.23, 1.43);
- assertEquals( complexFormat.format( c ), "1.23 + 1.43i" );
+ String expected = "1.23 + 1.43i";
+ String actual = complexFormat.format(c);
+ assertEquals(expected, actual);
}
public void testSimpleWithDecimalsTrunc() {
Complex c = new Complex(1.2323, 1.4343);
- assertEquals( complexFormat.format( c ), "1.23 + 1.43i" );
+ String expected = "1.23 + 1.43i";
+ String actual = complexFormat.format(c);
+ assertEquals(expected, actual);
}
public void testNegativeReal() {
Complex c = new Complex(-1.2323, 1.4343);
- assertEquals( complexFormat.format( c ), "-1.23 + 1.43i" );
+ String expected = "-1.23 + 1.43i";
+ String actual = complexFormat.format(c);
+ assertEquals(expected, actual);
}
public void testNegativeImaginary() {
Complex c = new Complex(1.2323, -1.4343);
- assertEquals( complexFormat.format( c ), "1.23 - 1.43i" );
+ String expected = "1.23 - 1.43i";
+ String actual = complexFormat.format(c);
+ assertEquals(expected, actual);
}
public void testNegativeBoth() {
Complex c = new Complex(-1.2323, -1.4343);
- assertEquals( complexFormat.format( c ), "-1.23 - 1.43i" );
+ String expected = "-1.23 - 1.43i";
+ String actual = complexFormat.format(c);
+ assertEquals(expected, actual);
}
public void testZeroReal() {
Complex c = new Complex(0.0, -1.4343);
- assertEquals( complexFormat.format( c ), "0 - 1.43i" );
+ String expected = "0 - 1.43i";
+ String actual = complexFormat.format(c);
+ assertEquals(expected, actual);
}
public void testZeroImaginary() {
Complex c = new Complex(30.233, 0);
- assertEquals( complexFormat.format( c ), "30.23" );
+ String expected = "30.23";
+ String actual = complexFormat.format(c);
+ assertEquals(expected, actual);
}
public void testDifferentImaginaryChar() {
Complex c = new Complex(1, 1);
- assertEquals( complexFormatJ.format( c ), "1 + 1j" );
+ String expected = "1 + 1j";
+ String actual = complexFormatJ.format(c);
+ assertEquals(expected, actual);
}
public void testStaticFormatComplex() {
Complex c = new Complex(232.222, -342.33);
- assertEquals( ComplexFormat.formatComplex( c ), "232.22 - 342.33i" );
+ String expected = "232.22 - 342.33i";
+ String actual = ComplexFormat.formatComplex(c);
+ assertEquals(expected, actual);
}
public void testNan() {
Complex c = new Complex(Double.NaN, Double.NaN);
- assertEquals( complexFormat.format( c ), "(NaN) + (NaN)i" );
+ String expected = "(NaN) + (NaN)i";
+ String actual = complexFormat.format(c);
+ assertEquals(expected, actual);
}
public void testPositiveInfinity() {
Complex c = new Complex(Double.POSITIVE_INFINITY,
Double.POSITIVE_INFINITY);
- assertEquals( complexFormat.format( c ), "(Infinity) + (Infinity)i" );
+ String expected = "(Infinity) + (Infinity)i";
+ String actual = complexFormat.format(c);
+ assertEquals(expected, actual);
}
public void testNegativeInfinity() {
Complex c = new Complex(Double.NEGATIVE_INFINITY,
Double.NEGATIVE_INFINITY);
- assertEquals( complexFormat.format( c ), "(-Infinity) - (Infinity)i" );
- }
+ String expected = "(-Infinity) - (Infinity)i";
+ String actual = complexFormat.format(c);
+ assertEquals(expected, actual);
+ }
+
+ public void testParseSimpleNoDecimals() {
+ String source = "1 + 1i";
+ Complex expected = new Complex(1, 1);
+ try {
+ Complex actual = (Complex)complexFormat.parseObject(source);
+ assertEquals(expected, actual);
+ } catch (ParseException ex) {
+ fail(ex.getMessage());
+ }
+ }
+
+ public void testParseSimpleWithDecimals() {
+ String source = "1.23 + 1.43i";
+ Complex expected = new Complex(1.23, 1.43);
+ try {
+ Complex actual = (Complex)complexFormat.parseObject(source);
+ assertEquals(expected, actual);
+ } catch (ParseException ex) {
+ fail(ex.getMessage());
+ }
+ }
+
+ public void testParseSimpleWithDecimalsTrunc() {
+ String source = "1.2323 + 1.4343i";
+ Complex expected = new Complex(1.2323, 1.4343);
+ try {
+ Complex actual = (Complex)complexFormat.parseObject(source);
+ assertEquals(expected, actual);
+ } catch (ParseException ex) {
+ fail(ex.getMessage());
+ }
+ }
+
+ public void testParseNegativeReal() {
+ String source = "-1.2323 + 1.4343i";
+ Complex expected = new Complex(-1.2323, 1.4343);
+ try {
+ Complex actual = (Complex)complexFormat.parseObject(source);
+ assertEquals(expected, actual);
+ } catch (ParseException ex) {
+ fail(ex.getMessage());
+ }
+ }
+
+ public void testParseNegativeImaginary() {
+ String source = "1.2323 - 1.4343i";
+ Complex expected = new Complex(1.2323, -1.4343);
+ try {
+ Complex actual = (Complex)complexFormat.parseObject(source);
+ assertEquals(expected, actual);
+ } catch (ParseException ex) {
+ fail(ex.getMessage());
+ }
+ }
+
+ public void testParseNegativeBoth() {
+ String source = "-1.2323 - 1.4343i";
+ Complex expected = new Complex(-1.2323, -1.4343);
+ try {
+ Complex actual = (Complex)complexFormat.parseObject(source);
+ assertEquals(expected, actual);
+ } catch (ParseException ex) {
+ fail(ex.getMessage());
+ }
+ }
+
+ public void testParseZeroReal() {
+ String source = "0.0 - 1.4343i";
+ Complex expected = new Complex(0.0, -1.4343);
+ try {
+ Complex actual = (Complex)complexFormat.parseObject(source);
+ assertEquals(expected, actual);
+ } catch (ParseException ex) {
+ fail(ex.getMessage());
+ }
+ }
+
+ public void testParseZeroImaginary() {
+ String source = "-1.2323";
+ Complex expected = new Complex(-1.2323, 0);
+ try {
+ Complex actual = (Complex)complexFormat.parseObject(source);
+ assertEquals(expected, actual);
+ } catch (ParseException ex) {
+ fail(ex.getMessage());
+ }
+ }
+
+ public void testParseDifferentImaginaryChar() {
+ String source = "-1.2323 - 1.4343j";
+ Complex expected = new Complex(-1.2323, -1.4343);
+ try {
+ Complex actual = (Complex)complexFormatJ.parseObject(source);
+ assertEquals(expected, actual);
+ } catch (ParseException ex) {
+ fail(ex.getMessage());
+ }
+ }
+
+ public void testParseNan() {
+ String source = "(NaN) + (NaN)i";
+ Complex expected = new Complex(Double.NaN, Double.NaN);
+ try {
+ Complex actual = (Complex)complexFormat.parseObject(source);
+ assertEquals(expected, actual);
+ } catch (ParseException ex) {
+ fail(ex.getMessage());
+ }
+ }
+ public void testParsePositiveInfinity() {
+ String source = "(Infinity) + (Infinity)i";
+ Complex expected = new Complex(Double.POSITIVE_INFINITY,
Double.POSITIVE_INFINITY);
+ try {
+ Complex actual = (Complex)complexFormat.parseObject(source);
+ assertEquals(expected, actual);
+ } catch (ParseException ex) {
+ fail(ex.getMessage());
+ }
+ }
+
+ public void testPaseNegativeInfinity() {
+ String source = "(-Infinity) - (Infinity)i";
+ Complex expected = new Complex(Double.NEGATIVE_INFINITY,
Double.NEGATIVE_INFINITY);
+ try {
+ Complex actual = (Complex)complexFormat.parseObject(source);
+ assertEquals(expected, actual);
+ } catch (ParseException ex) {
+ fail(ex.getMessage());
+ }
+ }
+
+ public void testConstructorSingleFormat() {
+ NumberFormat nf = NumberFormat.getInstance();
+ ComplexFormat cf = new ComplexFormat(nf);
+ assertNotNull(cf);
+ assertEquals(nf, cf.getRealFormat());
+ }
+
+ public void testGetImaginaryFormat() {
+ NumberFormat nf = NumberFormat.getInstance();
+ ComplexFormat cf = new ComplexFormat();
+
+ assertNotSame(nf, cf.getImaginaryFormat());
+ cf.setImaginaryFormat(nf);
+ assertSame(nf, cf.getImaginaryFormat());
+ }
+
+ public void testSetImaginaryFormatNull() {
+ try {
+ ComplexFormat cf = new ComplexFormat();
+ cf.setImaginaryFormat(null);
+ fail();
+ } catch (IllegalArgumentException ex) {
+ // success
+ }
+ }
+
+ public void testSetRealFormatNull() {
+ try {
+ ComplexFormat cf = new ComplexFormat();
+ cf.setRealFormat(null);
+ fail();
+ } catch (IllegalArgumentException ex) {
+ // success
+ }
+ }
+
+ public void testGetRealFormat() {
+ NumberFormat nf = NumberFormat.getInstance();
+ ComplexFormat cf = new ComplexFormat();
+
+ assertNotSame(nf, cf.getRealFormat());
+ cf.setRealFormat(nf);
+ assertSame(nf, cf.getRealFormat());
+ }
+
+ public void testSetImaginaryCharacterNull() {
+ try {
+ ComplexFormat cf = new ComplexFormat();
+ cf.setImaginaryCharacter(null);
+ fail();
+ } catch (IllegalArgumentException ex) {
+ // success
+ }
+ }
+
+ public void testSetImaginaryCharacterEmpty() {
+ try {
+ ComplexFormat cf = new ComplexFormat();
+ cf.setImaginaryCharacter("");
+ fail();
+ } catch (IllegalArgumentException ex) {
+ // success
+ }
+ }
+
+ public void testFormatNumber() {
+ ComplexFormat cf = new ComplexFormat();
+ Double pi = new Double(Math.PI);
+ String text = cf.format(pi);
+ assertEquals("3.14", text);
+ }
+
+ public void testFormatObject() {
+ try {
+ ComplexFormat cf = new ComplexFormat();
+ Object object = new Object();
+ cf.format(object);
+ fail();
+ } catch (IllegalArgumentException ex) {
+ // success
+ }
+ }
}
1.7 +440 -57
jakarta-commons/math/src/java/org/apache/commons/math/complex/ComplexFormat.java
Index: ComplexFormat.java
===================================================================
RCS file:
/home/cvs/jakarta-commons/math/src/java/org/apache/commons/math/complex/ComplexFormat.java,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- ComplexFormat.java 23 May 2004 00:52:32 -0000 1.6
+++ ComplexFormat.java 1 Jun 2004 13:47:17 -0000 1.7
@@ -16,103 +16,486 @@
package org.apache.commons.math.complex;
+import java.text.FieldPosition;
+import java.text.Format;
import java.text.NumberFormat;
+import java.text.ParseException;
+import java.text.ParsePosition;
/**
* Formats a Complex number in cartesian format "Re(c) + Im(c)i". 'i' can
- * be replaced with 'j', and the number of decimal places to display
+ * be replaced with 'j', and the number format for both real and imaginary parts
* can be configured.
*
* @author Apache Software Foundation
* @version $Revision$ $Date$
*/
-public class ComplexFormat {
-
+public class ComplexFormat extends Format {
+
/** The default complex format. */
private static final ComplexFormat DEFAULT = new ComplexFormat();
- /** The notation used to signify the imaginary part of the complex number. */
- private String imaginaryCharacter = "i";
-
- /** The maximum number of decimal digits in the formatted output. */
- private int fractionDigits = 2;
+ /** The default imaginary character. */
+ private static final String DEFAULT_IMAGINARY_CHARACTER = "i";
+
+ /** The notation used to signify the imaginary part of the complex number. */
+ private String imaginaryCharacter;
+
+ /** The format used for the imaginary part. */
+ private NumberFormat imaginaryFormat;
+ /** The format used for the real part. */
+ private NumberFormat realFormat;
+
/**
- * Create an instance with the default imaginary character 'i', and the default
- * number of decimal places - 2.
+ * Create an instance with the default imaginary character, 'i', and the
+ * default number format for both real and imaginary parts.
*/
- public ComplexFormat() {}
+ public ComplexFormat() {
+ this(DEFAULT_IMAGINARY_CHARACTER, getDefaultNumberFormat());
+ }
/**
- * Create an instance with a custom imaginary character, and the default number
- * of decimal places - 2.
+ * Create an instance with a custom number format for both real and
+ * imaginary parts.
+ * @param format the custom format for both real and imaginary parts.
+ */
+ public ComplexFormat(NumberFormat format) {
+ this(DEFAULT_IMAGINARY_CHARACTER, format);
+ }
+
+ /**
+ * Create an instance with a custom number format for the real part and a
+ * custom number format for the imaginary part.
+ * @param realFormat the custom format for the real part.
+ * @param imaginaryFormat the custom format for the imaginary part.
+ */
+ public ComplexFormat(NumberFormat realFormat,
+ NumberFormat imaginaryFormat) {
+ this(DEFAULT_IMAGINARY_CHARACTER, realFormat, imaginaryFormat);
+ }
+
+ /**
+ * Create an instance with a custom imaginary character, and the default
+ * number format for both real and imaginary parts.
* @param imaginaryCharacter The custom imaginary character.
*/
public ComplexFormat(String imaginaryCharacter) {
- this.imaginaryCharacter = imaginaryCharacter;
+ this(imaginaryCharacter, getDefaultNumberFormat());
}
-
+
/**
- * Create an instance with a custom imaginary character, and a custom number of
- * decimal places.
+ * Create an instance with a custom imaginary character, and a custom number
+ * format for both real and imaginary parts.
* @param imaginaryCharacter The custom imaginary character.
- * @param fractionDigits The custom number of decimal places.
+ * @param format the custom format for both real and imaginary parts.
*/
- public ComplexFormat(String imaginaryCharacter, int fractionDigits) {
- this.imaginaryCharacter = imaginaryCharacter;
- this.fractionDigits = fractionDigits;
+ public ComplexFormat(String imaginaryCharacter, NumberFormat format) {
+ this(imaginaryCharacter, format, (NumberFormat)format.clone());
+ }
+
+ /**
+ * Create an instance with a custom imaginary character, a custom number
+ * format for the real part, and a custom number format for the imaginary
+ * part.
+ * @param imaginaryCharacter The custom imaginary character.
+ * @param realFormat the custom format for the real part.
+ * @param imaginaryFormat the custom format for the imaginary part.
+ */
+ public ComplexFormat(String imaginaryCharacter, NumberFormat realFormat,
+ NumberFormat imaginaryFormat) {
+ super();
+ setImaginaryCharacter(imaginaryCharacter);
+ setImaginaryFormat(imaginaryFormat);
+ setRealFormat(realFormat);
}
/**
- * Formats a Complex object and returns a String representing the "cartesian
- * form" of a complex number.
+ * This static method calls formatComplex() on a default instance of
+ * ComplexFormat.
*
* @param c Complex object to format
* @return A formatted number in the form "Re(c) + Im(c)i"
*/
- public String format(Complex c) {
-
- NumberFormat format = NumberFormat.getInstance();
- format.setMaximumFractionDigits( fractionDigits );
-
- StringBuffer buffer = new StringBuffer();
+ public static String formatComplex( Complex c ) {
+ return DEFAULT.format( c );
+ }
+
+ /**
+ * Create a default number format. The default number format is based on
+ * [EMAIL PROTECTED] NumberFormat#getInstance()} with the only customizing is
the
+ * maximum number of fraction digits, which is set to 2.
+ *
+ * @return the default number format.
+ */
+ private static NumberFormat getDefaultNumberFormat() {
+ NumberFormat nf = NumberFormat.getInstance();
+ nf.setMaximumFractionDigits(2);
+ return nf;
+ }
+
+ /**
+ * Formats a [EMAIL PROTECTED] Complex} object to produce a string.
+ *
+ * @param complex the object to format.
+ * @param toAppendTo where the text is to be appended
+ * @param pos On input: an alignment field, if desired. On output: the
+ * offsets of the alignment field
+ * @return the value passed in as toAppendTo.
+ */
+ public StringBuffer format(Complex complex, StringBuffer toAppendTo,
+ FieldPosition pos) {
+
+ pos.setBeginIndex(0);
+ pos.setEndIndex(0);
- if( Double.isNaN( c.getReal() ) || Double.isInfinite( c.getReal() ) ) {
- buffer.append( "(" + c.getReal() + ")" );
- } else {
- buffer.append( format.format( c.getReal() ) );
- }
-
- if( c.getImaginary() < 0 ) {
- buffer.append( " - " );
- } else if( c.getImaginary() > 0 || Double.isNaN( c.getImaginary() )) {
- buffer.append( " + " );
- }
-
- if( c.getImaginary() != 0 ) {
- if( Double.isNaN( c.getImaginary() ) || Double.isInfinite(
c.getImaginary() ) ) {
- buffer.append( "(" + Math.abs( c.getImaginary() ) +
")" );
- } else {
- buffer.append( format.format(
Math.abs(c.getImaginary()) ) );
- }
- buffer.append( imaginaryCharacter );
- }
+ // format real
+ double re = complex.getReal();
+ formatDouble(re, getRealFormat(), toAppendTo, pos);
+
+ // format sign and imaginary
+ double im = complex.getImaginary();
+ if (im < 0.0) {
+ toAppendTo.append(" - ");
+ formatDouble(-im, getImaginaryFormat(), toAppendTo, pos);
+ toAppendTo.append(getImaginaryCharacter());
+ } else if (im > 0.0 || Double.isNaN(im)) {
+ toAppendTo.append(" + ");
+ formatDouble(im, getImaginaryFormat(), toAppendTo, pos);
+ toAppendTo.append(getImaginaryCharacter());
+ }
+
+ return toAppendTo;
+ }
+
+ /**
+ * Formats a object to produce a string. <code>obj</code> must be either a
+ * [EMAIL PROTECTED] Complex} object or a [EMAIL PROTECTED] Number} object.
Any other type of
+ * object will result in an [EMAIL PROTECTED] IllegalArgumentException} being
thrown.
+ *
+ * @param obj the object to format.
+ * @param toAppendTo where the text is to be appended
+ * @param pos On input: an alignment field, if desired. On output: the
+ * offsets of the alignment field
+ * @return the value passed in as toAppendTo.
+ * @see java.text.Format#format(java.lang.Object, java.lang.StringBuffer,
java.text.FieldPosition)
+ * @throws IllegalArgumentException is <code>obj</code> is not a valid type.
+ */
+ public StringBuffer format(Object obj, StringBuffer toAppendTo,
+ FieldPosition pos) {
+
+ StringBuffer ret = null;
- return( buffer.toString() );
+ if (obj instanceof Complex) {
+ ret = format( (Complex)obj, toAppendTo, pos);
+ } else if (obj instanceof Number) {
+ ret = format( new Complex(((Number)obj).doubleValue(), 0.0),
+ toAppendTo, pos);
+ } else {
+ throw new IllegalArgumentException(
+ "Cannot format given Object as a Date");
+ }
+
+ return ret;
+ }
+ /**
+ * Formats a double value to produce a string. In general, the value is
+ * formatted using the formatting rules of <code>format</code>. There are
+ * three exceptions to this:
+ * <ol>
+ * <li>NaN is formatted as '(NaN)'</li>
+ * <li>Positive infinity is formatted as '(Infinity)'</li>
+ * <li>Negative infinity is formatted as '(-Infinity)'</li>
+ * </ol>
+ *
+ * @param value the double to format.
+ * @param format the format used.
+ * @param toAppendTo where the text is to be appended
+ * @param pos On input: an alignment field, if desired. On output: the
+ * offsets of the alignment field
+ * @return the value passed in as toAppendTo.
+ */
+ private StringBuffer formatDouble(double value, NumberFormat format,
+ StringBuffer toAppendTo, FieldPosition pos) {
+ if( Double.isNaN(value) || Double.isInfinite(value) ) {
+ toAppendTo.append('(');
+ toAppendTo.append(value);
+ toAppendTo.append(')');
+ } else {
+ getRealFormat().format(value, toAppendTo, pos);
+ }
+ return toAppendTo;
}
/**
- * This static method calls formatComplex() on a default instance of
- * ComplexFormat.
+ * Access the imaginaryCharacter.
+ * @return the imaginaryCharacter.
+ */
+ public String getImaginaryCharacter() {
+ return imaginaryCharacter;
+ }
+
+ /**
+ * Access the imaginaryFormat.
+ * @return the imaginaryFormat.
+ */
+ public NumberFormat getImaginaryFormat() {
+ return imaginaryFormat;
+ }
+
+ /**
+ * Access the realFormat.
+ * @return the realFormat.
+ */
+ public NumberFormat getRealFormat() {
+ return realFormat;
+ }
+
+ /**
+ * Parses a string to produce a [EMAIL PROTECTED] Complex} object.
*
- * @param c Complex object to format
- * @return A formatted number in the form "Re(c) + Im(c)i"
+ * @param source the string to parse
+ * @return the parsed [EMAIL PROTECTED] Complex} object.
+ * @exception ParseException if the beginning of the specified string
+ * cannot be parsed.
*/
- public static String formatComplex( Complex c ) {
- return DEFAULT.format( c );
+ public Complex parse(String source) throws ParseException {
+ ParsePosition parsePosition = new ParsePosition(0);
+ Complex result = parse(source, parsePosition);
+ if (parsePosition.getIndex() == 0) {
+ throw new ParseException("Unparseable complex number: \"" + source +
+ "\"", parsePosition.getErrorIndex());
+ }
+ return result;
}
-}
+
+ /**
+ * Parses a string to produce a [EMAIL PROTECTED] Complex} object.
+ *
+ * @param source the string to parse
+ * @param pos input/ouput parsing parameter.
+ * @return the parsed [EMAIL PROTECTED] Complex} object.
+ */
+ public Complex parse(String source, ParsePosition pos) {
+ int initialIndex = pos.getIndex();
+
+ // parse whitespace
+ parseAndIgnoreWhitespace(source, pos);
+
+ // parse real
+ Number re = parseNumber(source, getRealFormat(), pos);
+ if (re == null) {
+ // invalid real number
+ // set index back to initial, error index should already be set
+ // character examined.
+ pos.setIndex(initialIndex);
+ return null;
+ }
+
+ // parse sign
+ int startIndex = pos.getIndex();
+ char c = parseNextCharacter(source, pos);
+ int sign = 0;
+ switch (c) {
+ case 0 :
+ // no sign
+ // return real only complex number
+ return new Complex(re.doubleValue(), 0.0);
+ case '-' :
+ sign = -1;
+ break;
+ case '+' :
+ sign = 1;
+ break;
+ default :
+ // invalid sign
+ // set index back to initial, error index should be the last
+ // character examined.
+ pos.setIndex(initialIndex);
+ pos.setErrorIndex(startIndex);
+ return null;
+ }
+
+ // parse whitespace
+ parseAndIgnoreWhitespace(source, pos);
+
+ // parse imaginary
+ Number im = parseNumber(source, getRealFormat(), pos);
+ if (im == null) {
+ // invalid imaginary number
+ // set index back to initial, error index should already be set
+ // character examined.
+ pos.setIndex(initialIndex);
+ return null;
+ }
+
+ // parse imaginary character
+ int n = getImaginaryCharacter().length();
+ startIndex = pos.getIndex();
+ int endIndex = startIndex + n;
+ if (source.substring(startIndex, endIndex).compareTo(
+ getImaginaryCharacter()) != 0) {
+ // set index back to initial, error index should be the start index
+ // character examined.
+ pos.setIndex(initialIndex);
+ pos.setErrorIndex(startIndex);
+ return null;
+ }
+ pos.setIndex(endIndex);
+ return new Complex(re.doubleValue(), im.doubleValue() * sign);
+ }
+
+ /**
+ * Parses <code>source</code> until a non-whitespace character is found.
+ *
+ * @param source the string to parse
+ * @param pos input/ouput parsing parameter. On output, <code>pos</code>
+ * holds the index of the next non-whitespace character.
+ */
+ private void parseAndIgnoreWhitespace(String source, ParsePosition pos) {
+ parseNextCharacter(source, pos);
+ pos.setIndex(pos.getIndex() - 1);
+ }
+
+ /**
+ * Parses <code>source</code> until a non-whitespace character is found.
+ *
+ * @param source the string to parse
+ * @param pos input/ouput parsing parameter.
+ * @return the first non-whitespace character.
+ */
+ private char parseNextCharacter(String source, ParsePosition pos) {
+ int index = pos.getIndex();
+ int n = source.length();
+ char ret = 0;
+
+ if (index < n) {
+ char c;
+ do {
+ c = source.charAt(index++);
+ } while (Character.isWhitespace(c) && index < n);
+ pos.setIndex(index);
+
+ if (index < n) {
+ ret = c;
+ }
+ }
+
+ return ret;
+ }
+
+ /**
+ * Parses <code>source</code> for a special double values. These values
+ * include Double.NaN, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY.
+ *
+ * @param source the string to parse
+ * @param value the special value to parse.
+ * @param pos input/ouput parsing parameter.
+ * @return the special number.
+ */
+ private Number parseNumber(String source, double value, ParsePosition pos) {
+ Number ret = null;
+
+ StringBuffer sb = new StringBuffer();
+ sb.append('(');
+ sb.append(value);
+ sb.append(')');
+
+ int n = sb.length();
+ int startIndex = pos.getIndex();
+ int endIndex = startIndex + n;
+ if (endIndex < source.length()) {
+ if (source.substring(startIndex, endIndex).compareTo(sb.toString()) ==
0) {
+ ret = new Double(value);
+ pos.setIndex(endIndex);
+ }
+ }
+
+ return ret;
+ }
+
+ /**
+ * Parses <code>source</code> for a number. This method can parse normal,
+ * numeric values as well as special values. These special values include
+ * Double.NaN, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY.
+ *
+ * @param source the string to parse
+ * @param format the number format used to parse normal, numeric values.
+ * @param pos input/ouput parsing parameter.
+ * @return the parsed number.
+ */
+ private Number parseNumber(String source, NumberFormat format, ParsePosition
pos) {
+ int startIndex = pos.getIndex();
+ Number number = getRealFormat().parse(source, pos);
+ int endIndex = pos.getIndex();
+
+ // check for error parsing number
+ if (startIndex == endIndex) {
+ // try parsing special numbers
+ double[] special = {Double.NaN, Double.POSITIVE_INFINITY,
Double.NEGATIVE_INFINITY};
+ for (int i = 0; i < special.length; ++i) {
+ number = parseNumber(source, special[i], pos);
+ if (number != null) {
+ break;
+ }
+ }
+ }
+
+ return number;
+ }
+ /**
+ * Parses a string to produce a object.
+ *
+ * @param source the string to parse
+ * @param pos input/ouput parsing parameter.
+ * @return the parsed object.
+ * @see java.text.Format#parseObject(java.lang.String, java.text.ParsePosition)
+ */
+ public Object parseObject(String source, ParsePosition pos) {
+ return parse(source, pos);
+ }
+ /**
+ * Modify the imaginaryCharacter.
+ * @param imaginaryCharacter The new imaginaryCharacter value.
+ * @throws IllegalArgumentException if <code>imaginaryCharacter</code> is
+ * <code>null</code> or an empty string.
+ */
+ public void setImaginaryCharacter(String imaginaryCharacter) {
+ if (imaginaryCharacter == null || imaginaryCharacter.length() == 0) {
+ throw new IllegalArgumentException(
+ "imaginaryCharacter must be a non-empty string.");
+ }
+ this.imaginaryCharacter = imaginaryCharacter;
+ }
+ /**
+ * Modify the imaginaryFormat.
+ * @param imaginaryFormat The new imaginaryFormat value.
+ * @throws IllegalArgumentException if <code>imaginaryFormat</code> is
+ * <code>null</code>.
+ */
+ public void setImaginaryFormat(NumberFormat imaginaryFormat) {
+ if (imaginaryFormat == null) {
+ throw new IllegalArgumentException(
+ "imaginaryFormat can not be null.");
+ }
+ this.imaginaryFormat = imaginaryFormat;
+ }
+
+ /**
+ * Modify the realFormat.
+ * @param realFormat The new realFormat value.
+ * @throws IllegalArgumentException if <code>realFormat</code> is
+ * <code>null</code>.
+ */
+ public void setRealFormat(NumberFormat realFormat) {
+ if (realFormat == null) {
+ throw new IllegalArgumentException(
+ "realFormat can not be null.");
+ }
+ this.realFormat = realFormat;
+ }
+}
1.2 +50 -4 jakarta-commons/math/xdocs/userguide/complex.xml
Index: complex.xml
===================================================================
RCS file: /home/cvs/jakarta-commons/math/xdocs/userguide/complex.xml,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- complex.xml 26 Apr 2004 20:06:50 -0000 1.1
+++ complex.xml 1 Jun 2004 13:47:17 -0000 1.2
@@ -75,9 +75,55 @@
answer = ComplexMath.pow(first, second); // first raised to the power of
second</source>
</p>
</subsection>
- <subsection name="7.4 Complex Formatting" href="formatting">
- <p>This is yet to be written. Any contributions will be gratefully
- accepted!</p>
+ <subsection name="7.4 Complex Formatting and Parsing" href="formatting">
+ <p>
+ <code>Complex</code> instances can be converted to and from strings
+ using the<a
href="../apidocs/org/apache/commons/math/complex/ComplexFormat.html">
+ org.apache.commons.math.complex.ComplexFormat</a> class.
+ <code>ComplexFormat</code> is a <code>java.text.Format</code>
+ extension and, as such, is used like other formatting objects (e.g.
+ <code>java.text.SimpleDateFormat</code>:
+ <source>ComplexFormat format = new ComplexFormat(); // default format
+Complex c = new Complex(1.1111, 2.2222);
+String s = format.format(c); // s contains "1.11 + 2.22i"</source>
+ </p>
+ <p>
+ To customize the formatting output, one or two
+ <code>java.text.NumberFormat</code> instances can be used to construct
+ a <code>ComplexFormat</code>. These number formats control the
+ formatting of the real and imaginary values of the complex number:
+ <source>NumberFormat nf = NumberFormat.getInstance();
+nf.setMinimumFractionDigits(3);
+nf.setMaximumFractionDigits(3);
+
+// create complex format with custom number format
+// when one number format is used, both real and
+// imaginary parts are formatted the same
+ComplexFormat cf = new ComplexFormat(nf);
+Complex c = new Complex(1.11, 2.2222);
+String s = format.format(c); // s contains "1.110 + 2.222i"
+
+NumberFormat nf2 = NumberFormat.getInstance();
+nf.setMinimumFractionDigits(1);
+nf.setMaximumFractionDigits(1);
+
+// create complex format with custom number formats
+cf = new ComplexFormat(nf, nf2);
+s = format.format(c); // s contains "1.110 + 2.2i"</source>
+ </p>
+ <p>
+ Another formatting customization provided by
+ <code>ComplexFormat</code> is the text used for the imaginary
+ designation. By default, the imaginary notation is "i" but, it can
be
+ manipulated using the <code>setImaginaryCharacter</code> method.
+ </p>
+ <p>
+ Formatting inverse operation, parsing, can also be performed by
+ <code>ComplexFormat</code>. Parse a complex number from a string,
+ simply call the <code>parse</code> method:
+ <source>ComplexFormat cf = new ComplexFormat();
+Complex c = cf.parse("1.110 + 2.222i");</source>
+ </p>
</subsection>
</section>
</body>
1.9 +2 -2 jakarta-commons/math/xdocs/userguide/index.xml
Index: index.xml
===================================================================
RCS file: /home/cvs/jakarta-commons/math/xdocs/userguide/index.xml,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- index.xml 26 Apr 2004 20:06:50 -0000 1.8
+++ index.xml 1 Jun 2004 13:47:17 -0000 1.9
@@ -84,7 +84,7 @@
<li><a href="complex.html#overview">7.1 Overview</a></li>
<li><a href="complex.html#complex">7.2 Complex Numbers</a></li>
<li><a href="complex.html#functions">7.3 Complex Transcendental
Functions</a></li>
- <li><a href="complex.html#formatting">7.4 Complex
Formatting</a></li>
+ <li><a href="complex.html#formatting">7.4 Complex Formatting and
Parsing</a></li>
</ul></li>
<li><a href="distribution.html">8. Probability Distributions</a>
<ul>
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]