/* | |
* Licensed to the Apache Software Foundation (ASF) under one or more | |
* contributor license agreements. See the NOTICE file distributed with | |
* this work for additional information regarding copyright ownership. | |
* The ASF licenses this file to You under the Apache License, Version 2.0 | |
* (the "License"); you may not use this file except in compliance with | |
* the License. You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
*/ | |
using System; | |
using NUnit.Framework; | |
namespace Lucene.Net.Util | |
{ | |
/// <author> yonik | |
/// </author> | |
/// <version> $Id$ | |
/// </version> | |
[TestFixture] | |
public class TestSmallFloat : LuceneTestCase | |
{ | |
// original lucene byteToFloat | |
internal static float Orig_byteToFloat(byte b) | |
{ | |
if (b == 0) | |
// zero is a special case | |
return 0.0f; | |
int mantissa = b & 7; | |
int exponent = (b >> 3) & 31; | |
int bits = ((exponent + (63 - 15)) << 24) | (mantissa << 21); | |
return (BitConverter.ToSingle(BitConverter.GetBytes(bits), 0)); | |
} | |
// original lucene floatToByte | |
internal static sbyte Orig_floatToByte(float f) | |
{ | |
if (f < 0.0f) | |
// round negatives up to zero | |
f = 0.0f; | |
if (f == 0.0f) | |
// zero is a special case | |
return 0; | |
int bits = BitConverter.ToInt32(BitConverter.GetBytes(f), 0); // parse float into parts | |
int mantissa = (bits & 0xffffff) >> 21; | |
int exponent = (((bits >> 24) & 0x7f) - 63) + 15; | |
if (exponent > 31) | |
{ | |
// overflow: use max value | |
exponent = 31; | |
mantissa = 7; | |
} | |
if (exponent < 0) | |
{ | |
// underflow: use min value | |
exponent = 0; | |
mantissa = 1; | |
} | |
return (sbyte) ((exponent << 3) | mantissa); // pack into a byte | |
} | |
[Test] | |
public virtual void TestByteToFloat() | |
{ | |
for (int i = 0; i < 256; i++) | |
{ | |
float f1 = Orig_byteToFloat((byte) i); | |
float f2 = SmallFloat.ByteToFloat((byte) i, 3, 15); | |
float f3 = SmallFloat.Byte315ToFloat((byte) i); | |
Assert.AreEqual(f1, f2, 0.0); | |
Assert.AreEqual(f2, f3, 0.0); | |
float f4 = SmallFloat.ByteToFloat((byte) i, 5, 2); | |
float f5 = SmallFloat.Byte52ToFloat((byte) i); | |
Assert.AreEqual(f4, f5, 0.0); | |
} | |
} | |
[Test] | |
public virtual void TestFloatToByte() | |
{ | |
System.Random rand = new System.Random((System.Int32) 0); | |
// up iterations for more exhaustive test after changing something | |
for (int i = 0; i < 100000; i++) | |
{ | |
float f = BitConverter.ToSingle(BitConverter.GetBytes(rand.Next()), 0); | |
if (f != f) | |
continue; // skip NaN | |
sbyte b1 = Orig_floatToByte(f); | |
sbyte b2 = SmallFloat.FloatToByte(f, 3, 15); | |
sbyte b3 = SmallFloat.FloatToByte315(f); | |
Assert.AreEqual(b1, b2); | |
Assert.AreEqual(b2, b3); | |
sbyte b4 = SmallFloat.FloatToByte(f, 5, 2); | |
sbyte b5 = SmallFloat.FloatToByte52(f); | |
Assert.AreEqual(b4, b5); | |
} | |
} | |
/// <summary> | |
/// // Do an exhaustive test of all possible floating point values | |
/// // for the 315 float against the original norm encoding in Similarity. | |
/// // Takes 75 seconds on my Pentium4 3GHz, with Java5 -server | |
/// public void testAllFloats() { | |
/// for(int i = Integer.MIN_VALUE;;i++) { | |
/// float f = Float.intBitsToFloat(i); | |
/// if (f==f) { // skip non-numbers | |
/// byte b1 = orig_floatToByte(f); | |
/// byte b2 = SmallFloat.floatToByte315(f); | |
/// if (b1!=b2) { | |
/// TestCase.Fail("Failed floatToByte315 for float " + f); | |
/// } | |
/// } | |
/// if (i==Integer.MAX_VALUE) break; | |
/// } | |
/// } | |
/// * | |
/// </summary> | |
} | |
} |