与
MTL
都是基于
C++ template
高效数值计算程序库,不过他们专注于不同的方向。
Blitz++
提供了一个
N
维(
1—10
)的
Array
类
,
这个
Array
类以
reference counting
技术实现,支持任意的存储序
(row-major
的
C-style
数组,
column-major
的
Fortran-style
数组
)
,数组的切割
(slicing),
子数组的提取
(subarray),
灵活的
Array
相关表达式处理。另外提供了可以产生不同分布的随机数
(F,Beta,Chi-Square
,正态,均匀分布等
)
的类也是很有特色的。
MTL
专注于线性代数相关的计算任务,如各种形式矩阵的生成
(
对角,共轭,稀疏,对称等
)
,相关的计算,变换,以及与一维向量的运算。
两个程序库对于从
Matlab
导入导出数据都有不错的支持。
本文主要介绍如何在
Visual C++7.1
编译器下运用这两个程序库。
以前的
VC6
编译器由于对
ISO C++98
标准的支持不够,特别是在
template
方面,以至于很难编译这种完全用
template
技术构造起来的程序库。
Blitz++
是完全不支持
VC6
的。
到了
VC7.1
,由于对于
ISO
标准的支持达到了
98%
,使得我们可以很轻松的编译使用这两个程序库。
不过这两个程序库的文档不是那么友好,特别是
MTL
,仅仅提供了类似于
reference
的文档,对于具体的使用方法则不作介绍。
Blitz++
相对来说好一些,还提供一份介绍性的入门文档
。所以使用这两个程序库阅读其源代码往往是必要的。当然了,两个程序库都是
template
代码,源代码必定是全开放的。
先来介绍一下配置吧
。
1,
Blitz++,
目前最高版本是
0.7
,
Blitz++
已经成为
SourceForge
的项目了,所以可以在
SourceForge.net
下载到。下载后解压缩,你会看到
\Blitz++-0.7\blitz
和
\Blitz++-0.7\random
两个文件夹,这是
blitz
的源代码所在处。
\Blitz++-0.7\manual
是文档所在文件夹。
\Blitz++-0.7\benchmarks,\Blitz++-0.7\examples
和
\Blitz++-0.7\testsuite
中都有很多好的使用实例可供参考。
现在将
VC++
的
IDE
的
Include
设置为
\Blitz++-0.7
,因为
blitz
源码中都有这样形式的
#include ,#include
。或者就干脆把两个源码文件夹整个得
copy
到
include
文件夹内。然后将
blitz
文件夹下的
config.h
改为其它名字,而将
config-VS.NET2003.h
的名字改为
config.h
。
OK,
现在你就可以编译所有的
testsuite
和
benchmarks
了。
1,
MTL
的配置相对来说麻烦一点,现在
http://www.osl.iu.edu/research/mtl/
这里下载一个
VC++7
的,不过还不能马上用。由于
VC++7.1
对标准的支持更近了一步,同时对于某些语法细节的检查更为严格
(
主要是对于
typename
和
template partial specialization
),我们要对代码做一些小小地修改,特别是
mtl/mtl_config.h
这个文件。有一些地方要加入
typename
。另外有两个模板偏特化的情况需要修改,加上
template <>
。在这里
http://newsuppy.go.nease.net/mtl.zip
我提供了一个修改完成的版本,不过我不保证我的修改可能引入的新的
bugs
,所以请谨慎使用。
MTL
的内部使用一定数量的
STL
组件和算法。
MTL
的源代码都在
mtl
文件夹内,由于
mtl
内部的
include
都是
#include “…”
的形式,使用时把
mtl
文件夹复制到当前
project
下就可以。如果要设
VC++
的
Include
目录,则应该先把所有的
#include “…”
改为
#include <…>
这样的形式。
不过刚开始使用
MTL
还是有一些不太容易让人接受的地方。比如
mtl::matrix
这个模板类并不能够产生实际的矩阵对象,而要通过它的
type
成员产生一个对应模板参数的类型,再通过这个类型来实例化对象。
比如
typedef mtl::matrix< SPAN>, rectangle<>, dense<>, row_major >::type Matrix; Matrix A;
这里的
A
才是真正的矩阵对象,而
Matrix
则是一个元素为
float
,矩形,密集,行主
(C-style)
的矩阵类。
下面我提供三个简单的入门例子解释
MTL
的使用。分别有矩阵的加法,乘法,转置,求逆以及一个线性方程组求解的例子。
另外
mtl
的
test
和
contrib
文件夹下也有很多不错的示例代码可以查阅。
MTL
使用示例
1
,矩阵的加法,乘法和转置。
#include
#include
#include
"
mtl/mtl.h
"
#include
using
namespace
std;
using
namespace
mtl;
template
<
class
Matrix
>
void
print_matrix(Matrix
&
mat,
const
string
&
description)
{
std::cout
<<
description;
std::cout
<<
'
[
'
;
for
(Matrix::iterator i
=
mat.begin(); i
!=
mat.end();
++
i)
{
for
(Matrix::OneD::iterator j
=
(
*
i).begin(); j
!=
(
*
i).end();
++
j)
{
std::cout
<<
'
\t
'
<<*
j;
}
std::cout
<<
((i
+
1
==
mat.end())
?
"
\t]\n
"
:
"
\n
"
);
}
}
int
main(
int
argc,
char
*
argv[])
{
typedef matrix
<
float
, rectangle
<>
, dense
<>
, row_major
>
::type Matrix;
const
Matrix::size_type MAX_ROW
=
3
, MAX_COL
=
3
;
Matrix A(MAX_ROW,MAX_COL),B(MAX_ROW,MAX_COL),C(MAX_ROW,MAX_COL);
//
fill Matrix A with the index syntax
for
(Matrix::size_type i
=
0
; i
<
MAX_ROW;
++
i)
{
for
(Matrix::size_type j
=
0
; j
<
MAX_COL;
++
j)
{
A(i, j)
=
Matrix::value_type(rand()
%
50
);
}
}
//
fill Matrix B with the iterator syntax
for
(Matrix::iterator i
=
B.begin(); i
!=
B.end();
++
i)
{
for
(Matrix::OneD::iterator j
=
(
*
i).begin(); j
!=
(
*
i).end();
++
j)
{
*
j
=
Matrix::value_type(rand()
%
50
);
}
}
print_matrix(A,
"
A=\n
"
);
print_matrix(B,
"
B=\n
"
);
//
Matrix C = A + B
add(A, C);
add(B,C);
print_matrix(C,
"
C = A + B \n
"
);
//
Matrix C = A * B^T, B^T: transpose of B
transpose(B);
print_matrix(B,
"
B^T=\n
"
);
zero_matrix(C);
//
because mult(A, B, C): C += A*B
mult(A,B,C);
print_matrix(C,
"
C = A * B^T\n
"
);
return
0
;
}
2
,下面是一个线性方程组的解法
#include
#include
#include
#include
"
mtl/mtl.h
"
#include
"
mtl/lu.h
"
#include
using
namespace
std;
using
namespace
mtl;
int
main(
int
argc,
char
*
argv[])
{
typedef matrix
<
float
, rectangle
<>
, dense
<
external
>
, row_major
>
::type Matrix;
//
dense : data copy from a float array,not generate them with yourself
const
Matrix::size_type MAX_ROW
=
3
, MAX_COL
=
3
;
//
solve the equation Ax=b
//
{ 4x - y + z = 7
//
4x - 8y + z= -21
//
-2x + y + 5z = 15 }
//
A = [ 4 -1 1
//
4 -8 1
//
-2 1 5 ]
//
b = [7 - 21 15]^T
float
a[]
=
{
4.0f
,
-
1.0f
,
1.0f
,
4.0f
,
-
8.0f
,
1.0f
,
-
2.0f
,
1.0f
,
5.0f
}
;
Matrix A(a, MAX_ROW, MAX_COL);
typedef matrix
<
float
, rectangle
<>
, dense
<>
, row_major
>
::type LUMatrix;
LUMatrix LU(A.nrows(), A.ncols());
mtl::copy(A, LU);
typedef dense1D
<
float
>
Vector;
Vector pvector(A.nrows());
lu_factor(LU, pvector);
Vector b(A.nrows()), x(A.nrows());
b[
0
]
=
7.0f
, b[
1
]
=
-
21.0f
, b[
2
]
=
15.0f
;
lu_solve(LU, pvector, b, x);
for
(Vector::iterator i
=
x.begin(); i
!=
x.end();
++
i)
cout
<<
*
i
<<
'
\t
'
;
system(
"
pause
"
);
return
0
;
}
3
,矩阵求逆
#include
#include
#include
#include
"
mtl/mtl.h
"
#include
"
mtl/lu.h
"
#include
using
namespace
std;
using
namespace
mtl;
template
<
class
Matrix
>
void
print_matrix(Matrix
&
mat,
const
string
&
description)
{
std::cout
<<
description;
std::cout
<<
'
[
'
;
for
(Matrix::iterator i
=
mat.begin(); i
!=
mat.end();
++
i)
{
for
(Matrix::OneD::iterator j
=
(
*
i).begin(); j
!=
(
*
i).end();
++
j)
{
std::cout
<<
'
\t
'
<<
*
j;
}
std::cout
<<
((i
+
1
==
mat.end())
?
"
\t]\n
"
:
"
\n
"
);
}
}
int
main(
int
argc,
char
*
argv[])
{
typedef matrix
<
float
, rectangle
<>
, dense
<
external
>
, row_major
>
::type Matrix;
//
dense : data copy from a float array,not generate them with yourself
const
Matrix::size_type MAX_ROW
=
3
, MAX_COL
=
3
;
//
inverse matrix A
//
A = [ 4 -1 1
//
4 -8 1
//
-2 1 5 ]
float
a[]
=
{
4.0f
,
-
1.0f
,
1.0f
,
4.0f
,
-
8.0f
,
1.0f
,
-
2.0f
,
1.0f
,
5.0f
}
;
Matrix A(a, MAX_ROW, MAX_COL);
typedef matrix
<
float
, rectangle
<>
, dense
<>
, row_major
>
::type CMatrix;
CMatrix LU(A.nrows(), A.ncols());
mtl::copy(A, LU);
typedef dense1D
<
float
>
Vector;
Vector pvector(A.nrows());
lu_factor(LU, pvector);
CMatrix InvA(A.nrows(), A.ncols());
lu_inverse(LU, pvector, InvA);
print_matrix(A,
"
A = \n
"
);
print_matrix(InvA,
"
A^(-1) = \n
"
);
system(
"
pause
"
);
return
0
;
}
参考:
1
,数值方法
(Matlab
版
) 3rd
John H.Mathews, Kurtis D.Fink
著,
陈渝,周璐,钱方
等译
2
,
Matlab 6.5
的文档
The MathWorks, Inc.