1187 lines
28 KiB
C++
1187 lines
28 KiB
C++
/********************************************************
|
||
* ██████╗ ██████╗████████╗██╗
|
||
* ██╔════╝ ██╔════╝╚══██╔══╝██║
|
||
* ██║ ███╗██║ ██║ ██║
|
||
* ██║ ██║██║ ██║ ██║
|
||
* ╚██████╔╝╚██████╗ ██║ ███████╗
|
||
* ╚═════╝ ╚═════╝ ╚═╝ ╚══════╝
|
||
* Geophysical Computational Tools & Library (GCTL)
|
||
*
|
||
* Copyright (c) 2023 Yi Zhang (yizhang-geo@zju.edu.cn)
|
||
*
|
||
* GCTL is distributed under a dual licensing scheme. You can redistribute
|
||
* it and/or modify it under the terms of the GNU Lesser General Public
|
||
* License as published by the Free Software Foundation, either version 2
|
||
* of the License, or (at your option) any later version. You should have
|
||
* received a copy of the GNU Lesser General Public License along with this
|
||
* program. If not, see <http://www.gnu.org/licenses/>.
|
||
*
|
||
* If the terms and conditions of the LGPL v.2. would prevent you from using
|
||
* the GCTL, please consider the option to obtain a commercial license for a
|
||
* fee. These licenses are offered by the GCTL's original author. As a rule,
|
||
* licenses are provided "as-is", unlimited in time for a one time fee. Please
|
||
* send corresponding requests to: yizhang-geo@zju.edu.cn. Please do not forget
|
||
* to include some description of your company and the realm of its activities.
|
||
* Also add information on how to contact you by electronic and paper mail.
|
||
******************************************************/
|
||
|
||
#ifndef _GCTL_MATRIX_H
|
||
#define _GCTL_MATRIX_H
|
||
|
||
#include <typeinfo>
|
||
#include "array.h"
|
||
|
||
namespace gctl
|
||
{
|
||
template <typename MatValType> class matrix;
|
||
|
||
/*
|
||
* Here we define some commonly used matrix types.
|
||
*/
|
||
typedef matrix<int> _2i_matrix; ///< 2-D integer matrix
|
||
typedef matrix<float> _2f_matrix; ///< 2-D single-precision floating-point matrix
|
||
typedef matrix<double> _2d_matrix; ///< 2-D double-precision floating-point matrix
|
||
typedef matrix<std::string> _2s_matrix; ///< 2-D string matrix
|
||
typedef matrix<std::complex<float> > _2cf_matrix; ///< 1-D complex float matrix
|
||
typedef matrix<std::complex<double> > _2cd_matrix; ///< 1-D complex double matrix
|
||
|
||
/**
|
||
* @brief 二维数组模版
|
||
*
|
||
* 二维数组模版是一个简单的二维动态数组实现,包含简单的数组操作与IO操作函数。
|
||
*
|
||
* @tparam MatValType 数组元素模版类型
|
||
*/
|
||
template <typename MatValType>
|
||
class matrix
|
||
{
|
||
protected:
|
||
MatValType **val; ///< 二维数组数据
|
||
size_t row_length, col_length; ///< 二维数组的行列数
|
||
|
||
public:
|
||
/**
|
||
* @brief 默认构造函数
|
||
*/
|
||
matrix();
|
||
|
||
/**
|
||
* @brief 构造函数:初始化二维数组空间
|
||
*
|
||
* @param[in] row_len 二维数组行数
|
||
* @param[in] col_len 二维数组列数
|
||
*/
|
||
matrix(size_t row_len, size_t col_len);
|
||
|
||
/**
|
||
* @brief 构造函数:初始化二维数组空间并赋处值
|
||
*
|
||
* @param[in] row_len 二维数组行数
|
||
* @param[in] col_len 二维数组列数
|
||
* @param[in] init_val 数组元素的初始值
|
||
*/
|
||
matrix(size_t row_len, size_t col_len, MatValType init_val);
|
||
|
||
/**
|
||
* @brief 构造函数:从一维数组初始化二维数组
|
||
*
|
||
* @param init_mat 输入的一维数组
|
||
* @param[in] row_len 二维数组行数
|
||
* @param[in] col_len 二维数组列数
|
||
*/
|
||
matrix(MatValType *init_mat, size_t row_len, size_t col_len);
|
||
|
||
/**
|
||
* @brief 构造函数:从二维数组初始化二维数组
|
||
*
|
||
* @param init_mat 输入的二维数组
|
||
* @param[in] row_len 二维数组行数
|
||
* @param[in] col_len 二维数组列数
|
||
*/
|
||
matrix(MatValType **init_mat, size_t row_len, size_t col_len);
|
||
|
||
/**
|
||
* @brief 构造函数:从一维向量初始化二维数组
|
||
*
|
||
* @param[in] b 输入向量的引用
|
||
* @param[in] row_len 二维数组行数
|
||
* @param[in] col_len 二维数组列数
|
||
*/
|
||
matrix(const std::vector<MatValType> &b, size_t row_len, size_t col_len);
|
||
|
||
/**
|
||
* @brief 构造函数:从二维向量初始化二维数组
|
||
*
|
||
* @param[in] b 输入向量的引用
|
||
*/
|
||
explicit matrix(const std::vector<std::vector<MatValType> > &b);
|
||
|
||
/**
|
||
* @brief 构造函数:从一维数组初始化二维数组
|
||
*
|
||
* @param[in] b 输入数组的引用
|
||
* @param[in] row_len 二维数组行数
|
||
* @param[in] col_len 二维数组列数
|
||
*/
|
||
matrix(const array<MatValType> &b, size_t row_len, size_t col_len);
|
||
|
||
/**
|
||
* @brief 拷贝构造函数
|
||
*
|
||
* @param[in] b 拷贝数组
|
||
*/
|
||
matrix(const matrix<MatValType> &b);
|
||
|
||
/**
|
||
* @brief 赋值操作符重载
|
||
*
|
||
* @param[in] b 赋值数组
|
||
*
|
||
* @return 新建数组
|
||
*/
|
||
matrix<MatValType>& operator= (const matrix<MatValType> &b);
|
||
|
||
/**
|
||
* @brief 析构函数
|
||
*/
|
||
virtual ~matrix();
|
||
|
||
/**
|
||
* @brief 初始化二维数组空间
|
||
*
|
||
* @param[in] row_len 二维数组行数
|
||
* @param[in] col_len 二维数组列数
|
||
*/
|
||
void resize(size_t row_len, size_t col_len);
|
||
|
||
/**
|
||
* @brief 构造函数:初始化二维数组空间并赋处值
|
||
*
|
||
* @param[in] row_len 二维数组行数
|
||
* @param[in] col_len 二维数组列数
|
||
* @param[in] init_val 数组元素的初始值
|
||
*/
|
||
void resize(size_t row_len, size_t col_len, MatValType init_val);
|
||
|
||
/**
|
||
* @brief 构造函数:从一维数组初始化二维数组
|
||
*
|
||
* @param init_mat 输入的一维数组
|
||
* @param[in] row_len 二维数组行数
|
||
* @param[in] col_len 二维数组列数
|
||
*/
|
||
void resize(MatValType *init_mat, size_t row_len, size_t col_len);
|
||
|
||
/**
|
||
* @brief 构造函数:从二维数组初始化二维数组
|
||
*
|
||
* @param init_mat 输入的二维数组
|
||
* @param[in] row_len 二维数组行数
|
||
* @param[in] col_len 二维数组列数
|
||
*/
|
||
void resize(MatValType **init_mat, size_t row_len, size_t col_len);
|
||
|
||
/**
|
||
* @brief 构造函数:从一维向量初始化二维数组
|
||
*
|
||
* @param[in] b 输入向量的引用
|
||
* @param[in] row_len 二维数组行数
|
||
* @param[in] col_len 二维数组列数
|
||
*/
|
||
void resize(const std::vector<MatValType> &b, size_t row_len, size_t col_len);
|
||
|
||
/**
|
||
* @brief 从二维向量初始化二维数组
|
||
*
|
||
* @param[in] b 输入向量的引用
|
||
*/
|
||
void resize(const std::vector<std::vector<MatValType> > &b);
|
||
|
||
/**
|
||
* @brief 构造函数:从一维数组初始化二维数组
|
||
*
|
||
* @param[in] b 输入数组的引用
|
||
* @param[in] row_len 二维数组行数
|
||
* @param[in] col_len 二维数组列数
|
||
*/
|
||
void resize(const array<MatValType> &b, size_t row_len, size_t col_len);
|
||
|
||
/**
|
||
* @brief 从二维数组初始化二维数组
|
||
*
|
||
* @param[in] b 输入数组
|
||
*/
|
||
void resize(const matrix<MatValType> &b);
|
||
|
||
/**
|
||
* @brief 清除并重置数组空间
|
||
*/
|
||
void clear();
|
||
|
||
/**
|
||
* @brief Initialize the array with selected random types.
|
||
*
|
||
* @param[in] np1 Mean (Gauss) or low bound value (Even)
|
||
* @param[in] np2 Standard deviation (Gauss) or hig bound value (Even).
|
||
* @param[in] mode Random types. 'RdNormal' for Gaussian distributed numbers and
|
||
* 'RdUniform' for even distributed numbers.
|
||
*/
|
||
void random_float(MatValType np1, MatValType np2, random_type_e mode = RdNormal, unsigned int seed = 0);
|
||
|
||
/**
|
||
* @brief Initialize the array with selected random types.
|
||
*
|
||
* @param[in] np1 Mean (Gauss) or low bound value (Even)
|
||
* @param[in] np2 Standard deviation (Gauss) or hig bound value (Even).
|
||
* @param[in] mode Random types. 'RdNormal' for Gaussian distributed numbers and
|
||
* 'RdUniform' for even distributed numbers.
|
||
*/
|
||
void random_int(MatValType np1, MatValType np2, unsigned int seed = 0);
|
||
|
||
/**
|
||
* @brief 对全体元素进行赋值
|
||
*
|
||
* @param[in] in_val 输入值
|
||
*/
|
||
void assign_all(MatValType in_val);
|
||
|
||
/**
|
||
* @brief 填充矩阵行
|
||
*
|
||
* @param r_id 行索引
|
||
* @param in_val 行数据
|
||
*/
|
||
void fill_row(size_t r_id, const array<MatValType> &in_arr);
|
||
|
||
/**
|
||
* @brief 填充矩阵列
|
||
*
|
||
* @param c_id 列索引
|
||
* @param in_val 列数据
|
||
*/
|
||
void fill_column(size_t c_id, const array<MatValType> &in_arr);
|
||
|
||
/**
|
||
* @brief 对全体元素进行缩放
|
||
*
|
||
* @param s 缩放的比例
|
||
*/
|
||
void scale(MatValType s);
|
||
|
||
/**
|
||
* @brief 按行或列计算元素平均值
|
||
*
|
||
* @param m 均值数组
|
||
* @param odr 计算行或列的平均值
|
||
*/
|
||
void mean(array<MatValType> &m, matrix_order_e odr = RowMajor);
|
||
|
||
/**
|
||
* @brief 按行或列归一化矩阵元素
|
||
*
|
||
* @param odr 计算行或列的平均值
|
||
*/
|
||
void normalize(matrix_order_e odr = RowMajor);
|
||
|
||
/**
|
||
* @brief 计算矩阵的模长
|
||
*
|
||
* @param n_type 模的类型
|
||
*/
|
||
double module(norm_type_e n_type = L2) const;
|
||
|
||
/**
|
||
* @brief Set elements' value as a sequent.
|
||
*
|
||
* @param st_val Start value.
|
||
* @param row_inc Row increasement.
|
||
* @param col_inc Column increasement.
|
||
*/
|
||
void sequence(MatValType st_val, MatValType row_inc, MatValType col_inc);
|
||
|
||
/**
|
||
* @brief 获取索引位置元素值
|
||
*
|
||
* @note 可用于指针情况
|
||
*
|
||
* @param[in] row_index 行索引值
|
||
* @param[in] col_index 列索引值
|
||
*
|
||
* @return 索引处元素
|
||
*/
|
||
MatValType &at(size_t row_index, size_t col_index);
|
||
|
||
/**
|
||
* @brief 获取索引位置元素值(常量重载)
|
||
*
|
||
* @note 可用于指针情况
|
||
*
|
||
* @param[in] row_index 行索引值
|
||
* @param[in] col_index 列索引值
|
||
*
|
||
* @return 索引处元素
|
||
*/
|
||
MatValType &at(size_t row_index, size_t col_index) const;
|
||
|
||
/**
|
||
* @brief 下标符号重载:获取索引位置元素值
|
||
*
|
||
* @note 不可用于指针情况,对于二维数组只需重载一次下标符号就行。
|
||
*
|
||
* @param[in] index 索引值
|
||
*
|
||
* @return 索引处元素
|
||
*/
|
||
MatValType *operator[](size_t index);
|
||
|
||
/**
|
||
* @brief 下标符号重载:获取索引位置元素值(常量重载)
|
||
*
|
||
* @note 不可用于指针情况,对于二维数组只需重载一次下标符号就行。
|
||
*
|
||
* @param[in] index 索引值
|
||
*
|
||
* @return 索引处元素
|
||
*/
|
||
MatValType *operator[](size_t index) const;
|
||
|
||
/**
|
||
* @brief 获取成员数组裸指针
|
||
*
|
||
* @param[in] row_index 行索引值 row_index = 0 时数组指针为全部矩阵数据的头指针
|
||
*
|
||
* @return 单个元素的指针
|
||
*/
|
||
MatValType *get(size_t row_index = 0) const;
|
||
|
||
/**
|
||
* @brief 判断数组是否为空
|
||
*
|
||
* @return 数组为空返回真,否则返回假
|
||
*/
|
||
bool empty() const;
|
||
|
||
/**
|
||
* @brief 返回矩阵行大小
|
||
*
|
||
* @return 矩阵行大小
|
||
*/
|
||
size_t row_size() const;
|
||
|
||
/**
|
||
* @brief 返回矩阵列大小
|
||
*
|
||
* @return 矩阵列大小
|
||
*/
|
||
size_t col_size() const;
|
||
|
||
/**
|
||
* @brief 返回矩阵数组大小
|
||
*
|
||
* @return 数组大小
|
||
*/
|
||
size_t val_size() const;
|
||
|
||
/**
|
||
* @brief 拷贝数组到新的二维数组
|
||
*
|
||
* @param b 拷贝对象数组
|
||
*/
|
||
void copy_to(matrix<MatValType> &b) const;
|
||
|
||
/**
|
||
* @brief 拷贝数组到二维向量
|
||
*
|
||
* @param b 拷贝对象向量
|
||
*/
|
||
void copy_to(std::vector<std::vector<MatValType> > &b) const;
|
||
|
||
/**
|
||
* @brief 提取二维数组的行或者列到输出数组
|
||
*
|
||
* @param b 输出一维数组
|
||
* @param[in] index 行或者列的索引值
|
||
* @param[in] order 按行或者列输出
|
||
*/
|
||
void extract(array<MatValType> &b, size_t index, matrix_order_e order = RowMajor) const;
|
||
|
||
/**
|
||
* @brief 将二维数组转换为一维数组
|
||
*
|
||
* @warning 此函数会重置输出的一维数组
|
||
*
|
||
* @param b 转换后数组
|
||
* @param[in] order 按行或者列优先排列输出
|
||
*/
|
||
void reform(array<MatValType> &b, matrix_order_e order = RowMajor) const;
|
||
|
||
/**
|
||
* @brief element operate function pointer
|
||
*
|
||
*/
|
||
typedef void (*foreach_m_ptr)(MatValType &ele_ptr, size_t r_id, size_t c_id);
|
||
|
||
/**
|
||
* @brief Operate on each and every element
|
||
*
|
||
* @param func operation function
|
||
*/
|
||
void for_each(foreach_m_ptr func);
|
||
|
||
/**
|
||
* @brief Display the elements.
|
||
*
|
||
*/
|
||
void show(std::ostream &os = std::cout, char sep = '\t') const;
|
||
};
|
||
|
||
template <typename MatValType>
|
||
matrix<MatValType>::matrix()
|
||
{
|
||
row_length = col_length = 0;
|
||
val = nullptr;
|
||
}
|
||
|
||
template <typename MatValType>
|
||
matrix<MatValType>::matrix(size_t row_len, size_t col_len)
|
||
{
|
||
row_length = col_length = 0;
|
||
val = nullptr;
|
||
resize(row_len, col_len);
|
||
}
|
||
|
||
template <typename MatValType>
|
||
matrix<MatValType>::matrix(size_t row_len, size_t col_len, MatValType init_val)
|
||
{
|
||
row_length = col_length = 0;
|
||
val = nullptr;
|
||
resize(row_len, col_len, init_val);
|
||
}
|
||
|
||
template <typename MatValType>
|
||
matrix<MatValType>::matrix(MatValType *init_mat, size_t row_len, size_t col_len)
|
||
{
|
||
row_length = col_length = 0;
|
||
val = nullptr;
|
||
resize(init_mat, row_len, col_len);
|
||
}
|
||
|
||
template <typename MatValType>
|
||
matrix<MatValType>::matrix(MatValType **init_mat, size_t row_len, size_t col_len)
|
||
{
|
||
row_length = col_length = 0;
|
||
val = nullptr;
|
||
resize(init_mat, row_len, col_len);
|
||
}
|
||
|
||
template <typename MatValType>
|
||
matrix<MatValType>::matrix(const std::vector<MatValType> &b, size_t row_len, size_t col_len)
|
||
{
|
||
row_length = col_length = 0;
|
||
val = nullptr;
|
||
resize(b, row_len, col_len);
|
||
}
|
||
|
||
template <typename MatValType>
|
||
matrix<MatValType>::matrix(const std::vector<std::vector<MatValType> > &b)
|
||
{
|
||
row_length = col_length = 0;
|
||
val = nullptr;
|
||
resize(b);
|
||
}
|
||
|
||
template <typename MatValType>
|
||
matrix<MatValType>::matrix(const array<MatValType> &b, size_t row_len, size_t col_len)
|
||
{
|
||
row_length = col_length = 0;
|
||
val = nullptr;
|
||
resize(b, row_len, col_len);
|
||
}
|
||
|
||
template <typename MatValType>
|
||
matrix<MatValType>::matrix(const matrix<MatValType> &b)
|
||
{
|
||
row_length = col_length = 0;
|
||
val = nullptr;
|
||
resize(b);
|
||
}
|
||
|
||
template <typename MatValType>
|
||
matrix<MatValType>& matrix<MatValType>::operator= (const matrix<MatValType> &b)
|
||
{
|
||
if (b.empty())
|
||
{
|
||
clear();
|
||
}
|
||
else
|
||
{
|
||
resize(b.row_size(), b.col_size());
|
||
for (size_t i = 0; i < row_length; i++)
|
||
{
|
||
for (size_t j = 0; j < col_length; j++)
|
||
{
|
||
val[i][j] = b[i][j];
|
||
}
|
||
}
|
||
}
|
||
return *this;
|
||
}
|
||
|
||
template <typename MatValType>
|
||
matrix<MatValType>::~matrix()
|
||
{
|
||
clear();
|
||
}
|
||
|
||
template <typename MatValType>
|
||
void matrix<MatValType>::resize(size_t row_len, size_t col_len)
|
||
{
|
||
if (row_len == 0 || col_len == 0)
|
||
{
|
||
throw std::invalid_argument("[gctl::matrix<T>::resize] Invalid matrix size.");
|
||
}
|
||
|
||
// nothing needs to be done
|
||
if (row_len == row_length && col_len == col_length)
|
||
{
|
||
return;
|
||
}
|
||
|
||
// re-indexing
|
||
if (row_len*col_len == row_length*col_length)
|
||
{
|
||
row_length = row_len;
|
||
col_length = col_len;
|
||
|
||
// construct new row-indexing
|
||
MatValType *t_ptr = val[0];
|
||
delete[] val;
|
||
val = new MatValType* [row_len];
|
||
val[0] = t_ptr;
|
||
|
||
for (size_t i = 1; i < row_len; i++)
|
||
{
|
||
val[i] = val[i-1] + col_len;
|
||
}
|
||
return;
|
||
}
|
||
|
||
// re-allocate
|
||
if (!empty()) clear();
|
||
|
||
row_length = row_len;
|
||
col_length = col_len;
|
||
|
||
val = new MatValType* [row_len];
|
||
val[0] = new MatValType [row_len*col_len];
|
||
|
||
for (size_t i = 1; i < row_len; i++)
|
||
{
|
||
val[i] = val[i-1] + col_len;
|
||
}
|
||
return;
|
||
}
|
||
|
||
template <typename MatValType>
|
||
void matrix<MatValType>::resize(size_t row_len, size_t col_len, MatValType init_val)
|
||
{
|
||
resize(row_len, col_len);
|
||
|
||
for (size_t i = 0; i < row_len; i++)
|
||
{
|
||
for (size_t j = 0; j < col_len; j++)
|
||
{
|
||
val[i][j] = init_val;
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
|
||
template <typename MatValType>
|
||
void matrix<MatValType>::resize(MatValType *init_mat, size_t row_len, size_t col_len)
|
||
{
|
||
if (init_mat == nullptr)
|
||
{
|
||
throw std::domain_error("[gctl::matrix<T>::resize] Invalid pointer.");
|
||
}
|
||
|
||
resize(row_len, col_len);
|
||
|
||
for (size_t i = 0; i < row_len; i++)
|
||
{
|
||
for (size_t j = 0; j < col_len; j++)
|
||
{
|
||
val[i][j] = init_mat[j + i*col_len];
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
|
||
template <typename MatValType>
|
||
void matrix<MatValType>::resize(MatValType **init_mat, size_t row_len, size_t col_len)
|
||
{
|
||
if (init_mat == nullptr)
|
||
{
|
||
throw std::domain_error("[gctl::matrix<T>::resize] Invalid pointer.");
|
||
}
|
||
|
||
resize(row_len, col_len);
|
||
|
||
for (size_t i = 0; i < row_len; i++)
|
||
{
|
||
for (size_t j = 0; j < col_len; j++)
|
||
{
|
||
val[i][j] = init_mat[i][j];
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
|
||
template <typename MatValType>
|
||
void matrix<MatValType>::resize(const std::vector<MatValType> &b, size_t row_len, size_t col_len)
|
||
{
|
||
if (!b.empty())
|
||
{
|
||
resize(row_len, col_len);
|
||
|
||
for (size_t i = 0; i < row_len; i++)
|
||
{
|
||
for (size_t j = 0; j < col_len; j++)
|
||
{
|
||
val[i][j] = b[j + i*col_len];
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
return;
|
||
}
|
||
|
||
template <typename MatValType>
|
||
void matrix<MatValType>::resize(const std::vector<std::vector<MatValType> > &b)
|
||
{
|
||
if (!b.empty())
|
||
{
|
||
size_t max_col = 0;
|
||
for (size_t i = 0; i < b.size(); i++)
|
||
{
|
||
max_col = std::max(max_col, b[i].size());
|
||
}
|
||
|
||
resize(b.size(), max_col, 0);
|
||
for (size_t i = 0; i < row_length; i++)
|
||
{
|
||
for (size_t j = 0; j < b[i].size(); j++)
|
||
{
|
||
val[i][j] = b[i][j];
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
return;
|
||
}
|
||
|
||
template <typename MatValType>
|
||
void matrix<MatValType>::resize(const array<MatValType> &b, size_t row_len, size_t col_len)
|
||
{
|
||
if (!b.empty())
|
||
{
|
||
if (b.size() != row_len*col_len)
|
||
{
|
||
throw std::runtime_error("[gctl::matrix<T>::resize] Invalid matrix parameters.");
|
||
}
|
||
|
||
resize(row_len, col_len);
|
||
|
||
for (size_t i = 0; i < row_len; i++)
|
||
{
|
||
for (size_t j = 0; j < col_len; j++)
|
||
{
|
||
val[i][j] = b[j + i*col_len];
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
return;
|
||
}
|
||
|
||
template <typename MatValType>
|
||
void matrix<MatValType>::resize(const matrix<MatValType> &b)
|
||
{
|
||
if (!b.empty())
|
||
{
|
||
resize(b.row_size(), b.col_size());
|
||
|
||
for (size_t i = 0; i < row_length; i++)
|
||
{
|
||
for (size_t j = 0; j < col_length; j++)
|
||
{
|
||
val[i][j] = b[i][j];
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
return;
|
||
}
|
||
|
||
template <typename MatValType>
|
||
void matrix<MatValType>::clear()
|
||
{
|
||
row_length = col_length = 0;
|
||
|
||
if (val != nullptr)
|
||
{
|
||
delete[] val[0];
|
||
delete[] val;
|
||
val = nullptr;
|
||
}
|
||
return;
|
||
}
|
||
|
||
template <typename MatValType>
|
||
void matrix<MatValType>::random_float(MatValType np1, MatValType np2, random_type_e mode, unsigned int seed)
|
||
{
|
||
static_assert(std::is_floating_point<MatValType>::value,
|
||
"gctl::matrix<T>::random_float(...) could only be used with a float point type.");
|
||
|
||
if (seed == 0) seed = std::chrono::system_clock::now().time_since_epoch().count();
|
||
std::default_random_engine generator(seed);
|
||
|
||
if (mode == RdNormal)
|
||
{
|
||
std::normal_distribution<MatValType> dist(np1, np2); // 添加高斯分布的随机值
|
||
|
||
for (size_t i = 0; i < row_length; i++)
|
||
{
|
||
for (size_t j = 0; j < col_length; j++)
|
||
{
|
||
val[i][j] = dist(generator);
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
|
||
std::uniform_real_distribution<MatValType> dist(np1, np2); // /添加均匀分布的随机值
|
||
|
||
for (size_t i = 0; i < row_length; i++)
|
||
{
|
||
for (size_t j = 0; j < col_length; j++)
|
||
{
|
||
val[i][j] = dist(generator);
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
|
||
template <typename MatValType>
|
||
void matrix<MatValType>::random_int(MatValType np1, MatValType np2, unsigned int seed)
|
||
{
|
||
static_assert(std::is_integral<MatValType>::value,
|
||
"gctl::matrix<T>::random_int(...) could only be used with an integral type.");
|
||
|
||
if (seed == 0) seed = std::chrono::system_clock::now().time_since_epoch().count();
|
||
std::default_random_engine generator(seed);
|
||
|
||
//添加均匀分布的随机值
|
||
std::uniform_int_distribution<MatValType> dist(np1, np2);
|
||
for (size_t i = 0; i < row_length; i++)
|
||
{
|
||
for (size_t j = 0; j < col_length; j++)
|
||
{
|
||
val[i][j] = dist(generator);
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
|
||
template <typename MatValType>
|
||
void matrix<MatValType>::assign_all(MatValType in_val)
|
||
{
|
||
for (size_t i = 0; i < row_length; i++)
|
||
{
|
||
for (size_t j = 0; j < col_length; j++)
|
||
{
|
||
val[i][j] = in_val;
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
|
||
template <typename MatValType>
|
||
void matrix<MatValType>::fill_row(size_t r_id, const array<MatValType> &in_arr)
|
||
{
|
||
if (r_id >= row_length) throw std::out_of_range("[gctl::matrix<T>::fill_row] Row index out of range.");
|
||
if (in_arr.size() != col_length) throw std::invalid_argument("[gctl::matrix<T>::fill_row] Invalid array length.");
|
||
|
||
for (size_t j = 0; j < col_length; j++)
|
||
{
|
||
val[r_id][j] = in_arr[j];
|
||
}
|
||
return;
|
||
}
|
||
|
||
template <typename MatValType>
|
||
void matrix<MatValType>::fill_column(size_t c_id, const array<MatValType> &in_arr)
|
||
{
|
||
if (c_id >= col_length) throw std::out_of_range("[gctl::matrix<T>::fill_column] Column index out of range.");
|
||
if (in_arr.size()!= row_length) throw std::invalid_argument("[gctl::matrix<T>::fill_column] Invalid array length.");
|
||
|
||
for (size_t i = 0; i < row_length; i++)
|
||
{
|
||
val[i][c_id] = in_arr[i];
|
||
}
|
||
return;
|
||
}
|
||
|
||
template <typename MatValType>
|
||
void matrix<MatValType>::scale(MatValType s)
|
||
{
|
||
for (size_t i = 0; i < row_length; i++)
|
||
{
|
||
for (size_t j = 0; j < col_length; j++)
|
||
{
|
||
val[i][j] *= s;
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
|
||
template <typename MatValType>
|
||
void matrix<MatValType>::mean(array<MatValType> &m, matrix_order_e odr)
|
||
{
|
||
if (odr == RowMajor)
|
||
{
|
||
m.resize(col_length);
|
||
for (size_t j = 0; j < col_length; j++)
|
||
{
|
||
m[j] = 0.0;
|
||
for (size_t i = 0; i < row_length; i++)
|
||
{
|
||
m[j] += val[i][j];
|
||
}
|
||
m[j] /= row_length;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
m.resize(row_length);
|
||
for (size_t i = 0; i < row_length; i++)
|
||
{
|
||
m[i] = 0.0;
|
||
for (size_t j = 0; j < col_length; j++)
|
||
{
|
||
m[i] += val[i][j];
|
||
}
|
||
m[i] /= col_length;
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
|
||
template <typename MatValType>
|
||
void matrix<MatValType>::normalize(matrix_order_e odr)
|
||
{
|
||
if (odr == RowMajor)
|
||
{
|
||
for (size_t i = 0; i < row_length; i++)
|
||
{
|
||
MatValType sum = 0.0;
|
||
for (size_t j = 0; j < col_length; j++)
|
||
{
|
||
sum += val[i][j]*val[i][j];
|
||
}
|
||
sum = sqrt(sum);
|
||
|
||
for (size_t j = 0; j < col_length; j++)
|
||
{
|
||
val[i][j] /= sum;
|
||
}
|
||
}
|
||
}
|
||
else // ColMajor
|
||
{
|
||
for (size_t j = 0; j < col_length; j++)
|
||
{
|
||
MatValType sum = 0.0;
|
||
for (size_t i = 0; i < row_length; i++)
|
||
{
|
||
sum += val[i][j]*val[i][j];
|
||
}
|
||
sum = sqrt(sum);
|
||
|
||
for (size_t i = 0; i < row_length; i++)
|
||
{
|
||
val[i][j] /= sum;
|
||
}
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
|
||
template <typename MatValType>
|
||
double matrix<MatValType>::module(norm_type_e n_type) const
|
||
{
|
||
MatValType nval = (MatValType) 0;
|
||
if (n_type == L0)
|
||
{
|
||
for (size_t i = 0; i < row_length; i++)
|
||
{
|
||
for (size_t j = 0; j < col_length; j++)
|
||
{
|
||
if (val[i][j] != (MatValType) 0)
|
||
{
|
||
nval += (MatValType) 1;
|
||
}
|
||
}
|
||
}
|
||
return nval;
|
||
}
|
||
|
||
if (n_type == L1)
|
||
{
|
||
for (size_t i = 0; i < row_length; i++)
|
||
{
|
||
for (size_t j = 0; j < col_length; j++)
|
||
{
|
||
nval += GCTL_FABS(val[i][j]);
|
||
}
|
||
}
|
||
return nval;
|
||
}
|
||
|
||
if (n_type == L2)
|
||
{
|
||
for (size_t i = 0; i < row_length; i++)
|
||
{
|
||
for (size_t j = 0; j < col_length; j++)
|
||
{
|
||
nval += val[i][j]*val[i][j];
|
||
}
|
||
}
|
||
return sqrt(nval);
|
||
}
|
||
|
||
nval = val[0][0];
|
||
for (size_t i = 0; i < row_length; i++)
|
||
{
|
||
for (size_t j = 0; j < col_length; j++)
|
||
{
|
||
nval = GCTL_MAX(nval, val[i][j]);
|
||
}
|
||
}
|
||
return sqrt(nval);
|
||
}
|
||
|
||
template <typename MatValType>
|
||
void matrix<MatValType>::sequence(MatValType st_val, MatValType row_inc, MatValType col_inc)
|
||
{
|
||
for (size_t i = 0; i < row_length; i++)
|
||
{
|
||
for (size_t j = 0; j < col_length; j++)
|
||
{
|
||
val[i][j] = st_val + i*row_inc + j*col_inc;
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
|
||
template <typename MatValType>
|
||
MatValType *matrix<MatValType>::get(size_t row_index) const
|
||
{
|
||
#ifdef GCTL_BOUND_CHECK
|
||
if (row_index >= row_length || col_index >= col_length)
|
||
throw std::out_of_range("[gctl::matrix<T>::get] Invalid index.");
|
||
#endif // GCTL_BOUND_CHECK
|
||
|
||
return val[row_index];
|
||
}
|
||
|
||
template <typename MatValType>
|
||
MatValType &matrix<MatValType>::at(size_t row_index, size_t col_index)
|
||
{
|
||
#ifdef GCTL_BOUND_CHECK
|
||
if (row_index >= row_length || col_index >= col_length)
|
||
throw std::out_of_range("[gctl::matrix<T>::at] Invalid index.");
|
||
#endif // GCTL_BOUND_CHECK
|
||
|
||
return val[row_index][col_index];
|
||
}
|
||
|
||
template <typename MatValType>
|
||
MatValType &matrix<MatValType>::at(size_t row_index, size_t col_index) const
|
||
{
|
||
#ifdef GCTL_BOUND_CHECK
|
||
if (row_index >= row_length || col_index >= col_length)
|
||
throw std::out_of_range("[gctl::matrix<T>::at] Invalid index.");
|
||
#endif // GCTL_BOUND_CHECK
|
||
|
||
return val[row_index][col_index];
|
||
}
|
||
|
||
template <typename MatValType>
|
||
MatValType *matrix<MatValType>::operator[](size_t index)
|
||
{
|
||
return val[index];
|
||
}
|
||
|
||
template <typename MatValType>
|
||
MatValType *matrix<MatValType>::operator[](size_t index) const
|
||
{
|
||
return val[index];
|
||
}
|
||
|
||
template <typename MatValType>
|
||
bool matrix<MatValType>::empty() const
|
||
{
|
||
if (row_length == 0 && col_length == 0) return true;
|
||
else return false;
|
||
}
|
||
|
||
template <typename MatValType>
|
||
size_t matrix<MatValType>::row_size() const
|
||
{
|
||
return row_length;
|
||
}
|
||
|
||
template <typename MatValType>
|
||
size_t matrix<MatValType>::col_size() const
|
||
{
|
||
return col_length;
|
||
}
|
||
|
||
template <typename MatValType>
|
||
size_t matrix<MatValType>::val_size() const
|
||
{
|
||
return row_length*col_length;
|
||
}
|
||
|
||
template <typename MatValType>
|
||
void matrix<MatValType>::copy_to(matrix<MatValType> &b) const
|
||
{
|
||
b.resize(row_length, col_length);
|
||
|
||
for (size_t i = 0; i < row_length; i++)
|
||
{
|
||
for (size_t j = 0; j < col_length; j++)
|
||
{
|
||
b[i][j] = val[i][j];
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
|
||
template <typename MatValType>
|
||
void matrix<MatValType>::copy_to(std::vector<std::vector<MatValType> > &b) const
|
||
{
|
||
if (!b.empty())
|
||
{
|
||
for (size_t i = 0; i < b.size(); i++)
|
||
{
|
||
b[i].clear();
|
||
}
|
||
b.clear();
|
||
}
|
||
|
||
b.resize(row_length);
|
||
for (size_t i = 0; i < row_length; i++)
|
||
{
|
||
b[i].resize(col_length);
|
||
}
|
||
|
||
for (size_t i = 0; i < row_length; i++)
|
||
{
|
||
for (size_t j = 0; j < col_length; j++)
|
||
{
|
||
b[i][j] = val[i][j];
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
|
||
template <typename MatValType>
|
||
void matrix<MatValType>::extract(array<MatValType> &b, size_t index, matrix_order_e order) const
|
||
{
|
||
if (order == RowMajor)
|
||
{
|
||
if (index >= row_length)
|
||
{
|
||
throw std::out_of_range("[gctl::matrix<T>::extract] Invalid index.");
|
||
}
|
||
|
||
b.resize(col_length);
|
||
for (size_t i = 0; i < col_length; i++)
|
||
{
|
||
b[i] = val[index][i];
|
||
}
|
||
return;
|
||
}
|
||
|
||
if (index >= col_length)
|
||
{
|
||
throw std::out_of_range("[gctl::matrix<T>::extract] Invalid index.");
|
||
}
|
||
|
||
b.resize(row_length);
|
||
for (size_t i = 0; i < row_length; i++)
|
||
{
|
||
b[i] = val[i][index];
|
||
}
|
||
return;
|
||
}
|
||
|
||
template <typename MatValType>
|
||
void matrix<MatValType>::reform(array<MatValType> &b, matrix_order_e order) const
|
||
{
|
||
b.resize(row_length*col_length);
|
||
|
||
if (order == RowMajor)
|
||
{
|
||
for (size_t i = 0; i < row_length; i++)
|
||
{
|
||
for (size_t j = 0; j < col_length; j++)
|
||
{
|
||
b[j+i*col_length] = val[i][j];
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
|
||
for (size_t j = 0; j < col_length; j++)
|
||
{
|
||
for (size_t i = 0; i < row_length; i++)
|
||
{
|
||
b[i+j*row_length] = val[i][j];
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
|
||
template <typename MatValType>
|
||
void matrix<MatValType>::for_each(foreach_m_ptr func)
|
||
{
|
||
for (size_t i = 0; i < row_length; i++)
|
||
{
|
||
for (size_t j = 0; j < col_length; j++)
|
||
{
|
||
func(val[i][j], i, j);
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
|
||
template <typename MatValType>
|
||
void matrix<MatValType>::show(std::ostream &os, char sep) const
|
||
{
|
||
for (size_t i = 0; i < row_length; i++)
|
||
{
|
||
os << val[i][0];
|
||
for (size_t j = 1; j < col_length; j++)
|
||
{
|
||
os << sep << val[i][j];
|
||
}
|
||
os << std::endl;
|
||
}
|
||
return;
|
||
}
|
||
};
|
||
|
||
#endif // _GCTL_MATRIX_H
|