Coverage Report

Created: 2024-04-24 06:23

/src/tarantool/third_party/libeio/ecb.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * libecb - http://software.schmorp.de/pkg/libecb
3
 *
4
 * Copyright (©) 2009-2015 Marc Alexander Lehmann <libecb@schmorp.de>
5
 * Copyright (©) 2011 Emanuele Giaquinta
6
 * All rights reserved.
7
 *
8
 * Redistribution and use in source and binary forms, with or without modifica-
9
 * tion, are permitted provided that the following conditions are met:
10
 *
11
 *   1.  Redistributions of source code must retain the above copyright notice,
12
 *       this list of conditions and the following disclaimer.
13
 *
14
 *   2.  Redistributions in binary form must reproduce the above copyright
15
 *       notice, this list of conditions and the following disclaimer in the
16
 *       documentation and/or other materials provided with the distribution.
17
 *
18
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
19
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
20
 * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO
21
 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
22
 * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-
26
 * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
27
 * OF THE POSSIBILITY OF SUCH DAMAGE.
28
 *
29
 * Alternatively, the contents of this file may be used under the terms of
30
 * the GNU General Public License ("GPL") version 2 or any later version,
31
 * in which case the provisions of the GPL are applicable instead of
32
 * the above. If you wish to allow the use of your version of this file
33
 * only under the terms of the GPL and not to allow others to use your
34
 * version of this file under the BSD license, indicate your decision
35
 * by deleting the provisions above and replace them with the notice
36
 * and other provisions required by the GPL. If you do not delete the
37
 * provisions above, a recipient may use your version of this file under
38
 * either the BSD or the GPL.
39
 */
40
41
#ifndef ECB_H
42
#define ECB_H
43
44
/* 16 bits major, 16 bits minor */
45
#define ECB_VERSION 0x00010004
46
47
#ifdef _WIN32
48
  typedef   signed char   int8_t;
49
  typedef unsigned char  uint8_t;
50
  typedef   signed short  int16_t;
51
  typedef unsigned short uint16_t;
52
  typedef   signed int    int32_t;
53
  typedef unsigned int   uint32_t;
54
  #if __GNUC__
55
    typedef   signed long long int64_t;
56
    typedef unsigned long long uint64_t;
57
  #else /* _MSC_VER || __BORLANDC__ */
58
    typedef   signed __int64   int64_t;
59
    typedef unsigned __int64   uint64_t;
60
  #endif
61
  #ifdef _WIN64
62
    #define ECB_PTRSIZE 8
63
    typedef uint64_t uintptr_t;
64
    typedef  int64_t  intptr_t;
65
  #else
66
    #define ECB_PTRSIZE 4
67
    typedef uint32_t uintptr_t;
68
    typedef  int32_t  intptr_t;
69
  #endif
70
#else
71
  #include <inttypes.h>
72
  #if UINTMAX_MAX > 0xffffffffU
73
    #define ECB_PTRSIZE 8
74
  #else
75
    #define ECB_PTRSIZE 4
76
  #endif
77
#endif
78
79
#define ECB_GCC_AMD64 (__amd64 || __amd64__ || __x86_64 || __x86_64__)
80
#define ECB_MSVC_AMD64 (_M_AMD64 || _M_X64)
81
82
/* work around x32 idiocy by defining proper macros */
83
#if ECB_GCC_AMD64 || ECB_MSVC_AMD64
84
  #if _ILP32
85
    #define ECB_AMD64_X32 1
86
  #else
87
    #define ECB_AMD64 1
88
  #endif
89
#endif
90
91
/* many compilers define _GNUC_ to some versions but then only implement
92
 * what their idiot authors think are the "more important" extensions,
93
 * causing enormous grief in return for some better fake benchmark numbers.
94
 * or so.
95
 * we try to detect these and simply assume they are not gcc - if they have
96
 * an issue with that they should have done it right in the first place.
97
 */
98
#if !defined __GNUC_MINOR__ || defined __INTEL_COMPILER || defined __SUNPRO_C || defined __SUNPRO_CC || defined __llvm__ || defined __clang__
99
  #define ECB_GCC_VERSION(major,minor) 0
100
#else
101
  #define ECB_GCC_VERSION(major,minor) (__GNUC__ > (major) || (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor)))
102
#endif
103
104
#define ECB_CLANG_VERSION(major,minor) (__clang_major__ > (major) || (__clang_major__ == (major) && __clang_minor__ >= (minor)))
105
106
#if __clang__ && defined __has_builtin
107
  #define ECB_CLANG_BUILTIN(x) __has_builtin (x)
108
#else
109
  #define ECB_CLANG_BUILTIN(x) 0
110
#endif
111
112
#if __clang__ && defined __has_extension
113
  #define ECB_CLANG_EXTENSION(x) __has_extension (x)
114
#else
115
  #define ECB_CLANG_EXTENSION(x) 0
116
#endif
117
118
#define ECB_CPP   (__cplusplus+0)
119
#define ECB_CPP11 (__cplusplus >= 201103L)
120
121
#if ECB_CPP
122
  #define ECB_C            0
123
  #define ECB_STDC_VERSION 0
124
#else
125
  #define ECB_C            1
126
  #define ECB_STDC_VERSION __STDC_VERSION__
127
#endif
128
129
#define ECB_C99   (ECB_STDC_VERSION >= 199901L)
130
#define ECB_C11   (ECB_STDC_VERSION >= 201112L)
131
132
#if ECB_CPP
133
  #define ECB_EXTERN_C extern "C"
134
  #define ECB_EXTERN_C_BEG ECB_EXTERN_C {
135
  #define ECB_EXTERN_C_END }
136
#else
137
  #define ECB_EXTERN_C extern
138
  #define ECB_EXTERN_C_BEG
139
  #define ECB_EXTERN_C_END
140
#endif
141
142
/*****************************************************************************/
143
144
/* ECB_NO_THREADS - ecb is not used by multiple threads, ever */
145
/* ECB_NO_SMP     - ecb might be used in multiple threads, but only on a single cpu */
146
147
#if ECB_NO_THREADS
148
  #define ECB_NO_SMP 1
149
#endif
150
151
#if ECB_NO_SMP
152
  #define ECB_MEMORY_FENCE do { } while (0)
153
#endif
154
155
/* http://www-01.ibm.com/support/knowledgecenter/SSGH3R_13.1.0/com.ibm.xlcpp131.aix.doc/compiler_ref/compiler_builtins.html */
156
#if __xlC__ && ECB_CPP
157
  #include <builtins.h>
158
#endif
159
160
#ifndef ECB_MEMORY_FENCE
161
  #if ECB_GCC_VERSION(2,5) || defined __INTEL_COMPILER || (__llvm__ && __GNUC__) || __SUNPRO_C >= 0x5110 || __SUNPRO_CC >= 0x5110
162
    #if __i386 || __i386__
163
      #define ECB_MEMORY_FENCE         __asm__ __volatile__ ("lock; orb $0, -1(%%esp)" : : : "memory")
164
      #define ECB_MEMORY_FENCE_ACQUIRE __asm__ __volatile__ (""                        : : : "memory")
165
      #define ECB_MEMORY_FENCE_RELEASE __asm__ __volatile__ ("")
166
    #elif ECB_GCC_AMD64
167
      #define ECB_MEMORY_FENCE         __asm__ __volatile__ ("mfence"   : : : "memory")
168
      #define ECB_MEMORY_FENCE_ACQUIRE __asm__ __volatile__ (""         : : : "memory")
169
      #define ECB_MEMORY_FENCE_RELEASE __asm__ __volatile__ ("")
170
    #elif __powerpc__ || __ppc__ || __powerpc64__ || __ppc64__
171
      #define ECB_MEMORY_FENCE         __asm__ __volatile__ ("sync"     : : : "memory")
172
    #elif defined __ARM_ARCH_6__  || defined __ARM_ARCH_6J__  \
173
       || defined __ARM_ARCH_6K__ || defined __ARM_ARCH_6ZK__
174
      #define ECB_MEMORY_FENCE         __asm__ __volatile__ ("mcr p15,0,%0,c7,c10,5" : : "r" (0) : "memory")
175
    #elif defined __ARM_ARCH_7__  || defined __ARM_ARCH_7A__  \
176
       || defined __ARM_ARCH_7M__ || defined __ARM_ARCH_7R__
177
      #define ECB_MEMORY_FENCE         __asm__ __volatile__ ("dmb"      : : : "memory")
178
    #elif __aarch64__
179
      #define ECB_MEMORY_FENCE         __asm__ __volatile__ ("dmb ish"  : : : "memory")
180
    #elif (__sparc || __sparc__) && !(__sparc_v8__ || defined __sparcv8)
181
      #define ECB_MEMORY_FENCE         __asm__ __volatile__ ("membar #LoadStore | #LoadLoad | #StoreStore | #StoreLoad" : : : "memory")
182
      #define ECB_MEMORY_FENCE_ACQUIRE __asm__ __volatile__ ("membar #LoadStore | #LoadLoad"                            : : : "memory")
183
      #define ECB_MEMORY_FENCE_RELEASE __asm__ __volatile__ ("membar #LoadStore             | #StoreStore")
184
    #elif defined __s390__ || defined __s390x__
185
      #define ECB_MEMORY_FENCE         __asm__ __volatile__ ("bcr 15,0" : : : "memory")
186
    #elif defined __mips__
187
      /* GNU/Linux emulates sync on mips1 architectures, so we force its use */
188
      /* anybody else who still uses mips1 is supposed to send in their version, with detection code. */
189
      #define ECB_MEMORY_FENCE         __asm__ __volatile__ (".set mips2; sync; .set mips0" : : : "memory")
190
    #elif defined __alpha__
191
      #define ECB_MEMORY_FENCE         __asm__ __volatile__ ("mb"       : : : "memory")
192
    #elif defined __hppa__
193
      #define ECB_MEMORY_FENCE         __asm__ __volatile__ (""         : : : "memory")
194
      #define ECB_MEMORY_FENCE_RELEASE __asm__ __volatile__ ("")
195
    #elif defined __ia64__
196
      #define ECB_MEMORY_FENCE         __asm__ __volatile__ ("mf"       : : : "memory")
197
    #elif defined __m68k__
198
      #define ECB_MEMORY_FENCE         __asm__ __volatile__ (""         : : : "memory")
199
    #elif defined __m88k__
200
      #define ECB_MEMORY_FENCE         __asm__ __volatile__ ("tb1 0,%%r0,128" : : : "memory")
201
    #elif defined __sh__
202
      #define ECB_MEMORY_FENCE         __asm__ __volatile__ (""         : : : "memory")
203
    #endif
204
  #endif
205
#endif
206
207
#ifndef ECB_MEMORY_FENCE
208
  #if ECB_GCC_VERSION(4,7)
209
    /* see comment below (stdatomic.h) about the C11 memory model. */
210
    #define ECB_MEMORY_FENCE         __atomic_thread_fence (__ATOMIC_SEQ_CST)
211
    #define ECB_MEMORY_FENCE_ACQUIRE __atomic_thread_fence (__ATOMIC_ACQUIRE)
212
    #define ECB_MEMORY_FENCE_RELEASE __atomic_thread_fence (__ATOMIC_RELEASE)
213
214
  #elif ECB_CLANG_EXTENSION(c_atomic)
215
    /* see comment below (stdatomic.h) about the C11 memory model. */
216
    #define ECB_MEMORY_FENCE         __c11_atomic_thread_fence (__ATOMIC_SEQ_CST)
217
    #define ECB_MEMORY_FENCE_ACQUIRE __c11_atomic_thread_fence (__ATOMIC_ACQUIRE)
218
    #define ECB_MEMORY_FENCE_RELEASE __c11_atomic_thread_fence (__ATOMIC_RELEASE)
219
220
  #elif ECB_GCC_VERSION(4,4) || defined __INTEL_COMPILER || defined __clang__
221
    #define ECB_MEMORY_FENCE         __sync_synchronize ()
222
  #elif _MSC_VER >= 1500 /* VC++ 2008 */
223
    /* apparently, microsoft broke all the memory barrier stuff in Visual Studio 2008... */
224
    #pragma intrinsic(_ReadBarrier,_WriteBarrier,_ReadWriteBarrier)
225
    #define ECB_MEMORY_FENCE         _ReadWriteBarrier (); MemoryBarrier()
226
    #define ECB_MEMORY_FENCE_ACQUIRE _ReadWriteBarrier (); MemoryBarrier() /* according to msdn, _ReadBarrier is not a load fence */
227
    #define ECB_MEMORY_FENCE_RELEASE _WriteBarrier (); MemoryBarrier()
228
  #elif _MSC_VER >= 1400 /* VC++ 2005 */
229
    #pragma intrinsic(_ReadBarrier,_WriteBarrier,_ReadWriteBarrier)
230
    #define ECB_MEMORY_FENCE         _ReadWriteBarrier ()
231
    #define ECB_MEMORY_FENCE_ACQUIRE _ReadWriteBarrier () /* according to msdn, _ReadBarrier is not a load fence */
232
    #define ECB_MEMORY_FENCE_RELEASE _WriteBarrier ()
233
  #elif defined _WIN32
234
    #include <WinNT.h>
235
    #define ECB_MEMORY_FENCE         MemoryBarrier () /* actually just xchg on x86... scary */
236
  #elif __SUNPRO_C >= 0x5110 || __SUNPRO_CC >= 0x5110
237
    #include <mbarrier.h>
238
    #define ECB_MEMORY_FENCE         __machine_rw_barrier ()
239
    #define ECB_MEMORY_FENCE_ACQUIRE __machine_r_barrier  ()
240
    #define ECB_MEMORY_FENCE_RELEASE __machine_w_barrier  ()
241
  #elif __xlC__
242
    #define ECB_MEMORY_FENCE         __sync ()
243
  #endif
244
#endif
245
246
#ifndef ECB_MEMORY_FENCE
247
  #if ECB_C11 && !defined __STDC_NO_ATOMICS__
248
    /* we assume that these memory fences work on all variables/all memory accesses, */
249
    /* not just C11 atomics and atomic accesses */
250
    #include <stdatomic.h>
251
    /* Unfortunately, neither gcc 4.7 nor clang 3.1 generate any instructions for */
252
    /* any fence other than seq_cst, which isn't very efficient for us. */
253
    /* Why that is, we don't know - either the C11 memory model is quite useless */
254
    /* for most usages, or gcc and clang have a bug */
255
    /* I *currently* lean towards the latter, and inefficiently implement */
256
    /* all three of ecb's fences as a seq_cst fence */
257
    /* Update, gcc-4.8 generates mfence for all c++ fences, but nothing */
258
    /* for all __atomic_thread_fence's except seq_cst */
259
    #define ECB_MEMORY_FENCE         atomic_thread_fence (memory_order_seq_cst)
260
  #endif
261
#endif
262
263
#ifndef ECB_MEMORY_FENCE
264
  #if !ECB_AVOID_PTHREADS
265
    /*
266
     * if you get undefined symbol references to pthread_mutex_lock,
267
     * or failure to find pthread.h, then you should implement
268
     * the ECB_MEMORY_FENCE operations for your cpu/compiler
269
     * OR provide pthread.h and link against the posix thread library
270
     * of your system.
271
     */
272
    #include <pthread.h>
273
    #define ECB_NEEDS_PTHREADS 1
274
    #define ECB_MEMORY_FENCE_NEEDS_PTHREADS 1
275
276
    static pthread_mutex_t ecb_mf_lock = PTHREAD_MUTEX_INITIALIZER;
277
    #define ECB_MEMORY_FENCE do { pthread_mutex_lock (&ecb_mf_lock); pthread_mutex_unlock (&ecb_mf_lock); } while (0)
278
  #endif
279
#endif
280
281
#if !defined ECB_MEMORY_FENCE_ACQUIRE && defined ECB_MEMORY_FENCE
282
  #define ECB_MEMORY_FENCE_ACQUIRE ECB_MEMORY_FENCE
283
#endif
284
285
#if !defined ECB_MEMORY_FENCE_RELEASE && defined ECB_MEMORY_FENCE
286
  #define ECB_MEMORY_FENCE_RELEASE ECB_MEMORY_FENCE
287
#endif
288
289
/*****************************************************************************/
290
291
#if ECB_CPP
292
  #define ecb_inline static inline
293
#elif ECB_GCC_VERSION(2,5)
294
  #define ecb_inline static __inline__
295
#elif ECB_C99
296
  #define ecb_inline static inline
297
#else
298
  #define ecb_inline static
299
#endif
300
301
#if ECB_GCC_VERSION(3,3)
302
  #define ecb_restrict __restrict__
303
#elif ECB_C99
304
  #define ecb_restrict restrict
305
#else
306
  #define ecb_restrict
307
#endif
308
309
typedef int ecb_bool;
310
311
#define ECB_CONCAT_(a, b) a ## b
312
#define ECB_CONCAT(a, b) ECB_CONCAT_(a, b)
313
#define ECB_STRINGIFY_(a) # a
314
#define ECB_STRINGIFY(a) ECB_STRINGIFY_(a)
315
#define ECB_STRINGIFY_EXPR(expr) ((expr), ECB_STRINGIFY_ (expr))
316
317
#define ecb_function_ ecb_inline
318
319
#if ECB_GCC_VERSION(3,1) || ECB_CLANG_VERSION(2,8)
320
  #define ecb_attribute(attrlist)        __attribute__ (attrlist)
321
#else
322
  #define ecb_attribute(attrlist)
323
#endif
324
325
#if ECB_GCC_VERSION(3,1) || ECB_CLANG_BUILTIN(__builtin_constant_p)
326
  #define ecb_is_constant(expr)          __builtin_constant_p (expr)
327
#else
328
  /* possible C11 impl for integral types
329
  typedef struct ecb_is_constant_struct ecb_is_constant_struct;
330
  #define ecb_is_constant(expr)          _Generic ((1 ? (struct ecb_is_constant_struct *)0 : (void *)((expr) - (expr)), ecb_is_constant_struct *: 0, default: 1)) */
331
332
  #define ecb_is_constant(expr)          0
333
#endif
334
335
#if ECB_GCC_VERSION(3,1) || ECB_CLANG_BUILTIN(__builtin_expect)
336
0
  #define ecb_expect(expr,value)         __builtin_expect ((expr),(value))
337
#else
338
  #define ecb_expect(expr,value)         (expr)
339
#endif
340
341
#if ECB_GCC_VERSION(3,1) || ECB_CLANG_BUILTIN(__builtin_prefetch)
342
  #define ecb_prefetch(addr,rw,locality) __builtin_prefetch (addr, rw, locality)
343
#else
344
  #define ecb_prefetch(addr,rw,locality)
345
#endif
346
347
/* no emulation for ecb_decltype */
348
#if ECB_CPP11
349
  // older implementations might have problems with decltype(x)::type, work around it
350
  template<class T> struct ecb_decltype_t { typedef T type; };
351
  #define ecb_decltype(x) ecb_decltype_t<decltype (x)>::type
352
#elif ECB_GCC_VERSION(3,0) || ECB_CLANG_VERSION(2,8)
353
  #define ecb_decltype(x) __typeof__ (x)
354
#endif
355
356
#if _MSC_VER >= 1300
357
  #define ecb_deprecated __declspec (deprecated)
358
#else
359
  #define ecb_deprecated ecb_attribute ((__deprecated__))
360
#endif
361
362
#if _MSC_VER >= 1500
363
  #define ecb_deprecated_message(msg) __declspec (deprecated (msg))
364
#elif ECB_GCC_VERSION(4,5)
365
  #define ecb_deprecated_message(msg) ecb_attribute ((__deprecated__ (msg))
366
#else
367
  #define ecb_deprecated_message(msg) ecb_deprecated
368
#endif
369
370
#if _MSC_VER >= 1400
371
  #define ecb_noinline __declspec (noinline)
372
#else
373
  #define ecb_noinline ecb_attribute ((__noinline__))
374
#endif
375
376
#define ecb_unused     ecb_attribute ((__unused__))
377
#define ecb_const      ecb_attribute ((__const__))
378
#define ecb_pure       ecb_attribute ((__pure__))
379
380
#if ECB_C11 || __IBMC_NORETURN
381
  /* http://www-01.ibm.com/support/knowledgecenter/SSGH3R_13.1.0/com.ibm.xlcpp131.aix.doc/language_ref/noreturn.html */
382
  #define ecb_noreturn   _Noreturn
383
#elif ECB_CPP11
384
  #define ecb_noreturn   [[noreturn]]
385
#elif _MSC_VER >= 1200
386
  /* http://msdn.microsoft.com/en-us/library/k6ktzx3s.aspx */
387
  #define ecb_noreturn   __declspec (noreturn)
388
#else
389
  #define ecb_noreturn   ecb_attribute ((__noreturn__))
390
#endif
391
392
#if ECB_GCC_VERSION(4,3)
393
  #define ecb_artificial ecb_attribute ((__artificial__))
394
  #define ecb_hot        ecb_attribute ((__hot__))
395
  #define ecb_cold       ecb_attribute ((__cold__))
396
#else
397
  #define ecb_artificial
398
  #define ecb_hot
399
  #define ecb_cold
400
#endif
401
402
/* put around conditional expressions if you are very sure that the  */
403
/* expression is mostly true or mostly false. note that these return */
404
/* booleans, not the expression.                                     */
405
0
#define ecb_expect_false(expr) ecb_expect (!!(expr), 0)
406
0
#define ecb_expect_true(expr)  ecb_expect (!!(expr), 1)
407
/* for compatibility to the rest of the world */
408
#define ecb_likely(expr)   ecb_expect_true  (expr)
409
#define ecb_unlikely(expr) ecb_expect_false (expr)
410
411
/* count trailing zero bits and count # of one bits */
412
#if ECB_GCC_VERSION(3,4) \
413
    || (ECB_CLANG_BUILTIN(__builtin_clz) && ECB_CLANG_BUILTIN(__builtin_clzll) \
414
        && ECB_CLANG_BUILTIN(__builtin_ctz) && ECB_CLANG_BUILTIN(__builtin_ctzll) \
415
        && ECB_CLANG_BUILTIN(__builtin_popcount))
416
  /* we assume int == 32 bit, long == 32 or 64 bit and long long == 64 bit */
417
  #define ecb_ld32(x)      (__builtin_clz      (x) ^ 31)
418
  #define ecb_ld64(x)      (__builtin_clzll    (x) ^ 63)
419
  #define ecb_ctz32(x)      __builtin_ctz      (x)
420
  #define ecb_ctz64(x)      __builtin_ctzll    (x)
421
  #define ecb_popcount32(x) __builtin_popcount (x)
422
  /* no popcountll */
423
#else
424
  ecb_function_ ecb_const int ecb_ctz32 (uint32_t x);
425
  ecb_function_ ecb_const int
426
  ecb_ctz32 (uint32_t x)
427
  {
428
    int r = 0;
429
430
    x &= ~x + 1; /* this isolates the lowest bit */
431
432
#if ECB_branchless_on_i386
433
    r += !!(x & 0xaaaaaaaa) << 0;
434
    r += !!(x & 0xcccccccc) << 1;
435
    r += !!(x & 0xf0f0f0f0) << 2;
436
    r += !!(x & 0xff00ff00) << 3;
437
    r += !!(x & 0xffff0000) << 4;
438
#else
439
    if (x & 0xaaaaaaaa) r +=  1;
440
    if (x & 0xcccccccc) r +=  2;
441
    if (x & 0xf0f0f0f0) r +=  4;
442
    if (x & 0xff00ff00) r +=  8;
443
    if (x & 0xffff0000) r += 16;
444
#endif
445
446
    return r;
447
  }
448
449
  ecb_function_ ecb_const int ecb_ctz64 (uint64_t x);
450
  ecb_function_ ecb_const int
451
  ecb_ctz64 (uint64_t x)
452
  {
453
    int shift = x & 0xffffffffU ? 0 : 32;
454
    return ecb_ctz32 (x >> shift) + shift;
455
  }
456
457
  ecb_function_ ecb_const int ecb_popcount32 (uint32_t x);
458
  ecb_function_ ecb_const int
459
  ecb_popcount32 (uint32_t x)
460
  {
461
    x -=  (x >> 1) & 0x55555555;
462
    x  = ((x >> 2) & 0x33333333) + (x & 0x33333333);
463
    x  = ((x >> 4) + x) & 0x0f0f0f0f;
464
    x *= 0x01010101;
465
466
    return x >> 24;
467
  }
468
469
  ecb_function_ ecb_const int ecb_ld32 (uint32_t x);
470
  ecb_function_ ecb_const int ecb_ld32 (uint32_t x)
471
  {
472
    int r = 0;
473
474
    if (x >> 16) { x >>= 16; r += 16; }
475
    if (x >>  8) { x >>=  8; r +=  8; }
476
    if (x >>  4) { x >>=  4; r +=  4; }
477
    if (x >>  2) { x >>=  2; r +=  2; }
478
    if (x >>  1) {           r +=  1; }
479
480
    return r;
481
  }
482
483
  ecb_function_ ecb_const int ecb_ld64 (uint64_t x);
484
  ecb_function_ ecb_const int ecb_ld64 (uint64_t x)
485
  {
486
    int r = 0;
487
488
    if (x >> 32) { x >>= 32; r += 32; }
489
490
    return r + ecb_ld32 (x);
491
  }
492
#endif
493
494
ecb_function_ ecb_const ecb_bool ecb_is_pot32 (uint32_t x);
495
0
ecb_function_ ecb_const ecb_bool ecb_is_pot32 (uint32_t x) { return !(x & (x - 1)); }
496
ecb_function_ ecb_const ecb_bool ecb_is_pot64 (uint64_t x);
497
0
ecb_function_ ecb_const ecb_bool ecb_is_pot64 (uint64_t x) { return !(x & (x - 1)); }
498
499
ecb_function_ ecb_const uint8_t  ecb_bitrev8  (uint8_t  x);
500
ecb_function_ ecb_const uint8_t  ecb_bitrev8  (uint8_t  x)
501
0
{
502
0
  return (  (x * 0x0802U & 0x22110U)
503
0
          | (x * 0x8020U & 0x88440U)) * 0x10101U >> 16;
504
0
}
505
506
ecb_function_ ecb_const uint16_t ecb_bitrev16 (uint16_t x);
507
ecb_function_ ecb_const uint16_t ecb_bitrev16 (uint16_t x)
508
0
{
509
0
  x = ((x >>  1) &     0x5555) | ((x &     0x5555) <<  1);
510
0
  x = ((x >>  2) &     0x3333) | ((x &     0x3333) <<  2);
511
0
  x = ((x >>  4) &     0x0f0f) | ((x &     0x0f0f) <<  4);
512
0
  x = ( x >>  8              ) | ( x               <<  8);
513
0
514
0
  return x;
515
0
}
516
517
ecb_function_ ecb_const uint32_t ecb_bitrev32 (uint32_t x);
518
ecb_function_ ecb_const uint32_t ecb_bitrev32 (uint32_t x)
519
0
{
520
0
  x = ((x >>  1) & 0x55555555) | ((x & 0x55555555) <<  1);
521
0
  x = ((x >>  2) & 0x33333333) | ((x & 0x33333333) <<  2);
522
0
  x = ((x >>  4) & 0x0f0f0f0f) | ((x & 0x0f0f0f0f) <<  4);
523
0
  x = ((x >>  8) & 0x00ff00ff) | ((x & 0x00ff00ff) <<  8);
524
0
  x = ( x >> 16              ) | ( x               << 16);
525
0
526
0
  return x;
527
0
}
528
529
/* popcount64 is only available on 64 bit cpus as gcc builtin */
530
/* so for this version we are lazy */
531
ecb_function_ ecb_const int ecb_popcount64 (uint64_t x);
532
ecb_function_ ecb_const int
533
ecb_popcount64 (uint64_t x)
534
0
{
535
0
  return ecb_popcount32 (x) + ecb_popcount32 (x >> 32);
536
0
}
537
538
ecb_inline ecb_const uint8_t  ecb_rotl8  (uint8_t  x, unsigned int count);
539
ecb_inline ecb_const uint8_t  ecb_rotr8  (uint8_t  x, unsigned int count);
540
ecb_inline ecb_const uint16_t ecb_rotl16 (uint16_t x, unsigned int count);
541
ecb_inline ecb_const uint16_t ecb_rotr16 (uint16_t x, unsigned int count);
542
ecb_inline ecb_const uint32_t ecb_rotl32 (uint32_t x, unsigned int count);
543
ecb_inline ecb_const uint32_t ecb_rotr32 (uint32_t x, unsigned int count);
544
ecb_inline ecb_const uint64_t ecb_rotl64 (uint64_t x, unsigned int count);
545
ecb_inline ecb_const uint64_t ecb_rotr64 (uint64_t x, unsigned int count);
546
547
0
ecb_inline ecb_const uint8_t  ecb_rotl8  (uint8_t  x, unsigned int count) { return (x >> ( 8 - count)) | (x << count); }
548
0
ecb_inline ecb_const uint8_t  ecb_rotr8  (uint8_t  x, unsigned int count) { return (x << ( 8 - count)) | (x >> count); }
549
0
ecb_inline ecb_const uint16_t ecb_rotl16 (uint16_t x, unsigned int count) { return (x >> (16 - count)) | (x << count); }
550
0
ecb_inline ecb_const uint16_t ecb_rotr16 (uint16_t x, unsigned int count) { return (x << (16 - count)) | (x >> count); }
551
0
ecb_inline ecb_const uint32_t ecb_rotl32 (uint32_t x, unsigned int count) { return (x >> (32 - count)) | (x << count); }
552
0
ecb_inline ecb_const uint32_t ecb_rotr32 (uint32_t x, unsigned int count) { return (x << (32 - count)) | (x >> count); }
553
0
ecb_inline ecb_const uint64_t ecb_rotl64 (uint64_t x, unsigned int count) { return (x >> (64 - count)) | (x << count); }
554
0
ecb_inline ecb_const uint64_t ecb_rotr64 (uint64_t x, unsigned int count) { return (x << (64 - count)) | (x >> count); }
555
556
#if ECB_GCC_VERSION(4,3) || (ECB_CLANG_BUILTIN(__builtin_bswap32) && ECB_CLANG_BUILTIN(__builtin_bswap64))
557
  #if ECB_GCC_VERSION(4,8) || ECB_CLANG_BUILTIN(__builtin_bswap16)
558
  #define ecb_bswap16(x)  __builtin_bswap16 (x)
559
  #else
560
  #define ecb_bswap16(x) (__builtin_bswap32 (x) >> 16)
561
  #endif
562
  #define ecb_bswap32(x)  __builtin_bswap32 (x)
563
  #define ecb_bswap64(x)  __builtin_bswap64 (x)
564
#elif _MSC_VER
565
  #include <stdlib.h>
566
  #define ecb_bswap16(x) ((uint16_t)_byteswap_ushort ((uint16_t)(x)))
567
  #define ecb_bswap32(x) ((uint32_t)_byteswap_ulong  ((uint32_t)(x)))
568
  #define ecb_bswap64(x) ((uint64_t)_byteswap_uint64 ((uint64_t)(x)))
569
#else
570
  ecb_function_ ecb_const uint16_t ecb_bswap16 (uint16_t x);
571
  ecb_function_ ecb_const uint16_t
572
  ecb_bswap16 (uint16_t x)
573
  {
574
    return ecb_rotl16 (x, 8);
575
  }
576
577
  ecb_function_ ecb_const uint32_t ecb_bswap32 (uint32_t x);
578
  ecb_function_ ecb_const uint32_t
579
  ecb_bswap32 (uint32_t x)
580
  {
581
    return (((uint32_t)ecb_bswap16 (x)) << 16) | ecb_bswap16 (x >> 16);
582
  }
583
584
  ecb_function_ ecb_const uint64_t ecb_bswap64 (uint64_t x);
585
  ecb_function_ ecb_const uint64_t
586
  ecb_bswap64 (uint64_t x)
587
  {
588
    return (((uint64_t)ecb_bswap32 (x)) << 32) | ecb_bswap32 (x >> 32);
589
  }
590
#endif
591
592
#if ECB_GCC_VERSION(4,5) || ECB_CLANG_BUILTIN(__builtin_unreachable)
593
  #define ecb_unreachable() __builtin_unreachable ()
594
#else
595
  /* this seems to work fine, but gcc always emits a warning for it :/ */
596
  ecb_inline ecb_noreturn void ecb_unreachable (void);
597
  ecb_inline ecb_noreturn void ecb_unreachable (void) { }
598
#endif
599
600
/* try to tell the compiler that some condition is definitely true */
601
#define ecb_assume(cond) if (!(cond)) ecb_unreachable (); else 0
602
603
ecb_inline ecb_const unsigned char ecb_byteorder_helper (void);
604
ecb_inline ecb_const unsigned char
605
ecb_byteorder_helper (void)
606
0
{
607
0
  /* the union code still generates code under pressure in gcc, */
608
0
  /* but less than using pointers, and always seems to */
609
0
  /* successfully return a constant. */
610
0
  /* the reason why we have this horrible preprocessor mess */
611
0
  /* is to avoid it in all cases, at least on common architectures */
612
0
  /* or when using a recent enough gcc version (>= 4.6) */
613
0
#if ((__i386 || __i386__) && !__VOS__) || _M_IX86 || ECB_GCC_AMD64 || ECB_MSVC_AMD64
614
0
  return 0x44;
615
0
#elif __BYTE_ORDER__ && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
616
0
  return 0x44;
617
0
#elif __BYTE_ORDER__ && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
618
0
  return 0x11;
619
0
#else
620
0
  union
621
0
  {
622
0
    uint32_t i;
623
0
    uint8_t c;
624
0
  } u = { 0x11223344 };
625
0
  return u.c;
626
0
#endif
627
0
}
628
629
ecb_inline ecb_const ecb_bool ecb_big_endian    (void);
630
0
ecb_inline ecb_const ecb_bool ecb_big_endian    (void) { return ecb_byteorder_helper () == 0x11; }
631
ecb_inline ecb_const ecb_bool ecb_little_endian (void);
632
0
ecb_inline ecb_const ecb_bool ecb_little_endian (void) { return ecb_byteorder_helper () == 0x44; }
633
634
#if ECB_GCC_VERSION(3,0) || ECB_C99
635
  #define ecb_mod(m,n) ((m) % (n) + ((m) % (n) < 0 ? (n) : 0))
636
#else
637
  #define ecb_mod(m,n) ((m) < 0 ? ((n) - 1 - ((-1 - (m)) % (n))) : ((m) % (n)))
638
#endif
639
640
#if ECB_CPP
641
  template<typename T>
642
  static inline T ecb_div_rd (T val, T div)
643
  {
644
    return val < 0 ? - ((-val + div - 1) / div) : (val          ) / div;
645
  }
646
  template<typename T>
647
  static inline T ecb_div_ru (T val, T div)
648
  {
649
    return val < 0 ? - ((-val          ) / div) : (val + div - 1) / div;
650
  }
651
#else
652
  #define ecb_div_rd(val,div) ((val) < 0 ? - ((-(val) + (div) - 1) / (div)) : ((val)            ) / (div))
653
  #define ecb_div_ru(val,div) ((val) < 0 ? - ((-(val)            ) / (div)) : ((val) + (div) - 1) / (div))
654
#endif
655
656
#if ecb_cplusplus_does_not_suck
657
  /* does not work for local types (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2657.htm) */
658
  template<typename T, int N>
659
  static inline int ecb_array_length (const T (&arr)[N])
660
  {
661
    return N;
662
  }
663
#else
664
  #define ecb_array_length(name) (sizeof (name) / sizeof (name [0]))
665
#endif
666
667
/*******************************************************************************/
668
/* floating point stuff, can be disabled by defining ECB_NO_LIBM */
669
670
/* basically, everything uses "ieee pure-endian" floating point numbers */
671
/* the only noteworthy exception is ancient armle, which uses order 43218765 */
672
#if 0 \
673
    || __i386 || __i386__ \
674
    || ECB_GCC_AMD64 \
675
    || __powerpc__ || __ppc__ || __powerpc64__ || __ppc64__ \
676
    || defined __s390__ || defined __s390x__ \
677
    || defined __mips__ \
678
    || defined __alpha__ \
679
    || defined __hppa__ \
680
    || defined __ia64__ \
681
    || defined __m68k__ \
682
    || defined __m88k__ \
683
    || defined __sh__ \
684
    || defined _M_IX86 || defined ECB_MSVC_AMD64 || defined _M_IA64 \
685
    || (defined __arm__ && (defined __ARM_EABI__ || defined __EABI__ || defined __VFP_FP__ || defined _WIN32_WCE || defined __ANDROID__)) \
686
    || defined __aarch64__
687
  #define ECB_STDFP 1
688
  #include <string.h> /* for memcpy */
689
#else
690
  #define ECB_STDFP 0
691
#endif
692
693
#ifndef ECB_NO_LIBM
694
695
  #include <math.h> /* for frexp*, ldexp*, INFINITY, NAN */
696
697
  /* only the oldest of old doesn't have this one. solaris. */
698
  #ifdef INFINITY
699
    #define ECB_INFINITY INFINITY
700
  #else
701
    #define ECB_INFINITY HUGE_VAL
702
  #endif
703
704
  #ifdef NAN
705
    #define ECB_NAN NAN
706
  #else
707
    #define ECB_NAN ECB_INFINITY
708
  #endif
709
710
  #if ECB_C99 || _XOPEN_VERSION >= 600 || _POSIX_VERSION >= 200112L
711
    #define ecb_ldexpf(x,e) ldexpf ((x), (e))
712
    #define ecb_frexpf(x,e) frexpf ((x), (e))
713
  #else
714
    #define ecb_ldexpf(x,e) (float) ldexp ((double) (x), (e))
715
    #define ecb_frexpf(x,e) (float) frexp ((double) (x), (e))
716
  #endif
717
718
  /* converts an ieee half/binary16 to a float */
719
  ecb_function_ ecb_const float ecb_binary16_to_float (uint16_t x);
720
  ecb_function_ ecb_const float
721
  ecb_binary16_to_float (uint16_t x)
722
0
  {
723
0
    int e = (x >> 10) & 0x1f;
724
0
    int m = x & 0x3ff;
725
0
    float r;
726
0
727
0
    if      (!e     ) r = ecb_ldexpf (m        ,    -24);
728
0
    else if (e != 31) r = ecb_ldexpf (m + 0x400, e - 25);
729
0
    else if (m      ) r = ECB_NAN;
730
0
    else              r = ECB_INFINITY;
731
0
732
0
    return x & 0x8000 ? -r : r;
733
0
  }
734
735
  /* convert a float to ieee single/binary32 */
736
  ecb_function_ ecb_const uint32_t ecb_float_to_binary32 (float x);
737
  ecb_function_ ecb_const uint32_t
738
  ecb_float_to_binary32 (float x)
739
0
  {
740
0
    uint32_t r;
741
0
742
0
    #if ECB_STDFP
743
0
      memcpy (&r, &x, 4);
744
0
    #else
745
0
      /* slow emulation, works for anything but -0 */
746
0
      uint32_t m;
747
0
      int e;
748
0
749
0
      if (x == 0e0f                    ) return 0x00000000U;
750
0
      if (x > +3.40282346638528860e+38f) return 0x7f800000U;
751
0
      if (x < -3.40282346638528860e+38f) return 0xff800000U;
752
0
      if (x != x                       ) return 0x7fbfffffU;
753
0
754
0
      m = ecb_frexpf (x, &e) * 0x1000000U;
755
0
756
0
      r = m & 0x80000000U;
757
0
758
0
      if (r)
759
0
        m = -m;
760
0
761
0
      if (e <= -126)
762
0
        {
763
0
          m &= 0xffffffU;
764
0
          m >>= (-125 - e);
765
0
          e = -126;
766
0
        }
767
0
768
0
      r |= (e + 126) << 23;
769
0
      r |= m & 0x7fffffU;
770
0
    #endif
771
0
772
0
    return r;
773
0
  }
774
775
  /* converts an ieee single/binary32 to a float */
776
  ecb_function_ ecb_const float ecb_binary32_to_float (uint32_t x);
777
  ecb_function_ ecb_const float
778
  ecb_binary32_to_float (uint32_t x)
779
0
  {
780
0
    float r;
781
0
782
0
    #if ECB_STDFP
783
0
      memcpy (&r, &x, 4);
784
0
    #else
785
0
      /* emulation, only works for normals and subnormals and +0 */
786
0
      int neg = x >> 31;
787
0
      int e = (x >> 23) & 0xffU;
788
0
789
0
      x &= 0x7fffffU;
790
0
791
0
      if (e)
792
0
        x |= 0x800000U;
793
0
      else
794
0
        e = 1;
795
0
796
0
      /* we distrust ldexpf a bit and do the 2**-24 scaling by an extra multiply */
797
0
      r = ecb_ldexpf (x * (0.5f / 0x800000U), e - 126);
798
0
799
0
      r = neg ? -r : r;
800
0
    #endif
801
0
802
0
    return r;
803
0
  }
804
805
  /* convert a double to ieee double/binary64 */
806
  ecb_function_ ecb_const uint64_t ecb_double_to_binary64 (double x);
807
  ecb_function_ ecb_const uint64_t
808
  ecb_double_to_binary64 (double x)
809
0
  {
810
0
    uint64_t r;
811
0
812
0
    #if ECB_STDFP
813
0
      memcpy (&r, &x, 8);
814
0
    #else
815
0
      /* slow emulation, works for anything but -0 */
816
0
      uint64_t m;
817
0
      int e;
818
0
819
0
      if (x == 0e0                     ) return 0x0000000000000000U;
820
0
      if (x > +1.79769313486231470e+308) return 0x7ff0000000000000U;
821
0
      if (x < -1.79769313486231470e+308) return 0xfff0000000000000U;
822
0
      if (x != x                       ) return 0X7ff7ffffffffffffU;
823
0
824
0
      m = frexp (x, &e) * 0x20000000000000U;
825
0
826
0
      r = m & 0x8000000000000000;;
827
0
828
0
      if (r)
829
0
        m = -m;
830
0
831
0
      if (e <= -1022)
832
0
        {
833
0
          m &= 0x1fffffffffffffU;
834
0
          m >>= (-1021 - e);
835
0
          e = -1022;
836
0
        }
837
0
838
0
      r |= ((uint64_t)(e + 1022)) << 52;
839
0
      r |= m & 0xfffffffffffffU;
840
0
    #endif
841
0
842
0
    return r;
843
0
  }
844
845
  /* converts an ieee double/binary64 to a double */
846
  ecb_function_ ecb_const double ecb_binary64_to_double (uint64_t x);
847
  ecb_function_ ecb_const double
848
  ecb_binary64_to_double (uint64_t x)
849
0
  {
850
0
    double r;
851
0
852
0
    #if ECB_STDFP
853
0
      memcpy (&r, &x, 8);
854
0
    #else
855
0
      /* emulation, only works for normals and subnormals and +0 */
856
0
      int neg = x >> 63;
857
0
      int e = (x >> 52) & 0x7ffU;
858
0
859
0
      x &= 0xfffffffffffffU;
860
0
861
0
      if (e)
862
0
        x |= 0x10000000000000U;
863
0
      else
864
0
        e = 1;
865
0
866
0
      /* we distrust ldexp a bit and do the 2**-53 scaling by an extra multiply */
867
0
      r = ldexp (x * (0.5 / 0x10000000000000U), e - 1022);
868
0
869
0
      r = neg ? -r : r;
870
0
    #endif
871
0
872
0
    return r;
873
0
  }
874
875
#endif
876
877
#endif
878