78#include <gsl/gsl_poly.h> 
   89#define degree_limit 46 
  121    throw std::invalid_argument ( 
"access with degree out of bounds" ) ;
 
  129    if ( x2 == -1 || x2 == 0 )
 
  136    column = x2 >= 0 ? x2 : -x2 ;
 
  152  mpq_class & f1 ( 
access_table ( degree - 1 , x2 + 1 ) ) ;
 
  153  mpq_class & f2 ( 
access_table ( degree - 1 , x2 - 1 ) ) ;
 
  159    =   (   f1 * ( degree + 1 + x2 )
 
  160          + f2 * ( degree + 1 - x2 ) )
 
  171  for ( 
int degree = 1 ; degree < 
degree_limit ; degree++ )
 
  173    for ( 
int x2 = 0 ; x2 <= degree ; x2++ )
 
  185template < 
typename dtype >
 
  188  dtype * pk = pcoeff + ncoeff - 1 ; 
 
  203    dfx += power * xd * *pk ;
 
  210  result = x - fx / dfx ;
 
  234  const int r = degree / 2 ;
 
  240  double coeffs [ 2 * r + 1 ] ;
 
  241  mpf_class mpf_coeffs [ 2 * r + 1 ] ;
 
  245  double roots [ 4 * r + 2 ] ;
 
  250  double * pcoeffs = coeffs ;
 
  251  mpf_class * pmpf_coeffs = mpf_coeffs ;
 
  253  for ( 
int x2 = -r * 2 ;
 
  255        x2 += 2 , pcoeffs++ , pmpf_coeffs++ )
 
  263  gsl_poly_complex_workspace * w 
 
  264          = gsl_poly_complex_workspace_alloc ( 2 * r + 1 ) ;
 
  268  gsl_poly_complex_solve ( coeffs , 2 * r + 1 , w , roots ) ;
 
  272  gsl_poly_complex_workspace_free ( w ) ;
 
  311  for ( 
int i = 2 * r - 2 ; i >= 0 ; i -= 2 )
 
  313    if ( std::abs ( roots[i] ) < 1.0 )
 
  318      mpf_class root ( roots[i] ) ;
 
  332      while ( ( pa - pb ) * ( pa - pb ) >= pdelta )
 
  340        newton ( pa , pa , 2*r+1 , mpf_coeffs ) ;
 
  346      res.push_back ( root ) ;
 
  355void forward ( mpf_class * x , 
int size , mpf_class pole )
 
  359  for ( 
int n = 1 ; n < size ; n++ )
 
  361    x[n] = X = x[n] + pole * X ;
 
  369void backward ( mpf_class * x , 
int size , mpf_class pole )
 
  373  for ( 
int n = size - 2 ; n >= 0 ; n-- )
 
  375    x[n] = X = pole * ( X - x[n] );
 
  389            const std::vector<mpf_class> & poles ,
 
  392  mpf_class buffer [ size ] ;
 
  393  for ( 
int k = 0 ; k < size ; k++ )
 
  400  mpf_class lambda = 1 ;
 
  402  for ( 
int k = 0 ; k < poles.size() ; k++ )
 
  404    lambda = lambda * ( 1 - poles[k] ) * ( 1 - 1 / poles[k] ) ;
 
  406  int center = size / 2 ;
 
  410  for ( 
int x2 = 0 ; x2 <= degree ; x2 += 2 )
 
  411      buffer [ center - x2/2 ]
 
  412    = buffer [ center + x2/2 ]
 
  417  for ( 
int k = 0 ; k < poles.size() ; k++ )
 
  419    forward ( buffer , size , poles[k] ) ;
 
  420    backward ( buffer , size , poles[k] ) ;
 
  425  mpf_class error = 0 ;
 
  426  mpf_class max_error = 0 ;
 
  428  for ( 
int x2 = 0 ; x2 <= degree ; x2 += 2 )
 
  430    error = abs ( buffer [ center - x2/2 ] - ( x2 == 0 ? 1 : 0 ) ) ;
 
  431    if ( error > max_error )
 
  433    error = abs ( buffer [ center + x2/2 ] - ( x2 == 0 ? 1 : 0 ) ) ;
 
  434    if ( error > max_error )
 
  437  mpf_class limit = 1e-150 ;
 
  438  if ( max_error > limit )
 
  439    std::cerr << 
"WARNING: degree " << degree
 
  440              << 
" error exceeds limit 1e-150: " 
  441              << max_error << std::endl ;
 
  450  std::string sign ( 
"+" ) ;
 
  456    sign = std::string ( 
"-" ) ;
 
  459  auto str = x.get_str ( exp , 10 , 64 ) ;
 
  461  std::string res =   sign + std::string ( 
"." ) + str
 
  462                    + std::string ( 
"e" ) + std::to_string ( exp )
 
  463                    + std::string ( 
"l" ) ;
 
  476  for ( 
int n = 1 ; n < size ; n++ )
 
  478    x[n] = X = x[n] + pole * X ;
 
  488  for ( 
int n = size - 2 ; n >= 0 ; n-- )
 
  490    x[n] = X = pole * ( X - x[n] );
 
  497              const std::vector<mpf_class> & poles ,
 
  500  int nbpoles = degree / 2 ;
 
  503  for ( 
int k = 0 ; k < size ; k++ )
 
  512  for ( 
int k = 0 ; k < nbpoles ; k++ )
 
  514    auto ldp = 
get_xlf ( poles[k] ) ;
 
  515    lambda = lambda * ( 1 - ldp ) * ( 1 - 1 / ldp ) ;
 
  518  int center = size / 2 ;
 
  522  for ( 
int x2 = 0 ; x2 <= degree ; x2 += 2 )
 
  526    buffer [ center - x2/2 ]
 
  527    = buffer [ center + x2/2 ]
 
  533  for ( 
int k = 0 ; k < nbpoles ; k++ )
 
  535    auto ldp = 
get_xlf ( poles[k] ) ;
 
  545  for ( 
int x2 = 0 ; x2 <= degree ; x2 += 2 )
 
  547    error = std::abs ( buffer [ center - x2/2 ] - ( x2 == 0 ? 1 : 0 ) ) ;
 
  548    if ( error > max_error )
 
  550    error = std::abs ( buffer [ center + x2/2 ] - ( x2 == 0 ? 1 : 0 ) ) ;
 
  551    if ( error > max_error )
 
  556  if ( max_error > limit )
 
  557    std::cerr << 
"WARNING: degree " << degree
 
  558              << 
" ld error exceeds limit 1e-12: " 
  559              << max_error << std::endl ;
 
  564int main ( 
int argc , 
char * argv[] )
 
  568  bool print_basis_function = true ;
 
  569  bool print_prefilter_poles = true ;
 
  570  bool print_umbrella_structures = true ;
 
  572  std::cout << std::setprecision ( 64 ) ;
 
  577  if ( print_basis_function )
 
  579    for ( 
int degree = 0 ; degree < 
degree_limit ; degree++ )
 
  581      std::cout << 
"const vspline::xlf_type K" 
  585      for ( 
int x2 = 0 ; x2 <= degree ; x2++ )
 
  599  for ( 
int degree = 2 ; degree < 
degree_limit ; degree++ )
 
  601    std::vector<mpf_class> res ;
 
  604    if ( res.size() != degree / 2 )
 
  606      std::cerr << 
"not enough poles for degree " << degree << std::endl ;
 
  610    if ( print_prefilter_poles )
 
  612      std::cout << 
"const vspline::xlf_type Poles_" 
  617      for ( 
int p = 0 ; p < degree / 2 ; p++ )
 
  629    test ( 10000 , res , degree ) ;
 
  631    ldtest ( 10000 , res , degree ) ;
 
  634  if ( print_umbrella_structures )
 
  636    std::cout << std::noshowpos ;
 
  637    std::cout << 
"const vspline::xlf_type* const precomputed_poles[] = {" 
  639    std::cout << 
"  0, " << std::endl ;
 
  640    std::cout << 
"  0, " << std::endl ;
 
  642      std::cout << 
"  Poles_" << i << 
", " << std::endl ;
 
  643    std::cout << 
"} ;" << std::endl ;
 
  644    std::cout << 
"const vspline::xlf_type* const precomputed_basis_function_values[] = {" 
  647      std::cout << 
"  K" << i << 
", " << std::endl ;
 
  648    std::cout << 
"} ;" << std::endl ;
 
int main(int argc, char *argv[])
 
void _fill_basis_table(int x2, int degree)
 
void ldbackward(vspline::xlf_type *x, int size, vspline::xlf_type pole)
 
mpq_class & access_table(int degree, int x2)
 
void forward(mpf_class *x, int size, mpf_class pole)
 
void ldtest(int size, const std::vector< mpf_class > &poles, int degree)
 
mpq_class basis_table[degree_limit][degree_limit+1]
 
void backward(mpf_class *x, int size, mpf_class pole)
 
void ldforward(vspline::xlf_type *x, int size, vspline::xlf_type pole)
 
void calculate_prefilter_poles(std::vector< mpf_class > &res, int degree)
 
void newton(dtype &result, dtype x, int ncoeff, dtype *pcoeff)
 
void test(int size, const std::vector< mpf_class > &poles, int degree)
 
vspline::xlf_type get_xlf(const mpf_class &_x)
 
includes all headers from vspline (most of them indirectly)