1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/* 2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Licensed to the Apache Software Foundation (ASF) under one or more 3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * contributor license agreements. See the NOTICE file distributed with 4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * this work for additional information regarding copyright ownership. 5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The ASF licenses this file to You under the Apache License, Version 2.0 6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * (the "License"); you may not use this file except in compliance with 7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the License. You may obtain a copy of the License at 8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software 12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * See the License for the specific language governing permissions and 15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * limitations under the License. 16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 18dc915c69ba2495dd2cf965d16058d0b13762142cElliott Hughespackage java.lang; 19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 20adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.regex.Matcher; 21adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.regex.Pattern; 22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/* 24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Parses hex string to a single or double precision floating point number. 25dc915c69ba2495dd2cf965d16058d0b13762142cElliott Hughes * 26dc915c69ba2495dd2cf965d16058d0b13762142cElliott Hughes * TODO: rewrite this! 27dc915c69ba2495dd2cf965d16058d0b13762142cElliott Hughes * 28dc915c69ba2495dd2cf965d16058d0b13762142cElliott Hughes * @hide 29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectfinal class HexStringParser { 31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static final int DOUBLE_EXPONENT_WIDTH = 11; 33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static final int DOUBLE_MANTISSA_WIDTH = 52; 35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static final int FLOAT_EXPONENT_WIDTH = 8; 37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static final int FLOAT_MANTISSA_WIDTH = 23; 39f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static final int HEX_RADIX = 16; 41f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static final int MAX_SIGNIFICANT_LENGTH = 15; 43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 44f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes private static final String HEX_SIGNIFICANT = "0[xX](\\p{XDigit}+\\.?|\\p{XDigit}*\\.\\p{XDigit}+)"; 45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 46f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes private static final String BINARY_EXPONENT = "[pP]([+-]?\\d+)"; 47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 48f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes private static final String FLOAT_TYPE_SUFFIX = "[fFdD]?"; 49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 50f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes private static final String HEX_PATTERN = "[\\x00-\\x20]*([+-]?)" + HEX_SIGNIFICANT 51f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes + BINARY_EXPONENT + FLOAT_TYPE_SUFFIX + "[\\x00-\\x20]*"; 52adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static final Pattern PATTERN = Pattern.compile(HEX_PATTERN); 54adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private final int EXPONENT_WIDTH; 56adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private final int MANTISSA_WIDTH; 58f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private final long EXPONENT_BASE; 60f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private final long MAX_EXPONENT; 62f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private final long MIN_EXPONENT; 64f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 65adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private final long MANTISSA_MASK; 66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private long sign; 68adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private long exponent; 70adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private long mantissa; 72f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 73f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes private String abandonedNumber=""; 74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 759229d47c1288e25ead3a2dc27fac8a4a2ee932a3Elliott Hughes public HexStringParser(int exponentWidth, int mantissaWidth) { 769229d47c1288e25ead3a2dc27fac8a4a2ee932a3Elliott Hughes this.EXPONENT_WIDTH = exponentWidth; 779229d47c1288e25ead3a2dc27fac8a4a2ee932a3Elliott Hughes this.MANTISSA_WIDTH = mantissaWidth; 78f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 799229d47c1288e25ead3a2dc27fac8a4a2ee932a3Elliott Hughes this.EXPONENT_BASE = ~(-1L << (exponentWidth - 1)); 809229d47c1288e25ead3a2dc27fac8a4a2ee932a3Elliott Hughes this.MAX_EXPONENT = ~(-1L << exponentWidth); 81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.MIN_EXPONENT = -(MANTISSA_WIDTH + 1); 829229d47c1288e25ead3a2dc27fac8a4a2ee932a3Elliott Hughes this.MANTISSA_MASK = ~(-1L << mantissaWidth); 83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* 86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Parses the hex string to a double number. 87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public static double parseDouble(String hexString) { 891f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes HexStringParser parser = new HexStringParser(DOUBLE_EXPONENT_WIDTH, DOUBLE_MANTISSA_WIDTH); 901f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes long result = parser.parse(hexString, true); 91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return Double.longBitsToDouble(result); 92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* 95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Parses the hex string to a float number. 96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public static float parseFloat(String hexString) { 981f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes HexStringParser parser = new HexStringParser(FLOAT_EXPONENT_WIDTH, FLOAT_MANTISSA_WIDTH); 991f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes int result = (int) parser.parse(hexString, false); 100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return Float.intBitsToFloat(result); 101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1031f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes private long parse(String hexString, boolean isDouble) { 1041f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes Matcher matcher = PATTERN.matcher(hexString); 1051f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes if (!matcher.matches()) { 1061f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes throw new NumberFormatException("Invalid hex " + (isDouble ? "double" : "float")+ ":" + 1071f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes hexString); 1081f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes } 1091f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes 1101f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes String signStr = matcher.group(1); 1111f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes String significantStr = matcher.group(2); 1121f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes String exponentStr = matcher.group(3); 113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project parseHexSign(signStr); 115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project parseExponent(exponentStr); 116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project parseMantissa(significantStr); 117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project sign <<= (MANTISSA_WIDTH + EXPONENT_WIDTH); 119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project exponent <<= MANTISSA_WIDTH; 120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return sign | exponent | mantissa; 121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* 124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Parses the sign field. 125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private void parseHexSign(String signStr) { 127f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes this.sign = signStr.equals("-") ? 1 : 0; 128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* 131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Parses the exponent field. 132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private void parseExponent(String exponentStr) { 134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project char leadingChar = exponentStr.charAt(0); 135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int expSign = (leadingChar == '-' ? -1 : 1); 136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!Character.isDigit(leadingChar)) { 137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project exponentStr = exponentStr.substring(1); 138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project exponent = expSign * Long.parseLong(exponentStr); 142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project checkedAddExponent(EXPONENT_BASE); 143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (NumberFormatException e) { 144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project exponent = expSign * Long.MAX_VALUE; 145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 147f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* 149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Parses the mantissa field. 150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private void parseMantissa(String significantStr) { 152f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes String[] strings = significantStr.split("\\."); 153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String strIntegerPart = strings[0]; 154f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes String strDecimalPart = strings.length > 1 ? strings[1] : ""; 155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String significand = getNormalizedSignificand(strIntegerPart,strDecimalPart); 157f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes if (significand.equals("0")) { 158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project setZero(); 159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int offset = getOffset(strIntegerPart, strDecimalPart); 163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project checkedAddExponent(offset); 164f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (exponent >= MAX_EXPONENT) { 166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project setInfinite(); 167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 169f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (exponent <= MIN_EXPONENT) { 171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project setZero(); 172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (significand.length() > MAX_SIGNIFICANT_LENGTH) { 176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project abandonedNumber = significand.substring(MAX_SIGNIFICANT_LENGTH); 177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project significand = significand.substring(0, MAX_SIGNIFICANT_LENGTH); 178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project mantissa = Long.parseLong(significand, HEX_RADIX); 181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (exponent >= 1) { 183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project processNormalNumber(); 184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else{ 185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project processSubNormalNumber(); 186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 188adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 189f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 190adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private void setInfinite() { 191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project exponent = MAX_EXPONENT; 192adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project mantissa = 0; 193adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private void setZero() { 196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project exponent = 0; 197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project mantissa = 0; 198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 199f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* 201adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Sets the exponent variable to Long.MAX_VALUE or -Long.MAX_VALUE if 202adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * overflow or underflow happens. 203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 204adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private void checkedAddExponent(long offset) { 205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project long result = exponent + offset; 206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int expSign = Long.signum(exponent); 207adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (expSign * Long.signum(offset) > 0 && expSign * Long.signum(result) < 0) { 208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project exponent = expSign * Long.MAX_VALUE; 209adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project exponent = result; 211adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 213f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private void processNormalNumber(){ 215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int desiredWidth = MANTISSA_WIDTH + 2; 216adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project fitMantissaInDesiredWidth(desiredWidth); 217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project round(); 218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project mantissa = mantissa & MANTISSA_MASK; 219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 220f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 221adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private void processSubNormalNumber(){ 222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int desiredWidth = MANTISSA_WIDTH + 1; 223adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project desiredWidth += (int)exponent;//lends bit from mantissa to exponent 224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project exponent = 0; 225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project fitMantissaInDesiredWidth(desiredWidth); 226adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project round(); 227adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project mantissa = mantissa & MANTISSA_MASK; 228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 229f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* 231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Adjusts the mantissa to desired width for further analysis. 232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 233adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private void fitMantissaInDesiredWidth(int desiredWidth){ 234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int bitLength = countBitsLength(mantissa); 235adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (bitLength > desiredWidth) { 236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project discardTrailingBits(bitLength - desiredWidth); 237adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 238adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project mantissa <<= (desiredWidth - bitLength); 239adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 241f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* 243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Stores the discarded bits to abandonedNumber. 244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private void discardTrailingBits(long num) { 246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project long mask = ~(-1L << num); 247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project abandonedNumber += (mantissa & mask); 248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project mantissa >>= num; 249adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* 252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The value is rounded up or down to the nearest infinitely precise result. 253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * If the value is exactly halfway between two infinitely precise results, 254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * then it should be rounded up to the nearest infinitely precise even. 255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private void round() { 257f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes String result = abandonedNumber.replaceAll("0+", ""); 258adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project boolean moreThanZero = (result.length() > 0 ? true : false); 259adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int lastDiscardedBit = (int) (mantissa & 1L); 261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project mantissa >>= 1; 262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int tailBitInMantissa = (int) (mantissa & 1L); 263f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (lastDiscardedBit == 1 && (moreThanZero || tailBitInMantissa == 1)) { 265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int oldLength = countBitsLength(mantissa); 266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project mantissa += 1L; 267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int newLength = countBitsLength(mantissa); 268f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project //Rounds up to exponent when whole bits of mantissa are one-bits. 270adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (oldLength >= MANTISSA_WIDTH && newLength > oldLength) { 271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project checkedAddExponent(1); 272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 274adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 275adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* 277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns the normalized significand after removing the leading zeros. 278adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 279adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private String getNormalizedSignificand(String strIntegerPart, String strDecimalPart) { 280adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String significand = strIntegerPart + strDecimalPart; 281f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes significand = significand.replaceFirst("^0+", ""); 282adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (significand.length() == 0) { 283f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes significand = "0"; 284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 285adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return significand; 286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 287adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* 289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Calculates the offset between the normalized number and unnormalized 290adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * number. In a normalized representation, significand is represented by the 291adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * characters "0x1." followed by a lowercase hexadecimal representation of 292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the rest of the significand as a fraction. 293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 294adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private int getOffset(String strIntegerPart, String strDecimalPart) { 295f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes strIntegerPart = strIntegerPart.replaceFirst("^0+", ""); 296f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 297f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson //If the Integer part is a nonzero number. 298adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (strIntegerPart.length() != 0) { 299adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String leadingNumber = strIntegerPart.substring(0, 1); 300adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return (strIntegerPart.length() - 1) * 4 + countBitsLength(Long.parseLong(leadingNumber,HEX_RADIX)) - 1; 301adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 302f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 303f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson //If the Integer part is a zero number. 304adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int i; 305f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes for (i = 0; i < strDecimalPart.length() && strDecimalPart.charAt(i) == '0'; i++); 306adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (i == strDecimalPart.length()) { 307adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return 0; 308adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 309adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String leadingNumber=strDecimalPart.substring(i,i + 1); 310adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return (-i - 1) * 4 + countBitsLength(Long.parseLong(leadingNumber, HEX_RADIX)) - 1; 311adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 312adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 313adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private int countBitsLength(long value) { 314adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int leadingZeros = Long.numberOfLeadingZeros(value); 315adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return Long.SIZE - leadingZeros; 316adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 317adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 318