1 9 package javax.measure.units; 10 11 import java.io.Serializable ; 12 13 import javax.measure.converters.ConversionException; 14 import javax.measure.converters.UnitConverter; 15 import javax.measure.quantities.Quantity; 16 17 33 public final class ProductUnit<Q extends Quantity> extends DerivedUnit<Q> { 34 35 38 private final Element[] _elements; 39 40 43 private int _hashCode; 44 45 48 ProductUnit() { 49 _elements = new Element[0]; 50 } 51 52 59 public ProductUnit(Unit productUnit) { 60 _elements = ((ProductUnit)productUnit)._elements; 61 } 62 63 68 private ProductUnit(Element[] elements) { 69 _elements = elements; 70 } 71 72 79 @SuppressWarnings ("unchecked") 80 private static Unit<? extends Quantity> getInstance(Element[] leftElems, 81 Element[] rightElems) { 82 83 Element[] result = new Element[leftElems.length + rightElems.length]; 85 int resultIndex = 0; 86 for (int i = 0; i < leftElems.length; i++) { 87 Unit unit = leftElems[i]._unit; 88 int p1 = leftElems[i]._pow; 89 int r1 = leftElems[i]._root; 90 int p2 = 0; 91 int r2 = 1; 92 for (int j = 0; j < rightElems.length; j++) { 93 if (unit.equals(rightElems[j]._unit)) { 94 p2 = rightElems[j]._pow; 95 r2 = rightElems[j]._root; 96 break; } 98 } 99 int pow = (p1 * r2) + (p2 * r1); 100 int root = r1 * r2; 101 if (pow != 0) { 102 int gcd = gcd(Math.abs(pow), root); 103 result[resultIndex++] = new Element(unit, pow / gcd, root / gcd); 104 } 105 } 106 107 for (int i = 0; i < rightElems.length; i++) { 109 Unit unit = rightElems[i]._unit; 110 boolean hasBeenMerged = false; 111 for (int j = 0; j < leftElems.length; j++) { 112 if (unit.equals(leftElems[j]._unit)) { 113 hasBeenMerged = true; 114 break; 115 } 116 } 117 if (!hasBeenMerged) { 118 result[resultIndex++] = rightElems[i]; 119 } 120 } 121 122 if (resultIndex == 0) { 124 return ONE; 125 } else if ((resultIndex == 1) && (result[0]._pow == result[0]._root)) { 126 return result[0]._unit; 127 } else { 128 Element[] elems = new Element[resultIndex]; 129 for (int i = 0; i < resultIndex; i++) { 130 elems[i] = result[i]; 131 } 132 return new ProductUnit<Quantity>(elems); 133 } 134 } 135 136 143 static Unit<? extends Quantity> getProductInstance(Unit left, Unit right) { 144 Element[] leftElems; 145 if (left instanceof ProductUnit) { 146 leftElems = ((ProductUnit) left)._elements; 147 } else { 148 leftElems = new Element[] { new Element(left, 1, 1) }; 149 } 150 Element[] rightElems; 151 if (right instanceof ProductUnit) { 152 rightElems = ((ProductUnit) right)._elements; 153 } else { 154 rightElems = new Element[] { new Element(right, 1, 1) }; 155 } 156 return getInstance(leftElems, rightElems); 157 } 158 159 166 static Unit<? extends Quantity> getQuotientInstance(Unit left, Unit right) { 167 Element[] leftElems; 168 if (left instanceof ProductUnit) { 169 leftElems = ((ProductUnit) left)._elements; 170 } else { 171 leftElems = new Element[] { new Element(left, 1, 1) }; 172 } 173 Element[] rightElems; 174 if (right instanceof ProductUnit) { 175 Element[] elems = ((ProductUnit) right)._elements; 176 rightElems = new Element[elems.length]; 177 for (int i = 0; i < elems.length; i++) { 178 rightElems[i] = new Element(elems[i]._unit, -elems[i]._pow, 179 elems[i]._root); 180 } 181 } else { 182 rightElems = new Element[] { new Element(right, -1, 1) }; 183 } 184 return getInstance(leftElems, rightElems); 185 } 186 187 196 static Unit<? extends Quantity> getRootInstance(Unit unit, int n) { 197 Element[] unitElems; 198 if (unit instanceof ProductUnit) { 199 Element[] elems = ((ProductUnit) unit)._elements; 200 unitElems = new Element[elems.length]; 201 for (int i = 0; i < elems.length; i++) { 202 int gcd = gcd(Math.abs(elems[i]._pow), elems[i]._root * n); 203 unitElems[i] = new Element(elems[i]._unit, elems[i]._pow / gcd, 204 elems[i]._root * n / gcd); 205 } 206 } else { 207 unitElems = new Element[] { new Element(unit, 1, n) }; 208 } 209 return getInstance(unitElems, new Element[0]); 210 } 211 212 220 static Unit<? extends Quantity> getPowInstance(Unit unit, int n) { 221 Element[] unitElems; 222 if (unit instanceof ProductUnit) { 223 Element[] elems = ((ProductUnit) unit)._elements; 224 unitElems = new Element[elems.length]; 225 for (int i = 0; i < elems.length; i++) { 226 int gcd = gcd(Math.abs(elems[i]._pow * n), elems[i]._root); 227 unitElems[i] = new Element(elems[i]._unit, elems[i]._pow * n 228 / gcd, elems[i]._root / gcd); 229 } 230 } else { 231 unitElems = new Element[] { new Element(unit, n, 1) }; 232 } 233 return getInstance(unitElems, new Element[0]); 234 } 235 236 241 public int getUnitCount() { 242 return _elements.length; 243 } 244 245 253 @SuppressWarnings ("unchecked") 254 public Unit<? extends Quantity> getUnit(int index) { 255 return _elements[index].getUnit(); 256 } 257 258 266 public int getUnitPow(int index) { 267 return _elements[index].getPow(); 268 } 269 270 278 public int getUnitRoot(int index) { 279 return _elements[index].getRoot(); 280 } 281 282 290 public boolean equals(Object that) { 291 if (this == that) 292 return true; 293 if (that instanceof ProductUnit) { 294 Element[] elems = ((ProductUnit) that)._elements; 297 if (_elements.length == elems.length) { 298 for (int i = 0; i < _elements.length; i++) { 299 boolean unitFound = false; 300 for (int j = 0; j < elems.length; j++) { 301 if (_elements[i]._unit.equals(elems[j]._unit)) { 302 if ((_elements[i]._pow != elems[j]._pow) 303 || (_elements[i]._root != elems[j]._root)) { 304 return false; 305 } else { 306 unitFound = true; 307 break; 308 } 309 } 310 } 311 if (!unitFound) { 312 return false; 313 } 314 } 315 return true; 316 } 317 } 318 return false; 319 } 320 321 @Override 322 public int hashCode() { 324 if (_hashCode != 0) 325 return _hashCode; 326 int code = 0; 327 for (int i = 0; i < _elements.length; i++) { 328 code += _elements[i]._unit.hashCode() 329 * (_elements[i]._pow * 3 - _elements[i]._root * 2); 330 } 331 _hashCode = code; 332 return code; 333 } 334 335 @Override 336 @SuppressWarnings ("unchecked") 337 public Unit<? super Q> getSystemUnit() { 338 if (isSystemUnit()) 339 return this; 340 Unit systemUnit = ONE; 341 for (int i = 0; i < _elements.length; i++) { 342 Unit unit = _elements[i]._unit.getSystemUnit(); 343 unit = unit.pow(_elements[i]._pow); 344 unit = unit.root(_elements[i]._root); 345 systemUnit = systemUnit.times(unit); 346 } 347 return systemUnit; 348 } 349 350 @Override 351 public UnitConverter toSystemUnit() { 352 if (isSystemUnit()) 353 return UnitConverter.IDENTITY; 354 UnitConverter converter = UnitConverter.IDENTITY; 355 for (int i = 0; i < _elements.length; i++) { 356 UnitConverter cvtr = _elements[i]._unit.toSystemUnit(); 357 if (!cvtr.isLinear()) 358 throw new ConversionException(_elements[i]._unit 359 + " is non-linear, cannot convert"); 360 if (_elements[i]._root != 1) 361 throw new ConversionException(_elements[i]._unit 362 + " holds a base unit with fractional exponent"); 363 int pow = _elements[i]._pow; 364 if (pow < 0) { pow = -pow; 366 cvtr = cvtr.inverse(); 367 } 368 for (int j = 0; j < pow; j++) { 369 converter = converter.concatenate(cvtr); 370 } 371 } 372 return converter; 373 } 374 375 381 private boolean isSystemUnit() { 382 for (int i = 0; i < _elements.length; i++) { 383 Unit u = _elements[i]._unit; 384 if (!u.getSystemUnit().equals(u)) 385 return false; 386 } 387 return true; 388 } 389 390 397 private static int gcd(int m, int n) { 398 if (n == 0) { 399 return m; 400 } else { 401 return gcd(n, m % n); 402 } 403 } 404 405 408 private final static class Element implements Serializable { 409 410 413 private final Unit _unit; 414 415 418 private final int _pow; 419 420 423 private final int _root; 424 425 432 private Element(Unit unit, int pow, int root) { 433 _unit = unit; 434 _pow = pow; 435 _root = root; 436 } 437 438 443 public Unit getUnit() { 444 return _unit; 445 } 446 447 453 public int getPow() { 454 return _pow; 455 } 456 457 463 public int getRoot() { 464 return _root; 465 } 466 467 private static final long serialVersionUID = 1L; 468 } 469 470 private static final long serialVersionUID = 1L; 471 } | Popular Tags |