001/* 002 * The MIT License (MIT) 003 * 004 * Copyright (c) 2015-2023 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.arithmetic; 025 026import org.decimal4j.truncate.DecimalRounding; 027 028/** 029 * Defines different inverses of a {@link DecimalRounding}. Each constant 030 * provides its own implementation of an {@link #invert(DecimalRounding)} 031 * method. 032 */ 033enum RoundingInverse { 034 /** 035 * Constant calculating inverted rounding due to sign reversion. 036 * <p> 037 * The inverted rounding mode can be used to round a value {@code a} instead 038 * of the value {@code -a}. 039 */ 040 SIGN_REVERSION { 041 @Override 042 public final DecimalRounding invert(DecimalRounding rounding) { 043 switch (rounding) { 044 case FLOOR: 045 return DecimalRounding.CEILING; 046 case CEILING: 047 return DecimalRounding.FLOOR; 048 case DOWN: 049 return DecimalRounding.DOWN; 050 case HALF_DOWN: 051 return DecimalRounding.HALF_DOWN; 052 case UP: 053 return DecimalRounding.UP; 054 case HALF_UP: 055 return DecimalRounding.HALF_UP; 056 case HALF_EVEN: 057 return DecimalRounding.HALF_EVEN; 058 case UNNECESSARY: 059 return DecimalRounding.UNNECESSARY; 060 default: 061 // should not get here 062 throw new IllegalArgumentException("Unsupported rounding mode: " + rounding); 063 } 064 } 065 }, 066 /** 067 * Constant calculating inverted rounding due to sign reversion occurring 068 * after an addition or subtraction. 069 * <p> 070 * The inverted rounding mode can be used to round a value {@code x} instead 071 * of the sum {@code (a + x)} when sum and {@code x} have opposite sign 072 * (equivalent for a difference {@code (a - x)}). 073 */ 074 ADDITIVE_REVERSION { 075 public final DecimalRounding invert(DecimalRounding rounding) { 076 switch (rounding) { 077 case FLOOR: 078 return DecimalRounding.FLOOR; 079 case CEILING: 080 return DecimalRounding.CEILING; 081 case DOWN: 082 return DecimalRounding.UP; 083 case HALF_DOWN: 084 return DecimalRounding.HALF_UP; 085 case UP: 086 return DecimalRounding.DOWN; 087 case HALF_UP: 088 return DecimalRounding.HALF_DOWN; 089 case HALF_EVEN: 090 return DecimalRounding.HALF_EVEN; 091 case UNNECESSARY: 092 return DecimalRounding.UNNECESSARY; 093 default: 094 // should not get here 095 throw new IllegalArgumentException("Unsupported rounding mode: " + rounding); 096 } 097 } 098 }, 099 /** 100 * Constant calculating inverted rounding due to reciprocal of a value. 101 * <p> 102 * The inverted rounding mode can be used to round a value {@code x} instead 103 * of the reciprocal value {@code 1/x}. 104 */ 105 RECIPROCAL { 106 public final DecimalRounding invert(DecimalRounding rounding) { 107 switch (rounding) { 108 case UP: 109 return DecimalRounding.DOWN; 110 case DOWN: 111 return DecimalRounding.UP; 112 case CEILING: 113 return DecimalRounding.FLOOR; 114 case FLOOR: 115 return DecimalRounding.CEILING; 116 case HALF_UP: 117 return DecimalRounding.HALF_DOWN; 118 case HALF_DOWN: 119 return DecimalRounding.HALF_UP; 120 case HALF_EVEN: 121 return DecimalRounding.HALF_EVEN;// HALF_UNEVEN? 122 case UNNECESSARY: 123 return DecimalRounding.UNNECESSARY; 124 default: 125 // should not get here 126 throw new IllegalArgumentException("Unsupported rounding mode: " + rounding); 127 } 128 } 129 }; 130 /** 131 * Returns the inverted rounding for the inversion case defined by this 132 * constant. 133 * 134 * @param rounding 135 * the original rounding 136 * @return the inverted rounding 137 */ 138 abstract public DecimalRounding invert(DecimalRounding rounding); 139}