Home | History | Annotate | Download | only in src
      1 /*M///////////////////////////////////////////////////////////////////////////////////////
      2 //
      3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
      4 //
      5 //  By downloading, copying, installing or using the software you agree to this license.
      6 //  If you do not agree to this license, do not download, install,
      7 //  copy or use the software.
      8 //
      9 //
     10 //                        Intel License Agreement
     11 //                For Open Source Computer Vision Library
     12 //
     13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
     14 // Third party copyrights are property of their respective owners.
     15 //
     16 // Redistribution and use in source and binary forms, with or without modification,
     17 // are permitted provided that the following conditions are met:
     18 //
     19 //   * Redistribution's of source code must retain the above copyright notice,
     20 //     this list of conditions and the following disclaimer.
     21 //
     22 //   * Redistribution's in binary form must reproduce the above copyright notice,
     23 //     this list of conditions and the following disclaimer in the documentation
     24 //     and/or other materials provided with the distribution.
     25 //
     26 //   * The name of Intel Corporation may not be used to endorse or promote products
     27 //     derived from this software without specific prior written permission.
     28 //
     29 // This software is provided by the copyright holders and contributors "as is" and
     30 // any express or implied warranties, including, but not limited to, the implied
     31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
     32 // In no event shall the Intel Corporation or contributors be liable for any direct,
     33 // indirect, incidental, special, exemplary, or consequential damages
     34 // (including, but not limited to, procurement of substitute goods or services;
     35 // loss of use, data, or profits; or business interruption) however caused
     36 // and on any theory of liability, whether in contract, strict liability,
     37 // or tort (including negligence or otherwise) arising in any way out of
     38 // the use of this software, even if advised of the possibility of such damage.
     39 //
     40 //M*/
     41 
     42 #include "_cxcore.h"
     43 
     44 /****************************************************************************************\
     45 *                                         N o r m                                        *
     46 \****************************************************************************************/
     47 
     48 #define ICV_NORM_CASE( _op_,                \
     49     _update_op_, worktype, len )            \
     50                                             \
     51     for( ; x <= (len) - 4; x += 4 )         \
     52     {                                       \
     53         worktype t0 = (src)[x];             \
     54         worktype t1 = (src)[x+1];           \
     55         t0 = _op_(t0);                      \
     56         t1 = _op_(t1);                      \
     57         norm = _update_op_( norm, t0 );     \
     58         norm = _update_op_( norm, t1 );     \
     59                                             \
     60         t0 = (src)[x+2];                    \
     61         t1 = (src)[x+3];                    \
     62         t0 = _op_(t0);                      \
     63         t1 = _op_(t1);                      \
     64         norm = _update_op_( norm, t0 );     \
     65         norm = _update_op_( norm, t1 );     \
     66     }                                       \
     67                                             \
     68     for( ; x < (len); x++ )                 \
     69     {                                       \
     70         worktype t0 = (src)[x];             \
     71         t0 = (worktype)_op_(t0);            \
     72         norm = _update_op_( norm, t0 );     \
     73     }
     74 
     75 
     76 #define ICV_NORM_COI_CASE( _op_,            \
     77     _update_op_, worktype, len, cn )        \
     78                                             \
     79     for( ; x < (len); x++ )                 \
     80     {                                       \
     81         worktype t0 = (src)[x*(cn)];        \
     82         t0 = (worktype)_op_(t0);            \
     83         norm = _update_op_( norm, t0 );     \
     84     }
     85 
     86 
     87 #define ICV_NORM_DIFF_CASE( _op_,           \
     88     _update_op_, worktype, len )            \
     89                                             \
     90     for( ; x <= (len) - 4; x += 4 )         \
     91     {                                       \
     92         worktype t0 = (src1)[x] - (src2)[x];\
     93         worktype t1 = (src1)[x+1]-(src2)[x+1];\
     94                                             \
     95         t0 = _op_(t0);                      \
     96         t1 = _op_(t1);                      \
     97                                             \
     98         norm = _update_op_( norm, t0 );     \
     99         norm = _update_op_( norm, t1 );     \
    100                                             \
    101         t0 = (src1)[x+2] - (src2)[x+2];     \
    102         t1 = (src1)[x+3] - (src2)[x+3];     \
    103                                             \
    104         t0 = _op_(t0);                      \
    105         t1 = _op_(t1);                      \
    106                                             \
    107         norm = _update_op_( norm, t0 );     \
    108         norm = _update_op_( norm, t1 );     \
    109     }                                       \
    110                                             \
    111     for( ; x < (len); x++ )                 \
    112     {                                       \
    113         worktype t0 = (src1)[x] - (src2)[x];\
    114         t0 = (worktype)_op_(t0);            \
    115         norm = _update_op_( norm, t0 );     \
    116     }
    117 
    118 
    119 #define ICV_NORM_DIFF_COI_CASE( _op_, _update_op_, worktype, len, cn ) \
    120     for( ; x < (len); x++ )                                     \
    121     {                                                           \
    122         worktype t0 = (src1)[x*(cn)] - (src2)[x*(cn)];          \
    123         t0 = (worktype)_op_(t0);                                \
    124         norm = _update_op_( norm, t0 );                         \
    125     }
    126 
    127 
    128 /*
    129  	The algorithm and its multiple variations below
    130     below accumulates the norm by blocks of size "block_size".
    131     Each block may span across multiple lines and it is
    132     not necessary aligned by row boundaries. Within a block
    133     the norm is accumulated to intermediate light-weight
    134     type (worktype). It really makes sense for 8u, 16s, 16u types
    135     and L1 & L2 norms, where worktype==int and normtype==int64.
    136     In other cases a simpler algorithm is used
    137 */
    138 #define  ICV_DEF_NORM_NOHINT_BLOCK_FUNC_2D( name, _op_, _update_op_, \
    139     post_func, arrtype, normtype, worktype, block_size )        \
    140 IPCVAPI_IMPL( CvStatus, name, ( const arrtype* src, int step,   \
    141     CvSize size, double* _norm ), (src, step, size, _norm) )    \
    142 {                                                               \
    143     int remaining = block_size;                                 \
    144     normtype total_norm = 0;                                    \
    145     worktype norm = 0;                                          \
    146     step /= sizeof(src[0]);                                     \
    147                                                                 \
    148     for( ; size.height--; src += step )                         \
    149     {                                                           \
    150         int x = 0;                                              \
    151         while( x < size.width )                                 \
    152         {                                                       \
    153             int limit = MIN( remaining, size.width - x );       \
    154             remaining -= limit;                                 \
    155             limit += x;                                         \
    156             ICV_NORM_CASE( _op_, _update_op_, worktype, limit );\
    157             if( remaining == 0 )                                \
    158             {                                                   \
    159                 remaining = block_size;                         \
    160                 total_norm += (normtype)norm;                   \
    161                 norm = 0;                                       \
    162             }                                                   \
    163         }                                                       \
    164     }                                                           \
    165                                                                 \
    166     total_norm += (normtype)norm;                               \
    167     *_norm = post_func((double)total_norm);                     \
    168     return CV_OK;                                               \
    169 }
    170 
    171 
    172 #define  ICV_DEF_NORM_NOHINT_FUNC_2D( name, _op_, _update_op_,  \
    173     post_func, arrtype, normtype, worktype, block_size )        \
    174 IPCVAPI_IMPL( CvStatus, name, ( const arrtype* src, int step,   \
    175     CvSize size, double* _norm ), (src, step, size, _norm) )    \
    176 {                                                               \
    177     normtype norm = 0;                                          \
    178     step /= sizeof(src[0]);                                     \
    179                                                                 \
    180     for( ; size.height--; src += step )                         \
    181     {                                                           \
    182         int x = 0;                                              \
    183         ICV_NORM_CASE(_op_, _update_op_, worktype, size.width); \
    184     }                                                           \
    185                                                                 \
    186     *_norm = post_func((double)norm);                           \
    187     return CV_OK;                                               \
    188 }
    189 
    190 
    191 /*
    192    In IPP only 32f flavors of norm functions are with hint.
    193    For float worktype==normtype==double, thus the block algorithm,
    194    described above, is not necessary.
    195  */
    196 #define  ICV_DEF_NORM_HINT_FUNC_2D( name, _op_, _update_op_,    \
    197     post_func, arrtype, normtype, worktype, block_size )        \
    198 IPCVAPI_IMPL( CvStatus, name, ( const arrtype* src, int step,   \
    199     CvSize size, double* _norm, CvHintAlgorithm /*hint*/ ),     \
    200     (src, step, size, _norm, cvAlgHintAccurate) )               \
    201 {                                                               \
    202     normtype norm = 0;                                          \
    203     step /= sizeof(src[0]);                                     \
    204                                                                 \
    205     for( ; size.height--; src += step )                         \
    206     {                                                           \
    207         int x = 0;                                              \
    208         ICV_NORM_CASE(_op_, _update_op_, worktype, size.width); \
    209     }                                                           \
    210                                                                 \
    211     *_norm = post_func((double)norm);                           \
    212     return CV_OK;                                               \
    213 }
    214 
    215 
    216 #define  ICV_DEF_NORM_NOHINT_BLOCK_FUNC_2D_COI( name, _op_,     \
    217     _update_op_, post_func, arrtype,                            \
    218     normtype, worktype, block_size )                            \
    219 static CvStatus CV_STDCALL name( const arrtype* src, int step,  \
    220                 CvSize size, int cn, int coi, double* _norm )   \
    221 {                                                               \
    222     int remaining = block_size;                                 \
    223     normtype total_norm = 0;                                    \
    224     worktype norm = 0;                                          \
    225     step /= sizeof(src[0]);                                     \
    226     src += coi - 1;                                             \
    227                                                                 \
    228     for( ; size.height--; src += step )                         \
    229     {                                                           \
    230         int x = 0;                                              \
    231         while( x < size.width )                                 \
    232         {                                                       \
    233             int limit = MIN( remaining, size.width - x );       \
    234             remaining -= limit;                                 \
    235             limit += x;                                         \
    236             ICV_NORM_COI_CASE( _op_, _update_op_,               \
    237                                worktype, limit, cn );           \
    238             if( remaining == 0 )                                \
    239             {                                                   \
    240                 remaining = block_size;                         \
    241                 total_norm += (normtype)norm;                   \
    242                 norm = 0;                                       \
    243             }                                                   \
    244         }                                                       \
    245     }                                                           \
    246                                                                 \
    247     total_norm += (normtype)norm;                               \
    248     *_norm = post_func((double)total_norm);                     \
    249     return CV_OK;                                               \
    250 }
    251 
    252 
    253 #define  ICV_DEF_NORM_NOHINT_FUNC_2D_COI( name, _op_,           \
    254     _update_op_, post_func,                                     \
    255     arrtype, normtype, worktype, block_size )                   \
    256 static CvStatus CV_STDCALL name( const arrtype* src, int step,  \
    257                 CvSize size, int cn, int coi, double* _norm )   \
    258 {                                                               \
    259     normtype norm = 0;                                          \
    260     step /= sizeof(src[0]);                                     \
    261     src += coi - 1;                                             \
    262                                                                 \
    263     for( ; size.height--; src += step )                         \
    264     {                                                           \
    265         int x = 0;                                              \
    266         ICV_NORM_COI_CASE( _op_, _update_op_,                   \
    267                            worktype, size.width, cn );          \
    268     }                                                           \
    269                                                                 \
    270     *_norm = post_func((double)norm);                           \
    271     return CV_OK;                                               \
    272 }
    273 
    274 
    275 #define  ICV_DEF_NORM_DIFF_NOHINT_BLOCK_FUNC_2D( name, _op_,    \
    276     _update_op_, post_func, arrtype,                            \
    277     normtype, worktype, block_size )                            \
    278 IPCVAPI_IMPL( CvStatus, name,( const arrtype* src1, int step1,  \
    279     const arrtype* src2, int step2, CvSize size, double* _norm),\
    280    (src1, step1, src2, step2, size, _norm))                     \
    281 {                                                               \
    282     int remaining = block_size;                                 \
    283     normtype total_norm = 0;                                    \
    284     worktype norm = 0;                                          \
    285     step1 /= sizeof(src1[0]);                                   \
    286     step2 /= sizeof(src2[0]);                                   \
    287                                                                 \
    288     for( ; size.height--; src1 += step1, src2 += step2 )        \
    289     {                                                           \
    290         int x = 0;                                              \
    291         while( x < size.width )                                 \
    292         {                                                       \
    293             int limit = MIN( remaining, size.width - x );       \
    294             remaining -= limit;                                 \
    295             limit += x;                                         \
    296             ICV_NORM_DIFF_CASE( _op_, _update_op_,              \
    297                                 worktype, limit );              \
    298             if( remaining == 0 )                                \
    299             {                                                   \
    300                 remaining = block_size;                         \
    301                 total_norm += (normtype)norm;                   \
    302                 norm = 0;                                       \
    303             }                                                   \
    304         }                                                       \
    305     }                                                           \
    306                                                                 \
    307     total_norm += (normtype)norm;                               \
    308     *_norm = post_func((double)total_norm);                     \
    309     return CV_OK;                                               \
    310 }
    311 
    312 
    313 #define  ICV_DEF_NORM_DIFF_NOHINT_FUNC_2D( name, _op_,          \
    314     _update_op_, post_func,                                     \
    315     arrtype, normtype, worktype, block_size )                   \
    316 IPCVAPI_IMPL( CvStatus, name,( const arrtype* src1, int step1,  \
    317     const arrtype* src2, int step2, CvSize size, double* _norm),\
    318     ( src1, step1, src2, step2, size, _norm ))                  \
    319 {                                                               \
    320     normtype norm = 0;                                          \
    321     step1 /= sizeof(src1[0]);                                   \
    322     step2 /= sizeof(src2[0]);                                   \
    323                                                                 \
    324     for( ; size.height--; src1 += step1, src2 += step2 )        \
    325     {                                                           \
    326         int x = 0;                                              \
    327         ICV_NORM_DIFF_CASE( _op_, _update_op_,                  \
    328                             worktype, size.width );             \
    329     }                                                           \
    330                                                                 \
    331     *_norm = post_func((double)norm);                           \
    332     return CV_OK;                                               \
    333 }
    334 
    335 
    336 #define  ICV_DEF_NORM_DIFF_HINT_FUNC_2D( name, _op_,            \
    337     _update_op_, post_func,                                     \
    338     arrtype, normtype, worktype, block_size )                   \
    339 IPCVAPI_IMPL( CvStatus, name,( const arrtype* src1, int step1,  \
    340     const arrtype* src2, int step2, CvSize size, double* _norm, \
    341     CvHintAlgorithm /*hint*/ ),                                 \
    342     (src1, step1, src2, step2, size, _norm, cvAlgHintAccurate ))\
    343 {                                                               \
    344     normtype norm = 0;                                          \
    345     step1 /= sizeof(src1[0]);                                   \
    346     step2 /= sizeof(src2[0]);                                   \
    347                                                                 \
    348     for( ; size.height--; src1 += step1, src2 += step2 )        \
    349     {                                                           \
    350         int x = 0;                                              \
    351         ICV_NORM_DIFF_CASE( _op_, _update_op_,                  \
    352                             worktype, size.width );             \
    353     }                                                           \
    354                                                                 \
    355     *_norm = post_func((double)norm);                           \
    356     return CV_OK;                                               \
    357 }
    358 
    359 
    360 #define  ICV_DEF_NORM_DIFF_NOHINT_BLOCK_FUNC_2D_COI( name, _op_,\
    361     _update_op_, post_func, arrtype,                            \
    362     normtype, worktype, block_size )                            \
    363 static CvStatus CV_STDCALL name( const arrtype* src1, int step1,\
    364     const arrtype* src2, int step2, CvSize size,                \
    365     int cn, int coi, double* _norm )                            \
    366 {                                                               \
    367     int remaining = block_size;                                 \
    368     normtype total_norm = 0;                                    \
    369     worktype norm = 0;                                          \
    370     step1 /= sizeof(src1[0]);                                   \
    371     step2 /= sizeof(src2[0]);                                   \
    372     src1 += coi - 1;                                            \
    373     src2 += coi - 1;                                            \
    374                                                                 \
    375     for( ; size.height--; src1 += step1, src2 += step2 )        \
    376     {                                                           \
    377         int x = 0;                                              \
    378         while( x < size.width )                                 \
    379         {                                                       \
    380             int limit = MIN( remaining, size.width - x );       \
    381             remaining -= limit;                                 \
    382             limit += x;                                         \
    383             ICV_NORM_DIFF_COI_CASE( _op_, _update_op_,          \
    384                                     worktype, limit, cn );      \
    385             if( remaining == 0 )                                \
    386             {                                                   \
    387                 remaining = block_size;                         \
    388                 total_norm += (normtype)norm;                   \
    389                 norm = 0;                                       \
    390             }                                                   \
    391         }                                                       \
    392     }                                                           \
    393                                                                 \
    394     total_norm += (normtype)norm;                               \
    395     *_norm = post_func((double)total_norm);                     \
    396     return CV_OK;                                               \
    397 }
    398 
    399 
    400 #define  ICV_DEF_NORM_DIFF_NOHINT_FUNC_2D_COI( name, _op_,      \
    401     _update_op_, post_func,                                     \
    402     arrtype, normtype, worktype, block_size )                   \
    403 static CvStatus CV_STDCALL name( const arrtype* src1, int step1,\
    404     const arrtype* src2, int step2, CvSize size,                \
    405     int cn, int coi, double* _norm )                            \
    406 {                                                               \
    407     normtype norm = 0;                                          \
    408     step1 /= sizeof(src1[0]);                                   \
    409     step2 /= sizeof(src2[0]);                                   \
    410     src1 += coi - 1;                                            \
    411     src2 += coi - 1;                                            \
    412                                                                 \
    413     for( ; size.height--; src1 += step1, src2 += step2 )        \
    414     {                                                           \
    415         int x = 0;                                              \
    416         ICV_NORM_DIFF_COI_CASE( _op_, _update_op_,              \
    417                                 worktype, size.width, cn );     \
    418     }                                                           \
    419                                                                 \
    420     *_norm = post_func((double)norm);                           \
    421     return CV_OK;                                               \
    422 }
    423 
    424 
    425 /****************************************************************************************\
    426 *                             N o r m   with    M A S K                                  *
    427 \****************************************************************************************/
    428 
    429 #define ICV_NORM_MASK_CASE( _op_,               \
    430         _update_op_, worktype, len )            \
    431 {                                               \
    432     for( ; x <= (len) - 2; x += 2 )             \
    433     {                                           \
    434         worktype t0;                            \
    435         if( mask[x] )                           \
    436         {                                       \
    437             t0 = (src)[x];                      \
    438             t0 = _op_(t0);                      \
    439             norm = _update_op_( norm, t0 );     \
    440         }                                       \
    441         if( mask[x+1] )                         \
    442         {                                       \
    443             t0 = (src)[x+1];                    \
    444             t0 = _op_(t0);                      \
    445             norm = _update_op_( norm, t0 );     \
    446         }                                       \
    447     }                                           \
    448                                                 \
    449     for( ; x < (len); x++ )                     \
    450         if( mask[x] )                           \
    451         {                                       \
    452             worktype t0 = (src)[x];             \
    453             t0 = _op_(t0);                      \
    454             norm = _update_op_( norm, t0 );     \
    455         }                                       \
    456 }
    457 
    458 
    459 #define ICV_NORM_DIFF_MASK_CASE( _op_, _update_op_, worktype, len ) \
    460 {                                               \
    461     for( ; x <= (len) - 2; x += 2 )             \
    462     {                                           \
    463         worktype t0;                            \
    464         if( mask[x] )                           \
    465         {                                       \
    466             t0 = (src1)[x] - (src2)[x];         \
    467             t0 = _op_(t0);                      \
    468             norm = _update_op_( norm, t0 );     \
    469         }                                       \
    470         if( mask[x+1] )                         \
    471         {                                       \
    472             t0 = (src1)[x+1] - (src2)[x+1];     \
    473             t0 = _op_(t0);                      \
    474             norm = _update_op_( norm, t0 );     \
    475         }                                       \
    476     }                                           \
    477                                                 \
    478     for( ; x < (len); x++ )                     \
    479         if( mask[x] )                           \
    480         {                                       \
    481             worktype t0 = (src1)[x] - (src2)[x];\
    482             t0 = _op_(t0);                      \
    483             norm = _update_op_( norm, t0 );     \
    484         }                                       \
    485 }
    486 
    487 
    488 #define ICV_NORM_MASK_COI_CASE( _op_, _update_op_, worktype, len, cn ) \
    489 {                                               \
    490     for( ; x < (len); x++ )                     \
    491         if( mask[x] )                           \
    492         {                                       \
    493             worktype t0 = (src)[x*(cn)];        \
    494             t0 = _op_(t0);                      \
    495             norm = _update_op_( norm, t0 );     \
    496         }                                       \
    497 }
    498 
    499 
    500 #define ICV_NORM_DIFF_MASK_COI_CASE( _op_, _update_op_, worktype, len, cn )\
    501 {                                               \
    502     for( ; x < (len); x++ )                     \
    503         if( mask[x] )                           \
    504         {                                       \
    505             worktype t0 = (src1)[x*(cn)] - (src2)[x*(cn)];  \
    506             t0 = _op_(t0);                      \
    507             norm = _update_op_( norm, t0 );     \
    508         }                                       \
    509 }
    510 
    511 
    512 #define  ICV_DEF_NORM_MASK_NOHINT_BLOCK_FUNC_2D( name, _op_,    \
    513     _update_op_, post_func, arrtype,                            \
    514     normtype, worktype, block_size )                            \
    515 IPCVAPI_IMPL( CvStatus, name, ( const arrtype* src, int step,   \
    516     const uchar* mask, int maskstep, CvSize size, double* _norm ),\
    517     (src, step, mask, maskstep, size, _norm) )                  \
    518 {                                                               \
    519     int remaining = block_size;                                 \
    520     normtype total_norm = 0;                                    \
    521     worktype norm = 0;                                          \
    522     step /= sizeof(src[0]);                                     \
    523                                                                 \
    524     for( ; size.height--; src += step, mask += maskstep )       \
    525     {                                                           \
    526         int x = 0;                                              \
    527         while( x < size.width )                                 \
    528         {                                                       \
    529             int limit = MIN( remaining, size.width - x );       \
    530             remaining -= limit;                                 \
    531             limit += x;                                         \
    532             ICV_NORM_MASK_CASE( _op_, _update_op_,              \
    533                                 worktype, limit );              \
    534             if( remaining == 0 )                                \
    535             {                                                   \
    536                 remaining = block_size;                         \
    537                 total_norm += (normtype)norm;                   \
    538                 norm = 0;                                       \
    539             }                                                   \
    540         }                                                       \
    541     }                                                           \
    542                                                                 \
    543     total_norm += (normtype)norm;                               \
    544     *_norm = post_func((double)total_norm);                     \
    545     return CV_OK;                                               \
    546 }
    547 
    548 
    549 #define  ICV_DEF_NORM_MASK_NOHINT_FUNC_2D( name, _op_, _update_op_,\
    550     post_func, arrtype, normtype, worktype, block_size )        \
    551 IPCVAPI_IMPL( CvStatus, name, ( const arrtype* src, int step,   \
    552     const uchar* mask, int maskstep, CvSize size, double* _norm ),\
    553     (src, step, mask, maskstep, size, _norm) )                  \
    554 {                                                               \
    555     normtype norm = 0;                                          \
    556     step /= sizeof(src[0]);                                     \
    557                                                                 \
    558     for( ; size.height--; src += step, mask += maskstep )       \
    559     {                                                           \
    560         int x = 0;                                              \
    561         ICV_NORM_MASK_CASE( _op_, _update_op_,                  \
    562                             worktype, size.width );             \
    563     }                                                           \
    564                                                                 \
    565     *_norm = post_func((double)norm);                           \
    566     return CV_OK;                                               \
    567 }
    568 
    569 
    570 #define  ICV_DEF_NORM_MASK_NOHINT_BLOCK_FUNC_2D_COI( name, _op_,\
    571                 _update_op_, post_func, arrtype,                \
    572                 normtype, worktype, block_size )                \
    573 static CvStatus CV_STDCALL name( const arrtype* src, int step,  \
    574     const uchar* mask, int maskstep, CvSize size,               \
    575     int cn, int coi, double* _norm )                            \
    576 {                                                               \
    577     int remaining = block_size;                                 \
    578     normtype total_norm = 0;                                    \
    579     worktype norm = 0;                                          \
    580     step /= sizeof(src[0]);                                     \
    581     src += coi - 1;                                             \
    582                                                                 \
    583     for( ; size.height--; src += step, mask += maskstep )       \
    584     {                                                           \
    585         int x = 0;                                              \
    586         while( x < size.width )                                 \
    587         {                                                       \
    588             int limit = MIN( remaining, size.width - x );       \
    589             remaining -= limit;                                 \
    590             limit += x;                                         \
    591             ICV_NORM_MASK_COI_CASE( _op_, _update_op_,          \
    592                                     worktype, limit, cn );      \
    593             if( remaining == 0 )                                \
    594             {                                                   \
    595                 remaining = block_size;                         \
    596                 total_norm += (normtype)norm;                   \
    597                 norm = 0;                                       \
    598             }                                                   \
    599         }                                                       \
    600     }                                                           \
    601                                                                 \
    602     total_norm += (normtype)norm;                               \
    603     *_norm = post_func((double)total_norm);                     \
    604     return CV_OK;                                               \
    605 }
    606 
    607 
    608 #define  ICV_DEF_NORM_MASK_NOHINT_FUNC_2D_COI( name, _op_,      \
    609     _update_op_, post_func,                                     \
    610     arrtype, normtype, worktype, block_size )                   \
    611 static CvStatus CV_STDCALL name( const arrtype* src, int step,  \
    612     const uchar* mask, int maskstep, CvSize size,               \
    613     int cn, int coi, double* _norm )                            \
    614 {                                                               \
    615     normtype norm = 0;                                          \
    616     step /= sizeof(src[0]);                                     \
    617     src += coi - 1;                                             \
    618                                                                 \
    619     for( ; size.height--; src += step, mask += maskstep )       \
    620     {                                                           \
    621         int x = 0;                                              \
    622         ICV_NORM_MASK_COI_CASE( _op_, _update_op_,              \
    623                                 worktype, size.width, cn );     \
    624     }                                                           \
    625                                                                 \
    626     *_norm = post_func((double)norm);                           \
    627     return CV_OK;                                               \
    628 }
    629 
    630 
    631 
    632 #define  ICV_DEF_NORM_DIFF_MASK_NOHINT_BLOCK_FUNC_2D( name,     \
    633     _op_, _update_op_, post_func, arrtype,                      \
    634     normtype, worktype, block_size )                            \
    635 IPCVAPI_IMPL( CvStatus, name,( const arrtype* src1, int step1,  \
    636     const arrtype* src2, int step2, const uchar* mask,          \
    637     int maskstep, CvSize size, double* _norm ),                 \
    638     (src1, step1, src2, step2, mask, maskstep, size, _norm ))   \
    639 {                                                               \
    640     int remaining = block_size;                                 \
    641     normtype total_norm = 0;                                    \
    642     worktype norm = 0;                                          \
    643     step1 /= sizeof(src1[0]);                                   \
    644     step2 /= sizeof(src2[0]);                                   \
    645                                                                 \
    646     for( ; size.height--; src1 += step1, src2 += step2,         \
    647                           mask += maskstep )                    \
    648     {                                                           \
    649         int x = 0;                                              \
    650         while( x < size.width )                                 \
    651         {                                                       \
    652             int limit = MIN( remaining, size.width - x );       \
    653             remaining -= limit;                                 \
    654             limit += x;                                         \
    655             ICV_NORM_DIFF_MASK_CASE( _op_, _update_op_,         \
    656                                      worktype, limit );         \
    657             if( remaining == 0 )                                \
    658             {                                                   \
    659                 remaining = block_size;                         \
    660                 total_norm += (normtype)norm;                   \
    661                 norm = 0;                                       \
    662             }                                                   \
    663         }                                                       \
    664     }                                                           \
    665                                                                 \
    666     total_norm += (normtype)norm;                               \
    667     *_norm = post_func((double)total_norm);                     \
    668     return CV_OK;                                               \
    669 }
    670 
    671 
    672 #define  ICV_DEF_NORM_DIFF_MASK_NOHINT_FUNC_2D( name, _op_,     \
    673     _update_op_, post_func,                                     \
    674     arrtype, normtype, worktype, block_size )                   \
    675 IPCVAPI_IMPL( CvStatus, name,( const arrtype* src1, int step1,  \
    676     const arrtype* src2, int step2, const uchar* mask,          \
    677     int maskstep, CvSize size, double* _norm ),                 \
    678     (src1, step1, src2, step2, mask, maskstep, size, _norm ))   \
    679 {                                                               \
    680     normtype norm = 0;                                          \
    681     step1 /= sizeof(src1[0]);                                   \
    682     step2 /= sizeof(src2[0]);                                   \
    683                                                                 \
    684     for( ; size.height--; src1 += step1, src2 += step2,         \
    685                           mask += maskstep )                    \
    686     {                                                           \
    687         int x = 0;                                              \
    688         ICV_NORM_DIFF_MASK_CASE( _op_, _update_op_,             \
    689                                  worktype, size.width );        \
    690     }                                                           \
    691                                                                 \
    692     *_norm = post_func((double)norm);                           \
    693     return CV_OK;                                               \
    694 }
    695 
    696 
    697 #define  ICV_DEF_NORM_DIFF_MASK_NOHINT_BLOCK_FUNC_2D_COI( name, \
    698     _op_, _update_op_, post_func, arrtype,                      \
    699     normtype, worktype, block_size )                            \
    700 static CvStatus CV_STDCALL name( const arrtype* src1, int step1,\
    701     const arrtype* src2, int step2, const uchar* mask,          \
    702     int maskstep, CvSize size, int cn, int coi, double* _norm ) \
    703 {                                                               \
    704     int remaining = block_size;                                 \
    705     normtype total_norm = 0;                                    \
    706     worktype norm = 0;                                          \
    707     step1 /= sizeof(src1[0]);                                   \
    708     step2 /= sizeof(src2[0]);                                   \
    709     src1 += coi - 1;                                            \
    710     src2 += coi - 1;                                            \
    711                                                                 \
    712     for( ; size.height--; src1 += step1, src2 += step2,         \
    713                           mask += maskstep )                    \
    714     {                                                           \
    715         int x = 0;                                              \
    716         while( x < size.width )                                 \
    717         {                                                       \
    718             int limit = MIN( remaining, size.width - x );       \
    719             remaining -= limit;                                 \
    720             limit += x;                                         \
    721             ICV_NORM_DIFF_MASK_COI_CASE( _op_, _update_op_,     \
    722                                     worktype, limit, cn );      \
    723             if( remaining == 0 )                                \
    724             {                                                   \
    725                 remaining = block_size;                         \
    726                 total_norm += (normtype)norm;                   \
    727                 norm = 0;                                       \
    728             }                                                   \
    729         }                                                       \
    730     }                                                           \
    731                                                                 \
    732     total_norm += (normtype)norm;                               \
    733     *_norm = post_func((double)total_norm);                     \
    734     return CV_OK;                                               \
    735 }
    736 
    737 
    738 #define  ICV_DEF_NORM_DIFF_MASK_NOHINT_FUNC_2D_COI( name, _op_, \
    739     _update_op_, post_func,                                     \
    740     arrtype, normtype, worktype, block_size )                   \
    741 static CvStatus CV_STDCALL name( const arrtype* src1, int step1,\
    742     const arrtype* src2, int step2, const uchar* mask,          \
    743     int maskstep, CvSize size, int cn, int coi, double* _norm ) \
    744 {                                                               \
    745     normtype norm = 0;                                          \
    746     step1 /= sizeof(src1[0]);                                   \
    747     step2 /= sizeof(src2[0]);                                   \
    748     src1 += coi - 1;                                            \
    749     src2 += coi - 1;                                            \
    750                                                                 \
    751     for( ; size.height--; src1 += step1, src2 += step2,         \
    752                           mask += maskstep )                    \
    753     {                                                           \
    754         int x = 0;                                              \
    755         ICV_NORM_DIFF_MASK_COI_CASE( _op_, _update_op_,         \
    756                                      worktype, size.width, cn );\
    757     }                                                           \
    758                                                                 \
    759     *_norm = post_func((double)norm);                           \
    760     return CV_OK;                                               \
    761 }
    762 
    763 
    764 //////////////////////////////////// The macros expanded /////////////////////////////////
    765 
    766 
    767 #define ICV_DEF_NORM_FUNC_ALL_C(flavor, _abs_, _abs_diff_, arrtype, worktype)\
    768                                                                             \
    769 ICV_DEF_NORM_NOHINT_FUNC_2D( icvNorm_Inf_##flavor##_C1R,                    \
    770     _abs_, MAX, CV_NOP, arrtype, worktype, worktype, 0 )                    \
    771                                                                             \
    772 ICV_DEF_NORM_NOHINT_FUNC_2D_COI( icvNorm_Inf_##flavor##_CnCR,               \
    773     _abs_, MAX, CV_NOP, arrtype, worktype, worktype, 0 )                    \
    774                                                                             \
    775 ICV_DEF_NORM_DIFF_NOHINT_FUNC_2D( icvNormDiff_Inf_##flavor##_C1R,           \
    776     _abs_diff_, MAX, CV_NOP, arrtype, worktype, worktype, 0 )               \
    777                                                                             \
    778 ICV_DEF_NORM_DIFF_NOHINT_FUNC_2D_COI( icvNormDiff_Inf_##flavor##_CnCR,      \
    779     _abs_diff_, MAX, CV_NOP, arrtype, worktype, worktype, 0 )               \
    780                                                                             \
    781 ICV_DEF_NORM_MASK_NOHINT_FUNC_2D( icvNorm_Inf_##flavor##_C1MR,              \
    782     _abs_, MAX, CV_NOP, arrtype, worktype, worktype, 0 )                    \
    783                                                                             \
    784 ICV_DEF_NORM_MASK_NOHINT_FUNC_2D_COI( icvNorm_Inf_##flavor##_CnCMR,         \
    785     _abs_, MAX, CV_NOP, arrtype, worktype, worktype, 0 )                    \
    786                                                                             \
    787 ICV_DEF_NORM_DIFF_MASK_NOHINT_FUNC_2D( icvNormDiff_Inf_##flavor##_C1MR,     \
    788     _abs_diff_, MAX, CV_NOP, arrtype, worktype, worktype, 0 )               \
    789                                                                             \
    790 ICV_DEF_NORM_DIFF_MASK_NOHINT_FUNC_2D_COI( icvNormDiff_Inf_##flavor##_CnCMR,\
    791     _abs_diff_, MAX, CV_NOP, arrtype, worktype, worktype, 0 )
    792 
    793 
    794 ICV_DEF_NORM_FUNC_ALL_C( 8u, CV_NOP, CV_IABS, uchar, int )
    795 ICV_DEF_NORM_FUNC_ALL_C( 16u, CV_NOP, CV_IABS, ushort, int )
    796 ICV_DEF_NORM_FUNC_ALL_C( 16s, CV_IABS, CV_IABS, short, int )
    797 // there is no protection from overflow
    798 // (otherwise we had to do everything in int64's or double's)
    799 ICV_DEF_NORM_FUNC_ALL_C( 32s, CV_IABS, CV_IABS, int, int )
    800 ICV_DEF_NORM_FUNC_ALL_C( 32f, fabs, fabs, float, double )
    801 ICV_DEF_NORM_FUNC_ALL_C( 64f, fabs, fabs, double, double )
    802 
    803 #define ICV_DEF_NORM_FUNC_ALL_L1( flavor, _abs_, _abs_diff_, hintp_func, nohint_func,\
    804                                   arrtype, normtype, worktype, block_size )         \
    805                                                                                     \
    806 ICV_DEF_NORM_##hintp_func##_FUNC_2D( icvNorm_L1_##flavor##_C1R,                     \
    807     _abs_, CV_ADD, CV_NOP, arrtype, normtype, worktype, block_size )                \
    808                                                                                     \
    809 ICV_DEF_NORM_##nohint_func##_FUNC_2D_COI( icvNorm_L1_##flavor##_CnCR,               \
    810     _abs_, CV_ADD, CV_NOP, arrtype, normtype, worktype, block_size )                \
    811                                                                                     \
    812 ICV_DEF_NORM_DIFF_##hintp_func##_FUNC_2D( icvNormDiff_L1_##flavor##_C1R,            \
    813     _abs_diff_, CV_ADD, CV_NOP, arrtype, normtype, worktype, block_size )           \
    814                                                                                     \
    815 ICV_DEF_NORM_DIFF_##nohint_func##_FUNC_2D_COI( icvNormDiff_L1_##flavor##_CnCR,      \
    816     _abs_diff_, CV_ADD, CV_NOP, arrtype, normtype, worktype, block_size )           \
    817                                                                                     \
    818 ICV_DEF_NORM_MASK_##nohint_func##_FUNC_2D( icvNorm_L1_##flavor##_C1MR,              \
    819     _abs_, CV_ADD, CV_NOP, arrtype, normtype, worktype, block_size )                \
    820                                                                                     \
    821 ICV_DEF_NORM_MASK_##nohint_func##_FUNC_2D_COI( icvNorm_L1_##flavor##_CnCMR,         \
    822     _abs_, CV_ADD, CV_NOP, arrtype, normtype, worktype, block_size )                \
    823                                                                                     \
    824 ICV_DEF_NORM_DIFF_MASK_##nohint_func##_FUNC_2D( icvNormDiff_L1_##flavor##_C1MR,     \
    825     _abs_diff_, CV_ADD, CV_NOP, arrtype, normtype, worktype, block_size )           \
    826                                                                                     \
    827 ICV_DEF_NORM_DIFF_MASK_##nohint_func##_FUNC_2D_COI( icvNormDiff_L1_##flavor##_CnCMR,\
    828     _abs_diff_, CV_ADD, CV_NOP, arrtype, normtype, worktype, block_size )
    829 
    830 
    831 ICV_DEF_NORM_FUNC_ALL_L1( 8u, CV_NOP, CV_IABS, NOHINT_BLOCK, NOHINT_BLOCK,
    832                           uchar, int64, int, 1 << 23 )
    833 ICV_DEF_NORM_FUNC_ALL_L1( 16u, CV_NOP, CV_IABS, NOHINT_BLOCK, NOHINT_BLOCK,
    834                           ushort, int64, int, 1 << 15 )
    835 ICV_DEF_NORM_FUNC_ALL_L1( 16s, CV_IABS, CV_IABS, NOHINT_BLOCK, NOHINT_BLOCK,
    836                           short, int64, int, 1 << 15 )
    837 // there is no protection from overflow on abs() stage.
    838 // (otherwise we had to do everything in int64's or double's)
    839 ICV_DEF_NORM_FUNC_ALL_L1( 32s, fabs, fabs, NOHINT, NOHINT,
    840                           int, double, double, INT_MAX )
    841 ICV_DEF_NORM_FUNC_ALL_L1( 32f, fabs, fabs, HINT, NOHINT,
    842                           float, double, double, INT_MAX )
    843 ICV_DEF_NORM_FUNC_ALL_L1( 64f, fabs, fabs, NOHINT, NOHINT,
    844                           double, double, double, INT_MAX )
    845 
    846 
    847 #define ICV_DEF_NORM_FUNC_ALL_L2( flavor, hintp_func, nohint_func, arrtype,         \
    848                                   normtype, worktype, block_size, sqr_macro )       \
    849                                                                                     \
    850 ICV_DEF_NORM_##hintp_func##_FUNC_2D( icvNorm_L2_##flavor##_C1R,                     \
    851     sqr_macro, CV_ADD, sqrt, arrtype, normtype, worktype, block_size )              \
    852                                                                                     \
    853 ICV_DEF_NORM_##nohint_func##_FUNC_2D_COI( icvNorm_L2_##flavor##_CnCR,               \
    854     sqr_macro, CV_ADD, sqrt, arrtype, normtype, worktype, block_size )              \
    855                                                                                     \
    856 ICV_DEF_NORM_DIFF_##hintp_func##_FUNC_2D( icvNormDiff_L2_##flavor##_C1R,            \
    857     sqr_macro, CV_ADD, sqrt, arrtype, normtype, worktype, block_size )              \
    858                                                                                     \
    859 ICV_DEF_NORM_DIFF_##nohint_func##_FUNC_2D_COI( icvNormDiff_L2_##flavor##_CnCR,      \
    860     sqr_macro, CV_ADD, sqrt, arrtype, normtype, worktype, block_size )              \
    861                                                                                     \
    862 ICV_DEF_NORM_MASK_##nohint_func##_FUNC_2D( icvNorm_L2_##flavor##_C1MR,              \
    863     sqr_macro, CV_ADD, sqrt, arrtype, normtype, worktype, block_size )              \
    864                                                                                     \
    865 ICV_DEF_NORM_MASK_##nohint_func##_FUNC_2D_COI( icvNorm_L2_##flavor##_CnCMR,         \
    866     sqr_macro, CV_ADD, sqrt, arrtype, normtype, worktype, block_size )              \
    867                                                                                     \
    868 ICV_DEF_NORM_DIFF_MASK_##nohint_func##_FUNC_2D( icvNormDiff_L2_##flavor##_C1MR,     \
    869     sqr_macro, CV_ADD, sqrt, arrtype, normtype, worktype, block_size )              \
    870                                                                                     \
    871 ICV_DEF_NORM_DIFF_MASK_##nohint_func##_FUNC_2D_COI( icvNormDiff_L2_##flavor##_CnCMR,\
    872     sqr_macro, CV_ADD, sqrt, arrtype, normtype, worktype, block_size )
    873 
    874 
    875 ICV_DEF_NORM_FUNC_ALL_L2( 8u, NOHINT_BLOCK, NOHINT_BLOCK, uchar,
    876                           int64, int, 1 << 15, CV_SQR_8U )
    877 ICV_DEF_NORM_FUNC_ALL_L2( 16u, NOHINT, NOHINT, ushort,
    878                           double, double, INT_MAX, CV_SQR )
    879 ICV_DEF_NORM_FUNC_ALL_L2( 16s, NOHINT, NOHINT, short,
    880                           double, double, INT_MAX, CV_SQR )
    881 // there is no protection from overflow on abs() stage.
    882 // (otherwise we had to do everything in int64's or double's)
    883 ICV_DEF_NORM_FUNC_ALL_L2( 32s, NOHINT, NOHINT, int,
    884                           double, double, INT_MAX, CV_SQR )
    885 ICV_DEF_NORM_FUNC_ALL_L2( 32f, HINT, NOHINT, float,
    886                           double, double, INT_MAX, CV_SQR )
    887 ICV_DEF_NORM_FUNC_ALL_L2( 64f, NOHINT, NOHINT, double,
    888                           double, double, INT_MAX, CV_SQR )
    889 
    890 
    891 #define ICV_DEF_INIT_NORM_TAB_2D( FUNCNAME, FLAG )              \
    892 static void icvInit##FUNCNAME##FLAG##Table( CvFuncTable* tab )  \
    893 {                                                               \
    894     tab->fn_2d[CV_8U] = (void*)icv##FUNCNAME##_8u_##FLAG;       \
    895     tab->fn_2d[CV_8S] = 0;                                      \
    896     tab->fn_2d[CV_16U] = (void*)icv##FUNCNAME##_16u_##FLAG;     \
    897     tab->fn_2d[CV_16S] = (void*)icv##FUNCNAME##_16s_##FLAG;     \
    898     tab->fn_2d[CV_32S] = (void*)icv##FUNCNAME##_32s_##FLAG;     \
    899     tab->fn_2d[CV_32F] = (void*)icv##FUNCNAME##_32f_##FLAG;     \
    900     tab->fn_2d[CV_64F] = (void*)icv##FUNCNAME##_64f_##FLAG;     \
    901 }
    902 
    903 ICV_DEF_INIT_NORM_TAB_2D( Norm_Inf, C1R )
    904 ICV_DEF_INIT_NORM_TAB_2D( Norm_L1, C1R )
    905 ICV_DEF_INIT_NORM_TAB_2D( Norm_L2, C1R )
    906 ICV_DEF_INIT_NORM_TAB_2D( NormDiff_Inf, C1R )
    907 ICV_DEF_INIT_NORM_TAB_2D( NormDiff_L1, C1R )
    908 ICV_DEF_INIT_NORM_TAB_2D( NormDiff_L2, C1R )
    909 
    910 ICV_DEF_INIT_NORM_TAB_2D( Norm_Inf, CnCR )
    911 ICV_DEF_INIT_NORM_TAB_2D( Norm_L1, CnCR )
    912 ICV_DEF_INIT_NORM_TAB_2D( Norm_L2, CnCR )
    913 ICV_DEF_INIT_NORM_TAB_2D( NormDiff_Inf, CnCR )
    914 ICV_DEF_INIT_NORM_TAB_2D( NormDiff_L1, CnCR )
    915 ICV_DEF_INIT_NORM_TAB_2D( NormDiff_L2, CnCR )
    916 
    917 ICV_DEF_INIT_NORM_TAB_2D( Norm_Inf, C1MR )
    918 ICV_DEF_INIT_NORM_TAB_2D( Norm_L1, C1MR )
    919 ICV_DEF_INIT_NORM_TAB_2D( Norm_L2, C1MR )
    920 ICV_DEF_INIT_NORM_TAB_2D( NormDiff_Inf, C1MR )
    921 ICV_DEF_INIT_NORM_TAB_2D( NormDiff_L1, C1MR )
    922 ICV_DEF_INIT_NORM_TAB_2D( NormDiff_L2, C1MR )
    923 
    924 ICV_DEF_INIT_NORM_TAB_2D( Norm_Inf, CnCMR )
    925 ICV_DEF_INIT_NORM_TAB_2D( Norm_L1, CnCMR )
    926 ICV_DEF_INIT_NORM_TAB_2D( Norm_L2, CnCMR )
    927 ICV_DEF_INIT_NORM_TAB_2D( NormDiff_Inf, CnCMR )
    928 ICV_DEF_INIT_NORM_TAB_2D( NormDiff_L1, CnCMR )
    929 ICV_DEF_INIT_NORM_TAB_2D( NormDiff_L2, CnCMR )
    930 
    931 
    932 static void icvInitNormTabs( CvFuncTable* norm_tab, CvFuncTable* normmask_tab )
    933 {
    934     icvInitNorm_InfC1RTable( &norm_tab[0] );
    935     icvInitNorm_L1C1RTable( &norm_tab[1] );
    936     icvInitNorm_L2C1RTable( &norm_tab[2] );
    937     icvInitNormDiff_InfC1RTable( &norm_tab[3] );
    938     icvInitNormDiff_L1C1RTable( &norm_tab[4] );
    939     icvInitNormDiff_L2C1RTable( &norm_tab[5] );
    940 
    941     icvInitNorm_InfCnCRTable( &norm_tab[6] );
    942     icvInitNorm_L1CnCRTable( &norm_tab[7] );
    943     icvInitNorm_L2CnCRTable( &norm_tab[8] );
    944     icvInitNormDiff_InfCnCRTable( &norm_tab[9] );
    945     icvInitNormDiff_L1CnCRTable( &norm_tab[10] );
    946     icvInitNormDiff_L2CnCRTable( &norm_tab[11] );
    947 
    948     icvInitNorm_InfC1MRTable( &normmask_tab[0] );
    949     icvInitNorm_L1C1MRTable( &normmask_tab[1] );
    950     icvInitNorm_L2C1MRTable( &normmask_tab[2] );
    951     icvInitNormDiff_InfC1MRTable( &normmask_tab[3] );
    952     icvInitNormDiff_L1C1MRTable( &normmask_tab[4] );
    953     icvInitNormDiff_L2C1MRTable( &normmask_tab[5] );
    954 
    955     icvInitNorm_InfCnCMRTable( &normmask_tab[6] );
    956     icvInitNorm_L1CnCMRTable( &normmask_tab[7] );
    957     icvInitNorm_L2CnCMRTable( &normmask_tab[8] );
    958     icvInitNormDiff_InfCnCMRTable( &normmask_tab[9] );
    959     icvInitNormDiff_L1CnCMRTable( &normmask_tab[10] );
    960     icvInitNormDiff_L2CnCMRTable( &normmask_tab[11] );
    961 }
    962 
    963 
    964 CV_IMPL  double
    965 cvNorm( const void* imgA, const void* imgB, int normType, const void* mask )
    966 {
    967     static CvFuncTable norm_tab[12];
    968     static CvFuncTable normmask_tab[12];
    969     static int inittab = 0;
    970 
    971     double  norm = 0, norm_diff = 0;
    972 
    973     CV_FUNCNAME("cvNorm");
    974 
    975     __BEGIN__;
    976 
    977     int type, depth, cn, is_relative;
    978     CvSize size;
    979     CvMat stub1, *mat1 = (CvMat*)imgB;
    980     CvMat stub2, *mat2 = (CvMat*)imgA;
    981     int mat2_flag = CV_MAT_CONT_FLAG;
    982     int mat1_step, mat2_step, mask_step = 0;
    983     int coi = 0, coi2 = 0;
    984 
    985     if( !mat1 )
    986     {
    987         mat1 = mat2;
    988         mat2 = 0;
    989     }
    990 
    991     is_relative = mat2 && (normType & CV_RELATIVE);
    992     normType &= ~CV_RELATIVE;
    993 
    994     switch( normType )
    995     {
    996     case CV_C:
    997     case CV_L1:
    998     case CV_L2:
    999     case CV_DIFF_C:
   1000     case CV_DIFF_L1:
   1001     case CV_DIFF_L2:
   1002         normType = (normType & 7) >> 1;
   1003         break;
   1004     default:
   1005         CV_ERROR( CV_StsBadFlag, "" );
   1006     }
   1007 
   1008     /* light variant */
   1009     if( CV_IS_MAT(mat1) && (!mat2 || CV_IS_MAT(mat2)) && !mask )
   1010     {
   1011         if( mat2 )
   1012         {
   1013             if( !CV_ARE_TYPES_EQ( mat1, mat2 ))
   1014                 CV_ERROR( CV_StsUnmatchedFormats, "" );
   1015 
   1016             if( !CV_ARE_SIZES_EQ( mat1, mat2 ))
   1017                 CV_ERROR( CV_StsUnmatchedSizes, "" );
   1018 
   1019             mat2_flag = mat2->type;
   1020         }
   1021 
   1022         size = cvGetMatSize( mat1 );
   1023         type = CV_MAT_TYPE(mat1->type);
   1024         depth = CV_MAT_DEPTH(type);
   1025         cn = CV_MAT_CN(type);
   1026 
   1027         if( CV_IS_MAT_CONT( mat1->type & mat2_flag ))
   1028         {
   1029             size.width *= size.height;
   1030 
   1031             if( size.width <= CV_MAX_INLINE_MAT_OP_SIZE && normType == 2 /* CV_L2 */ )
   1032             {
   1033                 if( depth == CV_32F )
   1034                 {
   1035                     const float* src1data = mat1->data.fl;
   1036                     int size0 = size.width *= cn;
   1037 
   1038                     if( !mat2 || is_relative )
   1039                     {
   1040                         do
   1041                         {
   1042                             double t = src1data[size.width-1];
   1043                             norm += t*t;
   1044                         }
   1045                         while( --size.width );
   1046                     }
   1047 
   1048                     if( mat2 )
   1049                     {
   1050                         const float* src2data = mat2->data.fl;
   1051                         size.width = size0;
   1052 
   1053                         do
   1054                         {
   1055                             double t = src1data[size.width-1] - src2data[size.width-1];
   1056                             norm_diff += t*t;
   1057                         }
   1058                         while( --size.width );
   1059 
   1060                         if( is_relative )
   1061                             norm = norm_diff/(norm + DBL_EPSILON);
   1062                         else
   1063                             norm = norm_diff;
   1064                     }
   1065                     norm = sqrt(norm);
   1066                     EXIT;
   1067                 }
   1068 
   1069                 if( depth == CV_64F )
   1070                 {
   1071                     const double* src1data = mat1->data.db;
   1072                     int size0 = size.width *= cn;
   1073 
   1074                     if( !mat2 || is_relative )
   1075                     {
   1076                         do
   1077                         {
   1078                             double t = src1data[size.width-1];
   1079                             norm += t*t;
   1080                         }
   1081                         while( --size.width );
   1082                     }
   1083 
   1084                     if( mat2 )
   1085                     {
   1086                         const double* src2data = mat2->data.db;
   1087                         size.width = size0;
   1088 
   1089                         do
   1090                         {
   1091                             double t = src1data[size.width-1] - src2data[size.width-1];
   1092                             norm_diff += t*t;
   1093                         }
   1094                         while( --size.width );
   1095 
   1096                         if( is_relative )
   1097                             norm = norm_diff/(norm + DBL_EPSILON);
   1098                         else
   1099                             norm = norm_diff;
   1100                     }
   1101                     norm = sqrt(norm);
   1102                     EXIT;
   1103                 }
   1104             }
   1105             size.height = 1;
   1106             mat1_step = mat2_step = CV_STUB_STEP;
   1107         }
   1108         else
   1109         {
   1110             mat1_step = mat1->step;
   1111             mat2_step = mat2 ? mat2->step : 0;
   1112         }
   1113     }
   1114     else if( !CV_IS_MATND(mat1) && !CV_IS_MATND(mat2) )
   1115     {
   1116         CV_CALL( mat1 = cvGetMat( mat1, &stub1, &coi ));
   1117 
   1118         if( mat2 )
   1119         {
   1120             CV_CALL( mat2 = cvGetMat( mat2, &stub2, &coi2 ));
   1121 
   1122             if( !CV_ARE_TYPES_EQ( mat1, mat2 ))
   1123                 CV_ERROR( CV_StsUnmatchedFormats, "" );
   1124 
   1125             if( !CV_ARE_SIZES_EQ( mat1, mat2 ))
   1126                 CV_ERROR( CV_StsUnmatchedSizes, "" );
   1127 
   1128             if( coi != coi2 && CV_MAT_CN( mat1->type ) > 1 )
   1129                 CV_ERROR( CV_BadCOI, "" );
   1130 
   1131             mat2_flag = mat2->type;
   1132         }
   1133 
   1134         size = cvGetMatSize( mat1 );
   1135         type = CV_MAT_TYPE(mat1->type);
   1136         depth = CV_MAT_DEPTH(type);
   1137         cn = CV_MAT_CN(type);
   1138         mat1_step = mat1->step;
   1139         mat2_step = mat2 ? mat2->step : 0;
   1140 
   1141         if( !mask && CV_IS_MAT_CONT( mat1->type & mat2_flag ))
   1142         {
   1143             size.width *= size.height;
   1144             size.height = 1;
   1145             mat1_step = mat2_step = CV_STUB_STEP;
   1146         }
   1147     }
   1148     else
   1149     {
   1150         CvArr* arrs[] = { mat1, mat2 };
   1151         CvMatND stubs[2];
   1152         CvNArrayIterator iterator;
   1153         int pass_hint;
   1154 
   1155         if( !inittab )
   1156         {
   1157             icvInitNormTabs( norm_tab, normmask_tab );
   1158             inittab = 1;
   1159         }
   1160 
   1161         if( mask )
   1162             CV_ERROR( CV_StsBadMask,
   1163             "This operation on multi-dimensional arrays does not support mask" );
   1164 
   1165         CV_CALL( cvInitNArrayIterator( 1 + (mat2 != 0), arrs, 0, stubs, &iterator ));
   1166 
   1167         type = CV_MAT_TYPE(iterator.hdr[0]->type);
   1168         depth = CV_MAT_DEPTH(type);
   1169         iterator.size.width *= CV_MAT_CN(type);
   1170 
   1171         pass_hint = normType != 0 && (depth == CV_32F);
   1172 
   1173         if( !mat2 || is_relative )
   1174         {
   1175             if( !pass_hint )
   1176             {
   1177                 CvFunc2D_1A1P func;
   1178 
   1179                 CV_GET_FUNC_PTR( func, (CvFunc2D_1A1P)norm_tab[normType].fn_2d[depth]);
   1180 
   1181                 do
   1182                 {
   1183                     double temp = 0;
   1184                     IPPI_CALL( func( iterator.ptr[0], CV_STUB_STEP,
   1185                                      iterator.size, &temp ));
   1186                     norm += temp;
   1187                 }
   1188                 while( cvNextNArraySlice( &iterator ));
   1189             }
   1190             else
   1191             {
   1192                 CvFunc2D_1A1P1I func;
   1193 
   1194                 CV_GET_FUNC_PTR( func, (CvFunc2D_1A1P1I)norm_tab[normType].fn_2d[depth]);
   1195 
   1196                 do
   1197                 {
   1198                     double temp = 0;
   1199                     IPPI_CALL( func( iterator.ptr[0], CV_STUB_STEP,
   1200                                      iterator.size, &temp, cvAlgHintAccurate ));
   1201                     norm += temp;
   1202                 }
   1203                 while( cvNextNArraySlice( &iterator ));
   1204             }
   1205         }
   1206 
   1207         if( mat2 )
   1208         {
   1209             if( !pass_hint )
   1210             {
   1211                 CvFunc2D_2A1P func;
   1212                 CV_GET_FUNC_PTR( func, (CvFunc2D_2A1P)norm_tab[3 + normType].fn_2d[depth]);
   1213 
   1214                 do
   1215                 {
   1216                     double temp = 0;
   1217                     IPPI_CALL( func( iterator.ptr[0], CV_STUB_STEP,
   1218                                      iterator.ptr[1], CV_STUB_STEP,
   1219                                      iterator.size, &temp ));
   1220                     norm_diff += temp;
   1221                 }
   1222                 while( cvNextNArraySlice( &iterator ));
   1223             }
   1224             else
   1225             {
   1226                 CvFunc2D_2A1P1I func;
   1227                 CV_GET_FUNC_PTR( func, (CvFunc2D_2A1P1I)norm_tab[3 + normType].fn_2d[depth]);
   1228 
   1229                 do
   1230                 {
   1231                     double temp = 0;
   1232                     IPPI_CALL( func( iterator.ptr[0], CV_STUB_STEP,
   1233                                      iterator.ptr[1], CV_STUB_STEP,
   1234                                      iterator.size, &temp, cvAlgHintAccurate ));
   1235                     norm_diff += temp;
   1236                 }
   1237                 while( cvNextNArraySlice( &iterator ));
   1238             }
   1239 
   1240             if( is_relative )
   1241                 norm = norm_diff/(norm + DBL_EPSILON);
   1242             else
   1243                 norm = norm_diff;
   1244         }
   1245         EXIT;
   1246     }
   1247 
   1248     if( !inittab )
   1249     {
   1250         icvInitNormTabs( norm_tab, normmask_tab );
   1251         inittab = 1;
   1252     }
   1253 
   1254     if( !mask )
   1255     {
   1256         if( cn == 1 || coi == 0 )
   1257         {
   1258             int pass_hint = depth == CV_32F && normType != 0;
   1259             size.width *= cn;
   1260 
   1261             if( !mat2 || is_relative )
   1262             {
   1263                 if( !pass_hint )
   1264                 {
   1265                     CvFunc2D_1A1P func;
   1266                     CV_GET_FUNC_PTR( func, (CvFunc2D_1A1P)norm_tab[normType].fn_2d[depth]);
   1267 
   1268                     IPPI_CALL( func( mat1->data.ptr, mat1_step, size, &norm ));
   1269                 }
   1270                 else
   1271                 {
   1272                     CvFunc2D_1A1P1I func;
   1273                     CV_GET_FUNC_PTR( func, (CvFunc2D_1A1P1I)norm_tab[normType].fn_2d[depth]);
   1274 
   1275                     IPPI_CALL( func( mat1->data.ptr, mat1_step, size, &norm, cvAlgHintAccurate ));
   1276                 }
   1277             }
   1278 
   1279             if( mat2 )
   1280             {
   1281                 if( !pass_hint )
   1282                 {
   1283                     CvFunc2D_2A1P func;
   1284                     CV_GET_FUNC_PTR( func, (CvFunc2D_2A1P)norm_tab[3 + normType].fn_2d[depth]);
   1285 
   1286                     IPPI_CALL( func( mat1->data.ptr, mat1_step, mat2->data.ptr, mat2_step,
   1287                                      size, &norm_diff ));
   1288                 }
   1289                 else
   1290                 {
   1291                     CvFunc2D_2A1P1I func;
   1292                     CV_GET_FUNC_PTR( func, (CvFunc2D_2A1P1I)norm_tab[3 + normType].fn_2d[depth]);
   1293 
   1294                     IPPI_CALL( func( mat1->data.ptr, mat1_step, mat2->data.ptr, mat2_step,
   1295                                      size, &norm_diff, cvAlgHintAccurate ));
   1296                 }
   1297 
   1298                 if( is_relative )
   1299                     norm = norm_diff/(norm + DBL_EPSILON);
   1300                 else
   1301                     norm = norm_diff;
   1302             }
   1303         }
   1304         else
   1305         {
   1306             if( !mat2 || is_relative )
   1307             {
   1308                 CvFunc2DnC_1A1P func;
   1309                 CV_GET_FUNC_PTR( func, (CvFunc2DnC_1A1P)norm_tab[6 + normType].fn_2d[depth]);
   1310 
   1311                 IPPI_CALL( func( mat1->data.ptr, mat1_step, size, cn, coi, &norm ));
   1312             }
   1313 
   1314             if( mat2 )
   1315             {
   1316                 CvFunc2DnC_2A1P func;
   1317                 CV_GET_FUNC_PTR( func, (CvFunc2DnC_2A1P)norm_tab[9 + normType].fn_2d[depth]);
   1318 
   1319                 IPPI_CALL( func( mat1->data.ptr, mat1_step, mat2->data.ptr, mat2_step,
   1320                                  size, cn, coi, &norm_diff ));
   1321 
   1322                 if( is_relative )
   1323                     norm = norm_diff/(norm + DBL_EPSILON);
   1324                 else
   1325                     norm = norm_diff;
   1326             }
   1327         }
   1328     }
   1329     else
   1330     {
   1331         CvMat maskstub, *matmask = (CvMat*)mask;
   1332 
   1333         if( CV_MAT_CN(type) > 1 && coi == 0 )
   1334             CV_ERROR( CV_StsBadArg, "" );
   1335 
   1336         CV_CALL( matmask = cvGetMat( matmask, &maskstub ));
   1337 
   1338         if( !CV_IS_MASK_ARR( matmask ))
   1339             CV_ERROR( CV_StsBadMask, "" );
   1340 
   1341         if( !CV_ARE_SIZES_EQ( mat1, matmask ))
   1342             CV_ERROR( CV_StsUnmatchedSizes, "" );
   1343 
   1344         mask_step = matmask->step;
   1345 
   1346         if( CV_IS_MAT_CONT( mat1->type & mat2_flag & matmask->type ))
   1347         {
   1348             size.width *= size.height;
   1349             size.height = 1;
   1350             mat1_step = mat2_step = mask_step = CV_STUB_STEP;
   1351         }
   1352 
   1353         if( CV_MAT_CN(type) == 1 || coi == 0 )
   1354         {
   1355             if( !mat2 || is_relative )
   1356             {
   1357                 CvFunc2D_2A1P func;
   1358                 CV_GET_FUNC_PTR( func,
   1359                     (CvFunc2D_2A1P)normmask_tab[normType].fn_2d[depth]);
   1360 
   1361                 IPPI_CALL( func( mat1->data.ptr, mat1_step,
   1362                                  matmask->data.ptr, mask_step, size, &norm ));
   1363             }
   1364 
   1365             if( mat2 )
   1366             {
   1367                 CvFunc2D_3A1P func;
   1368                 CV_GET_FUNC_PTR( func,
   1369                     (CvFunc2D_3A1P)normmask_tab[3 + normType].fn_2d[depth]);
   1370 
   1371                 IPPI_CALL( func( mat1->data.ptr, mat1_step, mat2->data.ptr, mat2_step,
   1372                                  matmask->data.ptr, mask_step, size, &norm_diff ));
   1373 
   1374                 if( is_relative )
   1375                     norm = norm_diff/(norm + DBL_EPSILON);
   1376                 else
   1377                     norm = norm_diff;
   1378             }
   1379         }
   1380         else
   1381         {
   1382             if( !mat2 || is_relative )
   1383             {
   1384                 CvFunc2DnC_2A1P func;
   1385                 CV_GET_FUNC_PTR( func,
   1386                     (CvFunc2DnC_2A1P)normmask_tab[6 + normType].fn_2d[depth]);
   1387 
   1388                 IPPI_CALL( func( mat1->data.ptr, mat1_step,
   1389                                  matmask->data.ptr, mask_step,
   1390                                  size, cn, coi, &norm ));
   1391             }
   1392 
   1393             if( mat2 )
   1394             {
   1395                 CvFunc2DnC_3A1P func;
   1396                 CV_GET_FUNC_PTR( func,
   1397                     (CvFunc2DnC_3A1P)normmask_tab[9 + normType].fn_2d[depth]);
   1398 
   1399                 IPPI_CALL( func( mat1->data.ptr, mat1_step,
   1400                                  mat2->data.ptr, mat2_step,
   1401                                  matmask->data.ptr, mask_step,
   1402                                  size, cn, coi, &norm_diff ));
   1403 
   1404                 if( is_relative )
   1405                     norm = norm_diff/(norm + DBL_EPSILON);
   1406                 else
   1407                     norm = norm_diff;
   1408             }
   1409         }
   1410     }
   1411 
   1412     __END__;
   1413 
   1414     return norm;
   1415 }
   1416 
   1417 /* End of file. */
   1418