00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #ifndef MLN_VALUE_INTERNAL_GRAY__HH
00027 # define MLN_VALUE_INTERNAL_GRAY__HH
00028
00032
00033 # include <iostream>
00034 # include <cmath>
00035
00036 # include <mln/metal/math/max.hh>
00037 # include <mln/metal/math/pow.hh>
00038
00039 # include <mln/value/concept/integer.hh>
00040 # include <mln/value/internal/value_like.hh>
00041
00042 # include <mln/value/graylevel_f.hh>
00043
00044 namespace mln
00045 {
00046
00047 namespace literal
00048 {
00050 struct black_t;
00051 struct white_t;
00053 }
00054
00055 namespace value
00056 {
00058 template <unsigned n>
00059 struct graylevel;
00060 template <unsigned N> class graylevel;
00061 class graylevel_f;
00062 namespace internal
00063 {
00064 template <unsigned n> class gray_;
00065 struct gray_f;
00066 }
00068 }
00069
00070
00071 namespace trait
00072 {
00073
00074 template < template <class, class> class Name, unsigned n, unsigned m>
00075 struct set_precise_binary_< Name, mln::value::internal::gray_<n>, mln::value::internal::gray_<m> >
00076 {
00077 typedef mln::value::internal::gray_< mlc_max_int(n, m) > ret;
00078 };
00079
00080 template <unsigned n, unsigned m>
00081 struct set_precise_binary_< op::greater, mln::value::internal::gray_<n>, mln::value::internal::gray_<m> >
00082 {
00083 typedef bool ret;
00084 };
00085
00086 template <unsigned n, unsigned m>
00087 struct set_precise_binary_< op::eq, mln::value::internal::gray_<n>, mln::value::internal::gray_<m> >
00088 {
00089 typedef bool ret;
00090 };
00091
00092
00093
00094 template <unsigned n>
00095 struct value_< mln::value::internal::gray_<n> >
00096 {
00097 private:
00098 typedef mln::value::internal::gray_<n> self_;
00099 public:
00100
00101 enum {
00102 nbits = 8 * (sizeof(unsigned) + sizeof(long)),
00103 card = 0
00104 };
00105
00106 typedef trait::value::nature::integer nature;
00107 typedef trait::value::kind::gray kind;
00108 typedef trait::value::quant::high quant;
00109
00110 static self_ min();
00111 static self_ max();
00112 static self_ epsilon();
00113
00114 typedef self_ sum;
00115 };
00116
00117 }
00118
00119
00120
00121 namespace value
00122 {
00123
00124 namespace internal
00125 {
00126
00129 template <unsigned n>
00130 class gray_
00131 :
00132 public Integer< gray_<n> >,
00133
00134 public internal::value_like_< int,
00135 int,
00136 gray_<n>,
00137 gray_<n> >
00138
00139 {
00140 public:
00141
00143 typedef int enc;
00144
00146 typedef int equiv;
00147
00149 gray_();
00151 gray_(int val);
00152
00154 explicit gray_(const literal::white_t&);
00155 explicit gray_(const literal::black_t&);
00157
00158
00160 template <unsigned m>
00161 gray_(const graylevel<m>& val);
00162 template <unsigned m>
00163 gray_<n>& operator=(const graylevel<m>& val);
00165
00167 int value() const;
00168
00170 template <unsigned m>
00171 operator gray_<m>() const;
00172
00174 template <unsigned m>
00175 operator graylevel<m>() const;
00176
00178 operator graylevel_f() const;
00179
00180 };
00181
00182
00183
00184
00185 template <unsigned n>
00186 std::ostream& operator<<(std::ostream& ostr, const gray_<n>& g);
00187
00188 template <unsigned n, unsigned m>
00189 bool operator==(const gray_<n>& lhs, const gray_<m>& rhs);
00190 template <unsigned n, unsigned m>
00191 bool operator<(const gray_<n>& lhs, const gray_<m>& rhs);
00192
00193 template <unsigned n, unsigned m>
00194 mln_trait_op_plus(gray_<n>, gray_<m>)
00195 operator+(const gray_<n>& lhs, const gray_<m>& rhs);
00196
00197 template <unsigned n, unsigned m>
00198 mln_trait_op_minus(gray_<n>, gray_<m>)
00199 operator-(const gray_<n>& lhs, const gray_<m>& rhs);
00200
00201 template <unsigned n>
00202 gray_<n> operator*(int s, const gray_<n>& rhs);
00203 template <unsigned n>
00204 gray_<n> operator*(const gray_<n>& lhs, int s);
00205 template <unsigned n>
00206 gray_<n> operator/(const gray_<n>& lhs, int s);
00207
00208 }
00209
00210 }
00211
00212 }
00213
00214
00215 # include <mln/value/internal/gray_f.hh>
00216
00217
00218 namespace mln
00219 {
00220
00221 # ifndef MLN_INCLUDE_ONLY
00222
00223 namespace value
00224 {
00225 namespace internal
00226 {
00227
00228 template <unsigned n_src, unsigned n_dest>
00229 inline
00230 long convert(int val)
00231 {
00232 using mln::metal::int_;
00233 typedef mlc_max(int_<n_dest - n_src> , int_<n_src - n_dest>) m;
00234
00235 if (n_dest == n_src)
00236 return val;
00237 else
00238 if (n_dest > n_src)
00239 return val * mlc_pow_int(2, m::value);
00240 else
00241 return val / mlc_pow_int(2, m::value);
00242 }
00243
00244
00245
00246 template <unsigned n>
00247 inline
00248 gray_<n>::gray_()
00249 {
00250 }
00251
00252 template <unsigned n>
00253 template <unsigned m>
00254 gray_<n>::gray_(const graylevel<m>& g)
00255 {
00256 this->v_ = convert<m, n>(g.value());
00257 }
00258
00259 template <unsigned n>
00260 template <unsigned m>
00261 inline
00262 gray_<n>&
00263 gray_<n>::operator=(const graylevel<m>& g)
00264 {
00265 this->v_ = convert<m, n>(g.value());
00266 return *this;
00267 }
00268
00269 template <unsigned n>
00270 inline
00271 gray_<n>::gray_(const literal::white_t&)
00272 {
00273 this->v_ = mlc_pow_int(2, n) - 1;
00274 }
00275
00276 template <unsigned n>
00277 inline
00278 gray_<n>::gray_(const literal::black_t&)
00279 {
00280 this->v_ = 0;
00281 }
00282
00283 template <unsigned n>
00284 inline
00285 gray_<n>::gray_(int val)
00286 {
00287 this->v_ = val;
00288 }
00289
00290 template <unsigned n>
00291 inline
00292 int
00293 gray_<n>::value() const
00294 {
00295 return this->v_;
00296 }
00297
00298 template <unsigned n>
00299 template <unsigned m>
00300 inline
00301 gray_<n>::operator gray_<m>() const
00302 {
00303 return gray_<m>(convert<n, m>(this->v_));
00304 }
00305
00306
00307 template <unsigned n>
00308 template <unsigned m>
00309 inline
00310 gray_<n>::operator graylevel<m>() const
00311 {
00312 graylevel<m> tmp(convert<n, m>(this->v_));
00313 mln_assertion(tmp.value() < std::pow(2.f, int(m)));
00314 return tmp;
00315 }
00316
00317
00318 template <unsigned n>
00319 inline
00320 gray_<n>::operator graylevel_f() const
00321 {
00322 static const float denom = float(metal::math::pow_int<2, n>::value) - 1.f;
00323 return graylevel_f(float(this->v_) / denom);
00324 }
00325
00326
00327
00328 template <unsigned n>
00329 inline
00330 std::ostream& operator<<(std::ostream& ostr, const gray_<n>& g)
00331 {
00332 return ostr << g.value() << "g/" << n << "bits";
00333 }
00334
00335 template <unsigned n, unsigned m>
00336 inline
00337 bool operator==(const gray_<n>& lhs, const gray_<m>& rhs)
00338 {
00339 if (n == m)
00340 return internal::gray_<mlc_max_int(n, m)>(lhs).value() ==
00341 internal::gray_<mlc_max_int(n, m)>(rhs).value();
00342 if (n > m)
00343 {
00344 gray_<n> down = rhs;
00345 gray_<n> up(down.value() +
00346 mlc_pow_int(2, m));
00347 return (lhs.value() >= down.value() && lhs.value() < up.value());
00348 }
00349 else
00350 {
00351 gray_<m> down = lhs;
00352 gray_<m> up(down.value() +
00353 mlc_pow_int(2, n));
00354 return (rhs.value() >= down.value() && rhs.value() < up.value());
00355 }
00356 }
00357
00358 template <unsigned n, unsigned m>
00359 inline
00360 bool operator<(const gray_<n>& lhs, const gray_<m>& rhs)
00361 {
00362 if (m == n)
00363 return lhs.value() < rhs.value();
00364 if (n > m)
00365 return lhs.value() < gray_<n>(rhs).value();
00366 else
00367 return gray_<m>(lhs).value() < rhs.value();
00368 }
00369
00370 template <unsigned n, unsigned m>
00371 inline
00372 mln_trait_op_plus(gray_<n>, gray_<m>)
00373 operator+(const gray_<n>& lhs, const gray_<m>& rhs)
00374 {
00375 typedef mln_trait_op_plus(gray_<n>, gray_<m>) ret;
00376 if (n > m)
00377 {
00378 ret tmp(ret(lhs).value() + ret(rhs).value());
00379 return tmp;
00380 }
00381 else
00382 {
00383 ret tmp(ret(lhs).value() + ret(rhs).value());
00384 return tmp;
00385 }
00386 }
00387
00388 template <unsigned n, unsigned m>
00389 inline
00390 mln_trait_op_minus(gray_<n>, gray_<m>)
00391 operator-(const gray_<n>& lhs, const gray_<m>& rhs)
00392 {
00393 typedef mln_trait_op_minus(gray_<n>, gray_<m>) ret;
00394
00395
00396 if (lhs == rhs)
00397 return ret(0);
00398 if (n == m)
00399 return ret(lhs.value() - rhs.value());
00400 if (n > m)
00401 {
00402 ret l = rhs;
00403 mln_assertion(lhs.value() >= l.value());
00404 ret tmp(lhs.value() - l.value());
00405 return tmp;
00406 }
00407 else
00408 {
00409 ret l = lhs;
00410 mln_assertion(l.value() >= rhs.value());
00411 ret tmp(l.value() - rhs.value());
00412 return tmp;
00413 }
00414 }
00415
00416 template <unsigned n, unsigned m>
00417 inline
00418 mln_trait_op_times(gray_<n>, gray_<m>)
00419 operator*(const gray_<n>& lhs, const gray_<m>& rhs)
00420 {
00421 typedef mln_trait_op_times(gray_<n>, gray_<m>) ret;
00422
00423 return ret(ret(lhs).value() * ret(rhs).value());
00424 }
00425
00426 template <unsigned n>
00427 inline
00428 gray_<n> operator*(int s, const gray_<n>& rhs)
00429 {
00430 gray_<n> tmp(rhs.value() * s);
00431 return tmp;
00432 }
00433
00434 template <unsigned n>
00435 inline
00436 gray_<n> operator*(const gray_<n>& lhs, int s)
00437 {
00438 gray_<n> tmp(lhs.value() * s);
00439 return tmp;
00440 }
00441
00442 template <unsigned n>
00443 inline
00444 gray_<n> operator/(const gray_<n>& lhs, int s)
00445 {
00446 mln_precondition(s != 0);
00447 gray_<n> tmp(lhs.value() / s);
00448 return tmp;
00449 }
00450
00451 }
00452
00453
00454
00455
00456
00457 template <typename I, unsigned n>
00458 inline
00459 bool
00460 operator==(const Integer<I>& lhs, const graylevel<n>& rhs)
00461 {
00462 return rhs.value() == exact(lhs);
00463 }
00464
00465
00466
00467 template <unsigned n, unsigned m>
00468 inline
00469 bool
00470 operator==(const graylevel<n>& lhs, const graylevel<m>& rhs)
00471 {
00472 return internal::gray_<n>(rhs) == internal::gray_<m>(lhs);
00473 }
00474
00475
00476
00477 template <unsigned n, unsigned m>
00478 inline
00479 mln_trait_op_plus(graylevel<n>, graylevel<m>)
00480 operator+(const graylevel<n>& lhs, const graylevel<m>& rhs)
00481 {
00482 return internal::gray_<n>(lhs) + internal::gray_<m>(rhs);
00483 }
00484
00485
00486 template <unsigned n, typename I>
00487 inline
00488 void
00489 operator+(const graylevel<n>& lhs, const I& i)
00490 {
00491 typename graylevel<n>::wrong_use_of_graylevel___Please_use_the__to_enc__method a;
00492 }
00493
00494
00495
00496 template <unsigned n, typename I>
00497 inline
00498 void
00499 operator+(const I& i, const graylevel<n>& rhs)
00500 {
00501 typename graylevel<n>::wrong_use_of_graylevel___Please_use_the__to_enc__method a;
00502 }
00503
00504
00505 template <unsigned n, unsigned m>
00506 inline
00507 mln_trait_op_minus(graylevel<n>, graylevel<m>)
00508 operator-(const graylevel<n>& lhs, const graylevel<m>& rhs)
00509 {
00510 return internal::gray_<n>(lhs) - internal::gray_<m>(rhs);
00511 }
00512
00513
00514 template <unsigned n, typename I>
00515 inline
00516 void
00517 operator-(const graylevel<n>& lhs, const I& i)
00518 {
00519 typename graylevel<n>::wrong_use_of_graylevel___Please_use_the__to_enc__method a;
00520 }
00521
00522
00523
00524 template <unsigned n, typename I>
00525 inline
00526 void
00527 operator-(const I& i, const graylevel<n>& rhs)
00528 {
00529 typename graylevel<n>::wrong_use_of_graylevel___Please_use_the__to_enc__method a;
00530 }
00531
00532
00533 template <unsigned n, unsigned m>
00534 inline
00535 mln_trait_op_times(graylevel<n>, graylevel<m>)
00536 operator*(const graylevel<n>& lhs, const graylevel<m>& rhs)
00537 {
00538 return internal::gray_<n>(lhs) * internal::gray_<m>(rhs);
00539 }
00540
00541
00542 template <unsigned n, typename I>
00543 inline
00544 internal::gray_<n>
00545 operator*(const graylevel<n>& lhs, const Integer<I>& rhs)
00546 {
00547 return internal::gray_<n>(lhs) * int(exact(rhs));
00548 }
00549
00550 template <typename I, unsigned n>
00551 inline
00552 mln_trait_op_times(I, graylevel<n>)
00553 operator*(const Integer<I>& lhs, const graylevel<n>& rhs)
00554 {
00555 return internal::gray_<n>(rhs) * int(exact(lhs));
00556 }
00557
00558
00559 template <unsigned n, typename F>
00560 inline
00561 mln_trait_op_times(graylevel<n>, F)
00562 operator*(const graylevel<n>& lhs, const Floating<F>& rhs)
00563 {
00564 return lhs.to_float() * float(exact(rhs));
00565 }
00566
00567 template <typename F, unsigned n>
00568 inline
00569 mln_trait_op_times(F, graylevel<n>)
00570 operator*(const Floating<F>& lhs, const graylevel<n>& rhs)
00571 {
00572 return rhs.to_float() * float(exact(lhs));
00573 }
00574
00575
00576 template <unsigned n, typename T>
00577 mln_trait_op_times(graylevel<n>, T)
00578 operator*(const graylevel<n>& lhs, const T& rhs)
00579 {
00580 return lhs * scalar_<T>(rhs);
00581 }
00582
00583 template <unsigned n, typename T>
00584 mln_trait_op_times(graylevel<n>, T)
00585 operator*(const T& lhs, const graylevel<n>& rhs)
00586 {
00587 return rhs * scalar_<T>(lhs);
00588 }
00589
00590
00591
00593 namespace internal
00594 {
00595 class gray_f;
00596 }
00598
00599 template <unsigned n, typename T>
00600 mln::value::internal::gray_f
00601 operator/(const graylevel<n>& lhs, const T& rhs)
00602 {
00603 return lhs / scalar_<T>(rhs);
00604 }
00605
00606
00607
00608 namespace internal
00609 {
00610
00611 template <typename ret>
00612 struct helper_gray__op_;
00613
00614 template <unsigned n>
00615 struct helper_gray__op_< gray_<n> >
00616 {
00617 template <unsigned m, typename S>
00618 inline static
00619 mln_trait_op_times(graylevel<m>, scalar_<S>)
00620 times(const graylevel<m>& lhs, const scalar_<S>& rhs)
00621 {
00622 typedef mln_trait_op_times(graylevel<m>, scalar_<S>) ret;
00623 ret tmp(typename ret::equiv
00624 (lhs.value() * typename ret::equiv(rhs.to_equiv())));
00625 return tmp;
00626 }
00627
00628 template <unsigned m, typename S>
00629 inline static
00630 mln_trait_op_times(graylevel<m>, scalar_<S>)
00631 div(const graylevel<m>& lhs, const scalar_<S>& rhs)
00632 {
00633 typedef mln_trait_op_times(graylevel<m>, scalar_<S>) ret;
00634 ret tmp(typename ret::equiv
00635 (lhs.value() / typename ret::equiv(rhs.to_equiv())));
00636 return tmp;
00637 }
00638 };
00639
00640 template <>
00641 struct helper_gray__op_< gray_f >
00642 {
00643 template <unsigned n, typename S>
00644 inline static
00645 mln_trait_op_times(graylevel<n>, scalar_<S>)
00646 times(const graylevel<n>& lhs, const scalar_<S>& rhs)
00647 {
00648 typedef mln_trait_op_times(graylevel<n>, scalar_<S>) ret;
00649 ret tmp(lhs.to_float() * typename ret::equiv(rhs.to_equiv()));
00650 return tmp;
00651 }
00652 template <unsigned n, typename S>
00653 inline static
00654 mln_trait_op_div(graylevel<n>, scalar_<S>)
00655 div(const graylevel<n>& lhs, const scalar_<S>& rhs)
00656 {
00657 typedef mln_trait_op_div(graylevel<n>, scalar_<S>) ret;
00658 ret tmp(typename ret::equiv
00659 (lhs.to_float() / typename ret::equiv(rhs.to_equiv())));
00660 return tmp;
00661 }
00662 };
00663
00664 }
00665
00666
00667 template <unsigned n, typename S>
00668 inline
00669 mln_trait_op_times(graylevel<n>, scalar_<S>)
00670 operator*(const graylevel<n>& lhs, const scalar_<S>& rhs)
00671 {
00672 typedef mln_trait_op_times(graylevel<n>, scalar_<S>) ret;
00673 return internal::helper_gray__op_<ret>::times(lhs, rhs);
00674 }
00675
00676
00677 template <unsigned n, typename S>
00678 inline
00679 mln_trait_op_div(graylevel<n>, scalar_<S>)
00680 operator/(const graylevel<n>& lhs, const scalar_<S>& rhs)
00681 {
00682 mln_precondition(rhs.to_equiv() != S(0));
00683 typedef mln_trait_op_div(graylevel<n>, scalar_<S>) ret;
00684 return internal::helper_gray__op_<ret>::div(lhs, rhs);
00685 }
00686
00687 }
00688
00689
00690
00691 namespace trait
00692 {
00693
00694
00695
00696 template <unsigned n>
00697 inline
00698 mln::value::internal::gray_<n>
00699 value_< mln::value::internal::gray_<n> >::min()
00700 {
00701 return mln::value::internal::gray_<n>(1, 0);
00702 }
00703
00704 template <unsigned n>
00705 inline
00706 mln::value::internal::gray_<n>
00707 value_< mln::value::internal::gray_<n> >::max()
00708 {
00709 return mln::value::internal::gray_<n>(1, 1);
00710 }
00711
00712 template <unsigned n>
00713 inline
00714 mln::value::internal::gray_<n>
00715 value_< mln::value::internal::gray_<n> >::epsilon()
00716 {
00717 return mln::value::internal::gray_<n>(1, 0);
00718 }
00719
00720 }
00721
00722
00723 # endif // ! MLN_INCLUDE_ONLY
00724
00725 }
00726
00727 #endif // ! MLN_VALUE_INTERNAL_GRAY__HH