Add clang format and used it for bitset (#240)

* Add clang format file .clang-format

* Use clang format on bitset


---------

Co-authored-by: MeirGavish <meir.gavish@gmail.com>
This commit is contained in:
Rickey
2025-11-17 22:56:32 -08:00
committed by GitHub
parent f3f375cef1
commit a4caa44580
4 changed files with 108 additions and 47 deletions
+50
View File
@@ -0,0 +1,50 @@
BasedOnStyle: LLVM
IndentWidth: 4
UseTab: Never
# Allman brace style
BreakBeforeBraces: Allman
AllowShortBlocksOnASingleLine: false
AllowShortIfStatementsOnASingleLine: false
AllowShortFunctionsOnASingleLine: None
AllowShortLoopsOnASingleLine: false
# Pointer alignment
PointerAlignment: Left
# Column limit
ColumnLimit: 120
# Case labels
IndentCaseLabels: true
# Include sorting
SortIncludes: CaseSensitive
IncludeBlocks: Regroup
ContinuationIndentWidth: 4
AlignArrayOfStructures: Left
PackConstructorInitializers: Never
SpaceBeforeParens: Custom
SpaceBeforeParensOptions:
AfterControlStatements: true
AfterFunctionDefinitionName: false
AlignOperands: AlignAfterOperator
BreakBeforeBinaryOperators: None
IndentPPDirectives: AfterHash
AlignConsecutiveMacros: Consecutive
BinPackArguments: false
BinPackParameters: false
AllowAllArgumentsOnNextLine: false
AllowAllParametersOfDeclarationOnNextLine: false
AlignAfterOpenBracket: Align
ReflowComments: true
SpacesInLineCommentPrefix:
Minimum: 1
Maximum: 1
@@ -9,9 +9,19 @@ jobs:
name: Run Tests name: Run Tests
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Install clang-format
run: |
sudo apt-get update
sudo apt-get install -y clang-format
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v5 uses: actions/checkout@v5
- name: Clang Format
run: clang-format --dry-run -Werror include/bitset.h source/bitset.c
# Currently contains only the code that has been formatted to conform
# When all existing code conforms, change to this:
# run: clang-format --dry-run -Werror include/*.h source/*.c
- name: Run Tests - name: Run Tests
run: cd tests && ./run_tests.sh run: cd tests && ./run_tests.sh
+22 -24
View File
@@ -1,12 +1,12 @@
/** @file bitset.h /** @file bitset.h
* *
* @brief A bitset for operating on flags * @brief A bitset for operating on flags
*/ */
#ifndef BITSET_H #ifndef BITSET_H
#define BITSET_H #define BITSET_H
#include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h>
/** /**
* @def BITSET_BITS_PER_WORD * @def BITSET_BITS_PER_WORD
@@ -24,13 +24,13 @@
* bitset will always use this number of words, though it's capacity can be any length * bitset will always use this number of words, though it's capacity can be any length
* from `1` to `BITSET_BITS_PER_WORD * BITSET_ARRAY_SIZE` * from `1` to `BITSET_BITS_PER_WORD * BITSET_ARRAY_SIZE`
*/ */
#define BITSET_ARRAY_SIZE 8 #define BITSET_ARRAY_SIZE 8
/** /**
* @def BITSET_MAX_BITS * @def BITSET_MAX_BITS
* @brief Maximum number of bits in a bitset * @brief Maximum number of bits in a bitset
*/ */
#define BITSET_MAX_BITS BITSET_BITS_PER_WORD * BITSET_ARRAY_SIZE #define BITSET_MAX_BITS (BITSET_BITS_PER_WORD * BITSET_ARRAY_SIZE)
/** /**
* @brief A bitset spread across multiple `uint32_t` words * @brief A bitset spread across multiple `uint32_t` words
@@ -40,7 +40,7 @@ typedef struct Bitset
/** /**
* @brief Word array of `uint32_t` to hold the bitset data * @brief Word array of `uint32_t` to hold the bitset data
*/ */
uint32_t *w; uint32_t* w;
/** /**
* @brief Number of bits in a word, will be 32 * @brief Number of bits in a word, will be 32
@@ -73,7 +73,7 @@ typedef struct
/** /**
* @brief @ref Bitset this is iterating through * @brief @ref Bitset this is iterating through
*/ */
const Bitset *bitset; const Bitset* bitset;
/** /**
* @brief Current word the iterator is on * @brief Current word the iterator is on
@@ -88,7 +88,7 @@ typedef struct
/** /**
* @brief Number of bits that have been iterated through in total * @brief Number of bits that have been iterated through in total
*/ */
int itr; int itr;
} BitsetItr; } BitsetItr;
/** /**
@@ -98,7 +98,7 @@ typedef struct
* @param idx the index of the flag to set * @param idx the index of the flag to set
* @param on the value to set the flag to * @param on the value to set the flag to
*/ */
void bitset_set_idx(Bitset *bitset, int idx, bool on); void bitset_set_idx(Bitset* bitset, int idx, bool on);
/** /**
* @brief Get the value of a flag * @brief Get the value of a flag
@@ -108,19 +108,19 @@ void bitset_set_idx(Bitset *bitset, int idx, bool on);
* *
* @return the value of the flag as `true` or `false` * @return the value of the flag as `true` or `false`
*/ */
bool bitset_get_idx(Bitset *bitset, int idx); bool bitset_get_idx(Bitset* bitset, int idx);
// Get the next free (set to 0) index in the bitset. // Get the next free (set to 0) index in the bitset.
// It also sets the bit which it maybe should do... It really shouldn't do two things // It also sets the bit which it maybe should do... It really shouldn't do two things
// But it's such a fast operation idk. // TODO: decide what you wanna do // But it's such a fast operation idk. // TODO: decide what you wanna do
int bitset_allocate_idx(Bitset *bitset); int bitset_allocate_idx(Bitset* bitset);
/** /**
* @brief Clear the bitset, all to 0 * @brief Clear the bitset, all to 0
* *
* @param bitset A @ref Bitset to operate on * @param bitset A @ref Bitset to operate on
*/ */
void bitset_clear(Bitset *bitset); void bitset_clear(Bitset* bitset);
/** /**
* @brief Check if a bitset is empty (all 0's) * @brief Check if a bitset is empty (all 0's)
@@ -129,7 +129,7 @@ void bitset_clear(Bitset *bitset);
* *
* @return `true` if empty, `false` otherwise * @return `true` if empty, `false` otherwise
*/ */
bool bitset_is_empty(Bitset *bitset); bool bitset_is_empty(Bitset* bitset);
/** /**
* @brief Count how many bits are set to `1` in a bitset * @brief Count how many bits are set to `1` in a bitset
@@ -138,7 +138,7 @@ bool bitset_is_empty(Bitset *bitset);
* *
* @return The number of flags set to `1` in a bitset * @return The number of flags set to `1` in a bitset
*/ */
int bitset_num_set_bits(Bitset *bitset); int bitset_num_set_bits(Bitset* bitset);
/** /**
* @brief Find the index of the nth set bit * @brief Find the index of the nth set bit
@@ -150,7 +150,7 @@ int bitset_num_set_bits(Bitset *bitset);
* *
* @return The index of the nth flag set to `1` in the bitset * @return The index of the nth flag set to `1` in the bitset
*/ */
int bitset_find_idx_of_nth_set(const Bitset *bitset, int n); int bitset_find_idx_of_nth_set(const Bitset* bitset, int n);
/** /**
* @brief Declare a @ref BitsetItr * @brief Declare a @ref BitsetItr
@@ -190,15 +190,13 @@ int bitset_itr_next(BitsetItr* itr);
* @param name the name of the bitset * @param name the name of the bitset
* @param capacity the capacity of the bitset * @param capacity the capacity of the bitset
*/ */
#define BITSET_DEFINE(name, capacity) \ #define BITSET_DEFINE(name, capacity) \
static uint32_t name##_w[BITSET_ARRAY_SIZE] = {0}; \ static uint32_t name##_w[BITSET_ARRAY_SIZE] = {0}; \
static Bitset name = \ static Bitset name = { \
{ \ .w = name##_w, \
.w = name##_w, \ .nbits = BITSET_BITS_PER_WORD, \
.nbits = BITSET_BITS_PER_WORD, \ .nwords = BITSET_ARRAY_SIZE, \
.nwords = BITSET_ARRAY_SIZE, \ .cap = capacity, \
.cap = capacity, \
}; };
#endif // BITSET_H #endif // BITSET_H
+26 -23
View File
@@ -1,7 +1,8 @@
#include "bitset.h" #include "bitset.h"
#include "util.h" #include "util.h"
void bitset_set_idx(Bitset *bitset, int idx, bool on) void bitset_set_idx(Bitset* bitset, int idx, bool on)
{ {
uint32_t i = idx / BITSET_BITS_PER_WORD; uint32_t i = idx / BITSET_BITS_PER_WORD;
uint32_t b = idx % BITSET_BITS_PER_WORD; uint32_t b = idx % BITSET_BITS_PER_WORD;
@@ -10,10 +11,10 @@ void bitset_set_idx(Bitset *bitset, int idx, bool on)
// These are more efficient, but removed for readability // These are more efficient, but removed for readability
// See: https://github.com/cellos51/balatro-gba/pull/132#discussion_r2365966071 // See: https://github.com/cellos51/balatro-gba/pull/132#discussion_r2365966071
// Divide by 32 to get the word index // Divide by 32 to get the word index
//uint32_t i = idx >> 5; // uint32_t i = idx >> 5;
// Get last 5-bits, same as a modulo (% 32) operation on positive numbers // Get last 5-bits, same as a modulo (% 32) operation on positive numbers
//uint32_t b = idx & 0x1F; // uint32_t b = idx & 0x1F;
if(on) if (on)
{ {
bitset->w[i] |= (uint32_t)1 << b; bitset->w[i] |= (uint32_t)1 << b;
} }
@@ -23,7 +24,7 @@ void bitset_set_idx(Bitset *bitset, int idx, bool on)
} }
} }
int bitset_allocate_idx(Bitset *bitset) int bitset_allocate_idx(Bitset* bitset)
{ {
for (uint32_t i = 0; i < bitset->nwords; i++) for (uint32_t i = 0; i < bitset->nwords; i++)
{ {
@@ -49,24 +50,25 @@ int bitset_allocate_idx(Bitset *bitset)
return UNDEFINED; return UNDEFINED;
} }
void bitset_clear(Bitset *bitset) void bitset_clear(Bitset* bitset)
{ {
for(int i = 0; i < bitset->nwords; i++) for (int i = 0; i < bitset->nwords; i++)
{ {
bitset->w[i] = 0; bitset->w[i] = 0;
} }
} }
bool bitset_is_empty(Bitset *bitset) bool bitset_is_empty(Bitset* bitset)
{ {
for(int i = 0; i < bitset->nwords; i++) for (int i = 0; i < bitset->nwords; i++)
{ {
if(bitset->w[i]) return false; if (bitset->w[i])
return false;
} }
return true; return true;
} }
bool bitset_get_idx(Bitset *bitset, int idx) bool bitset_get_idx(Bitset* bitset, int idx)
{ {
uint32_t i = idx / BITSET_BITS_PER_WORD; uint32_t i = idx / BITSET_BITS_PER_WORD;
uint32_t b = idx % BITSET_BITS_PER_WORD; uint32_t b = idx % BITSET_BITS_PER_WORD;
@@ -74,11 +76,11 @@ bool bitset_get_idx(Bitset *bitset, int idx)
return bitset->w[i] & (uint32_t)1 << b; return bitset->w[i] & (uint32_t)1 << b;
} }
int bitset_num_set_bits(Bitset *bitset) int bitset_num_set_bits(Bitset* bitset)
{ {
int sum = 0; int sum = 0;
for(int i = 0; i < bitset->nwords; i++) for (int i = 0; i < bitset->nwords; i++)
{ {
sum += __builtin_popcount(bitset->w[i]); sum += __builtin_popcount(bitset->w[i]);
} }
@@ -86,23 +88,25 @@ int bitset_num_set_bits(Bitset *bitset)
return sum; return sum;
} }
int bitset_find_idx_of_nth_set(const Bitset *bitset, int n) int bitset_find_idx_of_nth_set(const Bitset* bitset, int n)
{ {
int tracker = 0; int tracker = 0;
int prev_tracker = 0; int prev_tracker = 0;
for(int i = 0; i < bitset->nwords; i++) for (int i = 0; i < bitset->nwords; i++)
{ {
tracker += __builtin_popcount(bitset->w[i]); tracker += __builtin_popcount(bitset->w[i]);
if(tracker > n) if (tracker > n)
{ {
// The index is here somewhere // The index is here somewhere
int base = prev_tracker - 1; // this one is to count the 1's not the offset, underflow to -1 is good for finding the 0 index // this one is to count the 1's not the offset, underflow to -1 is good for finding the 0 index
int offset = bitset->nbits * i; // this one is for the actual offset we want to map the id to int base = prev_tracker - 1;
// this one is for the actual offset we want to map the id to
int offset = bitset->nbits * i;
for (int j = 0; j < bitset->nbits; j++) for (int j = 0; j < bitset->nbits; j++)
{ {
if(base == n) if (base == n)
{ {
return offset - 1; return offset - 1;
} }
@@ -121,8 +125,7 @@ int bitset_find_idx_of_nth_set(const Bitset *bitset, int n)
BitsetItr bitset_itr_create(const Bitset* bitset) BitsetItr bitset_itr_create(const Bitset* bitset)
{ {
BitsetItr itr = BitsetItr itr = {
{
.bitset = bitset, .bitset = bitset,
.word = 0, .word = 0,
.bit = 0, .bit = 0,
@@ -142,13 +145,13 @@ int bitset_itr_next(BitsetItr* itr)
// So one last thing you could do is something like `bitset_allocate_idx` does with the // So one last thing you could do is something like `bitset_allocate_idx` does with the
// __builtin_ctz function as well. // __builtin_ctz function as well.
// //
// The point being, this can be very slow, but it's simple and can be much faster. // The point being, this can be very slow, but it's simple and can be much faster.
for (; itr->word < itr->bitset->nwords; itr->word++) for (; itr->word < itr->bitset->nwords; itr->word++)
{ {
for (; itr->bit < itr->bitset->nbits; itr->bit++) for (; itr->bit < itr->bitset->nbits; itr->bit++)
{ {
itr->itr++; itr->itr++;
if(itr->bitset->w[itr->word] & (1 << itr->bit)) if (itr->bitset->w[itr->word] & (1 << itr->bit))
{ {
// if itr->bit == nbits on the next run, the for loop will handle it // if itr->bit == nbits on the next run, the for loop will handle it
itr->bit++; itr->bit++;