1 9 package org.jscience.physics.units; 10 11 import java.io.Serializable ; 12 import org.jscience.physics.quantities.Quantity; 13 14 import javolution.lang.MathLib; 15 16 31 public final class ProductUnit<Q extends Quantity> extends DerivedUnit<Q> { 32 33 36 private final Element[] _elements; 37 38 41 ProductUnit() { 42 _elements = new Element[0]; 43 } 44 45 50 private ProductUnit(Element[] elements) { 51 _elements = elements; 52 } 53 54 61 static Unit getInstance(Element[] leftElems, Element[] rightElems) { 62 63 Element[] result = new Element[leftElems.length + rightElems.length]; 65 int resultIndex = 0; 66 for (int i = 0; i < leftElems.length; i++) { 67 Unit unit = leftElems[i]._unit; 68 int p1 = leftElems[i]._pow; 69 int r1 = leftElems[i]._root; 70 int p2 = 0; 71 int r2 = 1; 72 for (int j = 0; j < rightElems.length; j++) { 73 if (unit == rightElems[j]._unit) { 74 p2 = rightElems[j]._pow; 75 r2 = rightElems[j]._root; 76 break; } 78 } 79 int pow = (p1 * r2) + (p2 * r1); 80 int root = r1 * r2; 81 if (pow != 0) { 82 int gcd = gcd(MathLib.abs(pow), root); 83 result[resultIndex++] = new Element(unit, pow / gcd, root / gcd); 84 } 85 } 86 87 for (int i = 0; i < rightElems.length; i++) { 89 Unit unit = rightElems[i]._unit; 90 boolean hasBeenMerged = false; 91 for (int j = 0; j < leftElems.length; j++) { 92 if (unit == leftElems[j]._unit) { 93 hasBeenMerged = true; 94 break; 95 } 96 } 97 if (!hasBeenMerged) { 98 result[resultIndex++] = rightElems[i]; 99 } 100 } 101 102 if (resultIndex == 0) { 104 return ONE; 105 } else if ((resultIndex == 1) && (result[0]._pow == result[0]._root)) { 106 return result[0]._unit; 107 } else { 108 Element[] elems = new Element[resultIndex]; 109 for (int i = 0; i < resultIndex; i++) { 110 elems[i] = result[i]; 111 } 112 return getInstance(new ProductUnit(elems)); 113 } 114 } 115 116 123 static Unit getProductInstance(Unit left, Unit right) { 124 Element[] leftElems; 125 if (left instanceof ProductUnit) { 126 leftElems = ((ProductUnit) left)._elements; 127 } else { 128 leftElems = new Element[] { new Element(left, 1, 1) }; 129 } 130 Element[] rightElems; 131 if (right instanceof ProductUnit) { 132 rightElems = ((ProductUnit) right)._elements; 133 } else { 134 rightElems = new Element[] { new Element(right, 1, 1) }; 135 } 136 return getInstance(leftElems, rightElems); 137 } 138 139 146 static Unit getQuotientInstance(Unit left, Unit right) { 147 Element[] leftElems; 148 if (left instanceof ProductUnit) { 149 leftElems = ((ProductUnit) left)._elements; 150 } else { 151 leftElems = new Element[] { new Element(left, 1, 1) }; 152 } 153 Element[] rightElems; 154 if (right instanceof ProductUnit) { 155 Element[] elems = ((ProductUnit) right)._elements; 156 rightElems = new Element[elems.length]; 157 for (int i = 0; i < elems.length; i++) { 158 rightElems[i] = new Element(elems[i]._unit, -elems[i]._pow, 159 elems[i]._root); 160 } 161 } else { 162 rightElems = new Element[] { new Element(right, -1, 1) }; 163 } 164 return getInstance(leftElems, rightElems); 165 } 166 167 176 static Unit getRootInstance(Unit unit, int n) { 177 Element[] unitElems; 178 if (unit instanceof ProductUnit) { 179 Element[] elems = ((ProductUnit) unit)._elements; 180 unitElems = new Element[elems.length]; 181 for (int i = 0; i < elems.length; i++) { 182 int gcd = gcd(MathLib.abs(elems[i]._pow), elems[i]._root * n); 183 unitElems[i] = new Element(elems[i]._unit, elems[i]._pow / gcd, 184 elems[i]._root * n / gcd); 185 } 186 } else { 187 unitElems = new Element[] { new Element(unit, 1, n) }; 188 } 189 return getInstance(unitElems, new Element[0]); 190 } 191 192 200 static Unit getPowInstance(Unit unit, int n) { 201 Element[] unitElems; 202 if (unit instanceof ProductUnit) { 203 Element[] elems = ((ProductUnit) unit)._elements; 204 unitElems = new Element[elems.length]; 205 for (int i = 0; i < elems.length; i++) { 206 int gcd = gcd(MathLib.abs(elems[i]._pow * n), elems[i]._root); 207 unitElems[i] = new Element(elems[i]._unit, elems[i]._pow * n 208 / gcd, elems[i]._root / gcd); 209 } 210 } else { 211 unitElems = new Element[] { new Element(unit, n, 1) }; 212 } 213 return getInstance(unitElems, new Element[0]); 214 } 215 216 221 public int size() { 222 return _elements.length; 223 } 224 225 233 public Element get(int index) { 234 return _elements[index]; 235 } 236 237 protected boolean equalsImpl(Object that) { 239 if (that instanceof ProductUnit) { 240 Element[] elems = ((ProductUnit) that)._elements; 243 if (_elements.length == elems.length) { 244 for (int i = 0; i < _elements.length; i++) { 245 boolean unitFound = false; 246 for (int j = 0; j < elems.length; j++) { 247 if (_elements[i]._unit == elems[j]._unit) { 248 if ((_elements[i]._pow != elems[j]._pow) 249 || (_elements[i]._root != elems[j]._root)) { 250 return false; 251 } else { 252 unitFound = true; 253 break; 254 } 255 } 256 } 257 if (!unitFound) { 258 return false; 259 } 260 } 261 return true; 262 } 263 } 264 return false; 265 } 266 267 protected int hashCodeImpl() { 269 int code = 0; 270 for (int i = 0; i < _elements.length; i++) { 271 code += _elements[i]._unit.hashCode() 272 * (_elements[i]._pow * 3 - _elements[i]._root * 2); 273 } 274 return code; 275 } 276 277 protected Unit<Q> getParentUnitImpl() { 279 if (isProductOfBaseUnits()) return this; 280 Unit parentUnit = ONE; 281 for (int i = 0; i < _elements.length; i++) { 282 Unit unit = _elements[i]._unit.getParentUnit(); 283 unit = unit.pow(_elements[i]._pow); 284 unit = unit.root(_elements[i]._root); 285 parentUnit = parentUnit.times(unit); 286 } 287 return parentUnit; 288 } 289 290 protected Converter toParentUnitImpl() { 292 if (isProductOfBaseUnits()) return Converter.IDENTITY; 293 double factor = 1.0; 294 for (int i = 0; i < _elements.length; i++) { 295 Converter cvtr = _elements[i]._unit.toParentUnit(); 296 if (cvtr.isLinear()) { 297 factor *= MathLib.pow(cvtr.derivative(0), 298 ((double) _elements[i]._pow) 299 / ((double) _elements[i]._root)); 300 } else { 301 throw new ConversionException(_elements[i]._unit 303 + " is non-linear, cannot convert"); 304 } 305 } 306 if (MathLib.abs(factor - 1.0) < 1e-9) { 307 return Converter.IDENTITY; 308 } else { 309 return new MultiplyConverter(factor); 310 } 311 } 312 313 319 private boolean isProductOfBaseUnits() { 320 for (int i = 0; i < _elements.length; i++) { 321 if (!(_elements[i]._unit instanceof BaseUnit)) { 322 return false; 323 } 324 } 325 return true; 326 } 327 328 335 private static int gcd(int m, int n) { 336 if (n == 0) { 337 return m; 338 } else { 339 return gcd(n, m % n); 340 } 341 } 342 343 346 public final static class Element implements Serializable { 347 348 351 private final Unit _unit; 352 353 356 private final int _pow; 357 358 361 private final int _root; 362 363 370 private Element(Unit unit, int pow, int root) { 371 _unit = unit; 372 _pow = pow; 373 _root = root; 374 } 375 376 381 public Unit getUnit() { 382 return _unit; 383 } 384 385 391 public int getPow() { 392 return _pow; 393 } 394 395 401 public int getRoot() { 402 return _root; 403 } 404 405 private static final long serialVersionUID = 1L; 406 } 407 408 private static final long serialVersionUID = 1L; 409 } | Popular Tags |