Path: blob/master/jcl/src/java.base/share/classes/com/ibm/jit/BigDecimalConverters.java
12628 views
/*[INCLUDE-IF]*/1package com.ibm.jit;23import java.math.BigDecimal;4import java.math.BigInteger;5import com.ibm.jit.BigDecimalExtension;6/*******************************************************************************7* Copyright (c) 2009, 2019 IBM Corp. and others8*9* This program and the accompanying materials are made available under10* the terms of the Eclipse Public License 2.0 which accompanies this11* distribution and is available at https://www.eclipse.org/legal/epl-2.0/12* or the Apache License, Version 2.0 which accompanies this distribution and13* is available at https://www.apache.org/licenses/LICENSE-2.0.14*15* This Source Code may also be made available under the following16* Secondary Licenses when the conditions for such availability set17* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU18* General Public License, version 2 with the GNU Classpath19* Exception [1] and GNU General Public License, version 2 with the20* OpenJDK Assembly Exception [2].21*22* [1] https://www.gnu.org/software/classpath/license.html23* [2] http://openjdk.java.net/legal/assembly-exception.html24*25* 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-exception26*******************************************************************************/2728public class BigDecimalConverters extends BigDecimalExtension {2930public static BigDecimal signedPackedDecimalToBigDecimal(byte[] packedDecimal, int scale)31{32if (DFPFacilityAvailable() && DFPUseDFP() &&33(packedDecimal.length <= 8 && -scale >= -398 && -scale < 369))34{35// fast conversion with hardware packed to DFP instruction36long longPack = 0;37if (packedDecimal.length == 8)38{39// explicitly unrolled loop to take advantage of sequential load40longPack = ((long)(packedDecimal[0] & 0xFF) << 56)41+ ((long)(packedDecimal[1] & 0xFF) << 48)42+ ((long)(packedDecimal[2] & 0xFF) << 40)43+ ((long)(packedDecimal[3] & 0xFF) << 32)44+ ((long)(packedDecimal[4] & 0xFF) << 24)45+ ((long)(packedDecimal[5] & 0xFF) << 16)46+ ((long)(packedDecimal[6] & 0xFF) << 8)47+ ((long)(packedDecimal[7] & 0xFF));48}49else50{51// slow way to load value into dfp52for(int i = 0; i < packedDecimal.length; ++i)53{54longPack = longPack << 8;55longPack += ((long)(packedDecimal[i] & 0xFF));56}57}5859BigDecimal bd = createZeroBigDecimal();60if (DFPConvertPackedToDFP(bd, longPack, 398 - scale, true))61{62// successfully converted to dfp63setflags(bd, 0x00);64return bd;65}66}67return slowSignedPackedToBigDecimal(packedDecimal, scale);68}6970private static BigDecimal slowSignedPackedToBigDecimal(byte[] packedDecimal, int scale)71{72String buffer = new String();73// convert the packed decimal to string buffer74for(int i = 0; i < packedDecimal.length - 1; ++i)75{76buffer += ((packedDecimal[i] & 0xF0) >> 4) + "" + (packedDecimal[i] & 0x0F); //$NON-NLS-1$77}78buffer += ((packedDecimal[packedDecimal.length - 1] & 0xF0) >> 4);7980// check to see if the packed decimal is negative81byte sign = (byte)(packedDecimal[packedDecimal.length - 1] & 0x0F);82if (sign == 0x0B || sign == 0x0D)83{84buffer = "-" + buffer; //$NON-NLS-1$85}86return new BigDecimal(new BigInteger(new String(buffer)), scale);87}8889public static byte[] BigDecimalToSignedPackedDecimal(BigDecimal bd)90{91if (DFPFacilityAvailable() && ((getflags(bd) & 0x3) == 0x0))92{93long longPack = DFPConvertDFPToPacked(getlaside(bd), true);94if (longPack != Long.MAX_VALUE)95{96// conversion from DFP to packed decimal was successful97byte [] packedDecimal = new byte[8];98packedDecimal[0] = (byte)((longPack >> 56) & 0xFF);99packedDecimal[1] = (byte)((longPack >> 48) & 0xFF);100packedDecimal[2] = (byte)((longPack >> 40) & 0xFF);101packedDecimal[3] = (byte)((longPack >> 32) & 0xFF);102packedDecimal[4] = (byte)((longPack >> 24) & 0xFF);103packedDecimal[5] = (byte)((longPack >> 16) & 0xFF);104packedDecimal[6] = (byte)((longPack >> 8) & 0xFF);105packedDecimal[7] = (byte)((longPack) & 0xFF);106return packedDecimal;107}108}109110// slow path to manually convert BigDecimal to packed decimal111return slowBigDecimalToSignedPacked(bd);112}113114private static byte [] slowBigDecimalToSignedPacked(BigDecimal bd)115{116// digits are right justified in the return byte array117BigInteger value = bd.unscaledValue();118char [] buffer = value.abs().toString().toCharArray();119int size = buffer.length / 2 + 1;120byte [] packedDecimal = new byte[size];121122int numDigitsLeft= buffer.length - 1;123int endPosition = numDigitsLeft % 2;124int index = size - 2;125126// take care of the sign nibble and the right most digit127packedDecimal[size - 1] = (byte)((buffer[numDigitsLeft] - '0') << 4);128packedDecimal[size - 1] |= ((value.signum() == -1) ? 0x0D : 0x0C);129130// compact 2 digits into each byte131for(int i = numDigitsLeft - 1; i >= endPosition; i -= 2, --index)132{133packedDecimal[index] = (byte)(buffer[i] - '0');134packedDecimal[index] |= (byte)((buffer[i - 1] - '0') << 4);135}136137// if there's a left over digit, put it in the last byte138if(endPosition > 0)139{140packedDecimal[index] = (byte)(buffer[0] - '0');141}142143return packedDecimal;144}145}146147148