Zip and Skip Tries
Loading...
Searching...
No Matches
Classes | Public Member Functions | Static Public Member Functions | Static Public Attributes | Static Private Member Functions | Private Attributes | Static Private Attributes | Friends | List of all members
BitString< CHAR_T, CHAR_SIZE_BITS > Class Template Reference

A class to store strings compactly into integers, packing multiple characters into a single word. More...

Classes

class  Iterator
 An iterator class for traversing the characters within a BitString. More...
 
struct  ResultLCP
 Structure to hold the result of a comparison, including the ordering and the length of the common prefix. More...
 

Public Member Functions

 BitString (const CHAR_T *data, size_t size)
 Constructs a BitString object from a raw character array.
 
template<typename Container >
 BitString (const Container &data)
 Constructs a BitString object from a container of characters.
 
 BitString (const std::string &data)
 Constructs a BitString object from a std::string.
 
 BitString ()=default
 Default constructor.
 
void push_back (CHAR_T c) noexcept
 Appends a single character to the end of the BitString.
 
CHAR_T operator[] (size_t index) const
 Accesses the character at a specific index.
 
size_t size () const noexcept
 Returns the number of characters stored in the BitString.
 
size_t word_count () const noexcept
 Returns the number of uintmax_t words used for storage.
 
void clear () noexcept
 Clears the contents of the BitString, making it empty.
 
ResultLCP seq_k_compare (const BitString &other, size_t lcp, size_t max_compare) const noexcept
 Performs sequential comparison with another BitString, starting from a given LCP offset, up to a maximum length.
 
ResultLCP seq_k_compare (const BitString &other, size_t lcp) const noexcept
 Performs sequential comparison with another BitString, starting from a given LCP offset.
 
ResultLCP par_k_compare (const BitString &other, size_t lcp, size_t max_compare, uintmax_t *d_a, uintmax_t *d_largeblock, size_t &max_copied) const noexcept
 Performs parallel comparison (potentially using CUDA) with another BitString, starting from a given LCP offset, up to a maximum length.
 
ResultLCP par_k_compare (const BitString &other, size_t lcp, uintmax_t *d_a, uintmax_t *d_largeblock, size_t &max_copied) const noexcept
 Performs parallel comparison (potentially using CUDA) with another BitString, starting from a given LCP offset.
 
const uintmax_tdata () const noexcept
 Provides direct access to the underlying packed data array.
 
void print_bytes (std::ostream &os) const
 Prints the raw byte representation of the BitString to an output stream.
 
void to_file (const std::string &filename) const
 Writes the BitString contents to a file in binary format.
 
void to_file (std::ofstream &file) const
 Writes the BitString contents to an already open output file stream.
 
std::string to_string () const noexcept
 Converts the BitString back to a standard std::string.
 
Iterator begin () const noexcept
 Returns an iterator pointing to the beginning of the BitString.
 
Iterator end () const noexcept
 Returns an iterator pointing past the end of the BitString.
 

Static Public Member Functions

static BitString from_file (const std::string &filename)
 Reads a BitString from a file in binary format.
 
static BitString from_file (std::ifstream &file)
 Reads a BitString from an already open input file stream.
 

Static Public Attributes

static constexpr unsigned WORD_SIZE_BITS = sizeof(uintmax_t) * 8
 Size of the underlying storage word (uintmax_t) in bits.
 
static constexpr unsigned ALPHA = WORD_SIZE_BITS / CHAR_SIZE_BITS
 Number of characters that can be packed into a single storage word.
 
static constexpr size_t MIN_PAR_COMPARE_CHAR_SIZE = MIN_PAR_COMPARE_WORD_SIZE * ALPHA
 Minimum number of characters required to trigger parallel comparison. Derived from MIN_PAR_COMPARE_WORD_SIZE.
 

Static Private Member Functions

static constexpr std::array< unsigned, ALPHAGET_SHIFTS ()
 Generates the bit shift amounts needed for character extraction/insertion at compile time.
 
static constexpr std::array< uintmax_t, ALPHAGET_MASKS ()
 Generates the bit masks needed for character extraction at compile time.
 
static constexpr CHAR_T GET_CHAR (uintmax_t word, unsigned bit_index)
 Extracts a single character from a given word at a specific bit index (sub-word position).
 

Private Attributes

std::vector< uintmax_tm_data
 Internal storage vector holding the packed character data.
 
size_t m_size = 0
 The number of characters stored in the BitString.
 

Static Private Attributes

static constexpr std::array< unsigned, ALPHAm_shifts = GET_SHIFTS()
 Compile-time generated array of bit shift amounts.
 
static constexpr std::array< uintmax_t, ALPHAm_masks = GET_MASKS()
 Compile-time generated array of bit masks.
 

Friends

template<typename CT , unsigned CSB>
std::ostream & operator<< (std::ostream &os, const BitString< CT, CSB > &bs)
 

Detailed Description

template<typename CHAR_T, unsigned CHAR_SIZE_BITS = sizeof(CHAR_T) * 8>
class BitString< CHAR_T, CHAR_SIZE_BITS >

A class to store strings compactly into integers, packing multiple characters into a single word.

This class allows for space-efficient storage of character strings by packing them into an array of uintmax_t integers. It focuses on optimizing storage and comparison operations. Comparisons leverage bitwise operations and can identify the longest common prefix (LCP) efficiently. Parallel comparison using CUDA is supported for large strings.

Template Parameters
CHAR_TThe character type to be stored (e.g., char, uint8_t, wchar_t).
CHAR_SIZE_BITSThe number of bits representing relevant data within CHAR_T. Defaults to the full size of CHAR_T in bits. This allows handling types where only a subset of bits are meaningful (e.g., 7-bit ASCII in an 8-bit char, or 2-bit nucleotides for DNA strings).

Definition at line 57 of file BitString.cuh.

Constructor & Destructor Documentation

◆ BitString() [1/4]

template<typename CHAR_T , unsigned CHAR_SIZE_BITS>
BitString< CHAR_T, CHAR_SIZE_BITS >::BitString ( const CHAR_T data,
size_t  size 
)
explicit

Constructs a BitString object from a raw character array.

Packs the input characters into the internal uintmax_t vector.

Parameters
dataPointer to the beginning of the character array. Must not be null if size > 0.
sizeThe number of characters in the array.

Definition at line 491 of file BitString.cuh.

493{
494 const size_t word_count = (size() + ALPHA - 1) / ALPHA;
495 m_data.resize(word_count, 0);
496
497 for (size_t i = 0; i < size(); ++i)
498 {
499 const size_t word_index = i / ALPHA;
500 const size_t bit_index = i % ALPHA;
501 const uintmax_t mask = static_cast<uintmax_t>(data[i]) << m_shifts[bit_index];
503 }
504}
size_t word_count() const noexcept
Returns the number of uintmax_t words used for storage.
size_t size() const noexcept
Returns the number of characters stored in the BitString.
static constexpr std::array< unsigned, ALPHA > m_shifts
Compile-time generated array of bit shift amounts.
size_t m_size
The number of characters stored in the BitString.
static constexpr unsigned ALPHA
Number of characters that can be packed into a single storage word.
Definition BitString.cuh:63
std::vector< uintmax_t > m_data
Internal storage vector holding the packed character data.
const uintmax_t * data() const noexcept
Provides direct access to the underlying packed data array.
T * alloc_to_device(size_t size)
Allocates memory on the CUDA device.

◆ BitString() [2/4]

template<typename CHAR_T , unsigned CHAR_SIZE_BITS>
template<typename Container >
BitString< CHAR_T, CHAR_SIZE_BITS >::BitString ( const Container data)
explicit

Constructs a BitString object from a container of characters.

Packs characters from the container into the internal vector.

The container must support size() and random access via operator[]. Examples include std::vector<CHAR_T>, std::basic_string<CHAR_T>, std::array<CHAR_T, N>.

Template Parameters
ContainerType of the container holding the character data.
Parameters
dataThe container instance.

Definition at line 508 of file BitString.cuh.

509 : m_size(data.size()) // Get size from the container
510{
511 const size_t word_count = (size() + ALPHA - 1) / ALPHA;
512 m_data.resize(word_count, 0);
513
514 for (size_t i = 0; i < size(); ++i)
515 {
516 const size_t word_index = i / ALPHA;
517 const size_t bit_index = i % ALPHA;
518 const uintmax_t mask = static_cast<uintmax_t>(data[i]) << m_shifts[bit_index];
520 }
521}

◆ BitString() [3/4]

template<typename CHAR_T , unsigned CHAR_SIZE_BITS = sizeof(CHAR_T) * 8>
BitString< CHAR_T, CHAR_SIZE_BITS >::BitString ( const std::string &  data)
inlineexplicit

Constructs a BitString object from a std::string.

Note
This constructor assumes CHAR_T is compatible with char.
Parameters
dataThe std::string used to initialize the BitString object.

Definition at line 93 of file BitString.cuh.

94 : BitString(reinterpret_cast<const CHAR_T*>(data.c_str()), data.size()) // Reinterpret cast assumes CHAR_T layout matches char
95 {
96 // Body intentionally empty
97 }
BitString()=default
Default constructor.

◆ BitString() [4/4]

template<typename CHAR_T , unsigned CHAR_SIZE_BITS = sizeof(CHAR_T) * 8>
BitString< CHAR_T, CHAR_SIZE_BITS >::BitString ( )
default

Default constructor.

Note
Creates an empty BitString. Primarily intended for use by the from_file static method.

Member Function Documentation

◆ begin()

template<typename CHAR_T , unsigned CHAR_SIZE_BITS = sizeof(CHAR_T) * 8>
Iterator BitString< CHAR_T, CHAR_SIZE_BITS >::begin ( ) const
inlinenoexcept

Returns an iterator pointing to the beginning of the BitString.

Returns
Iterator An iterator to the first character.

Definition at line 437 of file BitString.cuh.

438 {
439 return Iterator(*this, 0);
440 }

◆ clear()

template<typename CHAR_T , unsigned CHAR_SIZE_BITS = sizeof(CHAR_T) * 8>
void BitString< CHAR_T, CHAR_SIZE_BITS >::clear ( )
inlinenoexcept

Clears the contents of the BitString, making it empty.

Note
Resets size to 0 and clears the internal data vector.

Definition at line 141 of file BitString.cuh.

142 {
143 m_data.clear();
144 m_size = 0;
145 }

◆ data()

template<typename CHAR_T , unsigned CHAR_SIZE_BITS = sizeof(CHAR_T) * 8>
const uintmax_t * BitString< CHAR_T, CHAR_SIZE_BITS >::data ( ) const
inlinenoexcept

Provides direct access to the underlying packed data array.

Returns
const uintmax_t* A pointer to the beginning of the internal uintmax_t data array. Returns nullptr if the BitString is empty.
Warning
Modifying the data through this pointer may invalidate the BitString's state. Use with caution.

Definition at line 246 of file BitString.cuh.

246{ return m_data.data(); }

◆ end()

template<typename CHAR_T , unsigned CHAR_SIZE_BITS = sizeof(CHAR_T) * 8>
Iterator BitString< CHAR_T, CHAR_SIZE_BITS >::end ( ) const
inlinenoexcept

Returns an iterator pointing past the end of the BitString.

Returns
Iterator An iterator representing the end sentinel.

Definition at line 446 of file BitString.cuh.

447 {
448 return Iterator(*this, size());
449 }

◆ from_file() [1/2]

template<typename CHAR_T , unsigned CHAR_SIZE_BITS>
BitString< CHAR_T, CHAR_SIZE_BITS > BitString< CHAR_T, CHAR_SIZE_BITS >::from_file ( const std::string &  filename)
static

Reads a BitString from a file in binary format.

Opens the file, calls the stream version of from_file, and closes the file.

Deserializes the size and packed data from the specified file.

Parameters
filenameThe path to the input file.
Returns
BitString The BitString object reconstructed from the file data.
Exceptions
std::runtime_errorIf the file cannot be opened for reading.

Definition at line 763 of file BitString.cuh.

764{
765 std::ifstream file(filename, std::ios::binary);
766 if (!file)
767 {
768 throw std::runtime_error("Failed to open file for reading: " + filename);
769 }
770 return from_file(file);
771 // file automatically closed by destructor
772}
static BitString from_file(const std::string &filename)
Reads a BitString from a file in binary format.

◆ from_file() [2/2]

template<typename CHAR_T , unsigned CHAR_SIZE_BITS>
BitString< CHAR_T, CHAR_SIZE_BITS > BitString< CHAR_T, CHAR_SIZE_BITS >::from_file ( std::ifstream &  file)
static

Reads a BitString from an already open input file stream.

Reads the size, calculates words needed, resizes, then reads raw data. Does not perform error checking on reads.

Deserializes the size and packed data from the stream.

Parameters
fileThe std::ifstream object, opened in binary mode.
Returns
BitString The BitString object reconstructed from the stream data.

Definition at line 739 of file BitString.cuh.

740{
742
743 file.read(reinterpret_cast<char*>(&bs.m_size), sizeof(size_t));
744 if (!file) { // Check read success
745 throw std::runtime_error("Failed to read size from file stream.");
746 }
747
748 const size_t word_count = (bs.size() + ALPHA - 1) / ALPHA;
749 bs.m_data.resize(word_count, 0); // Resize before reading into it
750
751 if (word_count > 0) { // Only read if there's data expected
752 file.read(reinterpret_cast<char*>(bs.m_data.data()), word_count * sizeof(uintmax_t));
753 if (!file) { // Check read success
754 throw std::runtime_error("Failed to read data from file stream.");
755 }
756 }
757
758
759 return bs;
760}
A class to store strings compactly into integers, packing multiple characters into a single word.
Definition BitString.cuh:58

◆ GET_CHAR()

template<typename CHAR_T , unsigned CHAR_SIZE_BITS>
constexpr CHAR_T BitString< CHAR_T, CHAR_SIZE_BITS >::GET_CHAR ( uintmax_t  word,
unsigned  bit_index 
)
staticconstexprprivate

Extracts a single character from a given word at a specific bit index (sub-word position).

Applies the appropriate mask and shift to isolate and retrieve the character.

Template Parameters
CHAR_TCharacter type.
CHAR_SIZE_BITSBits per character.
Parameters
wordThe uintmax_t word containing the packed characters.
bit_indexThe index within the word (0 to ALPHA-1) corresponding to the desired character.
Returns
CHAR_T The extracted character.

Definition at line 483 of file BitString.cuh.

484{
487 return static_cast<CHAR_T>(shifted_word);
488}
static constexpr std::array< uintmax_t, ALPHA > m_masks
Compile-time generated array of bit masks.

◆ GET_MASKS()

template<typename CHAR_T , unsigned CHAR_SIZE_BITS>
constexpr std::array< uintmax_t, BitString< CHAR_T, CHAR_SIZE_BITS >::ALPHA > BitString< CHAR_T, CHAR_SIZE_BITS >::GET_MASKS ( )
staticconstexprprivate

Generates the bit masks needed for character extraction at compile time.

Creates a mask for each character position within a word.

Template Parameters
CHAR_TCharacter type.
CHAR_SIZE_BITSBits per character.
Returns
std::array<uintmax_t, ALPHA> An array where each element i is a mask that isolates the bits corresponding to the character at sub-word index i.

Definition at line 466 of file BitString.cuh.

467{
468 uintmax_t mask = 0;
469 for (unsigned i = 0; i < CHAR_SIZE_BITS; ++i)
470 {
471 mask |= static_cast<uintmax_t>(1) << i;
472 }
473
474 std::array<uintmax_t, ALPHA> masks;
475 for (unsigned i = 0; i < ALPHA; ++i)
476 {
477 masks[i] = mask << m_shifts[i];
478 }
479 return masks;
480}

◆ GET_SHIFTS()

template<typename CHAR_T , unsigned CHAR_SIZE_BITS>
constexpr std::array< unsigned, BitString< CHAR_T, CHAR_SIZE_BITS >::ALPHA > BitString< CHAR_T, CHAR_SIZE_BITS >::GET_SHIFTS ( )
staticconstexprprivate

Generates the bit shift amounts needed for character extraction/insertion at compile time.

Calculates the left shift amount needed for each character position within a word.

Template Parameters
CHAR_TCharacter type.
CHAR_SIZE_BITSBits per character.
Returns
std::array<unsigned, ALPHA> An array where each element i contains the left-shift amount required to position the character at sub-word index i correctly within a uintmax_t.

Definition at line 455 of file BitString.cuh.

456{
457 std::array<unsigned, ALPHA> shifts;
458 for (unsigned i = 0; i < ALPHA; ++i)
459 {
460 shifts[ALPHA - i - 1] = i * CHAR_SIZE_BITS;
461 }
462 return shifts;
463}

◆ operator[]()

template<typename CHAR_T , unsigned CHAR_SIZE_BITS>
CHAR_T BitString< CHAR_T, CHAR_SIZE_BITS >::operator[] ( size_t  index) const

Accesses the character at a specific index.

Calculates the word and sub-index, then uses GET_CHAR for extraction. Behavior undefined if index is out of bounds.

Behavior is undefined for out-of-bounds access.

Parameters
indexThe zero-based index of the character to access. Must be less than size().
Returns
CHAR_T The character at the specified index.
Note
This operation involves bitwise extraction and may be slower than direct array access.

Definition at line 540 of file BitString.cuh.

541{
542 return GET_CHAR(m_data[index / ALPHA], index % ALPHA);
543}
static constexpr CHAR_T GET_CHAR(uintmax_t word, unsigned bit_index)
Extracts a single character from a given word at a specific bit index (sub-word position).

◆ par_k_compare() [1/2]

template<typename CHAR_T , unsigned CHAR_SIZE_BITS>
auto BitString< CHAR_T, CHAR_SIZE_BITS >::par_k_compare ( const BitString< CHAR_T, CHAR_SIZE_BITS > &  other,
size_t  lcp,
size_t  max_compare,
uintmax_t d_a,
uintmax_t d_largeblock,
size_t max_copied 
) const
noexcept

Performs parallel comparison (potentially using CUDA) with another BitString, starting from a given LCP offset, up to a maximum length.

Checks size, copies data to GPU if necessary, calls parallel mismatch kernel, then refines LCP. Falls back to sequential if too small.

Compares this BitString with other, assuming the first lcp characters are equal. If the number of words to compare exceeds MIN_PAR_COMPARE_WORD_SIZE, this function attempts to use a parallel CUDA kernel (par_find_mismatch) for faster mismatch detection. Otherwise, it falls back to seq_k_compare. The comparison stops strictly at lcp + max_compare characters or the end of the shorter string, whichever comes first.

Parameters
otherThe BitString to compare against.
lcpThe starting offset (longest common prefix length) for the comparison, in characters.
max_compareThe maximum number of additional characters to compare beyond the initial lcp. The comparison will not proceed beyond lcp + max_compare total characters from the start.
d_aPointer to device (GPU) memory allocated for this BitString's data. Data might be copied here if needed.
d_largeblockPointer to auxiliary device (GPU) memory required by the parallel kernel.
[in,out]max_copiedTracks the amount of data already copied to d_a to avoid redundant transfers. Updated by this function.
Returns
ResultLCP A struct containing the comparison result (std::strong_ordering) of the substrings up to the comparison limit and the final calculated LCP length (which will not exceed the limit). Returns std::strong_ordering::equal if the substrings match up to the limit, even if the full strings might differ later.
See also
seq_k_compare
MIN_PAR_COMPARE_WORD_SIZE
Note
Requires properly allocated CUDA device memory (d_a, d_largeblock) and a valid CUDA context.
The other BitString's data is assumed to be accessible directly (e.g., host pinned memory or already on device if applicable to par_find_mismatch).
Uses std::bit_ceil and std::countl_zero.

Definition at line 587 of file BitString.cuh.

588{
589 // Fallback for small comparisons
591 {
592 return seq_k_compare(other, lcp, max_compare);
593 }
594
595 const size_t min_size = std::min(size(), other.size());
596 const size_t min_word_count = std::min(word_count(), other.word_count());
597 size_t word_index = lcp / ALPHA;
598
599 // Calculate how many full words remain to potentially compare
601
602 // Calculate max words to compare based on max_compare characters
603 // Need to compare up to the word containing character (lcp + max_compare - 1)
604 const size_t end_char_index = lcp + max_compare;
605 const size_t end_word_index = (end_char_index + ALPHA - 1) / ALPHA; // Word index containing the last char to check
607
608
610
611 // Fallback if the actual number of words to compare is too small
613 {
614 return seq_k_compare(other, lcp, max_compare);
615 }
616
617 // Ensure data is on the device
619 {
621
622 // get next power of 2 greater than or equal to end_copy_index
623 size_t end_copy = std::min(std::bit_ceil(end_copy_index), word_count());
624 if (end_copy > max_copied) {
627 }
628 }
629
630 lcp -= lcp % ALPHA; // Reset LCP to the start of the current word boundary for parallel comparison
631
632 // Perform parallel mismatch search
633 auto msw = par_find_mismatch(d_a + word_index, other.data() + word_index, d_largeblock, actual_max_compare_words);
634
635 // Calculate LCP based on mismatch word index (msw)
636 lcp += msw * ALPHA;
637
638 // If no mismatch found within the compared words
640 {
641 // Check if the comparison reached the end of either string
642 if (lcp >= min_size)
643 {
644 return { size() <=> other.size(), min_size };
645 }
646
647 return { std::strong_ordering::equal, lcp };
648 }
649
650 // Mismatch found by parallel kernel. Refine LCP within the mismatch word.
651 word_index = lcp / ALPHA; // Update word_index to the mismatch word
652
653 // Find exact mismatch character within the word
654 const uintmax_t XOR = m_data[word_index] ^ other.m_data[word_index];
655 const size_t l_zero = std::countl_zero(XOR);
656
657 lcp += l_zero / CHAR_SIZE_BITS;
658
659 const size_t bit_index = lcp % ALPHA;
660
661 // Mismatch is within the limit
663 const CHAR_T rhs = GET_CHAR(other.m_data[word_index], bit_index);
664
665 return { lhs <=> rhs, lcp };
666}
static constexpr size_t MIN_PAR_COMPARE_WORD_SIZE
Minimum number of words required to trigger parallel comparison.
Definition BitString.cuh:40
ResultLCP seq_k_compare(const BitString &other, size_t lcp, size_t max_compare) const noexcept
Performs sequential comparison with another BitString, starting from a given LCP offset,...
static constexpr size_t MIN_PAR_COMPARE_CHAR_SIZE
Minimum number of characters required to trigger parallel comparison. Derived from MIN_PAR_COMPARE_WO...
Definition BitString.cuh:65
T * copy_to_device(T *d_arr, const T *arr, size_t size)
Copies data from host memory to existing device memory.
size_t par_find_mismatch(const uintmax_t *const d_a, const uintmax_t *const b, uintmax_t *d_large_block, size_t n)
GPU-accelerated implementation of finding the first mismatching word with pre-allocated memory.
Definition msw.cu:178

◆ par_k_compare() [2/2]

template<typename CHAR_T , unsigned CHAR_SIZE_BITS = sizeof(CHAR_T) * 8>
ResultLCP BitString< CHAR_T, CHAR_SIZE_BITS >::par_k_compare ( const BitString< CHAR_T, CHAR_SIZE_BITS > &  other,
size_t  lcp,
uintmax_t d_a,
uintmax_t d_largeblock,
size_t max_copied 
) const
inlinenoexcept

Performs parallel comparison (potentially using CUDA) with another BitString, starting from a given LCP offset.

Compares this BitString with other, assuming the first lcp characters are equal. Compares up to the end of the shorter string using parallel methods if applicable.

Parameters
otherThe BitString to compare against.
lcpThe starting offset (longest common prefix length) for the comparison, in characters.
d_aPointer to device (GPU) memory for this BitString's data.
d_largeblockPointer to auxiliary device (GPU) memory.
[in,out]max_copiedTracks the amount of data copied to d_a.
Returns
ResultLCP A struct containing the comparison result and the final LCP length.
Note
Equivalent to par_k_compare(other, lcp, size(), d_a, d_largeblock, max_copied).
See also
par_k_compare(const BitString&, size_t, size_t, uintmax_t*, uintmax_t*, size_t&)

Definition at line 236 of file BitString.cuh.

237 {
238 return par_k_compare(other, lcp, size(), d_a, d_largeblock, max_copied);
239 }
ResultLCP par_k_compare(const BitString &other, size_t lcp, size_t max_compare, uintmax_t *d_a, uintmax_t *d_largeblock, size_t &max_copied) const noexcept
Performs parallel comparison (potentially using CUDA) with another BitString, starting from a given L...

◆ print_bytes()

template<typename CHAR_T , unsigned CHAR_SIZE_BITS>
void BitString< CHAR_T, CHAR_SIZE_BITS >::print_bytes ( std::ostream &  os) const

Prints the raw byte representation of the BitString to an output stream.

Iterates through words and extracts bytes based on WORD_SIZE_BITS. Handles the last partial word correctly.

Writes the packed uintmax_t data to the stream byte by byte, respecting the actual number of characters (size()). Handles partial final words correctly.

Parameters
osThe output stream (e.g., std::cout, std::ofstream) to write to.

Definition at line 669 of file BitString.cuh.

670{
671 static constexpr unsigned shift = WORD_SIZE_BITS - 8;
672
673 for (size_t i = 0, a = 0; i + ALPHA <= size(); i += ALPHA, ++a)
674 {
676
677 for (unsigned c = 0; c < WORD_SIZE_BITS / 8; c++, word <<= 8)
678 {
680 }
681 }
682
683 // Handle last partial word if it exists
684 if (size() % ALPHA != 0 && !m_data.empty())
685 {
686 uintmax_t word = m_data.back();
687 unsigned remaining_chars = size() % ALPHA;
689 unsigned bytes_to_print = (remaining_bits + 7) / 8; // Round up bytes
690
691 // Process the required bytes from the most significant side
692 for (unsigned byte_idx = 0; byte_idx < bytes_to_print; ++byte_idx)
693 {
695 }
696 }
697}
static constexpr unsigned WORD_SIZE_BITS
Size of the underlying storage word (uintmax_t) in bits.
Definition BitString.cuh:61

◆ push_back()

template<typename CHAR_T , unsigned CHAR_SIZE_BITS>
void BitString< CHAR_T, CHAR_SIZE_BITS >::push_back ( CHAR_T  c)
noexcept

Appends a single character to the end of the BitString.

Adds the character to the last word, potentially allocating a new word if needed.

Parameters
cThe character to append.
Note
This operation may reallocate the underlying storage if capacity is exceeded.

Definition at line 524 of file BitString.cuh.

525{
526 const size_t word_index = size() / ALPHA;
527 const size_t bit_index = size() % ALPHA;
528 const uintmax_t mask = static_cast<uintmax_t>(c) << m_shifts[bit_index];
529
530 if (word_index >= m_data.size())
531 {
532 m_data.push_back(0);
533 }
534
536 ++m_size;
537}

◆ seq_k_compare() [1/2]

template<typename CHAR_T , unsigned CHAR_SIZE_BITS = sizeof(CHAR_T) * 8>
ResultLCP BitString< CHAR_T, CHAR_SIZE_BITS >::seq_k_compare ( const BitString< CHAR_T, CHAR_SIZE_BITS > &  other,
size_t  lcp 
) const
inlinenoexcept

Performs sequential comparison with another BitString, starting from a given LCP offset.

Compares this BitString with other, assuming the first lcp characters are equal. Compares up to the end of the shorter string.

Parameters
otherThe BitString to compare against.
lcpThe starting offset (longest common prefix length) for the comparison, in characters.
Returns
ResultLCP A struct containing the comparison result and the final LCP length.
Note
This comparison is performed entirely on the CPU. Equivalent to seq_k_compare(other, lcp, size()).

Definition at line 187 of file BitString.cuh.

188 {
189 return seq_k_compare(other, lcp, size());
190 }

◆ seq_k_compare() [2/2]

template<typename CHAR_T , unsigned CHAR_SIZE_BITS>
auto BitString< CHAR_T, CHAR_SIZE_BITS >::seq_k_compare ( const BitString< CHAR_T, CHAR_SIZE_BITS > &  other,
size_t  lcp,
size_t  max_compare 
) const
noexcept

Performs sequential comparison with another BitString, starting from a given LCP offset, up to a maximum length.

Iterates word by word, finds the first mismatch using XOR and countl_zero.

Compares this BitString with other, assuming the first lcp characters are already known to be equal. The comparison proceeds character by character (packed within words) sequentially, but stops strictly at lcp + max_compare characters or the end of the shorter string, whichever comes first.

Parameters
otherThe BitString to compare against.
lcpThe starting offset (longest common prefix length) for the comparison, in characters.
max_compareThe maximum number of additional characters to compare beyond the initial lcp. The comparison will not proceed beyond lcp + max_compare total characters from the start.
Returns
ResultLCP A struct containing the comparison result (std::strong_ordering) of the substrings up to the comparison limit and the final calculated LCP length (which will not exceed the limit). Returns std::strong_ordering::equal if the substrings match up to the limit, even if the full strings might differ later.
Note
This comparison is performed entirely on the CPU. Uses std::countl_zero.

Definition at line 546 of file BitString.cuh.

547{
548 const size_t min_size = std::min(size(), other.size());
549 const size_t max_compare_until = lcp + max_compare;
550 size_t word_index = lcp / ALPHA;
551
552 lcp -= lcp % ALPHA; // Reset to word boundary
553
554 while (lcp < min_size && lcp < max_compare_until)
555 {
556 const uintmax_t XOR = m_data[word_index] ^ other.m_data[word_index];
557
558 if (XOR == 0)
559 {
560 lcp += ALPHA;
561 ++word_index;
562 continue;
563 }
564
565 const size_t l_zero = std::countl_zero(XOR);
566
567 lcp += l_zero / CHAR_SIZE_BITS;
568
569 const size_t bit_index = lcp % ALPHA;
570
571 // Mismatch found within limit
573 const CHAR_T rhs = GET_CHAR(other.m_data[word_index], bit_index);
574
575 return { lhs <=> rhs, lcp };
576 }
577
578 if (lcp >= min_size)
579 {
580 return { size() <=> other.size(), min_size };
581 }
582
583 return { std::strong_ordering::equal, lcp };
584}

◆ size()

template<typename CHAR_T , unsigned CHAR_SIZE_BITS = sizeof(CHAR_T) * 8>
size_t BitString< CHAR_T, CHAR_SIZE_BITS >::size ( ) const
inlinenoexcept

Returns the number of characters stored in the BitString.

Returns
size_t The total number of characters.

Definition at line 129 of file BitString.cuh.

129{ return m_size; }

◆ to_file() [1/2]

template<typename CHAR_T , unsigned CHAR_SIZE_BITS>
void BitString< CHAR_T, CHAR_SIZE_BITS >::to_file ( const std::string &  filename) const

Writes the BitString contents to a file in binary format.

Opens the file, calls the stream version of to_file, and closes the file.

Serializes the size and the packed data array to the specified file.

Parameters
filenameThe path to the output file.
Exceptions
std::runtime_errorIf the file cannot be opened for writing.

Definition at line 727 of file BitString.cuh.

728{
729 std::ofstream file(filename, std::ios::binary);
730 if (!file)
731 {
732 throw std::runtime_error("Failed to open file for writing: " + filename);
733 }
734 to_file(file);
735 // file automatically closed by destructor
736}
void to_file(const std::string &filename) const
Writes the BitString contents to a file in binary format.

◆ to_file() [2/2]

template<typename CHAR_T , unsigned CHAR_SIZE_BITS>
void BitString< CHAR_T, CHAR_SIZE_BITS >::to_file ( std::ofstream &  file) const

Writes the BitString contents to an already open output file stream.

Writes the size, then the raw uintmax_t data. Does not perform error checking on writes.

Serializes the size and the packed data array to the stream.

Parameters
fileThe std::ofstream object, opened in binary mode.

Definition at line 720 of file BitString.cuh.

721{
722 file.write(reinterpret_cast<const char*>(&m_size), sizeof(size_t));
723 file.write(reinterpret_cast<const char*>(m_data.data()), m_data.size() * sizeof(uintmax_t));
724}

◆ to_string()

template<typename CHAR_T , unsigned CHAR_SIZE_BITS>
std::string BitString< CHAR_T, CHAR_SIZE_BITS >::to_string ( ) const
noexcept

Converts the BitString back to a standard std::string.

Iterates through characters using iterators and appends them to a string. Assumes CHAR_T is convertible to char.

Returns
std::string A string containing the characters stored in the BitString.
Note
This assumes CHAR_T is convertible to char.

Definition at line 775 of file BitString.cuh.

776{
777 std::string str;
778 str.reserve(size());
779
780 for (CHAR_T c : *this)
781 {
782 // Assumes CHAR_T is convertible to char, potential truncation if wider.
783 str.push_back(static_cast<char>(c));
784 }
785
786 return str;
787}

◆ word_count()

template<typename CHAR_T , unsigned CHAR_SIZE_BITS = sizeof(CHAR_T) * 8>
size_t BitString< CHAR_T, CHAR_SIZE_BITS >::word_count ( ) const
inlinenoexcept

Returns the number of uintmax_t words used for storage.

Returns
size_t The number of words in the internal data vector.

Definition at line 135 of file BitString.cuh.

135{ return m_data.size(); }

Friends And Related Symbol Documentation

◆ operator<<

template<typename CHAR_T , unsigned CHAR_SIZE_BITS = sizeof(CHAR_T) * 8>
template<typename CT , unsigned CSB>
std::ostream & operator<< ( std::ostream &  os,
const BitString< CT, CSB > &  bs 
)
friend

Member Data Documentation

◆ ALPHA

template<typename CHAR_T , unsigned CHAR_SIZE_BITS = sizeof(CHAR_T) * 8>
constexpr unsigned BitString< CHAR_T, CHAR_SIZE_BITS >::ALPHA = WORD_SIZE_BITS / CHAR_SIZE_BITS
staticconstexpr

Number of characters that can be packed into a single storage word.

Definition at line 63 of file BitString.cuh.

◆ m_data

template<typename CHAR_T , unsigned CHAR_SIZE_BITS = sizeof(CHAR_T) * 8>
std::vector<uintmax_t> BitString< CHAR_T, CHAR_SIZE_BITS >::m_data
private

Internal storage vector holding the packed character data.

Definition at line 250 of file BitString.cuh.

◆ m_masks

template<typename CHAR_T , unsigned CHAR_SIZE_BITS = sizeof(CHAR_T) * 8>
constexpr std::array<uintmax_t, ALPHA> BitString< CHAR_T, CHAR_SIZE_BITS >::m_masks = GET_MASKS()
staticconstexprprivate

Compile-time generated array of bit masks.

Definition at line 276 of file BitString.cuh.

◆ m_shifts

template<typename CHAR_T , unsigned CHAR_SIZE_BITS = sizeof(CHAR_T) * 8>
constexpr std::array<unsigned, ALPHA> BitString< CHAR_T, CHAR_SIZE_BITS >::m_shifts = GET_SHIFTS()
staticconstexprprivate

Compile-time generated array of bit shift amounts.

Definition at line 264 of file BitString.cuh.

◆ m_size

template<typename CHAR_T , unsigned CHAR_SIZE_BITS = sizeof(CHAR_T) * 8>
size_t BitString< CHAR_T, CHAR_SIZE_BITS >::m_size = 0
private

The number of characters stored in the BitString.

Definition at line 252 of file BitString.cuh.

◆ MIN_PAR_COMPARE_CHAR_SIZE

template<typename CHAR_T , unsigned CHAR_SIZE_BITS = sizeof(CHAR_T) * 8>
constexpr size_t BitString< CHAR_T, CHAR_SIZE_BITS >::MIN_PAR_COMPARE_CHAR_SIZE = MIN_PAR_COMPARE_WORD_SIZE * ALPHA
staticconstexpr

Minimum number of characters required to trigger parallel comparison. Derived from MIN_PAR_COMPARE_WORD_SIZE.

Definition at line 65 of file BitString.cuh.

◆ WORD_SIZE_BITS

template<typename CHAR_T , unsigned CHAR_SIZE_BITS = sizeof(CHAR_T) * 8>
constexpr unsigned BitString< CHAR_T, CHAR_SIZE_BITS >::WORD_SIZE_BITS = sizeof(uintmax_t) * 8
staticconstexpr

Size of the underlying storage word (uintmax_t) in bits.

Definition at line 61 of file BitString.cuh.


The documentation for this class was generated from the following file: