#include "LCSmallFloat.h" /** Floating point numbers smaller than 32 bits. */ union { float fl; int il; } udata; float IntBitsToFloat(int b) { /* LuceneKit: // Float.intBitsToFloat(bits); * Assume C follows IEEE standard. * Assum sizeof(float) == sizeof(int) == 4; */ #if 0 union { float fl; int il; } udata; #endif udata.il = b; return udata.fl; } int FloatToIntBits (float f) { /* C implement of Float.floatToIntBits() */ // Assum sizeof(float) == sizeof(int) == 4; // Assume C follows IEEE standard. #if 0 union { float fl; int il; } udata; #endif udata.fl = f; return udata.il; } @implementation LCSmallFloat /** Converts a 32 bit float to an 8 bit float. *
Values less than zero are all mapped to zero. *
Values are truncated (rounded down) to the nearest 8 bit value. *
Values between zero and the smallest representable value * are rounded up. * * @param f the 32 bit float to be converted to an 8 bit float (byte) * @param numMantissaBits the number of mantissa bits to use in the byte, with the remainder to be used in the exponent * @param zeroExp the zero-point in the range of exponent values * @return the 8 bit float representation */ + (char) floatToByte: (float) f numberOfMantissaBits: (int) numMantissaBits zeroExponent: (int) zeroExp { // Adjustment from a float zero exponent to our zero exponent, // shifted over to our exponent position. int fzero = (63-zeroExp)<> (24-numMantissaBits); if (smallfloat < fzero) { return (bits<=0) ? (char)0 // negative numbers and zero both map to 0 byte :(char)1; // underflow is mapped to smallest non-zero number. } else if (smallfloat >= fzero + 0x100) { return -1; // overflow maps to largest number } else { return (char)(smallfloat - fzero); } } /** Converts an 8 bit float to a 32 bit float. */ + (float) byteToFloat: (char) b numberOfMantissaBits: (int) numMantissaBits zeroExponent: (int) zeroExp { if (b == 0) return 0.0f; int bits = (b&0xff) << (24-numMantissaBits); bits += (63-zeroExp) << 24; return IntBitsToFloat(bits); } // // Some specializations of the generic functions follow. // The generic functions are just as fast with current (1.5) // -server JVMs, but still slower with client JVMs. // /** floatToByte(b, mantissaBits=3, zeroExponent=15) *
smallest non-zero value = 5.820766E-10 *
largest value = 7.5161928E9 *
epsilon = 0.125 */ + (char) floatToByte315: (float) f { int bits = FloatToIntBits(f); int smallfloat = bits >> (24-3); if (smallfloat < (63-15)<<3) { return (bits<=0) ? (char)0 : (char)1; } if (smallfloat >= ((63-15)<<3) + 0x100) { return -1; } return (char)(smallfloat - ((63-15)<<3)); } /** byteToFloat(b, mantissaBits=3, zeroExponent=15) */ + (float) byte315ToFloat: (char) b { if (b == 0) return 0.0f; int bits = (b&0xff) << (24-3); bits += (63-15) << 24; return IntBitsToFloat(bits); } /** floatToByte(b, mantissaBits=5, zeroExponent=2) *
smallest nonzero value = 0.033203125 *
largest value = 1984.0 *
epsilon = 0.03125 */ + (char) floatToByte52: (float) f { int bits = FloatToIntBits(f); int smallfloat = bits >> (24-5); if (smallfloat < (63-2)<<5) { return (bits<=0) ? (char)0 : (char)1; } if (smallfloat >= ((63-2)<<5) + 0x100) { return -1; } return (char)(smallfloat - ((63-2)<<5)); } /** byteToFloat(b, mantissaBits=5, zeroExponent=2) */ + (float) byte52ToFloat: (char) b { if (b == 0) return 0.0f; int bits = (b&0xff) << (24-5); bits += (63-2) << 24; return IntBitsToFloat(bits); } @end