#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