001/*
002 * JScience - Java(TM) Tools and Libraries for the Advancement of Sciences.
003 * Copyright (C) 2006 - JScience (http://jscience.org/)
004 * All rights reserved.
005 * 
006 * Permission to use, copy, modify, and distribute this software is
007 * freely granted, provided that this notice is preserved.
008 */
009package org.jscience.mathematics.number;
010
011import org.jscience.mathematics.structure.Ring;
012import javolution.lang.Realtime;
013import javolution.text.Text;
014import javolution.xml.XMLSerializable;
015
016/**
017 * <p> This class represents a {@link javolution.lang.ValueType value-type}
018 *     number.</p>
019 *
020 * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
021 * @version 3.0, February 13, 2006
022 * @see <a href="http://en.wikipedia.org/wiki/Number">
023 *      Wikipedia: Number</a>
024 */
025public abstract class Number<T extends Number<T>> extends java.lang.Number
026        implements Ring<T>, Comparable<T>, Realtime, XMLSerializable {
027
028    /**
029     * Compares the magnitude of this number with that number.
030     *
031     * @return <code>|this| > |that|</code>
032     */
033    public abstract boolean isLargerThan(T that);
034
035    /**
036     * Returns the value of this number as a <code>long</code>.
037     *
038     * @return  the numeric value represented by this object after conversion
039     *          to type <code>long</code>.
040     */
041    public abstract long longValue();
042
043    /**
044     * Returns the value of this number as a <code>double</code>.
045     *
046     * @return  the numeric value represented by this object after conversion
047     *          to type <code>double</code>.
048     */
049    public abstract double doubleValue();
050
051    /**
052     * Compares this number with the specified number for order.  Returns a
053     * negative integer, zero, or a positive integer as this number is less
054     * than, equal to, or greater than the specified number. 
055     * Implementation must ensure that this method is consistent with equals 
056     * <code>(x.compareTo(y)==0) == (x.equals(y))</code>,  
057     * 
058     * @param that the number to be compared.
059     * @return a negative integer, zero, or a positive integer as this number
060     *        is less than, equal to, or greater than the specified number.
061     */
062    public abstract int compareTo(T that);
063
064    /**
065     * Indicates if this number is ordered before that number
066     * (convenience method).
067     *
068     * @param that the number to compare with.
069     * @return <code>this.compareTo(that) < 0</code>.
070     */
071    public final boolean isLessThan(T that) {
072        return this.compareTo(that) < 0;
073    }
074
075    /**
076     * Indicates if this number is ordered after that number
077     * (convenience method).
078     *
079     * @param that the number to compare with.
080     * @return <code>this.compareTo(that) > 0</code>.
081     */
082    public final boolean isGreaterThan(T that) {
083        return this.compareTo(that) > 0;
084    }
085
086    /**
087     * Returns the difference between this number and the one specified.
088     *
089     * @param  that the number to be subtracted.
090     * @return <code>this - that</code>.
091     */
092    public T minus(T that) {
093        return this.plus(that.opposite());
094    }
095
096    /**
097     * Returns this number raised at the specified positive exponent.
098     *
099     * @param  exp the positive exponent.
100     * @return <code>this<sup>exp</sup></code>
101     * @throws IllegalArgumentException if <code>exp &lt;= 0</code> 
102     */
103    @SuppressWarnings("unchecked")
104    public T pow(int exp) {
105        if (exp <= 0)
106            throw new IllegalArgumentException("exp: " + exp
107                    + " should be a positive number");
108        final T t = (T) this;
109        if (exp == 1) return t;
110        if (exp == 2) return t.times(t);
111        if (exp == 3) return t.times(t).times(t);
112        int halfExp = exp >> 1;
113        return this.pow(halfExp).times(this.pow(exp - halfExp));
114    }
115
116    /**
117     * Returns the value of this number as a <code>byte</code>.
118     * This may involve rounding or truncation.
119     *
120     * @return  the numeric value represented by this object after conversion
121     *          to type <code>byte</code>.
122     */
123    public final byte byteValue() {
124        return (byte) longValue();
125    }
126
127    /**
128     * Returns the value of this number as a <code>short</code>.
129     * This may involve rounding or truncation.
130     *
131     * @return  the numeric value represented by this object after conversion
132     *          to type <code>short</code>.
133     */
134    public final short shortValue() {
135        return (short) longValue();
136    }
137
138    /**
139     * Returns the value of this number as an <code>int</code>.
140     * This may involve rounding or truncation.
141     *
142     * @return  the numeric value represented by this object after conversion
143     *          to type <code>int</code>.
144     */
145    public final int intValue() {
146        return (int) longValue();
147    }
148
149    /**
150     * Returns the value of this number as a <code>float</code>.
151     * This may involve rounding.
152     *
153     * @return  the numeric value represented by this object after conversion
154     *          to type <code>float</code>.
155     */
156    public final float floatValue() {
157        return (float) doubleValue();
158    }
159    /**
160     * Indicates if this number is equals to the specified object.
161     *
162     * @param obj the object to be compared with.
163     * @return <code>true</code> if this number and the specified argument
164     *         represent the same number; <code>false</code> otherwise.
165     */
166    public abstract boolean equals(Object obj);
167
168    /**
169     * Returns the hash code for this number (consistent with 
170     * {@link #equals(Object)}.
171     *
172     * @return this number hash code.
173     */
174    public abstract int hashCode();
175
176    /**
177     * Returns the textual representation of this real-time object
178     * (equivalent to <code>toString</code> except that the returned value
179     * can be allocated from the local context space).
180     * 
181     * @return this object's textual representation.
182     */
183    public abstract Text toText();
184
185    /**
186     * Returns a copy of this number 
187     * {@link javolution.context.AllocatorContext allocated} 
188     * by the calling thread (possibly on the stack).
189     *     
190     * @return an identical and independant copy of this number.
191     */
192    public abstract Number<T> copy();
193
194    /**
195     * Returns the text representation of this number as a 
196     * <code>java.lang.String</code>.
197     * 
198     * @return <code>toText().toString()</code>
199     */
200    public final String toString() {
201        return toText().toString();
202    }
203
204}