Matrix transposition: Difference between revisions
Content added Content deleted
(Modify from C++ to cpp) |
(Add C++ generic solution) |
||
Line 324: | Line 324: | ||
[3,3]((0,3,6),(1,4,7),(2,5,8)) |
[3,3]((0,3,6),(1,4,7),(2,5,8)) |
||
===Generic solution=== |
|||
main.cpp |
|||
<lang 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() */</lang> |
|||
matrix.h |
|||
<lang cpp>#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 */</lang> |
|||
Output: |
|||
<pre>Before transposition: |
|||
rows = 2 columns = 3 |
|||
1 2 3 |
|||
4 5 6 |
|||
After transposition: |
|||
rows = 3 columns = 2 |
|||
1 4 |
|||
2 5 |
|||
3 6</pre> |
|||
=={{header|Clojure}}== |
=={{header|Clojure}}== |