convolve1D.h

Go to the documentation of this file.
00001 
00015 #ifndef _DLR_NUMERIC_CONVOLVE1D_H_
00016 #define _DLR_NUMERIC_CONVOLVE1D_H_
00017 
00018 #include <dlrNumeric/array1D.h>
00019 #include <dlrNumeric/convolutionStrategy.h>
00020 
00021 namespace dlr {
00022 
00023   namespace numeric {
00024     
00025 
00027     template <class OutputType, class KernelType, class SignalType>
00028     inline Array1D<OutputType>
00029     convolve1D(const Array1D<KernelType>& kernel,
00030                const Array1D<SignalType>& signal,
00031                ConvolutionStrategy strategy = DLR_CONVOLVE_ZERO_PAD_RESULT,
00032                ConvolutionROI roi = DLR_CONVOLVE_ROI_SAME);
00033 
00034 
00036     template <class OutputType, class KernelType, class SignalType,
00037               class FillType>
00038     inline Array1D<OutputType>
00039     convolve1D(const Array1D<KernelType>& kernel,
00040                const Array1D<SignalType>& signal,
00041                ConvolutionStrategy strategy,
00042                ConvolutionROI roi,
00043                const FillType& fillValue);
00044   
00045 
00047     template <class OutputType, class KernelType, class SignalType>
00048     Array1D<OutputType>
00049     convolve1D(const Array1D<KernelType>& kernel,
00050                const Array1D<SignalType>& signal,
00051                ConvolutionStrategy strategy,
00052                int boundary0,
00053                int boundary1);
00054 
00055     
00057     template <class OutputType, class KernelType, class SignalType,
00058               class FillType>
00059     Array1D<OutputType>
00060     convolve1D(const Array1D<KernelType>& kernel,
00061                const Array1D<SignalType>& signal,
00062                ConvolutionStrategy strategy,
00063                int boundary0,
00064                int boundary1,
00065                const FillType& fillValue);
00066 
00067     
00069     template <class OutputType, class KernelType, class SignalType>
00070     inline Array1D<OutputType>
00071     correlate1D(const Array1D<KernelType>& kernel,
00072                 const Array1D<SignalType>& signal,
00073                 ConvolutionStrategy strategy = DLR_CONVOLVE_ZERO_PAD_RESULT,
00074                 ConvolutionROI roi = DLR_CONVOLVE_ROI_SAME);
00075 
00076 
00078     template <class OutputType, class KernelType, class SignalType,
00079               class FillType>
00080     Array1D<OutputType>
00081     correlate1D(const Array1D<KernelType>& kernel,
00082                 const Array1D<SignalType>& signal,
00083                 ConvolutionStrategy strategy,
00084                 ConvolutionROI roi,
00085                 const FillType& fillValue);
00086 
00087     
00089     template <class OutputType, class KernelType, class SignalType>
00090     Array1D<OutputType>
00091     correlate1D(const Array1D<KernelType>& kernel,
00092                 const Array1D<SignalType>& signal,
00093                 ConvolutionStrategy strategy,
00094                 int boundary0,
00095                 int boundary1);
00096 
00097     
00099     template <class OutputType, class KernelType, class SignalType,
00100               class FillType>
00101     Array1D<OutputType>
00102     correlate1D(const Array1D<KernelType>& kernel,
00103                 const Array1D<SignalType>& signal,
00104                 ConvolutionStrategy strategy,
00105                 int boundary0,
00106                 int boundary1,
00107                 const FillType& fillValue);
00108 
00109 
00110   } // namespace numeric
00111 
00112 } // namespace dlr
00113 
00114 
00115 /* ================ Definitions follow ================ */
00116 
00117 
00118 #include <algorithm> // For std::reverse_copy()
00119 #include <numeric> // For std::partial_sum()
00120 #include <dlrCommon/functional.h> // for clip()
00121 #include <dlrNumeric/numericTraits.h>
00122 
00123 namespace dlr {
00124 
00125   namespace numeric {
00126 
00128     namespace privateCode {
00129 
00130       template <class OutputType, class KernelType, class SignalType>
00131       Array1D<OutputType>
00132       accumulateKernel(const Array1D<KernelType>& kernel,
00133                        SignalType fillValue)
00134       {
00135         typedef typename NumericTraits<KernelType>::SumType KernelSumType;
00136         Array1D<KernelSumType> accumulatedKernel(kernel.size() + 1);
00137         accumulatedKernel[0] = static_cast<KernelSumType>(0);
00138         std::partial_sum(kernel.begin(), kernel.end(),
00139                          accumulatedKernel.begin() + 1);
00140 
00141         Array1D<OutputType> result(accumulatedKernel.size());
00142         for(size_t index0 = 0; index0 < result.size(); ++index0) {
00143           result[index0] = static_cast<OutputType>(
00144             accumulatedKernel[index0]
00145             * static_cast<OutputType>(fillValue));
00146         }
00147         return result;
00148       }
00149 
00150 
00151       template <class OutputType, class KernelType, class SignalType>
00152       void
00153       correlate1DCommon(
00154         const Array1D<KernelType>& kernel,
00155         typename Array1D<SignalType>::const_iterator signalBegin,
00156         typename Array1D<SignalType>::const_iterator signalEnd,
00157         typename Array1D<OutputType>::iterator resultIterator)
00158       {
00159         typedef typename Array1D<SignalType>::const_iterator SignalIterator;
00160         typedef typename Array1D<KernelType>::const_iterator KernelIterator;
00161 
00162         SignalIterator signalIterator = signalBegin;
00163         while(signalIterator != signalEnd) {
00164           // Calculate one dot-product between the kernel and the
00165           // current section of the signal.
00166           OutputType dotProduct = static_cast<OutputType>(0);
00167           SignalIterator signalIteratorCopy = signalIterator;
00168           KernelIterator kernelIterator = kernel.begin();
00169           while(kernelIterator != kernel.end()) {
00170             dotProduct += static_cast<OutputType>(
00171               *(kernelIterator++)
00172               * static_cast<OutputType>(*(signalIteratorCopy++)));;
00173           }
00174           *resultIterator = dotProduct;
00175           ++resultIterator;
00176           ++signalIterator;
00177         }
00178       }
00179 
00180 
00181       template <class OutputType, class KernelType, class SignalType>
00182       Array1D<OutputType>
00183       correlate1DTruncateResult(const Array1D<KernelType>& kernel,
00184                                 const Array1D<SignalType>& signal)
00185       {
00186         Array1D<OutputType> result(signal.size() - kernel.size() + 1);
00187         correlate1DCommon<OutputType, KernelType, SignalType>(
00188           kernel, signal.begin(), signal.end() - kernel.size() + 1,
00189           result.begin());
00190         return result;
00191       }
00192 
00193 
00194       template <class OutputType, class KernelType, class SignalType>
00195       Array1D<OutputType>
00196       correlate1DPadResult(const Array1D<KernelType>& kernel,
00197                            const Array1D<SignalType>& signal,
00198                            int boundary0,
00199                            int boundary1,
00200                            OutputType fillValue)
00201       {
00202         Array1D<OutputType> result(boundary1 - boundary0);
00203 
00204         // Check for degenerate case.
00205         if(kernel.size() > signal.size()) {
00206           result = fillValue;
00207           return result;
00208         }
00209 
00210         // Establish significant coordinates in the output image.
00211 
00212         // Constants specified without reference to signal or result.
00213         const int kSizeOverTwo = static_cast<int>(kernel.size()) / 2;
00214         
00215         // Constants specified with respect to argument signal.
00216         const int transitionIndex0 = kSizeOverTwo;
00217         const int transitionIndex1 = static_cast<int>(signal.size()) - kSizeOverTwo;
00218         const int clippedTransitionIndex0 =
00219           dlr::common::clip(transitionIndex0, boundary0, boundary1);
00220         const int clippedTransitionIndex1 =
00221           dlr::common::clip(transitionIndex1, boundary0, boundary1);
00222 
00223         // Constants specified with respect to result.
00224         const int resultTransitionIndex0 =
00225           clippedTransitionIndex0 - boundary0;
00226 
00227         int inputIndex = boundary0;
00228         int outputIndex = 0;
00229         while(inputIndex < clippedTransitionIndex0) {
00230           result[outputIndex] = fillValue;
00231           ++inputIndex;
00232           ++outputIndex;
00233         }
00234         inputIndex = clippedTransitionIndex1;
00235         outputIndex += clippedTransitionIndex1 - clippedTransitionIndex0;
00236         while(inputIndex < boundary1) {
00237           result[outputIndex] = fillValue;
00238           ++inputIndex;
00239           ++outputIndex;
00240         }
00241 
00242         correlate1DCommon<OutputType, KernelType, SignalType>(
00243           kernel,
00244           signal.begin() + clippedTransitionIndex0 - kSizeOverTwo,
00245           signal.begin() + clippedTransitionIndex1 - kSizeOverTwo,
00246           result.begin() + resultTransitionIndex0);
00247         return result;
00248       }
00249     
00250                    
00251       template <class OutputType, class KernelType, class SignalType>
00252       Array1D<OutputType>
00253       correlate1DZeroPadSignal(const Array1D<KernelType>& kernel,
00254                                const Array1D<SignalType>& signal,
00255                                int boundary0,
00256                                int boundary1)
00257       {
00258         Array1D<OutputType> result(boundary1 - boundary0);
00259 
00260         // Constants specified without reference to signal or result.
00261         const int kSizeOverTwo = static_cast<int>(kernel.size()) / 2;
00262         
00263         // Constants specified with respect to argument signal.
00264         const int transitionIndex0 = kSizeOverTwo;
00265         const int transitionIndex1 = static_cast<int>(signal.size()) - kSizeOverTwo;
00266         const int clippedTransitionIndex0 =
00267           dlr::common::clip(transitionIndex0, boundary0, boundary1);
00268         const int clippedTransitionIndex1 =
00269           dlr::common::clip(transitionIndex1, boundary0, boundary1);
00270 
00271         // Constants specified with respect to result.
00272         const int resultTransitionIndex0 =
00273           clippedTransitionIndex0 - boundary0;
00274 
00275         int inputIndex = boundary0;
00276         int outputIndex = 0;
00277         while(inputIndex < clippedTransitionIndex0) {
00278           OutputType dotProduct0 = static_cast<OutputType>(0);
00279           int kernelIndex = clippedTransitionIndex0 - inputIndex;
00280           size_t signalIndex = boundary0 + kSizeOverTwo;
00281           while(kernelIndex < static_cast<int>(kernel.size())) {
00282             dotProduct0 += static_cast<OutputType>(
00283               kernel[kernelIndex]
00284               * static_cast<OutputType>(signal[signalIndex]));
00285             ++kernelIndex;
00286             ++signalIndex;
00287           }
00288           result[outputIndex] = dotProduct0;
00289           ++inputIndex;
00290           ++outputIndex;
00291         }
00292 
00293         inputIndex = clippedTransitionIndex1;
00294         outputIndex += clippedTransitionIndex1 - clippedTransitionIndex0;
00295         while(inputIndex < boundary1) {
00296           OutputType dotProduct0 = static_cast<OutputType>(0);
00297           int kernelStopIndex = boundary1 - inputIndex;
00298           int kernelIndex = 0;
00299           size_t signalIndex = inputIndex - kSizeOverTwo;
00300           while(kernelIndex < kernelStopIndex) {
00301             dotProduct0 += static_cast<OutputType>(
00302               kernel[kernelIndex]
00303               * static_cast<OutputType>(signal[signalIndex]));
00304             ++kernelIndex;
00305             ++signalIndex;
00306           }
00307           result[outputIndex] = dotProduct0;
00308           ++inputIndex;
00309           ++outputIndex;
00310         }
00311         
00312         correlate1DCommon<OutputType, KernelType, SignalType>(
00313           kernel,
00314           signal.begin() + clippedTransitionIndex0 - kSizeOverTwo,
00315           signal.begin() + clippedTransitionIndex1 - kSizeOverTwo,
00316           result.begin() + resultTransitionIndex0);
00317         return result;
00318       }
00319 
00320 
00321       template <class OutputType, class KernelType, class SignalType>
00322       Array1D<OutputType>
00323       correlate1DPadSignal(const Array1D<KernelType>& kernel,
00324                            const Array1D<SignalType>& signal,
00325                            int boundary0,
00326                            int boundary1,
00327                            SignalType fillValue)
00328       {
00329         Array1D<OutputType> result(boundary1 - boundary0);
00330 
00331         // Precompute numbers which will make it easy to total up the
00332         // portions of the kernel which overlap padded areas of the
00333         // signal.
00334         Array1D<OutputType> accumulatedKernel = accumulateKernel<
00335           OutputType, KernelType, SignalType>(kernel, fillValue);
00336         
00337         // Constants specified without reference to signal or result.
00338         const int kSizeOverTwo = static_cast<int>(kernel.size()) / 2;
00339         
00340         // Constants specified with respect to argument signal.
00341         const int transitionIndex0 = kSizeOverTwo;
00342         const int transitionIndex1 = static_cast<int>(signal.size()) - kSizeOverTwo;
00343         const int clippedTransitionIndex0 =
00344           dlr::common::clip(transitionIndex0, boundary0, boundary1);
00345         const int clippedTransitionIndex1 =
00346           dlr::common::clip(transitionIndex1, boundary0, boundary1);
00347 
00348         // Constants specified with respect to result.
00349         const int resultTransitionIndex0 =
00350           clippedTransitionIndex0 - boundary0;
00351 
00352         int inputIndex = boundary0;
00353         int outputIndex = 0;
00354         while(inputIndex < clippedTransitionIndex0) {
00355           int kernelIndex = clippedTransitionIndex0 - inputIndex;
00356           size_t signalIndex = boundary0 + kSizeOverTwo;
00357           OutputType dotProduct0 = accumulatedKernel[kernelIndex];
00358           while(kernelIndex < static_cast<int>(kernel.size())) {
00359             dotProduct0 += static_cast<OutputType>(
00360               kernel[kernelIndex]
00361               * static_cast<OutputType>(signal[signalIndex]));
00362             ++kernelIndex;
00363             ++signalIndex;
00364           }
00365           result[outputIndex] = dotProduct0;
00366           ++inputIndex;
00367           ++outputIndex;
00368         }
00369 
00370         inputIndex = clippedTransitionIndex1;
00371         outputIndex += clippedTransitionIndex1 - clippedTransitionIndex0;
00372         while(inputIndex < boundary1) {
00373           int kernelStopIndex = boundary1 - inputIndex;
00374           int kernelIndex = 0;
00375           size_t signalIndex = inputIndex - kSizeOverTwo;
00376           OutputType dotProduct0 = (accumulatedKernel[kernel.size()]
00377                                     - accumulatedKernel[kernelStopIndex]);
00378           while(kernelIndex < kernelStopIndex) {
00379             dotProduct0 += static_cast<OutputType>(
00380               kernel[kernelIndex]
00381               * static_cast<OutputType>(signal[signalIndex]));
00382             ++kernelIndex;
00383             ++signalIndex;
00384           }
00385           result[outputIndex] = dotProduct0;
00386           ++inputIndex;
00387           ++outputIndex;
00388         }
00389         
00390         correlate1DCommon<OutputType, KernelType, SignalType>(
00391           kernel,
00392           signal.begin() + clippedTransitionIndex0 - kSizeOverTwo,
00393           signal.begin() + clippedTransitionIndex1 - kSizeOverTwo,
00394           result.begin() + resultTransitionIndex0);
00395         return result;
00396       }
00397 
00398 
00399       template <class OutputType, class KernelType, class SignalType>
00400       Array1D<OutputType>
00401       correlate1DReflectSignal(const Array1D<KernelType>& kernel,
00402                                const Array1D<SignalType>& signal,
00403                                int boundary0,
00404                                int boundary1)
00405       {
00406         Array1D<OutputType> result(boundary1 - boundary0);
00407 
00408         // Constants specified without reference to signal or result.
00409         const int kSizeOverTwo = static_cast<int>(kernel.size()) / 2;
00410         
00411         // Constants specified with respect to argument signal.
00412         const int transitionIndex0 = kSizeOverTwo;
00413         const int transitionIndex1 = static_cast<int>(signal.size()) - kSizeOverTwo;
00414         const int clippedTransitionIndex0 =
00415           dlr::common::clip(transitionIndex0, boundary0, boundary1);
00416         const int clippedTransitionIndex1 =
00417           dlr::common::clip(transitionIndex1, boundary0, boundary1);
00418 
00419         // Constants specified with respect to result.
00420         const int resultTransitionIndex0 =
00421           clippedTransitionIndex0 - boundary0;
00422 
00423         int inputIndex = boundary0;
00424         int outputIndex = 0;
00425         while(inputIndex < clippedTransitionIndex0) {
00426           OutputType dotProduct0 = static_cast<OutputType>(0);
00427 
00428           int kernelIndex = clippedTransitionIndex0 - inputIndex;
00429           size_t signalIndex = boundary0 + kSizeOverTwo;
00430           while(kernelIndex < static_cast<int>(kernel.size())) {
00431             dotProduct0 += static_cast<OutputType>(
00432               kernel[kernelIndex]
00433               * static_cast<OutputType>(signal[signalIndex]));
00434             ++kernelIndex;
00435             ++signalIndex;
00436           }
00437           kernelIndex = clippedTransitionIndex0 - inputIndex - 1;
00438           signalIndex = boundary0 + kSizeOverTwo;
00439           while(kernelIndex >= 0) {
00440             dotProduct0 += static_cast<OutputType>(
00441               kernel[kernelIndex]
00442               * static_cast<OutputType>(signal[signalIndex]));
00443             --kernelIndex;
00444             ++signalIndex;
00445           }
00446           result[outputIndex] = dotProduct0;
00447           ++inputIndex;
00448           ++outputIndex;
00449         }
00450 
00451 
00452         inputIndex = clippedTransitionIndex1;
00453         outputIndex += clippedTransitionIndex1 - clippedTransitionIndex0;
00454         while(inputIndex < boundary1) {
00455           OutputType dotProduct0 = static_cast<OutputType>(0);
00456 
00457           int kernelStopIndex = boundary1 - inputIndex;
00458           int kernelIndex = 0;
00459           size_t signalIndex = inputIndex - kSizeOverTwo;
00460           while(kernelIndex < kernelStopIndex) {
00461             dotProduct0 += static_cast<OutputType>(
00462               kernel[kernelIndex]
00463               * static_cast<OutputType>(signal[signalIndex]));
00464             ++kernelIndex;
00465             ++signalIndex;
00466           }
00467           --signalIndex;
00468           while(kernelIndex < static_cast<int>(kernel.size())) {
00469             dotProduct0 += static_cast<OutputType>(
00470               kernel[kernelIndex]
00471               * static_cast<OutputType>(signal[signalIndex]));
00472             ++kernelIndex;
00473             --signalIndex;
00474           }
00475           result[outputIndex] = dotProduct0;
00476           ++inputIndex;
00477           ++outputIndex;
00478         }
00479         
00480         correlate1DCommon<OutputType, KernelType, SignalType>(
00481           kernel,
00482           signal.begin() + clippedTransitionIndex0 - kSizeOverTwo,
00483           signal.begin() + clippedTransitionIndex1 - kSizeOverTwo,
00484           result.begin() + resultTransitionIndex0);
00485         return result;
00486       }
00487 
00488 
00489       template <class OutputType, class KernelType, class SignalType>
00490       Array1D<OutputType>
00491       correlate1DWrapSignal(const Array1D<KernelType>& kernel,
00492                             const Array1D<SignalType>& signal,
00493                             int boundary0,
00494                             int boundary1)
00495       {
00496         Array1D<OutputType> result(boundary1 - boundary0);
00497 
00498         // Constants specified without reference to signal or result.
00499         const int kSizeOverTwo = static_cast<int>(kernel.size()) / 2;
00500         
00501         // Constants specified with respect to argument signal.
00502         const int transitionIndex0 = kSizeOverTwo;
00503         const int transitionIndex1 = static_cast<int>(signal.size()) - kSizeOverTwo;
00504         const int clippedTransitionIndex0 =
00505           dlr::common::clip(transitionIndex0, boundary0, boundary1);
00506         const int clippedTransitionIndex1 =
00507           dlr::common::clip(transitionIndex1, boundary0, boundary1);
00508 
00509         // Constants specified with respect to result.
00510         const int resultTransitionIndex0 =
00511           clippedTransitionIndex0 - boundary0;
00512 
00513         int inputIndex = boundary0;
00514         int outputIndex = 0;
00515         while(inputIndex < clippedTransitionIndex0) {
00516           OutputType dotProduct0 = static_cast<OutputType>(0);
00517 
00518           int kernelIndex = clippedTransitionIndex0 - inputIndex;
00519           size_t signalIndex = boundary0 + kSizeOverTwo;
00520           while(kernelIndex < static_cast<int>(kernel.size())) {
00521             dotProduct0 += static_cast<OutputType>(
00522               kernel[kernelIndex]
00523               * static_cast<OutputType>(signal[signalIndex]));
00524             ++kernelIndex;
00525             ++signalIndex;
00526           }
00527           kernelIndex = clippedTransitionIndex0 - inputIndex - 1;
00528           signalIndex = signal.size() - 1;
00529           while(kernelIndex >= 0) {
00530             dotProduct0 += static_cast<OutputType>(
00531               kernel[kernelIndex]
00532               * static_cast<OutputType>(signal[signalIndex]));
00533             --kernelIndex;
00534             --signalIndex;
00535           }
00536           result[outputIndex] = dotProduct0;
00537           ++inputIndex;
00538           ++outputIndex;
00539         }
00540 
00541 
00542         inputIndex = clippedTransitionIndex1;
00543         outputIndex += clippedTransitionIndex1 - clippedTransitionIndex0;
00544         while(inputIndex < boundary1) {
00545           OutputType dotProduct0 = static_cast<OutputType>(0);
00546 
00547           int kernelStopIndex = boundary1 - inputIndex;
00548           int kernelIndex = 0;
00549           size_t signalIndex = inputIndex - kSizeOverTwo;
00550           while(kernelIndex < kernelStopIndex) {
00551             dotProduct0 += static_cast<OutputType>(
00552               kernel[kernelIndex]
00553               * static_cast<OutputType>(signal[signalIndex]));
00554             ++kernelIndex;
00555             ++signalIndex;
00556           }
00557           signalIndex = 0;
00558           while(kernelIndex < static_cast<int>(kernel.size())) {
00559             dotProduct0 += static_cast<OutputType>(
00560               kernel[kernelIndex]
00561               * static_cast<OutputType>(signal[signalIndex]));
00562             ++kernelIndex;
00563             ++signalIndex;
00564           }
00565           result[outputIndex] = dotProduct0;
00566           ++inputIndex;
00567           ++outputIndex;
00568         }
00569 
00570         correlate1DCommon<OutputType, KernelType, SignalType>(
00571           kernel,
00572           signal.begin() + clippedTransitionIndex0 - kSizeOverTwo,
00573           signal.begin() + clippedTransitionIndex1 - kSizeOverTwo,
00574           result.begin() + resultTransitionIndex0);
00575         return result;
00576       }
00577 
00578     } // namespace privateCode
00580 
00581 
00582     template <class OutputType, class KernelType, class SignalType>
00583     inline Array1D<OutputType>
00584     convolve1D(const Array1D<KernelType>& kernel,
00585                const Array1D<SignalType>& signal,
00586                ConvolutionStrategy strategy,
00587                ConvolutionROI roi)
00588     {
00589       Array1D<KernelType> reversedKernel(kernel.size());
00590       std::reverse_copy(kernel.begin(), kernel.end(), reversedKernel.begin());
00591       return correlate1D<OutputType, KernelType, SignalType>(
00592         reversedKernel, signal, strategy, roi);
00593     }
00594     
00595 
00596     template <class OutputType, class KernelType, class SignalType,
00597               class FillType>
00598     inline Array1D<OutputType>
00599     convolve1D(const Array1D<KernelType>& kernel,
00600                const Array1D<SignalType>& signal,
00601                ConvolutionStrategy strategy,
00602                ConvolutionROI roi,
00603                const FillType& fillValue)
00604     {
00605       Array1D<KernelType> reversedKernel(kernel.size());
00606       std::reverse_copy(kernel.begin(), kernel.end(), reversedKernel.begin());
00607       return correlate1D<OutputType, KernelType, SignalType>(
00608         reversedKernel, signal, strategy, roi, fillValue);
00609     }
00610     
00611 
00612     template <class OutputType, class KernelType, class SignalType>
00613     inline Array1D<OutputType>
00614     convolve1D(const Array1D<KernelType>& kernel,
00615                const Array1D<SignalType>& signal,
00616                ConvolutionStrategy strategy,
00617                int boundary0,
00618                int boundary1)
00619     {
00620       Array1D<KernelType> reversedKernel(kernel.size());
00621       std::reverse_copy(kernel.begin(), kernel.end(), reversedKernel.begin());
00622       return correlate1D<OutputType, KernelType, SignalType>(
00623         reversedKernel, signal, strategy, boundary0, boundary1);
00624     }
00625     
00626 
00627     template <class OutputType, class KernelType, class SignalType,
00628               class FillType>
00629     inline Array1D<OutputType>
00630     convolve1D(const Array1D<KernelType>& kernel,
00631                const Array1D<SignalType>& signal,
00632                ConvolutionStrategy strategy,
00633                int boundary0,
00634                int boundary1,
00635                const FillType& fillValue)
00636     {
00637       Array1D<KernelType> reversedKernel(kernel.size());
00638       std::reverse_copy(kernel.begin(), kernel.end(), reversedKernel.begin());
00639       return correlate1D<OutputType, KernelType, SignalType>(
00640         reversedKernel, signal, strategy, boundary0, boundary1, fillValue);
00641     }
00642     
00643 
00644     template <class OutputType, class KernelType, class SignalType>
00645     Array1D<OutputType>
00646     correlate1D(const Array1D<KernelType>& kernel,
00647                 const Array1D<SignalType>& signal,
00648                 ConvolutionStrategy strategy,
00649                 ConvolutionROI roi)
00650     {
00651       switch(roi) {
00652       case DLR_CONVOLVE_ROI_SAME:
00653       {
00654         int boundary0 = 0;
00655         int boundary1 = static_cast<int>(signal.size());
00656         return correlate1D<OutputType, KernelType, SignalType>(
00657           kernel, signal, strategy, boundary0, boundary1);
00658         break;
00659       }
00660       case DLR_CONVOLVE_ROI_VALID:
00661       {
00662         int boundary0 = static_cast<int>(kernel.size()) / 2;
00663         int boundary1 = static_cast<int>(signal.size()) - boundary0;
00664         return correlate1D<OutputType, KernelType, SignalType>(
00665           kernel, signal, strategy, boundary0, boundary1);
00666         break;
00667       }
00668       case DLR_CONVOLVE_ROI_FULL:
00669       {
00670         int boundary0 = -static_cast<int>(kernel.size()) / 2;
00671         int boundary1 = static_cast<int>(signal.size()) - boundary0;
00672         return correlate1D<OutputType, KernelType, SignalType>(
00673           kernel, signal, strategy, boundary0, boundary1);
00674         break;
00675       }
00676       default:
00677         DLR_THROW(LogicException, "correlate1D()",
00678                   "Illegal value for roi argument.");
00679         break;
00680       }
00681       return Array1D<OutputType>();
00682     }
00683     
00684 
00685     template <class OutputType, class KernelType, class SignalType,
00686               class FillType>
00687     Array1D<OutputType>
00688     correlate1D(const Array1D<KernelType>& kernel,
00689                 const Array1D<SignalType>& signal,
00690                 ConvolutionStrategy strategy,
00691                 ConvolutionROI roi,
00692                 const FillType& fillValue)
00693     {
00694       switch(roi) {
00695       case DLR_CONVOLVE_ROI_SAME:
00696       {
00697         int boundary0 = 0;
00698         int boundary1 = static_cast<int>(signal.size());
00699         return correlate1D<OutputType, KernelType, SignalType, FillType>(
00700           kernel, signal, strategy, boundary0, boundary1, fillValue);
00701         break;
00702       }
00703       case DLR_CONVOLVE_ROI_VALID:
00704       {
00705         int boundary0 = static_cast<int>(kernel.size()) / 2;
00706         int boundary1 = static_cast<int>(signal.size()) - boundary0;
00707         return correlate1D<OutputType, KernelType, SignalType, FillType>(
00708           kernel, signal, strategy, boundary0, boundary1, fillValue);
00709         break;
00710       }
00711       case DLR_CONVOLVE_ROI_FULL:
00712       {
00713         int boundary0 = -static_cast<int>(kernel.size()) / 2;
00714         int boundary1 = static_cast<int>(signal.size()) - boundary0;
00715         return correlate1D<OutputType, KernelType, SignalType, FillType>(
00716           kernel, signal, strategy, boundary0, boundary1, fillValue);
00717         break;
00718       }
00719       default:
00720         DLR_THROW(LogicException, "correlate1D()",
00721                   "Illegal value for roi argument.");
00722         break;
00723       }
00724       return Array1D<OutputType>();
00725     }
00726 
00727     
00728     template <class OutputType, class KernelType, class SignalType>
00729     Array1D<OutputType>
00730     correlate1D(const Array1D<KernelType>& kernel,
00731                 const Array1D<SignalType>& signal,
00732                 ConvolutionStrategy strategy,
00733                 int boundary0,
00734                 int boundary1)
00735     {
00736       if(kernel.size() % 2 != 1) {
00737         DLR_THROW(ValueException, "correlate1D()",
00738                   "Argument kernel must have an odd number of elements.");
00739       }
00740       // Note(xxx): is the following check necessary?
00741       if(kernel.size() > signal.size()) {
00742         DLR_THROW(ValueException, "correlate1D()",
00743                   "Argument kernel must not have more elements than "
00744                   "argument signal.");
00745       }
00746 
00747       switch(strategy) {
00748       case DLR_CONVOLVE_TRUNCATE_RESULT:
00749         return privateCode::correlate1DTruncateResult<
00750           OutputType, KernelType, SignalType>(kernel, signal);
00751         break;
00752       case DLR_CONVOLVE_PAD_RESULT:
00753       case DLR_CONVOLVE_ZERO_PAD_RESULT:
00754       case DLR_CONVOLVE_PAD_SIGNAL:
00755         DLR_THROW(ValueException, "correlate1D()",
00756                   "The specified convolution strategy requires that a "
00757                   "fill value be specified.");
00758       case DLR_CONVOLVE_ZERO_PAD_SIGNAL:
00759         return privateCode::correlate1DZeroPadSignal<
00760           OutputType, KernelType, SignalType>(
00761             kernel, signal, boundary0, boundary1);
00762         break;
00763       case DLR_CONVOLVE_REFLECT_SIGNAL:
00764         return privateCode::correlate1DReflectSignal<
00765           OutputType, KernelType, SignalType>(
00766             kernel, signal, boundary0, boundary1);
00767         break;
00768       case DLR_CONVOLVE_WRAP_SIGNAL:
00769         return privateCode::correlate1DWrapSignal<
00770           OutputType, KernelType, SignalType>(
00771             kernel, signal, boundary0, boundary1);
00772         break;
00773       default:
00774         DLR_THROW(LogicException, "correlate1D()",
00775                   "Illegal value for strategy argument.");
00776         break;
00777       }
00778       return Array1D<OutputType>();
00779     }
00780     
00781 
00782     template <class OutputType, class KernelType, class SignalType,
00783               class FillType>
00784     Array1D<OutputType>
00785     correlate1D(const Array1D<KernelType>& kernel,
00786                 const Array1D<SignalType>& signal,
00787                 ConvolutionStrategy strategy,
00788                 int boundary0,
00789                 int boundary1,
00790                 const FillType& fillValue)
00791     {
00792       if(kernel.size() % 2 != 1) {
00793         DLR_THROW(ValueException, "correlate1D()",
00794                   "Argument kernel must have an odd number of elements.");
00795       }
00796       // Note(xxx): is the following check necessary?
00797       if(kernel.size() > signal.size()) {
00798         DLR_THROW(ValueException, "correlate1D()",
00799                   "Argument kernel must not have more elements than "
00800                   "argument signal.");
00801       }
00802 
00803       switch(strategy) {
00804       case DLR_CONVOLVE_TRUNCATE_RESULT:
00805         return privateCode::correlate1DTruncateResult<
00806           OutputType, KernelType, SignalType>(kernel, signal);
00807         break;
00808       case DLR_CONVOLVE_PAD_RESULT:
00809       case DLR_CONVOLVE_ZERO_PAD_RESULT:
00810         return privateCode::correlate1DPadResult<
00811           OutputType, KernelType, SignalType>(
00812             kernel, signal, boundary0, boundary1,
00813             static_cast<OutputType>(fillValue));
00814         break;
00815       case DLR_CONVOLVE_PAD_SIGNAL:
00816         return privateCode::correlate1DPadSignal<
00817           OutputType, KernelType, SignalType>(
00818             kernel, signal, boundary0, boundary1,
00819             static_cast<SignalType>(fillValue));
00820         break;
00821       case DLR_CONVOLVE_ZERO_PAD_SIGNAL:
00822         return privateCode::correlate1DZeroPadSignal<
00823           OutputType, KernelType, SignalType>(
00824             kernel, signal, boundary0, boundary1);
00825         break;
00826       case DLR_CONVOLVE_REFLECT_SIGNAL:
00827         return privateCode::correlate1DReflectSignal<
00828           OutputType, KernelType, SignalType>(
00829             kernel, signal, boundary0, boundary1);
00830         break;
00831       case DLR_CONVOLVE_WRAP_SIGNAL:
00832         return privateCode::correlate1DWrapSignal<
00833           OutputType, KernelType, SignalType>(
00834             kernel, signal, boundary0, boundary1);
00835         break;
00836       default:
00837         DLR_THROW(LogicException, "correlate1D()",
00838                   "Illegal value for strategy argument.");
00839         break;
00840       }
00841       return Array1D<OutputType>();
00842     }
00843 
00844   } // namespace numeric
00845 
00846 } // namespace dlr
00847 
00848 #endif // #ifndef _DLR_NUMERIC_CONVOLVE1D_H_

Generated on Mon Jul 9 20:34:02 2007 for dlrLibs Utility Libraries by  doxygen 1.5.2