PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Übergabe von C++ Vektoren an Fortran



aui
07-10-2008, 08:40
Hallo Leute,

ich bin ein Anfänger in der Programmierung, und soll gleich mit zwei Sprachen und dem Austausch von Variablen anfangen. Manchmal wird überschätzt, was in kurzer Zeit möglich ist. Hier mein Problem:

Ich habe mehrere Vektoren mit integer Werten. Außerdem lasse ich einen Vektor mit Zufallszahlen erstellen, der immer Stellen ausgibt, an denen die zwei anderen Vektoren vertauscht werden. push_back ist dafür der richtige Befehl denke ich. In C++ habe ich jetzt aber nichts gefunden, mit dem man einen Teil eines Vektors einem anderen zuweisen kann, wie es zum Beispiel in Fortran geht:

vektor2[1:10] = vektor1 [12:22]

Dehalb möchte ich jetzt die zwei Integer Vektoren und den Kombinationsvektor an Fortran übergeben, dort neu kombinieren und an c++ zum weiterarbeiten zurückgeben. Allerdings schaffe ich nur einen einzelnen Wert an Fortran zu übergeben, aber nicht einen Vektro.

Ich wäre jetzt sehr dankbar, wenn mir jemand sagen könnte, wie ich das entweder in c++ lösen kann, oder wie ich einen vektoren an eine Fortran Subroutine übergebe und dann wieder einen Vektor zurückbekomme.

Gruß,
Aui

Berufspenner
07-10-2008, 08:56
In C++ habe ich jetzt aber nichts gefunden, mit dem man einen Teil eines Vektors einem anderen zuweisen kann, wie es zum Beispiel in Fortran geht:
Vielleicht verstehe ich dein Problem/Vorhaben nicht ganz, aber du kannst doch mittels Indexoperator (eckige klammern []) ganz einfach auf jedes einzelne Element eines Vektors zugreifen.

aui
07-10-2008, 09:05
Hallo Berufspenner,

das ist es ja genau, ich will nicht auf einen einzelnen Wert zugreifen, sondern immer auf ein Teilfeld. Der Kombinationsvektor gibt den Anfange bzw. das Ende des Teilfeldes an.

Aui

Berufspenner
07-10-2008, 09:10
Hallo Berufspenner,

das ist es ja genau, ich will nicht auf einen einzelnen Wert zugreifen, sondern immer auf ein Teilfeld. Der Kombinationsvektor gibt den Anfange bzw. das Ende des Teilfeldes an.

Aui

Mir ist nichts dergleichen bekannt, dass man ganze Teilbereiche eines Vektors verschieben kann. Das ist stabilitätsbedingt aber auch ein vorteil, weil so jedes Element vorher geprüft werden müsste und so die Gefahr minimiert wird, auf nicht existente Elemente zu zugreifen. Du wirst Teile eines Vektors also mit einer Schleife elementweise kopieren müssen.

aui
07-10-2008, 09:18
Hallo Berufspenner,

genau das wollte ich nicht, weil ich dafür 2,4 *10^18 Abfragen brauche. Mit der Vorgehensweise von Fortran nur 3*10^12 Operationen. Dadurch ergibt sich ein ernormer Rechenzeitvorteil, und deshalb wollte ich ja wissen, wie man einen Vektor an Fortran übergibt. Die anderen Sachen sind in C++ leichter zu programmieren. Deshalb nehme ich das ja auch für Zufallszahlen und so.

Aui

ContainerDriver
07-10-2008, 10:05
Hallo,

um welchen Datentyp handelt es sich denn konkret bei dem Vektor? Ist das ein einfaches Int-Array?

Gruß, Florian

aui
07-10-2008, 10:22
Hallo,

der Vektor in c++ ist definiert als:

vector<unsigned int> recomb;

und in Fortran als:

integer*4, allocatable :: recomb( : )

locus vivendi
07-10-2008, 11:20
In C++ habe ich jetzt aber nichts gefunden, mit dem man einen Teil eines Vektors einem anderen zuweisen kann, wie es zum Beispiel in Fortran geht:

vektor2[1:10] = vektor1 [12:22]
Ich kenne mich mit Fortran nicht aus. Werden dabei in vektor2 die bisherigen Elemente nach hinten verschoben, oder werden sie überschrieben?
Im ersten Fall kannst du dafür die Memberfunktion "insert" eines C++ Vectors verwenden, ungefähr in der Art von "vektor2.insert(vektor2.begin() + X, vektor1.begin() + A, vektor1.begin() + B)", wobei X, A, und B Offsets sind, die natürlich innerhalb der jeweiligen Sequenzen liegen müssen.
Im zweiten Fall, also wenn Elemente überschrieben werden sollen, dann geht das mit std::copy aus dem Header "<algorithm>", ähnlich wie in "std::copy(vektor1.begin() + A, vektor1.begin() + B, vektor2.begin() + X)". In diesem Fall muss vektor2 unbedingt groß genug sein, um von Index X an noch B - A Elemente aufnehmen zu können.

aui
07-10-2008, 12:15
Hallo,

habe mich wohl schlecht ausgedrückt. Ich baue eine Schleife, die entsprechend der Anzahl der Elemente im Rekombinationsvektor wiederholt wird. Im neuen Vektor sind die Positionen 0 bis x mit Werten aus dem VektorA bestetzt, die Positionen x+1 bis y mit Werten aus dem VektorB, die Positionen y+1 bis z wieder mit Werten aus VektorA und so weiter.so hätte ich das ganze gerne zugeordnet. In Fortran ist das eben ganz einfach. Da kann man Teilfelder wie in R ansprechen. Einfach Feld[0:x] = VektorA[0:x]

Gruß,
Aui

locus vivendi
07-10-2008, 13:08
Aui, würde es dir etwas ausmachen, deinen bisherigen C++ code zum Bearbeiten der Vektoren zu posten? Dann könnte ich mal schauen, ob mir Verbesserungen einfallen - natürlich kann ich nichts garantieren.

Übrigens noch mal zum zweiten Teil deiner ursprünglichen Frage (bezüglich Austausch Fortran/C++): Wenn "v" ein std::vector ist, dann kannst du mit dem Ausdruck "&v.front()" einen Zeiger auf den Inhalt bekommen (*). Die Elemente liegen zusammenhängend im Speicher, wie in einem C Array. Wenn du eine Methode hast um C Arrays zwischen C++ und Fortran auszutauschen, dann solltest du diese also benutzen können.

*: Zumindest für "std::vector<unsigned int>" gilt das, wenn der Vektor nicht leer ist.

aui
07-10-2008, 13:42
Hallo locus vivendi,

also mit deinem Hinweis klappt das jetzt. Das Problem war, dass ich nicht die Zeiger weitergegeben habe, sondern die Werte des Vektors. Den Code poste ich in Kürze, dann können isch das merh ansehen.

Danke derweil,

Aui

ContainerDriver
07-10-2008, 15:06
Könnte man das nicht auch mit memcpy/memmove lösen? Erscheint mir etwas sauberer als der Weg über eine zweite Programmiersprache (gibt es bei der Vermengung von C/C++ mit Fortran überhaupt eine Typsicherheit?).

aui
17-10-2008, 09:52
Hallo Leute,

hier kommen jetzt die Programme, wenn auch mit einiger Verspätung. Das letzte mal wurde ich leider abgewürgt. Und meine Antwort hat sich in Nirwana verloren. So, also ich habe die beiden Programme hier angehängt, ebenso, wie die Library MersenneTwister.h. Die Anhänge müssen dann nur noch um ihrer .txt beraubt werden, soll heißen, einfach umbenennen. Bei Kompilieren bin ich folgendermaßen vorgegangen:

Zuerst alles in einen Ordner kopieren, dann die Fortran-Datei mit dem Befehl:

gfortran -O -c recombination.f95

Das erzeugt eine .o Datei im selben Ordner, dann mit folgendem Statement alles zu einer ausführbaren Datei zusammenpacken:

g++ -O -Lgfortran -o basis basis.cpp recombination.o

basis reicht dann, um die Maschine anzuwerfen.

In Wirklichkeit läuft das ganze mit numSNP = 80000 und generation = 1000. Aber für das Beispiel sollte das reichen. Das Problem mit der Kombitabilität der Variablen ist eigentlich beschränkt auf den Speicherplatzbedarf. Soll heißen, wenn man einen Wert übergibt, der 2 byte belegt, muss man dafür auch in Fortran eine Variable definieren, die 2 byte ausfüllt. Und hier war mein unsprünliches Problem. Ich hatte definiert:

vector<bool> animal, parent1, parent2

Das ganze dann auch schön als _bitwise übergeben. Aber in Fortran95 gibt es anscheinend keine Definition mit dem Typ bit. Jedenfalls habe ich nichts gefunden. Falls jemand Lust hat damit ein wenig herumzuspielen, gerne.

Gruß,

Aui

PS: Wenn ich Zeit habe, packe ich das ganze noch in Objekte. Ist dann ein wenig schöner, und auch allgemeiner verwendbar.