Transpose an arbitrarily sized rectangular Matrix.
Library: Boost.uBLAS
#include <boost/numeric/ublas/matrix.hpp> #include <boost/numeric/ublas/io.hpp> int main() { using namespace boost::numeric::ublas; matrix<double> m(3,3); for(int i=0; i!=m.size1(); ++i) for(int j=0; j!=m.size2(); ++j) m(i,j)=3*i+j; std::cout << trans(m) << std::endl; }
- Output:
[3,3]((0,3,6),(1,4,7),(2,5,8))
Generic solution
- main.cpp
#include <iostream> #include "matrix.h" #if !defined(ARRAY_SIZE) #define ARRAY_SIZE(x) (sizeof((x)) / sizeof((x)[0])) #endif template<class T> void printMatrix(const Matrix<T>& m) { std::cout << "rows = " << m.rowNum() << " columns = " << m.colNum() << std::endl; for (unsigned int i = 0; i < m.rowNum(); i++) { for (unsigned int j = 0; j < m.colNum(); j++) { std::cout << m[i][j] << " "; } std::cout << std::endl; } } /* printMatrix() */ int main() { int am[2][3] = { {1,2,3}, {4,5,6}, }; Matrix<int> a(ARRAY_SIZE(am), ARRAY_SIZE(am[0]), am[0], ARRAY_SIZE(am)*ARRAY_SIZE(am[0])); try { std::cout << "Before transposition:" << std::endl; printMatrix(a); std::cout << std::endl; a.transpose(); std::cout << "After transposition:" << std::endl; printMatrix(a); } catch (MatrixException& e) { std::cerr << e.message() << std::endl; return e.errorCode(); } } /* main() */
matrix.h
#ifndef _MATRIX_H #define _MATRIX_H #include <sstream> #include <string> #include <vector> #include <algorithm> #define MATRIX_ERROR_CODE_COUNT 5 #define MATRIX_ERR_UNDEFINED "1 Undefined exception!" #define MATRIX_ERR_WRONG_ROW_INDEX "2 The row index is out of range." #define MATRIX_ERR_MUL_ROW_AND_COL_NOT_EQUAL "3 The row number of second matrix must be equal with the column number of first matrix!" #define MATRIX_ERR_MUL_ROW_AND_COL_BE_GREATER_THAN_ZERO "4 The number of rows and columns must be greater than zero!" #define MATRIX_ERR_TOO_FEW_DATA "5 Too few data in matrix." class MatrixException { private: std::string message_; int errorCode_; public: MatrixException(std::string message = MATRIX_ERR_UNDEFINED); inline std::string message() { return message_; }; inline int errorCode() { return errorCode_; }; }; MatrixException::MatrixException(std::string message) { errorCode_ = MATRIX_ERROR_CODE_COUNT + 1; std::stringstream ss(message); ss >> errorCode_; if (errorCode_ < 1) { errorCode_ = MATRIX_ERROR_CODE_COUNT + 1; } std::string::size_type pos = message.find(' '); if (errorCode_ <= MATRIX_ERROR_CODE_COUNT && pos != std::string::npos) { message_ = message.substr(pos + 1); } else { message_ = message + " (This an unknown and unsupported exception!)"; } } /** * Generic class for matrices. */ template <class T> class Matrix { private: std::vector<T> v; // the data of matrix unsigned int m; // the number of rows unsigned int n; // the number of columns protected: virtual void clear() { v.clear(); m = n = 0; } public: Matrix() { clear(); } Matrix(unsigned int, unsigned int, T* = 0, unsigned int = 0); Matrix(unsigned int, unsigned int, const std::vector<T>&); virtual ~Matrix() { clear(); } Matrix& operator=(const Matrix&); std::vector<T> operator[](unsigned int) const; Matrix operator*(const Matrix&); void transpose(); inline unsigned int rowNum() const { return m; } inline unsigned int colNum() const { return n; } inline unsigned int size() const { return v.size(); } inline void add(const T& t) { v.push_back(t); } }; template <class T> Matrix<T>::Matrix(unsigned int row, unsigned int col, T* data, unsigned int dataLength) { clear(); if (row > 0 && col > 0) { m = row; n = col; unsigned int mxn = m * n; if (dataLength && data) { for (unsigned int i = 0; i < dataLength && i < mxn; i++) { v.push_back(data[i]); } } } } template <class T> Matrix<T>::Matrix(unsigned int row, unsigned int col, const std::vector<T>& data) { clear(); if (row > 0 && col > 0) { m = row; n = col; unsigned int mxn = m * n; if (data.size() > 0) { for (unsigned int i = 0; i < mxn && i < data.size(); i++) { v.push_back(data[i]); } } } } template<class T> Matrix<T>& Matrix<T>::operator=(const Matrix<T>& other) { clear(); if (other.m > 0 && other.n > 0) { m = other.m; n = other.n; unsigned int mxn = m * n; for (unsigned int i = 0; i < mxn && i < other.size(); i++) { v.push_back(other.v[i]); } } return *this; } template<class T> std::vector<T> Matrix<T>::operator[](unsigned int index) const { std::vector<T> result; if (index >= m) { throw MatrixException(MATRIX_ERR_WRONG_ROW_INDEX); } else if ((index + 1) * n > size()) { throw MatrixException(MATRIX_ERR_TOO_FEW_DATA); } else { unsigned int begin = index * n; unsigned int end = begin + n; for (unsigned int i = begin; i < end; i++) { result.push_back(v[i]); } } return result; } template<class T> Matrix<T> Matrix<T>::operator*(const Matrix<T>& other) { Matrix result(m, other.n); if (n != other.m) { throw MatrixException(MATRIX_ERR_MUL_ROW_AND_COL_NOT_EQUAL); } else if (m <= 0 || n <= 0 || other.n <= 0) { throw MatrixException(MATRIX_ERR_MUL_ROW_AND_COL_BE_GREATER_THAN_ZERO); } else if (m * n > size() || other.m * other.n > other.size()) { throw MatrixException(MATRIX_ERR_TOO_FEW_DATA); } else { for (unsigned int i = 0; i < m; i++) { for (unsigned int j = 0; j < other.n; j++) { T temp = v[i * n] * other.v[j]; for (unsigned int k = 1; k < n; k++) { temp += v[i * n + k] * other.v[k * other.n + j]; } result.v.push_back(temp); } } } return result; } template<class T> void Matrix<T>::transpose() { if (m * n > size()) { throw MatrixException(MATRIX_ERR_TOO_FEW_DATA); } else { std::vector<T> v2; std::swap(v, v2); for (unsigned int i = 0; i < n; i++) { for (unsigned int j = 0; j < m; j++) { v.push_back(v2[j * n + i]); } } std::swap(m, n); } } #endif /* _MATRIX_H */
- Output:
Before transposition: rows = 2 columns = 3 1 2 3 4 5 6 After transposition: rows = 3 columns = 2 1 4 2 5 3 6
Easy Mode
#include <iostream> int main(){ const int l = 5; const int w = 3; int m1[l][w] = {{1,2,3}, {4,5,6}, {7,8,9}, {10,11,12}, {13,14,15}}; int m2[w][l]; for(int i=0; i<w; i++){ for(int x=0; x<l; x++){ m2[i][x]=m1[x][i]; } } // This is just output... std::cout << "Before:"; for(int i=0; i<l; i++){ std::cout << std::endl; for(int x=0; x<w; x++){ std::cout << m1[i][x] << " "; } } std::cout << "\n\nAfter:"; for(int i=0; i<w; i++){ std::cout << std::endl; for(int x=0; x<l; x++){ std::cout << m2[i][x] << " "; } } std::cout << std::endl; return 0; }
- Output:
Before: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 After: 1 4 7 10 13 2 5 8 11 14 3 6 9 12 15
Content is available under GNU Free Documentation License 1.2.