Blob Blame History Raw
#include <testBitPatterns.h>
#include "half.h"
#include <float.h>
#include <iostream>
#include <string.h>
#include <assert.h>


using namespace std;

namespace {

bool
equalBitPatterns (const char *b1, const char *b2)
{
    //
    // Returns true if the characters in zero-terminated string b1
    // are the same as the charaters in string b2, except for places
    // where b1 or b2 contains an 'X'.  For example:
    //
    //	equalBitPatterns ("100", "100") returns true
    //	equalBitPatterns ("100", "101") returns false
    //	equalBitPatterns ("10X", "101") returns true
    //	equalBitPatterns ("10X", "100") returns true
    //

    while (*b1 && *b2)
    {
	if (*b1 != *b2 && *b1 != 'X' && *b2 != 'X')
	    return false;

	++b1;
	++b2;
    }

    return !(*b1 || *b2);
}


void
testBits (float f, const char bh[19], const char bg[35])
{
    half  h (f);
    float g (h);

    cout.width (15);
    cout.precision (8);
    cout << f << "    ";
    printBits (cout, f);
    cout << "    ";
    printBits (cout, h);
    cout << '\n';
    cout.width (15);
    cout << g << "    ";
    printBits (cout, g);
    cout << "\n\n";

    if (bh || bg)
    {
	char ch[19], cg[35];

	printBits (ch, h);
	printBits (cg, g);

	if (!equalBitPatterns (ch, bh))
	{
	    cout << "error: expected " << bh << ", got " << ch << endl;
	    assert (false);
	}

	if (!equalBitPatterns (cg, bg))
	{
	    cout << "error: expected " << bg << ", got " << cg << endl;
	    assert (false);
	}
    }
}


float
floatPosInfinity ()
{
    half::uif x;
    x.i = 0x7f800000;
    return x.f;
}


float
floatNegInfinity ()
{
    half::uif x;
    x.i = 0xff800000;
    return x.f;
}


float
floatPosQNan1 ()
{
    half::uif x;
    x.i = 0x7fffffff;
    return x.f;
}


float
floatNegQNan1 ()
{
    half::uif x;
    x.i = 0xffffffff;
    return x.f;
}


float
floatPosQNan2 ()
{
    half::uif x;
    x.i = 0x7fd55555;
    return x.f;
}


float
floatNegQNan2 ()
{
    half::uif x;
    x.i = 0xffd55555;
    return x.f;
}

} // namespace


void
testBitPatterns()
{
    cout << "specific bit patterns\n\n";

    //
    // Numbers close to 1.0
    //

    testBits (1.0f,
	      "0 01111 0000000000",
	      "0 01111111 00000000000000000000000");
    testBits (1.0f + HALF_EPSILON,
	      "0 01111 0000000001",
	      "0 01111111 00000000010000000000000");
    testBits (1.0f + HALF_EPSILON * 0.5f,
	      "0 01111 0000000000",
	      "0 01111111 00000000000000000000000");
    testBits (1.0f+ HALF_EPSILON * 0.4999f,
	      "0 01111 0000000000",
	      "0 01111111 00000000000000000000000");
    testBits (1.0f + HALF_EPSILON * 0.5001f,
	      "0 01111 0000000001",
	      "0 01111111 00000000010000000000000");
    testBits (1.0f + HALF_EPSILON + HALF_EPSILON,
	      "0 01111 0000000010",
	      "0 01111111 00000000100000000000000");
    testBits (1.0f + HALF_EPSILON + HALF_EPSILON * 0.5f,
	      "0 01111 0000000010",
	      "0 01111111 00000000100000000000000");
    testBits (1.0f + HALF_EPSILON + HALF_EPSILON * 0.4999f,
	      "0 01111 0000000001",
	      "0 01111111 00000000010000000000000");
    testBits (1.0f + HALF_EPSILON + HALF_EPSILON * 0.5001f,
	      "0 01111 0000000010",
	      "0 01111111 00000000100000000000000");
    testBits (1.0f - HALF_EPSILON * 0.5f,
	      "0 01110 1111111111",
	      "0 01111110 11111111110000000000000");
    testBits (1.0f - HALF_EPSILON * 0.5f * 0.5f,
	      "0 01111 0000000000",
	      "0 01111111 00000000000000000000000");
    testBits (1.0f - HALF_EPSILON * 0.5f * 0.4999f,
	      "0 01111 0000000000",
	      "0 01111111 00000000000000000000000");
    testBits (1.0f - HALF_EPSILON * 0.5f * 0.5001f,
	      "0 01110 1111111111",
	      "0 01111110 11111111110000000000000");

    //
    // Numbers close to HALF_MIN
    //

    testBits (HALF_MIN,
	      "0 00000 0000000001",
	      "0 01100111 00000000000000000000000");
    testBits (HALF_MIN + HALF_MIN,
	      "0 00000 0000000010",
	      "0 01101000 00000000000000000000000");
    testBits (HALF_MIN + HALF_MIN * 0.5f,
	      "0 00000 0000000010",
	      "0 01101000 00000000000000000000000");
    testBits (HALF_MIN + HALF_MIN * 0.4999f,
	      "0 00000 0000000001",
	      "0 01100111 00000000000000000000000");
    testBits (HALF_MIN + HALF_MIN * 0.5001f,
	      "0 00000 0000000010",
	      "0 01101000 00000000000000000000000");
    testBits (HALF_MIN - HALF_MIN,
	      "0 00000 0000000000",
	      "0 00000000 00000000000000000000000");
    testBits (HALF_MIN - HALF_MIN * 0.5f,
	      "0 00000 0000000000",
	      "0 00000000 00000000000000000000000");
    testBits (HALF_MIN - HALF_MIN * 0.4999f,
	      "0 00000 0000000001",
	      "0 01100111 00000000000000000000000");
    testBits (HALF_MIN - HALF_MIN * 0.5001f,
	      "0 00000 0000000000",
	      "0 00000000 00000000000000000000000");

    //
    // Numbers close to HALF_NRM_MIN
    //

    testBits (HALF_NRM_MIN,
	      "0 00001 0000000000",
	      "0 01110001 00000000000000000000000");
    testBits (HALF_NRM_MIN + HALF_MIN,
	      "0 00001 0000000001",
	      "0 01110001 00000000010000000000000");
    testBits (HALF_NRM_MIN + HALF_MIN * 0.5f,
	      "0 00001 0000000000",
	      "0 01110001 00000000000000000000000");
    testBits (HALF_NRM_MIN + HALF_MIN * 0.4999f,
	      "0 00001 0000000000",
	      "0 01110001 00000000000000000000000");
    testBits (HALF_NRM_MIN + HALF_MIN * 0.5001f,
	      "0 00001 0000000001",
	      "0 01110001 00000000010000000000000");
    testBits (HALF_NRM_MIN - HALF_MIN,
	      "0 00000 1111111111",
	      "0 01110000 11111111100000000000000");
    testBits (HALF_NRM_MIN - HALF_MIN * 0.5f,
	      "0 00001 0000000000",
	      "0 01110001 00000000000000000000000");
    testBits (HALF_NRM_MIN - HALF_MIN * 0.49995f,
	      "0 00001 0000000000",
	      "0 01110001 00000000000000000000000");
    testBits (HALF_NRM_MIN - HALF_MIN * 0.50005f,
	      "0 00000 1111111111",
	      "0 01110000 11111111100000000000000");

    //
    // Small positive integers and simple decimal fractions
    //

    testBits (2,
	      "0 10000 0000000000",
	      "0 10000000 00000000000000000000000");
    testBits (3,
	      "0 10000 1000000000",
	      "0 10000000 10000000000000000000000");
    testBits (10,
	      "0 10010 0100000000",
	      "0 10000010 01000000000000000000000");
    testBits (0.1f,
	      "0 01011 1001100110",
	      "0 01111011 10011001100000000000000");
    testBits (0.2f,
	      "0 01100 1001100110",
	      "0 01111100 10011001100000000000000");
    testBits (0.3f,
	      "0 01101 0011001101",
	      "0 01111101 00110011010000000000000");

    //
    // Numbers close to HALF_MAX
    //

    testBits (HALF_MAX,
	      "0 11110 1111111111",
	      "0 10001110 11111111110000000000000");
    testBits ((1 << HALF_MAX_EXP) * 1.0,
	      "0 11111 0000000000",			// +infinity
	      "0 11111111 00000000000000000000000");	// +infinity
    testBits ((1 << HALF_MAX_EXP) * (1.0f - HALF_EPSILON * 0.25f),
	      "0 11111 0000000000",			// +infinity
	      "0 11111111 00000000000000000000000");	// +infinity
    testBits ((1 << HALF_MAX_EXP) * (1.0f - HALF_EPSILON * 0.25005f),
	      "0 11110 1111111111",
	      "0 10001110 11111111110000000000000");
    testBits ((1 << HALF_MAX_EXP) * (1.0f - HALF_EPSILON * 0.24995f),
	      "0 11111 0000000000",			// +infinity
	      "0 11111111 00000000000000000000000");	// +infinity

    //
    // Large positive numbers, positive infinity and NANs
    //

    testBits (HALF_MAX * HALF_MAX,
	      "0 11111 0000000000",			// +infinity
	      "0 11111111 00000000000000000000000");	// +infinity
    testBits (FLT_MAX,
	      "0 11111 0000000000",			// +infinity
	      "0 11111111 00000000000000000000000");	// +infinity
    testBits (floatPosInfinity(),
	      "0 11111 0000000000",			// +infinity
	      "0 11111111 00000000000000000000000");	// +infinity
    testBits (floatPosQNan1(),
	      "0 11111 1111111111",			// nan
	      "0 11111111 11111111110000000000000");	// nan
    testBits (floatPosQNan2(),
	      "0 11111 1010101010",			// nan
	      "0 11111111 10101010100000000000000");	// nan

    //
    // Numbers close to -1.0
    //

    testBits (-1.0,
	      "1 01111 0000000000",
	      "1 01111111 00000000000000000000000");
    testBits (-(1.0f + HALF_EPSILON),
	      "1 01111 0000000001",
	      "1 01111111 00000000010000000000000");
    testBits (-(1.0f + HALF_EPSILON * 0.5f),
	      "1 01111 0000000000",
	      "1 01111111 00000000000000000000000");
    testBits (-(1.0f + HALF_EPSILON * 0.4999f),
	      "1 01111 0000000000",
	      "1 01111111 00000000000000000000000");
    testBits (-(1.0f + HALF_EPSILON * 0.5001f),
	      "1 01111 0000000001",
	      "1 01111111 00000000010000000000000");
    testBits (-(1.0f + HALF_EPSILON + HALF_EPSILON),
	      "1 01111 0000000010",
	      "1 01111111 00000000100000000000000");
    testBits (-(1.0f + HALF_EPSILON + HALF_EPSILON * 0.5f),
	      "1 01111 0000000010",
	      "1 01111111 00000000100000000000000");
    testBits (-(1.0f + HALF_EPSILON + HALF_EPSILON * 0.4999f),
	      "1 01111 0000000001",
	      "1 01111111 00000000010000000000000");
    testBits (-(1.0f + HALF_EPSILON + HALF_EPSILON * 0.5001f),
	      "1 01111 0000000010",
	      "1 01111111 00000000100000000000000");
    testBits (-(1.0f - HALF_EPSILON * 0.5f),
	      "1 01110 1111111111",
	      "1 01111110 11111111110000000000000");
    testBits (-(1.0f - HALF_EPSILON * 0.5f * 0.5f),
	      "1 01111 0000000000",
	      "1 01111111 00000000000000000000000");
    testBits (-(1.0f - HALF_EPSILON * 0.5f * 0.4999f),
	      "1 01111 0000000000",
	      "1 01111111 00000000000000000000000");
    testBits (-(1.0f - HALF_EPSILON * 0.5f * 0.5001f),
	      "1 01110 1111111111",
	      "1 01111110 11111111110000000000000");

    //
    // Numbers close to -HALF_MIN
    //

    testBits (-HALF_MIN,
	      "1 00000 0000000001",
	      "1 01100111 00000000000000000000000");
    testBits (-(HALF_MIN + HALF_MIN),
	      "1 00000 0000000010",
	      "1 01101000 00000000000000000000000");
    testBits (-(HALF_MIN + HALF_MIN * 0.5f),
	      "1 00000 0000000010",
	      "1 01101000 00000000000000000000000");
    testBits (-(HALF_MIN + HALF_MIN * 0.4999f),
	      "1 00000 0000000001",
	      "1 01100111 00000000000000000000000");
    testBits (-(HALF_MIN + HALF_MIN * 0.5001f),
	      "1 00000 0000000010",
	      "1 01101000 00000000000000000000000");
    testBits (-(HALF_MIN - HALF_MIN),
	      "X 00000 0000000000",
	      "X 00000000 00000000000000000000000");
    testBits (-(HALF_MIN - HALF_MIN * 0.5f),
	      "1 00000 0000000000",
	      "1 00000000 00000000000000000000000");
    testBits (-(HALF_MIN - HALF_MIN * 0.4999f),
	      "1 00000 0000000001",
	      "1 01100111 00000000000000000000000");
    testBits (-(HALF_MIN - HALF_MIN * 0.5001f),
	      "1 00000 0000000000",
	      "1 00000000 00000000000000000000000");

    //
    // Numbers close to -HALF_NRM_MIN
    //

    testBits (-HALF_NRM_MIN,
	      "1 00001 0000000000",
	      "1 01110001 00000000000000000000000");
    testBits (-(HALF_NRM_MIN + HALF_MIN),
	      "1 00001 0000000001",
	      "1 01110001 00000000010000000000000");
    testBits (-(HALF_NRM_MIN + HALF_MIN * 0.5f),
	      "1 00001 0000000000",
	      "1 01110001 00000000000000000000000");
    testBits (-(HALF_NRM_MIN + HALF_MIN * 0.4999f),
	      "1 00001 0000000000",
	      "1 01110001 00000000000000000000000");
    testBits (-(HALF_NRM_MIN + HALF_MIN * 0.5001f),
	      "1 00001 0000000001",
	      "1 01110001 00000000010000000000000");
    testBits (-(HALF_NRM_MIN - HALF_MIN),
	      "1 00000 1111111111",
	      "1 01110000 11111111100000000000000");
    testBits (-(HALF_NRM_MIN - HALF_MIN * 0.5f),
	      "1 00001 0000000000",
	      "1 01110001 00000000000000000000000");
    testBits (-(HALF_NRM_MIN - HALF_MIN * 0.49995f),
	      "1 00001 0000000000",
	      "1 01110001 00000000000000000000000");
    testBits (-(HALF_NRM_MIN - HALF_MIN * 0.50005f),
	      "1 00000 1111111111",
	      "1 01110000 11111111100000000000000");

    //
    // Small negative integers and simple decimal fractions
    //

    testBits (-2,
	      "1 10000 0000000000",
	      "1 10000000 00000000000000000000000");
    testBits (-3,
	      "1 10000 1000000000",
	      "1 10000000 10000000000000000000000");
    testBits (-10,
	      "1 10010 0100000000",
	      "1 10000010 01000000000000000000000");
    testBits (-0.1f,
	      "1 01011 1001100110",
	      "1 01111011 10011001100000000000000");
    testBits (-0.2f,
	      "1 01100 1001100110",
	      "1 01111100 10011001100000000000000");
    testBits (-0.3f,
	      "1 01101 0011001101",
	      "1 01111101 00110011010000000000000");

    //
    // Numbers close to -HALF_MAX
    //

    testBits (-HALF_MAX,
	      "1 11110 1111111111",
	      "1 10001110 11111111110000000000000");
    testBits (-(1 << HALF_MAX_EXP) * 1.0f,
	      "1 11111 0000000000",			// +infinity
	      "1 11111111 00000000000000000000000");	// +infinity
    testBits (-(1 << HALF_MAX_EXP) * (1.0f - HALF_EPSILON * 0.25f),
	      "1 11111 0000000000",			// +infinity
	      "1 11111111 00000000000000000000000");	// +infinity
    testBits (-(1 << HALF_MAX_EXP) * (1.0f - HALF_EPSILON * 0.25005f),
	      "1 11110 1111111111",
	      "1 10001110 11111111110000000000000");
    testBits (-(1 << HALF_MAX_EXP) * (1.0f - HALF_EPSILON * 0.24995f),
	      "1 11111 0000000000",			// +infinity
	      "1 11111111 00000000000000000000000");	// +infinity

    //
    // Large negative numbers, negative infinity and NANs
    //

    testBits (-HALF_MAX * HALF_MAX,
	      "1 11111 0000000000",			// +infinity
	      "1 11111111 00000000000000000000000");	// +infinity
    testBits (-FLT_MAX,
	      "1 11111 0000000000",			// +infinity
	      "1 11111111 00000000000000000000000");	// +infinity
    testBits (floatNegInfinity(),
	      "1 11111 0000000000",			// +infinity
	      "1 11111111 00000000000000000000000");	// +infinity
    testBits (floatNegQNan1(),
	      "1 11111 1111111111",			// nan
	      "1 11111111 11111111110000000000000");	// nan
    testBits (floatNegQNan2(),
	      "1 11111 1010101010",			// nan
	      "1 11111111 10101010100000000000000");	// nan

    cout << "ok\n\n" << flush;
}