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