add CuTest / update README

This commit is contained in:
2024-01-11 11:37:56 +01:00
parent 20e0c4d9fc
commit c2ad81b2b5
5 changed files with 246 additions and 182 deletions

View File

@@ -204,6 +204,8 @@ $(SLIB): $(OBJ) | $(LIBDIR)
##################################### testing ##################################### testing
.PHONY: cleanbin cleanbindir .PHONY: cleanbin cleanbindir
CUTESTSRC := $(TESTDIR)/cutest/CuTest.c
cleanbin: cleanbin:
$(call rmfiles,$(BIN),binary) $(call rmfiles,$(BIN),binary)
@@ -211,7 +213,7 @@ cleanbindir:
$(call rmdir,$(BINDIR),binaries) $(call rmdir,$(BINDIR),binaries)
$(BINDIR)/%: $(TESTDIR)/%.c libs | $(BINDIR) $(BINDIR)/%: $(TESTDIR)/%.c libs | $(BINDIR)
$(CC) $(CPPFLAGS) $(CFLAGS) $< $(LDFLAGS) $(LIBS) -o $@ $(CC) $(CPPFLAGS) $(CFLAGS) $< $(CUTESTSRC) $(LDFLAGS) $(LIBS) -o $@
##################################### pre-processed (.i) and assembler (.s) output ##################################### pre-processed (.i) and assembler (.s) output
%.i: %.c %.i: %.c

View File

@@ -1,13 +1,17 @@
* brlib - A small personal C library #+title: brlib - A small personal C library
#+OPTIONS: toc:nil
#+OPTIONS: num:2
#+startup: num
** License ** License
SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html> ~SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>~~
This work is, with exceptions below, Copyright (C) 2021-2024 Bruno Raoult This work is, with exceptions below, Copyright (C) 2021-2024 Bruno Raoult
("br"), and licensed under the GNU General Public License v3.0 or later. ("br"), and licensed under the GNU General Public License v3.0 or later.
Some rights reserved. See COPYING. Some rights reserved. See COPYING.
*** The licence exceptions are: *The licence exceptions are:**
**** Cutest testing framework. _Cutest testing framework.__
You can find the original work on You can find the original work on
[[https://sourceforge.net/projects/cutest/files/cutest/][sourceforge]]. [[https://sourceforge.net/projects/cutest/files/cutest/][sourceforge]].
@@ -16,17 +20,14 @@ See [[test/cutest/license.txt][license local copy]] or
<https://spdx.org/licenses/Zlib.html>. <https://spdx.org/licenses/Zlib.html>.
** Installation: ** Installation:
*** clone repository *** user...
**** user...
#+BEGIN_EXAMPLE #+BEGIN_EXAMPLE
$ git clone https://git.raoult.com:bruno/brlib.git $ git clone https://git.raoult.com:bruno/brlib.git
#+END_EXAMPLE
or or
#+BEGIN_EXAMPLE
$ git clone https://github.com/braoult/brlib.git $ git clone https://github.com/braoult/brlib.git
#+END_EXAMPLE #+END_EXAMPLE
**** ... or developer *** ...or developer
#+BEGIN_EXAMPLE #+BEGIN_EXAMPLE
$ git clone git@git.raoult.com:bruno/brlib.git $ git clone git@git.raoult.com:bruno/brlib.git
$ cd brlib $ cd brlib

View File

@@ -17,6 +17,10 @@
#include "bitops-emulated/generic-ctz.h" #include "bitops-emulated/generic-ctz.h"
#include "bitops-emulated/generic-clz.h" #include "bitops-emulated/generic-clz.h"
#ifndef __has_builtin
#define __has_builtin(x) 0
#endif
/* determine which native builtins are available /* determine which native builtins are available
*/ */
#if __has_builtin(__builtin_popcount) #if __has_builtin(__builtin_popcount)
@@ -41,10 +45,6 @@
*/ */
void print_bitops_impl(void); void print_bitops_impl(void);
#ifndef __has_builtin
#define __has_builtin(x) 0
#endif
/* no plan to support 32bits for now... /* no plan to support 32bits for now...
* #if __WORDSIZE != 64 * #if __WORDSIZE != 64
* #error "Only 64 bits word size supported." * #error "Only 64 bits word size supported."
@@ -52,8 +52,8 @@ void print_bitops_impl(void);
*/ */
/** /**
* lsb, msb: least/most significant bit: 10101000 * lsb, msb: 0-indexed least/most significant bit: 10101000
* msb = 7 ^ ^ lsb = 3 * msb = 7 ^ ^ lsb = 3
* *
*/ */
#define lsb64(x) (ctz64(x)) #define lsb64(x) (ctz64(x))
@@ -63,7 +63,7 @@ void print_bitops_impl(void);
/** /**
* popcount32, popcout64 - count set bits: 10101000 -> 3 * popcount32, popcout64 - count set bits: 10101000 -> 3
* @num: unsigned 32 or 64 bits integer. * @n: unsigned 32 or 64 bits integer.
* *
*/ */
#if defined(HAS_POPCOUNT) #if defined(HAS_POPCOUNT)
@@ -100,7 +100,7 @@ void print_bitops_impl(void);
/** /**
* ctz32, ctz64 - count trailing zeros: 00101000 -> 3 * ctz32, ctz64 - count trailing zeros: 00101000 -> 3
* @num: unsigned 32 or 64 bits integer. * @n: unsigned 32 or 64 bits integer.
* *
* Not defined if no bit set, so check for non-zero before calling this. * Not defined if no bit set, so check for non-zero before calling this.
* This is similat the FFS (First Find Set), which has FFS(0) = 0. * This is similat the FFS (First Find Set), which has FFS(0) = 0.
@@ -127,7 +127,7 @@ void print_bitops_impl(void);
/** /**
* clz32, clz64 - count leading zeros: 00101000 -> 2 * clz32, clz64 - count leading zeros: 00101000 -> 2
* *
* @num: unsigned 32 or 64 bits integer. * @n: unsigned 32 or 64 bits integer.
* *
* Not defined if no bit set, so check for non-zero before calling this. * Not defined if no bit set, so check for non-zero before calling this.
*/ */
@@ -144,8 +144,8 @@ void print_bitops_impl(void);
/** /**
* ffs32, ffs64 - find first bit set, indexed from 0: 00101000 -> 4 * ffs32, ffs64 - find first bit set, indexed from 0: 00101000 -> 4
* ffz32, ffz64 - find first bit unset, indexed from 0: 00101000 -> 0 * ffz32, ffz64 - find first bit unset, indexed from 0: 00101010 -> 2
* @num: unsigned 32 or 64 bits integer. * @n: unsigned 32 or 64 bits integer.
* *
* ffs(n) is similar to ctz(n) + 1, but returns 0 if n == 0 (except * ffs(n) is similar to ctz(n) + 1, but returns 0 if n == 0 (except
* for ctz version, where ffs(0) is undefined). * for ctz version, where ffs(0) is undefined).
@@ -176,20 +176,18 @@ void print_bitops_impl(void);
/** /**
* fls32, fls64 - return one plus MSB index: 00101000 -> 6 * fls32, fls64 - return one plus MSB index: 00101000 -> 6
* @num: unsigned 32 or 64 bits integer. * @n: unsigned 32 or 64 bits integer.
* *
* Similar to nbits(n) - clz(n), but returns 0 if n == 0; * Similar to nbits(n) - clz(n), but returns 0 if n == 0;
*/ */
#define fls32(n) ((n)? 32 - clz32(n): 0) #define fls32(n) ((n)? 32 - clz32(n): 0)
#define fls64(n) ((n)? 64 - clz64(n): 0) #define fls64(n) ((n)? 64 - clz64(n): 0)
/* rolXX/rorXX are taken from kernel's <linux/bitops.h> are are: /*
* SPDX-License-Identifier: GPL-2.0 * rol32, rot64 - rotate left
*/
/**
* rol8, rol16, rol32, rol64 - rotate left
* @num: unsigned 8, 16, 32 or 64 bits integer * @num: unsigned 8, 16, 32 or 64 bits integer
* @n: bits to roll * @n: bits to roll
* See: https://stackoverflow.com/a/31488147/3079831
*/ */
#define rol8(num, n) ((num << (n & 7)) | (num >> ((-n) & 7))) #define rol8(num, n) ((num << (n & 7)) | (num >> ((-n) & 7)))
#define rol16(num, n) ((num << (n & 15)) | (num >> ((-n) & 15))) #define rol16(num, n) ((num << (n & 15)) | (num >> ((-n) & 15)))
@@ -207,11 +205,13 @@ void print_bitops_impl(void);
#define ror64(num, n) ((num >> (n & 63)) | (num << ((-n) & 63))) #define ror64(num, n) ((num >> (n & 63)) | (num << ((-n) & 63)))
/** /**
* ilog2 - log base 2 * ilog2_32, ilog2_64 - log base 2
* @n: unsigned 32 or 64 bits integer. * @n: unsigned 32 or 64 bits integer.
*
* Undefine value if n = 0.
*/ */
#define ilog2_32(n) (fls32(n) - 1) #define ilog2_32(n) (msb32(n))
#define ilog2_64(n) (fls64(n) - 1) #define ilog2_64(n) (msb64(n))
/** /**
* is_pow2() - check if number is a power of two * is_pow2() - check if number is a power of two

View File

@@ -88,6 +88,7 @@ typedef signed char schar;
*/ */
#define __unused __attribute__((__unused__)) #define __unused __attribute__((__unused__))
#define __used __attribute__((__used__)) #define __used __attribute__((__used__))
#define __const __attribute__((__const__))
/* see https://lkml.org/lkml/2018/3/20/845 for explanation of this monster /* see https://lkml.org/lkml/2018/3/20/845 for explanation of this monster
*/ */

View File

@@ -16,181 +16,241 @@
#include "br.h" #include "br.h"
#include "bitops.h" #include "bitops.h"
// #include "cutest/CuTest.h" #include "cutest/CuTest.h"
static void test_popcount() static const struct test32_1 {
u32 t32; /* input */
int popc;
int ctz;
int clz;
int ffs;
int ffz;
int fls;
int ilog2;
} test32_1[] = {
{ 0x00000000, 0, 32, 32, 0, 1, 0, 0 }, /* C undefined for some values */
{ 0xffffffff, 32, 0, 0, 1, 0, 32, 31 },
{ 0x00000001, 1, 0, 31, 1, 2, 1, 0 },
{ 0x80000000, 1, 31, 0, 32, 1, 32, 31 },
{ 0x71800718, 10, 3, 1, 4, 1, 31, 30 },
{ 0x07eeeef7, 22, 0, 5, 1, 4, 27, 26 },
};
static const struct test64_1 {
u64 t64; /* input */
int popc;
int ctz;
int clz;
int ffs;
int ffz;
int fls;
int ilog2;
} test64_1[] = {
{ 0x0000000000000000, 0, 64, 64, 0, 1, 0, 0 }, /* undefined for some values */
{ 0xffffffffffffffff, 64, 0, 0, 1, 0, 64, 63 },
{ 0x0000000100000001, 2, 0, 31, 1, 2, 33, 32 },
{ 0x8000000000000000, 1, 63, 0, 64, 1, 64, 63 },
{ 0x7180071871800718, 20, 3, 1, 4, 1, 63, 62 },
{ 0x07eeeef707eeeef7, 44, 0, 5, 1, 4, 59, 58 },
};
static void cutest_popcount(CuTest *tc)
{ {
u32 t32[] = { 0x0, 0x88000101, 0xffffffff }; for (uint i = 0; i < ARRAY_SIZE(test32_1); ++i) {
u64 t64[] = { 0x0ll, 0x8880000000000101LL, 0xffffffffffffffffll }; int res = popcount32(test32_1[i].t32);
CuAssertIntEquals(tc, test32_1[i].popc, res);
for (uint i = 0; i < ARRAY_SIZE(t32); ++i) {
printf("popcount32 (%#x): ", t32[i]);
# ifdef ___popcount32_native
printf("native:%d ", __popcount32_native(t32[i]));
# else
printf("native:XXX ");
# endif
printf("emulated:%d ", __popcount_emulated(t32[i]));
printf("\n");
} }
printf("\n"); for (uint i = 0; i < ARRAY_SIZE(test64_1); ++i) {
for (uint i = 0; i < ARRAY_SIZE(t64); ++i) { int res = popcount64(test64_1[i].t64);
printf("popcount64 (%#lx): ", t64[i]); CuAssertIntEquals(tc, test64_1[i].popc, res);
# ifdef ___popcount64_native
printf("native:%d ", __popcount64_native(t64[i]));
# else
printf("native:XXX ");
# endif
printf("emulated:%d ", __popcount_emulated(t64[i]));
printf("\n");
} }
printf("\n");
} }
static void test_ctz() static void cutest_ctz(CuTest *tc)
{ {
u32 t32[] = { for (uint i = 0; i < ARRAY_SIZE(test32_1); ++i) {
0x88800101, int res = ctz32(test32_1[i].t32);
0xffffffff, CuAssertIntEquals(tc, test32_1[i].ctz, res);
0x800,
0x80000000,
0x00800000
};
u64 t64[] = {
0x8880000000000101LL,
0xffffffffffffffffll,
0x800ll,
0x8000000000000000LL,
0x0080000000000000LL};
for (uint i = 0; i < ARRAY_SIZE(t32); ++i) {
printf("ctz32 (%#x): ", t32[i]);
# ifdef __ctz32_native
printf("native:%d ", __ctz32_native(t32[i]));
# else
printf("native:XXX ");
# endif
printf("emulated1:%d ", __ctz32_emulated(t32[i]));
printf("emulated2:%d ", __ctz32_emulated2(t32[i]));
//printf("emulated3:%d ", __ctz32_emulated3(t32[i]));
//printf("emulated4:%d ", __ctz32_emulated4(t32[i]));
printf("\n");
} }
printf("\n"); for (uint i = 0; i < ARRAY_SIZE(test64_1); ++i) {
for (uint i = 0; i < ARRAY_SIZE(t64); ++i) { int res = ctz64(test64_1[i].t64);
printf("ctz64 (%#lx): ", t64[i]); //printf("t=%#llx r=%d e=%d\n", test64_1[i].t64, res, test64_1[i].ctz);
# ifdef __ctz64_native CuAssertIntEquals(tc, test64_1[i].ctz, res);
printf("native:%d ", __ctz64_native(t64[i]));
# else
printf("native:XXX ");
# endif
printf("emulated1:%d ", __ctz64_emulated(t64[i]));
printf("emulated2:%d ", __ctz64_emulated2(t64[i]));
//printf("emulated3:%d ", __ctz64_emulated3(t64[i]));
//printf("emulated4:%d ", __ctz64_emulated4(t64[i]));
printf("\n");
} }
printf("\n");
} }
static void test_clz() static void cutest_clz(CuTest *tc)
{ {
u32 t32[] = { for (uint i = 0; i < ARRAY_SIZE(test32_1); ++i) {
0x88800101, int res = clz32(test32_1[i].t32);
0xffffffff, //printf("clz t=%#x r=%d e=%d\n", test32_1[i].t32, res, test32_1[i].clz);
0x800, CuAssertIntEquals(tc, test32_1[i].clz, res);
0x80000000,
0x00800000
};
u64 t64[] = {
0x8880000000000101LL,
0xffffffffffffffffll,
0x800ll,
0x8000000000000000LL,
0x0080000000000000LL};
for (uint i = 0; i < ARRAY_SIZE(t32); ++i) {
printf("clz32 (%#x): ", t32[i]);
# ifdef __clz32_native
printf("native:%d ", __clz32_native(t32[i]));
# else
printf("native:XXX ");
# endif
printf("emulated1:%d ", __clz32_emulated(t32[i]));
//printf("emulated2:%d ", __clz32_emulated2(t32[i]));
//printf("emulated3:%d ", __ctz32_emulated3(t32[i]));
//printf("emulated4:%d ", __ctz32_emulated4(t32[i]));
printf("\n");
} }
printf("\n"); for (uint i = 0; i < ARRAY_SIZE(test64_1); ++i) {
for (uint i = 0; i < ARRAY_SIZE(t64); ++i) { int res = clz64(test64_1[i].t64);
printf("clz64 (%#lx): ", t64[i]); //printf("clz t=%#llx r=%d e=%d\n", test64_1[i].t64, res, test64_1[i].clz);
# ifdef __clz64_native CuAssertIntEquals(tc, test64_1[i].clz, res);
printf("native:%d ", __clz64_native(t64[i]));
# else
printf("native:XXX ");
# endif
printf("emulated1:%d ", __clz64_emulated(t64[i]));
//printf("emulated2:%d ", __ctz64_emulated2(t64[i]));
//printf("emulated3:%d ", __ctz64_emulated3(t64[i]));
//printf("emulated4:%d ", __ctz64_emulated4(t64[i]));
printf("\n");
} }
printf("\n");
} }
static void test_ffs() static void cutest_ffs(CuTest *tc)
{ {
u32 t32[] = { for (uint i = 0; i < ARRAY_SIZE(test32_1); ++i) {
0x88800101, int res = ffs32(test32_1[i].t32);
0xffffffff, CuAssertIntEquals(tc, test32_1[i].ffs, res);
0x800, }
0x80000000, for (uint i = 0; i < ARRAY_SIZE(test64_1); ++i) {
0x00800000 int res = ffs64(test64_1[i].t64);
}; //printf("ffs64 t=%#llx r=%d e=%d\n", test64_1[i].t64, res, test64_1[i].ffs);
u64 t64[] = { CuAssertIntEquals(tc, test64_1[i].ffs, res);
0x8880000000000101LL, }
0xffffffffffffffffll, }
0x800ll,
0x8000000000000000LL,
0x0080000000000000LL};
for (uint i = 0; i < ARRAY_SIZE(t32); ++i) { static void cutest_ffz(CuTest *tc)
printf("ffs32 (%#x): ", t32[i]); {
# ifdef __ffs32_native for (uint i = 0; i < ARRAY_SIZE(test32_1); ++i) {
printf("native:%d ", __ffs32_native(t32[i])); int res = ffz32(test32_1[i].t32);
# else //printf("ffz32 t=%#x r=%d e=%d\n", test32_1[i].t32, res, test32_1[i].ffz);
printf("native:XXX "); CuAssertIntEquals(tc, test32_1[i].ffz, res);
# endif
printf("popcount:%d ", __ffs32_popcount(t32[i]));
printf("ctz:%d ", __ffs32_ctz(t32[i]));
printf("emulated:%d ", __ffs32_emulated(t32[i]));
//printf("emulated4:%d ", __ctz32_emulated4(t32[i]));
printf("\n");
} }
printf("\n"); for (uint i = 0; i < ARRAY_SIZE(test64_1); ++i) {
for (uint i = 0; i < ARRAY_SIZE(t64); ++i) { int res = ffz64(test64_1[i].t64);
printf("ffs64 (%#lx): ", t64[i]); //printf("ffz64 t=%#llx r=%d e=%d\n", test64_1[i].t64, res, test64_1[i].ffz);
# ifdef __ffs64_native CuAssertIntEquals(tc, test64_1[i].ffz, res);
printf("native:%d ", __ffs64_native(t64[i]));
# else
printf("native:XXX ");
# endif
printf("popcount:%d ", __ffs64_popcount(t64[i]));
printf("ctz:%d ", __ffs64_ctz(t64[i]));
printf("emulated:%d ", __ffs64_emulated(t64[i]));
//printf("emulated4:%d ", __ctz64_emulated4(t64[i]));
printf("\n");
} }
printf("\n"); }
printf("\n");
static void cutest_fls(CuTest *tc)
{
for (uint i = 0; i < ARRAY_SIZE(test32_1); ++i) {
int res = fls32(test32_1[i].t32);
//printf("fls32 t=%#x r=%d e=%d\n", test32_1[i].t32, res, test32_1[i].fls);
CuAssertIntEquals(tc, test32_1[i].fls, res);
}
for (uint i = 0; i < ARRAY_SIZE(test64_1); ++i) {
int res = fls64(test64_1[i].t64);
//printf("fls64 t=%#llx r=%d e=%d\n", test64_1[i].t64, res, test64_1[i].fls);
CuAssertIntEquals(tc, test64_1[i].fls, res);
}
}
static void cutest_ilog(CuTest *tc)
{
for (uint i = 0; i < ARRAY_SIZE(test32_1); ++i) {
if (!test32_1[i].t32) {
printf("ilog2_32 t=%#x skipped\n", test32_1[i].t32);
continue;
}
int res = ilog2_32(test32_1[i].t32);
printf("ilog2_32_n t=%#x r=%d e=%d\n", test32_1[i].t32,
res, test32_1[i].ilog2);
CuAssertIntEquals(tc, test32_1[i].ilog2, res);
}
for (uint i = 0; i < ARRAY_SIZE(test64_1); ++i) {
if (!test64_1[i].t64) {
printf("ilog2_32 t=%#llx skipped\n", test64_1[i].t64);
continue;
}
int res = ilog2_64(test64_1[i].t64);
printf("ilog2_64_n t=%#llx r=%d e=%d\n", test64_1[i].t64,
res, test64_1[i].ilog2);
CuAssertIntEquals(tc, test64_1[i].ilog2, res);
}
}
struct test32_2 {
u32 t32; /* input */
u32 arg;
u32 rol;
u32 ror;
} test32_2[] = {
{ 0x00000000, 0, 0, 0 },
{ 0x00000000, 1, 0, 0 },
{ 0x10000001, 2, 0x40000004, 0x44000000 },
{ 0x80000008, 3, 0x00000044, 0x10000001 },
{ 0x71800718, 8, 0x80071871, 0x18718007 },
{ 0x07eeeef7, 4, 0x7eeeef70, 0x707eeeef },
};
struct test64_2 {
u64 t64; /* input */
u32 arg;
u64 rol;
u64 ror;
} test64_2[] = {
{ 0x0000000000000000, 0, 0, 0 },
{ 0x0000000000000000, 1, 0, 0 },
{ 0x1000000110000001, 2, 0x4000000440000004, 0x4400000044000000 },
{ 0x8000000880000008, 3, 0x0000004400000044, 0x1000000110000001 },
{ 0x7180071871800718, 8, 0x8007187180071871, 0x1871800718718007 },
{ 0x07eeeef707eeeef7, 4, 0x7eeeef707eeeef70, 0x707eeeef707eeeef },
};
static void cutest_rol(CuTest *tc)
{
for (uint i = 0; i < ARRAY_SIZE(test32_2); ++i) {
u32 res = rol32(test32_2[i].t32, test32_2[i].arg);
//printf("rol32 t=%#x a=%u r=%#08x e=%#08x\n", test32_2[i].t32,
// test32_2[i].arg, res, test32_2[i].rol);
CuAssertU32Equals(tc, test32_2[i].rol, res);
}
for (uint i = 0; i < ARRAY_SIZE(test64_2); ++i) {
u64 res = rol64(test64_2[i].t64, test64_2[i].arg);
//printf("rol64 t=%#llx a=%u r=%#08llx e=%#08llx\n", test64_2[i].t64,
// test64_2[i].arg, res, test64_2[i].rol);
CuAssertU64Equals(tc, test64_2[i].rol, res);
}
}
static void cutest_ror(CuTest *tc)
{
for (uint i = 0; i < ARRAY_SIZE(test32_2); ++i) {
u32 res = ror32(test32_2[i].t32, test32_2[i].arg);
//printf("ror32 t=%#x a=%u r=%#08x e=%#08x\n", test32_2[i].t32,
// test32_2[i].arg, res, test32_2[i].ror);
CuAssertU32Equals(tc, test32_2[i].ror, res);
}
for (uint i = 0; i < ARRAY_SIZE(test64_2); ++i) {
u64 res = ror64(test64_2[i].t64, test64_2[i].arg);
//printf("ror64 t=%#0llx a=%u r=%#08llx e=%#08llx\n", test64_2[i].t64,
// test64_2[i].arg, res, test64_2[i].ror);
CuAssertU64Equals(tc, test64_2[i].ror, res);
}
}
#define MAXLOOPS 8
static CuSuite *bitops_GetSuite()
{
CuSuite* suite = CuSuiteNew();
SUITE_ADD_TEST(suite, cutest_popcount);
SUITE_ADD_TEST(suite, cutest_ctz);
SUITE_ADD_TEST(suite, cutest_clz);
SUITE_ADD_TEST(suite, cutest_ffs);
SUITE_ADD_TEST(suite, cutest_ffz);
SUITE_ADD_TEST(suite, cutest_fls);
SUITE_ADD_TEST(suite, cutest_ilog);
SUITE_ADD_TEST(suite, cutest_rol);
SUITE_ADD_TEST(suite, cutest_ror);
return suite;
}
static void RunAllTests(void)
{
CuString *output = CuStringNew();
CuSuite* suite = CuSuiteNew();
CuSuiteAddSuite(suite, bitops_GetSuite());
CuSuiteRun(suite);
CuSuiteSummary(suite, output);
CuSuiteDetails(suite, output);
printf("%s\n", output->buffer);
} }
int main() int main()
{ {
test_popcount(); RunAllTests();
test_ctz();
test_clz();
test_ffs();
exit(0); exit(0);
} }