Intermediate commit.
Intermediate commit. Not complete yet.
diff --git a/Makefile b/Makefile
index 29ea20d..d124a2e 100644
--- a/Makefile
+++ b/Makefile
@@ -4,14 +4,15 @@
MAINO = $(patsubst %.c,%.o,$(MAIN))
DEPS = $(patsubst %.c,%.d,$(SRCS) $(MAIN))
EXECS = $(patsubst %.c,%,$(MAIN))
+FLAGS = -std=c99 -Wall
all : $(EXECS)
clean :
- rm -f $(OBJS) $(DEPS) $(MAINO)
+ rm -f $(OBJS) $(DEPS) $(MAINO) $(EXECS)
%.o : %.c
- gcc -MD -c $<
+ gcc $(FLAGS) -MD -c $<
%.d : %.c
- gcc -MD -c $<
+ gcc $(FLAGS) -MD -c $<
%.main : %.main.o $(OBJS)
- gcc $< $(OBJS) -o $@
+ gcc $(FLAGS) $< $(OBJS) -o $@
-include $(DEPS)
diff --git a/median.c b/median.c
index face1ef..3cc991a 100644
--- a/median.c
+++ b/median.c
@@ -1,48 +1,89 @@
#include "median.h"
#include <strings.h>
+// The buffer is cast into this struct.
typedef struct metadata {
- size_t buffer_size;
- size_t nLevels;
- unsigned char data[0];
+ size_t bufferSize; // Number of bytes available for use.
+ size_t nLevels; // Number of buffers available.
+ size_t currentBufferIdx; // The index of the currently active buffer.
+ unsigned char data[0]; // The start of the data.
} metadata_t;
+typedef uint32_t parity_t;
+
+typedef struct bufferdata {
+ parity_t parity; // The parity of this buffer.
+ size_t level; // The level of this buffer.
+ size_t occupancy; // Number of occupants for this buffer.
+} bufferdata_t;
+
+
+static const parity_t PARITY_NONE = 0; // The parity is none.
+static const parity_t PARITY_LEFT = 1; // The buffer has LEFT parity.
+static const parity_t PARITY_RIGHT = 2; // The buffer has RIGHT parity.
+
median_error_t median_suggest_buffer_size(double epsilon, size_t maxN, size_t *suggested_size){
// First check for sane parameters.
if (maxN <= 0) return MEDIAN_ERROR_INVALID_PARAMETERS;
+
// First compute the size of each buffer.
size_t n = (1.0/epsilon)+ 1;
// If n is too large, you are looking for too fine an approximation.
// This is not the right algorithm. Maybe consider random sampling instead.
if (n > 100000) return MEDIAN_ERROR_INVALID_PARAMETERS;
+
// Compute the log of maxN using a divide by 2 loop.
// There is no need to make this more complicated at this stage. It's not
// a deep loop function.
size_t nLevels = 1;
- while(maxN = (maxN >> 1)) nLevels++;
- // What is the size of the metadata structure
- size_t extra = sizeof(metadata_t);
- // This is the total.
- *suggested_size = n * nLevels + extra;
+ while((maxN = (maxN >> 1))) nLevels++;
- return MEDIAN_ERROR_OK;
+ // This is the total bytes needed.
+ // One metadata block. nLevels bufferdata_t blockes.
+ // and n * nLevels median_data_t elements.
+ *suggested_size = n * nLevels * sizeof(median_data_t) + nLevels * sizeof(bufferdata_t) + sizeof(metadata_t);
+
+ // Things worked. Return MEDIAN_OK
+ return MEDIAN_OK;
}
median_error_t median_init_buffer(void * buffer, size_t buffer_size, double epsilon, size_t maxN, median_buffer_t *initialized_buffer){
+
// Initialize.
- size_t expected_size = 0;
- median_error_t error = MEDIAN_ERROR_OK;;
+ size_t expectedSize = 0;
+ median_error_t error = MEDIAN_OK;
+
// First run median_suggest_buffer_size
- if ((error = median_suggest_buffer_size(epsilon,maxN,&expected_size)) != MEDIAN_ERROR_OK) return error;
+ if ((error = median_suggest_buffer_size(epsilon,maxN,&expectedSize)) != MEDIAN_OK) return error;
// Ensure that the buffer is large enough.
- if (expected_size > buffer_size) return MEDIAN_ERROR_BUFFER_TOO_SMALL;
+ if (expectedSize > buffer_size) return MEDIAN_ERROR_BUFFER_TOO_SMALL;
+
+ // Cast the buffer as metadata_t so that we can initialize the metadata block.
metadata_t * m = (metadata_t *)buffer;
+ // Initialize the metadata block.
+ m->bufferSize = buffer_size - sizeof(metadata_t);
+ m->nLevels = m->bufferSize/((maxN * sizeof(median_data_t)) + sizeof(bufferdata_t));
+ m->currentBufferIdx = 0;
+ bzero(m->data, m->bufferSize);
- m->buffer_size = buffer_size - sizeof(metadata_t);
- m->nLevels = m->buffer_size/(maxN * sizeof(median_data_t));
- bzero(m->data, m->buffer_size);
+ // cast the data part as an array of bufferdata_t blocks.
+ // and initialize each of the blocks.
+ bufferdata_t * t = (bufferdata_t *) m->data;
+ for(size_t i = 0; i < m->nLevels; i++) {
+ t[i].parity = PARITY_NONE;
+ t[i].level = 0;
+ t[i].occupancy = 0;
+ }
+ // Populate the return value.
+ *initialized_buffer = (median_buffer_t)buffer;
return error;
}
+median_error_t median_insert_data(median_buffer_t buffer, median_data_t data){
+ // First locate the empty buffer.
+ return MEDIAN_OK;
+}
-
+median_error_t median_output_median(median_buffer_t buffer, median_data_t *approximate_median){
+ return MEDIAN_OK;
+}
diff --git a/median.h b/median.h
index 90a3650..0ea0495 100644
--- a/median.h
+++ b/median.h
@@ -31,23 +31,23 @@
// All the error codes.
// No Error.
-static median_error_t MEDIAN_ERROR_OK = 0;
+static const median_error_t MEDIAN_OK = 0;
// The parameters are meaningless (for example, asking for neg values
// for epsilon).
-static median_error_t MEDIAN_ERROR_INVALID_PARAMETERS = -1;
+static const median_error_t MEDIAN_ERROR_INVALID_PARAMETERS = -1;
// The buffer allocated is too small for the parameters requested.
-static median_error_t MEDIAN_ERROR_BUFFER_TOO_SMALL = -2;
+static const median_error_t MEDIAN_ERROR_BUFFER_TOO_SMALL = -2;
// Overflow because MaxN has been exceeded.
-static median_error_t MEDIAN_ERROR_MAX_N_EXCEEDED = -3;
+static const median_error_t MEDIAN_ERROR_MAX_N_EXCEEDED = -3;
// Indicates that the size of the largest possible dataset is not known.
-static size_t MEDIAN_MAX_N_UNKNOWN = 0;
+static const size_t MEDIAN_MAX_N_UNKNOWN = 0;
// The default size of the largest possible dataset.
-static size_t MEDIAN_MAX_N_DEFAULT = 1024*1024*1024; // 1G.
+static const size_t MEDIAN_MAX_N_DEFAULT = 1024*1024*1024; // 1G.
// This routine returns a suggested size for a buffer to hold all the
// state needed for a median calculation. Here epsilon is the permissible error.
diff --git a/median.main.c b/median.main.c
index 4879c04..59c8a53 100644
--- a/median.main.c
+++ b/median.main.c
@@ -1,9 +1,25 @@
#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
#include "median.h"
+// A sinple main routine meant as an example,
+// and also to unit test most of the intersting
+// functions of the median module.
int main(int argc, char * argv[]) {
+ // Call suggest buffer size to determine the size of the buffer
+ // we need to build the data structure.
size_t n = 0;
- median_suggest_buffer_size(.001, 1000, &n);
+ assert(median_suggest_buffer_size(.001, 1000, &n) == MEDIAN_OK);
+ // Print the number out.
printf("%ld\n", n);
+
+ // Allocate the buffer of the required size. And then
+ // initialize it (median_init_buffer).
+ void * b = malloc(n);
+ median_buffer_t buf;
+ assert(median_init_buffer(b, n, .001, 1000, &buf) == MEDIAN_OK);
+
+ // All done, return 0
return 0;
}