001/** 002 * The MIT License (MIT) 003 * 004 * Copyright (c) 2015-2016 decimal4j (tools4j), Marco Terzer 005 * 006 * Permission is hereby granted, free of charge, to any person obtaining a copy 007 * of this software and associated documentation files (the "Software"), to deal 008 * in the Software without restriction, including without limitation the rights 009 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 010 * copies of the Software, and to permit persons to whom the Software is 011 * furnished to do so, subject to the following conditions: 012 * 013 * The above copyright notice and this permission notice shall be included in all 014 * copies or substantial portions of the Software. 015 * 016 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 017 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 018 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 019 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 020 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 021 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 022 * SOFTWARE. 023 */ 024package org.decimal4j.scale; 025 026import static java.math.RoundingMode.DOWN; 027import static java.math.RoundingMode.FLOOR; 028import static java.math.RoundingMode.HALF_EVEN; 029import static java.math.RoundingMode.HALF_UP; 030import static java.math.RoundingMode.UNNECESSARY; 031import static org.decimal4j.truncate.OverflowMode.CHECKED; 032import static org.decimal4j.truncate.OverflowMode.UNCHECKED; 033 034import java.math.BigDecimal; 035import java.math.BigInteger; 036import java.math.RoundingMode; 037 038import org.decimal4j.api.DecimalArithmetic; 039import org.decimal4j.arithmetic.CheckedScale0fRoundingArithmetic; 040import org.decimal4j.arithmetic.CheckedScale0fTruncatingArithmetic; 041import org.decimal4j.arithmetic.UncheckedScale0fRoundingArithmetic; 042import org.decimal4j.arithmetic.UncheckedScale0fTruncatingArithmetic; 043import org.decimal4j.truncate.DecimalRounding; 044import org.decimal4j.truncate.OverflowMode; 045import org.decimal4j.truncate.TruncationPolicy; 046 047/** 048 * Scale class for decimals with {@link #getScale() scale} 0 and 049 * {@link #getScaleFactor() scale factor} 1. Decimals with scale zero are 050 * essentially longs. 051 */ 052public enum Scale0f implements ScaleMetrics { 053 054 /** 055 * The singleton instance for scale 0. 056 */ 057 INSTANCE; 058 059 /** 060 * The scale value <code>0</code>. 061 */ 062 public static final int SCALE = 0; 063 064 /** 065 * The scale factor <code>10<sup>0</sup></code>. 066 */ 067 public static final long SCALE_FACTOR = 1L; 068 069 /** Long.numberOfLeadingZeros(SCALE_FACTOR)*/ 070 private static final int NLZ_SCALE_FACTOR = 63; 071 072 private static final long LONG_MASK = 0xffffffffL; 073 074 private static final DecimalArithmetic[] UNCHECKED_ARITHMETIC = initArithmetic(UNCHECKED); 075 private static final DecimalArithmetic[] CHECKED_ARITHMETIC = initArithmetic(CHECKED); 076 077 private static final DecimalArithmetic DEFAULT_ARITHMETIC = UNCHECKED_ARITHMETIC[HALF_UP.ordinal()]; 078 private static final DecimalArithmetic DEFAULT_CHECKED_ARITHMETIC = CHECKED_ARITHMETIC[HALF_UP.ordinal()]; 079 private static final DecimalArithmetic ROUNDING_DOWN_ARITHMETIC = UNCHECKED_ARITHMETIC[DOWN.ordinal()]; 080 private static final DecimalArithmetic ROUNDING_FLOOR_ARITHMETIC = UNCHECKED_ARITHMETIC[FLOOR.ordinal()]; 081 private static final DecimalArithmetic ROUNDING_HALF_EVEN_ARITHMETIC = UNCHECKED_ARITHMETIC[HALF_EVEN.ordinal()]; 082 private static final DecimalArithmetic ROUNDING_UNNECESSARY_ARITHMETIC = UNCHECKED_ARITHMETIC[UNNECESSARY.ordinal()]; 083 084 private static final DecimalArithmetic[] initArithmetic(OverflowMode overflowMode) { 085 final boolean checked = overflowMode == CHECKED; 086 final DecimalArithmetic[] arith = new DecimalArithmetic[DecimalRounding.VALUES.size()]; 087 for (final DecimalRounding dr : DecimalRounding.VALUES) { 088 final int index = dr.getRoundingMode().ordinal(); 089 if (dr == DecimalRounding.DOWN) { 090 arith[index] = checked ? CheckedScale0fTruncatingArithmetic.INSTANCE 091 : UncheckedScale0fTruncatingArithmetic.INSTANCE; 092 } else { 093 arith[index] = checked ? new CheckedScale0fRoundingArithmetic(dr) 094 : new UncheckedScale0fRoundingArithmetic(dr); 095 } 096 } 097 return arith; 098 } 099 100 @Override 101 public final int getScale() { 102 return SCALE; 103 } 104 105 @Override 106 public final long getScaleFactor() { 107 return SCALE_FACTOR; 108 } 109 110 @Override 111 public final int getScaleFactorNumberOfLeadingZeros() { 112 return NLZ_SCALE_FACTOR; 113 } 114 115 @Override 116 public final BigInteger getScaleFactorAsBigInteger() { 117 return BigInteger.ONE; 118 } 119 120 @Override 121 public final BigDecimal getScaleFactorAsBigDecimal() { 122 return BigDecimal.ONE; 123 } 124 125 @Override 126 public final long getMaxIntegerValue() { 127 return Long.MAX_VALUE; 128 } 129 130 @Override 131 public final long getMinIntegerValue() { 132 return Long.MIN_VALUE; 133 } 134 135 @Override 136 public final boolean isValidIntegerValue(long value) { 137 return true; 138 } 139 140 @Override 141 public final long multiplyByScaleFactor(long factor) { 142 return factor; 143 } 144 145 @Override 146 public final long multiplyByScaleFactorExact(long factor) { 147 return factor; 148 } 149 150 @Override 151 public final long mulloByScaleFactor(int factor) { 152 return factor & LONG_MASK; 153 } 154 155 @Override 156 public final long mulhiByScaleFactor(int factor) { 157 return 0; 158 } 159 160 @Override 161 public final long divideByScaleFactor(long dividend) { 162 return dividend; 163 } 164 165 @Override 166 public final long divideUnsignedByScaleFactor(long unsignedDividend) { 167 return unsignedDividend; 168 } 169 170 @Override 171 public final long moduloByScaleFactor(long dividend) { 172 return 0; 173 } 174 175 @Override 176 public final String toString(long value) { 177 return Long.toString(value); 178 } 179 180 @Override 181 public final DecimalArithmetic getDefaultArithmetic() { 182 return DEFAULT_ARITHMETIC; 183 } 184 185 @Override 186 public final DecimalArithmetic getDefaultCheckedArithmetic() { 187 return DEFAULT_CHECKED_ARITHMETIC; 188 } 189 190 @Override 191 public final DecimalArithmetic getRoundingDownArithmetic() { 192 return ROUNDING_DOWN_ARITHMETIC; 193 } 194 195 @Override 196 public final DecimalArithmetic getRoundingFloorArithmetic() { 197 return ROUNDING_FLOOR_ARITHMETIC; 198 } 199 200 @Override 201 public final DecimalArithmetic getRoundingHalfEvenArithmetic() { 202 return ROUNDING_HALF_EVEN_ARITHMETIC; 203 } 204 205 @Override 206 public final DecimalArithmetic getRoundingUnnecessaryArithmetic() { 207 return ROUNDING_UNNECESSARY_ARITHMETIC; 208 } 209 210 @Override 211 public final DecimalArithmetic getArithmetic(RoundingMode roundingMode) { 212 return UNCHECKED_ARITHMETIC[roundingMode.ordinal()]; 213 } 214 215 @Override 216 public final DecimalArithmetic getCheckedArithmetic(RoundingMode roundingMode) { 217 return CHECKED_ARITHMETIC[roundingMode.ordinal()]; 218 } 219 220 @Override 221 public final DecimalArithmetic getArithmetic(TruncationPolicy truncationPolicy) { 222 final OverflowMode overflow = truncationPolicy.getOverflowMode(); 223 final RoundingMode rounding = truncationPolicy.getRoundingMode(); 224 return (overflow == UNCHECKED ? UNCHECKED_ARITHMETIC : CHECKED_ARITHMETIC)[rounding.ordinal()]; 225 } 226 227 @Override 228 public final String toString() { 229 return "Scale0f"; 230 } 231}