#include <stdio.h>
#include <string.h>
#include <limits.h>
#include <assert.h>
#define C_ASSERT(expr) extern char CAssertExtern[(expr)?1:-1]
#if UINT_MAX >= 0xFFFFFFFF
typedef unsigned int uint32;
#else
typedef unsigned long uint32;
#endif
typedef unsigned long long uint64;
C_ASSERT(CHAR_BIT == 8);
C_ASSERT(sizeof(uint32) == 4);
C_ASSERT(sizeof(float) == 4);
int ProductIsOne(float f1, float f2)
{
uint32 m1, m2;
int e1, e2, s1, s2;
int e;
uint64 m;
// Make sure floats are 32-bit IEE754 and
// reinterpreted as integers as we expect
{
static const float testf = 8873283.0f;
uint32 testi;
memcpy(&testi
, &testf
, sizeof(testf
)); }
s1 = m1 >= 0x80000000;
m1 &= 0x7FFFFFFF;
e1 = m1 >> 23;
m1 &= 0x7FFFFF;
if (e1 > 0) m1 |= 0x800000;
s2 = m2 >= 0x80000000;
m2 &= 0x7FFFFFFF;
e2 = m2 >> 23;
m2 &= 0x7FFFFF;
if (e2 > 0) m2 |= 0x800000;
if (e1 == 0xFF || e2 == 0xFF || s1 != s2) // Inf, NaN, different signs
return 0;
m = (uint64)m1 * m2;
if (!m || (m & (m - 1))) // not a power of 2
return 0;
e = e1 + !e1 - 0x7F - 23 + e2 + !e2 - 0x7F - 23;
while (m > 1) m >>= 1, e++;
return e == 0;
}
const float testData[][2] =
{
{ .1f, 10.0f },
{ 0.5f, 2.0f },
{ 0.25f, 2.0f },
{ 4.0f, 0.25f },
{ 0.33333333f, 3.0f },
{ 0.00000762939453125f, 131072.0f }, // 2^-17 * 2^17
{ 1.26765060022822940E30f, 7.88860905221011805E-31f }, // 2^100 * 2^-100
};
int main(void)
{
int i;
for (i = 0; i < sizeof(testData) / sizeof(testData[0]); i++)
testData[i][0], testData[i][1],
"!="[ProductIsOne(testData[i][0], testData[i][1])]);
return 0;
}
I2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdHJpbmcuaD4KI2luY2x1ZGUgPGxpbWl0cy5oPgojaW5jbHVkZSA8YXNzZXJ0Lmg+CgojZGVmaW5lIENfQVNTRVJUKGV4cHIpIGV4dGVybiBjaGFyIENBc3NlcnRFeHRlcm5bKGV4cHIpPzE6LTFdCgojaWYgVUlOVF9NQVggPj0gMHhGRkZGRkZGRgp0eXBlZGVmIHVuc2lnbmVkIGludCB1aW50MzI7CiNlbHNlCnR5cGVkZWYgdW5zaWduZWQgbG9uZyB1aW50MzI7CiNlbmRpZgp0eXBlZGVmIHVuc2lnbmVkIGxvbmcgbG9uZyB1aW50NjQ7CgpDX0FTU0VSVChDSEFSX0JJVCA9PSA4KTsKQ19BU1NFUlQoc2l6ZW9mKHVpbnQzMikgPT0gNCk7CkNfQVNTRVJUKHNpemVvZihmbG9hdCkgPT0gNCk7CgppbnQgUHJvZHVjdElzT25lKGZsb2F0IGYxLCBmbG9hdCBmMikKewogIHVpbnQzMiBtMSwgbTI7CiAgaW50IGUxLCBlMiwgczEsIHMyOwogIGludCBlOwogIHVpbnQ2NCBtOwoKICAvLyBNYWtlIHN1cmUgZmxvYXRzIGFyZSAzMi1iaXQgSUVFNzU0IGFuZAogIC8vIHJlaW50ZXJwcmV0ZWQgYXMgaW50ZWdlcnMgYXMgd2UgZXhwZWN0CiAgewogICAgc3RhdGljIGNvbnN0IGZsb2F0IHRlc3RmID0gODg3MzI4My4wZjsKICAgIHVpbnQzMiB0ZXN0aTsKICAgIG1lbWNweSgmdGVzdGksICZ0ZXN0Ziwgc2l6ZW9mKHRlc3RmKSk7CiAgICBhc3NlcnQodGVzdGkgPT0gMHg0QjA3NjU0Myk7CiAgfQoKICBtZW1jcHkoJm0xLCAmZjEsIHNpemVvZihmMSkpOwogIHMxID0gbTEgPj0gMHg4MDAwMDAwMDsKICBtMSAmPSAweDdGRkZGRkZGOwogIGUxID0gbTEgPj4gMjM7CiAgbTEgJj0gMHg3RkZGRkY7CiAgaWYgKGUxID4gMCkgbTEgfD0gMHg4MDAwMDA7CgogIG1lbWNweSgmbTIsICZmMiwgc2l6ZW9mKGYyKSk7CiAgczIgPSBtMiA+PSAweDgwMDAwMDAwOwogIG0yICY9IDB4N0ZGRkZGRkY7CiAgZTIgPSBtMiA+PiAyMzsKICBtMiAmPSAweDdGRkZGRjsKICBpZiAoZTIgPiAwKSBtMiB8PSAweDgwMDAwMDsKCiAgaWYgKGUxID09IDB4RkYgfHwgZTIgPT0gMHhGRiB8fCBzMSAhPSBzMikgLy8gSW5mLCBOYU4sIGRpZmZlcmVudCBzaWducwogICAgcmV0dXJuIDA7CgogIG0gPSAodWludDY0KW0xICogbTI7CgogIGlmICghbSB8fCAobSAmIChtIC0gMSkpKSAvLyBub3QgYSBwb3dlciBvZiAyCiAgICByZXR1cm4gMDsKCiAgZSA9IGUxICsgIWUxIC0gMHg3RiAtIDIzICsgZTIgKyAhZTIgLSAweDdGIC0gMjM7CiAgd2hpbGUgKG0gPiAxKSBtID4+PSAxLCBlKys7CgogIHJldHVybiBlID09IDA7Cn0KCmNvbnN0IGZsb2F0IHRlc3REYXRhW11bMl0gPQp7CiAgeyAuMWYsIDEwLjBmIH0sCiAgeyAwLjVmLCAyLjBmIH0sCiAgeyAwLjI1ZiwgMi4wZiB9LAogIHsgNC4wZiwgMC4yNWYgfSwKICB7IDAuMzMzMzMzMzNmLCAzLjBmIH0sCiAgeyAwLjAwMDAwNzYyOTM5NDUzMTI1ZiwgMTMxMDcyLjBmIH0sIC8vIDJeLTE3ICogMl4xNwogIHsgMS4yNjc2NTA2MDAyMjgyMjk0MEUzMGYsIDcuODg4NjA5MDUyMjEwMTE4MDVFLTMxZiB9LCAvLyAyXjEwMCAqIDJeLTEwMAp9OwoKaW50IG1haW4odm9pZCkKewogIGludCBpOwogIGZvciAoaSA9IDA7IGkgPCBzaXplb2YodGVzdERhdGEpIC8gc2l6ZW9mKHRlc3REYXRhWzBdKTsgaSsrKQogICAgcHJpbnRmKCIlZyAqICVnICVjPSAxXG4iLAogICAgICAgICAgIHRlc3REYXRhW2ldWzBdLCB0ZXN0RGF0YVtpXVsxXSwKICAgICAgICAgICAiIT0iW1Byb2R1Y3RJc09uZSh0ZXN0RGF0YVtpXVswXSwgdGVzdERhdGFbaV1bMV0pXSk7CiAgcmV0dXJuIDA7Cn0K