Parameter Konvertierung von vector<vector<CComplex> > nach Complex*
-
Ich habe meine Arrays als
vector<vector<CComplex> >definiert und möchte diese an eine Funktion FFT2D übergeben, die als Eingabe erwartet:
void FFT2D(CComplex *E,CComplex *S,long N,long sd)Ich habe es mit probiert mit (CComplex*)m_W und &m_F
FFT2D((CComplex*)m_W,&m_F,N,1);was mir aber nur die Fehlermeldungen liefert:
\AdaptiveAlgorithm.cpp(292) : error C2440: 'Typumwandlung': 'std::vector<_Ty>' kann nicht in 'CComplex *' konvertiert werden
1> with
1> [
1> _Ty=std::vector<CComplex>
1> ]
1> Kein benutzerdefinierter Konvertierungsoperator verfügbar, der diese Konvertierung durchführen kann, oder der Operator kann nicht aufgerufen werden
1>.\AdaptiveAlgorithm.cpp(312) : error C2664: 'FFT2D': Konvertierung des Parameters 1 von 'std::vector<_Ty> *__w64 ' in 'CComplex *' nicht möglich
1> with
1> [
1> _Ty=std::vector<CComplex>
1> ]
1> Die Typen, auf die verwiesen wird, sind nicht verknüpft; die Konvertierung erfordert einen reinterpret_cast-Operator oder eine Typumwandlung im C- oder Funktionsformat.
1>Das Buildprotokoll wurde unter "file://e:\Daten\Dev\Cpp\LightModulator2DMat\LightModulator2D\Debug\BuildLog.htm" gespeichert.wie konvertiere ich das Datenformat, so dass es passt?
Matthias
-
Hi,
ich falle Dir hoffentlich nicht auf die Nerven, wenn ich schon wieder antworte (vielleicht korrigieren/ergänzen mich ja auch Andere)....

Ist doch ganz einfach:
FFT2D(&m_W[0][0],&&m_F[0][0],N,1);
Aber Du willst vermutlich nicht einfach die Adresse des ersten Elements, sondern in FFT2D() sowas wie "Pointerarithmetik" machen, also auf alle Elemente sukkzessive zugreifen, oder ?
Wenn, dann wird das, was Du willst, wird nicht mit einem noch so geschickten cast funktionieren, weil es sich einfach (schon von der Speicherrepräsentation her) um ganz andere Objekte handelt (ähnlich wie beim extract
).Mal zur Veranschaulichung:
Beim vector<vector<CComplex> > sieht es vereinfacht folgendermaßen aus: class vector<CComplex> { CComplex* ptr; size_t size; public: vector<CComplex>(size_t cap) : ptr(new CComplex[cap]), size(cap) {} // .... }; // Hier werden also cap-viele CComplexs IRGENDWO hintereinander in den Speicher gelegt; class vector<vector<CComplex> > { vector<CComplex>* ptr; size_t size; public: vector<vector<CComplex> >(size_t cap) : ptr(new vector<CComplex>[cap]), size(cap) {} // .... }; // Hier werden also cap-viele vector<CComplex> IRGENDWO hintereinander in den Speicher gelegt;Jetzt nehmen wir mal an, wir legen einen 3 vector<CComplex> in unseren vector<vector<CComplex> >, dann bekommt das Programm vielleicht folgende Positionen zugewiesen (beim new - je nachdem, wo die Runtime gerade Platz hat):
0x100 -> hier beginnt 1.vector<CComplex> 0x300 -> hierhin zeigt 1.vector<CComplex>.ptr 0x1000 -> hier beginnt 2.vector<CComplex> 0x1300 -> hierhin zeigt 2.vector<CComplex>.ptr 0x5000 -> hier beginnt 2.vector<CComplex> 0x5300 -> hierhin zeigt 2.vector<CComplex>.ptr 0x15000 -> vector<vector<CComplex> >Deine "CComplexdaten" liegen also verteilt hinter 0x300, 0x1300 und 0x5300 und vector<vector<CComplex> > wiederum liegt bei 0x15000...
Deine Funktion wird aber erwarten, dass sich alle CComplex-Daten in einem Block an 0x15000 befinden.
Auch hier gilt leider: "Falscher Container für die API"
entweder musst Du also umkopieren oder gleich mit einerm anderen Container arbeiten.Ich schau mal, ob ich das "knackig kopiert" bekomme....
Gruß,
Simon2.
-
Das
vector< vector<CComplex> >würde ich mal als eine komplexe Matrix bezeichnen.
void FFT2D(CComplex *E,CComplex *S,long N,long sd)Ich rate mal das es um quadratische Matrizen geht und N die Dimension ist.
Ferner rate ich dass Du nicht einefach die Funktion umschreiben kannst, so dass sievoid FFT2D(vector< vector<CComplex> >& E,vector< vector<CComplex> >& S, long N, long sd)Sind meine Vorannahmen richtig?
Gut:
- Complex foo[m][n] ist kein Complex** sondern ein Complex* der auf eine Sequenz von mn Complex Instanzen zeigt.
- Ein std::vector ist kein Array; er tut nur so mittels operator[](/**/)Die Funktion erwartet wohl einen CComplex* der auf N*N Objekte zeigt.
Dann tu ihm den Gefallen und
Kopier die Matrixelemente hin und zurück in/aus einen/m Speicherbereich wie das API sich das wünscht.
Das ist natürlich per-se inperformat.Irgendwie hab ich gerade hierüber nachgedacht
template<> class std::vector< std::vector<CComplex> > { /* Dereferenz-, cast-Operatoren-, Zugriffsoperatoren; */ }aber darüber kriegt ggf. man die Zeigerarithmeitk in der Funktion nicht klein
Was mir noch einfallen würde ist ein eigener Allokator der ggf im Verbund mit der Templatespezialisierung (Oder einer eigenen Klasse mit solchen ops) arbeitet und die Objekte tatsaächlich geeignet im Speicher plaziert.
Grüsse
Gast++
-
Gast++ schrieb:
Das
vector< vector<CComplex> >würde ich mal als eine komplexe Matrix bezeichnen.
void FFT2D(CComplex *E,CComplex *S,long N,long sd)Ich rate mal das es um quadratische Matrizen geht und N die Dimension ist.
Ferner rate ich dass Du nicht einefach die Funktion umschreiben kannst, so dass sievoid FFT2D(vector< vector<CComplex> >& E,vector< vector<CComplex> >& S, long N, long sd)Sind meine Vorannahmen richtig?
Ja.
Das Problem - ich habe die Funktion gerade von normalen Arrays geändert zu vector arrays weil ich nur dann die Größe zur Laufzeit festlegen kann (sehe ich doch richtig oder?).
Das ich mit der FFT damit ein Problem bekomme hatte ich nicht bedacht. Diese Funktion ist mehr oder weniger in C und selbstgeschrieben, aber nicht von mir.Jetzt könnte ich natürlich auch auf eine FFT Klasse für C++ ausweichen die andere Arrays aktzeptiert. Das Problem ist nur, dass ich die nicht habe.
Gibt es soetwas ? Also speziell FFT Bibliotheken für C++
Kenn bislang nur FFTW (noch nicht benutzt) das aber meines Wissens auch in C geschrieben ist und damit keine vector arrays aktzeptiert.Matthias
-
vector ist an sich nicht das Problem. Du müsstest einen vector<Complex> verwenden und die 2D-Adressierung von Hand vornehmen. Oder dir eine Klasse drumherum stricken, die dir das abnimmt. Nur mal zum Vergleich, Complex** wär auch nicht gegangen ...
-
Bashar schrieb:
vector ist an sich nicht das Problem. Du müsstest einen vector<Complex> verwenden und die 2D-Adressierung von Hand vornehmen.
Was bringt mir ein vector<Complex> ? Das wäre doch nur eindimensional.
Bashar schrieb:
Nur mal zum Vergleich, Complex** wär auch nicht gegangen ...
Klar.
Matthias
-
Hi,
Du könntest wieder mit copy arbeiten und einen Helper benutzen:
class CopyHelper { int* arr; size_t const maxLen; size_t size; public: typedef vector<int> const& const_reference; CopyHelper(int* a, size_t m) : arr(a), maxLen(m), size(0) {} void push_back(const_reference v) { if(size + v.size() >= maxLen) throw out_of_range("CopyHelper"); copy(v.begin(), v.end(), arr+size); size += v.size(); } }; int main() { size_t const maxLen = 10; vector<vector<int> > vec; int arr[maxLen]; CopyHelper helper(arr, maxLen); // ... vector<vector<int> > wird gefüllt: copy(vec.begin(), vec.end(), back_inserter(helper)); return 0; }Geht eigentlich gar nicht schlecht ... CopyHelper könnte man natürlich auch als template bauen - aber Achtung: back_insert_iterator (und damit auch back_inserter) braucht den typedef const_reference.
Gruß,
Simon2.
-
Sehe ich es richtig, dass ich bei allen Lösungen die ein vector Array beliebieger Größe in ein C-Array kopieren die Größe des C-Arrays schon zur Compilierzeit festgelegt haben muss?
Das war gerade der Grund warum ich ein vector array genommen habe.Matthias
-
pospiech schrieb:
Sehe ich es richtig, dass ich bei allen Lösungen die ein vector Array beliebieger Größe in ein C-Array kopieren die Größe des C-Arrays schon zur Compilierzeit festgelegt haben muss?
MatthiasAber nein:
unsigned int N = 0; cin >> N; /* * Hinten ECKIGE Klammern verwenden! * * Sonst ist's ein ctor-Aufruf * für EIN Complex mit einem uint * als Argument */ Complex* p = new Complex[N]; //.. delete[] p;
-
Gast++ schrieb:
unsigned int N = 0; cin >> N; Complex* p = new Complex[N]; //.. delete[] p;Ich hätte vielleicht dazu sagen sollen, dass ich 2-dimensionale Arrays habe.
Und mitint (*pArr)[N]; // im Header pArr = new int[N][N]; // im Konstruktor der CPP DateiMuss die Größe zur Laufzeit dann doch bekannt sein.
Wenn ich nurint (*pArr)[N] = new int[N][N]verwende sollte es gehen, dann ist aber mein Array nicht innerhalb der ganzen Klasse bekannt. Oder sehe ich den richtigen Weg einfach nur nicht ?
Matthias
-
Hi,
ich würde, ehrlich gesagt, 2D-Arrays nur dann nutzen, wenn es unbedingt sein müsste - und dann möglichst nicht mit vector<vector<> > mischen.
Letztlich eben genau deswegen, weil Arraydimensionen (zumindestens alle bis auf eine) zur Compilezeit (ich denke, Du meintest da nicht wirklich "Laufzeit", oder ?
) festgelegt sein muss....
Wenn Du es unbedingt brauchst, solltest Du mit meinem Ansatz (CopyHelper) eigentlich ganz gut klar kommen, denn im Speicher sind 2D-Arrays auch nur sequentielle Daten und der Compiler weiß einfach, wohin er "springen" muss.
Deswegen klappt auch Folgendes:void fillArr(int* arr) { for(int i=0; i<6; ++i) arr[i]=i; } int main() { int arr[2][3]; fillArr(&arr[0][0]); cout << arr[0][0] << " " << arr[0][1] << " " << arr[0][2] << "\n"; cout << arr[1][0] << " " << arr[1][1] << " " << arr[1][2] << "\n"; return 0; }Gruß,
Simon2.
-
pospiech schrieb:
Gast++ schrieb:
unsigned int N = 0; cin >> N; Complex* p = new Complex[N]; //.. delete[] p;Ich hätte vielleicht dazu sagen sollen, dass ich 2-dimensionale Arrays habe.
Das war mir jetzt schon klar...
Dann nimmt Du eben N*N:
Complex* p = new Complex[N*N];
Das ist im Speciher das gleiche wie Complex p[N][N], nur dass Du's halt zur Laufzeit angeben kannst.Das ist immer nur eine Folge von Complex-Instanzen die hintereinander im Speicher liegen!
Und zwar ab der Adresse p. Und das willst Du ja auch für FFT2D haben, oder?
Falls Du nen Stroustrup C++PL 4.Auflage hast lies mal §C.7 - Prof. Stroustrup erklärt das sicherlich besser als ich.
Happy Hacking!
Grüsse
*this