online compiler and debugger for c/c++

code. compile. run. debug. share.
Source Code   
Language
inline unsigned char FTOC_ARM(float a) { const float v = a < 0.0f ? 0.0f : (a > 1.0f ? 1.0f : a); return static_cast<unsigned char>(v * 255.0f); } inline unsigned char FTOC(float a) { //This value is 2^52 * 1.5. const double INT_MANTISSA = 6755399441055744.0; /* Be sure to truncate (not round) positive values. The highest value that * should be converted to 1 is roughly(1 / 256 - 0.00001); if we don't * truncate, values up to (1/256 + 0.5) will be converted to 1, which is * wrong. */ double base = double(a * 256.f - 0.5f); /* INT_MANTISSA is chosen such that, when added to a sufficiently small * double, the mantissa bits of that double can be reinterpreted as that * number rounded to an integer. This is done to improve performance. */ base += INT_MANTISSA; int ret = reinterpret_cast<int&>(base); /* Benchmarking shows that clamping here, as integers, is much faster than clamping * before the conversion, as floats. */ if (ret < 0) { return 0; } if (ret > 255) { return 255; } return static_cast<unsigned char>(ret); } inline unsigned char FTOC_union(float a) { //This value is 2^52 * 1.5. const double INT_MANTISSA = 6755399441055744.0; /* Be sure to truncate (not round) positive values. The highest value that * should be converted to 1 is roughly(1 / 256 - 0.00001); if we don't * truncate, values up to (1/256 + 0.5) will be converted to 1, which is * wrong. */ double base = double(a * 256.f - 0.5f); /* INT_MANTISSA is chosen such that, when added to a sufficiently small * double, the mantissa bits of that double can be reinterpreted as that * number rounded to an integer. This is done to improve performance. */ base += INT_MANTISSA; // union doesn't break strict aliasing rule in contrary to reinterpret cast union { double d; int i; } u; u.d = base; int ret = u.i; /* Benchmarking shows that clamping here, as integers, is much faster than clamping * before the conversion, as floats. */ if (ret < 0) { return 0; } if (ret > 255) { return 255; } return static_cast<unsigned char>(ret); } #include <algorithm> unsigned char FTOC_clamp(float a) { int value = static_cast<int>(a * 256.0f); return static_cast<unsigned char>(std::clamp(value, 0, 255)); } #include <cstdio> #include <cstring> void test(const char* fname, unsigned char (*f)(float)){ int cnts[1000]; std::memset(cnts, 0, sizeof(cnts)); printf("%s\ncnts: ", fname); for( float n = 0; n <= 1.0; n += 0.0001 ){ cnts[f(n)]++; }; for( int i = 0; i < 256; ++i ) std::printf("%i ", cnts[i]); printf("\n"); // orig comment says: /* Be sure to truncate (not round) positive values. The highest value that * should be converted to 1 is roughly(1 / 256 - 0.00001); if we don't * truncate, values up to (1/256 + 0.5) will be converted to 1, which is * wrong. */ // but does it make any sense? 1/256 ~= 0.00390625, subtracting 0.00001 would make it <0 but later we just clamp anyway float checkpoints[] = {-1.0f, -0.5f, 0.0f, 0.00001f, 0.0001f, 0.0002f, 1.0f / 256.0f - 0.00001f, 1.0f / 256.0f, 1.0f / 256.0f + 0.00001f, 1.0f / 256.0f + 0.6f, 0.5f, 0.9f, 1.0f-1.0f/256.0f, 1.0f}; for( float n: checkpoints ) printf("%f: %u, ", n, f(n)); printf("\n"); } int main() { test("FTOC", FTOC); test("FTOC ARM", FTOC_ARM); test("FTOC union", FTOC_union); test("FTOC clamp", FTOC_clamp); }

Compiling Program...

Command line arguments:
Standard Input: Interactive Console Text
×

                

                

Program is not being debugged. Click "Debug" button to start program in debug mode.

#FunctionFile:Line
VariableValue
RegisterValue
ExpressionValue