1 // license:GPL-2.0+
2 // copyright-holders:Couriersud
3 
4 #ifndef PMATRIX2D_H_
5 #define PMATRIX2D_H_
6 
7 ///
8 /// \file pmatrix2d.h
9 ///
10 
11 #include "palloc.h"
12 
13 #include <algorithm>
14 #include <type_traits>
15 #include <vector>
16 
17 namespace plib
18 {
19 
20 	template<typename T, typename A = aligned_arena>
21 	class pmatrix2d
22 	{
23 	public:
24 		using size_type = std::size_t;
25 		using arena_type = A;
26 		using allocator_type = typename A::template allocator_type<T, PALIGN_VECTOROPT>;
27 
28 		static constexpr const size_type align_size = align_traits<allocator_type>::align_size;
29 		static constexpr const size_type stride_size = align_traits<allocator_type>::stride_size;
30 
31 		using value_type = T;
32 		using reference = T &;
33 		using const_reference = const T &;
34 
35 		using pointer = T *;
36 		using const_pointer = const T *;
37 
pmatrix2d()38 		pmatrix2d() noexcept
39 		: m_N(0), m_M(0), m_stride(8), m_v(nullptr)
40 		{
41 		}
42 
pmatrix2d(size_type N,size_type M)43 		pmatrix2d(size_type N, size_type M)
44 		: m_N(N), m_M(M), m_v()
45 		{
46 			gsl_Expects(N>0);
47 			gsl_Expects(M>0);
48 			m_stride = ((M + stride_size-1) / stride_size) * stride_size;
49 			m_v = m_a.allocate(N * m_stride);
50 			for (std::size_t i = 0; i < N * m_stride; i++)
51 				::new(&m_v[i]) T();
52 		}
53 
54 		pmatrix2d(const pmatrix2d &) = delete;
55 		pmatrix2d &operator=(const pmatrix2d &) = delete;
56 		pmatrix2d(pmatrix2d &&) = delete;
57 		pmatrix2d &operator=(pmatrix2d &&) = delete;
58 
~pmatrix2d()59 		~pmatrix2d()
60 		{
61 			if (m_v != nullptr)
62 			{
63 				for (std::size_t i = 0; i < m_N * m_stride; i++)
64 					(&m_v[i])->~T();
65 				m_a.deallocate(m_v, m_N * m_stride);
66 			}
67 		}
68 
resize(size_type N,size_type M)69 		void resize(size_type N, size_type M)
70 		{
71 			gsl_Expects(N>0);
72 			gsl_Expects(M>0);
73 			if (m_v != nullptr)
74 			{
75 				for (std::size_t i = 0; i < N * m_stride; i++)
76 					(&m_v[i])->~T();
77 				m_a.deallocate(m_v, N * m_stride);
78 			}
79 			m_N = N;
80 			m_M = M;
81 			m_stride = ((M + stride_size-1) / stride_size) * stride_size;
82 			m_v = m_a.allocate(N * m_stride);
83 			for (std::size_t i = 0; i < N * m_stride; i++)
84 				::new(&m_v[i]) T();
85 		}
86 
87 		constexpr pointer operator[] (size_type row) noexcept
88 		{
89 			return &m_v[m_stride * row];
90 		}
91 
92 		constexpr const_pointer operator[] (size_type row) const noexcept
93 		{
94 			return &m_v[m_stride * row];
95 		}
96 
operator()97 		reference operator()(size_type r, size_type c) noexcept
98 		{
99 			return (*this)[r][c];
100 		}
101 
operator()102 		const_reference operator()(size_type r, size_type c) const noexcept
103 		{
104 			return (*this)[r][c];
105 		}
106 
107 		// for compatibility with vrl variant
set(size_type r,size_type c,const value_type & v)108 		void set(size_type r, size_type c, const value_type &v) noexcept
109 		{
110 			(*this)[r][c] = v;
111 		}
112 
data()113 		pointer data() noexcept
114 		{
115 			return m_v;
116 		}
117 
data()118 		const_pointer data() const noexcept
119 		{
120 			return m_v;
121 		}
122 
didx(size_type r,size_type c)123 		size_type didx(size_type r, size_type c) const noexcept
124 		{
125 			return m_stride * r + c;
126 		}
127 	private:
128 
129 		size_type m_N;
130 		size_type m_M;
131 		size_type m_stride;
132 
133 		T * __restrict m_v;
134 
135 		allocator_type m_a;
136 	};
137 
138 	// variable row length matrix
139 	template<typename T, typename A = aligned_arena>
140 	class pmatrix2d_vrl
141 	{
142 	public:
143 		using size_type = std::size_t;
144 		using value_type = T;
145 		using arena_type = A;
146 		using allocator_type = typename A::template allocator_type<T, PALIGN_VECTOROPT>;
147 
148 		static constexpr const size_type align_size = align_traits<allocator_type>::align_size;
149 		static constexpr const size_type stride_size = align_traits<allocator_type>::stride_size;
150 
pmatrix2d_vrl()151 		pmatrix2d_vrl() noexcept
152 		: m_N(0), m_M(0), m_v()
153 		{
154 		}
155 
pmatrix2d_vrl(size_type N,size_type M)156 		pmatrix2d_vrl(size_type N, size_type M)
157 		: m_N(N), m_M(M), m_v()
158 		{
159 			m_row.resize(N + 1, 0);
160 			m_v.resize(N); //FIXME
161 		}
162 
163 		pmatrix2d_vrl(const pmatrix2d_vrl &) = default;
164 		pmatrix2d_vrl &operator=(const pmatrix2d_vrl &) = default;
165 		pmatrix2d_vrl(pmatrix2d_vrl &&) = default;
166 		pmatrix2d_vrl &operator=(pmatrix2d_vrl &&) = default;
167 
168 		~pmatrix2d_vrl() = default;
169 
resize(size_type N,size_type M)170 		void resize(size_type N, size_type M)
171 		{
172 			m_N = N;
173 			m_M = M;
174 			m_row.resize(N + 1);
175 			for (std::size_t i = 0; i < m_N; i++)
176 				m_row[i] = 0;
177 			m_v.resize(N); //FIXME
178 		}
179 
180 		constexpr T * operator[] (size_type row) noexcept
181 		{
182 			return &(m_v[m_row[row]]);
183 		}
184 
185 		constexpr const T * operator[] (size_type row) const noexcept
186 		{
187 			return &(m_v[m_row[row]]);
188 		}
189 
190 		//FIXME: no check!
operator()191 		T & operator()(size_type r, size_type c) noexcept
192 		{
193 			return (*this)[r][c];
194 		}
195 
set(size_type r,size_type c,const T & v)196 		void set(size_type r, size_type c, const T &v) noexcept
197 		{
198 			if (c + m_row[r] >= m_row[r + 1])
199 			{
200 				m_v.insert(m_v.begin() + narrow_cast<std::ptrdiff_t>(m_row[r+1]), v);
201 				for (size_type i = r + 1; i <= m_N; i++)
202 					m_row[i] = m_row[i] + 1;
203 			}
204 			else
205 				(*this)[r][c] = v;
206 		}
207 
208 		//FIXME: no check!
operator()209 		const T & operator()(size_type r, size_type c) const noexcept
210 		{
211 			return (*this)[r][c];
212 		}
213 
data()214 		T * data() noexcept
215 		{
216 			return m_v.data();
217 		}
218 
data()219 		const T * data() const noexcept
220 		{
221 			return m_v.data();
222 		}
223 
224 		//FIXME: no check!
didx(size_type r,size_type c)225 		size_type didx(size_type r, size_type c) const noexcept
226 		{
227 			return m_row[r] + c;
228 		}
229 
colcount(size_type row)230 		size_type colcount(size_type row) const noexcept
231 		{
232 			return m_row[row + 1] - m_row[row];
233 		}
234 
tx()235 		size_type tx() const { return m_v.size(); }
236 	private:
237 
238 		size_type m_N;
239 		size_type m_M;
240 		std::vector<size_type, typename A::template allocator_type<size_type>> m_row;
241 		std::vector<T, allocator_type> m_v;
242 	};
243 
244 
245 } // namespace plib
246 
247 #endif // PMATRIX2D_H_
248