vspline 1.1.0
Generic C++11 Code for Uniform B-Splines
gradient.cc
Go to the documentation of this file.
1/************************************************************************/
2/* */
3/* vspline - a set of generic tools for creation and evaluation */
4/* of uniform b-splines */
5/* */
6/* Copyright 2015 - 2023 by Kay F. Jahnke */
7/* */
8/* Permission is hereby granted, free of charge, to any person */
9/* obtaining a copy of this software and associated documentation */
10/* files (the "Software"), to deal in the Software without */
11/* restriction, including without limitation the rights to use, */
12/* copy, modify, merge, publish, distribute, sublicense, and/or */
13/* sell copies of the Software, and to permit persons to whom the */
14/* Software is furnished to do so, subject to the following */
15/* conditions: */
16/* */
17/* The above copyright notice and this permission notice shall be */
18/* included in all copies or substantial portions of the */
19/* Software. */
20/* */
21/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */
22/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */
23/* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */
24/* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */
25/* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
26/* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
27/* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
28/* OTHER DEALINGS IN THE SOFTWARE. */
29/* */
30/************************************************************************/
31
32/// \file gradient.cc
33///
34/// \brief evaluating a specific spline, derivatives, precision
35///
36/// If we create a b-spline over an array containing, at each grid point,
37/// the sum of the grid point's coordinates, each 1D row, column, etc will
38/// hold a linear gradient with first derivative == 1. If we use NATURAL
39/// BCs, evaluating the spline with real coordinates anywhere inside the
40/// defined range should produce precisely the sum of the coordinates.
41/// This is a good test for both the precision of the evaluation and it's
42/// correct functioning, particularly with higher-D arrays.
43///
44/// compile: clang++ -O3 -DUSE_VC -march=native -std=c++11 -pthread
45/// -o gradient gradient.cc -lVc
46///
47/// (with Vc; use -DUSE_HWY and -lhwy for highway, or -std=c++17 and
48/// -DUSE_STDSIMD for the std::simd backend)
49///
50/// or clang++ -O3 -march=native -std=c++11 -pthread -o gradient gradient.cc
51
52#include <random>
53#include <iostream>
54
55#include <vspline/vspline.h>
56
57int main ( int argc , char * argv[] )
58{
60 typedef typename spline_type::shape_type shape_type ;
61 typedef typename spline_type::view_type view_type ;
62 typedef typename spline_type::bcv_type bcv_type ;
63
64 // let's have a knot point array with nicely odd shape
65
66 shape_type core_shape = { 35 , 43 , 19 } ;
67
68 // we have to use a longish call to the constructor since we want to pass
69 // 0.0 to 'tolerance' and it's way down in the argument list, so we have to
70 // explicitly pass a few arguments which usually take default values before
71 // we have a chance to pass the tolerance
72
73 spline_type bspl ( core_shape , // shape of knot point array
74 3 , // cubic b-spline
75 bcv_type ( vspline::NATURAL ) , // natural boundary conditions
76 0.0 ) ; // no tolerance
77
78 // get a view to the bspline's core, to fill it with data
79
80 view_type core = bspl.core ;
81
82 // create the gradient in each dimension
83
84 for ( int d = 0 ; d < bspl.dimension ; d++ )
85 {
86 for ( int c = 0 ; c < core_shape[d] ; c++ )
87 core.bindAt ( d , c ) += c ;
88 }
89
90 // now prefilter the spline. This is more to make sure that the prefilter
91 // does not do anything wrong - for the given signal, using 'brace()' would
92 // be sufficient, because the prefilter on a linear gradient should not have
93 // an effect on the coefficients (due to symmetry)
94
95 bspl.prefilter() ;
96
97 // set up the evaluator type
98
99 typedef vigra::TinyVector < double , 3 > coordinate_type ;
101
102 // we also want to verify the derivative along each axis
103
104 typedef typename evaluator_type::derivative_spec_type deriv_t ;
105 deriv_t dsx , dsy , dsz ;
106
107 dsx[0] = 1 ; // first derivative along axis 0
108 dsy[1] = 1 ; // first derivative along axis 1
109 dsz[2] = 1 ; // first derivative along axis 2
110
111 // set up the evaluator for the underived result
112
113 evaluator_type ev ( bspl ) ;
114
115 // and evaluators for the three first derivatives
116
117 evaluator_type ev_dx ( bspl , dsx ) ;
118 evaluator_type ev_dy ( bspl , dsy ) ;
119 evaluator_type ev_dz ( bspl , dsz ) ;
120
121 // we want to bombard the evaluator with random in-range coordinates
122
123 std::random_device rd;
124 std::mt19937 gen(rd());
125 // std::mt19937 gen(12345); // fix starting value for reproducibility
126
128
129 // here comes our test, feed 100 random 3D coordinates and compare the
130 // evaluator's result with the expected value, which is precisely the
131 // sum of the coordinate's components. The printout of the derivatives
132 // is boring: it's always 1. But this assures us that the b-spline is
133 // perfectly plane, even off the grid points. Towards the surface of the
134 // volume, the derivative remains at 1.0 because we're using NATURAL
135 // boundary conditions.
136
137 for ( int times = 0 ; times < 100 ; times++ )
138 {
139 for ( int d = 0 ; d < bspl.dimension ; d++ )
140 c[d] = ( core_shape[d] - 1 ) * std::generate_canonical<double, 20>(gen) ;
141 double result ;
142 ev.eval ( c , result ) ;
143 double delta = result - sum ( c ) ;
144
145 std::cout << "eval(" << c << ") = " << result
146 << " -> delta = " << delta << std::endl ;
147
148 ev_dx.eval ( c , result ) ;
149 std::cout << "dx: " << result ;
150
151 ev_dy.eval ( c , result ) ;
152 std::cout << " dy: " << result ;
153
154 ev_dz.eval ( c , result ) ;
155 std::cout << " dz: " << result << std::endl ;
156 }
157}
vigra::TinyVector< float, 2 > coordinate_type
Definition: ca_correct.cc:107
vspline::bspline< pixel_type, 2 > spline_type
Definition: ca_correct.cc:111
class evaluator encodes evaluation of a spline-like object. This is a generalization of b-spline eval...
Definition: eval.h:1718
int main(int argc, char *argv[])
Definition: gradient.cc:57
vigra::TinyVector< vspline::bc_code, dimension > bcv_type
a type for a set of boundary condition codes, one per axis
Definition: transform.h:554
@ NATURAL
Definition: common.h:75
int dsz[]
class bspline now builds on class bspline_base, adding coefficient storage, while bspline_base provid...
Definition: bspline.h:499
view_type core
Definition: bspline.h:566
vigra::TinyVector< std::ptrdiff_t, dimension > shape_type
type of a multidimensional index type
Definition: bspline.h:199
void prefilter(vspline::xlf_type boost=vspline::xlf_type(1), int njobs=vspline::default_njobs)
prefilter converts the knot point data in the 'core' area into b-spline coefficients....
Definition: bspline.h:815
vigra::TinyVector< bc_code, dimension > bcv_type
nD type for one boundary condition per axis
Definition: bspline.h:203
vigra::MultiArrayView< dimension, value_type > view_type
data are read and written to vigra MultiArrayViews:
Definition: bspline.h:539
includes all headers from vspline (most of them indirectly)