00001
00015 #ifndef _DLR_NUMERIC_CONVOLVE_H_
00016 #define _DLR_NUMERIC_CONVOLVE_H_
00017
00018 #include <dlrCommon/tags.h>
00019 #include <dlrNumeric/array1D.h>
00020 #include <dlrNumeric/convolutionStrategy.h>
00021
00022 namespace dlr {
00023
00024 namespace numeric {
00025
00028 template <class Type>
00029 inline Array1D<Type>
00030 convolve(const Array1D<Type>& kernel,
00031 const Array1D<Type>& signal,
00032 ConvolutionStrategy strategy = DLR_CONVOLVE_ZERO_PAD_RESULT);
00033
00034
00037 template <class Type0, class Type1>
00038 inline Array1D<Type1>
00039 convolve(const Array1D<Type0>& kernel,
00040 const Array1D<Type0>& signal,
00041 type_tag<Type1> resultTag,
00042 ConvolutionStrategy strategy = DLR_CONVOLVE_ZERO_PAD_RESULT);
00043
00044
00047 template <class Type>
00048 inline Array1D<Type>
00049 correlate(const Array1D<Type>& kernel,
00050 const Array1D<Type>& signal,
00051 ConvolutionStrategy strategy = DLR_CONVOLVE_ZERO_PAD_RESULT);
00052
00053
00056 template <class Type0, class Type1>
00057 Array1D<Type1>
00058 correlate(const Array1D<Type0>& kernel,
00059 const Array1D<Type0>& signal,
00060 type_tag<Type1> resultTag,
00061 ConvolutionStrategy strategy = DLR_CONVOLVE_ZERO_PAD_RESULT);
00062
00063
00064 }
00065
00066 }
00067
00068
00069
00070
00071 namespace dlr {
00072
00073 using numeric::convolve;
00074 using numeric::convolve;
00075 using numeric::correlate;
00076 using numeric::correlate;
00077
00078 }
00079
00080
00081
00082
00083
00084 #include <algorithm>
00085 #include <dlrNumeric/convolve1D.h>
00086
00087 namespace dlr {
00088
00089 namespace numeric {
00090
00092 namespace privateCode {
00093
00094 template <class Type0, class Type1>
00095 Array1D<Type1>
00096 oldCorrelateReflectSignal(const Array1D<Type0>& kernel,
00097 const Array1D<Type0>& signal,
00098 type_tag<Type1> resultTag)
00099 {
00100 if(kernel.size() % 2 != 1) {
00101 DLR_THROW(ValueException, "correlate()",
00102 "Argument kernel must have an odd number of elements.");
00103 }
00104 if(kernel.size() > signal.size()) {
00105 DLR_THROW(ValueException, "correlate()",
00106 "Argument kernel must not have more elements than "
00107 "argument signal.");
00108 }
00109
00110 Array1D<Type1> result(kernel.size() + signal.size() - 1);
00111 for(size_t borderIndex = 0; borderIndex < kernel.size() - 1;
00112 ++borderIndex) {
00113 Type1 dotProduct0 = static_cast<Type1>(0);
00114 Type1 dotProduct1 = static_cast<Type1>(0);
00115 size_t kernelIndex = 0;
00116 size_t signalIndex = (kernel.size() - borderIndex) - 1;
00117 while(kernelIndex < kernel.size() - borderIndex - 1) {
00118 dotProduct0 += kernel[kernelIndex] * signal[signalIndex];
00119 dotProduct1 +=
00120 kernel[(kernel.size() - kernelIndex) - 1]
00121 * signal[(signal.size() - signalIndex) - 1];
00122 ++kernelIndex;
00123 --signalIndex;
00124 }
00125 while(kernelIndex < kernel.size()) {
00126 dotProduct0 += kernel[kernelIndex] * signal[signalIndex];
00127 dotProduct1 +=
00128 kernel[(kernel.size() - kernelIndex) - 1]
00129 * signal[(signal.size() - signalIndex) - 1];
00130 ++kernelIndex;
00131 ++signalIndex;
00132 }
00133 result[borderIndex] = dotProduct0;
00134 result[(result.size() - borderIndex) - 1] = dotProduct1;
00135 }
00136
00137 correlate1DCommon<Type1, Type0, Type0>(
00138 kernel,
00139 signal.begin(),
00140 signal.end() - 2 * kernel.size() + 1,
00141 result.begin() + kernel.size() - 1);
00142 return result;
00143 }
00144
00145 }
00147
00148 template <class Type>
00149 inline Array1D<Type>
00150 convolve(const Array1D<Type>& kernel,
00151 const Array1D<Type>& signal,
00152 ConvolutionStrategy strategy)
00153 {
00154 return convolve(kernel, signal, type_tag<Type>(), strategy);
00155 }
00156
00157
00158 template <class Type0, class Type1>
00159 inline Array1D<Type1>
00160 convolve(const Array1D<Type0>& kernel,
00161 const Array1D<Type0>& signal,
00162 type_tag<Type1> resultTag,
00163 ConvolutionStrategy strategy)
00164 {
00165 Array1D<Type0> reversedKernel(kernel.size());
00166 std::reverse_copy(kernel.begin(), kernel.end(), reversedKernel.begin());
00167 return correlate(reversedKernel, signal, resultTag, strategy);
00168 }
00169
00170
00171
00172 template <class Type>
00173 inline Array1D<Type>
00174 correlate(const Array1D<Type>& kernel,
00175 const Array1D<Type>& signal,
00176 ConvolutionStrategy strategy)
00177 {
00178 return correlate(kernel, signal, type_tag<Type>(), strategy);
00179 }
00180
00181
00182 template <class Type0, class Type1>
00183 Array1D<Type1>
00184 correlate(const Array1D<Type0>& kernel,
00185 const Array1D<Type0>& signal,
00186 type_tag<Type1> resultTag,
00187 ConvolutionStrategy strategy)
00188 {
00189 switch(strategy) {
00190 case DLR_CONVOLVE_TRUNCATE_RESULT:
00191 return correlate1D<Type1>(
00192 kernel, signal, strategy, DLR_CONVOLVE_ROI_VALID);
00193 break;
00194 case DLR_CONVOLVE_ZERO_PAD_RESULT:
00195 return correlate1D<Type1>(
00196 kernel, signal, DLR_CONVOLVE_PAD_RESULT, DLR_CONVOLVE_ROI_SAME,
00197 static_cast<Type1>(0));
00198 break;
00199 case DLR_CONVOLVE_ZERO_PAD_SIGNAL:
00200 case DLR_CONVOLVE_WRAP_SIGNAL:
00201 return correlate1D<Type1>(
00202 kernel, signal, strategy, DLR_CONVOLVE_ROI_FULL);
00203 break;
00204 case DLR_CONVOLVE_REFLECT_SIGNAL:
00205 return privateCode::oldCorrelateReflectSignal(
00206 kernel, signal, type_tag<Type1>());
00207 break;
00208 default:
00209 DLR_THROW(LogicException, "correlate()",
00210 "Illegal value for strategy argument. "
00211 "This function is deprecated. "
00212 "Please consider using convolve1D() or correlate1D() "
00213 "instead.");
00214 break;
00215 }
00216 return Array1D<Type1>();
00217 }
00218
00219 }
00220
00221 }
00222
00223 #endif // #ifndef _DLR_NUMERIC_CONVOLVE_H_