Fixes: Android NDK r7b, android build warnings, build with Visual Studio 2005.
[profile/ivi/opencv.git] / modules / core / test / test_arithm.cpp
1 #include "test_precomp.hpp"
2
3 using namespace cv;
4 using namespace std;
5
6 namespace cvtest
7 {
8
9 const int ARITHM_NTESTS = 1000;
10 const int ARITHM_RNG_SEED = -1;
11 const int ARITHM_MAX_CHANNELS = 4;
12 const int ARITHM_MAX_NDIMS = 4;
13 const int ARITHM_MAX_SIZE_LOG = 10;
14
15 struct BaseElemWiseOp
16 {
17     enum { FIX_ALPHA=1, FIX_BETA=2, FIX_GAMMA=4, REAL_GAMMA=8, SUPPORT_MASK=16, SCALAR_OUTPUT=32 };
18     BaseElemWiseOp(int _ninputs, int _flags, double _alpha, double _beta,
19                    Scalar _gamma=Scalar::all(0), int _context=1)
20     : ninputs(_ninputs), flags(_flags), alpha(_alpha), beta(_beta), gamma(_gamma), context(_context) {}
21     BaseElemWiseOp() { flags = 0; alpha = beta = 0; gamma = Scalar::all(0); }
22     virtual ~BaseElemWiseOp() {}
23     virtual void op(const vector<Mat>&, Mat&, const Mat&) {}
24     virtual void refop(const vector<Mat>&, Mat&, const Mat&) {}
25     virtual void getValueRange(int depth, double& minval, double& maxval)
26     {
27         minval = depth < CV_32S ? cvtest::getMinVal(depth) : depth == CV_32S ? -1000000 : -1000.;
28         maxval = depth < CV_32S ? cvtest::getMaxVal(depth) : depth == CV_32S ? 1000000 : 1000.;
29     }
30     
31     virtual void getRandomSize(RNG& rng, vector<int>& size)
32     {
33         cvtest::randomSize(rng, 2, ARITHM_MAX_NDIMS, cvtest::ARITHM_MAX_SIZE_LOG, size);
34     }
35     
36     virtual int getRandomType(RNG& rng)
37     {
38         return cvtest::randomType(rng, DEPTH_MASK_ALL_BUT_8S, 1,
39                                   ninputs > 1 ? ARITHM_MAX_CHANNELS : 4);
40     }
41         
42     virtual double getMaxErr(int depth) { return depth < CV_32F ? 1 : depth == CV_32F ? 1e-5 : 1e-12; }    
43     virtual void generateScalars(int depth, RNG& rng)
44     {
45         const double m = 3.;
46         
47         if( !(flags & FIX_ALPHA) )
48         {
49             alpha = exp(rng.uniform(-0.5, 0.1)*m*2*CV_LOG2);
50             alpha *= rng.uniform(0, 2) ? 1 : -1;
51         }
52         if( !(flags & FIX_BETA) )
53         {
54             beta = exp(rng.uniform(-0.5, 0.1)*m*2*CV_LOG2);
55             beta *= rng.uniform(0, 2) ? 1 : -1;
56         }
57         
58         if( !(flags & FIX_GAMMA) )
59         {
60             for( int i = 0; i < 4; i++ )
61             {
62                 gamma[i] = exp(rng.uniform(-1, 6)*m*CV_LOG2);
63                 gamma[i] *= rng.uniform(0, 2) ? 1 : -1;
64             }
65             if( flags & REAL_GAMMA )
66                 gamma = Scalar::all(gamma[0]);
67         }
68         
69         if( depth == CV_32F )
70         {
71             Mat fl, db;
72             
73             db = Mat(1, 1, CV_64F, &alpha);
74             db.convertTo(fl, CV_32F);
75             fl.convertTo(db, CV_64F);
76             
77             db = Mat(1, 1, CV_64F, &beta);
78             db.convertTo(fl, CV_32F);
79             fl.convertTo(db, CV_64F);
80             
81             db = Mat(1, 4, CV_64F, &gamma[0]);
82             db.convertTo(fl, CV_32F);
83             fl.convertTo(db, CV_64F);
84         }
85     }
86     
87     int ninputs;
88     int flags;
89     double alpha;
90     double beta;
91     Scalar gamma;
92     int maxErr;
93     int context;
94 };
95
96
97 struct BaseAddOp : public BaseElemWiseOp
98 {
99     BaseAddOp(int _ninputs, int _flags, double _alpha, double _beta, Scalar _gamma=Scalar::all(0))
100     : BaseElemWiseOp(_ninputs, _flags, _alpha, _beta, _gamma) {}
101     
102     void refop(const vector<Mat>& src, Mat& dst, const Mat& mask)
103     {
104         Mat temp;
105         if( !mask.empty() )
106         {
107             cvtest::add(src[0], alpha, src.size() > 1 ? src[1] : Mat(), beta, gamma, temp, src[0].type());
108             cvtest::copy(temp, dst, mask);
109         }
110         else
111             cvtest::add(src[0], alpha, src.size() > 1 ? src[1] : Mat(), beta, gamma, dst, src[0].type());
112     }
113 };
114
115
116 struct AddOp : public BaseAddOp
117 {
118     AddOp() : BaseAddOp(2, FIX_ALPHA+FIX_BETA+FIX_GAMMA+SUPPORT_MASK, 1, 1, Scalar::all(0)) {};
119     void op(const vector<Mat>& src, Mat& dst, const Mat& mask)
120     {
121         if( mask.empty() )
122             add(src[0], src[1], dst);
123         else
124             add(src[0], src[1], dst, mask);
125     }
126 };
127
128
129 struct SubOp : public BaseAddOp
130 {
131     SubOp() : BaseAddOp(2, FIX_ALPHA+FIX_BETA+FIX_GAMMA+SUPPORT_MASK, 1, -1, Scalar::all(0)) {};
132     void op(const vector<Mat>& src, Mat& dst, const Mat& mask)
133     {
134         if( mask.empty() )
135             subtract(src[0], src[1], dst);
136         else
137             subtract(src[0], src[1], dst, mask);
138     }
139 };
140
141
142 struct AddSOp : public BaseAddOp
143 {
144     AddSOp() : BaseAddOp(1, FIX_ALPHA+FIX_BETA+SUPPORT_MASK, 1, 0, Scalar::all(0)) {};
145     void op(const vector<Mat>& src, Mat& dst, const Mat& mask)
146     {
147         if( mask.empty() )
148             add(src[0], gamma, dst);
149         else
150             add(src[0], gamma, dst, mask);
151     }
152 };
153
154
155 struct SubRSOp : public BaseAddOp
156 {
157     SubRSOp() : BaseAddOp(1, FIX_ALPHA+FIX_BETA+SUPPORT_MASK, -1, 0, Scalar::all(0)) {};
158     void op(const vector<Mat>& src, Mat& dst, const Mat& mask)
159     {
160         if( mask.empty() )
161             subtract(gamma, src[0], dst);
162         else
163             subtract(gamma, src[0], dst, mask);
164     }
165 };
166
167
168 struct ScaleAddOp : public BaseAddOp
169 {
170     ScaleAddOp() : BaseAddOp(2, FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {};
171     void op(const vector<Mat>& src, Mat& dst, const Mat&)
172     {
173         scaleAdd(src[0], alpha, src[1], dst);
174     }
175     double getMaxErr(int depth)
176     {
177         return depth <= CV_32S ? 2 : depth < CV_64F ? 1e-4 : 1e-12;
178     }
179 };
180
181
182 struct AddWeightedOp : public BaseAddOp
183 {
184     AddWeightedOp() : BaseAddOp(2, REAL_GAMMA, 1, 1, Scalar::all(0)) {};
185     void op(const vector<Mat>& src, Mat& dst, const Mat&)
186     {
187         addWeighted(src[0], alpha, src[1], beta, gamma[0], dst);
188     }
189     double getMaxErr(int depth)
190     {
191         return depth <= CV_32S ? 2 : depth < CV_64F ? 1e-5 : 1e-10;
192     }
193 };
194
195 struct MulOp : public BaseElemWiseOp
196 {
197     MulOp() : BaseElemWiseOp(2, FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {};
198     void getValueRange(int depth, double& minval, double& maxval)
199     {
200         minval = depth < CV_32S ? cvtest::getMinVal(depth) : depth == CV_32S ? -1000000 : -1000.;
201         maxval = depth < CV_32S ? cvtest::getMaxVal(depth) : depth == CV_32S ? 1000000 : 1000.;
202         minval = std::max(minval, -30000.);
203         maxval = std::min(maxval, 30000.);
204     }
205     void op(const vector<Mat>& src, Mat& dst, const Mat&)
206     {
207         cv::multiply(src[0], src[1], dst, alpha);
208     }
209     void refop(const vector<Mat>& src, Mat& dst, const Mat&)
210     {
211         cvtest::multiply(src[0], src[1], dst, alpha);
212     }
213     double getMaxErr(int depth)
214     {
215         return depth <= CV_32S ? 2 : depth < CV_64F ? 1e-5 : 1e-12;
216     }
217 };    
218
219 struct DivOp : public BaseElemWiseOp
220 {
221     DivOp() : BaseElemWiseOp(2, FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {};
222     void op(const vector<Mat>& src, Mat& dst, const Mat&)
223     {
224         cv::divide(src[0], src[1], dst, alpha);
225     }
226     void refop(const vector<Mat>& src, Mat& dst, const Mat&)
227     {
228         cvtest::divide(src[0], src[1], dst, alpha);
229     }
230     double getMaxErr(int depth)
231     {
232         return depth <= CV_32S ? 2 : depth < CV_64F ? 1e-5 : 1e-12;
233     }
234 };    
235
236 struct RecipOp : public BaseElemWiseOp
237 {
238     RecipOp() : BaseElemWiseOp(1, FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {};
239     void op(const vector<Mat>& src, Mat& dst, const Mat&)
240     {
241         cv::divide(alpha, src[0], dst);
242     }
243     void refop(const vector<Mat>& src, Mat& dst, const Mat&)
244     {
245         cvtest::divide(Mat(), src[0], dst, alpha);
246     }
247     double getMaxErr(int depth)
248     {
249         return depth <= CV_32S ? 2 : depth < CV_64F ? 1e-5 : 1e-12;
250     }
251 };        
252     
253 struct AbsDiffOp : public BaseAddOp
254 {
255     AbsDiffOp() : BaseAddOp(2, FIX_ALPHA+FIX_BETA+FIX_GAMMA, 1, -1, Scalar::all(0)) {};
256     void op(const vector<Mat>& src, Mat& dst, const Mat&)
257     {
258         absdiff(src[0], src[1], dst);
259     }
260     void refop(const vector<Mat>& src, Mat& dst, const Mat&)
261     {
262         cvtest::add(src[0], 1, src[1], -1, Scalar::all(0), dst, src[0].type(), true);
263     }
264 };
265
266 struct AbsDiffSOp : public BaseAddOp
267 {
268     AbsDiffSOp() : BaseAddOp(1, FIX_ALPHA+FIX_BETA, 1, 0, Scalar::all(0)) {};
269     void op(const vector<Mat>& src, Mat& dst, const Mat&)
270     {
271         absdiff(src[0], gamma, dst);
272     }
273     void refop(const vector<Mat>& src, Mat& dst, const Mat&)
274     {
275         cvtest::add(src[0], 1, Mat(), 0, -gamma, dst, src[0].type(), true);
276     }
277 };
278
279 struct LogicOp : public BaseElemWiseOp
280 {
281     LogicOp(char _opcode) : BaseElemWiseOp(2, FIX_ALPHA+FIX_BETA+FIX_GAMMA+SUPPORT_MASK, 1, 1, Scalar::all(0)), opcode(_opcode) {};
282     void op(const vector<Mat>& src, Mat& dst, const Mat& mask)
283     {
284         if( opcode == '&' )
285             bitwise_and(src[0], src[1], dst, mask);
286         else if( opcode == '|' )
287             bitwise_or(src[0], src[1], dst, mask);
288         else
289             bitwise_xor(src[0], src[1], dst, mask);
290     }
291     void refop(const vector<Mat>& src, Mat& dst, const Mat& mask)
292     {
293         Mat temp;
294         if( !mask.empty() )
295         {
296             cvtest::logicOp(src[0], src[1], temp, opcode);
297             cvtest::copy(temp, dst, mask);
298         }
299         else
300             cvtest::logicOp(src[0], src[1], dst, opcode);
301     }
302     double getMaxErr(int)
303     {
304         return 0;
305     }
306     char opcode;
307 };
308
309 struct LogicSOp : public BaseElemWiseOp
310 {
311     LogicSOp(char _opcode)
312     : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+(_opcode != '~' ? SUPPORT_MASK : 0), 1, 1, Scalar::all(0)), opcode(_opcode) {};
313     void op(const vector<Mat>& src, Mat& dst, const Mat& mask)
314     {
315         if( opcode == '&' )
316             bitwise_and(src[0], gamma, dst, mask);
317         else if( opcode == '|' )
318             bitwise_or(src[0], gamma, dst, mask);
319         else if( opcode == '^' )
320             bitwise_xor(src[0], gamma, dst, mask);
321         else
322             bitwise_not(src[0], dst);
323     }
324     void refop(const vector<Mat>& src, Mat& dst, const Mat& mask)
325     {
326         Mat temp;
327         if( !mask.empty() )
328         {
329             cvtest::logicOp(src[0], gamma, temp, opcode);
330             cvtest::copy(temp, dst, mask);
331         }
332         else
333             cvtest::logicOp(src[0], gamma, dst, opcode);
334     }
335     double getMaxErr(int)
336     {
337         return 0;
338     }
339     char opcode;
340 };
341
342 struct MinOp : public BaseElemWiseOp
343 {
344     MinOp() : BaseElemWiseOp(2, FIX_ALPHA+FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {};
345     void op(const vector<Mat>& src, Mat& dst, const Mat&)
346     {
347         cv::min(src[0], src[1], dst);
348     }
349     void refop(const vector<Mat>& src, Mat& dst, const Mat&)
350     {
351         cvtest::min(src[0], src[1], dst);
352     }
353     double getMaxErr(int)
354     {
355         return 0;
356     }
357 };    
358
359 struct MaxOp : public BaseElemWiseOp
360 {
361     MaxOp() : BaseElemWiseOp(2, FIX_ALPHA+FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {};
362     void op(const vector<Mat>& src, Mat& dst, const Mat&)
363     {
364         cv::max(src[0], src[1], dst);
365     }
366     void refop(const vector<Mat>& src, Mat& dst, const Mat&)
367     {
368         cvtest::max(src[0], src[1], dst);
369     }
370     double getMaxErr(int)
371     {
372         return 0;
373     }
374 };    
375
376 struct MinSOp : public BaseElemWiseOp
377 {
378     MinSOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+REAL_GAMMA, 1, 1, Scalar::all(0)) {};
379     void op(const vector<Mat>& src, Mat& dst, const Mat&)
380     {
381         cv::min(src[0], gamma[0], dst);
382     }
383     void refop(const vector<Mat>& src, Mat& dst, const Mat&)
384     {
385         cvtest::min(src[0], gamma[0], dst);
386     }
387     double getMaxErr(int)
388     {
389         return 0;
390     }
391 };    
392
393 struct MaxSOp : public BaseElemWiseOp
394 {
395     MaxSOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+REAL_GAMMA, 1, 1, Scalar::all(0)) {};
396     void op(const vector<Mat>& src, Mat& dst, const Mat&)
397     {
398         cv::max(src[0], gamma[0], dst);
399     }
400     void refop(const vector<Mat>& src, Mat& dst, const Mat&)
401     {
402         cvtest::max(src[0], gamma[0], dst);
403     }
404     double getMaxErr(int)
405     {
406         return 0;
407     }
408 };
409     
410 struct CmpOp : public BaseElemWiseOp
411 {
412     CmpOp() : BaseElemWiseOp(2, FIX_ALPHA+FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {};
413     void generateScalars(int depth, RNG& rng)
414     {
415         BaseElemWiseOp::generateScalars(depth, rng);
416         cmpop = rng.uniform(0, 6);
417     }
418     void op(const vector<Mat>& src, Mat& dst, const Mat&)
419     {
420         cv::compare(src[0], src[1], dst, cmpop);
421     }
422     void refop(const vector<Mat>& src, Mat& dst, const Mat&)
423     {
424         cvtest::compare(src[0], src[1], dst, cmpop);
425     }
426     int getRandomType(RNG& rng)
427     {
428         return cvtest::randomType(rng, DEPTH_MASK_ALL_BUT_8S, 1, 1);
429     }
430         
431     double getMaxErr(int)
432     {
433         return 0;
434     }
435     int cmpop;
436 };
437
438 struct CmpSOp : public BaseElemWiseOp
439 {
440     CmpSOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+REAL_GAMMA, 1, 1, Scalar::all(0)) {};
441     void generateScalars(int depth, RNG& rng)
442     {
443         BaseElemWiseOp::generateScalars(depth, rng);
444         cmpop = rng.uniform(0, 6);
445         if( depth < CV_32F )
446             gamma[0] = cvRound(gamma[0]);
447     }
448     void op(const vector<Mat>& src, Mat& dst, const Mat&)
449     {
450         cv::compare(src[0], gamma[0], dst, cmpop);
451     }
452     void refop(const vector<Mat>& src, Mat& dst, const Mat&)
453     {
454         cvtest::compare(src[0], gamma[0], dst, cmpop);
455     }
456     int getRandomType(RNG& rng)
457     {
458         return cvtest::randomType(rng, DEPTH_MASK_ALL_BUT_8S, 1, 1);
459     }
460     double getMaxErr(int)
461     {
462         return 0;
463     }
464     int cmpop;
465 };    
466
467     
468 struct CopyOp : public BaseElemWiseOp
469 {
470     CopyOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+FIX_GAMMA+SUPPORT_MASK, 1, 1, Scalar::all(0)) {};
471     void op(const vector<Mat>& src, Mat& dst, const Mat& mask)
472     {
473         src[0].copyTo(dst, mask);
474     }
475     void refop(const vector<Mat>& src, Mat& dst, const Mat& mask)
476     {
477         cvtest::copy(src[0], dst, mask);
478     }
479     int getRandomType(RNG& rng)
480     {
481         return cvtest::randomType(rng, DEPTH_MASK_ALL, 1, ARITHM_MAX_CHANNELS);
482     }
483     double getMaxErr(int)
484     {
485         return 0;
486     }
487     int cmpop;
488 };
489
490     
491 struct SetOp : public BaseElemWiseOp
492 {
493     SetOp() : BaseElemWiseOp(0, FIX_ALPHA+FIX_BETA+SUPPORT_MASK, 1, 1, Scalar::all(0)) {};
494     void op(const vector<Mat>&, Mat& dst, const Mat& mask)
495     {
496         dst.setTo(gamma, mask);
497     }
498     void refop(const vector<Mat>&, Mat& dst, const Mat& mask)
499     {
500         cvtest::set(dst, gamma, mask);
501     }
502     int getRandomType(RNG& rng)
503     {
504         return cvtest::randomType(rng, DEPTH_MASK_ALL, 1, ARITHM_MAX_CHANNELS);
505     }
506     double getMaxErr(int)
507     {
508         return 0;
509     }
510 };    
511
512 template<typename _Tp, typename _WTp> static void
513 inRangeS_(const _Tp* src, const _WTp* a, const _WTp* b, uchar* dst, size_t total, int cn)
514 {
515     size_t i;
516     int c;
517     for( i = 0; i < total; i++ )
518     {
519         _Tp val = src[i*cn];
520         dst[i] = (a[0] <= val && val <= b[0]) ? uchar(255) : 0;
521     }
522     for( c = 1; c < cn; c++ )
523     {
524         for( i = 0; i < total; i++ )
525         {
526             _Tp val = src[i*cn + c];
527             dst[i] = a[c] <= val && val <= b[c] ? dst[i] : 0;
528         }
529     }
530 }
531
532 template<typename _Tp> static void inRange_(const _Tp* src, const _Tp* a, const _Tp* b, uchar* dst, size_t total, int cn)
533 {
534     size_t i;
535     int c;
536     for( i = 0; i < total; i++ )
537     {
538         _Tp val = src[i*cn];
539         dst[i] = a[i*cn] <= val && val <= b[i*cn] ? 255 : 0;
540     }
541     for( c = 1; c < cn; c++ )
542     {
543         for( i = 0; i < total; i++ )
544         {
545             _Tp val = src[i*cn + c];
546             dst[i] = a[i*cn + c] <= val && val <= b[i*cn + c] ? dst[i] : 0;
547         }
548     }
549 }
550     
551
552 static void inRange(const Mat& src, const Mat& lb, const Mat& rb, Mat& dst)
553 {
554     CV_Assert( src.type() == lb.type() && src.type() == rb.type() &&
555               src.size == lb.size && src.size == rb.size );
556     dst.create( src.dims, &src.size[0], CV_8U );
557     const Mat *arrays[]={&src, &lb, &rb, &dst, 0};
558     Mat planes[4];
559     
560     NAryMatIterator it(arrays, planes);
561     size_t total = planes[0].total();
562     size_t i, nplanes = it.nplanes;
563         int depth = src.depth(), cn = src.channels();
564     
565     for( i = 0; i < nplanes; i++, ++it )
566     {
567         const uchar* sptr = planes[0].data;
568         const uchar* aptr = planes[1].data;
569         const uchar* bptr = planes[2].data;
570         uchar* dptr = planes[3].data;
571         
572         switch( depth )
573         {
574         case CV_8U:
575             inRange_((const uchar*)sptr, (const uchar*)aptr, (const uchar*)bptr, dptr, total, cn);
576             break;
577         case CV_8S:
578             inRange_((const schar*)sptr, (const schar*)aptr, (const schar*)bptr, dptr, total, cn);
579             break;
580         case CV_16U:
581             inRange_((const ushort*)sptr, (const ushort*)aptr, (const ushort*)bptr, dptr, total, cn);
582             break;
583         case CV_16S:
584             inRange_((const short*)sptr, (const short*)aptr, (const short*)bptr, dptr, total, cn);
585             break;
586         case CV_32S:
587             inRange_((const int*)sptr, (const int*)aptr, (const int*)bptr, dptr, total, cn);
588             break;
589         case CV_32F:
590             inRange_((const float*)sptr, (const float*)aptr, (const float*)bptr, dptr, total, cn);
591             break;
592         case CV_64F:
593             inRange_((const double*)sptr, (const double*)aptr, (const double*)bptr, dptr, total, cn);
594             break;
595         default:
596             CV_Error(CV_StsUnsupportedFormat, "");
597         }
598     }
599 }
600
601
602 static void inRangeS(const Mat& src, const Scalar& lb, const Scalar& rb, Mat& dst)
603 {
604     dst.create( src.dims, &src.size[0], CV_8U );
605     const Mat *arrays[]={&src, &dst, 0};
606     Mat planes[2];
607     
608     NAryMatIterator it(arrays, planes);
609     size_t total = planes[0].total();
610     size_t i, nplanes = it.nplanes;
611         int depth = src.depth(), cn = src.channels();
612     union { double d[4]; float f[4]; int i[4];} lbuf, rbuf;
613     int wtype = CV_MAKETYPE(depth <= CV_32S ? CV_32S : depth, cn);
614     scalarToRawData(lb, lbuf.d, wtype, cn);
615     scalarToRawData(rb, rbuf.d, wtype, cn);
616     
617     for( i = 0; i < nplanes; i++, ++it )
618     {
619         const uchar* sptr = planes[0].data;
620         uchar* dptr = planes[1].data;
621         
622         switch( depth )
623         {
624         case CV_8U:
625             inRangeS_((const uchar*)sptr, lbuf.i, rbuf.i, dptr, total, cn);
626             break;
627         case CV_8S:
628             inRangeS_((const schar*)sptr, lbuf.i, rbuf.i, dptr, total, cn);
629             break;
630         case CV_16U:
631             inRangeS_((const ushort*)sptr, lbuf.i, rbuf.i, dptr, total, cn);
632             break;
633         case CV_16S:
634             inRangeS_((const short*)sptr, lbuf.i, rbuf.i, dptr, total, cn);
635             break;
636         case CV_32S:
637             inRangeS_((const int*)sptr, lbuf.i, rbuf.i, dptr, total, cn);
638             break;
639         case CV_32F:
640             inRangeS_((const float*)sptr, lbuf.f, rbuf.f, dptr, total, cn);
641             break;
642         case CV_64F:
643             inRangeS_((const double*)sptr, lbuf.d, rbuf.d, dptr, total, cn);
644             break;
645         default:
646             CV_Error(CV_StsUnsupportedFormat, "");
647         }
648     }
649 }
650     
651     
652 struct InRangeSOp : public BaseElemWiseOp
653 {
654     InRangeSOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA, 1, 1, Scalar::all(0)) {};
655     void op(const vector<Mat>& src, Mat& dst, const Mat&)
656     {
657         cv::inRange(src[0], gamma, gamma1, dst);
658     }
659     void refop(const vector<Mat>& src, Mat& dst, const Mat&)
660     {
661         cvtest::inRangeS(src[0], gamma, gamma1, dst);
662     }
663     double getMaxErr(int)
664     {
665         return 0;
666     }
667     void generateScalars(int depth, RNG& rng)
668     {
669         BaseElemWiseOp::generateScalars(depth, rng);
670         Scalar temp = gamma;
671         BaseElemWiseOp::generateScalars(depth, rng);
672         for( int i = 0; i < 4; i++ )
673         {
674             gamma1[i] = std::max(gamma[i], temp[i]);
675             gamma[i] = std::min(gamma[i], temp[i]);
676         }
677     }
678     Scalar gamma1;
679 };    
680
681     
682 struct InRangeOp : public BaseElemWiseOp
683 {
684     InRangeOp() : BaseElemWiseOp(3, FIX_ALPHA+FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {};
685     void op(const vector<Mat>& src, Mat& dst, const Mat&)
686     {
687         Mat lb, rb;
688         cvtest::min(src[1], src[2], lb);
689         cvtest::max(src[1], src[2], rb);
690         
691         cv::inRange(src[0], lb, rb, dst);
692     }
693     void refop(const vector<Mat>& src, Mat& dst, const Mat&)
694     {
695         Mat lb, rb;
696         cvtest::min(src[1], src[2], lb);
697         cvtest::max(src[1], src[2], rb);
698         
699         cvtest::inRange(src[0], lb, rb, dst);
700     }
701     double getMaxErr(int)
702     {
703         return 0;
704     }
705 };    
706     
707     
708 struct ConvertScaleOp : public BaseElemWiseOp
709 {
710     ConvertScaleOp() : BaseElemWiseOp(1, FIX_BETA+REAL_GAMMA, 1, 1, Scalar::all(0)), ddepth(0) { };
711     void op(const vector<Mat>& src, Mat& dst, const Mat&)
712     {
713         src[0].convertTo(dst, ddepth, alpha, gamma[0]);
714     }
715     void refop(const vector<Mat>& src, Mat& dst, const Mat&)
716     {
717         cvtest::convert(src[0], dst, CV_MAKETYPE(ddepth, src[0].channels()), alpha, gamma[0]);
718     }
719     int getRandomType(RNG& rng)
720     {
721         int srctype = cvtest::randomType(rng, DEPTH_MASK_ALL, 1, ARITHM_MAX_CHANNELS);
722         ddepth = cvtest::randomType(rng, DEPTH_MASK_ALL, 1, 1);
723         return srctype;
724     }
725     double getMaxErr(int)
726     {
727         return ddepth <= CV_32S ? 2 : ddepth < CV_64F ? 1e-3 : 1e-12;
728     }
729     void generateScalars(int depth, RNG& rng)
730     {
731         if( rng.uniform(0, 2) )
732             BaseElemWiseOp::generateScalars(depth, rng);
733         else
734         {
735             alpha = 1;
736             gamma = Scalar::all(0);
737         }
738     }
739     int ddepth;
740 };
741
742     
743 struct ConvertScaleAbsOp : public BaseElemWiseOp
744 {
745     ConvertScaleAbsOp() : BaseElemWiseOp(1, FIX_BETA+REAL_GAMMA, 1, 1, Scalar::all(0)) {};
746     void op(const vector<Mat>& src, Mat& dst, const Mat&)
747     {
748         cv::convertScaleAbs(src[0], dst, alpha, gamma[0]);
749     }
750     void refop(const vector<Mat>& src, Mat& dst, const Mat&)
751     {
752         cvtest::add(src[0], alpha, Mat(), 0, Scalar::all(gamma[0]), dst, CV_8UC(src[0].channels()), true);
753     }
754     double getMaxErr(int)
755     {
756         return 1;
757     }
758     void generateScalars(int depth, RNG& rng)
759     {
760         if( rng.uniform(0, 2) )
761             BaseElemWiseOp::generateScalars(depth, rng);
762         else
763         {
764             alpha = 1;
765             gamma = Scalar::all(0);
766         }
767     }
768 };
769
770     
771 static void flip(const Mat& src, Mat& dst, int flipcode)
772 {
773     CV_Assert(src.dims == 2);
774     dst.create(src.size(), src.type());
775     int i, j, k, esz = (int)src.elemSize(), width = src.cols*esz;
776     
777     for( i = 0; i < dst.rows; i++ )
778     {
779         const uchar* sptr = src.ptr(flipcode == 1 ? i : dst.rows - i - 1);
780         uchar* dptr = dst.ptr(i);
781         if( flipcode == 0 )
782             memcpy(dptr, sptr, width);
783         else
784         {
785             for( j = 0; j < width; j += esz )
786                 for( k = 0; k < esz; k++ )
787                     dptr[j + k] = sptr[width - j - esz + k];
788         }
789     }
790 }
791
792
793 static void setIdentity(Mat& dst, const Scalar& s)
794 {
795     CV_Assert( dst.dims == 2 && dst.channels() <= 4 );
796     double buf[4];
797     scalarToRawData(s, buf, dst.type(), 0);
798     int i, k, esz = (int)dst.elemSize(), width = dst.cols*esz;
799     
800     for( i = 0; i < dst.rows; i++ )
801     {
802         uchar* dptr = dst.ptr(i);
803         memset( dptr, 0, width );
804         if( i < dst.cols )
805             for( k = 0; k < esz; k++ )
806                 dptr[i*esz + k] = ((uchar*)buf)[k];
807     }
808 }
809
810     
811 struct FlipOp : public BaseElemWiseOp
812 {
813     FlipOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {};
814     void getRandomSize(RNG& rng, vector<int>& size)
815     {
816         cvtest::randomSize(rng, 2, 2, cvtest::ARITHM_MAX_SIZE_LOG, size);
817     }
818     void op(const vector<Mat>& src, Mat& dst, const Mat&)
819     {
820         cv::flip(src[0], dst, flipcode);
821     }
822     void refop(const vector<Mat>& src, Mat& dst, const Mat&)
823     {
824         cvtest::flip(src[0], dst, flipcode);
825     }
826     void generateScalars(int, RNG& rng)
827     {
828         flipcode = rng.uniform(0, 3) - 1;
829     }
830     double getMaxErr(int)
831     {
832         return 0;
833     }
834     int flipcode;
835 };
836
837 struct TransposeOp : public BaseElemWiseOp
838 {
839     TransposeOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {};
840     void getRandomSize(RNG& rng, vector<int>& size)
841     {
842         cvtest::randomSize(rng, 2, 2, cvtest::ARITHM_MAX_SIZE_LOG, size);
843     }
844     void op(const vector<Mat>& src, Mat& dst, const Mat&)
845     {
846         cv::transpose(src[0], dst);
847     }
848     void refop(const vector<Mat>& src, Mat& dst, const Mat&)
849     {
850         cvtest::transpose(src[0], dst);
851     }
852     double getMaxErr(int)
853     {
854         return 0;
855     }
856 };    
857     
858 struct SetIdentityOp : public BaseElemWiseOp
859 {
860     SetIdentityOp() : BaseElemWiseOp(0, FIX_ALPHA+FIX_BETA, 1, 1, Scalar::all(0)) {};
861     void getRandomSize(RNG& rng, vector<int>& size)
862     {
863         cvtest::randomSize(rng, 2, 2, cvtest::ARITHM_MAX_SIZE_LOG, size);
864     }
865     void op(const vector<Mat>&, Mat& dst, const Mat&)
866     {
867         cv::setIdentity(dst, gamma);
868     }
869     void refop(const vector<Mat>&, Mat& dst, const Mat&)
870     {
871         cvtest::setIdentity(dst, gamma);
872     }
873     double getMaxErr(int)
874     {
875         return 0;
876     }
877 };    
878
879 struct SetZeroOp : public BaseElemWiseOp
880 {
881     SetZeroOp() : BaseElemWiseOp(0, FIX_ALPHA+FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {};
882     void op(const vector<Mat>&, Mat& dst, const Mat&)
883     {
884         dst = Scalar::all(0);
885     }
886     void refop(const vector<Mat>&, Mat& dst, const Mat&)
887     {
888         cvtest::set(dst, Scalar::all(0));
889     }
890     double getMaxErr(int)
891     {
892         return 0;
893     }
894 };
895
896     
897 static void exp(const Mat& src, Mat& dst)
898 {
899     dst.create( src.dims, &src.size[0], src.type() );
900     const Mat *arrays[]={&src, &dst, 0};
901     Mat planes[2];
902     
903     NAryMatIterator it(arrays, planes);
904     size_t j, total = planes[0].total()*src.channels();
905     size_t i, nplanes = it.nplanes;
906         int depth = src.depth();
907     
908     for( i = 0; i < nplanes; i++, ++it )
909     {
910         const uchar* sptr = planes[0].data;
911         uchar* dptr = planes[1].data;
912         
913         if( depth == CV_32F )
914         {
915             for( j = 0; j < total; j++ )
916                 ((float*)dptr)[j] = std::exp(((const float*)sptr)[j]);
917         }
918         else if( depth == CV_64F )
919         {
920             for( j = 0; j < total; j++ )
921                 ((double*)dptr)[j] = std::exp(((const double*)sptr)[j]);
922         }
923     }    
924 }
925
926 static void log(const Mat& src, Mat& dst)
927 {
928     dst.create( src.dims, &src.size[0], src.type() );
929     const Mat *arrays[]={&src, &dst, 0};
930     Mat planes[2];
931     
932     NAryMatIterator it(arrays, planes);
933     size_t j, total = planes[0].total()*src.channels();
934     size_t i, nplanes = it.nplanes;
935         int depth = src.depth();
936     
937     for( i = 0; i < nplanes; i++, ++it )
938     {
939         const uchar* sptr = planes[0].data;
940         uchar* dptr = planes[1].data;
941         
942         if( depth == CV_32F )
943         {
944             for( j = 0; j < total; j++ )
945                 ((float*)dptr)[j] = (float)std::log(fabs(((const float*)sptr)[j]));
946         }
947         else if( depth == CV_64F )
948         {
949             for( j = 0; j < total; j++ )
950                 ((double*)dptr)[j] = std::log(fabs(((const double*)sptr)[j]));
951         }
952     }    
953 }    
954     
955 struct ExpOp : public BaseElemWiseOp
956 {
957     ExpOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {};
958     int getRandomType(RNG& rng)
959     {
960         return cvtest::randomType(rng, DEPTH_MASK_FLT, 1, ARITHM_MAX_CHANNELS);
961     }
962     void getValueRange(int depth, double& minval, double& maxval)
963     {
964         maxval = depth == CV_32F ? 50 : 100;
965         minval = -maxval;
966     }
967     void op(const vector<Mat>& src, Mat& dst, const Mat&)
968     {
969         cv::exp(src[0], dst);
970     }
971     void refop(const vector<Mat>& src, Mat& dst, const Mat&)
972     {
973         cvtest::exp(src[0], dst);
974     }
975     double getMaxErr(int depth)
976     {
977         return depth == CV_32F ? 1e-5 : 1e-12;
978     }
979 };        
980
981
982 struct LogOp : public BaseElemWiseOp
983 {
984     LogOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {};
985     int getRandomType(RNG& rng)
986     {
987         return cvtest::randomType(rng, DEPTH_MASK_FLT, 1, ARITHM_MAX_CHANNELS);
988     }
989     void getValueRange(int depth, double& minval, double& maxval)
990     {
991         maxval = depth == CV_32F ? 50 : 100;
992         minval = -maxval;
993     }
994     void op(const vector<Mat>& src, Mat& dst, const Mat&)
995     {
996         Mat temp;
997         cvtest::exp(src[0], temp);
998         cv::log(temp, dst);
999     }
1000     void refop(const vector<Mat>& src, Mat& dst, const Mat&)
1001     {
1002         Mat temp;
1003         cvtest::exp(src[0], temp);
1004         cvtest::log(temp, dst);
1005     }
1006     double getMaxErr(int depth)
1007     {
1008         return depth == CV_32F ? 1e-5 : 1e-12;
1009     }
1010 };
1011
1012
1013 static void cartToPolar(const Mat& mx, const Mat& my, Mat& mmag, Mat& mangle, bool angleInDegrees)
1014 {
1015     CV_Assert( (mx.type() == CV_32F || mx.type() == CV_64F) &&
1016               mx.type() == my.type() && mx.size == my.size );
1017     mmag.create( mx.dims, &mx.size[0], mx.type() );
1018     mangle.create( mx.dims, &mx.size[0], mx.type() );
1019     const Mat *arrays[]={&mx, &my, &mmag, &mangle, 0};
1020     Mat planes[4];
1021     
1022     NAryMatIterator it(arrays, planes);
1023     size_t j, total = planes[0].total();
1024     size_t i, nplanes = it.nplanes;
1025         int depth = mx.depth();
1026     double scale = angleInDegrees ? 180/CV_PI : 1;
1027     
1028     for( i = 0; i < nplanes; i++, ++it )
1029     {
1030         if( depth == CV_32F )
1031         {
1032             const float* xptr = (const float*)planes[0].data;
1033             const float* yptr = (const float*)planes[1].data;
1034             float* mptr = (float*)planes[2].data;
1035             float* aptr = (float*)planes[3].data;
1036             
1037             for( j = 0; j < total; j++ )
1038             {
1039                 mptr[j] = std::sqrt(xptr[j]*xptr[j] + yptr[j]*yptr[j]);
1040                 double a = atan2((double)yptr[j], (double)xptr[j]);
1041                 if( a < 0 ) a += CV_PI*2;
1042                 aptr[j] = (float)(a*scale);
1043             }
1044         }
1045         else
1046         {
1047             const double* xptr = (const double*)planes[0].data;
1048             const double* yptr = (const double*)planes[1].data;
1049             double* mptr = (double*)planes[2].data;
1050             double* aptr = (double*)planes[3].data;
1051             
1052             for( j = 0; j < total; j++ )
1053             {
1054                 mptr[j] = std::sqrt(xptr[j]*xptr[j] + yptr[j]*yptr[j]);
1055                 double a = atan2(yptr[j], xptr[j]);
1056                 if( a < 0 ) a += CV_PI*2;
1057                 aptr[j] = a*scale;
1058             }
1059         }
1060     }
1061 }
1062     
1063     
1064 struct CartToPolarToCartOp : public BaseElemWiseOp
1065 {
1066     CartToPolarToCartOp() : BaseElemWiseOp(2, FIX_ALPHA+FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0))
1067     {
1068         context = 3;
1069         angleInDegrees = true;
1070     }
1071     int getRandomType(RNG& rng)
1072     {
1073         return cvtest::randomType(rng, DEPTH_MASK_FLT, 1, 1);
1074     }
1075     void op(const vector<Mat>& src, Mat& dst, const Mat&)
1076     {
1077         Mat mag, angle, x, y;
1078         
1079         cv::cartToPolar(src[0], src[1], mag, angle, angleInDegrees);
1080         cv::polarToCart(mag, angle, x, y, angleInDegrees);
1081         
1082         Mat msrc[] = {mag, angle, x, y};
1083         int pairs[] = {0, 0, 1, 1, 2, 2, 3, 3};
1084         dst.create(src[0].dims, src[0].size, CV_MAKETYPE(src[0].depth(), 4));
1085         cv::mixChannels(msrc, 4, &dst, 1, pairs, 4);
1086     }
1087     void refop(const vector<Mat>& src, Mat& dst, const Mat&)
1088     {
1089         Mat mag, angle;
1090         cvtest::cartToPolar(src[0], src[1], mag, angle, angleInDegrees);
1091         Mat msrc[] = {mag, angle, src[0], src[1]};
1092         int pairs[] = {0, 0, 1, 1, 2, 2, 3, 3};
1093         dst.create(src[0].dims, src[0].size, CV_MAKETYPE(src[0].depth(), 4));
1094         cv::mixChannels(msrc, 4, &dst, 1, pairs, 4);
1095     }
1096     void generateScalars(int, RNG& rng)
1097     {
1098         angleInDegrees = rng.uniform(0, 2) != 0;
1099     }
1100     double getMaxErr(int)
1101     {
1102         return 1e-3;
1103     }
1104     bool angleInDegrees;
1105 };
1106     
1107     
1108 struct MeanOp : public BaseElemWiseOp
1109 {
1110     MeanOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+FIX_GAMMA+SUPPORT_MASK+SCALAR_OUTPUT, 1, 1, Scalar::all(0))
1111     {
1112         context = 3;
1113     };
1114     void op(const vector<Mat>& src, Mat& dst, const Mat& mask)
1115     {
1116         dst.create(1, 1, CV_64FC4);
1117         dst.at<Scalar>(0,0) = cv::mean(src[0], mask);
1118     }
1119     void refop(const vector<Mat>& src, Mat& dst, const Mat& mask)
1120     {
1121         dst.create(1, 1, CV_64FC4);
1122         dst.at<Scalar>(0,0) = cvtest::mean(src[0], mask);
1123     }
1124     double getMaxErr(int)
1125     {
1126         return 1e-6;
1127     }
1128 };    
1129
1130
1131 struct SumOp : public BaseElemWiseOp
1132 {
1133     SumOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+FIX_GAMMA+SCALAR_OUTPUT, 1, 1, Scalar::all(0))
1134     {
1135         context = 3;
1136     };
1137     void op(const vector<Mat>& src, Mat& dst, const Mat&)
1138     {
1139         dst.create(1, 1, CV_64FC4);
1140         dst.at<Scalar>(0,0) = cv::sum(src[0]);
1141     }
1142     void refop(const vector<Mat>& src, Mat& dst, const Mat&)
1143     {
1144         dst.create(1, 1, CV_64FC4);
1145         dst.at<Scalar>(0,0) = cvtest::mean(src[0])*(double)src[0].total();
1146     }
1147     double getMaxErr(int)
1148     {
1149         return 1e-5;
1150     }
1151 };    
1152
1153     
1154 struct CountNonZeroOp : public BaseElemWiseOp
1155 {
1156     CountNonZeroOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+FIX_GAMMA+SCALAR_OUTPUT+SUPPORT_MASK, 1, 1, Scalar::all(0))
1157     {}
1158     int getRandomType(RNG& rng)
1159     {
1160         return cvtest::randomType(rng, DEPTH_MASK_ALL, 1, 1);
1161     }
1162     void op(const vector<Mat>& src, Mat& dst, const Mat& mask)
1163     {
1164         Mat temp;
1165         src[0].copyTo(temp);
1166         if( !mask.empty() )
1167             temp.setTo(Scalar::all(0), mask);
1168         dst.create(1, 1, CV_32S);
1169         dst.at<int>(0,0) = cv::countNonZero(temp);
1170     }
1171     void refop(const vector<Mat>& src, Mat& dst, const Mat& mask)
1172     {
1173         Mat temp;
1174         cvtest::compare(src[0], 0, temp, CMP_NE);
1175         if( !mask.empty() )
1176             cvtest::set(temp, Scalar::all(0), mask);
1177         dst.create(1, 1, CV_32S);
1178         dst.at<int>(0,0) = saturate_cast<int>(cvtest::mean(temp)[0]/255*temp.total());
1179     }
1180     double getMaxErr(int)
1181     {
1182         return 0;
1183     }
1184 };    
1185
1186     
1187 struct MeanStdDevOp : public BaseElemWiseOp
1188 {
1189     MeanStdDevOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+FIX_GAMMA+SUPPORT_MASK+SCALAR_OUTPUT, 1, 1, Scalar::all(0))
1190     {
1191         context = 7;
1192     };
1193     void op(const vector<Mat>& src, Mat& dst, const Mat& mask)
1194     {
1195         dst.create(1, 2, CV_64FC4);
1196         cv::meanStdDev(src[0], dst.at<Scalar>(0,0), dst.at<Scalar>(0,1), mask);
1197     }
1198     void refop(const vector<Mat>& src, Mat& dst, const Mat& mask)
1199     {
1200         Mat temp;
1201         cvtest::convert(src[0], temp, CV_64F);
1202         cvtest::multiply(temp, temp, temp);
1203         Scalar mean = cvtest::mean(src[0], mask);
1204         Scalar sqmean = cvtest::mean(temp, mask);
1205
1206         for( int c = 0; c < 4; c++ )
1207             sqmean[c] = std::sqrt(std::max(sqmean[c] - mean[c]*mean[c], 0.)); 
1208         
1209         dst.create(1, 2, CV_64FC4);
1210         dst.at<Scalar>(0,0) = mean;
1211         dst.at<Scalar>(0,1) = sqmean;
1212     }
1213     double getMaxErr(int)
1214     {
1215         return 1e-6;
1216     }
1217 };    
1218
1219     
1220 struct NormOp : public BaseElemWiseOp
1221 {
1222     NormOp() : BaseElemWiseOp(2, FIX_ALPHA+FIX_BETA+FIX_GAMMA+SUPPORT_MASK+SCALAR_OUTPUT, 1, 1, Scalar::all(0))
1223     {
1224         context = 1;
1225         normType = 0;
1226     };
1227     int getRandomType(RNG& rng)
1228     {
1229         return cvtest::randomType(rng, DEPTH_MASK_ALL_BUT_8S, 1, 4);
1230     }
1231     void op(const vector<Mat>& src, Mat& dst, const Mat& mask)
1232     {
1233         dst.create(1, 2, CV_64FC1);
1234         dst.at<double>(0,0) = cv::norm(src[0], normType, mask);
1235         dst.at<double>(0,1) = cv::norm(src[0], src[1], normType, mask);
1236     }
1237     void refop(const vector<Mat>& src, Mat& dst, const Mat& mask)
1238     {
1239         dst.create(1, 2, CV_64FC1);
1240         dst.at<double>(0,0) = cvtest::norm(src[0], normType, mask);
1241         dst.at<double>(0,1) = cvtest::norm(src[0], src[1], normType, mask);
1242     }
1243     void generateScalars(int, RNG& rng)
1244     {
1245         normType = 1 << rng.uniform(0, 3);
1246     }
1247     double getMaxErr(int)
1248     {
1249         return 1e-6;
1250     }
1251     int normType;
1252 };        
1253
1254
1255 struct MinMaxLocOp : public BaseElemWiseOp
1256 {
1257     MinMaxLocOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+FIX_GAMMA+SUPPORT_MASK+SCALAR_OUTPUT, 1, 1, Scalar::all(0))
1258     {
1259         context = ARITHM_MAX_NDIMS*2 + 2;
1260     };
1261     int getRandomType(RNG& rng)
1262     {
1263         return cvtest::randomType(rng, DEPTH_MASK_ALL_BUT_8S, 1, 1);
1264     }
1265     void saveOutput(const vector<int>& minidx, const vector<int>& maxidx,
1266                     double minval, double maxval, Mat& dst)
1267     {
1268         int i, ndims = (int)minidx.size();
1269         dst.create(1, ndims*2 + 2, CV_64FC1);
1270         
1271         for( i = 0; i < ndims; i++ )
1272         {
1273             dst.at<double>(0,i) = minidx[i];
1274             dst.at<double>(0,i+ndims) = maxidx[i];
1275         }
1276         dst.at<double>(0,ndims*2) = minval;
1277         dst.at<double>(0,ndims*2+1) = maxval;
1278     }
1279     void op(const vector<Mat>& src, Mat& dst, const Mat& mask)
1280     {
1281         int ndims = src[0].dims;
1282         vector<int> minidx(ndims), maxidx(ndims);
1283         double minval=0, maxval=0;
1284         cv::minMaxIdx(src[0], &minval, &maxval, &minidx[0], &maxidx[0], mask);
1285         saveOutput(minidx, maxidx, minval, maxval, dst);
1286     }
1287     void refop(const vector<Mat>& src, Mat& dst, const Mat& mask)
1288     {
1289         int ndims=src[0].dims;
1290         vector<int> minidx(ndims), maxidx(ndims);
1291         double minval=0, maxval=0;
1292         cvtest::minMaxLoc(src[0], &minval, &maxval, &minidx, &maxidx, mask);
1293         saveOutput(minidx, maxidx, minval, maxval, dst);
1294     }
1295     double getMaxErr(int)
1296     {
1297         return 0;
1298     }
1299 };            
1300     
1301     
1302 }
1303
1304 typedef Ptr<cvtest::BaseElemWiseOp> ElemWiseOpPtr;
1305 class ElemWiseTest : public ::testing::TestWithParam<ElemWiseOpPtr> {};
1306
1307 TEST_P(ElemWiseTest, accuracy)
1308 {
1309     ElemWiseOpPtr op = GetParam();
1310     
1311     int testIdx = 0;
1312     RNG rng((uint64)cvtest::ARITHM_RNG_SEED);
1313     for( testIdx = 0; testIdx < cvtest::ARITHM_NTESTS; testIdx++ )
1314     {
1315         vector<int> size;
1316         op->getRandomSize(rng, size);
1317         int type = op->getRandomType(rng);
1318         int depth = CV_MAT_DEPTH(type);
1319         bool haveMask = (op->flags & cvtest::BaseElemWiseOp::SUPPORT_MASK) != 0 && rng.uniform(0, 4) == 0;
1320         
1321         double minval=0, maxval=0;
1322         op->getValueRange(depth, minval, maxval);
1323         int i, ninputs = op->ninputs;
1324         vector<Mat> src(ninputs);
1325         for( i = 0; i < ninputs; i++ )
1326             src[i] = cvtest::randomMat(rng, size, type, minval, maxval, true);
1327         Mat dst0, dst, mask;
1328         if( haveMask )
1329             mask = cvtest::randomMat(rng, size, CV_8U, 0, 2, true);
1330         
1331         if( (haveMask || ninputs == 0) && !(op->flags & cvtest::BaseElemWiseOp::SCALAR_OUTPUT))
1332         {
1333             dst0 = cvtest::randomMat(rng, size, type, minval, maxval, false);
1334             dst = cvtest::randomMat(rng, size, type, minval, maxval, true);
1335             cvtest::copy(dst, dst0);
1336         }
1337         op->generateScalars(depth, rng);
1338         
1339         op->refop(src, dst0, mask);
1340         op->op(src, dst, mask);
1341         
1342         double maxErr = op->getMaxErr(depth);
1343         vector<int> pos;
1344                 ASSERT_PRED_FORMAT2(cvtest::MatComparator(maxErr, op->context), dst0, dst) << "\nsrc[0] ~ " << cvtest::MatInfo(!src.empty() ? src[0] : Mat()) << "\ntestCase #" << testIdx << "\n";
1345     }
1346 }
1347
1348  
1349 INSTANTIATE_TEST_CASE_P(Core_Copy, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::CopyOp)));
1350 INSTANTIATE_TEST_CASE_P(Core_Set, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::SetOp)));
1351 INSTANTIATE_TEST_CASE_P(Core_SetZero, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::SetZeroOp)));
1352 INSTANTIATE_TEST_CASE_P(Core_ConvertScale, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::ConvertScaleOp)));
1353 INSTANTIATE_TEST_CASE_P(Core_ConvertScaleAbs, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::ConvertScaleAbsOp)));
1354
1355 INSTANTIATE_TEST_CASE_P(Core_Add, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::AddOp)));
1356 INSTANTIATE_TEST_CASE_P(Core_Sub, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::SubOp)));
1357 INSTANTIATE_TEST_CASE_P(Core_AddS, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::AddSOp)));
1358 INSTANTIATE_TEST_CASE_P(Core_SubRS, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::SubRSOp)));
1359 INSTANTIATE_TEST_CASE_P(Core_ScaleAdd, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::ScaleAddOp)));
1360 INSTANTIATE_TEST_CASE_P(Core_AddWeighted, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::AddWeightedOp)));
1361 INSTANTIATE_TEST_CASE_P(Core_AbsDiff, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::AbsDiffOp)));
1362
1363
1364 INSTANTIATE_TEST_CASE_P(Core_AbsDiffS, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::AbsDiffSOp)));
1365
1366 INSTANTIATE_TEST_CASE_P(Core_And, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::LogicOp('&'))));
1367 INSTANTIATE_TEST_CASE_P(Core_AndS, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::LogicSOp('&'))));
1368 INSTANTIATE_TEST_CASE_P(Core_Or, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::LogicOp('|'))));
1369 INSTANTIATE_TEST_CASE_P(Core_OrS, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::LogicSOp('|'))));
1370 INSTANTIATE_TEST_CASE_P(Core_Xor, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::LogicOp('^'))));
1371 INSTANTIATE_TEST_CASE_P(Core_XorS, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::LogicSOp('^'))));
1372 INSTANTIATE_TEST_CASE_P(Core_Not, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::LogicSOp('~'))));
1373
1374 INSTANTIATE_TEST_CASE_P(Core_Max, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::MaxOp)));
1375 INSTANTIATE_TEST_CASE_P(Core_MaxS, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::MaxSOp)));
1376 INSTANTIATE_TEST_CASE_P(Core_Min, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::MinOp)));
1377 INSTANTIATE_TEST_CASE_P(Core_MinS, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::MinSOp)));
1378
1379 INSTANTIATE_TEST_CASE_P(Core_Mul, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::MulOp)));
1380 INSTANTIATE_TEST_CASE_P(Core_Div, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::DivOp)));
1381 INSTANTIATE_TEST_CASE_P(Core_Recip, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::RecipOp)));
1382
1383 INSTANTIATE_TEST_CASE_P(Core_Cmp, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::CmpOp)));
1384 INSTANTIATE_TEST_CASE_P(Core_CmpS, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::CmpSOp)));
1385
1386 INSTANTIATE_TEST_CASE_P(Core_InRangeS, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::InRangeSOp)));
1387 INSTANTIATE_TEST_CASE_P(Core_InRange, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::InRangeOp)));
1388
1389 INSTANTIATE_TEST_CASE_P(Core_Flip, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::FlipOp)));
1390 INSTANTIATE_TEST_CASE_P(Core_Transpose, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::TransposeOp)));
1391 INSTANTIATE_TEST_CASE_P(Core_SetIdentity, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::SetIdentityOp)));
1392
1393 INSTANTIATE_TEST_CASE_P(Core_Exp, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::ExpOp)));
1394 INSTANTIATE_TEST_CASE_P(Core_Log, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::LogOp)));
1395
1396 INSTANTIATE_TEST_CASE_P(Core_CountNonZero, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::CountNonZeroOp)));
1397 INSTANTIATE_TEST_CASE_P(Core_Mean, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::MeanOp)));
1398 INSTANTIATE_TEST_CASE_P(Core_MeanStdDev, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::MeanStdDevOp)));
1399 INSTANTIATE_TEST_CASE_P(Core_Sum, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::SumOp)));
1400 INSTANTIATE_TEST_CASE_P(Core_Norm, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::NormOp)));
1401 INSTANTIATE_TEST_CASE_P(Core_MinMaxLoc, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::MinMaxLocOp)));
1402 INSTANTIATE_TEST_CASE_P(Core_CartToPolarToCart, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::CartToPolarToCartOp)));
1403
1404
1405