Skip to content

Commit 77fc1ac

Browse files
committed
eckit::linalg::SparseMatrix::Allocator StandardContainerAllocator
1 parent c85a538 commit 77fc1ac

File tree

4 files changed

+141
-0
lines changed

4 files changed

+141
-0
lines changed

src/eckit/linalg/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ list( APPEND eckit_la_srcs
2424
allocator/NonOwningAllocator.h
2525
allocator/StandardAllocator.cc
2626
allocator/StandardAllocator.h
27+
allocator/StandardContainerAllocator.cc
28+
allocator/StandardContainerAllocator.h
2729
dense/LinearAlgebraGeneric.cc
2830
dense/LinearAlgebraGeneric.h
2931
sparse/LinearAlgebraGeneric.cc
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*
2+
* (C) Copyright 2024- ECMWF.
3+
*
4+
* This software is licensed under the terms of the Apache Licence Version 2.0
5+
* which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
6+
* In applying this licence, ECMWF does not waive the privileges and immunities
7+
* granted to it by virtue of its status as an intergovernmental organisation
8+
* nor does it submit to any jurisdiction.
9+
*/
10+
11+
12+
#include "eckit/linalg/allocator/StandardContainerAllocator.h"
13+
14+
#include <numeric>
15+
#include <ostream>
16+
17+
#include "eckit/exception/Exceptions.h"
18+
19+
20+
namespace eckit::linalg::allocator {
21+
22+
23+
StandardContainerAllocator::StandardContainerAllocator(Size Nr, Size Nc, const container_type& cont) :
24+
Nr_(Nr), Nc_(Nc), nnz_([Nc](const auto& cont) {
25+
return std::accumulate(cont.begin(), cont.end(), 0, [Nc](const auto& acc, const auto& row) {
26+
ASSERT(row.empty() || row.rbegin()->first < Nc);
27+
return acc + row.size();
28+
});
29+
}(cont)) {
30+
ASSERT(Nr == cont.size());
31+
32+
ia_.reserve(Nr_ + 1);
33+
ja_.reserve(nnz_);
34+
a_.reserve(nnz_);
35+
36+
ia_.emplace_back(0);
37+
for (const auto& row : cont) {
38+
ia_.emplace_back(ia_.back() + row.size());
39+
for (const auto& [col, val] : row) {
40+
ja_.emplace_back(static_cast<Index>(col));
41+
a_.emplace_back(val);
42+
}
43+
}
44+
}
45+
46+
47+
SparseMatrix::Layout StandardContainerAllocator::StandardContainerAllocator::allocate(SparseMatrix::Shape& shape) {
48+
shape.size_ = nnz_;
49+
shape.rows_ = Nr_;
50+
shape.cols_ = Nc_;
51+
52+
SparseMatrix::Layout layout;
53+
layout.outer_ = ia_.data();
54+
layout.inner_ = ja_.data();
55+
layout.data_ = a_.data();
56+
57+
return layout;
58+
}
59+
60+
61+
void StandardContainerAllocator::deallocate(SparseMatrix::Layout, SparseMatrix::Shape) {
62+
ia_.clear();
63+
ja_.clear();
64+
a_.clear();
65+
}
66+
67+
68+
bool StandardContainerAllocator::inSharedMemory() const {
69+
return false;
70+
}
71+
72+
73+
void StandardContainerAllocator::print(std::ostream& out) const {
74+
out << "StandardContainerAllocator[Nr=" << Nr_ << ",Nc=" << Nc_ << ",nnz=" << nnz_ << "]";
75+
}
76+
77+
78+
} // namespace eckit::linalg::allocator
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* (C) Copyright 2024- ECMWF.
3+
*
4+
* This software is licensed under the terms of the Apache Licence Version 2.0
5+
* which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
6+
* In applying this licence, ECMWF does not waive the privileges and immunities
7+
* granted to it by virtue of its status as an intergovernmental organisation
8+
* nor does it submit to any jurisdiction.
9+
*/
10+
11+
12+
#pragma once
13+
14+
#include <map>
15+
#include <vector>
16+
17+
#include "eckit/linalg/SparseMatrix.h"
18+
19+
20+
namespace eckit::linalg::allocator {
21+
22+
23+
/**
24+
* @brief In-place allocator for sparse matrices, directly mapping supporting arrays including from another
25+
* SparseMatrix. It is able to provide a "view".
26+
*/
27+
class StandardContainerAllocator : public SparseMatrix::Allocator {
28+
public:
29+
using container_type = std::vector<std::map<Size, Scalar>>;
30+
31+
StandardContainerAllocator(Size Nr, Size Nc, const container_type&);
32+
33+
SparseMatrix::Layout allocate(SparseMatrix::Shape&) override;
34+
35+
void deallocate(SparseMatrix::Layout, SparseMatrix::Shape) override;
36+
bool inSharedMemory() const override;
37+
void print(std::ostream&) const override;
38+
39+
private:
40+
const Size Nr_;
41+
const Size Nc_;
42+
const Size nnz_;
43+
44+
std::vector<SparseMatrix::UIndex> ia_;
45+
std::vector<Index> ja_;
46+
std::vector<Scalar> a_;
47+
};
48+
49+
50+
} // namespace eckit::linalg::allocator

tests/linalg/test_la_sparse.cc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "util.h"
1313

1414
#include "eckit/linalg/allocator/NonOwningAllocator.h"
15+
#include "eckit/linalg/allocator/StandardContainerAllocator.h"
1516

1617
using namespace eckit::linalg;
1718

@@ -212,6 +213,16 @@ CASE("eckit la sparse") {
212213
EXPECT(G.A.inner() == GA.inner());
213214
EXPECT(G.A.data() == GA.data());
214215
}
216+
217+
SECTION("containers allocator") {
218+
SparseMatrix FA(new allocator::StandardContainerAllocator(3, 3, {{{0, 2.}, {2, -3.}}, {{1, 2.}}, {{2, 2.}}}));
219+
220+
EXPECT(equal_sparse_matrix(FA, F.A.outer(), F.A.inner(), F.A.data()));
221+
222+
SparseMatrix GA(new allocator::StandardContainerAllocator(2, 3, {{{0, 1.}, {2, 2.}}, {{0, 3.}, {1, 4.}}}));
223+
224+
EXPECT(equal_sparse_matrix(GA, GA.outer(), G.A.inner(), G.A.data()));
225+
}
215226
}
216227

217228
//----------------------------------------------------------------------------------------------------------------------

0 commit comments

Comments
 (0)