FFTW Library installieren unter Suse



  • Hallo Leute,

    Mich interessiert, ob jemand Erfahrungen mit der Implementierung der FFTW library hat. Ich habe die Version 3.2.2 runtergeladen und Probleme sie einzubinden. Ich habe sie mit den Befehlen

    ./configure
    gmake
    make install

    installiert und auch den Testlauf durchlaufen. Werden bei der Installation die libraries in die richtigen Ordner geschoben? Ich kriege jedenfalls beim compilieren einer .c-Datei, die die library fftw.h mit den Befehl

    #include <fftw.h>
    

    einbindet, vom gcc

    nach eingabe des Befehls

    gcc fft_test.c

    ausgegeben, dass die Datei oder der Ordner nicht gefunden wurde. Kann mir jemand helfen? Vielleicht mache icn nur Anfängerfehler für Grundlagenfragen.Das ist mein erstes großes C/C++ Projekt.

    Grüße,

    die Inge



  • hallo Inge,

    die datei zum einbinden heißt bei mir fftw3.h und befindet sich bei mir im ordner /usr/include, kannst ja mal schauen ob das bei dir so ist. bei shared librarys was fftw ja sein soll genügt es idr. nicht nur den header anzugeben sondern du mußt dem compiler in deinem fall gcc mitteilen wo er die functionen die in der *.h datei declariert sind findet.

    versuch mal

    #include <fftw3.h>
    statt 
    #include <fftw.h>
    
    und
    
    gcc fft_test.c -lfftw3
    statt
    gcc fft_test.c
    

    hoffe ich konnte helfen 🙄

    -l ist ein kleines L 🤡

    lg lolo



  • Hallo,

    Danke lolo für den Hinweis.Die Datei steht wirklich nicht im include Ordner drin. Muss ich diese lib erstmal mit expliziten Befehlen einfügen? Leider steht in den tutorials nichts weiter drin.

    Grüße

    Inge



  • wenn du die folgende zeile in die console eingibst bekommst du eine auflistung aller verzeichnisse welche durchsucht werden wenn du #include <...> in deinem quelltext schreibst und es mit gcc übersetzt.

    echo | gcc -v -x c - 2>&1 1>/dev/null | grep -B 100 "End of search list" | grep -A 100 "> search starts here"
    

    in einem dieser verzeichnisse muß sich die datei fftw3.h befinden in welchem ist dabei egal.

    folgendes gibt dir eine mit doppelpunkten separierte liste der verzeichnisse in denen nach der shared library gesucht wird.

    echo | gcc -v -x c - 2>&1 1>/dev/null | grep "LIBRARY_PATH"
    

    bei mir wurde die datei fftw3.h in dem ordner /usr/local/include erstellt.
    und die libraray (libfftw3.la ist das richtig?) befindet sich in /usr/local/lib

    und noch ein kleiner link zum schmökern http://www.network-theory.co.uk/docs/gccintro/gccintro_21.html

    lg lolo



  • "wenn du die folgende zeile in die console eingibst"
    sollte natürlich heißen
    "wenn du die folgende zeile in die console kopierst"
    😃



  • Wenn du etwas selbst kompilierst, findest du die Sachen im Normalfall in /usr/local/ wieder und nicht in /usr/. Also /usr/local/include, /usr/local/lib, /usr/local/bin etc.

    Aber man sollte nach Möglichkeiten nicht selbst kompilieren, sondern die fertigen Pakete der Distribution nehmen. Mit SuSE kenne ich mich nicht aus. Aber da sollte es auch einen einfachen Paketinstaller (in YaST) geben, wo du mal nach fftw suchen solltest.

    Für die Linker- und Compiler-Optionen verwendet man am besten man: pkg-config. Probier mal

    pkg-config --list-all | grep fftw
    

    und dann

    gcc `pkg-config fftw3 --libs --cflags` foo.c
    

    Ansonsten kannst du mit -I<pfad> den Includepfad und mit -L<pfad> den Bibliothekspfad setzen.



  • Vielen Dank noch einmal für die Hilfe. Die FFTW_Lib lässt sich unter Suse einfach mit Yast einfach downloaden. Danke für den Hinweis. Das erleichtert einiges und speichert die Bibliotheken und Headerfiles in die richtigen Ordner. Damit hat also alles geklappt. Ich beschreibe hier mal dokumentarisch die wichtigsten Funktionen anhand eines Beispiels aus dem Internet.

    http://www.elisanet.fi/~d635415/webroot/FFTW_example/index.html

    /* ****************************************************
     * FFTW example
     * Markus Nentwig, 2007
     * This program is in the public domain
     * ****************************************************/
    #include <stdio.h>
    #include <math.h>
    #include <complex.h> 
    #include <fftw3.h>
    #include <stdlib.h>
    
    int main(void){
      /* ****************************************************
       * Allocate memory
       * ****************************************************/
      int n=128;
      fftw_complex* b1=fftw_malloc(sizeof(fftw_complex)*n);
      fftw_complex* b2=fftw_malloc(sizeof(fftw_complex)*n);
    

    Die beiden letzten Commandozeilen allokieren Speicher für zwei Variablen, die dem komplexen Datentyp entsprechen, der für die dft gebraucht wird. Dabei sind b1 und b2 entweder Ein- oder Ausgangsvariablen, je nach Funktion.

    fftw_plan p1=fftw_plan_dft_1d(n, b1, b2, FFTW_FORWARD, FFTW_ESTIMATE);
    
      fftw_plan p2=fftw_plan_dft_1d(n, b2, b1, FFTW_BACKWARD, FFTW_ESTIMATE);
    

    Diese zwei Funktionen bilden den Plan. Der Plan ermittelt wahrscheinlich alle wichtigen Parameter wie Frequenzen etc, die für die dft gebraucht werden. So genau weiß ich das nicht, weil ich die genauen Algorithmen nicht kenne. Die Funktion hat folgende Argumente.

    Das Ausgangsargumente sind p1 und p2, die jeweiligen Pläne der dfts.

    Die Eingangsaurgumente kommen in folgender Reihenfolge:

    p_ = fftw_plan_dft_1d (Anzahl der Samples, allokierte Eingangsgröße
    , allokierte Ausgangsgröße, Richtung der Trafo ,Art der Trafo)

    Richtung der Trafo ist vom Freq-bereich in den Zeitbereich FFTW_FORWARD und umgekehrt FFTW_BACKWARD.

    Zudem gibt es zwei Arten der Trafo:

    FFTW_ESTIMATE und FFTW_MEASUREMENT.Bei FFTW_ESTIMATE wird mehr geschätzt was die Laufzeit veringert aber auch die Genauigkeit. Mit FFTW_MEASUREMENT ist es genau umgekehrt.

    p1 ist der Plan für eine Fouriertrafo und p2 für die entsprechende Rücktrafo.

    int i;
      for (i=0; i < n; ++i){
        b1[i]=sin((double)i/(double)n*2.0*M_PI);
      }
    

    b1 ist ein simpler Sinus.

    fftw_execute(p1);
    
      for (i=0; i < n; ++i){
        printf("%1.7f\t%1.7f\n", creal(b2[i]), cimag(b2[i]));
      };
    

    fftw_execute führt die Fouriertrafo vom Sinus durch. b2 ist dann das Freq-spek. vom Sinus, das von -n/2 bis n/2 ausgegeben wird.

    fftw_execute(p2);
      printf("\n");
    
      for (i=0; i < n; ++i){
        printf("%1.7f\t%1.7f\n", creal(b1[i]), cimag(b1[i]));
      };
    
      fftw_destroy_plan(p1);
      fftw_destroy_plan(p2);
    
      fftw_free(b1);
      fftw_free(b2);
      return 0;
    }
    

    Anschließend wird die inverse dft durchgeführt und der Sinus wieder ausgegeben. Daraufhin werden die Pläne und Variablen (und Pointer) gelöscht und der Speicher freigegeben.

    Für nichtequidistanze Signale (Samplefrequenz ist unregelmäßig) gibt es die nonuniform FT Bibliotheken von Daniel Potts. Man läd die Bibliothek hier
    http://www-user.tu-chemnitz.de/~potts/nfft/download.php runter und öffnet den tar-File mit

    tar nfft-x.y.z.tar.gz
    

    Anschließend geht man in den Ordner der durch die Entpackung im Verzeichnis entsteht.

    cd nfft-x.y.z
    

    und konfiguriert mit

    ./configure
    

    anschließend wird mit make (was dieser Befehl genau macht weiß ich nicht) ein make File erstellt. Danach installiert man im Normalfall mit

    make install
    

    die Bibliothek. Sie werden in die richtigen Ordner geschoben.Bei Suse gibt es aber Zugriffsberechtigungsprobleme, die aber mit dem Befehl

    su
    

    und anschließender root-Codeeingabe umgangen werden. Anschließend kann der make install Befehl ausgeführt werden und der su-Modus mit exit beendet werden. Es gibt ein Beispiel als Download auf der selben Seite um die lib zu testen. Ich habe den c-File mit

    gcc simple_test.c -lutil -lnfft3
    

    versucht zu kompilieren. Ich erhalte aber die Fehlermeldung

    simple_test.c:27:18: error: util.h: Datei oder Verzeichnis nicht gefunden
    

    obwohl sich die Datei im Unterordner der vom gcc durchsuchten Daten befindet. Kann hier das Problem liegen? Ich bitte um Hilfe.

    Mfg Inge



  • scheint so als wär das beispiel für die version 2.x...

    util wird nicht gelinkt, sondern nur als header file verwendet

    dein compile aufruf müßte so in der richtung aussehen...

    gcc simple_test.c -lnfft3 -lfftw3 -lm
    

    und statt

    #include "util.h"
    versuch mal
    #include "nfft3util.h"
    

    😕

    lg lolo



  • Hm... ich habe die util.h einfach ersetzt und

    gcc simple_test.c -lnfft3
    

    reingehaun dann hautes hin. Danke für die Hinweise Lolo. Kleine Frage hierzu hätte ich aber noch. Was ist denn

    -lm
    

    und warum muss man nicht jede angegebene Header-datei mit beim Kompilierungsbefehl in die Konsole einhämmern?

    Zudem habe ich das Gefühl, dass im Quelltext simple_test.c keine einheitliche Variablenvergabe gemacht wird.

    #include <stdio.h>
    #include <math.h>
    #include <string.h>
    #include <stdlib.h>
    #include <complex.h>
    
    #include "nfft3util.h"
    #include "nfft3.h"
    
    void simple_test_nfft_1d(void)
    {
      nfft_plan p;
    
      int N=14;
      int M=19;
    

    Das macht Sinn das N die Anzahl der Samples im Zeitbereich sind und M diejenigen im Freq.-bereich. Zumindest werden entsprechenden Zahlen ausgegeben.

    nfft_init_1d(&p,N,M);
    
      nfft_vrand_shifted_unit_double(p.x,p.M_total);
    
      if(p.nfft_flags & PRE_ONE_PSI)
          nfft_precompute_one_psi(&p);
    
      nfft_vrand_unit_complex(p.f_hat,p.N_total);
      nfft_vpr_complex(p.f_hat,p.N_total,"given Fourier coefficients, vector f_hat");
    
      ndft_trafo(&p);
      nfft_vpr_complex(p.f,p.M_total,"ndft, vector f");
    
      nfft_trafo(&p);
      nfft_vpr_complex(p.f,p.M_total,"nfft, vector f");
    
      ndft_adjoint(&p);
      nfft_vpr_complex(p.f_hat,p.N_total,"adjoint ndft, vector f_hat");
    
      nfft_adjoint(&p);
      nfft_vpr_complex(p.f_hat,p.N_total,"adjoint nfft, vector f_hat");
    
      nfft_finalize(&p);
    }
    
    void simple_test_nfft_2d(void)
    {
      int K,N[2],n[2];
      double t;
    

    Aber hier hörts auf. K ist die Anzahl der ausgegebenen Samples sowohl transformmiert als auch rücktransformiert. Was sind N und n dann? Groß-K ist auch in der Dokumentation nirgends erwähnt. Hat jemand schon einmal damit gearbeitet? Ich habe da echt Probleme...

    nfft_plan p;
    
      N[0]=70; n[0]=128;
      N[1]=50; n[1]=128;
      K=12;
    
      t=nfft_second();
      nfft_init_guru(&p, 2, N, N[0]*N[1], n, 4,
    		 PRE_PHI_HUT| PRE_PSI| MALLOC_F_HAT| MALLOC_X| MALLOC_F |
    		 FFTW_INIT| FFT_OUT_OF_PLACE,
    		 FFTW_ESTIMATE| FFTW_DESTROY_INPUT);
    
      nfft_vrand_shifted_unit_double(p.x,p.d*p.M_total);
    
      if(p.nfft_flags & PRE_ONE_PSI)
        nfft_precompute_one_psi(&p);
    
      nfft_vrand_unit_complex(p.f_hat,p.N_total);
    
      t=nfft_second()-t;
      nfft_vpr_complex(p.f_hat,K,
                  "given Fourier coefficients, vector f_hat (first few entries)");
      printf(" ... initialisation took %e seconds.\n",t);
    
      t=nfft_second();
      ndft_trafo(&p);
      t=nfft_second()-t;
      nfft_vpr_complex(p.f,K,"ndft, vector f (first few entries)");
      printf(" took %e seconds.\n",t);
    
      t=nfft_second();
      nfft_trafo(&p);
      t=nfft_second()-t;
      nfft_vpr_complex(p.f,K,"nfft, vector f (first few entries)");
      printf(" took %e seconds.\n",t);
    
      t=nfft_second();
      ndft_adjoint(&p);
      t=nfft_second()-t;
      nfft_vpr_complex(p.f_hat,K,"adjoint ndft, vector f_hat (first few entries)");
      printf(" took %e seconds.\n",t);
    
      t=nfft_second();
      nfft_adjoint(&p);
      t=nfft_second()-t;
      nfft_vpr_complex(p.f_hat,K,"adjoint nfft, vector f_hat (first few entries)");
      printf(" took %e seconds.\n",t);
    
      nfft_finalize(&p);
    }
    
    int main(void)
    {
      system("clear");
      printf("1) computing an one dimensional ndft, nfft and an adjoint nfft\n\n");
      simple_test_nfft_1d();
      getc(stdin);
    
      system("clear");
      printf("2) computing a two dimensional ndft, nfft and an adjoint nfft\n\n");
      simple_test_nfft_2d();
    
      return 1;
    }
    

    Nuja bei den Mehrdimensionalitäten wird es sowieso ganz schön heftig. Da hätte ich so viele Fragen... Wenn ich was brauchbares habe, mache ich noch ein deutsches Tutorial hier zurecht. Vll kanns ja jemand gebrauchen...

    Grüße,

    die Inge



  • So liebe Leute,

    nachdem ich mich ausführlich mit der fftw und der nfft bib beschäftigt habe, möchte ich gern einige kleine Ergs mitgeben.

    Man muss ein paar Kniffs können, um die Funktionen zum laufen zu bekommen. Das sind nun folgende.

    Erstens ein paar Begrifflichkeiten.

    NFFT heißt nonequispaced fast fouriertransformation. die Lib findet man auf der HP der TU Chemnitz und ist unter der Leitung von Prof Daniel Potts geschrieben worden. Man findet sie einfach, wenn man mal googlet.

    Das erste was man beachten muss ist die Begrifflichkeit NFFT und inverse NFFT. Meist wird für die normale FFT die Wandlung von Abtastdaten in Frequenzdaten bezeichnet. Hier ist es aber genau UMGEKEHRT. Sprich man fängt im Frequenzbereich an. Nehmen wir der einfachheit halber einen double complex Datensatz input mit der Anzahl der Frequenzen der Dimensionen die in N gespeichert sind .

    #include <stdio.h>
    #include <math.h>
    #include <string.h>
    #include <stdlib.h>
    #include <complex.h>
    
    #include "nfft3util.h"
    #include "nfft3.h"
    
    int N[2]  = {f1, f2};
    int n[2]  = {n1, n2};
    int M = n1*n2;
    ///input ist der gegebene Datensatz woher auch immer, f1 und f2 die zughörigen f
    /*n beinhaltet die Anzzahl der gegebenen Punkte im t Bereich,die erhalten werden sollen*/
    //M Anzahl aller Punkte (in der lib doku auch knoten genannt)
    

    Ähnlich wie in der fftw bib wird hier mit Plänen gearbeitet.

    nfft_plan p;
    int h1 ,h2 ,d; // h1 h2 Hilfsvariablen, d = Dimension
    

    Diese Plane werden initialisiert. In unserem Falle 2d

    nfft_init_2d(&p,N[0],N[1],M);
    

    weitere initialisierungen hier:

    http://www-user.tu-chemnitz.de/~potts/nfft/guide3/html/node40.html

    Was einem bestimmt schon aufgefallen ist, hier läuft alles über 1d Pointer. D.H. man muss sich entsprechend in diese Thematik reinarbeiten. Als nächstes müssen die Koordinaten der Punkte oder Knoten hergegeben werden. Die müssen in der Reihenfolge übergeben werden, wie die zu erhaltenen Funktionswerte entstehen sollen. Man übergibt quasi ein d*M großes Array, das wie folgt ausieht

    array1d[d*j + t] [e]equiv[/e] array2d[j][d]
    // t ist die jweilige Dimension die gerade eingeliefert wird und j der gerade genutzte Punkt. j [e]epsilon[/e] M.
    

    Anschließend wird ein Fenster erstellt, welches für die weitere Verabeitung notwendig wird. Dies geschieht aber nur, wenn einige flags gesetzt sind, die ich aber nicht weiter ausführen werde.

    if(p.nfft_flags & PRE_ONE_PSI)
        nfft_precompute_one_psi(&p);
    

    Nun werden die Inputdaten übergeben. Da diese hoffentlich in einem 1d Pointer verpackt sind, reicht hierfür folgender Ausdruck:

    for(h1=0;h1<M;h1++)
      p.f_hat[h1] = input[h1];
    

    Nun wird die Transformation durchgeführt und die Daten können au p.f entnommen werden, wie Input eingefügt wurde. Anschließe muss derPlan noch zerstört werden. Man kann ihn abdr mehrfach nutzen und die Trafo durchführen. Einfach veränderten Input eingeben und fertsch is der Lack.

    nfft_trafo(&p);
    nfft_finalize(&p);
    

    Als nächstes kommt die inverse NFFT quasi die eigentliche Fouriertrafo wie sie allgemeingebräuchlich ist. Dies geht aber nicht so einfach rückwärts. hier wurde ein Standard Gauss Verfahren angewandt, nämlich die Methode der kleinsten Fehlerquadrate. Aber dazu später mehr. Is ja spät genug.

    Grüße die Inge

    PS: Hier ein wenig was zum Handling mit 1d pointer und arrays:

    http://www.fftw.org/fftw3_doc/Dynamic-Arrays-in-C.html#Dynamic-Arrays-in-C


Anmelden zum Antworten