This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Matrix - simple two-dimensional dynamic array based of std::vector | |
* http://projects.malcom.pl/code/matrix.xhtml | |
* | |
* Copyright (C) 2009, 2010 Marcin 'Malcom' Malich <me@malcom.pl> | |
* | |
* Released under the MIT License. | |
* | |
* Permission is hereby granted, free of charge, to any person obtaining a copy | |
* of this software and associated documentation files (the "Software"), to deal | |
* in the Software without restriction, including without limitation the rights | |
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
* copies of the Software, and to permit persons to whom the Software is | |
* furnished to do so, subject to the following conditions: | |
* | |
* The above copyright notice and this permission notice shall be included in | |
* all copies or substantial portions of the Software. | |
* | |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
* THE SOFTWARE. | |
* | |
* 2009-03-10 20:41:52 | |
*/ | |
#ifndef _MATRIX_H_ | |
#define _MATRIX_H_ | |
#include <vector> | |
template <typename T> | |
class matrix : public std::vector<T> { | |
typedef std::vector<T> base; | |
public: | |
typedef typename base::value_type value_type; | |
typedef typename base::pointer pointer; | |
typedef typename base::const_pointer const_pointer; | |
typedef typename base::reference reference; | |
typedef typename base::const_reference const_reference; | |
typedef typename base::iterator iterator; | |
typedef typename base::const_iterator const_iterator; | |
typedef typename base::reverse_iterator reverse_iterator; | |
typedef typename base::const_reverse_iterator const_reverse_iterator; | |
typedef typename base::size_type size_type; | |
typedef typename base::difference_type difference_type; | |
typedef typename base::allocator_type allocator_type; | |
explicit matrix(const allocator_type& a = allocator_type()) | |
: base(a), | |
m_cols(1) {} | |
matrix(size_type rows, size_type cols, const value_type& value, const allocator_type& a = allocator_type()) | |
: base(rows * cols, value, a), | |
m_cols(cols) {} | |
explicit matrix(size_type rows, size_type cols) | |
: base(rows * cols), | |
m_cols(cols) {} | |
matrix(const matrix& m) | |
: base(m), | |
m_cols(m.m_cols) {} | |
template<typename InputIterator> | |
matrix(InputIterator first, InputIterator last, size_type cols = 1, const allocator_type& a = allocator_type()) | |
: base(first, last, a), | |
m_cols(cols) {} | |
~matrix() {} | |
matrix& operator=(const matrix& m) { | |
base::operator=(m); | |
m_cols = m.m_cols; | |
return *this; | |
} | |
void assign(size_type rows, size_type cols, const value_type& value) { | |
base::assign(rows * cols, value); | |
} | |
template<typename InputIterator> | |
void assign(InputIterator first, InputIterator last) { | |
base::assign(first, last); | |
} | |
// iterators | |
using base::begin; | |
using base::end; | |
using base::rbegin; | |
using base::rend; | |
iterator begin(size_type row) { | |
return base::begin() + row * size_cols(); | |
} | |
const_iterator begin(size_type row) const { | |
return base::begin() + row * size_cols(); | |
} | |
iterator end(size_type row) { | |
return base::begin() + (row + 1) * size_cols(); | |
} | |
const_iterator end(size_type row) const { | |
return base::begin() + (row + 1) * size_cols(); | |
} | |
reverse_iterator rbegin(size_type row) { | |
return base::rbegin() + row * size_cols(); | |
} | |
const_reverse_iterator rbegin(size_type row) const { | |
return base::rbegin() + row * size_cols(); | |
} | |
reverse_iterator rend(size_type row) { | |
return base::rbegin() + (row + 1) * size_cols(); | |
} | |
const_reverse_iterator rend(size_type row) const { | |
return base::rbegin() + (row + 1) * size_cols(); | |
} | |
iterator begin(iterator item) { | |
return item - index_col(item); | |
} | |
const_iterator begin(const_iterator item) const { | |
return item - index_col(item); | |
} | |
iterator end(iterator item) { | |
return item - index_col(item) + size_cols(); | |
} | |
const_iterator end(const_iterator item) const { | |
return item - index_col(item) + size_cols(); | |
} | |
// capacity | |
size_type size_rows() const { | |
size_type rows = size() / size_cols(); | |
if (size() % size_cols()) | |
rows++; | |
return rows; | |
} | |
size_type size_cols() const { | |
return m_cols; | |
} | |
void resize(size_type rows, size_type cols) { | |
base::resize(rows * cols); | |
m_cols = cols; | |
} | |
void resize(size_type rows, size_type cols, const value_type& value) { | |
base::resize(rows * cols, value); | |
m_cols = cols; | |
} | |
void reserve(size_type rows, size_type cols) { | |
base::reserve(rows * cols); | |
m_cols = cols; | |
} | |
// element access | |
// return pointer for access like matrix[row][col] ;) | |
pointer operator[](size_type row) { | |
return &base::operator[](row * size_cols()); | |
} | |
const_pointer operator[](size_type row) const { | |
return &base::operator[](row * size_cols()); | |
} | |
reference operator()(size_type row, size_type col) { | |
return base::operator[](row * size_cols() + col); | |
} | |
const_reference operator()(size_type row, size_type col) const { | |
return base::operator[](row * size_cols() + col); | |
} | |
using base::at; | |
reference at(size_type row, size_type col) { | |
return base::at(row * size_cols() + col); | |
} | |
const_reference at(size_type row, size_type col) const { | |
return base::at(row * size_cols() + col); | |
} | |
using base::front; | |
using base::back; | |
reference front(size_type row) { | |
return *begin(row); | |
} | |
const_reference front(size_type row) const { | |
return *begin(row); | |
} | |
reference back(size_type row) { | |
return *(end(row) - 1); | |
} | |
const_reference back(size_type row) const { | |
return *(end(row) - 1); | |
} | |
// modifiers | |
using base::insert; | |
template<typename InputIterator> | |
void insert(iterator position, InputIterator first, InputIterator last) { | |
base::insert(position, first, last); | |
} | |
void swap(matrix& m) { | |
base::swap(m); | |
m_cols = m.m_cols; | |
} | |
// usefull methods | |
// przechodzi do nastepnego wiersza, jesli konieczne | |
// (wypelnia domyslnymi wartosciami aktualny wiersz, jesli nie jest pelny) | |
void next_row() { | |
if (size_cols() > 1 && size() % size_cols()) { | |
size_type n = size_cols() - size() % size_cols(); | |
insert(end(), n, value_type()); | |
} | |
} | |
// przechodzi do poprzedniego wiersza, jesli konieczne | |
// (usuwa domyslne wartosci z konca vectora, ale tylko max 1 wiersz) | |
void prev_row() { | |
if (size_cols() > 1 && !(size() % size_cols()) && size() > 0) { | |
iterator e = end() - size_cols(); | |
iterator i = end() - 1; | |
while (i > e && *i == value_type()) | |
--i; | |
erase(i + 1, end()); | |
} | |
} | |
size_type index_col(size_type item) const { | |
return item % size_cols(); | |
} | |
size_type index_row(size_type item) const { | |
return item / size_cols(); | |
} | |
size_type index_col(iterator item) const { | |
return index_col(item - begin()); | |
} | |
size_type index_row(iterator item) const { | |
return index_row(item - begin()); | |
} | |
size_type index_col(const_iterator item) const { | |
return index_col(item - begin()); | |
} | |
size_type index_row(const_iterator item) const { | |
return index_row(item - begin()); | |
} | |
private: | |
size_type m_cols; | |
}; | |
#endif // _MATRIX_H_ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment