Skip to content

Commit

Permalink
Merge pull request #7693 from kaspar030/improve_bitarithm
Browse files Browse the repository at this point in the history
core: optimize bitarithm_lsb()
  • Loading branch information
smlng committed Jan 17, 2018
2 parents ba7cbd0 + 99d484f commit c8c6289
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 16 deletions.
20 changes: 8 additions & 12 deletions core/bitarithm.c
Expand Up @@ -21,6 +21,8 @@

#include <stdio.h>

#include "bitarithm.h"

unsigned bitarithm_msb(unsigned v)
{
register unsigned r; // result of log2(v) will go here
Expand All @@ -43,19 +45,7 @@ unsigned bitarithm_msb(unsigned v)

return r;
}
/*---------------------------------------------------------------------------*/
unsigned bitarithm_lsb(register unsigned v)
{
register unsigned r = 0;

while ((v & 0x01) == 0) {
v >>= 1;
r++;
};

return r;
}
/*---------------------------------------------------------------------------*/
unsigned bitarithm_bits_set(unsigned v)
{
unsigned c; // c accumulates the total bits set in v
Expand All @@ -66,3 +56,9 @@ unsigned bitarithm_bits_set(unsigned v)

return c;
}

const uint8_t MultiplyDeBruijnBitPosition[32] =
{
0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
};
38 changes: 34 additions & 4 deletions core/include/bitarithm.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2014 Freie Universität Berlin
* Copyright (C) 2017 Kaspar Schleiser <kaspar@schleiser.de>
* 2014 Freie Universität Berlin
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
Expand All @@ -20,6 +21,10 @@
#ifndef BITARITHM_H
#define BITARITHM_H

#include <stdint.h>

#include "cpu_conf.h"

#ifdef __cplusplus
extern "C" {
#endif
Expand Down Expand Up @@ -105,19 +110,44 @@ unsigned bitarithm_msb(unsigned v);
* function will produce an infinite loop
* @return Bit Number
*
* Source: http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogObvious
*/
unsigned bitarithm_lsb(register unsigned v);
static inline unsigned bitarithm_lsb(unsigned v);

/**
* @brief Returns the number of bits set in a value
* @param[in] v Input value
* @return Number of set bits
*
* Source: http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogObvious
*/
unsigned bitarithm_bits_set(unsigned v);

/* implementations */

static inline unsigned bitarithm_lsb(unsigned v)
#if defined(BITARITHM_LSB_BUILTIN)
{
return __builtin_ffs(v) - 1;
}
#elif defined(BITARITHM_LSB_LOOKUP)
{
/* Source: http://graphics.stanford.edu/~seander/bithacks.html#ZerosOnRightMultLookup */
extern const uint8_t MultiplyDeBruijnBitPosition[32];
return MultiplyDeBruijnBitPosition[((uint32_t)((v & -v) * 0x077CB531U)) >> 27];
}
#else
{
/* Source: http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogObvious */
unsigned r = 0;

while ((v & 0x01) == 0) {
v >>= 1;
r++;
};

return r;
}
#endif

#ifdef __cplusplus
}
#endif
Expand Down
11 changes: 11 additions & 0 deletions cpu/cortexm_common/include/cpu_conf_common.h
Expand Up @@ -57,6 +57,17 @@ extern "C" {
#endif
/** @} */

/**
* @brief Select fastest bitarithm_lsb implementation
* @{
*/
#ifdef __ARM_FEATURE_CLZ
#define BITARITHM_LSB_BUILTIN
#else
#define BITARITHM_LSB_LOOKUP
#endif
/** @} */

#ifdef __cplusplus
}
#endif
Expand Down

0 comments on commit c8c6289

Please sign in to comment.