subview_field_meat.hpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556
  1. // Copyright 2008-2016 Conrad Sanderson (http://conradsanderson.id.au)
  2. // Copyright 2008-2016 National ICT Australia (NICTA)
  3. //
  4. // Licensed under the Apache License, Version 2.0 (the "License");
  5. // you may not use this file except in compliance with the License.
  6. // You may obtain a copy of the License at
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. // ------------------------------------------------------------------------
  15. //! \addtogroup subview_field
  16. //! @{
  17. template<typename oT>
  18. inline
  19. subview_field<oT>::~subview_field()
  20. {
  21. arma_extra_debug_sigprint();
  22. }
  23. template<typename oT>
  24. arma_inline
  25. subview_field<oT>::subview_field
  26. (
  27. const field<oT>& in_f,
  28. const uword in_row1,
  29. const uword in_col1,
  30. const uword in_n_rows,
  31. const uword in_n_cols
  32. )
  33. : f(in_f)
  34. , aux_row1(in_row1)
  35. , aux_col1(in_col1)
  36. , aux_slice1(0)
  37. , n_rows(in_n_rows)
  38. , n_cols(in_n_cols)
  39. , n_slices( (in_f.n_slices > 0) ? uword(1) : uword(0) )
  40. , n_elem(in_n_rows*in_n_cols*n_slices)
  41. {
  42. arma_extra_debug_sigprint();
  43. }
  44. template<typename oT>
  45. arma_inline
  46. subview_field<oT>::subview_field
  47. (
  48. const field<oT>& in_f,
  49. const uword in_row1,
  50. const uword in_col1,
  51. const uword in_slice1,
  52. const uword in_n_rows,
  53. const uword in_n_cols,
  54. const uword in_n_slices
  55. )
  56. : f(in_f)
  57. , aux_row1(in_row1)
  58. , aux_col1(in_col1)
  59. , aux_slice1(in_slice1)
  60. , n_rows(in_n_rows)
  61. , n_cols(in_n_cols)
  62. , n_slices(in_n_slices)
  63. , n_elem(in_n_rows*in_n_cols*in_n_slices)
  64. {
  65. arma_extra_debug_sigprint();
  66. }
  67. template<typename oT>
  68. inline
  69. void
  70. subview_field<oT>::operator= (const field<oT>& x)
  71. {
  72. arma_extra_debug_sigprint();
  73. subview_field<oT>& t = *this;
  74. arma_debug_check( (t.n_rows != x.n_rows) || (t.n_cols != x.n_cols) || (t.n_slices != x.n_slices), "incompatible field dimensions" );
  75. if(t.n_slices == 1)
  76. {
  77. for(uword col=0; col < t.n_cols; ++col)
  78. for(uword row=0; row < t.n_rows; ++row)
  79. {
  80. t.at(row,col) = x.at(row,col);
  81. }
  82. }
  83. else
  84. {
  85. for(uword slice=0; slice < t.n_slices; ++slice)
  86. for(uword col=0; col < t.n_cols; ++col )
  87. for(uword row=0; row < t.n_rows; ++row )
  88. {
  89. t.at(row,col,slice) = x.at(row,col,slice);
  90. }
  91. }
  92. }
  93. //! x.subfield(...) = y.subfield(...)
  94. template<typename oT>
  95. inline
  96. void
  97. subview_field<oT>::operator= (const subview_field<oT>& x)
  98. {
  99. arma_extra_debug_sigprint();
  100. if(check_overlap(x))
  101. {
  102. const field<oT> tmp(x);
  103. (*this).operator=(tmp);
  104. return;
  105. }
  106. subview_field<oT>& t = *this;
  107. arma_debug_check( (t.n_rows != x.n_rows) || (t.n_cols != x.n_cols) || (t.n_slices != x.n_slices), "incompatible field dimensions" );
  108. if(t.n_slices == 1)
  109. {
  110. for(uword col=0; col < t.n_cols; ++col)
  111. for(uword row=0; row < t.n_rows; ++row)
  112. {
  113. t.at(row,col) = x.at(row,col);
  114. }
  115. }
  116. else
  117. {
  118. for(uword slice=0; slice < t.n_slices; ++slice)
  119. for(uword col=0; col < t.n_cols; ++col )
  120. for(uword row=0; row < t.n_rows; ++row )
  121. {
  122. t.at(row,col,slice) = x.at(row,col,slice);
  123. }
  124. }
  125. }
  126. template<typename oT>
  127. arma_inline
  128. oT&
  129. subview_field<oT>::operator[](const uword i)
  130. {
  131. const uword n_elem_slice = n_rows*n_cols;
  132. const uword in_slice = i / n_elem_slice;
  133. const uword offset = in_slice * n_elem_slice;
  134. const uword j = i - offset;
  135. const uword in_col = j / n_rows;
  136. const uword in_row = j % n_rows;
  137. const uword index = (in_slice + aux_slice1)*(f.n_rows*f.n_cols) + (in_col + aux_col1)*f.n_rows + aux_row1 + in_row;
  138. return *((const_cast< field<oT>& >(f)).mem[index]);
  139. }
  140. template<typename oT>
  141. arma_inline
  142. const oT&
  143. subview_field<oT>::operator[](const uword i) const
  144. {
  145. const uword n_elem_slice = n_rows*n_cols;
  146. const uword in_slice = i / n_elem_slice;
  147. const uword offset = in_slice * n_elem_slice;
  148. const uword j = i - offset;
  149. const uword in_col = j / n_rows;
  150. const uword in_row = j % n_rows;
  151. const uword index = (in_slice + aux_slice1)*(f.n_rows*f.n_cols) + (in_col + aux_col1)*f.n_rows + aux_row1 + in_row;
  152. return *(f.mem[index]);
  153. }
  154. template<typename oT>
  155. arma_inline
  156. oT&
  157. subview_field<oT>::operator()(const uword i)
  158. {
  159. arma_debug_check( (i >= n_elem), "subview_field::operator(): index out of bounds" );
  160. return operator[](i);
  161. }
  162. template<typename oT>
  163. arma_inline
  164. const oT&
  165. subview_field<oT>::operator()(const uword i) const
  166. {
  167. arma_debug_check( (i >= n_elem), "subview_field::operator(): index out of bounds" );
  168. return operator[](i);
  169. }
  170. template<typename oT>
  171. arma_inline
  172. oT&
  173. subview_field<oT>::operator()(const uword in_row, const uword in_col)
  174. {
  175. return operator()(in_row, in_col, 0);
  176. }
  177. template<typename oT>
  178. arma_inline
  179. const oT&
  180. subview_field<oT>::operator()(const uword in_row, const uword in_col) const
  181. {
  182. return operator()(in_row, in_col, 0);
  183. }
  184. template<typename oT>
  185. arma_inline
  186. oT&
  187. subview_field<oT>::operator()(const uword in_row, const uword in_col, const uword in_slice)
  188. {
  189. arma_debug_check( ((in_row >= n_rows) || (in_col >= n_cols) || (in_slice >= n_slices)), "subview_field::operator(): index out of bounds" );
  190. const uword index = (in_slice + aux_slice1)*(f.n_rows*f.n_cols) + (in_col + aux_col1)*f.n_rows + aux_row1 + in_row;
  191. return *((const_cast< field<oT>& >(f)).mem[index]);
  192. }
  193. template<typename oT>
  194. arma_inline
  195. const oT&
  196. subview_field<oT>::operator()(const uword in_row, const uword in_col, const uword in_slice) const
  197. {
  198. arma_debug_check( ((in_row >= n_rows) || (in_col >= n_cols) || (in_slice >= n_slices)), "subview_field::operator(): index out of bounds" );
  199. const uword index = (in_slice + aux_slice1)*(f.n_rows*f.n_cols) + (in_col + aux_col1)*f.n_rows + aux_row1 + in_row;
  200. return *(f.mem[index]);
  201. }
  202. template<typename oT>
  203. arma_inline
  204. oT&
  205. subview_field<oT>::at(const uword in_row, const uword in_col)
  206. {
  207. return at(in_row, in_col, 0);
  208. }
  209. template<typename oT>
  210. arma_inline
  211. const oT&
  212. subview_field<oT>::at(const uword in_row, const uword in_col) const
  213. {
  214. return at(in_row, in_col, 0);
  215. }
  216. template<typename oT>
  217. arma_inline
  218. oT&
  219. subview_field<oT>::at(const uword in_row, const uword in_col, const uword in_slice)
  220. {
  221. const uword index = (in_slice + aux_slice1)*(f.n_rows*f.n_cols) + (in_col + aux_col1)*f.n_rows + aux_row1 + in_row;
  222. return *((const_cast< field<oT>& >(f)).mem[index]);
  223. }
  224. template<typename oT>
  225. arma_inline
  226. const oT&
  227. subview_field<oT>::at(const uword in_row, const uword in_col, const uword in_slice) const
  228. {
  229. const uword index = (in_slice + aux_slice1)*(f.n_rows*f.n_cols) + (in_col + aux_col1)*f.n_rows + aux_row1 + in_row;
  230. return *(f.mem[index]);
  231. }
  232. template<typename oT>
  233. arma_inline
  234. bool
  235. subview_field<oT>::is_empty() const
  236. {
  237. return (n_elem == 0);
  238. }
  239. template<typename oT>
  240. inline
  241. bool
  242. subview_field<oT>::check_overlap(const subview_field<oT>& x) const
  243. {
  244. const subview_field<oT>& t = *this;
  245. if(&t.f != &x.f)
  246. {
  247. return false;
  248. }
  249. else
  250. {
  251. if( (t.n_elem == 0) || (x.n_elem == 0) )
  252. {
  253. return false;
  254. }
  255. else
  256. {
  257. const uword t_row_start = t.aux_row1;
  258. const uword t_row_end_p1 = t_row_start + t.n_rows;
  259. const uword t_col_start = t.aux_col1;
  260. const uword t_col_end_p1 = t_col_start + t.n_cols;
  261. const uword t_slice_start = t.aux_slice1;
  262. const uword t_slice_end_p1 = t_slice_start + t.n_slices;
  263. const uword x_row_start = x.aux_row1;
  264. const uword x_row_end_p1 = x_row_start + x.n_rows;
  265. const uword x_col_start = x.aux_col1;
  266. const uword x_col_end_p1 = x_col_start + x.n_cols;
  267. const uword x_slice_start = x.aux_slice1;
  268. const uword x_slice_end_p1 = x_slice_start + x.n_slices;
  269. const bool outside_rows = ( (x_row_start >= t_row_end_p1 ) || (t_row_start >= x_row_end_p1 ) );
  270. const bool outside_cols = ( (x_col_start >= t_col_end_p1 ) || (t_col_start >= x_col_end_p1 ) );
  271. const bool outside_slices = ( (x_slice_start >= t_slice_end_p1) || (t_slice_start >= x_slice_end_p1) );
  272. return ( (outside_rows == false) && (outside_cols == false) && (outside_slices == false) );
  273. }
  274. }
  275. }
  276. template<typename oT>
  277. inline
  278. void
  279. subview_field<oT>::print(const std::string extra_text) const
  280. {
  281. arma_extra_debug_sigprint();
  282. if(extra_text.length() != 0)
  283. {
  284. const std::streamsize orig_width = get_cout_stream().width();
  285. get_cout_stream() << extra_text << '\n';
  286. get_cout_stream().width(orig_width);
  287. }
  288. arma_ostream::print(get_cout_stream(), *this);
  289. }
  290. template<typename oT>
  291. inline
  292. void
  293. subview_field<oT>::print(std::ostream& user_stream, const std::string extra_text) const
  294. {
  295. arma_extra_debug_sigprint();
  296. if(extra_text.length() != 0)
  297. {
  298. const std::streamsize orig_width = user_stream.width();
  299. user_stream << extra_text << '\n';
  300. user_stream.width(orig_width);
  301. }
  302. arma_ostream::print(user_stream, *this);
  303. }
  304. template<typename oT>
  305. template<typename functor>
  306. inline
  307. void
  308. subview_field<oT>::for_each(functor F)
  309. {
  310. arma_extra_debug_sigprint();
  311. subview_field<oT>& t = *this;
  312. if(t.n_slices == 1)
  313. {
  314. for(uword col=0; col < t.n_cols; ++col)
  315. for(uword row=0; row < t.n_rows; ++row)
  316. {
  317. F( t.at(row,col) );
  318. }
  319. }
  320. else
  321. {
  322. for(uword slice=0; slice < t.n_slices; ++slice)
  323. for(uword col=0; col < t.n_cols; ++col )
  324. for(uword row=0; row < t.n_rows; ++row )
  325. {
  326. F( t.at(row,col,slice) );
  327. }
  328. }
  329. }
  330. template<typename oT>
  331. template<typename functor>
  332. inline
  333. void
  334. subview_field<oT>::for_each(functor F) const
  335. {
  336. arma_extra_debug_sigprint();
  337. const subview_field<oT>& t = *this;
  338. if(t.n_slices == 1)
  339. {
  340. for(uword col=0; col < t.n_cols; ++col)
  341. for(uword row=0; row < t.n_rows; ++row)
  342. {
  343. F( t.at(row,col) );
  344. }
  345. }
  346. else
  347. {
  348. for(uword slice=0; slice < t.n_slices; ++slice)
  349. for(uword col=0; col < t.n_cols; ++col )
  350. for(uword row=0; row < t.n_rows; ++row )
  351. {
  352. F( t.at(row,col,slice) );
  353. }
  354. }
  355. }
  356. template<typename oT>
  357. inline
  358. void
  359. subview_field<oT>::fill(const oT& x)
  360. {
  361. arma_extra_debug_sigprint();
  362. subview_field<oT>& t = *this;
  363. if(t.n_slices == 1)
  364. {
  365. for(uword col=0; col < t.n_cols; ++col)
  366. for(uword row=0; row < t.n_rows; ++row)
  367. {
  368. t.at(row,col) = x;
  369. }
  370. }
  371. else
  372. {
  373. for(uword slice=0; slice < t.n_slices; ++slice)
  374. for(uword col=0; col < t.n_cols; ++col )
  375. for(uword row=0; row < t.n_rows; ++row )
  376. {
  377. t.at(row,col,slice) = x;
  378. }
  379. }
  380. }
  381. //! X = Y.subfield(...)
  382. template<typename oT>
  383. inline
  384. void
  385. subview_field<oT>::extract(field<oT>& actual_out, const subview_field<oT>& in)
  386. {
  387. arma_extra_debug_sigprint();
  388. //
  389. const bool alias = (&actual_out == &in.f);
  390. field<oT>* tmp = (alias) ? new field<oT> : 0;
  391. field<oT>& out = (alias) ? (*tmp) : actual_out;
  392. //
  393. const uword n_rows = in.n_rows;
  394. const uword n_cols = in.n_cols;
  395. const uword n_slices = in.n_slices;
  396. out.set_size(n_rows, n_cols, n_slices);
  397. arma_extra_debug_print(arma_str::format("out.n_rows = %d out.n_cols = %d out.n_slices = %d in.m.n_rows = %d in.m.n_cols = %d in.m.n_slices = %d") % out.n_rows % out.n_cols % out.n_slices % in.f.n_rows % in.f.n_cols % in.f.n_slices);
  398. if(n_slices == 1)
  399. {
  400. for(uword col = 0; col < n_cols; ++col)
  401. for(uword row = 0; row < n_rows; ++row)
  402. {
  403. out.at(row,col) = in.at(row,col);
  404. }
  405. }
  406. else
  407. {
  408. for(uword slice = 0; slice < n_slices; ++slice)
  409. for(uword col = 0; col < n_cols; ++col )
  410. for(uword row = 0; row < n_rows; ++row )
  411. {
  412. out.at(row,col,slice) = in.at(row,col,slice);
  413. }
  414. }
  415. if(alias)
  416. {
  417. actual_out = out;
  418. delete tmp;
  419. }
  420. }
  421. //! @}