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.truncate; 025 026import java.math.RoundingMode; 027import java.util.Collections; 028import java.util.EnumSet; 029import java.util.Set; 030 031/** 032 * Provides rounding constants implementing {@link TruncationPolicy} for {@link OverflowMode#UNCHECKED}. The constants 033 * are equivalent to the constants defined by {@link RoundingMode}; the policy's {@link #getOverflowMode()} method 034 * always returns {@link OverflowMode#UNCHECKED UNCHECKED} overflow mode. 035 */ 036public enum UncheckedRounding implements TruncationPolicy { 037 /** 038 * Unchecked truncation policy with rounding mode to round away from zero. Always increments the digit prior to a 039 * non-zero discarded fraction. Note that this rounding mode never decreases the magnitude of the calculated value. 040 * 041 * @see RoundingMode#UP 042 */ 043 UP { 044 @Override 045 public final RoundingMode getRoundingMode() { 046 return RoundingMode.UP; 047 } 048 049 @Override 050 public final CheckedRounding toCheckedRounding() { 051 return CheckedRounding.UP; 052 } 053 }, 054 055 /** 056 * Unchecked truncation policy with rounding mode to round towards zero. Never increments the digit prior to a 057 * discarded fraction (i.e., truncates). Note that this rounding mode never increases the magnitude of the 058 * calculated value. 059 * 060 * @see RoundingMode#DOWN 061 */ 062 DOWN { 063 @Override 064 public final RoundingMode getRoundingMode() { 065 return RoundingMode.DOWN; 066 } 067 068 @Override 069 public final CheckedRounding toCheckedRounding() { 070 return CheckedRounding.DOWN; 071 } 072 }, 073 074 /** 075 * Unchecked truncation policy with rounding mode to round towards positive infinity. If the result is positive, 076 * behaves as for {@code RoundingMode.UP}; if negative, behaves as for {@code RoundingMode.DOWN}. Note that this 077 * rounding mode never decreases the calculated value. 078 * 079 * @see RoundingMode#CEILING 080 */ 081 CEILING { 082 @Override 083 public final RoundingMode getRoundingMode() { 084 return RoundingMode.CEILING; 085 } 086 087 @Override 088 public final CheckedRounding toCheckedRounding() { 089 return CheckedRounding.CEILING; 090 } 091 }, 092 093 /** 094 * Unchecked truncation policy with rounding mode to round towards negative infinity. If the result is positive, 095 * behave as for {@code RoundingMode.DOWN}; if negative, behave as for {@code RoundingMode.UP}. Note that this 096 * rounding mode never increases the calculated value. 097 * 098 * @see RoundingMode#FLOOR 099 */ 100 FLOOR { 101 @Override 102 public final RoundingMode getRoundingMode() { 103 return RoundingMode.FLOOR; 104 } 105 106 @Override 107 public final CheckedRounding toCheckedRounding() { 108 return CheckedRounding.FLOOR; 109 } 110 }, 111 112 /** 113 * Unchecked truncation policy with rounding mode to round towards {@literal "nearest neighbor"} unless both 114 * neighbors are equidistant, in which case round up. Behaves as for {@code RoundingMode.UP} if the discarded 115 * fraction is ≥ 0.5; otherwise, behaves as for {@code RoundingMode.DOWN}. Note that this is the rounding mode 116 * commonly taught at school. 117 * 118 * @see RoundingMode#HALF_UP 119 */ 120 HALF_UP { 121 @Override 122 public final RoundingMode getRoundingMode() { 123 return RoundingMode.HALF_UP; 124 } 125 126 @Override 127 public final CheckedRounding toCheckedRounding() { 128 return CheckedRounding.HALF_UP; 129 } 130 }, 131 132 /** 133 * Unchecked truncation policy with rounding mode to round towards {@literal "nearest neighbor"} unless both 134 * neighbors are equidistant, in which case round down. Behaves as for {@code RoundingMode.UP} if the discarded 135 * fraction is > 0.5; otherwise, behaves as for {@code RoundingMode.DOWN}. 136 * 137 * @see RoundingMode#HALF_DOWN 138 */ 139 HALF_DOWN { 140 @Override 141 public final RoundingMode getRoundingMode() { 142 return RoundingMode.HALF_DOWN; 143 } 144 145 @Override 146 public final CheckedRounding toCheckedRounding() { 147 return CheckedRounding.HALF_DOWN; 148 } 149 }, 150 151 /** 152 * Unchecked truncation policy with rounding mode to round towards the {@literal "nearest neighbor"} unless both 153 * neighbors are equidistant, in which case, round towards the even neighbor. Behaves as for 154 * {@code RoundingMode.HALF_UP} if the digit to the left of the discarded fraction is odd; behaves as for 155 * {@code RoundingMode.HALF_DOWN} if it's even. Note that this is the rounding mode that statistically minimizes 156 * cumulative error when applied repeatedly over a sequence of calculations. It is sometimes known as 157 * {@literal "Banker's rounding,"} and is chiefly used in the USA. This rounding mode is analogous to the rounding 158 * policy used for {@code float} and {@code double} arithmetic in Java. 159 * 160 * @see RoundingMode#HALF_EVEN 161 */ 162 HALF_EVEN { 163 @Override 164 public final RoundingMode getRoundingMode() { 165 return RoundingMode.HALF_EVEN; 166 } 167 168 @Override 169 public final CheckedRounding toCheckedRounding() { 170 return CheckedRounding.HALF_EVEN; 171 } 172 }, 173 174 /** 175 * Unchecked truncation policy with rounding mode to assert that the requested operation has an exact result, hence 176 * no rounding is necessary. If this rounding mode is specified on an operation that yields an inexact result, an 177 * {@code ArithmeticException} is thrown. 178 * 179 * @see RoundingMode#UNNECESSARY 180 */ 181 UNNECESSARY { 182 @Override 183 public final RoundingMode getRoundingMode() { 184 return RoundingMode.UNNECESSARY; 185 } 186 187 @Override 188 public final CheckedRounding toCheckedRounding() { 189 return CheckedRounding.UNNECESSARY; 190 } 191 }; 192 193 /** 194 * Returns {@link OverflowMode#UNCHECKED}. 195 * 196 * @return UNCHECKED overflow mode 197 */ 198 @Override 199 public final OverflowMode getOverflowMode() { 200 return OverflowMode.UNCHECKED; 201 } 202 203 /** 204 * Returns the policy with the same {@link #getRoundingMode() rounding mode} as this unchecked rounding policy but 205 * for {@link OverflowMode#CHECKED CHECKED} {@link #getOverflowMode() overflow mode}. 206 * 207 * @return the {@link CheckedRounding} counterpart to this policy. 208 */ 209 abstract public CheckedRounding toCheckedRounding(); 210 211 /** 212 * Returns "UNCHECKED/(name)" where {@code (name)} stands for the {@link #name()} of this constant. 213 * 214 * @return a string like "UNCHECKED/HALF_UP" 215 */ 216 @Override 217 public final String toString() { 218 return "UNCHECKED/" + name(); 219 } 220 221 /** 222 * Immutable set with all values of this enum. Avoids object creation in contrast to {@link #values()}. 223 */ 224 public static final Set<UncheckedRounding> VALUES = Collections 225 .unmodifiableSet(EnumSet.allOf(UncheckedRounding.class)); 226 227 /** 228 * Returns the checked rounding constant for the given rounding mode. 229 * 230 * @param roundingMode 231 * the rounding mode 232 * @return the constant corresponding to the given rounding mode 233 */ 234 public static final UncheckedRounding valueOf(RoundingMode roundingMode) { 235 return ByRoundingMode.VALUES_BY_ROUNDING_MODE_ORDINAL[roundingMode.ordinal()]; 236 } 237 238 private static class ByRoundingMode { 239 private static final UncheckedRounding[] VALUES_BY_ROUNDING_MODE_ORDINAL = sortByRoundingModeOrdinal(); 240 241 private static final UncheckedRounding[] sortByRoundingModeOrdinal() { 242 final UncheckedRounding[] sorted = new UncheckedRounding[VALUES.size()]; 243 for (final UncheckedRounding dr : VALUES) { 244 sorted[dr.getRoundingMode().ordinal()] = dr; 245 } 246 return sorted; 247 } 248 } 249}