16d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver/* 26d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver * Copyright 2013, Google Inc. 36d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver * All rights reserved. 46d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver * 56d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver * Redistribution and use in source and binary forms, with or without 66d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver * modification, are permitted provided that the following conditions are 76d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver * met: 86d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver * 96d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver * * Redistributions of source code must retain the above copyright 106d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver * notice, this list of conditions and the following disclaimer. 116d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver * * Redistributions in binary form must reproduce the above 126d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver * copyright notice, this list of conditions and the following disclaimer 136d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver * in the documentation and/or other materials provided with the 146d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver * distribution. 156d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver * * Neither the name of Google Inc. nor the names of its 166d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver * contributors may be used to endorse or promote products derived from 176d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver * this software without specific prior written permission. 186d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver * 196d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 206d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 216d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 226d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 236d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 246d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 256d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 266d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 276d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 286d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 296d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 306d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver */ 316d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver 326d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruverpackage org.jf.util; 336d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver 346d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruverimport java.text.DecimalFormat; 356d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver 366d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruverpublic class NumberUtils { 376d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver private static final int canonicalFloatNaN = Float.floatToRawIntBits(Float.NaN); 386d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver private static final int maxFloat = Float.floatToRawIntBits(Float.MAX_VALUE); 396d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver private static final int piFloat = Float.floatToRawIntBits((float)Math.PI); 406d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver private static final int eFloat = Float.floatToRawIntBits((float)Math.E); 416d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver 426d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver private static final long canonicalDoubleNaN = Double.doubleToRawLongBits(Double.NaN); 436d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver private static final long maxDouble = Double.doubleToLongBits(Double.MAX_VALUE); 446d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver private static final long piDouble = Double.doubleToLongBits(Math.PI); 456d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver private static final long eDouble = Double.doubleToLongBits(Math.E); 466d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver 476d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver private static final DecimalFormat format = new DecimalFormat("0.####################E0"); 486d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver 496d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver public static boolean isLikelyFloat(int value) { 506d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver // Check for some common named float values 516d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver // We don't check for Float.MIN_VALUE, which has an integer representation of 1 526d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver if (value == canonicalFloatNaN || 536d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver value == maxFloat || 546d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver value == piFloat || 556d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver value == eFloat) { 566d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver return true; 576d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver } 586d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver 596d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver // Check for some named integer values 606d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver if (value == Integer.MAX_VALUE || value == Integer.MIN_VALUE) { 616d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver return false; 626d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver } 636d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver 646d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver 656d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver // Check for likely resource id 666d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver int packageId = value >> 24; 676d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver int resourceType = value >> 16 & 0xff; 686d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver int resourceId = value & 0xffff; 696d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver if ((packageId == 0x7f || packageId == 1) && resourceType < 0x1f && resourceId < 0xfff) { 706d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver return false; 716d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver } 726d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver 736d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver // a non-canocical NaN is more likely to be an integer 746d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver float floatValue = Float.intBitsToFloat(value); 756d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver if (Float.isNaN(floatValue)) { 766d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver return false; 776d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver } 786d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver 796d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver // Otherwise, whichever has a shorter scientific notation representation is more likely. 806d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver // Integer wins the tie 816d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver String asInt = format.format(value); 826d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver String asFloat = format.format(floatValue); 836d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver 846d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver // try to strip off any small imprecision near the end of the mantissa 856d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver int decimalPoint = asFloat.indexOf('.'); 866d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver int exponent = asFloat.indexOf("E"); 876d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver int zeros = asFloat.indexOf("000"); 886d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver if (zeros > decimalPoint && zeros < exponent) { 896d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver asFloat = asFloat.substring(0, zeros) + asFloat.substring(exponent); 906d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver } else { 916d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver int nines = asFloat.indexOf("999"); 926d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver if (nines > decimalPoint && nines < exponent) { 936d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver asFloat = asFloat.substring(0, nines) + asFloat.substring(exponent); 946d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver } 956d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver } 966d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver 976d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver return asFloat.length() < asInt.length(); 986d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver } 996d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver 1006d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver public static boolean isLikelyDouble(long value) { 1016d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver // Check for some common named double values 1026d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver // We don't check for Double.MIN_VALUE, which has a long representation of 1 1036d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver if (value == canonicalDoubleNaN || 1046d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver value == maxDouble || 1056d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver value == piDouble || 1066d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver value == eDouble) { 1076d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver return true; 1086d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver } 1096d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver 1106d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver // Check for some named long values 1116d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver if (value == Long.MAX_VALUE || value == Long.MIN_VALUE) { 1126d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver return false; 1136d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver } 1146d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver 1156d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver // a non-canocical NaN is more likely to be an long 1166d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver double doubleValue = Double.longBitsToDouble(value); 1176d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver if (Double.isNaN(doubleValue)) { 1186d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver return false; 1196d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver } 1206d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver 1216d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver // Otherwise, whichever has a shorter scientific notation representation is more likely. 1226d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver // Long wins the tie 1236d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver String asLong = format.format(value); 1246d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver String asDouble = format.format(doubleValue); 1256d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver 1266d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver // try to strip off any small imprecision near the end of the mantissa 1276d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver int decimalPoint = asDouble.indexOf('.'); 1286d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver int exponent = asDouble.indexOf("E"); 1296d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver int zeros = asDouble.indexOf("000"); 1306d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver if (zeros > decimalPoint && zeros < exponent) { 1316d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver asDouble = asDouble.substring(0, zeros) + asDouble.substring(exponent); 1326d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver } else { 1336d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver int nines = asDouble.indexOf("999"); 1346d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver if (nines > decimalPoint && nines < exponent) { 1356d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver asDouble = asDouble.substring(0, nines) + asDouble.substring(exponent); 1366d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver } 1376d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver } 1386d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver 1396d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver return asDouble.length() < asLong.length(); 1406d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver } 1416d607ebe1d7bccd4fdf220f0275207cb452501bdBen Gruver} 142