TRIQS/nda
2.0.0
Multi-dimensional array library for C++
Toggle main menu visibility
Loading...
Searching...
No Matches
bound_check_worker.hpp
Go to the documentation of this file.
1
// Copyright (c) 2018--present, The Simons Foundation
2
// This file is part of TRIQS/nda and is licensed under the Apache License, Version 2.0.
3
// SPDX-License-Identifier: Apache-2.0
4
// See LICENSE in the root of this distribution for details.
5
10
11
#pragma once
12
13
#include "
./range.hpp
"
14
15
#include <cstdint>
16
#include <stdexcept>
17
#include <sstream>
18
19
namespace
nda::detail {
20
21
// Check the bounds when accessing single elements or slices of an array/view.
22
struct
bound_check_worker {
23
// Shape of the array/view.
24
long
const
*lengths{};
25
26
// Error code to store the positions of the arguments which are out of bounds.
27
uint32_t error_code = 0;
28
29
// Number of dimensions that are covered by a given nda::ellipsis.
30
int
ellipsis_loss = 0;
31
32
// Current dimension to be checked.
33
int
N = 0;
34
35
// Check if the given index is within the bounds of the array/view.
36
void
check_current_dim(
long
idx) {
37
if
((idx < 0) or (idx >= lengths[N])) { error_code += 1ul << N; }
38
++N;
39
}
40
41
// Check if the given nda::range is within the bounds of the array/view.
42
void
check_current_dim(range
const
&r) {
43
if
(r.size() > 0) {
44
auto
first_idx = r.first();
45
auto
last_idx = first_idx + (r.size() - 1) * r.step();
46
if
(first_idx < 0 or first_idx >= lengths[N] or last_idx < 0 or last_idx >= lengths[N]) error_code += 1ul << N;
47
}
48
++N;
49
}
50
51
// Check the bounds when an nda::range::all_t is encountered (no need to check anything).
52
void
check_current_dim(range::all_t) { ++N; }
53
54
// Check the bounds when an nda::ellipsis is encountered (no need to check anything).
55
void
check_current_dim(ellipsis) { N += ellipsis_loss + 1; }
56
57
// Accumulate an error message for the current dimension and index.
58
void
accumulate_error_msg(std::stringstream &fs,
long
idx) {
59
if
(error_code & (1ull << N)) fs <<
"Argument "
<< N <<
" = "
<< idx <<
" is not within [0,"
<< lengths[N] <<
"[.\n"
;
60
N++;
61
}
62
63
// Accumulate an error message for the current dimension and nda::range.
64
void
accumulate_error_msg(std::stringstream &fs, range
const
&r) {
65
if
(error_code & (1ull << N)) fs <<
"Argument "
<< N <<
" = "
<< r <<
" is not within [0,"
<< lengths[N] <<
"[.\n"
;
66
++N;
67
}
68
69
// Accumulate an error message for the current dimension and nda::range::all_t.
70
void
accumulate_error_msg(std::stringstream &, range::all_t) { ++N; }
71
72
// Accumulate an error message for the current dimension and nda::ellipsis.
73
void
accumulate_error_msg(std::stringstream &, ellipsis) { N += ellipsis_loss + 1; }
74
};
75
76
}
// namespace nda::detail
77
78
namespace
nda {
79
92
template
<
typename
... Args>
93
void
assert_in_bounds
(
int
rank,
long
const
*lengths, Args
const
&...args) {
94
// initialize the bounds checker
95
detail::bound_check_worker w{lengths};
96
97
// number of dimensions covered by an nda::ellipsis
98
w.ellipsis_loss = rank -
sizeof
...(Args);
99
100
// check the bounds on each argument/index
101
(w.check_current_dim(args), ...);
102
103
// if no error, stop here
104
if
(!w.error_code)
return
;
105
106
// accumulate error message and throw
107
w.N = 0;
108
std::stringstream fs;
109
(w.accumulate_error_msg(fs, args), ...);
110
throw
std::runtime_error(
"Index/Range out of bounds:\n"
+ fs.str());
111
}
112
113
}
// namespace nda
nda::assert_in_bounds
void assert_in_bounds(int rank, long const *lengths, Args const &...args)
Check if the given indices/arguments are within the bounds of an array/view.
Definition
bound_check_worker.hpp:93
range.hpp
Includes the itertools header and provides some additional utilities.
nda
layout
bound_check_worker.hpp
Generated by
1.17.0