85#ifndef VSPLINE_PREFILTER_H
86#define VSPLINE_PREFILTER_H
96using namespace vigra ;
113static xlf_type overall_gain (
const int & nbpoles ,
118 for (
int k = 0 ; k < nbpoles ; k++ )
120 lambda *= ( 1 - pole[k] ) * ( 1 - 1 / pole[k] ) ;
127static xlf_type overall_gain (
const int & spline_degree )
129 if ( spline_degree < 2 )
131 assert ( spline_degree <= vspline_constants::max_degree ) ;
132 return overall_gain ( spline_degree / 2 ,
188template <
typename in_type ,
189 typename out_type = in_type ,
190 typename _math_type = out_type >
194 typedef _math_type math_type ;
196 typedef vigra::MultiArrayView < 1 , in_type > in_buffer_type ;
197 typedef vigra::MultiArrayView < 1 , out_type > out_buffer_type ;
205 std::vector < int > horizon ;
211 typedef void (
filter_type::*p_solve ) (
const in_buffer_type & input ,
212 out_buffer_type & output )
const ;
213 typedef math_type (
filter_type::*p_icc ) (
const in_buffer_type & buffer ,
int k )
const ;
214 typedef math_type (
filter_type::*p_iccx ) (
const out_buffer_type & buffer ,
int k )
const ;
215 typedef math_type (
filter_type::*p_iacc ) (
const out_buffer_type & buffer ,
int k )
const ;
248 return horizon [ 0 ] ;
259 void solve (
const in_buffer_type & input , out_buffer_type & output )
261 assert ( input.size ( ) == output.size ( ) ) ;
262 ( this->*_p_solve ) ( input , output ) ;
267 void solve ( out_buffer_type & data )
269 ( this->*_p_solve ) ( data , data ) ;
311template <
typename buffer_type >
314 const buffer_type & c ;
316 as_math_type (
const buffer_type & _c )
320 const math_type operator[] (
int i )
const
322 return math_type ( c [ i ] ) ;
332template <
typename buffer_type >
337 as_target ( buffer_type & _x )
341 const math_type operator[] (
int i )
const
343 return math_type ( x [ i ] ) ;
346 void store (
const math_type & v ,
const int & i )
348 x [ i ] =
typename buffer_type::value_type ( v ) ;
352template <
class buffer_type >
353math_type icc_mirror (
const buffer_type & _c ,
int k )
const
355 int M = _c.size ( ) ;
356 as_math_type < buffer_type > c ( _c ) ;
358 math_type z = math_type (
pole[k] ) ;
359 math_type zn , z2n , iz ;
363 if ( horizon[k] < M )
368 for ( n = 1 ; n < horizon[k] ; n++ )
378 iz = math_type ( 1.0 ) / z ;
380 Sum = c[0] + z2n * c[M - 1] ;
382 for ( n = 1 ; n <= M - 2 ; n++ )
384 Sum += ( zn + z2n ) * c[n] ;
388 Sum /= ( math_type ( 1.0 ) - zn * zn ) ;
400math_type iacc_mirror (
const out_buffer_type & _c ,
int k )
const
402 int M = _c.size ( ) ;
403 as_math_type < out_buffer_type > c ( _c ) ;
405 math_type z = math_type (
pole[k] ) ;
407 return ( math_type ( z / ( z * z - math_type ( 1.0 ) ) ) * ( c [ M - 1 ] + z * c [ M - 2 ] ) ) ;
418template <
class buffer_type >
419math_type icc_natural (
const buffer_type & _c ,
int k )
const
421 int M = _c.size ( ) ;
422 as_math_type < buffer_type > c ( _c ) ;
424 math_type z = math_type (
pole[k] ) ;
425 math_type zn , z2n , iz ;
426 math_type Sum , c02 ;
432 if ( horizon[k] < M )
437 for ( n = 1 ; n < horizon[k] ; n++ )
439 Sum += zn * ( c02 - c[n] ) ;
446 iz = math_type ( 1.0 ) / z ;
448 Sum = math_type ( ( math_type ( 1.0 ) + z ) / ( math_type ( 1.0 ) - z ) )
449 * ( c[0] - z2n * c[M - 1] ) ;
451 for ( n = 1 ; n <= M - 2 ; n++ )
453 Sum -= ( zn - z2n ) * c[n] ;
457 return ( Sum / ( math_type ( 1.0 ) - zn * zn )) ;
465math_type iacc_natural (
const out_buffer_type & _c ,
int k )
const
467 int M = _c.size ( ) ;
468 as_math_type < out_buffer_type > c ( _c ) ;
470 math_type z = math_type (
pole[k] ) ;
472 return - math_type ( z / ( ( math_type ( 1.0 ) - z ) * ( math_type ( 1.0 ) - z ) ) ) * ( c [ M - 1 ] - z * c [ M - 2 ] ) ;
486template <
class buffer_type >
487math_type icc_reflect (
const buffer_type & _c ,
int k )
const
489 int M = _c.size ( ) ;
490 as_math_type < buffer_type > c ( _c ) ;
492 math_type z = math_type (
pole[k] ) ;
493 math_type zn , z2n , iz ;
497 if ( horizon[k] < M )
501 for ( n = 0 ; n < horizon[k] ; n++ )
511 iz = math_type ( 1.0 ) / z ;
514 for ( n = 0 ; n < M - 1 ; n++ )
516 Sum += ( zn + z2n ) * c[n] ;
520 Sum += ( zn + z2n ) * c[n] ;
521 return c[0] + Sum / ( math_type ( 1.0 ) - zn * zn ) ;
529math_type iacc_reflect (
const out_buffer_type & _c ,
int k )
const
531 int M = _c.size ( ) ;
532 as_math_type < out_buffer_type > c ( _c ) ;
534 math_type z = math_type (
pole[k] ) ;
536 return c[M - 1] / ( math_type ( 1.0 ) - math_type ( 1.0 ) / z ) ;
547template <
class buffer_type >
548math_type icc_periodic (
const buffer_type & _c ,
int k )
const
550 int M = _c.size ( ) ;
551 as_math_type < buffer_type > c ( _c ) ;
553 math_type z = math_type (
pole[k] ) ;
558 if ( horizon[k] < M )
562 for ( n = M - 1 ; n > ( M - horizon[k] ) ; n-- )
572 for ( n = M - 1 ; n > 0 ; n-- )
577 Sum /= ( math_type ( 1.0 ) - zn ) ;
582math_type iacc_periodic (
const out_buffer_type & _c ,
int k )
const
584 int M = _c.size ( ) ;
585 as_math_type < out_buffer_type > c ( _c ) ;
587 math_type z = math_type (
pole[k] ) ;
591 if ( horizon[k] < M )
595 for (
int n = 0 ; n < horizon[k] ; n++ )
606 for (
int n = 0 ; n < M - 1 ; n++ )
611 Sum = z * Sum / ( zn - math_type ( 1.0 ) ) ;
623template <
class buffer_type >
624math_type icc_guess (
const buffer_type & _c ,
int k )
const
626 as_math_type < buffer_type > c ( _c ) ;
628 return c[0] * math_type ( 1.0 / ( 1.0 -
pole[k] ) ) ;
633math_type iacc_guess (
const out_buffer_type & c ,
int k )
const
635 return iacc_mirror ( c , k ) ;
638template <
class buffer_type >
639math_type icc_identity (
const buffer_type & _c ,
int k )
const
641 as_math_type < buffer_type > c ( _c ) ;
646math_type iacc_identity (
const out_buffer_type & _c ,
int k )
const
648 int M = _c.size ( ) ;
649 as_math_type < out_buffer_type > c ( _c ) ;
662void solve_gain_inlined (
const in_buffer_type & _c ,
663 out_buffer_type & _x )
const
665 int M = _c.size ( ) ;
666 assert ( _x.size ( ) == M ) ;
667 as_math_type < in_buffer_type > c ( _c ) ;
668 as_target < out_buffer_type > x ( _x ) ;
672 x.store ( c[0] , 0 ) ;
681 math_type p = math_type (
pole[0] ) ;
693 X = math_type ( gain ) * ( this->*_p_icc ) ( _c , 0 ) ;
699 for (
int n = 1 ; n < M ; n++ )
703 math_type cc = math_type ( gain ) * c[n] ;
704 X = fma ( X , p , cc ) ;
706 X = math_type ( gain ) * c[n] + p * X ;
716 X = ( this->*_p_iacc ) ( _x , 0 ) ;
717 x.store ( X , M - 1 ) ;
720 for (
int n = M - 2 ; 0 <= n ; n-- )
722 X = p * ( X - x[n] ) ;
729 for (
int k = 1 ; k <
npoles ; k++ )
731 p = math_type (
pole[k] ) ;
733 X = ( this->*_p_iccx ) ( _x , k ) ;
737 for (
int n = 1 ; n < M ; n++ )
741 math_type xx = x[n] ;
742 X = fma ( X , p , xx ) ;
750 X = ( this->*_p_iacc ) ( _x , k ) ;
751 x.store ( X , M - 1 ) ;
754 for (
int n = M - 2 ; 0 <= n ; n-- )
756 X = p * ( X - x[n] ) ;
767void solve_identity (
const in_buffer_type & _c ,
768 out_buffer_type & _x )
const
770 int M = _c.size ( ) ;
771 assert ( _x.size ( ) == M ) ;
772 as_math_type < in_buffer_type > c ( _c ) ;
773 as_target < out_buffer_type > x ( _x ) ;
778 if ( (
void* ) ( _c.data ( ) ) != (
void* ) ( _x.data ( ) ) )
781 for (
int n = 0 ; n < M ; n++ )
783 x.store ( c[n] , n ) ;
790 math_type factor = math_type (
boost ) ;
792 for (
int n = 0 ; n < M ; n++ )
794 x.store ( factor * c[n] , n ) ;
819 _p_solve = & filter_type::solve_identity ;
832 for (
int i = 0 ; i <
npoles ; i++ )
835 horizon.push_back ( ceil ( log (
tolerance )
836 / log ( std::abs (
pole[i] ) ) ) ) ;
838 horizon.push_back ( INT_MAX ) ;
846 _p_solve = & filter_type::solve_gain_inlined ;
855 _p_icc = & filter_type::icc_mirror<in_buffer_type> ;
856 _p_iccx = & filter_type::icc_mirror<out_buffer_type> ;
857 _p_iacc = & filter_type::iacc_mirror ;
861 _p_icc = & filter_type::icc_natural<in_buffer_type> ;
862 _p_iccx = & filter_type::icc_natural<out_buffer_type> ;
863 _p_iacc = & filter_type::iacc_natural ;
867 _p_icc = & filter_type::icc_periodic<in_buffer_type> ;
868 _p_iccx = & filter_type::icc_periodic<out_buffer_type> ;
869 _p_iacc = & filter_type::iacc_periodic ;
873 _p_icc = & filter_type::icc_reflect<in_buffer_type> ;
874 _p_iccx = & filter_type::icc_reflect<out_buffer_type> ;
875 _p_iacc = & filter_type::iacc_reflect ;
879 _p_icc = & filter_type::icc_identity<in_buffer_type> ;
880 _p_iccx = & filter_type::icc_identity<out_buffer_type> ;
881 _p_iacc = & filter_type::iacc_identity ;
885 _p_icc = & filter_type::icc_guess<in_buffer_type> ;
886 _p_iccx = & filter_type::icc_guess<out_buffer_type> ;
887 _p_iacc = & filter_type::iacc_guess ;
891 throw not_supported (
"boundary condition not supported by vspline::filter" ) ;
907template <
template <
typename ,
size_t >
class _vtype ,
908 typename _math_ele_type ,
932 vigra::MultiArray < 1 , vtype , allocator_t >
buffer ;
974 template <
typename in_type ,
975 typename out_type = in_type ,
976 typename math_type = out_type >
990template <
unsigned int dimension ,
991 typename in_value_type ,
992 typename out_value_type ,
993 typename math_ele_type >
995 < dimension , in_value_type > & input ,
996 vigra::MultiArrayView
997 < dimension , out_value_type > & output ,
998 math_ele_type boost = 1 ,
1005 if ( (
void*) ( input.data() ) == (
void*) ( output.data() )
1006 && boost == math_ele_type ( 1 ) )
1009 assert ( input.size() == output.size() ) ;
1014 std::ptrdiff_t batch_size = 1024 ;
1015 std::ptrdiff_t total_size = input.size() ;
1021 std::function < void() > payload =
1027 std::ptrdiff_t lo , hi ;
1030 ( tickets , batch_size , total_size , lo , hi ) )
1032 if ( boost == math_ele_type ( 1 ) )
1036 output[lo] = out_value_type ( input[lo] ) ;
1044 output[lo] = out_value_type ( input[lo] * boost ) ;
1073template <
unsigned int dimension ,
1074 typename in_value_type ,
1075 typename out_value_type ,
1076 typename math_ele_type =
1078 < in_value_type , out_value_type > ,
1083 vigra::MultiArrayView
1085 in_value_type > & input ,
1086 vigra::MultiArrayView
1088 out_value_type > & output ,
1091 static_cast < int > ( dimension ) > bcv ,
1094 = std::numeric_limits < math_ele_type > :: epsilon(),
1107 amplify < dimension , in_value_type , out_value_type , math_ele_type >
1108 ( input , output , math_ele_type ( boost ) ) ;
1113 std::vector < vspline::iir_filter_specs > vspecs ;
1120 for (
int axis = 0 ; axis < dimension ; axis++ )
1124 ( bcv [ axis ] , degree / 2 , poles , tolerance , 1 ) ) ;
1130 vspecs [ 0 ] . boost = boost ;
1146 < in_value_type , out_value_type , dimension , filter_type >
1147 ( input , output , vspecs ) ;
buffer_handling provides services needed for interfacing with a buffer of simdized/goading data....
_vtype< dtype, vsize > vtype
void init(vigra::MultiArrayView< 1, vtype > &_in_window, vigra::MultiArrayView< 1, vtype > &_out_window)
class iir_filter implements an n-pole forward/backward recursive filter to be used for b-spline prefi...
void solve(const in_buffer_type &input, out_buffer_type &output)
solve() takes two buffers, one to the input data and one to the output space. The containers must hav...
static const bool is_single_pass
void solve(out_buffer_type &data)
for in-place operation we use the same filter routine.
iir_filter(const iir_filter_specs &specs)
The last bit of work left is the constructor. This simply passes the specs to the base class construc...
int get_support_width() const
calling code may have to set up buffers with additional space around the actual data to allow filteri...
definitions common to all files in this project, utility code
generic implementation of separable filtering for nD arrays
const xlf_type *const precomputed_poles[]
void prefilter(const vigra::MultiArrayView< dimension, in_value_type > &input, vigra::MultiArrayView< dimension, out_value_type > &output, vigra::TinyVector< bc_code, static_cast< int >(dimension) > bcv, int degree, xlf_type tolerance=std::numeric_limits< math_ele_type > ::epsilon(), xlf_type boost=xlf_type(1), int njobs=default_njobs)
'prefilter' handles b-spline prefiltering for the whole range of acceptable input and output....
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....
typename vigra::NumericTraits< promote_ele_type< T1, T2 > > ::RealPromote common_math_ele_type
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...
void amplify(const vigra::MultiArrayView< dimension, in_value_type > &input, vigra::MultiArrayView< dimension, out_value_type > &output, math_ele_type boost=1, int njobs=vspline::default_njobs)
amplify is used to copy input to output, optionally applying 'boost' in the process....
typename vector_traits< T, N > ::type simdized_type
this alias is used as a shorthand to pick the vectorized type for a given type T and a size N from 'v...
bc_code
This enumeration is used for codes connected to boundary conditions. There are two aspects to boundar...
precalculated prefilter poles and basis function values
vspline creates vigra::MultiArrays of vectorized types. As long as the vectorized types are Vc::SimdA...
class to provide b-spline prefiltering, using 'iir_filter' above. The actual filter object has to int...
buffer_handling< _vtype, _math_ele_type, _vsize > buffer_handling_type
iir_filter_specs arg_type
vspline::iir_filter< simdized_math_type > filter_type
_math_ele_type math_ele_type
_vtype< _math_ele_type, _vsize > simdized_math_type
bspl_prefilter(const iir_filter_specs &specs, size_t size)
void solve(const in_buffer_type &input, out_buffer_type &output)
solve() takes two buffers, one to the input data and one to the output space. The containers must hav...
vigra::MultiArray< 1, vtype, allocator_t > buffer
typename vspline::allocator_traits< vtype > ::type allocator_t
static vspline::iir_filter< in_type, out_type, math_type > get_raw_filter(const iir_filter_specs &specs)
structure to hold specifications for an iir_filter object. This set of parameters has to be passed th...
iir_filter_specs(vspline::bc_code _bc, int _npoles, const xlf_type *_pole, xlf_type _tolerance, xlf_type _boost=xlf_type(1))
exception which is thrown if an opertion is requested which vspline does not support
with the definition of 'simd_traits', we can proceed to implement 'vector_traits': struct vector_trai...