added dual tvl1 optical flow gpu implementation
[profile/ivi/opencv.git] / modules / gpu / src / cuda / mathfunc.cu
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 #if !defined CUDA_DISABLER
44
45 #include "internal_shared.hpp"
46
47 namespace cv { namespace gpu { namespace device
48 {
49     namespace mathfunc
50     {
51         //////////////////////////////////////////////////////////////////////////////////////
52         // Cart <-> Polar
53
54         struct Nothing
55         {
56             static __device__ __forceinline__ void calc(int, int, float, float, float*, size_t, float)
57             {
58             }
59         };
60         struct Magnitude
61         {
62             static __device__ __forceinline__ void calc(int x, int y, float x_data, float y_data, float* dst, size_t dst_step, float)
63             {
64                 dst[y * dst_step + x] = ::sqrtf(x_data * x_data + y_data * y_data);
65             }
66         };
67         struct MagnitudeSqr
68         {
69             static __device__ __forceinline__ void calc(int x, int y, float x_data, float y_data, float* dst, size_t dst_step, float)
70             {
71                 dst[y * dst_step + x] = x_data * x_data + y_data * y_data;
72             }
73         };
74         struct Atan2
75         {
76             static __device__ __forceinline__ void calc(int x, int y, float x_data, float y_data, float* dst, size_t dst_step, float scale)
77             {
78                 float angle = ::atan2f(y_data, x_data);
79                 angle += (angle < 0) * 2.0f * CV_PI_F;
80                 dst[y * dst_step + x] = scale * angle;
81             }
82         };
83         template <typename Mag, typename Angle>
84         __global__ void cartToPolar(const float* xptr, size_t x_step, const float* yptr, size_t y_step,
85                                     float* mag, size_t mag_step, float* angle, size_t angle_step, float scale, int width, int height)
86         {
87             const int x = blockDim.x * blockIdx.x + threadIdx.x;
88             const int y = blockDim.y * blockIdx.y + threadIdx.y;
89
90             if (x < width && y < height)
91             {
92                 float x_data = xptr[y * x_step + x];
93                 float y_data = yptr[y * y_step + x];
94
95                 Mag::calc(x, y, x_data, y_data, mag, mag_step, scale);
96                 Angle::calc(x, y, x_data, y_data, angle, angle_step, scale);
97             }
98         }
99
100         struct NonEmptyMag
101         {
102             static __device__ __forceinline__ float get(const float* mag, size_t mag_step, int x, int y)
103             {
104                 return mag[y * mag_step + x];
105             }
106         };
107         struct EmptyMag
108         {
109             static __device__ __forceinline__ float get(const float*, size_t, int, int)
110             {
111                 return 1.0f;
112             }
113         };
114         template <typename Mag>
115         __global__ void polarToCart(const float* mag, size_t mag_step, const float* angle, size_t angle_step, float scale,
116             float* xptr, size_t x_step, float* yptr, size_t y_step, int width, int height)
117         {
118             const int x = blockDim.x * blockIdx.x + threadIdx.x;
119             const int y = blockDim.y * blockIdx.y + threadIdx.y;
120
121             if (x < width && y < height)
122             {
123                 float mag_data = Mag::get(mag, mag_step, x, y);
124                 float angle_data = angle[y * angle_step + x];
125                 float sin_a, cos_a;
126
127                 ::sincosf(scale * angle_data, &sin_a, &cos_a);
128
129                 xptr[y * x_step + x] = mag_data * cos_a;
130                 yptr[y * y_step + x] = mag_data * sin_a;
131             }
132         }
133
134         template <typename Mag, typename Angle>
135         void cartToPolar_caller(PtrStepSzf x, PtrStepSzf y, PtrStepSzf mag, PtrStepSzf angle, bool angleInDegrees, cudaStream_t stream)
136         {
137             dim3 threads(32, 8, 1);
138             dim3 grid(1, 1, 1);
139
140             grid.x = divUp(x.cols, threads.x);
141             grid.y = divUp(x.rows, threads.y);
142
143             const float scale = angleInDegrees ? (180.0f / CV_PI_F) : 1.f;
144
145             cartToPolar<Mag, Angle><<<grid, threads, 0, stream>>>(
146                 x.data, x.step/x.elemSize(), y.data, y.step/y.elemSize(),
147                 mag.data, mag.step/mag.elemSize(), angle.data, angle.step/angle.elemSize(), scale, x.cols, x.rows);
148             cudaSafeCall( cudaGetLastError() );
149
150             if (stream == 0)
151                 cudaSafeCall( cudaDeviceSynchronize() );
152         }
153
154         void cartToPolar_gpu(PtrStepSzf x, PtrStepSzf y, PtrStepSzf mag, bool magSqr, PtrStepSzf angle, bool angleInDegrees, cudaStream_t stream)
155         {
156             typedef void (*caller_t)(PtrStepSzf x, PtrStepSzf y, PtrStepSzf mag, PtrStepSzf angle, bool angleInDegrees, cudaStream_t stream);
157             static const caller_t callers[2][2][2] =
158             {
159                 {
160                     {
161                         cartToPolar_caller<Magnitude, Atan2>,
162                         cartToPolar_caller<Magnitude, Nothing>
163                     },
164                     {
165                         cartToPolar_caller<MagnitudeSqr, Atan2>,
166                         cartToPolar_caller<MagnitudeSqr, Nothing>,
167                     }
168                 },
169                 {
170                     {
171                         cartToPolar_caller<Nothing, Atan2>,
172                         cartToPolar_caller<Nothing, Nothing>
173                     },
174                     {
175                         cartToPolar_caller<Nothing, Atan2>,
176                         cartToPolar_caller<Nothing, Nothing>,
177                     }
178                 }
179             };
180
181             callers[mag.data == 0][magSqr][angle.data == 0](x, y, mag, angle, angleInDegrees, stream);
182         }
183
184         template <typename Mag>
185         void polarToCart_caller(PtrStepSzf mag, PtrStepSzf angle, PtrStepSzf x, PtrStepSzf y, bool angleInDegrees, cudaStream_t stream)
186         {
187             dim3 threads(32, 8, 1);
188             dim3 grid(1, 1, 1);
189
190             grid.x = divUp(mag.cols, threads.x);
191             grid.y = divUp(mag.rows, threads.y);
192
193             const float scale = angleInDegrees ? (CV_PI_F / 180.0f) : 1.0f;
194
195             polarToCart<Mag><<<grid, threads, 0, stream>>>(mag.data, mag.step/mag.elemSize(),
196                 angle.data, angle.step/angle.elemSize(), scale, x.data, x.step/x.elemSize(), y.data, y.step/y.elemSize(), mag.cols, mag.rows);
197             cudaSafeCall( cudaGetLastError() );
198
199             if (stream == 0)
200                 cudaSafeCall( cudaDeviceSynchronize() );
201         }
202
203         void polarToCart_gpu(PtrStepSzf mag, PtrStepSzf angle, PtrStepSzf x, PtrStepSzf y, bool angleInDegrees, cudaStream_t stream)
204         {
205             typedef void (*caller_t)(PtrStepSzf mag, PtrStepSzf angle, PtrStepSzf x, PtrStepSzf y, bool angleInDegrees, cudaStream_t stream);
206             static const caller_t callers[2] =
207             {
208                 polarToCart_caller<NonEmptyMag>,
209                 polarToCart_caller<EmptyMag>
210             };
211
212             callers[mag.data == 0](mag, angle, x, y, angleInDegrees, stream);
213         }
214     } // namespace mathfunc
215 }}} // namespace cv { namespace gpu { namespace device
216
217 #endif /* CUDA_DISABLER */