optimized cv::pow for integer power
This commit is contained in:
@@ -2033,17 +2033,17 @@ static IPowFunc ipowTab[] =
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
static bool ocl_pow(InputArray _src, double power, OutputArray _dst)
|
||||
static bool ocl_pow(InputArray _src, double power, OutputArray _dst,
|
||||
bool is_ipower, int ipower)
|
||||
{
|
||||
int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
|
||||
bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0;
|
||||
|
||||
if ( !(_src.dims() <= 2 && (depth == CV_32F || depth == CV_64F)) ||
|
||||
(depth == CV_64F && !doubleSupport) )
|
||||
if (depth == CV_64F && !doubleSupport)
|
||||
return false;
|
||||
|
||||
bool issqrt = std::abs(power - 0.5) < DBL_EPSILON;
|
||||
const char * const op = issqrt ? "OP_SQRT" : "OP_POW";
|
||||
const char * const op = issqrt ? "OP_SQRT" : is_ipower ? "OP_POWN" : "OP_POW";
|
||||
|
||||
ocl::Kernel k("KF", ocl::core::arithm_oclsrc,
|
||||
format("-D dstT=%s -D %s -D UNARY_OP%s", ocl::typeToStr(CV_MAKE_TYPE(depth, 1)),
|
||||
@@ -2060,6 +2060,8 @@ static bool ocl_pow(InputArray _src, double power, OutputArray _dst)
|
||||
|
||||
if (issqrt)
|
||||
k.args(srcarg, dstarg);
|
||||
else if (is_ipower)
|
||||
k.args(srcarg, dstarg, ipower);
|
||||
else
|
||||
{
|
||||
if (depth == CV_32F)
|
||||
@@ -2076,39 +2078,35 @@ static bool ocl_pow(InputArray _src, double power, OutputArray _dst)
|
||||
|
||||
void pow( InputArray _src, double power, OutputArray _dst )
|
||||
{
|
||||
CV_OCL_RUN(_dst.isUMat(),
|
||||
ocl_pow(_src, power, _dst))
|
||||
|
||||
Mat src = _src.getMat();
|
||||
int type = src.type(), depth = src.depth(), cn = src.channels();
|
||||
|
||||
_dst.create( src.dims, src.size, type );
|
||||
Mat dst = _dst.getMat();
|
||||
|
||||
int ipower = cvRound(power);
|
||||
bool is_ipower = false;
|
||||
bool is_ipower = false, same = false;
|
||||
int type = _src.type(), depth = CV_MAT_DEPTH(type),
|
||||
cn = CV_MAT_CN(type), ipower = cvRound(power);
|
||||
|
||||
if( fabs(ipower - power) < DBL_EPSILON )
|
||||
{
|
||||
if( ipower < 0 )
|
||||
{
|
||||
divide( 1., src, dst );
|
||||
divide( 1., _src, _dst );
|
||||
if( ipower == -1 )
|
||||
return;
|
||||
ipower = -ipower;
|
||||
src = dst;
|
||||
same = true;
|
||||
}
|
||||
|
||||
switch( ipower )
|
||||
{
|
||||
case 0:
|
||||
dst = Scalar::all(1);
|
||||
_dst.createSameSize(_src, type);
|
||||
_dst.setTo(Scalar::all(1));
|
||||
return;
|
||||
case 1:
|
||||
src.copyTo(dst);
|
||||
_src.copyTo(_dst);
|
||||
return;
|
||||
case 2:
|
||||
multiply(src, src, dst);
|
||||
if (same)
|
||||
multiply(_dst, _dst, _dst);
|
||||
else
|
||||
multiply(_src, _src, _dst);
|
||||
return;
|
||||
default:
|
||||
is_ipower = true;
|
||||
@@ -2117,6 +2115,22 @@ void pow( InputArray _src, double power, OutputArray _dst )
|
||||
else
|
||||
CV_Assert( depth == CV_32F || depth == CV_64F );
|
||||
|
||||
CV_OCL_RUN(_dst.isUMat() && _src.dims() <= 2,
|
||||
ocl_pow(same ? _dst : _src, power, _dst, is_ipower, ipower))
|
||||
|
||||
Mat src, dst;
|
||||
if (same)
|
||||
{
|
||||
dst = _dst.getMat();
|
||||
src = dst;
|
||||
}
|
||||
else
|
||||
{
|
||||
src = _src.getMat();
|
||||
_dst.create( src.dims, src.size, type );
|
||||
dst = _dst.getMat();
|
||||
}
|
||||
|
||||
const Mat* arrays[] = {&src, &dst, 0};
|
||||
uchar* ptrs[2];
|
||||
NAryMatIterator it(arrays, ptrs);
|
||||
|
Reference in New Issue
Block a user