C++矩阵库(2)

前言

之前介绍了一些常见的C++矩阵库,这些矩阵库用起来都很方便,但是在本人的科研过程中并不会用到这些矩阵库的高级功能(如LU分解、求逆矩阵等),只是需要其作为容器存放数据,而且需要一些定制功能(比如元素查找、求积分微分等),因此我写了一个简单的、只包含头文件的矩阵库。

安装

由于是只包含头文件的,所以很容易包含到其他项目中,安装方法如下:

1
2
git clone https://github.com/TING2938/Analysis.git
cp -r Analysis/gmxProject/Analysis/Core/include path/to/your/project

然后设置项目中包含include文件夹就可以用了。

简单应用

一个简单的Demo如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <itp/core>

int main(int argc, char** argv)
{
mati A(3, 4);

for (size_t i = 0; i != A.nrow(); ++i)
{
for (size_t j = 0; j != A.ncol(); ++j)
{
A(i, j) = 3*i+5*j;
// 也可以用方括号进行索引
// A[i][j] = 3*i+5*j;
}
}

A.print("A:");
}

会得到如下输出:

1
2
3
4
A:
0 5 10 15
3 8 13 18
6 11 16 21

其中,mati类型等为一些常用的类型,using mati = itp::Matrix<int>,其他类型如matdmatumatb分别对应模板参数为doublesize_tbool的版本。

API介绍

构造函数

1
2
3
4
5
6
7
8
9
10
11
Matrix();
Matrix(size_t nrow, size_t ncol); // 指定行列大小,初始值未定义
Matrix(size_t nrow, size_t ncol, T init); // 指定初始值为 init
Matrix(size_t nrow, size_t ncol, conststd::initializer_list<T>& it); //指定行列大小,并由初始化列表初始化,如 mati A(2, 3, {2, 3, 4, 5, 5, 6});
Matrix(const std::initializer_list<conststd::initializer_list<T>>& it); // 由初始化列表初始化,如 mati B = {{5, 6, 8}, {7, 10, 13}}; 初始化为2行3列的矩阵
Matrix(T* p, size_t nrow, size_t ncol, bool copy= true); // 由指针初始化,默认拷贝指针指向的资源,copy=false时不拷贝资源,此时p的生命周期一定要大于矩阵的生命周期
Matrix(Matrix<T>&& mat) noexcept; // 移动构造
Matrix(const Matrix<T>& mat); // 拷贝构造
~Matrix(); // 析构函数
Matrix<T>& operator=(Matrix<T>&& mat) noexcept; // 移动赋值运算符
Matrix<T>& operator=(const Matrix<T>& mat); // 拷贝赋值运算符

索引

1
2
3
4
5
6
7
8
9
T* operator[](size_t i) noexcept;
const T* operator[](size_t i) const noexcept;
Vector<T> operator[](const Matrix<bool>& bol) const;
T& operator()(size_t i, size_t j) noexcept;
const T& operator()(size_t i, size_t j) const noexcept;
// row major
T& operator()(size_t i) noexcept;
const T& operator()(size_t i) const noexcept;
Vector<T> operator()(const Matrix<bool>& bol) const;

采用row major内存布局,索引若只含一维,则将矩阵视为一维向量进行索引,如A[4] = 3;
注意,可以采用()[]两种方法进行索引,如A(1, 2) = 5; B[4][3] = 6,两种方法效果一样

重载运算符

注意:矩阵所有运算都是将矩阵视为向量后的运算,并不涉及真正的矩阵运算。

例如,mati A(3, 4), B(3, 4)

操作 说明
A + 3 A所有元素加3
A + B AB对应元素相加
A > 2 A中元素分别与2比较,返回与A形状相同的bool型矩阵
A > B A中元素分别与B中元素比较,返回与A(或B)形状相同的bool型矩阵
!A A中元素分别求非运算,返回与A形状相同的bool型矩阵
A && B AB中对应元素求与运算,返回与A(或B)形状相同的bool型矩阵
A &#124;&#124; B AB中对应元素求或运算,返回与A(或B)形状相同的bool型矩阵

矩阵与数:

1
2
3
4
5
6
7
8
9
Matrix<T>& operator+=(const T& val);
Matrix<T>& operator-=(const T& val);
Matrix<T>& operator*=(const T& val);
Matrix<T>& operator/=(const T& val);

Matrix<T> operator+(const T& val) const;
Matrix<T> operator-(const T& val) const;
Matrix<T> operator*(const T& val) const;
Matrix<T> operator/(const T& val) const;

矩阵与矩阵:

1
2
3
4
5
6
7
8
9
Matrix<T>& operator+=(const Matrix<T>& mat);
Matrix<T>& operator-=(const Matrix<T>& mat);
Matrix<T>& operator*=(const Matrix<T>& mat);
Matrix<T>& operator/=(const Matrix<T>& mat);

Matrix<T> operator+(const Matrix<T>& mat) const;
Matrix<T> operator-(const Matrix<T>& mat) const;
Matrix<T> operator*(const Matrix<T>& mat) const;
Matrix<T> operator/(const Matrix<T>& mat) const;

矩阵与数之间的比较:

1
2
3
4
5
6
Matrix<bool> operator==(const T& value) const;
Matrix<bool> operator!=(const T& value) const;
Matrix<bool> operator>(const T& value) const;
Matrix<bool> operator<(const T& value) const;
Matrix<bool> operator>=(const T& value) const;
Matrix<bool> operator<=(const T& value) const;

矩阵与矩阵之间的比较:

1
2
3
4
5
6
Matrix<bool> operator==(const Matrix<T>& mat) const;
Matrix<bool> operator!=(const Matrix<T>& mat) const;
Matrix<bool> operator>(const Matrix<T>& mat) const;
Matrix<bool> operator<(const Matrix<T>& mat) const;
Matrix<bool> operator>=(const Matrix<T>& mat) const;
Matrix<bool> operator<=(const Matrix<T>& mat) const;

逻辑运算符:

1
2
3
4
5
6
7
Matrix<bool> operator!() const;

template <typename S>
Matrix<bool> operator&&(const Matrix<S>& mat) const;

template <typename S>
Matrix<bool> operator||(const Matrix<S>& mat) const;

矩阵切片操作

例如,mati A(3, 4)

操作 说明
A.part(2, {1, 3}) 第2行、第1到3列
A.part({0, 2}, 1) 第0到2行、第1列
A.part({0, 2}, {1, 3}) 第0到2行、第1到3列
A.head(2) 前2行
A.tail(2) 后2行
1
2
3
4
5
6
Matrix<T> part(const Rg& row, const Rg& col) const;
Vector<T> part(size_t row, const Rg& rg, boolcopy = false) const;
Vector<T> part(const Rg& rg, size_t col) const;

Matrix<T> head(size_t row = 10) const;
Matrix<T> tail(size_t row = 10) const;

其他操作

例如,mati A(3, 4), B(4, 5);

操作 说明
A.nrow() 行数
A.ncol() 列数
A.size() 存入std::array的行列数
A.size(0) 行数
A.size(1) 列数
A.capacity() 内部指针的容量
A.fill(3) 用3填充整个矩阵
A.resize(4, 5) 重置大小为4行5列
A.clear() 使矩阵的行列数都为0
A.fillRandom(std::uniform_int_distribution<int>(1, 6)) 用从1到6之间的均匀分布随机数填充,随机数用法参考标准库中随机数部分
A.dot(B) AB的矩阵点乘
A.transpose() 转置
A.max(COL) 列方向上的最大值,返回向量
A.min(COL) 列方向上的最小值,返回向量
A.sum(COL) 列方向上的和,返回向量
A.mean(COL) 列方向上的平均值,返回向量
A.stdev(COL) 列方向上的标准差,返回向量
A.max(2, COL) 第2列上的最大值
A.print("A:", std::cout, "{:12}") std::cout中打印输出A,提示符为A:,格式为"{:12}"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
size_t nrow() const;
size_t ncol() const;
std::array<size_t, 2> size() const;
size_t size(size_t i) const; /* i < 2. */
const size_t& capacity() const;
size_t& capacity();
Matrix<T>& fill(const T& value);
Matrix<T>& resize(size_t nrow, size_t ncol);
void clear();

/* https://en.cppreference.com/w/cpp/header/random */
template <typename Distribution>
Matrix<T>& fillRandom(Distribution&& dist);

Matrix<T> dot(const Matrix<T>& mat) const;
Matrix<T> transpose() const;

/* calculate value of block */
Vector<T> max(Axis axis = COL) const;
Vector<T> min(Axis axis = COL) const;
Vector<T> sum(Axis axis = COL) const;
Vector<double> mean(Axis axis = COL) const;
Vector<double> stdev(Axis axis = COL, bool sample = true) const;

/* calculate value of row or column */
T max(size_t n, Axis axis = COL) const;
T min(size_t n, Axis axis = COL) const;
T sum(size_t n, Axis axis = COL) const;
double mean(size_t n, Axis axis = COL) const;
double stdev(size_t n, Axis axis = COL, bool sample = true) const;

void print(std::string str = "", std::ostream& os = std::cout, std::string fmt="{:12}") const;

C++矩阵库(2)
https://ting2938.github.io/程序设计/C++/C-矩阵库(2)/
作者
TING2938
发布于
2020年5月22日
许可协议