- Numerical Recipes, Ch1
@(Cabinet)[cpp_num, aca_book, published_gitbook]
date: 2016-05-17
Numerical Recipes, Ch1
struct vs class
The way this book treats numerical programming is similar to what Lua is doing. Lua uses table
, where in this book they recommend using struct
instead of class
.
struct Twovar {
Doub a, b; //Doub is defined in nr3.h
Twovar(const Doub aa, const Doub bb) : a(aa), b(bb) {}
Doub sum() {return a+b;}
Doub diff() {return a-b;}
};
Then we use it like:
Twovar mytwovar(3., 5.);
which invokes the Twovar
constructor and creates an instance of a Towvar
.
Objects, Classes, and Inheritance
Simple uses of objects
struct Erf {
Doub erf(Doub x);
Doub erfc(Doub x);
Doub inverf(Doub p);
Doub erfccheb(Doub z);
};
But why objects?
These methods share some code and also use common code in the last method, erfccheb
, which the user will normally ignore completely.
Scope rules and object destruction
We can make a good use of { }
Functions and functors
A functor is simply an object in which the operato ()
has been overloaded to play the role of returning a function value. can be coded as
struct Square {
Doub operator()(const Doub x) {
return x*x;
}
};
To use this with a quadrature of other routine, we can declare an instance of Square
Square g;
and pass g
to the routine.
To allow it to accept either functions or functors, we instaed make it a templated function:
template <class T>
Doub someQuadrature(T &func, const Doub a, const Doub b);
Inheritance
Is-a relationships
The diversity of tasks in scientific computing does not lend itself to strict is-a
hierarchies.
Prerequisite relationships
Partial abstraction
Vector and Matrix Objects
Typedefs
typedef
type-indirection is resolved at compile time so that there is no run-time performance penalty.
Those ending in a p
have elements that are pointers, e.g., VecCharp
is a vector of pointers to char
, that is, char *
.
For every vector and matrix type above, we also define types with the same names plus one of the suffixes _I
, _O
, and _IO
, for example VecDoub_IO
. We use these suffixed types for specifying argument types in function definitions. The meaning, respectively, is that the argument is input
, output
, or both input and output
. The _I
types are automatically defined to be const
.
Required methods for vector and matrix classes
Some further conventions and capabilities
Error and exception handling
This book uses throw
like
throw("error foo in routine bah");
Const correctness
We are firm believers in using const
wherever possible, to achieve what is called const correctness
.
Even if an argument is passed by value to a function, we still use const
, for example:
Doub f(const Doub x);
Abstract base class (ABC) or template?
The performance consideration regarding which to use is rarely significant. The deciding factors relate to software engineering.
NaN and floating point exceptions
According to the IEEE standard, NaN
is guaranteed to be the only value that is not equal to itself!
if (x!=x) {...} // it's a NaN!
quiet NaN
is supposed to be for uses like those above: you can set them, test them and other stuff.
signalling NaN
is supposed to signal exceptions. signalling NaN
should be generated by invalid operations, such as the square root or logarithm of a negative number, or pow(0., 0.)
.
Miscellany
Seldom do bounds checking.
Large vectors and matrices are passed by reference.
3D arrays
I remember that when I was doing tensor decomposition, there are some libraries build on MATLAB.
In this book, it declares a vector of matrices:
vector<MatDoub> threedee(17);
for (Int i=0;i<17;i++) threedee[i].resize(19,21);