Update the changelog
[opencv] / cxcore / src / cxnorm.cpp
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. */