# 前言

【注】代码都以单精度float的情况书写，主要流程要记住，使用mkl_malloc申请内存，使用mkl_free释放内存。n年没用过C++了，凑合看看吧。

# 向量-向量

## 加法

y=ax+by

y=a*x+b*y


#include<stdio.h>
#include<stdlib.h>
#include<mkl.h>
int main()
{
float *A, *B;//两个向量
int a=1, b=1;//标量
int n = 5;//向量大小
A = (float *)mkl_malloc(n * 1 * sizeof(float), 64);
B = (float *)mkl_malloc(n * 1 * sizeof(float), 64);
printf("The 1st vector is ");
for (int i = 0; i < n; i++){
A[i] = i;
printf("%2.0f", A[i]);
}
printf("\\n");
printf("The 2st vector is ");
for (int i = 0; i < n; i++){
B[i] =i+1;
printf("%2.0f", B[i]);
}
printf("\\n");
//计算a*A+b*B
cblas_saxpby(n, a, A, 1, b, B, 1);
printf("The a*A+b*B is ");
for (int i = 0; i < n; i++){
printf("%2.0f", B[i]);
}
printf("\\n");
mkl_free(A);
mkl_free(B);
getchar();
return 0;
}

The 1st vector is  0 1 2 3 4
The 2st vector is  1 2 3 4 5
The a*A+b*B is  1 3 5 7 9

## 乘法

//乘法
#include<stdio.h>
#include<stdlib.h>
#include <mkl.h>

int main()
{
float *A, *B;//两个向量
int a = 1, b = 1;//标量
int n = 5;//向量大小
float res;
A = (float *)mkl_malloc(n * 1 * sizeof(float), 64);
B = (float *)mkl_malloc(n * 1 * sizeof(float), 64);
printf("The 1st vector is ");
for (int i = 0; i < n; i++){
A[i] = i;
printf("%2.0f", A[i]);
}
printf("\\n");
printf("The 2st vector is ");
for (int i = 0; i < n; i++){
B[i] = i + 1;
printf("%2.0f", B[i]);
}
printf("\\n");
//乘法:对应元素乘积的加和
res=cblas_sdot(n, A, 1, B, 1);
printf("点乘结果： %2.0f",res);
printf("\\n");
mkl_free(A);
mkl_free(B);
getchar();
return 0;
}

The 1st vector is  0 1 2 3 4
The 2st vector is  1 2 3 4 5

## 二范数

//计算向量二范数
#include<stdio.h>
#include<stdlib.h>
#include<mkl.h>
void main()
{
float *A;
int n = 5;
float res;
A = (float *)mkl_malloc(n*sizeof(float), 64);
printf("The original vector：\\n");
for (int i = 0; i < n; i++)
{
A[i] = i + 1;
printf("%2.0f ", A[i]);
}
printf("\\n");
res = cblas_snrm2(n, A, 1);//计算二范数
printf("The norm2 of vector is:%2.6f", res);
mkl_free(A);
getchar();
}

The original vector：
1  2  3  4  5
The norm2 of vector is:7.416198

## 旋转

(2,0)
(2,0)绕原点旋转45°为例。代码有点问题，一释放内存就出错，具体原因是对两个向量开辟空间以后又让它们指向了别的地址，造成了开辟空间无用。所以调用Cblas函数，可以直接把指向数组的指针丢进去。暂时先这样理解吧，等把C++复习一遍再来看看分析的对不对。

//旋转，以二维空间中的一个点(2，0)绕原点旋转45°
#include<stdio.h>
#include<stdlib.h>
#include<mkl.h>
#include<math.h>
#define M_PI 3.14159265358979323846

int main()
{
float *A, *B;//A是坐标点，B是旋转矩阵
float point1[] = { 2 };//旋转点x坐标
float point2[] = { 0 };//旋转点y坐标
float rotpoint[] = { cos(45.0*M_PI / 180), sin(45.0*M_PI / 180) };
//A = (float *)mkl_malloc(1 * sizeof(float), 64);
//B = (float *)mkl_malloc(1 * sizeof(float), 64);
A = point1;
B = point2;
printf("The point is (%2.0f,%2.0f)",point1[0],point2[0]);
printf("\\n");
//计算旋转后的点
cblas_srot(1, A, 1, B, 1, rotpoint[0], rotpoint[1]);
printf("The rotated is (%2.6f,%2.6f)", A[0], B[0]);
printf("\\n");
//mkl_free(A);
//mkl_free(B);
getchar();
return 0;
}


The point is ( 2, 0)
The rotated is (1.414214,-1.414214)

## 缩放

x=ax

x=a*x

//计算向量缩放
#include<stdio.h>
#include<stdlib.h>
#include<mkl.h>
void main()
{
float *A;
int n = 5;
float scal=0.1;
A = (float *)mkl_malloc(n*sizeof(float), 64);
printf("The original vector：\\n");
for (int i = 0; i < n; i++)
{
A[i] = i + 1;
printf("%2.0f ", A[i]);
}
printf("\\n");
cblas_sscal(n, scal, A, 1);//缩放
printf("The scaled vector：\\n");
for (int i = 0; i < n; i++)
{
printf("%2.1f ", A[i]);
}
mkl_free(A);
getchar();
}

The original vector：
1  2  3  4  5
The scaled vector：
0.1 0.2 0.3 0.4 0.5

## 交换

//交换
#include<stdio.h>
#include<stdlib.h>
#include<mkl.h>

int main()
{
float *A, *B;//两个向量
int a = 1, b = 1;//标量
int n = 5;//向量大小
A = (float *)mkl_malloc(n * 1 * sizeof(float), 64);
B = (float *)mkl_malloc(n * 1 * sizeof(float), 64);
printf("The 1st vector is ");
for (int i = 0; i < n; i++){
A[i] = i;
printf("%2.0f", A[i]);
}
printf("\\n");
printf("The 2st vector is ");
for (int i = 0; i < n; i++){
B[i] = i + 1;
printf("%2.0f", B[i]);
}
printf("\\n");
//交换AB
cblas_sswap(n, A, 1, B, 1);
printf("The 1st swapped vctor is");
for (int i = 0; i < n; i++){
printf("%2.0f", A[i]);
}
printf("\\n");
printf("The 2st swapped vctor is");
for (int i = 0; i < n; i++){
printf("%2.0f", B[i]);
}
printf("\\n");
mkl_free(A);
mkl_free(B);
getchar();
return 0;
}

The 1st vector is  0 1 2 3 4
The 2st vector is  1 2 3 4 5
The 1st swapped vctor is 1 2 3 4 5
The 2st swapped vctor is 0 1 2 3 4

## 最值

//求最大最小值
#include<stdlib.h>
#include<stdio.h>
#include<mkl.h>
void main()
{
float *A;//向量
int n = 5;//向量大小
int max, min;
A = (float *)mkl_malloc(n * 1 * sizeof(float), 64);
printf("The 1st vector is ");
for (int i = 0; i < n; i++){
A[i] = i;
printf("%2.0f", A[i]);
}
printf("\\n");
//计算最值位置
max=cblas_isamax(n, A, 1);
min = cblas_isamin(n, A, 1);
printf("The max value is %2.0f, position is %d\\n", A[max], max + 1);
printf("The min value is %2.0f, position is %d\\n", A[min], min + 1);
mkl_free(A);
getchar();
}

The 1st vector is  0 1 2 3 4
The max value is  4, position is 5
The min value is  0, position is 1

# 矩阵-向量

## 乘法1

y:=αAx+βy

y := \\alpha*A*x + \\beta*y

//矩阵-向量乘积
#include<stdio.h>
#include<stdlib.h>
#include<mkl.h>
int main()
{
float *A, *B,*C;//A是矩阵，B是向量,C是向量
int m = 2;//矩阵行数
int n = 5;//向量维度，矩阵列数
int a = 1, b = 1;//缩放因子

A = (float *)mkl_malloc(m*n*sizeof(float), 64);
B = (float *)mkl_malloc(n*sizeof(float), 64);
C = (float *)mkl_malloc(m*sizeof(float), 64);
//赋值,按行存储?
printf("数组为\\n");
for (int i = 0; i < m*n; i++){
if (i%n == 0 && i != 0)
printf("\\n");

A[i] = i;
printf("%2.0f",A[i]);
}
printf("\\n");
printf("向量为\\n");
for (int i = 0; i < n; i++)
{
B[i] = i + 1;
printf("%2.0f", B[i]);
}
printf("\\n");
for (int i = 0; i < m*n; i++)
C[i] = 0;
//2*5的矩阵与5*1的向量相乘
cblas_sgemv(CblasRowMajor, CblasNoTrans, m, n, a, A, n, B, 1, b, C, 1);

printf("矩阵-向量乘法结果\\n");
for (int i = 0; i < m; i++){
printf("%2.0f ", C[i]);
}
mkl_free(A);
mkl_free(B);
mkl_free(C);
getchar();
return 0;
}

数组为
0 1 2 3 4
5 6 7 8 9

1 2 3 4 5

40 115

## 乘法2

A:=αxy+A,

A := \\alpha*x*y\’+ A,

//矩阵-向量乘积
#include<stdio.h>
#include<stdlib.h>
#include<mkl.h>
int main()
{
float *A, *B, *C;//A是矩阵，B是向量
int m=2,n = 5;//B,C向量维度
int a = 1;//缩放因子

A = (float *)mkl_malloc(m*n*sizeof(float), 64);
B = (float *)mkl_malloc(m*sizeof(float), 64);
C = (float *)mkl_malloc(n*sizeof(float), 64);
//赋值,按行存储?
printf("数组为\\n");
for (int i = 0; i < m*n; i++){
if (i%n == 0 && i != 0)
printf("\\n");

A[i] = 1;
printf("%2.0f", A[i]);
}
printf("\\n");
printf("向量1为\\n");
for (int i = 0; i < m; i++)
{
B[i] = i + 1;
printf("%2.0f", B[i]);
}
printf("\\n");
printf("向量2为\\n");
for (int i = 0; i < n; i++)
{
C[i] = i+2;
printf("%2.0f", C[i]);
}
printf("\\n");
//5*1向量乘以1*5向量，加上5*5矩阵
cblas_sger(CblasRowMajor, m, n, a, B, 1, C, 1, A, n);

printf("向量-向量相乘+矩阵的结果\\n");
for (int i = 0; i < m*n; i++){
if (i%n == 0 && i != 0)
printf("\\n");

printf("%2.0f ", A[i]);
}
mkl_free(A);
mkl_free(B);
mkl_free(C);
getchar();
return 0;
}

数组为
1 1 1 1 1
1 1 1 1 1

1 2

2 3 4 5 6

3  4  5  6  7
5  7  9 11 13

# 矩阵-矩阵

## 乘法1

C:=αop(A)op(B)+βC,

C := \\alpha*op(A)*op(B) + \\beta*C,

#include<stdio.h>
#include<stdlib.h>
#include<mkl.h>
int main()
{
float *A, *B, *C;
int m = 2, n = 3, k = 2;//A维度2*3,B维度2*3(计算时候转置),C维度2*2
int a = 1, b = 1;//缩放因子
A = (float *)mkl_malloc(m*n*sizeof(float), 64);
B = (float *)mkl_malloc(n*k*sizeof(float), 64);
C = (float *)mkl_malloc(m*k*sizeof(float), 64);

printf("矩阵1为\\n");
for (int i = 0; i < m*n; i++)
{
if (i != 0 && i%n == 0)
printf("\\n");
A[i] = i + 1;
printf("%2.0f", A[i]);
}
printf("\\n");

printf("矩阵2为\\n");
for (int i = 0; i < n*k; i++)
{
if (i != 0 && i%k == 0)
printf("\\n");
B[i] = 1;
printf("%2.0f", B[i]);
}
printf("\\n");

printf("矩阵3为\\n");
for (int i = 0; i < m*k; i++)
{
if (i != 0 && i%k == 0)
printf("\\n");
C[i] = i;
printf("%2.0f", C[i]);
}
printf("\\n");

printf("结果矩阵\\n");
cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, m, k, n, a, A, n, B, k, b, C, k);//注意mkn的顺序☆
for (int i = 0; i < m*k; i++)
{
if (i != 0 && i%k == 0)
printf("\\n");
printf("%2.0f", C[i]);
}
printf("\\n");

mkl_free(A);
mkl_free(B);
mkl_free(C);
getchar();
return 0;
}

矩阵1为
1 2 3
4 5 6

1 1
1 1
1 1

0 1
2 3

6 7
1718

## 乘法2

#include<stdio.h>
#include<stdlib.h>
#include<mkl.h>
int main()
{
float *A, *B, *C;
int m = 2, n = 3, k = 2;//A维度2*3,B维度2*3(计算时候转置),C维度2*2
int a = 1, b = 1;//缩放因子
A = (float *)mkl_malloc(m*n*sizeof(float), 64);
B = (float *)mkl_malloc(k*n*sizeof(float), 64);
C = (float *)mkl_malloc(m*k*sizeof(float), 64);

printf("矩阵1为\\n");
for (int i = 0; i < m*n; i++)
{
if (i != 0 && i%n == 0)
printf("\\n");
A[i] = i + 1;
printf("%2.0f", A[i]);
}
printf("\\n");

printf("矩阵2为\\n");
for (int i = 0; i < k*n; i++)
{
if (i != 0 && i%n == 0)
printf("\\n");
B[i] = 1;
printf("%2.0f", B[i]);
}
printf("\\n");

printf("矩阵3为\\n");
for (int i = 0; i < m*k; i++)
{
if (i != 0 && i%k == 0)
printf("\\n");
C[i] = i;
printf("%2.0f", C[i]);
}
printf("\\n");

printf("结果矩阵\\n");

cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasTrans, m, k, n, a, A, n, B, n, b, C, k);//注意mkn的顺序☆
for (int i = 0; i < m*k; i++)
{
if (i != 0 && i%k == 0)
printf("\\n");
printf("%2.0f", C[i]);
}
printf("\\n");

mkl_free(A);
mkl_free(B);
mkl_free(C);
getchar();
return 0;

}

矩阵1为
1 2 3
4 5 6

1 1 1
1 1 1

0 1
2 3

6 7
1718

## 注意点

op(A)
op(A)和的C行数，

op
op代表操作，乘法2中的

op
op就是转置；然后是矩阵

op(B)
op(B)和

C
C的列数；随后才是op(A)op(A)的列数和

op(B)
op(B)的行数。对于乘法2中的第二个矩阵，也就是

B
<script type="math/tex" id="MathJax-Element-399">B</script>矩阵，虽然转置了，但是还是以不转置时候，以行存储方式的引导维度，也就是列数为输入参数。