- 浏览: 491633 次
- 性别:
- 来自: 上海
文章分类
最新评论
-
hypercube:
markin'
配置D语言编程环境 -
qiezi:
qiezi 写道yangyang_08 写道1 ...
我的编程语言学习经历 -
qiezi:
yangyang_08 写道1、现在如果做并发服务器,楼主选用 ...
我的编程语言学习经历 -
yangyang_08:
1、现在如果做并发服务器,楼主选用什么样的语言架构?2、lua ...
我的编程语言学习经历 -
dearplain:
我也是语言爱好者,不过我一直坚持使用c。
我的编程语言学习经历
矩阵就不用再解释了,写成泛型主要是为了几个方便:
1、方便在栈上分配空间。由于维度在编译期已知,所以可以做到在栈上分配空间。当然如果这个对象是new出来的,自然是在堆上分配,这里说的是在栈上分配这个对象时,矩阵元素所占用的空间也在栈上分配。
2、方便在编译期检查非法的矩阵运算。C++模板的强大推导能力可以在编译期推导出结果矩阵的维度。
3、泛型类在方法内联上具有优势。
这个矩阵类为了能够直接从数组赋值,使用了一个ArrayPorxy类(可参考《Imperfect C++》)。
代码如下:
template
<
class
T,
int
D1,
int
D2
=
1
>
class ArrayProxy
{
T * data;
public :
ArrayProxy(T ( & value)[D1][D2])
: data( & value[ 0 ][ 0 ])
{
}
ArrayProxy(T ( & value)[D1 * D2])
: data(value)
{
}
T * getData() const
{
return data;
}
};
class ArrayProxy
{
T * data;
public :
ArrayProxy(T ( & value)[D1][D2])
: data( & value[ 0 ][ 0 ])
{
}
ArrayProxy(T ( & value)[D1 * D2])
: data(value)
{
}
T * getData() const
{
return data;
}
};
这个只是简单的实现。
因为我基本上不使用这个矩阵类,所以只完成几个简单功能:
1、从数组赋值:
int a[][3] = {{1,2,3}, {4,5,6}};
Matrix<int, 2, 3> m1(a);
或
int a[] = {1,2,3, 4,5,6};
Matrix<int, 2, 3> m1(a);
Matrix<int, 3, 2> m2(a);
Matrix<int, 6, 1> m3(a);
Matrix<int, 1, 6> m4(a);
2、矩阵乘法:
Matrix<int, 2, 3> m1;
Matrix<int, 2, 4> m2;
// m1 * m2 <== 编译错误,维度不匹配
Matrix<int, 3, 5> m3;
Matrix<int, 2, 5> m4 = m1 * m3; // <== 合法
// m3 * m1; // <== 编译错误,维度不匹配
源码如下:
template <class T, int R, int C>
class Matrix
{
T matrix[R][C];
public:
// Big three
Matrix(void)
{
memset(matrix, 0, sizeof(matrix));
}
Matrix(const Matrix& rhs)
{
memcpy(matrix, rhs.matrix, sizeof(matrix));
}
Matrix& operator =(const Matrix& rhs)
{
memcpy(matrix, rhs.matrix, sizeof(matrix));
return *this;
}
public:
Matrix(const ArrayProxy<T,R,C>& arr)
{
memcpy(matrix, arr.getData(), sizeof(matrix));
}
~Matrix(void)
{
}
public:
T get(int r, int c) const
{
assert(c < C && c >= 0 && r < R && r >= 0);
return matrix[r][c];
}
void set(int r, int c, T v)
{
assert(c < C && c >= 0 && r < R && r >= 0);
matrix[r][c] = v;
}
int getCols () const
{
return C;
}
int getRows () const
{
return R;
}
bool operator == (const Matrix& rhs) const
{
return memcmp(matrix, rhs.matrix, sizeof(matrix)) == 0;
}
bool operator != (const Matrix& rhs) const
{
return !(*this == rhs);
}
};
template <class T, int R, int C, int C1>
Matrix<T,R,C1> operator* (const Matrix<T,R,C>& lhs, const Matrix<T,C,C1>& rhs)
{
Matrix<T,R,C1> result;
for (int r=0; r<R; ++r)
{
for (int c=0; c<C1; ++c)
{
int value = 0;
for (int i=0; i<C; ++i)
{
value += lhs.get(r,i) * rhs.get(i,c);
}
result.set(r,c,value);
}
}
return result;
}
class Matrix
{
T matrix[R][C];
public:
// Big three
Matrix(void)
{
memset(matrix, 0, sizeof(matrix));
}
Matrix(const Matrix& rhs)
{
memcpy(matrix, rhs.matrix, sizeof(matrix));
}
Matrix& operator =(const Matrix& rhs)
{
memcpy(matrix, rhs.matrix, sizeof(matrix));
return *this;
}
public:
Matrix(const ArrayProxy<T,R,C>& arr)
{
memcpy(matrix, arr.getData(), sizeof(matrix));
}
~Matrix(void)
{
}
public:
T get(int r, int c) const
{
assert(c < C && c >= 0 && r < R && r >= 0);
return matrix[r][c];
}
void set(int r, int c, T v)
{
assert(c < C && c >= 0 && r < R && r >= 0);
matrix[r][c] = v;
}
int getCols () const
{
return C;
}
int getRows () const
{
return R;
}
bool operator == (const Matrix& rhs) const
{
return memcmp(matrix, rhs.matrix, sizeof(matrix)) == 0;
}
bool operator != (const Matrix& rhs) const
{
return !(*this == rhs);
}
};
template <class T, int R, int C, int C1>
Matrix<T,R,C1> operator* (const Matrix<T,R,C>& lhs, const Matrix<T,C,C1>& rhs)
{
Matrix<T,R,C1> result;
for (int r=0; r<R; ++r)
{
for (int c=0; c<C1; ++c)
{
int value = 0;
for (int i=0; i<C; ++i)
{
value += lhs.get(r,i) * rhs.get(i,c);
}
result.set(r,c,value);
}
}
return result;
}
测试代码:
int main()
{
{
// 测试初始化
Matrix<int, 3, 4> m1;
Matrix<int, 3, 4> m2(m1);
Matrix<int, 3, 4> m3 = m1;
Matrix<int, 3, 4> m4;
m4 = m1;
for (int i=0; i<3; i++)
for (int j=0; j<4; j++)
{
assert (m1.get(i, j) == 0);
assert (m2.get(i, j) == 0);
assert (m3.get(i, j) == 0);
assert (m4.get(i, j) == 0);
}
int a[] = {1,2,3,4, 5,6,7,8, 9,10,11,12};
Matrix<int, 3, 4> m5(a);
int b[3][4] = { {1,2,3,4},
{5,6,7,8},
{9,10,11,12}};
Matrix<int, 3, 4> m6(b);
Matrix<int, 3, 4> m7(m5);
Matrix<int, 3, 4> m8 = m5;
Matrix<int, 3, 4> m9;
m9 = m5;
for (int i=0; i<3; i++)
for (int j=0; j<4; j++)
{
assert (m5.get(i, j) == i*4+j+1);
assert (m6.get(i, j) == i*4+j+1);
assert (m7.get(i, j) == i*4+j+1);
assert (m8.get(i, j) == i*4+j+1);
assert (m9.get(i, j) == i*4+j+1);
}
// 维数不匹配,编译错误
// Matrix<int, 4, 5> m10 = m9;
int c[][2] = {{1,2}, {2,3}};
// 数组大小不匹配,编译错误
//Matrix<int, 3, 4> m10(c);
int d[] = {1,2};
// 数组大小不匹配,编译错误
//Matrix<int, 3, 4> m11(d);
// 乘法维数不合适,无法相乘
//m1 * m2;
Matrix<int,4,3> m12;
// 匹配,可以相乘
Matrix<int, 3, 3> m13 = m1 * m12;
Matrix<int, 8, 3> m14;
// 无法相乘
//Matrix<int, 3, 3> m15 = m1 * m14;
// 可以相乘
Matrix<int, 8, 4> m15 = m14 * m1;
}
{
// 检查点乘
int a[2][5] = {{1,2,3,4,5}, {6,7,8,9,10}};
Matrix<int, 2, 5> m1(a);
int b[5][3] = {{1,2,3}, {4,5,6}, {7,8,9}, {10,11,12}, {13,14,15}};
Matrix<int, 5, 3> m2(b);
int c[2][3] = {{135,150,165}, {310,350,390}};
Matrix<int, 2, 3> m3(c);
Matrix<int, 2, 3> m4 = m1 * m2;
assert(m4 == m3);
cout << m4.get(0,0) << endl;
}
return 0;
}
{
{
// 测试初始化
Matrix<int, 3, 4> m1;
Matrix<int, 3, 4> m2(m1);
Matrix<int, 3, 4> m3 = m1;
Matrix<int, 3, 4> m4;
m4 = m1;
for (int i=0; i<3; i++)
for (int j=0; j<4; j++)
{
assert (m1.get(i, j) == 0);
assert (m2.get(i, j) == 0);
assert (m3.get(i, j) == 0);
assert (m4.get(i, j) == 0);
}
int a[] = {1,2,3,4, 5,6,7,8, 9,10,11,12};
Matrix<int, 3, 4> m5(a);
int b[3][4] = { {1,2,3,4},
{5,6,7,8},
{9,10,11,12}};
Matrix<int, 3, 4> m6(b);
Matrix<int, 3, 4> m7(m5);
Matrix<int, 3, 4> m8 = m5;
Matrix<int, 3, 4> m9;
m9 = m5;
for (int i=0; i<3; i++)
for (int j=0; j<4; j++)
{
assert (m5.get(i, j) == i*4+j+1);
assert (m6.get(i, j) == i*4+j+1);
assert (m7.get(i, j) == i*4+j+1);
assert (m8.get(i, j) == i*4+j+1);
assert (m9.get(i, j) == i*4+j+1);
}
// 维数不匹配,编译错误
// Matrix<int, 4, 5> m10 = m9;
int c[][2] = {{1,2}, {2,3}};
// 数组大小不匹配,编译错误
//Matrix<int, 3, 4> m10(c);
int d[] = {1,2};
// 数组大小不匹配,编译错误
//Matrix<int, 3, 4> m11(d);
// 乘法维数不合适,无法相乘
//m1 * m2;
Matrix<int,4,3> m12;
// 匹配,可以相乘
Matrix<int, 3, 3> m13 = m1 * m12;
Matrix<int, 8, 3> m14;
// 无法相乘
//Matrix<int, 3, 3> m15 = m1 * m14;
// 可以相乘
Matrix<int, 8, 4> m15 = m14 * m1;
}
{
// 检查点乘
int a[2][5] = {{1,2,3,4,5}, {6,7,8,9,10}};
Matrix<int, 2, 5> m1(a);
int b[5][3] = {{1,2,3}, {4,5,6}, {7,8,9}, {10,11,12}, {13,14,15}};
Matrix<int, 5, 3> m2(b);
int c[2][3] = {{135,150,165}, {310,350,390}};
Matrix<int, 2, 3> m3(c);
Matrix<int, 2, 3> m4 = m1 * m2;
assert(m4 == m3);
cout << m4.get(0,0) << endl;
}
return 0;
}
补充:
1、加法、减法只需要2个矩阵维度相同即可。
template <class T, class R, class C>
Matrix<T,R,C> operator+ (const Matrix<T,R,C>& lhs, const Matrix<T,R,C>& rhs)
{
//
}
Matrix<T,R,C> operator+ (const Matrix<T,R,C>& lhs, const Matrix<T,R,C>& rhs)
{
//
}
2、由于1x1的矩阵可以看成一个标量,矩阵与标量运算结果维数与原矩阵相同,可以重载来实现。
template <class T, class R, class C>
Matrix<T,R,C> operator* (const Matrix<T,R,C>& lhs, const Matrix<T,1,1>& rhs)
{
//
}
Matrix<T,R,C> operator* (const Matrix<T,R,C>& lhs, const Matrix<T,1,1>& rhs)
{
//
}
3、由于类型泛化,可能某些合理的运算无法进行,比如float型矩阵,与一个int型标量运算等。这些最好是借助类型萃取等手段,推导出运算以后的类型。(c++0x中包含自动获取运算结果类型的关键字typeof,等几年就可以用了:)。GCC编译器中已有实现,不过似乎有BUG)。
4、其它。泛型实现可能会有一些考虑不周的地方,强类型有强类型的好处,不过必须要有完整的泛型算法支撑,否则难以使用。也可以把泛型矩阵类从一个普通矩阵类派生,这样更容易写出通用算法,不过在实现上可能要借助于运行期多态,对于矩阵类来说并不合适。
5、其它。。前面说C++的模板相当强大,D语言模板到目前为止似乎已经完全实现了C++模板的功能,还增加了一些比如字符串值参模板等特性,比C++模板功能更多。在代码编写上,由于可以编写静态判断语句(编译期)以及静态断言,编写模板比C++更容易。有时间可以试试用它写个矩阵类,纯粹是兴趣,这些东西真的很难用到,现成的库也挺多。
6、其它。。。c++0x要提供“template typedef”,也就是可以这样定义:
template <int R, int C> typedef Matrix<int, R, C> MatrixInt; // 定义类型,维度不定
template <class T> typedef Matrix<T, 4, 4> Matrix4x4; // 定义维度,类型不定
由此可以出定义行向量、列向量、标量等,当然实际使用起来可能没那么舒服了。
发表评论
-
Cilk++,XL
2009-08-05 10:04 2710刚看到CSDN新闻:Intel获得Cilk++技术 多核处理器 ... -
关于内存管理的一点想法
2009-07-14 16:11 1780分布式轻量级线程框架(还没取名)最近几个修改: 1、消息对象采 ... -
增加了monitor_node功能
2009-07-13 14:57 1835给分布式框架增加了类似 erlang 的 monitor_no ... -
轻量级线程切换效率
2009-07-13 12:07 2472同事测试了libcoro,它的linux版本可以使用4种模式, ... -
Cache Pool 架构
2009-06-16 10:05 3270先比较一下Hadoop。 Hadoop 架构: Cach ... -
高可用性Cache池
2009-06-15 16:10 4368前段时间开发上线了一个Cache池,使用双层Cache池冗余, ... -
抛开析构函数
2007-08-15 22:19 3408内存管理通常指的是堆 ... -
C++程序设计
2007-03-25 13:37 104上周在修改扩充同事的代码,发现几个问题。 1、访问级别几乎全 ... -
突发奇想续
2006-12-13 09:50 1963简单写了点代码,把那个方程组生成树结构: #include ... -
为C++实现一个IDL (零)
2005-09-15 01:27 4701一、问题。这段时间考虑实现一个纯C++的分布式服务包装库 ... -
为C++实现一个IDL (一)
2005-09-17 19:40 3002前面简单写了点静态结构,这一次将主要关注动态模型以及调用 ... -
正式建立asgard项目 (因ancients已经被人使用了)
2005-09-20 10:30 1898“为C++实现一个IDL” ... -
为C++实现一个IDL (二)
2005-09-20 22:34 2422说明:要看懂后面那部分代码,即使用Typelist的部分 ... -
为C++实现一个IDL (三)
2005-09-21 20:34 2725一、修正错误。首先修正第二篇中的一些错误,错误的内容可见 ... -
为C++实现一个IDL (四)
2005-09-22 19:13 2049如《为C++实现一个IDL(三)》一文中所说,还剩最后一 ... -
asgard项目遗留问题 (2005-09-27更新)
2005-09-24 17:00 1815asgard项目已经准备了 ... -
C++实现简单的类型库
2005-09-26 17:31 3003很久以前看到有人问“如何在C++中实现动态加载类”时,简 ... -
为C++实现一个IDL (五)
2005-09-28 22:57 2070本篇没什么清晰的目的,只是解释一下前面的几个问题,并提出 ... -
自己写的一个max函数
2005-12-12 10:45 1929CSDN上看到有人问能否实现一个效率较高的max函数,效 ... -
C++之AOP
2005-12-15 15:43 5763AOP是近年炒得很热,但却用得很少的一门技术,不过这并不 ...
相关推荐
用c++,能够实现任意矩阵加法,乘法,逆阵计算。
本文所描述的泛型Vector和泛型Matrix,具有不同数值类型Vector、Matrix矩阵构造、this[,]索引、Copy深度复制、运算符(+加、-减、*乘、>大于、<小于、>=大于等于、小于等于)重载、GetRow提取某一行、GetCol提取某一...
分数矩阵运算类:设计矩阵类和分数类,封装矩阵和分数的运用。 目的:掌握面向对象的程序设计思想,运用C#语言的继承-封装-重载-泛型,完成从数学算法到OOP实践。 要求: (1)设计矩阵类Matrix,重载运算符+,-,*...
matrs:试验Rust的const泛型以实现基于数组的矩阵运算
使用 rust 实现的矩阵乘法算法,包括矩阵乘法定义的直接相乘算法,时间复杂度 O(n^3),简单的分治算法(将矩阵划分为 4 个子矩阵),时间复杂度 O(n^3),以及strassen算法(使用了10个中间矩阵存储中间运算结果),...
矩阵行列式的对数广泛出现在多元统计的背景下。 高斯分布的 log-pdf、熵和... 对于泛型矩阵,它使用 LU 分解,而对于正定矩阵,可以使用 cholesky 分解,这通常更有效。 实现的核心只包含几行。 实际上,这个函数并不
本程序是根据java中的泛型开发的可以进行矩阵的加法,减法和乘法以及矩阵的迹的方法,具有通用性和参考性,需要的可以下载学习
这些关系以及传递矩阵在某些点上的一些渐近行为和值,使我们能够完全确定传递矩阵的特征值。 对于周期性边界条件情况,我们恢复了以前通过常规Bethe ansatz方法获得的相同的T-Q关系,而对于非对角边界条件情况,...
数学1.0 Kotlin语言的智能数学软件包。 使用用于组和环形对象的通用接口实现算术子包。 实现通用复杂对象和对象的数字子包以四舍五入。 实现子包以处理泛型矩阵和向量。 实现子包以处理坐标,如gerics笛卡尔坐标。
Java51.4.1 使用Object表示泛型1.4.2 基本类型的包装1.4.3 使用接口类型表示泛型1.4.4 数组类型的兼容性1.5 利用Java5泛性实现泛型特性成分1.5.1 简单的泛型类和接口1.5.2 自动装箱/拆箱1.5.3 带有限制的通配符...
java5 1.4.1 使用object表示泛型 1.4.2 基本类型的包装 1.4.3 使用接口类型表示泛型 1.4.4 数组类型的兼容性 1.5 利用java5泛性实现泛型特性成分 1.5.1 简单的泛型类和接口 1.5.2 自动装箱/拆箱....
java5 1.4.1 使用object表示泛型 1.4.2 基本类型的包装 1.4.3 使用接口类型表示泛型 1.4.4 数组类型的兼容性 1.5 利用java5泛性实现泛型特性成分 1.5.1 简单的泛型类和接口 1.5.2 自动装箱/拆箱....
指定长度的构造函数;以 x 为样板的构造函数;以数组 v 为数据的构造函数;以数组 x 为数据的赋值型构造函数;以字符串为数据的赋值型构造函数;...转为 M x N 的矩阵;ToString函数的重写;CompareTo比较器;
主要内容包括程序设计基础知识、类与对象的基本概念、继承与多态、输入输出流,以及泛型程序设计。此外,本教材还介绍了一些常用数据结构基础知识,使得读者学习本书后,能够解决一些简单的实际问题。整套教材语言...
Java51.4.1 使用Object表示泛型1.4.2 基本类型的包装1.4.3 使用接口类型表示泛型1.4.4 数组类型的兼容性1.5 利用Java5泛性实现泛型特性成分1.5.1 简单的泛型类和接口1.5.2 自动装箱/拆箱1.5.3 带有限制的通配符...
1.5.1 简单的泛型类和接口 1.5.2 自动装箱/拆箱 1.5.3 带有限制的通配符 1.5.4 泛型static方法 1.5.5 类型限界 1.5.6 类型擦除 1.5.7 对于泛型的限制 1.6 函数对象 小结 练习 参考文献 第2章 算法分析 2.1 数学...
Java51.4.1 使用Object表示泛型1.4.2 基本类型的包装1.4.3 使用接口类型表示泛型1.4.4 数组类型的兼容性1.5 利用Java5泛性实现泛型特性成分1.5.1 简单的泛型类和接口1.5.2 自动装箱/拆箱1.5.3 带有限制的通配符...
对于q的泛型值,可以使用Sklyanin的代数Bethe ansatz(ABA)形式来构造Uqsl(2)-恒定长度为N的不变自旋1/2 XXZ链的传输矩阵的所有特征向量。 但是,当q为单位根(q =eiπ/ p,整数p≥2)时,贝特方程获取连续解,...
《C 程序设计语言》(原书第4版)是C 领域最经典的参考书,介绍了C 11的各项新特性和新功能。全书共分四部分。第一部分(第1~5章)是引言,包括C 的背景知识,C 语言及其标准库的简要介绍;...第29章 一个矩阵设计 701