/* * Copyright (c) 2008 * Evan Teran * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, provided * that the above copyright notice appears in all copies and that both the * copyright notice and this permission notice appear in supporting * documentation, and that the same name not be used in advertising or * publicity pertaining to distribution of the software without specific, * written prior permission. We make no representations about the * suitability this software for any purpose. It is provided "as is" * without express or implied warranty. */ #ifndef MATRIX_20051222_H_ #define MATRIX_20051222_H_ //#define CHECKED_INDEXING #include // for std::size_t #include // for std::min #ifdef CHECKED_INDEXING #include // fot std::out_of_range #endif template class Matrix { public: typedef std::size_t size_type; class reference { // only the Matrix class can create a Matrix::reference friend class Matrix; reference(Matrix &owner, size_type x) : m_Owner(owner), m_X(x) {} public: #ifdef CHECKED_INDEXING T &operator[](size_type y) const { if(y>= m_Owner.m_Height) { throw std::out_of_range("y>= height"); } return m_Owner.m_Data[m_X + y * m_Owner.m_Width]; } T &operator[](size_type y) { if(y>= m_Owner.m_Height) { throw std::out_of_range("y>= height"); } return m_Owner.m_Data[m_X + y * m_Owner.m_Width]; } #else T &operator[](size_type y) const { return m_Owner.m_Data[m_X + y * m_Owner.m_Width]; } T &operator[](size_type y) { return m_Owner.m_Data[m_X + y * m_Owner.m_Width]; } #endif private: Matrix &m_Owner; size_type m_X; }; public: //------------------------------------------------------------------------------------ // Name: Matrix() //------------------------------------------------------------------------------------ Matrix() : m_Data(0), m_Width(0), m_Height(0) { } //------------------------------------------------------------------------------------ // Name: Matrix(const Matrix& m) //------------------------------------------------------------------------------------ Matrix(const Matrix& m) : m_Data(0), m_Width(0), m_Height(0) { // resize ourselves to match m resize(m.width(), m.height(), false); // if the new size is valid, copy all the elements if(m_Data != 0) { for(size_type y = 0; y < m_Height; ++y) { for(size_type x = 0; x < m_Width; ++x) { m_Data[x + y * m_Width] = m.m_Data[x + y * m_Width]; } } } } //------------------------------------------------------------------------------------ // Name: operator=(const Matrix& m) //------------------------------------------------------------------------------------ Matrix &operator=(const Matrix& m) { if(this != &m) { Matrix(m).swap(*this); } return *this; } //------------------------------------------------------------------------------------ // Name: Matrix(size_type width, size_type height) //------------------------------------------------------------------------------------ Matrix(size_type width, size_type height) : m_Data(0), m_Width(0), m_Height(0) { resize(width, height); } //------------------------------------------------------------------------------------ // Name: ~Matrix() //------------------------------------------------------------------------------------ ~Matrix() { delete [] m_Data; } //------------------------------------------------------------------------------------ // Name: operator[](size_type x) //------------------------------------------------------------------------------------ reference operator[](size_type x) { #ifdef CHECKED_INDEXING if(x>= m_Width) { throw std::out_of_range("x>= width"); } #endif return reference(*this, x); } //------------------------------------------------------------------------------------ // Name: reference operator[](size_type x) const //------------------------------------------------------------------------------------ const reference operator[](size_type x) const { #ifdef CHECKED_INDEXING if(x>= m_Width) { throw std::out_of_range("x>= width"); } #endif return reference(*this, x); } //------------------------------------------------------------------------------------ // Name: resize(size_type width, size_type height) //------------------------------------------------------------------------------------ void resize(size_type width, size_type height, bool preserve = true) { // if either the width or height is 0, we just make the whole thing empty if(width == 0 || height == 0) { Matrix().swap(*this); } else { // allocate the new matrix and initialize it T *const t = new T[width * height]; // if it is larger in either direction, copy old values into new matrix if(preserve && (m_Data != 0)) { for(size_type y = 0; y < std::min(height, m_Height); ++y) { for(size_type x = 0; x < std::min(width, m_Width); ++x) { t[x + y * width] = m_Data[x + y * width]; } } } // delete the old matrix delete [] m_Data; // make the new matrix the one we use m_Data = t; m_Width = width; m_Height = height; } } //------------------------------------------------------------------------------------ // Name: width() const //------------------------------------------------------------------------------------ size_type width() const { return m_Width; } //------------------------------------------------------------------------------------ // Name: height() const //------------------------------------------------------------------------------------ size_type height() const { return m_Height; } //------------------------------------------------------------------------------------ // Name: height() const //------------------------------------------------------------------------------------ void clear() { if(m_Data != 0) { for(size_type y = 0; y < m_Height; ++y) { for(size_type x = 0; x < m_Width; ++x) { m_Data[x][y] = T(); } } } } //------------------------------------------------------------------------------------ // Name: swap(Matrix &other) //------------------------------------------------------------------------------------ void swap(Matrix &other) { std::swap(m_Data, other.m_Data); std::swap(m_Width, other.m_Width); std::swap(m_Height, other.m_Height); } private: T *m_Data; size_type m_Width; size_type m_Height; }; #endif

AltStyle によって変換されたページ (->オリジナル) /