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.