Skip to content

Instantly share code, notes, and snippets.

@SmallJoker
Last active July 25, 2018 18:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SmallJoker/bb655b4425ab539587dd9b89ad756196 to your computer and use it in GitHub Desktop.
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
#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