aimstil  5.0.5
rf1.h
Go to the documentation of this file.
1 #ifndef TIL_RECURSIVE_FILTER1_H
2 #define TIL_RECURSIVE_FILTER1_H
3 
4 // includes from STL
5 #include <cassert>
6 #include <limits> // numeric_limits
7 #include <vector>
8 
9 // include from TIL library
10 #include "til/til_common.h"
11 #include "til/RecursiveFilter.h"
12 
13 
14 namespace til {
15 
16 
17 // 1st order recursive filter
18 
19 // direction = +1 : forward filter
20 // direction = -1 : backward filter
21 
22 template < typename T, int direction>
23 class RecursiveFilter<T, direction, 1>
24 {
25 public: // typedefs
26 
28 
29 public: // types
30 
31  // Boundary conditions of the recursive filter
32  // Zeros : values are supposed to be zero outside
33  // Constant : boundary values are duplicated to +/- infinity
34  // Mirror : image is assumed to have R/Z topology
35  enum BoundaryConditions { Zero, Constant, Mirror };
36 
37 public: // constuctors & destructor
38 
39  // Default constructor
40  RecursiveFilter() { m_boundaryConditions = Self::Constant; }
41 
42 public: // set & get
43 
44  // get filter coefficient for input
45  T getMI() const { return m_mi0; }
46  // get filter coefficient for output
47  T getMO() const { return m_mo0; }
48 
49  // Set filter coefficients
50  // The filter is output = mi0*input0 - mo0*output0
51  void setFilter(T mi0, T mo0)
52  {
53  m_mi0 = mi0;
54  m_mo0 = mo0;
55  }
56 
57  // Set boundary conditions
58  void setBoundaryConditions(BoundaryConditions bc) { m_boundaryConditions = bc; }
59 
60 
61 public: // methods
62 
63  // Apply filter to 'in' (of given length), result outputed in 'out'
64  // out has to be allocated with the same size as in
65  // NB: out and in cannot point to the same data
66  void apply(const std::vector<T> &in, std::vector<T> &out) const;
67 
68 
69 private: // methods
70 
71  // Multiplicative coefficient used for 'Constant' boundary condition
72 
73  T borderFactor() const { return m_mi0 /(1 + m_mo0); }
74 
75  T mirrorBC(const std::vector<T> &in, size_t length) const;
76 
77  T apply(T in0, T out0) const
78  {
79  return m_mi0 * in0 - m_mo0 * out0;
80  }
81 
82 private: // data
83 
84  // Boundary conditions
85  BoundaryConditions m_boundaryConditions;
86 
87  // Filter coefficients;
88  T m_mi0;
89  T m_mo0;
90 };
91 
92 
93 template < typename T, int direction >
94 void RecursiveFilter<T,direction,1>::apply(const std::vector<T> &in, std::vector<T> &out) const
95 {
96  assert(in.size() == out.size());
97 
98  size_t length = in.size();
99 
100  typename std::vector<T>::const_iterator pIn;
101  typename std::vector<T>::iterator pOut;
102 
103  if (direction == 1)
104  {
105  pIn = in.begin();
106  pOut = out.begin();
107  }
108  else if (direction == -1)
109  {
110  pIn = in.begin() + length - 1;
111  pOut = out.begin() + length - 1;
112  }
113 
114  T x0;
115  T y0 = 0; // useless initialization -- done just to avoid a warning.
116 
117  // Filter initialization on borders
118 
119  switch (m_boundaryConditions)
120  {
121  case Zero:
122  y0 = 0;
123  break;
124  case Constant:
125  y0 = *pIn * this->borderFactor();
126  case Mirror:
127  y0 = this->mirrorBC(in, length);
128  }
129 
130  for(size_t count = 0; count < length; ++count)
131  {
132  x0 = *pIn;
133  pIn += direction;
134  *pOut += y0 = this->apply(x0, y0);
135  pOut += direction;
136  }
137 }
138 
139 template < typename T, int direction >
140 T RecursiveFilter<T, direction,1>::mirrorBC(const std::vector<T> &in, size_t length) const
141 {
142  const T EPSILON = std::numeric_limits<T>::epsilon() * 128;
143  typename std::vector<T>::const_iterator pIn;
144  size_t count;
145 
146  if (direction == 1)
147  {
148  pIn = in.begin();
149  }
150  else if (direction == -1)
151  {
152  pIn == in.begin() + length - 1;
153  }
154 
155  T res = T(0);
156  T factor = m_mi0;
157 
158 
159  // One way...
160 
161  for(count = 0; count < length; ++count)
162  {
163  res += (*pIn)*factor;
164  factor *= m_mo0;
165  if (factor <= EPSILON) return res;
166  pIn += direction;
167  }
168 
169  // ...and back
170 
171  pIn -= direction;
172  for(count = 1; count < length; ++count)
173  {
174  res += (*pIn)*factor;
175  factor *= m_mo0;
176  if (factor <= EPSILON) return res;
177  pIn -= direction;
178  }
179 
180  return res / (1 - factor * m_mo0);
181 }
182 
183 } // namespace
184 
185 #endif
186 
INLINE void apply(const Affine< T1 > &a, const numeric_array< T2, 3 > &in, numeric_array< typename combine< T1, T2 >::type, 3 > &out)
Belongs to package Box Do not include directly, include til/Box.h instead.
Definition: Accumulator.h:10
General macros, definitions and functions.
RecursiveFilter< T, direction, 1 > Self
Definition: rf1.h:27
void setFilter(T mi0, T mo0)
Definition: rf1.h:51
void setBoundaryConditions(BoundaryConditions bc)
Definition: rf1.h:58