Advertisement
Guest User

Untitled

a guest
Dec 17th, 2017
80
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.23 KB | None | 0 0
  1. #define Py_LIMITED_API
  2. #include <Python.h>
  3. #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
  4. #include <numpy/arrayobject.h>
  5.  
  6. #include <vector>
  7. #include <algorithm>
  8.  
  9.  
  10. static PyObject* quantize_quantize(PyObject *self, PyObject *args);
  11.  
  12. static PyMethodDef quantize_methods[] = {
  13. {"quantize", quantize_quantize, METH_VARARGS, "Add to numbers."},
  14. {nullptr, nullptr, 0, nullptr} /* Sentinel */
  15. };
  16.  
  17. static PyModuleDef quantize_module = {
  18. PyModuleDef_HEAD_INIT,
  19. "quantize", /* name of module */
  20. "Simple module", /* module documentation */
  21. -1, /* irrelevant */
  22. quantize_methods
  23. };
  24.  
  25. // extern "C" PyObject* PyInit_quantize()
  26. PyMODINIT_FUNC PyInit_quantize()
  27. {
  28. return PyModule_Create(&quantize_module);
  29. }
  30.  
  31. template<class T>
  32. static std::vector<T> calculate_boundaries(T *array, size_t size, size_t quantized_quantity) {
  33. std::vector<T> input(size);
  34. for (size_t i = 0; i < size; ++i) {
  35. input[i] = array[i];
  36. }
  37. std::sort(input.begin(), input.end());
  38. std::vector<T> boundaries(quantized_quantity);
  39. for (size_t i = 0; i < quantized_quantity; ++i) {
  40. boundaries[i] = input[i*size / quantized_quantity];
  41. }
  42. return boundaries;
  43. }
  44.  
  45. template<class T>
  46. static std::vector<int64_t> calculate_quantized(T*array, size_t size, const std::vector<T>& boundaries) {
  47. std::vector<int64_t> quantized(size);
  48. for (size_t i = 0; i < size; ++i) {
  49. auto it = std::lower_bound(boundaries.begin(), boundaries.end(), array[i]);
  50. quantized[i] = boundaries.begin() - it;
  51. }
  52. return quantized;
  53. }
  54.  
  55. template<class T>
  56. static PyObject * convert_to_py_object(const std::vector<T>& boundaries,
  57. int type,
  58. const std::vector<int64_t>& quantized) {
  59. auto boundaries_size = (npy_intp)boundaries.size();
  60. auto quantize_size = (npy_intp)quantized.size();
  61.  
  62. auto boundaries_data = new T [boundaries.size()];
  63. auto quantize_data = new int64_t [quantized.size()];
  64.  
  65. std::memcpy(boundaries_data, &boundaries[0], boundaries.size() * sizeof(T));
  66. std::memcpy(quantize_data, &quantized[0], quantized.size() * sizeof(int64_t));
  67.  
  68. auto py_boundaries = (PyArrayObject *) PyArray_SimpleNewFromData(1,
  69. &boundaries_size,
  70. type,
  71. boundaries_data);
  72. auto py_quantized = (PyArrayObject *) PyArray_SimpleNewFromData(1,
  73. &quantize_size,
  74. NPY_INT64,
  75. quantize_data);
  76. return PyTuple_Pack(2, py_boundaries, py_quantized);
  77. }
  78.  
  79. static PyObject* quantize_quantize(PyObject *self, PyObject *args)
  80. {
  81. if (!self || !args) {
  82. PyErr_SetString(PyExc_RuntimeError, "bad self or args\n");
  83. return PyErr_Occurred();
  84. }
  85.  
  86. PyArrayObject *input_arr = nullptr;
  87. int arg2 = 0;
  88.  
  89. if (!PyArg_ParseTuple(args, "O!i", &PyArray_Type, &input_arr, &arg2)) {
  90. PyErr_SetString(PyExc_RuntimeError, "bad type or number of args\n");
  91. return PyErr_Occurred();
  92. }
  93.  
  94. if (PyArray_NDIM(input_arr) != 1) {
  95. PyErr_SetString(PyExc_RuntimeError, "bad dimension of array\n");
  96. return PyErr_Occurred();
  97. }
  98.  
  99. int type = PyArray_TYPE(input_arr);
  100. auto size = (size_t)PyArray_SHAPE(input_arr)[0];
  101. auto quantize_quantity = (size_t)arg2;
  102.  
  103. switch (type) {
  104. case NPY_FLOAT:
  105. case NPY_DOUBLE: {
  106. auto array = (double *) PyArray_DATA(input_arr);
  107. const auto boundaries = calculate_boundaries<double>(array, size, quantize_quantity);
  108. const auto quantized = calculate_quantized<double>( array, size, boundaries);
  109. return convert_to_py_object<double>(boundaries, NPY_DOUBLE, quantized);
  110. }
  111. default:
  112. PyErr_SetString(PyExc_RuntimeError, "unknown type elements in array\n");
  113. return PyErr_Occurred();
  114. }
  115. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement