KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jscience > mathematics > functions > Term


1 /*
2  * JScience - Java(TM) Tools and Libraries for the Advancement of Sciences.
3  * Copyright (C) 2006 - JScience (http://jscience.org/)
4  * All rights reserved.
5  *
6  * Permission to use, copy, modify, and distribute this software is
7  * freely granted, provided that this notice is preserved.
8  */

9 package org.jscience.mathematics.functions;
10
11 import java.io.Serializable JavaDoc;
12 import java.util.List JavaDoc;
13 import org.jscience.mathematics.structures.Ring;
14 import javolution.lang.MathLib;
15 import javolution.text.Text;
16 import javolution.text.TextBuilder;
17 import javolution.context.RealtimeObject;
18 import javolution.util.FastTable;
19
20 /**
21  * This class represents the term of a {@link Polynomial polynomial}
22  * such as <code>x·y²</code>.
23  *
24  * @author <a HREF="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
25  * @version 3.0, February 13, 2006
26  */

27 public final class Term extends RealtimeObject
28      implements Serializable JavaDoc, Comparable JavaDoc<Term> {
29
30     /**
31      * Holds the multiplicative identity.
32      */

33     public static Term ONE = new Term();
34     
35     /**
36      * Holds the variables (ordered).
37      */

38     private FastTable<Variable> _variables = new FastTable<Variable>();
39
40     /**
41      * Holds the corresponding powers (positive and different from zero).
42      */

43     private int[] _powers = new int[4];
44
45     /**
46      * Default constructor.
47      */

48     private Term() {
49     }
50
51     /**
52      * Return the term corresponding to the specified variable raised to
53      * the specified power.
54      *
55      * @param v the variable.
56      * @param n the power.
57      * @return the term for <code>v<sup>n</sup></code>
58      * @throws IllegalArgumentException if <code>n &lt; 0</code>
59      */

60     public static Term valueOf(Variable v, int n) {
61         if (n == 0) return ONE;
62         if (n < 0)
63             throw new IllegalArgumentException JavaDoc("n: " + n
64                     + " negative values are not allowed");
65         Term term = Term.newInstance(1);
66         term._variables.add(v);
67         term._powers[0] = n;
68         return term;
69     }
70
71     /**
72      * Returns the variables for this term (lexically ordered).
73      *
74      * @return this term variables.
75      */

76     public List JavaDoc<Variable> getVariables() {
77         return _variables.unmodifiable();
78     }
79
80     /**
81      * Returns the power of the specified variable.
82      *
83      * @param var the variable for which the power is returned.
84      * @return the power of the corresponding variable or <code>0</code> if
85      * this term does not hold the specified variable.
86      * @throws IllegalArgumentException if <code>(i < 0) || (i >= length())</code>
87      */

88     public int getPower(Variable var) {
89         int i = _variables.indexOf(var);
90         return (i < 0) ? 0 : _powers[i];
91     }
92
93     /**
94      * Return the product of this term with the one specified.
95      *
96      * @param that the term multiplier.
97      * @return <code>this · that</code>
98      * @throws IllegalArgumentException if the specified term holds a
99      * variable having the same symbol as one of the variable of
100      * this term; but both variables are distinct.
101      */

102     public Term times(Term that) {
103         final int thisSize = this._variables.size();
104         final int thatSize = that._variables.size();
105         Term result = Term.newInstance(thisSize + thatSize);
106         for (int i=0, j =0;;) {
107             Variable left = (i < thisSize) ? this._variables.get(i) : null;
108             Variable right = (j < thatSize) ? that._variables.get(j) : null;
109             if (left == null) {
110                 if (right == null) return result;
111                 result._powers[result._variables.size()] = that._powers[j++];
112                 result._variables.add(right);
113                 continue;
114             }
115             if (right == null) {
116                 result._powers[result._variables.size()] = this._powers[i++];
117                 result._variables.add(left);
118                 continue;
119             }
120             if (right == left) {
121                 result._powers[result._variables.size()]
122                                = this._powers[i++] + that._powers[j++];
123                 result._variables.add(right);
124                 continue;
125             }
126             final int cmp = left.getSymbol().compareTo(right.getSymbol());
127             if (cmp < 0) {
128                 result._powers[result._variables.size()] = this._powers[i++];
129                 result._variables.add(left);
130             } else if (cmp > 0) {
131                 result._powers[result._variables.size()] = that._powers[j++];
132                 result._variables.add(right);
133             } else {
134                 throw new IllegalArgumentException JavaDoc(
135                         "Found distinct variables with same symbol: "
136                             + left.getSymbol());
137             }
138         }
139     }
140
141     /**
142      * Return the division of this term with the one specified.
143      *
144      * @param that the term divisor.
145      * @return <code>this / that</code>
146      * @throws UnsupportedOperationException if this division would
147      * result in negative power.
148      * @throws IllegalArgumentException if the specified term holds a
149      * variable having the same symbol as one of the variable of
150      * this term; but both variables are distinct.
151      */

152     public Term divide(Term that) {
153         final int thisSize = this._variables.size();
154         final int thatSize = that._variables.size();
155         Term result = Term.newInstance(MathLib.max(thisSize, thatSize));
156         for (int i=0, j =0;;) {
157             Variable left = (i < thisSize) ? this._variables.get(i) : null;
158             Variable right = (j < thatSize) ? that._variables.get(j) : null;
159             if (left == null) {
160                 if (right == null) return result;
161                 throw new UnsupportedOperationException JavaDoc(this + "/" + that +
162                         " would result in a negative power");
163             }
164             if (right == null) {
165                 result._powers[result._variables.size()] = this._powers[i++];
166                 result._variables.add(left);
167                 continue;
168             }
169             if (right == left) {
170                 final int power = this._powers[i++] - that._powers[j++];
171                 if (power < 0)
172                     throw new UnsupportedOperationException JavaDoc(this + "/" + that +
173                     " would result in a negative power");
174                 if (power > 0) {
175                     result._powers[result._variables.size()] = power;
176                     result._variables.add(right);
177                 }
178                 continue;
179             }
180             final int cmp = left.getSymbol().compareTo(right.getSymbol());
181             if (cmp < 0) {
182                 result._powers[result._variables.size()] = this._powers[i++];
183                 result._variables.add(left);
184             } else if (cmp > 0) {
185                 throw new UnsupportedOperationException JavaDoc(this + "/" + that +
186                       " would result in a negative power");
187             } else {
188                 throw new IllegalArgumentException JavaDoc(
189                         "Found distinct variables with same symbol: "
190                             + left.getSymbol());
191             }
192         }
193     }
194
195     /**
196      * Indicates if this term is equal to the object specified.
197      *
198      * @param obj the object to compare for equality.
199      * @return <code>true</code> if this term and the specified object are
200      * considered equal; <code>false</code> otherwise.
201      */

202     public boolean equals(Object JavaDoc obj) {
203         if (this == obj) return true;
204         if (!(obj instanceof Term)) return false;
205         Term that = (Term) obj;
206         if (!this._variables.equals(that._variables)) return false;
207         final int size = this._variables.size();
208         for (int i=0; i < size; i++) {
209             if (this._powers[i] != that._powers[i])
210                 return false;
211         }
212         return true;
213     }
214
215     /**
216      * Returns a hash code for this term.
217      *
218      * @return a hash code value for this object.
219      */

220     public final int hashCode() {
221         int h = 0;
222         final int size = this._variables.size();
223         for (int i=0; i < size; i++) {
224             h += _variables.get(i).hashCode() * _powers[i];
225         }
226         return h;
227     }
228
229     /**
230      * Returns the text representation of this term.
231      */

232     public Text toText() {
233         TextBuilder tb = TextBuilder.newInstance();
234         final int size = this._variables.size();
235         for (int i=0; i < size; i++) {
236             tb.append(_variables.get(i).getSymbol());
237             int power = _powers[i];
238             if (power > 1) {
239                 tb.append('^');
240                 tb.append(_powers[i]);
241             }
242         }
243         return tb.toText();
244     }
245
246     /**
247      * Compares this term with the one specified for order.
248      *
249      * @param that the term to be compared to.
250      * @return a negative integer, zero, or a positive integer as this term
251      * is less than, equal to, or greater than the specified term.
252      */

253     public int compareTo(Term that) {
254         int n = Math.min(this._variables.size(), that._variables.size());
255         for (int i=0; i < n; i++) {
256             int cmp = this._variables.get(i).getSymbol().compareTo(
257                     that._variables.get(i).getSymbol());
258             if (cmp != 0) return cmp;
259             cmp = that._powers[i] - this._powers[i];
260             if (cmp != 0) return cmp;
261         }
262         return that._variables.size() - this._variables.size();
263     }
264
265     /**
266      * Evaluates this term by replacing its {@link Variable
267      * variables} by their current (context-local) values.
268      *
269      * @return the evaluation of this term or <code>null</code> if ONE.
270      * @throws FunctionException if any of this term's variable is not set.
271      */

272     @SuppressWarnings JavaDoc("unchecked")
273     Ring evaluate() {
274         Ring result = null;
275         final int size = this._variables.size();
276         for (int i=0; i < size; i++) {
277             Ring pow2 = (Ring)_variables.get(i).get();
278             if (pow2 == null)
279                 throw new FunctionException("Variable: " + _variables.get(i)
280                         + " is not set");
281             int n = _powers[i];
282             while (n >= 1) { // Iteration.
283
if ((n & 1) == 1) {
284                     result = (result == null) ? pow2 :
285                         (Ring) result.times(pow2);
286                 }
287                 pow2 = (Ring) pow2.times(pow2);
288                 n >>>= 1;
289             }
290         }
291         return result;
292     }
293
294     /**
295      * Returns a new instance of specified capacity.
296      *
297      * @param capacity the minimum number of variables.
298      * @return the corresponding instance.
299      */

300     private static Term newInstance(int capacity) {
301         Term term = FACTORY.object();
302         if (term._powers.length < capacity) {
303             term._powers = new int[capacity];
304         }
305         return term;
306     }
307     
308     private static final Factory<Term> FACTORY = new Factory<Term>() {
309
310         protected Term create() {
311             return new Term();
312         }
313         protected void cleanup(Term term) {
314             term._variables.reset();
315         }
316     };
317     
318     private static final long serialVersionUID = 1L;
319 }
Popular Tags