1 9 package org.jscience.mathematics.functions; 10 11 import java.io.Serializable ; 12 import java.util.List ; 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 27 public final class Term extends RealtimeObject 28 implements Serializable , Comparable <Term> { 29 30 33 public static Term ONE = new Term(); 34 35 38 private FastTable<Variable> _variables = new FastTable<Variable>(); 39 40 43 private int[] _powers = new int[4]; 44 45 48 private Term() { 49 } 50 51 60 public static Term valueOf(Variable v, int n) { 61 if (n == 0) return ONE; 62 if (n < 0) 63 throw new IllegalArgumentException ("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 76 public List <Variable> getVariables() { 77 return _variables.unmodifiable(); 78 } 79 80 88 public int getPower(Variable var) { 89 int i = _variables.indexOf(var); 90 return (i < 0) ? 0 : _powers[i]; 91 } 92 93 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 ( 135 "Found distinct variables with same symbol: " 136 + left.getSymbol()); 137 } 138 } 139 } 140 141 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 (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 (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 (this + "/" + that + 186 " would result in a negative power"); 187 } else { 188 throw new IllegalArgumentException ( 189 "Found distinct variables with same symbol: " 190 + left.getSymbol()); 191 } 192 } 193 } 194 195 202 public boolean equals(Object 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 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 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 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 272 @SuppressWarnings ("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) { 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 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 |