/* * Copyright 1999-2002 Carnegie Mellon University. * Portions Copyright 2002 Sun Microsystems, Inc. * Portions Copyright 2002 Mitsubishi Electric Research Laboratories. * All Rights Reserved. Use is subject to license terms. * * See the file "license.terms" for information on usage and * redistribution of this file, and for a DISCLAIMER OF ALL * WARRANTIES. * */ package edu.cmu.sphinx.util; import java.io.*; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.List; /** Provides a set of generic utilities */ public class Utilities { private final static boolean TRACKING_OBJECTS = false; // Unconstructable. private Utilities() { } /** * Returns a string with the given number of spaces. * * @param padding the number of spaces in the string * @return a string of length 'padding' containing only the SPACE char. */ public static String pad(int padding) { if (padding > 0) { StringBuilder sb = new StringBuilder(padding); for (int i = 0; i < padding; i++) { sb.append(' '); } return sb.toString(); } else { return ""; } } /** * Pads with spaces or truncates the given string to guarantee that it is exactly the desired length. * * @param string the string to be padded * @param minLength the desired length of the string * @return a string of length containing string padded with whitespace or truncated */ public static String pad(String string, int minLength) { String result = string; int pad = minLength - string.length(); if (pad > 0) { result = string + pad(minLength - string.length()); } else if (pad < 0) { result = string.substring(0, minLength); } return result; } /** * Pads with spaces or truncates the given int to guarantee that it is exactly the desired length. * * @param val the value to be padded * @param minLength the desired length of the string * @return a string of length containing string padded with whitespace or truncated */ public static String pad(int val, int minLength) { return pad(String.valueOf(val), minLength); } /** * Pads with spaces or truncates the given double to guarantee that it is exactly the desired length. * * @param val the value to be padded * @param minLength the desired length of the string * @return a string of length containing string padded with whitespace or truncated */ public static String pad(double val, int minLength) { return pad(String.valueOf(val), minLength); } /** * Dumps padded text. This is a simple tool for helping dump text with padding to a Writer. * * @param pw the stream to send the output * @param padding the number of spaces in the string * @param string the string to output */ public static void dump(PrintWriter pw, int padding, String string) { pw.print(pad(padding)); pw.println(string); } /** * utility method for tracking object counts * * @param name the name of the object * @param count the count of objects */ public static void objectTracker(String name, int count) { if (TRACKING_OBJECTS) { if (count % 1000 == 0) { System.out.println("OT: " + name + ' ' + count); } } } static long maxUsed; /** * Dumps out memory information * * @param msg addditional text for the dump */ public static void dumpMemoryInfo(String msg) { Runtime rt = Runtime.getRuntime(); long free = rt.freeMemory(); rt.gc(); long reclaimedMemory = (rt.freeMemory() - free) / (1024 * 1024); long freeMemory = rt.freeMemory() / (1024 * 1024); long totalMemory = rt.totalMemory() / (1024 * 1024); long usedMemory = rt.totalMemory() - rt.freeMemory(); if (usedMemory > maxUsed) { maxUsed = usedMemory; } System.out.println("Memory (mb) " + " total: " + totalMemory + " reclaimed: " + reclaimedMemory + " free: " + freeMemory + " Max Used: " + (maxUsed / (1024 * 1024)) + " -- " + msg); } /** * Returns the string representation of the given double value in normalized scientific notation. The * <code>fractionDigits</code> argument gives the number of decimal digits in the fraction portion. For example, if * <code>fractionDigits</code> is 4, then the 123450 will be "1.2345e+05". There will always be two digits in the * exponent portion, and a plus or minus sign before the exponent. * * @param number the double to convert * @param fractionDigits the number of digits in the fraction part, e.g., 4 in "1.2345e+05". * @return the string representation of the double in scientific notation */ public static String doubleToScientificString(double number, int fractionDigits) { DecimalFormat format = new DecimalFormat(); StringBuilder formatter = new StringBuilder(5 + fractionDigits).append("0."); for (int i = 0; i < fractionDigits; i++) { formatter.append('0'); } formatter.append("E00"); format.applyPattern(formatter.toString()); String formatted = format.format(number); int index = formatted.indexOf('E'); if (formatted.charAt(index + 1) != '-') { return formatted.substring(0, index + 1) + '+' + formatted.substring(index + 1); } else { return formatted; } } /** * Returns true if the given binary cepstra file is in big-endian format. It assumes that the first 4 bytes of the * file tells you how many 4-byte floating point cepstra values are in the file. * * @param filename the cepstra file name * @return true if the given binary cepstra file is big-endian * @throws IOException if something went wrong */ public static boolean isCepstraFileBigEndian(String filename) throws IOException { File cepstraFile = new File(filename); int fileSize = (int) cepstraFile.length(); DataInputStream stream = new DataInputStream(new FileInputStream(filename)); int numberBytes = stream.readInt() * 4 + 4; stream.close(); return (fileSize == numberBytes); } /** * Reads the next float from the given DataInputStream, where the data is in little endian. * * @param dataStream the DataInputStream to read from * @return a float * @throws IOException if something went wrong */ public static float readLittleEndianFloat(DataInputStream dataStream) throws IOException { return Float.intBitsToFloat(readLittleEndianInt(dataStream)); } /** * Reads the next little-endian integer from the given DataInputStream. * * @param dataStream the DataInputStream to read from * @return an integer * @throws IOException if something went wrong */ public static int readLittleEndianInt(DataInputStream dataStream) throws IOException { return dataStream.readUnsignedByte() | dataStream.readUnsignedByte() << 8 | dataStream.readUnsignedByte() << 16 | dataStream.readUnsignedByte() << 24; } /** * Byte-swaps the given integer to the other endian. That is, if this integer is big-endian, it becomes * little-endian, and vice-versa. * * @param integer the integer to swap * @return swapped integer */ public static int swapInteger(int integer) { return (((0x000000ff & integer) << 24) | ((0x0000ff00 & integer) << 8) | ((0x00ff0000 & integer) >> 8) | ((0xff000000 & integer) >> 24)); } /** * Byte-swaps the given float to the other endian. That is, if this float is big-endian, it becomes little-endian, * and vice-versa. * * @param floatValue the float to swap * @return swapped float */ public static float swapFloat(float floatValue) { return Float.intBitsToFloat (swapInteger(Float.floatToRawIntBits(floatValue))); } /** * If a data point is below 'floor' make it equal to floor. * * @param data the data to floor * @param floor the floored value */ public static void floorData(float[] data, float floor) { for (int i = 0; i < data.length; i++) { if (data[i] < floor) { data[i] = floor; } } } /** * If a data point is non-zero and below 'floor' make it equal to floor * (don't floor zero values though). * * @param data the data to floor * @param floor the floored value */ public static void nonZeroFloor(float[] data, float floor) { for (int i = 0; i < data.length; i++) { if (data[i] != 0.0 && data[i] < floor) { data[i] = floor; } } } /** * Normalize the given data. * * @param data the data to normalize */ public static void normalize(float[] data) { float sum = 0; for (float val : data) { sum += val; } if (sum != 0.0f) { for (int i = 0; i < data.length; i++) { data[i] = data[i] / sum; } } } public static String join(List<String> tokens) { StringBuilder builder = new StringBuilder(); for (String token : tokens) { builder.append(token); builder.append(' '); } return builder.toString().trim(); } public static List<Integer> asList(int[] align) { ArrayList<Integer> result = new ArrayList<Integer>(align.length); for (int i : align) { result.add(i); } return result; } /** * Combines two paths without too much logic only cares about avoiding * double backslashes since they hurt some resource searches. * * @param path1 First path to join * @param path2 Second path to join * @return combined path */ public static String pathJoin(String path1, String path2) { if (path1.length() > 0 && path1.charAt(path1.length() - 1) == '/') { path1 = path1.substring(0, path1.length() - 1); } if (path2.length() > 0 && path2.charAt(0) == '/') { path2 = path2.substring(1); } return path1 + "/" + path2; } }