001/* 002 * ModeShape (http://www.modeshape.org) 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.modeshape.common.math; 017 018import java.math.BigDecimal; 019import java.util.Comparator; 020import java.util.Random; 021import java.util.concurrent.TimeUnit; 022import org.modeshape.common.annotation.Immutable; 023 024/** 025 * The {@link MathOperations math operations} for {@link Duration}s. 026 */ 027@Immutable 028public class DurationOperations implements MathOperations<Duration>, Comparator<Duration> { 029 030 @Override 031 public Class<Duration> getOperandClass() { 032 return Duration.class; 033 } 034 035 @Override 036 public Duration add( Duration value1, 037 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 @Override 044 public Duration subtract( Duration value1, 045 Duration value2 ) { 046 if (value1 == null) return negate(value2); 047 if (value2 == null) return value1; 048 return value1.subtract(value2); 049 } 050 051 @Override 052 public Duration multiply( Duration value1, 053 Duration value2 ) { 054 if (value1 == null || value2 == null) return createZeroValue(); 055 return value1.multiply(value2.longValue()); 056 } 057 058 @Override 059 public double divide( Duration value1, 060 Duration value2 ) { 061 if (value1 == null || value2 == null) throw new IllegalArgumentException(); 062 return value1.divide(value2); 063 } 064 065 @Override 066 public Duration negate( Duration value ) { 067 if (value == null) return createZeroValue(); 068 return value.multiply(value.longValue() * -1); 069 } 070 071 @Override 072 public Duration increment( Duration value ) { 073 if (value == null) return createZeroValue(); 074 return value.add(1l, TimeUnit.NANOSECONDS); 075 } 076 077 @Override 078 public Duration maximum( Duration value1, 079 Duration value2 ) { 080 if (value1 == null) return value2; 081 if (value2 == null) return value1; 082 return new Duration(Math.max(value1.longValue(), value2.longValue())); 083 } 084 085 @Override 086 public Duration minimum( Duration value1, 087 Duration value2 ) { 088 if (value1 == null) return value2; 089 if (value2 == null) return value1; 090 return new Duration(Math.min(value1.longValue(), value2.longValue())); 091 } 092 093 @Override 094 public int compare( Duration value1, 095 Duration value2 ) { 096 if (value1 == null) return value2 != null ? -1 : 0; 097 if (value2 == null) return 1; 098 return value1.compareTo(value2); 099 } 100 101 @Override 102 public BigDecimal asBigDecimal( Duration value ) { 103 return value != null ? value.toBigDecimal() : null; 104 } 105 106 @Override 107 public Duration fromBigDecimal( BigDecimal value ) { 108 return value != null ? new Duration(value.longValue()) : null; 109 } 110 111 @Override 112 public Duration createZeroValue() { 113 return new Duration(0l); 114 } 115 116 @Override 117 public Duration create( int value ) { 118 return new Duration(value); 119 } 120 121 @Override 122 public Duration create( long value ) { 123 return new Duration(value); 124 } 125 126 @Override 127 public Duration create( double value ) { 128 return new Duration((long)value); 129 } 130 131 @Override 132 public double sqrt( Duration value ) { 133 return Math.sqrt(value.longValue()); 134 } 135 136 @Override 137 public Comparator<Duration> getComparator() { 138 return this; 139 } 140 141 @Override 142 public Duration random( Duration minimum, 143 Duration maximum, 144 Random rng ) { 145 Duration difference = subtract(maximum, minimum); 146 return new Duration(minimum.getDuratinInNanoseconds() + rng.nextInt(difference.intValue())); 147 } 148 149 @Override 150 public double doubleValue( Duration value ) { 151 return value.doubleValue(); 152 } 153 154 @Override 155 public float floatValue( Duration value ) { 156 return value.floatValue(); 157 } 158 159 @Override 160 public int intValue( Duration value ) { 161 return value.intValue(); 162 } 163 164 @Override 165 public long longValue( Duration value ) { 166 return value.longValue(); 167 } 168 169 @Override 170 public short shortValue( Duration value ) { 171 return value.shortValue(); 172 } 173 174 @Override 175 public int getExponentInScientificNotation( Duration value ) { 176 long v = Math.abs(value.getDuratinInNanoseconds()); 177 int exp = 0; 178 if (v > 1l) { 179 while (v >= 10l) { 180 v /= 10l; 181 ++exp; 182 } 183 } 184 return exp; 185 } 186 187 @Override 188 public Duration roundUp( Duration durationValue, 189 int decimalShift ) { 190 long value = durationValue.longValue(); 191 if (value == 0) return new Duration(0l); 192 if (decimalShift >= 0) return durationValue; 193 long shiftedValueP5 = Math.abs(value); 194 for (int i = 0; i != (-decimalShift - 1); ++i) 195 shiftedValueP5 /= 10l; 196 shiftedValueP5 += 5l; 197 long shiftedValue = shiftedValueP5 / 10l; 198 if (shiftedValue * 10l - shiftedValueP5 >= 5) ++shiftedValue; 199 shiftedValue *= Long.signum(value); 200 for (int i = 0; i != -decimalShift; ++i) 201 shiftedValue *= 10l; 202 return new Duration(shiftedValue); 203 } 204 205 @Override 206 public Duration roundDown( Duration durationValue, 207 int decimalShift ) { 208 long value = durationValue.longValue(); 209 if (value == 0) return new Duration(0l); 210 if (decimalShift >= 0) return durationValue; 211 long shiftedValue = Math.abs(value); 212 for (int i = 0; i != -decimalShift; ++i) 213 shiftedValue /= 10l; 214 shiftedValue *= Long.signum(value); 215 for (int i = 0; i != -decimalShift; ++i) 216 shiftedValue *= 10l; 217 return new Duration(shiftedValue); 218 } 219 220 @Override 221 public Duration keepSignificantFigures( Duration value, 222 int numSigFigs ) { 223 if (numSigFigs < 0) return value; 224 if (numSigFigs == 0) return new Duration(0l); 225 int currentExp = getExponentInScientificNotation(value); 226 int decimalShift = -currentExp + numSigFigs - 1; 227 return roundUp(value, decimalShift); 228 } 229}