实用矩阵类(Matrix)(带测试)
引言:
无意间看到国外一个网站写的Matrix类,实现了加减乘除基本运算以及各自的const版本等等,功能还算比较完善,,于是记录下来,以备后用:
#ifndef MATRIX_H
#define MATRIX_H #include <iostream>
#include <functional>
#include <algorithm> using namespace std; template <size_t Rows,size_t Cols,typename ElemType = double>
class Matrix
{
public:
Matrix(); //默认构造函数
template<typename InputIterator>
Matrix(InputIterator begin, InputIterator end); //用2迭代器构造
~Matrix(); //析构函数 ElemType & at(size_t row, size_t col); //获取某个元素(引用)
const ElemType & at(size_t row, size_t col) const; size_t numRows() const; //获得行数、列数
size_t numCols() const;
size_t size() const; //返回总元素数 //多维矩阵
class MutableReference;
class ImmutableReference;
MutableReference operator[] (size_t row);
ImmutableReference operator[] (size_t row) const; typedef ElemType* iterator; //将元素类型指针定义为迭代器
typedef const ElemType* const_iterator; iterator begin();
iterator end();
const_iterator begin() const;
const_iterator end() const; iterator row_begin(size_t row);
iterator row_end(size_t row);
const_iterator row_begin(size_t row) const;
const_iterator row_end(size_t row) const; Matrix& operator+= (const Matrix& rhs);
Matrix& operator-= (const Matrix& rhs);
Matrix& operator*= (const ElemType& scalar);
Matrix& operator/= (const ElemType& scalar); //打印矩阵
void printMatrix(void) const;
private:
ElemType elems[Rows*Cols]; //矩阵元素的数组 };
//两矩阵相加
template <size_t M,size_t N,typename T>
const Matrix<M, N, T> operator+ (const Matrix<M, N, T> &lhs, const Matrix<M, N, T> &rhs);
//两矩阵相减
template <size_t M, size_t N, typename T>
const Matrix<M, N, T> operator- (const Matrix<M, N, T> &lhs, const Matrix<M, N, T> &rhs);
//矩阵数乘(右乘)
template <size_t M, size_t N, typename T>
const Matrix<M, N, T> operator* (const Matrix<M, N, T> &lhs, const T& scalar);
//矩阵数乘(左乘)
template <size_t M, size_t N, typename T>
const Matrix<M, N, T> operator* (const T& scalar, const Matrix<M, N, T> &rhs);
//矩阵除以一个数
template <size_t M, size_t N, typename T>
const Matrix<M, N, T> operator/ (const Matrix<M, N, T>& lhs,const T& scalar);
//一元运算的加减 相当于添加符号
template <size_t M, size_t N, typename T>
const Matrix<M, N, T> operator+ (const Matrix<M, N, T>& operand);
template <size_t M, size_t N, typename T>
const Matrix<M, N, T> operator- (const Matrix<M, N, T>& operand);
//2矩阵相乘
template <size_t M, size_t N, size_t P, typename T>
const Matrix<M, P, T> operator*(const Matrix<M, N, T>& lhs,const Matrix<N, P, T>& rhs);
//矩阵的比较操作
template <size_t M, size_t N, typename T>
bool operator== (const Matrix<M, N, T>& lhs,const Matrix<M, N, T>& rhs); template <size_t M, size_t N, typename T>
bool operator!= (const Matrix<M, N, T>& lhs,const Matrix<M, N, T>& rhs); template <size_t M, size_t N, typename T>
bool operator< (const Matrix<M, N, T>& lhs,const Matrix<M, N, T>& rhs); template <size_t M, size_t N, typename T>
bool operator<= (const Matrix<M, N, T>& lhs,const Matrix<M, N, T>& rhs); template <size_t M, size_t N, typename T>
bool operator>= (const Matrix<M, N, T>& lhs,const Matrix<M, N, T>& rhs); template <size_t M, size_t N, typename T>
bool operator> (const Matrix<M, N, T>& lhs,const Matrix<M, N, T>& rhs);
//是否为单位矩阵
template <size_t M, typename T>
Matrix<M, M, T> Identity();
//矩阵转置
template <size_t M, size_t N, typename T>
const Matrix<N, M, T> Transpose(const Matrix<M, N, T>& m); //////////////////////////////////////////////////////////////////////////
/************************************************************************/
/*
函数的实现部分
*/
/************************************************************************/
//默认构造函数
template <size_t M, size_t N, typename T>
Matrix<M, N, T>::Matrix()
{
}
//迭代器构造函数
template <size_t M, size_t N, typename T>
template <typename InputIterator>
Matrix<M, N, T>::Matrix(InputIterator rangeBegin, InputIterator rangeEnd)
{
std::copy(rangeBegin, rangeEnd, begin());
}
//析构函数
template <size_t M, size_t N, typename T>
Matrix<M, N, T>::~Matrix()
{
}
//得到row,col处元素(引用) 常量版本
template <size_t M, size_t N, typename T>
const T& Matrix<M, N, T>::at(size_t row, size_t col) const
{
return *(begin() + row * numCols() + col);
}
//得到row,col处元素(引用) 非常量版本
template <size_t M, size_t N, typename T>
T& Matrix<M, N, T>::at(size_t row, size_t col)
{
return const_cast<T&>(static_cast<const Matrix<M, N, T>*>(this)->at(row, col));
}
//得到行数
template<size_t M,size_t N,typename T>
size_t Matrix<M, N, T>::numRows() const
{
return M;
}
template<size_t M,size_t N,typename T>
size_t Matrix<M, N, T>::numCols() const
{
return N;
} template<size_t M,size_t N,typename T>
size_t Matrix<M,N,T>::size() const
{
return M*N;
}
//迭代器返回首地址指针 //注意返回是迭代器类型
template<size_t M,size_t N,typename T>
typename Matrix<M, N, T>::iterator Matrix<M,N,T>::begin()
{
return elems;
}
//迭代器返回首地址指针的常量版本
template<size_t M, size_t N, typename T>
typename Matrix<M, N, T>::const_iterator Matrix<M, N, T>::begin() const
{
return elems;
}
//尾迭代器获取
template<size_t M, size_t N, typename T>
typename Matrix<M, N, T>::iterator Matrix<M, N, T>::end()
{
return begin()+size();
}
//尾迭代器获取(常量版本)
template<size_t M, size_t N, typename T>
typename Matrix<M, N, T>::const_iterator Matrix<M, N, T>::end() const
{
return begin() + size();
}
//行迭代器(跳过指定元素获取)
template<size_t M,size_t N,typename T>
typename Matrix<M, N, T>::iterator Matrix<M, N, T>::row_begin(size_t row)
{
return begin() + row*numCols();
}
//行迭代器(跳过指定元素获取) 常量版本
template <size_t M, size_t N, typename T>
typename Matrix<M, N, T>::const_iterator Matrix<M, N, T>::row_begin(size_t row) const
{
return begin() + row*numCols();
}
//获得行尾迭代器
template<size_t M,size_t N,typename T>
typename Matrix<M, N, T>::iterator Matrix<M, N, T>::row_end(size_t row)
{
return row_begin(row) + N;
}
//获得行尾迭代器 const版本
template<size_t M, size_t N, typename T>
typename Matrix<M, N, T>::const_iterator Matrix<M, N, T>::row_end(size_t row) const
{
return row_begin(row) + N;
}
/************************************************************************/
/*
方括号[]操作返回引用的实现(非const版本)
*/
/************************************************************************/
template <size_t M,size_t N,typename T>
class Matrix<M, N, T>::MutableReference
{
public:
T& operator[] (size_t col)
{
return parent->at(row, col);
}
private:
//私有构造函数 是获得此类实例的为例方法(有元类Matrix可以访问)
MutableReference(Matrix* owner, size_t row) :parent(owner), row(row)
{ }
friend class Matrix;
const size_t row;
Matrix *const parent;
};
/************************************************************************/
/*
方括号[]操作返回引用的实现(const版本)
*/
/************************************************************************/
template <size_t M, size_t N, typename T>
class Matrix<M, N, T>::ImmutableReference
{
public:
const T& operator[] (size_t col) const
{
return parent->at(row, col);
}
private:
//私有构造函数 是获得此类实例的为例方法(有元类Matrix可以访问)
ImmutableReference(const Matrix* owner, size_t row) :parent(owner), row(row)
{ }
friend class Matrix;
const size_t row;
const Matrix *const parent;
};
//方括号返回引用的真真实现(用了上面的类)
template<size_t M,size_t N,typename T>
typename Matrix<M, N, T>::MutableReference Matrix<M, N, T>::operator [] (size_t row)
{
return MutableReference(this, row);
}
template<size_t M, size_t N, typename T>
typename Matrix<M, N, T>::ImmutableReference Matrix<M, N, T>::operator [] (size_t row) const
{
return ImmutableReference(this, row);
}
/************************************************************************/
/*
复合运算符实现
*/
/************************************************************************/
template <size_t M, size_t N, typename T>
Matrix<M, N, T>& Matrix<M, N, T>::operator+= (const Matrix<M, N, T>& rhs)
{
std::transform(begin(), end(), // First input range is lhs
rhs.begin(), // Start of second input range is rhs
begin(), // Overwrite lhs
std::plus<T>()); // Using addition
return *this;
} template <size_t M, size_t N, typename T>
Matrix<M, N, T>& Matrix<M, N, T>::operator-= (const Matrix<M, N, T>& rhs)
{
std::transform(begin(), end(), // First input range is lhs
rhs.begin(), // Start of second input range is rhs
begin(), // Overwrite lhs
std::minus<T>()); // Using subtraction
return *this;
}
template <size_t M, size_t N, typename T>
Matrix<M, N, T>& Matrix<M, N, T>::operator*= (const T& scalar)
{
std::transform(begin(), end(), // Input range is lhs
begin(), // Output overwrites lhs
std::bind2nd(std::multiplies<T>(), scalar)); // Scalar mult.
return *this;
}
template <size_t M, size_t N, typename T>
Matrix<M, N, T>& Matrix<M, N, T>::operator/= (const T& scalar)
{
std::transform(begin(), end(), // Input range is lhs
begin(), // Output overwrites lhs
std::bind2nd(std::divides<T>(), scalar)); // Divide by scalar
return *this;
}
/************************************************************************/
/*
双目运算符实现
*/
/************************************************************************/
template <size_t M, size_t N, typename T>
const Matrix<M, N, T> operator+ (const Matrix<M, N, T>& lhs,const Matrix<M, N, T>& rhs)
{
return Matrix<M, N, T>(lhs) += rhs; //用到了复合运算符(成员函数)
}
template <size_t M, size_t N, typename T>
const Matrix<M, N, T> operator- (const Matrix<M, N, T>& lhs,const Matrix<M, N, T>& rhs)
{
return Matrix<M, N, T>(lhs) -= rhs;
}
template <size_t M, size_t N, typename T> //(右乘一个数)
const Matrix<M, N, T> operator* (const Matrix<M, N, T>& lhs,const T& scalar)
{
return Matrix<M, N, T>(lhs) *= scalar;
}
template <size_t M, size_t N, typename T> //左乘一个数
const Matrix<M, N, T> operator* (const T& scalar,const Matrix<M, N, T>& rhs)
{
return Matrix<M, N, T>(rhs) *= scalar;
}
template <size_t M, size_t N, typename T>
const Matrix<M, N, T> operator/ (const Matrix<M, N, T>& lhs,const T& scalar)
{
return Matrix<M, N, T>(lhs) /= scalar;
}
//一元运算符+
template <size_t M, size_t N, typename T>
const Matrix<M, N, T> operator+ (const Matrix<M, N, T>& operand) {
return operand;
}
//一元运算符-
template <size_t M, size_t N, typename T>
const Matrix<M, N, T> operator- (const Matrix<M, N, T>& operand)
{
return Matrix<M, N, T>(operand) *= T(-);
}
//2矩阵相乘
template <size_t M, size_t N, size_t P, typename T>
const Matrix<M, P, T> operator*(const Matrix<M, N, T>& one,const Matrix<N, P, T>& two)
{
/* Create a result matrix of the right size and initialize it to zero. */
Matrix<M, P, T> result;
std::fill(result.begin(), result.end(), T()); //初始化结果变量 /* Now go fill it in. */
for (size_t row = ; row < result.numRows(); ++row)
for (size_t col = ; col < result.numCols(); ++col)
for (size_t i = ; i < N; ++i)
result[row][col] += one[row][i] * two[i][col]; return result;
}
//matrix1*=matrix运算实现
template <size_t M, typename T>
Matrix<M, M, T>& operator*= (Matrix<M, M, T>& lhs,const Matrix<M, M, T>& rhs)
{
return lhs = lhs * rhs; // Nothing fancy here.
}
//比较运算符实现
template <size_t M, size_t N, typename T>
bool operator== (const Matrix<M, N, T>& lhs,const Matrix<M, N, T>& rhs)
{
return std::equal(lhs.begin(), lhs.end(), rhs.begin());
}
template <size_t M, size_t N, typename T>
bool operator!= (const Matrix<M, N, T>& lhs,const Matrix<M, N, T>& rhs)
{
return !(lhs == rhs); //用了==运算符
}
/* The less-than operator uses the std::mismatch algorithm to chase down
* the first element that differs in the two matrices, then returns whether
* the lhs element is less than the rhs element. This is essentially a
* lexicographical comparison optimized on the assumption that the two
* sequences have the same size.
*/
//小于运算符
template <size_t M, size_t N, typename T>
bool operator< (const Matrix<M, N, T>& lhs,const Matrix<M, N, T>& rhs)
{
/* Compute the mismatch. */
std::pair<typename Matrix<M, N, T>::const_iterator,
typename Matrix<M, N, T>::const_iterator> disagreement =
std::mismatch(lhs.begin(), lhs.end(), rhs.begin()); /* lhs < rhs only if there is a mismatch and the lhs's element is
* lower than the rhs's element.
*/
return disagreement.first != lhs.end() &&
*disagreement.first < *disagreement.second;
} /* The remaining relational operators are implemented in terms of <. */
template <size_t M, size_t N, typename T>
bool operator<= (const Matrix<M, N, T>& lhs, const Matrix<M, N, T>& rhs)
{
/* x <= y iff !(x > y) iff !(y < x) */
return !(rhs < lhs);
}
template <size_t M, size_t N, typename T>
bool operator>= (const Matrix<M, N, T>& lhs, const Matrix<M, N, T>& rhs)
{
/* x >= y iff !(y > x) iff !(x < y) */
return !(lhs < rhs);
}
template <size_t M, size_t N, typename T>
bool operator>(const Matrix<M, N, T>& lhs, const Matrix<M, N, T>& rhs)
{
/* x > y iff y < x */
return !(rhs < lhs);
} /* Transposition is reasonably straightforward. */ //转置
template <size_t M, size_t N, typename T>
const Matrix<N, M, T> Transpose(const Matrix<M, N, T>& m)
{
Matrix<N, M, T> result;
for (size_t row = ; row < m.numRows(); ++row)
for (size_t col = ; col < m.numCols(); ++col)
result[col][row] = m[row][col];
return result;
} /* Identity matrix just fills in the diagonal. */
template <size_t M, typename T> Matrix<M, M, T> Identity()
{
Matrix<M, M, T> result;
for (size_t row = ; row < result.numRows(); ++row)
for (size_t col = ; col < result.numCols(); ++col)
result[row][col] = (row == col ? T() : T());
return result;
}
template <size_t M,size_t N,typename T>
void Matrix<M, N, T>::printMatrix(void) const
{
for (size_t i = ; i < this->numRows();++i)
{
for (size_t j = ; j < this->numCols();++j)
{
cout << this->at(i, j)<<" ";
}
cout << endl;
}
} #endif
测试代码:
原站上并没有测试代码,为了验证类的正确性,自己写了一个简单的测试代码,仅供参考:
#include <iostream>
#include <vector>
#include "matrix.h" using namespace std; void testMatrixClass(); int main()
{
testMatrixClass(); return ;
}
void testMatrixClass()
{
vector<int> vec1,vec2;
for (int i = ; i < ;++i)
{
vec1.push_back(i);
}
for (int i = ; i < ; ++i)
{
vec2.push_back(i+);
}
vector<int>::iterator itBegin = vec1.begin();
vector<int>::iterator itEnd = vec1.end(); Matrix<, , int>m_matrix1(itBegin,itEnd ); //用迭代器构造矩阵对象
Matrix<, , int>m_matrix2(vec2.begin(),vec2.end());
cout << "---------Matrix 1 = :-----------------" << endl;
m_matrix1.printMatrix();
cout << "---------Matrix 2 = :-----------------" << endl;
m_matrix2.printMatrix();
cout << "-----matrix1(1,1) (从0开始)= " << m_matrix1.at(, ) << endl;
cout << "---matrix1's size = " << m_matrix1.size() << " rows = " << m_matrix1.numRows()
<< " cols = " << m_matrix1.numCols() << endl;
cout << "----matrix1 *3 = " << endl;
(m_matrix1 *= ).printMatrix();
cout << "----matrix1 * matrix 2 = " << endl;
Matrix<, , int> result;
result = m_matrix1*m_matrix2;
result.printMatrix(); }
实用矩阵类(Matrix)(带测试)的更多相关文章
- [Java]编写自己的Matrix矩阵类
用java实现一个简单的矩阵类,可以实现简单的矩阵计算功能. class Matrix 1.向量点乘 public static double dot(double[] x,double[] y) 2 ...
- 实用的随机数生成类Random:测试(随机产生100个不重复的正整数)
实用的随机数生成类Random:测试(使用Random类随机生成100个不重复的正整数) 一.之前我们使用随机数用的是Math类的random()方法: tips: 产生随机数(0~9中任意整数)的方 ...
- OpenGL矩阵类(C++)
概述 创建&初始化 存取器 矩阵运算 变换函数 实例:模型视图矩阵 实例:投影矩阵 概述 OpenGL固定功能管线提供4个不同类型的矩阵(GL_MODELVIEW.GL_PROJECTION. ...
- Java日期时间实用工具类
Java日期时间实用工具类 1.Date (java.util.Date) Date(); 以当前时间构造一个Date对象 Date(long); 构造函数 ...
- OpenGL矩阵类(C++) 【转】
http://www.cnblogs.com/hefee/p/3816727.html OpenGL矩阵类(C++) 概述 创建&初始化 存取器 矩阵运算 变换函数 实例:模型视图矩阵 实例: ...
- C++实现矩阵类和向量类
C++期末作业内容,写完之后觉得过于臃肿,又重新搞了个新的.新的当作业交,旧的拿来给同学参考. [问题描述]请仿照复数类,设计一个矩阵类,设计矩阵类的构成元素 1.编写构造函数完成初始化 2.编写成员 ...
- R语言编程艺术# 矩阵(matrix)和数组(array)
矩阵(matrix)是一种特殊的向量,包含两个附加的属性:行数和列数.所以矩阵也是和向量一样,有模式(数据类型)的概念.(但反过来,向量却不能看作是只有一列或一行的矩阵. 数组(array)是R里更一 ...
- 精解Mat类(一):基本数据类型-固定大小的 矩阵类(Matx) 向量类(Vector)
一.基础数据类型 1.(基础)固定大小矩阵类 matx 说明: ① 基础矩阵是我个人增加的描述,相对于Mat矩阵类(存储图像信息的大矩阵)而言. ② 固定大小矩阵类必须在编译期间就知晓其维 ...
- Spring统一返回Json工具类,带分页信息
前言: 项目做前后端分离时,我们会经常提供Json数据给前端,如果有一个统一的Json格式返回工具类,那么将大大提高开发效率和减低沟通成本. 此Json响应工具类,支持带分页信息,支持泛型,支持Htt ...
随机推荐
- 也谈如何获取真实正确的 Windows 系统版本号
关于 GetVersion 系列接口 关于如何获取 Windows 系统版本号的话题,网上已经有了太多的帖子.但个人觉得总结的都不尽全面,或者没有给出比较稳定的解决方案. 众所周知,获取 Window ...
- jquery datatable数据初始化
一个datatable的初始化问题,困扰了在下整整半天,最后在网上各位大神的帮助下,终于解决了. 首先分析一下我所遇到的问题: 在HTML上有个下拉框,我需要获取下拉框的值来从后台数据库中获取不同的数 ...
- SQL查询某库所有的表所有的字段及字段的属性
then d.name else null end) 表名, a.colorder 字段序号, a.name 字段名, ( then '√'else '' end) 标识, ( then '√' el ...
- 对Unity一个Shader编译Bug的分析(Unrecognized sampler 'samplerunity_lightmap)
写在前面 Unity的用户量越来越大,越来越有钱,这几年摊子也铺的越来越大,所以各个版本总是有很多Bug.对于一些Bug官方在ReleaseNote里的说明是很不详细的,而对于一些渲染相关的Bug,有 ...
- DLC 基本定律与规则
字母数字码 :除了数字以外,数字系统还需要处理数字以外的符号,如标点符号,控制命令等 最常见的是ASCII ASCII码是7位二进制码有128种组合,表示128个符号例如 二进制表示 十六进制表示 十 ...
- Redis单机版分布式锁实现
转载自:https://www.cnblogs.com/linjiqin/p/8003838.html Redis分布式锁的正确实现方式 前言 分布式锁一般有三种实现方式:1. 数据库乐观锁:2. 基 ...
- void类型及void指针(转载)
转载 https://www.cnblogs.com/pengyingh/articles/2407267.html 2.void的含义 void的字面意思是“无类型”,void *则为“无类型指针” ...
- yml使用
yml: value: 可以用单引号或者双引号引起来,这样就不会出现内容中特殊字符含义. yml中 key:value ,如果value是数字需要和前面的冒号隔一个空格,否则获取不到value
- MM-科目自动分配
SAP系统篇 MM自动记账解析之基本概念(01) https://blog.csdn.net/qq_33641781/article/details/78027802 MM自动记账解析之功能实现(02 ...
- lnmp环境部署脚本-y
系统环境:centos6.X #!/bin/bash#date:2018-01-01## MySQL 安装8版本的话不太适合,有待于添加安装脚本进行测试#新版的MySQL安装需要高版本2.8以上cma ...