/* * @(#)XDouble.java 2.5.0 6 September 2006 * * Copyright 2006 * College of Computer and Information Science * Northeastern University * Boston, MA 02115 * * The Java Power Tools software may be used for educational * purposes as long as this copyright notice is retained intact * at the top of all source files. * * To discuss possible commercial use of this software, * contact Richard Rasala at Northeastern University, * College of Computer and Information Science, * 617-373-2462 or rasala@ccs.neu.edu. * * The Java Power Tools software has been designed and built * in collaboration with Viera Proulx and Jeff Raab. * * Should this software be modified, the words "Modified from * Original" must be included as a comment below this notice. * * All publication rights are retained. This software or its * documentation may not be published in any media either * in whole or in part without explicit permission. * * This software was created with support from Northeastern * University and from NSF grant DUE-9950829. */ package edu.neu.ccs; import edu.neu.ccs.parser.*; import java.beans.*; import java.text.ParseException; /** *

Object wrapper for the primitive * double type that also provides * {@link Stringable Stringable} capabilities.

* *

The default value for this class is * the double representation of zero.

* *

As of 2.5.0, added methods isInfinite and * isNaN in imitation of class Double, * and also added methods isFinite to make the test * for finiteness directly available to a caller.

* * @author Richard Rasala * @author Jeff Raab * @version 2.5.0 */ public class XDouble extends XNumber { /** The wrapped value of this object. */ private double value = 0; /** * Constructs a wrapper for the default * double value. * * @see #XDouble(double) * @see #XDouble(String) */ public XDouble() {} /** * Constructs a wrapper for the given * double value. * * @param d the value to be wrapped * @see #XDouble() * @see #XDouble(String) */ public XDouble(double d) { value = d; } /** * Constructs a wrapper for the double value * whose state information is encapsulated * in the given String data. * * @param s a String representation * of the desired value * @throws ParseException if the data is malformed * @see #XDouble() * @see #XDouble(double) */ public XDouble(String s) throws ParseException { fromStringData(s); } //////////////// // Stringable // //////////////// public void fromStringData(String data) throws ParseException { double oldValue = value; Parser p = ParserUtilities.getDefaultParser(); Object obj = p.parse(data); // store extracted value if (obj instanceof XNumber) { XNumber n = (XNumber)obj; value = n.doubleValue(); } // otherwise throw an exception else { throw new ParseException( "Expected numeric value.", data.length()); } // report property change changeAdapter.firePropertyChange( VALUE, new Double(oldValue), data); } public String toStringData() { return value + ""; } ///////////// // XNumber // ///////////// public byte byteValue() { if ((getValue() > Byte.MAX_VALUE) || (getValue() < Byte.MIN_VALUE)) { throw new NumberFormatException( "Number beyond precision of a byte."); } return (byte)getValue(); } public short shortValue() { if ((getValue() > Short.MAX_VALUE) || (getValue() < Short.MIN_VALUE)) { throw new NumberFormatException( "Number beyond precision of a short."); } return (short)getValue(); } public int intValue() { if ((getValue() > Integer.MAX_VALUE) || (getValue() < Integer.MIN_VALUE)) { throw new NumberFormatException( "Number beyond precision of an int."); } return (int)getValue(); } public long longValue() { if ((getValue() > Long.MAX_VALUE) || (getValue() < Long.MIN_VALUE)) { throw new NumberFormatException( "Number beyond precision of a long."); } return (long)getValue(); } public float floatValue() { if ((getValue() > Float.MAX_VALUE) || (getValue() < -Float.MAX_VALUE)) { throw new NumberFormatException( "Number beyond precision of a float."); } return (float)getValue(); } public double doubleValue() { return getValue(); } //////////////// // Public API // //////////////// /** * Returns true if the wrapped object * is equal to the given object, and false * if it is not. * * @param other the object to be compared with the wrapped object */ public boolean equals(Object other) { if (other instanceof XByte) return getValue() == ((XDouble)other).getValue(); return false; } /** * Returns an int hash code * appropriate for the wrapped object. */ public int hashCode() { return (new Double(getValue())).hashCode(); } /** * Returns a String representation * of the wrapped value. */ public String toString() { return value + ""; } /** * Sets the value wrapped by this object * to the given value. * * @param d the value to be wrapped * @see #getValue() */ public void setValue(double d) { double oldValue = value; value = d; // if the value has changed if (getValue() != oldValue) { // notify listeners of property change changeAdapter.firePropertyChange( VALUE, new Double(oldValue), new Double(getValue())); } } /** * Returns the value wrapped by this object. * * @see #setValue(double) */ public double getValue() { return value; } /** * Returns true if this XDouble is finite, that is, * it is not positive or negative infinity nor * is it NaN. */ public boolean isFinite() { return (! (isInfinite(value) || isNaN(value))); } /** *

Returns true if this XDouble is either * positive or negative infinity.

*/ public boolean isInfinite() { return Double.isInfinite(value); } /** *

Returns true if this XDouble is NaN, * that is, "not a number".

*/ public boolean isNaN() { return Double.isNaN(value); } //////////////////// // Static methods // //////////////////// /** * Returns true if the given double is finite, that is, * it is not positive or negative infinity nor * is it NaN. */ public static boolean isFinite(double v) { return (! (isInfinite(v) || isNaN(v))); } /** *

Returns true if the given double is either * positive or negative infinity.

* *

Identical to Double.isInfinite.

*/ public static boolean isInfinite(double v) { return Double.isInfinite(v); } /** *

Returns true if the given double is NaN, * that is, "not a number".

* *

Identical to Double.isNaN.

*/ public static boolean isNaN(double v) { return Double.isNaN(v); } /** * Parses a double value from a String * using the current shared parser. * * @param s the String data to parse * @return the extracted double value * @throws NumberFormatException if the data is malformed */ public static double parseDouble(String s) throws NumberFormatException { try { return (new XDouble(s)).value; } catch (ParseException e) { throw new NumberFormatException( formatErrorMessage(e, s)); } } /** * Returns an array of primitive double values * copied from the given array * of XDouble objects. * * @param x an array of XDoubles * @return the resulting array * of double values * @see #toXArray(double[]) */ public static double[] toPrimitiveArray(XDouble[] x) { // return null array if appropriate if (x == null) return null; // otherwise perform the type translation double[] temp = new double[x.length]; for (int i = 0; i < temp.length; i++) if (x[i] != null) temp[i] = x[i].getValue(); return temp; } /** * Returns an array of XDouble objects * initialized from the given array * of double values. * * @param a an array of doubles * @return the resulting array * of XDouble objects * @see #toPrimitiveArray(XDouble[]) */ public static XDouble[] toXArray(double[] a) { // return null array if appropriate if (a == null) return null; // otherwise perform the type translation XDouble[] temp = new XDouble[a.length]; for (int i = 0; i < temp.length; i++) temp[i] = new XDouble(a[i]); return temp; } }