nr3.h的实现

Adam posted @ Sat, 03 Mar 2012 00:37:47 +0800 in Numerical Receipes with tags c++ NumericalAlgebra , 2740 readers

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

 

 


Login *


loading captcha image...
(type the code from the image)
or Ctrl+Enter