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 )