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 long numbers. 025 */ 026@Immutable 027public class LongOperations implements MathOperations<Long>, Comparator<Long> { 028 029 @Override 030 public Class<Long> getOperandClass() { 031 return Long.class; 032 } 033 034 @Override 035 public Long add( Long value1, 036 Long 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 Long subtract( Long value1, 044 Long value2 ) { 045 if (value1 == null) return negate(value2); 046 if (value2 == null) return value1; 047 return (value1 - value2); 048 } 049 050 @Override 051 public Long multiply( Long value1, 052 Long value2 ) { 053 if (value1 == null || value2 == null) return createZeroValue(); 054 return (value1 * value2); 055 } 056 057 @Override 058 public double divide( Long value1, 059 Long value2 ) { 060 if (value1 == null || value2 == null) throw new IllegalArgumentException(); 061 return value1 / value2; 062 } 063 064 @Override 065 public Long negate( Long value ) { 066 if (value == null) return createZeroValue(); 067 return (value * -1); 068 } 069 070 @Override 071 public Long increment( Long value ) { 072 if (value == null) return createZeroValue(); 073 return (value + 1); 074 } 075 076 @Override 077 public Long maximum( Long value1, 078 Long 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 Long minimum( Long value1, 086 Long 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( Long value1, 094 Long 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( Long value ) { 102 return value != null ? new BigDecimal(value) : null; 103 } 104 105 @Override 106 public Long fromBigDecimal( BigDecimal value ) { 107 return value != null ? value.longValue() : null; 108 } 109 110 @Override 111 public Long createZeroValue() { 112 return 0l; 113 } 114 115 @Override 116 public Long create( int value ) { 117 return (long)value; 118 } 119 120 @Override 121 public Long create( long value ) { 122 return value; 123 } 124 125 @Override 126 public Long create( double value ) { 127 return (long)value; 128 } 129 130 @Override 131 public double sqrt( Long value ) { 132 return Math.sqrt(value); 133 } 134 135 @Override 136 public Comparator<Long> getComparator() { 137 return this; 138 } 139 140 @Override 141 public Long random( Long minimum, 142 Long maximum, 143 Random rng ) { 144 Long difference = subtract(maximum, minimum); 145 return minimum + rng.nextInt(difference.intValue()); 146 } 147 148 @Override 149 public double doubleValue( Long value ) { 150 return value.doubleValue(); 151 } 152 153 @Override 154 public float floatValue( Long value ) { 155 return value.floatValue(); 156 } 157 158 @Override 159 public int intValue( Long value ) { 160 return value.intValue(); 161 } 162 163 @Override 164 public long longValue( Long value ) { 165 return value.longValue(); 166 } 167 168 @Override 169 public short shortValue( Long value ) { 170 return value.shortValue(); 171 } 172 173 @Override 174 public int getExponentInScientificNotation( Long value ) { 175 long v = Math.abs(value); 176 int exp = 0; 177 if (v > 1l) { 178 while (v >= 10l) { 179 v /= 10l; 180 ++exp; 181 } 182 } else if (v == 0l) { 183 } else if (v < 1l) { 184 while (v < 1l) { 185 v *= 10l; 186 --exp; 187 } 188 } 189 return exp; 190 } 191 192 @Override 193 public Long roundUp( Long value, 194 int decimalShift ) { 195 if (value == 0) return 0l; 196 if (decimalShift >= 0) return value; 197 long shiftedValueP5 = Math.abs(value); 198 for (int i = 0; i != (-decimalShift - 1); ++i) 199 shiftedValueP5 /= 10l; 200 shiftedValueP5 += 5l; 201 long shiftedValue = shiftedValueP5 / 10l; 202 if (shiftedValue * 10l - shiftedValueP5 >= 5) ++shiftedValue; 203 shiftedValue *= Long.signum(value); 204 for (int i = 0; i != -decimalShift; ++i) 205 shiftedValue *= 10l; 206 return shiftedValue; 207 } 208 209 @Override 210 public Long roundDown( Long value, 211 int decimalShift ) { 212 if (value == 0) return 0l; 213 if (decimalShift >= 0) return value; 214 long shiftedValue = Math.abs(value); 215 for (int i = 0; i != -decimalShift; ++i) 216 shiftedValue /= 10l; 217 shiftedValue *= Long.signum(value); 218 for (int i = 0; i != -decimalShift; ++i) 219 shiftedValue *= 10l; 220 return shiftedValue; 221 } 222 223 @Override 224 public Long keepSignificantFigures( Long value, 225 int numSigFigs ) { 226 if (value == 0l) return value; 227 if (numSigFigs < 0) return value; 228 if (numSigFigs == 0) return 0l; 229 int currentExp = getExponentInScientificNotation(value); 230 int decimalShift = -currentExp + numSigFigs - 1; 231 return roundUp(value, decimalShift); 232 } 233}