IO-AIO
view release on metacpan or search on metacpan
libeio/ecb.h view on Meta::CPAN
template<typename T> inline void ecb_poke_be (void *ptr, T v) { return ecb_poke <T> (ptr, ecb_host_to_be (v)); }
template<typename T> inline void ecb_poke_le (void *ptr, T v) { return ecb_poke <T> (ptr, ecb_host_to_le (v)); }
template<typename T> inline void ecb_poke_u (void *ptr, T v) { memcpy (ptr, &v, sizeof (v)); }
template<typename T> inline void ecb_poke_be_u (void *ptr, T v) { return ecb_poke_u<T> (ptr, ecb_host_to_be (v)); }
template<typename T> inline void ecb_poke_le_u (void *ptr, T v) { return ecb_poke_u<T> (ptr, ecb_host_to_le (v)); }
#endif
/*****************************************************************************/
/* division */
#if ECB_GCC_VERSION(3,0) || ECB_C99
/* C99 tightened the definition of %, so we can use a more efficient version */
#define ecb_mod(m,n) ((m) % (n) + ((m) % (n) < 0 ? (n) : 0))
#else
#define ecb_mod(m,n) ((m) < 0 ? ((n) - 1 - ((-1 - (m)) % (n))) : ((m) % (n)))
#endif
#if ECB_CPP
template<typename T>
static inline T ecb_div_rd (T val, T div)
{
return val < 0 ? - ((-val + div - 1) / div) : (val ) / div;
}
template<typename T>
static inline T ecb_div_ru (T val, T div)
{
return val < 0 ? - ((-val ) / div) : (val + div - 1) / div;
}
#else
#define ecb_div_rd(val,div) ((val) < 0 ? - ((-(val) + (div) - 1) / (div)) : ((val) ) / (div))
#define ecb_div_ru(val,div) ((val) < 0 ? - ((-(val) ) / (div)) : ((val) + (div) - 1) / (div))
#endif
/*****************************************************************************/
/* array length */
#if ecb_cplusplus_does_not_suck
/* does not work for local types (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2657.htm) */
template<typename T, int N>
static inline int ecb_array_length (const T (&arr)[N])
{
return N;
}
#else
#define ecb_array_length(name) (sizeof (name) / sizeof (name [0]))
#endif
/*****************************************************************************/
/* IEEE 754-2008 half float conversions */
ecb_function_ ecb_const uint32_t ecb_binary16_to_binary32 (uint32_t x);
ecb_function_ ecb_const uint32_t
ecb_binary16_to_binary32 (uint32_t x)
{
unsigned int s = (x & 0x8000) << (31 - 15);
int e = (x >> 10) & 0x001f;
unsigned int m = x & 0x03ff;
if (ecb_expect_false (e == 31))
/* infinity or NaN */
e = 255 - (127 - 15);
else if (ecb_expect_false (!e))
{
if (ecb_expect_true (!m))
/* zero, handled by code below by forcing e to 0 */
e = 0 - (127 - 15);
else
{
/* subnormal, renormalise */
unsigned int s = 10 - ecb_ld32 (m);
m = (m << s) & 0x3ff; /* mask implicit bit */
e -= s - 1;
}
}
/* e and m now are normalised, or zero, (or inf or nan) */
e += 127 - 15;
return s | (e << 23) | (m << (23 - 10));
}
ecb_function_ ecb_const uint16_t ecb_binary32_to_binary16 (uint32_t x);
ecb_function_ ecb_const uint16_t
ecb_binary32_to_binary16 (uint32_t x)
{
unsigned int s = (x >> 16) & 0x00008000; /* sign bit, the easy part */
int e = ((x >> 23) & 0x000000ff) - (127 - 15); /* the desired exponent */
unsigned int m = x & 0x007fffff;
x &= 0x7fffffff;
/* if it's within range of binary16 normals, use fast path */
if (ecb_expect_true (0x38800000 <= x && x <= 0x477fefff))
{
/* mantissa round-to-even */
m += 0x00000fff + ((m >> (23 - 10)) & 1);
/* handle overflow */
if (ecb_expect_false (m >= 0x00800000))
{
m >>= 1;
e += 1;
}
return s | (e << 10) | (m >> (23 - 10));
}
/* handle large numbers and infinity */
if (ecb_expect_true (0x477fefff < x && x <= 0x7f800000))
return s | 0x7c00;
/* handle zero, subnormals and small numbers */
if (ecb_expect_true (x < 0x38800000))
{
/* zero */
if (ecb_expect_true (!x))
return s;
/* handle subnormals */
/* too small, will be zero */
if (e < (14 - 24)) /* might not be sharp, but is good enough */
return s;
m |= 0x00800000; /* make implicit bit explicit */
/* very tricky - we need to round to the nearest e (+10) bit value */
{
unsigned int bits = 14 - e;
unsigned int half = (1 << (bits - 1)) - 1;
unsigned int even = (m >> bits) & 1;
/* if this overflows, we will end up with a normalised number */
m = (m + half + even) >> bits;
}
return s | m;
}
/* handle NaNs, preserve leftmost nan bits, but make sure we don't turn them into infinities */
m >>= 13;
return s | 0x7c00 | m | !m;
}
/*******************************************************************************/
/* fast integer to ascii */
/*
* This code is pretty complicated because it is general. The idea behind it,
* however, is pretty simple: first, the number is multiplied with a scaling
* factor (2**bits / 10**(digits-1)) to convert the integer into a fixed-point
* number with the first digit in the upper bits.
* Then this digit is converted to text and masked out. The resulting number
* is then multiplied by 10, by multiplying the fixed point representation
* by 5 and shifting the (binary) decimal point one to the right, so a 4.28
* format becomes 5.27, 6.26 and so on.
* The rest involves only advancing the pointer if we already generated a
* non-zero digit, so leading zeroes are overwritten.
*/
// simply return a mask with "bits" bits set
#define ecb_i2a_mask(type,bits) ((((type)1) << (bits)) - 1)
// oputput a single digit. maskvalue is 10**digitidx
#define ecb_i2a_digit(type,bits,digitmask,maskvalue,digitidx) \
if (digitmask >= maskvalue) /* constant, used to decide how many digits to generate */ \
{ \
char digit = x >> (bits - digitidx); /* calculate the topmost digit */ \
*ptr = digit + '0'; /* output it */ \
nz = (digitmask == maskvalue) || nz || digit; /* first term == always output last digit */ \
ptr += nz; /* output digit only if non-zero digit seen */ \
x = (x & ecb_i2a_mask (type, bits - digitidx)) * 5; /* *10, but shift decimal point right */ \
}
// convert integer to fixed point format and multiply out digits, highest first
// requires magic constants: max. digits and number of bits after the decimal point
#define ecb_i2a_def(suffix,ptr,v,type,bits,digitmask,lz) \
ecb_inline char *ecb_i2a_ ## suffix (char *ptr, uint32_t u) \
{ \
char nz = lz; /* non-zero digit seen? */ \
/* convert to x.bits fixed-point */ \
type x = u * ((ecb_i2a_mask (type, bits) + digitmask) / digitmask); \
/* output up to 10 digits */ \
ecb_i2a_digit (type,bits,digitmask, 1, 0); \
ecb_i2a_digit (type,bits,digitmask, 10, 1); \
ecb_i2a_digit (type,bits,digitmask, 100, 2); \
ecb_i2a_digit (type,bits,digitmask, 1000, 3); \
ecb_i2a_digit (type,bits,digitmask, 10000, 4); \
ecb_i2a_digit (type,bits,digitmask, 100000, 5); \
ecb_i2a_digit (type,bits,digitmask, 1000000, 6); \
ecb_i2a_digit (type,bits,digitmask, 10000000, 7); \
ecb_i2a_digit (type,bits,digitmask, 100000000, 8); \
ecb_i2a_digit (type,bits,digitmask, 1000000000, 9); \
return ptr; \
}
// predefined versions of the above, for various digits
// ecb_i2a_xN = almost N digits, limit defined by macro
// ecb_i2a_N = up to N digits, leading zeroes suppressed
( run in 1.860 second using v1.01-cache-2.11-cpan-39bf76dae61 )