Skip to content

Instantly share code, notes, and snippets.

@malcom
Created September 9, 2009 20:23
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save malcom/184050 to your computer and use it in GitHub Desktop.
/*
* 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