Skip to content

Commit

Permalink
Merge branch 'work-rp' into develop (see #15 wip)
Browse files Browse the repository at this point in the history
  • Loading branch information
CodePurble committed Aug 6, 2021
2 parents 7643314 + 8eee64f commit fe82570
Show file tree
Hide file tree
Showing 20 changed files with 777 additions and 141 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
# gdb
.gdb_history

*.ezw
perf/
build/
compile_commands.json

Expand Down
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ add_executable(main
./src/node.c
./src/queue.c
./src/stack.c
./src/bitstream.c
)

target_link_libraries(main PUBLIC wavelib m) # "m" to link math.h
# target_link_libraries(main PUBLIC wavelib gsl gslcblas m) # "m" to link math.h

28 changes: 28 additions & 0 deletions include/bitstream.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#ifndef BITSTREAM_H
#define BITSTREAM_H
#include <stdio.h>
#include "queue.h"

// 0b00111000
#define SYMB_MASK 0x38

typedef struct {
unsigned short threshold_pow;
unsigned int num_bytes;
unsigned char *bytes;
} mini_header;

enum file_op_mode {
A, // append
W // write
};

// OPTIMIZE: Maybe pass by reference? Soo many copies!!
// OPTIMIZE: Maybe pass by const reference when not mutating?

mini_header *create_mini_header(unsigned int threshold, Queue *symbols);
void write_bitstream_file(const char* filename, enum file_op_mode mode,
mini_header *m_hdr, unsigned int dim);
Queue* read_bitstream_file(const char* filename, Queue *header_queue, unsigned char *dim_pow);

#endif
48 changes: 48 additions & 0 deletions include/bitstream.h.old
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#ifndef BITSTREAM_H
#define BITSTREAM_H
#include "queue.h"

// TODO:
// A bitstream is a main header followed by groups of "mini-headers" and
// symbols packed into bytes
// Operations that need to be implemented:
// * Initialise bitstream
// * Close bitstream
// * Pack symbols into bytes
// * Create header and mini-headers
// * Write next set of symbols
// * Read next set of symbols

// WARNING:
// The __packed__ attribute will result in unsafe behaviour on non x86
// systems. Use this code with care.
// ref: https://stackoverflow.com/a/8568441
//
// Group 10 symbols together to save space
//
// Change of plans....... no more structs
// Just fall back to 2 symbols per byte, 2 MSBs are discarded
// I just want to finish this....
struct __attribute__((__packed__)) symbols_group {
unsigned char s0 : 3;
unsigned char s1 : 3;
unsigned char s2 : 3;
unsigned char s3 : 3;
unsigned char s4 : 3;
unsigned char s5 : 3;
unsigned char s6 : 3;
unsigned char s7 : 3;
unsigned char s8 : 3;
unsigned char s9 : 3;
};

struct symbol_set {
unsigned short threshold;
unsigned int size;
struct symbols_group *symbols;
};

void symbol_set_init(struct symbol_set *s_set, unsigned short threshold, unsigned int size);
void symbol_group_insert(struct symbols_group *s_grp, int count, unsigned char symbol);

#endif
12 changes: 11 additions & 1 deletion include/ezw.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,18 @@
#define EZW_H
#include "smap.h"

Queue *dominant_pass(Smap_tree_node *smap_root, int threshold);
// OPTIMIZE: Maybe pass by reference? Soo many copies!!
// OPTIMIZE: Maybe pass by const reference when not mutating?

void check_descendants(Smap_tree_node *parent, int threshold);
enum smap_symbol encode_coeff(float coeff, int threshold);
Queue *dominant_pass(Smap_tree_node *smap_root, int threshold);
Queue *subordinate_pass(Queue *dominant_list, int threshold);
// void ezw(Smap_tree_node *smap_root, unsigned char iter);
void ezw(const char *filename, Smap_tree_node *smap_root, int rows, int cols, unsigned char iter);
Smap_tree_node* reconstruct(unsigned char dim_pow, Queue *header_q);

// NOTE: when decoding, just do morton scan, but replace coeff with decoded
// NOTE: approximation only if the current node coeff is zero

#endif // EZW_H
13 changes: 12 additions & 1 deletion include/queue.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,22 @@
typedef struct Queue {
Node *head;
Node *tail;
int len;
} Queue;

enum q_type {
SMAP_TREE_NODE,
MINI_HDR,
INT,
DOUBLE
};

// OPTIMIZE: Maybe pass by reference? Soo many copies!!

Queue *enqueue(Queue *q, void *data);
Node *dequeue(Queue *q);
void free_queue(Queue *q);
void queue_pretty_print(Queue *q);
void queue_pretty_print(Queue *q, enum q_type t);

#endif // QUEUE_H

2 changes: 2 additions & 0 deletions include/sbtree.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ typedef struct SBtree_node {
enum sb_type type;
} SBtree_node;

// OPTIMIZE: Maybe pass by reference? Soo many copies!!

SBtree_node* sb_tree_init_root();
SBtree_node* sb_tree_insert(SBtree_node *root, enum sb_type t, double *coeffs);
SBtree_node* sb_treeify(int levels, double *input, int rows, int cols);
Expand Down
12 changes: 8 additions & 4 deletions include/smap.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,23 @@ enum smap_symbol { // significance map value
enum print_conf {
COEFF,
TYPE,
FULL
ALL
};

typedef struct Smap_tree_node {
double coeff;
struct Smap_tree_node *parent;
struct Smap_tree_node *children[4];
char isroot : 1;
enum smap_symbol type;
unsigned char not_available;
} Smap_tree_node;

// OPTIMIZE: Maybe pass by reference? Soo many copies!!

char* smap_symbol_to_str(enum smap_symbol s);

void smap_tree_print_levelorder(Smap_tree_node *root, enum print_conf p);
void smap_tree_print_preorder(Smap_tree_node *root, enum print_conf p);
Smap_tree_node *smap_tree_init_node(double coeff);
Smap_tree_node *smap_tree_init_root(double val,
Expand All @@ -35,7 +40,6 @@ Smap_tree_node *smap_tree_init_root(double val,

Queue *smap_tree_insert_quad(Queue *q, double *cvals);
Smap_tree_node *smap_treeify(SBtree_node *sb_root, int levels);



Smap_tree_node* smap_tree_reset(Smap_tree_node *root);
double *smap2levelorder(Smap_tree_node *root, int rows, int cols);
#endif // SMAP_H
2 changes: 2 additions & 0 deletions include/stack.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ typedef struct Stack {
Node *bottom;
} Stack;

// OPTIMIZE: Maybe pass by reference? Soo many copies!!

Stack *push(Stack *st, void *data);
Node *pop(Stack *st);
void free_stack(Stack *st);
Expand Down
27 changes: 27 additions & 0 deletions include/utils.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#ifndef UTILS_H
#define UTILS_H
#include<stdio.h>
#include "smap.h"

static inline void BOLD_CYAN_FG(char *str)
{
Expand All @@ -25,6 +26,20 @@ static inline void DEBUG_STR(char *str, char *x)
printf("%s:%s\n", str, x);
}

static inline void DEBUG_UINT_PAIR(char *str, unsigned int *x)
{
BOLD_CYAN_FG("[debug_uint_pair] ");
printf("%s:(%u %u)\n", str, x[0], x[1]);
}

static inline void DEBUG_ARR_BYTE(unsigned char *x, int len) {
BOLD_CYAN_FG("[debug_arr_byte] ");
for(int i = 0; i < len; i++) {
printf("%x ", x[i]);
}
printf("\n");
}

static inline void DEBUG_ARR_F_1(double *x, int len) {
BOLD_CYAN_FG("[debug_arr_f_1] ");
for(int i = 0; i < len; i++) {
Expand All @@ -43,6 +58,15 @@ static inline void DEBUG_ARR_F_2(double **x, int r, int c) {
}
}

static inline void DEBUG_SMAP_NODE(Smap_tree_node *n) {
if(n) {
DEBUG_DOUBLE("coeff", n->coeff);
}
else {
DEBUG_STR("coeff", "NULL");
}
}

#define DEBUG_BLANK DEBUG_STR("", "")

void read_binary_file(FILE *infile, unsigned char *dest_arr, int rows, int cols);
Expand All @@ -51,4 +75,7 @@ void double_to_uchar(double *src, unsigned char* dest, int rows, int cols);
double max_double(double *arr, int len);
double** quads_from_arr(double *arr, int rows, int cols);

double* smap2arr(Smap_tree_node* smap_root, int rows, int cols);
unsigned int* morton_decode(unsigned int morton, unsigned int *inds);

#endif // UTILS_H
86 changes: 86 additions & 0 deletions src/bitstream.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
#include <stdlib.h>
#include <math.h>
#include "utils.h"
#include "bitstream.h"

mini_header *create_mini_header(unsigned int threshold, Queue *symbols)
{
mini_header *m_hdr = malloc(sizeof(mini_header));
m_hdr->num_bytes = (unsigned int) (symbols->len / 2) + (symbols->len % 2);
unsigned char curr_byte = 0xff;
unsigned char *bytes = (unsigned char *) calloc(m_hdr->num_bytes, sizeof(unsigned char));

// NOTE: Do we really need this??
Node *node_pair[2] = {NULL};

m_hdr->threshold_pow = (unsigned short) log2(threshold);
unsigned int ind = 0;
while(symbols->head) {
curr_byte = 0xff;
// Pack pairs of symbols into bytes
for(int i = 0; i < 2; i++) {
node_pair[i] = dequeue(symbols);
if(node_pair[i]) {
curr_byte = (curr_byte << 3) | *(unsigned char *) node_pair[i]->data;
}
}
bytes[ind] = curr_byte;
ind++;
}
m_hdr->bytes = bytes;
// DEBUG_INT("t", m_hdr->threshold_pow);
// DEBUG_INT("n", m_hdr->num_bytes);
// DEBUG_ARR_BYTE(m_hdr->bytes, m_hdr->num_bytes);
return m_hdr;
}

void write_bitstream_file(const char* filename, enum file_op_mode mode,
mini_header *m_hdr, unsigned int dim)
{
FILE *fptr = NULL;
unsigned char dim_pow = log2(dim);
// DEBUG_INT("num_bytes", m_hdr->num_bytes);
if(mode == A) {
fptr = fopen(filename, "ab");
}
else if(mode == W) {
fptr = fopen(filename, "wb");
if(fwrite(&dim_pow, sizeof(dim_pow), 1, fptr) != 1) {
fprintf(stderr, "Error while writing file: %s", filename);
exit(1);
}
}
if(fwrite(&m_hdr->threshold_pow, sizeof(m_hdr->threshold_pow), 1, fptr) != 1) {
fprintf(stderr, "Error while writing file: %s", filename);
exit(1);
}
// if(fwrite(&m_hdr->num_bytes, sizeof(m_hdr->num_bytes), 1, fptr) != 1) {
if(fwrite(&m_hdr->num_bytes, sizeof(unsigned int), 1, fptr) != 1) {
fprintf(stderr, "Error while writing file: %s", filename);
exit(1);
}
// DEBUG_ARR_BYTE(m_hdr->bytes, m_hdr->num_bytes);
if(fwrite(m_hdr->bytes, sizeof(m_hdr->bytes[0]), m_hdr->num_bytes, fptr) != m_hdr->num_bytes) {
fprintf(stderr, "Error while writing file: %s", filename);
exit(1);
}
fclose(fptr);
}

Queue* read_bitstream_file(const char* filename, Queue *header_queue, unsigned char *dim_pow)
{
FILE *fptr = fopen(filename, "rb");

fread(dim_pow, sizeof(unsigned char), 1, fptr);

unsigned short threshold_pow;
while(fread(&threshold_pow, sizeof(unsigned short), 1, fptr) != 0) {
mini_header *curr_hdr = (mini_header *) malloc(sizeof(mini_header));
curr_hdr->threshold_pow = threshold_pow;
fread(&curr_hdr->num_bytes, sizeof(unsigned int), 1, fptr);
curr_hdr->bytes = calloc(curr_hdr->num_bytes, sizeof(unsigned int));
fread(curr_hdr->bytes, sizeof(unsigned char), curr_hdr->num_bytes, fptr);
header_queue = enqueue(header_queue, curr_hdr);
}
return header_queue;
}
45 changes: 45 additions & 0 deletions src/bitstream.c.old
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#include "bitstream.h.old"
#include "smap.h"

void symbol_set_init(struct symbol_set *s_set, unsigned short threshold, unsigned int size)
{
s_set->threshold = threshold;
s_set->size = size;
}

void symbol_group_insert(struct symbols_group *s_grp, int count, unsigned char symbol)
{
switch(count) {
case 0:
s_grp->s0 = symbol;
break;
case 1:
s_grp->s1 = symbol;
break;
case 2:
s_grp->s2 = symbol;
break;
case 3:
s_grp->s3 = symbol;
break;
case 4:
s_grp->s4 = symbol;
break;
case 5:
s_grp->s5 = symbol;
break;
case 6:
s_grp->s6 = symbol;
break;
case 7:
s_grp->s7 = symbol;
break;
case 8:
s_grp->s8 = symbol;
break;
case 9:
s_grp->s9 = symbol;
break;
default: return;
}
}
Loading

0 comments on commit fe82570

Please sign in to comment.