TRIQS/nda 2.0.0
Multi-dimensional array library for C++
Loading...
Searching...
No Matches
ex9.cpp
1#include <nda/nda.hpp>
2#include <complex>
3#include <iostream>
4
5int main() {
8
9 // construct a rank-3 tensor of shape 2x3x4 and fill it with consecutive integers
10 auto A = nda::array<double, 3>(2, 3, 4);
11 for (int n = 0; auto &x : A) x = n++;
12 std::cout << "A = " << A << std::endl;
13 std::cout << "A.shape() = " << A.shape() << std::endl;
14
15 // default index strings: one letter per rank, starting from 'a'
16 std::cout << "default_index<3>() = " << nda::tensor::default_index<3>() << std::endl;
17
18 // in-place tensor addition: B_ijk <- alpha * A_ijk + beta * B_ijk
19 auto B = nda::array<double, 3>(2, 3, 4);
20 B = 1.0;
21 double a1 = 2.0;
22 double b1 = 3.0;
23 nda::tensor::add(a1, A, "ijk", b1, B, "ijk");
24 std::cout << "B = 2*A + 3 = " << B << std::endl;
25
26 // tensor contraction: C_il = sum_jk A_ijk * B_jkl
27 auto A2 = nda::array<double, 3>(2, 3, 4);
28 for (int n = 0; auto &x : A2) x = 0.1 * n++;
29 auto B2 = nda::array<double, 3>(3, 4, 5);
30 for (int n = 0; auto &x : B2) x = 0.1 * n++;
31 auto C2 = nda::array<double, 2>::zeros({2, 5});
32 nda::tensor::contract(1.0, A2, "ijk", B2, "jkl", 0.0, C2, "il");
33 std::cout << "C_il = A_ijk * B_jkl = " << C2 << std::endl;
34
35 // matrix-matrix multiplication expressed as a rank-2 contraction: C_ik = A_ij * B_jk
36 auto Am = nda::array<double, 2>{{1, 2, 3}, {4, 5, 6}};
37 auto Bm = nda::array<double, 2>{{7, 8}, {9, 10}, {11, 12}};
38 auto Cm = nda::array<double, 2>::zeros({2, 2});
39 nda::tensor::contract(1.0, Am, "ij", Bm, "jk", 0.0, Cm, "ik");
40 std::cout << "A_ij * B_jk = " << Cm << std::endl;
41
42 // tensor dot product (sum over all matching indices, returns a scalar)
43 auto d_indexed = nda::tensor::dot(A2, "ijk", A2, "ijk");
44 auto d_default = nda::tensor::dot(A2, A2);
45 std::cout << "dot(A2, A2) [indexed] = " << d_indexed << std::endl;
46 std::cout << "dot(A2, A2) [default] = " << d_default << std::endl;
47
48 // full tensor reductions to a scalar with different binary operations
49 std::cout << "reduce(A, SUM) = " << nda::tensor::reduce(A) << std::endl;
50 std::cout << "reduce(A, MAX) = " << nda::tensor::reduce(A, binary_op::MAX) << std::endl;
51 std::cout << "reduce(A, MIN) = " << nda::tensor::reduce(A, binary_op::MIN) << std::endl;
52 std::cout << "reduce(A, NORM_2) = " << nda::tensor::reduce(A, binary_op::NORM_2) << std::endl;
53
54 // in-place tensor scaling with an optional element-wise unary operation
55 auto S = nda::array<double, 3>(2, 3, 4);
56 for (int n = 0; auto &x : S) x = static_cast<double>(n++ + 1);
57 nda::tensor::scale(2.0, S);
58 std::cout << "2 * S = " << S << std::endl;
59 nda::tensor::scale(1.0, S, unary_op::SQRT);
60 std::cout << "sqrt(2 * S) = " << S << std::endl;
61
62 // CONJ acts on a complex tensor
63 using cplx = std::complex<double>;
64 auto Z = nda::array<cplx, 3>(2, 2, 2);
65 for (int n = 0; auto &x : Z) {
66 x = cplx(n, n + 1);
67 ++n;
68 }
69 nda::tensor::scale(cplx{1.0, 0.0}, Z, unary_op::CONJ);
70 std::cout << "conj(Z) = " << Z << std::endl;
71
72 // element-wise binary operation: B_ijk <- op(alpha * A_ijk, beta * B_ijk)
73 auto E1 = nda::array<double, 3>(2, 3, 4);
74 for (int n = 0; auto &x : E1) x = static_cast<double>(n++);
75 auto E2 = nda::array<double, 3>(2, 3, 4);
76 E2 = 1.0;
77 nda::tensor::elementwise(1.0, E1, "ijk", 1.0, E2, "ijk", binary_op::SUM);
78 std::cout << "E2 <- E1 + E2 = " << E2 << std::endl;
79
80 auto F1 = nda::array<double, 3>(2, 3, 4);
81 F1 = 2.0;
82 auto F2 = nda::array<double, 3>(2, 3, 4);
83 F2 = 3.0;
84 nda::tensor::elementwise(1.0, F1, "ijk", 1.0, F2, "ijk", binary_op::PROD);
85 std::cout << "F2 <- F1 * F2 = " << F2 << std::endl;
86}
static basic_array zeros(std::array< Int, Rank > const &shape)
basic_array< ValueType, Rank, Layout, 'A', ContainerPolicy > array
Alias template of an nda::basic_array with an 'A' algebra.
void add(get_value_t< A > alpha, A const &a, std::string_view idx_a, get_value_t< A > beta, B &&b, std::string_view idx_b)
Tensor addition with cuTENSOR/TBLIS/nda dispatch.
Definition add.hpp:63
void contract(get_value_t< A > alpha, A const &a, std::string_view idx_a, B const &b, std::string_view idx_b, get_value_t< A > beta, C &&c, std::string_view idx_c)
Tensor contraction with cuTENSOR/TBLIS dispatch.
Definition contract.hpp:66
void scale(get_value_t< A > alpha, A &&a, unary_op op=unary_op::IDENTITY)
In-place tensor scaling with cuTENSOR/TBLIS/nda dispatch and optional element-wise unary operation.
Definition scale.hpp:55
get_value_t< A > dot(A const &a, std::string_view idx_a, B const &b, std::string_view idx_b)
Full tensor dot product with cuTENSOR/TBLIS/nda dispatch.
Definition dot.hpp:68
get_value_t< A > reduce(A const &a, binary_op op_reduce=binary_op::SUM)
Full tensor reduction with cuTENSOR/TBLIS/nda dispatch.
Definition reduce.hpp:67
void elementwise(get_value_t< A > alpha, A const &a, std::string_view idx_a, get_value_t< A > beta, B &&b, std::string_view idx_b, binary_op op=binary_op::SUM)
In-place elementwise binary tensor operation with cuTENSOR/nda dispatch.
unary_op
Unary element-wise operations for tensor operations.
Definition tools.hpp:103
binary_op
Binary operations for tensor operations.
Definition tools.hpp:67
std::string_view default_index()
Generate a default index string ("abc...") of a given length.
Definition tools.hpp:265
Includes all relevant headers for the core nda library.