Milena (Olena)
User documentation 2.0a Id
|
00001 // Copyright (C) 2008, 2009 EPITA Research and Development Laboratory 00002 // (LRDE) 00003 // 00004 // This file is part of Olena. 00005 // 00006 // Olena is free software: you can redistribute it and/or modify it under 00007 // the terms of the GNU General Public License as published by the Free 00008 // Software Foundation, version 2 of the License. 00009 // 00010 // Olena is distributed in the hope that it will be useful, 00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 // General Public License for more details. 00014 // 00015 // You should have received a copy of the GNU General Public License 00016 // along with Olena. If not, see <http://www.gnu.org/licenses/>. 00017 // 00018 // As a special exception, you may use this file as part of a free 00019 // software project without restriction. Specifically, if other files 00020 // instantiate templates or use macros or inline functions from this 00021 // file, or you compile this file and link it with other files to produce 00022 // an executable, this file does not by itself cause the resulting 00023 // executable to be covered by the GNU General Public License. This 00024 // exception does not however invalidate any other reasons why the 00025 // executable file might be covered by the GNU General Public License. 00026 00027 #ifndef MLN_ACCU_TRANSFORM_LINE_HH 00028 # define MLN_ACCU_TRANSFORM_LINE_HH 00029 00042 00043 # include <mln/core/concept/image.hh> 00044 # include <mln/core/concept/meta_accumulator.hh> 00045 # include <mln/extension/adjust.hh> 00046 00047 00048 namespace mln 00049 { 00050 00051 namespace accu 00052 { 00053 00054 00055 template <typename A, typename I> 00056 mln_ch_value(I, mln_result(A)) 00057 transform_line(const Accumulator<A>& a, 00058 const Image<I>& input, 00059 unsigned length, unsigned dir); 00060 00061 template <typename A, typename I> 00062 mln_ch_value(I, mln_meta_accu_result(A, mln_value(I))) 00063 transform_line(const Meta_Accumulator<A>& a, 00064 const Image<I>& input, 00065 unsigned length, unsigned dir); 00066 00067 00068 00069 # ifndef MLN_INCLUDE_ONLY 00070 00071 00072 // Tests. 00073 00074 00075 namespace internal 00076 { 00077 00078 template <typename A, typename I> 00079 void 00080 transform_line_tests(const Accumulator<A>& a_, const Image<I>& input_) 00081 { 00082 A a = exact(a_); 00083 const I& input = exact(input_); 00084 00085 mln_precondition(input.is_valid()); 00086 mln_psite(I)* p; 00087 mln_precondition(sizeof(a.take(input(*p)), 0) == sizeof(int)); 00088 00089 (void) p; 00090 (void) a; 00091 (void) input; 00092 } 00093 00094 } // end of namespace mln::accu::internal 00095 00096 00097 00098 // Implementations. 00099 00100 00101 namespace impl 00102 { 00103 00104 namespace generic 00105 { 00106 00107 template <typename A, typename I> 00108 inline 00109 mln_ch_value(I, mln_result(A)) 00110 transform_line(const Accumulator<A>& a_, 00111 const Image<I>& input_, 00112 unsigned length, unsigned dir) 00113 { 00114 trace::entering("accu::impl::transform_line"); 00115 00116 const I& input = exact(input_); 00117 A a = exact(a_); 00118 00119 internal::transform_line_tests(a, input); 00120 00121 extension::adjust(input, length / 2); // Safety. 00122 00123 mln_ch_value(I, mln_result(A)) output; 00124 initialize(output, input); 00125 00126 typedef mln_psite(I) P; 00127 const P 00128 pmin = input.domain().pmin(), 00129 pmax = input.domain().pmax(); 00130 const def::coord 00131 pmax_dir = pmax[dir], 00132 pmin_dir = pmin[dir]; 00133 00134 P p = pmin, // Starting point. 00135 qt, qu; 00136 def::coord& p_dir = p [dir]; 00137 def::coord& qt_dir = qt[dir]; 00138 def::coord& qu_dir = qu[dir]; 00139 00140 do 00141 { 00142 00143 // Start the line. 00144 // --------------- 00145 00146 qt = p; 00147 qt_dir = p_dir - length / 2; 00148 qu = qt; 00149 a.init(); 00150 00151 for (unsigned i = 0; i < length; ++i) 00152 { 00153 if (input.has(qt)) 00154 a.take(input(qt)); 00155 qt_dir++; 00156 } 00157 if (input.has(p)) 00158 output(p) = a.to_result(); 00159 00160 // Browse the line. 00161 // ---------------- 00162 00163 while (p_dir < pmax_dir) 00164 { 00165 if (input.has(qt)) 00166 a.take(input(qt)); 00167 qt_dir++; 00168 00169 if (input.has(qu)) 00170 a.untake(input(qu)); 00171 qu_dir++; 00172 00173 ++p_dir; 00174 if (input.has(p)) 00175 output(p) = a.to_result(); 00176 } 00177 00178 // Go to the next line. 00179 // -------------------- 00180 00181 p_dir = pmin_dir; 00182 00183 for (int c = P::dim - 1; c >= 0; --c) 00184 { 00185 if (c == int(dir)) 00186 continue; 00187 if (p[c] != pmax[c]) 00188 { 00189 ++p[c]; 00190 break; 00191 } 00192 p[c] = pmin[c]; 00193 } 00194 00195 } while (p != pmin); 00196 00197 trace::exiting("accu::impl::transform_line"); 00198 return output; 00199 } 00200 00201 } // end of namespace mln::accu::impl::generic 00202 00203 00204 template <typename A, typename I> 00205 inline 00206 mln_ch_value(I, mln_result(A)) 00207 transform_line_fastest(const Accumulator<A>& a_, 00208 const Image<I>& input_, 00209 unsigned length, unsigned dir) 00210 { 00211 trace::entering("accu::impl::transform_line_fastest"); 00212 00213 const I& input = exact(input_); 00214 A a = exact(a_); 00215 00216 internal::transform_line_tests(a, input); 00217 00218 extension::adjust(input, length / 2); // Safety. 00219 00220 mln_ch_value(I, mln_result(A)) output; 00221 initialize(output, input); 00222 00223 typedef mln_psite(I) P; 00224 const P 00225 pmin = input.domain().pmin(), 00226 pmax = input.domain().pmax(); 00227 const def::coord 00228 pmax_dir = pmax[dir], 00229 pmin_dir = pmin[dir]; 00230 00231 P p = pmin; // Starting point. 00232 def::coord& p_dir = p[dir]; 00233 00234 // Step. 00235 mln_delta(P) dp(literal::zero); 00236 dp[dir] = 1; 00237 int step = input.delta_index(dp); 00238 00239 do 00240 { 00241 // Start the line. 00242 // --------------- 00243 00244 unsigned o_p = input.index_of_point(p); 00245 unsigned o_qt = o_p - (length / 2) * step; 00246 unsigned o_qu = o_qt; 00247 a.init(); 00248 00249 for (unsigned i = 0; i < length; ++i) 00250 // t o | x o o 00251 // ... 00252 // o o | x o t 00253 { 00254 a.take(input.element(o_qt)); 00255 o_qt += step; 00256 } 00257 output.element(o_p) = a.to_result(); 00258 00259 // Browse the line. 00260 // ---------------- 00261 00262 while (p_dir < pmax_dir) 00263 // u o | o x o t 00264 // ... 00265 // u o o x | o t 00266 { 00267 a.take(input.element(o_qt)); 00268 o_qt += step; 00269 00270 a.untake(input.element(o_qu)); 00271 o_qu += step; 00272 00273 ++p_dir; 00274 o_p += step; 00275 output.element(o_p) = a.to_result(); 00276 } 00277 00278 // Go to the next line. 00279 // -------------------- 00280 00281 p_dir = pmin_dir; 00282 00283 for (int c = P::dim - 1; c >= 0; --c) 00284 { 00285 if (c == int(dir)) 00286 continue; 00287 if (p[c] != pmax[c]) 00288 { 00289 ++p[c]; 00290 break; 00291 } 00292 p[c] = pmin[c]; 00293 } 00294 00295 } while (p != pmin); 00296 00297 trace::exiting("accu::impl::transform_line_fastest"); 00298 return output; 00299 } 00300 00301 /* 00302 00303 template <typename A, typename I> 00304 inline 00305 mln_ch_value(I, mln_result(A)) 00306 transform_line_fastest_without_border(const Accumulator<A>& a_, 00307 const Image<I>& input_, 00308 unsigned length, unsigned dir) 00309 { 00310 trace::entering("accu::impl::transform_line_fastest_without_border"); 00311 00312 const I& input = exact(input_); 00313 A a = exact(a_); 00314 00315 internal::transform_line_tests(a, input); 00316 00317 mln_ch_value(I, mln_result(A)) output; 00318 initialize(output, input); 00319 00320 typedef mln_psite(I) P; 00321 const P 00322 pmin = input.domain().pmin(), 00323 pmax = input.domain().pmax(); 00324 const def::coord 00325 pmax_dir = pmax[dir] - length / 2, 00326 pmin_dir = pmin[dir]; 00327 00328 P p = pmin; // Starting point. 00329 def::coord& p_dir = p [dir]; 00330 00331 // Step. 00332 mln_delta(P) dp(literal::zero); 00333 dp[dir] = 1; 00334 int step = input.delta_index(dp); 00335 00336 do 00337 { 00338 // Start the line. 00339 // --------------- 00340 00341 unsigned o_p = input.index_of_point(p); 00342 unsigned o_qt = o_p; 00343 unsigned o_qu = o_p; 00344 00345 a.init(); 00346 00347 // Causal part. 00348 for (unsigned i = 0; i <= length / 2; ++i) 00349 // | t 00350 // | x t 00351 // | x o t 00352 { 00353 a.take(input.element(o_qt)); 00354 o_qt += step; 00355 } 00356 output.element(o_p) = a.to_result(); 00357 00358 // Non-causal part. 00359 for (unsigned i = 0; i < length / 2; ++i) 00360 // | x o o <- end of previous loop 00361 // | o x o t 00362 // | o o x o t 00363 { 00364 a.take(input.element(o_qt)); 00365 o_qt += step; 00366 00367 ++p_dir; 00368 o_p += step; 00369 output.element(o_p) = a.to_result(); 00370 } 00371 00372 // Browse the line. 00373 // ---------------- 00374 00375 while (p_dir < pmax_dir) 00376 // from .. o o x o o .. 00377 // to .. u o o x o t .. 00378 { 00379 a.take(input.element(o_qt)); 00380 o_qt += step; 00381 00382 a.untake(input.element(o_qu)); 00383 o_qu += step; 00384 00385 ++p_dir; 00386 o_p += step; 00387 output.element(o_p) = a.to_result(); 00388 } 00389 00390 // Finalize. 00391 // --------- 00392 00393 for (unsigned i = 0; i < length / 2; ++i) 00394 // o o x o o | <- end of previous loop 00395 // u o o x o | 00396 // u o o x | 00397 { 00398 a.untake(input.element(o_qu)); 00399 o_qu += step; 00400 00401 o_p += step; 00402 output.element(o_p) = a.to_result(); 00403 } 00404 00405 // Go to the next line. 00406 // -------------------- 00407 00408 p_dir = pmin_dir; 00409 00410 for (int c = P::dim - 1; c >= 0; --c) 00411 { 00412 if (c == int(dir)) 00413 continue; 00414 if (p[c] != pmax[c]) 00415 { 00416 ++p[c]; 00417 break; 00418 } 00419 p[c] = pmin[c]; 00420 } 00421 00422 } while (p != pmin); 00423 00424 trace::exiting("accu::impl::transform_line_fastest_without_border"); 00425 return output; 00426 } 00427 00428 */ 00429 00430 } // end of namespace mln::accu::impl 00431 00432 00433 00434 00435 // Dispatch. 00436 00437 00438 namespace internal 00439 { 00440 00441 template <typename A, typename I> 00442 inline 00443 mln_ch_value(I, mln_result(A)) 00444 transform_line_dispatch(trait::image::speed::any, 00445 trait::accumulator::when_pix::any, 00446 const Accumulator<A>& a, 00447 const Image<I>& input, 00448 unsigned length, unsigned dir) 00449 { 00450 return impl::generic::transform_line(a, 00451 input, 00452 length, dir); 00453 } 00454 00455 template <typename A, typename I> 00456 inline 00457 mln_ch_value(I, mln_result(A)) 00458 transform_line_dispatch(trait::image::speed::fastest, 00459 trait::accumulator::when_pix::use_none, 00460 const Accumulator<A>& a, 00461 const Image<I>& input, 00462 unsigned length, unsigned dir) 00463 { 00464 return impl::transform_line_fastest(a, 00465 input, 00466 length, dir); 00467 } 00468 00469 template <typename A, typename I> 00470 inline 00471 mln_ch_value(I, mln_result(A)) 00472 transform_line_dispatch(trait::image::speed::fastest, 00473 trait::accumulator::when_pix::use_v, 00474 const Accumulator<A>& a, 00475 const Image<I>& input, 00476 unsigned length, unsigned dir) 00477 { 00478 return impl::transform_line_fastest(a, 00479 input, 00480 length, dir); 00481 } 00482 00483 template <typename A, typename I> 00484 inline 00485 mln_ch_value(I, mln_result(A)) 00486 transform_line_dispatch(const Accumulator<A>& a, 00487 const Image<I>& input, 00488 unsigned length, unsigned dir) 00489 { 00490 return transform_line_dispatch(mln_trait_image_speed(I)(), 00491 mln_trait_accumulator_when_pix(A)(), 00492 a, input, length, dir); 00493 } 00494 00495 } // end of namespace mln::accu::internal 00496 00497 00498 00499 00500 // Facades. 00501 00502 00503 template <typename A, typename I> 00504 inline 00505 mln_ch_value(I, mln_result(A)) 00506 transform_line(const Accumulator<A>& a, 00507 const Image<I>& input, 00508 unsigned length, unsigned dir) 00509 { 00510 trace::entering("accu::transform_line"); 00511 00512 internal::transform_line_tests(a, input); 00513 00514 extension::adjust(input, length / 2); // Safety. 00515 00516 mln_ch_value(I, mln_result(A)) output; 00517 output = internal::transform_line_dispatch(a, input, length, dir); 00518 00519 trace::exiting("accu::transform_line"); 00520 return output; 00521 } 00522 00523 00524 template <typename A, typename I> 00525 inline 00526 mln_ch_value(I, mln_meta_accu_result(A, mln_value(I))) 00527 transform_line(const Meta_Accumulator<A>& a, 00528 const Image<I>& input, 00529 unsigned length, unsigned dir) 00530 { 00531 trace::entering("accu::transform_line"); 00532 00533 typedef mln_accu_with(A, mln_value(I)) A_; 00534 A_ a_ = accu::unmeta(exact(a), mln_value(I)()); 00535 00536 internal::transform_line_tests(a_, input); 00537 00538 mln_ch_value(I, mln_result(A_)) output; 00539 output = internal::transform_line_dispatch(a_, input, length, dir); 00540 00541 trace::exiting("accu::transform_line"); 00542 return output; 00543 } 00544 00545 00546 # endif // ! MLN_INCLUDE_ONLY 00547 00548 } // end of namespace mln::accu 00549 00550 } // end of namespace mln 00551 00552 00553 #endif // ! MLN_ACCU_TRANSFORM_LINE_HH