matlib数学库与Mm数据类型

从Test1和Test2工程中可知,MATcom与VC++中数据交换,是基于MAThtools提供的MATcom C数学库函数及其数据类型Mm的。因此,本节对MATcom C数学库函数及其数据类型Mm作简单介绍,详细情况可查阅%MATcom4.5%\lib\matlib.h文件。

MATcom C数学库函数是一个丰富的数学库,它提供的数学函数约600个,这些数学函数可分为:矩阵基础类、系统常数、特殊函数、异常处理函数、矩阵生成函数、操作系统资源函数、数值计算函数、数学函数、矩阵操作函数、矩阵属性函数、图形函数、颜色函数、用户介面函数、判断函数族、mex函数、字符串函数、字符串函数和类型转换函数等十几大类。其中最常用是的矩阵基础类函数和字符串函数。

MATcom矩阵基础类数据类型为Mm,与C++程序中的类一样,采用class定义。因而,用户可像C++中的类一样用Mm来定义数据对象和使用Mm类数据对象,Mm类还封装众多的Mm类对象操作函数和析构函数,当程序程序终止时,程序调用Mm类的析构函数释放Mm数据对象所占的内存空间。下面列出了Mm类中常用的成员变量及操作函数。

code.vc
class Mm {
friend class Mr; ////////////// Mr为matlib.h中定义的另一个类
protected:  //////////////////// 受保护成员变量
  int ndims;   ////////////// 维数
  int dims[max_ndims]; //////////// 维数数组,存放对象每一维的大小
  int p; /////////////////////////// 指向Mm对象的指针
  int* pc; /////////////////////// 指向Mm对象中复数指针
  m_type* pr; ////////////////// 指向Mm对象中实部指针
  m_type* pi; ////////////////// 指向Mm对象中虚部指针
  const char* self_name; //////////////类名
  const char** fields; ////////////字段名
  int nfields; //////////////////////// 字段数
  int classid;  ////////////////////// 类ID值
………….
public: ////////////////////////////////// 公有函数
  M_types flags; ///////////////// 数据符号
  DLLI Mm(); ///////////////////////////////无参数构造函数,用于类对象声明
//////////////////////////////////////////////////////带参数的构造函数
  DLLI Mm(int isc, int iss, int nonzeros, int nrows, int ncols, mt_matrix_types new_type=mt_double_matrix);

其中:isc—是否为复数矩阵;iss-是否为字符串矩阵;nonzeros-是否为非数值矩阵;

nrows-矩阵行数;  ncols-矩阵列数;   mt_double_matrix-双精度矩阵

code.vc
  DLLI Mm(int isc, int iss, int nonzeros, int new_ndims, const int new_dims[max_ndims], mt_matrix_types new_type=mt_double_matrix);
  DLLI Mm(i_o_t, const char* mname, int isglobal);
  DLLI Mm(const char* mname, int m, int n); /////////////////
  DLLI Mm(int aisc, cMm x, cMm y, cMm dim1, op_t op, int do_dim, Mm& minmax_idx);
  DLLI Mm(m_type src);
  DLLI Mm(cMm src);
  DLLI Mm(cMm src, const char* mname);
  DLLI Mm(const Mc& src);
  DLLI ~Mm(); //////////////////////////// 析构函数,程序终止时调用析构函数进行内存释放
  Mm RDLLI operator =(cMm src);///////赋值操作符重载
  inline int DLLI rows() const { return dims[0]; } //////////返回矩阵的行数
  inline int DLLI cols() const { return dims[1]; }  /////////返回矩阵的列数
  int DLLI size() const; ////////返回Mm对象的元素个数大小
  int DLLI size(int dim) const; /////返回Mm对象每一维的元素个数
  int DLLI vectordim() const; /////返回向量的维数
  const char PDLLI getname() const { return self_name; }///获取类名
  void DLLI setname(const char* new_name);////////////////////设置新的类名
  int DLLI isstr() const { return(flags.str!=0); }////判断是否为字符矩阵
  inline int DLLI issparse() const { return(flags.sparse!=0); }////判断是否为稀疏矩阵
  inline int DLLI isglobal() const { return(flags.global!=0); }////判断是否为全局矩阵
  inline int DLLI isstruct() const { return(fields!=NULL); }////判断是否为结构体矩阵
  inline int DLLI isc() const { return(pi!=NULL); }////判断是否为复数矩阵
  inline int DLLI islogical() const { return(flags.logical!=0); }////判断是否为逻辑变量矩阵
  inline int RDLLI getndims() const { return(int&)ndims; }/////获取维数数组指针
  void DLLI setstr(int newd);////////设置字符串
  void DLLI setsparse(int sp);/////设置稀疏矩阵
  void DLLI setlogical(int newd);/////设置逻辑变量
  inline M_types RDLLI getflags() { return flags; }///获取数据符号
  inline m_type PDLLI getpr(m_type*) const { return(m_type*)pr; }///获取实部指针
  inline m_type PDLLI getpi(m_type*) const { return(m_type*)pi; }///获取虚部指针
  m_type PDLLI addr() const; /////////// 获取指向Mm对象的实部指针起始地址
  m_type PDLLI addr(int i0) const; ///获取指向Mm对象的虚部指针起始地址
  m_type PDLLI addr(int i0,int i1) const; //获取指向Mm对象(i0,i1) 实部地址
  m_type PDLLI addi() const; /////////// 获取指向Mm对象的虚部起始地址
  m_type PDLLI addi(int i0) const; /// 获取指向Mm对象中第i0个元素的虚部地址
  m_type PDLLI addi(int i0,int i1) const; /获取指向Mm对象(i0,i1) 虚部地址
  int DLLI getreal(int force=0) const;/////////获取实部
  int DLLI getcomplex();///////////////////////////获取复数
  int DLLI findfield(const char* field, int err) const;////查找字符串
  const char PDLLI getfield(int i) const;//////////////////// 按索引号获取字符串指针
  int DLLI addfield(const char* field,int quick);///////// 按索引号添加字符串
  int DLLI getclassid() const { return classid; }/////////获取类ID
  void DLLI setclassid(int new_classid) { classid=new_classid; }///设置新的ID
……
}; // M

在上述Mm类定义基础上,举例说明Mm类对象的定义、赋值和运算等操作。下面程序清单为VC++的主要程序片段。

(1)使用Mm类,必须包含头文件:

code.vc
#include “matlib.h”
////////////////////////////////

(2) Mm对象定义、赋值、运算等举例

code.vc
//////////////Mm对象定义、赋值、运算等举例
int i,j,m,n;
double **A1,**B1,**C1,**D1;
Mm X1,X2,X3,X4,X5; ////用无参数的构造函数定义Mm类对象
FILE* fp;
if((fp=fopen("Mm.txt","w"))==NULL){MessageBox("Can't open R_R Input File");exit(0);}
m=n=5;
A1=new double*[m];for(i=0;i<m;i++)A1[i]=new double[n];//C动态数组由用户创建并分配地址
B1=new double*[m];for(i=0;i<m;i++)B1[i]=new double[n];
C1=new double*[m];for(i=0;i<m;i++)C1[i]=new double[n];
D1=new double*[m];for(i=0;i<m;i++)D1[i]=new double[n];
X1=magic(n); ///////////生成一个3阶魔方矩阵,由MATlib矩阵直接赋值,赋值时隐含矩阵方式初始化
X2=X1;      /////Mm类实现了操作符"="重载,赋值时隐含矩阵方式初始化
//Mm ii,jj;
X3=X1+X2; /////Mm类实现了操作符"+"重载,赋值时隐含矩阵方式初始化
X4=X1*X2; /////Mm类实现了操作符"*"重载(矩阵乘法),赋值时隐含矩阵方式初始化
for(i=0;i<n;i++)for(j=0;j<n;j++)
{A1[i][j]=*X1.addr(i+1,j+1);// .addr(i+1,j+1)获取(i+1,j+1)元素实部地址,并将数据赋给A1[i][j]
B1[i][j]=*X3.addr(i+1,j+1);// 组下标从0开始,而Mm矩阵下标从1开始,故(i+1,j+1)与[i][j]对应
C1[i][j]=X4.r(i+1,j+1);    // .r(i+1,j+1)直接读取Mm对象的实部(i+1,j+1)中数据赋给C1[i][j]
D1[i][j]=(*X1.addr(i+1,j+1))*(*X2.addr(i+1,j+1));
*X1.addr(i+1,j+1)=D1[i][j];//X5虽由Mm定义对象,但未经矩阵方式初化而直接引用Mm对象中元素,
             ///////////////////这种方式极易出错,建议不使用未经矩阵方式初始化的Mm对象
}
///////////////////输出操作
fprintf(fp,"\n Output X1 by *X1.addr(i+1,j+1):\n");
for(i=0;i<n;i++){fprintf(fp,"\n");for(j=0;j<n;j++)fprintf(fp," %8.3lf ",*X1.addr(i+1,j+1));}
fprintf(fp,"\n Output X2 by X2.r(i+1,j+1) :\n");
for(i=0;i<n;i++){fprintf(fp,"\n");for(j=0;j<n;j++)fprintf(fp," %8.3lf ",X2.r(i+1,j+1));}
fprintf(fp,"\n Output X1+X2 by B1[i][j]:\n");
for(i=0;i<n;i++){fprintf(fp,"\n");for(j=0;j<n;j++)fprintf(fp," %8.3lf ",B1[i][j]);}
fprintf(fp,"\n Output X1*X2 by C1[i][j]:\n");
for(i=0;i<n;i++){fprintf(fp,"\n");for(j=0;j<n;j++)fprintf(fp," %8.3lf ",C1[i][j]);}
///////////////////////////////////////////////
fprintf(fp,"\n Output X1.*X2 by D1[i][j] :\n");
for(i=0;i<n;i++){fprintf(fp,"\n");for(j=0;j<n;j++)fprintf(fp," %8.3lf ",D1[i][j]);}
fprintf(fp,"\n Output X1.*X2 by D1[i][j] :\n");
for(i=0;i<n;i++){fprintf(fp,"\n");for(j=0;j<n;j++)fprintf(fp," %8.3lf ",*X1.addr(i+1,j+1));}
//////////D1[i][j]输出数据应与*X1.addr(i+1,j+1)输出数据相同,但程序运行结果不同,表明,直接
//引用未经矩阵方式初始化的Mm对象元素,易导致错误结果,*X1.addr(i+1,j+1)输出结果错误
Mm Y1=ones(n); ///定义对象时隐含矩阵方式初始化
Mm Y2(" &quot;,m,n); ///或采用带参数m,n的构造函数定义对象
for(i=0;i<n;i++)for(j=0;j<n;j++)
{
 Y1.r(i+1,j+1)=A1[i][j]; ////////可引用Mm对象中元素
 *Y2.addr(i+1,j+1)=B1[i][j];////////可引用Mm对象中元素
}
fprintf(fp,"\n Output Y1 by Y1.r(i+1,j+1) :\n");
for(i=0;i<n;i++){fprintf(fp,"\n");for(j=0;j<n;j++)fprintf(fp," %8.3lf ",Y1.r(i+1,j+1));}
fprintf(fp,"\n Output Y2 by *Y2.addr(i+1,j+1) :\n");
for(i=0;i<n;i++){fprintf(fp,"\n");for(j=0;j<n;j++)fprintf(fp," %8.3lf ",*Y2.addr(i+1,j+1));}
//////////////////// Y1.r(i+1,j+1)和*Y2.addr(i+1,j+1)输出正确
//////////////////// 使用宏BR()对Mm对象赋初值举例
Mm Z;
Z=(BR(10),1,3,5,7,semi,6,7,8,9,10,semi,12,17,18,19,20);//赋值时隐含用矩阵初始化Z对象
///BR()宏表示Z矩阵开始,BR(10)表示Z矩阵第一个元素值为10,以后依次将数据赋与Z,
///semi宏表示分号
fprintf(fp,"\n Output Z by *Z.addr(i+1,j+1) :\n");
for(i=0;i<3;i++){fprintf(fp,"\n");for(j=0;j<5;j++)fprintf(fp," %8.3lf ",*Z.addr(i+1,j+1));}
//////////////////// 使用宏M_VECTOR对Mm对象赋初值举例
double E_Vector[6]={1,2,3,4,5,6};
Mm Z1; M_VECTOR(Z1,E_Vector); // 使用宏M_VECTOR对Mm对象赋初值
fprintf(fp,"\n Output Z1 by *Z.addr(1,j+1) :\n");
for(j=0;j<6;j++)fprintf(fp," %8.3lf ",*Z1.addr(1,j+1));
for(i=0;i<m;i++)delete A1[i];delete A1; //由用户释放内存空间,而Mm对象则自动调用
for(i=0;i<m;i++)delete B1[i];delete B1; //析构函数来释放所分配的空间
for(i=0;i<m;i++)delete C1[i];delete C1;
for(i=0;i<m;i++)delete D1[i];delete D1;
/////////////////////字符串操作举例
Mm Z2=("",m,n);
CString str[5];
str[0]="MATcom is based on the Mm";
str[1]="Mm is defined in matlib.h";
str[2]="Read it carefully";
str[3]="Learn the data exhange mechanism";
str[4]="You'll sigh the MATcom's programming is a piece of cake with emotion";
for(i=0;i<m;i++)Z2.addfield(str[i],i+1);///使用.addfield将字符串添加到Mm对象中
fprintf(fp,"\n Output Z2 by Z2.getfield() :\n");
for(i=0;i<m;i++)fprintf(fp,"\n %s \n",Z2.getfield(i));////////按索引号获取字符串指针
fclose(fp); //////////////关闭文件
////////////////////////////////////////////结束//////////////////////////////////////////////

程序运行后的输出结果如下:

code.vc
Output X1 by *X1.addr(i+1,j+1):
   17.000    24.000     1.000     8.000    11.000
   23.000     1.000     7.000    14.000    16.000
    4.000     6.000    13.000    20.000    22.000
   10.000    12.000    19.000    21.000     3.000
   11.000    18.000    21.000     2.000     9.000
 Output X2 by X2.r(i+1,j+1) :
   17.000    24.000     1.000     8.000    11.000
   23.000     1.000     7.000    14.000    16.000
    4.000     6.000    13.000    20.000    22.000
   10.000    12.000    19.000    21.000     3.000
   11.000    18.000    21.000     2.000     9.000
 Output X1+X2 by B1[i][j]:
   34.000    48.000     2.000    16.000    30.000
   46.000    10.000    14.000    28.000    32.000
    8.000    12.000    26.000    40.000    44.000
   20.000    24.000    38.000    42.000     6.000
   22.000    36.000    50.000     4.000    18.000
 Output X1*X2 by C1[i][j]:
 1090.000   900.000   721.000   690.000   820.000
  850.000  1071.000   811.000   720.000   761.000
  700.000   840.000  1141.000   840.000   700.000
  761.000   720.000   811.000  1071.000   850.000
  820.000   690.000   721.000   900.000  1090.000
 Output X1.*X2 by D1[i][j] :
  289.000   576.000     1.000    64.000   221.000
  529.000    21.000    49.000   196.000   256.000
   16.000    36.000   169.000   400.000   484.000
  100.000   144.000   361.000   441.000     9.000
  121.000   324.000   621.000     4.000    81.000
 Output X1.*X2 by D1[i][j] :
  221.000   221.000   221.000   221.000   221.000
  256.000   256.000   256.000   256.000   256.000
  484.000   484.000   484.000   484.000   484.000
    9.000     9.000     9.000     9.000     9.000
   81.000    81.000    81.000    81.000    81.000
 Output Y1 by Y1.r(i+1,j+1) :
   17.000    24.000     1.000     8.000    11.000
   23.000     1.000     7.000    14.000    16.000
    4.000     6.000    13.000    20.000    22.000
   10.000    12.000    19.000    21.000     3.000
   11.000    18.000    21.000     2.000     9.000
 Output Y2 by *Y2.addr(i+1,j+1) :
   34.000    48.000     2.000    16.000    30.000
   46.000    10.000    14.000    28.000    32.000
    8.000    12.000    26.000    40.000    44.000
   20.000    24.000    38.000    42.000     6.000
   22.000    36.000    50.000     4.000    18.000
 Output Z by *Z.addr(i+1,j+1) :
   10.000     1.000     3.000     1.000     7.000
    6.000     7.000     8.000     9.000    10.000
   12.000    17.000    18.000    19.000    20.000
 Output Z1 by *Z.addr(1,j+1) :
    1.000     2.000     3.000     4.000     1.000     6.000
 Output Z2 by Z2.getfield :
 MATcom is based on the Mm
 Mm is defined in matlib.h
 Read it carefully
 Learn the data exhange mechanism
 You'll sigh the MATcom's programming is a piece of cake with emotion