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 )        \
140IPCVAPI_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 )        \
174IPCVAPI_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 )        \
198IPCVAPI_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 )                            \
219static 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 )                   \
256static 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 )                            \
278IPCVAPI_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 )                   \
316IPCVAPI_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 )                   \
339IPCVAPI_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 )                            \
363static 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 )                   \
403static 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 )                            \
515IPCVAPI_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 )        \
551IPCVAPI_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 )                \
573static 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 )                   \
611static 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 )                            \
635IPCVAPI_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 )                   \
675IPCVAPI_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 )                            \
700static 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 )                   \
741static 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                                                                            \
769ICV_DEF_NORM_NOHINT_FUNC_2D( icvNorm_Inf_##flavor##_C1R,                    \
770    _abs_, MAX, CV_NOP, arrtype, worktype, worktype, 0 )                    \
771                                                                            \
772ICV_DEF_NORM_NOHINT_FUNC_2D_COI( icvNorm_Inf_##flavor##_CnCR,               \
773    _abs_, MAX, CV_NOP, arrtype, worktype, worktype, 0 )                    \
774                                                                            \
775ICV_DEF_NORM_DIFF_NOHINT_FUNC_2D( icvNormDiff_Inf_##flavor##_C1R,           \
776    _abs_diff_, MAX, CV_NOP, arrtype, worktype, worktype, 0 )               \
777                                                                            \
778ICV_DEF_NORM_DIFF_NOHINT_FUNC_2D_COI( icvNormDiff_Inf_##flavor##_CnCR,      \
779    _abs_diff_, MAX, CV_NOP, arrtype, worktype, worktype, 0 )               \
780                                                                            \
781ICV_DEF_NORM_MASK_NOHINT_FUNC_2D( icvNorm_Inf_##flavor##_C1MR,              \
782    _abs_, MAX, CV_NOP, arrtype, worktype, worktype, 0 )                    \
783                                                                            \
784ICV_DEF_NORM_MASK_NOHINT_FUNC_2D_COI( icvNorm_Inf_##flavor##_CnCMR,         \
785    _abs_, MAX, CV_NOP, arrtype, worktype, worktype, 0 )                    \
786                                                                            \
787ICV_DEF_NORM_DIFF_MASK_NOHINT_FUNC_2D( icvNormDiff_Inf_##flavor##_C1MR,     \
788    _abs_diff_, MAX, CV_NOP, arrtype, worktype, worktype, 0 )               \
789                                                                            \
790ICV_DEF_NORM_DIFF_MASK_NOHINT_FUNC_2D_COI( icvNormDiff_Inf_##flavor##_CnCMR,\
791    _abs_diff_, MAX, CV_NOP, arrtype, worktype, worktype, 0 )
792
793
794ICV_DEF_NORM_FUNC_ALL_C( 8u, CV_NOP, CV_IABS, uchar, int )
795ICV_DEF_NORM_FUNC_ALL_C( 16u, CV_NOP, CV_IABS, ushort, int )
796ICV_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)
799ICV_DEF_NORM_FUNC_ALL_C( 32s, CV_IABS, CV_IABS, int, int )
800ICV_DEF_NORM_FUNC_ALL_C( 32f, fabs, fabs, float, double )
801ICV_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                                                                                    \
806ICV_DEF_NORM_##hintp_func##_FUNC_2D( icvNorm_L1_##flavor##_C1R,                     \
807    _abs_, CV_ADD, CV_NOP, arrtype, normtype, worktype, block_size )                \
808                                                                                    \
809ICV_DEF_NORM_##nohint_func##_FUNC_2D_COI( icvNorm_L1_##flavor##_CnCR,               \
810    _abs_, CV_ADD, CV_NOP, arrtype, normtype, worktype, block_size )                \
811                                                                                    \
812ICV_DEF_NORM_DIFF_##hintp_func##_FUNC_2D( icvNormDiff_L1_##flavor##_C1R,            \
813    _abs_diff_, CV_ADD, CV_NOP, arrtype, normtype, worktype, block_size )           \
814                                                                                    \
815ICV_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                                                                                    \
818ICV_DEF_NORM_MASK_##nohint_func##_FUNC_2D( icvNorm_L1_##flavor##_C1MR,              \
819    _abs_, CV_ADD, CV_NOP, arrtype, normtype, worktype, block_size )                \
820                                                                                    \
821ICV_DEF_NORM_MASK_##nohint_func##_FUNC_2D_COI( icvNorm_L1_##flavor##_CnCMR,         \
822    _abs_, CV_ADD, CV_NOP, arrtype, normtype, worktype, block_size )                \
823                                                                                    \
824ICV_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                                                                                    \
827ICV_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
831ICV_DEF_NORM_FUNC_ALL_L1( 8u, CV_NOP, CV_IABS, NOHINT_BLOCK, NOHINT_BLOCK,
832                          uchar, int64, int, 1 << 23 )
833ICV_DEF_NORM_FUNC_ALL_L1( 16u, CV_NOP, CV_IABS, NOHINT_BLOCK, NOHINT_BLOCK,
834                          ushort, int64, int, 1 << 15 )
835ICV_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)
839ICV_DEF_NORM_FUNC_ALL_L1( 32s, fabs, fabs, NOHINT, NOHINT,
840                          int, double, double, INT_MAX )
841ICV_DEF_NORM_FUNC_ALL_L1( 32f, fabs, fabs, HINT, NOHINT,
842                          float, double, double, INT_MAX )
843ICV_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                                                                                    \
850ICV_DEF_NORM_##hintp_func##_FUNC_2D( icvNorm_L2_##flavor##_C1R,                     \
851    sqr_macro, CV_ADD, sqrt, arrtype, normtype, worktype, block_size )              \
852                                                                                    \
853ICV_DEF_NORM_##nohint_func##_FUNC_2D_COI( icvNorm_L2_##flavor##_CnCR,               \
854    sqr_macro, CV_ADD, sqrt, arrtype, normtype, worktype, block_size )              \
855                                                                                    \
856ICV_DEF_NORM_DIFF_##hintp_func##_FUNC_2D( icvNormDiff_L2_##flavor##_C1R,            \
857    sqr_macro, CV_ADD, sqrt, arrtype, normtype, worktype, block_size )              \
858                                                                                    \
859ICV_DEF_NORM_DIFF_##nohint_func##_FUNC_2D_COI( icvNormDiff_L2_##flavor##_CnCR,      \
860    sqr_macro, CV_ADD, sqrt, arrtype, normtype, worktype, block_size )              \
861                                                                                    \
862ICV_DEF_NORM_MASK_##nohint_func##_FUNC_2D( icvNorm_L2_##flavor##_C1MR,              \
863    sqr_macro, CV_ADD, sqrt, arrtype, normtype, worktype, block_size )              \
864                                                                                    \
865ICV_DEF_NORM_MASK_##nohint_func##_FUNC_2D_COI( icvNorm_L2_##flavor##_CnCMR,         \
866    sqr_macro, CV_ADD, sqrt, arrtype, normtype, worktype, block_size )              \
867                                                                                    \
868ICV_DEF_NORM_DIFF_MASK_##nohint_func##_FUNC_2D( icvNormDiff_L2_##flavor##_C1MR,     \
869    sqr_macro, CV_ADD, sqrt, arrtype, normtype, worktype, block_size )              \
870                                                                                    \
871ICV_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
875ICV_DEF_NORM_FUNC_ALL_L2( 8u, NOHINT_BLOCK, NOHINT_BLOCK, uchar,
876                          int64, int, 1 << 15, CV_SQR_8U )
877ICV_DEF_NORM_FUNC_ALL_L2( 16u, NOHINT, NOHINT, ushort,
878                          double, double, INT_MAX, CV_SQR )
879ICV_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)
883ICV_DEF_NORM_FUNC_ALL_L2( 32s, NOHINT, NOHINT, int,
884                          double, double, INT_MAX, CV_SQR )
885ICV_DEF_NORM_FUNC_ALL_L2( 32f, HINT, NOHINT, float,
886                          double, double, INT_MAX, CV_SQR )
887ICV_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 )              \
892static 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
903ICV_DEF_INIT_NORM_TAB_2D( Norm_Inf, C1R )
904ICV_DEF_INIT_NORM_TAB_2D( Norm_L1, C1R )
905ICV_DEF_INIT_NORM_TAB_2D( Norm_L2, C1R )
906ICV_DEF_INIT_NORM_TAB_2D( NormDiff_Inf, C1R )
907ICV_DEF_INIT_NORM_TAB_2D( NormDiff_L1, C1R )
908ICV_DEF_INIT_NORM_TAB_2D( NormDiff_L2, C1R )
909
910ICV_DEF_INIT_NORM_TAB_2D( Norm_Inf, CnCR )
911ICV_DEF_INIT_NORM_TAB_2D( Norm_L1, CnCR )
912ICV_DEF_INIT_NORM_TAB_2D( Norm_L2, CnCR )
913ICV_DEF_INIT_NORM_TAB_2D( NormDiff_Inf, CnCR )
914ICV_DEF_INIT_NORM_TAB_2D( NormDiff_L1, CnCR )
915ICV_DEF_INIT_NORM_TAB_2D( NormDiff_L2, CnCR )
916
917ICV_DEF_INIT_NORM_TAB_2D( Norm_Inf, C1MR )
918ICV_DEF_INIT_NORM_TAB_2D( Norm_L1, C1MR )
919ICV_DEF_INIT_NORM_TAB_2D( Norm_L2, C1MR )
920ICV_DEF_INIT_NORM_TAB_2D( NormDiff_Inf, C1MR )
921ICV_DEF_INIT_NORM_TAB_2D( NormDiff_L1, C1MR )
922ICV_DEF_INIT_NORM_TAB_2D( NormDiff_L2, C1MR )
923
924ICV_DEF_INIT_NORM_TAB_2D( Norm_Inf, CnCMR )
925ICV_DEF_INIT_NORM_TAB_2D( Norm_L1, CnCMR )
926ICV_DEF_INIT_NORM_TAB_2D( Norm_L2, CnCMR )
927ICV_DEF_INIT_NORM_TAB_2D( NormDiff_Inf, CnCMR )
928ICV_DEF_INIT_NORM_TAB_2D( NormDiff_L1, CnCMR )
929ICV_DEF_INIT_NORM_TAB_2D( NormDiff_L2, CnCMR )
930
931
932static 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
964CV_IMPL  double
965cvNorm( 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