2009-05-28 11 views
1

Ich habe derzeit ein 5D-Array in der Variablen namens Vorlage in 1D-Array namens template1D geschrieben, mit einer Hash-Tabelle von 3456 (8 * 12 * 3 * 4 * 3) Einträge. In Matlab wurde das mehrdimensionale Array zugegriffen wird, wie folgt:5D Array Hash-Tabelle

template{idx_r, idx_l, idx_rho, idx_alpha, idx_beta} 

jedoch, wie ich die Indices von 0-7 gehen, 0-11, 0-2, 0-3, und 0-2 jeweils Ich bin mir nicht ganz sicher, was der einfachste Weg wäre, eine Gesamtindexnummer aus diesen fünf Indizes abzurufen, um das richtige Segment im Template-Array richtig zu erhalten. Was wäre die einfachste Methode, um solche Hash-Funktionen richtig zu machen?

+0

Five nahm sich die Zeit, um auf null zu antworten. Es war eine Frage, die gut genug war, um sie zu bewerten. Ich mache +1 – Copas

Antwort

2

Sie können zwar sicherlich tun, die Mathematik selbst den linearen Index zu berechnen (wie von Tal wies darauf hin), wäre es sauberer und einfacher sein, mit Hilfe der eingebauten Funktion SUB2IND (als spitzer zu lesen out von Loren). Für Ihr Beispiel, können Sie es auf folgende Weise verwenden würde:

index = sub2ind([8 12 3 4 3], idx_r, idx_l, idx_rho, idx_alpha, idx_beta); 

Wenn alle Ihre Indizes 0-basiert sind, würden Sie 1 zu jedem von ihnen hinzuzufügen, bevor sie SUB2IND vorbei.

EDIT:

Wenn Sie sehen möchten, wie man richtig selbst in MATLAB lineare Indizes berechnen, so dass sie mit den Ergebnissen aus SUB2IND einverstanden ist, hier der Code ist verwenden Sie:

index = (((idx_beta*4 + idx_alpha)*3 + idx_rho)*12 + idx_l)*8 + idx_r + 1; 

HINWEIS, dass die Indizes, die mit dieser Gleichung verwendet werden müssen, 0-basiert sein müssen, während die Indizes, die an SUB2IND übergeben werden, 1-basiert sein müssen.

index = (...(idx(N)*sz(N-1) + idx(N-1))*sz(N-2) + ...)*sz(1) + idx(1) + 1; 

oder kompakter: für jede Dimension und

index = 1 + sum(idx.*cumsum([1 sz(1:(N-1))])); 

wo idx ist ein Array von 0 basierten Indexwerte diese Gleichung zu einer beliebigen Anzahl von Dimensionen N zu verallgemeinern sz ist ein Array der Größen jeder Dimension.

+0

Gibt es eine ähnliche Funktion in einer der C++ - Bibliotheken, die nicht von Mex-Funktionen Gebrauch macht, die ähnliche Dinge tun? Ich habe Probleme, es zu finden, wenn es existiert. – stanigator

+0

Ich habe kein C++ - Äquivalent von SUB2IND gefunden. Müssen Sie Ihre Indizierung in einer mex Datei machen, die Sie schreiben? Ich weiß, dass es eine Funktion namens "mexCallMATLAB" (http://www.mathworks.com/support/tech-notes/1600/1605.html#example5) gibt, mit der Sie MATLAB-Funktionen aus einer mex-Datei aufrufen können, aber dies kann funktioniert nur in C. – gnovice

+0

Zur Zeit verwende ich den C++ - Code als eine mex-Datei, aber letztendlich werde ich nicht sein, daher die Frage, ob es ein anderes C++ - Äquivalent gibt als die angenommene Antwort. – stanigator

2

Haben Sie überlegt, eine Zeichenfolge zum Hash zu verwenden? Man könnte es auch eine hexadezimale Zahl machen,

5 Zeichen

#Character 0 is in the range '0'...'7', 
#Character 1 is in the range '0'...'B', 
#Character 2 is in the range '0'...'2', 
#Character 3 is in the range '0'...'3', 
#Character 4 is in the range '0'...'2' 

Ein Teil der Schönheit des Strings als eine hexadezimale Zahl ist, dass es eine einfache int bekam ist ... err ... unsigned long long Darstellung, wenn Sie jemals konvertieren müssen.

+0

Auch wenn ich eine Zeichenfolge zum Hash verwende, wie würde ich das entsprechende Segment aus dem Template-Array bekommen? – stanigator

+0

Die Umwandlung Ihrer Zeichenfolge in 5 verschiedene Ganzzahlen, 1 für jedes Zeichen, wäre trivial. Ich benutze Matlab nicht - vermisse ich hier etwas? – Aftermathew

3

Wenn es sich um ein 2D-Array handelt, das als flaches Array angeordnet ist, hätten Sie den ersten Index mit der Größe der ersten Dimension multipliziert und den zweiten Index hinzugefügt. In der gleichen Art und Weise, mit 5 Dimensionen würden Sie so etwas wie:

index = (((i1*l1 + i2)*l2 + i3)*l3 + i4)*l4 + i5; 
+0

Das ist eigentlich die Funktion, die SUB2IND für Sie in MATLAB leistet. – gnovice

+1

Ich denke, dass die Größen in Ihrer Gleichung abweichen können. Bei einem 2-D-Array würden Sie den ersten Index mit der Größe der * zweiten * Dimension multiplizieren und den zweiten Index hinzufügen. Wenn man sich auf das Array mit der größeren Dimension erstreckt, wäre es: Index = (((i1 * l2 + i2) * l3 + i3) * l4 + i4) * l5 + i5; – gnovice

+0

Danke für den Vorschlag. Ich werde Sie wissen lassen, wie meine Diskrepanzen zwischen Ihrem Vorschlag und dem, was ich mit Sub2ind in Matlab für die gleichen Indizes erhalten habe. – stanigator

0

Ich weiß nicht, ob ich die Frage richtig verstanden, so werde ich sagen, was ich verstehe:

  • Sie haben ein Array einer gegebenen Größe, die eine multidimensionale Matrix darstellt.
  • Sie wollen einen 5-dimensionalen Vektor in die reale Position des Arrays konvertieren

ich eine Klasse zuerst schaffen würde es zu kapseln, und ich würde mit 5 Argumenten operator() definiert liefern (std :: size_t , unsigned int oder so). Dieser Operator() sollte zuerst Bereiche überprüfen (vielleicht eine Ausnahme aus, und alle Argumente in die Endposition konvertieren

Simplest Transformation wäre.

size_t position(size_t idx_r, size_t idx_l, size_t idx_rho, size_t idx_alpha, size_t idx_beta) 
{ 
    size_t pos = (((((((idx_r * dim_l) + idx_l) * dim_rho) + idx_rho) * dim_alpha) + idx_alpha) * dim_beta) + idx_beta; 
    return pos; 
} 

Wo dim_XXX die Größe der Matrix repräsentieren in Dimension XXX.

Wenn Sie viele Operationen ausführen können Sie ohne Änderung die Schnittstelle zu erhalten eine bessere Cache Trefferrate intern die Daten, welche mit einer anderen Reihenfolge zu betrachten.

Der allgemeine Algorithmus konvertiert jeden Index in einer Dimension in das folgende Dimensionselement und fügt den Offset für diese Dimension hinzu. Das einfachste Beispiel ist ein 2-dimensionales System. Um auf Zeile 3 Spalte 2 in einem 10-Spalten-Array zuzugreifen (vorausgesetzt, Sie speichern nach Zeilen und zählen von 1 auf ein Argument), berechnen Sie zuerst den Anfang der dritten Zeile, also 3 * 10 Elemente pro Zeile. Dann fügen Sie den Offset innerhalb der Zeile 2 (Spalte 2) hinzu.

Wenn Sie es auf eine 3-dimensionale Matrix wachsen, zuerst würden Sie die Ebene, die Sie suchen, indem der Ebenenindex durch die Größe der Ebene und dann den vorherigen Algorithmus finden müssen:

size_t position(size_t x, size_t y, size_t z) 
{ 
    size_t start_of_plane_z = z * dim_y * dim_x; // z * size_of_plane 
    size_t start_of_row_y = y * dim_x; // y * size_of_row 
    size_t offset_inside_row = x; 

    return start_of_plane_z + start_of_row_y + offset_inside_row; 
} 

nun einige grundlegende Algebra anwenden Sie die Gleichung in drehen kann:

size_t pos = (((z * dim_y) + y) * dim_x) + x; 

dass die Zahl der Multiplikationen reduzieren und einfacher für eine höhere Anzahl von Dimensionen zu definieren.

7

Nicht sicher, was genau Sie hier versuchen, aber haben Sie die Funktionen ind2sub und sub2ind berücksichtigt? Sie können helfen. Sie müssen sich möglicherweise über 0 gegenüber 1-basierten Indizes sorgen, da MATLAB 1-basiert ist.

--Loren

+2

+1 für "der" Loren aus Mathworks (ich nehme an?) ... willkommen in SO .... –

+0

Ja, herzlich willkommen! Es ist toll zu sehen, dass mehr MathWorker hier auftauchen ... obwohl das eine härtere Konkurrenz für die Beantwortung von Fragen bedeutet. =) – gnovice

Verwandte Themen