nr3.h可能会在以后被改动,如果改动了,就会在本文中添加或者修改。
在书中它是用nr3.h这个头文件的,名字便不再去改了。它是用类和泛型实现Vector和Matrix的,根据书上提供的几个接口,大致实现了一下这个东西。
Version 1.0
/** *@file nr3.h */ #ifndef NR3_H_INCLUDED #define NR3_H_INCLUDED /**Switches*/ #define _USEMACROFUNCTIONS_//See "nr3BasicFunctions.h" /*END_Switches*/ #include "nr3UserTypes.h" #include "nr3ErrorHandle.h" #include "nr3NRvector.h" #include "nr3NRmatrix.h" #include "nr3BasicFunctions.h" #include "readMatrix.h" #include "readVector.h" #include "printMatrix.h" #include "printVector.h" #endif // NR3_H_INCLUDED
/** *@file nr3BasicFunctions.h */ #ifndef NR3BASICFUNCTIONS_H_INCLUDED #define NR3BASICFUNCTIONS_H_INCLUDED #include <limits.h> #include <cmath> /**Basic Functions*/ #ifdef _USEMACROFUNCTIONS_ //Macro Functions #else //Inline Functions #endif //_USEMACROFUNCTIONS_ //Other Functions template <class T> inline void SWAP(T &a, T &b){ T temp = a; a = b; b = temp; } inline int abs(int x){ //return abs(x) without using branching. int mask = ((int)x >> (sizeof(int) * CHAR_BIT - 1)); return (x + mask) ^ mask; } /*END_Basic Functions*/ #endif // NR3BASICFUNCTIONS_H_INCLUDED
/** *@file nr3ErrorHandle.h */ #ifndef NR3ERRORHANDLE_H_INCLUDED #define NR3ERRORHANDLE_H_INCLUDED #include <stdio.h> #include <stdlib.h> /**Error Handle*/ #define NRthrow(message) {printf("ERROR: %s\n in file %s at line %d\n", message, __FILE__, __LINE__);exit(1);} /*END_Error Handle*/ #endif // NR3ERRORHANDLE_H_INCLUDED
/** *@file nr3UserTypes.h */ #ifndef NR3USERTYPES_H_INCLUDED #define NR3USERTYPES_H_INCLUDED #include "nr3NRvector.h" #include "nr3NRmatrix.h" /**User_Types*/ typedef char Char; typedef unsigned char Uchar; typedef int Int; typedef unsigned int Uint; typedef long long int Llong; typedef unsigned long long int Ullong; typedef double Doub; typedef long double Ldoub; typedef bool Bool; /*END_User_Types*/ /**Vector Types & Matrix Types*/ typedef NRvector<Int> VecInt, VecInt_O, VecInt_IO; typedef const NRvector<Int> VecInt_I; typedef NRvector<Doub> VecDoub, VecDoub_O, VecDoub_IO; typedef const NRvector<Doub> VecDoub_I; /*----------*/ typedef NRmatrix<Int> MatInt, MatInt_O, MatInt_IO; typedef const NRmatrix<Int> MatInt_I; typedef NRmatrix<Doub> MatDoub, MatDoub_O, MatDoub_IO; typedef const NRmatrix<Doub> MatDoub_I; /*END_Vector Types & Matrix Types*/ #endif // NR3USERTYPES_H_INCLUDED
/** *@file nr3NRvector.h */ #ifndef NR3NRVECTOR_H_INCLUDED #define NR3NRVECTOR_H_INCLUDED /**NRvector*/ template <class T> //NRvector Class class NRvector { private: int nn; ///Size of array, indices 0..nn-1; T *v; ///Pointer to data array public: NRvector(); ///Default constructor explicit NRvector(int n); ///Construct vector of size n NRvector(int n, const T &a); ///Initialize to constant value a. NRvector(int n, const T *a); ///Initialize to values in C-Style array a. NRvector(const NRvector &rhs); ///Copy constructor NRvector & operator = (const NRvector &rhs); ///Assignment operator. typedef T value_type; ///Make T available inline T & operator[] (const int i); ///Return element number i. inline const T & operator[] (const int i) const; ///const version inline int size() const; ///Return size of vector. void resize(int newn); ///Resize, losing contents void assign(int newn, const T &a); ///Resize and assign a to every element. ~NRvector(); ///Destructor }; template <class T> NRvector<T> :: NRvector() : nn(0), v(0){ ///Default constructor } template <class T> NRvector<T> :: NRvector(int n) : nn(n), v(n > 0 ? new T[n] : NULL){ ///Construct vector of size n } template <class T> NRvector<T> :: NRvector(int n, const T &a) : nn(n), v(n > 0 ? new T[n] : NULL){ ///Initialize to constant value a. for(int i = 0; i < nn; ++i) v[i] = a; } template <class T> NRvector<T> :: NRvector(int n, const T *a) : nn(n), v(n > 0 ? new T[n] : NULL){ ///Initialize to values in C-Style array a. for(int i = 0; i < nn; ++i) v[i] = *a++; } template <class T> NRvector<T> :: NRvector(const NRvector &rhs) : nn(rhs.size()), v(new T[nn]){ ///Copy constructor for(int i=0; i < nn; ++i) v[i] = rhs[i]; } template <class T> NRvector<T> & NRvector<T> :: operator = (const NRvector &rhs){ ///Assignment operator /* *Test size first. If size are the same, copy; else resize then copy. */ if(nn != rhs.size){ if(v != NULL) delete [] (v); nn = rhs.size; v = new T[nn]; } for (int i = 0; i < nn; ++i) v[i]=rhs[i]; return *this; } template <class T> inline T & NRvector<T> :: operator[] (const int i) { ///Return element number i. return v[i]; } template <class T> inline const T & NRvector<T> :: operator[] (const int i) const{ ///const version return v[i]; } template <class T> inline int NRvector<T> :: size() const{ ///Return size of vector. return nn; } template <class T> void NRvector<T> :: resize(int newn){ ///Resize, losing contents if(v != NULL) delete [] (v); nn = newn; v = new T[nn]; } template <class T> void NRvector<T> :: assign(int newn, const T &a){ ///Resize and assign a to every element. /* *Test size first. If size are the same, just assign; else resize then assign. */ if(nn != newn){ if(v != NULL) delete [] (v); nn = newn; v = new T[nn]; } for (int i=0; i<nn; i++) v[i] = a; } template <class T> NRvector<T> :: ~NRvector(){ ///Destructor if(v != NULL) delete [] (v); } /*END_NRvector*/ #endif // NR3NRVECTOR_H_INCLUDED
个人比较困惑的是在nr3NRmatrix.h中,对构造一个n*m的matrix是这样实现的(这是书上给出的实现方法):
template <class T> NRmatrix<T> :: NRmatrix(int n, int m) : nn(n), mm(m), v(n>0 ? new T*[n] : NULL){ int i, nel = nn*mm; if(v) v[0] = (nel > 0) ? new T[nel] : NULL; for(i = 1; i < nn; ++i) v[i] = v[i-1] + mm; }
它为什么不直接一开始就new一个n*m的空间,却选择了先new了n个指针,然后再一下子new出n*m的空间。非常搞不懂的。
/** *@file nr3NRmatrix.h */ #ifndef NR3NRMATRIX_H_INCLUDED #define NR3NRMATRIX_H_INCLUDED /**NRmatrix*/ template <class T> class NRmatrix { private: int nn; ///Number of rows and columns. Index range is 0..nn-1, 0..mm-1. int mm; T **v; ///Storage for data. public: NRmatrix(); ///Default constructor NRmatrix(int n, int m); ///Construct n*m matrix. NRmatrix(int n, int m, const T &a); ///Initialize to constant value a. NRmatrix(int n, int m, const T *a); ///Initialize to values in C-Style array a. NRmatrix(const NRmatrix &rhs); ///Copy constructor. NRmatrix & operator = (const NRmatrix &rhs); ///Assignment operator. typedef T value_type; ///Make T available. inline T* operator[] (const int i); ///Subscripting: pointer to row i. inline const T* operator[] (const int i) const; ///const version. inline int nrows() const; ///Return number of rows. inline int ncols() const; ///Return number of columns. void resize(int newn, int newm); ///Resize, losing contents. void assign(int newn, int newm, const T &a); ///Resize and assign a to every element. ~NRmatrix();///Destructor }; template <class T> NRmatrix<T> :: NRmatrix() : nn(0), mm(0), v(0) { ///Default constructor } template <class T> NRmatrix<T> :: NRmatrix(int n, int m) : nn(n), mm(m), v(n>0 ? new T*[n] : NULL){ ///Construct n*m matrix. /* *The private variable **v points not to the data but rather to an array of pointers to *the data rows. Memory allocation of this array is separate from the allocation of space *for the actual data. The data space is allocated as a single block, not separately for each *row. For matrices fo zero size, we have to account for the separate possibilities that *there are zero rows, or that there are a finite number of rows, but each with zero columns. */ int i, nel = nn*mm; if(v) v[0] = (nel > 0) ? new T[nel] : NULL; for(i = 1; i < nn; ++i) v[i] = v[i-1] + mm; } template <class T> NRmatrix<T> :: NRmatrix(int n, int m, const T &a) : nn(n), mm(m), v(n>0 ? new T*[n] : NULL){ ///Initialize to constant value a. int i, j, nel = nn*mm; if(v) v[0] = (nel > 0) ? new T[nel] : NULL; for(i = 1; i < nn; ++i) v[i] = v[i-1] + mm; for(i = 0; i < nn; ++i) for(j = 0; j < mm; ++j) v[i][j] = a; } template <class T> NRmatrix<T> :: NRmatrix(int n, int m, const T *a) : nn(n), mm(m), v(n>0 ? new T*[n] : NULL){ ///Initialize to values in C-Style array a. int i, j, nel = nn*mm; if(v) v[0] = (nel > 0) ? new T[nel] : NULL; for(i = 1; i < nn; ++i) v[i] = v[i-1] + mm; for(i = 0; i < nn; ++i) for(j = 0; j < mm; ++j) v[i][j] = *a++; } template <class T> NRmatrix<T> :: NRmatrix(const NRmatrix &rhs) : nn(rhs.nrows()), mm(rhs.ncols()), v(nn>0 ? new T*[nn] : NULL) { ///Copy constructor int i, j, nel = mm*nn; if(v) v[0] = (nel > 0) ? new T[nel] : NULL; for(i = 1; i < nn; ++i) v[i] = v[i-1] + mm; for(i = 0; i < nn; ++i) for(j = 0; j < nn; ++j) v[i][j] = rhs[i][j]; } template <class T> NRmatrix<T> & NRmatrix<T> :: operator = (const NRmatrix<T> &rhs){ ///Assignment operator /* *Test size first. If size are the same, copy; else resize then copy. */ int i,j; if(nn != rhs.nrows() || mm != rhs.ncols()){ if(v != NULL){ delete [] (v[0]); delete [] (v); } nn = rhs.nrows(); mm = rhs.ncols(); v = new T*[nn]; v[0] = new T[nn*mm]; } for(i = 1; i < nn; ++i) v[i] = v[i-1] + mm; for(i = 0; i < nn; ++i) for(j = 0; j < mm; ++j) v[i][j] = rhs[i][j]; return *this; } template <class T> inline T* NRmatrix<T> :: operator[] (const int i){ ///Subscripting: pointer to row i return v[i]; } template <class T> inline const T* NRmatrix<T> :: operator[] (const int i) const{ ///const version. return v[i]; } template <class T> inline int NRmatrix<T> :: nrows() const{ ///Return number of rows return nn; } template <class T> inline int NRmatrix<T> :: ncols() const{ ///Return number of columns return mm; } template <class T> void NRmatrix<T> :: resize(int newn, int newm){ ///Resize, losing contents if(nn != newn || mm != newm){ if(v != NULL){ delete [] (v[0]); delete [] (v); } nn = newn; mm = newm; v = new T*[nn]; v[0] = new T[nn*mm]; for(int i = 1; i < nn; ++i) v[i] = v[i-1] + mm; } } template <class T> void NRmatrix<T> :: assign(int newn, int newm, const T &a){ ///Resize and assign a to every element int i,j; if(nn != newn || mm != newm){ if(v != NULL){ delete [] (v[0]); delete [] (v); } nn = newn; mm = newm; v = new T*[nn]; v[0] = new T[nn*mm]; for(int i = 1; i < nn; ++i) v[i] = v[i-1] + mm; } for(i = 0; i < nn; ++i) for(j = 0; j < mm; ++j) v[i][j] = a; } template <class T> NRmatrix<T> :: ~NRmatrix(){ if(v != 0){ delete [] (v[0]); delete [] (v); } } /*END_NRmatrix*/ #endif // NR3NRMATRIX_H_INCLUDED
Version 1.1
/** *@file readMatrix.h */ #ifndef READMATRIX_H_INCLUDED #define READMATRIX_H_INCLUDED #include "nr3NRmatrix.h" #include <iostream> #include <fstream> #include <string> using namespace std; template <class T> void readMatrix_file(const string filename, NRmatrix<T> &m){ ifstream fp(filename); if(fp.fail()){ NRthrow("Data File not found."); } for(int i = 0; i < m.nrows(); ++i) for(int j = 0; j < m.ncols(); ++j) fp >> m[i][j]; }//readMatrix_file(const string filename, NRmatrix<T> &m) template <class T> void readMatrix_console(NRmatrix<T> &m){ cout << "Please Input the Matrix Data: " << endl; for(int i = 0; i < m.nrows(); ++i) for(int j = 0; j < m.ncols(); ++j) cin >> m[i][j]; }//readMatrix_console(NRmatrix<T> &m) #endif // READMATRIX_H_INCLUDED
/** *@file printMatrix.h */ #ifndef PRINTMATRIX_H_INCLUDED #define PRINTMATRIX_H_INCLUDED #include "nr3NRmatrix.h" #include <iostream> #include <fstream> #include <string> using namespace std; template <class T> void printMatrix_file(const string filename, NRmatrix<T> &m){ ofstream fp(filename); if(fp.fail()) NRthrow("Data File not found."); for(int i = 0; i < m.nrows(); ++i) { for(int j = 0; j < m.ncols(); ++j) { fp << m[i][j] << " "; } fp << endl; } } template <class T> void printMatrix_console(NRmatrix<T> &m){ for(int i = 0; i < m.nrows(); ++i) { for(int j = 0; j < m.ncols(); ++j) { cout << m[i][j] << " "; } cout << endl; } } #endif // PRINTMATRIX_H_INCLUDED
/** *@file readVector.h */ #ifndef READVECTOR_H_INCLUDED #define READVECTOR_H_INCLUDED #include "nr3NRvector.h" #include <iostream> #include <fstream> #include <string> using namespace std; template <class T> void readVector_file(const string filename, NRvector<T> &v){ ifstream fp(filename); if(fp.fail()){ NRthrow("Data File not found."); } //if for(int i = 0; i < v.size; ++i) fp >> v[i]; } //readVector_file(const string filename, NRvector<T> &v) template <class T> void readVector_console(NRvector<T> &v){ cout << "Please Input the Vector Data: " << endl; for(int i = 0; i < v.size(); ++i) cin >> v[i]; }//readVector_console(NRvector<T> &v) #endif // READVECTOR_H_INCLUDED
/** *@file printVector.h */ #ifndef PRINTVECTOR_H_INCLUDED #define PRINTVECTOR_H_INCLUDED #include "nr3NRvector.h" #include <iostream> #include <fstream> #include <string> using namespace std; template <class T> void printVector_file(const string filename, NRvector<T> &v){ ofstream fp(filename); if(fp.fail()) NRthrow("Data File not found."); for(int i = 0; i < v.size(); ++i) fp << v[i] << " "; fp << endl; } template <class T> void printVector_console(NRvector<T> &v){ for(int i = 0; i < v.size(); ++i) cout << v[i] << " "; cout << endl; } #endif // PRINTVECTOR_H_INCLUDED