1 // SPDX-License-Identifier: Apache-2.0
2 //
3 // Copyright 2008-2016 Conrad Sanderson (http://conradsanderson.id.au)
4 // Copyright 2008-2016 National ICT Australia (NICTA)
5 //
6 // Licensed under the Apache License, Version 2.0 (the "License");
7 // you may not use this file except in compliance with the License.
8 // You may obtain a copy of the License at
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 // ------------------------------------------------------------------------
17 
18 
19 //! \addtogroup glue_atan2
20 //! @{
21 
22 
23 
24 template<typename T1, typename T2>
25 inline
26 void
apply(Mat<typename T1::elem_type> & out,const Glue<T1,T2,glue_atan2> & expr)27 glue_atan2::apply(Mat<typename T1::elem_type>& out, const Glue<T1, T2, glue_atan2>& expr)
28   {
29   arma_extra_debug_sigprint();
30 
31   typedef typename T1::elem_type eT;
32 
33   const Proxy<T1> P1(expr.A);
34   const Proxy<T2> P2(expr.B);
35 
36   arma_assert_same_size(P1, P2, "atan2()");
37 
38   const bool bad_alias = ( (Proxy<T1>::has_subview && P1.is_alias(out)) || (Proxy<T2>::has_subview && P2.is_alias(out)) );
39 
40   if(bad_alias == false)
41     {
42     glue_atan2::apply_noalias(out, P1, P2);
43     }
44   else
45     {
46     Mat<eT> tmp;
47 
48     glue_atan2::apply_noalias(tmp, P1, P2);
49 
50     out.steal_mem(tmp);
51     }
52   }
53 
54 
55 
56 template<typename T1, typename T2>
57 inline
58 void
apply_noalias(Mat<typename T1::elem_type> & out,const Proxy<T1> & P1,const Proxy<T2> & P2)59 glue_atan2::apply_noalias(Mat<typename T1::elem_type>& out, const Proxy<T1>& P1, const Proxy<T2>& P2)
60   {
61   arma_extra_debug_sigprint();
62 
63   typedef typename T1::elem_type eT;
64 
65   const uword n_rows = P1.get_n_rows();
66   const uword n_cols = P1.get_n_cols();
67   const uword n_elem = P1.get_n_elem();
68 
69   out.set_size(n_rows, n_cols);
70 
71   eT* out_mem = out.memptr();
72 
73   const bool use_mp = arma_config::openmp && mp_gate<eT, (Proxy<T1>::use_mp || Proxy<T2>::use_mp)>::eval(n_elem);
74   const bool use_at = Proxy<T1>::use_at || Proxy<T2>::use_at;
75 
76   if(use_at == false)
77     {
78     typename Proxy<T1>::ea_type eaP1 = P1.get_ea();
79     typename Proxy<T2>::ea_type eaP2 = P2.get_ea();
80 
81     if(use_mp)
82       {
83       #if defined(ARMA_USE_OPENMP)
84         {
85         const int n_threads = mp_thread_limit::get();
86         #pragma omp parallel for schedule(static) num_threads(n_threads)
87         for(uword i=0; i<n_elem; ++i)
88           {
89           out_mem[i] = std::atan2( eaP1[i], eaP2[i] );
90           }
91         }
92       #endif
93       }
94     else
95       {
96       for(uword i=0; i<n_elem; ++i)
97         {
98         out_mem[i] = std::atan2( eaP1[i], eaP2[i] );
99         }
100       }
101     }
102   else
103     {
104     if(use_mp)
105       {
106       const unwrap<typename Proxy<T1>::stored_type> U1(P1.Q);
107       const unwrap<typename Proxy<T2>::stored_type> U2(P2.Q);
108 
109       out = arma::atan2(U1.M, U2.M);
110       }
111     else
112       {
113       for(uword col=0; col < n_cols; ++col)
114       for(uword row=0; row < n_rows; ++row)
115         {
116         *out_mem = std::atan2( P1.at(row,col), P2.at(row,col) );
117         out_mem++;
118         }
119       }
120     }
121   }
122 
123 
124 
125 template<typename T1, typename T2>
126 inline
127 void
apply(Cube<typename T1::elem_type> & out,const GlueCube<T1,T2,glue_atan2> & expr)128 glue_atan2::apply(Cube<typename T1::elem_type>& out, const GlueCube<T1, T2, glue_atan2>& expr)
129   {
130   arma_extra_debug_sigprint();
131 
132   typedef typename T1::elem_type eT;
133 
134   const ProxyCube<T1> P1(expr.A);
135   const ProxyCube<T2> P2(expr.B);
136 
137   arma_assert_same_size(P1, P2, "atan2()");
138 
139   const bool bad_alias = ( (ProxyCube<T1>::has_subview && P1.is_alias(out)) || (ProxyCube<T2>::has_subview && P2.is_alias(out)) );
140 
141   if(bad_alias == false)
142     {
143     glue_atan2::apply_noalias(out, P1, P2);
144     }
145   else
146     {
147     Cube<eT> tmp;
148 
149     glue_atan2::apply_noalias(tmp, P1, P2);
150 
151     out.steal_mem(tmp);
152     }
153   }
154 
155 
156 
157 template<typename T1, typename T2>
158 inline
159 void
apply_noalias(Cube<typename T1::elem_type> & out,const ProxyCube<T1> & P1,const ProxyCube<T2> & P2)160 glue_atan2::apply_noalias(Cube<typename T1::elem_type>& out, const ProxyCube<T1>& P1, const ProxyCube<T2>& P2)
161   {
162   arma_extra_debug_sigprint();
163 
164   typedef typename T1::elem_type eT;
165 
166   const uword n_rows   = P1.get_n_rows();
167   const uword n_cols   = P1.get_n_cols();
168   const uword n_slices = P1.get_n_slices();
169   const uword n_elem   = P1.get_n_elem();
170 
171   out.set_size(n_rows, n_cols, n_slices);
172 
173   eT* out_mem = out.memptr();
174 
175   const bool use_mp = arma_config::openmp && mp_gate<eT, (ProxyCube<T1>::use_mp || ProxyCube<T2>::use_mp)>::eval(n_elem);
176   const bool use_at = ProxyCube<T1>::use_at || ProxyCube<T2>::use_at;
177 
178   if(use_at == false)
179     {
180     typename ProxyCube<T1>::ea_type eaP1 = P1.get_ea();
181     typename ProxyCube<T2>::ea_type eaP2 = P2.get_ea();
182 
183     if(use_mp)
184       {
185       #if defined(ARMA_USE_OPENMP)
186         {
187         const int n_threads = mp_thread_limit::get();
188         #pragma omp parallel for schedule(static) num_threads(n_threads)
189         for(uword i=0; i<n_elem; ++i)
190           {
191           out_mem[i] = std::atan2( eaP1[i], eaP2[i] );
192           }
193         }
194       #endif
195       }
196     else
197       {
198       for(uword i=0; i<n_elem; ++i)
199         {
200         out_mem[i] = std::atan2( eaP1[i], eaP2[i] );
201         }
202       }
203     }
204   else
205     {
206     if(use_mp)
207       {
208       const unwrap_cube<typename ProxyCube<T1>::stored_type> U1(P1.Q);
209       const unwrap_cube<typename ProxyCube<T2>::stored_type> U2(P2.Q);
210 
211       out = arma::atan2(U1.M, U2.M);
212       }
213     else
214       {
215       for(uword slice=0; slice < n_slices; ++slice)
216       for(uword   col=0;   col < n_cols;   ++col  )
217       for(uword   row=0;   row < n_rows;   ++row  )
218         {
219         *out_mem = std::atan2( P1.at(row,col,slice), P2.at(row,col,slice) );
220         out_mem++;
221         }
222       }
223     }
224   }
225 
226 
227 
228 //! @}
229