CLAHE Python bindings
[profile/ivi/opencv.git] / modules / gpu / src / nvidia / core / NCV.hpp
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 //                           License Agreement
11 //                For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
14 // Copyright (C) 2009, Willow Garage Inc., all rights reserved.
15 // Third party copyrights are property of their respective owners.
16 //
17 // Redistribution and use in source and binary forms, with or without modification,
18 // are permitted provided that the following conditions are met:
19 //
20 //   * Redistribution's of source code must retain the above copyright notice,
21 //     this list of conditions and the following disclaimer.
22 //
23 //   * Redistribution's in binary form must reproduce the above copyright notice,
24 //     this list of conditions and the following disclaimer in the documentation
25 //     and/or other materials provided with the distribution.
26 //
27 //   * The name of the copyright holders may not be used to endorse or promote products
28 //     derived from this software without specific prior written permission.
29 //
30 // This software is provided by the copyright holders and contributors "as is" and
31 // any express or implied warranties, including, but not limited to, the implied
32 // warranties of merchantability and fitness for a particular purpose are disclaimed.
33 // In no event shall the Intel Corporation or contributors be liable for any direct,
34 // indirect, incidental, special, exemplary, or consequential damages
35 // (including, but not limited to, procurement of substitute goods or services;
36 // loss of use, data, or profits; or business interruption) however caused
37 // and on any theory of liability, whether in contract, strict liability,
38 // or tort (including negligence or otherwise) arising in any way out of
39 // the use of this software, even if advised of the possibility of such damage.
40 //
41 //M*/
42
43 #ifndef _ncv_hpp_
44 #define _ncv_hpp_
45
46 #if (defined WIN32 || defined _WIN32 || defined WINCE) && defined CVAPI_EXPORTS
47     #define NCV_EXPORTS __declspec(dllexport)
48 #else
49     #define NCV_EXPORTS
50 #endif
51
52 #ifdef _WIN32
53     #define WIN32_LEAN_AND_MEAN
54 #endif
55
56 #include <cuda_runtime.h>
57 #include <sstream>
58 #include <iostream>
59
60
61 //==============================================================================
62 //
63 // Compile-time assert functionality
64 //
65 //==============================================================================
66
67
68 /**
69 * Compile-time assert namespace
70 */
71 namespace NcvCTprep
72 {
73     template <bool x>
74     struct CT_ASSERT_FAILURE;
75
76     template <>
77     struct CT_ASSERT_FAILURE<true> {};
78
79     template <int x>
80     struct assertTest{};
81 }
82
83
84 #define NCV_CT_PREP_PASTE_AUX(a,b)      a##b                         ///< Concatenation indirection macro
85 #define NCV_CT_PREP_PASTE(a,b)          NCV_CT_PREP_PASTE_AUX(a, b)  ///< Concatenation macro
86
87
88 /**
89 * Performs compile-time assertion of a condition on the file scope
90 */
91 #define NCV_CT_ASSERT(X) \
92     typedef NcvCTprep::assertTest<sizeof(NcvCTprep::CT_ASSERT_FAILURE< (bool)(X) >)> \
93     NCV_CT_PREP_PASTE(__ct_assert_typedef_, __LINE__)
94
95
96
97 //==============================================================================
98 //
99 // Alignment macros
100 //
101 //==============================================================================
102
103
104 #if !defined(__align__) && !defined(__CUDACC__)
105     #if defined(_WIN32) || defined(_WIN64)
106         #define __align__(n)         __declspec(align(n))
107     #elif defined(__unix__)
108         #define __align__(n)         __attribute__((__aligned__(n)))
109     #endif
110 #endif
111
112
113 //==============================================================================
114 //
115 // Integral and compound types of guaranteed size
116 //
117 //==============================================================================
118
119
120 typedef               bool NcvBool;
121 typedef          long long Ncv64s;
122
123 #if defined(__APPLE__) && !defined(__CUDACC__)
124     typedef uint64_t Ncv64u;
125 #else
126     typedef unsigned long long Ncv64u;
127 #endif
128
129 typedef                int Ncv32s;
130 typedef       unsigned int Ncv32u;
131 typedef              short Ncv16s;
132 typedef     unsigned short Ncv16u;
133 typedef               char Ncv8s;
134 typedef      unsigned char Ncv8u;
135 typedef              float Ncv32f;
136 typedef             double Ncv64f;
137
138
139 struct NcvRect8u
140 {
141     Ncv8u x;
142     Ncv8u y;
143     Ncv8u width;
144     Ncv8u height;
145     __host__ __device__ NcvRect8u() : x(0), y(0), width(0), height(0) {};
146     __host__ __device__ NcvRect8u(Ncv8u x_, Ncv8u y_, Ncv8u width_, Ncv8u height_) : x(x_), y(y_), width(width_), height(height_) {}
147 };
148
149
150 struct NcvRect32s
151 {
152     Ncv32s x;          ///< x-coordinate of upper left corner.
153     Ncv32s y;          ///< y-coordinate of upper left corner.
154     Ncv32s width;      ///< Rectangle width.
155     Ncv32s height;     ///< Rectangle height.
156     __host__ __device__ NcvRect32s() : x(0), y(0), width(0), height(0) {};
157     __host__ __device__ NcvRect32s(Ncv32s x_, Ncv32s y_, Ncv32s width_, Ncv32s height_)
158         : x(x_), y(y_), width(width_), height(height_) {}
159 };
160
161
162 struct NcvRect32u
163 {
164     Ncv32u x;          ///< x-coordinate of upper left corner.
165     Ncv32u y;          ///< y-coordinate of upper left corner.
166     Ncv32u width;      ///< Rectangle width.
167     Ncv32u height;     ///< Rectangle height.
168     __host__ __device__ NcvRect32u() : x(0), y(0), width(0), height(0) {};
169     __host__ __device__ NcvRect32u(Ncv32u x_, Ncv32u y_, Ncv32u width_, Ncv32u height_)
170         : x(x_), y(y_), width(width_), height(height_) {}
171 };
172
173
174 struct NcvSize32s
175 {
176     Ncv32s width;  ///< Rectangle width.
177     Ncv32s height; ///< Rectangle height.
178     __host__ __device__ NcvSize32s() : width(0), height(0) {};
179     __host__ __device__ NcvSize32s(Ncv32s width_, Ncv32s height_) : width(width_), height(height_) {}
180 };
181
182
183 struct NcvSize32u
184 {
185     Ncv32u width;  ///< Rectangle width.
186     Ncv32u height; ///< Rectangle height.
187     __host__ __device__ NcvSize32u() : width(0), height(0) {};
188     __host__ __device__ NcvSize32u(Ncv32u width_, Ncv32u height_) : width(width_), height(height_) {}
189     __host__ __device__ bool operator == (const NcvSize32u &another) const {return this->width == another.width && this->height == another.height;}
190 };
191
192
193 struct NcvPoint2D32s
194 {
195     Ncv32s x; ///< Point X.
196     Ncv32s y; ///< Point Y.
197     __host__ __device__ NcvPoint2D32s() : x(0), y(0) {};
198     __host__ __device__ NcvPoint2D32s(Ncv32s x_, Ncv32s y_) : x(x_), y(y_) {}
199 };
200
201
202 struct NcvPoint2D32u
203 {
204     Ncv32u x; ///< Point X.
205     Ncv32u y; ///< Point Y.
206     __host__ __device__ NcvPoint2D32u() : x(0), y(0) {};
207     __host__ __device__ NcvPoint2D32u(Ncv32u x_, Ncv32u y_) : x(x_), y(y_) {}
208 };
209
210
211 NCV_CT_ASSERT(sizeof(NcvBool) <= 4);
212 NCV_CT_ASSERT(sizeof(Ncv64s) == 8);
213 NCV_CT_ASSERT(sizeof(Ncv64u) == 8);
214 NCV_CT_ASSERT(sizeof(Ncv32s) == 4);
215 NCV_CT_ASSERT(sizeof(Ncv32u) == 4);
216 NCV_CT_ASSERT(sizeof(Ncv16s) == 2);
217 NCV_CT_ASSERT(sizeof(Ncv16u) == 2);
218 NCV_CT_ASSERT(sizeof(Ncv8s) == 1);
219 NCV_CT_ASSERT(sizeof(Ncv8u) == 1);
220 NCV_CT_ASSERT(sizeof(Ncv32f) == 4);
221 NCV_CT_ASSERT(sizeof(Ncv64f) == 8);
222 NCV_CT_ASSERT(sizeof(NcvRect8u) == sizeof(Ncv32u));
223 NCV_CT_ASSERT(sizeof(NcvRect32s) == 4 * sizeof(Ncv32s));
224 NCV_CT_ASSERT(sizeof(NcvRect32u) == 4 * sizeof(Ncv32u));
225 NCV_CT_ASSERT(sizeof(NcvSize32u) == 2 * sizeof(Ncv32u));
226 NCV_CT_ASSERT(sizeof(NcvPoint2D32u) == 2 * sizeof(Ncv32u));
227
228
229 //==============================================================================
230 //
231 // Persistent constants
232 //
233 //==============================================================================
234
235
236 const Ncv32u K_WARP_SIZE = 32;
237 const Ncv32u K_LOG2_WARP_SIZE = 5;
238
239
240 //==============================================================================
241 //
242 // Error handling
243 //
244 //==============================================================================
245
246
247 NCV_EXPORTS void ncvDebugOutput(const std::string &msg);
248
249
250 typedef void NCVDebugOutputHandler(const std::string &msg);
251
252
253 NCV_EXPORTS void ncvSetDebugOutputHandler(NCVDebugOutputHandler* func);
254
255
256 #define ncvAssertPrintCheck(pred, msg) \
257     do \
258     { \
259         if (!(pred)) \
260         { \
261             std::ostringstream oss; \
262             oss << "NCV Assertion Failed: " << msg << ", file=" << __FILE__ << ", line=" << __LINE__ << std::endl; \
263             ncvDebugOutput(oss.str()); \
264         } \
265     } while (0)
266
267
268 #define ncvAssertPrintReturn(pred, msg, err) \
269     do \
270     { \
271         ncvAssertPrintCheck(pred, msg); \
272         if (!(pred)) return err; \
273     } while (0)
274
275
276 #define ncvAssertReturn(pred, err) \
277     ncvAssertPrintReturn(pred, "retcode=" << (int)err, err)
278
279
280 #define ncvAssertReturnNcvStat(ncvOp) \
281     do \
282     { \
283         NCVStatus _ncvStat = ncvOp; \
284         ncvAssertPrintReturn(NCV_SUCCESS==_ncvStat, "NcvStat=" << (int)_ncvStat, _ncvStat); \
285     } while (0)
286
287
288 #define ncvAssertCUDAReturn(cudacall, errCode) \
289     do \
290     { \
291         cudaError_t res = cudacall; \
292         ncvAssertPrintReturn(cudaSuccess==res, "cudaError_t=" << (int)res, errCode); \
293     } while (0)
294
295
296 #define ncvAssertCUDALastErrorReturn(errCode) \
297     do \
298     { \
299         cudaError_t res = cudaGetLastError(); \
300         ncvAssertPrintReturn(cudaSuccess==res, "cudaError_t=" << (int)res, errCode); \
301     } while (0)
302
303
304 /**
305 * Return-codes for status notification, errors and warnings
306 */
307 enum
308 {
309     //NCV statuses
310     NCV_SUCCESS,
311     NCV_UNKNOWN_ERROR,
312
313     NCV_CUDA_ERROR,
314     NCV_NPP_ERROR,
315     NCV_FILE_ERROR,
316
317     NCV_NULL_PTR,
318     NCV_INCONSISTENT_INPUT,
319     NCV_TEXTURE_BIND_ERROR,
320     NCV_DIMENSIONS_INVALID,
321
322     NCV_INVALID_ROI,
323     NCV_INVALID_STEP,
324     NCV_INVALID_SCALE,
325
326     NCV_ALLOCATOR_NOT_INITIALIZED,
327     NCV_ALLOCATOR_BAD_ALLOC,
328     NCV_ALLOCATOR_BAD_DEALLOC,
329     NCV_ALLOCATOR_INSUFFICIENT_CAPACITY,
330     NCV_ALLOCATOR_DEALLOC_ORDER,
331     NCV_ALLOCATOR_BAD_REUSE,
332
333     NCV_MEM_COPY_ERROR,
334     NCV_MEM_RESIDENCE_ERROR,
335     NCV_MEM_INSUFFICIENT_CAPACITY,
336
337     NCV_HAAR_INVALID_PIXEL_STEP,
338     NCV_HAAR_TOO_MANY_FEATURES_IN_CLASSIFIER,
339     NCV_HAAR_TOO_MANY_FEATURES_IN_CASCADE,
340     NCV_HAAR_TOO_LARGE_FEATURES,
341     NCV_HAAR_XML_LOADING_EXCEPTION,
342
343     NCV_NOIMPL_HAAR_TILTED_FEATURES,
344     NCV_NOT_IMPLEMENTED,
345
346     NCV_WARNING_HAAR_DETECTIONS_VECTOR_OVERFLOW,
347
348     //NPP statuses
349     NPPST_SUCCESS = NCV_SUCCESS,              ///< Successful operation (same as NPP_NO_ERROR)
350     NPPST_ERROR,                              ///< Unknown error
351     NPPST_CUDA_KERNEL_EXECUTION_ERROR,        ///< CUDA kernel execution error
352     NPPST_NULL_POINTER_ERROR,                 ///< NULL pointer argument error
353     NPPST_TEXTURE_BIND_ERROR,                 ///< CUDA texture binding error or non-zero offset returned
354     NPPST_MEMCPY_ERROR,                       ///< CUDA memory copy error
355     NPPST_MEM_ALLOC_ERR,                      ///< CUDA memory allocation error
356     NPPST_MEMFREE_ERR,                        ///< CUDA memory deallocation error
357
358     //NPPST statuses
359     NPPST_INVALID_ROI,                        ///< Invalid region of interest argument
360     NPPST_INVALID_STEP,                       ///< Invalid image lines step argument (check sign, alignment, relation to image width)
361     NPPST_INVALID_SCALE,                      ///< Invalid scale parameter passed
362     NPPST_MEM_INSUFFICIENT_BUFFER,            ///< Insufficient user-allocated buffer
363     NPPST_MEM_RESIDENCE_ERROR,                ///< Memory residence error detected (check if pointers should be device or pinned)
364     NPPST_MEM_INTERNAL_ERROR,                 ///< Internal memory management error
365
366     NCV_LAST_STATUS                           ///< Marker to continue error numeration in other files
367 };
368
369
370 typedef Ncv32u NCVStatus;
371
372
373 #define NCV_SET_SKIP_COND(x) \
374     bool __ncv_skip_cond = x
375
376
377 #define NCV_RESET_SKIP_COND(x) \
378     __ncv_skip_cond = x
379
380
381 #define NCV_SKIP_COND_BEGIN \
382     if (!__ncv_skip_cond) {
383
384
385 #define NCV_SKIP_COND_END \
386     }
387
388
389 //==============================================================================
390 //
391 // Timer
392 //
393 //==============================================================================
394
395
396 typedef struct _NcvTimer *NcvTimer;
397
398 NCV_EXPORTS NcvTimer ncvStartTimer(void);
399
400 NCV_EXPORTS double ncvEndQueryTimerUs(NcvTimer t);
401
402 NCV_EXPORTS double ncvEndQueryTimerMs(NcvTimer t);
403
404
405 //==============================================================================
406 //
407 // Memory management classes template compound types
408 //
409 //==============================================================================
410
411
412 /**
413 * Calculates the aligned top bound value
414 */
415 NCV_EXPORTS Ncv32u alignUp(Ncv32u what, Ncv32u alignment);
416
417
418 /**
419 * NCVMemoryType
420 */
421 enum NCVMemoryType
422 {
423     NCVMemoryTypeNone,
424     NCVMemoryTypeHostPageable,
425     NCVMemoryTypeHostPinned,
426     NCVMemoryTypeDevice
427 };
428
429
430 /**
431 * NCVMemPtr
432 */
433 struct NCV_EXPORTS NCVMemPtr
434 {
435     void *ptr;
436     NCVMemoryType memtype;
437     void clear();
438 };
439
440
441 /**
442 * NCVMemSegment
443 */
444 struct NCV_EXPORTS NCVMemSegment
445 {
446     NCVMemPtr begin;
447     size_t size;
448     void clear();
449 };
450
451
452 /**
453 * INCVMemAllocator (Interface)
454 */
455 class NCV_EXPORTS INCVMemAllocator
456 {
457 public:
458     virtual ~INCVMemAllocator() = 0;
459
460     virtual NCVStatus alloc(NCVMemSegment &seg, size_t size) = 0;
461     virtual NCVStatus dealloc(NCVMemSegment &seg) = 0;
462
463     virtual NcvBool isInitialized(void) const = 0;
464     virtual NcvBool isCounting(void) const = 0;
465
466     virtual NCVMemoryType memType(void) const = 0;
467     virtual Ncv32u alignment(void) const = 0;
468     virtual size_t maxSize(void) const = 0;
469 };
470
471 inline INCVMemAllocator::~INCVMemAllocator() {}
472
473
474 /**
475 * NCVMemStackAllocator
476 */
477 class NCV_EXPORTS NCVMemStackAllocator : public INCVMemAllocator
478 {
479     NCVMemStackAllocator();
480     NCVMemStackAllocator(const NCVMemStackAllocator &);
481
482 public:
483
484     explicit NCVMemStackAllocator(Ncv32u alignment);
485     NCVMemStackAllocator(NCVMemoryType memT, size_t capacity, Ncv32u alignment, void *reusePtr=NULL);
486     virtual ~NCVMemStackAllocator();
487
488     virtual NCVStatus alloc(NCVMemSegment &seg, size_t size);
489     virtual NCVStatus dealloc(NCVMemSegment &seg);
490
491     virtual NcvBool isInitialized(void) const;
492     virtual NcvBool isCounting(void) const;
493
494     virtual NCVMemoryType memType(void) const;
495     virtual Ncv32u alignment(void) const;
496     virtual size_t maxSize(void) const;
497
498 private:
499
500     NCVMemoryType _memType;
501     Ncv32u _alignment;
502     Ncv8u *allocBegin;
503     Ncv8u *begin;
504     Ncv8u *end;
505     size_t currentSize;
506     size_t _maxSize;
507     NcvBool bReusesMemory;
508 };
509
510
511 /**
512 * NCVMemNativeAllocator
513 */
514 class NCV_EXPORTS NCVMemNativeAllocator : public INCVMemAllocator
515 {
516 public:
517
518     NCVMemNativeAllocator(NCVMemoryType memT, Ncv32u alignment);
519     virtual ~NCVMemNativeAllocator();
520
521     virtual NCVStatus alloc(NCVMemSegment &seg, size_t size);
522     virtual NCVStatus dealloc(NCVMemSegment &seg);
523
524     virtual NcvBool isInitialized(void) const;
525     virtual NcvBool isCounting(void) const;
526
527     virtual NCVMemoryType memType(void) const;
528     virtual Ncv32u alignment(void) const;
529     virtual size_t maxSize(void) const;
530
531 private:
532
533     NCVMemNativeAllocator();
534     NCVMemNativeAllocator(const NCVMemNativeAllocator &);
535
536     NCVMemoryType _memType;
537     Ncv32u _alignment;
538     size_t currentSize;
539     size_t _maxSize;
540 };
541
542
543 /**
544 * Copy dispatchers
545 */
546 NCV_EXPORTS NCVStatus memSegCopyHelper(void *dst, NCVMemoryType dstType,
547                                        const void *src, NCVMemoryType srcType,
548                                        size_t sz, cudaStream_t cuStream);
549
550
551 NCV_EXPORTS NCVStatus memSegCopyHelper2D(void *dst, Ncv32u dstPitch, NCVMemoryType dstType,
552                                          const void *src, Ncv32u srcPitch, NCVMemoryType srcType,
553                                          Ncv32u widthbytes, Ncv32u height, cudaStream_t cuStream);
554
555
556 /**
557 * NCVVector (1D)
558 */
559 template <class T>
560 class NCVVector
561 {
562     NCVVector(const NCVVector &);
563
564 public:
565
566     NCVVector()
567     {
568         clear();
569     }
570
571     virtual ~NCVVector() {}
572
573     void clear()
574     {
575         _ptr = NULL;
576         _length = 0;
577         _memtype = NCVMemoryTypeNone;
578     }
579
580     NCVStatus copySolid(NCVVector<T> &dst, cudaStream_t cuStream, size_t howMuch=0) const
581     {
582         if (howMuch == 0)
583         {
584             ncvAssertReturn(dst._length == this->_length, NCV_MEM_COPY_ERROR);
585             howMuch = this->_length * sizeof(T);
586         }
587         else
588         {
589             ncvAssertReturn(dst._length * sizeof(T) >= howMuch &&
590                 this->_length * sizeof(T) >= howMuch &&
591                 howMuch > 0, NCV_MEM_COPY_ERROR);
592         }
593         ncvAssertReturn((this->_ptr != NULL || this->_memtype == NCVMemoryTypeNone) &&
594                         (dst._ptr != NULL || dst._memtype == NCVMemoryTypeNone), NCV_NULL_PTR);
595
596         NCVStatus ncvStat = NCV_SUCCESS;
597         if (this->_memtype != NCVMemoryTypeNone)
598         {
599             ncvStat = memSegCopyHelper(dst._ptr, dst._memtype,
600                                        this->_ptr, this->_memtype,
601                                        howMuch, cuStream);
602         }
603
604         return ncvStat;
605     }
606
607     T *ptr() const {return this->_ptr;}
608     size_t length() const {return this->_length;}
609     NCVMemoryType memType() const {return this->_memtype;}
610
611 protected:
612
613     T *_ptr;
614     size_t _length;
615     NCVMemoryType _memtype;
616 };
617
618
619 /**
620 * NCVVectorAlloc
621 */
622 template <class T>
623 class NCVVectorAlloc : public NCVVector<T>
624 {
625     NCVVectorAlloc();
626     NCVVectorAlloc(const NCVVectorAlloc &);
627     NCVVectorAlloc& operator=(const NCVVectorAlloc<T>&);
628
629 public:
630
631     NCVVectorAlloc(INCVMemAllocator &allocator_, Ncv32u length_)
632         :
633         allocator(allocator_)
634     {
635         NCVStatus ncvStat;
636
637         this->clear();
638         this->allocatedMem.clear();
639
640         ncvStat = allocator.alloc(this->allocatedMem, length_ * sizeof(T));
641         ncvAssertPrintReturn(ncvStat == NCV_SUCCESS, "NCVVectorAlloc ctor:: alloc failed", );
642
643         this->_ptr = (T *)this->allocatedMem.begin.ptr;
644         this->_length = length_;
645         this->_memtype = this->allocatedMem.begin.memtype;
646     }
647
648     ~NCVVectorAlloc()
649     {
650         NCVStatus ncvStat;
651
652         ncvStat = allocator.dealloc(this->allocatedMem);
653         ncvAssertPrintCheck(ncvStat == NCV_SUCCESS, "NCVVectorAlloc dtor:: dealloc failed");
654
655         this->clear();
656     }
657
658     NcvBool isMemAllocated() const
659     {
660         return (this->allocatedMem.begin.ptr != NULL) || (this->allocator.isCounting());
661     }
662
663     Ncv32u getAllocatorsAlignment() const
664     {
665         return allocator.alignment();
666     }
667
668     NCVMemSegment getSegment() const
669     {
670         return allocatedMem;
671     }
672
673 private:
674     INCVMemAllocator &allocator;
675     NCVMemSegment allocatedMem;
676 };
677
678
679 /**
680 * NCVVectorReuse
681 */
682 template <class T>
683 class NCVVectorReuse : public NCVVector<T>
684 {
685     NCVVectorReuse();
686     NCVVectorReuse(const NCVVectorReuse &);
687
688 public:
689
690     explicit NCVVectorReuse(const NCVMemSegment &memSegment)
691     {
692         this->bReused = false;
693         this->clear();
694
695         this->_length = memSegment.size / sizeof(T);
696         this->_ptr = (T *)memSegment.begin.ptr;
697         this->_memtype = memSegment.begin.memtype;
698
699         this->bReused = true;
700     }
701
702     NCVVectorReuse(const NCVMemSegment &memSegment, Ncv32u length_)
703     {
704         this->bReused = false;
705         this->clear();
706
707         ncvAssertPrintReturn(length_ * sizeof(T) <= memSegment.size, \
708             "NCVVectorReuse ctor:: memory binding failed due to size mismatch", );
709
710         this->_length = length_;
711         this->_ptr = (T *)memSegment.begin.ptr;
712         this->_memtype = memSegment.begin.memtype;
713
714         this->bReused = true;
715     }
716
717     NcvBool isMemReused() const
718     {
719         return this->bReused;
720     }
721
722 private:
723
724     NcvBool bReused;
725 };
726
727
728 /**
729 * NCVMatrix (2D)
730 */
731 template <class T>
732 class NCVMatrix
733 {
734     NCVMatrix(const NCVMatrix &);
735
736 public:
737
738     NCVMatrix()
739     {
740         clear();
741     }
742
743     virtual ~NCVMatrix() {}
744
745     void clear()
746     {
747         _ptr = NULL;
748         _pitch = 0;
749         _width = 0;
750         _height = 0;
751         _memtype = NCVMemoryTypeNone;
752     }
753
754     Ncv32u stride() const
755     {
756         return _pitch / sizeof(T);
757     }
758
759     //a side effect of this function is that it copies everything in a single chunk, so the "padding" will be overwritten
760     NCVStatus copySolid(NCVMatrix<T> &dst, cudaStream_t cuStream, size_t howMuch=0) const
761     {
762         if (howMuch == 0)
763         {
764             ncvAssertReturn(dst._pitch == this->_pitch &&
765                             dst._height == this->_height, NCV_MEM_COPY_ERROR);
766             howMuch = this->_pitch * this->_height;
767         }
768         else
769         {
770             ncvAssertReturn(dst._pitch * dst._height >= howMuch &&
771                             this->_pitch * this->_height >= howMuch &&
772                             howMuch > 0, NCV_MEM_COPY_ERROR);
773         }
774         ncvAssertReturn((this->_ptr != NULL || this->_memtype == NCVMemoryTypeNone) &&
775                         (dst._ptr != NULL || dst._memtype == NCVMemoryTypeNone), NCV_NULL_PTR);
776
777         NCVStatus ncvStat = NCV_SUCCESS;
778         if (this->_memtype != NCVMemoryTypeNone)
779         {
780             ncvStat = memSegCopyHelper(dst._ptr, dst._memtype,
781                                        this->_ptr, this->_memtype,
782                                        howMuch, cuStream);
783         }
784
785         return ncvStat;
786     }
787
788     NCVStatus copy2D(NCVMatrix<T> &dst, NcvSize32u roi, cudaStream_t cuStream) const
789     {
790         ncvAssertReturn(this->width() >= roi.width && this->height() >= roi.height &&
791                         dst.width() >= roi.width && dst.height() >= roi.height, NCV_MEM_COPY_ERROR);
792         ncvAssertReturn((this->_ptr != NULL || this->_memtype == NCVMemoryTypeNone) &&
793                         (dst._ptr != NULL || dst._memtype == NCVMemoryTypeNone), NCV_NULL_PTR);
794
795         NCVStatus ncvStat = NCV_SUCCESS;
796         if (this->_memtype != NCVMemoryTypeNone)
797         {
798             ncvStat = memSegCopyHelper2D(dst._ptr, dst._pitch, dst._memtype,
799                                          this->_ptr, this->_pitch, this->_memtype,
800                                          roi.width * sizeof(T), roi.height, cuStream);
801         }
802
803         return ncvStat;
804     }
805
806     T& at(Ncv32u x, Ncv32u y) const
807     {
808         NcvBool bOutRange = (x >= this->_width || y >= this->_height);
809         ncvAssertPrintCheck(!bOutRange, "Error addressing matrix at [" << x << ", " << y << "]");
810         if (bOutRange)
811         {
812             return *this->_ptr;
813         }
814         return ((T *)((Ncv8u *)this->_ptr + y * this->_pitch))[x];
815     }
816
817     T *ptr() const {return this->_ptr;}
818     Ncv32u width() const {return this->_width;}
819     Ncv32u height() const {return this->_height;}
820     NcvSize32u size() const {return NcvSize32u(this->_width, this->_height);}
821     Ncv32u pitch() const {return this->_pitch;}
822     NCVMemoryType memType() const {return this->_memtype;}
823
824 protected:
825
826     T *_ptr;
827     Ncv32u _width;
828     Ncv32u _height;
829     Ncv32u _pitch;
830     NCVMemoryType _memtype;
831 };
832
833
834 /**
835 * NCVMatrixAlloc
836 */
837 template <class T>
838 class NCVMatrixAlloc : public NCVMatrix<T>
839 {
840     NCVMatrixAlloc();
841     NCVMatrixAlloc(const NCVMatrixAlloc &);
842     NCVMatrixAlloc& operator=(const NCVMatrixAlloc &);
843 public:
844
845     NCVMatrixAlloc(INCVMemAllocator &allocator_, Ncv32u width_, Ncv32u height_, Ncv32u pitch_=0)
846         :
847         allocator(allocator_)
848     {
849         NCVStatus ncvStat;
850
851         this->clear();
852         this->allocatedMem.clear();
853
854         Ncv32u widthBytes = width_ * sizeof(T);
855         Ncv32u pitchBytes = alignUp(widthBytes, allocator.alignment());
856
857         if (pitch_ != 0)
858         {
859             ncvAssertPrintReturn(pitch_ >= pitchBytes &&
860                 (pitch_ & (allocator.alignment() - 1)) == 0,
861                 "NCVMatrixAlloc ctor:: incorrect pitch passed", );
862             pitchBytes = pitch_;
863         }
864
865         Ncv32u requiredAllocSize = pitchBytes * height_;
866
867         ncvStat = allocator.alloc(this->allocatedMem, requiredAllocSize);
868         ncvAssertPrintReturn(ncvStat == NCV_SUCCESS, "NCVMatrixAlloc ctor:: alloc failed", );
869
870         this->_ptr = (T *)this->allocatedMem.begin.ptr;
871         this->_width = width_;
872         this->_height = height_;
873         this->_pitch = pitchBytes;
874         this->_memtype = this->allocatedMem.begin.memtype;
875     }
876
877     ~NCVMatrixAlloc()
878     {
879         NCVStatus ncvStat;
880
881         ncvStat = allocator.dealloc(this->allocatedMem);
882         ncvAssertPrintCheck(ncvStat == NCV_SUCCESS, "NCVMatrixAlloc dtor:: dealloc failed");
883
884         this->clear();
885     }
886
887     NcvBool isMemAllocated() const
888     {
889         return (this->allocatedMem.begin.ptr != NULL) || (this->allocator.isCounting());
890     }
891
892     Ncv32u getAllocatorsAlignment() const
893     {
894         return allocator.alignment();
895     }
896
897     NCVMemSegment getSegment() const
898     {
899         return allocatedMem;
900     }
901
902 private:
903
904     INCVMemAllocator &allocator;
905     NCVMemSegment allocatedMem;
906 };
907
908
909 /**
910 * NCVMatrixReuse
911 */
912 template <class T>
913 class NCVMatrixReuse : public NCVMatrix<T>
914 {
915     NCVMatrixReuse();
916     NCVMatrixReuse(const NCVMatrixReuse &);
917
918 public:
919
920     NCVMatrixReuse(const NCVMemSegment &memSegment, Ncv32u alignment, Ncv32u width_, Ncv32u height_, Ncv32u pitch_=0, NcvBool bSkipPitchCheck=false)
921     {
922         this->bReused = false;
923         this->clear();
924
925         Ncv32u widthBytes = width_ * sizeof(T);
926         Ncv32u pitchBytes = alignUp(widthBytes, alignment);
927
928         if (pitch_ != 0)
929         {
930             if (!bSkipPitchCheck)
931             {
932                 ncvAssertPrintReturn(pitch_ >= pitchBytes &&
933                     (pitch_ & (alignment - 1)) == 0,
934                     "NCVMatrixReuse ctor:: incorrect pitch passed", );
935             }
936             else
937             {
938                 ncvAssertPrintReturn(pitch_ >= widthBytes, "NCVMatrixReuse ctor:: incorrect pitch passed", );
939             }
940             pitchBytes = pitch_;
941         }
942
943         ncvAssertPrintReturn(pitchBytes * height_ <= memSegment.size, \
944             "NCVMatrixReuse ctor:: memory binding failed due to size mismatch", );
945
946         this->_width = width_;
947         this->_height = height_;
948         this->_pitch = pitchBytes;
949         this->_ptr = (T *)memSegment.begin.ptr;
950         this->_memtype = memSegment.begin.memtype;
951
952         this->bReused = true;
953     }
954
955     NCVMatrixReuse(const NCVMatrix<T> &mat, NcvRect32u roi)
956     {
957         this->bReused = false;
958         this->clear();
959
960         ncvAssertPrintReturn(roi.x < mat.width() && roi.y < mat.height() && \
961             roi.x + roi.width <= mat.width() && roi.y + roi.height <= mat.height(),
962             "NCVMatrixReuse ctor:: memory binding failed due to mismatching ROI and source matrix dims", );
963
964         this->_width = roi.width;
965         this->_height = roi.height;
966         this->_pitch = mat.pitch();
967         this->_ptr = &mat.at(roi.x, roi.y);
968         this->_memtype = mat.memType();
969
970         this->bReused = true;
971     }
972
973     NcvBool isMemReused() const
974     {
975         return this->bReused;
976     }
977
978 private:
979
980     NcvBool bReused;
981 };
982
983
984 /**
985 * Operations with rectangles
986 */
987 NCV_EXPORTS NCVStatus ncvGroupRectangles_host(NCVVector<NcvRect32u> &hypotheses, Ncv32u &numHypotheses,
988                                               Ncv32u minNeighbors, Ncv32f intersectEps, NCVVector<Ncv32u> *hypothesesWeights);
989
990
991 NCV_EXPORTS NCVStatus ncvDrawRects_8u_host(Ncv8u *h_dst, Ncv32u dstStride, Ncv32u dstWidth, Ncv32u dstHeight,
992                                            NcvRect32u *h_rects, Ncv32u numRects, Ncv8u color);
993
994
995 NCV_EXPORTS NCVStatus ncvDrawRects_32u_host(Ncv32u *h_dst, Ncv32u dstStride, Ncv32u dstWidth, Ncv32u dstHeight,
996                                             NcvRect32u *h_rects, Ncv32u numRects, Ncv32u color);
997
998
999 NCV_EXPORTS NCVStatus ncvDrawRects_8u_device(Ncv8u *d_dst, Ncv32u dstStride, Ncv32u dstWidth, Ncv32u dstHeight,
1000                                              NcvRect32u *d_rects, Ncv32u numRects, Ncv8u color, cudaStream_t cuStream);
1001
1002
1003 NCV_EXPORTS NCVStatus ncvDrawRects_32u_device(Ncv32u *d_dst, Ncv32u dstStride, Ncv32u dstWidth, Ncv32u dstHeight,
1004                                               NcvRect32u *d_rects, Ncv32u numRects, Ncv32u color, cudaStream_t cuStream);
1005
1006
1007 #define CLAMP(x,a,b)        ( (x) > (b) ? (b) : ( (x) < (a) ? (a) : (x) ) )
1008 #define CLAMP_TOP(x, a)     (((x) > (a)) ? (a) : (x))
1009 #define CLAMP_BOTTOM(x, a)  (((x) < (a)) ? (a) : (x))
1010 #define CLAMP_0_255(x)      CLAMP(x,0,255)
1011
1012
1013 #define SUB_BEGIN(type, name)    struct { __inline type name
1014 #define SUB_END(name)            } name;
1015 #define SUB_CALL(name)           name.name
1016
1017 #define SQR(x)              ((x)*(x))
1018
1019
1020 #define ncvSafeMatAlloc(name, type, alloc, width, height, err) \
1021     NCVMatrixAlloc<type> name(alloc, width, height); \
1022     ncvAssertReturn(name.isMemAllocated(), err);
1023
1024
1025
1026 #endif // _ncv_hpp_