value.hpp 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889
  1. /**
  2. * @file
  3. * @author Caleb Fangmeier <caleb@fangmeier.tech>
  4. * @version 0.1
  5. *
  6. * @section LICENSE
  7. *
  8. *
  9. * MIT License
  10. *
  11. * Copyright (c) 2017 Caleb Fangmeier
  12. *
  13. * Permission is hereby granted, free of charge, to any person obtaining a copy
  14. * of this software and associated documentation files (the "Software"), to deal
  15. * in the Software without restriction, including without limitation the rights
  16. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  17. * copies of the Software, and to permit persons to whom the Software is
  18. * furnished to do so, subject to the following conditions:
  19. *
  20. * The above copyright notice and this permission notice shall be included in all
  21. * copies or substantial portions of the Software.
  22. *
  23. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  24. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  25. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  26. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  27. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  28. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  29. * SOFTWARE.
  30. *
  31. * @section DESCRIPTION
  32. * This header defines a set of generic classes that wrap up "values". In
  33. * essence, a Value<T> object is just something that contains a value of type T
  34. * and can provide it when requested. The usefulness stems from composing
  35. * values together with calculations. This enables very clear dependency
  36. * mapping and a way to know clearly how every value was arrived at. This could
  37. * be used to, for example, automatically generate commentary for plots that
  38. * explain the exect calculation used to create it. Or easily making a series
  39. * of plots contrasting different values that have been composed slightly
  40. * differently.
  41. */
  42. #ifndef value_hpp
  43. #define value_hpp
  44. #include <iomanip>
  45. #include <iostream>
  46. #include <sstream>
  47. #include <utility>
  48. #include <algorithm>
  49. #include <map>
  50. #include <limits>
  51. #include <vector>
  52. #include <tuple>
  53. #include <initializer_list>
  54. #include <functional>
  55. #include "log.hpp"
  56. /**
  57. * The namespace containing all filval classes and functions.
  58. */
  59. namespace fv{
  60. /* bool in_register_function = false; */
  61. template<typename> class Function; // undefined
  62. /**
  63. * Parent class to all Function classes. Holds a class-level collection of all
  64. * created function objects.
  65. */
  66. class GenFunction {
  67. private:
  68. std::string name;
  69. std::string impl;
  70. protected:
  71. inline static bool in_register_function=false;
  72. public:
  73. /**
  74. * Static mapping of functions from their name to the object wrapper of
  75. * the function.
  76. */
  77. inline static std::map<const std::string, GenFunction*> function_registry;
  78. GenFunction(const std::string& name, const std::string& impl)
  79. :impl(impl), name(name){ }
  80. virtual ~GenFunction() { };
  81. std::string& get_name(){
  82. return name;
  83. }
  84. /**
  85. * Attempt to invoke clang-format for the purpose of printing out
  86. * nicely formatted functions to the log file. If clang-format is not
  87. * present, this function just passes through the code unmodified.
  88. */
  89. static std::string format_code(const std::string& code){
  90. std::stringstream code_out("");
  91. std::string command("echo \""+code+"\" | clang-format");
  92. char buffer[255];
  93. FILE *stream = popen(command.c_str(), "r");
  94. while (fgets(buffer, 255, stream) != NULL)
  95. code_out << buffer;
  96. if (pclose(stream) == 0)
  97. return code_out.str();
  98. else
  99. return code;
  100. }
  101. static std::string summary(){
  102. std::stringstream ss;
  103. ss << "The following functions have been registered" << std::endl;
  104. for(auto p : function_registry){
  105. if (p.second == nullptr) continue;
  106. ss << "-->" << p.second->name << std::endl;
  107. ss << format_code(p.second->impl);
  108. }
  109. return ss.str();
  110. }
  111. template <typename T>
  112. static Function<T>& register_function(const std::string& name, std::function<T> f, const std::string& impl){
  113. in_register_function = true;
  114. Function<T>* func;
  115. if (GenFunction::function_registry[name] != nullptr){
  116. func = dynamic_cast<Function<T>*>(GenFunction::function_registry[name]);
  117. if (func == nullptr){
  118. ERROR("Trying to register function which has already been registered with a different type");
  119. }
  120. } else {
  121. func = new Function<T>(name, impl, f);
  122. GenFunction::function_registry[name] = func;
  123. }
  124. in_register_function = false;
  125. return *func;
  126. }
  127. };
  128. /**
  129. * In order to enable proper provenance tracking, and at the same time keep
  130. * the ability to embed functions into values, the Function class should be
  131. * used. It is simply a wrapper around a std::function that also has a name.
  132. * This name is used when generating the name of values that use the function.
  133. * A function name is automatically prepended with "func::" to explicitly state
  134. * that the value is the result of a computation encoded within the function
  135. * object, and not from some other Value object. Unfortunately, it is up to the
  136. * user to find where that function is defined in the source code to inspect
  137. * what it is doing. But hopefully this isn't too onerous by just using grep.
  138. */
  139. template <typename R, typename... ArgTypes>
  140. class Function<R(ArgTypes...)> : public GenFunction {
  141. private:
  142. std::function<R(ArgTypes...)> f;
  143. public:
  144. Function(const std::string& name, const std::string& impl, std::function<R(ArgTypes...)> f)
  145. :GenFunction(name, impl), f(f){
  146. if (!in_register_function) {
  147. WARNING("Don't instantiate Function objects directly! Use GenFunction::register_function instead.");
  148. }
  149. }
  150. Function(const std::string& name, std::function<R(ArgTypes...)> f)
  151. :Function(name, "N/A", f){ }
  152. ~Function() { }
  153. R operator()(ArgTypes ...args){
  154. return f(args...);
  155. }
  156. };
  157. #define FUNC(f) f, #f
  158. /**
  159. * A type-agnostic value.
  160. * It is necessary to create a type-agnostic parent class to Value so that
  161. * it is possible to handle collections of them. GenValue also provides the
  162. * rest of the type-independent interface to Value.
  163. */
  164. class GenValue;
  165. typedef std::map<std::string, GenValue*> ValueSet;
  166. class GenValue{
  167. private:
  168. /**
  169. * The name of the value.
  170. * This is used to allow for dynamic lookup of
  171. * values based on their name via GenValue::get_value.
  172. */
  173. std::string name;
  174. protected:
  175. /**
  176. * Mark the internal value as invalid. This is needed for DerivedValue
  177. * to force a recalculation of the internal value when a new
  178. * observation is loaded into memory. It is called automatically for
  179. * all GenValue objects when reset is called.
  180. */
  181. virtual void _reset() = 0;
  182. /**
  183. * A static mapping containing all created Value objects.
  184. * Every value object must have a unique name, and this name is used as
  185. * a key in values to that object. This is used to enable more dynamic
  186. * creation of objects as well as avoiding the uneccesary passing of
  187. * pointers.
  188. */
  189. inline static std::map<const std::string, GenValue*> values;
  190. /**
  191. * Composite value names are typically nested. This makes complex
  192. * values have rather unwieldy names. Therefore, one can declare
  193. * aliases which allow for more human-usable names to be used. When a
  194. * value is requested by name, an alias with that value takes precidence
  195. * over a name with that value.
  196. */
  197. inline static std::map<const std::string, GenValue*> aliases;
  198. /**
  199. * This function serves to check that this Value has been created with
  200. * real, i.e. non null, arguments. This is to avoid segfaulting when a
  201. * dynamic_cast fails. If no checks need to be made, simple override
  202. * this method with a no-op. If checks fail, the function should
  203. * utilize the CRITICAL macro with a meaningfull error message stating
  204. * what failed and especially the name of the current value.
  205. */
  206. virtual void verify_integrity() = 0;
  207. public:
  208. GenValue(const std::string& name, const std::string& alias)
  209. :name(name){
  210. values[name] = this;
  211. if (alias != "")
  212. GenValue::alias(alias, this);
  213. }
  214. const std::string& get_name(){
  215. return name;
  216. }
  217. static void reset(){
  218. for (auto val : values){
  219. val.second->_reset();
  220. }
  221. }
  222. static GenValue* get_value(const std::string& name){
  223. if (aliases[name] != nullptr)
  224. return aliases[name];
  225. else if (values[name] != nullptr)
  226. return values[name];
  227. else{
  228. ERROR("Could not find alias or value \"" << name << "\". I'll tell you the ones I know about." << std::endl
  229. << summary());
  230. CRITICAL("Aborting... :(",-1);
  231. }
  232. }
  233. static void alias(const std::string& name, GenValue* value){
  234. if (aliases[name] != nullptr){
  235. WARNING("WARNING: alias \"" << name << "\" overrides previous entry.");
  236. }
  237. aliases[name] = value;
  238. }
  239. static GenValue* alias(const std::string& name){
  240. if (values[name] != nullptr){
  241. WARNING("Alias \"" << name << "\" does not exist.");
  242. }
  243. return aliases[name];
  244. }
  245. static std::string summary(){
  246. std::stringstream ss;
  247. ss << "The following values have been created: " << std::endl;
  248. for (auto value : values){
  249. if (value.second == nullptr) continue;
  250. ss << "\t\"" << value.first << "\" at address " << value.second << std::endl;
  251. }
  252. ss << "And these aliases:" << std::endl;
  253. for (auto alias : aliases){
  254. std::string orig("VOID");
  255. if (alias.second == nullptr) continue;
  256. for (auto value : values){
  257. if (alias.second == value.second){
  258. orig = value.second->get_name();
  259. break;
  260. }
  261. }
  262. ss << "\t\"" << alias.first << "\" referring to \"" << orig << "\"" << std::endl;
  263. }
  264. return ss.str();
  265. }
  266. friend std::ostream& operator<<(std::ostream& os, const GenValue& gv);
  267. };
  268. std::ostream& operator<<(std::ostream& os, GenValue& gv){
  269. os << gv.get_name();
  270. return os;
  271. }
  272. /**
  273. * A generic value.
  274. * In order to facilitate run-time creation of analysis routines, it is
  275. * necessary to have some ability to get and store *values*. Values can either
  276. * be directly taken from some original data source (i.e. ObservedValue), or
  277. * they can be a function of some other set of values (i.e. DerivedValue). They
  278. * template class T of Value<T> is the type of thing that is returned upon
  279. * calling get_value().
  280. */
  281. template <typename T>
  282. class Value : public GenValue{
  283. public:
  284. Value(const std::string& name, const std::string& alias="")
  285. :GenValue(name, alias){ }
  286. /** Calculate, if necessary, and return the value held by this object.
  287. */
  288. virtual T& get_value() = 0;
  289. };
  290. /**
  291. * A generic, observed, value.
  292. * An ObservedValue is the interface to your dataset. Upon creation, an
  293. * ObservedValue is given a pointer to an object of type T. When an observation
  294. * is loaded into memory, the value at the location referenced by that pointer
  295. * must be updated with the associated data from that observation. This is the
  296. * responsibility of whatever DataSet implementation is being used. This object
  297. * then will read that data and return it when requested.
  298. */
  299. template <typename T>
  300. class ObservedValue : public Value<T>{
  301. private:
  302. T *val_ref;
  303. void _reset(){ }
  304. void verify_integrity() {
  305. if (val_ref == nullptr)
  306. CRITICAL("ObservedValue " << this->get_name() << " created with null pointer",-1);
  307. }
  308. public:
  309. ObservedValue(const std::string& name, T* val_ref, const std::string& alias="")
  310. :Value<T>(name, alias),
  311. val_ref(val_ref){ }
  312. T& get_value(){
  313. return *val_ref;
  314. }
  315. };
  316. /**
  317. * A generic, derived, value.
  318. * A DerivedValue is generally defined as some function of other Value objects.
  319. * For example, a Pair is a function of two other Value objects that makes a
  320. * pair of them. Note that these other Value objects are free to be either
  321. * ObservedValues or other DerivedValues.
  322. *
  323. * It is desireable from a performance standpoint that each DerivedValue be
  324. * calculated no more than once per observation. Therefore, when a get_value is
  325. * called on a DerivedValue, it first checks whether the value that it holds is
  326. * **valid**, meaning it has already been calculated for this observation. If
  327. * so, it simply returns the value. If not, the update_value function is called
  328. * to calculate the value. and then the newly calculated value is marked as
  329. * valid and returned.
  330. */
  331. template <typename T>
  332. class DerivedValue : public Value<T>{
  333. private:
  334. void _reset(){
  335. value_valid = false;
  336. }
  337. protected:
  338. T value;
  339. bool value_valid;
  340. /**
  341. * Updates the internal value.
  342. * This function should be overridden by any child class to do the
  343. * actual work of updating value based on whatever rules the class
  344. * chooses. Normally, this consists of geting the values from some
  345. * associated Value objects, doing some calculation on them, and
  346. * storing the result in value.
  347. */
  348. virtual void update_value() = 0;
  349. public:
  350. DerivedValue(const std::string& name, const std::string& alias="")
  351. :Value<T>(name, alias),
  352. value_valid(false) { }
  353. T& get_value(){
  354. if (!value_valid){
  355. update_value();
  356. value_valid = true;
  357. }
  358. return value;
  359. }
  360. };
  361. /**
  362. * A std::vector wrapper around a C-style array.
  363. * In order to make some of the higher-level Value types easier to work with,
  364. * it is a good idea to wrap all arrays in the original data source with
  365. * std::vector objects. To do this, it is necessary to supply both a Value
  366. * object containing the array itself as well as another Value object
  367. * containing the size of that array. Currently, update_value will simply copy
  368. * the contents of the array into the interally held vector.
  369. */
  370. template <typename T>
  371. class WrapperVector : public DerivedValue<std::vector<T> >{
  372. private:
  373. Value<int>* size;
  374. Value<T*>* data;
  375. void update_value(){
  376. int n = size->get_value();
  377. T* data_ref = data->get_value();
  378. this->value.assign(data_ref, data_ref+n);
  379. }
  380. void verify_integrity() {
  381. if (size == nullptr)
  382. CRITICAL("WrapperVector " << this->get_name() << " created with invalid size.",-1);
  383. if (data == nullptr)
  384. CRITICAL("WrapperVector " << this->get_name() << " created with invalid value.",-1);
  385. }
  386. public:
  387. WrapperVector(Value<int>* size, Value<T*>* data, const std::string& alias="")
  388. :DerivedValue<std::vector<T> >("vectorOf("+size->get_name()+","+data->get_name()+")", alias),
  389. size(size), data(data){ }
  390. WrapperVector(const std::string &label_size, const std::string &label_data, const std::string& alias="")
  391. :WrapperVector(dynamic_cast<Value<int>*>(GenValue::get_value(label_size)),
  392. dynamic_cast<Value<T*>*>(GenValue::get_value(label_data)), alias) { }
  393. };
  394. /**
  395. * Creates a std::pair type from a two other Value objects.
  396. */
  397. template <typename T1, typename T2>
  398. class Pair : public DerivedValue<std::pair<T1, T2> >{
  399. protected:
  400. std::pair<Value<T1>*, Value<T2>* > value_pair;
  401. void update_value(){
  402. this->value.first = value_pair.first->get_value();
  403. this->value.second = value_pair.second->get_value();
  404. }
  405. void verify_integrity() {
  406. if (value_pair.first == nullptr)
  407. CRITICAL("Pair " << this->get_name() << " created with invalid first value.",-1);
  408. if (value_pair.second == nullptr)
  409. CRITICAL("Pair " << this->get_name() << " created with invalid second value.",-1);
  410. }
  411. public:
  412. Pair(Value<T1> *value1, Value<T2> *value2, const std::string alias="")
  413. :DerivedValue<std::pair<T1, T2> >("pair("+value1->get_name()+","+value2->get_name()+")", alias),
  414. value_pair(value1, value2){ }
  415. Pair(const std::string& label1, const std::string& label2, const std::string alias="")
  416. :Pair(dynamic_cast<Value<T1>*>(GenValue::get_value(label1)),
  417. dynamic_cast<Value<T1>*>(GenValue::get_value(label2)),
  418. alias){ }
  419. };
  420. template<typename... T> class _Zip;
  421. template<>
  422. class _Zip<> {
  423. protected:
  424. int _get_size(){
  425. return std::numeric_limits<int>::max();
  426. }
  427. std::tuple<> _get_at(int idx){
  428. return std::make_tuple();
  429. }
  430. public:
  431. _Zip() { }
  432. };
  433. template<typename Head, typename... Tail>
  434. class _Zip<Head, Tail...> : private _Zip<Tail...> {
  435. protected:
  436. Value<std::vector<Head>>* head;
  437. int _get_size(){
  438. int this_size = head->get_value().size();
  439. int rest_size = _Zip<Tail...>::_get_size();
  440. return std::min(this_size, rest_size);
  441. }
  442. typename std::tuple<Head,Tail...> _get_at(int idx){
  443. auto tail_tuple = _Zip<Tail...>::_get_at(idx);
  444. return std::tuple_cat(std::make_tuple(head->get_value()[idx]),tail_tuple);
  445. }
  446. public:
  447. _Zip() { }
  448. _Zip(Value<std::vector<Head>>* head, Value<std::vector<Tail>>*... tail)
  449. : _Zip<Tail...>(tail...),
  450. head(head) { }
  451. };
  452. /**
  453. * Zips a series of observations together
  454. */
  455. template <typename... ArgTypes>
  456. class Zip : public DerivedValue<std::vector<std::tuple<ArgTypes...>>>,
  457. private _Zip<ArgTypes...>{
  458. protected:
  459. void update_value(){
  460. /* auto tuple_of_vectors this->_get_value(); */
  461. this->value.clear();
  462. int size = _Zip<ArgTypes...>::_get_size();
  463. for(int i=0; i<size; i++){
  464. this->value.push_back(_Zip<ArgTypes...>::_get_at(i));
  465. }
  466. }
  467. /**
  468. * /todo Implement this.
  469. */
  470. void verify_integrity() { }
  471. public:
  472. Zip(Value<std::vector<ArgTypes>>*... args, const std::string alias="")
  473. :DerivedValue<std::vector<std::tuple<ArgTypes...>>>("a kickin zip", ""),
  474. _Zip<ArgTypes...>(args...) { }
  475. };
  476. /**
  477. * Takes a set of four Value<std::vector<T> > objects and a function of four Ts
  478. * and returns a std::vector<R>. This is used in, for instance, calculating the
  479. * energy of a set of particles when one has separate arrays containing pt,
  480. * eta, phi, and mass. These arrays are first wrapped up in VectorWrappers and
  481. * then passes along with a function to calculate the energy into a ZipMapFour.
  482. * The result of this calculation is a new vector containing the energy for
  483. * each particle. Note that if the input vectors are not all the same size,
  484. * calculations are only performed up to the size of the shortest.
  485. * \see MiniTreeDataSet
  486. * \todo find way to implement for arbitrary number(and possibly type) of
  487. * vector inputs.
  488. */
  489. template <typename R, typename T>
  490. class ZipMapFour : public DerivedValue<std::vector<R> >{
  491. private:
  492. Function<R(T, T, T, T)>& f;
  493. Value<std::vector<T> >* v1;
  494. Value<std::vector<T> >* v2;
  495. Value<std::vector<T> >* v3;
  496. Value<std::vector<T> >* v4;
  497. void update_value(){
  498. std::vector<T> v1_val = v1->get_value();
  499. std::vector<T> v2_val = v2->get_value();
  500. std::vector<T> v3_val = v3->get_value();
  501. std::vector<T> v4_val = v4->get_value();
  502. int n;
  503. std::tie(n, std::ignore) = std::minmax({v1_val.size(), v2_val.size(), v3_val.size(), v4_val.size()});
  504. this->value.resize(n);
  505. for (int i=0; i<n; i++){
  506. this->value[i] = f(v1_val[i], v2_val[i], v3_val[i], v4_val[i]);
  507. }
  508. }
  509. void verify_integrity() {
  510. if (v1 == nullptr)
  511. CRITICAL("ZipMapFour " << this->get_name() << " created with invalid first value.",-1);
  512. if (v2 == nullptr)
  513. CRITICAL("ZipMapFour " << this->get_name() << " created with invalid second value.",-1);
  514. if (v3 == nullptr)
  515. CRITICAL("ZipMapFour " << this->get_name() << " created with invalid third value.",-1);
  516. if (v4 == nullptr)
  517. CRITICAL("ZipMapFour " << this->get_name() << " created with invalid fourth value.",-1);
  518. }
  519. public:
  520. ZipMapFour(Function<R(T, T, T, T)>& f,
  521. Value<std::vector<T> >* v1, Value<std::vector<T> >* v2,
  522. Value<std::vector<T> >* v3, Value<std::vector<T> >* v4, const std::string alias="")
  523. :DerivedValue<std::vector<R> >("zipmap("+f.get_name()+":"+v1->get_name()+","+v2->get_name()+","+
  524. v3->get_name()+","+v4->get_name()+")", alias),
  525. f(f), v1(v1), v2(v2), v3(v3), v4(v4) { }
  526. ZipMapFour(Function<R(T, T, T, T)>& f,
  527. const std::string& label1, const std::string& label2,
  528. const std::string& label3, const std::string& label4, const std::string alias="")
  529. :ZipMapFour(f,
  530. dynamic_cast<Value<std::vector<T> >*>(GenValue::get_value(label1)),
  531. dynamic_cast<Value<std::vector<T> >*>(GenValue::get_value(label2)),
  532. dynamic_cast<Value<std::vector<T> >*>(GenValue::get_value(label3)),
  533. dynamic_cast<Value<std::vector<T> >*>(GenValue::get_value(label4)),
  534. alias){ }
  535. };
  536. /**
  537. * Returns the count of elements in the input vector passing a test function.
  538. */
  539. template<typename T>
  540. class Count : public DerivedValue<int>{
  541. private:
  542. Function<bool(T)>& selector;
  543. Value<std::vector<T> >* v;
  544. void update_value(){
  545. value = 0;
  546. for(auto val : v->get_value()){
  547. if(selector(val))
  548. value++;
  549. }
  550. }
  551. void verify_integrity() {
  552. if (v == nullptr)
  553. CRITICAL("Count " << this->get_name() << " created with invalid value.",-1);
  554. }
  555. public:
  556. Count(Function<bool(T)>& selector, Value<std::vector<T>>* v, const std::string alias="")
  557. :DerivedValue<int>("count("+selector.get_name()+":"+v->get_name()+")", alias),
  558. selector(selector), v(v) { }
  559. Count(Function<bool(T)>& selector, const std::string& v_name, const std::string alias="")
  560. :Count(selector, dynamic_cast<Value<std::vector<T> >*>(GenValue::get_value(v_name)), alias) { }
  561. };
  562. /**
  563. * Reduce a Value of type vector<T> to just a T.
  564. * This is useful functionality to model, for instance, calculating the maximum
  565. * element of a vector, or a the mean. See child classes for specific
  566. * implementations.
  567. */
  568. template <typename T>
  569. class Reduce : public DerivedValue<T>{
  570. private:
  571. Function<T(std::vector<T>)>& reduce;
  572. void update_value(){
  573. this->value = reduce(v->get_value());
  574. }
  575. virtual void verify_integrity() {
  576. if (v == nullptr)
  577. CRITICAL("Reduce " << this->get_name() << " created with invalid value.",-1);
  578. }
  579. protected:
  580. Value<std::vector<T> >* v;
  581. public:
  582. Reduce(Function<T(std::vector<T>)>& reduce, Value<std::vector<T> >* v, const std::string alias="")
  583. :DerivedValue<T>("reduceWith("+reduce.get_name()+":"+v->get_name()+")", alias),
  584. reduce(reduce), v(v) { }
  585. Reduce(Function<T(std::vector<T>)>& reduce, const std::string& v_name, const std::string alias="")
  586. :Reduce(reduce, dynamic_cast<Value<std::vector<T> >*>(GenValue::get_value(v_name)), alias) { }
  587. };
  588. /**
  589. * Find and return the maximum value of a vector.
  590. */
  591. template <typename T>
  592. class Max : public Reduce<T>{
  593. private:
  594. void verify_integrity() {
  595. if (this->v == nullptr)
  596. CRITICAL("Max " << this->get_name() << " created with invalid value.",-1);
  597. }
  598. public:
  599. Max(const std::string& v_name, const std::string alias="")
  600. :Reduce<T>(GenFunction::register_function<T(std::vector<T>)>("max",
  601. FUNC(([](std::vector<T> vec){
  602. return *std::max_element(vec.begin(), vec.end());}))),
  603. v_name, alias) { }
  604. };
  605. /**
  606. * Find and return the minimum value of a vector.
  607. */
  608. template <typename T>
  609. class Min : public Reduce<T>{
  610. private:
  611. void verify_integrity() {
  612. if (this->v == nullptr)
  613. CRITICAL("Min " << this->get_name() << " created with invalid value.",-1);
  614. }
  615. public:
  616. Min(const std::string& v_name, const std::string alias="")
  617. :Reduce<T>(GenFunction::register_function<T(std::vector<T>)>("min",
  618. FUNC(([](std::vector<T> vec){
  619. return *std::min_element(vec.begin(), vec.end());}))),
  620. v_name, alias) { }
  621. };
  622. /**
  623. * Calculate the mean value of a vector.
  624. */
  625. template <typename T>
  626. class Mean : public Reduce<T>{
  627. private:
  628. void verify_integrity() {
  629. if (this->v == nullptr)
  630. CRITICAL("Mean " << this->get_name() << " created with invalid value.",-1);
  631. }
  632. public:
  633. Mean(const std::string& v_name, const std::string alias="")
  634. :Reduce<T>(GenFunction::register_function<T(std::vector<T>)>("mean",
  635. FUNC(([](std::vector<T> vec){
  636. int n = 0; T sum = 0;
  637. for (T e : vec){ n++; sum += e; }
  638. return n>0 ? sum / n : 0; }))),
  639. v_name, alias) { }
  640. };
  641. /**
  642. * Calculate the range of the values in a vector
  643. */
  644. template <typename T>
  645. class Range : public Reduce<T>{
  646. private:
  647. void verify_integrity() {
  648. if (this->v == nullptr)
  649. CRITICAL("Range " << this->get_name() << " created with invalid value.",-1);
  650. }
  651. public:
  652. Range(const std::string& v_name, const std::string alias="")
  653. :Reduce<T>(GenFunction::register_function<T(std::vector<T>)>("range",
  654. FUNC(([](std::vector<T> vec){
  655. auto minmax = std::minmax_element(vec.begin(), vec.end());
  656. return (*minmax.second) - (*minmax.first); }))),
  657. v_name, alias) { }
  658. };
  659. /**
  660. * Extract the element at a specific index from a vector.
  661. */
  662. template <typename T>
  663. class ElementOf : public Reduce<T>{
  664. private:
  665. void verify_integrity() {
  666. if (this->v == nullptr)
  667. CRITICAL("ElementOf " << this->get_name() << " created with invalid value.",-1);
  668. }
  669. public:
  670. ElementOf(Value<int>* index, const std::string& v_name, const std::string alias="")
  671. :Reduce<T>(GenFunction::register_function<T(std::vector<T>)>("elementOf",
  672. FUNC(([index](std::vector<T> vec){return vec[index->get_value()];}))),
  673. v_name, alias) { }
  674. ElementOf(const std::string& name, int index, const std::string& v_name, const std::string alias="")
  675. :Reduce<T>(name, [index](std::vector<T> vec){return vec[index];}, v_name, alias) { }
  676. };
  677. /**
  678. * Similar to Reduce, but returns a pair of a T and an int.
  679. * This is useful if you need to know where in the vector exists the element
  680. * being returned.
  681. */
  682. template <typename T>
  683. class ReduceIndex : public DerivedValue<std::pair<T, int> >{
  684. private:
  685. Function<std::pair<T,int>(std::vector<T>)>& reduce;
  686. Value<std::vector<T> >* v;
  687. void update_value(){
  688. this->value = reduce(v->get_value());
  689. }
  690. virtual void verify_integrity() {
  691. if (v == nullptr)
  692. CRITICAL("ReduceIndex " << this->get_name() << " created with invalid value.",-1);
  693. }
  694. public:
  695. ReduceIndex(Function<std::pair<T,int>(std::vector<T>)>& reduce, Value<std::vector<T> >* v, const std::string alias="")
  696. :DerivedValue<T>("reduceIndexWith("+reduce.get_name()+":"+v->get_name()+")", alias),
  697. reduce(reduce), v(v) { }
  698. ReduceIndex(Function<std::pair<T,int>(std::vector<T>)>& reduce, const std::string& v_name, const std::string alias="")
  699. :ReduceIndex(reduce, dynamic_cast<Value<std::vector<T> >*>(GenValue::get_value(v_name)), alias) { }
  700. };
  701. /**
  702. * Find and return the maximum value of a vector and its index.
  703. */
  704. template <typename T>
  705. class MaxIndex : public ReduceIndex<T>{
  706. private:
  707. void verify_integrity() {
  708. if (this->v == nullptr)
  709. CRITICAL("MaxIndex " << this->get_name() << " created with invalid value.",-1);
  710. }
  711. public:
  712. MaxIndex(const std::string& v_name, const std::string alias="")
  713. :ReduceIndex<T>(GenFunction::register_function<T(std::vector<T>)>("maxIndex",
  714. FUNC(([](std::vector<T> vec){
  715. auto elptr = std::max_element(vec.begin(), vec.end());
  716. return std::pair<T,int>(*elptr, int(elptr-vec.begin())); }
  717. ))), v_name, alias) { }
  718. };
  719. /**
  720. * Find and return the minimum value of a vector and its index.
  721. */
  722. template <typename T>
  723. class MinIndex : public ReduceIndex<T>{
  724. private:
  725. void verify_integrity() {
  726. if (this->v == nullptr)
  727. CRITICAL("MinIndex " << this->get_name() << " created with invalid value.",-1);
  728. }
  729. public:
  730. MinIndex(const std::string& v_name, const std::string alias="")
  731. :ReduceIndex<T>(GenFunction::register_function<T(std::vector<T>)>("minIndex",
  732. FUNC(([](std::vector<T> vec){
  733. auto elptr = std::min_element(vec.begin(), vec.end());
  734. return std::pair<T,int>(*elptr, int(elptr-vec.begin())); }
  735. ))), v_name, alias) { }
  736. };
  737. /**
  738. * A generic value owning only a function object.
  739. * All necessary values upon which this value depends must be bound to the
  740. * function object.
  741. */
  742. template <typename T>
  743. class BoundValue : public DerivedValue<T>{
  744. private:
  745. void verify_integrity() { }
  746. protected:
  747. Function<T()>& f;
  748. void update_value(){
  749. this->value = f();
  750. }
  751. public:
  752. BoundValue(Function<T()>& f, const std::string alias="")
  753. :DerivedValue<T>(f.get_name()+"(<bound>)", alias),
  754. f(f) { }
  755. };
  756. /**
  757. * A Value of a pointer. The pointer is constant, however the data the pointer
  758. * points to is variable.
  759. */
  760. template <typename T>
  761. class PointerValue : public DerivedValue<T*>{
  762. private:
  763. void verify_integrity() {
  764. if(this->value == nullptr)
  765. CRITICAL("PointerValue " << this->get_name() << " created with null pointer",-1);
  766. }
  767. protected:
  768. void update_value(){ }
  769. public:
  770. PointerValue(const std::string& name, T* ptr, const std::string alias="")
  771. :DerivedValue<T*>(name, alias){
  772. this->value = ptr;
  773. }
  774. };
  775. /**
  776. * A Value which always returns the same value, supplied in the constructor.
  777. */
  778. template <typename T>
  779. class ConstantValue : public DerivedValue<T>{
  780. private:
  781. void verify_integrity() { }
  782. protected:
  783. void update_value(){ }
  784. public:
  785. ConstantValue(const std::string& name, T const_value, const std::string alias="")
  786. :DerivedValue<T>("const::"+name, alias),
  787. Value<T>::value(const_value) { }
  788. };
  789. }
  790. #endif // value_hpp