Lattice Land Core Library
Loading...
Searching...
No Matches
env.hpp
Go to the documentation of this file.
1// Copyright 2021 Pierre Talbot
2
3#ifndef LALA_CORE_ENV_HPP
4#define LALA_CORE_ENV_HPP
5
6#include "battery/utility.hpp"
7#include "battery/vector.hpp"
8#include "battery/string.hpp"
9#include "battery/tuple.hpp"
10#include "battery/variant.hpp"
11#include "ast.hpp"
12#include "diagnostics.hpp"
13
14#include <string>
15#include <unordered_map>
16
17namespace lala {
18
19template<class Allocator>
20struct Variable {
21 template<class T>
22 using bvector = battery::vector<T, Allocator>;
23 using bstring = battery::string<Allocator>;
24
28
30 Variable(const Variable<Allocator>&) = default;
31
32 CUDA NI Variable(const bstring& name, const Sort<Allocator>& sort, AVar av, const Allocator& allocator = Allocator{})
33 : name(name, allocator), sort(sort, allocator), avars(allocator)
34 {
35 avars.push_back(av);
36 }
37
38 template <class Alloc2>
39 CUDA NI Variable(const Variable<Alloc2>& other, const Allocator& allocator = Allocator{})
40 : name(other.name, allocator)
41 , sort(other.sort, allocator)
42 , avars(other.avars, allocator)
43 {}
44
45 CUDA NI thrust::optional<AVar> avar_of(AType aty) const {
46 for(int i = 0; i < avars.size(); ++i) {
47 if(avars[i].aty() == aty) {
48 return avars[i];
49 }
50 }
51 return {};
52 }
53};
54
55template <class Allocator>
57 using allocator_type = Allocator;
60
61 template<class T>
62 using bvector = battery::vector<T, Allocator>;
63 using bstring = battery::string<Allocator>;
64
66
70
71 template <class Alloc2>
75
76 // For this operator=, we suppose `lvars` is updated before.
77 CUDA this_type& operator=(this_type&& other) {
78 return *this;
79 }
80
81 CUDA this_type& operator=(const this_type& other) {
82 return *this;
83 }
84
85 CUDA thrust::optional<size_t> lvar_index_of(const char* lv) const {
86 for(size_t i = 0; i < lvars->size(); ++i) {
87 if((*lvars)[i].name == lv) {
88 return i;
89 }
90 }
91 return {};
92 }
93
94 CUDA void push_back(variable_type&& var) {
95 lvars->push_back(std::move(var));
96 }
97
98 CUDA void erase(const char* lv) {}
99
101 this->lvars = lvars;
102 }
103};
104
105template <class Allocator>
107 using allocator_type = Allocator;
110
111 template<class T>
112 using bvector = battery::vector<T, Allocator>;
113 using bstring = battery::string<Allocator>;
114
116 std::unordered_map<std::string, size_t> lvar_index;
117
119 for(size_t i = 0; i < lvars->size(); ++i) {
120 lvar_index[std::string((*lvars)[i].name.data())] = i;
121 }
122 }
123
126
129
130 template <class Alloc2>
134
135 // For this operator=, we suppose `lvars` is updated before.
137 lvar_index = std::move(other.lvar_index);
138 return *this;
139 }
141 lvar_index = other.lvar_index;
142 return *this;
143 }
144
145 thrust::optional<size_t> lvar_index_of(const char* lv) const {
146 auto it = lvar_index.find(std::string(lv));
147 if(it != lvar_index.end()) {
148 return {it->second};
149 }
150 return {};
151 }
152
154 lvar_index[std::string(var.name.data())] = lvars->size();
155 lvars->push_back(std::move(var));
156 }
157
158 void erase(const char* lv) {
159 lvar_index.erase(std::string(lv));
160 }
161
163 this->lvars = lvars;
164 }
165};
166
167template <class Allocator>
169 using allocator_type = Allocator;
172
173 template<class T>
174 using bvector = battery::vector<T, Allocator>;
175 using bstring = battery::string<Allocator>;
176
177 battery::unique_ptr<HashMapVarIndex<allocator_type>, allocator_type> cpu_index;
178 battery::unique_ptr<ListVarIndex<allocator_type>, allocator_type> gpu_index;
179
180 CUDA DispatchIndex(bvector<variable_type>* lvars): cpu_index(nullptr), gpu_index(nullptr) {
181 gpu_index = std::move(battery::allocate_unique<ListVarIndex<allocator_type>>(lvars->get_allocator(), lvars));
182 #ifndef __CUDA_ARCH__
183 cpu_index = std::move(battery::allocate_unique<HashMapVarIndex<allocator_type>>(lvars->get_allocator(), lvars));
184 #endif
185 }
186
188 : gpu_index(std::move(other.gpu_index))
189 {
190 #ifndef __CUDA_ARCH__
191 cpu_index = std::move(other.cpu_index);
192 #endif
193 }
194
196 {
197 gpu_index = std::move(battery::allocate_unique<ListVarIndex<allocator_type>>(lvars->get_allocator(), *other.gpu_index, lvars));
198 #ifndef __CUDA_ARCH__
199 cpu_index = std::move(battery::allocate_unique<HashMapVarIndex<allocator_type>>(lvars->get_allocator(), *other.cpu_index, lvars));
200 #endif
201 }
202
203 template <class Alloc2>
205 {
206 gpu_index = std::move(battery::allocate_unique<ListVarIndex<allocator_type>>(lvars->get_allocator(), *other.gpu_index, lvars));
207 #ifndef __CUDA_ARCH__
208 cpu_index = std::move(battery::allocate_unique<HashMapVarIndex<allocator_type>>(lvars->get_allocator(), *other.cpu_index, lvars));
209 #endif
210 }
211
212 // For this operator=, we suppose `lvars` is updated before.
214 gpu_index = std::move(other.gpu_index);
215 #ifndef __CUDA_ARCH__
216 cpu_index = std::move(other.cpu_index);
217 #endif
218 return *this;
219 }
220
221 CUDA this_type& operator=(const this_type& other) {
222 *gpu_index = *other.gpu_index;
223 #ifndef __CUDA_ARCH__
224 *cpu_index = *other.cpu_index;
225 #endif
226 return *this;
227 }
228
229 CUDA thrust::optional<size_t> lvar_index_of(const char* lv) const {
230 #ifdef __CUDA_ARCH__
231 return gpu_index->lvar_index_of(lv);
232 #else
233 return cpu_index->lvar_index_of(lv);
234 #endif
235 }
236
237 CUDA void push_back(variable_type&& var) {
238 #ifdef __CUDA_ARCH__
239 gpu_index->push_back(std::move(var));
240 #else
241 cpu_index->push_back(std::move(var));
242 #endif
243 }
244
245 CUDA void erase(const char* lv) {
246 #ifdef __CUDA_ARCH__
247 gpu_index->erase(lv);
248 #else
249 cpu_index->erase(lv);
250 #endif
251 }
252
254 gpu_index->set_lvars(lvars);
255 #ifndef __CUDA_ARCH__
256 cpu_index->set_lvars(lvars);
257 #endif
258 }
259};
260
261/** A `VarEnv` is a variable environment mapping between logical variables and abstract variables. */
262template <class Allocator>
263class VarEnv {
264 template <class F> using fstring = battery::string<typename F::allocator_type>;
265public:
266 using allocator_type = Allocator;
268
269 constexpr static const char* name = "VarEnv";
270
271 template<class T>
272 using bvector = battery::vector<T, Allocator>;
273 using bstring = battery::string<Allocator>;
274
276
277 template <class Alloc2>
278 friend class VarEnv;
279
280private:
282 bvector<bvector<size_t>> avar2lvar;
283 DispatchIndex<allocator_type> var_index; // Note that this must always be declared *after* `lvars` because it stores a reference to it.
284
285public:
287 avar2lvar.push_back(bvector<int>(get_allocator()));
288 return static_cast<AType>(avar2lvar.size()) - 1;
289 }
290
291private:
292 CUDA NI void extends_abstract_doms(AType aty) {
293 assert(aty != UNTYPED);
294 while(aty >= avar2lvar.size()) {
296 }
297 }
298
299 template <class Alloc2, class Alloc3>
300 CUDA NI AVar extends_vars(AType aty, const battery::string<Alloc2>& name, const Sort<Alloc3>& sort) {
301 extends_abstract_doms(aty);
302 AVar avar(aty, static_cast<int>(avar2lvar[aty].size()));
303 // We first verify the variable doesn't already exist.
304 auto lvar_idx = var_index.lvar_index_of(name.data());
305 if(lvar_idx.has_value()) {
306 auto avar_opt = lvars[*lvar_idx].avar_of(aty);
307 if(avar_opt.has_value()) {
308 return *avar_opt;
309 }
310 else {
311 lvars[*lvar_idx].avars.push_back(avar);
312 }
313 }
314 else {
315 lvar_idx ={lvars.size()};
316 var_index.push_back(Variable<allocator_type>{name, sort, avar, get_allocator()});
317 }
318 avar2lvar[aty].push_back(*lvar_idx);
319 return avar;
320 }
321
322 // Variable redeclaration does not lead to an error, instead the abstract type of the variable is added to the abstract variables list (`avars`) of the variable.
323 template <bool diagnose = false, class F>
324 CUDA NI bool interpret_existential(const F& f, AVar& avar, IDiagnostics& diagnostics) {
325 const auto& vname = battery::get<0>(f.exists());
326 if(f.type() == UNTYPED) {
327 RETURN_INTERPRETATION_ERROR("Untyped abstract type: variable `" + vname + "` has no abstract type.");
328 }
329 auto var = variable_of(vname);
330 if(var.has_value()) {
331 if(var->sort != battery::get<1>(f.exists())) {
332 RETURN_INTERPRETATION_ERROR("Invalid redeclaration with different sort: variable `" + vname + "` has already been declared and the sort does not coincide.");
333 }
334 }
335 avar = extends_vars(f.type(), vname, battery::get<1>(f.exists()));
336 return true;
337 }
338
339 template <bool diagnose = false, class F>
340 CUDA NI bool interpret_lv(const F& f, AVar& avar, IDiagnostics& diagnostics) {
341 const auto& vname = f.lv();
342 auto var = variable_of(vname);
343 if(var.has_value()) {
344 if(f.type() != UNTYPED) {
345 auto avar = var->avar_of(f.type());
346 if(avar.has_value()) {
347 avar = AVar(*avar);
348 return true;
349 }
350 else {
351 RETURN_INTERPRETATION_ERROR("Variable `" + vname + "` has not been declared in the abstract domain `" + fstring<F>::from_int(f.type()) + "`.");
352 }
353 }
354 else {
355 // We take the first abstract variable as a representative. Need more thought on this, but currently we need it for the simplifier, because each variable is typed in both PC and Simplifier, and this interpretation fails.
356
357 // if(var->avars.size() == 1) {
358 avar = AVar(var->avars[0]);
359 return true;
360 // }
361 // else {
362 // RETURN_INTERPRETATION_ERROR("Variable occurrence `" + vname + "` is untyped, but exists in multiple abstract domains.");
363 // }
364 }
365 }
366 else {
367 RETURN_INTERPRETATION_ERROR("Undeclared variable `" + vname + "`.");
368 }
369 }
370
371public:
372 CUDA VarEnv(const Allocator& allocator): lvars(allocator), avar2lvar(allocator), var_index(&lvars) {}
373 CUDA VarEnv(this_type&& other): lvars(std::move(other.lvars)), avar2lvar(std::move(other.avar2lvar)), var_index(std::move(other.var_index), &lvars) {}
374 CUDA VarEnv(): VarEnv(Allocator{}) {}
375 CUDA VarEnv(const this_type& other): lvars(other.lvars), avar2lvar(other.avar2lvar), var_index(other.var_index, &lvars) {}
376
377 template <class Alloc2>
378 CUDA VarEnv(const VarEnv<Alloc2>& other, const Allocator& allocator = Allocator{})
379 : lvars(other.lvars, allocator)
380 , avar2lvar(other.avar2lvar, allocator)
381 , var_index(other.var_index, &lvars)
382 {}
383
385 lvars = std::move(other.lvars);
386 avar2lvar = std::move(other.avar2lvar);
387 var_index = std::move(other.var_index);
388 var_index.set_lvars(&lvars);
389 return *this;
390 }
391
392 CUDA this_type& operator=(const this_type& other) {
393 lvars = other.lvars;
394 avar2lvar = other.avar2lvar;
395 var_index = DispatchIndex<allocator_type>(other.var_index, &lvars);
396 var_index.set_lvars(&lvars);
397 return *this;
398 }
399
400 template <class Alloc2>
401 CUDA this_type& operator=(const VarEnv<Alloc2>& other) {
402 lvars = other.lvars;
403 avar2lvar = other.avar2lvar;
404 var_index = DispatchIndex<allocator_type>(other.var_index, &lvars);
405 var_index.set_lvars(&lvars);
406 return *this;
407 }
408
410 return lvars.get_allocator();
411 }
412
413 CUDA size_t num_abstract_doms() const {
414 return avar2lvar.size();
415 }
416
417 CUDA size_t num_vars() const {
418 return lvars.size();
419 }
420
421 CUDA size_t num_vars_in(AType aty) const {
422 if(aty >= avar2lvar.size()) {
423 return 0;
424 }
425 else {
426 return avar2lvar[aty].size();
427 }
428 }
429
430 /** A variable environment can interpret formulas of two forms:
431 * - Existential formula with a valid abstract type (`f.type() != UNTYPED`).
432 * - Variable occurrence.
433 * It returns an abstract variable (`AVar`) corresponding to the variable created (existential) or already presents (occurrence). */
434 template <bool diagnose = false, class F>
435 CUDA NI bool interpret(const F& f, AVar& avar, IDiagnostics& diagnostics) {
436 if(f.is(F::E)) {
437 return interpret_existential<diagnose>(f, avar, diagnostics);
438 }
439 else if(f.is(F::LV)) {
440 return interpret_lv<diagnose>(f, avar, diagnostics);
441 }
442 else if(f.is(F::V)) {
443 if(contains(f.v())) {
444 avar = f.v();
445 return true;
446 }
447 else {
448 RETURN_INTERPRETATION_ERROR("Undeclared abstract variable `" + fstring<F>::from_int(f.v().aty()) + ", " + fstring<F>::from_int(f.v().vid()) + "`.");
449 }
450 }
451 else {
452 RETURN_INTERPRETATION_ERROR("Unsupported formula: `VarEnv` can only interpret quantifiers and occurrences of variables.");
453 }
454 }
455
456 CUDA NI thrust::optional<const variable_type&> variable_of(const char* lv) const {
457 auto r = var_index.lvar_index_of(lv);
458 if(r.has_value()) {
459 return lvars[*r];
460 }
461 else {
462 return {};
463 }
464 }
465
466 template <class Alloc2>
467 CUDA thrust::optional<const variable_type&> variable_of(const battery::string<Alloc2>& lv) const {
468 return variable_of(lv.data());
469 }
470
471 template <class Alloc2>
472 CUDA bool contains(const battery::string<Alloc2>& lv) const {
473 return contains(lv.data());
474 }
475
476 CUDA bool contains(const char* lv) const {
477 return variable_of(lv).has_value();
478 }
479
480 CUDA bool contains(AVar av) const {
481 if(!av.is_untyped()) {
482 return avar2lvar.size() > av.aty() && avar2lvar[av.aty()].size() > av.vid();
483 }
484 return false;
485 }
486
487 CUDA const variable_type& operator[](int i) const {
488 return lvars[i];
489 }
490
491 CUDA const variable_type& operator[](AVar av) const {
492 return lvars[avar2lvar[av.aty()][av.vid()]];
493 }
494
495 CUDA const bstring& name_of(AVar av) const {
496 return (*this)[av].name;
497 }
498
499 CUDA const Sort<Allocator>& sort_of(AVar av) const {
500 return (*this)[av].sort;
501 }
502
507
508 /** Save the state of the environment. */
509 CUDA NI snapshot_type snapshot() const {
510 snapshot_type snap;
511 for(int i = 0; i < lvars.size(); ++i) {
512 snap.lvars_snap.push_back(lvars[i].avars.size());
513 }
514 for(int i = 0; i < avar2lvar.size(); ++i) {
515 snap.avar2lvar_snap.push_back(avar2lvar[i].size());
516 }
517 return std::move(snap);
518 }
519
520 /** Restore the environment to its previous state `snap`. */
521 CUDA NI void restore(const snapshot_type& snap) {
522 assert(lvars.size() >= snap.lvars_snap.size());
523 assert(avar2lvar.size() >= snap.avar2lvar_snap.size());
524 while(lvars.size() > snap.lvars_snap.size()) {
525 var_index.erase(lvars.back().name.data());
526 lvars.pop_back();
527 }
528 for(int i = 0; i < lvars.size(); ++i) {
529 lvars[i].avars.resize(snap.lvars_snap[i]);
530 }
531 while(avar2lvar.size() > snap.avar2lvar_snap.size()) {
532 avar2lvar.pop_back();
533 }
534 for(int i = 0; i < avar2lvar.size(); ++i) {
535 avar2lvar[i].resize(snap.avar2lvar_snap[i]);
536 }
537 }
538};
539
540/** Given a formula `f` and an environment, return the first variable occurring in `f` or `{}` if `f` has no variable in `env`. */
541template <class F, class Env>
542CUDA NI thrust::optional<const typename Env::variable_type&> var_in(const F& f, const Env& env) {
543 const auto& g = var_in(f);
544 switch(g.index()) {
545 case F::V:
546 if(g.v().is_untyped()) { return {}; }
547 else { return env[g.v()]; }
548 case F::E:
549 return env.variable_of(battery::get<0>(g.exists()));
550 case F::LV:
551 return env.variable_of(g.lv());
552 }
553 return {};
554}
555}
556
557#endif
Definition ast.hpp:38
CUDA constexpr int vid() const
Definition ast.hpp:69
CUDA constexpr int aty() const
Definition ast.hpp:65
CUDA constexpr bool is_untyped() const
Definition ast.hpp:61
Definition diagnostics.hpp:19
Definition env.hpp:263
CUDA this_type & operator=(this_type &&other)
Definition env.hpp:384
CUDA const variable_type & operator[](AVar av) const
Definition env.hpp:491
CUDA allocator_type get_allocator() const
Definition env.hpp:409
CUDA VarEnv()
Definition env.hpp:374
CUDA size_t num_abstract_doms() const
Definition env.hpp:413
CUDA bool contains(const char *lv) const
Definition env.hpp:476
CUDA this_type & operator=(const this_type &other)
Definition env.hpp:392
CUDA VarEnv(this_type &&other)
Definition env.hpp:373
CUDA NI bool interpret(const F &f, AVar &avar, IDiagnostics &diagnostics)
Definition env.hpp:435
CUDA bool contains(AVar av) const
Definition env.hpp:480
battery::vector< T, Allocator > bvector
Definition env.hpp:272
battery::string< Allocator > bstring
Definition env.hpp:273
CUDA const variable_type & operator[](int i) const
Definition env.hpp:487
CUDA NI thrust::optional< const variable_type & > variable_of(const char *lv) const
Definition env.hpp:456
CUDA size_t num_vars() const
Definition env.hpp:417
CUDA VarEnv(const VarEnv< Alloc2 > &other, const Allocator &allocator=Allocator{})
Definition env.hpp:378
static constexpr const char * name
Definition env.hpp:269
Allocator allocator_type
Definition env.hpp:266
CUDA size_t num_vars_in(AType aty) const
Definition env.hpp:421
CUDA thrust::optional< const variable_type & > variable_of(const battery::string< Alloc2 > &lv) const
Definition env.hpp:467
CUDA VarEnv(const Allocator &allocator)
Definition env.hpp:372
CUDA NI AType extends_abstract_dom()
Definition env.hpp:286
CUDA const bstring & name_of(AVar av) const
Definition env.hpp:495
CUDA this_type & operator=(const VarEnv< Alloc2 > &other)
Definition env.hpp:401
CUDA const Sort< Allocator > & sort_of(AVar av) const
Definition env.hpp:499
CUDA NI snapshot_type snapshot() const
Definition env.hpp:509
CUDA NI void restore(const snapshot_type &snap)
Definition env.hpp:521
CUDA bool contains(const battery::string< Alloc2 > &lv) const
Definition env.hpp:472
CUDA VarEnv(const this_type &other)
Definition env.hpp:375
#define RETURN_INTERPRETATION_ERROR(MSG)
Definition diagnostics.hpp:155
Definition abstract_deps.hpp:14
int AType
Definition sort.hpp:18
CUDA const TFormula< Allocator, ExtendedSig > & var_in(const TFormula< Allocator, ExtendedSig > &f)
Definition algorithm.hpp:145
#define UNTYPED
Definition sort.hpp:21
Definition env.hpp:168
battery::unique_ptr< HashMapVarIndex< allocator_type >, allocator_type > cpu_index
Definition env.hpp:177
CUDA void erase(const char *lv)
Definition env.hpp:245
CUDA void set_lvars(bvector< variable_type > *lvars)
Definition env.hpp:253
CUDA this_type & operator=(const this_type &other)
Definition env.hpp:221
CUDA DispatchIndex(const DispatchIndex< Alloc2 > &other, bvector< variable_type > *lvars)
Definition env.hpp:204
CUDA this_type & operator=(this_type &&other)
Definition env.hpp:213
CUDA DispatchIndex(const this_type &other, bvector< variable_type > *lvars)
Definition env.hpp:195
CUDA thrust::optional< size_t > lvar_index_of(const char *lv) const
Definition env.hpp:229
CUDA DispatchIndex(bvector< variable_type > *lvars)
Definition env.hpp:180
battery::string< Allocator > bstring
Definition env.hpp:175
battery::unique_ptr< ListVarIndex< allocator_type >, allocator_type > gpu_index
Definition env.hpp:178
battery::vector< T, Allocator > bvector
Definition env.hpp:174
CUDA void push_back(variable_type &&var)
Definition env.hpp:237
Allocator allocator_type
Definition env.hpp:169
CUDA DispatchIndex(this_type &&other, bvector< variable_type > *lvars)
Definition env.hpp:187
Definition env.hpp:106
HashMapVarIndex(this_type &&other, bvector< variable_type > *lvars)
Definition env.hpp:124
void push_back(variable_type &&var)
Definition env.hpp:153
battery::string< Allocator > bstring
Definition env.hpp:113
std::unordered_map< std::string, size_t > lvar_index
Definition env.hpp:116
bvector< variable_type > * lvars
Definition env.hpp:115
Allocator allocator_type
Definition env.hpp:107
battery::vector< T, Allocator > bvector
Definition env.hpp:112
HashMapVarIndex(const this_type &other, bvector< variable_type > *lvars)
Definition env.hpp:127
this_type & operator=(const this_type &other)
Definition env.hpp:140
thrust::optional< size_t > lvar_index_of(const char *lv) const
Definition env.hpp:145
void set_lvars(bvector< variable_type > *lvars)
Definition env.hpp:162
HashMapVarIndex(bvector< variable_type > *lvars)
Definition env.hpp:118
void erase(const char *lv)
Definition env.hpp:158
this_type & operator=(this_type &&other)
Definition env.hpp:136
HashMapVarIndex(const HashMapVarIndex< Alloc2 > &other, bvector< variable_type > *lvars)
Definition env.hpp:131
Definition env.hpp:56
CUDA this_type & operator=(this_type &&other)
Definition env.hpp:77
battery::string< Allocator > bstring
Definition env.hpp:63
CUDA thrust::optional< size_t > lvar_index_of(const char *lv) const
Definition env.hpp:85
bvector< variable_type > * lvars
Definition env.hpp:65
CUDA ListVarIndex(this_type &&, bvector< variable_type > *lvars)
Definition env.hpp:68
CUDA ListVarIndex(const this_type &, bvector< variable_type > *lvars)
Definition env.hpp:69
CUDA ListVarIndex(bvector< variable_type > *lvars)
Definition env.hpp:67
CUDA this_type & operator=(const this_type &other)
Definition env.hpp:81
CUDA void erase(const char *lv)
Definition env.hpp:98
CUDA void push_back(variable_type &&var)
Definition env.hpp:94
Allocator allocator_type
Definition env.hpp:57
CUDA ListVarIndex(const ListVarIndex< Alloc2 > &, bvector< variable_type > *lvars)
Definition env.hpp:72
CUDA void set_lvars(bvector< variable_type > *lvars)
Definition env.hpp:100
battery::vector< T, Allocator > bvector
Definition env.hpp:62
Definition sort.hpp:26
Definition env.hpp:503
bvector< size_t > avar2lvar_snap
Definition env.hpp:505
bvector< size_t > lvars_snap
Definition env.hpp:504
Definition env.hpp:20
bstring name
Definition env.hpp:25
battery::string< Allocator > bstring
Definition env.hpp:23
CUDA NI thrust::optional< AVar > avar_of(AType aty) const
Definition env.hpp:45
CUDA NI Variable(const bstring &name, const Sort< Allocator > &sort, AVar av, const Allocator &allocator=Allocator{})
Definition env.hpp:32
CUDA NI Variable(const Variable< Alloc2 > &other, const Allocator &allocator=Allocator{})
Definition env.hpp:39
Variable(const Variable< Allocator > &)=default
Variable(Variable< Allocator > &&)=default
battery::vector< T, Allocator > bvector
Definition env.hpp:22
bvector< AVar > avars
Definition env.hpp:27
Sort< Allocator > sort
Definition env.hpp:26