summaryrefslogtreecommitdiff
path: root/firmware/include/bitarray.h
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/include/bitarray.h')
-rw-r--r--firmware/include/bitarray.h231
1 files changed, 231 insertions, 0 deletions
diff --git a/firmware/include/bitarray.h b/firmware/include/bitarray.h
new file mode 100644
index 0000000000..4777ccb6a4
--- /dev/null
+++ b/firmware/include/bitarray.h
@@ -0,0 +1,231 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2014 by Michael Sevakis
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#ifndef BITARRAY_H
22#define BITARRAY_H
23
24/* Type-checked bit array definitions */
25
26/* All this stuff gets optimized into very simple object code */
27
28#define BITARRAY_WORD_BITS \
29 (sizeof (unsigned int) * 8)
30#define BITARRAY_NWORDS(bits) \
31 (((bits) + BITARRAY_WORD_BITS - 1) / BITARRAY_WORD_BITS)
32#define BITARRAY_BITWORD(bitnum) \
33 ((bitnum) / BITARRAY_WORD_BITS)
34#define BITARRAY_WORDBIT(bitnum) \
35 ((bitnum) % BITARRAY_WORD_BITS)
36#define BITARRAY_NBIT(word, bit) \
37 ((word)*BITARRAY_WORD_BITS + (bit))
38#define BITARRAY_BITS(bits) \
39 (BITARRAY_NWORDS(bits)*BITARRAY_WORD_BITS)
40#define BITARRAY_BITN(bitnum) \
41 (1u << BITARRAY_WORDBIT(bitnum))
42
43
44/** Iterators **/
45#include "config.h"
46#include <stdint.h>
47
48#if (defined(CPU_ARM) && ARM_ARCH >= 5) || UINT32_MAX < UINT_MAX
49#define __BITARRAY_CTZ(wval) __builtin_ctz(wval)
50#else
51#include "system.h"
52#define __BITARRAY_CTZ(wval) find_first_set_bit(wval)
53#endif
54#define __BITARRAY_POPCNT(wval) __builtin_popcount(wval)
55
56#ifndef BIT_N
57#define BIT_N(n) (1u << (n))
58#endif
59
60/* Enumerate each word index */
61#define FOR_EACH_BITARRAY_WORD_INDEX(nwords, index) \
62 for (unsigned int index = 0, _nwords = (nwords); \
63 index < _nwords; index++)
64
65/* Enumerate each word value */
66#define FOR_EACH_BITARRAY_WORD(a, wval) \
67 FOR_EACH_BITARRAY_WORD_INDEX(ARRAYLEN((a)->words), _w) \
68 for (unsigned int wval = (a)->words[_w], _ = 1; _; _--)
69
70/* Enumerate the bit number of each set bit of a word in sequence */
71#define FOR_EACH_BITARRAY_SET_WORD_BIT(wval, bit) \
72 for (unsigned int _wval = (wval), bit; \
73 _wval ? (((bit) = __BITARRAY_CTZ(_wval)), 1) : 0; \
74 _wval &= ~BIT_N(bit))
75
76/* Enumerate the bit number of each set bit in the bit array in sequence */
77#define FOR_EACH_BITARRAY_SET_BIT_ARR(nwords, words, nbit) \
78 FOR_EACH_BITARRAY_WORD_INDEX(nwords, _w) \
79 FOR_EACH_BITARRAY_SET_WORD_BIT(words[_w], _bit) \
80 for (unsigned int nbit = BITARRAY_NBIT(_w, _bit), _ = 1; _; _--)
81
82/* As above but takes an array type for an argument */
83#define FOR_EACH_BITARRAY_SET_BIT(a, nbit) \
84 FOR_EACH_BITARRAY_SET_BIT_ARR(ARRAYLEN((a)->words), (a)->words, nbit)
85
86
87/** Base functions (called by typed functions) **/
88
89/* Return the word associated with the bit */
90static inline unsigned int
91__bitarray_get_word(unsigned int words[], unsigned int bitnum)
92{
93 return words[BITARRAY_BITWORD(bitnum)];
94}
95
96/* Set the word associated with the bit */
97static inline void
98__bitarray_set_word(unsigned int words[], unsigned int bitnum,
99 unsigned int wordval)
100{
101 words[BITARRAY_BITWORD(bitnum)] = wordval;
102}
103
104/* Set the bit at index 'bitnum' to '1' */
105static inline void
106__bitarray_set_bit(unsigned int words[], unsigned int bitnum)
107{
108 unsigned int word = BITARRAY_BITWORD(bitnum);
109 unsigned int bit = BITARRAY_BITN(bitnum);
110 words[word] |= bit;
111}
112
113/* Set the bit at index 'bitnum' to '0' */
114static inline void
115__bitarray_clear_bit(unsigned int words[], unsigned int bitnum)
116{
117 unsigned int word = BITARRAY_BITWORD(bitnum);
118 unsigned int bit = BITARRAY_BITN(bitnum);
119 words[word] &= ~bit;
120}
121
122/* Return the value of the specified bit ('0' or '1') */
123static inline unsigned int
124__bitarray_test_bit(const unsigned int words[], unsigned int bitnum)
125{
126 unsigned int word = BITARRAY_BITWORD(bitnum);
127 unsigned int nbit = BITARRAY_WORDBIT(bitnum);
128 return (words[word] >> nbit) & 1u;
129}
130
131/* Check if all bits in the bit array are '0' */
132static inline bool
133__bitarray_is_clear(const unsigned int words[], unsigned int nbits)
134{
135 FOR_EACH_BITARRAY_WORD_INDEX(BITARRAY_NWORDS(nbits), word)
136 {
137 if (words[word] != 0)
138 return false;
139 }
140
141 return true;
142}
143
144/* Set every bit in the array to '0' */
145static inline void
146__bitarray_clear(unsigned int words[], unsigned int nbits)
147{
148 FOR_EACH_BITARRAY_WORD_INDEX(BITARRAY_NWORDS(nbits), word)
149 words[word] = 0;
150}
151
152/* Set every bit in the array to '1' */
153static inline void
154__bitarray_set(unsigned int words[], unsigned int nbits)
155{
156 FOR_EACH_BITARRAY_WORD_INDEX(BITARRAY_NWORDS(nbits), word)
157 words[word] = ~0u;
158}
159
160/* Find the lowest-indexed '1' bit in the bit array, returning the size of
161 the array if none are set */
162static inline unsigned int
163__bitarray_ffs(const unsigned int words[], unsigned int nbits)
164{
165 FOR_EACH_BITARRAY_SET_BIT_ARR(BITARRAY_NWORDS(nbits), words, nbit)
166 return nbit;
167
168 return BITARRAY_BITS(nbits);
169}
170
171/* Return the number of bits currently set to '1' in the bit array */
172static inline unsigned int
173__bitarray_popcount(const unsigned int words[], unsigned int nbits)
174{
175 unsigned int count = 0;
176
177 FOR_EACH_BITARRAY_WORD_INDEX(BITARRAY_NWORDS(nbits), word)
178 count += __BITARRAY_POPCNT(words[word]);
179
180 return count;
181}
182
183/**
184 * Giant macro to define all the typed functions
185 * typename: The name of the type (e.g. myarr_t myarr;)
186 * fnprefix: The prefix all functions get (e.g. myarr_set_bit)
187 * nbits : The minimum number of bits the array is meant to hold
188 * (the implementation rounds this up to the word size
189 * and all words may be fully utilized)
190 *
191 * uses 'typedef' to freely change from, e.g., struct to union without
192 * changing source code
193 */
194#define BITARRAY_TYPE_DECLARE(typename, fnprefix, nbits) \
195typedef struct \
196{ \
197 unsigned int words[BITARRAY_NWORDS(nbits)]; \
198} typename; \
199static inline unsigned int \
200fnprefix##_get_word(typename *array, unsigned int bitnum) \
201 { return __bitarray_get_word(array->words, bitnum); } \
202static inline void \
203fnprefix##_set_word(typename *array, unsigned int bitnum, \
204 unsigned int wordval) \
205 { __bitarray_set_word(array->words, bitnum, wordval); } \
206static inline void \
207fnprefix##_set_bit(typename *array, unsigned int bitnum) \
208 { __bitarray_set_bit(array->words, bitnum); } \
209static inline void \
210fnprefix##_clear_bit(typename *array, unsigned int bitnum) \
211 { __bitarray_clear_bit(array->words, bitnum); } \
212static inline unsigned int \
213fnprefix##_test_bit(const typename *array, unsigned int bitnum) \
214 { return __bitarray_test_bit(array->words, bitnum); } \
215static inline bool \
216fnprefix##_is_clear(const typename *array) \
217 { return __bitarray_is_clear(array->words, nbits); } \
218static inline void \
219fnprefix##_clear(typename *array) \
220 { __bitarray_clear(array->words, nbits); } \
221static inline void \
222fnprefix##_set(typename *array) \
223 { __bitarray_set(array->words, nbits); } \
224static inline unsigned int \
225fnprefix##_ffs(const typename *array) \
226 { return __bitarray_ffs(array->words, nbits); } \
227static inline unsigned int \
228fnprefix##_popcount(const typename *array) \
229 { return __bitarray_popcount(array->words, nbits); }
230
231#endif /* BITARRAY_H */