部分来自 ncnn
// window 平台
#include <windows.h>
double get_current_time()
{
LARGE_INTEGER freq; // 频率
LARGE_INTEGER pc; // 计数
QueryPerformanceFrequency(&freq);
QueryPerformanceCounter(&pc);
return pc.QuadPart * 1000.0 / freq.QuadPart; // us
}
// android 平台 ios linux 等
#include <sys/time.h>
double get_current_time()
{
struct timeval tv;
gettimeofday(&tv, NULL);
return tv.tv_sec * 1000.0 + tv.tv_usec / 1000.0;
}
// convert float to half precision floating point
static unsigned short float32_to_float16(float value)
{
// 1 : 8 : 23
union
{
unsigned int u;
float f;
} tmp;
tmp.f = value;
// 1 : 8 : 23
unsigned short sign = (tmp.u & 0x80000000) >> 31;
unsigned short exponent = (tmp.u & 0x7F800000) >> 23;
unsigned int significand = tmp.u & 0x7FFFFF;
// fprintf(stderr, "%d %d %d\n", sign, exponent, significand);
// 1 : 5 : 10
unsigned short fp16;
if (exponent == 0)
{
// zero or denormal, always underflow
fp16 = (sign << 15) | (0x00 << 10) | 0x00;
}
else if (exponent == 0xFF)
{
// infinity or NaN
fp16 = (sign << 15) | (0x1F << 10) | (significand ? 0x200 : 0x00);
}
else
{
// normalized
short newexp = exponent + (- 127 + 15);
if (newexp >= 31)
{
// overflow, return infinity
fp16 = (sign << 15) | (0x1F << 10) | 0x00;
}
else if (newexp <= 0)
{
// underflow
if (newexp >= -10)
{
// denormal half-precision
unsigned short sig = (significand | 0x800000) >> (14 - newexp);
fp16 = (sign << 15) | (0x00 << 10) | sig;
}
else
{
// underflow
fp16 = (sign << 15) | (0x00 << 10) | 0x00;
}
}
else
{
fp16 = (sign << 15) | (newexp << 10) | (significand >> 13);
}
}
return fp16;
}
// convert half precision floating point to float
static float float16_to_float32(unsigned short value)
{
// 1 : 5 : 10
unsigned short sign = (value & 0x8000) >> 15;
unsigned short exponent = (value & 0x7c00) >> 10;
unsigned short significand = value & 0x03FF;
// fprintf(stderr, "%d %d %d\n", sign, exponent, significand);
// 1 : 8 : 23
union
{
unsigned int u;
float f;
} tmp;
if (exponent == 0)
{
if (significand == 0)
{
// zero
tmp.u = (sign << 31);
}
else
{
// denormal
exponent = 0;
// find non-zero bit
while ((significand & 0x200) == 0)
{
significand <<= 1;
exponent++;
}
significand <<= 1;
significand &= 0x3FF;
tmp.u = (sign << 31) | ((-exponent + (-15 + 127)) << 23) | (significand << 13);
}
}
else if (exponent == 0x1F)
{
// infinity or NaN
tmp.u = (sign << 31) | (0xFF << 23) | (significand << 13);
}
else
{
// normalized
tmp.u = (sign << 31) | ((exponent + (-15 + 127)) << 23) | (significand << 13);
}
return tmp.f;
}
// round to nearest
static signed char float32_to_int8(float value)
{
float tmp;
if (value >= 0.f) tmp = value + 0.5;
else tmp = value - 0.5;
if (tmp > 127)
return 127;
if (tmp < -128)
return -128;
return tmp;
}