您的位置:首页 > 其它

gsl数据类型之矩阵

2013-04-15 15:17 239 查看
如果在程序中需要调用gsl中的矩阵类型,首先需要声明#include<gsl/gsl_matrix.h> 与向量一样,gsl中的矩阵同样也构建在数据块之上。其声明如下:
[cpp] view plaincopy[gsl_matrix_double.h]
......
typedef struct
{
size_t size1;//矩阵的行数
size_t size2;//矩阵的列数
size_t tda;//矩阵的实际列数
double * data;//实际上就是block->data
gsl_block * block;//矩阵相应的数据块
int owner;//所有者标识符
} gsl_matrix;
......

需要仔细说明的是矩阵中tda的意义。举一个矩阵的例子:1 2 3 X X X4 5 6 X X X 这个矩阵中"X"表示未使用的内存单元。则在这个矩阵中,size1=2,size2=3,而实际列数tda=6。这样的规定与c语言中二维数组的存储格式为行优先有关。因此gsl_matrix中block->data内存块的实际大小为size1*tda*sizeof(double)。 gsl在矩阵中还设置了一个size2参数正是体现了内容与描述分离的思想。 类似于向量,gsl也提供了各种关于矩阵内存分配的函数:[cpp] view plaincopy[gsl_matrix_double.h]
......
gsl_matrix *
gsl_matrix_alloc (const size_t n1, const size_t n2);
gsl_matrix *
gsl_matrix_calloc (const size_t n1, const size_t n2);
gsl_matrix *
gsl_matrix_alloc_from_block (gsl_block * b,
const size_t offset,
const size_t n1,
const size_t n2,
const size_t d2);
gsl_matrix *
gsl_matrix_alloc_from_matrix (gsl_matrix * m,
const size_t k1,
const size_t k2,
const size_t n1,
const size_t n2);
gsl_vector *
gsl_vector_alloc_row_from_matrix (gsl_matrix * m,
const size_t i);
gsl_vector *
gsl_vector_alloc_col_from_matrix (gsl_matrix * m,
const size_t j);
void gsl_matrix_free (gsl_matrix * m);
......

这些函数的作用容易从函数名中理解。需要注意的是其中alloc与calloc函数创建的矩阵中owner=1,而alloc_from_block与alloc_from_matrix中owner=0。如同vector 中的owner一样,不同的取值将影响gsl_matrix_free的动作。即如果owner=1,则销毁矩阵时将同时销毁矩阵所对应的数据块,而如果owner=0,则销毁矩阵的同时不会销毁对应的数据块。 如果需要访问矩阵中的第i+1行,j+1列的元素,可以使用下面的两个函数:[cpp] view plaincopy[gsl_matrix_double.h]
......
double gsl_matrix_get(const gsl_matrix * m, const size_t i, const size_t j);
void gsl_matrix_set(gsl_matrix * m, const size_t i, const size_t j, const double x);
......

当然,gsl也允许以向量为单位访问矩阵元素。下面的两个函数将把给定向量中的元素拷贝到矩阵中行或列元素:[cpp] view plaincopy[gsl_matrix_double.h]
......
int gsl_matrix_set_row(gsl_matrix * m, const size_t i, const gsl_vector * v);
int gsl_matrix_set_col(gsl_matrix * m, const size_t j, const gsl_vector * v);
......

或者,反过来,亦可将矩阵中某行或者某列拷贝到给定的向量中: [cpp] view plaincopy[gsl_matrix_double.h]
......
int gsl_matrix_get_row(gsl_vector * v, const gsl_matrix * m, const size_t i);
int gsl_matrix_get_col(gsl_vector * v, const gsl_matrix * m, const size_t j);
......

此外,我们还可利用如下的两个函数直接根据矩阵中的数据创建新的向量: [cpp] view plaincopy[gsl_matrix_double.h]
......
gsl_vector *
gsl_vector_alloc_row_from_matrix (gsl_matrix * m,
const size_t i);
gsl_vector *
gsl_vector_alloc_col_from_matrix (gsl_matrix * m,
const size_t j);
......

值得注意的是,与前面两个函数的拷贝方法不同,以这种方式创建的向量中的数据只是对矩阵中相应数据的一种引用,这一点在函数的源代码中得到验证:[cpp] view plaincopy[getset_source.c]
......
TYPE (gsl_vector) *
FUNCTION (gsl_vector, alloc_row_from_matrix) (TYPE(gsl_matrix) * m,
const size_t i)
{
TYPE (gsl_vector) * v;
const size_t M = m->size1;
......
v = (TYPE (gsl_vector) *) malloc (sizeof (TYPE (gsl_vector)));
......
v->data = m->data + MULTIPLICITY * i * m->tda ;
v->size = m->size2;
v->stride = 1;
v->block = 0;
return v;
}

有趣的是,新创建的向量中v->block域实际上为空指针。 gsl中还提供了一些根据矩阵元素创建vector view类型的函数:[cpp] view plaincopy[gsl_matrix_double.h]
......
_gsl_vector_view
gsl_matrix_row (gsl_matrix * m, const size_t i);
_gsl_vector_view
gsl_matrix_column (gsl_matrix * m, const size_t j);
_gsl_vector_view
gsl_matrix_diagonal (gsl_matrix * m);
_gsl_vector_view
gsl_matrix_subdiagonal (gsl_matrix * m, const size_t k);
_gsl_vector_view
gsl_matrix_superdiagonal (gsl_matrix * m, const size_t k);
......

其中,gsl_matrix_diagonal将由矩阵的对角元素创建vector view,gsl_matrix_subdiagonal则将获得矩阵的第k层下对角元元素,而gsl_matrix_superdiagonal则获得矩阵的第k层上对角元元素。注意,这些函数并不要求矩阵为方阵。例如,对于下面的矩阵a:

则gsl_matrix_diagonal(a)将返回向量(11,22,33)的view,gsl_matrix_subdiagonal(a,1)将返回向量(21,32)的view,而gsl_matrix_subdiagonal(a,1)将将返回向量(12,23)的view。 当然,既然是view数据类型,则意味着这些向量只是对矩阵中原有数据的引用。我们以gsl_matrix_diagonal函数为例说明之:[cpp] view plaincopy[rowcol_source.c]
......
QUALIFIED_VIEW(_gsl_vector,view)
FUNCTION (gsl_matrix, diagonal) (QUALIFIED_TYPE(gsl_matrix) * m)
{
QUALIFIED_VIEW(_gsl_vector,view) view = NULL_VECTOR_VIEW;
TYPE(gsl_vector) v = NULL_VECTOR;
v.data = m->data;
v.size = GSL_MIN(m->size1,m->size2);
v.stride = m->tda + 1;
v.block = m->block;
v.owner = 0;
view.vector = v;
return view;
}
......

其中的宏定义与《gsl数据类型之向量》文末中的定义是相同的。特别注意到v向量中的stride域被设置成m->tda+1,而读源代码可知,使用gsl_vector_get(v,i)获取v中的第i+1个元素时,函数将返回v->data[i * v->stride],这就不难理解gsl是如何实现对矩阵对角元的引用的。 gsl中还有一些对矩阵整体赋值的函数,常用的有下面三个函数:[cpp] view plaincopy[gsl_matrix_double.h]
......
void gsl_matrix_set_zero (gsl_matrix * m);//将矩阵所有元素初始化为零
void gsl_matrix_set_identity (gsl_matrix * m);//初始化矩阵为单位阵
void gsl_matrix_set_all (gsl_matrix * m, double x);//将矩阵所有元素初始化为x
......

而更多的涉及矩阵操作的函数信息可以参见手册http://www.gnu.org/software/gsl/manual/html_node/Matrices.html 此外矩阵也有相应的matrix view类型的数据结构,可以实现提取子矩阵等功能,限于篇幅,这里不再展开介绍。有兴趣的读者可以参考手册matrix views一节http://www.gnu.org/software/gsl/manual/html_node/Matrix-views.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: