Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/jcl/src/java.base/share/classes/com/ibm/jit/BigDecimalConverters.java
12628 views
1
/*[INCLUDE-IF]*/
2
package com.ibm.jit;
3
4
import java.math.BigDecimal;
5
import java.math.BigInteger;
6
import com.ibm.jit.BigDecimalExtension;
7
/*******************************************************************************
8
* Copyright (c) 2009, 2019 IBM Corp. and others
9
*
10
* This program and the accompanying materials are made available under
11
* the terms of the Eclipse Public License 2.0 which accompanies this
12
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
13
* or the Apache License, Version 2.0 which accompanies this distribution and
14
* is available at https://www.apache.org/licenses/LICENSE-2.0.
15
*
16
* This Source Code may also be made available under the following
17
* Secondary Licenses when the conditions for such availability set
18
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
19
* General Public License, version 2 with the GNU Classpath
20
* Exception [1] and GNU General Public License, version 2 with the
21
* OpenJDK Assembly Exception [2].
22
*
23
* [1] https://www.gnu.org/software/classpath/license.html
24
* [2] http://openjdk.java.net/legal/assembly-exception.html
25
*
26
* 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
27
*******************************************************************************/
28
29
public class BigDecimalConverters extends BigDecimalExtension {
30
31
public static BigDecimal signedPackedDecimalToBigDecimal(byte[] packedDecimal, int scale)
32
{
33
if (DFPFacilityAvailable() && DFPUseDFP() &&
34
(packedDecimal.length <= 8 && -scale >= -398 && -scale < 369))
35
{
36
// fast conversion with hardware packed to DFP instruction
37
long longPack = 0;
38
if (packedDecimal.length == 8)
39
{
40
// explicitly unrolled loop to take advantage of sequential load
41
longPack = ((long)(packedDecimal[0] & 0xFF) << 56)
42
+ ((long)(packedDecimal[1] & 0xFF) << 48)
43
+ ((long)(packedDecimal[2] & 0xFF) << 40)
44
+ ((long)(packedDecimal[3] & 0xFF) << 32)
45
+ ((long)(packedDecimal[4] & 0xFF) << 24)
46
+ ((long)(packedDecimal[5] & 0xFF) << 16)
47
+ ((long)(packedDecimal[6] & 0xFF) << 8)
48
+ ((long)(packedDecimal[7] & 0xFF));
49
}
50
else
51
{
52
// slow way to load value into dfp
53
for(int i = 0; i < packedDecimal.length; ++i)
54
{
55
longPack = longPack << 8;
56
longPack += ((long)(packedDecimal[i] & 0xFF));
57
}
58
}
59
60
BigDecimal bd = createZeroBigDecimal();
61
if (DFPConvertPackedToDFP(bd, longPack, 398 - scale, true))
62
{
63
// successfully converted to dfp
64
setflags(bd, 0x00);
65
return bd;
66
}
67
}
68
return slowSignedPackedToBigDecimal(packedDecimal, scale);
69
}
70
71
private static BigDecimal slowSignedPackedToBigDecimal(byte[] packedDecimal, int scale)
72
{
73
String buffer = new String();
74
// convert the packed decimal to string buffer
75
for(int i = 0; i < packedDecimal.length - 1; ++i)
76
{
77
buffer += ((packedDecimal[i] & 0xF0) >> 4) + "" + (packedDecimal[i] & 0x0F); //$NON-NLS-1$
78
}
79
buffer += ((packedDecimal[packedDecimal.length - 1] & 0xF0) >> 4);
80
81
// check to see if the packed decimal is negative
82
byte sign = (byte)(packedDecimal[packedDecimal.length - 1] & 0x0F);
83
if (sign == 0x0B || sign == 0x0D)
84
{
85
buffer = "-" + buffer; //$NON-NLS-1$
86
}
87
return new BigDecimal(new BigInteger(new String(buffer)), scale);
88
}
89
90
public static byte[] BigDecimalToSignedPackedDecimal(BigDecimal bd)
91
{
92
if (DFPFacilityAvailable() && ((getflags(bd) & 0x3) == 0x0))
93
{
94
long longPack = DFPConvertDFPToPacked(getlaside(bd), true);
95
if (longPack != Long.MAX_VALUE)
96
{
97
// conversion from DFP to packed decimal was successful
98
byte [] packedDecimal = new byte[8];
99
packedDecimal[0] = (byte)((longPack >> 56) & 0xFF);
100
packedDecimal[1] = (byte)((longPack >> 48) & 0xFF);
101
packedDecimal[2] = (byte)((longPack >> 40) & 0xFF);
102
packedDecimal[3] = (byte)((longPack >> 32) & 0xFF);
103
packedDecimal[4] = (byte)((longPack >> 24) & 0xFF);
104
packedDecimal[5] = (byte)((longPack >> 16) & 0xFF);
105
packedDecimal[6] = (byte)((longPack >> 8) & 0xFF);
106
packedDecimal[7] = (byte)((longPack) & 0xFF);
107
return packedDecimal;
108
}
109
}
110
111
// slow path to manually convert BigDecimal to packed decimal
112
return slowBigDecimalToSignedPacked(bd);
113
}
114
115
private static byte [] slowBigDecimalToSignedPacked(BigDecimal bd)
116
{
117
// digits are right justified in the return byte array
118
BigInteger value = bd.unscaledValue();
119
char [] buffer = value.abs().toString().toCharArray();
120
int size = buffer.length / 2 + 1;
121
byte [] packedDecimal = new byte[size];
122
123
int numDigitsLeft= buffer.length - 1;
124
int endPosition = numDigitsLeft % 2;
125
int index = size - 2;
126
127
// take care of the sign nibble and the right most digit
128
packedDecimal[size - 1] = (byte)((buffer[numDigitsLeft] - '0') << 4);
129
packedDecimal[size - 1] |= ((value.signum() == -1) ? 0x0D : 0x0C);
130
131
// compact 2 digits into each byte
132
for(int i = numDigitsLeft - 1; i >= endPosition; i -= 2, --index)
133
{
134
packedDecimal[index] = (byte)(buffer[i] - '0');
135
packedDecimal[index] |= (byte)((buffer[i - 1] - '0') << 4);
136
}
137
138
// if there's a left over digit, put it in the last byte
139
if(endPosition > 0)
140
{
141
packedDecimal[index] = (byte)(buffer[0] - '0');
142
}
143
144
return packedDecimal;
145
}
146
}
147
148