Compare commits

..

11 commits

Author SHA1 Message Date
Christian Zimmermann
153d82223a merge 2024-04-02 20:47:30 +02:00
Christian Zimmermann
6a6e1c823c wrap more functions in Range wrapper 2024-04-02 20:23:08 +02:00
Christian Zimmermann
bd76070940 add more functions 2024-02-25 01:38:01 +01:00
Christian Zimmermann
b04a5ddc9d Merge remote-tracking branch 'origin/new-cpp' into new-cpp 2024-02-24 18:53:15 +01:00
Christian Zimmermann
53ec4a1276 adapt setup.py 2024-02-24 18:51:53 +01:00
Christian Zimmermann
034a9bcc8e create empty array 2024-02-09 13:45:21 +01:00
Christian Zimmermann
5a5e2fe59b write/read array works 2024-02-09 00:30:51 +01:00
Christian Zimmermann
a06bb976a0 array and range wrapper work again 2024-02-08 01:01:47 +01:00
Christian Zimmermann
564b3eebb5 WIP... 2024-02-06 01:41:49 +01:00
Christian Zimmermann
eeefff2cde WIP: range wrapper + WIP: array IO 2024-02-05 00:38:08 +01:00
Christian Zimmermann
c0fb3fe7ea switch to cpp wrapper -> first array wrapper works 2023-05-24 00:41:11 +02:00
13 changed files with 490 additions and 490 deletions

2
.gitignore vendored
View file

@ -1,5 +1,5 @@
.eggs/ .eggs/
build/ build/
dist/
cnorxz.egg-info/ cnorxz.egg-info/
*.so *.so
*.cpp

View file

@ -1,60 +0,0 @@
from libcpp.memory cimport shared_ptr
from range cimport cpp_RangeBase
from index cimport cpp_YIndex
cdef extern from "array/array.h" namespace "CNORXZ":
cdef cppclass cpp_AIndex "CNORXZ::AIndex" [T] (cpp_YIndex):
cpp_AIndex() except+
cpp_AIndex(const cpp_AIndex&) except+
cpp_AIndex(const T*, const shared_ptr[cpp_RangeBase]&, size_t lexpos) except+
cpp_AIndex(const T*, const cpp_YIndex&) except+
cpp_AIndex A_plus "operator+" (int n) except+
cpp_AIndex A_minus "operator-" (int n) except+
const T& A_get "operator*" () except+
cdef extern from "array/array.h" namespace "CNORXZ":
cdef cppclass cpp_BIndex "CNORXZ::BIndex" [T] (cpp_AIndex[T]):
cpp_BIndex() except+
cpp_BIndex(const cpp_AIndex[T]&) except+
cpp_BIndex(const T*, const shared_ptr[cpp_RangeBase]&, size_t lexpos) except+
cpp_BIndex(const T*, const cpp_AIndex[T]&) except+
cpp_BIndex B_plus "operator+" (int n) except+
cpp_BIndex B_minus "operator-" (int n) except+
T& B_get "operator*" () except+
cdef extern from "array/array.h" namespace "CNORXZ":
cdef cppclass cpp_CArrayBase "CNORXZ::CArrayBase" [T]:
cpp_CArrayBase() except+
cpp_CArrayBase(const cpp_CArrayBase[T]&) except+
size_t size() except+
shared_ptr[cpp_RangeBase] range() except+
cpp_AIndex[T] begin() except+
cpp_AIndex[T] end() except+
cdef extern from "array/array.h" namespace "CNORXZ":
cdef cppclass cpp_ArrayBase "CNORXZ::ArrayBase" [T] (cpp_CArrayBase[T]):
cpp_ArrayBase() except+
cpp_ArrayBase(const cpp_ArrayBase[T]&) except+
cpp_BIndex[T] begin() except+
cpp_BIndex[T] end() except+
cdef extern from "array/array.h" namespace "CNORXZ":
cdef cppclass cpp_MArray "CNORXZ::MArray" [T] (cpp_ArrayBase[T]):
cpp_MArray() except+
cpp_MArray(const cpp_MArray[T]&) except+
cpp_MArray(const shared_ptr[cpp_RangeBase]&) except+

View file

@ -1,24 +0,0 @@
from libcpp.string cimport string
from array cimport cpp_MArray
cdef extern from "cereal/cnorxz_cereal.h" namespace "CNORXZ::cer":
cdef cppclass cpp_Format "CNORXZ::cer::Format":
pass
cdef extern from "cereal/cnorxz_cereal.h" namespace "CNORXZ::cer::Format":
cdef cpp_Format BINARY
cdef cpp_Format JSON
cdef cpp_Format XML
cdef extern from "cereal/cnorxz_cereal.h" namespace "CNORXZ::cer":
cdef void cpp_writeJSONFile "CNORXZ::cer::writeJSONFile" [T] (const string&, const cpp_MArray[T]&)
cdef extern from "cereal/cnorxz_cereal.h" namespace "CNORXZ::cer":
cdef void cpp_writeBINARYFile "CNORXZ::cer::writeBINARYFile" [T] (const string&, const cpp_MArray[T]&)
cdef extern from "cereal/cnorxz_cereal.h" namespace "CNORXZ::cer":
cdef void cpp_readJSONFile "CNORXZ::cer::readJSONFile" [T] (const string&, cpp_MArray[T]&)
cdef extern from "cereal/cnorxz_cereal.h" namespace "CNORXZ::cer":
cdef void cpp_readBINARYFile "CNORXZ::cer::readBINARYFile" [T] (const string&, cpp_MArray[T]&)

46
cnorxz/core/core.cpp Normal file
View file

@ -0,0 +1,46 @@
#include <Python.h>
#include "array_wrapper.h"
#include "range_wrapper.h"
using namespace CNORXZ;
static PyMethodDef cnorxz_core_methods[] = {
{ "readFile", (PyCFunction) PyCxReadFile, METH_VARARGS| METH_KEYWORDS, "Read cnorxz-formatted file." },
{ NULL, NULL, 0, NULL }
};
static PyModuleDef cnorxz_core_module = {
PyModuleDef_HEAD_INIT,
"cnorxz",
"cnorxz core module",
-1,
cnorxz_core_methods
};
PyMODINIT_FUNC PyInit_cnorxz()
{
PyObject* m;
PyTypeObject* cxarray_type = PyCxArrayBType_init();
PyTypeObject* cxrange_type = PyCxRangeType_init();
if(cxarray_type == NULL){
return NULL;
}
if(cxrange_type == NULL){
return NULL;
}
m = PyModule_Create(&cnorxz_core_module);
if(m == NULL){
return NULL;
}
Py_INCREF(cxarray_type);
Py_INCREF(cxrange_type);
PyModule_AddObject(m, "Array", (PyObject*) cxarray_type);
PyModule_AddObject(m, "Range", (PyObject*) cxrange_type);
return m;
}

View file

@ -1,284 +0,0 @@
#cython: language_level=3
#cython: c_string_type=str
#cython: c_string_encoding=ascii
#cython: boundscheck=False
#cython: wrapparound=False
#cython: cdivision=True
#cython: embedsignature=True
from libcpp.memory cimport shared_ptr, make_shared, dynamic_pointer_cast
from libcpp.string cimport string
from libcpp cimport bool
from cython.operator cimport dereference as deref
from range cimport cpp_RangeBase
from range_factory cimport cpp_RangeFactoryBase, cpp_CRangeFactory
from array cimport cpp_CArrayBase, cpp_MArray, cpp_AIndex
from index cimport cpp_DIndex
from cereal cimport cpp_writeJSONFile, cpp_writeBINARYFile, cpp_readJSONFile, cpp_readBINARYFile
## ============
## Range
## ============
cdef class Range:
cdef shared_ptr[cpp_RangeBase] cpp_range
def size(self):
return self.cpp_range.get().size()
def dim(self):
return self.cpp_range.get().dim()
def sub(self):
return getSubRange(self)
def index(self):
return getRangeIndex(self)
cdef class RangeFactory:
cdef shared_ptr[cpp_RangeFactoryBase] cpp_rfactory
def __cinit__(self,rangetype,**kvargs):
cdef size_t size = 0
if rangetype == 'C':
size = kvargs['size']
self.cpp_rfactory = dynamic_pointer_cast[cpp_RangeFactoryBase,cpp_CRangeFactory](
make_shared[cpp_CRangeFactory](size))
else:
raise Exception('unknown range type:'+ rangetype)
def create(self):
r = Range()
r.cpp_range = self.cpp_rfactory.get().create()
return r
## ===========
## Index
## ===========
cdef class Index:
def __iter__(self):
return self
def __next__(self):
return self
def lex(self):
return 0
def dim(self):
return 0
def stringMeta(self):
return ''
cdef class DIndex (Index):
cdef shared_ptr[cpp_DIndex] cpp_index
cdef bool itercall
def __cinit__(self,_range,_lexpos=0):
cdef Range r = _range
cdef size_t l = _lexpos
self.cpp_index = make_shared[cpp_DIndex] (r.cpp_range,l)
self.itercall = False
def __iter__(self):
self.cpp_index.get().setlpos(0)
self.itercall = True # otherwise first (i.e. zeroth) will be excluded
return self
def __next__(self):
cdef DIndex ret = self
if self.itercall:
ret.itercall = False
return ret
if self.lex() < self.cpp_index.get().range().get().size()-1:
ret.cpp_index = make_shared[cpp_DIndex] (self.cpp_index.get().plus(1))
return ret
else:
raise StopIteration
def lex(self):
return self.cpp_index.get().lex()
def dim(self):
return self.cpp_index.get().dim()
def stringMeta(self):
return self.cpp_index.get().stringMeta()
def getRangeIndex(_range):
return DIndex(_range)
## ===========
## Array
## ===========
cdef class Array:
def size(self):
return 0
def range(self):
cdef Range r = Range()
return r
cdef class Array_Double (Array):
cdef shared_ptr[cpp_CArrayBase[double]] cpp_array
def __cinit__(self,_range=None):
cdef Range r
if not _range is None:
r = _range
self.cpp_array = dynamic_pointer_cast[cpp_CArrayBase[double],cpp_MArray[double]] (make_shared[cpp_MArray[double]] (r.cpp_range) )
def size(self):
return self.cpp_array.get().size()
def range(self):
cdef Range r = Range()
r.cpp_range = self.cpp_array.get().range()
return r
def index(self):
return AIndex_Double(self)
cdef class Array_Range (Array):
cdef shared_ptr[cpp_CArrayBase[shared_ptr[cpp_RangeBase]]] cpp_array
def __cinit__(self,_range=None):
cdef Range r
if not _range is None:
r = _range
self.cpp_array = dynamic_pointer_cast[cpp_CArrayBase[shared_ptr[cpp_RangeBase]],cpp_MArray[shared_ptr[cpp_RangeBase]]] (make_shared[cpp_MArray[shared_ptr[cpp_RangeBase]]] (r.cpp_range) )
def size(self):
return self.cpp_array.get().size()
def range(self):
cdef Range r = Range()
r.cpp_range = self.cpp_array.get().range()
return r
def index(self):
return AIndex_Range(self)
def getSubRange(_range):
cdef Range r = _range
cdef Array_Range a = Array_Range()
a.cpp_array = dynamic_pointer_cast[cpp_CArrayBase[shared_ptr[cpp_RangeBase]],cpp_MArray[shared_ptr[cpp_RangeBase]]] (make_shared[cpp_MArray[shared_ptr[cpp_RangeBase]]] (r.cpp_range.get().sub()) )
return a
def writeFile(_fname,_array,_format):
cdef Array_Double a = _array
cdef shared_ptr[cpp_MArray[double]] ap = dynamic_pointer_cast[cpp_MArray[double],cpp_CArrayBase[double]](a.cpp_array)
if _format.upper() == "JSON":
cpp_writeJSONFile[double](_fname, deref(ap.get()))
elif _format.upper() == "BINARY":
cpp_writeBINARYFile[double](_fname, deref(ap.get()))
else:
raise Exception("unknown array file format '{}'".format(_format))
def readFile(_fname,_format):
cdef Array_Double a = Array_Double()
cdef shared_ptr[cpp_MArray[double]] ap = make_shared[cpp_MArray[double]]()
a.cpp_array = dynamic_pointer_cast[cpp_CArrayBase[double],cpp_MArray[double]](ap)
if _format.upper() == "JSON":
cpp_readJSONFile[double](_fname, deref(ap.get()))
elif _format.upper() == "BINARY":
cpp_readBINARYFile[double](_fname, deref(ap.get()))
else:
raise Exception("unknown array file format '{}'".format(_format))
return a
cdef class AIndex_Double (Index):
cdef shared_ptr[cpp_CArrayBase[double]] cpp_array # keep the instance alive
cdef shared_ptr[cpp_AIndex[double]] cpp_index
cdef bool itercall
def __cinit__(self,_array,_lexpos=0):
cdef size_t l = _lexpos
cdef Array_Double a = _array
self.cpp_array = a.cpp_array
self.cpp_index = make_shared[cpp_AIndex[double]] (a.cpp_array.get().begin().A_plus(l))
self.itercall = False
def __iter__(self):
self.cpp_index.get().setlpos(0)
self.itercall = True # otherwise first (i.e. zeroth) will be excluded
return self
def __next__(self):
cdef AIndex_Double ret = self
if self.itercall:
ret.itercall = False
return ret
if self.lex() < self.cpp_index.get().range().get().size()-1:
ret.cpp_index = make_shared[cpp_AIndex[double]] (self.cpp_index.get().A_plus(1))
return ret
else:
raise StopIteration
def lex(self):
return self.cpp_index.get().lex()
def dim(self):
return self.cpp_index.get().dim()
def stringMeta(self):
return self.cpp_index.get().stringMeta()
def get(self):
return self.cpp_index.get().A_get()
cdef class AIndex_Range (Index):
cdef shared_ptr[cpp_CArrayBase[shared_ptr[cpp_RangeBase]]] cpp_array # keep the instance alive
cdef shared_ptr[cpp_AIndex[shared_ptr[cpp_RangeBase]]] cpp_index
cdef bool itercall
def __cinit__(self,_array,_lexpos=0):
cdef size_t l = _lexpos
cdef Array_Range a = _array
self.cpp_array = a.cpp_array
self.cpp_index = make_shared[cpp_AIndex[shared_ptr[cpp_RangeBase]]] (a.cpp_array.get().begin().A_plus(l))
self.itercall = False
def __iter__(self):
self.cpp_index.get().setlpos(0)
self.itercall = True # otherwise first (i.e. zeroth) will be excluded
return self
def __next__(self):
cdef AIndex_Range ret = self
if self.itercall:
ret.itercall = False
return ret
if self.lex() < self.cpp_index.get().range().get().size()-1:
ret.cpp_index = make_shared[cpp_AIndex[shared_ptr[cpp_RangeBase]]] (self.cpp_index.get().A_plus(1))
return ret
else:
raise StopIteration
def lex(self):
return self.cpp_index.get().lex()
def dim(self):
return self.cpp_index.get().dim()
def stringMeta(self):
return self.cpp_index.get().stringMeta()
def get(self):
cdef Range r = Range()
r.cpp_range = self.cpp_index.get().A_get()
return r

View file

@ -1,6 +1,11 @@
#ifndef __python_cnorxz_array_wrapper_h__
#define __python_cnorxz_array_wrapper_h__
#include <Python.h> #include <Python.h>
#include "cnorxz.h" #include "cnorxz.h"
#include "cereal/cnorxz_cereal.h"
#include "numpy/ndarraytypes.h"
namespace CNORXZ namespace CNORXZ
{ {
@ -8,32 +13,118 @@ namespace CNORXZ
class CArrayWrapperBase class CArrayWrapperBase
{ {
public: public:
DEFAULT_MEMBERS(ArrayWrapperBase); DEFAULT_MEMBERS(CArrayWrapperBase);
virtual ~CArrayWrapperBase() = default; virtual ~CArrayWrapperBase() = default;
virtual RangePtr range() const = 0; virtual RangePtr range() const = 0;
virtual SizeT size() const = 0; virtual SizeT size() const = 0;
// virtual PyObject* get() const = 0; // operator[]!! // virtual PyObject* get() const = 0; // operator[]!!
#ifdef HAVE_CEREAL
virtual void writeFile(cer::Format f, const String& fname) const = 0;
virtual void readFile(cer::Format f, const String& fname) const = 0;
#endif
virtual int typenum() const = 0;
virtual const void* data() const = 0;
virtual SizeT datasize() const = 0;
};
class ArrayWrapperBase : public CArrayWrapperBase
{
public:
virtual void* data() = 0;
}; };
template <typename T> template <typename T>
class CArrayWrapper : public CArrayWrapperBase struct Typenum
{
static const int value = NPY_NOTYPE;
};
template <>
struct Typenum<Double>
{
static const int value = NPY_DOUBLE;
};
template <>
struct Typenum<Int>
{
static const int value = NPY_INT32;
};
template <>
struct Typenum<LInt>
{
static const int value = NPY_INT64;
};
template <>
struct Typenum<SizeT>
{
static const int value = NPY_UINT64;
};
template <typename T>
class ArrayWrapper : public ArrayWrapperBase
{ {
private: private:
Sptr<CArrayBase<T>> mArr; Sptr<ArrayBase<T>> mArr;
public: public:
DEFAULT_MEMBERS(ArrayWrapper); ArrayWrapper() : mArr( std::make_shared<MArray<T>>() ) {}
CArrayWrapper(const RangePtr& r) : mArr( std::make_shared<MArray<T>>(r) ) {} ArrayWrapper(const RangePtr& r) : mArr( std::make_shared<MArray<T>>(r) ) {}
ArrayWrapper(const Sptr<ArrayBase<T>>& arr) : mArr(arr) {}
virtual RangePtr range() const override final { return mArr->range(); } virtual RangePtr range() const override final { return mArr->range(); }
virtual SizeT size() const override final { return mArr->size(); } virtual SizeT size() const override final { return mArr->size(); }
#ifdef HAVE_CEREAL
virtual void writeFile(cer::Format f, const String& fname) const override final
{
auto a = std::dynamic_pointer_cast<MArray<T>>( mArr );
if(a){
if(f == cer::Format::XML) { cer::writeXMLFile(fname, *a); }
else if(f == cer::Format::JSON) { cer::writeJSONFile(fname, *a); }
else { cer::writeBINARYFile(fname, *a); }
}
}
virtual void readFile(cer::Format f, const String& fname) const override final
{
auto a = std::dynamic_pointer_cast<MArray<T>>( mArr );
if(a){
if(f == cer::Format::XML) { cer::readXMLFile(fname, *a); }
else if(f == cer::Format::JSON) { cer::readJSONFile(fname, *a); }
else { cer::readBINARYFile(fname, *a); }
}
}
#endif
virtual int typenum() const override final { return Typenum<T>::value; }
virtual const void* data() const override final
{ return reinterpret_cast<const void*>( mArr->data() ); }
virtual void* data() override final
{ return reinterpret_cast<void*>( mArr->data() ); }
virtual SizeT datasize() const override final { return size() * sizeof(T); }
}; };
} }
struct PyCArrayB struct PyCxArrayB
{ {
PyObject_HEAD PyObject_HEAD
CNORXZ::CArrayWrapperBase* ptrObj; CNORXZ::CArrayWrapperBase* ptrObj;
}; };
int PyCxArrayB_init(PyCxArrayB* self, PyObject* args, PyObject* kwds);
void PyCxArrayB_dealloc(PyCxArrayB* self);
PyObject* PyCxArrayB_size(PyCxArrayB* self);
PyObject* PyCxArrayB_range(PyCxArrayB* self);
PyObject* PyCxArrayB_writeFile(PyCxArrayB* self, PyObject* args, PyObject* kwds);
PyObject* PyCxArrayB_readFile(PyCxArrayB* self, PyObject* args, PyObject* kwds);
PyTypeObject* PyCxArrayBType_init();
PyObject* PyCxReadFile(PyObject* self, PyObject* args, PyObject* kwds);
extern PyMethodDef PyCxArrayB_methods[];
extern PyTypeObject PyCxArrayBType;
#endif

View file

@ -0,0 +1,46 @@
#ifndef __python_cnorxz_range_wrapper_h__
#define __python_cnorxz_range_wrapper_h__
#include <Python.h>
#include "cnorxz.h"
namespace CNORXZ
{
class RangeWrapper
{
public:
DEFAULT_MEMBERS(RangeWrapper);
RangeWrapper(const RangePtr r) : mR(r) {}
inline bool _init() const { return mR != nullptr; }
inline SizeT size() const { return mR->size(); }
inline SizeT dim() const { return mR->dim(); }
inline RangePtr sub(SizeT pos) { return mR->sub(pos); }
inline String stringMeta(SizeT pos) const { return mR->stringMeta(pos); }
inline MArray<RangePtr> sub() const { return mR->sub(); }
inline RangePtr sub(SizeT pos) const { return mR->sub(pos); }
private:
RangePtr mR;
};
}
struct PyCxRange
{
PyObject_HEAD
CNORXZ::RangeWrapper* ptrObj;
};
int PyCxRange_init(PyCxRange* self, PyObject* args, PyObject* kwds);
void PyCxRange_dealloc(PyCxRange* self);
PyObject* PyCxRange_size(PyCxRange* self);
PyObject* PyCxRange_dim(PyCxRange* self);
PyObject* PyCxRange_sub(PyCxRange* self, PyObject* args, PyObject* kwds);
PyObject* PyCxRange_stringMeta(PyCxRange* self, PyObject* args, PyObject* kwds);
PyObject* PyCxRange_sub(PyCxRange* self, PyObject* args, PyObject* kwds);
PyTypeObject* PyCxRangeType_init();
extern PyMethodDef PyCxRange_methods[];
extern PyTypeObject PyCxRangeType;
#endif

View file

@ -1,44 +0,0 @@
from libcpp.memory cimport shared_ptr
from libcpp.string cimport string
from range cimport cpp_RangeBase
cdef extern from "ranges/ranges.h" namespace "CNORXZ":
cdef cppclass cpp_DIndex "CNORXZ::DIndex":
cpp_DIndex() except+
cpp_DIndex(const cpp_DIndex&) except+
cpp_DIndex(const shared_ptr[cpp_RangeBase]&, size_t lexpos) except+
cpp_DIndex setlpos "operator=" (size_t n) except+
cpp_DIndex setincr "operator++"() except+
cpp_DIndex setdecr "operator--"() except+
cpp_DIndex plus "operator+"(int n) except+
cpp_DIndex minus "operator-"(int n) except+
size_t lex() except+
size_t dim() except+
shared_ptr[cpp_RangeBase] range() except+
string stringMeta() except+
cdef extern from "ranges/ranges.h" namespace "CNORXZ":
cdef cppclass cpp_YIndex "CNORXZ::YIndex":
cpp_YIndex() except+
cpp_YIndex(const cpp_YIndex&) except+
cpp_YIndex(const shared_ptr[cpp_RangeBase]&, size_t lexpos) except+
cpp_YIndex setlpos "operator=" (size_t n) except+
cpp_YIndex setincr "operator++"() except+
cpp_YIndex setdecr "operator--"() except+
cpp_YIndex plus "operator+"(int n) except+
cpp_YIndex minus "operator-"(int n) except+
size_t lex() except+
size_t dim() except+
shared_ptr[cpp_RangeBase] range() except+
string stringMeta() except+

View file

@ -1,46 +1,185 @@
#include "cnorxz/core/include/array_wrapper.h" #include "array_wrapper.h"
#include "range_wrapper.h"
#include "numpy/arrayobject.h"
using namespace CNORXZ using namespace CNORXZ;
using namespace CNORXZ::cer;
static int PyCArrayB_init(CArrayWrapperBase* self, PyObject* args, PyObject* kwds) int PyCxArrayB_init(PyCxArrayB* self, PyObject* args, PyObject* kwds)
{ {
static char* kwlist[] = { "type", "extension" , NULL }; static char* kwlist[] = { "type", "extension" , NULL };
SizeT ext = 0; SizeT ext = 0;
const char* type; char* type = NULL;
if(not PyArg_ParseTupleAndKeywords(args, kwds, "s|k", kwlist, &type, &ext)){ if(not PyArg_ParseTupleAndKeywords(args, kwds, "|sk", kwlist, &type, &ext)){
return NULL; return -1;
} }
if(ext != 0){ if(ext != 0){
RangePtr r = CRangeFactory(ext).create(); RangePtr r = CRangeFactory(ext).create();
self->ptrObj = new CArrayBase<T>(r); // TODO: different types!!!
self->ptrObj = new ArrayWrapper<Double>(r);
} }
else { else {
self->ptrObj = new CArrayBase<T>(); self->ptrObj = new ArrayWrapper<Double>();
} }
return 0; return 0;
} }
static void PyCArrayB_dealloc(CArrayWrapperBase* self) void PyCxArrayB_dealloc(PyCxArrayB* self)
{ {
delete self->ptrObject; delete self->ptrObj;
Py_TYPE(self)->tp_free(self); Py_TYPE(self)->tp_free(self);
} }
static PyObject* PyCArrayB_size(CArrayWrapperBase* self) PyObject* PyCxArrayB_size(PyCxArrayB* self)
{ {
if(not self->ptrObj->range()){ if(not self->ptrObj->range()){
PyErr_SetString(PyExc_RuntimeError, "array not initialized"); PyErr_SetString(PyExc_RuntimeError, "array not initialized");
return NULL; return NULL;
} }
const SizeT retval = self->ptrObj->size(); const SizeT retval = self->ptrObj->size();
return Py_BuildValue("k",retval); return Py_BuildValue("k", retval);
} }
static PyMethodDef PyCArrayB_methods[] = { PyObject* PyCxArrayB_range(PyCxArrayB* self)
{ "size", (PyCFunction)PyCArrayB_size, METH_VARARGS, "return size of the array" }, {
{ NULL } if(not self->ptrObj->range()){
PyErr_SetString(PyExc_RuntimeError, "array not initialized");
return NULL;
}
const RangePtr r = self->ptrObj->range();
PyCxRange* o;
o = PyObject_New(PyCxRange, &PyCxRangeType);
o->ptrObj = new RangeWrapper(r);
return Py_BuildValue("O", o);
}
Format formatFromString(const char* fstr)
{
Format f = Format::BINARY;
if(fstr != NULL){
if(strcmp(fstr,"binary") == 0){
f = Format::BINARY;
}
else if(strcmp(fstr,"json") == 0){
f = Format::JSON;
}
else if(strcmp(fstr,"xml") == 0){
f = Format::XML;
}
else {
PyErr_SetString(PyExc_RuntimeError, "unknown format");
}
}
return f;
}
#ifdef HAVE_CEREAL
PyObject* PyCxArrayB_writeFile(PyCxArrayB* self, PyObject* args, PyObject* kwds)
{
if(not self->ptrObj->range()){
PyErr_SetString(PyExc_RuntimeError, "array not initialized");
}
static char* kwlist[] = { "format", "filename" , NULL };
char* fname = NULL;
char* format = NULL;
if(not PyArg_ParseTupleAndKeywords(args, kwds, "ss|", kwlist, &fname, &format)){
return NULL;
}
const String fn(fname);
const Format f = formatFromString(format);
self->ptrObj->writeFile(f, fn);
Py_RETURN_NONE;
}
PyObject* PyCxArrayB_readFile(PyCxArrayB* self, PyObject* args, PyObject* kwds)
{
static char* kwlist[] = { "format", "filename" , NULL };
char* fname = NULL;
char* format = NULL;
if(not PyArg_ParseTupleAndKeywords(args, kwds, "ss|", kwlist, &fname, &format)){
return NULL;
}
const String fn(fname);
const Format f = formatFromString(format);
self->ptrObj->readFile(f, fn);
Py_RETURN_NONE;
}
#endif
PyObject* PyCxArrayB_npa(PyCxArrayB* self)
{
// return viewing (!) numpy array
if(not self->ptrObj->range()){
PyErr_SetString(PyExc_RuntimeError, "array not initialized");
return NULL;
}
const SizeT d = self->ptrObj->range()->dim();
std::vector<npy_intp> dims(d);
for(SizeT i = 0; i != dims.size(); ++i){
dims[i] = self->ptrObj->range()->sub(i)->size();
}
// TODO: Do the following for mutable arrays!!!
/*
Py_INCREF(self); // keep data alive
PyObject* o = PyArray_SimpleNewFromData
( static_cast<int>( d ) , dims.data(), self->ptrObj->typenum(), self->ptrObj->data() );
PyArray_BASE(o) = (PyObject*) self;
*/
PyObject* o = PyArray_SimpleNew
( static_cast<int>( d ) , dims.data(), self->ptrObj->typenum() );
void* data = PyArray_DATA(o);
//const npy_intp s = PyArray_NBYTES(o);
const SizeT s = static_cast<SizeT>( PyArray_NBYTES(o) );
if(s != self->ptrObj->datasize()) {
PyErr_Format(PyExc_RuntimeError, "lib error %d vs %d", s, self->ptrObj->datasize());
//PyErr_SetString(PyExc_RuntimeError, "lib error");
return NULL;
}
memcpy( data, self->ptrObj->data(), self->ptrObj->datasize() );
return o;
}
PyMethodDef PyCxArrayB_methods[] = {
{ "size", (PyCFunction) PyCxArrayB_size, METH_VARARGS| METH_KEYWORDS, "return size of the array" },
{ "range", (PyCFunction) PyCxArrayB_range, METH_VARARGS| METH_KEYWORDS, "return array range" },
{ "writeFile", (PyCFunction) PyCxArrayB_writeFile, METH_VARARGS| METH_KEYWORDS, "write array to file" },
{ "readFile", (PyCFunction) PyCxArrayB_readFile, METH_VARARGS| METH_KEYWORDS, "read array from file" },
{ "npa", (PyCFunction) PyCxArrayB_npa, METH_VARARGS| METH_KEYWORDS, "return numpy array (view)" },
{ NULL, NULL, 0, NULL }
}; };
PyTypeObject PyCxArrayBType = { PyVarObject_HEAD_INIT(NULL,0) "cnorxz.Array" };
PyTypeObject* PyCxArrayBType_init()
{
PyCxArrayBType.tp_new = PyType_GenericNew;
PyCxArrayBType.tp_basicsize = sizeof(PyCxArrayB);
PyCxArrayBType.tp_dealloc = (destructor) PyCxArrayB_dealloc;
PyCxArrayBType.tp_flags = Py_TPFLAGS_DEFAULT;
PyCxArrayBType.tp_doc = "cnorxz Array wrapper";
PyCxArrayBType.tp_methods = PyCxArrayB_methods;
PyCxArrayBType.tp_init = (initproc) PyCxArrayB_init;
import_array();
if(PyType_Ready(&PyCxArrayBType) < 0) {
return NULL;
}
else {
return &PyCxArrayBType;
}
}
PyObject* PyCxReadFile(PyObject* self, PyObject* args, PyObject* kwds)
{
PyCxArrayB* out = (PyCxArrayB*) PyObject_NEW(PyCxArrayB, &PyCxArrayBType);
out->ptrObj = new ArrayWrapper<Double>();
PyCxArrayB_readFile(out,args,kwds);
return Py_BuildValue("O", out);;
}

View file

@ -0,0 +1,106 @@
#include "array_wrapper.h"
#include "range_wrapper.h"
using namespace CNORXZ;
int PyCxRange_init(PyCxRange* self, PyObject* args, PyObject* kwds)
{
//!!!
return 0;
}
void PyCxRange_dealloc(PyCxRange* self)
{
delete self->ptrObj;
Py_TYPE(self)->tp_free(self);
}
PyObject* PyCxRange_size(PyCxRange* self)
{
if(not self->ptrObj->_init()){
const SizeT retval = 0;
return Py_BuildValue("k", retval);
}
const SizeT retval = self->ptrObj->size();
return Py_BuildValue("k", retval);
}
PyObject* PyCxRange_dim(PyCxRange* self)
{
if(not self->ptrObj->_init()){
const SizeT retval = 0;
return Py_BuildValue("k", retval);
}
const SizeT retval = self->ptrObj->dim();
return Py_BuildValue("k", retval);
}
PyObject* PyCxRange_sub(PyCxRange* self, PyObject* args, PyObject* kwds)
{
static char* kwlist[] = { "pos", NULL };
SizeT pos = 0;
if(not PyArg_ParseTupleAndKeywords(args, kwds, "k|", kwlist, &pos)){
return NULL;
}
SizeT dim = self->ptrObj->dim();
if(pos >= dim){
return PyErr_Format(PyExc_RuntimeError, "requested sub-range position (%d) exceeds range dimension (%d)", pos, dim);
}
// entire set of sub-ranges:
/*
PyCxArrayB* o;
o = PyObject_New(PyCxArrayB, &PyCxArrayBType);
o->ptrObj = new ArrayWrapper<RangePtr>( std::make_shared<MArray<RangePtr>>(self->ptrObj->sub()) );
return Py_BuildValue("O", o);
*/
const RangePtr r = self->ptrObj->sub(pos);
PyCxRange* o = PyObject_New(PyCxRange, &PyCxRangeType);
o->ptrObj = new RangeWrapper(r);
return Py_BuildValue("O", o);
}
PyObject* PyCxRange_stringMeta(PyCxRange* self, PyObject* args, PyObject* kwds)
{
const SizeT size = self->ptrObj->size();
PyObject* out = PyList_New(size);
for(SizeT i = 0; i != size; ++i){
PyObject* s = Py_BuildValue("s", self->ptrObj->stringMeta(i).c_str() );
PyList_SetItem(out, i, s);
}
return out;
}
PyMethodDef PyCxRange_methods[] = {
{ "size", (PyCFunction) PyCxRange_size, METH_VARARGS, "return range size" },
{ "dim", (PyCFunction) PyCxRange_dim, METH_VARARGS, "return range dimension" },
{ "sub", (PyCFunction) PyCxRange_sub, METH_VARARGS|METH_KEYWORDS, "return sub-range for given dimension" },
{ "stringMeta", (PyCFunction) PyCxRange_stringMeta, METH_VARARGS,
"return string meta data for given range position" },
{ NULL }
};
PyTypeObject PyCxRangeType = { PyVarObject_HEAD_INIT(NULL,0) "cnorxz.Range" };
PyTypeObject* PyCxRangeType_init()
{
PyCxRangeType.tp_new = PyType_GenericNew;
PyCxRangeType.tp_basicsize = sizeof(PyCxRange);
PyCxRangeType.tp_dealloc = (destructor) PyCxRange_dealloc;
PyCxRangeType.tp_flags = Py_TPFLAGS_DEFAULT;
PyCxRangeType.tp_doc = "cnorxz Range wrapper";
PyCxRangeType.tp_methods = PyCxRange_methods;
PyCxRangeType.tp_init = (initproc) PyCxRange_init;
if(PyType_Ready(&PyCxRangeType) < 0){
return NULL;
}
else {
return &PyCxRangeType;
}
}

View file

@ -1,11 +0,0 @@
from libcpp.memory cimport shared_ptr
from array cimport cpp_MArray
from range cimport cpp_RangeBase
cdef extern from "ranges/ranges.h" namespace "CNORXZ":
cdef cppclass cpp_RangeBase "CNORXZ::RangeBase":
size_t size() except +
size_t dim() except +
cpp_MArray[shared_ptr[cpp_RangeBase]] sub() except+

View file

@ -1,12 +0,0 @@
from libcpp.memory cimport shared_ptr
from range cimport cpp_RangeBase
cdef extern from "ranges/ranges.h" namespace "CNORXZ":
cdef cppclass cpp_RangeFactoryBase "CNORXZ::RangeFactoryBase":
shared_ptr[cpp_RangeBase] create() except +
cdef extern from "ranges/ranges.h" namespace "CNORXZ":
cdef cppclass cpp_CRangeFactory "CNORXZ::CRangeFactory" (cpp_RangeFactoryBase):
cpp_CRangeFactory(size_t size) except +
shared_ptr[cpp_RangeBase] create() except +

View file

@ -1,41 +1,57 @@
#!/usr/bin/env python #!/usr/bin/env python
import Cython.Build # imports:
import setuptools import setuptools
from distutils.core import setup, Extension
import os
import sysconfig import sysconfig
import subprocess import subprocess
# basic variables:
libname = "cnorxz" libname = "cnorxz"
author = "Christian Zimmermann" author = "Christian Zimmermann"
author_email = "chizeta@f3l.de" author_email = "chizeta@f3l.de"
path_to_cnorxz = "/home/chizeta/repos/cnorxz/install" path_to_cnorxz = ""
expected_cnorxz_version = "1.0.0" # dummy for now; in the future this is supposed to be the c++ version which is guaranteed to be compatible with py cnorxz if 'CNORXZ' in os.environ:
path_to_cnorxz = os.environ['CNORXZ']
version = "0.0.0"
have_numpy = True
git_hash = subprocess.run(['git','rev-parse','HEAD'],stdout=subprocess.PIPE).stdout.decode('ascii')[:-1] # flags:
git_tags = subprocess.run(['git', 'tag', '-l', '--sort=refname', 'v*'],stdout=subprocess.PIPE).stdout.decode('ascii').split()
cnorxz_version = subprocess.run([path_to_cnorxz+"/bin/cnorxz-config",'--version'],stdout=subprocess.PIPE).stdout.decode('ascii')[:-1]
assert len(git_tags) != 0, "no version tags found" config_bin = path_to_cnorxz+"/bin/cnorxz-config"
git_tag = git_tags[-1] extra_compile_args = sysconfig.get_config_var('CFLAGS').split()
version = git_tag[1:] + 'dev' cnorxz_version = subprocess.run([config_bin,'--version'],stdout=subprocess.PIPE).stdout.decode('ascii')[:-1]
git_hash_tag = subprocess.run(['git','rev-list','-n','1',git_tag],stdout=subprocess.PIPE).stdout.decode('ascii')[:-1] cnorxz_flags = subprocess.run([config_bin,'--flags'],stdout=subprocess.PIPE).stdout.decode('ascii').split()
if git_hash_tag == git_hash and expected_cnorxz_version != cnorxz_version: cnorxz_definitions = subprocess.run([config_bin,'--definitions'],stdout=subprocess.PIPE).stdout.decode('ascii').split()
version = git_tag[1:] cnorxz_flags.remove("-Werror")
cnorxz_flags.append("-Wno-write-strings")
extra_compile_args += cnorxz_flags
# includes:
inc_dirs = list() inc_dirs = list()
if path_to_cnorxz != "": if path_to_cnorxz != "":
inc_dirs.append( path_to_cnorxz + "/include/cnorxz" ) inc_dirs.append( path_to_cnorxz + "/include/cnorxz" )
inc_dirs.append( "cnorxz/core/include" )
# library dirs:
lib_dirs = list() lib_dirs = list()
lib_dirs.append( "/usr/lib" ) lib_dirs.append( "/usr/lib" )
lib_dirs.append( "/usr/local/lib" ) lib_dirs.append( "/usr/local/lib" )
if path_to_cnorxz != "": if path_to_cnorxz != "":
inc_dirs.append( path_to_cnorxz + "/lib" ) lib_dirs.append( path_to_cnorxz + "/lib" )
lib_dirs.append( "/home/chizeta/repos/cnorxz/install/lib" )
extra_compile_args = sysconfig.get_config_var('CFLAGS').split() # optional dependencies:
cnorxz_flags = subprocess.run([path_to_cnorxz+"/bin/cnorxz-config",'--flags'],stdout=subprocess.PIPE).stdout.decode('ascii').split()
extra_compile_args += cnorxz_flags if have_numpy:
import numpy
inc_dirs.append( numpy.get_include() )
# main
default_extension_args = dict( default_extension_args = dict(
language = "c++", language = "c++",
@ -43,6 +59,7 @@ default_extension_args = dict(
libraries = [libname], libraries = [libname],
library_dirs = lib_dirs, library_dirs = lib_dirs,
extra_compile_args = extra_compile_args, extra_compile_args = extra_compile_args,
define_macros = [(mac,None) for mac in cnorxz_definitions]
) )
if __name__ == "__main__": if __name__ == "__main__":
@ -53,25 +70,15 @@ if __name__ == "__main__":
for d in lib_dirs: for d in lib_dirs:
print("\t",d) print("\t",d)
extensions = list() setup(
extensions.append(
setuptools.Extension(
name = libname + ".core",
sources = [
"cnorxz/core/core.pyx",
],
define_macros=[('HAVE_CEREAL',None)],
**default_extension_args
)
)
# append further extensions (cereal, hdf5, mpi ...) here
setuptools.setup(
name = libname, name = libname,
packages = setuptools.find_packages(), packages = setuptools.find_packages(),
version = version, version = version,
include_dirs = inc_dirs, include_dirs = inc_dirs,
ext_modules = Cython.Build.cythonize(extensions), ext_modules = [Extension(
'cnorxz', ['cnorxz/core/core.cpp','cnorxz/core/lib/array_wrapper.cpp','cnorxz/core/lib/range_wrapper.cpp'],
**default_extension_args
)],
author = author, author = author,
author_email = author_email, author_email = author_email,
) )