<commit_before>// Copyright (c) 2013 Spotify AB
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.

#include "annoylib.h"
#include "kissrandom.h"
#include "Python.h"
#include "structmember.h"
#include <exception>
#include <stdint.h>

#if PY_MAJOR_VERSION >= 3
#define IS_PY3K
#endif

#ifndef Py_TYPE
    #define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
#endif

#ifdef IS_PY3K
    #define PyInt_FromLong PyLong_FromLong
#endif

template class AnnoyIndexInterface<int32_t, float>;

// annoy python object
typedef struct {
  PyObject_HEAD
  int f;
  AnnoyIndexInterface<int32_t, float>* ptr;
} py_annoy;

static PyObject *
py_an_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
  py_annoy *self;
  self = (py_annoy *)type->tp_alloc(type, 0);
  if (self == NULL) {
    return NULL;
  }
  const char *metric = NULL;

  if (!PyArg_ParseTuple(args, "i|s", &self->f, &metric))
    return NULL;
  if (!metric || !strcmp(metric, "angular")) {
   self->ptr = new AnnoyIndex<int32_t, float, Angular, Kiss64Random>(self->f);
  } else if (!strcmp(metric, "euclidean")) {
    self->ptr = new AnnoyIndex<int32_t, float, Euclidean, Kiss64Random>(self->f);
  } else if (!strcmp(metric, "manhattan")) {
    self->ptr = new AnnoyIndex<int32_t, float, Manhattan, Kiss64Random>(self->f);
  } else {
    PyErr_SetString(PyExc_ValueError, "No such metric");
    return NULL;
  }

  return (PyObject *)self;
}

static int
py_an_init(py_annoy *self, PyObject *args, PyObject *kwds) {
  // Seems to be needed for Python 3
  const char *metric = NULL;
  PyArg_ParseTuple(args, "i|s", &self->f, &metric);
  return 0;
}

static void
py_an_dealloc(py_annoy* self) {
  if (self->ptr) {
    delete self->ptr;
  }
  Py_TYPE(self)->tp_free((PyObject*)self);
}

static PyMemberDef py_annoy_members[] = {
  {(char*)"_f", T_INT, offsetof(py_annoy, f), 0,
   (char*)""},
  {NULL}	/* Sentinel */
};

static PyObject *
py_an_load(py_annoy *self, PyObject *args) {
  char* filename;
  bool res = false;
  if (!self->ptr)
    Py_RETURN_NONE;
  if (!PyArg_ParseTuple(args, "s", &filename))
    Py_RETURN_NONE;

  res = self->ptr->load(filename);

  if (!res) {
    PyErr_SetFromErrno(PyExc_IOError);
    return NULL;
  }
  Py_RETURN_TRUE;
}

static PyObject *
py_an_save(py_annoy *self, PyObject *args) {
  char *filename;
  bool res = false;
  if (!self->ptr)
    Py_RETURN_NONE;
  if (!PyArg_ParseTuple(args, "s", &filename))
    Py_RETURN_NONE;

  res = self->ptr->save(filename);

  if (!res) {
    PyErr_SetFromErrno(PyExc_IOError);
    return NULL;
  }
  Py_RETURN_TRUE;
}

PyObject*
get_nns_to_python(const vector<int32_t>& result, const vector<float>& distances, int include_distances) {
  PyObject* l = PyList_New(result.size());
  for (size_t i = 0; i < result.size(); i++)
    PyList_SetItem(l, i, PyInt_FromLong(result[i]));
  if (!include_distances)
    return l;

  PyObject* d = PyList_New(distances.size());
  for (size_t i = 0; i < distances.size(); i++)
    PyList_SetItem(d, i, PyFloat_FromDouble(distances[i]));

  PyObject* t = PyTuple_New(2);
  PyTuple_SetItem(t, 0, l);
  PyTuple_SetItem(t, 1, d);

  return t;
}

static PyObject*
py_an_get_nns_by_item(py_annoy *self, PyObject *args) {
  int32_t item, n, search_k=-1, include_distances=0;
  if (!self->ptr)
    Py_RETURN_NONE;
  if (!PyArg_ParseTuple(args, "ii|ii", &item, &n, &search_k, &include_distances))
    Py_RETURN_NONE;

  vector<int32_t> result;
  vector<float> distances;

  Py_BEGIN_ALLOW_THREADS;
  self->ptr->get_nns_by_item(item, n, search_k, &result, include_distances ? &distances : NULL);
  Py_END_ALLOW_THREADS;

  return get_nns_to_python(result, distances, include_distances);
}

static PyObject*
py_an_get_nns_by_vector(py_annoy *self, PyObject *args) {
  PyObject* v;
  int32_t n, search_k=-1, include_distances=0;
  if (!self->ptr)
    Py_RETURN_NONE;
  if (!PyArg_ParseTuple(args, "Oi|ii", &v, &n, &search_k, &include_distances))
    Py_RETURN_NONE;

  vector<float> w(self->f);
  for (int z = 0; z < PyList_Size(v) && z < self->f; z++) {
    PyObject *pf = PyList_GetItem(v,z);
    w[z] = PyFloat_AsDouble(pf);
  }

  vector<int32_t> result;
  vector<float> distances;

  Py_BEGIN_ALLOW_THREADS;
  self->ptr->get_nns_by_vector(&w[0], n, search_k, &result, include_distances ? &distances : NULL);
  Py_END_ALLOW_THREADS;

  return get_nns_to_python(result, distances, include_distances);
}

static PyObject*
py_an_get_item_vector(py_annoy *self, PyObject *args) {
  int32_t item;
  if (!self->ptr)
    Py_RETURN_NONE;
  if (!PyArg_ParseTuple(args, "i", &item))
    Py_RETURN_NONE;

  vector<float> v(self->f);
  self->ptr->get_item(item, &v[0]);
  PyObject* l = PyList_New(self->f);
  for (int z = 0; z < self->f; z++) {
    PyList_SetItem(l, z, PyFloat_FromDouble(v[z]));
  }

  return l;
}

static PyObject*
py_an_add_item(py_annoy *self, PyObject *args) {
  PyObject* l;
  int32_t item;
  if (!self->ptr)
    Py_RETURN_NONE;
  if (!PyArg_ParseTuple(args, "iO", &item, &l))
    Py_RETURN_NONE;

  vector<float> w(self->f, 0.0);
  for (int z = 0; z < self->f; z++) {
    PyObject *pf = PyList_GetItem(l,z);
    w[z] = PyFloat_AsDouble(pf);
  }
  self->ptr->add_item(item, &w[0]);

  Py_RETURN_NONE;
}

static PyObject *
py_an_build(py_annoy *self, PyObject *args) {
  int q;
  if (!self->ptr)
    Py_RETURN_NONE;
  if (!PyArg_ParseTuple(args, "i", &q))
    Py_RETURN_NONE;

  Py_BEGIN_ALLOW_THREADS;
  self->ptr->build(q);
  Py_END_ALLOW_THREADS;

  Py_RETURN_TRUE;
}

static PyObject *
py_an_unbuild(py_annoy *self, PyObject *args) {
  if (!self->ptr)
    Py_RETURN_NONE;

  Py_BEGIN_ALLOW_THREADS;
  self->ptr->unbuild();
  Py_END_ALLOW_THREADS;

  Py_RETURN_TRUE;
}

static PyObject *
py_an_unload(py_annoy *self, PyObject *args) {
  if (!self->ptr)
    Py_RETURN_NONE;

  self->ptr->unload();

  Py_RETURN_TRUE;
}

static PyObject *
py_an_get_distance(py_annoy *self, PyObject *args) {
  int32_t i, j;
  if (!self->ptr)
    Py_RETURN_NONE;
  if (!PyArg_ParseTuple(args, "ii", &i, &j))
    Py_RETURN_NONE;

  double d = self->ptr->get_distance(i,j);
  return PyFloat_FromDouble(d);
}

static PyObject *
py_an_get_n_items(py_annoy *self, PyObject *args) {
  if (!self->ptr)
    Py_RETURN_NONE;

  int32_t n = self->ptr->get_n_items();
  return PyInt_FromLong(n);
}

static PyObject *
py_an_verbose(py_annoy *self, PyObject *args) {
  int verbose;
  if (!self->ptr)
    Py_RETURN_NONE;
  if (!PyArg_ParseTuple(args, "i", &verbose))
    Py_RETURN_NONE;

  self->ptr->verbose((bool)verbose);

  Py_RETURN_TRUE;
}

static PyObject *
py_an_set_seed(py_annoy *self, PyObject *args) {
  int q;
  if (!self->ptr)
    Py_RETURN_NONE;
  if (!PyArg_ParseTuple(args, "i", &q))
    Py_RETURN_NONE;

  self->ptr->set_seed(q);

  Py_RETURN_NONE;
}

static PyMethodDef AnnoyMethods[] = {
  {"load",	(PyCFunction)py_an_load, METH_VARARGS, ""},
  {"save",	(PyCFunction)py_an_save, METH_VARARGS, ""},
  {"get_nns_by_item",(PyCFunction)py_an_get_nns_by_item, METH_VARARGS, ""},
  {"get_nns_by_vector",(PyCFunction)py_an_get_nns_by_vector, METH_VARARGS, ""},
  {"get_item_vector",(PyCFunction)py_an_get_item_vector, METH_VARARGS, ""},
  {"add_item",(PyCFunction)py_an_add_item, METH_VARARGS, ""},
  {"build",(PyCFunction)py_an_build, METH_VARARGS, ""},
  {"unbuild",(PyCFunction)py_an_unbuild, METH_VARARGS, ""},
  {"unload",(PyCFunction)py_an_unload, METH_VARARGS, ""},
  {"get_distance",(PyCFunction)py_an_get_distance, METH_VARARGS, ""},
  {"get_n_items",(PyCFunction)py_an_get_n_items, METH_VARARGS, ""},
  {"verbose",(PyCFunction)py_an_verbose, METH_VARARGS, ""},
  {"set_seed",(PyCFunction)py_an_set_seed, METH_VARARGS, ""},
  {NULL, NULL, 0, NULL}		 /* Sentinel */
};

static PyTypeObject PyAnnoyType = {
  PyVarObject_HEAD_INIT(NULL, 0)
  "annoy.Annoy",          /*tp_name*/
  sizeof(py_annoy),       /*tp_basicsize*/
  0,                      /*tp_itemsize*/
  (destructor)py_an_dealloc, /*tp_dealloc*/
  0,                      /*tp_print*/
  0,                      /*tp_getattr*/
  0,                      /*tp_setattr*/
  0,                      /*tp_compare*/
  0,                      /*tp_repr*/
  0,                      /*tp_as_number*/
  0,                      /*tp_as_sequence*/
  0,                      /*tp_as_mapping*/
  0,                      /*tp_hash */
  0,                      /*tp_call*/
  0,                      /*tp_str*/
  0,                      /*tp_getattro*/
  0,                      /*tp_setattro*/
  0,                      /*tp_as_buffer*/
  Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
  "annoy objects",        /* tp_doc */
  0,                      /* tp_traverse */
  0,                      /* tp_clear */
  0,                      /* tp_richcompare */
  0,                      /* tp_weaklistoffset */
  0,                      /* tp_iter */
  0,                      /* tp_iternext */
  AnnoyMethods,           /* tp_methods */
  py_annoy_members,       /* tp_members */
  0,                      /* tp_getset */
  0,                      /* tp_base */
  0,                      /* tp_dict */
  0,                      /* tp_descr_get */
  0,                      /* tp_descr_set */
  0,                      /* tp_dictoffset */
  (initproc)py_an_init,   /* tp_init */
  0,                      /* tp_alloc */
  py_an_new,              /* tp_new */
};

static PyMethodDef module_methods[] = {
  {NULL}	/* Sentinel */
};

#if PY_MAJOR_VERSION >= 3
  static struct PyModuleDef moduledef = {
    PyModuleDef_HEAD_INIT,
    "annoylib",          /* m_name */
    "",                  /* m_doc */
    -1,                  /* m_size */
    module_methods,      /* m_methods */
    NULL,                /* m_reload */
    NULL,                /* m_traverse */
    NULL,                /* m_clear */
    NULL,                /* m_free */
  };
#endif

PyObject *create_module(void) {
  PyObject *m;

  if (PyType_Ready(&PyAnnoyType) < 0)
    return NULL;

#if PY_MAJOR_VERSION >= 3
  m = PyModule_Create(&moduledef);
#else
  m = Py_InitModule("annoylib", module_methods);
#endif

  if (m == NULL)
    return NULL;

  Py_INCREF(&PyAnnoyType);
  PyModule_AddObject(m, "Annoy", (PyObject *)&PyAnnoyType);
  return m;
}

#if PY_MAJOR_VERSION >= 3
  PyMODINIT_FUNC PyInit_annoylib(void) {
    return create_module();      // it should return moudule object in py3
  }
#else
  PyMODINIT_FUNC initannoylib(void) {
    create_module();
  }
#endif

// vim: tabstop=2 shiftwidth=2
<commit_msg>bugfix<commit_after>// Copyright (c) 2013 Spotify AB
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.

#include "annoylib.h"
#include "kissrandom.h"
#include "Python.h"
#include "structmember.h"
#include <exception>
#include <stdint.h>

#if PY_MAJOR_VERSION >= 3
#define IS_PY3K
#endif

#ifndef Py_TYPE
    #define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
#endif

#ifdef IS_PY3K
    #define PyInt_FromLong PyLong_FromLong
#endif

template class AnnoyIndexInterface<int32_t, float>;

// annoy python object
typedef struct {
  PyObject_HEAD
  int f;
  AnnoyIndexInterface<int32_t, float>* ptr;
} py_annoy;

static PyObject *
py_an_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) {
  py_annoy *self;
  self = (py_annoy *)type->tp_alloc(type, 0);
  if (self == NULL) {
    return NULL;
  }
  const char *metric = NULL;

  static char * kwlist[] = {"f", "metric", NULL};
  if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|s", kwlist, &self->f, &metric))
    return NULL;
  if (!metric || !strcmp(metric, "angular")) {
   self->ptr = new AnnoyIndex<int32_t, float, Angular, Kiss64Random>(self->f);
  } else if (!strcmp(metric, "euclidean")) {
    self->ptr = new AnnoyIndex<int32_t, float, Euclidean, Kiss64Random>(self->f);
  } else if (!strcmp(metric, "manhattan")) {
    self->ptr = new AnnoyIndex<int32_t, float, Manhattan, Kiss64Random>(self->f);
  } else {
    PyErr_SetString(PyExc_ValueError, "No such metric");
    return NULL;
  }

  return (PyObject *)self;
}

static int
py_an_init(py_annoy *self, PyObject *args, PyObject *kwds) {
  // Seems to be needed for Python 3
  const char *metric = NULL;
  PyArg_ParseTuple(args, "i|s", &self->f, &metric);
  return 0;
}

static void
py_an_dealloc(py_annoy* self) {
  if (self->ptr) {
    delete self->ptr;
  }
  Py_TYPE(self)->tp_free((PyObject*)self);
}

static PyMemberDef py_annoy_members[] = {
  {(char*)"_f", T_INT, offsetof(py_annoy, f), 0,
   (char*)""},
  {NULL}	/* Sentinel */
};

static PyObject *
py_an_load(py_annoy *self, PyObject *args) {
  char* filename;
  bool res = false;
  if (!self->ptr)
    Py_RETURN_NONE;
  if (!PyArg_ParseTuple(args, "s", &filename))
    Py_RETURN_NONE;

  res = self->ptr->load(filename);

  if (!res) {
    PyErr_SetFromErrno(PyExc_IOError);
    return NULL;
  }
  Py_RETURN_TRUE;
}

static PyObject *
py_an_save(py_annoy *self, PyObject *args) {
  char *filename;
  bool res = false;
  if (!self->ptr)
    Py_RETURN_NONE;
  if (!PyArg_ParseTuple(args, "s", &filename))
    Py_RETURN_NONE;

  res = self->ptr->save(filename);

  if (!res) {
    PyErr_SetFromErrno(PyExc_IOError);
    return NULL;
  }
  Py_RETURN_TRUE;
}

PyObject*
get_nns_to_python(const vector<int32_t>& result, const vector<float>& distances, int include_distances) {
  PyObject* l = PyList_New(result.size());
  for (size_t i = 0; i < result.size(); i++)
    PyList_SetItem(l, i, PyInt_FromLong(result[i]));
  if (!include_distances)
    return l;

  PyObject* d = PyList_New(distances.size());
  for (size_t i = 0; i < distances.size(); i++)
    PyList_SetItem(d, i, PyFloat_FromDouble(distances[i]));

  PyObject* t = PyTuple_New(2);
  PyTuple_SetItem(t, 0, l);
  PyTuple_SetItem(t, 1, d);

  return t;
}

static PyObject*
py_an_get_nns_by_item(py_annoy *self, PyObject *args) {
  int32_t item, n, search_k=-1, include_distances=0;
  if (!self->ptr)
    Py_RETURN_NONE;
  if (!PyArg_ParseTuple(args, "ii|ii", &item, &n, &search_k, &include_distances))
    Py_RETURN_NONE;

  vector<int32_t> result;
  vector<float> distances;

  Py_BEGIN_ALLOW_THREADS;
  self->ptr->get_nns_by_item(item, n, search_k, &result, include_distances ? &distances : NULL);
  Py_END_ALLOW_THREADS;

  return get_nns_to_python(result, distances, include_distances);
}

static PyObject*
py_an_get_nns_by_vector(py_annoy *self, PyObject *args) {
  PyObject* v;
  int32_t n, search_k=-1, include_distances=0;
  if (!self->ptr)
    Py_RETURN_NONE;
  if (!PyArg_ParseTuple(args, "Oi|ii", &v, &n, &search_k, &include_distances))
    Py_RETURN_NONE;

  vector<float> w(self->f);
  for (int z = 0; z < PyList_Size(v) && z < self->f; z++) {
    PyObject *pf = PyList_GetItem(v,z);
    w[z] = PyFloat_AsDouble(pf);
  }

  vector<int32_t> result;
  vector<float> distances;

  Py_BEGIN_ALLOW_THREADS;
  self->ptr->get_nns_by_vector(&w[0], n, search_k, &result, include_distances ? &distances : NULL);
  Py_END_ALLOW_THREADS;

  return get_nns_to_python(result, distances, include_distances);
}

static PyObject*
py_an_get_item_vector(py_annoy *self, PyObject *args) {
  int32_t item;
  if (!self->ptr)
    Py_RETURN_NONE;
  if (!PyArg_ParseTuple(args, "i", &item))
    Py_RETURN_NONE;

  vector<float> v(self->f);
  self->ptr->get_item(item, &v[0]);
  PyObject* l = PyList_New(self->f);
  for (int z = 0; z < self->f; z++) {
    PyList_SetItem(l, z, PyFloat_FromDouble(v[z]));
  }

  return l;
}

static PyObject*
py_an_add_item(py_annoy *self, PyObject *args) {
  PyObject* l;
  int32_t item;
  if (!self->ptr)
    Py_RETURN_NONE;
  if (!PyArg_ParseTuple(args, "iO", &item, &l))
    Py_RETURN_NONE;

  vector<float> w(self->f, 0.0);
  for (int z = 0; z < self->f; z++) {
    PyObject *pf = PyList_GetItem(l,z);
    w[z] = PyFloat_AsDouble(pf);
  }
  self->ptr->add_item(item, &w[0]);

  Py_RETURN_NONE;
}

static PyObject *
py_an_build(py_annoy *self, PyObject *args) {
  int q;
  if (!self->ptr)
    Py_RETURN_NONE;
  if (!PyArg_ParseTuple(args, "i", &q))
    Py_RETURN_NONE;

  Py_BEGIN_ALLOW_THREADS;
  self->ptr->build(q);
  Py_END_ALLOW_THREADS;

  Py_RETURN_TRUE;
}

static PyObject *
py_an_unbuild(py_annoy *self, PyObject *args) {
  if (!self->ptr)
    Py_RETURN_NONE;

  Py_BEGIN_ALLOW_THREADS;
  self->ptr->unbuild();
  Py_END_ALLOW_THREADS;

  Py_RETURN_TRUE;
}

static PyObject *
py_an_unload(py_annoy *self, PyObject *args) {
  if (!self->ptr)
    Py_RETURN_NONE;

  self->ptr->unload();

  Py_RETURN_TRUE;
}

static PyObject *
py_an_get_distance(py_annoy *self, PyObject *args) {
  int32_t i, j;
  if (!self->ptr)
    Py_RETURN_NONE;
  if (!PyArg_ParseTuple(args, "ii", &i, &j))
    Py_RETURN_NONE;

  double d = self->ptr->get_distance(i,j);
  return PyFloat_FromDouble(d);
}

static PyObject *
py_an_get_n_items(py_annoy *self, PyObject *args) {
  if (!self->ptr)
    Py_RETURN_NONE;

  int32_t n = self->ptr->get_n_items();
  return PyInt_FromLong(n);
}

static PyObject *
py_an_verbose(py_annoy *self, PyObject *args) {
  int verbose;
  if (!self->ptr)
    Py_RETURN_NONE;
  if (!PyArg_ParseTuple(args, "i", &verbose))
    Py_RETURN_NONE;

  self->ptr->verbose((bool)verbose);

  Py_RETURN_TRUE;
}

static PyObject *
py_an_set_seed(py_annoy *self, PyObject *args) {
  int q;
  if (!self->ptr)
    Py_RETURN_NONE;
  if (!PyArg_ParseTuple(args, "i", &q))
    Py_RETURN_NONE;

  self->ptr->set_seed(q);

  Py_RETURN_NONE;
}

static PyMethodDef AnnoyMethods[] = {
  {"load",	(PyCFunction)py_an_load, METH_VARARGS, ""},
  {"save",	(PyCFunction)py_an_save, METH_VARARGS, ""},
  {"get_nns_by_item",(PyCFunction)py_an_get_nns_by_item, METH_VARARGS, ""},
  {"get_nns_by_vector",(PyCFunction)py_an_get_nns_by_vector, METH_VARARGS, ""},
  {"get_item_vector",(PyCFunction)py_an_get_item_vector, METH_VARARGS, ""},
  {"add_item",(PyCFunction)py_an_add_item, METH_VARARGS, ""},
  {"build",(PyCFunction)py_an_build, METH_VARARGS, ""},
  {"unbuild",(PyCFunction)py_an_unbuild, METH_VARARGS, ""},
  {"unload",(PyCFunction)py_an_unload, METH_VARARGS, ""},
  {"get_distance",(PyCFunction)py_an_get_distance, METH_VARARGS, ""},
  {"get_n_items",(PyCFunction)py_an_get_n_items, METH_VARARGS, ""},
  {"verbose",(PyCFunction)py_an_verbose, METH_VARARGS, ""},
  {"set_seed",(PyCFunction)py_an_set_seed, METH_VARARGS, ""},
  {NULL, NULL, 0, NULL}		 /* Sentinel */
};

static PyTypeObject PyAnnoyType = {
  PyVarObject_HEAD_INIT(NULL, 0)
  "annoy.Annoy",          /*tp_name*/
  sizeof(py_annoy),       /*tp_basicsize*/
  0,                      /*tp_itemsize*/
  (destructor)py_an_dealloc, /*tp_dealloc*/
  0,                      /*tp_print*/
  0,                      /*tp_getattr*/
  0,                      /*tp_setattr*/
  0,                      /*tp_compare*/
  0,                      /*tp_repr*/
  0,                      /*tp_as_number*/
  0,                      /*tp_as_sequence*/
  0,                      /*tp_as_mapping*/
  0,                      /*tp_hash */
  0,                      /*tp_call*/
  0,                      /*tp_str*/
  0,                      /*tp_getattro*/
  0,                      /*tp_setattro*/
  0,                      /*tp_as_buffer*/
  Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
  "annoy objects",        /* tp_doc */
  0,                      /* tp_traverse */
  0,                      /* tp_clear */
  0,                      /* tp_richcompare */
  0,                      /* tp_weaklistoffset */
  0,                      /* tp_iter */
  0,                      /* tp_iternext */
  AnnoyMethods,           /* tp_methods */
  py_annoy_members,       /* tp_members */
  0,                      /* tp_getset */
  0,                      /* tp_base */
  0,                      /* tp_dict */
  0,                      /* tp_descr_get */
  0,                      /* tp_descr_set */
  0,                      /* tp_dictoffset */
  (initproc)py_an_init,   /* tp_init */
  0,                      /* tp_alloc */
  py_an_new,              /* tp_new */
};

static PyMethodDef module_methods[] = {
  {NULL}	/* Sentinel */
};

#if PY_MAJOR_VERSION >= 3
  static struct PyModuleDef moduledef = {
    PyModuleDef_HEAD_INIT,
    "annoylib",          /* m_name */
    "",                  /* m_doc */
    -1,                  /* m_size */
    module_methods,      /* m_methods */
    NULL,                /* m_reload */
    NULL,                /* m_traverse */
    NULL,                /* m_clear */
    NULL,                /* m_free */
  };
#endif

PyObject *create_module(void) {
  PyObject *m;

  if (PyType_Ready(&PyAnnoyType) < 0)
    return NULL;

#if PY_MAJOR_VERSION >= 3
  m = PyModule_Create(&moduledef);
#else
  m = Py_InitModule("annoylib", module_methods);
#endif

  if (m == NULL)
    return NULL;

  Py_INCREF(&PyAnnoyType);
  PyModule_AddObject(m, "Annoy", (PyObject *)&PyAnnoyType);
  return m;
}

#if PY_MAJOR_VERSION >= 3
  PyMODINIT_FUNC PyInit_annoylib(void) {
    return create_module();      // it should return moudule object in py3
  }
#else
  PyMODINIT_FUNC initannoylib(void) {
    create_module();
  }
#endif

// vim: tabstop=2 shiftwidth=2
<|endoftext|>


<commit_before>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)
//
// Contributors: Kirsten Weber

#ifndef DUNE_GDT_DISCRETEFUNCTION_DEFAULT_HH
#define DUNE_GDT_DISCRETEFUNCTION_DEFAULT_HH

#include <memory>
#include <type_traits>

#include <dune/common/exceptions.hh>
#include <dune/common/fvector.hh>

#include <dune/grid/io/file/vtk.hh>

#include <dune/stuff/la/container/interfaces.hh>
#include <dune/stuff/functions/interfaces.hh>

#include <dune/gdt/spaces/interface.hh>

#include "local.hh"

namespace Dune {
namespace GDT {

template< class SpaceImp, class VectorImp >
class ConstDiscreteFunction
  : public Stuff::LocalizableFunctionInterface< typename SpaceImp::EntityType,
                                                typename SpaceImp::DomainFieldType, SpaceImp::dimDomain,
                                                typename SpaceImp::RangeFieldType, SpaceImp::dimRange, SpaceImp::dimRangeCols >
{
  static_assert(std::is_base_of< SpaceInterface< typename SpaceImp::Traits >, SpaceImp >::value,
                "SpaceImp has to be derived from SpaceInterface!");
  static_assert(std::is_base_of< Dune::Stuff::LA::VectorInterface< typename VectorImp::Traits >, VectorImp >::value,
                "VectorImp has to be derived from Stuff::LA::VectorInterface!");
  static_assert(std::is_same< typename SpaceImp::RangeFieldType, typename VectorImp::ScalarType >::value,
                "Types do not match!");
  typedef Stuff::LocalizableFunctionInterface
      < typename SpaceImp::EntityType, typename SpaceImp::DomainFieldType, SpaceImp::dimDomain,
        typename SpaceImp::RangeFieldType, SpaceImp::dimRange, SpaceImp::dimRangeCols >
    BaseType;
  typedef ConstDiscreteFunction< SpaceImp, VectorImp > ThisType;
public:
  typedef SpaceImp                              SpaceType;
  typedef VectorImp                             VectorType;
  typedef typename BaseType::EntityType         EntityType;
  typedef typename BaseType::LocalfunctionType  LocalfunctionType;

  static const unsigned int                   dimDomain = BaseType::dimDomain;
  typedef typename BaseType::DomainFieldType  DomainFieldType;
  typedef typename BaseType::DomainType       DomainType;

  static const unsigned int                     dimRange = BaseType::dimRange;
  static const unsigned int                     dimRangeCols = BaseType::dimRangeCols;
  typedef typename BaseType::RangeFieldType     RangeFieldType;
  typedef typename BaseType::RangeType          RangeType;
  typedef typename BaseType::JacobianRangeType  JacobianRangeType;

  typedef ConstLocalDiscreteFunction< SpaceType, VectorType > ConstLocalDiscreteFunctionType;

  ConstDiscreteFunction(const SpaceType& sp,
                        const VectorType& vec,
                        const std::string nm = "dune.gdt.constdiscretefunction")
    : space_(sp)
    , vector_(vec)
    , name_(nm)
  {
    assert(vector_.size() == space_.mapper().size() && "Given vector has wrong size!");
  }

  ConstDiscreteFunction(const ThisType& other)
    : space_(other.space_)
    , vector_(other.vector_)
    , name_(other.name_)
  {}

  ConstDiscreteFunction(ThisType&& source)
    : space_(source.space_)
    , vector_(source.vector_)
    , name_(std::move(source.name_))
  {}

  virtual ~ConstDiscreteFunction() {}

  ThisType& operator=(const ThisType& other) = delete;

  virtual ThisType* copy() const DS_OVERRIDE
  {
    return new ThisType(*this);
  }

  virtual std::string name() const DS_OVERRIDE
  {
    return name_;
  }

  const SpaceType& space() const
  {
    return space_;
  }

  const VectorType& vector() const
  {
    return vector_;
  }

  ConstLocalDiscreteFunctionType local_discrete_function(const EntityType& entity) const
  {
    assert(space_.grid_view()->indexSet().contains(entity));
    return ConstLocalDiscreteFunctionType(space_, vector_, entity);
  }

  virtual std::unique_ptr< LocalfunctionType > local_function(const EntityType& entity) const DS_OVERRIDE
  {
    return std::unique_ptr< ConstLocalDiscreteFunctionType >
        (new ConstLocalDiscreteFunctionType(local_discrete_function(entity)));
  }

  void visualize(const std::string filename,
                 const bool subsampling = (SpaceType::polOrder > 1),
                 VTK::OutputType vtk_output_type = VTK::appendedraw) const
  {
    BaseType::template visualize< typename SpaceType::GridViewType >(*(space().grid_view()),
                                                                     filename,
                                                                     subsampling,
                                                                     vtk_output_type);
  }

protected:
  const SpaceType& space_;
private:
  const VectorType& vector_;
  const std::string name_;
}; // class ConstDiscreteFunction

template< class SpaceImp, class VectorImp >
class DiscreteFunction
  : public ConstDiscreteFunction< SpaceImp, VectorImp >
{
  typedef ConstDiscreteFunction< SpaceImp, VectorImp >  BaseType;
  typedef DiscreteFunction< SpaceImp, VectorImp >       ThisType;
public:
  typedef typename BaseType::SpaceType          SpaceType;
  typedef typename BaseType::VectorType         VectorType;
  typedef typename BaseType::EntityType         EntityType;
  typedef typename BaseType::LocalfunctionType  LocalfunctionType;

  typedef LocalDiscreteFunction< SpaceType, VectorType > LocalDiscreteFunctionType;

  DiscreteFunction(const SpaceType& sp,
                   VectorType& vec,
                   const std::string nm = "dune.gdt.discretefunction")
    : BaseType(sp, vec, nm)
    , vector_(vec)
  {}

  DiscreteFunction(const ThisType& other)
    : BaseType(other)
    , vector_(other.vector_)
  {}

  DiscreteFunction(ThisType&& source)
    : BaseType(std::move(source))
    , vector_(source.vector_)
  {}

  ~DiscreteFunction() {}

  ThisType& operator=(const ThisType& other) = delete;

  virtual ThisType* copy() const DS_OVERRIDE
  {
    return new ThisType(*this);
  }

  VectorType& vector()
  {
    return vector_;
  }

  using BaseType::local_discrete_function;

  LocalDiscreteFunctionType local_discrete_function(const EntityType& entity)
  {
    assert(space_.grid_view()->indexSet().contains(entity));
    return LocalDiscreteFunctionType(space_, vector_, entity);
  }

private:
  using BaseType::space_;
  VectorType& vector_;
}; // class DiscreteFunction

template< class SpaceImp, class VectorImp >
class StoredDiscreteFunction
  : public DiscreteFunction< SpaceImp, VectorImp >
{
  typedef DiscreteFunction< SpaceImp, VectorImp >  BaseType;
  typedef StoredDiscreteFunction< SpaceImp, VectorImp >       ThisType;
public:
  typedef typename BaseType::SpaceType          SpaceType;
  typedef typename BaseType::VectorType         VectorType;
  typedef typename BaseType::EntityType         EntityType;
  typedef typename BaseType::LocalfunctionType  LocalfunctionType;

  typedef LocalDiscreteFunction< SpaceType, VectorType > LocalDiscreteFunctionType;

  StoredDiscreteFunction(const SpaceType& sp,
                   const std::string nm = "dune.gdt.discretefunction")
    : BaseType(sp, vector_, nm)
    , vector_(sp.mapper().size())
  {}

  ~StoredDiscreteFunction() {}

  ThisType& operator=(const ThisType& other) = delete;

  virtual ThisType* copy() const DS_OVERRIDE
  {
    return new ThisType(*this);
  }

  VectorType& vector()
  {
    return vector_;
  }

  LocalDiscreteFunctionType local_discrete_function(const EntityType& entity)
  {
    return LocalDiscreteFunctionType(BaseType::space(), vector_, entity);
  }

  bool dofsValid() const {
    for(const auto& val : vector_) {
      if(std::isnan(val) || std::isinf(val))
        return false;
    }
    return true;
  }

private:
  VectorType vector_;
}; // class DiscreteFunction

} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_DISCRETEFUNCTION_DEFAULT_HH
<commit_msg>[discretefunction.default] merged StoredDiscreteFunction * seems to work for me<commit_after>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)
//
// Contributors: Kirsten Weber

#ifndef DUNE_GDT_DISCRETEFUNCTION_DEFAULT_HH
#define DUNE_GDT_DISCRETEFUNCTION_DEFAULT_HH

#include <memory>
#include <type_traits>

#include <dune/common/exceptions.hh>
#include <dune/common/fvector.hh>

#include <dune/grid/io/file/vtk.hh>

#include <dune/stuff/la/container/interfaces.hh>
#include <dune/stuff/functions/interfaces.hh>
#include <dune/stuff/common/memory.hh>

#include <dune/gdt/spaces/interface.hh>

#include "local.hh"

namespace Dune {
namespace GDT {

template< class SpaceImp, class VectorImp >
class ConstDiscreteFunction
  : public Stuff::LocalizableFunctionInterface< typename SpaceImp::EntityType,
                                                typename SpaceImp::DomainFieldType, SpaceImp::dimDomain,
                                                typename SpaceImp::RangeFieldType, SpaceImp::dimRange, SpaceImp::dimRangeCols >
{
  static_assert(std::is_base_of< SpaceInterface< typename SpaceImp::Traits >, SpaceImp >::value,
                "SpaceImp has to be derived from SpaceInterface!");
  static_assert(std::is_base_of< Dune::Stuff::LA::VectorInterface< typename VectorImp::Traits >, VectorImp >::value,
                "VectorImp has to be derived from Stuff::LA::VectorInterface!");
  static_assert(std::is_same< typename SpaceImp::RangeFieldType, typename VectorImp::ScalarType >::value,
                "Types do not match!");
  typedef Stuff::LocalizableFunctionInterface
      < typename SpaceImp::EntityType, typename SpaceImp::DomainFieldType, SpaceImp::dimDomain,
        typename SpaceImp::RangeFieldType, SpaceImp::dimRange, SpaceImp::dimRangeCols >
    BaseType;
  typedef ConstDiscreteFunction< SpaceImp, VectorImp > ThisType;
public:
  typedef SpaceImp                              SpaceType;
  typedef VectorImp                             VectorType;
  typedef typename BaseType::EntityType         EntityType;
  typedef typename BaseType::LocalfunctionType  LocalfunctionType;

  static const unsigned int                   dimDomain = BaseType::dimDomain;
  typedef typename BaseType::DomainFieldType  DomainFieldType;
  typedef typename BaseType::DomainType       DomainType;

  static const unsigned int                     dimRange = BaseType::dimRange;
  static const unsigned int                     dimRangeCols = BaseType::dimRangeCols;
  typedef typename BaseType::RangeFieldType     RangeFieldType;
  typedef typename BaseType::RangeType          RangeType;
  typedef typename BaseType::JacobianRangeType  JacobianRangeType;

  typedef ConstLocalDiscreteFunction< SpaceType, VectorType > ConstLocalDiscreteFunctionType;

  ConstDiscreteFunction(const SpaceType& sp,
                        const VectorType& vec,
                        const std::string nm = "dune.gdt.constdiscretefunction")
    : space_(sp)
    , vector_(vec)
    , name_(nm)
  {
    assert(vector_.size() == space_.mapper().size() && "Given vector has wrong size!");
  }

  ConstDiscreteFunction(const ThisType& other)
    : space_(other.space_)
    , vector_(other.vector_)
    , name_(other.name_)
  {}

  ConstDiscreteFunction(ThisType&& source)
    : space_(source.space_)
    , vector_(source.vector_)
    , name_(std::move(source.name_))
  {}

  virtual ~ConstDiscreteFunction() {}

  ThisType& operator=(const ThisType& other) = delete;

  virtual ThisType* copy() const DS_OVERRIDE
  {
    return new ThisType(*this);
  }

  virtual std::string name() const DS_OVERRIDE
  {
    return name_;
  }

  const SpaceType& space() const
  {
    return space_;
  }

  const VectorType& vector() const
  {
    return vector_;
  }

  ConstLocalDiscreteFunctionType local_discrete_function(const EntityType& entity) const
  {
    assert(space_.grid_view()->indexSet().contains(entity));
    return ConstLocalDiscreteFunctionType(space_, vector_, entity);
  }

  virtual std::unique_ptr< LocalfunctionType > local_function(const EntityType& entity) const DS_OVERRIDE
  {
    return std::unique_ptr< ConstLocalDiscreteFunctionType >
        (new ConstLocalDiscreteFunctionType(local_discrete_function(entity)));
  }

  void visualize(const std::string filename,
                 const bool subsampling = (SpaceType::polOrder > 1),
                 VTK::OutputType vtk_output_type = VTK::appendedraw) const
  {
    BaseType::template visualize< typename SpaceType::GridViewType >(*(space().grid_view()),
                                                                     filename,
                                                                     subsampling,
                                                                     vtk_output_type);
  }

  bool dofs_valid() const
  {
    return vector().valid();
  }

protected:
  const SpaceType& space_;
private:
  const VectorType& vector_;
  const std::string name_;
}; // class ConstDiscreteFunction

namespace internal {

template< class VectorType >
class RefProvider
{
public:
  virtual ~RefProvider() {}

  virtual VectorType& ref() = 0;
};

template< class VectorType >
class RefProviderByRef
  : public RefProvider< VectorType >
{
public:
  RefProviderByRef(VectorType& vec)
    : vector_(vec)
  {}

  virtual ~RefProviderByRef() {}

  virtual VectorType& ref() DS_OVERRIDE DS_FINAL
  {
    return vector_;
  }

private:
  VectorType& vector_;
};

template< class VectorType >
class RefProviderByPtr
  : public RefProvider< VectorType >
{
public:
  RefProviderByPtr(const size_t sz)
    : vector_(new VectorType(sz))
  {}

  virtual ~RefProviderByPtr() {}

  virtual VectorType& ref() DS_OVERRIDE DS_FINAL
  {
    return *vector_;
  }

private:
  std::unique_ptr< VectorType > vector_;
};

template< class VectorType >
class VectorProvider
{
public:
  VectorProvider(VectorType& ref)
    : ref_provider_(Stuff::Common::make_unique< RefProviderByRef< VectorType > >(ref))
  {}

  VectorProvider(const size_t sz)
    : ref_provider_(Stuff::Common::make_unique< RefProviderByPtr< VectorType > >(sz))
  {}

  VectorProvider(const VectorProvider< VectorType >& other)
    : ref_provider_(Stuff::Common::make_unique< RefProviderByPtr< VectorType > >(other.vector_ref().size()))
  {
    vector_ref() = other.vector_ref();
  }

  VectorProvider(VectorProvider< VectorType >&& source)
    : ref_provider_(std::move(source.ref_provider_))
  {}

  VectorProvider< VectorType >& operator=(const VectorProvider< VectorType >& other)
  {
    if (this != &other) {
      vector_ref() = other.vector_ref();
    }
    return *this;
  }

  VectorType& vector_ref()
  {
    return ref_provider_->ref();
  }

  const VectorType& vector_ref() const
  {
    return ref_provider_->ref();
  }

private:
  std::unique_ptr< RefProvider< VectorType > > ref_provider_;
};

} // namespace internal

template< class SpaceImp, class VectorImp >
class DiscreteFunction
  : internal::VectorProvider< VectorImp >
  , public ConstDiscreteFunction< SpaceImp, VectorImp >
{
  typedef internal::VectorProvider< VectorImp > VectorProviderBaseType;
  typedef ConstDiscreteFunction< SpaceImp, VectorImp >  BaseType;
  typedef DiscreteFunction< SpaceImp, VectorImp >       ThisType;
public:
  typedef typename BaseType::SpaceType          SpaceType;
  typedef typename BaseType::VectorType         VectorType;
  typedef typename BaseType::EntityType         EntityType;
  typedef typename BaseType::LocalfunctionType  LocalfunctionType;

  typedef LocalDiscreteFunction< SpaceType, VectorType > LocalDiscreteFunctionType;

  DiscreteFunction(const SpaceType& sp,
                   VectorType& vec,
                   const std::string nm = "dune.gdt.discretefunction")
    : VectorProviderBaseType(vec)
    , BaseType(sp, VectorProviderBaseType::vector_ref(), nm)
  {}

  DiscreteFunction(const SpaceType& sp,
                   const std::string nm = "dune.gdt.discretefunction")
    : VectorProviderBaseType(sp.mapper().size())
    , BaseType(sp, VectorProviderBaseType::vector_ref(), nm)
  {}

  DiscreteFunction(const ThisType& other)
    : VectorProviderBaseType(other)
    , BaseType(other.space(), VectorProviderBaseType::vector_ref(), other.name())
  {}

  DiscreteFunction(ThisType&& source)
    : VectorProviderBaseType(source)
    , BaseType(source.space(), VectorProviderBaseType::vector_ref(), source.name())
  {}

  ~DiscreteFunction() {}

  ThisType& operator=(const ThisType& other) = delete;

  virtual ThisType* copy() const DS_OVERRIDE
  {
    return new ThisType(*this);
  }

  VectorType& vector()
  {
    return this->vector_ref();
  }

  using BaseType::local_discrete_function;

  LocalDiscreteFunctionType local_discrete_function(const EntityType& entity)
  {
    assert(space_.grid_view()->indexSet().contains(entity));
    return LocalDiscreteFunctionType(space_, this->vector_ref(), entity);
  }

private:
  using BaseType::space_;
}; // class DiscreteFunction

} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_DISCRETEFUNCTION_DEFAULT_HH
<|endoftext|>


<commit_before>#include "qaesencryption.h"
#include <QDebug>

#define Multiply(x, y)                                \
      (  ((y & 1) * x) ^                              \
      ((y>>1 & 1) * xTime(x)) ^                       \
      ((y>>2 & 1) * xTime(xTime(x))) ^                \
      ((y>>3 & 1) * xTime(xTime(xTime(x)))) ^         \
      ((y>>4 & 1) * xTime(xTime(xTime(xTime(x))))))   \

QAESEncryption::QAESEncryption(QAESEncryption::AES level, QAESEncryption::MODE mode) : m_level(level), m_mode(mode)
{
    m_state = NULL;

    switch (level)
    {
    case AES_128: {
        AES128 aes;
        m_nk = aes.nk;
        m_keyLen = aes.keylen;
        m_nr = aes.nr;
        m_expandedKey = aes.expandedKey;
        qDebug() << "AES128";
        }
        break;
    case AES_192: {
        AES192 aes;
        m_nk = aes.nk;
        m_keyLen = aes.keylen;
        m_nr = aes.nr;
        m_expandedKey = aes.expandedKey;
        qDebug() << "AES192";
        }
        break;
    case AES_256: {
        AES256 aes;
        m_nk = aes.nk;
        m_keyLen = aes.keylen;
        m_nr = aes.nr;
        m_expandedKey = aes.expandedKey;
        qDebug() << "AES256";
        }
        break;
    default: {
        AES128 aes;
        m_nk = aes.nk;
        m_keyLen = aes.keylen;
        m_nr = aes.nr;
        m_expandedKey = aes.expandedKey;
        qDebug() << "Defaulting to AES128";
        }
        break;
    }

}

QByteArray QAESEncryption::expandKey(const QByteArray key)
{
  int i, k;
  quint8 tempa[4]; // Used for the column/row operations
  QByteArray roundKey(key);

  // The first round key is the key itself.
  // ...

  // All other round keys are found from the previous round keys.
  //i == Nk
  for(i = m_nk; i < m_nb * (m_nr + 1); i++)
  {
    {
      tempa[0] = (quint8) roundKey.at((i-1) * 4 + 0);
      tempa[1] = (quint8) roundKey.at((i-1) * 4 + 1);
      tempa[2] = (quint8) roundKey.at((i-1) * 4 + 2);
      tempa[3] = (quint8) roundKey.at((i-1) * 4 + 3);
    }

    if (i % m_nk == 0)
    {
      // This function shifts the 4 bytes in a word to the left once.
      // [a0,a1,a2,a3] becomes [a1,a2,a3,a0]

      // Function RotWord()
      {
        k = tempa[0];
        tempa[0] = tempa[1];
        tempa[1] = tempa[2];
        tempa[2] = tempa[3];
        tempa[3] = k;
      }

      // SubWord() is a function that takes a four-byte input word and
      // applies the S-box to each of the four bytes to produce an output word.

      // Function Subword()
      {
        tempa[0] = getSBoxValue(tempa[0]);
        tempa[1] = getSBoxValue(tempa[1]);
        tempa[2] = getSBoxValue(tempa[2]);
        tempa[3] = getSBoxValue(tempa[3]);
      }

      tempa[0] =  tempa[0] ^ Rcon[i/m_nk];
    }
    if (m_level == AES_256 && i % m_nk == 4)
    {
      // Function Subword()
      {
        qDebug() << "AES_256";
        tempa[0] = getSBoxValue(tempa[0]);
        tempa[1] = getSBoxValue(tempa[1]);
        tempa[2] = getSBoxValue(tempa[2]);
        tempa[3] = getSBoxValue(tempa[3]);
      }
    }
    roundKey.insert(i * 4 + 0, roundKey.at((i - m_nk) * 4 + 0) ^ tempa[0]);
    roundKey.insert(i * 4 + 1, roundKey.at((i - m_nk) * 4 + 1) ^ tempa[1]);
    roundKey.insert(i * 4 + 2, roundKey.at((i - m_nk) * 4 + 2) ^ tempa[2]);
    roundKey.insert(i * 4 + 3, roundKey.at((i - m_nk) * 4 + 3) ^ tempa[3]);
  }

  //qDebug() << print(roundKey);
  return roundKey;
}

// This function adds the round key to state.
// The round key is added to the state by an XOR function.
void QAESEncryption::addRoundKey(quint8 round, const QByteArray expKey)
{
  QByteArray::iterator it = m_state->begin();
  for(int i=0; i < 16; i++)
      it[i] = (quint8)it[i] ^ (quint8)expKey.at(round * m_nb * 4 + (i/4) * m_nb + (i%4));
}

// The SubBytes Function Substitutes the values in the
// state matrix with values in an S-box.
void QAESEncryption::subBytes()
{
  QByteArray::iterator it = m_state->begin();
  for(int i = 0; i < 16; i++)
    it[i] = getSBoxValue((quint8) it[i]);
}

// The ShiftRows() function shifts the rows in the state to the left.
// Each row is shifted with different offset.
// Offset = Row number. So the first row is not shifted.
void QAESEncryption::shiftRows()
{
    QByteArray::iterator it = m_state->begin();
    quint8 temp;

     //Shift 1 to left
    temp = (quint8) it[4];
    it[4] = it[4+1];
    it[4+1] = it[4+2];
    it[4+2] = it[4+3];
    it[4+3] = temp;

    //Shift 2 to left
    temp = (quint8) it[8];
    it[8] = it[8+2];
    it[8+2] = temp;
    temp = it[8+1];
    it[8+1] = it[8+3];
    it[8+3] = temp;

    //Shift 3 to left
    temp = (quint8) it[12];
    it[12] = it[12+3];
    it[12+3] = it[12+2];
    it[12+2] = it[12+1];
    it[12+1] = temp;
}

// MixColumns function mixes the columns of the state matrix
//optimized!!
void QAESEncryption::mixColumns()
{
  QByteArray::iterator it = m_state->begin();
  quint8 tmp, tm, t;

  for(int i = 0; i < 16; i += 4)
  {
    t   = it[i];
    tmp =  it[i] ^ it[i+1] ^ it[i+2] ^ it[i+3] ;

    tm = xTime( it[i] ^ it[i+1] );
    it[i] ^= tm ^ tmp;

    tm = xTime( it[i+1] ^ it[i+2]);
    it[i+1] ^= tm ^ tmp;

    tm = xTime( it[i+2] ^ it[i+3]);
    it[i+2] ^= tm ^ tmp;

    tm = xTime(it[i+3] ^ t);
    it[i+3] ^= tm ^ tmp;
  }
}

// MixColumns function mixes the columns of the state matrix.
// The method used to multiply may be difficult to understand for the inexperienced.
// Please use the references to gain more information.
void QAESEncryption::invMixColumns()
{
  QByteArray::iterator it = m_state->begin();
  quint8 a,b,c,d;
  for(int i = 0; i < 16; i+=4)
  {
    a = (quint8) it[i];
    b = (quint8) it[i+1];
    c = (quint8) it[i+2];
    d = (quint8) it[i+3];

    it[i]   = (quint8) (Multiply(a, 0x0e) ^ Multiply(b, 0x0b) ^ Multiply(c, 0x0d) ^ Multiply(d, 0x09));
    it[i+1] = (quint8) (Multiply(a, 0x09) ^ Multiply(b, 0x0e) ^ Multiply(c, 0x0b) ^ Multiply(d, 0x0d));
    it[i+2] = (quint8) (Multiply(a, 0x0d) ^ Multiply(b, 0x09) ^ Multiply(c, 0x0e) ^ Multiply(d, 0x0b));
    it[i+3] = (quint8) (Multiply(a, 0x0b) ^ Multiply(b, 0x0d) ^ Multiply(c, 0x09) ^ Multiply(d, 0x0e));
  }
}

// The SubBytes Function Substitutes the values in the
// state matrix with values in an S-box.
void QAESEncryption::invSubBytes()
{
    QByteArray::iterator it = m_state->begin();
    for(int i = 0; i < 16; ++i)
        it[i] = getSBoxInvert(it[i]);
}

void QAESEncryption::invShiftRows()
{
    QByteArray::iterator it = m_state->begin();
    uint8_t temp;

    //Shift 1 to right
    temp = (quint8) it[4+3];
    it[4+3] = it[4+2];
    it[4+2] = it[4+1];
    it[4+1] = it[4];
    it[4] = temp;

    //Shift 2
    temp = (quint8) it[8+2];
    it[8+2] = it[8];
    it[8] = temp;
    temp = (quint8) it[8+3];
    it[8+3] = it[8+1];
    it[8+1] = temp;

    //Shift 3
    temp = (quint8) it[12+3];
    it[12+3] = it[12];
    it[12] = it[12+1];
    it[12+1] = it[12+2];
    it[12+2] = temp;
}

// Cipher is the main function that encrypts the PlainText.
QByteArray QAESEncryption::cipher(const QByteArray expKey, const QByteArray in)
{

  //m_state is the input buffer...
  QByteArray output(in);
  m_state = &output;

  quint8 round = 0;

  // Add the First round key to the state before starting the rounds.
  addRoundKey(0, expKey);

  //qDebug() << print(output);
  // There will be Nr rounds.
  // The first Nr-1 rounds are identical.
  // These Nr-1 rounds are executed in the loop below.
  for(round = 1; round < m_nr; ++round)
  {
    subBytes();
    shiftRows();
    mixColumns();
    addRoundKey(round, expKey);
  }

  // The last round is given below.
  // The MixColumns function is not here in the last round.
  subBytes();
  shiftRows();
  addRoundKey(m_nr, expKey);

  return output;
}

QByteArray QAESEncryption::invCipher(const QByteArray expKey, const QByteArray in)
{
    //m_state is the input buffer.... handle it!
    QByteArray output(in);
    m_state = &output;
    uint8_t round = 0;

    // Add the First round key to the state before starting the rounds.
    addRoundKey(m_nr, expKey);

    // There will be Nr rounds.
    // The first Nr-1 rounds are identical.
    // These Nr-1 rounds are executed in the loop below.
    for(round=m_nr-1;round>0;round--)
    {
        invShiftRows();
        invSubBytes();
        addRoundKey(round, expKey);
        invMixColumns();
    }

    // The last round is given below.
    // The MixColumns function is not here in the last round.
    invShiftRows();
    invSubBytes();
    addRoundKey(0, expKey);

    return output;
}

QByteArray QAESEncryption::encode(const QByteArray rawText, const QByteArray key, const QByteArray iv)
{
    if (m_mode == CBC && iv.isNull())
       return QByteArray();

    QByteArray ret;
    QByteArray expandedKey = expandKey(key);
    QByteArray alignedText(rawText);

    alignedText.append(getPadding(rawText.size(), m_keyLen), 0); //filling the array with zeros

    for(int i=0; i < alignedText.size(); i+= m_keyLen)
    {
        ret.append(cipher(expandedKey, alignedText.mid(i, m_keyLen)));
        qDebug() << print(ret.mid(i, m_keyLen)); //test
    }
    qDebug() << "--";
    return ret;
}

QByteArray QAESEncryption::decode(const QByteArray rawText, const QByteArray key, const QByteArray iv)
{
    if (m_mode == CBC && iv.isNull())
       return QByteArray();

    QByteArray ret;
    QByteArray expandedKey = expandKey(key);
    QByteArray alignedText(rawText);

    alignedText.append(getPadding(rawText.size(), m_keyLen), 0); //filling the array with zeros

    for(int i=0; i < alignedText.size(); i+= m_keyLen)
    {
        ret.append(invCipher(expandedKey, alignedText.mid(i, m_keyLen)));
        qDebug() << print(ret.mid(i, m_keyLen)); //test
    }
    qDebug() << "--";
    return ret;
}

QString QAESEncryption::print(QByteArray in)
{
    QString ret="";
    for (int i=0; i < in.size();i++) {
        QString number = QString::number((quint8)in.at(i), 16);
        if (number.size()==1)
            number.insert(0, "0");
        ret.append(QString("%1, ").arg(number));
    }
    return ret;
}
<commit_msg>cleaning<commit_after>#include "qaesencryption.h"
#include <QDebug>

#define Multiply(x, y)                                \
      (  ((y & 1) * x) ^                              \
      ((y>>1 & 1) * xTime(x)) ^                       \
      ((y>>2 & 1) * xTime(xTime(x))) ^                \
      ((y>>3 & 1) * xTime(xTime(xTime(x)))) ^         \
      ((y>>4 & 1) * xTime(xTime(xTime(xTime(x))))))   \

QAESEncryption::QAESEncryption(QAESEncryption::AES level, QAESEncryption::MODE mode) : m_level(level), m_mode(mode)
{
    m_state = NULL;

    switch (level)
    {
    case AES_128: {
        AES128 aes;
        m_nk = aes.nk;
        m_keyLen = aes.keylen;
        m_nr = aes.nr;
        m_expandedKey = aes.expandedKey;
        qDebug() << "AES128";
        }
        break;
    case AES_192: {
        AES192 aes;
        m_nk = aes.nk;
        m_keyLen = aes.keylen;
        m_nr = aes.nr;
        m_expandedKey = aes.expandedKey;
        qDebug() << "AES192";
        }
        break;
    case AES_256: {
        AES256 aes;
        m_nk = aes.nk;
        m_keyLen = aes.keylen;
        m_nr = aes.nr;
        m_expandedKey = aes.expandedKey;
        qDebug() << "AES256";
        }
        break;
    default: {
        AES128 aes;
        m_nk = aes.nk;
        m_keyLen = aes.keylen;
        m_nr = aes.nr;
        m_expandedKey = aes.expandedKey;
        qDebug() << "Defaulting to AES128";
        }
        break;
    }

}

QByteArray QAESEncryption::expandKey(const QByteArray key)
{
  int i, k;
  quint8 tempa[4]; // Used for the column/row operations
  QByteArray roundKey(key);

  // The first round key is the key itself.
  // ...

  // All other round keys are found from the previous round keys.
  //i == Nk
  for(i = m_nk; i < m_nb * (m_nr + 1); i++)
  {
    {
      tempa[0] = (quint8) roundKey.at((i-1) * 4 + 0);
      tempa[1] = (quint8) roundKey.at((i-1) * 4 + 1);
      tempa[2] = (quint8) roundKey.at((i-1) * 4 + 2);
      tempa[3] = (quint8) roundKey.at((i-1) * 4 + 3);
    }

    if (i % m_nk == 0)
    {
      // This function shifts the 4 bytes in a word to the left once.
      // [a0,a1,a2,a3] becomes [a1,a2,a3,a0]

      // Function RotWord()
      {
        k = tempa[0];
        tempa[0] = tempa[1];
        tempa[1] = tempa[2];
        tempa[2] = tempa[3];
        tempa[3] = k;
      }

      // SubWord() is a function that takes a four-byte input word and
      // applies the S-box to each of the four bytes to produce an output word.

      // Function Subword()
      {
        tempa[0] = getSBoxValue(tempa[0]);
        tempa[1] = getSBoxValue(tempa[1]);
        tempa[2] = getSBoxValue(tempa[2]);
        tempa[3] = getSBoxValue(tempa[3]);
      }

      tempa[0] =  tempa[0] ^ Rcon[i/m_nk];
    }
    if (m_level == AES_256 && i % m_nk == 4)
    {
      // Function Subword()
      {
        qDebug() << "AES_256";
        tempa[0] = getSBoxValue(tempa[0]);
        tempa[1] = getSBoxValue(tempa[1]);
        tempa[2] = getSBoxValue(tempa[2]);
        tempa[3] = getSBoxValue(tempa[3]);
      }
    }
    roundKey.insert(i * 4 + 0, roundKey.at((i - m_nk) * 4 + 0) ^ tempa[0]);
    roundKey.insert(i * 4 + 1, roundKey.at((i - m_nk) * 4 + 1) ^ tempa[1]);
    roundKey.insert(i * 4 + 2, roundKey.at((i - m_nk) * 4 + 2) ^ tempa[2]);
    roundKey.insert(i * 4 + 3, roundKey.at((i - m_nk) * 4 + 3) ^ tempa[3]);
  }

  //qDebug() << print(roundKey);
  return roundKey;
}

// This function adds the round key to state.
// The round key is added to the state by an XOR function.
void QAESEncryption::addRoundKey(quint8 round, const QByteArray expKey)
{
  QByteArray::iterator it = m_state->begin();
  for(int i=0; i < 16; ++i) {
      it[i] = it[i] ^ expKey.at(round * m_nb * 4 + (i/4) * m_nb + (i%4));
  }
}

// The SubBytes Function Substitutes the values in the
// state matrix with values in an S-box.
void QAESEncryption::subBytes()
{
  QByteArray::iterator it = m_state->begin();
  for(int i = 0; i < 16; i++)
    it[i] = getSBoxValue((quint8) it[i]);
}

// The ShiftRows() function shifts the rows in the state to the left.
// Each row is shifted with different offset.
// Offset = Row number. So the first row is not shifted.
void QAESEncryption::shiftRows()
{
    QByteArray::iterator it = m_state->begin();
    quint8 temp;

     //Shift 1 to left
    temp = (quint8) it[4];
    it[4] = it[4+1];
    it[4+1] = it[4+2];
    it[4+2] = it[4+3];
    it[4+3] = temp;

    //Shift 2 to left
    temp = (quint8) it[8];
    it[8] = it[8+2];
    it[8+2] = temp;
    temp = it[8+1];
    it[8+1] = it[8+3];
    it[8+3] = temp;

    //Shift 3 to left
    temp = (quint8) it[12];
    it[12] = it[12+3];
    it[12+3] = it[12+2];
    it[12+2] = it[12+1];
    it[12+1] = temp;
}

// MixColumns function mixes the columns of the state matrix
//optimized!!
void QAESEncryption::mixColumns()
{
  QByteArray::iterator it = m_state->begin();
  quint8 tmp, tm, t;

  for(int i = 0; i < 16; i += 4)
  {
    t   = it[i];
    tmp =  it[i] ^ it[i+1] ^ it[i+2] ^ it[i+3] ;

    tm = xTime( it[i] ^ it[i+1] );
    it[i] ^= tm ^ tmp;

    tm = xTime( it[i+1] ^ it[i+2]);
    it[i+1] ^= tm ^ tmp;

    tm = xTime( it[i+2] ^ it[i+3]);
    it[i+2] ^= tm ^ tmp;

    tm = xTime(it[i+3] ^ t);
    it[i+3] ^= tm ^ tmp;
  }
}

// MixColumns function mixes the columns of the state matrix.
// The method used to multiply may be difficult to understand for the inexperienced.
// Please use the references to gain more information.
void QAESEncryption::invMixColumns()
{
  QByteArray::iterator it = m_state->begin();
  quint8 a,b,c,d;
  for(int i = 0; i < 16; i+=4)
  {
    a = (quint8) it[i];
    b = (quint8) it[i+1];
    c = (quint8) it[i+2];
    d = (quint8) it[i+3];

    it[i]   = (quint8) (Multiply(a, 0x0e) ^ Multiply(b, 0x0b) ^ Multiply(c, 0x0d) ^ Multiply(d, 0x09));
    it[i+1] = (quint8) (Multiply(a, 0x09) ^ Multiply(b, 0x0e) ^ Multiply(c, 0x0b) ^ Multiply(d, 0x0d));
    it[i+2] = (quint8) (Multiply(a, 0x0d) ^ Multiply(b, 0x09) ^ Multiply(c, 0x0e) ^ Multiply(d, 0x0b));
    it[i+3] = (quint8) (Multiply(a, 0x0b) ^ Multiply(b, 0x0d) ^ Multiply(c, 0x09) ^ Multiply(d, 0x0e));
  }
}

// The SubBytes Function Substitutes the values in the
// state matrix with values in an S-box.
void QAESEncryption::invSubBytes()
{
    QByteArray::iterator it = m_state->begin();
    for(int i = 0; i < 16; ++i)
        it[i] = getSBoxInvert(it[i]);
}

void QAESEncryption::invShiftRows()
{
    QByteArray::iterator it = m_state->begin();
    uint8_t temp;

    //Shift 1 to right
    temp = (quint8) it[4+3];
    it[4+3] = it[4+2];
    it[4+2] = it[4+1];
    it[4+1] = it[4];
    it[4] = temp;

    //Shift 2
    temp = (quint8) it[8+2];
    it[8+2] = it[8];
    it[8] = temp;
    temp = (quint8) it[8+3];
    it[8+3] = it[8+1];
    it[8+1] = temp;

    //Shift 3
    temp = (quint8) it[12+3];
    it[12+3] = it[12];
    it[12] = it[12+1];
    it[12+1] = it[12+2];
    it[12+2] = temp;
}

// Cipher is the main function that encrypts the PlainText.
QByteArray QAESEncryption::cipher(const QByteArray expKey, const QByteArray in)
{

  //m_state is the input buffer...
  QByteArray output(in);
  m_state = &output;

  quint8 round = 0;

  // Add the First round key to the state before starting the rounds.
  addRoundKey(0, expKey);

  //qDebug() << print(output);
  // There will be Nr rounds.
  // The first Nr-1 rounds are identical.
  // These Nr-1 rounds are executed in the loop below.
  for(round = 1; round < m_nr; ++round)
  {
    subBytes();
    shiftRows();
    mixColumns();
    addRoundKey(round, expKey);
  }

  // The last round is given below.
  // The MixColumns function is not here in the last round.
  subBytes();
  shiftRows();
  addRoundKey(m_nr, expKey);

  return output;
}

QByteArray QAESEncryption::invCipher(const QByteArray expKey, const QByteArray in)
{
    //m_state is the input buffer.... handle it!
    QByteArray output(in);
    m_state = &output;
    uint8_t round = 0;

    // Add the First round key to the state before starting the rounds.
    addRoundKey(m_nr, expKey);

    // There will be Nr rounds.
    // The first Nr-1 rounds are identical.
    // These Nr-1 rounds are executed in the loop below.
    for(round=m_nr-1;round>0;round--)
    {
        invShiftRows();
        invSubBytes();
        addRoundKey(round, expKey);
        invMixColumns();
    }

    // The last round is given below.
    // The MixColumns function is not here in the last round.
    invShiftRows();
    invSubBytes();
    addRoundKey(0, expKey);

    return output;
}

QByteArray QAESEncryption::encode(const QByteArray rawText, const QByteArray key, const QByteArray iv)
{
    if (m_mode == CBC && iv.isNull())
       return QByteArray();

    QByteArray ret;
    QByteArray expandedKey = expandKey(key);
    QByteArray alignedText(rawText);

    alignedText.append(getPadding(rawText.size(), m_keyLen), 0); //filling the array with zeros

    for(int i=0; i < alignedText.size(); i+= m_keyLen)
    {
        ret.append(cipher(expandedKey, alignedText.mid(i, m_keyLen)));
        qDebug() << print(ret.mid(i, m_keyLen)); //test
    }
    qDebug() << "--";
    return ret;
}

QByteArray QAESEncryption::decode(const QByteArray rawText, const QByteArray key, const QByteArray iv)
{
    if (m_mode == CBC && iv.isNull())
       return QByteArray();

    QByteArray ret;
    QByteArray expandedKey = expandKey(key);
    QByteArray alignedText(rawText);

    alignedText.append(getPadding(rawText.size(), m_keyLen), 0); //filling the array with zeros

    for(int i=0; i < alignedText.size(); i+= m_keyLen)
    {
        ret.append(invCipher(expandedKey, alignedText.mid(i, m_keyLen)));
        qDebug() << print(ret.mid(i, m_keyLen)); //test
    }
    qDebug() << "--";
    return ret;
}

QString QAESEncryption::print(QByteArray in)
{
    QString ret="";
    for (int i=0; i < in.size();i++) {
        QString number = QString::number((quint8)in.at(i), 16);
        if (number.size()==1)
            number.insert(0, "0");
        ret.append(QString("%1").arg(number));
    }
    return ret;
}
<|endoftext|>


<commit_before>#include "single_thread_lock_free.h"
#include "../src/transwarp.h"
#include <array>
#include <iostream>
#include <fstream>
#include <functional>
#include <numeric>
#include <queue>
#include <random>

namespace tw = transwarp;

namespace examples {

namespace {

class lock_free_executor : public tw::executor {
public:
    lock_free_executor()
    : done_{false}, thread_{&lock_free_executor::worker, this}
    {}

    ~lock_free_executor() {
        done_ = true;
        thread_.join();
    }

    std::string name() const override {
        return "lock_free_executor";
    }

    void execute(const std::function<void()>& functor, tw::itask&) override {
        std::lock_guard lock{mutex_};
        queue_.push(functor);
    }

private:

    void worker() {
        while (!done_) {
            decltype(queue_) queue;
            {
                std::lock_guard lock{mutex_};
                queue_.swap(queue);
            }
            while (!queue.empty()) {
                queue.front()();
                queue.pop();
            }
        }
    }

    std::atomic_bool done_;
    std::mutex mutex_; // wouldn't need this if queue_ was lock-free
    std::queue<std::function<void()>> queue_; // this could be a lock-free queue in the real world
    std::thread thread_;
};

using data_t = std::array<double, 1024>;

const data_t& generate_data(data_t& data, std::shared_ptr<std::mt19937> gen) {
    std::uniform_real_distribution<double> dist;
    for (auto& value : data) {
        value = dist(*gen);
    }
    return data;
}

double average(const data_t& data) {
    return std::accumulate(data.begin(), data.end(), 0.) / static_cast<double>(data.size());
}

double stddev(const data_t& data, double average) {
    double sum = 0;
    std::for_each(data.begin(), data.end(),
                  [average,&sum](double x) { sum += std::pow(x - average, 2.); });
    return std::sqrt(sum / static_cast<double>(data.size()));
}

struct result {
    double avg;
    double stddev;
};

std::ostream& operator<<(std::ostream& os, const result& r) {
    os << "avg=" << r.avg << ", stddev=" << r.stddev;
    return os;
}

std::shared_ptr<tw::task<result>> build_graph(data_t& buffer) {
    auto gen = std::make_shared<std::mt19937>(1);
    auto gen_task = tw::make_value_task(gen)->named("rand gen");
    auto buffer_task = tw::make_task(tw::root, [&buffer]() -> data_t& { return buffer; })->named("buffer");
    auto generator_task = tw::make_task(tw::consume, generate_data, buffer_task, gen_task)->named("generator");
    auto avg_task = tw::make_task(tw::consume, average, generator_task)->named("average");
    auto stddev_task = tw::make_task(tw::consume, stddev, generator_task, avg_task)->named("stddev");
    return tw::make_task(tw::consume, [](double avg, double stddev) { return result{avg, stddev}; },
                         avg_task, stddev_task)->named("aggregation");
}

}

// This example demonstrates how tasks can be scheduled for execution using
// a potentially lock-free, single-thread executor. In addition, it is shown that a stack
// allocated buffer can be used as input into the graph.
void single_thread_lock_free(std::ostream& os, std::size_t sample_size) {
    os.precision(3);

    // Stack allocated buffer
    data_t buffer;

    // Building the graph and retrieving the final task
    auto task = build_graph(buffer);

    // Output the graph for visualization
    std::ofstream("single_thread_lock_free.dot") << tw::to_string(task->edges());

    // The single-thread executor
    lock_free_executor executor;

    std::size_t count = 0;
    while (count < sample_size) {
        task->schedule_all(executor);
        os << task->get() << std::endl;
        ++count;
    }
}

}

#ifndef UNITTEST
int main() {
    std::cout << "Running example: single_thread_lock_free ..." << std::endl;
    examples::single_thread_lock_free(std::cout);
}
#endif
<commit_msg>better naming<commit_after>#include "single_thread_lock_free.h"
#include "../src/transwarp.h"
#include <array>
#include <iostream>
#include <fstream>
#include <functional>
#include <numeric>
#include <queue>
#include <random>

namespace tw = transwarp;

namespace examples {

namespace {

class executor : public tw::executor {
public:
    executor()
    : done_{false}, thread_{&executor::worker, this}
    {}

    ~executor() {
        done_ = true;
        thread_.join();
    }

    std::string name() const override {
        return "lock_free_executor";
    }

    void execute(const std::function<void()>& functor, tw::itask&) override {
        std::lock_guard lock{mutex_};
        queue_.push(functor);
    }

private:

    void worker() {
        while (!done_) {
            decltype(queue_) queue;
            {
                std::lock_guard lock{mutex_};
                queue_.swap(queue);
            }
            while (!queue.empty()) {
                queue.front()();
                queue.pop();
            }
        }
    }

    std::atomic_bool done_;
    std::mutex mutex_; // wouldn't need this if queue_ was lock-free
    std::queue<std::function<void()>> queue_; // this could be a lock-free queue (e.g. boost::spsc_queue)
    std::thread thread_;
};

using data_t = std::array<double, 1024>;

const data_t& generate_data(data_t& data, std::shared_ptr<std::mt19937> gen) {
    std::uniform_real_distribution<double> dist;
    for (auto& value : data) {
        value = dist(*gen);
    }
    return data;
}

double average(const data_t& data) {
    return std::accumulate(data.begin(), data.end(), 0.) / static_cast<double>(data.size());
}

double stddev(const data_t& data, double average) {
    double sum = 0;
    std::for_each(data.begin(), data.end(),
                  [average,&sum](double x) { sum += std::pow(x - average, 2.); });
    return std::sqrt(sum / static_cast<double>(data.size()));
}

struct result {
    double avg;
    double stddev;
};

std::ostream& operator<<(std::ostream& os, const result& r) {
    os << "avg=" << r.avg << ", stddev=" << r.stddev;
    return os;
}

std::shared_ptr<tw::task<result>> build_graph(data_t& buffer) {
    auto gen = std::make_shared<std::mt19937>(1);
    auto gen_task = tw::make_value_task(gen)->named("rand gen");
    auto buffer_task = tw::make_task(tw::root, [&buffer]() -> data_t& { return buffer; })->named("buffer");
    auto generator_task = tw::make_task(tw::consume, generate_data, buffer_task, gen_task)->named("generator");
    auto avg_task = tw::make_task(tw::consume, average, generator_task)->named("average");
    auto stddev_task = tw::make_task(tw::consume, stddev, generator_task, avg_task)->named("stddev");
    return tw::make_task(tw::consume, [](double avg, double stddev) { return result{avg, stddev}; },
                         avg_task, stddev_task)->named("aggregation");
}

}

// This example demonstrates how tasks can be scheduled for execution using
// a potentially lock-free, single-thread executor. In addition, it is shown that a stack
// allocated buffer can be used as input into the graph.
void single_thread_lock_free(std::ostream& os, std::size_t sample_size) {
    os.precision(3);

    // Stack allocated buffer
    data_t buffer;

    // Building the graph and retrieving the final task
    auto task = build_graph(buffer);

    // Output the graph for visualization
    std::ofstream("single_thread_lock_free.dot") << tw::to_string(task->edges());

    // The single-thread executor
    executor exec;

    std::size_t count = 0;
    while (count < sample_size) {
        task->schedule_all(exec);
        os << task->get() << std::endl;
        ++count;
    }
}

}

#ifndef UNITTEST
int main() {
    std::cout << "Running example: single_thread_lock_free ..." << std::endl;
    examples::single_thread_lock_free(std::cout);
}
#endif
<|endoftext|>


<commit_before>/******************************************************************************
 * Copyright 2019 Google
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/
#include "CloudIoTCoreMqtt.h"

// Forward global callback declarations
String getJwt();
void setupCert();
Client* setupNetwork(bool);
void messageReceived(String &topic, String &payload);

///////////////////////////////
// MQTT common functions
///////////////////////////////
CloudIoTCoreMqtt::CloudIoTCoreMqtt(
    MQTTClient *_mqttClient, Client *_netClient, CloudIoTCoreDevice *_device){
  this->mqttClient = _mqttClient;
  this->netClient = _netClient;
  this->device = _device;
}

void CloudIoTCoreMqtt::loop() {
  if (false && millis() > device->getExpMillis() && mqttClient->connected()) {
    // reconnect
    Serial.println("Reconnecting before JWT expiration");
    iss = 0; // Force JWT regeneration
    getJwt(); // Regenerate JWT using device function
    mqttClient->disconnect();
    mqttConnect(true); // TODO: should we skip closing connection
  }
  this->mqttClient->loop();
}

void CloudIoTCoreMqtt::mqttConnect(bool skip) {
  Serial.print("\nconnecting...");
  bool keepgoing = true;
  while (keepgoing) {
    bool result =
        this->mqttClient->connect(
            device->getClientId().c_str(),
            "unused",
            getJwt().c_str(),
            skip);

    if (this->mqttClient->lastError() != LWMQTT_SUCCESS && result){
      // TODO: refactorme
      // Inform the client why it could not connect and help debugging.
      logError();
      logReturnCode();
      logConfiguration(false);

      // See https://cloud.google.com/iot/docs/how-tos/exponential-backoff
      if (this->__backoff__ < this->__minbackoff__) {
        this->__backoff__ = this->__minbackoff__;
      }
      this->__backoff__ = (this->__backoff__ * this->__factor__) + random(this->__jitter__);
      if (this->__backoff__ > this->__max_backoff__) {
        this->__backoff__ = this->__max_backoff__;
      }

      // Clean up the client
      this->mqttClient->disconnect();
      skip = false;
      Serial.println("Delaying " + String(this->__backoff__) + "ms");
      delay(this->__backoff__);
      keepgoing = true;
    } else {
      Serial.println(mqttClient->connected() ? "connected" : "not connected");
      if (!mqttClient->connected()) {
        Serial.println("Settings incorrect or missing a cyper for SSL");
        mqttClient->disconnect();
        logConfiguration(false);
        skip = false;
        keepgoing = true;
        Serial.println("Waiting 60 seconds, retry will likely fail");
        delay(this->__max_backoff__);
      } else {
        // We're now connected
        Serial.println("\nLibrary connected!");
        keepgoing = false;
        this->__backoff__ = this->__minbackoff__;
      }
    }
  }

  // Set QoS to 1 (ack) for configuration messages
  this->mqttClient->subscribe(device->getConfigTopic(), 1);
  // QoS 0 (no ack) for commands
  this->mqttClient->subscribe(device->getCommandsTopic(), 0);

  onConnect();
}

void CloudIoTCoreMqtt::startMQTT() {
  if (this->useLts) {
    this->mqttClient->begin(CLOUD_IOT_CORE_MQTT_HOST_LTS, CLOUD_IOT_CORE_MQTT_PORT, *netClient);
  } else {
    this->mqttClient->begin(CLOUD_IOT_CORE_MQTT_HOST, CLOUD_IOT_CORE_MQTT_PORT, *netClient);
  }
  this->mqttClient->onMessage(messageReceived);
}

bool CloudIoTCoreMqtt::publishTelemetry(String data) {
  return this->mqttClient->publish(device->getEventsTopic(), data);
}

bool CloudIoTCoreMqtt::publishTelemetry(const char* data, int length) {
  return this->mqttClient->publish(device->getEventsTopic().c_str(), data, length);
}

bool CloudIoTCoreMqtt::publishTelemetry(String subtopic, String data) {
  return this->mqttClient->publish(device->getEventsTopic() + subtopic, data);
}

bool CloudIoTCoreMqtt::publishTelemetry(String subtopic, const char* data, int length) {
  return this->mqttClient->publish(String(device->getEventsTopic() + subtopic).c_str(), data, length);
}

// Helper that just sends default sensor
bool CloudIoTCoreMqtt::publishState(String data) {
  return this->mqttClient->publish(device->getStateTopic(), data);
}

bool CloudIoTCoreMqtt::publishState(const char* data, int length) {
  return this->mqttClient->publish(device->getStateTopic().c_str(), data, length);
}

void CloudIoTCoreMqtt::logError() {
  Serial.println(this->mqttClient->lastError());
  switch(this->mqttClient->lastError()) {
    case (LWMQTT_BUFFER_TOO_SHORT):
      Serial.println("LWMQTT_BUFFER_TOO_SHORT");
      break;
    case (LWMQTT_VARNUM_OVERFLOW):
      Serial.println("LWMQTT_VARNUM_OVERFLOW");
      break;
    case (LWMQTT_NETWORK_FAILED_CONNECT):
      Serial.println("LWMQTT_NETWORK_FAILED_CONNECT");
      break;
    case (LWMQTT_NETWORK_TIMEOUT):
      Serial.println("LWMQTT_NETWORK_TIMEOUT");
      break;
    case (LWMQTT_NETWORK_FAILED_READ):
      Serial.println("LWMQTT_NETWORK_FAILED_READ");
      break;
    case (LWMQTT_NETWORK_FAILED_WRITE):
      Serial.println("LWMQTT_NETWORK_FAILED_WRITE");
      break;
    case (LWMQTT_REMAINING_LENGTH_OVERFLOW):
      Serial.println("LWMQTT_REMAINING_LENGTH_OVERFLOW");
      break;
    case (LWMQTT_REMAINING_LENGTH_MISMATCH):
      Serial.println("LWMQTT_REMAINING_LENGTH_MISMATCH");
      break;
    case (LWMQTT_MISSING_OR_WRONG_PACKET):
      Serial.println("LWMQTT_MISSING_OR_WRONG_PACKET");
      break;
    case (LWMQTT_CONNECTION_DENIED):
      Serial.println("LWMQTT_CONNECTION_DENIED");
      break;
    case (LWMQTT_FAILED_SUBSCRIPTION):
      Serial.println("LWMQTT_FAILED_SUBSCRIPTION");
      break;
    case (LWMQTT_SUBACK_ARRAY_OVERFLOW):
      Serial.println("LWMQTT_SUBACK_ARRAY_OVERFLOW");
      break;
    case (LWMQTT_PONG_TIMEOUT):
      Serial.println("LWMQTT_PONG_TIMEOUT");
      break;
    default:
      Serial.println("This error code should never be reached.");
      break;
  }
}

void CloudIoTCoreMqtt::logConfiguration(bool showJWT) {
  Serial.println("Connect with " + String(CLOUD_IOT_CORE_MQTT_HOST_LTS) +
      ":" + String(CLOUD_IOT_CORE_MQTT_PORT));
  Serial.println("ClientId: " + device->getClientId());
  if (showJWT) {
    Serial.println("JWT: " + getJwt());
  }
}

void CloudIoTCoreMqtt::logReturnCode() {
  Serial.println(this->mqttClient->returnCode());
  switch(this->mqttClient->returnCode()) {
    case (LWMQTT_CONNECTION_ACCEPTED):
      Serial.println("OK");
      break;
    case (LWMQTT_UNACCEPTABLE_PROTOCOL):
      Serial.println("LWMQTT_UNACCEPTABLE_PROTOCOLL");
      break;
    case (LWMQTT_IDENTIFIER_REJECTED):
      Serial.println("LWMQTT_IDENTIFIER_REJECTED");
      break;
    case (LWMQTT_SERVER_UNAVAILABLE):
      Serial.println("LWMQTT_SERVER_UNAVAILABLE");
      break;
    case (LWMQTT_BAD_USERNAME_OR_PASSWORD):
      Serial.println("LWMQTT_BAD_USERNAME_OR_PASSWORD");
      iss = 0; // Force JWT regeneration
      break;
    case (LWMQTT_NOT_AUTHORIZED):
      Serial.println("LWMQTT_NOT_AUTHORIZED");
      iss = 0; // Force JWT regeneration
      break;
    case (LWMQTT_UNKNOWN_RETURN_CODE):
      Serial.println("LWMQTT_UNKNOWN_RETURN_CODE");
      break;
    default:
      Serial.println("This return code should never be reached.");
      break;
  }
}

void CloudIoTCoreMqtt::onConnect() {
  if (logConnect) {
    publishState("connected");
    publishTelemetry("/events", device->getDeviceId() + String("-connected"));
  }
}

void CloudIoTCoreMqtt::setLogConnect(boolean enabled) {
  this->logConnect = enabled;
}

void CloudIoTCoreMqtt::setUseLts(boolean enabled) {
  this->useLts = enabled;
}
<commit_msg>Log fail connect (#140)<commit_after>/******************************************************************************
 * Copyright 2019 Google
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/
#include "CloudIoTCoreMqtt.h"

// Forward global callback declarations
String getJwt();
void setupCert();
Client* setupNetwork(bool);
void messageReceived(String &topic, String &payload);

///////////////////////////////
// MQTT common functions
///////////////////////////////
CloudIoTCoreMqtt::CloudIoTCoreMqtt(
    MQTTClient *_mqttClient, Client *_netClient, CloudIoTCoreDevice *_device){
  this->mqttClient = _mqttClient;
  this->netClient = _netClient;
  this->device = _device;
}

void CloudIoTCoreMqtt::loop() {
  if (millis() > device->getExpMillis() && mqttClient->connected()) {
    // reconnect
    Serial.println("Reconnecting before JWT expiration");
    iss = 0; // Force JWT regeneration
    getJwt(); // Regenerate JWT using device function
    mqttClient->disconnect();
    mqttConnect(true); // TODO: should we skip closing connection
  }
  this->mqttClient->loop();
}

void CloudIoTCoreMqtt::mqttConnect(bool skip) {
  Serial.print("\nconnecting...");
  bool keepgoing = true;
  while (keepgoing) {
    bool result =
        this->mqttClient->connect(
            device->getClientId().c_str(),
            "unused",
            getJwt().c_str(),
            skip);

    if (this->mqttClient->lastError() != LWMQTT_SUCCESS && result){
      // TODO: refactorme
      // Inform the client why it could not connect and help debugging.
      logError();
      logReturnCode();
      logConfiguration(false);

      // See https://cloud.google.com/iot/docs/how-tos/exponential-backoff
      if (this->__backoff__ < this->__minbackoff__) {
        this->__backoff__ = this->__minbackoff__;
      }
      this->__backoff__ = (this->__backoff__ * this->__factor__) + random(this->__jitter__);
      if (this->__backoff__ > this->__max_backoff__) {
        this->__backoff__ = this->__max_backoff__;
      }

      // Clean up the client
      this->mqttClient->disconnect();
      skip = false;
      Serial.println("Delaying " + String(this->__backoff__) + "ms");
      delay(this->__backoff__);
      keepgoing = true;
    } else {
      Serial.println(mqttClient->connected() ? "connected" : "not connected");
      if (!mqttClient->connected()) {
        Serial.println("Settings incorrect or missing a cyper for SSL");
        mqttClient->disconnect();
        logConfiguration(false);
        skip = false;
        keepgoing = true;
        Serial.println("Waiting 60 seconds, retry will likely fail");
        delay(this->__max_backoff__);
      } else {
        // We're now connected
        Serial.println("\nLibrary connected!");
        keepgoing = false;
        this->__backoff__ = this->__minbackoff__;
      }
    }
  }

  // Set QoS to 1 (ack) for configuration messages
  this->mqttClient->subscribe(device->getConfigTopic(), 1);
  // QoS 0 (no ack) for commands
  this->mqttClient->subscribe(device->getCommandsTopic(), 0);

  onConnect();
}

void CloudIoTCoreMqtt::startMQTT() {
  if (this->useLts) {
    this->mqttClient->begin(CLOUD_IOT_CORE_MQTT_HOST_LTS, CLOUD_IOT_CORE_MQTT_PORT, *netClient);
  } else {
    this->mqttClient->begin(CLOUD_IOT_CORE_MQTT_HOST, CLOUD_IOT_CORE_MQTT_PORT, *netClient);
  }
  this->mqttClient->onMessage(messageReceived);
}

bool CloudIoTCoreMqtt::publishTelemetry(String data) {
  return this->mqttClient->publish(device->getEventsTopic(), data);
}

bool CloudIoTCoreMqtt::publishTelemetry(const char* data, int length) {
  return this->mqttClient->publish(device->getEventsTopic().c_str(), data, length);
}

bool CloudIoTCoreMqtt::publishTelemetry(String subtopic, String data) {
  return this->mqttClient->publish(device->getEventsTopic() + subtopic, data);
}

bool CloudIoTCoreMqtt::publishTelemetry(String subtopic, const char* data, int length) {
  return this->mqttClient->publish(String(device->getEventsTopic() + subtopic).c_str(), data, length);
}

// Helper that just sends default sensor
bool CloudIoTCoreMqtt::publishState(String data) {
  return this->mqttClient->publish(device->getStateTopic(), data);
}

bool CloudIoTCoreMqtt::publishState(const char* data, int length) {
  return this->mqttClient->publish(device->getStateTopic().c_str(), data, length);
}

void CloudIoTCoreMqtt::logError() {
  Serial.println(this->mqttClient->lastError());
  switch(this->mqttClient->lastError()) {
    case (LWMQTT_BUFFER_TOO_SHORT):
      Serial.println("LWMQTT_BUFFER_TOO_SHORT");
      break;
    case (LWMQTT_VARNUM_OVERFLOW):
      Serial.println("LWMQTT_VARNUM_OVERFLOW");
      break;
    case (LWMQTT_NETWORK_FAILED_CONNECT):
      Serial.println("LWMQTT_NETWORK_FAILED_CONNECT");
      break;
    case (LWMQTT_NETWORK_TIMEOUT):
      Serial.println("LWMQTT_NETWORK_TIMEOUT");
      break;
    case (LWMQTT_NETWORK_FAILED_READ):
      Serial.println("LWMQTT_NETWORK_FAILED_READ");
      break;
    case (LWMQTT_NETWORK_FAILED_WRITE):
      Serial.println("LWMQTT_NETWORK_FAILED_WRITE");
      break;
    case (LWMQTT_REMAINING_LENGTH_OVERFLOW):
      Serial.println("LWMQTT_REMAINING_LENGTH_OVERFLOW");
      break;
    case (LWMQTT_REMAINING_LENGTH_MISMATCH):
      Serial.println("LWMQTT_REMAINING_LENGTH_MISMATCH");
      break;
    case (LWMQTT_MISSING_OR_WRONG_PACKET):
      Serial.println("LWMQTT_MISSING_OR_WRONG_PACKET");
      break;
    case (LWMQTT_CONNECTION_DENIED):
      Serial.println("LWMQTT_CONNECTION_DENIED");
      break;
    case (LWMQTT_FAILED_SUBSCRIPTION):
      Serial.println("LWMQTT_FAILED_SUBSCRIPTION");
      break;
    case (LWMQTT_SUBACK_ARRAY_OVERFLOW):
      Serial.println("LWMQTT_SUBACK_ARRAY_OVERFLOW");
      break;
    case (LWMQTT_PONG_TIMEOUT):
      Serial.println("LWMQTT_PONG_TIMEOUT");
      break;
    default:
      Serial.println("This error code should never be reached.");
      break;
  }
}

void CloudIoTCoreMqtt::logConfiguration(bool showJWT) {
  Serial.println("Connect with " + String(CLOUD_IOT_CORE_MQTT_HOST_LTS) +
      ":" + String(CLOUD_IOT_CORE_MQTT_PORT));
  Serial.println("ClientId: " + device->getClientId());
  if (showJWT) {
    Serial.println("JWT: " + getJwt());
  }
}

void CloudIoTCoreMqtt::logReturnCode() {
  Serial.println(this->mqttClient->returnCode());
  switch(this->mqttClient->returnCode()) {
    case (LWMQTT_CONNECTION_ACCEPTED):
      Serial.println("OK");
      break;
    case (LWMQTT_UNACCEPTABLE_PROTOCOL):
      Serial.println("LWMQTT_UNACCEPTABLE_PROTOCOLL");
      break;
    case (LWMQTT_IDENTIFIER_REJECTED):
      Serial.println("LWMQTT_IDENTIFIER_REJECTED");
      break;
    case (LWMQTT_SERVER_UNAVAILABLE):
      Serial.println("LWMQTT_SERVER_UNAVAILABLE");
      break;
    case (LWMQTT_BAD_USERNAME_OR_PASSWORD):
      Serial.println("LWMQTT_BAD_USERNAME_OR_PASSWORD");
      iss = 0; // Force JWT regeneration
      break;
    case (LWMQTT_NOT_AUTHORIZED):
      Serial.println("LWMQTT_NOT_AUTHORIZED");
      iss = 0; // Force JWT regeneration
      break;
    case (LWMQTT_UNKNOWN_RETURN_CODE):
      Serial.println("LWMQTT_UNKNOWN_RETURN_CODE");
      break;
    default:
      Serial.println("This return code should never be reached.");
      break;
  }
}

void CloudIoTCoreMqtt::onConnect() {
  if (logConnect) {
    publishState("connected");
    publishTelemetry("/events", device->getDeviceId() + String("-connected"));
  }
}

void CloudIoTCoreMqtt::setLogConnect(boolean enabled) {
  this->logConnect = enabled;
}

void CloudIoTCoreMqtt::setUseLts(boolean enabled) {
  this->useLts = enabled;
}
<|endoftext|>