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
ICV_DEF_INIT_NORM_TAB_2D(Norm_Inf,C1R)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
cvNorm(const void * imgA,const void * imgB,int normType,const void * mask)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