Parent Directory | Revision Log | Patch
--- incubator/derby/code/trunk/java/client/org/apache/derby/client/am/Decimal.java 2005/05/02 05:18:08 165584 +++ incubator/derby/code/trunk/java/client/org/apache/derby/client/am/Decimal.java 2005/05/02 06:25:59 165585 @@ -20,470 +20,457 @@ package org.apache.derby.client.am; /** - * Converters from fixed point decimal bytes to <code>java.math.BigDecimal</code>, - * <code>double</code>, or <code>long</code>. + * Converters from fixed point decimal bytes to <code>java.math.BigDecimal</code>, <code>double</code>, or + * <code>long</code>. */ -public class Decimal -{ - /** - * Packed Decimal representation - */ - public final static int PACKED_DECIMAL = 0x30; - - //--------------------------private constants--------------------------------- - - private static final int[][] tenRadixMagnitude = { - { 0x3b9aca00 }, // 10^9 - { 0x0de0b6b3, 0xa7640000 }, // 10^18 - { 0x033b2e3c, 0x9fd0803c, 0xe8000000 }, // 10^27 - }; - - //--------------------------constructors-------------------------------------- - - // Hide the default constructor, this is a static class. - private Decimal() {} - - //--------------------------private helper methods---------------------------- - - /** - * Convert a range of packed nybbles (up to 9 digits without overflow) to an int. - * Note that for performance purpose, it does not do array-out-of-bound checking. - */ - private static final int packedNybblesToInt (byte[] buffer, - int offset, - int startNybble, - int numberOfNybbles) - { - int value = 0; - - int i = startNybble / 2; - if ((startNybble % 2) != 0) { - // process low nybble of the first byte if necessary. - value += buffer[offset+i] & 0x0F; - i++; - } +public class Decimal { + /** + * Packed Decimal representation + */ + public final static int PACKED_DECIMAL = 0x30; + + //--------------------------private constants--------------------------------- + + private static final int[][] tenRadixMagnitude = { + {0x3b9aca00}, // 10^9 + {0x0de0b6b3, 0xa7640000}, // 10^18 + {0x033b2e3c, 0x9fd0803c, 0xe8000000}, // 10^27 + }; + + //--------------------------constructors-------------------------------------- + + // Hide the default constructor, this is a static class. + private Decimal() { + } + + //--------------------------private helper methods---------------------------- + + /** + * Convert a range of packed nybbles (up to 9 digits without overflow) to an int. Note that for performance purpose, + * it does not do array-out-of-bound checking. + */ + private static final int packedNybblesToInt(byte[] buffer, + int offset, + int startNybble, + int numberOfNybbles) { + int value = 0; + + int i = startNybble / 2; + if ((startNybble % 2) != 0) { + // process low nybble of the first byte if necessary. + value += buffer[offset + i] & 0x0F; + i++; + } - int endNybble = startNybble + numberOfNybbles -1; - for (; i<(endNybble+1)/2; i++) { - value = value*10 + ((buffer[offset+i] & 0xF0) >>> 4); // high nybble. - value = value*10 + (buffer[offset+i] & 0x0F); // low nybble. - } + int endNybble = startNybble + numberOfNybbles - 1; + for (; i < (endNybble + 1) / 2; i++) { + value = value * 10 + ((buffer[offset + i] & 0xF0) >>> 4); // high nybble. + value = value * 10 + (buffer[offset + i] & 0x0F); // low nybble. + } - if ((endNybble % 2) == 0) { - // process high nybble of the last byte if necessary. - value = value*10 + ((buffer[offset+i] & 0xF0) >>> 4); + if ((endNybble % 2) == 0) { + // process high nybble of the last byte if necessary. + value = value * 10 + ((buffer[offset + i] & 0xF0) >>> 4); + } + + return value; } - return value; - } + /** + * Convert a range of packed nybbles (up to 18 digits without overflow) to a long. Note that for performance + * purpose, it does not do array-out-of-bound checking. + */ + private static final long packedNybblesToLong(byte[] buffer, + int offset, + int startNybble, + int numberOfNybbles) { + long value = 0; + + int i = startNybble / 2; + if ((startNybble % 2) != 0) { + // process low nybble of the first byte if necessary. + value += buffer[offset + i] & 0x0F; + i++; + } - /** - * Convert a range of packed nybbles (up to 18 digits without overflow) to a long. - * Note that for performance purpose, it does not do array-out-of-bound checking. - */ - private static final long packedNybblesToLong (byte[] buffer, - int offset, - int startNybble, - int numberOfNybbles) - { - long value = 0; - - int i = startNybble / 2; - if ((startNybble % 2) != 0) { - // process low nybble of the first byte if necessary. - value += buffer[offset+i] & 0x0F; - i++; - } + int endNybble = startNybble + numberOfNybbles - 1; + for (; i < (endNybble + 1) / 2; i++) { + value = value * 10 + ((buffer[offset + i] & 0xF0) >>> 4); // high nybble. + value = value * 10 + (buffer[offset + i] & 0x0F); // low nybble. + } + + if ((endNybble % 2) == 0) { + // process high nybble of the last byte if necessary. + value = value * 10 + ((buffer[offset + i] & 0xF0) >>> 4); + } - int endNybble = startNybble + numberOfNybbles -1; - for (; i<(endNybble+1)/2; i++) { - value = value*10 + ((buffer[offset+i] & 0xF0) >>> 4); // high nybble. - value = value*10 + (buffer[offset+i] & 0x0F); // low nybble. + return value; } - if ((endNybble % 2) == 0) { - // process high nybble of the last byte if necessary. - value = value*10 + ((buffer[offset+i] & 0xF0) >>> 4); + /** + * Compute the int array of magnitude from input value segments. + */ + private static final int[] computeMagnitude(int[] input) { + int length = input.length; + int[] mag = new int[length]; + + mag[length - 1] = input[length - 1]; + for (int i = 0; i < length - 1; i++) { + int carry = 0; + int j = tenRadixMagnitude[i].length - 1; + int k = length - 1; + for (; j >= 0; j--, k--) { + long product = (input[length - 2 - i] & 0xFFFFFFFFL) * (tenRadixMagnitude[i][j] & 0xFFFFFFFFL) + + (mag[k] & 0xFFFFFFFFL) // add previous value + + (carry & 0xFFFFFFFFL); // add carry + carry = (int) (product >>> 32); + mag[k] = (int) (product & 0xFFFFFFFFL); + } + mag[k] = (int) carry; + } + return mag; } - return value; - } + //--------------entry points for runtime representation----------------------- - /** - * Compute the int array of magnitude from input value segments. - */ - private static final int[] computeMagnitude(int[] input) - { - int length = input.length; - int[] mag = new int[length]; - - mag[length-1] = input[length-1]; - for (int i=0; i<length-1; i++) { - int carry = 0; - int j = tenRadixMagnitude[i].length-1; - int k = length-1; - for (; j>=0; j--, k--) { - long product = (input[length-2-i] & 0xFFFFFFFFL) * (tenRadixMagnitude[i][j] & 0xFFFFFFFFL) - + (mag[k] & 0xFFFFFFFFL) // add previous value - + (carry & 0xFFFFFFFFL); // add carry - carry = (int) (product >>> 32); - mag[k] = (int) (product & 0xFFFFFFFFL); - } - mag[k] = (int) carry; - } - return mag; - } - - //--------------entry points for runtime representation----------------------- - - /** - * Build a <code>java.math.BigDecimal</code> from a fixed point decimal byte representation. - * - * @exception IllegalArgumentException if the specified representation is not recognized. - */ - public static final java.math.BigDecimal getBigDecimal (byte[] buffer, - int offset, - int precision, - int scale - ) throws java.io.UnsupportedEncodingException - { - // The byte-length of a packed decimal with precision <code>p</code> is always <code>p/2 + 1</code> - int length = precision / 2 + 1; - - // check for sign. - int signum; - if ((buffer[offset+length-1] & 0x0F) == 0x0D) - signum = -1; - else - signum = 1; - - if (precision <= 9) { - // can be handled by int without overflow. - int value = packedNybblesToInt(buffer, offset, 0, length*2-1); - - // convert value to a byte array of magnitude. - byte[] magnitude = new byte[4]; - magnitude[0] = (byte)(value >>> 24); - magnitude[1] = (byte)(value >>> 16); - magnitude[2] = (byte)(value >>> 8); - magnitude[3] = (byte)(value); + /** + * Build a <code>java.math.BigDecimal</code> from a fixed point decimal byte representation. + * + * @throws IllegalArgumentException if the specified representation is not recognized. + */ + public static final java.math.BigDecimal getBigDecimal(byte[] buffer, + int offset, + int precision, + int scale) throws java.io.UnsupportedEncodingException { + // The byte-length of a packed decimal with precision <code>p</code> is always <code>p/2 + 1</code> + int length = precision / 2 + 1; + + // check for sign. + int signum; + if ((buffer[offset + length - 1] & 0x0F) == 0x0D) { + signum = -1; + } else { + signum = 1; + } - return new java.math.BigDecimal (new java.math.BigInteger(signum, magnitude), scale); + if (precision <= 9) { + // can be handled by int without overflow. + int value = packedNybblesToInt(buffer, offset, 0, length * 2 - 1); + + // convert value to a byte array of magnitude. + byte[] magnitude = new byte[4]; + magnitude[0] = (byte) (value >>> 24); + magnitude[1] = (byte) (value >>> 16); + magnitude[2] = (byte) (value >>> 8); + magnitude[3] = (byte) (value); + + return new java.math.BigDecimal(new java.math.BigInteger(signum, magnitude), scale); + } else if (precision <= 18) { + // can be handled by long without overflow. + long value = packedNybblesToLong(buffer, offset, 0, length * 2 - 1); + + // convert value to a byte array of magnitude. + byte[] magnitude = new byte[8]; + magnitude[0] = (byte) (value >>> 56); + magnitude[1] = (byte) (value >>> 48); + magnitude[2] = (byte) (value >>> 40); + magnitude[3] = (byte) (value >>> 32); + magnitude[4] = (byte) (value >>> 24); + magnitude[5] = (byte) (value >>> 16); + magnitude[6] = (byte) (value >>> 8); + magnitude[7] = (byte) (value); + + return new java.math.BigDecimal(new java.math.BigInteger(signum, magnitude), scale); + } else if (precision <= 27) { + // get the value of last 9 digits (5 bytes). + int lo = packedNybblesToInt(buffer, offset, (length - 5) * 2, 9); + // get the value of another 9 digits (5 bytes). + int me = packedNybblesToInt(buffer, offset, (length - 10) * 2 + 1, 9); + // get the value of the rest digits. + int hi = packedNybblesToInt(buffer, offset, 0, (length - 10) * 2 + 1); + + // compute the int array of magnitude. + int[] value = computeMagnitude(new int[]{hi, me, lo}); + + // convert value to a byte array of magnitude. + byte[] magnitude = new byte[12]; + magnitude[0] = (byte) (value[0] >>> 24); + magnitude[1] = (byte) (value[0] >>> 16); + magnitude[2] = (byte) (value[0] >>> 8); + magnitude[3] = (byte) (value[0]); + magnitude[4] = (byte) (value[1] >>> 24); + magnitude[5] = (byte) (value[1] >>> 16); + magnitude[6] = (byte) (value[1] >>> 8); + magnitude[7] = (byte) (value[1]); + magnitude[8] = (byte) (value[2] >>> 24); + magnitude[9] = (byte) (value[2] >>> 16); + magnitude[10] = (byte) (value[2] >>> 8); + magnitude[11] = (byte) (value[2]); + + return new java.math.BigDecimal(new java.math.BigInteger(signum, magnitude), scale); + } else if (precision <= 31) { + // get the value of last 9 digits (5 bytes). + int lo = packedNybblesToInt(buffer, offset, (length - 5) * 2, 9); + // get the value of another 9 digits (5 bytes). + int meLo = packedNybblesToInt(buffer, offset, (length - 10) * 2 + 1, 9); + // get the value of another 9 digits (5 bytes). + int meHi = packedNybblesToInt(buffer, offset, (length - 14) * 2, 9); + // get the value of the rest digits. + int hi = packedNybblesToInt(buffer, offset, 0, (length - 14) * 2); + + // compute the int array of magnitude. + int[] value = computeMagnitude(new int[]{hi, meHi, meLo, lo}); + + // convert value to a byte array of magnitude. + byte[] magnitude = new byte[16]; + magnitude[0] = (byte) (value[0] >>> 24); + magnitude[1] = (byte) (value[0] >>> 16); + magnitude[2] = (byte) (value[0] >>> 8); + magnitude[3] = (byte) (value[0]); + magnitude[4] = (byte) (value[1] >>> 24); + magnitude[5] = (byte) (value[1] >>> 16); + magnitude[6] = (byte) (value[1] >>> 8); + magnitude[7] = (byte) (value[1]); + magnitude[8] = (byte) (value[2] >>> 24); + magnitude[9] = (byte) (value[2] >>> 16); + magnitude[10] = (byte) (value[2] >>> 8); + magnitude[11] = (byte) (value[2]); + magnitude[12] = (byte) (value[3] >>> 24); + magnitude[13] = (byte) (value[3] >>> 16); + magnitude[14] = (byte) (value[3] >>> 8); + magnitude[15] = (byte) (value[3]); + + return new java.math.BigDecimal(new java.math.BigInteger(signum, magnitude), scale); + } else { + // throw an exception here if nibbles is greater than 31 + throw new java.lang.IllegalArgumentException("Decimal may only be up to 31 digits!"); + } } - else if (precision <= 18) { - // can be handled by long without overflow. - long value = packedNybblesToLong(buffer, offset, 0, length*2-1); - - // convert value to a byte array of magnitude. - byte[] magnitude = new byte[8]; - magnitude[0] = (byte)(value >>> 56); - magnitude[1] = (byte)(value >>> 48); - magnitude[2] = (byte)(value >>> 40); - magnitude[3] = (byte)(value >>> 32); - magnitude[4] = (byte)(value >>> 24); - magnitude[5] = (byte)(value >>> 16); - magnitude[6] = (byte)(value >>> 8); - magnitude[7] = (byte)(value); - return new java.math.BigDecimal (new java.math.BigInteger(signum, magnitude), scale); - } - else if (precision <= 27) { - // get the value of last 9 digits (5 bytes). - int lo = packedNybblesToInt(buffer, offset, (length-5)*2, 9); - // get the value of another 9 digits (5 bytes). - int me = packedNybblesToInt(buffer, offset, (length-10)*2+1, 9); - // get the value of the rest digits. - int hi = packedNybblesToInt(buffer, offset, 0, (length-10)*2+1); - - // compute the int array of magnitude. - int[] value = computeMagnitude(new int[] {hi, me, lo}); - - // convert value to a byte array of magnitude. - byte[] magnitude = new byte[12]; - magnitude[0] = (byte)(value[0] >>> 24); - magnitude[1] = (byte)(value[0] >>> 16); - magnitude[2] = (byte)(value[0] >>> 8); - magnitude[3] = (byte)(value[0]); - magnitude[4] = (byte)(value[1] >>> 24); - magnitude[5] = (byte)(value[1] >>> 16); - magnitude[6] = (byte)(value[1] >>> 8); - magnitude[7] = (byte)(value[1]); - magnitude[8] = (byte)(value[2] >>> 24); - magnitude[9] = (byte)(value[2] >>> 16); - magnitude[10] = (byte)(value[2] >>> 8); - magnitude[11] = (byte)(value[2]); + /** + * Build a Java <code>double</code> from a fixed point decimal byte representation. + * + * @throws IllegalArgumentException if the specified representation is not recognized. + */ + public static final double getDouble(byte[] buffer, + int offset, + int precision, + int scale) throws java.io.UnsupportedEncodingException { + // The byte-length of a packed decimal with precision <code>p</code> is always <code>p/2 + 1</code> + int length = precision / 2 + 1; + + // check for sign. + int signum; + if ((buffer[offset + length - 1] & 0x0F) == 0x0D) { + signum = -1; + } else { + signum = 1; + } - return new java.math.BigDecimal (new java.math.BigInteger(signum, magnitude), scale); + if (precision <= 9) { + // can be handled by int without overflow. + int value = packedNybblesToInt(buffer, offset, 0, length * 2 - 1); + + return signum * value / Math.pow(10, scale); + } else if (precision <= 18) { + // can be handled by long without overflow. + long value = packedNybblesToLong(buffer, offset, 0, length * 2 - 1); + + return signum * value / Math.pow(10, scale); + } else if (precision <= 27) { + // get the value of last 9 digits (5 bytes). + int lo = packedNybblesToInt(buffer, offset, (length - 5) * 2, 9); + // get the value of another 9 digits (5 bytes). + int me = packedNybblesToInt(buffer, offset, (length - 10) * 2 + 1, 9); + // get the value of the rest digits. + int hi = packedNybblesToInt(buffer, offset, 0, (length - 10) * 2 + 1); + + return signum * (lo / Math.pow(10, scale) + + me * Math.pow(10, 9 - scale) + + hi * Math.pow(10, 18 - scale)); + } else if (precision <= 31) { + // get the value of last 9 digits (5 bytes). + int lo = packedNybblesToInt(buffer, offset, (length - 5) * 2, 9); + // get the value of another 9 digits (5 bytes). + int meLo = packedNybblesToInt(buffer, offset, (length - 10) * 2 + 1, 9); + // get the value of another 9 digits (5 bytes). + int meHi = packedNybblesToInt(buffer, offset, (length - 14) * 2, 9); + // get the value of the rest digits. + int hi = packedNybblesToInt(buffer, offset, 0, (length - 14) * 2); + + return signum * (lo / Math.pow(10, scale) + + meLo * Math.pow(10, 9 - scale) + + meHi * Math.pow(10, 18 - scale) + + hi * Math.pow(10, 27 - scale)); + } else { + // throw an exception here if nibbles is greater than 31 + throw new java.lang.IllegalArgumentException("Decimal may only be up to 31 digits!"); + } } - else if (precision <= 31) { - // get the value of last 9 digits (5 bytes). - int lo = packedNybblesToInt(buffer, offset, (length-5)*2, 9); - // get the value of another 9 digits (5 bytes). - int meLo = packedNybblesToInt(buffer, offset, (length-10)*2+1, 9); - // get the value of another 9 digits (5 bytes). - int meHi = packedNybblesToInt(buffer, offset, (length-14)*2, 9); - // get the value of the rest digits. - int hi = packedNybblesToInt(buffer, offset, 0, (length-14)*2); - - // compute the int array of magnitude. - int[] value = computeMagnitude(new int[] {hi, meHi, meLo, lo}); - - // convert value to a byte array of magnitude. - byte[] magnitude = new byte[16]; - magnitude[0] = (byte)(value[0] >>> 24); - magnitude[1] = (byte)(value[0] >>> 16); - magnitude[2] = (byte)(value[0] >>> 8); - magnitude[3] = (byte)(value[0]); - magnitude[4] = (byte)(value[1] >>> 24); - magnitude[5] = (byte)(value[1] >>> 16); - magnitude[6] = (byte)(value[1] >>> 8); - magnitude[7] = (byte)(value[1]); - magnitude[8] = (byte)(value[2] >>> 24); - magnitude[9] = (byte)(value[2] >>> 16); - magnitude[10] = (byte)(value[2] >>> 8); - magnitude[11] = (byte)(value[2]); - magnitude[12] = (byte)(value[3] >>> 24); - magnitude[13] = (byte)(value[3] >>> 16); - magnitude[14] = (byte)(value[3] >>> 8); - magnitude[15] = (byte)(value[3]); - return new java.math.BigDecimal (new java.math.BigInteger(signum, magnitude), scale); - } - else { - // throw an exception here if nibbles is greater than 31 - throw new java.lang.IllegalArgumentException("Decimal may only be up to 31 digits!"); - } - } + /** + * Build a Java <code>long</code> from a fixed point decimal byte representation. + * + * @throws IllegalArgumentException if the specified representation is not recognized. + */ + public static final long getLong(byte[] buffer, + int offset, + int precision, + int scale) throws java.io.UnsupportedEncodingException { + if (precision > 31) { + // throw an exception here if nibbles is greater than 31 + throw new java.lang.IllegalArgumentException("Decimal may only be up to 31 digits!"); + } - /** - * Build a Java <code>double</code> from a fixed point decimal byte representation. - * - * @exception IllegalArgumentException if the specified representation is not recognized. - */ - public static final double getDouble (byte[] buffer, - int offset, - int precision, - int scale - ) throws java.io.UnsupportedEncodingException - { - // The byte-length of a packed decimal with precision <code>p</code> is always <code>p/2 + 1</code> - int length = precision / 2 + 1; - - // check for sign. - int signum; - if ((buffer[offset+length-1] & 0x0F) == 0x0D) - signum = -1; - else - signum = 1; - - if (precision <= 9) { - // can be handled by int without overflow. - int value = packedNybblesToInt(buffer, offset, 0, length*2-1); + // The byte-length of a packed decimal with precision <code>p</code> is always <code>p/2 + 1</code> + int length = precision / 2 + 1; - return signum * value / Math.pow(10, scale); - } - else if (precision <= 18) { - // can be handled by long without overflow. - long value = packedNybblesToLong(buffer, offset, 0, length*2-1); + // check for sign. + int signum; + if ((buffer[offset + length - 1] & 0x0F) == 0x0D) { + signum = -1; + } else { + signum = 1; + } - return signum * value / Math.pow(10, scale); - } - else if (precision <= 27) { - // get the value of last 9 digits (5 bytes). - int lo = packedNybblesToInt(buffer, offset, (length-5)*2, 9); - // get the value of another 9 digits (5 bytes). - int me = packedNybblesToInt(buffer, offset, (length-10)*2+1, 9); - // get the value of the rest digits. - int hi = packedNybblesToInt(buffer, offset, 0, (length-10)*2+1); - - return signum * (lo / Math.pow(10, scale) + - me * Math.pow(10, 9-scale) + - hi * Math.pow(10, 18-scale)); - } - else if (precision <= 31) { - // get the value of last 9 digits (5 bytes). - int lo = packedNybblesToInt(buffer, offset, (length-5)*2, 9); - // get the value of another 9 digits (5 bytes). - int meLo = packedNybblesToInt(buffer, offset, (length-10)*2+1, 9); - // get the value of another 9 digits (5 bytes). - int meHi = packedNybblesToInt(buffer, offset, (length-14)*2, 9); - // get the value of the rest digits. - int hi = packedNybblesToInt(buffer, offset, 0, (length-14)*2); - - return signum * (lo / Math.pow(10, scale) + - meLo * Math.pow(10, 9-scale) + - meHi * Math.pow(10, 18-scale) + - hi * Math.pow(10, 27-scale)); - } - else { - // throw an exception here if nibbles is greater than 31 - throw new java.lang.IllegalArgumentException ("Decimal may only be up to 31 digits!"); - } - } + // compute the integer part only. + int leftOfDecimalPoint = length * 2 - 1 - scale; + long integer = 0; + if (leftOfDecimalPoint > 0) { + int i = 0; + for (; i < leftOfDecimalPoint / 2; i++) { + integer = integer * 10 + signum * ((buffer[offset + i] & 0xF0) >>> 4); // high nybble. + integer = integer * 10 + signum * (buffer[offset + i] & 0x0F); // low nybble. + } + if ((leftOfDecimalPoint % 2) == 1) { + // process high nybble of the last byte if necessary. + integer = integer * 10 + signum * ((buffer[offset + i] & 0xF0) >>> 4); + } + } - /** - * Build a Java <code>long</code> from a fixed point decimal byte representation. - * - * @exception IllegalArgumentException if the specified representation is not recognized. - */ - public static final long getLong (byte[] buffer, - int offset, - int precision, - int scale - ) throws java.io.UnsupportedEncodingException - { - if (precision > 31) { - // throw an exception here if nibbles is greater than 31 - throw new java.lang.IllegalArgumentException ("Decimal may only be up to 31 digits!"); + return integer; } - // The byte-length of a packed decimal with precision <code>p</code> is always <code>p/2 + 1</code> - int length = precision / 2 + 1; + //--------------entry points for runtime representation----------------------- - // check for sign. - int signum; - if ((buffer[offset+length-1] & 0x0F) == 0x0D) - signum = -1; - else - signum = 1; - - // compute the integer part only. - int leftOfDecimalPoint = length*2-1-scale; - long integer = 0; - if (leftOfDecimalPoint > 0) { - int i = 0; - for (; i<leftOfDecimalPoint/2; i++) { - integer = integer*10 + signum*((buffer[offset+i] & 0xF0) >>> 4); // high nybble. - integer = integer*10 + signum* (buffer[offset+i] & 0x0F); // low nybble. - } - if ((leftOfDecimalPoint % 2) == 1) { - // process high nybble of the last byte if necessary. - integer = integer*10 + signum*((buffer[offset+i] & 0xF0) >>> 4); - } - } + /** + * Write a Java <code>java.math.BigDecimal</code> to packed decimal bytes. + */ + public static final int bigDecimalToPackedDecimalBytes(byte[] buffer, + int offset, + java.math.BigDecimal b, + int declaredPrecision, + int declaredScale) + throws ConversionException { + // packed decimal may only be up to 31 digits. + if (declaredPrecision > 31) { + throw new ConversionException("Packed decimal may only be up to 31 digits!"); + } - return integer; - } + // get absolute unscaled value of the BigDecimal as a String. + String unscaledStr = b.unscaledValue().abs().toString(); - //--------------entry points for runtime representation----------------------- + // get precision of the BigDecimal. + int bigPrecision = unscaledStr.length(); - /** - Write a Java <code>java.math.BigDecimal</code> to packed decimal bytes. - */ - public static final int bigDecimalToPackedDecimalBytes (byte[] buffer, - int offset, - java.math.BigDecimal b, - int declaredPrecision, - int declaredScale) - throws ConversionException - { - // packed decimal may only be up to 31 digits. - if (declaredPrecision > 31) - throw new ConversionException ("Packed decimal may only be up to 31 digits!"); - - // get absolute unscaled value of the BigDecimal as a String. - String unscaledStr = b.unscaledValue().abs().toString(); - - // get precision of the BigDecimal. - int bigPrecision = unscaledStr.length(); - - if (bigPrecision > 31) - throw new ConversionException ("The numeric literal \"" + - b.toString() + - "\" is not valid because its value is out of range.", - "42820", - -405); - - int bigScale = b.scale(); - int bigWholeIntegerLength = bigPrecision - bigScale; - if ( (bigWholeIntegerLength > 0) && (!unscaledStr.equals ("0")) ) { - // if whole integer part exists, check if overflow. - int declaredWholeIntegerLength = declaredPrecision - declaredScale; - if (bigWholeIntegerLength > declaredWholeIntegerLength) - throw new ConversionException ("Overflow occurred during numeric data type conversion of \"" + - b.toString() + - "\".", - "22003", - -413); - } + if (bigPrecision > 31) { + throw new ConversionException("The numeric literal \"" + + b.toString() + + "\" is not valid because its value is out of range.", + "42820", + -405); + } - // convert the unscaled value to a packed decimal bytes. + int bigScale = b.scale(); + int bigWholeIntegerLength = bigPrecision - bigScale; + if ((bigWholeIntegerLength > 0) && (!unscaledStr.equals("0"))) { + // if whole integer part exists, check if overflow. + int declaredWholeIntegerLength = declaredPrecision - declaredScale; + if (bigWholeIntegerLength > declaredWholeIntegerLength) { + throw new ConversionException("Overflow occurred during numeric data type conversion of \"" + + b.toString() + + "\".", + "22003", + -413); + } + } - // get unicode '0' value. - int zeroBase = '0'; + // convert the unscaled value to a packed decimal bytes. - // start index in target packed decimal. - int packedIndex = declaredPrecision-1; + // get unicode '0' value. + int zeroBase = '0'; - // start index in source big decimal. - int bigIndex; - - if (bigScale >= declaredScale) { - // If target scale is less than source scale, - // discard excessive fraction. - - // set start index in source big decimal to ignore excessive fraction. - bigIndex = bigPrecision-1-(bigScale-declaredScale); - - if (bigIndex < 0) { - // all digits are discarded, so only process the sign nybble. - buffer[offset+(packedIndex+1)/2] = - (byte) ( (b.signum()>=0)?12:13 ); // sign nybble - } - else { - // process the last nybble together with the sign nybble. - buffer[offset+(packedIndex+1)/2] = - (byte) ( ( (unscaledStr.charAt(bigIndex)-zeroBase) << 4 ) + // last nybble - ( (b.signum()>=0)?12:13 ) ); // sign nybble - } - packedIndex-=2; - bigIndex-=2; - } - else { - // If target scale is greater than source scale, - // pad the fraction with zero. - - // set start index in source big decimal to pad fraction with zero. - bigIndex = declaredScale-bigScale-1; - - // process the sign nybble. - buffer[offset+(packedIndex+1)/2] = - (byte) ( (b.signum()>=0)?12:13 ); // sign nybble - - for (packedIndex-=2, bigIndex-=2; bigIndex>=0; packedIndex-=2, bigIndex-=2) - buffer[offset+(packedIndex+1)/2] = (byte) 0; - - if (bigIndex == -1) { - buffer[offset+(packedIndex+1)/2] = - (byte) ( (unscaledStr.charAt(bigPrecision-1)-zeroBase) << 4 ); // high nybble - - packedIndex-=2; - bigIndex = bigPrecision-3; - } - else { - bigIndex = bigPrecision-2; - } - } + // start index in target packed decimal. + int packedIndex = declaredPrecision - 1; - // process the rest. - for (; bigIndex>=0; packedIndex-=2, bigIndex-=2) { - buffer[offset+(packedIndex+1)/2] = - (byte) ( ( (unscaledStr.charAt(bigIndex)-zeroBase) << 4 ) + // high nybble - ( unscaledStr.charAt(bigIndex+1)-zeroBase ) ); // low nybble - } + // start index in source big decimal. + int bigIndex; + + if (bigScale >= declaredScale) { + // If target scale is less than source scale, + // discard excessive fraction. + + // set start index in source big decimal to ignore excessive fraction. + bigIndex = bigPrecision - 1 - (bigScale - declaredScale); + + if (bigIndex < 0) { + // all digits are discarded, so only process the sign nybble. + buffer[offset + (packedIndex + 1) / 2] = + (byte) ((b.signum() >= 0) ? 12 : 13); // sign nybble + } else { + // process the last nybble together with the sign nybble. + buffer[offset + (packedIndex + 1) / 2] = + (byte) (((unscaledStr.charAt(bigIndex) - zeroBase) << 4) + // last nybble + ((b.signum() >= 0) ? 12 : 13)); // sign nybble + } + packedIndex -= 2; + bigIndex -= 2; + } else { + // If target scale is greater than source scale, + // pad the fraction with zero. + + // set start index in source big decimal to pad fraction with zero. + bigIndex = declaredScale - bigScale - 1; + + // process the sign nybble. + buffer[offset + (packedIndex + 1) / 2] = + (byte) ((b.signum() >= 0) ? 12 : 13); // sign nybble + + for (packedIndex -= 2, bigIndex -= 2; bigIndex >= 0; packedIndex -= 2, bigIndex -= 2) { + buffer[offset + (packedIndex + 1) / 2] = (byte) 0; + } + + if (bigIndex == -1) { + buffer[offset + (packedIndex + 1) / 2] = + (byte) ((unscaledStr.charAt(bigPrecision - 1) - zeroBase) << 4); // high nybble + + packedIndex -= 2; + bigIndex = bigPrecision - 3; + } else { + bigIndex = bigPrecision - 2; + } + } - // process the first nybble when there is one left. - if (bigIndex == -1) { - buffer[offset+(packedIndex+1)/2] = - (byte) (unscaledStr.charAt(0) - zeroBase); + // process the rest. + for (; bigIndex >= 0; packedIndex -= 2, bigIndex -= 2) { + buffer[offset + (packedIndex + 1) / 2] = + (byte) (((unscaledStr.charAt(bigIndex) - zeroBase) << 4) + // high nybble + (unscaledStr.charAt(bigIndex + 1) - zeroBase)); // low nybble + } - packedIndex-=2; - } + // process the first nybble when there is one left. + if (bigIndex == -1) { + buffer[offset + (packedIndex + 1) / 2] = + (byte) (unscaledStr.charAt(0) - zeroBase); - // pad zero in front of the big decimal if necessary. - for (; packedIndex>=-1; packedIndex-=2) - buffer[offset+(packedIndex+1)/2] = (byte) 0; + packedIndex -= 2; + } - return declaredPrecision/2 + 1; - } + // pad zero in front of the big decimal if necessary. + for (; packedIndex >= -1; packedIndex -= 2) { + buffer[offset + (packedIndex + 1) / 2] = (byte) 0; + } + + return declaredPrecision / 2 + 1; + } }
infrastructure at apache.org | ViewVC Help |
Powered by ViewVC 1.1.26 |