Frage nach der Speicherbelegung...
-
Hallo Forum...
Ich habe folgenden Quelltext(stark vereinfacht):#include <R.h> #include <Rinternals.h> typedef unsigned int BLOCK; const int BITS_PER_BLOCK = sizeof(BLOCK) * 8; // [...] void main(SEXP A) { // SEXP ist in dem Fall ein Matrix Objekt aus R int N, NB; BLOCK *m; N = INTEGER(getAttrib(A, R_DimSymbol))[0]; // speichert einfach die Spaltengröße der quadratischen Matrix A NB = N / BITS_PER_BLOCK + 1; m = (BLOCK *) R_alloc(sizeof(BLOCK), NB * N) // Beschreibung zur Funktion R_alloc folgt unten BLOCK *pos = m; BLOCK shift = 0; BLOCK *rstart = pos; for (int col = 0; col < N; col++) { if (abs(INTEGER(A)[col * N ]) > 0) // Es wird geprüft ob das Element der Matrix A in Spalte col (, 0. Zeile) größer als 0 ist shift |= (1 << (col & (BITS_PER_BLOCK - 1))); if ((col & (BITS_PER_BLOCK - 1)) == BITS_PER_BLOCK - 1) { (*pos++) = shift; shift = 0; } } }
Erstmal die Beschreibung zur Funktion R_alloc:
Aus einer R Manual
Use
char* R_alloc(long n, int size)
which allocates n units of size bytes each.Nun Kommen meine Fragen...
typedef unsigned int BLOCK; const int BITS_PER_BLOCK = sizeof(BLOCK) * 8;
BLOCK belegt also 4 Bytes (unsigned int eben, oder)?
BITS_PER_BLOCK hingegen ist (wenn BLOCK 4 Bytes belegt) 4 * 8 = 32. Das bedeutet BITS_PER_BLOCK belegt 4 Bytes, wobei es den Wert 32 enthält. Stimmt das?NB = N / BITS_PER_BLOCK + 1;
Ich glaube diese Rechnung wird ausgeführt, damit man mit NB angeben kann, wieviele Speicherplätze des types Int (BIT_PER_BYTE = 32 Bit)man braucht, um eine ganze Reihe aus der Matrix unterzubringen, wenn man jedes Element in 1 Bit schreibt. (Die Matrix A besteht nur aus 1 und 0, also werden da nur Bits entnommen).
m = (BLOCK *) R_alloc(sizeof(BLOCK), NB * N)
Laut obiger Beschreibung werden also 4 Einheiten von NB*N großen Speicherfeldern angelegt. So ganz verstehe ich diese Speicherweise noch nicht. Insgesamt werden also 4 * NB*N Bytes reserviert... Genug also um die N*N große Matrix unterzubringen, wenn man jedes Element in ein Bit schreibt?
m zeigt ja dabei auf die 1. Speicheradresse des angelegten Speicherplatzes?shift |= (1 << (col & (BITS_PER_BLOCK - 1))); if ((col & (BITS_PER_BLOCK - 1)) == BITS_PER_BLOCK - 1) { (*pos++) = shift; shift = 0;
Das passiert nur, wenn das gerade kontrollierte Element aus A = 1 (also > 0) ist. Im Prinzip werden damit die Bits der 0. Zeile aus A in shift hineinkopiert(nur in umgekehrter Reihenfolge). Dabei wird die 1 maximal bis zur Stelle 32 verschoben, sonst würde ja der Speicher in shift (4 Bytes - Größe von BLOCK) überschritten, oder?
Weil ich noch nicht ganz so sicher in Zeigern bin, nur noch zur Kontrolle:
Der Pointer pos zeigt ja auf die Speicheradresse des großen Feldes (wo m draufgezeigt hat), also schreibt dieser durch (*pos++) = shift; erst den Wert von shift in die ersten 4 Bytes und rutscht dann um seinen Variablentyp (BLOCK), also um 4 Bytes weiter, oder?Insgesamt wird ja aber die Reihenfolge der Zeile aus A durcheinandergebracht, oder? Angenommen die Bits sind jetzt Zahlen (die einfach nur 1 Bit belegen) und A hat die folgende Zeile:
1 2 3 4 5 6 7 8 9 10 11 12
Wenn ein Speicherblock jetzt mal nicht 32 Stellen, sondern nur 4 fast, dann legt das Programm die Zeile ja wie folgt im Speicher an:
4 3 2 1 - 8 7 6 5 - 12 11 10 9
Stimmt das so?