namespace cpp

C++ lernen, kennen, anwenden

Benutzer-Werkzeuge

Webseiten-Werkzeuge


kennen:include:valarray

<valarray>

Vektor-Arithmetik

Für Gleitkommaberechnungen mit großen Datenmengen wurde std::valarray<T> entworfen. Auf entsprechenden Maschinen können diese Operationen besonders effizient ausgeführt werden. Einfache eindimensionale Zahlenfelder sind die Grundlage solcher Berechnungen. Der Typ std::valarray<T> wird durch vier Hilfstypen zur Auswahl von Teilmengen unterstützt:

  • std::slice_array<T> und std::gslice_array<T> schneiden slices (Scheiben oder Schichten) heraus.
  • std::mask_array<T> definieren eine Teilmenge, indem jedes Element als zugehörig oder nicht markiert wird.
  • std::indirect_array<T> listet die Indizes der in Frage kommenden Element auf.

Konstruktoren

std::valarray(n) n Elemente mit Standardwert
std::valarray(wert, n) n Elemente mit wert
std::valarray(ptr, n) aus Feld ptr mit n Elementen
std::valarray(slicearr) aus Teilmengen anderer Vektoren
std::valarray(gslicearr)
std::valarray(maskarr)
std::valarray(indirectarr)
double arr[] = {0,1,2,3,4,5,6,7,8,9,10,11};
std::valarray<double> v(arr, 12);

Der Indexzugriff wählt ein oder mehrere Elemente aus.

v[n] Zugriff auf Wert an Position n
v[slice] liefert ein slice_array
v[gslice] liefert ein gslice_array
v[boolarr] liefert ein mask_array, Index ist valarray<bool>
v[indexarr] liefert ein indirect_array, Index ist valarray<size_t>

Zuweisungen sind aus std::val_array<T> und von Teilmengentypen std::slice_array<T>, std::gslice_array<T>, std::mask_array<T>, std::indirect_array<T> als auch zu Teilmengen möglich.

Verbundoperatoren wie v*=wert verändern alle Elemente um den wert. Es werden auch die üblichen zweistelligen Operatoren und mathematischen Funktionen aus <cmath> angeboten. Die zweistelligen Operationen sind für Valarrays mit gleicher Elementanzahl und für Kombinationen von Valarray mit Skalaren definiert.

std::valarray<double> v2 = 2.0 * v;
std::valarray<double> v3 = v * v2;  
std::valarray<double> v4 = v << 2;

Die Doppelpfeiloperatoren dienen nur als Schiebeoperatoren. Ein- und Ausgabe-Operatoren sind nicht definiert.

Methoden

sum() Summe aller Elemente
min() liefert kleinsten Wert
max() liefert größten Wert
size() Anzahl der Elemente
resize(n, wert=0) n Werte wert (vorheriger Inhalt geht verloren)
apply(f) liefert neues Array mit u[i]=f(v[i])
shift(i) Schieben nach links (i>0) bzw. rechts (i<0)
cshift(i) zirkuläres Schieben (liefern neues Array)

Durch Slices slice ist es möglich, ein eindimensionales Feld als Matrix mit beliebig vielen Dimensionen zu betrachten, z.B. ein 12elementiges Feld als Matrix aus 3 Zeilen mit je 4 Spalten

( 0  1  2  3 )  
( 4  5  6  7 )     [ 0 1 2 3 4 5 6 7 8 9 10 11 ]
( 8  9 10 11 )

Von diesem Feld soll eine Spalte oder eine Zeile ausgewählt werden. Mit start wird das erste Element festgelegt, size ist die Anzahl ausgewählter Elemente und stride ist der Abstand zwischen den Indizes.

int start=0, size=3, stride=4;
std::slice s(start, size, stride); // Elemente [0] [4] [8] = linke Spalte

Ein Slice ist eine Folge von Ganzzahlwerten, die als Indexfolge in einem Valarray dienen.

v[std::slice(0, v.size()/2, 2)] += 1.0;  // erhöht Werte der 1. und 3. Spalte

Manchmal muss man einen Teilbereich ansprechen, der keine Zeile oder Spalte ist, z.B. die rechte untere 2x3-Teilmatrix. Dazu sind 2 Länge-Abstand-Paare erforderlich.

size_t start = 5;
size_t len [] = { 3, 2 }; // 3 Spalten, 2 Zeilen
size_t abst[] = { 1, 4 }; // Abstand 1, Abstand 4 

Verallgemeinerte Slices gslice verwalten n Anzahlen und n Abstände.

std::valarray<size_t> laengen(len, 2);
std::valarray<size_t> abstaende(abst, 2);
std::gslice g(start, laengen, abstaende);
v[g] = 0;

Masken aus Feldern von booleschen Werten sind eine weitere Möglichkeit, Elemente auszuwählen, vor allem dann, wenn es kein einfaches Muster gibt.

bool b[] = { true, false, false, true, true };
std::valarray<bool> maske(b, 5);
v[maske] *= 2;

Mit indirekten Arrays können beliebige Elemente in beliebiger Folge ausgewählt und umsortiert werden.

size_t i[] = {0, 8, 11, 3}; 
std::valarray<size_t> index(i, 4);
std::valarray<double> ecken = v[index];

Die Indizierung mit Slices, Masken und indirekten Arrays muss so erfolgen, dass in einem Ausdruck auf kein Element zweifach Bezug genommen wird:

v[mask] = v[index]; // nicht erlaubt!

Diese Art Aliasing führt zu undefiniertem Verhalten.

kennen/include/valarray.txt · Zuletzt geändert: 2012-02-24 15:15 (Externe Bearbeitung)