diff --git a/spot/bricks/brick-bitlevel b/spot/bricks/brick-bitlevel index 86d8ce265563bd35b527a326dbea63552494d526..0c33b8ee9efa198b53bd19cf52bd441dfb306048 100644 --- a/spot/bricks/brick-bitlevel +++ b/spot/bricks/brick-bitlevel @@ -37,6 +37,7 @@ #include #include +#include #ifndef BRICK_BITLEVEL_H #define BRICK_BITLEVEL_H @@ -182,19 +183,19 @@ static inline unsigned MSB( T x ) { template<> inline unsigned MSB< unsigned int >( unsigned int x ) { static const unsigned long bits = sizeof( unsigned int ) * 8 - 1; - return bits - __builtin_clz( x ); + return bits - spot::clz( x ); } template<> inline unsigned MSB< unsigned long >( unsigned long x ) { static const unsigned bits = sizeof( unsigned long ) * 8 - 1; - return bits - __builtin_clzl( x ); + return bits - spot::clz( x ); } template<> inline unsigned MSB< unsigned long long >( unsigned long long x ) { static const unsigned bits = sizeof( unsigned long long ) * 8 - 1; - return bits - __builtin_clzll( x ); + return bits - spot::clz( x ); } // gets only Most Significant Bit diff --git a/spot/misc/Makefile.am b/spot/misc/Makefile.am index ab1085cfa25c9244b72ec8304325ae687cc23870..3fb3e70d8c527a2de17021566c9395f81e9df79a 100644 --- a/spot/misc/Makefile.am +++ b/spot/misc/Makefile.am @@ -36,6 +36,7 @@ misc_HEADERS = \ bitvect.hh \ casts.hh \ common.hh \ + clz.hh \ escape.hh \ fixpool.hh \ formater.hh \ @@ -63,6 +64,7 @@ libmisc_la_SOURCES = \ bareword.cc \ bitset.cc \ bitvect.cc \ + clz.cc \ escape.cc \ formater.cc \ game.cc \ diff --git a/spot/misc/bitset.hh b/spot/misc/bitset.hh index bb1693d2bd201c24eb61bdda5baa8b8baf81b1cf..0ab26763ae546689b338c6f9131279e786c6d05b 100644 --- a/spot/misc/bitset.hh +++ b/spot/misc/bitset.hh @@ -22,6 +22,7 @@ #include #include #include +#include namespace spot { @@ -362,7 +363,7 @@ namespace spot continue; } #ifdef __GNUC__ - res += 8*sizeof(word_t) - __builtin_clz(v); + res += 8*sizeof(word_t) - clz(v); #else while (v) { diff --git a/spot/misc/clz.cc b/spot/misc/clz.cc new file mode 100644 index 0000000000000000000000000000000000000000..6b217350183c24784ff8b020f0d25440dc1dd2ed --- /dev/null +++ b/spot/misc/clz.cc @@ -0,0 +1,115 @@ +// -*- coding: utf-8 -*- +// Copyright (C) 2018 Laboratoire de Recherche et Développement +// de l'Epita (LRDE). +// +// This file is part of Spot, a model checking library. +// +// Spot is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. +// +// Spot is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +// License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#include "config.h" +#include + +namespace spot +{ + // use gcc and clang built-in functions + // both compilers use the same function names, and define __GNUC__ +#if __GNUC__ + template + struct _clz; + + template<> + struct _clz + { + unsigned + operator()(unsigned n) const noexcept + { + return __builtin_clz(n); + } + }; + + template<> + struct _clz + { + unsigned long + operator()(unsigned long n) const noexcept + { + return __builtin_clzl(n); + } + }; + + template<> + struct _clz + { + unsigned long long + operator()(unsigned long long n) const noexcept + { + return __builtin_clzll(n); + } + }; + + size_t + clz(unsigned n) + { + return _clz()(n); + } + + size_t + clz(unsigned long n) + { + return _clz()(n); + } + + size_t + clz(unsigned long long n) + { + return _clz()(n); + } +#else + size_t + clz(unsigned n) + { + size_t res = CHAR_BIT*sizeof(size_t); + while (n) + { + --res; + n >>= 1; + } + return res; + } + + size_t + clz(unsigned long n) + { + size_t res = CHAR_BIT*sizeof(unsigned long); + while (n) + { + --res; + n >>= 1; + } + return res; + } + + size_t + clz(unsigned long long n) + { + size_t res = CHAR_BIT*sizeof(unsigned long long); + while (n) + { + --res; + n >>= 1; + } + return res; + } +#endif +} diff --git a/spot/misc/clz.hh b/spot/misc/clz.hh new file mode 100644 index 0000000000000000000000000000000000000000..5b3d674c7641dbef335be5048383c392ad2d9a5c --- /dev/null +++ b/spot/misc/clz.hh @@ -0,0 +1,33 @@ +// -*- coding: utf-8 -*- +// Copyright (C) 2018 Laboratoire de Recherche et Développement +// de l'Epita (LRDE). +// +// This file is part of Spot, a model checking library. +// +// Spot is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. +// +// Spot is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +// License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#pragma once + +#include +#include +#include + +namespace spot +{ + SPOT_API size_t clz(unsigned n); + + SPOT_API size_t clz(unsigned long n); + + SPOT_API size_t clz(unsigned long long n); +} diff --git a/spot/misc/fixpool.hh b/spot/misc/fixpool.hh index 285e9e932c75857ff754fc669d6600dfd65d99d8..d07dfd14e2c18cfc8751e070b3dec2a861e79ae8 100644 --- a/spot/misc/fixpool.hh +++ b/spot/misc/fixpool.hh @@ -20,8 +20,7 @@ #pragma once #include -#include -#include +#include #if SPOT_DEBUG && defined(HAVE_VALGRIND_MEMCHECK_H) #include @@ -59,8 +58,7 @@ namespace spot return size; // small numbers are best aligned to the next power of 2 else if (size < alignof(std::max_align_t)) - return size_t{1} << (CHAR_BIT*sizeof(size_t) - - __builtin_clz(size)); + return size_t{1} << (CHAR_BIT*sizeof(size_t) - clz(size)); else { size_t mask = alignof(std::max_align_t)-1;