c++实现矩阵运算的加减法乘法以及测试用例
Posted Hero_HL
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c++实现矩阵运算的加减法乘法以及测试用例相关的知识,希望对你有一定的参考价值。
1.引言
最近在看图像AI相关的知识,在此记录一个自己思考的代码用例。
关于矩阵的应用在AI中应用还是很广泛,尤其是深度学习的特征值这块中。
这里先简单记录上自己简单的基础矩阵算法的类,后续学习中会不断丰富这个类。
参考opencv3.4.0源码中libjasper模块中的jas_seq.c本例中增加了加减乘运算,
缩减和扩充了一些自己的理解
2.矩阵基本运算
我就是典型的:上课不听讲,考试混及格。书到用时方恨少!!
看到的同学们一定要好好的认真的学习大学知识,我现在才觉得大学学习的知识真的太有用了。
当然忘记了或者没学过的可以像我一样参考以下的视频进行学习
bilibili考研课程《线性代数》 https://www.bilibili.com/video/BV1aW411Q7x1?p=9
2.1 矩阵加减法
主要记住以下几个点:
1.同型矩阵指的是两个矩阵的行数和列数相等。
2.两矩阵对应元素相加减(前提必须是同型矩阵)
3.矩阵相乘满足:中间相等取两头
3.代码实现
对于矩阵的赋值都采用了调用类创建矩阵时赋值或不赋值(默认参数)处理,
和接口设置所有元素为一个数,具体见如下代码。
matrix.h 矩阵类的定义
/*******************************
* file: matrix.h
* author: hehl
* time: 2021/7/9
*******************************/
#pragma once
#include <iostream>
#include <vector>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
using namespace std;
typedef int INT;
// 基本的二维矩阵结构体
typedef struct matix_s
{
INT s_nRowsNums; // 矩阵的行数
INT s_nColsNums; // 矩阵的列数
INT** s_pRows; // 指向矩阵每行开头的指针的指针(保存s_pData中每行的指针数组)
INT s_nRowsSize; // 行数组分配大小
INT* s_pData; // 矩阵的数据
INT s_nDataSize; // 数据数组分配大小
matix_s()
{
s_nRowsNums = 0;
s_nColsNums = 0;
s_pRows = nullptr;
s_nRowsSize = 0;
s_pData = nullptr;
s_nDataSize = 0;
}
} matrix_t;
class Matrix
{
public:
// 单例
static Matrix* GetInstance();
// 创建矩阵,返回创建成功后矩阵的指针,失败返回nullptr 可以直接输入对应参数进行创建.仅仅用于测试
matrix_t* matrix_create(INT nRows, INT nCols, bool bSet = false, ...);
// 释放矩阵,释放内存
void matrix_destroy(matrix_t* pMatrix_t);
// 将矩阵的所有元素设置为指定值
void matrix_setall(matrix_t* pMatrix_t, INT nValue);
// 打印矩阵中的值
void matrix_printf(matrix_t* pMatrix_t);
// 两个矩阵相加
bool two_matrix_add(matrix_t* pMatSrcA, matrix_t* pMatSrcB, matrix_t* pMatDes);
// 两个矩阵相减
bool two_matrix_subtrac(matrix_t* pMatSrcA, matrix_t* pMatSrcB, matrix_t* pMatDes);
// 两个矩阵相乘
bool two_matrix_multiply(matrix_t* pMatSrcA, matrix_t* pMatSrcB, matrix_t* pMatDes);
// 当前有多少未释放内存的矩阵
INT get_matix_objects_nums(void);
// 释放当前所有未释放矩阵的内存
void destory_all_matrix_objects(void);
private:
// 构造函数,用于初始化
Matrix();
// 析构函数,用于释放内存
~Matrix();
// 获取矩阵行数
INT matrix_getrows(matrix_t* pMatrix_t);
// 获取矩阵列数
INT matrix_getcols(matrix_t* pMatrix_t);
// 获取矩阵数据大小
INT matrix_get_data_size(matrix_t* pMatrix_t);
private:
vector<matrix_t*> m_vpMatrix_t;
static Matrix* m_pInstance;
};
matrix.cpp 具体实现矩阵类
/*******************************
* file: matrix.cpp
* author: hehl
* time: 2021/7/9
*******************************/
#include "matrix.h"
Matrix* Matrix::m_pInstance = new Matrix();
Matrix* Matrix::GetInstance()
{
if (m_pInstance == nullptr)
{
m_pInstance = new Matrix();
}
return m_pInstance;
}
Matrix::Matrix()
{
}
Matrix::~Matrix()
{
destory_all_matrix_objects();
delete m_pInstance;
m_pInstance = nullptr;
}
matrix_t* Matrix::matrix_create(INT nRows, INT nCols, bool bSet, ...)
{
matrix_t* matrix = new matrix_t;
if (nullptr == matrix)
{
return nullptr;
}
matrix->s_nRowsNums = nRows;
matrix->s_nColsNums = nCols;
matrix->s_nRowsSize = nRows;
matrix->s_nDataSize = nRows * nCols;
if (matrix->s_nRowsSize > 0 && matrix->s_nColsNums > 0)
{
matrix->s_pRows = new INT * [matrix->s_nRowsSize];
if (nullptr == matrix->s_pRows)
{
matrix_destroy(matrix);
return nullptr;
}
}
if (matrix->s_nDataSize > 0)
{
matrix->s_pData = new INT[matrix->s_nDataSize];
if (nullptr == matrix->s_pData)
{
matrix_destroy(matrix);
return nullptr;
}
if (bSet)
{
va_list ap;
va_start(ap, bSet);
for (INT i = 0; i < matrix->s_nDataSize; i++)
{
matrix->s_pData[i] = va_arg(ap, INT);
}
va_end(ap);
}
else
{
memset(matrix->s_pData, 0, matrix->s_nDataSize * sizeof(INT));
}
}
for (INT i = 0; i < nRows; i++)
{
matrix->s_pRows[i] = &matrix->s_pData[i * matrix->s_nColsNums];
}
m_vpMatrix_t.push_back(matrix);
return matrix;
}
void Matrix::matrix_destroy(matrix_t* pMatrix_t)
{
if (pMatrix_t)
{
for (auto it = m_vpMatrix_t.begin(); it != m_vpMatrix_t.end(); it++)
{
if (*it == pMatrix_t)
{
m_vpMatrix_t.erase(it);
break;
}
}
if (pMatrix_t->s_pRows)
{
delete[]pMatrix_t->s_pRows;
pMatrix_t->s_pRows = nullptr;
}
if (pMatrix_t->s_pData)
{
delete[]pMatrix_t->s_pData;
pMatrix_t->s_pData = nullptr;
}
delete pMatrix_t;
pMatrix_t = nullptr;
}
}
void Matrix::matrix_setall(matrix_t* pMatrix_t, INT nValue)
{
if (nullptr == pMatrix_t)
{
cout << "matrix_setall:matrix is nullptr" << endl;
return;
}
for (INT nRows = 0; nRows < matrix_getrows(pMatrix_t); nRows++)
{
for (INT nCols = 0; nCols < matrix_getcols(pMatrix_t); nCols++)
{
pMatrix_t->s_pRows[nRows][nCols] = nValue;
}
}
return;
}
void Matrix::matrix_printf(matrix_t* pMatrix_t)
{
if (nullptr == pMatrix_t)
{
cout << "matrix_printf:matrix is nullptr" << endl;
return;
}
for (INT nRows = 0; nRows < matrix_getrows(pMatrix_t); nRows++)
{
for (INT nCols = 0; nCols < matrix_getcols(pMatrix_t); nCols++)
{
printf("%-5d", pMatrix_t->s_pRows[nRows][nCols]);
}
cout << endl;
}
return;
}
INT Matrix::matrix_getrows(matrix_t* pMatrix_t)
{
if (nullptr == pMatrix_t)
{
return 0;
}
return pMatrix_t->s_nRowsNums;
}
INT Matrix::matrix_getcols(matrix_t* pMatrix_t)
{
if (nullptr == pMatrix_t)
{
return 0;
}
return pMatrix_t->s_nColsNums;
}
INT Matrix::matrix_get_data_size(matrix_t* pMatrix_t)
{
if (nullptr == pMatrix_t)
{
return 0;
}
return pMatrix_t->s_nDataSize;
}
bool Matrix::two_matrix_add(matrix_t* pMatSrcA, matrix_t* pMatSrcB, matrix_t* pMatDes)
{
if (nullptr == pMatSrcA || nullptr == pMatSrcB || nullptr == pMatDes)
{
return false;
}
if (!(pMatSrcA->s_nColsNums == pMatSrcB->s_nColsNums && pMatSrcA->s_nColsNums == pMatDes->s_nColsNums))
{
return false;
}
if (!(pMatSrcA->s_nRowsNums == pMatSrcB->s_nRowsNums && pMatSrcA->s_nRowsNums == pMatDes->s_nRowsNums))
{
return false;
}
for (INT nRows = 0; nRows < matrix_getrows(pMatDes); nRows++)
{
for (INT nCols = 0; nCols < matrix_getcols(pMatDes); nCols++)
{
pMatDes->s_pRows[nRows][nCols] = pMatSrcA->s_pRows[nRows][nCols] + pMatSrcB->s_pRows[nRows][nCols];
}
}
return true;
}
bool Matrix::two_matrix_subtrac(matrix_t* pMatSrcA, matrix_t* pMatSrcB, matrix_t* pMatDes)
{
if (nullptr == pMatSrcA || nullptr == pMatSrcB || nullptr == pMatDes)
{
return false;
}
if (!(pMatSrcA->s_nColsNums == pMatSrcB->s_nColsNums && pMatSrcA->s_nColsNums == pMatDes->s_nColsNums))
{
return false;
}
if (!(pMatSrcA->s_nRowsNums == pMatSrcB->s_nRowsNums && pMatSrcA->s_nRowsNums == pMatDes->s_nRowsNums))
{
return false;
}
for (INT nRows = 0; nRows < matrix_getrows(pMatDes); nRows++)
{
for (INT nCols = 0; nCols < matrix_getcols(pMatDes); nCols++)
{
pMatDes->s_pRows[nRows][nCols] = pMatSrcA->s_pRows[nRows][nCols] - pMatSrcB->s_pRows[nRows][nCols];
}
}
return true;
}
bool Matrix::two_matrix_multiply(matrix_t* pMatSrcA, matrix_t* pMatSrcB, matrix_t* pMatDes)
{
if (nullptr == pMatSrcA || nullptr == pMatSrcB || nullptr == pMatDes)
{
return false;
}
if (pMatSrcA->s_nColsNums != pMatSrcB->s_nRowsNums || pMatSrcA->s_nRowsNums != pMatDes->s_nRowsNums || pMatSrcB->s_nColsNums != pMatDes->s_nColsNums)
{
return false;
}
for (INT nRows = 0; nRows < matrix_getrows(pMatSrcA); nRows++)
{
for (INT nCols = 0; nCols < matrix_getcols(pMatSrcB); nCols++)
{
pMatDes->s_pRows[nRows][nCols] = 0;
for (INT des = 0; des < matrix_getcols(pMatSrcA)/* or matrix_getrows(pMatSrcB) */; des++)
{
pMatDes->s_pRows[nRows][nCols] += pMatSrcA->s_pRows[nRows][des] * pMatSrcB->s_pRows[des][nCols];
}
}
}
return true;
}
INT Matrix::get_matix_objects_nums(void)
{
return m_vpMatrix_t.size();
}
void Matrix::destory_all_matrix_objects(void)
{
for (int i = 0; i < m_vpMatrix_t.size(); i++)
{
matrix_destroy(m_vpMatrix_t[i]);
}
}
main.cpp 测试矩阵类的demo
/*******************************
* file: main.cpp
* author: hehl
* time: 2021/7/9
*******************************/
#include "matrix.h"
int main()
{
// 测试加减
Matrix* matrixObj = Matrix::GetInstance();
matrix_t* pMatrixA = matrixObj->matrix_create(2, 4);
matrixObj->matrix_setall(pMatrixA, 2);
cout << "matrixA:" << endl;
matrixObj->matrix_printf(pMatrixA);
matrix_t* pMatrixB = matrixObj->matrix_create(2, 4);
matrixObj->matrix_setall(pMatrixB, 3);
cout << "matrixB:" << endl;
matrixObj->matrix_printf(pMatrixB);
matrix_t* pMatrixC = matrixObj->matrix_create(2, 4);
matrixObj->matrix_setall(pMatrixC, -5);
cout << "matrixC:" << endl;
matrixObj->matrix_printf(pMatrixC);
if (matrixObj->two_matrix_add(pMatrixA, pMatrixB, pMatrixC))
{
cout << "matrixA + matrixB =:" << endl;
matrixObj->matrix_printf(pMatrixC);
}
if (matrixObj->two_matrix_subtrac(pMatrixA, pMatrixB, pMatrixC))
{
cout << "matrixA - matrixB =:" << endl;
matrixObj->matrix_printf(pMatrixC);
}
cout << endl << endl;
// 测试乘法
matrix_t* p1 = matrixObj->matrix_create(2, 3, true, 1, 2, 3, 4, 5, 6);
cout << "matrix1:" << endl;
matrixObj->matrix_printf(p1);
matrix_t* p2 = matrixObj->matrix_create(3, 3, true, 1, 2, 3, 4, 5, 6, 7, 8, 9);
cout << "matrix2:" << endl;
matrixObj->matrix_printf(p2);
matrix_t* p3 = matrixObj->matrix_create(2, 3);
matrixObj->two_matrix_multiply(p1, p2, p3);
cout << "matrix1 * matrix2:" << endl;
matrixObj->matrix_printf(p3);
matrixObj->destory_all_matrix_objects();
system("pause");
return 0;
}
4.测试结果
C++使用cuBLAS加速矩阵乘法运算