saturate.hpp 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. // This file is part of OpenCV project.
  2. // It is subject to the license terms in the LICENSE file found in the top-level directory
  3. // of this distribution and at http://opencv.org/license.html.
  4. //
  5. // Copyright (C) 2018 Intel Corporation
  6. #ifndef OPENCV_GAPI_OWN_SATURATE_HPP
  7. #define OPENCV_GAPI_OWN_SATURATE_HPP
  8. #include <cmath>
  9. #include <limits>
  10. #include <type_traits>
  11. #include <opencv2/gapi/own/assert.hpp>
  12. namespace cv { namespace gapi { namespace own {
  13. //-----------------------------
  14. //
  15. // Numeric cast with saturation
  16. //
  17. //-----------------------------
  18. template<typename DST, typename SRC>
  19. static inline DST saturate(SRC x)
  20. {
  21. // only integral types please!
  22. GAPI_DbgAssert(std::is_integral<DST>::value &&
  23. std::is_integral<SRC>::value);
  24. if (std::is_same<DST, SRC>::value)
  25. return static_cast<DST>(x);
  26. if (sizeof(DST) > sizeof(SRC))
  27. return static_cast<DST>(x);
  28. // compiler must recognize this saturation,
  29. // so compile saturate<s16>(a + b) with adds
  30. // instruction (e.g.: _mm_adds_epi16 if x86)
  31. return x < std::numeric_limits<DST>::min()?
  32. std::numeric_limits<DST>::min():
  33. x > std::numeric_limits<DST>::max()?
  34. std::numeric_limits<DST>::max():
  35. static_cast<DST>(x);
  36. }
  37. // Note, that OpenCV rounds differently:
  38. // - like std::round() for add, subtract
  39. // - like std::rint() for multiply, divide
  40. template<typename DST, typename SRC, typename R>
  41. static inline DST saturate(SRC x, R round)
  42. {
  43. if (std::is_floating_point<DST>::value)
  44. {
  45. return static_cast<DST>(x);
  46. }
  47. else if (std::is_integral<SRC>::value)
  48. {
  49. GAPI_DbgAssert(std::is_integral<DST>::value &&
  50. std::is_integral<SRC>::value);
  51. return saturate<DST>(x);
  52. }
  53. else
  54. {
  55. GAPI_DbgAssert(std::is_integral<DST>::value &&
  56. std::is_floating_point<SRC>::value);
  57. #ifdef _WIN32
  58. // Suppress warning about convering x to floating-point
  59. // Note that x is already floating-point at this point
  60. #pragma warning(disable: 4244)
  61. #endif
  62. int ix = static_cast<int>(round(x));
  63. #ifdef _WIN32
  64. #pragma warning(default: 4244)
  65. #endif
  66. return saturate<DST>(ix);
  67. }
  68. }
  69. // explicit suffix 'd' for double type
  70. inline double ceild(double x) { return std::ceil(x); }
  71. inline double floord(double x) { return std::floor(x); }
  72. inline double roundd(double x) { return std::round(x); }
  73. inline double rintd(double x) { return std::rint(x); }
  74. } //namespace own
  75. } //namespace gapi
  76. } //namespace cv
  77. #endif /* OPENCV_GAPI_OWN_SATURATE_HPP */