Path: blob/master/jcl/src/java.base/share/classes/com/ibm/jit/BigDecimalExtension.java
12628 views
/*[INCLUDE-IF]*/1package com.ibm.jit;23import java.math.BigDecimal;4import java.math.BigInteger;5import java.math.MathContext;6import java.math.RoundingMode;7import java.util.Arrays;89/*******************************************************************************10* Copyright (c) 2009, 2021 IBM Corp. and others11*12* This program and the accompanying materials are made available under13* the terms of the Eclipse Public License 2.0 which accompanies this14* distribution and is available at https://www.eclipse.org/legal/epl-2.0/15* or the Apache License, Version 2.0 which accompanies this distribution and16* is available at https://www.apache.org/licenses/LICENSE-2.0.17*18* This Source Code may also be made available under the following19* Secondary Licenses when the conditions for such availability set20* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU21* General Public License, version 2 with the GNU Classpath22* Exception [1] and GNU General Public License, version 2 with the23* OpenJDK Assembly Exception [2].24*25* [1] https://www.gnu.org/software/classpath/license.html26* [2] http://openjdk.java.net/legal/assembly-exception.html27*28* 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-exception29*******************************************************************************/3031public class BigDecimalExtension implements java.math.BigDecimal.BigDecimalExtension {32// Used to keep behavior of DFPHWAvailable consistent between33// jitted code and interpreter34// DO NOT CHANGE OR MOVE THIS LINE35// IT MUST BE THE FIRST THING IN THE INITIALIZATION36private static final boolean DFP_HW_AVAILABLE = DFPCheckHWAvailable();3738/*39* public static final int ROUND_CEILING 240* DFP hardware uses the value 010 == 241* public static final int ROUND_DOWN 142* DFP hardware uses the value 001 = 143* public static final int ROUND_FLOOR 344* DFP hardware uses the value 011 = 345* public static final int ROUND_HALF_DOWN 546* DFP hardware uses the value 101 = 547* public static final int ROUND_HALF_EVEN 6 <--mismatch in HW/Classlib spec48* DFP hardware uses the value 000 = 049* public static final int ROUND_HALF_UP 450* DFP hardware uses the value 100 = 451* public static final int ROUND_UNNECESSARY 752* DFP hardware uses the value 111 = 753* public static final int ROUND_UP 0 <--mismatch in HW/Classlib spec54* DFP hardware uses the value 110 = 655*/5657/**58* LUT for DFP double combination field - gives us the leftmost59* digit of the coefficient, as well as the first two bits of the60* exponent in form: 0xXY where X = LMD, Y = first two bits61*/62private static byte []doubleDFPComboField = comboinit();6364// LUT for converting DPD to BCD, 1024 elements65private static short []DPD2BCD = dpd2bcdinit();6667// DFP 0 with exponent 068private static final long dfpZERO = 2465720795985346560L;6970private static final BigInteger MAXDFP64 = BigInteger.valueOf(9999999999999999L);71private static final BigInteger MINDFP64 = BigInteger.valueOf(-9999999999999999L);7273/* Used for Hysteresis for mixed-representation74* We want the BigDecimal class to choose the best representation75* for construction and operations. We start assuming the LL76* is the best representation. Over the course of time, using77* hysterisis, we might alter this decision.78*79* The constructors are annotated with the checks on deciding80* which representation to use, and other APIs contribute81* to biasing towards or away from a representation.82*83* NOTE: Hysterisis only works on platforms that supports DFP84* since we prepend a DFPHWAvailable check before performing85* mods to the counters, and before basing decisions off them.86*/87private static int hys_threshold = 1000; // threshold for representation change88// above means that hys_counter must reach -/+ MAX_VALUE before changing rep89private static boolean hys_type; // false = non-dfp, true = dfp90private static int hys_counter; // increment for dfp, decrement for non-dfp9192private static BigDecimalExtension instance;9394protected BigDecimalExtension() {95}9697public static BigDecimalExtension getInstance() {98if (instance == null) {99instance = new BigDecimalExtension();100}101return instance;102}103104public boolean performHardwareUsageHeuristic(MathContext set, int bias) {105if (DFPPerformHysteresis() &&106set.getPrecision() == 16 && set.getRoundingMode().ordinal() == BigDecimal.ROUND_HALF_EVEN){107performHardwareUsageHeuristic(bias);108return true;109}110return false;111}112113private void performHardwareUsageHeuristic(int bias) {114int sum = hys_counter + bias;115hys_counter += bias & ~(((sum^bias) & (sum^hys_counter)) >>> 31);116117if (hys_counter<-hys_threshold){118hys_type = false; //nonDFP119hys_counter=0;120}121else if (hys_counter>hys_threshold){122hys_type = true; // DFP123hys_counter=0;124}125}126127public boolean isAvailable() {128return DFPHWAvailable();129}130131public boolean useExtension() {132return DFPUseDFP();133}134135public boolean suitableForExtension(int nDigits, int scale) {136return (nDigits < 17 && scale >= -398 && scale < 369);137}138139public int add(BigDecimal res, BigDecimal lhs, BigDecimal rhs) {140int resExp =-(Math.max(lhs.scale(), rhs.scale()));141/* Precision = 0, rounding = UNNECESSARY */142if (resExp >=-398 && resExp<=369){143if(DFPScaledAdd(res, getlaside(rhs), getlaside(lhs), resExp+398)){144// we can and out the flags because we don't have145// a sense of the exponent/precision/sign146// of this result, nor do we want to use DFP hw147// to figure it out, so we do not cache anything148149//set res as DFP - (already set to 00)150151// because DFP add takes the exclusive or of the sign bits152//for the result, need to make sure result of add 0 by -0153//doesn't store a negative sign...154long laside = getlaside(res);155if(isDFPZero(laside)) {156laside &= 0x7FFFFFFFFFFFFFFFL;157setlaside(res, laside);158}159return HARDWARE_OPERATION_SUCCESS;160}161}162return HARDWARE_OPERATION_FAIL;163}164165public int add(BigDecimal res, BigDecimal lhs, BigDecimal rhs, MathContext set) {166boolean passed = false;167int prec = set.getPrecision();168int rm = set.getRoundingMode().ordinal();169long lhslaside = getlaside(lhs);170long rhslaside = getlaside(rhs);171172// need to special case this since DFP hardware173// doesn't conform to BigDecimal API when adding174// to a 0..175if (prec != 0 && set.getRoundingMode().ordinal() != BigDecimal.ROUND_UNNECESSARY){176boolean lZero = isDFPZero(lhslaside);177boolean rZero = isDFPZero(rhslaside);178179if(lZero || rZero) {180if(!lZero) {181clone(lhs, res); // rhs is zero182if (rhs.scale() > lhs.scale()){183if (set.getPrecision()-rhs.precision() >0) {184clone(res.setScale(Math.abs(-rhs.scale())), res); //might return BI185}186}187} else if (!rZero) {188clone(rhs, res); // lhs is zero189if (lhs.scale() > rhs.scale()){190if (set.getPrecision()-rhs.precision() >0) {191clone(res.setScale(Math.abs(-lhs.scale())), res); //might return BI192}193}194} else {195BigDecimal temp = BigDecimal.valueOf(0, Math.max(lhs.scale(), rhs.scale())); // both operands are zero196clone(temp, res); //CMVC 136111 -- res could be one of statics (shared)197}198199if (set != MathContext.UNLIMITED) {200if(finish(res, set.getPrecision(), set.getRoundingMode().ordinal()) == HARDWARE_OPERATION_FAIL) {201return HARDWARE_OPERATION_FAIL;202}203204}205return HARDWARE_OPERATION_SUCCESS;206}207}208209// we can and out the flags because we don't have210// a sense of the exponent/precision/sign211// of this result, nor do we want to use DFP hw212// to figure it out, so we do not cache anything213214// fast path for MathContext64215if (prec == 16 && rm == BigDecimal.ROUND_HALF_EVEN){216if(DFPAdd(res, rhslaside, lhslaside, 64, 0, 0)){217passed =true;218}219} else if (prec == 0) { // same as scaled DFPAddition220int resExp =-(Math.max(lhs.scale(), rhs.scale()));221if (resExp >=-398 && resExp <= 369){222if(DFPScaledAdd(res, rhslaside, lhslaside, resExp+398)){223//set res as DFP - (already set to 00)224passed = true;225}226}227} else if (prec > 0 && rm == BigDecimal.ROUND_UNNECESSARY){ // fast path for NO ROUNDING, as well as the ArithmeticException228if(DFPAdd(res, rhslaside, lhslaside, 0, 0, 0)){229performHardwareUsageHeuristic(set, -3);230// set res as DFP - (already set to 00)231if(finish(res, prec, rm) == HARDWARE_OPERATION_FAIL) { // See if we need to throw an arithmetic exception232return HARDWARE_OPERATION_FAIL;233}234passed = true;235}236} else if (prec <=16) { // Otherwise, if a precision to round to is specified237238// NOTE: We do the following two if statements239// since the constants used for HALF_EVEN and ROUND_UP in240// the classlib do not map correctly to the DFP hardware241// rounding mode bits. All other classlib RoundingModes, however, do.242243//the default DFP rounding mode244if (rm == BigDecimal.ROUND_HALF_EVEN)245rm = BigDecimal.ROUND_UP; //correct DFP HW rounding mode for HALF_EVEN246else if (rm == BigDecimal.ROUND_UP)247rm = BigDecimal.ROUND_HALF_EVEN; //correct DFP HW rounding mode for HALF_UP248249// defect 144394250boolean dfpPassed = prec == 16 ?251DFPAdd(res, rhslaside, lhslaside, 1, 16, rm) :252DFPAdd(res, rhslaside, lhslaside, 1, prec, rm);253if(dfpPassed){254performHardwareUsageHeuristic(set, -3);255// set res as DFP - (already set to 00)256passed=true;257}258}259260// because DFP add takes the exclusive or of the sign bits261//for the result, need to make sure result of add 0 by -0262//doesn't store a negative sign...263if (passed){264long reslaside = getlaside(res);265if(isDFPZero(reslaside)) {266reslaside &= 0x7FFFFFFFFFFFFFFFL;267setlaside(res, reslaside);268}269return HARDWARE_OPERATION_SUCCESS;270}271return HARDWARE_OPERATION_FAIL;272}273274public int subtract(BigDecimal res, BigDecimal lhs, BigDecimal rhs) {275276int resExp =-(Math.max(lhs.scale(), rhs.scale()));277// Precision = 0, rounding = UNNECESSARY278if (resExp >=-398 && resExp<=369){279if(DFPScaledSubtract(res, getlaside(rhs), getlaside(lhs), resExp+398)){280// set res as DFP - (already set to 00)281282// because DFP subtract takes the exclusive or of the sign bits283//for the result, need to make sure result of subtract 0 by -0284//doesn't store a negative sign...285long laside = getlaside(res);286if(isDFPZero(laside)) {287laside &= 0x7FFFFFFFFFFFFFFFL;288setlaside(res, laside);289}290return HARDWARE_OPERATION_SUCCESS;291292}293}294return HARDWARE_OPERATION_FAIL;295}296297public int subtract(BigDecimal res, BigDecimal lhs, BigDecimal rhs, MathContext set) {298boolean passed = false;299int prec = set.getPrecision();300int rm = set.getRoundingMode().ordinal();301long lhslaside = getlaside(lhs);302long rhslaside = getlaside(rhs);303304// need to special case this since DFP hardware305// doesn't conform to BigDecimal API when adding306// to a 0..307if (prec != 0 && set.getRoundingMode().ordinal() != BigDecimal.ROUND_UNNECESSARY){308boolean lZero = isDFPZero(lhslaside);309boolean rZero = isDFPZero(rhslaside);310if(lZero || rZero) {311if(!lZero) {312clone(lhs, res); // rhs is zero313if (rhs.scale() > lhs.scale()){314if (set.getPrecision()-rhs.precision() >0) {315clone(res.setScale(Math.abs(-rhs.scale())), res); //might return BI316}317}318} else if (!rZero) {319clone(rhs.negate(), res); // lhs is zero320if (lhs.scale() > rhs.scale()){321if (set.getPrecision()-rhs.precision() >0) {322clone(res.setScale(Math.abs(-lhs.scale())), res); //might return BI323}324}325} else {326BigDecimal temp = BigDecimal.valueOf(0, Math.max(lhs.scale(), rhs.scale())); // both operands are zero327clone(temp, res); //CMVC 136111 -- res could be one of statics (shared)328}329330if (set != MathContext.UNLIMITED) {331if(finish(res, set.getPrecision(), set.getRoundingMode().ordinal()) == HARDWARE_OPERATION_FAIL) {332return HARDWARE_OPERATION_FAIL;333}334}335return HARDWARE_OPERATION_SUCCESS;336}337}338339340341// at this point, not dealing with 0s342// fast path for MathContext64343if (prec == 16 && rm == BigDecimal.ROUND_HALF_EVEN){344if(DFPSubtract(res, rhslaside, lhslaside, 64, 0, 0)){345// set res as DFP - (already set to 00)346passed=true;347}348} else if (prec == 0){ // same as DFPScaledSubtract349int resExp =-(Math.max(lhs.scale(), rhs.scale()));350if (resExp >=-398 && resExp<=369){351if(DFPScaledSubtract(res, rhslaside, lhslaside, resExp+398)){352// we can and out the flags because we don't have353// a sense of the exponent/precision/sign354// of this result, nor do we want to use DFP hw355// to figure it out, so we do not cache anything356357// set res as DFP - (already set to 00)358passed = true;359}360}361} else if (prec > 0 && rm == BigDecimal.ROUND_UNNECESSARY){ // fast path for NO ROUNDING, as well as the ArithmeticException362if(DFPSubtract(res, rhslaside, lhslaside, 0, 0, 0)){363performHardwareUsageHeuristic(set, -3);364// set res as DFP - (already set to 00)365// See if we need to throw an arithmetic exception366if(finish(res, prec, rm) == HARDWARE_OPERATION_FAIL) {367return HARDWARE_OPERATION_FAIL;368}369passed=true;370}371} else if(prec <=16){ // Otherwise, if a precision to round to is specified372373/* NOTE: We do the following two if statements374* since the constants used for HALF_EVEN and ROUND_UP in375* the classlib do not map correctly to the DFP hardware376* rounding mode bits. All other classlib RoundingModes, however, do.377*/378379//the default DFP rounding mode380if (rm == BigDecimal.ROUND_HALF_EVEN) {381rm = BigDecimal.ROUND_UP; //correct DFP HW rounding mode for HALF_EVEN382} else if (rm == BigDecimal.ROUND_UP) {383rm = BigDecimal.ROUND_HALF_EVEN; //correct DFP HW rounding mode for HALF_UP384}385// defect 144394386boolean dfpPassed = prec == 16 ?387DFPSubtract(res, rhslaside, lhslaside, 1, 16, rm) :388DFPSubtract(res, rhslaside, lhslaside, 1, prec, rm);389if(dfpPassed){390performHardwareUsageHeuristic(set, -3);391// set res as DFP - (already set to 00)392passed=true;393}394}395396// because DFP subtracts takes the exclusive or of the sign bits397//for the result, need to make sure result of subtract 0 by -0398//doesn't store a negative sign...399if (passed){400long reslaside = getlaside(res);401if(isDFPZero(reslaside)) {402reslaside &= 0x7FFFFFFFFFFFFFFFL;403setlaside(res, reslaside);404}405return HARDWARE_OPERATION_SUCCESS;406}407return HARDWARE_OPERATION_FAIL;408}409410public int multiply(BigDecimal res, BigDecimal lhs, BigDecimal rhs) {411412int resExp =-(lhs.scale()+rhs.scale());413414/* Precision = 0, rounding = UNNECESSARY */415if (resExp >=-398 && resExp<=369){416if(DFPScaledMultiply(res, getlaside(rhs), getlaside(lhs), resExp+398)){417// set res as DFP - (already set to 00)418419// because DFP subtract takes the exclusive or of the sign bits420//for the result, need to make sure result of subtract 0 by -0421//doesn't store a negative sign...422long laside = getlaside(res);423if(isDFPZero(laside)) {424laside &= 0x7FFFFFFFFFFFFFFFL;425setlaside(res, laside);426}427return HARDWARE_OPERATION_SUCCESS;428}429}430return HARDWARE_OPERATION_FAIL;431}432433public int multiply(BigDecimal res, BigDecimal lhs, BigDecimal rhs, MathContext set) {434435boolean passed = false;436int prec = set.getPrecision();437int rm = set.getRoundingMode().ordinal();438long lhslaside = getlaside(lhs);439long rhslaside = getlaside(rhs);440441442// fast path for MathContext64443if (prec == 16 && rm == BigDecimal.ROUND_HALF_EVEN){444if(DFPMultiply(res, rhslaside, lhslaside, 64, 0, 0)){445// set res as DFP - (already set to 00)446passed = true;447}448} else if (prec == 0){ // same as DFPScaledMultiply449int resExp =-(lhs.scale()+rhs.scale());450if (resExp >=-398 && resExp<=369){451if(DFPScaledMultiply(res, rhslaside, lhslaside, resExp+398)){452// set res as DFP - (already set to 00)453// because DFP multiply takes the exclusive or of the sign bits454//for the result, need to make sure result of multiply by 0455//doesn't store a negative sign...456passed = true;457}458}459} else if (prec > 0 && rm == BigDecimal.ROUND_UNNECESSARY){ // fast path for NO ROUNDING, as well as the ArithmeticException460if(DFPMultiply(res, rhslaside, lhslaside, 0, 0, 0)){461// set res as DFP - (already set to 00)462463// See if we need to throw an arithmetic exception464if(finish(res, prec, rm) == HARDWARE_OPERATION_FAIL) {465return HARDWARE_OPERATION_FAIL;466}467passed=true;468}469} else if (prec <= 16) { // Otherwise, if a precision to round to is specified470/* NOTE: We do the following two if statements471* since the constants used for HALF_EVEN and ROUND_UP in472* the classlib do not map correctly to the DFP hardware473* rounding mode bits. All other classlib RoundingModes, however, do.474*/475476//the default DFP rounding mode477if (rm == BigDecimal.ROUND_HALF_EVEN) {478rm = BigDecimal.ROUND_UP; //correct DFP HW rounding mode for HALF_EVEN479} else if (rm == BigDecimal.ROUND_UP) {480rm = BigDecimal.ROUND_HALF_EVEN; //correct DFP HW rounding mode for HALF_UP481}482483// defect 144394484boolean dfpPassed = prec == 16 ?485DFPMultiply(res, rhslaside, lhslaside, 1, 16, rm) :486DFPMultiply(res, rhslaside, lhslaside, 1, prec, rm);487if(dfpPassed) {488// set res as DFP - (already set to 00)489passed =true;490}491}492493// because DFP multiply takes the exclusive or of the sign bits494// for the result, need to make sure result of multiply by 0495// doesn't store a negative sign...496if (passed){497long reslaside = getlaside(res);498if(isDFPZero(reslaside)) {499reslaside &= 0x7FFFFFFFFFFFFFFFL;500setlaside(res, reslaside);501}502return HARDWARE_OPERATION_SUCCESS;503}504return HARDWARE_OPERATION_FAIL;505}506507public int divide(BigDecimal res, BigDecimal lhs, BigDecimal rhs) {508509long rhslaside = getlaside(rhs);510if(isDFPZero(rhslaside)) {511badDivideByZero();512}513boolean passed = false;514long lhslaside = getlaside(lhs);515516/*517* Interpreted return value:518* Returns -1 if not JIT compiled.519*520* JIT compiled return value:521* Return 1 if JIT compiled and DFP divide is successful.522* Return 0 if JIT compiled, but DFP divide was inexact523* Return -2 if JIT compiled, but other exception (i.e. overflow)524*/525526// we need this in order to throw a "non-terminating decimal expansion" error527int desiredPrecision = (int)Math.min(lhs.precision() + Math.ceil(10*rhs.precision()/3),Integer.MAX_VALUE);528529int ret = DFPDivide(res, rhslaside, lhslaside, true, 0, 0, 0);530531// we passed, just check for non-terminating decimal expansion532if (ret == 1){533if (res.precision() > desiredPrecision) {534/*[MSG "K0460", "Non-terminating decimal expansion"]*/535throw new ArithmeticException(com.ibm.oti.util.Msg.getString("K0460")); //$NON-NLS-1$536}537// set res as DFP - (already set to 00)538passed=true;539}540541//otherwise, we had an inexact, or failure... so we'll continue on slow path542543// because DFP divide takes the exclusive or of the sign bits544//for the result, need to make sure result of multiply by 0545//doesn't store a negative sign...546if (passed){547long reslaside = getlaside(res);548if(isDFPZero(reslaside)) {549reslaside &= 0x7FFFFFFFFFFFFFFFL;550setlaside(res, reslaside);551}552return HARDWARE_OPERATION_SUCCESS;553}554555return HARDWARE_OPERATION_FAIL;556}557558public int divide(BigDecimal res, BigDecimal lhs, BigDecimal rhs, MathContext set) {559560long rhslaside = getlaside(rhs);561if(isDFPZero(rhslaside)) {562badDivideByZero();563}564long lhslaside = getlaside(lhs);565int prec = set.getPrecision();566int rm = set.getRoundingMode().ordinal();567boolean passed=false;568569// fast path for MathContext64570if (prec == 16 && rm == BigDecimal.ROUND_HALF_EVEN){571int ret = DFPDivide(res, rhslaside, lhslaside, false, 64, 0, 0);572if (ret == 1){573// set res as DFP - (already set to 00)574passed = true;575}576} else if (prec <= 16) {577578//the default DFP rounding mode579if (rm == BigDecimal.ROUND_HALF_EVEN) {580rm = BigDecimal.ROUND_UP; //correct DFP HW rounding mode for HALF_EVEN581} else if (rm == BigDecimal.ROUND_UP) {582rm = BigDecimal.ROUND_HALF_EVEN; //correct DFP HW rounding mode for HALF_UP583}584585// defect 144394586int ret = prec == 16 ?587DFPDivide(res, rhslaside, lhslaside, true, 1, 16, rm) :588DFPDivide(res, rhslaside, lhslaside, true, 1, prec, rm);589if (ret == 0 && rm == BigDecimal.ROUND_UNNECESSARY) {590/*[MSG "K0461", "Inexact result requires rounding"]*/591throw new ArithmeticException(com.ibm.oti.util.Msg.getString("K0461")); //$NON-NLS-1$592}593//otherwise, we divide perfectly and returned 1, or divided594//and got inexact (in the absence of checking for ROUND_UNNECESSARY595//but that's ok because we had:596// REREOUND + TGDT + CHECKINEXACT597598//d120228599if (ret == 1){600performHardwareUsageHeuristic(set, 10);601// set res as DFP - (already set to 00)602passed = true;603}604}605// because DFP divide takes the exclusive or of the sign bits606//for the result, need to make sure result of multiply by 0607//doesn't store a negative sign...608if (passed){609long reslaside = getlaside(res);610if(isDFPZero(reslaside)) {611reslaside &= 0x7FFFFFFFFFFFFFFFL;612setlaside(res, reslaside);613}614return HARDWARE_OPERATION_SUCCESS;615}616617return HARDWARE_OPERATION_FAIL;618}619620public int negate(BigDecimal res, MathContext set) {621622int signum = res.signum();623int flags = getflags(res);624long laside = getlaside(res);625// we're going to cache a new sign bit...626627flags |= 0x4;628629// need to flip DFP sign bit and cached sign630if (signum == -1){631laside &= 0x7FFFFFFFFFFFFFFFL; //flip DFP sign bit632flags &= 0xFFFFFF9F; //clear the cached sign bits633flags |= ( 1 << 5) & 0x60;// ispos634}635else if (signum == 1){636laside |= 0x8000000000000000L; //flip DFP sign bit637flags &= 0xFFFFFF9F; //clear the cached sign bits638flags |= (3 << 5) & 0x60; // isneg639}640if (getbi(res) != null) {641setbi(res, getbi(res).negate());642}643setflags(res, flags);644setlaside(res, laside);645646return HARDWARE_OPERATION_SUCCESS;647}648649public int compareTo(BigDecimal lhs, BigDecimal rhs) {650651int res = DFPCompareTo(getlaside(lhs), getlaside(rhs));652if (res != -2) {653return res;654}655return HARDWARE_OPERATION_FAIL;656}657658public int getScale(BigDecimal bd) {659660int myscale = getscale(bd);661// have we cached it?662if ((getflags(bd) & 0x8) != 0) {663return myscale;664}665666//caching it667668setflags(bd, getflags(bd) | 0x8); //cache on669670int newExp = DFPExponent(getlaside(bd));671if (newExp == 1000) {672myscale = -(extractDFPExponent(getlaside(bd))-398);673} else {674myscale = -(newExp-398);675}676setscale(bd, myscale);677return myscale;678}679680public int setScale(BigDecimal bd, int scale) {681682if (-scale >= -398 && -scale <= 369){683int ret = DFPSetScale(bd, getlaside(bd), -scale+398, false, 0, true);684if (ret == 1){685if(DFPPerformHysteresis()) {686performHardwareUsageHeuristic(5);687}688689/* cache - SGP ESRR */690691// set representation to DFP692// (already 00)693694// because DFPSetScale maintains the sign of the DFP695// -23 might get scaled down to -0696long laside = getlaside(bd);697int flags = getflags(bd);698if(isDFPZero(laside)){699laside &= 0x7FFFFFFFFFFFFFFFL;700flags |= 0x4;701flags &= 0xFFFFFF9F; //clear signum bits for 0702}703else{704// cache the sign of the src705flags|= 0x4;706flags |= (bd.signum()<<5)&0x60;707}708709// cache the exponent710flags|=0x8;711//NOTE: We do not cache precision!712flags&=0xFFFFFFEF; //clear prec cache bit713714setscale(bd, scale);715setflags(bd, flags);716setlaside(bd, laside);717718719return HARDWARE_OPERATION_SUCCESS;720}721else if (ret == 0) {722/*[MSG "K0455", "Requires rounding: {0}"]*/723throw new ArithmeticException(com.ibm.oti.util.Msg.getString("K0455", Long.toString(scale))); //$NON-NLS-1$724}725}726727return HARDWARE_OPERATION_FAIL;728}729730public int setScale(BigDecimal bd, int scale, int roundingMode) {731732if (-scale >= -398 && -scale <= 369){733734// If the rounding mode is UNNECESSARY, then we can set735// the scale as if we were setting in the previous API736// i.e. with no concern to rounding (the 3rd parameter)737if (roundingMode == BigDecimal.ROUND_UNNECESSARY){738739//120991 (changed last param from false to true)740int ret = DFPSetScale(bd, getlaside(bd), -scale+398,false, 0, true);741if (ret == 1){742if (DFPPerformHysteresis()){743performHardwareUsageHeuristic(5);744}745746/* cache - SGP ESRR */747748// set representation to DFP749// (already 00)750751// because DFPSetScale maintains the sign of the DFP752// -23 might get scaled down to -0753long laside = getlaside(bd);754int flags = 0;755756if(isDFPZero(laside)){757laside &= 0x7FFFFFFFFFFFFFFFL;758flags|=0x4;759flags&=0xFFFFFF9F; //clear signum bits for 0760}761else{762// cache the sign of the src763flags|=0x4;764flags |=(bd.signum()<<5)&0x60;765}766767// cache the exponent768flags|=0x8;769770setscale(bd, scale);771setflags(bd, flags);772setlaside(bd, laside);773return HARDWARE_OPERATION_SUCCESS;774775}776}777else{778779//the default DFP rounding mode780if (roundingMode == BigDecimal.ROUND_HALF_EVEN) {781roundingMode = BigDecimal.ROUND_UP; //correct DFP HW rounding mode for HALF_EVEN782} else if (roundingMode == BigDecimal.ROUND_UP) {783roundingMode = BigDecimal.ROUND_HALF_EVEN; //correct DFP HW rounding mode for HALF_UP784}785int ret = DFPSetScale(bd, getlaside(bd), -scale+398,true, roundingMode, false);786if (ret == 1){787if (DFPPerformHysteresis()){788performHardwareUsageHeuristic(5);789}790791/* cache - SGP ESRR */792793// set representation to DFP794// (already 00)795796// because DFPSetScale maintains the sign of the DFP797// -23 might get scaled down to -0798long laside = getlaside(bd);799int flags = 0;800801if(isDFPZero(laside)){802laside &= 0x7FFFFFFFFFFFFFFFL;803flags |= 0x4;804flags &= 0xFFFFFF9F; //clear signum bits for 0805}806else{807// cache the sign of the src808flags |= 0x4;809flags |= (bd.signum()<<5)&0x60;810}811812// cache the exponent813flags |= 0x8;814setscale(bd, scale);815setflags(bd, flags);816setlaside(bd, laside);817818return HARDWARE_OPERATION_SUCCESS;819}820}821}822return HARDWARE_OPERATION_FAIL;823}824825public String toStringNoDecimal(BigDecimal bd) {826// Get the unscaled value;827long laside = getlaside(bd);828long lVal = DFPUnscaledValue(laside);829if (lVal == Long.MAX_VALUE){830lVal = DFPBCDDigits(laside);831if (lVal == 10) {832lVal = extractDFPDigitsBCD(laside);833}834// now extract each 4 bit BCD digit from left to right835long val=0; //to store the result836int i=0;837while (lVal!= 0){838val += (lVal & 0xF) * powerOfTenLL(i++);839lVal >>>= 4;840}841//is the sign negative?842return Long.toString(val * bd.signum());843} else {844return Long.toString(lVal);845}846}847848public String toString(BigDecimal bd, int length) {849// Get the exponent850// Need to store it as a long since we may have851// stored Long.MIN_VALUE (which needs to be printed852// to screen as Long.MIN_VALUE853854long actualExp = -(long)bd.scale();855856// Get the precision857int precision = bd.precision();858859// Get the unscaled value;860long laside = getlaside(bd);861long bcd = DFPBCDDigits(laside);862if (bcd == 10)863bcd = extractDFPDigitsBCD(laside);864865long adjExp= actualExp + precision -1;866867// two cases to consider:868/*869* case 1: precision > 1870* singlenumber.remaining numbersE(+/-adjusted exponent)871* case 2: else872* numberE(+/-adjusted exponent)873*/874875int expPrecision = numDigits(adjExp);876877// Fill 'er up878879// the character array to fill up880char [] str;881int index=0;882883if (length <=22)884str = (char [])thLocalToString.get();885else886str = new char [ length ];887888// the sign889if (bd.signum() == -1){890str[index++] = '-';891}892893// the first digit894str[index++] = (char)(digitAtBCD(bcd,precision,0)|0x0030);895896if (precision > 1){897898// the decimal dot899str[index++] = '.';900901// rest of the digits902for (int i=0;i < precision-1 ;i++)903str[index++] = (char)(digitAtBCD(bcd,precision,i+1)|0x0030);904}905906// E907str[index++] = 'E';908909// the +910if (actualExp>0)911str[index++] = '+';912else if (actualExp<0)913str[index++] = '-';914915// exponent digits916for (int i=0; i < expPrecision; i++)917str[index++] = (char)(digitAt(adjExp,expPrecision,i)|0x0030);918919return new String(str, 0, length);920}921922public String toStringPadded(BigDecimal bd, int sign, int precision, int strlen) {923//NOTE : unscaledValue is in BCD form924char [] str;925int actualExp = -bd.scale();926int signLen=0;927if (sign == -1)928signLen = 1;929long laside = getlaside(bd);930// Get the unscaled value;931long unscaledValue= DFPBCDDigits(laside);932if (unscaledValue == 10) {933unscaledValue = extractDFPDigitsBCD(laside);934}935// if scale is less than precision, won't have936// any leading zeros, and our number will have a decimal937// point somewhere in the middle...938939/*940* 1234 scale 1 = 123.4941* 1234 scale 2 = 12.34942* 1234 scale 3 = 1.234943* 123400 scale 3 = 123.400 <-- need to handle trailing zeros for BI rep944* 123400 scale 5 = 12340.0 <-- need to handle trailing zeros for BI rep945*946* NOTE: don't need to handle scale <= 0 since this is taken care of947* in other branches in toStringHelper948*/949if (-actualExp < precision){950int i=0;951952// for LL953// 1 no need to fill with trailing zeros954// 2 lay down sign955// 3 lay down all digits after decimal point956// 4 lay down digits before decimal point957958int length= signLen + 1 /*for .*/ + precision;959960if (length <=22)961str = (char [])thLocalToString.get();962else963str = new char [ length ];964int start=0;965int decimalPointLoc = length-(-actualExp)-1;966967// 2 Place sign968if (signLen !=0){969str[start++]='-';970}971972int curBCD = 0;973974//3 lay down all digits after decimal point975for (i=(length-1); i > decimalPointLoc; i--){976curBCD = (int)(unscaledValue & 0xF);977unscaledValue >>>=4;978str[i] = (char)(curBCD|0x0030);979}980981// lay down decimal point982str[i--]='.';983984//4 lay down all digits before decimal point985for (;i >=start; i--){986curBCD = (int) (unscaledValue & 0xF);987unscaledValue >>>=4;988str[i] = (char)(curBCD|0x0030);989}990}991else{992// easy case.. where scale >= precision993994/*995* 1234 scale 4 = 0.1234996* 1234 scale 5 = 0.01234997* 1234 scale 6 = 0.001234998*/9991000int numZeros = -actualExp - precision;10011002// for both LL & BI1003// 1 fill with zeros1004// 2 lay down sign & lay down decimal point1005// 3 lay down all digits10061007int length= signLen + 1 /*for 0*/ +10081 /*for .*/+ numZeros + precision;10091010if (length <=22)1011str = (char [])thLocalToString.get();1012else1013str = new char [ length ];1014int start=0;1015int i=0;10161017//1 Fill with 01018Arrays.fill(str,0,length,'0');10191020//2 Place sign1021if (signLen !=0)1022str[start++]='-';10231024//2 skip leading zero1025start++;10261027//2 Place decimal point1028str[start++]='.';10291030//2 skip more leading zeros that occur after decimal point1031start+=(-actualExp - precision);10321033// fill up laside bytes (from back to front)1034int curBCD=0;1035for (i=length-1; i >= start; i--){1036curBCD = (int) (unscaledValue & 0xF);1037unscaledValue >>>=4;1038str[i] = (char)(curBCD|0x0030);1039}1040}10411042return new String(str, 0, strlen);1043}10441045public int valueOf(BigDecimal res, long value, int scale) {10461047if (DFPUseDFP()) {1048if (value == 0 && scale == 0){1049createZero(res);1050return HARDWARE_OPERATION_SUCCESS;1051}10521053if (value <= 9999999999999999L && value >= -9999999999999999L && -scale>= -398 && -scale<= 369){10541055// NOTE: When we don't specify rounding in DFP, we'll never1056// fail, so don't bother checking the return value1057if (DFPLongExpConstructor(res, value, -scale + 398, 0, 0, 0, false)){1058int tempFlags = getflags(res);1059/* cache: SGP ESRR */10601061// store DFP representation1062// (already 00)10631064// cache the exponent for all DFP paths1065tempFlags|=0x8; //cache on1066setscale(res, scale);10671068// cache the sign for DFP, on all paths1069tempFlags|=0x4; //cache on1070if (value < 0) {1071tempFlags |= 0x60; //isneg1072} else if (value > 0) {1073tempFlags |= 0x20; //ispos1074//iszero is already 001075}1076setflags(res, tempFlags);1077return HARDWARE_OPERATION_SUCCESS;1078}1079}1080}10811082return HARDWARE_OPERATION_FAIL;1083}10841085public int round(BigDecimal res, int precision, int roundingMode) {10861087// Only enter here iff precision > 01088if (res.precision() > precision){ // and only perform if request is shorter then us1089long laside = getlaside(res);1090int flags = getflags(res);1091long bcd = DFPBCDDigits(laside);1092if (bcd == 10) {1093bcd = extractDFPDigitsBCD(laside);1094}10951096if (roundingMode== BigDecimal.ROUND_UNNECESSARY){1097if (!allzeroBCD(bcd, res.precision() - precision)) {1098/*[MSG "K0468", "Rounding mode unnecessary, but rounding changes value"]*/1099throw new ArithmeticException(com.ibm.oti.util.Msg.getString("K0468")); //$NON-NLS-1$1100}1101}11021103//the default DFP rounding mode1104if (roundingMode == BigDecimal.ROUND_HALF_EVEN) {1105roundingMode = BigDecimal.ROUND_UP; //correct DFP HW rounding mode for HALF_EVEN1106} else if (roundingMode == BigDecimal.ROUND_UP) {1107roundingMode = BigDecimal.ROUND_HALF_EVEN; //correct DFP HW rounding mode for HALF_UP1108}1109if(!DFPRound(res, laside, precision, roundingMode)) {1110return HARDWARE_OPERATION_FAIL;1111} else {1112/* cache - SGP ESRR */1113// if successful, update the precision cache...1114flags = getflags(res);1115flags |= 0x10; //cache on1116flags &= 0x7F;1117flags |= precision << 7;11181119//exponent may have changed, but we don't know1120//to what...1121flags &= 0xFFFFFFF7; //clear exponent cache bit1122setflags(res, flags);1123}11241125// if the result is still in DFP and is 0, make1126// sure the sign bit is off...1127laside = getlaside(res);1128if ((flags & 0x3) == 0x0 && isDFPZero(laside)) {1129laside &= 0x7FFFFFFFFFFFFFFFL;1130setlaside(res, laside);1131}1132}11331134return HARDWARE_OPERATION_SUCCESS;1135}11361137public int convertToLongLookaside(BigDecimal res) {11381139long laside = getlaside(res);1140int flags = getflags(res);1141//quick check for 01142if (laside == dfpZERO){11431144// set representation as long lookaside1145flags &= 0xFFFFFFFC; //clear bits1146flags |= 0x00000001;11471148// reset exponent1149setscale(res, 0);1150// set long lookaside1151setlaside(res, 0);11521153// cache the precision of 11154flags &= 0x7F; // clear the cached precision1155flags |= 0x10; //caching the precision1156flags |= 1 << 7; //precision of 11157}1158else{11591160// need to store representation and new long lookaside last1161// since helper functions that are called1162// depend on the correct internal representation flag bit11631164int signum = res.signum();;11651166//store the exponent1167setscale(res, res.scale());11681169//cache the precision1170int prec = res.precision();1171flags &= 0x7F; // clear the cached precision1172flags &= 0xFFFFFFEF;//clear bits1173flags |= 0x10; //cache on1174flags |= prec << 7;11751176long lVal = DFPUnscaledValue(laside);11771178if (lVal == Long.MAX_VALUE){1179lVal = DFPBCDDigits(laside);1180if (lVal == 10) {1181lVal = extractDFPDigitsBCD(laside);1182}1183// now extract each 4 bit BCD digit from left to right1184long val = 0; //to store the result1185int i = 0;1186while (lVal!= 0) {1187val += (lVal & 0xF) * powerOfTenLL(i++);1188lVal >>>= 4;1189}11901191//is the sign negative?1192laside = val * signum;1193} else {1194laside = lVal;1195}11961197// store representation as long lookaside1198flags &= 0xFFFFFFFC;1199flags |= 0x00000001;1200setlaside(res, laside);1201}1202setflags(res, flags);1203// need to make sure bi is not cached by previous calls to unscaled value1204setbi(res, null);12051206return HARDWARE_OPERATION_SUCCESS;1207}12081209public int convertToBigInteger(BigDecimal res) {12101211long laside = getlaside(res);1212int flags = getflags(res);1213//quick check for 01214if (laside == dfpZERO){12151216//store BigInteger representation1217flags &= 0xFFFFFFFC; //clear bits1218flags |= 0x00000002;12191220//clear exponent1221setscale(res, 0);12221223//store BI1224setbi(res, BigInteger.ZERO);12251226// cache the precision of 11227flags&=0x7F; // clear the cached precision1228flags|=0x10; //caching the precision1229flags |= 1 << 7; //precision of 11230} else {12311232// need to store representation last1233// since helper functions that are called1234// depend on the correct internal representation flag bit12351236//store the exponent1237setscale(res, res.scale());12381239//store the BigInteger12401241setbi(res, res.unscaledValue());12421243/* cache - SGP ESRR */12441245//cache the precision1246int prec = res.precision();1247flags &= 0x7F; // clear the cached precision1248flags |= 0x10; //cache on1249flags |= prec << 7;12501251// store representation as BigInteger1252flags &= 0xFFFFFFFC; //clear bits1253flags |= 0x00000002;1254}1255setlaside(res, laside);1256setflags(res, flags);12571258return HARDWARE_OPERATION_SUCCESS;1259}12601261public int convertToExtension(BigDecimal res) {12621263int flags = getflags(res);1264BigInteger bi = getbi(res);1265int scale = getscale(res);1266long laside =getlaside(res);1267// from BI to DFP1268if ((flags & 0x3) == 0x2 &&1269bi.compareTo(MAXDFP64) <= 0 &&1270bi.compareTo(MINDFP64) >=0 &&1271scale > -369 && scale < 398){12721273long lint = bi.longValue();12741275// NOTE: When we don't specify rounding in DFP, we'll never1276// fail, so don't bother checking the return value1277if (DFPLongExpConstructor(res, lint, -scale + 398, 0, 0, 0, false)){12781279/* cache: SGP ESRR */12801281// store DFP representation1282flags &= 0xFFFFFFFC; // clear rep bits1283//sets the bits to (00)12841285// cache the exponent1286flags |= 0x8; //cache on1287//res.exp already stores the value12881289// cache the sign1290flags |= 0x4; //cache on1291flags &= 0xFFFFFF9F; //clear signum1292if (bi.signum() < 0) {1293flags |= 0x60; //isneg1294} else if (bi.signum() > 0) {1295flags |= 0x20; //ispos1296} else {1297flags &= 0xFFFFFF9F;1298}12991300// fix to d1243621301setbi(res, null);1302}1303}13041305// from LL to DFP1306else if ((flags & 0x3) == 0x1 &&1307laside <= 9999999999999999L &&1308laside >= -9999999999999999L &&1309scale > -369 && scale < 398){13101311int signum = res.signum();13121313// NOTE: When we don't specify rounding in DFP, we'll never1314// fail, so don't bother checking the return value1315if (DFPLongExpConstructor(res, laside, -scale + 398, 0, 0, 0, false)){13161317/* cache: SGP ESRR */13181319// store DFP representation1320flags &= 0xFFFFFFFC; // clear rep bits1321//sets the bits to (00)13221323// cache the exponent1324flags |= 0x8; //cache on1325//res.exp already stores the value13261327// cache the sign1328flags |= 0x4; //cache on1329flags &= 0xFFFFFF9F; //clear signum1330if (signum < 0) {1331flags |= 0x60; //isneg1332} else if (signum > 0) {1333flags |= 0x20; //ispos1334} else {1335flags &= 0xFFFFFF9F;1336}1337}1338}13391340setflags(res, flags);13411342return HARDWARE_OPERATION_SUCCESS;1343}13441345public int significance(BigDecimal bd) {13461347int tempFlags = getflags(bd);1348long laside = getlaside(bd);13491350// we're caching it1351tempFlags |= 0x10; // cache on1352tempFlags &= 0x7F; //clear pre-existing bits13531354int sig = DFPSignificance(laside);1355if (sig < 0){1356long digits = DFPBCDDigits(laside);1357if (digits == 10){1358digits = extractDFPDigitsBCD(laside);1359}1360int nlz = Long.numberOfLeadingZeros(digits);1361nlz>>=2;1362nlz=16-nlz;13631364// Preceding algorithm would return 0 for 01365// and we need it to return a precision of 11366if (nlz == 0)1367nlz++;136813691370tempFlags |= nlz << 7;1371setflags(bd, tempFlags);1372return nlz;1373}1374else{1375// DFPSignificance would return 0 for 01376// and we need it to return a precision of 11377if (sig ==0) {1378sig++;1379}1380tempFlags |= sig << 7;1381setflags(bd, tempFlags);1382return sig;1383}1384}13851386public int signum(BigDecimal bd) {13871388int tempFlags = getflags(bd);1389long laside = getlaside(bd);1390// is it cached?1391if ((tempFlags&0x4)!=0) {1392return (((tempFlags & 0x00000060) << 25) >>30);1393}13941395//we're going to cache it1396tempFlags |= 0x4; //cache on13971398//check for negative first1399if ((laside & 0x8000000000000000L) == 0x8000000000000000L){1400tempFlags |= 0x60; //store negative1401setflags(bd, tempFlags);1402return -1;1403}14041405//now we're checking for positive or zero1406long mask = DFPBCDDigits(laside);1407if (mask == 10){1408//still haven't jitted the method1409if (isDFPZero(laside)){1410tempFlags&=0xFFFFFF9F; //clear the signum cache (00)1411setflags(bd, tempFlags);1412return 0;1413} else {1414tempFlags&=0xFFFFFF9F; //clear the signum cache1415tempFlags|=0x20; //store positive1416setflags(bd, tempFlags);1417return 1;1418}1419} else if (mask !=0) {1420tempFlags&=0xFFFFFF9F; //clear the signum cache1421tempFlags|=0x20; //store positive1422setflags(bd, tempFlags);1423return 1;1424} else {1425tempFlags&=0xFFFFFF9F; //clear the signum cache (00)1426}1427setflags(bd, tempFlags);1428return 0;1429}14301431public BigInteger unscaledValue(BigDecimal bd) {1432long laside = getlaside(bd);1433long lVal = DFPUnscaledValue(laside);1434if (lVal != Long.MAX_VALUE) {1435setbi(bd, BigInteger.valueOf(lVal));1436return getbi(bd);1437} else {1438lVal = DFPBCDDigits(laside);1439if (lVal == 10) {1440lVal = extractDFPDigitsBCD(laside);1441}14421443//check for zero1444if (lVal == 0) {1445setbi(bd, BigInteger.ZERO);1446return getbi(bd);1447}14481449// now extract each 4 bit BCD digit from left to right1450long val = 0; //to store the result1451int i = 0;1452while (lVal != 0){1453val += (lVal & 0xF) * powerOfTenLL(i++);1454lVal >>>= 4;1455}1456setbi(bd, BigInteger.valueOf(bd.signum() * val));1457return getbi(bd);1458}1459}14601461public int createZero(BigDecimal res) {1462setlaside(res, dfpZERO);1463setbi(res, null);1464setscale(res, 0);1465int flags = getflags(res);14661467flags|=0x4; //cache on14681469// cache the precision of 11470flags&=0x7F; // clear the cached precision1471flags|=0x10; //caching the precision1472flags |= 1 << 7; //precision of 114731474// cache the exponent (exp already 0)1475flags|=0x8; //cache on1476setflags(res, flags);14771478return HARDWARE_OPERATION_SUCCESS;1479}14801481public int intConstructor(BigDecimal res, int value, MathContext set) {1482// quick path for 0e01483if (value == 0){1484createZero(res);1485return HARDWARE_OPERATION_SUCCESS;1486}14871488// cache the exp for all DFP paths1489// exp remains 01490int flags = getflags(res);1491flags |= 0x8; //cache on14921493// cache the sign for DFP, on all paths1494flags|=0x4; //cache on1495if (value < 0) {1496flags|=0x60; //isneg1497} else if (value > 0) {1498flags|=0x20; //ispos1499}1500//iszero is already 0015011502// we're going to take the full blown path to1503// constructing a DFP internal representation15041505int prec = set.getPrecision();1506int rm = set.getRoundingMode().ordinal();15071508// fast path for MathContext641509if (prec == 16 && rm == BigDecimal.ROUND_HALF_EVEN){1510if (DFPIntConstructor(res, value, 64, 0, 0)){15111512// We assume in the worst case that the precision and1513// exp remain the same since the number of digits1514// is at most 16. If we passed in 999999999999999999be7671515// and rounded to +inf, we'd get overflow, fail and take1516// the slow path anyway.15171518/* cache: SGP ESRR */15191520// cache the precision1521flags |= 0x10;1522flags |= numDigits(value) << 7;15231524// store DFP representation1525// (representation bits already 00)1526setflags(res, flags);1527return HARDWARE_OPERATION_SUCCESS;1528}1529}15301531// fast path for NO ROUNDING, as well as the ArithmeticException1532if ((prec == 0) || (prec > 0 && rm == BigDecimal.ROUND_UNNECESSARY) ||1533(prec > 16)){15341535/* This case catches:1536* -when no rounding is required1537* -if rounding is unnecessary and precision !=0, check1538* to see that result wasn't inexact (via call to Finish)1539* (the latter satisfies the API description of :1540* ArithmeticException - if the result is inexact but1541* the rounding mode is UNNECESSARY.1542*/15431544if (DFPIntConstructor(res, value, 0, 0, 0)){15451546/* cache: SGP ESRR */15471548// store DFP representation1549// (representation bits already 00)15501551// See if we need to throw an arithmetic exception15521553/*[IF]*/1554//TODO: Return a special value in DFP hardware to improve1555// this case1556/*[ENDIF]*/15571558if (prec > 0 && rm == BigDecimal.ROUND_UNNECESSARY) {1559setflags(res, flags);1560if(finish(res, prec, rm) == HARDWARE_OPERATION_FAIL) {1561return HARDWARE_OPERATION_FAIL;1562}1563} else {1564// we can cache the precision and exp1565// since no rounding meant that (no rounding)15661567// cache the precision1568flags |= 0x10; //cache on1569flags |= numDigits(value) << 7;1570setflags(res, flags);15711572}1573return HARDWARE_OPERATION_SUCCESS;1574}1575// Otherwise, if a precision to round to is specified1576} else if (prec <= 16){15771578/* NOTE: We do the following two if statements1579* since the constants used for HALF_EVEN and ROUND_UP in1580* the classlib do not map correctly to the DFP hardware1581* rounding mode bits. All other classlib RoundingModes, however, do.1582*/15831584//the default DFP rounding mode1585if (rm == BigDecimal.ROUND_HALF_EVEN) {1586rm = BigDecimal.ROUND_UP; //correct DFP HW rounding mode for HALF_EVEN1587} else if (rm == BigDecimal.ROUND_UP) {1588rm = BigDecimal.ROUND_HALF_EVEN; //correct DFP HW rounding mode for HALF_UP1589}15901591// now construct in hardware if possible1592if(DFPIntConstructor(res, value, 1, prec, rm)){15931594/* cache: SGP ESRR */15951596// store DFP representation1597// (representation bits already 00)15981599//don't try to cache precision/exp since1600//prec might be different precision(val)16011602//so turn cache of exp off...1603flags &= 0xFFFFFFF7;16041605return HARDWARE_OPERATION_SUCCESS;1606}1607}1608return HARDWARE_OPERATION_FAIL;1609}16101611public int longConstructor(BigDecimal res, long value, int scale, MathContext set) {1612// don't want to send in 0 and then round with hardware1613// cause it might place a crummy exponent value...1614if (value == 0){1615createZero(res);1616return HARDWARE_OPERATION_SUCCESS;1617// otherwise, make sure the long is within 64-bit DFP range1618} else if (value <=9999999999999999L && value >= -9999999999999999L &&1619-scale>=-398 && -scale<369){1620int flags = getflags(res);1621/* cache: SGP ESRR */16221623// cache the sign for DFP, on all paths1624flags|=0x4; //cache on16251626if (value < 0) {1627flags|=0x60; //isneg1628} else if (value > 0) {1629flags|=0x20; //ispos1630}1631//iszero is already 0016321633int prec = set.getPrecision();1634int rm = set.getRoundingMode().ordinal();16351636// fast path for MathContext641637if (prec == 16 && rm == BigDecimal.ROUND_HALF_EVEN){1638if(DFPLongExpConstructor(res, value, -scale + 398, 64, 0, 0, false)){16391640// We assume in the worst case that the precision and1641// exponent remain the same since the number of digits1642// is at most 16. If we passed in 999999999999999999be7671643// and rounded to +inf, we'd get overflow, fail and take1644// the slow path anyway.16451646/* cache: SGP ESRR */16471648// cache the precision1649flags |= 0x10; //cache on1650flags |= numDigits(value) << 7;16511652// cache the exponent1653flags |= 0x8; //cache on16541655setflags(res, flags);1656setscale(res, scale);165716581659//store DFP representation1660// (already set to 00)16611662return HARDWARE_OPERATION_SUCCESS;1663}1664}16651666// fast path for NO ROUNDING, as well as the ArithmeticException1667if ((prec == 0) || (prec > 0 && rm == BigDecimal.ROUND_UNNECESSARY)1668|| (prec > 16)){16691670/* This case catches:1671* -when no rounding is required1672* -if rounding is unnecessary and precision !=0, check1673* to see that result wasn't inexact (via call to Finish)1674* (the latter satisfies the API description of :1675* ArithmeticException - if the result is inexact but1676* the rounding mode is UNNECESSARY.1677*/16781679// NOTE: When we don't specify rounding in DFP, we'll never1680// fail, so don't bother checking the return value1681if (this.DFPLongExpConstructor(res, value, -scale + 398, 0, 0, 0, false)){16821683// store DFP representation1684// (already set to 00)16851686/*[IF]*/1687//TODO: Return a special value in DFP hardware to improve1688// this case1689/*[ENDIF]*/16901691// See if we need to throw an arithmetic exception1692if (prec > 0 && rm == BigDecimal.ROUND_UNNECESSARY) {1693setflags(res, flags);1694if(finish(res, prec, rm) == HARDWARE_OPERATION_FAIL) {1695return HARDWARE_OPERATION_FAIL;1696}1697} else {16981699// cache the exponent1700flags|=0x8; //cache on17011702// cache the precision1703flags |= 0x10; //cache on1704flags |= numDigits(value) << 7;17051706setflags(res, flags);1707setscale(res, scale);1708}1709return HARDWARE_OPERATION_SUCCESS;1710}1711// Otherwise, if a precision to round to is specified1712} else if (prec <=16){17131714/* NOTE: We do the following two if statements1715* since the constants used for HALF_EVEN and ROUND_UP in1716* the classlib do not map correctly to the DFP hardware1717* rounding mode bits. All other classlib RoundingModes, however, do.1718*/17191720//the default DFP rounding mode1721if (rm == BigDecimal.ROUND_HALF_EVEN) {1722rm = BigDecimal.ROUND_UP; //correct DFP HW rounding mode for HALF_EVEN1723} else if (rm == BigDecimal.ROUND_UP) {1724rm = BigDecimal.ROUND_HALF_EVEN; //correct DFP HW rounding mode for HALF_UP1725}17261727// now construct in hardware if possible1728if(DFPLongExpConstructor(res, value, -scale + 398, 1, prec, rm, false)){17291730//store DFP representation1731// (already 00)17321733//don't try to cache precision/exponent since1734//prec might be different precision(val)17351736// so turn caching of exponent off1737setflags(res, flags);17381739return HARDWARE_OPERATION_SUCCESS;1740}1741}1742}17431744return HARDWARE_OPERATION_FAIL;1745}17461747public int longConstructor(BigDecimal res, long value, int scale, int nDigits, int sign, MathContext set) {1748int prec = set.getPrecision();1749int rm = set.getRoundingMode().ordinal();17501751// fast path for 0e01752if (value == 0 && scale == 0){1753createZero(res);1754return HARDWARE_OPERATION_SUCCESS;1755}17561757/* cache - SGP ESRR */17581759int flags = getflags(res);17601761// cache the sign for DFP on all paths..1762flags|=0x4; //cache on1763if (value != 0) { //if not-zero, then we set the val1764flags|=sign;1765}17661767// cache the exponent for DFP on all paths..1768flags |= 0x8; //cache on1769setscale(res, -scale);17701771// fast path for MathContext641772if (prec == 16 && rm == BigDecimal.ROUND_HALF_EVEN){1773if (sign == 0x60){ //isneg1774if (DFPLongExpConstructor(res, value, scale + 398, 64, 0, 0, true)){17751776// store DFP representation1777// (already 00)1778long laside = getlaside(res);1779// since we use unsigned BCDs to get full 16 digits worth1780// lets flip the DFP's sign bit to indicate the fact...1781if (sign == 0x60) { //inseg1782laside |= 0x8000000000000000l;1783}1784setlaside(res, laside);1785/* cache - SGP ESRR */17861787// cache the precision1788flags |= 0x10;1789flags |= nDigits << 7;17901791setflags(res, flags);1792if(finish(res, prec, rm) == HARDWARE_OPERATION_FAIL) {1793return HARDWARE_OPERATION_FAIL;1794}1795return HARDWARE_OPERATION_SUCCESS;1796}1797}1798else{1799if(DFPLongExpConstructor(res, value, scale + 398, 64, 0, 0, true)){18001801// We assume in the worst case that the precision and1802// exponent remain the same since the number of digits1803// is at most 16. If we passed in 999999999999999999be7671804// and rounded to +inf, we'd get overflow, fail and take1805// the slow path anyway.18061807// cache the precision1808flags|=0x10;1809flags |= nDigits << 7;18101811setflags(res, flags);18121813//store DFP representation1814//(already 00)1815return HARDWARE_OPERATION_SUCCESS;1816}1817}1818}18191820// fast path for NO ROUNDING, as well as the ArithmeticException1821if ((prec == 0) || (prec > 0 && rm == BigDecimal.ROUND_UNNECESSARY) ||1822(prec > 16)){18231824/* This case catches:1825* -when no rounding is required1826* -if rounding is unnecessary and precision !=0, check1827* to see that result wasn't inexact (via call to Finish)1828* (the latter satisfies the API description of :1829* ArithmeticException - if the result is inexact but1830* the rounding mode is UNNECESSARY.1831*/1832if (DFPLongExpConstructor(res, value, scale + 398, 0, 0, 0, true)){18331834// store DFP representation1835// (already 00)18361837// since we use unsigned BCDs to get full 16 digits worth1838// lets flip the DFP's sign bit to indicate the fact...1839long laside = getlaside(res);1840if (sign == 0x60) { //isneg1841laside |= 0x8000000000000000l;1842}1843setlaside(res, laside);1844// See if we need to throw an arithmetic exception1845if (prec > 0 && rm == BigDecimal.ROUND_UNNECESSARY){18461847// since we use unsigned BCDs to get full 16 digits worth1848// lets flip the DFP's sign bit to indicate the fact...1849if (sign == 0x60) { //inseg1850laside |= 0x8000000000000000l;1851}1852setlaside(res, laside);1853setflags(res, flags);18541855if(finish(res, prec, rm) == HARDWARE_OPERATION_FAIL) {1856return HARDWARE_OPERATION_FAIL;1857}1858}1859else{1860// we can cache the precision and exponent1861// since no rounding meant that (no rounding)1862// cache the precision1863flags|=0x10;1864flags |= nDigits << 7;1865setflags(res, flags);186618671868}1869return HARDWARE_OPERATION_SUCCESS;1870}1871}18721873// Otherwise, if a precision to round to is specified1874else if (prec <=16){18751876/* NOTE: We do the following two if statements1877* since the constants used for HALF_EVEN and ROUND_UP in1878* the classlib do not map correctly to the DFP hardware1879* rounding mode bits. All other classlib RoundingModes, however, do.1880*/18811882// for negative BCDs1883if (sign == 0x60){1884if (DFPLongExpConstructor(res, value, scale + 398, 0, 0, 0, true)){18851886// store DFP representation1887// (already 00)18881889// since we use unsigned BCDs to get full 16 digits worth1890// lets flip the DFP's sign bit to indicate the fact...1891long laside = getlaside(res);1892laside |= 0x8000000000000000l;1893setlaside(res, laside);18941895/* cache - SGP ESRR */18961897// can't store precision since it's going to be prec,1898// but isn't just yet...1899setflags(res, flags);1900if(finish(res, prec, rm) == HARDWARE_OPERATION_FAIL) {1901return HARDWARE_OPERATION_FAIL;1902}1903return HARDWARE_OPERATION_SUCCESS;1904}1905}1906else{19071908// NOTE: We do the following rm reversal here because1909// doing so in common code above would cause the eventual1910// call to roundDFP to switch them back.19111912// the default DFP rounding mode1913if (rm == BigDecimal.ROUND_HALF_EVEN) {1914rm = BigDecimal.ROUND_UP; //correct DFP HW rounding mode for HALF_EVEN1915} else if (rm == BigDecimal.ROUND_UP) {1916rm = BigDecimal.ROUND_HALF_EVEN; //correct DFP HW rounding mode for HALF_UP1917}1918// for positive BCDs1919if(DFPLongExpConstructor(res, value, scale + 398, 1, prec, rm, true)){19201921//store DFP representation1922//(already 00)19231924//don't try to cache precision/exponent since1925//exp might be diff due to rounding, and precision1926//may be larger than actual19271928/* cache - SGP ESRR */19291930//reset caching of exponent1931flags&=0xFFFFFFF7;1932setflags(res, flags);193319341935return HARDWARE_OPERATION_SUCCESS;1936}1937}1938}1939//at this point, DFP paths were unsuccessful, want to stick with BI1940return HARDWARE_OPERATION_FAIL;1941}19421943public int bigIntegerConstructor(BigDecimal res, BigInteger bi, int scale, MathContext set) {19441945int biPrecision = bi.toString().length() + ((bi.signum() ==-1) ? -1 : 0);19461947if (biPrecision < 17 && -scale <= 369 && -scale >= -398){19481949// get the long value with the appropriate sign1950long val = bi.longValue();19511952// quick path for 0e01953if (val == 0 && scale == 0){1954createZero(res);1955return HARDWARE_OPERATION_SUCCESS;1956}19571958// otherwise, we'll need to perform DFP construction1959// using the correct precision/roundingmodes19601961int prec = set.getPrecision();1962int rm = set.getRoundingMode().ordinal();19631964int flags = getflags(res);1965// fast path for MathContext641966if (prec == 16 && rm == BigDecimal.ROUND_HALF_EVEN){1967if(DFPLongExpConstructor(res, val, -scale + 398, 64, 0, 0, false)){19681969// We assume in the worst case that the precision and1970// exponent remain the same since the number of digits1971// is at most 16. If we passed in 999999999999999999be7671972// and rounded to +inf, we'd get overflow, fail and take1973// the slow path anyway.19741975/* cache - SGP ESRR */19761977// cache the precision1978flags |= 0x10; //cache on1979flags |= numDigits(val) << 7;19801981// cache the sign1982flags|=0x4; //cache on1983flags|= ((bi.signum() <<5) & 0x60);19841985//cache the exponent1986flags|=0x8; //cache on19871988setflags(res, flags);1989setscale(res, scale);19901991// store DFP representation1992// (representation bits already 00)19931994return HARDWARE_OPERATION_SUCCESS;1995}1996}19971998// fast path for NO ROUNDING, as well as the ArithmeticException1999if ((prec == 0) || (prec > 0 && rm == BigDecimal.ROUND_UNNECESSARY)2000|| (prec > 16)){20012002/* This case catches:2003* -when no rounding is required2004* -if rounding is unnecessary and precision !=0, check2005* to see that result wasn't inexact (via call to Finish)2006* (the latter satisfies the API description of :2007* ArithmeticException - if the result is inexact but2008* the rounding mode is UNNECESSARY.2009*/20102011// NOTE: When we don't specify rounding in DFP, we'll never2012// fail, so don't bother checking the return value2013if (DFPLongExpConstructor(res, val, -scale + 398, 0, 0, 0, false)){2014/* cache - SGP ESRR */20152016// cache the sign2017flags |= 0x4; // cache on2018flags |= ((bi.signum() <<5) & 0x60);20192020// store DFP representation2021// (representation bits already 00)20222023// See if we need to throw an arithmetic exception20242025/*[IF]*/2026//TODO: Return a special value in DFP hardware to improve2027// this case2028/*[ENDIF]*/20292030if (prec > 0 && rm == BigDecimal.ROUND_UNNECESSARY) {2031setflags(res, flags);2032if(finish(res, prec, rm) == HARDWARE_OPERATION_FAIL) {2033return HARDWARE_OPERATION_FAIL;2034}2035} else {2036// we can cache the precision and exponent2037// since no rounding left things as is20382039// cache the precision2040flags|=0x10; // cache on2041flags |= numDigits(val) << 7;20422043//cache the exponent2044flags|=0x8; // cache on20452046setflags(res, flags);2047setscale(res, scale);2048}2049return HARDWARE_OPERATION_SUCCESS;2050}2051}20522053// Otherwise, if a precision to round to is specified2054else if (prec <=16){20552056/* NOTE: We do the following two if statements2057* since the constants used for HALF_EVEN and ROUND_UP in2058* the classlib do not map correctly to the DFP hardware2059* rounding mode bits. All other classlib RoundingModes, however, do.2060*/20612062//the default DFP rounding mode2063if (rm == BigDecimal.ROUND_HALF_EVEN) {2064rm = BigDecimal.ROUND_UP; //correct DFP HW rounding mode for HALF_EVEN2065} else if (rm == BigDecimal.ROUND_UP) {2066rm = BigDecimal.ROUND_HALF_EVEN; //correct DFP HW rounding mode for HALF_UP2067}20682069// now construct in hardware if possible2070if(DFPLongExpConstructor(res, val,-scale + 398, 1, prec, rm, false)){20712072/* cache - SGP ESRR */20732074// cache the sign2075flags|=0x4; //cache on2076flags|=((bi.signum() <<5) & 0x60);2077setflags(res, flags);20782079//store DFP representation2080// (representation bits already 00)20812082//don't try to cache precision/exponent since2083//prec might be different after rounding2084return HARDWARE_OPERATION_SUCCESS;2085}2086}2087}2088return HARDWARE_OPERATION_FAIL;2089}209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113// DO NOT MODIFY THIS METHOD2114/* The method is only called once to setup the flag DFP_HW_AVAILABLE2115* Return value2116* true - when JIT compiled this method, replaces it with loadconst 12117* if user -Xnodfp hasn't been supplied2118* false - if still interpreting this method or disabled by VM option2119*/2120private final static boolean DFPCheckHWAvailable() {2121return false;2122}21232124// DO NOT MODIFY THIS METHOD2125/*2126* Return value2127* true - when JIT compiled this method, replaces it with loadconst 12128* if user -Xnodfp hasn't been supplied2129* false - if still interpreting this method or disabled by VM option2130*/2131private final static boolean DFPHWAvailable(){2132return DFP_HW_AVAILABLE;2133}21342135/*2136* Return value2137* true - when JIT compiled this method, replaces it with loadconst 12138* if user -Xjit:disableDFPHys hasn't been supplied2139* false - if still interpreting this method or disabled by JIT option2140*/2141private final static boolean DFPPerformHysteresis(){2142return false;2143}21442145/*2146* Return value2147* true - when JIT compiled this method, replaces it with loadconst 12148* if -Xjit:disableDFPHys has been supplied OR when hys_type becomes true2149* false - when hys_type is false2150*/2151private final static boolean DFPUseDFP(){2152return hys_type;2153}21542155// DO NOT MODIFY THIS METHOD21562157/* NOTE: The fact we return a boolean means we kill a register2158* in the cases we don't want to perform rounding.2159* i.e. rndFlag = 0 or 64 since we must load and2160* return a 1 value in the generated JIT code.2161*/2162private final static boolean DFPIntConstructor(BigDecimal bd, int val, int rndFlag, int prec, int rm){2163return false;2164}21652166// DO NOT MODIFY THIS METHOD2167/*[IF]*/2168//TODO: Use this for the longConstructor when it's called with scale=02169/*[ENDIF]*/2170private final static boolean DFPLongConstructor(BigDecimal bd, long val, int rndFlag, int prec, int rm){2171return false;2172}21732174// DO NOT MODIFY THIS METHOD2175/*2176* Interpreted return value:2177* true - never2178* false - always2179*2180* Jitted return value:2181* true - if rounding succeeded2182* false - if rounding failed2183*2184* Parameters:2185* val - long to be converted to DFP2186* biasedExp - biased exponent to be inserted into DFP2187* rndFlag2188* =0 - no rounding2189* =1 - rounding according to prec, rm2190* =64 - rounding according to MathContext642191* prec - precision to round constructed DFP to2192* rm - rm to use2193* bcd - whether long is in bcd form2194*2195*/2196private final static boolean DFPLongExpConstructor(BigDecimal bd, long val, int biasedExp, int rndFlag, int prec, int rm, boolean bcd){2197return false;2198}21992200// DO NOT MODIFY THIS METHOD2201private final static boolean DFPScaledAdd(BigDecimal bd, long lhsDFP,long rhsDFP,int biasedExp){2202return false;2203}22042205// DO NOT MODIFY THIS METHOD2206/*2207* Parameters:2208* rndFlag2209* =0 - no rounding2210* =1 - rounding according to prec, rm2211* =64 - rounding according to MathContext642212*/2213private final static boolean DFPAdd(BigDecimal bd, long lhsDFP,long rhsDFP, int rndFlag, int precision, int rm){2214return false;2215}22162217// DO NOT MODIFY THIS METHOD2218private final static boolean DFPScaledSubtract(BigDecimal bd, long lhsDFP,long rhsDFP,int biasedExp){2219return false;2220}22212222// DO NOT MODIFY THIS METHOD2223/*2224* Parameters:2225* rndFlag2226* =0 - no rounding2227* =1 - rounding according to prec, rm2228* =64 - rounding according to MathContext642229*/2230private final static boolean DFPSubtract(BigDecimal res, long lhsDFP, long rhsDFP, int rndFlag, int precision, int rm){2231return false;2232}22332234// DO NOT MODIFY THIS METHOD2235private final static boolean DFPScaledMultiply(BigDecimal res, long lhsDFP,long rhsDFP,int biasedExp){2236return false;2237}22382239// DO NOT MODIFY THIS METHOD2240/*2241* Parameters:2242* rndFlag2243* =0 - no rounding2244* =1 - rounding according to prec, rm2245* =64 - rounding according to MathContext642246*/2247private final static boolean DFPMultiply(BigDecimal res, long lhsDFP, long rhsDFP, int rndFlag, int precision, int rm){2248return false;2249}22502251// DO NOT MODIFY THIS METHOD2252/*2253* Interpreted return value:2254* Returns -1 if not JIT compiled.2255*2256* JIT compiled return value:2257* 0 - ok, but inexact exception --> check UNNECESSARY2258* 1 - ok, no inexact2259* -1 - not ok --> try slow path2260*2261* rndFlag2262* =0 - rounding according to MathContext642263* =1 - rounding according to prec, rm2264*/2265private final static int DFPScaledDivide(BigDecimal res, long lhsDFP, long rhsDFP, int scale, int rndFlg, int rm){2266return -1;2267}22682269// DO NOT MODIFY THIS METHOD2270/*2271* Interpreted return value:2272* -1 = always2273*2274* JIT compiled return value:2275* Return 1 if JIT compiled and DFP divide is successful.2276* Return 0 if JIT compiled, but DFP divide was inexact2277* Return -1 if JIT compiled, but other exception (i.e. overflow)2278*2279* rndFlag2280* =0 - no rounding2281* =1 - rounding according to prec, rm2282* =64 - rounding according to MathContext642283*/2284private final static int DFPDivide(BigDecimal bd, long lhsDFP, long rhsDFP, boolean checkForInexact, int rndFlag, int prec, int rm){2285return -1; //return an invalid result2286}22872288// DO NOT MODIFY THIS METHOD2289private final static boolean DFPRound(BigDecimal bd, long dfpSrc, int precision, int rm){2290return false;2291}22922293// DO NOT MODIFY THIS METHOD2294private final static int DFPCompareTo(long lhsDFP, long rhsDFP){2295return -2; //return an invalid result2296}22972298// DO NOT MODIFY THIS METHOD2299private final static long DFPBCDDigits(long dfp){2300return 10; //since each digit in a BCD is from 0 to 92301}23022303// DO NOT MODIFY THIS METHOD2304private final static int DFPSignificance(long dfp){2305return -1; //illegal significance2306}23072308// DO NOT MODIFY THIS METHOD2309private final static int DFPExponent(long dfp){2310return 1000; //return a value out of the range of Double DFP2311}23122313// DO NOT MODIFY THIS METHOD2314/*2315* Interpreted return value:2316* -1 = always2317*2318* JIT compiled return value:2319* Return 1 if passed2320* Return 0 if JIT compiled, but inexact result2321* Return -1 if JIT compiled, but other failure2322*2323*/2324private final static int DFPSetScale(BigDecimal bd, long srcDFP, int biasedExp, boolean round, int rm, boolean checkInexact){2325return -1;2326}23272328// DO NOT MODIFY THIS METHOD2329private final static long DFPUnscaledValue(long srcDFP){2330return Long.MAX_VALUE;2331}2332233323342335233623372338233923402341234223432344234523462347234823492350235123522353private static final ThreadLocal thLocalToString = new ThreadLocal(){2354/* 22 is the best number for the fastest path2355* [-]digits.digits when scale > 0 & scale <=192356*/23572358protected synchronized Object initialValue() {2359return new char[22];2360}2361};23622363private final static byte [] comboinit(){2364final byte comboCode[]={23650, 4, 8, 12, 16, 20, 24, 28,23661, 5, 9, 13, 17, 21, 25, 29,23672, 6, 10, 14, 18, 22, 26, 30,236832, 36, 33, 37, 34, 382369};2370return comboCode;2371}23722373private final static short [] dpd2bcdinit(){2374final short[] dpd2bcd = {23750, 1, 2, 3, 4, 5, 6, 7,23768, 9, 128, 129, 2048, 2049, 2176, 2177, 16, 17, 18, 19, 20,237721, 22, 23, 24, 25, 144, 145, 2064, 2065, 2192, 2193, 32, 33,237834, 35, 36, 37, 38, 39, 40, 41, 130, 131, 2080, 2081, 2056,23792057, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 146, 147,23802096, 2097, 2072, 2073, 64, 65, 66, 67, 68, 69, 70, 71, 72,238173, 132, 133, 2112, 2113, 136, 137, 80, 81, 82, 83, 84, 85,238286, 87, 88, 89, 148, 149, 2128, 2129, 152, 153, 96, 97, 98,238399, 100, 101, 102, 103, 104, 105, 134, 135, 2144, 2145, 2184, 2185,2384112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 150, 151, 2160,23852161, 2200, 2201, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265,2386384, 385, 2304, 2305, 2432, 2433, 272, 273, 274, 275, 276, 277, 278,2387279, 280, 281, 400, 401, 2320, 2321, 2448, 2449, 288, 289, 290, 291,2388292, 293, 294, 295, 296, 297, 386, 387, 2336, 2337, 2312, 2313, 304,2389305, 306, 307, 308, 309, 310, 311, 312, 313, 402, 403, 2352, 2353,23902328, 2329, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 388,2391389, 2368, 2369, 392, 393, 336, 337, 338, 339, 340, 341, 342, 343,2392344, 345, 404, 405, 2384, 2385, 408, 409, 352, 353, 354, 355, 356,2393357, 358, 359, 360, 361, 390, 391, 2400, 2401, 2440, 2441, 368, 369,2394370, 371, 372, 373, 374, 375, 376, 377, 406, 407, 2416, 2417, 2456,23952457, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 640, 641,23962050, 2051, 2178, 2179, 528, 529, 530, 531, 532, 533, 534, 535, 536,2397537, 656, 657, 2066, 2067, 2194, 2195, 544, 545, 546, 547, 548, 549,2398550, 551, 552, 553, 642, 643, 2082, 2083, 2088, 2089, 560, 561, 562,2399563, 564, 565, 566, 567, 568, 569, 658, 659, 2098, 2099, 2104, 2105,2400576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 644, 645, 2114,24012115, 648, 649, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601,2402660, 661, 2130, 2131, 664, 665, 608, 609, 610, 611, 612, 613, 614,2403615, 616, 617, 646, 647, 2146, 2147, 2184, 2185, 624, 625, 626, 627,2404628, 629, 630, 631, 632, 633, 662, 663, 2162, 2163, 2200, 2201, 768,2405769, 770, 771, 772, 773, 774, 775, 776, 777, 896, 897, 2306, 2307,24062434, 2435, 784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 912,2407913, 2322, 2323, 2450, 2451, 800, 801, 802, 803, 804, 805, 806, 807,2408808, 809, 898, 899, 2338, 2339, 2344, 2345, 816, 817, 818, 819, 820,2409821, 822, 823, 824, 825, 914, 915, 2354, 2355, 2360, 2361, 832, 833,2410834, 835, 836, 837, 838, 839, 840, 841, 900, 901, 2370, 2371, 904,2411905, 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 916, 917,24122386, 2387, 920, 921, 864, 865, 866, 867, 868, 869, 870, 871, 872,2413873, 902, 903, 2402, 2403, 2440, 2441, 880, 881, 882, 883, 884, 885,2414886, 887, 888, 889, 918, 919, 2418, 2419, 2456, 2457, 1024, 1025, 1026,24151027, 1028, 1029, 1030, 1031, 1032, 1033, 1152, 1153, 2052, 2053, 2180, 2181,24161040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1168, 1169, 2068,24172069, 2196, 2197, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065,24181154, 1155, 2084, 2085, 2120, 2121, 1072, 1073, 1074, 1075, 1076, 1077, 1078,24191079, 1080, 1081, 1170, 1171, 2100, 2101, 2136, 2137, 1088, 1089, 1090, 1091,24201092, 1093, 1094, 1095, 1096, 1097, 1156, 1157, 2116, 2117, 1160, 1161, 1104,24211105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1172, 1173, 2132, 2133,24221176, 1177, 1120, 1121, 1122, 1123, 1124, 1125, 1126, 1127, 1128, 1129, 1158,24231159, 2148, 2149, 2184, 2185, 1136, 1137, 1138, 1139, 1140, 1141, 1142, 1143,24241144, 1145, 1174, 1175, 2164, 2165, 2200, 2201, 1280, 1281, 1282, 1283, 1284,24251285, 1286, 1287, 1288, 1289, 1408, 1409, 2308, 2309, 2436, 2437, 1296, 1297,24261298, 1299, 1300, 1301, 1302, 1303, 1304, 1305, 1424, 1425, 2324, 2325, 2452,24272453, 1312, 1313, 1314, 1315, 1316, 1317, 1318, 1319, 1320, 1321, 1410, 1411,24282340, 2341, 2376, 2377, 1328, 1329, 1330, 1331, 1332, 1333, 1334, 1335, 1336,24291337, 1426, 1427, 2356, 2357, 2392, 2393, 1344, 1345, 1346, 1347, 1348, 1349,24301350, 1351, 1352, 1353, 1412, 1413, 2372, 2373, 1416, 1417, 1360, 1361, 1362,24311363, 1364, 1365, 1366, 1367, 1368, 1369, 1428, 1429, 2388, 2389, 1432, 1433,24321376, 1377, 1378, 1379, 1380, 1381, 1382, 1383, 1384, 1385, 1414, 1415, 2404,24332405, 2440, 2441, 1392, 1393, 1394, 1395, 1396, 1397, 1398, 1399, 1400, 1401,24341430, 1431, 2420, 2421, 2456, 2457, 1536, 1537, 1538, 1539, 1540, 1541, 1542,24351543, 1544, 1545, 1664, 1665, 2054, 2055, 2182, 2183, 1552, 1553, 1554, 1555,24361556, 1557, 1558, 1559, 1560, 1561, 1680, 1681, 2070, 2071, 2198, 2199, 1568,24371569, 1570, 1571, 1572, 1573, 1574, 1575, 1576, 1577, 1666, 1667, 2086, 2087,24382152, 2153, 1584, 1585, 1586, 1587, 1588, 1589, 1590, 1591, 1592, 1593, 1682,24391683, 2102, 2103, 2168, 2169, 1600, 1601, 1602, 1603, 1604, 1605, 1606, 1607,24401608, 1609, 1668, 1669, 2118, 2119, 1672, 1673, 1616, 1617, 1618, 1619, 1620,24411621, 1622, 1623, 1624, 1625, 1684, 1685, 2134, 2135, 1688, 1689, 1632, 1633,24421634, 1635, 1636, 1637, 1638, 1639, 1640, 1641, 1670, 1671, 2150, 2151, 2184,24432185, 1648, 1649, 1650, 1651, 1652, 1653, 1654, 1655, 1656, 1657, 1686, 1687,24442166, 2167, 2200, 2201, 1792, 1793, 1794, 1795, 1796, 1797, 1798, 1799, 1800,24451801, 1920, 1921, 2310, 2311, 2438, 2439, 1808, 1809, 1810, 1811, 1812, 1813,24461814, 1815, 1816, 1817, 1936, 1937, 2326, 2327, 2454, 2455, 1824, 1825, 1826,24471827, 1828, 1829, 1830, 1831, 1832, 1833, 1922, 1923, 2342, 2343, 2408, 2409,24481840, 1841, 1842, 1843, 1844, 1845, 1846, 1847, 1848, 1849, 1938, 1939, 2358,24492359, 2424, 2425, 1856, 1857, 1858, 1859, 1860, 1861, 1862, 1863, 1864, 1865,24501924, 1925, 2374, 2375, 1928, 1929, 1872, 1873, 1874, 1875, 1876, 1877, 1878,24511879, 1880, 1881, 1940, 1941, 2390, 2391, 1944, 1945, 1888, 1889, 1890, 1891,24521892, 1893, 1894, 1895, 1896, 1897, 1926, 1927, 2406, 2407, 2440, 2441, 1904,24531905, 1906, 1907, 1908, 1909, 1910, 1911, 1912, 1913, 1942, 1943, 2422, 2423,24542456, 2457};2455return dpd2bcd;2456}24572458/**2459* LUT for powers of ten2460*/2461private static final long [/*19*/]powersOfTenLL={24621L, 10L, 100L, 1000L, /*0 to 4 */246310000L, 100000L, 1000000L, 10000000L, /*5 to 8*/2464100000000L, 1000000000L, 10000000000L, 100000000000L, /*9 to 12*/24651000000000000L, 10000000000000L, 100000000000000L, 1000000000000000L, /*13 to 16 */246610000000000000000L, 100000000000000000L, 1000000000000000000L /*17 to 18 */2467};24682469private final static boolean isDFPZero(long laside){2470// quick check for 02471if (laside == dfpZERO) {2472return true;2473}2474// if DPF is ZERO, then the combo field will be XX000 where XX is I don't care2475// values, and then coefficient continuation field will be all 0s2476return ((laside & 0x0003FFFFFFFFFFFFL) == 0 && ((laside >>> 58) & 0x7) == 0);2477}24782479private final void clone(BigDecimal src, BigDecimal tar) {2480int tempFlags = getflags(src);2481setflags(tar, tempFlags);2482setlaside(tar, getlaside(src));2483setscale(tar, getscale(src));2484if ((tempFlags & 0x3) == 0x2) {2485setbi(tar, getbi(src));2486}2487}24882489private final int finish(BigDecimal bd, int prec, int rm){2490if (prec > 0 && bd.precision() > prec) {2491if ((getflags(bd) & 0x3) == 0x0) {2492return round(bd, prec, rm);2493} else {2494MathContext mc = new MathContext(prec, RoundingMode.valueOf(rm));2495clone(bd.round(mc), bd);2496}2497}2498return HARDWARE_OPERATION_SUCCESS;2499}25002501protected final static int getflags(BigDecimal bd) {2502throw new RuntimeException("getflags not compiled\n"); //$NON-NLS-1$2503}25042505protected final static long getlaside(BigDecimal bd) {2506throw new RuntimeException("getlaside not compiled\n"); //$NON-NLS-1$2507}25082509protected final static int getscale(BigDecimal bd) {2510throw new RuntimeException("getscale not compiled\n"); //$NON-NLS-1$2511}25122513protected final static BigInteger getbi(BigDecimal bd) {2514throw new RuntimeException("getbi not compiled\n"); //$NON-NLS-1$2515}25162517protected final static void setflags(BigDecimal bd, int flags) {2518throw new RuntimeException("setflags not compiled\n"); //$NON-NLS-1$2519}25202521protected final static void setlaside(BigDecimal bd, long laside) {2522throw new RuntimeException("setlaside not compiled\n"); //$NON-NLS-1$2523}25242525protected final static void setscale(BigDecimal bd, int scale) {2526throw new RuntimeException("setscale not compiled\n"); //$NON-NLS-1$2527}25282529protected final static void setbi(BigDecimal bd, BigInteger bi) {2530throw new RuntimeException("setbi not compiled\n"); //$NON-NLS-1$2531}25322533private final static long extractDFPDigitsBCD(long dfpNum){25342535int combo=0; // 5 bit combo field25362537//quick check for 02538if (dfpNum == dfpZERO)2539return 0;25402541// store the combo field bits2542combo = (int)(dfpNum >>> 58); //shift out extraneous bits2543combo &= 0x1F; //and out sign bit25442545// MANTISSA25462547// store the mantissa continuation field bits 14 to 62 (50 bits in total)2548long ccf = dfpNum & 0x0003FFFFFFFFFFFFL;25492550// Convert each set of 10 DPD bits from continuation bits to 12 BCD digits2551long ccBCD=0;2552long bcd=0;2553for (int i=0; i <5; i++){ //5 groups of 10 bits2554bcd = DPD2BCD[(int)((ccf & 0x3FF0000000000L)>>>40)];2555ccBCD <<=12;2556ccBCD|=bcd;2557ccf <<= 10; //shift out top 10 bits2558}25592560//ccBCD contains 15 BCD digits, now need to prepend the first one2561ccBCD|=(((long)(doubleDFPComboField[combo]>>>2))<<60);2562return ccBCD;2563}256425652566private final static boolean allzeroBCD(long num, int numDigsToCheck){25672568// isolate numDigsToCheck rightmost digits...2569long mask = 0xFFFFFFFFFFFFFFFFL;2570mask >>>= (64-numDigsToCheck)*4;2571return ((mask & num) == 0);2572}25732574private final static int extractDFPExponent(long dfpNum){25752576byte combo=0; // 5 bit combo field25772578// store the combo field bits2579combo = (byte)(dfpNum >>> 58); //shift out extraneous bits2580//combo &= 0x1F; //and out sign bit - not sure why I was doing this25812582// store the biased exponent field bits 6 to 132583short bxf = (short)(dfpNum >>> 50); //shift out extraneous bits2584bxf &= 0x00FF; //and out sign and combo field25852586// parse the combo field2587byte exp2Digits = (byte)(doubleDFPComboField[combo] & 0x03);25882589// unbias the exponent2590short unbExp = (short)(exp2Digits);2591unbExp <<= 8;2592unbExp|=bxf;2593return unbExp;2594}25952596private static final long powerOfTenLL(long i){2597if (i > -1 && i <= 18)2598return powersOfTenLL[(int)i];2599else2600return -1;2601}26022603/* Return number of digits in lon2604* The value '0' has numDigits = 1.2605*/2606private final static int numDigits(long lon){2607//if (lon <0) lon*=-1; //need to make it positive for this to work2608lon = Math.abs(lon);26092610//hardcode powers of ten to avoid LUT lookups26112612//rhs of the tree2613if (lon < 1000000000L /*powerOfTenLL[9]*/){2614if (lon < 100000000L /*powerOfTenLL[8]*/){2615if (lon < 10000L /*powerOfTenLL[4]*/){2616if (lon < 100L /* powerOfTenLL[2]*/){2617if (lon < 10L /*powerOfTenLL[1]*/)2618return 1;2619else2620return 2;2621}2622else if (lon < 1000L /*powerOfTenLL[3]*/)2623return 3;2624else2625return 4;2626}2627else if (lon < 1000000L /*powerOfTenLL[6]*/){2628if ( lon < 100000L /*powerOfTenLL[5]*/)2629return 5;2630else2631return 6;2632}2633else if (lon < 10000000L /*powerOfTenLL[7]*/)2634return 7;2635else return 8;2636}2637else2638return 9;2639}2640//lhs of the tree2641else{2642if (lon < 10000000000L /*powerOfTenLL[10]*/)2643return 10;2644else if (lon < 100000000000000L /*powerOfTenLL[14]*/){2645if (lon < 1000000000000L /*powerOfTenLL[12]*/){2646if (lon < 100000000000L /*powerOfTenLL[11]*/)2647return 11;2648else2649return 12;2650}2651else if (lon < 10000000000000L /*powerOfTenLL[13]*/)2652return 13;2653else2654return 14;2655}2656else if (lon < 10000000000000000L /*powerOfTenLL[16]*/){2657if (lon < 1000000000000000L /*powerOfTenLL[15]*/)2658return 15;2659else2660return 16;2661}2662else if (lon < 100000000000000000L /*powerOfTenLL[17]*/)2663return 17;2664else if (lon < 1000000000000000000L /*powerOfTenLL[18]*/)2665return 18;2666return 19;2667}2668}26692670private final static int digitAtBCD(long bcd, int numDigits, int indexFromLeft){26712672int indexFromRight = numDigits-indexFromLeft-1;2673switch (indexFromRight){2674case 0:2675return (int)(bcd & 0x000000000000000FL);2676case 1:2677return (int)((bcd & 0x00000000000000F0L)>>>4);2678case 2:2679return (int)((bcd & 0x0000000000000F00L)>>>8);2680case 3:2681return (int)((bcd & 0x000000000000F000L)>>>12);2682case 4:2683return (int)((bcd & 0x00000000000F0000L)>>>16);2684case 5:2685return (int)((bcd & 0x0000000000F00000L)>>>20);2686case 6:2687return (int)((bcd & 0x000000000F000000L)>>>24);2688case 7:2689return (int)((bcd & 0x00000000F0000000L)>>>28);2690case 8:2691return (int)((bcd & 0xF00000000L)>>>32);2692case 9:2693return (int)((bcd & 0xF000000000L)>>>36);2694case 10:2695return (int)((bcd & 0xF0000000000L)>>>40);2696case 11:2697return (int)((bcd & 0xF00000000000L)>>44);2698case 12:2699return (int)((bcd & 0xF000000000000L)>>>48);2700case 13:2701return (int)((bcd & 0xF0000000000000L)>>>52);2702case 14:2703return (int)((bcd & 0xF00000000000000L)>>>56);2704case 15:2705return (int)((bcd & 0xF000000000000000L)>>>60);2706default:2707return 0;2708}2709}27102711private final static int digitAt(long lon, int numdigits, int loc){27122713lon = Math.abs(lon);2714if (loc > numdigits-1)return -1;2715if (loc < 0) return -1;2716int indexFromRight = numdigits-loc-1;2717if (lon <= Integer.MAX_VALUE){2718int temp=(int)lon;2719switch (indexFromRight){2720case 0:2721break;2722case 1:2723temp /=10;2724break;2725case 2:2726temp /=100;2727break;2728case 3:2729temp /=1000;2730break;2731case 4:2732temp /=10000;2733break;2734case 5:2735temp /=100000;2736break;2737case 6:2738temp /=1000000;2739break;2740case 7:2741temp /=10000000;2742break;2743case 8:2744temp /=100000000;2745break;2746case 9:2747temp /=1000000000; //unsure whether remaining cases would2748break; //ever be taken in the Integer case2749case 10:2750temp /=10000000000L;2751break;2752case 11:2753temp /=100000000000L;2754break;2755case 12:2756temp /=1000000000000L;2757break;2758case 13:2759temp /=10000000000000L;2760break;2761case 14:2762temp /=100000000000000L;2763break;2764case 15:2765temp /=1000000000000000L;2766break;2767case 16:2768temp /=10000000000000000L;2769break;2770case 17:2771temp /=100000000000000000L;2772break;2773case 18:2774temp /=1000000000000000000L;2775break;2776}27772778// find remainder2779if (temp <= Integer.MAX_VALUE){2780int intTmp = (int)temp;2781int tmpVal = intTmp;2782intTmp = uDivideByTen(intTmp);2783return (tmpVal - ((intTmp << 3) + (intTmp << 1)));2784}2785else{2786long tmpVal = temp;2787temp/=10;2788return (int)(tmpVal - (((temp << 3) + (temp << 1))));2789}2790}2791else{2792long temp=lon;2793switch (indexFromRight){2794case 0:2795break;2796case 1:2797temp /= 10;2798break;2799case 2:2800temp /= 100;2801break;2802case 3:2803temp /= 1000;2804break;2805case 4:2806temp /= 10000;2807break;2808case 5:2809temp /= 100000;2810break;2811case 6:2812temp /= 1000000;2813break;2814case 7:2815temp /= 10000000;2816break;2817case 8:2818temp /= 100000000;2819break;2820case 9:2821temp /= 1000000000;2822break;2823case 10:2824temp /= 10000000000L;2825break;2826case 11:2827temp /= 100000000000L;2828break;2829case 12:2830temp /= 1000000000000L;2831break;2832case 13:2833temp /= 10000000000000L;2834break;2835case 14:2836temp /= 100000000000000L;2837break;2838case 15:2839temp /= 1000000000000000L;2840break;2841case 16:2842temp /= 10000000000000000L;2843break;2844case 17:2845temp /= 100000000000000000L;2846break;2847case 18:2848temp /= 1000000000000000000L;2849break;2850}28512852// find remainder2853if (temp <= Integer.MAX_VALUE){2854int intTmp = (int)temp;2855int tmpVal = intTmp;2856intTmp = uDivideByTen(intTmp);2857return (tmpVal - ((intTmp << 3) + (intTmp << 1)));2858}2859else{2860long tmpVal = temp;2861temp/=10;2862return (int)(tmpVal - (((temp << 3) + (temp << 1))));2863}2864}2865}28662867private final static int uDivideByTen(int x){2868int q = (x >> 1) + (x >> 2);2869q = q + (q >> 4);2870q = q + (q >> 8);2871q = q + (q >> 16);2872q >>=3;2873x -= q*10;2874return q + ((x + 6) >> 4);2875}28762877private final void badDivideByZero() {2878/*[MSG "K0407", "division by zero"]*/2879throw new ArithmeticException(com.ibm.oti.util.Msg.getString("K0407")); //$NON-NLS-1$2880}2881private final void conversionOverflow(BigDecimal bd) {2882/*[MSG "K0458", "Conversion overflow: {0}"]*/2883throw new ArithmeticException(com.ibm.oti.util.Msg.getString("K0458", bd)); //$NON-NLS-1$2884}2885private final void nonZeroDecimals(BigDecimal bd) {2886/*[MSG "K0457", "Non-zero decimal digits: {0}"]*/2887throw new ArithmeticException(com.ibm.oti.util.Msg.getString("K0457", bd)); //$NON-NLS-1$2888}2889private final void scaleOutOfRange(long s) {2890/*[MSG "K0451", "BigDecimal scale outside legal range: {0}"]*/2891throw new ArithmeticException(com.ibm.oti.util.Msg.getString("K0451", Long.toString(s))); //$NON-NLS-1$2892}2893private static final void scaleOverflow() {2894/*[MSG "K0453", "Scale overflow"]*/2895throw new ArithmeticException(com.ibm.oti.util.Msg.getString("K0453")); //$NON-NLS-1$2896}2897}28982899/*[ENDIF] #INCLUDE */2900/*[REM] do not remove following blank line*/2901290229032904