Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "Python.h"
- #include "Numeric/arrayobject.h"
- #define SEARCH_LOOP(OP, INC) { \
- for (i = start_addr; i != end_addr; INC) { \
- if (*i OP value) { \
- return (void*)i; \
- } \
- } \
- return (void*)0; }
- #define SWITCH_ON_OP(TYPE, INC) { \
- TYPE* i; \
- switch (op) { \
- case EQ: \
- SEARCH_LOOP(==, INC) \
- case GT: \
- SEARCH_LOOP(>, INC) \
- case GTE: \
- SEARCH_LOOP(>=, INC) \
- case LT: \
- SEARCH_LOOP(<, INC) \
- case LTE: \
- SEARCH_LOOP(<=, INC) \
- case NEQ: \
- SEARCH_LOOP(!=, INC) \
- default: \
- return (void*)0; \
- } \
- }
- #define SWITCH_ON_STRIDE(TYPE) { \
- if (stride > 0) \
- { \
- SWITCH_ON_OP(TYPE, i++) \
- } \
- else \
- { \
- SWITCH_ON_OP(TYPE, i--) \
- } \
- }
- enum comp_operators {
- EQ,
- GT,
- GTE,
- LT,
- LTE,
- NEQ
- };
- static void* array_find_byte(PyObject* searchval, void* start_addr, void* end_addr, int stride, int op) {
- char value = (char)(PyInt_AsLong(searchval));
- SWITCH_ON_STRIDE(char)
- }
- static void* array_find_short(PyObject* searchval, void* start_addr, void* end_addr, int stride, int op) {
- short value = (short)(PyInt_AsLong(searchval));
- SWITCH_ON_STRIDE(short)
- }
- static void* array_find_long(PyObject* searchval, void* start_addr, void* end_addr, int stride, int op) {
- long value = PyInt_AsLong(searchval);
- SWITCH_ON_STRIDE(long)
- }
- static void* array_find_longlong(PyObject* searchval, void* start_addr, void* end_addr, int stride, int op) {
- long long value = PyLong_AsLongLong(searchval);
- SWITCH_ON_STRIDE(long long)
- }
- static void* array_find_ubyte(PyObject* searchval, void* start_addr, void* end_addr, int stride, int op) {
- unsigned char value = (unsigned char)(PyInt_AsUnsignedLongMask(searchval));
- SWITCH_ON_STRIDE(unsigned char)
- }
- static void* array_find_ushort(PyObject* searchval, void* start_addr, void* end_addr, int stride, int op) {
- unsigned short value = (unsigned short)(PyInt_AsUnsignedLongMask(searchval));
- SWITCH_ON_STRIDE(unsigned short)
- }
- static void* array_find_ulong(PyObject* searchval, void* start_addr, void* end_addr, int stride, int op) {
- unsigned long value = PyInt_AsUnsignedLongMask(searchval);
- SWITCH_ON_STRIDE(unsigned long)
- }
- static void* array_find_ulonglong(PyObject* searchval, void* start_addr, void* end_addr, int stride, int op) {
- unsigned long long value = PyLong_AsUnsignedLongLong(searchval);
- SWITCH_ON_STRIDE(unsigned long long)
- }
- static void* array_find_float(PyObject* searchval, void* start_addr, void* end_addr, int stride, int op) {
- float value = (float)(PyFloat_AsDouble(searchval));
- SWITCH_ON_STRIDE(float)
- }
- static void* array_find_double(PyObject* searchval, void* start_addr, void* end_addr, int stride, int op) {
- double value = PyFloat_AsDouble(searchval);
- SWITCH_ON_STRIDE(double)
- }
- static void* array_find_eq_string(char* value, void* start_addr, void* end_addr, int stride, int elsize)
- {
- char dest[elsize+1];
- dest[elsize] = '\0';
- void* i;
- for (i = start_addr; i != end_addr; i += stride)
- {
- memcpy((void*)dest, i, elsize);
- if (strcmp(dest, value) == 0)
- {
- return i;
- }
- }
- return 0;
- }
- static void* array_find_neq_string(char* value, void* start_addr, void* end_addr, int stride, int elsize)
- {
- char dest[elsize+1];
- dest[elsize] = '\0';
- void* i;
- for (i = start_addr; i != end_addr; i += stride)
- {
- memcpy((void*)dest, i, elsize);
- if (strcmp(dest, value) != 0)
- {
- return i;
- }
- }
- return 0;
- }
- static void* array_find_string(PyObject* searchval, void* start_addr, void* end_addr, int stride, int op, int elsize) {
- char* value = PyString_AsString(searchval);
- if (op == NEQ)
- {
- return array_find_neq_string(value, start_addr, end_addr, stride, elsize);
- }
- else
- {
- return array_find_eq_string(value, start_addr, end_addr, stride, elsize);
- }
- }
- static PyObject* multi_find(PyObject* self, PyObject* args, short direction)
- {
- PyArrayObject* arr;
- PyObject* value;
- short eqtest;
- int start, end;
- if (!PyArg_ParseTuple(args, "O!Ohii", &PyArray_Type, &arr, &value, &eqtest, &start, &end))
- {
- return NULL;
- }
- char type = arr->descr->type;
- int elsize = arr->descr->elsize;
- int stride = arr->strides[0];
- void* base_addr = PyArray_DATA(arr);
- void* start_addr;
- void* end_addr;
- int dirstride = stride;
- void* temp;
- if (stride > 0)
- {
- start_addr = base_addr + stride * start;
- end_addr = base_addr + stride * end;
- }
- else
- {
- start_addr = base_addr + stride * start;
- end_addr = base_addr + stride * end;
- }
- if (!direction)
- {
- temp = start_addr;
- //Shift by one place so we read the same set of data backwards
- start_addr = end_addr - stride;
- end_addr = temp - stride;
- dirstride = -1 * stride;
- }
- void* dest_addr;
- switch (type)
- {
- case 'b':
- dest_addr = array_find_byte(value, start_addr, end_addr, dirstride, eqtest);
- break;
- case 'h':
- dest_addr = array_find_short(value, start_addr, end_addr, dirstride, eqtest);
- break;
- case 'i':
- dest_addr = array_find_long(value, start_addr, end_addr, dirstride, eqtest);
- break;
- case 'l':
- dest_addr = array_find_long(value, start_addr, end_addr, dirstride, eqtest);
- break;
- case 'q':
- dest_addr = array_find_longlong(value, start_addr, end_addr, dirstride, eqtest);
- break;
- case 'B':
- dest_addr = array_find_ubyte(value, start_addr, end_addr, dirstride, eqtest);
- break;
- case 'H':
- dest_addr = array_find_ushort(value, start_addr, end_addr, dirstride, eqtest);
- break;
- case 'I':
- dest_addr = array_find_ulong(value, start_addr, end_addr, dirstride, eqtest);
- break;
- case 'L':
- dest_addr = array_find_ulong(value, start_addr, end_addr, dirstride, eqtest);
- break;
- case 'Q':
- dest_addr = array_find_ulonglong(value, start_addr, end_addr, dirstride, eqtest);
- break;
- case 'f':
- dest_addr = array_find_float(value, start_addr, end_addr, dirstride, eqtest);
- break;
- case 'd':
- dest_addr = array_find_double(value, start_addr, end_addr, dirstride, eqtest);
- break;
- case 'S':
- dest_addr = array_find_string(value, start_addr, end_addr, dirstride, eqtest, elsize);
- break;
- default:
- dest_addr = 0;
- }
- // printf("%s\t%s\t%d\t%d\t%p\t%p\t%p\t%p\n", &(arr->descr->kind), &type, elsize, dirstride,
- // base_addr, start_addr, end_addr, dest_addr);
- int dest_index;
- if (dest_addr > 0)
- {
- dest_index = (dest_addr - base_addr) / stride;
- }
- else
- {
- dest_index = -1;
- }
- return Py_BuildValue("i", dest_index);
- }
- static char py_find_doc[] = "Finds the first index of the occurrence of a value in an array.";
- static PyObject* py_find(PyObject* self, PyObject* args)
- {
- return multi_find(self, args, 1);
- }
- static char py_rfind_doc[] = "Finds the last index of the occurrence of a value in an array.";
- static PyObject* py_rfind(PyObject* self, PyObject* args)
- {
- return multi_find(self, args, 0);
- }
- static PyMethodDef _npfindmethods[] = {
- {"np_find", py_find, METH_VARARGS, py_find_doc},
- {"np_rfind", py_rfind, METH_VARARGS, py_rfind_doc},
- {NULL, NULL, 0, NULL}
- };
- void init_npfind(void)
- {
- Py_InitModule("_npfind", _npfindmethods);
- import_array();
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement