00001
00002 #ifndef vnl_convolve_txx_
00003 #define vnl_convolve_txx_
00004
00005 #include "vnl_convolve.h"
00006 #include <vnl/algo/vnl_fft_1d.h>
00007 #include <vcl_cassert.h>
00008 #include <vcl_iostream.h>
00009
00010 template <class T1, class T2, class U>
00011 inline
00012 vnl_vector<U> vnl_convolve_cyclic_using_fft(vnl_vector<T1> const& v1, vnl_vector<T2> const& v2, U*)
00013 {
00014 assert (v1.size() == v2.size());
00015 unsigned int n = v1.size();
00016
00017 typedef vcl_complex<double> C;
00018 vnl_vector<C> w1(n, C(0)); for (unsigned i=0; i<n; ++i) w1[i]=v1[i];
00019 vnl_vector<C> w2(n, C(0)); for (unsigned i=0; i<n; ++i) w2[i]=v2[i];
00020
00021 vnl_fft_1d<double> fft(n); fft.fwd_transform(w1); fft.fwd_transform(w2);
00022 for (unsigned int i=0; i<n; ++i) w1[i] *= w2[i];
00023 fft.bwd_transform(w1);
00024 #ifdef DEBUG
00025 vcl_cout << w1 << vcl_endl;
00026 #endif
00027
00028 vnl_vector<U> r(n);
00029 for (unsigned int i = 0; i<n; ++i)
00030 r[i] = U(vcl_real(w1[i]) / n);
00031 #ifdef DEBUG
00032 for (unsigned int i = 0; i<n; ++i)
00033 assert(vcl_imag(w1[i]) == 0);
00034 #endif
00035 return r;
00036 }
00037
00038 template <class T1, class T2, class U>
00039 vnl_vector<U> vnl_convolve_cyclic(vnl_vector<T1> const& v1, vnl_vector<T2> const& v2, U*, bool use_fft)
00040 {
00041 assert (v1.size() == v2.size());
00042 unsigned int n = v1.size();
00043
00044
00045 if (n == 0) return vnl_vector<U>(0, U(0));
00046 if (n == 1) return vnl_vector<U>(1, U(v1[0]*v2[0]));
00047
00048 if (use_fft)
00049 return vnl_convolve_cyclic_using_fft(v1, v2, (U*)0);
00050
00051 vnl_vector<U> ret(n, (U)0);
00052 for (unsigned int k=0; k<n; ++k)
00053 {
00054 for (unsigned int i=0; i<=k; ++i)
00055 ret[k] += U(v1[k-i]) * U(v2[i]);
00056 for (unsigned int i=k+1; i<n; ++i)
00057 ret[k] += U(v1[n+k-i]) * U(v2[i]);
00058 }
00059
00060 return ret;
00061 }
00062
00063 inline bool has_only_primefactors_2_3_5(unsigned int n)
00064 {
00065 if (n <= 1) return true;
00066 while (n%2 == 0) n /= 2;
00067 while (n%3 == 0) n /= 3;
00068 while (n%5 == 0) n /= 5;
00069 return n==1;
00070 }
00071
00072 template <class T1, class T2, class U>
00073 inline
00074 vnl_vector<U> vnl_convolve_using_fft(vnl_vector<T1> const& v1, vnl_vector<T2> const& v2, U*, int n)
00075 {
00076 if (n+1 < int(v1.size() + v2.size())) n = v1.size() + v2.size() - 1;
00077
00078
00079 while (!has_only_primefactors_2_3_5(n)) ++n;
00080
00081
00082 vnl_vector<U> w1(n, U(0)); for (unsigned i=0; i<v1.size(); ++i) w1[i]=U(v1[i]);
00083 vnl_vector<U> w2(n, U(0)); for (unsigned i=0; i<v2.size(); ++i) w2[i]=U(v2[i]);
00084
00085 w1 = vnl_convolve_cyclic_using_fft(w1, w2, (U*)0);
00086
00087 return vnl_vector<U>(v1.size()+v2.size()-1, v1.size()+v2.size()-1, w1.data_block());
00088 }
00089
00090 template <class T>
00091 vnl_vector<T> vnl_convolve(vnl_vector<T> const& v1, vnl_vector<T> const& v2, int use_fft)
00092 {
00093
00094 if (v1.size() == 0 || v2.size() == 0)
00095 return vnl_vector<T>(0);
00096 if (v1.size() == 1) return v2*v1[0];
00097 if (v2.size() == 1) return v1*v2[0];
00098
00099 if (use_fft != 0)
00100 return vnl_convolve_using_fft(v1, v2, (T*)0, use_fft);
00101
00102 unsigned int n = v1.size() + v2.size() - 1;
00103 vnl_vector<T> ret(n, (T)0);
00104 for (unsigned int k=0; k<v1.size(); ++k)
00105 for (unsigned int i=0; i<=k && i<v2.size(); ++i)
00106 ret[k] += v1[k-i] * v2[i];
00107 for (unsigned int k=v1.size(); k<n; ++k)
00108 for (unsigned int i=k+1-v1.size(); i<=k && i<v2.size(); ++i)
00109 ret[k] += v1[k-i] * v2[i];
00110
00111 return ret;
00112 }
00113
00114 template <class T1, class T2, class U>
00115 vnl_vector<U> vnl_convolve(vnl_vector<T1> const& v1, vnl_vector<T2> const& v2, U*, int use_fft)
00116 {
00117
00118 if (v1.size() == 0 || v2.size() == 0)
00119 return vnl_vector<U>(0);
00120
00121 if (use_fft != 0)
00122 return vnl_convolve_using_fft(v1, v2, (U*)0, use_fft);
00123
00124 unsigned int n = v1.size() + v2.size() - 1;
00125 vnl_vector<U> ret(n, (U)0);
00126 for (unsigned int k=0; k<v1.size(); ++k)
00127 for (unsigned int i=0; i<=k && i<v2.size(); ++i)
00128 ret[k] += U(v1[k-i]) * U(v2[i]);
00129 for (unsigned int k=v1.size(); k<n; ++k)
00130 for (unsigned int i=k+1-v1.size(); i<=k && i<v2.size(); ++i)
00131 ret[k] += U(v1[k-i]) * U(v2[i]);
00132
00133 return ret;
00134 }
00135
00136 #undef VNL_CONVOLVE_INSTANTIATE
00137 #define VNL_CONVOLVE_INSTANTIATE_2(T,U) \
00138 template vnl_vector<U > vnl_convolve(vnl_vector<T > const&, vnl_vector<U > const&, U*, int); \
00139 template vnl_vector<U > vnl_convolve_cyclic(vnl_vector<T > const&, vnl_vector<U > const&, U*, bool)
00140
00141 #define VNL_CONVOLVE_INSTANTIATE(T,U) \
00142 VNL_CONVOLVE_INSTANTIATE_2(T,U); \
00143 template vnl_vector<T > vnl_convolve(vnl_vector<T > const&, vnl_vector<T > const&, int)
00144
00145 #endif // vnl_convolve_txx_