116#ifndef VSPLINE_UNARY_FUNCTOR_H
117#define VSPLINE_UNARY_FUNCTOR_H
129template <
size_t _vsize >
184template <
typename IN ,
282template <
class derived_type ,
297 auto self =
static_cast < const derived_type *
const > ( this ) ;
299 self->eval ( in , out ) ;
305 auto self =
static_cast < derived_type *
> ( this ) ;
307 self->eval ( in , out ) ;
311 template <
typename = std::enable_if < ( vsize > 1 ) > >
314 auto self =
static_cast < const derived_type *
const > ( this ) ;
316 self->eval ( in , out ) ;
320 template <
typename = std::enable_if < ( vsize > 1 ) > >
323 auto self =
static_cast < derived_type *
> ( this ) ;
325 self->eval ( in , out ) ;
335template <
class IN ,
class OUT >
336std::function < void (
const IN& , OUT& ) >
339 return [f] (
const IN& in , OUT& out ) { out = f ( in ) ; } ;
361template <
class derived_type ,
395 template <
typename = std::enable_if < ( vsize > 1 ) > >
401 auto fp =
static_cast < const derived_type *
> ( this ) ;
424 for (
int e = 0 ; e <
vsize ; e++ )
428 for (
int d = 0 ; d <
dim_in ; d++ )
429 nd_in [ d ] = iv [ d ] [ e ] ;
433 fp->eval ( in , out ) ;
437 for (
int d = 0 ; d <
dim_out ; d++ )
438 ov [ d ] [ e ] = nd_out [ d ] ;
459template <
typename I ,
463:
public broadcast < broadcast_type < I , O , S > , I , O , S >
465 typedef std::function < void (
const I & , O & ) >
eval_type ;
490 void eval (
const I & in , O & out )
const
512template <
typename T1 ,
516 typename T2::out_type ,
519 < chain_type < T1 , T2 > ,
520 typename T1::in_type ,
521 typename T2::out_type ,
530 typename T2::out_type ,
541 "can only chain unary_functors with the same vector width" ) ;
543 static_assert ( std::is_same < typename T1::out_type , typename T2::in_type > :: value ,
544 "chain: output of first functor must match input of second functor" ) ;
568 t1.eval ( argument , intermediate ) ;
569 t2.eval ( intermediate , result ) ;
572 template <
typename = std::enable_if < ( vsize > 1 ) > >
574 out_v & result )
const
577 t1.eval ( argument , intermediate ) ;
578 t2.eval ( intermediate , result ) ;
586template <
class T1 ,
class T2 >
588chain (
const T1 & t1 ,
const T2 & t2 )
598template <
typename T1 ,
600 typename enable =
typename
675template <
typename IN ,
749 typename std::enable_if
758 :
_ev ( [ grokkee ] ( const IN & in , OUT & out )
759 { grokkee.
eval ( in , out ) ; } )
761 { grokkee.eval ( in , out ) ; } )
770 ( [fev] ( const IN & in )
791 void eval (
const IN & i , OUT & o )
const
800 template <
typename = std::enable_if < ( vsize > 1 ) > >
812template <
typename IN ,
836 typename std::enable_if
845 :
_ev ( [ grokkee ] ( const IN & in , OUT & out )
846 { grokkee.
eval ( in , out ) ; } )
857 void eval (
const IN & i , OUT & o )
const
867template <
class grokkee_type >
887template <
class _in_type ,
888 class _out_type = _in_type ,
889 class _math_type = _in_type ,
894 < amplify_type < _in_type , _out_type , _math_type , _vsize > ,
917 typedef typename vigra::ExpandElementResult < math_type > :: type
931 template <
typename = std::enable_if < ( dimension > 1 ) > >
945 template <
typename = std::enable_if < ( vsize > 1 ) > >
952 =
reinterpret_cast < in_nd_ele_v const &
> ( in ) ;
976template <
typename _in_type ,
981 < flip < _in_type , _vsize > ,
1018 _out [ e ] = _in [
dimension - e - 1 ] ;
1021 template <
typename = std::enable_if < ( vsize > 1 ) > >
1032 =
reinterpret_cast < in_nd_ele_v const &
> ( in ) ;
1052template <
typename crd_t ,
1062template <
typename T >
1064 typename std::conditional
1065 < std::is_fundamental<T>::value ,
1066 std::is_integral<T> ,
1067 std::is_integral<typename T::value_type>
1070template <
typename crd_t ,
1074 < crd_t , data_t , _vsize ,
1075 typename
std::enable_if
1076 < crd_integral < crd_t > :: value > :: type >
1079 < yield_type < crd_t , data_t , _vsize > ,
1080 crd_t , data_t , _vsize
1088 enum { dimension = base_type::dim_in } ;
1089 enum { channels = base_type::dim_out } ;
1090 using typename base_type::in_type ;
1091 using typename base_type::out_type ;
1092 using typename base_type::in_ele_type ;
1093 using typename base_type::out_ele_type ;
1094 using typename base_type::in_v ;
1095 using typename base_type::out_v ;
1097 typedef typename std::integral_constant
1100 typedef typename std::integral_constant
1103 typedef vigra::MultiArrayView < dimension , out_type >
array_type ;
1116 template <
typename d_t ,
typename c_t >
1117 void eval (
const in_type & crd , out_type & v ,
1129 void eval (
const in_v & crd , out_v & v ,
1132 std::false_type )
const
1134 auto ofs = crd * int(data.stride(0)) ;
1136 data_t * p_src = data.data() ;
1137 v.gather ( p_src , ofs ) ;
1142 void eval (
const in_v & crd , out_v & v ,
1145 std::true_type )
const
1147 auto ofs = crd * int(data.stride(0)) ;
1150 out_ele_type * p_src = (out_ele_type*) ( data.data() ) ;
1151 for (
int ch = 0 ; ch < channels ; ch++ )
1153 v[ch].gather ( p_src + ch , ofs ) ;
1159 void eval (
const in_v & crd , out_v & v ,
1162 std::false_type )
const
1164 auto ofs = crd[0] * int(data.stride(0)) ;
1165 for (
int d = 1 ; d < dimension ; d++ )
1167 ofs += crd[d] * int(data.stride(d)) ;
1170 out_ele_type * p_src = (out_ele_type*) ( data.data() ) ;
1171 v.gather ( p_src , ofs ) ;
1176 void eval (
const in_v & crd , out_v & v ,
1179 std::true_type )
const
1181 auto ofs = crd[0] * int(data.stride(0)) ;
1182 for (
int d = 1 ; d < dimension ; d++ )
1184 ofs += crd[d] * int(data.stride(d)) ;
1188 out_ele_type * p_src = (out_ele_type*) ( data.data() ) ;
1189 for (
int ch = 0 ; ch < channels ; ch++ )
1191 v[ch].gather ( p_src + ch , ofs ) ;
1199 template <
typename in_t ,
typename out_t >
1200 void eval (
const in_t & crd , out_t & v )
const
1202 typedef typename std::is_same < out_t , out_type > :: type is_scalar_t ;
1210template <
typename crd_t ,
1214 < crd_t , data_t , _vsize ,
1215 typename
std::enable_if
1216 < ! crd_integral < crd_t > :: value > :: type >
1219 < yield_type < crd_t , data_t , _vsize > ,
1220 crd_t , data_t , _vsize
1228 enum { dimension = base_type::dim_in } ;
1229 enum { channels = base_type::dim_out } ;
1230 using typename base_type::in_type ;
1231 using typename base_type::out_type ;
1232 using typename base_type::in_ele_type ;
1233 using typename base_type::out_ele_type ;
1234 using typename base_type::in_v ;
1235 using typename base_type::out_v ;
1237 typedef typename std::integral_constant
1240 typedef vigra::MultiArrayView < dimension , out_type >
array_type ;
1242 typedef typename std::conditional
1245 vigra::TinyVector < int , dimension >
1263 void eval (
const in_type & crd , out_type & v ,
1265 std::false_type )
const
1267 iy.eval ( std::round ( crd ) , v ) ;
1270 void eval (
const in_type & crd , out_type & v ,
1272 std::true_type )
const
1274 vigra::TinyVector < int , dimension > icrd ;
1275 for (
int d = 0 ; d < dimension ; d++ )
1276 icrd [ d ] = std::round ( crd [ d ] ) ;
1277 iy.eval ( icrd , v ) ;
1282 void eval (
const in_v & crd , out_v & v ,
1284 std::false_type )
const
1286 typename iy_t::in_v icrd ( round ( crd ) ) ;
1287 iy.eval ( icrd , v ) ;
1290 void eval (
const in_v & crd , out_v & v ,
1292 std::true_type )
const
1294 typename iy_t::in_v icrd ;
1295 for (
int d = 0 ; d < dimension ; d++ )
1296 icrd [ d ] = round ( crd [ d ] ) ;
1297 iy.eval ( icrd , v ) ;
1302 template <
typename in_t ,
typename out_t >
1303 void eval (
const in_t & crd , out_t & v )
const
1305 typedef typename std::is_same < out_t , out_type > :: type is_scalar_t ;
1306 eval ( crd , v , is_scalar_t() ,
is_nd_t() ) ;
1314template <
size_t _vsize >
1321template <
typename IN ,
definitions common to all files in this project, utility code
vspline::chain_type< T1, T2 > operator+(const T1 &t1, const T2 &t2)
using operator overloading, we can exploit operator+'s semantics to chain several unary functors....
void assign(T &t, const U &u)
vspline::grok_type< typename grokkee_type::in_type, typename grokkee_type::out_type, grokkee_type::vsize > grok(const grokkee_type &grokkee)
grok() is the corresponding factory function, wrapping grokkee in a vspline::grok_type.
vspline::chain_type< T1, T2 > chain(const T1 &t1, const T2 &t2)
chain is a factory function yielding the result of chaining two unary_functors.
typename std::conditional< std::is_fundamental< T >::value, std::is_integral< T >, std::is_integral< typename T::value_type > > ::type crd_integral
First, we specialize for integral coordinates.
std::function< void(const IN &, OUT &) > eval_wrap(std::function< OUT(const IN &) > f)
eval_wrap is a helper function template, wrapping an 'ordinary' function which returns some value giv...
grokkee_type is a vspline::unary_functor returning twice it's input
void eval(const IN &in, OUT &out) const
amplify_type amplifies it's input with a factor. If the data are multi-channel, the factor is multi-c...
vspline::vector_traits< math_ele_type, vsize >::type math_ele_v
vector_traits< IN, vsize >::nd_ele_v in_nd_ele_v
vigra::ExpandElementResult< math_type >::type math_ele_type
vector_traits< IN, vsize >::type in_v
vectorized in_type and out_type. vspline::vector_traits supplies these types so that multidimensional...
amplify_type(const math_type &_factor)
vector_traits< OUT, vsize >::nd_ele_v out_nd_ele_v
vector_traits< OUT, vsize >::type out_v
vspline::unary_functor< _in_type, _out_type, _vsize > base_type
vigra::TinyVector< math_ele_type, dimension > math_nd_ele_type
amplify_type(const math_ele_type &_factor)
void eval(const in_v &in, out_v &out) const
void eval(const in_type &in, out_type &out) const
broadcast_type(const eval_type &_ev)
std::function< void(const I &, O &) > eval_type
std::function< O(const I &) > call_type
void eval(const I &in, O &out) const
broadcast_type(const call_type &_f)
struct broadcast is a mixin providing an 'eval' method to a functor which can process vectorized argu...
vigra::TinyVector< in_ele_type, dim_in > in_nd_ele_type
vector_traits< IN, vsize >::nd_ele_v in_nd_ele_v
vigra::TinyVector< out_ele_type, dim_out > out_nd_ele_type
vector_traits< IN, vsize >::type in_v
vectorized in_type and out_type. vspline::vector_traits supplies these types so that multidimensional...
vspline::unary_functor< IN, OUT, _vsize > base_type
vector_traits< OUT, vsize >::nd_ele_v out_nd_ele_v
vector_traits< OUT, vsize >::type out_v
void eval(const in_v &inv, out_v &outv) const
mixin 'callable' is used with CRTP: it serves as additional base to unary functors which are meant to...
vector_traits< OUT, vsize >::type cl_out_v
OUT operator()(const IN &in) const
vector_traits< IN, vsize >::type cl_in_v
class chain_type is a helper class to pass one unary functor's result as argument to another one....
vspline::unary_functor< typename T1::in_type, typename T2::out_type, vsize > base_type
chain_type(const T1 &_t1, const T2 &_t2)
vector_traits< IN, vsize >::type in_v
vectorized in_type and out_type. vspline::vector_traits supplies these types so that multidimensional...
void eval(const in_type &argument, out_type &result) const
vector_traits< OUT, vsize >::type out_v
void eval(const in_v &argument, out_v &result) const
T1::out_type intermediate_type
flip functor produces it's input with component order reversed. This can be used to deal with situati...
void eval(const in_type &in_, out_type &out) const
vigra::TinyVector< in_ele_type, dim_in > in_nd_ele_type
vspline::unary_functor< _in_type, _in_type, _vsize > base_type
vector_traits< IN, vsize >::nd_ele_v in_nd_ele_v
vigra::TinyVector< out_ele_type, dim_out > out_nd_ele_type
vector_traits< IN, vsize >::type in_v
vectorized in_type and out_type. vspline::vector_traits supplies these types so that multidimensional...
vector_traits< OUT, vsize >::nd_ele_v out_nd_ele_v
vector_traits< OUT, vsize >::type out_v
void eval(const in_v &in_, out_v &out) const
void eval(const IN &i, OUT &o) const
grok_type(const eval_type &fev)
std::function< void(const in_type &, out_type &) > eval_type
std::function< out_type(const in_type &) > call_type
vspline::unary_functor< IN, OUT, 1 > base_type
grok_type(grokkee_type grokkee)
class grok_type is a helper class wrapping a vspline::unary_functor so that it's type becomes opaque ...
grok_type(call_type f, v_call_type vf)
constructor taking a call_type and a v_call_type, initializing the two std::functions _ev and _v_ev w...
void eval(const in_v &i, out_v &o) const
vectorized evaluation function template the eval overload above will catch calls with (in_type,...
grok_type()
we provide a default constructor so we can create an empty grok_type and assign to it later....
void eval(const IN &i, OUT &o) const
unvectorized evaluation. This is delegated to _ev.
std::function< out_v(const in_v &) > v_call_type
std::function< out_type(const in_type &) > call_type
vector_traits< IN, vsize >::type in_v
vectorized in_type and out_type. vspline::vector_traits supplies these types so that multidimensional...
grok_type(grokkee_type grokkee)
constructor from 'grokkee' using lambda expressions to initialize the std::functions _ev and _v_ev....
vector_traits< OUT, vsize >::type out_v
std::function< void(const in_type &, out_type &) > eval_type
grok_type(const eval_type &fev, const v_eval_type &vfev)
direct initialization of the internal evaluation functions this overload, with two arguments,...
grok_type(const call_type &f)
constructor taking only one call_type, which is also broadcast, since the call_type std::function is ...
std::function< void(const in_v &, out_v &) > v_eval_type
vspline::unary_functor< IN, OUT, _vsize > base_type
grok_type(const eval_type &fev)
constructor taking only an unvectorized evaluation function. this function is broadcast,...
while 'normal' unary_functors are all derived from unary_functor_tag, sink functors will be derived f...
sink_functor is used for functors without an output - e.g. reductors which are used for analytic purp...
vector_traits< IN, vsize >::nd_ele_v in_nd_ele_v
vspline::vector_traits< IN >::ele_type in_ele_type
vector_traits< IN, vsize >::type in_v
vectorized in_type. vspline::vector_traits supplies this type so that multidimensional/multichannel d...
vector_traits< IN, vsize >::ele_v in_ele_v
a simdized type of the elementary type of result_type, which is used for coefficients and results....
vector_traits< int, vsize >::ele_v ic_v
vsize wide vector of ints, used for gather/scatter indexes
vigra::TinyVector< in_ele_type, dim_in > in_nd_ele_type
we derive all vspline::unary_functors from this empty class, to have a common base type for all of th...
class unary_functor provides a functor object which offers a system of types for concrete unary funct...
vigra::TinyVector< in_ele_type, dim_in > in_nd_ele_type
vspline::vector_traits< OUT >::ele_type out_ele_type
vector_traits< IN, vsize >::nd_ele_v in_nd_ele_v
vigra::TinyVector< out_ele_type, dim_out > out_nd_ele_type
vector_traits< IN, vsize >::type in_v
vectorized in_type and out_type. vspline::vector_traits supplies these types so that multidimensional...
vspline::vector_traits< IN >::ele_type in_ele_type
vector_traits< OUT, vsize >::nd_ele_v out_nd_ele_v
vector_traits< OUT, vsize >::type out_v
vector_traits< int, vsize >::ele_v ic_v
vsize wide vector of ints, used for gather/scatter indexes
vector_traits< IN, vsize >::ele_v in_ele_v
a simdized type of the elementary type of result_type, which is used for coefficients and results....
static const bool has_capped_eval
vector_traits< OUT, vsize >::ele_v out_ele_v
with the definition of 'simd_traits', we can proceed to implement 'vector_traits': struct vector_trai...
std::integral_constant< bool,(dimension >1)>::type is_nd_t
unary_functor< crd_t, data_t, _vsize > base_type
vigra::MultiArrayView< dimension, out_type > array_type
yield_type< ic_t, data_t, _vsize > iy_t
std::conditional< dimension==1, int, vigra::TinyVector< int, dimension > >::type ic_t
yield_type(const array_type &_data)
void eval(const in_t &crd, out_t &v) const
std::integral_constant< bool,(dimension >1)>::type is_nd_t
std::integral_constant< bool,(channels >1)>::type is_mc_t
vigra::MultiArrayView< dimension, out_type > array_type
void eval(const in_t &crd, out_t &v) const
yield_type(const array_type &_data)
unary_functor< crd_t, data_t, _vsize > base_type
at times we require reading access to an nD array at given coordinates, as a functor which,...