Bouncer / bouncer / linear_sketches / headers / countmin.h
countmin.h
Raw
#ifndef COUNT_MIN_H
#define COUNT_MIN_H

/*******************************************************/
/*    Inherited Linear sketch/ countmin declarations    */
/*******************************************************/

typedef struct {
    LinearSketch super; // inherits from the linear sketch class 
    uint32_t* hash_table; // table storing random bits that acts as hash function 
    uint32_t* X; 
    uint8_t hash_bit : 1; 
    uint16_t seed; 
} CountMin;

static void CountMin_dealloc(CountMin*); 
static PyObject *CountMin_new(PyTypeObject*, PyObject *, PyObject *);
static int CountMin_init(CountMin *, PyObject *, PyObject *);
static PyObject *CountMin_update(CountMin *, PyObject * );
static PyObject *CountMin_query(CountMin *, PyObject * );
static PyObject *CountMin_combine(PyObject *, PyObject *, PyObject *);
static PyObject*get_shape(CountMin* , void* );
static PyObject*get_hasher(CountMin*, void* );
static PyObject*get_sketch(CountMin*, void* );

static PyObject*
get_shape(CountMin* self, void* closure){
    PyObject* shape; 
    float epsilon, delta; 
    uint32_t s,t; 

    epsilon = byte_to_float(self->super.epsilon);
    delta = byte_to_float(self->super.delta); 

    s = (uint32_t) ceil(2/ (float) epsilon); 
    t = ceil( log2(1/(float) delta));

     if(self->hash_bit == 0){
        s = nextPrime(s); 
    }

    if( (shape = PyTuple_Pack(2, PyLong_FromUnsignedLong((unsigned long) t), PyLong_FromUnsignedLong((unsigned long) s))) == NULL){
        PyErr_NoMemory();
        return Py_None;
    }

    return shape; 
}

static PyObject*
get_hasher(CountMin* self, void* closure)
{
    const char* s;
    if(self->hash_bit == 0){
        s = "CW";
    }
    else if(self->hash_bit == 1){
        s = "mult-shift";
    }
    return Py_BuildValue("s#", s, strlen(s));
}

static PyObject*
get_sketch(CountMin* self, void* closure){
    PyObject* list; 
    float epsilon, delta; 
    uint32_t s,t; 
    
    epsilon = byte_to_float(self->super.epsilon);
    delta = byte_to_float(self->super.delta); 

    s = (uint32_t) ceil(2/ (float) epsilon); 
    t = ceil( log2(1/(float) delta));

    if(self->hash_bit == 0){
        s = nextPrime(s); 
    }

    list = PyList_New(t);
    for(uint32_t i = 0; i < t; i++){
        PyObject* temp = PyList_New(s);
        for(uint32_t j = 0; j < s; j++){
            PyList_SetItem(temp, j, Py_BuildValue("i", self->X[i*t + j]));
        }
        PyList_SetItem(list, i, temp);
    }
    return list; 
}


PyGetSetDef get_CountMin_sets[] = {
     {"shape",  /* name */
     (getter) get_shape,
     NULL,
     NULL,  /* doc */
     NULL /* closure */},
     {"hasher",  /* name */
     (getter) get_hasher,
     NULL,
     NULL,  /* doc */
     NULL /* closure */},
     {"sketch",  /* name */
     (getter) get_sketch,
     NULL,
     NULL,  /* doc */
     NULL /* closure */},
    {NULL}
};

static PyMethodDef CountMin_methods[] = {
    {"update", (PyCFunction) CountMin_update, METH_VARARGS,
     "Updates the sketch with a new token input from the stream"
    },
    {"query", (PyCFunction) CountMin_query, METH_VARARGS,
     "Output the counter estimate"
    },
    {"combine", (PyCFunction) CountMin_combine, METH_VARARGS | METH_KEYWORDS,
     "Combine two CountMin skeches"
    },
    {NULL}  /* Sentinel */
};


static PyTypeObject CountMin_type = {
    PyVarObject_HEAD_INIT(NULL, 0)
    .tp_name = "sketches.CountMin",
    .tp_doc = "CountMin Sketch class",
    .tp_basicsize = sizeof(CountMin),
    .tp_itemsize = 0,
    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
    .tp_new = CountMin_new,
    .tp_init = (initproc)CountMin_init,
    .tp_dealloc = (destructor)CountMin_dealloc,
    .tp_methods = CountMin_methods,
    .tp_base = &LinearSketch_type, 
    .tp_getset = get_CountMin_sets,
};

#endif //COUNT_MIN_H