Last active
July 25, 2018 18:39
-
-
Save SmallJoker/bb655b4425ab539587dd9b89ad756196 to your computer and use it in GitHub Desktop.
Test script to measure different methods of eoncoding and decoding floats over the network
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <cmath> | |
#include <cstdint> | |
#include <cstring> | |
#include <iostream> | |
#include <iomanip> | |
#include <chrono> | |
#include <cassert> | |
typedef uint8_t u8; | |
typedef int8_t s8; | |
typedef uint32_t u32; | |
typedef int32_t s32; | |
typedef float f32; | |
inline u32 readU32(const u8 *data) | |
{ | |
return | |
((u32)data[0] << 24) | ((u32)data[1] << 16) | | |
((u32)data[2] << 8) | ((u32)data[3] << 0); | |
} | |
inline void writeU32(u8 *data, u32 i) | |
{ | |
data[0] = (i >> 24) & 0xFF; | |
data[1] = (i >> 16) & 0xFF; | |
data[2] = (i >> 8) & 0xFF; | |
data[3] = (i >> 0) & 0xFF; | |
} | |
// Method: log2 | |
inline f32 readF32_log(const u8 *data) | |
{ | |
const u32 v = readU32(data); | |
u32 fraction_i = v & 0xFFFFFF; | |
u32 exponent_i = v >> 24; | |
// Correct negative number notation | |
if (v & 0x00800000) | |
fraction_i |= 0xFF000000; | |
float fraction = (s32)fraction_i / (float)0x800000; | |
/* | |
In contrast to the scientific notation, frexp return values in | |
the range of [0.5;1.0[ or ]-1.0;0.5]. This results in a (by 1) | |
higher exponent. To have correct signed number handling for the | |
exponent 128, it is decreased by 1 over the network. | |
*/ | |
return ldexp(fraction, (s8)exponent_i + 1); | |
} | |
inline void writeF32_log(u8 *data, f32 i) | |
{ | |
assert(!std::isnan(i) && !std::isinf(i)); | |
float fraction; | |
int exponent; | |
fraction = frexp(i, &exponent) * 0x800000; | |
// [x...x...][x...x...x...x...x...x...] | |
// EXPONENT MANTISSA (24 bits) | |
u32 dat = (u32)(exponent - 1) << 24 | ((u32)fraction & 0xFFFFFF); | |
writeU32(data, dat); | |
} | |
#define LOGGING | |
int main() | |
{ | |
f32 tests[] = { | |
0.f, 1.f, -1.f, | |
0.1f, -0.1f, | |
1945329.2634, | |
-23298764.315, | |
0.5f, -0.5f, | |
//1/0.0f, -1/0.0f, // inf, -inf | |
//0.0f/0.0f, | |
1.1755E-38, 3.4028E38, // positive | |
-1.1755E-38, -3.4028E38 // negative | |
}; | |
u8 data[4]; | |
auto start = std::chrono::steady_clock::now(); | |
for (f32 input : tests) { | |
memset(data, 0, 4); | |
writeF32_log(data, input); | |
f32 output = readF32_log(data); | |
#ifdef LOGGING | |
float error_ppm = output == input ? 0 : | |
(std::max(output / input, input / output) - 1) * 1.0E6; | |
printf("In=%-+17.17E Out=%-+17.17E Error=%-+15f\n", input, output, error_ppm); | |
#endif | |
} | |
auto end = std::chrono::steady_clock::now(); | |
std::cout << "Execution time: " << std::chrono::duration<double, std::micro> | |
(end - start).count() << " us" << std::endl; | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment