C ++ 26'ya genel bir bakış: kütüphanedeki aritmetik uzantı
C ++ 26 kütüphanesindeki yeni özelliklere genel bakışımdan sonra, şimdi ikinci yazıda aritmetik genişlemeyi kısaca sunuyorum.
Rainer Grimm yıllardır yazılım mimarı, ekip ve eğitim müdürü olarak çalıştı. C ++ programlama dilleri, Python ve Haskell hakkında makaleler yazmayı seviyor, ancak uzman konferanslarla konuşmayı da seviyor. Modern C ++ blogunda, C ++ tutkusuyla yoğun bir şekilde ilgileniyor.
std::submdspan
C ++ 26'da yeni Sottospante std::submdspan. Mevcut sürenin bir alt grubudur std::mdspan (C ++ 23), onu C ++ 23'e dönüştürmemişti.
C ++ 26 ile devam etmeden önce, C ++ 23'e kısa bir sapma yapmam gerekiyor.
std::mdspan
A std::mdspan Nesnelerin tutarlı bir bölümüne ait olmayan çok boyutlu bir vizyondur. Tutarlı nesneler dizisi, basit bir C dizisi olabilir, boyutta bir işaretçi, bir std::array oa std::string Olmak. Bu çok boyutlu görünüme genellikle çok boyutlu dizi denir.
Her boyutun boyutu ve boyutu sayısı çok boyutlu dizinin şeklini belirler. Boyut sayısına sıralama denir, her boyutun boyutu uzantı olarak. Boyutu std::mdspan BEN0 olmayan tüm boyutların ürünü. Birinin unsurlarında std::mdspan Çok boyutlu dizin operatörü ile [] erişim.
A'nın her boyutu std::mdspan Olabilmek statik VEYA Dinamik uzatma Sahip olmak. Statik uzatma Bu, uzunluğunuzun derleme döneminde belirtildiği anlamına gelir; Dinamik uzatma Bu, uzunluğunuzun sonunda belirtildiği anlamına gelir.
C ++ 17'deki sınıf modeli (CTAG) konusunun türetilmesi sayesinde, derleyici genellikle modelin konularını başlatma verilerinin türlerinden otomatik olarak türetebilir.
// mdspan.cpp
#include <mdspan>
#include <iostream>
#include <vector>
int main() {
std::vector myVec{1, 2, 3, 4, 5, 6, 7, 8}; // (1)
std::mdspan m{myVec.data(), 2, 4}; // (2)
std::cout << "m.rank(): " << m.rank() << 'n'; // (4)
for (std::size_t i = 0; i < m.extent(0); ++i) { // (6)
for (std::size_t j = 0; j < m.extent(1); ++j) { // (7)
std::cout << m[i, j] << ' '; // (8)
}
std::cout << 'n';
}
std::cout << 'n';
std::mdspan m2{myVec.data(), 4, 2}; // (3)
std::cout << "m2.rank(): " << m2.rank() << 'n'; // (5)
for (std::size_t i = 0; i < m2.extent(0); ++i) {
for (std::size_t j = 0; j < m2.extent(1); ++j) {
std::cout << m2[i, j] << ' ';
}
std::cout << 'n';
}
}
Bu örnekte, sınıf modelleri konusunun çıkarımını üç kez kullanıyorum. (1) satırda biri için std::vector Biri için (2) ve (3) satırlarında kullanılır std::mdspan. İlk iki boyutlu dizi m Şekli var (2, 4), ikincisi m2 form (4, 2). (4) ve (5) satırlarında her ikisinin std::mdspan görüntülenir. Her boyutun genişlemesi (satır 6 ve 7) ve çevrimiçi dizin (8) operatörü sayesinde, çok boyutlu dizilerle işlemek kolaydır.
Burada C ++ 23 ve Guido'ya Guido'ya C ++ 26 std::submdspan Güçlü.
std::submdspan
İşlev std::submdspan Başlangıçta genel işlevselliği için çok önemliydi mdspan görüş. Ancak revizyondaki zamansal kısıtlamalar nedeniyle, ilk kez kaldırıldı. mdspan C ++ 23'te kaydedilebilir.
Bir yaratılış std::submdspan Basit. İlk parametre bir mdspan xVe gerisi x.rank()-Pamerler dilimlere özgüdür, her boyut için bir tane için bir x. Dilimin özellikleri alanın unsurları olarak tanımlanır [0,x.extent(d)) Teil des mehrdimensionalen Indexraums des zurückgegebenen mdspan sind.
Dies führt zu der folgenden grundlegenden Signatur:
template<class T, class E, class L, class A,
class ... SliceArgs)
auto submdspan(mdspan<T,E,L,A> x, SliceArgs ... args);
Dabei muss E.rank() gleich sizeof...(SliceArgs) sein.
Das Proposal P2630R4 enthält neben der Definition eines std::submdspan auch einige Beispiele für ein mdspan mit Rang 1.
int* ptr = ...;
int N = ...;
mdspan a(ptr, N);
// subspan of a single element
auto a_sub1 = submdspan(a, 1);
static_assert(decltype(a_sub1)::rank() == 0);
assert(&a_sub1() == &a(1));
// subrange
auto a_sub2 = submdspan(a, tuple{1, 4});
static_assert(decltype(a_sub2)::rank() == 1);
assert(&a_sub2(0) == &a(1));
assert(a_sub2.extent(0) == 3);
// subrange with stride
auto a_sub3 = submdspan(a, strided_slice{1, 7, 2});
static_assert(decltype(a_sub3)::rank() == 1);
assert(&a_sub3(0) == &a(1));
assert(&a_sub3(3) == &a(7));
assert(a_sub3.extent(0) == 4);
// full range
auto a_sub4 = submdspan(a, full_extent);
static_assert(decltype(a_sub4)::rank() == 1);
assert(a_sub4(0) == a(0));
assert(a_sub4.extent(0) == a.extent(0));
Die gleichen Regeln gelten für den mehrdimensionalen Anwendungsfall:
int* ptr = ...;
int N0 = ..., N1 = ..., N2 = ..., N3 = ..., N4 = ...;
mdspan a(ptr, N0, N1, N2, N3, N4);
auto a_sub = submdspan(a,full_extent_t(), 3, strided_slice{2,N2-5, 2}, 4, tuple{3, N5-5});
// two integral specifiers so the rank is reduced by 2
static_assert(decltype(a_sub) == 3);
// 1st dimension is taking the whole extent
assert(a_sub.extent(0) == a.extent(0));
// the new 2nd dimension corresponds to the old 3rd dimension
assert(a_sub.extent(1) == (a.extent(2) - 5)/2);
assert(a_sub.stride(1) == a.stride(2)*2);
// the new 3rd dimension corresponds to the old 5th dimension
assert(a_sub.extent(2) == a.extent(4)-8);
assert(&a_sub(1,5,7) == &a(1, 3, 2+5*2, 4, 3+7));
Dies ist allerdings noch nicht das Ende der Unterstützung für C++26.
<linalg> – lineare Algebra
linalg ist eine auf BLAS (Basic Linear Algebra Subprograms) basierende, freie Schnittstelle für lineare Algebra. BLAS ist laut Wikipedia eine Spezifikation, die eine Reihe von Low-Level-Routinen zur Durchführung gängiger linearer Algebra-Operationen wie Vektoraddition, skalare Multiplikation, Punktprodukte, Linearkombinationen und Matrixmultiplikation vorschreibt. Sie sind de facto der Standard für Low-Level-Routinen in Bibliotheken der linearen Algebra.
Das Proposal P1673R13 schlägt eine Schnittstelle für die Dense Linear Algebra der C++-Standardbibliothek vor, die auf den Dense Basic Linear Algebra Subroutines (BLAS) basiert. Dies entspricht einer Teilmenge des BLAS-Standards.
Diese lineare Algebra wurde in der C++-Community lange vermisst. Gemäß dem Proposal ist der folgende Codeausschnitt das “Hallo Welt” der linearen Algebra. Er skaliert die Elemente eines 1-D-mdspan um einen konstanten Faktor, zuerst sequenziell, dann parallel:
constexpr size_t N = 40;
std::vector<double> x_vec(N);
mdspan x(x_vec.data(), N);
for(size_t i = 0; i < N; ++i) {
x = çift (i); } Lininalg :: ölçek (2.0, x); // x = 2.0 * x linalg :: ölçek (std :: yürütme :: par_unseq, 3.0, x); (size_t i = 0; i için == 6.0 * çift (i)); }
Sırada ne var?
C ++ 26'daki yenilikler hiç de ayrıntılı değildir. Bir sonraki yazımda Satürn'ün aritmetiği ve C ++ 26'daki rekabetin desteği üzerine yazıyorum.
(harita)
C ++ 26'ya genel bir bakış: kütüphanedeki aritmetik uzantı
C ++ 26 kütüphanesindeki yeni özelliklere genel bakışımdan sonra, şimdi ikinci yazıda aritmetik genişlemeyi kısaca sunuyorum.


Rainer Grimm yıllardır yazılım mimarı, ekip ve eğitim müdürü olarak çalıştı. C ++ programlama dilleri, Python ve Haskell hakkında makaleler yazmayı seviyor, ancak uzman konferanslarla konuşmayı da seviyor. Modern C ++ blogunda, C ++ tutkusuyla yoğun bir şekilde ilgileniyor.
std::submdspan
C ++ 26'da yeni Sottospante std::submdspan. Mevcut sürenin bir alt grubudur std::mdspan (C ++ 23), onu C ++ 23'e dönüştürmemişti.
C ++ 26 ile devam etmeden önce, C ++ 23'e kısa bir sapma yapmam gerekiyor.
std::mdspan
A std::mdspan Nesnelerin tutarlı bir bölümüne ait olmayan çok boyutlu bir vizyondur. Tutarlı nesneler dizisi, basit bir C dizisi olabilir, boyutta bir işaretçi, bir std::array oa std::string Olmak. Bu çok boyutlu görünüme genellikle çok boyutlu dizi denir.
Her boyutun boyutu ve boyutu sayısı çok boyutlu dizinin şeklini belirler. Boyut sayısına sıralama denir, her boyutun boyutu uzantı olarak. Boyutu std::mdspan BEN0 olmayan tüm boyutların ürünü. Birinin unsurlarında std::mdspan Çok boyutlu dizin operatörü ile [] erişim.
A'nın her boyutu std::mdspan Olabilmek statik VEYA Dinamik uzatma Sahip olmak. Statik uzatma Bu, uzunluğunuzun derleme döneminde belirtildiği anlamına gelir; Dinamik uzatma Bu, uzunluğunuzun sonunda belirtildiği anlamına gelir.
C ++ 17'deki sınıf modeli (CTAG) konusunun türetilmesi sayesinde, derleyici genellikle modelin konularını başlatma verilerinin türlerinden otomatik olarak türetebilir.
// mdspan.cpp
#include <mdspan>
#include <iostream>
#include <vector>
int main() {
std::vector myVec{1, 2, 3, 4, 5, 6, 7, 8}; // (1)
std::mdspan m{myVec.data(), 2, 4}; // (2)
std::cout << "m.rank(): " << m.rank() << 'n'; // (4)
for (std::size_t i = 0; i < m.extent(0); ++i) { // (6)
for (std::size_t j = 0; j < m.extent(1); ++j) { // (7)
std::cout << m[i, j] << ' '; // (8)
}
std::cout << 'n';
}
std::cout << 'n';
std::mdspan m2{myVec.data(), 4, 2}; // (3)
std::cout << "m2.rank(): " << m2.rank() << 'n'; // (5)
for (std::size_t i = 0; i < m2.extent(0); ++i) {
for (std::size_t j = 0; j < m2.extent(1); ++j) {
std::cout << m2[i, j] << ' ';
}
std::cout << 'n';
}
}
Bu örnekte, sınıf modelleri konusunun çıkarımını üç kez kullanıyorum. (1) satırda biri için std::vector Biri için (2) ve (3) satırlarında kullanılır std::mdspan. İlk iki boyutlu dizi m Şekli var (2, 4), ikincisi m2 form (4, 2). (4) ve (5) satırlarında her ikisinin std::mdspan görüntülenir. Her boyutun genişlemesi (satır 6 ve 7) ve çevrimiçi dizin (8) operatörü sayesinde, çok boyutlu dizilerle işlemek kolaydır.
Burada C ++ 23 ve Guido'ya Guido'ya C ++ 26 std::submdspan Güçlü.
std::submdspan
İşlev std::submdspan Başlangıçta genel işlevselliği için çok önemliydi mdspan görüş. Ancak revizyondaki zamansal kısıtlamalar nedeniyle, ilk kez kaldırıldı. mdspan C ++ 23'te kaydedilebilir.
Bir yaratılış std::submdspan Basit. İlk parametre bir mdspan xVe gerisi x.rank()-Pamerler dilimlere özgüdür, her boyut için bir tane için bir x. Dilimin özellikleri alanın unsurları olarak tanımlanır [0,x.extent(d)) Teil des mehrdimensionalen Indexraums des zurückgegebenen mdspan sind.
Dies führt zu der folgenden grundlegenden Signatur:
template<class T, class E, class L, class A,
class ... SliceArgs)
auto submdspan(mdspan<T,E,L,A> x, SliceArgs ... args);
Dabei muss E.rank() gleich sizeof...(SliceArgs) sein.
Das Proposal P2630R4 enthält neben der Definition eines std::submdspan auch einige Beispiele für ein mdspan mit Rang 1.
int* ptr = ...;
int N = ...;
mdspan a(ptr, N);
// subspan of a single element
auto a_sub1 = submdspan(a, 1);
static_assert(decltype(a_sub1)::rank() == 0);
assert(&a_sub1() == &a(1));
// subrange
auto a_sub2 = submdspan(a, tuple{1, 4});
static_assert(decltype(a_sub2)::rank() == 1);
assert(&a_sub2(0) == &a(1));
assert(a_sub2.extent(0) == 3);
// subrange with stride
auto a_sub3 = submdspan(a, strided_slice{1, 7, 2});
static_assert(decltype(a_sub3)::rank() == 1);
assert(&a_sub3(0) == &a(1));
assert(&a_sub3(3) == &a(7));
assert(a_sub3.extent(0) == 4);
// full range
auto a_sub4 = submdspan(a, full_extent);
static_assert(decltype(a_sub4)::rank() == 1);
assert(a_sub4(0) == a(0));
assert(a_sub4.extent(0) == a.extent(0));
Die gleichen Regeln gelten für den mehrdimensionalen Anwendungsfall:
int* ptr = ...;
int N0 = ..., N1 = ..., N2 = ..., N3 = ..., N4 = ...;
mdspan a(ptr, N0, N1, N2, N3, N4);
auto a_sub = submdspan(a,full_extent_t(), 3, strided_slice{2,N2-5, 2}, 4, tuple{3, N5-5});
// two integral specifiers so the rank is reduced by 2
static_assert(decltype(a_sub) == 3);
// 1st dimension is taking the whole extent
assert(a_sub.extent(0) == a.extent(0));
// the new 2nd dimension corresponds to the old 3rd dimension
assert(a_sub.extent(1) == (a.extent(2) - 5)/2);
assert(a_sub.stride(1) == a.stride(2)*2);
// the new 3rd dimension corresponds to the old 5th dimension
assert(a_sub.extent(2) == a.extent(4)-8);
assert(&a_sub(1,5,7) == &a(1, 3, 2+5*2, 4, 3+7));
Dies ist allerdings noch nicht das Ende der Unterstützung für C++26.
<linalg> – lineare Algebra
linalg ist eine auf BLAS (Basic Linear Algebra Subprograms) basierende, freie Schnittstelle für lineare Algebra. BLAS ist laut Wikipedia eine Spezifikation, die eine Reihe von Low-Level-Routinen zur Durchführung gängiger linearer Algebra-Operationen wie Vektoraddition, skalare Multiplikation, Punktprodukte, Linearkombinationen und Matrixmultiplikation vorschreibt. Sie sind de facto der Standard für Low-Level-Routinen in Bibliotheken der linearen Algebra.
Das Proposal P1673R13 schlägt eine Schnittstelle für die Dense Linear Algebra der C++-Standardbibliothek vor, die auf den Dense Basic Linear Algebra Subroutines (BLAS) basiert. Dies entspricht einer Teilmenge des BLAS-Standards.
Diese lineare Algebra wurde in der C++-Community lange vermisst. Gemäß dem Proposal ist der folgende Codeausschnitt das “Hallo Welt” der linearen Algebra. Er skaliert die Elemente eines 1-D-mdspan um einen konstanten Faktor, zuerst sequenziell, dann parallel:
constexpr size_t N = 40;
std::vector<double> x_vec(N);
mdspan x(x_vec.data(), N);
for(size_t i = 0; i < N; ++i) {
x = çift (i); } Lininalg :: ölçek (2.0, x); // x = 2.0 * x linalg :: ölçek (std :: yürütme :: par_unseq, 3.0, x); (size_t i = 0; i için == 6.0 * çift (i)); }
Sırada ne var?
C ++ 26'daki yenilikler hiç de ayrıntılı değildir. Bir sonraki yazımda Satürn'ün aritmetiği ve C ++ 26'daki rekabetin desteği üzerine yazıyorum.
(harita)