Scientific programming in C++

CppMatLib

by Nikolai Shokhirev

Up Scientific Programming

Up: Scientific programming
Previous: Project environment
Next: C++ notes, tips

Introduction

Why do we need home-made C++ libraries at all?

The language itself does not have a decent support for numerical objects (complex numbers, vectors, matrices, etc). The STL also does not solve all problems. This situation is reflected in the variety coexisting libraries (see e.g. C++ links).

Complex numbers

Option 1. Use STL complex:

  #include <complex>
  using namespace std;
  typedef complex<double> Complex;
  Complex a, b, c;

Remarks

  1. Type choice: complex<T>. Here T is a scalar type. All integer types should be excluded because in numerical calculation only floating point numbers are used. Integers are used for numbering and indexes.
  2. Precision choice. The float type holds ~7 digits,  which is not enough for numeric computations. The double type is sufficient for extensive numeric computations (see also here). Depending on the implementation, long double can be really longer or is simply a synonym for double. The only accurate and portable variant is double.
  3. After we ruled out integer types, the comparison operators, == and !=, make no sense. For floating-point numbers, the comparison functions with tolerance parameters should be used instead.

Option 2. Use the structure and complex function libraries:

/* Option 2a C style */
struct complex {
double Re;
double Im;
};
typedef struct complex Complex;
Complex a, b, c;

or

/* Option 2b C++ style */
struct Complex {
double Re;
double Im;
};
Complex a, b, c;

This approach is implemented in the files below   

 View source   Complex.h, Complex.cpp, MathUtils.h, MathUtils.cpp, StringUtils.h, StringUtils.cpp, test.cpp  
 Download source   CppComplexStruct.zip ( includes make file for g++ ).

To build the project, cd to unzipped directory and run mingw32-make:

C:\WINDOWS\system32>cd C:\MinGW\projects\CppComplexStruct

C:\MinGW\projects\CppComplexStruct>mingw32-make
g++ -c test.cpp
g++ -c Complex.cpp
g++ -c MathUtils.cpp
g++ -c StringUtils.cpp
g++ test.o Complex.o MathUtils.o StringUtils.o  -o test

C:\MinGW\projects\CppComplexStruct>

Then run test.

C:\MinGW\projects\CppComplexStruct>test
c0 = c2 : true
Cadd(c0, c1) : true
Cadd(c0, -1.0) : true
Cadd(1.0, c1) : true
Cadd(Real(1),Img(2)) : true
Csub(c0, c1) : true
Csub(c0, 1.0) : true
Csub(3.0, c1) : false
c2 = conjug(c1) : true
c0*conjug(c0)=mod2(c0) : true
Cmul(c0, c1) : true
Cmul(c0, 3.0) : true
Cmul(3.0, c1) : true
Cdiv(c0, c0) : true
Cdiv(c1, c0) : true
(3.0/c0)*c0 : true
(c0/3.0)*3.0 : true
Csqrt(c0) = 1.27202+i*0.786151 : true

Option 3. Take advantage of C++ operator overloading and extend the option 2b.

We are going to keep the object simple and will not implement unnecessary features:

  1. No increment/decrement operators ++, --
  2. No comparison operators ==, !=, >, <
  3. No accessors (getters/setters or selectors/modifiers) for the real and imaginary parts.

The first two features make no sense for the complex numbers. The third one formally violate one of the Object-oriented dogmas. The accessor idiom is intended to hide the details of private members and protect them (e.g. by range checking). In case of Re and Im there is no structure to hide and they accept any floating point values.

The implementation of the first two features fall into the category of "Speculative generality" and the third one into the "Cargo cult programming". 

Variant 1. "Classical" ("Orthodox")

Implemented as member functions

Implemented as global (but not necessarily friends because Re and Im are public and there is no need to access private fields).

 View source    Complex.h, Complex.cpp, MathUtils.h, MathUtils.cpp, StringUtils.h, StringUtils.cpp, Tests.cpp, GenTests.h, GenTests.cpp
 Download source   CppComplexVar1.zip ( includes make file for g++ ).

Variant 2. Via compound assignment operators

In this approach the compound assignment operators

 +=, -=, *=, /= 

are implemented first and the rest are expressed in terms of the above operators (see [2-4]).

Implemented as member functions

Implemented as global functions:

 View source   Complex.h, Complex.cpp, MathUtils.h, MathUtils.cpp, StringUtils.h, StringUtils.cpp, Tests.cpp, GenTests.h, GenTests.cpp
 Download source   CppComplexVar2.zip ( includes make file for g++ ).

 

Vectors and Matrices

in progress . . .  for now visit my  Programming Tools page.

Variant 1.

in progress . . .

Variant 2. Via compound assignment operators

in progress . . .

 

References

  1. C++ Operator Overloading Tutorial by Mayukh Bose.
  2. Overloading Operator + the Right Way By Danny Kalev, C++ Pro.
  3. Yet another complex number class in C++ by Clment Lavoillotte.
  4. C++ Operator Overloading Guidelines by Donnie Pinkston.
  5. Operator Overloading in C++ by Ben Watson.
  6. C++ notes. Operator overloading. by Fred Swartz.
  7. C++: Overloading Derived Class Assignment http://www.fredosaurus.com/notes-cpp/oop-overloading/overloadassign2.html
  8. The ABCs of Writing C++ Classes. Constructors, Destructors, and Assignment Operators byG. Bowden
  9. The Anatomy of the Assignment Operator by Richard Gillam
  10. Introduction to C++ for Financial Engineers: An Object-Oriented Approach by Daniel J. Duff
Up Scientific Programming

Up: Scientific programming
Previous: Project environment
Next: C++ notes, tips

Programming toolsScientific programming | Sample code

Home | Resumé |  Shokhirev.com |  Computing |  Links |  Publications

Nikolai Shokhirev, 2004-2009