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 op_diff
20 //! @{
21
22
23 template<typename eT>
24 inline
25 void
apply_noalias(Mat<eT> & out,const Mat<eT> & X,const uword k,const uword dim)26 op_diff::apply_noalias(Mat<eT>& out, const Mat<eT>& X, const uword k, const uword dim)
27 {
28 arma_extra_debug_sigprint();
29
30 uword n_rows = X.n_rows;
31 uword n_cols = X.n_cols;
32
33 if(dim == 0)
34 {
35 if(n_rows <= k) { out.set_size(0,n_cols); return; }
36
37 --n_rows;
38
39 out.set_size(n_rows,n_cols);
40
41 for(uword col=0; col < n_cols; ++col)
42 {
43 eT* out_colmem = out.colptr(col);
44 const eT* X_colmem = X.colptr(col);
45
46 for(uword row=0; row < n_rows; ++row)
47 {
48 const eT val0 = X_colmem[row ];
49 const eT val1 = X_colmem[row+1];
50
51 out_colmem[row] = val1 - val0;
52 }
53 }
54
55 if(k >= 2)
56 {
57 for(uword iter=2; iter <= k; ++iter)
58 {
59 --n_rows;
60
61 for(uword col=0; col < n_cols; ++col)
62 {
63 eT* colmem = out.colptr(col);
64
65 for(uword row=0; row < n_rows; ++row)
66 {
67 const eT val0 = colmem[row ];
68 const eT val1 = colmem[row+1];
69
70 colmem[row] = val1 - val0;
71 }
72 }
73 }
74
75 out = out( span(0,n_rows-1), span::all );
76 }
77 }
78 else
79 if(dim == 1)
80 {
81 if(n_cols <= k) { out.set_size(n_rows,0); return; }
82
83 --n_cols;
84
85 out.set_size(n_rows,n_cols);
86
87 if(n_rows == 1)
88 {
89 const eT* X_mem = X.memptr();
90 eT* out_mem = out.memptr();
91
92 for(uword col=0; col < n_cols; ++col)
93 {
94 const eT val0 = X_mem[col ];
95 const eT val1 = X_mem[col+1];
96
97 out_mem[col] = val1 - val0;
98 }
99 }
100 else
101 {
102 for(uword col=0; col < n_cols; ++col)
103 {
104 eT* out_col_mem = out.colptr(col);
105
106 const eT* X_col0_mem = X.colptr(col );
107 const eT* X_col1_mem = X.colptr(col+1);
108
109 for(uword row=0; row < n_rows; ++row)
110 {
111 out_col_mem[row] = X_col1_mem[row] - X_col0_mem[row];
112 }
113 }
114 }
115
116 if(k >= 2)
117 {
118 for(uword iter=2; iter <= k; ++iter)
119 {
120 --n_cols;
121
122 if(n_rows == 1)
123 {
124 eT* out_mem = out.memptr();
125
126 for(uword col=0; col < n_cols; ++col)
127 {
128 const eT val0 = out_mem[col ];
129 const eT val1 = out_mem[col+1];
130
131 out_mem[col] = val1 - val0;
132 }
133 }
134 else
135 {
136 for(uword col=0; col < n_cols; ++col)
137 {
138 eT* col0_mem = out.colptr(col );
139 const eT* col1_mem = out.colptr(col+1);
140
141 for(uword row=0; row < n_rows; ++row)
142 {
143 col0_mem[row] = col1_mem[row] - col0_mem[row];
144 }
145 }
146 }
147 }
148
149 out = out( span::all, span(0,n_cols-1) );
150 }
151 }
152 }
153
154
155
156 template<typename T1>
157 inline
158 void
apply(Mat<typename T1::elem_type> & out,const Op<T1,op_diff> & in)159 op_diff::apply(Mat<typename T1::elem_type>& out, const Op<T1,op_diff>& in)
160 {
161 arma_extra_debug_sigprint();
162
163 typedef typename T1::elem_type eT;
164
165 const uword k = in.aux_uword_a;
166 const uword dim = in.aux_uword_b;
167
168 arma_debug_check( (dim > 1), "diff(): parameter 'dim' must be 0 or 1" );
169
170 if(k == 0) { out = in.m; return; }
171
172 const quasi_unwrap<T1> U(in.m);
173
174 if(U.is_alias(out))
175 {
176 Mat<eT> tmp;
177
178 op_diff::apply_noalias(tmp, U.M, k, dim);
179
180 out.steal_mem(tmp);
181 }
182 else
183 {
184 op_diff::apply_noalias(out, U.M, k, dim);
185 }
186 }
187
188
189
190 template<typename T1>
191 inline
192 void
apply(Mat<typename T1::elem_type> & out,const Op<T1,op_diff_vec> & in)193 op_diff_vec::apply(Mat<typename T1::elem_type>& out, const Op<T1,op_diff_vec>& in)
194 {
195 arma_extra_debug_sigprint();
196
197 typedef typename T1::elem_type eT;
198
199 const uword k = in.aux_uword_a;
200
201 if(k == 0) { out = in.m; return; }
202
203 const quasi_unwrap<T1> U(in.m);
204
205 const uword dim = (T1::is_xvec) ? uword(U.M.is_rowvec() ? 1 : 0) : uword((T1::is_row) ? 1 : 0);
206
207 if(U.is_alias(out))
208 {
209 Mat<eT> tmp;
210
211 op_diff::apply_noalias(tmp, U.M, k, dim);
212
213 out.steal_mem(tmp);
214 }
215 else
216 {
217 op_diff::apply_noalias(out, U.M, k, dim);
218 }
219 }
220
221
222
223 //! @}
224
225