|
template<class IT , class RT > |
void | split (const RT &input, IT &select, RT &tune) const |
| split function. This function is used to split incoming real coordinates into an integral and a remainder part, which are used at the core of the evaluation. selection of even or odd splitting is done via the const bool flag 'even_spline_degree'. My initial implementation had this flag as a template argument, but this way it's more flexible and there seems to be no runtime penalty. This method delegates to the free function templates even_split and odd_split, respectively, which are defined in basis.h. More...
|
|
const int & | get_order () const |
|
const int & | get_degree () const |
|
const shape_type & | get_estride () const |
|
| inner_evaluator (const cf_ele_type *const _cf_ebase, const shape_type &_cf_estride, int _spline_degree, const mbf_type &_wgt) |
| inner_evaluator only has a single constructor, which takes these arguments: More...
|
|
template<typename nd_rc_type , typename weight_type > |
void | obtain_weights (vigra::MultiArrayView< 2, weight_type > &weight, const nd_rc_type &c) const |
| obtain_weights calculates the weights to be applied to a section of the coefficients from the fractional parts of the split coordinates. What is calculated here is the evaluation of the spline's basis function at dx, dx+/-1 ... but doing it naively is computationally expensive, as the evaluation of the spline's basis function at arbitrary values has to look at the value, find out the right interval, and then calculate the value with the appropriate function. But we always have to calculate the basis function for all intervals anyway, and the method used here performs this tasks efficiently using a vector/matrix multiplication. If the spline is more than 1-dimensional, we need a set of weights for every dimension. The weights are accessed through a 2D MultiArrayView. For every dimension, there are spline_order weights. Note that this code will process unvectorized and vectorized data alike - hence the template arguments. note that wgt[axis] contains a 'basis_functor' object (see basis.h) which encodes the generation of the set of weights. More...
|
|
template<typename weight_type > |
void | obtain_weights (vigra::MultiArrayView< 2, weight_type > &weight) const |
|
template<typename rc_type , typename weight_type > |
void | obtain_weights (weight_type *p_weight, const int &axis, const rc_type &c) const |
| obtain weight for a single axis More...
|
|
template<typename weight_type > |
void | obtain_weights (weight_type *p_weight, const int &axis) const |
|
template<class result_type , class math1_type , class offset_type > |
void | eval (const offset_type &select, const vigra::MultiArrayView< 2, math1_type > &weight, result_type &result) const |
| the 'innermost' eval routine is called with offset(s) and weights. This routine is public because it is used from outside (namely by grid_eval). In this final delegate we call the workhorse code in class _eval More...
|
|
template<template< typename, int > class bunch, template< typename, size_t > class vector, size_t vsize> |
void | eval (const bunch< vector< rc_ele_type, vsize >, dimension > &coordinate, bunch< vector< trg_ele_type, vsize >, channels > &result, std::false_type) const |
| while class evaluator accepts the argument signature of a vspline::unary_functor, class inner_evaluator uses 'synthetic' types, which are always TinyVectors - possibly of just one element. This simplifies the code, since the 'singular' arguments don't have to be treated separately. The data are just the same in memory and class evaluator simply reinterpret_casts the arguments it receives to the 'synthetic' types. Another effect of moving to the 'synthetic' types is to 'erase' their type: any 'meaning' they may have, like std::complex etc., is removed - they are treated as 'bunches' of a fundamental type or a vector. The synthetic types are built using a combination of two template template arguments: 'bunch' and 'vector': More...
|
|
template<template< typename, int > class bunch, template< typename, size_t > class vector, size_t vsize> |
void | ieval (const bunch< vector< ic_ele_type, vsize >, dimension > &select, bunch< vector< trg_ele_type, vsize >, channels > &result, std::false_type) const |
| first ieval overload taking discrete coordinates, implying a 'delta' of zero. this overload is for 'uspecialized' evaluation. Here we use the call to obtain_weights without a delta, which simply takes only the first line of the weight matrix, which is precisely what obtain_weights would produce with a delta of zero. More...
|
|
template<template< typename, int > class bunch, template< typename, size_t > class vector, size_t vsize> |
void | ieval (const bunch< vector< ic_ele_type, vsize >, dimension > &select, bunch< vector< trg_ele_type, vsize >, channels > &result, std::true_type) const |
| second ieval overload taking discrete coordinates, implying a 'delta' of zero. this overload is for evaluators specialized to 0 or 1, where we can simply load the coefficients and don't need weights: the support is so narrow that we needn't consider neighbouring coefficients More...
|
|
template<template< typename, int > class bunch, template< typename, size_t > class vector, size_t vsize> |
void | eval (const bunch< vector< ic_ele_type, vsize >, dimension > &select, bunch< vector< trg_ele_type, vsize >, channels > &result, std::true_type) const |
| this overload is taken for discrete coordinates, and dispatches again, depending on the evaluator's 'specialize' template argument, to one of two variants of 'ieval', above More...
|
|
template<template< typename, int > class bunch, template< typename, size_t > class vector, size_t vsize> |
void | eval (const bunch< vector< rc_ele_type, vsize >, dimension > &select, bunch< vector< trg_ele_type, vsize >, channels > &result) const |
| initial dispatch on whether incoming coordinates are discrete or real More...
|
|
template<typename _ic_ele_type, typename _rc_ele_type, typename _ofs_ele_type, typename _cf_ele_type, typename _math_ele_type, typename _trg_ele_type, unsigned int _dimension, unsigned int _channels, int _specialize, typename _mbf_type = multi_bf_type < basis_functor < _math_ele_type > , _dimension >>
struct vspline::detail::inner_evaluator< _ic_ele_type, _rc_ele_type, _ofs_ele_type, _cf_ele_type, _math_ele_type, _trg_ele_type, _dimension, _channels, _specialize, _mbf_type >
'inner_evaluator' implements evaluation of a uniform b-spline, or some other spline-like construct relying on basis functions which can provide sets of weights for given deltas. While class evaluator (below, after namespace detail ends) provides objects derived from vspline::unary_functor which are meant to be used by user code, here we have a 'workhorse' object to which 'evaluator' delegates. This code 'rolls out' the per-axis weights the basis functor produces to the set of coefficients relevant to the current evaluation locus (the support window). We rely on a few constraints:
- we require all basis functors to provide degree+1 weights
- the cross product of the per-axis weights is applied to the coefficient window (the kernel is separable).
TODO: investigate generalization to variable degree basis functors and nD kernels which aren't separable, like RBFs
The template arguments are, first, the elementary types (e.t.) of the types involved, then several non-type template arguments fixing aggregate sizes. inner_evaluator only uses 'synthetic' types devoid of any specific meaning, so while class evaluator might accept types like 'std::complex<float>' or 'double' class inner_evaluator would instead accept the synthetic types vigra::TinyVector<float,2> and vigra::TinyVector<double,1>.
Note the name system used for the types. first prefixes:
- ic: integral coordinate
- rc: real coordinate
- ofs: offset in memory
- cf: b-spline coefficient
- math: used for calculations
- trg: type for result ('target') of the evaluation an infix of 'ele' refers to a type's elementary type. suffix 'type' is for unvectorized types, while suffix 'v' is used for simdized types, see below.
User code will not usually create and handle objects of class inner_evaluator, but to understand the code, it's necessary to know the meaning of the template arguments for class inner_evaluator:
- _ic_ele_type: e.t. of integral coordinates. integral coordinates occur when incoming real coordinates are split into an integral part and a remainder. Currently, only int is used.
- _rc_ele_type: e.t. of real coordinates. This is used for incoming real coordinates and the remainder mentioned above
- _ofs_ele_type: e.t. for offsets (in memory). This is used to encode the location of specific coefficients relative to the coefficients' origin in memory. Currently, only int is used.
- _cf_ele_type: elementary type of b-spline coefficients. While in most cases, this type will be the same as the elementary type of the knot point data the spline is built over, it may also be different. See class bspline's prefilter method.
- _math_ele_type: e.t. for mathematical operations. All arithmetic inside class inner_evaluator is done with this elementary type. It's used for weight generation, coefficients are cast to it, and only after the result is complete, it's cast to the 'target type'
- _trg_ele_type: e.t. of target (result). Since class inner_evaluator normally receives it's 'target' per reference, this template argument fixes the target's type. This way, after the arithmetic is done, the result is cast to the target type and then assigned to the target location.
- _dimension: number of dimensions of the spline, and therefore the number of components in incoming coordinates. If the spline is 1D, coordinates will still be contained in vigra::TinyVectors, with only one component.
- _channels: number of channels per coefficient. So, when working on RGB pixels, the number of channels would be three. If the spline is over fundamentals (float, double...), _channels is one and the type used here for coefficients is a vigra::TinyVector with one element.
- _specialize: class inner_evaluator has specialized code for degree-0 and degree-1 b-splines, aka nearest neighbour and linear interpolation. This specialized code can be activated by passing 0 or 1 here, respectively. All other values will result in the use of general b-spline evaluation, which can handle degree-0 and degree-1 splines as well, but less efficiently.
- _mbf_type: This defines the basis functors. For b-splines, this is a multi_bf_type of as many vspline::basis_functors as the spline's dimensions. Making this type a template argument opens the code up to the use of arbitrary basis functions, as long as all the basis functors are of the same type. To use differently-typed basis functors, erase their type using bf_grok_type (see above)
Definition at line 499 of file eval.h.
template<typename _ic_ele_type , typename _rc_ele_type , typename _ofs_ele_type , typename _cf_ele_type , typename _math_ele_type , typename _trg_ele_type , unsigned int _dimension, unsigned int _channels, int _specialize, typename _mbf_type = multi_bf_type < basis_functor < _math_ele_type > , _dimension >>
template<template< typename, int > class bunch, template< typename, size_t > class vector, size_t vsize>
void vspline::detail::inner_evaluator< _ic_ele_type, _rc_ele_type, _ofs_ele_type, _cf_ele_type, _math_ele_type, _trg_ele_type, _dimension, _channels, _specialize, _mbf_type >::eval |
( |
const bunch< vector< ic_ele_type, vsize >, dimension > & |
select, |
|
|
bunch< vector< trg_ele_type, vsize >, channels > & |
result, |
|
|
std::true_type |
|
|
) |
| const |
|
inline |
this overload is taken for discrete coordinates, and dispatches again, depending on the evaluator's 'specialize' template argument, to one of two variants of 'ieval', above
Definition at line 1412 of file eval.h.
template<typename _ic_ele_type , typename _rc_ele_type , typename _ofs_ele_type , typename _cf_ele_type , typename _math_ele_type , typename _trg_ele_type , unsigned int _dimension, unsigned int _channels, int _specialize, typename _mbf_type = multi_bf_type < basis_functor < _math_ele_type > , _dimension >>
template<template< typename, int > class bunch, template< typename, size_t > class vector, size_t vsize>
void vspline::detail::inner_evaluator< _ic_ele_type, _rc_ele_type, _ofs_ele_type, _cf_ele_type, _math_ele_type, _trg_ele_type, _dimension, _channels, _specialize, _mbf_type >::eval |
( |
const bunch< vector< rc_ele_type, vsize >, dimension > & |
coordinate, |
|
|
bunch< vector< trg_ele_type, vsize >, channels > & |
result, |
|
|
std::false_type |
|
|
) |
| const |
|
inline |
while class evaluator accepts the argument signature of a vspline::unary_functor, class inner_evaluator uses 'synthetic' types, which are always TinyVectors - possibly of just one element. This simplifies the code, since the 'singular' arguments don't have to be treated separately. The data are just the same in memory and class evaluator simply reinterpret_casts the arguments it receives to the 'synthetic' types. Another effect of moving to the 'synthetic' types is to 'erase' their type: any 'meaning' they may have, like std::complex etc., is removed - they are treated as 'bunches' of a fundamental type or a vector. The synthetic types are built using a combination of two template template arguments: 'bunch' and 'vector':
- 'bunch', which forms an aggregate of several of a given type, like a vigra::TinyVector, which is currently the only template used for the purpose.
- 'vector', which represents an aggregate of several fundamentals of equal type which will be processed with SIMD logic. Currently, the templates used for the purpose are vspline::simd_type (simulating SIMD operations with ordinary scalar code), Vc::SimdArray, which is a 'proper' SIMD type, and vspline::scalar, which is used for unvectorized data. Note how 'vsize' is a template argument to this function, and not a template argument to class inner_evaluator. This is more flexible, the calling code can process any vsize with the same inner_evaluator. the last template argument is used to differentiate between 'normal' operation with real coordinates and access with discrete coordinates. Weight generation for discrete coordinates is easier, because when they are split into an integral part and a remainder, the remainder is always zero. From degree 2 up we still need to calculate weights for the evaluation, but we can use a simplified method for obtaining the weights. For degree 0 and 1, we need no weights at all, and so we can directly load and return the spline coefficients, which is just like the code for the nearest-neighbour evaluation variants, minus the coordinate splitting. First in line is the overload taking real coordinates:
Definition at line 1296 of file eval.h.
template<typename _ic_ele_type , typename _rc_ele_type , typename _ofs_ele_type , typename _cf_ele_type , typename _math_ele_type , typename _trg_ele_type , unsigned int _dimension, unsigned int _channels, int _specialize, typename _mbf_type = multi_bf_type < basis_functor < _math_ele_type > , _dimension >>
template<template< typename, int > class bunch, template< typename, size_t > class vector, size_t vsize>
void vspline::detail::inner_evaluator< _ic_ele_type, _rc_ele_type, _ofs_ele_type, _cf_ele_type, _math_ele_type, _trg_ele_type, _dimension, _channels, _specialize, _mbf_type >::ieval |
( |
const bunch< vector< ic_ele_type, vsize >, dimension > & |
select, |
|
|
bunch< vector< trg_ele_type, vsize >, channels > & |
result, |
|
|
std::false_type |
|
|
) |
| const |
|
inline |
first ieval overload taking discrete coordinates, implying a 'delta' of zero. this overload is for 'uspecialized' evaluation. Here we use the call to obtain_weights without a delta, which simply takes only the first line of the weight matrix, which is precisely what obtain_weights would produce with a delta of zero.
Definition at line 1347 of file eval.h.
template<typename _ic_ele_type , typename _rc_ele_type , typename _ofs_ele_type , typename _cf_ele_type , typename _math_ele_type , typename _trg_ele_type , unsigned int _dimension, unsigned int _channels, int _specialize, typename _mbf_type = multi_bf_type < basis_functor < _math_ele_type > , _dimension >>
template<template< typename, int > class bunch, template< typename, size_t > class vector, size_t vsize>
void vspline::detail::inner_evaluator< _ic_ele_type, _rc_ele_type, _ofs_ele_type, _cf_ele_type, _math_ele_type, _trg_ele_type, _dimension, _channels, _specialize, _mbf_type >::ieval |
( |
const bunch< vector< ic_ele_type, vsize >, dimension > & |
select, |
|
|
bunch< vector< trg_ele_type, vsize >, channels > & |
result, |
|
|
std::true_type |
|
|
) |
| const |
|
inline |
second ieval overload taking discrete coordinates, implying a 'delta' of zero. this overload is for evaluators specialized to 0 or 1, where we can simply load the coefficients and don't need weights: the support is so narrow that we needn't consider neighbouring coefficients
Definition at line 1384 of file eval.h.
template<typename _ic_ele_type , typename _rc_ele_type , typename _ofs_ele_type , typename _cf_ele_type , typename _math_ele_type , typename _trg_ele_type , unsigned int _dimension, unsigned int _channels, int _specialize, typename _mbf_type = multi_bf_type < basis_functor < _math_ele_type > , _dimension >>
template<typename nd_rc_type , typename weight_type >
void vspline::detail::inner_evaluator< _ic_ele_type, _rc_ele_type, _ofs_ele_type, _cf_ele_type, _math_ele_type, _trg_ele_type, _dimension, _channels, _specialize, _mbf_type >::obtain_weights |
( |
vigra::MultiArrayView< 2, weight_type > & |
weight, |
|
|
const nd_rc_type & |
c |
|
) |
| const |
|
inline |
obtain_weights calculates the weights to be applied to a section of the coefficients from the fractional parts of the split coordinates. What is calculated here is the evaluation of the spline's basis function at dx, dx+/-1 ... but doing it naively is computationally expensive, as the evaluation of the spline's basis function at arbitrary values has to look at the value, find out the right interval, and then calculate the value with the appropriate function. But we always have to calculate the basis function for all intervals anyway, and the method used here performs this tasks efficiently using a vector/matrix multiplication. If the spline is more than 1-dimensional, we need a set of weights for every dimension. The weights are accessed through a 2D MultiArrayView. For every dimension, there are spline_order weights. Note that this code will process unvectorized and vectorized data alike - hence the template arguments. note that wgt[axis] contains a 'basis_functor' object (see basis.h) which encodes the generation of the set of weights.
Definition at line 753 of file eval.h.
template<typename _ic_ele_type , typename _rc_ele_type , typename _ofs_ele_type , typename _cf_ele_type , typename _math_ele_type , typename _trg_ele_type , unsigned int _dimension, unsigned int _channels, int _specialize, typename _mbf_type = multi_bf_type < basis_functor < _math_ele_type > , _dimension >>
template<class IT , class RT >
void vspline::detail::inner_evaluator< _ic_ele_type, _rc_ele_type, _ofs_ele_type, _cf_ele_type, _math_ele_type, _trg_ele_type, _dimension, _channels, _specialize, _mbf_type >::split |
( |
const RT & |
input, |
|
|
IT & |
select, |
|
|
RT & |
tune |
|
) |
| const |
|
inline |
split function. This function is used to split incoming real coordinates into an integral and a remainder part, which are used at the core of the evaluation. selection of even or odd splitting is done via the const bool flag 'even_spline_degree'. My initial implementation had this flag as a template argument, but this way it's more flexible and there seems to be no runtime penalty. This method delegates to the free function templates even_split and odd_split, respectively, which are defined in basis.h.
Definition at line 592 of file eval.h.