1495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert/* GENERATED SOURCE. DO NOT MODIFY. */ 2495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert// © 2017 and later: Unicode, Inc. and others. 3495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert// License & terms of use: http://www.unicode.org/copyright.html#License 4495cb271e305cfb399d463f32210a371198f0abfFredrik Roubertpackage android.icu.impl.number; 5495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert 6495cb271e305cfb399d463f32210a371198f0abfFredrik Roubertimport java.math.BigDecimal; 7495cb271e305cfb399d463f32210a371198f0abfFredrik Roubertimport java.math.BigInteger; 8495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert 9495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert/** 1005fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * A DecimalQuantity with internal storage as a 64-bit BCD, with fallback to a byte array 1105fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * for numbers that don't fit into the standard BCD. 12495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert * @hide Only a subset of ICU is exposed in Android 13495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert */ 1405fa7802d0874812c234a29745586677ee5837eaFredrik Roubertpublic final class DecimalQuantity_DualStorageBCD extends DecimalQuantity_AbstractBCD { 15495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert 16495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert /** 17495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert * The BCD of the 16 digits of the number represented by this object. Every 4 bits of the long map 18495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert * to one digit. For example, the number "12345" in BCD is "0x12345". 19495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert * 20495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert * <p>Whenever bcd changes internally, {@link #compact()} must be called, except in special cases 21495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert * like setting the digit to zero. 22495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert */ 23495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert private byte[] bcdBytes; 24495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert 25495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert private long bcdLong = 0L; 26495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert 27495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert private boolean usingBytes = false; 28495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert 29495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert @Override 30495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert public int maxRepresentableDigits() { 31495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert return Integer.MAX_VALUE; 32495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } 33495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert 3405fa7802d0874812c234a29745586677ee5837eaFredrik Roubert public DecimalQuantity_DualStorageBCD() { 35495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert setBcdToZero(); 3605fa7802d0874812c234a29745586677ee5837eaFredrik Roubert flags = 0; 37495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } 38495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert 3905fa7802d0874812c234a29745586677ee5837eaFredrik Roubert public DecimalQuantity_DualStorageBCD(long input) { 40495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert setToLong(input); 41495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } 42495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert 4305fa7802d0874812c234a29745586677ee5837eaFredrik Roubert public DecimalQuantity_DualStorageBCD(int input) { 44495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert setToInt(input); 45495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } 46495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert 4705fa7802d0874812c234a29745586677ee5837eaFredrik Roubert public DecimalQuantity_DualStorageBCD(double input) { 48495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert setToDouble(input); 49495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } 50495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert 5105fa7802d0874812c234a29745586677ee5837eaFredrik Roubert public DecimalQuantity_DualStorageBCD(BigInteger input) { 52495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert setToBigInteger(input); 53495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } 54495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert 5505fa7802d0874812c234a29745586677ee5837eaFredrik Roubert public DecimalQuantity_DualStorageBCD(BigDecimal input) { 56495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert setToBigDecimal(input); 57495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } 58495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert 5905fa7802d0874812c234a29745586677ee5837eaFredrik Roubert public DecimalQuantity_DualStorageBCD(DecimalQuantity_DualStorageBCD other) { 60495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert copyFrom(other); 61495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } 62495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert 6305fa7802d0874812c234a29745586677ee5837eaFredrik Roubert public DecimalQuantity_DualStorageBCD(Number number) { 64495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert if (number instanceof Long) { 65495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert setToLong(number.longValue()); 66495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } else if (number instanceof Integer) { 67495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert setToInt(number.intValue()); 68495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } else if (number instanceof Double) { 69495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert setToDouble(number.doubleValue()); 70495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } else if (number instanceof BigInteger) { 71495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert setToBigInteger((BigInteger) number); 72495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } else if (number instanceof BigDecimal) { 73495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert setToBigDecimal((BigDecimal) number); 74495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } else if (number instanceof android.icu.math.BigDecimal) { 75495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert setToBigDecimal(((android.icu.math.BigDecimal) number).toBigDecimal()); 76495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } else { 77495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert throw new IllegalArgumentException( 78495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert "Number is of an unsupported type: " + number.getClass().getName()); 79495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } 80495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } 81495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert 82495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert @Override 8305fa7802d0874812c234a29745586677ee5837eaFredrik Roubert public DecimalQuantity createCopy() { 8405fa7802d0874812c234a29745586677ee5837eaFredrik Roubert return new DecimalQuantity_DualStorageBCD(this); 8505fa7802d0874812c234a29745586677ee5837eaFredrik Roubert } 8605fa7802d0874812c234a29745586677ee5837eaFredrik Roubert 8705fa7802d0874812c234a29745586677ee5837eaFredrik Roubert @Override 88495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert protected byte getDigitPos(int position) { 89495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert if (usingBytes) { 90495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert if (position < 0 || position > precision) return 0; 91495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert return bcdBytes[position]; 92495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } else { 93495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert if (position < 0 || position >= 16) return 0; 94495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert return (byte) ((bcdLong >>> (position * 4)) & 0xf); 95495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } 96495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } 97495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert 98495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert @Override 99495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert protected void setDigitPos(int position, byte value) { 100495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert assert position >= 0; 101495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert if (usingBytes) { 102495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert ensureCapacity(position + 1); 103495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert bcdBytes[position] = value; 104495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } else if (position >= 16) { 105495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert switchStorage(); 106495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert ensureCapacity(position + 1); 107495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert bcdBytes[position] = value; 108495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } else { 109495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert int shift = position * 4; 110495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert bcdLong = bcdLong & ~(0xfL << shift) | ((long) value << shift); 111495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } 112495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } 113495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert 114495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert @Override 115495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert protected void shiftLeft(int numDigits) { 116495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert if (!usingBytes && precision + numDigits > 16) { 117495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert switchStorage(); 118495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } 119495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert if (usingBytes) { 120495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert ensureCapacity(precision + numDigits); 121495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert int i = precision + numDigits - 1; 122495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert for (; i >= numDigits; i--) { 123495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert bcdBytes[i] = bcdBytes[i - numDigits]; 124495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } 125495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert for (; i >= 0; i--) { 126495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert bcdBytes[i] = 0; 127495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } 128495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } else { 129495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert bcdLong <<= (numDigits * 4); 130495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } 131495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert scale -= numDigits; 132495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert precision += numDigits; 133495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } 134495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert 135495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert @Override 136495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert protected void shiftRight(int numDigits) { 137495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert if (usingBytes) { 138495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert int i = 0; 139495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert for (; i < precision - numDigits; i++) { 140495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert bcdBytes[i] = bcdBytes[i + numDigits]; 141495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } 142495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert for (; i < precision; i++) { 143495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert bcdBytes[i] = 0; 144495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } 145495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } else { 146495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert bcdLong >>>= (numDigits * 4); 147495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } 148495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert scale += numDigits; 149495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert precision -= numDigits; 150495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } 151495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert 152495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert @Override 153495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert protected void setBcdToZero() { 154495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert if (usingBytes) { 15505fa7802d0874812c234a29745586677ee5837eaFredrik Roubert bcdBytes = null; 15605fa7802d0874812c234a29745586677ee5837eaFredrik Roubert usingBytes = false; 157495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } 158495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert bcdLong = 0L; 159495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert scale = 0; 160495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert precision = 0; 161495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert isApproximate = false; 162495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert origDouble = 0; 163495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert origDelta = 0; 164495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } 165495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert 166495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert @Override 167495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert protected void readIntToBcd(int n) { 168495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert assert n != 0; 169495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert // ints always fit inside the long implementation. 170495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert long result = 0L; 171495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert int i = 16; 172495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert for (; n != 0; n /= 10, i--) { 173495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert result = (result >>> 4) + (((long) n % 10) << 60); 174495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } 17505fa7802d0874812c234a29745586677ee5837eaFredrik Roubert assert !usingBytes; 176495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert bcdLong = result >>> (i * 4); 177495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert scale = 0; 178495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert precision = 16 - i; 179495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } 180495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert 181495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert @Override 182495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert protected void readLongToBcd(long n) { 183495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert assert n != 0; 184495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert if (n >= 10000000000000000L) { 185495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert ensureCapacity(); 186495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert int i = 0; 187495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert for (; n != 0L; n /= 10L, i++) { 188495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert bcdBytes[i] = (byte) (n % 10); 189495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } 19005fa7802d0874812c234a29745586677ee5837eaFredrik Roubert assert usingBytes; 191495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert scale = 0; 192495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert precision = i; 193495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } else { 194495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert long result = 0L; 195495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert int i = 16; 196495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert for (; n != 0L; n /= 10L, i--) { 197495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert result = (result >>> 4) + ((n % 10) << 60); 198495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } 199495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert assert i >= 0; 20005fa7802d0874812c234a29745586677ee5837eaFredrik Roubert assert !usingBytes; 201495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert bcdLong = result >>> (i * 4); 202495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert scale = 0; 203495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert precision = 16 - i; 204495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } 205495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } 206495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert 207495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert @Override 208495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert protected void readBigIntegerToBcd(BigInteger n) { 209495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert assert n.signum() != 0; 210495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert ensureCapacity(); // allocate initial byte array 211495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert int i = 0; 212495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert for (; n.signum() != 0; i++) { 213495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert BigInteger[] temp = n.divideAndRemainder(BigInteger.TEN); 214495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert ensureCapacity(i + 1); 215495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert bcdBytes[i] = temp[1].byteValue(); 216495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert n = temp[0]; 217495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } 218495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert scale = 0; 219495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert precision = i; 220495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } 221495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert 222495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert @Override 223495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert protected BigDecimal bcdToBigDecimal() { 224495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert if (usingBytes) { 225495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert // Converting to a string here is faster than doing BigInteger/BigDecimal arithmetic. 22605fa7802d0874812c234a29745586677ee5837eaFredrik Roubert BigDecimal result = new BigDecimal(toNumberString()); 22705fa7802d0874812c234a29745586677ee5837eaFredrik Roubert if (isNegative()) { 22805fa7802d0874812c234a29745586677ee5837eaFredrik Roubert result = result.negate(); 229495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } 23005fa7802d0874812c234a29745586677ee5837eaFredrik Roubert return result; 231495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } else { 232495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert long tempLong = 0L; 233495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert for (int shift = (precision - 1); shift >= 0; shift--) { 234495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert tempLong = tempLong * 10 + getDigitPos(shift); 235495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } 236495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert BigDecimal result = BigDecimal.valueOf(tempLong); 237495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert result = result.scaleByPowerOfTen(scale); 238495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert if (isNegative()) result = result.negate(); 239495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert return result; 240495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } 241495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } 242495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert 243495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert @Override 244495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert protected void compact() { 245495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert if (usingBytes) { 246495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert int delta = 0; 247495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert for (; delta < precision && bcdBytes[delta] == 0; delta++) ; 248495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert if (delta == precision) { 249495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert // Number is zero 250495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert setBcdToZero(); 251495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert return; 252495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } else { 253495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert // Remove trailing zeros 254495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert shiftRight(delta); 255495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } 256495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert 257495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert // Compute precision 258495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert int leading = precision - 1; 259495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert for (; leading >= 0 && bcdBytes[leading] == 0; leading--) ; 260495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert precision = leading + 1; 261495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert 262495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert // Switch storage mechanism if possible 263495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert if (precision <= 16) { 264495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert switchStorage(); 265495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } 266495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert 267495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } else { 268495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert if (bcdLong == 0L) { 269495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert // Number is zero 270495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert setBcdToZero(); 271495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert return; 272495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } 273495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert 274495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert // Compact the number (remove trailing zeros) 275495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert int delta = Long.numberOfTrailingZeros(bcdLong) / 4; 276495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert bcdLong >>>= delta * 4; 277495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert scale += delta; 278495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert 279495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert // Compute precision 280495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert precision = 16 - (Long.numberOfLeadingZeros(bcdLong) / 4); 281495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } 282495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } 283495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert 284495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert /** Ensure that a byte array of at least 40 digits is allocated. */ 285495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert private void ensureCapacity() { 286495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert ensureCapacity(40); 287495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } 288495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert 289495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert private void ensureCapacity(int capacity) { 290495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert if (capacity == 0) return; 29105fa7802d0874812c234a29745586677ee5837eaFredrik Roubert int oldCapacity = usingBytes ? bcdBytes.length : 0; 29205fa7802d0874812c234a29745586677ee5837eaFredrik Roubert if (!usingBytes) { 293495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert bcdBytes = new byte[capacity]; 29405fa7802d0874812c234a29745586677ee5837eaFredrik Roubert } else if (oldCapacity < capacity) { 295495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert byte[] bcd1 = new byte[capacity * 2]; 29605fa7802d0874812c234a29745586677ee5837eaFredrik Roubert System.arraycopy(bcdBytes, 0, bcd1, 0, oldCapacity); 297495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert bcdBytes = bcd1; 298495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } 29905fa7802d0874812c234a29745586677ee5837eaFredrik Roubert usingBytes = true; 300495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } 301495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert 302495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert /** Switches the internal storage mechanism between the 64-bit long and the byte array. */ 303495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert private void switchStorage() { 304495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert if (usingBytes) { 305495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert // Change from bytes to long 306495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert bcdLong = 0L; 307495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert for (int i = precision - 1; i >= 0; i--) { 308495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert bcdLong <<= 4; 309495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert bcdLong |= bcdBytes[i]; 310495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } 31105fa7802d0874812c234a29745586677ee5837eaFredrik Roubert bcdBytes = null; 312495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert usingBytes = false; 313495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } else { 314495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert // Change from long to bytes 315495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert ensureCapacity(); 316495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert for (int i = 0; i < precision; i++) { 317495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert bcdBytes[i] = (byte) (bcdLong & 0xf); 318495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert bcdLong >>>= 4; 319495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } 32005fa7802d0874812c234a29745586677ee5837eaFredrik Roubert assert usingBytes; 321495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } 322495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } 323495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert 324495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert @Override 32505fa7802d0874812c234a29745586677ee5837eaFredrik Roubert protected void copyBcdFrom(DecimalQuantity _other) { 32605fa7802d0874812c234a29745586677ee5837eaFredrik Roubert DecimalQuantity_DualStorageBCD other = (DecimalQuantity_DualStorageBCD) _other; 32705fa7802d0874812c234a29745586677ee5837eaFredrik Roubert setBcdToZero(); 328495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert if (other.usingBytes) { 329495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert ensureCapacity(other.precision); 330495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert System.arraycopy(other.bcdBytes, 0, bcdBytes, 0, other.precision); 331495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } else { 332495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert bcdLong = other.bcdLong; 333495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } 334495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } 335495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert 336495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert /** 337495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert * Checks whether the bytes stored in this instance are all valid. For internal unit testing only. 338495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert * 339495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert * @return An error message if this instance is invalid, or null if this instance is healthy. 340495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert * @deprecated This API is for ICU internal use only. 341495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert * @hide draft / provisional / internal are hidden on Android 342495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert */ 343495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert @Deprecated 344495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert public String checkHealth() { 345495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert if (usingBytes) { 346495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert if (bcdLong != 0) return "Value in bcdLong but we are in byte mode"; 347495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert if (precision == 0) return "Zero precision but we are in byte mode"; 348495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert if (precision > bcdBytes.length) return "Precision exceeds length of byte array"; 349495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert if (getDigitPos(precision - 1) == 0) return "Most significant digit is zero in byte mode"; 350495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert if (getDigitPos(0) == 0) return "Least significant digit is zero in long mode"; 351495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert for (int i = 0; i < precision; i++) { 352495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert if (getDigitPos(i) >= 10) return "Digit exceeding 10 in byte array"; 353495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert if (getDigitPos(i) < 0) return "Digit below 0 in byte array"; 354495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } 355495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert for (int i = precision; i < bcdBytes.length; i++) { 356495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert if (getDigitPos(i) != 0) return "Nonzero digits outside of range in byte array"; 357495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } 358495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } else { 359495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert if (bcdBytes != null) { 360495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert for (int i = 0; i < bcdBytes.length; i++) { 361495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert if (bcdBytes[i] != 0) return "Nonzero digits in byte array but we are in long mode"; 362495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } 363495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } 364495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert if (precision == 0 && bcdLong != 0) return "Value in bcdLong even though precision is zero"; 365495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert if (precision > 16) return "Precision exceeds length of long"; 366495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert if (precision != 0 && getDigitPos(precision - 1) == 0) 367495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert return "Most significant digit is zero in long mode"; 368495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert if (precision != 0 && getDigitPos(0) == 0) 369495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert return "Least significant digit is zero in long mode"; 370495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert for (int i = 0; i < precision; i++) { 371495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert if (getDigitPos(i) >= 10) return "Digit exceeding 10 in long"; 372495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert if (getDigitPos(i) < 0) return "Digit below 0 in long (?!)"; 373495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } 374495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert for (int i = precision; i < 16; i++) { 375495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert if (getDigitPos(i) != 0) return "Nonzero digits outside of range in long"; 376495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } 377495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } 378495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert 379495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert return null; 380495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } 381495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert 382495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert /** 38305fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * Checks whether this {@link DecimalQuantity_DualStorageBCD} is using its internal byte array storage mechanism. 384495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert * 385495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert * @return true if an internal byte array is being used; false if a long is being used. 386495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert * @deprecated This API is ICU internal only. 387495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert * @hide draft / provisional / internal are hidden on Android 388495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert */ 389495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert @Deprecated 39005fa7802d0874812c234a29745586677ee5837eaFredrik Roubert public boolean isUsingBytes() { 391495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert return usingBytes; 392495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } 393495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert 394495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert @Override 395495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert public String toString() { 396495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert return String.format( 39705fa7802d0874812c234a29745586677ee5837eaFredrik Roubert "<DecimalQuantity %s:%d:%d:%s %s %s>", 39805fa7802d0874812c234a29745586677ee5837eaFredrik Roubert (lOptPos > 1000 ? "999" : String.valueOf(lOptPos)), 399495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert lReqPos, 400495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert rReqPos, 40105fa7802d0874812c234a29745586677ee5837eaFredrik Roubert (rOptPos < -1000 ? "-999" : String.valueOf(rOptPos)), 402495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert (usingBytes ? "bytes" : "long"), 40305fa7802d0874812c234a29745586677ee5837eaFredrik Roubert toNumberString()); 40405fa7802d0874812c234a29745586677ee5837eaFredrik Roubert } 40505fa7802d0874812c234a29745586677ee5837eaFredrik Roubert 40605fa7802d0874812c234a29745586677ee5837eaFredrik Roubert public String toNumberString() { 40705fa7802d0874812c234a29745586677ee5837eaFredrik Roubert StringBuilder sb = new StringBuilder(); 40805fa7802d0874812c234a29745586677ee5837eaFredrik Roubert if (usingBytes) { 40905fa7802d0874812c234a29745586677ee5837eaFredrik Roubert for (int i = precision - 1; i >= 0; i--) { 41005fa7802d0874812c234a29745586677ee5837eaFredrik Roubert sb.append(bcdBytes[i]); 41105fa7802d0874812c234a29745586677ee5837eaFredrik Roubert } 41205fa7802d0874812c234a29745586677ee5837eaFredrik Roubert } else { 41305fa7802d0874812c234a29745586677ee5837eaFredrik Roubert sb.append(Long.toHexString(bcdLong)); 41405fa7802d0874812c234a29745586677ee5837eaFredrik Roubert } 41505fa7802d0874812c234a29745586677ee5837eaFredrik Roubert sb.append("E"); 41605fa7802d0874812c234a29745586677ee5837eaFredrik Roubert sb.append(scale); 41705fa7802d0874812c234a29745586677ee5837eaFredrik Roubert return sb.toString(); 418495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert } 419495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert} 420