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 org.modeshape.common.annotation.Immutable; 022 023/** 024 * The {@link MathOperations math operations} for double numbers. 025 */ 026@Immutable 027public class DoubleOperations implements MathOperations<Double>, Comparator<Double> { 028 029 @Override 030 public Class<Double> getOperandClass() { 031 return Double.class; 032 } 033 034 @Override 035 public Double add( Double value1, 036 Double value2 ) { 037 if (value1 == null) return value2 != null ? value2 : createZeroValue(); 038 if (value2 == null) return value1; 039 return (value1 + value2); 040 } 041 042 @Override 043 public Double subtract( Double value1, 044 Double value2 ) { 045 if (value1 == null) return negate(value2); 046 if (value2 == null) return value1; 047 return (value1 - value2); 048 } 049 050 @Override 051 public Double multiply( Double value1, 052 Double value2 ) { 053 if (value1 == null || value2 == null) return createZeroValue(); 054 return (value1 * value2); 055 } 056 057 @Override 058 public double divide( Double value1, 059 Double value2 ) { 060 if (value1 == null || value2 == null) throw new IllegalArgumentException(); 061 return value1 / value2; 062 } 063 064 @Override 065 public Double negate( Double value ) { 066 if (value == null) return createZeroValue(); 067 return (value * -1); 068 } 069 070 @Override 071 public Double increment( Double value ) { 072 if (value == null) return createZeroValue(); 073 return (value + 1); 074 } 075 076 @Override 077 public Double maximum( Double value1, 078 Double value2 ) { 079 if (value1 == null) return value2; 080 if (value2 == null) return value1; 081 return Math.max(value1, value2); 082 } 083 084 @Override 085 public Double minimum( Double value1, 086 Double value2 ) { 087 if (value1 == null) return value2; 088 if (value2 == null) return value1; 089 return Math.min(value1, value2); 090 } 091 092 @Override 093 public int compare( Double value1, 094 Double value2 ) { 095 if (value1 == null) return value2 != null ? -1 : 0; 096 if (value2 == null) return 1; 097 return value1.compareTo(value2); 098 } 099 100 @Override 101 public BigDecimal asBigDecimal( Double value ) { 102 return value != null ? new BigDecimal(value) : null; 103 } 104 105 @Override 106 public Double fromBigDecimal( BigDecimal value ) { 107 return value != null ? value.doubleValue() : null; 108 } 109 110 @Override 111 public Double createZeroValue() { 112 return 0.0d; 113 } 114 115 @Override 116 public Double create( int value ) { 117 return (double)value; 118 } 119 120 @Override 121 public Double create( long value ) { 122 return (double)value; 123 } 124 125 @Override 126 public Double create( double value ) { 127 return value; 128 } 129 130 @Override 131 public double sqrt( Double value ) { 132 return Math.sqrt(value); 133 } 134 135 @Override 136 public Comparator<Double> getComparator() { 137 return this; 138 } 139 140 @Override 141 public Double random( Double minimum, 142 Double maximum, 143 Random rng ) { 144 Double difference = subtract(maximum, minimum); 145 return minimum + difference.doubleValue() * rng.nextDouble(); 146 } 147 148 @Override 149 public double doubleValue( Double value ) { 150 return value.doubleValue(); 151 } 152 153 @Override 154 public float floatValue( Double value ) { 155 return value.floatValue(); 156 } 157 158 @Override 159 public int intValue( Double value ) { 160 return value.intValue(); 161 } 162 163 @Override 164 public long longValue( Double value ) { 165 return value.longValue(); 166 } 167 168 @Override 169 public short shortValue( Double value ) { 170 return value.shortValue(); 171 } 172 173 @Override 174 public int getExponentInScientificNotation( Double value ) { 175 double v = Math.abs(value); 176 int exp = 0; 177 if (v > 1.0d) { 178 while (v >= 10.0d) { 179 v /= 10.0d; 180 ++exp; 181 } 182 } else if (v == 0.0d) { 183 } else if (v < 1.0d) { 184 while (v < 1.0d) { 185 v *= 10.0d; 186 --exp; 187 } 188 } 189 return exp; 190 } 191 192 @Override 193 public Double roundUp( Double value, 194 int decimalShift ) { 195 if (value == 0) return 0.0d; 196 double shiftedValue = (Math.abs(value) * Math.pow(10.0d, decimalShift) + 0.5d) * Math.signum(value); 197 double roundedValue = (int)shiftedValue; 198 return roundedValue * Math.pow(10.0d, -decimalShift); 199 } 200 201 @Override 202 public Double roundDown( Double value, 203 int decimalShift ) { 204 if (value == 0) return 0.0d; 205 double shiftedValue = (Math.abs(value) * Math.pow(10.0d, decimalShift)) * Math.signum(value); 206 double roundedValue = (int)shiftedValue; 207 return roundedValue * Math.pow(10.0d, -decimalShift); 208 } 209 210 @Override 211 public Double keepSignificantFigures( Double value, 212 int numSigFigs ) { 213 if (numSigFigs < 0) return value; 214 if (numSigFigs == 0) return 0.0d; 215 int currentExp = getExponentInScientificNotation(value); 216 int decimalShift = -currentExp + numSigFigs - 1; 217 return roundUp(value, decimalShift); 218 } 219}