Ezen az oldalon arról lesz szó, hogy a Numerical Recipes programcsomagból
kiválasztott algoritmust hogyan tudjuk a saját programunkba beilleszteni.
Kifejezetten a Visual C programnyelvre koncentráltam, mivel ez ma az egyik
legelterjedtebb C fordító és a tanszéken is ezt használják többségben.
A programok használatánál három fontos dologról kell említést tenni,
amelyek nem egyértelműek:
Változók deklarálása
Az első fontos pont a beillesztésben a változók helyes deklarálása.
Apró eltérések vannak ugyanis a vektor és mátrix típusú változók definiálásánál.
Vektorok defíniálására Visual C-ben a legalkalmasabb a new operátor
használata. Ilyen módon azonban közvetlenül csak olyan vektorok állíthatók
elő, amelyek sorszámozása 0-ról indul. A Numerical Recipes kicsit más,
de nagyon jól kigondolt struktúrában használja a vektorokat és a mátrixokat.
A számozás az NR programokban használt vektorokban és mátrixokban általában
1-től indul. A vektorok és mátrixok definiálása speciális függvények segítségével
történik. Ezek a függvénypárok a következők:
float *vector(long n1,long nh)
…
void free_vector(float *v, long n1, long nh)
Egy [n1..nh] értéktartományú egyszeres pontosságú valós számokat tartalmazó
vektorhoz memória lefoglalása majd felszabadítása.
int *ivector(long n1,long nh)
…
void free_ivector(int *v, long n1, long nh)
Ugyanaz mint az előbb, csak előjeles egész számokat tartalmazó vektorhoz.
char *cvector(long n1,long nh)
…
void free_cvector(char *v, long n1, long nh)
Ugyanez előjel nélküli, 1 bájt hosszúságú számokhoz.
long *lvector(long n1,long nh)
…
void free_lvector(long *v, long n1, long nh)
És végül előjeles 4 bájton ábrázolt számokat tartalmazó vektor megadása.
float **matrix(long nr1, long nrh, long nc1, long nch)
…
void free_matrix(float **m, long nr1, long nrh, long nc1, long nch)
Egy [nr1..nrh][nc1..nch] értéktartományú egyszeres pontosságú valós
számokat tartalmazó mátrixhoz memória lefoglalása majd felszabadítása.
float **dmatrix(long nr1, long nrh, long nc1, long nch)
…
void free_dmatrix(double **m, long nr1, long nrh, long nc1, long nch)
Ugyanez dupla pontosságú számok esetén.
float **imatrix(long nr1, long nrh, long nc1, long nch)
…
void free_imatrix(int **m, long nr1, long nrh, long nc1, long nch)
Végül egész számok esetén mátrix lefoglalás. (a Numerical Recipes nem
használ char és long mátrixokat)
Az így előállított vektorok ezután ugyanúgy használhatók mint a new utasítással előállított vektorok (csak itt az általunk definiált értéktartományt használjuk). Ha valaki mindenképpen 0-tól akar indexelni egy vektort de a Numerical Recipes függvényben 1-től indul a számozás, akkor sincsen baj, mert az indexelés eltolása könnyen megoldható: csak vonjuk ki a szükséges elemszámot a vektorra mutató pointerből, amikor azt átadjuk egy NR rutinnak. Szélsőséges esetként az is megoldható, ha valaki new utasítással defíniált egy vektort, de át akarja adni egy NR rutinnak. Például:
float *SampleArray = new float[1024]; //ez a tomb 0-tol indul
for(i=0;i<1024;i++) {SampleArray[i]=i;}
four1(SampleArray-1,1024,1); //egydimenzios Fourier-transzformacio,
az indexeles 1 float ertekkel eltolva
Fontos: ha deklaráltunk egy vektort és adott számú elemmel el akarjuk tolni az indexelést, akkor ne a memóriaterület bájtban megadott méretével toljunk, hanem a tényleges elemszámmal, ugyanis a memóriában való pontos pozícionálást a C fordító fogja ez alapján kiszámítani.
Hibaüzenetek megjelenítése
Windows könyezetben minden a grafikus képernyőn történik, tehát a hibaüzenetet is oda szokás kiírni, viszont a Numerical Recipes függvények szöveges képernyőt tételeznek fel és a printf függvényt használják. A printf függvény Windows könyezetben való lefutásakor nincs semmi probléma, kivéve, hogy nem jelenik meg a hibaüzenet és esetleg nem értjük, hogy miért áll már órák hosszat a programunk. Ennek a kiküszöböléséhez néhány ponton át kell írni az NRUTIL.C programfájlt, hogy a hibaüzeneteket AfxMessageBox függvényeken keresztül írja ki a képernyőre. Ezt én meg is tettem. A módosított programfájl letölthető erről az oldalról itt:
Beillesztés és fordítás
A Numerical Recipes programcsomag eredetileg ANSI C-re és Borland C-re, DOS környezethez készült, viszont a következő műveletsor szerint eljárva tökéletesen használhatók és fordíthatók a programok Visual C-ben is.
A programok használatának jobb megértéséért kidolgoztam két darab
Visual C 6.0 példaprogramot, amelyek forrása letölthető itt:
DEMO1.ZIP (52770 bájt) Egy példaprogram
a Numerical Recipes
FOUR1.C FFT rutinjának a használatához.
A programmal wav fájlok amplitúdóspektruma nézegethető
DEMO2.ZIP (45720 bájt) Egy példaprogram
a Numerical recipes
SVDCMP.C szinguláris érték dekompozíció rutinjának a használatához.
A programmal szöveges fájlban megadott mátrixok dekomponálhatók.
Az eredmény látható a képernyőn és az SVDresult szöveges fájlban.