001    /*
002     * JBoss DNA (http://www.jboss.org/dna)
003     * See the COPYRIGHT.txt file distributed with this work for information
004     * regarding copyright ownership.  Some portions may be licensed
005     * to Red Hat, Inc. under one or more contributor license agreements.
006     * See the AUTHORS.txt file in the distribution for a full listing of 
007     * individual contributors. 
008     *
009     * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
010     * is licensed to you under the terms of the GNU Lesser General Public License as
011     * published by the Free Software Foundation; either version 2.1 of
012     * the License, or (at your option) any later version.
013     *
014     * JBoss DNA is distributed in the hope that it will be useful,
015     * but WITHOUT ANY WARRANTY; without even the implied warranty of
016     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
017     * Lesser General Public License for more details.
018     *
019     * You should have received a copy of the GNU Lesser General Public
020     * License along with this software; if not, write to the Free
021     * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
022     * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
023     */
024    package org.jboss.dna.common.math;
025    
026    import java.math.BigDecimal;
027    import java.util.Comparator;
028    import java.util.Random;
029    import java.util.concurrent.TimeUnit;
030    
031    public class DurationOperations implements MathOperations<Duration>, Comparator<Duration> {
032    
033        public Class<Duration> getOperandClass() {
034            return Duration.class;
035        }
036    
037        public Duration add( Duration value1, Duration value2 ) {
038            if (value1 == null) return value2 != null ? value2 : createZeroValue();
039            if (value2 == null) return value1;
040            return value1.add(value2);
041        }
042    
043        public Duration subtract( Duration value1, Duration value2 ) {
044            if (value1 == null) return negate(value2);
045            if (value2 == null) return value1;
046            return value1.subtract(value2);
047        }
048    
049        public Duration multiply( Duration value1, Duration value2 ) {
050            if (value1 == null || value2 == null) return createZeroValue();
051            return value1.multiply(value2.longValue());
052        }
053    
054        public double divide( Duration value1, Duration value2 ) {
055            if (value1 == null || value2 == null) throw new IllegalArgumentException();
056            return value1.divide(value2);
057        }
058    
059        public Duration negate( Duration value ) {
060            if (value == null) return createZeroValue();
061            return value.multiply(value.longValue() * -1);
062        }
063    
064        public Duration increment( Duration value ) {
065            if (value == null) return createZeroValue();
066            return value.add(1l, TimeUnit.NANOSECONDS);
067        }
068    
069        public Duration maximum( Duration value1, Duration value2 ) {
070            if (value1 == null) return value2;
071            if (value2 == null) return value1;
072            return new Duration(Math.max(value1.longValue(), value2.longValue()));
073        }
074    
075        public Duration minimum( Duration value1, Duration value2 ) {
076            if (value1 == null) return value2;
077            if (value2 == null) return value1;
078            return new Duration(Math.min(value1.longValue(), value2.longValue()));
079        }
080    
081        public int compare( Duration value1, Duration value2 ) {
082            if (value1 == null) return value2 != null ? -1 : 0;
083            if (value2 == null) return 1;
084            return value1.compareTo(value2);
085        }
086    
087        public BigDecimal asBigDecimal( Duration value ) {
088            return value != null ? value.toBigDecimal() : null;
089        }
090    
091        public Duration fromBigDecimal( BigDecimal value ) {
092            return value != null ? new Duration(value.longValue()) : null;
093        }
094    
095        public Duration createZeroValue() {
096            return new Duration(0l);
097        }
098    
099        public Duration create( int value ) {
100            return new Duration(value);
101        }
102    
103        public Duration create( long value ) {
104            return new Duration(value);
105        }
106    
107        public Duration create( double value ) {
108            return new Duration((long)value);
109        }
110    
111        public double sqrt( Duration value ) {
112            return Math.sqrt(value.longValue());
113        }
114    
115        public Comparator<Duration> getComparator() {
116            return this;
117        }
118    
119        public Duration random( Duration minimum, Duration maximum, Random rng ) {
120            Duration difference = subtract(maximum, minimum);
121            return new Duration(minimum.getDuratinInNanoseconds() + rng.nextInt(difference.intValue()));
122        }
123    
124        public double doubleValue( Duration value ) {
125            return value.doubleValue();
126        }
127    
128        public float floatValue( Duration value ) {
129            return value.floatValue();
130        }
131    
132        public int intValue( Duration value ) {
133            return value.intValue();
134        }
135    
136        public long longValue( Duration value ) {
137            return value.longValue();
138        }
139    
140        public short shortValue( Duration value ) {
141            return value.shortValue();
142        }
143    
144        public int getExponentInScientificNotation( Duration value ) {
145            long v = Math.abs(value.getDuratinInNanoseconds());
146            int exp = 0;
147            if (v > 1l) {
148                while (v >= 10l) {
149                    v /= 10l;
150                    ++exp;
151                }
152            }
153            return exp;
154        }
155    
156        public Duration roundUp( Duration durationValue, int decimalShift ) {
157            long value = durationValue.longValue();
158            if (value == 0) return new Duration(0l);
159            if (decimalShift >= 0) return durationValue;
160            long shiftedValueP5 = Math.abs(value);
161            for (int i = 0; i != (-decimalShift - 1); ++i)
162                shiftedValueP5 /= 10l;
163            shiftedValueP5 += 5l;
164            long shiftedValue = shiftedValueP5 / 10l;
165            if (shiftedValue * 10l - shiftedValueP5 >= 5) ++shiftedValue;
166            shiftedValue *= Long.signum(value);
167            for (int i = 0; i != -decimalShift; ++i)
168                shiftedValue *= 10l;
169            return new Duration(shiftedValue);
170        }
171    
172        public Duration roundDown( Duration durationValue, int decimalShift ) {
173            long value = durationValue.longValue();
174            if (value == 0) return new Duration(0l);
175            if (decimalShift >= 0) return durationValue;
176            long shiftedValue = Math.abs(value);
177            for (int i = 0; i != -decimalShift; ++i)
178                shiftedValue /= 10l;
179            shiftedValue *= Long.signum(value);
180            for (int i = 0; i != -decimalShift; ++i)
181                shiftedValue *= 10l;
182            return new Duration(shiftedValue);
183        }
184    
185        public Duration keepSignificantFigures( Duration value, int numSigFigs ) {
186            if (numSigFigs < 0) return value;
187            if (numSigFigs == 0) return new Duration(0l);
188            int currentExp = getExponentInScientificNotation(value);
189            int decimalShift = -currentExp + numSigFigs - 1;
190            return roundUp(value, decimalShift);
191        }
192    }