1 /*M///////////////////////////////////////////////////////////////////////////////////////
3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
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.
10 // Intel License Agreement
11 // For Open Source Computer Vision Library
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
19 // * Redistribution's of source code must retain the above copyright notice,
20 // this list of conditions and the following disclaimer.
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.
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.
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.
44 /****************************************************************************************\
46 \****************************************************************************************/
48 #define ICV_NORM_CASE( _op_, \
49 _update_op_, worktype, len ) \
51 for( ; x <= (len) - 4; x += 4 ) \
53 worktype t0 = (src)[x]; \
54 worktype t1 = (src)[x+1]; \
57 norm = _update_op_( norm, t0 ); \
58 norm = _update_op_( norm, t1 ); \
64 norm = _update_op_( norm, t0 ); \
65 norm = _update_op_( norm, t1 ); \
68 for( ; x < (len); x++ ) \
70 worktype t0 = (src)[x]; \
71 t0 = (worktype)_op_(t0); \
72 norm = _update_op_( norm, t0 ); \
76 #define ICV_NORM_COI_CASE( _op_, \
77 _update_op_, worktype, len, cn ) \
79 for( ; x < (len); x++ ) \
81 worktype t0 = (src)[x*(cn)]; \
82 t0 = (worktype)_op_(t0); \
83 norm = _update_op_( norm, t0 ); \
87 #define ICV_NORM_DIFF_CASE( _op_, \
88 _update_op_, worktype, len ) \
90 for( ; x <= (len) - 4; x += 4 ) \
92 worktype t0 = (src1)[x] - (src2)[x];\
93 worktype t1 = (src1)[x+1]-(src2)[x+1];\
98 norm = _update_op_( norm, t0 ); \
99 norm = _update_op_( norm, t1 ); \
101 t0 = (src1)[x+2] - (src2)[x+2]; \
102 t1 = (src1)[x+3] - (src2)[x+3]; \
107 norm = _update_op_( norm, t0 ); \
108 norm = _update_op_( norm, t1 ); \
111 for( ; x < (len); x++ ) \
113 worktype t0 = (src1)[x] - (src2)[x];\
114 t0 = (worktype)_op_(t0); \
115 norm = _update_op_( norm, t0 ); \
119 #define ICV_NORM_DIFF_COI_CASE( _op_, _update_op_, worktype, len, cn ) \
120 for( ; x < (len); x++ ) \
122 worktype t0 = (src1)[x*(cn)] - (src2)[x*(cn)]; \
123 t0 = (worktype)_op_(t0); \
124 norm = _update_op_( norm, t0 ); \
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
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) ) \
143 int remaining = block_size; \
144 normtype total_norm = 0; \
146 step /= sizeof(src[0]); \
148 for( ; size.height--; src += step ) \
151 while( x < size.width ) \
153 int limit = MIN( remaining, size.width - x ); \
154 remaining -= limit; \
156 ICV_NORM_CASE( _op_, _update_op_, worktype, limit );\
157 if( remaining == 0 ) \
159 remaining = block_size; \
160 total_norm += (normtype)norm; \
166 total_norm += (normtype)norm; \
167 *_norm = post_func((double)total_norm); \
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) ) \
178 step /= sizeof(src[0]); \
180 for( ; size.height--; src += step ) \
183 ICV_NORM_CASE(_op_, _update_op_, worktype, size.width); \
186 *_norm = post_func((double)norm); \
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.
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) ) \
203 step /= sizeof(src[0]); \
205 for( ; size.height--; src += step ) \
208 ICV_NORM_CASE(_op_, _update_op_, worktype, size.width); \
211 *_norm = post_func((double)norm); \
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 ) \
222 int remaining = block_size; \
223 normtype total_norm = 0; \
225 step /= sizeof(src[0]); \
228 for( ; size.height--; src += step ) \
231 while( x < size.width ) \
233 int limit = MIN( remaining, size.width - x ); \
234 remaining -= limit; \
236 ICV_NORM_COI_CASE( _op_, _update_op_, \
237 worktype, limit, cn ); \
238 if( remaining == 0 ) \
240 remaining = block_size; \
241 total_norm += (normtype)norm; \
247 total_norm += (normtype)norm; \
248 *_norm = post_func((double)total_norm); \
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 ) \
260 step /= sizeof(src[0]); \
263 for( ; size.height--; src += step ) \
266 ICV_NORM_COI_CASE( _op_, _update_op_, \
267 worktype, size.width, cn ); \
270 *_norm = post_func((double)norm); \
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)) \
282 int remaining = block_size; \
283 normtype total_norm = 0; \
285 step1 /= sizeof(src1[0]); \
286 step2 /= sizeof(src2[0]); \
288 for( ; size.height--; src1 += step1, src2 += step2 ) \
291 while( x < size.width ) \
293 int limit = MIN( remaining, size.width - x ); \
294 remaining -= limit; \
296 ICV_NORM_DIFF_CASE( _op_, _update_op_, \
298 if( remaining == 0 ) \
300 remaining = block_size; \
301 total_norm += (normtype)norm; \
307 total_norm += (normtype)norm; \
308 *_norm = post_func((double)total_norm); \
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 )) \
321 step1 /= sizeof(src1[0]); \
322 step2 /= sizeof(src2[0]); \
324 for( ; size.height--; src1 += step1, src2 += step2 ) \
327 ICV_NORM_DIFF_CASE( _op_, _update_op_, \
328 worktype, size.width ); \
331 *_norm = post_func((double)norm); \
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 ))\
345 step1 /= sizeof(src1[0]); \
346 step2 /= sizeof(src2[0]); \
348 for( ; size.height--; src1 += step1, src2 += step2 ) \
351 ICV_NORM_DIFF_CASE( _op_, _update_op_, \
352 worktype, size.width ); \
355 *_norm = post_func((double)norm); \
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 ) \
367 int remaining = block_size; \
368 normtype total_norm = 0; \
370 step1 /= sizeof(src1[0]); \
371 step2 /= sizeof(src2[0]); \
375 for( ; size.height--; src1 += step1, src2 += step2 ) \
378 while( x < size.width ) \
380 int limit = MIN( remaining, size.width - x ); \
381 remaining -= limit; \
383 ICV_NORM_DIFF_COI_CASE( _op_, _update_op_, \
384 worktype, limit, cn ); \
385 if( remaining == 0 ) \
387 remaining = block_size; \
388 total_norm += (normtype)norm; \
394 total_norm += (normtype)norm; \
395 *_norm = post_func((double)total_norm); \
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 ) \
408 step1 /= sizeof(src1[0]); \
409 step2 /= sizeof(src2[0]); \
413 for( ; size.height--; src1 += step1, src2 += step2 ) \
416 ICV_NORM_DIFF_COI_CASE( _op_, _update_op_, \
417 worktype, size.width, cn ); \
420 *_norm = post_func((double)norm); \
425 /****************************************************************************************\
426 * N o r m with M A S K *
427 \****************************************************************************************/
429 #define ICV_NORM_MASK_CASE( _op_, \
430 _update_op_, worktype, len ) \
432 for( ; x <= (len) - 2; x += 2 ) \
439 norm = _update_op_( norm, t0 ); \
445 norm = _update_op_( norm, t0 ); \
449 for( ; x < (len); x++ ) \
452 worktype t0 = (src)[x]; \
454 norm = _update_op_( norm, t0 ); \
459 #define ICV_NORM_DIFF_MASK_CASE( _op_, _update_op_, worktype, len ) \
461 for( ; x <= (len) - 2; x += 2 ) \
466 t0 = (src1)[x] - (src2)[x]; \
468 norm = _update_op_( norm, t0 ); \
472 t0 = (src1)[x+1] - (src2)[x+1]; \
474 norm = _update_op_( norm, t0 ); \
478 for( ; x < (len); x++ ) \
481 worktype t0 = (src1)[x] - (src2)[x];\
483 norm = _update_op_( norm, t0 ); \
488 #define ICV_NORM_MASK_COI_CASE( _op_, _update_op_, worktype, len, cn ) \
490 for( ; x < (len); x++ ) \
493 worktype t0 = (src)[x*(cn)]; \
495 norm = _update_op_( norm, t0 ); \
500 #define ICV_NORM_DIFF_MASK_COI_CASE( _op_, _update_op_, worktype, len, cn )\
502 for( ; x < (len); x++ ) \
505 worktype t0 = (src1)[x*(cn)] - (src2)[x*(cn)]; \
507 norm = _update_op_( norm, t0 ); \
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) ) \
519 int remaining = block_size; \
520 normtype total_norm = 0; \
522 step /= sizeof(src[0]); \
524 for( ; size.height--; src += step, mask += maskstep ) \
527 while( x < size.width ) \
529 int limit = MIN( remaining, size.width - x ); \
530 remaining -= limit; \
532 ICV_NORM_MASK_CASE( _op_, _update_op_, \
534 if( remaining == 0 ) \
536 remaining = block_size; \
537 total_norm += (normtype)norm; \
543 total_norm += (normtype)norm; \
544 *_norm = post_func((double)total_norm); \
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) ) \
556 step /= sizeof(src[0]); \
558 for( ; size.height--; src += step, mask += maskstep ) \
561 ICV_NORM_MASK_CASE( _op_, _update_op_, \
562 worktype, size.width ); \
565 *_norm = post_func((double)norm); \
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 ) \
577 int remaining = block_size; \
578 normtype total_norm = 0; \
580 step /= sizeof(src[0]); \
583 for( ; size.height--; src += step, mask += maskstep ) \
586 while( x < size.width ) \
588 int limit = MIN( remaining, size.width - x ); \
589 remaining -= limit; \
591 ICV_NORM_MASK_COI_CASE( _op_, _update_op_, \
592 worktype, limit, cn ); \
593 if( remaining == 0 ) \
595 remaining = block_size; \
596 total_norm += (normtype)norm; \
602 total_norm += (normtype)norm; \
603 *_norm = post_func((double)total_norm); \
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 ) \
616 step /= sizeof(src[0]); \
619 for( ; size.height--; src += step, mask += maskstep ) \
622 ICV_NORM_MASK_COI_CASE( _op_, _update_op_, \
623 worktype, size.width, cn ); \
626 *_norm = post_func((double)norm); \
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 )) \
640 int remaining = block_size; \
641 normtype total_norm = 0; \
643 step1 /= sizeof(src1[0]); \
644 step2 /= sizeof(src2[0]); \
646 for( ; size.height--; src1 += step1, src2 += step2, \
650 while( x < size.width ) \
652 int limit = MIN( remaining, size.width - x ); \
653 remaining -= limit; \
655 ICV_NORM_DIFF_MASK_CASE( _op_, _update_op_, \
657 if( remaining == 0 ) \
659 remaining = block_size; \
660 total_norm += (normtype)norm; \
666 total_norm += (normtype)norm; \
667 *_norm = post_func((double)total_norm); \
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 )) \
681 step1 /= sizeof(src1[0]); \
682 step2 /= sizeof(src2[0]); \
684 for( ; size.height--; src1 += step1, src2 += step2, \
688 ICV_NORM_DIFF_MASK_CASE( _op_, _update_op_, \
689 worktype, size.width ); \
692 *_norm = post_func((double)norm); \
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 ) \
704 int remaining = block_size; \
705 normtype total_norm = 0; \
707 step1 /= sizeof(src1[0]); \
708 step2 /= sizeof(src2[0]); \
712 for( ; size.height--; src1 += step1, src2 += step2, \
716 while( x < size.width ) \
718 int limit = MIN( remaining, size.width - x ); \
719 remaining -= limit; \
721 ICV_NORM_DIFF_MASK_COI_CASE( _op_, _update_op_, \
722 worktype, limit, cn ); \
723 if( remaining == 0 ) \
725 remaining = block_size; \
726 total_norm += (normtype)norm; \
732 total_norm += (normtype)norm; \
733 *_norm = post_func((double)total_norm); \
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 ) \
746 step1 /= sizeof(src1[0]); \
747 step2 /= sizeof(src2[0]); \
751 for( ; size.height--; src1 += step1, src2 += step2, \
755 ICV_NORM_DIFF_MASK_COI_CASE( _op_, _update_op_, \
756 worktype, size.width, cn );\
759 *_norm = post_func((double)norm); \
764 //////////////////////////////////// The macros expanded /////////////////////////////////
767 #define ICV_DEF_NORM_FUNC_ALL_C(flavor, _abs_, _abs_diff_, arrtype, worktype)\
769 ICV_DEF_NORM_NOHINT_FUNC_2D( icvNorm_Inf_##flavor##_C1R, \
770 _abs_, MAX, CV_NOP, arrtype, worktype, worktype, 0 ) \
772 ICV_DEF_NORM_NOHINT_FUNC_2D_COI( icvNorm_Inf_##flavor##_CnCR, \
773 _abs_, MAX, CV_NOP, arrtype, worktype, worktype, 0 ) \
775 ICV_DEF_NORM_DIFF_NOHINT_FUNC_2D( icvNormDiff_Inf_##flavor##_C1R, \
776 _abs_diff_, MAX, CV_NOP, arrtype, worktype, worktype, 0 ) \
778 ICV_DEF_NORM_DIFF_NOHINT_FUNC_2D_COI( icvNormDiff_Inf_##flavor##_CnCR, \
779 _abs_diff_, MAX, CV_NOP, arrtype, worktype, worktype, 0 ) \
781 ICV_DEF_NORM_MASK_NOHINT_FUNC_2D( icvNorm_Inf_##flavor##_C1MR, \
782 _abs_, MAX, CV_NOP, arrtype, worktype, worktype, 0 ) \
784 ICV_DEF_NORM_MASK_NOHINT_FUNC_2D_COI( icvNorm_Inf_##flavor##_CnCMR, \
785 _abs_, MAX, CV_NOP, arrtype, worktype, worktype, 0 ) \
787 ICV_DEF_NORM_DIFF_MASK_NOHINT_FUNC_2D( icvNormDiff_Inf_##flavor##_C1MR, \
788 _abs_diff_, MAX, CV_NOP, arrtype, worktype, worktype, 0 ) \
790 ICV_DEF_NORM_DIFF_MASK_NOHINT_FUNC_2D_COI( icvNormDiff_Inf_##flavor##_CnCMR,\
791 _abs_diff_, MAX, CV_NOP, arrtype, worktype, worktype, 0 )
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 )
803 #define ICV_DEF_NORM_FUNC_ALL_L1( flavor, _abs_, _abs_diff_, hintp_func, nohint_func,\
804 arrtype, normtype, worktype, block_size ) \
806 ICV_DEF_NORM_##hintp_func##_FUNC_2D( icvNorm_L1_##flavor##_C1R, \
807 _abs_, CV_ADD, CV_NOP, arrtype, normtype, worktype, block_size ) \
809 ICV_DEF_NORM_##nohint_func##_FUNC_2D_COI( icvNorm_L1_##flavor##_CnCR, \
810 _abs_, CV_ADD, CV_NOP, arrtype, normtype, worktype, block_size ) \
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 ) \
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 ) \
818 ICV_DEF_NORM_MASK_##nohint_func##_FUNC_2D( icvNorm_L1_##flavor##_C1MR, \
819 _abs_, CV_ADD, CV_NOP, arrtype, normtype, worktype, block_size ) \
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 ) \
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 ) \
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 )
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 )
847 #define ICV_DEF_NORM_FUNC_ALL_L2( flavor, hintp_func, nohint_func, arrtype, \
848 normtype, worktype, block_size, sqr_macro ) \
850 ICV_DEF_NORM_##hintp_func##_FUNC_2D( icvNorm_L2_##flavor##_C1R, \
851 sqr_macro, CV_ADD, sqrt, arrtype, normtype, worktype, block_size ) \
853 ICV_DEF_NORM_##nohint_func##_FUNC_2D_COI( icvNorm_L2_##flavor##_CnCR, \
854 sqr_macro, CV_ADD, sqrt, arrtype, normtype, worktype, block_size ) \
856 ICV_DEF_NORM_DIFF_##hintp_func##_FUNC_2D( icvNormDiff_L2_##flavor##_C1R, \
857 sqr_macro, CV_ADD, sqrt, arrtype, normtype, worktype, block_size ) \
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 ) \
862 ICV_DEF_NORM_MASK_##nohint_func##_FUNC_2D( icvNorm_L2_##flavor##_C1MR, \
863 sqr_macro, CV_ADD, sqrt, arrtype, normtype, worktype, block_size ) \
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 ) \
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 ) \
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 )
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 )
891 #define ICV_DEF_INIT_NORM_TAB_2D( FUNCNAME, FLAG ) \
892 static void icvInit##FUNCNAME##FLAG##Table( CvFuncTable* tab ) \
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; \
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 )
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 )
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 )
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 )
932 static void icvInitNormTabs( CvFuncTable* norm_tab, CvFuncTable* normmask_tab )
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] );
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] );
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] );
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] );
965 cvNorm( const void* imgA, const void* imgB, int normType, const void* mask )
967 static CvFuncTable norm_tab[12];
968 static CvFuncTable normmask_tab[12];
969 static int inittab = 0;
971 double norm = 0, norm_diff = 0;
973 CV_FUNCNAME("cvNorm");
977 int type, depth, cn, is_relative;
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;
991 is_relative = mat2 && (normType & CV_RELATIVE);
992 normType &= ~CV_RELATIVE;
1002 normType = (normType & 7) >> 1;
1005 CV_ERROR( CV_StsBadFlag, "" );
1009 if( CV_IS_MAT(mat1) && (!mat2 || CV_IS_MAT(mat2)) && !mask )
1013 if( !CV_ARE_TYPES_EQ( mat1, mat2 ))
1014 CV_ERROR( CV_StsUnmatchedFormats, "" );
1016 if( !CV_ARE_SIZES_EQ( mat1, mat2 ))
1017 CV_ERROR( CV_StsUnmatchedSizes, "" );
1019 mat2_flag = mat2->type;
1022 size = cvGetMatSize( mat1 );
1023 type = CV_MAT_TYPE(mat1->type);
1024 depth = CV_MAT_DEPTH(type);
1025 cn = CV_MAT_CN(type);
1027 if( CV_IS_MAT_CONT( mat1->type & mat2_flag ))
1029 size.width *= size.height;
1031 if( size.width <= CV_MAX_INLINE_MAT_OP_SIZE && normType == 2 /* CV_L2 */ )
1033 if( depth == CV_32F )
1035 const float* src1data = mat1->data.fl;
1036 int size0 = size.width *= cn;
1038 if( !mat2 || is_relative )
1042 double t = src1data[size.width-1];
1045 while( --size.width );
1050 const float* src2data = mat2->data.fl;
1055 double t = src1data[size.width-1] - src2data[size.width-1];
1058 while( --size.width );
1061 norm = norm_diff/(norm + DBL_EPSILON);
1069 if( depth == CV_64F )
1071 const double* src1data = mat1->data.db;
1072 int size0 = size.width *= cn;
1074 if( !mat2 || is_relative )
1078 double t = src1data[size.width-1];
1081 while( --size.width );
1086 const double* src2data = mat2->data.db;
1091 double t = src1data[size.width-1] - src2data[size.width-1];
1094 while( --size.width );
1097 norm = norm_diff/(norm + DBL_EPSILON);
1106 mat1_step = mat2_step = CV_STUB_STEP;
1110 mat1_step = mat1->step;
1111 mat2_step = mat2 ? mat2->step : 0;
1114 else if( !CV_IS_MATND(mat1) && !CV_IS_MATND(mat2) )
1116 CV_CALL( mat1 = cvGetMat( mat1, &stub1, &coi ));
1120 CV_CALL( mat2 = cvGetMat( mat2, &stub2, &coi2 ));
1122 if( !CV_ARE_TYPES_EQ( mat1, mat2 ))
1123 CV_ERROR( CV_StsUnmatchedFormats, "" );
1125 if( !CV_ARE_SIZES_EQ( mat1, mat2 ))
1126 CV_ERROR( CV_StsUnmatchedSizes, "" );
1128 if( coi != coi2 && CV_MAT_CN( mat1->type ) > 1 )
1129 CV_ERROR( CV_BadCOI, "" );
1131 mat2_flag = mat2->type;
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;
1141 if( !mask && CV_IS_MAT_CONT( mat1->type & mat2_flag ))
1143 size.width *= size.height;
1145 mat1_step = mat2_step = CV_STUB_STEP;
1150 CvArr* arrs[] = { mat1, mat2 };
1152 CvNArrayIterator iterator;
1157 icvInitNormTabs( norm_tab, normmask_tab );
1162 CV_ERROR( CV_StsBadMask,
1163 "This operation on multi-dimensional arrays does not support mask" );
1165 CV_CALL( cvInitNArrayIterator( 1 + (mat2 != 0), arrs, 0, stubs, &iterator ));
1167 type = CV_MAT_TYPE(iterator.hdr[0]->type);
1168 depth = CV_MAT_DEPTH(type);
1169 iterator.size.width *= CV_MAT_CN(type);
1171 pass_hint = normType != 0 && (depth == CV_32F);
1173 if( !mat2 || is_relative )
1179 CV_GET_FUNC_PTR( func, (CvFunc2D_1A1P)norm_tab[normType].fn_2d[depth]);
1184 IPPI_CALL( func( iterator.ptr[0], CV_STUB_STEP,
1185 iterator.size, &temp ));
1188 while( cvNextNArraySlice( &iterator ));
1192 CvFunc2D_1A1P1I func;
1194 CV_GET_FUNC_PTR( func, (CvFunc2D_1A1P1I)norm_tab[normType].fn_2d[depth]);
1199 IPPI_CALL( func( iterator.ptr[0], CV_STUB_STEP,
1200 iterator.size, &temp, cvAlgHintAccurate ));
1203 while( cvNextNArraySlice( &iterator ));
1212 CV_GET_FUNC_PTR( func, (CvFunc2D_2A1P)norm_tab[3 + normType].fn_2d[depth]);
1217 IPPI_CALL( func( iterator.ptr[0], CV_STUB_STEP,
1218 iterator.ptr[1], CV_STUB_STEP,
1219 iterator.size, &temp ));
1222 while( cvNextNArraySlice( &iterator ));
1226 CvFunc2D_2A1P1I func;
1227 CV_GET_FUNC_PTR( func, (CvFunc2D_2A1P1I)norm_tab[3 + normType].fn_2d[depth]);
1232 IPPI_CALL( func( iterator.ptr[0], CV_STUB_STEP,
1233 iterator.ptr[1], CV_STUB_STEP,
1234 iterator.size, &temp, cvAlgHintAccurate ));
1237 while( cvNextNArraySlice( &iterator ));
1241 norm = norm_diff/(norm + DBL_EPSILON);
1250 icvInitNormTabs( norm_tab, normmask_tab );
1256 if( cn == 1 || coi == 0 )
1258 int pass_hint = depth == CV_32F && normType != 0;
1261 if( !mat2 || is_relative )
1266 CV_GET_FUNC_PTR( func, (CvFunc2D_1A1P)norm_tab[normType].fn_2d[depth]);
1268 IPPI_CALL( func( mat1->data.ptr, mat1_step, size, &norm ));
1272 CvFunc2D_1A1P1I func;
1273 CV_GET_FUNC_PTR( func, (CvFunc2D_1A1P1I)norm_tab[normType].fn_2d[depth]);
1275 IPPI_CALL( func( mat1->data.ptr, mat1_step, size, &norm, cvAlgHintAccurate ));
1284 CV_GET_FUNC_PTR( func, (CvFunc2D_2A1P)norm_tab[3 + normType].fn_2d[depth]);
1286 IPPI_CALL( func( mat1->data.ptr, mat1_step, mat2->data.ptr, mat2_step,
1287 size, &norm_diff ));
1291 CvFunc2D_2A1P1I func;
1292 CV_GET_FUNC_PTR( func, (CvFunc2D_2A1P1I)norm_tab[3 + normType].fn_2d[depth]);
1294 IPPI_CALL( func( mat1->data.ptr, mat1_step, mat2->data.ptr, mat2_step,
1295 size, &norm_diff, cvAlgHintAccurate ));
1299 norm = norm_diff/(norm + DBL_EPSILON);
1306 if( !mat2 || is_relative )
1308 CvFunc2DnC_1A1P func;
1309 CV_GET_FUNC_PTR( func, (CvFunc2DnC_1A1P)norm_tab[6 + normType].fn_2d[depth]);
1311 IPPI_CALL( func( mat1->data.ptr, mat1_step, size, cn, coi, &norm ));
1316 CvFunc2DnC_2A1P func;
1317 CV_GET_FUNC_PTR( func, (CvFunc2DnC_2A1P)norm_tab[9 + normType].fn_2d[depth]);
1319 IPPI_CALL( func( mat1->data.ptr, mat1_step, mat2->data.ptr, mat2_step,
1320 size, cn, coi, &norm_diff ));
1323 norm = norm_diff/(norm + DBL_EPSILON);
1331 CvMat maskstub, *matmask = (CvMat*)mask;
1333 if( CV_MAT_CN(type) > 1 && coi == 0 )
1334 CV_ERROR( CV_StsBadArg, "" );
1336 CV_CALL( matmask = cvGetMat( matmask, &maskstub ));
1338 if( !CV_IS_MASK_ARR( matmask ))
1339 CV_ERROR( CV_StsBadMask, "" );
1341 if( !CV_ARE_SIZES_EQ( mat1, matmask ))
1342 CV_ERROR( CV_StsUnmatchedSizes, "" );
1344 mask_step = matmask->step;
1346 if( CV_IS_MAT_CONT( mat1->type & mat2_flag & matmask->type ))
1348 size.width *= size.height;
1350 mat1_step = mat2_step = mask_step = CV_STUB_STEP;
1353 if( CV_MAT_CN(type) == 1 || coi == 0 )
1355 if( !mat2 || is_relative )
1358 CV_GET_FUNC_PTR( func,
1359 (CvFunc2D_2A1P)normmask_tab[normType].fn_2d[depth]);
1361 IPPI_CALL( func( mat1->data.ptr, mat1_step,
1362 matmask->data.ptr, mask_step, size, &norm ));
1368 CV_GET_FUNC_PTR( func,
1369 (CvFunc2D_3A1P)normmask_tab[3 + normType].fn_2d[depth]);
1371 IPPI_CALL( func( mat1->data.ptr, mat1_step, mat2->data.ptr, mat2_step,
1372 matmask->data.ptr, mask_step, size, &norm_diff ));
1375 norm = norm_diff/(norm + DBL_EPSILON);
1382 if( !mat2 || is_relative )
1384 CvFunc2DnC_2A1P func;
1385 CV_GET_FUNC_PTR( func,
1386 (CvFunc2DnC_2A1P)normmask_tab[6 + normType].fn_2d[depth]);
1388 IPPI_CALL( func( mat1->data.ptr, mat1_step,
1389 matmask->data.ptr, mask_step,
1390 size, cn, coi, &norm ));
1395 CvFunc2DnC_3A1P func;
1396 CV_GET_FUNC_PTR( func,
1397 (CvFunc2DnC_3A1P)normmask_tab[9 + normType].fn_2d[depth]);
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 ));
1405 norm = norm_diff/(norm + DBL_EPSILON);