| /* |
| * Copyright 2009 Google Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| * use this file except in compliance with the License. You may obtain a copy of |
| * the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| * License for the specific language governing permissions and limitations under |
| * the License. |
| */ |
| |
| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with this |
| * work for additional information regarding copyright ownership. The ASF |
| * licenses this file to You under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| * License for the specific language governing permissions and limitations under |
| * the License. |
| * |
| * INCLUDES MODIFICATIONS BY RICHARD ZSCHECH AS WELL AS GOOGLE. |
| */ |
| package java.math; |
| |
| /** |
| * Specifies the rounding behavior for operations whose results cannot be |
| * represented exactly. |
| */ |
| public enum RoundingMode { |
| |
| /** |
| * Rounding mode where positive values are rounded towards positive infinity |
| * and negative values towards negative infinity. <br> |
| * Rule: {@code x.round().abs() >= x.abs()} |
| */ |
| UP(BigDecimal.ROUND_UP), |
| |
| /** |
| * Rounding mode where the values are rounded towards zero. <br> |
| * Rule: {@code x.round().abs() <= x.abs()} |
| */ |
| DOWN(BigDecimal.ROUND_DOWN), |
| |
| /** |
| * Rounding mode to round towards positive infinity. For positive values this |
| * rounding mode behaves as {@link #UP}, for negative values as {@link #DOWN}. <br> |
| * Rule: {@code x.round() >= x} |
| */ |
| CEILING(BigDecimal.ROUND_CEILING), |
| |
| /** |
| * Rounding mode to round towards negative infinity. For positive values this |
| * rounding mode behaves as {@link #DOWN}, for negative values as {@link #UP}. <br> |
| * Rule: {@code x.round() <= x} |
| */ |
| FLOOR(BigDecimal.ROUND_FLOOR), |
| |
| /** |
| * Rounding mode where values are rounded towards the nearest neighbor. Ties |
| * are broken by rounding up. |
| */ |
| HALF_UP(BigDecimal.ROUND_HALF_UP), |
| |
| /** |
| * Rounding mode where values are rounded towards the nearest neighbor. Ties |
| * are broken by rounding down. |
| */ |
| HALF_DOWN(BigDecimal.ROUND_HALF_DOWN), |
| |
| /** |
| * Rounding mode where values are rounded towards the nearest neighbor. Ties |
| * are broken by rounding to the even neighbor. |
| */ |
| HALF_EVEN(BigDecimal.ROUND_HALF_EVEN), |
| |
| /** |
| * Rounding mode where the rounding operations throws an ArithmeticException |
| * for the case that rounding is necessary, i.e. for the case that the value |
| * cannot be represented exactly. |
| */ |
| UNNECESSARY(BigDecimal.ROUND_UNNECESSARY); |
| |
| /** |
| * Some constant char arrays for optimized comparisons |
| */ |
| private static final char[] chCEILING = {'C','E','I','L','I','N','G'}; |
| private static final char[] chDOWN = {'D','O','W','N'}; |
| private static final char[] chFLOOR = {'F','L','O','O','R'}; |
| private static final char[] chHALF_DOWN = {'H','A','L','F','_','D','O','W','N'}; |
| private static final char[] chHALF_EVEN = {'H','A','L','F','_','E','V','E','N'}; |
| private static final char[] chHALF_UP = {'H','A','L','F','_','U','P'}; |
| private static final char[] chUNNECESSARY = {'U','N','N','E','C','E','S','S','A','R','Y'}; |
| private static final char[] chUP = {'U','P'}; |
| |
| /** |
| * Converts rounding mode constants from class {@code BigDecimal} into {@code |
| * RoundingMode} values. |
| * |
| * @param mode rounding mode constant as defined in class {@code BigDecimal} |
| * @return corresponding rounding mode object |
| */ |
| public static RoundingMode valueOf(int mode) { |
| switch (mode) { |
| case BigDecimal.ROUND_CEILING: |
| return CEILING; |
| case BigDecimal.ROUND_DOWN: |
| return DOWN; |
| case BigDecimal.ROUND_FLOOR: |
| return FLOOR; |
| case BigDecimal.ROUND_HALF_DOWN: |
| return HALF_DOWN; |
| case BigDecimal.ROUND_HALF_EVEN: |
| return HALF_EVEN; |
| case BigDecimal.ROUND_HALF_UP: |
| return HALF_UP; |
| case BigDecimal.ROUND_UNNECESSARY: |
| return UNNECESSARY; |
| case BigDecimal.ROUND_UP: |
| return UP; |
| default: |
| // math.00=Invalid rounding mode |
| throw new IllegalArgumentException("Invalid rounding mode"); //$NON-NLS-1$ |
| } |
| } |
| |
| /** |
| * Bypasses calls to the implicit valueOf(String) method, which will break |
| * if enum name obfuscation is enabled. This should be package visible only. |
| * |
| * @param mode rounding mode string as defined in class {@code BigDecimal} |
| * @return corresponding rounding mode object |
| */ |
| static RoundingMode valueOfExplicit(String mode) { |
| /* |
| * Note this is optimized to avoid multiple String compares, |
| * using specific knowledge of the set of allowed enum constants. |
| */ |
| |
| if (mode == null) { |
| throw new NullPointerException(); |
| } |
| |
| char[] modeChars = mode.toCharArray(); |
| int len = modeChars.length; |
| if (len < chUP.length || len > chUNNECESSARY.length) { |
| throw new IllegalArgumentException(); |
| } |
| |
| char[] targetChars = null; |
| RoundingMode target = null; |
| if (modeChars[0] == 'C') { |
| target = RoundingMode.CEILING; |
| targetChars = chCEILING; |
| } else if (modeChars[0] == 'D') { |
| target = RoundingMode.DOWN; |
| targetChars = chDOWN; |
| } else if (modeChars[0] == 'F') { |
| target = RoundingMode.FLOOR; |
| targetChars = chFLOOR; |
| } else if (modeChars[0] == 'H') { |
| if (len > 6) { |
| if (modeChars[5] == 'D') { |
| target = RoundingMode.HALF_DOWN; |
| targetChars = chHALF_DOWN; |
| } else if (modeChars[5] == 'E') { |
| target = RoundingMode.HALF_EVEN; |
| targetChars = chHALF_EVEN; |
| } else if (modeChars[5] == 'U') { |
| target = RoundingMode.HALF_UP; |
| targetChars = chHALF_UP; |
| } |
| } |
| } else if (modeChars[0] == 'U') { |
| if (modeChars[1] == 'P') { |
| target = RoundingMode.UP; |
| targetChars = chUP; |
| } else if (modeChars[1] == 'N') { |
| target = RoundingMode.UNNECESSARY; |
| targetChars = chUNNECESSARY; |
| } |
| } |
| |
| if (target != null && len == targetChars.length) { |
| int i; |
| for (i = 1; i < len && modeChars[i] == targetChars[i]; i++) { |
| } |
| if (i == len) { |
| return target; |
| } |
| } |
| |
| throw new IllegalArgumentException(); |
| } |
| |
| /** |
| * Set the old constant. |
| * @param rm unused |
| */ |
| RoundingMode(int rm) { |
| // Note that we do not need the old-style rounding mode, so we ignore it. |
| } |
| } |