Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/jcl/src/openj9.dataaccess/share/classes/com/ibm/dataaccess/CommonData.java
12558 views
1
/*[INCLUDE-IF DAA]*/
2
/*******************************************************************************
3
* Copyright (c) 2013, 2015 IBM Corp. and others
4
*
5
* This program and the accompanying materials are made available under
6
* the terms of the Eclipse Public License 2.0 which accompanies this
7
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
8
* or the Apache License, Version 2.0 which accompanies this distribution and
9
* is available at https://www.apache.org/licenses/LICENSE-2.0.
10
*
11
* This Source Code may also be made available under the following
12
* Secondary Licenses when the conditions for such availability set
13
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
14
* General Public License, version 2 with the GNU Classpath
15
* Exception [1] and GNU General Public License, version 2 with the
16
* OpenJDK Assembly Exception [2].
17
*
18
* [1] https://www.gnu.org/software/classpath/license.html
19
* [2] http://openjdk.java.net/legal/assembly-exception.html
20
*
21
* 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-exception
22
*******************************************************************************/
23
24
package com.ibm.dataaccess;
25
26
import java.util.Arrays;
27
28
/**
29
* Common data to assist conversions between binary, packed decimal & zoned
30
* decimal representations and arithmetic operations on packed decimals.
31
* *
32
* @author IBM
33
* @version $Revision$ on $Date$
34
*/
35
36
class CommonData {
37
38
public final static int HIGHER_NIBBLE_MASK = 0xF0;
39
public final static int LOWER_NIBBLE_MASK = 0x0F;
40
public final static int INTEGER_MASK = 0xFF; // used for converting byte to
41
// integer
42
/** Constant representing a packed zero */
43
final static byte PACKED_ZERO = (byte) (0x00);
44
45
final static byte PACKED_SIGNED_ZERO = (byte) 0x0C;
46
final static byte PACKED_PLUS = (byte) 0x0C;
47
final static byte PACKED_MINUS = (byte) 0x0D;
48
private static final byte PACKED_ALT_PLUS = (byte) 0x0F;
49
private static final byte PACKED_ALT_PLUS1 = (byte) 0x0E;
50
private static final byte PACKED_ALT_PLUS2 = (byte) 0x0A;
51
private static final byte PACKED_ALT_MINUS = (byte) 0x0B;
52
protected static final byte EXTERNAL_SIGN_PLUS = (byte)0x4e;
53
protected static final byte EXTERNAL_SIGN_MINUS = (byte)0x60;
54
protected static final byte EXTERNAL_EMBEDDED_SIGN_PLUS = (byte)0xC0;
55
protected static final byte EXTERNAL_EMBEDDED_SIGN_MINUS = (byte)0xD0;
56
57
protected static final byte EXTERNAL_EMBEDDED_SIGN_PLUS_ALTERNATE_A = (byte) 0xA0;
58
protected static final byte EXTERNAL_EMBEDDED_SIGN_PLUS_ALTERNATE_E = (byte) 0xE0;
59
protected static final byte EXTERNAL_EMBEDDED_SIGN_PLUS_ALTERNATE_F = (byte) 0xF0;
60
protected static final byte EXTERNAL_EMBEDDED_SIGN_MINUS_ALTERNATE_B = (byte) 0xB0;
61
62
protected final static byte PACKED_INVALID_DIGIT = (byte) (0xff);
63
64
/**
65
* The map table's for calculating byte arithmetics. sized to be 2^10 as we
66
* need to consider carries/borrows.
67
*/
68
private static final int BYTE_ARITHMETICS_TABLE_LENGTH = 1024;
69
70
/**
71
* Outputs the sum of two bytes
72
*/
73
public static int getPackedSumValues(int input) {
74
return packedSumValues[input] & INTEGER_MASK;
75
}
76
77
/**
78
* counts how many bytes are there in an external decimal.
79
*/
80
public static int getExternalByteCounts(int precision, int decimalType)
81
{
82
switch (decimalType)
83
{
84
case DecimalData.EBCDIC_SIGN_EMBEDDED_TRAILING:
85
case DecimalData.EBCDIC_SIGN_EMBEDDED_LEADING:
86
return precision;
87
case DecimalData.EBCDIC_SIGN_SEPARATE_TRAILING:
88
case DecimalData.EBCDIC_SIGN_SEPARATE_LEADING:
89
return precision+1;
90
default:
91
throw new IllegalArgumentException("illegal decimalType.");
92
}
93
}
94
95
/**
96
* Outputs the sum of two bytes plus one
97
*/
98
public static byte getPackedSumPlusOneValues(int input) {
99
return packedSumPlusOneValues[input];
100
}
101
102
/**
103
* Outputs the difference of two bytes
104
*/
105
public static byte getPackedDifferenceValues(int input) {
106
return packedDifferenceValues[input];
107
}
108
109
/**
110
* Outputs the difference of two bytes minus one
111
*/
112
public static byte getPackedDifferenceMinusOneValues(int input) {
113
return packedDifferenceMinusOneValues[input];
114
}
115
116
/**
117
* Outputs the sum of the input and one
118
*/
119
public static byte getPackedAddOneValues(byte input) {
120
int carryHighDigit = ((input & CommonData.HIGHER_NIBBLE_MASK) >> 4);
121
int carryLowDigit = (input & CommonData.LOWER_NIBBLE_MASK) + 1;
122
if (carryLowDigit == 10) {
123
carryLowDigit = 0;
124
carryHighDigit = carryHighDigit + 1;
125
if (carryHighDigit == 10) {
126
carryHighDigit = 0;
127
}
128
}
129
return (byte) ((carryHighDigit << 4) + carryLowDigit);
130
}
131
132
/**
133
* Outputs the difference of two bytes
134
*/
135
public static byte getPackedBorrowOneValues(byte input) {
136
int borrowHighDigit = ((input & CommonData.HIGHER_NIBBLE_MASK) >> 4);
137
int borrowLowDigit = (input & CommonData.LOWER_NIBBLE_MASK) - 1;
138
if (borrowLowDigit < 0) {
139
borrowLowDigit = 9;
140
borrowHighDigit = borrowHighDigit - 1;
141
if (borrowHighDigit < 0) {
142
borrowHighDigit = 9;
143
}
144
}
145
return (byte) ((borrowHighDigit << 4) + borrowLowDigit);
146
}
147
148
/**
149
* Converts a packed byte to binary value
150
*/
151
public static int getPackedToBinaryValues(int input) {
152
return (((input & CommonData.HIGHER_NIBBLE_MASK) >> 4) * 10) +
153
(input & CommonData.LOWER_NIBBLE_MASK);
154
}
155
156
/**
157
* Converts a binary value to a packed byte
158
*/
159
public static byte getBinaryToPackedValues(int input) {
160
int value = ((input/10) << 4) + (input % 10);
161
return (byte)value;
162
}
163
164
/**
165
* Normalizes the input sign code to the preferred sign code.
166
*
167
* @return PACKED_MINUS if and only if the input is PACKED_MINUS or PACKED_ALT_MINUS, otherwise PACKED_PLUS
168
*/
169
public static byte getSign(int i) {
170
return (i == PACKED_MINUS || i == PACKED_ALT_MINUS) ? PACKED_MINUS : PACKED_PLUS;
171
}
172
173
/**
174
* Returns the number of bytes required for storing a packed decimal of a
175
* given precision
176
*
177
* @param precision
178
* number of packed decimal digits
179
* @return number of bytes required for storing the packed decimal
180
*
181
* @throws ArrayIndexOutOfBoundsException
182
* if the precision value is invalid
183
*/
184
public static int getPackedByteCount(int precision) {
185
return ((precision / 2) + 1);
186
}
187
188
/**
189
* Outputs the sum of the input and one taking into consideration the sign
190
* of the input
191
*/
192
public static byte getPackedAddOneSignValues(byte input) {
193
int digit = (input & CommonData.HIGHER_NIBBLE_MASK) >> 4;
194
digit++;
195
if (digit == 10)
196
digit = 0;
197
return (byte) (digit << 4 | (input & CommonData.LOWER_NIBBLE_MASK));
198
}
199
/**
200
* Byte array of single byte packed decimals. Each packed decimal is the sum
201
* of two packed decimals operands. The index is a function of the operand
202
* values.
203
*/
204
private static final byte[] packedSumValues = new byte[BYTE_ARITHMETICS_TABLE_LENGTH];
205
206
/**
207
* Byte array of single byte packed decimals. Each packed decimal is the sum
208
* of two packed decimals operands and a carry from the previous byte. The
209
* index is a function of the operand values.
210
*/
211
private static final byte[] packedSumPlusOneValues = new byte[BYTE_ARITHMETICS_TABLE_LENGTH];
212
213
/**
214
* Byte array of single byte packed decimals. Each packed decimal is the
215
* difference of two packed decimal operands. The index is a function of the
216
* operand values.
217
*/
218
private static final byte[] packedDifferenceValues = new byte[BYTE_ARITHMETICS_TABLE_LENGTH];
219
220
/**
221
* Byte array of single byte packed decimals. Each packed decimal is the
222
* difference of two packed decimal operands and a borrow from the previous
223
* byte. The index is a function of the operand values.
224
*/
225
private static final byte[] packedDifferenceMinusOneValues = new byte[BYTE_ARITHMETICS_TABLE_LENGTH];
226
227
static {
228
int i, j, m, n;
229
230
Arrays.fill(packedSumValues, PACKED_INVALID_DIGIT);
231
Arrays.fill(packedSumPlusOneValues, PACKED_INVALID_DIGIT);
232
Arrays.fill(packedDifferenceValues, PACKED_INVALID_DIGIT);
233
Arrays.fill(packedDifferenceMinusOneValues, PACKED_INVALID_DIGIT);
234
// setting valid elements
235
for (i = 0; i < 10; i++) {
236
for (j = 0; j < 10; j++) {
237
for (m = 0; m < 10; m++) {
238
for (n = 0; n < 10; n++) {
239
setPackedSumArrays(i, j, m, n);
240
}
241
}
242
}
243
}
244
}
245
246
/**
247
* Creates arrays holding results of simple operations on bytes comprising
248
* packed decimal digits.
249
*
250
* @param i
251
* first nibble (digit) of the first byte
252
* @param j
253
* second nibble (digit) of the first byte
254
* @param m
255
* first nibble (digit) of the second byte
256
* @param n
257
* second nibble (digit) of the second byte
258
*/
259
public static void setPackedSumArrays(int i, int j, int m, int n) {
260
int opAIndexValue, opBIndexValue;
261
int valueIdx, onesValue, tensValue;
262
byte byteValue;
263
// allow 5 bits for both tens sum and ones sum to get unique index
264
opAIndexValue = (i << 5) + j;
265
opBIndexValue = (m << 5) + n;
266
valueIdx = opAIndexValue + opBIndexValue;
267
// a + b or b + a values
268
onesValue = (j + n) % 10;
269
if (onesValue < j)
270
tensValue = (i + m + 1) % 10;
271
else
272
tensValue = (i + m) % 10;
273
byteValue = (byte) ((tensValue << 4) + onesValue);
274
packedSumValues[valueIdx] = byteValue;
275
276
// a + b + 1(carry to previous byte) values
277
onesValue = (j + n + 1) % 10;
278
if (onesValue <= j)
279
tensValue = (i + m + 1) % 10;
280
else
281
tensValue = (i + m) % 10;
282
byteValue = (byte) ((tensValue << 4) + onesValue);
283
packedSumPlusOneValues[valueIdx] = byteValue;
284
285
valueIdx = (opAIndexValue - opBIndexValue) & 0x3FF;
286
// a - b values
287
onesValue = (j - n + 10) % 10;
288
if (onesValue > j) // borrow required;
289
tensValue = (i - m - 1 + 10) % 10;
290
else
291
tensValue = (i - m + 10) % 10;
292
byteValue = (byte) ((tensValue << 4) + onesValue);
293
294
if (packedDifferenceValues[valueIdx] == PACKED_INVALID_DIGIT)
295
packedDifferenceValues[valueIdx] = byteValue;
296
297
// a - b - 1 (borrow from previous byte) values
298
onesValue = (j - n - 1 + 10) % 10;
299
if (onesValue >= j) // borrow required;
300
tensValue = (i - m - 1 + 10) % 10;
301
else
302
tensValue = (i - m + 10) % 10;
303
byteValue = (byte) ((tensValue << 4) + onesValue);
304
packedDifferenceMinusOneValues[valueIdx] = byteValue;
305
}
306
307
}
308
309