vspline 1.1.0
Generic C++11 Code for Uniform B-Splines
int_spline.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 int_spline.cc
33
34 \brief using a b-spline with integer coefficients
35
36 vspline can use integral data types as b-spline coefficients,
37 but doing so naively will produce imprecise results. This example
38 demonstrates how to do it right. What needs to be done is using
39 'boosted', or amplified, coefficients, so that the range of
40 possible coefficients is 'spread out' to the range of the
41 integral coefficient type. After evaluation, the 'raw' result
42 value has to be attenuated back to the range of original values.
43
44 You can pass the 'boost' factor on the command line to see how
45 different values influence precision of the results. You'll also
46 notice that, when passing too high 'boost' values, the results will
47 turn wrong due to the int coefficients overflowing.
48
49 Prefiltering will create a signal with higher peak values, so
50 the maximal boost factor has to be chosen to take this into
51 account, see 'max_boost' below.
52*/
53
54#include <iostream>
55#include <random>
56#include <limits>
57#include <vspline/vspline.h>
58
59/// given cf_type, the type for a b-spline coefficient, min and max
60/// as the signal's minimum and maximum, and the spline's degree,
61/// max_boost calculates the maximal safe boost to apply during
62/// prefiltering so that the signal won't be damaged. This is
63/// conservative, assuming the worst case (the value oscillating
64/// between min and max). Instead of doing the 'proper' math, we
65/// take the easy route: build a periodic b-spline over min and max
66/// as the sole knot points, prefilter, get the coefficient with
67/// the highest absolute value. Then divide the maximal value
68/// of cf_type by this coefficient's absolute value.
69
70// TODO might put this function into the library code
71
73
74template < typename cf_type >
75static xlf_type max_boost ( xlf_type min , xlf_type max ,
76 const int & spline_degree )
77{
79 ( 2 , spline_degree , vspline::PERIODIC ) ;
80
81 sample.core[0] = min ;
82 sample.core[1] = max ;
83
84 sample.prefilter() ;
85
86 xlf_type d = std::max ( std::abs ( sample.core[0] ) ,
87 std::abs ( sample.core[1] ) ) ;
88
89 if ( d != 0 )
90 return std::numeric_limits<cf_type>::max() / d ;
91
92 return 1 ;
93}
94
95int main ( int argc , char * argv[] )
96{
97 double min_x = -1.0 ;
98 double max_x = 1.0 ;
99
100 // per default, apply maximum boost
101
102 double boost = max_boost<int> ( min_x , max_x , 3 ) ;
103
104 // user has passed a different value on the CL; use that instead
105
106 if ( argc > 1 )
107 boost = std::atof ( argv[1] ) ;
108
109 assert ( boost != 0.0 ) ;
110
111 // we'll create a spline over two know points only:
112
113 vigra::MultiArray < 1 , double > original ( 2 ) ;
114 original[0] = 1 ;
115 original[1] = -1 ;
116
117 // create a bspline object holding int coefficients
118
120
121 // prefilter with 'boost'
122
123 ibspl.prefilter ( original , boost ) ;
124
125 // create a reference b-spline with double coefficients over the
126 // same data, using no 'boost'.
127
129 bspl.prefilter ( original ) ;
130
131 // to compare the results of using the 'boosted' int spline with the
132 // 'ordinary' b-spline with double coefficients, we create evaluators
133 // of both types. the first evaluator, which takes int coefficients,
134 // is piped to an amplify_type object, which multiplies with a factor
135 // of 1/boost, putting the signal back in range.
136
137 // we need these template arguments, in sequence:
138 // evaluator taking float coordinates and yielding double, aggregating
139 // into SIMD types with 8 elements, using general b-spline evaluation,
140 // doing maths in double precision and using int spline coefficients:
141
142 typedef vspline::evaluator
143 < float , double , 8 , -1 , double , int > iev_t ;
144
145 // create such an evaluator from 'ibspl', the b-spline holding
146 // (boosted) int coefficients
147
148 iev_t _iev ( ibspl ) ;
149
150 // to 'undo' the boost we use an amplify_type object with a
151 // factor which is the reciprocal of 'boost'
152
153 auto attenuate = vspline::amplify_type
154 < double , double , double , 8 > ( 1.0 / boost ) ;
155
156 // chain 'attenuate' to the evaluator, so that the evaluator's
157 // output is multiplied with the factor in 'attenuate'
158
159 auto iev = _iev + attenuate ;
160
161 // the equivalent evaluator using the spline 'bspl' which holds
162 // double coefficients with no boost, first it's type, then the object
163
165
166 ev_t ev ( bspl ) ;
167
168 // now we call both evaluators at 0 and 1, the extrema,
169 // expecting to see the results 1 and -1, respectively.
170 // If boost is too low, we may find quantization errors,
171 // if it is too high, the signal will be damaged.
172
173 std::cout << "iev ( 0 ) = " << iev ( 0.0f ) << std::endl ;
174 std::cout << " ev ( 0 ) = " << ev ( 0.0f ) << std::endl ;
175 std::cout << "iev ( 1 ) = " << iev ( 1.0f ) << std::endl ;
176 std::cout << " ev ( 1 ) = " << ev ( 1.0f ) << std::endl ;
177
178 // just to doublecheck: vectorized operation with 'iev'
179
181 std::cout << iv << " -> " << iev ( iv ) << std::endl ;
183 std::cout << iv << " -> " << iev ( iv ) << std::endl ;
184
185 std::cout << "used boost = " << boost << std::endl ;
186}
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: int_spline.cc:95
long double xlf_type
Definition: common.h:102
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...
Definition: vector.h:459
@ PERIODIC
Definition: common.h:73
amplify_type amplifies it's input with a factor. If the data are multi-channel, the factor is multi-c...
class bspline now builds on class bspline_base, adding coefficient storage, while bspline_base provid...
Definition: bspline.h:499
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
includes all headers from vspline (most of them indirectly)