Loading [MathJax]/extensions/TeX/AMSmath.js
Radium Engine  1.5.29
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
variableset.cpp
1#include <Core/Containers/DynamicVisitor.hpp>
2#include <Core/Containers/VariableSet.hpp>
3
4#include <Core/Utils/TypesUtils.hpp>
5#include <catch2/catch_test_macros.hpp>
6#include <cmath>
7#include <string>
8
9#include "../unittestUtils.hpp"
10
11using namespace Ra::Core;
12
13struct PrintThemAll
14 : public PrintAllHelper<Ra::Core::Utils::TypeList<int, size_t, float, double, std::string>> {};
15
16class MyParameterVisitor : public DynamicVisitor
17{
18 public:
19 MyParameterVisitor() : DynamicVisitor() {
20 addOperator<int>( *this );
21 addOperator<float>( *this );
23 }
24
25 template <typename T>
26 void operator()( const std::string& name, T& _in, std::any&& ) {
27 std::cout << "\t(MyParameterVisitor : ( " << Utils::simplifiedDemangledType<T>() << " ) "
28 << name << " --> " << _in << " // ";
29 _in /= 2;
30 std::cout << _in << "\n";
31 ++m_counter;
32 }
33
34 void operator()( const std::string& name, std::string& _in, std::any&& ) {
35 std::cout << "\t(MyParameterVisitor : ( std::string ) " << name << " --> " << _in << "\n";
36 ++m_counter;
37 }
38
39 size_t getCount() { return m_counter; }
40 void resetCount() { m_counter = 0; }
41
42 private:
43 size_t m_counter { 0 };
44};
45
46// Apply a functor to mofify each integer of a VariableSet
47struct modifyInts : public VariableSet::StaticVisitor<int> {
48 template <typename F>
49 void operator()( const std::string&, int& value, F&& f ) {
50 value = f( value );
51 }
52};
53auto print_container = []( const std::string& name, VariableSet& ps ) {
54 std::cout << name << " content : ";
55 ps.visit( PrintThemAll {} );
57};
58
59TEST_CASE( "Core/Container/VariableSet", "[unittests][Core][Container][VariableSet]" ) {
60 REQUIRE( PrintThemAll::types::Size == 5 );
61
62 VariableSet params;
63 REQUIRE( !params.existsVariableType<int>() );
64 int i { 1 };
65 int initial_i = i;
66 float x { 1.f };
67
68 std::cout << "Adding parameters" << std::endl;
69 params.insertVariable( "i", i ); // i added by value
70 params.insertVariable( "j", std::ref( i ) ); // j is a reference on i
71 params.insertVariable( "x", 2 );
72 params.insertVariable( "x", x );
73 params.insertVariable( "foo", std::string { "bar" } );
74 std::cout << " ... done!" << std::endl;
75 print_container( "Initial set", params );
76
77 SECTION( "Construction, access and removal to and from a variable set" ) {
78
79 REQUIRE( params.existsVariable<int>( "i" ) );
80 REQUIRE( params.existsVariable<std::reference_wrapper<int>>( "j" ) );
81 REQUIRE( params.existsVariable<int>( "x" ) );
82 REQUIRE( params.existsVariable<float>( "x" ) );
83 REQUIRE( params.existsVariable<std::string>( "foo" ) );
84
85 auto added = params.insertVariable( "x", x );
86 REQUIRE( added.second == false );
87 REQUIRE( added.first->second == x );
88
89 // Verify handle validity
90 auto fooHandle = params.getVariableHandle<std::string>( "foo" );
91 REQUIRE( params.isHandleValid( fooHandle ) == true );
92 REQUIRE( fooHandle->first == "foo" );
93 REQUIRE( fooHandle->second == "bar" );
94
95 auto dummyHandle = params.getVariableHandle<int>( "z" );
96 REQUIRE( params.isHandleValid( dummyHandle ) == false );
97
98 REQUIRE( params.size() == 5 );
99 REQUIRE( params.numberOf<int>() == 2 );
100 REQUIRE( params.numberOf<std::reference_wrapper<int>>() == 1 );
101 REQUIRE( params.numberOf<float>() == 1 );
102 REQUIRE( params.numberOf<std::string>() == 1 );
103
104 REQUIRE( params.getVariable<float>( "x" ) == x );
105 // modify "x" through its handle
106 auto xHandle = params.getVariableHandle<float>( "x" );
107 REQUIRE( xHandle->second == x );
108 xHandle->second = 5;
109 REQUIRE( params.getVariable<float>( "x" ) != x );
110 REQUIRE( params.getVariable<float>( "x" ) == 5 );
111
112 // variable i store a value, copy of local variable i. Changing its value ...
113 auto inserted = params.setVariable( "i", 2 );
114 REQUIRE( inserted.second == false );
115 REQUIRE( params.getVariable<int>( "i" ) == 2 );
116 // does not change the local variable i
117 REQUIRE( i == 1 );
118
119 inserted = params.setVariable( "k", 3 );
120 REQUIRE( inserted.second == true );
121
122 // variable "j" is a reference to local variable i, and has the same value
123 REQUIRE( params.getVariable<std::reference_wrapper<int>>( "j" ) == i );
124 // Changing local variable i ....
125 i = 3;
126 // ... changes the content of its reference "j"
127 REQUIRE( params.getVariable<std::reference_wrapper<int>>( "j" ) == i );
128
129 params.deleteVariable<float>( "x" );
130 REQUIRE( !params.existsVariable<float>( "x" ).has_value() );
131 // as x (float) variable was removed, xHandle is now invalid
132 REQUIRE( params.isHandleValid( xHandle ) == false );
133 REQUIRE( params.existsVariable<int>( "x" ).has_value() );
134 params.deleteVariable<int>( "x" );
135 REQUIRE( !params.existsVariable<int>( "x" ).has_value() );
136 }
137
138 SECTION( "Visiting and modifying variable set using static visitor" ) {
139 auto modifyFunction = []( int x_ ) { return 2 * x_ + 1; };
140
141 REQUIRE( params.getVariable<int>( "i" ) == 1 );
142 REQUIRE( params.getVariable<int>( "x" ) == 2 );
143 REQUIRE( params.getVariable<float>( "x" ) == 1 );
144 // modifies params i, and params j as a ref, so local var i is also modified
145 params.visit( modifyInts {}, modifyFunction );
146 REQUIRE( params.getVariable<int>( "i" ) == modifyFunction( initial_i ) );
147 REQUIRE( i == modifyFunction( initial_i ) );
148 REQUIRE( params.getVariable<std::reference_wrapper<int>>( "j" ) ==
149 modifyFunction( initial_i ) );
150 REQUIRE( params.getVariable<int>( "x" ) == modifyFunction( 2 ) );
151 REQUIRE( params.getVariable<float>( "x" ) == 1 );
152 }
153
154 SECTION( "Visiting and modifying variable set using dynamic visitor" ) {
155 REQUIRE( params.getVariable<int>( "i" ) == 1 );
156 REQUIRE( params.getVariable<int>( "x" ) == 2 );
157 REQUIRE( params.getVariable<float>( "x" ) == 1 );
158
160 // Adding a visitor operator on ints
161 vf.addOperator<int>( []( const std::string& name, auto& value, std::any&& ) {
162 std::cout << "\tDoubling the int " << name << " (equal to " << value << ")\n";
163 value *= 2;
164 } );
165 params.visit( vf );
166 print_container( "Doubled set", params );
167 REQUIRE( params.getVariable<int>( "i" ) == ( 2 * initial_i ) );
168 REQUIRE( params.getVariable<std::reference_wrapper<int>>( "j" ) == ( 2 * initial_i ) );
169 REQUIRE( params.getVariable<std::reference_wrapper<int>>( "j" ) == i );
170 REQUIRE( params.getVariable<int>( "x" ) == ( 2 * 2 ) );
171 REQUIRE( params.getVariable<float>( "x" ) == 1 );
172
173 // Changing the visitor operator on ints
174 vf.addOrReplaceOperator<int>( []( const std::string& name, auto& value, std::any&& ) {
175 std::cout << "\tHalving the int " << name << " (equal to " << value << ")\n";
176 value /= 2;
177 } );
178 params.visit( vf );
179 REQUIRE( params.getVariable<int>( "i" ) == ( i ) );
180 REQUIRE( params.getVariable<int>( "x" ) == ( 2 ) );
181 REQUIRE( params.getVariable<float>( "x" ) == 1 );
182 // removing the visitor operator on ints
183 vf.removeOperator<int>();
184 params.visit( vf );
185 REQUIRE( params.getVariable<int>( "i" ) == ( i ) );
186 REQUIRE( params.getVariable<int>( "x" ) == ( 2 ) );
187 REQUIRE( params.getVariable<float>( "x" ) == 1 );
188 }
189
190 SECTION( "Visiting and modifying variable set using standard range for" ) {
191 params.insertVariable( "y", std::sqrt( 3 * x ) );
192
193 REQUIRE( params.getVariable<float>( "x" ) == x );
194 REQUIRE( params.getVariable<float>( "y" ) == std::sqrt( 3 * x ) );
195 auto& floatParams = params.getAllVariables<float>();
196 // read-write loop on float params
197 for ( auto& p : floatParams ) {
198 std::cout << p.first << " = " << p.second;
199 p.second = p.second * 2;
200 std::cout << " ==> " << p.second << "\n";
201 }
202 REQUIRE( params.getVariable<float>( "x" ) == 2 * x );
203 REQUIRE( params.getVariable<float>( "y" ) == 2 * std::sqrt( 3 * x ) );
204
205 // read-only loop on int params
206 for ( const auto& p : params.getAllVariables<int>() ) {
207 std::cout << p.first << " = " << p.second;
208 // p.second = p.second * 2; // this does not compile ^^
209 std::cout << " ==> " << p.second << "\n";
210 }
211 print_container( "Final set", params );
212
213 auto handle = params.getVariableHandle<int>( "i" );
214 REQUIRE( params.isHandleValid( handle ) );
215 params.deleteVariable( handle );
216 REQUIRE( params.isHandleValid( handle ) == false );
217 auto& intVariables = params.getAllVariablesFromHandle( handle );
218 std::cout << "Looping on all variables with the same type of a given handle\n";
219 for ( const auto& p : intVariables ) {
220 std::cout << p.first << " = " << p.second << " ";
221 }
222 std::cout << "\n";
223 }
224 SECTION( "General visit using a custom visitor" ) {
225 std::cout << "General visit using a custom visitor" << std::endl;
226
227 MyParameterVisitor mp;
228 REQUIRE( mp.getCount() == 0 );
229 params.visit( mp );
230 REQUIRE( mp.getCount() == 5 );
231 REQUIRE( i == 0 );
232
233 auto xHandle = params.getVariableHandle<float>( "x" );
234 REQUIRE( params.isHandleValid( xHandle ) == true );
235 auto deletedFloats = params.deleteAllVariables<float>();
236 REQUIRE( deletedFloats );
237 REQUIRE( !params.existsVariableType<float>() );
238 deletedFloats = params.deleteAllVariables<float>();
239 REQUIRE( !deletedFloats );
240 // as all floats was removed, xHandle is now invalid
241 REQUIRE( params.isHandleValid( xHandle ) == false );
242
243 mp.resetCount();
244 params.visit( mp );
245 REQUIRE( mp.getCount() == 4 );
246 print_container( "Final set", params );
247 }
248
249 print_container( "Final set", params );
250}
251TEST_CASE( "Core/Container/VariableSet/Merging, copying, moving",
252 "[Core][Container][VariableSet]" ) {
253
254 VariableSet params;
255
256 REQUIRE( !params.existsVariableType<int>() );
257 params.insertVariable( "a", 1 );
258 params.insertVariable( "b", 2 );
259 print_container( "initial params ", params );
260
261 VariableSet params2;
262 params2.insertVariable( "b", 4 );
263 params2.insertVariable( "c", 5 );
264 params2.insertVariable( "e", 2.7182818285 );
265 print_container( "initial params2 ", params2 );
266
267 VariableSet params3;
268 params3.insertVariable( "a", 0 );
269 params3.insertVariable( "c", 4 );
270 params3.insertVariable( "pi", 3.151592f );
271 print_container( "initial params3 ", params3 );
272
273 print_container( "initial params ", params );
274
275 REQUIRE( params.getVariable<int>( "b" ) == 2 );
276 REQUIRE( params2.getVariable<int>( "b" ) == 4 );
277 params.mergeReplaceVariables( params2 );
278 REQUIRE( params.getVariable<int>( "b" ) == 4 );
279 print_container( "params after merge of params2 (replace)", params );
280
281 REQUIRE( params.getVariable<int>( "c" ) == 5 );
282 REQUIRE( params3.getVariable<int>( "c" ) == 4 );
283 params.mergeKeepVariables( params3 );
284 REQUIRE( params.getVariable<int>( "c" ) == 5 );
285 print_container( "params after merge of params3 (keep)", params );
286
287 // copy constructor
288 auto newparams = new VariableSet( params );
289 REQUIRE( newparams->size() == params.size() );
290
291 auto numInt = params.numberOf<int>();
292 auto numIntN = newparams->numberOf<int>();
293 REQUIRE( numInt == numIntN );
294
295 auto numFloat = params.numberOf<float>();
296 auto numFloatN = newparams->numberOf<float>();
297 REQUIRE( numFloat == numFloatN );
298
299 auto numDouble = params.numberOf<double>();
300 auto numDoubleN = newparams->numberOf<double>();
301 REQUIRE( numDouble == numDoubleN );
302
303 REQUIRE( ( numIntN + numFloatN + numDoubleN ) == newparams->size() );
304
305 auto numString = newparams->numberOf<std::string>();
306 REQUIRE( numString == 0 );
307 auto removed = newparams->deleteAllVariables<std::string>();
308 REQUIRE( removed == false );
309
310 print_container( "Copied params into newparams", *newparams );
311 delete newparams;
312 auto sp = params.size();
313 auto paramsMoved { std::move( params ) };
314 REQUIRE( params.size() == 0 );
315 REQUIRE( paramsMoved.size() == sp );
316 print_container( "Moved params into paramsMoved", paramsMoved );
317 print_container( "params is empty", params );
318
319 REQUIRE( !params.existsVariableType<int>() );
320}
321
322TEST_CASE( "Core/Container/VariableSe/Iterating on stored types",
323 "[unittests][Core][Container][VariableSet]" ) {
324 VariableSet vs;
325 vs.insertVariable( "x", 1.414_ra );
326 vs.insertVariable( "y", std::sqrt( 2 ) );
327 std::function<Scalar( Scalar )> multBy2 = []( Scalar x ) { return x * 2_ra; };
328 vs.insertVariable( "f", multBy2 );
329 auto typeVector = vs.getStoredTypes();
330 std::cout << "Stored types : \n";
331 for ( const auto& t : typeVector ) {
332 std::cout << "\t" << Ra::Core::Utils::simplifiedDemangledType( t ) << "\n";
333 }
334
335 REQUIRE( std::find( typeVector.begin(),
336 typeVector.end(),
337 std::type_index( typeid( Scalar ) ) ) != typeVector.end() );
338 REQUIRE( std::find( typeVector.begin(),
339 typeVector.end(),
340 std::type_index( typeid( std::function<Scalar( Scalar )> ) ) ) !=
341 typeVector.end() );
342
343 auto b = vs.deleteVariable<Scalar>( "x" );
344 REQUIRE( b );
345 b = vs.deleteVariable<float>( "y" );
346 REQUIRE( !b );
347 b = vs.deleteVariable<double>( "y" );
348 REQUIRE( b );
349}
350
351TEST_CASE( "Core/Container/VariableSet/Clear", "[unittests][Core][Container][VariableSet]" ) {
352 VariableSet params;
353 REQUIRE( !params.existsVariableType<int>() );
354 REQUIRE( !params.existsVariableType<std::string>() );
355
356 params.insertVariable( "a", 1 );
357 params.insertVariable( "b", 2 );
358 params.insertVariable( "s1", std::string { "String 1" } );
359 REQUIRE( params.existsVariableType<int>() );
360
361 REQUIRE( params.existsVariableType<std::string>() );
362 REQUIRE( params.size() == 3 );
363 params.clear();
364 REQUIRE( params.size() == 0 );
365 REQUIRE( !params.existsVariableType<int>() );
366 REQUIRE( !params.existsVariableType<std::string>() );
367}
Base class for visitors with configurable per-type callbacks. Visiting will be prepared at running ti...
bool addOperator(F &&f)
Add a visiting operator.
void addOrReplaceOperator(F &&f)
Add or replace a visiting operator.
bool removeOperator()
Remove a visiting operator.
Heterogeneous container storing "Variables", that maps a name (std::string) to a value (of any type T...
auto getStoredTypes() const -> const std::vector< std::type_index > &
Gets the stored data type.
bool isHandleValid(const H &handle) const
Test the validity of a handle.
bool deleteAllVariables()
Removes all variables of the given type.
auto existsVariable(const std::string &name) const -> Utils::optional< VariableHandle< T > >
test the existence of the given variable
bool deleteVariable(const std::string &name)
Remove a variable, i.e. a name->value association.
auto getAllVariables() const -> VariableContainer< T > &
Get the whole container for variables of a given type.
size_t numberOf() const
Get the number of variables of the given type.
void mergeKeepVariables(const VariableSet &from)
Merge the VariableSet from into this.
auto getVariableHandle(const std::string &name) const -> const VariableHandle< T >
get the handle on the variable with the given name
auto getVariable(const std::string &name) const -> const T &
get the value of the given variable
auto setVariable(const std::string &name, const T &value) -> std::pair< VariableHandle< T >, bool >
reset (or set if the variable does not exist yet) the value of the variable.
auto existsVariableType() const -> Utils::optional< VariableContainer< T > * >
Test if the storage supports a given variable type.
auto getAllVariablesFromHandle(const H &handle) -> VariableContainer< VariableTypeFromHandle< H > > &
Get the whole container for variables of the same type than the given handled variable.
auto insertVariable(const std::string &name, const T &value) -> std::pair< VariableHandle< T >, bool >
Add a variable, i.e. an association name->value, into the container.
void clear()
remove all elements from the container
void mergeReplaceVariables(const VariableSet &from)
Merge the VariableSet from into this.
size_t size() const
Gets the total number of variables (of any type)
void visit(F &&visitor) const
Visit the container using a user defined visitor.
T endl(T... args)
T find(T... args)
T move(T... args)
This namespace contains everything "low level", related to data, datastuctures, and computation.
Definition Cage.cpp:5
T ref(T... args)
T sqrt(T... args)
Types, list of types as Ra::Core::Utils::TypeList< ... >
Base class for visitors with static supported types. Visiting will be prepared at compile time by unf...