commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From brentwor...@apache.org
Subject cvs commit: jakarta-commons/math/xdocs/userguide complex.xml index.xml
Date Tue, 01 Jun 2004 13:47:17 GMT
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
  +     * {@link NumberFormat#getInstance()} with the only customizing is the
  +     * maximum number of fraction digits, which is set to 2.  
  +     *
  +     * @return the default number format.
  +     */
  +    private static NumberFormat getDefaultNumberFormat() {
  +        NumberFormat nf = NumberFormat.getInstance();
  +        nf.setMaximumFractionDigits(2);
  +        return nf;
  +    }
  +    
  +    /**
  +     * Formats a {@link 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 
  +     * {@link Complex} object or a {@link Number} object.  Any other type of
  +     * object will result in an {@link 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 {@link 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 {@link 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 {@link Complex} object.
  +     *
  +     * @param source the string to parse
  +     * @param pos input/ouput parsing parameter.
  +     * @return the parsed {@link 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: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


Mime
View raw message