# Advanced Introduction to C++, Scientific Computing and Machine Learning

Claudius Gros, SS 2023

Institut für theoretische Physik
Goethe-University Frankfurt a.M.

# common data structures

• sequence containers
• dynamic arrays  <vector>  : a container, not a math-vector $\ \vec x$
• double ended queues  <deque>  : a  vector  which is dynamic both at end and start
• double linked lists  <list>  : for constant time insertion, for- and backward iteration
• stacks  <stack>  : LIFO (last-in first-out)
• queues  <queue>  : FIFO (first-in first-out)
• heaps  <queue>  priority_queue  : first element is always the largest element
• associative containers (no indices)
• trees  <set>  : ordered sets
• bag of beans  <multiset>  : like  set, multiple copies however allowed
• associative arrays  <map>  : stores data as map:   key $\to$ value

# dynamical arrays using the vector container

• containers come with iterators, encapsulating the pointer increment dynamics
• all containers come with a range of member functions like
.begin()  and  .end()  facilitating iteration
#include <iostream>
#include <stdio.h>
#include <vector>
#define VARIABLE_NAME(x) #x
using namespace std;

int main()
{
vector<int> intVec_1(7,77); // create and initialize a vector of length 7
vector<int> intVec_2;       // empty
intVec_1.at(5) = 55;        // change element
intVec_1.reserve(9);        // reserve memory
//
intVec_2 = intVec_1;        // the assignment operator = has been overwritten
intVec_2.resize(3);         // change size
intVec_2.at(1) = 11;        // change element
intVec_2[2] = 22;           // the [] operator has been overwritten
intVec_2.push_back(44);     // increase size and add an element

//
// change vector size while iterating
//
vector<int>::iterator it;      // iterator in the namespace vector<int>
it = intVec_1.begin();         // start iteration at the begining
while (it != intVec_1.end())
if (*it==55)              // "it" is a pointer
intVec_1.erase(it);     // element gone --> "it" points already to next element
else
it++;                   // pointer arithmetic encapsulated in interator class
//
// === vector output
//
printf("%8s |"," ");
printf("%4s |","(s)");
printf("%4s |","(c)");
for (int index=0; index<intVec_1.size(); ++index)
printf("%4d",index);
printf("\n");
//
printf("%8s |",VARIABLE_NAME(intVec_1));
printf("%4i |",(int)intVec_1.size());             // the actual number of elements
printf("%4i |",(int)intVec_1.capacity());         // total space reserved
for (int index=0; index<intVec_1.size(); ++index)
printf("%4d",intVec_1[index]);
printf("\n");
//
printf("%8s |",VARIABLE_NAME(intVec_2));
printf("%4i |",(int)intVec_2.size());
printf("%4i |",(int)intVec_2.capacity());
for (int index=0; index<intVec_2.size(); ++index)
printf("%4d",intVec_2[index]);
printf("\n");
//
return 1;
}


# associative maps (I)

• no indices $\ \to\$ iteration mandatory
very usefull (human brain works this way)
• (key,value) pairs accessed via an iterator  myIterator  through
myIterator->first  and  myIterator->second
#include <iostream>  // std IO
#include <stdio.h>   // printf, sprintf
#include <map>       // associative maps
#define VARIABLE_NAME(x) #x
using namespace std;

int main()
{
map<string,double> mapOfWords;                 // maping strings to double
mapOfWords.insert(make_pair("earth", 6378.0));           // typical C++: many ways
mapOfWords.insert(pair<string,double>("moon", 1738.0));  // to do the same stuff
mapOfWords["sun"] = 695000.0;                   // standard way of inserting
mapOfWords["earth"] = 6378.01;                  // and overwriting
//
if (mapOfWords.find("venus") == mapOfWords.end()) // searching for a key
mapOfWords["venus"] = 6052.0;
//
// === erasing
//
printf("\n");
if (mapOfWords.erase("venus"))                   // can only erase if existed
printf("\"venus\" found in %s and erased\n",VARIABLE_NAME(mapOfWords));
else
//
// === iterating through the map
//
printf("\n");
map<string, double>::iterator it = mapOfWords.begin();  // instantiate and initialize iterator
while (it != mapOfWords.end())
{
char buffer[50];      // formatting before sending to standard output stream
int n = sprintf(buffer,"%s[\"%s\"] = ",VARIABLE_NAME(mapOfWords),
(it->first).c_str());    // access key (first)
printf("%25s%9.2f\n",buffer,it->second);                // access value (second)
it++;
}
//
// === stuff
//
int beforeSize = mapOfWords.size();
mapOfWords.clear();
int afterSize = mapOfWords.size();
//
string trueFalse = (mapOfWords.empty()) ? "true" : "false";
printf("\n");
printf("before/after size, empty: %i %i  %s\n",beforeSize,afterSize,trueFalse.c_str());
return 1;
}


# associative maps (II)

• store planetatry data in  planets.data
• in modern programming languages, including C++11 (but not the original C++98, we are using here), one can iterate implicitly via
 for (string planet : allPlanets) {..}
# list of planet properties by E.T. Skywatcher
# actually from http://www.astronomynotes.com/solarsys/plantbla.htm
#
# planet mass (relative to earth)
# diameter (km)
# density g/cm3
# oblateness [=(De-Dp)/De]
# rotation [h or d]
# distance (A.U.)
# revolution [d or y]
# eccentricity
# inclination [deg]
# axis tilt [deg]
#
# string double double double double double char double double char double double double
Mercury 0.0553 4880 5.43 0.000 58.81 d 0.387 87.97 d 0.2056 7.0 0.1
Venus 0.815 12104 5.20 0.000 243.69 d 0.723 224.70 d 0.0068 3.4 177.3
Earth 1.000 12742 5.52 0.0034 23.9345 h 1.000 365.26 d 0.0167 0.00 23.45
Mars 0.107 6780 3.93 0.0065 24.623 h 1.524 686.98 d 0.0934 1.85 25.19
Jupiter 317.83 139822 1.33 0.0649 9.925 h 5.203 11.86 y 0.04845 1.305 3.12
Saturn 95.162 116464 0.687 0.098 10.50 h 9.539 29.46 y 0.05565 2.489 26.73
Uranus 14.536 50724 1.32 0.023 17.24 h 19.182 84.01 y 0.0472 0.773 97.86
Neptune 17.147 49248 1.64 0.017 16.11 h 30.06 164.79 y 0.00858 1.773 29.56
Pluto 0.0021 2274 2.05 0.0 6.405 d 39.53 247.68 y 0.2482 17.15 122.46


#include <iostream>  // std IO
#include <stdio.h>   // printf, sprintf
#include <fstream>   // file streams
#include <limits.h>  // INT_MAX, etc
#include <map>       // associative maps
using namespace std;

// --- -----------------
// --- planet data class
// --- -----------------

struct A_Planet
{
double planet_mass;
double diameter;
double density;
double oblateness;
double rotation;
char rotationUnit;
double distance;
double revolution;
char revolutionUnit;
double eccentricity;
double inclination;
double axis_tilt;
string getName(){return planet_name;}       // only way to access name
A_Planet(string name) {planet_name=name;}   // constructor
private:
string planet_name;                         // cannot be changed
};

// --- -----------------------------------
// --- function for skipping comment lines
// --- -----------------------------------

int skipComments(ifstream &fileInputStream)  // passing stream by reference
{
char inChar = fileInputStream.peek();     // peak first char of file
{
inChar = fileInputStream.peek();       // peak first char of line
}
}

// --- ----
// --- main
// --- ----

int main()
{
map<string,A_Planet*> allPlanets;   // mapping string to (pointer to A_Planet)
allPlanets["exoplanet"] = new A_Planet("exoplanet");
//
ifstream myInput("planets.data");   // input file stream for planetary data
//
// --- skip comment lines
//
printf("\n# number of comment lines: %d\n\n",skipComments(myInput));
//
// --- reading data from file
//
string planet_name;
while ( !myInput.eof() )          // reading until end of file
{
myInput >> planet_name;
allPlanets[planet_name] = new A_Planet(planet_name);
printf("%s .. ",planet_name.c_str());
//
myInput >> allPlanets[planet_name]->planet_mass
>> allPlanets[planet_name]->diameter
>> allPlanets[planet_name]->density
>> allPlanets[planet_name]->oblateness
>> allPlanets[planet_name]->rotation
>> allPlanets[planet_name]->rotationUnit
>> allPlanets[planet_name]->distance
>> allPlanets[planet_name]->revolution
>> allPlanets[planet_name]->revolutionUnit
>> allPlanets[planet_name]->eccentricity
>> allPlanets[planet_name]->inclination
>> allPlanets[planet_name]->axis_tilt;
}
printf("\n\n");
myInput.close();
//
// --- looking at the planets
//
map<string,A_Planet*>::iterator it = allPlanets.begin(); // instantiate and initialize iterator
while (it != allPlanets.end())
{
printf("%9s %8.3f %11.3f \n",(it->first).c_str()        // key is a string
,(it->second)->planet_mass  // value is pointer
,(it->second)->diameter);
it++;                                                   // next entry
}
//
return 1;
}


# C++ include files

• more standard built-in utilities for C+11 and C+17

### general utilities

  General purpose utilities: program control, dynamic memory allocation, random numbers, sort and search  Functions and macro constants for signal management  Macro (and function) that saves (and jumps) to an execution context  Handling of variable length argument lists  Runtime type information utilities  bitset class template  Function objects, designed for use with the standard algorithms  Various utility components  C-style time/date utilites  typedefs for types such as size_t, NULL and others

### dynamic memory management

  Low-level memory management utilities  Higher level memory management utilities

### numerical limits (maximal/minmal numbers)

  limits of integral types  limits of float types  standardized way to query properties of arithmetic types

### error handling

  Exception handling utilities  Standard exception objects  Conditionally compiled macro that compares its argument to zero  Macro containing the last error number

### strings library

  functions to determine the type contained in character data  functions for determining the type of wide character data  various narrow character string handling functions  various wide and multibyte string handling functions  basic_string class template

### containers

  vector container  deque container  list container  stack container adaptor  queue and priority_queue container adaptors  and multiset associative containers  map and multimap associative containers

### Iterators library

  Container iterators

### algorithms & numerics

  Algorithms that operate on containers  Common mathematics functions  Complex number type  Class for representing and manipulating arrays of values  Numeric operations on values in containers

### input & output

  forward declarations of all classes in the input/output library  ios_base class, basic_ios class template and several typedefs  basic_istream class template and several typedefs  basic_ostream, basic_iostream class templates and several typedefs  several standard stream objects  basic_fstream, basic_ifstream, basic_ofstream class templates and several typedefs  basic_stringstream, basic_istringstream, basic_ostringstream class templates and several typedefs  strstream, istrstream, ostrstream(deprecated)  Helper functions to control the format or input and output  basic_streambufclass template  C-style input-output functions

### locale (country and language specifics)

  Localization utilities  C localization utilities

# C++ precompiler macros

• __LINE__    (line number),
__FILE__    (file name),
__FUNCTION__    (file name),
__DATE__    (date),
__TIME__  (time),
__VERSION__  (of the compiler) and
__TIMESTAMP__  (of program) are macros evaluated by the precompiler
• useful for debugging
• user defined macros possible, making codes however less portable
#include <iostream>
using namespace std;

#define EulerNumber 2.71828182845904523536028747135266249775724709369995

#define MIN(a,b) (((a)<(b)) ? a : b)   // a user defined macro
#define VARIABLE_NAME(x) #x            // expanding to string

int main ()
{
cout << "value of __LINE__      : " << __LINE__ << endl;
cout << "value of __FILE__      : " << __FILE__ << endl;
cout << "value of __FUNCTION__  : " << __FUNCTION__ << endl;
cout << "value of __DATE__      : " << __DATE__ << endl;
cout << "value of __TIME__      : " << __TIME__ << endl;
//
cout <<  endl;
cout << "value of __VERSION__   : " << __VERSION__ << endl;
cout << "value of __TIMESTAMP__ : " << __TIMESTAMP__ << endl;
//
cout <<  endl;
cout << "value of EulerNumber   : " << EulerNumber << endl;

return 0;
}