xcomplex_sequence.hpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578
  1. /***************************************************************************
  2. * Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
  3. * Copyright (c) QuantStack *
  4. * *
  5. * Distributed under the terms of the BSD 3-Clause License. *
  6. * *
  7. * The full license is in the file LICENSE, distributed with this software. *
  8. ****************************************************************************/
  9. #ifndef XTL_XCOMPLEX_SEQUENCE_HPP
  10. #define XTL_XCOMPLEX_SEQUENCE_HPP
  11. #include <array>
  12. #include <vector>
  13. #include <algorithm>
  14. #include "xclosure.hpp"
  15. #include "xcomplex.hpp"
  16. #include "xiterator_base.hpp"
  17. #include "xsequence.hpp"
  18. namespace xtl
  19. {
  20. /************************************
  21. * Optimized 1-D xcomplex container *
  22. ************************************/
  23. template <class IT, bool ieee_compliant>
  24. class xcomplex_iterator;
  25. template <class C, bool ieee_compliant>
  26. class xcomplex_sequence
  27. {
  28. public:
  29. using container_type = C;
  30. using cvt = typename C::value_type;
  31. using value_type = xcomplex<cvt, cvt, ieee_compliant>;
  32. using reference = xcomplex<cvt&, cvt&, ieee_compliant>;
  33. using const_reference = xcomplex<const cvt&, const cvt&, ieee_compliant>;
  34. using pointer = xclosure_pointer<reference>;
  35. using const_pointer = xclosure_pointer<const_reference>;
  36. using size_type = typename container_type::size_type;
  37. using difference_type = typename container_type::difference_type;
  38. using iterator = xcomplex_iterator<typename C::iterator, ieee_compliant>;
  39. using const_iterator = xcomplex_iterator<typename C::const_iterator, ieee_compliant>;
  40. using reverse_iterator = xcomplex_iterator<typename C::reverse_iterator, ieee_compliant>;
  41. using const_reverse_iterator = xcomplex_iterator<typename C::const_reverse_iterator, ieee_compliant>;
  42. bool empty() const noexcept;
  43. size_type size() const noexcept;
  44. size_type max_size() const noexcept;
  45. reference at(size_type i);
  46. const_reference at(size_type i) const;
  47. reference operator[](size_type i);
  48. const_reference operator[](size_type i) const;
  49. reference front();
  50. const_reference front() const;
  51. reference back();
  52. const_reference back() const;
  53. iterator begin() noexcept;
  54. iterator end() noexcept;
  55. const_iterator begin() const noexcept;
  56. const_iterator end() const noexcept;
  57. const_iterator cbegin() const noexcept;
  58. const_iterator cend() const noexcept;
  59. reverse_iterator rbegin() noexcept;
  60. reverse_iterator rend() noexcept;
  61. const_reverse_iterator rbegin() const noexcept;
  62. const_reverse_iterator rend() const noexcept;
  63. const_reverse_iterator crbegin() const noexcept;
  64. const_reverse_iterator crend() const noexcept;
  65. container_type real() && noexcept;
  66. container_type& real() & noexcept;
  67. const container_type& real() const & noexcept;
  68. container_type imag() && noexcept;
  69. container_type& imag() & noexcept;
  70. const container_type& imag() const & noexcept;
  71. protected:
  72. xcomplex_sequence() = default;
  73. xcomplex_sequence(size_type s);
  74. xcomplex_sequence(size_type s, const value_type& v);
  75. template <class TR, class TC, bool B>
  76. xcomplex_sequence(size_type s, const xcomplex<TR, TC, B>& v);
  77. xcomplex_sequence(std::initializer_list<value_type> init);
  78. ~xcomplex_sequence() = default;
  79. xcomplex_sequence(const xcomplex_sequence&) = default;
  80. xcomplex_sequence& operator=(const xcomplex_sequence&) = default;
  81. xcomplex_sequence(xcomplex_sequence&&) = default;
  82. xcomplex_sequence& operator=(xcomplex_sequence&&) = default;
  83. container_type m_real;
  84. container_type m_imag;
  85. };
  86. template <class C, bool B>
  87. bool operator==(const xcomplex_sequence<C, B>& lhs, const xcomplex_sequence<C, B>& rhs);
  88. template <class C, bool B>
  89. bool operator!=(const xcomplex_sequence<C, B>& lhs, const xcomplex_sequence<C, B>& rhs);
  90. /******************
  91. * xcomplex_array *
  92. ******************/
  93. template <class T, std::size_t N, bool ieee_compliant = false>
  94. class xcomplex_array : public xcomplex_sequence<std::array<T, N>, ieee_compliant>
  95. {
  96. public:
  97. using base_type = xcomplex_sequence<std::array<T, N>, ieee_compliant>;
  98. using value_type = typename base_type::value_type;
  99. using size_type = typename base_type::size_type;
  100. xcomplex_array() = default;
  101. xcomplex_array(size_type s);
  102. xcomplex_array(size_type s, const value_type& v);
  103. template <class TR, class TI, bool B>
  104. xcomplex_array(size_type s, const xcomplex<TR, TI, B>& v);
  105. };
  106. /*******************
  107. * xcomplex_vector *
  108. *******************/
  109. template <class T, bool ieee_compliant = false, class A = std::allocator<T>>
  110. class xcomplex_vector : public xcomplex_sequence<std::vector<T, A>, ieee_compliant>
  111. {
  112. public:
  113. using base_type = xcomplex_sequence<std::vector<T, A>, ieee_compliant>;
  114. using value_type = typename base_type::value_type;
  115. using size_type = typename base_type::size_type;
  116. xcomplex_vector() = default;
  117. xcomplex_vector(size_type s);
  118. xcomplex_vector(size_type s, const value_type& v);
  119. xcomplex_vector(std::initializer_list<value_type> init);
  120. template <class TR, class TI, bool B>
  121. xcomplex_vector(size_type s, const xcomplex<TR, TI, B>& v);
  122. void resize(size_type);
  123. void resize(size_type, const value_type&);
  124. template <class TR, class TI, bool B>
  125. void resize(size_type s, const xcomplex<TR, TI, B>& v);
  126. };
  127. /*********************
  128. * xcomplex_iterator *
  129. *********************/
  130. template <class IT, bool ieee_compliant>
  131. struct xcomplex_iterator_traits
  132. {
  133. using iterator_type = xcomplex_iterator<IT, ieee_compliant>;
  134. using value_type = xcomplex<typename IT::value_type, typename IT::value_type, ieee_compliant>;
  135. using reference = xcomplex<typename IT::reference, typename IT::reference, ieee_compliant>;
  136. using pointer = xclosure_pointer<reference>;
  137. using difference_type = typename IT::difference_type;
  138. };
  139. template <class IT, bool B>
  140. class xcomplex_iterator : public xrandom_access_iterator_base2<xcomplex_iterator_traits<IT, B>>
  141. {
  142. public:
  143. using self_type = xcomplex_iterator<IT, B>;
  144. using base_type = xrandom_access_iterator_base2<xcomplex_iterator_traits<IT, B>>;
  145. using value_type = typename base_type::value_type;
  146. using reference = typename base_type::reference;
  147. using pointer = typename base_type::pointer;
  148. using difference_type = typename base_type::difference_type;
  149. xcomplex_iterator() = default;
  150. xcomplex_iterator(IT it_real, IT it_imag);
  151. self_type& operator++();
  152. self_type& operator--();
  153. self_type& operator+=(difference_type n);
  154. self_type& operator-=(difference_type n);
  155. difference_type operator-(const self_type& rhs) const;
  156. reference operator*() const;
  157. pointer operator->() const;
  158. bool operator==(const self_type& rhs) const;
  159. private:
  160. IT m_it_real;
  161. IT m_it_imag;
  162. };
  163. /************************************
  164. * xcomplex_sequence implementation *
  165. ************************************/
  166. template <class C, bool B>
  167. inline xcomplex_sequence<C, B>::xcomplex_sequence(size_type s)
  168. : m_real(make_sequence<container_type>(s)),
  169. m_imag(make_sequence<container_type>(s))
  170. {
  171. }
  172. template <class C, bool B>
  173. inline xcomplex_sequence<C, B>::xcomplex_sequence(size_type s, const value_type& v)
  174. : m_real(make_sequence<container_type>(s, v.real())),
  175. m_imag(make_sequence<container_type>(s, v.imag()))
  176. {
  177. }
  178. template <class C, bool B>
  179. template <class TR, class TC, bool B2>
  180. inline xcomplex_sequence<C, B>::xcomplex_sequence(size_type s, const xcomplex<TR, TC, B2>& v)
  181. : m_real(make_sequence<container_type>(s, v.real())),
  182. m_imag(make_sequence<container_type>(s, v.imag()))
  183. {
  184. }
  185. template <class C, bool B>
  186. inline xcomplex_sequence<C, B>::xcomplex_sequence(std::initializer_list<value_type> init)
  187. : m_real(make_sequence<container_type>(init.size())),
  188. m_imag(make_sequence<container_type>(init.size()))
  189. {
  190. std::transform(init.begin(), init.end(), m_real.begin(), [](const auto& v) { return v.real(); });
  191. std::transform(init.begin(), init.end(), m_imag.begin(), [](const auto& v) { return v.imag(); });
  192. }
  193. template <class C, bool B>
  194. inline bool xcomplex_sequence<C, B>::empty() const noexcept
  195. {
  196. return m_real.empty();
  197. }
  198. template <class C, bool B>
  199. inline auto xcomplex_sequence<C, B>::size() const noexcept -> size_type
  200. {
  201. return m_real.size();
  202. }
  203. template <class C, bool B>
  204. inline auto xcomplex_sequence<C, B>::max_size() const noexcept -> size_type
  205. {
  206. return m_real.max_size();
  207. }
  208. template <class C, bool B>
  209. inline auto xcomplex_sequence<C, B>::at(size_type i) -> reference
  210. {
  211. return reference(m_real.at(i), m_imag.at(i));
  212. }
  213. template <class C, bool B>
  214. inline auto xcomplex_sequence<C, B>::at(size_type i) const -> const_reference
  215. {
  216. return const_reference(m_real.at(i), m_imag.at(i));
  217. }
  218. template <class C, bool B>
  219. inline auto xcomplex_sequence<C, B>::operator[](size_type i) -> reference
  220. {
  221. return reference(m_real[i], m_imag[i]);
  222. }
  223. template <class C, bool B>
  224. inline auto xcomplex_sequence<C, B>::operator[](size_type i) const -> const_reference
  225. {
  226. return const_reference(m_real[i], m_imag[i]);
  227. }
  228. template <class C, bool B>
  229. inline auto xcomplex_sequence<C, B>::front() -> reference
  230. {
  231. return reference(m_real.front(), m_imag.front());
  232. }
  233. template <class C, bool B>
  234. inline auto xcomplex_sequence<C, B>::front() const -> const_reference
  235. {
  236. return const_reference(m_real.front(), m_imag.front());
  237. }
  238. template <class C, bool B>
  239. inline auto xcomplex_sequence<C, B>::back() -> reference
  240. {
  241. return reference(m_real.back(), m_imag.back());
  242. }
  243. template <class C, bool B>
  244. inline auto xcomplex_sequence<C, B>::back() const -> const_reference
  245. {
  246. return const_reference(m_real.back(), m_imag.back());
  247. }
  248. template <class C, bool B>
  249. inline auto xcomplex_sequence<C, B>::begin() noexcept -> iterator
  250. {
  251. return iterator(m_real.begin(), m_imag.begin());
  252. }
  253. template <class C, bool B>
  254. inline auto xcomplex_sequence<C, B>::end() noexcept -> iterator
  255. {
  256. return iterator(m_real.end(), m_imag.end());
  257. }
  258. template <class C, bool B>
  259. inline auto xcomplex_sequence<C, B>::begin() const noexcept -> const_iterator
  260. {
  261. return cbegin();
  262. }
  263. template <class C, bool B>
  264. inline auto xcomplex_sequence<C, B>::end() const noexcept -> const_iterator
  265. {
  266. return cend();
  267. }
  268. template <class C, bool B>
  269. inline auto xcomplex_sequence<C, B>::cbegin() const noexcept -> const_iterator
  270. {
  271. return const_iterator(m_real.cbegin(), m_imag.cbegin());
  272. }
  273. template <class C, bool B>
  274. inline auto xcomplex_sequence<C, B>::cend() const noexcept -> const_iterator
  275. {
  276. return const_iterator(m_real.cend(), m_imag.cend());
  277. }
  278. template <class C, bool B>
  279. inline auto xcomplex_sequence<C, B>::rbegin() noexcept -> reverse_iterator
  280. {
  281. return reverse_iterator(m_real.rbegin(), m_imag.rbegin());
  282. }
  283. template <class C, bool B>
  284. inline auto xcomplex_sequence<C, B>::rend() noexcept -> reverse_iterator
  285. {
  286. return reverse_iterator(m_real.rend(), m_imag.rend());
  287. }
  288. template <class C, bool B>
  289. inline auto xcomplex_sequence<C, B>::rbegin() const noexcept -> const_reverse_iterator
  290. {
  291. return crbegin();
  292. }
  293. template <class C, bool B>
  294. inline auto xcomplex_sequence<C, B>::rend() const noexcept -> const_reverse_iterator
  295. {
  296. return crend();
  297. }
  298. template <class C, bool B>
  299. inline auto xcomplex_sequence<C, B>::crbegin() const noexcept -> const_reverse_iterator
  300. {
  301. return const_reverse_iterator(m_real.crbegin(), m_imag.crbegin());
  302. }
  303. template <class C, bool B>
  304. inline auto xcomplex_sequence<C, B>::crend() const noexcept -> const_reverse_iterator
  305. {
  306. return const_reverse_iterator(m_real.crend(), m_imag.crend());
  307. }
  308. template <class C, bool B>
  309. inline auto xcomplex_sequence<C, B>::real() && noexcept -> container_type
  310. {
  311. return m_real;
  312. }
  313. template <class C, bool B>
  314. inline auto xcomplex_sequence<C, B>::real() & noexcept -> container_type&
  315. {
  316. return m_real;
  317. }
  318. template <class C, bool B>
  319. inline auto xcomplex_sequence<C, B>::real() const & noexcept -> const container_type&
  320. {
  321. return m_real;
  322. }
  323. template <class C, bool B>
  324. inline auto xcomplex_sequence<C, B>::imag() && noexcept -> container_type
  325. {
  326. return m_imag;
  327. }
  328. template <class C, bool B>
  329. inline auto xcomplex_sequence<C, B>::imag() & noexcept -> container_type&
  330. {
  331. return m_imag;
  332. }
  333. template <class C, bool B>
  334. inline auto xcomplex_sequence<C, B>::imag() const & noexcept -> const container_type&
  335. {
  336. return m_imag;
  337. }
  338. template <class C, bool B>
  339. inline bool operator==(const xcomplex_sequence<C, B>& lhs, const xcomplex_sequence<C, B>& rhs)
  340. {
  341. return lhs.real() == rhs.real() && lhs.imag() == rhs.imag();
  342. }
  343. template <class C, bool B>
  344. inline bool operator!=(const xcomplex_sequence<C, B>& lhs, const xcomplex_sequence<C, B>& rhs)
  345. {
  346. return !(lhs == rhs);
  347. }
  348. /*********************************
  349. * xcomplex_array implementation *
  350. *********************************/
  351. template <class T, std::size_t N, bool B>
  352. inline xcomplex_array<T, N, B>::xcomplex_array(size_type s)
  353. : base_type(s)
  354. {
  355. }
  356. template <class T, std::size_t N, bool B>
  357. inline xcomplex_array<T, N, B>::xcomplex_array(size_type s, const value_type& v)
  358. : base_type(s, v)
  359. {
  360. }
  361. template <class T, std::size_t N, bool B>
  362. template <class TR, class TI, bool B2>
  363. inline xcomplex_array<T, N, B>::xcomplex_array(size_type s, const xcomplex<TR, TI, B2>& v)
  364. : base_type(s, v)
  365. {
  366. }
  367. /**********************************
  368. * xcomplex_vector implementation *
  369. **********************************/
  370. template <class T, bool B, class A>
  371. inline xcomplex_vector<T, B, A>::xcomplex_vector(size_type s)
  372. : base_type(s)
  373. {
  374. }
  375. template <class T, bool B, class A>
  376. inline xcomplex_vector<T, B, A>::xcomplex_vector(size_type s, const value_type& v)
  377. : base_type(s, v)
  378. {
  379. }
  380. template <class T, bool B, class A>
  381. template <class TR, class TI, bool B2>
  382. inline xcomplex_vector<T, B, A>::xcomplex_vector(size_type s, const xcomplex<TR, TI, B2>& v)
  383. : base_type(s, v)
  384. {
  385. }
  386. template <class T, bool B, class A>
  387. inline xcomplex_vector<T, B, A>::xcomplex_vector(std::initializer_list<value_type> init)
  388. : base_type(init)
  389. {
  390. }
  391. template <class T, bool B, class A>
  392. void xcomplex_vector<T, B, A>::resize(size_type s)
  393. {
  394. this->m_real.resize(s);
  395. this->m_imag.resize(s);
  396. }
  397. template <class T, bool B, class A>
  398. void xcomplex_vector<T, B, A>::resize(size_type s, const value_type& v)
  399. {
  400. this->m_real.resize(s, v.real());
  401. this->m_imag.resize(s, v.imag());
  402. }
  403. template <class T, bool B, class A>
  404. template <class TR, class TI, bool B2>
  405. inline void xcomplex_vector<T, B, A>::resize(size_type s, const xcomplex<TR, TI, B2>& v)
  406. {
  407. this->m_real.resize(s, v.real());
  408. this->m_imag.resize(s, v.imag());
  409. }
  410. /************************************
  411. * xcomplex_iterator implementation *
  412. ************************************/
  413. template <class IT, bool B>
  414. inline xcomplex_iterator<IT, B>::xcomplex_iterator(IT it_real, IT it_imag)
  415. : m_it_real(it_real), m_it_imag(it_imag)
  416. {
  417. }
  418. template <class IT, bool B>
  419. inline auto xcomplex_iterator<IT, B>::operator++() -> self_type&
  420. {
  421. ++m_it_real;
  422. ++m_it_imag;
  423. return *this;
  424. }
  425. template <class IT, bool B>
  426. inline auto xcomplex_iterator<IT, B>::operator--() -> self_type&
  427. {
  428. --m_it_real;
  429. --m_it_imag;
  430. return *this;
  431. }
  432. template <class IT, bool B>
  433. inline auto xcomplex_iterator<IT, B>::operator+=(difference_type n) -> self_type&
  434. {
  435. m_it_real += n;
  436. m_it_imag += n;
  437. return *this;
  438. }
  439. template <class IT, bool B>
  440. inline auto xcomplex_iterator<IT, B>::operator-=(difference_type n) -> self_type&
  441. {
  442. m_it_real -= n;
  443. m_it_imag -= n;
  444. return *this;
  445. }
  446. template <class IT, bool B>
  447. inline auto xcomplex_iterator<IT, B>::operator-(const self_type& rhs) const -> difference_type
  448. {
  449. return m_it_real - rhs.m_it_real;
  450. }
  451. template <class IT, bool B>
  452. inline auto xcomplex_iterator<IT, B>::operator*() const -> reference
  453. {
  454. return reference(*m_it_real, *m_it_imag);
  455. }
  456. template <class IT, bool B>
  457. inline auto xcomplex_iterator<IT, B>::operator->() const -> pointer
  458. {
  459. return pointer(operator*());
  460. }
  461. template <class IT, bool B>
  462. inline bool xcomplex_iterator<IT, B>::operator==(const self_type& rhs) const
  463. {
  464. return m_it_real == rhs.m_it_real && m_it_imag == rhs.m_it_imag;
  465. }
  466. }
  467. #endif