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