EMMA Coverage Report (generated Sun Feb 05 10:43:15 CET 2012)
[all classes][javax.measure.unit]

COVERAGE SUMMARY FOR SOURCE FILE [ProductUnit.java]

nameclass, %method, %block, %line, %
ProductUnit.java0%   (0/2)0%   (0/26)0%   (0/832)0%   (0/156)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class ProductUnit0%   (0/1)0%   (0/18)0%   (0/796)0%   (0/145)
ProductUnit (): void 0%   (0/1)0%   (0/7)0%   (0/3)
ProductUnit (ProductUnit$Element []): void 0%   (0/1)0%   (0/6)0%   (0/3)
ProductUnit (Unit): void 0%   (0/1)0%   (0/8)0%   (0/3)
equals (Object): boolean 0%   (0/1)0%   (0/81)0%   (0/18)
gcd (int, int): int 0%   (0/1)0%   (0/10)0%   (0/3)
getInstance (ProductUnit$Element [], ProductUnit$Element []): Unit 0%   (0/1)0%   (0/180)0%   (0/35)
getPowInstance (Unit, int): Unit 0%   (0/1)0%   (0/76)0%   (0/9)
getProductInstance (Unit, Unit): Unit 0%   (0/1)0%   (0/46)0%   (0/7)
getQuotientInstance (Unit, Unit): Unit 0%   (0/1)0%   (0/78)0%   (0/11)
getRootInstance (Unit, int): Unit 0%   (0/1)0%   (0/76)0%   (0/9)
getStandardUnit (): Unit 0%   (0/1)0%   (0/45)0%   (0/9)
getUnit (int): Unit 0%   (0/1)0%   (0/6)0%   (0/1)
getUnitCount (): int 0%   (0/1)0%   (0/4)0%   (0/1)
getUnitPow (int): int 0%   (0/1)0%   (0/6)0%   (0/1)
getUnitRoot (int): int 0%   (0/1)0%   (0/6)0%   (0/1)
hasOnlyStandardUnit (): boolean 0%   (0/1)0%   (0/22)0%   (0/5)
hashCode (): int 0%   (0/1)0%   (0/47)0%   (0/8)
toStandardUnit (): UnitConverter 0%   (0/1)0%   (0/92)0%   (0/18)
     
class ProductUnit$Element0%   (0/1)0%   (0/8)0%   (0/36)0%   (0/11)
ProductUnit$Element (Unit, int, int): void 0%   (0/1)0%   (0/12)0%   (0/5)
ProductUnit$Element (Unit, int, int, ProductUnit$Element): void 0%   (0/1)0%   (0/6)0%   (0/1)
access$0 (ProductUnit$Element): Unit 0%   (0/1)0%   (0/3)0%   (0/1)
access$1 (ProductUnit$Element): int 0%   (0/1)0%   (0/3)0%   (0/1)
access$2 (ProductUnit$Element): int 0%   (0/1)0%   (0/3)0%   (0/1)
getPow (): int 0%   (0/1)0%   (0/3)0%   (0/1)
getRoot (): int 0%   (0/1)0%   (0/3)0%   (0/1)
getUnit (): Unit 0%   (0/1)0%   (0/3)0%   (0/1)

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 */
9package javax.measure.unit;
10 
11import java.io.Serializable;
12 
13import javax.measure.converter.ConversionException;
14import javax.measure.converter.UnitConverter;
15import javax.measure.quantity.Quantity;
16 
17/**
18 * <p> This class represents units formed by the product of rational powers of
19 *     existing units.</p>
20 *     
21 * <p> This class maintains the canonical form of this product (simplest
22 *     form after factorization). For example:
23 *     <code>METER.pow(2).divide(METER)</code> returns
24 *     <code>METER</code>.</p>
25 *
26 * @author  <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
27 * @version 3.1, April 22, 2006
28 * @see     Unit#times(Unit)
29 * @see     Unit#divide(Unit)
30 * @see     Unit#pow(int)
31 * @see     Unit#root(int)
32 */
33public final class ProductUnit<Q extends Quantity> extends DerivedUnit<Q> {
34 
35    /**
36     * Holds the units composing this product unit.
37     */
38    private final Element[] _elements;
39 
40    /**
41     * Holds the hashcode (optimization).
42     */
43    private int _hashCode;
44 
45    /**
46     * Default constructor (used solely to create <code>ONE</code> instance).
47     */
48    ProductUnit() {
49        _elements = new Element[0];
50    }
51 
52    /**
53     * Copy constructor (allows for parameterization of product units).
54     *
55     * @param productUnit the product unit source.
56     * @throws ClassCastException if the specified unit is not 
57     *         a product unit.
58     */
59    public ProductUnit(Unit<?> productUnit) {
60        _elements = ((ProductUnit<?>)productUnit)._elements;        
61    }
62 
63    /**
64     * Product unit constructor.
65     *
66     * @param  elements the product elements.
67     */
68    private ProductUnit(Element[] elements) {
69        _elements = elements;
70    }
71 
72    /**
73     * Returns the unit defined from the product of the specifed elements.
74     *
75     * @param  leftElems left multiplicand elements.
76     * @param  rightElems right multiplicand elements.
77     * @return the corresponding unit.
78     */
79    @SuppressWarnings("unchecked")
80    private static Unit<? extends Quantity> getInstance(Element[] leftElems,
81            Element[] rightElems) {
82 
83        // Merges left elements with right elements.
84        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; // No duplicate.
97                }
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        // Appends remaining right elements not merged.
108        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        // Returns or creates instance.
123        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    /**
137     * Returns the product of the specified units.
138     *
139     * @param  left the left unit operand.
140     * @param  right the right unit operand.
141     * @return <code>left * right</code>
142     */
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    /**
160     * Returns the quotient of the specified units.
161     *
162     * @param  left the dividend unit operand.
163     * @param  right the divisor unit operand.
164     * @return <code>dividend / divisor</code>
165     */
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    /**
188     * Returns the product unit corresponding to the specified root of
189     * the specified unit.
190     *
191     * @param  unit the unit.
192     * @param  n the root's order (n &gt; 0).
193     * @return <code>unit^(1/nn)</code>
194     * @throws ArithmeticException if <code>n == 0</code>.
195     */
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    /**
213     * Returns the product unit corresponding to this unit raised to
214     * the specified exponent.
215     *
216     * @param  unit the unit.
217     * @param  nn the exponent (nn &gt; 0).
218     * @return <code>unit^n</code>
219     */
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    /**
237     * Returns the number of units in this product.
238     *
239     * @return  the number of units being multiplied.
240     */
241    public int getUnitCount() {
242        return _elements.length;
243    }
244 
245    /**
246     * Returns the unit at the specified position.
247     *
248     * @param  index the index of the unit to return.
249     * @return the unit at the specified position.
250     * @throws IndexOutOfBoundsException if index is out of range
251     *         <code>(index &lt; 0 || index &gt;= size())</code>.
252     */
253    @SuppressWarnings("unchecked")
254    public Unit<? extends Quantity> getUnit(int index) {
255        return _elements[index].getUnit();
256    }
257 
258    /**
259     * Returns the power exponent of the unit at the specified position.
260     *
261     * @param  index the index of the unit to return.
262     * @return the unit power exponent at the specified position.
263     * @throws IndexOutOfBoundsException if index is out of range
264     *         <code>(index &lt; 0 || index &gt;= size())</code>.
265     */
266    public int getUnitPow(int index) {
267        return _elements[index].getPow();
268    }
269 
270    /**
271     * Returns the root exponent of the unit at the specified position.
272     *
273     * @param  index the index of the unit to return.
274     * @return the unit root exponent at the specified position.
275     * @throws IndexOutOfBoundsException if index is out of range
276     *         <code>(index &lt; 0 || index &gt;= size())</code>.
277     */
278    public int getUnitRoot(int index) {
279        return _elements[index].getRoot();
280    }
281 
282    /**
283     * Indicates if this product unit is considered equals to the specified 
284     * object.
285     *
286     * @param  that the object to compare for equality.
287     * @return <code>true</code> if <code>this</code> and <code>that</code>
288     *         are considered equals; <code>false</code>otherwise. 
289     */
290    public boolean equals(Object that) {
291        if (this == that)
292            return true;
293        if (that instanceof ProductUnit) {
294            // Two products are equals if they have the same elements
295            // regardless of the elements' order.
296            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    // Implements abstract method.
323    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> getStandardUnit() {
338        if (hasOnlyStandardUnit())
339            return this;
340        Unit systemUnit = ONE;
341        for (int i = 0; i < _elements.length; i++) {
342            Unit unit = _elements[i]._unit.getStandardUnit();
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 toStandardUnit() {
352        if (hasOnlyStandardUnit())
353            return UnitConverter.IDENTITY;
354        UnitConverter converter = UnitConverter.IDENTITY;
355        for (int i = 0; i < _elements.length; i++) {
356            UnitConverter cvtr = _elements[i]._unit.toStandardUnit();
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) { // Negative power.
365                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    /**
376     * Indicates if this product unit is a standard unit.
377     *
378     * @return <code>true</code> if all elements are standard units;
379     *         <code>false</code> otherwise.
380     */
381    private boolean hasOnlyStandardUnit() {
382        for (int i = 0; i < _elements.length; i++) {
383            Unit<?> u = _elements[i]._unit;
384            if (!u.isStandardUnit())
385                return false;
386        }
387        return true;
388    }
389 
390    /**
391     * Returns the greatest common divisor (Euclid's algorithm).
392     *
393     * @param  m the first number.
394     * @param  nn the second number.
395     * @return the greatest common divisor.
396     */
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    /**
406     * Inner product element represents a rational power of a single unit.
407     */
408    private final static class Element implements Serializable {
409 
410        /**
411         * Holds the single unit.
412         */
413        private final Unit<?> _unit;
414 
415        /**
416         * Holds the power exponent.
417         */
418        private final int _pow;
419 
420        /**
421         * Holds the root exponent.
422         */
423        private final int _root;
424 
425        /**
426         * Structural constructor.
427         *
428         * @param  unit the unit.
429         * @param  pow the power exponent.
430         * @param  root the root exponent.
431         */
432        private Element(Unit<?> unit, int pow, int root) {
433            _unit = unit;
434            _pow = pow;
435            _root = root;
436        }
437 
438        /**
439         * Returns this element's unit.
440         *
441         * @return the single unit.
442         */
443        public Unit<?> getUnit() {
444            return _unit;
445        }
446 
447        /**
448         * Returns the power exponent. The power exponent can be negative
449         * but is always different from zero.
450         *
451         * @return the power exponent of the single unit.
452         */
453        public int getPow() {
454            return _pow;
455        }
456 
457        /**
458         * Returns the root exponent. The root exponent is always greater
459         * than zero.
460         *
461         * @return the root exponent of the single unit.
462         */
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}

[all classes][javax.measure.unit]
EMMA 2.0.9414 (unsupported private build) (C) Vladimir Roubtsov