Path: blob/master/jcl/src/openj9.dataaccess/share/classes/com/ibm/dataaccess/CommonData.java
12558 views
/*[INCLUDE-IF DAA]*/1/*******************************************************************************2* Copyright (c) 2013, 2015 IBM Corp. and others3*4* This program and the accompanying materials are made available under5* the terms of the Eclipse Public License 2.0 which accompanies this6* distribution and is available at https://www.eclipse.org/legal/epl-2.0/7* or the Apache License, Version 2.0 which accompanies this distribution and8* is available at https://www.apache.org/licenses/LICENSE-2.0.9*10* This Source Code may also be made available under the following11* Secondary Licenses when the conditions for such availability set12* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU13* General Public License, version 2 with the GNU Classpath14* Exception [1] and GNU General Public License, version 2 with the15* OpenJDK Assembly Exception [2].16*17* [1] https://www.gnu.org/software/classpath/license.html18* [2] http://openjdk.java.net/legal/assembly-exception.html19*20* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception21*******************************************************************************/2223package com.ibm.dataaccess;2425import java.util.Arrays;2627/**28* Common data to assist conversions between binary, packed decimal & zoned29* decimal representations and arithmetic operations on packed decimals.30* *31* @author IBM32* @version $Revision$ on $Date$33*/3435class CommonData {3637public final static int HIGHER_NIBBLE_MASK = 0xF0;38public final static int LOWER_NIBBLE_MASK = 0x0F;39public final static int INTEGER_MASK = 0xFF; // used for converting byte to40// integer41/** Constant representing a packed zero */42final static byte PACKED_ZERO = (byte) (0x00);4344final static byte PACKED_SIGNED_ZERO = (byte) 0x0C;45final static byte PACKED_PLUS = (byte) 0x0C;46final static byte PACKED_MINUS = (byte) 0x0D;47private static final byte PACKED_ALT_PLUS = (byte) 0x0F;48private static final byte PACKED_ALT_PLUS1 = (byte) 0x0E;49private static final byte PACKED_ALT_PLUS2 = (byte) 0x0A;50private static final byte PACKED_ALT_MINUS = (byte) 0x0B;51protected static final byte EXTERNAL_SIGN_PLUS = (byte)0x4e;52protected static final byte EXTERNAL_SIGN_MINUS = (byte)0x60;53protected static final byte EXTERNAL_EMBEDDED_SIGN_PLUS = (byte)0xC0;54protected static final byte EXTERNAL_EMBEDDED_SIGN_MINUS = (byte)0xD0;5556protected static final byte EXTERNAL_EMBEDDED_SIGN_PLUS_ALTERNATE_A = (byte) 0xA0;57protected static final byte EXTERNAL_EMBEDDED_SIGN_PLUS_ALTERNATE_E = (byte) 0xE0;58protected static final byte EXTERNAL_EMBEDDED_SIGN_PLUS_ALTERNATE_F = (byte) 0xF0;59protected static final byte EXTERNAL_EMBEDDED_SIGN_MINUS_ALTERNATE_B = (byte) 0xB0;6061protected final static byte PACKED_INVALID_DIGIT = (byte) (0xff);6263/**64* The map table's for calculating byte arithmetics. sized to be 2^10 as we65* need to consider carries/borrows.66*/67private static final int BYTE_ARITHMETICS_TABLE_LENGTH = 1024;6869/**70* Outputs the sum of two bytes71*/72public static int getPackedSumValues(int input) {73return packedSumValues[input] & INTEGER_MASK;74}7576/**77* counts how many bytes are there in an external decimal.78*/79public static int getExternalByteCounts(int precision, int decimalType)80{81switch (decimalType)82{83case DecimalData.EBCDIC_SIGN_EMBEDDED_TRAILING:84case DecimalData.EBCDIC_SIGN_EMBEDDED_LEADING:85return precision;86case DecimalData.EBCDIC_SIGN_SEPARATE_TRAILING:87case DecimalData.EBCDIC_SIGN_SEPARATE_LEADING:88return precision+1;89default:90throw new IllegalArgumentException("illegal decimalType.");91}92}9394/**95* Outputs the sum of two bytes plus one96*/97public static byte getPackedSumPlusOneValues(int input) {98return packedSumPlusOneValues[input];99}100101/**102* Outputs the difference of two bytes103*/104public static byte getPackedDifferenceValues(int input) {105return packedDifferenceValues[input];106}107108/**109* Outputs the difference of two bytes minus one110*/111public static byte getPackedDifferenceMinusOneValues(int input) {112return packedDifferenceMinusOneValues[input];113}114115/**116* Outputs the sum of the input and one117*/118public static byte getPackedAddOneValues(byte input) {119int carryHighDigit = ((input & CommonData.HIGHER_NIBBLE_MASK) >> 4);120int carryLowDigit = (input & CommonData.LOWER_NIBBLE_MASK) + 1;121if (carryLowDigit == 10) {122carryLowDigit = 0;123carryHighDigit = carryHighDigit + 1;124if (carryHighDigit == 10) {125carryHighDigit = 0;126}127}128return (byte) ((carryHighDigit << 4) + carryLowDigit);129}130131/**132* Outputs the difference of two bytes133*/134public static byte getPackedBorrowOneValues(byte input) {135int borrowHighDigit = ((input & CommonData.HIGHER_NIBBLE_MASK) >> 4);136int borrowLowDigit = (input & CommonData.LOWER_NIBBLE_MASK) - 1;137if (borrowLowDigit < 0) {138borrowLowDigit = 9;139borrowHighDigit = borrowHighDigit - 1;140if (borrowHighDigit < 0) {141borrowHighDigit = 9;142}143}144return (byte) ((borrowHighDigit << 4) + borrowLowDigit);145}146147/**148* Converts a packed byte to binary value149*/150public static int getPackedToBinaryValues(int input) {151return (((input & CommonData.HIGHER_NIBBLE_MASK) >> 4) * 10) +152(input & CommonData.LOWER_NIBBLE_MASK);153}154155/**156* Converts a binary value to a packed byte157*/158public static byte getBinaryToPackedValues(int input) {159int value = ((input/10) << 4) + (input % 10);160return (byte)value;161}162163/**164* Normalizes the input sign code to the preferred sign code.165*166* @return PACKED_MINUS if and only if the input is PACKED_MINUS or PACKED_ALT_MINUS, otherwise PACKED_PLUS167*/168public static byte getSign(int i) {169return (i == PACKED_MINUS || i == PACKED_ALT_MINUS) ? PACKED_MINUS : PACKED_PLUS;170}171172/**173* Returns the number of bytes required for storing a packed decimal of a174* given precision175*176* @param precision177* number of packed decimal digits178* @return number of bytes required for storing the packed decimal179*180* @throws ArrayIndexOutOfBoundsException181* if the precision value is invalid182*/183public static int getPackedByteCount(int precision) {184return ((precision / 2) + 1);185}186187/**188* Outputs the sum of the input and one taking into consideration the sign189* of the input190*/191public static byte getPackedAddOneSignValues(byte input) {192int digit = (input & CommonData.HIGHER_NIBBLE_MASK) >> 4;193digit++;194if (digit == 10)195digit = 0;196return (byte) (digit << 4 | (input & CommonData.LOWER_NIBBLE_MASK));197}198/**199* Byte array of single byte packed decimals. Each packed decimal is the sum200* of two packed decimals operands. The index is a function of the operand201* values.202*/203private static final byte[] packedSumValues = new byte[BYTE_ARITHMETICS_TABLE_LENGTH];204205/**206* Byte array of single byte packed decimals. Each packed decimal is the sum207* of two packed decimals operands and a carry from the previous byte. The208* index is a function of the operand values.209*/210private static final byte[] packedSumPlusOneValues = new byte[BYTE_ARITHMETICS_TABLE_LENGTH];211212/**213* Byte array of single byte packed decimals. Each packed decimal is the214* difference of two packed decimal operands. The index is a function of the215* operand values.216*/217private static final byte[] packedDifferenceValues = new byte[BYTE_ARITHMETICS_TABLE_LENGTH];218219/**220* Byte array of single byte packed decimals. Each packed decimal is the221* difference of two packed decimal operands and a borrow from the previous222* byte. The index is a function of the operand values.223*/224private static final byte[] packedDifferenceMinusOneValues = new byte[BYTE_ARITHMETICS_TABLE_LENGTH];225226static {227int i, j, m, n;228229Arrays.fill(packedSumValues, PACKED_INVALID_DIGIT);230Arrays.fill(packedSumPlusOneValues, PACKED_INVALID_DIGIT);231Arrays.fill(packedDifferenceValues, PACKED_INVALID_DIGIT);232Arrays.fill(packedDifferenceMinusOneValues, PACKED_INVALID_DIGIT);233// setting valid elements234for (i = 0; i < 10; i++) {235for (j = 0; j < 10; j++) {236for (m = 0; m < 10; m++) {237for (n = 0; n < 10; n++) {238setPackedSumArrays(i, j, m, n);239}240}241}242}243}244245/**246* Creates arrays holding results of simple operations on bytes comprising247* packed decimal digits.248*249* @param i250* first nibble (digit) of the first byte251* @param j252* second nibble (digit) of the first byte253* @param m254* first nibble (digit) of the second byte255* @param n256* second nibble (digit) of the second byte257*/258public static void setPackedSumArrays(int i, int j, int m, int n) {259int opAIndexValue, opBIndexValue;260int valueIdx, onesValue, tensValue;261byte byteValue;262// allow 5 bits for both tens sum and ones sum to get unique index263opAIndexValue = (i << 5) + j;264opBIndexValue = (m << 5) + n;265valueIdx = opAIndexValue + opBIndexValue;266// a + b or b + a values267onesValue = (j + n) % 10;268if (onesValue < j)269tensValue = (i + m + 1) % 10;270else271tensValue = (i + m) % 10;272byteValue = (byte) ((tensValue << 4) + onesValue);273packedSumValues[valueIdx] = byteValue;274275// a + b + 1(carry to previous byte) values276onesValue = (j + n + 1) % 10;277if (onesValue <= j)278tensValue = (i + m + 1) % 10;279else280tensValue = (i + m) % 10;281byteValue = (byte) ((tensValue << 4) + onesValue);282packedSumPlusOneValues[valueIdx] = byteValue;283284valueIdx = (opAIndexValue - opBIndexValue) & 0x3FF;285// a - b values286onesValue = (j - n + 10) % 10;287if (onesValue > j) // borrow required;288tensValue = (i - m - 1 + 10) % 10;289else290tensValue = (i - m + 10) % 10;291byteValue = (byte) ((tensValue << 4) + onesValue);292293if (packedDifferenceValues[valueIdx] == PACKED_INVALID_DIGIT)294packedDifferenceValues[valueIdx] = byteValue;295296// a - b - 1 (borrow from previous byte) values297onesValue = (j - n - 1 + 10) % 10;298if (onesValue >= j) // borrow required;299tensValue = (i - m - 1 + 10) % 10;300else301tensValue = (i - m + 10) % 10;302byteValue = (byte) ((tensValue << 4) + onesValue);303packedDifferenceMinusOneValues[valueIdx] = byteValue;304}305306}307308309