36 #ifndef VIGRA_NUMPY_ARRAY_TRAITS_HXX
37 #define VIGRA_NUMPY_ARRAY_TRAITS_HXX
39 #include "numerictraits.hxx"
40 #include "multi_array.hxx"
41 #include "numpy_array_taggedshape.hxx"
65 struct NumericTraits<Singleband<T> >
66 :
public NumericTraits<T>
70 struct NumericTraits<Multiband<T> >
72 typedef Multiband<T> Type;
79 typedef Type ValueType;
81 typedef typename NumericTraits<T>::isIntegral isIntegral;
82 typedef VigraFalseType isScalar;
83 typedef typename NumericTraits<T>::isSigned isSigned;
84 typedef typename NumericTraits<T>::isSigned isOrdered;
85 typedef typename NumericTraits<T>::isSigned isComplex;
123 template<
class ValueType>
124 struct ERROR_NumpyArrayValuetypeTraits_not_specialized_for_ { };
126 template<
class ValueType>
127 struct NumpyArrayValuetypeTraits
129 static bool isValuetypeCompatible(PyArrayObject
const * obj)
131 return ERROR_NumpyArrayValuetypeTraits_not_specialized_for_<ValueType>();
134 static ERROR_NumpyArrayValuetypeTraits_not_specialized_for_<ValueType> typeCode;
136 static std::string typeName()
138 return std::string(
"ERROR: NumpyArrayValuetypeTraits not specialized for this case");
141 static std::string typeNameImpex()
143 return std::string(
"ERROR: NumpyArrayValuetypeTraits not specialized for this case");
146 static PyObject * typeObject()
148 return (PyObject *)0;
152 template<
class ValueType>
153 ERROR_NumpyArrayValuetypeTraits_not_specialized_for_<ValueType> NumpyArrayValuetypeTraits<ValueType>::typeCode;
155 #define VIGRA_NUMPY_VALUETYPE_TRAITS(type, typeID, numpyTypeName, impexTypeName) \
157 struct NumpyArrayValuetypeTraits<type > \
159 static bool isValuetypeCompatible(PyArrayObject const * obj) \
161 return PyArray_EquivTypenums(typeID, PyArray_DESCR((PyObject *)obj)->type_num) && \
162 PyArray_ITEMSIZE((PyObject *)obj) == sizeof(type); \
165 static NPY_TYPES const typeCode = typeID; \
167 static std::string typeName() \
169 return #numpyTypeName; \
172 static std::string typeNameImpex() \
174 return impexTypeName; \
177 static PyObject * typeObject() \
179 return PyArray_TypeObjectFromType(typeID); \
183 VIGRA_NUMPY_VALUETYPE_TRAITS(
bool, NPY_BOOL,
bool,
"UINT8")
184 VIGRA_NUMPY_VALUETYPE_TRAITS(
signed char, NPY_INT8, int8, "INT16")
185 VIGRA_NUMPY_VALUETYPE_TRAITS(
unsigned char, NPY_UINT8, uint8, "UINT8")
186 VIGRA_NUMPY_VALUETYPE_TRAITS(
short, NPY_INT16, int16, "INT16")
187 VIGRA_NUMPY_VALUETYPE_TRAITS(
unsigned short, NPY_UINT16, uint16, "UINT16")
189 #if VIGRA_BITSOF_LONG == 32
190 VIGRA_NUMPY_VALUETYPE_TRAITS(
long, NPY_INT32, int32,
"INT32")
191 VIGRA_NUMPY_VALUETYPE_TRAITS(
unsigned long, NPY_UINT32, uint32, "UINT32")
192 #elif VIGRA_BITSOF_LONG == 64
193 VIGRA_NUMPY_VALUETYPE_TRAITS(
long, NPY_INT64, int64,
"DOUBLE")
194 VIGRA_NUMPY_VALUETYPE_TRAITS(
unsigned long, NPY_UINT64, uint64, "DOUBLE")
197 #if VIGRA_BITSOF_INT == 32
198 VIGRA_NUMPY_VALUETYPE_TRAITS(
int, NPY_INT32, int32,
"INT32")
199 VIGRA_NUMPY_VALUETYPE_TRAITS(
unsigned int, NPY_UINT32, uint32, "UINT32")
200 #elif VIGRA_BITSOF_INT == 64
201 VIGRA_NUMPY_VALUETYPE_TRAITS(
int, NPY_INT64, int64,
"DOUBLE")
202 VIGRA_NUMPY_VALUETYPE_TRAITS(
unsigned int, NPY_UINT64, uint64, "DOUBLE")
206 # if VIGRA_BITSOF_LONG_LONG == 32
207 VIGRA_NUMPY_VALUETYPE_TRAITS(
long long, NPY_INT32, int32,
"INT32")
208 VIGRA_NUMPY_VALUETYPE_TRAITS(
unsigned long long, NPY_UINT32, uint32, "UINT32")
209 # elif VIGRA_BITSOF_LONG_LONG == 64
210 VIGRA_NUMPY_VALUETYPE_TRAITS(
long long, NPY_INT64, int64,
"DOUBLE")
211 VIGRA_NUMPY_VALUETYPE_TRAITS(
unsigned long long, NPY_UINT64, uint64, "DOUBLE")
215 VIGRA_NUMPY_VALUETYPE_TRAITS(npy_float32, NPY_FLOAT32, float32,
"FLOAT")
216 VIGRA_NUMPY_VALUETYPE_TRAITS(npy_float64, NPY_FLOAT64, float64, "DOUBLE")
217 #if NPY_SIZEOF_LONGDOUBLE != NPY_SIZEOF_DOUBLE
218 VIGRA_NUMPY_VALUETYPE_TRAITS(npy_longdouble, NPY_LONGDOUBLE, longdouble,
"")
220 VIGRA_NUMPY_VALUETYPE_TRAITS(npy_cfloat, NPY_CFLOAT, complex64,
"")
221 VIGRA_NUMPY_VALUETYPE_TRAITS(std::complex<npy_float>, NPY_CFLOAT, complex64, "")
222 VIGRA_NUMPY_VALUETYPE_TRAITS(npy_cdouble, NPY_CDOUBLE, complex128, "")
223 VIGRA_NUMPY_VALUETYPE_TRAITS(std::complex<npy_double>, NPY_CDOUBLE, complex128, "")
224 VIGRA_NUMPY_VALUETYPE_TRAITS(npy_clongdouble, NPY_CLONGDOUBLE, clongdouble, "")
225 #if NPY_SIZEOF_LONGDOUBLE != NPY_SIZEOF_DOUBLE
226 VIGRA_NUMPY_VALUETYPE_TRAITS(std::complex<npy_longdouble>, NPY_CLONGDOUBLE, clongdouble,
"")
229 #undef VIGRA_NUMPY_VALUETYPE_TRAITS
237 template<
unsigned int N,
class T,
class Str
ide>
238 struct NumpyArrayTraits;
242 template<
unsigned int N,
class T>
243 struct NumpyArrayTraits<N, T, StridedArrayTag>
246 typedef T value_type;
247 typedef NumpyArrayValuetypeTraits<T> ValuetypeTraits;
248 static NPY_TYPES
const typeCode = ValuetypeTraits::typeCode;
250 static bool isArray(PyObject * obj)
252 return obj && PyArray_Check(obj);
255 static bool isValuetypeCompatible(PyArrayObject * obj)
257 return ValuetypeTraits::isValuetypeCompatible(obj);
260 static bool isShapeCompatible(PyArrayObject * array)
262 PyObject * obj = (PyObject *)array;
263 int ndim = PyArray_NDIM(obj);
272 static bool isPropertyCompatible(PyArrayObject * obj)
274 return isShapeCompatible(obj) && isValuetypeCompatible(obj);
280 static TaggedShape taggedShape(TinyVector<U, N>
const & shape, PyAxisTags axistags)
282 return TaggedShape(shape, axistags);
289 static TaggedShape taggedShape(TinyVector<U, N>
const & shape, std::string
const & order =
"")
293 return TaggedShape(shape, PyAxisTags(detail::emptyAxistags(shape.size())));
298 static void finalizeTaggedShape(TaggedShape & tagged_shape)
300 vigra_precondition(tagged_shape.size() == N,
301 "reshapeIfEmpty(): tagged_shape has wrong size.");
309 template <
class ARRAY>
310 static void permuteLikewise(python_ptr array, ARRAY
const & data, ARRAY & res)
312 vigra_precondition((
int)data.size() == N,
313 "NumpyArray::permuteLikewise(): size mismatch.");
315 ArrayVector<npy_intp> permute;
316 detail::getAxisPermutationImpl(permute, array,
"permutationToNormalOrder",
317 AxisInfo::AllAxes,
true);
319 if(permute.size() != 0)
321 applyPermutation(permute.begin(), permute.end(), data.begin(), res.begin());
328 static void permutationToSetupOrder(python_ptr array, ArrayVector<U> & permute)
330 detail::getAxisPermutationImpl(permute, array,
"permutationToNormalOrder",
331 AxisInfo::AllAxes,
true);
333 if(permute.size() == 0)
345 static python_ptr unsafeConstructorFromData(TinyVector<U, N>
const & shape,
346 T *data, TinyVector<U, N>
const & stride)
348 TinyVector<npy_intp, N> npyStride(stride *
sizeof(T));
349 return constructNumpyArrayFromData(shape, npyStride.begin(),
350 ValuetypeTraits::typeCode, data);
356 template<
unsigned int N,
class T>
357 struct NumpyArrayTraits<N, T, UnstridedArrayTag>
358 :
public NumpyArrayTraits<N, T, StridedArrayTag>
360 typedef NumpyArrayTraits<N, T, StridedArrayTag> BaseType;
361 typedef typename BaseType::ValuetypeTraits ValuetypeTraits;
363 static bool isShapeCompatible(PyArrayObject * array)
365 PyObject * obj = (PyObject *)array;
366 int ndim = PyArray_NDIM(obj);
367 long channelIndex = pythonGetAttr(obj,
"channelIndex", ndim);
368 long majorIndex = pythonGetAttr(obj,
"innerNonchannelIndex", ndim);
369 npy_intp * strides = PyArray_STRIDES(obj);
371 if(channelIndex < ndim)
374 return (ndim == N && strides[channelIndex] ==
sizeof(T));
376 else if(majorIndex < ndim)
380 return (ndim == N && strides[majorIndex] ==
sizeof(T));
385 return (ndim == N && strides[0] ==
sizeof(T));
389 static bool isPropertyCompatible(PyArrayObject * obj)
391 return isShapeCompatible(obj) && BaseType::isValuetypeCompatible(obj);
397 template<
unsigned int N,
class T>
398 struct NumpyArrayTraits<N, Singleband<T>, StridedArrayTag>
399 :
public NumpyArrayTraits<N, T, StridedArrayTag>
401 typedef NumpyArrayTraits<N, T, StridedArrayTag> BaseType;
402 typedef typename BaseType::ValuetypeTraits ValuetypeTraits;
404 static bool isShapeCompatible(PyArrayObject * array)
406 PyObject * obj = (PyObject *)array;
407 int ndim = PyArray_NDIM(obj);
408 long channelIndex = pythonGetAttr(obj,
"channelIndex", ndim);
412 if(channelIndex == ndim)
416 return ndim == N+1 && PyArray_DIM(obj, channelIndex) == 1;
419 static bool isPropertyCompatible(PyArrayObject * obj)
421 return isShapeCompatible(obj) && BaseType::isValuetypeCompatible(obj);
425 static TaggedShape taggedShape(TinyVector<U, N>
const & shape, PyAxisTags axistags)
427 return TaggedShape(shape, axistags).setChannelCount(1);
431 static TaggedShape taggedShape(TinyVector<U, N>
const & shape, std::string
const & order =
"")
433 return TaggedShape(shape,
434 PyAxisTags(detail::defaultAxistags(shape.size()+1, order))).setChannelCount(1);
437 static void finalizeTaggedShape(TaggedShape & tagged_shape)
439 if(tagged_shape.axistags.hasChannelAxis())
441 tagged_shape.setChannelCount(1);
442 vigra_precondition(tagged_shape.size() == N+1,
443 "reshapeIfEmpty(): tagged_shape has wrong size.");
447 tagged_shape.setChannelCount(0);
448 vigra_precondition(tagged_shape.size() == N,
449 "reshapeIfEmpty(): tagged_shape has wrong size.");
453 template <
class ARRAY>
454 static void permuteLikewise(python_ptr array, ARRAY
const & data, ARRAY & res)
456 vigra_precondition((
int)data.size() == N,
457 "NumpyArray::permuteLikewise(): size mismatch.");
459 ArrayVector<npy_intp> permute;
460 detail::getAxisPermutationImpl(permute, array,
"permutationToNormalOrder",
461 AxisInfo::NonChannel,
true);
463 if(permute.size() == 0)
469 applyPermutation(permute.begin(), permute.end(), data.begin(), res.begin());
473 static void permutationToSetupOrder(python_ptr array, ArrayVector<U> & permute)
475 detail::getAxisPermutationImpl(permute, array,
"permutationToNormalOrder",
476 AxisInfo::AllAxes,
true);
477 if(permute.size() == 0)
482 else if(permute.size() == N+1)
484 permute.erase(permute.begin());
491 template<
unsigned int N,
class T>
492 struct NumpyArrayTraits<N, Singleband<T>, UnstridedArrayTag>
493 :
public NumpyArrayTraits<N, Singleband<T>, StridedArrayTag>
495 typedef NumpyArrayTraits<N, T, UnstridedArrayTag> UnstridedTraits;
496 typedef NumpyArrayTraits<N, Singleband<T>, StridedArrayTag> BaseType;
497 typedef typename BaseType::ValuetypeTraits ValuetypeTraits;
499 static bool isShapeCompatible(PyArrayObject * array)
501 PyObject * obj = (PyObject *)array;
502 int ndim = PyArray_NDIM(obj);
503 long channelIndex = pythonGetAttr(obj,
"channelIndex", ndim);
504 long majorIndex = pythonGetAttr(obj,
"innerNonchannelIndex", ndim);
505 npy_intp * strides = PyArray_STRIDES(obj);
508 if(majorIndex == ndim)
509 return N == ndim && strides[0] ==
sizeof(T);
513 if(channelIndex == ndim)
514 return N == ndim && strides[majorIndex] ==
sizeof(T);
518 return ndim == N+1 && PyArray_DIM(obj, channelIndex) == 1 &&
519 strides[majorIndex] ==
sizeof(T);
522 static bool isPropertyCompatible(PyArrayObject * obj)
524 return isShapeCompatible(obj) && BaseType::isValuetypeCompatible(obj);
530 template<
unsigned int N,
class T>
531 struct NumpyArrayTraits<N, Multiband<T>, StridedArrayTag>
532 :
public NumpyArrayTraits<N, T, StridedArrayTag>
534 typedef NumpyArrayTraits<N, T, StridedArrayTag> BaseType;
535 typedef typename BaseType::ValuetypeTraits ValuetypeTraits;
537 static bool isShapeCompatible(PyArrayObject * array)
539 PyObject * obj = (PyObject*)array;
540 int ndim = PyArray_NDIM(obj);
541 long channelIndex = pythonGetAttr(obj,
"channelIndex", ndim);
542 long majorIndex = pythonGetAttr(obj,
"innerNonchannelIndex", ndim);
544 if(channelIndex < ndim)
549 else if(majorIndex < ndim)
557 return ndim == N || ndim == N-1;
561 static bool isPropertyCompatible(PyArrayObject * obj)
563 return isShapeCompatible(obj) && ValuetypeTraits::isValuetypeCompatible(obj);
567 static TaggedShape taggedShape(TinyVector<U, N>
const & shape, PyAxisTags axistags)
569 return TaggedShape(shape, axistags).setChannelIndexLast();
573 static TaggedShape taggedShape(TinyVector<U, N>
const & shape, std::string
const & order =
"")
575 return TaggedShape(shape,
576 PyAxisTags(detail::defaultAxistags(shape.size(), order))).setChannelIndexLast();
579 static void finalizeTaggedShape(TaggedShape & tagged_shape)
581 if(tagged_shape.axistags &&
582 !tagged_shape.axistags.hasChannelAxis() && tagged_shape.channelCount() == 1)
584 tagged_shape.setChannelCount(0);
585 vigra_precondition(tagged_shape.size() == N-1,
586 "reshapeIfEmpty(): tagged_shape has wrong size.");
590 vigra_precondition(tagged_shape.size() == N,
591 "reshapeIfEmpty(): tagged_shape has wrong size.");
595 template <
class ARRAY>
596 static void permuteLikewise(python_ptr array, ARRAY
const & data, ARRAY & res)
598 ArrayVector<npy_intp> permute;
600 if((
int)data.size() == N)
602 vigra_precondition(PyArray_NDIM((PyArrayObject*)array.get()) == N,
603 "NumpyArray::permuteLikewise(): input array has no channel axis.");
605 detail::getAxisPermutationImpl(permute, array,
"permutationToNormalOrder",
606 AxisInfo::AllAxes,
true);
608 if(permute.size() == 0)
616 int channelIndex = permute[0];
617 for(
int k=1; k<N; ++k)
618 permute[k-1] = permute[k];
619 permute[N-1] = channelIndex;
624 vigra_precondition((
int)data.size() == N-1,
625 "NumpyArray::permuteLikewise(): size mismatch.");
627 detail::getAxisPermutationImpl(permute, array,
"permutationToNormalOrder",
628 AxisInfo::NonChannel,
true);
630 if(permute.size() == 0)
637 applyPermutation(permute.begin(), permute.end(), data.begin(), res.begin());
641 static void permutationToSetupOrder(python_ptr array, ArrayVector<U> & permute)
643 detail::getAxisPermutationImpl(permute, array,
"permutationToNormalOrder",
644 AxisInfo::AllAxes,
true);
646 if(permute.size() == 0)
648 permute.resize(PyArray_NDIM((PyArrayObject*)array.get()));
651 else if(permute.size() == N)
654 int channelIndex = permute[0];
655 for(
int k=1; k<N; ++k)
656 permute[k-1] = permute[k];
657 permute[N-1] = channelIndex;
664 template<
unsigned int N,
class T>
665 struct NumpyArrayTraits<N, Multiband<T>, UnstridedArrayTag>
666 :
public NumpyArrayTraits<N, Multiband<T>, StridedArrayTag>
668 typedef NumpyArrayTraits<N, Multiband<T>, StridedArrayTag> BaseType;
669 typedef typename BaseType::ValuetypeTraits ValuetypeTraits;
671 static bool isShapeCompatible(PyArrayObject * array)
673 PyObject * obj = (PyObject *)array;
674 int ndim = PyArray_NDIM(obj);
675 long channelIndex = pythonGetAttr(obj,
"channelIndex", ndim);
676 long majorIndex = pythonGetAttr(obj,
"innerNonchannelIndex", ndim);
677 npy_intp * strides = PyArray_STRIDES(obj);
679 if(channelIndex < ndim)
683 return ndim == N && strides[majorIndex] ==
sizeof(T);
685 else if(majorIndex < ndim)
689 return ndim == N-1 && strides[majorIndex] ==
sizeof(T);
695 return (ndim == N || ndim == N-1) && strides[0] ==
sizeof(T);
699 static bool isPropertyCompatible(PyArrayObject * obj)
701 return isShapeCompatible(obj) && BaseType::isValuetypeCompatible(obj);
707 template<
unsigned int N,
int M,
class T>
708 struct NumpyArrayTraits<N, TinyVector<T, M>, StridedArrayTag>
711 typedef TinyVector<T, M> value_type;
712 typedef NumpyArrayValuetypeTraits<T> ValuetypeTraits;
713 static NPY_TYPES
const typeCode = ValuetypeTraits::typeCode;
715 static bool isArray(PyObject * obj)
717 return obj && PyArray_Check(obj);
720 static bool isValuetypeCompatible(PyArrayObject * obj)
722 return ValuetypeTraits::isValuetypeCompatible(obj);
725 static bool isShapeCompatible(PyArrayObject * array)
727 PyObject * obj = (PyObject *)array;
730 if(PyArray_NDIM(obj) != N+1)
734 long channelIndex = pythonGetAttr(obj,
"channelIndex", N);
735 npy_intp * strides = PyArray_STRIDES(obj);
737 return PyArray_DIM(obj, channelIndex) == M && strides[channelIndex] ==
sizeof(T);
740 static bool isPropertyCompatible(PyArrayObject * obj)
742 return isShapeCompatible(obj) && ValuetypeTraits::isValuetypeCompatible(obj);
746 static TaggedShape taggedShape(TinyVector<U, N>
const & shape, PyAxisTags axistags)
748 return TaggedShape(shape, axistags).setChannelCount(M);
752 static TaggedShape taggedShape(TinyVector<U, N>
const & shape, std::string
const & order =
"")
754 return TaggedShape(shape,
755 PyAxisTags(detail::defaultAxistags(shape.size()+1, order))).setChannelCount(M);
758 static void finalizeTaggedShape(TaggedShape & tagged_shape)
760 tagged_shape.setChannelCount(M);
761 vigra_precondition(tagged_shape.size() == N+1,
762 "reshapeIfEmpty(): tagged_shape has wrong size.");
765 template <
class ARRAY>
766 static void permuteLikewise(python_ptr array, ARRAY
const & data, ARRAY & res)
768 vigra_precondition((
int)data.size() == N,
769 "NumpyArray::permuteLikewise(): size mismatch.");
771 ArrayVector<npy_intp> permute;
772 detail::getAxisPermutationImpl(permute, array,
"permutationToNormalOrder",
773 AxisInfo::NonChannel,
true);
775 if(permute.size() == 0)
781 applyPermutation(permute.begin(), permute.end(), data.begin(), res.begin());
785 static void permutationToSetupOrder(python_ptr array, ArrayVector<U> & permute)
787 detail::getAxisPermutationImpl(permute, array,
"permutationToNormalOrder",
788 AxisInfo::AllAxes,
true);
789 if(permute.size() == 0)
794 else if(permute.size() == N+1)
796 permute.erase(permute.begin());
801 static python_ptr unsafeConstructorFromData(TinyVector<U, N>
const & shape,
802 value_type *data, TinyVector<U, N>
const & stride)
804 TinyVector<npy_intp, N+1> npyShape;
805 std::copy(shape.begin(), shape.end(), npyShape.begin());
808 TinyVector<npy_intp, N+1> npyStride;
810 stride.begin(), stride.end(), npyStride.begin(),
811 std::bind2nd(std::multiplies<npy_intp>(),
sizeof(value_type)));
812 npyStride[N] =
sizeof(T);
814 return constructNumpyArrayFromData(npyShape, npyStride.begin(),
815 ValuetypeTraits::typeCode, data);
821 template<
unsigned int N,
int M,
class T>
822 struct NumpyArrayTraits<N, TinyVector<T, M>, UnstridedArrayTag>
823 :
public NumpyArrayTraits<N, TinyVector<T, M>, StridedArrayTag>
825 typedef NumpyArrayTraits<N, TinyVector<T, M>, StridedArrayTag> BaseType;
826 typedef typename BaseType::value_type value_type;
827 typedef typename BaseType::ValuetypeTraits ValuetypeTraits;
829 static bool isShapeCompatible(PyArrayObject * array)
831 PyObject * obj = (PyObject *)array;
832 int ndim = PyArray_NDIM(obj);
838 long channelIndex = pythonGetAttr(obj,
"channelIndex", ndim);
839 long majorIndex = pythonGetAttr(obj,
"innerNonchannelIndex", ndim);
840 npy_intp * strides = PyArray_STRIDES(obj);
842 if(majorIndex < ndim)
845 if(channelIndex == ndim)
849 return PyArray_DIM(obj, channelIndex) == M &&
850 strides[channelIndex] ==
sizeof(T) &&
851 strides[majorIndex] ==
sizeof(TinyVector<T, M>);
858 return PyArray_DIM(obj, N) == M &&
859 strides[N] ==
sizeof(T) &&
860 strides[0] ==
sizeof(TinyVector<T, M>);
864 static bool isPropertyCompatible(PyArrayObject * obj)
866 return isShapeCompatible(obj) && BaseType::isValuetypeCompatible(obj);
872 template<
unsigned int N,
class T>
873 struct NumpyArrayTraits<N, RGBValue<T>, StridedArrayTag>
874 :
public NumpyArrayTraits<N, TinyVector<T, 3>, StridedArrayTag>
877 typedef RGBValue<T> value_type;
878 typedef NumpyArrayValuetypeTraits<T> ValuetypeTraits;
883 template<
unsigned int N,
class T>
884 struct NumpyArrayTraits<N, RGBValue<T>, UnstridedArrayTag>
885 :
public NumpyArrayTraits<N, RGBValue<T>, StridedArrayTag>
887 typedef NumpyArrayTraits<N, TinyVector<T, 3>, UnstridedArrayTag> UnstridedTraits;
888 typedef NumpyArrayTraits<N, RGBValue<T>, StridedArrayTag> BaseType;
889 typedef typename BaseType::value_type value_type;
890 typedef typename BaseType::ValuetypeTraits ValuetypeTraits;
892 static bool isShapeCompatible(PyArrayObject * obj)
894 return UnstridedTraits::isShapeCompatible(obj);
897 static bool isPropertyCompatible(PyArrayObject * obj)
899 return UnstridedTraits::isPropertyCompatible(obj);
905 #endif // VIGRA_NUMPY_ARRAY_TRAITS_HXX