[vspline] 54/72: changed template argument signature of grid_eval

Kay F. Jahnke kfj-guest at moszumanska.debian.org
Sun Jul 2 09:02:42 UTC 2017


This is an automated email from the git hooks/post-receive script.

kfj-guest pushed a commit to branch master
in repository vspline.

commit 3e38f24c533e99071e03a96ab8db0d30b413b17f
Author: Kay F. Jahnke <kfjahnke at gmail.com>
Date:   Wed May 3 18:32:06 2017 +0200

    changed template argument signature of grid_eval
---
 remap.h | 136 +++++++++++++++++++++++++++++-----------------------------------
 1 file changed, 62 insertions(+), 74 deletions(-)

diff --git a/remap.h b/remap.h
index 20f96b4..81640e2 100644
--- a/remap.h
+++ b/remap.h
@@ -57,6 +57,13 @@
 ///
 /// t[j] = i(a,c[j]) for all j
 ///
+/// Now we widen the concept of remapping to something which is more like a 'transform'
+/// function. Instead of limiting the process to the use of an 'interpolator', we use
+/// an arbitrary unary functor to transform incoming values to outgoing values, where
+/// the type of the incoming and outgoing values is determined by the functor. If the
+/// functor actually is an interpolator, we have a 'true' remap transforming coordinates
+/// into values, but this is merely a special case.
+///
 /// st_remap is the single_threaded implementation; remap itself partitions it's work
 /// and feeds several threads, each running one instance of st_remap.
 ///
@@ -69,12 +76,6 @@
 /// for example, remap from a volume to a 2D image, using a 2D warp array containing
 /// 3D coordinates.
 ///
-/// In these routines, we can switch the use of vectorization on or off. When using
-/// vectorization, this is done in a straightforward fashion by aggregating the input.
-/// If the source/target array lends itself to it, we can pass it's memory directly
-/// to the vectorized eval code.
-/// If the memory is not suited, I 'manually' aggregate to a simdized type.
-///
 /// There is also a second set of remap functions in this file, which don't take a
 /// 'warp' array. Instead, for every target location, the location's discrete coordinates
 /// are passed to the unary_functor_type object. This way, transformation-based remaps
@@ -88,8 +89,8 @@
 ///
 /// - unary_functor_type: functor object yielding values for coordinates
 ///
-/// This file also has code to evaluate a b-spline at positions in a mesh grid, which can be used
-/// for scaling, and for separable geometric transformations.
+/// This file also has code to evaluate a b-spline at positions in a mesh grid, which can
+/// be used for scaling, and for separable geometric transformations.
 ///
 /// The current implementation of the remap functionality uses a straightforward mode of
 /// operation, which factors out the various needed tasks into separate bits of code. The
@@ -167,7 +168,7 @@ using bcv_type = vigra::TinyVector < bc_code , dimension > ;
 /// or gather/scatter operations, even when the arrays involved are strided.
 /// Taking the hierarchical descent down to level 0 is encoded in fill() and it's
 /// workhorse code, the generator objects implemented here depend on the descent
-/// going all thw way down.
+/// going all the way down to 1D.
 ///
 /// _fill is used by st_fill. It's an object implementing an hierarchical fill
 /// of the target array. This is done recursively. while the generator's and the
@@ -298,7 +299,7 @@ void st_fill ( shape_range_type < dim_out > range ,
 /// turn uses st_fill, the single-threaded fill routine.
 
 template < typename generator_type  , // functor object yielding values
-           int dim_target >              // number of dimensions of output array
+           int dim_target >           // number of dimensions of output array
 void fill ( generator_type & gen ,
             MultiArrayView < dim_target , typename generator_type::value_type >
               & output )
@@ -562,7 +563,7 @@ void apply ( const unary_functor_type & ev ,
 
 template < typename coordinate_type , // type of coordinates in the warp array
            typename value_type ,      // type of values to produce
-           int dim_out >              // number of dimensions of output array
+           int dim_out >              // number of dimensions of warp and output array
 int remap ( const MultiArrayView
               < vigra::ExpandElementResult < coordinate_type > :: size ,
                 value_type > & input ,
@@ -817,18 +818,18 @@ namespace detail // workhorse code for grid_eval
 // offsets for all dimensions yields the offset into the coefficient array
 // to the window of coefficients where the weights are to be applied.
 
-template < typename unary_functor_type , // type offering eval()
-           typename target_type ,       // iterates over target array
-           typename weight_type ,       // singular weight data type
-           int level >                  // current axis
+template < typename evaluator_type , int level >
 struct _grid_eval
 {
+  typedef typename evaluator_type::ele_type weight_type ;
+  typedef MultiArrayView < level + 1 , typename evaluator_type::value_type > target_type ;
+  
   void operator() ( int initial_ofs ,
                     MultiArrayView < 2 , weight_type > & weight ,
                     weight_type** const & grid_weight ,
                     const int & ORDER ,
                     int ** const & grid_ofs ,
-                    const unary_functor_type & itp ,
+                    const evaluator_type & itp ,
                     target_type & result )
   {
     for ( int ofs = 0 ; ofs < result.shape ( level ) ; ofs++ )
@@ -837,26 +838,24 @@ struct _grid_eval
         weight [ vigra::Shape2 ( e , level ) ] = grid_weight [ level ] [ ORDER * ofs + e ] ;
       int cum_ofs = initial_ofs + grid_ofs [ level ] [ ofs ] ;
       auto region = result.bindAt ( level , ofs ) ;
-      _grid_eval < unary_functor_type , decltype ( region ) , weight_type , level-1 >()
+      _grid_eval < evaluator_type , level-1 >()
         ( cum_ofs , weight , grid_weight , ORDER , grid_ofs , itp , region ) ;
     }
   }
 } ;
 
-template < typename unary_functor_type ,
-           typename target_type ,
-           typename weight_type >
-struct _grid_eval < unary_functor_type ,
-                    target_type ,
-                    weight_type ,
-                    0 >
+template < typename evaluator_type >
+struct _grid_eval < evaluator_type , 0 >
 {
+  typedef typename evaluator_type::ele_type weight_type ;
+  typedef MultiArrayView < 1 , typename evaluator_type::value_type > target_type ;
+  
   void operator() ( int initial_ofs ,
                     MultiArrayView < 2 , weight_type > & weight ,
                     weight_type** const & grid_weight ,
                     const int & ORDER ,
                     int ** const & grid_ofs ,
-                    const unary_functor_type & itp ,
+                    const evaluator_type & itp ,
                     target_type & region )
   {
     auto iter = region.begin() ;    
@@ -868,13 +867,13 @@ struct _grid_eval < unary_functor_type ,
     // than the unvectorized code. With g++, the vectorized code is faster
     // than either clang version, but the unvectorized code is much slower.
 
-    const int vsize = unary_functor_type::vsize ;
-    const int channels = unary_functor_type::channels ;
-    typedef typename unary_functor_type::value_type value_type ;
-    typedef typename unary_functor_type::ele_type ele_type ;
-    typedef typename unary_functor_type::ic_v ic_v ;
-    typedef typename unary_functor_type::ele_v ele_v ;
-    typedef typename unary_functor_type::mc_ele_v mc_ele_v ;
+    const int vsize = evaluator_type::vsize ;
+    const int channels = evaluator_type::channels ;
+    typedef typename evaluator_type::value_type value_type ;
+    typedef typename evaluator_type::ele_type ele_type ;
+    typedef typename evaluator_type::ic_v ic_v ;
+    typedef typename evaluator_type::ele_v ele_v ;
+    typedef typename evaluator_type::mc_ele_v mc_ele_v ;
 
     // number of vectorized results
     int aggregates = region.size() / vsize ;
@@ -954,37 +953,39 @@ struct _grid_eval < unary_functor_type ,
 // via 'multithread()' which sets up the partitioning and distribution
 // to threads from a thread pool.
 
-template < typename evaluator_type , // type offering eval()
-           typename target_type ,       // type of target MultiArrayView
-           typename weight_type ,       // singular weight data type
-           typename rc_type >           // singular real coordinate
-void st_grid_eval ( shape_range_type < target_type::actual_dimension > range ,
-                    rc_type ** const _grid_coordinate ,
+template < typename evaluator_type , // b-spline evaluator type
+           int dim_out >             // dimension of target
+void st_grid_eval ( shape_range_type < dim_out > range ,
+                    typename evaluator_type::rc_type ** const _grid_coordinate ,
                     const evaluator_type * itp ,
-                    target_type * p_result )
+                    MultiArrayView < dim_out , typename evaluator_type::value_type >
+                      * p_result )
 {
+  typedef typename evaluator_type::ele_type weight_type ;
+  typedef typename evaluator_type::rc_type rc_type ;
+  typedef MultiArrayView < dim_out , typename evaluator_type::value_type > target_type ;
+  
   const int ORDER = itp->get_order() ;
-  const int dim_target = target_type::actual_dimension ;
   
   // pick the subarray of the 'whole' target array pertaining to this thread's range
   auto result = p_result->subarray ( range[0] , range[1] ) ;
   
   // pick the subset of coordinates pertaining to this thread's range
-  const rc_type * grid_coordinate [ dim_target ] ;
-  for ( int d = 0 ; d < dim_target ; d++ )
+  const rc_type * grid_coordinate [ dim_out ] ;
+  for ( int d = 0 ; d < dim_out ; d++ )
     grid_coordinate[d] = _grid_coordinate[d] + range[0][d] ;
 
   // set up storage for precalculated weights and offsets
 
-  weight_type * grid_weight [ dim_target ] ;
-  int * grid_ofs [ dim_target ] ;
+  weight_type * grid_weight [ dim_out ] ;
+  int * grid_ofs [ dim_out ] ;
   
   // get some metrics
-  TinyVector < int , dim_target > shape ( result.shape() ) ;
-  TinyVector < int , dim_target > stride ( itp->get_stride() ) ;
+  TinyVector < int , dim_out > shape ( result.shape() ) ;
+  TinyVector < int , dim_out > stride ( itp->get_stride() ) ;
   
   // allocate space for the per-axis weights and offsets
-  for ( int d = 0 ; d < dim_target ; d++ )
+  for ( int d = 0 ; d < dim_out ; d++ )
   {
     grid_weight[d] = new weight_type [ ORDER * shape [ d ] ] ;
     grid_ofs[d] = new int [ shape [ d ] ] ;
@@ -1000,7 +1001,7 @@ void st_grid_eval ( shape_range_type < target_type::actual_dimension > range ,
   // the coordinates received in grid_coordinate, the interpolator's obtain_weights
   // method to produce the weight components, and the strides of the coefficient array
   // to convert the integral parts of the coordinates into offsets.
-  for ( int d = 0 ; d < dim_target ; d++ )
+  for ( int d = 0 ; d < dim_out ; d++ )
   {
     for ( int c = 0 ; c < shape [ d ] ; c++ )
     {
@@ -1011,23 +1012,14 @@ void st_grid_eval ( shape_range_type < target_type::actual_dimension > range ,
   }
   
   // allocate storage for a set of singular weights
-  MultiArray < 2 , weight_type > weight ( vigra::Shape2 ( ORDER , dim_target ) ) ;
+  MultiArray < 2 , weight_type > weight ( vigra::Shape2 ( ORDER , dim_out ) ) ;
   
   // now call the recursive workhorse routine
-  detail::_grid_eval < evaluator_type ,
-                       target_type ,
-                       weight_type ,
-                       dim_target - 1 >()
-   ( 0 ,
-     weight ,
-     grid_weight ,
-     ORDER ,
-     grid_ofs ,
-     *itp ,
-     result ) ;
+  detail::_grid_eval < evaluator_type , dim_out - 1 >()
+   ( 0 , weight , grid_weight , ORDER , grid_ofs , *itp , result ) ;
 
   // clean up
-  for ( int d = 0 ; d < dim_target ; d++ )
+  for ( int d = 0 ; d < dim_out ; d++ )
   {
     delete[] grid_weight[d] ;
     delete[] grid_ofs[d] ;
@@ -1069,19 +1061,15 @@ void st_grid_eval ( shape_range_type < target_type::actual_dimension > range ,
 /// to the prefiltering routine. Of course any other way of smoothing can
 /// be used just the same, like a Burt filter or Gaussian smoothing.
 
-// TODO template args are too many and too unspecific, especially weight_type
-
-template < typename evaluator_type , // type offering eval()
-           typename target_type ,
-           typename weight_type ,       // singular weight data type
-           typename rc_type >           // singular real coordinate
-void grid_eval ( rc_type ** const grid_coordinate ,
+template < typename evaluator_type , // b-spline evaluator
+           int dim_out >             // dimension of target
+void grid_eval ( typename evaluator_type::rc_type ** const grid_coordinate ,
                  const evaluator_type & itp ,
-                 target_type & result )
+                 MultiArrayView < dim_out , typename evaluator_type::value_type >
+                   & result )
 {
-  const int dim_target = target_type::actual_dimension ;
-  shape_range_type < dim_target > range ( shape_type < dim_target > () , result.shape() ) ;
-  multithread ( st_grid_eval < evaluator_type , target_type , weight_type , rc_type > ,
+  shape_range_type < dim_out > range ( shape_type < dim_out > () , result.shape() ) ;
+  multithread ( st_grid_eval < evaluator_type , dim_out > ,
                 ncores * 8 , range , grid_coordinate , &itp , &result ) ;
 }
 
@@ -1122,14 +1110,14 @@ void restore ( const vspline::bspline < value_type , dimension > & bspl ,
   {
     typedef vspline::evaluator < coordinate_type , value_type , -1 , 0 > ev_type ;
     ev_type ev ( bspl ) ;
-    vspline::grid_eval < ev_type , target_type , weight_type , rc_type >
+    vspline::grid_eval < ev_type , dimension > // target_type , weight_type , rc_type >
      ( p_ruler , ev , target ) ;
   }
   else
   {
     typedef vspline::evaluator < coordinate_type , value_type , -1 , 1 > ev_type ;
     ev_type ev ( bspl ) ;
-    vspline::grid_eval < ev_type , target_type , weight_type , rc_type >
+    vspline::grid_eval < ev_type , dimension > // , target_type , weight_type , rc_type >
      ( p_ruler , ev , target ) ;
   }
 

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/vspline.git



More information about the debian-science-commits mailing list