~obeancomputer/bitter

7806827bea6513c853a33754b8c57141daa32998 — ocsmit 1 year, 1 month ago a1dd574
Update how word size of bitarray is decided
5 files changed, 27 insertions(+), 41 deletions(-)

M src/bitarr.c
M src/bitarr.h
M src/bitarr_io.c
M src/bitops.c
M tests/tests.c
M src/bitarr.c => src/bitarr.c +8 -9
@@ 2,20 2,20 @@
#include "bitops.h"
#include <stdint.h>

BitArray* BitArray_calloc(uint32_t n, uint8_t l)
BitArray* BitArray_calloc(uint32_t n, uint8_t element_size, size_t word_size)
{
    unsigned int n_entries = 1 + (((l * n) - 1) / WORD_SIZE);
    unsigned int n_entries = 1 + (((element_size * n) - 1) / 32);
    // space for bitarray + space needed for n_entries of word_size
    BitArray *bitarr = calloc(1, sizeof(BitArray) + WORD_SIZE * n_entries);
    BitArray *bitarr = calloc(1, sizeof(BitArray) + (word_size * CHAR_BIT) * n_entries);
    if (bitarr == NULL) {
        printf("Couldn't allocate memory for vector.\n");
        exit(EXIT_FAILURE);
    }
    // Set values
    bitarr->l = l;
    bitarr->width = WORD_SIZE;
    bitarr->element_size = element_size;
    bitarr->width = word_size * CHAR_BIT;
    bitarr->n = n;
    

    return bitarr;
}



@@ 23,10 23,9 @@ void BitArray_free(BitArray *bitarr) {
    free(bitarr);
}


BitArray* BitArray_init(unsigned int A[], uint32_t n, uint8_t l)
BitArray* BitArray_init(unsigned int A[], uint32_t n, uint8_t element_size, size_t word_size)
{
    BitArray* bit_arr = BitArray_calloc(n, l);
    BitArray* bit_arr = BitArray_calloc(n, element_size, word_size);
    // Compress values from A into BitArray
    unsigned int i;
    for (i = 0; i < n; ++i) BitArray_write(bit_arr, i, A[i]);

M src/bitarr.h => src/bitarr.h +10 -20
@@ 17,7 17,7 @@
 *         │      │      │      │      │      │      │      │      │      │
 *         ▼      ▼      ▼      ▼      ▼      ▼      ▼      ▼      ▼      ▼
 *     ┌──────┬──────┬──────┬──────┬──────┬──────┬──────┬──────┬──────┬──────┐
 *  B  │10100 │10010 │10110 │10110 │10000 │10101 │01011 │10110 │10101 │10101 │ 
 *  B  │10100 │10010 │10110 │10110 │10000 │10101 │01011 │10110 │10101 │10101 │
 *     └──────┴──────┴──────┴──────┴──────┴──────┴──────┴──────┴──────┴──────┘
 *         │      │      │      │      │      │      │      │      │      │
 *         │      │      │  B is a virtual bit array │      │      │      │


@@ 63,6 63,7 @@
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <limits.h>


typedef enum {


@@ 72,25 73,13 @@ typedef enum {
} BITARR_ERROR;


// The size of each 'word' in W is 4 bytes (32 bits)
// sizeof(uint32_t) == sizeof(int) == (sizeof(unsigned int) * 2)
//
// NOTE: 
// What is the valid type (or size) to consider as the systems word size?
// Is it appropriate to just define the size in our implementation?
//  - https://stackoverflow.com/q/35843365
//  - https://stackoverflow.com/q/14792068
//  
//
#define WORD_SIZE (sizeof(uint32_t) * 8)

/**
 * @struct BitArray
 *
 * Compact BitArray implementation where each element in the original array (A)
 * is the same size.
 *
 * @var BitArray.l 
 * @var BitArray.l
 *  number of bits to store each value in A
 * @var BitArray.width
 *  number of bits of each member in v (e.g. 32)


@@ 100,10 89,10 @@ typedef enum {
 *  compressed version of A (v)
 */
typedef struct {
  uint8_t l;       
  uint8_t width;   
  size_t element_size;
  uint8_t width;
  uint32_t n;
  unsigned int v[]; 
  unsigned int v[];
} BitArray;




@@ 114,12 103,12 @@ typedef struct {
 * @param l             Size in bits of each item
 * @return              Pointer to BitArray
 */
BitArray* BitArray_calloc(uint32_t n, uint8_t l);
BitArray* BitArray_calloc(uint32_t n, uint8_t element_size, size_t word_size);

/**
 * @brief Free BitArray allocated on the heap
 *
 * @param bitarr 
 * @param bitarr
 */
void BitArray_free(BitArray *bitarr);



@@ 131,7 120,8 @@ void BitArray_free(BitArray *bitarr);
 * @param l         Maximum number of bits for each element in A
 * @return          pointer to BitArray
 */
BitArray* BitArray_init(unsigned int A[], uint32_t length, uint8_t l);
BitArray* BitArray_init(unsigned int A[], uint32_t length, uint8_t element_size, 
  size_t word_size);


#endif // BITARR_H_

M src/bitarr_io.c => src/bitarr_io.c +4 -8
@@ 1,8 1,4 @@
#include "bitarr_io.h"
#include "bitarr.h"
#include <stdio.h>
#include <string.h>


void BitArray_save(BitArray* bitarr, FILE *fp)
{


@@ 11,12 7,12 @@ void BitArray_save(BitArray* bitarr, FILE *fp)
    fwrite(&BIT_MAGIC_NUMBER, sizeof(char), strlen(BIT_MAGIC_NUMBER), fp);

    // BitArray metadata needed to construct data structure
    fwrite(&bitarr->l, sizeof(uint8_t), 1, fp);
    fwrite(&bitarr->element_size, sizeof(uint8_t), 1, fp);
    fwrite(&bitarr->width, sizeof(uint8_t), 1, fp);
    fwrite(&bitarr->n, sizeof(uint32_t), 1, fp);

    // Write out compressed array
    unsigned int n_entries = 1 + (((bitarr->l * bitarr->n) - 1) / WORD_SIZE);
    unsigned int n_entries = 1 + (((bitarr->element_size * bitarr->n) - 1) / bitarr->width);
    fwrite(&(bitarr->v), sizeof(unsigned int), n_entries, fp);
}



@@ 37,9 33,9 @@ BitArray* BitArray_open(FILE *fp)
    fread(&l, sizeof(uint8_t), 1, fp);
    fread(&width, sizeof(uint8_t), 1, fp);
    fread(&n, sizeof(uint32_t), 1, fp);
    BitArray* bitarr = BitArray_calloc(n, l);
    BitArray* bitarr = BitArray_calloc(n, l, width / CHAR_BIT);

    // Read in compressed array
    fread(&(bitarr->v), WORD_SIZE, 1, fp);
    fread(&(bitarr->v), width, 1, fp);
    return bitarr;
}

M src/bitops.c => src/bitops.c +4 -3
@@ 14,7 14,6 @@ extern inline unsigned int sig_bit_idx(unsigned int j, unsigned int word_size)
// -- Single bit ops ----------------------------------------------------------

unsigned int BitArray_bitread(BitArray* bit_arr, unsigned int j) {
  // TODO: Add range checking
  return (bit_arr->v[j/bit_arr->width] >> (j % bit_arr->width)) & 1;
}



@@ 70,7 69,8 @@ unsigned int BitArray_read(BitArray* bit_arr, unsigned int i)
    fprintf(stderr, "%s:%d Out of bounds index\n", __FILE__, __LINE__);
    exit(OUT_OF_BOUNDS);
  }
  return BitArray_bitsread(bit_arr, i*bit_arr->l, (i+1)*bit_arr->l-1); 
  return BitArray_bitsread(bit_arr, i*bit_arr->element_size,
    (i+1)*bit_arr->element_size-1); 
}

// -- Writing -----------------------------------------------------------------


@@ 115,5 115,6 @@ void BitArray_write(BitArray* bit_arr, unsigned int i, unsigned int x)
    fprintf(stderr, "%s:%d Out of bounds index\n", __FILE__, __LINE__);
    exit(OUT_OF_BOUNDS);
  }
  BitArray_bitswrite(bit_arr, i*bit_arr->l, (i+1)*bit_arr->l-1, x); 
  BitArray_bitswrite(bit_arr, i*bit_arr->element_size, 
    (i+1)*bit_arr->element_size-1, x); 
}

M tests/tests.c => tests/tests.c +1 -1
@@ 29,7 29,7 @@ unsigned int B_sig_ordered[64] = {
    0,1,0,0,1,1,0,1,1,0,1,0,1,1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0
};
unsigned int correct_W[2] = { 3943389780, 177586} ;
BitArray* bit_arr = BitArray_init(A, (sizeof(A)/sizeof(A[0])), 5);
BitArray* bit_arr = BitArray_init(A, (sizeof(A)/sizeof(A[0])), 5, sizeof(uint32_t));

static char bit_arr_fp[] = "./data/bitarr_test.bit";