001: package org.apache.lucene.util;
002:
003: /**
004: * Copyright 2005 The Apache Software Foundation
005: *
006: * Licensed under the Apache License, Version 2.0 (the "License");
007: * you may not use this file except in compliance with the License.
008: * You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing, software
013: * distributed under the License is distributed on an "AS IS" BASIS,
014: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: * See the License for the specific language governing permissions and
016: * limitations under the License.
017: */
018:
019: /** Floating point numbers smaller than 32 bits.
020: *
021: * @author yonik
022: * @version $Id$
023: */
024: public class SmallFloat {
025:
026: /** Converts a 32 bit float to an 8 bit float.
027: * <br>Values less than zero are all mapped to zero.
028: * <br>Values are truncated (rounded down) to the nearest 8 bit value.
029: * <br>Values between zero and the smallest representable value
030: * are rounded up.
031: *
032: * @param f the 32 bit float to be converted to an 8 bit float (byte)
033: * @param numMantissaBits the number of mantissa bits to use in the byte, with the remainder to be used in the exponent
034: * @param zeroExp the zero-point in the range of exponent values
035: * @return the 8 bit float representation
036: */
037: public static byte floatToByte(float f, int numMantissaBits,
038: int zeroExp) {
039: // Adjustment from a float zero exponent to our zero exponent,
040: // shifted over to our exponent position.
041: int fzero = (63 - zeroExp) << numMantissaBits;
042: int bits = Float.floatToRawIntBits(f);
043: int smallfloat = bits >> (24 - numMantissaBits);
044: if (smallfloat < fzero) {
045: return (bits <= 0) ? (byte) 0 // negative numbers and zero both map to 0 byte
046: : (byte) 1; // underflow is mapped to smallest non-zero number.
047: } else if (smallfloat >= fzero + 0x100) {
048: return -1; // overflow maps to largest number
049: } else {
050: return (byte) (smallfloat - fzero);
051: }
052: }
053:
054: /** Converts an 8 bit float to a 32 bit float. */
055: public static float byteToFloat(byte b, int numMantissaBits,
056: int zeroExp) {
057: // on Java1.5 & 1.6 JVMs, prebuilding a decoding array and doing a lookup
058: // is only a little bit faster (anywhere from 0% to 7%)
059: if (b == 0)
060: return 0.0f;
061: int bits = (b & 0xff) << (24 - numMantissaBits);
062: bits += (63 - zeroExp) << 24;
063: return Float.intBitsToFloat(bits);
064: }
065:
066: //
067: // Some specializations of the generic functions follow.
068: // The generic functions are just as fast with current (1.5)
069: // -server JVMs, but still slower with client JVMs.
070: //
071:
072: /** floatToByte(b, mantissaBits=3, zeroExponent=15)
073: * <br>smallest non-zero value = 5.820766E-10
074: * <br>largest value = 7.5161928E9
075: * <br>epsilon = 0.125
076: */
077: public static byte floatToByte315(float f) {
078: int bits = Float.floatToRawIntBits(f);
079: int smallfloat = bits >> (24 - 3);
080: if (smallfloat < (63 - 15) << 3) {
081: return (bits <= 0) ? (byte) 0 : (byte) 1;
082: }
083: if (smallfloat >= ((63 - 15) << 3) + 0x100) {
084: return -1;
085: }
086: return (byte) (smallfloat - ((63 - 15) << 3));
087: }
088:
089: /** byteToFloat(b, mantissaBits=3, zeroExponent=15) */
090: public static float byte315ToFloat(byte b) {
091: // on Java1.5 & 1.6 JVMs, prebuilding a decoding array and doing a lookup
092: // is only a little bit faster (anywhere from 0% to 7%)
093: if (b == 0)
094: return 0.0f;
095: int bits = (b & 0xff) << (24 - 3);
096: bits += (63 - 15) << 24;
097: return Float.intBitsToFloat(bits);
098: }
099:
100: /** floatToByte(b, mantissaBits=5, zeroExponent=2)
101: * <br>smallest nonzero value = 0.033203125
102: * <br>largest value = 1984.0
103: * <br>epsilon = 0.03125
104: */
105: public static byte floatToByte52(float f) {
106: int bits = Float.floatToRawIntBits(f);
107: int smallfloat = bits >> (24 - 5);
108: if (smallfloat < (63 - 2) << 5) {
109: return (bits <= 0) ? (byte) 0 : (byte) 1;
110: }
111: if (smallfloat >= ((63 - 2) << 5) + 0x100) {
112: return -1;
113: }
114: return (byte) (smallfloat - ((63 - 2) << 5));
115: }
116:
117: /** byteToFloat(b, mantissaBits=5, zeroExponent=2) */
118: public static float byte52ToFloat(byte b) {
119: // on Java1.5 & 1.6 JVMs, prebuilding a decoding array and doing a lookup
120: // is only a little bit faster (anywhere from 0% to 7%)
121: if (b == 0)
122: return 0.0f;
123: int bits = (b & 0xff) << (24 - 5);
124: bits += (63 - 2) << 24;
125: return Float.intBitsToFloat(bits);
126: }
127: }
|