C++ Mathematical Expression Toolkit (ExprTk) release
Loading...
Searching...
No Matches
exprtk_groups_examples.cpp
Go to the documentation of this file.
1/*
2 **************************************************************
3 * C++ Mathematical Expression Toolkit Library *
4 * *
5 * Group Example (add, create, contains, size, get, erase) *
6 * Author: Arash Partow (1999-2024) *
7 * URL: https://www.partow.net/programming/exprtk/index.html *
8 * *
9 * Copyright notice: *
10 * Free use of the Mathematical Expression Toolkit Library is *
11 * permitted under the guidelines and in accordance with the *
12 * most current version of the MIT License. *
13 * https://www.opensource.org/licenses/MIT *
14 * SPDX-License-Identifier: MIT *
15 * *
16 **************************************************************
17*/
18
19
20#include <algorithm>
21#include <cassert>
22#include <chrono>
23#include <cstdio>
24#include <iterator>
25#include <map>
26#include <set>
27#include <string>
28
29#include "exprtk.hpp"
30
31
32namespace groups_impl
33{
34
35template <typename T>
37{
38 bool add_group(const std::string& group_name, const std::set<T>& set)
39 {
40 const auto itr = groups.find(group_name);
41
42 if (itr != groups.end())
43 {
44 return false;
45 }
46
47 groups[group_name] = set;
48 return true;
49 }
50
51 bool contains(const std::string& group_name) const
52 {
53 return groups.count(group_name) > 0;
54 }
55
56 using set_t = std::set<T>;
57 using ptr_t = set_t*;
58
59 ptr_t get(const std::string group_name)
60 {
61 auto itr = groups.find(group_name);
62 if (itr == groups.end())
63 {
64 return nullptr;
65 }
66 return &(itr->second);
67 }
68
69 std::map<std::string, std::set<T>> groups;
70};
71
72template <typename T>
73class create final : public exprtk::igeneric_function<T>
74{
75public:
76
78 using parameter_list_t = typename igfun_t::parameter_list_t;
79 using generic_type = typename igfun_t::generic_type;
80 using string_t = typename generic_type::string_view;
81
83
84 using exprtk::igeneric_function<T>::operator();
85
87 : exprtk::igeneric_function<T>("S")
88 , groups_(groups)
89 { exprtk::rtl::io::file::details::perform_check<T>(); }
90
91 inline T operator() (parameter_list_t parameters) override
92 {
93 const std::string group_name = to_str(string_t(parameters[0]));
94
95 if (
96 !groups_.contains(group_name) &&
97 !groups_.add_group(group_name, {})
98 )
99 {
100 return T(0);
101 }
102
103 auto ptr = groups_.get(group_name);
104 const std::size_t ptr_size = sizeof(ptr);
105 T result = T(0);
106
107 std::memcpy(reinterpret_cast<char*>(&result ),
108 reinterpret_cast<char*>(&ptr),
109 ptr_size);
110
111 return result;
112 }
113
115};
116
117template <typename SetType, typename T>
118SetType* make_set_handle(T v)
119{
120 const std::size_t ptr_size = sizeof(SetType*);
121 SetType* ptr = reinterpret_cast<SetType*>(0);
122
123 std::memcpy(reinterpret_cast<exprtk::details::char_ptr>(&ptr),
124 reinterpret_cast<exprtk::details::char_ptr>(&v ),
125 ptr_size);
126
127 return ptr;
128}
129
130template <typename T>
131class add final : public exprtk::igeneric_function<T>
132{
133public:
134
136 using parameter_list_t = typename igfun_t::parameter_list_t;
137 using generic_type = typename igfun_t::generic_type;
138 using scalar_t = typename generic_type::scalar_view;
139 using string_t = typename generic_type::string_view;
141
142 using exprtk::igeneric_function<T>::operator();
143
145 : exprtk::igeneric_function<T>("TS*")
146 , groups_(groups)
147 { exprtk::rtl::io::file::details::perform_check<T>(); }
148
149 inline T operator() (parameter_list_t parameters) override
150 {
151 auto ptr = scalar_t(parameters[0])();
152 assert(ptr != T(0));
153 auto& set = *make_set_handle<strgrps_cllctn::set_t>(ptr);
154 return process(set, parameters);
155 }
156
157private:
158
159 inline T process(strgrps_cllctn::set_t& set, const parameter_list_t& parameters)
160 {
161 for (std::size_t i = 1; i < parameters.size(); ++i)
162 {
163 set.insert(to_str(string_t(parameters[i])));
164 }
165
166 return T(1);
167 }
168
170};
171
172template <typename T>
173class contains final : public exprtk::igeneric_function<T>
174{
175public:
176
178 using parameter_list_t = typename igfun_t::parameter_list_t;
179 using generic_type = typename igfun_t::generic_type;
180 using scalar_t = typename generic_type::scalar_view;
181 using string_t = typename generic_type::string_view;
183
184 using exprtk::igeneric_function<T>::operator();
185
187 : exprtk::igeneric_function<T>("TS*")
188 , groups_(groups)
189 { exprtk::rtl::io::file::details::perform_check<T>(); }
190
191 inline T operator() (parameter_list_t parameters) override
192 {
193 auto ptr = scalar_t(parameters[0])();
194 assert(ptr != T(0));
195 const auto& set = *make_set_handle<strgrps_cllctn::set_t>(ptr);
196 return process(set, parameters);
197 }
198
199private:
200
201 inline T process(const strgrps_cllctn::set_t& set, parameter_list_t& parameters) const
202 {
203 for (std::size_t i = 1; i < parameters.size(); ++i)
204 {
205 if (set.count(to_str(string_t(parameters[i]))))
206 {
207 return T(1);
208 }
209 }
210
211 return T(0);
212 }
213
215};
216
217template <typename T>
218class size final : public exprtk::igeneric_function<T>
219{
220public:
221
223 using parameter_list_t = typename igfun_t::parameter_list_t;
224 using generic_type = typename igfun_t::generic_type;
225 using scalar_t = typename generic_type::scalar_view;
226 using string_t = typename generic_type::string_view;
228
229 using exprtk::igeneric_function<T>::operator();
230
232 : exprtk::igeneric_function<T>("T")
233 , groups_(groups)
234 { exprtk::rtl::io::file::details::perform_check<T>(); }
235
236 inline T operator() (parameter_list_t parameters) override
237 {
238 auto ptr = scalar_t(parameters[0])();
239 assert(ptr != T(0));
240 const auto& set = *make_set_handle<strgrps_cllctn::set_t>(ptr);
241 return T(set.size());
242 }
243
244private:
245
247};
248
249template <typename T>
250class get final : public exprtk::igeneric_function<T>
251{
252public:
253
255 using parameter_list_t = typename igfun_t::parameter_list_t;
256 using generic_type = typename igfun_t::generic_type;
257 using scalar_t = typename generic_type::scalar_view;
258 using string_t = typename generic_type::string_view;
260
261 using exprtk::igeneric_function<T>::operator();
262
265 , groups_(groups)
266 { exprtk::rtl::io::file::details::perform_check<T>(); }
267
268 inline T operator() (std::string& result, parameter_list_t parameters) override
269 {
270 const auto ptr = scalar_t(parameters[0])();
271 const int index = static_cast<int>(scalar_t(parameters[1])());
272
273 assert(ptr != T(0));
274
275 auto& set = *make_set_handle<strgrps_cllctn::set_t>(ptr);
276
277 if (
278 (index >= 0) &&
279 (static_cast<std::size_t>(index) >= set.size())
280 )
281 {
282 return T(0);
283 }
284
285 auto itr = set.begin();
286 std::advance(itr,index);
287 result = *itr;
288 return T(1);
289 }
290
291private:
292
294};
295
296template <typename T>
297class erase final : public exprtk::igeneric_function<T>
298{
299public:
300
302 using parameter_list_t = typename igfun_t::parameter_list_t;
303 using generic_type = typename igfun_t::generic_type;
304 using scalar_t = typename generic_type::scalar_view;
305 using string_t = typename generic_type::string_view;
307
308 using exprtk::igeneric_function<T>::operator();
309
311 : exprtk::igeneric_function<T>("TS*")
312 , groups_(groups)
313 { exprtk::rtl::io::file::details::perform_check<T>(); }
314
315 inline T operator() (parameter_list_t parameters) override
316 {
317 auto ptr = scalar_t(parameters[0])();
318 assert(ptr != T(0));
319 auto& set = *make_set_handle<strgrps_cllctn::set_t>(ptr);
320 return process(set,parameters);
321 }
322
323private:
324
326 {
327 std::size_t count = 0;
328 for (std::size_t i = 1; i < parameters.size(); ++i)
329 {
330 count += set.erase(to_str(string_t(parameters[i])));
331 }
332
333 return T(count);
334 }
335
337};
338
339
340} // namespace groups_impl
341
342template <typename T>
344{
345 using symbol_table_t = exprtk::symbol_table<T>;
346 using expression_t = exprtk::expression<T>;
347 using parser_t = exprtk::parser<T>;
348
349 using strset_t = std::set<std::string>;
350
351 strset_t girl_names;
352 strset_t boy_names;
353
354 girl_names.insert("jane");
355 girl_names.insert("jill");
356
357 boy_names.insert("jack");
358 boy_names.insert("jim" );
359 boy_names.insert("john");
360
362
363 names_groups.add_group("girls", girl_names);
364 names_groups.add_group("boys", boy_names );
365
366 assert(names_groups.contains("girls"));
367 assert(names_groups.contains("boys" ));
368
369 groups_impl::create <T> group_create (names_groups);
370 groups_impl::add <T> group_add (names_groups);
371 groups_impl::contains<T> group_contains(names_groups);
372 groups_impl::size <T> group_size (names_groups);
373 groups_impl::get <T> group_get (names_groups);
374 groups_impl::erase <T> group_erase (names_groups);
375
377
378 symbol_table_t symbol_table;
379 expression_t expression;
380 parser_t parser;
381
382 symbol_table.add_function("create" , group_create );
383 symbol_table.add_function("add" , group_add );
384 symbol_table.add_function("contains", group_contains);
385 symbol_table.add_function("size" , group_size );
386 symbol_table.add_function("get" , group_get );
387 symbol_table.add_function("erase" , group_erase );
388 symbol_table.add_function("println" , println );
389
390 expression.register_symbol_table(symbol_table);
391
392 const std::string program =
393 " /* Load the groups from symbol table */ "
394 " var girls := create('girls'); "
395 " var boys := create('boys' ); "
396 " "
397 " if (not(girls)) "
398 " { "
399 " println('failed to create girls set!'); "
400 " return []; "
401 " }; "
402 " "
403 " if (not(boys)) "
404 " { "
405 " println('failed to create boys set!'); "
406 " return []; "
407 " }; "
408 " "
409 " var name := 'john'; "
410 " "
411 " if (contains(girls, name)) "
412 " { "
413 " println(name, ' in girls set'); "
414 " } "
415 " else "
416 " { "
417 " println(name, ' NOT in girls set'); "
418 " }; "
419 " "
420 " if (contains(boys, name)) "
421 " { "
422 " println(name, ' in boys set'); "
423 " } "
424 " else "
425 " { "
426 " println(name, ' NOT in boys set'); "
427 " }; "
428 " "
429 " /* Create a group from scratch */ "
430 " var pets := create('pets'); "
431 " "
432 " add(pets, 'buddy'); "
433 " add(pets, 'fluffy', 'snowy'); "
434 " add(pets, 'ziggy', 'monty', 'teddy'); "
435 " "
436 " if (contains(pets, name)) "
437 " { "
438 " println(name, ' in pets set'); "
439 " } "
440 " else "
441 " { "
442 " println(name, ' NOT in pets set'); "
443 " }; "
444 " "
445 " if (contains(pets, name, 'fluffy')) "
446 " { "
447 " println(name, ' or fluffy in pets set'); "
448 " } "
449 " else "
450 " { "
451 " println(name, ' or fluffy NOT in pets set'); "
452 " }; "
453 " "
454 " println('List of \\'pets\\':'); "
455 " "
456 " for (var i := 0; i < size(pets); i += 1) "
457 " { "
458 " println('[', i ,']: ', get(pets,i)); "
459 " }; "
460 " "
461 " if (erase(pets, 'fluffy', 'teddy') != 2) "
462 " { "
463 " println('Failed to erase fluffy and teddy'); "
464 " return []; "
465 " }; "
466 " "
467 " println('List of \\'pets\\':'); "
468 " "
469 " for (var i := 0; i < size(pets); i += 1) "
470 " { "
471 " println('[', i ,']: ', get(pets,i)); "
472 " }; "
473 " ";
474
475 if (!parser.compile(program, expression))
476 {
477 printf("Error: %s\tExpression: %s\n",
478 parser.error().c_str(),
479 program.c_str());
480 return;
481 }
482
483 expression.value();
484
485 // Benchmark
486 //{
487 // constexpr auto rounds = 100000;
488 //
489 // const auto begin = std::chrono::system_clock::now();
490 // {
491 // for (std::size_t i = 0; i < rounds; ++i)
492 // {
493 // expression.value();
494 // }
495 // }
496 // const auto end = std::chrono::system_clock::now();
497 //
498 // const auto total_time_ms = std::chrono::duration_cast<std::chrono::milliseconds>(end - begin).count();
499 //
500 // printf("[*] total time: %5.4fsec rate: %8.4feval/sec\n",
501 // total_time_ms / 1000.0,
502 // (1000.0 * rounds) / total_time_ms);
503 //}
504}
505
506int main()
507{
508 groups_example<double>();
509 return 0;
510}
511
512
513/*
514 Build:
515 c++ -pedantic-errors -Wall -Wextra -Werror -std=c++17 -O3 -DNDEBUG -o exprtk_groups_examples exprtk_groups_examples.cpp -lm
516*/
igeneric_function(const std::string &param_seq="", const return_type rtr_type=e_rtrn_scalar)
Definition exprtk.hpp:19667
T operator()(parameter_list_t parameters) override
typename exprtk::igeneric_function< T > igfun_t
typename generic_type::scalar_view scalar_t
T process(strgrps_cllctn::set_t &set, const parameter_list_t &parameters)
add(groups_collection< std::string > &groups)
typename igfun_t::generic_type generic_type
typename generic_type::string_view string_t
typename igfun_t::parameter_list_t parameter_list_t
typename generic_type::string_view string_t
typename exprtk::igeneric_function< T > igfun_t
typename generic_type::scalar_view scalar_t
T process(const strgrps_cllctn::set_t &set, parameter_list_t &parameters) const
typename igfun_t::parameter_list_t parameter_list_t
T operator()(parameter_list_t parameters) override
contains(groups_collection< std::string > &groups)
typename igfun_t::generic_type generic_type
T operator()(parameter_list_t parameters) override
typename igfun_t::generic_type generic_type
typename generic_type::string_view string_t
typename exprtk::igeneric_function< T > igfun_t
create(groups_collection< std::string > &groups)
typename igfun_t::parameter_list_t parameter_list_t
typename generic_type::scalar_view scalar_t
T operator()(parameter_list_t parameters) override
typename exprtk::igeneric_function< T > igfun_t
T process(strgrps_cllctn::set_t &set, parameter_list_t &parameters)
typename igfun_t::parameter_list_t parameter_list_t
typename generic_type::string_view string_t
erase(groups_collection< std::string > &groups)
typename igfun_t::generic_type generic_type
typename exprtk::igeneric_function< T > igfun_t
T operator()(std::string &result, parameter_list_t parameters) override
typename generic_type::string_view string_t
typename igfun_t::generic_type generic_type
get(groups_collection< std::string > &groups)
typename generic_type::scalar_view scalar_t
typename igfun_t::parameter_list_t parameter_list_t
typename generic_type::string_view string_t
typename generic_type::scalar_view scalar_t
T operator()(parameter_list_t parameters) override
size(groups_collection< std::string > &groups)
typename igfun_t::parameter_list_t parameter_list_t
typename igfun_t::generic_type generic_type
typename exprtk::igeneric_function< T > igfun_t
void groups_example()
char_t * char_ptr
Definition exprtk.hpp:95
SetType * make_set_handle(T v)
std::map< std::string, std::set< T > > groups
ptr_t get(const std::string group_name)
bool contains(const std::string &group_name) const
bool add_group(const std::string &group_name, const std::set< T > &set)