/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// Intel License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000, Intel Corporation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of Intel Corporation may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "_cxcore.h"
/****************************************************************************************\
* N o r m *
\****************************************************************************************/
#define ICV_NORM_CASE( _op_, \
_update_op_, worktype, len ) \
\
for( ; x <= (len) - 4; x += 4 ) \
{ \
worktype t0 = (src)[x]; \
worktype t1 = (src)[x+1]; \
t0 = _op_(t0); \
t1 = _op_(t1); \
norm = _update_op_( norm, t0 ); \
norm = _update_op_( norm, t1 ); \
\
t0 = (src)[x+2]; \
t1 = (src)[x+3]; \
t0 = _op_(t0); \
t1 = _op_(t1); \
norm = _update_op_( norm, t0 ); \
norm = _update_op_( norm, t1 ); \
} \
\
for( ; x < (len); x++ ) \
{ \
worktype t0 = (src)[x]; \
t0 = (worktype)_op_(t0); \
norm = _update_op_( norm, t0 ); \
}
#define ICV_NORM_COI_CASE( _op_, \
_update_op_, worktype, len, cn ) \
\
for( ; x < (len); x++ ) \
{ \
worktype t0 = (src)[x*(cn)]; \
t0 = (worktype)_op_(t0); \
norm = _update_op_( norm, t0 ); \
}
#define ICV_NORM_DIFF_CASE( _op_, \
_update_op_, worktype, len ) \
\
for( ; x <= (len) - 4; x += 4 ) \
{ \
worktype t0 = (src1)[x] - (src2)[x];\
worktype t1 = (src1)[x+1]-(src2)[x+1];\
\
t0 = _op_(t0); \
t1 = _op_(t1); \
\
norm = _update_op_( norm, t0 ); \
norm = _update_op_( norm, t1 ); \
\
t0 = (src1)[x+2] - (src2)[x+2]; \
t1 = (src1)[x+3] - (src2)[x+3]; \
\
t0 = _op_(t0); \
t1 = _op_(t1); \
\
norm = _update_op_( norm, t0 ); \
norm = _update_op_( norm, t1 ); \
} \
\
for( ; x < (len); x++ ) \
{ \
worktype t0 = (src1)[x] - (src2)[x];\
t0 = (worktype)_op_(t0); \
norm = _update_op_( norm, t0 ); \
}
#define ICV_NORM_DIFF_COI_CASE( _op_, _update_op_, worktype, len, cn ) \
for( ; x < (len); x++ ) \
{ \
worktype t0 = (src1)[x*(cn)] - (src2)[x*(cn)]; \
t0 = (worktype)_op_(t0); \
norm = _update_op_( norm, t0 ); \
}
/*
The algorithm and its multiple variations below
below accumulates the norm by blocks of size "block_size".
Each block may span across multiple lines and it is
not necessary aligned by row boundaries. Within a block
the norm is accumulated to intermediate light-weight
type (worktype). It really makes sense for 8u, 16s, 16u types
and L1 & L2 norms, where worktype==int and normtype==int64.
In other cases a simpler algorithm is used
*/
#define ICV_DEF_NORM_NOHINT_BLOCK_FUNC_2D( name, _op_, _update_op_, \
post_func, arrtype, normtype, worktype, block_size ) \
IPCVAPI_IMPL( CvStatus, name, ( const arrtype* src, int step, \
CvSize size, double* _norm ), (src, step, size, _norm) ) \
{ \
int remaining = block_size; \
normtype total_norm = 0; \
worktype norm = 0; \
step /= sizeof(src[0]); \
\
for( ; size.height--; src += step ) \
{ \
int x = 0; \
while( x < size.width ) \
{ \
int limit = MIN( remaining, size.width - x ); \
remaining -= limit; \
limit += x; \
ICV_NORM_CASE( _op_, _update_op_, worktype, limit );\
if( remaining == 0 ) \
{ \
remaining = block_size; \
total_norm += (normtype)norm; \
norm = 0; \
} \
} \
} \
\
total_norm += (normtype)norm; \
*_norm = post_func((double)total_norm); \
return CV_OK; \
}
#define ICV_DEF_NORM_NOHINT_FUNC_2D( name, _op_, _update_op_, \
post_func, arrtype, normtype, worktype, block_size ) \
IPCVAPI_IMPL( CvStatus, name, ( const arrtype* src, int step, \
CvSize size, double* _norm ), (src, step, size, _norm) ) \
{ \
normtype norm = 0; \
step /= sizeof(src[0]); \
\
for( ; size.height--; src += step ) \
{ \
int x = 0; \
ICV_NORM_CASE(_op_, _update_op_, worktype, size.width); \
} \
\
*_norm = post_func((double)norm); \
return CV_OK; \
}
/*
In IPP only 32f flavors of norm functions are with hint.
For float worktype==normtype==double, thus the block algorithm,
described above, is not necessary.
*/
#define ICV_DEF_NORM_HINT_FUNC_2D( name, _op_, _update_op_, \
post_func, arrtype, normtype, worktype, block_size ) \
IPCVAPI_IMPL( CvStatus, name, ( const arrtype* src, int step, \
CvSize size, double* _norm, CvHintAlgorithm /*hint*/ ), \
(src, step, size, _norm, cvAlgHintAccurate) ) \
{ \
normtype norm = 0; \
step /= sizeof(src[0]); \
\
for( ; size.height--; src += step ) \
{ \
int x = 0; \
ICV_NORM_CASE(_op_, _update_op_, worktype, size.width); \
} \
\
*_norm = post_func((double)norm); \
return CV_OK; \
}
#define ICV_DEF_NORM_NOHINT_BLOCK_FUNC_2D_COI( name, _op_, \
_update_op_, post_func, arrtype, \
normtype, worktype, block_size ) \
static CvStatus CV_STDCALL name( const arrtype* src, int step, \
CvSize size, int cn, int coi, double* _norm ) \
{ \
int remaining = block_size; \
normtype total_norm = 0; \
worktype norm = 0; \
step /= sizeof(src[0]); \
src += coi - 1; \
\
for( ; size.height--; src += step ) \
{ \
int x = 0; \
while( x < size.width ) \
{ \
int limit = MIN( remaining, size.width - x ); \
remaining -= limit; \
limit += x; \
ICV_NORM_COI_CASE( _op_, _update_op_, \
worktype, limit, cn ); \
if( remaining == 0 ) \
{ \
remaining = block_size; \
total_norm += (normtype)norm; \
norm = 0; \
} \
} \
} \
\
total_norm += (normtype)norm; \
*_norm = post_func((double)total_norm); \
return CV_OK; \
}
#define ICV_DEF_NORM_NOHINT_FUNC_2D_COI( name, _op_, \
_update_op_, post_func, \
arrtype, normtype, worktype, block_size ) \
static CvStatus CV_STDCALL name( const arrtype* src, int step, \
CvSize size, int cn, int coi, double* _norm ) \
{ \
normtype norm = 0; \
step /= sizeof(src[0]); \
src += coi - 1; \
\
for( ; size.height--; src += step ) \
{ \
int x = 0; \
ICV_NORM_COI_CASE( _op_, _update_op_, \
worktype, size.width, cn ); \
} \
\
*_norm = post_func((double)norm); \
return CV_OK; \
}
#define ICV_DEF_NORM_DIFF_NOHINT_BLOCK_FUNC_2D( name, _op_, \
_update_op_, post_func, arrtype, \
normtype, worktype, block_size ) \
IPCVAPI_IMPL( CvStatus, name,( const arrtype* src1, int step1, \
const arrtype* src2, int step2, CvSize size, double* _norm),\
(src1, step1, src2, step2, size, _norm)) \
{ \
int remaining = block_size; \
normtype total_norm = 0; \
worktype norm = 0; \
step1 /= sizeof(src1[0]); \
step2 /= sizeof(src2[0]); \
\
for( ; size.height--; src1 += step1, src2 += step2 ) \
{ \
int x = 0; \
while( x < size.width ) \
{ \
int limit = MIN( remaining, size.width - x ); \
remaining -= limit; \
limit += x; \
ICV_NORM_DIFF_CASE( _op_, _update_op_, \
worktype, limit ); \
if( remaining == 0 ) \
{ \
remaining = block_size; \
total_norm += (normtype)norm; \
norm = 0; \
} \
} \
} \
\
total_norm += (normtype)norm; \
*_norm = post_func((double)total_norm); \
return CV_OK; \
}
#define ICV_DEF_NORM_DIFF_NOHINT_FUNC_2D( name, _op_, \
_update_op_, post_func, \
arrtype, normtype, worktype, block_size ) \
IPCVAPI_IMPL( CvStatus, name,( const arrtype* src1, int step1, \
const arrtype* src2, int step2, CvSize size, double* _norm),\
( src1, step1, src2, step2, size, _norm )) \
{ \
normtype norm = 0; \
step1 /= sizeof(src1[0]); \
step2 /= sizeof(src2[0]); \
\
for( ; size.height--; src1 += step1, src2 += step2 ) \
{ \
int x = 0; \
ICV_NORM_DIFF_CASE( _op_, _update_op_, \
worktype, size.width ); \
} \
\
*_norm = post_func((double)norm); \
return CV_OK; \
}
#define ICV_DEF_NORM_DIFF_HINT_FUNC_2D( name, _op_, \
_update_op_, post_func, \
arrtype, normtype, worktype, block_size ) \
IPCVAPI_IMPL( CvStatus, name,( const arrtype* src1, int step1, \
const arrtype* src2, int step2, CvSize size, double* _norm, \
CvHintAlgorithm /*hint*/ ), \
(src1, step1, src2, step2, size, _norm, cvAlgHintAccurate ))\
{ \
normtype norm = 0; \
step1 /= sizeof(src1[0]); \
step2 /= sizeof(src2[0]); \
\
for( ; size.height--; src1 += step1, src2 += step2 ) \
{ \
int x = 0; \
ICV_NORM_DIFF_CASE( _op_, _update_op_, \
worktype, size.width ); \
} \
\
*_norm = post_func((double)norm); \
return CV_OK; \
}
#define ICV_DEF_NORM_DIFF_NOHINT_BLOCK_FUNC_2D_COI( name, _op_,\
_update_op_, post_func, arrtype, \
normtype, worktype, block_size ) \
static CvStatus CV_STDCALL name( const arrtype* src1, int step1,\
const arrtype* src2, int step2, CvSize size, \
int cn, int coi, double* _norm ) \
{ \
int remaining = block_size; \
normtype total_norm = 0; \
worktype norm = 0; \
step1 /= sizeof(src1[0]); \
step2 /= sizeof(src2[0]); \
src1 += coi - 1; \
src2 += coi - 1; \
\
for( ; size.height--; src1 += step1, src2 += step2 ) \
{ \
int x = 0; \
while( x < size.width ) \
{ \
int limit = MIN( remaining, size.width - x ); \
remaining -= limit; \
limit += x; \
ICV_NORM_DIFF_COI_CASE( _op_, _update_op_, \
worktype, limit, cn ); \
if( remaining == 0 ) \
{ \
remaining = block_size; \
total_norm += (normtype)norm; \
norm = 0; \
} \
} \
} \
\
total_norm += (normtype)norm; \
*_norm = post_func((double)total_norm); \
return CV_OK; \
}
#define ICV_DEF_NORM_DIFF_NOHINT_FUNC_2D_COI( name, _op_, \
_update_op_, post_func, \
arrtype, normtype, worktype, block_size ) \
static CvStatus CV_STDCALL name( const arrtype* src1, int step1,\
const arrtype* src2, int step2, CvSize size, \
int cn, int coi, double* _norm ) \
{ \
normtype norm = 0; \
step1 /= sizeof(src1[0]); \
step2 /= sizeof(src2[0]); \
src1 += coi - 1; \
src2 += coi - 1; \
\
for( ; size.height--; src1 += step1, src2 += step2 ) \
{ \
int x = 0; \
ICV_NORM_DIFF_COI_CASE( _op_, _update_op_, \
worktype, size.width, cn ); \
} \
\
*_norm = post_func((double)norm); \
return CV_OK; \
}
/****************************************************************************************\
* N o r m with M A S K *
\****************************************************************************************/
#define ICV_NORM_MASK_CASE( _op_, \
_update_op_, worktype, len ) \
{ \
for( ; x <= (len) - 2; x += 2 ) \
{ \
worktype t0; \
if( mask[x] ) \
{ \
t0 = (src)[x]; \
t0 = _op_(t0); \
norm = _update_op_( norm, t0 ); \
} \
if( mask[x+1] ) \
{ \
t0 = (src)[x+1]; \
t0 = _op_(t0); \
norm = _update_op_( norm, t0 ); \
} \
} \
\
for( ; x < (len); x++ ) \
if( mask[x] ) \
{ \
worktype t0 = (src)[x]; \
t0 = _op_(t0); \
norm = _update_op_( norm, t0 ); \
} \
}
#define ICV_NORM_DIFF_MASK_CASE( _op_, _update_op_, worktype, len ) \
{ \
for( ; x <= (len) - 2; x += 2 ) \
{ \
worktype t0; \
if( mask[x] ) \
{ \
t0 = (src1)[x] - (src2)[x]; \
t0 = _op_(t0); \
norm = _update_op_( norm, t0 ); \
} \
if( mask[x+1] ) \
{ \
t0 = (src1)[x+1] - (src2)[x+1]; \
t0 = _op_(t0); \
norm = _update_op_( norm, t0 ); \
} \
} \
\
for( ; x < (len); x++ ) \
if( mask[x] ) \
{ \
worktype t0 = (src1)[x] - (src2)[x];\
t0 = _op_(t0); \
norm = _update_op_( norm, t0 ); \
} \
}
#define ICV_NORM_MASK_COI_CASE( _op_, _update_op_, worktype, len, cn ) \
{ \
for( ; x < (len); x++ ) \
if( mask[x] ) \
{ \
worktype t0 = (src)[x*(cn)]; \
t0 = _op_(t0); \
norm = _update_op_( norm, t0 ); \
} \
}
#define ICV_NORM_DIFF_MASK_COI_CASE( _op_, _update_op_, worktype, len, cn )\
{ \
for( ; x < (len); x++ ) \
if( mask[x] ) \
{ \
worktype t0 = (src1)[x*(cn)] - (src2)[x*(cn)]; \
t0 = _op_(t0); \
norm = _update_op_( norm, t0 ); \
} \
}
#define ICV_DEF_NORM_MASK_NOHINT_BLOCK_FUNC_2D( name, _op_, \
_update_op_, post_func, arrtype, \
normtype, worktype, block_size ) \
IPCVAPI_IMPL( CvStatus, name, ( const arrtype* src, int step, \
const uchar* mask, int maskstep, CvSize size, double* _norm ),\
(src, step, mask, maskstep, size, _norm) ) \
{ \
int remaining = block_size; \
normtype total_norm = 0; \
worktype norm = 0; \
step /= sizeof(src[0]); \
\
for( ; size.height--; src += step, mask += maskstep ) \
{ \
int x = 0; \
while( x < size.width ) \
{ \
int limit = MIN( remaining, size.width - x ); \
remaining -= limit; \
limit += x; \
ICV_NORM_MASK_CASE( _op_, _update_op_, \
worktype, limit ); \
if( remaining == 0 ) \
{ \
remaining = block_size; \
total_norm += (normtype)norm; \
norm = 0; \
} \
} \
} \
\
total_norm += (normtype)norm; \
*_norm = post_func((double)total_norm); \
return CV_OK; \
}
#define ICV_DEF_NORM_MASK_NOHINT_FUNC_2D( name, _op_, _update_op_,\
post_func, arrtype, normtype, worktype, block_size ) \
IPCVAPI_IMPL( CvStatus, name, ( const arrtype* src, int step, \
const uchar* mask, int maskstep, CvSize size, double* _norm ),\
(src, step, mask, maskstep, size, _norm) ) \
{ \
normtype norm = 0; \
step /= sizeof(src[0]); \
\
for( ; size.height--; src += step, mask += maskstep ) \
{ \
int x = 0; \
ICV_NORM_MASK_CASE( _op_, _update_op_, \
worktype, size.width ); \
} \
\
*_norm = post_func((double)norm); \
return CV_OK; \
}
#define ICV_DEF_NORM_MASK_NOHINT_BLOCK_FUNC_2D_COI( name, _op_,\
_update_op_, post_func, arrtype, \
normtype, worktype, block_size ) \
static CvStatus CV_STDCALL name( const arrtype* src, int step, \
const uchar* mask, int maskstep, CvSize size, \
int cn, int coi, double* _norm ) \
{ \
int remaining = block_size; \
normtype total_norm = 0; \
worktype norm = 0; \
step /= sizeof(src[0]); \
src += coi - 1; \
\
for( ; size.height--; src += step, mask += maskstep ) \
{ \
int x = 0; \
while( x < size.width ) \
{ \
int limit = MIN( remaining, size.width - x ); \
remaining -= limit; \
limit += x; \
ICV_NORM_MASK_COI_CASE( _op_, _update_op_, \
worktype, limit, cn ); \
if( remaining == 0 ) \
{ \
remaining = block_size; \
total_norm += (normtype)norm; \
norm = 0; \
} \
} \
} \
\
total_norm += (normtype)norm; \
*_norm = post_func((double)total_norm); \
return CV_OK; \
}
#define ICV_DEF_NORM_MASK_NOHINT_FUNC_2D_COI( name, _op_, \
_update_op_, post_func, \
arrtype, normtype, worktype, block_size ) \
static CvStatus CV_STDCALL name( const arrtype* src, int step, \
const uchar* mask, int maskstep, CvSize size, \
int cn, int coi, double* _norm ) \
{ \
normtype norm = 0; \
step /= sizeof(src[0]); \
src += coi - 1; \
\
for( ; size.height--; src += step, mask += maskstep ) \
{ \
int x = 0; \
ICV_NORM_MASK_COI_CASE( _op_, _update_op_, \
worktype, size.width, cn ); \
} \
\
*_norm = post_func((double)norm); \
return CV_OK; \
}
#define ICV_DEF_NORM_DIFF_MASK_NOHINT_BLOCK_FUNC_2D( name, \
_op_, _update_op_, post_func, arrtype, \
normtype, worktype, block_size ) \
IPCVAPI_IMPL( CvStatus, name,( const arrtype* src1, int step1, \
const arrtype* src2, int step2, const uchar* mask, \
int maskstep, CvSize size, double* _norm ), \
(src1, step1, src2, step2, mask, maskstep, size, _norm )) \
{ \
int remaining = block_size; \
normtype total_norm = 0; \
worktype norm = 0; \
step1 /= sizeof(src1[0]); \
step2 /= sizeof(src2[0]); \
\
for( ; size.height--; src1 += step1, src2 += step2, \
mask += maskstep ) \
{ \
int x = 0; \
while( x < size.width ) \
{ \
int limit = MIN( remaining, size.width - x ); \
remaining -= limit; \
limit += x; \
ICV_NORM_DIFF_MASK_CASE( _op_, _update_op_, \
worktype, limit ); \
if( remaining == 0 ) \
{ \
remaining = block_size; \
total_norm += (normtype)norm; \
norm = 0; \
} \
} \
} \
\
total_norm += (normtype)norm; \
*_norm = post_func((double)total_norm); \
return CV_OK; \
}
#define ICV_DEF_NORM_DIFF_MASK_NOHINT_FUNC_2D( name, _op_, \
_update_op_, post_func, \
arrtype, normtype, worktype, block_size ) \
IPCVAPI_IMPL( CvStatus, name,( const arrtype* src1, int step1, \
const arrtype* src2, int step2, const uchar* mask, \
int maskstep, CvSize size, double* _norm ), \
(src1, step1, src2, step2, mask, maskstep, size, _norm )) \
{ \
normtype norm = 0; \
step1 /= sizeof(src1[0]); \
step2 /= sizeof(src2[0]); \
\
for( ; size.height--; src1 += step1, src2 += step2, \
mask += maskstep ) \
{ \
int x = 0; \
ICV_NORM_DIFF_MASK_CASE( _op_, _update_op_, \
worktype, size.width ); \
} \
\
*_norm = post_func((double)norm); \
return CV_OK; \
}
#define ICV_DEF_NORM_DIFF_MASK_NOHINT_BLOCK_FUNC_2D_COI( name, \
_op_, _update_op_, post_func, arrtype, \
normtype, worktype, block_size ) \
static CvStatus CV_STDCALL name( const arrtype* src1, int step1,\
const arrtype* src2, int step2, const uchar* mask, \
int maskstep, CvSize size, int cn, int coi, double* _norm ) \
{ \
int remaining = block_size; \
normtype total_norm = 0; \
worktype norm = 0; \
step1 /= sizeof(src1[0]); \
step2 /= sizeof(src2[0]); \
src1 += coi - 1; \
src2 += coi - 1; \
\
for( ; size.height--; src1 += step1, src2 += step2, \
mask += maskstep ) \
{ \
int x = 0; \
while( x < size.width ) \
{ \
int limit = MIN( remaining, size.width - x ); \
remaining -= limit; \
limit += x; \
ICV_NORM_DIFF_MASK_COI_CASE( _op_, _update_op_, \
worktype, limit, cn ); \
if( remaining == 0 ) \
{ \
remaining = block_size; \
total_norm += (normtype)norm; \
norm = 0; \
} \
} \
} \
\
total_norm += (normtype)norm; \
*_norm = post_func((double)total_norm); \
return CV_OK; \
}
#define ICV_DEF_NORM_DIFF_MASK_NOHINT_FUNC_2D_COI( name, _op_, \
_update_op_, post_func, \
arrtype, normtype, worktype, block_size ) \
static CvStatus CV_STDCALL name( const arrtype* src1, int step1,\
const arrtype* src2, int step2, const uchar* mask, \
int maskstep, CvSize size, int cn, int coi, double* _norm ) \
{ \
normtype norm = 0; \
step1 /= sizeof(src1[0]); \
step2 /= sizeof(src2[0]); \
src1 += coi - 1; \
src2 += coi - 1; \
\
for( ; size.height--; src1 += step1, src2 += step2, \
mask += maskstep ) \
{ \
int x = 0; \
ICV_NORM_DIFF_MASK_COI_CASE( _op_, _update_op_, \
worktype, size.width, cn );\
} \
\
*_norm = post_func((double)norm); \
return CV_OK; \
}
//////////////////////////////////// The macros expanded /////////////////////////////////
#define ICV_DEF_NORM_FUNC_ALL_C(flavor, _abs_, _abs_diff_, arrtype, worktype)\
\
ICV_DEF_NORM_NOHINT_FUNC_2D( icvNorm_Inf_##flavor##_C1R, \
_abs_, MAX, CV_NOP, arrtype, worktype, worktype, 0 ) \
\
ICV_DEF_NORM_NOHINT_FUNC_2D_COI( icvNorm_Inf_##flavor##_CnCR, \
_abs_, MAX, CV_NOP, arrtype, worktype, worktype, 0 ) \
\
ICV_DEF_NORM_DIFF_NOHINT_FUNC_2D( icvNormDiff_Inf_##flavor##_C1R, \
_abs_diff_, MAX, CV_NOP, arrtype, worktype, worktype, 0 ) \
\
ICV_DEF_NORM_DIFF_NOHINT_FUNC_2D_COI( icvNormDiff_Inf_##flavor##_CnCR, \
_abs_diff_, MAX, CV_NOP, arrtype, worktype, worktype, 0 ) \
\
ICV_DEF_NORM_MASK_NOHINT_FUNC_2D( icvNorm_Inf_##flavor##_C1MR, \
_abs_, MAX, CV_NOP, arrtype, worktype, worktype, 0 ) \
\
ICV_DEF_NORM_MASK_NOHINT_FUNC_2D_COI( icvNorm_Inf_##flavor##_CnCMR, \
_abs_, MAX, CV_NOP, arrtype, worktype, worktype, 0 ) \
\
ICV_DEF_NORM_DIFF_MASK_NOHINT_FUNC_2D( icvNormDiff_Inf_##flavor##_C1MR, \
_abs_diff_, MAX, CV_NOP, arrtype, worktype, worktype, 0 ) \
\
ICV_DEF_NORM_DIFF_MASK_NOHINT_FUNC_2D_COI( icvNormDiff_Inf_##flavor##_CnCMR,\
_abs_diff_, MAX, CV_NOP, arrtype, worktype, worktype, 0 )
ICV_DEF_NORM_FUNC_ALL_C( 8u, CV_NOP, CV_IABS, uchar, int )
ICV_DEF_NORM_FUNC_ALL_C( 16u, CV_NOP, CV_IABS, ushort, int )
ICV_DEF_NORM_FUNC_ALL_C( 16s, CV_IABS, CV_IABS, short, int )
// there is no protection from overflow
// (otherwise we had to do everything in int64's or double's)
ICV_DEF_NORM_FUNC_ALL_C( 32s, CV_IABS, CV_IABS, int, int )
ICV_DEF_NORM_FUNC_ALL_C( 32f, fabs, fabs, float, double )
ICV_DEF_NORM_FUNC_ALL_C( 64f, fabs, fabs, double, double )
#define ICV_DEF_NORM_FUNC_ALL_L1( flavor, _abs_, _abs_diff_, hintp_func, nohint_func,\
arrtype, normtype, worktype, block_size ) \
\
ICV_DEF_NORM_##hintp_func##_FUNC_2D( icvNorm_L1_##flavor##_C1R, \
_abs_, CV_ADD, CV_NOP, arrtype, normtype, worktype, block_size ) \
\
ICV_DEF_NORM_##nohint_func##_FUNC_2D_COI( icvNorm_L1_##flavor##_CnCR, \
_abs_, CV_ADD, CV_NOP, arrtype, normtype, worktype, block_size ) \
\
ICV_DEF_NORM_DIFF_##hintp_func##_FUNC_2D( icvNormDiff_L1_##flavor##_C1R, \
_abs_diff_, CV_ADD, CV_NOP, arrtype, normtype, worktype, block_size ) \
\
ICV_DEF_NORM_DIFF_##nohint_func##_FUNC_2D_COI( icvNormDiff_L1_##flavor##_CnCR, \
_abs_diff_, CV_ADD, CV_NOP, arrtype, normtype, worktype, block_size ) \
\
ICV_DEF_NORM_MASK_##nohint_func##_FUNC_2D( icvNorm_L1_##flavor##_C1MR, \
_abs_, CV_ADD, CV_NOP, arrtype, normtype, worktype, block_size ) \
\
ICV_DEF_NORM_MASK_##nohint_func##_FUNC_2D_COI( icvNorm_L1_##flavor##_CnCMR, \
_abs_, CV_ADD, CV_NOP, arrtype, normtype, worktype, block_size ) \
\
ICV_DEF_NORM_DIFF_MASK_##nohint_func##_FUNC_2D( icvNormDiff_L1_##flavor##_C1MR, \
_abs_diff_, CV_ADD, CV_NOP, arrtype, normtype, worktype, block_size ) \
\
ICV_DEF_NORM_DIFF_MASK_##nohint_func##_FUNC_2D_COI( icvNormDiff_L1_##flavor##_CnCMR,\
_abs_diff_, CV_ADD, CV_NOP, arrtype, normtype, worktype, block_size )
ICV_DEF_NORM_FUNC_ALL_L1( 8u, CV_NOP, CV_IABS, NOHINT_BLOCK, NOHINT_BLOCK,
uchar, int64, int, 1 << 23 )
ICV_DEF_NORM_FUNC_ALL_L1( 16u, CV_NOP, CV_IABS, NOHINT_BLOCK, NOHINT_BLOCK,
ushort, int64, int, 1 << 15 )
ICV_DEF_NORM_FUNC_ALL_L1( 16s, CV_IABS, CV_IABS, NOHINT_BLOCK, NOHINT_BLOCK,
short, int64, int, 1 << 15 )
// there is no protection from overflow on abs() stage.
// (otherwise we had to do everything in int64's or double's)
ICV_DEF_NORM_FUNC_ALL_L1( 32s, fabs, fabs, NOHINT, NOHINT,
int, double, double, INT_MAX )
ICV_DEF_NORM_FUNC_ALL_L1( 32f, fabs, fabs, HINT, NOHINT,
float, double, double, INT_MAX )
ICV_DEF_NORM_FUNC_ALL_L1( 64f, fabs, fabs, NOHINT, NOHINT,
double, double, double, INT_MAX )
#define ICV_DEF_NORM_FUNC_ALL_L2( flavor, hintp_func, nohint_func, arrtype, \
normtype, worktype, block_size, sqr_macro ) \
\
ICV_DEF_NORM_##hintp_func##_FUNC_2D( icvNorm_L2_##flavor##_C1R, \
sqr_macro, CV_ADD, sqrt, arrtype, normtype, worktype, block_size ) \
\
ICV_DEF_NORM_##nohint_func##_FUNC_2D_COI( icvNorm_L2_##flavor##_CnCR, \
sqr_macro, CV_ADD, sqrt, arrtype, normtype, worktype, block_size ) \
\
ICV_DEF_NORM_DIFF_##hintp_func##_FUNC_2D( icvNormDiff_L2_##flavor##_C1R, \
sqr_macro, CV_ADD, sqrt, arrtype, normtype, worktype, block_size ) \
\
ICV_DEF_NORM_DIFF_##nohint_func##_FUNC_2D_COI( icvNormDiff_L2_##flavor##_CnCR, \
sqr_macro, CV_ADD, sqrt, arrtype, normtype, worktype, block_size ) \
\
ICV_DEF_NORM_MASK_##nohint_func##_FUNC_2D( icvNorm_L2_##flavor##_C1MR, \
sqr_macro, CV_ADD, sqrt, arrtype, normtype, worktype, block_size ) \
\
ICV_DEF_NORM_MASK_##nohint_func##_FUNC_2D_COI( icvNorm_L2_##flavor##_CnCMR, \
sqr_macro, CV_ADD, sqrt, arrtype, normtype, worktype, block_size ) \
\
ICV_DEF_NORM_DIFF_MASK_##nohint_func##_FUNC_2D( icvNormDiff_L2_##flavor##_C1MR, \
sqr_macro, CV_ADD, sqrt, arrtype, normtype, worktype, block_size ) \
\
ICV_DEF_NORM_DIFF_MASK_##nohint_func##_FUNC_2D_COI( icvNormDiff_L2_##flavor##_CnCMR,\
sqr_macro, CV_ADD, sqrt, arrtype, normtype, worktype, block_size )
ICV_DEF_NORM_FUNC_ALL_L2( 8u, NOHINT_BLOCK, NOHINT_BLOCK, uchar,
int64, int, 1 << 15, CV_SQR_8U )
ICV_DEF_NORM_FUNC_ALL_L2( 16u, NOHINT, NOHINT, ushort,
double, double, INT_MAX, CV_SQR )
ICV_DEF_NORM_FUNC_ALL_L2( 16s, NOHINT, NOHINT, short,
double, double, INT_MAX, CV_SQR )
// there is no protection from overflow on abs() stage.
// (otherwise we had to do everything in int64's or double's)
ICV_DEF_NORM_FUNC_ALL_L2( 32s, NOHINT, NOHINT, int,
double, double, INT_MAX, CV_SQR )
ICV_DEF_NORM_FUNC_ALL_L2( 32f, HINT, NOHINT, float,
double, double, INT_MAX, CV_SQR )
ICV_DEF_NORM_FUNC_ALL_L2( 64f, NOHINT, NOHINT, double,
double, double, INT_MAX, CV_SQR )
#define ICV_DEF_INIT_NORM_TAB_2D( FUNCNAME, FLAG ) \
static void icvInit##FUNCNAME##FLAG##Table( CvFuncTable* tab ) \
{ \
tab->fn_2d[CV_8U] = (void*)icv##FUNCNAME##_8u_##FLAG; \
tab->fn_2d[CV_8S] = 0; \
tab->fn_2d[CV_16U] = (void*)icv##FUNCNAME##_16u_##FLAG; \
tab->fn_2d[CV_16S] = (void*)icv##FUNCNAME##_16s_##FLAG; \
tab->fn_2d[CV_32S] = (void*)icv##FUNCNAME##_32s_##FLAG; \
tab->fn_2d[CV_32F] = (void*)icv##FUNCNAME##_32f_##FLAG; \
tab->fn_2d[CV_64F] = (void*)icv##FUNCNAME##_64f_##FLAG; \
}
ICV_DEF_INIT_NORM_TAB_2D( Norm_Inf, C1R )
ICV_DEF_INIT_NORM_TAB_2D( Norm_L1, C1R )
ICV_DEF_INIT_NORM_TAB_2D( Norm_L2, C1R )
ICV_DEF_INIT_NORM_TAB_2D( NormDiff_Inf, C1R )
ICV_DEF_INIT_NORM_TAB_2D( NormDiff_L1, C1R )
ICV_DEF_INIT_NORM_TAB_2D( NormDiff_L2, C1R )
ICV_DEF_INIT_NORM_TAB_2D( Norm_Inf, CnCR )
ICV_DEF_INIT_NORM_TAB_2D( Norm_L1, CnCR )
ICV_DEF_INIT_NORM_TAB_2D( Norm_L2, CnCR )
ICV_DEF_INIT_NORM_TAB_2D( NormDiff_Inf, CnCR )
ICV_DEF_INIT_NORM_TAB_2D( NormDiff_L1, CnCR )
ICV_DEF_INIT_NORM_TAB_2D( NormDiff_L2, CnCR )
ICV_DEF_INIT_NORM_TAB_2D( Norm_Inf, C1MR )
ICV_DEF_INIT_NORM_TAB_2D( Norm_L1, C1MR )
ICV_DEF_INIT_NORM_TAB_2D( Norm_L2, C1MR )
ICV_DEF_INIT_NORM_TAB_2D( NormDiff_Inf, C1MR )
ICV_DEF_INIT_NORM_TAB_2D( NormDiff_L1, C1MR )
ICV_DEF_INIT_NORM_TAB_2D( NormDiff_L2, C1MR )
ICV_DEF_INIT_NORM_TAB_2D( Norm_Inf, CnCMR )
ICV_DEF_INIT_NORM_TAB_2D( Norm_L1, CnCMR )
ICV_DEF_INIT_NORM_TAB_2D( Norm_L2, CnCMR )
ICV_DEF_INIT_NORM_TAB_2D( NormDiff_Inf, CnCMR )
ICV_DEF_INIT_NORM_TAB_2D( NormDiff_L1, CnCMR )
ICV_DEF_INIT_NORM_TAB_2D( NormDiff_L2, CnCMR )
static void icvInitNormTabs( CvFuncTable* norm_tab, CvFuncTable* normmask_tab )
{
icvInitNorm_InfC1RTable( &norm_tab[0] );
icvInitNorm_L1C1RTable( &norm_tab[1] );
icvInitNorm_L2C1RTable( &norm_tab[2] );
icvInitNormDiff_InfC1RTable( &norm_tab[3] );
icvInitNormDiff_L1C1RTable( &norm_tab[4] );
icvInitNormDiff_L2C1RTable( &norm_tab[5] );
icvInitNorm_InfCnCRTable( &norm_tab[6] );
icvInitNorm_L1CnCRTable( &norm_tab[7] );
icvInitNorm_L2CnCRTable( &norm_tab[8] );
icvInitNormDiff_InfCnCRTable( &norm_tab[9] );
icvInitNormDiff_L1CnCRTable( &norm_tab[10] );
icvInitNormDiff_L2CnCRTable( &norm_tab[11] );
icvInitNorm_InfC1MRTable( &normmask_tab[0] );
icvInitNorm_L1C1MRTable( &normmask_tab[1] );
icvInitNorm_L2C1MRTable( &normmask_tab[2] );
icvInitNormDiff_InfC1MRTable( &normmask_tab[3] );
icvInitNormDiff_L1C1MRTable( &normmask_tab[4] );
icvInitNormDiff_L2C1MRTable( &normmask_tab[5] );
icvInitNorm_InfCnCMRTable( &normmask_tab[6] );
icvInitNorm_L1CnCMRTable( &normmask_tab[7] );
icvInitNorm_L2CnCMRTable( &normmask_tab[8] );
icvInitNormDiff_InfCnCMRTable( &normmask_tab[9] );
icvInitNormDiff_L1CnCMRTable( &normmask_tab[10] );
icvInitNormDiff_L2CnCMRTable( &normmask_tab[11] );
}
CV_IMPL double
cvNorm( const void* imgA, const void* imgB, int normType, const void* mask )
{
static CvFuncTable norm_tab[12];
static CvFuncTable normmask_tab[12];
static int inittab = 0;
double norm = 0, norm_diff = 0;
CV_FUNCNAME("cvNorm");
__BEGIN__;
int type, depth, cn, is_relative;
CvSize size;
CvMat stub1, *mat1 = (CvMat*)imgB;
CvMat stub2, *mat2 = (CvMat*)imgA;
int mat2_flag = CV_MAT_CONT_FLAG;
int mat1_step, mat2_step, mask_step = 0;
int coi = 0, coi2 = 0;
if( !mat1 )
{
mat1 = mat2;
mat2 = 0;
}
is_relative = mat2 && (normType & CV_RELATIVE);
normType &= ~CV_RELATIVE;
switch( normType )
{
case CV_C:
case CV_L1:
case CV_L2:
case CV_DIFF_C:
case CV_DIFF_L1:
case CV_DIFF_L2:
normType = (normType & 7) >> 1;
break;
default:
CV_ERROR( CV_StsBadFlag, "" );
}
/* light variant */
if( CV_IS_MAT(mat1) && (!mat2 || CV_IS_MAT(mat2)) && !mask )
{
if( mat2 )
{
if( !CV_ARE_TYPES_EQ( mat1, mat2 ))
CV_ERROR( CV_StsUnmatchedFormats, "" );
if( !CV_ARE_SIZES_EQ( mat1, mat2 ))
CV_ERROR( CV_StsUnmatchedSizes, "" );
mat2_flag = mat2->type;
}
size = cvGetMatSize( mat1 );
type = CV_MAT_TYPE(mat1->type);
depth = CV_MAT_DEPTH(type);
cn = CV_MAT_CN(type);
if( CV_IS_MAT_CONT( mat1->type & mat2_flag ))
{
size.width *= size.height;
if( size.width <= CV_MAX_INLINE_MAT_OP_SIZE && normType == 2 /* CV_L2 */ )
{
if( depth == CV_32F )
{
const float* src1data = mat1->data.fl;
int size0 = size.width *= cn;
if( !mat2 || is_relative )
{
do
{
double t = src1data[size.width-1];
norm += t*t;
}
while( --size.width );
}
if( mat2 )
{
const float* src2data = mat2->data.fl;
size.width = size0;
do
{
double t = src1data[size.width-1] - src2data[size.width-1];
norm_diff += t*t;
}
while( --size.width );
if( is_relative )
norm = norm_diff/(norm + DBL_EPSILON);
else
norm = norm_diff;
}
norm = sqrt(norm);
EXIT;
}
if( depth == CV_64F )
{
const double* src1data = mat1->data.db;
int size0 = size.width *= cn;
if( !mat2 || is_relative )
{
do
{
double t = src1data[size.width-1];
norm += t*t;
}
while( --size.width );
}
if( mat2 )
{
const double* src2data = mat2->data.db;
size.width = size0;
do
{
double t = src1data[size.width-1] - src2data[size.width-1];
norm_diff += t*t;
}
while( --size.width );
if( is_relative )
norm = norm_diff/(norm + DBL_EPSILON);
else
norm = norm_diff;
}
norm = sqrt(norm);
EXIT;
}
}
size.height = 1;
mat1_step = mat2_step = CV_STUB_STEP;
}
else
{
mat1_step = mat1->step;
mat2_step = mat2 ? mat2->step : 0;
}
}
else if( !CV_IS_MATND(mat1) && !CV_IS_MATND(mat2) )
{
CV_CALL( mat1 = cvGetMat( mat1, &stub1, &coi ));
if( mat2 )
{
CV_CALL( mat2 = cvGetMat( mat2, &stub2, &coi2 ));
if( !CV_ARE_TYPES_EQ( mat1, mat2 ))
CV_ERROR( CV_StsUnmatchedFormats, "" );
if( !CV_ARE_SIZES_EQ( mat1, mat2 ))
CV_ERROR( CV_StsUnmatchedSizes, "" );
if( coi != coi2 && CV_MAT_CN( mat1->type ) > 1 )
CV_ERROR( CV_BadCOI, "" );
mat2_flag = mat2->type;
}
size = cvGetMatSize( mat1 );
type = CV_MAT_TYPE(mat1->type);
depth = CV_MAT_DEPTH(type);
cn = CV_MAT_CN(type);
mat1_step = mat1->step;
mat2_step = mat2 ? mat2->step : 0;
if( !mask && CV_IS_MAT_CONT( mat1->type & mat2_flag ))
{
size.width *= size.height;
size.height = 1;
mat1_step = mat2_step = CV_STUB_STEP;
}
}
else
{
CvArr* arrs[] = { mat1, mat2 };
CvMatND stubs[2];
CvNArrayIterator iterator;
int pass_hint;
if( !inittab )
{
icvInitNormTabs( norm_tab, normmask_tab );
inittab = 1;
}
if( mask )
CV_ERROR( CV_StsBadMask,
"This operation on multi-dimensional arrays does not support mask" );
CV_CALL( cvInitNArrayIterator( 1 + (mat2 != 0), arrs, 0, stubs, &iterator ));
type = CV_MAT_TYPE(iterator.hdr[0]->type);
depth = CV_MAT_DEPTH(type);
iterator.size.width *= CV_MAT_CN(type);
pass_hint = normType != 0 && (depth == CV_32F);
if( !mat2 || is_relative )
{
if( !pass_hint )
{
CvFunc2D_1A1P func;
CV_GET_FUNC_PTR( func, (CvFunc2D_1A1P)norm_tab[normType].fn_2d[depth]);
do
{
double temp = 0;
IPPI_CALL( func( iterator.ptr[0], CV_STUB_STEP,
iterator.size, &temp ));
norm += temp;
}
while( cvNextNArraySlice( &iterator ));
}
else
{
CvFunc2D_1A1P1I func;
CV_GET_FUNC_PTR( func, (CvFunc2D_1A1P1I)norm_tab[normType].fn_2d[depth]);
do
{
double temp = 0;
IPPI_CALL( func( iterator.ptr[0], CV_STUB_STEP,
iterator.size, &temp, cvAlgHintAccurate ));
norm += temp;
}
while( cvNextNArraySlice( &iterator ));
}
}
if( mat2 )
{
if( !pass_hint )
{
CvFunc2D_2A1P func;
CV_GET_FUNC_PTR( func, (CvFunc2D_2A1P)norm_tab[3 + normType].fn_2d[depth]);
do
{
double temp = 0;
IPPI_CALL( func( iterator.ptr[0], CV_STUB_STEP,
iterator.ptr[1], CV_STUB_STEP,
iterator.size, &temp ));
norm_diff += temp;
}
while( cvNextNArraySlice( &iterator ));
}
else
{
CvFunc2D_2A1P1I func;
CV_GET_FUNC_PTR( func, (CvFunc2D_2A1P1I)norm_tab[3 + normType].fn_2d[depth]);
do
{
double temp = 0;
IPPI_CALL( func( iterator.ptr[0], CV_STUB_STEP,
iterator.ptr[1], CV_STUB_STEP,
iterator.size, &temp, cvAlgHintAccurate ));
norm_diff += temp;
}
while( cvNextNArraySlice( &iterator ));
}
if( is_relative )
norm = norm_diff/(norm + DBL_EPSILON);
else
norm = norm_diff;
}
EXIT;
}
if( !inittab )
{
icvInitNormTabs( norm_tab, normmask_tab );
inittab = 1;
}
if( !mask )
{
if( cn == 1 || coi == 0 )
{
int pass_hint = depth == CV_32F && normType != 0;
size.width *= cn;
if( !mat2 || is_relative )
{
if( !pass_hint )
{
CvFunc2D_1A1P func;
CV_GET_FUNC_PTR( func, (CvFunc2D_1A1P)norm_tab[normType].fn_2d[depth]);
IPPI_CALL( func( mat1->data.ptr, mat1_step, size, &norm ));
}
else
{
CvFunc2D_1A1P1I func;
CV_GET_FUNC_PTR( func, (CvFunc2D_1A1P1I)norm_tab[normType].fn_2d[depth]);
IPPI_CALL( func( mat1->data.ptr, mat1_step, size, &norm, cvAlgHintAccurate ));
}
}
if( mat2 )
{
if( !pass_hint )
{
CvFunc2D_2A1P func;
CV_GET_FUNC_PTR( func, (CvFunc2D_2A1P)norm_tab[3 + normType].fn_2d[depth]);
IPPI_CALL( func( mat1->data.ptr, mat1_step, mat2->data.ptr, mat2_step,
size, &norm_diff ));
}
else
{
CvFunc2D_2A1P1I func;
CV_GET_FUNC_PTR( func, (CvFunc2D_2A1P1I)norm_tab[3 + normType].fn_2d[depth]);
IPPI_CALL( func( mat1->data.ptr, mat1_step, mat2->data.ptr, mat2_step,
size, &norm_diff, cvAlgHintAccurate ));
}
if( is_relative )
norm = norm_diff/(norm + DBL_EPSILON);
else
norm = norm_diff;
}
}
else
{
if( !mat2 || is_relative )
{
CvFunc2DnC_1A1P func;
CV_GET_FUNC_PTR( func, (CvFunc2DnC_1A1P)norm_tab[6 + normType].fn_2d[depth]);
IPPI_CALL( func( mat1->data.ptr, mat1_step, size, cn, coi, &norm ));
}
if( mat2 )
{
CvFunc2DnC_2A1P func;
CV_GET_FUNC_PTR( func, (CvFunc2DnC_2A1P)norm_tab[9 + normType].fn_2d[depth]);
IPPI_CALL( func( mat1->data.ptr, mat1_step, mat2->data.ptr, mat2_step,
size, cn, coi, &norm_diff ));
if( is_relative )
norm = norm_diff/(norm + DBL_EPSILON);
else
norm = norm_diff;
}
}
}
else
{
CvMat maskstub, *matmask = (CvMat*)mask;
if( CV_MAT_CN(type) > 1 && coi == 0 )
CV_ERROR( CV_StsBadArg, "" );
CV_CALL( matmask = cvGetMat( matmask, &maskstub ));
if( !CV_IS_MASK_ARR( matmask ))
CV_ERROR( CV_StsBadMask, "" );
if( !CV_ARE_SIZES_EQ( mat1, matmask ))
CV_ERROR( CV_StsUnmatchedSizes, "" );
mask_step = matmask->step;
if( CV_IS_MAT_CONT( mat1->type & mat2_flag & matmask->type ))
{
size.width *= size.height;
size.height = 1;
mat1_step = mat2_step = mask_step = CV_STUB_STEP;
}
if( CV_MAT_CN(type) == 1 || coi == 0 )
{
if( !mat2 || is_relative )
{
CvFunc2D_2A1P func;
CV_GET_FUNC_PTR( func,
(CvFunc2D_2A1P)normmask_tab[normType].fn_2d[depth]);
IPPI_CALL( func( mat1->data.ptr, mat1_step,
matmask->data.ptr, mask_step, size, &norm ));
}
if( mat2 )
{
CvFunc2D_3A1P func;
CV_GET_FUNC_PTR( func,
(CvFunc2D_3A1P)normmask_tab[3 + normType].fn_2d[depth]);
IPPI_CALL( func( mat1->data.ptr, mat1_step, mat2->data.ptr, mat2_step,
matmask->data.ptr, mask_step, size, &norm_diff ));
if( is_relative )
norm = norm_diff/(norm + DBL_EPSILON);
else
norm = norm_diff;
}
}
else
{
if( !mat2 || is_relative )
{
CvFunc2DnC_2A1P func;
CV_GET_FUNC_PTR( func,
(CvFunc2DnC_2A1P)normmask_tab[6 + normType].fn_2d[depth]);
IPPI_CALL( func( mat1->data.ptr, mat1_step,
matmask->data.ptr, mask_step,
size, cn, coi, &norm ));
}
if( mat2 )
{
CvFunc2DnC_3A1P func;
CV_GET_FUNC_PTR( func,
(CvFunc2DnC_3A1P)normmask_tab[9 + normType].fn_2d[depth]);
IPPI_CALL( func( mat1->data.ptr, mat1_step,
mat2->data.ptr, mat2_step,
matmask->data.ptr, mask_step,
size, cn, coi, &norm_diff ));
if( is_relative )
norm = norm_diff/(norm + DBL_EPSILON);
else
norm = norm_diff;
}
}
}
__END__;
return norm;
}
/* End of file. */