78#ifndef VSPLINE_FILTER_H
79#define VSPLINE_FILTER_H
90template <
class dtype ,
95 const std::ptrdiff_t *
idx ;
100 const std::ptrdiff_t * _idx ,
101 std::ptrdiff_t _stride ,
112template <
class stype ,
117 std::ptrdiff_t trg_stride
125 for (
size_t i = 0 ; i <
vsize ; i++ )
128 trg [ i ] = ttype ( ps [ src.
idx [ i ] ] ) ;
139template <
class stype ,
144 std::ptrdiff_t trg_stride ,
152 for (
int i = 0 ; i < ni ; i++ )
155 trg [ i ] = ttype ( ps [ src.
idx [ i ] ] ) ;
164template <
class stype ,
168 std::ptrdiff_t src_stride ,
176 for (
size_t i = 0 ; i <
vsize ; i++ )
179 pt [ trg.
idx [ i ] ] = ttype ( src [ i ] ) ;
189template <
class stype ,
193 std::ptrdiff_t src_stride ,
202 for (
int i = 0 ; i < ni ; i++ )
205 pt [ trg.
idx [ i ] ] = ttype ( src [ i ] ) ;
223template <
template <
typename ,
size_t >
class _vtype ,
232 typedef _vtype < dtype , vsize >
vtype ;
237 void init ( vigra::MultiArrayView < 1 , vtype > & _in_window ,
238 vigra::MultiArrayView < 1 , vtype > & _out_window )
267 template <
class tractor >
268 void get (
const tractor & src ,
269 std::ptrdiff_t offset = 0 ,
270 int ni =
vsize )
const
290 template <
class tractor >
291 void put (
const tractor & trg ,
292 std::ptrdiff_t offset = 0 ,
293 int ni =
vsize )
const
388template <
typename source_view_type ,
389 typename target_view_type ,
390 typename stripe_handler_type >
392 const source_view_type * p_source ,
393 target_view_type * p_target ,
394 const typename stripe_handler_type::arg_type * p_args ,
397 enum { dimension = source_view_type::actual_dimension } ;
402 const source_view_type & source ( *p_source ) ;
403 target_view_type & target ( *p_target ) ;
407 std::ptrdiff_t count = source.shape ( axis ) ;
415 stripe_handler_type handler ( *p_args , count ) ;
420 typedef typename source_view_type::value_type stype ;
421 typedef typename target_view_type::value_type ttype ;
433 auto sample_slice = source.bindAt ( axis , 0 ) ;
435 vigra::MultiCoordinateIterator < dimension - 1 >
436 sliter ( sample_slice.shape() ) ;
441 typedef vigra::TinyVector < std::ptrdiff_t , dimension - 1 > shape_type ;
446 vigra::TinyVector < shape_type , vsize > indexes { *sliter } ;
452 vigra::TinyVector < std::ptrdiff_t , vsize > offsets ;
457 std::ptrdiff_t lo , hi ;
458 std::ptrdiff_t batch_size =
vsize ;
459 std::ptrdiff_t total_size = sample_slice.size() ;
462 ( *p_tickets , batch_size , total_size , lo , hi ) )
464 std::ptrdiff_t n_fetch = hi - lo ;
466 for ( std::ptrdiff_t i = 0 , f = lo ; i < n_fetch ; ++i , ++f )
468 indexes [ i ] = sliter [ f ] ;
473 auto stride = source.stride ( axis ) ;
474 auto size = source.shape ( axis ) ;
476 auto source_slice = source.bindAt ( axis , 0 ) ;
477 auto source_base_adress = source_slice.data() ;
482 for (
int e = 0 ; e <
vsize ; e++ )
484 offsets[e] = sum ( source_slice.stride() * indexes[e] ) ;
496 handler.get ( bi , 0 , n_fetch ) ;
508 stride = target.stride ( axis ) ;
509 size = target.shape ( axis ) ;
511 auto target_slice = target.bindAt ( axis , 0 ) ;
512 auto target_base_adress = target_slice.data() ;
514 for (
int e = 0 ; e <
vsize ; e++ )
515 offsets[e] = sum ( target_slice.stride() * indexes[e] ) ;
522 handler.put ( bo , 0 , n_fetch ) ;
534template <
typename source_view_type ,
535 typename target_view_type ,
536 typename stripe_handler_type >
538 const std::vector<source_view_type> * p_source ,
539 std::vector<target_view_type> * p_target ,
540 const typename stripe_handler_type::arg_type * p_args ,
543 enum { dimension = source_view_type::actual_dimension } ;
548 const std::vector<source_view_type> & source ( *p_source ) ;
549 std::vector<target_view_type> & target ( *p_target ) ;
553 std::ptrdiff_t count = 0 ;
554 for (
auto & e : source )
555 count += e.shape ( axis ) ;
563 stripe_handler_type handler ( *p_args , count ) ;
568 typedef typename source_view_type::value_type stype ;
569 typedef typename target_view_type::value_type ttype ;
575 auto sample_slice = source[0].bindAt ( axis , 0 ) ;
577 vigra::MultiCoordinateIterator < dimension - 1 >
578 sliter ( sample_slice.shape() ) ;
583 typedef vigra::TinyVector < std::ptrdiff_t , dimension - 1 > shape_type ;
588 vigra::TinyVector < shape_type , vsize > indexes { *sliter } ;
594 vigra::TinyVector < std::ptrdiff_t , vsize > offsets ;
599 std::ptrdiff_t lo , hi ;
600 std::ptrdiff_t batch_size =
vsize ;
601 std::ptrdiff_t total_size = sample_slice.size() ;
604 ( *p_tickets , batch_size , total_size , lo , hi ) )
606 std::ptrdiff_t n_fetch = hi - lo ;
608 for ( std::ptrdiff_t i = 0 , f = lo ; i < n_fetch ; ++i , ++f )
610 indexes [ i ] = sliter [ f ] ;
618 std::ptrdiff_t progress = 0 ;
624 for (
auto & input : source )
626 auto source_stride = input.stride ( axis ) ;
627 auto part_size = input.shape ( axis ) ;
628 auto slice = input.bindAt ( axis , 0 ) ;
629 auto source_base_adress = slice.data() ;
634 for (
int e = 0 ; e <
vsize ; e++ )
636 offsets[e] = sum ( slice.stride() * indexes[e] ) ;
651 handler.get ( bi , progress , n_fetch ) ;
652 progress += part_size ;
667 for (
auto & output : target )
669 auto target_stride = output.stride ( axis ) ;
670 auto part_size = output.shape ( axis ) ;
671 auto slice = output.bindAt ( axis , 0 ) ;
672 auto target_base_adress = slice.data() ;
674 for (
int e = 0 ; e <
vsize ; e++ )
675 offsets[e] = sum ( slice.stride() * indexes[e] ) ;
682 handler.put ( bo , progress , n_fetch ) ;
683 progress += part_size ;
726template <
typename input_array_type ,
727 typename output_array_type ,
728 typename stripe_handler_type >
731 enum {
dimension = input_array_type::actual_dimension } ;
732 static_assert (
dimension == output_array_type::actual_dimension ,
733 "separable_filter: input and output array type must have the same dimension" ) ;
738 enum {
channels = vigra::ExpandElementResult < in_value_type > :: size } ;
740 == vigra::ExpandElementResult < out_value_type > :: size ,
741 "separable_filter: input and output data type must have the same number of channels" ) ;
743 typedef typename vigra::ExpandElementResult < in_value_type >
746 typedef typename vigra::ExpandElementResult < out_value_type >
749 typedef std::integral_constant < bool , dimension == 1 >
is_1d_type ;
756 template <
class filter_args >
758 output_array_type & output ,
759 const filter_args & handler_args ,
765 input , output , handler_args , njobs ) ;
772 template <
typename ... types >
774 types ... args )
const
782 template <
typename ... types >
784 types ... args )
const
798 template <
typename in_vt ,
typename out_vt >
802 <
typename stripe_handler_type::arg_type >
806 assert ( handler_args.size() == 1 ) ;
807 _process_1d ( input , output , handler_args[0] , njobs ) ;
847 template <
typename in_vt ,
typename out_vt >
851 const typename stripe_handler_type::arg_type
855 _process_1d ( input , output , handler_args , njobs ) ;
858 template <
typename in_vt ,
typename out_vt >
861 const typename stripe_handler_type::arg_type
872 typedef typename stripe_handler_type::math_ele_type math_ele_type ;
877 auto raw_filter = stripe_handler_type::template
878 get_raw_filter < math_type > ( handler_args ) ;
884 int runup = raw_filter.get_support_width() ;
900 int min_length = 4 * runup * lanes + 2 * runup ;
905 if ( runup == INT_MAX || input.shape(0) < min_length )
919 int good_length = 64 * runup * lanes + 2 * runup ;
926 while ( input.shape(0) / ( 2 * split ) >= good_length )
948 if ( std::is_same < out_value_type , math_type > :: value
949 || stripe_handler_type::is_single_pass )
951 auto raw_filter = stripe_handler_type::template
954 math_type > ( handler_args ) ;
956 raw_filter.solve ( input , output ) ;
971 vigra::MultiArray < 1 , math_type > buffer ( input.shape() ) ;
973 auto raw_filter = stripe_handler_type::template
976 math_type > ( handler_args ) ;
978 raw_filter.solve ( input , buffer ) ;
980 auto trg = output.begin() ;
981 for (
auto const & src : buffer )
994 int core_size = input.shape(0) ;
995 int chunk_size = core_size / lanes ;
996 core_size = lanes * chunk_size ;
997 int tail_size = input.shape(0) - core_size ;
1001 assert ( core_size + tail_size == input.shape(0) ) ;
1030 int front = 2 * runup ;
1031 int back = tail_size + 2 * runup ;
1032 int total = front + back ;
1037 vigra::MultiArray < 1 , math_type > head_and_tail ( total ) ;
1039 auto target_it = head_and_tail.begin() ;
1040 auto source_it = input.begin() ;
1041 for (
int i = 0 ; i < front ; i++ )
1043 *target_it = math_type ( *source_it ) ;
1047 source_it = input.end() - back ;
1048 for (
int i = 0 ; i < back ; i++ )
1050 *target_it = math_type ( *source_it ) ;
1058 raw_filter.solve ( head_and_tail , head_and_tail ) ;
1064 vigra::MultiArrayView < 1 , math_type > head
1065 ( vigra::Shape1 ( front ) , head_and_tail.data() ) ;
1067 vigra::MultiArrayView < 1 , math_type > tail
1068 ( vigra::Shape1 ( back ) , head_and_tail.data() + front ) ;
1089 typename stripe_handler_type::arg_type
1090 handler_args_with_bc_guess ( handler_args ) ;
1100 vigra::MultiArrayView < 2 , in_value_type >
1102 fake_2d_margin ( vigra::Shape2 ( 4 * runup ,
1105 vigra::Shape2 ( input.stride(0) ,
1109 input.data() + input.stride(0)
1110 * ( chunk_size - 2 * runup )
1115 vigra::MultiArray < 2 , out_value_type >
1116 margin_buffer ( fake_2d_margin.shape() ) ;
1119 vigra::MultiArrayView < 2 , out_value_type > ,
1120 stripe_handler_type >()
1121 ( fake_2d_margin , margin_buffer , 0 , handler_args_with_bc_guess , njobs ) ;
1127 vigra::MultiArrayView < 2 , out_value_type > margin
1128 = margin_buffer.subarray ( vigra::Shape2 ( runup , 0 ) ,
1129 vigra::Shape2 ( 3 * runup , lanes - 1 ) ) ;
1135 vigra::MultiArrayView < 2 , out_value_type >
1137 margin_target ( vigra::Shape2 ( 2 * runup ,
1140 vigra::Shape2 ( output.stride(0) ,
1144 output.data() + output.stride(0)
1145 * ( chunk_size - runup )
1152 vigra::MultiArrayView < 2 , in_value_type >
1153 fake_2d_source ( vigra::Shape2 ( chunk_size , lanes ) ,
1154 vigra::Shape2 ( input.stride(0) , input.stride(0) * chunk_size ) ,
1157 vigra::MultiArrayView < 2 , out_value_type >
1158 fake_2d_target ( vigra::Shape2 ( chunk_size , lanes ) ,
1159 vigra::Shape2 ( output.stride(0) , output.stride(0) * chunk_size ) ,
1165 vigra::MultiArrayView < 2 , out_value_type > ,
1166 stripe_handler_type >()
1167 ( fake_2d_source , fake_2d_target , 0 , handler_args_with_bc_guess , njobs ) ;
1176 margin_target = margin ;
1182 for (
int i = 0 ; i < runup ; i++ )
1185 int j = tail.size() - tail_size - runup ;
1186 for (
int i = output.size() - tail_size - runup ;
1187 i < output.size() ; i++ , j++ )
1197 output_array_type & output ,
1199 <
typename stripe_handler_type::arg_type >
1204 handler_args [ 0 ] , njobs ) ;
1206 for (
int axis = 1 ; axis <
dimension ; axis++ )
1214 handler_args [ axis ] , njobs ) ;
1231 output_array_type & output ,
1233 const typename stripe_handler_type::arg_type
1238 input , output , axis ,
1239 handler_args , njobs ) ;
1250 template <
typename ... types >
1270 template <
typename in_t ,
typename out_t >
1272 const in_t & input ,
1275 const typename stripe_handler_type::arg_type
1279 auto source = input.expandElements ( 0 ) ;
1280 auto target = output.expandElements ( 0 ) ;
1307 template <
typename in_t ,
typename out_t >
1309 const in_t & input ,
1312 const typename stripe_handler_type::arg_type
1323 auto size = input.size() / input.shape ( axis ) ;
1332 std::function < void() > worker =
1335 present < in_t , out_t , stripe_handler_type >
1336 ( &tickets , &input , &output , &handler_args , axis ) ;
1365 std::vector<output_array_type> & output ,
1367 const typename stripe_handler_type::arg_type
1372 "processing of stacked 1D arrays is not supported" ) ;
1375 handler_args , njobs ) ;
1383 template <
typename in_vt ,
typename out_vt >
1385 const std::vector < in_vt > & input ,
1386 std::vector < out_vt > & output ,
1388 const typename stripe_handler_type::arg_type
1392 typedef vigra::MultiArrayView < dimension + 1 , in_ele_type >
1393 e_input_array_type ;
1395 typedef vigra::MultiArrayView < dimension + 1 , out_ele_type >
1396 e_output_array_type ;
1401 std::vector<e_input_array_type> source ;
1402 for (
auto & e : input )
1403 source.push_back ( e.expandElements ( 0 ) ) ;
1405 std::vector<e_output_array_type> target ;
1406 for (
auto & e : output )
1407 target.push_back ( e.expandElements ( 0 ) ) ;
1433 template <
typename in_vt ,
typename out_vt >
1435 const std::vector < in_vt > & input ,
1436 std::vector < out_vt > & output ,
1438 const typename stripe_handler_type::arg_type
1449 auto size = input[0].size() / input[0].shape ( axis ) ;
1458 std::function < void() > worker =
1461 vpresent < in_vt , out_vt , stripe_handler_type >
1462 ( &tickets , &input , &output , &handler_args , axis ) ;
1490template <
typename in_type ,
1494 typename ... types >
1495void filter (
const vigra::MultiArrayView < D , in_type > & input ,
1496 vigra::MultiArrayView < D , out_type > & output ,
1502 typedef typename vigra::ExpandElementResult < in_type >
1503 :: type in_ele_type ;
1505 typedef typename vigra::ExpandElementResult < out_type >
1506 :: type out_ele_type ;
1510 enum { channels = vigra::ExpandElementResult < in_type > :: size } ;
1512 static_assert ( channels
1513 == vigra::ExpandElementResult < out_type > :: size ,
1514 "separable_filter: input and output data type must have the same number of channels" ) ;
1519 typedef vigra::MultiArrayView < D , canonical_in_value_type > cn_in_type ;
1522 typedef vigra::MultiArrayView < D , canonical_out_value_type > cn_out_type ;
1530 (
reinterpret_cast < const cn_in_type &
> ( input ) ,
1531 reinterpret_cast < cn_out_type &
> ( output ) ,
buffer_handling provides services needed for interfacing with a buffer of simdized/goading data....
void put(const tractor &trg, std::ptrdiff_t offset=0, int ni=vsize) const
deposit result data from 'out_window' into target memory
void get(const tractor &src, std::ptrdiff_t offset=0, int ni=vsize) const
fetch data from 'source' into the buffer 'in_window'
vigra::MultiArrayView< 1, vtype > in_window
static const std::ptrdiff_t bf_stride
_vtype< dtype, vsize > vtype
vigra::MultiArrayView< 1, vtype > out_window
void init(vigra::MultiArrayView< 1, vtype > &_in_window, vigra::MultiArrayView< 1, vtype > &_out_window)
definitions common to all files in this project, utility code
void present(vspline::atomic< std::ptrdiff_t > *p_tickets, const source_view_type *p_source, target_view_type *p_target, const typename stripe_handler_type::arg_type *p_args, int axis)
'present' feeds 'raw' data to a filter and returns the filtered data. In order to perform this task w...
void vpresent(vspline::atomic< std::ptrdiff_t > *p_tickets, const std::vector< source_view_type > *p_source, std::vector< target_view_type > *p_target, const typename stripe_handler_type::arg_type *p_args, int axis)
vpresent is a variant of 'present' processing 'stacks' of arrays. See 'present' for discussion....
void filter(const vigra::MultiArrayView< D, in_type > &input, vigra::MultiArrayView< D, out_type > &output, types ... args)
vspline::filter is the common entry point for filter operations in vspline. This routine does not yet...
int multithread(std::function< void() > payload, std::size_t nr_workers=default_njobs)
multithread uses a thread pool of worker threads to perform a multithreaded operation....
bool fetch_range_ascending(vspline::atomic< index_t > &source, const index_t &count, const index_t &total, index_t &low, index_t &high)
fetch_range_ascending also uses an atomic initialized to the total number of indexes to be distribute...
typename std::conditional< N==1, ET< T >, vigra::TinyVector< ET< T >, N > > ::type canonical_type
produce the 'canonical type' for a given type T. If T is single-channel, this will be the elementary ...
void move(const bundle< stype, vsize > &src, ttype *trg, std::ptrdiff_t trg_stride)
move bundle data to compact memory
class 'bundle' holds all information needed to access a set of vsize 1D subarrays of an nD array....
const std::ptrdiff_t * idx
bundle(dtype *_data, const std::ptrdiff_t *_idx, std::ptrdiff_t _stride, unsigned long _z)
struct separable_filter is the central object used for 'wielding' filters. The filters themselves are...
void _on_expand(std::true_type, const in_t &input, out_t &output, int axis, const typename stripe_handler_type::arg_type &handler_args, int njobs) const
Variant of _on_expand for single arrays. This is the single-channel overload. The arrays now hold fun...
void _on_expand(std::false_type, const std::vector< in_vt > &input, std::vector< out_vt > &output, int axis, const typename stripe_handler_type::arg_type &handler_args, int njobs) const
variant of _on_expand for stacks of arrays. this overload is called if the data are multi-channel....
void _on_dimension(std::true_type, types ... args) const
void _process_1d(const in_vt &input, out_vt &output, const typename stripe_handler_type::arg_type &handler_args, int njobs) const
std::integral_constant< bool, channels==1 > is_1_channel_type
void operator()(const input_array_type &input, output_array_type &output, const filter_args &handler_args, int njobs=vspline::default_njobs) const
this is the standard entry point to the separable filter code for processing all axes of an array....
void _process_nd(const input_array_type &input, output_array_type &output, const std::vector< typename stripe_handler_type::arg_type > &handler_args, int njobs) const
specialized processing of nD input/output. We have established that the data are nD....
vigra::ExpandElementResult< out_value_type >::type out_ele_type
void _process_1d(const in_vt &input, out_vt &output, const std::vector< typename stripe_handler_type::arg_type > &handler_args, int njobs) const
specialized processing of 1D input/output. We have established that the data are 1D....
void _on_dimension(std::false_type, types ... args) const
std::integral_constant< bool, dimension==1 > is_1d_type
void _process_1d(const in_vt &input, out_vt &output, int axis, const typename stripe_handler_type::arg_type &handler_args, int njobs) const
specialized processing of 1D input/output. We have established that the data are 1D and we have a sin...
input_array_type::value_type in_value_type
void _on_expand(std::true_type, const std::vector< in_vt > &input, std::vector< out_vt > &output, int axis, const typename stripe_handler_type::arg_type &handler_args, int njobs) const
variant of _on_expand for stacks of arrays this is the single-channel overload. The arrays now hold f...
output_array_type::value_type out_value_type
vigra::ExpandElementResult< in_value_type >::type in_ele_type
void _on_expand(std::false_type, const in_t &input, out_t &output, int axis, const typename stripe_handler_type::arg_type &handler_args, int njobs) const
variant of _on_expand for single arrays. this overload is called if the data are multi-channel....
void _process_nd(types ... args) const
processing of nD input/output. we have established that the data are nD. now we look at the data type...