36 #ifndef VIGRA_NUMPY_ARRAY_TRAITS_HXX
37 #define VIGRA_NUMPY_ARRAY_TRAITS_HXX
39 #ifndef NPY_NO_DEPRECATED_API
40 # define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
43 #include "numerictraits.hxx"
44 #include "multi_array.hxx"
45 #include "numpy_array_taggedshape.hxx"
55 template<
class ValueType>
56 struct ERROR_NumpyArrayValuetypeTraits_not_specialized_for_ { };
58 template<
class ValueType>
59 struct NumpyArrayValuetypeTraits
61 static bool isValuetypeCompatible(PyArrayObject
const * obj)
63 return ERROR_NumpyArrayValuetypeTraits_not_specialized_for_<ValueType>();
66 static ERROR_NumpyArrayValuetypeTraits_not_specialized_for_<ValueType> typeCode;
68 static std::string typeName()
70 return std::string(
"ERROR: NumpyArrayValuetypeTraits not specialized for this case");
73 static std::string typeNameImpex()
75 return std::string(
"ERROR: NumpyArrayValuetypeTraits not specialized for this case");
78 static PyObject * typeObject()
84 template<
class ValueType>
85 ERROR_NumpyArrayValuetypeTraits_not_specialized_for_<ValueType> NumpyArrayValuetypeTraits<ValueType>::typeCode;
87 #define VIGRA_NUMPY_VALUETYPE_TRAITS(type, typeID, numpyTypeName, impexTypeName) \
89 struct NumpyArrayValuetypeTraits<type > \
91 static bool isValuetypeCompatible(PyArrayObject const * obj) \
93 return PyArray_EquivTypenums(typeID, PyArray_DESCR((PyArrayObject *)obj)->type_num) && \
94 PyArray_ITEMSIZE((PyArrayObject *)obj) == sizeof(type); \
97 static NPY_TYPES const typeCode = typeID; \
99 static std::string typeName() \
101 return #numpyTypeName; \
104 static std::string typeNameImpex() \
106 return impexTypeName; \
109 static PyObject * typeObject() \
111 return PyArray_TypeObjectFromType(typeID); \
115 VIGRA_NUMPY_VALUETYPE_TRAITS(
bool, NPY_BOOL,
bool,
"UINT8")
116 VIGRA_NUMPY_VALUETYPE_TRAITS(
signed char, NPY_INT8, int8, "INT16")
117 VIGRA_NUMPY_VALUETYPE_TRAITS(
unsigned char, NPY_UINT8, uint8, "UINT8")
118 VIGRA_NUMPY_VALUETYPE_TRAITS(
short, NPY_INT16, int16, "INT16")
119 VIGRA_NUMPY_VALUETYPE_TRAITS(
unsigned short, NPY_UINT16, uint16, "UINT16")
121 #if VIGRA_BITSOF_LONG == 32
122 VIGRA_NUMPY_VALUETYPE_TRAITS(
long, NPY_INT32, int32,
"INT32")
123 VIGRA_NUMPY_VALUETYPE_TRAITS(
unsigned long, NPY_UINT32, uint32, "UINT32")
124 #elif VIGRA_BITSOF_LONG == 64
125 VIGRA_NUMPY_VALUETYPE_TRAITS(
long, NPY_INT64, int64,
"DOUBLE")
126 VIGRA_NUMPY_VALUETYPE_TRAITS(
unsigned long, NPY_UINT64, uint64, "DOUBLE")
129 #if VIGRA_BITSOF_INT == 32
130 VIGRA_NUMPY_VALUETYPE_TRAITS(
int, NPY_INT32, int32,
"INT32")
131 VIGRA_NUMPY_VALUETYPE_TRAITS(
unsigned int, NPY_UINT32, uint32, "UINT32")
132 #elif VIGRA_BITSOF_INT == 64
133 VIGRA_NUMPY_VALUETYPE_TRAITS(
int, NPY_INT64, int64,
"DOUBLE")
134 VIGRA_NUMPY_VALUETYPE_TRAITS(
unsigned int, NPY_UINT64, uint64, "DOUBLE")
138 # if VIGRA_BITSOF_LONG_LONG == 32
139 VIGRA_NUMPY_VALUETYPE_TRAITS(
long long, NPY_INT32, int32,
"INT32")
140 VIGRA_NUMPY_VALUETYPE_TRAITS(
unsigned long long, NPY_UINT32, uint32, "UINT32")
141 # elif VIGRA_BITSOF_LONG_LONG == 64
142 VIGRA_NUMPY_VALUETYPE_TRAITS(
long long, NPY_INT64, int64,
"DOUBLE")
143 VIGRA_NUMPY_VALUETYPE_TRAITS(
unsigned long long, NPY_UINT64, uint64, "DOUBLE")
147 VIGRA_NUMPY_VALUETYPE_TRAITS(npy_float32, NPY_FLOAT32, float32,
"FLOAT")
148 VIGRA_NUMPY_VALUETYPE_TRAITS(npy_float64, NPY_FLOAT64, float64, "DOUBLE")
149 #if NPY_SIZEOF_LONGDOUBLE != NPY_SIZEOF_DOUBLE
150 VIGRA_NUMPY_VALUETYPE_TRAITS(npy_longdouble, NPY_LONGDOUBLE, longdouble,
"")
152 VIGRA_NUMPY_VALUETYPE_TRAITS(npy_cfloat, NPY_CFLOAT, complex64,
"")
153 VIGRA_NUMPY_VALUETYPE_TRAITS(std::complex<npy_float>, NPY_CFLOAT, complex64, "")
154 VIGRA_NUMPY_VALUETYPE_TRAITS(npy_cdouble, NPY_CDOUBLE, complex128, "")
155 VIGRA_NUMPY_VALUETYPE_TRAITS(std::complex<npy_double>, NPY_CDOUBLE, complex128, "")
156 VIGRA_NUMPY_VALUETYPE_TRAITS(npy_clongdouble, NPY_CLONGDOUBLE, clongdouble, "")
157 #if NPY_SIZEOF_LONGDOUBLE != NPY_SIZEOF_DOUBLE
158 VIGRA_NUMPY_VALUETYPE_TRAITS(std::complex<npy_longdouble>, NPY_CLONGDOUBLE, clongdouble,
"")
161 #undef VIGRA_NUMPY_VALUETYPE_TRAITS
169 template<
unsigned int N,
class T,
class Str
ide>
170 struct NumpyArrayTraits;
174 template<
unsigned int N,
class T>
175 struct NumpyArrayTraits<N, T, StridedArrayTag>
178 typedef T value_type;
179 typedef NumpyArrayValuetypeTraits<T> ValuetypeTraits;
180 static NPY_TYPES
const typeCode = ValuetypeTraits::typeCode;
182 static bool isArray(PyObject * obj)
184 return obj && PyArray_Check(obj);
187 static bool isValuetypeCompatible(PyArrayObject * obj)
189 return ValuetypeTraits::isValuetypeCompatible(obj);
192 static bool isShapeCompatible(PyArrayObject * array)
194 int ndim = PyArray_NDIM(array);
203 static bool isPropertyCompatible(PyArrayObject * obj)
205 return isShapeCompatible(obj) && isValuetypeCompatible(obj);
211 static TaggedShape taggedShape(TinyVector<U, N>
const & shape, PyAxisTags axistags)
213 return TaggedShape(shape, axistags);
220 static TaggedShape taggedShape(TinyVector<U, N>
const & shape,
221 std::string
const & =
"")
227 return TaggedShape(shape, PyAxisTags());
232 static void finalizeTaggedShape(TaggedShape & tagged_shape)
234 vigra_precondition(tagged_shape.size() == N,
235 "reshapeIfEmpty(): tagged_shape has wrong size.");
243 template <
class ARRAY>
244 static void permuteLikewise(python_ptr array, ARRAY
const & data, ARRAY & res)
246 vigra_precondition((
int)data.size() == N,
247 "NumpyArray::permuteLikewise(): size mismatch.");
249 ArrayVector<npy_intp> permute;
250 detail::getAxisPermutationImpl(permute, array,
"permutationToNormalOrder",
251 AxisInfo::AllAxes,
true);
253 if(permute.size() != 0)
255 applyPermutation(permute.begin(), permute.end(), data.begin(), res.begin());
262 static void permutationToSetupOrder(python_ptr array, ArrayVector<U> & permute)
264 detail::getAxisPermutationImpl(permute, array,
"permutationToNormalOrder",
265 AxisInfo::AllAxes,
true);
267 if(permute.size() == 0)
279 static python_ptr unsafeConstructorFromData(TinyVector<U, N>
const & shape,
280 T *data, TinyVector<U, N>
const & stride)
282 TinyVector<npy_intp, N> npyStride(stride *
sizeof(T));
283 return constructNumpyArrayFromData(shape, npyStride.begin(),
284 ValuetypeTraits::typeCode, data);
290 template<
unsigned int N,
class T>
291 struct NumpyArrayTraits<N, T, UnstridedArrayTag>
292 :
public NumpyArrayTraits<N, T, StridedArrayTag>
294 typedef NumpyArrayTraits<N, T, StridedArrayTag> BaseType;
295 typedef typename BaseType::ValuetypeTraits ValuetypeTraits;
297 static bool isShapeCompatible(PyArrayObject * array)
299 PyObject * obj = (PyObject *)array;
300 int ndim = PyArray_NDIM(array);
301 long channelIndex = pythonGetAttr(obj,
"channelIndex", ndim);
302 long majorIndex = pythonGetAttr(obj,
"innerNonchannelIndex", ndim);
303 npy_intp * strides = PyArray_STRIDES(array);
305 if(channelIndex < ndim)
308 return (ndim == N && strides[channelIndex] ==
sizeof(T));
310 else if(majorIndex < ndim)
314 return (ndim == N && strides[majorIndex] ==
sizeof(T));
319 return (ndim == N && strides[0] ==
sizeof(T));
323 static bool isPropertyCompatible(PyArrayObject * obj)
325 return isShapeCompatible(obj) && BaseType::isValuetypeCompatible(obj);
331 template<
unsigned int N,
class T>
332 struct NumpyArrayTraits<N, Singleband<T>, StridedArrayTag>
333 :
public NumpyArrayTraits<N, T, StridedArrayTag>
335 typedef NumpyArrayTraits<N, T, StridedArrayTag> BaseType;
336 typedef typename BaseType::ValuetypeTraits ValuetypeTraits;
338 static bool isShapeCompatible(PyArrayObject * array)
340 PyObject * obj = (PyObject *)array;
341 int ndim = PyArray_NDIM(array);
342 long channelIndex = pythonGetAttr(obj,
"channelIndex", ndim);
346 if(channelIndex == ndim)
350 return ndim == N+1 && PyArray_DIM(array, channelIndex) == 1;
353 static bool isPropertyCompatible(PyArrayObject * obj)
355 return isShapeCompatible(obj) && BaseType::isValuetypeCompatible(obj);
359 static TaggedShape taggedShape(TinyVector<U, N>
const & shape, PyAxisTags axistags)
361 return TaggedShape(shape, axistags).setChannelCount(1);
365 static TaggedShape taggedShape(TinyVector<U, N>
const & shape, std::string
const & order =
"")
367 return TaggedShape(shape,
368 PyAxisTags(detail::defaultAxistags(shape.size()+1, order))).setChannelCount(1);
371 static void finalizeTaggedShape(TaggedShape & tagged_shape)
373 if(tagged_shape.axistags.hasChannelAxis())
375 tagged_shape.setChannelCount(1);
376 vigra_precondition(tagged_shape.size() == N+1,
377 "reshapeIfEmpty(): tagged_shape has wrong size.");
381 tagged_shape.setChannelCount(0);
382 vigra_precondition(tagged_shape.size() == N,
383 "reshapeIfEmpty(): tagged_shape has wrong size.");
387 template <
class ARRAY>
388 static void permuteLikewise(python_ptr array, ARRAY
const & data, ARRAY & res)
390 vigra_precondition((
int)data.size() == N,
391 "NumpyArray::permuteLikewise(): size mismatch.");
393 ArrayVector<npy_intp> permute;
394 detail::getAxisPermutationImpl(permute, array,
"permutationToNormalOrder",
395 AxisInfo::NonChannel,
true);
397 if(permute.size() == 0)
403 applyPermutation(permute.begin(), permute.end(), data.begin(), res.begin());
407 static void permutationToSetupOrder(python_ptr array, ArrayVector<U> & permute)
409 detail::getAxisPermutationImpl(permute, array,
"permutationToNormalOrder",
410 AxisInfo::AllAxes,
true);
411 if(permute.size() == 0)
416 else if(permute.size() == N+1)
418 permute.erase(permute.begin());
425 template<
unsigned int N,
class T>
426 struct NumpyArrayTraits<N, Singleband<T>, UnstridedArrayTag>
427 :
public NumpyArrayTraits<N, Singleband<T>, StridedArrayTag>
429 typedef NumpyArrayTraits<N, T, UnstridedArrayTag> UnstridedTraits;
430 typedef NumpyArrayTraits<N, Singleband<T>, StridedArrayTag> BaseType;
431 typedef typename BaseType::ValuetypeTraits ValuetypeTraits;
433 static bool isShapeCompatible(PyArrayObject * array)
435 PyObject * obj = (PyObject *)array;
436 int ndim = PyArray_NDIM(array);
437 long channelIndex = pythonGetAttr(obj,
"channelIndex", ndim);
438 long majorIndex = pythonGetAttr(obj,
"innerNonchannelIndex", ndim);
439 npy_intp * strides = PyArray_STRIDES(array);
442 if(majorIndex == ndim)
443 return N == ndim && strides[0] ==
sizeof(T);
447 if(channelIndex == ndim)
448 return N == ndim && strides[majorIndex] ==
sizeof(T);
452 return ndim == N+1 && PyArray_DIM(array, channelIndex) == 1 &&
453 strides[majorIndex] ==
sizeof(T);
456 static bool isPropertyCompatible(PyArrayObject * obj)
458 return isShapeCompatible(obj) && BaseType::isValuetypeCompatible(obj);
464 template<
unsigned int N,
class T>
465 struct NumpyArrayTraits<N, Multiband<T>, StridedArrayTag>
466 :
public NumpyArrayTraits<N, T, StridedArrayTag>
468 typedef NumpyArrayTraits<N, T, StridedArrayTag> BaseType;
469 typedef typename BaseType::ValuetypeTraits ValuetypeTraits;
471 static bool isShapeCompatible(PyArrayObject * array)
473 PyObject * obj = (PyObject*)array;
474 int ndim = PyArray_NDIM(array);
475 long channelIndex = pythonGetAttr(obj,
"channelIndex", ndim);
476 long majorIndex = pythonGetAttr(obj,
"innerNonchannelIndex", ndim);
478 if(channelIndex < ndim)
483 else if(majorIndex < ndim)
491 return ndim == N || ndim == N-1;
495 static bool isPropertyCompatible(PyArrayObject * obj)
497 return isShapeCompatible(obj) && ValuetypeTraits::isValuetypeCompatible(obj);
501 static TaggedShape taggedShape(TinyVector<U, N>
const & shape, PyAxisTags axistags)
503 return TaggedShape(shape, axistags).setChannelIndexLast();
507 static TaggedShape taggedShape(TinyVector<U, N>
const & shape, std::string
const & order =
"")
509 return TaggedShape(shape,
510 PyAxisTags(detail::defaultAxistags(shape.size(), order))).setChannelIndexLast();
513 static void finalizeTaggedShape(TaggedShape & tagged_shape)
517 if(tagged_shape.channelCount() == 1 && !tagged_shape.axistags.hasChannelAxis())
519 tagged_shape.setChannelCount(0);
520 vigra_precondition(tagged_shape.size() == N-1,
521 "reshapeIfEmpty(): tagged_shape has wrong size.");
525 vigra_precondition(tagged_shape.size() == N,
526 "reshapeIfEmpty(): tagged_shape has wrong size.");
530 template <
class ARRAY>
531 static void permuteLikewise(python_ptr array, ARRAY
const & data, ARRAY & res)
533 ArrayVector<npy_intp> permute;
535 if((
int)data.size() == N)
537 vigra_precondition(PyArray_NDIM((PyArrayObject*)array.get()) == N,
538 "NumpyArray::permuteLikewise(): input array has no channel axis.");
540 detail::getAxisPermutationImpl(permute, array,
"permutationToNormalOrder",
541 AxisInfo::AllAxes,
true);
543 if(permute.size() == 0)
551 int channelIndex = permute[0];
552 for(
int k=1; k<N; ++k)
553 permute[k-1] = permute[k];
554 permute[N-1] = channelIndex;
559 vigra_precondition((
int)data.size() == N-1,
560 "NumpyArray::permuteLikewise(): size mismatch.");
562 detail::getAxisPermutationImpl(permute, array,
"permutationToNormalOrder",
563 AxisInfo::NonChannel,
true);
565 if(permute.size() == 0)
572 applyPermutation(permute.begin(), permute.end(), data.begin(), res.begin());
576 static void permutationToSetupOrder(python_ptr array, ArrayVector<U> & permute)
578 detail::getAxisPermutationImpl(permute, array,
"permutationToNormalOrder",
579 AxisInfo::AllAxes,
true);
581 if(permute.size() == 0)
583 permute.resize(PyArray_NDIM((PyArrayObject*)array.get()));
586 else if(permute.size() == N)
589 int channelIndex = permute[0];
590 for(
int k=1; k<N; ++k)
591 permute[k-1] = permute[k];
592 permute[N-1] = channelIndex;
599 template<
unsigned int N,
class T>
600 struct NumpyArrayTraits<N, Multiband<T>, UnstridedArrayTag>
601 :
public NumpyArrayTraits<N, Multiband<T>, StridedArrayTag>
603 typedef NumpyArrayTraits<N, Multiband<T>, StridedArrayTag> BaseType;
604 typedef typename BaseType::ValuetypeTraits ValuetypeTraits;
606 static bool isShapeCompatible(PyArrayObject * array)
608 PyObject * obj = (PyObject *)array;
609 int ndim = PyArray_NDIM(array);
610 long channelIndex = pythonGetAttr(obj,
"channelIndex", ndim);
611 long majorIndex = pythonGetAttr(obj,
"innerNonchannelIndex", ndim);
612 npy_intp * strides = PyArray_STRIDES(array);
614 if(channelIndex < ndim)
618 return ndim == N && strides[majorIndex] ==
sizeof(T);
620 else if(majorIndex < ndim)
624 return ndim == N-1 && strides[majorIndex] ==
sizeof(T);
630 return (ndim == N || ndim == N-1) && strides[0] ==
sizeof(T);
634 static bool isPropertyCompatible(PyArrayObject * obj)
636 return isShapeCompatible(obj) && BaseType::isValuetypeCompatible(obj);
642 template<
unsigned int N,
int M,
class T>
643 struct NumpyArrayTraits<N, TinyVector<T, M>, StridedArrayTag>
646 typedef TinyVector<T, M> value_type;
647 typedef NumpyArrayValuetypeTraits<T> ValuetypeTraits;
648 static NPY_TYPES
const typeCode = ValuetypeTraits::typeCode;
650 static bool isArray(PyObject * obj)
652 return obj && PyArray_Check(obj);
655 static bool isValuetypeCompatible(PyArrayObject * obj)
657 return ValuetypeTraits::isValuetypeCompatible(obj);
660 static bool isShapeCompatible(PyArrayObject * array)
662 PyObject * obj = (PyObject *)array;
665 if(PyArray_NDIM(array) != N+1)
669 long channelIndex = pythonGetAttr(obj,
"channelIndex", N);
670 npy_intp * strides = PyArray_STRIDES(array);
672 return PyArray_DIM(array, channelIndex) == M && strides[channelIndex] ==
sizeof(T);
675 static bool isPropertyCompatible(PyArrayObject * obj)
677 return isShapeCompatible(obj) && ValuetypeTraits::isValuetypeCompatible(obj);
681 static TaggedShape taggedShape(TinyVector<U, N>
const & shape, PyAxisTags axistags)
683 return TaggedShape(shape, axistags).setChannelCount(M);
687 static TaggedShape taggedShape(TinyVector<U, N>
const & shape, std::string
const & order =
"")
689 return TaggedShape(shape,
690 PyAxisTags(detail::defaultAxistags(shape.size()+1, order))).setChannelCount(M);
693 static void finalizeTaggedShape(TaggedShape & tagged_shape)
695 tagged_shape.setChannelCount(M);
696 vigra_precondition(tagged_shape.size() == N+1,
697 "reshapeIfEmpty(): tagged_shape has wrong size.");
700 template <
class ARRAY>
701 static void permuteLikewise(python_ptr array, ARRAY
const & data, ARRAY & res)
703 vigra_precondition((
int)data.size() == N,
704 "NumpyArray::permuteLikewise(): size mismatch.");
706 ArrayVector<npy_intp> permute;
707 detail::getAxisPermutationImpl(permute, array,
"permutationToNormalOrder",
708 AxisInfo::NonChannel,
true);
710 if(permute.size() == 0)
716 applyPermutation(permute.begin(), permute.end(), data.begin(), res.begin());
720 static void permutationToSetupOrder(python_ptr array, ArrayVector<U> & permute)
722 detail::getAxisPermutationImpl(permute, array,
"permutationToNormalOrder",
723 AxisInfo::AllAxes,
true);
724 if(permute.size() == 0)
729 else if(permute.size() == N+1)
731 permute.erase(permute.begin());
736 static python_ptr unsafeConstructorFromData(TinyVector<U, N>
const & shape,
737 value_type *data, TinyVector<U, N>
const & stride)
739 TinyVector<npy_intp, N+1> npyShape;
740 std::copy(shape.begin(), shape.end(), npyShape.begin());
743 TinyVector<npy_intp, N+1> npyStride;
745 stride.begin(), stride.end(), npyStride.begin(),
746 std::bind2nd(std::multiplies<npy_intp>(),
sizeof(value_type)));
747 npyStride[N] =
sizeof(T);
749 return constructNumpyArrayFromData(npyShape, npyStride.begin(),
750 ValuetypeTraits::typeCode, data);
756 template<
unsigned int N,
int M,
class T>
757 struct NumpyArrayTraits<N, TinyVector<T, M>, UnstridedArrayTag>
758 :
public NumpyArrayTraits<N, TinyVector<T, M>, StridedArrayTag>
760 typedef NumpyArrayTraits<N, TinyVector<T, M>, StridedArrayTag> BaseType;
761 typedef typename BaseType::value_type value_type;
762 typedef typename BaseType::ValuetypeTraits ValuetypeTraits;
764 static bool isShapeCompatible(PyArrayObject * array)
766 PyObject * obj = (PyObject *)array;
767 int ndim = PyArray_NDIM(array);
773 long channelIndex = pythonGetAttr(obj,
"channelIndex", ndim);
774 long majorIndex = pythonGetAttr(obj,
"innerNonchannelIndex", ndim);
775 npy_intp * strides = PyArray_STRIDES(array);
777 if(majorIndex < ndim)
780 if(channelIndex == ndim)
784 return PyArray_DIM(array, channelIndex) == M &&
785 strides[channelIndex] ==
sizeof(T) &&
786 strides[majorIndex] ==
sizeof(TinyVector<T, M>);
793 return PyArray_DIM(array, N) == M &&
794 strides[N] ==
sizeof(T) &&
795 strides[0] ==
sizeof(TinyVector<T, M>);
799 static bool isPropertyCompatible(PyArrayObject * obj)
801 return isShapeCompatible(obj) && BaseType::isValuetypeCompatible(obj);
807 template<
unsigned int N,
class T>
808 struct NumpyArrayTraits<N, RGBValue<T>, StridedArrayTag>
809 :
public NumpyArrayTraits<N, TinyVector<T, 3>, StridedArrayTag>
812 typedef RGBValue<T> value_type;
813 typedef NumpyArrayValuetypeTraits<T> ValuetypeTraits;
818 template<
unsigned int N,
class T>
819 struct NumpyArrayTraits<N, RGBValue<T>, UnstridedArrayTag>
820 :
public NumpyArrayTraits<N, RGBValue<T>, StridedArrayTag>
822 typedef NumpyArrayTraits<N, TinyVector<T, 3>, UnstridedArrayTag> UnstridedTraits;
823 typedef NumpyArrayTraits<N, RGBValue<T>, StridedArrayTag> BaseType;
824 typedef typename BaseType::value_type value_type;
825 typedef typename BaseType::ValuetypeTraits ValuetypeTraits;
827 static bool isShapeCompatible(PyArrayObject * obj)
829 return UnstridedTraits::isShapeCompatible(obj);
832 static bool isPropertyCompatible(PyArrayObject * obj)
834 return UnstridedTraits::isPropertyCompatible(obj);
840 #endif // VIGRA_NUMPY_ARRAY_TRAITS_HXX
void applyPermutation(IndexIterator index_first, IndexIterator index_last, InIterator in, OutIterator out)
Sort an array according to the given index permutation.
Definition: algorithm.hxx:388
void linearSequence(Iterator first, Iterator last, Value start, Value step)
Fill an array with a sequence of numbers.
Definition: algorithm.hxx:207