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 }
00111
00112 }
00113
00114
00115
00116
00117
00118 #include <algorithm>
00119 #include <numeric>
00120 #include <dlrCommon/functional.h>
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
00165
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
00205 if(kernel.size() > signal.size()) {
00206 result = fillValue;
00207 return result;
00208 }
00209
00210
00211
00212
00213 const int kSizeOverTwo = static_cast<int>(kernel.size()) / 2;
00214
00215
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
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
00261 const int kSizeOverTwo = static_cast<int>(kernel.size()) / 2;
00262
00263
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
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
00332
00333
00334 Array1D<OutputType> accumulatedKernel = accumulateKernel<
00335 OutputType, KernelType, SignalType>(kernel, fillValue);
00336
00337
00338 const int kSizeOverTwo = static_cast<int>(kernel.size()) / 2;
00339
00340
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
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
00409 const int kSizeOverTwo = static_cast<int>(kernel.size()) / 2;
00410
00411
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
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
00499 const int kSizeOverTwo = static_cast<int>(kernel.size()) / 2;
00500
00501
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
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 }
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
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
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 }
00845
00846 }
00847
00848 #endif // #ifndef _DLR_NUMERIC_CONVOLVE1D_H_