giovedì, novembre 02, 2006

organizzare il codice in librerie

Quando il numero di funzioni in un programma cresce molto, la compilazione rallenta perche' ad ogni modifica e' necessario ri-compilare tutto quanto e' stato scritto.

Per accelerare questo processo si suddivide il codice scritto in moduli divisi fra di loro, solitamente per funzionalita': tutto quello che e' stato scritto con una certa funzione e con carattere di generalita' viene impacchettato in un singolo "oggetto" (del compilatore, non del C++: e' un caso di omonimia).

Un esempio calzante di questo puo' essere tratto dalle funzioni di generazione di numeri casuali che abbiamo scritto.
In questo caso, divido le funzioni che generano numeri casuali dal main program, creando:


  • randomMIB.h le definizioni delle funzioni
  • randomMIB.cc le implementazioni delle funzioni
  • testRandom.cpp il programma che le utilizza

E' necessario definire il file randomMIB.h diviso dal randomMIB.cc, perche' nel randomMIB.h stanno gli header delle funzioni, quindi dovra' essere incluso in tutti gli eseguibili che ne fanno uso perche' il parser ne conosca il prototipo.
Lasciare randomMIB.cc separato permette di compilarlo una volta sola e di utilizzare la parte gia' compilata linkandola al codice in esecuzione (come Enzo ha spiegato).

Insomma, per provare effettivamente come si fa.
Per compilare la libreria di funzioni di genralzione di numeri casuali:

c++ -c randomMIB.cc -lm

per compilare il programma di test:

c++ -lm randomMIB.o testRandom.cpp -o testRandom

per eseguire il programma di test:

./testRandom

Nel caso si modificasse il programma di test, oppure se ne creasse un altro, e' sufficiente compilare quest'ultimo, perche' la libreria non e' cambiata.

Ecco di seguito i codici dei tre pezzi.

PS: ho modificato randFunc seguendo la implementazione di Eugenio.

randomMIB.h

#ifndef randomMIB_h
#define randomMIB_h

#include <iostream>
#include <cmath>
#include <ctime>
#include <cstdlib>

double randFlat (double min, double max) ;
double randFunc (double func (double),
double minx, double maxx,
double miny, double maxy) ;

#endif


randomMIB.cc

#include "randomMIB.h"
#include <iostream>
#include <cmath>
#include <ctime>
#include <cstdlib>


//! restituisce un numero casuale fra min e max
//! secondo una distribuzione uniforme
double randFlat (double min, double max)
{
return min + (max-min) * rand () / static_cast<double> (RAND_MAX) ;
}


// ----------------------------------------------------------------------


//! restituisce un numero casuale fra minx e maxx
//! secondo una distribuzione che segue func
double randFunc (double func (double),
double minx, double maxx,
double miny, double maxy)
{
if (maxx < minx) return maxx - 1 ;
if (maxy < miny) return minx - 1 ;
double x,y ;
do
{
x = randFlat (minx, maxx) ;
y = randFlat (miny, maxy) ;
}
while (func (x) < y) ;
return x ;
}


testRandom.cpp

#include <iostream>
#include <cmath>
#include <ctime>
#include <cstdlib>

#include "randomMIB.h"

double generationPDF (double x) ;


// ----------------------------------------------------------------------


int main ()
{

// inizializzo il seme di generazione casuale
srand (time (NULL)) ;

// loop sugli eventi da generare
for (int i=0; i<10; ++i)
{
// genero un numero casuale
double numero = randFunc (generationPDF,
0,2 * M_PI,
-0.1,2.1) ;
std::cout << "numero casuale n. " << i
<< " : " << numero << std::endl ;
} // loop sugli eventi da generare

return 0 ;

}


// ----------------------------------------------------------------------


double generationPDF (double x)
{
// return 1 ;
return cos (x) + 1 ;
}

Nessun commento: