File: extrapolate.h

package info (click to toggle)
vspline 1.1.7-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,708 kB
  • sloc: cpp: 15,905; ansic: 443; sh: 17; makefile: 2
file content (229 lines) | stat: -rw-r--r-- 7,695 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
/************************************************************************/
/*                                                                      */
/*    vspline - a set of generic tools for creation and evaluation      */
/*              of uniform b-splines                                    */
/*                                                                      */
/*            Copyright 2015 - 2023 by Kay F. Jahnke                    */
/*                                                                      */
/*    The git repository for this software is at                        */
/*                                                                      */
/*    https://bitbucket.org/kfj/vspline                                 */
/*                                                                      */
/*    Please direct questions, bug reports, and contributions to        */
/*                                                                      */
/*    kfjahnke+vspline@gmail.com                                        */
/*                                                                      */
/*    Permission is hereby granted, free of charge, to any person       */
/*    obtaining a copy of this software and associated documentation    */
/*    files (the "Software"), to deal in the Software without           */
/*    restriction, including without limitation the rights to use,      */
/*    copy, modify, merge, publish, distribute, sublicense, and/or      */
/*    sell copies of the Software, and to permit persons to whom the    */
/*    Software is furnished to do so, subject to the following          */
/*    conditions:                                                       */
/*                                                                      */
/*    The above copyright notice and this permission notice shall be    */
/*    included in all copies or substantial portions of the             */
/*    Software.                                                         */
/*                                                                      */
/*    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND    */
/*    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES   */
/*    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND          */
/*    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT       */
/*    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,      */
/*    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING      */
/*    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR     */
/*    OTHER DEALINGS IN THE SOFTWARE.                                   */
/*                                                                      */
/************************************************************************/

/*! \file extrapolate.h

    \brief extrapolation of 1D data sets with specific boundary conditions
*/

#ifndef VSPLINE_EXTRAPOLATE_H
#define VSPLINE_EXTRAPOLATE_H

#include "common.h"

namespace vspline
{

/// struct extrapolator is a helper class providing extrapolated
/// values for a 1D buffer indexed with possibly out-of-range indices.
/// The extrapolated value is returned by value. boundary conditions
/// PERIODIC , MIRROR , REFLECT, NATURAL and CONSTANT are currently
/// supported.
/// An extrapolator is set up by passing the boundary condition code
/// (see common.h) and a const reference to the 1D data set, coded
/// as a 1D vigra::MultiArrayView. The view has to refer to valid data
/// for the time the extrapolator is in use.
/// Now the extrapolator object can be indexed with arbitrary indices,
/// and it will return extrapolated values. The indexing is done with
/// operator() rather than operator[] to mark the semantic difference.
/// Note how buffers with size 1 are treated specially for some
/// boundary conditions: here we simply return the value at index 0.

template < class buffer_type >
struct extrapolator
{
  const buffer_type & buffer ;
  typedef typename buffer_type::value_type value_type ;
  
  // we handle the polymorphism by calling the specific extrapolation
  // routine via a method pointer. This enables us to provide a uniform
  // interface without having to set up a virtual base class and inherit
  // from it.
  
  typedef value_type ( extrapolator::*p_xtr ) ( int i ) const ;
  p_xtr _p_xtr ;
  
  value_type extrapolate_mirror ( int i ) const
  {
    int w = buffer.size() - 1 ;

    if ( w == 0 )
      return buffer[0] ;

    i = std::abs ( i ) ;
    if ( i >= w )
    {
      i %= 2 * w ;
      i -= w ;
      i = std::abs ( i ) ;
      i = w - i ;
    }
    return buffer [ i ] ;
  }
  
  value_type extrapolate_natural ( int i ) const
  {
    int w = buffer.size() - 1 ;

    if ( w == 0 )
      return buffer[0] ;

    if ( i >= 0 && i <= w )
      return buffer[i] ;
    
    int sign = i < 0 ? -1 : 1 ;
    i = std::abs ( i ) ;
    
    int p = 2 * w ;
    int np = i / p ;
    int r = i % p ;
    value_type help ;
    
    if ( r <= w )
    {
      help = buffer[r] - buffer[0] ;
      help += np * 2 * ( buffer[w] - buffer[0] ) ;
      help *= sign ;
      help += buffer [ 0 ] ;
      return help ;
    }
    
    r = 2 * w - r ;
    help = 2 * ( buffer [ w ] - buffer [ 0 ] );
    help -= ( buffer[r] - buffer [ 0 ] ) ;
    help += np * 2 * ( buffer[w] - buffer[0] ) ;
    help *= sign ;
      help += buffer [ 0 ] ;
    return help ;
  }
  
  value_type extrapolate_reflect ( int i ) const
  {
    int w = buffer.size() ;
    if ( i < 0 )
      i = -1 - i ;
    if ( i >= w )
    {
      i %= 2 * w ;
      if ( i >= w )
        i = 2 * w - i - 1 ;
    }
    return buffer [ i ] ;
  }
  
  value_type extrapolate_periodic ( int i ) const
  {
    int w = buffer.size() ;
    
    if ( w == 1 )
      return buffer[0] ;

    if ( i < 0 || i >= w )
    {
      i %= w ;
      if ( i < 0 )
        i += w ;
    }
    return buffer [ i ] ;
  }
  
  value_type extrapolate_clamp ( int i ) const
  {
    if ( i < 0 )
      return buffer [ 0 ] ;
    int w = buffer.size() - 1 ;
    if ( i >= w )
      return buffer [ w ] ;
    return buffer [ i ] ;
  }
  
  value_type extrapolate_zeropad ( int i ) const
  {
    return value_type ( 0 ) ;
  }
  
  /// class extrapolator's constructor takes the boundary
  /// condition code and a const reference to the buffer.
  /// the specific extrapolation routine is picked in the
  /// case switch and assigned to the method pointer which
  /// will be invoked by operator().
  
  extrapolator ( vspline::bc_code bc , const buffer_type & _buffer )
  : buffer ( _buffer )
  {
    switch ( bc )
    {
      case vspline::PERIODIC :
        _p_xtr = & extrapolator::extrapolate_periodic ;
        break ;
      case vspline::REFLECT :
        _p_xtr = & extrapolator::extrapolate_reflect ;
        break ;
      case vspline::NATURAL :
        _p_xtr = & extrapolator::extrapolate_natural ;
        break ;
      case vspline::MIRROR :
        _p_xtr = & extrapolator::extrapolate_mirror ;
        break ;
      case vspline::GUESS :
      case vspline::CONSTANT :
        _p_xtr = & extrapolator::extrapolate_clamp ;
        break ;
      case vspline::ZEROPAD :
        _p_xtr = & extrapolator::extrapolate_zeropad ;
        break ;
      default:
        throw vspline::not_implemented
              ( "extrapolator: unknown boundary condition" ) ;
        break ;
    }
  }
  
  /// operator() uses the specific extrapolation method to provide
  /// a value for position i.
  
  value_type operator() ( const int & i ) const
  {
    return (this->*_p_xtr) ( i ) ;
  }
} ;

} ; // namespace vspline

#endif // #define VSPLINE_EXTRAPOLATE_H