#pragma once
#include <cassert>
#include <climits>
#include <cmath>
#include <cstddef>
#include "./aligned_allocator.h"
#include "./common.h"
#include "src/common/utils.h"
#include "megdnn/basic_types.h"
#include "megdnn/opr_param_defs.h"
#if defined(__SSE2__)
#include <xmmintrin.h>
#endif
#define MegCVException(expr) \
do { \
megdnn_throw(#expr); \
} while (0)
namespace megdnn {
namespace megcv {
template <typename T>
using AlignedVector = std::vector<T, ah::aligned_allocator<T, 16>>;
static inline size_t align_size(size_t sz, int n) {
megdnn_assert((n & (n - 1)) == 0);
return (sz + n - 1) & -n;
}
static inline int clip(int x, int a, int b) {
return x >= a ? (x < b ? x : b - 1) : a;
}
template <typename _Tp>
static inline _Tp* align_ptr(_Tp* ptr, int n = (int)sizeof(_Tp)) {
return (_Tp*)(((size_t)ptr + n - 1) & -n);
}
template <typename T>
inline T saturate(T x, T lower, T upper) {
return (x < lower ? lower : (x >= upper ? upper - 1 : x));
}
template <typename T>
T modf(T x, T* iptr) {
T ival;
T rval(std::modf(x, &ival));
*iptr = ival;
return rval;
}
template <typename T>
int round(T value) {
T intpart, fractpart;
fractpart = modf(value, &intpart);
if ((fabs(fractpart) != 0.5) || ((((int)intpart) % 2) != 0))
return (int)(value + (value >= 0 ? 0.5 : -0.5));
else
return (int)intpart;
}
template <typename DT, typename ST>
static inline DT saturate_cast(ST x) {
return x;
}
template <>
inline unsigned char saturate_cast<unsigned char, int>(int x) {
return (unsigned char)((unsigned)x <= UCHAR_MAX ? x : x > 0 ? UCHAR_MAX : 0);
}
template <>
inline short saturate_cast<short, int>(int x) {
return (short)((unsigned)(x - SHRT_MIN) <= (unsigned)USHRT_MAX
? x
: x > 0 ? SHRT_MAX : SHRT_MIN);
}
template <typename ST>
static inline int cv_round(ST value);
template <>
inline int cv_round<float>(float value) {
#if defined(__SSE2__)
__m128 t = _mm_set_ss(value);
return _mm_cvtss_si32(t);
#elif defined(__GNUC__)
return (int)lrintf(value);
#else
return (int)(value + (value >= 0 ? 0.5f : -0.5f));
#endif
}
template <>
inline int cv_round<double>(double value) {
#if defined(__SSE2__)
__m128d t = _mm_set_sd(value);
return _mm_cvtsd_si32(t);
#elif defined(__GNUC__)
return (int)lrint(value);
#else
return (int)(value + (value >= 0 ? 0.5f : -0.5f));
#endif
}
template <>
inline int saturate_cast<int, float>(float x) {
return cv_round(x);
}
template <>
inline short saturate_cast<short, float>(float x) {
return saturate_cast<short, int>(saturate_cast<int, float>(x));
}
template <>
inline int saturate_cast<int, double>(double x) {
return cv_round(x);
}
template <typename ST, typename DT, int bits>
struct FixedPtCast {
typedef ST type1;
typedef DT rtype;
enum { SHIFT = bits, DELTA = 1 << (bits - 1) };
DT operator()(ST val) const { return saturate_cast<DT>((val + DELTA) >> SHIFT); }
};
template <typename ST, typename DT>
struct FixedPtCastEx {
typedef ST type1;
typedef DT rtype;
FixedPtCastEx() : SHIFT(0), DELTA(0) {}
FixedPtCastEx(int bits) : SHIFT(bits), DELTA(bits ? 1 << (bits - 1) : 0) {}
DT operator()(ST val) const { return saturate_cast<DT>(val + DELTA); }
int SHIFT, DELTA;
};
template <>
struct FixedPtCastEx<int, uchar> {
typedef int type1;
typedef uchar rtype;
FixedPtCastEx() : SHIFT(0), DELTA(0) {}
FixedPtCastEx(int bits) : SHIFT(bits), DELTA(bits ? 1 << (bits - 1) : 0) {}
uchar operator()(int val) const {
return saturate_cast<uchar>((val + DELTA) >> SHIFT);
}
int SHIFT, DELTA;
};
template <typename ST, typename DT>
struct Cast {
typedef ST type1;
typedef DT rtype;
DT operator()(ST val) const { return saturate_cast<DT>(val); }
};
template <param::WarpPerspective::BorderMode bmode>
static inline int border_interpolate(int p, int len) {
using BorderMode = param::WarpPerspective::BorderMode;
if ((unsigned)p < (unsigned)len)
;
else if (bmode == BorderMode::BORDER_REPLICATE)
p = p < 0 ? 0 : len - 1;
else if (
bmode == BorderMode::BORDER_REFLECT ||
bmode == BorderMode::BORDER_REFLECT_101) {
int delta = (bmode == BorderMode::BORDER_REFLECT_101);
if (len == 1)
return 0;
do {
if (p < 0)
p = -p - 1 + delta;
else
p = len - 1 - (p - len) - delta;
} while ((unsigned)p >= (unsigned)len);
} else if (bmode == BorderMode::BORDER_WRAP) {
if (p < 0)
p -= ((p - len + 1) / len) * len;
while (p >= len) {
p -= len;
}
} else if (
bmode == BorderMode::BORDER_CONSTANT ||
bmode == BorderMode::BORDER_TRANSPARENT)
p = -1;
else
megdnn_throw("Unknown/unsupported border type");
return p;
}
namespace gaussian_blur {
using BorderMode = param::GaussianBlur::BorderMode;
#include "./bordermode-inl.h"
}
} }